init commit
This commit is contained in:
862
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/lr_fhss_mac.c
vendored
Normal file
862
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/lr_fhss_mac.c
vendored
Normal file
@@ -0,0 +1,862 @@
|
||||
/*!
|
||||
* @file lr_fhss_mac.c
|
||||
*
|
||||
* @brief Radio-independent LR-FHSS driver implementation
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2021. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
#include "lr_fhss_mac.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TEST
|
||||
#define STATIC
|
||||
#else
|
||||
#define STATIC static
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LR_FHSS_MAX_TMP_BUF_BYTES ( 608 )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @brief Channel count as function of bandwidth index, from Table 9 specification v18 */
|
||||
STATIC const uint16_t lr_fhss_channel_count[] = { 80, 176, 280, 376, 688, 792, 1480, 1584, 3120, 3224 };
|
||||
|
||||
/** @brief Generating polynomial as function of polynomial index, n_grid in { 10, 22, 28, 30, 35, 47 } */
|
||||
STATIC const uint8_t lr_fhss_lfsr_poly1[] = { 33, 45, 48, 51, 54, 57 };
|
||||
|
||||
/** @brief Generating polynomial as function of polynomial index, n_grid in { 86, 99 } */
|
||||
STATIC const uint8_t lr_fhss_lfsr_poly2[] = { 65, 68, 71, 72 };
|
||||
|
||||
/** @brief Generating polynomial as function of polynomial index, n_grid in { 185, 198 } */
|
||||
STATIC const uint8_t lr_fhss_lfsr_poly3[] = { 142, 149 };
|
||||
|
||||
/** @brief used for 1/3 rate viterbi encoding */
|
||||
STATIC const uint8_t lr_fhss_viterbi_1_3_table[64][2] =
|
||||
{
|
||||
{ 0, 7 }, { 3, 4 }, { 7, 0 }, { 4, 3 }, { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2, 5 }, { 1, 6 }, { 2, 5 }, { 6, 1 },
|
||||
{ 5, 2 }, { 7, 0 }, { 4, 3 }, { 0, 7 }, { 3, 4 }, { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0, 7 }, { 2, 5 }, { 1, 6 },
|
||||
{ 5, 2 }, { 6, 1 }, { 5, 2 }, { 6, 1 }, { 2, 5 }, { 1, 6 }, { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7, 0 }, { 7, 0 },
|
||||
{ 4, 3 }, { 0, 7 }, { 3, 4 }, { 1, 6 }, { 2, 5 }, { 6, 1 }, { 5, 2 }, { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2, 5 },
|
||||
{ 0, 7 }, { 3, 4 }, { 7, 0 }, { 4, 3 }, { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7, 0 }, { 5, 2 }, { 6, 1 }, { 2, 5 },
|
||||
{ 1, 6 }, { 2, 5 }, { 1, 6 }, { 5, 2 }, { 6, 1 }, { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0, 7 }
|
||||
};
|
||||
|
||||
/** @brief used for 1/2 rate viterbi encoding */
|
||||
STATIC const uint8_t lr_fhss_viterbi_1_2_table[16][2] =
|
||||
{
|
||||
{ 0, 3 }, { 1, 2 }, { 2, 1 }, { 3, 0 }, { 2, 1 }, { 3, 0 },
|
||||
{ 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 }, { 1, 2 }, { 0, 3 },
|
||||
{ 1, 2 }, { 0, 3 }, { 3, 0 }, { 2, 1 }
|
||||
};
|
||||
|
||||
/** @brief used header interleaving */
|
||||
STATIC const uint8_t lr_fhss_header_interleaver_minus_one[80] =
|
||||
{
|
||||
0, 18, 36, 54, 72, 4, 22, 40, //
|
||||
58, 76, 8, 26, 44, 62, 12, 30, //
|
||||
48, 66, 16, 34, 52, 70, 1, 19, //
|
||||
37, 55, 73, 5, 23, 41, 59, 77, //
|
||||
9, 27, 45, 63, 13, 31, 49, 67, //
|
||||
17, 35, 53, 71, 2, 20, 38, 56, //
|
||||
74, 6, 24, 42, 60, 78, 10, 28, //
|
||||
46, 64, 14, 32, 50, 68, 3, 21, //
|
||||
39, 57, 75, 7, 25, 43, 61, 79, //
|
||||
11, 29, 47, 65, 15, 33, 51, 69 //
|
||||
};
|
||||
|
||||
/** @brief lookup table for lr_fhss_header_crc8 */
|
||||
const uint8_t lr_fhss_header_crc8_lut[256] =
|
||||
{
|
||||
0, 47, 94, 113, 188, 147, 226, 205, 87, 120, 9, 38, 235, 196, 181, 154, //
|
||||
174, 129, 240, 223, 18, 61, 76, 99, 249, 214, 167, 136, 69, 106, 27, 52, //
|
||||
115, 92, 45, 2, 207, 224, 145, 190, 36, 11, 122, 85, 152, 183, 198, 233, //
|
||||
221, 242, 131, 172, 97, 78, 63, 16, 138, 165, 212, 251, 54, 25, 104, 71, //
|
||||
230, 201, 184, 151, 90, 117, 4, 43, 177, 158, 239, 192, 13, 34, 83, 124, //
|
||||
72, 103, 22, 57, 244, 219, 170, 133, 31, 48, 65, 110, 163, 140, 253, 210, //
|
||||
149, 186, 203, 228, 41, 6, 119, 88, 194, 237, 156, 179, 126, 81, 32, 15, //
|
||||
59, 20, 101, 74, 135, 168, 217, 246, 108, 67, 50, 29, 208, 255, 142, 161, //
|
||||
227, 204, 189, 146, 95, 112, 1, 46, 180, 155, 234, 197, 8, 39, 86, 121, //
|
||||
77, 98, 19, 60, 241, 222, 175, 128, 26, 53, 68, 107, 166, 137, 248, 215, //
|
||||
144, 191, 206, 225, 44, 3, 114, 93, 199, 232, 153, 182, 123, 84, 37, 10, //
|
||||
62, 17, 96, 79, 130, 173, 220, 243, 105, 70, 55, 24, 213, 250, 139, 164, //
|
||||
5, 42, 91, 116, 185, 150, 231, 200, 82, 125, 12, 35, 238, 193, 176, 159, //
|
||||
171, 132, 245, 218, 23, 56, 73, 102, 252, 211, 162, 141, 64, 111, 30, 49, //
|
||||
118, 89, 40, 7, 202, 229, 148, 187, 33, 14, 127, 80, 157, 178, 195, 236, //
|
||||
216, 247, 134, 169, 100, 75, 58, 21, 143, 160, 209, 254, 51, 28, 109, 66 //
|
||||
};
|
||||
|
||||
/** @brief lookup table for lr_fhss_payload_crc16 */
|
||||
const uint16_t lr_fhss_payload_crc16_lut[256] =
|
||||
{
|
||||
0, 30043, 60086, 40941, 41015, 54636, 19073, 16346, 13621, 16494, 57219, 43736, 38146, 57433, 32692, 2799, //
|
||||
27242, 7985, 32988, 62855, 51805, 48902, 8427, 21936, 24415, 10756, 46569, 49330, 65384, 35379, 5598, 24709, //
|
||||
54484, 41359, 15970, 19257, 29923, 440, 40533, 60174, 57825, 38074, 2903, 32268, 16854, 13453, 43872, 56891, //
|
||||
48830, 52197, 21512, 8531, 7817, 27602, 62527, 33124, 35723, 65232, 24893, 5222, 11196, 24295, 49418, 46161, //
|
||||
56563, 43432, 13893, 17182, 31940, 2463, 38514, 58153, 59846, 40093, 880, 30251, 18929, 15530, 41799, 54812, //
|
||||
46745, 50114, 23599, 10612, 5806, 25589, 64536, 35139, 33708, 63223, 26906, 7233, 9115, 22208, 51501, 48246, //
|
||||
2087, 32124, 58001, 38858, 43024, 56651, 17062, 14333, 15634, 18505, 55204, 41727, 40229, 59518, 30611, 712, //
|
||||
25165, 5910, 35067, 64928, 49786, 46881, 10444, 23959, 22392, 8739, 48590, 51349, 63311, 33300, 7673, 26786, //
|
||||
52413, 47590, 9739, 21328, 27786, 6609, 34364, 62311, 63880, 36051, 4926, 26213, 22975, 11492, 45833, 50770, //
|
||||
42711, 54156, 19553, 14650, 1760, 29627, 60502, 39181, 37858, 59065, 31060, 3087, 13269, 18062, 55651, 44088, //
|
||||
6249, 27954, 62175, 34692, 47198, 52485, 21224, 10163, 11612, 22535, 51178, 45745, 36203, 63536, 26589, 4742, //
|
||||
29187, 1880, 39093, 60910, 53812, 42863, 14466, 19929, 18230, 12909, 44416, 55515, 59137, 37466, 3511, 30956, //
|
||||
4174, 25877, 64248, 36771, 45177, 50466, 23247, 12180, 9595, 20512, 53197, 47766, 34124, 61463, 28666, 6817, //
|
||||
31268, 3967, 37010, 58825, 55827, 44872, 12453, 17918, 20241, 14922, 42407, 53500, 61222, 39549, 1424, 28875, //
|
||||
50330, 45505, 11820, 23415, 25773, 4598, 36379, 64320, 61871, 34036, 6937, 28226, 20888, 9411, 47918, 52853, //
|
||||
44784, 56235, 17478, 12573, 3783, 31644, 58481, 37162, 39877, 61086, 29043, 1064, 15346, 20137, 53572, 42015
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief integral square root, rounded up
|
||||
*
|
||||
* @param [in] x argument
|
||||
*
|
||||
* @returns Square root of argument, rounded up to next integer
|
||||
*
|
||||
* @remark This function is only appropriate to use for reasonably small arguments
|
||||
*/
|
||||
STATIC uint16_t sqrt_uint16( uint16_t x );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTION DECLARATIONS -------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Compute 16-bit payload CRC
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bytecount Input buffer length, in bytes
|
||||
*
|
||||
* @returns 16-bit CRC
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_payload_crc16( const uint8_t *data_in, uint16_t data_in_bytecount );
|
||||
|
||||
/*!
|
||||
* @brief Compute 8-bit header CRC
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bytecount Input buffer length, in bytes
|
||||
*
|
||||
* @returns 8-bit CRC
|
||||
*/
|
||||
STATIC uint8_t lr_fhss_header_crc8( const uint8_t *data_in, uint16_t data_in_bytecount );
|
||||
|
||||
/*!
|
||||
* @brief Whiten the payload
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bytecount Input buffer length, in bytes
|
||||
* @param [out] data_out Pointer to output buffer, of same length as input buffer
|
||||
*/
|
||||
STATIC void lr_fhss_payload_whitening( const uint8_t *data_in, uint16_t data_in_bytecount, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Extract specific bit from array of bytes
|
||||
*
|
||||
* @param [in] data_in Array of bytes
|
||||
* @param [in] bit_number Index of bit in array
|
||||
*
|
||||
* @returns Value of the bit
|
||||
*/
|
||||
STATIC uint8_t lr_fhss_extract_bit_in_byte_vector( const uint8_t *data_in, uint32_t bit_number );
|
||||
|
||||
/*!
|
||||
* @brief Set specific bit in array of bytes
|
||||
*
|
||||
* @param [in] data_in Array of bytes
|
||||
* @param [in] bit_number Index of bit in array
|
||||
* @param [in] bit_value Value to be set
|
||||
*/
|
||||
STATIC void lr_fhss_set_bit_in_byte_vector( uint8_t *vector, uint32_t bit_number, uint8_t bit_value );
|
||||
|
||||
/*!
|
||||
* @brief Compute 1/2 rate Viterbi encoding
|
||||
*
|
||||
* @param [in,out] encod_state Pointer to encoded state
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bitcount Length of input buffer, in bits
|
||||
* @param [in] data_out Pointer to output buffer
|
||||
*
|
||||
* @returns Length of output buffer, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_2_base( uint8_t *encod_state, const uint8_t *data_in,
|
||||
uint16_t data_in_bitcount, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Compute 1/3 rate Viterbi encoding
|
||||
*
|
||||
* @param [in,out] encod_state Pointer to encoded state
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bitcount Length of input buffer, in bits
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
*
|
||||
* @returns Length of output buffer, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_3_base( uint8_t *encod_state, const uint8_t *data_in,
|
||||
uint16_t data_in_bitcount, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Convolute using lr_fhss_convolution_encode_viterbi_1_2_base with optional tail-biting
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bitcount Length of input buffer, in bits
|
||||
* @param [in] tail_biting Set to true to activate tail-biting
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
*
|
||||
* @remark If tail-biting is activated, this function calls lr_fhss_convolution_encode_viterbi_1_2_base twice
|
||||
*
|
||||
* @returns Length of output buffer, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_2( const uint8_t *data_in, uint16_t data_in_bitcount,
|
||||
bool tail_biting, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Convolute using lr_fhss_convolution_encode_viterbi_1_3_base
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bitcount Length of input buffer, in bits
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
*
|
||||
* @returns Length of output buffer, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_3( const uint8_t *data_in, uint16_t data_in_bitcount,
|
||||
uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Computes payload interleaving
|
||||
*
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bitcount Length of input buffer, in bits
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
* @param [in] output_offset Output offset indicating where data must be placed, in bits, relative to data_out bit 0
|
||||
*
|
||||
* @returns Length of output buffer, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_payload_interleaving( const uint8_t *data_in, uint16_t data_in_bitcount, uint8_t *data_out,
|
||||
uint32_t output_offset );
|
||||
|
||||
/*!
|
||||
* @brief Create the raw LR-FHSS header
|
||||
*
|
||||
* @param [in] params Parameter structure
|
||||
* @param [in] hop_sequence_id The hop sequence ID that will be used to obtain hop-related data
|
||||
* @param [in] payload_length Length of application payload, in bytes
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
*/
|
||||
STATIC void lr_fhss_raw_header( const lr_fhss_v1_params_t *params, uint16_t hop_sequence_id, uint16_t payload_length,
|
||||
uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Store sync word index inside provided header
|
||||
*
|
||||
* @param [in] sync_word_index The sync word index to store
|
||||
* @param [out] data_out Pointer to output buffer
|
||||
*/
|
||||
STATIC void lr_fhss_store_header_sync_word_index( uint8_t sync_word_index, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Get the bit count and block count for a LR-FHSS frame
|
||||
*
|
||||
* @param [in] params Parameter structure
|
||||
* @param [in] payload_length Length of physical payload, in bytes
|
||||
* @param [out] nb_hops_out Number of LR-FHSS hops
|
||||
*
|
||||
* @returns Length of physical payload, in bits
|
||||
*/
|
||||
STATIC uint16_t lr_fhss_get_bit_and_hop_count( const lr_fhss_v1_params_t *params, uint16_t payload_length,
|
||||
uint8_t *nb_hops_out );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTION DEFINITIONS ---------------------------------------------
|
||||
*/
|
||||
|
||||
unsigned int lr_fhss_get_hop_sequence_count( const lr_fhss_v1_params_t *params )
|
||||
{
|
||||
if( ( params->grid == LR_FHSS_V1_GRID_25391_HZ ) ||
|
||||
( ( params->grid == LR_FHSS_V1_GRID_3906_HZ ) && ( params->bw < LR_FHSS_V1_BW_335938_HZ ) ) )
|
||||
{
|
||||
return 384;
|
||||
}
|
||||
return 512;
|
||||
}
|
||||
|
||||
void lr_fhss_process_parameters( const lr_fhss_v1_params_t *params, uint16_t payload_length, lr_fhss_digest_t *digest )
|
||||
{
|
||||
digest->nb_bits = lr_fhss_get_bit_and_hop_count( params, payload_length, &digest->nb_hops );
|
||||
|
||||
digest->nb_bytes = ( digest->nb_bits + 8 - 1 ) / 8;
|
||||
if( params->enable_hopping )
|
||||
{
|
||||
digest->nb_hops = digest->nb_hops;
|
||||
}
|
||||
else
|
||||
{
|
||||
digest->nb_hops = 1;
|
||||
}
|
||||
}
|
||||
|
||||
radio_status_t lr_fhss_get_hop_params( const lr_fhss_v1_params_t *params, lr_fhss_hop_params_t *hop_params,
|
||||
uint16_t *initial_state, uint16_t hop_sequence_id )
|
||||
{
|
||||
uint32_t channel_count = lr_fhss_channel_count[params->bw];
|
||||
|
||||
if( params->grid == LR_FHSS_V1_GRID_3906_HZ )
|
||||
{
|
||||
hop_params->n_grid = channel_count / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
hop_params->n_grid = channel_count / 52;
|
||||
}
|
||||
|
||||
switch( hop_params->n_grid )
|
||||
{
|
||||
case 10:
|
||||
case 22:
|
||||
case 28:
|
||||
case 30:
|
||||
case 35:
|
||||
case 47:
|
||||
{
|
||||
*initial_state = 6;
|
||||
hop_params->polynomial = lr_fhss_lfsr_poly1[hop_sequence_id >> 6];
|
||||
hop_params->xoring_seed = hop_sequence_id & 0x3F;
|
||||
if( hop_sequence_id >= 384 )
|
||||
{
|
||||
return RADIO_STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 60:
|
||||
case 62:
|
||||
{
|
||||
*initial_state = 56;
|
||||
hop_params->polynomial = lr_fhss_lfsr_poly1[hop_sequence_id >> 6];
|
||||
hop_params->xoring_seed = hop_sequence_id & 0x3F;
|
||||
if( hop_sequence_id >= 384 )
|
||||
{
|
||||
return RADIO_STATUS_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 86:
|
||||
case 99:
|
||||
{
|
||||
*initial_state = 6;
|
||||
hop_params->polynomial = lr_fhss_lfsr_poly2[hop_sequence_id >> 7];
|
||||
hop_params->xoring_seed = hop_sequence_id & 0x7F;
|
||||
break;
|
||||
}
|
||||
case 185:
|
||||
case 198:
|
||||
{
|
||||
*initial_state = 6;
|
||||
hop_params->polynomial = lr_fhss_lfsr_poly3[hop_sequence_id >> 8];
|
||||
hop_params->xoring_seed = hop_sequence_id & 0xFF;
|
||||
break;
|
||||
}
|
||||
case 390:
|
||||
case 403:
|
||||
{
|
||||
*initial_state = 6;
|
||||
hop_params->polynomial = 264;
|
||||
hop_params->xoring_seed = hop_sequence_id;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return RADIO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
hop_params->hop_sequence_id = hop_sequence_id;
|
||||
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
uint16_t lr_fhss_get_next_state( uint16_t *lfsr_state, const lr_fhss_hop_params_t *hop_params )
|
||||
{
|
||||
uint16_t hop;
|
||||
|
||||
do
|
||||
{
|
||||
uint16_t lsb = *lfsr_state & 1;
|
||||
*lfsr_state >>= 1;
|
||||
if( lsb )
|
||||
{
|
||||
*lfsr_state ^= hop_params->polynomial;
|
||||
}
|
||||
hop = hop_params->xoring_seed;
|
||||
if( hop != *lfsr_state )
|
||||
{
|
||||
hop ^= *lfsr_state;
|
||||
}
|
||||
} while( hop > hop_params->n_grid );
|
||||
|
||||
return hop - 1;
|
||||
}
|
||||
|
||||
int16_t lr_fhss_get_next_freq_in_grid( uint16_t *lfsr_state, const lr_fhss_hop_params_t *hop_params,
|
||||
const lr_fhss_v1_params_t *params )
|
||||
{
|
||||
uint16_t n_i;
|
||||
|
||||
if( params->enable_hopping )
|
||||
{
|
||||
n_i = lr_fhss_get_next_state( lfsr_state, hop_params );
|
||||
}
|
||||
else
|
||||
{
|
||||
n_i = hop_params->hop_sequence_id % hop_params->n_grid;
|
||||
}
|
||||
|
||||
if( n_i < ( hop_params->n_grid >> 1 ) )
|
||||
{
|
||||
return n_i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return n_i - hop_params->n_grid;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************** Build LR-FHSS Frame ***********************************************************
|
||||
* Core of the LR-FHSS frame generator *
|
||||
* *
|
||||
* In |---------| |-----| |-----------------| |-------| |------------| |----------------------| Out *
|
||||
**---|Whitening|--|CRC16|--|Outer Code + CRC8|--|Viterbi|--|Interleaving|--|Sync+header+crc Header|------ *
|
||||
* |---------| |-----| |-----------------|--|-------| |------------| |----------------------| *
|
||||
* *
|
||||
**********************************************************************************************************/
|
||||
uint16_t lr_fhss_build_frame( const lr_fhss_v1_params_t *params, uint16_t hop_sequence_id, const uint8_t *data_in,
|
||||
uint16_t data_in_bytecount, uint8_t *data_out )
|
||||
{
|
||||
uint8_t data_out_tmp[LR_FHSS_MAX_TMP_BUF_BYTES] = { 0 };
|
||||
|
||||
lr_fhss_payload_whitening( data_in, data_in_bytecount, data_out );
|
||||
uint16_t payload_crc = lr_fhss_payload_crc16( data_out, data_in_bytecount );
|
||||
|
||||
data_out[data_in_bytecount] = ( payload_crc >> 8 ) & 0xFF;
|
||||
data_out[data_in_bytecount + 1] = payload_crc & 0xFF;
|
||||
data_out[data_in_bytecount + 2] = 0;
|
||||
|
||||
// the 1/3 encoded bytes can go up to LR_FHSS_MAX_TMP_BUF_BYTES temporarily, before puncturing it
|
||||
uint16_t nb_bits =
|
||||
lr_fhss_convolution_encode_viterbi_1_3( data_out, 8 * ( data_in_bytecount + 2 ) + 6, data_out_tmp );
|
||||
|
||||
// Avoid putting random stack data into payload
|
||||
memset( data_out, 0, LR_FHSS_MAX_PHY_PAYLOAD_BYTES );
|
||||
|
||||
if( params->cr != LR_FHSS_V1_CR_1_3 )
|
||||
{
|
||||
// this assumes first matrix values are always the same, which is the case
|
||||
uint32_t matrix_index = 0;
|
||||
uint8_t matrix[15] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 };
|
||||
uint8_t matrix_len = 0;
|
||||
switch( params->cr )
|
||||
{
|
||||
case LR_FHSS_V1_CR_5_6:
|
||||
matrix_len = 15;
|
||||
break;
|
||||
case LR_FHSS_V1_CR_2_3:
|
||||
matrix_len = 6;
|
||||
break;
|
||||
case LR_FHSS_V1_CR_1_2:
|
||||
matrix_len = 3;
|
||||
break;
|
||||
default:
|
||||
// LR_FHSS_V1_CR_1_3 is excluded from this code block
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t j = 0;
|
||||
for( uint32_t i = 0; i < nb_bits; i++ )
|
||||
{
|
||||
if( matrix[matrix_index] )
|
||||
{
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, j++, lr_fhss_extract_bit_in_byte_vector( data_out_tmp, i ) );
|
||||
}
|
||||
if( ++matrix_index == matrix_len )
|
||||
{
|
||||
matrix_index = 0;
|
||||
}
|
||||
}
|
||||
nb_bits = j;
|
||||
|
||||
memcpy( data_out_tmp, data_out, ( nb_bits + 7 ) / 8 );
|
||||
}
|
||||
|
||||
// Interleave directly to data_out
|
||||
nb_bits =
|
||||
lr_fhss_payload_interleaving( data_out_tmp, nb_bits, data_out, LR_FHSS_HEADER_BITS * params->header_count );
|
||||
|
||||
// Build the header
|
||||
uint8_t raw_header[LR_FHSS_HALF_HDR_BYTES];
|
||||
lr_fhss_raw_header( params, hop_sequence_id, data_in_bytecount, raw_header );
|
||||
|
||||
uint16_t header_offset = 0;
|
||||
for( uint32_t i = 0; i < params->header_count; i++ )
|
||||
{
|
||||
// Insert appropriate index into header
|
||||
lr_fhss_store_header_sync_word_index( params->header_count - i - 1, raw_header );
|
||||
raw_header[4] = lr_fhss_header_crc8( raw_header, 4 );
|
||||
|
||||
// Convolutional encode
|
||||
uint8_t coded_header[LR_FHSS_HDR_BYTES] = { 0 };
|
||||
lr_fhss_convolution_encode_viterbi_1_2( raw_header, LR_FHSS_HALF_HDR_BITS, 1, coded_header );
|
||||
|
||||
// Header guard bits
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, header_offset + 0, 0 );
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, header_offset + 1, 0 );
|
||||
|
||||
// Interleave the header directly to the physical payload buffer
|
||||
for( uint32_t j = 0; j < LR_FHSS_HALF_HDR_BITS; j++ )
|
||||
{
|
||||
lr_fhss_set_bit_in_byte_vector(
|
||||
data_out, header_offset + 2 + j,
|
||||
lr_fhss_extract_bit_in_byte_vector( coded_header, lr_fhss_header_interleaver_minus_one[j] ) );
|
||||
}
|
||||
for( uint32_t j = 0; j < LR_FHSS_HALF_HDR_BITS; j++ )
|
||||
{
|
||||
lr_fhss_set_bit_in_byte_vector(
|
||||
data_out, header_offset + 2 + LR_FHSS_HALF_HDR_BITS + LR_FHSS_SYNC_WORD_BITS + j,
|
||||
lr_fhss_extract_bit_in_byte_vector( coded_header,
|
||||
lr_fhss_header_interleaver_minus_one[LR_FHSS_HALF_HDR_BITS + j] ) );
|
||||
}
|
||||
|
||||
// Copy the sync word to the physical payload buffer
|
||||
for( uint32_t j = 0; j < LR_FHSS_SYNC_WORD_BITS; j++ )
|
||||
{
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, header_offset + 2 + LR_FHSS_HALF_HDR_BITS + j,
|
||||
lr_fhss_extract_bit_in_byte_vector( params->sync_word, j ) );
|
||||
}
|
||||
|
||||
header_offset += LR_FHSS_HEADER_BITS;
|
||||
}
|
||||
|
||||
return ( header_offset + nb_bits + 7 ) / 8;
|
||||
}
|
||||
|
||||
uint32_t lr_fhss_get_time_on_air_in_ms( const lr_fhss_v1_params_t *params, uint16_t payload_length )
|
||||
{
|
||||
// Multiply by 1000 / 488.28125, or equivalently 256/125, rounding up
|
||||
return ( ( lr_fhss_get_time_on_air_numerator( params, payload_length ) << 8 ) + 124 ) / 125;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTION DEFINITIONS --------------------------------------------
|
||||
*/
|
||||
|
||||
STATIC uint16_t lr_fhss_payload_crc16( const uint8_t *data_in, uint16_t data_in_bytecount )
|
||||
{
|
||||
uint16_t crc16 = 65535;
|
||||
uint8_t pos = 0;
|
||||
for( uint16_t k = 0; k < data_in_bytecount; k++ )
|
||||
{
|
||||
pos = ( ( crc16 >> 8 ) ^ data_in[k] );
|
||||
crc16 = ( crc16 << 8 ) ^ lr_fhss_payload_crc16_lut[pos];
|
||||
}
|
||||
return crc16;
|
||||
}
|
||||
|
||||
STATIC uint8_t lr_fhss_header_crc8( const uint8_t *data_in, uint16_t data_in_bytecount )
|
||||
{
|
||||
uint8_t crc8 = 255;
|
||||
for( uint16_t k = 0; k < data_in_bytecount; k++ )
|
||||
{
|
||||
uint8_t pos = ( crc8 ^ data_in[k] );
|
||||
crc8 = lr_fhss_header_crc8_lut[pos];
|
||||
}
|
||||
|
||||
return crc8;
|
||||
}
|
||||
|
||||
STATIC void lr_fhss_payload_whitening( const uint8_t *data_in, uint16_t data_in_bytecount, uint8_t *data_out )
|
||||
{
|
||||
uint8_t lfsr = 0xFF;
|
||||
|
||||
for( uint8_t index = 0; index < data_in_bytecount; index++ )
|
||||
{
|
||||
uint8_t u = data_in[index] ^ lfsr;
|
||||
data_out[index] = ( ( u & 0x0F ) << 4 ) | ( ( u & 0xF0 ) >> 4 );
|
||||
lfsr =
|
||||
( lfsr << 1 ) | ( ( ( lfsr & 0x80 ) >> 7 ) ^
|
||||
( ( ( lfsr & 0x20 ) >> 5 ) ^ ( ( ( lfsr & 0x10 ) >> 4 ) ^ ( ( lfsr & 0x8 ) >> 3 ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
STATIC uint8_t lr_fhss_extract_bit_in_byte_vector( const uint8_t *data_in, uint32_t bit_number )
|
||||
{
|
||||
uint32_t index = bit_number >> 3;
|
||||
uint8_t bit_pos = 7 - ( bit_number % 8 );
|
||||
|
||||
if( data_in[index] & ( 1 << bit_pos ) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC void lr_fhss_set_bit_in_byte_vector( uint8_t *vector, uint32_t bit_number, uint8_t bit_value )
|
||||
{
|
||||
uint32_t index = bit_number >> 3;
|
||||
uint8_t bit_pos = 7 - ( bit_number % 8 );
|
||||
|
||||
vector[index] = ( vector[index] & ( 0xff - ( 1 << bit_pos ) ) ) | ( bit_value << bit_pos );
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_2_base( uint8_t *encod_state, const uint8_t *data_in,
|
||||
uint16_t data_in_bitcount, uint8_t *data_out )
|
||||
{
|
||||
uint8_t g1g0;
|
||||
uint8_t cur_bit;
|
||||
uint16_t ind_bit;
|
||||
uint16_t data_out_bitcount = 0;
|
||||
uint16_t bin_out_16 = 0;
|
||||
|
||||
for( ind_bit = 0; ind_bit < data_in_bitcount; ind_bit++ )
|
||||
{
|
||||
cur_bit = lr_fhss_extract_bit_in_byte_vector( data_in, ind_bit );
|
||||
g1g0 = lr_fhss_viterbi_1_2_table[*encod_state][cur_bit];
|
||||
*encod_state = ( *encod_state * 2 + cur_bit ) % 16;
|
||||
bin_out_16 |= ( g1g0 << ( ( 7 - ( ind_bit % 8 ) ) << 1 ) );
|
||||
if( ind_bit % 8 == 7 )
|
||||
{
|
||||
*data_out++ = ( uint8_t )( bin_out_16 >> 8 );
|
||||
*data_out++ = ( uint8_t ) bin_out_16;
|
||||
bin_out_16 = 0;
|
||||
}
|
||||
data_out_bitcount += 2;
|
||||
}
|
||||
if( ind_bit % 8 )
|
||||
{
|
||||
*data_out++ = ( uint8_t )( bin_out_16 >> 8 );
|
||||
*data_out++ = ( uint8_t ) bin_out_16;
|
||||
bin_out_16 = 0;
|
||||
}
|
||||
|
||||
return data_out_bitcount;
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_3_base( uint8_t *encod_state, const uint8_t *data_in,
|
||||
uint16_t data_in_bitcount, uint8_t *data_out )
|
||||
{
|
||||
uint8_t g1g0;
|
||||
uint8_t cur_bit;
|
||||
uint16_t ind_bit;
|
||||
uint16_t data_out_bitcount = 0;
|
||||
uint32_t bin_out_32 = 0;
|
||||
|
||||
for( ind_bit = 0; ind_bit < data_in_bitcount; ind_bit++ )
|
||||
{
|
||||
cur_bit = lr_fhss_extract_bit_in_byte_vector( data_in, ind_bit );
|
||||
g1g0 = lr_fhss_viterbi_1_3_table[*encod_state][cur_bit];
|
||||
*encod_state = ( *encod_state * 2 + cur_bit ) % 64;
|
||||
bin_out_32 |= ( g1g0 << ( ( 7 - ( ind_bit % 8 ) ) * 3 ) );
|
||||
if( ind_bit % 8 == 7 )
|
||||
{
|
||||
*data_out++ = ( uint8_t )( bin_out_32 >> 16 );
|
||||
*data_out++ = ( uint8_t )( bin_out_32 >> 8 );
|
||||
*data_out++ = ( uint8_t ) bin_out_32;
|
||||
bin_out_32 = 0;
|
||||
}
|
||||
data_out_bitcount += 3;
|
||||
}
|
||||
if( ind_bit % 8 )
|
||||
{
|
||||
*data_out++ = ( uint8_t )( bin_out_32 >> 16 );
|
||||
*data_out++ = ( uint8_t )( bin_out_32 >> 8 );
|
||||
*data_out++ = ( uint8_t ) bin_out_32;
|
||||
bin_out_32 = 0;
|
||||
}
|
||||
|
||||
return data_out_bitcount;
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_2( const uint8_t *data_in, uint16_t data_in_bitcount,
|
||||
bool tail_biting, uint8_t *data_out )
|
||||
{
|
||||
uint8_t encode_state = 0;
|
||||
uint16_t data_out_bitcount;
|
||||
|
||||
data_out_bitcount =
|
||||
lr_fhss_convolution_encode_viterbi_1_2_base( &encode_state, data_in, data_in_bitcount, data_out );
|
||||
if( tail_biting )
|
||||
{
|
||||
data_out_bitcount =
|
||||
lr_fhss_convolution_encode_viterbi_1_2_base( &encode_state, data_in, data_in_bitcount, data_out );
|
||||
}
|
||||
return data_out_bitcount;
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_convolution_encode_viterbi_1_3( const uint8_t *data_in, uint16_t data_in_bitcount,
|
||||
uint8_t *data_out )
|
||||
{
|
||||
uint8_t encode_state = 0;
|
||||
return lr_fhss_convolution_encode_viterbi_1_3_base( &encode_state, data_in, data_in_bitcount, data_out );
|
||||
}
|
||||
|
||||
STATIC uint16_t sqrt_uint16( uint16_t x )
|
||||
{
|
||||
uint16_t y = 0;
|
||||
|
||||
while( y * y < x )
|
||||
{
|
||||
y += 1;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_payload_interleaving( const uint8_t *data_in, uint16_t data_in_bitcount, uint8_t *data_out,
|
||||
uint32_t output_offset )
|
||||
{
|
||||
uint16_t step = sqrt_uint16( data_in_bitcount );
|
||||
const uint16_t step_v = step >> 1;
|
||||
step = step << 1;
|
||||
|
||||
uint16_t pos = 0;
|
||||
uint16_t st_idx = 0;
|
||||
uint16_t st_idx_init = 0;
|
||||
int16_t bits_left = data_in_bitcount;
|
||||
uint16_t out_row_index = output_offset;
|
||||
|
||||
while( bits_left > 0 )
|
||||
{
|
||||
int16_t in_row_width = bits_left;
|
||||
if( in_row_width > LR_FHSS_FRAG_BITS )
|
||||
{
|
||||
in_row_width = LR_FHSS_FRAG_BITS;
|
||||
}
|
||||
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, 0 + out_row_index, 0 ); // guard bits
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, 1 + out_row_index, 0 ); // guard bits
|
||||
for( uint32_t j = 0; j < in_row_width; j++ )
|
||||
{
|
||||
lr_fhss_set_bit_in_byte_vector( data_out, j + 2 + out_row_index,
|
||||
lr_fhss_extract_bit_in_byte_vector( data_in, pos ) ); // guard bit
|
||||
|
||||
pos += step;
|
||||
if( pos >= data_in_bitcount )
|
||||
{
|
||||
st_idx += step_v;
|
||||
if( st_idx >= step )
|
||||
{
|
||||
st_idx_init++;
|
||||
st_idx = st_idx_init;
|
||||
}
|
||||
pos = st_idx;
|
||||
}
|
||||
}
|
||||
|
||||
bits_left -= LR_FHSS_FRAG_BITS;
|
||||
out_row_index += 2 + in_row_width;
|
||||
}
|
||||
|
||||
return out_row_index - output_offset;
|
||||
}
|
||||
|
||||
STATIC void lr_fhss_raw_header( const lr_fhss_v1_params_t *params, uint16_t hop_sequence_id, uint16_t payload_length,
|
||||
uint8_t *data_out )
|
||||
{
|
||||
data_out[0] = payload_length;
|
||||
data_out[1] = ( params->modulation_type << 5 ) + ( params->cr << 3 ) + ( params->grid << 2 ) +
|
||||
( params->enable_hopping ? 2 : 0 ) + ( params->bw >> 3 );
|
||||
data_out[2] = ( ( params->bw & 0x07 ) << 5 ) + ( hop_sequence_id >> 4 );
|
||||
data_out[3] = ( ( hop_sequence_id & 0x000F ) << 4 );
|
||||
}
|
||||
|
||||
STATIC void lr_fhss_store_header_sync_word_index( uint8_t sync_word_index, uint8_t *data_out )
|
||||
{
|
||||
data_out[3] = ( data_out[3] & ~0x0C ) | ( sync_word_index << 2 );
|
||||
}
|
||||
|
||||
STATIC uint16_t lr_fhss_get_bit_and_hop_count( const lr_fhss_v1_params_t *params, uint16_t payload_length,
|
||||
uint8_t *nb_hops_out )
|
||||
{
|
||||
// check length : payload + 16bit crc, encoded, padded to 48bits, adding 2 guard bit / 48bits
|
||||
uint16_t length_bits = ( payload_length + 2 ) * 8 + 6;
|
||||
switch( params->cr )
|
||||
{
|
||||
case LR_FHSS_V1_CR_5_6:
|
||||
length_bits = ( ( length_bits * 6 ) + 4 ) / 5;
|
||||
break;
|
||||
|
||||
case LR_FHSS_V1_CR_2_3:
|
||||
length_bits = length_bits * 3 / 2;
|
||||
break;
|
||||
|
||||
case LR_FHSS_V1_CR_1_2:
|
||||
length_bits = length_bits * 2;
|
||||
break;
|
||||
|
||||
case LR_FHSS_V1_CR_1_3:
|
||||
length_bits = length_bits * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
*nb_hops_out = ( length_bits + 47 ) / 48 + params->header_count;
|
||||
|
||||
// calculate total number of payload bits, after breaking into blocks
|
||||
uint16_t payload_bits = length_bits / LR_FHSS_FRAG_BITS * LR_FHSS_BLOCK_BITS;
|
||||
uint16_t last_block_bits = length_bits % LR_FHSS_FRAG_BITS;
|
||||
if( last_block_bits > 0 )
|
||||
{
|
||||
// add the 2 guard bits for the last block + the actual remaining payload bits
|
||||
payload_bits += last_block_bits + 2;
|
||||
}
|
||||
|
||||
return ( LR_FHSS_HEADER_BITS * params->header_count ) + payload_bits;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
198
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/lr_fhss_mac.h
vendored
Normal file
198
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/lr_fhss_mac.h
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
/*!
|
||||
* @file lr_fhss_mac.h
|
||||
*
|
||||
* @brief Radio-independent LR-FHSS algorithms driver internal API
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2021. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LR_FHSS_MAC_H__
|
||||
#define LR_FHSS_MAC_H__
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "radio_def.h"
|
||||
#include "lr_fhss_v1_base_types.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Digest, holding physical payload length and hop information
|
||||
*/
|
||||
typedef struct lr_fhss_digest_s
|
||||
{
|
||||
uint16_t nb_bytes; /**< Length of LR-FHSS frame, in bytes */
|
||||
uint16_t nb_bits; /**< Number of bits */
|
||||
uint8_t nb_hops; /**< Number of hops */
|
||||
} lr_fhss_digest_t;
|
||||
|
||||
/*!
|
||||
* Hopping configuration, created by @ref lr_fhss_get_hop_params, and used to generate hop sequence
|
||||
*/
|
||||
typedef struct lr_fhss_hop_params_s
|
||||
{
|
||||
uint16_t n_grid; /**< Ngrid, as described in specification */
|
||||
uint16_t polynomial; /**< polynomial, as described in specification, used for hop sequence generation */
|
||||
uint16_t xoring_seed; /**< xoring seed, as described in specification, used for hop sequence generation */
|
||||
uint16_t hop_sequence_id; /**< Hopping sequence seed, as described in specification, determines which hop sequence
|
||||
will be used */
|
||||
} lr_fhss_hop_params_t;
|
||||
|
||||
/*!
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Return the number of hop sequences available using the given parameters
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
*
|
||||
* @returns Number of valid hop sequences (512 or 384)
|
||||
*/
|
||||
unsigned int lr_fhss_get_hop_sequence_count( const lr_fhss_v1_params_t *params );
|
||||
|
||||
/*!
|
||||
* @brief Fill the digest structure with various size-related data for a LR-FHSS frame
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
* @param [in] payload_length Length of payload, in bytes
|
||||
* @param [out] digest Contains block count byte count, and number of hops
|
||||
*/
|
||||
void lr_fhss_process_parameters( const lr_fhss_v1_params_t *params, uint16_t payload_length, lr_fhss_digest_t *digest );
|
||||
|
||||
/*!
|
||||
* @brief Fill the hop structure with various hop-related data for a LR-FHSS frame, and provide initial state
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
* @param [out] hop_params Hop parameter structure
|
||||
* @param [out] initial_state Initial LFSR state
|
||||
* @param [in] hop_sequence_id The hop sequence ID that will be used to obtain hop-related data
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t lr_fhss_get_hop_params( const lr_fhss_v1_params_t *params, lr_fhss_hop_params_t *hop_params,
|
||||
uint16_t *initial_state, uint16_t hop_sequence_id );
|
||||
|
||||
/*!
|
||||
* @brief Update the LFSR state by performing a hop, and return the hop grid position
|
||||
*
|
||||
* @param [in,out] lfsr_state LFSR state
|
||||
* @param [in] hop_params Hop parameter structure
|
||||
*
|
||||
* @returns Hop position in the grid
|
||||
*/
|
||||
uint16_t lr_fhss_get_next_state( uint16_t *lfsr_state, const lr_fhss_hop_params_t *hop_params );
|
||||
|
||||
/*!
|
||||
* @brief Return the frequency in grid units for given LR-FHSS parameters and hop index
|
||||
*
|
||||
* @param [in,out] lfsr_state LFSR state
|
||||
* @param [in] hop_params Hop parameter structure
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
*
|
||||
* @returns Frequency, in grid units
|
||||
*/
|
||||
int16_t lr_fhss_get_next_freq_in_grid( uint16_t *lfsr_state, const lr_fhss_hop_params_t *hop_params,
|
||||
const lr_fhss_v1_params_t *params );
|
||||
|
||||
/*!
|
||||
* @brief Construct the LR-FHSS frame
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
* @param [in] hop_sequence_id The hop sequence ID that will be used to obtain hop-related data
|
||||
* @param [in] data_in Pointer to input buffer
|
||||
* @param [in] data_in_bytecount Length of input buffer, in bytes
|
||||
* @param [out] data_out Pointer to a buffer into which the final LR-FHSS frame is stored, large enough to hold
|
||||
* 255 bytes
|
||||
*
|
||||
* @returns Length of frame, in bytes
|
||||
*/
|
||||
uint16_t lr_fhss_build_frame( const lr_fhss_v1_params_t *params, uint16_t hop_sequence_id, const uint8_t *data_in,
|
||||
uint16_t data_in_bytecount, uint8_t *data_out );
|
||||
|
||||
/*!
|
||||
* @brief Compute the numerator for LR-FHSS time-on-air computation.
|
||||
*
|
||||
* @remark To get the actual time-on-air in seconds, this value must be divided by the LR-FHSS bitrate in bits per
|
||||
* second, 488.28125.
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
* @param [in] payload_length Length of application payload, in bytes
|
||||
*
|
||||
* @returns LR-FHSS time-on-air numerator
|
||||
*/
|
||||
static inline uint32_t lr_fhss_get_time_on_air_numerator( const lr_fhss_v1_params_t *params, uint16_t payload_length )
|
||||
{
|
||||
lr_fhss_digest_t digest;
|
||||
lr_fhss_process_parameters( params, payload_length, &digest );
|
||||
|
||||
return digest.nb_bits;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the time on air in ms for LR-FHSS transmission
|
||||
*
|
||||
* @param [in] params LR-FHSS parameter structure
|
||||
* @param [in] payload_length Length of application-layer payload
|
||||
*
|
||||
* @returns Time-on-air value in ms for LR-FHSS transmission
|
||||
*/
|
||||
uint32_t lr_fhss_get_time_on_air_in_ms( const lr_fhss_v1_params_t *params, uint16_t payload_length );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LR_FHSS_MAC_H__
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
2390
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio.c
vendored
Normal file
2390
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1205
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
vendored
Normal file
1205
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1307
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.h
vendored
Normal file
1307
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_driver.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1112
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_fw.c
vendored
Normal file
1112
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_fw.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
154
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_fw.h
vendored
Normal file
154
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/radio_fw.h
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file radio_fw.h
|
||||
* @author MCD Application Team
|
||||
* @brief Extends radio capabilities (whitening, long packet)
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2020(-2021) STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __RADIO_FW_H__
|
||||
#define __RADIO_FW_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "radio_def.h"
|
||||
#include "radio_ex.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
/*reserved for SubGHz_Phy internal MW communication*/
|
||||
typedef enum
|
||||
{
|
||||
CONFIG_RX = 0,
|
||||
CONFIG_TX,
|
||||
} ConfigGenericRTx_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TxConfigGeneric_t *TxConfig;
|
||||
RxConfigGeneric_t *RxConfig;
|
||||
ConfigGenericRTx_t rtx;
|
||||
} ConfigGeneric_t;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
|
||||
/*!
|
||||
* @brief Initialise the RFW module and enables custom whitening, optionally long packet feature
|
||||
*
|
||||
* @param [in] config rx or tx config from the application
|
||||
* @param [in] RadioEvents from the radio
|
||||
* @param [in] TimeoutTimerEvent Timer for Rx or Tx timeout event
|
||||
* @return 0 when no parameters error, -1 otherwise
|
||||
*/
|
||||
int32_t RFW_Init( ConfigGeneric_t *config, RadioEvents_t *RadioEvents, TimerEvent_t *TimeoutTimerEvent );
|
||||
|
||||
/*!
|
||||
* @brief Return whether the RFW module is enabled
|
||||
*
|
||||
* @return 0 when not initialised, -1 otherwise
|
||||
*/
|
||||
uint8_t RFW_Is_Init( void );
|
||||
|
||||
/*!
|
||||
* @brief Return whether the RFW module long packet is enabled
|
||||
*
|
||||
* @return 0 when not initialised, -1 otherwise
|
||||
*/
|
||||
uint8_t RFW_Is_LongPacketModeEnabled( void );
|
||||
|
||||
/*!
|
||||
* @brief Return whether the RFW module long packet is enabled
|
||||
*
|
||||
* @param [in] Modem set in the radio
|
||||
*/
|
||||
void RFW_SetRadioModem( RadioModems_t Modem );
|
||||
|
||||
/*!
|
||||
* @brief DeInitialise the RFW module and enable custom whitening and optionally long packet feature
|
||||
*
|
||||
*/
|
||||
void RFW_DeInit( void );
|
||||
|
||||
/*!
|
||||
* @brief DeInitialise the TxLongPacket
|
||||
*
|
||||
*/
|
||||
void RFW_DeInit_TxLongPacket( void );
|
||||
|
||||
/*!
|
||||
* @brief Set antenna switch output to be used in Tx
|
||||
*
|
||||
* @param [in] AntSwitch RFO_LP or FRO_HP
|
||||
*
|
||||
*/
|
||||
void RFW_SetAntSwitch( uint8_t AntSwitch );
|
||||
|
||||
/*!
|
||||
* @brief Initialise reception for IBM whitening case
|
||||
*
|
||||
* @return 0 when RFW_ENABLE exists, -1 otherwise
|
||||
*/
|
||||
int32_t RFW_ReceiveInit( void );
|
||||
|
||||
/*!
|
||||
* @brief Initialise transmission for IBM whitening case
|
||||
*
|
||||
* @param [in,out] inOutBuffer pointer of exchange buffer to send or receive data
|
||||
* @param [in] size input buffer size
|
||||
* @param [out] outSize output buffer size
|
||||
*
|
||||
*/
|
||||
int32_t RFW_TransmitInit( uint8_t *inOutBuffer, uint8_t size, uint8_t *outSize );
|
||||
|
||||
/*!
|
||||
* @brief Starts receiving payload. Called at Rx Sync IRQ
|
||||
*
|
||||
*/
|
||||
void RFW_ReceivePayload( void );
|
||||
|
||||
/*!
|
||||
* @brief Starts transmitting long Packet, note packet length may be on 1 bytes depending on config
|
||||
*
|
||||
* @param [in] payload_size total payload size to be sent
|
||||
* @param [in] timeout Reception timeout [ms]
|
||||
* @param [in] TxLongPacketGetNextChunkCb callback to be implemented on user side to feed partial chunk
|
||||
* buffer: source buffer allocated by the app
|
||||
* size: size in bytes to feed. User to implement the offset based on previous chunk request
|
||||
* @return 0 when no parameters error, -1 otherwise
|
||||
*/
|
||||
int32_t RFW_TransmitLongPacket( uint16_t payload_size, uint32_t timeout, void ( *TxLongPacketGetNextChunkCb )( uint8_t **buffer, uint8_t buffer_size ) );
|
||||
|
||||
/*!
|
||||
* @brief Starts receiving long Packet, packet maybe short
|
||||
*
|
||||
* @param [in] boosted_mode boosted_mode: 0 normal Rx, 1:improved sensitivity
|
||||
* @param [in] timeout Reception timeout [ms]
|
||||
* @param [in] RxLongStorePacketChunkCb callback to be implemented on user side to record partial chunk in the application
|
||||
* buffer: source buffer allocated in the radio driver
|
||||
* size: size in bytes to record
|
||||
* @return 0 when no parameters error, -1 otherwise
|
||||
*/
|
||||
int32_t RFW_ReceiveLongPacket( uint8_t boosted_mode, uint32_t timeout, void ( *RxLongStorePacketChunkCb )( uint8_t *buffer, uint8_t chunk_size ) );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__RADIO_FW_H__*/
|
||||
53
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/subghz_phy_version.h
vendored
Normal file
53
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/subghz_phy_version.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/******************************************************************************
|
||||
* @file subghz_phy_version.h
|
||||
* @author MCD Application Team
|
||||
* @brief defines the radio driver version
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2020(-2021) STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef __SUBGHZ_PHY_VERSION_H__
|
||||
#define __SUBGHZ_PHY_VERSION_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* __SUBGHZ_PHY_TYPE: 0x01 STM32WL
|
||||
0x61 SX126X
|
||||
0x72 SX1272
|
||||
0x76 SX1276 */
|
||||
|
||||
#define SUBGHZ_PHY_VERSION_MAIN (0x01U) /*!< [31:24] main version */
|
||||
#define SUBGHZ_PHY_VERSION_SUB1 (0x03U) /*!< [23:16] sub1 version */
|
||||
#define SUBGHZ_PHY_VERSION_SUB2 (0x01U) /*!< [15:8] sub2 version */
|
||||
#define SUBGHZ_PHY_TYPE (0x01U) /*!< [7:0] type version */
|
||||
#define SUBGHZ_PHY_VERSION ((SUBGHZ_PHY_VERSION_MAIN << 24) \
|
||||
|(SUBGHZ_PHY_VERSION_SUB1 << 16) \
|
||||
|(SUBGHZ_PHY_VERSION_SUB2 << 8) \
|
||||
|(SUBGHZ_PHY_TYPE))
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* External variables --------------------------------------------------------*/
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SUBGHZ_PHY_VERSION_H__*/
|
||||
425
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/wl_lr_fhss.c
vendored
Normal file
425
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/wl_lr_fhss.c
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
/*!
|
||||
* @file wl_lr_fhss.c
|
||||
*
|
||||
* @brief STM32WL LR-FHSS driver implementation
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2021. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
#include "wl_lr_fhss.h"
|
||||
#include "lr_fhss_mac.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE MACROS-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE CONSTANTS -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* \cond */
|
||||
|
||||
#define WL_SET_MODULATION_PARAMS ( 0x8B )
|
||||
#define WL_SET_PKT_PARAMS ( 0x8C )
|
||||
|
||||
#define WL_LR_FHSS_DISABLE_HOPPING ( 0 )
|
||||
#define WL_LR_FHSS_ENABLE_HOPPING ( 1 )
|
||||
|
||||
#define WL_LR_FHSS_HOP_TABLE_SIZE ( 16 )
|
||||
#define WL_LR_FHSS_HOP_ENTRY_SIZE ( 6 )
|
||||
|
||||
#define WL_LR_FHSS_GRID_3906_HZ_PLL_STEPS ( 4096 )
|
||||
#define WL_LR_FHSS_GRID_25391_HZ_PLL_STEPS ( 26624 )
|
||||
|
||||
#define WL_LR_FHSS_GRID_INDEX_TO_PLL_STEPS ( 512 )
|
||||
|
||||
/* \endcond */
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE TYPES -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE VARIABLES -------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTION DECLARATIONS -------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief Configure the radio to perform frequency hopping
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] nb_bytes Total number of bytes
|
||||
* @param [in] nb_hops Total number of hops
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_write_hop_config( const uint8_t nb_bytes, const uint8_t nb_hops );
|
||||
|
||||
/*!
|
||||
* @brief Write a hop frequency/duration pair to the radio hop table
|
||||
*
|
||||
* @param [in] context Chip implementation context
|
||||
* @param [in] index Index to chip hop table
|
||||
* @param [in] nb_symbols Hop duration in symbols
|
||||
* @param [in] freq_in_pll_steps Hop frequency, in PLL steps
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_write_hop( const uint8_t index, const uint16_t nb_symbols,
|
||||
const uint32_t freq_in_pll_steps );
|
||||
|
||||
/*!
|
||||
* @brief Get Frequency, in PLL steps, of the next hop
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [out] state stm32wl LR-FHSS state structure that will be initialized by this function
|
||||
*
|
||||
* @returns Frequency, in PLL steps, of the next hop
|
||||
*/
|
||||
uint32_t wl_lr_fhss_get_next_freq_in_pll_steps( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state );
|
||||
|
||||
/*!
|
||||
* @brief Get grid frequency, in PLL steps
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
*
|
||||
* @returns Grid frequency, in PLL steps
|
||||
*/
|
||||
static inline unsigned int wl_lr_fhss_get_grid_in_pll_steps( const wl_lr_fhss_params_t *params );
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS DEFINITION ---------------------------------------------
|
||||
*/
|
||||
|
||||
radio_status_t wl_lr_fhss_init( const wl_lr_fhss_params_t *params )
|
||||
{
|
||||
radio_status_t status = RADIO_STATUS_OK;
|
||||
SUBGRF_SetPacketType( PACKET_TYPE_LR_FHSS );
|
||||
|
||||
uint8_t pkt_params_buffer[8] = {0};
|
||||
uint8_t mod_params_buffer[] = {32, 0, 0, MOD_SHAPING_G_BT_1, 0, 0, 0, 0};
|
||||
|
||||
SUBGRF_WriteCommand( RADIO_SET_PACKETPARAMS, pkt_params_buffer, sizeof( pkt_params_buffer ) );
|
||||
|
||||
SUBGRF_WriteCommand( RADIO_SET_MODULATIONPARAMS, mod_params_buffer, sizeof( mod_params_buffer ) );
|
||||
|
||||
SUBGRF_SetBufferBaseAddress( 0x00, 0x00 );
|
||||
return status;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_process_parameters( const wl_lr_fhss_params_t *params, uint16_t hop_sequence_id,
|
||||
uint16_t payload_length, wl_lr_fhss_state_t *state )
|
||||
{
|
||||
lr_fhss_process_parameters( ¶ms->lr_fhss_params, payload_length, &state->digest );
|
||||
|
||||
if( state->digest.nb_bytes > LR_FHSS_MAX_PHY_PAYLOAD_BYTES )
|
||||
{
|
||||
return RADIO_STATUS_UNKNOWN_VALUE;
|
||||
}
|
||||
if( params->lr_fhss_params.grid == LR_FHSS_V1_GRID_25391_HZ )
|
||||
{
|
||||
if( params->device_offset > 25 || params->device_offset < -26 )
|
||||
{
|
||||
return RADIO_STATUS_UNKNOWN_VALUE;
|
||||
}
|
||||
if( params->lr_fhss_params.bw < LR_FHSS_V1_BW_722656_HZ )
|
||||
{
|
||||
return RADIO_STATUS_UNKNOWN_VALUE;
|
||||
}
|
||||
}
|
||||
if( params->lr_fhss_params.grid == LR_FHSS_V1_GRID_3906_HZ )
|
||||
{
|
||||
if( params->device_offset > 3 || params->device_offset < -4 )
|
||||
{
|
||||
return RADIO_STATUS_UNKNOWN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize hop index and params
|
||||
state->current_hop = 0;
|
||||
radio_status_t status =
|
||||
lr_fhss_get_hop_params( ¶ms->lr_fhss_params, &state->hop_params, &state->lfsr_state, hop_sequence_id );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return ( radio_status_t ) status;
|
||||
}
|
||||
|
||||
// Skip the hop frequencies inside the set [0, 4 - header_count):
|
||||
if( params->lr_fhss_params.enable_hopping != 0 )
|
||||
{
|
||||
for( int i = 0; i < 4 - params->lr_fhss_params.header_count; ++i )
|
||||
{
|
||||
lr_fhss_get_next_state( &state->lfsr_state, &state->hop_params );
|
||||
}
|
||||
}
|
||||
|
||||
state->next_freq_in_pll_steps = wl_lr_fhss_get_next_freq_in_pll_steps( params, state );
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_write_hop_sequence_head( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state )
|
||||
{
|
||||
radio_status_t status = wl_lr_fhss_write_hop_config( state->digest.nb_bytes, state->digest.nb_hops );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
const uint16_t pulse_shape_compensation = 1;
|
||||
|
||||
if( params->lr_fhss_params.enable_hopping == 0 )
|
||||
{
|
||||
// (LR_FHSS_HEADER_BITS + pulse_shape_compensation) symbols on first sync_word, LR_FHSS_HEADER_BITS on next
|
||||
// sync_words, LR_FHSS_BLOCK_BITS on payload
|
||||
const uint16_t nb_symbols = state->digest.nb_bits + pulse_shape_compensation;
|
||||
|
||||
status = wl_lr_fhss_write_hop( state->current_hop, nb_symbols, state->next_freq_in_pll_steps );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
state->current_hop++;
|
||||
state->digest.nb_bits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fill at most WL_LR_FHSS_HOP_TABLE_SIZE hops of the hardware hop table
|
||||
uint8_t truncated_hops = state->digest.nb_hops;
|
||||
if( truncated_hops > WL_LR_FHSS_HOP_TABLE_SIZE )
|
||||
{
|
||||
truncated_hops = WL_LR_FHSS_HOP_TABLE_SIZE;
|
||||
}
|
||||
|
||||
while( state->current_hop < truncated_hops )
|
||||
{
|
||||
uint16_t nb_symbols;
|
||||
|
||||
// (LR_FHSS_HEADER_BITS + pulse_shape_compensation) symbols on first sync_word, LR_FHSS_HEADER_BITS on
|
||||
// next sync_words, LR_FHSS_BLOCK_BITS on payload
|
||||
if( state->current_hop >= params->lr_fhss_params.header_count )
|
||||
{
|
||||
if( state->digest.nb_bits > LR_FHSS_BLOCK_BITS )
|
||||
{
|
||||
nb_symbols = LR_FHSS_BLOCK_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nb_symbols = state->digest.nb_bits;
|
||||
}
|
||||
}
|
||||
else if( state->current_hop > 0 )
|
||||
{
|
||||
nb_symbols = LR_FHSS_HEADER_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nb_symbols = LR_FHSS_HEADER_BITS + pulse_shape_compensation;
|
||||
}
|
||||
|
||||
status = wl_lr_fhss_write_hop( state->current_hop, nb_symbols, state->next_freq_in_pll_steps );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
state->current_hop++;
|
||||
state->digest.nb_bits -= nb_symbols;
|
||||
|
||||
state->next_freq_in_pll_steps = wl_lr_fhss_get_next_freq_in_pll_steps( params, state );
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_write_payload( const wl_lr_fhss_state_t *state,
|
||||
const uint8_t *payload )
|
||||
{
|
||||
//return wl_write_buffer( context, 0x00, payload, state->digest.nb_bytes );
|
||||
SUBGRF_WriteBuffer( 0x00, ( uint8_t * ) payload, state->digest.nb_bytes );
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_build_frame( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state, uint16_t hop_sequence_id,
|
||||
const uint8_t *payload, uint16_t payload_length,
|
||||
uint32_t *first_frequency_in_pll_steps )
|
||||
{
|
||||
radio_status_t status = wl_lr_fhss_process_parameters( params, hop_sequence_id, payload_length, state );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if( first_frequency_in_pll_steps != NULL )
|
||||
{
|
||||
*first_frequency_in_pll_steps = state->next_freq_in_pll_steps;
|
||||
}
|
||||
|
||||
uint8_t tx_buffer[LR_FHSS_MAX_PHY_PAYLOAD_BYTES];
|
||||
lr_fhss_build_frame( ¶ms->lr_fhss_params, state->hop_params.hop_sequence_id, payload, payload_length,
|
||||
tx_buffer );
|
||||
|
||||
status = wl_lr_fhss_write_payload( state, tx_buffer );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
status = wl_lr_fhss_write_hop_sequence_head( params, state );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_handle_hop( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state )
|
||||
{
|
||||
if( state->current_hop < state->digest.nb_hops )
|
||||
{
|
||||
uint16_t nb_bits;
|
||||
if( state->digest.nb_bits > LR_FHSS_BLOCK_BITS )
|
||||
{
|
||||
nb_bits = LR_FHSS_BLOCK_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
nb_bits = state->digest.nb_bits;
|
||||
}
|
||||
radio_status_t status = wl_lr_fhss_write_hop( state->current_hop % WL_LR_FHSS_HOP_TABLE_SIZE,
|
||||
LR_FHSS_BLOCK_BITS, state->next_freq_in_pll_steps );
|
||||
if( status != RADIO_STATUS_OK )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
state->current_hop++;
|
||||
state->digest.nb_bits -= nb_bits;
|
||||
state->next_freq_in_pll_steps = wl_lr_fhss_get_next_freq_in_pll_steps( params, state );
|
||||
}
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_handle_tx_done( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state )
|
||||
{
|
||||
//const uint8_t ctrl = WL_LR_FHSS_DISABLE_HOPPING;
|
||||
|
||||
//return wl_write_register( context, WL_LR_FHSS_REG_CTRL, &ctrl, 1 );
|
||||
SUBGRF_WriteRegister( WL_LR_FHSS_REG_CTRL, WL_LR_FHSS_DISABLE_HOPPING );
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PRIVATE FUNCTIONS DEFINITION --------------------------------------------
|
||||
*/
|
||||
|
||||
radio_status_t wl_lr_fhss_write_hop_config( const uint8_t nb_bytes, const uint8_t nb_hops )
|
||||
{
|
||||
uint8_t data[] = { WL_LR_FHSS_ENABLE_HOPPING, nb_bytes, nb_hops };
|
||||
|
||||
//return wl_write_register( context, WL_LR_FHSS_REG_CTRL, data, 3 );
|
||||
SUBGRF_WriteRegisters( WL_LR_FHSS_REG_CTRL, data, 3 );
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
radio_status_t wl_lr_fhss_write_hop( const uint8_t index, const uint16_t nb_symbols,
|
||||
const uint32_t freq_in_pll_steps )
|
||||
{
|
||||
if( index >= WL_LR_FHSS_HOP_TABLE_SIZE )
|
||||
{
|
||||
return RADIO_STATUS_ERROR;
|
||||
}
|
||||
|
||||
uint8_t data[WL_LR_FHSS_HOP_ENTRY_SIZE] =
|
||||
{
|
||||
( uint8_t )( nb_symbols >> 8 ), ( uint8_t ) nb_symbols,
|
||||
( uint8_t )( freq_in_pll_steps >> 24 ), ( uint8_t )( freq_in_pll_steps >> 16 ),
|
||||
( uint8_t )( freq_in_pll_steps >> 8 ), ( uint8_t ) freq_in_pll_steps,
|
||||
};
|
||||
|
||||
//return wl_write_register( context, WL_LR_FHSS_REG_NUM_SYMBOLS_0 + ( WL_LR_FHSS_HOP_ENTRY_SIZE * index ),
|
||||
// data, WL_LR_FHSS_HOP_ENTRY_SIZE );
|
||||
SUBGRF_WriteRegisters( WL_LR_FHSS_REG_NUM_SYMBOLS_0 + ( WL_LR_FHSS_HOP_ENTRY_SIZE * index ),
|
||||
data, WL_LR_FHSS_HOP_ENTRY_SIZE );
|
||||
return RADIO_STATUS_OK;
|
||||
}
|
||||
|
||||
uint32_t wl_lr_fhss_get_next_freq_in_pll_steps( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state )
|
||||
{
|
||||
#ifdef HOP_AT_CENTER_FREQ
|
||||
const int16_t freq_table = 0;
|
||||
uint32_t grid_offset = 0;
|
||||
#else
|
||||
const int16_t freq_table =
|
||||
lr_fhss_get_next_freq_in_grid( &state->lfsr_state, &state->hop_params, ¶ms->lr_fhss_params );
|
||||
uint32_t nb_channel_in_grid = params->lr_fhss_params.grid ? 8 : 52;
|
||||
uint32_t grid_offset = ( 1 + ( state->hop_params.n_grid % 2 ) ) * ( nb_channel_in_grid / 2 );
|
||||
#endif
|
||||
|
||||
unsigned int grid_in_pll_steps = wl_lr_fhss_get_grid_in_pll_steps( params );
|
||||
uint32_t freq = params->center_freq_in_pll_steps - freq_table * grid_in_pll_steps -
|
||||
( params->device_offset + grid_offset ) * WL_LR_FHSS_GRID_INDEX_TO_PLL_STEPS;
|
||||
|
||||
#ifndef HOP_AT_CENTER_FREQ
|
||||
// Perform frequency correction for every other sync header
|
||||
if( params->lr_fhss_params.enable_hopping && ( state->current_hop < params->lr_fhss_params.header_count ) )
|
||||
{
|
||||
if( ( ( ( params->lr_fhss_params.header_count - state->current_hop ) % 2 ) == 0 ) )
|
||||
{
|
||||
// OFFSET_SYNCWORD = 488.28125 / 2, and FREQ_STEP = 0.95367431640625, so
|
||||
// OFFSET_SYNCWORD / FREQ_STEP = 256
|
||||
freq = freq + 256;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return freq;
|
||||
}
|
||||
|
||||
static inline unsigned int wl_lr_fhss_get_grid_in_pll_steps( const wl_lr_fhss_params_t *params )
|
||||
{
|
||||
return ( params->lr_fhss_params.grid == LR_FHSS_V1_GRID_3906_HZ ) ? WL_LR_FHSS_GRID_3906_HZ_PLL_STEPS : WL_LR_FHSS_GRID_25391_HZ_PLL_STEPS;
|
||||
}
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
238
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/wl_lr_fhss.h
vendored
Normal file
238
Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver/wl_lr_fhss.h
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
/*!
|
||||
* @file wl_lr_fhss.h
|
||||
*
|
||||
* @brief STM32WL LR-FHSS driver module API (internal to SubGHz_Phy middleware)
|
||||
*
|
||||
* The Clear BSD License
|
||||
* Copyright Semtech Corporation 2021. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted (subject to the limitations in the disclaimer
|
||||
* below) provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the Semtech corporation nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||
* THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
|
||||
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SEMTECH CORPORATION BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WL_LR_FHSS_H__
|
||||
#define WL_LR_FHSS_H__
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- DEPENDENCIES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "radio_driver.h"
|
||||
#include "lr_fhss_mac.h"
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC MACROS -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC CONSTANTS --------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define WL_LR_FHSS_REG_CTRL ( 0x0385 )
|
||||
#define WL_LR_FHSS_REG_PACKET_LEN ( 0x0386 )
|
||||
#define WL_LR_FHSS_REG_NUM_HOPS ( 0x0387 )
|
||||
#define WL_LR_FHSS_REG_NUM_SYMBOLS_0 ( 0x0388 )
|
||||
#define WL_LR_FHSS_REG_FREQ_0 ( 0x038A )
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC TYPES ------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @brief STM32WL LR-FHSS LR-FHSS parameter definition
|
||||
*/
|
||||
typedef struct wl_lr_fhss_params_s
|
||||
{
|
||||
lr_fhss_v1_params_t lr_fhss_params;
|
||||
uint32_t center_freq_in_pll_steps; /**< Center frequency in transceiver units */
|
||||
int8_t device_offset; //<! Per device offset to avoid collisions over the air. Possible values:
|
||||
//<! - if (lr_fhss_params.grid == LR_FHSS_V1_GRID_25391_HZ): [-26, 25]
|
||||
//<! - if (lr_fhss_params.grid == LR_FHSS_V1_GRID_3906_HZ): [-4, 3]
|
||||
} wl_lr_fhss_params_t;
|
||||
|
||||
/*!
|
||||
* @brief STM32WL LR-FHSS LR-FHSS state definition
|
||||
*/
|
||||
typedef struct wl_lr_fhss_state_s
|
||||
{
|
||||
lr_fhss_hop_params_t hop_params;
|
||||
lr_fhss_digest_t digest;
|
||||
uint32_t next_freq_in_pll_steps; /**< Frequency that will be used on next hop */
|
||||
uint16_t lfsr_state; /**< LFSR state for hop sequence generation */
|
||||
uint8_t current_hop; /**< Index of the current hop */
|
||||
} wl_lr_fhss_state_t;
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------------------
|
||||
* --- PUBLIC FUNCTIONS PROTOTYPES ---------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Initialize LR-FHSS packet type and modulation parameters
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_init( const wl_lr_fhss_params_t *params );
|
||||
|
||||
/*!
|
||||
* @brief Check the parameters, and in case of success, generate the digest summary which contains important size info
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] hop_sequence_id Specifies which hop sequence to use
|
||||
* @param [in] payload_length Length of application-layer payload
|
||||
* @param [out] state stm32wl LR-FHSS state structure that will be initialized by this function
|
||||
*
|
||||
* @remark It is not necessary to explicitly call this function if the helper function @ref wl_lr_fhss_build_frame
|
||||
* is used. If the preprocessor symbol HOP_AT_CENTER_FREQ is defined, hopping will be performed with PA ramp
|
||||
* up/down, but without actually changing frequencies.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_process_parameters( const wl_lr_fhss_params_t *params, uint16_t hop_sequence_id,
|
||||
uint16_t payload_length, wl_lr_fhss_state_t *state );
|
||||
|
||||
/*!
|
||||
* @brief Sent the initial hopping confifguration to the radio
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] state stm32wl LR-FHSS state structure
|
||||
*
|
||||
* @remark It is not necessary to explicitly call this function if the helper function @ref wl_lr_fhss_build_frame
|
||||
* is used. If the preprocessor symbol HOP_AT_CENTER_FREQ is defined, hopping will be performed with PA ramp
|
||||
* up/down, but without actually changing frequencies.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_write_hop_sequence_head( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state );
|
||||
|
||||
/*!
|
||||
* @brief Write physical LR-FHSS payload to radio
|
||||
*
|
||||
* @param [in] state stm32wl LR-FHSS state structure
|
||||
* @param [in] payload Array containing application-layer payload
|
||||
*
|
||||
* @remark It is not necessary to explicitly call this function if the helper function @ref wl_lr_fhss_build_frame
|
||||
* is used.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_write_payload( const wl_lr_fhss_state_t *state,
|
||||
const uint8_t *payload );
|
||||
|
||||
/*!
|
||||
* @brief Check parameter validity, build a frame, then send it
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] state stm32wl LR-FHSS state structure
|
||||
* @param [in] hop_sequence_id Specifies which hop sequence to use
|
||||
* @param [in] payload Array containing application-layer payload
|
||||
* @param [in] payload_length Length of application-layer payload
|
||||
* @param [out] first_frequency_in_pll_steps If non-NULL, provides the frequency that will be used on the first hop
|
||||
*
|
||||
* @remark This helper function calls the @ref wl_lr_fhss_process_parameters,
|
||||
* lr_fhss_build_frame, @ref wl_lr_fhss_write_hop_sequence_head, and @ref wl_lr_fhss_write_payload
|
||||
* functions. If the preprocessor symbol HOP_AT_CENTER_FREQ is defined, hopping will be performed with PA ramp
|
||||
* up/down, but without actually changing frequencies.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_build_frame( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state, uint16_t hop_sequence_id,
|
||||
const uint8_t *payload, uint16_t payload_length,
|
||||
uint32_t *first_frequency_in_pll_steps );
|
||||
|
||||
/*!
|
||||
* @brief Perform an actual frequency hop
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] state stm32wl LR-FHSS state structure
|
||||
*
|
||||
* @remark This should be called to respond to the WL_IRQ_LR_FHSS_HOP interrupt. If the preprocessor symbol
|
||||
* HOP_AT_CENTER_FREQ is defined, hopping will be performed with PA ramp up/down, but without actually
|
||||
* changing frequencies.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_handle_hop( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state );
|
||||
|
||||
/*!
|
||||
* @brief Indicate to the radio that frequency hopping is no longer needed
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] state stm32wl LR-FHSS state structure
|
||||
*
|
||||
* @remark The should be called to respond to the WL_IRQ_TX_DONE interrupt following LR-FHSS transmission.
|
||||
*
|
||||
* @returns Operation status
|
||||
*/
|
||||
radio_status_t wl_lr_fhss_handle_tx_done( const wl_lr_fhss_params_t *params,
|
||||
wl_lr_fhss_state_t *state );
|
||||
|
||||
/*!
|
||||
* @brief Get the time on air in ms for LR-FHSS transmission
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
* @param [in] payload_length Length of application-layer payload
|
||||
*
|
||||
* @returns Time-on-air value in ms for LR-FHSS transmission
|
||||
*/
|
||||
static inline uint32_t wl_lr_fhss_get_time_on_air_in_ms( const wl_lr_fhss_params_t *params,
|
||||
uint16_t payload_length )
|
||||
{
|
||||
return lr_fhss_get_time_on_air_in_ms( ¶ms->lr_fhss_params, payload_length );
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Return the number of hop sequences available using the given parameters
|
||||
*
|
||||
* @param [in] params stm32wl LR-FHSS parameter structure
|
||||
*
|
||||
* @return Returns the number of valid hop sequences (512 or 384)
|
||||
*/
|
||||
static inline unsigned int wl_lr_fhss_get_hop_sequence_count( const wl_lr_fhss_params_t *params )
|
||||
{
|
||||
return lr_fhss_get_hop_sequence_count( ¶ms->lr_fhss_params );
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // WL_LR_FHSS_H__
|
||||
|
||||
/* --- EOF ------------------------------------------------------------------ */
|
||||
Reference in New Issue
Block a user