Tiny-WS2812  1.0.0
A tiny cross-platform WS2812 LED Strip driver
Macros | Functions
ws2812.h File Reference

Exposes the Tiny-WS2812 library interface. More...

#include "ws2812_avr.h"
#include "ws2812_stm8s.h"
#include <stddef.h>
#include <stdint.h>
#include "ws2812_common.h"
Include dependency graph for ws2812.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void _ws2812_get_rgbmap (uint8_t(*rgbmap)[3], ws2812_order order)
 Initializes a rgb map for a given color order. More...
 
uint8_t ws2812_config (ws2812 *dev, ws2812_cfg *cfg)
 Configures a WS2812 device struct. More...
 
void ws2812_prep_tx (ws2812 *dev)
 Prepares the host device for data transmission. More...
 
void ws2812_tx (ws2812 *dev, ws2812_rgb *pxls, size_t n_pxls)
 Transmits RGB values to the provided WS2812 device. More...
 
void ws2812_wait_rst (ws2812 *dev)
 Waits for the WS2812 device to reset. More...
 
void ws2812_close_tx (ws2812 *dev)
 Closes a WS2812 transmission. More...
 

Detailed Description

Exposes the Tiny-WS2812 library interface.

Author
Patrick Pedersen
Date
2021-04-09

The Tiny-WS2812 library initially derives from the driver code of an open source WS2812 LED controller that I had worked on prior, and provides a nearly barebone interface to communicate with WS2812 LED devices.

The following platforms and frameworks are currently supported:

It has been developed out of the necessity to have an extremely light weight and flexible cross-platform library that can be further abstracted and used troughout my WS2812 projects, particullary on MCUs with severe memory constraints (ex. ATTiny chips), where one cannot just define an RGB array equivalent to the number of LEDs. This libraries purpose is NOT to provide fancy abstractions and functions for color correction, brightness settings, animations etc.

To summerize, this library is inteded to:

Note
Because the motivation of this library is to be as barebone as possible, it relies on a superficial understanding of the WS2812 protocol and may demand an understanding of the host platforms platform (eg. registers etc.). For quick and simple programming of WS2812 devices, where memory and processing power are not a big issue, other libraries should probably be consulted.

Definition in file ws2812.h.

Function Documentation

◆ _ws2812_get_rgbmap()

void _ws2812_get_rgbmap ( uint8_t(*)  rgbmap[3],
ws2812_order  order 
)

Initializes a rgb map for a given color order.

The following function is intended only to be used for internal library code, hence the _ prefix. It fills a 3 element byte array with the necessary offsets to map/convert RGB values to a different color order. For example, setting the order to rgb fills the rgb map with 0, 1, 2 and bgr fill the rgb map with 2, 1, 0, etc.

Definition at line 43 of file ws2812_common.c.

44 {
45  switch (order) {
46  case rbg:
47  memcpy(rgbmap, ws2812_order_rbg, 3);
48  break;
49  case brg:
50  memcpy(rgbmap, ws2812_order_brg, 3);
51  break;
52  case bgr:
53  memcpy(rgbmap, ws2812_order_bgr, 3);
54  break;
55  case grb:
56  memcpy(rgbmap, ws2812_order_grb, 3);
57  break;
58  case gbr:
59  memcpy(rgbmap, ws2812_order_gbr, 3);
60  break;
61  default: // rgb
62  memcpy(rgbmap, ws2812_order_rgb, 3);
63  break;
64  }
65 }

◆ ws2812_close_tx()

void ws2812_close_tx ( ws2812 dev)

Closes a WS2812 transmission.

The following function should be called after ending data transmission with a WS2812 device. The exact closing procedure is platform specific but will typically involve restoring stashed registers to their previous states, re-enable interrupts, wait for the WS2812 to reset by calling ws2812_wait_rst(), and potentially alter fields of the provided WS2812 device struct.

Definition at line 275 of file ws2812_avr.c.

276 {
277  if (_prep == true) {
278  SREG = _sreg_prev;
279  _prep = false;
280  ws2812_wait_rst(dev);
281  }
282 }
void ws2812_wait_rst(ws2812 *dev)
Waits for the WS2812 device to reset.
Definition: ws2812_avr.c:168

◆ ws2812_config()

uint8_t ws2812_config ( ws2812 dev,
ws2812_cfg cfg 
)

Configures a WS2812 device struct.

The following function initializes/configures a WS2812 device struct using a ws2812_cfg configuration struct.

Definition at line 126 of file ws2812_avr.c.

127 {
128  if (cfg->n_dev == 0)
129  return 1; // No devices to be driven!
130 
131  uint8_t pin_msk = 0;
132 
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]))
137  return 2; // Pins do not share same port!
138  pinMode(cfg->pins[i], OUTPUT);
139  pin_msk |= digitalPinToBitMask(cfg->pins[i]);
140  }
141  dev->port = portOutputRegister(digitalPinToPort(cfg->pins[0]));
142 #else
143  for (uint8_t i = 0; i < cfg->n_dev; i++)
144  pin_msk |= 1 << cfg->pins[i];
145 
146  *cfg->ddr = pin_msk;
147  dev->port = cfg->port;
148 #endif
149  dev->rst_time_us = cfg->rst_time_us;
150  dev->masklo = ~pin_msk & *(dev->port);
151  dev->maskhi = pin_msk | *(dev->port);
152 
153  _ws2812_get_rgbmap(&dev->rgbmap, cfg->order);
154 
155  return 0;
156 }
volatile uint8_t * ddr
Data Direction Register (ex. DDRB, DDRC, DDRD...)
Definition: ws2812_avr.h:68
uint8_t n_dev
Number of WS2812 device to drive.
Definition: ws2812_avr.h:78
volatile uint8_t * port
PORT Register (ex. PORTB, PORTC, PORTD...)
Definition: ws2812_avr.h:67
uint8_t rst_time_us
Time required for the WS2812 device(s) to reset in us.
Definition: ws2812_avr.h:76
ws2812_order order
CoColor order of the WS2812 device(s) (ex. rgb, grb, bgr...)
Definition: ws2812_avr.h:77
uint8_t * pins
Array of pins used to program WS2812 devices (Must share the same PORT! (ex. PB0, PB1,...
Definition: ws2812_avr.h:69
uint8_t rgbmap[3]
RGB map to map/convert RGB values to another color order.
Definition: ws2812_avr.h:112
uint8_t rst_time_us
Time required for WS2812 to reset in us.
Definition: ws2812_avr.h:109
uint8_t masklo
PORT masks to toggle the data pins low.
Definition: ws2812_avr.h:111
uint8_t maskhi
PORT masks to toggle the data pins high.
Definition: ws2812_avr.h:110
volatile uint8_t * port
PORT register of pins used to drive the WS2812 device(s)
Definition: ws2812_avr.h:108
void _ws2812_get_rgbmap(uint8_t(*rgbmap)[3], ws2812_order order)
Initializes a rgb map for a given color order.
Definition: ws2812_common.c:43

◆ ws2812_prep_tx()

void ws2812_prep_tx ( ws2812 dev)

Prepares the host device for data transmission.

The following function prepares the host device for data transmission. The exact preperation procedure is platform specific, but typically will involve disabling interrupts, stashing registers that may be modified when communicating to the WS2812 device and potentially preparing the passed WS2812 device struct for data transmission. For a more detailed understanding, please refer to the platform specific code of this function.

Warning
Always call this function before making any calls to ws2812_tx()! Not doing so may result in undefined behaivour!

Definition at line 159 of file ws2812_avr.c.

160 {
161  if (_prep == false) {
162  _sreg_prev = SREG;
163  _prep = true;
164  }
165 }

◆ ws2812_tx()

void ws2812_tx ( ws2812 dev,
ws2812_rgb pxls,
size_t  n_pxls 
)

Transmits RGB values to the provided WS2812 device.

The following function transmits RGB values to the provided WS2812 device. Calling this function consecutively for the same device will continue programming LEDs after the position where the last transmission has ended. In other words, calling the function consecutively for the same device will NOT program the device from the first LED, but rather take off from where it last ended. If this is not desired, call ws2812_wait_rst() after each transmission.

Definition at line 264 of file ws2812_avr.c.

265 {
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]);
269  ws2812_tx_byte(dev, pxl[dev->rgbmap[j]]);
270  }
271  }
272 }
void ws2812_tx_byte(ws2812 *dev, uint8_t byte)
Transmits a byte of data to the WS2812 device.
Definition: ws2812_avr.c:192

◆ ws2812_wait_rst()

void ws2812_wait_rst ( ws2812 dev)

Waits for the WS2812 device to reset.

The following function waits for the WS2812 device to reset, thus allowing it to be overwritten from the first LED again. The reset time is configuredin the ws2812_cfg object used to initialize/configure the passed WS2812 device struct, and is recommended to be 50us according to the WS2812 datasheet, but may be set significantly lower for some WS2812 devices. Call this function if you wish to overwritte the WS2812 device after a previous ws2812_tx() call.

Note
This function does not have to be called prior calling #ws2812_end_tx() as it already contains a call to ws2812_wait_rst().

Definition at line 168 of file ws2812_avr.c.

169 {
170 #ifdef WS2812_TARGET_PLATFORM_ARDUINO_AVR
171  delayMicroseconds(dev->rst_time_us);
172 #else
173  delay_us(dev->rst_time_us);
174 #endif
175 }
void delay_us(uint8_t us)
Halts the program for a given ammount of microseconds.
Definition: ws2812_avr.c:116