-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathGwtS.cpp
226 lines (206 loc) · 5.97 KB
/
GwtS.cpp
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
/*
GWTS.cpp - Library for driving GE Color Effects
LED Holiday Lights with an Arduino
Created by Paul Martis, October 1, 2011.
http://www.digitalmisery.com
Based on Christmas Light Control by Robert Quattlebaum <[email protected]>
(http://www.deepdarc.com/2010/11/27/hacking-christmas-lights)
and Arduino adaptation by Scott Harris <[email protected]>
http://scottrharris.blogspot.com/2010/12/controlling-ge-color-effects-lights.html
*/
#include "Arduino.h"
#include "GwtS.h"
#define PD2 2
#define PD3 3
byte codeLookup[5][5][5] = {
{
{0x1D, 0x1D, 0x04, 0x04, 0x04},
{0x04, 0x04, 0x02, 0x02, 0x02},
{0x02, 0x02, 0x01, 0x01, 0x01},
{0x01, 0x01, 0x1A, 0x1A, 0x1A},
{0x1A, 0x17, 0x17, 0x17, 0x16}
},
{
{0x16, 0x16, 0x16, 0x16, 0x07},
{0x07, 0x07, 0x07, 0x07, 0x07},
{0x07, 0x07, 0x07, 0x07, 0x07},
{0x07, 0x07, 0x07, 0x08, 0x08},
{0x08, 0x08, 0x08, 0x08, 0x08}
},
{
{0x08, 0x08, 0x08, 0x08, 0x08},
{0x08, 0x08, 0x08, 0x08, 0x08},
{0x08, 0x08, 0x08, 0x08, 0x08},
{0x08, 0x08, 0x08, 0x08, 0x06},
{0x06, 0x06, 0x06, 0x06, 0x06}
},
{
{0x06, 0x06, 0x06, 0x06, 0x06},
{0x06, 0x06, 0x06, 0x06, 0x06},
{0x06, 0x06, 0x06, 0x06, 0x06},
{0x06, 0x06, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00}
},
{
{0x15, 0x0D, 0x0D, 0x0C, 0x0A},
{0x10, 0x10, 0x10, 0x10, 0x10},
{0x11, 0x11, 0x11, 0x11, 0x11},
{0x0F, 0x0F, 0x05, 0x05, 0x05},
{0x12, 0x12, 0x1B, 0x1B, 0x1C}
}
};
//#define DEBUG
unsigned char GWTS::calc_crc(unsigned char *data, unsigned char length) {
// Courtesy of rjchu and Timon - A godsend
unsigned char crc = 0;
while(length--) {
crc ^= *data++;
unsigned n = 8;
do crc = (crc & 1) ? (crc >> 1) ^ 0x8C : crc >> 1;
while(--n);
}
return crc;
}
void GWTS::pulseIR(long microsecs, int hilo) {
// we'll count down from the number of microseconds we are told to wait
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
if ( hilo )
PORTD |= _BV(PD2);
else
PORTD &= ~_BV(PD2);
delayMicroseconds(12); // hang out for 12 microseconds
int i;
for ( i = 0; i < 50; i++ )
continue;
PORTD &= ~_BV(PD2);
delayMicroseconds(12); // hang out for 12 microseconds
microsecs -= 26;
}
}
void GWTS::sendbyte(byte b) {
#ifdef DEBUG
Serial.print("Sending: ");
if ( b < 0x10 ) {Serial.print('0');}
Serial.println(b, HEX);
#endif
byte i=0;
// Send 8-N-1 data as the mouse ears communicate in.
// Data consists of 1 Start Bit, 8 Data Bits, 1 Stop Bit, and NO parity bit
// 1 bit is 417 microseconds @ 2400 baud
PORTD |= _BV(PD3);
PORTD &= ~_BV(PD3);
pulseIR(400, HIGH); // Start bit
PORTD |= _BV(PD3);
PORTD &= ~_BV(PD3);
while(i<8) {
pulseIR(400, (b>>(i++)&1)?LOW:HIGH); // Data Bits
}
PORTD |= _BV(PD3);
PORTD &= ~_BV(PD3);
pulseIR(400, LOW); // Stop bit
PORTD |= _BV(PD3);
PORTD &= ~_BV(PD3);
}
byte GWTS::bytefromhex(char hexed[2]) {
// This can be massaged if desired to allow better work. I'm just going to use a cheap ASCII offset.
// This isn't "safe" or "pretty" programming but works for this purpose.
if(hexed[1]>'9') hexed[1] -= 7; // (7 is the offset from 'A' to ':' which follows '9')
if(hexed[0]>'9') hexed[0] -= 7;
return (byte)(((hexed[0] - '0')<<4) + hexed[1] - '0');
}
GWTS::GWTS()
{
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
cmdcount = 0;
_lred = 0;
_lgreen = 0;
_lblue = 0;
_rred = 0;
_rgreen = 0;
_rblue = 0;
}
void GWTS::set_colors(uint8_t lRed, uint8_t lGreen, uint8_t lBlue, uint8_t rRed, uint8_t rGreen, uint8_t rBlue)
{
_lred = floor(lRed/51);
_lgreen = floor(lGreen/51);
_lblue = floor(lBlue/51);
_rred = floor(rRed/51);
_rgreen = floor(rGreen/51);
_rblue = floor(rBlue/51);
if (_lred > 4) _lred = 4;
if (_lgreen > 4) _lgreen = 4;
if (_lblue > 4) _lblue = 4;
if (_rred > 4) _rred = 4;
if (_rgreen > 4) _rgreen = 4;
if (_rblue > 4) _rblue = 4;
#ifdef DEBUG
//Serial.print("Left RGB Values are ");
Serial.print("LR:");
Serial.print(_lred, HEX);
Serial.print(" G:");
Serial.print(_lgreen, HEX);
Serial.print(" B:");
Serial.println(_lblue, HEX);
//Serial.print("Right RGB Values are ");
Serial.print("RR:");
Serial.print(_rred, HEX);
Serial.print(" G:");
Serial.print(_rgreen, HEX);
Serial.print(" B:");
Serial.println(_rblue, HEX);
#endif
char tempArray[2];
if ((_lred == _rred) && (_lgreen == _rgreen) && (_lblue == _rblue)) {
tempArray[0] = '9';
tempArray[1] = '1';
cmdbuf[0] = bytefromhex(tempArray); //0x91;
tempArray[0] = '0';
tempArray[1] = 'E';
cmdbuf[1] = bytefromhex(tempArray); //0x0E;
cmdbuf[2] = codeLookup[_lred][_lgreen][_lblue]; // Color code for both ears
cmdcount = 3;
checksum = calc_crc(cmdbuf, cmdcount);
}
else {
tempArray[0] = '9';
tempArray[1] = '4';
cmdbuf[0] = bytefromhex(tempArray); //0x94;
tempArray[0] = '0';
tempArray[1] = 'E';
cmdbuf[1] = bytefromhex(tempArray); //0x0E;
cmdbuf[2] = codeLookup[_lred][_lgreen][_lblue]; // Color code for the left ear
tempArray[0] = '0';
tempArray[1] = 'E';
cmdbuf[3] = bytefromhex(tempArray); //0x0E;
cmdbuf[4] = codeLookup[_rred][_rgreen][_rblue]; // Add 0x80 to color code for the right ear
tempArray[0] = '8';
tempArray[1] = '0';
cmdbuf[4] = cmdbuf[4] + bytefromhex(tempArray);
cmdcount = 6;
checksum = calc_crc(cmdbuf, cmdcount);
}
#ifdef DEBUG
int i = 0;
while ( i < cmdcount )
{
if (cmdbuf[i]<0x10) {Serial.print("0");}
Serial.print(cmdbuf[i++], HEX);
}
if (checksum<0x10) {Serial.print("0");}
Serial.print(checksum, HEX);
Serial.println("");
#endif
send_data();
}
void GWTS::send_data()
{
cli();
int j = 0;
while (j < cmdcount) {
sendbyte(cmdbuf[j++]);
}
sendbyte(checksum);
sei();
}