From de81911ef4c15a9518acf32f61ad2d7d0e2f156f Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sat, 5 Dec 2020 01:53:33 -0700 Subject: Got a very basic external interrupt to work. --- src/kern/gpio/gpio_manager.c | 9 +++++ src/kern/main.c | 86 ++++++++++++++++---------------------------- 2 files changed, 40 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/kern/gpio/gpio_manager.c b/src/kern/gpio/gpio_manager.c index 749ae79..ea720e9 100644 --- a/src/kern/gpio/gpio_manager.c +++ b/src/kern/gpio/gpio_manager.c @@ -388,3 +388,12 @@ void set_gpio_pin_low(gpio_reserved_pin_t pin) regset(portcfg->od_r, (1 << off), 0); } + +bool get_gpio_pin_input_state(gpio_reserved_pin_t pin) +{ + int off; + gpio_port_config_t* portcfg; + get_gpio_pin_port_off(pin.v_, &portcfg, &off); + + return !!regget(portcfg->id_r, (1 << off)); +} diff --git a/src/kern/main.c b/src/kern/main.c index fab2eb9..2b97197 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -2,9 +2,11 @@ #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 "drv/ws2812B/ws2812b.h" #include "kern/delay.h" @@ -82,68 +84,42 @@ static uint32_t bytescale(uint32_t n, uint32_t sc) /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - klogf("Entering main\n"); - gpio_reserved_pin_t sysled = get_sysled(); + regset(RCC.apb2en_r, rcc_syscfgen, 1); - systick_add_callback(on_systick, NULL); - enable_systick(1000); - configure_gpio(); + klogf("Entering main\n"); int ec; - ws2812b_t* drv = ws2812b_new(SPI_SELECT_SPI1, &ec); - - if (ec || !drv) { - panic("Unable to create WS2812b driver :( (%d)\n", ec); - } - -#define SIZE 256 - rgb_t rgb[SIZE]; - for (int i = 0; i < SIZE; ++i) { - rgb[i].g = 0xff; - rgb[i].r = 0xff; - rgb[i].b = 0xff; - } + gpio_reserved_pin_t sysled = get_sysled(); - uint32_t red = 0x40; - uint32_t green = 0x40; - uint32_t brightness = 255; + gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_INPUT; + opts.pull_dir = GPIO_PULL_DIR_NONE; + gpio_reserved_pin_t pb6 = reserve_gpio_pin(GPIO_PIN_PB6, &opts, &ec); - for (int i = 0; i < 100; ++i) { - ws2812b_write_rgb_sync(drv, 0, 0, 0); + if (ec) { + panic("Unable to reserve GPIO pin ec=%d\n", ec); } - ws2812b_latch(drv); - - for (;;) { - set_gpio_pin_high(sysled); - ws2812b_latch(drv); - - int i; - for (i = 0; i < SIZE; ++i) { - red = byte_sin(time / 1000 + i * 4); - green = 255 - red; - - brightness = 3 * byte_sin(time / 5000) / 4 + 63; - - /* Add a little white flair that comes around every once in a while. */ - uint32_t white = time / 137 + i * 4; - if ((white / 256) % 8 == 0) { - white = amp(byte_sin(white)); - } else { - white = 0; - } - - ws2812b_write_rgb_sync( - drv, - bytescale(min(red + white, 255), brightness), - bytescale(min(green + white, 255), brightness), - bytescale(white, brightness)); - } - - set_gpio_pin_low(sysled); - - ws2812b_latch(drv); - } + // while (1) { + // if (get_gpio_pin_input_state(pb6)) { + // set_gpio_pin_high(sysled); + // } else { + // set_gpio_pin_low(sysled); + // } + // // klogf("GPIO is set? %d\n", get_gpio_pin_input_state(pb6)); + // } + + regset(SYSCFG.extic_r2, syscfg_exti6, 1 /* Port B. */); + regset(EXTI.im_r1, exti_im_n(6), 1); /* Enable the EXTI interrupt. */ + regset(EXTI.fts_r1, exti_ft_n(6), 1); /* Enable for falling edge. */ + regset(EXTI.rts_r1, exti_rt_n(6), 1); /* Enable for rising edge. */ + enable_interrupt(IRQ_EXTI9_5); + enable_interrupt(IRQ_EXTI0_IRQ); + enable_interrupt(IRQ_EXTI1_IRQ); + enable_interrupt(IRQ_EXTI2_IRQ); + enable_interrupt(IRQ_EXTI3_IRQ); + enable_interrupt(IRQ_EXTI4_IRQ); + + for(;;); } #endif -- cgit From d29ea8d7fb8cc6f7c3dda1cbca6266908acd4291 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sat, 5 Dec 2020 16:25:27 -0700 Subject: Add remove ability to linked list. --- src/kern/stdlibrepl.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/kern/stdlibrepl.c b/src/kern/stdlibrepl.c index 588191b..38b8477 100644 --- a/src/kern/stdlibrepl.c +++ b/src/kern/stdlibrepl.c @@ -15,14 +15,37 @@ size_t strlen(char* ch) #ifdef ARCH_STM32L4 -void memcpy(void* dest, void* src, size_t size) +void* memcpy(void* dest, const void* src, size_t size) { uint8_t* dest_ = dest; - uint8_t* src_ = src; + const uint8_t* src_ = src; - while(size --) { + while (size--) { *(dest_++) = *(src_++); } + + return dest; +} + +int memcmp(const void* s1_, const void* s2_, size_t size) +{ + const uint8_t* s1 = s1_; + const uint8_t* s2 = s2_; + + while (size--) { + if (*s1 != *s2) { + if (*s1 > *s2) { + return 1; + } else { + return -1; + } + } + + ++s1; + ++s2; + } + + return 0; } #endif -- cgit From 1710871aa1958c2cac38e4b372964ef22032ed4a Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Sun, 6 Dec 2020 02:00:43 -0700 Subject: Added header files implementing a basic AVL tree and Map based off it. These headers take inspiration from the linked list and array list headers as a way to provide primitive templates in C. This time they implement an AVL tree and Map template (which uses the AVL tree). Included are relatively robust tests, though they could be improved. --- src/kern/mem.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/kern/mem.c b/src/kern/mem.c index aa221ff..d7f7dc3 100644 --- a/src/kern/mem.c +++ b/src/kern/mem.c @@ -50,7 +50,7 @@ typedef uint64_t ptrint_t; typedef uint32_t ptrint_t; #endif -#define CANARY ((uint32_t) 0xdeadbeee) +#define CANARY ((uint32_t)0xdeadbeee) #define kalloc_node_in_use(node) ((node)->used_and_canary & 1) #define kalloc_node_get_canary(node) ((node)->used_and_canary & (~1)) #define WORD_SIZE (sizeof(uint32_t)) @@ -153,7 +153,7 @@ static void coalesce(kalloc_node_t* cur) /* Find the next used block. */ cur = orig; - while (!kalloc_node_in_use(cur) && !kalloc_node_out_of_range(cur)) { + while (!kalloc_node_out_of_range(cur) && !kalloc_node_in_use(cur)) { cur = kalloc_node_next(cur); } @@ -212,6 +212,8 @@ void debug_print_blocks() printf("---------------------------\n"); kalloc_node_t* cur = kalloc_node_at_off(0); + int total_words = 0; + int total_blocks = 0; while (!kalloc_node_out_of_range(cur)) { printf( "header (%04x)@%p {used=%d, size=%5d, prev=%04x, canary=%04x}\n", @@ -221,8 +223,13 @@ void debug_print_blocks() cur->size_words, cur->prev, kalloc_node_get_canary(cur)); + total_words += cur->size_words; + total_blocks ++; cur = kalloc_node_next(cur); } + + printf("Total words allocated: %d\n", total_words); + printf("Total blocks allocated: %d\n", total_blocks); } /* Tests that we can walk up and down the allocated blocks and that they @@ -305,4 +312,10 @@ int debug_kalloc_assert_consistency(char* error, size_t len) return 1; } +int debug_is_heap_empty() +{ + return (void*)((uint8_t*)kalloc_start + kalloc_start->size_words * sizeof(uint32_t) + sizeof(kalloc_node_t)) == + (void*)&HEAP_STOP; +} + #endif -- cgit From a5923b21e48fcfe660c1e7d586fe0c6a5b79e421 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 9 Dec 2020 20:29:31 -0700 Subject: Got a basic timer to work. --- src/kern/main.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src') diff --git a/src/kern/main.c b/src/kern/main.c index 2b97197..082d450 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -2,6 +2,7 @@ #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" #include "arch/stm32l4xxx/peripherals/dma.h" +#include "arch/stm32l4xxx/peripherals/tim.h" #include "arch/stm32l4xxx/peripherals/exti.h" #include "arch/stm32l4xxx/peripherals/irq.h" #include "arch/stm32l4xxx/peripherals/rcc.h" @@ -23,6 +24,15 @@ #include "kern/systick/systick_manager.h" #include "user/syscall.h" +void on_exti9_5() +{ + klogf("Exit Interrupt!\n"); + klogf("Pending Reg_again: %p\n", EXTI.p_r1); + klogf("Write: %p\n", (1 << 6)); + EXTI.p_r1 |= 1 << 6; + klogf("Pending Reg_again: %p\n", EXTI.p_r1); +} + void on_hard_fault() { panic("Hard fault encountered!\n"); @@ -81,6 +91,15 @@ static uint32_t bytescale(uint32_t n, uint32_t sc) return n * sc / 255; } +void on_tim2() +{ + if (regget(TIM2.s_r, tim_uif)) { + regset(TIM2.s_r, tim_uif, 0); + } + + klogf("Tim2 Update\n"); +} + /* Main function. This gets executed from the interrupt vector defined above. */ int main() { @@ -88,6 +107,21 @@ int main() klogf("Entering main\n"); + klogf("Enable ir\n"); + enable_interrupt(IRQ_TIM2); + klogf("Enable clock\n"); + regset(RCC.apb1en1_r, rcc_tim2en, 1); + klogf("psc\n"); + TIM2.psc = 39999; /* Counts every half millisecond. */ + klogf("ar_r\n"); + TIM2.ar_r = 1000; + klogf("die_r\n"); + regset(TIM2.die_r, tim_uie, 1); + klogf("eg_r\n"); + regset(TIM2.eg_r, tim_ug, 1); + klogf("c_r1\n"); + regset(TIM2.c_r1, tim_cen, 1); + int ec; gpio_reserved_pin_t sysled = get_sysled(); -- cgit From 5f1763ec87503527583cb1a7c6deb73604db0dfc Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Wed, 9 Dec 2020 23:15:14 -0700 Subject: Can read from the A/C remote control! --- src/drv/ir/control.c | 43 ++++++++++++++ src/drv/ir/ir.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/kern/lib.c | 5 ++ src/kern/main.c | 145 +++++++++------------------------------------ src/kern/stdlibrepl.c | 7 +++ 5 files changed, 242 insertions(+), 118 deletions(-) create mode 100644 src/drv/ir/control.c create mode 100644 src/drv/ir/ir.c (limited to 'src') diff --git a/src/drv/ir/control.c b/src/drv/ir/control.c new file mode 100644 index 0000000..6be2cf1 --- /dev/null +++ b/src/drv/ir/control.c @@ -0,0 +1,43 @@ +#include "drv/ir/control.h" + +#include "drv/ir/ir.h" +#include "shared/map.h" + +typedef struct { + void* closure; + void (*fn)(uint32_t code, void* closure); +} ir_code_listener_t; + +#define integer_cmp_(a, b) (a - b) +MAP_DECL(uint32_t, ir_code_listener_t); +MAP_IMPL(uint32_t, ir_code_listener_t, integer_cmp_, null_dtor); + +static map_t(uint32_t, ir_code_listener_t) * listeners; + +static void ir_callback(const ir_code_t* ir) +{ + uint32_t code; + if (ir_generic_decode(ir, &code)) { + ir_code_listener_t* l = + map_get(uint32_t, ir_code_listener_t)(listeners, code); + + if (l) { + l->fn(code, l->closure); + } + } +} + +void add_ir_code_callback_( + uint32_t code, void (*fn)(uint32_t, void*), void* closure) +{ + ir_code_listener_t l; + l.fn = fn; + l.closure = closure; + map_put(uint32_t, ir_code_listener_t)(listeners, code, l); +} + +void enable_ir_control() +{ + listeners = map_new(uint32_t, ir_code_listener_t)(); + add_ir_callback(ir_callback); +} diff --git a/src/drv/ir/ir.c b/src/drv/ir/ir.c new file mode 100644 index 0000000..c84417d --- /dev/null +++ b/src/drv/ir/ir.c @@ -0,0 +1,160 @@ +#include "drv/ir/ir.h" + +#include "arch/stm32l4xxx/peripherals/exti.h" +#include "arch/stm32l4xxx/peripherals/irq.h" +#include "arch/stm32l4xxx/peripherals/rcc.h" +#include "arch/stm32l4xxx/peripherals/syscfg.h" +#include "arch/stm32l4xxx/peripherals/tim.h" +#include "kern/gpio/gpio_manager.h" +#include "kern/mem.h" +#include "kern/log.h" +#include "kern/panic.h" +#include "shared/linked_list.h" + +typedef void (*ir_callback_t)(const ir_code_t*); + +LINKED_LIST_DECL(ir_callback_t); +LINKED_LIST_IMPL(ir_callback_t); + +static linked_list_t(ir_callback_t) callbacks; +static ir_code_t read_into; + +void on_exti9_5() +{ + EXTI.p_r1 |= 1 << 6; + /* The IR pin has been activated. */ + + if (read_into.n == 0) { + /* Starting fresh, start the timer. */ + regset(TIM2.c_r1, tim_cen, 1); + read_into.ts[read_into.n ++] = 0; + } else { + uint32_t ts = TIM2.cnt; + if (read_into.n < 64) { + read_into.ts[read_into.n++] = ts; + } + } +} + +typedef enum { + PARITY_LOW = 0, + PARITY_HIGH = 1 +} ir_parity_t; + +static ir_parity_t ir_discover_parity(const ir_code_t* code) +{ + uint32_t max_even = 0; + uint32_t min_even = (uint32_t) -1; + + uint32_t max_odd = 0; + uint32_t min_odd = (uint32_t) -1; + + for (int i = 3; i < code->n; ++ i) { + uint32_t n = code->ts[i] - code->ts[i-1]; + if (i % 2 == 0) { + if (n < min_even) { + min_even = n; + } else if (n > max_even) { + max_even = n; + } + } else { + if (n < min_odd) { + min_odd = n; + } else if (n > max_odd) { + max_odd = n; + } + } + } + + if (max_even - min_even > max_odd - min_odd) { + return PARITY_LOW; + } else { + return PARITY_HIGH; + } +} + +int ir_generic_decode( + const ir_code_t* code, uint32_t* out_) +{ + if (code->n < 5) { + return 0; + } + + uint32_t min = (uint32_t) -1; + uint32_t max = 0; + + uint32_t start = 4 + ir_discover_parity(code); + + for (int i = start; i < code->n; i += 2) { + uint32_t n = code->ts[i] - code->ts[i-1]; + + if (n > max) { + max = n; + } else if (n < min) { + min = n; + } + } + + uint32_t mid = (max + min) / 2; + + uint32_t out = 0; + uint32_t mask = 0x80000000; + + for (int i = start; i < code->n; i += 2) { + if ((code->ts[i] - code->ts[i-1]) >= mid) { + out |= mask; + } + mask >>= 1; + } + + *out_ = out; + return 1; +} + +void on_tim2() +{ + if (regget(TIM2.s_r, tim_uif)) { + regset(TIM2.s_r, tim_uif, 0); + } + + /* The timer has run out. */ + linked_list_foreach(callbacks, cb) { cb(&read_into); } + + read_into.n = 0; +} + +void add_ir_callback(ir_callback_t callback) +{ + linked_list_push_front(ir_callback_t)(&callbacks, callback); +} + +void ir_begin_listen() +{ + int ec; + + gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_INPUT; + opts.pull_dir = GPIO_PULL_DIR_NONE; + gpio_reserved_pin_t pb6 = reserve_gpio_pin(GPIO_PIN_PB6, &opts, &ec); + + regset(RCC.apb1en1_r, rcc_tim2en, 1); + regset(RCC.apb2en_r, rcc_syscfgen, 1); + + enable_interrupt(IRQ_TIM2); + enable_interrupt(IRQ_EXTI9_5); + + /* Configure the timer. */ + TIM2.psc = 80; /* Counts every microsecond. */ + TIM2.ar_r = 50000; /* Stop after 50ms. */ + regset(TIM2.die_r, tim_uie, 1); /* Enable interrupts. */ + regset(TIM2.c_r1, tim_opm, 1); /* Set one-pulse-mode. */ + + /* Configure the external interrupts. */ + regset(SYSCFG.extic_r2, syscfg_exti6, 1 /* Port B. */); + regset(EXTI.im_r1, exti_im_n(6), 1); /* Enable the EXTI interrupt. */ + regset(EXTI.fts_r1, exti_ft_n(6), 1); /* Enable for falling edge. */ + regset(EXTI.rts_r1, exti_rt_n(6), 1); /* Enable for rising edge. */ + + if (ec) { + panic("Unable to reserve GPIO pin ec=%d\n", ec); + } +} diff --git a/src/kern/lib.c b/src/kern/lib.c index 24e1658..e0d3e23 100644 --- a/src/kern/lib.c +++ b/src/kern/lib.c @@ -37,6 +37,11 @@ void decimalify(int v, char* into) *into = 0; return; } else { + if (v < 0) { + v = -v; + *(into++) = '-'; + } + while (v > 0) { *(into++) = 0x30 + (v % 10); v /= 10; diff --git a/src/kern/main.c b/src/kern/main.c index 082d450..208f5d9 100644 --- a/src/kern/main.c +++ b/src/kern/main.c @@ -2,13 +2,16 @@ #include "arch/arm/cortex-m4/mpu.h" #include "arch/stm32l4xxx/peripherals/clock.h" #include "arch/stm32l4xxx/peripherals/dma.h" -#include "arch/stm32l4xxx/peripherals/tim.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" @@ -23,15 +26,7 @@ #include "kern/spi/spi_manager.h" #include "kern/systick/systick_manager.h" #include "user/syscall.h" - -void on_exti9_5() -{ - klogf("Exit Interrupt!\n"); - klogf("Pending Reg_again: %p\n", EXTI.p_r1); - klogf("Write: %p\n", (1 << 6)); - EXTI.p_r1 |= 1 << 6; - klogf("Pending Reg_again: %p\n", EXTI.p_r1); -} +#include void on_hard_fault() { @@ -40,120 +35,34 @@ void on_hard_fault() #ifdef ARCH_STM32L4 -void configure_gpio() +void printit(uint32_t code, const char* str) { - 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); - } -} - -static uint8_t* compiled; -static size_t compiled_len; - -extern uint8_t sintable[256]; - -static uint32_t time; - -static void on_systick(void* nil) -{ - ++time; -} - -#define min(a, b) (a) < (b) ? (a) : (b) - -static uint8_t amp(uint8_t in) -{ - uint32_t out = in; - - for (int i = 0; i < 20; ++i) { - out = (out * in) / 256; - } - - return min(out, 255); -} - -static uint32_t bytescale(uint32_t n, uint32_t sc) -{ - return n * sc / 255; -} - -void on_tim2() -{ - if (regget(TIM2.s_r, tim_uif)) { - regset(TIM2.s_r, tim_uif, 0); - } - - klogf("Tim2 Update\n"); + (void)code; + klogf("%s\n", str); } /* Main function. This gets executed from the interrupt vector defined above. */ int main() { - regset(RCC.apb2en_r, rcc_syscfgen, 1); - - klogf("Entering main\n"); - - klogf("Enable ir\n"); - enable_interrupt(IRQ_TIM2); - klogf("Enable clock\n"); - regset(RCC.apb1en1_r, rcc_tim2en, 1); - klogf("psc\n"); - TIM2.psc = 39999; /* Counts every half millisecond. */ - klogf("ar_r\n"); - TIM2.ar_r = 1000; - klogf("die_r\n"); - regset(TIM2.die_r, tim_uie, 1); - klogf("eg_r\n"); - regset(TIM2.eg_r, tim_ug, 1); - klogf("c_r1\n"); - regset(TIM2.c_r1, tim_cen, 1); - - int ec; - gpio_reserved_pin_t sysled = get_sysled(); - - gpio_pin_opts_t opts = DEFAULT_GPIO_OPTS_INPUT; - opts.pull_dir = GPIO_PULL_DIR_NONE; - gpio_reserved_pin_t pb6 = reserve_gpio_pin(GPIO_PIN_PB6, &opts, &ec); - - if (ec) { - panic("Unable to reserve GPIO pin ec=%d\n", ec); - } - - // while (1) { - // if (get_gpio_pin_input_state(pb6)) { - // set_gpio_pin_high(sysled); - // } else { - // set_gpio_pin_low(sysled); - // } - // // klogf("GPIO is set? %d\n", get_gpio_pin_input_state(pb6)); - // } - - regset(SYSCFG.extic_r2, syscfg_exti6, 1 /* Port B. */); - regset(EXTI.im_r1, exti_im_n(6), 1); /* Enable the EXTI interrupt. */ - regset(EXTI.fts_r1, exti_ft_n(6), 1); /* Enable for falling edge. */ - regset(EXTI.rts_r1, exti_rt_n(6), 1); /* Enable for rising edge. */ - enable_interrupt(IRQ_EXTI9_5); - enable_interrupt(IRQ_EXTI0_IRQ); - enable_interrupt(IRQ_EXTI1_IRQ); - enable_interrupt(IRQ_EXTI2_IRQ); - enable_interrupt(IRQ_EXTI3_IRQ); - enable_interrupt(IRQ_EXTI4_IRQ); - - for(;;); + klogf("Ir begin listening\n"); + 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_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_UNITS, printit, "RC_UNITS"); + add_ir_code_callback(RC_TIMER, printit, "RC_TIMER"); + add_ir_code_callback(RC_POWER, printit, "RC_POWER"); + + for (;;) + ; } #endif diff --git a/src/kern/stdlibrepl.c b/src/kern/stdlibrepl.c index 38b8477..676b820 100644 --- a/src/kern/stdlibrepl.c +++ b/src/kern/stdlibrepl.c @@ -1,4 +1,5 @@ #include "arch.h" +#include "kern/panic.h" /* * Replacement for common stdlib functions that don't exist * on the ARM bare-metal compilation environment. @@ -48,4 +49,10 @@ int memcmp(const void* s1_, const void* s2_, size_t size) return 0; } +void __assert_func( + const char* file, int line, const char* func, const char* failedexpr) +{ + panic("Assertion failed: %s:%d in %s at %s\n", file, line, func, failedexpr); +} + #endif -- cgit From 90eb3a0b79bfef67c70dc545b49c48928eea05f4 Mon Sep 17 00:00:00 2001 From: Josh Rahm Date: Mon, 27 Sep 2021 22:56:46 -0600 Subject: Completed ws2812b 2020 Christmas Lights. --- src/drv/ws2812B/ws2812b.c | 26 ------ src/kern/main.c | 219 +++++++++++++++++++++++++++++++++++++++++++--- src/shared/math.c | 38 ++++++++ 3 files changed, 244 insertions(+), 39 deletions(-) create mode 100644 src/shared/math.c (limited to 'src') 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 + #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 + +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); +} -- cgit