This commit is contained in:
Alexey Zholtikov 2024-05-16 16:02:27 +03:00
parent 3dc289d795
commit 9a668b759e
4 changed files with 401 additions and 78 deletions

View File

@ -1 +1 @@
idf_component_register(SRCS "zh_rf24.c" INCLUDE_DIRS "include" REQUIRES driver esp_event)
idf_component_register(SRCS "main.c" "zh_rf24.c" INCLUDE_DIRS "include" REQUIRES driver esp_event)

View File

@ -26,28 +26,24 @@
* @brief Default values for zh_rf24_init_config_t structure for initial initialization of RF24 interface.
*
*/
#define ZH_RF24_INIT_CONFIG_DEFAULT() \
{ \
.ce_pin = 1, \
.csn_pin = 2, \
.sck_pin = 3, \
.mosi_pin = 4, \
.miso_pin = 5, \
.irq_pin = 6, \
.work_mode = ZH_RF24_RECEIVER, \
.channel = 100, \
.pa_level = ZH_RF24_PA_MAX, \
.data_rate = ZH_RF24_250KBPS, \
.tx_address = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}, \
.rx_address_preamble = {0xC2, 0xC2, 0xC2, 0xC2}, \
.rx_pipe_1_address = 0xC2, \
.rx_pipe_2_address = 0xC3, \
.rx_pipe_3_address = 0xC4, \
.rx_pipe_4_address = 0xC5, \
.rx_pipe_5_address = 0xC6, \
.task_priority = 3, \
.stack_size = 2048, \
.queue_size = 16 \
#define ZH_RF24_INIT_CONFIG_DEFAULT() \
{ \
.ce_pin = 1, \
.csn_pin = 2, \
.sck_pin = 3, \
.mosi_pin = 4, \
.miso_pin = 5, \
.irq_pin = 6, \
.channel = 100, \
.tx_address = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7}, \
.rx_pipe_1_address = {0xC2, 0xC2, 0xC2, 0xC2, 0xC2}, \
.rx_pipe_2_address = 0xC3, \
.rx_pipe_3_address = 0xC4, \
.rx_pipe_4_address = 0xC5, \
.rx_pipe_5_address = 0xC6, \
.task_priority = 3, \
.stack_size = 2048, \
.queue_size = 16 \
}
#ifdef __cplusplus
@ -55,27 +51,6 @@ extern "C"
{
#endif
typedef enum
{
ZH_RF24_PA_MIN,
ZH_RF24_PA_LOW,
ZH_RF24_PA_HIGH,
ZH_RF24_PA_MAX,
} __attribute__((packed)) zh_rf24_pa_level_t;
typedef enum
{
ZH_RF24_1MBPS,
ZH_RF24_2MBPS,
ZH_RF24_250KBPS
} __attribute__((packed)) zh_rf24_data_rate_t;
typedef enum
{
ZH_RF24_TRANSMITTER,
ZH_RF24_RECEIVER
} __attribute__((packed)) zh_rf24_work_mode_t;
/**
* @brief Structure for initial initialization of RF24 interface.
*
@ -93,13 +68,9 @@ extern "C"
uint8_t mosi_pin;
uint8_t miso_pin;
uint8_t irq_pin;
zh_rf24_work_mode_t work_mode;
uint8_t channel;
zh_rf24_pa_level_t pa_level;
zh_rf24_data_rate_t data_rate;
uint8_t tx_address[5];
uint8_t rx_address_preamble[4];
uint8_t rx_pipe_1_address;
uint8_t rx_pipe_1_address[5];
uint8_t rx_pipe_2_address;
uint8_t rx_pipe_3_address;
uint8_t rx_pipe_4_address;
@ -198,7 +169,7 @@ extern "C"
* - ESP_ERR_INVALID_STATE if queue for outgoing data is almost full
* - ESP_FAIL if ESP-NOW is not initialized
*/
esp_err_t zh_rf24_send(const uint8_t *data, const uint8_t data_len, const bool confirm);
esp_err_t zh_rf24_send(const uint8_t *data, const uint8_t data_len);
#ifdef __cplusplus
}

72
main.c Normal file
View File

@ -0,0 +1,72 @@
#include "nvs_flash.h"
#include "esp_netif.h"
#include "zh_rf24.h"
#ifdef CONFIG_IDF_TARGET_ESP8266
#include "esp_system.h"
#else
#include "esp_random.h"
#endif
void zh_rf24_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
typedef struct
{
char char_value[10];
int int_value;
float float_value;
bool bool_value;
} example_message_t;
void app_main(void)
{
// esp_log_level_set("zh_rf24", ESP_LOG_NONE);
nvs_flash_init();
esp_netif_init();
esp_event_loop_create_default();
zh_rf24_init_config_t zh_rf24_init_config = ZH_RF24_INIT_CONFIG_DEFAULT();
zh_rf24_init(&zh_rf24_init_config);
#ifdef CONFIG_IDF_TARGET_ESP8266
esp_event_handler_register(ZH_RF24, ESP_EVENT_ANY_ID, &zh_rf24_event_handler, NULL);
#else
esp_event_handler_instance_register(ZH_RF24, ESP_EVENT_ANY_ID, &zh_rf24_event_handler, NULL, NULL);
#endif
example_message_t send_message = {0};
strcpy(send_message.char_value, "CHAR");
send_message.float_value = 1.234;
send_message.bool_value = false;
for (;;)
{
send_message.int_value = esp_random();
// zh_rf24_send((uint8_t *)&send_message, sizeof(send_message), true);
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
void zh_rf24_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
switch (event_id)
{
case ZH_RF24_ON_RECV_EVENT:;
zh_rf24_event_on_recv_t *recv_data = event_data;
printf("Message via pipe %d is received. Data lenght %d bytes.\n", recv_data->pipe, recv_data->data_len);
example_message_t *recv_message = (example_message_t *)recv_data->data;
printf("Char %s\n", recv_message->char_value);
printf("Int %d\n", recv_message->int_value);
printf("Float %f\n", recv_message->float_value);
printf("Bool %d\n", recv_message->bool_value);
free(recv_data->data); // Do not delete to avoid memory leaks!
break;
case ZH_RF24_ON_SEND_EVENT:;
zh_rf24_event_on_send_t *send_data = event_data;
if (send_data->status == ZH_RF24_SEND_SUCCESS)
{
printf("Message sent success.\n");
}
else
{
printf("Message sent fail.\n");
}
default:
break;
}
}

336
zh_rf24.c
View File

@ -12,10 +12,178 @@
#define ZH_SPI_HOST SPI2_HOST
/// \endcond
/* Команды */
#define R_REGISTER 0x00 // + n Прочитать регистр n
#define W_REGISTER 0x20 // + n Записать регистр n
#define R_RX_PAYLOAD 0x61 // Принять данные данные из верхнего слота очереди приёмника.
#define W_TX_PAYLOAD 0xA0 // Записать в очередь передатчика данные для отправки
#define FLUSH_TX 0xE1 // Сбросить очередь передатчика
#define FLUSH_RX 0xE2 // Сбросить очередь приёмника
#define REUSE_TX_PL 0xE3 // Использовать повторно последний переданный пакет
#define R_RX_PL_WID 0x60 // Прочитать размер данных принятого пакета в начале очереди приёмника.
#define W_ACK_PAYLOAD 0xA8 // + p Записать данные для отправки с пакетом подтверждения по каналу p.
#define W_TX_PAYLOAD_NOACK 0xB0 // Записать в очередь передатчика данные, для отправки без подтверждения
#define NOP 0xFF // Нет операции. Может быть использовано для чтения регистра статуса
/* Регистры */
#define CONFIG 0x00 // Регистр настроек
#define EN_AA 0x01 // Выбор автоподтверждения
#define EN_RXADDR 0x02 // Выбор каналов приёмника
#define SETUP_AW 0x03 // Настройка размера адреса
#define SETUP_RETR 0x04 // Настройка повторной отправки
#define RF_CH 0x05 // Номер радиоканала, на котором осуществляется работа. От 0 до 125.
#define RF_SETUP 0x06 // Настройка радиоканала
#define STATUS 0x07 // Регистр статуса.
#define OBSERVE_TX 0x08 // Количество повторов передачи и потерянных пакетов
#define RPD 0x09 // Мощность принимаемого сигнала. Если младший бит = 1, то уровень более -64dBm
#define RX_ADDR_P0 0x0A // 3-5 байт (начиная с младшего байта). Адрес канала 0 приёмника.
#define RX_ADDR_P1 0x0B // 3-5 байт (начиная с младшего байта). Адрес канала 1 приёмника.
#define RX_ADDR_P2 0x0C // Младший байт адреса канала 2 приёмника. Старшие байты из RX_ADDR_P1
#define RX_ADDR_P3 0x0D // Младший байт адреса канала 3 приёмника. Старшие байты из RX_ADDR_P1
#define RX_ADDR_P4 0x0E // Младший байт адреса канала 4 приёмника. Старшие байты из RX_ADDR_P1
#define RX_ADDR_P5 0x0F // Младший байт адреса канала 5 приёмника. Старшие байты из RX_ADDR_P1
#define TX_ADDR 0x10 // 3-5 байт (начиная с младшего байта). Адрес удалённого устройства для передачи
#define RX_PW_P0 0x11 // Размер данных при приёме по каналу 0: от 1 до 32. 0 - канал не используется.
#define RX_PW_P1 0x12 // Размер данных при приёме по каналу 1: от 1 до 32. 0 - канал не используется.
#define RX_PW_P2 0x13 // Размер данных при приёме по каналу 2: от 1 до 32. 0 - канал не используется.
#define RX_PW_P3 0x14 // Размер данных при приёме по каналу 3: от 1 до 32. 0 - канал не используется.
#define RX_PW_P4 0x15 // Размер данных при приёме по каналу 4: от 1 до 32. 0 - канал не используется.
#define RX_PW_P5 0x16 // Размер данных при приёме по каналу 5: от 1 до 32. 0 - канал не используется.
#define FIFO_STATUS 0x17 // Состояние очередей FIFO приёмника и передатчика
#define DYNPD 0x1C // Выбор каналов приёмника для которых используется произвольная длина пакетов.
#define FEATURE 0x1D // Регистр опций
/* Биты регистров */
// CONFIG
#define MASK_RX_DR 6 // Запрещает прерывание по RX_DR (получение пакета)
#define MASK_TX_DS 5 // Запрещает прерывание по TX_DS (завершение отправки пакета)
#define MASK_MAX_RT 4 // Запрещает прерывание по MAX_RT (превышение числа повторных попыток отправки)
#define EN_CRC 3 // Включает CRC
#define CRCO 2 // Размер поля CRC: 0 - 1 байт; 1 - 2 байта
#define PWR_UP 1 // Включение питания
#define PRIM_RX 0 // Выбор режима: 0 - PTX (передатчик) 1 - PRX (приёмник)
// EN_AA
#define ENAA_P5 5 // Включает автоподтверждение данных, полученных по каналу 5
#define ENAA_P4 4 // Включает автоподтверждение данных, полученных по каналу 4
#define ENAA_P3 3 // Включает автоподтверждение данных, полученных по каналу 3
#define ENAA_P2 2 // Включает автоподтверждение данных, полученных по каналу 2
#define ENAA_P1 1 // Включает автоподтверждение данных, полученных по каналу 1
#define ENAA_P0 0 // Включает автоподтверждение данных, полученных по каналу 0
// EN_RXADDR
#define ERX_P5 5 // Включает канал 5 приёмника
#define ERX_P4 4 // Включает канал 4 приёмника
#define ERX_P3 3 // Включает канал 3 приёмника
#define ERX_P2 2 // Включает канал 2 приёмника
#define ERX_P1 1 // Включает канал 1 приёмника
#define ERX_P0 0 // Включает канал 0 приёмника
// SETUP_AW
#define AW 0 // Два бита, Выбирает ширину поля адреса: 1 - 3 байта; 2 - 4 байта; 3 - 5 байт.
#define SETUP_AW_3BYTES_ADDRESS (1 << AW)
#define SETUP_AW_4BYTES_ADDRESS (2 << AW)
#define SETUP_AW_5BYTES_ADDRESS (3 << AW)
// SETUP_RETR
#define ARD 4 // 4 бита. Задаёт значение задержки перед повторной отправкой пакета: 250 x (n + 1) мкс
#define ARC 0 // 4 битай. Количество повторных попыток отправки, 0 - повторная отправка отключена.
#define SETUP_RETR_DELAY_250MKS (0 << ARD)
#define SETUP_RETR_DELAY_500MKS (1 << ARD)
#define SETUP_RETR_DELAY_750MKS (2 << ARD)
#define SETUP_RETR_DELAY_1000MKS (3 << ARD)
#define SETUP_RETR_DELAY_1250MKS (4 << ARD)
#define SETUP_RETR_DELAY_1500MKS (5 << ARD)
#define SETUP_RETR_DELAY_1750MKS (6 << ARD)
#define SETUP_RETR_DELAY_2000MKS (7 << ARD)
#define SETUP_RETR_DELAY_2250MKS (8 << ARD)
#define SETUP_RETR_DELAY_2500MKS (9 << ARD)
#define SETUP_RETR_DELAY_2750MKS (10 << ARD)
#define SETUP_RETR_DELAY_3000MKS (11 << ARD)
#define SETUP_RETR_DELAY_3250MKS (12 << ARD)
#define SETUP_RETR_DELAY_3500MKS (13 << ARD)
#define SETUP_RETR_DELAY_3750MKS (14 << ARD)
#define SETUP_RETR_DELAY_4000MKS (15 << ARD)
#define SETUP_RETR_NO_RETRANSMIT (0 << ARC)
#define SETUP_RETR_UP_TO_1_RETRANSMIT (1 << ARC)
#define SETUP_RETR_UP_TO_2_RETRANSMIT (2 << ARC)
#define SETUP_RETR_UP_TO_3_RETRANSMIT (3 << ARC)
#define SETUP_RETR_UP_TO_4_RETRANSMIT (4 << ARC)
#define SETUP_RETR_UP_TO_5_RETRANSMIT (5 << ARC)
#define SETUP_RETR_UP_TO_6_RETRANSMIT (6 << ARC)
#define SETUP_RETR_UP_TO_7_RETRANSMIT (7 << ARC)
#define SETUP_RETR_UP_TO_8_RETRANSMIT (8 << ARC)
#define SETUP_RETR_UP_TO_9_RETRANSMIT (9 << ARC)
#define SETUP_RETR_UP_TO_10_RETRANSMIT (10 << ARC)
#define SETUP_RETR_UP_TO_11_RETRANSMIT (11 << ARC)
#define SETUP_RETR_UP_TO_12_RETRANSMIT (12 << ARC)
#define SETUP_RETR_UP_TO_13_RETRANSMIT (13 << ARC)
#define SETUP_RETR_UP_TO_14_RETRANSMIT (14 << ARC)
#define SETUP_RETR_UP_TO_15_RETRANSMIT (15 << ARC)
// RF_SETUP
#define CONT_WAVE 7 // (Только для nRF24L01+) Непрерывная передача несущей (для тестов)
#define RF_DR_LOW 5 // (Только для nRF24L01+) Включает скорость 250кбит/с. RF_DR_HIGH должен быть 0
#define PLL_LOCK 4 // Для тестов
#define RF_DR_HIGH 3 // Выбор скорости обмена (при значении бита RF_DR_LOW = 0): 0 - 1Мбит/с; 1 - 2Мбит/с
#define RF_PWR 1 // 2бита. Выбирает мощность передатчика: 0 - -18dBm; 1 - -16dBm; 2 - -6dBm; 3 - 0dBm
#define RF_SETUP_MINUS18DBM (0 << RF_PWR)
#define RF_SETUP_MINUS12DBM (1 << RF_PWR)
#define RF_SETUP_MINUS6DBM (2 << RF_PWR)
#define RF_SETUP_0DBM (3 << RF_PWR)
#define RF_SETUP_1MBPS (0 << RF_DR_HIGH)
#define RF_SETUP_2MBPS (1 << RF_DR_HIGH)
#define RF_SETUP_250KBPS (1 << RF_DR_LOW) // этот режим не должен использоваться с контролем доставки
// STATUS
#define RX_DR 6 // Флаг получения новых данных в FIFO приёмника. Для сброса флага нужно записать 1
#define TX_DS 5 // Флаг завершения передачи. Для сброса флага нужно записать 1
#define MAX_RT 4 // Флаг превышения установленного числа повторов. Без сброса (записать 1) обмен невозможен
#define RX_P_NO 1 // 3 бита. Номер канала, данные для которого доступны в FIFO приёмника. 7 - FIFO пусто.
#define TX_FULL_STATUS 0 // Признак заполнения FIFO передатчика: 1 - заполнено; 0 - есть доступные слоты
// (переименовано из TX_FULL во избежание путаницы с одноимённым битом из регистра FIFO_STATUS)
// OBSERVE_TX
#define PLOS_CNT 4 // 4 бита. Общее количество пакетов без подтверждения. Сбрасывается записью RF_CH
#define ARC_CNT 0 // 4 бита. Количество предпринятых повторов при последней отправке.
// FIFO_STATUS
#define TX_REUSE 6 // Признак готовности последнего пакета для повторной отправки.
#define TX_FULL_FIFO 5 // Флаг переполнения FIFO очереди передатчика.
// (переименовано из TX_FULL во избежание путаницы с одноимённым битом из регистра STATUS)
#define TX_EMPTY 4 // Флаг освобождения FIFO очереди передатчика.
#define RX_FULL 1 // Флаг переполнения FIFO очереди приёмника.
#define RX_EMPTY 0 // Флаг освобождения FIFO очереди приёмника.
// DYNDP
#define DPL_P5 5 // Включает приём пакетов произвольной длины по каналу 5
#define DPL_P4 4 // Включает приём пакетов произвольной длины по каналу 4
#define DPL_P3 3 // Включает приём пакетов произвольной длины по каналу 3
#define DPL_P2 2 // Включает приём пакетов произвольной длины по каналу 2
#define DPL_P1 1 // Включает приём пакетов произвольной длины по каналу 1
#define DPL_P0 0 // Включает приём пакетов произвольной длины по каналу 0
// FEATURE
#define EN_DPL 2 // Включает поддержку приёма и передачи пакетов произвольной длины
#define EN_ACK_PAY 1 // Разрешает передачу данных с пакетами подтверждения приёма
#define EN_DYN_ACK 0 // Разрешает использование W_TX_PAYLOAD_NOACK
static void s_zh_rf24_processing(void *pvParameter);
static void s_zh_rf24_irq_isr_handler(void *arg);
static void s_zh_rf24_irq_processing(void *pvParameter);
static void s_zh_rf24_read_register(const uint8_t *address, uint8_t *value, const uint8_t length);
static void s_zh_rf24_read_register(const uint8_t *reg, uint8_t *value, const uint8_t length);
static void s_zh_rf24_write_register(const uint8_t *reg, uint8_t *value, const uint8_t length);
static void s_zh_rf24_read_data(uint8_t *data, const uint8_t length);
static void s_zh_rf24_write_data(uint8_t *data, const uint8_t length);
static uint8_t s_zh_rf24_send_command(uint8_t *command);
static const char *TAG = "zh_rf24";
@ -37,7 +205,6 @@ typedef enum
typedef struct
{
uint8_t pipe;
bool confirm;
uint8_t *data;
uint8_t data_len;
} __attribute__((packed)) zh_rf24_queue_data_t;
@ -99,8 +266,8 @@ esp_err_t zh_rf24_init(zh_rf24_init_config_t *config)
.sclk_io_num = s_zh_rf24_init_config.sck_pin,
.mosi_io_num = s_zh_rf24_init_config.mosi_pin,
.miso_io_num = s_zh_rf24_init_config.miso_pin,
.quadwp_io_num = -1,
.quadhd_io_num = -1};
.quadwp_io_num = -1, // ??
.quadhd_io_num = -1}; // ??
if (spi_bus_initialize(ZH_SPI_HOST, &spi_bus_config, SPI_DMA_CH_AUTO) != ESP_OK)
{
ESP_LOGE(TAG, "RF24 initialization fail. SPI initialization error.");
@ -109,28 +276,63 @@ esp_err_t zh_rf24_init(zh_rf24_init_config_t *config)
spi_device_interface_config_t spi_device_interface_config = {
.clock_speed_hz = 4000000,
.spics_io_num = -1,
.queue_size = 7,
.mode = 0,
.queue_size = 7, // ??
.mode = 0, // ??
.flags = SPI_DEVICE_NO_DUMMY};
if (spi_bus_add_device(ZH_SPI_HOST, &spi_device_interface_config, &s_zh_rf24_spi_handle) != ESP_OK)
{
ESP_LOGE(TAG, "RF24 initialization fail. SPI initialization error.");
return ESP_FAIL;
}
s_zh_rf24_irq_semaphore = xSemaphoreCreateBinary();
if (gpio_install_isr_service(0) != ESP_OK || gpio_isr_handler_add(s_zh_rf24_init_config.irq_pin, s_zh_rf24_irq_isr_handler, NULL) != ESP_OK)
for (uint8_t i = 0; i < 100; ++i)
{
ESP_LOGE(TAG, "RF24 initialization fail. Internal error.");
return ESP_FAIL;
s_zh_rf24_write_register(CONFIG, (1 << EN_CRC) | (1 << CRCO) | (1 << PRIM_RX), 1);
uint8_t value = 0;
s_zh_rf24_read_register(CONFIG, &value, 1);
if (value == ((1 << EN_CRC) | (1 << CRCO) | (1 << PRIM_RX)))
{
s_zh_rf24_write_register(EN_AA, 0x3F, 1); // Enable auto acknowledgment for all pipes.
s_zh_rf24_write_register(EN_RXADDR, 0x3F, 1); // Enable all pipes.
s_zh_rf24_write_register(SETUP_AW, 0x03, 1); // Setup address widths for 5 bytes. // выбор длины адреса 5 байт
s_zh_rf24_write_register(SETUP_RETR, 0x1F, 1); // Setup automatic retransmission a maximum of 15 times with delay of 500 µs between attempts.
s_zh_rf24_write_register(RF_CH, &s_zh_rf24_init_config.channel, 1); // Setup RF channel.
s_zh_rf24_write_register(RF_SETUP, 0x06, 1); // Setup data rate 1 Mbps and 0 dBm RF output power in TX mode.
s_zh_rf24_write_register(RX_ADDR_P0, &s_zh_rf24_init_config.tx_address, 5); // Setup receive address for pipe 0.
s_zh_rf24_write_register(RX_ADDR_P1, &s_zh_rf24_init_config.rx_pipe_1_address, 5); // Setup receive address for pipe 1.
s_zh_rf24_write_register(RX_ADDR_P2, &s_zh_rf24_init_config.rx_pipe_2_address, 1); // Setup receive address for pipe 2.
s_zh_rf24_write_register(RX_ADDR_P3, &s_zh_rf24_init_config.rx_pipe_3_address, 1); // Setup receive address for pipe 3.
s_zh_rf24_write_register(RX_ADDR_P4, &s_zh_rf24_init_config.rx_pipe_4_address, 1); // Setup receive address for pipe 4.
s_zh_rf24_write_register(RX_ADDR_P5, &s_zh_rf24_init_config.rx_pipe_5_address, 1); // Setup receive address for pipe 5.
s_zh_rf24_write_register(TX_ADDR, &s_zh_rf24_init_config.tx_address, 5); // Setup transmitter address.
s_zh_rf24_write_register(RX_PW_P0, 32, 1); // Setup the maximum data length for pipe 0.
s_zh_rf24_write_register(RX_PW_P1, 32, 1); // Setup the maximum data length for pipe 1.
s_zh_rf24_write_register(RX_PW_P2, 32, 1); // Setup the maximum data length for pipe 2.
s_zh_rf24_write_register(RX_PW_P3, 32, 1); // Setup the maximum data length for pipe 3.
s_zh_rf24_write_register(RX_PW_P4, 32, 1); // Setup the maximum data length for pipe 4.
s_zh_rf24_write_register(RX_PW_P5, 32, 1); // Setup the maximum data length for pipe 5.
s_zh_rf24_write_register(FEATURE, 0x04, 1); // Enable dynamic payload length.
s_zh_rf24_write_register(DYNPD, 0x3F, 1); // Setup dynamic payload length for all pipes.
s_zh_rf24_write_register(CONFIG, (1 << EN_CRC) | (1 << CRCO) | (1 << PWR_UP) | (1 << PRIM_RX), 1);
s_zh_rf24_irq_semaphore = xSemaphoreCreateBinary();
if (gpio_install_isr_service(0) != ESP_OK || gpio_isr_handler_add(s_zh_rf24_init_config.irq_pin, s_zh_rf24_irq_isr_handler, NULL) != ESP_OK)
{
ESP_LOGE(TAG, "RF24 initialization fail. Internal error.");
return ESP_FAIL;
}
if (xTaskCreatePinnedToCore(&s_zh_rf24_irq_processing, "NULL", s_zh_rf24_init_config.stack_size, NULL, s_zh_rf24_init_config.task_priority, NULL, tskNO_AFFINITY) != pdPASS)
{
ESP_LOGE(TAG, "RF24 initialization fail. Internal error.");
return ESP_FAIL;
}
s_zh_rf24_is_initialized = true;
gpio_set_level(s_zh_rf24_init_config.ce_pin, 1);
ESP_LOGI(TAG, "RF24 initialization success.");
return ESP_OK;
}
esp_rom_delay_us(1);
}
if (xTaskCreatePinnedToCore(&s_zh_rf24_irq_processing, "NULL", s_zh_rf24_init_config.stack_size, NULL, s_zh_rf24_init_config.task_priority, NULL, tskNO_AFFINITY) != pdPASS)
{
ESP_LOGE(TAG, "RF24 initialization fail. Internal error.");
return ESP_FAIL;
}
s_zh_rf24_is_initialized = true;
ESP_LOGI(TAG, "RF24 initialization success.");
return ESP_OK;
ESP_LOGE(TAG, "RF24 initialization fail. Module not connected or not responding.");
return ESP_FAIL;
}
esp_err_t zh_rf24_deinit(void)
@ -138,9 +340,49 @@ esp_err_t zh_rf24_deinit(void)
return 0;
}
esp_err_t zh_rf24_send(const uint8_t *data, const uint8_t data_len, const bool confirm)
esp_err_t zh_rf24_send(const uint8_t *data, const uint8_t data_len)
{
return 0;
ESP_LOGI(TAG, "Adding outgoing RF24 data to queue begin.");
if (s_zh_rf24_is_initialized == false)
{
ESP_LOGE(TAG, "Adding outgoing RF24 data to queue fail. RF24 not initialized.");
return ESP_FAIL;
}
if (data == NULL || data_len == 0 || data_len > ZH_RF24_MAX_MESSAGE_SIZE)
{
ESP_LOGE(TAG, "Adding outgoing RF24 data to queue fail. Invalid argument.");
return ESP_ERR_INVALID_ARG;
}
if (uxQueueSpacesAvailable(s_zh_rf24_queue_handle) < s_zh_rf24_init_config.queue_size / 10)
{
ESP_LOGW(TAG, "Adding outgoing RF24 data to queue fail. Queue is almost full.");
return ESP_ERR_INVALID_STATE;
}
zh_rf24_queue_t rf24_queue = {0};
rf24_queue.id = ZH_RF24_SEND;
zh_rf24_queue_data_t *send_data = &rf24_queue.data;
if (data_len / sizeof(void *) == 0)
{
send_data->data = heap_caps_malloc(data_len, MALLOC_CAP_32BIT);
}
else
{
send_data->data = heap_caps_malloc(data_len, MALLOC_CAP_8BIT);
}
if (send_data->data == NULL)
{
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. Memory allocation fail or no free memory in the heap.");
return ESP_ERR_NO_MEM;
}
memset(send_data->data, 0, data_len);
memcpy(send_data->data, data, data_len);
send_data->data_len = data_len;
ESP_LOGI(TAG, "Adding outgoing RF24 data to queue success.");
if (xQueueSend(s_zh_rf24_queue_handle, &rf24_queue, portTICK_PERIOD_MS) != pdTRUE)
{
ESP_LOGE(TAG, "RF24 message processing task internal error.");
}
return ESP_OK;
}
static void s_zh_rf24_processing(void *pvParameter)
@ -171,17 +413,55 @@ static void s_zh_rf24_irq_processing(void *pvParameter)
vTaskDelete(NULL);
}
static void s_zh_rf24_read_register(const uint8_t *address, uint8_t *value, const uint8_t length)
static void s_zh_rf24_read_register(const uint8_t *reg, uint8_t *value, const uint8_t length)
{
// uint8_t status = 0;
gpio_set_level(s_zh_rf24_init_config.csn_pin, 0);
spi_transaction_t spi_transaction = {0};
// spi_transaction.length = DataLength * 8;
// spi_transaction.tx_buffer = Dataout;
// spi_transaction.rx_buffer = Datain;
spi_transaction.length = 8;
spi_transaction.tx_buffer = ((*reg & 0x1F) | R_REGISTER);
spi_transaction.rx_buffer = NULL;
spi_device_transmit(s_zh_rf24_spi_handle, &spi_transaction);
spi_transaction.length = length * 8;
spi_transaction.tx_buffer = NULL;
spi_transaction.rx_buffer = value;
spi_device_transmit(s_zh_rf24_spi_handle, &spi_transaction);
// spi_transfer(dev, R_REGISTER | (REGISTER_MASK & reg));
// spi_read_byte(dev, value, value, len);
gpio_set_level(s_zh_rf24_init_config.csn_pin, 1);
}
static void s_zh_rf24_write_register(const uint8_t *reg, uint8_t *value, const uint8_t length)
{
// uint8_t status = 0;
gpio_set_level(s_zh_rf24_init_config.csn_pin, 0);
spi_transaction_t spi_transaction = {0};
spi_transaction.length = 8;
spi_transaction.tx_buffer = ((*reg & 0x1F) | W_REGISTER);
spi_transaction.rx_buffer = NULL;
spi_device_transmit(s_zh_rf24_spi_handle, &spi_transaction);
spi_transaction.length = length * 8;
spi_transaction.tx_buffer = value;
spi_transaction.rx_buffer = NULL;
spi_device_transmit(s_zh_rf24_spi_handle, &spi_transaction);
gpio_set_level(s_zh_rf24_init_config.csn_pin, 1);
}
static void s_zh_rf24_read_data(uint8_t *data, const uint8_t length)
{
}
static void s_zh_rf24_write_data(uint8_t *data, const uint8_t length)
{
}
static uint8_t s_zh_rf24_send_command(uint8_t *command)
{
uint8_t status = 0;
gpio_set_level(s_zh_rf24_init_config.csn_pin, 0);
spi_transaction_t spi_transaction = {0};
spi_transaction.length = 8;
spi_transaction.tx_buffer = command;
spi_transaction.rx_buffer = status;
spi_device_transmit(s_zh_rf24_spi_handle, &spi_transaction);
gpio_set_level(s_zh_rf24_init_config.csn_pin, 1);
return status;
}