#ifndef AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B #define AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B #include "llcc68_definitions.hpp" #include "llcc68_raw.h" #include #include #include #include #include #include namespace app::driver::llcc68 { constexpr size_t MAX_BUFFER_PAYLOAD = 128; constexpr uint32_t TIMEOUT_NONE = 0; constexpr uint32_t TIMEOUT_INF = 0xffffffff; constexpr auto DEFAULT_TX_BUFFER_ADDRESS = 0x00; constexpr auto DEFAULT_RX_BUFFER_ADDRESS = 0x80; using user_dio1_handler_t = void (*)(const struct device *dev, void *user_data); } // namespace app::driver::llcc68 namespace app::driver::llcc68 { template using expected = std::expected; template using unexpected = std::unexpected; using unit = std::monostate; constexpr auto DEFAULT_BUSY_TIMEOUT_MS = 100; /** * @brief calculate time-on-air for a LoRa packet * * @param len Payload length in bytes * @param sf Spreading factor (7-12) * @param bw Bandwidth (125, 250, 500 kHz) * @param cr Coding rate (4/5, 4/6, 4/7, 4/8) * @param preamble_length Preamble length in symbols * @param header_type Header type (implicit or explicit). * @param crc_type CRC type (none or 16-bit) */ constexpr airtime_t calc_time_on_air(uint8_t len, uint8_t sf, LoRaBandwidth bw, LoRaCodingRate cr, uint16_t preamble_length, LoRaHeaderType header_type, LoRaCrcType crc_type); struct LLCC68 { /** trivial getter */ [[nodiscard]] const struct llcc68_config &config() const; struct llcc68_data &data(); [[nodiscard]] std::optional tx_enable_gpio() const; [[nodiscard]] std::optional rx_enable_gpio() const; using timeout_ms_t = uint16_t; /** SPI operation API */ expected read_stream(uint8_t cmd, std::span data_to_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); expected write_stream(uint8_t cmd, std::span data_from_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); expected read_register(uint16_t reg, std::span data_to_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); expected write_register(uint16_t reg, std::span data_from_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); /** READ BUFFER */ /** * @brief read buffer of any offset and length, copying to user buffer * @param[in] offset offset in the LLCC68 buffer to read from * @param[out] data_to_host buffer to copy data into, the read length is * determined by the size of this span * @returns number of bytes read */ expected read_buffer_copy(uint8_t offset, std::span data_to_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); /** * @brief read buffer of any offset and length * @returns span referencing internal buffer */ expected, error_code> read_buffer_ref(uint8_t offset, uint8_t n, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); /** * @brief read the RX buffer (whose offset would be DEFAULT_RX_BUFFER_ADDRESS) * with all its current available data * @returns span referencing internal buffer */ expected, error_code> read_rx_buffer_ref(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); /** WRITE BUFFER */ expected write_tx_buffer(std::span data_from_host); expected flush_tx_buffer(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); expected write_buffer_immediate_mode( uint8_t offset, std::span data_from_host, timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); void tx_rx_en_pin_set(TxRxPinState state); /** LLCC68 DataSheet Function */ expected get_status(); expected get_packet_status(); expected get_rssi_inst_x2_neg(); expected reset(); expected set_standby(); expected hal_get_chip_type(); expected set_dio_irq_params(irq_params_t params); expected get_irq_status(); expected clear_irq_status(irq_status_t irq = irq_status_t::all()); expected set_packet_type_lora(); expected set_packet_type_gfsk(); expected set_modulation_params(modulation_params_t mod_params); expected set_modulation_params(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro); expected set_gfsk_modulation_params(gfsk_modulation_params_t mod_params); /*! \brief Sets LoRa sync word. \param sync_word LoRa sync word to be set. \note Differentiate the LoRa signal for Public or Private Network Set to 0x3444 for Public Network Set to 0x1424 for Private Network */ expected set_lora_sync_word(uint16_t sync_word); expected set_dio2_as_rf_switch(bool en); expected set_rf_frequency(freq_t freq_mhz); expected set_rf_frequency(uint32_t freq_raw); expected set_packet_params(uint16_t preamble_length, uint8_t payload_length, uint8_t crc_type, uint8_t hdr_type, uint8_t iq_type); expected set_gfsk_packet_params(gfsk_packet_params_t packet_params); expected set_gfsk_sync_word(std::span sync_word); expected set_gfsk_address_filtering(uint8_t node_address, uint8_t broadcast_address); expected set_gfsk_crc_seed(uint16_t seed); expected set_gfsk_crc_polynomial(uint16_t polynomial); expected set_gfsk_whitening_seed(uint16_t seed); expected calibrate_image(uint8_t freq1, uint8_t freq2); expected set_tx_params(tx_params_t params); expected set_tx_params(int8_t pwr, LoRaTxRampTime ramp_time); expected set_pa_config(pa_setting_t settings); /** * @brief fixes overly eager PA clamping * * fixes overly eager PA clamping * see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for * details * * The LLCC68 platform embeds a Power Amplifier (PA) clamping mechanism, * backing-off the power when over-voltage conditions are detected internally. * This method is put in place to protect the internal devices and ensure * long-term reliability of the chip. Considering a high-power operation of * the LLCC68 (supporting +22dBm on-chip), these "clamping" devices are overly * protective, causing the chip to back-down its output power when even a * reasonable mismatch is detected at the PA output. The observation is * typically 5 to 6 dB less output power than the expected. * * @param enable * @return Result */ expected fix_pa_clamping(bool enable = true); /** * \brief fixes inverted IQ on SX1262 rev. B * \param iq_config RADIOLIB_SX126X_LORA_IQ_STANDARD or * RADIOLIB_SX126X_LORA_IQ_INVERTED * \see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.4 * for details */ expected fix_inverted_iq(uint8_t iq_config); /** * \brief Some sensitivity degradation may be observed on any LoRa device, when receiving signals transmitted by the LLCC68 with a LoRa BW of 500 kHz. * \note should be used before each packet transmission, to properly configure the chip * \param bw the bandwidth * \sa SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.1 for details */ expected fix_sensitivity(LoRaBandwidth bw); expected fix_gfsk_tx_modulation(); expected fix_gfsk_low_bitrate(uint32_t bitrate_bps); /** * \brief Channel Activity Detection (CAD) params */ expected set_cad_params(cad_params_t params); /** * \brief Set the CAD mode * * The command SetCAD() can be used only in LoRa packet type. The Channel * Activity Detection is a LoRa specific mode of operation where the device * searches for the presence of a LoRa preamble signal. After the search has * completed, the device returns in STDBY_RC mode. The length of the search is * configured via the command SetCadParams(...). At the end of the search * period, the device triggers the IRQ CAD DONE if it has been enabled. If a * valid signal has been detected it also generates the IRQ CAD DETECTED. * * The time taken for the channel activity detection is dependent upon the * LoRa® modulation settings used. For a given configuration (SF/BW) the * typical CAD detection time can be selected to be either 1, 2, 4, 8 or 16 * symbols. Once the duration of the selected number of symbols has been done, * the radio will remains for around half a symbol in Rx to post-process the * measurement. */ expected set_cad(); expected set_tx(uint32_t timeout = TIMEOUT_NONE); expected set_rx(uint32_t timeout = TIMEOUT_INF); expected set_sleep(sleep_config_t config); expected set_tx_continuous_wave(); expected set_tx_infinite_preamble(); expected set_buffer_base_address(uint8_t tx_base_addr = DEFAULT_TX_BUFFER_ADDRESS, uint8_t rx_base_addr = DEFAULT_RX_BUFFER_ADDRESS); struct rx_buffer_status_t { uint8_t payload_length; uint8_t start_address; }; expected get_rx_buffer_status(timeout_ms_t busy_timeout = DEFAULT_BUSY_TIMEOUT_MS); /** * @brief Random Number Generator (RNG) */ expected random_number_gen(); /** DIO1 IRQ registration helpers (like sx126x) */ expected dio1_irq_enable(); void dio1_irq_disable(); void set_dio1_irq_handler(user_dio1_handler_t handler, void *user_data); /** high level API that wraps the raw function call */ expected hal_modem_init(lora_parameters_t params); expected hal_gfsk_modem_init(gfsk_parameters_t params); expected hal_async_transmit(std::span data, lora_parameters_t params); expected hal_async_flush(lora_parameters_t params); expected hal_async_rx(lora_parameters_t params); expected hal_gfsk_async_transmit(std::span data, gfsk_parameters_t params); expected hal_gfsk_async_flush(gfsk_parameters_t params); expected hal_gfsk_async_rx(gfsk_parameters_t params); expected hal_set_output_power(ChipType chip, tx_params_t params); error_code init(); /** properties */ const struct device *dev; }; } // namespace app::driver::llcc68 namespace app::radio { namespace llcc68 = app::driver::llcc68; } #endif /* AA1F69D0_32E3_44B6_BFD7_2013E1E86A6B */