aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2021-09-27 22:56:46 -0600
committerJosh Rahm <joshuarahm@gmail.com>2021-09-27 22:56:46 -0600
commit90eb3a0b79bfef67c70dc545b49c48928eea05f4 (patch)
tree66718a17063ce4fa5c32c4a8ac094d09f7fab6de
parent5f1763ec87503527583cb1a7c6deb73604db0dfc (diff)
downloadstm32l4-90eb3a0b79bfef67c70dc545b49c48928eea05f4.tar.gz
stm32l4-90eb3a0b79bfef67c70dc545b49c48928eea05f4.tar.bz2
stm32l4-90eb3a0b79bfef67c70dc545b49c48928eea05f4.zip
Completed ws2812b 2020 Christmas Lights.ir_leds
-rw-r--r--include/drv/ws2812B/ws2812b.h3
-rw-r--r--include/kern/exti/exti_manager.h32
-rw-r--r--include/shared/avl_tree.h.gchbin0 -> 11451 bytes
-rw-r--r--include/shared/math.h19
-rw-r--r--src/drv/ws2812B/ws2812b.c26
-rw-r--r--src/kern/main.c219
-rw-r--r--src/shared/math.c38
-rw-r--r--tests/test_mpu.c27
8 files changed, 322 insertions, 42 deletions
diff --git a/include/drv/ws2812B/ws2812b.h b/include/drv/ws2812B/ws2812b.h
index 3189907..d7137a1 100644
--- a/include/drv/ws2812B/ws2812b.h
+++ b/include/drv/ws2812B/ws2812b.h
@@ -30,7 +30,4 @@ void ws2812b_write_rgb_arr_sync(ws2812b_t* drv, rgb_t* arr, size_t arr_len);
void ws2812b_delete(ws2812b_t* drv);
-/* Returns round(sin(2πn / 256) * 127.5 + 127.5). */
-uint8_t byte_sin(uint8_t n);
-
#endif /* WS2812B_H_ */
diff --git a/include/kern/exti/exti_manager.h b/include/kern/exti/exti_manager.h
new file mode 100644
index 0000000..aa39b4f
--- /dev/null
+++ b/include/kern/exti/exti_manager.h
@@ -0,0 +1,32 @@
+#ifndef _KERN_EXTI_EXTI_MANAGER_H_
+#define _KERN_EXTI_EXTI_MANAGER_H_
+
+#include "kern/common.h"
+#include "kern/gpio/gpio_manager.h"
+#include "shared/linked_list.h"
+
+#define EXTI_ERROR_ALREADY_IN_USE 1
+
+struct EXTI_HANDLE;
+
+
+typedef struct {
+ void (*fn)(struct EXTI_HANDLE, void*);
+ void* closure;
+} exti_callback_t;
+
+LINKED_LIST_DECL(exti_callback_t);
+typedef struct EXTI_HANDLE {
+ uint8_t id;
+ linked_list_t(exti_callback_t)* callbacks;
+} exti_handle_t;
+
+exti_handle_t* enable_exti_for_gpio(gpio_pin_t gpio_pin, int* ec);
+
+exti_handle_t* exti_add_callback(exti_handle_t*, exti_callback_t* callback);
+
+gpio_pin_t exti_gpio_pin(exti_handle_t* handle);
+
+
+
+#endif /* _KERN_EXTI_EXTI_MANAGER_H_ */
diff --git a/include/shared/avl_tree.h.gch b/include/shared/avl_tree.h.gch
new file mode 100644
index 0000000..78fc043
--- /dev/null
+++ b/include/shared/avl_tree.h.gch
Binary files differ
diff --git a/include/shared/math.h b/include/shared/math.h
new file mode 100644
index 0000000..6aec0e7
--- /dev/null
+++ b/include/shared/math.h
@@ -0,0 +1,19 @@
+#ifndef _SHARED_MATH_H_
+#define _SHARED_MATH_H_
+
+#include "kern/common.h"
+
+/* Returns round(sin(2πn / 256) * 127.5 + 127.5). */
+uint8_t byte_sin(uint8_t n);
+
+static inline uint8_t byte_scale(uint8_t n, uint8_t sc) {
+ return n * sc / 255;
+}
+
+#define min(a, b) (a) < (b) ? (a) : (b)
+#define max(a, b) (a) > (b) ? (a) : (b)
+
+/* returns (in / 256)^n * 256. */
+uint8_t amp(uint8_t in, uint8_t n);
+
+#endif /* _SHARED_MATH_H_ */
diff --git a/src/drv/ws2812B/ws2812b.c b/src/drv/ws2812B/ws2812b.c
index 3cf3570..aeb3784 100644
--- a/src/drv/ws2812B/ws2812b.c
+++ b/src/drv/ws2812B/ws2812b.c
@@ -4,32 +4,6 @@
#include "kern/mem.h"
#include "kern/panic.h"
-uint8_t sintable[256] = {
- 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170,
- 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211,
- 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240,
- 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254,
- 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251,
- 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232,
- 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198,
- 196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155,
- 152, 149, 146, 143, 140, 137, 134, 131, 128, 124, 121, 118, 115, 112, 109,
- 106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65,
- 62, 59, 57, 54, 52, 49, 47, 44, 42, 40, 37, 35, 33, 31, 29,
- 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6,
- 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11,
- 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37,
- 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
- 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121,
- 124,
-};
-
-uint8_t byte_sin(uint8_t n)
-{
- return sintable[n];
-}
-
ws2812b_t* ws2812b_new(spi_select_t spi_select, int* ec)
{
spi_opts_t spi_opts = DEFAULT_SPI_OPTS;
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
diff --git a/src/shared/math.c b/src/shared/math.c
new file mode 100644
index 0000000..900cced
--- /dev/null
+++ b/src/shared/math.c
@@ -0,0 +1,38 @@
+#include "shared/math.h"
+
+uint8_t sintable[256] = {
+ 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170,
+ 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211,
+ 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240,
+ 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254,
+ 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251,
+ 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 238, 237, 235, 234, 232,
+ 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198,
+ 196, 193, 190, 188, 185, 182, 179, 176, 173, 170, 167, 165, 162, 158, 155,
+ 152, 149, 146, 143, 140, 137, 134, 131, 128, 124, 121, 118, 115, 112, 109,
+ 106, 103, 100, 97, 93, 90, 88, 85, 82, 79, 76, 73, 70, 67, 65,
+ 62, 59, 57, 54, 52, 49, 47, 44, 42, 40, 37, 35, 33, 31, 29,
+ 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11, 10, 9, 7, 6,
+ 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11,
+ 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37,
+ 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
+ 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121,
+ 124,
+};
+
+uint8_t byte_sin(uint8_t n)
+{
+ return sintable[n];
+}
+
+uint8_t amp(uint8_t in, uint8_t n)
+{
+ uint32_t out = in;
+
+ for (int i = 0; i < n; ++i) {
+ out = (out * in) / 256;
+ }
+
+ return min(out, 255);
+}
diff --git a/tests/test_mpu.c b/tests/test_mpu.c
new file mode 100644
index 0000000..551e079
--- /dev/null
+++ b/tests/test_mpu.c
@@ -0,0 +1,27 @@
+#include "test_harness.c"
+
+#include "arch/arm/cortex-m4/mpu.h"
+#include "kern/mpu/mpu_manager.h"
+
+TEST(mpu, smell)
+{
+ memory_region_opts_t memopts = { 0 };
+ memopts.region = (void*) 0;
+ memopts.bufferable = 0;
+ memopts.cacheable = 1;
+ memopts.sharable = 1;
+ memopts.tex = 0;
+ memopts.size = REGION_SIZE_4Gb;
+ memopts.perms = ACCESS_PERMS_FULL;
+ memopts.subregion_disable = 0;
+ memopts.executable = 1;
+ memopts.enable = 1;
+
+ mpu_configure_region(0, &memopts);
+ mpu_set_enabled(1);
+
+ ASSERT_EQ(MPU.rba_r, 1 << 4);
+ ASSERT_EQ(MPU.ras_r, 0x0306003F);
+
+ return 0;
+}