Subversion Repositories Code-Repo

Rev

Rev 282 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
280 Kevin 1
#include "defines.h"
2
#include "NEOPIXEL.h"
3
 
281 Kevin 4
extern NEOPIXEL_DATA neopixel_data;
280 Kevin 5
 
281 Kevin 6
void NeoPixel_Init(void) {
280 Kevin 7
 
8
    // Clear buffer
281 Kevin 9
    for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) {
10
        neopixel_data.values[i] = 0x0;
280 Kevin 11
    }
12
 
281 Kevin 13
    neopixel_data.offset = 0;
14
 
280 Kevin 15
    // Output pin initially blocked
16
    NEOPIXEL_TRIS = 1;
17
 
18
    /* Initialize PWM module */
19
    PR2 = 0x09; // 1.25us @ 32MHz
20
    CCP1CONbits.P1M = 0b00;     // Single output, P1A modulated only
21
    CCP1CONbits.CCP1M = 0b1100; // PWM mode, P1A active-high, P1B active-high
22
 
23
    // Idle the output till width is specified
24
    CCPR1L = 0x00;
25
    CCP1CONbits.DC1B = 0b00;
26
 
27
    /* Initialize Timer 2 */
28
    PIR1bits.TMR2IF = 0;        // Clear the interrupt flag for Timer 2
29
    T2CONbits.T2CKPS = 0b00;    // Set a prescaler of 1:1
30
    T2CONbits.TMR2ON = 1;       // Enable the timer
31
 
32
    // Wait for the timer to overflow before enabling output
33
    while (!PIR1bits.TMR2IF);
34
    NEOPIXEL_TRIS = 0;
35
}
36
 
281 Kevin 37
void NeoPixel_Offet(uint8_t value) {
38
    neopixel_data.offset = value;
39
}
280 Kevin 40
 
281 Kevin 41
void NeoPixel_Clear(void) {
42
    // Clear buffer
43
    for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) {
44
        neopixel_data.values[i] = 0x0;
45
    }
280 Kevin 46
}
47
 
282 Kevin 48
void NeoPixel_Set(uint8_t index, uint8_t R, uint8_t G, uint8_t B, uint8_t multiplier) {
281 Kevin 49
    uint8_t i = ((index + neopixel_data.offset) % NEOPIXEL_LENGTH);
50
 
282 Kevin 51
    if (G == 0)
52
        neopixel_data.values[(i * 3) + 0] = 0;
53
    else
54
        neopixel_data.values[(i * 3) + 0] = (G * multiplier) - 1;
55
    if (R == 0)
56
        neopixel_data.values[(i * 3) + 1] = 0;
57
    else
58
        neopixel_data.values[(i * 3) + 1] = (R * multiplier) - 1;
59
    if (B == 0)
60
        neopixel_data.values[(i * 3) + 2] = 0;
61
    else
62
        neopixel_data.values[(i * 3) + 2] = (B * multiplier) - 1;
281 Kevin 63
}
64
 
282 Kevin 65
void NeoPixel_Or(uint8_t index, uint8_t R, uint8_t G, uint8_t B, uint8_t multiplier) {
281 Kevin 66
    uint8_t i = ((index + neopixel_data.offset) % NEOPIXEL_LENGTH);
67
 
282 Kevin 68
    if (G != 0)
69
        neopixel_data.values[(i * 3) + 0] |= (G * multiplier) - 1;
70
    if (R != 0)
71
        neopixel_data.values[(i * 3) + 1] |= (R * multiplier) - 1;
72
    if (B != 0)
73
        neopixel_data.values[(i * 3) + 2] |= (B * multiplier) - 1;
281 Kevin 74
}
75
 
280 Kevin 76
void NeoPixel_Write_All(void) {
281 Kevin 77
    for (uint8_t i = 0; i < NEOPIXEL_LENGTH * 3; i++) {
78
        NeoPixel_Write_One(neopixel_data.values[i]);
280 Kevin 79
    }
80
    // Delay for 50us to latch data
81
    __delay_us(50);
82
}
83
 
281 Kevin 84
void NeoPixel_Write_One(uint8_t value) {
280 Kevin 85
    // Enable timer and wait for it to overflow
86
    T2CONbits.TMR2ON = 1;
87
    while (!PIR1bits.TMR2IF);
88
 
89
    // Set pulse width for bit 7
90
    if (value & 0x80) {
91
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
92
    } else {
93
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
94
    }
95
    while (!PIR1bits.TMR2IF);
96
 
97
    // Set pulse width for bit 6
98
    if (value & 0x40) {
99
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
100
    } else {
101
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
102
    }
103
    while (!PIR1bits.TMR2IF);
104
 
105
    // Set pulse width for bit 5
106
    if (value & 0x20) {
107
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
108
    } else {
109
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
110
    }
111
    while (!PIR1bits.TMR2IF);
112
 
113
    // Set pulse width for bit 4
114
    if (value & 0x10) {
115
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
116
    } else {
117
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
118
    }
119
    while (!PIR1bits.TMR2IF);
120
 
121
    // Set pulse width for bit 3
122
    if (value & 0x08) {
123
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
124
    } else {
125
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
126
    }
127
    while (!PIR1bits.TMR2IF);
128
 
129
    // Set pulse width for bit 2
130
    if (value & 0x04) {
131
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
132
    } else {
133
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
134
    }
135
    while (!PIR1bits.TMR2IF);
136
 
137
    // Set pulse width for bit 1
138
    if (value & 0x02) {
139
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
140
    } else {
141
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
142
    }
143
    while (!PIR1bits.TMR2IF);
144
 
145
    // Set pulse width for bit 0
146
    if (value & 0x01) {
147
        CCPR1L = NEOPIXEL_LOGIC_1; // ~800ns high, ~450ns low (logic 1)
148
    } else {
149
        CCPR1L = NEOPIXEL_LOGIC_0; // ~400ns high, ~850ns low (logic 0)
150
    }
151
 
152
    // Idle line low
153
    while (!PIR1bits.TMR2IF);
154
    asm("NOP");
155
    asm("NOP");
156
    asm("NOP");
157
    asm("NOP");
158
    asm("NOP");
159
    CCPR1L = 0b00000000;
160
 
161
    // Disable and reset timer
162
    while (!PIR1bits.TMR2IF);
163
    asm("NOP");
164
    asm("NOP");
165
    T2CONbits.TMR2ON = 0;
166
    TMR2 = 0x0;
167
}