mirror of
				https://github.com/liberatedsystems/RNode_Firmware_CE.git
				synced 2024-07-02 14:34:13 +02:00 
			
		
		
		
	Initial commit
This commit is contained in:
		
						commit
						f2762af576
					
				
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					*.hex
 | 
				
			||||||
 | 
					TODO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										63
									
								
								Config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								Config.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					#ifndef CONFIG_H
 | 
				
			||||||
 | 
						#define CONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define MCU_328P 0x90
 | 
				
			||||||
 | 
						#define MCU_1284P 0x91
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#if defined(__AVR_ATmega328P__)
 | 
				
			||||||
 | 
							#define MCU_VARIANT MCU_328P
 | 
				
			||||||
 | 
							#warning "Firmware is being compiled for atmega328p based boards"
 | 
				
			||||||
 | 
						#elif defined(__AVR_ATmega1284P__)
 | 
				
			||||||
 | 
							#define MCU_VARIANT MCU_1284P
 | 
				
			||||||
 | 
							#warning "Firmware is being compiled for atmega1284p based boards"
 | 
				
			||||||
 | 
						#else
 | 
				
			||||||
 | 
							#error "The firmware cannot be compiled for the selected MCU variant"
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define MTU   	   500
 | 
				
			||||||
 | 
						#define SINGLE_MTU 255
 | 
				
			||||||
 | 
						#define HEADER_L   1
 | 
				
			||||||
 | 
						#define CMD_L      4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MCU dependent configuration parameters
 | 
				
			||||||
 | 
						#if MCU_VARIANT == MCU_328P
 | 
				
			||||||
 | 
							const int pin_cs = 7;
 | 
				
			||||||
 | 
							const int pin_reset = 6;
 | 
				
			||||||
 | 
							const int pin_dio = 2;
 | 
				
			||||||
 | 
							const int pin_led_rx = 5;
 | 
				
			||||||
 | 
							const int pin_led_tx = 4;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#if MCU_VARIANT == MCU_1284P
 | 
				
			||||||
 | 
							const int pin_cs = 4;
 | 
				
			||||||
 | 
							const int pin_reset = 3;
 | 
				
			||||||
 | 
							const int pin_dio = 2;
 | 
				
			||||||
 | 
							const int pin_led_rx = 12;
 | 
				
			||||||
 | 
							const int pin_led_tx = 13;
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MCU independent configuration parameters
 | 
				
			||||||
 | 
						const long serial_baudrate = 115200;
 | 
				
			||||||
 | 
						const int  rssi_offset     = 164;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Default LoRa settings
 | 
				
			||||||
 | 
						int  lora_sf   = 0;
 | 
				
			||||||
 | 
						int  lora_txp  = 0xFF;
 | 
				
			||||||
 | 
						uint32_t lora_bw   = 0;
 | 
				
			||||||
 | 
						uint32_t lora_freq = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Operational variables
 | 
				
			||||||
 | 
						bool radio_locked = true;
 | 
				
			||||||
 | 
						bool radio_online = false;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						int		last_rssi		= -164;
 | 
				
			||||||
 | 
						size_t	read_len		= 0;
 | 
				
			||||||
 | 
						uint8_t seq				= 0xFF;
 | 
				
			||||||
 | 
						uint8_t pbuf[MTU];
 | 
				
			||||||
 | 
						uint8_t sbuf[MTU];
 | 
				
			||||||
 | 
						uint8_t cbuf[CMD_L];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t stat_rx		= 0;
 | 
				
			||||||
 | 
						uint32_t stat_tx		= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										55
									
								
								Framing.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Framing.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					#ifndef FRAMING_H
 | 
				
			||||||
 | 
						#define FRAMING_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define FEND			0xC0
 | 
				
			||||||
 | 
						#define FESC			0xDB
 | 
				
			||||||
 | 
						#define TFEND			0xDC
 | 
				
			||||||
 | 
						#define TFESC			0xDD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define CMD_UNKNOWN		0xFE
 | 
				
			||||||
 | 
						#define CMD_DATA		0x00
 | 
				
			||||||
 | 
						#define CMD_FREQUENCY	0x01
 | 
				
			||||||
 | 
						#define CMD_BANDWIDTH	0x02
 | 
				
			||||||
 | 
						#define CMD_TXPOWER		0x03
 | 
				
			||||||
 | 
						#define CMD_SF			0x04
 | 
				
			||||||
 | 
						#define CMD_RADIO_STATE 0x05
 | 
				
			||||||
 | 
						#define CMD_RADIO_LOCK	0x06
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define CMD_STAT_RX		0x21
 | 
				
			||||||
 | 
						#define CMD_STAT_TX		0x22
 | 
				
			||||||
 | 
						#define CMD_STAT_RSSI	0x23
 | 
				
			||||||
 | 
						#define CMD_BLINK		0x30
 | 
				
			||||||
 | 
						#define CMD_RANDOM		0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define RADIO_STATE_OFF 0x00
 | 
				
			||||||
 | 
						#define RADIO_STATE_ON	0x01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define CMD_ERROR		0x90
 | 
				
			||||||
 | 
						#define ERROR_INITRADIO 0x01
 | 
				
			||||||
 | 
						#define ERROR_TXFAILED	0x02
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define NIBBLE_SEQ		0xF0
 | 
				
			||||||
 | 
						#define NIBBLE_FLAGS	0x0F
 | 
				
			||||||
 | 
						#define FLAG_SPLIT		0x01
 | 
				
			||||||
 | 
						#define SEQ_UNSET		0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Serial framing variables
 | 
				
			||||||
 | 
						size_t frame_len;
 | 
				
			||||||
 | 
						bool IN_FRAME = false;
 | 
				
			||||||
 | 
						bool ESCAPE = false;
 | 
				
			||||||
 | 
						uint8_t command = CMD_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Frequency 433.200		0xc00119d21b80c0
 | 
				
			||||||
 | 
					Bandwidth 20.800		0xc00200005140c0
 | 
				
			||||||
 | 
					TX Power 8dbm			0xc00308c0
 | 
				
			||||||
 | 
					SF 7					0xc00407c0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All:					0xc00119d21b80c00200005140c00308c00407c0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Radio on 				0xc00501c0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Config+on 				0xc00119d21b80c00200005140c00308c00407c00501c0
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
							
								
								
									
										584
									
								
								LoRa.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										584
									
								
								LoRa.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,584 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <LoRa.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// registers
 | 
				
			||||||
 | 
					#define REG_FIFO                 0x00
 | 
				
			||||||
 | 
					#define REG_OP_MODE              0x01
 | 
				
			||||||
 | 
					#define REG_FRF_MSB              0x06
 | 
				
			||||||
 | 
					#define REG_FRF_MID              0x07
 | 
				
			||||||
 | 
					#define REG_FRF_LSB              0x08
 | 
				
			||||||
 | 
					#define REG_PA_CONFIG            0x09
 | 
				
			||||||
 | 
					#define REG_LNA                  0x0c
 | 
				
			||||||
 | 
					#define REG_FIFO_ADDR_PTR        0x0d
 | 
				
			||||||
 | 
					#define REG_FIFO_TX_BASE_ADDR    0x0e
 | 
				
			||||||
 | 
					#define REG_FIFO_RX_BASE_ADDR    0x0f
 | 
				
			||||||
 | 
					#define REG_FIFO_RX_CURRENT_ADDR 0x10
 | 
				
			||||||
 | 
					#define REG_IRQ_FLAGS            0x12
 | 
				
			||||||
 | 
					#define REG_RX_NB_BYTES          0x13
 | 
				
			||||||
 | 
					#define REG_PKT_SNR_VALUE        0x19
 | 
				
			||||||
 | 
					#define REG_PKT_RSSI_VALUE       0x1a
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_1       0x1d
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_2       0x1e
 | 
				
			||||||
 | 
					#define REG_PREAMBLE_MSB         0x20
 | 
				
			||||||
 | 
					#define REG_PREAMBLE_LSB         0x21
 | 
				
			||||||
 | 
					#define REG_PAYLOAD_LENGTH       0x22
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_3       0x26
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_MSB       0x28
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_MID       0x29
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_LSB       0x2a
 | 
				
			||||||
 | 
					#define REG_RSSI_WIDEBAND        0x2c
 | 
				
			||||||
 | 
					#define REG_DETECTION_OPTIMIZE   0x31
 | 
				
			||||||
 | 
					#define REG_DETECTION_THRESHOLD  0x37
 | 
				
			||||||
 | 
					#define REG_SYNC_WORD            0x39
 | 
				
			||||||
 | 
					#define REG_DIO_MAPPING_1        0x40
 | 
				
			||||||
 | 
					#define REG_VERSION              0x42
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// modes
 | 
				
			||||||
 | 
					#define MODE_LONG_RANGE_MODE     0x80
 | 
				
			||||||
 | 
					#define MODE_SLEEP               0x00
 | 
				
			||||||
 | 
					#define MODE_STDBY               0x01
 | 
				
			||||||
 | 
					#define MODE_TX                  0x03
 | 
				
			||||||
 | 
					#define MODE_RX_CONTINUOUS       0x05
 | 
				
			||||||
 | 
					#define MODE_RX_SINGLE           0x06
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PA config
 | 
				
			||||||
 | 
					#define PA_BOOST                 0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IRQ masks
 | 
				
			||||||
 | 
					#define IRQ_TX_DONE_MASK           0x08
 | 
				
			||||||
 | 
					#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
 | 
				
			||||||
 | 
					#define IRQ_RX_DONE_MASK           0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_PKT_LENGTH           255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LoRaClass::LoRaClass() :
 | 
				
			||||||
 | 
					  _spiSettings(8E6, MSBFIRST, SPI_MODE0),
 | 
				
			||||||
 | 
					  _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
 | 
				
			||||||
 | 
					  _frequency(0),
 | 
				
			||||||
 | 
					  _packetIndex(0),
 | 
				
			||||||
 | 
					  _implicitHeaderMode(0),
 | 
				
			||||||
 | 
					  _onReceive(NULL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // overide Stream timeout value
 | 
				
			||||||
 | 
					  setTimeout(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::begin(long frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // setup pins
 | 
				
			||||||
 | 
					  pinMode(_ss, OUTPUT);
 | 
				
			||||||
 | 
					  // set SS high
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (_reset != -1) {
 | 
				
			||||||
 | 
					    pinMode(_reset, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // perform reset
 | 
				
			||||||
 | 
					    digitalWrite(_reset, LOW);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					    digitalWrite(_reset, HIGH);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // start SPI
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check version
 | 
				
			||||||
 | 
					  uint8_t version = readRegister(REG_VERSION);
 | 
				
			||||||
 | 
					  if (version != 0x12) {
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set frequency
 | 
				
			||||||
 | 
					  setFrequency(frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set base addresses
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set LNA boost
 | 
				
			||||||
 | 
					  writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set auto AGC
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_3, 0x04);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set output power to 17 dBm
 | 
				
			||||||
 | 
					  setTxPower(17);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::end()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // stop SPI
 | 
				
			||||||
 | 
					  SPI.end();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::beginPacket(int implicitHeader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (implicitHeader) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // reset FIFO address and paload length
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_ADDR_PTR, 0);
 | 
				
			||||||
 | 
					  writeRegister(REG_PAYLOAD_LENGTH, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::endPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in TX mode
 | 
				
			||||||
 | 
					  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // wait for TX done
 | 
				
			||||||
 | 
					  while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) {
 | 
				
			||||||
 | 
					    yield();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // clear IRQ's
 | 
				
			||||||
 | 
					  writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::parsePacket(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int packetLength = 0;
 | 
				
			||||||
 | 
					  int irqFlags = readRegister(REG_IRQ_FLAGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (size > 0) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // clear IRQ's
 | 
				
			||||||
 | 
					  writeRegister(REG_IRQ_FLAGS, irqFlags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
 | 
				
			||||||
 | 
					    // received a packet
 | 
				
			||||||
 | 
					    _packetIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // read packet length
 | 
				
			||||||
 | 
					    if (_implicitHeaderMode) {
 | 
				
			||||||
 | 
					      packetLength = readRegister(REG_PAYLOAD_LENGTH);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      packetLength = readRegister(REG_RX_NB_BYTES);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set FIFO address to current RX address
 | 
				
			||||||
 | 
					    writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // put in standby mode
 | 
				
			||||||
 | 
					    idle();
 | 
				
			||||||
 | 
					  } else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
 | 
				
			||||||
 | 
					    // not currently in RX mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // reset FIFO address
 | 
				
			||||||
 | 
					    writeRegister(REG_FIFO_ADDR_PTR, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // put in single RX mode
 | 
				
			||||||
 | 
					    writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return packetLength;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::packetRssi()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < 868E6 ? 164 : 157));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float LoRaClass::packetSnr()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long LoRaClass::packetFrequencyError()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t freqError = 0;
 | 
				
			||||||
 | 
					  freqError = static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MSB) & B111);
 | 
				
			||||||
 | 
					  freqError <<= 8L;
 | 
				
			||||||
 | 
					  freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MID));
 | 
				
			||||||
 | 
					  freqError <<= 8L;
 | 
				
			||||||
 | 
					  freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_LSB));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (readRegister(REG_FREQ_ERROR_MSB) & B1000) { // Sign bit is on
 | 
				
			||||||
 | 
					     freqError -= 524288; // B1000'0000'0000'0000'0000
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const float fXtal = 32E6; // FXOSC: crystal oscillator (XTAL) frequency (2.5. Chip Specification, p. 14)
 | 
				
			||||||
 | 
					  const float fError = ((static_cast<float>(freqError) * (1L << 24)) / fXtal) * (getSignalBandwidth() / 500000.0f); // p. 37
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return static_cast<long>(fError);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t LoRaClass::write(uint8_t byte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return write(&byte, sizeof(byte));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t LoRaClass::write(const uint8_t *buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int currentLength = readRegister(REG_PAYLOAD_LENGTH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check size
 | 
				
			||||||
 | 
					  if ((currentLength + size) > MAX_PKT_LENGTH) {
 | 
				
			||||||
 | 
					    size = MAX_PKT_LENGTH - currentLength;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // write data
 | 
				
			||||||
 | 
					  for (size_t i = 0; i < size; i++) {
 | 
				
			||||||
 | 
					    writeRegister(REG_FIFO, buffer[i]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // update length
 | 
				
			||||||
 | 
					  writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::available()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::read()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _packetIndex++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return readRegister(REG_FIFO);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int LoRaClass::peek()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // store current FIFO address
 | 
				
			||||||
 | 
					  int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // read
 | 
				
			||||||
 | 
					  uint8_t b = readRegister(REG_FIFO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // restore FIFO address
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::flush()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::onReceive(void(*callback)(int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _onReceive = callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (callback) {
 | 
				
			||||||
 | 
					    pinMode(_dio0, INPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_DIO_MAPPING_1, 0x00);
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    detachInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::receive(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (size > 0) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::idle()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::sleep()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setTxPower(int level, int outputPin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (PA_OUTPUT_RFO_PIN == outputPin) {
 | 
				
			||||||
 | 
					    // RFO
 | 
				
			||||||
 | 
					    if (level < 0) {
 | 
				
			||||||
 | 
					      level = 0;
 | 
				
			||||||
 | 
					    } else if (level > 14) {
 | 
				
			||||||
 | 
					      level = 14;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_PA_CONFIG, 0x70 | level);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    // PA BOOST
 | 
				
			||||||
 | 
					    if (level < 2) {
 | 
				
			||||||
 | 
					      level = 2;
 | 
				
			||||||
 | 
					    } else if (level > 17) {
 | 
				
			||||||
 | 
					      level = 17;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setFrequency(long frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _frequency = frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long LoRaClass::getFrequency() {
 | 
				
			||||||
 | 
					  uint8_t msb = readRegister(REG_FRF_MSB);
 | 
				
			||||||
 | 
					  uint8_t mid = readRegister(REG_FRF_MID);
 | 
				
			||||||
 | 
					  uint8_t lsb = readRegister(REG_FRF_LSB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64_t frf = msb << 16 | mid << 8 | lsb;
 | 
				
			||||||
 | 
					  long frequency = (uint64_t)(frf*32000000) >> 19;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return frequency;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setSpreadingFactor(int sf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (sf < 6) {
 | 
				
			||||||
 | 
					    sf = 6;
 | 
				
			||||||
 | 
					  } else if (sf > 12) {
 | 
				
			||||||
 | 
					    sf = 12;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (sf == 6) {
 | 
				
			||||||
 | 
					    writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
 | 
				
			||||||
 | 
					    writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
 | 
				
			||||||
 | 
					    writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long LoRaClass::getSignalBandwidth()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  byte bw = (readRegister(REG_MODEM_CONFIG_1) >> 4);
 | 
				
			||||||
 | 
					  switch (bw) {
 | 
				
			||||||
 | 
					    case 0: return 7.8E3;
 | 
				
			||||||
 | 
					    case 1: return 10.4E3; 
 | 
				
			||||||
 | 
					    case 2: return 15.6E3; 
 | 
				
			||||||
 | 
					    case 3: return 20.8E3; 
 | 
				
			||||||
 | 
					    case 4: return 31.25E3; 
 | 
				
			||||||
 | 
					    case 5: return 41.7E3; 
 | 
				
			||||||
 | 
					    case 6: return 62.5E3; 
 | 
				
			||||||
 | 
					    case 7: return 125E3; 
 | 
				
			||||||
 | 
					    case 8: return 250E3; 
 | 
				
			||||||
 | 
					    case 9: return 500E3; 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setSignalBandwidth(long sbw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int bw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (sbw <= 7.8E3) {
 | 
				
			||||||
 | 
					    bw = 0;
 | 
				
			||||||
 | 
					  } else if (sbw <= 10.4E3) {
 | 
				
			||||||
 | 
					    bw = 1;
 | 
				
			||||||
 | 
					  } else if (sbw <= 15.6E3) {
 | 
				
			||||||
 | 
					    bw = 2;
 | 
				
			||||||
 | 
					  } else if (sbw <= 20.8E3) {
 | 
				
			||||||
 | 
					    bw = 3;
 | 
				
			||||||
 | 
					  } else if (sbw <= 31.25E3) {
 | 
				
			||||||
 | 
					    bw = 4;
 | 
				
			||||||
 | 
					  } else if (sbw <= 41.7E3) {
 | 
				
			||||||
 | 
					    bw = 5;
 | 
				
			||||||
 | 
					  } else if (sbw <= 62.5E3) {
 | 
				
			||||||
 | 
					    bw = 6;
 | 
				
			||||||
 | 
					  } else if (sbw <= 125E3) {
 | 
				
			||||||
 | 
					    bw = 7;
 | 
				
			||||||
 | 
					  } else if (sbw <= 250E3) {
 | 
				
			||||||
 | 
					    bw = 8;
 | 
				
			||||||
 | 
					  } else /*if (sbw <= 250E3)*/ {
 | 
				
			||||||
 | 
					    bw = 9;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setCodingRate4(int denominator)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (denominator < 5) {
 | 
				
			||||||
 | 
					    denominator = 5;
 | 
				
			||||||
 | 
					  } else if (denominator > 8) {
 | 
				
			||||||
 | 
					    denominator = 8;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int cr = denominator - 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setPreambleLength(long length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8));
 | 
				
			||||||
 | 
					  writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setSyncWord(int sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_SYNC_WORD, sw);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::enableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::disableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte LoRaClass::random()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return readRegister(REG_RSSI_WIDEBAND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setPins(int ss, int reset, int dio0)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _ss = ss;
 | 
				
			||||||
 | 
					  _reset = reset;
 | 
				
			||||||
 | 
					  _dio0 = dio0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::setSPIFrequency(uint32_t frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::dumpRegisters(Stream& out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (int i = 0; i < 128; i++) {
 | 
				
			||||||
 | 
					    out.print("0x");
 | 
				
			||||||
 | 
					    out.print(i, HEX);
 | 
				
			||||||
 | 
					    out.print(": 0x");
 | 
				
			||||||
 | 
					    out.println(readRegister(i), HEX);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::explicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::implicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::handleDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int irqFlags = readRegister(REG_IRQ_FLAGS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // clear IRQ's
 | 
				
			||||||
 | 
					  writeRegister(REG_IRQ_FLAGS, irqFlags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
 | 
				
			||||||
 | 
					    // received a packet
 | 
				
			||||||
 | 
					    _packetIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // read packet length
 | 
				
			||||||
 | 
					    int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH) : readRegister(REG_RX_NB_BYTES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set FIFO address to current RX address
 | 
				
			||||||
 | 
					    writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_onReceive) {
 | 
				
			||||||
 | 
					      _onReceive(packetLength);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // reset FIFO address
 | 
				
			||||||
 | 
					    writeRegister(REG_FIFO_ADDR_PTR, 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t LoRaClass::readRegister(uint8_t address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return singleTransfer(address & 0x7f, 0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::writeRegister(uint8_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  singleTransfer(address | 0x80, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					  SPI.transfer(address);
 | 
				
			||||||
 | 
					  response = SPI.transfer(value);
 | 
				
			||||||
 | 
					  SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return response;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void LoRaClass::onDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  LoRa.handleDio0Rise();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LoRaClass LoRa;
 | 
				
			||||||
							
								
								
									
										96
									
								
								LoRa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								LoRa.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LORA_H
 | 
				
			||||||
 | 
					#define LORA_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_SS_PIN    10
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_RESET_PIN 9
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_DIO0_PIN  2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PA_OUTPUT_RFO_PIN      0
 | 
				
			||||||
 | 
					#define PA_OUTPUT_PA_BOOST_PIN 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoRaClass : public Stream {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  LoRaClass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int begin(long frequency);
 | 
				
			||||||
 | 
					  void end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int beginPacket(int implicitHeader = false);
 | 
				
			||||||
 | 
					  int endPacket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int parsePacket(int size = 0);
 | 
				
			||||||
 | 
					  int packetRssi();
 | 
				
			||||||
 | 
					  float packetSnr();
 | 
				
			||||||
 | 
					  long packetFrequencyError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Print
 | 
				
			||||||
 | 
					  virtual size_t write(uint8_t byte);
 | 
				
			||||||
 | 
					  virtual size_t write(const uint8_t *buffer, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Stream
 | 
				
			||||||
 | 
					  virtual int available();
 | 
				
			||||||
 | 
					  virtual int read();
 | 
				
			||||||
 | 
					  virtual int peek();
 | 
				
			||||||
 | 
					  virtual void flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void onReceive(void(*callback)(int));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void receive(int size = 0);
 | 
				
			||||||
 | 
					  void idle();
 | 
				
			||||||
 | 
					  void sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					  long getFrequency();
 | 
				
			||||||
 | 
					  void setFrequency(long frequency);
 | 
				
			||||||
 | 
					  void setSpreadingFactor(int sf);
 | 
				
			||||||
 | 
					  long getSignalBandwidth();
 | 
				
			||||||
 | 
					  void setSignalBandwidth(long sbw);
 | 
				
			||||||
 | 
					  void setCodingRate4(int denominator);
 | 
				
			||||||
 | 
					  void setPreambleLength(long length);
 | 
				
			||||||
 | 
					  void setSyncWord(int sw);
 | 
				
			||||||
 | 
					  void enableCrc();
 | 
				
			||||||
 | 
					  void disableCrc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // deprecated
 | 
				
			||||||
 | 
					  void crc() { enableCrc(); }
 | 
				
			||||||
 | 
					  void noCrc() { disableCrc(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte random();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN);
 | 
				
			||||||
 | 
					  void setSPIFrequency(uint32_t frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void dumpRegisters(Stream& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  void explicitHeaderMode();
 | 
				
			||||||
 | 
					  void implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void handleDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t readRegister(uint8_t address);
 | 
				
			||||||
 | 
					  void writeRegister(uint8_t address, uint8_t value);
 | 
				
			||||||
 | 
					  uint8_t singleTransfer(uint8_t address, uint8_t value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static void onDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  SPISettings _spiSettings;
 | 
				
			||||||
 | 
					  int _ss;
 | 
				
			||||||
 | 
					  int _reset;
 | 
				
			||||||
 | 
					  int _dio0;
 | 
				
			||||||
 | 
					  long _frequency;
 | 
				
			||||||
 | 
					  int _packetIndex;
 | 
				
			||||||
 | 
					  int _implicitHeaderMode;
 | 
				
			||||||
 | 
					  void (*_onReceive)(int);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern LoRaClass LoRa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										311
									
								
								RNode_Firmware.ino
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								RNode_Firmware.ino
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,311 @@
 | 
				
			|||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					#include <LoRa.h>
 | 
				
			||||||
 | 
					#include "Config.h"
 | 
				
			||||||
 | 
					#include "Framing.h"
 | 
				
			||||||
 | 
					#include "Utilities.cpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setup() {
 | 
				
			||||||
 | 
					  // Seed the PRNG
 | 
				
			||||||
 | 
					  randomSeed(analogRead(0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Initialise serial communication
 | 
				
			||||||
 | 
					  Serial.begin(serial_baudrate);
 | 
				
			||||||
 | 
					  while (!Serial);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Configure input and output pins
 | 
				
			||||||
 | 
					  pinMode(pin_led_rx, OUTPUT);
 | 
				
			||||||
 | 
					  pinMode(pin_led_tx, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set up buffers
 | 
				
			||||||
 | 
					  memset(pbuf, 0, sizeof(pbuf));
 | 
				
			||||||
 | 
					  memset(sbuf, 0, sizeof(sbuf));
 | 
				
			||||||
 | 
					  memset(cbuf, 0, sizeof(cbuf));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Set chip select, reset and interrupt
 | 
				
			||||||
 | 
					  // pins for the LoRa module
 | 
				
			||||||
 | 
					  LoRa.setPins(pin_cs, pin_reset, pin_dio);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool startRadio() {
 | 
				
			||||||
 | 
					  update_radio_lock();
 | 
				
			||||||
 | 
					  if (!radio_online) {
 | 
				
			||||||
 | 
					    if (!radio_locked) {
 | 
				
			||||||
 | 
					      if (!LoRa.begin(lora_freq)) {
 | 
				
			||||||
 | 
					        // The radio could not be started.
 | 
				
			||||||
 | 
					        // Indicate this failure over both the
 | 
				
			||||||
 | 
					        // serial port and with the onboard LEDs
 | 
				
			||||||
 | 
					        kiss_indicate_error(ERROR_INITRADIO);
 | 
				
			||||||
 | 
					        led_indicate_error(0);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        radio_online = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setTXPower();
 | 
				
			||||||
 | 
					        setBandwidth();
 | 
				
			||||||
 | 
					        setSpreadingFactor();
 | 
				
			||||||
 | 
					        getFrequency();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LoRa.enableCrc();
 | 
				
			||||||
 | 
					        LoRa.onReceive(receiveCallback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LoRa.receive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Flash an info pattern to indicate
 | 
				
			||||||
 | 
					        // that the radio is now on
 | 
				
			||||||
 | 
					        led_indicate_info(3);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      // Flash a warning pattern to indicate
 | 
				
			||||||
 | 
					      // that the radio was locked, and thus
 | 
				
			||||||
 | 
					      // not started
 | 
				
			||||||
 | 
					      led_indicate_warning(3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    // If radio is already on, we silently
 | 
				
			||||||
 | 
					    // ignore the request.
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void stopRadio() {
 | 
				
			||||||
 | 
					  LoRa.end();
 | 
				
			||||||
 | 
					  radio_online = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void update_radio_lock() {
 | 
				
			||||||
 | 
					  if (lora_freq != 0 && lora_bw != 0 && lora_txp != 0xFF && lora_sf != 0) {
 | 
				
			||||||
 | 
					    radio_locked = false;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    radio_locked = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void receiveCallback(int packet_size) {
 | 
				
			||||||
 | 
					  led_rx_on();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t header   = LoRa.read(); packet_size--;
 | 
				
			||||||
 | 
					  uint8_t sequence = packetSequence(header);
 | 
				
			||||||
 | 
					  bool    ready    = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (isSplitPacket(header) && seq == SEQ_UNSET) {
 | 
				
			||||||
 | 
					    // This is the first part of a split
 | 
				
			||||||
 | 
					    // packet, so we set the seq variable
 | 
				
			||||||
 | 
					    // and add the data to the buffer
 | 
				
			||||||
 | 
					    read_len = 0;
 | 
				
			||||||
 | 
					    seq = sequence;
 | 
				
			||||||
 | 
					    last_rssi = LoRa.packetRssi();
 | 
				
			||||||
 | 
					    getPacketData(packet_size);
 | 
				
			||||||
 | 
					  } else if (isSplitPacket(header) && seq == sequence) {
 | 
				
			||||||
 | 
					    // This is the second part of a split
 | 
				
			||||||
 | 
					    // packet, so we add it to the buffer
 | 
				
			||||||
 | 
					    // and set the ready flag.
 | 
				
			||||||
 | 
					    last_rssi = (last_rssi+LoRa.packetRssi())/2;
 | 
				
			||||||
 | 
					    getPacketData(packet_size);
 | 
				
			||||||
 | 
					    seq = SEQ_UNSET;
 | 
				
			||||||
 | 
					    ready = true;
 | 
				
			||||||
 | 
					  } else if (isSplitPacket(header) && seq != sequence) {
 | 
				
			||||||
 | 
					    // This split packet does not carry the
 | 
				
			||||||
 | 
					    // same sequence id, so we must assume
 | 
				
			||||||
 | 
					    // that we are seeing the first part of
 | 
				
			||||||
 | 
					    // a new split packet.
 | 
				
			||||||
 | 
					    read_len = 0;
 | 
				
			||||||
 | 
					    seq = sequence;
 | 
				
			||||||
 | 
					    last_rssi = LoRa.packetRssi();
 | 
				
			||||||
 | 
					    getPacketData(packet_size);
 | 
				
			||||||
 | 
					  } else if (!isSplitPacket(header)) {
 | 
				
			||||||
 | 
					    // This is not a split packet, so we
 | 
				
			||||||
 | 
					    // just read it and set the ready
 | 
				
			||||||
 | 
					    // flag to true.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (seq != SEQ_UNSET) {
 | 
				
			||||||
 | 
					      // If we already had part of a split
 | 
				
			||||||
 | 
					      // packet in the buffer, we clear it.
 | 
				
			||||||
 | 
					      read_len = 0;
 | 
				
			||||||
 | 
					      seq = SEQ_UNSET;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    last_rssi = LoRa.packetRssi();
 | 
				
			||||||
 | 
					    getPacketData(packet_size);
 | 
				
			||||||
 | 
					    ready = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (ready) {
 | 
				
			||||||
 | 
					    // We first signal the RSSI of the
 | 
				
			||||||
 | 
					    // recieved packet to the host.
 | 
				
			||||||
 | 
					    Serial.write(FEND);
 | 
				
			||||||
 | 
					    Serial.write(CMD_STAT_RSSI);
 | 
				
			||||||
 | 
					    Serial.write((uint8_t)(last_rssi-rssi_offset));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // And then write the entire packet
 | 
				
			||||||
 | 
					    Serial.write(FEND);
 | 
				
			||||||
 | 
					    Serial.write(CMD_DATA);
 | 
				
			||||||
 | 
					    for (int i = 0; i < read_len; i++) {
 | 
				
			||||||
 | 
					      uint8_t byte = pbuf[i];
 | 
				
			||||||
 | 
					      if (byte == FEND) { Serial.write(FESC); byte = TFEND; }
 | 
				
			||||||
 | 
					      if (byte == FESC) { Serial.write(FESC); byte = TFESC; }
 | 
				
			||||||
 | 
					      Serial.write(byte);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Serial.write(FEND);
 | 
				
			||||||
 | 
					    read_len = 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  led_rx_off();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void transmit(size_t size) {
 | 
				
			||||||
 | 
					  if (radio_online) {
 | 
				
			||||||
 | 
					    led_tx_on();
 | 
				
			||||||
 | 
					    size_t  written = 0;
 | 
				
			||||||
 | 
					    uint8_t header  = random(256) & 0xF0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (size > SINGLE_MTU - HEADER_L) {
 | 
				
			||||||
 | 
					      header = header | FLAG_SPLIT;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LoRa.beginPacket();
 | 
				
			||||||
 | 
					    LoRa.write(header); written++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (size_t i; i < size; i++) {
 | 
				
			||||||
 | 
					      LoRa.write(sbuf[i]);
 | 
				
			||||||
 | 
					      written++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (written == 255) {
 | 
				
			||||||
 | 
					        LoRa.endPacket();
 | 
				
			||||||
 | 
					        LoRa.beginPacket();
 | 
				
			||||||
 | 
					        LoRa.write(header);
 | 
				
			||||||
 | 
					        written = 1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LoRa.endPacket();
 | 
				
			||||||
 | 
					    led_tx_off();
 | 
				
			||||||
 | 
					    LoRa.receive();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    kiss_indicate_error(ERROR_TXFAILED);
 | 
				
			||||||
 | 
					    led_indicate_error(5);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void serialCallback(uint8_t sbyte) {
 | 
				
			||||||
 | 
					  if (IN_FRAME && sbyte == FEND && command == CMD_DATA) {
 | 
				
			||||||
 | 
					    IN_FRAME = false;
 | 
				
			||||||
 | 
					    transmit(frame_len);
 | 
				
			||||||
 | 
					  } else if (sbyte == FEND) {
 | 
				
			||||||
 | 
					    IN_FRAME = true;
 | 
				
			||||||
 | 
					    command = CMD_UNKNOWN;
 | 
				
			||||||
 | 
					    frame_len = 0;
 | 
				
			||||||
 | 
					  } else if (IN_FRAME && frame_len < MTU) {
 | 
				
			||||||
 | 
					    // Have a look at the command byte first
 | 
				
			||||||
 | 
					    if (frame_len == 0 && command == CMD_UNKNOWN) {
 | 
				
			||||||
 | 
					        command = sbyte;
 | 
				
			||||||
 | 
					    } else if (command == CMD_DATA) {
 | 
				
			||||||
 | 
					        if (sbyte == FESC) {
 | 
				
			||||||
 | 
					            ESCAPE = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (ESCAPE) {
 | 
				
			||||||
 | 
					                if (sbyte == TFEND) sbyte = FEND;
 | 
				
			||||||
 | 
					                if (sbyte == TFESC) sbyte = FESC;
 | 
				
			||||||
 | 
					                ESCAPE = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            sbuf[frame_len++] = sbyte;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if (command == CMD_FREQUENCY) {
 | 
				
			||||||
 | 
					      if (sbyte == FESC) {
 | 
				
			||||||
 | 
					            ESCAPE = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (ESCAPE) {
 | 
				
			||||||
 | 
					                if (sbyte == TFEND) sbyte = FEND;
 | 
				
			||||||
 | 
					                if (sbyte == TFESC) sbyte = FESC;
 | 
				
			||||||
 | 
					                ESCAPE = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            cbuf[frame_len++] = sbyte;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (frame_len == 4) {
 | 
				
			||||||
 | 
					          uint32_t freq = (uint32_t)cbuf[0] << 24 | (uint32_t)cbuf[1] << 16 | (uint32_t)cbuf[2] << 8 | (uint32_t)cbuf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (freq == 0) {
 | 
				
			||||||
 | 
					            kiss_indicate_frequency();
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            lora_freq = freq;
 | 
				
			||||||
 | 
					            setFrequency();
 | 
				
			||||||
 | 
					            kiss_indicate_frequency();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if (command == CMD_BANDWIDTH) {
 | 
				
			||||||
 | 
					      if (sbyte == FESC) {
 | 
				
			||||||
 | 
					            ESCAPE = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (ESCAPE) {
 | 
				
			||||||
 | 
					                if (sbyte == TFEND) sbyte = FEND;
 | 
				
			||||||
 | 
					                if (sbyte == TFESC) sbyte = FESC;
 | 
				
			||||||
 | 
					                ESCAPE = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            cbuf[frame_len++] = sbyte;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (frame_len == 4) {
 | 
				
			||||||
 | 
					          uint32_t bw = (uint32_t)cbuf[0] << 24 | (uint32_t)cbuf[1] << 16 | (uint32_t)cbuf[2] << 8 | (uint32_t)cbuf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (bw == 0) {
 | 
				
			||||||
 | 
					            kiss_indicate_bandwidth();
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            lora_bw = bw;
 | 
				
			||||||
 | 
					            setBandwidth();
 | 
				
			||||||
 | 
					            kiss_indicate_bandwidth();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if (command == CMD_TXPOWER) {
 | 
				
			||||||
 | 
					      if (sbyte == 0xFF) {
 | 
				
			||||||
 | 
					        kiss_indicate_txpower();
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        int txp = sbyte;
 | 
				
			||||||
 | 
					        if (txp > 17) txp = 17;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lora_txp = txp;
 | 
				
			||||||
 | 
					        setTXPower();
 | 
				
			||||||
 | 
					        kiss_indicate_txpower();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if (command == CMD_SF) {
 | 
				
			||||||
 | 
					      if (sbyte == 0xFF) {
 | 
				
			||||||
 | 
					        kiss_indicate_spreadingfactor();
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        int sf = sbyte;
 | 
				
			||||||
 | 
					        if (sf < 7) sf = 7;
 | 
				
			||||||
 | 
					        if (sf > 12) sf = 12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lora_sf = sf;
 | 
				
			||||||
 | 
					        setSpreadingFactor();
 | 
				
			||||||
 | 
					        kiss_indicate_spreadingfactor();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if (command == CMD_RADIO_STATE) {
 | 
				
			||||||
 | 
					      if (sbyte == 0xFF) {
 | 
				
			||||||
 | 
					        kiss_indicate_radiostate();
 | 
				
			||||||
 | 
					      } else if (sbyte == 0x00) {
 | 
				
			||||||
 | 
					        stopRadio();
 | 
				
			||||||
 | 
					        kiss_indicate_radiostate();
 | 
				
			||||||
 | 
					      } else if (sbyte == 0x01) {
 | 
				
			||||||
 | 
					        startRadio();
 | 
				
			||||||
 | 
					        kiss_indicate_radiostate();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } else if (command == CMD_STAT_RX) {
 | 
				
			||||||
 | 
					      kiss_indicate_stat_rx();
 | 
				
			||||||
 | 
					    } else if (command == CMD_STAT_TX) {
 | 
				
			||||||
 | 
					      kiss_indicate_stat_tx();
 | 
				
			||||||
 | 
					    } else if (command == CMD_STAT_RSSI) {
 | 
				
			||||||
 | 
					      kiss_indicate_stat_rssi();
 | 
				
			||||||
 | 
					    } else if (command == CMD_RADIO_LOCK) {
 | 
				
			||||||
 | 
					      update_radio_lock();
 | 
				
			||||||
 | 
					      kiss_indicate_radio_lock();
 | 
				
			||||||
 | 
					    } else if (command == CMD_BLINK) {
 | 
				
			||||||
 | 
					      led_indicate_info(sbyte);
 | 
				
			||||||
 | 
					    } else if (command == CMD_RANDOM) {
 | 
				
			||||||
 | 
					      kiss_indicate_random(getRandom());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void loop() {
 | 
				
			||||||
 | 
					  if (Serial.available()) {
 | 
				
			||||||
 | 
					    char sbyte = Serial.read();
 | 
				
			||||||
 | 
					    serialCallback(sbyte);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										199
									
								
								Utilities.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								Utilities.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
				
			|||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <LoRa.h>
 | 
				
			||||||
 | 
					#include "Config.h"
 | 
				
			||||||
 | 
					#include "Framing.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void led_rx_on()  { digitalWrite(pin_led_rx, HIGH); }
 | 
				
			||||||
 | 
					void led_rx_off() {	digitalWrite(pin_led_rx, LOW); }
 | 
				
			||||||
 | 
					void led_tx_on()  { digitalWrite(pin_led_tx, HIGH); }
 | 
				
			||||||
 | 
					void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void led_indicate_error(int cycles) {
 | 
				
			||||||
 | 
						bool forever = (cycles == 0) ? true : false;
 | 
				
			||||||
 | 
						cycles = forever ? 1 : cycles;
 | 
				
			||||||
 | 
						while(cycles > 0) {
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_rx, HIGH);
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_tx, LOW);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_rx, LOW);
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_tx, HIGH);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        if (!forever) cycles--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    digitalWrite(pin_led_rx, LOW);
 | 
				
			||||||
 | 
					    digitalWrite(pin_led_tx, LOW);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void led_indicate_warning(int cycles) {
 | 
				
			||||||
 | 
						bool forever = (cycles == 0) ? true : false;
 | 
				
			||||||
 | 
						cycles = forever ? 1 : cycles;
 | 
				
			||||||
 | 
						digitalWrite(pin_led_tx, HIGH);
 | 
				
			||||||
 | 
						while(cycles > 0) {
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_tx, LOW);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_tx, HIGH);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        if (!forever) cycles--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    digitalWrite(pin_led_tx, LOW);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void led_indicate_info(int cycles) {
 | 
				
			||||||
 | 
						bool forever = (cycles == 0) ? true : false;
 | 
				
			||||||
 | 
						cycles = forever ? 1 : cycles;
 | 
				
			||||||
 | 
						while(cycles > 0) {
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_rx, LOW);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        digitalWrite(pin_led_rx, HIGH);
 | 
				
			||||||
 | 
					        delay(100);
 | 
				
			||||||
 | 
					        if (!forever) cycles--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    digitalWrite(pin_led_rx, LOW);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_error(uint8_t error_code) {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_ERROR);
 | 
				
			||||||
 | 
						Serial.write(error_code);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_radiostate() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_RADIO_STATE);
 | 
				
			||||||
 | 
						Serial.write(radio_online);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_stat_rx() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_STAT_RX);
 | 
				
			||||||
 | 
						Serial.write(stat_rx>>24);
 | 
				
			||||||
 | 
						Serial.write(stat_rx>>16);
 | 
				
			||||||
 | 
						Serial.write(stat_rx>>8);
 | 
				
			||||||
 | 
						Serial.write(stat_rx);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_stat_tx() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_STAT_TX);
 | 
				
			||||||
 | 
						Serial.write(stat_tx>>24);
 | 
				
			||||||
 | 
						Serial.write(stat_tx>>16);
 | 
				
			||||||
 | 
						Serial.write(stat_tx>>8);
 | 
				
			||||||
 | 
						Serial.write(stat_tx);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_stat_rssi() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_STAT_RSSI);
 | 
				
			||||||
 | 
						Serial.write((uint8_t)last_rssi+rssi_offset);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_radio_lock() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_RADIO_LOCK);
 | 
				
			||||||
 | 
						Serial.write(radio_locked);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_spreadingfactor() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_SF);
 | 
				
			||||||
 | 
						Serial.write((uint8_t)lora_sf);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_txpower() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_TXPOWER);
 | 
				
			||||||
 | 
						Serial.write((uint8_t)lora_txp);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_bandwidth() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_BANDWIDTH);
 | 
				
			||||||
 | 
						Serial.write(lora_bw>>24);
 | 
				
			||||||
 | 
						Serial.write(lora_bw>>16);
 | 
				
			||||||
 | 
						Serial.write(lora_bw>>8);
 | 
				
			||||||
 | 
						Serial.write(lora_bw);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_frequency() {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_FREQUENCY);
 | 
				
			||||||
 | 
						Serial.write(lora_freq>>24);
 | 
				
			||||||
 | 
						Serial.write(lora_freq>>16);
 | 
				
			||||||
 | 
						Serial.write(lora_freq>>8);
 | 
				
			||||||
 | 
						Serial.write(lora_freq);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void kiss_indicate_random(uint8_t byte) {
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
						Serial.write(CMD_RANDOM);
 | 
				
			||||||
 | 
						Serial.write(byte);
 | 
				
			||||||
 | 
						Serial.write(FEND);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool isSplitPacket(uint8_t header) {
 | 
				
			||||||
 | 
						return (header & FLAG_SPLIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t packetSequence(uint8_t header) {
 | 
				
			||||||
 | 
						return header >> 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void getPacketData(int len) {
 | 
				
			||||||
 | 
						while (len--) {
 | 
				
			||||||
 | 
							pbuf[read_len++] = LoRa.read();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setSpreadingFactor() {
 | 
				
			||||||
 | 
						if (radio_online) LoRa.setSpreadingFactor(lora_sf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setTXPower() {
 | 
				
			||||||
 | 
						if (radio_online) LoRa.setTxPower(lora_txp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void getBandwidth() {
 | 
				
			||||||
 | 
						if (radio_online) {
 | 
				
			||||||
 | 
								lora_bw = LoRa.getSignalBandwidth();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setBandwidth() {
 | 
				
			||||||
 | 
						if (radio_online) {
 | 
				
			||||||
 | 
							LoRa.setSignalBandwidth(lora_bw);
 | 
				
			||||||
 | 
							getBandwidth();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void getFrequency() {
 | 
				
			||||||
 | 
						if (radio_online) {
 | 
				
			||||||
 | 
							lora_freq = LoRa.getFrequency();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void setFrequency() {
 | 
				
			||||||
 | 
						if (radio_online) {
 | 
				
			||||||
 | 
							LoRa.setFrequency(lora_freq);
 | 
				
			||||||
 | 
							getFrequency();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t getRandom() {
 | 
				
			||||||
 | 
						if (radio_online) {
 | 
				
			||||||
 | 
							return LoRa.random();
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return 0x00;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user