From c6c656aa0d3bd30956a2da147b5bb1a9636ed903 Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Thu, 30 Sep 2021 13:28:58 +0300 Subject: [PATCH] LoRa Send and Receive works --- CMakeLists.txt | 2 +- include/sx1276.h | 18 ++-- openocd.cfg => openocd/ftdi.cfg | 3 - openocd/stlink.cfg | 21 +++++ src/main.c | 141 +++++++++++++++++++++++++------- src/sx1276.c | 10 ++- 6 files changed, 156 insertions(+), 39 deletions(-) rename openocd.cfg => openocd/ftdi.cfg (99%) create mode 100644 openocd/stlink.cfg diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c32e80..a2b927a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.19) -project(dht_test LANGUAGES C) +project(lora LANGUAGES C) set(LIBOPENCM3_DIR ${CMAKE_SOURCE_DIR}/libopencm3) set(CMAKE_C_STANDARD 99) diff --git a/include/sx1276.h b/include/sx1276.h index 3811a56..5b40b68 100644 --- a/include/sx1276.h +++ b/include/sx1276.h @@ -23,7 +23,7 @@ enum sx1276_reg { SX1276_REG_FIFO_RX_CURRENT_ADDR = 0x10, // Start address of last packet received SX1276_REG_IRQ_FLAGS = 0x12, // IRQ flags SX1276_REG_RX_NB_BYTES = 0x13, // Number of received bytes - SX1276_REG_MODEM_STATUS = 0x18, // Live LoRa modem status + SX1276_REG_MODEM_STATUS = 0x18, // Live LoRa modem status SX1276_REG_PKT_SNR_VALUE = 0x19, // Espimation of last packet SNR SX1276_REG_PKT_RSSI_VALUE = 0x1a, // RSSI of last packet SX1276_REG_MODEM_CONFIG_1 = 0x1d, // Modem PHY config 1 @@ -31,6 +31,7 @@ enum sx1276_reg { SX1276_REG_PREAMBLE_MSB = 0x20, // Size of preamble SX1276_REG_PREAMBLE_LSB = 0x21, // Size of preamble SX1276_REG_PAYLOAD_LENGTH = 0x22, // LoRa payload length + SX1276_REG_FIFO_RX_BYTE_PTR = 0x25, // Current value of RX databuffer pointer (written by Lora receiver) SX1276_REG_MODEM_CONFIG_3 = 0x26, // Modem PHY config 3 SX1276_REG_RSSI_WIDEBAND = 0x2c, // Wideband RSSI measurement SX1276_REG_DETECTION_OPTIMIZE = 0x31, // LoRa detection Optimize for SF6 @@ -60,10 +61,17 @@ enum sx1276_mode { // SX1276_REG_OP_MODE values // PA config #define PA_BOOST 1<<7 -// IRQ masks -#define IRQ_TX_DONE_MASK 0x08 -#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20 -#define IRQ_RX_DONE_MASK 0x40 +// LORA IRQ masks +enum sx1276_lora_irq { + SX1267_LORA_IRQ_RX_TIMEOUT = 1<<7, + SX1267_LORA_IRQ_RX_DONE = 1<<6, + SX1267_LORA_IRQ_PAYLOAD_CRC_ERR = 1<<5, + SX1267_LORA_IRQ_VALID_HEADER = 1<<4, + SX1267_LORA_IRQ_TX_DONE = 1<<3, + SX1267_LORA_IRQ_CAD_DONE = 1<<2, + SX1267_LORA_IRQ_FHSS_CHANGE_CH = 1<<1, + SX1267_LORA_IRQ_CAD_DETECTED = 1<<0, +}; // FSK IRQ FLAGS #define IRQ_FLAGS1_MODE_READY 1<<7 // Set when the operation mode requested in Mode, is ready diff --git a/openocd.cfg b/openocd/ftdi.cfg similarity index 99% rename from openocd.cfg rename to openocd/ftdi.cfg index 98c3032..c47f180 100644 --- a/openocd.cfg +++ b/openocd/ftdi.cfg @@ -1,5 +1,4 @@ # FT2232H Board V3 connected to Maple Mini - adapter driver ftdi transport select swd ftdi_vid_pid 0x0403 0x6010 @@ -19,14 +18,12 @@ ftdi_layout_signal nTRST -ndata 0x0010 -noe 0x0040 ftdi_layout_signal nSRST -ndata 0x0020 -noe 0x0040 source [find target/stm32f1x.cfg] - reset_config srst_only # Search for RTT string from start of RAM rtt setup 0x20000000 8192 "SEGGER RTT" rtt server start 9090 0 - # $_TARGETNAME configure -event resume-end { # #rtt start # } diff --git a/openocd/stlink.cfg b/openocd/stlink.cfg new file mode 100644 index 0000000..00761b9 --- /dev/null +++ b/openocd/stlink.cfg @@ -0,0 +1,21 @@ +# ST-Link v2 clone connected to Maple Mini board +source [find interface/stlink.cfg] +source [find target/stm32f1x.cfg] + +#reset_config srst_only + +# Search for RTT string from start of RAM +rtt setup 0x20000000 8192 "SEGGER RTT" +rtt server start 9090 0 + +# $_TARGETNAME configure -event resume-end { +# #rtt start +# } + +$_TARGETNAME configure -event gdb-start { + rtt start +} + +$_TARGETNAME configure -event halted { + rtt stop +} diff --git a/src/main.c b/src/main.c index 3c697ef..e1f770f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -69,6 +71,111 @@ static void spi_setup(void) spi_enable(SPI1); } +static void print_status(void) { + int dio = gpio_get(GPIOA, GPIO2 | GPIO3); + SEGGER_RTT_printf(0, "DIO5: %d DIO0: %d ", (dio&GPIO3)?1:0, (dio&GPIO2)?1:0); + int ret = sx1276_read(SX1276_REG_OP_MODE); + SEGGER_RTT_printf(0, "MOD: 0x%02x ", ret); + ret = sx1276_read(SX1276_REG_MODEM_STATUS); + SEGGER_RTT_printf(0, "STAT: 0x%02x ", ret); + ret = sx1276_read(SX1276_REG_IRQ_FLAGS); + SEGGER_RTT_printf(0, "IRQ: 0x%02x ", ret); + ret = sx1276_read(SX1276_REG_FIFO_RX_CURRENT_ADDR); + SEGGER_RTT_printf(0, "FIFO_RX_START: 0x%02x ", ret); + ret = sx1276_read(SX1276_REG_FIFO_RX_BYTE_PTR); + SEGGER_RTT_printf(0, "FIFO_RX_END: 0x%02x\n", ret); +} + + +static uint8_t handle_irq_flags() { + uint8_t irq_flags = sx1276_read(SX1276_REG_IRQ_FLAGS); + + if (irq_flags & SX1267_LORA_IRQ_RX_TIMEOUT) { + sx1276_write(SX1276_REG_IRQ_FLAGS, SX1267_LORA_IRQ_RX_TIMEOUT); + SEGGER_RTT_printf(0,"RX_TIMEOUT\n"); + } + if (irq_flags & SX1267_LORA_IRQ_RX_DONE) { + sx1276_write(SX1276_REG_IRQ_FLAGS, SX1267_LORA_IRQ_RX_DONE); + SEGGER_RTT_printf(0, "RX_DONE\n"); + } + if (irq_flags & SX1267_LORA_IRQ_PAYLOAD_CRC_ERR) { + sx1276_write(SX1276_REG_IRQ_FLAGS, SX1267_LORA_IRQ_PAYLOAD_CRC_ERR); + SEGGER_RTT_printf(0, "RX_CRC_ERR\n"); + } + if (irq_flags & SX1267_LORA_IRQ_VALID_HEADER) { + sx1276_write(SX1276_REG_IRQ_FLAGS, SX1267_LORA_IRQ_VALID_HEADER); + SEGGER_RTT_printf(0, "RX_VALID_HEADER\n"); + } + if (irq_flags & SX1267_LORA_IRQ_TX_DONE) { + sx1276_write(SX1276_REG_IRQ_FLAGS, SX1267_LORA_IRQ_TX_DONE); + SEGGER_RTT_printf(0, "TX_DONE\n"); + } + return irq_flags; +} + +static void send(struct sx1276_state_st *state) { + + gpio_set(GPIOB, GPIO1); + + + char msg[] = "Hello World\n"; + uint32_t msg_len = strlen(msg) + 1; + memcpy(state->fifo, msg, msg_len); + sx1276_fifo_load(state); + sx1276_fifo_dump(state); + hexdump((char *)state->fifo, msg_len, 8); + + sx1276_write(SX1276_REG_PAYLOAD_LENGTH, 0x4); + + sx1276_write(SX1276_REG_DIO_MAPPING_1, 0b01000000); // configure DIO0 as TX done flag + + print_status(); + sx1276_write(SX1276_REG_OP_MODE, SX1276_MODE_LONG_RANGE_MODE | SX1276_MODE_TX); + + for (int i = 0; i < 100; ++i) { + print_status(); + if (handle_irq_flags() & SX1267_LORA_IRQ_TX_DONE) { // tx done flag check + break; + } + delay_ms(1); + } + + print_status(); + sx1276_write(SX1276_REG_DIO_MAPPING_1, 0b00000000); // configure DIO0 as RX done flag + SEGGER_RTT_printf(0, "Done\n"); + + gpio_clear(GPIOB, GPIO1); + +} + + +static void receive(struct sx1276_state_st *state) { + gpio_set(GPIOB, GPIO1); + + print_status(); + sx1276_write(SX1276_REG_OP_MODE, SX1276_MODE_LONG_RANGE_MODE | SX1276_MODE_RX_CONTINUOUS); + for (int i = 0; i < 100; ++i) { + print_status(); + if (handle_irq_flags() & ( + SX1267_LORA_IRQ_RX_TIMEOUT | + SX1267_LORA_IRQ_RX_DONE | + SX1267_LORA_IRQ_PAYLOAD_CRC_ERR + )) + { + sx1276_fifo_dump(state); + hexdump((char *)state->fifo, 16, 16); + } + delay_ms(100); + } + + SEGGER_RTT_printf(0, "Done\n"); + + sx1276_write(SX1276_REG_OP_MODE, SX1276_MODE_LONG_RANGE_MODE | SX1276_MODE_STDBY); + + + gpio_clear(GPIOB, GPIO1); +} + int main(void) { clock_setup(); @@ -78,38 +185,16 @@ int main(void) SEGGER_RTT_WriteString(0, "SX1276 LoRa test\n"); SEGGER_RTT_printf(0, "CPU clk: %dHz\n", rcc_ahb_frequency); - struct sx1276_state_st *sx1276_state = sx1276_init(86520000); + struct sx1276_state_st *sx1276_state = sx1276_init(865200000); - sx1276_fifo_write(0x0, 0xde); - sx1276_fifo_write(0x1, 0xad); - sx1276_fifo_write(0x2, 0xbe); - sx1276_fifo_write(0x3, 0xef); - - sx1276_write(SX1276_REG_PAYLOAD_LENGTH, 4); - - sx1276_write(SX1276_REG_OP_MODE, SX1276_MODE_LONG_RANGE_MODE | SX1276_MODE_TX); + send(sx1276_state); while (1) { - int ret = sx1276_read(SX1276_REG_OP_MODE); - SEGGER_RTT_printf(0, "MOD: 0x%02x ", ret); - ret = sx1276_read(SX1276_REG_MODEM_STATUS); - SEGGER_RTT_printf(0, "STAT: 0x%02x ", ret); - ret = sx1276_read(SX1276_REG_IRQ_FLAGS); - SEGGER_RTT_printf(0, "IRQ: 0x%02x\n", ret); - if (ret & (1<<3)){ - break; + char r = SEGGER_RTT_WaitKey(); + if (r == '\n') { + receive(sx1276_state); } - delay_ms(100); - } - SEGGER_RTT_printf(0, "Done\n"); - - - /* Blink the LED (PA5) on the board. */ - while (1) { - - /* Using API function gpio_toggle(): */ - gpio_toggle(GPIOB, GPIO1); /* LED on/off */ - delay_ms(500); + delay_ms(50); } return 0; diff --git a/src/sx1276.c b/src/sx1276.c index 7cf289b..2a7bdfc 100644 --- a/src/sx1276.c +++ b/src/sx1276.c @@ -96,6 +96,14 @@ struct sx1276_state_st *sx1276_init(uint64_t frequency) { sx1276_write(SX1276_REG_FIFO_TX_BASE_ADDR, 0); sx1276_write(SX1276_REG_FIFO_RX_BASE_ADDR, 0); +// ret = sx1276_read(SX1276_REG_LNA); +// set = ret | 0x03; +// sx1276_write(SX1276_REG_LNA, set); +// SEGGER_RTT_printf(0, "LNA from: 0x%02x, to: 0x%02x\n", ret, set); + +// sx1276_write(SX1276_REG_MODEM_CONFIG_3, 0x04); // LNA gain set by the internal AGC loop + //sx1276_write(SX1276_REG_PA_CONFIG, 1<<7 | 15); // select PA_BOOST pin as output + sx1276_write(SX1276_REG_LNA, 0b11000000); // minimum strenght sx1276_write(SX1276_REG_PA_CONFIG, 1<<7); // minimum 2dBm @@ -104,13 +112,11 @@ struct sx1276_state_st *sx1276_init(uint64_t frequency) { // SpreadingFactor 7 128 chips sx1276_write(SX1276_REG_MODEM_CONFIG_2, (7 << 4)); - set = SX1276_MODE_LONG_RANGE_MODE | SX1276_MODE_STDBY; ret = sx1276_write(SX1276_REG_OP_MODE, set); SEGGER_RTT_printf(0, "Going to LoRa STDBY from: 0x%02X, to: 0x%02x\n", ret, set); - // We need to wait ~250us for TS_OSC to startup before we can access FIFO and some other things delay_us(250); return sx1276_state;