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.
 
 
 
 
 
 

223 lines
7.1 KiB

//-----------------------------------------------------------------------------
// 2024 Ahoy, https://github.com/lumpapu/ahoy
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
#ifndef __NRF_HAL_H__
#define __NRF_HAL_H__
#pragma once
#include "../utils/spiPatcher.h"
#include <esp_rom_gpio.h>
#include <RF24_hal.h>
#define NRF_MAX_TRANSFER_SZ 64
#define NRF_DEFAULT_SPI_SPEED 10000000 // 10 MHz
class nrfHal: public RF24_hal, public SpiPatcherHandle {
public:
nrfHal() {
mSpiPatcher = SpiPatcher::getInstance(SPI2_HOST);
}
void patch() override {
esp_rom_gpio_connect_out_signal(mPinMosi, spi_periph_signal[mHostDevice].spid_out, false, false);
esp_rom_gpio_connect_in_signal(mPinMiso, spi_periph_signal[mHostDevice].spiq_in, false);
esp_rom_gpio_connect_out_signal(mPinClk, spi_periph_signal[mHostDevice].spiclk_out, false, false);
}
void unpatch() override {
esp_rom_gpio_connect_out_signal(mPinMosi, SIG_GPIO_OUT_IDX, false, false);
esp_rom_gpio_connect_in_signal(mPinMiso, GPIO_MATRIX_CONST_ZERO_INPUT, false);
esp_rom_gpio_connect_out_signal(mPinClk, SIG_GPIO_OUT_IDX, false, false);
}
void init(int8_t mosi, int8_t miso, int8_t sclk, int8_t cs, int8_t en, int32_t speed = NRF_DEFAULT_SPI_SPEED) {
mPinMosi = static_cast<gpio_num_t>(mosi);
mPinMiso = static_cast<gpio_num_t>(miso);
mPinClk = static_cast<gpio_num_t>(sclk);
mPinCs = static_cast<gpio_num_t>(cs);
mPinEn = static_cast<gpio_num_t>(en);
mSpiSpeed = speed;
mHostDevice = mSpiPatcher->getDevice();
gpio_reset_pin(mPinMosi);
gpio_set_direction(mPinMosi, GPIO_MODE_OUTPUT);
gpio_set_level(mPinMosi, 1);
gpio_reset_pin(mPinMiso);
gpio_set_direction(mPinMiso, GPIO_MODE_INPUT);
gpio_reset_pin(mPinClk);
gpio_set_direction(mPinClk, GPIO_MODE_OUTPUT);
gpio_set_level(mPinClk, 0);
gpio_reset_pin(mPinCs);
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = 0,
.duty_cycle_pos = 0,
.cs_ena_pretrans = 0,
.cs_ena_posttrans = 0,
.clock_speed_hz = mSpiSpeed,
.input_delay_ns = 0,
.spics_io_num = mPinCs,
.flags = 0,
.queue_size = 1,
.pre_cb = nullptr,
.post_cb = nullptr
};
ESP_ERROR_CHECK(spi_bus_add_device(mHostDevice, &devcfg, &spi));
gpio_reset_pin(mPinEn);
gpio_set_direction(mPinEn, GPIO_MODE_OUTPUT);
gpio_set_level(mPinEn, 0);
}
bool begin() override {
return true;
}
void end() override {}
void ce(bool level) override {
gpio_set_level(mPinEn, level);
}
uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t len) override {
uint8_t data[NRF_MAX_TRANSFER_SZ];
data[0] = cmd;
std::copy(&buf[0], &buf[len], &data[1]);
request_spi();
size_t spiLen = (static_cast<size_t>(len) + 1u) << 3;
spi_transaction_t t = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = spiLen,
.rxlength = spiLen,
.user = NULL,
.tx_buffer = data,
.rx_buffer = data
};
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t));
release_spi();
return data[0]; // status
}
uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t data_len, uint8_t blank_len) override {
uint8_t data[NRF_MAX_TRANSFER_SZ];
data[0] = cmd;
memset(&data[1], 0, (NRF_MAX_TRANSFER_SZ-1));
std::copy(&buf[0], &buf[data_len], &data[1]);
request_spi();
size_t spiLen = (static_cast<size_t>(data_len) + static_cast<size_t>(blank_len) + 1u) << 3;
spi_transaction_t t = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = spiLen,
.rxlength = spiLen,
.user = NULL,
.tx_buffer = data,
.rx_buffer = data
};
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t));
release_spi();
return data[0]; // status
}
uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t len) override {
uint8_t data[NRF_MAX_TRANSFER_SZ + 1];
data[0] = cmd;
if(len > NRF_MAX_TRANSFER_SZ)
len = NRF_MAX_TRANSFER_SZ;
memset(&data[1], 0xff, len);
request_spi();
size_t spiLen = (static_cast<size_t>(len) + 1u) << 3;
spi_transaction_t t = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = spiLen,
.rxlength = spiLen,
.user = NULL,
.tx_buffer = data,
.rx_buffer = data
};
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t));
release_spi();
std::copy(&data[1], &data[len+1], buf);
return data[0]; // status
}
uint8_t read(uint8_t cmd, uint8_t* buf, uint8_t data_len, uint8_t blank_len) override {
uint8_t data[NRF_MAX_TRANSFER_SZ + 1];
uint8_t len = data_len + blank_len;
data[0] = cmd;
if(len > (NRF_MAX_TRANSFER_SZ + 1))
len = (NRF_MAX_TRANSFER_SZ + 1);
memset(&data[1], 0xff, len);
request_spi();
size_t spiLen = (static_cast<size_t>(len) + 1u) << 3;
spi_transaction_t t = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = spiLen,
.rxlength = spiLen,
.user = NULL,
.tx_buffer = data,
.rx_buffer = data
};
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &t));
release_spi();
std::copy(&data[1], &data[data_len+1], buf);
return data[0]; // status
}
private:
inline void request_spi() {
mSpiPatcher->request(this);
}
inline void release_spi() {
mSpiPatcher->release();
}
private:
gpio_num_t mPinMosi = GPIO_NUM_NC;
gpio_num_t mPinMiso = GPIO_NUM_NC;
gpio_num_t mPinClk = GPIO_NUM_NC;
gpio_num_t mPinCs = GPIO_NUM_NC;
gpio_num_t mPinEn = GPIO_NUM_NC;
int32_t mSpiSpeed = NRF_DEFAULT_SPI_SPEED;
spi_host_device_t mHostDevice;
spi_device_handle_t spi;
SpiPatcher *mSpiPatcher;
};
#endif /*__NRF_HAL_H__*/