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