diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2020-11-29 00:50:10 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2020-11-29 00:50:10 -0700 |
commit | 1ec4e164df03fae8c42fd7aea2614fa836bcc2d7 (patch) | |
tree | bf80e5375a26bbb5504ffd64a8b08bb7a0bbbfa4 | |
parent | fd674424d19cf12c1186394606729cff236d5bdf (diff) | |
download | stm32l4-1ec4e164df03fae8c42fd7aea2614fa836bcc2d7.tar.gz stm32l4-1ec4e164df03fae8c42fd7aea2614fa836bcc2d7.tar.bz2 stm32l4-1ec4e164df03fae8c42fd7aea2614fa836bcc2d7.zip |
Have a stable red/green pattern on my LED strip.
I finally got a stable red/green pattern to show up on the LED strip.
Unfortunately I had to do this manually because my driver is broken. No
Dma, interrupts or drivers, but manually writing to the spi bus.
Currently the driver assums the data sheet doesn't lie and inflates each
bit 3:1 so a 1 is a 110 pattern and a 0 is a 100 pattern. This should be
well within the tolerances at 2.5Mhz, but alas it's not.
I figured out that it's better to inflate each bit to a 4:1 ratio so a 1
is a 1100 pattern and a 0 is a 1000 pattern. This appears to produce
cleaner results.
-rw-r--r-- | include/drv/ws2812B/ws2812b.h | 3 | ||||
-rw-r--r-- | src/drv/ws2812B/ws2812b.c | 71 | ||||
-rw-r--r-- | src/kern/main.c | 278 |
3 files changed, 155 insertions, 197 deletions
diff --git a/include/drv/ws2812B/ws2812b.h b/include/drv/ws2812B/ws2812b.h index cdbb41a..bc86cc5 100644 --- a/include/drv/ws2812B/ws2812b.h +++ b/include/drv/ws2812B/ws2812b.h @@ -15,4 +15,7 @@ static_assert(sizeof(rgb_t) == 3, "Sizeof rgb_t should be 3."); uint8_t* ws2812b_compile_rgb(rgb_t* out, size_t arr_len); +/* Returns sin((n - 128) / 256) * 256. */ +uint8_t byte_sin(uint8_t n); + #endif /* WS2812B_H_ */ diff --git a/src/drv/ws2812B/ws2812b.c b/src/drv/ws2812B/ws2812b.c index e1e9309..2a1ccfb 100644 --- a/src/drv/ws2812B/ws2812b.c +++ b/src/drv/ws2812B/ws2812b.c @@ -1,13 +1,38 @@ #include "drv/ws2812B/ws2812b.h" +#include "arch/stm32l4xxx/peripherals/spi.h" +#include "kern/dma/dma_manager.h" #include "kern/mem.h" #include "kern/panic.h" -#include "kern/dma/dma_manager.h" -#include "arch/stm32l4xxx/peripherals/spi.h" + +uint8_t sintable[256] = { + 128, 148, 156, 162, 168, 172, 177, 181, 184, 187, 191, 194, 196, 199, 202, + 204, 207, 209, 211, 213, 215, 217, 219, 221, 223, 224, 226, 228, 229, 231, + 232, 233, 235, 236, 237, 239, 240, 241, 242, 243, 244, 245, 246, 246, 247, + 248, 249, 249, 250, 251, 251, 252, 252, 253, 253, 253, 254, 254, 254, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, + 253, 252, 252, 251, 251, 250, 249, 249, 248, 247, 246, 246, 245, 244, 243, + 242, 241, 240, 239, 237, 236, 235, 233, 232, 231, 229, 228, 226, 224, 223, + 221, 219, 217, 215, 213, 211, 209, 207, 204, 202, 199, 196, 194, 191, 187, + 184, 181, 177, 172, 168, 162, 156, 148, 128, 108, 100, 94, 88, 84, 79, + 75, 72, 69, 65, 62, 60, 57, 54, 52, 49, 47, 45, 43, 41, 39, + 37, 35, 33, 32, 30, 28, 27, 25, 24, 23, 21, 20, 19, 17, 16, + 15, 14, 13, 12, 11, 10, 10, 9, 8, 7, 7, 6, 5, 5, 4, + 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, + 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, + 23, 24, 25, 27, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 47, + 49, 52, 54, 57, 60, 62, 65, 69, 72, 75, 79, 84, 88, 94, 100, + 108}; + +uint8_t byte_sin(uint8_t n) +{ + return sintable[n]; +} uint8_t* ws2812b_compile_rgb(rgb_t* out_, size_t arr_len) { - uint8_t* out = (uint8_t*) out_; + uint8_t* out = (uint8_t*)out_; uint8_t* spi_out = kalloc(arr_len * 9); if (!spi_out) { @@ -20,35 +45,17 @@ uint8_t* ws2812b_compile_rgb(rgb_t* out_, size_t arr_len) for (i = 0, j = 0; i < arr_len * 3; ++i, j += 3) { // stuff uint8_t c = out[i]; - spi_out[j] = 0 - | (1 << 7) - | ((c & (1 << 7)) << 6) - | (0 << 5) - | (1 << 4) - | ((c & (1 << 6)) << 3) - | (0 << 2) - | (1 << 1) - | ((c & (1 << 5)) << 0); - - spi_out[j + 1] = 0 - | (0 << 7) - | (1 << 6) - | ((c & (1 << 4)) << 5) - | (0 << 4) - | (1 << 3) - | ((c & (1 << 3)) << 2) - | (0 << 1) - | (1 << 0); - - spi_out[j + 2] = 0 - | ((c & (1 << 2)) << 7) - | (0 << 6) - | (1 << 5) - | ((c & (1 << 1)) << 4) - | (0 << 3) - | (1 << 2) - | ((c & (1 << 0)) << 1) - | (0 << 0); + spi_out[j] = 0 | (1 << 7) | ((c & (1 << 7)) << 6) | (0 << 5) | (1 << 4) | + ((c & (1 << 6)) << 3) | (0 << 2) | (1 << 1) | + ((c & (1 << 5)) << 0); + + spi_out[j + 1] = 0 | (0 << 7) | (1 << 6) | ((c & (1 << 4)) << 5) | + (0 << 4) | (1 << 3) | ((c & (1 << 3)) << 2) | (0 << 1) | + (1 << 0); + + spi_out[j + 2] = 0 | ((c & (1 << 2)) << 7) | (0 << 6) | (1 << 5) | + ((c & (1 << 1)) << 4) | (0 << 3) | (1 << 2) | + ((c & (1 << 0)) << 1) | (0 << 0); } return spi_out; diff --git a/src/kern/main.c b/src/kern/main.c index 3dcadf6..5af5fa7 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -2,203 +2,52 @@ #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" #include "arch/stm32l4xxx/peripherals/dma.h" -#include "arch/stm32l4xxx/peripherals/rcc.h" #include "arch/stm32l4xxx/peripherals/irq.h" +#include "arch/stm32l4xxx/peripherals/rcc.h" #include "arch/stm32l4xxx/peripherals/spi.h" #include "arch/stm32l4xxx/peripherals/system.h" -#include "kern/gpio/gpio_manager.h" +#include "drv/ws2812B/ws2812b.h" +#include "kern/delay.h" #include "kern/dma/dma_manager.h" +#include "kern/gpio/gpio_manager.h" +#include "kern/gpio/sysled.h" #include "kern/init.h" #include "kern/log.h" #include "kern/mem.h" #include "kern/mpu/mpu_manager.h" #include "kern/panic.h" -#include "kern/delay.h" #include "kern/priv.h" -#include "kern/gpio/sysled.h" -#include "arch/stm32l4xxx/peripherals/clock.h" #include "user/syscall.h" -#include "drv/ws2812B/ws2812b.h" - - -gpio_reserved_pin_t sysl; -int syslon; -int n; -uint16_t my_short; -extern uint16_t dma_inuse; - -void on_spi1() -{ - SPI1.d_r = ~my_short; - if (n++ == 10000) { - if (syslon) { - set_gpio_pin_low(sysl); - } else { - set_gpio_pin_high(sysl); - } - - syslon = !syslon; - n = 0; - } -} - -inline void spi_write_byte(uint8_t byte) -{ - // volatile uint32_t read; - - //delay(5); - //while (regget(SPI1.s_r, spi_rxne)) { - // read = SPI1.d_r; - //} - //delay(5); - - //delay(5); - while (regget(SPI1.s_r, spi_ftlvl) > SPI_FIFO_STATUS_HALF); - SPI1.d_r = (byte << 8) | byte; -} void on_hard_fault() { panic("Hard fault encountered!\n"); } -void on_systick() /* Overrides weak-symbol on_systick. */ -{ - // klogf("systick\n"); - if (my_short == 0) my_short = 0xffff; - my_short >>=1; -} - -void configure_mpu() -{ - configure_flash_region((void*)0x08000000, REGION_SIZE_256Kb, NOT_PRIVILEGED); - configure_ram_region((void*)SRAM1_BASE, REGION_SIZE_64Kb, NOT_PRIVILEGED); - configure_ram_region((void*)SRAM2_BASE, REGION_SIZE_16Kb, NOT_PRIVILEGED); - configure_peripheral_region((void*)0x40000000, REGION_SIZE_512Mb, PRIVILEGED); - mpu_set_enabled(1); -} - -static void dma_callback(void* arg) -{ - klogf("Dma callback\n"); - dma_channel_t* chan = arg; - - release_dma_channel(*chan); - dma_channel_interrupt_enable(*chan, 0); - - regset(SPI1.c_r1, spi_spe, 0); - - DMA2.ifc_r |= 0xffffffff; - DMA1.ifc_r |= 0xffffffff; - regset(DMA2.channel_config[3].cc_r, dma_cc_en, 0); -} - #ifdef ARCH_STM32L4 -/* Main function. This gets executed from the interrupt vector defined above. */ -int main() +void configure_spi1() { int ec = 0; - size_t size = 20; - rgb_t arr[] = { - {0x00, 0x00, 0xff}, - {0x00, 0xff, 0x00}, - {0xff, 0x00, 0x00}, - - {0xff, 0x80, 0x80}, - {0x80, 0xff, 0x80}, - {0x80, 0x80, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - }; - uint8_t* dataptr = ws2812b_compile_rgb(arr, size); - - klogf("Heap start: %p\n", &HEAP_START); - klogf("Heap end: %p\n", &HEAP_STOP); - klogf("Dataptr start: %p\n", dataptr); - klogf("Dataptr end: %p\n", (dataptr + size)); - - dma_opts_t opts = DEFAULT_DMA_OPTS; - opts.transfer_complete_interrupt_enable = 1; - opts.circular_mode = 0; - dma_mem2p_channel_t dma_chan = - select_dma_channel_mem2p(DMA2_PERIPH_SPI1_TX, &opts, &ec); - dma_chan_set_callback(dma_chan.c_, dma_callback, &dma_chan); - - if (ec) { - panic("Unable to allocate dma channel: %d\n", ec); - } - - my_short = 0xff; - klogf("This is weird.\n"); - // configure_mpu(); - sysl = get_sysled(); - - // gpio_enable_alternate_function( - // GPIO_ALTERNATE_FUNCTION_SPI1_MISO, GPIO_PIN_PA6, &ec); - // if (ec) { - // klogf("Unable to set pin PA6 (ec=%d)\n", ec); - // } gpio_enable_alternate_function( GPIO_ALTERNATE_FUNCTION_SPI1_MOSI, GPIO_PIN_PA7, &ec); if (ec) { - klogf("Unable to set pin PA7 (ec=%d)\n", ec); + panic("Unable to set pin PA7 (ec=%d)\n", ec); } gpio_enable_alternate_function( GPIO_ALTERNATE_FUNCTION_SPI1_NSS, GPIO_PIN_PA4, &ec); if (ec) { - klogf("Unable to set pin PA4 (ec=%d)\n", ec); + panic("Unable to set pin PA4 (ec=%d)\n", ec); } gpio_enable_alternate_function( GPIO_ALTERNATE_FUNCTION_SPI1_SCK, GPIO_PIN_PA5, &ec); if (ec) { - klogf("Unable to set pin PA5 (ec=%d)\n", ec); + panic("Unable to set pin PA5 (ec=%d)\n", ec); } - /* Set the countdown to start from 10,000,0000. */ - SCB.strv_r = 1000000; - - /* Enable interrupts. */ - regset(SCB.stcs_r, scb_tickint, 1); - - /* Start the systick. */ - regset(SCB.stcs_r, scb_enable, 1); - regset(RCC.apb2en_r, rcc_spi1en, 1); - enable_interrupt(IRQ_SPI1); - uint32_t reg = 0; regset(reg, spi_ldma_tx, 0); regset(reg, spi_ldma_rx, 0); @@ -210,7 +59,7 @@ int main() regset(reg, spi_frf, 0); regset(reg, spi_nssp, 0); regset(reg, spi_ssoe, 0); - regset(reg, spi_txdmaen, 1); + regset(reg, spi_txdmaen, 0); regset(reg, spi_rxdmaen, 0); SPI1.c_r2 = reg; @@ -229,13 +78,112 @@ int main() regset(reg, spi_cpol, 0); regset(reg, spi_cpha, 0); SPI1.c_r1 = reg; +} + +static uint8_t* compiled; +static size_t compiled_len; - klogf("Initiate xfer\n"); - dma_mem2p_initiate_transfer(dma_chan, dataptr, size * 9); - klogf("Post\n"); +extern uint8_t sintable[256]; - // for (;;); +static void spi_write(uint8_t byte) +{ + while (!regget(SPI1.s_r, spi_txe)) + ; + SPI1.d_r = byte; + asm volatile("nop"); } +static void write_rgb(uint8_t red, uint8_t green, uint8_t blue) +{ +#undef BIT +#define BIT(b, n) (!!((b) & (1 << (n)))) + spi_write( + (1 << 7) | (BIT(green, 7) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(green, 6) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(green, 5) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(green, 4) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(green, 3) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(green, 2) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(green, 1) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(green, 0) << 2) | (0 << 1) | (0 << 0)); + + spi_write( + (1 << 7) | (BIT(red, 7) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(red, 6) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(red, 5) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(red, 4) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(red, 3) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(red, 2) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(red, 1) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(red, 0) << 2) | (0 << 1) | (0 << 0)); + + spi_write( + (1 << 7) | (BIT(blue, 7) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(blue, 6) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(blue, 5) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(blue, 4) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(blue, 3) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(blue, 2) << 2) | (0 << 1) | (0 << 0)); + spi_write( + (1 << 7) | (BIT(blue, 1) << 6) | (0 << 5) | (0 << 4) | (1 << 3) | + (BIT(blue, 0) << 2) | (0 << 1) | (0 << 0)); +} + +void latch() +{ + for (int i = 0; i < 20; ++i) { + spi_write(0); + } +} + +/* Main function. This gets executed from the interrupt vector defined above. */ +int main() +{ + gpio_reserved_pin_t sysled = get_sysled(); + klogf("Start\n"); + klogf("sintable: %p\n", sintable); + klogf("sintable[5]: %d\n", sintable[5]); + +#define SIZE 16 + rgb_t rgb[SIZE]; + for (int i = 0; i < SIZE; ++i) { + rgb[i].g = 0x18; + rgb[i].r = 0x80; + rgb[i].b = 0x18; + } + + uint8_t red = 0x30; + uint8_t green = 0x30; + uint8_t blue = 0x00; + + // compiled = ws2812b_compile_rgb(rgb, SIZE); + // compiled_len = SIZE * 9; + + configure_spi1(); + + set_gpio_pin_high(sysled); + for (int i = 0; i < 100; ++ i) { + write_rgb(0, 0, 0); + } + + latch(); + + for (int i = 0; i < 256; ++i) { + write_rgb(red, byte_sin((i * 16) & 0xff) / 2, blue); + } + set_gpio_pin_low(sysled); + + for (;;) { + spi_write(0); + } +} #endif |