30 #if defined(WS2812_TARGET_PLATFORM_AVR) || defined(WS2812_TARGET_PLATFORM_ARDUINO_AVR)
35 #include <avr/interrupt.h>
37 #include <util/delay.h>
41 #ifdef WS2812_TARGET_PLATFORM_ARDUINO_AVR
46 #define w_zeropulse 350
47 #define w_onepulse 900
48 #define w_totalperiod 1250
53 #define w_fixedtotal 10
56 #define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
57 #define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
58 #define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)
61 #define w1 (w_zerocycles-w_fixedlow)
63 #define w2 (w_onecycles-w_fixedhigh-w1)
65 #define w3 (w_totalcycles-w_fixedtotal-w1-w2)
75 #define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
77 #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
79 #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
80 #warning "Please consider a higher clockspeed, if possible"
95 #define w_nop1 "nop \n\t"
96 #define w_nop2 "rjmp .+0 \n\t"
97 #define w_nop4 w_nop2 w_nop2
98 #define w_nop8 w_nop4 w_nop4
99 #define w_nop16 w_nop8 w_nop8
101 static uint8_t _sreg_prev;
102 static bool _prep =
false;
104 #ifdef WS2812_TARGET_PLATFORM_AVR
119 for (uint8_t i = 0; i < us; i++)
133 #ifdef WS2812_TARGET_PLATFORM_ARDUINO_AVR
134 for (uint8_t i = 0; i < cfg->
n_dev; i++) {
135 if (i+1 < cfg->
n_dev &&
136 digitalPinToPort(cfg->
pins[i]) != digitalPinToPort(cfg->
pins[i+1]))
138 pinMode(cfg->
pins[i], OUTPUT);
139 pin_msk |= digitalPinToBitMask(cfg->
pins[i]);
141 dev->
port = portOutputRegister(digitalPinToPort(cfg->
pins[0]));
143 for (uint8_t i = 0; i < cfg->
n_dev; i++)
144 pin_msk |= 1 << cfg->
pins[i];
161 if (_prep ==
false) {
170 #ifdef WS2812_TARGET_PLATFORM_ARDUINO_AVR
178 #pragma GCC push_options
179 #pragma GCC optimize ("O0")
234 " brcc skipone%= \n\t"
256 :
"r" (
byte),
"x" ((uint8_t *) dev->
port),
"r" (dev->
maskhi),
"r" (dev->
masklo)
261 #pragma GCC pop_options
266 for (
size_t i = 0; i < n_leds; i++) {
267 for (uint8_t j = 0; j <
sizeof(dev->
rgbmap); j++) {
268 uint8_t *pxl = (uint8_t *) &(
leds[i]);
ws2812_rgb leds[N_LEDS]
RGB array which represents the LEDs.
ALL PLATFORMS: Data structure to configure a WS2812 device struct.
volatile uint8_t * ddr
Data Direction Register (ex. DDRB, DDRC, DDRD...)
uint8_t n_dev
Number of WS2812 device to drive.
volatile uint8_t * port
PORT Register (ex. PORTB, PORTC, PORTD...)
uint8_t rst_time_us
Time required for the WS2812 device(s) to reset in us.
ws2812_order order
CoColor order of the WS2812 device(s) (ex. rgb, grb, bgr...)
uint8_t * pins
Array of pins used to program WS2812 devices (Must share the same PORT! (ex. PB0, PB1,...
Data structure to hold RGB color values.
ALL PLATFORMS: WS2812 device struct to drive one or more WS2812 devices.
uint8_t rgbmap[3]
RGB map to map/convert RGB values to another color order.
uint8_t rst_time_us
Time required for WS2812 to reset in us.
uint8_t masklo
PORT masks to toggle the data pins low.
uint8_t maskhi
PORT masks to toggle the data pins high.
volatile uint8_t * port
PORT register of pins used to drive the WS2812 device(s)
Exposes the Tiny-WS2812 library interface.
void ws2812_close_tx(ws2812 *dev)
Closes a WS2812 transmission.
void ws2812_wait_rst(ws2812 *dev)
Waits for the WS2812 device to reset.
uint8_t ws2812_config(ws2812 *dev, ws2812_cfg *cfg)
Configures a WS2812 device struct.
void delay_us(uint8_t us)
Halts the program for a given ammount of microseconds.
void ws2812_prep_tx(ws2812 *dev)
Prepares the host device for data transmission.
void ws2812_tx(ws2812 *dev, ws2812_rgb *leds, size_t n_leds)
Transmits RGB values to the provided WS2812 device.
void ws2812_tx_byte(ws2812 *dev, uint8_t byte)
Transmits a byte of data to the WS2812 device.
void _ws2812_get_rgbmap(uint8_t(*rgbmap)[3], ws2812_order order)
Initializes a rgb map for a given color order.