moved register definitions to a different file and created higher level functions for using them; added preliminary support for 868 MHz mode, not fully working yet

This commit is contained in:
Tomer Abramovich 2020-01-23 22:25:00 +02:00
parent 77bf17967d
commit 6f9740f03f
3 changed files with 310 additions and 102 deletions

View File

@ -1,41 +1,11 @@
#if defined(FRSKYR9_SX1276_INO)
#include "iface_sx1276.h"
#define REG_IRQ_FLAGS_MASK 0x11
#define FREQ_MAP_SIZE 29
#define REG_PAYLOAD_LENGTH 0x22
// TODO the channel spacing is equal, consider calculating the new channel instead of using lookup tables (first_chan + index * step)
#define REG_FIFO_ADDR_PTR 0x0D
#define REG_FIFO_TX_BASE_ADDR 0x0E
#define REG_OP_MODE 0x01
#define REG_DETECT_OPTIMIZE 0x31
#define REG_DIO_MAPPING1 0x40
#define REG_VERSION 0x42
#define REG_MODEM_CONFIG1 0x1D
#define REG_MODEM_CONFIG2 0x1E
#define REG_MODEM_CONFIG3 0x26
#define REG_PREAMBLE_LSB 0x21
#define REG_DETECTION_THRESHOLD 0x37
#define REG_LNA 0x0C
#define REG_HOP_PERIOD 0x24
#define REG_PA_DAC 0x4D
#define REG_PA_CONFIG 0x09
#define REG_FRF_MSB 0x06
#define REG_FIFO 0x00
#define REG_OCP 0x0B
static uint32_t _freq_map[] =
static uint32_t _freq_map_915[FREQ_MAP_SIZE] =
{
914472960,
914972672,
@ -70,58 +40,74 @@ static uint32_t _freq_map[] =
0
};
static uint8_t _step = 1;
static uint32_t _freq_map_868[FREQ_MAP_SIZE] =
{
859504640,
860004352,
860504064,
861003776,
861503488,
862003200,
862502912,
863002624,
863502336,
864002048,
864501760,
865001472,
865501184,
866000896,
866500608,
867000320,
867500032,
867999744,
868499456,
868999168,
869498880,
869998592,
870498304,
870998016,
871497728,
871997440,
872497152,
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_temp( uint8_t i )
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
uint16_t chan_val=convert_channel_frsky(i)-1226;
if(i>7) chan_val|=2048; // upper channels offset
return chan_val;
}
// last two determined by _step
0,
0
};
static uint8_t _step = 1;
static uint32_t* _freq_map = _freq_map_915;
uint16_t initFrSkyR9()
{
set_rx_tx_addr(MProtocol_id_master);
if(sub_protocol == 0) // 915MHz
_freq_map = _freq_map_915;
else if(sub_protocol == 1) // 868MHz
_freq_map = _freq_map_868;
_step = 1 + (random(0xfefefefe) % 24);
_freq_map[27] = _freq_map[_step];
_freq_map[28] = _freq_map[_step+1];
SX1276_WriteReg(REG_OP_MODE, 0x80); // sleep
SX1276_WriteReg(REG_OP_MODE, 0x81); // standby
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
uint8_t buffer[2];
buffer[0] = 0x00;
buffer[1] = 0x00;
SX1276_WriteRegisterMulti(REG_DIO_MAPPING1, buffer, 2);
// uint8_t buffer[2];
// buffer[0] = 0x00;
// buffer[1] = 0x00;
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2);
uint8_t val = SX1276_ReadReg(REG_DETECT_OPTIMIZE);
val = (val & 0b11111000) | 0b00000101;
SX1276_WriteReg(REG_DETECT_OPTIMIZE, val);
// val = SX1276_ReadReg(REG_MODEM_CONFIG2);
// val = (val & 0b00011111) | 0b11000000;
// writeRegister(REG_MODEM_CONFIG2, val);
SX1276_WriteReg(REG_MODEM_CONFIG1, 0x93);
SX1276_WriteReg(REG_MODEM_CONFIG2, 0x60);
val = SX1276_ReadReg(REG_MODEM_CONFIG3);
val = (val & 0b11110011);
SX1276_WriteReg(REG_MODEM_CONFIG3, val);
SX1276_WriteReg(REG_PREAMBLE_LSB, 9);
SX1276_WriteReg(REG_DETECTION_THRESHOLD, 0x0C);
SX1276_WriteReg(REG_LNA, 0x23);
SX1276_WriteReg(REG_HOP_PERIOD, 0x00);
val = SX1276_ReadReg(REG_PA_DAC);
val = (val & 0b11111000) | 0b00000111;
SX1276_WriteReg(REG_PA_DAC, val);
SX1276_SetDetectOptimize(true, SX1276_DETECT_OPTIMIZE_SF6);
SX1276_ConfigModem1(SX1276_MODEM_CONFIG1_BW_500KHZ, SX1276_MODEM_CONFIG1_CODING_RATE_4_5, true);
SX1276_ConfigModem2(6, false, false);
SX1276_ConfigModem3(false, false);
SX1276_SetPreambleLength(9);
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
SX1276_SetLna(1, true);
SX1276_SetHopPeriod(0); // 0 = disabled, we hope frequencies manually
SX1276_SetPaDac(true);
// TODO this can probably be shorter
return 20000; // start calling FrSkyR9_callback in 20 milliseconds
@ -129,47 +115,41 @@ uint16_t initFrSkyR9()
uint16_t FrSkyR9_callback()
{
static uint16_t index = 0;
uint8_t buffer[3];
static uint16_t freq_hop_index = 0;
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
SX1276_WriteReg(REG_OP_MODE, 0x81); // STDBY
SX1276_WriteReg(REG_IRQ_FLAGS_MASK, 0xbf); // use only RxDone interrupt
//SX1276_WriteReg(SX1276_11_IRQFLAGSMASK, 0xbf); // use only RxDone interrupt
buffer[0] = 0x00;
buffer[1] = 0x00;
SX1276_WriteRegisterMulti(REG_DIO_MAPPING1, buffer, 2); // RxDone interrupt mapped to DIO0 (the rest are not used because of the REG_IRQ_FLAGS_MASK)
// uint8_t buffer[2];
// buffer[0] = 0x00;
// buffer[1] = 0x00;
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2); // RxDone interrupt mapped to DIO0 (the rest are not used because of the REG_IRQ_FLAGS_MASK)
// SX1276_WriteReg(REG_PAYLOAD_LENGTH, 13);
// SX1276_WriteReg(REG_FIFO_ADDR_PTR, 0x00);
// SX1276_WriteReg(REG_OP_MODE, 0x85); // RXCONTINUOUS
// SX1276_WriteReg(SX1276_01_OPMODE, 0x85); // RXCONTINUOUS
// delay(10); // 10 ms
// SX1276_WriteReg(REG_OP_MODE, 0x81); // STDBY
// SX1276_WriteReg(SX1276_01_OPMODE, 0x81); // STDBY
SX1276_WriteReg(REG_PA_CONFIG, 0xF0);
//SX1276_WriteReg(SX1276_09_PACONFIG, 0xF0);
uint32_t freq = _freq_map[index] / 61;
buffer[0] = (freq & (0xFF << 16)) >> 16;
buffer[1] = (freq & (0xFF << 8)) >> 8;
buffer[2] = freq & 0xFF;
SX1276_WriteRegisterMulti(REG_FRF_MSB, buffer, 3); // set current center frequency
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
// output_power: 2 dBm (17-(15-OutputPower) (if pa_boost_pin == true))
SX1276_SetPaConfig(true, 7, 0);
SX1276_SetFrequency(_freq_map[freq_hop_index]); // set current center frequency
delayMicroseconds(500);
SX1276_WriteReg(REG_PAYLOAD_LENGTH, 26);
SX1276_WriteReg(REG_FIFO_TX_BASE_ADDR, 0x00);
SX1276_WriteReg(REG_FIFO_ADDR_PTR, 0x00);
uint8_t payload[26];
payload[0] = 0x3C; // ????
payload[1] = rx_tx_addr[3]; // unique radio id
payload[2] = rx_tx_addr[2]; // unique radio id
payload[3] = index; // current channel index
payload[3] = freq_hop_index; // current channel index
payload[4] = _step; // step size and last 2 channels start index
payload[5] = RX_num; // receiver number from OpenTX
@ -223,12 +203,11 @@ uint16_t FrSkyR9_callback()
payload[24] = crc; // low byte
payload[25] = crc >> 8; // high byte
// write payload to fifo
SX1276_WriteRegisterMulti(REG_FIFO, payload, 26);
SX1276_WritePayloadToFifo(payload, 26);
index = (index + _step) % 29;
freq_hop_index = (freq_hop_index + _step) % FREQ_MAP_SIZE;
SX1276_WriteReg(REG_OP_MODE, 0x83); // TX
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
// need to clear RegIrqFlags?

View File

@ -1,4 +1,5 @@
#ifdef SX1276_INSTALLED
#include "iface_sx1276.h"
void SX1276_WriteReg(uint8_t address, uint8_t data)
{
@ -12,19 +13,21 @@ void SX1276_WriteReg(uint8_t address, uint8_t data)
uint8_t SX1276_ReadReg(uint8_t address)
{
SPI_CSN_off;
SPI_Write(address & 0b01111111);
SPI_Write(address & 0x7F);
uint8_t result = SPI_Read();
SPI_CSN_on;
return result;
}
void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t data[], uint8_t length)
void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t* data, uint8_t length)
{
SPI_CSN_off;
SPI_Write(address | 0x80); // MSB 1 = write
for(uint8_t i = 0; i < length; i++)
SPI_Write(data[i]);
SPI_CSN_on;
}
@ -35,4 +38,140 @@ uint8_t SX1276_Reset()
return 0;
}
void SX1276_SetFrequency(uint32_t frequency)
{
uint32_t f = frequency / 61;
uint8_t data[3];
data[0] = (f & (0xFF << 16)) >> 16;
data[1] = (f & (0xFF << 8)) >> 8;
data[2] = f & 0xFF;
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
}
void SX1276_SetMode(bool lora, bool low_freq_mode, uint8_t mode)
{
uint8_t data = 0x00;
if(lora)
{
data = data | (1 << 7);
data = data & ~(1 << 6);
}
else
{
data = data & ~(1 << 7);
data = data | (1 << 6);
}
if(low_freq_mode)
data = data | (1 << 3);
data = data | mode;
SX1276_WriteReg(SX1276_01_OPMODE, data);
}
void SX1276_SetDetectOptimize(bool auto_if, uint8_t detect_optimize)
{
uint8_t data = SX1276_ReadReg(SX1276_31_DETECTOPTIMIZE);
data = (data & 0b01111000) | detect_optimize;
data = data | (auto_if << 7);
SX1276_WriteReg(SX1276_31_DETECTOPTIMIZE, data);
}
void SX1276_ConfigModem1(uint8_t bandwidth, uint8_t coding_rate, bool implicit_header_mode)
{
uint8_t data = 0x00;
data = data | (bandwidth << 4);
data = data | (coding_rate << 1);
data = data | implicit_header_mode;
SX1276_WriteReg(SX1276_1D_MODEMCONFIG1, data);
}
void SX1276_ConfigModem2(uint8_t spreading_factor, bool tx_continuous_mode, bool rx_payload_crc_on)
{
uint8_t data = SX1276_ReadReg(SX1276_1E_MODEMCONFIG2);
data = data & 0b11; // preserve the last 2 bits
data = data | (spreading_factor << 4);
data = data | (tx_continuous_mode << 3);
data = data | (rx_payload_crc_on << 2);
SX1276_WriteReg(SX1276_1E_MODEMCONFIG2, data);
}
void SX1276_ConfigModem3(bool low_data_rate_optimize, bool agc_auto_on)
{
uint8_t data = SX1276_ReadReg(SX1276_26_MODEMCONFIG3);
data = data & 0b11; // preserve the last 2 bits
data = data | (low_data_rate_optimize << 3);
data = data | (agc_auto_on << 2);
SX1276_WriteReg(SX1276_26_MODEMCONFIG3, data);
}
void SX1276_SetPreambleLength(uint16_t length)
{
uint8_t data[2];
data[0] = (length >> 8) & 0xFF; // high byte
data[1] = length & 0xFF; // low byte
SX1276_WriteRegisterMulti(SX1276_20_PREAMBLEMSB, data, 2);
}
void SX1276_SetDetectionThreshold(uint8_t threshold)
{
SX1276_WriteReg(SX1276_37_DETECTIONTHRESHOLD, threshold);
}
void SX1276_SetLna(uint8_t gain, bool high_freq_lna_boost)
{
uint8_t data = SX1276_ReadReg(SX1276_0C_LNA);
data = data & 0b100; // preserve the third bit
data = data | (gain << 5);
if(high_freq_lna_boost)
data = data | 0b11;
SX1276_WriteReg(SX1276_0C_LNA, data);
}
void SX1276_SetHopPeriod(uint8_t freq_hop_period)
{
SX1276_WriteReg(SX1276_24_HOPPERIOD, freq_hop_period);
}
void SX1276_SetPaDac(bool on)
{
uint8_t data = SX1276_ReadReg(SX1276_4D_PADAC);
data = data & 0b11111000; // preserve the upper 5 bits
if(on)
data = data | 0x07;
else
data = data | 0x04;
SX1276_WriteReg(SX1276_4D_PADAC, data);
}
void SX1276_SetPaConfig(bool pa_boost_pin, uint8_t max_power, uint8_t output_power)
{
uint8_t data = 0x00;
data = data | (pa_boost_pin << 7);
data = data | (max_power << 4);
data = data | output_power;
SX1276_WriteReg(SX1276_09_PACONFIG, data);
}
void SX1276_WritePayloadToFifo(uint8_t* payload, uint8_t length)
{
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, length);
SX1276_WriteReg(SX1276_0E_FIFOTXBASEADDR, 0x00);
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
SX1276_WriteRegisterMulti(SX1276_00_FIFO, payload, length);
}
#endif

View File

@ -0,0 +1,90 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IFACE_SX1276_H_
#define _IFACE_SX1276_H_
enum
{
SX1276_00_FIFO = 0x00,
SX1276_01_OPMODE = 0x01,
SX1276_06_FRFMSB = 0x06,
SX1276_09_PACONFIG = 0x09,
SX1276_0B_OCP = 0x0B,
SX1276_0C_LNA = 0x0C,
SX1276_0D_FIFOADDRPTR = 0x0D,
SX1276_0E_FIFOTXBASEADDR = 0x0E,
SX1276_11_IRQFLAGSMASK = 0x11,
SX1276_1D_MODEMCONFIG1 = 0x1D,
SX1276_1E_MODEMCONFIG2 = 0x1E,
SX1276_20_PREAMBLEMSB = 0x20,
SX1276_22_PAYLOAD_LENGTH = 0x22,
SX1276_24_HOPPERIOD = 0x24,
SX1276_26_MODEMCONFIG3 = 0x26,
SX1276_31_DETECTOPTIMIZE = 0x31,
SX1276_37_DETECTIONTHRESHOLD = 0x37,
SX1276_40_DIOMAPPING1 = 0x40,
SX1276_42_VERSION = 0x42,
SX1276_4D_PADAC = 0x4D
};
enum
{
SX1276_OPMODE_SLEEP = 0,
SX1276_OPMODE_STDBY,
SX1276_OPMODE_FSTX,
SX1276_OPMODE_TX,
SX1276_OPMODE_FSRX,
SX1276_OPMODE_RXCONTINUOUS,
SX1276_OPMODE_RXSINGLE,
SX1276_OPMODE_CAD
};
enum
{
SX1276_DETECT_OPTIMIZE_SF7_TO_SF12 = 0x03,
SX1276_DETECT_OPTIMIZE_SF6 = 0x05
};
enum
{
SX1276_MODEM_CONFIG1_BW_7_8KHZ = 0,
SX1276_MODEM_CONFIG1_BW_10_4KHZ,
SX1276_MODEM_CONFIG1_BW_15_6KHZ,
SX1276_MODEM_CONFIG1_BW_20_8KHZ,
SX1276_MODEM_CONFIG1_BW_31_25KHZ,
SX1276_MODEM_CONFIG1_BW_41_7KHZ,
SX1276_MODEM_CONFIG1_BW_62_5KHZ,
SX1276_MODEM_CONFIG1_BW_125KHZ,
SX1276_MODEM_CONFIG1_BW_250KHZ,
SX1276_MODEM_CONFIG1_BW_500KHZ
};
enum
{
SX1276_MODEM_CONFIG1_CODING_RATE_4_5 = 1,
SX1276_MODEM_CONFIG1_CODING_RATE_4_6,
SX1276_MODEM_CONFIG1_CODING_RATE_4_7,
SX1276_MODEM_CONFIG1_CODING_RATE_4_8
};
enum
{
SX1276_MODEM_DETECTION_THRESHOLD_SF7_TO_SF12 = 0x0A,
SX1276_MODEM_DETECTION_THRESHOLD_SF6 = 0x0C,
};
#endif