An access controller for man doors at our facility. It receives Wiegand signals from a keypad/card reader and activates a relay to open the door. Access codes are stored in EEPROM. The active code list is updated from TFTP on a local server.
Dependencies: 24LCxx_I2C CardReader USBHOST
Diff: CodeMemory.cpp
- Revision:
- 0:a56239ae90c2
diff -r 000000000000 -r a56239ae90c2 CodeMemory.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CodeMemory.cpp Mon Sep 25 19:02:40 2017 +0000 @@ -0,0 +1,326 @@ + +#include "CodeMemory.h" + +void CodeMemory::EEPROMClear() +{ + for (int i = 0 ; i < EEPROM_LENGTH ; i += 4) + { + _eeprom->Write(i, (int)0, C24LCXX_I2C::LittleEndian); + } +} + +unsigned short CodeMemory::ReadAccessCode(unsigned short address) +{ + // Read two bytes at the specified address + short code; + _eeprom->Read((short)address, &code, C24LCXX_I2C::LittleEndian); + + return code; +} + +void CodeMemory::WriteAccessCode(unsigned short address, unsigned short value) +{ + //Write the bytes into the eeprom memory. + _eeprom->Write(address, (short)value, C24LCXX_I2C::LittleEndian); + + return; +} + +unsigned int CodeMemory::ReadEEPROMULong(unsigned short address) +{ + // Read four bytes at the specified address. + int value; + _eeprom->Read((short)address, &value, C24LCXX_I2C::LittleEndian); + + return value; +} + +void CodeMemory::WriteEEPROMULong(unsigned short address, unsigned int value) +{ + _eeprom->Write((short)address, (int)value, C24LCXX_I2C::LittleEndian); + + return; +} + +// Find the address of the specified code +int CodeMemory::FindAccessCode(unsigned short code) +{ + return FindAccessCode(code, 0, CODE_TABLE_SIZE); +} + +int CodeMemory::FindAccessCode(unsigned short code, unsigned short startAddress, unsigned short stopAddress) +{ + int address = startAddress; + while ((address < stopAddress) && (ReadAccessCode(address) != code)) + { + address += 2; + } + + if (address >= stopAddress) + { + address = -1; + } + + return address; +} + +// ************************************************** +// EEPROM Access Code Functions +// ************************************************** + +int CodeMemory::ActivateAccessCode(unsigned short value) +{ + int address = FindAccessCode(value); + if (address >= 0) + { + return -1; // The code already exists in the list. + } + + // Find the address of the next available 16 bit code slot (zero valued) + address = FindAccessCode(0); + if (address >= 0) + { + WriteAccessCode(address, value); + } + else // Memory Full + { + address = -2; + } + + return address; +} + +int CodeMemory::DeactivateAccessCode(unsigned short value) +{ + int address = FindAccessCode(value); + if (address < 0) + { + return -1; // The code was not found + } + else + { + // Erase the two bytes of data from eeprom + _eeprom->Write(address, (short)0, C24LCXX_I2C::LittleEndian); + } + + return address; +} + +void CodeMemory::PrintAllAccessCodes() +{ + int address = 0; + while (address < CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE) + { + unsigned int code = ReadAccessCode(address); + if (code > 0) + { + printf("%d - %d\n", address, code); + } + address += 2; + } + + return; +} + +void CodeMemory::SyncAccessCodes(unsigned short* codeList, unsigned short codeCount) +{ + // Deactivate codes that don't exist in the new set. + for (int address = 0; address < CODE_TABLE_SIZE; address += 2) + { + unsigned short code = ReadAccessCode(address); + + if (code > 0) + { + // Search the new code list for this code. + unsigned short* codePtr = std::find(codeList, codeList + codeCount, code); + if (codePtr == codeList + codeCount) + { + // Code not found. + WriteAccessCode(address, 0); + } + } + } + + // Activate all codes in the code list. Duplicates will be ignored. + for (int codeIndex = 0; codeIndex < codeCount; codeIndex++) + { + ActivateAccessCode(codeList[codeIndex]); + } + + return; +} + +// ************************************************** +// EEPROM Special Command Code Functions +// ************************************************** + +bool CodeMemory::IsSpecialCode(unsigned short specialCodeIndex, unsigned short code, unsigned short defaultCode) +{ + // Check for code index out of range + if (specialCodeIndex >= (SPECIAL_CODE_TABLE_SIZE / 2)) + { + return false; + } + + // Check test code value against the default code or eeprom custom code + else + { + unsigned short eepromValue = ReadAccessCode(CODE_TABLE_SIZE + (specialCodeIndex * 2)); + return ((eepromValue == 0) && (code == defaultCode)) || (code == eepromValue); + } +} + +bool CodeMemory::SetSpecialCode(unsigned short specialCodeIndex, unsigned short code) +{ + // Don't allow duplicate codes + if (FindAccessCode(code, CODE_TABLE_SIZE, CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE) < 0) + { + printf("Changing special code at index %d to %d\n", specialCodeIndex, code); + + WriteAccessCode(CODE_TABLE_SIZE + (specialCodeIndex * 2), code); + return true; + } + else + { + printf("Failed to change special code: Code Exists\n"); + return false; // Code already exists in the special code table + } +} + +// ************************************************** +// EEPROM Event Log +// ************************************************** + +int CodeMemory::LogPointerAddress() +{ + return CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE; +} + +int CodeMemory::FirstEventLogAddress() +{ + return LogPointerAddress() + EVENT_LOG_POINTER_SIZE + EVENT_LOG_TIME_BASE_SIZE; +} + +int CodeMemory::EventLogEndAddress() +{ + return EEPROM_LENGTH; +} + +void CodeMemory::PrintEvent(unsigned short eventAddress) +{ + unsigned char memByte; + _eeprom->Read((short)eventAddress, &memByte); + printf("%u:%u:%u\n", ReadEEPROMULong(eventAddress + 3), memByte, ReadAccessCode(eventAddress + 1)); + + return; +} + +int CodeMemory::GetLatestEventAddress() +{ + return ReadAccessCode(LogPointerAddress()); // Get the location of the last event +} + +int CodeMemory::GetNextEventAddress() +{ + return GetNextEventAddress(GetLatestEventAddress()); +} + +int CodeMemory::GetNextEventAddress(unsigned short startAddress) +{ + int address = startAddress; + + if (address < FirstEventLogAddress()) + { + // Empty log, so point to the first slot + address = FirstEventLogAddress(); + } + else if ((address + EVENT_SIZE + (EVENT_SIZE - 1)) < EventLogEndAddress()) + { + // No wrap necessary + address += EVENT_SIZE; + } + else + { + // Wrap to the beginning of the log + address = FirstEventLogAddress(); + } + + return address; +} + +int CodeMemory::GetPreviousEventAddress(unsigned short startAddress) +{ + int address = startAddress; + + if ((address - EVENT_SIZE) >= FirstEventLogAddress()) + { + // No wrap necessary + address -= EVENT_SIZE; + } + else // Wrap to the end of the log + { + int eventLogLength = ((EventLogEndAddress() - FirstEventLogAddress()) / EVENT_SIZE); + address = FirstEventLogAddress() + ((eventLogLength * EVENT_SIZE) - EVENT_SIZE); // Last event address + } + + return address; +} + +void CodeMemory::WriteEvent(unsigned char eventType, unsigned short eventValue) +{ + unsigned int currentTime = time(NULL); + + // Determine the location of the next event + int eventAddress = GetNextEventAddress(); + WriteAccessCode(LogPointerAddress(), eventAddress); + + // Write the event type byte + _eeprom->Write(eventAddress, eventType); + + // Write the event value integer + WriteAccessCode(eventAddress + 1, eventValue); + + // Write the timestamp + WriteEEPROMULong(eventAddress + 3, currentTime); + + // Send the event code to the supervisor for SQL storage + printf("Evt:%lu:%u:%u\n", currentTime, eventType, eventValue); + + return; +} + +void CodeMemory::PrintEventLog() +{ + int oldestEventAddress = GetNextEventAddress(); + int eventAddress = oldestEventAddress; + + // Print all of the events, oldest to newest + do + { + PrintEvent(eventAddress); + + // Increment to the next event in the log + eventAddress = GetNextEventAddress(eventAddress); + } while (eventAddress != oldestEventAddress); + + return; +} + +void CodeMemory::PrintRecentEvents() +{ + PrintRecentEvents(10); + return; +} + +void CodeMemory::PrintRecentEvents(unsigned short numEvents) +{ + int eventAddress = GetLatestEventAddress(); + + for (int eventIndex = 0; eventIndex < numEvents; eventIndex++) + { + PrintEvent(eventAddress); + eventAddress = GetPreviousEventAddress(eventAddress); + } + + return; +} \ No newline at end of file