From 3a6d5a2682b761b914d611e980a256202f1b1cf6 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 9 Jan 2022 22:12:16 +0100 Subject: ws2812b dmap: use double buffering and more efficient RX ring buffer --- src/app/ws2812b_dmap/main.cc | 88 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 15 deletions(-) (limited to 'src/app/ws2812b_dmap/main.cc') 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; -- cgit v1.2.3