@@ -363,6 +363,178 @@ void notFound(Request &req, Response &res) {
363363}
364364#endif /* USE_BRIDGE */
365365
366+ #if defined(USE_NEOPIXEL)
367+ #include < sys/ioctl.h>
368+ #include < stdio.h>
369+ #include < string.h>
370+ #include < fcntl.h>
371+ #include < unistd.h>
372+
373+ #include < stdint.h>
374+ #include < linux/spi/spidev.h>
375+
376+ #define SPI_DEVICE " /dev/spidev1.1"
377+ #define NUM_PIXELS 12
378+
379+ typedef enum
380+ {
381+ SPIMODE0 = SPI_MODE_0 ,
382+ SPIMODE1 = SPI_MODE_1 ,
383+ SPIMODE2 = SPI_MODE_2 ,
384+ SPIMODE3 = SPI_MODE_3 ,
385+ } SPI_MODE ;
386+
387+ typedef enum
388+ {
389+ S_1M = 1000000 ,
390+ S_6_75M = 6750000 ,
391+ S_8M = 8000000 ,
392+ S_13_5M = 13500000 ,
393+ S_27M = 27000000 ,
394+ } SPI_SPEED ;
395+
396+ #define isTimeToDisplay () (millis() - LEDTimeMarker > 1000 )
397+
398+ unsigned long LEDTimeMarker = 0 ;
399+
400+ static unsigned char send_buf[24 * NUM_PIXELS ];
401+ static int spi_fd;
402+
403+ static int spi_init (const char *spi_dev)
404+ {
405+ int fd_spidev;
406+ int ret;
407+ SPI_MODE mode;
408+ char spi_bits;
409+ uint32_t spi_speed;
410+
411+ fd_spidev = open (spi_dev, O_RDWR );
412+ if (fd_spidev < 0 )
413+ {
414+ printf (" open %s err\n " , spi_dev);
415+ return -1 ;
416+ }
417+
418+ /* mode */
419+ mode = SPIMODE0 ;
420+ ret = ioctl (fd_spidev, SPI_IOC_WR_MODE , &mode); // mode 0
421+ if (ret < 0 )
422+ {
423+ printf (" SPI_IOC_WR_MODE err\n " );
424+ return -1 ;
425+ }
426+
427+ /* bits per word */
428+ spi_bits = 8 ;
429+ ret = ioctl (fd_spidev, SPI_IOC_WR_BITS_PER_WORD , &spi_bits); // 8bits
430+ if (ret < 0 )
431+ {
432+ printf (" SPI_IOC_WR_BITS_PER_WORD err\n " );
433+ return -1 ;
434+ }
435+
436+ /* speed */
437+ spi_speed = (uint32_t ) S_8M ;
438+ ret = ioctl (fd_spidev, SPI_IOC_WR_MAX_SPEED_HZ , &spi_speed); // 1MHz
439+ if (ret < 0 )
440+ {
441+ printf (" SPI_IOC_WR_MAX_SPEED_HZ err\n " );
442+ return -1 ;
443+ }
444+
445+ return fd_spidev;
446+ }
447+
448+ static int spi_write_nbyte_data (unsigned int fd_spidev,
449+ unsigned char *send_buf,
450+ unsigned int send_buf_len)
451+ {
452+ struct spi_ioc_transfer xfer[2 ];
453+ unsigned char recv_buf[send_buf_len];
454+ int status;
455+
456+ if (send_buf == NULL || send_buf_len < 1 )
457+ return -1 ;
458+
459+ memset (xfer, 0 , sizeof (xfer));
460+ memset (recv_buf, 0 , sizeof (send_buf_len));
461+
462+ xfer[0 ].tx_buf = (unsigned long )send_buf;
463+ xfer[0 ].rx_buf = (unsigned long )recv_buf;
464+ xfer[0 ].len = send_buf_len;
465+
466+ status = ioctl (fd_spidev, SPI_IOC_MESSAGE (1 ), xfer);
467+ if (status < 0 )
468+ {
469+ perror (" SPI_IOC_MESSAGE" );
470+ return -1 ;
471+ }
472+
473+ return 0 ;
474+ }
475+
476+ static void spi_exit (unsigned int fd_spidev)
477+ {
478+ if (fd_spidev >= 0 )
479+ close (fd_spidev);
480+ }
481+
482+ static void update_sendbuff (int n, unsigned char r, unsigned char g, unsigned char b)
483+ {
484+ int i = 0 ;
485+
486+ // update g
487+ for (i = 0 ; i < 8 ; i++)
488+ {
489+ send_buf[i + 24 * n] = (g & 0x80 ) ? (0xFC ) : (0xC0 );
490+ g <<= 1 ;
491+ }
492+
493+ // update r
494+ for (i = 8 ; i < 16 ; i++)
495+ {
496+ send_buf[i + 24 * n] = (r & 0x80 ) ? (0xFC ) : (0xC0 );
497+ r <<= 1 ;
498+ }
499+
500+ // update b
501+ for (i = 16 ; i < 24 ; i++)
502+ {
503+ send_buf[i + 24 * n] = (b & 0x80 ) ? (0xFC ) : (0xC0 );
504+ b <<= 1 ;
505+ }
506+ }
507+
508+ int ws281x_init (void )
509+ {
510+ spi_fd = spi_init (SPI_DEVICE );
511+ if (spi_fd < 0 )
512+ return -1 ;
513+
514+ return 0 ;
515+ }
516+
517+ void ws281x_show (void )
518+ {
519+ spi_write_nbyte_data (spi_fd, send_buf, sizeof (send_buf));
520+ }
521+
522+ int ws281x_numPixels (void )
523+ {
524+ return NUM_PIXELS ;
525+ }
526+
527+ void ws281x_setPixelColor (int n, color_t c)
528+ {
529+ update_sendbuff (n, (c>>16 )&0xFF , (c>>8 )&0xFF , (c>>0 )&0xFF );
530+ }
531+
532+ color_t ws281x_Color (uint8_t r, uint8_t g, uint8_t b)
533+ {
534+ return ((uint32_t )r << 16 ) | ((uint32_t )g << 8 ) | b;
535+ }
536+ #endif /* USE_NEOPIXEL */
537+
366538// -------------------------------------------------------------------------
367539//
368540// The MIT License (MIT)
@@ -1115,6 +1287,17 @@ void normal_loop()
11151287 Traffic_loop ();
11161288 }
11171289
1290+ #if defined(USE_NEOPIXEL)
1291+ if (isTimeToDisplay ()) {
1292+ if (isValidFix ()) {
1293+ LED_DisplayTraffic ();
1294+ } else {
1295+ LED_Clear ();
1296+ }
1297+ LEDTimeMarker = millis ();
1298+ }
1299+ #endif /* USE_NEOPIXEL */
1300+
11181301 if (isTimeToExport ()) {
11191302
11201303 NMEA_Export ();
@@ -1257,6 +1440,13 @@ void txrx_test_loop()
12571440
12581441 Traffic_loop ();
12591442
1443+ #if defined(USE_NEOPIXEL)
1444+ if (isTimeToDisplay ()) {
1445+ LED_DisplayTraffic ();
1446+ LEDTimeMarker = millis ();
1447+ }
1448+ #endif /* USE_NEOPIXEL */
1449+
12601450#if DEBUG_TIMING
12611451 export_start_ms = millis ();
12621452#endif
@@ -1456,6 +1646,11 @@ int main()
14561646// hw_info.gnss = GNSS_setup();
14571647
14581648 Traffic_setup ();
1649+
1650+ #if defined(USE_NEOPIXEL)
1651+ LED_setup ();
1652+ #endif /* USE_NEOPIXEL */
1653+
14591654 NMEA_setup ();
14601655
14611656 Traffic_TCP_Server.setup (JSON_SRV_TCP_PORT );
@@ -1496,6 +1691,10 @@ int main()
14961691 Serial.println ((unsigned long ) RELAY_SRC_PORT );
14971692#endif /* USE_BRIDGE */
14981693
1694+ #if defined(USE_NEOPIXEL)
1695+ LED_test ();
1696+ #endif /* USE_NEOPIXEL */
1697+
14991698 Sound_setup ();
15001699 SoC->Sound_test (reset_info.reason );
15011700
@@ -1566,6 +1765,10 @@ void shutdown(int reason)
15661765 SoC->Display_fini (reason);
15671766 }
15681767
1768+ #if defined(USE_NEOPIXEL)
1769+ spi_exit (spi_fd);
1770+ #endif /* USE_NEOPIXEL */
1771+
15691772#if defined(USE_BRIDGE)
15701773 WebServer.end ();
15711774 Uni_Udp.stop ();
0 commit comments