Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ws2813 timings support #510

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ to the appropriate output pin.
For SPI the Raspbian spidev driver is used (`/dev/spidev0.0`).
This library and test program set the clock rate to 3X the desired output
frequency and creates a bit pattern in RAM from an array of colors where
each bit is represented by 3 bits as follows.
each bit is represented by 4 bits as follows.

Bit 1 - 1 1 0
Bit 0 - 1 0 0
Bit 1 - 1 1 1 0
Bit 0 - 1 0 0 0


### GPIO Usage:
Expand Down
32 changes: 17 additions & 15 deletions ws2811.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,21 @@
#define OSC_FREQ 19200000 // crystal frequency
#define OSC_FREQ_PI4 54000000 // Pi 4 crystal frequency

// Symbol definitions
#define SYMBOL_HIGH 0b1110
#define SYMBOL_LOW 0b1000

// Symbol definitions for software inversion (PCM and SPI only)
#define SYMBOL_HIGH_INV 0b0001
#define SYMBOL_LOW_INV 0b0111

#define SYMBOL_LEN ((int)log2(SYMBOL_HIGH)+1)

/* 4 colors (R, G, B + W), 8 bits per byte, 3 symbols per bit + 55uS low for reset signal */
#define LED_COLOURS 4
#define LED_RESET_uS 55
#define LED_BIT_COUNT(leds, freq) ((leds * LED_COLOURS * 8 * 3) + ((LED_RESET_uS * \
(freq * 3)) / 1000000))
#define LED_RESET_uS SYMBOL_LEN == 3 ? 55 : 300
#define LED_BIT_COUNT(leds, freq) ((leds * LED_COLOURS * 8 * SYMBOL_LEN) + ((LED_RESET_uS * \
(freq * SYMBOL_LEN)) / 1000000))

/* Minimum time to wait for reset to occur in microseconds. */
#define LED_RESET_WAIT_TIME 300
Expand All @@ -72,14 +82,6 @@
RPI_PWM_CHANNELS)
#define PCM_BYTE_COUNT(leds, freq) ((((LED_BIT_COUNT(leds, freq) >> 3) & ~0x7) + 4) + 4)

// Symbol definitions
#define SYMBOL_HIGH 0x6 // 1 1 0
#define SYMBOL_LOW 0x4 // 1 0 0

// Symbol definitions for software inversion (PCM and SPI only)
#define SYMBOL_HIGH_INV 0x1 // 0 0 1
#define SYMBOL_LOW_INV 0x3 // 0 1 1

// Driver mode definitions
#define NONE 0
#define PWM 1
Expand Down Expand Up @@ -359,7 +361,7 @@ static int setup_pwm(ws2811_t *ws2811)
stop_pwm(ws2811);

// Setup the Clock - Use OSC @ 19.2Mhz w/ 3 clocks/tick
cm_clk->div = CM_CLK_DIV_PASSWD | CM_CLK_DIV_DIVI(osc_freq / (3 * freq));
cm_clk->div = CM_CLK_DIV_PASSWD | CM_CLK_DIV_DIVI(osc_freq / (SYMBOL_LEN * freq));
cm_clk->ctl = CM_CLK_CTL_PASSWD | CM_CLK_CTL_SRC_OSC;
cm_clk->ctl = CM_CLK_CTL_PASSWD | CM_CLK_CTL_SRC_OSC | CM_CLK_CTL_ENAB;
usleep(10);
Expand Down Expand Up @@ -442,7 +444,7 @@ static int setup_pcm(ws2811_t *ws2811)
stop_pcm(ws2811);

// Setup the PCM Clock - Use OSC @ 19.2Mhz w/ 3 clocks/tick
cm_clk->div = CM_CLK_DIV_PASSWD | CM_CLK_DIV_DIVI(osc_freq / (3 * freq));
cm_clk->div = CM_CLK_DIV_PASSWD | CM_CLK_DIV_DIVI(osc_freq / (SYMBOL_LEN * freq));
cm_clk->ctl = CM_CLK_CTL_PASSWD | CM_CLK_CTL_SRC_OSC;
cm_clk->ctl = CM_CLK_CTL_PASSWD | CM_CLK_CTL_SRC_OSC | CM_CLK_CTL_ENAB;
usleep(10);
Expand Down Expand Up @@ -1196,7 +1198,7 @@ ws2811_return_t ws2811_render(ws2811_t *ws2811)
if ((driver_mode != PWM) && channel->invert) symbol = SYMBOL_HIGH_INV;
}

for (l = 2; l >= 0; l--) // Symbol
for (l = SYMBOL_LEN; l >= 0; l--) // Symbol
{
uint32_t *wordptr = &((uint32_t *)pxl_raw)[wordpos]; // PWM & PCM
volatile uint8_t *byteptr = &pxl_raw[bytepos]; // SPI
Expand Down Expand Up @@ -1229,7 +1231,7 @@ ws2811_return_t ws2811_render(ws2811_t *ws2811)
else // PWM & PCM
{
// Every other word is on the same channel for PWM
wordpos += (driver_mode == PWM ? 2 : 1);
wordpos += (driver_mode == PWM ? RPI_PWM_CHANNELS : 1);
bitpos = 31;
}
}
Expand Down