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

Committer:
acesrobertm
Date:
Mon Sep 25 19:02:40 2017 +0000
Revision:
0:a56239ae90c2
in process of moving networking code to non-blocking format

Who changed what in which revision?

UserRevisionLine numberNew contents of line
acesrobertm 0:a56239ae90c2 1
acesrobertm 0:a56239ae90c2 2 #include "CodeMemory.h"
acesrobertm 0:a56239ae90c2 3
acesrobertm 0:a56239ae90c2 4 void CodeMemory::EEPROMClear()
acesrobertm 0:a56239ae90c2 5 {
acesrobertm 0:a56239ae90c2 6 for (int i = 0 ; i < EEPROM_LENGTH ; i += 4)
acesrobertm 0:a56239ae90c2 7 {
acesrobertm 0:a56239ae90c2 8 _eeprom->Write(i, (int)0, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 9 }
acesrobertm 0:a56239ae90c2 10 }
acesrobertm 0:a56239ae90c2 11
acesrobertm 0:a56239ae90c2 12 unsigned short CodeMemory::ReadAccessCode(unsigned short address)
acesrobertm 0:a56239ae90c2 13 {
acesrobertm 0:a56239ae90c2 14 // Read two bytes at the specified address
acesrobertm 0:a56239ae90c2 15 short code;
acesrobertm 0:a56239ae90c2 16 _eeprom->Read((short)address, &code, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 17
acesrobertm 0:a56239ae90c2 18 return code;
acesrobertm 0:a56239ae90c2 19 }
acesrobertm 0:a56239ae90c2 20
acesrobertm 0:a56239ae90c2 21 void CodeMemory::WriteAccessCode(unsigned short address, unsigned short value)
acesrobertm 0:a56239ae90c2 22 {
acesrobertm 0:a56239ae90c2 23 //Write the bytes into the eeprom memory.
acesrobertm 0:a56239ae90c2 24 _eeprom->Write(address, (short)value, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 25
acesrobertm 0:a56239ae90c2 26 return;
acesrobertm 0:a56239ae90c2 27 }
acesrobertm 0:a56239ae90c2 28
acesrobertm 0:a56239ae90c2 29 unsigned int CodeMemory::ReadEEPROMULong(unsigned short address)
acesrobertm 0:a56239ae90c2 30 {
acesrobertm 0:a56239ae90c2 31 // Read four bytes at the specified address.
acesrobertm 0:a56239ae90c2 32 int value;
acesrobertm 0:a56239ae90c2 33 _eeprom->Read((short)address, &value, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 34
acesrobertm 0:a56239ae90c2 35 return value;
acesrobertm 0:a56239ae90c2 36 }
acesrobertm 0:a56239ae90c2 37
acesrobertm 0:a56239ae90c2 38 void CodeMemory::WriteEEPROMULong(unsigned short address, unsigned int value)
acesrobertm 0:a56239ae90c2 39 {
acesrobertm 0:a56239ae90c2 40 _eeprom->Write((short)address, (int)value, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 41
acesrobertm 0:a56239ae90c2 42 return;
acesrobertm 0:a56239ae90c2 43 }
acesrobertm 0:a56239ae90c2 44
acesrobertm 0:a56239ae90c2 45 // Find the address of the specified code
acesrobertm 0:a56239ae90c2 46 int CodeMemory::FindAccessCode(unsigned short code)
acesrobertm 0:a56239ae90c2 47 {
acesrobertm 0:a56239ae90c2 48 return FindAccessCode(code, 0, CODE_TABLE_SIZE);
acesrobertm 0:a56239ae90c2 49 }
acesrobertm 0:a56239ae90c2 50
acesrobertm 0:a56239ae90c2 51 int CodeMemory::FindAccessCode(unsigned short code, unsigned short startAddress, unsigned short stopAddress)
acesrobertm 0:a56239ae90c2 52 {
acesrobertm 0:a56239ae90c2 53 int address = startAddress;
acesrobertm 0:a56239ae90c2 54 while ((address < stopAddress) && (ReadAccessCode(address) != code))
acesrobertm 0:a56239ae90c2 55 {
acesrobertm 0:a56239ae90c2 56 address += 2;
acesrobertm 0:a56239ae90c2 57 }
acesrobertm 0:a56239ae90c2 58
acesrobertm 0:a56239ae90c2 59 if (address >= stopAddress)
acesrobertm 0:a56239ae90c2 60 {
acesrobertm 0:a56239ae90c2 61 address = -1;
acesrobertm 0:a56239ae90c2 62 }
acesrobertm 0:a56239ae90c2 63
acesrobertm 0:a56239ae90c2 64 return address;
acesrobertm 0:a56239ae90c2 65 }
acesrobertm 0:a56239ae90c2 66
acesrobertm 0:a56239ae90c2 67 // **************************************************
acesrobertm 0:a56239ae90c2 68 // EEPROM Access Code Functions
acesrobertm 0:a56239ae90c2 69 // **************************************************
acesrobertm 0:a56239ae90c2 70
acesrobertm 0:a56239ae90c2 71 int CodeMemory::ActivateAccessCode(unsigned short value)
acesrobertm 0:a56239ae90c2 72 {
acesrobertm 0:a56239ae90c2 73 int address = FindAccessCode(value);
acesrobertm 0:a56239ae90c2 74 if (address >= 0)
acesrobertm 0:a56239ae90c2 75 {
acesrobertm 0:a56239ae90c2 76 return -1; // The code already exists in the list.
acesrobertm 0:a56239ae90c2 77 }
acesrobertm 0:a56239ae90c2 78
acesrobertm 0:a56239ae90c2 79 // Find the address of the next available 16 bit code slot (zero valued)
acesrobertm 0:a56239ae90c2 80 address = FindAccessCode(0);
acesrobertm 0:a56239ae90c2 81 if (address >= 0)
acesrobertm 0:a56239ae90c2 82 {
acesrobertm 0:a56239ae90c2 83 WriteAccessCode(address, value);
acesrobertm 0:a56239ae90c2 84 }
acesrobertm 0:a56239ae90c2 85 else // Memory Full
acesrobertm 0:a56239ae90c2 86 {
acesrobertm 0:a56239ae90c2 87 address = -2;
acesrobertm 0:a56239ae90c2 88 }
acesrobertm 0:a56239ae90c2 89
acesrobertm 0:a56239ae90c2 90 return address;
acesrobertm 0:a56239ae90c2 91 }
acesrobertm 0:a56239ae90c2 92
acesrobertm 0:a56239ae90c2 93 int CodeMemory::DeactivateAccessCode(unsigned short value)
acesrobertm 0:a56239ae90c2 94 {
acesrobertm 0:a56239ae90c2 95 int address = FindAccessCode(value);
acesrobertm 0:a56239ae90c2 96 if (address < 0)
acesrobertm 0:a56239ae90c2 97 {
acesrobertm 0:a56239ae90c2 98 return -1; // The code was not found
acesrobertm 0:a56239ae90c2 99 }
acesrobertm 0:a56239ae90c2 100 else
acesrobertm 0:a56239ae90c2 101 {
acesrobertm 0:a56239ae90c2 102 // Erase the two bytes of data from eeprom
acesrobertm 0:a56239ae90c2 103 _eeprom->Write(address, (short)0, C24LCXX_I2C::LittleEndian);
acesrobertm 0:a56239ae90c2 104 }
acesrobertm 0:a56239ae90c2 105
acesrobertm 0:a56239ae90c2 106 return address;
acesrobertm 0:a56239ae90c2 107 }
acesrobertm 0:a56239ae90c2 108
acesrobertm 0:a56239ae90c2 109 void CodeMemory::PrintAllAccessCodes()
acesrobertm 0:a56239ae90c2 110 {
acesrobertm 0:a56239ae90c2 111 int address = 0;
acesrobertm 0:a56239ae90c2 112 while (address < CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE)
acesrobertm 0:a56239ae90c2 113 {
acesrobertm 0:a56239ae90c2 114 unsigned int code = ReadAccessCode(address);
acesrobertm 0:a56239ae90c2 115 if (code > 0)
acesrobertm 0:a56239ae90c2 116 {
acesrobertm 0:a56239ae90c2 117 printf("%d - %d\n", address, code);
acesrobertm 0:a56239ae90c2 118 }
acesrobertm 0:a56239ae90c2 119 address += 2;
acesrobertm 0:a56239ae90c2 120 }
acesrobertm 0:a56239ae90c2 121
acesrobertm 0:a56239ae90c2 122 return;
acesrobertm 0:a56239ae90c2 123 }
acesrobertm 0:a56239ae90c2 124
acesrobertm 0:a56239ae90c2 125 void CodeMemory::SyncAccessCodes(unsigned short* codeList, unsigned short codeCount)
acesrobertm 0:a56239ae90c2 126 {
acesrobertm 0:a56239ae90c2 127 // Deactivate codes that don't exist in the new set.
acesrobertm 0:a56239ae90c2 128 for (int address = 0; address < CODE_TABLE_SIZE; address += 2)
acesrobertm 0:a56239ae90c2 129 {
acesrobertm 0:a56239ae90c2 130 unsigned short code = ReadAccessCode(address);
acesrobertm 0:a56239ae90c2 131
acesrobertm 0:a56239ae90c2 132 if (code > 0)
acesrobertm 0:a56239ae90c2 133 {
acesrobertm 0:a56239ae90c2 134 // Search the new code list for this code.
acesrobertm 0:a56239ae90c2 135 unsigned short* codePtr = std::find(codeList, codeList + codeCount, code);
acesrobertm 0:a56239ae90c2 136 if (codePtr == codeList + codeCount)
acesrobertm 0:a56239ae90c2 137 {
acesrobertm 0:a56239ae90c2 138 // Code not found.
acesrobertm 0:a56239ae90c2 139 WriteAccessCode(address, 0);
acesrobertm 0:a56239ae90c2 140 }
acesrobertm 0:a56239ae90c2 141 }
acesrobertm 0:a56239ae90c2 142 }
acesrobertm 0:a56239ae90c2 143
acesrobertm 0:a56239ae90c2 144 // Activate all codes in the code list. Duplicates will be ignored.
acesrobertm 0:a56239ae90c2 145 for (int codeIndex = 0; codeIndex < codeCount; codeIndex++)
acesrobertm 0:a56239ae90c2 146 {
acesrobertm 0:a56239ae90c2 147 ActivateAccessCode(codeList[codeIndex]);
acesrobertm 0:a56239ae90c2 148 }
acesrobertm 0:a56239ae90c2 149
acesrobertm 0:a56239ae90c2 150 return;
acesrobertm 0:a56239ae90c2 151 }
acesrobertm 0:a56239ae90c2 152
acesrobertm 0:a56239ae90c2 153 // **************************************************
acesrobertm 0:a56239ae90c2 154 // EEPROM Special Command Code Functions
acesrobertm 0:a56239ae90c2 155 // **************************************************
acesrobertm 0:a56239ae90c2 156
acesrobertm 0:a56239ae90c2 157 bool CodeMemory::IsSpecialCode(unsigned short specialCodeIndex, unsigned short code, unsigned short defaultCode)
acesrobertm 0:a56239ae90c2 158 {
acesrobertm 0:a56239ae90c2 159 // Check for code index out of range
acesrobertm 0:a56239ae90c2 160 if (specialCodeIndex >= (SPECIAL_CODE_TABLE_SIZE / 2))
acesrobertm 0:a56239ae90c2 161 {
acesrobertm 0:a56239ae90c2 162 return false;
acesrobertm 0:a56239ae90c2 163 }
acesrobertm 0:a56239ae90c2 164
acesrobertm 0:a56239ae90c2 165 // Check test code value against the default code or eeprom custom code
acesrobertm 0:a56239ae90c2 166 else
acesrobertm 0:a56239ae90c2 167 {
acesrobertm 0:a56239ae90c2 168 unsigned short eepromValue = ReadAccessCode(CODE_TABLE_SIZE + (specialCodeIndex * 2));
acesrobertm 0:a56239ae90c2 169 return ((eepromValue == 0) && (code == defaultCode)) || (code == eepromValue);
acesrobertm 0:a56239ae90c2 170 }
acesrobertm 0:a56239ae90c2 171 }
acesrobertm 0:a56239ae90c2 172
acesrobertm 0:a56239ae90c2 173 bool CodeMemory::SetSpecialCode(unsigned short specialCodeIndex, unsigned short code)
acesrobertm 0:a56239ae90c2 174 {
acesrobertm 0:a56239ae90c2 175 // Don't allow duplicate codes
acesrobertm 0:a56239ae90c2 176 if (FindAccessCode(code, CODE_TABLE_SIZE, CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE) < 0)
acesrobertm 0:a56239ae90c2 177 {
acesrobertm 0:a56239ae90c2 178 printf("Changing special code at index %d to %d\n", specialCodeIndex, code);
acesrobertm 0:a56239ae90c2 179
acesrobertm 0:a56239ae90c2 180 WriteAccessCode(CODE_TABLE_SIZE + (specialCodeIndex * 2), code);
acesrobertm 0:a56239ae90c2 181 return true;
acesrobertm 0:a56239ae90c2 182 }
acesrobertm 0:a56239ae90c2 183 else
acesrobertm 0:a56239ae90c2 184 {
acesrobertm 0:a56239ae90c2 185 printf("Failed to change special code: Code Exists\n");
acesrobertm 0:a56239ae90c2 186 return false; // Code already exists in the special code table
acesrobertm 0:a56239ae90c2 187 }
acesrobertm 0:a56239ae90c2 188 }
acesrobertm 0:a56239ae90c2 189
acesrobertm 0:a56239ae90c2 190 // **************************************************
acesrobertm 0:a56239ae90c2 191 // EEPROM Event Log
acesrobertm 0:a56239ae90c2 192 // **************************************************
acesrobertm 0:a56239ae90c2 193
acesrobertm 0:a56239ae90c2 194 int CodeMemory::LogPointerAddress()
acesrobertm 0:a56239ae90c2 195 {
acesrobertm 0:a56239ae90c2 196 return CODE_TABLE_SIZE + SPECIAL_CODE_TABLE_SIZE;
acesrobertm 0:a56239ae90c2 197 }
acesrobertm 0:a56239ae90c2 198
acesrobertm 0:a56239ae90c2 199 int CodeMemory::FirstEventLogAddress()
acesrobertm 0:a56239ae90c2 200 {
acesrobertm 0:a56239ae90c2 201 return LogPointerAddress() + EVENT_LOG_POINTER_SIZE + EVENT_LOG_TIME_BASE_SIZE;
acesrobertm 0:a56239ae90c2 202 }
acesrobertm 0:a56239ae90c2 203
acesrobertm 0:a56239ae90c2 204 int CodeMemory::EventLogEndAddress()
acesrobertm 0:a56239ae90c2 205 {
acesrobertm 0:a56239ae90c2 206 return EEPROM_LENGTH;
acesrobertm 0:a56239ae90c2 207 }
acesrobertm 0:a56239ae90c2 208
acesrobertm 0:a56239ae90c2 209 void CodeMemory::PrintEvent(unsigned short eventAddress)
acesrobertm 0:a56239ae90c2 210 {
acesrobertm 0:a56239ae90c2 211 unsigned char memByte;
acesrobertm 0:a56239ae90c2 212 _eeprom->Read((short)eventAddress, &memByte);
acesrobertm 0:a56239ae90c2 213 printf("%u:%u:%u\n", ReadEEPROMULong(eventAddress + 3), memByte, ReadAccessCode(eventAddress + 1));
acesrobertm 0:a56239ae90c2 214
acesrobertm 0:a56239ae90c2 215 return;
acesrobertm 0:a56239ae90c2 216 }
acesrobertm 0:a56239ae90c2 217
acesrobertm 0:a56239ae90c2 218 int CodeMemory::GetLatestEventAddress()
acesrobertm 0:a56239ae90c2 219 {
acesrobertm 0:a56239ae90c2 220 return ReadAccessCode(LogPointerAddress()); // Get the location of the last event
acesrobertm 0:a56239ae90c2 221 }
acesrobertm 0:a56239ae90c2 222
acesrobertm 0:a56239ae90c2 223 int CodeMemory::GetNextEventAddress()
acesrobertm 0:a56239ae90c2 224 {
acesrobertm 0:a56239ae90c2 225 return GetNextEventAddress(GetLatestEventAddress());
acesrobertm 0:a56239ae90c2 226 }
acesrobertm 0:a56239ae90c2 227
acesrobertm 0:a56239ae90c2 228 int CodeMemory::GetNextEventAddress(unsigned short startAddress)
acesrobertm 0:a56239ae90c2 229 {
acesrobertm 0:a56239ae90c2 230 int address = startAddress;
acesrobertm 0:a56239ae90c2 231
acesrobertm 0:a56239ae90c2 232 if (address < FirstEventLogAddress())
acesrobertm 0:a56239ae90c2 233 {
acesrobertm 0:a56239ae90c2 234 // Empty log, so point to the first slot
acesrobertm 0:a56239ae90c2 235 address = FirstEventLogAddress();
acesrobertm 0:a56239ae90c2 236 }
acesrobertm 0:a56239ae90c2 237 else if ((address + EVENT_SIZE + (EVENT_SIZE - 1)) < EventLogEndAddress())
acesrobertm 0:a56239ae90c2 238 {
acesrobertm 0:a56239ae90c2 239 // No wrap necessary
acesrobertm 0:a56239ae90c2 240 address += EVENT_SIZE;
acesrobertm 0:a56239ae90c2 241 }
acesrobertm 0:a56239ae90c2 242 else
acesrobertm 0:a56239ae90c2 243 {
acesrobertm 0:a56239ae90c2 244 // Wrap to the beginning of the log
acesrobertm 0:a56239ae90c2 245 address = FirstEventLogAddress();
acesrobertm 0:a56239ae90c2 246 }
acesrobertm 0:a56239ae90c2 247
acesrobertm 0:a56239ae90c2 248 return address;
acesrobertm 0:a56239ae90c2 249 }
acesrobertm 0:a56239ae90c2 250
acesrobertm 0:a56239ae90c2 251 int CodeMemory::GetPreviousEventAddress(unsigned short startAddress)
acesrobertm 0:a56239ae90c2 252 {
acesrobertm 0:a56239ae90c2 253 int address = startAddress;
acesrobertm 0:a56239ae90c2 254
acesrobertm 0:a56239ae90c2 255 if ((address - EVENT_SIZE) >= FirstEventLogAddress())
acesrobertm 0:a56239ae90c2 256 {
acesrobertm 0:a56239ae90c2 257 // No wrap necessary
acesrobertm 0:a56239ae90c2 258 address -= EVENT_SIZE;
acesrobertm 0:a56239ae90c2 259 }
acesrobertm 0:a56239ae90c2 260 else // Wrap to the end of the log
acesrobertm 0:a56239ae90c2 261 {
acesrobertm 0:a56239ae90c2 262 int eventLogLength = ((EventLogEndAddress() - FirstEventLogAddress()) / EVENT_SIZE);
acesrobertm 0:a56239ae90c2 263 address = FirstEventLogAddress() + ((eventLogLength * EVENT_SIZE) - EVENT_SIZE); // Last event address
acesrobertm 0:a56239ae90c2 264 }
acesrobertm 0:a56239ae90c2 265
acesrobertm 0:a56239ae90c2 266 return address;
acesrobertm 0:a56239ae90c2 267 }
acesrobertm 0:a56239ae90c2 268
acesrobertm 0:a56239ae90c2 269 void CodeMemory::WriteEvent(unsigned char eventType, unsigned short eventValue)
acesrobertm 0:a56239ae90c2 270 {
acesrobertm 0:a56239ae90c2 271 unsigned int currentTime = time(NULL);
acesrobertm 0:a56239ae90c2 272
acesrobertm 0:a56239ae90c2 273 // Determine the location of the next event
acesrobertm 0:a56239ae90c2 274 int eventAddress = GetNextEventAddress();
acesrobertm 0:a56239ae90c2 275 WriteAccessCode(LogPointerAddress(), eventAddress);
acesrobertm 0:a56239ae90c2 276
acesrobertm 0:a56239ae90c2 277 // Write the event type byte
acesrobertm 0:a56239ae90c2 278 _eeprom->Write(eventAddress, eventType);
acesrobertm 0:a56239ae90c2 279
acesrobertm 0:a56239ae90c2 280 // Write the event value integer
acesrobertm 0:a56239ae90c2 281 WriteAccessCode(eventAddress + 1, eventValue);
acesrobertm 0:a56239ae90c2 282
acesrobertm 0:a56239ae90c2 283 // Write the timestamp
acesrobertm 0:a56239ae90c2 284 WriteEEPROMULong(eventAddress + 3, currentTime);
acesrobertm 0:a56239ae90c2 285
acesrobertm 0:a56239ae90c2 286 // Send the event code to the supervisor for SQL storage
acesrobertm 0:a56239ae90c2 287 printf("Evt:%lu:%u:%u\n", currentTime, eventType, eventValue);
acesrobertm 0:a56239ae90c2 288
acesrobertm 0:a56239ae90c2 289 return;
acesrobertm 0:a56239ae90c2 290 }
acesrobertm 0:a56239ae90c2 291
acesrobertm 0:a56239ae90c2 292 void CodeMemory::PrintEventLog()
acesrobertm 0:a56239ae90c2 293 {
acesrobertm 0:a56239ae90c2 294 int oldestEventAddress = GetNextEventAddress();
acesrobertm 0:a56239ae90c2 295 int eventAddress = oldestEventAddress;
acesrobertm 0:a56239ae90c2 296
acesrobertm 0:a56239ae90c2 297 // Print all of the events, oldest to newest
acesrobertm 0:a56239ae90c2 298 do
acesrobertm 0:a56239ae90c2 299 {
acesrobertm 0:a56239ae90c2 300 PrintEvent(eventAddress);
acesrobertm 0:a56239ae90c2 301
acesrobertm 0:a56239ae90c2 302 // Increment to the next event in the log
acesrobertm 0:a56239ae90c2 303 eventAddress = GetNextEventAddress(eventAddress);
acesrobertm 0:a56239ae90c2 304 } while (eventAddress != oldestEventAddress);
acesrobertm 0:a56239ae90c2 305
acesrobertm 0:a56239ae90c2 306 return;
acesrobertm 0:a56239ae90c2 307 }
acesrobertm 0:a56239ae90c2 308
acesrobertm 0:a56239ae90c2 309 void CodeMemory::PrintRecentEvents()
acesrobertm 0:a56239ae90c2 310 {
acesrobertm 0:a56239ae90c2 311 PrintRecentEvents(10);
acesrobertm 0:a56239ae90c2 312 return;
acesrobertm 0:a56239ae90c2 313 }
acesrobertm 0:a56239ae90c2 314
acesrobertm 0:a56239ae90c2 315 void CodeMemory::PrintRecentEvents(unsigned short numEvents)
acesrobertm 0:a56239ae90c2 316 {
acesrobertm 0:a56239ae90c2 317 int eventAddress = GetLatestEventAddress();
acesrobertm 0:a56239ae90c2 318
acesrobertm 0:a56239ae90c2 319 for (int eventIndex = 0; eventIndex < numEvents; eventIndex++)
acesrobertm 0:a56239ae90c2 320 {
acesrobertm 0:a56239ae90c2 321 PrintEvent(eventAddress);
acesrobertm 0:a56239ae90c2 322 eventAddress = GetPreviousEventAddress(eventAddress);
acesrobertm 0:a56239ae90c2 323 }
acesrobertm 0:a56239ae90c2 324
acesrobertm 0:a56239ae90c2 325 return;
acesrobertm 0:a56239ae90c2 326 }