diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2021-10-26 00:10:06 -0600 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2021-10-26 00:10:06 -0600 |
commit | f9b12f748b557994b958115c04fd1591b322248e (patch) | |
tree | 7d80680edadf5b0018944966af64f8773bfa8f1a /src | |
parent | dbbe83bd8882fe18e26f6305a1f425145bfea8db (diff) | |
parent | 90eb3a0b79bfef67c70dc545b49c48928eea05f4 (diff) | |
download | stm32l4-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.c | 43 | ||||
-rw-r--r-- | src/drv/ir/ir.c | 160 | ||||
-rw-r--r-- | src/drv/ws2812B/ws2812b.c | 26 | ||||
-rw-r--r-- | src/kern/gpio/gpio_manager.c | 9 | ||||
-rw-r--r-- | src/kern/lib.c | 5 | ||||
-rw-r--r-- | src/kern/main.c | 236 | ||||
-rw-r--r-- | src/kern/mem.c | 17 | ||||
-rw-r--r-- | src/kern/stdlibrepl.c | 36 | ||||
-rw-r--r-- | src/shared/math.c | 38 |
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); +} |