Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RWDModule/RWDModule.cpp@4:952267f44d02, 2013-06-29 (annotated)
- Committer:
- seblovett
- Date:
- Sat Jun 29 18:57:07 2013 +0000
- Revision:
- 4:952267f44d02
- Parent:
- 0:340078fc5139
v1.01 minor changes, mainly added comments
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
seblovett | 0:340078fc5139 | 1 | /* |
seblovett | 0:340078fc5139 | 2 | Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) |
seblovett | 0:340078fc5139 | 3 | |
seblovett | 0:340078fc5139 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
seblovett | 0:340078fc5139 | 5 | of this software and associated documentation files (the "Software"), to deal |
seblovett | 0:340078fc5139 | 6 | in the Software without restriction, including without limitation the rights |
seblovett | 0:340078fc5139 | 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
seblovett | 0:340078fc5139 | 8 | copies of the Software, and to permit persons to whom the Software is |
seblovett | 0:340078fc5139 | 9 | furnished to do so, subject to the following conditions: |
seblovett | 0:340078fc5139 | 10 | |
seblovett | 0:340078fc5139 | 11 | The above copyright notice and this permission notice shall be included in |
seblovett | 0:340078fc5139 | 12 | all copies or substantial portions of the Software. |
seblovett | 0:340078fc5139 | 13 | |
seblovett | 0:340078fc5139 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
seblovett | 0:340078fc5139 | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
seblovett | 0:340078fc5139 | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
seblovett | 0:340078fc5139 | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
seblovett | 0:340078fc5139 | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
seblovett | 0:340078fc5139 | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
seblovett | 0:340078fc5139 | 20 | THE SOFTWARE. |
seblovett | 0:340078fc5139 | 21 | */ |
seblovett | 0:340078fc5139 | 22 | |
seblovett | 0:340078fc5139 | 23 | #include "RWDModule.h" |
seblovett | 0:340078fc5139 | 24 | |
seblovett | 0:340078fc5139 | 25 | RWDModule::RWDModule(PinName tx, PinName rx, PinName cts) : m_serial(tx, rx), m_cts(cts), |
seblovett | 0:340078fc5139 | 26 | 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) |
seblovett | 0:340078fc5139 | 27 | { |
seblovett | 0:340078fc5139 | 28 | //Setup baudrate |
seblovett | 0:340078fc5139 | 29 | m_serial.baud(9600); |
seblovett | 0:340078fc5139 | 30 | //Setup interrupts |
seblovett | 0:340078fc5139 | 31 | m_serial.attach(this, &RWDModule::intTx, Serial::TxIrq); //Serial port writeable |
seblovett | 0:340078fc5139 | 32 | m_serial.attach(this, &RWDModule::intRx, Serial::RxIrq); //Serial port readable |
seblovett | 0:340078fc5139 | 33 | m_cts.fall(this, &RWDModule::intClearToSend); //Clear To Send: can send a command |
seblovett | 0:340078fc5139 | 34 | } |
seblovett | 0:340078fc5139 | 35 | |
seblovett | 0:340078fc5139 | 36 | 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 |
seblovett | 0:340078fc5139 | 37 | { |
seblovett | 0:340078fc5139 | 38 | if(!ready()) //If reader is not ready, does not submit another command yet |
seblovett | 0:340078fc5139 | 39 | return; |
seblovett | 0:340078fc5139 | 40 | |
seblovett | 0:340078fc5139 | 41 | //Setup command |
seblovett | 0:340078fc5139 | 42 | m_cmd = cmd; |
seblovett | 0:340078fc5139 | 43 | |
seblovett | 0:340078fc5139 | 44 | //Setup parameters |
seblovett | 0:340078fc5139 | 45 | m_paramsBuf = (uint8_t*) params; |
seblovett | 0:340078fc5139 | 46 | m_paramsLen = paramsLen; |
seblovett | 0:340078fc5139 | 47 | |
seblovett | 0:340078fc5139 | 48 | //Setup response |
seblovett | 0:340078fc5139 | 49 | m_respBuf = resp; |
seblovett | 0:340078fc5139 | 50 | m_respLen = respLen; |
seblovett | 0:340078fc5139 | 51 | |
seblovett | 0:340078fc5139 | 52 | //Pos in buf is 0 |
seblovett | 0:340078fc5139 | 53 | m_pos = 0; |
seblovett | 0:340078fc5139 | 54 | |
seblovett | 0:340078fc5139 | 55 | //Setup ack requirements |
seblovett | 0:340078fc5139 | 56 | m_ackOk = ackOk; |
seblovett | 0:340078fc5139 | 57 | m_ackOkMask = ackOkMask; |
seblovett | 0:340078fc5139 | 58 | |
seblovett | 0:340078fc5139 | 59 | m_state = CMD_QUEUED; |
seblovett | 0:340078fc5139 | 60 | } |
seblovett | 0:340078fc5139 | 61 | |
seblovett | 0:340078fc5139 | 62 | bool RWDModule::ready() |
seblovett | 0:340078fc5139 | 63 | { |
seblovett | 0:340078fc5139 | 64 | return (m_state==READY); |
seblovett | 0:340078fc5139 | 65 | } |
seblovett | 0:340078fc5139 | 66 | |
seblovett | 0:340078fc5139 | 67 | bool RWDModule::result(uint8_t* pAck /*= NULL*/) |
seblovett | 0:340078fc5139 | 68 | { |
seblovett | 0:340078fc5139 | 69 | if(!ready()) //Has command returned yet? |
seblovett | 0:340078fc5139 | 70 | return false; |
seblovett | 0:340078fc5139 | 71 | if(pAck) //If pointer is passed, return reader's ack |
seblovett | 0:340078fc5139 | 72 | *pAck = m_ack; |
seblovett | 0:340078fc5139 | 73 | return ((m_ack & m_ackOkMask) == m_ackOk); //Return whether the reader returned an error or OK ack |
seblovett | 0:340078fc5139 | 74 | } |
seblovett | 0:340078fc5139 | 75 | |
seblovett | 0:340078fc5139 | 76 | void RWDModule::intClearToSend() |
seblovett | 0:340078fc5139 | 77 | { |
seblovett | 0:340078fc5139 | 78 | //Start sending command when Clear To Send falls |
seblovett | 0:340078fc5139 | 79 | if(m_state == CMD_QUEUED) //Is there a command to be sent? |
seblovett | 0:340078fc5139 | 80 | { |
seblovett | 0:340078fc5139 | 81 | m_state = SENDING_CMD; |
seblovett | 0:340078fc5139 | 82 | intTx(); //Start sending command |
seblovett | 0:340078fc5139 | 83 | } |
seblovett | 0:340078fc5139 | 84 | } |
seblovett | 0:340078fc5139 | 85 | |
seblovett | 0:340078fc5139 | 86 | |
seblovett | 0:340078fc5139 | 87 | void RWDModule::intTx() |
seblovett | 0:340078fc5139 | 88 | { |
seblovett | 0:340078fc5139 | 89 | if(m_state != SENDING_CMD) |
seblovett | 0:340078fc5139 | 90 | return; |
seblovett | 0:340078fc5139 | 91 | if(m_pos==0) //Must send command-byte first |
seblovett | 0:340078fc5139 | 92 | m_serial.putc((char)m_cmd); |
seblovett | 0:340078fc5139 | 93 | while(true) //Send payload |
seblovett | 0:340078fc5139 | 94 | { |
seblovett | 0:340078fc5139 | 95 | if(m_pos >= m_paramsLen) //Payload sent completely? |
seblovett | 0:340078fc5139 | 96 | { |
seblovett | 0:340078fc5139 | 97 | m_pos = 0; |
seblovett | 0:340078fc5139 | 98 | m_state = WAITING_FOR_ACK; //Next step |
seblovett | 0:340078fc5139 | 99 | return; |
seblovett | 0:340078fc5139 | 100 | } |
seblovett | 0:340078fc5139 | 101 | m_serial.putc((char)m_paramsBuf[m_pos]); //Send payload byte |
seblovett | 0:340078fc5139 | 102 | m_pos++; |
seblovett | 0:340078fc5139 | 103 | } |
seblovett | 0:340078fc5139 | 104 | } |
seblovett | 0:340078fc5139 | 105 | |
seblovett | 0:340078fc5139 | 106 | void RWDModule::intRx() |
seblovett | 0:340078fc5139 | 107 | { |
seblovett | 0:340078fc5139 | 108 | if(m_state == WAITING_FOR_ACK) //Get answer |
seblovett | 0:340078fc5139 | 109 | { |
seblovett | 0:340078fc5139 | 110 | m_ack = m_serial.getc(); //Get Ack |
seblovett | 0:340078fc5139 | 111 | if( (m_ack & m_ackOkMask) != m_ackOk ) //Check if an error is returned |
seblovett | 0:340078fc5139 | 112 | { |
seblovett | 0:340078fc5139 | 113 | m_state = READY; //If yes, transfer is completed and result() will return false |
seblovett | 0:340078fc5139 | 114 | return; |
seblovett | 0:340078fc5139 | 115 | } |
seblovett | 0:340078fc5139 | 116 | if(m_respLen) |
seblovett | 0:340078fc5139 | 117 | { |
seblovett | 0:340078fc5139 | 118 | m_state = RECEIVING_ACK; //Ack OK, now need to get response |
seblovett | 0:340078fc5139 | 119 | } |
seblovett | 0:340078fc5139 | 120 | else |
seblovett | 0:340078fc5139 | 121 | { |
seblovett | 0:340078fc5139 | 122 | m_state = READY; //Ack OK, end of transfer |
seblovett | 0:340078fc5139 | 123 | return; |
seblovett | 0:340078fc5139 | 124 | } |
seblovett | 0:340078fc5139 | 125 | } |
seblovett | 0:340078fc5139 | 126 | if(m_state != RECEIVING_ACK) //Error, should not happen |
seblovett | 0:340078fc5139 | 127 | { |
seblovett | 0:340078fc5139 | 128 | while(m_serial.readable()) |
seblovett | 0:340078fc5139 | 129 | m_serial.getc(); //Dump these bytes |
seblovett | 0:340078fc5139 | 130 | return; |
seblovett | 0:340078fc5139 | 131 | } |
seblovett | 0:340078fc5139 | 132 | while(m_serial.readable()) //Read payload |
seblovett | 0:340078fc5139 | 133 | { |
seblovett | 0:340078fc5139 | 134 | m_respBuf[m_pos] = (uint8_t) m_serial.getc(); //Read byte and put it in resp buf |
seblovett | 0:340078fc5139 | 135 | m_pos++; |
seblovett | 0:340078fc5139 | 136 | if(m_pos >= m_respLen) |
seblovett | 0:340078fc5139 | 137 | { |
seblovett | 0:340078fc5139 | 138 | m_pos = 0; |
seblovett | 0:340078fc5139 | 139 | m_state = READY; //End of transfer, response retrieved with success |
seblovett | 0:340078fc5139 | 140 | } |
seblovett | 0:340078fc5139 | 141 | } |
seblovett | 0:340078fc5139 | 142 | } |