First version for PN532 I2C , can get FirmwareVersion
authorandre Ebersold <andre.ebersold@free.fr>
Sun, 12 Nov 2023 16:03:52 +0000 (17:03 +0100)
committerandre Ebersold <andre.ebersold@free.fr>
Sun, 12 Nov 2023 16:03:52 +0000 (17:03 +0100)
13 files changed:
Application/WorkhourMeter/WorkMeterHandler.cpp
Application/WorkhourMeter/WorkMeterHandler.h
Application/WorkhourMeter/main.cpp
HAL/AVR/AvrI2C.cpp
HAL/Abstract/II2C.h
HAL/Abstract/RFID/IPN532Interface.h [new file with mode: 0644]
HAL/Drivers/CMakeLists.txt
HAL/Drivers/DS3231.cpp
HAL/Drivers/DS3231.h
HAL/Drivers/PN532.cpp [new file with mode: 0644]
HAL/Drivers/PN532.h [new file with mode: 0644]
HAL/Drivers/PN532Interface_I2C.cpp [new file with mode: 0644]
HAL/Drivers/PN532Interface_I2C.h [new file with mode: 0644]

index 85219613aacdd090b72b946d58e7b8cecbb9ade4..2cf14c3a8e8468d0e4905a5cee5243bb1c421f9e 100644 (file)
@@ -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<const Uint8_t *>("1"));
+            } else
+            {
+                m_LCD->print(reinterpret_cast<const Uint8_t *>("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;
     };
 }
index 65d88a1ad4385a2fc643c08b1456d75f973c49b9..c8325537cdf4fbeb2b8bff30c1a36d94f86ec92c 100644 (file)
@@ -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
index 6e2316e56d596bca8edb6bed005b7db1ffd7f48d..bb8252c4f6f422fc033ae1238497fcb46b137211 100644 (file)
@@ -15,6 +15,7 @@
 #include <Abstract/IRtc.h>
 #include <Abstract/ILCD.h>
 #include <Abstract/ISwitch.h>
+#include "Abstract/RFID/IPN532Interface.h"
 #include <Abstract/IEeprom.h>
 #include <Application/ITask.h>
 #include <AVR/AvrTimer0.h>
@@ -32,6 +33,8 @@
 #include <Drivers/NetString.h>
 #include <Drivers/DS3231.h>
 #include <Drivers/LiquidCrystal.h>
+#include <Drivers/PN532Interface_I2C.h>
+#include <Drivers/PN532.h>
 #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<Uint8_t>(0x4E)
-                          ,static_cast<Uint8_t>(16)
-                          ,static_cast<Uint8_t>(2));
+                           ,static_cast<Uint8_t>(0x4E)
+                           ,static_cast<Uint8_t>(16)
+                           ,static_cast<Uint8_t>(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<Uint8_t >(((ver >>24) & 0xFF) / 10 + 48 );
+   msg[1]= static_cast<Uint8_t >((ver>>24) - ( (( (ver >>24) & 0xFF) / 10) * 10 ) + 48 );
+   msg[2] = 0;
+   lcd.print(msg);
+   lcd.setCursor(14,1);
+   msg[0]= static_cast<Uint8_t >( (ver >>16 & 0xFF)  + 48 );
+   msg[1]= static_cast<Uint8_t >( (ver  >>8 & 0xFF ) + 48 );
+   lcd.print(msg);
+   nfc.setPassiveActivationRetries(0xFF);
+   nfc.SAMConfig();
    lTimer.init();
    init(&gParam);
    gEeprom.init();
+   gRtc.init();
    while(1)
    {
       sched.schedule();
index 167d6d264a684f0b63c145ee8bda26b4876de9ae..734bcd8f9bcae8c5674a720779bff7893701748d 100644 (file)
@@ -37,35 +37,6 @@ void AvrI2C::init()
     //PORTC &= ~((1<<TW_SDA_PIN) | (1 <<TW_SCL_PIN));
     DDRC  &= ~((1<<TW_SDA_PIN) | (1 <<TW_SCL_PIN));
 
-    //TWCR = (1<<(TWINT))|(1<<TWSTA )|(1<<TWEN);
-
-#if 0
-    printf("TWCR 0x%x \n",TWCR);
-#endif
-    //while( !( TWCR & (1<< TWINT) ) ) ;
-#if 0
-    printf(" Start condition has been transmitted \n");
-    if( (TWSR&0xF8) != TW_START)
-    {
-
-     printf(" Error \n");
-    }
-#endif
-#if 0    
-    // Setting Address 
-    TWDR = 0x1C; 
-    // cleating TWCR 
-    TWCR = (1<<TWINT) |(1<<TWEN);
-
-    while ( !(TWCR & (1<<TWINT))) ;
-#endif    
-#if 0
-    if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
-    {
-       printf(" Error at TWSR   0x%x\n", TWSR);  // here is the problem !!!!!!!!!  TWSR value should be 0x18
-       return; 
-    }        
-#endif
 }
 
 II2C::Error_t AvrI2C::write(const Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen)
@@ -88,17 +59,28 @@ II2C::Error_t AvrI2C::write(const Uint8_t argAddress,Uint8_t *argData,Uint8_t ar
 II2C::Error_t AvrI2C::read(const Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen)
 {
     if ( ! start() )
+    {
+        stop();
         return I2C_ERROR;
-
+    }
     if (  ! sendSla( (argAddress | 1 ) ) )
+    {
+        stop();
         return I2C_ERROR;
+    }
     for (Uint8_t i = 0; i < argLen -1  ; ++i)
     {
         if (  ! receiveByte(&argData[i],true) )
+        {
+            stop();
             return I2C_ERROR;
+        }
     }
     if (  ! receiveByte(&argData[argLen-1],false) )
+    {
+        stop();
         return I2C_ERROR;
+    }
     stop();
     
     return I2C_SUCCESS;
index 82d7268a1e38c01b4b6f22b2618012ef7a5dfc5f..092f99ebe2bd41e208c9d1354f79291349714290 100644 (file)
@@ -12,9 +12,9 @@ class II2C
     virtual Error_t read(const Uint8_t argAddress,Uint8_t *argData ,Uint8_t argLen) = 0;
     
     virtual Error_t read( const Uint8_t argAddress
-                    , const Uint8_t regAddr
-                    , Uint8_t *argData
-                    , Uint8_t argLen) = 0;
+                        , const Uint8_t regAddr
+                        , Uint8_t *argData
+                        , Uint8_t argLen) = 0;
 };
 
 #endif
diff --git a/HAL/Abstract/RFID/IPN532Interface.h b/HAL/Abstract/RFID/IPN532Interface.h
new file mode 100644 (file)
index 0000000..b26ca2b
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __IPN532Interface_H__
+#define __IPN532Interface_H__
+
+#define PN532_PREAMBLE                (0x00)
+#define PN532_STARTCODE1              (0x00)
+#define PN532_STARTCODE2              (0xFF)
+#define PN532_POSTAMBLE               (0x00)
+
+#define PN532_HOSTTOPN532             (0xD4)
+#define PN532_PN532TOHOST             (0xD5)
+
+#define PN532_ACK_WAIT_TIME           (10)  // ms, timeout of waiting for ACK
+
+#define PN532_INVALID_ACK             (-1)
+#define PN532_TIMEOUT                 (-2)
+#define PN532_INVALID_FRAME           (-3)
+#define PN532_NO_SPACE                (-4)
+#define PN532_INVALID_FRAME2           (-5)
+#define PN532_INVALID_FRAME3           (-6)
+#define PN532_INVALID_FRAME4           (-7)
+#define PN532_INVALID_FRAME5           (-8)
+
+#define REVERSE_BITS_ORDER(b)         b = (b & 0xF0) >> 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
index b273975ddfb19505ddd9cbcc836bc1410e09cf21..7759086b3411a0ea32971abc08d70b0b682de2a7 100644 (file)
@@ -8,5 +8,7 @@ add_avr_library(
   DS3231.cpp
   XPT2046_Touchscreen.cpp
   LiquidCrystal.cpp
+  PN532Interface_I2C.cpp
+  PN532.cpp
    )
 
index fe78ec4ea12b243274c7235a4224721aabba72e8..93068943ad89b5badc5d7c66274bfb8df27d884b 100644 (file)
@@ -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);
 }
index 4021ba19f944f6d82bcd1717c831bb3bf79770ee..eb94e66e63ba22dacda9c5240d4cbed9ef8d0d86 100644 (file)
@@ -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 (file)
index 0000000..b1dca1b
--- /dev/null
@@ -0,0 +1,108 @@
+#include <Utils/StdTypes.h>
+#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 (file)
index 0000000..262954a
--- /dev/null
@@ -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 (file)
index 0000000..79a6f34
--- /dev/null
@@ -0,0 +1,189 @@
+#include <Utils/StdTypes.h>
+// AVr Gcc includes
+#include <string.h>
+#include <util/delay.h>
+//
+#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<Uint8_t>(sizeof(PN532_NACK)));
+
+    return length;
+}
+
diff --git a/HAL/Drivers/PN532Interface_I2C.h b/HAL/Drivers/PN532Interface_I2C.h
new file mode 100644 (file)
index 0000000..45ebd67
--- /dev/null
@@ -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