aboutsummaryrefslogtreecommitdiff
path: root/src/kern
diff options
context:
space:
mode:
Diffstat (limited to 'src/kern')
-rw-r--r--src/kern/main.c219
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