From 2f008797f0b0caf348472ab33e1f799d07f1e9bb Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Mon, 31 Dec 2018 12:56:02 -0700 Subject: [PATCH] add support for packet rx --- components/sx127x_driver/sx127x_driver.c | 105 ++++++++++++++++--- components/sx127x_driver/sx127x_driver.h | 16 +++ components/sx127x_driver/sx127x_internal.h | 9 +- components/sx127x_driver/sx127x_registers.c | 36 +++++++ components/sx127x_driver/sx127x_registers.h | 5 +- main/ugv_main.c | 106 +++++++------------- 6 files changed, 191 insertions(+), 86 deletions(-) diff --git a/components/sx127x_driver/sx127x_driver.c b/components/sx127x_driver/sx127x_driver.c index b299ea8..5dd1cb6 100644 --- a/components/sx127x_driver/sx127x_driver.c +++ b/components/sx127x_driver/sx127x_driver.c @@ -145,8 +145,7 @@ esp_err_t sx127x_free(sx127x_t *handle) { } void IRAM_ATTR sx127x_isr(void *arg) { - sx127x_t *handle = (sx127x_t *)arg; - ESP_LOGI(SX127X_TAG, "sx127x_isr"); + sx127x_t * handle = (sx127x_t *)arg; BaseType_t hpTaskWoken; xSemaphoreGiveFromISR(handle->intr_semaphore, &hpTaskWoken); if (hpTaskWoken) { @@ -160,7 +159,7 @@ void IRAM_ATTR sx127x_isr(void *arg) { goto error; \ } -void sx127x_do_tx(sx127x_t *handle, sx127x_packet_t *packet) { +static void sx127x_do_tx(sx127x_t *handle, sx127x_packet_t *packet) { esp_err_t ret; uint8_t op_mode, irq_flags, config_2; while (handle->task_state == SX127X_TASK_RUNNING) { @@ -218,24 +217,88 @@ error: SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); } +static void sx127x_do_rx(sx127x_t *handle) { + uint8_t irq_flags, packet_len; + sx127x_rx_packet_t packet; + esp_err_t ret; + BaseType_t pdRet; + + _TX_CHECK(sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags)); + // clear irq flags + _TX_CHECK(sx127x_write_register(handle, REG_IRQ_FLAGS, irq_flags)); + + if (irq_flags & IRQ_PAYLOAD_CRC_ERROR_MASK) { + ESP_LOGW(SX127X_TAG, "rx crc error"); + goto error; + } + if ((irq_flags & IRQ_RX_DONE_MASK) == 0) { + ESP_LOGD(SX127X_TAG, "sx127x_do_rx called but no rx done"); + goto error; + } + + sx127x_write_register(handle, REG_OP_MODE, + SX127X_LONG_RANGE | SX127X_MODE_STDBY); + + // TODO: implicit header receive? + _TX_CHECK(sx127x_read_register(handle, REG_RX_NB_BYTES, &packet_len)); + _TX_CHECK(sx127x_write_register(handle, REG_FIFO_ADDR_PTR, + REG_FIFO_RX_CURRENT_ADDR)); + + packet.data_len = packet_len; + packet.data = heap_caps_malloc( + packet.data_len, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_DMA); + if (!packet.data) { + ESP_LOGE(SX127X_TAG, "malloc error"); + goto error; + } + _TX_CHECK(sx127x_read_fifo(handle, packet.data, packet.data_len)); + + sx127x_read_pkt_rssi(handle, &packet.rssi); + sx127x_read_pkt_snr(handle, &packet.snr); + + pdRet = xQueueSend(handle->rx_packet_queue, &packet, 0); + if (pdRet != pdTRUE) { + ESP_LOGE(SX127X_TAG, "rx queue full"); + free(packet.data); + goto error; + } + +error: + if (ret != ESP_OK) { + const char *error_name = esp_err_to_name(ret); + ESP_LOGE(SX127X_TAG, "rx error: %s (%d)", error_name, ret); + } + sx127x_write_register(handle, REG_FIFO_ADDR_PTR, 0); + // go back to rx mode + sx127x_write_register(handle, REG_OP_MODE, + SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); +} + void sx127x_task(void *arg) { sx127x_t * handle = (sx127x_t *)arg; - TickType_t delay_time = 0; + TickType_t delay_time = portMAX_DELAY; QueueSetHandle_t qSet = xQueueCreateSet(8); xQueueAddToSet(handle->intr_semaphore, qSet); xQueueAddToSet(handle->tx_packet_queue, qSet); sx127x_packet_t packet; + + // be in rx mode by default + sx127x_write_register(handle, REG_OP_MODE, + SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); + while (handle->task_state == SX127X_TASK_RUNNING) { QueueSetMemberHandle_t queue = xQueueSelectFromSet(qSet, delay_time); if (queue == handle->intr_semaphore) { BaseType_t didRecv = xSemaphoreTake(handle->intr_semaphore, 0); if (didRecv) { - ESP_LOGI(SX127X_TAG, "recv from isr: %d", didRecv); + ESP_LOGV(SX127X_TAG, "recv from isr"); + + sx127x_do_rx(handle); } } else if (queue == handle->tx_packet_queue) { BaseType_t didRecv = xQueueReceive(handle->tx_packet_queue, &packet, 0); if (didRecv) { - ESP_LOGI(SX127X_TAG, "tx packet: %.*s", packet.data_len, packet.data); + ESP_LOGV(SX127X_TAG, "tx packet: %.*s", packet.data_len, packet.data); sx127x_do_tx(handle, &packet); @@ -254,9 +317,10 @@ esp_err_t sx127x_start(sx127x_t *handle) { SX127X_CHECK(handle->task_handle == NULL, "task already running", ESP_ERR_INVALID_STATE); - handle->intr_semaphore = xSemaphoreCreateBinary(); - // handle->recv_packet_queue = xQueueCreate(8, 10); - handle->tx_packet_queue = xQueueCreate(8, sizeof(sx127x_packet_t)); + handle->intr_semaphore = xSemaphoreCreateBinary(); + handle->tx_packet_queue = xQueueCreate(TX_QUEUE_LEN, sizeof(sx127x_packet_t)); + handle->rx_packet_queue = + xQueueCreate(RX_QUEUE_LEN, sizeof(sx127x_rx_packet_t)); handle->task_state = SX127X_TASK_RUNNING; BaseType_t pdRet = @@ -308,12 +372,13 @@ esp_err_t sx127x_stop(sx127x_t *handle) { esp_err_t sx127x_send_packet(sx127x_t *handle, const char *data, size_t data_len, TickType_t ticks_to_wait) { SX127X_CHECK(handle->task_state == SX127X_TASK_RUNNING, "task not running", - ESP_FAIL); + ESP_ERR_INVALID_STATE); SX127X_CHECK(data_len < SX127_MAX_PACKET_LEN, "packet len too long: %d", - ESP_FAIL, data_len); + ESP_ERR_INVALID_ARG, data_len); sx127x_packet_t packet; packet.data_len = data_len; - packet.data = heap_caps_malloc(data_len, MALLOC_CAP_DMA); + packet.data = heap_caps_malloc( + data_len, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT | MALLOC_CAP_DMA); SX127X_CHECK(packet.data != NULL, "malloc error", ESP_ERR_NO_MEM); memcpy(packet.data, data, data_len); BaseType_t pdRet = @@ -321,3 +386,19 @@ esp_err_t sx127x_send_packet(sx127x_t *handle, const char *data, SX127X_CHECK(pdRet == pdTRUE, "tx queue full", ESP_ERR_TIMEOUT); return ESP_OK; } + +esp_err_t sx127x_recv_packet(sx127x_t *handle, sx127x_rx_packet_t *packet, + TickType_t ticks_to_wait) { + SX127X_CHECK(packet != NULL, "packet must not be NULL", ESP_ERR_INVALID_ARG); + BaseType_t pdRet = + xQueueReceive(handle->rx_packet_queue, packet, ticks_to_wait); + if (pdRet != pdTRUE) { + ESP_LOGV(SX127X_TAG, "timeout on recv_packet"); + return ESP_ERR_TIMEOUT; + } + return ESP_OK; +} + +QueueHandle_t sx127x_get_recv_queue(sx127x_t *handle) { return handle->rx_packet_queue; } + +void sx127x_packet_rx_free(sx127x_rx_packet_t *packet) { free(packet->data); } \ No newline at end of file diff --git a/components/sx127x_driver/sx127x_driver.h b/components/sx127x_driver/sx127x_driver.h index 02a52c3..1658044 100644 --- a/components/sx127x_driver/sx127x_driver.h +++ b/components/sx127x_driver/sx127x_driver.h @@ -70,6 +70,15 @@ typedef struct sx127x_config { } // clang-format on +typedef struct sx127x_packet_rx { + char * data; + size_t data_len; + // rssi value + int32_t rssi; + // snr value in steps of .25 + int8_t snr; +} sx127x_rx_packet_t; + typedef struct sx127x sx127x_t; sx127x_config_t sx127x_config_default(); @@ -84,3 +93,10 @@ esp_err_t sx127x_stop(sx127x_t *handle); esp_err_t sx127x_send_packet(sx127x_t *handle, const char *data, size_t data_len, TickType_t ticks_to_wait); + +esp_err_t sx127x_recv_packet(sx127x_t *handle, sx127x_rx_packet_t *packet_out, + TickType_t ticks_to_wait); + +QueueHandle_t sx127x_get_recv_queue(sx127x_t *handle); + +void sx127x_packet_rx_free(sx127x_rx_packet_t *packet); diff --git a/components/sx127x_driver/sx127x_internal.h b/components/sx127x_driver/sx127x_internal.h index 4e37c1b..c46cd5a 100644 --- a/components/sx127x_driver/sx127x_internal.h +++ b/components/sx127x_driver/sx127x_internal.h @@ -4,12 +4,17 @@ #include #include +// TODO: these should be in Kconfig +#define TASK_STACK_SIZE (2 * 1024) +#define TASK_PRIORITY 3 +#define RX_QUEUE_LEN 8 +#define TX_QUEUE_LEN 8 + #define SX127X_MAX_TRANSFER (256) #define RESET_DELAY (pdMS_TO_TICKS(15)) + // 8mhz #define SPI_CLOCK_HZ (8 * 1000 * 1000) -#define TASK_STACK_SIZE (2 * 1024) -#define TASK_PRIORITY 3 #define REG_FIFO 0x00 #define REG_OP_MODE 0x01 diff --git a/components/sx127x_driver/sx127x_registers.c b/components/sx127x_driver/sx127x_registers.c index ce2d057..cebbfe3 100644 --- a/components/sx127x_driver/sx127x_registers.c +++ b/components/sx127x_driver/sx127x_registers.c @@ -204,6 +204,26 @@ esp_err_t sx127x_set_crc(sx127x_t *handle, sx127x_crc_t crc) { return ESP_OK; } +esp_err_t sx127x_read_pkt_rssi(sx127x_t *handle, int32_t *rssi) { + SX127X_CHECK(rssi != NULL, "rssi can not be NULL", ESP_ERR_INVALID_ARG); + uint8_t rssi_val; + uint64_t freq = handle->config.frequency; + int32_t min_rssi = (freq < 868E6) ? -164 : -157; + SX127X_ERROR_CHECK( + sx127x_read_register(handle, REG_PKT_RSSI_VALUE, &rssi_val)) + *rssi = min_rssi + rssi_val; + return ESP_OK; +} + +esp_err_t sx127x_read_pkt_snr(sx127x_t *handle, int8_t *snr) { + SX127X_CHECK(snr != NULL, "rssi can not be NULL", ESP_ERR_INVALID_ARG); + int8_t snr_val; + SX127X_ERROR_CHECK( + sx127x_read_register(handle, REG_PKT_SNR_VALUE, (uint8_t *)&snr_val)) + *snr = snr_val; + return ESP_OK; +} + esp_err_t sx127x_write_fifo(sx127x_t *handle, const char *data, size_t data_len) { spi_transaction_t trans; @@ -220,3 +240,19 @@ esp_err_t sx127x_write_fifo(sx127x_t *handle, const char *data, ESP_LOGV(SX127X_TAG, "sx127x_write_fifo(%.*s)", data_len, data); return ESP_OK; } + +esp_err_t sx127x_read_fifo(sx127x_t *handle, char *data_out, size_t data_len) { + spi_transaction_t trans; + memset(&trans, 0, sizeof(trans)); + trans.flags = 0; + trans.addr = REG_FIFO; + trans.length = 8 * data_len; + trans.tx_buffer = NULL; + trans.rxlength = 0; // match length + trans.rx_buffer = data_out; + + esp_err_t ret = spi_device_transmit(handle->device_handle, &trans); + SX127X_ERROR_CHECK2(ret, spi_device_transmit); + ESP_LOGV(SX127X_TAG, "sx127x_read_fifo(%.*s)", data_len, data_out); + return ESP_OK; +} \ No newline at end of file diff --git a/components/sx127x_driver/sx127x_registers.h b/components/sx127x_driver/sx127x_registers.h index 996879b..68d8849 100644 --- a/components/sx127x_driver/sx127x_registers.h +++ b/components/sx127x_driver/sx127x_registers.h @@ -26,6 +26,9 @@ esp_err_t sx127x_set_sync_word(sx127x_t *handle, uint8_t sync_word); esp_err_t sx127x_set_crc(sx127x_t *handle, sx127x_crc_t crc); +esp_err_t sx127x_read_pkt_rssi(sx127x_t *handle, int32_t *rssi); +esp_err_t sx127x_read_pkt_snr(sx127x_t *handle, int8_t *snr); + esp_err_t sx127x_write_fifo(sx127x_t *handle, const char *data, size_t data_len); esp_err_t sx127x_read_fifo(sx127x_t *handle, char *data_out, - size_t *data_len_out); + size_t data_len); diff --git a/main/ugv_main.c b/main/ugv_main.c index ad57d12..94b5390 100644 --- a/main/ugv_main.c +++ b/main/ugv_main.c @@ -29,13 +29,6 @@ u8g2_t u8g2; #define OLED_H 64 #define OLED_W 128 -struct Packet { - int rssi; - double snr; - size_t buffer_len; - char buffer[LORA_BUF_LEN]; -}; - uint16_t packet_num; sx127x_t *lora; @@ -44,12 +37,8 @@ void loraOnReceive(int packetSize); void loraTask(void *params); TaskHandle_t lora_task_hndl; -// packets recieved (type Packet) -QueueHandle_t lora_packet_recv_queue; -// packet lengths from the recieve isr (type int) -QueueHandle_t lora_packet_isr_queue; -struct Packet packet; +sx127x_rx_packet_t rx_packet; void setup_oled(void) { u8g2_esp32_hal_t u8g2_hal_config = { @@ -71,11 +60,6 @@ void setup(void) { setup_oled(); - lora_packet_recv_queue = xQueueCreate(4, sizeof(struct Packet)); - lora_packet_isr_queue = xQueueCreate(4, sizeof(int)); - configASSERT(lora_packet_recv_queue != 0); - configASSERT(lora_packet_isr_queue != 0); - sx127x_config_t lora_config = SX127X_CONFIG_DEFAULT; lora_config.tx_power = 17; lora_config.spreading_factor = 11; @@ -94,74 +78,52 @@ void setup(void) { ESP_LOGI(TAG, "LoRa start failed: %d", ret); } } - // LoRa.onReceive(loraOnReceive); - // LoRa.receive(0); + memset(&rx_packet, 0, sizeof(rx_packet)); packet_num = 0; xTaskCreate(loraTask, "loraTask", 1024 * 10, NULL, 2, &lora_task_hndl); - memset(&packet, 0, sizeof(struct Packet)); } #define XO 10 -void loraOnReceive(int packetSize) { - if (packetSize == 0) return; - ESP_LOGV(TAG, "loraOnReceive"); - xQueueSendFromISR(lora_packet_isr_queue, &packetSize, NULL); -} - void loraTask(void *params) { - char tx_buf[20]; - const size_t tx_buf_len = (sizeof(tx_buf) / sizeof(tx_buf[0])); - int packet_len; - TickType_t send_period = pdMS_TO_TICKS(1000); - TickType_t current_time = xTaskGetTickCount(); - TickType_t next_send = current_time + send_period; - struct Packet recvd_packet; + char tx_buf[20]; + const size_t tx_buf_len = (sizeof(tx_buf) / sizeof(tx_buf[0])); + TickType_t send_period = pdMS_TO_TICKS(1000); + TickType_t current_time = xTaskGetTickCount(); + TickType_t next_send = current_time + send_period; while (true) { TickType_t delay_ticks = next_send - current_time; - BaseType_t didReceive = - xQueueReceive(lora_packet_isr_queue, &packet_len, delay_ticks); - if (didReceive) { - int packetSize = - (packet_len > LORA_BUF_LEN - 1) ? (LORA_BUF_LEN - 1) : (packet_len); - // LoRa.setTimeout(50); - // LoRa.readBytes(recvd_packet.buffer, packetSize); - recvd_packet.buffer_len = packetSize; - recvd_packet.buffer[packetSize - 1] = '\0'; - // recvd_packet.rssi = LoRa.packetRssi(); - // recvd_packet.snr = LoRa.packetSnr(); - - xQueueSend(lora_packet_recv_queue, &recvd_packet, 10); - } + vTaskDelay(delay_ticks); current_time = xTaskGetTickCount(); - if (current_time >= next_send) { - int written_bytes = - snprintf(tx_buf, tx_buf_len, "hello world %d", packet_num); - if (written_bytes < 0) { - ESP_LOGE(TAG, "snprintf error: %d", written_bytes); - continue; - } - packet_num++; - esp_err_t ret = sx127x_send_packet(lora, tx_buf, written_bytes, - 0); // 0 means error if queue full - if (ret != ESP_OK) { - ESP_LOGE(TAG, "error sending packet: %d", ret); - } else { - ESP_LOGI(TAG, "lora wrote %d bytes", written_bytes); - } - - current_time = xTaskGetTickCount(); - next_send = current_time + send_period; + if (current_time < next_send) { + continue; } + int written_bytes = + snprintf(tx_buf, tx_buf_len, "hello world %d", packet_num); + if (written_bytes < 0) { + ESP_LOGE(TAG, "snprintf error: %d", written_bytes); + continue; + } + packet_num++; + esp_err_t ret = sx127x_send_packet(lora, tx_buf, written_bytes, + 0); // 0 means error if queue full + if (ret != ESP_OK) { + ESP_LOGE(TAG, "error sending packet: %d", ret); + } else { + ESP_LOGI(TAG, "lora wrote %d bytes", written_bytes); + } + + current_time = xTaskGetTickCount(); + next_send = current_time + send_period; } } void loop(void) { ESP_LOGI(TAG, "loop"); u8g2_FirstPage(&u8g2); - xQueueReceive(lora_packet_recv_queue, &packet, 10); + sx127x_recv_packet(lora, &rx_packet, 0); do { u8g2_DrawRFrame(&u8g2, 0, 0, OLED_W, OLED_H, 4); @@ -175,13 +137,15 @@ void loop(void) { heap_info.total_free_bytes); u8g2_DrawStr(&u8g2, 4, 8 + 8, buf); - if (packet.buffer_len) { - ESP_LOGI(TAG, "lora received packet (len %d, rssi: %d, snr: %f): %s\n", - packet.buffer_len, packet.rssi, packet.snr, packet.buffer); + if (rx_packet.data_len) { + ESP_LOGI(TAG, "lora received packet (len %d, rssi: %d, snr: %f): %.*s\n", + rx_packet.data_len, rx_packet.rssi, rx_packet.snr * 0.25f, + rx_packet.data_len, rx_packet.data); u8g2_SetFont(&u8g2, u8g2_font_4x6_mf); - snprintf(buf, 40, "lora pkt(rssi: %d, snr: %f)", packet.rssi, packet.snr); + snprintf(buf, 40, "lora pkt(rssi: %d, snr: %f)", rx_packet.rssi, + rx_packet.snr * 0.25f); u8g2_DrawStr(&u8g2, 4, 8 + 8 + 8, buf); - snprintf(buf, 40, "%s", packet.buffer); + snprintf(buf, 40, "%.*s", rx_packet.data_len, rx_packet.data); u8g2_DrawStr(&u8g2, 4, 8 + 8 + 8 + 8, buf); } } while (u8g2_NextPage(&u8g2));