From ef158a7431753e8479e92408247b66ed8c4c8aa5 Mon Sep 17 00:00:00 2001 From: andre Ebersold Date: Sun, 12 Nov 2023 17:03:52 +0100 Subject: [PATCH] First version for PN532 I2C , can get FirmwareVersion --- .../WorkhourMeter/WorkMeterHandler.cpp | 97 ++++++--- Application/WorkhourMeter/WorkMeterHandler.h | 30 ++- Application/WorkhourMeter/main.cpp | 37 +++- HAL/AVR/AvrI2C.cpp | 42 ++-- HAL/Abstract/II2C.h | 6 +- HAL/Abstract/RFID/IPN532Interface.h | 58 ++++++ HAL/Drivers/CMakeLists.txt | 2 + HAL/Drivers/DS3231.cpp | 30 ++- HAL/Drivers/DS3231.h | 2 + HAL/Drivers/PN532.cpp | 108 ++++++++++ HAL/Drivers/PN532.h | 145 ++++++++++++++ HAL/Drivers/PN532Interface_I2C.cpp | 189 ++++++++++++++++++ HAL/Drivers/PN532Interface_I2C.h | 50 +++++ 13 files changed, 721 insertions(+), 75 deletions(-) create mode 100644 HAL/Abstract/RFID/IPN532Interface.h create mode 100644 HAL/Drivers/PN532.cpp create mode 100644 HAL/Drivers/PN532.h create mode 100644 HAL/Drivers/PN532Interface_I2C.cpp create mode 100644 HAL/Drivers/PN532Interface_I2C.h diff --git a/Application/WorkhourMeter/WorkMeterHandler.cpp b/Application/WorkhourMeter/WorkMeterHandler.cpp index 8521961..2cf14c3 100644 --- a/Application/WorkhourMeter/WorkMeterHandler.cpp +++ b/Application/WorkhourMeter/WorkMeterHandler.cpp @@ -2,14 +2,16 @@ #include "Application/ITask.h" #include "Abstract/IRtc.h" #include "Abstract/ILCD.h" +#include "Abstract/RFID/IPN532Interface.h" +#include "HAL/Drivers/PN532.h" #include "Platform/IParameterHandler.h" #include "Metadata/WorkmeterParamIds.h" #include "WorkMeterHandler.h" -WorkMeterHandler::WorkMeterHandler(IRtc *argRtc,ILCD *argLCD,IParameterHandler *argPH) - : m_Rtc(argRtc), m_LCD(argLCD),m_Params(argPH),m_Ticks(0) +WorkMeterHandler::WorkMeterHandler(IRtc *argRtc,ILCD *argLCD,IParameterHandler *argPH,PN532 *argPN532) + : m_Rtc(argRtc), m_LCD(argLCD),m_NFC(argPN532),m_Params(argPH),m_Ticks(0),m_State(ST_IDLE) { Uint8_t i = 0; m_Params->writeValue(PID_Seconde,i); @@ -17,10 +19,10 @@ WorkMeterHandler::WorkMeterHandler(IRtc *argRtc,ILCD *argLCD,IParameterHandler * m_Params->writeValue(PID_Hour,i); m_Time.seconds = 10; m_Params->registerListener(PID_BackLight,this); /* State on or off */ -#if 1 + m_Params->registerListener(PID_Hour,this); /* State on or off */ m_Params->registerListener(PID_Minute,this); /* State on or off */ -#endif + } void WorkMeterHandler::onWriteValue(const Uint8_t paramID,const Uint8_t _val) @@ -28,21 +30,21 @@ void WorkMeterHandler::onWriteValue(const Uint8_t paramID,const Uint8_t _val) switch (paramID) { case PID_Seconde: - m_Time.seconds = _val; + m_Time.seconds = _val; break; case PID_Minute: - m_Time.min = _val; - //m_Rtc->setTime(m_Time); + m_Time.min = _val; + m_State = ST_SET_TIME; break; case PID_Hour: - m_Time.hour = _val; - //m_Rtc->setTime(m_Time); + m_Time.hour = _val; + m_State = ST_SET_TIME; break; case PID_BackLight: m_LCD->setDisplay(_val); break; - default: - ; + default: + ; } } @@ -62,28 +64,75 @@ void WorkMeterHandler::timeToString() m_StrTime[7] = ((m_Time.seconds) -( (m_Time.seconds / 10) *10 )) + 0x30; m_StrTime[8] = 0; } + +void WorkMeterHandler::getTime() +{ + m_Rtc->getTime(m_Time); + m_Params->writeValue(PID_Seconde,m_Time.seconds); + m_Params->writeValue(PID_Minute,m_Time.min); + m_Params->writeValue(PID_Hour,m_Time.hour); +} +/**/ +void WorkMeterHandler::setTime() +{ +} void WorkMeterHandler::run() { if (m_Ticks++ > 100) { - m_Rtc->getTime(m_Time); - m_Params->writeValue(PID_Seconde,m_Time.seconds); - m_Params->writeValue(PID_Minute,m_Time.min); - m_Params->writeValue(PID_Hour,m_Time.hour); m_Ticks = 0; + m_State = ST_IDLE; } - switch (m_Ticks) + switch (m_State) { - case 8: + case ST_IDLE: + m_State = ST_GET_TIME; + break; + case ST_SET_TIME: + m_Rtc->setTime(m_Time); + m_State = ST_WAIT; + break; + case ST_GET_TIME: + getTime(); + m_State = ST_DISP_UPDATE_CURSOR; + break; + case ST_DISP_UPDATE_CURSOR_TAG: + m_LCD->setCursor(11,0); + m_State = ST_DISP_UPDATE_TAG; + break; + case ST_DISP_UPDATE_CURSOR: + m_LCD->setCursor(4,1); + m_State = ST_DISP_UPDATE_TIME; + break; + case ST_DISP_UPDATE_TAG: + if (m_UidLength > 0) + { + m_LCD->print(reinterpret_cast("1")); + } else + { + m_LCD->print(reinterpret_cast("0")); + } + m_State = ST_WAIT; + break; + case ST_DISP_UPDATE_TIME: timeToString(); - break; - case 10: - m_LCD->setCursor(4,6); - //m_LCD->setCursor(6,0); - break; - case 25: m_LCD->print(m_StrTime); - break; + m_State = ST_WAIT_BADGE; + break; + case ST_WAIT_BADGE: + /* 0 is fail :*/ + m_UidLength = + m_NFC->readPassiveTargetID(PN532_MIFARE_ISO14443A,m_UID,&m_UidLength); + if (m_UidLength > 0) + { + m_State = ST_DISP_UPDATE_CURSOR_TAG; + } else + m_State = ST_DISP_UPDATE_CURSOR_TAG; + //m_State = ST_WAIT; + break; + case ST_WAIT: + m_State = ST_WAIT; + break; }; } diff --git a/Application/WorkhourMeter/WorkMeterHandler.h b/Application/WorkhourMeter/WorkMeterHandler.h index 65d88a1..c832553 100644 --- a/Application/WorkhourMeter/WorkMeterHandler.h +++ b/Application/WorkhourMeter/WorkMeterHandler.h @@ -3,8 +3,20 @@ class WorkMeterHandler : public ITask, public IParameterListener { + enum eStates { + ST_IDLE + ,ST_GET_TIME + ,ST_SET_TIME + ,ST_WAIT_BADGE + ,ST_WAIT + ,ST_DISP_UPDATE_TIME + ,ST_DISP_UPDATE_TAG + ,ST_DISP_UPDATE_CURSOR + ,ST_DISP_UPDATE_CURSOR_TAG + ,ST_DISP_VISIBILITY + }; public: - WorkMeterHandler(IRtc *argRTC,ILCD *argLCD,IParameterHandler *argPH); + WorkMeterHandler(IRtc *argRTC,ILCD *argLCD,IParameterHandler *argPH,PN532 *argPN532); void run(); @@ -12,14 +24,22 @@ class WorkMeterHandler : public ITask, public IParameterListener void onWriteValue(const Uint8_t paramID,const Float32_t _val) ; private: - void timeToString(); + void timeToString(); + /**/ + void getTime(); + /**/ + void setTime(); private: - Uint8_t m_StrTime[9]; - IRtc *m_Rtc; - ILCD *m_LCD; + Uint8_t m_StrTime[9]; + Uint8_t m_UID[7]; + Uint8_t m_UidLength; + IRtc *m_Rtc; + ILCD *m_LCD; + PN532 *m_NFC; IParameterHandler *m_Params; RtcTime_t m_Time; Uint32_t m_Ticks; + Uint8_t m_State; }; #endif diff --git a/Application/WorkhourMeter/main.cpp b/Application/WorkhourMeter/main.cpp index 6e2316e..bb8252c 100644 --- a/Application/WorkhourMeter/main.cpp +++ b/Application/WorkhourMeter/main.cpp @@ -15,6 +15,7 @@ #include #include #include +#include "Abstract/RFID/IPN532Interface.h" #include #include #include @@ -32,6 +33,8 @@ #include #include #include +#include +#include #include "Led0.h" #include "WorkMeterHandler.h" #if 0 @@ -91,8 +94,8 @@ class Scheduler : public IInterruptActivity switch (m_CurrentTask) { case TASK1: - //m_Adc->run(); - m_WorkMeter->run(); + //m_Adc->run(); + m_WorkMeter->run(); //m_Led->tick(); break; case TASK2: @@ -100,7 +103,7 @@ class Scheduler : public IInterruptActivity break; case TASK3: m_Led->tick(); - m_Storage->run(); + m_Storage->run(); break; default: ; @@ -173,16 +176,18 @@ int main(void) AvrI2C gI2c; DS3231 gRtc(&gI2c); LiquidCrystal lcd(&gI2c - ,static_cast(0x4E) - ,static_cast(16) - ,static_cast(2)); + ,static_cast(0x4E) + ,static_cast(16) + ,static_cast(2)); + PN532InterfaceI2C gPN532If(&gI2c); + PN532 nfc(&gPN532If); AvrEeprom gEeprom; NetString netstring(&uart); CommunicationHandler gCom(&netstring,&gParam); PersistentStorage gStorage(&gEeprom,&gParam); - WorkMeterHandler gWorkMeter(&gRtc,&lcd,&gParam); + WorkMeterHandler gWorkMeter(&gRtc,&lcd,&gParam,&nfc); Scheduler sched(&led,&netstring,&gCom,&gWorkMeter,&gStorage); - + Uint8_t msg[15] ; uart.init(); gI2c.init(); netstring.init(); @@ -193,10 +198,24 @@ int main(void) _delay_ms(300); led.off(); _delay_ms(300); - + nfc.begin(); + lcd.setCursor(0,1); + Uint32_t ver = nfc.getFirmwareVersion(); + //Uint32_t ver = 13; + msg[0]= static_cast(((ver >>24) & 0xFF) / 10 + 48 ); + msg[1]= static_cast((ver>>24) - ( (( (ver >>24) & 0xFF) / 10) * 10 ) + 48 ); + msg[2] = 0; + lcd.print(msg); + lcd.setCursor(14,1); + msg[0]= static_cast( (ver >>16 & 0xFF) + 48 ); + msg[1]= static_cast( (ver >>8 & 0xFF ) + 48 ); + lcd.print(msg); + nfc.setPassiveActivationRetries(0xFF); + nfc.SAMConfig(); lTimer.init(); init(&gParam); gEeprom.init(); + gRtc.init(); while(1) { sched.schedule(); diff --git a/HAL/AVR/AvrI2C.cpp b/HAL/AVR/AvrI2C.cpp index 167d6d2..734bcd8 100644 --- a/HAL/AVR/AvrI2C.cpp +++ b/HAL/AVR/AvrI2C.cpp @@ -37,35 +37,6 @@ void AvrI2C::init() //PORTC &= ~((1<> 4 | (b & 0x0F) << 4; \ + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; \ + b = (b & 0xAA) >> 1 | (b & 0x55) << 1 + +class IPN532Interface +{ + public: + IPN532Interface() {}; + /** + * + */ + virtual void begin() = 0; + + /** + * + */ + virtual void wakeup() = 0; + /** + * + */ + virtual Int8_t writeCommand( const Uint8_t *header + , Uint8_t len + , Uint8_t *body = 0 + , Uint8_t blen = 0) = 0; + + /** + * + */ + virtual Int16_t readResponse( Uint8_t *buf + , Uint8_t len + , Uint8_t timeout = 100) = 0; + + +}; + +#endif diff --git a/HAL/Drivers/CMakeLists.txt b/HAL/Drivers/CMakeLists.txt index b273975..7759086 100644 --- a/HAL/Drivers/CMakeLists.txt +++ b/HAL/Drivers/CMakeLists.txt @@ -8,5 +8,7 @@ add_avr_library( DS3231.cpp XPT2046_Touchscreen.cpp LiquidCrystal.cpp + PN532Interface_I2C.cpp + PN532.cpp ) diff --git a/HAL/Drivers/DS3231.cpp b/HAL/Drivers/DS3231.cpp index fe78ec4..9306894 100644 --- a/HAL/Drivers/DS3231.cpp +++ b/HAL/Drivers/DS3231.cpp @@ -11,12 +11,34 @@ DS3231::DS3231(II2C *argI2c) { } +void DS3231::init() +{ + Uint8_t cmd[4]; + cmd[0] = 0x0E; + Bool_t success = itsII2C->read(DS3231_ADDRESS,cmd[0],&cmd[1],2); + if (success) + { + if ((cmd[1] & 0x80 ) || (cmd[2] & 0x80)) + { + cmd[1] &= 0x7F; + itsII2C->write(DS3231_ADDRESS,cmd,2); + } + } +#if 0 + else +#endif + { + cmd[1] = 0x00; + cmd[2] = 0x00; + itsII2C->write(DS3231_ADDRESS,cmd,3); + } +} void DS3231::getTime(RtcTime_t &argTime) { Uint8_t cmd[9] ; - cmd[0] = 0x00; cmd[1] = 128; + cmd[0] = 0x00; #if 1 Bool_t success = itsII2C->read(DS3231_ADDRESS,cmd[0],&cmd[1],8); @@ -46,13 +68,13 @@ void DS3231::setTime(const RtcTime_t &argTime) Uint8_t cmd[5] ; cmd[0] = 0x00; cmd[1] = (argTime.seconds / 10)<<4; - cmd[1] |= (argTime.seconds - (argTime.seconds/10)); + cmd[1] |= (argTime.seconds - (argTime.seconds/10) * 10 ); // Set Minutes cmd[2] = (argTime.min / 10)<<4; - cmd[2] |= (argTime.min - (argTime.min/10) ); + cmd[2] |= (argTime.min - (argTime.min/10) * 10 ); // Hours cmd[3] = (argTime.hour / 10)<<4; - cmd[3] |= ( argTime.hour - (argTime.hour/10) ) | 0x40; + cmd[3] |= ( argTime.hour - (argTime.hour/10) * 10 ) ; itsII2C->write(DS3231_ADDRESS,cmd,4); } diff --git a/HAL/Drivers/DS3231.h b/HAL/Drivers/DS3231.h index 4021ba1..eb94e66 100644 --- a/HAL/Drivers/DS3231.h +++ b/HAL/Drivers/DS3231.h @@ -9,6 +9,8 @@ class DS3231 : public IRtc public: DS3231(II2C *); + void init(); + void getTime(RtcTime_t &argTime); void setTime(const RtcTime_t &argTime); diff --git a/HAL/Drivers/PN532.cpp b/HAL/Drivers/PN532.cpp new file mode 100644 index 0000000..b1dca1b --- /dev/null +++ b/HAL/Drivers/PN532.cpp @@ -0,0 +1,108 @@ +#include +#include "Abstract/II2C.h" + +#include "Abstract/RFID/IPN532Interface.h" +#include "PN532.h" + +#define ITF(fct) (m_Itf->fct) + +PN532::PN532(IPN532Interface *_itf) + : m_Itf(_itf) +{ +} + + +void PN532::begin() +{ + ITF(begin)(); + ITF(wakeup)(); +} + +Uint32_t PN532::getFirmwareVersion() +{ + Uint32_t response; + + m_PacketBuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION; + Int8_t res = (ITF(writeCommand)(m_PacketBuffer,1)); + if (res) + { + return 3; + } + Int16_t status = ITF(readResponse)(m_PacketBuffer,sizeof(m_PacketBuffer)); + if (0 > status) + { + //return status; + return 5; + } + response = m_PacketBuffer[0]; response <<= 8; + response |= m_PacketBuffer[1]; response <<= 8; + response |= m_PacketBuffer[2]; response <<= 8; + response |= m_PacketBuffer[3]; + return response; +} + +Bool_t PN532::SAMConfig() +{ + m_PacketBuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + m_PacketBuffer[1] = 0x01; // normal mode + m_PacketBuffer[2] = 0x14; // timeout 50ms * 20 = 1 second ? + m_PacketBuffer[4] = 0x01; // use IRQ pin ? + + if (ITF(writeCommand)(m_PacketBuffer,4)) + { + return false; + } + return ( 0 < ITF(readResponse)(m_PacketBuffer,sizeof(m_PacketBuffer))); +} + +Bool_t PN532::readPassiveTargetID( Uint8_t _type + , Uint8_t *uid + , Uint8_t *uidLength) +{ + m_PacketBuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + m_PacketBuffer[1] = 0x01; // normal mode + m_PacketBuffer[2] = _type; + + if (ITF(writeCommand)(m_PacketBuffer,3)) + { + return 0; // command failed + } + // read response + if (ITF(readResponse)(m_PacketBuffer,sizeof(m_PacketBuffer)) < 0) + { + return 0; // command failed + } + /** + * Ok analyse the response + */ + if ( m_PacketBuffer[0] != 1) + { + return 0; //Tag not found + } + + *uidLength = m_PacketBuffer[5]; + + for (Uint8_t i = 0 ; i < *uidLength ; i++) + { + m_UID[i] = m_PacketBuffer[6 + i]; + } + return 1; +} + +/** + * + */ +Bool_t PN532::setPassiveActivationRetries(Uint8_t _retries) +{ + m_PacketBuffer[0] = PN532_COMMAND_RFCONFIGURATION; + m_PacketBuffer[1] = 0x05; // Config item 5 (MaxRetries) + m_PacketBuffer[2] = 0xFF; + m_PacketBuffer[3] = 0x01; + m_PacketBuffer[4] = _retries; + + if (ITF(writeCommand)(m_PacketBuffer,5)) + { + return 0; // no Ack + } + return ( 0 < ITF(readResponse)(m_PacketBuffer,sizeof(m_PacketBuffer))); +} diff --git a/HAL/Drivers/PN532.h b/HAL/Drivers/PN532.h new file mode 100644 index 0000000..262954a --- /dev/null +++ b/HAL/Drivers/PN532.h @@ -0,0 +1,145 @@ +#ifndef __PN532_H__ +#define __PN532_H__ + +// PN532 Commands +#define PN532_COMMAND_DIAGNOSE (0x00) +#define PN532_COMMAND_GETFIRMWAREVERSION (0x02) +#define PN532_COMMAND_GETGENERALSTATUS (0x04) +#define PN532_COMMAND_READREGISTER (0x06) +#define PN532_COMMAND_WRITEREGISTER (0x08) +#define PN532_COMMAND_READGPIO (0x0C) +#define PN532_COMMAND_WRITEGPIO (0x0E) +#define PN532_COMMAND_SETSERIALBAUDRATE (0x10) +#define PN532_COMMAND_SETPARAMETERS (0x12) +#define PN532_COMMAND_SAMCONFIGURATION (0x14) +#define PN532_COMMAND_POWERDOWN (0x16) +#define PN532_COMMAND_RFCONFIGURATION (0x32) +#define PN532_COMMAND_RFREGULATIONTEST (0x58) +#define PN532_COMMAND_INJUMPFORDEP (0x56) +#define PN532_COMMAND_INJUMPFORPSL (0x46) +#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A) +#define PN532_COMMAND_INATR (0x50) +#define PN532_COMMAND_INPSL (0x4E) +#define PN532_COMMAND_INDATAEXCHANGE (0x40) +#define PN532_COMMAND_INCOMMUNICATETHRU (0x42) +#define PN532_COMMAND_INDESELECT (0x44) +#define PN532_COMMAND_INRELEASE (0x52) +#define PN532_COMMAND_INSELECT (0x54) +#define PN532_COMMAND_INAUTOPOLL (0x60) +#define PN532_COMMAND_TGINITASTARGET (0x8C) +#define PN532_COMMAND_TGSETGENERALBYTES (0x92) +#define PN532_COMMAND_TGGETDATA (0x86) +#define PN532_COMMAND_TGSETDATA (0x8E) +#define PN532_COMMAND_TGSETMETADATA (0x94) +#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88) +#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90) +#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A) + +#define PN532_RESPONSE_INDATAEXCHANGE (0x41) +#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B) + + +#define PN532_MIFARE_ISO14443A (0x00) + +// Mifare Commands +#define MIFARE_CMD_AUTH_A (0x60) +#define MIFARE_CMD_AUTH_B (0x61) +#define MIFARE_CMD_READ (0x30) +#define MIFARE_CMD_WRITE (0xA0) +#define MIFARE_CMD_WRITE_ULTRALIGHT (0xA2) +#define MIFARE_CMD_TRANSFER (0xB0) +#define MIFARE_CMD_DECREMENT (0xC0) +#define MIFARE_CMD_INCREMENT (0xC1) +#define MIFARE_CMD_STORE (0xC2) + +// FeliCa Commands +#define FELICA_CMD_POLLING (0x00) +#define FELICA_CMD_REQUEST_SERVICE (0x02) +#define FELICA_CMD_REQUEST_RESPONSE (0x04) +#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06) +#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08) +#define FELICA_CMD_REQUEST_SYSTEM_CODE (0x0C) + +// Prefixes for NDEF Records (to identify record type) +#define NDEF_URIPREFIX_NONE (0x00) +#define NDEF_URIPREFIX_HTTP_WWWDOT (0x01) +#define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02) +#define NDEF_URIPREFIX_HTTP (0x03) +#define NDEF_URIPREFIX_HTTPS (0x04) +#define NDEF_URIPREFIX_TEL (0x05) +#define NDEF_URIPREFIX_MAILTO (0x06) +#define NDEF_URIPREFIX_FTP_ANONAT (0x07) +#define NDEF_URIPREFIX_FTP_FTPDOT (0x08) +#define NDEF_URIPREFIX_FTPS (0x09) +#define NDEF_URIPREFIX_SFTP (0x0A) +#define NDEF_URIPREFIX_SMB (0x0B) +#define NDEF_URIPREFIX_NFS (0x0C) +#define NDEF_URIPREFIX_FTP (0x0D) +#define NDEF_URIPREFIX_DAV (0x0E) +#define NDEF_URIPREFIX_NEWS (0x0F) +#define NDEF_URIPREFIX_TELNET (0x10) +#define NDEF_URIPREFIX_IMAP (0x11) +#define NDEF_URIPREFIX_RTSP (0x12) +#define NDEF_URIPREFIX_URN (0x13) +#define NDEF_URIPREFIX_POP (0x14) +#define NDEF_URIPREFIX_SIP (0x15) +#define NDEF_URIPREFIX_SIPS (0x16) +#define NDEF_URIPREFIX_TFTP (0x17) +#define NDEF_URIPREFIX_BTSPP (0x18) +#define NDEF_URIPREFIX_BTL2CAP (0x19) +#define NDEF_URIPREFIX_BTGOEP (0x1A) +#define NDEF_URIPREFIX_TCPOBEX (0x1B) +#define NDEF_URIPREFIX_IRDAOBEX (0x1C) +#define NDEF_URIPREFIX_FILE (0x1D) +#define NDEF_URIPREFIX_URN_EPC_ID (0x1E) +#define NDEF_URIPREFIX_URN_EPC_TAG (0x1F) +#define NDEF_URIPREFIX_URN_EPC_PAT (0x20) +#define NDEF_URIPREFIX_URN_EPC_RAW (0x21) +#define NDEF_URIPREFIX_URN_EPC (0x22) +#define NDEF_URIPREFIX_URN_NFC (0x23) + +#define PN532_GPIO_VALIDATIONBIT (0x80) +#define PN532_GPIO_P30 (0) +#define PN532_GPIO_P31 (1) +#define PN532_GPIO_P32 (2) +#define PN532_GPIO_P33 (3) +#define PN532_GPIO_P34 (4) +#define PN532_GPIO_P35 (5) + +// FeliCa consts +#define FELICA_READ_MAX_SERVICE_NUM 16 +#define FELICA_READ_MAX_BLOCK_NUM 12 // for typical FeliCa card +#define FELICA_WRITE_MAX_SERVICE_NUM 16 +#define FELICA_WRITE_MAX_BLOCK_NUM 10 // for typical FeliCa card +#define FELICA_REQ_SERVICE_MAX_NODE_NUM 32 + + +/** + * Driver to control the PN532 chip + */ +class PN532 +{ + private: + IPN532Interface *m_Itf; + public: + PN532(IPN532Interface *itf); // Default contructor Needs in Interface + + void begin(); + + Uint32_t getFirmwareVersion(); + + Bool_t SAMConfig(); + + Bool_t setPassiveActivationRetries(Uint8_t _retries); + + Bool_t readPassiveTargetID(Uint8_t _type,Uint8_t *uid,Uint8_t *uidLength); + + private: + Uint8_t m_PacketBuffer[64]; // For low level exchanges + Uint8_t m_UID[7]; // ISO14443A uid + Uint8_t m_UIDLength; + + +}; + +#endif diff --git a/HAL/Drivers/PN532Interface_I2C.cpp b/HAL/Drivers/PN532Interface_I2C.cpp new file mode 100644 index 0000000..79a6f34 --- /dev/null +++ b/HAL/Drivers/PN532Interface_I2C.cpp @@ -0,0 +1,189 @@ +#include +// AVr Gcc includes +#include +#include +// +#include "Abstract/II2C.h" +#include "Abstract/RFID/IPN532Interface.h" +#include "Drivers/PN532Interface_I2C.h" + +Uint8_t PN532InterfaceI2C::m_Message[PN532_MESSAGE_SIZE] = {0}; + +PN532InterfaceI2C::PN532InterfaceI2C(II2C *_i2c,Uint8_t _address) + : m_I2C(_i2c), m_Address(_address) +{ +} + + + +void PN532InterfaceI2C::begin() +{ +} + +void PN532InterfaceI2C::wakeup() +{ +} + +Int8_t PN532InterfaceI2C::writeCommand( const Uint8_t *header + , Uint8_t len + , Uint8_t *body + , Uint8_t blen) +{ + Uint8_t _count = 0; + Uint8_t length = len + blen + 1; // TFI + DATA + Uint8_t sum = PN532_HOSTTOPN532; + m_Command = header[0]; // Used when cheking the response + m_Message[_count++] = PN532_PREAMBLE; + m_Message[_count++] = PN532_STARTCODE1; + m_Message[_count++] = PN532_STARTCODE2; + m_Message[_count++] = length; + m_Message[_count++] = ~length + 1 ; // Checksum of length + m_Message[_count++] = sum; // PN532_HOSTTOPN532 + + /* Copy Header */ + for ( Uint8_t i = 0 + ; (i < len) && (_count < PN532_MESSAGE_SIZE ) + ; _count++ , i++) + { + m_Message[_count] = header[i]; + sum += header[i]; + } + /* Copy body */ + for ( Uint8_t i = 0 + ; (i < blen) && (_count < PN532_MESSAGE_SIZE ) + ; _count++ , i++) + { + m_Message[_count] = body[i]; + sum += body[i]; + } + + Uint8_t checksum = ~sum + 1; + if (_count < PN532_MESSAGE_SIZE - 2) + { + m_Message[_count++] = checksum; + m_Message[_count++] = PN532_POSTAMBLE; + } else + { + return PN532_INVALID_FRAME; + } + m_I2C->write(m_Address,m_Message,_count ); + return readAckFrame(); +} + +/** + * + */ +Int16_t PN532InterfaceI2C::readResponse(Uint8_t *buf + ,Uint8_t len + ,Uint8_t timeout) +{ + Uint8_t _count = 0; + Uint8_t length = getResponseLength(buf,len,timeout); + /* Error don't continue */ + if (length < 0) + return length; + + do + { + m_I2C->read(m_Address,m_Message,6+length + 2); + if (m_Message[_count] & 0x01) + { + _count+=4; + break; // Ok, got frame ready + } + timeout--; + _delay_ms(1); + } while (timeout); + /**/ + if (!timeout) + return -1; // timeout + length = m_Message[_count++]; + /* Check len checksum */ + if ( 0 != (Uint8_t )(length + m_Message[_count++]) ) + { + return PN532_INVALID_FRAME; + } + Uint8_t cmd = m_Command + 1; + /* Check response to command */ + if ( (PN532_PN532TOHOST != m_Message[_count++]) + || (cmd != m_Message[_count++])) + { + return PN532_INVALID_FRAME; + } + + length-=2; + if ( len < length) + { + return PN532_NO_SPACE; + } + + Uint8_t sum = PN532_PN532TOHOST + cmd; + /* Read response frame */ + for (Uint8_t i = 0 ; i < length ; i++) + { + buf[i] = m_Message[_count++]; + sum+=buf[i]; + } + /* Check message checksum*/ + if (0 != (Uint8_t)(sum + m_Message[_count++])) + { + return PN532_INVALID_FRAME; + } + return length; + //return 5; +} + +Int8_t PN532InterfaceI2C::readAckFrame() +{ + const Uint8_t PN532_ACK[] = {0, 0, 0xFF, 0 , 0xFF, 0}; + Uint16_t timeout = PN532_ACK_WAIT_TIME; + do + { + m_I2C->read(m_Address,m_Message,sizeof(PN532_ACK) + 1); + if (m_Message[0] & 0x01) + { + break; + } + timeout--; + _delay_ms(1); + } while (timeout > 0); + /* If Succeed compare result */ + if (memcmp(&m_Message[1],PN532_ACK,sizeof(PN532_ACK))) + { + return PN532_INVALID_ACK; + } + return 0; +} + +/** + * + * Odd, _buff and len are unsed + */ +Int16_t PN532InterfaceI2C::getResponseLength( Uint8_t *_buff + , Uint8_t len + , Uint16_t timeout) +{ + Uint8_t PN532_NACK[] = {0,0,0xFF,0xFf,0,0}; + + do + { + m_I2C->read(m_Address,m_Message,6); + if (m_Message[0] & 0x01) + { + break; + } + timeout--; + _delay_ms(1); + } while(timeout); + + if (memcmp(&m_Message[1],PN532_NACK,3)) + { + return PN532_INVALID_FRAME; + } + Uint8_t length = m_Message[4]; + /* Send NACK */ + m_I2C->write(m_Address,PN532_NACK,static_cast(sizeof(PN532_NACK))); + + return length; +} + diff --git a/HAL/Drivers/PN532Interface_I2C.h b/HAL/Drivers/PN532Interface_I2C.h new file mode 100644 index 0000000..45ebd67 --- /dev/null +++ b/HAL/Drivers/PN532Interface_I2C.h @@ -0,0 +1,50 @@ +#ifndef __IPN532INTERFACE_I2C_H__ +#define __IPN532INTERFACE_I2C_H__ + +#define PN532_I2C_ADDRESS 0x48 +/* Let's see if max header 11 + 21 data is enough */ +/* Seems that I2C max size is 32 bytes */ +#define PN532_MESSAGE_SIZE 32 +class PN532InterfaceI2C : public IPN532Interface +{ + private: + II2C *m_I2C; + Uint8_t m_Address; + Uint8_t m_Command; + static Uint8_t m_Message[PN532_MESSAGE_SIZE]; + public: + PN532InterfaceI2C(II2C *m_i2c,Uint8_t address = PN532_I2C_ADDRESS); + + void begin(); + + void wakeup(); + + Int8_t writeCommand( const Uint8_t *header + , Uint8_t len + , Uint8_t *body = 0 + , Uint8_t blen = 0); + + Int16_t readResponse(Uint8_t *buf,Uint8_t len,Uint8_t timeout); + + private: + Uint8_t m_ReceiveByte; + private: + Int8_t readAckFrame(); + + Int16_t getResponseLength( Uint8_t *_buff + , Uint8_t len + , Uint16_t timeout); + + inline Uint8_t write(Uint8_t data) + { + return m_I2C->write(m_Address,&data,1); + } + + inline Uint8_t read() + { + m_I2C->read(m_Address,&m_ReceiveByte,1); + return m_ReceiveByte; + } + +}; +#endif -- 2.30.2