0,0 → 1,155 |
#include "defines.h" |
#include "NEOPIXEL.h" |
|
extern NEOPIXEL_DATA neopixel_data; |
|
void NeoPixel_Init(void) { |
|
// Clear buffer |
for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) { |
neopixel_data.values[i] = 0x0; |
} |
|
neopixel_data.offset = 0; |
|
// Output pin initially blocked |
NEOPIXEL_TRIS = 1; |
|
/* Initialize PWM module */ |
PR2 = 0x09; // 1.25us @ 32MHz |
CCP1CONbits.P1M = 0b00; // Single output, P1A modulated only |
CCP1CONbits.CCP1M = 0b1100; // PWM mode, P1A active-high, P1B active-high |
|
// Idle the output till width is specified |
CCPR1L = 0x00; |
CCP1CONbits.DC1B = 0b00; |
|
/* Initialize Timer 2 */ |
PIR1bits.TMR2IF = 0; // Clear the interrupt flag for Timer 2 |
T2CONbits.T2CKPS = 0b00; // Set a prescaler of 1:1 |
T2CONbits.TMR2ON = 1; // Enable the timer |
|
// Wait for the timer to overflow before enabling output |
while (!PIR1bits.TMR2IF); |
NEOPIXEL_TRIS = 0; |
} |
|
void NeoPixel_Offet(uint8_t value) { |
neopixel_data.offset = value; |
} |
|
void NeoPixel_Clear(void) { |
// Clear buffer |
for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) { |
neopixel_data.values[i] = 0x0; |
} |
} |
|
void NeoPixel_Set(uint8_t index, uint8_t R, uint8_t G, uint8_t B) { |
uint8_t i = ((index + neopixel_data.offset) % NEOPIXEL_LENGTH); |
|
neopixel_data.values[(i * 3) + 0] = G; |
neopixel_data.values[(i * 3) + 1] = R; |
neopixel_data.values[(i * 3) + 2] = B; |
} |
|
void NeoPixel_Or(uint8_t index, uint8_t R, uint8_t G, uint8_t B) { |
uint8_t i = ((index + neopixel_data.offset) % NEOPIXEL_LENGTH); |
|
neopixel_data.values[(i * 3) + 0] |= G; |
neopixel_data.values[(i * 3) + 1] |= R; |
neopixel_data.values[(i * 3) + 2] |= B; |
} |
|
void NeoPixel_Write_All(void) { |
for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) { |
NeoPixel_Write_One(neopixel_data.values[i]); |
} |
// Delay for 50us to latch data |
__delay_us(50); |
} |
|
void NeoPixel_Write_One(uint8_t value) { |
// Enable timer and wait for it to overflow |
T2CONbits.TMR2ON = 1; |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 7 |
if (value & 0x80) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 6 |
if (value & 0x40) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 5 |
if (value & 0x20) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 4 |
if (value & 0x10) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 3 |
if (value & 0x08) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 2 |
if (value & 0x04) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 1 |
if (value & 0x02) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
while (!PIR1bits.TMR2IF); |
|
// Set pulse width for bit 0 |
if (value & 0x01) { |
CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1) |
} else { |
CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0) |
} |
|
// Idle line low |
while (!PIR1bits.TMR2IF); |
asm("NOP"); |
asm("NOP"); |
asm("NOP"); |
asm("NOP"); |
asm("NOP"); |
CCPR1L = 0b00000000; |
|
// Disable and reset timer |
while (!PIR1bits.TMR2IF); |
asm("NOP"); |
asm("NOP"); |
T2CONbits.TMR2ON = 0; |
TMR2 = 0x0; |
} |