-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSmartClock.ino
385 lines (353 loc) · 9.02 KB
/
SmartClock.ino
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#include <RGBmatrixPanel.h>
#include <avr/wdt.h>
#include "WeatherIcons.h"
#define CLK 11
#define OE 9
#define LAT 10
#define A A0
#define B A1
#define C A2
#define D A3
enum state {
normal,
checkWeather,
alarm
};
state st = normal;
volatile int h = 0, m = 0, s = 0;
volatile bool getTweet = false;
int alarmH = -1, alarmM = -1;
int dayOfWeek = 0;
int dayOfMonth = 0;
int monthN = 0;
long unsigned int startTime = 0;
String hS, mS, sS;
int weatherBuf[8];
int alarmBuf[4];
char messageBuf[64];
RGBmatrixPanel matrix(A, B, C, D, CLK, LAT, OE, true, 64);
int16_t textX = matrix.width(), textMin = 0;
void setup() {
MCUSR = 0; // set for WatchdogTimer
// Enable timer5 interrupt; timer5 is 16bits
cli();
TCCR5A = 0;
TCCR5B = 0;
TCNT5 = 0; //set counter value to 0
OCR5A = 15624; // set compare match register for 1Hz, output compare register
TCCR5B |= (1 << WGM12); // set timer to CTC mode
TCCR5B |= (1 << CS12) | (1 << CS10); // set to 1024 prescalar mode
TIMSK5 |= (1 << OCIE5A); // enable timer compare interrupt
sei();
Serial.begin(115200);
delay(10);
int timeBuf[9];
int tCount = 0;
while(1) {
if(Serial.read() == '&') {
systemDelay(100);
while(Serial.available() > 0) {
if(tCount < 7) timeBuf[tCount++] = Serial.read() - '0'; // receiving the decimal value of the char number.. so 51 - 48 = 3
else timeBuf[tCount++] = (int)Serial.read();
}
break;
}
}
s = (timeBuf[4] * 10 + timeBuf[5]);
m = timeBuf[2] * 10 + timeBuf[3];
h = timeBuf[0] * 10 + timeBuf[1];
dayOfWeek = timeBuf[6];
dayOfMonth = timeBuf[8];
monthN = timeBuf[7];
matrix.begin();
matrix.setTextWrap(false);
}
void loop() {
if(getTweet) { // at every hour, this condition will run.
Serial.write(0x7E);
getTweet = false;
}
if(Serial.available() > 0) {
// Baud rate is very high, so without a long delay,
// the system ignores an incoming msg because it has not arrived yet
systemDelay(800);
checkMessage();
}
switch(st) {
case normal:
if(dayOfWeek >= 7) dayOfWeek = 0;
if(monthN >= 12) monthN = 1;
printTime();
displayNews();
break;
case checkWeather:
exitWeather();
break;
case alarm:
Serial.println("WAKE UP");
st = normal;
break;
}
matrix.swapBuffers(true);
}
/**
* @brief function to scroll text across the bottom section of the screen
*
*/
void displayNews() {
if((--textX) < textMin) textX = matrix.width();
matrix.setTextColor(matrix.ColorHSV(45, 255, 255, true));
matrix.setCursor(textX, 25);
matrix.print(messageBuf);
}
/**
* @brief function reads data and stores them into their appropriate buffers
* **Could be updated to include a single buffer**
*/
void checkMessage() {
int data = 0;
byte recData = Serial.read();
// Serial.println(recData);
if(recData == 0x3C) { // weather information
while(Serial.available() > 0) {
weatherBuf[data++] = (int)Serial.read(); // coming in as byte
}
printWeather();
startTime = millis();
st = checkWeather;
} else if(recData == 0x3F) { // alarm state
while(Serial.available() > 0) {
alarmBuf[data++] = Serial.read() - '0';
}
setAlarm();
} else if(recData == 0x2B) { // reset system
resetClock();
} else if(recData == 0x5E) {
while(Serial.available() > 0 && data < 64) {
char m = (char)Serial.read();
if(m == '#' && data != 0) messageBuf[data++] = ' ';
messageBuf[data++] = m;
}
textMin = -1 * (sizeof(messageBuf) * 5);
}
flushBuffer();
}
/**
* @brief print out weather information
*
*/
void printWeather() {
matrix.setCursor(0, 0);
matrix.fillScreen(0);
matrix.setTextColor(matrix.ColorHSV(0, 1, 150, true));
matrix.setTextSize(1);
// PRINT WEATHER ICONS
drawWeather(weatherBuf[0], 0, 0);
drawWeather(weatherBuf[1], 15, 16);
drawWeather(weatherBuf[2], 32, 0);
drawWeather(weatherBuf[3], 48, 16);
// PRINT DAY OF WEEK
matrix.setCursor(2, 24);
matrix.print(nameOfDay(dayOfWeek % 7));
matrix.setCursor(19, 8);
matrix.print(nameOfDay((dayOfWeek + 1) % 7));
matrix.setCursor(34, 24);
matrix.print(nameOfDay((dayOfWeek + 2) % 7));
matrix.setCursor(51, 8);
matrix.print(nameOfDay((dayOfWeek + 3) % 7));
// PRINT TEMP(F)
matrix.setCursor(2, 16);
matrix.print(weatherBuf[4]);
matrix.setCursor(19, 0);
matrix.print(weatherBuf[5]);
matrix.setCursor(34, 16);
matrix.print(weatherBuf[6]);
matrix.setCursor(51, 0);
matrix.print(weatherBuf[7]);
}
/**
* @brief function to print weather icon based on weather code
* Weather Code:
* 0 = thunderstorm
* 1 = Drizzle
* 2 = Rain
* 3 = Snow
* 4 = Mist
* 5 = Clear
* 6 = Tornado
* 7 = Clouds
* 8 = Fog
* 9 = IGNORE
* @param code unique weather id
* @param x x position of the image
* @param y y position of the image
*/
void drawWeather(int code, int x, int y) {
if (code == 0) matrix.drawRGBBitmap(x, y, thunderstorms, 16, 16);
else if(code == 1) matrix.drawRGBBitmap(x, y, light_rain, 16, 16);
else if(code == 2) matrix.drawRGBBitmap(x, y, rain, 16, 16);
else if(code == 3) matrix.drawRGBBitmap(x, y, snow, 16, 16);
else if(code == 4) matrix.drawRGBBitmap(x, y, showers, 16, 16);
else if(code == 5) matrix.drawRGBBitmap(x, y, sunny_period, 16, 16);
else if(code == 6) matrix.drawRGBBitmap(x, y, storm, 16, 16);
else if(code == 7) matrix.drawRGBBitmap(x, y, cloudy, 16, 16);
else if(code == 8) matrix.drawRGBBitmap(x, y, foggy, 16, 16);
}
/**
* @brief helper function to print out the time on the matrix
*
*/
void printTime() {
mS = String(m);
hS = String(h);
sS = String(s);
if(s < 10) sS = '0' + sS;
if(m < 10) mS = '0' + mS;
if(h < 10) hS = '0' + hS;
matrix.setCursor(0, 0);
matrix.fillScreen(0);
matrix.setTextColor(matrix.Color333(255, 255, 255));
matrix.setTextSize(2);
matrix.print(hS);
matrix.setCursor(19, 0);
matrix.print(":");
matrix.setCursor(26, 0);
matrix.print(mS);
matrix.setTextSize(1);
matrix.setCursor(49, 7);
matrix.print(sS);
matrix.setCursor(0, 16);
matrix.print(nameOfDay(dayOfWeek));
matrix.print(nameOfMonth(monthN));
matrix.print(dayOfMonth);
}
/**
* @brief function to get the name of the day
*
* @param dayWeek 0 - Sun
* @return String returns the string of the day
*/
String nameOfDay(int dayWeek) {
if (dayWeek == 0) return "SU";
else if(dayWeek == 1) return "MO";
else if(dayWeek == 2) return "TU";
else if(dayWeek == 3) return "WE";
else if(dayWeek == 4) return "TH";
else if(dayWeek == 5) return "FR";
else if(dayWeek == 6) return "SA";
else return "EMPTY";
}
/**
* @brief function to get the name of the month
*
* @param m int correlating with the month number
* @return String 1 - January
*/
String nameOfMonth(int m) {
if (m == 1) return " January ";
else if(m == 2) return " February ";
else if(m == 3) return " March ";
else if(m == 4) return " April ";
else if(m == 5) return " May ";
else if(m == 6) return " June ";
else if(m == 7) return " July ";
else if(m == 8) return " August ";
else if(m == 9) return " September ";
else if(m == 10) return " Octber ";
else if(m == 11) return " November ";
else if(m == 12) return " December ";
else return "EMPTY";
}
/**
* @brief function to exit weather state after 8 secs since state change elapsed
*
*/
void exitWeather() {
long unsigned int currentTime = millis();
if(currentTime - startTime > 8000) {
st = normal;
}
}
/**
* @brief helper function that sets the global variables based on the data from alarmBuf
*
*/
void setAlarm() {
alarmH = alarmBuf[0] * 10 + alarmBuf[1];
alarmM = alarmBuf[2] * 10 + alarmBuf[3];
// Serial.println(alarmH);
// Serial.println(alarmM);
}
/**
* @brief deprecated code
*
*/
void updateTime() {
s++;
if(s >= 60) {
s = 0;
m++;
if(m >= 60) {
m = 0;
h++;
if(h >= 24) {
h = 0;
}
}
}
if(alarmH == h && alarmM == m) st = alarm;
mS = String(m);
hS = String(h);
sS = String(s);
if(s < 10) sS = '0' + sS;
if(m < 10) mS = '0' + mS;
if(h < 10) hS = '0' + hS;
}
/**
* @brief function to empty out the data buffer
*
*/
void flushBuffer() {
while(Serial.available() > 0) Serial.read();
}
/**
* @brief enables WatchDogTimer and idles system to trigger it - causing reset
*
*/
void resetClock() {
wdt_enable(WDTO_30MS);
while(1) {}
}
/*
function is used to pause system. Purpose is to avoid using Delay()
@param int wait, 1000 = 1 sec
@return nothing
*/
void systemDelay(int wait) {
long unsigned int timeStamp = millis();
while ((millis() - timeStamp) < wait) { // wait designated time
// do nothing
}
}
/**
* @brief Construct a new ISR object, increments s, m, h and changes st to alarm if triggered
*
*/
ISR(TIMER5_COMPA_vect) {
s++;
if(s >= 60) {
s = 0;
m++;
if(m >= 60) {
m = 0;
h++;
getTweet = true;
if(h >= 24) {
h = 0;
dayOfMonth++;
dayOfWeek++;
}
}
}
if(alarmH == h && alarmM == m && s == 0) st = alarm;
}