macros for rendering array in WS strip, ADC lib, testing radnom

This commit is contained in:
2014-12-24 01:53:59 +01:00
parent e30f2ba0c7
commit c3201fe3aa
9 changed files with 1259 additions and 156 deletions
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <avr/io.h>
#include <stdbool.h>
#include "calc.h"
/** Initialize the ADC */
void adc_init()
{
ADCSRA |= _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 128 prescaler -> 125 kHz
ADMUX |= _BV(REFS0); // Voltage reference
sbi(ADCSRA, ADEN); // Enable ADC
}
/** Sample analog pin with 8-bit precision */
uint8_t adc_read_byte(uint8_t channel)
{
write_low_nibble(ADMUX, channel); // Select channel to sample
sbi(ADMUX, ADLAR); // Align result to left
sbi(ADCSRA, ADSC); // Start conversion
while(bit_is_high(ADCSRA, ADSC)); // Wait for it...
return ADCH; // The upper 8 bits of ADC result
}
/** Sample analog pin with 10-bit precision */
uint16_t adc_read_word(uint8_t channel)
{
write_low_nibble(ADMUX, channel); // Select channel to sample
cbi(ADMUX, ADLAR); // Align result to right
sbi(ADCSRA, ADSC); // Start conversion
while(get_bit(ADCSRA, ADSC)); // Wait for it...
return ADCW; // The whole ADC word (10 bits)
}
+6
View File
@@ -16,6 +16,9 @@
#define read_bit(reg, bit) ((((uint8_t)(reg)) >> (uint8_t)(bit)) & 0x1)
#define get_bit(reg, bit) read_bit(reg, bit)
#define bit_is_high(reg, bit) read_bit(reg, bit)
#define bit_is_low(reg, bit) !read_bit(reg, bit)
// Can't use bit_is_set, as it's redefined in sfr_def.h
#define write_bit(reg, bit, value) do { (reg) = ((reg) & ~(1 << (uint8_t)(bit))) | (((uint8_t)(value) & 0x1) << (uint8_t)(bit)); } while(0)
#define set_bit(reg, bit, value) write_bit(reg, bit, value)
@@ -32,6 +35,9 @@
#define set_bit_p(reg, bit, value) write_bit_p(reg_p, bit, value)
#define toggle_bit_p(reg_p, bit) do { *(reg_p) ^= (1 << (uint8_t)(bit)); } while(0)
#define write_low_nibble(reg, value) do { (reg) = ((reg) & 0xF0) | ((uint8_t)(value) & 0xF); } while(0)
#define write_high_nibble(reg, value) do { (reg) = ((reg) & 0x0F) | (((uint8_t)(value) & 0xF) << 4); } while(0)
// Check if value is in range A..B or B..A
#define in_range(x, low, high) (((low) < (high)) && ((x) > (low) && (x) < (high))) || (((low) > (high)) && ((x) < (low) || (x) > (high)))
+29 -5
View File
@@ -2,6 +2,13 @@
/*
Some useful utilities for RGB color manipulation
The XXXc macros don't use cast, so they can be used in array initializers.
xrgb ... 3-byte true-color RGB (8 bits per component)
rgbXX ... XX-bit color value, with equal nr of bits per component
XX_r (_g, _b) ... extract component from the color, and convert it to 0..255
*/
typedef struct {
@@ -16,7 +23,9 @@ typedef uint16_t rgb12_t;
typedef uint8_t rgb6_t;
#define xrgb(rr, gg, bb) ((xrgb_t) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) })
#define xrgb(rr, gg, bb) ((xrgb_t)xrgbc(rr, gg, bb))
// xrgb for constant array declarations
#define xrgbc(rr, gg, bb) { .r = ((uint8_t)(rr)), .g = ((uint8_t)(gg)), .b = ((uint8_t)(bb)) }
#define xrgb_r(c) ((uint8_t)(c.r))
#define xrgb_g(c) ((uint8_t)(c.g))
#define xrgb_b(c) ((uint8_t)(c.b))
@@ -26,34 +35,49 @@ typedef uint8_t rgb6_t;
#define xrgb_rgb6(c) (((((rgb6_t)c.r) & 0xC0) >> 2) | ((((rgb6_t)c.g) & 0xC0) >> 4) | ((((rgb6_t)c.b) & 0xC0) >> 6))
#define rgb24(r,g,b) ((rgb24_t) (((((rgb24_t)r) & 0xFF) << 16) | ((((rgb24_t)g) & 0xFF) << 8) | (((rgb24_t)b) & 0xFF)))
#define rgb24(r,g,b) (((((rgb24_t)r) & 0xFF) << 16) | ((((rgb24_t)g) & 0xFF) << 8) | (((rgb24_t)b) & 0xFF))
#define rgb24c(r,g,b) ((rgb24_t) rgb24(r,g,b))
#define rgb24_r(c) ((((rgb24_t) (c)) >> 16) & 0xFF)
#define rgb24_g(c) ((((rgb24_t) (c)) >> 8) & 0xFF)
#define rgb24_b(c) ((((rgb24_t) (c)) >> 0) & 0xFF)
#define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c))
#define rgb24_xrgbc(c) xrgbc(rgb24_r(c), rgb24_g(c), rgb24_b(c))
#define rgb15(r,g,b) ((rgb16_t) (((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F)))
#define rgb15(r,g,b) ((rgb16_t) rgb15c(r,g,b))
#define rgb15c(r,g,b) (((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F))
#define rgb15_r(c) ((((rgb15_t) (c)) & 0x7C00) >> 7)
#define rgb15_g(c) ((((rgb15_t) (c)) & 0x3E0) >> 2)
#define rgb15_b(c) ((((rgb15_t) (c)) & 0x1F) << 3)
#define rgb15_xrgb(c) xrgb(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb15_rgb24(c) rgb24(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb15_rgb24c(c) rgb24c(rgb15_r(c), rgb15_g(c), rgb15_b(c))
#define rgb12(r,g,b) ((rgb12_t) (((r & 0xF) << 8) | ((g & 0xF) << 4) | (b & 0xF)))
#define rgb12(r,g,b) ((rgb12_t) rgb12c(r,g,b))
#define rgb12c(r,g,b) (((r & 0xF) << 8) | ((g & 0xF) << 4) | (b & 0xF))
#define rgb12_r(c) ((((rgb12_t) (c)) & 0xF00) >> 4)
#define rgb12_g(c) (((rgb12_t) (c)) & 0xF0)
#define rgb12_b(c) (((r(rgb12_t) (c)gb) & 0x0F) << 4)
#define rgb12_xrgb(c) xrgb(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_xrgbc(c) xrgbc(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_rgb24(c) rgb24(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb12_rgb24c(c) rgb24c(rgb12_r(c), rgb12_g(c), rgb12_b(c))
#define rgb6(r,g,b) ((rgb6_t) (((r & 3) << 4) | ((g & 3) << 2) | (b & 3)))
#define rgb6(r,g,b) ((rgb6_t) rgb6c(r,g,b))
#define rgb6c(r,g,b) (((r & 3) << 4) | ((g & 3) << 2) | (b & 3))
#define rgb6_r(c) ((((rgb6_t) (c)) & 0x30) << 2)
#define rgb6_g(c) ((((rgb6_t) (c)) & 0xC) << 4)
#define rgb6_b(c) ((((rgb6_t) (c)) & 0x3) << 6)
#define rgb6_xrgb(c) xrgb(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_xrgbc(c) xrgbc(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_rgb24(c) rgb24(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define rgb6_rgb24c(c) rgb24c(rgb6_r(c), rgb6_g(c), rgb6_b(c))
#define add_xrgb(x, y) ((xrgb_t) { (((y).r > (255 - (x).r)) ? 255 : ((x).r + (y).r)), (((y).g > (255 - (x).g)) ? 255 : ((x).g + (y).g)), (((y).b > 255 - (x).b) ? 255 : ((x).b + (y).b)) })
+27 -6
View File
@@ -4,11 +4,17 @@
Utils for driving a WS2812 (WS2812B) RGB LED strips.
It's implemented as macros to avoid overhead when passing values, and to
enable driving multiple strips at once. There is over 1us of free time between
the colors, which can be used for some processing or color computation.
enable driving multiple strips at once.
To avoid bloating your code, try to reduce the nuýmber of invocations -
To avoid bloating your code, try to reduce the number of invocations -
compute color and then send it.
[IMPORTANT]
Some seemingly random influences can ruin the communication.
If you have enough memory, consider preparing the colors in array,
and sending this array using one of the "ws_send_XXX_array" macros.
*/
#include <avr/io.h>
@@ -43,13 +49,13 @@
/** Wait long enough for the colors to show */
#define ws_show() do { delay_ns_c(WS_T_LATCH, 0); } while(0)
#define ws_show() do {delay_ns_c(WS_T_LATCH, 0); } while(0)
/** Send one byte to the RGB strip */
#define ws_send_byte(io, bb) do { \
for (volatile int8_t __wsba_i = 7; __wsba_i >= 0; --__wsba_i) { \
if ((bb) & (1 << __wsba_i)) { \
for (volatile int8_t __ws_tmp = 7; __ws_tmp >= 0; --__ws_tmp) { \
if ((bb) & (1 << __ws_tmp)) { \
pin_high(io_pack(io)); delay_ns_c(WS_T_1H, -2); \
pin_low(io_pack(io)); delay_ns_c(WS_T_1L, -10); \
} else { \
@@ -75,3 +81,18 @@
#define ws_send_rgb15(io, rgb) ws_send_rgb(io_pack(io), rgb15_r(rgb), rgb15_g(rgb), rgb15_b(rgb))
#define ws_send_rgb12(io, rgb) ws_send_rgb(io_pack(io), rgb12_r(rgb), rgb12_g(rgb), rgb12_b(rgb))
#define ws_send_rgb6(io, rgb) ws_send_rgb(io_pack(io), rgb6_r(rgb), rgb6_g(rgb), rgb6_b(rgb))
/** Send array of colors */
#define ws_send_xrgb_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), xrgb)
#define ws_send_rgb24_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb24)
#define ws_send_rgb15_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb15)
#define ws_send_rgb12_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb12)
#define ws_send_rgb6_array(io, rgbs, length) __ws_send_array_proto(io_pack(io), (rgbs), (length), rgb6)
// prototype for sending array. it's ugly, sorry.
#define __ws_send_array_proto(io, rgbs, length, style) do { \
for (uint8_t __ws_tmp_sap_i = 0; __ws_tmp_sap_i < length; __ws_tmp_sap_i++) { \
style ## _t __ws_tmp_sap2 = (rgbs)[__ws_tmp_sap_i]; \
ws_send_ ## style(io_pack(io), __ws_tmp_sap2); \
} \
} while(0)