|
|
@ -17,45 +17,45 @@ sx127x_config_t sx127x_config_default() { |
|
|
|
return config; |
|
|
|
return config; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static esp_err_t sx127x_write_config(sx127x_t *handle) { |
|
|
|
static esp_err_t sx127x_write_config(sx127x_t *hndl) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
const sx127x_config_t *config = &handle->config; |
|
|
|
const sx127x_config_t *config = &hndl->config; |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_sleep(handle); |
|
|
|
ret = sx127x_sleep(hndl); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_set_frequency(handle, config->frequency); |
|
|
|
ret = sx127x_set_frequency(hndl, config->frequency); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_write_register(handle, REG_FIFO_TX_BASE_ADDR, 0); |
|
|
|
ret = sx127x_write_register(hndl, REG_FIFO_TX_BASE_ADDR, 0); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
sx127x_write_register(handle, REG_FIFO_RX_BASE_ADDR, 0); |
|
|
|
sx127x_write_register(hndl, REG_FIFO_RX_BASE_ADDR, 0); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
uint8_t reg_lna; |
|
|
|
uint8_t reg_lna; |
|
|
|
ret = sx127x_read_register(handle, REG_LNA, ®_lna); |
|
|
|
ret = sx127x_read_register(hndl, REG_LNA, ®_lna); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
reg_lna |= 0x03; // set LNA boost
|
|
|
|
reg_lna |= 0x03; // set LNA boost
|
|
|
|
ret = sx127x_write_register(handle, REG_LNA, reg_lna); |
|
|
|
ret = sx127x_write_register(hndl, REG_LNA, reg_lna); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
// set auto AGC
|
|
|
|
// set auto AGC
|
|
|
|
ret = sx127x_write_register(handle, REG_MODEM_CONFIG_3, CONFIG3_AUTO_AGC); |
|
|
|
ret = sx127x_write_register(hndl, REG_MODEM_CONFIG_3, CONFIG3_AUTO_AGC); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_set_tx_power(handle, config->tx_power, true); |
|
|
|
ret = sx127x_set_tx_power(hndl, config->tx_power, true); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_set_spreading_factor(handle, config->spreading_factor); |
|
|
|
ret = sx127x_set_spreading_factor(hndl, config->spreading_factor); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_set_sync_word(handle, config->sync_word); |
|
|
|
ret = sx127x_set_sync_word(hndl, config->sync_word); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_set_crc(handle, config->crc); |
|
|
|
ret = sx127x_set_crc(hndl, config->crc); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_standby(handle); |
|
|
|
ret = sx127x_standby(hndl); |
|
|
|
ESP_ERROR_CHECK(ret); |
|
|
|
ESP_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
@ -63,12 +63,12 @@ static esp_err_t sx127x_write_config(sx127x_t *handle) { |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_init(const sx127x_config_t *config, sx127x_t **handle_ptr) { |
|
|
|
esp_err_t sx127x_init(const sx127x_config_t *config, sx127x_t **handle_ptr) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
sx127x_t *handle = malloc(sizeof(sx127x_t)); |
|
|
|
sx127x_t *hndl = malloc(sizeof(sx127x_t)); |
|
|
|
SX127X_CHECK(handle != NULL, "malloc error", ESP_ERR_NO_MEM); |
|
|
|
SX127X_CHECK(hndl != NULL, "malloc error", ESP_ERR_NO_MEM); |
|
|
|
|
|
|
|
|
|
|
|
handle->task_handle = NULL; |
|
|
|
hndl->task_handle = NULL; |
|
|
|
handle->task_state = SX127X_TASK_STOPPED; |
|
|
|
hndl->task_state = SX127X_TASK_STOPPED; |
|
|
|
memcpy(&handle->config, config, sizeof(sx127x_config_t)); |
|
|
|
memcpy(&hndl->config, config, sizeof(sx127x_config_t)); |
|
|
|
|
|
|
|
|
|
|
|
ret = gpio_set_direction(config->rst_io_num, GPIO_MODE_OUTPUT); |
|
|
|
ret = gpio_set_direction(config->rst_io_num, GPIO_MODE_OUTPUT); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_set_direction) |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_set_direction) |
|
|
@ -108,46 +108,46 @@ esp_err_t sx127x_init(const sx127x_config_t *config, sx127x_t **handle_ptr) { |
|
|
|
.post_cb = NULL, |
|
|
|
.post_cb = NULL, |
|
|
|
}; |
|
|
|
}; |
|
|
|
ret = spi_bus_add_device(config->spi_host, &device_config, |
|
|
|
ret = spi_bus_add_device(config->spi_host, &device_config, |
|
|
|
&handle->device_handle); |
|
|
|
&hndl->device_handle); |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_add_device) |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_add_device) |
|
|
|
|
|
|
|
|
|
|
|
// read version and check that it is compatible
|
|
|
|
// read version and check that it is compatible
|
|
|
|
uint8_t version; |
|
|
|
uint8_t version; |
|
|
|
ret = sx127x_read_register(handle, REG_VERSION, &version); |
|
|
|
ret = sx127x_read_register(hndl, REG_VERSION, &version); |
|
|
|
SX127X_ERROR_CHECK2(ret, sx127x_read_register); |
|
|
|
SX127X_ERROR_CHECK2(ret, sx127x_read_register); |
|
|
|
SX127X_CHECK(version == 0x12, "unsupported version %#x", |
|
|
|
SX127X_CHECK(version == 0x12, "unsupported version %#x", |
|
|
|
ESP_ERR_INVALID_VERSION, version); |
|
|
|
ESP_ERR_INVALID_VERSION, version); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_write_config(handle); |
|
|
|
ret = sx127x_write_config(hndl); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
*handle_ptr = handle; |
|
|
|
*handle_ptr = hndl; |
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_free(sx127x_t *handle) { |
|
|
|
esp_err_t sx127x_free(sx127x_t *hndl) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
|
|
|
|
|
|
|
|
if (handle->task_handle) { |
|
|
|
if (hndl->task_handle) { |
|
|
|
ret = sx127x_stop(handle); |
|
|
|
ret = sx127x_stop(hndl); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ret = spi_bus_remove_device(handle->device_handle); |
|
|
|
ret = spi_bus_remove_device(hndl->device_handle); |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_remove_device) |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_remove_device) |
|
|
|
|
|
|
|
|
|
|
|
ret = spi_bus_free(handle->config.spi_host); |
|
|
|
ret = spi_bus_free(hndl->config.spi_host); |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_free) |
|
|
|
SX127X_ERROR_CHECK2(ret, spi_bus_free) |
|
|
|
|
|
|
|
|
|
|
|
free(handle); |
|
|
|
free(hndl); |
|
|
|
|
|
|
|
|
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void IRAM_ATTR sx127x_isr(void *arg) { |
|
|
|
void IRAM_ATTR sx127x_isr(void *arg) { |
|
|
|
sx127x_t * handle = (sx127x_t *)arg; |
|
|
|
sx127x_t * hndl = (sx127x_t *)arg; |
|
|
|
BaseType_t hpTaskWoken; |
|
|
|
BaseType_t hpTaskWoken; |
|
|
|
xSemaphoreGiveFromISR(handle->intr_semaphore, &hpTaskWoken); |
|
|
|
xSemaphoreGiveFromISR(hndl->intr_semaphore, &hpTaskWoken); |
|
|
|
if (hpTaskWoken) { |
|
|
|
if (hpTaskWoken) { |
|
|
|
portYIELD_FROM_ISR(); |
|
|
|
portYIELD_FROM_ISR(); |
|
|
|
} |
|
|
|
} |
|
|
@ -159,11 +159,11 @@ void IRAM_ATTR sx127x_isr(void *arg) { |
|
|
|
goto error; \ |
|
|
|
goto error; \ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void sx127x_do_tx(sx127x_t *handle, sx127x_packet_t *packet) { |
|
|
|
static void sx127x_do_tx(sx127x_t *hndl, sx127x_packet_t *packet) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
uint8_t op_mode, irq_flags, config_2; |
|
|
|
uint8_t op_mode, irq_flags, config_2; |
|
|
|
while (handle->task_state == SX127X_TASK_RUNNING) { |
|
|
|
while (hndl->task_state == SX127X_TASK_RUNNING) { |
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_OP_MODE, &op_mode)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_OP_MODE, &op_mode)); |
|
|
|
uint8_t mode = op_mode & SX127X_MODE; |
|
|
|
uint8_t mode = op_mode & SX127X_MODE; |
|
|
|
if (mode != SX127X_MODE_TX && mode != SX127X_MODE_FS_TX) { |
|
|
|
if (mode != SX127X_MODE_TX && mode != SX127X_MODE_FS_TX) { |
|
|
|
break; |
|
|
|
break; |
|
|
@ -171,41 +171,41 @@ static void sx127x_do_tx(sx127x_t *handle, sx127x_packet_t *packet) { |
|
|
|
vTaskDelay(1); // wait for finish transmitting
|
|
|
|
vTaskDelay(1); // wait for finish transmitting
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_standby(handle)); |
|
|
|
_TX_CHECK(sx127x_standby(hndl)); |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
if (irq_flags & IRQ_TX_DONE_MASK) { |
|
|
|
if (irq_flags & IRQ_TX_DONE_MASK) { |
|
|
|
// clear tx done bit
|
|
|
|
// clear tx done bit
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_MODEM_CONFIG_2, &config_2)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_MODEM_CONFIG_2, &config_2)); |
|
|
|
config_2 &= ~0x01; // set explicit header mode TODO: implicit header?
|
|
|
|
config_2 &= ~0x01; // set explicit header mode TODO: implicit header?
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_MODEM_CONFIG_2, config_2)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_MODEM_CONFIG_2, config_2)); |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_FIFO_ADDR_PTR, 0)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_FIFO_ADDR_PTR, 0)); |
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_PAYLOAD_LENGTH, 0)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_PAYLOAD_LENGTH, 0)); |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_write_fifo(handle, packet->data, packet->data_len)); |
|
|
|
_TX_CHECK(sx127x_write_fifo(hndl, packet->data, packet->data_len)); |
|
|
|
_TX_CHECK( |
|
|
|
_TX_CHECK( |
|
|
|
sx127x_write_register(handle, REG_PAYLOAD_LENGTH, packet->data_len)); |
|
|
|
sx127x_write_register(hndl, REG_PAYLOAD_LENGTH, packet->data_len)); |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_FS_TX)); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_FS_TX)); |
|
|
|
vTaskDelay(pdMS_TO_TICKS(1)); |
|
|
|
vTaskDelay(pdMS_TO_TICKS(1)); |
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_TX)); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_TX)); |
|
|
|
|
|
|
|
|
|
|
|
// wait for transmission to finish
|
|
|
|
// wait for transmission to finish
|
|
|
|
while (true) { |
|
|
|
while (true) { |
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
if (irq_flags & IRQ_TX_DONE_MASK) { // if the transmission is done
|
|
|
|
if (irq_flags & IRQ_TX_DONE_MASK) { // if the transmission is done
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
vTaskDelay(1); |
|
|
|
vTaskDelay(1); |
|
|
|
} |
|
|
|
} |
|
|
|
// clear tx done bit
|
|
|
|
// clear tx done bit
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_IRQ_FLAGS, IRQ_TX_DONE_MASK)); |
|
|
|
|
|
|
|
|
|
|
|
error: |
|
|
|
error: |
|
|
|
if (ret != ESP_OK) { |
|
|
|
if (ret != ESP_OK) { |
|
|
@ -213,19 +213,19 @@ error: |
|
|
|
ESP_LOGE(SX127X_TAG, "tx error: %s (%d)", error_name, ret); |
|
|
|
ESP_LOGE(SX127X_TAG, "tx error: %s (%d)", error_name, ret); |
|
|
|
} |
|
|
|
} |
|
|
|
// go back to rx mode
|
|
|
|
// go back to rx mode
|
|
|
|
sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void sx127x_do_rx(sx127x_t *handle) { |
|
|
|
static void sx127x_do_rx(sx127x_t *hndl) { |
|
|
|
uint8_t irq_flags, packet_len; |
|
|
|
uint8_t irq_flags, packet_len; |
|
|
|
sx127x_rx_packet_t packet; |
|
|
|
sx127x_rx_packet_t packet; |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
BaseType_t pdRet; |
|
|
|
BaseType_t pdRet; |
|
|
|
|
|
|
|
|
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_IRQ_FLAGS, &irq_flags)); |
|
|
|
// clear irq flags
|
|
|
|
// clear irq flags
|
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_IRQ_FLAGS, irq_flags)); |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_IRQ_FLAGS, irq_flags)); |
|
|
|
|
|
|
|
|
|
|
|
if (irq_flags & IRQ_PAYLOAD_CRC_ERROR_MASK) { |
|
|
|
if (irq_flags & IRQ_PAYLOAD_CRC_ERROR_MASK) { |
|
|
|
ESP_LOGW(SX127X_TAG, "rx crc error"); |
|
|
|
ESP_LOGW(SX127X_TAG, "rx crc error"); |
|
|
@ -236,12 +236,12 @@ static void sx127x_do_rx(sx127x_t *handle) { |
|
|
|
goto error; |
|
|
|
goto error; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_STDBY); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_STDBY); |
|
|
|
|
|
|
|
|
|
|
|
// TODO: implicit header receive?
|
|
|
|
// TODO: implicit header receive?
|
|
|
|
_TX_CHECK(sx127x_read_register(handle, REG_RX_NB_BYTES, &packet_len)); |
|
|
|
_TX_CHECK(sx127x_read_register(hndl, REG_RX_NB_BYTES, &packet_len)); |
|
|
|
_TX_CHECK(sx127x_write_register(handle, REG_FIFO_ADDR_PTR, |
|
|
|
_TX_CHECK(sx127x_write_register(hndl, REG_FIFO_ADDR_PTR, |
|
|
|
REG_FIFO_RX_CURRENT_ADDR)); |
|
|
|
REG_FIFO_RX_CURRENT_ADDR)); |
|
|
|
|
|
|
|
|
|
|
|
packet.data_len = packet_len; |
|
|
|
packet.data_len = packet_len; |
|
|
@ -251,12 +251,12 @@ static void sx127x_do_rx(sx127x_t *handle) { |
|
|
|
ESP_LOGE(SX127X_TAG, "malloc error"); |
|
|
|
ESP_LOGE(SX127X_TAG, "malloc error"); |
|
|
|
goto error; |
|
|
|
goto error; |
|
|
|
} |
|
|
|
} |
|
|
|
_TX_CHECK(sx127x_read_fifo(handle, packet.data, packet.data_len)); |
|
|
|
_TX_CHECK(sx127x_read_fifo(hndl, packet.data, packet.data_len)); |
|
|
|
|
|
|
|
|
|
|
|
sx127x_read_pkt_rssi(handle, &packet.rssi); |
|
|
|
sx127x_read_pkt_rssi(hndl, &packet.rssi); |
|
|
|
sx127x_read_pkt_snr(handle, &packet.snr); |
|
|
|
sx127x_read_pkt_snr(hndl, &packet.snr); |
|
|
|
|
|
|
|
|
|
|
|
pdRet = xQueueSend(handle->rx_packet_queue, &packet, 0); |
|
|
|
pdRet = xQueueSend(hndl->rx_packet_queue, &packet, 0); |
|
|
|
if (pdRet != pdTRUE) { |
|
|
|
if (pdRet != pdTRUE) { |
|
|
|
ESP_LOGE(SX127X_TAG, "rx queue full"); |
|
|
|
ESP_LOGE(SX127X_TAG, "rx queue full"); |
|
|
|
free(packet.data); |
|
|
|
free(packet.data); |
|
|
@ -268,73 +268,73 @@ error: |
|
|
|
const char *error_name = esp_err_to_name(ret); |
|
|
|
const char *error_name = esp_err_to_name(ret); |
|
|
|
ESP_LOGE(SX127X_TAG, "rx error: %s (%d)", error_name, ret); |
|
|
|
ESP_LOGE(SX127X_TAG, "rx error: %s (%d)", error_name, ret); |
|
|
|
} |
|
|
|
} |
|
|
|
sx127x_write_register(handle, REG_FIFO_ADDR_PTR, 0); |
|
|
|
sx127x_write_register(hndl, REG_FIFO_ADDR_PTR, 0); |
|
|
|
// go back to rx mode
|
|
|
|
// go back to rx mode
|
|
|
|
sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sx127x_task(void *arg) { |
|
|
|
void sx127x_task(void *arg) { |
|
|
|
sx127x_t * handle = (sx127x_t *)arg; |
|
|
|
sx127x_t * hndl = (sx127x_t *)arg; |
|
|
|
TickType_t delay_time = portMAX_DELAY; |
|
|
|
TickType_t delay_time = portMAX_DELAY; |
|
|
|
QueueSetHandle_t qSet = xQueueCreateSet(8); |
|
|
|
QueueSetHandle_t qSet = xQueueCreateSet(8); |
|
|
|
xQueueAddToSet(handle->intr_semaphore, qSet); |
|
|
|
xQueueAddToSet(hndl->intr_semaphore, qSet); |
|
|
|
xQueueAddToSet(handle->tx_packet_queue, qSet); |
|
|
|
xQueueAddToSet(hndl->tx_packet_queue, qSet); |
|
|
|
sx127x_packet_t packet; |
|
|
|
sx127x_packet_t packet; |
|
|
|
|
|
|
|
|
|
|
|
// be in rx mode by default
|
|
|
|
// be in rx mode by default
|
|
|
|
sx127x_write_register(handle, REG_OP_MODE, |
|
|
|
sx127x_write_register(hndl, REG_OP_MODE, |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
SX127X_LONG_RANGE | SX127X_MODE_RX_CONT); |
|
|
|
|
|
|
|
|
|
|
|
while (handle->task_state == SX127X_TASK_RUNNING) { |
|
|
|
while (hndl->task_state == SX127X_TASK_RUNNING) { |
|
|
|
QueueSetMemberHandle_t queue = xQueueSelectFromSet(qSet, delay_time); |
|
|
|
QueueSetMemberHandle_t queue = xQueueSelectFromSet(qSet, delay_time); |
|
|
|
if (queue == handle->intr_semaphore) { |
|
|
|
if (queue == hndl->intr_semaphore) { |
|
|
|
BaseType_t didRecv = xSemaphoreTake(handle->intr_semaphore, 0); |
|
|
|
BaseType_t didRecv = xSemaphoreTake(hndl->intr_semaphore, 0); |
|
|
|
if (didRecv) { |
|
|
|
if (didRecv) { |
|
|
|
ESP_LOGV(SX127X_TAG, "recv from isr"); |
|
|
|
ESP_LOGV(SX127X_TAG, "recv from isr"); |
|
|
|
|
|
|
|
|
|
|
|
sx127x_do_rx(handle); |
|
|
|
sx127x_do_rx(hndl); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (queue == handle->tx_packet_queue) { |
|
|
|
} else if (queue == hndl->tx_packet_queue) { |
|
|
|
BaseType_t didRecv = xQueueReceive(handle->tx_packet_queue, &packet, 0); |
|
|
|
BaseType_t didRecv = xQueueReceive(hndl->tx_packet_queue, &packet, 0); |
|
|
|
if (didRecv) { |
|
|
|
if (didRecv) { |
|
|
|
ESP_LOGV(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); |
|
|
|
sx127x_do_tx(hndl, &packet); |
|
|
|
|
|
|
|
|
|
|
|
free(packet.data); |
|
|
|
free(packet.data); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
ESP_LOGI(SX127X_TAG, "sx127x_task exiting"); |
|
|
|
ESP_LOGI(SX127X_TAG, "sx127x_task exiting"); |
|
|
|
handle->task_state = SX127X_TASK_STOPPED; |
|
|
|
hndl->task_state = SX127X_TASK_STOPPED; |
|
|
|
vTaskDelete(NULL); // must delete own task
|
|
|
|
vTaskDelete(NULL); // must delete own task
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_start(sx127x_t *handle) { |
|
|
|
esp_err_t sx127x_start(sx127x_t *hndl) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
|
|
|
|
|
|
|
|
SX127X_CHECK(handle->task_handle == NULL, "task already running", |
|
|
|
SX127X_CHECK(hndl->task_handle == NULL, "task already running", |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
|
|
|
|
|
|
|
|
handle->intr_semaphore = xSemaphoreCreateBinary(); |
|
|
|
hndl->intr_semaphore = xSemaphoreCreateBinary(); |
|
|
|
handle->tx_packet_queue = xQueueCreate(TX_QUEUE_LEN, sizeof(sx127x_packet_t)); |
|
|
|
hndl->tx_packet_queue = xQueueCreate(TX_QUEUE_LEN, sizeof(sx127x_packet_t)); |
|
|
|
handle->rx_packet_queue = |
|
|
|
hndl->rx_packet_queue = |
|
|
|
xQueueCreate(RX_QUEUE_LEN, sizeof(sx127x_rx_packet_t)); |
|
|
|
xQueueCreate(RX_QUEUE_LEN, sizeof(sx127x_rx_packet_t)); |
|
|
|
|
|
|
|
|
|
|
|
handle->task_state = SX127X_TASK_RUNNING; |
|
|
|
hndl->task_state = SX127X_TASK_RUNNING; |
|
|
|
BaseType_t pdRet = |
|
|
|
BaseType_t pdRet = |
|
|
|
xTaskCreate(sx127x_task, "sx127x_task", TASK_STACK_SIZE, (void *)handle, |
|
|
|
xTaskCreate(sx127x_task, "sx127x_task", TASK_STACK_SIZE, (void *)hndl, |
|
|
|
TASK_PRIORITY, &handle->task_handle); |
|
|
|
TASK_PRIORITY, &hndl->task_handle); |
|
|
|
SX127X_CHECK(pdRet == pdPASS, "failed to create task", ESP_FAIL); |
|
|
|
SX127X_CHECK(pdRet == pdPASS, "failed to create task", ESP_FAIL); |
|
|
|
|
|
|
|
|
|
|
|
ret = sx127x_write_register(handle, REG_DIO_MAPPING_1, 0x00); |
|
|
|
ret = sx127x_write_register(hndl, REG_DIO_MAPPING_1, 0x00); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
SX127X_ERROR_CHECK(ret); |
|
|
|
|
|
|
|
|
|
|
|
gpio_config_t irq_io_config; |
|
|
|
gpio_config_t irq_io_config; |
|
|
|
irq_io_config.intr_type = GPIO_INTR_POSEDGE; |
|
|
|
irq_io_config.intr_type = GPIO_INTR_POSEDGE; |
|
|
|
irq_io_config.mode = GPIO_MODE_INPUT; |
|
|
|
irq_io_config.mode = GPIO_MODE_INPUT; |
|
|
|
irq_io_config.pin_bit_mask = (1ULL << handle->config.irq_io_num); |
|
|
|
irq_io_config.pin_bit_mask = (1ULL << hndl->config.irq_io_num); |
|
|
|
irq_io_config.pull_down_en = 0; |
|
|
|
irq_io_config.pull_down_en = 0; |
|
|
|
irq_io_config.pull_up_en = 0; |
|
|
|
irq_io_config.pull_up_en = 0; |
|
|
|
ret = gpio_config(&irq_io_config); |
|
|
|
ret = gpio_config(&irq_io_config); |
|
|
@ -342,36 +342,36 @@ esp_err_t sx127x_start(sx127x_t *handle) { |
|
|
|
|
|
|
|
|
|
|
|
ret = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1); |
|
|
|
ret = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_install_isr_service); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_install_isr_service); |
|
|
|
ret = gpio_isr_handler_add(handle->config.irq_io_num, sx127x_isr, |
|
|
|
ret = gpio_isr_handler_add(hndl->config.irq_io_num, sx127x_isr, |
|
|
|
(void *)handle); |
|
|
|
(void *)hndl); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_isr_handler_add); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_isr_handler_add); |
|
|
|
|
|
|
|
|
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_stop(sx127x_t *handle) { |
|
|
|
esp_err_t sx127x_stop(sx127x_t *hndl) { |
|
|
|
esp_err_t ret; |
|
|
|
esp_err_t ret; |
|
|
|
|
|
|
|
|
|
|
|
SX127X_CHECK(handle->task_handle != NULL, "task has not been started", |
|
|
|
SX127X_CHECK(hndl->task_handle != NULL, "task has not been started", |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
handle->task_state = SX127X_TASK_STOPPING; |
|
|
|
hndl->task_state = SX127X_TASK_STOPPING; |
|
|
|
xTaskNotifyGive(handle->task_handle); |
|
|
|
xTaskNotifyGive(hndl->task_handle); |
|
|
|
|
|
|
|
|
|
|
|
ret = gpio_isr_handler_remove(handle->config.irq_io_num); |
|
|
|
ret = gpio_isr_handler_remove(hndl->config.irq_io_num); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_isr_handler_remove); |
|
|
|
SX127X_ERROR_CHECK2(ret, gpio_isr_handler_remove); |
|
|
|
gpio_uninstall_isr_service(); |
|
|
|
gpio_uninstall_isr_service(); |
|
|
|
|
|
|
|
|
|
|
|
while (handle->task_state != SX127X_TASK_STOPPED) { |
|
|
|
while (hndl->task_state != SX127X_TASK_STOPPED) { |
|
|
|
vTaskDelay(10); |
|
|
|
vTaskDelay(10); |
|
|
|
} |
|
|
|
} |
|
|
|
handle->task_handle = NULL; |
|
|
|
hndl->task_handle = NULL; |
|
|
|
|
|
|
|
|
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_send_packet(sx127x_t *handle, const char *data, |
|
|
|
esp_err_t sx127x_send_packet(sx127x_t *hndl, const char *data, |
|
|
|
size_t data_len, TickType_t ticks_to_wait) { |
|
|
|
size_t data_len, TickType_t ticks_to_wait) { |
|
|
|
SX127X_CHECK(handle->task_state == SX127X_TASK_RUNNING, "task not running", |
|
|
|
SX127X_CHECK(hndl->task_state == SX127X_TASK_RUNNING, "task not running", |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
ESP_ERR_INVALID_STATE); |
|
|
|
SX127X_CHECK(data_len < SX127_MAX_PACKET_LEN, "packet len too long: %d", |
|
|
|
SX127X_CHECK(data_len < SX127_MAX_PACKET_LEN, "packet len too long: %d", |
|
|
|
ESP_ERR_INVALID_ARG, data_len); |
|
|
|
ESP_ERR_INVALID_ARG, data_len); |
|
|
@ -382,16 +382,16 @@ esp_err_t sx127x_send_packet(sx127x_t *handle, const char *data, |
|
|
|
SX127X_CHECK(packet.data != NULL, "malloc error", ESP_ERR_NO_MEM); |
|
|
|
SX127X_CHECK(packet.data != NULL, "malloc error", ESP_ERR_NO_MEM); |
|
|
|
memcpy(packet.data, data, data_len); |
|
|
|
memcpy(packet.data, data, data_len); |
|
|
|
BaseType_t pdRet = |
|
|
|
BaseType_t pdRet = |
|
|
|
xQueueSend(handle->tx_packet_queue, &packet, ticks_to_wait); |
|
|
|
xQueueSend(hndl->tx_packet_queue, &packet, ticks_to_wait); |
|
|
|
SX127X_CHECK(pdRet == pdTRUE, "tx queue full", ESP_ERR_TIMEOUT); |
|
|
|
SX127X_CHECK(pdRet == pdTRUE, "tx queue full", ESP_ERR_TIMEOUT); |
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
esp_err_t sx127x_recv_packet(sx127x_t *handle, sx127x_rx_packet_t *packet, |
|
|
|
esp_err_t sx127x_recv_packet(sx127x_t *hndl, sx127x_rx_packet_t *packet, |
|
|
|
TickType_t ticks_to_wait) { |
|
|
|
TickType_t ticks_to_wait) { |
|
|
|
SX127X_CHECK(packet != NULL, "packet must not be NULL", ESP_ERR_INVALID_ARG); |
|
|
|
SX127X_CHECK(packet != NULL, "packet must not be NULL", ESP_ERR_INVALID_ARG); |
|
|
|
BaseType_t pdRet = |
|
|
|
BaseType_t pdRet = |
|
|
|
xQueueReceive(handle->rx_packet_queue, packet, ticks_to_wait); |
|
|
|
xQueueReceive(hndl->rx_packet_queue, packet, ticks_to_wait); |
|
|
|
if (pdRet != pdTRUE) { |
|
|
|
if (pdRet != pdTRUE) { |
|
|
|
ESP_LOGV(SX127X_TAG, "timeout on recv_packet"); |
|
|
|
ESP_LOGV(SX127X_TAG, "timeout on recv_packet"); |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
@ -399,6 +399,6 @@ esp_err_t sx127x_recv_packet(sx127x_t *handle, sx127x_rx_packet_t *packet, |
|
|
|
return ESP_OK; |
|
|
|
return ESP_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QueueHandle_t sx127x_get_recv_queue(sx127x_t *handle) { return handle->rx_packet_queue; } |
|
|
|
QueueHandle_t sx127x_get_recv_queue(sx127x_t *hndl) { return hndl->rx_packet_queue; } |
|
|
|
|
|
|
|
|
|
|
|
void sx127x_packet_rx_free(sx127x_rx_packet_t *packet) { free(packet->data); } |
|
|
|
void sx127x_packet_rx_free(sx127x_rx_packet_t *packet) { free(packet->data); } |