Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SpiManager and support W5500 #2306

Merged
merged 11 commits into from
Sep 27, 2024
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;
};
142 changes: 0 additions & 142 deletions lib/CMT2300a/cmt_spi3.c

This file was deleted.

155 changes: 155 additions & 0 deletions lib/CMT2300a/cmt_spi3.cpp
Original file line number Diff line number Diff line change
@@ -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();
}
10 changes: 9 additions & 1 deletion lib/CMT2300a/cmt_spi3.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@

#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);

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 changes: 13 additions & 0 deletions lib/SpiManager/library.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
Loading