aboutsummaryrefslogtreecommitdiff
path: root/src/drv
diff options
context:
space:
mode:
Diffstat (limited to 'src/drv')
-rw-r--r--src/drv/ir/control.c43
-rw-r--r--src/drv/ir/ir.c160
-rw-r--r--src/drv/ws2812B/ws2812b.c26
3 files changed, 203 insertions, 26 deletions
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/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;