macros for rendering array in WS strip, ADC lib, testing radnom
This commit is contained in:
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user