changing app
This commit is contained in:
Vendored
+3
-5
@@ -2,17 +2,15 @@
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ESP-IDF",
|
||||
"compileCommands": "/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build/compile_commands.json",
|
||||
"compilerPath": "C:\\Espressif\\tools\\xtensa-esp-elf\\esp-14.2.0_20250730\\xtensa-esp-elf\\bin\\xtensa-esp32-elf-gcc.exe",
|
||||
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
||||
"intelliSenseMode": "gcc-x86",
|
||||
"includePath": [
|
||||
"${config:idf.espIdfPath}/components/**",
|
||||
"${config:idf.espIdfPathWin}/components/**",
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/core/**"
|
||||
],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${config:idf.espIdfPath}/components",
|
||||
"${config:idf.espIdfPathWin}/components",
|
||||
"${workspaceFolder}",
|
||||
"${workspaceFolder}/core"
|
||||
],
|
||||
|
||||
Vendored
-5
@@ -5,11 +5,6 @@
|
||||
"type": "gdbtarget",
|
||||
"request": "attach",
|
||||
"name": "Eclipse CDT GDB Adapter"
|
||||
},
|
||||
{
|
||||
"type": "espidf",
|
||||
"name": "Launch",
|
||||
"request": "launch"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+30
-6
@@ -4,16 +4,19 @@
|
||||
"idf.customExtraVars": {
|
||||
"OPENOCD_SCRIPTS": "/home/gustice/tools/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/share/openocd/scripts/",
|
||||
"IDF_CCACHE_ENABLE": "1",
|
||||
"ESP_ROM_ELF_DIR": "/home/gustice/tools/.espressif/tools/esp-rom-elfs/20241011/"
|
||||
"ESP_ROM_ELF_DIR": "/home/gustice/tools/.espressif/tools/esp-rom-elfs/20241011/",
|
||||
"IDF_TARGET": "esp32"
|
||||
},
|
||||
"idf.openOcdConfigs": [
|
||||
"board/esp32c6-builtin.cfg"
|
||||
"interface/ftdi/esp_ftdi.cfg",
|
||||
"target/esp32.cfg"
|
||||
// "board/esp32-wrover-kit-3.3v.cfg"
|
||||
],
|
||||
"idf.flashType": "UART",
|
||||
"C_Cpp.autoAddFileAssociations": false,
|
||||
"project.deviceIp": "172.16.17.56",
|
||||
"sonarlint.pathToCompileCommands": "${workspaceFolder}\\build\\compile_commands.json",
|
||||
"idf.port": "/dev/ttyACM0",
|
||||
"idf.portWin": "COM4",
|
||||
"cmake.showSystemKits": false,
|
||||
"cmake.defaultVariants": {
|
||||
"buildType": {
|
||||
@@ -33,12 +36,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"clangd.path": "/home/gustice/.espressif/tools/esp-clang/esp-18.1.2_20240912/esp-clang/bin/clangd",
|
||||
"clangd.path": "C:\\Espressif\\tools\\esp-clang\\esp-18.1.2_20240912\\esp-clang\\bin\\clangd.exe",
|
||||
"clangd.arguments": [
|
||||
"--background-index",
|
||||
"--query-driver=/home/gustice/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20241119/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
|
||||
"--compile-commands-dir=/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build"
|
||||
"--query-driver=**",
|
||||
"--compile-commands-dir=c:\\Users\\Jakob\\hello_world\\build"
|
||||
],
|
||||
"cmake.configureOnOpen": false,
|
||||
"cmake.configureOnEdit": false,
|
||||
"cmake.automaticReconfigure": false,
|
||||
"cmake.autoSelectActiveFolder": false,
|
||||
"cmake.debugConfig": {
|
||||
"setupCommands": [
|
||||
{
|
||||
@@ -54,5 +61,22 @@
|
||||
"text": "skip namespace std"
|
||||
}
|
||||
]
|
||||
},
|
||||
"cmake.options.advanced": {
|
||||
"build": {
|
||||
"statusBarVisibility": "inherit",
|
||||
"inheritDefault": "hidden"
|
||||
},
|
||||
"launch": {
|
||||
"statusBarVisibility": "inherit",
|
||||
"inheritDefault": "hidden"
|
||||
},
|
||||
"debug": {
|
||||
"statusBarVisibility": "inherit",
|
||||
"inheritDefault": "hidden"
|
||||
}
|
||||
},
|
||||
|
||||
"idf.currentSetup": "C:\\esp\\v5.4.3\\esp-idf",
|
||||
"idf.port": "COM4"
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ else()
|
||||
else()
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
"core/components"
|
||||
"core/components_extern"
|
||||
"core/managed_components"
|
||||
)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
@@ -159,7 +159,7 @@ int SProcessor::sendOvertakingMessage(int msgNumRec) {
|
||||
|
||||
if (msgNum == msgNumNext) {
|
||||
msgNumRec = msgNum;
|
||||
mInternCallbacks.parseMessage(*overtakingMessage);
|
||||
parseMessage(*overtakingMessage);
|
||||
mOvertakingMessages.erase(it);
|
||||
it = mOvertakingMessages.begin();
|
||||
} else {
|
||||
|
||||
+1
-1
Submodule core updated: 37e288c012...e584259b31
+3
-3
@@ -12,10 +12,10 @@ dependencies:
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.4.1
|
||||
version: 5.4.3
|
||||
direct_dependencies:
|
||||
- frozen-eye/esp_telnet
|
||||
- idf
|
||||
manifest_hash: 8e2a908d16408b9cafcd4c4b109b841acfca6e660d2500fc6d1362f0f143376c
|
||||
target: esp32c6
|
||||
manifest_hash: f3dbb2beffe19f6e4fa3818b79ea2bfac679eaaf47effee78f152007a2be54f5
|
||||
target: esp32
|
||||
version: 2.0.0
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
idf_component_register(SRCS "watchMain.cpp"
|
||||
idf_component_register(SRCS "lightsMain.cpp"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
+4
-22
@@ -13,36 +13,18 @@ struct {
|
||||
// MQTT Topics
|
||||
struct {
|
||||
// Subscriptions:
|
||||
const char *moveTo = /* <mqttPrefix>/ */ "watch/moveTo";
|
||||
const char *startShuffle = /* <mqttPrefix>/ */ "watch/startShuffle";
|
||||
const char *startShow = /* <mqttPrefix>/ */ "elixirLights/startShow";
|
||||
// Publishes:
|
||||
const char *inPosition = /* <mqttPrefix>/ */ "watch/inPosition";
|
||||
const char *changingPosition = /* <mqttPrefix>/ */ "watch/changingPosition";
|
||||
const char *showDone = /* <mqttPrefix>/ */ "elixirLights/showDone";
|
||||
} MqttTopics;
|
||||
|
||||
struct {
|
||||
const char *expectedServer = "";
|
||||
struct {
|
||||
const char *group = "CatasWatchMovement";
|
||||
const char *startShuffle = "ActionStartShuffle";
|
||||
const char *moveToX[6] = {
|
||||
"ActionMoveTo1",
|
||||
"ActionMoveTo2",
|
||||
"ActionMoveTo3",
|
||||
"ActionMoveTo4",
|
||||
"ActionMoveTo5",
|
||||
"ActionMoveTo6",
|
||||
};
|
||||
const char *startShow = "StartShow";
|
||||
} Provided;
|
||||
struct {
|
||||
const char *changingPos = "ChangingPositionScene";
|
||||
const char *inPosX[6] = {
|
||||
"InPosition1Scene",
|
||||
"InPosition2Scene",
|
||||
"InPosition3Scene",
|
||||
"InPosition4Scene",
|
||||
"InPosition5Scene",
|
||||
"InPosition6Scene",
|
||||
};
|
||||
const char *showDone = "ShowDone";
|
||||
} Expected;
|
||||
} SpitTypes;
|
||||
@@ -17,15 +17,12 @@
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_private/wifi.h"
|
||||
#include "ethernet_init.h"
|
||||
#include "ethernet.hpp"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_eth.h"
|
||||
|
||||
// Component header
|
||||
#include "Task.hpp"
|
||||
#include "pwmExpanderPca9685.hpp"
|
||||
#include "stepperDrv.hpp"
|
||||
#include "stepperMotor.hpp"
|
||||
#include "cliWrapper.hpp"
|
||||
#include "udpSockets.hpp"
|
||||
#include "tcpSockets.hpp"
|
||||
@@ -49,3 +46,4 @@
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -0,0 +1,651 @@
|
||||
/**
|
||||
* @author Gustice
|
||||
* @brief ChaosWatch Application
|
||||
*/
|
||||
|
||||
// using Elite2D-EXMU
|
||||
// Gledopto Series With Ethernet
|
||||
// { // 13
|
||||
// 1, // eth_address,
|
||||
// 5, // eth_power,
|
||||
// 23, // eth_mdc,
|
||||
// 33, // eth_mdio,
|
||||
// ETH_PHY_LAN8720, // eth_type,
|
||||
// ETH_CLOCK_GPIO0_IN // eth_clk_mode as input
|
||||
// },
|
||||
|
||||
#include "config.hpp"
|
||||
#include "lighsMain.hpp"
|
||||
|
||||
using namespace spit;
|
||||
using namespace std;
|
||||
|
||||
string ClientName = "LeoLightsDev";
|
||||
string ProjectName = "LeoLightsProj";
|
||||
|
||||
extern "C" { // This switch allows the ROS C-implementation to find this main
|
||||
void app_main(void);
|
||||
}
|
||||
|
||||
struct DeviceState {
|
||||
Color color{0x80, 0x80, 0x80};
|
||||
vector<uint8_t> counts;
|
||||
vector<uint8_t> times;
|
||||
};
|
||||
struct StartCommand {
|
||||
uint8_t pos; // 0 for none / Valid indexes 1 .. 6
|
||||
};
|
||||
static fos::Queue<StartCommand> commandQ(2);
|
||||
|
||||
DeviceState State;
|
||||
static const char* TAG = "Light";
|
||||
|
||||
unique_ptr<Cli> pShell;
|
||||
|
||||
void onCommand(string name, Cli::CArgs args) {
|
||||
ESP_LOGI(TAG, "Invoking: %s", name.c_str());
|
||||
}
|
||||
|
||||
void startUpdate(Cli::CArgs args) {
|
||||
ESP_LOGI(TAG, "Invoking Update");
|
||||
if (args.size() != 1) {
|
||||
pShell->writeLine("Need URL to application");
|
||||
return;
|
||||
}
|
||||
// @ToDo: Start Update here
|
||||
}
|
||||
|
||||
void getConfig(Cli::CArgs args) {
|
||||
if (args.size() != 1) {
|
||||
pShell->writeLine("Needs string key for query");
|
||||
return;
|
||||
}
|
||||
auto key = args[0];
|
||||
auto& store = NvsApi::getInstance();
|
||||
auto val = store.getValue(key);
|
||||
pShell->writeLine(key + ": " + val + "");
|
||||
}
|
||||
|
||||
void setConfig(Cli::CArgs args) {
|
||||
if (args.size() != 2) {
|
||||
pShell->writeLine("Needs string key and value");
|
||||
return;
|
||||
}
|
||||
auto key = args[0];
|
||||
auto val = args[1];
|
||||
|
||||
auto& store = NvsApi::getInstance();
|
||||
pShell->writeLine(string{"Storing value = '"} + val + "'");
|
||||
store.setValue(key, val);
|
||||
}
|
||||
|
||||
void setLogServerConfig(Cli::CArgs args) {
|
||||
ESP_LOGI(TAG, "on showLogServerConfig:");
|
||||
auto& store = NvsApi::getInstance();
|
||||
if (args.size() != 1) {
|
||||
auto logger = store.getValue("syslogDst");
|
||||
pShell->writeLine(string{"syslog destination = '"} + logger + "'");
|
||||
pShell->writeLine("provide argument to change syslog server");
|
||||
return;
|
||||
}
|
||||
pShell->writeLine(string{"setting syslog destination to = '"} + args[0] + "'");
|
||||
store.setValue("syslogDst", args[0]);
|
||||
}
|
||||
|
||||
void testLights(Cli::CArgs args) {
|
||||
ESP_LOGI(TAG, "on testLights:");
|
||||
commandQ.enqueue(make_unique<StartCommand>());
|
||||
}
|
||||
|
||||
void showProcessValues(Cli::CArgs args) {
|
||||
pShell->writeLine("Process values:");
|
||||
char buff[256];
|
||||
|
||||
sprintf(buff, "%02x,%02x,%02x", State.color.getRed(), State.color.getGreen(), State.color.getBlue());
|
||||
std::stringstream ssC;
|
||||
for (auto& c : State.counts) {
|
||||
ssC << string{c} << ",";
|
||||
}
|
||||
std::stringstream ssT;
|
||||
for (auto& t : State.times) {
|
||||
ssT << string{t} << ",";
|
||||
}
|
||||
pShell->writeLine(string{" Color RGB: "} + buff);
|
||||
pShell->writeLine(string{" LED-Counts: "} + ssC.str());
|
||||
pShell->writeLine(string{" Switch-Times: "} + ssT.str());
|
||||
}
|
||||
|
||||
void setSyslogLevel(Cli::CArgs args) {
|
||||
if (args.size() != 1) {
|
||||
pShell->writeLine("Needs SyslogLevel Warning = 4, Notice = 5, Informational = 6, Debug = 7");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
auto lvl = stoi(args[0]);
|
||||
if (lvl >= (int)Syslog::Severity::Warning && lvl <= (int)Syslog::Severity::Debug) {
|
||||
Syslog::setSeverity((Syslog::Severity)lvl);
|
||||
} else {
|
||||
pShell->writeLine("New level was not accepted");
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Telnet socket via TCP/IP
|
||||
*
|
||||
* @details The ini-file for TeraTerm only changes CRReceive and CRSend values both to "=CR"
|
||||
* @param arg ignored task argument
|
||||
*/
|
||||
static void telnetSocketTask(int addrFamily) {
|
||||
ESP_LOGI(TAG, "Starting Telnet task");
|
||||
try {
|
||||
TelnetServer telnet(addrFamily);
|
||||
telnet.run(
|
||||
[](TcpSession& session) {
|
||||
pShell = make_unique<Cli>(session, [](string n, Cli::CArgs a) { onCommand(n, a); });
|
||||
pShell->addBinding(
|
||||
{"update", "Start OTA-Update-Process",
|
||||
[](Cli::CArgs a) { startUpdate(a); }});
|
||||
pShell->addBinding(
|
||||
{"setLogserver", "Set log server config ip",
|
||||
[](Cli::CArgs a) { setLogServerConfig(a); }});
|
||||
pShell->addBinding(
|
||||
{"setLogLevel", "Set severity log server",
|
||||
[](Cli::CArgs a) { setSyslogLevel(a); }});
|
||||
|
||||
pShell->addBinding(
|
||||
{"getcfg", "Get configuration value for key",
|
||||
[](Cli::CArgs a) { getConfig(a); }});
|
||||
pShell->addBinding(
|
||||
{"setcfg", "Set configuration value by key and value",
|
||||
[](Cli::CArgs a) { setConfig(a); }});
|
||||
|
||||
pShell->addBinding(
|
||||
{"setDyn", "set dynamics of movement (velocity,accelerations) as floats",
|
||||
[](Cli::CArgs a) { testLights(a); }});
|
||||
pShell->addBinding(
|
||||
{"showData", "Show process values that are input by DMX, MQTT and SPIT",
|
||||
[](Cli::CArgs a) { showProcessValues(a); }});
|
||||
},
|
||||
[](TcpSession& session) {
|
||||
pShell->process();
|
||||
Syslog::setupTask(session.getOther());
|
||||
});
|
||||
} catch (const exception& e) {
|
||||
ESP_LOGE("TCP", "%s", e.what());
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void startShow(string data) {
|
||||
ESP_LOGI(TAG, "StartShuffle command %s", data.c_str());
|
||||
try {
|
||||
Syslog::logv(Syslog::Severity::Informational, "got Shuffle-Command");
|
||||
commandQ.enqueue(make_unique<StartCommand>());
|
||||
} catch (const exception& e) {
|
||||
ESP_LOGE(TAG, "Error to process data %s, with ex: %s", data.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMX-Socket for ArtNet TCP/IP
|
||||
*
|
||||
* @details Tested with [Q Light Controller+](https://www.qlcplus.org/)
|
||||
* @param args ignored task argument
|
||||
*/
|
||||
static void dmxSocketSenderTask(UdpSocket& socket) {
|
||||
try {
|
||||
ArtnetSender artnet(socket);
|
||||
array<uint8_t, 16> data;
|
||||
while (socket.isActive()) {
|
||||
data[0]++;
|
||||
artnet.send("", 0, data.data(), data.size());
|
||||
fos::Task::delayMs(500);
|
||||
}
|
||||
|
||||
} catch (const exception& e) {
|
||||
ESP_LOGE("UDP", "%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
fos::Semaphore etherActive;
|
||||
fos::Semaphore spitProjectFinish;
|
||||
|
||||
/** Event handler for IP_EVENT_ETH_GOT_IP */
|
||||
void got_ip_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
|
||||
const esp_netif_ip_info_t* ip_info = &event->ip_info;
|
||||
|
||||
ESP_LOGI(TAG, "Ethernet Got IP Address");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
|
||||
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
|
||||
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
etherActive.give();
|
||||
}
|
||||
|
||||
static void initialize_ethernet(void) {
|
||||
uint8_t eth_port_cnt = 0;
|
||||
esp_eth_handle_t* eth_handles;
|
||||
ESP_ERROR_CHECK(eth_init(ð_handles, ð_port_cnt));
|
||||
if (eth_port_cnt > 1) {
|
||||
ESP_LOGW(TAG, "multiple Ethernet devices detected, the first initialized is to be used!");
|
||||
}
|
||||
|
||||
static esp_eth_handle_t s_eth_handle = NULL;
|
||||
s_eth_handle = eth_handles[0];
|
||||
free(eth_handles);
|
||||
|
||||
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
// Create default event loop that running in background
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify
|
||||
// default esp-netif configuration parameters.
|
||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
||||
esp_netif_t* eth_netif = esp_netif_new(&cfg);
|
||||
// Attach Ethernet driver to TCP/IP stack
|
||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(s_eth_handle)));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_eth_start(s_eth_handle));
|
||||
}
|
||||
|
||||
namespace Effect {
|
||||
extern const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
|
||||
extern const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
|
||||
extern const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
|
||||
extern const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
|
||||
extern const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
|
||||
|
||||
const Macro macDemoStart = {
|
||||
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
|
||||
{32, 1, StateMachine::UpdateIdle, 0xFF},
|
||||
};
|
||||
|
||||
const Macro macDemoPulse = {
|
||||
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
|
||||
{32, 2, StateMachine::UpdateIdle, 0xFF},
|
||||
{64, 1, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
|
||||
};
|
||||
|
||||
const Macro macDemoFlicker = {
|
||||
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
|
||||
{32, 1, StateMachine::UpdateFlicker, 0xFF},
|
||||
};
|
||||
} // namespace Effect
|
||||
|
||||
void LightingTask() {
|
||||
ESP_LOGI(TAG, "Start Lighting");
|
||||
auto const& colorSource = State.color;
|
||||
array<Effect::EffectProcessor, 2> processors{
|
||||
Effect::EffectProcessor(8),
|
||||
Effect::EffectProcessor(8)};
|
||||
processors[0].setEffect(Effect::macDark, &colorSource, 0);
|
||||
processors[1].setEffect(Effect::macDark, &colorSource, 0);
|
||||
|
||||
const array<Effect::Macro, 2> PictoEffects{
|
||||
Effect::macDemoPulse,
|
||||
Effect::macDemoPulse};
|
||||
|
||||
while (true) {
|
||||
// ESP_LOGI(TAG, "Current color set r%i g%i b%i ",
|
||||
// State.color.getRed(), State.color.getGreen(), State.color.getBlue());
|
||||
// processors[0].setEffect(Effect::macDark, &colorSource, 0);
|
||||
// auto idx = 0;
|
||||
// Syslog::logv(Syslog::Severity::Informational, "Running show");
|
||||
// processors[idx].setEffect(PictoEffects[idx], &colorSource, 0);
|
||||
|
||||
// for (size_t i = 0; i < processors.size(); i++) {
|
||||
// auto col = processors[i].tick();
|
||||
// }
|
||||
// fos::Task::delayMs(40);
|
||||
static int cnt{};
|
||||
fos::Task::delayMs(1000);
|
||||
printf("running %d\n", cnt++);
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalSpitObj {
|
||||
string iD;
|
||||
string groupName;
|
||||
string name;
|
||||
};
|
||||
map<string, StartCommand> ProvidedSpitActions;
|
||||
map<string, string> ExpectedObjects;
|
||||
|
||||
void onServerEvent(SClient::ServerEvent event, const SadDetectedServer& p_DetectedServer) {
|
||||
switch (event) {
|
||||
case SClient::ServerEvent::Detect:
|
||||
ESP_LOGI(TAG, "SERVER DETECTED");
|
||||
ESP_LOGI(TAG, " Name: %s", p_DetectedServer.getName().data());
|
||||
ESP_LOGI(TAG, " ID: %s", p_DetectedServer.getID().data());
|
||||
ESP_LOGI(TAG, " Computer: %s", p_DetectedServer.getComputerName().data());
|
||||
ESP_LOGI(TAG, " IP: %s", p_DetectedServer.getIP().data());
|
||||
ESP_LOGI(TAG, " Port: %s", p_DetectedServer.getPort().data());
|
||||
ESP_LOGI(TAG, " Addition: %s", p_DetectedServer.getAdditions().data());
|
||||
ESP_LOGI(TAG, " ClientIP: %s", p_DetectedServer.getClientIP().data());
|
||||
break;
|
||||
case SClient::ServerEvent::Lost:
|
||||
ESP_LOGW(TAG, "Server lost Name: %s IP: %s", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
|
||||
|
||||
break;
|
||||
case SClient::ServerEvent::Changed:
|
||||
ESP_LOGW(TAG, "Server lost Name: %s IP: %s", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime,
|
||||
SClient::Connection p_ConnectionStatus, SClient::Connection p_OldConnectionStatus) {
|
||||
ESP_LOGI(TAG, "MySPITApp: eventConnectionStatus %d->%d ", (int)p_OldConnectionStatus, (int)p_ConnectionStatus);
|
||||
}
|
||||
|
||||
// The transfer of the server's SPITTypes and SPITObjects is finished.
|
||||
void onProjectUpdate(SClient::ProjUpdate state, string projectId) {
|
||||
switch (state) {
|
||||
case SClient::ProjUpdate::ServerLoaded:
|
||||
ESP_LOGI(TAG, "eventProjectReport ID: %s ", projectId.data());
|
||||
break;
|
||||
case SClient::ProjUpdate::StartTransfer:
|
||||
ESP_LOGI(TAG, "eventStartProjectTransfer");
|
||||
break;
|
||||
case SClient::ProjUpdate::EndTransfer:
|
||||
ESP_LOGI(TAG, "eventEndProjectTransfer");
|
||||
spitProjectFinish.give();
|
||||
break;
|
||||
case SClient::ProjUpdate::ServerClosed:
|
||||
ESP_LOGI(TAG, "eventProjectClosed ID: %s", projectId.data());
|
||||
// If we don't save SPITServer's project specific information
|
||||
// perhaps close all SPITObjects and RemoteSPITObjects to avoid conflicts, when the SPITServer loads a new project
|
||||
// SPITObject::clearSPITObjects();
|
||||
// SPITObject::clearSPITObjectsRemote();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) {
|
||||
return true; // Bypass veto
|
||||
if (!knownType || !createdByClient) { // Don't allow foreign SPITTypes
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onCheckSpitObjectVeto(bool knownType) {
|
||||
return true; // Bypass veto
|
||||
if (!knownType) { // Don't allow objects of unregistered SPITTypes
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when the server has created, loaded, changed or deleted a (Remote) SPITType.
|
||||
// Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer.
|
||||
// May also occur when the server confirms a SPITType created or changed by the client.
|
||||
void onSpitType(SClient::ObjectEvent event, bool isRemote, const SType& sType) {
|
||||
if (isRemote) {
|
||||
if (event == SClient::ObjectEvent::Created) {
|
||||
ESP_LOGI(TAG, "NEW SPIT-REMOTE-Type ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
|
||||
auto typeName = sType.Name.get();
|
||||
if (ExpectedObjects.contains(typeName)) {
|
||||
ExpectedObjects[typeName] = sType.getID();
|
||||
}
|
||||
} else if (event == SClient::ObjectEvent::Changed) {
|
||||
// we had to inform all Remote SPITObjects using the p_SPITType
|
||||
// perhaps the SPITObject uses information from the SPITType
|
||||
// SPITObject *ptrSPITObject;
|
||||
// int intSPITObjectCount;
|
||||
// intSPITObjectCount = SPITObject::getSPITObjectRemoteCount();
|
||||
// for (int intObject = 0; intObject < intSPITObjectCount; intObject++) {
|
||||
// ptrSPITObject = SPITObject::getSPITObjectRemote(intObject);
|
||||
// if (ptrSPITObject == nullptr)
|
||||
// continue;
|
||||
// if (ptrSPITObject->getSPITTypeID() == p_SPITType.getID()) {
|
||||
// // call ecentSPITObjectRemote
|
||||
// // onSpitObjectRemote(SClient::ObjectEvent::Changed, p_SPITType, *ptrSPITObject);
|
||||
// }
|
||||
// }
|
||||
// ESP_LOGI(TAG, "SPIT-REMOTE-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
|
||||
} else if (event == SClient::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-REMOTE-Type Removed ID: %s GroupName: %s Name: %s\n", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data());
|
||||
}
|
||||
} else {
|
||||
if (event == SClient::ObjectEvent::Created) {
|
||||
// Whenever you provide an action for this SPITType take this over in your code.
|
||||
// call _SpitClient.setActionSPITType(sType.getID(), true);
|
||||
// ESP_LOGI(TAG, "NEW SPIT-Type ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
|
||||
} else if (event == SClient::ObjectEvent::Changed) {
|
||||
// ESP_LOGI(TAG, "SPIT-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
|
||||
} else if (event == SClient::ObjectEvent::Deleted) {
|
||||
// ESP_LOGI(TAG, "SPIT-Type Removed ID: %s GroupName: %s Name: %s\n", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the server has created, loaded or changed a SPITObject.
|
||||
// A Remote SPITObject is used to remote control the SPITServer.
|
||||
// May also occur when the server confirms a SPITObject created by the client, what the client should never do!!.
|
||||
// false = server changed a existing SPITObject
|
||||
// @param p_SPITType a reference to a copy of the associated SPITType instance.
|
||||
// @param p_SPITObject a reference to a copy of the SPITObject instance.
|
||||
void onSpitObject(SClient::ObjectEvent event, bool isRemote, const SType& sType, const SObject& sObject) {
|
||||
if (isRemote) {
|
||||
if (event == SClient::ObjectEvent::Created) {
|
||||
// ESP_LOGI(TAG, "NEW SPIT-REMOTE-Object ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
|
||||
// This is a remote SPITObject which can be used to remote control the server.
|
||||
// If you want you can list this for later use
|
||||
} else if (event == SClient::ObjectEvent::Changed) {
|
||||
// ESP_LOGI(TAG, "SPIT-REMOTE-Object CHANGED ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
|
||||
} else if (event == SClient::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-REMOTE-Object Removed ID: %s Name: %s\n", sObject.getID().data(), sObject.Name.get().data());
|
||||
// This is a remote SPITObject
|
||||
// If you have listet this prior you should remove it from the list
|
||||
}
|
||||
} else {
|
||||
if (event == SClient::ObjectEvent::Created) {
|
||||
// ESP_LOGI(TAG, "NEW SPIT-Object ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
|
||||
// check your actions
|
||||
// Whenever you provide an action for this SPITObject take this over in your code.
|
||||
// call _SpitClient.setActionSPITObject(sObject.getID(), true);
|
||||
|
||||
// for our little excample as described in loadClientProject:
|
||||
// We have only actions for SPITTypes - means every SPITObject with the associated "Actionx"-SPITTypes will trigger the action when it is played
|
||||
//-> no need to do something here, because setActionSPITType has been set prior and the SPITObject will automatically inherits this
|
||||
// SPITObjects with other SPITTypes asscciated will trigger no actions
|
||||
|
||||
} else if (event == SClient::ObjectEvent::Changed) {
|
||||
// ESP_LOGI(TAG, "SPIT-Object CHANGED ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
|
||||
} else if (event == SClient::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-Object Removed ID: %s Name: %s\n", sObject.getID().data(), sObject.Name.get().data());
|
||||
// Check your actions
|
||||
// take the removal of the SPITObject over in your code
|
||||
|
||||
// CAUTION: Deleted SPITObjects can be added later again (perhaps per UNDO on the SPITServer)
|
||||
//-> don't remove your assigned action immediately - keep it to reassign it later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SPITServer may use several methods for playing SPITObjects.
|
||||
// e.g. liveSHOWsoftware has the timeline and jingles which plays objects, where the timeline the main player is.
|
||||
// SPIT distinguishes between the different players. All eventPlay... functions contain the information which player plays the SPIT object.
|
||||
void onPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, uint64_t p_TimeFrames) {
|
||||
ESP_LOGD(TAG, "eventPlay Player: %s Runs: %d Time: %lld", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames);
|
||||
|
||||
switch (p_PlayerType) {
|
||||
case SClient::PlayerType::PTYPE_MAIN:
|
||||
// p_FrameTimes contains the position inside the server's project, we can use it like a timecode
|
||||
// int intMilliseconds = (int)(((double)p_TimeFrames / (double)m_ServerFramesPerSecond) * 1000);
|
||||
break;
|
||||
case SClient::PlayerType::PTYPE_CONTINOUS:
|
||||
// The olayer is playing only single Object sequences sometime during the project
|
||||
break;
|
||||
case SClient::PlayerType::PTYPE_DISCRETE:
|
||||
// Only discrete values where submitted, e.g the fader position of remote faders.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onPlaySpitType(string p_PlayerID, string spitTypeId, bool p_PlayerIsRunning, bool p_Started, bool p_Ended, double p_Value) {
|
||||
// double doubleValue = ((double)p_PlayObject.getValue() / 1000000) * ((double)p_PlayObject.getValueFactor() / 1000000);
|
||||
ESP_LOGD(TAG, "eventPlayObject Player: %s is running: %d Object Started: %d Stopped: %d", p_PlayerID.data(), p_PlayerIsRunning, p_Started, p_Ended);
|
||||
// ESP_LOGD(TAG, " SPITType: %s SPITObject: %s Position: %lld Value: %f\n", spitTypeId.data(), p_SPITObject.getName().data(), p_PlayObject.getFrameInside(), doubleValue);
|
||||
ESP_LOGD(TAG, " SPITType: %s Value: %f\n", spitTypeId.data(), p_Value);
|
||||
|
||||
if (!ProvidedSpitActions.contains(spitTypeId)) {
|
||||
ESP_LOGE(TAG, "SPIT ID %s is not accepted", spitTypeId.c_str());
|
||||
return;
|
||||
}
|
||||
if (p_Started == true) {
|
||||
auto command = ProvidedSpitActions[spitTypeId];
|
||||
// ESP_LOGI(TAG, "Player: %s is running: %s Object", p_PlayerID.data(), spitTypeId.c_str());
|
||||
commandQ.enqueue(make_unique<StartCommand>());
|
||||
Syslog::logv(Syslog::Severity::Informational, "Got SPIT command for move ot : r%d", command.pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a remote SpitObject which value function is changed by the server.
|
||||
* This allows the Client to adjust its display for the remote command.
|
||||
* @param p_SPITType the assigned remote SPITType of p_SPITObject
|
||||
* @param p_SPITObject the remote SPITObject which is changed
|
||||
* @param p_FrameInsideObject can be discarded
|
||||
* @param p_Value the new value
|
||||
*/
|
||||
void onPlayRemoteObjectStatus(const SType& sType, const SObject& sObject, uint64_t frameInsideObject, int value) {
|
||||
ESP_EARLY_LOGD(TAG, "eventPlayRemoteObjectStatus RemoteSPITType: %s RemoteSPITObject: %s Position: %lld Value: %d", sType.Name.get().data(), sObject.Name.get().data(), frameInsideObject, value);
|
||||
}
|
||||
|
||||
// void SpitClientApp() {
|
||||
// ESP_LOGI(TAG, "Starting SPIT task");
|
||||
|
||||
// auto& provided = SpitTypes.Provided;
|
||||
// auto& expected = SpitTypes.Expected;
|
||||
// vector<LocalSpitObj> ProvidedObj;
|
||||
// ProvidedSpitActions[provided.startShuffle] = MoveCommand{.type = MoveType::Shuffle, .pos = 0};
|
||||
// ProvidedObj.push_back(LocalSpitObj{.iD = provided.startShuffle, .groupName = provided.group, .name = provided.startShuffle});
|
||||
// ExpectedObjects[expected.changingPos] = "";
|
||||
// for (size_t i = 0; i < 6; i++) {
|
||||
// ProvidedSpitActions[provided.moveToX[i]] = MoveCommand{.type = MoveType::StepTo, .pos = (uint8_t)(i + 1)};
|
||||
// ProvidedObj.push_back(LocalSpitObj{.iD = provided.moveToX[i], .groupName = provided.group, .name = provided.moveToX[i]});
|
||||
// ExpectedObjects[expected.inPosX[i]] = "";
|
||||
// }
|
||||
|
||||
// auto ip = spit::Socket::getAdaptersInfo();
|
||||
// spit::Socket socket(ip);
|
||||
// SClient spitClient(ClientName, ProjectName, socket,
|
||||
// {
|
||||
// .onServerEvent = onServerEvent,
|
||||
// .onConnectionStatus = onConnectionStatus,
|
||||
// .onProjectUpdate = onProjectUpdate,
|
||||
// .onSpitType = onSpitType,
|
||||
// .onSpitObject = onSpitObject,
|
||||
// .onPlay = onPlay,
|
||||
// .onPlaySpitType = onPlaySpitType,
|
||||
// .onPlayRemoteObjectStatus = onPlayRemoteObjectStatus,
|
||||
// .onCheckSpitTypeVeto = onCheckSpitTypeVeto,
|
||||
// .onCheckSpitObjectVeto = onCheckSpitObjectVeto,
|
||||
// });
|
||||
|
||||
// for (auto& obj : ProvidedObj) {
|
||||
// SType* ptrSPITType1Fix = spitClient.createTypeFixed(obj.iD, obj.groupName, obj.name, 0, 0);
|
||||
// spitClient.setActionType(ptrSPITType1Fix->getID(), true); // should be executed whenever a SPITObject with this SPITType is played
|
||||
// }
|
||||
// spitClient.clientProjectLoaded();
|
||||
// spitClient.startServerAutoDetect();
|
||||
|
||||
// spitProjectFinish.take();
|
||||
// string serverProjectID = spitClient.getServerProjectID();
|
||||
// string serverProjectName = spitClient.getClientProjectName();
|
||||
// int serverFramesPerSecond = spitClient.getServerFramesPerSecond(); // set when the server reports his project, see eventProjectReport
|
||||
// ESP_LOGI(TAG, "eventProjectReport ID: %s Name: %s FramesPerSecond: %d", serverProjectID.data(), serverProjectName.data(), serverFramesPerSecond);
|
||||
|
||||
// for (auto&& obj : ExpectedObjects) {
|
||||
// if (obj.second == "") {
|
||||
// ESP_LOGE(TAG, "No matching Remote ID for %s", obj.first.c_str());
|
||||
// }
|
||||
// }
|
||||
|
||||
// while (true) {
|
||||
// auto res = responseQueue.dequeue();
|
||||
// if (res->type == ResponseType::StartMoving) {
|
||||
// spitClient.sendRemoteObject(ExpectedObjects[expected.changingPos]);
|
||||
// } else if (res->type == ResponseType::StepAt) {
|
||||
// spitClient.sendRemoteObject(ExpectedObjects[expected.inPosX[res->pos - 1]]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// void MqttThread() {
|
||||
// ESP_LOGI(TAG, "Starting MQTT task");
|
||||
|
||||
// auto& store = NvsApi::getInstance();
|
||||
// auto broker = store.getValue(ConfigKeys.mqttBroker);
|
||||
// if (broker != "") {
|
||||
// ESP_LOGI(TAG, "Initializing MQTT");
|
||||
// auto prefix = store.getValue(ConfigKeys.mqttPrefix);
|
||||
// auto& client = MqttClient::init(broker, prefix);
|
||||
// if (!client.isRunning()) {
|
||||
// client.addSubscription(MqttTopics.moveTo, [](string d) { startShuffle(d); });
|
||||
// client.start();
|
||||
// }
|
||||
|
||||
// while (true) {
|
||||
// auto res = responseQueue.dequeue();
|
||||
// if (res->type == ResponseType::StartMoving) {
|
||||
// client.publish(MqttTopics.showDone, "");
|
||||
// } else if (res->type == ResponseType::StepAt) {
|
||||
// client.publish(MqttTopics.inPosition, to_string(res->pos));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void app_main(void) {
|
||||
initialize_ethernet();
|
||||
NvsApi::init();
|
||||
static fos::Task lightingTask(LightingTask, "Lights", 0x8000uL);
|
||||
|
||||
etherActive.take();
|
||||
ESP_LOGI(TAG, "Start net services");
|
||||
|
||||
// static int ipVersion = AF_INET;
|
||||
// static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
|
||||
// static fos::Task spit(SpitClientApp, "SpitClient");
|
||||
// // static fos::Task mqtt(MqttThread, "MqttEndpoint");
|
||||
// // static Task otaUpdate(SystemFunctions::OtaTaskEntry, "otaTask", 8192);
|
||||
|
||||
auto& store = NvsApi::getInstance();
|
||||
auto logger = store.getValue(ConfigKeys.syslogDest);
|
||||
if (logger != "") {
|
||||
Syslog::setupTask(IpAdr{logger, 0});
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Configuration");
|
||||
ESP_LOGI(TAG, "%s: %s", ConfigKeys.syslogDest, store.getValue(ConfigKeys.syslogDest).c_str());
|
||||
ESP_LOGI(TAG, "%s: %s", ConfigKeys.mqttBroker, store.getValue(ConfigKeys.mqttBroker).c_str());
|
||||
ESP_LOGI(TAG, "%s: %s", ConfigKeys.mqttPrefix, store.getValue(ConfigKeys.mqttPrefix).c_str());
|
||||
ESP_LOGI(TAG, "%s: %s", ConfigKeys.spitServer, store.getValue(ConfigKeys.spitServer).c_str());
|
||||
|
||||
while (true) {
|
||||
fos::Task::delayMs(5000);
|
||||
Syslog::logv(Syslog::Severity::Notice, "Min heap size: %u / FreeHeap %lu",
|
||||
heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
|
||||
esp_get_free_heap_size());
|
||||
}
|
||||
}
|
||||
-1027
File diff suppressed because it is too large
Load Diff
+8
-30
@@ -2,32 +2,6 @@
|
||||
# Compiler options
|
||||
#
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
CONFIG_LWIP_LOCAL_HOSTNAME="ChaosWatch"
|
||||
|
||||
#
|
||||
# Ethernet Configuration
|
||||
#
|
||||
CONFIG_USE_SPI_ETHERNET=y
|
||||
CONFIG_SPI_ETHERNETS_NUM=1
|
||||
# CONFIG_USE_DM9051 is not set
|
||||
# CONFIG_USE_KSZ8851SNL is not set
|
||||
CONFIG_USE_W5500=y
|
||||
CONFIG_ETH_SPI_HOST=1
|
||||
CONFIG_ETH_SPI_SCLK_GPIO=6
|
||||
CONFIG_ETH_SPI_MOSI_GPIO=7
|
||||
CONFIG_ETH_SPI_MISO_GPIO=2
|
||||
CONFIG_ETH_SPI_CLOCK_MHZ=16
|
||||
CONFIG_ETH_SPI_CS0_GPIO=3
|
||||
CONFIG_ETH_SPI_INT0_GPIO=4
|
||||
CONFIG_ETH_SPI_POLLING0_MS=0
|
||||
CONFIG_ETH_SPI_PHY_RST0_GPIO=-1
|
||||
CONFIG_ETH_SPI_PHY_ADDR0=1
|
||||
# end of Ethernet Configuration
|
||||
|
||||
#
|
||||
# Ethernet
|
||||
#
|
||||
CONFIG_ETH_SPI_ETHERNET_W5500=y
|
||||
|
||||
#
|
||||
# Wi-Fi
|
||||
@@ -37,11 +11,15 @@ CONFIG_ETH_SPI_ETHERNET_W5500=y
|
||||
#
|
||||
# LWIP
|
||||
#
|
||||
CONFIG_LWIP_LOCAL_HOSTNAME="ChaosWatch"
|
||||
CONFIG_LWIP_LOCAL_HOSTNAME="LeoLights"
|
||||
|
||||
#
|
||||
# Serial flasher config
|
||||
# Ethernet
|
||||
#
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
|
||||
CONFIG_USE_INTERNAL_ETHERNET=y
|
||||
CONFIG_ETH_PHY_LAN87XX=y
|
||||
|
||||
CONFIG_ETH_MDC_GPIO=23
|
||||
CONFIG_ETH_MDIO_GPIO=33
|
||||
CONFIG_ETH_PHY_RST_GPIO=5
|
||||
CONFIG_ETH_PHY_ADDR=1
|
||||
|
||||
Reference in New Issue
Block a user