├── .gitignore
├── Alarm.pde
├── README.md
├── libraries
├── Button
│ ├── AlphaLicense.txt
│ ├── Button.cpp
│ ├── Button.h
│ ├── Examples
│ │ └── Button
│ │ │ └── Button.pde
│ └── keywords.txt
├── EEPROM
│ ├── EEPROM.cpp
│ ├── EEPROM.h
│ ├── examples
│ │ ├── eeprom_clear
│ │ │ └── eeprom_clear.pde
│ │ ├── eeprom_read
│ │ │ └── eeprom_read.pde
│ │ └── eeprom_write
│ │ │ └── eeprom_write.pde
│ └── keywords.txt
├── Keypad
│ ├── Examples
│ │ ├── CustomKeypad
│ │ │ └── CustomKeypad.pde
│ │ ├── DynamicKeypad
│ │ │ └── DynamicKeypad.pde
│ │ ├── EventKeypad
│ │ │ └── EventKeypad.pde
│ │ └── HelloKeypad
│ │ │ └── HelloKeypad.pde
│ ├── Keypad.cpp
│ ├── Keypad.h
│ └── keywords.txt
└── ShiftRegLCD
│ ├── ShiftRegLCD.cpp
│ ├── ShiftRegLCD.h
│ ├── examples
│ ├── CustomChar
│ │ └── CustomChar.pde
│ ├── CustomChar2
│ │ └── CustomChar2.pde
│ ├── HelloWorld
│ │ └── HelloWorld.pde
│ ├── HelloWorld2
│ │ └── HelloWorld2.pde
│ └── SerialDisplay
│ │ └── SerialDisplay.pde
│ └── keywords.txt
└── schematic
├── 4x4-Matrix-Keypad.png
├── LCD_2-wire.png
└── Relay.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 | *.dylib
9 |
10 | # Compiled Static libraries
11 | *.lai
12 | *.la
13 | *.a
14 |
--------------------------------------------------------------------------------
/Alarm.pde:
--------------------------------------------------------------------------------
1 | /*
2 | Arduino-based Burglar and Fire Alarm System GPL Source Code
3 | Copyright (C) 2010-2012 mykh
4 |
5 | This file is part of the Arduino-based Burglar and Fire Alarm System GPL Source Code ("Alarm Source Code").
6 |
7 | Alarm Source Code is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | Alarm Source Code is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with Alarm Source Code. If not, see .
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | //#define TEST
28 | //#define EVENTS_LOG_ENABLED
29 | //#define LANG_UKR
30 | //#define USE_ANALOG_FIRE_SENSOR // not tested, since I haven't an analog fire sensor. details: http://www.seeedstudio.com/wiki/Grove_-_Gas_Sensor%28MQ2%29
31 |
32 | #ifdef USE_ANALOG_FIRE_SENSOR
33 | const static float FireSensorThreshold = 0.5; // set value from 0 to 1.
34 | #endif
35 |
36 | #if defined(ARDUINO) && (ARDUINO < 19)
37 | // copied from WProgram.h
38 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
39 | const static uint8_t A0 = 54;
40 | const static uint8_t A1 = 55;
41 | const static uint8_t A2 = 56;
42 | const static uint8_t A3 = 57;
43 | const static uint8_t A4 = 58;
44 | const static uint8_t A5 = 59;
45 | const static uint8_t A6 = 60;
46 | const static uint8_t A7 = 61;
47 | const static uint8_t A8 = 62;
48 | const static uint8_t A9 = 63;
49 | const static uint8_t A10 = 64;
50 | const static uint8_t A11 = 65;
51 | const static uint8_t A12 = 66;
52 | const static uint8_t A13 = 67;
53 | const static uint8_t A14 = 68;
54 | const static uint8_t A15 = 69;
55 | #else
56 | const static uint8_t A0 = 14;
57 | const static uint8_t A1 = 15;
58 | const static uint8_t A2 = 16;
59 | const static uint8_t A3 = 17;
60 | const static uint8_t A4 = 18;
61 | const static uint8_t A5 = 19;
62 | const static uint8_t A6 = 20;
63 | const static uint8_t A7 = 21;
64 | #endif
65 | #endif
66 |
67 | #define BoolToHighLow(val) (val ? HIGH : LOW)
68 |
69 | const static byte PIN_BAD = 0xFF;
70 | // Keypad pins
71 | const static byte PinKeypad_Col0 = 3;
72 | const static byte PinKeypad_Col1 = 4;
73 | const static byte PinKeypad_Col2 = 5;
74 | const static byte PinKeypad_Col3 = 6;
75 | const static byte PinKeypad_Row0 = 7;
76 | const static byte PinKeypad_Row1 = 8;
77 | const static byte PinKeypad_Row2 = 9;
78 | const static byte PinKeypad_Row3 = 10;
79 | // ShiftRegLCD pins
80 | const static uint8_t PinLCD_Backlight = 13;
81 | const static uint8_t PinLCD_Data = 12;
82 | const static uint8_t PinLCD_Clock = 11;
83 | // Alarm pins
84 | const static byte PinAlarm_Out = A0;
85 | const static byte PinAlarm_In = A1;
86 | const static byte PinAlarm_Tamper = A2;
87 | const static byte PinLed = A3;
88 | const static byte PinFire = A4; //PIN_BAD;
89 | const static byte PinBuzzer = 2;
90 | //const static byte PinGSM_TX = 1;
91 | //const static byte PinGSM_RX = 0;
92 |
93 | const static byte SettingsMagic = 0x11;
94 | const static byte PasswordLength_Max = 17;
95 | struct AlarmSettings
96 | {
97 | byte magic;
98 | char alarmPassword1[PasswordLength_Max];
99 | // char alarmPassword2[PasswordLength_Max];
100 | // char alarmPassword3[PasswordLength_Max];
101 | // char alarmPassword4[PasswordLength_Max];
102 | char menuPassword[PasswordLength_Max];
103 | unsigned int keypadDebounceTime;
104 | unsigned int lcdBacklightTime;
105 | unsigned int beforeTurnOnDelay;
106 | unsigned int beforeAlarmDelay;
107 | unsigned int alarmOutMask;
108 | unsigned int alarmInMask;
109 | unsigned int alarmTamperMask;
110 | unsigned int alarmFireMask;
111 | unsigned int alarmStatOutCount;
112 | unsigned int alarmStatInCount;
113 | unsigned int alarmStatTamperCount;
114 | unsigned int alarmStatFireCount;
115 | }
116 | settings =
117 | {
118 | SettingsMagic, // magic
119 | "1111", // alarmPassword1,
120 | // "1111", // alarmPassword2,
121 | // "1111", // alarmPassword3,
122 | // "1111", // alarmPassword4,
123 | "0000", // menuPassword
124 | 80, // keypadDebounceTime
125 | 60000, // lcdBacklightTime
126 | 30000, // beforeTurnOnDelay
127 | 15000, // beforeAlarmDelay
128 | 0xFFFFFFFF, // alarmOutMask - all outputs are enabled
129 | 0xFFFFFFFF, // alarmInMask - all inputs are enabled
130 | 0xFFFFFFFF, // alarmTamperMask - all tampers are enabled
131 | 0xFFFFFFFF, // alarmFireMask - all fire inputs are enabled
132 | 0, // alarmStatOutCount
133 | 0, // alarmStatInCount
134 | 0, // alarmStatTamperCount
135 | 0, // alarmFireCount
136 | };
137 |
138 | void saveSettings(void)
139 | {
140 | byte* p = (byte*)&settings;
141 | for (int i = 0; i < sizeof(AlarmSettings); i++)
142 | EEPROM.write(i, p[i]);
143 | };
144 |
145 | void loadSettings(void)
146 | {
147 | byte magic = EEPROM.read(0);
148 | if (magic != SettingsMagic)
149 | {
150 | saveSettings();
151 | return;
152 | }
153 |
154 | byte* p = (byte*)&settings;
155 | for (int i = 0; i < sizeof(AlarmSettings); i++)
156 | p[i] = EEPROM.read(i);
157 | };
158 |
159 | /////////////////// ShiftRegLCDExt ///////////////////
160 |
161 | class ShiftRegLCDExt: public ShiftRegLCD
162 | {
163 | private:
164 | const uint8_t pinBacklight;
165 | public:
166 | ShiftRegLCDExt(uint8_t srdata, uint8_t srclock, uint8_t srbacklight, uint8_t enable, uint8_t lines);
167 |
168 | unsigned long lcdBacklightOnTime;
169 |
170 | void setBacklight(bool on);
171 | void setBacklightOn();
172 | void printn(char ch, int n);
173 | };
174 |
175 | ShiftRegLCDExt::ShiftRegLCDExt(uint8_t srdata, uint8_t srclock, uint8_t srbacklight, uint8_t enable, uint8_t lines)
176 | : ShiftRegLCD(srdata, srclock, enable, lines), pinBacklight(srbacklight), lcdBacklightOnTime(0)
177 | {
178 | pinMode(pinBacklight, OUTPUT);
179 | #ifdef LANG_UKR
180 | static const uint8_t ch_d[8] = {14, 10, 10, 10, 10, 31, 17, 0};
181 | static const uint8_t ch_ya[8] = {15, 17, 17, 15, 9, 9, 17, 0};
182 | static const uint8_t ch_sh[8] = {17, 17, 21, 21, 21, 21, 31, 0};
183 | static const uint8_t ch_l[8] = {15, 9, 9, 9, 9, 9, 17, 0};
184 | static const uint8_t ch_uj[8] = {6, 17, 19, 21, 25, 17, 17, 0};
185 |
186 | createChar(1, ch_d);
187 | createChar(2, ch_ya);
188 | createChar(3, ch_sh);
189 | createChar(4, ch_l);
190 | createChar(5, ch_uj);
191 | #endif
192 | }
193 |
194 | void ShiftRegLCDExt::setBacklight(bool on)
195 | {
196 | digitalWrite(pinBacklight, BoolToHighLow(on));
197 | }
198 |
199 | void ShiftRegLCDExt::setBacklightOn()
200 | {
201 | setBacklight(true);
202 | lcdBacklightOnTime = millis();
203 | }
204 |
205 | void ShiftRegLCDExt::printn(char ch, int n)
206 | {
207 | for (int i = 0; i < n; i++)
208 | print(ch);
209 | }
210 |
211 | /////////////////// ShiftRegLCDExt ///////////////////
212 |
213 | // LCD Init
214 | ShiftRegLCDExt lcd(PinLCD_Data, PinLCD_Clock, PinLCD_Backlight, TWO_WIRE, 2 /* lines */);
215 |
216 | /////////////////// KeypadExt ///////////////////
217 |
218 | class KeypadExt: public Keypad
219 | {
220 | public:
221 | const static char KeyMenu = 'a';
222 | const static char KeyEnter = 'd';
223 | const static char KeyBackspace = 'c';
224 | const static char KeyEsc = 'b';
225 | const static char KeyLeft = '*';
226 | const static char KeyRight = '#';
227 | private:
228 | const static int bufferLenMax = 16;
229 | char buffer[bufferLenMax + 1];
230 | public:
231 | KeypadExt(char *userKeymap, byte *row, byte *col, byte rows, byte cols);
232 |
233 | char getKey();
234 | char gets(bool onlyDigits = false);
235 | char* getBuffer();
236 | void setBuffer(const char* str);
237 | void clearBuffer();
238 | };
239 |
240 | KeypadExt::KeypadExt(char *userKeymap, byte *row, byte *col, byte rows, byte cols)
241 | : Keypad(userKeymap, row, col, rows, cols)
242 | {
243 | clearBuffer();
244 | }
245 |
246 | char KeypadExt::getKey()
247 | {
248 | char key = Keypad::getKey();
249 | if (key != NO_KEY)
250 | lcd.setBacklightOn();
251 | return key;
252 | }
253 |
254 | char KeypadExt::gets(bool onlyDigits)
255 | {
256 | char key = getKey();
257 | int len = strlen(buffer);
258 | switch (key)
259 | {
260 | case NO_KEY:
261 | case KeypadExt::KeyMenu:
262 | case KeypadExt::KeyEnter:
263 | case KeypadExt::KeyEsc:
264 | case KeypadExt::KeyLeft:
265 | case KeypadExt::KeyRight:
266 | break;
267 | case KeypadExt::KeyBackspace:
268 | if (len > 0)
269 | buffer[len - 1] = '\0';
270 | break;
271 | default:
272 | if (onlyDigits && !isdigit(key))
273 | break;
274 | if (len < bufferLenMax)
275 | {
276 | buffer[len] = key;
277 | buffer[len + 1] = '\0';
278 | };
279 | break;
280 | }
281 | #ifdef TEST
282 | if (key != NO_KEY)
283 | {
284 | Serial.print("Buffer ");
285 | Serial.println(buffer);
286 | }
287 | #endif
288 | return key;
289 | }
290 |
291 | char* KeypadExt::getBuffer()
292 | {
293 | return buffer;
294 | }
295 |
296 | void KeypadExt::setBuffer(const char* str)
297 | {
298 | if (strlen(str) <= bufferLenMax)
299 | strcpy(buffer, str);
300 | }
301 |
302 | void KeypadExt::clearBuffer()
303 | {
304 | buffer[0] = '\0';
305 | }
306 |
307 | /////////////////// KeypadExt ///////////////////
308 |
309 | /////////////////// ButtonExt ///////////////////
310 |
311 | class ButtonExt: public Button
312 | {
313 | protected:
314 | unsigned long pressedLastTime;
315 | unsigned int debounceTime;
316 | public:
317 | ButtonExt(uint8_t buttonPin, uint8_t buttonMode=PULLDOWN, unsigned int _debounceTime=50);
318 |
319 | bool isPressedExt();
320 | };
321 |
322 | ButtonExt::ButtonExt(uint8_t buttonPin, uint8_t buttonMode, unsigned int _debounceTime)
323 | : Button(buttonPin, buttonMode), debounceTime(_debounceTime), pressedLastTime(0)
324 | {
325 | }
326 |
327 | bool ButtonExt::isPressedExt()
328 | {
329 | bool result = Button::isPressed();
330 | return result;
331 | if (result || (debounceTime == 0))
332 | {
333 | pressedLastTime = 0;
334 | return result;
335 | };
336 | unsigned long now = millis();
337 | if (pressedLastTime == 0)
338 | {
339 | pressedLastTime = now;
340 | return false;
341 | }
342 | if (pressedLastTime > now)
343 | {
344 | if (now <= debounceTime)
345 | return false;
346 | else
347 | pressedLastTime = now - debounceTime;
348 | };
349 | result = ((now - pressedLastTime) <= debounceTime);
350 | return result;
351 | }
352 |
353 | /////////////////// ButtonExt ///////////////////
354 |
355 | // Keypad init
356 | const static byte rowsKeypad = 4;
357 | const static byte colsKeypad = 4;
358 | char keys[rowsKeypad][colsKeypad] = {
359 | {'1','2','3', 'a'},
360 | {'4','5','6', 'b'},
361 | {'7','8','9', 'c'},
362 | {'*','0','#', 'd'}
363 | };
364 |
365 | byte rowPins[rowsKeypad] = {PinKeypad_Row0, PinKeypad_Row1, PinKeypad_Row2, PinKeypad_Row3}; //connect to the row pinouts of the keypad
366 | byte colPins[colsKeypad] = {PinKeypad_Col0, PinKeypad_Col1, PinKeypad_Col2, PinKeypad_Col3}; //connect to the column pinouts of the keypad
367 |
368 | KeypadExt keypad = KeypadExt(makeKeymap(keys), rowPins, colPins, rowsKeypad, colsKeypad);
369 |
370 | /////////////////// Menu ///////////////////
371 |
372 | class MenuBase
373 | {
374 | private:
375 | const char* name;
376 | bool menuActive;
377 | public:
378 | MenuBase(const char* _name)
379 | : name(_name)
380 | {
381 | setActive(false);
382 | }
383 | virtual void setActive(bool _active)
384 | {
385 | menuActive = _active;
386 | }
387 | bool isActive(void)
388 | {
389 | return menuActive;
390 | }
391 | const char* getName()
392 | {
393 | return name;
394 | }
395 | virtual char* getHint(void)
396 | {
397 | return "";
398 | }
399 | virtual bool process(void) = 0;
400 | };
401 |
402 | class MenuItemValue
403 | {
404 | public:
405 | virtual void load(void)
406 | {
407 | keypad.clearBuffer();
408 | }
409 | virtual bool save(void)
410 | {
411 | return true;
412 | }
413 | char* getLastError()
414 | {
415 | return "Invalid input";
416 | }
417 | };
418 |
419 | class MenuItemUIntValue: public MenuItemValue
420 | {
421 | private:
422 | unsigned int* value;
423 | public:
424 | MenuItemUIntValue(unsigned int* _value)
425 | : value(_value)
426 | {
427 | }
428 | virtual void load(void)
429 | {
430 | ltoa(*value, keypad.getBuffer(), 10);
431 | }
432 | virtual bool save(void)
433 | {
434 | *value = atol(keypad.getBuffer());
435 | saveSettings();
436 | return true;
437 | }
438 | };
439 |
440 | class MenuItemMaskValue: public MenuItemValue
441 | {
442 | private:
443 | unsigned int* value;
444 | public:
445 | MenuItemMaskValue(unsigned int* _value)
446 | : value(_value)
447 | {
448 | }
449 | virtual void load(void)
450 | {
451 | ltoa((*value & 1), keypad.getBuffer(), 10);
452 | }
453 | virtual bool save(void)
454 | {
455 | *value = (atol(keypad.getBuffer()) == 0) ? 0 : 1;
456 | saveSettings();
457 | return true;
458 | }
459 | };
460 |
461 | class MenuItemStrValue: public MenuItemValue
462 | {
463 | private:
464 | char* value;
465 | public:
466 | MenuItemStrValue(char* _value)
467 | : value(_value)
468 | {
469 | }
470 | virtual void load(void)
471 | {
472 | keypad.setBuffer(value);
473 | }
474 | virtual bool save(void)
475 | {
476 | strcpy(value, keypad.getBuffer());
477 | saveSettings();
478 | return true;
479 | }
480 | };
481 |
482 | class MenuItem: public MenuBase
483 | {
484 | public:
485 | MenuItemValue* value;
486 |
487 | MenuItem(const char* _name, MenuItemValue* _value);
488 |
489 | bool process();
490 |
491 | void setActive(bool _active);
492 | char* getHint(void);
493 | void print(void);
494 | };
495 |
496 | class Menu: public MenuBase
497 | {
498 | protected:
499 | int itemCount;
500 | int currIndex;
501 | MenuBase** items;
502 | public:
503 | Menu(const char* _name, int _index, MenuBase** _item);
504 |
505 | bool process();
506 | };
507 |
508 | MenuItem::MenuItem(const char* _name, MenuItemValue* _value)
509 | : MenuBase(_name), value(_value)
510 | {
511 | }
512 |
513 | bool MenuItem::process()
514 | {
515 | char ch = keypad.gets();
516 | switch (ch)
517 | {
518 | case KeypadExt::KeyEsc:
519 | setActive(false);
520 | keypad.clearBuffer();
521 | return true;
522 | case KeypadExt::KeyEnter:
523 | if (value->save())
524 | {
525 | setActive(false);
526 | keypad.clearBuffer();
527 | return true;
528 | }
529 | {
530 | lcd.clear();
531 | lcd.print(value->getLastError());
532 | delay(2000);
533 | return false;
534 | }
535 | }
536 | if (ch != NO_KEY)
537 | print();
538 | return false;
539 | }
540 |
541 | void MenuItem::setActive(bool _active)
542 | {
543 | MenuBase::setActive(_active);
544 | if(_active)
545 | {
546 | value->load();
547 | lcd.cursor();
548 | print();
549 | }
550 | else
551 | lcd.noCursor();
552 | }
553 |
554 | char* MenuItem::getHint(void)
555 | {
556 | if (!isActive())
557 | value->load();
558 | return keypad.getBuffer();
559 | }
560 |
561 | void MenuItem::print(void)
562 | {
563 | lcd.clear();
564 | lcd.print(getName());
565 | lcd.setCursor(0, 1);
566 | lcd.print(getHint());
567 | }
568 |
569 | Menu::Menu(const char* _name, int _itemCount, MenuBase** _items)
570 | : MenuBase(_name), itemCount(_itemCount), items(_items), currIndex(0)
571 | {
572 | }
573 |
574 | bool Menu::process()
575 | {
576 | if (isActive())
577 | {
578 | char ch = keypad.getKey();
579 | switch (ch)
580 | {
581 | case KeypadExt::KeyEsc:
582 | setActive(false);
583 | return true;
584 | case KeypadExt::KeyEnter:
585 | setActive(false);
586 | items[currIndex]->setActive(true);
587 | return false;
588 | case KeypadExt::KeyLeft:
589 | if (currIndex == 0)
590 | currIndex = itemCount - 1;
591 | else
592 | currIndex--;
593 | break;
594 | case KeypadExt::KeyRight:
595 | if (currIndex == (itemCount - 1))
596 | currIndex = 0;
597 | else
598 | currIndex++;
599 | break;
600 | }
601 | lcd.clear();
602 | lcd.print(currIndex + 1);
603 | lcd.print('.');
604 | lcd.print(items[currIndex]->getName());
605 | lcd.setCursor(0, 1);
606 | lcd.print(items[currIndex]->getHint());
607 | delay(100);
608 | }
609 | else
610 | if (items[currIndex]->process())
611 | setActive(true);
612 |
613 | return false;
614 | }
615 |
616 | /////////////////// Menu ///////////////////
617 |
618 | // Menu init
619 | MenuItemUIntValue menuDebounceTimeVal(&settings.keypadDebounceTime);
620 | MenuItemUIntValue menuBeforeTurnOnDelayVal(&settings.beforeTurnOnDelay);
621 | MenuItemUIntValue menuBeforeAlarmDelayVal(&settings.beforeAlarmDelay);
622 | MenuItemUIntValue menuBacklightTimeVal(&settings.lcdBacklightTime);
623 |
624 | MenuItemStrValue menuAlarmPasswordVal(settings.alarmPassword1);
625 | MenuItemStrValue menuMenuPasswordVal(settings.menuPassword);
626 |
627 | MenuItemMaskValue menuAlarmOutVal(&settings.alarmOutMask);
628 | MenuItemMaskValue menuAlarmInVal(&settings.alarmInMask);
629 | MenuItemMaskValue menuAlarmTamperVal(&settings.alarmTamperMask);
630 | MenuItemMaskValue menuAlarmFireVal(&settings.alarmFireMask);
631 |
632 | MenuItemUIntValue menuAlarmOutStatVal(&settings.alarmStatOutCount);
633 | MenuItemUIntValue menuAlarmInStatVal(&settings.alarmStatInCount);
634 | MenuItemUIntValue menuAlarmTamperStatVal(&settings.alarmStatTamperCount);
635 | MenuItemUIntValue menuAlarmFireStatVal(&settings.alarmStatFireCount);
636 |
637 | const static int menuDelayItemCount = 4;
638 | MenuItem menuBeforeTurnOnDelay("Turn On", &menuBeforeTurnOnDelayVal);
639 | MenuItem menuItemDelayAlarm("Alarm", &menuBeforeAlarmDelayVal);
640 | MenuItem menuItemDelayDebounce("Key Debounce", &menuDebounceTimeVal);
641 | MenuItem menuItemDelayBacklight("LCD backlight", &menuBacklightTimeVal);
642 | MenuBase* menuDelayItems[menuDelayItemCount] =
643 | {
644 | &menuBeforeTurnOnDelay,
645 | &menuItemDelayAlarm,
646 | &menuItemDelayDebounce,
647 | &menuItemDelayBacklight
648 | };
649 | Menu menuDelay("Delays (in ms)", menuDelayItemCount, menuDelayItems);
650 |
651 | const static int menuPinsItemCount = 4;
652 | MenuItem menuItemAlarmOut("Out", &menuAlarmOutVal);
653 | MenuItem menuItemAlarmIn("In", &menuAlarmInVal);
654 | MenuItem menuItemAlarmTamper("Tamper", &menuAlarmTamperVal);
655 | MenuItem menuItemAlarmFire("Fire", &menuAlarmFireVal);
656 | MenuBase* menuPinsItems[menuPinsItemCount] =
657 | {
658 | &menuItemAlarmOut,
659 | &menuItemAlarmIn,
660 | &menuItemAlarmTamper,
661 | &menuItemAlarmFire
662 | };
663 | Menu menuPins("Pins mask", menuPinsItemCount, menuPinsItems);
664 |
665 | #ifdef EVENTS_LOG_ENABLED
666 | const static int menuPinsStatItemCount = 4;
667 | MenuItem menuItemAlarmOutStat("Out stat", &menuAlarmOutStatVal);
668 | MenuItem menuItemAlarmInStat("In stat", &menuAlarmInStatVal);
669 | MenuItem menuItemAlarmTamperStat("Tamper stat", &menuAlarmTamperStatVal);
670 | MenuItem menuItemAlarmFireStat("Fire stat", &menuAlarmFireStatVal);
671 | MenuBase* menuPinsStatItems[menuPinsStatItemCount] =
672 | {
673 | &menuItemAlarmOutStat,
674 | &menuItemAlarmInStat,
675 | &menuItemAlarmTamperStat,
676 | &menuItemAlarmFireStat
677 | };
678 | Menu menuPinsStat("Statistics", menuPinsStatItemCount, menuPinsStatItems);
679 | #endif
680 |
681 | const static int menuMainItemCount = 4
682 | #ifdef EVENTS_LOG_ENABLED
683 | + 1
684 | #endif
685 | ;
686 | MenuItem menuItemPasswordAlarm("Alarm Password", &menuAlarmPasswordVal);
687 | MenuItem menuItemPasswordMenu("Menu Password", &menuMenuPasswordVal);
688 | MenuBase* menuMainItems[menuMainItemCount] =
689 | {
690 | //&menuDateTime,
691 | &menuDelay,
692 | &menuPins,
693 | #ifdef EVENTS_LOG_ENABLED
694 | &menuPinsStat,
695 | #endif
696 | &menuItemPasswordAlarm,
697 | &menuItemPasswordMenu
698 | };
699 | Menu menu("", menuMainItemCount, menuMainItems);
700 |
701 | /////////////////// Alarm ////////////////////////////
702 |
703 | enum AlarmState {asBeforeArmed, asArmed, asBeforeAlarm, asAlarm, asDisarmed, asMenuPwdPromt, asMenuShow};
704 | enum AlarmLedMode {lmOff, lmOn, lmBlink};
705 |
706 | #ifdef LANG_UKR
707 | const char* lcdPasswordPromt = "BBE\1ITb KO\1 ";
708 | const char* lcdPasswordWrong = "HEBIPHU\5 KO\1";
709 | const char* lcdBeforeArmMsg1 = "\1O BBIMKHEH\2";
710 | const char* lcdBeforeArmMsg2 = "3A\4U\3U\4OCb ";
711 | const char* lcdArmModeOnMsg = "BBIMKHEHO !";
712 | const char* lcdArmModeOffMsg = "BUMKHEHO";
713 | const char* lcdMotionDetectedMsg = "PYX";
714 | const char* lcdFireDetectedMsg = "FIRE";
715 | #else
716 | const char* lcdPasswordPromt = "ENTER PASSWORD ";
717 | const char* lcdPasswordWrong = "WRONG PASSWORD";
718 | const char* lcdBeforeArmMsg1 = "WILL BE ARMED";
719 | const char* lcdBeforeArmMsg2 = "IN ";
720 | const char* lcdArmModeOnMsg = "ARMED !";
721 | const char* lcdArmModeOffMsg = "DISARMED";
722 | const char* lcdMotionDetectedMsg = "MOTION";
723 | const char* lcdFireDetectedMsg = "FIRE";
724 | #endif
725 |
726 | const char KeyAlarmOn = KeypadExt::KeyEnter;
727 | const char KeyAlarmOff = KeypadExt::KeyEnter;
728 | const char KeyAlarmMenu = 'a';
729 |
730 | class Alarm
731 | {
732 | protected:
733 | const static unsigned int lcdPrintDelay = 250;
734 | const static unsigned int lcdShowInvalidPasswordMessageTime = 2500;
735 | const static unsigned int ledBlinkTime = 500;
736 | const static byte passwordLenMax = 8;
737 |
738 | const byte pinOut;
739 | const byte pinLed;
740 | const byte pinBuzzer;
741 | const byte pinTamper;
742 | const byte pinIn;
743 | const byte pinFire;
744 |
745 | unsigned long lcdPrintLastTime;
746 | unsigned long lcdShowInvalidPasswordMessageLastTime;
747 | unsigned long ledBlinkLastTime;
748 | unsigned long currStateStartTime;
749 |
750 | bool ledOn;
751 | volatile AlarmState currState;
752 | AlarmLedMode ledMode;
753 | bool showInvalidPasswordMessage;
754 |
755 | ButtonExt btnInput;
756 | ButtonExt btnTamper;
757 | #ifndef USE_ANALOG_FIRE_SENSOR
758 | ButtonExt btnFire;
759 | #endif
760 |
761 | bool lcdCanPrint();
762 |
763 | bool passwordPromt(bool _showInvalidPasswordMessage);
764 |
765 | void setAlarm(bool on);
766 | void setBuzzer(bool on);
767 | void setLedMode(AlarmLedMode _ledMode);
768 | void setState(const AlarmState _newState);
769 | bool isFireDetected();
770 |
771 | void process_BeforeArmed();
772 | void process_Armed();
773 | void process_BeforeAlarm();
774 | void process_Alarm();
775 | void process_Disarmed();
776 | void process_MenuPwdPromt();
777 | void process_MenuShow();
778 |
779 | void enter_BeforeArmed();
780 | void enter_Armed();
781 | void enter_BeforeAlarm();
782 | void enter_Alarm();
783 | void enter_Disarmed();
784 | void enter_MenuPwdPromt();
785 | void enter_MenuShow();
786 |
787 | void leave_BeforeArmed();
788 | void leave_Armed();
789 | void leave_BeforeAlarm();
790 | void leave_Alarm();
791 | void leave_Disarmed();
792 | void leave_MenuPwdPromt();
793 | void leave_MenuShow();
794 | public:
795 | Alarm(AlarmState _state, byte _pinOut, byte _pinIn, byte _pinTamper, byte _pinFire, byte _pinLed, byte _pinBuzzer);
796 |
797 | void init();
798 |
799 | void process();
800 | };
801 |
802 | Alarm::Alarm(AlarmState _state, byte _pinOut, byte _pinIn, byte _pinTamper, byte _pinFire, byte _pinLed, byte _pinBuzzer)
803 | : currState(_state), pinOut(_pinOut), pinIn(_pinIn), pinTamper(_pinTamper), pinFire(pinFire), pinLed(_pinLed), pinBuzzer(_pinBuzzer),
804 | btnInput(_pinIn, PULLUP), btnTamper(_pinTamper, PULLUP)
805 | #ifndef USE_ANALOG_FIRE_SENSOR
806 | , btnFire(_pinFire, PULLUP)
807 | #endif
808 | {
809 | currStateStartTime = 0;
810 | lcdPrintLastTime = 0;
811 | lcdShowInvalidPasswordMessageLastTime = 0;
812 | ledBlinkLastTime = 0;
813 | ledMode = lmOff;
814 | ledOn = false;
815 | showInvalidPasswordMessage = false;
816 | if (pinOut != PIN_BAD)
817 | pinMode(pinOut, OUTPUT);
818 | if (pinLed != PIN_BAD)
819 | pinMode(pinLed, OUTPUT);
820 | if (pinBuzzer != PIN_BAD)
821 | pinMode(pinBuzzer, OUTPUT);
822 | if (pinIn != PIN_BAD)
823 | pinMode(pinIn, INPUT);
824 | if (pinTamper != PIN_BAD)
825 | pinMode(pinTamper, INPUT);
826 | #ifdef USE_ANALOG_FIRE_SENSOR
827 | if (pinFire != PIN_BAD)
828 | pinMode(pinFire, INPUT);
829 | #endif
830 | }
831 |
832 | void Alarm::init()
833 | {
834 | lcd.clear();
835 | lcd.setBacklightOn();
836 | setState(currState);
837 | }
838 |
839 | bool Alarm::lcdCanPrint()
840 | {
841 | unsigned long now = millis();
842 | if (lcdPrintLastTime > now)
843 | lcdPrintLastTime = 0;
844 | if ((now - lcdPrintLastTime) > lcdPrintDelay)
845 | {
846 | lcdPrintLastTime = now;
847 | return true;
848 | }
849 | else
850 | return false;
851 | }
852 |
853 | bool Alarm::passwordPromt(bool _showInvalidPasswordMessage)
854 | {
855 | unsigned long now = millis();
856 | if (_showInvalidPasswordMessage)
857 | {
858 | showInvalidPasswordMessage = true;
859 | lcdShowInvalidPasswordMessageLastTime = now;
860 | lcd.clear();
861 | lcd.print(lcdPasswordWrong);
862 | return false;
863 | }
864 | if (showInvalidPasswordMessage)
865 | {
866 | if (lcdShowInvalidPasswordMessageLastTime > now)
867 | lcdShowInvalidPasswordMessageLastTime = 0;
868 | if ((now - lcdShowInvalidPasswordMessageLastTime) > lcdShowInvalidPasswordMessageTime)
869 | showInvalidPasswordMessage = false;
870 | if (showInvalidPasswordMessage)
871 | {
872 | if (lcdCanPrint())
873 | {
874 | lcd.clear();
875 | lcd.print(lcdPasswordWrong);
876 | }
877 | return false;
878 | }
879 | }
880 | char key = keypad.gets();
881 | if (lcdCanPrint() || (key != NO_KEY))
882 | {
883 | lcd.clear();
884 | lcd.print(lcdPasswordPromt);
885 | lcd.setCursor(0, 1);
886 | lcd.printn('*', strlen(keypad.getBuffer()));
887 | lcd.setBacklightOn();
888 | }
889 | return (key == KeypadExt::KeyEnter);
890 | }
891 |
892 | bool Alarm::isFireDetected()
893 | {
894 | #ifdef USE_ANALOG_FIRE_SENSOR
895 | if (pinFire == PIN_BAD)
896 | return false;
897 | else
898 | {
899 | float value = (float)analogRead(pinFire) / 1024.0;
900 | return (value > FireSensorThreshold);
901 | }
902 | #else
903 | return !btnFire.isPressedExt();
904 | #endif
905 | }
906 |
907 | void Alarm::setAlarm(bool on)
908 | {
909 | if (settings.alarmOutMask & 1)
910 | digitalWrite(pinOut, BoolToHighLow(on));
911 | }
912 |
913 | void Alarm::setBuzzer(bool on)
914 | {
915 | digitalWrite(pinBuzzer, BoolToHighLow(on));
916 | }
917 |
918 | void Alarm::setLedMode(AlarmLedMode _ledMode)
919 | {
920 | ledMode = _ledMode;
921 | }
922 |
923 | void Alarm::setState(const AlarmState _newState)
924 | {
925 | switch(currState)
926 | {
927 | case asBeforeArmed:
928 | leave_BeforeArmed();
929 | break;
930 | case asArmed:
931 | leave_Armed();
932 | break;
933 | case asBeforeAlarm:
934 | leave_BeforeAlarm();
935 | break;
936 | case asAlarm:
937 | leave_Alarm();
938 | break;
939 | case asDisarmed:
940 | leave_Disarmed();
941 | break;
942 | case asMenuPwdPromt:
943 | leave_MenuPwdPromt();
944 | break;
945 | case asMenuShow:
946 | leave_MenuShow();
947 | break;
948 | };
949 | switch(_newState)
950 | {
951 | case asBeforeArmed:
952 | enter_BeforeArmed();
953 | break;
954 | case asArmed:
955 | enter_Armed();
956 | break;
957 | case asBeforeAlarm:
958 | enter_BeforeAlarm();
959 | break;
960 | case asAlarm:
961 | enter_Alarm();
962 | break;
963 | case asDisarmed:
964 | enter_Disarmed();
965 | break;
966 | case asMenuPwdPromt:
967 | enter_MenuPwdPromt();
968 | break;
969 | case asMenuShow:
970 | enter_MenuShow();
971 | break;
972 | };
973 | currState = _newState;
974 | currStateStartTime = millis();
975 | }
976 |
977 | void Alarm::process()
978 | {
979 | unsigned long now = millis();
980 | // backlight
981 | lcd.setBacklight((now - lcd.lcdBacklightOnTime) <= settings.lcdBacklightTime);
982 | // led
983 | if (ledMode == lmBlink)
984 | {
985 | if (ledBlinkLastTime > now)
986 | ledBlinkLastTime = 0;
987 | if ((now - ledBlinkLastTime) > ledBlinkTime)
988 | {
989 | ledBlinkLastTime = now;
990 | ledOn = !ledOn;
991 | }
992 | }
993 | else
994 | ledOn = (ledMode == lmOn);
995 | digitalWrite(pinLed, BoolToHighLow(ledOn));
996 | // correct start time
997 | if (currStateStartTime > now)
998 | currStateStartTime = 0;
999 |
1000 | if (currState != asAlarm)
1001 | {
1002 | if ((settings.alarmTamperMask & 1) && !btnTamper.isPressedExt())
1003 | {
1004 | #ifdef TEST
1005 | Serial.println("Tamper pin is disconnected");
1006 | #endif
1007 | setState(asAlarm);
1008 | #ifdef EVENTS_LOG_ENABLED
1009 | settings.alarmStatTamperCount++;
1010 | saveSettings();
1011 | #endif
1012 | }
1013 | }
1014 | // process
1015 | switch(currState)
1016 | {
1017 | case asBeforeArmed:
1018 | process_BeforeArmed();
1019 | break;
1020 | case asArmed:
1021 | process_Armed();
1022 | break;
1023 | case asBeforeAlarm:
1024 | process_BeforeAlarm();
1025 | break;
1026 | case asAlarm:
1027 | process_Alarm();
1028 | break;
1029 | case asDisarmed:
1030 | process_Disarmed();
1031 | break;
1032 | case asMenuPwdPromt:
1033 | process_MenuPwdPromt();
1034 | break;
1035 | case asMenuShow:
1036 | process_MenuShow();
1037 | break;
1038 | };
1039 | }
1040 |
1041 | void Alarm::enter_BeforeArmed()
1042 | {
1043 | // ? setLedMode(lmOn);
1044 | }
1045 |
1046 | void Alarm::process_BeforeArmed()
1047 | {
1048 | unsigned long workTime = millis() - currStateStartTime;
1049 | if (lcdCanPrint())
1050 | {
1051 | lcd.clear();
1052 | lcd.print(lcdBeforeArmMsg1);
1053 | lcd.setCursor(0, 1);
1054 | lcd.print(lcdBeforeArmMsg2);
1055 | lcd.print((settings.beforeTurnOnDelay - workTime) / 1000);
1056 | lcd.setBacklightOn();
1057 | }
1058 | if (workTime > settings.beforeTurnOnDelay)
1059 | setState(asArmed);
1060 | }
1061 |
1062 | void Alarm::leave_BeforeArmed()
1063 | {
1064 | lcd.clear();
1065 | }
1066 |
1067 | void Alarm::enter_Armed()
1068 | {
1069 | setLedMode(lmOn);
1070 | // to avoid false positives
1071 | keypad.getKey();
1072 | delay(200);
1073 | }
1074 |
1075 | void Alarm::process_Armed()
1076 | {
1077 | if (lcdCanPrint())
1078 | {
1079 | lcd.clear();
1080 | lcd.print(lcdArmModeOnMsg);
1081 | };
1082 |
1083 | if ((settings.alarmFireMask & 1) && isFireDetected())
1084 | {
1085 | #ifdef TEST
1086 | Serial.println("Fire detected");
1087 | #endif
1088 | setState(asBeforeAlarm);
1089 | #ifdef EVENTS_LOG_ENABLED
1090 | settings.alarmStatFireCount++;
1091 | saveSettings();
1092 | #endif
1093 | return;
1094 | }
1095 |
1096 | if ((settings.alarmInMask & 1) && !btnInput.isPressedExt())
1097 | {
1098 | #ifdef TEST
1099 | Serial.println("Input pin is disconnected");
1100 | #endif
1101 | setState(asBeforeAlarm);
1102 | #ifdef EVENTS_LOG_ENABLED
1103 | settings.alarmStatInCount++;
1104 | saveSettings();
1105 | #endif
1106 | return;
1107 | }
1108 |
1109 | char key = keypad.getKey();
1110 | if (key == NO_KEY)
1111 | return;
1112 |
1113 | if (key == KeyAlarmOff)
1114 | setState(asBeforeAlarm);
1115 | }
1116 |
1117 | void Alarm::leave_Armed()
1118 | {
1119 | setLedMode(lmOff);
1120 | lcd.clear();
1121 | }
1122 |
1123 | void Alarm::enter_BeforeAlarm()
1124 | {
1125 | setBuzzer(true);
1126 | }
1127 |
1128 | void Alarm::process_BeforeAlarm()
1129 | {
1130 | unsigned long workTime = millis() - currStateStartTime;
1131 | if (workTime > settings.beforeAlarmDelay)
1132 | setState(asAlarm);
1133 | if (passwordPromt(false))
1134 | {
1135 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.alarmPassword1) == 0);
1136 | keypad.clearBuffer();
1137 | if (pwdMatch)
1138 | setState(asDisarmed);
1139 | else
1140 | passwordPromt(true);
1141 | }
1142 | }
1143 |
1144 | void Alarm::leave_BeforeAlarm()
1145 | {
1146 | setBuzzer(false);
1147 | lcd.clear();
1148 | }
1149 |
1150 | void Alarm::enter_Alarm()
1151 | {
1152 | setAlarm(true);
1153 | setBuzzer(true);
1154 | setLedMode(lmBlink);
1155 | // TODO: Send SMS
1156 |
1157 | #ifdef EVENTS_LOG_ENABLED
1158 | settings.alarmStatOutCount++;
1159 | saveSettings();
1160 | #endif
1161 | }
1162 |
1163 | void Alarm::process_Alarm()
1164 | {
1165 | if (passwordPromt(false))
1166 | {
1167 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.alarmPassword1) == 0);
1168 | keypad.clearBuffer();
1169 | if (pwdMatch)
1170 | setState(asDisarmed);
1171 | else
1172 | passwordPromt(true);
1173 | }
1174 | }
1175 |
1176 | void Alarm::leave_Alarm()
1177 | {
1178 | setAlarm(false);
1179 | setBuzzer(false);
1180 | setLedMode(lmOff);
1181 | // ? SMS
1182 | lcd.clear();
1183 | }
1184 |
1185 | void Alarm::enter_Disarmed()
1186 | {
1187 | // to avoid false positives
1188 | keypad.getKey();
1189 | delay(200);
1190 | }
1191 |
1192 | void Alarm::process_Disarmed()
1193 | {
1194 | if (lcdCanPrint())
1195 | {
1196 | lcd.clear();
1197 | lcd.print(lcdArmModeOffMsg);
1198 | lcd.setCursor(0, 1);
1199 | if ((settings.alarmInMask & 1) && !btnInput.isPressedExt())
1200 | {
1201 | lcd.print(lcdMotionDetectedMsg);
1202 | lcd.print(" ");
1203 | }
1204 | if ((settings.alarmFireMask & 1) && isFireDetected())
1205 | lcd.print(lcdFireDetectedMsg);
1206 | }
1207 |
1208 | char key = keypad.getKey();
1209 | switch (key)
1210 | {
1211 | case KeyAlarmMenu:
1212 | setState(asMenuPwdPromt);
1213 | break;
1214 | case KeyAlarmOn:
1215 | setState(asBeforeArmed);
1216 | break;
1217 | }
1218 | }
1219 |
1220 | void Alarm::leave_Disarmed()
1221 | {
1222 | lcd.clear();
1223 | }
1224 |
1225 | void Alarm::enter_MenuPwdPromt()
1226 | {
1227 | }
1228 |
1229 | void Alarm::process_MenuPwdPromt()
1230 | {
1231 | if (passwordPromt(false))
1232 | {
1233 | bool pwdMatch = (strcmp(keypad.getBuffer(), settings.menuPassword) == 0);
1234 | keypad.clearBuffer();
1235 | if (pwdMatch)
1236 | setState(asMenuShow);
1237 | else
1238 | {
1239 | lcd.clear();
1240 | lcd.print(lcdPasswordWrong);
1241 | delay(2000);
1242 | setState(asDisarmed);
1243 | }
1244 | }
1245 | }
1246 |
1247 | void Alarm::leave_MenuPwdPromt()
1248 | {
1249 | }
1250 |
1251 | void Alarm::enter_MenuShow()
1252 | {
1253 | menu.setActive(true);
1254 | }
1255 |
1256 | void Alarm::process_MenuShow()
1257 | {
1258 | if (menu.process())
1259 | setState(asDisarmed);
1260 | }
1261 |
1262 | void Alarm::leave_MenuShow()
1263 | {
1264 | keypad.clearBuffer();
1265 | }
1266 |
1267 | /////////////////// Alarm ////////////////////////////
1268 |
1269 | // Alarm init
1270 | Alarm alarm(asBeforeArmed/*asDisarmed*/, PinAlarm_Out, PinAlarm_In, PinAlarm_Tamper,
1271 | PinFire, PinLed, PinBuzzer);
1272 |
1273 | void setup()
1274 | {
1275 | #ifdef TEST
1276 | Serial.begin(9600);
1277 | #endif
1278 | loadSettings();
1279 | keypad.setDebounceTime(settings.keypadDebounceTime);
1280 | alarm.init();
1281 | }
1282 |
1283 | void loop()
1284 | {
1285 | alarm.process();
1286 | }
1287 |
1288 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Arduino-based Burglar and Fire Alarm System
2 | ===========================================
3 | Quick video on youtube: http://youtu.be/SJTbPBYI8FU
4 |
5 | 
6 |
7 | Used Libraries
8 | ==============
9 | * Button
10 | * EEPROM
11 | * Keypad
12 | * ShiftRegLCD
13 |
--------------------------------------------------------------------------------
/libraries/Button/AlphaLicense.txt:
--------------------------------------------------------------------------------
1 | /*
2 | ||
3 | || @file AlphaLicense.txt
4 | || @version 1.0
5 | || @author Alexander Brevig
6 | || @contact alexanderbrevig@gmail.com
7 | ||
8 | || @description
9 | || | Descripbe the rights and expectations when using my code
10 | || #
11 | ||
12 | || @license
13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved.
14 | || | http://www.gnu.org/licenses/lgpl.html
15 | || #
16 | ||
17 | */
18 |
19 | All content is released into the public domain, under the terms of the GNU LGPL (latest version).
20 | All code is intellectual property, unless stated otherwise.
21 | All usage of my code is permitted, as long as the headers stay intact ( from /* to */ ) or comply to these rules:
22 | *) You are not permitted to change any of these fields, and they should stay as is:
23 | @file
24 | @version
25 | @author
26 | @contact
27 | @licence
28 | *) You are permitted to modify the @description field, remember to update the changelog
29 | *) You are permitted to add these fields
30 | @contribution
31 | This field has to be inserted immediatly after the @contact with a 'blank' line above and below (blank as in '||')
32 | The changelog should indicate what is contributed
33 | @dependencies
34 | This field has to be inserted immediatly after the @description with a 'blank' line above and below (blank as in '||')
35 | @configuration
36 | This field has to be inserted immediatly after the @description or, if existant, the @dependencies with a 'blank' line above and below (blank as in '||')
37 | *) You are permitted and expected to add to the changelog, if changes or contributions are made.
38 |
39 | Example Header (the header to this file modified according to rules)
40 | /*
41 | ||
42 | || @file AlphaLicense.txt
43 | || @version 1.0
44 | || @author Alexander Brevig
45 | || @contact alexanderbrevig@gmail.com
46 | ||
47 | || @contribution
48 | || | Name Surname - www.domain.com - contact@domain.com
49 | || #
50 | ||
51 | || @description
52 | || | Descripbe the rights and expectations when using my code
53 | || #
54 | ||
55 | || @dependencies
56 | || | This file depends on the user having accsess to the internet, in order to read the LGPL
57 | || #
58 | ||
59 | || @configuration
60 | || | No configuration needed
61 | || #
62 | ||
63 | || @license
64 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved.
65 | || | http://www.gnu.org/licenses/lgpl.html
66 | || #
67 | ||
68 | */
69 |
--------------------------------------------------------------------------------
/libraries/Button/Button.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ||
3 | || @file Button.cpp
4 | || @version 1.6
5 | || @author Alexander Brevig
6 | || @contact alexanderbrevig@gmail.com
7 | ||
8 | || @description
9 | || | Provide an easy way of making buttons
10 | || #
11 | ||
12 | || @license
13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved.
14 | || | This code is subject to AlphaLicence.txt
15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt
16 | || #
17 | ||
18 | */
19 |
20 | //include the class definition
21 | #include "Button.h"
22 |
23 | /*
24 | || <>
25 | || @parameter buttonPin sets the pin that this switch is connected to
26 | || @parameter buttonMode indicates PULLUP or PULLDOWN resistor
27 | */
28 | Button::Button(uint8_t buttonPin, uint8_t buttonMode){
29 | this->pin=buttonPin;
30 | pinMode(pin,INPUT);
31 | buttonMode==PULLDOWN ? pulldown() : pullup();
32 | state = 0;
33 | bitWrite(state,CURRENT,!mode);
34 | }
35 |
36 | /*
37 | || Set pin HIGH as default
38 | */
39 | void Button::pullup(void){
40 | mode=PULLUP;
41 | digitalWrite(pin,HIGH);
42 | }
43 |
44 | /*
45 | || Set pin LOW as default
46 | */
47 | void Button::pulldown(void){
48 | mode=PULLDOWN;
49 | //digitalWrite(pin,LOW);
50 | }
51 |
52 | /*
53 | || Return the bitWrite(state,CURRENT, of the switch
54 | */
55 | bool Button::isPressed(void){
56 | bitWrite(state,PREVIOUS,bitRead(state,CURRENT));
57 | if (digitalRead(pin) == mode){
58 | bitWrite(state,CURRENT,false);
59 | } else {
60 | bitWrite(state,CURRENT,true);
61 | }
62 | if (bitRead(state,CURRENT) != bitRead(state,PREVIOUS)){
63 | bitWrite(state,CHANGED,true);
64 | }else{
65 | bitWrite(state,CHANGED,false);
66 | }
67 | return bitRead(state,CURRENT);
68 | }
69 |
70 | /*
71 | || Return true if the button has been pressed
72 | */
73 | bool Button::wasPressed(void){
74 | if (bitRead(state,CURRENT)){
75 | return true;
76 | } else {
77 | return false;
78 | }
79 | }
80 |
81 | /*
82 | || Return true if state has been changed
83 | */
84 | bool Button::stateChanged(void){
85 | return bitRead(state,CHANGED);
86 | }
87 |
88 | /*
89 | || Return true if the button is pressed, and was not pressed before
90 | */
91 | bool Button::uniquePress(void){
92 | return (isPressed() && stateChanged());
93 | }
94 |
95 | /*
96 | || @changelog
97 | || | 2009-05-05 - Alexander Brevig : Added uniquePress()
98 | || | 2009-04-24 - Alexander Brevig : Added wasPressed()
99 | || | 2009-04-12 - Alexander Brevig : Added constructor
100 | || | Shortened logic
101 | || | 2009-04-10 - Alexander Brevig : Namechange from Switch
102 | || | 2009-04-07 - Alexander Brevig : Altered API
103 | || | 2008-10-23 - Alexander Brevig : Initial Release
104 | || | 2008-10-22 - Alexander Brevig : Class implemented
105 | || #
106 | */
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/libraries/Button/Button.h:
--------------------------------------------------------------------------------
1 | /*
2 | ||
3 | || @file Button.h
4 | || @version 1.6
5 | || @author Alexander Brevig
6 | || @contact alexanderbrevig@gmail.com
7 | ||
8 | || @description
9 | || | Provide an easy way of making buttons
10 | || #
11 | ||
12 | || @license
13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved.
14 | || | This code is subject to AlphaLicence.txt
15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt
16 | || #
17 | ||
18 | */
19 |
20 | #ifndef BUTTON_H
21 | #define BUTTON_H
22 |
23 | #if defined(ARDUINO) && (ARDUINO >= 100)
24 | #include "Arduino.h"
25 | #else
26 | #include "WProgram.h"
27 | #endif
28 |
29 | #define PULLUP HIGH
30 | #define PULLDOWN LOW
31 |
32 | #define CURRENT 0
33 | #define PREVIOUS 1
34 | #define CHANGED 2
35 |
36 | class Button{
37 | public:
38 | Button(uint8_t buttonPin, uint8_t buttonMode=PULLDOWN);
39 | void pullup();
40 | void pulldown();
41 | bool isPressed();
42 | bool wasPressed();
43 | bool stateChanged();
44 | bool uniquePress();
45 | private:
46 | uint8_t pin;
47 | uint8_t mode;
48 | uint8_t state;
49 | };
50 |
51 | #endif
52 |
53 | /*
54 | || @changelog
55 | || | 1.6 2009-05-05 - Alexander Brevig : Added uniquePress, it returns true if the state has changed AND the button is pressed
56 | || | 1.5 2009-04-24 - Alexander Brevig : Added stateChanged, @contribution http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=klickadiklick
57 | || | 1.4 2009-04-24 - Alexander Brevig : Added wasPressed, @contribution http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=klickadiklick
58 | || | 1.3 2009-04-12 - Alexander Brevig : Added constructor with one parameter Button(uint8_t buttonPin)
59 | || | 1.2 2009-04-10 - Alexander Brevig : Namechange from Switch to Button
60 | || | 1.1 2009-04-07 - Alexander Brevig : Altered API
61 | || | 1.0 2008-10-23 - Alexander Brevig : Initial Release
62 | || #
63 | */
64 |
65 |
66 |
--------------------------------------------------------------------------------
/libraries/Button/Examples/Button/Button.pde:
--------------------------------------------------------------------------------
1 | /*
2 | ||
3 | || @file Button.pde
4 | || @version 1.1
5 | || @author Alexander Brevig
6 | || @contact alexanderbrevig@gmail.com
7 | ||
8 | || @description
9 | || | Display the intuitive way of using a button when using this Hardware Abstraction class
10 | || #
11 | ||
12 | || @license
13 | || | Copyright (c) 2009 Alexander Brevig. All rights reserved.
14 | || | This code is subject to AlphaLicence.txt
15 | || | alphabeta.alexanderbrevig.com/AlphaLicense.txt
16 | || #
17 | ||
18 | */
19 |
20 | #include
21 |
22 | //create a Button object at pin 12
23 | /*
24 | || Wiring:
25 | || GND -----/ ------ pin 12
26 | */
27 | Button button = Button(12,PULLUP);
28 |
29 | void setup(){
30 | pinMode(13,OUTPUT); //debug to led 13
31 | }
32 |
33 | void loop(){
34 | if(button.isPressed()){
35 | digitalWrite(13,HIGH);
36 | }else{
37 | digitalWrite(13,LOW);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/libraries/Button/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For Buttons
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | Button KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 |
15 | isPressed KEYWORD2
16 | wasPressed KEYWORD2
17 | stateChanged KEYWORD2
18 | uniquePress KEYWORD2
19 | pullup KEYWORD2
20 | pulldown KEYWORD2
21 |
22 | #######################################
23 | # Constants (LITERAL1)
24 | #######################################
25 |
26 | PULLUP LITERAL1
27 | PULLDOWN LITERAL1
28 |
--------------------------------------------------------------------------------
/libraries/EEPROM/EEPROM.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | EEPROM.cpp - EEPROM library
3 | Copyright (c) 2006 David A. Mellis. All right reserved.
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 | */
19 |
20 | /******************************************************************************
21 | * Includes
22 | ******************************************************************************/
23 |
24 | #include
25 | #if defined(ARDUINO) && (ARDUINO >= 100)
26 | #include "Arduino.h"
27 | #else
28 | #include "WConstants.h"
29 | #endif
30 | #include "EEPROM.h"
31 |
32 | /******************************************************************************
33 | * Definitions
34 | ******************************************************************************/
35 |
36 | /******************************************************************************
37 | * Constructors
38 | ******************************************************************************/
39 |
40 | /******************************************************************************
41 | * User API
42 | ******************************************************************************/
43 |
44 | uint8_t EEPROMClass::read(int address)
45 | {
46 | return eeprom_read_byte((unsigned char *) address);
47 | }
48 |
49 | void EEPROMClass::write(int address, uint8_t value)
50 | {
51 | eeprom_write_byte((unsigned char *) address, value);
52 | }
53 |
54 | EEPROMClass EEPROM;
55 |
--------------------------------------------------------------------------------
/libraries/EEPROM/EEPROM.h:
--------------------------------------------------------------------------------
1 | /*
2 | EEPROM.h - EEPROM library
3 | Copyright (c) 2006 David A. Mellis. All right reserved.
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 | */
19 |
20 | #ifndef EEPROM_h
21 | #define EEPROM_h
22 |
23 | #include
24 |
25 | class EEPROMClass
26 | {
27 | public:
28 | uint8_t read(int);
29 | void write(int, uint8_t);
30 | };
31 |
32 | extern EEPROMClass EEPROM;
33 |
34 | #endif
35 |
36 |
--------------------------------------------------------------------------------
/libraries/EEPROM/examples/eeprom_clear/eeprom_clear.pde:
--------------------------------------------------------------------------------
1 | /*
2 | * EEPROM Clear
3 | *
4 | * Sets all of the bytes of the EEPROM to 0.
5 | */
6 |
7 | #include
8 |
9 | void setup()
10 | {
11 | // write a 0 to all 512 bytes of the EEPROM
12 | for (int i = 0; i < 512; i++)
13 | EEPROM.write(i, 0);
14 |
15 | // turn the LED on when we're done
16 | digitalWrite(13, HIGH);
17 | }
18 |
19 | void loop()
20 | {
21 | }
22 |
--------------------------------------------------------------------------------
/libraries/EEPROM/examples/eeprom_read/eeprom_read.pde:
--------------------------------------------------------------------------------
1 | /*
2 | * EEPROM Read
3 | *
4 | * Reads the value of each byte of the EEPROM and prints it
5 | * to the computer.
6 | */
7 |
8 | #include
9 |
10 | // start reading from the first byte (address 0) of the EEPROM
11 | int address = 0;
12 | byte value;
13 |
14 | void setup()
15 | {
16 | Serial.begin(9600);
17 | }
18 |
19 | void loop()
20 | {
21 | // read a byte from the current address of the EEPROM
22 | value = EEPROM.read(address);
23 |
24 | Serial.print(address);
25 | Serial.print("\t");
26 | Serial.print(value, DEC);
27 | Serial.println();
28 |
29 | // advance to the next address of the EEPROM
30 | address = address + 1;
31 |
32 | // there are only 512 bytes of EEPROM, from 0 to 511, so if we're
33 | // on address 512, wrap around to address 0
34 | if (address == 512)
35 | address = 0;
36 |
37 | delay(500);
38 | }
39 |
--------------------------------------------------------------------------------
/libraries/EEPROM/examples/eeprom_write/eeprom_write.pde:
--------------------------------------------------------------------------------
1 | /*
2 | * EEPROM Write
3 | *
4 | * Stores values read from analog input 0 into the EEPROM.
5 | * These values will stay in the EEPROM when the board is
6 | * turned off and may be retrieved later by another sketch.
7 | */
8 |
9 | #include
10 |
11 | // the current address in the EEPROM (i.e. which byte
12 | // we're going to write to next)
13 | int addr = 0;
14 |
15 | void setup()
16 | {
17 | }
18 |
19 | void loop()
20 | {
21 | // need to divide by 4 because analog inputs range from
22 | // 0 to 1023 and each byte of the EEPROM can only hold a
23 | // value from 0 to 255.
24 | int val = analogRead(0) / 4;
25 |
26 | // write the value to the appropriate byte of the EEPROM.
27 | // these values will remain there when the board is
28 | // turned off.
29 | EEPROM.write(addr, val);
30 |
31 | // advance to the next address. there are 512 bytes in
32 | // the EEPROM, so go back to 0 when we hit 512.
33 | addr = addr + 1;
34 | if (addr == 512)
35 | addr = 0;
36 |
37 | delay(100);
38 | }
39 |
--------------------------------------------------------------------------------
/libraries/EEPROM/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For Ultrasound
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | EEPROM KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 |
15 | #######################################
16 | # Constants (LITERAL1)
17 | #######################################
18 |
19 |
--------------------------------------------------------------------------------
/libraries/Keypad/Examples/CustomKeypad/CustomKeypad.pde:
--------------------------------------------------------------------------------
1 | /* @file CustomKeypad.pde
2 | || @version 1.0
3 | || @author Alexander Brevig
4 | || @contact alexanderbrevig@gmail.com
5 | ||
6 | || @description
7 | || | Demonstrates changing the keypad size and key values.
8 | || #
9 | */
10 | #include
11 |
12 | const byte ROWS = 4; //four rows
13 | const byte COLS = 4; //four columns
14 | //define the cymbols on the buttons of the keypads
15 | char hexaKeys[ROWS][COLS] = {
16 | {'0','1','2','3'},
17 | {'4','5','6','7'},
18 | {'8','9','A','B'},
19 | {'C','D','E','F'}
20 | };
21 | byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
22 | byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad
23 |
24 | //initialize an instance of class NewKeypad
25 | Keypad cusomKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
26 |
27 | void setup(){
28 | Serial.begin(9600);
29 | }
30 |
31 | void loop(){
32 | char customKey = cusomKeypad.getKey();
33 |
34 | if (customKey != NO_KEY){
35 | Serial.println(customKey);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/libraries/Keypad/Examples/DynamicKeypad/DynamicKeypad.pde:
--------------------------------------------------------------------------------
1 | /* @file DynamicKeypad.pde
2 | || @version 1.0
3 | || @author Mark Stanley
4 | || @contact mstanley@technologist.com
5 | ||
6 | || @dificulty: Intermediate
7 | ||
8 | || *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. ***
9 | ||
10 | || @description
11 | || | This is a demonstration of keypadEvents. It's used to switch between keymaps
12 | || | while using only one keypad. The main concepts being demonstrated are:
13 | || |
14 | || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding.
15 | || | How to use setHoldTime() and why.
16 | || | Making more than one thing happen with the same key.
17 | || | Assigning and changing keymaps on the fly.
18 | || |
19 | || | Another useful feature is also included with this demonstration although
20 | || | it's not really one of the concepts that I wanted to show you. If you look
21 | || | at the code in the PRESSED event you will see that the first section of that
22 | || | code is used to scroll through three different letters on each key. For
23 | || | example, pressing the '2' key will step through the letters 'd', 'e' and 'f'.
24 | || |
25 | || |
26 | || | Using the keypad events, PRESSED, HOLD and RELEASED to simplify coding
27 | || | Very simply, the PRESSED event occurs imediately upon detecting a pressed
28 | || | key and will not happen again until after a RELEASED event. When the HOLD
29 | || | event fires it always falls between PRESSED and RELEASED. However, it will
30 | || | only occur if a key has been pressed for longer than the setHoldTime() interval.
31 | || |
32 | || | How to use setHoldTime() and why
33 | || | Take a look at keypad.setHoldTime(500) in the code. It is used to set the
34 | || | time delay between a PRESSED event and the start of a HOLD event. The value
35 | || | 500 is in milliseconds (mS) and is equivalent to half a second. After pressing
36 | || | a key for 500mS the HOLD event will fire and any code contained therein will be
37 | || | executed. This event will stay active for as long as you hold the key except
38 | || | in the case of bug #1 listed above.
39 | || |
40 | || | Making more than one thing happen with the same key.
41 | || | If you look under the PRESSED event (case PRESSED:) you will see that the '#'
42 | || | is used to print a new line, Serial.println(). But take a look at the first
43 | || | half of the HOLD event and you will see the same key being used to switch back
44 | || | and forth between the letter and number keymaps that were created with alphaKeys[4][5]
45 | || | and numberKeys[4][5] respectively.
46 | || |
47 | || | Assigning and changing keymaps on the fly
48 | || | You will see that the '#' key has been designated to perform two different functions
49 | || | depending on how long you hold it down. If you press the '#' key for less than the
50 | || | setHoldTime() then it will print a new line. However, if you hold if for longer
51 | || | than that it will switch back and forth between numbers and letters. You can see the
52 | || | keymap changes in the HOLD event.
53 | || |
54 | || |
55 | || | In addition...
56 | || | You might notice a couple of things that you won't find in the Arduino language
57 | || | reference. The first would be #include . This is a standard library from
58 | || | the C programming language and though I don't normally demonstrate these types of
59 | || | things from outside the Arduino language reference I felt that its use here was
60 | || | justified by the simplicity that it brings to this sketch.
61 | || | That simplicity is provided by the two calls to isalpha(key) and isdigit(key).
62 | || | The first one is used to decide if the key that was pressed is any letter from a-z
63 | || | or A-Z and the second one decides if the key is any number from 0-9. The return
64 | || | value from these two functions is either a zero or some positive number greater
65 | || | than zero. This makes it very simple to test a key and see if it is a number or
66 | || | a letter. So when you see the following:
67 | || |
68 | || | if (isalpha(key)) // this tests to see if your key was a letter
69 | || |
70 | || | And the following may be more familiar to some but it is equivalent:
71 | || |
72 | || | if (isalpha(key) != 0) // this tests to see if your key was a letter
73 | || |
74 | || | And Finally...
75 | || | To better understand how the event handler affects your code you will need to remember
76 | || | that it gets called only when you press, hold or release a key. However, once a key
77 | || | is pressed or held then the event handler gets called at the full speed of the loop().
78 | || |
79 | || | *** THE KEYPAD REQUIRES PULL-UP RESISTORS ON THE ROW PINS. ***
80 | || #
81 | */
82 | #include
83 | #include
84 |
85 | // Define the keymaps. The blank spot (lower left) is the space character.
86 | char alphaKeys[4][3] = {
87 | { 'a','d','g' },
88 | { 'j','m','p' },
89 | { 's','v','y' },
90 | { ' ','.','#' }
91 | };
92 |
93 | char numberKeys[4][3] = {
94 | { '1','2','3' },
95 | { '4','5','6' },
96 | { '7','8','9' },
97 | { ' ','0','#' }
98 | };
99 |
100 | boolean alpha = false; // Start with the numeric keypad.
101 |
102 | char* keypadMap = (alpha == true) ? makeKeymap(alphaKeys) : makeKeymap(numberKeys);
103 |
104 | // Connect keypad ROW0, ROW1, ROW2 and ROW3 to these pins, eg. ROW0 = Arduino pin2.
105 | byte rowPins[] = { 9, 8, 7, 6 };
106 |
107 | // Connect keypad COL0, COL1 and COL2 to these pins, eg. COL0 = Arduino pin6.
108 | byte colPins[] = { 12, 11, 10 };
109 |
110 | //create a new Keypad
111 | Keypad keypad = Keypad(keypadMap, rowPins, colPins, sizeof(rowPins), sizeof(colPins));
112 |
113 | const byte ledPin = 13; // Use the LED on pin 13.
114 |
115 | void setup() {
116 | Serial.begin(9600);
117 | digitalWrite(ledPin, HIGH); // Turns the LED on.
118 | keypad.addEventListener(keypadEvent); // Add an event listener.
119 | keypad.setHoldTime(500); // Default is 1000mS
120 | keypad.setDebounceTime(250); // Default is 50mS
121 | }
122 |
123 | void loop() {
124 | char key = keypad.getKey();
125 |
126 | if (alpha) { // Flash the LED if we are using the letter keymap.
127 | digitalWrite(ledPin,!digitalRead(ledPin));
128 | delay(100);
129 | }
130 | }
131 |
132 | // Take care of some special events.
133 | void keypadEvent(KeypadEvent key) {
134 | static char virtKey = NO_KEY; // Stores the last virtual key press. (Alpha keys only)
135 | static char physKey = NO_KEY; // Stores the last physical key press. (Alpha keys only)
136 | static char buildStr[12];
137 | static byte buildCount;
138 | static byte pressCount;
139 |
140 | switch (keypad.getState())
141 | {
142 | case PRESSED:
143 | if (isalpha(key)) { // This is a letter key so we're using the letter keymap.
144 | if (physKey != key) { // New key so start with the first of 3 characters.
145 | pressCount = 0;
146 | virtKey = key;
147 | physKey = key;
148 | }
149 | else { // Pressed the same key again...
150 | virtKey++; // so select the next character on that key.
151 | pressCount++; // Tracks how many times we press the same key.
152 | }
153 | if (pressCount > 2) { // Last character reached so cycle back to start.
154 | pressCount = 0;
155 | virtKey = key;
156 | }
157 | Serial.print(virtKey); // Used for testing.
158 | }
159 | if (isdigit(key) || key == ' ' || key == '.') Serial.print(key);
160 | if (key == '#') Serial.println();
161 | break;
162 |
163 | case HOLD:
164 | if (key == '#') { // Toggle between keymaps.
165 | if (alpha == true) { // We are currently using a keymap with letters
166 | keypad.begin(*numberKeys); // and want to change to numbers.
167 | alpha = false;
168 | }
169 | else { // Or, we are currently using a keymap with numbers
170 | keypad.begin(*alphaKeys); // and want to change to letters.
171 | alpha = true;
172 | }
173 | }
174 | else { // Some key other than '#' was pressed.
175 | buildStr[buildCount++] = (isalpha(key)) ? virtKey : key;
176 | buildStr[buildCount] = '\0';
177 | Serial.println();
178 | Serial.println(buildStr);
179 | }
180 | break;
181 |
182 | case RELEASED:
183 | if (buildCount >= sizeof(buildStr)) buildCount = 0; // Our string is full. Start fresh.
184 | break;
185 |
186 | } // end switch-case
187 | } // end keypad events
188 |
--------------------------------------------------------------------------------
/libraries/Keypad/Examples/EventKeypad/EventKeypad.pde:
--------------------------------------------------------------------------------
1 | /* @file EventSerialKeypad.pde
2 | || @version 1.0
3 | || @author Alexander Brevig
4 | || @contact alexanderbrevig@gmail.com
5 | ||
6 | || @description
7 | || | Demonstrates using the KeypadEvent.
8 | || #
9 | */
10 | #include
11 |
12 | const byte ROWS = 4; //four rows
13 | const byte COLS = 4; //four columns
14 | char keys[ROWS][COLS] = {
15 | {'1','2','3','A'},
16 | {'4','5','6','B'},
17 | {'7','8','9','C'},
18 | {'#','0','*','D'}
19 | };
20 | byte rowPins[ROWS] = {2,3,4,5}; //connect to the row pinouts of the keypad
21 | byte colPins[COLS] = {6,7,8,9}; //connect to the column pinouts of the keypad
22 |
23 | Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
24 | byte ledPin = 13;
25 |
26 | boolean blink = false;
27 |
28 | void setup(){
29 | Serial.begin(9600);
30 | pinMode(ledPin, OUTPUT); // sets the digital pin as output
31 | digitalWrite(ledPin, HIGH); // sets the LED on
32 | keypad.addEventListener(keypadEvent); //add an event listener for this keypad
33 | }
34 |
35 | void loop(){
36 | char key = keypad.getKey();
37 |
38 | if (key != NO_KEY) {
39 | Serial.println(key);
40 | }
41 | if (blink){
42 | digitalWrite(ledPin,!digitalRead(ledPin));
43 | delay(100);
44 | }
45 | }
46 |
47 | //take care of some special events
48 | void keypadEvent(KeypadEvent key){
49 | switch (keypad.getState()){
50 | case PRESSED:
51 | switch (key){
52 | case '#': digitalWrite(ledPin,!digitalRead(ledPin)); break;
53 | case '*':
54 | digitalWrite(ledPin,!digitalRead(ledPin));
55 | break;
56 | }
57 | break;
58 | case RELEASED:
59 | switch (key){
60 | case '*':
61 | digitalWrite(ledPin,!digitalRead(ledPin));
62 | blink = false;
63 | break;
64 | }
65 | break;
66 | case HOLD:
67 | switch (key){
68 | case '*': blink = true; break;
69 | }
70 | break;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/libraries/Keypad/Examples/HelloKeypad/HelloKeypad.pde:
--------------------------------------------------------------------------------
1 | /* @file HelloKeypad.pde
2 | || @version 1.0
3 | || @author Alexander Brevig
4 | || @contact alexanderbrevig@gmail.com
5 | ||
6 | || @description
7 | || | Demonstrates the simplest use of the matrix Keypad library.
8 | || #
9 | */
10 | #include
11 |
12 | const byte ROWS = 4; //four rows
13 | const byte COLS = 3; //three columns
14 | char keys[ROWS][COLS] = {
15 | {'1','2','3'},
16 | {'4','5','6'},
17 | {'7','8','9'},
18 | {'#','0','*'}
19 | };
20 | byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
21 | byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad
22 |
23 | Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
24 |
25 | void setup(){
26 | Serial.begin(9600);
27 | }
28 |
29 | void loop(){
30 | char key = keypad.getKey();
31 |
32 | if (key != NO_KEY){
33 | Serial.println(key);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/libraries/Keypad/Keypad.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | ||
3 | || @file Keypad.h
4 | || @version 1.8
5 | || @author Mark Stanley, Alexander Brevig
6 | || @contact mstanley@technologist.com, alexanderbrevig@gmail.com
7 | ||
8 | || @description
9 | || | This library provides a simple interface for using matrix
10 | || | keypads. It supports the use of multiple keypads with the
11 | || | same or different sets of keys. It also supports user
12 | || | selectable pins and definable keymaps.
13 | || #
14 | ||
15 | || @license
16 | || | This library is free software; you can redistribute it and/or
17 | || | modify it under the terms of the GNU Lesser General Public
18 | || | License as published by the Free Software Foundation; version
19 | || | 2.1 of the License.
20 | || |
21 | || | This library is distributed in the hope that it will be useful,
22 | || | but WITHOUT ANY WARRANTY; without even the implied warranty of
23 | || | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 | || | Lesser General Public License for more details.
25 | || |
26 | || | You should have received a copy of the GNU Lesser General Public
27 | || | License along with this library; if not, write to the Free Software
28 | || | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 | || #
30 | ||
31 | */
32 |
33 | #include "Keypad.h"
34 |
35 | // <> Allows custom keymap. pin configuration and keypad size
36 | Keypad::Keypad(char *userKeymap, byte *row, byte *col, byte rows, byte cols)
37 | {
38 | rowPins = row;
39 | columnPins = col;
40 |
41 | size.rows = rows;
42 | size.columns = cols;
43 |
44 | begin(userKeymap);
45 |
46 | lastUpdate = 0;
47 | debounceTime = 50;
48 | holdTime = 1000;
49 | keypadEventListener = 0;
50 | currentKey = NO_KEY;
51 | state = IDLE;
52 |
53 | initializePins();
54 | }
55 |
56 | // Let the user define a keymap - assume the same row- / columncount as defined in constructor
57 | void Keypad::begin( char *userKeymap){
58 | keymap = userKeymap;
59 | }
60 |
61 | // Returns the keykode of the pressed key, or NO_KEY if no key is pressed
62 | char Keypad::getKey(){
63 | char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey()
64 | for (byte c=0; c= holdTime) && digitalRead(rowPins[r]) == LOW){
71 | transitionTo(HOLD);
72 | }
73 | // Button release
74 | if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH){
75 | transitionTo(RELEASED);
76 | currentKey = NO_KEY;
77 | }
78 | }
79 | // Button pressed event. The user pressed a button.
80 | else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW){
81 | digitalWrite(columnPins[c],HIGH); // De-activate the current column.
82 | key = keymap[c+(r*size.columns)];
83 | lastUpdate = millis();
84 | goto EVALUATE_KEY; // Save resources and do not attempt to parse to keys at a time
85 | }
86 | }
87 | digitalWrite(columnPins[c],HIGH); // De-activate the current column.
88 | }
89 |
90 | EVALUATE_KEY:
91 | if (key != NO_KEY && key != currentKey){
92 | currentKey = key;
93 | transitionTo(PRESSED);
94 | return currentKey;
95 | }
96 | else{
97 | return NO_KEY;
98 | }
99 | }
100 |
101 |
102 | KeypadState Keypad::getState(){
103 | return state;
104 | }
105 |
106 | void Keypad::setDebounceTime(unsigned int debounce){
107 | debounceTime = debounce;
108 | }
109 | void Keypad::setHoldTime(unsigned int hold){
110 | holdTime = hold;
111 | }
112 |
113 | void Keypad::addEventListener(void (*listener)(char)){
114 | keypadEventListener = listener;
115 | }
116 |
117 | //private
118 | void Keypad::transitionTo(KeypadState newState){
119 | if (state!=newState){
120 | state = newState;
121 | if (keypadEventListener!=NULL){
122 | keypadEventListener(currentKey);
123 | }
124 | }
125 | }
126 |
127 | void Keypad::initializePins(){
128 | for (byte r=0; r= 100)
37 | #include "Arduino.h"
38 | #else
39 | #include "WProgram.h"
40 | #endif
41 |
42 | #define makeKeymap(x) ((char*)x)
43 |
44 | typedef char KeypadEvent;
45 |
46 | typedef enum {
47 | IDLE=0,
48 | PRESSED,
49 | RELEASED,
50 | HOLD
51 | } KeypadState;
52 |
53 | typedef struct {
54 | byte rows : 4;
55 | byte columns : 4;
56 | } KeypadSize;
57 |
58 | const char NO_KEY = '\0';
59 | #define KEY_RELEASED NO_KEY
60 |
61 | class Keypad {
62 | public:
63 | /*
64 | Keypad();
65 | Keypad(byte row[], byte col[], byte rows, byte cols);
66 | */
67 | Keypad(char *userKeymap, byte *row, byte *col, byte rows, byte cols);
68 |
69 | //void begin(); //DEPRECATED!
70 | void begin(char *userKeymap);
71 | char getKey();
72 | KeypadState getState();
73 | void setDebounceTime(unsigned int debounce);
74 | void setHoldTime(unsigned int hold);
75 | void addEventListener(void (*listener)(char));
76 |
77 | private:
78 | void transitionTo(KeypadState newState);
79 | void initializePins();
80 |
81 | char *keymap;
82 | byte *rowPins;
83 | byte *columnPins;
84 | KeypadSize size;
85 | KeypadState state;
86 | char currentKey;
87 | unsigned long lastUpdate;
88 | unsigned int debounceTime;
89 | unsigned int holdTime;
90 | void (*keypadEventListener)(char);
91 | };
92 |
93 | #endif
94 |
95 | /*
96 | || @changelog
97 | || | 1.8 2009-07-08 - Alexander Brevig : No longer uses arrays
98 | || | 1.7 2009-06-18 - Alexander Brevig : This library is a Finite State Machine
99 | || | every time a state changes the keypadEventListener will trigger, if set
100 | || | 1.7 2009-06-18 - Alexander Brevig : Added setDebounceTime
101 | || | setHoldTime specifies the amount of microseconds before a HOLD state triggers
102 | || | 1.7 2009-06-18 - Alexander Brevig : Added transitionTo
103 | || | 1.6 2009-06-15 - Alexander Brevig : Added getState() and state variable
104 | || | 1.5 2009-05-19 - Alexander Brevig : Added setHoldTime()
105 | || | 1.4 2009-05-15 - Alexander Brevig : Added addEventListener
106 | || | 1.3 2009-05-12 - Alexander Brevig : Added lastUdate, in order to do simple debouncing
107 | || | 1.2 2009-05-09 - Alexander Brevig : Changed getKey()
108 | || | 1.1 2009-04-28 - Alexander Brevig : Modified API, and made variables private
109 | || | 1.0 2007-XX-XX - Mark Stanley : Initial Release
110 | || #
111 | */
112 |
--------------------------------------------------------------------------------
/libraries/Keypad/keywords.txt:
--------------------------------------------------------------------------------
1 | Keypad KEYWORD1
2 | KeypadEvent KEYWORD1
3 |
4 | begin KEYWORD2
5 | getKey KEYWORD2
6 | getState KEYWORD2
7 | setHoldTime KEYWORD2
8 | addEventListener KEYWORD2
9 |
10 | # this is a macro that converts 2d arrays to pointers
11 | makeKeymap KEYWORD2
12 |
13 | # this is a way to standardize the client code, help enhance the use of the name keypadEvent
14 | keypadEvent KEYWORD2
15 |
16 | NO_KEY LITERAL1
17 | KEY_RELEASED LITERAL1
18 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/ShiftRegLCD.cpp:
--------------------------------------------------------------------------------
1 | // ShiftRegLCD - Shiftregister-based LCD library for Arduino
2 | //
3 | // Connects an LCD using 2 or 3 pins from the Arduino, via an 8-bit ShiftRegister (SR from now on).
4 | //
5 | // Acknowledgements:
6 | //
7 | // Based very much on the "official" LiquidCrystal library for the Arduino:
8 | // ttp://arduino.cc/en/Reference/Libraries
9 | // and also the improved version (with examples CustomChar1 and SerialDisplay) from LadyAda:
10 | // http://web.alfredstate.edu/weimandn/arduino/LiquidCrystal_library/LiquidCrystal_index.html
11 | // and also inspired by this schematics from an unknown author (thanks to mircho on the arduino playground forum!):
12 | // http://www.scienceprog.com/interfacing-lcd-to-atmega-using-two-wires/
13 | //
14 | // Modified to work serially with the shiftOut() function, an 8-bit shiftregister (SR) and an LCD in 4-bit mode.
15 | //
16 | // Shiftregister connection description (NEW as of 2007.07.27)
17 | //
18 | // Bit #0 - N/C - not connected, used to hold a zero
19 | // Bits #1 - N/C
20 | // Bit #2 - connects to RS (Register Select) on the LCD
21 | // Bits #3 - #6 from SR connects to LCD data inputs D4 - D7.
22 | // Bit #7 - is used to enabling the enable-puls (via a diode-resistor AND "gate")
23 | //
24 | // 2 or 3 Pins required from the Arduino for Data, Clock, and Enable (optional). If not using Enable,
25 | // the Data pin is used for the enable signal by defining the same pin for Enable as for Data.
26 | // Data and Clock outputs/pins goes to the shiftregister.
27 | // LCD RW-pin hardwired to LOW (only writing to LCD). Busy Flag (BF, data bit D7) is not read.
28 | //
29 | // Any shift register should do. I used 74LS164, for the reason that's what I had at hand.
30 | //
31 | // Project homepage: http://code.google.com/p/arduinoshiftreglcd/
32 | //
33 | // History
34 | // 2009.05.23 raron, but; based mostly (as in almost verbatim) on the "official" LiquidCrystal library.
35 | // 2009.07.23 raron (yes exactly 2 months later). Incorporated some proper initialization routines
36 | // inspired (lets say copy-paste-tweaked) from LiquidCrystal library improvements from LadyAda
37 | // Also a little re-read of the datasheet for the HD44780 LCD controller.
38 | // 2009.07.25 raron - Fixed comments. I really messed up the comments before posting this, so I had to fix it.
39 | // Also renamed a function, but no improvements or functional changes.
40 | // 2009.07.27 Thanks to an excellent suggestion from mircho at the Arduiono playgrond forum,
41 | // the number of wires now required is only two!
42 | // 2009.07.28 Mircho / raron - a new modification to the schematics, and a more streamlined interface
43 | // 2009.07.30 raron - minor corrections to the comments. Fixed keyword highlights. Fixed timing to datasheet safe.
44 |
45 | #include "ShiftRegLCD.h"
46 | #include
47 | #include
48 | #include
49 | #if defined(ARDUINO) && (ARDUINO >= 100)
50 | #include "Arduino.h"
51 | #else
52 | #include "WProgram.h"
53 | #endif
54 |
55 | // Assuming 1 line 8 pixel high font
56 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable) {
57 | init(srdata, srclock, enable, 1, 0);
58 | }
59 | // Set nr. of lines, assume 8 pixel high font
60 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines) {
61 | init(srdata, srclock, enable, lines, 0);
62 | }
63 | // Set nr. of lines and font
64 | ShiftRegLCD::ShiftRegLCD(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font) {
65 | init(srdata, srclock, enable, lines, font);
66 | }
67 |
68 |
69 | void ShiftRegLCD::init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font)
70 | {
71 | _two_wire = 0;
72 | _srdata_pin = srdata; _srclock_pin = srclock; _enable_pin = enable;
73 | if (enable == TWO_WIRE)
74 | {
75 | _enable_pin = _srdata_pin;
76 | _two_wire = 1;
77 | }
78 | pinMode(_srclock_pin, OUTPUT);
79 | pinMode(_srdata_pin, OUTPUT);
80 | pinMode(_enable_pin, OUTPUT);
81 |
82 | if (lines>1)
83 | _numlines = LCD_2LINE;
84 | else
85 | _numlines = LCD_1LINE;
86 |
87 | _displayfunction = LCD_4BITMODE | _numlines;
88 |
89 | // For some displays you can select a 10 pixel high font
90 | // (Just in case I removed the neccesity to have 1-line display for this)
91 | if (font != 0)
92 | _displayfunction |= LCD_5x10DOTS;
93 | else
94 | _displayfunction |= LCD_5x8DOTS;
95 |
96 | // At this time this is for 4-bit mode only, as described above.
97 | // Page 47-ish of this (HD44780 LCD) datasheet:
98 | // http://www.datasheetarchive.com/pdf-datasheets/Datasheets-13/DSA-247674.pdf
99 | // According to datasheet, we need at least 40ms after power rises above 2.7V
100 | // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
101 | delayMicroseconds(50000);
102 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
103 | delayMicroseconds(4500); // wait more than 4.1ms
104 | // Second try
105 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
106 | delayMicroseconds(150);
107 | // Third go
108 | init4bits(LCD_FUNCTIONSET | LCD_8BITMODE);
109 |
110 | // And finally, set to 4-bit interface
111 | init4bits(LCD_FUNCTIONSET | LCD_4BITMODE);
112 |
113 | // Set # lines, font size, etc.
114 | command(LCD_FUNCTIONSET | _displayfunction);
115 | // Turn the display on with no cursor or blinking default
116 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
117 | display();
118 | // Clear it off
119 | clear();
120 | // Initialize to default text direction (for romance languages)
121 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
122 | // set the entry mode
123 | command(LCD_ENTRYMODESET | _displaymode);
124 | home();
125 | }
126 |
127 |
128 | // ********** high level commands, for the user! **********
129 | void ShiftRegLCD::clear()
130 | {
131 | command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
132 | delayMicroseconds(2000); // this command takes a long time!
133 | }
134 |
135 | void ShiftRegLCD::home()
136 | {
137 | command(LCD_RETURNHOME); // set cursor position to zero
138 | delayMicroseconds(2000); // this command takes a long time!
139 | }
140 |
141 | void ShiftRegLCD::setCursor(uint8_t col, uint8_t row)
142 | {
143 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
144 | if ( row > _numlines )
145 | row = _numlines-1; // we count rows starting w/0
146 | command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
147 | }
148 |
149 | // Turn the display on/off (quickly)
150 | void ShiftRegLCD::noDisplay() {
151 | _displaycontrol &= ~LCD_DISPLAYON;
152 | command(LCD_DISPLAYCONTROL | _displaycontrol);
153 | }
154 | void ShiftRegLCD::display() {
155 | _displaycontrol |= LCD_DISPLAYON;
156 | command(LCD_DISPLAYCONTROL | _displaycontrol);
157 | }
158 |
159 | // Turns the underline cursor on/off
160 | void ShiftRegLCD::noCursor() {
161 | _displaycontrol &= ~LCD_CURSORON;
162 | command(LCD_DISPLAYCONTROL | _displaycontrol);
163 | }
164 | void ShiftRegLCD::cursor() {
165 | _displaycontrol |= LCD_CURSORON;
166 | command(LCD_DISPLAYCONTROL | _displaycontrol);
167 | }
168 |
169 | // Turn on and off the blinking cursor
170 | void ShiftRegLCD::noBlink() {
171 | _displaycontrol &= ~LCD_BLINKON;
172 | command(LCD_DISPLAYCONTROL | _displaycontrol);
173 | }
174 | void ShiftRegLCD::blink() {
175 | _displaycontrol |= LCD_BLINKON;
176 | command(LCD_DISPLAYCONTROL | _displaycontrol);
177 | }
178 |
179 | // These commands scroll the display without changing the RAM
180 | void ShiftRegLCD::scrollDisplayLeft(void) {
181 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
182 | }
183 | void ShiftRegLCD::scrollDisplayRight(void) {
184 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
185 | }
186 |
187 | // This is for text that flows Left to Right
188 | void ShiftRegLCD::shiftLeft(void) {
189 | _displaymode |= LCD_ENTRYLEFT;
190 | command(LCD_ENTRYMODESET | _displaymode);
191 | }
192 |
193 | // This is for text that flows Right to Left
194 | void ShiftRegLCD::shiftRight(void) {
195 | _displaymode &= ~LCD_ENTRYLEFT;
196 | command(LCD_ENTRYMODESET | _displaymode);
197 | }
198 |
199 | // This will 'right justify' text from the cursor
200 | void ShiftRegLCD::shiftIncrement(void) {
201 | _displaymode |= LCD_ENTRYSHIFTINCREMENT;
202 | command(LCD_ENTRYMODESET | _displaymode);
203 | }
204 |
205 | // This will 'left justify' text from the cursor
206 | void ShiftRegLCD::shiftDecrement(void) {
207 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
208 | command(LCD_ENTRYMODESET | _displaymode);
209 | }
210 |
211 | // Allows us to fill the first 8 CGRAM locations with custom characters
212 | void ShiftRegLCD::createChar(uint8_t location, const uint8_t charmap[]) {
213 | location &= 0x7; // we only have 8 locations 0-7
214 | command(LCD_SETCGRAMADDR | location << 3);
215 | for (int i=0; i<8; i++) {
216 | write(charmap[i]);
217 | }
218 | command(LCD_SETDDRAMADDR); // Reset display to display text (from pos. 0)
219 | }
220 |
221 | // ********************
222 |
223 | void ShiftRegLCD::command(uint8_t value) {
224 | send(value, LOW);
225 | }
226 |
227 | #if defined(ARDUINO) && (ARDUINO >= 100)
228 | size_t ShiftRegLCD::write(uint8_t value) {
229 | send(value, HIGH);
230 | return 1;
231 | }
232 | #else
233 | void ShiftRegLCD::write(uint8_t value) {
234 | send(value, HIGH);
235 | }
236 | #endif
237 |
238 | // For sending data via the shiftregister
239 | void ShiftRegLCD::send(uint8_t value, uint8_t mode) {
240 | uint8_t val1, val2;
241 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister
242 | digitalWrite( _enable_pin, LOW );
243 | mode = mode ? SR_RS_BIT : 0; // RS bit; LOW: command. HIGH: character.
244 | val1 = mode | SR_EN_BIT | ((value >> 1) & 0x78); // upper nibble
245 | val2 = mode | SR_EN_BIT | ((value << 3) & 0x78); // lower nibble
246 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
247 | digitalWrite( _enable_pin, HIGH );
248 | delayMicroseconds(1); // enable pulse must be >450ns
249 | digitalWrite( _enable_pin, LOW );
250 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister
251 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val2 );
252 | digitalWrite( _enable_pin, HIGH );
253 | delayMicroseconds(1); // enable pulse must be >450ns
254 | digitalWrite( _enable_pin, LOW );
255 | delayMicroseconds(40); // commands need > 37us to settle
256 | }
257 |
258 | // For sending data when initializing the display to 4-bit
259 | void ShiftRegLCD::init4bits(uint8_t value) {
260 | uint8_t val1;
261 | if ( _two_wire ) shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, 0x00 ); // clear shiftregister
262 | digitalWrite( _enable_pin, LOW );
263 | val1 = SR_EN_BIT | ((value >> 1) & 0x78);
264 | shiftOut ( _srdata_pin, _srclock_pin, MSBFIRST, val1 );
265 | digitalWrite( _enable_pin, HIGH );
266 | delayMicroseconds(1); // enable pulse must be >450ns
267 | digitalWrite( _enable_pin, LOW );
268 | delayMicroseconds(40); // commands need > 37us to settle
269 | }
270 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/ShiftRegLCD.h:
--------------------------------------------------------------------------------
1 | #ifndef ShiftRegLCD_h
2 | #define ShiftRegLCD_h
3 |
4 | #include
5 | #include "Print.h"
6 |
7 | // commands
8 | #define LCD_CLEARDISPLAY 0x01
9 | #define LCD_RETURNHOME 0x02
10 | #define LCD_ENTRYMODESET 0x04
11 | #define LCD_DISPLAYCONTROL 0x08
12 | #define LCD_CURSORSHIFT 0x10
13 | #define LCD_FUNCTIONSET 0x20
14 | #define LCD_SETCGRAMADDR 0x40
15 | #define LCD_SETDDRAMADDR 0x80
16 |
17 | // flags for display entry mode
18 | #define LCD_ENTRYRIGHT 0x00
19 | #define LCD_ENTRYLEFT 0x02
20 | #define LCD_ENTRYSHIFTINCREMENT 0x01
21 | #define LCD_ENTRYSHIFTDECREMENT 0x00
22 |
23 | // flags for display on/off control
24 | #define LCD_DISPLAYON 0x04
25 | #define LCD_DISPLAYOFF 0x00
26 | #define LCD_CURSORON 0x02
27 | #define LCD_CURSOROFF 0x00
28 | #define LCD_BLINKON 0x01
29 | #define LCD_BLINKOFF 0x00
30 |
31 | // flags for display/cursor shift
32 | #define LCD_DISPLAYMOVE 0x08
33 | #define LCD_CURSORMOVE 0x00
34 | #define LCD_MOVERIGHT 0x04
35 | #define LCD_MOVELEFT 0x00
36 |
37 | // flags for function set
38 | #define LCD_8BITMODE 0x10
39 | #define LCD_4BITMODE 0x00
40 | #define LCD_2LINE 0x08
41 | #define LCD_1LINE 0x00
42 | #define LCD_5x10DOTS 0x04
43 | #define LCD_5x8DOTS 0x00
44 |
45 | // two-wire indicator constant
46 | #define TWO_WIRE 204
47 | #define SR_RS_BIT 0x04
48 | #define SR_EN_BIT 0x80
49 |
50 |
51 | class ShiftRegLCD : public Print {
52 | public:
53 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable);
54 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable, uint8_t lines);
55 | ShiftRegLCD(uint8_t srdata, uint8_t srclockd, uint8_t enable, uint8_t lines, uint8_t font);
56 | void clear();
57 | void home();
58 |
59 | void noDisplay();
60 | void display();
61 | void noBlink();
62 | void blink();
63 | void noCursor();
64 | void cursor();
65 | void scrollDisplayLeft();
66 | void scrollDisplayRight();
67 | void printLeft();
68 | void printRight();
69 | void shiftLeft();
70 | void shiftRight();
71 | void shiftIncrement();
72 | void shiftDecrement();
73 |
74 | void createChar(uint8_t, const uint8_t[]);
75 | void setCursor(uint8_t, uint8_t);
76 | #if defined(ARDUINO) && (ARDUINO >= 100)
77 | virtual size_t write(uint8_t);
78 | #else
79 | virtual void write(uint8_t);
80 | #endif
81 | void command(uint8_t);
82 | private:
83 | void init(uint8_t srdata, uint8_t srclock, uint8_t enable, uint8_t lines, uint8_t font);
84 | void send(uint8_t, uint8_t);
85 | void init4bits(uint8_t);
86 | uint8_t _srdata_pin;
87 | uint8_t _srclock_pin;
88 | uint8_t _enable_pin;
89 | uint8_t _two_wire;
90 |
91 | uint8_t _displayfunction;
92 | uint8_t _displaycontrol;
93 | uint8_t _displaymode;
94 | uint8_t _numlines;
95 |
96 | };
97 |
98 | #endif
99 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/examples/CustomChar/CustomChar.pde:
--------------------------------------------------------------------------------
1 | // Example creating custom characters 0-7 on a HD44700 compatible LCD
2 | // using 2-wire connection to LCD
3 |
4 | #include
5 |
6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE);
7 |
8 | void setup()
9 | {
10 | uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4};
11 | uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0};
12 | uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
13 | uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
14 | uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0};
15 | uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0};
16 | uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0};
17 | uint8_t retarrow[8] = {0x1,0x1,0x5,0x9,0x1f,0x8,0x4};
18 |
19 | srlcd.createChar(0, bell);
20 | srlcd.createChar(1, note);
21 | srlcd.createChar(2, clock);
22 | srlcd.createChar(3, heart);
23 | srlcd.createChar(4, duck);
24 | srlcd.createChar(5, check);
25 | srlcd.createChar(6, cross);
26 | srlcd.createChar(7, retarrow);
27 |
28 | for (uint8_t i=8;i>0;i--) srlcd.write(i);
29 |
30 | srlcd.print(" CUSTOM CHARACTERS");
31 | }
32 |
33 | void loop()
34 | {
35 | }
36 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/examples/CustomChar2/CustomChar2.pde:
--------------------------------------------------------------------------------
1 | // Example creating custom characters 0-7 on a HD44700 compatible LCD
2 | // using 2-wire connection to LCD
3 |
4 | #include
5 |
6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE);
7 |
8 | void setup()
9 | {
10 | // very simple characters, could be used for a bar-graph
11 | uint8_t customchar[][8] ={ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F },
12 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F },
13 | { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F },
14 | { 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F },
15 | { 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F },
16 | { 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F },
17 | { 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F },
18 | { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F } };
19 |
20 |
21 | // Program the characters into the LCD
22 |
23 | for (uint8_t c = 0;c<8;c++) {
24 | srlcd.createChar(c, customchar[c]);
25 | }
26 |
27 | for (uint8_t i=0;i<8;i++) srlcd.write(i);
28 | srlcd.print("CUSTOM CHARS");
29 | for (uint8_t i=8;i>0;i--) srlcd.write(i-1);
30 | }
31 |
32 | void loop()
33 | {
34 | }
35 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/examples/HelloWorld/HelloWorld.pde:
--------------------------------------------------------------------------------
1 | // 2-wire connection to a HD44780-compatible LCD via shiftregister with:
2 | // Data (and Enable) on Arduino pin 12
3 | // Clock on Arduino pin 13
4 | //
5 | // Shiftregister bits #0 - #1 - not used (bit #0 must be set to zero)
6 | // Shiftregister bit #2 - connects to LCD RS (Register Select)
7 | // Shiftregister bits #3 - #6 on LCD data inputs D4-D7.
8 | // Shiftregister bit #7 - used for enabling the Enable puls.
9 | // LCD R/!W (or rw) hardwired to GND (write to LCD only, no reading from)
10 | //
11 | // USAGE: ShiftRegLCD LCDobjectvariablename(Datapin, Clockpin, Enablepin or TWO_WIRE [, Lines [, Font]]])
12 | // where Lines and Font are optional.
13 | // Enablepin: can be replaced by constant TWO_WIRE, if using only 2 wires.
14 | // Lines: 1 or 2 lines (or more if possible)
15 | // Font : 0 or 1, small or big font (8 or 10 pixel tall font, if available).
16 |
17 | #include
18 |
19 | ShiftRegLCD srlcd(12, 13, TWO_WIRE);
20 |
21 | void setup()
22 | {
23 | // Print a message to the LCD.
24 | srlcd.print("HELLO, WORLD!");
25 | }
26 |
27 | void loop()
28 | {
29 | }
30 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/examples/HelloWorld2/HelloWorld2.pde:
--------------------------------------------------------------------------------
1 | // 3-wire connection to a HD44780-compatible LCD via shiftregister with:
2 | // Data on pin 12
3 | // Clock on pin 13
4 | // Enable on pin 8
5 | //
6 | // Shiftregister bits #0 - #1 - not used (bit #0 must be set to zero)
7 | // Shiftregister bit #2 - connects to LCD RS (Register Select)
8 | // Shiftregister bits #3 - #6 on LCD data inputs D4-D7.
9 | // Shiftregister bit #7 - used for enabling the Enable puls.
10 | // LCD R/!W (or rw) hardwired to GND (write to LCD only, no reading from)
11 | //
12 | // USAGE: ShiftRegLCD LCDobjectvariablename(Datapin, Clockpin, Enablepin or TWO_WIRE [, Lines [, Font]]])
13 | // where Lines and Font are optional.
14 | // Enablepin: can be replaced by constant TWO_WIRE, if using only 2 wires.
15 | // Lines: 1 or 2 lines (or more if possible)
16 | // Font : 0 or 1, small or big font (8 or 10 pixel tall font, if available).
17 |
18 | #include
19 |
20 | ShiftRegLCD srlcd(12, 13, 8);
21 |
22 | void setup()
23 | {
24 | // Print a message to the LCD.
25 | srlcd.print("HELLO, WORLD!");
26 | }
27 |
28 | void loop()
29 | {
30 | }
31 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/examples/SerialDisplay/SerialDisplay.pde:
--------------------------------------------------------------------------------
1 | // Displays text sent over the serial port (e.g. from the Serial Monitor) on
2 | // an attached LCD, using 2-wire connection to the LCD.
3 |
4 | #include
5 |
6 | ShiftRegLCD srlcd(12, 13, TWO_WIRE);
7 |
8 | void setup()
9 | {
10 | Serial.begin(9600);
11 | }
12 |
13 | void loop()
14 | {
15 | // when characters arrive over the serial port...
16 | if (Serial.available()) {
17 | // wait a bit for the entire message to arrive
18 | delay(100);
19 | // clear the screen
20 | srlcd.clear();
21 | // read all the available characters
22 | while (Serial.available() > 0) {
23 | // display each character to the LCD
24 | srlcd.write(Serial.read());
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/libraries/ShiftRegLCD/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map For ShiftRegLCD
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | ShiftRegLCD KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 |
15 | clear KEYWORD2
16 | home KEYWORD2
17 | print KEYWORD2
18 | noDisplay KEYWORD2
19 | display KEYWORD2
20 | noBlink KEYWORD2
21 | blink KEYWORD2
22 | noCursor KEYWORD2
23 | cursor KEYWORD2
24 | scrollDisplayLeft KEYWORD2
25 | scrollDisplayRight KEYWORD2
26 | printLeft KEYWORD2
27 | printRight KEYWORD2
28 | shiftLeft KEYWORD2
29 | shiftRight KEYWORD2
30 | shiftIncrement KEYWORD2
31 | shiftDecrement KEYWORD2
32 | createChar KEYWORD2
33 | setCursor KEYWORD2
34 |
35 | #######################################
36 | # Constants (LITERAL1)
37 | #######################################
38 |
--------------------------------------------------------------------------------
/schematic/4x4-Matrix-Keypad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/4x4-Matrix-Keypad.png
--------------------------------------------------------------------------------
/schematic/LCD_2-wire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/LCD_2-wire.png
--------------------------------------------------------------------------------
/schematic/Relay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mykh/Burglar-and-Fire-Alarm-System-Arduino/d52fde9da445c21b4bccd23cab87b4a2e31f6893/schematic/Relay.png
--------------------------------------------------------------------------------