Merge branch 'pr2306' into dev
This commit is contained in:
commit
326525c961
@ -5,6 +5,7 @@
|
||||
#include <TaskSchedulerDeclarations.h>
|
||||
#include <WiFi.h>
|
||||
#include <vector>
|
||||
#include "W5500.h"
|
||||
|
||||
enum class network_mode {
|
||||
WiFi,
|
||||
@ -83,6 +84,7 @@ private:
|
||||
bool _ethConnected = false;
|
||||
std::vector<NetworkEventCbList_t> _cbEventList;
|
||||
bool _lastMdnsEnabled = false;
|
||||
std::unique_ptr<W5500> _w5500;
|
||||
};
|
||||
|
||||
extern NetworkSettingsClass NetworkSettings;
|
||||
|
||||
@ -26,6 +26,13 @@ struct PinMapping_t {
|
||||
int8_t cmt_gpio3;
|
||||
int8_t cmt_sdio;
|
||||
|
||||
int8_t w5500_mosi;
|
||||
int8_t w5500_miso;
|
||||
int8_t w5500_sclk;
|
||||
int8_t w5500_cs;
|
||||
int8_t w5500_int;
|
||||
int8_t w5500_rst;
|
||||
|
||||
int8_t eth_phy_addr;
|
||||
bool eth_enabled;
|
||||
int eth_power;
|
||||
@ -49,10 +56,11 @@ public:
|
||||
|
||||
bool isValidNrf24Config() const;
|
||||
bool isValidCmt2300Config() const;
|
||||
bool isValidW5500Config() const;
|
||||
bool isValidEthConfig() const;
|
||||
|
||||
private:
|
||||
PinMapping_t _pinMapping;
|
||||
};
|
||||
|
||||
extern PinMappingClass PinMapping;
|
||||
extern PinMappingClass PinMapping;
|
||||
|
||||
19
include/W5500.h
Normal file
19
include/W5500.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <esp_netif.h>
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class W5500 {
|
||||
public:
|
||||
explicit W5500(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst);
|
||||
W5500(const W5500&) = delete;
|
||||
W5500 &operator=(const W5500&) = delete;
|
||||
~W5500();
|
||||
|
||||
String macAddress();
|
||||
|
||||
private:
|
||||
esp_eth_handle_t eth_handle;
|
||||
esp_netif_t *eth_netif;
|
||||
};
|
||||
@ -1,142 +0,0 @@
|
||||
#include "cmt_spi3.h"
|
||||
#include <Arduino.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include <esp_rom_gpio.h> // for esp_rom_gpio_connect_out_signal
|
||||
|
||||
SemaphoreHandle_t paramLock = NULL;
|
||||
#define SPI_PARAM_LOCK() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS)
|
||||
#define SPI_PARAM_UNLOCK() xSemaphoreGive(paramLock)
|
||||
|
||||
// for ESP32 this is the so-called HSPI
|
||||
// for ESP32-S2/S3/C3 this nomenclature does not really exist anymore,
|
||||
// it is simply the first externally usable hardware SPI master controller
|
||||
#define SPI_CMT SPI2_HOST
|
||||
|
||||
spi_device_handle_t spi_reg, spi_fifo;
|
||||
|
||||
void cmt_spi3_init(const int8_t pin_sdio, const int8_t pin_clk, const int8_t pin_cs, const int8_t pin_fcs, const uint32_t spi_speed)
|
||||
{
|
||||
paramLock = xSemaphoreCreateMutex();
|
||||
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = pin_sdio,
|
||||
.miso_io_num = -1, // single wire MOSI/MISO
|
||||
.sclk_io_num = pin_clk,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = 32,
|
||||
};
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 1,
|
||||
.address_bits = 7,
|
||||
.dummy_bits = 0,
|
||||
.mode = 0, // SPI mode 0
|
||||
.cs_ena_pretrans = 1,
|
||||
.cs_ena_posttrans = 1,
|
||||
.clock_speed_hz = spi_speed,
|
||||
.spics_io_num = pin_cs,
|
||||
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
|
||||
.queue_size = 1,
|
||||
.pre_cb = NULL,
|
||||
.post_cb = NULL,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI_CMT, &buscfg, SPI_DMA_DISABLED));
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg, &spi_reg));
|
||||
|
||||
// FiFo
|
||||
spi_device_interface_config_t devcfg2 = {
|
||||
.command_bits = 0,
|
||||
.address_bits = 0,
|
||||
.dummy_bits = 0,
|
||||
.mode = 0, // SPI mode 0
|
||||
.cs_ena_pretrans = 2,
|
||||
.cs_ena_posttrans = (uint8_t)(1 / (spi_speed * 10e6 * 2) + 2), // >2 us
|
||||
.clock_speed_hz = spi_speed,
|
||||
.spics_io_num = pin_fcs,
|
||||
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
|
||||
.queue_size = 1,
|
||||
.pre_cb = NULL,
|
||||
.post_cb = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg2, &spi_fifo));
|
||||
|
||||
esp_rom_gpio_connect_out_signal(pin_sdio, spi_periph_signal[SPI_CMT].spid_out, true, false);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
void cmt_spi3_write(const uint8_t addr, const uint8_t dat)
|
||||
{
|
||||
uint8_t tx_data;
|
||||
tx_data = ~dat;
|
||||
spi_transaction_t t = {
|
||||
.cmd = 1,
|
||||
.addr = ~addr,
|
||||
.length = 8,
|
||||
.tx_buffer = &tx_data,
|
||||
.rx_buffer = NULL
|
||||
};
|
||||
SPI_PARAM_LOCK();
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
|
||||
SPI_PARAM_UNLOCK();
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
|
||||
uint8_t cmt_spi3_read(const uint8_t addr)
|
||||
{
|
||||
uint8_t rx_data;
|
||||
spi_transaction_t t = {
|
||||
.cmd = 0,
|
||||
.addr = ~addr,
|
||||
.length = 8,
|
||||
.rxlength = 8,
|
||||
.tx_buffer = NULL,
|
||||
.rx_buffer = &rx_data
|
||||
};
|
||||
SPI_PARAM_LOCK();
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
|
||||
SPI_PARAM_UNLOCK();
|
||||
delayMicroseconds(100);
|
||||
return rx_data;
|
||||
}
|
||||
|
||||
void cmt_spi3_write_fifo(const uint8_t* buf, const uint16_t len)
|
||||
{
|
||||
uint8_t tx_data;
|
||||
|
||||
spi_transaction_t t = {
|
||||
.length = 8,
|
||||
.tx_buffer = &tx_data, // reference to write data
|
||||
.rx_buffer = NULL
|
||||
};
|
||||
|
||||
SPI_PARAM_LOCK();
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
tx_data = ~buf[i]; // negate buffer contents
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
|
||||
delayMicroseconds(4); // > 4 us
|
||||
}
|
||||
SPI_PARAM_UNLOCK();
|
||||
}
|
||||
|
||||
void cmt_spi3_read_fifo(uint8_t* buf, const uint16_t len)
|
||||
{
|
||||
uint8_t rx_data;
|
||||
|
||||
spi_transaction_t t = {
|
||||
.length = 8,
|
||||
.rxlength = 8,
|
||||
.tx_buffer = NULL,
|
||||
.rx_buffer = &rx_data
|
||||
};
|
||||
|
||||
SPI_PARAM_LOCK();
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
|
||||
delayMicroseconds(4); // > 4 us
|
||||
buf[i] = rx_data;
|
||||
}
|
||||
SPI_PARAM_UNLOCK();
|
||||
}
|
||||
155
lib/CMT2300a/cmt_spi3.cpp
Normal file
155
lib/CMT2300a/cmt_spi3.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
#include "cmt_spi3.h"
|
||||
#include <Arduino.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include <SpiManager.h>
|
||||
|
||||
SemaphoreHandle_t paramLock = NULL;
|
||||
#define SPI_PARAM_LOCK() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS)
|
||||
#define SPI_PARAM_UNLOCK() xSemaphoreGive(paramLock)
|
||||
|
||||
static void IRAM_ATTR pre_cb(spi_transaction_t *trans) {
|
||||
gpio_set_level(*reinterpret_cast<gpio_num_t*>(trans->user), 0);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR post_cb(spi_transaction_t *trans) {
|
||||
gpio_set_level(*reinterpret_cast<gpio_num_t*>(trans->user), 1);
|
||||
}
|
||||
|
||||
spi_device_handle_t spi;
|
||||
gpio_num_t cs_reg, cs_fifo;
|
||||
|
||||
void cmt_spi3_init(const int8_t pin_sdio, const int8_t pin_clk, const int8_t pin_cs, const int8_t pin_fcs, const int32_t spi_speed)
|
||||
{
|
||||
paramLock = xSemaphoreCreateMutex();
|
||||
|
||||
auto bus_config = std::make_shared<SpiBusConfig>(
|
||||
static_cast<gpio_num_t>(pin_sdio),
|
||||
GPIO_NUM_NC,
|
||||
static_cast<gpio_num_t>(pin_clk)
|
||||
);
|
||||
|
||||
spi_device_interface_config_t device_config {
|
||||
.command_bits = 0, // set by transactions individually
|
||||
.address_bits = 0, // set by transactions individually
|
||||
.dummy_bits = 0,
|
||||
.mode = 0, // SPI mode 0
|
||||
.duty_cycle_pos = 0,
|
||||
.cs_ena_pretrans = 2, // only 1 pre and post cycle would be required for register access
|
||||
.cs_ena_posttrans = static_cast<uint8_t>(2 * spi_speed / 1000000), // >2 us
|
||||
.clock_speed_hz = spi_speed,
|
||||
.input_delay_ns = 0,
|
||||
.spics_io_num = -1, // CS handled by callbacks
|
||||
.flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
|
||||
.queue_size = 1,
|
||||
.pre_cb = pre_cb,
|
||||
.post_cb = post_cb,
|
||||
};
|
||||
|
||||
spi = SpiManagerInst.alloc_device("", bus_config, device_config);
|
||||
if (!spi)
|
||||
ESP_ERROR_CHECK(ESP_FAIL);
|
||||
|
||||
cs_reg = static_cast<gpio_num_t>(pin_cs);
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(cs_reg));
|
||||
ESP_ERROR_CHECK(gpio_set_level(cs_reg, 1));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(cs_reg, GPIO_MODE_OUTPUT));
|
||||
|
||||
cs_fifo = static_cast<gpio_num_t>(pin_fcs);
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(cs_fifo));
|
||||
ESP_ERROR_CHECK(gpio_set_level(cs_fifo, 1));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(cs_fifo, GPIO_MODE_OUTPUT));
|
||||
}
|
||||
|
||||
void cmt_spi3_write(const uint8_t addr, const uint8_t data)
|
||||
{
|
||||
spi_transaction_ext_t trans {
|
||||
.base {
|
||||
.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR,
|
||||
.cmd = 0,
|
||||
.addr = addr,
|
||||
.length = 8,
|
||||
.rxlength = 0,
|
||||
.user = &cs_reg, // CS for register access
|
||||
.tx_buffer = &data,
|
||||
.rx_buffer = nullptr,
|
||||
},
|
||||
.command_bits = 1,
|
||||
.address_bits = 7,
|
||||
.dummy_bits = 0,
|
||||
};
|
||||
SPI_PARAM_LOCK();
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, reinterpret_cast<spi_transaction_t*>(&trans)));
|
||||
SPI_PARAM_UNLOCK();
|
||||
}
|
||||
|
||||
uint8_t cmt_spi3_read(const uint8_t addr)
|
||||
{
|
||||
uint8_t data;
|
||||
spi_transaction_ext_t trans {
|
||||
.base {
|
||||
.flags = SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR,
|
||||
.cmd = 1,
|
||||
.addr = addr,
|
||||
.length = 0,
|
||||
.rxlength = 8,
|
||||
.user = &cs_reg, // CS for register access
|
||||
.tx_buffer = nullptr,
|
||||
.rx_buffer = &data,
|
||||
},
|
||||
.command_bits = 1,
|
||||
.address_bits = 7,
|
||||
.dummy_bits = 0,
|
||||
};
|
||||
SPI_PARAM_LOCK();
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, reinterpret_cast<spi_transaction_t*>(&trans)));
|
||||
SPI_PARAM_UNLOCK();
|
||||
return data;
|
||||
}
|
||||
|
||||
void cmt_spi3_write_fifo(const uint8_t* buf, const uint16_t len)
|
||||
{
|
||||
spi_transaction_t trans {
|
||||
.flags = 0,
|
||||
.cmd = 0,
|
||||
.addr = 0,
|
||||
.length = 8,
|
||||
.rxlength = 0,
|
||||
.user = &cs_fifo, // CS for FIFO access
|
||||
.tx_buffer = nullptr,
|
||||
.rx_buffer = nullptr,
|
||||
};
|
||||
|
||||
SPI_PARAM_LOCK();
|
||||
spi_device_acquire_bus(spi, portMAX_DELAY);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
trans.tx_buffer = buf + i;
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &trans));
|
||||
}
|
||||
spi_device_release_bus(spi);
|
||||
SPI_PARAM_UNLOCK();
|
||||
}
|
||||
|
||||
void cmt_spi3_read_fifo(uint8_t* buf, const uint16_t len)
|
||||
{
|
||||
spi_transaction_t trans {
|
||||
.flags = 0,
|
||||
.cmd = 0,
|
||||
.addr = 0,
|
||||
.length = 0,
|
||||
.rxlength = 8,
|
||||
.user = &cs_fifo, // CS for FIFO access
|
||||
.tx_buffer = nullptr,
|
||||
.rx_buffer = nullptr,
|
||||
};
|
||||
|
||||
SPI_PARAM_LOCK();
|
||||
spi_device_acquire_bus(spi, portMAX_DELAY);
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
trans.rx_buffer = buf + i;
|
||||
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &trans));
|
||||
}
|
||||
spi_device_release_bus(spi);
|
||||
SPI_PARAM_UNLOCK();
|
||||
}
|
||||
@ -3,7 +3,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void cmt_spi3_init(const int8_t pin_sdio, const int8_t pin_clk, const int8_t pin_cs, const int8_t pin_fcs, const uint32_t spi_speed);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void cmt_spi3_init(const int8_t pin_sdio, const int8_t pin_clk, const int8_t pin_cs, const int8_t pin_fcs, const int32_t spi_speed);
|
||||
|
||||
void cmt_spi3_write(const uint8_t addr, const uint8_t dat);
|
||||
uint8_t cmt_spi3_read(const uint8_t addr);
|
||||
@ -11,4 +15,8 @@ uint8_t cmt_spi3_read(const uint8_t addr);
|
||||
void cmt_spi3_write_fifo(const uint8_t* p_buf, const uint16_t len);
|
||||
void cmt_spi3_read_fifo(uint8_t* p_buf, const uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
13
lib/SpiManager/library.json
Normal file
13
lib/SpiManager/library.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "SpiManager",
|
||||
"keywords": "spi",
|
||||
"description": "Library for managing the allocation of dedicated or shared SPI buses on the ESP32.",
|
||||
"authors": {
|
||||
"name": "Lennart Ferlemann"
|
||||
},
|
||||
"version": "0.0.1",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
]
|
||||
}
|
||||
49
lib/SpiManager/src/SpiBus.cpp
Normal file
49
lib/SpiManager/src/SpiBus.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "SpiBus.h"
|
||||
|
||||
#include "SpiBusConfig.h"
|
||||
#include "SpiCallback.h"
|
||||
|
||||
SpiBus::SpiBus(const std::string &_id, spi_host_device_t _host_device) :
|
||||
id(_id),
|
||||
host_device(_host_device),
|
||||
cur_config(nullptr)
|
||||
{
|
||||
spi_bus_config_t bus_config {
|
||||
.mosi_io_num = -1,
|
||||
.miso_io_num = -1,
|
||||
.sclk_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.data4_io_num = -1,
|
||||
.data5_io_num = -1,
|
||||
.data6_io_num = -1,
|
||||
.data7_io_num = -1,
|
||||
.max_transfer_sz = SPI_MAX_DMA_LEN,
|
||||
.flags = 0,
|
||||
.intr_flags = 0
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(host_device, &bus_config, SPI_DMA_CH_AUTO));
|
||||
}
|
||||
|
||||
SpiBus::~SpiBus() {
|
||||
ESP_ERROR_CHECK(spi_bus_free(host_device));
|
||||
}
|
||||
|
||||
spi_device_handle_t SpiBus::add_device(const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config) {
|
||||
if (!SpiCallback::patch(shared_from_this(), bus_config, device_config))
|
||||
return nullptr;
|
||||
|
||||
spi_device_handle_t device;
|
||||
ESP_ERROR_CHECK(spi_bus_add_device(host_device, &device_config, &device));
|
||||
return device;
|
||||
}
|
||||
|
||||
// TODO: add remove_device (with spi_device_acquire_bus)
|
||||
|
||||
void SpiBus::apply_config(SpiBusConfig *config) {
|
||||
if (cur_config)
|
||||
cur_config->unpatch(host_device);
|
||||
cur_config = config;
|
||||
if (cur_config)
|
||||
cur_config->patch(host_device);
|
||||
}
|
||||
45
lib/SpiManager/src/SpiBus.h
Normal file
45
lib/SpiManager/src/SpiBus.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class SpiBusConfig;
|
||||
|
||||
class SpiBus : public std::enable_shared_from_this<SpiBus> {
|
||||
public:
|
||||
explicit SpiBus(const std::string &id, spi_host_device_t host_device);
|
||||
SpiBus(const SpiBus&) = delete;
|
||||
SpiBus &operator=(const SpiBus&) = delete;
|
||||
~SpiBus();
|
||||
|
||||
inline __attribute__((always_inline)) void require_config(SpiBusConfig *config) {
|
||||
if (config == cur_config)
|
||||
return;
|
||||
apply_config(config);
|
||||
}
|
||||
|
||||
inline __attribute__((always_inline)) void free_config(SpiBusConfig *config) {
|
||||
if (config != cur_config)
|
||||
return;
|
||||
apply_config(nullptr);
|
||||
}
|
||||
|
||||
inline const std::string &get_id() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
inline spi_host_device_t get_host_device() const {
|
||||
return host_device;
|
||||
}
|
||||
|
||||
spi_device_handle_t add_device(const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config);
|
||||
|
||||
private:
|
||||
void apply_config(SpiBusConfig *config);
|
||||
|
||||
std::string id;
|
||||
spi_host_device_t host_device;
|
||||
SpiBusConfig *cur_config;
|
||||
};
|
||||
67
lib/SpiManager/src/SpiBusConfig.cpp
Normal file
67
lib/SpiManager/src/SpiBusConfig.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "SpiBusConfig.h"
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <esp_rom_gpio.h>
|
||||
#include <soc/spi_periph.h>
|
||||
|
||||
SpiBusConfig::SpiBusConfig(gpio_num_t _pin_mosi, gpio_num_t _pin_miso, gpio_num_t _pin_sclk) :
|
||||
pin_mosi(_pin_mosi),
|
||||
pin_miso(_pin_miso),
|
||||
pin_sclk(_pin_sclk)
|
||||
{
|
||||
if (pin_mosi != GPIO_NUM_NC) {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_mosi));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(pin_mosi, GPIO_MODE_INPUT_OUTPUT));
|
||||
}
|
||||
|
||||
if (pin_miso != GPIO_NUM_NC) {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_miso));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(pin_miso, GPIO_MODE_INPUT));
|
||||
}
|
||||
|
||||
if (pin_sclk != GPIO_NUM_NC) {
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_sclk));
|
||||
ESP_ERROR_CHECK(gpio_set_direction(pin_sclk, GPIO_MODE_INPUT_OUTPUT));
|
||||
}
|
||||
}
|
||||
|
||||
SpiBusConfig::~SpiBusConfig() {
|
||||
if (pin_mosi != GPIO_NUM_NC)
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_mosi));
|
||||
|
||||
if (pin_miso != GPIO_NUM_NC)
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_miso));
|
||||
|
||||
if (pin_sclk != GPIO_NUM_NC)
|
||||
ESP_ERROR_CHECK(gpio_reset_pin(pin_sclk));
|
||||
}
|
||||
|
||||
void SpiBusConfig::patch(spi_host_device_t host_device) {
|
||||
if (pin_mosi != GPIO_NUM_NC) {
|
||||
esp_rom_gpio_connect_out_signal(pin_mosi, spi_periph_signal[host_device].spid_out, false, false);
|
||||
esp_rom_gpio_connect_in_signal(pin_mosi, spi_periph_signal[host_device].spid_in, false);
|
||||
}
|
||||
|
||||
if (pin_miso != GPIO_NUM_NC)
|
||||
esp_rom_gpio_connect_in_signal(pin_miso, spi_periph_signal[host_device].spiq_in, false);
|
||||
|
||||
if (pin_sclk != GPIO_NUM_NC) {
|
||||
esp_rom_gpio_connect_out_signal(pin_sclk, spi_periph_signal[host_device].spiclk_out, false, false);
|
||||
esp_rom_gpio_connect_in_signal(pin_sclk, spi_periph_signal[host_device].spiclk_in, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SpiBusConfig::unpatch(spi_host_device_t host_device) {
|
||||
if (pin_mosi != GPIO_NUM_NC) {
|
||||
esp_rom_gpio_connect_out_signal(pin_mosi, SIG_GPIO_OUT_IDX, false, false);
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host_device].spid_in, false);
|
||||
}
|
||||
|
||||
if (pin_miso != GPIO_NUM_NC)
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host_device].spiq_in, false);
|
||||
|
||||
if (pin_sclk != GPIO_NUM_NC) {
|
||||
esp_rom_gpio_connect_out_signal(pin_sclk, SIG_GPIO_OUT_IDX, false, false);
|
||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host_device].spiclk_in, false);
|
||||
}
|
||||
}
|
||||
20
lib/SpiManager/src/SpiBusConfig.h
Normal file
20
lib/SpiManager/src/SpiBusConfig.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <hal/gpio_types.h>
|
||||
#include <hal/spi_types.h>
|
||||
|
||||
class SpiBusConfig {
|
||||
public:
|
||||
explicit SpiBusConfig(gpio_num_t pin_mosi, gpio_num_t pin_miso, gpio_num_t pin_sclk);
|
||||
SpiBusConfig(const SpiBusConfig&) = delete;
|
||||
SpiBusConfig &operator=(const SpiBusConfig&) = delete;
|
||||
~SpiBusConfig();
|
||||
|
||||
void patch(spi_host_device_t host_device);
|
||||
void unpatch(spi_host_device_t host_device);
|
||||
|
||||
private:
|
||||
gpio_num_t pin_mosi;
|
||||
gpio_num_t pin_miso;
|
||||
gpio_num_t pin_sclk;
|
||||
};
|
||||
65
lib/SpiManager/src/SpiCallback.cpp
Normal file
65
lib/SpiManager/src/SpiCallback.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "SpiCallback.h"
|
||||
|
||||
#include "SpiBus.h"
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
namespace SpiCallback {
|
||||
namespace {
|
||||
struct CallbackData {
|
||||
std::shared_ptr<SpiBus> bus;
|
||||
std::shared_ptr<SpiBusConfig> config;
|
||||
transaction_cb_t inner_pre_cb;
|
||||
transaction_cb_t inner_post_cb;
|
||||
};
|
||||
|
||||
std::array<std::optional<CallbackData>, SPI_MANAGER_CALLBACK_COUNT> instances;
|
||||
|
||||
template<int N>
|
||||
void IRAM_ATTR fn_pre_cb(spi_transaction_t *trans) {
|
||||
instances[N]->bus->require_config(instances[N]->config.get());
|
||||
if (instances[N]->inner_pre_cb)
|
||||
instances[N]->inner_pre_cb(trans);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void IRAM_ATTR fn_post_cb(spi_transaction_t *trans) {
|
||||
if (instances[N]->inner_post_cb)
|
||||
instances[N]->inner_post_cb(trans);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline __attribute__((always_inline)) bool alloc(CallbackData *&instance, transaction_cb_t &pre_cb, transaction_cb_t &post_cb) {
|
||||
if constexpr (N > 0) {
|
||||
if (alloc<N - 1>(instance, pre_cb, post_cb))
|
||||
return true;
|
||||
if (!instances[N - 1]) {
|
||||
instances[N - 1].emplace();
|
||||
instance = &*instances[N - 1];
|
||||
pre_cb = fn_pre_cb<N - 1>;
|
||||
post_cb = fn_post_cb<N - 1>;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool patch(const std::shared_ptr<SpiBus> &bus, const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config) {
|
||||
CallbackData *instance;
|
||||
transaction_cb_t pre_cb;
|
||||
transaction_cb_t post_cb;
|
||||
if (!alloc<SPI_MANAGER_CALLBACK_COUNT>(instance, pre_cb, post_cb))
|
||||
return false;
|
||||
|
||||
instance->bus = bus;
|
||||
instance->config = bus_config;
|
||||
instance->inner_pre_cb = device_config.pre_cb;
|
||||
instance->inner_post_cb = device_config.post_cb;
|
||||
device_config.pre_cb = pre_cb;
|
||||
device_config.post_cb = post_cb;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
15
lib/SpiManager/src/SpiCallback.h
Normal file
15
lib/SpiManager/src/SpiCallback.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Pre and post callbacks for 2 buses with 3 devices each
|
||||
#define SPI_MANAGER_CALLBACK_COUNT 6
|
||||
|
||||
class SpiBus;
|
||||
class SpiBusConfig;
|
||||
|
||||
namespace SpiCallback {
|
||||
bool patch(const std::shared_ptr<SpiBus> &bus, const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config);
|
||||
}
|
||||
106
lib/SpiManager/src/SpiManager.cpp
Normal file
106
lib/SpiManager/src/SpiManager.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "SpiManager.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
SpiManager::SpiManager() {
|
||||
}
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
std::optional<uint8_t> SpiManager::to_arduino(spi_host_device_t host_device) {
|
||||
switch (host_device) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case SPI1_HOST:
|
||||
return FSPI;
|
||||
case SPI2_HOST:
|
||||
return HSPI;
|
||||
case SPI3_HOST:
|
||||
return VSPI;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
case SPI2_HOST:
|
||||
return FSPI;
|
||||
case SPI3_HOST:
|
||||
return HSPI;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
case SPI2_HOST:
|
||||
return FSPI;
|
||||
#endif
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool SpiManager::register_bus(spi_host_device_t host_device) {
|
||||
for (int i = 0; i < SPI_MANAGER_NUM_BUSES; ++i) {
|
||||
if (available_buses[i])
|
||||
continue;
|
||||
|
||||
available_buses[i] = host_device;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpiManager::claim_bus(spi_host_device_t &host_device) {
|
||||
for (int i = SPI_MANAGER_NUM_BUSES - 1; i >= 0; --i) {
|
||||
if (!available_buses[i])
|
||||
continue;
|
||||
|
||||
host_device = *available_buses[i];
|
||||
available_buses[i].reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
std::optional<uint8_t> SpiManager::claim_bus_arduino() {
|
||||
spi_host_device_t host_device;
|
||||
if (!claim_bus(host_device))
|
||||
return std::nullopt;
|
||||
return to_arduino(host_device);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
spi_device_handle_t SpiManager::alloc_device(const std::string &bus_id, const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config) {
|
||||
std::shared_ptr<SpiBus> shared_bus = get_shared_bus(bus_id);
|
||||
if (!shared_bus)
|
||||
return nullptr;
|
||||
|
||||
return shared_bus->add_device(bus_config, device_config);
|
||||
}
|
||||
|
||||
std::shared_ptr<SpiBus> SpiManager::get_shared_bus(const std::string &bus_id) {
|
||||
// look for existing shared bus
|
||||
for (int i = 0; i < SPI_MANAGER_NUM_BUSES; ++i) {
|
||||
if (!shared_buses[i])
|
||||
continue;
|
||||
if (shared_buses[i]->get_id() == bus_id)
|
||||
return shared_buses[i];
|
||||
}
|
||||
|
||||
// create new shared bus
|
||||
for (int i = 0; i < SPI_MANAGER_NUM_BUSES; ++i) {
|
||||
if (shared_buses[i])
|
||||
continue;
|
||||
|
||||
spi_host_device_t host_device;
|
||||
if (!claim_bus(host_device))
|
||||
return nullptr;
|
||||
|
||||
shared_buses[i] = std::make_shared<SpiBus>(bus_id, host_device);
|
||||
return shared_buses[i];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SpiManager SpiManagerInst;
|
||||
40
lib/SpiManager/src/SpiManager.h
Normal file
40
lib/SpiManager/src/SpiManager.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "SpiBus.h"
|
||||
#include "SpiBusConfig.h"
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#define SPI_MANAGER_NUM_BUSES SOC_SPI_PERIPH_NUM
|
||||
|
||||
class SpiManager {
|
||||
public:
|
||||
explicit SpiManager();
|
||||
SpiManager(const SpiManager&) = delete;
|
||||
SpiManager &operator=(const SpiManager&) = delete;
|
||||
|
||||
#ifdef ARDUINO
|
||||
static std::optional<uint8_t> to_arduino(spi_host_device_t host_device);
|
||||
#endif
|
||||
|
||||
bool register_bus(spi_host_device_t host_device);
|
||||
bool claim_bus(spi_host_device_t &host_device);
|
||||
#ifdef ARDUINO
|
||||
std::optional<uint8_t> claim_bus_arduino();
|
||||
#endif
|
||||
|
||||
spi_device_handle_t alloc_device(const std::string &bus_id, const std::shared_ptr<SpiBusConfig> &bus_config, spi_device_interface_config_t &device_config);
|
||||
|
||||
private:
|
||||
std::shared_ptr<SpiBus> get_shared_bus(const std::string &bus_id);
|
||||
|
||||
std::array<std::optional<spi_host_device_t>, SPI_MANAGER_NUM_BUSES> available_buses;
|
||||
std::array<std::shared_ptr<SpiBus>, SPI_MANAGER_NUM_BUSES> shared_buses;
|
||||
};
|
||||
|
||||
extern SpiManager SpiManagerInst;
|
||||
@ -229,6 +229,7 @@ build_flags = ${env.build_flags}
|
||||
-DLED0=17
|
||||
-DLED1=18
|
||||
-DARDUINO_USB_MODE=1
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
[env:opendtufusionv2]
|
||||
board = esp32-s3-devkitc-1
|
||||
@ -252,3 +253,32 @@ build_flags = ${env.build_flags}
|
||||
-DCMT_SDIO=5
|
||||
-DARDUINO_USB_MODE=1
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
[env:opendtufusionv2_shield]
|
||||
board = esp32-s3-devkitc-1
|
||||
upload_protocol = esp-builtin
|
||||
debug_tool = esp-builtin
|
||||
debug_speed = 12000
|
||||
build_flags = ${env.build_flags}
|
||||
-DHOYMILES_PIN_MISO=48
|
||||
-DHOYMILES_PIN_MOSI=35
|
||||
-DHOYMILES_PIN_SCLK=36
|
||||
-DHOYMILES_PIN_IRQ=47
|
||||
-DHOYMILES_PIN_CE=38
|
||||
-DHOYMILES_PIN_CS=37
|
||||
-DLED0=17
|
||||
-DLED1=18
|
||||
-DCMT_CLK=6
|
||||
-DCMT_CS=4
|
||||
-DCMT_FCS=21
|
||||
-DCMT_GPIO2=3
|
||||
-DCMT_GPIO3=8
|
||||
-DCMT_SDIO=5
|
||||
-DW5500_MOSI=40
|
||||
-DW5500_MISO=41
|
||||
-DW5500_SCLK=39
|
||||
-DW5500_CS=42
|
||||
-DW5500_INT=44
|
||||
-DW5500_RST=43
|
||||
-DARDUINO_USB_MODE=1
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
@ -8,20 +8,7 @@
|
||||
#include "PinMapping.h"
|
||||
#include "SunPosition.h"
|
||||
#include <Hoymiles.h>
|
||||
|
||||
// the NRF shall use the second externally usable HW SPI controller
|
||||
// for ESP32 that is the so-called VSPI, for ESP32-S2/S3 it is now called implicitly
|
||||
// HSPI, as it has shifted places for these chip generations
|
||||
// for all generations, this is equivalent to SPI3_HOST in the lower level driver
|
||||
// For ESP32-C2, the only externally usable HW SPI controller is SPI2, its signal names
|
||||
// being prefixed with FSPI.
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#define SPI_NRF HSPI
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define SPI_NRF FSPI
|
||||
#else
|
||||
#define SPI_NRF VSPI
|
||||
#endif
|
||||
#include <SpiManager.h>
|
||||
|
||||
InverterSettingsClass InverterSettings;
|
||||
|
||||
@ -44,7 +31,10 @@ void InverterSettingsClass::init(Scheduler& scheduler)
|
||||
|
||||
if (PinMapping.isValidNrf24Config() || PinMapping.isValidCmt2300Config()) {
|
||||
if (PinMapping.isValidNrf24Config()) {
|
||||
SPIClass* spiClass = new SPIClass(SPI_NRF);
|
||||
auto spi_bus = SpiManagerInst.claim_bus_arduino();
|
||||
ESP_ERROR_CHECK(spi_bus ? ESP_OK : ESP_FAIL);
|
||||
|
||||
SPIClass* spiClass = new SPIClass(*spi_bus);
|
||||
spiClass->begin(pin.nrf24_clk, pin.nrf24_miso, pin.nrf24_mosi, pin.nrf24_cs);
|
||||
Hoymiles.initNRF(spiClass, pin.nrf24_en, pin.nrf24_irq);
|
||||
}
|
||||
|
||||
@ -31,6 +31,15 @@ void NetworkSettingsClass::init(Scheduler& scheduler)
|
||||
WiFi.disconnect(true, true);
|
||||
|
||||
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1, _2));
|
||||
|
||||
if (PinMapping.isValidW5500Config()) {
|
||||
PinMapping_t& pin = PinMapping.get();
|
||||
_w5500 = std::make_unique<W5500>(pin.w5500_mosi, pin.w5500_miso, pin.w5500_sclk, pin.w5500_cs, pin.w5500_int, pin.w5500_rst);
|
||||
} else if (PinMapping.isValidEthConfig()) {
|
||||
PinMapping_t& pin = PinMapping.get();
|
||||
ETH.begin(pin.eth_phy_addr, pin.eth_power, pin.eth_mdc, pin.eth_mdio, pin.eth_type, pin.eth_clk_mode);
|
||||
}
|
||||
|
||||
setupMode();
|
||||
|
||||
scheduler.addTask(_loopTask);
|
||||
@ -168,11 +177,6 @@ void NetworkSettingsClass::setupMode()
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (PinMapping.isValidEthConfig()) {
|
||||
PinMapping_t& pin = PinMapping.get();
|
||||
ETH.begin(pin.eth_phy_addr, pin.eth_power, pin.eth_mdc, pin.eth_mdio, pin.eth_type, pin.eth_clk_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSettingsClass::enableAdminMode()
|
||||
@ -400,6 +404,8 @@ String NetworkSettingsClass::macAddress() const
|
||||
{
|
||||
switch (_networkMode) {
|
||||
case network_mode::Ethernet:
|
||||
if (_w5500)
|
||||
return _w5500->macAddress();
|
||||
return ETH.macAddress();
|
||||
break;
|
||||
case network_mode::WiFi:
|
||||
|
||||
@ -84,6 +84,30 @@
|
||||
#define CMT_SDIO -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_MOSI
|
||||
#define W5500_MOSI -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_MISO
|
||||
#define W5500_MISO -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_SCLK
|
||||
#define W5500_SCLK -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_CS
|
||||
#define W5500_CS -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_INT
|
||||
#define W5500_INT -1
|
||||
#endif
|
||||
|
||||
#ifndef W5500_RST
|
||||
#define W5500_RST -1
|
||||
#endif
|
||||
|
||||
PinMappingClass PinMapping;
|
||||
|
||||
PinMappingClass::PinMappingClass()
|
||||
@ -103,6 +127,13 @@ PinMappingClass::PinMappingClass()
|
||||
_pinMapping.cmt_gpio3 = CMT_GPIO3;
|
||||
_pinMapping.cmt_sdio = CMT_SDIO;
|
||||
|
||||
_pinMapping.w5500_mosi = W5500_MOSI;
|
||||
_pinMapping.w5500_miso = W5500_MISO;
|
||||
_pinMapping.w5500_sclk = W5500_SCLK;
|
||||
_pinMapping.w5500_cs = W5500_CS;
|
||||
_pinMapping.w5500_int = W5500_INT;
|
||||
_pinMapping.w5500_rst = W5500_RST;
|
||||
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
_pinMapping.eth_enabled = true;
|
||||
#else
|
||||
@ -164,6 +195,13 @@ bool PinMappingClass::init(const String& deviceMapping)
|
||||
_pinMapping.cmt_gpio3 = doc[i]["cmt"]["gpio3"] | CMT_GPIO3;
|
||||
_pinMapping.cmt_sdio = doc[i]["cmt"]["sdio"] | CMT_SDIO;
|
||||
|
||||
_pinMapping.w5500_mosi = doc[i]["w5500"]["mosi"] | W5500_MOSI;
|
||||
_pinMapping.w5500_miso = doc[i]["w5500"]["miso"] | W5500_MISO;
|
||||
_pinMapping.w5500_sclk = doc[i]["w5500"]["sclk"] | W5500_SCLK;
|
||||
_pinMapping.w5500_cs = doc[i]["w5500"]["cs"] | W5500_CS;
|
||||
_pinMapping.w5500_int = doc[i]["w5500"]["int"] | W5500_INT;
|
||||
_pinMapping.w5500_rst = doc[i]["w5500"]["rst"] | W5500_RST;
|
||||
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
_pinMapping.eth_enabled = doc[i]["eth"]["enabled"] | true;
|
||||
#else
|
||||
@ -211,6 +249,16 @@ bool PinMappingClass::isValidCmt2300Config() const
|
||||
&& _pinMapping.cmt_sdio >= 0;
|
||||
}
|
||||
|
||||
bool PinMappingClass::isValidW5500Config() const
|
||||
{
|
||||
return _pinMapping.w5500_mosi >= 0
|
||||
&& _pinMapping.w5500_miso >= 0
|
||||
&& _pinMapping.w5500_sclk >= 0
|
||||
&& _pinMapping.w5500_cs >= 0
|
||||
&& _pinMapping.w5500_int >= 0
|
||||
&& _pinMapping.w5500_rst >= 0;
|
||||
}
|
||||
|
||||
bool PinMappingClass::isValidEthConfig() const
|
||||
{
|
||||
return _pinMapping.eth_enabled;
|
||||
|
||||
107
src/W5500.cpp
Normal file
107
src/W5500.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "W5500.h"
|
||||
|
||||
#include <SpiManager.h>
|
||||
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
// Internal Arduino functions from WiFiGeneric
|
||||
void tcpipInit();
|
||||
void add_esp_interface_netif(esp_interface_t interface, esp_netif_t *esp_netif);
|
||||
|
||||
W5500::W5500(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst) :
|
||||
eth_handle(nullptr),
|
||||
eth_netif(nullptr)
|
||||
{
|
||||
gpio_reset_pin(static_cast<gpio_num_t>(pin_rst));
|
||||
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 0);
|
||||
gpio_set_direction(static_cast<gpio_num_t>(pin_rst), GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_reset_pin(static_cast<gpio_num_t>(pin_cs));
|
||||
gpio_reset_pin(static_cast<gpio_num_t>(pin_int));
|
||||
|
||||
esp_err_t err = gpio_install_isr_service(ARDUINO_ISR_FLAG);
|
||||
if (err != ESP_ERR_INVALID_STATE) // don't raise an error when ISR service is already installed
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
auto bus_config = std::make_shared<SpiBusConfig>(
|
||||
static_cast<gpio_num_t>(pin_mosi),
|
||||
static_cast<gpio_num_t>(pin_miso),
|
||||
static_cast<gpio_num_t>(pin_sclk)
|
||||
);
|
||||
|
||||
spi_device_interface_config_t device_config {
|
||||
.command_bits = 16, // actually address phase
|
||||
.address_bits = 8, // actually command phase
|
||||
.dummy_bits = 0,
|
||||
.mode = 0,
|
||||
.duty_cycle_pos = 0,
|
||||
.cs_ena_pretrans = 0, // only 0 supported
|
||||
.cs_ena_posttrans = 0, // only 0 supported
|
||||
.clock_speed_hz = 20000000, // stable with OpenDTU Fusion shield
|
||||
.input_delay_ns = 0,
|
||||
.spics_io_num = pin_cs,
|
||||
.flags = 0,
|
||||
.queue_size = 20,
|
||||
.pre_cb = nullptr,
|
||||
.post_cb = nullptr,
|
||||
};
|
||||
|
||||
spi_device_handle_t spi = SpiManagerInst.alloc_device("", bus_config, device_config);
|
||||
if (!spi)
|
||||
ESP_ERROR_CHECK(ESP_FAIL);
|
||||
|
||||
// Reset sequence
|
||||
delayMicroseconds(500);
|
||||
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 1);
|
||||
delayMicroseconds(1000);
|
||||
|
||||
// Arduino function to start networking stack if not already started
|
||||
tcpipInit();
|
||||
|
||||
ESP_ERROR_CHECK(tcpip_adapter_set_default_eth_handlers());
|
||||
|
||||
eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(spi);
|
||||
w5500_config.int_gpio_num = pin_int;
|
||||
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
mac_config.rx_task_stack_size = 4096;
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.reset_gpio_num = -1;
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
|
||||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
ESP_ERROR_CHECK(esp_eth_driver_install(ð_config, ð_handle));
|
||||
|
||||
// Configure MAC address
|
||||
uint8_t mac_addr[6];
|
||||
ESP_ERROR_CHECK(esp_read_mac(mac_addr, ESP_MAC_ETH));
|
||||
ESP_ERROR_CHECK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr));
|
||||
|
||||
esp_netif_config_t netif_config = ESP_NETIF_DEFAULT_ETH();
|
||||
eth_netif = esp_netif_new(&netif_config);
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
|
||||
|
||||
// Add to Arduino
|
||||
add_esp_interface_netif(ESP_IF_ETH, eth_netif);
|
||||
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handle));
|
||||
}
|
||||
|
||||
W5500::~W5500() {
|
||||
// TODO(LennartF22): support cleanup at some point?
|
||||
}
|
||||
|
||||
String W5500::macAddress() {
|
||||
uint8_t mac_addr[6] = {};
|
||||
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
|
||||
|
||||
char mac_addr_str[18];
|
||||
snprintf(
|
||||
mac_addr_str, sizeof(mac_addr_str), "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]
|
||||
);
|
||||
return String(mac_addr_str);
|
||||
}
|
||||
@ -50,6 +50,14 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
||||
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
||||
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
||||
|
||||
auto w5500PinObj = curPin["w5500"].to<JsonObject>();
|
||||
w5500PinObj["sclk"] = pin.w5500_sclk;
|
||||
w5500PinObj["mosi"] = pin.w5500_mosi;
|
||||
w5500PinObj["miso"] = pin.w5500_miso;
|
||||
w5500PinObj["cs"] = pin.w5500_cs;
|
||||
w5500PinObj["int"] = pin.w5500_int;
|
||||
w5500PinObj["rst"] = pin.w5500_rst;
|
||||
|
||||
auto ethPinObj = curPin["eth"].to<JsonObject>();
|
||||
ethPinObj["enabled"] = pin.eth_enabled;
|
||||
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
||||
|
||||
@ -26,12 +26,21 @@
|
||||
#include <LittleFS.h>
|
||||
#include <TaskScheduler.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <SpiManager.h>
|
||||
|
||||
#include <driver/uart.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Move all dynamic allocations >512byte to psram (if available)
|
||||
heap_caps_malloc_extmem_enable(512);
|
||||
|
||||
// Initialize SpiManager
|
||||
SpiManagerInst.register_bus(SPI2_HOST);
|
||||
#if SOC_SPI_PERIPH_NUM > 2
|
||||
SpiManagerInst.register_bus(SPI3_HOST);
|
||||
#endif
|
||||
|
||||
// Initialize serial output
|
||||
Serial.begin(SERIAL_BAUDRATE);
|
||||
#if ARDUINO_USB_CDC_ON_BOOT
|
||||
|
||||
Loading…
Reference in New Issue
Block a user