diff options
-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 |