### LoRa Transmit Example Source: https://context7.com/lora-net/swdr001/llms.txt This example demonstrates how to configure the LR11XX radio for LoRa transmission, including setting packet type, modulation parameters, packet parameters, sync word, RF frequency, PA configuration, and then initiating the transmission. ```APIDOC ## lora_transmit ### Description Configures the radio for LoRa transmission and sends a payload. ### Parameters - `ctx` (radio_context_t*): Pointer to the radio context. - `payload` (const uint8_t*): Pointer to the data payload to transmit. - `len` (uint8_t): The length of the payload in bytes. ### Steps: 1. Set packet type to LoRa. 2. Set LoRa modulation parameters (SF, BW, CR, ldro). 3. Set LoRa packet parameters (preamble length, header type, payload length, CRC, IQ settings). 4. Set LoRa sync word. 5. Set the RF frequency. 6. Configure the PA (Power Amplifier) settings. 7. Set TX power and ramp time. 8. Compute and log time-on-air. 9. Load the payload into the TX buffer. 10. Start the transmission with a timeout. ### Example Usage: ```c lora_transmit(ctx, my_payload, payload_length); ``` ``` -------------------------------- ### Install lr11xx_driver Target Source: https://github.com/lora-net/swdr001/blob/master/src/CMakeLists.txt Installs the lr11xx_driver target, including its library, archive, runtime binaries, and include files. This defines how the library is packaged for use in other projects. ```cmake install(TARGETS lr11xx_driver EXPORT Lr11xxDriverTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin INCLUDES DESTINATION include ) ``` -------------------------------- ### LoRa Receive Example Source: https://context7.com/lora-net/swdr001/llms.txt This example shows how to configure the LR11XX radio for LoRa reception, including setting packet type, modulation parameters, packet parameters, RF frequency, and then initiating reception. It also covers reading received buffer status and packet status. ```APIDOC ## lora_receive ### Description Configures the radio for LoRa reception and initiates a listening period. ### Parameters - `ctx` (radio_context_t*): Pointer to the radio context. ### Steps: 1. Set packet type to LoRa. 2. Set LoRa modulation parameters (SF, BW, CR, ldro). 3. Set LoRa packet parameters (preamble length, header type, payload length, CRC, IQ settings). 4. Set the RF frequency. 5. Enable LNA boost. 6. Set LoRa sync timeout. 7. Start reception with a timeout. 8. After IRQ, read buffer status and payload. 9. Read packet status (RSSI, SNR, signal RSSI). ### Example Usage: ```c lora_receive(ctx); ``` ``` -------------------------------- ### LoRa Channel Activity Detection (CAD) Example Source: https://context7.com/lora-net/swdr001/llms.txt This example demonstrates how to configure and initiate Channel Activity Detection (CAD) for LoRa on the LR11XX chip. ```APIDOC ## lora_cad ### Description Configures and initiates Channel Activity Detection (CAD) for LoRa. ### Parameters - `ctx` (radio_context_t*): Pointer to the radio context. ### Steps: 1. Set packet type to LoRa. 2. Set LoRa modulation parameters (SF, BW). 3. Set CAD parameters (symbol number, detection peak, detection minimum, exit mode, timeout). 4. Initiate CAD. ### Notes: - IRQ `LR11XX_SYSTEM_IRQ_CAD_DONE` fires when CAD is complete. - Check `LR11XX_SYSTEM_IRQ_CAD_DETECTED` for activity. ### Example Usage: ```c lora_cad(ctx); ``` ``` -------------------------------- ### GNSS Scan and Result Retrieval Example Source: https://context7.com/lora-net/swdr001/llms.txt This example demonstrates the typical workflow for performing a GNSS scan and retrieving the results using the LR11XX GNSS library. It covers setting up constellations, assistance data, initiating a scan, and processing the returned data. ```APIDOC ## `lr11xx_gnss_set_constellations_to_use` / `lr11xx_gnss_scan` / `lr11xx_gnss_read_results` ### Description This section provides a C code example demonstrating the usage of several GNSS functions for configuring and performing satellite acquisition scans with the LR11XX chip. It includes setting up constellations, almanac updates, assistance position, time synchronization, initiating a scan, and reading the results. ### Method C Function Calls ### Functions and Usage 1. **`lr11xx_gnss_set_constellations_to_use`**: Configures which GNSS constellations (GPS, BeiDou) to use for the scan. - **Parameters**: `ctx` (radio context), `constellations_mask` (e.g., `LR11XX_GNSS_GPS_MASK | LR11XX_GNSS_BEIDOU_MASK`) 2. **`lr11xx_gnss_set_almanac_update`**: Enables almanac updates for specified constellations. - **Parameters**: `ctx` (radio context), `constellations_mask` 3. **`lr11xx_gnss_set_assistance_position`**: Sets the assistance position to aid the GNSS solver. - **Parameters**: `ctx` (radio context), `assist_pos` (pointer to `lr11xx_gnss_solver_assistance_position_t` with `latitude` and `longitude`) 4. **`lr11xx_gnss_set_time`**: Provides current GPS time to speed up assisted scans. - **Parameters**: `ctx` (radio context), `gps_time` (seconds since epoch), `accuracy_ms` (milliseconds) 5. **`lr11xx_gnss_scan`**: Launches the GNSS scan with specified options. - **Parameters**: `ctx` (radio context), `scan_options` (e.g., `LR11XX_GNSS_OPTION_LOW_EFFORT`), `results_mask` (e.g., `LR11XX_GNSS_RESULTS_DOPPLER_ENABLE_MASK`), `min_satellites` - **Note**: Waits for `LR11SYSTEM_IRQ_GNSS_SCAN_DONE` IRQ. 6. **`lr11xx_gnss_get_result_size`** and **`lr11xx_gnss_read_results`**: Retrieves the size of the scan results and then reads the results into a buffer. - **Parameters**: `ctx` (radio context), `result_size` (output pointer), `result_buf` (output buffer), `size` (size of buffer) 7. **`lr11xx_gnss_get_result_destination`**: Determines the destination of the scan results. - **Parameters**: `result_buf`, `size`, `dest` (output pointer to `lr11xx_gnss_destination_t`) 8. **`lr11xx_gnss_get_nb_detected_satellites`** and **`lr11xx_gnss_get_detected_satellites`**: Retrieves information about detected satellites. - **Parameters**: `ctx` (radio context), `nb_sv` (output pointer), `sv_list` (output buffer for `lr11xx_gnss_detected_satellite_t`) 9. **`lr11xx_gnss_read_cumulative_timing`**, **`lr11xx_gnss_compute_power_consumption`**: Reads timing data and computes power consumption for the scan. - **Parameters**: `ctx` (radio context), `timing` (output pointer to `lr11xx_gnss_cumulative_timing_t`), `power_table` (pointer to `lr11xx_gnss_instantaneous_power_consumption_ua_t`), `nah` (output pointer for nano-ampere-hours), `nwh` (output pointer for nano-watt-hours) ### Request Example ```c #include "lr11xx_gnss.h" void gnss_scan_and_read( radio_context_t* ctx ) { lr11xx_status_t status; /* 1. Use both GPS and BeiDou */ status = lr11xx_gnss_set_constellations_to_use( ctx, LR11XX_GNSS_GPS_MASK | LR11XX_GNSS_BEIDOU_MASK ); assert( status == LR11XX_STATUS_OK ); /* 2. Enable almanac update for both constellations */ lr11xx_gnss_set_almanac_update( ctx, LR11XX_GNSS_GPS_MASK | LR11XX_GNSS_BEIDOU_MASK ); /* 3. Set assistance position (San Francisco: 37.77°N, -122.42°E) */ lr11xx_gnss_solver_assistance_position_t assist_pos = { .latitude = 37.77f, .longitude = -122.42f, }; lr11xx_gnss_set_assistance_position( ctx, &assist_pos ); /* 4. Provide current GPS time to speed up assisted scan */ /* GPS time = Unix time - 315964800 + leap_seconds */ lr11xx_gnss_set_time( ctx, 1390000000, 1000 ); /* 1-second accuracy */ /* 5. Launch scan: low effort, request doppler + almanac fields, want 6 satellites */ status = lr11xx_gnss_scan( ctx, LR11XX_GNSS_OPTION_LOW_EFFORT, LR11XX_GNSS_RESULTS_DOPPLER_ENABLE_MASK | LR11XX_GNSS_RESULTS_ALMANAC_STATUS_MASK, 6 ); /* Wait for LR11XX_SYSTEM_IRQ_GNSS_SCAN_DONE IRQ */ /* 6. Read result size then results */ uint16_t result_size = 0; lr11xx_gnss_get_result_size( ctx, &result_size ); uint8_t result_buf[256] = { 0 }; lr11xx_gnss_read_results( ctx, result_buf, result_size ); /* 7. Determine destination (host processor or cloud solver) */ lr11xx_gnss_destination_t dest; lr11xx_gnss_get_result_destination( result_buf, result_size, &dest ); /* 8. Read detected satellites for diagnostics */ uint8_t nb_sv = 0; lr11xx_gnss_get_nb_detected_satellites( ctx, &nb_sv ); lr11xx_gnss_detected_satellite_t sv_list[32] = { 0 }; lr11xx_gnss_get_detected_satellites( ctx, nb_sv, sv_list ); /* sv_list[i].satellite_id, sv_list[i].cnr, sv_list[i].doppler */ /* 9. Compute power consumption for this scan */ lr11xx_gnss_cumulative_timing_t timing = { 0 }; lr11xx_gnss_read_cumulative_timing( ctx, &timing ); lr11xx_gnss_instantaneous_power_consumption_ua_t power_table = { /* typical values from application note */ .board_voltage_mv = 3300, .init_ua = 4100, .phase1_gps_ua = 9000, .phase2_gps_ua = 9000, .phase1_beidou_ua = 9000, .phase2_beidou_ua = 9000, .demod_sleep_us_ua = 10, .demod_gps_ua = 11000, .demod_beidou_ua = 11000, }; uint32_t nah = 0, nwh = 0; lr11xx_gnss_compute_power_consumption( &timing, &power_table, &nah, &nwh ); /* nah: nano-ampere-hours, nwh: nano-watt-hours */ } ``` ### Response N/A (This is a C code example, not an HTTP API) ``` -------------------------------- ### RTToF Manager Device Setup and Ranging Source: https://context7.com/lora-net/swdr001/llms.txt Configure LoRa modulation, set TX parameters, and initiate ranging as a manager device. Raw results are then read and converted to meters and dBm. ```c #include "lr11xx_rttof.h" #include "lr11xx_radio.h" /* ---- Manager device setup and ranging ---- */ void rttof_manager( radio_context_t* ctx ) { lr11xx_status_t status; /* 1. Configure LoRa modulation for ranging (SF8, BW500 recommended) */ lr11xx_radio_set_pkt_type( ctx, LR11XX_RADIO_PKT_TYPE_LORA ); lr11xx_radio_mod_params_lora_t mod = { .sf = LR11XX_RADIO_LORA_SF8, .bw = LR11XX_RADIO_LORA_BW_500, .cr = LR11XX_RADIO_LORA_CR_4_5, .ldro = 0, }; lr11xx_radio_set_lora_mod_params( ctx, &mod ); lr11xx_radio_set_rf_freq( ctx, 868100000 ); /* 2. Set TX params */ lr11xx_radio_pa_cfg_t pa = { .pa_sel = LR11XX_RADIO_PA_SEL_HP, .pa_reg_supply = LR11XX_RADIO_PA_REG_SUPPLY_VBAT, .pa_duty_cycle = 0x04, .pa_hp_sel = 0x07 }; lr11xx_radio_set_pa_cfg( ctx, &pa ); lr11xx_radio_set_tx_params( ctx, 14, LR11XX_RADIO_RAMP_200_US ); /* 3. Set request address (must match subordinate's configured address) */ status = lr11xx_rttof_set_request_address( ctx, 0x00000019 ); /* 4. Set HW delay compensation (SF8/BW500 calibration value) */ status = lr11xx_rttof_set_rx_tx_delay_indicator( ctx, 11000 ); /* 5. Configure RTToF with 15 symbols in response (accuracy/power tradeoff) */ status = lr11xx_rttof_set_parameters( ctx, 15 ); /* 6. Start ranging TX — the chip automatically handles the exchange */ lr11xx_radio_set_tx( ctx, 1000 ); /* Wait for LR11XX_SYSTEM_IRQ_RTTOF_EXCH_VALID or LR11XX_SYSTEM_IRQ_RTTOF_TIMEOUT */ /* 7. Read raw distance and convert to meters */ uint8_t raw_dist[LR11XX_RTTOF_RESULT_LENGTH] = { 0 }; status = lr11xx_rttof_get_raw_result( ctx, LR11XX_RTTOF_RESULT_TYPE_RAW, raw_dist ); int32_t distance_m = lr11xx_rttof_distance_raw_to_meter( LR11XX_RADIO_LORA_BW_500, raw_dist ); /* distance_m may be negative (noise); typical accuracy ±5 m at short ranges */ /* 8. Read RSSI of the ranging exchange */ uint8_t raw_rssi[LR11XX_RTTOF_RESULT_LENGTH] = { 0 }; lr11xx_rttof_get_raw_result( ctx, LR11XX_RTTOF_RESULT_TYPE_RSSI, raw_rssi ); int8_t rssi_dbm = lr11xx_rttof_rssi_raw_to_value( raw_rssi ); } ``` -------------------------------- ### Get Version Source: https://context7.com/lora-net/swdr001/llms.txt Retrieves the hardware and firmware version of the LR11XX chip. ```APIDOC ## lr11xx_system_get_version ### Description Retrieves the hardware and firmware version of the LR11XX chip. ### Method C Function Call ### Parameters - **ctx** (*radio_context_t*) - Required - Pointer to the radio context structure. - **ver** (*lr11xx_system_version_t*) - Required - Pointer to a structure to store the version information. - **ver.hw** (uint8_t) - Hardware revision. - **ver.type** (uint8_t) - Chip type (e.g., LR11XX_SYSTEM_VERSION_TYPE_LR1110). - **ver.fw** (uint16_t) - Firmware version (e.g., 0x0307). ### Return Value - **lr11xx_status_t** - Returns LR11XX_STATUS_OK on success. ``` -------------------------------- ### Set Public Include Directories Source: https://github.com/lora-net/swdr001/blob/master/src/CMakeLists.txt Configures the public include directories for the lr11xx_driver library. It includes the current source directory for build-time and specifies an empty interface for installation. ```cmake target_include_directories(lr11xx_driver PUBLIC $ $ ) ``` -------------------------------- ### RTToF Subordinate Device Setup Source: https://context7.com/lora-net/swdr001/llms.txt Configure the subordinate device with the same LoRa modulation and frequency as the manager. Set the subordinate address to match the manager's request address to enable automatic response to ranging requests. ```c /* ---- Subordinate device setup ---- */ void rttof_subordinate( radio_context_t* ctx ) { /* Configure same modulation and frequency as manager */ lr11xx_radio_set_pkt_type( ctx, LR11XX_RADIO_PKT_TYPE_LORA ); lr11xx_radio_mod_params_lora_t mod = { .sf = LR11XX_RADIO_LORA_SF8, .bw = LR11XX_RADIO_LORA_BW_500, .cr = LR11XX_RADIO_LORA_CR_4_5, .ldro = 0, }; lr11xx_radio_set_lora_mod_params( ctx, &mod ); lr11xx_radio_set_rf_freq( ctx, 868100000 ); /* Configure subordinate address (match the manager's request address) */ lr11xx_rttof_set_address( ctx, 0x00000019, 4 ); /* check all 4 bytes */ lr11xx_rttof_set_rx_tx_delay_indicator( ctx, 11000 ); lr11xx_rttof_set_parameters( ctx, 15 ); /* Start RX — responds automatically upon receiving a matching RTToF request */ lr11xx_radio_set_rx( ctx, 0 ); /* RX single, wait indefinitely */ } ``` -------------------------------- ### Receive LoRa Packet with Duty Cycle Source: https://context7.com/lora-net/swdr001/llms.txt Configures the radio to listen for a specified duration and then sleep. This example sets up a 100 ms listen period followed by a 900 ms sleep, using standard RX mode. ```c lr11xx_radio_set_rx_duty_cycle( ctx, 100, 900, LR11XX_RADIO_RX_DUTY_CYCLE_MODE_RX ); ``` -------------------------------- ### Get Status Source: https://context7.com/lora-net/swdr001/llms.txt Retrieves the status of the LR11XX chip, including error flags. ```APIDOC ## lr11xx_system_get_status ### Description Retrieves the status of the LR11XX chip, including error flags. ### Method C Function Call ### Parameters - **ctx** (*radio_context_t*) - Required - Pointer to the radio context structure. - **errors** (*uint16_t*) - Required - Pointer to a 16-bit integer to store error flags. ### Return Value - **lr11xx_status_t** - Returns LR11XX_STATUS_OK on success. ``` -------------------------------- ### Transmit LoRa Packet Source: https://context7.com/lora-net/swdr001/llms.txt Initiates a LoRa transmission. The transmission will start immediately after this function is called. ```c lr11xx_radio_set_tx( ctx, tx_payload_len ); ``` -------------------------------- ### lr11xx_radio_set_rx_duty_cycle Source: https://context7.com/lora-net/swdr001/llms.txt Configures the radio to operate in a duty cycle mode, alternating between listening and sleeping. This specific example sets the radio to listen for 100 ms and sleep for 900 ms, using standard RX mode. ```APIDOC ## lr11xx_radio_set_rx_duty_cycle ### Description Configures the radio to operate in a duty cycle mode, alternating between listening and sleeping. This function allows for power saving by defining periods of inactivity. ### Parameters #### Path Parameters - **ctx** (lr11xx_radio_t*) - Required - Pointer to the radio context structure. - **rx_timeout** (uint32_t) - Required - Duration in milliseconds for the RX listening period. - **sleep_timeout** (uint32_t) - Required - Duration in milliseconds for the sleep period. - **mode** (lr11xx_radio_rx_duty_cycle_mode_t) - Required - The mode for the RX period. Use `LR11XX_RADIO_RX_DUTY_CYCLE_MODE_RX` for standard RX. ### Request Example ```c // Listen 100 ms, sleep 900 ms, use standard RX (not CAD) lr11xx_radio_set_rx_duty_cycle( ctx, 100, 900, LR11XX_RADIO_RX_DUTY_CYCLE_MODE_RX ); ``` ### Response #### Success Response (0) - **void** - No return value on success. #### Error Response - **lr11xx_status_t** - Returns an error code if the operation fails. ``` -------------------------------- ### LoRaWAN Key Operations with Crypto Engine Source: https://context7.com/lora-net/swdr001/llms.txt Demonstrates loading root keys, deriving session keys using nonces, storing keys to flash, AES encryption/decryption, and CMAC computation for LoRaWAN messages. ```c #include "lr11xx_crypto_engine.h" #define APP_KEY_ID 0x00 #define NWK_KEY_ID 0x01 #define DERIVED_ID 0x02 void crypto_lorawan_key_operations( radio_context_t* ctx ) { lr11xx_status_t status; lr11xx_crypto_status_t crypto_status; /* 1. Load the application root key (16 bytes) */ lr11xx_crypto_key_t app_key = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }; status = lr11xx_crypto_set_key( ctx, &crypto_status, APP_KEY_ID, app_key ); assert( status == LR11XX_STATUS_OK && crypto_status == LR11XX_CRYPTO_STATUS_SUCCESS ); /* 2. Derive a session key using a nonce (e.g., DevNonce for LoRaWAN 1.0) */ lr11xx_crypto_nonce_t nonce = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; status = lr11xx_crypto_derive_key( ctx, &crypto_status, APP_KEY_ID, DERIVED_ID, nonce ); /* 3. Store derived key to flash for persistence across power cycles */ status = lr11xx_crypto_store_to_flash( ctx, &crypto_status ); assert( status == LR11XX_STATUS_OK ); /* 4. AES-128 encrypt a 16-byte block */ uint8_t plaintext[16] = { 0x32, 0x43, 0xF6, 0xA8, 0x88, 0x5A, 0x30, 0x8D, 0x31, 0x31, 0x98, 0xA2, 0xE0, 0x37, 0x07, 0x34 }; uint8_t ciphertext[16] = { 0 }; status = lr11xx_crypto_aes_encrypt( ctx, &crypto_status, DERIVED_ID, plaintext, 16, ciphertext ); /* 5. AES decrypt to recover plaintext */ uint8_t recovered[16] = { 0 }; status = lr11xx_crypto_aes_decrypt( ctx, &crypto_status, DERIVED_ID, ciphertext, 16, recovered ); /* 6. Compute AES-CMAC (MIC) over a LoRaWAN message */ uint8_t message[32] = { /* LoRaWAN frame bytes */ }; lr11xx_crypto_mic_t mic = { 0 }; status = lr11xx_crypto_compute_aes_cmac( ctx, &crypto_status, NWK_KEY_ID, message, sizeof( message ), mic ); /* mic[0..3] = first 4 bytes of CMAC = LoRaWAN MIC */ /* 7. Verify a received MIC */ lr11xx_crypto_mic_t received_mic = { 0xDE, 0xAD, 0xBE, 0xEF }; status = lr11xx_crypto_verify_aes_cmac( ctx, &crypto_status, NWK_KEY_ID, message, sizeof( message ), received_mic ); /* crypto_status == LR11XX_CRYPTO_STATUS_SUCCESS if MIC matches */ /* 8. Process a LoRaWAN join-accept (decrypt + MIC verify in one call) */ uint8_t join_accept_header[1] = { 0x20 }; uint8_t join_accept_data[16] = { /* encrypted join-accept payload */ }; uint8_t decrypted[16] = { 0 }; status = lr11xx_crypto_process_join_accept( ctx, &crypto_status, APP_KEY_ID, NWK_KEY_ID, LR11XX_CRYPTO_LORAWAN_VERSION_1_0, join_accept_header, join_accept_data, 16, decrypted ); } ``` -------------------------------- ### Initialize LoRa-Net SWDR001 Radio Source: https://context7.com/lora-net/swdr001/llms.txt This sequence performs a hard and software reset, reads the chip version, checks for boot errors, configures the TCXO, calibrates the image, sets up RF switch DIOs, routes IRQs, configures the regulator, reads the UID, and sets the standby mode. Ensure the `radio_context_t` is properly initialized before calling. ```c #include "lr11xx_system.h" /* --- Typical initialization sequence --- */ void radio_init( radio_context_t* ctx ) { lr11xx_status_t status; /* 1. Hard reset via HAL, then software reset */ lr11xx_hal_reset( ctx ); status = lr11xx_system_reset( ctx ); assert( status == LR11XX_STATUS_OK ); /* 2. Read chip version */ lr11xx_system_version_t ver = { 0 }; status = lr11xx_system_get_version( ctx, &ver ); /* ver.hw = hardware revision ver.type = LR11XX_SYSTEM_VERSION_TYPE_LR1110 / LR1120 ver.fw = firmware version (e.g. 0x0307) */ /* 3. Check for errors from previous boot */ uint16_t errors = 0; lr11xx_system_get_errors( ctx, &errors ); if( errors ) { lr11xx_system_clear_errors( ctx ); /* Run full calibration if RC/PLL errors present */ lr11xx_system_calibrate( ctx, LR11XX_SYSTEM_CALIB_LF_RC_BITMASK | LR11XX_SYSTEM_CALIB_HF_RC_BITMASK | LR11XX_SYSTEM_CALIB_PLL_BITMASK | LR11XX_SYSTEM_CALIB_ADC_BITMASK | LR11XX_SYSTEM_CALIB_IMG_BITMASK ); } /* 4. Configure TCXO (1.8 V, 5 ms startup) */ lr11xx_system_set_tcxo_mode( ctx, LR11XX_SYSTEM_TCXO_CTRL_1_8V, 5 * 1000 / 30 ); /* timeout in 30.52 µs ticks ≈ 164 */ /* 5. Calibrate image for 868 MHz band */ lr11xx_system_calibrate_image_in_mhz( ctx, 863, 870 ); /* 6. Configure RF switch DIOs */ lr11xx_system_rfswitch_cfg_t rf_cfg = { .enable = LR11XX_SYSTEM_RFSW0_HIGH, .standby = 0, .rx = LR11XX_SYSTEM_RFSW0_HIGH, .tx = LR11XX_SYSTEM_RFSW1_HIGH, .tx_hp = LR11XX_SYSTEM_RFSW1_HIGH, .tx_hf = 0, .gnss = 0, .wifi = 0, }; lr11xx_system_set_dio_as_rf_switch( ctx, &rf_cfg ); /* 7. Route TxDone / RxDone IRQs to DIO9 */ lr11xx_system_set_dio_irq_params( ctx, LR11XX_SYSTEM_IRQ_TX_DONE | LR11XX_SYSTEM_IRQ_RX_DONE | LR11XX_SYSTEM_IRQ_TIMEOUT | LR11XX_SYSTEM_IRQ_CRC_ERROR, 0 ); /* 8. Use DC-DC regulator */ lr11xx_system_set_reg_mode( ctx, LR11XX_SYSTEM_REG_MODE_DCDC ); /* 9. Read UID for device identification */ lr11xx_system_uid_t uid = { 0 }; lr11xx_system_read_uid( ctx, uid ); /* uid[0..7] now holds the 8-byte unique identifier */ /* 10. Enter standby on XOSC */ lr11xx_system_set_standby( ctx, LR11XX_SYSTEM_STANDBY_CFG_XOSC ); } ``` -------------------------------- ### Apply Mixer Configuration Workaround (User-Handled) Source: https://github.com/lora-net/swdr001/blob/master/README.md This implementation requires the user to explicitly call lr11xx_gnss_apply_mixer_cfg_workaround after a 2.4GHz reception and before a GNSS scan, if the chip did not enter a sleep or scan state. This method requires disabling the default driver implementation by defining LR11XX_DISABLE_MIXER_CFG_WORKAROUND. ```c lr11xx_gnss_apply_mixer_cfg_workaround(); ``` -------------------------------- ### lr11xx_hal_wakeup Source: https://context7.com/lora-net/swdr001/llms.txt Wakes up the LR11XX chip from a low-power state. This function is part of the HAL and must be implemented by the user for porting the driver. ```APIDOC ## lr11xx_hal_wakeup ### Description Wakes up the LR11XX chip from a low-power state. This function is part of the HAL and must be implemented by the user for porting the driver. ### Function Signature ```c lr11xx_hal_status_t lr11xx_hal_wakeup( const void* context ) ``` ### Parameters - **context**: Pointer to the platform-specific context. ### Returns - **lr11xx_hal_status_t**: Status of the operation, typically LR11XX_HAL_STATUS_OK on success. ``` -------------------------------- ### Crypto Engine Operations Source: https://context7.com/lora-net/swdr001/llms.txt Demonstrates the usage of various crypto engine functions for key management, AES operations, and CMAC computation. ```APIDOC ## Crypto Engine Functions ### `lr11xx_crypto_set_key` #### Description Sets a key in the crypto engine's internal keychain. ### `lr11xx_crypto_derive_key` #### Description Derives a new key based on an existing key and a nonce. Useful for session key derivation. ### `lr11xx_crypto_store_to_flash` #### Description Stores the currently derived key to flash memory for persistence. ### `lr11xx_crypto_aes_encrypt` #### Description Performs AES-128 encryption on a given plaintext block using a specified key. ### `lr11xx_crypto_aes_decrypt` #### Description Performs AES-128 decryption on a given ciphertext block using a specified key. ### `lr11xx_crypto_compute_aes_cmac` #### Description Computes the AES-CMAC (Cipher-based Message Authentication Code) for a given message using a specified key. This is often used for Message Integrity Code (MIC) in LoRaWAN. ### `lr11xx_crypto_verify_aes_cmac` #### Description Verifies a received AES-CMAC against a computed one for a given message and key. Returns success if they match. ### `lr11xx_crypto_process_join_accept` #### Description Processes a LoRaWAN join-accept message by decrypting the payload and verifying its integrity using the provided keys and LoRaWAN version. ``` -------------------------------- ### Implement LR11XX HAL Functions Source: https://context7.com/lora-net/swdr001/llms.txt Provides the platform-dependent HAL functions for LR11XX communication. Requires a custom SPI driver and context structure for MCU-specific details. ```c #include "lr11xx_hal.h" #include "your_spi_driver.h" /* --- Platform context passed to every driver call --- */ typedef struct { SPI_HandleTypeDef* hspi; GPIO_TypeDef* nss_port; uint16_t nss_pin; GPIO_TypeDef* reset_port; uint16_t reset_pin; GPIO_TypeDef* busy_port; uint16_t busy_pin; } radio_context_t; ``` ```c /* Wait for chip to de-assert BUSY */ static void wait_busy( const radio_context_t* ctx ) { while( HAL_GPIO_ReadPin( ctx->busy_port, ctx->busy_pin ) == GPIO_PIN_SET ); } ``` ```c lr11xx_hal_status_t lr11xx_hal_write( const void* context, const uint8_t* command, const uint16_t command_length, const uint8_t* data, const uint16_t data_length ) { const radio_context_t* ctx = ( const radio_context_t* ) context; wait_busy( ctx ); HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_RESET ); HAL_SPI_Transmit( ctx->hspi, (uint8_t*) command, command_length, HAL_MAX_DELAY ); if( data_length > 0 ) HAL_SPI_Transmit( ctx->hspi, (uint8_t*) data, data_length, HAL_MAX_DELAY ); HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_SET ); return LR11XX_HAL_STATUS_OK; } ``` ```c lr11xx_hal_status_t lr11xx_hal_read( const void* context, const uint8_t* command, const uint16_t command_length, uint8_t* data, const uint16_t data_length ) { const radio_context_t* ctx = ( const radio_context_t* ) context; wait_busy( ctx ); /* Step 1: send command */ HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_RESET ); HAL_SPI_Transmit( ctx->hspi, (uint8_t*) command, command_length, HAL_MAX_DELAY ); HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_SET ); wait_busy( ctx ); /* Step 2: re-assert NSS, read dummy + response (write only NOP bytes) */ uint8_t dummy = LR11XX_NOP; HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_RESET ); HAL_SPI_Receive( ctx->hspi, &dummy, 1, HAL_MAX_DELAY ); /* discard dummy */ HAL_SPI_Receive( ctx->hspi, data, data_length, HAL_MAX_DELAY ); HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_SET ); return LR11XX_HAL_STATUS_OK; } ``` ```c lr11xx_hal_status_t lr11xx_hal_reset( const void* context ) { const radio_context_t* ctx = ( const radio_context_t* ) context; HAL_GPIO_WritePin( ctx->reset_port, ctx->reset_pin, GPIO_PIN_RESET ); HAL_Delay( 1 ); HAL_GPIO_WritePin( ctx->reset_port, ctx->reset_pin, GPIO_PIN_SET ); HAL_Delay( 5 ); return LR11XX_HAL_STATUS_OK; } ``` ```c lr11xx_hal_status_t lr11xx_hal_wakeup( const void* context ) { const radio_context_t* ctx = ( const radio_context_t* ) context; HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_RESET ); HAL_Delay( 1 ); HAL_GPIO_WritePin( ctx->nss_port, ctx->nss_pin, GPIO_PIN_SET ); return LR11XX_HAL_STATUS_OK; } ``` ```c /* CRC helper (no chip communication) */ uint8_t compute_my_crc( const uint8_t* buf, uint16_t len ) { return lr11xx_hal_compute_crc( 0x00, buf, len ); /* Returns CRC-8 using polynomial 0x65 */ } ``` -------------------------------- ### Perform Wi-Fi Scan and Read Results Source: https://context7.com/lora-net/swdr001/llms.txt Initiates a Wi-Fi scan for 802.11 b/g/n signals, retrieves the number of detected results, and reads the basic complete results. Parses MAC address, channel information, and signal type. Also estimates power consumption and shows an alternative time-limited scan configuration. ```c #include "lr11xx_wifi.h" /* --- Wi-Fi scan and result reading --- */ void wifi_scan_and_read( radio_context_t* ctx ) { lr11xx_status_t status; /* 1. Scan all channels for B/G/N signals, beacon+packet mode, up to 16 results, 3 scans per channel, 100 ms timeout, abort on timeout */ status = lr11xx_wifi_scan( ctx, LR11XX_WIFI_TYPE_SCAN_B_G_N, LR11XX_WIFI_ALL_CHANNELS, LR11XX_WIFI_SCAN_MODE_BEACON_AND_PKT, 16, /* max_results */ 3, /* nb_scan_per_channel */ 100, /* timeout_in_ms */ true /* abort_on_timeout */ ); assert( status == LR11XX_STATUS_OK ); /* Wait for LR11XX_SYSTEM_IRQ_WIFI_SCAN_DONE IRQ */ /* 2. Get number of results */ uint8_t nb_results = 0; lr11xx_wifi_get_nb_results( ctx, &nb_results ); /* 3. Read all results at once (basic complete format) */ lr11xx_wifi_basic_complete_result_t results[32] = { 0 }; lr11xx_wifi_read_basic_complete_results( ctx, 0, nb_results, results ); for( uint8_t i = 0; i < nb_results; i++ ) { /* MAC address */ uint8_t* mac = results[i].mac_address; /* Parse channel info */ lr11xx_wifi_channel_t channel; bool rssi_valid; lr11xx_wifi_mac_origin_t origin; lr11xx_wifi_parse_channel_info( results[i].channel_info_byte, &channel, &rssi_valid, &origin ); /* Parse data rate / signal type */ lr11xx_wifi_signal_type_result_t sig_type; lr11xx_wifi_datarate_t data_rate; lr11xx_wifi_parse_data_rate_info( results[i].data_rate_info_byte, &sig_type, &data_rate ); /* results[i].rssi contains signal strength in dBm */ } /* 4. Estimate power consumption of this scan */ lr11xx_wifi_cumulative_timings_t timing = { 0 }; lr11xx_wifi_read_cumulative_timing( ctx, &timing ); uint32_t consumption_nah = lr11xx_wifi_get_consumption_nah( LR11XX_SYSTEM_REG_MODE_DCDC, timing ); /* 5. Alternative: time-limited scan (no nb_scan_per_channel) */ lr11xx_wifi_scan_time_limit( ctx, LR11XX_WIFI_TYPE_SCAN_B, LR11XX_WIFI_ALL_CHANNELS, LR11XX_WIFI_SCAN_MODE_BEACON, 16, /* max_results */ 200, /* timeout_per_channel_ms */ 50 /* timeout_per_scan_ms */ ); } ``` -------------------------------- ### Define lr11xx_driver Static Library Source: https://github.com/lora-net/swdr001/blob/master/src/CMakeLists.txt Defines the lr11xx_driver as a static library, listing its core source files. This is the primary library definition. ```cmake add_library(lr11xx_driver STATIC lr11xx_bootloader.c lr11xx_crypto_engine.c lr11xx_driver_version.c lr11xx_lr_fhss.c lr11xx_radio_timings.c lr11xx_radio.c lr11xx_regmem.c lr11xx_rttof.c lr11xx_system.c ) ``` -------------------------------- ### Write and Read 32-bit Register LR11XX Source: https://context7.com/lora-net/swdr001/llms.txt Demonstrates reading and writing 32-bit registers. Includes a workaround for high-ACP issues by directly manipulating a register. Use the masked write for simpler operations. ```c #include "lr11xx_regmem.h" /* --- Apply the high-ACP workaround manually (write to register 0x00F30054) --- */ void apply_high_acp_workaround( radio_context_t* ctx ) { const uint32_t reg_addr = 0x00F30054; uint32_t reg_val = 0; /* Read current value */ lr11xx_regmem_read_regmem32( ctx, reg_addr, ®_val, 1 ); /* Clear bit 30 */ reg_val &= ~( 1UL << 30 ); /* Write back */ lr11xx_regmem_write_regmem32( ctx, reg_addr, ®_val, 1 ); } /* --- Or use the masked write shorthand --- */ void apply_high_acp_workaround_masked( radio_context_t* ctx ) { lr11xx_regmem_write_regmem32_mask( ctx, 0x00F30054, ~( 1UL << 30 ), /* mask: clear bit 30 */ 0 ); /* data: write 0 into that bit */ } ``` -------------------------------- ### Apply Mixer Configuration Workaround (Driver) Source: https://github.com/lora-net/swdr001/blob/master/README.md This is the default implementation in the driver, automatically updating the mixer configuration parameter before GNSS scans. It is transparent to the user but may be called unnecessarily. Define LR11XX_DISABLE_MIXER_CFG_WORKAROUND to disable. ```c #define LR11XX_DISABLE_MIXER_CFG_WORKAROUND ``` -------------------------------- ### lr11xx_hal_read Source: https://context7.com/lora-net/swdr001/llms.txt Sends a command, releases NSS, then reads a dummy byte followed by the response. This function is part of the HAL and must be implemented by the user for porting the driver. ```APIDOC ## lr11xx_hal_read ### Description Sends a command, releases NSS, then reads a dummy byte followed by the response. This function is part of the HAL and must be implemented by the user for porting the driver. ### Function Signature ```c lr11xx_hal_status_t lr11xx_hal_read( const void* context, const uint8_t* command, const uint16_t command_length, uint8_t* data, const uint16_t data_length ) ``` ### Parameters - **context**: Pointer to the platform-specific context. - **command**: Pointer to the command buffer. - **command_length**: Length of the command buffer. - **data**: Pointer to the buffer where the response will be stored. - **data_length**: Length of the data buffer to read. ### Returns - **lr11xx_hal_status_t**: Status of the operation, typically LR11XX_HAL_STATUS_OK on success. ``` -------------------------------- ### Create Alias Target for lr11xx_driver Source: https://github.com/lora-net/swdr001/blob/master/src/CMakeLists.txt Creates an alias target 'lr11xx_driver::lr11xx_driver' for the 'lr11xx_driver' library. This is a common CMake practice for modern target usage. ```cmake add_library(lr11xx_driver::lr11xx_driver ALIAS lr11xx_driver) ``` -------------------------------- ### lr11xx_hal_write Source: https://context7.com/lora-net/swdr001/llms.txt Sends a command and optional data over SPI. This function is part of the HAL and must be implemented by the user for porting the driver. ```APIDOC ## lr11xx_hal_write ### Description Sends a command and optional data over SPI. This function is part of the HAL and must be implemented by the user for porting the driver. ### Function Signature ```c lr11xx_hal_status_t lr11xx_hal_write( const void* context, const uint8_t* command, const uint16_t command_length, const uint8_t* data, const uint16_t data_length ) ``` ### Parameters - **context**: Pointer to the platform-specific context. - **command**: Pointer to the command buffer. - **command_length**: Length of the command buffer. - **data**: Pointer to the data buffer (optional). - **data_length**: Length of the data buffer (optional). ### Returns - **lr11xx_hal_status_t**: Status of the operation, typically LR11XX_HAL_STATUS_OK on success. ```