Basic Read and Writer implementation for an OEM Mifare RWD Device.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RWDModule.cpp Source File

RWDModule.cpp

00001 /*
00002 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00003  
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010  
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013  
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 #include "RWDModule.h"
00024 
00025 RWDModule::RWDModule(PinName tx, PinName rx, PinName cts) : m_serial(tx, rx), m_cts(cts),
00026 m_cmd(0), m_paramsBuf(NULL), m_respBuf(NULL), m_pos(0), m_paramsLen(0), m_respLen(0), m_ackOk(0), m_ackOkMask(0), m_ack(0), m_state(READY)
00027 {
00028   //Setup baudrate
00029   m_serial.baud(9600);
00030   //Setup interrupts
00031   m_serial.attach(this, &RWDModule::intTx, Serial::TxIrq); //Serial port writeable
00032   m_serial.attach(this, &RWDModule::intRx, Serial::RxIrq); //Serial port readable
00033   m_cts.fall(this, &RWDModule::intClearToSend); //Clear To Send: can send a command
00034 }
00035 
00036 void RWDModule::command(uint8_t cmd, const uint8_t* params, int paramsLen, uint8_t* resp, size_t respLen, uint8_t ackOk, size_t ackOkMask) //Ack Byte is not included in the resp buf
00037 {
00038   if(!ready()) //If reader is not ready, does not submit another command yet
00039     return;
00040   
00041   //Setup command
00042   m_cmd = cmd;
00043   
00044   //Setup parameters
00045   m_paramsBuf = (uint8_t*) params;
00046   m_paramsLen = paramsLen;
00047   
00048   //Setup response
00049   m_respBuf = resp;
00050   m_respLen = respLen;
00051   
00052   //Pos in buf is 0
00053   m_pos = 0;
00054   
00055   //Setup ack requirements
00056   m_ackOk = ackOk;
00057   m_ackOkMask = ackOkMask;
00058   
00059   m_state = CMD_QUEUED;
00060 }
00061   
00062 bool RWDModule::ready()
00063 {
00064   return (m_state==READY);
00065 }
00066    
00067 bool RWDModule::result(uint8_t* pAck /*= NULL*/)
00068 {
00069   if(!ready()) //Has command returned yet?
00070     return false;
00071   if(pAck) //If pointer is passed, return reader's ack
00072     *pAck = m_ack;
00073   return ((m_ack & m_ackOkMask) == m_ackOk); //Return whether the reader returned an error or OK ack
00074 }
00075 
00076 void RWDModule::intClearToSend()
00077 {
00078   //Start sending command when Clear To Send falls
00079   if(m_state == CMD_QUEUED) //Is there a command to be sent?
00080   {
00081     m_state = SENDING_CMD;
00082     intTx(); //Start sending command
00083   }
00084 }
00085 
00086 
00087 void RWDModule::intTx()
00088 {
00089   if(m_state != SENDING_CMD)
00090     return;  
00091   if(m_pos==0) //Must send command-byte first
00092     m_serial.putc((char)m_cmd);
00093   while(true) //Send payload
00094   {
00095     if(m_pos >= m_paramsLen) //Payload sent completely?
00096     {
00097       m_pos = 0;
00098       m_state = WAITING_FOR_ACK; //Next step
00099       return;
00100     }
00101     m_serial.putc((char)m_paramsBuf[m_pos]); //Send payload byte
00102     m_pos++;
00103   }
00104 }
00105 
00106 void RWDModule::intRx()
00107 {
00108   if(m_state == WAITING_FOR_ACK) //Get answer
00109   {
00110     m_ack = m_serial.getc(); //Get Ack
00111     if( (m_ack & m_ackOkMask) != m_ackOk ) //Check if an error is returned
00112     {
00113       m_state = READY; //If yes, transfer is completed and result() will return false
00114       return;
00115     }
00116     if(m_respLen)
00117     {
00118       m_state = RECEIVING_ACK; //Ack OK, now need to get response
00119     }
00120     else
00121     {
00122       m_state = READY; //Ack OK, end of transfer
00123       return;
00124     }
00125   }
00126   if(m_state != RECEIVING_ACK) //Error, should not happen
00127   {
00128     while(m_serial.readable())
00129       m_serial.getc(); //Dump these bytes
00130     return; 
00131   }
00132   while(m_serial.readable()) //Read payload
00133   {
00134     m_respBuf[m_pos] = (uint8_t) m_serial.getc(); //Read byte and put it in resp buf
00135     m_pos++;
00136     if(m_pos >= m_respLen)
00137     {
00138       m_pos = 0;
00139       m_state = READY; //End of transfer, response retrieved with success
00140     }
00141   }
00142 }