diff --git a/brmdoor/brmdoor.ino b/brmdoor/brmdoor.ino index 0195886..d0ac984 100644 --- a/brmdoor/brmdoor.ino +++ b/brmdoor/brmdoor.ino @@ -3,6 +3,8 @@ #define MUSIC 1 #include +#include + // pins const int magnetPin = 10; const int soundPin = 9; /* piezo in series with 100R */ @@ -14,24 +16,72 @@ const int doorLock = 4; const int rfidRx = 3; const int rfidTx = 2; +// Pins where Adafruit PN532 shield is connected. +// Note that these are the analog pins used in digital mode - no other pins +// were available. +const int PN532_SCK = A3; +const int PN532_MOSI = A2; +const int PN532_SS = A1; +const int PN532_MISO = A0; + +// Set to true if you want to have correct UID printed in hex after CARD +// message into UART (case when card is known). +bool printFullUID = false; + +// Max retries to read card before timeout, 200 is around 1 second, 0xFF means +// wait forever (constitutes blocking read). +uint8_t pn532MaxRetries = 200; +bool pn532Working; //whether we have connected and working chip + int statusState = 0, statusStateOverride = 0; int videoState = 0, videoStateOverride = 0; -// cardId is the same as you can see in CARD telnet message -struct ACLdata { - byte cardId[7]; - char *nick; -} ACL[] = { -// the following include file contains lines like -// { {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE}, "username" }, +/*! + * The cardId is the same as you can see in CARD telnet message + * + * It's called broken, because we had broken reader that couldn't read 7-byte IDs. + * I.e. the old reader could only use SELECT cascade 1, which begins with 0x88 + * cascading tag, thus we have only 3 bytes from 7-byte UIDs. + * + * So if we get a 7-byte ID, we must do "retarded search" for the 3-byte part. + * If an ID in this struct contains 0x88 as third byte (index 2), it means it's + * a card with 7 or 10 byte UID and begins with a cascading tag 0x88. + * + * Currently the bytes seem to be: + * + * case of 4-byte UID: 0x00, 0x00, UID1, UID2, UID3, UID4, BCC + * case of 7-byte UID: 0xFF, 0x00, 0x88, UID1, UID2, UID3, BCC + * case of 10-byte UID: ??? I don't think I actually saw a real card with + * 10-byte UID, but it's in the NXP specs + * + */ +typedef struct ACLdataBroken { + byte cardId[7]; + char *nick; +} ACLRecordBroken; + +/*! + * List of ACLs included from a static array, see ACLRecordBroken for details. + */ +ACLRecordBroken ACL[] = { +/* The following include file contains lines like + * { {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE}, "username" }, + */ #include "cardids.h" }; +// Let's hope aliasing won't break this. +// OMG why not some proper structures? +#define ACL_COUNT (sizeof(ACL)/sizeof(ACLRecordBroken)) + +// ISO14443 cascading tag +#define CASCADING_TAG 0x88 + // comSerial for communication with the host #define comSerial Serial -// rfidSerial for communication with the RFID reader -SoftwareSerial rfidSerial(rfidTx, rfidRx); +// PN532 chip instance +Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); #if MUSIC @@ -101,64 +151,113 @@ void openDoorForTime(int ms) digitalWrite(doorLock, LOW); } -void readCard() +/*! + * Will search for given card UID in the borken ACL list with truncated UIDs. + * + * @param uid UID of the card read + * @param length length of the UID in bytes + * @param acls list of ACLs in the old b0rken form + * @param count of ACLs in the above array + * @returns index into acls if found or -1 if not found + */ +int retardedACLSearch(const uint8_t *uid, uint8_t length, const struct ACLdataBroken *acls, int aclCount) +{ + int idx = -1; + + for(int i=0; i 0) { - if (i < sizeof(buf)) { - buf[i] = rfidSerial.read(); - } - ++i; - } - // no card is detected - if (!memcmp(buf, NoCardResponse, 7)) { - comSerial.write("NOCARD\n"); - } - - // card detected - message has form AA0006xxxxxxxxxxxxxxBB where xxx... is the card ID - if (buf[0] == 0xAA && buf[1] == 0x00 && buf[2] == 0x06 && buf[10] == 0xBB) { - bool known = false; - // go through ACL - for (int i = 0; i < sizeof(ACL)/sizeof(ACL[0]); ++i) { - // if there is a match - print known card ... - if (!memcmp(ACL[i].cardId, buf+3, 7)) { - known = true; - comSerial.write("CARD "); - comSerial.write(ACL[i].nick); - comSerial.write("\n"); - // ... and open door for 5s - openDoorForTime(5000); - break; - } - } - // card was not found in the ACL - if (!known) { - comSerial.write("CARD UNKNOWN "); - for (int i = 0; i < 7; ++i) { - if (buf[i+3] <= 0xF) comSerial.write("0"); - comSerial.print(buf[i+3], HEX); - } - comSerial.write("\n"); - playMelodyNak(); - } - } else { - // make cycle interval 1s - delay(750); - } } void readSerial() @@ -187,7 +286,16 @@ void setup() pinMode(videoBtn, INPUT); digitalWrite(videoBtn, HIGH); comSerial.begin(9600); - rfidSerial.begin(9600); + + uint32_t versiondata = nfc.getFirmwareVersion(); + if (! versiondata) { + comSerial.write("CARD READER BROKEN\n"); + pn532Working = false; + } else { + nfc.SAMConfig(); + nfc.setPassiveActivationRetries(pn532MaxRetries); + pn532Working = true; + } } void loop() @@ -204,11 +312,16 @@ void loop() int doorOpen = digitalRead(magnetPin); - digitalWrite(statusLed, !statusState); // will be turned back in readCard() + digitalWrite(statusLed, !statusState); digitalWrite(videoLed, videoState); + comSerial.print(statusState, DEC); comSerial.write(" "); comSerial.print(videoState, DEC); comSerial.write(" "); comSerial.print(doorOpen, DEC); comSerial.write(" "); - readCard(); + + statusUpdate(); + + readCardPN532(); readSerial(); } +