Elmo Terminal provides functionality to test Lora radio and access SX1272 chip registers delivered with Elmo board. This firmware allows the user to control the LoRa radio parameters (eg. frequency, bandwidth, spreading factor etc.) by entering console commands via serial terminal. Application also contains "Ping-Pong" and data transmission functionalities.
Fork of Elmo-Terminal by
RadioContex.cpp@6:453b018a9ba0, 2015-10-01 (annotated)
- Committer:
- WGorniak
- Date:
- Thu Oct 01 13:13:08 2015 +0000
- Revision:
- 6:453b018a9ba0
- Parent:
- 4:2767f13b0a75
- Child:
- 10:e4cbc7292f40
removed sstream from radiocontext
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 | |
WGorniak | 2:8d8295a51f68 | 7 | |
WGorniak | 2:8d8295a51f68 | 8 | /* Set this flag to '1' to display debug messages on the console */ |
WGorniak | 2:8d8295a51f68 | 9 | |
WGorniak | 2:8d8295a51f68 | 10 | #define DEBUG_MESSAGE 0 |
WGorniak | 2:8d8295a51f68 | 11 | #define RX_TIMEOUT_VALUE 3500000 // in us |
WGorniak | 2:8d8295a51f68 | 12 | #define BUFFER_SIZE 32 // Define the payload size here |
WGorniak | 2:8d8295a51f68 | 13 | |
WGorniak | 2:8d8295a51f68 | 14 | // Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation |
WGorniak | 2:8d8295a51f68 | 15 | #define USE_MODEM_LORA 1 |
WGorniak | 2:8d8295a51f68 | 16 | #define USE_MODEM_FSK !USE_MODEM_LORA |
WGorniak | 2:8d8295a51f68 | 17 | |
WGorniak | 2:8d8295a51f68 | 18 | #if USE_MODEM_LORA == 1 |
WGorniak | 2:8d8295a51f68 | 19 | |
WGorniak | 2:8d8295a51f68 | 20 | #define LORA_FIX_LENGTH_PAYLOAD_ON false |
WGorniak | 2:8d8295a51f68 | 21 | #define LORA_FHSS_ENABLED false |
WGorniak | 2:8d8295a51f68 | 22 | #define LORA_NB_SYMB_HOP 4 |
WGorniak | 2:8d8295a51f68 | 23 | #define LORA_IQ_INVERSION_ON false |
WGorniak | 2:8d8295a51f68 | 24 | #define LORA_CRC_ENABLED true |
WGorniak | 2:8d8295a51f68 | 25 | |
WGorniak | 2:8d8295a51f68 | 26 | #elif USE_MODEM_FSK == 1 |
WGorniak | 2:8d8295a51f68 | 27 | |
WGorniak | 2:8d8295a51f68 | 28 | #define FSK_FDEV 25000 // Hz |
WGorniak | 2:8d8295a51f68 | 29 | #define FSK_DATARATE 19200 // bps |
WGorniak | 2:8d8295a51f68 | 30 | #define FSK_BANDWIDTH 50000 // Hz |
WGorniak | 2:8d8295a51f68 | 31 | #define FSK_AFC_BANDWIDTH 83333 // Hz |
WGorniak | 2:8d8295a51f68 | 32 | #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx |
WGorniak | 2:8d8295a51f68 | 33 | #define FSK_FIX_LENGTH_PAYLOAD_ON false |
WGorniak | 2:8d8295a51f68 | 34 | #define FSK_CRC_ENABLED true |
WGorniak | 2:8d8295a51f68 | 35 | |
WGorniak | 2:8d8295a51f68 | 36 | #else |
WGorniak | 2:8d8295a51f68 | 37 | #error "Please define a modem in the compiler options." |
WGorniak | 2:8d8295a51f68 | 38 | #endif |
WGorniak | 2:8d8295a51f68 | 39 | |
WGorniak | 2:8d8295a51f68 | 40 | |
WGorniak | 2:8d8295a51f68 | 41 | RadioContex* RadioContex::thi = 0; |
WGorniak | 2:8d8295a51f68 | 42 | |
WGorniak | 2:8d8295a51f68 | 43 | const char* RadioContex::rx_error_msg = "rx_error"; |
WGorniak | 2:8d8295a51f68 | 44 | const char* RadioContex::rx_timeout_msg = "rx_timeout"; |
WGorniak | 2:8d8295a51f68 | 45 | |
WGorniak | 2:8d8295a51f68 | 46 | |
WGorniak | 2:8d8295a51f68 | 47 | RadioContex::RadioContex (Settings* settings) |
WGorniak | 2:8d8295a51f68 | 48 | : radio_ (0) |
WGorniak | 2:8d8295a51f68 | 49 | { |
WGorniak | 2:8d8295a51f68 | 50 | assert(thi == 0); |
WGorniak | 2:8d8295a51f68 | 51 | thi = this; |
WGorniak | 2:8d8295a51f68 | 52 | BufferSize = BUFFER_SIZE; |
WGorniak | 2:8d8295a51f68 | 53 | State = LOWPOWER; |
WGorniak | 2:8d8295a51f68 | 54 | |
WGorniak | 2:8d8295a51f68 | 55 | sendCntr = 0; |
WGorniak | 2:8d8295a51f68 | 56 | |
WGorniak | 4:2767f13b0a75 | 57 | radio_ = new SX1272BRD ( RadioContex::StaticOnTxDone, RadioContex::StaticOnTxTimeout, RadioContex::StaticOnRxDone, |
WGorniak | 2:8d8295a51f68 | 58 | RadioContex::StaticOnRxTimeout, RadioContex::StaticOnRxError, NULL, NULL, |
WGorniak | 2:8d8295a51f68 | 59 | RF_SPI_MOSI, RF_SPI_MISO, RF_SPI_SCK, RF_SPI_CS, |
WGorniak | 2:8d8295a51f68 | 60 | RF_RESET, RF_DIO0, RF_DIO1, RF_DIO2, RF_DIO3, RF_DIO4, RF_DIO5, |
WGorniak | 2:8d8295a51f68 | 61 | RF_RXTX_SW ); |
WGorniak | 2:8d8295a51f68 | 62 | |
WGorniak | 2:8d8295a51f68 | 63 | // verify the connection with the board |
WGorniak | 2:8d8295a51f68 | 64 | while( radio_->Read( REG_VERSION ) == 0x00 ) |
WGorniak | 2:8d8295a51f68 | 65 | { |
WGorniak | 2:8d8295a51f68 | 66 | debug( "Radio could not be detected!\n\r", NULL ); |
WGorniak | 2:8d8295a51f68 | 67 | wait( 1 ); |
WGorniak | 2:8d8295a51f68 | 68 | } |
WGorniak | 2:8d8295a51f68 | 69 | |
WGorniak | 2:8d8295a51f68 | 70 | radio_->SetChannel( settings->aget("freq") * 1000 ); |
WGorniak | 2:8d8295a51f68 | 71 | |
WGorniak | 2:8d8295a51f68 | 72 | #if USE_MODEM_LORA == 1 |
WGorniak | 2:8d8295a51f68 | 73 | |
WGorniak | 2:8d8295a51f68 | 74 | debug_if( LORA_FHSS_ENABLED, "> Radio start LORA FHSS Mode < \n\r"); |
WGorniak | 2:8d8295a51f68 | 75 | debug_if( !LORA_FHSS_ENABLED, "> Radio start LORA Mode < \n\r"); |
WGorniak | 2:8d8295a51f68 | 76 | |
WGorniak | 2:8d8295a51f68 | 77 | radio_->SetTxConfig( MODEM_LORA, settings->aget("power") , 0, settings->aget("bandwidth"), |
WGorniak | 2:8d8295a51f68 | 78 | settings->aget("dataRate"), settings->aget("codeRate"), |
WGorniak | 2:8d8295a51f68 | 79 | settings->aget("preambleLen"), LORA_FIX_LENGTH_PAYLOAD_ON, |
WGorniak | 2:8d8295a51f68 | 80 | LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, |
WGorniak | 2:8d8295a51f68 | 81 | LORA_IQ_INVERSION_ON, 2000000, settings->aget("paBoost")); |
WGorniak | 2:8d8295a51f68 | 82 | |
WGorniak | 2:8d8295a51f68 | 83 | radio_->SetRxConfig( MODEM_LORA, settings->aget("bandwidth"), |
WGorniak | 2:8d8295a51f68 | 84 | settings->aget("dataRate"), settings->aget("codeRate"), 0, settings->aget("preambleLen"), |
WGorniak | 2:8d8295a51f68 | 85 | settings->aget("symbTimeout"), LORA_FIX_LENGTH_PAYLOAD_ON, 0, |
WGorniak | 2:8d8295a51f68 | 86 | LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, |
WGorniak | 2:8d8295a51f68 | 87 | LORA_IQ_INVERSION_ON, true ); |
WGorniak | 2:8d8295a51f68 | 88 | |
WGorniak | 2:8d8295a51f68 | 89 | #elif USE_MODEM_FSK == 1 |
WGorniak | 2:8d8295a51f68 | 90 | |
WGorniak | 2:8d8295a51f68 | 91 | debug("\n\n\r > FSK Mode < \n\n\r"); |
WGorniak | 2:8d8295a51f68 | 92 | radio_->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, |
WGorniak | 2:8d8295a51f68 | 93 | FSK_DATARATE, 0, |
WGorniak | 2:8d8295a51f68 | 94 | FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, |
WGorniak | 2:8d8295a51f68 | 95 | FSK_CRC_ENABLED, 0, 0, 0, 2000000 ); |
WGorniak | 2:8d8295a51f68 | 96 | |
WGorniak | 2:8d8295a51f68 | 97 | radio_->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, |
WGorniak | 2:8d8295a51f68 | 98 | 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, |
WGorniak | 2:8d8295a51f68 | 99 | 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, |
WGorniak | 2:8d8295a51f68 | 100 | 0, 0, false, true ); |
WGorniak | 2:8d8295a51f68 | 101 | |
WGorniak | 2:8d8295a51f68 | 102 | #else |
WGorniak | 2:8d8295a51f68 | 103 | |
WGorniak | 2:8d8295a51f68 | 104 | #error "Please define a modem in the compiler options." |
WGorniak | 2:8d8295a51f68 | 105 | |
WGorniak | 2:8d8295a51f68 | 106 | #endif |
WGorniak | 2:8d8295a51f68 | 107 | |
WGorniak | 2:8d8295a51f68 | 108 | } |
WGorniak | 2:8d8295a51f68 | 109 | |
WGorniak | 2:8d8295a51f68 | 110 | |
WGorniak | 2:8d8295a51f68 | 111 | RadioContex::States_t RadioContex::getState() const |
WGorniak | 2:8d8295a51f68 | 112 | { |
WGorniak | 2:8d8295a51f68 | 113 | return State; |
WGorniak | 2:8d8295a51f68 | 114 | } |
WGorniak | 2:8d8295a51f68 | 115 | |
WGorniak | 2:8d8295a51f68 | 116 | |
WGorniak | 2:8d8295a51f68 | 117 | bool RadioContex::setState(States_t newState) |
WGorniak | 2:8d8295a51f68 | 118 | { |
WGorniak | 2:8d8295a51f68 | 119 | State = newState; |
WGorniak | 2:8d8295a51f68 | 120 | return true; |
WGorniak | 2:8d8295a51f68 | 121 | } |
WGorniak | 2:8d8295a51f68 | 122 | |
WGorniak | 6:453b018a9ba0 | 123 | extern std::string to_string(const int32_t val); |
WGorniak | 2:8d8295a51f68 | 124 | |
WGorniak | 2:8d8295a51f68 | 125 | bool RadioContex::Send(std::string arg) |
WGorniak | 2:8d8295a51f68 | 126 | { |
WGorniak | 6:453b018a9ba0 | 127 | std::string ss(" "); |
WGorniak | 6:453b018a9ba0 | 128 | ss.append(to_string(sendCntr)); |
WGorniak | 6:453b018a9ba0 | 129 | arg.append(ss); |
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 |