/* * WS281x LED Strip Driver for PRU1 * Vixy's Jaw LEDs - 24 LEDs (12 per side) * * Original Pin: P8_45 = pr1_pru1_pru_r30_0 (Mode 5) - LOCKED BY HDMI * Alternative: We use PRU0 with different memory offset instead * since all PRU1 pins are HDMI locked on this image * * This firmware is kept for reference but we'll use a combined * PRU0 firmware that handles both strips sequentially. */ #include #include #define LED_PIN 0 #define NUM_LEDS 24 /* WS2812 timing at 200MHz */ #define T0H 70 #define T0L 160 #define T1H 140 #define T1L 120 /* Shared memory offset for jaw data (after mood strip) */ #define SHARED_MEM 0x00010100 /* 256 bytes after PRU0 data */ volatile uint8_t *shared = (volatile uint8_t *)SHARED_MEM; volatile register uint32_t __R30; static inline void delay_cycles(uint32_t cycles) { while (cycles--) { __asm(" NOP"); } } static void send_bit(uint8_t bit) { if (bit) { __R30 |= (1 << LED_PIN); delay_cycles(T1H); __R30 &= ~(1 << LED_PIN); delay_cycles(T1L); } else { __R30 |= (1 << LED_PIN); delay_cycles(T0H); __R30 &= ~(1 << LED_PIN); delay_cycles(T0L); } } static void send_byte(uint8_t byte) { for (int i = 7; i >= 0; i--) { send_bit((byte >> i) & 1); } } void main(void) { CT_CFG.SYSCFG_bit.STANDBY_INIT = 0; __R30 &= ~(1 << LED_PIN); while (1) { if (shared[1] == 1) { uint8_t num = shared[0]; if (num > NUM_LEDS) num = NUM_LEDS; for (int i = 0; i < num; i++) { uint8_t g = shared[4 + i * 3 + 0]; uint8_t r = shared[4 + i * 3 + 1]; uint8_t b = shared[4 + i * 3 + 2]; send_byte(g); send_byte(r); send_byte(b); } __R30 &= ~(1 << LED_PIN); delay_cycles(10000); shared[1] = 0; } } }