feat: implement double-buffered glitch-free unrolled 3-bit SPI driver to guarantee continuous clock and zero glitches
This commit is contained in:
17
App/main.c
17
App/main.c
@@ -162,12 +162,17 @@ void WS2812_Write24Bit(u8 g, u8 r, u8 b)
|
|||||||
P2M1 &= ~((1 << 3) | (1 << 5));
|
P2M1 &= ~((1 << 3) | (1 << 5));
|
||||||
P2M0 |= ((1 << 3) | (1 << 5));
|
P2M0 |= ((1 << 3) | (1 << 5));
|
||||||
|
|
||||||
SPSTAT = 0xC0; // Clear flags first
|
SPSTAT = 0xC0; // Clear flags
|
||||||
SPCTL = 0xD0; // Enable SPI at SYSCLK/4 (3.0 MHz actual clock on board)
|
SPCTL = 0xD0; // Enable SPI at SYSCLK/4 (3.0 MHz actual clock on board)
|
||||||
SPDAT = b0; // Send 0x00. MOSI remains low during startup delay!
|
|
||||||
|
|
||||||
// Unrolled 10-byte transmission with minimal gap (~300ns)
|
SPDAT = b0; // Start transmitting dummy 0x00 (absorbs startup delay at MOSI=0)
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b1;
|
// Wait at least 16 CPU cycles to ensure b0 has moved to the shifter
|
||||||
|
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
|
||||||
|
_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
|
||||||
|
|
||||||
|
SPDAT = b1; // Buffer b1 (zero gap!)
|
||||||
|
|
||||||
|
// Transmission loop unrolled with double-buffering (zero gap SCLK)
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b2;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b2;
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b3;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b3;
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b4;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b4;
|
||||||
@@ -176,7 +181,9 @@ void WS2812_Write24Bit(u8 g, u8 r, u8 b)
|
|||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b7;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b7;
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b8;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b8;
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b9;
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; SPDAT = b9;
|
||||||
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0;
|
|
||||||
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; // Wait for b8 to finish shifting, b9 moves to shifter
|
||||||
|
while (!(SPSTAT & 0x80)); SPSTAT = 0xC0; // Wait for b9 to finish shifting
|
||||||
|
|
||||||
SPCTL = 0x90; // Disable SPI
|
SPCTL = 0x90; // Disable SPI
|
||||||
WS2812_DI = 0;
|
WS2812_DI = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user