2 * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3 * Copyright (c) 2014 Intel Corporation.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 struct SM130Exception : public std::exception {
37 SM130Exception (std::string msg) : message (msg) { }
38 ~SM130Exception () throw () { }
39 const char* what() const throw () { return message.c_str(); }
42 SM130::SM130 (int bus, int devAddr, int rst, int dready) {
43 mraa_result_t error = MRAA_SUCCESS;
45 this->m_name = "SM130";
47 this->m_i2cAddr = devAddr;
50 this->m_i2Ctx = mraa_i2c_init(this->m_bus);
52 mraa_result_t ret = mraa_i2c_address(this->m_i2Ctx, this->m_i2cAddr);
53 if (ret != MRAA_SUCCESS) {
54 throw SM130Exception ("Couldn't initilize I2C.");
57 this->m_resetPinCtx = mraa_gpio_init (rst);
58 if (m_resetPinCtx == NULL) {
59 throw SM130Exception ("Couldn't initilize RESET pin.");
62 this->m_dataReadyPinCtx = mraa_gpio_init (dready);
63 if (m_dataReadyPinCtx == NULL) {
64 throw SM130Exception ("Couldn't initilize DATA READY pin.");
67 error = mraa_gpio_dir (this->m_resetPinCtx, MRAA_GPIO_OUT);
68 if (error != MRAA_SUCCESS) {
69 throw SM130Exception ("Couldn't set direction for RESET pin.");
72 error = mraa_gpio_dir (this->m_dataReadyPinCtx, MRAA_GPIO_OUT);
73 if (error != MRAA_SUCCESS) {
74 throw SM130Exception ("Couldn't set direction for DATA READY pin.");
79 mraa_result_t error = MRAA_SUCCESS;
81 error = mraa_i2c_stop(this->m_i2Ctx);
82 if (error != MRAA_SUCCESS) {
83 mraa_result_print(error);
85 error = mraa_gpio_close (this->m_resetPinCtx);
86 if (error != MRAA_SUCCESS) {
87 mraa_result_print(error);
89 error = mraa_gpio_close (this->m_dataReadyPinCtx);
90 if (error != MRAA_SUCCESS) {
91 mraa_result_print(error);
96 SM130::getFirmwareVersion () {
97 // Send VERSION command and retry a few times if no response
98 for (uint8_t n = 0; n < 10; n++) {
99 sendCommand (CMD_VERSION);
100 if (available() && getCommand() == CMD_VERSION)
101 // return versionString;
109 SM130::available () {
110 // If in SEEK mode and using DREADY pin, check the status
111 if (this->m_LastCMD == CMD_SEEK_TAG) {
112 if (!mraa_gpio_read(this->m_dataReadyPinCtx)) {
117 // Set the maximum length of the expected response packet
119 switch(this->m_LastCMD) {
120 case CMD_ANTENNA_POWER:
121 case CMD_AUTHENTICATE:
130 case CMD_WRITE_VALUE:
141 // If valid data received, process the response packet
142 if (this->i2cRecievePacket(len) > 0) {
143 // Init response variables
144 this->m_TagType = this->m_TagLength = *this->m_TagString = 0;
146 // If packet length is 2, the command failed. Set error code.
147 errorCode = this->getPacketLength () < 3 ? this->m_Data[2] : 0;
149 // Process command response
150 switch (this->getCommand ()) {
153 // RESET and VERSION commands produce the firmware version
154 len = std::min ((unsigned int) getPacketLength(), (unsigned int) sizeof(this->m_Version)) - 1;
155 memcpy(this->m_Version, this->m_Data + 2, len);
156 this->m_Version[len] = 0;
161 // If no error, get tag number
162 if(errorCode == 0 && this->getPacketLength () >= 6)
164 this->m_TagLength = this->getPacketLength () - 2;
165 this->m_TagType = this->m_Data[2];
166 memcpy(this->m_TagNumber, this->m_Data + 3, this->m_TagLength);
167 this->arrayToHex (this->m_TagString, this->m_TagNumber, this->m_TagLength);
171 case CMD_AUTHENTICATE:
181 case CMD_ANTENNA_POWER:
183 antennaPower = this->m_Data[2];
187 // If in SLEEP mode, no data is available
199 SM130::i2cRecievePacket (uint32_t len) {
202 mraa_i2c_address(this->m_i2Ctx, this->m_i2cAddr);
203 readByte = mraa_i2c_read(this->m_i2Ctx, this->m_Data, len);
206 // verify checksum if length > 0 and <= SIZE_PAYLOAD
207 if (this->m_Data[0] > 0 && this->m_Data[0] <= SIZE_PAYLOAD)
210 for (i = 0, sum = 0; i <= this->m_Data[0]; i++) {
211 sum += this->m_Data[i];
213 // return with length of response, or -1 if invalid checksum
214 return sum == this->m_Data[i] ? this->m_Data[0] : -1;
222 SM130::arrayToHex (char *s, uint8_t array[], uint8_t len) {
223 for (uint8_t i = 0; i < len; i++) {
224 *s++ = toHex(array[i] >> 4);
225 *s++ = toHex(array[i]);
232 SM130::toHex (uint8_t b) {
235 return b < 10 ? b + '0' : b + 'A' - 10;
239 SM130::i2cTransmitPacket (uint32_t len) {
240 mraa_result_t error = MRAA_SUCCESS;
244 this->m_LastCMD = this->m_Data[0];
246 // calculate the sum check
247 for (int i = 0; i < len; i++) {
248 sum += this->m_Data[i];
251 // placing the sum check to the last byte of the packet
252 this->m_Data[len + 1] = sum;
254 error = mraa_i2c_address (this->m_i2Ctx, this->m_i2cAddr);
255 error = mraa_i2c_write (this->m_i2Ctx, this->m_Data, len + 1);
261 SM130::sendCommand (uint8_t cmd) {
263 this->m_Data[1] = cmd;
264 this->i2cTransmitPacket(2);