Files
HBshuiwuConcentrator/APP/sx1276-Fsk.c
2025-12-15 16:07:49 +08:00

639 lines
17 KiB
C

/*
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* Copyright (C) SEMTECH S.A.
*/
/*!
* \file sx1276.c
* \brief SX1276 RF chip driver
*
* \version 2.0.0
* \date May 6 2013
* \author Gregory Cristian
*
* Last modified by Miguel Luis on Jun 19 2013
*/
#include <string.h>
#include <math.h>
#include "include.h"
#include "sx1276-Fsk.h"
#include "sx1276-FskMisc.h"
#include "hal_radio.h"
// Default settings
tFskSettings FskSettings =
{
492000000, // RFFrequency
10000, // Bitrate
20000, // Fdev
0, // Power
40000, // RxBw
150000, // RxBwAfc
true, // CrcOn
true, // AfcOn
255 // PayloadLength (set payload size to the maximum for variable mode, else set the exact payload length)
};
extern struct etimer timer_rf;
sRF_FSK g_fsk = {
.states = RF_STATE_IDLE,
.index = 0,
.packetLenth = 0,
.rssi = 0.0,
.sync_timeout = 1000,
.plyloadtimeout = 1000
};
void SX1276Fsk_recrive_Packet(void);
/*!
* SX1276 FSK registers variable
*/
extern uint8_t SX1276Regs[];
tSX1276* SX1276 = ( tSX1276* )SX1276Regs;;
/*!
* Local RF buffer for communication support
*/
static uint8_t RFBuffer[RF_BUFFER_SIZE];
/*!
* Chunk size of data write in buffer
*/
//static uint8_t DataChunkSize = 32;
/*!
* RF state machine variable
*/
static uint8_t RFState = RF_STATE_IDLE;
/*!
* Rx management support variables
*/
/*!
* PacketTimeout holds the RF packet timeout
* SyncSize = [0..8]
* VariableSize = [0;1]
* AddressSize = [0;1]
* PayloadSize = [0..RF_BUFFER_SIZE]
* CrcSize = [0;2]
* PacketTimeout = ( ( 8 * ( VariableSize + AddressSize + PayloadSize + CrcSize ) / BR ) * 1000.0 ) + 1
* Computed timeout is in miliseconds
*/
//static uint32_t PacketTimeout;
/*!
* Preamble2SyncTimeout
* Preamble2SyncTimeout = ( ( 8 * ( PremableSize + SyncSize ) / RFBitrate ) * 1000.0 ) + 1
* Computed timeout is in miliseconds
*/
//static uint32_t Preamble2SyncTimeout;
//static bool PreambleDetected = false;
//static bool SyncWordDetected = false;
//static bool PacketDetected = false;
static uint16_t RxPacketSize = 0;
//static uint8_t RxBytesRead = 0;
//static uint8_t TxBytesSent = 0;
static double RxPacketRssiValue;
static uint32_t RxPacketAfcValue;
static uint8_t RxGain = 1;
//static uint32_t RxTimeoutTimer = 0;
//static uint32_t Preamble2SyncTimer = 0;
//static bool firstReceiveByte = true;
/*!
* Tx management support variables
*/
static uint16_t TxPacketSize = 0;
//static uint32_t TxTimeoutTimer = 0;
void SX1276FskInit( void )
{
SX1276FskSetOpMode( RF_OPMODE_SLEEP );
SX1276->RegOpMode = ( SX1276->RegOpMode & 0x7F ) | 0x00;
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
SX1276FskSetDefaults( );
SX1276ReadBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
// Set the device in FSK mode and Sleep Mode
SX1276->RegOpMode = RF_OPMODE_MODULATIONTYPE_FSK | RF_OPMODE_SLEEP;
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
SX1276->RegPaRamp = RF_PARAMP_MODULATIONSHAPING_01;
SX1276Write( REG_PARAMP, SX1276->RegPaRamp );
SX1276->RegLna = RF_LNA_GAIN_G1;
SX1276Write( REG_LNA, SX1276->RegLna );
SX1276->RegRxConfig = ( FskSettings.AfcOn == true ) ? RF_RXCONFIG_AFCAUTO_ON: RF_RXCONFIG_AFCAUTO_OFF;
SX1276->RegRxConfig |= RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AGCAUTO_ON;// |RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
if( FskSettings.AfcOn == true )
{
SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_ON |
RF_RXCONFIG_AGCAUTO_ON;// |RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
}
else
{
SX1276->RegRxConfig = RF_RXCONFIG_RESTARTRXONCOLLISION_OFF | RF_RXCONFIG_AFCAUTO_OFF |
RF_RXCONFIG_AGCAUTO_ON;// | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT;
}
SX1276->RegPreambleLsb = 30;
SX1276->RegPreambleDetect = RF_PREAMBLEDETECT_DETECTOR_ON | RF_PREAMBLEDETECT_DETECTORSIZE_3 |
RF_PREAMBLEDETECT_DETECTORTOL_10;
SX1276->RegRssiThresh = 0xFF;
SX1276->RegSyncConfig = RF_SYNCCONFIG_AUTORESTARTRXMODE_OFF | RF_SYNCCONFIG_PREAMBLEPOLARITY_AA |
RF_SYNCCONFIG_SYNC_ON |
RF_SYNCCONFIG_SYNCSIZE_4;
SX1276->RegSyncValue1 = 0x69;
SX1276->RegSyncValue2 = 0x81;
SX1276->RegSyncValue3 = 0x7E;
SX1276->RegSyncValue4 = 0x96;
SX1276->RegPacketConfig1 = RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE | RF_PACKETCONFIG1_DCFREE_OFF |
( FskSettings.CrcOn << 4 ) | RF_PACKETCONFIG1_CRCAUTOCLEAR_OFF |
RF_PACKETCONFIG1_ADDRSFILTERING_OFF | RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT;
SX1276FskGetPacketCrcOn( ); // Update CrcOn on FskSettings
SX1276->RegPayloadLength = FskSettings.PayloadLength;
// we can now update the registers with our configuration
SX1276WriteBuffer( REG_OPMODE, SX1276Regs + 1, 0x70 - 1 );
// then we need to set the RF settings
SX1276FskSetRFFrequency( FskSettings.RFFrequency );
SX1276FskSetBitrate( FskSettings.Bitrate );
SX1276FskSetFdev( FskSettings.Fdev );
SX1276FskSetDccBw( &SX1276->RegRxBw, 0, FskSettings.RxBw );
SX1276FskSetDccBw( &SX1276->RegAfcBw, 0, FskSettings.RxBwAfc );
SX1276FskSetRssiOffset( 0 );
SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_RFO );
//SX1276FskSetPAOutput( RF_PACONFIG_PASELECT_PABOOST );
SX1276FskSetPa20dBm( false );
SX1276FskSetRFPower( FskSettings.Power );
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
// Calibrate the HF
SX1276FskRxCalibrate( );
g_fsk.sync_timeout = (u16)(8*8*1000/FskSettings.Bitrate) + 5;
g_fsk.plyloadtimeout = (u16)(255*2*8*1000/FskSettings.Bitrate) + 5;
SX1276Fsk_recrive_Packet();
}
void SX1276FskSetDefaults( void )
{
// REMARK: See SX1276 datasheet for modified default values.
SX1276Read( REG_VERSION, &SX1276->RegVersion );
}
void SX1276FskSetOpMode( uint8_t opMode )
{
static uint8_t opModePrev = RF_OPMODE_STANDBY;
static bool antennaSwitchTxOnPrev = true;
bool antennaSwitchTxOn = false;
opModePrev = SX1276->RegOpMode & ~RF_OPMODE_MASK;
if( opMode != opModePrev )
{
if( opMode == RF_OPMODE_TRANSMITTER )
{
antennaSwitchTxOn = true;
}
else
{
antennaSwitchTxOn = false;
}
if( antennaSwitchTxOn != antennaSwitchTxOnPrev )
{
antennaSwitchTxOnPrev = antennaSwitchTxOn;
//RXTX( antennaSwitchTxOn ); // Antenna switch control
}
SX1276->RegOpMode = ( SX1276->RegOpMode & RF_OPMODE_MASK ) | opMode;
SX1276Write( REG_OPMODE, SX1276->RegOpMode );
}
}
uint8_t SX1276FskGetOpMode( void )
{
SX1276Read( REG_OPMODE, &SX1276->RegOpMode );
return SX1276->RegOpMode & ~RF_OPMODE_MASK;
}
int32_t SX1276FskReadFei( void )
{
SX1276ReadBuffer( REG_FEIMSB, &SX1276->RegFeiMsb, 2 ); // Reads the FEI value
return ( int32_t )(( double )( ( ( uint16_t )SX1276->RegFeiMsb << 8 ) | ( uint16_t )SX1276->RegFeiLsb ) * ( double )FREQ_STEP);
}
int32_t SX1276FskReadAfc( void )
{
SX1276ReadBuffer( REG_AFCMSB, &SX1276->RegAfcMsb, 2 ); // Reads the AFC value
return ( int32_t )(( double )( ( ( uint16_t )SX1276->RegAfcMsb << 8 ) | ( uint16_t )SX1276->RegAfcLsb ) * ( double )FREQ_STEP);
}
uint8_t SX1276FskReadRxGain( void )
{
SX1276Read( REG_LNA, &SX1276->RegLna );
return( SX1276->RegLna >> 5 ) & 0x07;
}
double SX1276FskReadRssi( void )
{
SX1276Read( REG_RSSIVALUE, &SX1276->RegRssiValue ); // Reads the RSSI value
return -( double )( ( double )SX1276->RegRssiValue / 2.0 );
}
uint8_t SX1276FskGetPacketRxGain( void )
{
return RxGain;
}
double SX1276FskGetPacketRssi( void )
{
return RxPacketRssiValue;
}
uint32_t SX1276FskGetPacketAfc( void )
{
return RxPacketAfcValue;
}
/*
void SX1276FskStartRx( void )
{
SX1276FskSetRFState( RF_STATE_RX_INIT );
}
*/
void SX1276FskGetRxPacket( void *buffer, uint16_t *size )
{
*size = RxPacketSize;
RxPacketSize = 0;
memcpy( ( void * )buffer, ( void * )RFBuffer, ( size_t )*size );
}
void SX1276FskSetTxPacket( const void *buffer, uint16_t size )
{
TxPacketSize = size;
memcpy( ( void * )RFBuffer, buffer, ( size_t )TxPacketSize );
RFState = RF_STATE_TX_INIT;
}
// Remark: SX1276 must be fully initialized before calling this function
uint16_t SX1276FskGetPacketPayloadSize( void )
{
uint16_t syncSize;
uint16_t variableSize;
uint16_t addressSize;
uint16_t payloadSize;
uint16_t crcSize;
syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
variableSize = ( ( SX1276->RegPacketConfig1 & 0x80 ) == 0x80 ) ? 1 : 0;
addressSize = ( ( SX1276->RegPacketConfig1 & 0x06 ) != 0x00 ) ? 1 : 0;
payloadSize = SX1276->RegPayloadLength;
crcSize = ( ( SX1276->RegPacketConfig1 & 0x10 ) == 0x10 ) ? 2 : 0;
return syncSize + variableSize + addressSize + payloadSize + crcSize;
}
// Remark: SX1276 must be fully initialized before calling this function
uint16_t SX1276FskGetPacketHeaderSize( void )
{
uint16_t preambleSize;
uint16_t syncSize;
preambleSize = ( ( uint16_t )SX1276->RegPreambleMsb << 8 ) | ( uint16_t )SX1276->RegPreambleLsb;
syncSize = ( SX1276->RegSyncConfig & 0x07 ) + 1;
return preambleSize + syncSize;
}
uint8_t SX1276FskGetRFState( void )
{
return RFState;
}
void SX1276FskSetRFState( uint8_t state )
{
RFState = state;
}
void start_continuous_mode(void)
{
//4¡¢BitSyncOn
//5¡¢continuous mode
//6¡¢RX
u8 RegDioMapping[2];
u8 temp = 0;;
SX1276FskSetOpMode(RF_OPMODE_STANDBY);
switch_Rx();
RegDioMapping[0] = RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_00 | RF_DIOMAPPING1_DIO2_11 | RF_DIOMAPPING1_DIO3_10;
RegDioMapping[1] = RF_DIOMAPPING2_DIO4_00 | RF_DIOMAPPING2_DIO5_11 | RF_DIOMAPPING2_MAP_PREAMBLEDETECT;
SX1276WriteBuffer( REG_DIOMAPPING1, RegDioMapping, 2 );
SX1276Read(REG_OOKPEAK, &temp);
temp |= (0x20);
SX1276Write(REG_OOKPEAK, temp);
SX1276Read(REG_PACKETCONFIG2, &temp);
temp &= (~0x40);
SX1276Write(REG_PACKETCONFIG2, temp);
SX1276FskSetOpMode(RF_OPMODE_RECEIVER);
}
void packet_tx_data(u8 *PBuffer,u8 length)
{
g_fsk.buffer[0] = length;
memcpy( ( void * )(g_fsk.buffer+1), PBuffer, length);
g_fsk.packetLenth = length + 1;
g_fsk.index = 0;
}
void fill_fifo(void)
{
u8 sendLenth;
u8 leftlength = g_fsk.packetLenth - g_fsk.index;
if (g_fsk.index == 0)
{
if (leftlength <= 64)
{
SX1276WriteFifo(g_fsk.buffer, leftlength);
g_fsk.index += leftlength;
hal_DIOx_ITConfig(1,DISABLE);
}
else
{
SX1276WriteFifo(g_fsk.buffer, 64);
g_fsk.index += 64;
}
}
else if (g_fsk.index < g_fsk.packetLenth)
{
sendLenth = ( leftlength > (FIFO_LENGTH - TX_FIFO_THRESHOLD) ? (FIFO_LENGTH - TX_FIFO_THRESHOLD) : leftlength);
SX1276WriteFifo(g_fsk.buffer+g_fsk.index, sendLenth);
g_fsk.index += sendLenth;
}
}
void contious_tx(void)
{
SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFOTHRESH | TX_FIFO_THRESHOLD; // 24 bytes of data
SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
switch_Tx();
SX1276FskSetOpMode( RF_OPMODE_TRANSMITTER );
}
void read_fifo(bool rxdone)
{
u8 leftlength;
if (g_fsk.index == 0)
{
SX1276ReadFifo(&g_fsk.packetLenth , 1);
}
leftlength = g_fsk.packetLenth - g_fsk.index;
if (rxdone)
{
if (leftlength <= FIFO_LENGTH)
{
//hal_DIOx_ITConfig(all,DISABLE);
SX1276ReadFifo(g_fsk.buffer+g_fsk.index, leftlength);
}
}
else
{
if (g_fsk.index < (g_fsk.packetLenth -1) )
{
SX1276ReadFifo(g_fsk.buffer+g_fsk.index, RX_FIFO_THRESHOLD);
g_fsk.index += RX_FIFO_THRESHOLD;
}
leftlength = g_fsk.packetLenth - g_fsk.index;
if (leftlength <= FIFO_LENGTH)
{
hal_DIOx_ITConfig(1,DISABLE);
}
}
}
void SX1276Fsk_Send_Packet(u8 *PBuffer,u8 length)
{
hal_DIOx_ITConfig(all, DISABLE);
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
// PacketSent, FifoLevel, FifoFull, TxReady
SX1276->RegDioMapping1 = packet_DIO0_packetSend | packet_DIO1_fifoLevel | packet_DIO2_fifoFull | packet_DIO3_TxReady;
// LowBat, Data
SX1276->RegDioMapping2 = packet_DIO4_TimeOut | packet_DIO5_Data ;
SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | TX_FIFO_THRESHOLD; // 24 bytes of data
SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
packet_tx_data(PBuffer, length);
hal_DIOx_ITConfig(0,ENABLE);
hal_DIOx_ITConfig(1,ENABLE);
fill_fifo();
switch_Tx();
g_fsk.states = RF_STATE_TX_RUNNING;
SX1276FskSetOpMode( RF_OPMODE_TRANSMITTER );
}
void SX1276Fsk_recrive_Packet(void)
{
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
hal_DIOx_ITConfig(all, DISABLE);
SX1276->RegDioMapping1 = packet_DIO0_RxpayloadReady | packet_DIO1_fifoLevel | packet_DIO2_SyncAddress | packet_DIO3_fifoEmpty;
// LowBat, Data
SX1276->RegDioMapping2 = packet_DIO4_Rssi_PreambleDetect | packet_DIO5_Data | RF_DIOMAPPING2_MAP_PREAMBLEDETECT;
SX1276WriteBuffer( REG_DIOMAPPING1, &SX1276->RegDioMapping1, 2 );
SX1276->RegFifoThresh = RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY | RX_FIFO_THRESHOLD; // 24 bytes of data
SX1276Write( REG_FIFOTHRESH, SX1276->RegFifoThresh );
g_fsk.states = RF_STATE_RX_INIT;
g_fsk.index = 0;
hal_DIOx_ITConfig(4,ENABLE);
hal_DIOx_ITConfig(0,ENABLE);
hal_DIOx_ITConfig(1,ENABLE);
hal_DIOx_ITConfig(2,ENABLE);
hal_DIOx_ITConfig(3,ENABLE);
switch_Rx();
SX1276FskSetOpMode( RF_OPMODE_RECEIVER );
}
#if 0
/*****************************************************************************
Prototype : GPIO_EVEN_IRQHandler
Description :
Input : void
Output : None
Return Value :
Date : 2016/08/15
Author : Barry
*****************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
u32 flags = GPIO->IF;
GPIO->IFC = flags;
if(flags & (1 << sRF_DIO0_PIN) )
{
hal_DIOx_ITConfig(all, DISABLE);
hal_sRF_ClearAllRF_IT();
if(g_fsk.states == RF_STATE_TX_RUNNING)
{
// Tx done
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
g_fsk.states = RF_STATE_TX_DONE;
process_post(&hal_RF_process, PROCESS_EVENT_MSG, (void *)(&g_fsk.states));
}
if(g_fsk.states == RF_STATE_RX_SYNC)
{
// Rx done
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
read_fifo(true);
etimer_stop(&timer_rf);
g_fsk.states = RF_STATE_RX_DONE;
process_post(&hal_RF_process, PROCESS_EVENT_MSG, (void *)(&g_fsk.states));
}
}
else if (flags & (1 << sRF_DIO2_PIN) )
{
if(g_fsk.states == RF_STATE_TX_RUNNING)
{
hal_DIOx_ITConfig(all,DISABLE);
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
}
//sync detect
if(g_fsk.states == RF_STATE_RX_PREAMBLE)
{
hal_DIOx_ITConfig(2,DISABLE);
etimer_remodify(&timer_rf, g_fsk.plyloadtimeout);
printf("sync det\r\n");
g_fsk.states = RF_STATE_RX_SYNC;
g_fsk.rssi = SX1276FskReadRssi( );
}
}
else if (flags & (1 << sRF_DIO3_PIN) )
{
hal_DIOx_ITConfig(all,DISABLE);
SX1276FskSetOpMode( RF_OPMODE_STANDBY );
}
}
void GPIO_ODD_IRQHandler(void)
{
u32 flags = GPIO->IF;
GPIO->IFC = flags;
if (flags & (1 << sRF_DIO1_PIN) )
{
if(g_fsk.states == RF_STATE_TX_RUNNING)
{
fill_fifo();
}
if(g_fsk.states == RF_STATE_RX_SYNC)
{
read_fifo(false);
}
}
else if (flags & (1 << sRF_DIO4_PIN) )
{
if(g_fsk.states == RF_STATE_RX_INIT)
{
hal_DIOx_ITConfig(4,DISABLE);
etimer_remodify(&timer_rf, g_fsk.sync_timeout); //²»Ö´ÐÐÕâ¸öµÄ»°£¬ÖжϺ¯ÊýÉÙµãʱ¼ä£¬Ö´Ðеϰ£¬¿É¿ìËÙÅжϳ¬Ê±
printf("preamble det\r\n");
g_fsk.states = RF_STATE_RX_PREAMBLE;
process_post(&hal_RF_process, PROCESS_EVENT_MSG, (void *)(&g_fsk.states));
}
}
}
#endif