You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
5.3 KiB

#include "sx127x_driver.h"
#include "sx127x_internal.h"
#include "sx127x_registers.h"
#include <esp_log.h>
#include <string.h>
const char *SX127X_TAG = "sx127x";
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;
memcpy(&handle->config, config, sizeof(sx127x_config_t));
ret = gpio_set_direction(config->rst_io_num, GPIO_MODE_OUTPUT);
SX127X_ERROR_CHECK2(ret, gpio_set_direction)
// perform reset
gpio_set_level(config->rst_io_num, 0);
vTaskDelay(RESET_DELAY);
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);
SX127X_ERROR_CHECK2(ret, spi_bus_initialize)
spi_device_interface_config_t device_config = {
.command_bits = 0,
.address_bits = 8,
.dummy_bits = 0,
.mode = 0,
.duty_cycle_pos = 0,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.clock_speed_hz = SPI_CLOCK_HZ, // 8mhz
.input_delay_ns = 0,
.spics_io_num = config->cs_io_num,
.flags = 0,
.queue_size = 8,
.pre_cb = NULL,
.post_cb = NULL,
};
ret = spi_bus_add_device(config->spi_host, &device_config, &handle->device_handle);
SX127X_ERROR_CHECK2(ret, spi_bus_add_device)
// read version and check that it is compatible
uint8_t version;
ret = sx127x_read_register(handle, REG_VERSION, &version);
SX127X_ERROR_CHECK2(ret, sx127x_read_register);
SX127X_CHECK(version == 0x12, "unsupported version %#x", ESP_ERR_INVALID_VERSION, version);
ret = sx127x_sleep(handle);
SX127X_ERROR_CHECK(ret);
ret = sx127x_set_frequency(handle, config->frequency);
SX127X_ERROR_CHECK(ret);
ret = sx127x_write_register(handle, REG_FIFO_TX_BASE_ADDR, 0);
SX127X_ERROR_CHECK(ret);
sx127x_write_register(handle, REG_FIFO_RX_BASE_ADDR, 0);
SX127X_ERROR_CHECK(ret);
uint8_t reg_lna;
ret = sx127x_read_register(handle, REG_LNA, &reg_lna);
SX127X_ERROR_CHECK(ret);
reg_lna |= 0x03; // set LNA boost
ret = sx127x_write_register(handle, REG_LNA, reg_lna);
SX127X_ERROR_CHECK(ret);
// set auto AGC
ret = sx127x_write_register(handle, REG_MODEM_CONFIG_3, CONFIG3_AUTO_AGC);
SX127X_ERROR_CHECK(ret);
ret = sx127x_set_tx_power(handle, config->tx_power, true);
SX127X_ERROR_CHECK(ret);
ret = sx127x_set_spreading_factor(handle, config->spreading_factor);
SX127X_ERROR_CHECK(ret);
ret = sx127x_set_sync_word(handle, config->sync_word);
SX127X_ERROR_CHECK(ret);
ret = sx127x_set_crc(handle, config->crc);
SX127X_ERROR_CHECK(ret);
ret = sx127x_standby(handle);
ESP_ERROR_CHECK(ret);
*handle_ptr = handle;
return ESP_OK;
}
esp_err_t sx127x_free(sx127x_t *handle) {
esp_err_t ret;
if (handle->task_handle) {
ret = sx127x_stop(handle);
SX127X_ERROR_CHECK(ret);
}
ret = spi_bus_remove_device(handle->device_handle);
SX127X_ERROR_CHECK2(ret, spi_bus_remove_device)
ret = spi_bus_free(handle->config.spi_host);
SX127X_ERROR_CHECK2(ret, spi_bus_free)
free(handle);
return ESP_OK;
}
void sx127x_isr(void *arg) {
sx127x_t *handle = (sx127x_t *)arg;
ESP_LOGI(SX127X_TAG, "sx127x_isr");
}
void sx127x_task(void *arg) {
sx127x_t *handle = (sx127x_t *)arg;
while (handle->task_running) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}
esp_err_t sx127x_start(sx127x_t *handle) {
esp_err_t ret;
SX127X_CHECK(handle->task_handle == NULL, "task already running", ESP_ERR_INVALID_STATE);
ret = sx127x_write_register(handle, REG_DIO_MAPPING_1, 0x00);
SX127X_ERROR_CHECK(ret);
gpio_config_t irq_io_config;
irq_io_config.intr_type = GPIO_INTR_POSEDGE;
irq_io_config.mode = GPIO_MODE_INPUT;
irq_io_config.pin_bit_mask = (1ULL << handle->config.irq_io_num);
irq_io_config.pull_down_en = 0;
irq_io_config.pull_up_en = 0;
ret = gpio_config(&irq_io_config);
SX127X_ERROR_CHECK2(ret, gpio_config)
ret = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
SX127X_ERROR_CHECK2(ret, gpio_install_isr_service);
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;
}
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);
ret = gpio_isr_handler_remove(handle->config.irq_io_num);
SX127X_ERROR_CHECK2(ret, gpio_isr_handler_remove);
gpio_uninstall_isr_service();
return ESP_OK;
}