00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #include <dev/term.h>
00076
00077 #include <stdlib.h>
00078 #include <string.h>
00079 #include <fcntl.h>
00080 #include <memdebug.h>
00081
00087
00088 static prog_char termid[] = "Term 1.0";
00089
00090 static void TermRefreshLineEnd(CONST TERMDCB * dcb, uint8_t row, uint8_t col)
00091 {
00092 uint8_t i = col;
00093 uint8_t *cp = dcb->dcb_smem + row * dcb->dcb_vcols + col;
00094
00095
00096 if (dcb->dcb_modeflags & LCD_MF_CURSORON)
00097 (*dcb->dss_cursor_mode) (0);
00098
00099
00100 (*dcb->dss_set_cursor) (row * dcb->dcb_ncols + col);
00101
00102
00103
00104
00105
00106 for (;;) {
00107 if (i++ >= dcb->dcb_vcols)
00108 break;
00109 (*dcb->dss_write) (*cp++);
00110 }
00111
00112
00113 if (dcb->dcb_modeflags & LCD_MF_CURSORON)
00114 (*dcb->dss_cursor_mode) (1);
00115 }
00116
00117 void TermRefresh(TERMDCB * dcb)
00118 {
00119 uint8_t ir;
00120
00121 for (ir = 0; ir < dcb->dcb_nrows; ir++)
00122 TermRefreshLineEnd(dcb, ir, 0);
00123 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00124 }
00125
00126 static void TermClear(TERMDCB * dcb)
00127 {
00128 memset(dcb->dcb_smem, ' ', dcb->dcb_vcols * dcb->dcb_nrows);
00129 dcb->dcb_col = 0;
00130 dcb->dcb_row = 0;
00131 (*dcb->dss_clear) ();
00132 }
00133
00134 static void TermDeleteLine(TERMDCB * dcb, uint8_t row)
00135 {
00136 uint8_t i;
00137 uint8_t *dcp;
00138
00139 for (i = row; i < dcb->dcb_nrows - 1; i++) {
00140 dcp = dcb->dcb_smem + i * dcb->dcb_vcols;
00141 memcpy(dcp, dcp + dcb->dcb_vcols, dcb->dcb_vcols);
00142 }
00143 memset(dcb->dcb_smem + (dcb->dcb_nrows - 1) * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00144 TermRefresh(dcb);
00145 }
00146
00147 static void TermInsertLine(TERMDCB * dcb, uint8_t row)
00148 {
00149 uint8_t i;
00150 uint8_t *dcp;
00151
00152 for (i = dcb->dcb_nrows - 1; i > row; i--) {
00153 dcp = dcb->dcb_smem + i * dcb->dcb_vcols;
00154 memcpy(dcp, dcp - dcb->dcb_vcols, dcb->dcb_vcols);
00155 }
00156 memset(dcb->dcb_smem + row * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00157 TermRefresh(dcb);
00158 }
00159
00160 static void TermCursorLeft(TERMDCB * dcb)
00161 {
00162 if (dcb->dcb_col) {
00163 (*dcb->dss_cursor_left) ();
00164 dcb->dcb_col--;
00165 }
00166 }
00167
00168 static void TermCursorRight(TERMDCB * dcb)
00169 {
00170 if (++dcb->dcb_col < dcb->dcb_vcols)
00171 (*dcb->dss_cursor_right) ();
00172 else
00173 dcb->dcb_col = dcb->dcb_vcols - 1;
00174 }
00175
00176 static void TermCursorUp(TERMDCB * dcb)
00177 {
00178 if (dcb->dcb_row) {
00179 dcb->dcb_row--;
00180 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00181 }
00182 }
00183
00184 static void TermLinefeed(TERMDCB * dcb)
00185 {
00186 if (++dcb->dcb_row >= dcb->dcb_nrows) {
00187 dcb->dcb_row = dcb->dcb_nrows - 1;
00188 TermDeleteLine(dcb, 0);
00189 } else
00190 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00191 }
00192
00193 static void TermReverseLinefeed(TERMDCB * dcb)
00194 {
00195 if (dcb->dcb_row--)
00196 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00197 else {
00198 dcb->dcb_row = 0;
00199 TermInsertLine(dcb, 0);
00200 }
00201 }
00202
00203 static void TermEraseLineEnd(TERMDCB * dcb, uint8_t col)
00204 {
00205 if (col < dcb->dcb_vcols) {
00206 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + col, ' ', dcb->dcb_vcols - col);
00207 TermRefresh(dcb);
00208 }
00209 }
00210
00211 static void TermEraseEnd(TERMDCB * dcb)
00212 {
00213 uint8_t i;
00214
00215 if (dcb->dcb_col < dcb->dcb_vcols)
00216 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + dcb->dcb_col, ' ', dcb->dcb_vcols - dcb->dcb_col);
00217 for (i = dcb->dcb_row + 1; i < dcb->dcb_nrows; i++)
00218 memset(dcb->dcb_smem + i * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00219 TermRefresh(dcb);
00220 }
00221
00222 static void TermEraseLineStart(TERMDCB * dcb)
00223 {
00224 if (dcb->dcb_col) {
00225 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols, ' ', dcb->dcb_col);
00226 TermRefresh(dcb);
00227 }
00228 }
00229
00230 static void TermEraseStart(TERMDCB * dcb)
00231 {
00232 uint8_t i;
00233
00234 if (dcb->dcb_col)
00235 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols, ' ', dcb->dcb_col);
00236 for (i = 0; i < dcb->dcb_row; i++)
00237 memset(dcb->dcb_smem + i * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00238 TermRefresh(dcb);
00239 }
00240
00241 static void TermDeleteChar(TERMDCB * dcb, uint8_t col)
00242 {
00243 uint8_t i;
00244 uint8_t *cp = dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + col;
00245
00246 for (i = col; i < dcb->dcb_vcols - 1; i++, cp++)
00247 *cp = *(cp + 1);
00248 *cp = ' ';
00249 TermRefresh(dcb);
00250 }
00251
00252
00253
00254
00255 static void TermInsertSpace(TERMDCB * dcb)
00256 {
00257 uint8_t i;
00258 uint8_t *cp = dcb->dcb_smem + (dcb->dcb_row + 1) * dcb->dcb_vcols - 1;
00259
00260 for (i = dcb->dcb_col; i < dcb->dcb_vcols - 1; i++, cp--)
00261 *cp = *(cp - 1);
00262 *cp = ' ';
00263 TermRefreshLineEnd(dcb, dcb->dcb_row, dcb->dcb_col);
00264 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00265 }
00266
00267
00268
00269
00270 static void TermIdentify(TERMDCB * dcb)
00271 {
00272 PGM_P pcp = termid;
00273
00274 TermClear(dcb);
00275 while (PRG_RDB(pcp)) {
00276 (*dcb->dss_write) (PRG_RDB(pcp));
00277 pcp++;
00278 }
00279 }
00280
00318 int TermIOCtl(NUTDEVICE * dev, int req, void *conf)
00319 {
00320 TERMDCB *dcb = dev->dev_dcb;
00321 uint16_t usv;
00322 uint32_t ulv;
00323 WINSIZE *win_size;
00324
00325 switch (req) {
00326 case LCD_CMDBYTE:
00327 (*dcb->dss_command) (*(uint8_t *)conf, 10);
00328 break;
00329 case LCD_CMDWORD16:
00330 usv = *(uint16_t *)conf;
00331 (*dcb->dss_command) ((uint8_t)(usv >> 8), 10);
00332 (*dcb->dss_command) ((uint8_t)usv, 10);
00333 break;
00334 case LCD_CMDWORD32:
00335 ulv = *(uint32_t *)conf;
00336 (*dcb->dss_command) ((uint8_t)(ulv >> 24), 10);
00337 (*dcb->dss_command) ((uint8_t)(ulv >> 16), 10);
00338 (*dcb->dss_command) ((uint8_t)(ulv >> 8), 10);
00339 (*dcb->dss_command) ((uint8_t)ulv, 10);
00340 break;
00341 case LCD_DATABYTE:
00342 (*dcb->dss_write) (*(uint8_t *)conf);
00343 break;
00344 case LCD_DATAWORD16:
00345 usv = *(uint16_t *)conf;
00346 (*dcb->dss_write) ((uint8_t)(usv >> 8));
00347 (*dcb->dss_write) ((uint8_t)usv);
00348 break;
00349 case LCD_DATAWORD32:
00350 ulv = *(uint32_t *)conf;
00351 (*dcb->dss_write) ((uint8_t)(ulv >> 24));
00352 (*dcb->dss_write) ((uint8_t)(ulv >> 16));
00353 (*dcb->dss_write) ((uint8_t)(ulv >> 8));
00354 (*dcb->dss_write) ((uint8_t)ulv);
00355 break;
00356 case LCD_SETCOOKEDMODE:
00357 if (*(uint32_t *)conf)
00358 dcb->dcb_modeflags |= LCD_MF_COOKEDMODE;
00359 else
00360 dcb->dcb_modeflags &= ~LCD_MF_COOKEDMODE;
00361 break;
00362 case LCD_GETCOOKEDMODE:
00363 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE)
00364 *(uint32_t *)conf = 1;
00365 else
00366 *(uint32_t *)conf = 0;
00367 break;
00368 case TIOCGWINSZ:
00369 win_size = (WINSIZE *)conf;
00370 win_size->ws_col = dcb->dcb_nrows;
00371 win_size->ws_row = dcb->dcb_vcols;
00372 win_size->ws_xpixel = 0;
00373 win_size->ws_ypixel = 0;
00374 break;
00375 }
00376 return 0;
00377 }
00378
00379
00392 int TermInit(NUTDEVICE * dev)
00393 {
00394 TERMDCB *dcb = dev->dev_dcb;
00395
00396
00397
00398
00399 (*dcb->dss_init) (dev);
00400
00401
00402
00403
00404 dcb->dcb_smem = malloc(dcb->dcb_nrows * dcb->dcb_vcols);
00405 TermClear(dcb);
00406
00407 return 0;
00408 }
00409
00421 static int TermPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
00422 {
00423 int rc;
00424 CONST uint8_t *cp;
00425 uint8_t ch;
00426 TERMDCB *dcb = dev->dev_dcb;
00427
00428
00429
00430
00431 if (buffer == 0)
00432 return 0;
00433
00434
00435
00436
00437 cp = buffer;
00438 for (rc = 0; rc < len; cp++, rc++) {
00439 ch = pflg ? PRG_RDB(cp) : *cp;
00440
00441 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00442
00443 if (dcb->dcb_ctlseq == 0) {
00444
00445 if (ch == 10) {
00446 dcb->dcb_col = 0;
00447 TermLinefeed(dcb);
00448 continue;
00449 }
00450
00451
00452 if (ch == 13) {
00453 dcb->dcb_col = 0;
00454 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols);
00455 continue;
00456 }
00457
00458
00459 if (ch == 27) {
00460 dcb->dcb_ctlseq = 1;
00461 continue;
00462 }
00463
00464
00465 if (ch == 8) {
00466 if (dcb->dcb_col) {
00467 dcb->dcb_col--;
00468 TermDeleteChar(dcb, dcb->dcb_col);
00469 }
00470 continue;
00471 }
00472
00473
00474 if (ch == 12) {
00475 TermClear(dcb);
00476 continue;
00477 }
00478 }
00479
00480
00481 if (dcb->dcb_ctlseq == 1) {
00482 dcb->dcb_ctlseq = 0;
00483
00484 switch (ch) {
00485
00486 case '@':
00487 TermInsertSpace(dcb);
00488 break;
00489
00490
00491 case 'A':
00492 TermCursorUp(dcb);
00493 break;
00494
00495
00496 case 'B':
00497 if (++dcb->dcb_row >= dcb->dcb_nrows)
00498 dcb->dcb_row = dcb->dcb_nrows - 1;
00499 else
00500 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00501 break;
00502
00503
00504 case 'C':
00505 TermCursorRight(dcb);
00506 break;
00507
00508
00509 case 'D':
00510 TermCursorLeft(dcb);
00511 break;
00512
00513
00514 case 'E':
00515 TermClear(dcb);
00516 break;
00517
00518
00519 case 'H':
00520 dcb->dcb_col = 0;
00521 dcb->dcb_row = 0;
00522 (*dcb->dss_cursor_home) ();
00523 break;
00524
00525
00526 case 'I':
00527 TermReverseLinefeed(dcb);
00528 break;
00529
00530
00531 case 'J':
00532 TermEraseEnd(dcb);
00533 break;
00534
00535
00536 case 'K':
00537 TermEraseLineEnd(dcb, dcb->dcb_col);
00538 break;
00539
00540
00541 case 'L':
00542 TermInsertLine(dcb, dcb->dcb_row);
00543 break;
00544
00545
00546 case 'M':
00547 TermDeleteLine(dcb, dcb->dcb_row);
00548 break;
00549
00550
00551 case 'P':
00552 TermDeleteChar(dcb, dcb->dcb_col);
00553 break;
00554
00555
00556 case 'Y':
00557 dcb->dcb_ctlseq = 2;
00558 break;
00559
00560
00561 case 'Z':
00562 TermIdentify(dcb);
00563 break;
00564
00565
00566 case 'e':
00567 dcb->dcb_modeflags |= LCD_MF_CURSORON;
00568 (*dcb->dss_cursor_mode) (1);
00569 break;
00570
00571
00572 case 'f':
00573 dcb->dcb_modeflags &= ~LCD_MF_CURSORON;
00574 (*dcb->dss_cursor_mode) (0);
00575 break;
00576
00577
00578 case 'd':
00579 TermEraseStart(dcb);
00580 break;
00581
00582
00583 case 'o':
00584 TermEraseLineStart(dcb);
00585 break;
00586 }
00587 continue;
00588 }
00589
00590
00591 if (dcb->dcb_ctlseq == 2) {
00592 dcb->dcb_ctlseq = 3;
00593 if (ch < 32)
00594 dcb->dcb_row = 0;
00595 else if (ch - 32 >= dcb->dcb_nrows)
00596 dcb->dcb_row = dcb->dcb_nrows - 1;
00597 else
00598 dcb->dcb_row = ch - 32;
00599 continue;
00600 }
00601
00602
00603 if (dcb->dcb_ctlseq == 3) {
00604 dcb->dcb_ctlseq = 0;
00605 if (ch < 32)
00606 dcb->dcb_col = 0;
00607 else if (ch - 32 >= dcb->dcb_vcols)
00608 dcb->dcb_col = dcb->dcb_vcols - 1;
00609 else
00610 dcb->dcb_col = ch - 32;
00611 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00612 continue;
00613 }
00614 }
00615
00616
00617
00618
00619
00620 (*dcb->dss_write) (ch);
00621
00622
00623 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00624 *(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + dcb->dcb_col) = ch;
00625 if (++dcb->dcb_col >= dcb->dcb_vcols) {
00626 dcb->dcb_col = dcb->dcb_vcols - 1;
00627 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00628 }
00629 }
00630 }
00631 return rc;
00632 }
00633
00685 int TermWrite(NUTFILE * fp, CONST void *buffer, int len)
00686 {
00687 return TermPut(fp->nf_dev, buffer, len, 0);
00688 }
00689
00704 #ifdef __HARVARD_ARCH__
00705 int TermWrite_P(NUTFILE * fp, PGM_P buffer, int len)
00706 {
00707 return TermPut(fp->nf_dev, (CONST char *) buffer, len, 1);
00708 }
00709 #endif
00710
00728 NUTFILE *TermOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00729 {
00730 TERMDCB *dcb = dev->dev_dcb;
00731 NUTFILE *fp = malloc(sizeof(NUTFILE));
00732
00733 if (fp == 0)
00734 return NUTFILE_EOF;
00735
00736 if (mode & _O_BINARY)
00737 dcb->dcb_modeflags &= ~LCD_MF_COOKEDMODE;
00738 else
00739 dcb->dcb_modeflags |= LCD_MF_COOKEDMODE;
00740 fp->nf_next = 0;
00741 fp->nf_dev = dev;
00742 fp->nf_fcb = 0;
00743
00744 return fp;
00745 }
00746
00757 int TermClose(NUTFILE * fp)
00758 {
00759 if (fp && fp != NUTFILE_EOF) {
00760 free(fp);
00761 return 0;
00762 }
00763 return -1;
00764 }
00765