aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2021-10-26 00:10:06 -0600
committerJosh Rahm <joshuarahm@gmail.com>2021-10-26 00:10:06 -0600
commitf9b12f748b557994b958115c04fd1591b322248e (patch)
tree7d80680edadf5b0018944966af64f8773bfa8f1a /src
parentdbbe83bd8882fe18e26f6305a1f425145bfea8db (diff)
parent90eb3a0b79bfef67c70dc545b49c48928eea05f4 (diff)
downloadstm32l4-f9b12f748b557994b958115c04fd1591b322248e.tar.gz
stm32l4-f9b12f748b557994b958115c04fd1591b322248e.tar.bz2
stm32l4-f9b12f748b557994b958115c04fd1591b322248e.zip
Merge branch 'christmas' into HEAD
Diffstat (limited to 'src')
-rw-r--r--src/drv/ir/control.c43
-rw-r--r--src/drv/ir/ir.c160
-rw-r--r--src/drv/ws2812B/ws2812b.c26
-rw-r--r--src/kern/gpio/gpio_manager.c9
-rw-r--r--src/kern/lib.c5
-rw-r--r--src/kern/main.c236
-rw-r--r--src/kern/mem.c17
-rw-r--r--src/kern/stdlibrepl.c36
-rw-r--r--src/shared/math.c38
9 files changed, 477 insertions, 93 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;
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/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 fab2eb9..cdaa2b1 100644
--- a/src/kern/main.c
+++ b/src/kern/main.c
@@ -1,11 +1,19 @@
+#include <assert.h>
+
#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"
@@ -19,8 +27,23 @@
#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");
@@ -49,100 +72,189 @@ void configure_gpio()
}
}
-static uint8_t* compiled;
-static size_t compiled_len;
+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;
+ }
-extern uint8_t sintable[256];
+ /* Add a little white flair that comes around every once in a while. */
-static uint32_t time;
+ 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,
+ };
-static void on_systick(void* nil)
+ 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)
{
- ++time;
+ (*v)++;
}
-#define min(a, b) (a) < (b) ? (a) : (b)
+void decrement_it_u8(uint32_t unused, uint8_t* v)
+{
+ (*v)--;
+}
-static uint8_t amp(uint8_t in)
+void timetick_up(uint32_t unused, void* nil)
{
- uint32_t out = in;
+ state.timetick += 5;
+}
- for (int i = 0; i < 20; ++i) {
- out = (out * in) / 256;
+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;
+}
- return min(out, 255);
+static void set_red()
+{
+ state.n_red += 50;
+ state.n_red %= 250;
}
-static uint32_t bytescale(uint32_t n, uint32_t sc)
+static void reset_state()
{
- return n * sc / 255;
+ 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");
- gpio_reserved_pin_t sysled = get_sysled();
+ klogf("Entering Main\n");
systick_add_callback(on_systick, NULL);
- enable_systick(1000);
+ 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;
- ws2812b_t* drv = ws2812b_new(SPI_SELECT_SPI1, &ec);
+ state.drv = ws2812b_new(SPI_SELECT_SPI1, &ec);
- if (ec || !drv) {
+ if (ec || !state.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;
- }
-
- uint32_t red = 0x40;
- uint32_t green = 0x40;
- uint32_t brightness = 255;
+ reset_state();
- for (int i = 0; i < 100; ++i) {
- ws2812b_write_rgb_sync(drv, 0, 0, 0);
+ 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(drv);
+ ws2812b_latch(state.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 (!do_redraw)
+ // ;
+ // do_redraw = 0;
+ if (!state.sleep) redraw();
}
}
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
diff --git a/src/kern/stdlibrepl.c b/src/kern/stdlibrepl.c
index 588191b..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.
@@ -15,14 +16,43 @@ 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;
+}
+
+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
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);
+}