diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-12-07 13:58:46 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-12-07 13:58:46 -0700 |
commit | 546a5ccdba66dd8d8c19ce6d8486f46c84637cf2 (patch) | |
tree | 95b52da91414c1bfbad745c6b55617011012813e | |
parent | 9182b65ae2045c5087257751d30409deecf9520a (diff) | |
download | ch573-546a5ccdba66dd8d8c19ce6d8486f46c84637cf2.tar.gz ch573-546a5ccdba66dd8d8c19ce6d8486f46c84637cf2.tar.bz2 ch573-546a5ccdba66dd8d8c19ce6d8486f46c84637cf2.zip |
Add way to toggle the default pattern and a way to switch the pattern.
-rw-r--r-- | CMakeLists.txt | 15 | ||||
-rw-r--r-- | fdl/ch573/gpio.fdl | 16 | ||||
-rw-r--r-- | fdl/ch573/pfic.fdl | 6 | ||||
-rw-r--r-- | include/btsel.h | 19 | ||||
-rw-r--r-- | include/byte_math.h | 21 | ||||
-rw-r--r-- | include/sysled.h | 6 | ||||
-rw-r--r-- | include/systick.h | 9 | ||||
-rw-r--r-- | linker/ls.ld | 14 | ||||
-rw-r--r-- | src/btsel.c | 38 | ||||
-rw-r--r-- | src/main.c | 142 |
10 files changed, 209 insertions, 77 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d30b125..be194aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,17 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +if (NOT DEFINED PATTERN) + set(PATTERN "CandyCane") +endif() + +if (NOT DEFINED LED_BYTE_ORDER) + set(LED_BYTE_ORDER "GRB") +endif() + +set(PATTERN ${PATTERN} CACHE STRING "Define the default pattern to use.") +set(LED_BYTE_ORDER ${LED_BYTE_ORDER} CACHE STRING "The byte order to use. This should either be RGB or GRB") + set(TC_PREFIX riscv32-picolibc-elf-) # Set compiler and tools set(CMAKE_C_COMPILER "${TC_PREFIX}gcc" CACHE INTERNAL "C Compiler") @@ -23,6 +34,10 @@ endif() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) file(REAL_PATH "stubs/libgloss_stub.c" LIBGLOSS_STUB) +add_compile_definitions(DEFAULT_PATTERN=${PATTERN}) + +add_compile_definitions(LED_BYTE_ORDER=${LED_BYTE_ORDER}) + # Configure for Bare Metal. set(CMAKE_SYSTEM_NAME Generic) diff --git a/fdl/ch573/gpio.fdl b/fdl/ch573/gpio.fdl index bab481a..86ffaef 100644 --- a/fdl/ch573/gpio.fdl +++ b/fdl/ch573/gpio.fdl @@ -4,7 +4,7 @@ import "ch573/common.fdl"; package ch573.gpio { location sys_base = 0x4000_1000; - location gpio_base = 0x4000_1018; + location gpio_base = 0x4000_1000; location gpio_port_a_base = 0x4000_10A0; location gpio_port_b_base = 0x4000_10C0; @@ -64,7 +64,7 @@ package ch573.gpio { /** Gpio Type. */ type gpio_t : struct { /** Function pin remapping register. */ - reg pin_alternate(16) : struct { + reg pin_alternate(16) @0x18 : struct { /** * TMR0 function pin mapping selection bit: * @@ -201,22 +201,22 @@ package ch573.gpio { }; /** Port A interrupt enable register. */ - reg pa_interrupt_enable(16); + reg pa_interrupt_enable(16) @0x90; /** Port B interrupt enable register. */ - reg pb_interrupt_enable(16); + reg pb_interrupt_enable(16) @0x92; /** Port A interrupt mode configure register. */ - reg pa_interrupt_mode(16); + reg pa_interrupt_mode(16) @0x94; /** Port B interrupt mode configure register. */ - reg pb_interrupt_mode(16); + reg pb_interrupt_mode(16) @0x96; /** Port A interrupt flag register. */ - reg pa_interrupt_flag(16); + reg pa_interrupt_flag(16) @0x9c; /** Port B interrupt flag register. */ - reg pb_interrupt_flag(16); + reg pb_interrupt_flag(16) @0x9e; }; instance gpio at gpio_base : gpio_t; diff --git a/fdl/ch573/pfic.fdl b/fdl/ch573/pfic.fdl index 13ed54f..2323ad2 100644 --- a/fdl/ch573/pfic.fdl +++ b/fdl/ch573/pfic.fdl @@ -9,6 +9,12 @@ package ch573.pfic { bits interrupts : enum(32) { [[ c: unqualified ]] IRQ_SysTick = 0x1000, + + [[ c: unqualified ]] + IRQ_GpioA = 0x20000, + + [[ c: unqualified ]] + IRQ_GpioB = 0x40000, }; /** Type definition for the PFIC structure */ diff --git a/include/btsel.h b/include/btsel.h new file mode 100644 index 0000000..9d2c676 --- /dev/null +++ b/include/btsel.h @@ -0,0 +1,19 @@ +#pragma once + +// Header file for detecting bootsel button presses. + +#define PASTER(x, y) x##y +#define CONCAT(x, y) PASTER(x, y) + +typedef void (*bootsel_cb_t)(void); +#define On_BootSelPress() \ + static void __local_on_bootsel__(void); \ + __attribute__(( \ + __section__(".bootsel_callbacks"))) static volatile bootsel_cb_t \ + __bootsel__position = __local_on_bootsel__; \ + static void __local_on_bootsel__() + +#undef PASTER +#undef CONCAT + +void enable_bootsel_button(void); diff --git a/include/byte_math.h b/include/byte_math.h index 79f93b8..9be4b67 100644 --- a/include/byte_math.h +++ b/include/byte_math.h @@ -13,3 +13,24 @@ static inline uint8_t byte_sin(uint8_t n) } uint8_t calc_w(uint8_t n); + +static inline uint8_t byte_scale(uint8_t v, uint8_t scale) +{ + uint16_t acc = v; + return (acc * scale) >> 8; +} + +static inline uint8_t clip(int x) +{ + if (x > 240) { + return 240; + } + + if (x < 0) { + return 0; + } + + return (uint8_t)x; +} + +#define AS_BYTE(n) ((n) * 256) diff --git a/include/sysled.h b/include/sysled.h index b1a21c1..fea8f54 100644 --- a/include/sysled.h +++ b/include/sysled.h @@ -6,12 +6,12 @@ static inline void enable_sysled() { - CH573_GPIO__GPIO_PORT_T_INTF.dir.set(ch573_gpio__gpio_port_b, DIR_OUT, 10); - CH573_GPIO__GPIO_PORT_T_INTF.pd_drv.set(ch573_gpio__gpio_port_b, 1, 10); + CH573_GPIO__GPIO_PORT_T_INTF.dir.set(ch573_gpio__gpio_port_a, DIR_OUT, 11); + CH573_GPIO__GPIO_PORT_T_INTF.pd_drv.set(ch573_gpio__gpio_port_a, 1, 11); } static inline void set_sysled(int on) { CH573_GPIO__GPIO_PORT_T_INTF.out.set( - ch573_gpio__gpio_port_b, on ? ON : OFF, 10); + ch573_gpio__gpio_port_a, on ? ON : OFF, 11); } diff --git a/include/systick.h b/include/systick.h index 285b9b8..09c69ec 100644 --- a/include/systick.h +++ b/include/systick.h @@ -10,9 +10,16 @@ uint64_t get_systick(); int systick_interrupt(); + +#define PASTER(x, y) x##y +#define CONCAT(x, y) PASTER(x, y) + #define On_SysTick() \ static void __local_on_systick__(void); \ __attribute__(( \ __section__(".systick_callbacks"))) static volatile systick_cb_t \ - __FILE__##__LINE__ = __local_on_systick__; \ + __systick__position = __local_on_systick__; \ static void __local_on_systick__() + +#undef PASTER +#undef CONCAT diff --git a/linker/ls.ld b/linker/ls.ld index 08e1901..791647b 100644 --- a/linker/ls.ld +++ b/linker/ls.ld @@ -42,6 +42,20 @@ SECTIONS SYSTICK_LISTENERS_END = .; } > flash AT>flash + .bootsel_callbacks : ALIGN(0x04) { + BOOTSEL_LISTENERS_START = .; + KEEP(*(.bootsel_callbacks)); + BOOTSEL_LISTENERS_END = .; + } > flash AT>flash + + + .patterns : ALIGN(0x04) { + PATTERNS_START = .; + KEEP(*(.patterns)); + PATTERNS_END = .; + } > flash AT>flash + + ISR_VECTOR_IN_FLASH = LOADADDR(.isr_vector); .isr_vector : ALIGN(0x04) { ISR_VECTOR_START = .; diff --git a/src/btsel.c b/src/btsel.c new file mode 100644 index 0000000..873b20a --- /dev/null +++ b/src/btsel.c @@ -0,0 +1,38 @@ +#include "btsel.h" + +#include "ch573/gpio.h" +#include "isr_vector.h" + +#define GPIO ch573_gpio__gpio +#define GPIO_I CH573_GPIO__GPIO_T_INTF +#define GPIO_PORT CH573_GPIO__GPIO_PORT_T_INTF +#define GPIO_PORT_A ch573_gpio__gpio_port_a +#define GPIO_PORT_B ch573_gpio__gpio_port_b + +extern bootsel_cb_t BOOTSEL_LISTENERS_START; +extern bootsel_cb_t BOOTSEL_LISTENERS_END; + +#define BOOTSEL_PIN 7 + +void enable_bootsel_button(void) +{ + GPIO_PORT.dir.set(GPIO_PORT_B, DIR_IN, BOOTSEL_PIN); + GPIO_PORT.pu.set(GPIO_PORT_B, ENABLED, BOOTSEL_PIN); + // GPIO_PORT.pd_drv.set(GPIO_PORT_B, PD_DRV_OPEN_DRAIN, BOOTSEL_PIN); + GPIO_PORT.out.set(GPIO_PORT_B, OFF, BOOTSEL_PIN); + GPIO_PORT.clr.set(GPIO_PORT_B, 1 << BOOTSEL_PIN); + + GPIO_I.pb_interrupt_mode.set(GPIO, 1 << BOOTSEL_PIN); + GPIO_I.pb_interrupt_flag.set(GPIO, 1 << BOOTSEL_PIN); + GPIO_I.pb_interrupt_enable.set(GPIO, 1 << BOOTSEL_PIN); +} + +IRQ(gpio_b) +{ + bootsel_cb_t* cur = &BOOTSEL_LISTENERS_START; + while (cur != &BOOTSEL_LISTENERS_END) { + (*cur)(); + ++cur; + } + GPIO_I.pb_interrupt_flag.set(GPIO, 1 << BOOTSEL_PIN); +} @@ -2,13 +2,16 @@ #include <stdint.h> #include <stdio.h> +#include "btsel.h" #include "byte_math.h" #include "ch573/gpio.h" #include "ch573/pfic.h" #include "ch573/pwr.h" #include "ch573/uart.h" #include "clock.h" +#include "isr_vector.h" #include "panic.h" +#include "pattern.h" #include "spi.h" #include "string.h" #include "sysled.h" @@ -16,12 +19,28 @@ #include "systick.h" #include "ws2812b.h" +#ifndef LED_BYTE_ORDER +#define LED_BYTE_ORDER GRB +#endif + +#define PASTER(x, y) x##y +#define CONCAT(x, y) PASTER(x, y) +#define LED_BYTE_ORDER_ENUM CONCAT(BYTE_ORDER_, LED_BYTE_ORDER) + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +#ifndef DEFAULT_PATTERN +#define DEFAULT_PATTERN CandyCane +#endif + #define PFIC_I CH573_PFIC__PFIC_T_INTF #define PFIC ch573_pfic__pfic #define GPIO_PORT_A ch573_gpio__gpio_port_a #define GPIO_PORT_B ch573_gpio__gpio_port_b #define GPIO_PORT CH573_GPIO__GPIO_PORT_T_INTF +#define GPIO_I CH573_GPIO__GPIO_T_INTF +#define GPIO ch573_gpio__gpio #define UART1 ch573_uart__uart1 #define UART CH573_UART__UART_T_INTF @@ -29,8 +48,6 @@ #define PWR1 ch573_pwr__pwr_mgmt #define PWR CH573_PWR__PWR_MGMT_T_INTF -#define AS_BYTE(n) ((n) * 256) - #define min(a, b) (a) < (b) ? (a) : (b) uint8_t amp(uint8_t in, uint8_t n) @@ -44,21 +61,6 @@ uint8_t amp(uint8_t in, uint8_t n) return min(out, 255); } -uint32_t collatz(uint32_t n) -{ - uint32_t c = 0; - - while (n > 1) { - if (n % 2 == 0) { - n /= 2; - } else { - n = n * 3 + 1; - } - c++; - } - - return c; -} static void set_system_clock_60Mhz(void) { @@ -71,58 +73,40 @@ static void set_system_clock_60Mhz(void) } } -#define N_LEDS 150 -#define N_DMA_XFER 2 +#define N_LEDS 255 +#define N_DMA_XFER 3 extern int uart1_FILE_get(FILE* f); -static inline uint8_t byte_scale(uint8_t v, uint8_t scale) -{ - uint16_t acc = v; - return (acc * scale) >> 8; -} - -uint8_t clip(int x) -{ - if (x > 240) { - return 240; - } - - if (x < 0) { - return 0; - } - - return (uint8_t)x; -} - #define TIME_STEP 1 -rgb_t get_rgb(uint32_t time, size_t x) -{ - int r = 0, g = 0, b = 0; - - uint8_t time8 = time & 0xff; - int w = calc_w(time8 * TIME_STEP + x * 4); +static volatile uint32_t time = 0; +static volatile int spin_lock = 0; - r = 0xff; - g = byte_scale(byte_sin(time8 * TIME_STEP + x * 2), 0x90); - b = byte_scale(byte_sin(time8 * TIME_STEP + x * 2), 0x20); +static size_t current_pattern_idx = 0; - rgb_t color; - color.color = 0; - color.r = clip(r + w); - color.g = clip(byte_scale(g, AS_BYTE(0.75)) + w); - color.b = clip(byte_scale(b, AS_BYTE(0.75)) + w); - return color; +static size_t debounce = 0; +On_SysTick() +{ + if (debounce > 0) { + debounce --; + } + time++; + spin_lock = 0; } +On_BootSelPress() +{ + if (debounce > 0) return; + debounce = 10; -static volatile uint32_t time = 0; -static volatile int spin_lock = 0; - -On_SysTick() { - time ++; - spin_lock = 0; + size_t tmp = current_pattern_idx; + tmp ++; + if (tmp >= n_patterns) { + tmp = 0; + } + current_pattern_idx = tmp; + printf("Switch to '%s'\n", patterns[current_pattern_idx].name); } /* @@ -135,6 +119,10 @@ int main(void) PFIC_I.vector_table_control.set(PFIC, 1); PFIC->interrupt_priority_threshold = 0x10; PFIC->interrupt_enable |= IRQ_SysTick; + PFIC->interrupt_priority_threshold = 0x10; + PFIC->interrupt_enable |= IRQ_GpioA; + PFIC->interrupt_priority_threshold = 0x10; + PFIC->interrupt_enable |= IRQ_GpioB; set_system_clock_60Mhz(); set_systick(250000); @@ -142,30 +130,54 @@ int main(void) enable_sysled(); enable_spi(); + for (current_pattern_idx = 0; current_pattern_idx < n_patterns; + ++current_pattern_idx) { + if (strcmp( + patterns[current_pattern_idx].name, "" TOSTRING(DEFAULT_PATTERN)) == + 0) { + break; + } + } + + if (current_pattern_idx == n_patterns) { + printf( + "Could not find a pattern with the name '%s'.\n", + TOSTRING(DEFAULT_PATTERN)); + panic(0xaa); + } + + printf("\nRunning Pattern '%s'\n", patterns[current_pattern_idx].name); + + enable_bootsel_button(); + size_t n = sizeof(buf); struct ws2812b_buf ws_buf; make_wsb2812b(&ws_buf, buf, n); - ws_buf.byte_order = BYTE_ORDER_GRB; + ws_buf.byte_order = LED_BYTE_ORDER_ENUM; rgb_t color; - GPIO_PORT.dir.set(GPIO_PORT_B, DIR_OUT, 7); + GPIO_PORT.dir.set(GPIO_PORT_A, DIR_OUT, 10); + + // GPIO->pb_interrupt_mode |= (1 << 7) | (1 << 8); while (1) { + pattern_t* current_pattern = &patterns[current_pattern_idx]; ws_buf.cur = 0; for (int i = 0; i < N_LEDS; ++i) { - rgb_t rgb = get_rgb(time, i); + rgb_t rgb = current_pattern->get_rgb(time, i); write_rgb(&ws_buf, rgb); } while (spin_lock) { - set_sysled(1); // Setting the sysled helps me to measure down time. + // set_sysled(1); // Setting the sysled helps me to measure down time. + GPIO_PORT.out.set(GPIO_PORT_A, ON, 10); } - set_sysled(0); + GPIO_PORT.out.set(GPIO_PORT_A, OFF, 10); spin_lock = 1; - for (int j = 0; j < N_DMA_XFER; ++ j) { + for (int j = 0; j < N_DMA_XFER; ++j) { wait_for_dma(); start_dma(&ws_buf); } |