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 #include <dev/term.h>
00070
00071 #include <stdlib.h>
00072 #include <string.h>
00073 #include <fcntl.h>
00074
00080
00081 static prog_char termid[] = "Term 1.0";
00082
00083 static void TermRefreshLineEnd(CONST TERMDCB * dcb, u_char row, u_char col)
00084 {
00085 u_char i = col;
00086 u_char *cp = dcb->dcb_smem + row * dcb->dcb_vcols + col;
00087
00088
00089 if (dcb->dcb_modeflags & LCD_MF_CURSORON)
00090 (*dcb->dss_cursor_mode) (0);
00091
00092
00093 (*dcb->dss_set_cursor) (row * dcb->dcb_ncols + col);
00094
00095
00096
00097
00098
00099 for (;;) {
00100 if (i++ >= dcb->dcb_vcols)
00101 break;
00102 (*dcb->dss_write) (*cp++);
00103 }
00104
00105
00106 if (dcb->dcb_modeflags & LCD_MF_CURSORON)
00107 (*dcb->dss_cursor_mode) (1);
00108 }
00109
00110 void TermRefresh(TERMDCB * dcb)
00111 {
00112 u_char ir;
00113
00114 for (ir = 0; ir < dcb->dcb_nrows; ir++)
00115 TermRefreshLineEnd(dcb, ir, 0);
00116 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00117 }
00118
00119 static void TermClear(TERMDCB * dcb)
00120 {
00121 memset(dcb->dcb_smem, ' ', dcb->dcb_vcols * dcb->dcb_nrows);
00122 dcb->dcb_col = 0;
00123 dcb->dcb_row = 0;
00124 (*dcb->dss_clear) ();
00125 }
00126
00127 static void TermDeleteLine(TERMDCB * dcb, u_char row)
00128 {
00129 u_char i;
00130 u_char *dcp;
00131
00132 for (i = row; i < dcb->dcb_nrows - 1; i++) {
00133 dcp = dcb->dcb_smem + i * dcb->dcb_vcols;
00134 memcpy(dcp, dcp + dcb->dcb_vcols, dcb->dcb_vcols);
00135 }
00136 memset(dcb->dcb_smem + (dcb->dcb_nrows - 1) * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00137 TermRefresh(dcb);
00138 }
00139
00140 static void TermInsertLine(TERMDCB * dcb, u_char row)
00141 {
00142 u_char i;
00143 u_char *dcp;
00144
00145 for (i = dcb->dcb_nrows - 1; i > row; i--) {
00146 dcp = dcb->dcb_smem + i * dcb->dcb_vcols;
00147 memcpy(dcp, dcp - dcb->dcb_vcols, dcb->dcb_vcols);
00148 }
00149 memset(dcb->dcb_smem + row * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00150 TermRefresh(dcb);
00151 }
00152
00153 static void TermCursorLeft(TERMDCB * dcb)
00154 {
00155 if (dcb->dcb_col) {
00156 (*dcb->dss_cursor_left) ();
00157 dcb->dcb_col--;
00158 }
00159 }
00160
00161 static void TermCursorRight(TERMDCB * dcb)
00162 {
00163 if (++dcb->dcb_col < dcb->dcb_vcols)
00164 (*dcb->dss_cursor_right) ();
00165 else
00166 dcb->dcb_col = dcb->dcb_vcols - 1;
00167 }
00168
00169 static void TermCursorUp(TERMDCB * dcb)
00170 {
00171 if (dcb->dcb_row) {
00172 dcb->dcb_row--;
00173 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00174 }
00175 }
00176
00177 static void TermLinefeed(TERMDCB * dcb)
00178 {
00179 if (++dcb->dcb_row >= dcb->dcb_nrows) {
00180 dcb->dcb_row = dcb->dcb_nrows - 1;
00181 TermDeleteLine(dcb, 0);
00182 } else
00183 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00184 }
00185
00186 static void TermReverseLinefeed(TERMDCB * dcb)
00187 {
00188 if (dcb->dcb_row--)
00189 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00190 else {
00191 dcb->dcb_row = 0;
00192 TermInsertLine(dcb, 0);
00193 }
00194 }
00195
00196 static void TermEraseLineEnd(TERMDCB * dcb, u_char col)
00197 {
00198 if (col < dcb->dcb_vcols) {
00199 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + col, ' ', dcb->dcb_vcols - col);
00200 TermRefresh(dcb);
00201 }
00202 }
00203
00204 static void TermEraseEnd(TERMDCB * dcb)
00205 {
00206 u_char i;
00207
00208 if (dcb->dcb_col < dcb->dcb_vcols)
00209 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + dcb->dcb_col, ' ', dcb->dcb_vcols - dcb->dcb_col);
00210 for (i = dcb->dcb_row + 1; i < dcb->dcb_nrows; i++)
00211 memset(dcb->dcb_smem + i * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00212 TermRefresh(dcb);
00213 }
00214
00215 static void TermEraseLineStart(TERMDCB * dcb)
00216 {
00217 if (dcb->dcb_col) {
00218 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols, ' ', dcb->dcb_col);
00219 TermRefresh(dcb);
00220 }
00221 }
00222
00223 static void TermEraseStart(TERMDCB * dcb)
00224 {
00225 u_char i;
00226
00227 if (dcb->dcb_col)
00228 memset(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols, ' ', dcb->dcb_col);
00229 for (i = 0; i < dcb->dcb_row; i++)
00230 memset(dcb->dcb_smem + i * dcb->dcb_vcols, ' ', dcb->dcb_vcols);
00231 TermRefresh(dcb);
00232 }
00233
00234 static void TermDeleteChar(TERMDCB * dcb, u_char col)
00235 {
00236 u_char i;
00237 u_char *cp = dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + col;
00238
00239 for (i = col; i < dcb->dcb_vcols - 1; i++, cp++)
00240 *cp = *(cp + 1);
00241 *cp = ' ';
00242 TermRefresh(dcb);
00243 }
00244
00245
00246
00247
00248 static void TermInsertSpace(TERMDCB * dcb)
00249 {
00250 u_char i;
00251 u_char *cp = dcb->dcb_smem + (dcb->dcb_row + 1) * dcb->dcb_vcols - 1;
00252
00253 for (i = dcb->dcb_col; i < dcb->dcb_vcols - 1; i++, cp--)
00254 *cp = *(cp - 1);
00255 *cp = ' ';
00256 TermRefreshLineEnd(dcb, dcb->dcb_row, dcb->dcb_col);
00257 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00258 }
00259
00260
00261
00262
00263 static void TermIdentify(TERMDCB * dcb)
00264 {
00265 PGM_P pcp = termid;
00266
00267 TermClear(dcb);
00268 while (PRG_RDB(pcp)) {
00269 (*dcb->dss_write) (PRG_RDB(pcp));
00270 pcp++;
00271 }
00272 }
00273
00311 int TermIOCtl(NUTDEVICE * dev, int req, void *conf)
00312 {
00313 TERMDCB *dcb = dev->dev_dcb;
00314 u_short usv;
00315 u_long ulv;
00316 WINSIZE *win_size;
00317
00318 switch (req) {
00319 case LCD_CMDBYTE:
00320 (*dcb->dss_command) (*(u_char *)conf, 10);
00321 break;
00322 case LCD_CMDWORD16:
00323 usv = *(u_short *)conf;
00324 (*dcb->dss_command) ((u_char)(usv >> 8), 10);
00325 (*dcb->dss_command) ((u_char)usv, 10);
00326 break;
00327 case LCD_CMDWORD32:
00328 ulv = *(u_long *)conf;
00329 (*dcb->dss_command) ((u_char)(ulv >> 24), 10);
00330 (*dcb->dss_command) ((u_char)(ulv >> 16), 10);
00331 (*dcb->dss_command) ((u_char)(ulv >> 8), 10);
00332 (*dcb->dss_command) ((u_char)ulv, 10);
00333 break;
00334 case LCD_DATABYTE:
00335 (*dcb->dss_write) (*(u_char *)conf);
00336 break;
00337 case LCD_DATAWORD16:
00338 usv = *(u_short *)conf;
00339 (*dcb->dss_write) ((u_char)(usv >> 8));
00340 (*dcb->dss_write) ((u_char)usv);
00341 break;
00342 case LCD_DATAWORD32:
00343 ulv = *(u_long *)conf;
00344 (*dcb->dss_write) ((u_char)(ulv >> 24));
00345 (*dcb->dss_write) ((u_char)(ulv >> 16));
00346 (*dcb->dss_write) ((u_char)(ulv >> 8));
00347 (*dcb->dss_write) ((u_char)ulv);
00348 break;
00349 case LCD_SETCOOKEDMODE:
00350 if (*(u_long *)conf)
00351 dcb->dcb_modeflags |= LCD_MF_COOKEDMODE;
00352 else
00353 dcb->dcb_modeflags &= ~LCD_MF_COOKEDMODE;
00354 break;
00355 case LCD_GETCOOKEDMODE:
00356 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE)
00357 *(u_long *)conf = 1;
00358 else
00359 *(u_long *)conf = 0;
00360 break;
00361 case TIOCGWINSZ:
00362 win_size = (WINSIZE *)conf;
00363 win_size->ws_col = dcb->dcb_nrows;
00364 win_size->ws_row = dcb->dcb_vcols;
00365 win_size->ws_xpixel = 0;
00366 win_size->ws_ypixel = 0;
00367 break;
00368 }
00369 return 0;
00370 }
00371
00372
00385 int TermInit(NUTDEVICE * dev)
00386 {
00387 TERMDCB *dcb = dev->dev_dcb;
00388
00389
00390
00391
00392 (*dcb->dss_init) (dev);
00393
00394
00395
00396
00397 dcb->dcb_smem = malloc(dcb->dcb_nrows * dcb->dcb_vcols);
00398 TermClear(dcb);
00399
00400 return 0;
00401 }
00402
00414 static int TermPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
00415 {
00416 int rc;
00417 CONST u_char *cp;
00418 u_char ch;
00419 TERMDCB *dcb = dev->dev_dcb;
00420
00421
00422
00423
00424 if (buffer == 0)
00425 return 0;
00426
00427
00428
00429
00430 cp = buffer;
00431 for (rc = 0; rc < len; cp++, rc++) {
00432 ch = pflg ? PRG_RDB(cp) : *cp;
00433
00434 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00435
00436 if (dcb->dcb_ctlseq == 0) {
00437
00438 if (ch == 10) {
00439 dcb->dcb_col = 0;
00440 TermLinefeed(dcb);
00441 continue;
00442 }
00443
00444
00445 if (ch == 13) {
00446 dcb->dcb_col = 0;
00447 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols);
00448 continue;
00449 }
00450
00451
00452 if (ch == 27) {
00453 dcb->dcb_ctlseq = 1;
00454 continue;
00455 }
00456
00457
00458 if (ch == 8) {
00459 if (dcb->dcb_col) {
00460 dcb->dcb_col--;
00461 TermDeleteChar(dcb, dcb->dcb_col);
00462 }
00463 continue;
00464 }
00465
00466
00467 if (ch == 12) {
00468 TermClear(dcb);
00469 continue;
00470 }
00471 }
00472
00473
00474 if (dcb->dcb_ctlseq == 1) {
00475 dcb->dcb_ctlseq = 0;
00476
00477 switch (ch) {
00478
00479 case '@':
00480 TermInsertSpace(dcb);
00481 break;
00482
00483
00484 case 'A':
00485 TermCursorUp(dcb);
00486 break;
00487
00488
00489 case 'B':
00490 if (++dcb->dcb_row >= dcb->dcb_nrows)
00491 dcb->dcb_row = dcb->dcb_nrows - 1;
00492 else
00493 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00494 break;
00495
00496
00497 case 'C':
00498 TermCursorRight(dcb);
00499 break;
00500
00501
00502 case 'D':
00503 TermCursorLeft(dcb);
00504 break;
00505
00506
00507 case 'E':
00508 TermClear(dcb);
00509 break;
00510
00511
00512 case 'H':
00513 dcb->dcb_col = 0;
00514 dcb->dcb_row = 0;
00515 (*dcb->dss_cursor_home) ();
00516 break;
00517
00518
00519 case 'I':
00520 TermReverseLinefeed(dcb);
00521 break;
00522
00523
00524 case 'J':
00525 TermEraseEnd(dcb);
00526 break;
00527
00528
00529 case 'K':
00530 TermEraseLineEnd(dcb, dcb->dcb_col);
00531 break;
00532
00533
00534 case 'L':
00535 TermInsertLine(dcb, dcb->dcb_row);
00536 break;
00537
00538
00539 case 'M':
00540 TermDeleteLine(dcb, dcb->dcb_row);
00541 break;
00542
00543
00544 case 'P':
00545 TermDeleteChar(dcb, dcb->dcb_col);
00546 break;
00547
00548
00549 case 'Y':
00550 dcb->dcb_ctlseq = 2;
00551 break;
00552
00553
00554 case 'Z':
00555 TermIdentify(dcb);
00556 break;
00557
00558
00559 case 'e':
00560 dcb->dcb_modeflags |= LCD_MF_CURSORON;
00561 (*dcb->dss_cursor_mode) (1);
00562 break;
00563
00564
00565 case 'f':
00566 dcb->dcb_modeflags &= ~LCD_MF_CURSORON;
00567 (*dcb->dss_cursor_mode) (0);
00568 break;
00569
00570
00571 case 'd':
00572 TermEraseStart(dcb);
00573 break;
00574
00575
00576 case 'o':
00577 TermEraseLineStart(dcb);
00578 break;
00579 }
00580 continue;
00581 }
00582
00583
00584 if (dcb->dcb_ctlseq == 2) {
00585 dcb->dcb_ctlseq = 3;
00586 if (ch < 32)
00587 dcb->dcb_row = 0;
00588 else if (ch - 32 >= dcb->dcb_nrows)
00589 dcb->dcb_row = dcb->dcb_nrows - 1;
00590 else
00591 dcb->dcb_row = ch - 32;
00592 continue;
00593 }
00594
00595
00596 if (dcb->dcb_ctlseq == 3) {
00597 dcb->dcb_ctlseq = 0;
00598 if (ch < 32)
00599 dcb->dcb_col = 0;
00600 else if (ch - 32 >= dcb->dcb_vcols)
00601 dcb->dcb_col = dcb->dcb_vcols - 1;
00602 else
00603 dcb->dcb_col = ch - 32;
00604 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00605 continue;
00606 }
00607 }
00608
00609
00610
00611
00612
00613 (*dcb->dss_write) (ch);
00614
00615
00616 if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00617 *(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + dcb->dcb_col) = ch;
00618 if (++dcb->dcb_col >= dcb->dcb_vcols) {
00619 dcb->dcb_col = dcb->dcb_vcols - 1;
00620 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00621 }
00622 }
00623 }
00624 return rc;
00625 }
00626
00678 int TermWrite(NUTFILE * fp, CONST void *buffer, int len)
00679 {
00680 return TermPut(fp->nf_dev, buffer, len, 0);
00681 }
00682
00697 #ifdef __HARVARD_ARCH__
00698 int TermWrite_P(NUTFILE * fp, PGM_P buffer, int len)
00699 {
00700 return TermPut(fp->nf_dev, (CONST char *) buffer, len, 1);
00701 }
00702 #endif
00703
00721 NUTFILE *TermOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00722 {
00723 TERMDCB *dcb = dev->dev_dcb;
00724 NUTFILE *fp = malloc(sizeof(NUTFILE));
00725
00726 if (fp == 0)
00727 return NUTFILE_EOF;
00728
00729 if (mode & _O_BINARY)
00730 dcb->dcb_modeflags &= ~LCD_MF_COOKEDMODE;
00731 else
00732 dcb->dcb_modeflags |= LCD_MF_COOKEDMODE;
00733 fp->nf_next = 0;
00734 fp->nf_dev = dev;
00735 fp->nf_fcb = 0;
00736
00737 return fp;
00738 }
00739
00750 int TermClose(NUTFILE * fp)
00751 {
00752 if (fp && fp != NUTFILE_EOF) {
00753 free(fp);
00754 return 0;
00755 }
00756 return -1;
00757 }
00758