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 
00369     case LCD_SET_AUTOLF:
00370         if (*(uint32_t *)conf)
00371             dcb->dcb_modeflags |= LCD_MF_AUTOLF;
00372         else
00373             dcb->dcb_modeflags &= ~LCD_MF_AUTOLF;
00374         break;
00375     case LCD_GET_AUTOLF:
00376         if (dcb->dcb_modeflags & LCD_MF_AUTOLF)
00377             *(uint32_t *)conf = 1;
00378         else
00379             *(uint32_t *)conf = 0;
00380         break;
00381         
00382     case TIOCGWINSZ:
00383         win_size = (WINSIZE *)conf;
00384         win_size->ws_col    = dcb->dcb_nrows;
00385         win_size->ws_row    = dcb->dcb_vcols;
00386         win_size->ws_xpixel = 0;
00387         win_size->ws_ypixel = 0;
00388         break;
00389     }
00390     return 0;
00391 }
00392 
00393 
00406 int TermInit(NUTDEVICE * dev)
00407 {
00408     TERMDCB *dcb = dev->dev_dcb;
00409 
00410     
00411 
00412 
00413     if( dcb->dss_init != NULL) {
00414         
00415 
00416 
00417         if(  dcb->dss_init(dev) != 0) {
00418             return -1;
00419         }
00420     }
00421     
00422 
00423 
00424     dcb->dcb_smem = malloc(dcb->dcb_nrows * dcb->dcb_vcols);
00425     if( dcb->dcb_smem == NULL) {
00426         return -1;
00427     }
00428 
00429     TermClear(dcb);
00430 
00431     return 0;
00432 }
00433 
00445 static int TermPut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg)
00446 {
00447     int rc;
00448     CONST uint8_t *cp;
00449     uint8_t ch;
00450     TERMDCB *dcb = dev->dev_dcb;
00451 
00452     
00453 
00454 
00455     if (buffer == 0)
00456         return 0;
00457 
00458     
00459 
00460 
00461     cp = buffer;
00462     for (rc = 0; rc < len; cp++, rc++) {
00463         ch = pflg ? PRG_RDB(cp) : *cp;
00464 
00465         if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00466             
00467             if (dcb->dcb_ctlseq == 0) {
00468 
00469                 
00470                 if (ch == 10) {
00471                     dcb->dcb_col = 0;
00472                     TermLinefeed(dcb);
00473                     continue;
00474                 }
00475 
00476                 
00477                 if (ch == 13) {
00478                     dcb->dcb_col = 0;
00479                     (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols);
00480                     continue;
00481                 }
00482 
00483                 
00484                 if (ch == 27) {
00485                     dcb->dcb_ctlseq = 1;
00486                     continue;
00487                 }
00488 
00489                 
00490                 if (ch == 8) {
00491                     if (dcb->dcb_col) {
00492                         dcb->dcb_col--;
00493                         TermDeleteChar(dcb, dcb->dcb_col);
00494                     }
00495                     continue;
00496                 }
00497 
00498                 
00499                 if (ch == 12) {
00500                     TermClear(dcb);
00501                     continue;
00502                 }
00503             }
00504 
00505             
00506             if (dcb->dcb_ctlseq == 1) {
00507                 dcb->dcb_ctlseq = 0;
00508 
00509                 switch (ch) {
00510                     
00511                 case '@':
00512                     TermInsertSpace(dcb);
00513                     break;
00514 
00515                     
00516                 case 'A':
00517                     TermCursorUp(dcb);
00518                     break;
00519 
00520                     
00521                 case 'B':
00522                     if (++dcb->dcb_row >= dcb->dcb_nrows)
00523                         dcb->dcb_row = dcb->dcb_nrows - 1;
00524                     else
00525                         (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00526                     break;
00527 
00528                     
00529                 case 'C':
00530                     TermCursorRight(dcb);
00531                     break;
00532 
00533                     
00534                 case 'D':
00535                     TermCursorLeft(dcb);
00536                     break;
00537 
00538                     
00539                 case 'E':
00540                     TermClear(dcb);
00541                     break;
00542 
00543                     
00544                 case 'H':
00545                     dcb->dcb_col = 0;
00546                     dcb->dcb_row = 0;
00547                     (*dcb->dss_cursor_home) ();
00548                     break;
00549 
00550                     
00551                 case 'I':
00552                     TermReverseLinefeed(dcb);
00553                     break;
00554 
00555                     
00556                 case 'J':
00557                     TermEraseEnd(dcb);
00558                     break;
00559 
00560                     
00561                 case 'K':
00562                     TermEraseLineEnd(dcb, dcb->dcb_col);
00563                     break;
00564 
00565                     
00566                 case 'L':
00567                     TermInsertLine(dcb, dcb->dcb_row);
00568                     break;
00569 
00570                     
00571                 case 'M':
00572                     TermDeleteLine(dcb, dcb->dcb_row);
00573                     break;
00574 
00575                     
00576                 case 'P':
00577                     TermDeleteChar(dcb, dcb->dcb_col);
00578                     break;
00579 
00580                     
00581                 case 'Y':
00582                     dcb->dcb_ctlseq = 2;
00583                     break;
00584 
00585                     
00586                 case 'Z':
00587                     TermIdentify(dcb);
00588                     break;
00589 
00590                     
00591                 case 'e':
00592                     dcb->dcb_modeflags |= LCD_MF_CURSORON;
00593                     (*dcb->dss_cursor_mode) (1);
00594                     break;
00595 
00596                     
00597                 case 'f':
00598                     dcb->dcb_modeflags &= ~LCD_MF_CURSORON;
00599                     (*dcb->dss_cursor_mode) (0);
00600                     break;
00601 
00602                     
00603                 case 'd':
00604                     TermEraseStart(dcb);
00605                     break;
00606 
00607                     
00608                 case 'o':
00609                     TermEraseLineStart(dcb);
00610                     break;
00611                     
00612                 case 'i':
00613                     dcb->dcb_modeflags |= LCD_MF_INVERTED;
00614                     (*dcb->dss_cursor_mode) (3);
00615                     break;
00616                     
00617                 case 'n':
00618                     dcb->dcb_modeflags &= ~LCD_MF_INVERTED;
00619                     (*dcb->dss_cursor_mode) (2);
00620                     break;
00621                 }
00622                 continue;
00623             }
00624 
00625             
00626             if (dcb->dcb_ctlseq == 2) {
00627                 dcb->dcb_ctlseq = 3;
00628                 if (ch < 32)
00629                     dcb->dcb_row = 0;
00630                 else if (ch - 32 >= dcb->dcb_nrows)
00631                     dcb->dcb_row = dcb->dcb_nrows - 1;
00632                 else
00633                     dcb->dcb_row = ch - 32;
00634                 continue;
00635             }
00636 
00637             
00638             if (dcb->dcb_ctlseq == 3) {
00639                 dcb->dcb_ctlseq = 0;
00640                 if (ch < 32)
00641                     dcb->dcb_col = 0;
00642                 else if (ch - 32 >= dcb->dcb_vcols)
00643                     dcb->dcb_col = dcb->dcb_vcols - 1;
00644                 else
00645                     dcb->dcb_col = ch - 32;
00646                 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00647                 continue;
00648             }
00649         }
00650 
00651         
00652 
00653 
00654 
00655         (*dcb->dss_write) (ch);
00656 
00657         if (dcb->dcb_modeflags & LCD_MF_COOKEDMODE) {
00658             
00659             *(dcb->dcb_smem + dcb->dcb_row * dcb->dcb_vcols + dcb->dcb_col) = ch;
00660 
00661             
00662             if (++dcb->dcb_col >= dcb->dcb_vcols) {
00663                 if( dcb->dcb_modeflags & LCD_MF_AUTOLF) {
00664                     dcb->dcb_col = 0;
00665                     if( dcb->dcb_row < dcb->dcb_nrows) dcb->dcb_row++;
00666                 }
00667                 else
00668                     dcb->dcb_col = dcb->dcb_vcols - 1;
00669                 (*dcb->dss_set_cursor) (dcb->dcb_row * dcb->dcb_ncols + dcb->dcb_col);
00670             }
00671         }
00672     }
00673     return rc;
00674 }
00675 
00727 int TermWrite(NUTFILE * fp, CONST void *buffer, int len)
00728 {
00729     return TermPut(fp->nf_dev, buffer, len, 0);
00730 }
00731 
00746 #ifdef __HARVARD_ARCH__
00747 int TermWrite_P(NUTFILE * fp, PGM_P buffer, int len)
00748 {
00749     return TermPut(fp->nf_dev, (CONST char *) buffer, len, 1);
00750 }
00751 #endif
00752 
00770 NUTFILE *TermOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00771 {
00772     TERMDCB *dcb = dev->dev_dcb;
00773     NUTFILE *fp = malloc(sizeof(NUTFILE));
00774 
00775     if (fp == 0)
00776         return NUTFILE_EOF;
00777 
00778     if (mode & _O_BINARY)
00779         dcb->dcb_modeflags &= ~LCD_MF_COOKEDMODE;
00780     else
00781         dcb->dcb_modeflags |= LCD_MF_COOKEDMODE;
00782     fp->nf_next = 0;
00783     fp->nf_dev = dev;
00784     fp->nf_fcb = 0;
00785 
00786     return fp;
00787 }
00788 
00799 int TermClose(NUTFILE * fp)
00800 {
00801     if (fp && fp != NUTFILE_EOF) {
00802         free(fp);
00803         return 0;
00804     }
00805     return -1;
00806 }
00807