diff --git a/inc/llcc68.hpp b/inc/llcc68.hpp index 6d986cf..a0be8f9 100644 --- a/inc/llcc68.hpp +++ b/inc/llcc68.hpp @@ -444,7 +444,7 @@ set_dio2_as_rf_switch(const bool en) { /** * \brief set packet type and do the calibration */ -inline Result config_packet_type(const parameters_t ¶ms) { +inline Result config_packet_type(uint8_t sf) { Result res; constexpr auto mod = RADIOLIB_SX126X_PACKET_TYPE_LORA; uint8_t data[7]; @@ -456,7 +456,7 @@ inline Result config_packet_type(const parameters_t ¶ms) { APP_RADIO_RETURN_ERR(res); data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB; - data[1] = params.sf + 13; + data[1] = sf + 13; data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN; data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY; data[4] = 0x00; @@ -490,12 +490,16 @@ inline Result config_packet_type(const parameters_t ¶ms) { \returns Expected time-on-air in microseconds. */ constexpr uint32_t -calc_time_on_air(const size_t len, const calc_time_on_air_t params) { +calc_time_on_air(const size_t len, + uint8_t sf, + uint8_t bw, + uint8_t cr, + uint16_t preamble_length, + uint8_t header_type) { // everything is in microseconds to allow integer arithmetic // some constants have .25, these are multiplied by 4, and have _x4 postfix to indicate that fact - const auto bw_ = float{bw_khz(params.bw)}; + const auto bw_ = float{bw_khz(bw)}; const auto ubw = static_cast(bw_ * 10); - const auto sf = params.sf; const uint32_t symbolLength_us = (static_cast(1000 * 10) << sf) / ubw; uint8_t sfCoeff1_x4 = 17; // (4.25 * 4) uint8_t sfCoeff2 = 8; @@ -507,20 +511,20 @@ calc_time_on_air(const size_t len, const calc_time_on_air_t params) { if (symbolLength_us >= 16000) { sfDivisor = 4 * (sf - 2); } - constexpr int8_t bitsPerCrc = 16; - constexpr int8_t N_symbol_header = params.header_type == RADIOLIB_SX126X_LORA_HEADER_EXPLICIT ? 20 : 0; + constexpr int8_t bitsPerCrc = 16; + int8_t N_symbol_header = header_type == RADIOLIB_SX126X_LORA_HEADER_EXPLICIT ? 20 : 0; // numerator of equation in section 6.1.4 of SX1268 datasheet v1.1 (might not actually be bitcount, but it has len * 8) - int16_t bitCount = static_cast(8) * len + params.crc_type * bitsPerCrc - 4 * sf + sfCoeff2 + N_symbol_header; + int16_t bitCount = static_cast(8) * len + RADIOLIB_SX126X_LORA_CRC_ON * bitsPerCrc - 4 * sf + sfCoeff2 + N_symbol_header; if (bitCount < 0) { bitCount = 0; } // add (sfDivisor) - 1 to the numerator to give integer CEIL(...) const uint16_t nPreCodedSymbols = (bitCount + (sfDivisor - 1)) / (sfDivisor); - const auto de = std::get<1>(cr_to_ratio(params.cr)); + const auto de = std::get<1>(cr_to_ratio(cr)); // preamble can be 65k, therefore nSymbol_x4 needs to be 32 bit - const uint32_t nSymbol_x4 = (params.preamble_length + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * de * 4; + const uint32_t nSymbol_x4 = (preamble_length + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * de * 4; return symbolLength_us * nSymbol_x4 / 4; } @@ -1017,7 +1021,7 @@ read_data_internal() { \note The IRQ RxDone means that a packet has been received but the CRC could be wrong: the user must check the CRC before validating the packet. */ inline Result -kick_inf_rx() { +kick_inf_rx(const modulation_params_t &mod_params, const packet_params_t &packet_params) { Result res; res = standby(); APP_RADIO_RETURN_ERR_CTX(res, "failed to standby"); @@ -1032,6 +1036,11 @@ kick_inf_rx() { DIO3_PIN == NC_PIN ? RADIOLIB_SX126X_IRQ_NONE : irq_mask, }; + res = set_modulation_params(mod_params.sf, mod_params.bw, mod_params.cr, mod_params.ldr_optimize); + APP_RADIO_RETURN_ERR_CTX(res, "failed to set modulation params"); + res = set_packet_params(packet_params.preamble_len, packet_params.payload_len, packet_params.crc_type, packet_params.hdr_type); + APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params"); + res = set_dio_irq_params(irq_params); APP_RADIO_RETURN_ERR_CTX(res, "failed to set dio irq params"); res = clear_irq_status(); @@ -1042,27 +1051,6 @@ kick_inf_rx() { } -enum class AFTER_TX_BEHAVIOR { - STDBY, - RX, -}; - -/** - * \brief will be called after each `sync_transmit` - * \note Application writer (i.e. myself) should manually enable the receiver after transmission - */ -inline void after_tx(const AFTER_TX_BEHAVIOR behavior = AFTER_TX_BEHAVIOR::RX) { - clear_irq_status(); - switch (behavior) { - case AFTER_TX_BEHAVIOR::STDBY: - standby(); - break; - case AFTER_TX_BEHAVIOR::RX: - kick_inf_rx(); - break; - } -} - /** After power up (battery insertion or hard reset) the chip runs automatically a calibration procedure and goes to STDBY_RC mode. This is indicated by a low state on BUSY pin. From this state the steps are: @@ -1082,7 +1070,7 @@ inline void after_tx(const AFTER_TX_BEHAVIOR behavior = AFTER_TX_BEHAVIOR::RX) { 14. Clear the IRQ TxDone flag */ inline Result -sync_transmit(const uint8_t *data, const size_t len, const calc_time_on_air_t ¶ms) { +sync_transmit(const std::span data, const lora_parameters_t ¶ms) { // unimplemented std::unreachable(); return {}; @@ -1098,30 +1086,32 @@ sync_transmit(const uint8_t *data, const size_t len, const calc_time_on_air_t &p * \see poll_tx_state */ inline Result -async_transmit(const uint8_t *data, const size_t len, - const calc_time_on_air_t ¶ms, +async_transmit(const std::span data, + const lora_parameters_t ¶ms, const transmit_state_t &tx_state) { if (tx_state.is_transmitting) { return ue_t{error_t{error::RADIO_BUSY_TX}}; } - if (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { + if (data.size() > RADIOLIB_SX126X_MAX_PACKET_LENGTH) { return ue_t{error_t{error::INVALID_SIZE}}; } + const auto &mod_params = params.mod_params; + const auto &packet_params = params.packet_params; Result res; res = standby(); APP_RADIO_RETURN_ERR_CTX(res, "failed to standby"); - res = set_packet_params(params.preamble_length, len, params.crc_type, params.header_type); + res = set_packet_params(packet_params.preamble_len, data.size(), packet_params.crc_type, packet_params.hdr_type); APP_RADIO_RETURN_ERR_CTX(res, "failed to set packet params"); res = set_buffer_base_address(); APP_RADIO_RETURN_ERR_CTX(res, "failed to set buffer base address"); - res = write_buffer(std::span{data, len}); + res = write_buffer(data); APP_RADIO_RETURN_ERR_CTX(res, "failed to write buffer"); - res = fix_sensitivity(params.bw); + res = fix_sensitivity(mod_params.bw); APP_RADIO_RETURN_ERR_CTX(res, "failed to fix sensitivity"); constexpr auto irq_mask = RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT; @@ -1139,7 +1129,14 @@ async_transmit(const uint8_t *data, const size_t len, res = tx(); APP_RADIO_RETURN_ERR_CTX(res, "failed to transmit"); - const auto timeout_us = calc_time_on_air(len, params) * 11u / 10u; + constexpr auto TIMEOUT_FACTOR = 11u / 10u; + const auto timeout_us = calc_time_on_air(data.size(), + mod_params.sf, + mod_params.bw, + mod_params.cr, + packet_params.preamble_len, + packet_params.hdr_type) * + TIMEOUT_FACTOR; const uint16_t timeout_ms = timeout_us / 1000; auto instant = Instant<>{}; return transmit_state_t{ @@ -1149,13 +1146,6 @@ async_transmit(const uint8_t *data, const size_t len, }; } -inline Result -async_transmit(const std::span data, - const calc_time_on_air_t ¶ms, - const transmit_state_t &tx_state) { - return async_transmit(data.data(), data.size(), params, tx_state); -} - static constexpr auto init_pins = [](void (*isr)(void *), void *arg) { if (RST_PIN != GPIO_NUM_NC) { @@ -1183,7 +1173,7 @@ static constexpr auto init_pins = [](void (*isr)(void *), void *arg) { } }; -static constexpr auto begin = [](const parameters_t ¶ms) -> Result { +static constexpr auto begin = [](const lora_parameters_t ¶ms) -> Result { /** * Most of the commands can be sent in any order except for the radio configuration commands which will set the radio in * the proper operating mode. Indeed, it is mandatory to set the radio protocol using the command SetPacketType(...) as a first @@ -1212,16 +1202,17 @@ static constexpr auto begin = [](const parameters_t ¶ms) -> Result Result= min && v <= max; } @@ -332,60 +354,6 @@ constexpr bool valid_sf(const uint8_t bw, const uint8_t sf) { constexpr bool valid_freq(const freq_t freq) { return in_range(freq, freq_t{150.0}, freq_t{960.0}); } - -/** - * \brief check if the parameters are valid. if not, set them to default. - * \param params the parameters to check - * \return if the parameters are valid, and the modified parameters - */ -constexpr std::tuple -check_fix_params(parameters_t params) { - bool ok = true; - - if (not valid_bw(params.bw)) { - params.bw = DEFAULT_BW; - ok = false; - } - if (not valid_sf(params.bw, params.sf)) { - params.sf = DEFAULT_SF; - ok = false; - } - if (not valid_cr(params.cr)) { - params.cr = DEFAULT_CR; - ok = false; - } - if (not valid_freq(params.frequency)) { - params.frequency = DEFAULT_FREQUENCY; - ok = false; - } - if (not valid_ldr_optimize(params.ldr_optimize)) { - params.ldr_optimize = DEFAULT_LDR_OPTIMIZE; - ok = false; - } - return {ok, params}; -} - -/** - * \brief only do the check - */ -constexpr bool check_params(const parameters_t ¶ms) { - if (not valid_bw(params.bw)) { - return false; - } - if (not valid_sf(params.bw, params.sf)) { - return false; - } - if (not valid_cr(params.cr)) { - return false; - } - if (not valid_freq(params.frequency)) { - return false; - } - if (not valid_ldr_optimize(params.ldr_optimize)) { - return false; - } - return true; -} } #endif // LLCC68_DEFINITIONS_H