mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-02-04 22:28:12 +00:00
0d8a7e46de
* Change Looptimes state => bind_counter
244 lines
7.2 KiB
C++
244 lines
7.2 KiB
C++
/*
|
|
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/>.
|
|
*/
|
|
|
|
#if defined(REDPINE_CC2500_INO)
|
|
|
|
#include "iface_cc2500.h"
|
|
|
|
#define REDPINE_LOOPTIME_FAST 25 //2.5ms
|
|
#define REDPINE_LOOPTIME_SLOW 6 //6ms
|
|
|
|
#define REDPINE_BIND 1000
|
|
#define REDPINE_PACKET_SIZE 11
|
|
#define REDPINE_FEC false // from cc2500 datasheet: The convolutional coder is a rate 1/2 code with a constraint length of m=4
|
|
#define REDPINE_NUM_HOPS 50
|
|
|
|
static void REDPINE_set_channel(uint8_t ch)
|
|
{
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
|
|
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
|
|
}
|
|
|
|
static void REDPINE_build_bind_packet()
|
|
{
|
|
memset(&packet[0], 0, REDPINE_PACKET_SIZE);
|
|
|
|
packet[0] = REDPINE_PACKET_SIZE - 1;
|
|
packet[1] = 0x03;
|
|
packet[2] = 0x01;
|
|
packet[3] = rx_tx_addr[2];
|
|
packet[4] = rx_tx_addr[3]; // Use RX_Num
|
|
uint16_t idx = ((REDPINE_BIND - bind_counter) % 10) * 5;
|
|
packet[5] = idx;
|
|
packet[6] = hopping_frequency[idx++];
|
|
packet[7] = hopping_frequency[idx++];
|
|
packet[8] = hopping_frequency[idx++];
|
|
packet[9] = hopping_frequency[idx++];
|
|
packet[10] = hopping_frequency[idx++];
|
|
// packet[11] = 0x02;
|
|
// packet[12] = RXNUM;
|
|
}
|
|
|
|
static uint16_t Redpine_Scale(uint8_t chan)
|
|
{
|
|
uint16_t chan_val=Channel_data[chan]; // -125%..+125% <=> 0..2047
|
|
if (chan_val > 2046) chan_val = 2046;
|
|
else if (chan_val < 10) chan_val = 10;
|
|
return chan_val;
|
|
}
|
|
|
|
|
|
static void REDPINE_data_frame() {
|
|
uint16_t chan[4];
|
|
|
|
memset(&packet[0], 0, REDPINE_PACKET_SIZE);
|
|
|
|
packet[0] = REDPINE_PACKET_SIZE - 1;
|
|
packet[1] = rx_tx_addr[2];
|
|
packet[2] = rx_tx_addr[3]; // Use RX_Num
|
|
|
|
chan[0] = Redpine_Scale(0);
|
|
chan[1] = Redpine_Scale(1);
|
|
chan[2] = Redpine_Scale(2);
|
|
chan[3] = Redpine_Scale(3);
|
|
|
|
packet[3] = chan[0];
|
|
packet[4] = (((chan[0] >> 8) & 0x07) | (chan[1] << 4)) | GET_FLAG(CH5_SW, 0x08);
|
|
packet[5] = ((chan[1] >> 4) & 0x7F) | GET_FLAG(CH6_SW, 0x80);
|
|
packet[6] = chan[2];
|
|
packet[7] = (((chan[2] >> 8) & 0x07) | (chan[3] << 4)) | GET_FLAG(CH7_SW, 0x08);
|
|
packet[8] = ((chan[3] >> 4) & 0x7F) | GET_FLAG(CH8_SW, 0x80);
|
|
packet[9] = GET_FLAG(CH9_SW, 0x01)
|
|
| GET_FLAG(CH10_SW, 0x02)
|
|
| GET_FLAG(CH11_SW, 0x04)
|
|
| GET_FLAG(CH12_SW, 0x08)
|
|
| GET_FLAG(CH13_SW, 0x10)
|
|
| GET_FLAG(CH14_SW, 0x20)
|
|
| GET_FLAG(CH15_SW, 0x40)
|
|
| GET_FLAG(CH16_SW, 0x80);
|
|
|
|
if (sub_protocol==0)
|
|
packet[10] = REDPINE_LOOPTIME_FAST;
|
|
else
|
|
packet[10] = REDPINE_LOOPTIME_SLOW;
|
|
}
|
|
|
|
static uint16_t ReadREDPINE()
|
|
{
|
|
if ( prev_option != option )
|
|
{ // Frequency adjust
|
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
|
prev_option = option ;
|
|
}
|
|
if(IS_BIND_IN_PROGRESS)
|
|
{
|
|
if(bind_counter == REDPINE_BIND)
|
|
REDPINE_init(0);
|
|
if(bind_counter == REDPINE_BIND/2)
|
|
REDPINE_init(1);
|
|
REDPINE_set_channel(49);
|
|
CC2500_SetTxRxMode(TX_EN);
|
|
CC2500_SetPower();
|
|
CC2500_Strobe(CC2500_SFRX);
|
|
REDPINE_build_bind_packet();
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
|
|
if(--bind_counter==0)
|
|
{
|
|
BIND_DONE;
|
|
REDPINE_init(sub_protocol);
|
|
}
|
|
return 9000;
|
|
}
|
|
else
|
|
{
|
|
CC2500_SetTxRxMode(TX_EN);
|
|
REDPINE_set_channel(hopping_frequency_no);
|
|
CC2500_SetPower();
|
|
CC2500_Strobe(CC2500_SFRX);
|
|
REDPINE_data_frame();
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
|
|
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
|
|
if (sub_protocol==0)
|
|
return REDPINE_LOOPTIME_FAST*100;
|
|
else
|
|
return REDPINE_LOOPTIME_SLOW*1000;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// register, fast 250k, slow
|
|
static const uint8_t REDPINE_init_data[][3] = {
|
|
{CC2500_00_IOCFG2, 0x06, 0x06},
|
|
{CC2500_02_IOCFG0, 0x06, 0x06},
|
|
{CC2500_03_FIFOTHR, 0x07, 0x07},
|
|
{CC2500_07_PKTCTRL1, 0x04, 0x04},
|
|
{CC2500_08_PKTCTRL0, 0x05, 0x05},
|
|
{CC2500_09_ADDR, 0x00, 0x00},
|
|
{CC2500_0B_FSCTRL1, 0x0A, 0x0A},
|
|
{CC2500_0C_FSCTRL0, 0x00, 0x00},
|
|
{CC2500_0D_FREQ2, 0x5D, 0x5c},
|
|
{CC2500_0E_FREQ1, 0x93, 0x76},
|
|
{CC2500_0F_FREQ0, 0xB1, 0x27},
|
|
{CC2500_10_MDMCFG4, 0x2D, 0x7B},
|
|
{CC2500_11_MDMCFG3, 0x3B, 0x61},
|
|
{CC2500_12_MDMCFG2, 0x73, 0x13},
|
|
#ifdef REDPINE_FEC
|
|
{CC2500_13_MDMCFG1, 0xA3, 0xA3},
|
|
#else
|
|
{CC2500_13_MDMCFG1, 0x23, 0x23},
|
|
#endif
|
|
{CC2500_14_MDMCFG0, 0x56, 0x7a}, // Chan space
|
|
{CC2500_15_DEVIATN, 0x00, 0x51},
|
|
{CC2500_17_MCSM1, 0x0c, 0x0c},
|
|
{CC2500_18_MCSM0, 0x08, 0x08}, //??? 0x18, 0x18},
|
|
{CC2500_19_FOCCFG, 0x1D, 0x16},
|
|
{CC2500_1A_BSCFG, 0x1C, 0x6c},
|
|
{CC2500_1B_AGCCTRL2, 0xC7, 0x43},
|
|
{CC2500_1C_AGCCTRL1, 0x00, 0x40},
|
|
{CC2500_1D_AGCCTRL0, 0xB0, 0x91},
|
|
{CC2500_21_FREND1, 0xB6, 0x56},
|
|
{CC2500_22_FREND0, 0x10, 0x10},
|
|
{CC2500_23_FSCAL3, 0xEA, 0xA9},
|
|
{CC2500_24_FSCAL2, 0x0A, 0x0A},
|
|
{CC2500_25_FSCAL1, 0x00, 0x00},
|
|
{CC2500_26_FSCAL0, 0x11, 0x11},
|
|
{CC2500_29_FSTEST, 0x59, 0x59},
|
|
{CC2500_2C_TEST2, 0x88, 0x88},
|
|
{CC2500_2D_TEST1, 0x31, 0x31},
|
|
{CC2500_2E_TEST0, 0x0B, 0x0B},
|
|
{CC2500_3E_PATABLE, 0xff, 0xff}
|
|
};
|
|
|
|
static void REDPINE_init(uint8_t format)
|
|
{
|
|
CC2500_Reset();
|
|
|
|
CC2500_WriteReg(CC2500_06_PKTLEN, REDPINE_PACKET_SIZE);
|
|
|
|
for (uint8_t i=0; i < ((sizeof REDPINE_init_data) / (sizeof REDPINE_init_data[0])); i++)
|
|
CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]);
|
|
|
|
prev_option = option;
|
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
|
|
// calibrate hop channels
|
|
for (uint8_t c = 0; c < REDPINE_NUM_HOPS; c++)
|
|
{
|
|
CC2500_Strobe(CC2500_SIDLE);
|
|
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[c]);
|
|
CC2500_Strobe(CC2500_SCAL);
|
|
delayMicroseconds(900);
|
|
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
|
|
}
|
|
}
|
|
|
|
static uint16_t initREDPINE()
|
|
{
|
|
hopping_frequency_no = 0;
|
|
// Used from kn_nrf24l01.c : kn_calculate_freqency_hopping_channels
|
|
uint32_t idx = 0;
|
|
uint32_t rnd = MProtocol_id;
|
|
#define REDPINE_MAX_RF_CHANNEL 255
|
|
hopping_frequency[idx++] = 1;
|
|
while (idx < REDPINE_NUM_HOPS-1)
|
|
{
|
|
uint32_t i;
|
|
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
|
|
// Drop least-significant byte for better randomization. Start from 1
|
|
uint8_t next_ch = (rnd >> 8) % REDPINE_MAX_RF_CHANNEL + 1;
|
|
// Check that it's not duplicate nor adjacent nor channel 0 or 1
|
|
for (i = 0; i < idx; i++)
|
|
{
|
|
uint8_t ch = hopping_frequency[i];
|
|
if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch > 1))
|
|
break;
|
|
}
|
|
if (i != idx)
|
|
continue;
|
|
hopping_frequency[idx++] = next_ch;
|
|
}
|
|
hopping_frequency[49] = 0; // Last channel is the bind channel at hop 0
|
|
|
|
bind_counter=REDPINE_BIND;
|
|
REDPINE_init(sub_protocol);
|
|
CC2500_SetTxRxMode(TX_EN); // enable PA
|
|
return 10000;
|
|
}
|
|
#endif
|