From 833823dbeb3e8da406fe04e37ddb04ef0b1abf10 Mon Sep 17 00:00:00 2001 From: Will Bradley Date: Thu, 4 Jul 2019 09:23:44 -0700 Subject: [PATCH] Initial Commit from upstream - v1.4 --- Open_Access_Control_v4_std.ino | 1818 +++++++++++++++++ README.txt | 22 + .../Adafruit_MCP23017/Adafruit_MCP23017.cpp | 230 +++ .../Adafruit_MCP23017/Adafruit_MCP23017.h | 63 + libraries/Adafruit_MCP23017/README.txt | 15 + .../Adafruit_MCP23017/examples/button.pde | 800 ++++++++ .../examples/button/button.pde | 31 + .../Adafruit_MCP23017/examples/toggle.pde | 803 ++++++++ .../examples/toggle/toggle.pde | 34 + libraries/Adafruit_MCP23017/keywords.txt | 21 + libraries/Adafruit_MCP23017/license.txt | 26 + libraries/DS1307/DS1307.cpp | 119 ++ libraries/DS1307/DS1307.h | 44 + libraries/DS1307/keywords.txt | 4 + libraries/E24C1024/E24C1024.cpp | 76 + libraries/E24C1024/E24C1024.h | 62 + .../examples/EEPROM1024/EEPROM1024.pde | 115 ++ .../NewSoftSerialTest/NewSoftSerialTest.pde | 25 + .../Examples/TwoNSSTest/TwoNSSTest.pde | 33 + libraries/NewSoftSerial/NewSoftSerial.cpp | 539 +++++ libraries/NewSoftSerial/NewSoftSerial.h | 107 + libraries/NewSoftSerial/NewSoftSerial.o | Bin 0 -> 21940 bytes libraries/NewSoftSerial/keywords.txt | 30 + libraries/PCATTACH/PCATTACH.cpp | 138 ++ libraries/PCATTACH/PCATTACH.h | 30 + libraries/PCATTACH/keywords.txt | 2 + libraries/Wiegand26/WIEGAND26.cpp | 118 ++ libraries/Wiegand26/WIEGAND26.h | 36 + libraries/Wiegand26/keywords.txt | 9 + user.h | 41 + 30 files changed, 5391 insertions(+) create mode 100644 Open_Access_Control_v4_std.ino create mode 100644 README.txt create mode 100644 libraries/Adafruit_MCP23017/Adafruit_MCP23017.cpp create mode 100644 libraries/Adafruit_MCP23017/Adafruit_MCP23017.h create mode 100644 libraries/Adafruit_MCP23017/README.txt create mode 100644 libraries/Adafruit_MCP23017/examples/button.pde create mode 100644 libraries/Adafruit_MCP23017/examples/button/button.pde create mode 100644 libraries/Adafruit_MCP23017/examples/toggle.pde create mode 100644 libraries/Adafruit_MCP23017/examples/toggle/toggle.pde create mode 100644 libraries/Adafruit_MCP23017/keywords.txt create mode 100644 libraries/Adafruit_MCP23017/license.txt create mode 100644 libraries/DS1307/DS1307.cpp create mode 100644 libraries/DS1307/DS1307.h create mode 100644 libraries/DS1307/keywords.txt create mode 100644 libraries/E24C1024/E24C1024.cpp create mode 100644 libraries/E24C1024/E24C1024.h create mode 100644 libraries/E24C1024/examples/EEPROM1024/EEPROM1024.pde create mode 100644 libraries/NewSoftSerial/Examples/NewSoftSerialTest/NewSoftSerialTest.pde create mode 100644 libraries/NewSoftSerial/Examples/TwoNSSTest/TwoNSSTest.pde create mode 100644 libraries/NewSoftSerial/NewSoftSerial.cpp create mode 100644 libraries/NewSoftSerial/NewSoftSerial.h create mode 100644 libraries/NewSoftSerial/NewSoftSerial.o create mode 100644 libraries/NewSoftSerial/keywords.txt create mode 100644 libraries/PCATTACH/PCATTACH.cpp create mode 100644 libraries/PCATTACH/PCATTACH.h create mode 100644 libraries/PCATTACH/keywords.txt create mode 100644 libraries/Wiegand26/WIEGAND26.cpp create mode 100644 libraries/Wiegand26/WIEGAND26.h create mode 100644 libraries/Wiegand26/keywords.txt create mode 100644 user.h diff --git a/Open_Access_Control_v4_std.ino b/Open_Access_Control_v4_std.ino new file mode 100644 index 0000000..87cec3d --- /dev/null +++ b/Open_Access_Control_v4_std.ino @@ -0,0 +1,1818 @@ +/* + * Open Source RFID Access Controller - v4 Standard Hardware + * + * 10/214/2015 Version 1.40 + * Last build test with Arduino v1.6.4 for Linux + * Arclight - arclight@23.org + * Danozano - danozano@gmail.com + * + * 10.14.2015 Removed the "Superuser" feature. + * + * Notice: This is free software and is probably buggy. Use it at + * at your own peril. Use of this software may result in your + * doors being left open, your stuff going missing, or buggery by + * high seas pirates. No warranties are expressed on implied. + * You are warned. + * + * + * For latest downloads, see the Wiki at: + * http://www.accxproducts.com/wiki/index.php?title=Open_Access_4.0 + * + * For the SVN repository and alternate download site, see: + * http://code.google.com/p/open-access-control/downloads/list + * + * Latest update puts configuration variables in user.h + * This version supports the new Open Access v4 hardware. + * + * + * This program interfaces the Arduino to RFID, PIN pad and all + * other input devices using the Wiegand-26 Communications + * Protocol. It is recommended that the keypad inputs be + * opto-isolated in case a malicious user shorts out the + * input device. + * Outputs go to a Darlington relay driver array for door hardware/etc control. + * Analog inputs are used for alarm sensor monitoring. These should be + * isolated as well, since many sensors use +12V. Note that resistors of + * different values can be used on each zone to detect shorting of the sensor + * or wiring. + * + * Version 4.x of the hardware implements these features and emulates an + * Arduino Duemilanova. + * The "standard" hardware uses the MC23017 i2c 16-channel I/O expander. + * I/O pins are addressed in two banks, as GPA0..7 and GPB0..7 + * + * Relay outpus on digital pins: GPA6, GPA7, GPB0, GPB1 + * DS1307 Real Time Clock (I2C): A4 (SDA), A5 (SCL) + * Analog pins (for alarm): A0,A1,A2,A3 + * Digital input in (tamper): D9 + * Reader 1: D2,D3 + * Reader 2: D4,D5 + * RS485 TX enable / RX disable: D8 + * RS485 RX, TX: D6,D7 + * Reader1 LED: GPB2 + * Reader1 Buzzer: GPB3 + * Reader2 LED: GPB4 + * Reader2 Buzzer: GPB5 + * Status LED: GPB6 + + * LCD RS: GPA0 + * LCD EN: GPA1 + * LCD D4..D7: GPA2..GPA5 + + * Ethernet/SPI: D10..D1313 (Not used, reserved for the Ethernet shield) + * + * Quickstart tips: + * Set the console password(PRIVPASSWORD) value to a numeric DEC or HEX value. + * Define the static user list by swiping a tag and copying the value received into the #define values shown below + * Compile and upload the code, then log in via serial console at 57600,8,N,1 + * + */ +#include "user.h" // User preferences file. Use this to select hardware options, passwords, etc. +#include // Needed for I2C Connection to the DS1307 date/time chip +#include // Needed for saving to non-voilatile memory on the Arduino. +#include // Allows data to be stored in FLASH instead of RAM + +#include // DS1307 RTC Clock/Date/Time chip library +#include // Wiegand 26 reader format libary + +#ifdef MCU328 +#include // Pcint.h implementation, allows for >2 software interupts. +#endif + +#ifdef MCPIOXP +#include // Library for the MCP23017 i2c I/O expander +#endif + +#ifdef AT24EEPROM +#include // AT24C i2C EEPOROM library +#define MIN_ADDRESS 0 +#define MAX_ADDRESS 4096 // 1x32K device +#endif + +#define EEPROM_ALARM 0 // EEPROM address to store alarm triggered state between reboots (0..511) +#define EEPROM_ALARMARMED 1 // EEPROM address to store alarm armed state between reboots +#define EEPROM_ALARMZONES 20 // Starting address to store "normal" analog values for alarm zone sensor reads. + + +#define EEPROM_FIRSTUSER 24 +#define EEPROM_LASTUSER 1024 +#define NUMUSERS ((EEPROM_LASTUSER - EEPROM_FIRSTUSER)/5) //Define number of internal users (200 for UNO/Duemillanova) + + +#ifdef HWV4STD // Use these pinouts for the v3 Standard hardware +#define DOORPIN1 6 // Define the pin for electrified door 1 hardware. (MCP) +#define DOORPIN2 7 // Define the pin for electrified door 2 hardware (MCP) +#define ALARMSTROBEPIN 8 // Define the "non alarm: output pin. Can go to a strobe, small chime, etc. Uses GPB0 (MCP pin 8). +#define ALARMSIRENPIN 9 // Define the alarm siren pin. This should be a LOUD siren for alarm purposes. Uses GPB1 (MCP pin9). +#define READER1GRN 10 +#define READER1BUZ 11 +#define READER2GRN 12 +#define READER2BUZ 13 +#define RS485ENA 6 // Arduino Pin D6 +#define STATUSLED 14 // MCP pin 14 +#define R1ZERO 2 +#define R1ONE 3 +#define R2ZERO 4 +#define R2ONE 5 +#endif + +uint8_t reader1Pins[]={R1ZERO, R1ONE}; // Reader 1 pin definition +uint8_t reader2Pins[]={R2ZERO, R2ONE}; // Reade 2 pin definition + +const uint8_t analogsensorPins[] = {0,1,2,3}; // Alarm Sensors connected to other analog pins + +/* Global Boolean values + * + */ +bool door1Locked=true; // Keeps track of whether the doors are supposed to be locked right now +bool door2Locked=true; +boolean doorChime=false; // Keep track of when door chime last activated +boolean doorClosed=false; // Keep track of when door last closed for exit delay +boolean sensor[4]={false}; // Keep track of tripped sensors, do not log again until reset. + + + +/* Global Timers + * + */ +unsigned long door1locktimer=0; // Keep track of when door is supposed to be relocked +unsigned long door2locktimer=0; // after access granted. +unsigned long alarmDelay=0; // Keep track of alarm delay. Used for "delayed activation" or level 2 alarm. +unsigned long alarmSirenTimer=0; // Keep track of how long alarm has gone off +unsigned long consolefailTimer=0; // Console password timer for failed logins +unsigned long sensorDelay[2]={0}; // Used with sensor[] above, but sets a timer for 2 of them. Useful for logging + // motion detector hits for "occupancy check" functions. + + + +#define NUMDOORS (sizeof(doorPin)/sizeof(uint8_t)) +#define numAlarmPins (sizeof(analogsensorPins)/sizeof(uint8_t)) + +//Other global variables +uint8_t second, minute, hour, dayOfWeek, dayOfMonth, month, year; // Global RTC clock variables. Can be set using DS1307.getDate function. + +uint8_t alarmActivated = EEPROM.read(EEPROM_ALARM); // Read the last alarm state as saved in eeprom. +uint8_t alarmArmed = EEPROM.read(EEPROM_ALARMARMED); // Alarm level variable (0..5, 0==OFF) + +uint8_t consoleFail=0; // Tracks failed console logins for lockout + +/* Global values for the Wiegand RFID readers + * + */ +volatile long reader1 = 0; // Reader1 buffer +long reader1dec=0; // Separate value for decoded reader1 values +long reader2dec=0; // Separate value for decoded reader1 values +volatile int reader1Count = 0; // Reader1 received bits counter +volatile long reader2 = 0; +volatile int reader2Count = 0; +int userMask1=0; +int userMask2=0; + +boolean keypadGranted=0; // Variable that is set for authenticated users to use keypad after login + +//volatile long reader3 = 0; // Uncomment if using a third reader. +//volatile int reader3Count = 0; + +unsigned long keypadTime = 0; // Timeout counter for reader with key pad +unsigned long keypadValue=0; + + +// Serial terminal buffer (needs to be global) +char inString[64]={0}; // Size of command buffer (<=128 for Arduino) +uint8_t inCount=0; +boolean privmodeEnabled = false; // Switch for enabling "priveleged" commands + + + +/* Create an instance of the various C++ libraries we are using. + */ + +DS1307 ds1307; // RTC Instance +WIEGAND26 wiegand26; // Wiegand26 (RFID reader serial protocol) library + + +#ifdef MCPIOXP +Adafruit_MCP23017 mcp; +#endif + +#ifdef MCU328 +PCATTACH pcattach; // Software interrupt library +#endif + +#ifdef LCDBOARD +cLCD lcd; +#endif + +/* Set up some strings that will live in flash instead of memory. This saves our precious 2k of + * RAM for something else. +*/ +const unsigned char rebootMessage[] PROGMEM = {"Access Control System rebooted."}; +const unsigned char doorChimeMessage[] PROGMEM = {"Front Door opened."}; +const unsigned char doorslockedMessage[] PROGMEM = {"All Doors relocked"}; +const unsigned char alarmtrainMessage[] PROGMEM = {"Alarm Training performed."}; +const unsigned char privsdeniedMessage[] PROGMEM = {"Access Denied. Priveleged mode is not enabled."}; +const unsigned char privsenabledMessage[] PROGMEM = {"Priveleged mode enabled."}; +const unsigned char privsdisabledMessage[] PROGMEM = {"Priveleged mode disabled."}; +const unsigned char privsAttemptsMessage[] PROGMEM = {"Too many failed attempts. Try again later."}; + +const unsigned char consolehelpMessage1[] PROGMEM = {"Valid commands are:"}; +const unsigned char consolehelpMessage2[] PROGMEM = {"(d)ate, (s)show user, (m)odify user "}; +const unsigned char consolehelpMessage3[] PROGMEM = {"(a)ll user dump,(r)emove_user ,(o)open door "}; +const unsigned char consolehelpMessage4[] PROGMEM = {"(u)nlock all doors,(l)lock all doors"}; +const unsigned char consolehelpMessage5[] PROGMEM = {"(1)disarm_alarm, (2)arm_alarm,(3)train_alarm (9)show_status"}; +const unsigned char consolehelpMessage6[] PROGMEM = {"(t)ime set "}; +const unsigned char consolehelpMessage7[] PROGMEM = {" "}; +const unsigned char consolehelpMessage8[] PROGMEM = {"(e)nable - enable or disable priveleged mode"}; +const unsigned char consolehelpMessage9[] PROGMEM = {"(h)ardware Test - Run the hardware test"}; +const unsigned char consoledefaultMessage[] PROGMEM = {"Invalid command. Press '?' for help."}; + +const unsigned char statusMessage1[] PROGMEM = {"Alarm armed state (1=armed):"}; +const unsigned char statusMessage2[] PROGMEM = {"Alarm siren state (1=activated):"}; +const unsigned char statusMessage3[] PROGMEM = {"Front door open state (0=closed):"}; +const unsigned char statusMessage4[] PROGMEM = {"Roll up door open state (0=closed):"}; +const unsigned char statusMessage5[] PROGMEM = {"Door 1 unlocked state(1=locked):"}; +const unsigned char statusMessage6[] PROGMEM = {"Door 2 unlocked state(1=locked):"}; + + + +void setup(){ // Runs once at Arduino boot-up + + + + + Wire.begin(); // start Wire library as I2C-Bus Master + mcp.begin(); // use default address 0 + + pinMode(2,INPUT); // Initialize the Arduino built-in pins + pinMode(3,INPUT); + pinMode(4,INPUT); + pinMode(5,INPUT); + mcp.pinMode(DOORPIN1, OUTPUT); + mcp.pinMode(DOORPIN2, OUTPUT); + pinMode(6,OUTPUT); + + for(int i=0; i<=15; i++) // Initialize the I/O expander pins + { + mcp.pinMode(i, OUTPUT); + } + + + digitalWrite(RS485ENA, HIGH); // Set the RS485 chip to HIGH (not asserted) + + + /* Attach pin change interrupt service routines from the Wiegand RFID readers + */ +#ifdef MCU328 + pcattach.PCattachInterrupt(reader1Pins[0], callReader1Zero, CHANGE); + pcattach.PCattachInterrupt(reader1Pins[1], callReader1One, CHANGE); + pcattach.PCattachInterrupt(reader2Pins[1], callReader2One, CHANGE); + pcattach.PCattachInterrupt(reader2Pins[0], callReader2Zero, CHANGE); + #endif + + //Clear and initialize readers + wiegand26.initReaderOne(); //Set up Reader 1 and clear buffers. + wiegand26.initReaderTwo(); + + mcp.digitalWrite(DOORPIN1, LOW); // Sets the relay outputs to LOW (relays off) + mcp.digitalWrite(DOORPIN2, LOW); + mcp.digitalWrite(ALARMSTROBEPIN, LOW); + mcp.digitalWrite(ALARMSIRENPIN, LOW); + + //Initialize LEDs + + +//ds1307.setDateDs1307(0,57,0,7,21,9,13); + /* Sets the date/time (needed once at commissioning) + + uint8_t second, // 0-59 + uint8_t minute, // 0-59 + uint8_t hour, // 1-23 + uint8_t dayOfWeek, // 1-7 + uint8_t dayOfMonth, // 1-28/29/30/31 + uint8_t month, // 1-12 + uint8_t year); // 0-99 + */ + + + + Serial.begin(UBAUDRATE); // Set up Serial output to value in user.h + logReboot(); + chirpAlarm(1); // Chirp the alarm to show system ready. + +#ifdef LCDBOARD +lcd.begin(16,2); +lcd.setCursor(0,0); +lcd.print("Open Access "); +lcd.print(VERSION); +delay(500); +lcd.clear(); +#endif + //Set up the MCP23017 IO expander and initialize +#ifdef MCPIOXP +mcp.digitalWrite(STATUSLED, LOW); // Turn the status LED green +#endif + + +} + + + + +void loop() // Main branch, runs over and over again +{ + + +readCommand(); // Check for commands entered at serial console + + + /* Check if doors are supposed to be locked and lock/unlock them + * if needed. Uses global variables that can be set in other functions. + */ + + if(((millis() - door1locktimer) >= DOORDELAY) && (door1locktimer !=0)) + { + if(door1Locked==true){ + doorLock(1); + door1locktimer=0; + + + } + + else { + doorUnlock(1); + door1locktimer=0; + } + } + + + + if(((millis() - door2locktimer) >= DOORDELAY) && (door2locktimer !=0)) + { + if(door2Locked==true) { + doorLock(2); + door2locktimer=0; + } + + else { + doorUnlock(2); + door2locktimer=0; + } + + } +#ifdef LCDBOARD +lcdStatus(1,door1Locked); +lcdStatus(2,door2Locked); +#endif + + /* Set optional "failsafe" time to lock up every night. + */ + + ds1307.getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // Get the current date/time + + if(hour==23 && minute==59 && door1Locked==false){ + doorLock(1); + door1Locked==true; + Serial.println("Door 1 locked for 2359 bed time."); + } + + + + + + + + // Notes: RFID polling is interrupt driven, just test for the reader1Count value to climb to the bit length of the key + // change reader1Count & reader1 et. al. to arrays for loop handling of multiple reader output events + // later change them for interrupt handling as well! + // currently hardcoded for a single reader unit + + /* This code checks a reader with a 26-bit keycard input. Use the second routine for readers with keypads. + * A 5-second window for commands is opened after each successful key access read. + */ + + if(reader1Count >= 26){ // When tag presented to reader1 (No keypad on this reader) + reader1dec=decodeCard(reader1); // Format the card data (format can be defined in user.h) + logTagPresent(reader1dec,1); // Write log entry to serial port + reader1=0; + reader1Count=0; + +/* Check a user's security level and take action as needed. The +* usermask is a variable from 0..255. By default, 0 and 255 are for +* locked out users or uninitialized records. +* Modify these for each door as needed. +*/ + + userMask1=checkUser(reader1dec); + + if(userMask1>=0) { + + switch(userMask1) { + + case 0: // No outside privs, do not log denied. + { // authenticate only. + logAccessGranted(reader1dec, 1); + break; + } + // Example office user class + case 20: // "Door stays open on scans after 0500 user + { // Any scan after 0500 results in staying unlocked until 1700. + ds1307.getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); + if((hour >=5) && (hour <17)){ + logAccessGranted(reader1dec, 1); // Log and unlock door 2 + alarmState(0); + armAlarm(0); // Deactivate Alarm + doorUnlock(1); // Set door to stay open + door1Locked=false; + //chirpAlarm(1); + + } + else + { + logAccessGranted(reader1dec, 1); // Log and unlock door 1 + alarmState(0); + armAlarm(0); // Deactivate Alarm + door1locktimer=millis(); + doorUnlock(1); // Unlock the door. + break; + } + + break; + } + + case 255: // Locked out user + { + Serial.print("User "); + Serial.print(userMask1,DEC); + Serial.println(" locked out."); + break; + } + + default: + { + logAccessGranted(reader1dec, 1); // Log and unlock door 1 + alarmState(0); + armAlarm(0); // Deactivate Alarm + door1locktimer=millis(); + doorUnlock(1); // Unlock the door. + break; + } + } + + } + + else + + { + + logAccessDenied(reader1dec,1); // No tickee, no laundree + chirpAlarm(1); + } + +wiegand26.initReaderOne(); // Reset for next tag scan + + } // End of Reader 1 check logic + + + + + if(reader2Count >= 26){ // Tag presented to reader 2 + reader2dec=decodeCard(reader2); // Format the card data (format can be defined in user.h) + logTagPresent(reader2dec,2); // Write log entry to serial port + reader2=0; + reader2Count=0; + //chirpAlarm(1); // Chirp alarm to show that tag input done + // CHECK TAG IN OUR LIST OF USERS. -1 = no match + keypadGranted=false; // Reset the keypad authorized variable + + userMask2=checkUser(reader2dec); + + if(userMask2>=0){ + switch(userMask2) { + + case 0: // No outside privs, do not log denied. + { // authenticate and log only. + logAccessGranted(reader2dec, 2); + break; + } + + case 10: // Authenticating immediately locks up and arms alarm + { // + logAccessGranted(reader2dec, 2); + runCommand(0x2); + break; + } + + case 20: //Limited hours user + { + ds1307.getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); + if((hour >=5) && (hour <=17)){ + logAccessGranted(reader2dec, 2); // Log and unlock door 2 + alarmState(0); + armAlarm(0); // Deactivate Alarm + door2locktimer=millis(); + doorUnlock(2); // Unlock the door. + keypadGranted=1; + } + break; + } + + case 255: // Locked out + { + Serial.print("User "); + Serial.print(userMask2,DEC); + Serial.println(" locked out."); + break; + } + + default: + { + logAccessGranted(reader2dec, 2); // Log and unlock door 2 + alarmState(0); + armAlarm(0); // Deactivate Alarm + door2locktimer=millis(); + doorUnlock(2); // Unlock the door. + keypadGranted=1; + break; + } + } + + } + else + { + logAccessDenied(reader2dec,2); // no tickee, no laundree + } +wiegand26.initReaderTwo(); // Reset for next tag scan + + +if(READER2KEYPAD == 1) // If Reader2 has a keypad, users can also enter commands +{ + unsigned long keypadTime=0; // Timeout counter for reader with key pad + long keypadValue=0; + keypadTime=millis(); + + if(keypadGranted==1) + { + while((millis() - keypadTime) <=KEYPADTIMEOUT){ + + // If access granted, open 5 second window for pin pad commands. + if(reader2Count >=4){ + if(reader2 !=0xB){ // Pin pad command can be any length, terminated with '#' on the keypad. + if(keypadValue ==0){ // This 0..9, A..F encoding works with many Wiegand-format keypad or reader + keypadValue = reader2; // plus keypad units. + + } + else if(keypadValue !=0) { + keypadValue = keypadValue <<4; + keypadValue |= reader2; + } + wiegand26.initReaderTwo(); //Reset reader one and move on. + } + else break; + + } + + } + + logkeypadCommand(2,keypadValue); + runCommand(keypadValue); // Run any commands entered at the keypads. + wiegand26.initReaderTwo(); + + + } + wiegand26.initReaderTwo(); + } + +} // end of keypad check + + +/* Example "bed time" feature. +* Check if open hours and relock doors if BEDTIME hour has passed and door1 is still open. +* +*/ + +if(BEDTIME_ENABLED == 1) + { + ds1307.getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); + if((hour >=BEDTIME) && (door1Locked==false)){ + lockall(); + door1Locked=true; + chirpAlarm(1); + + } + } + + + /* Check physical sensors with + the logic below. Behavior is based on + the current alarmArmed value. + 0=disarmed + 1=armed + 2= + 3= + 4=door chime only (Unlock DOOR1, Check zone 0/chirp alarm if active) + + Modify the alarm sequence to meet your needs. + */ + + switch(alarmArmed) { + + + case 0: + { + break; // Alarm is not armed, do nothing. + } + + case 1: // Alarm is armed + { + + + if(alarmActivated==0){ // If alarm is armed but not currently alarming, check sensor zones. + + if(pollAlarm(0) == 1 ){ // If this zone is tripped, immediately set Alarm State to 2 (alarm delay). + alarmState(2); // Also starts the delay timer + alarmDelay=millis(); + if(sensor[0]==false) { // Only log and save if sensor activation is new. + logalarmSensor(0); + EEPROM.write(EEPROM_ALARM,0); // Save the alarm sensor tripped to eeprom + sensor[0]=true; // Set value to not log this again + } + } + if(pollAlarm(1) == 1 ){ // If this zone is tripped, immediately set Alarm State to 1 (alarm immediate). + alarmState(1); + if(sensor[1]==false) { // Only log and save if sensor activation is new. + logalarmSensor(1); + EEPROM.write(EEPROM_ALARM,1); // Save the alarm sensor tripped to eeprom + sensor[1]=true; // Set value to not log this again + } + } + if(pollAlarm(2) == 1 ){ // If this zone is tripped, immediately set Alarm State to 1 (alarm immediate). + alarmState(1); + if(sensor[2]==false) { // Only log and save if sensor activation is new. + logalarmSensor(2); + EEPROM.write(EEPROM_ALARM,2); // Save the alarm sensor tripped to eeprom + sensor[2]=true; // Set value to not log this again + } + + } + + if(pollAlarm(3) == 1 ){ // If this zone is tripped, immediately set Alarm State to 2 (alarm delay). + alarmState(2); // Also starts the delay timer + alarmDelay=millis(); + if(sensor[3]==false) { // Only log and save if sensor activation is new. + logalarmSensor(3); + EEPROM.write(EEPROM_ALARM,3); // Save the alarm sensor tripped to eeprom + sensor[3]=true; // Set value to not log this again + } + } + + + + } + if(alarmActivated==1) { // If alarm is actively going off (siren/strobe) for 10 min (6e5=10min) + if(millis()-alarmSirenTimer >=3.6e6) // Check for alarm interval expired and turn off if needed + { + mcp.digitalWrite(ALARMSIRENPIN,LOW); // Turn on the chime instead + mcp.digitalWrite(ALARMSTROBEPIN,HIGH); + } + } + + if(alarmActivated==2) { // If alarm is activated on delay, take this action + if(millis()-alarmDelay >=60000) // Turn on the siren once delay exceeds 60sec. + { + alarmState(1); + } + } + + + break; + + } + + case 4: + { // Door chime mode + + if((pollAlarm(3) !=0) && (doorChime==false)) { // Only activate door chime once per opening + chirpAlarm(3); + logChime(); + doorChime=true; + } + if(pollAlarm(3) ==0){ + doorChime=false; } + break; + + } + + default: + { + break; + } + } + +// Log all motion detector activations regardless of alarm armed state. Useful for "occupancy detection" + + if(pollAlarm(0) == 1 ){ // If this zone is tripped, log the action only + // if(sensor[0]==false) + if((millis() - sensorDelay[0]) >=7500) { + logalarmSensor(0); + sensorDelay[0]=millis(); + sensor[0]=true; } // Set value to not log this again for 7.5s + } + + if(pollAlarm(1) == 1 ){ // If this zone is tripped, log the action only + // if(sensor[1]==false) + if((millis() - sensorDelay[1]) >=7500) { + logalarmSensor(1); + sensorDelay[1]=millis(); + sensor[1]=true; // Set value to not log this again for 7.5s + } + } + } // End of loop() + + +void runCommand(long command) { // Run any commands entered at the pin pad. + + switch(command) { + + + case 0x1: + { // If command = 1, deactivate alarm + alarmState(0); // Set global alarm level variable + armAlarm(0); + chirpAlarm(1); + break; + } + + case 0x2: + { // If command =2, activate alarm with delay. + + doorUnlock(1); // Set global alarm level variable + door1Locked=false; + doorClosed=false; // 200 chirps = ~30 seconds delay + + if((pollAlarm(3) == 0) && (pollAlarm(2) == 0)) { // Do not arm the alarm if doors are open + + for(uint8_t i=0; i<30; i++) { + if((pollAlarm(3) !=0) && doorClosed==false) { // Set door to be unlocked until alarm timeout or user exits + lockall(); + doorClosed=true; + } + mcp.digitalWrite(ALARMSTROBEPIN, HIGH); + delay(500); + mcp.digitalWrite(ALARMSTROBEPIN, LOW); + delay(500); + } + chirpAlarm(2); + armAlarm(1); + lockall(); // Lock all doors on exit + } + else { // Beep the alarm once and exit if attempt made to arm alarm with doors open + mcp.digitalWrite(ALARMSTROBEPIN, HIGH); + delay(500); + mcp.digitalWrite(ALARMSTROBEPIN, LOW); + delay(500); + lockall(); // Lock all doors anyway + } + break; + } + + case 0x3: + { + + doorLock(1); // Set door 2 to stay unlocked, and door 1 to be locked + doorUnlock(2); + door1Locked=true; + door2Locked=false; + chirpAlarm(3); + break; + } + + case 0x4: // Set doors to remain open + { + armAlarm(4); + doorUnlock(1); + doorUnlock(2); + door1Locked=false; + door2Locked=false; + chirpAlarm(4); + break; + } + case 0x5: // Relock all doors + { + lockall(); + chirpAlarm(5); + break; + } + + case 0x911: + { + chirpAlarm(9); // Emergency + armAlarm(1); + alarmState(1); + break; + } + + case 0x20: + { // If command = 20, do nothing + break; + } + default: + { + break; + } + } + + +} + + +/* Alarm System Functions - Modify these as needed for your application. + Sensor zones may be polled with digital or analog pins. Unique reader2 + resistors can be used to check more zones from the analog pins. + */ + +void alarmState(uint8_t alarmLevel) { //Changes the alarm status based on this flow + + logalarmState(alarmLevel); + switch (alarmLevel) { + case 0: + { // If alarmLevel == 0 turn off alarm. + mcp.digitalWrite(ALARMSIRENPIN, LOW); + mcp.digitalWrite(ALARMSTROBEPIN, LOW); + alarmActivated = alarmLevel; //Set global alarm level variable + break; + } + case 1: + { + mcp.digitalWrite(ALARMSIRENPIN, HIGH); // If alarmLevel == 1 turn on strobe lights and siren + // mcp.digitalWrite(ALARMSTROBEPIN, HIGH); // Optionally activate yoru strobe/chome + alarmSirenTimer=millis(); + alarmActivated = alarmLevel; //Set global alarm level variable + logalarmTriggered(); + + break; + } + + case 2: + { + mcp.digitalWrite(ALARMSTROBEPIN, HIGH); + alarmActivated = alarmLevel; + break; + } + + case 3: + { + + alarmActivated = alarmLevel; + break; + } + /* + case 4: { + vaporize_intruders(STUN); + break; + } + + case 5: { + vaporize_intruders(MAIM); + } etc. etc. etc. + break; + */ + + default: + { // Exceptional cases kill alarm outputs + mcp.digitalWrite(ALARMSIRENPIN, LOW); // Turn off siren and strobe + // mcp.digitalWrite(ALARMSTROBEPIN, LOW); + break; + } + + + + + } + + if(alarmActivated != EEPROM.read(EEPROM_ALARM)){ // Update eeprom value + EEPROM.write(EEPROM_ALARM,alarmActivated); + } + +} //End of alarmState() + +void chirpAlarm(uint8_t chirps){ // Chirp the siren pin or strobe to indicate events. + for(uint8_t i=0; iSENSORTHRESHOLD){ + return 1; + + } + else return 0; +} + +void trainAlarm(){ // Train the system about the default states of the alarm pins. + armAlarm(0); // Disarm alarm first + alarmState(0); + + int temp[5]={0}; + int avg; + + for(int i=0; i NUMUSERS)) { // Do not write to invalid EEPROM addresses. + + Serial.print("Invalid user modify attempted."); + } + else + { + + + + + EEPROM_buffer[0] = uint8_t(tagNumber & 0xFFF); // Fill the buffer with the values to write to bytes 0..4 + EEPROM_buffer[1] = uint8_t(tagNumber >> 8); + EEPROM_buffer[2] = uint8_t(tagNumber >> 16); + EEPROM_buffer[3] = uint8_t(tagNumber >> 24); + EEPROM_buffer[4] = uint8_t(userMask); + + + + for(int i=0; i<5; i++){ + EEPROM.write((offset+i), (EEPROM_buffer[i])); // Store the resulting value in 5 bytes of EEPROM. + + } + + Serial.print("User "); + Serial.print(userNum,DEC); + Serial.println(" successfully modified"); + + + } +} + +void deleteUser(int userNum) // Deletes a user from the local database. +{ // Users number 0..NUMUSERS + int offset = (EEPROM_FIRSTUSER+(userNum*5)); // Find the offset to write this user to + + logDate(); + + if((userNum <0) || (userNum > NUMUSERS)) { // Do not write to invalid EEPROM addresses. + + Serial.print("Invalid user delete attempted."); + } + else + { + + + + for(int i=0; i<5; i++){ + EEPROM.write((offset+i), 0xFF); // Store the resulting value in 5 bytes of EEPROM. + // Starting at offset. + + + + } + + Serial.print("User deleted at position "); + Serial.println(userNum); + + } + +} + + + +int checkUser(unsigned long tagNumber) // Check if a particular tag exists in the local database. Returns userMask if found. +{ // Users number 0..NUMUSERS + // Find the first offset to check + + unsigned long EEPROM_buffer=0; // Buffer for recreating tagNumber from the 4 stored bytes. + int found=-1; + + logDate(); + + + for(int i=EEPROM_FIRSTUSER; i<=(EEPROM_LASTUSER-5); i=i+5){ + + + EEPROM_buffer=0; + EEPROM_buffer=(EEPROM.read(i+3)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i+2)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i+1)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i)); + + + if((EEPROM_buffer == tagNumber) && (tagNumber !=0xFFFFFFFF) && (tagNumber !=0x0)) { // Return a not found on blank (0xFFFFFFFF) entries + logDate(); + Serial.print("User "); + Serial.print(((i-EEPROM_FIRSTUSER)/5),DEC); + Serial.println(" authenticated."); + found = EEPROM.read(i+4); + return found; + } + + } + Serial.println("User not found"); + delay(1000); // Delay to prevent brute-force attacks on reader + return found; +} + + + + + +void dumpUser(uint8_t usernum) // Return information ona particular entry in the local DB +{ // Users number 0..NUMUSERS + + + unsigned long EEPROM_buffer=0; // Buffer for recreating tagNumber from the 4 stored bytes. + + + if((0<=usernum) && (usernum <=199)){ + + int i=usernum*5+EEPROM_FIRSTUSER; + + EEPROM_buffer=0; + EEPROM_buffer=(EEPROM.read(i+3)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i+2)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i+1)); + EEPROM_buffer= EEPROM_buffer<<8; + EEPROM_buffer=(EEPROM_buffer ^ EEPROM.read(i)); + + + + Serial.print(((i-EEPROM_FIRSTUSER)/5),DEC); + Serial.print("\t"); + Serial.print(EEPROM.read(i+4),DEC); + Serial.print("\t"); + + if(DEBUG>=2){ + Serial.println(EEPROM_buffer,DEC); // Show user in DEC + } + else { + if(EEPROM_buffer != 0xFFFFFFFF) { + Serial.print("********");} + } + + + + + } + else Serial.println("Bad user number!"); +} + + +/* Displays a serial terminal menu system for + * user management and other tasks + */ + +long decodeCard(long input) +{ + if(CARDFORMAT==0) + { + return(input); + } + + if(CARDFORMAT==1) + { + bool parityHigh; + bool parityLow; + parityLow=bitRead(input,0); + parityHigh=bitRead(input,26); + bitWrite(input,25,0); // Set highest (parity bit) to zero + input=(input>>1); // Shift out lowest bit (parity bit) + +/* + bool parityTemp0=0; + for(unsigned int i=0; i<13; i++) + { + parityTemp0+=bitRead(input,i); + } + + bool parityTemp1=0; + for(unsigned int i=14; i<24; i++) + { + parityTemp1+=bitRead(input,i); + } + + if( (parityTemp0 != parityLow) && (parityTemp1 != parityHigh) ) + { + return(input); + } + + else + { + Serial.print("ParityTemp0: "); Serial.print(parityTemp0); Serial.print(' ');Serial.println(parityLow); + Serial.print("ParityTemp1: "); Serial.print(parityTemp1); Serial.print(' ');Serial.println(parityHigh); + return(-1); + } + */ + return(input); + } +} + +void readCommand() { +byte cmds=7; +byte cmdlen=9; + +uint8_t stringSize=(sizeof(inString)/sizeof(char)); +char cmdString[cmds][cmdlen]; // Size of commands (4=number of items to parse, 10 = max length of each) + + +uint8_t j=0; // Counters +uint8_t k=0; +char cmd=0; + + +char ch; + + if (Serial.available()) { // Check if user entered a command this round + ch = Serial.read(); + if( ch == '\r' || inCount >=stringSize-1) { // Check if this is the terminating carriage return + inString[inCount] = 0; + inCount=0; + } + else{ + (inString[inCount++] = ch); } + //Serial.print(ch); // Turns echo on or off + + +if(inCount==0) { + for(uint8_t i=0; i=5) && (millis()-consolefailTimer<300000)) // Do not allow priv mode if more than 5 failed logins in 5 minute + { + PROGMEMprintln(privsAttemptsMessage); + break; + } + if (strtoul(cmdString[1],NULL,16) == PRIVPASSWORD) + { + consoleFail=0; + PROGMEMprintln(privsenabledMessage); + privmodeEnabled=true; + } + else { + PROGMEMprintln(privsdisabledMessage); + privmodeEnabled=false; + if(consoleFail==0) { // Set the timeout for failed logins + consolefailTimer=millis(); + } + consoleFail++; // Increment the login failure counter + } + + break; + + } + +//privmodeEnabled=true; //Debugging statement + + + case 'a': { // List whole user database + if(privmodeEnabled==true) { + logDate(); + Serial.println("User dump started."); + Serial.print("UserNum:"); + Serial.print(" "); + Serial.print("Usermask:"); + Serial.print(" "); + Serial.println("TagNum:"); + + for(int i=0; i<(NUMUSERS); i++){ + dumpUser(i); + Serial.println(); + } + } + else{logprivFail();} + break; + } + + case 's': { // List user + if(privmodeEnabled==true) { + Serial.print("UserNum:"); + Serial.print(" "); + Serial.print("Usermask:"); + Serial.print(" "); + Serial.println("TagNum:"); + dumpUser(atoi(cmdString[1])); + Serial.println(); + } + else{logprivFail();} + break; + } + + case 'd': { // Display current time + logDate(); + Serial.println(); + break; + } + + case '1': { // Deactivate alarm + if(privmodeEnabled==true) { + armAlarm(0); + alarmState(0); + chirpAlarm(1); + } + else{logprivFail();} + break; + } + case '2': { // Activate alarm with delay. + chirpAlarm(20); // 200 chirps = ~30 seconds delay + armAlarm(1); + break; + } + + case 'u': { + if(privmodeEnabled==true) { + alarmState(0); // Set to door chime only/open doors + armAlarm(4); + doorUnlock(1); + doorUnlock(2); + door1Locked=false; + door2Locked=false; + chirpAlarm(3); + } + + else{logprivFail();} + break; + } + case 'l': { // Lock all doors + lockall(); + chirpAlarm(1); + break; + } + + case '3': { // Train alarm sensors + if(privmodeEnabled==true) { + trainAlarm(); + } + else{logprivFail();} + break; + } + case '9': { // Show site status + PROGMEMprint(statusMessage1); + Serial.println(alarmArmed,DEC); + PROGMEMprint(statusMessage2); + Serial.println(alarmActivated,DEC); + PROGMEMprint(statusMessage3); + Serial.println(pollAlarm(3),DEC); + PROGMEMprint(statusMessage4); + Serial.println(pollAlarm(2),DEC); + PROGMEMprint(statusMessage5); + Serial.println(door1Locked); + PROGMEMprint(statusMessage6); + Serial.println(door2Locked); + break; + } + + case 'o': { + if(privmodeEnabled==true) { + if(atoi(cmdString[1]) == 1){ + alarmState(0); // Set to door chime only/open doors + armAlarm(4); + doorUnlock(1); // Open the door specified + door1locktimer=millis(); + break; + } + if(atoi(cmdString[1]) == 2){ + alarmState(0); // Set to door chime only/open doors + armAlarm(4); + doorUnlock(2); + door2locktimer=millis(); + break; + } + Serial.print("Invalid door number!"); + } + + else{logprivFail();} + break; + } + + case 'r': { // Remove a user + if(privmodeEnabled==true) { + dumpUser(atoi(cmdString[1])); + deleteUser(atoi(cmdString[1])); + } + else{logprivFail();} + break; + } + + case 'm': { // Add/change a user + if(privmodeEnabled==true) { + dumpUser(atoi(cmdString[1])); + addUser(atoi(cmdString[1]), atoi(cmdString[2]), strtoul(cmdString[3],NULL,10)); // Decimal add user defined + dumpUser(atoi(cmdString[1])); + } + else{logprivFail();} + + break; + } + + + case 't': { // Change date/time + if(privmodeEnabled==true) { + + Serial.print("Old time :"); + logDate(); + Serial.println(); + ds1307.setDateDs1307(atoi(cmdString[1]),atoi(cmdString[2]),atoi(cmdString[3]), + atoi(cmdString[4]),atoi(cmdString[5]),atoi(cmdString[6]),atoi(cmdString[7])); + Serial.print("New time :"); + logDate(); + Serial.println(); + } + else{logprivFail();} + + break; + } + + case 'h': { // Run hardware test + hardwareTest(atoi(cmdString[1])); + } + + case '?': { // Display help menu + PROGMEMprintln(consolehelpMessage1); + PROGMEMprintln(consolehelpMessage2); + PROGMEMprintln(consolehelpMessage3); + PROGMEMprintln(consolehelpMessage4); + PROGMEMprintln(consolehelpMessage5); + PROGMEMprintln(consolehelpMessage6); + PROGMEMprintln(consolehelpMessage7); + PROGMEMprintln(consolehelpMessage8); + PROGMEMprintln(consolehelpMessage9); + break; + } + + default: + PROGMEMprintln(consoledefaultMessage); + break; + } + + } // End of 'if' statement for Serial.available + } // End of 'if' for string finished +} // End of function + + + + +/* Wrapper functions for interrupt attachment + Could be cleaned up in library? + */ +void callReader1Zero(){wiegand26.reader1Zero();} +void callReader1One(){wiegand26.reader1One();} +void callReader2Zero(){wiegand26.reader2Zero();} +void callReader2One(){wiegand26.reader2One();} +void callReader3Zero(){wiegand26.reader3Zero();} +void callReader3One(){wiegand26.reader3One();} + + diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..0a16f2e --- /dev/null +++ b/README.txt @@ -0,0 +1,22 @@ +Instructions: + +1. Place the .ino and .h files in a directory under your Arduino sketeches folder named "Open_Access_Control_v4_std" . +2. Place the remaining directories in your Arduino libraries area (usually C:\Program Files (x86)\Arduino\libraries for Windows) +3. Restart the Arduino software if libraries were just added. +4. Connect up the Open Access v4. Allow the system to detect the USB/Serial port. Select "Arduino Duemillanove" from the +list of boards. +5. Change the privilege password in user.h and check other settings as needed. +6. Compile and upload the program. + +Changes: + +10/15/2013 (Version 1.40) +Ported libraries to work on Arduino Software 1.5 and higher +Removed "Superuser" functions +Removed unused test cases from reader function to save memory. + +10/23/2013 (Version 1.36) +Updated the lockall() function to fix bug when relocking all doors (I/O pins high instead of low) +Updated reader code to allow user to define whether or not a reader has a keypad from user.h file +Updated superuser code to disable superusers by default. + diff --git a/libraries/Adafruit_MCP23017/Adafruit_MCP23017.cpp b/libraries/Adafruit_MCP23017/Adafruit_MCP23017.cpp new file mode 100644 index 0000000..cb0bee4 --- /dev/null +++ b/libraries/Adafruit_MCP23017/Adafruit_MCP23017.cpp @@ -0,0 +1,230 @@ +/*************************************************** + This is a library for the MCP23017 i2c port expander + + These displays use I2C to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + +#include +#include +#include "Adafruit_MCP23017.h" + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +// minihelper +static inline void wiresend(uint8_t x) { +#if ARDUINO >= 100 + Wire.write((uint8_t)x); +#else + Wire.send(x); +#endif +} + +static inline uint8_t wirerecv(void) { +#if ARDUINO >= 100 + return Wire.read(); +#else + return Wire.receive(); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// + +void Adafruit_MCP23017::begin(uint8_t addr) { + if (addr > 7) { + addr = 7; + } + i2caddr = addr; + + Wire.begin(); + + + // set defaults! + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(MCP23017_IODIRA); + wiresend(0xFF); // all inputs on port A + Wire.endTransmission(); + + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(MCP23017_IODIRB); + wiresend(0xFF); // all inputs on port B + Wire.endTransmission(); +} + + +void Adafruit_MCP23017::begin(void) { + begin(0); +} + +void Adafruit_MCP23017::pinMode(uint8_t p, uint8_t d) { + uint8_t iodir; + uint8_t iodiraddr; + + // only 16 bits! + if (p > 15) + return; + + if (p < 8) + iodiraddr = MCP23017_IODIRA; + else { + iodiraddr = MCP23017_IODIRB; + p -= 8; + } + + // read the current IODIR + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(iodiraddr); + Wire.endTransmission(); + + Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); + iodir = wirerecv(); + + // set the pin and direction + if (d == INPUT) { + iodir |= 1 << p; + } else { + iodir &= ~(1 << p); + } + + // write the new IODIR + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(iodiraddr); + wiresend(iodir); + Wire.endTransmission(); +} + +uint16_t Adafruit_MCP23017::readGPIOAB() { + uint16_t ba = 0; + uint8_t a; + + // read the current GPIO output latches + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(MCP23017_GPIOA); + Wire.endTransmission(); + + Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2); + a = wirerecv(); + ba = wirerecv(); + ba <<= 8; + ba |= a; + + return ba; +} + +void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) { + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(MCP23017_GPIOA); + wiresend(ba & 0xFF); + wiresend(ba >> 8); + Wire.endTransmission(); +} + +void Adafruit_MCP23017::digitalWrite(uint8_t p, uint8_t d) { + uint8_t gpio; + uint8_t gpioaddr, olataddr; + + // only 16 bits! + if (p > 15) + return; + + if (p < 8) { + olataddr = MCP23017_OLATA; + gpioaddr = MCP23017_GPIOA; + } else { + olataddr = MCP23017_OLATB; + gpioaddr = MCP23017_GPIOB; + p -= 8; + } + + // read the current GPIO output latches + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(olataddr); + Wire.endTransmission(); + + Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); + gpio = wirerecv(); + + // set the pin and direction + if (d == HIGH) { + gpio |= 1 << p; + } else { + gpio &= ~(1 << p); + } + + // write the new GPIO + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(gpioaddr); + wiresend(gpio); + Wire.endTransmission(); +} + +void Adafruit_MCP23017::pullUp(uint8_t p, uint8_t d) { + uint8_t gppu; + uint8_t gppuaddr; + + // only 16 bits! + if (p > 15) + return; + + if (p < 8) + gppuaddr = MCP23017_GPPUA; + else { + gppuaddr = MCP23017_GPPUB; + p -= 8; + } + + + // read the current pullup resistor set + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(gppuaddr); + Wire.endTransmission(); + + Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); + gppu = wirerecv(); + + // set the pin and direction + if (d == HIGH) { + gppu |= 1 << p; + } else { + gppu &= ~(1 << p); + } + + // write the new GPIO + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(gppuaddr); + wiresend(gppu); + Wire.endTransmission(); +} + +uint8_t Adafruit_MCP23017::digitalRead(uint8_t p) { + uint8_t gpioaddr; + + // only 16 bits! + if (p > 15) + return 0; + + if (p < 8) + gpioaddr = MCP23017_GPIOA; + else { + gpioaddr = MCP23017_GPIOB; + p -= 8; + } + + // read the current GPIO + Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); + wiresend(gpioaddr); + Wire.endTransmission(); + + Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); + return (wirerecv() >> p) & 0x1; +} diff --git a/libraries/Adafruit_MCP23017/Adafruit_MCP23017.h b/libraries/Adafruit_MCP23017/Adafruit_MCP23017.h new file mode 100644 index 0000000..0e9ff5c --- /dev/null +++ b/libraries/Adafruit_MCP23017/Adafruit_MCP23017.h @@ -0,0 +1,63 @@ +/*************************************************** + This is a library for the MCP23017 i2c port expander + + These displays use I2C to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + +#ifndef _Adafruit_MCP23017_H_ +#define _Adafruit_MCP23017_H_ + +// Don't forget the Wire library +class Adafruit_MCP23017 { +public: + void begin(uint8_t addr); + void begin(void); + + void pinMode(uint8_t p, uint8_t d); + void digitalWrite(uint8_t p, uint8_t d); + void pullUp(uint8_t p, uint8_t d); + uint8_t digitalRead(uint8_t p); + + void writeGPIOAB(uint16_t); + uint16_t readGPIOAB(); + + private: + uint8_t i2caddr; +}; + +#define MCP23017_ADDRESS 0x20 + +// registers +#define MCP23017_IODIRA 0x00 +#define MCP23017_IPOLA 0x02 +#define MCP23017_GPINTENA 0x04 +#define MCP23017_DEFVALA 0x06 +#define MCP23017_INTCONA 0x08 +#define MCP23017_IOCONA 0x0A +#define MCP23017_GPPUA 0x0C +#define MCP23017_INTFA 0x0E +#define MCP23017_INTCAPA 0x10 +#define MCP23017_GPIOA 0x12 +#define MCP23017_OLATA 0x14 + + +#define MCP23017_IODIRB 0x01 +#define MCP23017_IPOLB 0x03 +#define MCP23017_GPINTENB 0x05 +#define MCP23017_DEFVALB 0x07 +#define MCP23017_INTCONB 0x09 +#define MCP23017_IOCONB 0x0B +#define MCP23017_GPPUB 0x0D +#define MCP23017_INTFB 0x0F +#define MCP23017_INTCAPB 0x11 +#define MCP23017_GPIOB 0x13 +#define MCP23017_OLATB 0x15 + +#endif diff --git a/libraries/Adafruit_MCP23017/README.txt b/libraries/Adafruit_MCP23017/README.txt new file mode 100644 index 0000000..e53140d --- /dev/null +++ b/libraries/Adafruit_MCP23017/README.txt @@ -0,0 +1,15 @@ +This is a library for the MCP23017 I2c Port Expander + +These chips use I2C to communicate, 2 pins required to interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above must be included in any redistribution + +To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_MCP23017. Check that the Adafruit_MCP23017 folder contains Adafruit_MCP23017.cpp and Adafruit_MCP23017.h + +Place the Adafruit_MCP23017 library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. \ No newline at end of file diff --git a/libraries/Adafruit_MCP23017/examples/button.pde b/libraries/Adafruit_MCP23017/examples/button.pde new file mode 100644 index 0000000..f06ce8f --- /dev/null +++ b/libraries/Adafruit_MCP23017/examples/button.pde @@ -0,0 +1,800 @@ + + + + + + + + + Adafruit-MCP23017-Arduino-Library/examples/button/button.pde at 17ab72f32b9128e00a21bac6c2b95d10681b1b39 · adafruit/Adafruit-MCP23017-Arduino-Library · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+
+
+ + + + + + +

+ public + + + / + Adafruit-MCP23017-Arduino-Library +

+
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + +
+ + ladyada + + + + + +
+ +
+
+ +
+
+
+
+ + 100644 + 31 lines (21 sloc) + 0.844 kb +
+ +
+
+ + + + + +
+
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+
+
+
#include <Wire.h>
#include "Adafruit_MCP23017.h"

// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!

// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)

// Input #0 is on pin 21 so connect a button or switch from there to ground

Adafruit_MCP23017 mcp;
  
void setup() {
  mcp.begin(); // use default address 0

  mcp.pinMode(0, INPUT);
  mcp.pullUp(0, HIGH); // turn on a 100K pullup internally

  pinMode(13, OUTPUT); // use the p13 LED as debugging
}



void loop() {
  // The LED will 'echo' the button
  digitalWrite(13, mcp.digitalRead(0));
}
+
+
+ +
+
+
+
+ +
+ + + +
+
+
+ + +
+ + + + + + + + +
+

Markdown Cheat Sheet

+ +
+ +
+
+

Format Text

+

Headers

+
+# This is an <h1> tag
+## This is an <h2> tag
+###### This is an <h6> tag
+

Text styles

+
+*This text will be italic*
+_This will also be italic_
+**This text will be bold**
+__This will also be bold__
+
+*You **can** combine them*
+
+
+
+

Lists

+

Unordered

+
+* Item 1
+* Item 2
+  * Item 2a
+  * Item 2b
+

Ordered

+
+1. Item 1
+2. Item 2
+3. Item 3
+   * Item 3a
+   * Item 3b
+
+
+

Miscellaneous

+

Images

+
+![GitHub Logo](/images/logo.png)
+Format: ![Alt Text](url)
+
+

Links

+
+http://github.com - automatic!
+[GitHub](http://github.com)
+

Blockquotes

+
+As Kanye West said:
+
+> We're living the future so
+> the present is our past.
+
+
+
+
+ +

Code Examples in Markdown

+
+

Syntax highlighting with GFM

+
+```javascript
+function fancyAlert(arg) {
+  if(arg) {
+    $.facebox({div:'#foo'})
+  }
+}
+```
+
+
+

Or, indent your code 4 spaces

+
+Here is a Python code example
+without syntax highlighting:
+
+    def foo:
+      if not bar:
+        return true
+
+
+

Inline code for comments

+
+I think you should use an
+`<addr>` element here instead.
+
+
+ +
+ + + +
+

Something went wrong with that request. Please try again. Dismiss

+
+ +
+

Looking for the GitHub logo?

+ +
+ + + + + + + + diff --git a/libraries/Adafruit_MCP23017/examples/button/button.pde b/libraries/Adafruit_MCP23017/examples/button/button.pde new file mode 100644 index 0000000..4a77f3f --- /dev/null +++ b/libraries/Adafruit_MCP23017/examples/button/button.pde @@ -0,0 +1,31 @@ +#include +#include "Adafruit_MCP23017.h" + +// Basic pin reading and pullup test for the MCP23017 I/O expander +// public domain! + +// Connect pin #12 of the expander to Analog 5 (i2c clock) +// Connect pin #13 of the expander to Analog 4 (i2c data) +// Connect pins #15, 16 and 17 of the expander to ground (address selection) +// Connect pin #9 of the expander to 5V (power) +// Connect pin #10 of the expander to ground (common ground) + +// Input #0 is on pin 21 so connect a button or switch from there to ground + +Adafruit_MCP23017 mcp; + +void setup() { + mcp.begin(); // use default address 0 + + mcp.pinMode(0, INPUT); + mcp.pullUp(0, HIGH); // turn on a 100K pullup internally + + pinMode(13, OUTPUT); // use the p13 LED as debugging +} + + + +void loop() { + // The LED will 'echo' the button + digitalWrite(13, mcp.digitalRead(0)); +} \ No newline at end of file diff --git a/libraries/Adafruit_MCP23017/examples/toggle.pde b/libraries/Adafruit_MCP23017/examples/toggle.pde new file mode 100644 index 0000000..03aa25e --- /dev/null +++ b/libraries/Adafruit_MCP23017/examples/toggle.pde @@ -0,0 +1,803 @@ + + + + + + + + + Adafruit-MCP23017-Arduino-Library/examples/toggle/toggle.pde at 17ab72f32b9128e00a21bac6c2b95d10681b1b39 · adafruit/Adafruit-MCP23017-Arduino-Library · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+
+
+ + + + + + +

+ public + + + / + Adafruit-MCP23017-Arduino-Library +

+
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + +
+ + ladyada + + + + + +
+ +
+
+ +
+
+
+
+ + 100644 + 34 lines (22 sloc) + 0.771 kb +
+ +
+
+ + + + + +
+
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+
+
+
#include <Wire.h>
#include "Adafruit_MCP23017.h"

// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!

// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)

// Output #0 is on pin 21 so connect an LED or whatever from that to ground

Adafruit_MCP23017 mcp;
  
void setup() {
  mcp.begin(); // use default address 0

  mcp.pinMode(0, OUTPUT);
}


// flip the pin #0 up and down

void loop() {
  delay(100);

  mcp.digitalWrite(0, HIGH);

  delay(100);

  mcp.digitalWrite(0, LOW);
}
+
+
+ +
+
+
+
+ +
+ + + +
+
+
+ + +
+ + + + + + + + +
+

Markdown Cheat Sheet

+ +
+ +
+
+

Format Text

+

Headers

+
+# This is an <h1> tag
+## This is an <h2> tag
+###### This is an <h6> tag
+

Text styles

+
+*This text will be italic*
+_This will also be italic_
+**This text will be bold**
+__This will also be bold__
+
+*You **can** combine them*
+
+
+
+

Lists

+

Unordered

+
+* Item 1
+* Item 2
+  * Item 2a
+  * Item 2b
+

Ordered

+
+1. Item 1
+2. Item 2
+3. Item 3
+   * Item 3a
+   * Item 3b
+
+
+

Miscellaneous

+

Images

+
+![GitHub Logo](/images/logo.png)
+Format: ![Alt Text](url)
+
+

Links

+
+http://github.com - automatic!
+[GitHub](http://github.com)
+

Blockquotes

+
+As Kanye West said:
+
+> We're living the future so
+> the present is our past.
+
+
+
+
+ +

Code Examples in Markdown

+
+

Syntax highlighting with GFM

+
+```javascript
+function fancyAlert(arg) {
+  if(arg) {
+    $.facebox({div:'#foo'})
+  }
+}
+```
+
+
+

Or, indent your code 4 spaces

+
+Here is a Python code example
+without syntax highlighting:
+
+    def foo:
+      if not bar:
+        return true
+
+
+

Inline code for comments

+
+I think you should use an
+`<addr>` element here instead.
+
+
+ +
+ + + +
+

Something went wrong with that request. Please try again. Dismiss

+
+ +
+

Looking for the GitHub logo?

+ +
+ + + + + + + + diff --git a/libraries/Adafruit_MCP23017/examples/toggle/toggle.pde b/libraries/Adafruit_MCP23017/examples/toggle/toggle.pde new file mode 100644 index 0000000..daa8da8 --- /dev/null +++ b/libraries/Adafruit_MCP23017/examples/toggle/toggle.pde @@ -0,0 +1,34 @@ +#include +#include "Adafruit_MCP23017.h" + +// Basic pin reading and pullup test for the MCP23017 I/O expander +// public domain! + +// Connect pin #12 of the expander to Analog 5 (i2c clock) +// Connect pin #13 of the expander to Analog 4 (i2c data) +// Connect pins #15, 16 and 17 of the expander to ground (address selection) +// Connect pin #9 of the expander to 5V (power) +// Connect pin #10 of the expander to ground (common ground) + +// Output #0 is on pin 21 so connect an LED or whatever from that to ground + +Adafruit_MCP23017 mcp; + +void setup() { + mcp.begin(); // use default address 0 + + mcp.pinMode(0, OUTPUT); +} + + +// flip the pin #0 up and down + +void loop() { + delay(100); + + mcp.digitalWrite(0, HIGH); + + delay(100); + + mcp.digitalWrite(0, LOW); +} \ No newline at end of file diff --git a/libraries/Adafruit_MCP23017/keywords.txt b/libraries/Adafruit_MCP23017/keywords.txt new file mode 100644 index 0000000..9014299 --- /dev/null +++ b/libraries/Adafruit_MCP23017/keywords.txt @@ -0,0 +1,21 @@ +####################################### +# Syntax Coloring Map for MCP23017 +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +MCP23017 KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +pullUp KEYWORD2 +writeGPIOAB KEYWORD2 +readGPIOAB KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/Adafruit_MCP23017/license.txt b/libraries/Adafruit_MCP23017/license.txt new file mode 100644 index 0000000..f6a0f22 --- /dev/null +++ b/libraries/Adafruit_MCP23017/license.txt @@ -0,0 +1,26 @@ +Software License Agreement (BSD License) + +Copyright (c) 2012, Adafruit Industries +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holders nor the +names of its contributors may be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libraries/DS1307/DS1307.cpp b/libraries/DS1307/DS1307.cpp new file mode 100644 index 0000000..2f97b1e --- /dev/null +++ b/libraries/DS1307/DS1307.cpp @@ -0,0 +1,119 @@ +/* +* Maurice Ribble +* 4-17-2008 +* http://www.glacialwanderer.com/hobbyrobotics +* This code tests the DS1307 Real Time clock on the Arduino board. +* The ds1307 works in binary coded decimal or BCD. You can look up +* bcd in google if you aren't familior with it. There can output +* a square wave, but I don't expose that in this code. See the +* ds1307 for it's full capabilities. +* +* Add Wire.begin(); to main setup function when ready to use. +* +* Modified 9/12/2009 by Arclight for C library use. +* arclight@gmail.com +*/ + +#include +#include + + +DS1307::DS1307(){ + +} + +DS1307::~DS1307(){ +} + + +// Convert normal decimal numbers to binary coded decimal +uint8_t DS1307::decToBcd(uint8_t val) +{ + return ( (val/10*16) + (val%10) ); +} + +// Convert binary coded decimal to normal decimal numbers +uint8_t DS1307::bcdToDec(uint8_t val) +{ + return ( (val/16*10) + (val%16) ); +} + +// Stops the DS1307, but it has the side effect of setting seconds to 0 +// Probably only want to use this for testing + +/* +void DS1307::stopDs1307() +{ + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write(0); + Wire.write(0x80); + Wire.endTransmission(); +} +*/ + +// 1) Sets the date and time on the ds1307 +// 2) Starts the clock +// 3) Sets hour mode to 24 hour clock +// Assumes you're passing in valid numbers + +void DS1307::setDateDs1307(uint8_t second, // 0-59 + uint8_t minute, // 0-59 + uint8_t hour, // 1-23 + uint8_t dayOfWeek, // 1-7 + uint8_t dayOfMonth, // 1-28/29/30/31 + uint8_t month, // 1-12 + uint8_t year) // 0-99 +{ + Wire.beginTransmission(DS1307_I2C_ADDRESS); + + Wire.write(byte(0)); + Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock + Wire.write(decToBcd(minute)); + Wire.write(decToBcd(hour)); // If you want 12 hour am/pm you need to set + // bit 6 (also need to change readDateDs1307) + Wire.write(decToBcd(dayOfWeek)); + Wire.write(decToBcd(dayOfMonth)); + Wire.write(decToBcd(month)); + Wire.write(decToBcd(year)); + Wire.endTransmission(); +} + +// Gets the date and time from the ds1307 +void DS1307::getDateDs1307(uint8_t *second, + uint8_t *minute, + uint8_t *hour, + uint8_t *dayOfWeek, + uint8_t *dayOfMonth, + uint8_t *month, + uint8_t *year) +{ + // Reset the register pointer + Wire.beginTransmission(DS1307_I2C_ADDRESS); + Wire.write(byte(0)); + Wire.endTransmission(); + + Wire.requestFrom(DS1307_I2C_ADDRESS, 7); + + // A few of these need masks because certain bits are control bits + *second = bcdToDec(Wire.read() & 0x7f); + *minute = bcdToDec(Wire.read()); + *hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm + *dayOfWeek = bcdToDec(Wire.read()); + *dayOfMonth = bcdToDec(Wire.read()); + *month = bcdToDec(Wire.read()); + *year = bcdToDec(Wire.read()); +} + +/* + // Change these values to what you want to set your clock to. + // You probably only want to set your clock once and then remove + // the setDateDs1307 call. +uint8_t second = 20; +uint8_t minute = 9; +uint8_t hour = 19; +uint8_t dayOfWeek = 6; +uint8_t dayOfMonth = 12; +uint8_t month = 9; +uint8_t year = 9; +setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year); +*/ diff --git a/libraries/DS1307/DS1307.h b/libraries/DS1307/DS1307.h new file mode 100644 index 0000000..f6a3cc7 --- /dev/null +++ b/libraries/DS1307/DS1307.h @@ -0,0 +1,44 @@ +/* Adds support for the DS1307 real-time clock chip (RTC) +*/ + +#ifndef _DS1307_H_ +#define _DS1307_H_ +#endif + +#ifndef _Wire_H_ +#define _Wire_H_ +#endif + +#include + +#define DS1307_I2C_ADDRESS 0x68 + + +extern byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; + +class DS1307 { +public: +DS1307(); +~DS1307(); + +void setDateDs1307(byte second, // 0-59 + byte minute, // 0-59 + byte hour, // 1-23 + byte dayOfWeek, // 1-7 + byte dayOfMonth, // 1-28/29/30/31 + byte month, // 1-12 + byte year); // 0-99 + +void getDateDs1307(byte *second, + byte *minute, + byte *hour, + byte *dayOfWeek, + byte *dayOfMonth, + byte *month, + byte *year); + +private: +byte decToBcd(byte val); +byte bcdToDec(byte val); + +}; diff --git a/libraries/DS1307/keywords.txt b/libraries/DS1307/keywords.txt new file mode 100644 index 0000000..543b2ba --- /dev/null +++ b/libraries/DS1307/keywords.txt @@ -0,0 +1,4 @@ +decToBcd KEYWORD2 +bcdToDec KEYWORD2 +setDateDs1307 KEYWORD2 +getDateDs1307 KEYWORD2 diff --git a/libraries/E24C1024/E24C1024.cpp b/libraries/E24C1024/E24C1024.cpp new file mode 100644 index 0000000..b70c28f --- /dev/null +++ b/libraries/E24C1024/E24C1024.cpp @@ -0,0 +1,76 @@ +/* + E24C1024.cpp + AT24C1024 Library for Arduino + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + + This library is based on several projects: + + The Arduino EEPROM library found here: + http://arduino.cc/en/Reference/EEPROM + + The 24C256 library found here: + http://www.arduino.cc/playground/Code/I2CEEPROM + + The 24C512 library found here: + http://www.arduino.cc/playground/Code/I2CEEPROM24LC512 + + Our project page is here: + http://www.arduino.cc/playground/Code/I2CEEPROM24C1024 + + From the datasheet: + + The AT24C1024B provides 1,048,576 bits of serial electrically + erasable and programmable read only memory (EEPROM) organized + as 131,072 words of 8 bits each. The devices cascadable + feature allows up to four devices to share a common two-wire + bus. + + http://www.atmel.com/dyn/resources/prod_documents/doc5194.pdf + +*/ + +#include +#include +#include "E24C1024.h" + +E24C1024::E24C1024(void) +{ + Wire.begin(); +} + +void E24C1024::write(unsigned long dataAddress, uint8_t data) +{ + Wire.beginTransmission((uint8_t)((0x500000 | dataAddress) >> 16)); // B1010xxx + Wire.write((uint8_t)((dataAddress & WORD_MASK) >> 8)); // MSB + Wire.write((uint8_t)(dataAddress & 0xFF)); // LSB + Wire.write(data); + Wire.endTransmission(); + delay(5); +} + +uint8_t E24C1024::read(unsigned long dataAddress) +{ + uint8_t data = 0x00; + Wire.beginTransmission((uint8_t)((0x500000 | dataAddress) >> 16)); // B1010xxx + Wire.write((uint8_t)((dataAddress & WORD_MASK) >> 8)); // MSB + Wire.write((uint8_t)(dataAddress & 0xFF)); // LSB + Wire.endTransmission(); + Wire.requestFrom(0x50,1); + if (Wire.available()) data = Wire.read(); + return data; +} + +E24C1024 EEPROM1024; diff --git a/libraries/E24C1024/E24C1024.h b/libraries/E24C1024/E24C1024.h new file mode 100644 index 0000000..4adbfd6 --- /dev/null +++ b/libraries/E24C1024/E24C1024.h @@ -0,0 +1,62 @@ +#ifndef E24C1024_h +#define E24C1024_h +/* + E24C1024.h + AT24C1024 Library for Arduino + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + + This library is based on several projects: + + The Arduino EEPROM library found here: + http://arduino.cc/en/Reference/EEPROM + + The 24C256 library found here: + http://www.arduino.cc/playground/Code/I2CEEPROM + + The 24C512 library found here: + http://www.arduino.cc/playground/Code/I2CEEPROM24LC512 + + Our project page is here: + http://www.arduino.cc/playground/Code/I2CEEPROM24C1024 + + From the datasheet: + + The AT24C1024B provides 1,048,576 bits of serial electrically + erasable and programmable read only memory (EEPROM) organized + as 131,072 words of 8 bits each. The devices cascadable + feature allows up to four devices to share a common two-wire + bus. + + http://www.atmel.com/dyn/resources/prod_documents/doc5194.pdf + +*/ + +//#include +#include +#define FULL_MASK 0x7FFFF +#define DEVICE_MASK 0x7F0000 +#define WORD_MASK 0xFFFF +class E24C1024 +{ + public: + E24C1024(); + static void write(unsigned long, uint8_t); + static uint8_t read(unsigned long); +}; + +extern E24C1024 EEPROM1024; + +#endif diff --git a/libraries/E24C1024/examples/EEPROM1024/EEPROM1024.pde b/libraries/E24C1024/examples/EEPROM1024/EEPROM1024.pde new file mode 100644 index 0000000..daaf814 --- /dev/null +++ b/libraries/E24C1024/examples/EEPROM1024/EEPROM1024.pde @@ -0,0 +1,115 @@ +/* + EEPROM1024.pde + AT24C1024 EEPROM Benchmark Sketch + + Our project page is here: + http://www.arduino.cc/playground/Code/I2CEEPROM24C1024 + + From the datasheet: + + The AT24C1024B provides 1,048,576 bits of serial electrically + erasable and programmable read only memory (EEPROM) organized + as 131,072 words of 8 bits each. The device’s cascadable + feature allows up to four devices to share a common two-wire + bus. + + http://www.atmel.com/dyn/resources/prod_documents/doc5194.pdf + +*/ +#include +#include +#include + +unsigned long time; +unsigned long finishTime; +unsigned long errors = 0; +unsigned long address = 0; +byte loop_size; + +// Set to a higher number if you want to start at a higher address. +#define MIN_ADDRESS 0 + +// Upper boundary of the address space. Choose one. +#define MAX_ADDRESS 131072 // 1 device +//#define MAX_ADDRESS 262144 // 2 devices +//#define MAX_ADDRESS 393216 // 3 devices +//#define MAX_ADDRESS 524288 // 4 devices + +void setup() +{ + // Make sure we aren't reading old data + randomSeed(analogRead(0)); + loop_size = random(1, 100); + Serial.begin(9600); + Serial.println(); + Serial.println("E24C1024 Library Benchmark Sketch"); + Serial.println(); + writeByByteTest(); + readByByteTest(); +} + +void loop() +{ +} + +void writeByByteTest() +{ + time = millis(); + errors = 0; + Serial.println("--------------------------------"); + Serial.println("Write By Byte Test:"); + Serial.println(); + Serial.print("Writing data:"); + for (address = MIN_ADDRESS; address < MAX_ADDRESS; address++) + { + EEPROM1024.write(address, (uint8_t)(address % loop_size)); + if (!(address % 5000)) Serial.print("."); + } + finishTime = millis() - time; + Serial.println("DONE"); + Serial.print("Total Time (seconds): "); + Serial.println((unsigned long)(finishTime / 1000)); + Serial.print("Write operations per second: "); + Serial.println((unsigned long)(MAX_ADDRESS / (finishTime / 1000))); + Serial.println("--------------------------------"); + Serial.println(); +} + +void readByByteTest() +{ + time = millis(); + errors = 0; + Serial.println("--------------------------------"); + Serial.println("Read By Byte Test:"); + Serial.println(); + Serial.print("Reading data:"); + for (address = MIN_ADDRESS; address < MAX_ADDRESS; address++) + { + uint8_t data; + data = EEPROM1024.read(address); + if (data != (uint8_t)(address % loop_size)) + { + Serial.println(); + Serial.print("Address: "); + Serial.print(address); + Serial.print(" Should be: "); + Serial.print((uint8_t)(address % loop_size), DEC); + Serial.print(" Read val: "); + Serial.println(data, DEC); + errors++; + } + if (!(address % 5000)) Serial.print("."); + } + finishTime = millis() - time; + Serial.println("DONE"); + Serial.println(); + Serial.print("Total Test Time (secs): "); + Serial.println((unsigned long)(finishTime / 1000)); + Serial.print("Read operations per second: "); + Serial.println((unsigned long)(MAX_ADDRESS / (finishTime / 1000))); + Serial.print("Total errors: "); + Serial.println(errors); + Serial.println("--------------------------------"); + Serial.println(); +} + diff --git a/libraries/NewSoftSerial/Examples/NewSoftSerialTest/NewSoftSerialTest.pde b/libraries/NewSoftSerial/Examples/NewSoftSerialTest/NewSoftSerialTest.pde new file mode 100644 index 0000000..0d9e815 --- /dev/null +++ b/libraries/NewSoftSerial/Examples/NewSoftSerialTest/NewSoftSerialTest.pde @@ -0,0 +1,25 @@ + +#include + +NewSoftSerial mySerial(2, 3); + +void setup() +{ + Serial.begin(57600); + Serial.println("Goodnight moon!"); + + // set the data rate for the NewSoftSerial port + mySerial.begin(4800); + mySerial.println("Hello, world?"); +} + +void loop() // run over and over again +{ + + if (mySerial.available()) { + Serial.print((char)mySerial.read()); + } + if (Serial.available()) { + mySerial.print((char)Serial.read()); + } +} diff --git a/libraries/NewSoftSerial/Examples/TwoNSSTest/TwoNSSTest.pde b/libraries/NewSoftSerial/Examples/TwoNSSTest/TwoNSSTest.pde new file mode 100644 index 0000000..73aa991 --- /dev/null +++ b/libraries/NewSoftSerial/Examples/TwoNSSTest/TwoNSSTest.pde @@ -0,0 +1,33 @@ +#include + +NewSoftSerial nss(2, 3); +NewSoftSerial nss2(4, 5); + +void setup() +{ + nss2.begin(4800); + nss.begin(4800); + Serial.begin(115200); +} + +void loop() +{ + // Every 10 seconds switch from + // one serial GPS device to the other + if ((millis() / 10000) % 2 == 0) + { + if (nss.available()) + { + Serial.print(nss.read(), BYTE); + } + } + + else + { + if (nss2.available()) + { + Serial.print(nss2.read(), BYTE); + } + } +} + diff --git a/libraries/NewSoftSerial/NewSoftSerial.cpp b/libraries/NewSoftSerial/NewSoftSerial.cpp new file mode 100644 index 0000000..463ab01 --- /dev/null +++ b/libraries/NewSoftSerial/NewSoftSerial.cpp @@ -0,0 +1,539 @@ +/* +NewSoftSerial.cpp - Multi-instance software serial library +Copyright (c) 2006 David A. Mellis. All rights reserved. +-- Interrupt-driven receive and other improvements by ladyada +-- Tuning, circular buffer, derivation from class Print, + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +The latest version of this library can always be found at +http://arduiniana.org. +*/ + +// When set, _DEBUG co-opts pins 11 and 13 for debugging with an +// oscilloscope or logic analyzer. Beware: it also slightly modifies +// the bit times, so don't rely on it too much at high baud rates +#define _DEBUG 0 +#define _DEBUG_PIN1 11 +#define _DEBUG_PIN2 13 +// +// Includes +// +#include +#include +#include "WConstants.h" +#include "pins_arduino.h" +#include "NewSoftSerial.h" + +// Abstractions for maximum portability between processors +// These are macros to associate pins to pin change interrupts +#if !defined(digitalPinToPCICR) // Courtesy Paul Stoffregen +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) +#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)NULL)) +#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) +#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)NULL)))) +#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) +#else +#define digitalPinToPCICR(p) ((uint8_t *)NULL) +#define digitalPinToPCICRbit(p) 0 +#define digitalPinToPCMSK(p) ((uint8_t *)NULL) +#define digitalPinToPCMSKbit(p) 0 +#endif +#endif + +// +// Lookup table +// +typedef struct _DELAY_TABLE +{ + long baud; + unsigned short rx_delay_centering; + unsigned short rx_delay_intrabit; + unsigned short rx_delay_stopbit; + unsigned short tx_delay; +} DELAY_TABLE; + +#if F_CPU == 16000000 + +static const DELAY_TABLE PROGMEM table[] = +{ + // baud rxcenter rxintra rxstop tx + { 115200, 1, 17, 17, 12, }, + { 57600, 10, 37, 37, 33, }, + { 38400, 25, 57, 57, 54, }, + { 31250, 31, 70, 70, 68, }, + { 28800, 34, 77, 77, 74, }, + { 19200, 54, 117, 117, 114, }, + { 14400, 74, 156, 156, 153, }, + { 9600, 114, 236, 236, 233, }, + { 4800, 233, 474, 474, 471, }, + { 2400, 471, 950, 950, 947, }, + { 1200, 947, 1902, 1902, 1899, }, + { 300, 3804, 7617, 7617, 7614, }, +}; + +const int XMIT_START_ADJUSTMENT = 5; + +#elif F_CPU == 8000000 + +static const DELAY_TABLE table[] PROGMEM = +{ + // baud rxcenter rxintra rxstop tx + { 115200, 1, 5, 5, 3, }, + { 57600, 1, 15, 15, 13, }, + { 38400, 2, 25, 26, 23, }, + { 31250, 7, 32, 33, 29, }, + { 28800, 11, 35, 35, 32, }, + { 19200, 20, 55, 55, 52, }, + { 14400, 30, 75, 75, 72, }, + { 9600, 50, 114, 114, 112, }, + { 4800, 110, 233, 233, 230, }, + { 2400, 229, 472, 472, 469, }, + { 1200, 467, 948, 948, 945, }, + { 300, 1895, 3805, 3805, 3802, }, +}; + +const int XMIT_START_ADJUSTMENT = 4; + +#elif F_CPU == 20000000 + +// 20MHz support courtesy of the good people at macegr.com. +// Thanks, Garrett! + +static const DELAY_TABLE PROGMEM table[] = +{ + // baud rxcenter rxintra rxstop tx + { 115200, 3, 21, 21, 18, }, + { 57600, 20, 43, 43, 41, }, + { 38400, 37, 73, 73, 70, }, + { 31250, 45, 89, 89, 88, }, + { 28800, 46, 98, 98, 95, }, + { 19200, 71, 148, 148, 145, }, + { 14400, 96, 197, 197, 194, }, + { 9600, 146, 297, 297, 294, }, + { 4800, 296, 595, 595, 592, }, + { 2400, 592, 1189, 1189, 1186, }, + { 1200, 1187, 2379, 2379, 2376, }, + { 300, 4759, 9523, 9523, 9520, }, +}; + +const int XMIT_START_ADJUSTMENT = 6; + +#else + +#error This version of NewSoftSerial supports only 20, 16 and 8MHz processors + +#endif + +// +// Statics +// +NewSoftSerial *NewSoftSerial::active_object = 0; +char NewSoftSerial::_receive_buffer[_NewSS_MAX_RX_BUFF]; +volatile uint8_t NewSoftSerial::_receive_buffer_tail = 0; +volatile uint8_t NewSoftSerial::_receive_buffer_head = 0; + +// +// Debugging +// +// This function generates a brief pulse +// for debugging or measuring on an oscilloscope. +inline void DebugPulse(uint8_t pin, uint8_t count) +{ +#if _DEBUG + volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); + + uint8_t val = *pport; + while (count--) + { + *pport = val | digitalPinToBitMask(pin); + *pport = val; + } +#endif +} + +// +// Private methods +// + +/* static */ +inline void NewSoftSerial::tunedDelay(uint16_t delay) { + uint8_t tmp=0; + + asm volatile("sbiw %0, 0x01 \n\t" + "ldi %1, 0xFF \n\t" + "cpi %A0, 0xFF \n\t" + "cpc %B0, %1 \n\t" + "brne .-10 \n\t" + : "+r" (delay), "+a" (tmp) + : "0" (delay) + ); +} + +// This function sets the current object as the "active" +// one and returns true if it replaces another +bool NewSoftSerial::activate(void) +{ + if (active_object != this) + { + _buffer_overflow = false; + uint8_t oldSREG = SREG; + cli(); + _receive_buffer_head = _receive_buffer_tail = 0; + active_object = this; + SREG = oldSREG; + return true; + } + + return false; +} + +// +// The receive routine called by the interrupt handler +// +void NewSoftSerial::recv() +{ + +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Preserve the registers that the compiler misses +// (courtesy of Arduino forum user *etracer*) + asm volatile( + "push r18 \n\t" + "push r19 \n\t" + "push r20 \n\t" + "push r21 \n\t" + "push r22 \n\t" + "push r23 \n\t" + "push r26 \n\t" + "push r27 \n\t" + ::); +#endif + + uint8_t d = 0; + + // If RX line is high, then we don't see any start bit + // so interrupt is probably not for us + if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) + { + // Wait approximately 1/2 of a bit width to "center" the sample + tunedDelay(_rx_delay_centering); + DebugPulse(_DEBUG_PIN2, 1); + + // Read each of the 8 bits + for (uint8_t i=0x1; i; i <<= 1) + { + tunedDelay(_rx_delay_intrabit); + DebugPulse(_DEBUG_PIN2, 1); + uint8_t noti = ~i; + if (rx_pin_read()) + d |= i; + else // else clause added to ensure function timing is ~balanced + d &= noti; + } + + // skip the stop bit + tunedDelay(_rx_delay_stopbit); + DebugPulse(_DEBUG_PIN2, 1); + + if (_inverse_logic) + d = ~d; + + // if buffer full, set the overflow flag and return + if ((_receive_buffer_tail + 1) % _NewSS_MAX_RX_BUFF != _receive_buffer_head) + { + // save new data in buffer: tail points to where byte goes + _receive_buffer[_receive_buffer_tail] = d; // save new byte + _receive_buffer_tail = (_receive_buffer_tail + 1) % _NewSS_MAX_RX_BUFF; + } + else + { +#if _DEBUG // for scope: pulse pin as overflow indictator + DebugPulse(_DEBUG_PIN1, 1); +#endif + _buffer_overflow = true; + } + } + +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Restore the registers that the compiler misses + asm volatile( + "pop r27 \n\t" + "pop r26 \n\t" + "pop r23 \n\t" + "pop r22 \n\t" + "pop r21 \n\t" + "pop r20 \n\t" + "pop r19 \n\t" + "pop r18 \n\t" + ::); +#endif +} + +void NewSoftSerial::tx_pin_write(uint8_t pin_state) +{ + if (pin_state == LOW) + *_transmitPortRegister &= ~_transmitBitMask; + else + *_transmitPortRegister |= _transmitBitMask; +} + +uint8_t NewSoftSerial::rx_pin_read() +{ + return *_receivePortRegister & _receiveBitMask; +} + +// +// Interrupt handling +// + +/* static */ +inline void NewSoftSerial::handle_interrupt() +{ + if (active_object) + { + active_object->recv(); + } +} + +#if defined(PCINT0_vect) +ISR(PCINT0_vect) +{ + NewSoftSerial::handle_interrupt(); +} +#endif + +#if defined(PCINT1_vect) +ISR(PCINT1_vect) +{ + NewSoftSerial::handle_interrupt(); +} +#endif + +#if defined(PCINT2_vect) +ISR(PCINT2_vect) +{ + NewSoftSerial::handle_interrupt(); +} +#endif + +#if defined(PCINT3_vect) +ISR(PCINT3_vect) +{ + NewSoftSerial::handle_interrupt(); +} +#endif + +// +// Constructor +// +NewSoftSerial::NewSoftSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : + _rx_delay_centering(0), + _rx_delay_intrabit(0), + _rx_delay_stopbit(0), + _tx_delay(0), + _buffer_overflow(false), + _inverse_logic(inverse_logic) +{ + setTX(transmitPin); + setRX(receivePin); +} + +// +// Destructor +// +NewSoftSerial::~NewSoftSerial() +{ + end(); +} + +void NewSoftSerial::setTX(uint8_t tx) +{ + pinMode(tx, OUTPUT); + digitalWrite(tx, HIGH); + _transmitBitMask = digitalPinToBitMask(tx); + uint8_t port = digitalPinToPort(tx); + _transmitPortRegister = portOutputRegister(port); +} + +void NewSoftSerial::setRX(uint8_t rx) +{ + pinMode(rx, INPUT); + if (!_inverse_logic) + digitalWrite(rx, HIGH); // pullup for normal logic! + _receivePin = rx; + _receiveBitMask = digitalPinToBitMask(rx); + uint8_t port = digitalPinToPort(rx); + _receivePortRegister = portInputRegister(port); +} + +// +// Public methods +// + +void NewSoftSerial::begin(long speed) +{ + _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; + + for (unsigned i=0; i +#include "Print.h" + +/****************************************************************************** +* Definitions +******************************************************************************/ + +#define _NewSS_MAX_RX_BUFF 64 // RX buffer size +#define _NewSS_VERSION 10 // software version of this library +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +class NewSoftSerial : public Print +{ +private: + // per object data + uint8_t _receivePin; + uint8_t _receiveBitMask; + volatile uint8_t *_receivePortRegister; + uint8_t _transmitBitMask; + volatile uint8_t *_transmitPortRegister; + + uint16_t _rx_delay_centering; + uint16_t _rx_delay_intrabit; + uint16_t _rx_delay_stopbit; + uint16_t _tx_delay; + + uint16_t _buffer_overflow:1; + uint16_t _inverse_logic:1; + + // static data + static char _receive_buffer[_NewSS_MAX_RX_BUFF]; + static volatile uint8_t _receive_buffer_tail; + static volatile uint8_t _receive_buffer_head; + static NewSoftSerial *active_object; + + // private methods + void recv(); + bool activate(); + virtual void write(uint8_t byte); + uint8_t rx_pin_read(); + void tx_pin_write(uint8_t pin_state); + void setTX(uint8_t transmitPin); + void setRX(uint8_t receivePin); + + // private static method for timing + static inline void tunedDelay(uint16_t delay); + +public: + // public methods + NewSoftSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + ~NewSoftSerial(); + void begin(long speed); + void end(); + int read(); + uint8_t available(void); + bool active() { return this == active_object; } + bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; } + static int library_version() { return _NewSS_VERSION; } + static void enable_timer0(bool enable); + void flush(); + + // public only for easy access by interrupt handlers + static inline void handle_interrupt(); +}; + +// Arduino 0012 workaround +#undef int +#undef char +#undef long +#undef byte +#undef float +#undef abs +#undef round + +#endif diff --git a/libraries/NewSoftSerial/NewSoftSerial.o b/libraries/NewSoftSerial/NewSoftSerial.o new file mode 100644 index 0000000000000000000000000000000000000000..0d6361c2541f7553084f5212cc02d31d46999857 GIT binary patch literal 21940 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 literal 0 HcmV?d00001 diff --git a/libraries/NewSoftSerial/keywords.txt b/libraries/NewSoftSerial/keywords.txt new file mode 100644 index 0000000..2eba1af --- /dev/null +++ b/libraries/NewSoftSerial/keywords.txt @@ -0,0 +1,30 @@ +####################################### +# Syntax Coloring Map for NewSoftSerial +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +NewSoftSerial KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +setTX KEYWORD2 +setRX KEYWORD2 +begin KEYWORD2 +end KEYWORD2 +read KEYWORD2 +available KEYWORD2 +active KEYWORD2 +overflow KEYWORD2 +library_version KEYWORD2 +enable_timer0 KEYWORD2 +flush KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/PCATTACH/PCATTACH.cpp b/libraries/PCATTACH/PCATTACH.cpp new file mode 100644 index 0000000..fa2cb31 --- /dev/null +++ b/libraries/PCATTACH/PCATTACH.cpp @@ -0,0 +1,138 @@ +#include "pins_arduino.h" +#include "PCATTACH.h" + +/* + * an extension to the interrupt support for arduino. + * add pin change interrupts to the external interrupts, giving a way + * for users to have interrupts drive off of any pin. + * Refer to avr-gcc header files, arduino source and atmega datasheet. + */ + +/* + * Theory: all IO pins on Atmega168 are covered by Pin Change Interrupts. + * The PCINT corresponding to the pin must be enabled and masked, and + * an ISR routine provided. Since PCINTs are per port, not per pin, the ISR + * must use some logic to actually implement a per-pin interrupt service. + */ + +PCATTACH::PCATTACH(){ + +} + +PCATTACH::~PCATTACH(){ +} + +PCATTACH pc1; + +/* Pin to interrupt map: + * D0-D7 = PCINT 16-23 = PCIR2 = PD = PCIE2 = pcmsk2 + * D8-D13 = PCINT 0-5 = PCIR0 = PB = PCIE0 = pcmsk0 + * A0-A5 (D14-D19) = PCINT 8-13 = PCIR1 = PC = PCIE1 = pcmsk1 + */ + +volatile uint8_t *port_to_pcmask[] = { + &PCMSK0, + &PCMSK1, + &PCMSK2 +}; + +typedef void (*voidFuncPtr)(void); + +volatile static voidFuncPtr PCintFunc[24] = { + NULL }; + +volatile static uint8_t PCintLast[3]; + +/* + * attach an interrupt to a specific pin using pin change interrupts. + * First version only supports CHANGE mode. + */ + void PCATTACH::PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) { + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t slot; + volatile uint8_t *pcmask; + + if (mode != CHANGE) { + return; + } + // map pin to PCIR register + if (port == NOT_A_PORT) { + return; + } + else { + port -= 2; + pcmask = port_to_pcmask[port]; + } + slot = port * 8 + (pin % 8); + PCintFunc[slot] = userFunc; + // set the mask + *pcmask |= bit; + // enable the interrupt + PCICR |= 0x01 << port; +} + +void PCATTACH::PCdetachInterrupt(uint8_t pin) { + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *pcmask; + + // map pin to PCIR register + if (port == NOT_A_PORT) { + return; + } + else { + port -= 2; + pcmask = port_to_pcmask[port]; + } + + // disable the mask. + *pcmask &= ~bit; + // if that's the last one, disable the interrupt. + if (*pcmask == 0) { + PCICR &= ~(0x01 << port); + } +} + +// common code for isr handler. "port" is the PCINT number. +// there isn't really a good way to back-map ports and masks to pins. + +void PCATTACH::PCint(uint8_t port) { + uint8_t bit; + uint8_t curr; + uint8_t mask; + uint8_t pin; + + // get the pin states for the indicated port. + curr = *portInputRegister(port+2); + mask = curr ^ PCintLast[port]; + PCintLast[port] = curr; + // mask is pins that have changed. screen out non pcint pins. + if ((mask &= *port_to_pcmask[port]) == 0) { + return; + } + // mask is pcint pins that have changed. + for (uint8_t i=0; i < 8; i++) { + bit = 0x01 << i; + if (bit & mask) { + pin = port * 8 + i; + if (PCintFunc[pin] != NULL) { + PCintFunc[pin](); + } + } + } +} + + +SIGNAL (PCINT0_vect) { + pc1.PCint(0); +} +SIGNAL (PCINT1_vect) { + pc1.PCint(1); +} +SIGNAL (PCINT2_vect) { + pc1.PCint(2); +} + + + diff --git a/libraries/PCATTACH/PCATTACH.h b/libraries/PCATTACH/PCATTACH.h new file mode 100644 index 0000000..bb3da60 --- /dev/null +++ b/libraries/PCATTACH/PCATTACH.h @@ -0,0 +1,30 @@ +#ifndef _PCATTACH_H_ +#define _PCATTACH_H_ +#endif + +#include + +class PCATTACH { + +public: +PCATTACH(); +~PCATTACH(); + + + +void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode); +void PCdetachInterrupt(uint8_t pin); + + +static void PCint(uint8_t); + +/* +volatile uint8_t *port_to_pcmask[]; +typedef void (*voidFuncPtr)(void); +volatile static voidFuncPtr PCintFunc[]; +volatile static uint8_t PCintLast[]; +*/ + + +}; + diff --git a/libraries/PCATTACH/keywords.txt b/libraries/PCATTACH/keywords.txt new file mode 100644 index 0000000..497a9f8 --- /dev/null +++ b/libraries/PCATTACH/keywords.txt @@ -0,0 +1,2 @@ +PCattachInterrupt KEYWORD2 +PCdetachInterrupt KEYWORD2 diff --git a/libraries/Wiegand26/WIEGAND26.cpp b/libraries/Wiegand26/WIEGAND26.cpp new file mode 100644 index 0000000..2eb4ce0 --- /dev/null +++ b/libraries/Wiegand26/WIEGAND26.cpp @@ -0,0 +1,118 @@ +#include + +extern byte reader1Pins[]; // Reader 1 connected to pins 4,5 +extern byte reader2Pins[]; // Reader2 connected to pins 6,7 +extern byte reader3Pins[]; // Reader3 connected to pins X,Y +extern long reader1; +extern int reader1Count; +extern long reader2; +extern int reader2Count; +extern long reader3; +extern int reader3Count; + + +WIEGAND26::WIEGAND26(){ +} + +WIEGAND26::~WIEGAND26(){ +} + + + +/* Wiegand Reader code. Modify as needed or comment out unused readers. + * system supports up to 3 independent readers. + */ + + + +void WIEGAND26::initReaderOne(void) { + for(byte i=0; i<2; i++){ + pinMode(reader1Pins[i], OUTPUT); + digitalWrite(reader1Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader1Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader1Pins[i], INPUT); + digitalWrite(reader1Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader1Count=0; + reader1=0; +} + + +void WIEGAND26::initReaderTwo(void) { + for(byte i=0; i<2; i++){ + pinMode(reader2Pins[i], OUTPUT); + digitalWrite(reader2Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader2Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader2Pins[i], INPUT); + digitalWrite(reader2Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader2Count=0; + reader2=0; +} + + + +void WIEGAND26::reader1One() { + if(digitalRead(reader1Pins[1]) == LOW){ + reader1Count++; + reader1 = reader1 << 1; + reader1 |= 1; + } +} + +void WIEGAND26::reader1Zero() { + if(digitalRead(reader1Pins[0]) == LOW){ + reader1Count++; + reader1 = reader1 << 1; + + } +} + + +void WIEGAND26::reader2One() { + if(digitalRead(reader2Pins[1]) == LOW){ + reader2Count++; + reader2 = reader2 << 1; + reader2 |= 1; + } +} + +void WIEGAND26::reader2Zero(void) { + if(digitalRead(reader2Pins[0]) == LOW){ + reader2Count++; + reader2 = reader2 << 1; + } +} + + + +void WIEGAND26::initReaderThree(void) { + for(byte i=0; i<2; i++){ + pinMode(reader3Pins[i], OUTPUT); + digitalWrite(reader3Pins[i], HIGH); // enable internal pull up causing a one + digitalWrite(reader3Pins[i], LOW); // disable internal pull up causing zero and thus an interrupt + pinMode(reader3Pins[i], INPUT); + digitalWrite(reader3Pins[i], HIGH); // enable internal pull up + } + delay(10); + reader3Count=0; + reader3=0; + } + + void WIEGAND26::reader3One(void) { + if(digitalRead(reader3Pins[1]) == LOW){ + reader3Count++; + reader3 = reader3 << 1; + reader3 |= 1; + } + } + + void WIEGAND26::reader3Zero(void) { + if(digitalRead(reader3Pins[0]) == LOW){ + reader3Count++; + reader3 = reader3 << 1; + } + } + diff --git a/libraries/Wiegand26/WIEGAND26.h b/libraries/Wiegand26/WIEGAND26.h new file mode 100644 index 0000000..621b2d3 --- /dev/null +++ b/libraries/Wiegand26/WIEGAND26.h @@ -0,0 +1,36 @@ +#ifndef _WIEGAND26_H_ +#define _WIEGAND26_H_ +#endif + +#include + +class WIEGAND26 { +public: +WIEGAND26(); +~WIEGAND26(); + + +//const byte reader1Pins[]; // Reader 1 connected to pins 4,5 +//const byte reader2Pins[]; // Reader2 connected to pins 6,7 +//const byte reader3Pins[]; // Reader3 connected to pins X,Y + +//volatile long reader1; +//volatile int reader1Count; +//volatile long reader2; +//volatile int reader2Count; +//volatile long reader3; +//volatile int reader3Count; + +void initReaderOne(void); +void initReaderTwo(void); +void reader1One(void); +void reader1Zero(void); +void reader2One(void); +void reader2Zero(void); +void initReaderThree(void); +void reader3One(void); +void reader3Zero(void); + +private: + +}; diff --git a/libraries/Wiegand26/keywords.txt b/libraries/Wiegand26/keywords.txt new file mode 100644 index 0000000..8b8118e --- /dev/null +++ b/libraries/Wiegand26/keywords.txt @@ -0,0 +1,9 @@ +initReaderOne KEYWORD2 +initReaderTwo KEYWORD2 +reader1One KEYWORD2 +reader1Zero KEYWORD2 +reader2One KEYWORD2 +reader2Zero KEYWORD2 +initReaderThree KEYWORD2 +reader3One KEYWORD2 +reader3Zero KEYWORD2 diff --git a/user.h b/user.h new file mode 100644 index 0000000..2211c80 --- /dev/null +++ b/user.h @@ -0,0 +1,41 @@ +/* User preferences file - Modify this header to use the correct options for your + * installation. + * Be sure to set the passwords/etc, as the defaul is "1234" + */ + +/* Hardware options + * + */ +#define MCU328 // Set this if using any boards other than the "Mega" +#define HWV4STD // Use this option if using Open access v3 Standard board + +#define MCPIOXP // Set this if using the v4 hardware with the MCP23017 i2c IO chip +//#define AT24EEPROM // Set this if you have the At24C i2c EEPROM chip installed + +#define READER2KEYPAD 0 // Set this if your second reader has a keypad + + +/* Static user List - Implemented as an array for testing and access override +*/ +//#define LCDBOARD // Uncomment to use LCD board + // Uses the "cLCD" library that extends arduino LCD class + // Has issues - must use a non-standard pinout, disables other MCP IO pins + // Library is from the TC4 Coffee Roaster project + // Download here: http://code.google.com/p/tc4-shield/ + + +#define DEBUG 2 // Set to 4 for display of raw tag numbers in BIN, 3 for decimal, 2 for HEX, 1 for only denied, 0 for never. +#define VERSION 1.40 +#define UBAUDRATE 9600 // Set the baud rate for the USB serial port + +#define PRIVPASSWORD 0x1234 // Console "priveleged mode" password + +#define DOORDELAY 5000 // How long to open door lock once access is granted. (2500 = 2.5s) +#define SENSORTHRESHOLD 100 // Analog sensor change that will trigger an alarm (0..255) +#define KEYPADTIMEOUT 5000 // Timeout for pin pad entry. Users on keypads can enter commands after reader swipe. +#define CARDFORMAT 1 // Card format + // 0=first 25 raw bytes from card + // 1=First and second parity bits stripped (default for most systems) +#define BEDTIME 23 // Set the time to automatically relock front door. +#define BEDTIME_ENABLED 0 // Determine whether or not to relock front door nightly +