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 
00044 
00045 
00046 #include <cfg/os.h>
00047 #include <cfg/arch.h>
00048 
00049 #include <compiler.h>
00050 #include <string.h>
00051 #include <stdlib.h>
00052 
00053 #ifdef SPI2SEG_DEBUG
00054 #include <stdio.h>
00055 #define NPRINTF(args,...) printf(args,##__VA_ARGS__)
00056 #else
00057 #define NPRINTF(args,...)
00058 #endif
00059 
00060 
00061 #include <sys/nutdebug.h>
00062 #include <sys/timer.h>
00063 
00064 #include <stdio.h>
00065 
00066 #include <cfg/memory.h>
00067 
00068 #include <dev/blockdev.h>
00069 #include <cfg/spi_7seg.h>
00070 #include <dev/spi_7seg.h>
00071 
00072 #include <cfg/arch/gpio.h>
00073 #include <dev/spibus_at91.h>
00074 
00075 
00076 #ifndef SEG7_DIGITS
00077 #define SEG7_DIGITS 4
00078 #endif
00079 
00080 #define SEG7_REVERSE
00081 
00082 
00083 #define SEGR_NOOP       0x00
00084 #define SEGR_DIG0       0x01
00085 #define SEGR_DIG1       0x02
00086 #define SEGR_DIG2       0x03
00087 #define SEGR_DIG3       0x04
00088 #define SEGR_DIG4       0x05
00089 #define SEGR_DIG5       0x06
00090 #define SEGR_DIG6       0x07
00091 #define SEGR_DIG7       0x08
00092 
00093 #define SEGR_DEC_MODE   0x09
00094 #define SEGR_INTENSITY  0x0a
00095 #define SEGR_SCAN_LIM   0x0b
00096 #define SEGR_SHUTDOWN   0x0c
00097 #define SEGR_FEATURE    0x0e
00098 #define SEGR_DSP_TEST   0x0f
00099 
00100 
00101 #define SHUTDOWN_RESET  0x00
00102 #define SHUTDOWN_SOFT   0x80
00103 #define NORM_OP_RESET   0x01
00104 #define NORM_OP_SOFT    0x81
00105 
00106 
00107 #define NO_DIG_DECODE   0x00
00108 #define DIG_0_DECODE    0x01
00109 #define DIG_0_3_DECODE  0x0f
00110 #define DIG_0_7_DECODE  0xff
00111 
00112 
00113 #define SEGF_EXTCLK     0x01
00114 #define SEGF_REGRES     0x02
00115 #define SEGF_DECSEL     0x04
00116 #define SEGF_SPIEN      0x08
00117 #define SEGF_BLINK      0x10
00118 #define SEGF_BLSLOW     0x20
00119 #define SEGF_BLSYNC     0x40
00120 #define SEGF_BLSTART    0x80
00121 
00122 #define SEGF_BLMASK     (SEGF_BLINK|SEGF_BLSLOW)
00123 
00124 
00125 #define TEST_MODE_OFF   0x00
00126 #define TEST_MODE_ON    0x01
00127 
00128 
00129 #define DISPLAY_LIMIT   2
00130 
00131 #ifndef SPI_RATE_DISP_7SEG
00132 #define SPI_RATE_DISP_7SEG  400000
00133 #endif
00134 
00135 #ifndef SPI_MODE_DISP_7SEG
00136 #define SPI_MODE_DISP_7SEG SPI_MODE_3
00137 #endif
00138 
00139 
00140 #define ICMD_UPDATE     0x01
00141 #define ICMD_INTENS     0x02
00142 #define ICMD_ESCAPE     0x80
00143 
00147 typedef struct {
00148     uint_fast8_t  digit[SEG7_DIGITS]; 
00149     uint_fast8_t  dip;        
00150     uint_fast8_t  freg;      
00151     uint_fast8_t  icmd;      
00152 } DCB_7SEG;
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 static CONST uint8_t Seg7CharTab[] = {
00172         (0x00),
00173         (0x28),
00174         (0x22),
00175         (0x00),
00176         (0x5B),
00177         (0x00),
00178         (0x6F),
00179         (0x20),
00180         (0x4E),
00181         (0x78),
00182         (0x00),
00183         (0x31),
00184         (0x20),
00185         (0x01),
00186         (0x01),
00187         (0x15),
00188         (0x7E),
00189         (0x30),
00190         (0x6D),
00191         (0x79),
00192         (0x33),
00193         (0x5B),
00194         (0x5F),
00195         (0x70),
00196         (0x7F),
00197         (0x7B),
00198         (0x00),
00199         (0x00),
00200         (0x00),
00201         (0x09),
00202         (0x00),
00203         (0x65),
00204         (0x00),
00205         (0x77),
00206         (0x1F),
00207         (0x0D),
00208         (0x3D),
00209         (0x4F),
00210         (0x47),
00211         (0x5F),
00212         (0x37),
00213         (0x10),
00214         (0x3C),
00215         (0x0F),
00216         (0x0E),
00217         (0x76),
00218         (0x15),
00219         (0x1D),
00220         (0x67),
00221         (0x73),
00222         (0x05),
00223         (0x5B),
00224         (0x0F),
00225         (0x3E),
00226         (0x1C),
00227         (0x3F),
00228         (0x37),
00229         (0x3B),
00230         (0x6D),
00231         (0x4E),
00232         (0x13),
00233         (0x78),
00234         (0x42),
00235         (0x01),
00236 };
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00253 static int disp7segCommand(NUTSPINODE * node, uint8_t addr, CONST void *txbuf, void *rxbuf, int xlen)
00254 {
00255     int rc = -1;
00256     NUTSPIBUS *bus;
00257     uint8_t *tmp;
00258         uint8_t cmd[2];
00259 
00260     NUTASSERT(node != NULL);
00261     bus = (NUTSPIBUS *) node->node_bus;
00262     NUTASSERT(bus != NULL);
00263     NUTASSERT(bus->bus_alloc != NULL);
00264     NUTASSERT(bus->bus_transfer != NULL);
00265     NUTASSERT(bus->bus_release != NULL);
00266 
00267         
00268          cmd[0] = addr;
00269 
00270         tmp = (uint8_t *)txbuf;
00271         
00272          cmd[1] = tmp[0];
00273         
00274         
00275     rc = (*bus->bus_alloc) (node, 1000);
00276     if (rc == 0) {
00277         rc = (*bus->bus_transfer) (node, cmd, NULL, 2);
00278 
00279         (*bus->bus_release) (node);
00280     }
00281     return rc;
00282 }
00283 
00289 void Spi7SegPush( NUTDEVICE * dev)
00290 {
00291         uint_fast8_t i;
00292     DCB_7SEG * dcb;
00293         NUTSPINODE *node;
00294 
00295     NUTASSERT(dev->dev_dcb != NULL);
00296     NUTASSERT(dev->dev_icb != NULL);
00297 
00298     dcb  = dev->dev_dcb;
00299     node = dev->dev_icb;
00300 
00301 #ifdef SEG7_REVERSE
00302     NPRINTF("<");
00303         for (i=0;i<SEG7_DIGITS;i++)
00304         {
00305         
00306                 disp7segCommand( node, SEG7_DIGITS-i, &(dcb->digit[i]), NULL, 1);
00307         NPRINTF(" %02x",dcb->digit[i]);
00308         }
00309     NPRINTF(">\n");
00310 #else
00311         disp7segCommand(node, 0, dcb->digit, NULL, SEG7_DIGITS);
00312 #endif
00313 }
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00329 int Spi7segPutc(NUTDEVICE * dev, char c)
00330 {
00331     DCB_7SEG * dcb;
00332         NUTSPINODE *node;
00333 
00334     NUTASSERT(dev->dev_dcb != NULL);
00335     NUTASSERT(dev->dev_icb != NULL);
00336 
00337     dcb  = dev->dev_dcb;
00338     node = dev->dev_icb;
00339 
00340     NPRINTF("[%c]", c);
00341 
00342     if( dcb->icmd & ICMD_ESCAPE) {
00343 
00344         dcb->icmd &= ~ICMD_ESCAPE;
00345         
00346         switch( c) {
00347             case 'b':       
00348                 dcb->freg |= (SEGF_BLINK | SEGF_BLSLOW);
00349                 disp7segCommand( node, SEGR_FEATURE, &dcb->freg, NULL, 1);
00350                 return 0;
00351                 break;
00352             case 'f':       
00353                 dcb->freg &= ~SEGF_BLMASK;
00354                 dcb->freg |= SEGF_BLINK ;
00355                 disp7segCommand( node, SEGR_FEATURE, &dcb->freg, NULL, 1);
00356                 return 0;
00357                 break;
00358             case 'n':       
00359                 dcb->freg &= ~SEGF_BLMASK;
00360                 disp7segCommand( node, SEGR_FEATURE, &dcb->freg, NULL, 1);
00361                 return 0;
00362                 break;
00363             case 'h':       
00364                 dcb->dip = 0;
00365                 return 0;
00366                 break;
00367             case 'c':       
00368                 memset( dcb->digit, 0, SEG7_DIGITS);
00369                 dcb->icmd |= ICMD_UPDATE;
00370                 break;
00371             case 't':       
00372                 memset( dcb->digit, 0xFF, SEG7_DIGITS);
00373                 dcb->icmd |= ICMD_UPDATE;
00374                 break;
00375             case 'i':       
00376                 dcb->icmd |= ICMD_INTENS;
00377                 return 0;
00378                 break;
00379             default:
00380                 break;
00381         }
00382 
00383     }
00384     else {
00385         
00386 
00387         
00388         if( c == 0x1b) {
00389             dcb->icmd |= ICMD_ESCAPE;
00390             return 0;
00391         }
00392 
00393         
00394         if( dcb->icmd & ICMD_INTENS) {
00395             dcb->icmd &= ~ICMD_INTENS;
00396             c = (c>'9')?(c-'A'+10):(c-'0');
00397             disp7segCommand( node, SEGR_INTENSITY, &c, NULL, 1);
00398             return 0;
00399         }
00400 
00401         if( c == '\n' ) {  
00402             dcb->dip = 0;
00403             return 0;
00404         }
00405 
00406         
00407 
00408         if( c == '.') {
00409             
00410             if( dcb->dip > 0) dcb->digit[dcb->dip-1] |= 0x80;
00411             dcb->icmd |= ICMD_UPDATE;
00412         }
00413         else if( (c >= ' ') && ( dcb->dip < SEG7_DIGITS)) {
00414             if( c > 0x5F) c -= 0x20;  
00415             
00416             dcb->digit[ dcb->dip++] = Seg7CharTab[(c&0xff)-' '];
00417             dcb->icmd |= ICMD_UPDATE;
00418         }
00419     }
00420 
00421     if( dcb->dip > SEG7_DIGITS) dcb->dip = SEG7_DIGITS;
00422 
00423     if( dcb->icmd & ICMD_UPDATE)
00424     {
00425         dcb->icmd &= ~ICMD_UPDATE;
00426                 Spi7SegPush( dev);
00427     }
00428         return 0;
00429 }
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00444 static int Spi7SegIOCtl(NUTDEVICE * dev, int req, void *conf)
00445 {
00446     return 0;
00447 }
00448 
00457 int Spi7segWrite(NUTFILE * fp, CONST void *buffer, int len)
00458 {
00459     int i=len;
00460     CONST char *cp = buffer;
00461 
00462     NUTASSERT(fp->nf_dev != NULL);
00463 
00464     while(i--)
00465     {
00466         Spi7segPutc( fp->nf_dev, *cp++);
00467     }
00468     return len;
00469 }
00470 
00478 void Spi7segDot(NUTDEVICE * dev, uint8_t pos, uint8_t act)
00479 {
00480     DCB_7SEG * dcb;
00481 
00482     NUTASSERT(dev->dev_dcb != NULL);
00483 
00484     dcb  = dev->dev_dcb;
00485 
00486         if( pos < SEG7_DIGITS)
00487         {
00488                 switch( act)
00489                 {
00490                         case DOT_7SEG_FLIP:     dcb->digit[pos] ^= 0x80; break;
00491                         case DOT_7SEG_SET:      dcb->digit[pos] |= 0x80; break;
00492                         case DOT_7SEG_CLR:      dcb->digit[pos] &= ~0x80; break;
00493                 }
00494                 Spi7SegPush( dev);
00495         }
00496 
00497 }
00498 
00506 NUTFILE *Spi7SegOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00507 {
00508     NUTFILE *fp;
00509 
00510     NUTASSERT( dev != NULL);
00511 
00512     if ((fp = malloc(sizeof(NUTFILE))) == 0) {
00513         return NUTFILE_EOF;
00514     }
00515 
00516     fp->nf_fcb = 0;
00517     fp->nf_dev = dev;
00518     fp->nf_next = 0;
00519 
00520     return fp;
00521 
00522 }
00523 
00529 static int Spi7SegClose(NUTFILE * fp)
00530 {
00531     if( fp != NULL) {
00532         free( fp);
00533         return 0;
00534     }
00535     return -1;
00536 }
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00556 int Spi7segInit(NUTDEVICE * dev)
00557 {
00558         uint8_t data;
00559     NUTSPINODE *node;
00560     DCB_7SEG * dcb;
00561 
00562     NUTASSERT(dev != NULL);
00563     NUTASSERT(dev->dev_icb != NULL);
00564     node = dev->dev_icb;
00565 
00566     
00567     dcb = malloc( sizeof( DCB_7SEG));
00568     if( dcb == NULL)
00569         return -1;
00570     memset( dcb, 0, sizeof( DCB_7SEG));
00571     dev->dev_dcb = dcb;
00572 
00573     NPRINTF("INIT %d Digits...\n", SEG7_DIGITS);
00574 
00575         data = TEST_MODE_OFF;
00576         disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00577         disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00578         disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00579 
00580         data = NORM_OP_RESET;
00581         disp7segCommand(node, SEGR_SHUTDOWN, &data, NULL, 1);
00582 
00583         data = SEG7_DIGITS;
00584         disp7segCommand(node, SEGR_SCAN_LIM, &data, NULL, 1);
00585 
00586         dcb->freg = NO_DIG_DECODE;
00587         disp7segCommand(node, SEGR_DEC_MODE, &dcb->freg, NULL, 1);
00588 
00589         data = 0x0F;
00590         disp7segCommand(node, SEGR_INTENSITY, &data, NULL, 1);
00591 
00592         data = 0;
00593         disp7segCommand(node, SEGR_DIG0, &data, NULL, 1);
00594         disp7segCommand(node, SEGR_DIG1, &data, NULL, 1);
00595         disp7segCommand(node, SEGR_DIG2, &data, NULL, 1);
00596 
00597         return 0;
00598 
00599 }
00600 
00604 NUTSPINODE nodeSpi7SEG = {
00605     NULL,                   
00606     NULL,                   
00607     SPI_RATE_DISP_7SEG,     
00608     SPI_MODE_DISP_7SEG,     
00609     8,                      
00610     0                       
00611 };
00612 
00616 NUTDEVICE devSpi7SEG = {
00617     NULL,                               
00618     {'7', 'S', 'E', 'G', 0, 0, 0},  
00619     IFTYP_CHAR,                         
00620     0,                                  
00621     0,                                  
00622     &nodeSpi7SEG,                       
00623     0,                              
00624     Spi7segInit,                        
00625     Spi7SegIOCtl,                   
00626         0,                                                              
00627     Spi7segWrite,                   
00628 #ifdef __HARVARD_ARCH__
00629     0,                                                          
00630 #endif
00631     Spi7SegOpen,                                
00632     Spi7SegClose,                               
00633     0                                                           
00634 };
00635