229 lines
6.2 KiB
Arduino
Raw Normal View History

/*
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(AFHDS2A_RX_A7105_INO)
#include "iface_a7105.h"
#define AFHDS2A_RX_TXPACKET_SIZE 38
#define AFHDS2A_RX_RXPACKET_SIZE 37
#define AFHDS2A_RX_NUMFREQ 16
enum {
AFHDS2A_RX_BIND1,
AFHDS2A_RX_BIND2,
AFHDS2A_RX_BIND3,
AFHDS2A_RX_DATA
};
2021-02-09 18:23:33 +01:00
static void __attribute__((unused)) AFHDS2A_RX_build_telemetry_packet()
{
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 0;
2019-10-02 21:24:50 +02:00
packet_in[idx++] = RX_LQI; // 0 - 130
packet_in[idx++] = RX_RSSI;
packet_in[idx++] = 0; // start channel
packet_in[idx++] = 14; // number of channels in packet
// pack channels
for (uint8_t i = 0; i < 14; i++) {
2021-01-16 18:33:10 +01:00
uint32_t val = packet[9+i*2] | (((packet[10+i*2])&0x0F) << 8);
if (val < 860)
val = 860;
2019-10-05 13:30:50 +02:00
// convert ppm (860-2140) to Multi (0-2047)
2019-10-05 19:02:59 +02:00
val = min(((val-860)<<3)/5, 2047);
2019-10-05 13:30:50 +02:00
bits |= val << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8) {
2019-10-02 21:24:50 +02:00
packet_in[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
}
2021-02-09 18:23:33 +01:00
static uint8_t __attribute__((unused)) AFHDS2A_RX_data_ready()
{
// check if FECF+CRCF Ok
return !(A7105_ReadReg(A7105_00_MODE) & (1 << 5 | 1 << 6 | 1 << 0));
}
2021-02-09 18:23:33 +01:00
void AFHDS2A_RX_init()
{
uint8_t i;
A7105_Init();
hopping_frequency_no = 0;
packet_count = 0;
2019-10-13 16:35:09 +02:00
rx_data_started = false;
2019-10-13 11:08:20 +02:00
rx_disable_lna = IS_POWER_FLAG_on;
2019-10-13 16:35:09 +02:00
A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
A7105_Strobe(A7105_RX);
if (IS_BIND_IN_PROGRESS) {
phase = AFHDS2A_RX_BIND1;
}
else {
uint16_t temp = AFHDS2A_RX_EEPROM_OFFSET;
for (i = 0; i < 4; i++)
rx_id[i] = eeprom_read_byte((EE_ADDR)temp++);
for (i = 0; i < AFHDS2A_RX_NUMFREQ; i++)
hopping_frequency[i] = eeprom_read_byte((EE_ADDR)temp++);
phase = AFHDS2A_RX_DATA;
}
}
#define AFHDS2A_RX_WAIT_WRITE 0x80
2021-02-09 18:23:33 +01:00
uint16_t AFHDS2A_RX_callback()
{
static int8_t read_retry;
int16_t temp;
uint8_t i;
#ifndef FORCE_AFHDS2A_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
2019-10-13 11:08:20 +02:00
if (rx_disable_lna != IS_POWER_FLAG_on) {
rx_disable_lna = IS_POWER_FLAG_on;
2019-10-13 16:35:09 +02:00
A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
}
switch(phase) {
case AFHDS2A_RX_BIND1:
2021-02-09 18:23:33 +01:00
if(IS_BIND_DONE)
{
AFHDS2A_RX_init(); // Abort bind
break;
}
debugln("bind p=%d", phase+1);
2021-02-09 18:23:33 +01:00
if (AFHDS2A_RX_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if ((packet[0] == 0xbb && packet[9] == 0x01) || (packet[0] == 0xbc && packet[9] <= 0x02)) {
memcpy(rx_id, &packet[1], 4); // TX id actually
memcpy(hopping_frequency, &packet[11], AFHDS2A_RX_NUMFREQ);
phase = AFHDS2A_RX_BIND2;
debugln("phase bind2");
}
}
A7105_WriteReg(A7105_0F_PLL_I, (packet_count++ & 1) ? 0x0D : 0x8C); // bind channels
A7105_Strobe(A7105_RX);
return 10000;
case AFHDS2A_RX_BIND2:
2021-02-09 18:23:33 +01:00
if(IS_BIND_DONE)
{
AFHDS2A_RX_init(); // Abort bind
break;
}
// got 2nd bind packet from tx ?
2021-02-09 18:23:33 +01:00
if (AFHDS2A_RX_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if ((packet[0] == 0xBC && packet[9] == 0x02 && packet[10] == 0x00) &&
(memcmp(rx_id, &packet[1], 4) == 0) &&
(memcmp(rx_tx_addr, &packet[5], 4) == 0)) {
// save tx info to eeprom
temp = AFHDS2A_RX_EEPROM_OFFSET;
for (i = 0; i < 4; i++)
eeprom_write_byte((EE_ADDR)temp++, rx_id[i]);
for (i = 0; i < AFHDS2A_RX_NUMFREQ; i++)
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[i]);
phase = AFHDS2A_RX_BIND3;
debugln("phase bind3");
packet_count = 0;
}
}
case AFHDS2A_RX_BIND3:
debugln("bind p=%d", phase+1);
// transmit response packet
packet[0] = 0xBC;
memcpy(&packet[1], rx_id, 4);
memcpy(&packet[5], rx_tx_addr, 4);
//packet[9] = 0x01;
packet[10] = 0x00;
memset(&packet[11], 0xFF, 26);
2021-01-16 18:33:10 +01:00
A7105_SetTxRxMode(TX_EN);
rx_disable_lna = !IS_POWER_FLAG_on;
A7105_WriteData(AFHDS2A_RX_RXPACKET_SIZE, packet_count++ & 1 ? 0x0D : 0x8C);
if(phase == AFHDS2A_RX_BIND3 && packet_count > 20)
{
debugln("done");
BIND_DONE;
2021-02-09 18:23:33 +01:00
AFHDS2A_RX_init(); // Restart protocol
break;
}
phase |= AFHDS2A_RX_WAIT_WRITE;
return 1700;
case AFHDS2A_RX_BIND2 | AFHDS2A_RX_WAIT_WRITE:
//Wait for TX completion
pps_timer = micros();
2020-12-10 16:52:34 +01:00
while ((uint32_t)(micros() - pps_timer) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if (!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_Strobe(A7105_RX);
case AFHDS2A_RX_BIND3 | AFHDS2A_RX_WAIT_WRITE:
phase &= ~AFHDS2A_RX_WAIT_WRITE;
return 10000;
case AFHDS2A_RX_DATA:
2021-02-09 18:23:33 +01:00
if (AFHDS2A_RX_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) {
2021-03-04 09:11:20 +01:00
if (packet[0] == 0x58 && packet[37] == 0x00 && (telemetry_link&0x7F) == 0) { // standard packet, send channels to TX
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
2019-10-05 13:30:50 +02:00
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
2021-02-09 18:23:33 +01:00
AFHDS2A_RX_build_telemetry_packet();
telemetry_link = 1;
2021-03-06 11:33:32 +01:00
#ifdef SEND_CPPM
2021-03-03 10:07:19 +01:00
if(sub_protocol>0)
2021-03-06 11:33:32 +01:00
telemetry_link |= 0x80; // Disable telemetry output
2021-03-03 10:07:19 +01:00
#endif
}
2019-10-13 16:35:09 +02:00
rx_data_started = true;
read_retry = 10; // hop to next channel
pps_counter++;
}
}
// packets per second
if (millis() - pps_timer >= 1000) {
pps_timer = millis();
2019-10-02 21:24:50 +02:00
debugln("%d pps", pps_counter);
RX_LQI = pps_counter / 2;
pps_counter = 0;
}
// frequency hopping
if (read_retry++ >= 10) {
hopping_frequency_no++;
if(hopping_frequency_no >= AFHDS2A_RX_NUMFREQ)
hopping_frequency_no = 0;
A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[hopping_frequency_no]);
A7105_Strobe(A7105_RX);
2019-10-13 11:08:20 +02:00
if (rx_data_started)
read_retry = 0;
else
read_retry = -127; // retry longer until first packet is catched
}
return 385;
}
return 3850; // never reached
}
#endif