Home | History | Annotate | Download | only in hmtrp
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      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:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     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.
     23  */
     24 
     25 #include <iostream>
     26 #include <string>
     27 #include <stdexcept>
     28 
     29 #include "hmtrp.h"
     30 
     31 using namespace upm;
     32 using namespace std;
     33 
     34 static const int defaultDelay = 100;     // max wait time for read
     35 
     36 // protocol start code
     37 const uint8_t HMTRP_START1 = 0xaa;
     38 const uint8_t HMTRP_START2 = 0xfa;
     39 
     40 HMTRP::HMTRP(int uart)
     41 {
     42   m_ttyFd = -1;
     43 
     44   if ( !(m_uart = mraa_uart_init(uart)) )
     45     {
     46       throw std::invalid_argument(std::string(__FUNCTION__) +
     47                                   ": mraa_uart_init() failed");
     48       return;
     49     }
     50 
     51   // This requires a recent MRAA (1/2015)
     52   const char *devPath = mraa_uart_get_dev_path(m_uart);
     53 
     54   if (!devPath)
     55     {
     56       throw std::runtime_error(std::string(__FUNCTION__) +
     57                                ": mraa_uart_get_dev_path() failed");
     58       return;
     59     }
     60 
     61   // now open the tty
     62   if ( (m_ttyFd = open(devPath, O_RDWR)) == -1)
     63     {
     64       throw std::runtime_error(std::string(__FUNCTION__) +
     65                                ": open of " +
     66                                string(devPath) + " failed: " +
     67                                string(strerror(errno)));
     68       return;
     69     }
     70 }
     71 
     72 HMTRP::~HMTRP()
     73 {
     74   if (m_ttyFd != -1)
     75     close(m_ttyFd);
     76 }
     77 
     78 bool HMTRP::dataAvailable(unsigned int millis)
     79 {
     80   if (m_ttyFd == -1)
     81     return false;
     82 
     83   struct timeval timeout;
     84 
     85   timeout.tv_sec = 0;
     86   timeout.tv_usec = millis * 1000;
     87 
     88   int nfds;
     89   fd_set readfds;
     90 
     91   FD_ZERO(&readfds);
     92 
     93   FD_SET(m_ttyFd, &readfds);
     94 
     95   if (select(m_ttyFd + 1, &readfds, NULL, NULL, &timeout) > 0)
     96     return true;                // data is ready
     97   else
     98     return false;
     99 }
    100 
    101 int HMTRP::readData(char *buffer, int len, int millis)
    102 {
    103   if (m_ttyFd == -1)
    104     return(-1);
    105 
    106   // if specified, wait to see if input shows up, otherwise block
    107   if (millis >= 0)
    108     {
    109       if (!dataAvailable(millis))
    110         return 0;               // timed out
    111     }
    112 
    113   int rv = read(m_ttyFd, buffer, len);
    114 
    115   if (rv < 0)
    116     {
    117       throw std::runtime_error(std::string(__FUNCTION__) +
    118                                ": read() failed: " +
    119                                string(strerror(errno)));
    120       return rv;
    121     }
    122 
    123   return rv;
    124 }
    125 
    126 int HMTRP::writeData(char *buffer, int len)
    127 {
    128   if (m_ttyFd == -1)
    129     return(-1);
    130 
    131   int rv = write(m_ttyFd, buffer, len);
    132 
    133   if (rv < 0)
    134     {
    135       throw std::runtime_error(std::string(__FUNCTION__) +
    136                                ": write() failed: " +
    137                                string(strerror(errno)));
    138       return rv;
    139     }
    140 
    141   tcdrain(m_ttyFd);
    142 
    143   return rv;
    144 }
    145 
    146 bool HMTRP::setupTty(speed_t baud)
    147 {
    148   if (m_ttyFd == -1)
    149     return(false);
    150 
    151   struct termios termio;
    152 
    153   // get current modes
    154   tcgetattr(m_ttyFd, &termio);
    155 
    156   // setup for a 'raw' mode.  81N, no echo or special character
    157   // handling, such as flow control.
    158   cfmakeraw(&termio);
    159 
    160   // set our baud rates
    161   cfsetispeed(&termio, baud);
    162   cfsetospeed(&termio, baud);
    163 
    164   // make it so
    165   if (tcsetattr(m_ttyFd, TCSAFLUSH, &termio) < 0)
    166     {
    167       throw std::runtime_error(std::string(__FUNCTION__) +
    168                                ": tcsetattr() failed: " +
    169                                string(strerror(errno)));
    170       return false;
    171     }
    172 
    173   return true;
    174 }
    175 
    176 bool HMTRP::checkOK()
    177 {
    178   char buf[4];
    179 
    180   int rv = readData(buf, 4, defaultDelay);
    181 
    182   if (rv != 4)
    183     {
    184       cerr << __FUNCTION__ << ": failed to receive OK response, rv = "
    185            << rv << ", expected 4" << endl;
    186       return false;
    187     }
    188 
    189   // looking for "OK\r\n"
    190   if (buf[0] == 'O' && buf[1] == 'K' &&
    191       buf[2] == '\r' && buf[3] == '\n')
    192     return true;
    193   else
    194     return false;
    195 }
    196 
    197 bool HMTRP::reset()
    198 {
    199   char pkt[3];
    200 
    201   pkt[0] = HMTRP_START1;
    202   pkt[1] = HMTRP_START2;
    203   pkt[2] = RESET;
    204 
    205   writeData(pkt, 3);
    206 
    207   return checkOK();
    208 }
    209 
    210 bool HMTRP::getConfig(uint32_t *freq, uint32_t *dataRate,
    211                       uint16_t *rxBandwidth, uint8_t *modulation,
    212                       uint8_t *txPower, uint32_t *uartBaud)
    213 {
    214   char pkt[3];
    215   pkt[0] = HMTRP_START1;
    216   pkt[1] = HMTRP_START2;
    217   pkt[2] = GET_CONFIG;
    218 
    219   writeData(pkt, 3);
    220   usleep(100000);
    221 
    222   // now read back a 16 byte response
    223   char buf[16];
    224   int rv = readData(buf, 16, defaultDelay);
    225 
    226   if (rv != 16)
    227     {
    228       cerr << __FUNCTION__ << ": failed to receive correct response: rv = "
    229            << rv << ", expected 16" << endl;
    230       return false;
    231     }
    232 
    233   // now decode
    234   if (freq)
    235     {
    236       *freq = ( ((buf[0] & 0xff) << 24) |
    237                 ((buf[1] & 0xff) << 16) |
    238                 ((buf[2] & 0xff) << 8)  |
    239                  (buf[3] & 0xff) );
    240     }
    241 
    242   if (dataRate)
    243     {
    244       *dataRate = ( ((buf[4] & 0xff) << 24) |
    245                     ((buf[5] & 0xff) << 16) |
    246                     ((buf[6] & 0xff) << 8)  |
    247                      (buf[7] & 0xff) );
    248     }
    249 
    250   if (rxBandwidth)
    251     {
    252       *rxBandwidth = ( ((buf[8] & 0xff) << 8) |
    253                         (buf[9] & 0xff) );
    254     }
    255 
    256   if (modulation)
    257     {
    258       *modulation = buf[10] & 0xff;
    259     }
    260 
    261   if (txPower)
    262     {
    263       *txPower = buf[11] & 0xff;
    264     }
    265 
    266   if (uartBaud)
    267     {
    268       *uartBaud = ( ((buf[12] & 0xff) << 24) |
    269                     ((buf[13] & 0xff) << 16) |
    270                     ((buf[14] & 0xff) << 8)  |
    271                      (buf[15] & 0xff) );
    272     }
    273 
    274   return true;
    275 }
    276 
    277 bool HMTRP::setFrequency(uint32_t freq)
    278 {
    279   char pkt[7];
    280 
    281   pkt[0] = HMTRP_START1;
    282   pkt[1] = HMTRP_START2;
    283   pkt[2] = SET_FREQUENCY;
    284 
    285   pkt[3] = ( ((freq & 0xff000000) >> 24) & 0xff );
    286   pkt[4] = ( ((freq & 0x00ff0000) >> 16) & 0xff );
    287   pkt[5] = ( ((freq & 0x0000ff00) >> 8)  & 0xff );
    288   pkt[6] = ( (freq & 0x000000ff) & 0xff );
    289 
    290   writeData(pkt, 7);
    291 
    292   return checkOK();
    293 }
    294 
    295 bool HMTRP::setRFDataRate(uint32_t rate)
    296 {
    297   //  Valid values are between 1200-115200
    298 
    299   if (rate < 1200 || rate > 115200)
    300     {
    301       throw std::out_of_range(std::string(__FUNCTION__) +
    302                               ": Valid rate values are between 1200-115200");
    303       return false;
    304     }
    305 
    306   char pkt[7];
    307 
    308   pkt[0] = HMTRP_START1;
    309   pkt[1] = HMTRP_START2;
    310   pkt[2] = SET_RF_DATARATE;
    311 
    312   pkt[3] = ( ((rate & 0xff000000) >> 24) & 0xff );
    313   pkt[4] = ( ((rate & 0x00ff0000) >> 16) & 0xff );
    314   pkt[5] = ( ((rate & 0x0000ff00) >> 8)  & 0xff );
    315   pkt[6] = ( (rate & 0x000000ff) & 0xff );
    316 
    317   writeData(pkt, 7);
    318 
    319   return checkOK();
    320 }
    321 
    322 bool HMTRP::setRXBandwidth(uint16_t rxBand)
    323 {
    324   //  Valid values are between 30-620 (in Khz)
    325 
    326   if (rxBand < 30 || rxBand > 620)
    327     {
    328       throw std::out_of_range(std::string(__FUNCTION__) +
    329                               ": Valid rxBand values are between 30-620");
    330       return false;
    331     }
    332 
    333   char pkt[5];
    334 
    335   pkt[0] = HMTRP_START1;
    336   pkt[1] = HMTRP_START2;
    337   pkt[2] = SET_RX_BW;
    338 
    339   pkt[3] = ( ((rxBand & 0xff00) >> 8) & 0xff );
    340   pkt[4] = ( rxBand & 0xff );
    341 
    342   writeData(pkt, 5);
    343 
    344   return checkOK();
    345 }
    346 
    347 bool HMTRP::setFrequencyModulation(uint8_t modulation)
    348 {
    349   //  Valid values are between 10-160 (in Khz)
    350 
    351   if (modulation < 10 || modulation > 160)
    352     {
    353       throw std::out_of_range(std::string(__FUNCTION__) +
    354                               ": Valid modulation values are between 10-160");
    355       return false;
    356     }
    357 
    358   char pkt[4];
    359 
    360   pkt[0] = HMTRP_START1;
    361   pkt[1] = HMTRP_START2;
    362   pkt[2] = SET_FREQ_MODULATION;
    363 
    364   pkt[3] = modulation;
    365 
    366   writeData(pkt, 4);
    367 
    368   return checkOK();
    369 }
    370 
    371 bool HMTRP::setTransmitPower(uint8_t power)
    372 {
    373   //  Valid values are between 0-7
    374 
    375   if (power > 7)
    376     {
    377       throw std::out_of_range(std::string(__FUNCTION__) +
    378                               ": Valid power values are between 0-7");
    379       return false;
    380     }
    381 
    382   char pkt[4];
    383 
    384   pkt[0] = HMTRP_START1;
    385   pkt[1] = HMTRP_START2;
    386   pkt[2] = SET_TX_POWER;
    387 
    388   pkt[3] = power;
    389 
    390   writeData(pkt, 4);
    391 
    392   return checkOK();
    393 }
    394 
    395 bool HMTRP::setUARTSpeed(uint32_t speed)
    396 {
    397   //  Valid values are between 1200-115200
    398 
    399   if (speed < 1200 || speed > 115200)
    400     {
    401       throw std::out_of_range(std::string(__FUNCTION__) +
    402                               ": Valid speed values are between 1200-115200");
    403       return false;
    404     }
    405 
    406   char pkt[7];
    407 
    408   pkt[0] = HMTRP_START1;
    409   pkt[1] = HMTRP_START2;
    410   pkt[2] = SET_UART_SPEED;
    411 
    412   pkt[3] = ( ((speed & 0xff000000) >> 24) & 0xff );
    413   pkt[4] = ( ((speed & 0x00ff0000) >> 16) & 0xff );
    414   pkt[5] = ( ((speed & 0x0000ff00) >> 8)  & 0xff );
    415   pkt[6] = ( (speed & 0x000000ff) & 0xff );
    416 
    417   writeData(pkt, 7);
    418 
    419   return checkOK();
    420 }
    421 
    422 
    423 bool HMTRP::getRFSignalStrength(uint8_t *strength)
    424 {
    425   if (!strength)
    426     return false;
    427 
    428   *strength = 0;
    429 
    430   char pkt[3];
    431   pkt[0] = HMTRP_START1;
    432   pkt[1] = HMTRP_START2;
    433   pkt[2] = GET_RF_SIGNAL_STR;
    434 
    435   writeData(pkt, 3);
    436   usleep(100000);
    437 
    438   // now read back a 1 byte response
    439   char buf;
    440   int rv = readData(&buf, 1, defaultDelay);
    441 
    442   if (rv != 1)
    443     {
    444       cerr << __FUNCTION__ << ": failed to receive correct response: rv = "
    445            << rv << ", expected 1" << endl;
    446       return false;
    447     }
    448 
    449   // now decode
    450   *strength = (uint8_t)buf;
    451 
    452   return true;
    453 }
    454 
    455 bool HMTRP::getModSignalStrength(uint8_t *strength)
    456 {
    457   if (!strength)
    458     return false;
    459 
    460   *strength = 0;
    461 
    462   char pkt[3];
    463   pkt[0] = HMTRP_START1;
    464   pkt[1] = HMTRP_START2;
    465   pkt[2] = GET_MOD_SIGNAL_STR;
    466 
    467   writeData(pkt, 3);
    468   usleep(100000);
    469 
    470   // now read back a 1 byte response
    471   char buf;
    472   int rv = readData(&buf, 1, defaultDelay);
    473 
    474   if (rv != 1)
    475     {
    476       cerr << __FUNCTION__ << ": failed to receive correct response: rv = "
    477            << rv << ", expected 1" << endl;
    478       return false;
    479     }
    480 
    481   // now decode
    482   *strength = (uint8_t)buf;
    483 
    484   return true;
    485 }
    486 
    487