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 NUTSPINODE *node;
00482
00483 NUTASSERT(dev->dev_dcb != NULL);
00484 NUTASSERT(dev->dev_icb != NULL);
00485
00486 dcb = dev->dev_dcb;
00487 node = dev->dev_icb;
00488
00489 if( pos < SEG7_DIGITS)
00490 {
00491 switch( act)
00492 {
00493 case DOT_7SEG_FLIP: dcb->digit[pos] ^= 0x80; break;
00494 case DOT_7SEG_SET: dcb->digit[pos] |= 0x80; break;
00495 case DOT_7SEG_CLR: dcb->digit[pos] &= ~0x80; break;
00496 }
00497 Spi7SegPush( dev);
00498 }
00499
00500 }
00501
00509 NUTFILE *Spi7SegOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc)
00510 {
00511 NUTFILE *fp;
00512
00513 NUTASSERT( dev != NULL);
00514
00515 if ((fp = malloc(sizeof(NUTFILE))) == 0) {
00516 return NUTFILE_EOF;
00517 }
00518
00519 fp->nf_fcb = 0;
00520 fp->nf_dev = dev;
00521 fp->nf_next = 0;
00522
00523 return fp;
00524
00525 }
00526
00532 static int Spi7SegClose(NUTFILE * fp)
00533 {
00534 if( fp != NULL) {
00535 free( fp);
00536 return 0;
00537 }
00538 return -1;
00539 }
00540
00541
00542
00543
00544
00545
00546
00559 int Spi7segInit(NUTDEVICE * dev)
00560 {
00561 uint8_t data;
00562 NUTSPINODE *node;
00563 DCB_7SEG * dcb;
00564
00565 NUTASSERT(dev != NULL);
00566 NUTASSERT(dev->dev_icb != NULL);
00567 node = dev->dev_icb;
00568
00569
00570 dcb = malloc( sizeof( DCB_7SEG));
00571 if( dcb == NULL)
00572 return -1;
00573 memset( dcb, 0, sizeof( DCB_7SEG));
00574 dev->dev_dcb = dcb;
00575
00576 NPRINTF("INIT %d Digits...\n", SEG7_DIGITS);
00577
00578 data = TEST_MODE_OFF;
00579 disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00580 disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00581 disp7segCommand(node, SEGR_DSP_TEST, &data, NULL, 1);
00582
00583 data = NORM_OP_RESET;
00584 disp7segCommand(node, SEGR_SHUTDOWN, &data, NULL, 1);
00585
00586 data = SEG7_DIGITS;
00587 disp7segCommand(node, SEGR_SCAN_LIM, &data, NULL, 1);
00588
00589 dcb->freg = NO_DIG_DECODE;
00590 disp7segCommand(node, SEGR_DEC_MODE, &dcb->freg, NULL, 1);
00591
00592 data = 0x0F;
00593 disp7segCommand(node, SEGR_INTENSITY, &data, NULL, 1);
00594
00595 data = 0;
00596 disp7segCommand(node, SEGR_DIG0, &data, NULL, 1);
00597 disp7segCommand(node, SEGR_DIG1, &data, NULL, 1);
00598 disp7segCommand(node, SEGR_DIG2, &data, NULL, 1);
00599
00600 return 0;
00601
00602 }
00603
00607 NUTSPINODE nodeSpi7SEG = {
00608 NULL,
00609 NULL,
00610 SPI_RATE_DISP_7SEG,
00611 SPI_MODE_DISP_7SEG,
00612 8,
00613 0
00614 };
00615
00619 NUTDEVICE devSpi7SEG = {
00620 NULL,
00621 {'7', 'S', 'E', 'G', 0, 0, 0},
00622 IFTYP_CHAR,
00623 0,
00624 0,
00625 &nodeSpi7SEG,
00626 0,
00627 Spi7segInit,
00628 Spi7SegIOCtl,
00629 0,
00630 Spi7segWrite,
00631 #ifdef __HARVARD_ARCH__
00632 0,
00633 #endif
00634 Spi7SegOpen,
00635 Spi7SegClose,
00636 0
00637 };
00638