Skip to content

Commit

Permalink
Implement W5500 support
Browse files Browse the repository at this point in the history
  • Loading branch information
LennartF22 committed Sep 24, 2024
1 parent 992e174 commit 851190d
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 6 deletions.
2 changes: 2 additions & 0 deletions include/NetworkSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <TaskSchedulerDeclarations.h>
#include <WiFi.h>
#include <vector>
#include "W5500.h"

enum class network_mode {
WiFi,
Expand Down Expand Up @@ -83,6 +84,7 @@ class NetworkSettingsClass {
bool _ethConnected = false;
std::vector<NetworkEventCbList_t> _cbEventList;
bool _lastMdnsEnabled = false;
std::unique_ptr<W5500> _w5500;
};

extern NetworkSettingsClass NetworkSettings;
10 changes: 9 additions & 1 deletion include/PinMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -49,10 +56,11 @@ class PinMappingClass {

bool isValidNrf24Config() const;
bool isValidCmt2300Config() const;
bool isValidW5500Config() const;
bool isValidEthConfig() const;

private:
PinMapping_t _pinMapping;
};

extern PinMappingClass PinMapping;
extern PinMappingClass PinMapping;
19 changes: 19 additions & 0 deletions include/W5500.h
Original file line number Diff line number Diff line change
@@ -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;
};
30 changes: 30 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,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
Expand All @@ -250,3 +251,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
16 changes: 11 additions & 5 deletions src/NetworkSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -169,11 +178,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()
Expand Down Expand Up @@ -401,6 +405,8 @@ String NetworkSettingsClass::macAddress() const
{
switch (_networkMode) {
case network_mode::Ethernet:
if (_w5500)
return _w5500->macAddress();
return ETH.macAddress();
break;
case network_mode::WiFi:
Expand Down
48 changes: 48 additions & 0 deletions src/PinMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
119 changes: 119 additions & 0 deletions src/W5500.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include "W5500.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_mosi));
gpio_reset_pin(static_cast<gpio_num_t>(pin_miso));
gpio_reset_pin(static_cast<gpio_num_t>(pin_sclk));
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);

spi_bus_config_t bus_config {
.mosi_io_num = pin_mosi,
.miso_io_num = pin_miso,
.sclk_io_num = pin_sclk,
.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 = 0, // uses default value internally
.flags = 0,
.intr_flags = 0,
};

ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &bus_config, SPI_DMA_CH_AUTO));

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;
ESP_ERROR_CHECK(spi_bus_add_device(SPI3_HOST, &device_config, &spi));

// 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(&eth_config, &eth_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);
}
8 changes: 8 additions & 0 deletions src/WebApi_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 851190d

Please sign in to comment.