aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-12-03 10:35:55 -0700
committerJosh Rahm <joshuarahm@gmail.com>2024-12-03 10:35:55 -0700
commitf5e15a5a2d55cf0a6fbdbe04e5c49499a6eac642 (patch)
treed9f570c228268dfa0ecc31ad15579d412b953a6f
parenta15656b399689d0c7b12963a718729bea9b6dfcc (diff)
downloadch573-f5e15a5a2d55cf0a6fbdbe04e5c49499a6eac642.tar.gz
ch573-f5e15a5a2d55cf0a6fbdbe04e5c49499a6eac642.tar.bz2
ch573-f5e15a5a2d55cf0a6fbdbe04e5c49499a6eac642.zip
Basic Christmas light implementation!
-rw-r--r--include/byte_math.h15
-rw-r--r--include/sysled.h19
-rw-r--r--include/ws2812b.h4
-rw-r--r--src/byte_math.c41
-rw-r--r--src/main.c130
-rw-r--r--src/spi.c6
-rw-r--r--src/ws2812b.c19
7 files changed, 183 insertions, 51 deletions
diff --git a/include/byte_math.h b/include/byte_math.h
new file mode 100644
index 0000000..79f93b8
--- /dev/null
+++ b/include/byte_math.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <stdint.h>
+
+/* Library for doing fast math functions using just uint8_t. */
+
+extern uint8_t sintable[256];
+
+/* Returns ((sin(n) + 1) / 2) * 255 */
+static inline uint8_t byte_sin(uint8_t n)
+{
+ return sintable[n];
+}
+
+uint8_t calc_w(uint8_t n);
diff --git a/include/sysled.h b/include/sysled.h
new file mode 100644
index 0000000..b9556f1
--- /dev/null
+++ b/include/sysled.h
@@ -0,0 +1,19 @@
+#pragma once
+
+/* Easily turn on and off the system-led. */
+
+#include "ch573/gpio.h"
+
+static inline void enable_sysled()
+{
+ CH573_GPIO__GPIO_PORT_T_INTF.dir.set(ch573_gpio__gpio_port_a, DIR_OUT, 8);
+ CH573_GPIO__GPIO_PORT_T_INTF.pd_drv.set(ch573_gpio__gpio_port_a, 0, 8);
+}
+
+// If "on" then turn on the sysled (which counter-intuitively means turning off
+// the GPIO).
+static inline void set_sysled(int on)
+{
+// CH573_GPIO__GPIO_PORT_T_INTF.out.set(
+// ch573_gpio__gpio_port_a, on ? OFF : ON, 8);
+}
diff --git a/include/ws2812b.h b/include/ws2812b.h
index cb10979..e814b65 100644
--- a/include/ws2812b.h
+++ b/include/ws2812b.h
@@ -4,11 +4,11 @@
#include <stdlib.h>
#define WIRE_BYTES_PER_COLOR 9
-#define PADDING_BYTES 0
+#define PADDING_BYTES 1
#define TOTAL_BYTES_PER_LED (PADDING_BYTES + WIRE_BYTES_PER_COLOR)
enum ws2812b_byte_order {
- BYTE_ORDER_BGR = 0,
+ BYTE_ORDER_RGB = 0,
BYTE_ORDER_GBR = 1,
};
diff --git a/src/byte_math.c b/src/byte_math.c
new file mode 100644
index 0000000..ebe49cc
--- /dev/null
+++ b/src/byte_math.c
@@ -0,0 +1,41 @@
+#include "byte_math.h"
+
+// The shape of a "spike"
+uint8_t w_arr[91] = {1, 2, 4, 7, 11, 17, 24, 33, 44, 56, 70, 85,
+ 101, 117, 134, 151, 167, 183, 197, 210, 222, 232, 240, 247,
+ 251, 254, 255, 255, 253, 250, 246, 240, 234, 227, 219, 211,
+ 202, 194, 185, 176, 167, 158, 149, 140, 132, 123, 116, 108,
+ 101, 94, 87, 81, 75, 69, 64, 59, 54, 50, 46, 42,
+ 39, 35, 32, 30, 27, 25, 22, 20, 18, 17, 15, 14,
+ 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3,
+ 3, 3, 2, 2, 2, 1, 1};
+
+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 calc_w(uint8_t n)
+{
+ if (n < 164) {
+ return 0;
+ }
+
+ return w_arr[n - 164];
+}
diff --git a/src/main.c b/src/main.c
index 199f04b..7b998eb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,12 +1,17 @@
+#include <math.h>
#include <stdint.h>
#include <stdio.h>
+#include "string.h"
+#include "byte_math.h"
#include "ch573/gpio.h"
#include "ch573/pwr.h"
#include "ch573/uart.h"
#include "clock.h"
+#include "panic.h"
#include "spi.h"
#include "string.h"
+#include "sysled.h"
#include "system.h"
#include "ws2812b.h"
@@ -20,6 +25,21 @@
#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)
+{
+ uint32_t out = in;
+
+ for (int i = 0; i < n; ++i) {
+ out = (out * in) / 256;
+ }
+
+ return min(out, 255);
+}
+
uint32_t collatz(uint32_t n)
{
uint32_t c = 0;
@@ -111,9 +131,11 @@ static void set_system_clock_32kHz()
static void basic_delay()
{
- for (int i = 0; i < 100000; ++i) {
+ set_sysled(1);
+ for (int i = 0; i < 30000; ++i) {
asm volatile("");
}
+ set_sysled(0);
}
static void fast_delay()
@@ -123,71 +145,95 @@ static void fast_delay()
}
}
-#define N_LEDS 100
+#define N_LEDS 150
+memset(buf, 0xff, sizeof(buf));
+#define N_DMA_XFER 2
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);
+
+ r = 0xff;
+ g = byte_scale(byte_sin(time8 * TIME_STEP + x * 2), 0x90);
+ b = byte_scale(byte_sin(time8 * TIME_STEP + x * 2), 0x20);
+ // r = byte_scale(byte_sin(time8 * TIME_STEP + x * 2), AS_BYTE(0.25)) +
+ // AS_BYTE(0.75);
+ // b = 0x40;
+ // g = byte_scale(
+ // 0xff - byte_sin(time8 * TIME_STEP + x * 7 + 0x80), AS_BYTE(0.5)) +
+ // AS_BYTE(0.5);
+
+ rgb_t color;
+ color.color = 0;
+ color.r = clip(r + w);
+ color.g = clip(byte_scale(g, AS_BYTE(0.75)) + w);
+ color.b = claa(byte_scale(b, AS_BYTE(0.75)) + w);
+ return color;
+}
+
/*
* Main routine. This is called on_reset once everything else has been set up.
*/
int main(void)
{
- printf("Running SPI.\n");
+ char buf[N_LEDS * TOTAL_BYTES_PER_LED];
set_system_clock_60Mhz();
-
- printf("What is your name? ");
- char buf[1024];
+ enable_sysled();
enable_spi();
- // char buf[1024];
- // memset(buf, 0xf0, sizeof(buf));
- // for (int i = 0; i < 50; ++ i) {
- // buf[i] = 0xaa;
- // buf[sizeof(buf) - i] = 0xaa;
- // }
-
size_t n = sizeof(buf);
struct ws2812b_buf ws_buf;
make_wsb2812b(&ws_buf, buf, n);
+ ws_buf.byte_order = BYTE_ORDER_GBR;
+
+ printf("Test %u", byte_scale(40, 0x80));
+
rgb_t color;
- color.color = 0;
- color.r = 0xff;
- color.g = 0x00;
- color.b = 0x00;
- uint8_t time = 0xff;
-
- // for (size_t i = 0; i < N_LEDS; ++i) {
- // char* loc = buf + i * TOTAL_BYTES_PER_LED;
- // printf(
- // "Bytes: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
- // loc[0],
- // loc[1],
- // loc[2],
- // loc[3],
- // loc[4],
- // loc[5],
- // loc[6],
- // loc[7],
- // loc[8],
- // loc[9],
- // loc[10]);
- // }
+ uint32_t time = 0;
GPIO_PORT.dir.set(GPIO_PORT_B, DIR_OUT, 7);
while (1) {
+ // Fill the buffer with calculated rgb colors.
ws_buf.cur = 0;
for (int i = 0; i < N_LEDS; ++i) {
- color.r = time;
- color.g = 0;
- color.b = 0xff - time;
- write_rgb(&ws_buf, color);
+ rgb_t rgb = get_rgt(time, i);
+ write_rgb(&ws_buf, rgb);
}
- time --;
+
+ time++;
GPIO_PORT.out.set(GPIO_PORT_B, ON, 7);
// printf("WS_BUF: %p, %zu\n", ws_buf.buf, ws_buf.cur);
- start_dma(&ws_buf);
- wait_for_dma();
+ for (int i = 0; i < N_DMA_XFER; ++i) {
+ wait_for_dma();
+ start_dma(&ws_buf);
+ }
basic_delay();
}
diff --git a/src/spi.c b/src/spi.c
index 5c84b77..a416014 100644
--- a/src/spi.c
+++ b/src/spi.c
@@ -4,6 +4,7 @@
#include "ch573/gpio.h"
#include "ch573/spi.h"
+#include "sysled.h"
#define MAX_SPI_FIFO 8
@@ -79,7 +80,10 @@ void dma_transfer(void* output_buffer, size_t len)
void wait_for_dma()
{
- while (SPI.total_count.get(SPI0) > 0);
+ while (SPI.total_count.get(SPI0) > 0) {
+ set_sysled(1);
+ }
+ set_sysled(0);
}
void run_spi(void)
diff --git a/src/ws2812b.c b/src/ws2812b.c
index 8547b5d..3721b23 100644
--- a/src/ws2812b.c
+++ b/src/ws2812b.c
@@ -3,6 +3,7 @@
#include <string.h>
#include "spi.h"
+#include "sysled.h"
// either 0b110 when (n) is true, otherwise 0b100
#define BIT_TO_SPI_DATA(v, n) ((BIT_N(v, n)) ? 6 : 4)
@@ -32,20 +33,24 @@ inline static void complie_color_inline(
rgb_t color, struct rgb_compiled* out, enum ws2812b_byte_order byte_order)
{
if (byte_order == BYTE_ORDER_GBR) {
- uint8_t tmp = color.b;
- color.b = color.g;
+ uint8_t tmp = color.r;
+ color.r = color.g;
color.g = tmp;
}
+ color.r = color.r;
+ color.g = color.g;
+ color.b = color.b;
+
out->first_bits =
- BYTE_1(COLOR_BYTE_1(color.b)) | BYTE_2(COLOR_BYTE_2(color.b)) |
- BYTE_3(COLOR_BYTE_3(color.b)) | BYTE_4(COLOR_BYTE_1(color.g));
+ BYTE_1(COLOR_BYTE_1(color.r)) | BYTE_2(COLOR_BYTE_2(color.r)) |
+ BYTE_3(COLOR_BYTE_3(color.r)) | BYTE_4(COLOR_BYTE_1(color.g));
out->second_bits =
BYTE_1(COLOR_BYTE_2(color.g)) | BYTE_2(COLOR_BYTE_3(color.g)) |
- BYTE_3(COLOR_BYTE_1(color.r)) | BYTE_4(COLOR_BYTE_2(color.r));
+ BYTE_3(COLOR_BYTE_1(color.b)) | BYTE_4(COLOR_BYTE_2(color.b));
- out->last_bits = COLOR_BYTE_3(color.r);
+ out->last_bits = COLOR_BYTE_3(color.b);
}
void compile_color(
@@ -74,8 +79,10 @@ int write_rgb(struct ws2812b_buf* out, rgb_t color)
while ((dma_loc - CLIP_TO_DMA_BITS(out->buf + out->cur) <
TOTAL_BYTES_PER_LED) &&
(dma_loc < dma_end)) {
+ set_sysled(1); // Little indication to tell if we are waiting for the DMA.
dma_loc = *dma_now;
}
+ set_sysled(0);
}
memcpy(out->buf + out->cur, comp.buf, WIRE_BYTES_PER_COLOR);