From 9f1580bec2db9fb12845b9b0bc87874c6d9ba555 Mon Sep 17 00:00:00 2001 From: andre Ebersold Date: Sun, 12 Nov 2023 21:44:07 +0100 Subject: [PATCH] First Badge detection working --- Application/WorkhourMeter/CMakeLists.txt | 4 +- .../WorkhourMeter/WorkMeterHandler.cpp | 20 +-- Application/WorkhourMeter/main.cpp | 33 +++-- HAL/Abstract/RFID/IPN532Interface.h | 9 +- HAL/Drivers/PN532.cpp | 39 ++++++ HAL/Drivers/PN532.h | 10 +- HAL/Drivers/PN532Interface_I2C.cpp | 55 +++++--- HAL/Drivers/PN532Interface_I2C.h | 14 +- Metadata/WorkMeterParamIds.h | 8 +- Platform/CMakeLists.txt | 1 + Platform/RFIDReader/RFIDReaderHandler.cpp | 126 ++++++++++++++++++ Platform/RFIDReader/RFIDReaderHandler.h | 40 ++++++ 12 files changed, 315 insertions(+), 44 deletions(-) create mode 100644 Platform/RFIDReader/RFIDReaderHandler.cpp create mode 100644 Platform/RFIDReader/RFIDReaderHandler.h diff --git a/Application/WorkhourMeter/CMakeLists.txt b/Application/WorkhourMeter/CMakeLists.txt index 113c8a2..705607d 100644 --- a/Application/WorkhourMeter/CMakeLists.txt +++ b/Application/WorkhourMeter/CMakeLists.txt @@ -13,8 +13,8 @@ target_link_libraries( avrHAL-${AVR_MCU} avrDrivers-${AVR_MCU} avrComm-${AVR_MCU} - avrPS-Ptf-${AVR_MCU} - avrPowerswitchParameters-${AVR_MCU} + avrWM-Ptf-${AVR_MCU} + avrWorkMeterParameters-${AVR_MCU} ) IF ( "${AVR_MCU}" STREQUAL "atmega328p") diff --git a/Application/WorkhourMeter/WorkMeterHandler.cpp b/Application/WorkhourMeter/WorkMeterHandler.cpp index 2cf14c3..2648468 100644 --- a/Application/WorkhourMeter/WorkMeterHandler.cpp +++ b/Application/WorkhourMeter/WorkMeterHandler.cpp @@ -19,6 +19,7 @@ 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 */ + m_Params->registerListener(PID_Display,this); /* State on or off */ m_Params->registerListener(PID_Hour,this); /* State on or off */ m_Params->registerListener(PID_Minute,this); /* State on or off */ @@ -43,6 +44,9 @@ void WorkMeterHandler::onWriteValue(const Uint8_t paramID,const Uint8_t _val) case PID_BackLight: m_LCD->setDisplay(_val); break; + case PID_Display: + m_LCD->setDisplay(_val); + break; default: ; } @@ -106,7 +110,10 @@ void WorkMeterHandler::run() m_State = ST_DISP_UPDATE_TIME; break; case ST_DISP_UPDATE_TAG: - if (m_UidLength > 0) + { + uint8_t _present = 0; + m_Params->readValue(PID_BadgePresent,_present); + if (_present> 0) { m_LCD->print(reinterpret_cast("1")); } else @@ -114,6 +121,7 @@ void WorkMeterHandler::run() m_LCD->print(reinterpret_cast("0")); } m_State = ST_WAIT; + } break; case ST_DISP_UPDATE_TIME: timeToString(); @@ -122,14 +130,8 @@ void WorkMeterHandler::run() 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; + m_State = ST_DISP_UPDATE_CURSOR_TAG; + //m_State = ST_WAIT; break; case ST_WAIT: m_State = ST_WAIT; diff --git a/Application/WorkhourMeter/main.cpp b/Application/WorkhourMeter/main.cpp index bb8252c..401ec4f 100644 --- a/Application/WorkhourMeter/main.cpp +++ b/Application/WorkhourMeter/main.cpp @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -35,6 +35,8 @@ #include #include #include + +#include #include "Led0.h" #include "WorkMeterHandler.h" #if 0 @@ -73,15 +75,19 @@ class Scheduler : public IInterruptActivity static Task_type gTasks[TASK_COUNT]; public: - Scheduler(Led0 *_led,IProtocolLayer2 *_net,CommunicationHandler *_com,ITask *_argRtc - ,ITask *_Storage - ) + Scheduler( Led0 *_led,IProtocolLayer2 *_net + , CommunicationHandler *_com + , ITask *_argRtc + , ITask *_Storage + , ITask *_RFIDReader + ) : m_Led(_led) , m_Netstring(_net) , m_Com(_com) , m_WorkMeter(_argRtc) - , m_Storage(_Storage) + , m_Storage(_Storage) + , m_RFIDReader(_RFIDReader) , m_CurrentTimeslot(FIRST_TIME_SLOT) , m_CurrentTask(TASK1) { @@ -100,6 +106,7 @@ class Scheduler : public IInterruptActivity break; case TASK2: m_Led->tick(); + m_RFIDReader->run(); break; case TASK3: m_Led->tick(); @@ -140,6 +147,7 @@ class Scheduler : public IInterruptActivity CommunicationHandler *m_Com; ITask *m_WorkMeter; ITask *m_Storage; + ITask *m_RFIDReader; volatile TIME_SLOTS m_CurrentTimeslot; ETASK_ID m_CurrentTask; RtcTime_t m_Time; @@ -166,7 +174,7 @@ void init(IParameterHandler *m_Param) */ int main(void) { - PowerswitchParameterHandler gParam; + ParameterHandler gParam; #if defined (__AVR_ATmega32U4__) Led0 led(&PORTC, &DDRC, PINB7,&gParam); #else @@ -185,8 +193,15 @@ int main(void) NetString netstring(&uart); CommunicationHandler gCom(&netstring,&gParam); PersistentStorage gStorage(&gEeprom,&gParam); + RFIDReaderHandler gRFIDReader(&nfc,&gParam); WorkMeterHandler gWorkMeter(&gRtc,&lcd,&gParam,&nfc); - Scheduler sched(&led,&netstring,&gCom,&gWorkMeter,&gStorage); + Scheduler sched( &led + , &netstring + , &gCom + , &gWorkMeter + , &gStorage + , &gRFIDReader + ); Uint8_t msg[15] ; uart.init(); gI2c.init(); @@ -210,7 +225,7 @@ int main(void) msg[0]= static_cast( (ver >>16 & 0xFF) + 48 ); msg[1]= static_cast( (ver >>8 & 0xFF ) + 48 ); lcd.print(msg); - nfc.setPassiveActivationRetries(0xFF); + nfc.setPassiveActivationRetries(0x01); nfc.SAMConfig(); lTimer.init(); init(&gParam); diff --git a/HAL/Abstract/RFID/IPN532Interface.h b/HAL/Abstract/RFID/IPN532Interface.h index b26ca2b..4daed1f 100644 --- a/HAL/Abstract/RFID/IPN532Interface.h +++ b/HAL/Abstract/RFID/IPN532Interface.h @@ -37,6 +37,13 @@ class IPN532Interface * */ virtual void wakeup() = 0; + /** + * \brief before reading a response, the caller must + * check if a response is ready or else, he needs to + * wait and check later + * + */ + virtual Bool_t isReady() = 0; /** * */ @@ -50,7 +57,7 @@ class IPN532Interface */ virtual Int16_t readResponse( Uint8_t *buf , Uint8_t len - , Uint8_t timeout = 100) = 0; + , Uint16_t timeout = 100) = 0; }; diff --git a/HAL/Drivers/PN532.cpp b/HAL/Drivers/PN532.cpp index b1dca1b..e49c706 100644 --- a/HAL/Drivers/PN532.cpp +++ b/HAL/Drivers/PN532.cpp @@ -106,3 +106,42 @@ Bool_t PN532::setPassiveActivationRetries(Uint8_t _retries) } return ( 0 < ITF(readResponse)(m_PacketBuffer,sizeof(m_PacketBuffer))); } + + +Bool_t PN532::reqPassiveTargetID(Uint8_t _type) +{ + m_PacketBuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + m_PacketBuffer[1] = 0x01; // normal mode + m_PacketBuffer[2] = _type; + + if (ITF(writeCommand)(m_PacketBuffer,3)) + { + return false; // command failed + } + return true; +} + +Bool_t PN532::processPassiveTargetID( Uint8_t *uid,Uint8_t *uidLength) +{ + // 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 < 7) ; i++) + { + uid[i] = m_PacketBuffer[6 + i]; + } + return 1; +} + diff --git a/HAL/Drivers/PN532.h b/HAL/Drivers/PN532.h index 262954a..52b55c6 100644 --- a/HAL/Drivers/PN532.h +++ b/HAL/Drivers/PN532.h @@ -123,6 +123,8 @@ class PN532 IPN532Interface *m_Itf; public: PN532(IPN532Interface *itf); // Default contructor Needs in Interface + + inline Bool_t isReady() { return m_Itf->isReady(); }; void begin(); @@ -134,9 +136,15 @@ class PN532 Bool_t readPassiveTargetID(Uint8_t _type,Uint8_t *uid,Uint8_t *uidLength); + /** + * Req / process based not using internal wait delay + */ + Bool_t reqPassiveTargetID(Uint8_t _type); + + Bool_t processPassiveTargetID( 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_UID[9]; // ISO14443A uid Uint8_t m_UIDLength; diff --git a/HAL/Drivers/PN532Interface_I2C.cpp b/HAL/Drivers/PN532Interface_I2C.cpp index 79a6f34..ae5a458 100644 --- a/HAL/Drivers/PN532Interface_I2C.cpp +++ b/HAL/Drivers/PN532Interface_I2C.cpp @@ -12,6 +12,7 @@ Uint8_t PN532InterfaceI2C::m_Message[PN532_MESSAGE_SIZE] = {0}; PN532InterfaceI2C::PN532InterfaceI2C(II2C *_i2c,Uint8_t _address) : m_I2C(_i2c), m_Address(_address) { + m_ReadReady = false; } @@ -70,18 +71,38 @@ Int8_t PN532InterfaceI2C::writeCommand( const Uint8_t *header return readAckFrame(); } +/** + * + */ +Bool_t PN532InterfaceI2C::isReady() +{ + m_I2C->read(m_Address,m_Message,6); + if (m_Message[0] & 0x01) + { + m_ReadReady = true; + } + return m_ReadReady; +} + + /** * */ Int16_t PN532InterfaceI2C::readResponse(Uint8_t *buf ,Uint8_t len - ,Uint8_t timeout) + ,Uint16_t timeout) { Uint8_t _count = 0; - Uint8_t length = getResponseLength(buf,len,timeout); + Uint16_t ResponseLength = getResponseLength(buf,len,timeout); /* Error don't continue */ - if (length < 0) - return length; + if (ResponseLength < 0) + return ResponseLength; + Uint8_t length = static_cast(ResponseLength); + + if ( PN532_MESSAGE_SIZE < (length + 8)) + { + return PN532_NO_SPACE; + } do { @@ -92,7 +113,7 @@ Int16_t PN532InterfaceI2C::readResponse(Uint8_t *buf break; // Ok, got frame ready } timeout--; - _delay_ms(1); + _delay_us(100); } while (timeout); /**/ if (!timeout) @@ -137,6 +158,7 @@ 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); @@ -148,6 +170,7 @@ Int8_t PN532InterfaceI2C::readAckFrame() _delay_ms(1); } while (timeout > 0); /* If Succeed compare result */ + m_ReadReady = false; if (memcmp(&m_Message[1],PN532_ACK,sizeof(PN532_ACK))) { return PN532_INVALID_ACK; @@ -164,17 +187,19 @@ Int16_t PN532InterfaceI2C::getResponseLength( Uint8_t *_buff , Uint16_t timeout) { Uint8_t PN532_NACK[] = {0,0,0xFF,0xFf,0,0}; - - do + /* In case we already wait we don't retry */ + if (!m_ReadReady) { - m_I2C->read(m_Address,m_Message,6); - if (m_Message[0] & 0x01) + do { - break; - } - timeout--; - _delay_ms(1); - } while(timeout); + if (isReady()) + { + break; + } + timeout--; + _delay_ms(1); + } while(timeout); + } if (memcmp(&m_Message[1],PN532_NACK,3)) { @@ -183,7 +208,7 @@ Int16_t PN532InterfaceI2C::getResponseLength( Uint8_t *_buff Uint8_t length = m_Message[4]; /* Send NACK */ m_I2C->write(m_Address,PN532_NACK,static_cast(sizeof(PN532_NACK))); - + m_ReadReady = false; return length; } diff --git a/HAL/Drivers/PN532Interface_I2C.h b/HAL/Drivers/PN532Interface_I2C.h index 45ebd67..f30eaa7 100644 --- a/HAL/Drivers/PN532Interface_I2C.h +++ b/HAL/Drivers/PN532Interface_I2C.h @@ -5,6 +5,7 @@ /* 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: @@ -24,17 +25,23 @@ class PN532InterfaceI2C : public IPN532Interface , Uint8_t *body = 0 , Uint8_t blen = 0); - Int16_t readResponse(Uint8_t *buf,Uint8_t len,Uint8_t timeout); + Int16_t readResponse(Uint8_t *buf,Uint8_t len,Uint16_t timeout); + + /** + * In addition to check if a response is ready, + * this method also stores the length to read + */ + Bool_t isReady() ; private: - Uint8_t m_ReceiveByte; + Bool_t m_ReadReady; private: Int8_t readAckFrame(); Int16_t getResponseLength( Uint8_t *_buff , Uint8_t len , Uint16_t timeout); - +#if 0 inline Uint8_t write(Uint8_t data) { return m_I2C->write(m_Address,&data,1); @@ -45,6 +52,7 @@ class PN532InterfaceI2C : public IPN532Interface m_I2C->read(m_Address,&m_ReceiveByte,1); return m_ReceiveByte; } +#endif }; #endif diff --git a/Metadata/WorkMeterParamIds.h b/Metadata/WorkMeterParamIds.h index 42c9594..bd3b707 100644 --- a/Metadata/WorkMeterParamIds.h +++ b/Metadata/WorkMeterParamIds.h @@ -15,10 +15,10 @@ enum ParameterIds { , PID_LedCycle = 5 /* Ye Blinking led cycle. 0 is off */ , PID_LedState = 6 /* Set let state ... */ , PID_Display = 7 /* Set On/Off Display */ - , PID_DelayP2 = 8 - , PID_DelayP3 = 9 /* Cycle Per rotation used in closed loop */ - , PID_DelayP4 = 10 /* Set PID constant factor */ - , PID_Ki = 11 /* Set PID integral factor */ + , PID_RFFirmwareVersion = 8 + , PID_FirmwareVersion = 9 /* Cycle Per rotation used in closed loop */ + , PID_BadgePresent = 10 /* Set PID constant factor */ + , PID_BadgeCount = 11 /* Set PID integral factor */ , PID_Kd = 12 /* Set PID derivation factor */ , PID_MAConsPwm = 13 /* Pwm modulation instruction, Applied in open loop, ignore in closed loop */ , PID_MAConsRpm = 14 /* Rpm instruction used as reference in closed loop */ diff --git a/Platform/CMakeLists.txt b/Platform/CMakeLists.txt index 283bf36..3b9d0e2 100644 --- a/Platform/CMakeLists.txt +++ b/Platform/CMakeLists.txt @@ -46,6 +46,7 @@ add_avr_library( avrWM-Ptf ParameterHandler.cpp PersistentStorage.cpp + RFIDReader/RFIDReaderHandler.cpp ) set_target_properties( diff --git a/Platform/RFIDReader/RFIDReaderHandler.cpp b/Platform/RFIDReader/RFIDReaderHandler.cpp new file mode 100644 index 0000000..ef992ab --- /dev/null +++ b/Platform/RFIDReader/RFIDReaderHandler.cpp @@ -0,0 +1,126 @@ +#include "Utils/StdTypes.h" +#include "Application/ITask.h" +#include "Abstract/RFID/IPN532Interface.h" +#include "HAL/Drivers/PN532.h" +#include "Platform/IParameterHandler.h" + +#include "Metadata/WorkmeterParamIds.h" +#include "Platform/RFIDReader/RFIDReaderHandler.h" + + + + + +RFIDReaderHandler::RFIDReaderHandler(PN532 *argNFC,IParameterHandler *argParam) + : m_NFC(argNFC), m_Param(argParam),m_State(ST_IDLE) +{ +} + +void RFIDReaderHandler::run() +{ + if (m_Ticks++ > 100) + { + m_Ticks = 0; + m_State = ST_IDLE; + } + doStateMachine(); +} + +void RFIDReaderHandler::doStateMachine() +{ + switch (m_State) + { + case ST_IDLE: + { // Check if + //m_State = ST_DISP_OFF; + m_State = ST_REQ_BADGE_ID; + } + break; + case ST_REQ_FIRMWAREVERSION: + break; + case ST_REQ_BADGE_ID: + doRequestBadgeID(); + + m_CurrentRequest = ST_PROCESS_BADGE_ID; + m_State = ST_PROCESS_BADGE_ID; + break; + case ST_PROCESS_BADGE_ID: + if (m_NFC->isReady()) + { + doProcessBadgeID(); + m_State = ST_DISP_ON; // Do nothing + } else + { + m_1Milli = 10; + m_State = ST_WAIT_RESPONSE; + } + break; + case ST_PROCESS_FIRMWAREVERSION: + break; + case ST_DISP_ON: + doDisplay(false); + m_State = ST_WAIT_BADGE; // Do nothing + break; + case ST_DISP_OFF: + doDisplay(true); + m_1Milli = 10; + m_State = ST_WAIT_RESPONSE; + m_CurrentRequest = ST_REQ_BADGE_ID; + break; + case ST_WAIT_BADGE: + break; + case ST_WAIT_RESPONSE: + { + // Check if I get a ready response + // If not go to state + doDelay1Milli(); + } + break; + case ST_DELAY_1MILLI: + { + if (! (m_1Milli--) ) + m_State = ST_WAIT_RESPONSE; + } + break; + default: + ; + } +} + +void RFIDReaderHandler::doRequestFirmwareVersion() +{ +} + +void RFIDReaderHandler::doRequestBadgeID() +{ + m_NFC->reqPassiveTargetID(PN532_MIFARE_ISO14443A); + +} + +void RFIDReaderHandler::doDelay1Milli() +{ + if ( ! m_1Milli--) + { + m_State = m_CurrentRequest; + } +} + + +void RFIDReaderHandler::doProcessFirmwareVersion() +{ +} + +void RFIDReaderHandler::doProcessBadgeID() +{ + Uint8_t Uid[9]; + Uint8_t UidLength = 0; + m_NFC->processPassiveTargetID(Uid,&UidLength); + m_Param->writeValue(PID_BadgePresent,UidLength); + Uint8_t disp = 0; + m_Param->writeValue(PID_Display,disp); +} + +void RFIDReaderHandler::doDisplay(Uint8_t _on) +{ + m_Param->writeValue(PID_Display,_on); +} diff --git a/Platform/RFIDReader/RFIDReaderHandler.h b/Platform/RFIDReader/RFIDReaderHandler.h new file mode 100644 index 0000000..9326d96 --- /dev/null +++ b/Platform/RFIDReader/RFIDReaderHandler.h @@ -0,0 +1,40 @@ +#ifndef __RFIDREADERHANDLER_H__ +#define __RFIDREADERHANDLER_H__ + +#define RFID_TICKS_1MILLI 10 +#define RFID_TICKS_10MILLI 100 + +class RFIDReaderHandler : public ITask +{ + enum eStates { + ST_IDLE + ,ST_REQ_FIRMWAREVERSION + ,ST_REQ_BADGE_ID + ,ST_PROCESS_BADGE_ID + ,ST_PROCESS_FIRMWAREVERSION + ,ST_DISP_OFF + ,ST_DISP_ON + ,ST_WAIT_BADGE + ,ST_WAIT_RESPONSE + ,ST_DELAY_1MILLI + }; + public: + RFIDReaderHandler(PN532 *argNFC,IParameterHandler *argParam); + void run(); + private: + void doStateMachine(); + void doRequestFirmwareVersion(); + void doRequestBadgeID(); + void doProcessFirmwareVersion(); + void doProcessBadgeID(); + void doDelay1Milli(); + void doDisplay(Uint8_t _on); + private: + PN532 *m_NFC; + IParameterHandler *m_Param; + Uint8_t m_State; + Uint8_t m_1Milli; + Uint8_t m_CurrentRequest; + Uint16_t m_Ticks; // Count 100us ticks +}; +#endif -- 2.30.2