Merge upstream tag 'v24.9.30' into development
This commit is contained in:
commit
185ac36282
@ -1,6 +1,9 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v1",
|
"name": "OpenDTU Fusion v1",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -25,6 +28,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v1 with SSD1306 Display",
|
"name": "OpenDTU Fusion v1 with SSD1306 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -54,6 +60,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v1 with SH1106 Display",
|
"name": "OpenDTU Fusion v1 with SH1106 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -83,6 +92,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v2 with CMT2300A and NRF24",
|
"name": "OpenDTU Fusion v2 with CMT2300A and NRF24",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -115,6 +127,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v2 with CMT2300A, NRF24 and SH1106 Display",
|
"name": "OpenDTU Fusion v2 with CMT2300A, NRF24 and SH1106 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -152,6 +167,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "OpenDTU Fusion v2 with CMT2300A, NRF24 and SSD1306 Display",
|
"name": "OpenDTU Fusion v2 with CMT2300A, NRF24 and SSD1306 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
"nrf24": {
|
"nrf24": {
|
||||||
"miso": 48,
|
"miso": 48,
|
||||||
"mosi": 35,
|
"mosi": 35,
|
||||||
@ -186,5 +204,122 @@
|
|||||||
"data": 2,
|
"data": 2,
|
||||||
"clk": 1
|
"clk": 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OpenDTU Fusion v2 PoE",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
|
"nrf24": {
|
||||||
|
"miso": 48,
|
||||||
|
"mosi": 35,
|
||||||
|
"clk": 36,
|
||||||
|
"irq": 47,
|
||||||
|
"en": 38,
|
||||||
|
"cs": 37
|
||||||
|
},
|
||||||
|
"cmt": {
|
||||||
|
"clk": 6,
|
||||||
|
"cs": 4,
|
||||||
|
"fcs": 21,
|
||||||
|
"sdio": 5,
|
||||||
|
"gpio2": 3,
|
||||||
|
"gpio3": 8
|
||||||
|
},
|
||||||
|
"w5500": {
|
||||||
|
"mosi": 40,
|
||||||
|
"miso": 41,
|
||||||
|
"sclk": 39,
|
||||||
|
"cs": 42,
|
||||||
|
"int": 44,
|
||||||
|
"rst": 43
|
||||||
|
},
|
||||||
|
"led": {
|
||||||
|
"led0": 17,
|
||||||
|
"led1": 18
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"type": 0,
|
||||||
|
"data": 2,
|
||||||
|
"clk": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OpenDTU Fusion v2 PoE with SH1106 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
|
"nrf24": {
|
||||||
|
"miso": 48,
|
||||||
|
"mosi": 35,
|
||||||
|
"clk": 36,
|
||||||
|
"irq": 47,
|
||||||
|
"en": 38,
|
||||||
|
"cs": 37
|
||||||
|
},
|
||||||
|
"cmt": {
|
||||||
|
"clk": 6,
|
||||||
|
"cs": 4,
|
||||||
|
"fcs": 21,
|
||||||
|
"sdio": 5,
|
||||||
|
"gpio2": 3,
|
||||||
|
"gpio3": 8
|
||||||
|
},
|
||||||
|
"w5500": {
|
||||||
|
"mosi": 40,
|
||||||
|
"miso": 41,
|
||||||
|
"sclk": 39,
|
||||||
|
"cs": 42,
|
||||||
|
"int": 44,
|
||||||
|
"rst": 43
|
||||||
|
},
|
||||||
|
"led": {
|
||||||
|
"led0": 17,
|
||||||
|
"led1": 18
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"type": 3,
|
||||||
|
"data": 2,
|
||||||
|
"clk": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "OpenDTU Fusion v2 PoE with SSD1306 Display",
|
||||||
|
"links": [
|
||||||
|
{"name": "Information", "url": "https://github.com/markusdd/OpenDTUFusionDocs"}
|
||||||
|
],
|
||||||
|
"nrf24": {
|
||||||
|
"miso": 48,
|
||||||
|
"mosi": 35,
|
||||||
|
"clk": 36,
|
||||||
|
"irq": 47,
|
||||||
|
"en": 38,
|
||||||
|
"cs": 37
|
||||||
|
},
|
||||||
|
"cmt": {
|
||||||
|
"clk": 6,
|
||||||
|
"cs": 4,
|
||||||
|
"fcs": 21,
|
||||||
|
"sdio": 5,
|
||||||
|
"gpio2": 3,
|
||||||
|
"gpio3": 8
|
||||||
|
},
|
||||||
|
"w5500": {
|
||||||
|
"mosi": 40,
|
||||||
|
"miso": 41,
|
||||||
|
"sclk": 39,
|
||||||
|
"cs": 42,
|
||||||
|
"int": 44,
|
||||||
|
"rst": 43
|
||||||
|
},
|
||||||
|
"led": {
|
||||||
|
"led0": 17,
|
||||||
|
"led1": 18
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"type": 2,
|
||||||
|
"data": 2,
|
||||||
|
"clk": 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "W5500.h"
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
#include <TaskSchedulerDeclarations.h>
|
#include <TaskSchedulerDeclarations.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
@ -23,10 +24,10 @@ enum class network_event {
|
|||||||
NETWORK_EVENT_MAX
|
NETWORK_EVENT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<void(network_event event)> NetworkEventCb;
|
typedef std::function<void(network_event event)> DtuNetworkEventCb;
|
||||||
|
|
||||||
typedef struct NetworkEventCbList {
|
typedef struct NetworkEventCbList {
|
||||||
NetworkEventCb cb;
|
DtuNetworkEventCb cb;
|
||||||
network_event event;
|
network_event event;
|
||||||
|
|
||||||
NetworkEventCbList()
|
NetworkEventCbList()
|
||||||
@ -53,7 +54,7 @@ public:
|
|||||||
bool isConnected() const;
|
bool isConnected() const;
|
||||||
network_mode NetworkMode() const;
|
network_mode NetworkMode() const;
|
||||||
|
|
||||||
bool onEvent(NetworkEventCb cbEvent, const network_event event = network_event::NETWORK_EVENT_MAX);
|
bool onEvent(DtuNetworkEventCb cbEvent, const network_event event = network_event::NETWORK_EVENT_MAX);
|
||||||
void raiseEvent(const network_event event);
|
void raiseEvent(const network_event event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -83,6 +84,7 @@ private:
|
|||||||
bool _ethConnected = false;
|
bool _ethConnected = false;
|
||||||
std::vector<NetworkEventCbList_t> _cbEventList;
|
std::vector<NetworkEventCbList_t> _cbEventList;
|
||||||
bool _lastMdnsEnabled = false;
|
bool _lastMdnsEnabled = false;
|
||||||
|
std::unique_ptr<W5500> _w5500;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetworkSettingsClass NetworkSettings;
|
extern NetworkSettingsClass NetworkSettings;
|
||||||
|
|||||||
@ -26,6 +26,13 @@ struct PinMapping_t {
|
|||||||
int8_t cmt_gpio3;
|
int8_t cmt_gpio3;
|
||||||
int8_t cmt_sdio;
|
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;
|
int8_t eth_phy_addr;
|
||||||
bool eth_enabled;
|
bool eth_enabled;
|
||||||
int eth_power;
|
int eth_power;
|
||||||
@ -72,6 +79,7 @@ public:
|
|||||||
|
|
||||||
bool isValidNrf24Config() const;
|
bool isValidNrf24Config() const;
|
||||||
bool isValidCmt2300Config() const;
|
bool isValidCmt2300Config() const;
|
||||||
|
bool isValidW5500Config() const;
|
||||||
bool isValidEthConfig() const;
|
bool isValidEthConfig() const;
|
||||||
bool isValidHuaweiConfig() const;
|
bool isValidHuaweiConfig() const;
|
||||||
|
|
||||||
|
|||||||
29
include/W5500.h
Normal file
29
include/W5500.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <driver/spi_master.h>
|
||||||
|
#include <esp_eth.h> // required for esp_eth_handle_t
|
||||||
|
#include <esp_netif.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class W5500 {
|
||||||
|
private:
|
||||||
|
explicit W5500(spi_device_handle_t spi, gpio_num_t pin_int);
|
||||||
|
|
||||||
|
public:
|
||||||
|
W5500(const W5500&) = delete;
|
||||||
|
W5500& operator=(const W5500&) = delete;
|
||||||
|
~W5500();
|
||||||
|
|
||||||
|
static std::unique_ptr<W5500> setup(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst);
|
||||||
|
String macAddress();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool connection_check_spi(spi_device_handle_t spi);
|
||||||
|
static bool connection_check_interrupt(gpio_num_t pin_int);
|
||||||
|
|
||||||
|
esp_eth_handle_t eth_handle;
|
||||||
|
esp_netif_t* eth_netif;
|
||||||
|
};
|
||||||
@ -38,6 +38,7 @@ class WebApiClass {
|
|||||||
public:
|
public:
|
||||||
WebApiClass();
|
WebApiClass();
|
||||||
void init(Scheduler& scheduler);
|
void init(Scheduler& scheduler);
|
||||||
|
void reload();
|
||||||
|
|
||||||
static bool checkCredentials(AsyncWebServerRequest* request);
|
static bool checkCredentials(AsyncWebServerRequest* request);
|
||||||
static bool checkCredentialsReadonly(AsyncWebServerRequest* request);
|
static bool checkCredentialsReadonly(AsyncWebServerRequest* request);
|
||||||
|
|||||||
@ -8,9 +8,11 @@ class WebApiWsConsoleClass {
|
|||||||
public:
|
public:
|
||||||
WebApiWsConsoleClass();
|
WebApiWsConsoleClass();
|
||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
void reload();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AsyncWebSocket _ws;
|
AsyncWebSocket _ws;
|
||||||
|
AuthenticationMiddleware _simpleDigestAuth;
|
||||||
|
|
||||||
Task _wsCleanupTask;
|
Task _wsCleanupTask;
|
||||||
void wsCleanupTaskCb();
|
void wsCleanupTaskCb();
|
||||||
|
|||||||
@ -11,6 +11,7 @@ class WebApiWsLiveClass {
|
|||||||
public:
|
public:
|
||||||
WebApiWsLiveClass();
|
WebApiWsLiveClass();
|
||||||
void init(AsyncWebServer& server, Scheduler& scheduler);
|
void init(AsyncWebServer& server, Scheduler& scheduler);
|
||||||
|
void reload();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void generateInverterCommonJsonResponse(JsonObject& root, std::shared_ptr<InverterAbstract> inv);
|
static void generateInverterCommonJsonResponse(JsonObject& root, std::shared_ptr<InverterAbstract> inv);
|
||||||
@ -27,6 +28,7 @@ private:
|
|||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|
||||||
AsyncWebSocket _ws;
|
AsyncWebSocket _ws;
|
||||||
|
AuthenticationMiddleware _simpleDigestAuth;
|
||||||
|
|
||||||
uint32_t _lastPublishOnBatteryFull = 0;
|
uint32_t _lastPublishOnBatteryFull = 0;
|
||||||
uint32_t _lastPublishVictron = 0;
|
uint32_t _lastPublishVictron = 0;
|
||||||
|
|||||||
@ -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>
|
#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);
|
void cmt_spi3_write(const uint8_t addr, const uint8_t dat);
|
||||||
uint8_t cmt_spi3_read(const uint8_t addr);
|
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_write_fifo(const uint8_t* p_buf, const uint16_t len);
|
||||||
void cmt_spi3_read_fifo(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
|
#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"
|
||||||
|
]
|
||||||
|
}
|
||||||
52
lib/SpiManager/src/SpiBus.cpp
Normal file
52
lib/SpiManager/src/SpiBus.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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);
|
||||||
|
}
|
||||||
49
lib/SpiManager/src/SpiBus.h
Normal file
49
lib/SpiManager/src/SpiBus.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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;
|
||||||
|
};
|
||||||
71
lib/SpiManager/src/SpiBusConfig.cpp
Normal file
71
lib/SpiManager/src/SpiBusConfig.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
lib/SpiManager/src/SpiBusConfig.h
Normal file
21
lib/SpiManager/src/SpiBusConfig.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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;
|
||||||
|
};
|
||||||
69
lib/SpiManager/src/SpiCallback.cpp
Normal file
69
lib/SpiManager/src/SpiCallback.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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);
|
||||||
|
}
|
||||||
114
lib/SpiManager/src/SpiManager.cpp
Normal file
114
lib/SpiManager/src/SpiManager.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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;
|
||||||
41
lib/SpiManager/src/SpiManager.h
Normal file
41
lib/SpiManager/src/SpiManager.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#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;
|
||||||
@ -19,7 +19,7 @@ extra_configs =
|
|||||||
custom_ci_action = generic_esp32_4mb_no_ota,generic_esp32_8mb,generic_esp32s3,generic_esp32s3_usb
|
custom_ci_action = generic_esp32_4mb_no_ota,generic_esp32_8mb,generic_esp32s3,generic_esp32s3_usb
|
||||||
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
platform = espressif32@6.8.1
|
platform = espressif32@6.9.0
|
||||||
platform_packages =
|
platform_packages =
|
||||||
platformio/tool-mklittlefs
|
platformio/tool-mklittlefs
|
||||||
|
|
||||||
@ -243,6 +243,7 @@ build_flags = ${env.build_flags}
|
|||||||
-DLED0=17
|
-DLED0=17
|
||||||
-DLED1=18
|
-DLED1=18
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
|
||||||
[env:opendtufusionv2]
|
[env:opendtufusionv2]
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
@ -266,3 +267,32 @@ build_flags = ${env.build_flags}
|
|||||||
-DCMT_SDIO=5
|
-DCMT_SDIO=5
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
|
||||||
|
[env:opendtufusionv2_poe]
|
||||||
|
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 "PinMapping.h"
|
||||||
#include "SunPosition.h"
|
#include "SunPosition.h"
|
||||||
#include <Hoymiles.h>
|
#include <Hoymiles.h>
|
||||||
|
#include <SpiManager.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
|
|
||||||
|
|
||||||
InverterSettingsClass InverterSettings;
|
InverterSettingsClass InverterSettings;
|
||||||
|
|
||||||
@ -44,7 +31,10 @@ void InverterSettingsClass::init(Scheduler& scheduler)
|
|||||||
|
|
||||||
if (PinMapping.isValidNrf24Config() || PinMapping.isValidCmt2300Config()) {
|
if (PinMapping.isValidNrf24Config() || PinMapping.isValidCmt2300Config()) {
|
||||||
if (PinMapping.isValidNrf24Config()) {
|
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);
|
spiClass->begin(pin.nrf24_clk, pin.nrf24_miso, pin.nrf24_mosi, pin.nrf24_cs);
|
||||||
Hoymiles.initNRF(spiClass, pin.nrf24_en, pin.nrf24_irq);
|
Hoymiles.initNRF(spiClass, pin.nrf24_en, pin.nrf24_irq);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
#include "SyslogLogger.h"
|
#include "SyslogLogger.h"
|
||||||
#include "PinMapping.h"
|
#include "PinMapping.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
#include "__compiled_constants.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
#include "__compiled_constants.h"
|
|
||||||
|
|
||||||
NetworkSettingsClass::NetworkSettingsClass()
|
NetworkSettingsClass::NetworkSettingsClass()
|
||||||
: _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&NetworkSettingsClass::loop, this))
|
: _loopTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&NetworkSettingsClass::loop, this))
|
||||||
@ -32,6 +32,23 @@ void NetworkSettingsClass::init(Scheduler& scheduler)
|
|||||||
WiFi.disconnect(true, true);
|
WiFi.disconnect(true, true);
|
||||||
|
|
||||||
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1, _2));
|
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1, _2));
|
||||||
|
|
||||||
|
if (PinMapping.isValidW5500Config()) {
|
||||||
|
PinMapping_t& pin = PinMapping.get();
|
||||||
|
_w5500 = W5500::setup(pin.w5500_mosi, pin.w5500_miso, pin.w5500_sclk, pin.w5500_cs, pin.w5500_int, pin.w5500_rst);
|
||||||
|
if (_w5500)
|
||||||
|
MessageOutput.println("W5500: Connection successful");
|
||||||
|
else
|
||||||
|
MessageOutput.println("W5500: Connection error!!");
|
||||||
|
} else if (PinMapping.isValidEthConfig()) {
|
||||||
|
PinMapping_t& pin = PinMapping.get();
|
||||||
|
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
||||||
|
ETH.begin(pin.eth_phy_addr, pin.eth_power, pin.eth_mdc, pin.eth_mdio, pin.eth_type, pin.eth_clk_mode);
|
||||||
|
#else
|
||||||
|
ETH.begin(pin.eth_type, pin.eth_phy_addr, pin.eth_mdc, pin.eth_mdio, pin.eth_power, pin.eth_clk_mode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
setupMode();
|
setupMode();
|
||||||
|
|
||||||
scheduler.addTask(_loopTask);
|
scheduler.addTask(_loopTask);
|
||||||
@ -100,7 +117,7 @@ void NetworkSettingsClass::NetworkEvent(const WiFiEvent_t event, WiFiEventInfo_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetworkSettingsClass::onEvent(NetworkEventCb cbEvent, const network_event event)
|
bool NetworkSettingsClass::onEvent(DtuNetworkEventCb cbEvent, const network_event event)
|
||||||
{
|
{
|
||||||
if (!cbEvent) {
|
if (!cbEvent) {
|
||||||
return pdFALSE;
|
return pdFALSE;
|
||||||
@ -171,11 +188,6 @@ void NetworkSettingsClass::setupMode()
|
|||||||
WiFi.mode(WIFI_MODE_NULL);
|
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()
|
void NetworkSettingsClass::enableAdminMode()
|
||||||
@ -405,6 +417,9 @@ String NetworkSettingsClass::macAddress() const
|
|||||||
{
|
{
|
||||||
switch (_networkMode) {
|
switch (_networkMode) {
|
||||||
case network_mode::Ethernet:
|
case network_mode::Ethernet:
|
||||||
|
if (_w5500) {
|
||||||
|
return _w5500->macAddress();
|
||||||
|
}
|
||||||
return ETH.macAddress();
|
return ETH.macAddress();
|
||||||
break;
|
break;
|
||||||
case network_mode::WiFi:
|
case network_mode::WiFi:
|
||||||
|
|||||||
@ -84,6 +84,54 @@
|
|||||||
#define CMT_SDIO -1
|
#define CMT_SDIO -1
|
||||||
#endif
|
#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
|
||||||
|
|
||||||
|
#ifndef ETH_PHY_ADDR
|
||||||
|
#define ETH_PHY_ADDR -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETH_PHY_POWER
|
||||||
|
#define ETH_PHY_POWER -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETH_PHY_MDC
|
||||||
|
#define ETH_PHY_MDC -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETH_PHY_MDIO
|
||||||
|
#define ETH_PHY_MDIO -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETH_PHY_TYPE
|
||||||
|
#define ETH_PHY_TYPE ETH_PHY_LAN8720
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ETH_CLK_MODE
|
||||||
|
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef VICTRON_PIN_TX
|
#ifndef VICTRON_PIN_TX
|
||||||
#define VICTRON_PIN_TX -1
|
#define VICTRON_PIN_TX -1
|
||||||
#endif
|
#endif
|
||||||
@ -197,6 +245,13 @@ PinMappingClass::PinMappingClass()
|
|||||||
_pinMapping.cmt_gpio3 = CMT_GPIO3;
|
_pinMapping.cmt_gpio3 = CMT_GPIO3;
|
||||||
_pinMapping.cmt_sdio = CMT_SDIO;
|
_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
|
#ifdef OPENDTU_ETHERNET
|
||||||
_pinMapping.eth_enabled = true;
|
_pinMapping.eth_enabled = true;
|
||||||
#else
|
#else
|
||||||
@ -286,6 +341,13 @@ bool PinMappingClass::init(const String& deviceMapping)
|
|||||||
_pinMapping.cmt_gpio3 = doc[i]["cmt"]["gpio3"] | CMT_GPIO3;
|
_pinMapping.cmt_gpio3 = doc[i]["cmt"]["gpio3"] | CMT_GPIO3;
|
||||||
_pinMapping.cmt_sdio = doc[i]["cmt"]["sdio"] | CMT_SDIO;
|
_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
|
#ifdef OPENDTU_ETHERNET
|
||||||
_pinMapping.eth_enabled = doc[i]["eth"]["enabled"] | true;
|
_pinMapping.eth_enabled = doc[i]["eth"]["enabled"] | true;
|
||||||
#else
|
#else
|
||||||
@ -359,9 +421,21 @@ bool PinMappingClass::isValidCmt2300Config() const
|
|||||||
&& _pinMapping.cmt_sdio >= 0;
|
&& _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
|
bool PinMappingClass::isValidEthConfig() const
|
||||||
{
|
{
|
||||||
return _pinMapping.eth_enabled;
|
return _pinMapping.eth_enabled
|
||||||
|
&& _pinMapping.eth_mdc >= 0
|
||||||
|
&& _pinMapping.eth_mdio >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PinMappingClass::isValidHuaweiConfig() const
|
bool PinMappingClass::isValidHuaweiConfig() const
|
||||||
|
|||||||
153
src/W5500.cpp
Normal file
153
src/W5500.cpp
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Thomas Basler and others
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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(spi_device_handle_t spi, gpio_num_t pin_int)
|
||||||
|
: eth_handle(nullptr)
|
||||||
|
, eth_netif(nullptr)
|
||||||
|
{
|
||||||
|
// 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?
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<W5500> W5500::setup(int8_t pin_mosi, int8_t pin_miso, int8_t pin_sclk, int8_t pin_cs, int8_t pin_int, int8_t pin_rst)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
|
||||||
|
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)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Reset sequence
|
||||||
|
delayMicroseconds(500);
|
||||||
|
gpio_set_level(static_cast<gpio_num_t>(pin_rst), 1);
|
||||||
|
delayMicroseconds(1000);
|
||||||
|
|
||||||
|
if (!connection_check_spi(spi))
|
||||||
|
return nullptr;
|
||||||
|
if (!connection_check_interrupt(static_cast<gpio_num_t>(pin_int)))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Use Arduino functions to temporarily attach interrupt to enable the GPIO ISR service
|
||||||
|
// (if we used ESP-IDF functions, a warning would be printed the first time anyone uses attachInterrupt)
|
||||||
|
attachInterrupt(pin_int, nullptr, FALLING);
|
||||||
|
detachInterrupt(pin_int);
|
||||||
|
|
||||||
|
// Return to default state once again after connection check and temporary interrupt registration
|
||||||
|
gpio_reset_pin(static_cast<gpio_num_t>(pin_int));
|
||||||
|
|
||||||
|
return std::unique_ptr<W5500>(new W5500(spi, static_cast<gpio_num_t>(pin_int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool W5500::connection_check_spi(spi_device_handle_t spi)
|
||||||
|
{
|
||||||
|
spi_transaction_t trans = {
|
||||||
|
.flags = SPI_TRANS_USE_RXDATA,
|
||||||
|
.cmd = 0x0039, // actually address (VERSIONR)
|
||||||
|
.addr = (0b00000 << 3) | (0 << 2) | (0b00 < 0), // actually command (common register, read, VDM)
|
||||||
|
.length = 8,
|
||||||
|
.rxlength = 8,
|
||||||
|
.user = nullptr,
|
||||||
|
.tx_buffer = nullptr,
|
||||||
|
.rx_data = {},
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(spi_device_polling_transmit(spi, &trans));
|
||||||
|
|
||||||
|
// Version number (VERSIONR) is always 0x04
|
||||||
|
return *reinterpret_cast<uint8_t*>(&trans.rx_data) == 0x04;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool W5500::connection_check_interrupt(gpio_num_t pin_int)
|
||||||
|
{
|
||||||
|
gpio_set_direction(pin_int, GPIO_MODE_INPUT);
|
||||||
|
gpio_set_pull_mode(pin_int, GPIO_PULLDOWN_ONLY);
|
||||||
|
int level = gpio_get_level(pin_int);
|
||||||
|
|
||||||
|
// Interrupt line must be high
|
||||||
|
return level == 1;
|
||||||
|
}
|
||||||
@ -47,6 +47,12 @@ void WebApiClass::init(Scheduler& scheduler)
|
|||||||
_server.begin();
|
_server.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebApiClass::reload()
|
||||||
|
{
|
||||||
|
_webApiWsConsole.reload();
|
||||||
|
_webApiWsLive.reload();
|
||||||
|
}
|
||||||
|
|
||||||
bool WebApiClass::checkCredentials(AsyncWebServerRequest* request)
|
bool WebApiClass::checkCredentials(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
CONFIG_T& config = Configuration.get();
|
CONFIG_T& config = Configuration.get();
|
||||||
|
|||||||
@ -50,6 +50,14 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
|||||||
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
cmtPinObj["gpio2"] = pin.cmt_gpio2;
|
||||||
cmtPinObj["gpio3"] = pin.cmt_gpio3;
|
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>();
|
auto ethPinObj = curPin["eth"].to<JsonObject>();
|
||||||
ethPinObj["enabled"] = pin.eth_enabled;
|
ethPinObj["enabled"] = pin.eth_enabled;
|
||||||
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
||||||
|
|||||||
@ -71,6 +71,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
|||||||
WebApi.writeConfig(retMsg);
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
|
||||||
|
|
||||||
|
WebApi.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
||||||
|
|||||||
@ -21,16 +21,30 @@ void WebApiWsConsoleClass::init(AsyncWebServer& server, Scheduler& scheduler)
|
|||||||
|
|
||||||
scheduler.addTask(_wsCleanupTask);
|
scheduler.addTask(_wsCleanupTask);
|
||||||
_wsCleanupTask.enable();
|
_wsCleanupTask.enable();
|
||||||
|
|
||||||
|
_simpleDigestAuth.setUsername(AUTH_USERNAME);
|
||||||
|
_simpleDigestAuth.setRealm("console websocket");
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApiWsConsoleClass::reload()
|
||||||
|
{
|
||||||
|
_ws.removeMiddleware(&_simpleDigestAuth);
|
||||||
|
|
||||||
|
auto const& config = Configuration.get();
|
||||||
|
|
||||||
|
if (config.Security.AllowReadonly) { return; }
|
||||||
|
|
||||||
|
_ws.enable(false);
|
||||||
|
_simpleDigestAuth.setPassword(config.Security.Password);
|
||||||
|
_ws.addMiddleware(&_simpleDigestAuth);
|
||||||
|
_ws.closeAll();
|
||||||
|
_ws.enable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsConsoleClass::wsCleanupTaskCb()
|
void WebApiWsConsoleClass::wsCleanupTaskCb()
|
||||||
{
|
{
|
||||||
// see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
|
// see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
|
||||||
_ws.cleanupClients();
|
_ws.cleanupClients();
|
||||||
|
|
||||||
if (Configuration.get().Security.AllowReadonly) {
|
|
||||||
_ws.setAuthentication("", "");
|
|
||||||
} else {
|
|
||||||
_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,18 +40,31 @@ void WebApiWsLiveClass::init(AsyncWebServer& server, Scheduler& scheduler)
|
|||||||
|
|
||||||
scheduler.addTask(_sendDataTask);
|
scheduler.addTask(_sendDataTask);
|
||||||
_sendDataTask.enable();
|
_sendDataTask.enable();
|
||||||
|
_simpleDigestAuth.setUsername(AUTH_USERNAME);
|
||||||
|
_simpleDigestAuth.setRealm("live websocket");
|
||||||
|
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebApiWsLiveClass::reload()
|
||||||
|
{
|
||||||
|
_ws.removeMiddleware(&_simpleDigestAuth);
|
||||||
|
|
||||||
|
auto const& config = Configuration.get();
|
||||||
|
|
||||||
|
if (config.Security.AllowReadonly) { return; }
|
||||||
|
|
||||||
|
_ws.enable(false);
|
||||||
|
_simpleDigestAuth.setPassword(config.Security.Password);
|
||||||
|
_ws.addMiddleware(&_simpleDigestAuth);
|
||||||
|
_ws.closeAll();
|
||||||
|
_ws.enable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsLiveClass::wsCleanupTaskCb()
|
void WebApiWsLiveClass::wsCleanupTaskCb()
|
||||||
{
|
{
|
||||||
// see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
|
// see: https://github.com/me-no-dev/ESPAsyncWebServer#limiting-the-number-of-web-socket-clients
|
||||||
_ws.cleanupClients();
|
_ws.cleanupClients();
|
||||||
|
|
||||||
if (Configuration.get().Security.AllowReadonly) {
|
|
||||||
_ws.setAuthentication("", "");
|
|
||||||
} else {
|
|
||||||
_ws.setAuthentication(AUTH_USERNAME, Configuration.get().Security.Password);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool all)
|
void WebApiWsLiveClass::generateOnBatteryJsonResponse(JsonVariant& root, bool all)
|
||||||
|
|||||||
@ -38,12 +38,21 @@
|
|||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
#include <TaskScheduler.h>
|
#include <TaskScheduler.h>
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
|
#include <SpiManager.h>
|
||||||
|
|
||||||
|
#include <driver/uart.h>
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// Move all dynamic allocations >512byte to psram (if available)
|
// Move all dynamic allocations >512byte to psram (if available)
|
||||||
heap_caps_malloc_extmem_enable(512);
|
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
|
// Initialize serial output
|
||||||
Serial.begin(SERIAL_BAUDRATE);
|
Serial.begin(SERIAL_BAUDRATE);
|
||||||
#if ARDUINO_USB_CDC_ON_BOOT
|
#if ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"vue": "^3.5.9",
|
"vue": "^3.5.10",
|
||||||
"vue-i18n": "9.13.1",
|
"vue-i18n": "9.13.1",
|
||||||
"vue-router": "^4.4.5"
|
"vue-router": "^4.4.5"
|
||||||
},
|
},
|
||||||
@ -27,7 +27,7 @@
|
|||||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||||
"@tsconfig/node22": "^22.0.0",
|
"@tsconfig/node22": "^22.0.0",
|
||||||
"@types/bootstrap": "^5.2.10",
|
"@types/bootstrap": "^5.2.10",
|
||||||
"@types/node": "^22.7.2",
|
"@types/node": "^22.7.4",
|
||||||
"@types/pulltorefreshjs": "^0.1.7",
|
"@types/pulltorefreshjs": "^0.1.7",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@types/spark-md5": "^3.0.4",
|
"@types/spark-md5": "^3.0.4",
|
||||||
@ -40,11 +40,11 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"pulltorefreshjs": "^0.1.22",
|
"pulltorefreshjs": "^0.1.22",
|
||||||
"sass": "^1.77.6",
|
"sass": "^1.77.6",
|
||||||
"terser": "^5.34.0",
|
"terser": "^5.34.1",
|
||||||
"typescript": "^5.6.2",
|
"typescript": "^5.6.2",
|
||||||
"vite": "^5.4.8",
|
"vite": "^5.4.8",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-css-injected-by-js": "^3.5.1",
|
"vite-plugin-css-injected-by-js": "^3.5.2",
|
||||||
"vue-tsc": "^2.1.6"
|
"vue-tsc": "^2.1.6"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||||
|
|||||||
148
webapp/yarn.lock
148
webapp/yarn.lock
@ -507,10 +507,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||||
|
|
||||||
"@types/node@^22.7.2":
|
"@types/node@^22.7.4":
|
||||||
version "22.7.2"
|
version "22.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.2.tgz#80ed66c0a5025ffa037587fd69a816f29b54e4c7"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.4.tgz#e35d6f48dca3255ce44256ddc05dee1c23353fcc"
|
||||||
integrity sha512-866lXSrpGpgyHBZUa2m9YNWqHDjjM0aBTJlNtYaGEw4rqY/dcD7deRVTbBBAJelfA7oaGDbNftXF/TL/A6RgoA==
|
integrity sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~6.19.2"
|
undici-types "~6.19.2"
|
||||||
|
|
||||||
@ -667,13 +667,13 @@
|
|||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
"@vue/compiler-core@3.5.9":
|
"@vue/compiler-core@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.9.tgz#d51fbfe6c18479b27fe6b1723344ba0832e4aacb"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.10.tgz#dc382e4173c5ad6d309887f5cb02983dfd88cfee"
|
||||||
integrity sha512-KE1sCdwqSKq0CQ/ltg3XnlMTKeinjegIkuFsuq9DKvNPmqLGdmI51ChZdGBBRXIvEYTLm8X/JxOuBQ1HqF/+PA==
|
integrity sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.25.3"
|
"@babel/parser" "^7.25.3"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
entities "^4.5.0"
|
entities "^4.5.0"
|
||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
source-map-js "^1.2.0"
|
source-map-js "^1.2.0"
|
||||||
@ -686,13 +686,13 @@
|
|||||||
"@vue/compiler-core" "3.2.47"
|
"@vue/compiler-core" "3.2.47"
|
||||||
"@vue/shared" "3.2.47"
|
"@vue/shared" "3.2.47"
|
||||||
|
|
||||||
"@vue/compiler-dom@3.5.9":
|
"@vue/compiler-dom@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.9.tgz#6fa2b7e536ae4c416fc2d60b7e9e33b3410eac7a"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz#233c660289ce289a48e8fe759b07b95f607cd98e"
|
||||||
integrity sha512-gEAURwPo902AsJF50vl59VaWR+Cx6cX9SoqLYHu1jq9hDbmQlXvpZyYNIIbxa2JTJ+FD/oBQweVUwuTQv79KTg==
|
integrity sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-core" "3.5.9"
|
"@vue/compiler-core" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
"@vue/compiler-dom@^3.4.0":
|
"@vue/compiler-dom@^3.4.0":
|
||||||
version "3.4.21"
|
version "3.4.21"
|
||||||
@ -702,16 +702,16 @@
|
|||||||
"@vue/compiler-core" "3.4.21"
|
"@vue/compiler-core" "3.4.21"
|
||||||
"@vue/shared" "3.4.21"
|
"@vue/shared" "3.4.21"
|
||||||
|
|
||||||
"@vue/compiler-sfc@3.5.9":
|
"@vue/compiler-sfc@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.9.tgz#020b7654f1fde7c606a49ec4e4d2838e8e1a43c5"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.10.tgz#95e262a5ed836521a5aeee9492cc265ad3f1c787"
|
||||||
integrity sha512-kp9qawcTXakYm0TN6YAwH24IurSywoXh4fWhRbLu0at4UVyo994bhEzJlQn82eiyqtut4GjkQodSfn8drFbpZQ==
|
integrity sha512-to8E1BgpakV7224ZCm8gz1ZRSyjNCAWEplwFMWKlzCdP9DkMKhRRwt0WkCjY7jkzi/Vz3xgbpeig5Pnbly4Tow==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/parser" "^7.25.3"
|
"@babel/parser" "^7.25.3"
|
||||||
"@vue/compiler-core" "3.5.9"
|
"@vue/compiler-core" "3.5.10"
|
||||||
"@vue/compiler-dom" "3.5.9"
|
"@vue/compiler-dom" "3.5.10"
|
||||||
"@vue/compiler-ssr" "3.5.9"
|
"@vue/compiler-ssr" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
magic-string "^0.30.11"
|
magic-string "^0.30.11"
|
||||||
postcss "^8.4.47"
|
postcss "^8.4.47"
|
||||||
@ -741,13 +741,13 @@
|
|||||||
"@vue/compiler-dom" "3.2.47"
|
"@vue/compiler-dom" "3.2.47"
|
||||||
"@vue/shared" "3.2.47"
|
"@vue/shared" "3.2.47"
|
||||||
|
|
||||||
"@vue/compiler-ssr@3.5.9":
|
"@vue/compiler-ssr@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.9.tgz#e30f8e866589392421abcbfc0e0241470f3ca9a6"
|
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.10.tgz#195f83ae7c52174be37fd7a4a0217132c1c0ed11"
|
||||||
integrity sha512-fb1g2mQv32QzIei76rlXRTz08Grw+ZzBXSQfHo4StGFutm/flyebw3dGJkexKwcU3GjX9s5fIGjEv/cjO8j8Yw==
|
integrity sha512-hxP4Y3KImqdtyUKXDRSxKSRkSm1H9fCvhojEYrnaoWhE4w/y8vwWhnosJoPPe2AXm5sU7CSbYYAgkt2ZPhDz+A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.5.9"
|
"@vue/compiler-dom" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
"@vue/compiler-vue2@^2.7.16":
|
"@vue/compiler-vue2@^2.7.16":
|
||||||
version "2.7.16"
|
version "2.7.16"
|
||||||
@ -801,38 +801,38 @@
|
|||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
magic-string "^0.25.7"
|
magic-string "^0.25.7"
|
||||||
|
|
||||||
"@vue/reactivity@3.5.9":
|
"@vue/reactivity@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.9.tgz#8864a55e4c495666f3c679beb8f734489eeb042e"
|
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.10.tgz#81140ef0b05096973356d3c8fc32f48c79940b9c"
|
||||||
integrity sha512-88ApgNZ6yPYpyYkTfXzcbWk6O8+LrPRIpa/U4AdeTzpfRUO+EUt5jemnTBVSlAUNmlYY96xa5feUNEq+BouLog==
|
integrity sha512-kW08v06F6xPSHhid9DJ9YjOGmwNDOsJJQk0ax21wKaUYzzuJGEuoKNU2Ujux8FLMrP7CFJJKsHhXN9l2WOVi2g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
"@vue/runtime-core@3.5.9":
|
"@vue/runtime-core@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.9.tgz#e47f890734039f77dac86328cc059cf8188c5729"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.10.tgz#e902eb2640fa6ab4cc4589af263818a898812668"
|
||||||
integrity sha512-YAeP0zNkjSl5mEc1NxOg9qoAhLNbREElHAhfYbMXT57oF0ixehEEJWBhg2uvVxslCGh23JhpEAyMvJrJHW9WGg==
|
integrity sha512-9Q86I5Qq3swSkFfzrZ+iqEy7Vla325M7S7xc1NwKnRm/qoi1Dauz0rT6mTMmscqx4qz0EDJ1wjB+A36k7rl8mA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/reactivity" "3.5.9"
|
"@vue/reactivity" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
"@vue/runtime-dom@3.5.9":
|
"@vue/runtime-dom@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.9.tgz#088746207f74963d09b31ce7b79add0bf96aa337"
|
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.10.tgz#dca26d7761147373c6929f1370cf2733aa19f3de"
|
||||||
integrity sha512-5Oq/5oenpB9lw94moKvOHqBDEaMSyDmcu2HS8AtAT6/pwdo/t9fR9aVtLh6FzYGGqZR9yRfoHAN6P7goblq1aA==
|
integrity sha512-t3x7ht5qF8ZRi1H4fZqFzyY2j+GTMTDxRheT+i8M9Ph0oepUxoadmbwlFwMoW7RYCpNQLpP2Yx3feKs+fyBdpA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/reactivity" "3.5.9"
|
"@vue/reactivity" "3.5.10"
|
||||||
"@vue/runtime-core" "3.5.9"
|
"@vue/runtime-core" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
csstype "^3.1.3"
|
csstype "^3.1.3"
|
||||||
|
|
||||||
"@vue/server-renderer@3.5.9":
|
"@vue/server-renderer@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.9.tgz#3bf0736001623960d120ef01dee5045fad6efadb"
|
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.10.tgz#90462492c30c8cae499b9149d1b90af2ebfe7599"
|
||||||
integrity sha512-tbuUsZfMWGazR9LXLNiiDSTwkO8K9sLyR70diY+FbQmKmh7236PPz4jkTxymelV8D89IJUGtbfe4VdmpHkmuxg==
|
integrity sha512-IVE97tt2kGKwHNq9yVO0xdh1IvYfZCShvDSy46JIh5OQxP1/EXSpoDqetVmyIzL7CYOWnnmMkVqd7YK2QSWkdw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-ssr" "3.5.9"
|
"@vue/compiler-ssr" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
"@vue/shared@3.2.47":
|
"@vue/shared@3.2.47":
|
||||||
version "3.2.47"
|
version "3.2.47"
|
||||||
@ -844,10 +844,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.21.tgz#de526a9059d0a599f0b429af7037cd0c3ed7d5a1"
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.21.tgz#de526a9059d0a599f0b429af7037cd0c3ed7d5a1"
|
||||||
integrity sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==
|
integrity sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==
|
||||||
|
|
||||||
"@vue/shared@3.5.9":
|
"@vue/shared@3.5.10":
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.9.tgz#713257216ea2cbf4e200cb9ae395c34ae2349385"
|
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.10.tgz#066f7dde31e09d700123e92e63eaa126cda21a17"
|
||||||
integrity sha512-8wiT/m0mnsLhTME0mPgc57jv+4TipRBSAAmheUdYgiOaO6AobZPNOmm87ub4np65VVDgLcWxc+Edc++5Wyz1uA==
|
integrity sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ==
|
||||||
|
|
||||||
"@vue/tsconfig@^0.5.1":
|
"@vue/tsconfig@^0.5.1":
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
@ -2506,10 +2506,10 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||||
|
|
||||||
terser@^5.34.0:
|
terser@^5.34.1:
|
||||||
version "5.34.0"
|
version "5.34.1"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.34.0.tgz#62f2496542290bc6d8bf886edaee7fac158e37e4"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.34.1.tgz#af40386bdbe54af0d063e0670afd55c3105abeb6"
|
||||||
integrity sha512-y5NUX+U9HhVsK/zihZwoq4r9dICLyV2jXGOriDAVOeKhq3LKVjgJbGO90FisozXLlJfvjHqgckGmJFBb9KYoWQ==
|
integrity sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/source-map" "^0.3.3"
|
"@jridgewell/source-map" "^0.3.3"
|
||||||
acorn "^8.8.2"
|
acorn "^8.8.2"
|
||||||
@ -2619,10 +2619,10 @@ vite-plugin-compression@^0.5.1:
|
|||||||
debug "^4.3.3"
|
debug "^4.3.3"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
vite-plugin-css-injected-by-js@^3.5.1:
|
vite-plugin-css-injected-by-js@^3.5.2:
|
||||||
version "3.5.1"
|
version "3.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.1.tgz#b9c568c21b131d08e31aa6d368ee39c9d6c1b6c1"
|
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz#1f75d16ad5c05b6b49bf18018099a189ec2e46ad"
|
||||||
integrity sha512-9ioqwDuEBxW55gNoWFEDhfLTrVKXEEZgl5adhWmmqa88EQGKfTmexy4v1Rh0pAS6RhKQs2bUYQArprB32JpUZQ==
|
integrity sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ==
|
||||||
|
|
||||||
vite@^5.4.8:
|
vite@^5.4.8:
|
||||||
version "5.4.8"
|
version "5.4.8"
|
||||||
@ -2691,16 +2691,16 @@ vue-tsc@^2.1.6:
|
|||||||
"@vue/language-core" "2.1.6"
|
"@vue/language-core" "2.1.6"
|
||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
|
|
||||||
vue@^3.5.9:
|
vue@^3.5.10:
|
||||||
version "3.5.9"
|
version "3.5.10"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.9.tgz#a065952d7a7c0e2cbfec8e016582b055ab984357"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.10.tgz#14be9d4655e07be8d5e8295d017815ed14337f96"
|
||||||
integrity sha512-nHzQhZ5cjFKynAY2beAm7XtJ5C13VKAFTLTgRYXy+Id1KEKBeiK6hO2RcW1hUjdbHMadz1YzxyHgQigOC54wug==
|
integrity sha512-Vy2kmJwHPlouC/tSnIgXVg03SG+9wSqT1xu1Vehc+ChsXsRd7jLkKgMltVEFOzUdBr3uFwBCG+41LJtfAcBRng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vue/compiler-dom" "3.5.9"
|
"@vue/compiler-dom" "3.5.10"
|
||||||
"@vue/compiler-sfc" "3.5.9"
|
"@vue/compiler-sfc" "3.5.10"
|
||||||
"@vue/runtime-dom" "3.5.9"
|
"@vue/runtime-dom" "3.5.10"
|
||||||
"@vue/server-renderer" "3.5.9"
|
"@vue/server-renderer" "3.5.10"
|
||||||
"@vue/shared" "3.5.9"
|
"@vue/shared" "3.5.10"
|
||||||
|
|
||||||
webpack-sources@^3.2.3:
|
webpack-sources@^3.2.3:
|
||||||
version "3.2.3"
|
version "3.2.3"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user