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 01 09:40:30 2015 +0200
Revision:
2:8d8295a51f68
Child:
4:2767f13b0a75
added terminal app

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 #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