diff options
Diffstat (limited to 'src/kern')
-rw-r--r-- | src/kern/main.c | 219 |
1 files changed, 206 insertions, 13 deletions
diff --git a/src/kern/main.c b/src/kern/main.c index 208f5d9..cdaa2b1 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -1,3 +1,5 @@ +#include <assert.h> + #include "arch.h" #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" @@ -25,8 +27,22 @@ #include "kern/priv.h" #include "kern/spi/spi_manager.h" #include "kern/systick/systick_manager.h" +#include "shared/math.h" #include "user/syscall.h" -#include <assert.h> + +volatile struct { + uint32_t time; + signed int timetick; + ws2812b_t* drv; + uint8_t brightness; + uint8_t n_leds; + uint8_t off; + uint8_t n_snow; + uint8_t n_red; + bool sleep; + bool power; + bool cool; +} state; void on_hard_fault() { @@ -35,34 +51,211 @@ void on_hard_fault() #ifdef ARCH_STM32L4 +void configure_gpio() +{ + int ec = 0; + + gpio_enable_alternate_function( + GPIO_ALTERNATE_FUNCTION_SPI1_MOSI, GPIO_PIN_PA7, &ec); + if (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) { + 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) { + panic("Unable to set pin PA5 (ec=%d)\n", ec); + } +} + void printit(uint32_t code, const char* str) { (void)code; klogf("%s\n", str); } +volatile bool do_redraw; +static void on_systick() +{ + if (!state.sleep) state.time += state.timetick; +} + +void redraw() +{ + uint32_t red = 0, green = 0, blue = 0; + + for (int i = 0; i < state.n_leds; ++i) { + if (!state.power) { + ws2812b_write_rgb_sync(state.drv, 0, 0, 0); + continue; + } + + red = byte_scale(byte_sin(state.time / 1000 + i * 4), 255 - state.n_red) + + state.n_red; + green = 255 - red; + + if (state.cool) { + uint32_t tmp = green; + green = blue; + blue = tmp; + } + + /* Add a little white flair that comes around every once in a while. */ + + uint32_t whitesum = 0; + if (state.n_snow) { + uint32_t white[] = { + /* Parallax "snow" */ + state.time / 179 + i * 8, + state.time / 193 + i * 12, + state.time / 211 + i * 16, + (state.time) / 233 + i * 8, + // (state.time + 128) / 233 + i * 8, + }; + + for (int i = 0; i < sizeof(white) / sizeof(uint32_t); ++i) { + if ((white[i] / 256) % state.n_snow == 0) { + white[i] = amp(byte_sin(white[i]), 20); + } else { + white[i] = 0; + } + whitesum += white[i]; + } + } + + ws2812b_write_rgb_sync( + state.drv, + byte_scale(min(red + whitesum, 255), state.brightness), + byte_scale(min(green + whitesum, 255), state.brightness), + byte_scale(min(blue + whitesum, 255), state.brightness)); + } + + ws2812b_latch(state.drv); + + delay(100000); +} + +void increment_it_u8(uint32_t unused, uint8_t* v) +{ + (*v)++; +} + +void decrement_it_u8(uint32_t unused, uint8_t* v) +{ + (*v)--; +} + +void timetick_up(uint32_t unused, void* nil) +{ + state.timetick += 5; +} + +void timetick_down(uint32_t unused, void* nil) +{ + state.timetick -= 5; +} + +void toggle_brightness(uint32_t unused, void* nil) +{ + klogf("Toggle %d\n", state.brightness); + if (state.brightness == 255) { + state.brightness = 32; + } else { + state.brightness = 255; + } +} + +static void toggle_sleep(uint32_t unused, void* nil) +{ + state.sleep = !state.sleep; +} + +static void toggle_power(uint32_t unused, void* nil) +{ + state.power = !state.power; +} + +static void toggle_cool(uint32_t unused, void* nil) +{ + state.cool = !state.cool; +} + +static void set_snow() +{ + state.n_snow = (state.n_snow + 1) % 10; +} + +static void set_red() +{ + state.n_red += 50; + state.n_red %= 250; +} + +static void reset_state() +{ + ws2812b_t* tmp = state.drv; + memset((void*) &state, 0, sizeof(state)); + state.drv = tmp; + state.brightness = 255; + state.n_leds = 250; + state.off = 8; + state.timetick = 10; + state.power = 1; + state.n_snow = 2; +} + /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - klogf("Ir begin listening\n"); + klogf("Entering Main\n"); + + systick_add_callback(on_systick, NULL); + enable_systick(10000); + configure_gpio(); + ir_begin_listen(); enable_ir_control(); add_ir_code_callback(RC_HIGH, printit, "RC_HIGH"); - add_ir_code_callback(RC_TEMP_UP, printit, "RC_TEMP_UP"); - add_ir_code_callback(RC_DRY, printit, "RC_DRY"); + add_ir_code_callback(RC_TEMP_UP, timetick_up, NULL); + add_ir_code_callback(RC_DRY, set_red, NULL); add_ir_code_callback(RC_LOW, printit, "RC_LOW"); - add_ir_code_callback(RC_TEMP_DOWN, printit, "RC_TEMP_DOWN"); - add_ir_code_callback(RC_COOL, printit, "RC_COOL"); - add_ir_code_callback(RC_CONTINUOUS, printit, "RC_CONTINUOUS"); - add_ir_code_callback(RC_FAN, printit, "RC_FAN"); - add_ir_code_callback(RC_SLEEP, printit, "RC_SLEEP"); + add_ir_code_callback(RC_TEMP_DOWN, timetick_down, NULL); + add_ir_code_callback(RC_COOL, toggle_cool, NULL); + add_ir_code_callback(RC_CONTINUOUS, set_snow, "RC_CONTINUOUS"); + add_ir_code_callback(RC_FAN, toggle_brightness, NULL); + add_ir_code_callback(RC_SLEEP, toggle_sleep, NULL); add_ir_code_callback(RC_UNITS, printit, "RC_UNITS"); - add_ir_code_callback(RC_TIMER, printit, "RC_TIMER"); - add_ir_code_callback(RC_POWER, printit, "RC_POWER"); + add_ir_code_callback(RC_TIMER, reset_state, NULL); + add_ir_code_callback(RC_POWER, toggle_power, NULL); + + int ec; + state.drv = ws2812b_new(SPI_SELECT_SPI1, &ec); + + if (ec || !state.drv) { + panic("Unable to create WS2812b driver :( (%d)\n", ec); + } + + reset_state(); + + for (int i = 0; i < state.n_leds; ++i) { + /* Clear the LED strip. */ + disable_all_interrupts(); + ws2812b_write_rgb_sync(state.drv, 0, 0, 0); + enable_all_interrupts(); + } + ws2812b_latch(state.drv); - for (;;) - ; + for (;;) { + // while (!do_redraw) + // ; + // do_redraw = 0; + if (!state.sleep) redraw(); + } } #endif |