Last active
January 7, 2020 16:59
-
-
Save thexeno/24e3d7c8cbaba84bd3c3d028cfbc1522 to your computer and use it in GitHub Desktop.
Test firmware for the Atmega328P to communicate with the WS2812B, in line with its relative datasheet Version 5. Two chunks of data are sent, one per pixel, considering the overhead of double buffering of the PWM module.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* main.c | |
* Author : Enrico | |
* | |
* | |
*/ | |
#define F_CPU 16000000UL | |
#include <avr/interrupt.h> | |
#include <avr/pgmspace.h> | |
#include <avr/io.h> | |
#include <avr/delay.h> | |
#include <avr/sfr_defs.h> | |
#include <stdio.h> | |
#define BIT_HIGH 242 | |
#define BIT_LOW 249 | |
uint32_t color_data = 0x00005888; | |
uint32_t buff_data; | |
uint8_t rx_dummy; | |
uint8_t serial_data[55]; // just some bytes more to debug boundaries | |
volatile bit_counter = 0; | |
ISR(TIMER0_OVF_vect) | |
{ | |
TCCR0B &= ~((1 << CS00) | (1 << CS01) | (1 << CS02)); // stop timer | |
TCNT0 = 0; // reset timer | |
OCR0B = serial_data[bit_counter++]; // update dc here to keep last bit ending with value low | |
if (bit_counter <= 49) // compensate for first cycle at 255. 48 cycles in total for 2 chunks, | |
// +2 for initial low value and final double buffering which introduce latency of one ISR | |
{ | |
TCCR0B |= 1; // continue transfer | |
} | |
// after 50 pulses pwm pin is low because the pwm cycle is restored to initial value and with no compare match since timer value is 0, hence pin is still low | |
} | |
int main(void) | |
{ | |
uint16_t i, j; | |
uint8_t temp = 0; | |
//for now just fixed in a certain way (start at 0x0000) | |
temp = MCUCR; | |
/* Enable change of Interrupt Vectors */ | |
MCUCR = temp|(1<<IVCE); | |
/* Move interrupts to 0x0002 */ | |
MCUCR = temp & (~(1<<IVSEL)); | |
// Enable data pin, initial low | |
DDRD |= (1 << PIND5); | |
PORTD &= ~(1 << PORTD5); | |
// Fast PWM, no prescaler, invert and output low with max duty cycle | |
// Is very important that the PWM will end the cycle with the pwm pin low and start with the pwm pin low, to assert the LED reset | |
TCCR0A |= ((1 << WGM00) | (1 << WGM01) | (1 << COM0B1) | (1 << COM0B0)); | |
TCCR0B |= (1 << WGM02); | |
OCR0B = 255; // duty cycle, start low | |
// update in ISR after timer times out | |
TIMSK0 |= (1 << TOIE0); | |
OCR0A = 255; // period | |
sei(); | |
// prepare data from the color_data | |
// buff so is possible to add more chunks and preserve the shifted data | |
buff_data = color_data; | |
for (i = 0; i < 24; i++) | |
{ | |
if (buff_data & 0x01) | |
{ | |
serial_data[i] = BIT_HIGH; | |
} | |
else | |
{ | |
serial_data[i] = BIT_LOW; | |
} | |
buff_data = buff_data >> 1; | |
} | |
// second chunk to be shifted just to probe if the signal is correctly output from the LED | |
buff_data = 0x00505000; | |
for (; i < 49; i++) // the additional 49th bit will not be shifted out, but used to put the compare output low and triggering the reset on the WS2812 | |
{ | |
if (buff_data & 0x01) | |
{ | |
serial_data[i] = BIT_HIGH; | |
} | |
else | |
{ | |
serial_data[i] = BIT_LOW; | |
} | |
buff_data = buff_data >> 1; | |
} | |
color_data = 0x00800000; | |
TCCR0B |= 1; | |
while (1) | |
{ | |
if (bit_counter > 49) | |
{ | |
OCR0B = 255; | |
_delay_ms(50); | |
bit_counter = 0; | |
buff_data = color_data; | |
for (i = 0; i < 24; i++) | |
{ | |
if (buff_data & 0x01) | |
{ | |
serial_data[i] = BIT_HIGH; | |
} | |
else | |
{ | |
serial_data[i] = BIT_LOW; | |
} | |
buff_data = buff_data >> 1; | |
} | |
buff_data = color_data >> 1; | |
for (; i < 49; i++) | |
{ | |
if (buff_data & 0x01) | |
{ | |
serial_data[i] = BIT_HIGH; | |
} | |
else | |
{ | |
serial_data[i] = BIT_LOW; | |
} | |
buff_data = buff_data >> 1; | |
} | |
serial_data[i-1] = 255; | |
color_data = color_data >> 1; | |
if (color_data == 0) | |
{ | |
color_data = 0x00800000; | |
} | |
TCCR0B |= 1; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment