mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-08-14 07:19:46 +00:00
initial ch390 ethernet support for thinknode m7 companion
This commit is contained in:
@@ -48,6 +48,9 @@ static uint32_t _atoi(const char* sp) {
|
||||
#include <helpers/ArduinoSerialInterface.h>
|
||||
ArduinoSerialInterface serial_interface;
|
||||
HardwareSerial companion_serial(1);
|
||||
#elif defined(ETHERNET_ENABLED)
|
||||
#include <helpers/ethernet/Ethernet.h>
|
||||
ETHERNET_CLASS serial_interface;
|
||||
#else
|
||||
#include <helpers/ArduinoSerialInterface.h>
|
||||
ArduinoSerialInterface serial_interface;
|
||||
@@ -240,6 +243,8 @@ void setup() {
|
||||
companion_serial.setPins(SERIAL_RX, SERIAL_TX);
|
||||
companion_serial.begin(115200);
|
||||
serial_interface.begin(companion_serial);
|
||||
#elif defined(ETHERNET_ENABLED)
|
||||
serial_interface.begin();
|
||||
#else
|
||||
serial_interface.begin(Serial);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(ETHERNET_ENABLED)
|
||||
#if defined(ETHERNET_USE_CH390)
|
||||
#include "helpers/ethernet/ch390/CH390EthernetInterface.h"
|
||||
#else
|
||||
#error "ETHERNET_ENABLED is defined, but no specific driver flag (e.g. ETHERNET_USE_CH390) was provided!"
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "CH390EthernetInterface.h"
|
||||
|
||||
#define RECV_STATE_IDLE 0
|
||||
#define RECV_STATE_HDR_FOUND 1
|
||||
#define RECV_STATE_LEN1_FOUND 2
|
||||
#define RECV_STATE_LEN2_FOUND 3
|
||||
|
||||
bool CH390EthernetInterface::begin() {
|
||||
ETHERNET_DEBUG_PRINTLN("Ethernet initializing");
|
||||
|
||||
// Init CH390
|
||||
ch390_config_t config = CH390_DEFAULT_CONFIG();
|
||||
config.spi_miso_gpio = ETH_MISO_PIN;
|
||||
config.spi_mosi_gpio = ETH_MOSI_PIN;
|
||||
config.spi_sck_gpio = ETH_SCLK_PIN;
|
||||
config.spi_cs_gpio = ETH_CS_PIN;
|
||||
config.int_gpio = ETH_INT_PIN;
|
||||
if (!CH390.begin(config)) {
|
||||
ETHERNET_DEBUG_PRINTLN("Failed to initialize CH390 hardware.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup Static IP if build flags are present
|
||||
#if defined(ETHERNET_STATIC_IP) && defined(ETHERNET_STATIC_GATEWAY) && defined(ETHERNET_STATIC_SUBNET)
|
||||
IPAddress ip(ETHERNET_STATIC_IP);
|
||||
IPAddress gw(ETHERNET_STATIC_GATEWAY);
|
||||
IPAddress sn(ETHERNET_STATIC_SUBNET);
|
||||
CH390.config(ip, gw, sn);
|
||||
#endif
|
||||
|
||||
// Start Server
|
||||
server.begin();
|
||||
ETHERNET_DEBUG_PRINTLN("listening on TCP port: %d", ETHERNET_TCP_PORT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CH390EthernetInterface::enable() {
|
||||
if (_isEnabled) return;
|
||||
_isEnabled = true;
|
||||
clearBuffers();
|
||||
}
|
||||
|
||||
void CH390EthernetInterface::disable() {
|
||||
_isEnabled = false;
|
||||
}
|
||||
|
||||
size_t CH390EthernetInterface::writeFrame(const uint8_t src[], size_t len) {
|
||||
if (len > MAX_FRAME_SIZE) {
|
||||
ETHERNET_DEBUG_PRINTLN("writeFrame(), frame too big, len=%d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (deviceConnected && len > 0) {
|
||||
if (send_queue_len >= FRAME_QUEUE_SIZE) {
|
||||
ETHERNET_DEBUG_PRINTLN("writeFrame(), send_queue is full!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
send_queue[send_queue_len].len = len; // add to send queue
|
||||
memcpy(send_queue[send_queue_len].buf, src, len);
|
||||
send_queue_len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CH390EthernetInterface::isWriteBusy() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t CH390EthernetInterface::checkRecvFrame(uint8_t dest[]) {
|
||||
if (server.hasClient()) {
|
||||
auto newClient = server.available();
|
||||
if (newClient) {
|
||||
IPAddress new_ip = newClient.remoteIP();
|
||||
uint16_t new_port = newClient.remotePort();
|
||||
ETHERNET_DEBUG_PRINTLN(
|
||||
"New client accepted %u.%u.%u.%u:%u",
|
||||
new_ip[0], new_ip[1], new_ip[2], new_ip[3], new_port);
|
||||
|
||||
deviceConnected = false;
|
||||
if (client) {
|
||||
ETHERNET_DEBUG_PRINTLN("Closing previous client");
|
||||
client.stop();
|
||||
}
|
||||
_state = RECV_STATE_IDLE;
|
||||
_frame_len = 0;
|
||||
_rx_len = 0;
|
||||
client = newClient;
|
||||
ETHERNET_DEBUG_PRINTLN("Switched to new client");
|
||||
}
|
||||
}
|
||||
|
||||
if (client.connected()) {
|
||||
if (!deviceConnected) {
|
||||
ETHERNET_DEBUG_PRINTLN(
|
||||
"Got connection %u.%u.%u.%u:%u",
|
||||
client.remoteIP()[0],
|
||||
client.remoteIP()[1],
|
||||
client.remoteIP()[2],
|
||||
client.remoteIP()[3],
|
||||
client.remotePort());
|
||||
deviceConnected = true;
|
||||
}
|
||||
} else {
|
||||
if (deviceConnected) {
|
||||
deviceConnected = false;
|
||||
ETHERNET_DEBUG_PRINTLN("Disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceConnected) {
|
||||
if (send_queue_len > 0) { // first, check send queue
|
||||
|
||||
_last_write = millis();
|
||||
int len = send_queue[0].len;
|
||||
|
||||
#if ETHERNET_RAW_LINE
|
||||
ETHERNET_DEBUG_PRINTLN("TX line len=%d", len);
|
||||
client.write(send_queue[0].buf, len);
|
||||
client.write("\r\n", 2);
|
||||
#else
|
||||
uint8_t pkt[3+len]; // use same header as serial interface so client can delimit frames
|
||||
pkt[0] = '>';
|
||||
pkt[1] = (len & 0xFF); // LSB
|
||||
pkt[2] = (len >> 8); // MSB
|
||||
memcpy(&pkt[3], send_queue[0].buf, send_queue[0].len);
|
||||
ETHERNET_DEBUG_PRINTLN("Sending frame len=%d", len);
|
||||
#if ETHERNET_DEBUG_LOGGING && ARDUINO
|
||||
ETHERNET_DEBUG_PRINTLN("TX frame len=%d", len);
|
||||
#endif
|
||||
client.write(pkt, 3 + len);
|
||||
#endif
|
||||
send_queue_len--;
|
||||
for (int i = 0; i < send_queue_len; i++) { // delete top item from queue
|
||||
send_queue[i] = send_queue[i + 1];
|
||||
}
|
||||
} else {
|
||||
while (client.available()) {
|
||||
int c = client.read();
|
||||
if (c < 0) break;
|
||||
|
||||
#if ETHERNET_RAW_LINE
|
||||
if (c == '\r' || c == '\n') {
|
||||
if (_rx_len == 0) {
|
||||
continue;
|
||||
}
|
||||
uint16_t out_len = _rx_len;
|
||||
if (out_len > MAX_FRAME_SIZE) out_len = MAX_FRAME_SIZE;
|
||||
memcpy(dest, _rx_buf, out_len);
|
||||
_rx_len = 0;
|
||||
return out_len;
|
||||
}
|
||||
if (_rx_len < MAX_FRAME_SIZE) {
|
||||
_rx_buf[_rx_len] = (uint8_t)c;
|
||||
_rx_len++;
|
||||
}
|
||||
#else
|
||||
switch (_state) {
|
||||
case RECV_STATE_IDLE:
|
||||
if (c == '<') {
|
||||
_state = RECV_STATE_HDR_FOUND;
|
||||
}
|
||||
break;
|
||||
case RECV_STATE_HDR_FOUND:
|
||||
_frame_len = (uint8_t)c;
|
||||
_state = RECV_STATE_LEN1_FOUND;
|
||||
break;
|
||||
case RECV_STATE_LEN1_FOUND:
|
||||
_frame_len |= ((uint16_t)c) << 8;
|
||||
_rx_len = 0;
|
||||
_state = _frame_len > 0 ? RECV_STATE_LEN2_FOUND : RECV_STATE_IDLE;
|
||||
break;
|
||||
default:
|
||||
if (_rx_len < MAX_FRAME_SIZE) {
|
||||
_rx_buf[_rx_len] = (uint8_t)c;
|
||||
}
|
||||
_rx_len++;
|
||||
if (_rx_len >= _frame_len) {
|
||||
if (_frame_len > MAX_FRAME_SIZE) {
|
||||
_frame_len = MAX_FRAME_SIZE;
|
||||
}
|
||||
#if ETHERNET_DEBUG_LOGGING && ARDUINO
|
||||
ETHERNET_DEBUG_PRINTLN("RX frame len=%d", _frame_len);
|
||||
#endif
|
||||
memcpy(dest, _rx_buf, _frame_len);
|
||||
_state = RECV_STATE_IDLE;
|
||||
return _frame_len;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CH390EthernetInterface::isConnected() const {
|
||||
return deviceConnected;
|
||||
}
|
||||
|
||||
void CH390EthernetInterface::loop() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../BaseSerialInterface.h"
|
||||
#include <SPI.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiServer.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP32_CH390.h>
|
||||
|
||||
#ifndef ETHERNET_TCP_PORT
|
||||
#define ETHERNET_TCP_PORT 5000
|
||||
#endif
|
||||
// define ETHERNET_RAW_LINE=1 to use raw line-based CLI instead of framed packets
|
||||
|
||||
class CH390EthernetInterface : public BaseSerialInterface {
|
||||
bool deviceConnected;
|
||||
bool _isEnabled;
|
||||
unsigned long _last_write;
|
||||
uint8_t _state;
|
||||
uint16_t _frame_len;
|
||||
uint16_t _rx_len;
|
||||
uint8_t _rx_buf[MAX_FRAME_SIZE];
|
||||
|
||||
WiFiServer server;
|
||||
WiFiClient client;
|
||||
|
||||
struct Frame {
|
||||
uint8_t len;
|
||||
uint8_t buf[MAX_FRAME_SIZE];
|
||||
};
|
||||
|
||||
#define FRAME_QUEUE_SIZE 4
|
||||
int send_queue_len;
|
||||
Frame send_queue[FRAME_QUEUE_SIZE];
|
||||
|
||||
void clearBuffers() {
|
||||
send_queue_len = 0;
|
||||
_state = 0;
|
||||
_frame_len = 0;
|
||||
_rx_len = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
CH390EthernetInterface() : server(ETHERNET_TCP_PORT) {
|
||||
deviceConnected = false;
|
||||
_isEnabled = false;
|
||||
_last_write = 0;
|
||||
send_queue_len = 0;
|
||||
_state = 0;
|
||||
_frame_len = 0;
|
||||
_rx_len = 0;
|
||||
}
|
||||
bool begin();
|
||||
void loop();
|
||||
|
||||
// BaseSerialInterface methods
|
||||
void enable() override;
|
||||
void disable() override;
|
||||
bool isEnabled() const override { return _isEnabled; }
|
||||
|
||||
bool isConnected() const override;
|
||||
bool isWriteBusy() const override;
|
||||
|
||||
size_t writeFrame(const uint8_t src[], size_t len) override;
|
||||
size_t checkRecvFrame(uint8_t dest[]) override;
|
||||
};
|
||||
|
||||
|
||||
#if ETHERNET_DEBUG_LOGGING && ARDUINO
|
||||
#include <Arduino.h>
|
||||
#define ETHERNET_DEBUG_PRINT(F, ...) Serial.printf("ETH: " F, ##__VA_ARGS__)
|
||||
#define ETHERNET_DEBUG_PRINTLN(F, ...) Serial.printf("ETH: " F "\n", ##__VA_ARGS__)
|
||||
#define ETHERNET_DEBUG_PRINT_IP(name, ip) Serial.printf(name ": %u.%u.%u.%u" "\n", ip[0], ip[1], ip[2], ip[3])
|
||||
#else
|
||||
#define ETHERNET_DEBUG_PRINT(...) {}
|
||||
#define ETHERNET_DEBUG_PRINTLN(...) {}
|
||||
#define ETHERNET_DEBUG_PRINT_IP(...) {}
|
||||
#endif
|
||||
@@ -34,6 +34,22 @@ build_src_filter = ${esp32_base.build_src_filter}
|
||||
lib_deps = ${esp32_base.lib_deps}
|
||||
stevemarple/MicroNMEA @ ^2.0.6
|
||||
|
||||
[ThinkNode_M7_ethernet]
|
||||
build_flags =
|
||||
-D ETHERNET_ENABLED
|
||||
-D ETHERNET_USE_CH390
|
||||
-D ETHERNET_CLASS=CH390EthernetInterface
|
||||
-D ETH_MISO_PIN=14
|
||||
-D ETH_MOSI_PIN=48
|
||||
-D ETH_SCLK_PIN=47
|
||||
-D ETH_CS_PIN=21
|
||||
-D ETH_INT_PIN=45
|
||||
-D ETHERNET_DEBUG_LOGGING=1
|
||||
build_src_filter =
|
||||
+<helpers/ethernet/ch390/>
|
||||
lib_deps =
|
||||
https://github.com/liamcottle/ESP32-CH390.git#47b401f1de546118b03c18b5689dedec45871f2d
|
||||
|
||||
[env:ThinkNode_M7_repeater]
|
||||
extends = ThinkNode_M7
|
||||
build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
@@ -130,6 +146,26 @@ lib_deps =
|
||||
${ThinkNode_M7.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:ThinkNode_M7_companion_radio_ethernet]
|
||||
extends = ThinkNode_M7
|
||||
build_flags =
|
||||
${ThinkNode_M7.build_flags}
|
||||
${ThinkNode_M7_ethernet.build_flags}
|
||||
-I examples/companion_radio/ui-orig
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D DISPLAY_CLASS=NullDisplayDriver
|
||||
-D OFFLINE_QUEUE_SIZE=256
|
||||
build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
${ThinkNode_M7_ethernet.build_src_filter}
|
||||
+<helpers/esp32/*.cpp>
|
||||
+<helpers/ui/MomentaryButton.cpp>
|
||||
+<../examples/companion_radio/*.cpp>
|
||||
+<../examples/companion_radio/ui-orig/*.cpp>
|
||||
lib_deps = ${ThinkNode_M7.lib_deps}
|
||||
${ThinkNode_M7_ethernet.lib_deps}
|
||||
densaugeo/base64 @ ~1.4.0
|
||||
|
||||
[env:ThinkNode_M7_kiss_modem]
|
||||
extends = ThinkNode_M7
|
||||
build_src_filter = ${ThinkNode_M7.build_src_filter}
|
||||
|
||||
Reference in New Issue
Block a user