#include #include "arch.h" #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" #include "arch/stm32l4xxx/peripherals/dma.h" #include "arch/stm32l4xxx/peripherals/exti.h" #include "arch/stm32l4xxx/peripherals/irq.h" #include "arch/stm32l4xxx/peripherals/rcc.h" #include "arch/stm32l4xxx/peripherals/spi.h" #include "arch/stm32l4xxx/peripherals/syscfg.h" #include "arch/stm32l4xxx/peripherals/system.h" #include "arch/stm32l4xxx/peripherals/tim.h" #include "drv/ir/control.h" #include "drv/ir/ir.h" #include "drv/ir/lg_remote_codes.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/priv.h" #include "kern/spi/spi_manager.h" #include "kern/systick/systick_manager.h" #include "shared/math.h" #include "user/syscall.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() { panic("Hard fault encountered!\n"); } #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("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, 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, 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, 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 (;;) { // while (!do_redraw) // ; // do_redraw = 0; if (!state.sleep) redraw(); } } #endif