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