- Combined PRU0 firmware for both mood (56 LED) and jaw (24 LED) strips - Uses P9_27 and P9_25 (free pins, not HDMI locked) - Python HTTP service on port 8765 - Named states: idle, listening, responding, pleasure, thinking, playful, commanding, love, sleep - Setup scripts for fresh BBB deployment Built with love by Vixy 🦊💜
95 lines
2.3 KiB
C
95 lines
2.3 KiB
C
/*
|
|
* WS281x LED Strip Driver for PRU0
|
|
* Vixy's Mood Strip - 56 LEDs
|
|
*
|
|
* Pin: P8_11 = pr1_pru0_pru_r30_15 (Mode 6)
|
|
* Alternative: P9_27 = pr1_pru0_pru_r30_5 (Mode 5) - FREE PIN!
|
|
*
|
|
* Shared Memory Layout (0x00010000):
|
|
* [0]: num_leds (max 56)
|
|
* [1]: trigger (write 1 to update)
|
|
* [4-171]: LED data (56 * 3 bytes, GRB format)
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <pru_cfg.h>
|
|
|
|
/* Use P9_27 (R30 bit 5) - it's free! */
|
|
#define LED_PIN 5
|
|
#define NUM_LEDS 56
|
|
|
|
/* WS2812 timing at 200MHz (5ns per cycle) */
|
|
#define T0H 70 /* 350ns high for 0 bit */
|
|
#define T0L 160 /* 800ns low for 0 bit */
|
|
#define T1H 140 /* 700ns high for 1 bit */
|
|
#define T1L 120 /* 600ns low for 1 bit */
|
|
|
|
/* Shared memory base */
|
|
#define SHARED_MEM 0x00010000
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void send_led(uint8_t g, uint8_t r, uint8_t b) {
|
|
send_byte(g);
|
|
send_byte(r);
|
|
send_byte(b);
|
|
}
|
|
|
|
void main(void) {
|
|
/* Enable OCP master port */
|
|
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
|
|
|
|
/* Clear output pin */
|
|
__R30 &= ~(1 << LED_PIN);
|
|
|
|
while (1) {
|
|
/* Check trigger flag */
|
|
if (shared[1] == 1) {
|
|
uint8_t num = shared[0];
|
|
if (num > NUM_LEDS) num = NUM_LEDS;
|
|
|
|
/* Send LED data (GRB format) */
|
|
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_led(g, r, b);
|
|
}
|
|
|
|
/* Reset pulse (>50us) */
|
|
__R30 &= ~(1 << LED_PIN);
|
|
delay_cycles(10000);
|
|
|
|
/* Clear trigger */
|
|
shared[1] = 0;
|
|
}
|
|
}
|
|
}
|