diff --git a/examples/c++/zfm20.cxx b/examples/c++/zfm20.cxx index 7a4a2e3f..db9bdba2 100644 --- a/examples/c++/zfm20.cxx +++ b/examples/c++/zfm20.cxx @@ -38,7 +38,7 @@ main(int argc, char** argv) upm::ZFM20 fp(0); // make sure port is initialized properly. 57600 baud is the default. - if (!fp.setupTty(B57600)) { + if (!fp.setupTty(57600)) { cerr << "Failed to setup tty port parameters" << endl; return 1; } @@ -83,7 +83,7 @@ main(int argc, char** argv) // we search for a print matching slot 1, where we shored our last // converted fingerprint - if ((rv = fp.search(1, &id, &score)) != ZFM20::ERR_OK) { + if ((rv = fp.search(1, id, score)) != ZFM20::ERR_OK) { if (rv == ZFM20::ERR_FP_NOTFOUND) { cout << "Finger Print not found" << endl; return 0; diff --git a/src/zfm20/CMakeLists.txt b/src/zfm20/CMakeLists.txt index 3fa95e8a..bc49e1af 100644 --- a/src/zfm20/CMakeLists.txt +++ b/src/zfm20/CMakeLists.txt @@ -2,4 +2,4 @@ set (libname "zfm20") set (libdescription "Fingerprint Sensor Module") set (module_src ${libname}.cxx) set (module_hpp ${libname}.hpp) -upm_module_init(mraa) +upm_module_init(mraa utilities-c) diff --git a/src/zfm20/common.i b/src/zfm20/common.i new file mode 100644 index 00000000..a9041311 --- /dev/null +++ b/src/zfm20/common.i @@ -0,0 +1,11 @@ +%include "../upm.i" + +/* Make it easy to use the methods which take a uint& id and score */ +%include "typemaps.i" +%apply uint16_t &OUTPUT {uint16_t &id}; +%apply uint16_t &OUTPUT {uint16_t &score}; + +%{ + #include "zfm20.hpp" +%} +%include "zfm20.hpp" diff --git a/src/zfm20/javaupm_zfm20.i b/src/zfm20/javaupm_zfm20.i index cbecc9e2..99153c73 100644 --- a/src/zfm20/javaupm_zfm20.i +++ b/src/zfm20/javaupm_zfm20.i @@ -1,20 +1,10 @@ %module javaupm_zfm20 -%include "../upm.i" %include "stdint.i" %include "typemaps.i" %include "arrays_java.i"; %include "../java_buffer.i"; -%apply uint16_t *OUTPUT { uint16_t *id, uint16_t *score }; - -%{ - #include "zfm20.hpp" - speed_t int_B57600 = B57600; -%} - - -%include "zfm20.hpp" -speed_t int_B57600 = B57600; +%include "common.i" %pragma(java) jniclasscode=%{ static { @@ -25,4 +15,4 @@ speed_t int_B57600 = B57600; System.exit(1); } } -%} \ No newline at end of file +%} diff --git a/src/zfm20/jsupm_zfm20.i b/src/zfm20/jsupm_zfm20.i index 0dcb44bb..5def2e28 100644 --- a/src/zfm20/jsupm_zfm20.i +++ b/src/zfm20/jsupm_zfm20.i @@ -1,5 +1,4 @@ %module jsupm_zfm20 -%include "../upm.i" %include "../carrays_uint8_t.i" %include "../carrays_uint16_t.i" %include "../carrays_uint32_t.i" @@ -7,10 +6,5 @@ /* Send "int *" to JavaScript as intp */ %pointer_functions(int, intp); -%{ - #include "zfm20.hpp" - speed_t int_B57600 = B57600; -%} -%include "zfm20.hpp" -speed_t int_B57600 = B57600; +%include "common.i" diff --git a/src/zfm20/pyupm_zfm20.i b/src/zfm20/pyupm_zfm20.i index 28bd5446..e16cb23c 100644 --- a/src/zfm20/pyupm_zfm20.i +++ b/src/zfm20/pyupm_zfm20.i @@ -1,17 +1,9 @@ // Include doxygen-generated documentation %include "pyupm_doxy2swig.i" %module pyupm_zfm20 -%include "../upm.i" %include "../carrays_uint8_t.i" %include "../carrays_uint16_t.i" %include "../carrays_uint32_t.i" %include "cpointer.i" -/* Send "int *" to python as intp */ -%pointer_functions(int, intp); -%{ - #include "zfm20.hpp" - speed_t int_B57600 = B57600; -%} -%include "zfm20.hpp" -speed_t int_B57600 = B57600; +%include "common.i" diff --git a/src/zfm20/zfm20.cxx b/src/zfm20/zfm20.cxx index a652e14a..021cef04 100644 --- a/src/zfm20/zfm20.cxx +++ b/src/zfm20/zfm20.cxx @@ -33,154 +33,66 @@ using namespace std; static const int defaultDelay = 100; // max wait time for read -ZFM20::ZFM20(int uart) +ZFM20::ZFM20(int uart, int baud): m_uart(uart) { - m_ttyFd = -1; - - if ( !(m_uart = mraa_uart_init(uart)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_uart_init() failed"); - return; - } - - // This requires a recent MRAA (1/2015) - const char *devPath = mraa_uart_get_dev_path(m_uart); - - if (!devPath) - { - throw std::runtime_error(std::string(__FUNCTION__) + - ": mraa_uart_get_dev_path() failed"); - return; - } - - // now open the tty - if ( (m_ttyFd = open(devPath, O_RDWR)) == -1) - { - throw std::runtime_error(std::string(__FUNCTION__) + - ": open of " + - string(devPath) + " failed: " + - string(strerror(errno))); - return; - } - // Set the default password and address setPassword(ZFM20_DEFAULT_PASSWORD); setAddress(ZFM20_DEFAULT_ADDRESS); initClock(); + + if (!setupTty(baud)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": failed to set baud rate to " + std::to_string(baud)); } -ZFM20::~ZFM20() + +ZFM20::ZFM20(std::string uart_raw, int baud) : m_uart(uart_raw) { - if (m_ttyFd != -1) - close(m_ttyFd); + // Set the default password and address + setPassword(ZFM20_DEFAULT_PASSWORD); + setAddress(ZFM20_DEFAULT_ADDRESS); - mraa_deinit(); -} + initClock(); -bool ZFM20::dataAvailable(unsigned int millis) -{ - if (m_ttyFd == -1) - return false; - - struct timeval timeout; - - // no waiting - timeout.tv_sec = 0; - timeout.tv_usec = millis * 1000; - - fd_set readfds; - - FD_ZERO(&readfds); - - FD_SET(m_ttyFd, &readfds); - - if (select(m_ttyFd + 1, &readfds, NULL, NULL, &timeout) > 0) - return true; // data is ready - else - return false; + if (!setupTty(baud)) + throw std::runtime_error(std::string(__FUNCTION__) + + ": failed to set baud rate to " + std::to_string(baud)); } int ZFM20::readData(char *buffer, int len) { - if (m_ttyFd == -1) - return(-1); - - if (!dataAvailable(defaultDelay)) + if (!m_uart.dataAvailable(defaultDelay)) return 0; // timed out - int rv = read(m_ttyFd, buffer, len); + int rv = m_uart.read(buffer, len); if (rv < 0) - { - throw std::runtime_error(std::string(__FUNCTION__) + - ": read() failed: " + - string(strerror(errno))); - return rv; - } + throw std::runtime_error(std::string(__FUNCTION__) + + ": Uart::read() failed: " + string(strerror(errno))); return rv; } int ZFM20::writeData(char *buffer, int len) { - if (m_ttyFd == -1) - return(-1); - - // first, flush any pending but unread input - tcflush(m_ttyFd, TCIFLUSH); - - int rv = write(m_ttyFd, buffer, len); + int rv = m_uart.write(buffer, len); if (rv < 0) - { throw std::runtime_error(std::string(__FUNCTION__) + - ": write() failed: " + + ": Uart::write() failed: " + string(strerror(errno))); - return rv; - } if (rv == 0) - { throw std::runtime_error(std::string(__FUNCTION__) + - ": write() failed, no bytes written"); - return rv; - } - - tcdrain(m_ttyFd); + ": Uart::write() failed, no bytes written"); return rv; } -bool ZFM20::setupTty(speed_t baud) +bool ZFM20::setupTty(uint32_t baud) { - if (m_ttyFd == -1) - return(false); - - struct termios termio; - - // get current modes - tcgetattr(m_ttyFd, &termio); - - // setup for a 'raw' mode. 81N, no echo or special character - // handling, such as flow control. - cfmakeraw(&termio); - - // set our baud rates - cfsetispeed(&termio, baud); - cfsetospeed(&termio, baud); - - // make it so - if (tcsetattr(m_ttyFd, TCSAFLUSH, &termio) < 0) - { - throw std::runtime_error(std::string(__FUNCTION__) + - ": tcsetattr() failed: " + - string(strerror(errno))); - return false; - } - - return true; + return m_uart.setBaudRate(baud) == mraa::SUCCESS; } int ZFM20::writeCmdPacket(uint8_t *pkt, int len) @@ -219,55 +131,26 @@ int ZFM20::writeCmdPacket(uint8_t *pkt, int len) void ZFM20::initClock() { - gettimeofday(&m_startTime, NULL); + upm_clock_init(&m_clock); } uint32_t ZFM20::getMillis() { - struct timeval elapsed, now; - uint32_t elapse; - - // get current time - gettimeofday(&now, NULL); - - // compute the delta since m_startTime - if( (elapsed.tv_usec = now.tv_usec - m_startTime.tv_usec) < 0 ) - { - elapsed.tv_usec += 1000000; - elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec - 1; - } - else - { - elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec; - } - - elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000)); - - // never return 0 - if (elapse == 0) - elapse = 1; - - return elapse; + return upm_elapsed_ms(&m_clock); } bool ZFM20::verifyPacket(uint8_t *pkt, int len) { // verify packet header if (pkt[0] != ZFM20_START1 || pkt[1] != ZFM20_START2) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Invalid packet header"); - return false; - } // check the ack byte if (pkt[6] != PKT_ACK) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Invalid ACK code"); - return false; - } - + return true; } @@ -284,25 +167,19 @@ bool ZFM20::getResponse(uint8_t *pkt, int len) while (idx < len) { // wait for some data - if (!dataAvailable(100)) + if (!m_uart.dataAvailable(100)) { timer += getMillis(); if (timer > ZFM20_TIMEOUT) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Timed out waiting for packet"); - return false; - } continue; } if ((rv = readData(buf, ZFM20_MAX_PKT_LEN)) == 0) - { throw std::runtime_error(std::string(__FUNCTION__) + ": readData() failed, no data returned"); - return false; - } // copy it into the user supplied buffer for (int i=0; i((m_password >> 24) & 0xff), static_cast((m_password >> 16) & 0xff), static_cast((m_password >> 8) & 0xff), @@ -353,19 +230,15 @@ int ZFM20::getNumTemplates() // check confirmation code if (rPkt[9] != 0x00) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Invalid confirmation code"); - return 0; - } - return ((rPkt[10] << 8) | rPkt[11]); } bool ZFM20::setNewPassword(uint32_t pwd) { const int pktLen = 5; - uint8_t pkt[pktLen] = {CMD_SET_PASSWORD, + uint8_t pkt[pktLen] = {CMD_SET_PASSWORD, static_cast((pwd >> 24) & 0xff), static_cast((pwd >> 16) & 0xff), static_cast((pwd >> 8) & 0xff), @@ -381,11 +254,8 @@ bool ZFM20::setNewPassword(uint32_t pwd) // check confirmation code if (rPkt[9] != 0x00) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Invalid confirmation code"); - return false; - } m_password = pwd; @@ -395,7 +265,7 @@ bool ZFM20::setNewPassword(uint32_t pwd) bool ZFM20::setNewAddress(uint32_t addr) { const int pktLen = 5; - uint8_t pkt[pktLen] = {CMD_SET_ADDRESS, + uint8_t pkt[pktLen] = {CMD_SET_ADDRESS, static_cast((addr >> 24) & 0xff), static_cast((addr >> 16) & 0xff), static_cast((addr >> 8) & 0xff), @@ -411,11 +281,8 @@ bool ZFM20::setNewAddress(uint32_t addr) // check confirmation code if (rPkt[9] != 0x00) - { throw std::runtime_error(std::string(__FUNCTION__) + ": Invalid confirmation code"); - return false; - } m_address = addr; @@ -441,11 +308,8 @@ uint8_t ZFM20::generateImage() uint8_t ZFM20::image2Tz(int slot) { if (slot != 1 && slot != 2) - { throw std::out_of_range(std::string(__FUNCTION__) + ": slot must be 1 or 2"); - return ERR_INTERNAL_ERR; - } const int pktLen = 2; uint8_t pkt[pktLen] = {CMD_IMG2TZ, @@ -481,11 +345,8 @@ uint8_t ZFM20::createModel() uint8_t ZFM20::storeModel(int slot, uint16_t id) { if (slot != 1 && slot != 2) - { throw std::out_of_range(std::string(__FUNCTION__) + ": slot must be 1 or 2"); - return ERR_INTERNAL_ERR; - } const int pktLen = 4; uint8_t pkt[pktLen] = {CMD_STORE, @@ -540,17 +401,14 @@ uint8_t ZFM20::deleteDB() return rPkt[9]; } -uint8_t ZFM20::search(int slot, uint16_t *id, uint16_t *score) +uint8_t ZFM20::search(int slot, uint16_t &id, uint16_t &score) { - *id = 0; - *score = 0; + id = 0; + score = 0; if (slot != 1 && slot != 2) - { throw std::out_of_range(std::string(__FUNCTION__) + ": slot must be 1 or 2"); - return ERR_INTERNAL_ERR; - } // search from page 0x0000 to page 0x00a3 const int pktLen = 6; @@ -572,16 +430,16 @@ uint8_t ZFM20::search(int slot, uint16_t *id, uint16_t *score) // if it was found, extract the location and the score if (rPkt[9] == ERR_OK) { - *id = ((rPkt[10] << 8) & 0xff) | (rPkt[11] & 0xff); - *score = ((rPkt[12] << 8) & 0xff) | (rPkt[13] & 0xff); + id = ((rPkt[10] << 8) & 0xff) | (rPkt[11] & 0xff); + score = ((rPkt[12] << 8) & 0xff) | (rPkt[13] & 0xff); } return rPkt[9]; } -uint8_t ZFM20::match(uint16_t *score) +uint8_t ZFM20::match(uint16_t &score) { - *score = 0; + score = 0; const int pktLen = 1; uint8_t pkt[pktLen] = {CMD_MATCH}; @@ -594,9 +452,7 @@ uint8_t ZFM20::match(uint16_t *score) getResponse(rPkt, rPktLen); - *score = ((rPkt[10] << 8) & 0xff) | (rPkt[11] & 0xff); + score = ((rPkt[10] << 8) & 0xff) | (rPkt[11] & 0xff); return rPkt[9]; } - - diff --git a/src/zfm20/zfm20.hpp b/src/zfm20/zfm20.hpp index 25b9b2fa..67c3e1db 100644 --- a/src/zfm20/zfm20.hpp +++ b/src/zfm20/zfm20.hpp @@ -35,13 +35,12 @@ #include #include #include -#include -#include #include #include #include -#include +#include "mraa.hpp" +#include "upm_utilities.h" #define ZFM20_DEFAULT_UART 0 @@ -153,22 +152,23 @@ namespace upm { /** * ZFM20 constructor * - * @param uart Default UART to use (0 or 1) + * @param uart Target mraa UART index to use (0 or 1) + * @param baud Desired baud rate */ - ZFM20(int uart); + ZFM20(int uart, int baud = 57600); + + /** + * ZFM20 constructor + * + * @param uart File path (/dev/ttyXXX to uart + * @param baud Desired baud rate + */ + ZFM20(std::string uart_raw, int baud = 57600); /** * ZFM20 destructor */ - ~ZFM20(); - - /** - * Checks to see if there is data available for reading - * - * @param millis Number of milliseconds to wait; 0 means no waiting - * @return true if there is data available for reading - */ - bool dataAvailable(unsigned int millis); + virtual ~ZFM20() {} /** * Reads any available data in a user-supplied buffer. Note: the @@ -193,12 +193,12 @@ namespace upm { /** * Sets up proper tty I/O modes and the baud rate. For this device, - * the default baud rate is 57,600 (B57600). + * the default baud rate is 57,600. * * @param baud Desired baud rate. * @return True if successful */ - bool setupTty(speed_t baud=B57600); + bool setupTty(uint32_t baud = 57600); /** * Composes and writes a command packet @@ -353,7 +353,7 @@ namespace upm { * @param score Score if found, 0 otherwise * @return One of the ZFM20_ERRORS_T values */ - uint8_t search(int slot, uint16_t *id, uint16_t *score); + uint8_t search(int slot, uint16_t &id, uint16_t &score); /** * Compares the features in characteristics buffers 1 and 2 and @@ -362,19 +362,12 @@ namespace upm { * @param score Score * @return One of the ZFM20_ERRORS_T values */ - uint8_t match(uint16_t *score); - - - protected: - int ttyFd() { return m_ttyFd; }; + uint8_t match(uint16_t &score); private: - mraa_uart_context m_uart; - int m_ttyFd; + mraa::Uart m_uart; uint32_t m_password; uint32_t m_address; - struct timeval m_startTime; + upm_clock_t m_clock; }; } - -