Skip to content

Commit 9cec91b

Browse files
committed
[RK35] add driver for WS281X RGB LED (NeoPixel) ring
1 parent b188f3a commit 9cec91b

4 files changed

Lines changed: 245 additions & 2 deletions

File tree

software/firmware/source/SoftRF/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,14 @@ ifeq ($(BRIDGE), yes)
286286
CFLAGS += -DUSE_BRIDGE
287287
endif
288288

289+
pi:
289290
ifeq ($(NEOPIXEL), yes)
290291
OBJS += $(WS281X_PATH)/mailbox.o $(WS281X_PATH)/ws2811.o \
291292
$(WS281X_PATH)/pwm.o $(WS281X_PATH)/pcm.o \
292293
$(WS281X_PATH)/dma.o $(WS281X_PATH)/rpihw.o
294+
endif
295+
296+
ifeq ($(NEOPIXEL), yes)
293297
CFLAGS += -DUSE_NEOPIXEL
294298
endif
295299

software/firmware/source/SoftRF/src/platform/RK35.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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();

software/firmware/source/SoftRF/src/platform/RK35.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@
3838

3939
#define isValidFix() (isValidGNSSFix() || isValidGPSDFix())
4040

41+
#if defined(USE_NEOPIXEL)
42+
#define uni_begin() ws281x_init()
43+
#define uni_show() ws281x_show()
44+
#define uni_setPixelColor(i, c) ws281x_setPixelColor(i, c)
45+
#define uni_numPixels() ws281x_numPixels()
46+
#define uni_Color(r,g,b) ws281x_Color(r, g, b)
47+
#define color_t uint32_t
48+
#else
49+
50+
#define EXCLUDE_LED_RING
51+
52+
#endif /* USE_NEOPIXEL */
53+
4154
#define EEPROM_commit() {}
4255

4356
#define LED_STATE_ON HIGH // State when LED is litted
@@ -91,7 +104,7 @@ struct rst_info {
91104
#define SOC_GPIO_PIN_SCL 26 // RMIO26
92105

93106
#define SOC_GPIO_PIN_NEOPIXEL 4 // RMIO4
94-
#define SOC_GPIO_PIN_LED SOC_UNUSED_PIN
107+
#define SOC_GPIO_PIN_LED SOC_GPIO_PIN_NEOPIXEL
95108
#define SOC_GPIO_PIN_STATUS SOC_UNUSED_PIN
96109
#define SOC_GPIO_PIN_BUZZER 8 // RMIO8
97110

@@ -119,7 +132,6 @@ extern const char *Hardware_Rev[];
119132

120133
#define EXCLUDE_WIFI
121134
#define EXCLUDE_ETHERNET
122-
#define EXCLUDE_LED_RING
123135
//#define EXCLUDE_SOUND
124136
//#define EXCLUDE_EEPROM
125137
#define EXCLUDE_CC13XX
@@ -179,6 +191,14 @@ extern char* itoa(int, char *, int);
179191
extern bool RK35_OLED_probe_func(void);
180192
#endif /* USE_OLED */
181193

194+
#if defined(USE_NEOPIXEL)
195+
extern int ws281x_init(void);
196+
extern void ws281x_show(void);
197+
extern int ws281x_numPixels(void);
198+
extern void ws281x_setPixelColor(int, color_t);
199+
extern color_t ws281x_Color(uint8_t, uint8_t, uint8_t);
200+
#endif /* USE_NEOPIXEL */
201+
182202
#endif /* PLATFORM_RK35_H */
183203

184204
#endif /* LUCKFOX_LYRA */

software/firmware/source/SoftRF/src/platform/RPi.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,9 @@ static int led_count = LED_COUNT;
393393

394394
ws2811_t ledstring =
395395
{
396+
.render_wait_time = 0,
397+
.device = NULL,
398+
.rpi_hw = NULL,
396399
.freq = TARGET_FREQ,
397400
.dmanum = DMA,
398401
.channel =
@@ -403,14 +406,27 @@ ws2811_t ledstring =
403406
.invert = 0,
404407
.count = LED_COUNT,
405408
.strip_type = STRIP_TYPE,
409+
.leds = 0,
406410
.brightness = 255,
411+
.wshift = 0,
412+
.rshift = 0,
413+
.gshift = 0,
414+
.bshift = 0,
415+
.gamma = NULL,
407416
},
408417
[1] =
409418
{
410419
.gpionum = 0,
411420
.invert = 0,
412421
.count = 0,
422+
.strip_type = 0,
423+
.leds = 0,
413424
.brightness = 0,
425+
.wshift = 0,
426+
.rshift = 0,
427+
.gshift = 0,
428+
.bshift = 0,
429+
.gamma = NULL,
414430
},
415431
},
416432
};

0 commit comments

Comments
 (0)