summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2022-01-09 22:12:16 +0100
committerDaniel Friesel <derf@finalrewind.org>2022-01-09 22:12:16 +0100
commit3a6d5a2682b761b914d611e980a256202f1b1cf6 (patch)
tree7aaf1b712382c688a4e167d850834ba33bbf6312
parentcd266af44d991c00e841f1bbac95d89f44d52212 (diff)
ws2812b dmap: use double buffering and more efficient RX ring buffer
-rw-r--r--src/app/ws2812b_dmap/main.cc88
1 files changed, 73 insertions, 15 deletions
diff --git a/src/app/ws2812b_dmap/main.cc b/src/app/ws2812b_dmap/main.cc
index ed9b083..7e953e3 100644
--- a/src/app/ws2812b_dmap/main.cc
+++ b/src/app/ws2812b_dmap/main.cc
@@ -19,6 +19,7 @@
#define BUF_SIZE 36
#define BUF_MAX ((BUF_SIZE)-1)
+#define RINGBUF_SIZE ((BUF_SIZE)+2)
#define NUM_PIXELS 256
@@ -27,21 +28,24 @@ Adafruit_NeoPixel np(NUM_PIXELS, GPIO::pb0, NEO_GRB+NEO_KHZ800);
#define MYADDRESS (0x0006)
volatile uint16_t address;
+volatile uint8_t ringbuf[RINGBUF_SIZE];
+volatile uint8_t ringbuf_byte = 0;
+volatile uint8_t ringbuf_bitmask = 0x80;
volatile uint8_t buf[BUF_SIZE];
volatile uint8_t done;
void update()
{
- if (buf[35] > 100) {
- buf[35] = 100;
+ if (buf[0] > 100) {
+ buf[0] = 100;
}
- if (buf[32] + buf[33] + buf[34] > 50) {
- buf[32] = 0;
- buf[33] = 0;
- buf[34] = 5;
+ if (buf[1] + buf[2] + buf[3] > 50) {
+ buf[1] = 5;
+ buf[2] = 0;
+ buf[3] = 0;
}
- uint32_t color = np.Color(buf[34], buf[33], buf[32]);
- uint8_t rgb = buf[35];
+ uint32_t color = np.Color(buf[1], buf[2], buf[3]);
+ uint8_t rgb = buf[0];
for (uint8_t col = 0; col < 32; col++) {
for (uint8_t row = 0; row < 8; row++) {
uint8_t pixel_index = col*8;
@@ -53,7 +57,7 @@ void update()
if (rgb) {
color = np.gamma32(np.ColorHSV(((uint16_t)col*8+row) * 255, 255, rgb));
}
- if (buf[col] & _BV(row)) {
+ if (buf[31-col+4] & _BV(row)) {
np.setPixelColor(pixel_index, color);
} else {
np.setPixelColor(pixel_index, 0);
@@ -63,6 +67,40 @@ void update()
np.show();
}
+void next_bit(uint8_t *byte, uint8_t *mask, uint8_t const size)
+{
+ if (*mask > 0x01) {
+ *mask >>= 1;
+ } else {
+ *byte = (*byte + 1) % size;
+ *mask = 0x80;
+ }
+}
+
+void ringbuf_to_buf(void)
+{
+ uint8_t read_byte = ringbuf_byte;
+ uint8_t read_bitmask = ringbuf_bitmask;
+
+ // byte[bitmask] is the next bit that would be written -- and, thanks to
+ // the buffer size, also the most significant bit of message byte 0.
+
+ for (uint8_t write_byte = 0; write_byte < BUF_SIZE; write_byte++) {
+ buf[write_byte] = 0;
+ for (uint8_t write_bitmask = 0x80; write_bitmask > 0; write_bitmask >>= 1) {
+ if (ringbuf[read_byte] & read_bitmask) {
+ buf[write_byte] |= write_bitmask;
+ }
+ if (read_bitmask > 0x01) {
+ read_bitmask >>= 1;
+ } else {
+ read_byte = (read_byte + 1) % RINGBUF_SIZE;
+ read_bitmask = 0x80;
+ }
+ }
+ }
+}
+
int main(void)
{
@@ -85,6 +123,21 @@ int main(void)
while (1) {
arch.idle();
if (done) {
+ /*
+ kout << dec << "done, byte=" << ringbuf_byte << hex << " bitmask=" << ringbuf_bitmask << " ringbuf = " << hex;
+ for (uint8_t i = 0; i < RINGBUF_SIZE; i++) {
+ kout << ringbuf[i] << " ";
+ }
+ kout << endl;
+ */
+ ringbuf_to_buf();
+ /*
+ kout << "update, buf = " << hex;
+ for (uint8_t i = 0; i < BUF_SIZE; i++) {
+ kout << buf[i] << " ";
+ }
+ kout << endl;
+ */
update();
done = 0;
}
@@ -95,17 +148,22 @@ int main(void)
ISR(INT1_vect)
{
- if (CLOCK_HI) {
- for (uint8_t i = BUF_MAX; i > 0; i--) {
- buf[i] = (buf[i] << 1) | (buf[i-1] >> 7);
- }
- buf[0] = (buf[0] << 1) | (address >> 15);
- address = (address << 1) | DATA_BIT;
+ if (CLOCK_HI && !done) {
if (DATA_BIT) {
+ ringbuf[ringbuf_byte] |= ringbuf_bitmask;
+ address = (address << 1) | 1;
gpio.led_on(0);
} else {
+ ringbuf[ringbuf_byte] &= ~ringbuf_bitmask;
+ address = (address << 1) | 0;
gpio.led_off(0);
}
+ if (ringbuf_bitmask > 0x01) {
+ ringbuf_bitmask >>= 1;
+ } else {
+ ringbuf_byte = (ringbuf_byte + 1) % RINGBUF_SIZE;
+ ringbuf_bitmask = 0x80;
+ }
}
else if (DATA_HI && (address == MYADDRESS)) {
done = 1;