Files
Maison/OpenSky/arch/cc251x/hal_cc25xx.c
2026-04-21 12:19:15 +02:00

232 lines
7.0 KiB
C

/*
Copyright 2017 fishpepper <AT> gmail.com
This program 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.
This program 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 this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_cc25xx.h"
#include "cc25xx.h"
#include "hal_defines.h"
#include "hal_dma.h"
#include "delay.h"
#include "timeout.h"
#include "debug.h"
#include "led.h"
#include "frsky.h"
#include <cc2510fx.h>
EXTERNAL_MEMORY volatile uint8_t hal_cc25xx_mode;
void hal_cc25xx_init(void) {
// set highest prio for ch0 (RF)
IP1 |= (1<<0);
IP0 |= (1<<0);
hal_cc25xx_mode = CC25XX_MODE_RX;
// if we support LNA/PA make sure to config the pin as output:
#ifdef RF_LNA_PORT
PORT2DIR(RF_LNA_PORT) |= (1 << RF_LNA_PIN);
PORT2DIR(RF_PA_PORT) |= (1 << RF_PA_PIN);
// set default to LNA active
RF_PA_DISABLE();
RF_LNA_ENABLE();
#endif // RF_LNA_PORT
// if we support Diversity make sure to config the pin as output:
#ifdef RF_ANTENNA_SWITCH_PORT
PORT2DIR(RF_ANTENNA_SWITCH_PORT) |= (1 << RF_ANTENNA_SWITCH_PIN);
// select first antenna
RF_ANTENNA_SELECT_A();
#endif // RF_ANTENNA_SWITCH_PORT
// if we support HIGH GAIN mode config pin as output:
#ifdef RF_HIGH_GAIN_MODE_PORT
PORT2DIR(RF_HIGH_GAIN_MODE_PORT) |= (1 << RF_HIGH_GAIN_MODE_PIN);
// enable high gain mode?
#ifdef RF_HIGH_GAIN_MODE_ENABLED
RF_HIGH_GAIN_MODE_ENABLE();
#else
RF_HIGH_GAIN_MODE_DISABLE();
#endif // RF_HIGH_GAIN_MODE_ENABLED
#endif // RF_HIGH_GAIN_MODE_PORT
// if we support Bypass mode make sure to config the pin as output:
#ifdef RF_BYPASS_PORT
PORT2DIR(RF_BYPASS_MODE_PORT) |= (1 << RF_BYPASS_MODE_PIN);
// set default to Bypass off
#ifdef RF_BYPASS_MODE_ENABLED
RF_BYPASS_MODE_ENABLE();
#else
RF_BYPASS_MODE_DISABLE();
#endif // RF_BYPASS_MODE_ENABLED
#endif // RF_BYPASS_PORT
}
uint32_t hal_cc25xx_set_antenna(uint8_t id) {
// select antenna 0 or 1:
#ifdef RF_ANTENA_SWITCH_PORT
if (id) {
RF_ANTENNA_SELECT_B();
} else {
RF_ANTENNA_SELECT_A();
}
#endif // RF_ANTENNA_SWITCH_PORT
return id;
}
void hal_cc25xx_disable_rf_interrupt(void) {
IEN2 &= ~(IEN2_RFIE);
RFIM = 0;
}
void hal_cc25xx_enter_rxmode(void) {
#ifdef RF_LNA_PORT
RF_LNA_ENABLE();
delay_us(20);
RF_PA_DISABLE();
delay_us(5);
#endif // RF_LNA_PORT
// set up dma for radio--->buffer
hal_cc25xx_setup_rf_dma(CC25XX_MODE_RX);
// configure interrupt for every received packet
IEN2 |= (IEN2_RFIE);
// mask done irq
RFIM = (1<<4);
// interrupts should be enabled globally already..
// skip this! sei();
}
void hal_cc25xx_enter_txmode(void) {
#ifdef RF_LNA_PORT
RF_LNA_DISABLE();
delay_us(20);
RF_PA_ENABLE();
delay_us(5);
#endif // RF_LNA_PORT
// abort ch0
DMAARM = DMA_ARM_ABORT | DMA_ARM_CH0;
hal_cc25xx_setup_rf_dma(CC25XX_MODE_TX);
}
void hal_cc25xx_setup_rf_dma(uint8_t mode) {
// CPU has priority over DMA
// Use 8 bits for transfer count
// No DMA interrupt when done
// DMA triggers on radio
// Single transfer per trigger.
// One byte is transferred each time.
hal_dma_config[0].PRIORITY = DMA_PRI_HIGH;
hal_dma_config[0].M8 = DMA_M8_USE_8_BITS;
hal_dma_config[0].IRQMASK = DMA_IRQMASK_DISABLE;
hal_dma_config[0].TRIG = DMA_TRIG_RADIO;
hal_dma_config[0].TMODE = DMA_TMODE_SINGLE;
hal_dma_config[0].WORDSIZE = DMA_WORDSIZE_BYTE;
// store mode
hal_cc25xx_mode = mode;
if (hal_cc25xx_mode == CC25XX_MODE_TX) {
// Transmitter specific DMA settings
// Source: radioPktBuffer
// Destination: RFD register
// Use the first byte read + 1
// Sets the maximum transfer count allowed (length byte + data)
// Data source address is incremented by 1 byte
// Destination address is constant
SET_WORD(hal_dma_config[0].SRCADDRH, hal_dma_config[0].SRCADDRL, frsky_packet_buffer);
SET_WORD(hal_dma_config[0].DESTADDRH, hal_dma_config[0].DESTADDRL, &X_RFD);
hal_dma_config[0].VLEN = DMA_VLEN_FIRST_BYTE_P_1;
SET_WORD(hal_dma_config[0].LENH, hal_dma_config[0].LENL, (FRSKY_PACKET_LENGTH+1));
hal_dma_config[0].SRCINC = DMA_SRCINC_1;
hal_dma_config[0].DESTINC = DMA_DESTINC_0;
} else {
// Receiver specific DMA settings:
// Source: RFD register
// Destination: radioPktBuffer
// Use the first byte read + 3 (incl. 2 status bytes)
// Sets maximum transfer count allowed (length byte + data + 2 status bytes)
// Data source address is constant
// Destination address is incremented by 1 byte for each write
SET_WORD(hal_dma_config[0].SRCADDRH, hal_dma_config[0].SRCADDRL, &X_RFD);
SET_WORD(hal_dma_config[0].DESTADDRH, hal_dma_config[0].DESTADDRL, frsky_packet_buffer);
hal_dma_config[0].VLEN = DMA_VLEN_FIRST_BYTE_P_3;
SET_WORD(hal_dma_config[0].LENH, hal_dma_config[0].LENL, (FRSKY_PACKET_LENGTH+3));
hal_dma_config[0].SRCINC = DMA_SRCINC_0;
hal_dma_config[0].DESTINC = DMA_DESTINC_1;
}
// Save pointer to the DMA configuration struct into DMA-channel 0
// configuration registers
SET_WORD(DMA0CFGH, DMA0CFGL, &hal_dma_config[0]);
// frsky_packet_received = 0;
}
void hal_cc25xx_enable_receive(void) {
// start receiving on dma channel 0
DMAARM = DMA_ARM_CH0;
}
void hal_cc25xx_rf_interrupt(void) __interrupt RF_VECTOR {
// clear int flag
RFIF &= ~(1<<4);
// clear general statistics reg
S1CON &= ~0x03;
if (hal_cc25xx_mode == CC25XX_MODE_RX) {
// mark as received:
frsky_packet_received = 1;
// re arm DMA channel 0
hal_cc25xx_enable_receive();
} else {
frsky_packet_sent = 1;
}
}
uint8_t hal_cc25xx_transmission_completed(void) {
// this flag is set in the RF isr
return (frsky_packet_sent);
}
void hal_cc25xx_transmit_packet(volatile uint8_t *buffer, uint8_t len) {
UNUSED(buffer);
UNUSED(len);
RFST = RFST_STX;
// start transmitting on dma channel 0
DMAARM = DMA_ARM_CH0;
// mark packet as not sent (will be modified in RF isr):
frsky_packet_sent = 0;
// tricky: this will force an int request and
// initiate the actual transmission
S1CON |= 0x03;
}