Elmo Terminal provides functionality to test Lora radio and access SX1272 chip registers delivered with Elmo board. Also contains example ping-pong application.
Dependencies: SX1272lib mbed-src
RadioContex.cpp@2:8d8295a51f68, 2015-10-01 (annotated)
- Committer:
- WGorniak
- Date:
- Thu Oct 01 09:40:30 2015 +0200
- Revision:
- 2:8d8295a51f68
- Child:
- 4:2767f13b0a75
added terminal app
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WGorniak | 2:8d8295a51f68 | 1 | #include "assert.h" |
WGorniak | 2:8d8295a51f68 | 2 | |
WGorniak | 2:8d8295a51f68 | 3 | #include "RadioContex.h" |
WGorniak | 2:8d8295a51f68 | 4 | #include "Settings.h" |
WGorniak | 2:8d8295a51f68 | 5 | #include "dbg.h" |
WGorniak | 2:8d8295a51f68 | 6 | #include <sstream> |
WGorniak | 2:8d8295a51f68 | 7 | |
WGorniak | 2:8d8295a51f68 | 8 | |
WGorniak | 2:8d8295a51f68 | 9 | /* Set this flag to '1' to display debug messages on the console */ |
WGorniak | 2:8d8295a51f68 | 10 | |
WGorniak | 2:8d8295a51f68 | 11 | #define DEBUG_MESSAGE 0 |
WGorniak | 2:8d8295a51f68 | 12 | #define RX_TIMEOUT_VALUE 3500000 // in us |
WGorniak | 2:8d8295a51f68 | 13 | #define BUFFER_SIZE 32 // Define the payload size here |
WGorniak | 2:8d8295a51f68 | 14 | |
WGorniak | 2:8d8295a51f68 | 15 | // Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation |
WGorniak | 2:8d8295a51f68 | 16 | #define USE_MODEM_LORA 1 |
WGorniak | 2:8d8295a51f68 | 17 | #define USE_MODEM_FSK !USE_MODEM_LORA |
WGorniak | 2:8d8295a51f68 | 18 | |
WGorniak | 2:8d8295a51f68 | 19 | #if USE_MODEM_LORA == 1 |
WGorniak | 2:8d8295a51f68 | 20 | |
WGorniak | 2:8d8295a51f68 | 21 | #define LORA_FIX_LENGTH_PAYLOAD_ON false |
WGorniak | 2:8d8295a51f68 | 22 | #define LORA_FHSS_ENABLED false |
WGorniak | 2:8d8295a51f68 | 23 | #define LORA_NB_SYMB_HOP 4 |
WGorniak | 2:8d8295a51f68 | 24 | #define LORA_IQ_INVERSION_ON false |
WGorniak | 2:8d8295a51f68 | 25 | #define LORA_CRC_ENABLED true |
WGorniak | 2:8d8295a51f68 | 26 | |
WGorniak | 2:8d8295a51f68 | 27 | #elif USE_MODEM_FSK == 1 |
WGorniak | 2:8d8295a51f68 | 28 | |
WGorniak | 2:8d8295a51f68 | 29 | #define FSK_FDEV 25000 // Hz |
WGorniak | 2:8d8295a51f68 | 30 | #define FSK_DATARATE 19200 // bps |
WGorniak | 2:8d8295a51f68 | 31 | #define FSK_BANDWIDTH 50000 // Hz |
WGorniak | 2:8d8295a51f68 | 32 | #define FSK_AFC_BANDWIDTH 83333 // Hz |
WGorniak | 2:8d8295a51f68 | 33 | #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx |
WGorniak | 2:8d8295a51f68 | 34 | #define FSK_FIX_LENGTH_PAYLOAD_ON false |
WGorniak | 2:8d8295a51f68 | 35 | #define FSK_CRC_ENABLED true |
WGorniak | 2:8d8295a51f68 | 36 | |
WGorniak | 2:8d8295a51f68 | 37 | #else |
WGorniak | 2:8d8295a51f68 | 38 | #error "Please define a modem in the compiler options." |
WGorniak | 2:8d8295a51f68 | 39 | #endif |
WGorniak | 2:8d8295a51f68 | 40 | |
WGorniak | 2:8d8295a51f68 | 41 | |
WGorniak | 2:8d8295a51f68 | 42 | RadioContex* RadioContex::thi = 0; |
WGorniak | 2:8d8295a51f68 | 43 | |
WGorniak | 2:8d8295a51f68 | 44 | const char* RadioContex::rx_error_msg = "rx_error"; |
WGorniak | 2:8d8295a51f68 | 45 | const char* RadioContex::rx_timeout_msg = "rx_timeout"; |
WGorniak | 2:8d8295a51f68 | 46 | |
WGorniak | 2:8d8295a51f68 | 47 | |
WGorniak | 2:8d8295a51f68 | 48 | RadioContex::RadioContex (Settings* settings) |
WGorniak | 2:8d8295a51f68 | 49 | : radio_ (0) |
WGorniak | 2:8d8295a51f68 | 50 | { |
WGorniak | 2:8d8295a51f68 | 51 | assert(thi == 0); |
WGorniak | 2:8d8295a51f68 | 52 | thi = this; |
WGorniak | 2:8d8295a51f68 | 53 | BufferSize = BUFFER_SIZE; |
WGorniak | 2:8d8295a51f68 | 54 | State = LOWPOWER; |
WGorniak | 2:8d8295a51f68 | 55 | |
WGorniak | 2:8d8295a51f68 | 56 | sendCntr = 0; |
WGorniak | 2:8d8295a51f68 | 57 | |
WGorniak | 2:8d8295a51f68 | 58 | radio_ = new SX1272MB1xAS ( RadioContex::StaticOnTxDone, RadioContex::StaticOnTxTimeout, RadioContex::StaticOnRxDone, |
WGorniak | 2:8d8295a51f68 | 59 | RadioContex::StaticOnRxTimeout, RadioContex::StaticOnRxError, NULL, NULL, |
WGorniak | 2:8d8295a51f68 | 60 | RF_SPI_MOSI, RF_SPI_MISO, RF_SPI_SCK, RF_SPI_CS, |
WGorniak | 2:8d8295a51f68 | 61 | RF_RESET, RF_DIO0, RF_DIO1, RF_DIO2, RF_DIO3, RF_DIO4, RF_DIO5, |
WGorniak | 2:8d8295a51f68 | 62 | RF_RXTX_SW ); |
WGorniak | 2:8d8295a51f68 | 63 | |
WGorniak | 2:8d8295a51f68 | 64 | // verify the connection with the board |
WGorniak | 2:8d8295a51f68 | 65 | while( radio_->Read( REG_VERSION ) == 0x00 ) |
WGorniak | 2:8d8295a51f68 | 66 | { |
WGorniak | 2:8d8295a51f68 | 67 | debug( "Radio could not be detected!\n\r", NULL ); |
WGorniak | 2:8d8295a51f68 | 68 | wait( 1 ); |
WGorniak | 2:8d8295a51f68 | 69 | } |
WGorniak | 2:8d8295a51f68 | 70 | |
WGorniak | 2:8d8295a51f68 | 71 | radio_->SetChannel( settings->aget("freq") * 1000 ); |
WGorniak | 2:8d8295a51f68 | 72 | |
WGorniak | 2:8d8295a51f68 | 73 | #if USE_MODEM_LORA == 1 |
WGorniak | 2:8d8295a51f68 | 74 | |
WGorniak | 2:8d8295a51f68 | 75 | debug_if( LORA_FHSS_ENABLED, "> Radio start LORA FHSS Mode < \n\r"); |
WGorniak | 2:8d8295a51f68 | 76 | debug_if( !LORA_FHSS_ENABLED, "> Radio start LORA Mode < \n\r"); |
WGorniak | 2:8d8295a51f68 | 77 | |
WGorniak | 2:8d8295a51f68 | 78 | radio_->SetTxConfig( MODEM_LORA, settings->aget("power") , 0, settings->aget("bandwidth"), |
WGorniak | 2:8d8295a51f68 | 79 | settings->aget("dataRate"), settings->aget("codeRate"), |
WGorniak | 2:8d8295a51f68 | 80 | settings->aget("preambleLen"), LORA_FIX_LENGTH_PAYLOAD_ON, |
WGorniak | 2:8d8295a51f68 | 81 | LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, |
WGorniak | 2:8d8295a51f68 | 82 | LORA_IQ_INVERSION_ON, 2000000, settings->aget("paBoost")); |
WGorniak | 2:8d8295a51f68 | 83 | |
WGorniak | 2:8d8295a51f68 | 84 | radio_->SetRxConfig( MODEM_LORA, settings->aget("bandwidth"), |
WGorniak | 2:8d8295a51f68 | 85 | settings->aget("dataRate"), settings->aget("codeRate"), 0, settings->aget("preambleLen"), |
WGorniak | 2:8d8295a51f68 | 86 | settings->aget("symbTimeout"), LORA_FIX_LENGTH_PAYLOAD_ON, 0, |
WGorniak | 2:8d8295a51f68 | 87 | LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, |
WGorniak | 2:8d8295a51f68 | 88 | LORA_IQ_INVERSION_ON, true ); |
WGorniak | 2:8d8295a51f68 | 89 | |
WGorniak | 2:8d8295a51f68 | 90 | #elif USE_MODEM_FSK == 1 |
WGorniak | 2:8d8295a51f68 | 91 | |
WGorniak | 2:8d8295a51f68 | 92 | debug("\n\n\r > FSK Mode < \n\n\r"); |
WGorniak | 2:8d8295a51f68 | 93 | radio_->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, |
WGorniak | 2:8d8295a51f68 | 94 | FSK_DATARATE, 0, |
WGorniak | 2:8d8295a51f68 | 95 | FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, |
WGorniak | 2:8d8295a51f68 | 96 | FSK_CRC_ENABLED, 0, 0, 0, 2000000 ); |
WGorniak | 2:8d8295a51f68 | 97 | |
WGorniak | 2:8d8295a51f68 | 98 | radio_->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, |
WGorniak | 2:8d8295a51f68 | 99 | 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, |
WGorniak | 2:8d8295a51f68 | 100 | 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, |
WGorniak | 2:8d8295a51f68 | 101 | 0, 0, false, true ); |
WGorniak | 2:8d8295a51f68 | 102 | |
WGorniak | 2:8d8295a51f68 | 103 | #else |
WGorniak | 2:8d8295a51f68 | 104 | |
WGorniak | 2:8d8295a51f68 | 105 | #error "Please define a modem in the compiler options." |
WGorniak | 2:8d8295a51f68 | 106 | |
WGorniak | 2:8d8295a51f68 | 107 | #endif |
WGorniak | 2:8d8295a51f68 | 108 | |
WGorniak | 2:8d8295a51f68 | 109 | } |
WGorniak | 2:8d8295a51f68 | 110 | |
WGorniak | 2:8d8295a51f68 | 111 | |
WGorniak | 2:8d8295a51f68 | 112 | RadioContex::States_t RadioContex::getState() const |
WGorniak | 2:8d8295a51f68 | 113 | { |
WGorniak | 2:8d8295a51f68 | 114 | return State; |
WGorniak | 2:8d8295a51f68 | 115 | } |
WGorniak | 2:8d8295a51f68 | 116 | |
WGorniak | 2:8d8295a51f68 | 117 | |
WGorniak | 2:8d8295a51f68 | 118 | bool RadioContex::setState(States_t newState) |
WGorniak | 2:8d8295a51f68 | 119 | { |
WGorniak | 2:8d8295a51f68 | 120 | State = newState; |
WGorniak | 2:8d8295a51f68 | 121 | return true; |
WGorniak | 2:8d8295a51f68 | 122 | } |
WGorniak | 2:8d8295a51f68 | 123 | |
WGorniak | 2:8d8295a51f68 | 124 | |
WGorniak | 2:8d8295a51f68 | 125 | bool RadioContex::Send(std::string arg) |
WGorniak | 2:8d8295a51f68 | 126 | { |
WGorniak | 2:8d8295a51f68 | 127 | stringstream ss; |
WGorniak | 2:8d8295a51f68 | 128 | ss <<" "<< sendCntr; |
WGorniak | 2:8d8295a51f68 | 129 | arg.append(ss.str()); |
WGorniak | 2:8d8295a51f68 | 130 | |
WGorniak | 2:8d8295a51f68 | 131 | const uint8_t* msg = (const unsigned char *)(arg.c_str()); |
WGorniak | 2:8d8295a51f68 | 132 | uint16_t msgSize = static_cast<uint16_t>(arg.size()); |
WGorniak | 2:8d8295a51f68 | 133 | |
WGorniak | 2:8d8295a51f68 | 134 | strcpy( ( char* )Buffer, ( char* )msg ); |
WGorniak | 2:8d8295a51f68 | 135 | // We fill the buffer with numbers for the payload |
WGorniak | 2:8d8295a51f68 | 136 | for(int i = msgSize; i < BufferSize; i++ ) |
WGorniak | 2:8d8295a51f68 | 137 | { |
WGorniak | 2:8d8295a51f68 | 138 | Buffer[i] = i - msgSize; |
WGorniak | 2:8d8295a51f68 | 139 | } |
WGorniak | 2:8d8295a51f68 | 140 | sendCntr++; |
WGorniak | 2:8d8295a51f68 | 141 | |
WGorniak | 2:8d8295a51f68 | 142 | wait_ms( 10 ); |
WGorniak | 2:8d8295a51f68 | 143 | radio_->Send( Buffer, BufferSize ); |
WGorniak | 2:8d8295a51f68 | 144 | debug("%s\r\n", arg.c_str()); |
WGorniak | 2:8d8295a51f68 | 145 | return true; |
WGorniak | 2:8d8295a51f68 | 146 | } |
WGorniak | 2:8d8295a51f68 | 147 | |
WGorniak | 2:8d8295a51f68 | 148 | bool RadioContex::initReceive() |
WGorniak | 2:8d8295a51f68 | 149 | { |
WGorniak | 2:8d8295a51f68 | 150 | radio_->Rx( RX_TIMEOUT_VALUE ); |
WGorniak | 2:8d8295a51f68 | 151 | return true; |
WGorniak | 2:8d8295a51f68 | 152 | } |
WGorniak | 2:8d8295a51f68 | 153 | |
WGorniak | 2:8d8295a51f68 | 154 | bool RadioContex::pool_rx() |
WGorniak | 2:8d8295a51f68 | 155 | { |
WGorniak | 2:8d8295a51f68 | 156 | switch( State ) |
WGorniak | 2:8d8295a51f68 | 157 | { |
WGorniak | 2:8d8295a51f68 | 158 | case RX: |
WGorniak | 2:8d8295a51f68 | 159 | Buffer[BUFFER_SIZE-1] = 0; |
WGorniak | 2:8d8295a51f68 | 160 | State = LOWPOWER; |
WGorniak | 2:8d8295a51f68 | 161 | radio_->Rx( RX_TIMEOUT_VALUE ); |
WGorniak | 2:8d8295a51f68 | 162 | // Buffer[0] = 0; |
WGorniak | 2:8d8295a51f68 | 163 | return true; |
WGorniak | 2:8d8295a51f68 | 164 | case RX_TIMEOUT: |
WGorniak | 2:8d8295a51f68 | 165 | case RX_ERROR: |
WGorniak | 2:8d8295a51f68 | 166 | case IDLE: |
WGorniak | 2:8d8295a51f68 | 167 | radio_->Rx( RX_TIMEOUT_VALUE ); |
WGorniak | 2:8d8295a51f68 | 168 | State = LOWPOWER; |
WGorniak | 2:8d8295a51f68 | 169 | /* no break */ |
WGorniak | 2:8d8295a51f68 | 170 | case LOWPOWER: |
WGorniak | 2:8d8295a51f68 | 171 | break; |
WGorniak | 2:8d8295a51f68 | 172 | default: |
WGorniak | 2:8d8295a51f68 | 173 | State = LOWPOWER; |
WGorniak | 2:8d8295a51f68 | 174 | } |
WGorniak | 2:8d8295a51f68 | 175 | return false; |
WGorniak | 2:8d8295a51f68 | 176 | } |
WGorniak | 2:8d8295a51f68 | 177 | |
WGorniak | 2:8d8295a51f68 | 178 | |
WGorniak | 2:8d8295a51f68 | 179 | Radio& RadioContex::radio() |
WGorniak | 2:8d8295a51f68 | 180 | { |
WGorniak | 2:8d8295a51f68 | 181 | return *radio_; |
WGorniak | 2:8d8295a51f68 | 182 | } |
WGorniak | 2:8d8295a51f68 | 183 | |
WGorniak | 2:8d8295a51f68 | 184 | RadioContex::~RadioContex () |
WGorniak | 2:8d8295a51f68 | 185 | { |
WGorniak | 2:8d8295a51f68 | 186 | radio_->Reset(); |
WGorniak | 2:8d8295a51f68 | 187 | delete radio_; |
WGorniak | 2:8d8295a51f68 | 188 | thi = 0; |
WGorniak | 2:8d8295a51f68 | 189 | debug( "> Radio stop <\n\r" ); |
WGorniak | 2:8d8295a51f68 | 190 | // TODO Auto-generated destructor stub |
WGorniak | 2:8d8295a51f68 | 191 | } |
WGorniak | 2:8d8295a51f68 | 192 | |
WGorniak | 2:8d8295a51f68 | 193 | void RadioContex::StaticOnTxDone() |
WGorniak | 2:8d8295a51f68 | 194 | { |
WGorniak | 2:8d8295a51f68 | 195 | thi->OnTxDone(); |
WGorniak | 2:8d8295a51f68 | 196 | } |
WGorniak | 2:8d8295a51f68 | 197 | |
WGorniak | 2:8d8295a51f68 | 198 | void RadioContex::StaticOnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) |
WGorniak | 2:8d8295a51f68 | 199 | { |
WGorniak | 2:8d8295a51f68 | 200 | thi->OnRxDone(payload, size, rssi, snr); |
WGorniak | 2:8d8295a51f68 | 201 | } |
WGorniak | 2:8d8295a51f68 | 202 | |
WGorniak | 2:8d8295a51f68 | 203 | void RadioContex::StaticOnTxTimeout( void ) |
WGorniak | 2:8d8295a51f68 | 204 | { |
WGorniak | 2:8d8295a51f68 | 205 | thi->OnTxTimeout(); |
WGorniak | 2:8d8295a51f68 | 206 | } |
WGorniak | 2:8d8295a51f68 | 207 | |
WGorniak | 2:8d8295a51f68 | 208 | void RadioContex::StaticOnRxTimeout( void ) |
WGorniak | 2:8d8295a51f68 | 209 | { |
WGorniak | 2:8d8295a51f68 | 210 | thi->OnRxTimeout(); |
WGorniak | 2:8d8295a51f68 | 211 | } |
WGorniak | 2:8d8295a51f68 | 212 | |
WGorniak | 2:8d8295a51f68 | 213 | void RadioContex::StaticOnRxError( void ) |
WGorniak | 2:8d8295a51f68 | 214 | { |
WGorniak | 2:8d8295a51f68 | 215 | thi->OnRxError(); |
WGorniak | 2:8d8295a51f68 | 216 | } |
WGorniak | 2:8d8295a51f68 | 217 | |
WGorniak | 2:8d8295a51f68 | 218 | void RadioContex::OnTxDone( void ) |
WGorniak | 2:8d8295a51f68 | 219 | { |
WGorniak | 2:8d8295a51f68 | 220 | radio_->Sleep( ); |
WGorniak | 2:8d8295a51f68 | 221 | State = TX; |
WGorniak | 2:8d8295a51f68 | 222 | debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" ); |
WGorniak | 2:8d8295a51f68 | 223 | } |
WGorniak | 2:8d8295a51f68 | 224 | |
WGorniak | 2:8d8295a51f68 | 225 | void RadioContex::OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) |
WGorniak | 2:8d8295a51f68 | 226 | { |
WGorniak | 2:8d8295a51f68 | 227 | radio_->Sleep( ); |
WGorniak | 2:8d8295a51f68 | 228 | BufferSize = size; |
WGorniak | 2:8d8295a51f68 | 229 | memcpy( Buffer, payload, BufferSize ); |
WGorniak | 2:8d8295a51f68 | 230 | RssiValue = rssi; |
WGorniak | 2:8d8295a51f68 | 231 | SnrValue = snr; |
WGorniak | 2:8d8295a51f68 | 232 | State = RX; |
WGorniak | 2:8d8295a51f68 | 233 | debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" ); |
WGorniak | 2:8d8295a51f68 | 234 | } |
WGorniak | 2:8d8295a51f68 | 235 | |
WGorniak | 2:8d8295a51f68 | 236 | void RadioContex::OnTxTimeout( void ) |
WGorniak | 2:8d8295a51f68 | 237 | { |
WGorniak | 2:8d8295a51f68 | 238 | radio_->Sleep( ); |
WGorniak | 2:8d8295a51f68 | 239 | State = TX_TIMEOUT; |
WGorniak | 2:8d8295a51f68 | 240 | debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" ); |
WGorniak | 2:8d8295a51f68 | 241 | } |
WGorniak | 2:8d8295a51f68 | 242 | |
WGorniak | 2:8d8295a51f68 | 243 | void RadioContex::OnRxTimeout( void ) |
WGorniak | 2:8d8295a51f68 | 244 | { |
WGorniak | 2:8d8295a51f68 | 245 | radio_->Sleep( ); |
WGorniak | 2:8d8295a51f68 | 246 | Buffer[ BufferSize ] = 0; |
WGorniak | 2:8d8295a51f68 | 247 | State = RX_TIMEOUT; |
WGorniak | 2:8d8295a51f68 | 248 | debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" ); |
WGorniak | 2:8d8295a51f68 | 249 | } |
WGorniak | 2:8d8295a51f68 | 250 | |
WGorniak | 2:8d8295a51f68 | 251 | void RadioContex::OnRxError( void ) |
WGorniak | 2:8d8295a51f68 | 252 | { |
WGorniak | 2:8d8295a51f68 | 253 | radio_->Sleep( ); |
WGorniak | 2:8d8295a51f68 | 254 | State = RX_ERROR; |
WGorniak | 2:8d8295a51f68 | 255 | debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" ); |
WGorniak | 2:8d8295a51f68 | 256 | } |
WGorniak | 2:8d8295a51f68 | 257 |