From bb38b35b323f0935bcc8b7b6b5eaf2016c397d79 Mon Sep 17 00:00:00 2001 From: Kiveisha Yevgeniy Date: Fri, 4 Jul 2014 15:10:09 +0000 Subject: [PATCH] sm130: Added new sensor (basic function was implemented and not tested) Signed-off-by: Kiveisha Yevgeniy --- src/sm130/CMakeLists.txt | 5 + src/sm130/jsupm_sm130.i | 8 ++ src/sm130/pyupm_sm130.i | 9 ++ src/sm130/sm130.cxx | 265 +++++++++++++++++++++++++++++++++++++++++++++++ src/sm130/sm130.h | 148 ++++++++++++++++++++++++++ 5 files changed, 435 insertions(+) create mode 100644 src/sm130/CMakeLists.txt create mode 100644 src/sm130/jsupm_sm130.i create mode 100644 src/sm130/pyupm_sm130.i create mode 100644 src/sm130/sm130.cxx create mode 100644 src/sm130/sm130.h diff --git a/src/sm130/CMakeLists.txt b/src/sm130/CMakeLists.txt new file mode 100644 index 0000000..1875951 --- /dev/null +++ b/src/sm130/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "sm130") +set (libdescription "upm rfid reader") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/sm130/jsupm_sm130.i b/src/sm130/jsupm_sm130.i new file mode 100644 index 0000000..6ee7806 --- /dev/null +++ b/src/sm130/jsupm_sm130.i @@ -0,0 +1,8 @@ +%module jsupm_sm130 +%include "../upm.i" + +%{ + #include "sm130.h" +%} + +%include "sm130.h" diff --git a/src/sm130/pyupm_sm130.i b/src/sm130/pyupm_sm130.i new file mode 100644 index 0000000..6e5d8f5 --- /dev/null +++ b/src/sm130/pyupm_sm130.i @@ -0,0 +1,9 @@ +%module pyupm_sm130 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "sm130.h" +%{ + #include "sm130.h" +%} diff --git a/src/sm130/sm130.cxx b/src/sm130/sm130.cxx new file mode 100644 index 0000000..786dd85 --- /dev/null +++ b/src/sm130/sm130.cxx @@ -0,0 +1,265 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "sm130.h" + +using namespace upm; + +struct SM130Exception : public std::exception { + std::string message; + SM130Exception (std::string msg) : message (msg) { } + ~SM130Exception () throw () { } + const char* what() const throw () { return message.c_str(); } +}; + +SM130::SM130 (int bus, int devAddr, int rst, int dready) { + mraa_result_t error = MRAA_SUCCESS; + + this->m_name = "SM130"; + + this->m_i2cAddr = devAddr; + this->m_bus = bus; + + this->m_i2Ctx = mraa_i2c_init(this->m_bus); + + mraa_result_t ret = mraa_i2c_address(this->m_i2Ctx, this->m_i2cAddr); + if (ret != MRAA_SUCCESS) { + throw SM130Exception ("Couldn't initilize I2C."); + } + + this->m_resetPinCtx = mraa_gpio_init (rst); + if (m_resetPinCtx == NULL) { + throw SM130Exception ("Couldn't initilize RESET pin."); + } + + this->m_dataReadyPinCtx = mraa_gpio_init (dready); + if (m_dataReadyPinCtx == NULL) { + throw SM130Exception ("Couldn't initilize DATA READY pin."); + } + + error = mraa_gpio_dir (this->m_resetPinCtx, MRAA_GPIO_OUT); + if (error != MRAA_SUCCESS) { + throw SM130Exception ("Couldn't set direction for RESET pin."); + } + + error = mraa_gpio_dir (this->m_dataReadyPinCtx, MRAA_GPIO_OUT); + if (error != MRAA_SUCCESS) { + throw SM130Exception ("Couldn't set direction for DATA READY pin."); + } +} + +SM130::~SM130 () { + mraa_result_t error = MRAA_SUCCESS; + + error = mraa_i2c_stop(this->m_i2Ctx); + if (error != MRAA_SUCCESS) { + mraa_result_print(error); + } + error = mraa_gpio_close (this->m_resetPinCtx); + if (error != MRAA_SUCCESS) { + mraa_result_print(error); + } + error = mraa_gpio_close (this->m_dataReadyPinCtx); + if (error != MRAA_SUCCESS) { + mraa_result_print(error); + } +} + +const char* +SM130::getFirmwareVersion () { + // Send VERSION command and retry a few times if no response + for (uint8_t n = 0; n < 10; n++) { + sendCommand (CMD_VERSION); + if (available() && getCommand() == CMD_VERSION) + // return versionString; + usleep(100 * 1000); + } + + return 0; +} + +uint8_t +SM130::available () { + // If in SEEK mode and using DREADY pin, check the status + if (this->m_LastCMD == CMD_SEEK_TAG) { + if (!mraa_gpio_read(this->m_dataReadyPinCtx)) { + return false; + } + } + + // Set the maximum length of the expected response packet + uint8_t len; + switch(this->m_LastCMD) { + case CMD_ANTENNA_POWER: + case CMD_AUTHENTICATE: + case CMD_DEC_VALUE: + case CMD_INC_VALUE: + case CMD_WRITE_KEY: + case CMD_HALT_TAG: + case CMD_SLEEP: + len = 4; + break; + case CMD_WRITE4: + case CMD_WRITE_VALUE: + case CMD_READ_VALUE: + len = 8; + case CMD_SEEK_TAG: + case CMD_SELECT_TAG: + len = 11; + break; + default: + len = SIZE_PACKET; + } + + // If valid data received, process the response packet + if (this->i2cRecievePacket(len) > 0) { + // Init response variables + this->m_TagType = this->m_TagLength = *this->m_TagString = 0; + + // If packet length is 2, the command failed. Set error code. + errorCode = this->getPacketLength () < 3 ? this->m_Data[2] : 0; + + // Process command response + switch (this->getCommand ()) { + case CMD_RESET: + case CMD_VERSION: + // RESET and VERSION commands produce the firmware version + len = std::min ((unsigned int) getPacketLength (), sizeof (this->m_Version)) - 1; + memcpy(this->m_Version, this->m_Data + 2, len); + this->m_Version[len] = 0; + break; + + case CMD_SEEK_TAG: + case CMD_SELECT_TAG: + // If no error, get tag number + if(errorCode == 0 && this->getPacketLength () >= 6) + { + this->m_TagLength = this->getPacketLength () - 2; + this->m_TagType = this->m_Data[2]; + memcpy(this->m_TagNumber, this->m_Data + 3, this->m_TagLength); + this->arrayToHex (this->m_TagString, this->m_TagNumber, this->m_TagLength); + } + break; + + case CMD_AUTHENTICATE: + break; + + case CMD_READ16: + break; + + case CMD_WRITE16: + case CMD_WRITE4: + break; + + case CMD_ANTENNA_POWER: + errorCode = 0; + antennaPower = this->m_Data[2]; + break; + + case CMD_SLEEP: + // If in SLEEP mode, no data is available + return false; + } + + // Data available + return true; + } + // No data available + return false; +} + +uint16_t +SM130::i2cRecievePacket (uint32_t len) { + int readByte = 0; + + mraa_i2c_address(this->m_i2Ctx, this->m_i2cAddr); + readByte = mraa_i2c_read(this->m_i2Ctx, this->m_Data, len); + + if (readByte > 0) { + // verify checksum if length > 0 and <= SIZE_PAYLOAD + if (this->m_Data[0] > 0 && this->m_Data[0] <= SIZE_PAYLOAD) + { + uint8_t i, sum; + for (i = 0, sum = 0; i <= this->m_Data[0]; i++) { + sum += this->m_Data[i]; + } + // return with length of response, or -1 if invalid checksum + return sum == this->m_Data[i] ? this->m_Data[0] : -1; + } + } + + return readByte; +} + +void +SM130::arrayToHex (char *s, uint8_t array[], uint8_t len) { + for (uint8_t i = 0; i < len; i++) { + *s++ = toHex(array[i] >> 4); + *s++ = toHex(array[i]); + } + + *s = 0; +} + +char +SM130::toHex (uint8_t b) { + b = b & 0x0f; + + return b < 10 ? b + '0' : b + 'A' - 10; +} + +mraa_result_t +SM130::i2cTransmitPacket (uint32_t len) { + mraa_result_t error = MRAA_SUCCESS; + uint8_t sum = 0; + + // Save last command + this->m_LastCMD = this->m_Data[0]; + + // calculate the sum check + for (int i = 0; i < len; i++) { + sum += this->m_Data[i]; + } + + // placing the sum check to the last byte of the packet + this->m_Data[len + 1] = sum; + + error = mraa_i2c_address (this->m_i2Ctx, this->m_i2cAddr); + error = mraa_i2c_write (this->m_i2Ctx, this->m_Data, len + 1); + + return error; +} + +mraa_result_t +SM130::sendCommand (uint8_t cmd) { + this->m_Data[0] = 1; + this->m_Data[1] = cmd; + this->i2cTransmitPacket(2); +} + diff --git a/src/sm130/sm130.h b/src/sm130/sm130.h new file mode 100644 index 0000000..0d773c1 --- /dev/null +++ b/src/sm130/sm130.h @@ -0,0 +1,148 @@ +/* + * Author: Yevgeniy Kiveisha + * Copyright (c) 2014 Intel Corporation. + * + * Based on SM130 library developed by Marc Boon + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#define SIZE_PAYLOAD 18 // maximum payload size of I2C packet +#define SIZE_PACKET (SIZE_PAYLOAD + 2) // total I2C packet size, including length uint8_t and checksum + +#define HIGH 1 +#define LOW 0 + +namespace upm { + +/** + * @brief C++ API for SM130 RFID reader module + * + * This file defines the SM130 C++ interface for libsm130 + * + */ +class SM130 { + + uint8_t m_Data[SIZE_PACKET]; //!< packet data + char m_Version[8]; //!< version string + uint8_t m_TagNumber[7]; //!< tag number as uint8_t array + uint8_t m_TagLength; //!< length of tag number in uint8_ts (4 or 7) + char m_TagString[15]; //!< tag number as hex string + uint8_t m_TagType; //!< type of tag + char errorCode; //!< error code from some commands + uint8_t antennaPower; //!< antenna power level + uint8_t m_LastCMD; //!< last sent command + + public: + static const uint8_t MIFARE_ULTRALIGHT = 1; + static const uint8_t MIFARE_1K = 2; + static const uint8_t MIFARE_4K = 3; + + static const uint8_t CMD_RESET = 0x80; + static const uint8_t CMD_VERSION = 0x81; + static const uint8_t CMD_SEEK_TAG = 0x82; + static const uint8_t CMD_SELECT_TAG = 0x83; + static const uint8_t CMD_AUTHENTICATE = 0x85; + static const uint8_t CMD_READ16 = 0x86; + static const uint8_t CMD_READ_VALUE = 0x87; + static const uint8_t CMD_WRITE16 = 0x89; + static const uint8_t CMD_WRITE_VALUE = 0x8a; + static const uint8_t CMD_WRITE4 = 0x8b; + static const uint8_t CMD_WRITE_KEY = 0x8c; + static const uint8_t CMD_INC_VALUE = 0x8d; + static const uint8_t CMD_DEC_VALUE = 0x8e; + static const uint8_t CMD_ANTENNA_POWER = 0x90; + static const uint8_t CMD_READ_PORT = 0x91; + static const uint8_t CMD_WRITE_PORT = 0x92; + static const uint8_t CMD_HALT_TAG = 0x93; + static const uint8_t CMD_SET_BAUD = 0x94; + static const uint8_t CMD_SLEEP = 0x96; + + /** + * Instanciates a SM130 object + * + * @param di data pin + * @param dcki clock pin + */ + SM130 (int bus, int devAddr, int rst, int dready); + + /** + * SM130 object destructor + */ + ~SM130 (); + + /** + * Get the firmware version string. + */ + const char* getFirmwareVersion (); + + /** + * Checks for availability of a valid response packet. + * + * This function should always be called and return true prior to using results + * of a command. + * + * @returns true if a valid response packet is available + */ + uint8_t available (); + + /** + * Returns the packet length, excluding checksum + */ + uint8_t getPacketLength () { return this->m_Data[0]; }; + + /** + * Returns the last executed command + */ + uint8_t getCommand () { return this->m_Data[1]; }; + + /** + * Return name of the component + */ + std::string name() + { + return m_name; + } + private: + std::string m_name; + mraa_gpio_context m_resetPinCtx; + mraa_gpio_context m_dataReadyPinCtx; + + int m_i2cAddr; + int m_bus; + mraa_i2c_context m_i2Ctx; + + void arrayToHex (char *s, uint8_t array[], uint8_t len); + char toHex (uint8_t b); + + uint16_t i2cRecievePacket (uint32_t len); + mraa_result_t i2cTransmitPacket (uint32_t len); + mraa_result_t sendCommand (uint8_t cmd); +}; + +} -- 2.7.4