forked from jnutzmann/doaflip
/
led.c
244 lines (207 loc) · 4.65 KB
/
led.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#include "config.h"
#include "nutz.h"
#include "led.h"
void led_init() {
SDO_LAT = 0;
}
void delayPTime(uint8 multiplier) {
uint8 i;
for (i = 0; i < multiplier; i++) {
Nop();
}
}
/*
void writeLED(uint8 ledNum, uint8 red, uint8 green, uint8 blue) {
//for (int i = 0; i< numLeds; i++) {
writeCommTimer();
// if (i = ledNum){
writeCommand();
writeData(red);
writeData(green);
writeData(blue);
// }
waitEOS();
//}
waitGSLAT();
}
*/
void writeZero() {
SDO_LAT = 1;
Nop()
SDO_LAT = 0;
Nop();
Nop();
Nop();
Nop();
Nop();
}
void writeOne() {
SDO_LAT = 1;
Nop();
SDO_LAT = 0;
Nop();
SDO_LAT = 1; //rising edge of second pulse has to be within 0.5 * tCycle
Nop();
SDO_LAT = 0;
Nop();
}
void writeCommTimer() {
//first two zeroes determine the timing (tcycle) after device is powered up or after a GSLAT
writeZero();
writeZero();
}
void writeCommand() {
//write command in hex is 3AA, binary is 11 1010 1010
writeOne();
writeOne();
writeOne();
writeZero();
writeOne();
writeZero();
writeOne();
writeZero();
writeOne();
writeZero();
}
//end of sequence (for a single driver chip)
void waitEOS() {
SDO_LAT = 0;
delayPTime(4*8); // min 3.5 to max 5.5 times tCycle
}
//grayscale latch (for the end of a chain of driver chips)
void waitGSLAT() {
SDO_LAT = 0;
delayPTime(10*8); // minimum 8 time tCycle
}
#define PULSE() SDO_LAT = 1; SDO_LAT = 0;
void _writeZero(){
PULSE();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
Nop();
}
void _writeOne(){
PULSE();
Nop();
PULSE();
Nop();
Nop();
Nop();
Nop();
Nop();
}
void writeWord(uint8 word){
uint8 i;
for(i = 0; i < 8; i++){
if(word & 0x80)
writeOne();
else
writeZero();
word <<= 1;
}
}
void writeLED(uint8 R, uint8 G, uint8 B){
uint16 i;
uint8 word = 0x3A;
uint8 words[4];
words[0] = 0x3A;
words[1] = R;
words[2] = G;
words[3] = B;
for(i = 0; i < 8; i++){
if(word & 0x80)
writeOne();
else
writeZero();
word <<= 1;
}
for(i = 0; i < 8; i++){
if(R & 0x80)
writeOne();
else
writeZero();
R <<= 1;
}
for(i = 0; i < 8; i++){
if(G & 0x80)
writeOne();
else
writeZero();
G <<= 1;
}
for(i = 0; i < 8; i++){
if(B & 0x80)
writeOne();
else
writeZero();
B <<= 1;
}
waitEOS();
waitGSLAT();
}
void writeData(uint8 data) {
uint8 i;
for (i = 0; i < 8; i++) {
if (data & 0b10000000) {
writeOne();
} else {
writeZero();
}
data <<= 1;
}
}
int8 dc_step[2];
int16 duty_cycle[2];
int16 dc_max = 104; // Brightness seems linear up to here
// Higher than this there is no discernible change
// Probably varies based on the LED
void pwm_on(uint8 index) {
duty_cycle[index] = dc_max;
dc_step[index] = 0;
}
void pwm_off(uint8 index) {
duty_cycle[index] = 0;
dc_step[index] = 0;
}
void pwm_update() {
int i;
for (i = 0; i < 2; i++) {
if (dc_step[i] != 0) {
duty_cycle[i] += dc_step[i];
if (duty_cycle[i] >= dc_max) {
duty_cycle[i] = dc_max;
dc_step[i] = 0;
}
if (duty_cycle[i] <= 0) {
duty_cycle[i] = 0;
dc_step[i] = 0;
}
}
}
CCPR3L = duty_cycle[0] & 0b1111111100;
CCP3CONbits.DC3B = duty_cycle[0] & 0b0000000011;
CCPR5L = duty_cycle[1] & 0b1111111100;
CCP5CONbits.DC5B = duty_cycle[1] & 0b0000000011;
}
void pwm_init() {
CCP3CONbits.CCP3M = 0b1100; // 0b11xx PWM mode
CCPR3L = 0b00000000; // Duty cycle, high 8 bits
CCP3CONbits.DC3B = 0b00; // Duty cycle, low 2 bits
CCP5CONbits.CCP5M = 0b1100; // 0b11xx PWM mode
CCPR5L = 0b00000000; // Duty cycle, high 8 bits
CCP5CONbits.DC5B = 0b00; // Duty cycle, low 2 bits
dc_step[0] = 0;
dc_step[1] = 0;
duty_cycle[0] = 0;
duty_cycle[1] = 0;
pwm_update();
}
void pwm_fade(uint8 index, int8 step) {
dc_step[index] = step;
pwm_update();
}