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.

Dependencies:   SX1272lib mbed

Fork of Elmo-Terminal by Michal Leksinski

Committer:
WGorniak
Date:
Thu Oct 22 08:03:32 2015 +0000
Revision:
12:26045241f50f
Parent:
10:e4cbc7292f40
updated sx lib

Who changed what in which revision?

UserRevisionLine numberNew 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 10:e4cbc7292f40 76
WGorniak 10:e4cbc7292f40 77 if (!settings->aget("paBoost"))
WGorniak 10:e4cbc7292f40 78 {
WGorniak 10:e4cbc7292f40 79 if(settings->aget("power")>14)
WGorniak 10:e4cbc7292f40 80 {
WGorniak 10:e4cbc7292f40 81 printf("RFO mode, limiting power to 14 dBm\r\n");
WGorniak 10:e4cbc7292f40 82 settings->set("power",14);
WGorniak 10:e4cbc7292f40 83 }
WGorniak 10:e4cbc7292f40 84 }
WGorniak 2:8d8295a51f68 85
WGorniak 2:8d8295a51f68 86 radio_->SetTxConfig( MODEM_LORA, settings->aget("power") , 0, settings->aget("bandwidth"),
WGorniak 2:8d8295a51f68 87 settings->aget("dataRate"), settings->aget("codeRate"),
WGorniak 2:8d8295a51f68 88 settings->aget("preambleLen"), LORA_FIX_LENGTH_PAYLOAD_ON,
WGorniak 2:8d8295a51f68 89 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
WGorniak 2:8d8295a51f68 90 LORA_IQ_INVERSION_ON, 2000000, settings->aget("paBoost"));
WGorniak 2:8d8295a51f68 91
WGorniak 2:8d8295a51f68 92 radio_->SetRxConfig( MODEM_LORA, settings->aget("bandwidth"),
WGorniak 2:8d8295a51f68 93 settings->aget("dataRate"), settings->aget("codeRate"), 0, settings->aget("preambleLen"),
WGorniak 2:8d8295a51f68 94 settings->aget("symbTimeout"), LORA_FIX_LENGTH_PAYLOAD_ON, 0,
WGorniak 2:8d8295a51f68 95 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
WGorniak 2:8d8295a51f68 96 LORA_IQ_INVERSION_ON, true );
WGorniak 2:8d8295a51f68 97
WGorniak 2:8d8295a51f68 98 #elif USE_MODEM_FSK == 1
WGorniak 2:8d8295a51f68 99
WGorniak 2:8d8295a51f68 100 debug("\n\n\r > FSK Mode < \n\n\r");
WGorniak 2:8d8295a51f68 101 radio_->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
WGorniak 2:8d8295a51f68 102 FSK_DATARATE, 0,
WGorniak 2:8d8295a51f68 103 FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
WGorniak 2:8d8295a51f68 104 FSK_CRC_ENABLED, 0, 0, 0, 2000000 );
WGorniak 2:8d8295a51f68 105
WGorniak 2:8d8295a51f68 106 radio_->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
WGorniak 2:8d8295a51f68 107 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
WGorniak 2:8d8295a51f68 108 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
WGorniak 2:8d8295a51f68 109 0, 0, false, true );
WGorniak 2:8d8295a51f68 110
WGorniak 2:8d8295a51f68 111 #else
WGorniak 2:8d8295a51f68 112
WGorniak 2:8d8295a51f68 113 #error "Please define a modem in the compiler options."
WGorniak 2:8d8295a51f68 114
WGorniak 2:8d8295a51f68 115 #endif
WGorniak 2:8d8295a51f68 116
WGorniak 2:8d8295a51f68 117 }
WGorniak 2:8d8295a51f68 118
WGorniak 2:8d8295a51f68 119
WGorniak 2:8d8295a51f68 120 RadioContex::States_t RadioContex::getState() const
WGorniak 2:8d8295a51f68 121 {
WGorniak 2:8d8295a51f68 122 return State;
WGorniak 2:8d8295a51f68 123 }
WGorniak 2:8d8295a51f68 124
WGorniak 2:8d8295a51f68 125
WGorniak 2:8d8295a51f68 126 bool RadioContex::setState(States_t newState)
WGorniak 2:8d8295a51f68 127 {
WGorniak 2:8d8295a51f68 128 State = newState;
WGorniak 2:8d8295a51f68 129 return true;
WGorniak 2:8d8295a51f68 130 }
WGorniak 2:8d8295a51f68 131
WGorniak 6:453b018a9ba0 132 extern std::string to_string(const int32_t val);
WGorniak 2:8d8295a51f68 133
WGorniak 2:8d8295a51f68 134 bool RadioContex::Send(std::string arg)
WGorniak 2:8d8295a51f68 135 {
WGorniak 6:453b018a9ba0 136 std::string ss(" ");
WGorniak 6:453b018a9ba0 137 ss.append(to_string(sendCntr));
WGorniak 6:453b018a9ba0 138 arg.append(ss);
WGorniak 2:8d8295a51f68 139
WGorniak 2:8d8295a51f68 140 const uint8_t* msg = (const unsigned char *)(arg.c_str());
WGorniak 2:8d8295a51f68 141 uint16_t msgSize = static_cast<uint16_t>(arg.size());
WGorniak 2:8d8295a51f68 142
WGorniak 2:8d8295a51f68 143 strcpy( ( char* )Buffer, ( char* )msg );
WGorniak 2:8d8295a51f68 144 // We fill the buffer with numbers for the payload
WGorniak 2:8d8295a51f68 145 for(int i = msgSize; i < BufferSize; i++ )
WGorniak 2:8d8295a51f68 146 {
WGorniak 2:8d8295a51f68 147 Buffer[i] = i - msgSize;
WGorniak 2:8d8295a51f68 148 }
WGorniak 2:8d8295a51f68 149 sendCntr++;
WGorniak 2:8d8295a51f68 150
WGorniak 2:8d8295a51f68 151 wait_ms( 10 );
WGorniak 2:8d8295a51f68 152 radio_->Send( Buffer, BufferSize );
WGorniak 2:8d8295a51f68 153 debug("%s\r\n", arg.c_str());
WGorniak 2:8d8295a51f68 154 return true;
WGorniak 2:8d8295a51f68 155 }
WGorniak 2:8d8295a51f68 156
WGorniak 2:8d8295a51f68 157 bool RadioContex::initReceive()
WGorniak 2:8d8295a51f68 158 {
WGorniak 2:8d8295a51f68 159 radio_->Rx( RX_TIMEOUT_VALUE );
WGorniak 2:8d8295a51f68 160 return true;
WGorniak 2:8d8295a51f68 161 }
WGorniak 2:8d8295a51f68 162
WGorniak 2:8d8295a51f68 163 bool RadioContex::pool_rx()
WGorniak 2:8d8295a51f68 164 {
WGorniak 2:8d8295a51f68 165 switch( State )
WGorniak 2:8d8295a51f68 166 {
WGorniak 2:8d8295a51f68 167 case RX:
WGorniak 2:8d8295a51f68 168 Buffer[BUFFER_SIZE-1] = 0;
WGorniak 2:8d8295a51f68 169 State = LOWPOWER;
WGorniak 2:8d8295a51f68 170 radio_->Rx( RX_TIMEOUT_VALUE );
WGorniak 2:8d8295a51f68 171 // Buffer[0] = 0;
WGorniak 2:8d8295a51f68 172 return true;
WGorniak 2:8d8295a51f68 173 case RX_TIMEOUT:
WGorniak 2:8d8295a51f68 174 case RX_ERROR:
WGorniak 2:8d8295a51f68 175 case IDLE:
WGorniak 2:8d8295a51f68 176 radio_->Rx( RX_TIMEOUT_VALUE );
WGorniak 2:8d8295a51f68 177 State = LOWPOWER;
WGorniak 2:8d8295a51f68 178 /* no break */
WGorniak 2:8d8295a51f68 179 case LOWPOWER:
WGorniak 2:8d8295a51f68 180 break;
WGorniak 2:8d8295a51f68 181 default:
WGorniak 2:8d8295a51f68 182 State = LOWPOWER;
WGorniak 2:8d8295a51f68 183 }
WGorniak 2:8d8295a51f68 184 return false;
WGorniak 2:8d8295a51f68 185 }
WGorniak 2:8d8295a51f68 186
WGorniak 2:8d8295a51f68 187
WGorniak 2:8d8295a51f68 188 Radio& RadioContex::radio()
WGorniak 2:8d8295a51f68 189 {
WGorniak 2:8d8295a51f68 190 return *radio_;
WGorniak 2:8d8295a51f68 191 }
WGorniak 2:8d8295a51f68 192
WGorniak 2:8d8295a51f68 193 RadioContex::~RadioContex ()
WGorniak 2:8d8295a51f68 194 {
WGorniak 2:8d8295a51f68 195 radio_->Reset();
WGorniak 2:8d8295a51f68 196 delete radio_;
WGorniak 2:8d8295a51f68 197 thi = 0;
WGorniak 2:8d8295a51f68 198 debug( "> Radio stop <\n\r" );
WGorniak 2:8d8295a51f68 199 // TODO Auto-generated destructor stub
WGorniak 2:8d8295a51f68 200 }
WGorniak 2:8d8295a51f68 201
WGorniak 2:8d8295a51f68 202 void RadioContex::StaticOnTxDone()
WGorniak 2:8d8295a51f68 203 {
WGorniak 2:8d8295a51f68 204 thi->OnTxDone();
WGorniak 2:8d8295a51f68 205 }
WGorniak 2:8d8295a51f68 206
WGorniak 2:8d8295a51f68 207 void RadioContex::StaticOnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
WGorniak 2:8d8295a51f68 208 {
WGorniak 2:8d8295a51f68 209 thi->OnRxDone(payload, size, rssi, snr);
WGorniak 2:8d8295a51f68 210 }
WGorniak 2:8d8295a51f68 211
WGorniak 2:8d8295a51f68 212 void RadioContex::StaticOnTxTimeout( void )
WGorniak 2:8d8295a51f68 213 {
WGorniak 2:8d8295a51f68 214 thi->OnTxTimeout();
WGorniak 2:8d8295a51f68 215 }
WGorniak 2:8d8295a51f68 216
WGorniak 2:8d8295a51f68 217 void RadioContex::StaticOnRxTimeout( void )
WGorniak 2:8d8295a51f68 218 {
WGorniak 2:8d8295a51f68 219 thi->OnRxTimeout();
WGorniak 2:8d8295a51f68 220 }
WGorniak 2:8d8295a51f68 221
WGorniak 2:8d8295a51f68 222 void RadioContex::StaticOnRxError( void )
WGorniak 2:8d8295a51f68 223 {
WGorniak 2:8d8295a51f68 224 thi->OnRxError();
WGorniak 2:8d8295a51f68 225 }
WGorniak 2:8d8295a51f68 226
WGorniak 2:8d8295a51f68 227 void RadioContex::OnTxDone( void )
WGorniak 2:8d8295a51f68 228 {
WGorniak 2:8d8295a51f68 229 radio_->Sleep( );
WGorniak 2:8d8295a51f68 230 State = TX;
WGorniak 2:8d8295a51f68 231 debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
WGorniak 2:8d8295a51f68 232 }
WGorniak 2:8d8295a51f68 233
WGorniak 2:8d8295a51f68 234 void RadioContex::OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
WGorniak 2:8d8295a51f68 235 {
WGorniak 2:8d8295a51f68 236 radio_->Sleep( );
WGorniak 2:8d8295a51f68 237 BufferSize = size;
WGorniak 2:8d8295a51f68 238 memcpy( Buffer, payload, BufferSize );
WGorniak 2:8d8295a51f68 239 RssiValue = rssi;
WGorniak 2:8d8295a51f68 240 SnrValue = snr;
WGorniak 2:8d8295a51f68 241 State = RX;
WGorniak 2:8d8295a51f68 242 debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
WGorniak 2:8d8295a51f68 243 }
WGorniak 2:8d8295a51f68 244
WGorniak 2:8d8295a51f68 245 void RadioContex::OnTxTimeout( void )
WGorniak 2:8d8295a51f68 246 {
WGorniak 2:8d8295a51f68 247 radio_->Sleep( );
WGorniak 2:8d8295a51f68 248 State = TX_TIMEOUT;
WGorniak 2:8d8295a51f68 249 debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
WGorniak 2:8d8295a51f68 250 }
WGorniak 2:8d8295a51f68 251
WGorniak 2:8d8295a51f68 252 void RadioContex::OnRxTimeout( void )
WGorniak 2:8d8295a51f68 253 {
WGorniak 2:8d8295a51f68 254 radio_->Sleep( );
WGorniak 2:8d8295a51f68 255 Buffer[ BufferSize ] = 0;
WGorniak 2:8d8295a51f68 256 State = RX_TIMEOUT;
WGorniak 2:8d8295a51f68 257 debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
WGorniak 2:8d8295a51f68 258 }
WGorniak 2:8d8295a51f68 259
WGorniak 2:8d8295a51f68 260 void RadioContex::OnRxError( void )
WGorniak 2:8d8295a51f68 261 {
WGorniak 2:8d8295a51f68 262 radio_->Sleep( );
WGorniak 2:8d8295a51f68 263 State = RX_ERROR;
WGorniak 2:8d8295a51f68 264 debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
WGorniak 2:8d8295a51f68 265 }
WGorniak 2:8d8295a51f68 266