From 589a819e4f995e443088b2b904f9458145bc8b31 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Sun, 30 Dec 2018 02:47:47 -0700 Subject: [PATCH] add support for packet tx --- components/sx127x_driver/sx127x_driver.c | 142 +++++++++++++++++--- components/sx127x_driver/sx127x_driver.h | 8 +- components/sx127x_driver/sx127x_internal.h | 46 +++++-- components/sx127x_driver/sx127x_registers.c | 19 ++- components/sx127x_driver/sx127x_registers.h | 10 +- main/ugv_main.c | 22 +-- 6 files changed, 199 insertions(+), 48 deletions(-) diff --git a/components/sx127x_driver/sx127x_driver.c b/components/sx127x_driver/sx127x_driver.c index 258712b..57890b7 100644 --- a/components/sx127x_driver/sx127x_driver.c +++ b/components/sx127x_driver/sx127x_driver.c @@ -7,12 +7,18 @@ const char *SX127X_TAG = "sx127x"; +typedef struct sx127x_packet { + char * data; + size_t data_len; +} sx127x_packet_t; + esp_err_t sx127x_init(sx127x_config_t *config, sx127x_t **handle_ptr) { esp_err_t ret; sx127x_t *handle = malloc(sizeof(sx127x_t)); SX127X_CHECK(handle != NULL, "malloc error", ESP_ERR_NO_MEM); handle->task_handle = NULL; + handle->task_state = SX127X_TASK_STOPPED; memcpy(&handle->config, config, sizeof(sx127x_config_t)); ret = gpio_set_direction(config->rst_io_num, GPIO_MODE_OUTPUT); @@ -24,13 +30,16 @@ esp_err_t sx127x_init(sx127x_config_t *config, sx127x_t **handle_ptr) { gpio_set_level(config->rst_io_num, 1); vTaskDelay(RESET_DELAY); - spi_bus_config_t bus_config = {.mosi_io_num = config->mosi_io_num, - .miso_io_num = config->miso_io_num, - .sclk_io_num = config->sck_io_num, - .quadhd_io_num = -1, - .quadwp_io_num = -1, - .max_transfer_sz = SX127X_MAX_TRANSFER}; - ret = spi_bus_initialize(config->spi_host, &bus_config, 1); + spi_bus_config_t bus_config = { + .mosi_io_num = config->mosi_io_num, + .miso_io_num = config->miso_io_num, + .sclk_io_num = config->sck_io_num, + .quadhd_io_num = -1, + .quadwp_io_num = -1, + .max_transfer_sz = SX127X_MAX_TRANSFER, + }; + + ret = spi_bus_initialize(config->spi_host, &bus_config, 1); SX127X_ERROR_CHECK2(ret, spi_bus_initialize) spi_device_interface_config_t device_config = { @@ -120,14 +129,90 @@ esp_err_t sx127x_free(sx127x_t *handle) { void sx127x_isr(void *arg) { sx127x_t *handle = (sx127x_t *)arg; - ESP_LOGI(SX127X_TAG, "sx127x_isr"); + ESP_LOGV(SX127X_TAG, "sx127x_isr"); + BaseType_t hpTaskWoken; + xSemaphoreGiveFromISR(handle->intr_semaphore, &hpTaskWoken); + if (hpTaskWoken) { + portYIELD_FROM_ISR(); + } +} + +void sx127x_do_tx(sx127x_t *handle, sx127x_packet_t *packet) { + uint8_t op_mode, irq_flags, config_2; + while (handle->task_state == SX127X_TASK_RUNNING) { + sx127x_read_register(handle, REG_OP_MODE, &op_mode); + uint8_t mode = op_mode & SX127X_MODE; + if (mode != SX127X_MODE_TX && mode != SX127X_MODE_FS_TX) { + break; + } + vTaskDelay(1); // wait for finish transmitting + } + + sx127x_standby(handle); + + sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags); + if (irq_flags & IRQ_TX_DONE_MASK) { + // clear tx done bit + sx127x_write_register(handle, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + } + + sx127x_read_register(handle, REG_MODEM_CONFIG_2, &config_2); + config_2 &= ~0x01; // set explicit header mode TODO: implicit header? + sx127x_write_register(handle, REG_MODEM_CONFIG_2, config_2); + + sx127x_write_register(handle, REG_FIFO_ADDR_PTR, 0); + sx127x_write_register(handle, REG_PAYLOAD_LENGTH, 0); + + sx127x_write_fifo(handle, packet->data, packet->data_len); + sx127x_write_register(handle, REG_PAYLOAD_LENGTH, packet->data_len); + + sx127x_write_register(handle, REG_OP_MODE, SX127X_LONG_RANGE | SX127X_MODE_FS_TX); + vTaskDelay(pdMS_TO_TICKS(1)); + sx127x_write_register(handle, REG_OP_MODE, SX127X_LONG_RANGE | SX127X_MODE_TX); + + // wait for transmission to finish + while (true) { + sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags); + if (irq_flags & IRQ_TX_DONE_MASK) { // if the transmission is done + break; + } + vTaskDelay(1); + } + // clear tx done bit + sx127x_write_register(handle, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK); + + // 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; - while (handle->task_running) { - vTaskDelay(pdMS_TO_TICKS(10)); + sx127x_t * handle = (sx127x_t *)arg; + TickType_t delay_time = 0; + QueueSetHandle_t qSet = xQueueCreateSet(8); + xQueueAddToSet(handle->intr_semaphore, qSet); + xQueueAddToSet(handle->tx_packet_queue, qSet); + sx127x_packet_t packet; + 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); + } + } 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); + + sx127x_do_tx(handle, &packet); + + free(packet.data); + } + } } + ESP_LOGI(SX127X_TAG, "sx127x_task exiting"); + handle->task_state = SX127X_TASK_STOPPED; + vTaskDelete(NULL); // must delete own task } esp_err_t sx127x_start(sx127x_t *handle) { @@ -135,6 +220,15 @@ 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(4, sizeof(sx127x_packet_t)); + + handle->task_state = SX127X_TASK_RUNNING; + BaseType_t pdRet = + xTaskCreate(sx127x_task, "sx127x_task", TASK_STACK_SIZE, (void *)handle, TASK_PRIORITY, &handle->task_handle); + SX127X_CHECK(pdRet == pdPASS, "failed to create task", ESP_FAIL); + ret = sx127x_write_register(handle, REG_DIO_MAPPING_1, 0x00); SX127X_ERROR_CHECK(ret); @@ -152,11 +246,6 @@ esp_err_t sx127x_start(sx127x_t *handle) { ret = gpio_isr_handler_add(handle->config.irq_io_num, sx127x_isr, (void *)handle); SX127X_ERROR_CHECK2(ret, gpio_isr_handler_add); - handle->task_running = true; - - BaseType_t pdRet = - xTaskCreate(sx127x_task, "sx127x_task", TASK_STACK_SIZE, (void *)handle, TASK_PRIORITY, &handle->task_handle); - SX127X_CHECK(pdRet == pdPASS, "failed to create task", ESP_FAIL); return ESP_OK; } @@ -164,12 +253,29 @@ esp_err_t sx127x_stop(sx127x_t *handle) { esp_err_t ret; SX127X_CHECK(handle->task_handle != NULL, "task has not been started", ESP_ERR_INVALID_STATE); - handle->task_running = false; - xTaskNotify(handle->task_handle, 0, eNoAction); + handle->task_state = SX127X_TASK_STOPPING; + xTaskNotifyGive(handle->task_handle); ret = gpio_isr_handler_remove(handle->config.irq_io_num); SX127X_ERROR_CHECK2(ret, gpio_isr_handler_remove); gpio_uninstall_isr_service(); + while (handle->task_state != SX127X_TASK_STOPPED) { + vTaskDelay(10); + } + handle->task_handle = NULL; + + return ESP_OK; +} + +esp_err_t sx127x_send_packet(sx127x_t *handle, char *data, size_t data_len) { + SX127X_CHECK(data_len < SX127_MAX_PACKET_LEN, "packet len too long: %d", ESP_FAIL, data_len); + sx127x_packet_t packet; + packet.data_len = data_len; + packet.data = heap_caps_malloc(data_len, MALLOC_CAP_DMA); + SX127X_CHECK(packet.data != NULL, "malloc error", ESP_ERR_NO_MEM); + memcpy(packet.data, data, data_len); + BaseType_t pdRet = xQueueSend(handle->tx_packet_queue, &packet, 0); + SX127X_CHECK(pdRet == pdTRUE, "tx queue full", ESP_FAIL); return ESP_OK; } diff --git a/components/sx127x_driver/sx127x_driver.h b/components/sx127x_driver/sx127x_driver.h index f9fbc0b..9a4cff5 100644 --- a/components/sx127x_driver/sx127x_driver.h +++ b/components/sx127x_driver/sx127x_driver.h @@ -4,7 +4,7 @@ #include #include -#define SX127X_MAX_TRANSFER (256) +#define SX127_MAX_PACKET_LEN 255 // carrier frequency type typedef uint64_t sx127x_freq_t; @@ -76,10 +76,8 @@ esp_err_t sx127x_init(sx127x_config_t *config, sx127x_t **handle_ptr); esp_err_t sx127x_free(sx127x_t *handle); -esp_err_t sx127x_sleep(sx127x_t *handle); - -esp_err_t sx127x_standby(sx127x_t *handle); - esp_err_t sx127x_start(sx127x_t *handle); esp_err_t sx127x_stop(sx127x_t *handle); + +esp_err_t sx127x_send_packet(sx127x_t *handle, char *data, size_t data_len); diff --git a/components/sx127x_driver/sx127x_internal.h b/components/sx127x_driver/sx127x_internal.h index 853c18d..fc2b6ee 100644 --- a/components/sx127x_driver/sx127x_internal.h +++ b/components/sx127x_driver/sx127x_internal.h @@ -1,7 +1,10 @@ #include +#include +#include +#include #include -#define MAX_PKT_LENGTH 255 +#define SX127X_MAX_TRANSFER (256) #define RESET_DELAY (pdMS_TO_TICKS(15)) // 8mhz #define SPI_CLOCK_HZ (8 * 1000 * 1000) @@ -43,13 +46,18 @@ #define REG_VERSION 0x42 #define REG_PA_DAC 0x4d -// modes -#define MODE_LONG_RANGE_MODE 0x80 -#define MODE_SLEEP 0x00 -#define MODE_STDBY 0x01 -#define MODE_TX 0x03 -#define MODE_RX_CONTINUOUS 0x05 -#define MODE_RX_SINGLE 0x06 +typedef enum sx127x_op_mode { + SX127X_MODE_SLEEP = 0x00, + SX127X_MODE_STDBY = 0x01, + SX127X_MODE_FS_TX = 0x02, + SX127X_MODE_TX = 0x03, + SX127X_MODE_FS_RX = 0x04, + SX127X_MODE_RX_CONT = 0x05, + SX127X_MODE_RX_SINGLE = 0x06, + SX127X_MODE_CAD = 0x07, + SX127X_MODE = 0x07, + SX127X_LONG_RANGE = (1 << 7) +} sx127x_op_mode_t; #define CONFIG2_CRC 0x04 #define CONFIG3_AUTO_AGC 0x04 @@ -65,7 +73,7 @@ #ifdef NODEBUG #define SX127X_CHECK(check, str, ret_val, ...) \ if (!(check)) { \ - ESP_LOGE(SX127X_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ESP_LOGE(SX127X_TAG, str, ##__VA_ARGS__); \ return (ret_val); \ } #define SX127X_ERROR_CHECK(ret) \ @@ -79,7 +87,7 @@ #else #define SX127X_CHECK(check, str, ret_val, ...) \ if (!(check)) { \ - ESP_LOGE(SX127X_TAG, "%s(%d): " #check ": " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ESP_LOGE(SX127X_TAG, "%s:%d: " #check ": " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ return (ret_val); \ } #define SX127X_ERROR_CHECK(ret) \ @@ -87,7 +95,7 @@ esp_err_t _error_code = (ret); \ if (_error_code != ESP_OK) { \ const char *_error_name = esp_err_to_name(_error_code); \ - ESP_LOGE(SX127X_TAG, "%s(%d): %s (%d)", __FUNCTION__, __LINE__, _error_name, _error_code); \ + ESP_LOGE(SX127X_TAG, "%s:%d: %s (%d)", __FUNCTION__, __LINE__, _error_name, _error_code); \ return _error_code; \ } \ } @@ -96,17 +104,29 @@ esp_err_t _error_code = (ret); \ if (_error_code != ESP_OK) { \ const char *_error_name = esp_err_to_name(_error_code); \ - ESP_LOGE(SX127X_TAG, "%s(%d): " #fun ": %s (%d)", __FUNCTION__, __LINE__, _error_name, _error_code); \ + ESP_LOGE(SX127X_TAG, "%s:%d: " #fun ": %s (%d)", __FUNCTION__, __LINE__, _error_name, _error_code); \ return _error_code; \ } \ } #endif +typedef enum sx127x_task_state { + SX127X_TASK_STOPPED = 0, + SX127X_TASK_RUNNING = 1, + SX127X_TASK_STOPPING = 2, +} sx127x_task_state_t; + struct sx127x { sx127x_config_t config; spi_device_handle_t device_handle; TaskHandle_t task_handle; - bool task_running; + sx127x_task_state_t task_state; + // binary semaphore which is given when an interrupt is received from the radio + SemaphoreHandle_t intr_semaphore; + // queue of packets received from the radio + QueueHandle_t rx_packet_queue; + // queue of packets to send to the radio + QueueHandle_t tx_packet_queue; }; const char *SX127X_TAG; diff --git a/components/sx127x_driver/sx127x_registers.c b/components/sx127x_driver/sx127x_registers.c index 04813ef..794101a 100644 --- a/components/sx127x_driver/sx127x_registers.c +++ b/components/sx127x_driver/sx127x_registers.c @@ -30,11 +30,11 @@ esp_err_t sx127x_single_transfer(sx127x_t *handle, uint8_t addr, uint8_t to_slav } esp_err_t sx127x_sleep(sx127x_t *handle) { - return sx127x_write_register(handle, REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP); + return sx127x_write_register(handle, REG_OP_MODE, SX127X_LONG_RANGE | SX127X_MODE_SLEEP); } esp_err_t sx127x_standby(sx127x_t *handle) { - return sx127x_write_register(handle, REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY); + return sx127x_write_register(handle, REG_OP_MODE, SX127X_LONG_RANGE | SX127X_MODE_STDBY); } esp_err_t sx127x_set_frequency(sx127x_t *handle, uint64_t frequency) { @@ -182,3 +182,18 @@ esp_err_t sx127x_set_crc(sx127x_t *handle, sx127x_crc_t crc) { handle->config.crc = crc; return ESP_OK; } + +esp_err_t sx127x_write_fifo(sx127x_t *handle, char *data, size_t data_len) { + spi_transaction_t trans; + memset(&trans, 0, sizeof(trans)); + trans.flags = SPI_TRANS_USE_RXDATA; + trans.addr = REG_FIFO; + trans.length = 8 * data_len; + trans.rxlength = 0; + trans.tx_buffer = data; + + esp_err_t ret = spi_device_transmit(handle->device_handle, &trans); + SX127X_ERROR_CHECK2(ret, spi_device_transmit); + ESP_LOGV(SX127X_TAG, "sx127x_write_fifo(%.*s)", data_len, data); + return ESP_OK; +} diff --git a/components/sx127x_driver/sx127x_registers.h b/components/sx127x_driver/sx127x_registers.h index 5c604b4..57e1239 100644 --- a/components/sx127x_driver/sx127x_registers.h +++ b/components/sx127x_driver/sx127x_registers.h @@ -4,8 +4,9 @@ esp_err_t sx127x_read_register(sx127x_t *handle, uint8_t reg, uint8_t *value); esp_err_t sx127x_write_register(sx127x_t *handle, uint8_t reg, uint8_t value); esp_err_t sx127x_single_transfer(sx127x_t *handle, uint8_t addr, uint8_t to_slave, uint8_t *from_slave); -uint8_t sx127x_bw_to_reg(uint64_t bandwidth); -uint64_t sx127x_reg_to_bw(uint8_t bandwidth_reg); +esp_err_t sx127x_sleep(sx127x_t *handle); + +esp_err_t sx127x_standby(sx127x_t *handle); esp_err_t sx127x_set_frequency(sx127x_t *handle, uint64_t frequency); @@ -14,7 +15,12 @@ esp_err_t sx127x_set_tx_power(sx127x_t *handle, uint8_t tx_power, sx127x_pa_boos esp_err_t sx127x_set_spreading_factor(sx127x_t *handle, uint8_t spreading_factor); esp_err_t sx127x_set_signal_bandwidth(sx127x_t *handle, uint64_t signal_bandwidth); +uint8_t sx127x_bw_to_reg(uint64_t bandwidth); +uint64_t sx127x_reg_to_bw(uint8_t bandwidth_reg); 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_write_fifo(sx127x_t *handle, char *data, size_t data_len); +esp_err_t sx127x_read_fifo(sx127x_t *handle, char *data_out, size_t *data_len_out); diff --git a/main/ugv_main.c b/main/ugv_main.c index 77458d8..030424e 100644 --- a/main/ugv_main.c +++ b/main/ugv_main.c @@ -38,8 +38,10 @@ struct Packet { uint16_t packet_num; -void loraTask(void *params); +sx127x_t *lora; + void loraOnReceive(int packetSize); +void loraTask(void *params); TaskHandle_t lora_task_hndl; // packets recieved (type Packet) @@ -96,7 +98,6 @@ void setup(void) { lora_config.sync_word = 0x34; lora_config.crc = SX127X_CRC_ENABLED; - sx127x_t *lora; esp_err_t ret = sx127x_init(&lora_config, &lora); if (ret != ESP_OK) { const char *err_name = esp_err_to_name(ret); @@ -149,13 +150,18 @@ void loraTask(void *params) { } current_time = xTaskGetTickCount(); if (current_time >= next_send) { - sprintf(outBuf, "hello world %d", packet_num); + int len = sprintf(outBuf, "hello world %d", packet_num); + if (len < 0) { + ESP_LOGE(TAG, "sprintf error: %d", len); + continue; + } packet_num++; - // LoRa.beginPacket(); - // size_t written = LoRa.write((uint8_t *)outBuf, outBufLen - 1); - // LoRa.endPacket(); - // ESP_LOGI(TAG, "lora wrote %d bytes\n", written); - // LoRa.receive(0); // go back to receive mode + esp_err_t ret = sx127x_send_packet(lora, outBuf, len); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "error sending packet: %d", ret); + } else { + ESP_LOGI(TAG, "lora wrote %d bytes\n", len); + } current_time = xTaskGetTickCount(); next_send = current_time + send_period;