diff --git a/.gitignore b/.gitignore index 2906ee4..9c3231a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ install_manifest.txt compile_commands.json CTestTestfile.cmake _deps +.vscode/ build/ diff --git a/API.md b/API.md index 4751bd8..cb09c87 100644 --- a/API.md +++ b/API.md @@ -12,7 +12,7 @@ ```c // pin configuration for SX1276 radio module -struct lorawan_sx1276_settings sx1276_settings = { +struct lorawan_sx12xx_settings sx12xx_settings = { .spi = { .inst = PICO_DEFAULT_SPI_INSTANCE, // RP2040 SPI instance .mosi = PICO_DEFAULT_SPI_TX_PIN, // SPI MOSI GPIO @@ -47,10 +47,10 @@ const struct lorawan_abp_settings abp_settings = { .channel_mask = NULL, }; -int lorawan_init_abp(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings); +int lorawan_init_abp(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings); ``` -- `sx1276_settings` - pointer to settings for SX1276 SPI and GPIO pins +- `sx12xx_settings` - pointer to settings for SX1276 SPI and GPIO pins - `region` - region to use, see [`enum LoRaMacRegion_t `](http://stackforce.github.io/LoRaMac-doc/LoRaMac-doc-v4.5.1/group___l_o_r_a_m_a_c.html#ga3b9d54f0355b51e85df8b33fd1757eec)for supported values] - `abp_settings` - pointer to LoRaWAN ABP settings @@ -77,10 +77,10 @@ const struct lorawan_otaa_settings otaa_settings = { .channel_mask = NULL, }; -int lorawan_init_otaa(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings); +int lorawan_init_otaa(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings); ``` -- `sx1276_settings` - pointer to settings for SX1276 SPI and GPIO pins +- `sx12xx_settings` - pointer to settings for SX1276 SPI and GPIO pins - `region` - region to use, see [`enum LoRaMacRegion_t `](http://stackforce.github.io/LoRaMac-doc/LoRaMac-doc-v4.5.1/group___l_o_r_a_m_a_c.html#ga3b9d54f0355b51e85df8b33fd1757eec)for supported values] - `otaa_settings` - pointer to LoRaWAN OTAA settings diff --git a/CMakeLists.txt b/CMakeLists.txt index 45a0918..5d9594c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,30 @@ pico_sdk_init() set(LORAMAC_NODE_PATH ${CMAKE_CURRENT_LIST_DIR}/lib/LoRaMac-node) +# Choose whether to enable Waveshare SX1262 module support instead of SX1276 support. +# This will control cmake's build behavior. +option(WITH_WAVESHARE_SX126X "Enable Waveshare SX1262 Raspberry Pi LoRa module support instead of SX1276" OFF) + +# Enable for use with SX126X, e.g. Waveshare Raspberry Pi Pico LoRa module SX1262 by uncommenting: +#set(WITH_WAVESHARE_SX126X ON) + +## Depending on previous selection, add the following items +if(WITH_WAVESHARE_SX126X) + message("Building for SX126X") + set(SX12XX_RADIO_FILES + ${LORAMAC_NODE_PATH}/src/radio/sx126x/sx126x.c + ${LORAMAC_NODE_PATH}/src/radio/sx126x/radio.c + ) + set(SX12XX_BOARD_FILES ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/sx126x-board.c) +else() + message("Building for SX1276") + set(SX12XX_RADIO_FILES + ${LORAMAC_NODE_PATH}/src/radio/sx1276/sx1276.c + ) + set(SX12XX_BOARD_FILES ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/sx1276-board.c) +endif() + + add_library(pico_loramac_node INTERFACE) target_sources(pico_loramac_node INTERFACE @@ -65,7 +89,7 @@ target_sources(pico_loramac_node INTERFACE ${LORAMAC_NODE_PATH}/src/peripherals/soft-se/soft-se-hal.c ${LORAMAC_NODE_PATH}/src/peripherals/soft-se/soft-se.c - ${LORAMAC_NODE_PATH}/src/radio/sx1276/sx1276.c + ${SX12XX_RADIO_FILES} ${LORAMAC_NODE_PATH}/src/system/delay.c ${LORAMAC_NODE_PATH}/src/system/gpio.c @@ -79,7 +103,8 @@ target_sources(pico_loramac_node INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/gpio-board.c ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/rtc-board.c ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/spi-board.c - ${CMAKE_CURRENT_LIST_DIR}/src/boards/rp2040/sx1276-board.c + + ${SX12XX_BOARD_FILES} ) target_include_directories(pico_loramac_node INTERFACE @@ -108,7 +133,11 @@ target_compile_definitions(pico_loramac_node INTERFACE -DREGION_CN470) target_compile_definitions(pico_loramac_node INTERFACE -DREGION_KR920) target_compile_definitions(pico_loramac_node INTERFACE -DREGION_IN865) target_compile_definitions(pico_loramac_node INTERFACE -DREGION_RU864) -target_compile_definitions(pico_loramac_node INTERFACE -DACTIVE_REGION=LORAMAC_REGION_US915) +if(WITH_WAVESHARE_SX126X) + target_compile_definitions(pico_loramac_node INTERFACE -DACTIVE_REGION=LORAMAC_REGION_EU868) +else() + target_compile_definitions(pico_loramac_node INTERFACE -DACTIVE_REGION=LORAMAC_REGION_US915) +endif() add_library(pico_lorawan INTERFACE) @@ -122,7 +151,17 @@ target_include_directories(pico_lorawan INTERFACE target_link_libraries(pico_lorawan INTERFACE pico_loramac_node) -add_subdirectory("examples/default_dev_eui") -add_subdirectory("examples/hello_abp") -add_subdirectory("examples/hello_otaa") -add_subdirectory("examples/otaa_temperature_led") +# define sx1262 for preprocessor if Waveshare sx1262 support is enabled in cmake. +# Also do not build all examples for now (they are partly incompatible) +if(WITH_WAVESHARE_SX126X) + add_definitions(-Dsx126x) + add_subdirectory("examples/otaa_temperature_led") +else() + add_definitions(-Dsx1276) + add_subdirectory("examples/default_dev_eui") + add_subdirectory("examples/hello_abp") + add_subdirectory("examples/hello_otaa") + add_subdirectory("examples/otaa_temperature_led") +endif() + + diff --git a/README.md b/README.md index a2ca0a0..81f3947 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # pico-lorawan -Enable LoRaWAN communications on your [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/) or any RP2040 based board using a [Semtech SX1276 radio module](https://www.semtech.com/apps/product.php?pn=SX1276). +Enable LoRaWAN communications on your [Raspberry Pi Pico](https://www.raspberrypi.org/products/raspberry-pi-pico/) or any RP2040 based board using a [Semtech SX1276 radio module](https://www.semtech.com/apps/product.php?pn=SX1276) or [Waveshare's SX1262-based LoRaWAN module](https://www.waveshare.com/wiki/Pico-LoRa-SX1262-868M). Based on the Semtech's [LoRaWAN end-device stack implementation and example projects](https://github.com/Lora-net/LoRaMac-node). @@ -11,9 +11,13 @@ Based on the Semtech's [LoRaWAN end-device stack implementation and example proj * Semtech SX1276 board * [Adafruit RFM95W LoRa Radio Transceiver Breakout - 868 or 915 MHz - RadioFruit](https://www.adafruit.com/product/3072) * [Adafruit LoRa Radio FeatherWing - RFM95W 900 MHz - RadioFruit](https://www.adafruit.com/product/3231) + * Semtech SX1262 board + * [Waveshare Pico-LoRa-SX1262-868M](https://www.waveshare.com/wiki/Pico-LoRa-SX1262-868M) | [Shop](https://www.waveshare.com/pico-lora-sx1262-868m.htm) ### Default Pinout +Default Pinout for Semtech SX1276: + | Raspberry Pi Pico / RP2040 | Semtech SX1276 | | ----------------- | -------------- | | 3.3V | VCC | @@ -26,8 +30,63 @@ Based on the Semtech's [LoRaWAN end-device stack implementation and example proj | GPIO 9 | RESET | | GPIO 10 | DIO1 / G1 | +Default Pinout for Semtech SX1262 on Waveshare Pico-LoRa-SX1262-868M: + +| Raspberry Pi Pico / RP2040 | Waveshare Pico-LoRa-SX1262-868M | +| ----------------- | -------------- | +| 3.3V | VCC | +| GND | GND | +| GPIO 10 | SCK | +| GPIO 11 | MOSI | +| GPIO 12 | MISO | +| GPIO 3 | NSS / CS | +| GPIO 15 | RESET | +| GPIO 20 | DIO1 | +| GPIO 2 | BUSY | + GPIO pins are configurable in examples or API. +## Enabling support for Waveshare Pico-LoRa-SX1262-868M + +By default this library only supports the Semtech SX1276 boards mentioned in the first section. Support for Waveshare's SX1262-based Raspberry Pi Pico Hat is available, but needs to be enabled actively. + +Take the following steps to switch from SX1276 to Waveshare SX1262 support: + +Uncomment + +``` +set(WITH_WAVESHARE_SX126X ON) +``` + +in `CMakeLists.txt`. + +In your example application, e.g. otaa_temperature_led/ set the region to EU868 in `config.h`: + +``` +#define LORAWAN_REGION LORAMAC_REGION_EU868 +``` + +_(and also provide your Device EUI, App EUI and App Key here!)_ + +In the example application's `main.c` make sure that you're using the proper `sx12xx_settings` for your SX1262 Waveshare module: + +``` +const struct lorawan_sx12xx_settings sx12xx_settings = { + .spi = { + .inst = spi1, + .mosi = 11, + .miso = 12, + .sck = 10, + .nss = 3 + }, + .reset = 15, + .busy = 2, + .dio1 = 20 +}; +``` + +_**There is no guarantee that other SX1262-based boards will work. Tests have only been run using Waveshare's board.**_ + ## Examples See [examples](examples/) folder. @@ -60,5 +119,7 @@ make A big thanks to [Alasdair Allan](https://github.com/aallan) for his initial testing of EU868 support! +Thanks to Waveshare and [siuwahzhong](https://github.com/siuwahzhong) for providing their modified version of this library. Parts of their work have been merged back into this library by [Thomas Leister](https://github.com/ThomasLeister). Original source: [ZIP](https://www.waveshare.com/w/upload/0/08/Pico-LoRa-SX1262-868M_Code.zip) | [GitHub](https://github.com/siuwahzhong/lorawan-library-for-pico) + This project was created on behalf of the [Arm Software Developers](https://developer.arm.com/) team, follow them on Twitter: [@ArmSoftwareDev](https://twitter.com/armsoftwaredev) and YouTube: [Arm Software Developers](https://www.youtube.com/channel/UCHUAckhCfRom2EHDGxwhfOg) for more resources! diff --git a/examples/hello_abp/main.c b/examples/hello_abp/main.c index b1481df..f97bca4 100644 --- a/examples/hello_abp/main.c +++ b/examples/hello_abp/main.c @@ -19,20 +19,38 @@ // edit with LoRaWAN Node Region and ABP settings #include "config.h" -// pin configuration for SX1276 radio module -const struct lorawan_sx1276_settings sx1276_settings = { +/* + * Pin configuration for SX1276 radio module (default) + */ +const struct lorawan_sx12xx_settings sx12xx_settings = { .spi = { .inst = PICO_DEFAULT_SPI_INSTANCE, .mosi = PICO_DEFAULT_SPI_TX_PIN, .miso = PICO_DEFAULT_SPI_RX_PIN, .sck = PICO_DEFAULT_SPI_SCK_PIN, - .nss = 8 + .nss = 8 }, .reset = 9, - .dio0 = 7, - .dio1 = 10 + .dio0 = 7, + .dio1 = 10 }; +/* + * Configuration for SX1262 Waveshare module + */ +//const struct lorawan_sx12xx_settings sx12xx_settings = { +// .spi = { +// .inst = spi1, +// .mosi = 11, +// .miso = 12, +// .sck = 10, +// .nss = 3 +// }, +// .reset = 15, +// .busy = 2, +// .dio1 = 20 +//}; + // ABP settings const struct lorawan_abp_settings abp_settings = { .device_address = LORAWAN_DEV_ADDR, @@ -62,7 +80,7 @@ int main( void ) // initialize the LoRaWAN stack printf("Initilizating LoRaWAN ... "); - if (lorawan_init_abp(&sx1276_settings, LORAWAN_REGION, &abp_settings) < 0) { + if (lorawan_init_abp(&sx12xx_settings, LORAWAN_REGION, &abp_settings) < 0) { printf("failed!!!\n"); while (1) { tight_loop_contents(); diff --git a/examples/hello_otaa/main.c b/examples/hello_otaa/main.c index 537a99b..fd68285 100644 --- a/examples/hello_otaa/main.c +++ b/examples/hello_otaa/main.c @@ -18,8 +18,10 @@ // edit with LoRaWAN Node Region and OTAA settings #include "config.h" -// pin configuration for SX1276 radio module -const struct lorawan_sx1276_settings sx1276_settings = { +/* + * Pin configuration for SX1276 radio module (default) + */ +const struct lorawan_sx12xx_settings sx12xx_settings = { .spi = { .inst = PICO_DEFAULT_SPI_INSTANCE, .mosi = PICO_DEFAULT_SPI_TX_PIN, @@ -32,6 +34,22 @@ const struct lorawan_sx1276_settings sx1276_settings = { .dio1 = 10 }; +/* + * Configuration for SX1262 Waveshare module + */ +//const struct lorawan_sx12xx_settings sx12xx_settings = { +// .spi = { +// .inst = spi1, +// .mosi = 11, +// .miso = 12, +// .sck = 10, +// .nss = 3 +// }, +// .reset = 15, +// .busy = 2, +// .dio1 = 20 +//}; + // OTAA settings const struct lorawan_otaa_settings otaa_settings = { .device_eui = LORAWAN_DEVICE_EUI, @@ -61,7 +79,7 @@ int main( void ) // initialize the LoRaWAN stack printf("Initilizating LoRaWAN ... "); - if (lorawan_init_otaa(&sx1276_settings, LORAWAN_REGION, &otaa_settings) < 0) { + if (lorawan_init_otaa(&sx12xx_settings, LORAWAN_REGION, &otaa_settings) < 0) { printf("failed!!!\n"); while (1) { tight_loop_contents(); diff --git a/examples/otaa_temperature_led/main.c b/examples/otaa_temperature_led/main.c index f666fbf..6139455 100644 --- a/examples/otaa_temperature_led/main.c +++ b/examples/otaa_temperature_led/main.c @@ -22,8 +22,10 @@ // edit with LoRaWAN Node Region and OTAA settings #include "config.h" -// pin configuration for SX1276 radio module -const struct lorawan_sx1276_settings sx1276_settings = { +/* + * Pin configuration for SX1276 radio module (default) + */ +const struct lorawan_sx12xx_settings sx12xx_settings = { .spi = { .inst = PICO_DEFAULT_SPI_INSTANCE, .mosi = PICO_DEFAULT_SPI_TX_PIN, @@ -36,6 +38,22 @@ const struct lorawan_sx1276_settings sx1276_settings = { .dio1 = 10 }; +/* + * Configuration for SX1262 Waveshare module + */ +//const struct lorawan_sx12xx_settings sx12xx_settings = { +// .spi = { +// .inst = spi1, +// .mosi = 11, +// .miso = 12, +// .sck = 10, +// .nss = 3 +// }, +// .reset = 15, +// .busy = 2, +// .dio1 = 20 +//}; + // OTAA settings const struct lorawan_otaa_settings otaa_settings = { .device_eui = LORAWAN_DEVICE_EUI, @@ -74,7 +92,7 @@ int main( void ) // initialize the LoRaWAN stack printf("Initilizating LoRaWAN ... "); - if (lorawan_init_otaa(&sx1276_settings, LORAWAN_REGION, &otaa_settings) < 0) { + if (lorawan_init_otaa(&sx12xx_settings, LORAWAN_REGION, &otaa_settings) < 0) { printf("failed!!!\n"); while (1) { tight_loop_contents(); diff --git a/src/boards/rp2040/eeprom-board.c b/src/boards/rp2040/eeprom-board.c index 7241819..069a59b 100644 --- a/src/boards/rp2040/eeprom-board.c +++ b/src/boards/rp2040/eeprom-board.c @@ -26,7 +26,7 @@ void EepromMcuInit() uint8_t EepromMcuReadBuffer( uint16_t addr, uint8_t *buffer, uint16_t size ) { - memcpy(buffer, EEPROM_ADDRESS + addr, size); + memcpy(buffer, eeprom_write_cache + addr, size); return SUCCESS; } diff --git a/src/boards/rp2040/gpio-board.c b/src/boards/rp2040/gpio-board.c index 60c89ab..4af5c12 100644 --- a/src/boards/rp2040/gpio-board.c +++ b/src/boards/rp2040/gpio-board.c @@ -60,3 +60,13 @@ uint32_t GpioMcuRead( Gpio_t *obj ) { return gpio_get(obj->pin); } + +void GpioMcuSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ) +{ + gpio_set_irq_enabled_with_callback(obj->pin,GPIO_IRQ_EDGE_RISE,true,irqHandler); +} + +void GpioMcuRemoveInterrupt( Gpio_t *obj ) +{ + gpio_set_irq_enabled(obj->pin,GPIO_IRQ_EDGE_RISE,false); +} diff --git a/src/boards/rp2040/sx126x-board.c b/src/boards/rp2040/sx126x-board.c new file mode 100644 index 0000000..55322be --- /dev/null +++ b/src/boards/rp2040/sx126x-board.c @@ -0,0 +1,352 @@ +/*! + * \file sx1262mbxdas-board.c + * + * \brief Target board SX1262MBXDAS shield driver implementation + * + * \remark This target board is only available with the SX126xDVK1xAS + * development kit. + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include +#include "utilities.h" +#include "pico/board-config.h" +#include "board.h" +#include "delay.h" +#include "radio.h" +#include "sx126x-board.h" + +#if defined( USE_RADIO_DEBUG ) +/*! + * \brief Writes new Tx debug pin state + * + * \param [IN] state Debug pin state + */ +static void SX126xDbgPinTxWrite( uint8_t state ); + +/*! + * \brief Writes new Rx debug pin state + * + * \param [IN] state Debug pin state + */ +static void SX126xDbgPinRxWrite( uint8_t state ); +#endif + +/*! + * \brief Holds the internal operating mode of the radio + */ +static RadioOperatingModes_t OperatingMode; + +/*! + * Antenna switch GPIO pins objects + */ +// Gpio_t AntPow; +// Gpio_t DeviceSel; + +/*! + * Debug GPIO pins objects + */ +#if defined( USE_RADIO_DEBUG ) +Gpio_t DbgPinTx; +Gpio_t DbgPinRx; +#endif + +void SX126xIoInit( void ) +{ + GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + // GpioInit( &DeviceSel, RADIO_DEVICE_SEL, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +} + +void SX126xIoIrqInit( DioIrqHandler dioIrq ) +{ + GpioSetInterrupt( &SX126x.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dioIrq ); +} + +void SX126xIoDeInit( void ) +{ + GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +} + +void SX126xIoDbgInit( void ) +{ +#if defined( USE_RADIO_DEBUG ) + GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +#endif +} + +void SX126xIoTcxoInit( void ) +{ + CalibrationParams_t calibParam; + + SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, SX126xGetBoardTcxoWakeupTime( ) << 6 ); // convert from ms to SX126x time base + calibParam.Value = 0x7F; + SX126xCalibrate( calibParam ); +} + +uint32_t SX126xGetBoardTcxoWakeupTime( void ) +{ + return BOARD_TCXO_WAKEUP_TIME; +} + +void SX126xIoRfSwitchInit( void ) +{ + SX126xSetDio2AsRfSwitchCtrl( true ); +} + +RadioOperatingModes_t SX126xGetOperatingMode( void ) +{ + return OperatingMode; +} + +void SX126xSetOperatingMode( RadioOperatingModes_t mode ) +{ + OperatingMode = mode; +#if defined( USE_RADIO_DEBUG ) + switch( mode ) + { + case MODE_TX: + SX126xDbgPinTxWrite( 1 ); + SX126xDbgPinRxWrite( 0 ); + break; + case MODE_RX: + case MODE_RX_DC: + SX126xDbgPinTxWrite( 0 ); + SX126xDbgPinRxWrite( 1 ); + break; + default: + SX126xDbgPinTxWrite( 0 ); + SX126xDbgPinRxWrite( 0 ); + break; + } +#endif +} + +void SX126xReset( void ) +{ + DelayMs( 10 ); + GpioInit( &SX126x.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + DelayMs( 20 ); + GpioInit( &SX126x.Reset, RADIO_RESET, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); // internal pull-up + DelayMs( 10 ); +} + +void SX126xWaitOnBusy( void ) +{ + while( GpioRead( &SX126x.BUSY ) == 1 ); +} + +void SX126xWakeup( void ) +{ + CRITICAL_SECTION_BEGIN( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, RADIO_GET_STATUS ); + SpiInOut( &SX126x.Spi, 0x00 ); + + GpioWrite( &SX126x.Spi.Nss, 1 ); + + // Wait for chip to be ready. + SX126xWaitOnBusy( ); + + // Update operating mode context variable + SX126xSetOperatingMode( MODE_STDBY_RC ); + + CRITICAL_SECTION_END( ); +} + +void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) +{ + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, ( uint8_t )command ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( &SX126x.Spi, buffer[i] ); + } + + GpioWrite( &SX126x.Spi.Nss, 1 ); + + if( command != RADIO_SET_SLEEP ) + { + SX126xWaitOnBusy( ); + } +} + +uint8_t SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size ) +{ + uint8_t status = 0; + + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, ( uint8_t )command ); + status = SpiInOut( &SX126x.Spi, 0x00 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( &SX126x.Spi, 0 ); + } + + GpioWrite( &SX126x.Spi.Nss, 1 ); + + SX126xWaitOnBusy( ); + + return status; +} + +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, RADIO_WRITE_REGISTER ); + SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 ); + SpiInOut( &SX126x.Spi, address & 0x00FF ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( &SX126x.Spi, buffer[i] ); + } + + GpioWrite( &SX126x.Spi.Nss, 1 ); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegister( uint16_t address, uint8_t value ) +{ + SX126xWriteRegisters( address, &value, 1 ); +} + +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, RADIO_READ_REGISTER ); + SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 ); + SpiInOut( &SX126x.Spi, address & 0x00FF ); + SpiInOut( &SX126x.Spi, 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( &SX126x.Spi, 0 ); + } + GpioWrite( &SX126x.Spi.Nss, 1 ); + + SX126xWaitOnBusy( ); +} + +uint8_t SX126xReadRegister( uint16_t address ) +{ + uint8_t data; + SX126xReadRegisters( address, &data, 1 ); + return data; +} + +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, RADIO_WRITE_BUFFER ); + SpiInOut( &SX126x.Spi, offset ); + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( &SX126x.Spi, buffer[i] ); + } + GpioWrite( &SX126x.Spi.Nss, 1 ); + + SX126xWaitOnBusy( ); +} + +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + SX126xCheckDeviceReady( ); + + GpioWrite( &SX126x.Spi.Nss, 0 ); + + SpiInOut( &SX126x.Spi, RADIO_READ_BUFFER ); + SpiInOut( &SX126x.Spi, offset ); + SpiInOut( &SX126x.Spi, 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( &SX126x.Spi, 0 ); + } + GpioWrite( &SX126x.Spi.Nss, 1 ); + + SX126xWaitOnBusy( ); +} + +void SX126xSetRfTxPower( int8_t power ) +{ + SX126xSetTxParams( power, RADIO_RAMP_40_US ); +} + +uint8_t SX126xGetDeviceId( void ) +{ + // if( GpioRead( &DeviceSel ) == 1 ) + // { + // return SX1261; + // } + // else + // { + // return SX1262; + // } + + return SX1262; +} + +void SX126xAntSwOn( void ) +{ + // GpioInit( &AntPow, RADIO_ANT_SWITCH_POWER, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 ); +} + +void SX126xAntSwOff( void ) +{ + // GpioInit( &AntPow, RADIO_ANT_SWITCH_POWER, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +} + +bool SX126xCheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} + +#if defined( USE_RADIO_DEBUG ) +static void SX126xDbgPinTxWrite( uint8_t state ) +{ + GpioWrite( &DbgPinTx, state ); +} + +static void SX126xDbgPinRxWrite( uint8_t state ) +{ + GpioWrite( &DbgPinRx, state ); +} +#endif \ No newline at end of file diff --git a/src/include/pico/board-config.h b/src/include/pico/board-config.h new file mode 100644 index 0000000..7a1a5cc --- /dev/null +++ b/src/include/pico/board-config.h @@ -0,0 +1,65 @@ +/*! + * \file board-config.h + * + * \brief Board configuration + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * ___ _____ _ ___ _ _____ ___ ___ ___ ___ + * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| + * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| + * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| + * embedded.connectivity.solutions=============== + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + * + * \author Daniel Jaeckle ( STACKFORCE ) + * + * \author Johannes Bruder ( STACKFORCE ) + */ +#ifndef __BOARD_CONFIG_H__ +#define __BOARD_CONFIG_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + * Defines the time required for the TCXO to wakeup [ms]. + */ +#define BOARD_TCXO_WAKEUP_TIME 5 + +/*! + * Board MCU pins definitions + */ +#define RADIO_RESET 15 + +#define RADIO_MOSI 11 +#define RADIO_MISO 12 +#define RADIO_SCLK 10 + +#define RADIO_NSS 3 +#define RADIO_BUSY 2 +#define RADIO_DIO_1 20 + +// #define RADIO_ANT_SWITCH_POWER 22 + +#ifdef __cplusplus +} +#endif + +#endif // __BOARD_CONFIG_H__ \ No newline at end of file diff --git a/src/include/pico/lorawan.h b/src/include/pico/lorawan.h index a79e35d..e9ab19a 100644 --- a/src/include/pico/lorawan.h +++ b/src/include/pico/lorawan.h @@ -13,7 +13,7 @@ #include "LoRaMac.h" -struct lorawan_sx1276_settings { +struct lorawan_sx12xx_settings { struct { spi_inst_t* inst; uint mosi; @@ -22,6 +22,7 @@ struct lorawan_sx1276_settings { uint nss; } spi; uint reset; + uint busy; uint dio0; uint dio1; }; @@ -42,9 +43,9 @@ struct lorawan_otaa_settings { const char* lorawan_default_dev_eui(char* dev_eui); -int lorawan_init_abp(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings); +int lorawan_init_abp(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings); -int lorawan_init_otaa(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings); +int lorawan_init_otaa(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings); int lorawan_join(); diff --git a/src/lorawan.c b/src/lorawan.c index 8993374..03d6121 100644 --- a/src/lorawan.c +++ b/src/lorawan.c @@ -31,7 +31,13 @@ #include "board.h" #include "rtc-board.h" + +#if defined sx1276 #include "sx1276-board.h" +#elif defined sx126x +#include "sx126x-board.h" +#include "pico/board-config.h" +#endif #include "../../periodic-uplink-lpp/firmwareVersion.h" #include "Commissioning.h" @@ -197,24 +203,25 @@ const char* lorawan_default_dev_eui(char* dev_eui) return dev_eui; } -static int lorawan_init(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region) +static int lorawan_init(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region) { EepromMcuInit(); RtcInit(); +#if defined sx1276 SpiInit( &SX1276.Spi, - (SpiId_t)((sx1276_settings->spi.inst == spi0) ? 0 : 1), - sx1276_settings->spi.mosi /*MOSI*/, - sx1276_settings->spi.miso /*MISO*/, - sx1276_settings->spi.sck /*SCK*/, + (SpiId_t)((sx12xx_settings->spi.inst == spi0) ? 0 : 1), + sx12xx_settings->spi.mosi /*MOSI*/, + sx12xx_settings->spi.miso /*MISO*/, + sx12xx_settings->spi.sck /*SCK*/, NC ); - SX1276.Spi.Nss.pin = sx1276_settings->spi.nss; - SX1276.Reset.pin = sx1276_settings->reset; - SX1276.DIO0.pin = sx1276_settings->dio0; - SX1276.DIO1.pin = sx1276_settings->dio1; + SX1276.Spi.Nss.pin = sx12xx_settings->spi.nss; + SX1276.Reset.pin = sx12xx_settings->reset; + SX1276.DIO0.pin = sx12xx_settings->dio0; + SX1276.DIO1.pin = sx12xx_settings->dio1; SX1276IoInit(); @@ -223,6 +230,35 @@ static int lorawan_init(const struct lorawan_sx1276_settings* sx1276_settings, L return -1; } +#elif defined sx126x + Gpio_t gpio_busy; + Gpio_t gpio_dio1; + Gpio_t gpio_reset; + Gpio_t gpio_nss; + + Spi_t spi1_t; + + gpio_busy.pin = RADIO_BUSY; + gpio_dio1.pin = RADIO_DIO_1; + gpio_reset.pin = RADIO_RESET; + gpio_nss.pin = RADIO_NSS; + spi1_t.Nss = gpio_nss; +// raspberry pi pico spi1 + spi1_t.SpiId = SPI_2; + + SX126x.BUSY = gpio_busy; + SX126x.DIO1 = gpio_dio1; + SX126x.Reset = gpio_reset; + SX126x.Spi = spi1_t; + SpiInit( &SX126x.Spi, SPI_2, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC ); + + SX126x.Spi.Nss.pin = sx12xx_settings->spi.nss; + SX126x.Reset.pin = sx12xx_settings->reset; + SX126x.DIO1.pin = sx12xx_settings->dio1; + + SX126xIoInit(); +#endif + LmHandlerParams.Region = region; if ( LmHandlerInit( &LmHandlerCallbacks, &LmHandlerParams ) != LORAMAC_HANDLER_SUCCESS ) @@ -240,20 +276,20 @@ static int lorawan_init(const struct lorawan_sx1276_settings* sx1276_settings, L return 0; } -int lorawan_init_abp(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings) +int lorawan_init_abp(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_abp_settings* abp_settings) { AbpSettings = abp_settings; OtaaSettings = NULL; - return lorawan_init(sx1276_settings, region); + return lorawan_init(sx12xx_settings, region); } -int lorawan_init_otaa(const struct lorawan_sx1276_settings* sx1276_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings) +int lorawan_init_otaa(const struct lorawan_sx12xx_settings* sx12xx_settings, LoRaMacRegion_t region, const struct lorawan_otaa_settings* otaa_settings) { AbpSettings = NULL; OtaaSettings = otaa_settings; - return lorawan_init(sx1276_settings, region); + return lorawan_init(sx12xx_settings, region); } int lorawan_join() @@ -406,9 +442,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 4; i++) { int b; - sscanf(device_address + i * 2, "%2hhx", &b); - params->DevAddr = (params->DevAddr << 8) | b; } } else { @@ -428,9 +462,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 8; i++) { int b; - sscanf(device_eui + i * 2, "%2x", &b); - deviceEui[i] = b; } @@ -445,9 +477,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 8; i++) { int b; - sscanf(app_eui + i * 2, "%2x", &b); - joinEui[i] = b; } @@ -462,9 +492,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 16; i++) { int b; - sscanf(app_key + i * 2, "%2x", &b); - appKey[i] = b; } @@ -482,9 +510,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 16; i++) { int b; - sscanf(app_session_key + i * 2, "%2x", &b); - appSessionKey[i] = b; } @@ -498,9 +524,7 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 16; i++) { int b; - sscanf(network_session_key + i * 2, "%2x", &b); - networkSessionKey[i] = b; } @@ -522,10 +546,8 @@ static void OnNetworkParametersChange( CommissioningParams_t* params ) for (int i = 0; i < 6; i++) { int b[2]; - sscanf(channel_mask + i * 4 + 0, "%2x", &b[0]); sscanf(channel_mask + i * 4 + 2, "%2x", &b[1]); - channelMask[i] = (b[0] << 8) | b[1]; }