aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-12-07 13:58:46 -0700
committerJosh Rahm <joshuarahm@gmail.com>2024-12-07 13:58:46 -0700
commit546a5ccdba66dd8d8c19ce6d8486f46c84637cf2 (patch)
tree95b52da91414c1bfbad745c6b55617011012813e
parent9182b65ae2045c5087257751d30409deecf9520a (diff)
downloadch573-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.txt15
-rw-r--r--fdl/ch573/gpio.fdl16
-rw-r--r--fdl/ch573/pfic.fdl6
-rw-r--r--include/btsel.h19
-rw-r--r--include/byte_math.h21
-rw-r--r--include/sysled.h6
-rw-r--r--include/systick.h9
-rw-r--r--linker/ls.ld14
-rw-r--r--src/btsel.c38
-rw-r--r--src/main.c142
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);
+}
diff --git a/src/main.c b/src/main.c
index 33728ea..8deb257 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
}