From 6ff61b3e04ec583f679db658772fe6ed37315e69 Mon Sep 17 00:00:00 2001
From: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
Date: Sat, 2 Dec 2023 21:47:52 +0100
Subject: [PATCH] Pico W: Initial Wi-Fi support (#2980)
* Pico W: Initial WiFi support: connects, but freezes after a while
* Update arduino-pico core to fix hang with Wi-Fi
* Add `picow` to workflow since it's different from `pico` now
---
.github/workflows/main_matrix.yml | 1 +
arch/nrf52/nrf52.ini | 2 +-
arch/portduino/portduino.ini | 1 +
arch/rp2040/rp2040.ini | 6 +-
arch/stm32/stm32wl5e.ini | 2 +-
src/graphics/Screen.cpp | 11 +-
src/main.cpp | 11 +-
src/mesh/NodeDB.cpp | 2 +-
src/mesh/api/WiFiServerAPI.h | 2 +-
src/mesh/http/ContentHandler.cpp | 2 +-
src/mesh/http/ContentHandler.h | 3 +-
src/mesh/http/ContentHelper.cpp | 4 +-
src/mesh/http/WebServer.cpp | 4 +-
src/mesh/{http => wifi}/WiFiAPClient.cpp | 194 +++++++++++++----------
src/mesh/{http => wifi}/WiFiAPClient.h | 4 +-
src/modules/AdminModule.h | 6 +-
src/mqtt/MQTT.cpp | 2 +-
src/platform/esp32/main-esp32.cpp | 2 +-
src/sleep.cpp | 2 +-
variants/rpipicow/platformio.ini | 6 +-
variants/rpipicow/variant.h | 6 +-
21 files changed, 154 insertions(+), 119 deletions(-)
rename src/mesh/{http => wifi}/WiFiAPClient.cpp (94%)
rename src/mesh/{http => wifi}/WiFiAPClient.h (79%)
diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml
index 6b6ff1ad7..e53c35bd2 100644
--- a/.github/workflows/main_matrix.yml
+++ b/.github/workflows/main_matrix.yml
@@ -123,6 +123,7 @@ jobs:
matrix:
include:
- board: pico
+ - board: picow
- board: rak11310
uses: ./.github/workflows/build_rpi2040.yml
with:
diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini
index 1a3631420..5da571cce 100644
--- a/arch/nrf52/nrf52.ini
+++ b/arch/nrf52/nrf52.ini
@@ -11,7 +11,7 @@ build_flags =
-Isrc/platform/nrf52
build_src_filter =
- ${arduino_base.build_src_filter} - - - - - - - -
+ ${arduino_base.build_src_filter} - - - - - - - - -
lib_deps=
${arduino_base.lib_deps}
diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini
index 8b4ab5d4b..c4b6d5377 100644
--- a/arch/portduino/portduino.ini
+++ b/arch/portduino/portduino.ini
@@ -10,6 +10,7 @@ build_src_filter =
-
-
-
+ -
-
-
-
diff --git a/arch/rp2040/rp2040.ini b/arch/rp2040/rp2040.ini
index 38acde1e0..7674fbd52 100644
--- a/arch/rp2040/rp2040.ini
+++ b/arch/rp2040/rp2040.ini
@@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
-platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2
+platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
extends = arduino_base
-platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2
+platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#d2461a14ad5aa920e44508d236c2f459e3befbf8
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -12,7 +12,7 @@ build_flags =
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
- ${arduino_base.build_src_filter} - - - - - - - -
+ ${arduino_base.build_src_filter} - - - - - - - -
lib_ignore =
BluetoothOTA
diff --git a/arch/stm32/stm32wl5e.ini b/arch/stm32/stm32wl5e.ini
index f563eec18..cac7110f2 100644
--- a/arch/stm32/stm32wl5e.ini
+++ b/arch/stm32/stm32wl5e.ini
@@ -13,7 +13,7 @@ build_flags =
-DVECT_TAB_OFFSET=0x08000000
build_src_filter =
- ${arduino_base.build_src_filter} - - - - - - - - - - - -
+ ${arduino_base.build_src_filter} - - - - - - - - - - - - -
board_upload.offset_address = 0x08000000
upload_protocol = stlink
diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp
index 2e144e41a..e75a432d4 100644
--- a/src/graphics/Screen.cpp
+++ b/src/graphics/Screen.cpp
@@ -45,7 +45,7 @@ along with this program. If not, see .
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#endif
@@ -1618,12 +1618,19 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
} else if (WiFi.status() == WL_IDLE_STATUS) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
- } else {
+ }
+#ifdef ARCH_ESP32
+ else {
// Codes:
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
display->drawString(x, y + FONT_HEIGHT_SMALL * 1,
WiFi.disconnectReasonName(static_cast(getWifiDisconnectReason())));
}
+#else
+ else {
+ display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Unkown status: " + String(WiFi.status()));
+ }
+#endif
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
diff --git a/src/main.cpp b/src/main.cpp
index 5cea142bc..b3671c020 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -32,9 +32,6 @@
#include
// #include
-#include "mesh/eth/ethClient.h"
-#include "mesh/http/WiFiAPClient.h"
-
#ifdef ARCH_ESP32
#include "mesh/http/WebServer.h"
#include "nimble/NimbleBluetooth.h"
@@ -48,10 +45,12 @@ NRF52Bluetooth *nrf52Bluetooth;
#if HAS_WIFI
#include "mesh/api/WiFiServerAPI.h"
+#include "mesh/wifi/WiFiAPClient.h"
#endif
#if HAS_ETHERNET
#include "mesh/api/ethServerAPI.h"
+#include "mesh/eth/ethClient.h"
#endif
#include "mqtt/MQTT.h"
@@ -835,11 +834,15 @@ void setup()
#ifndef ARCH_PORTDUINO
// Initialize Wifi
+#if HAS_WIFI
initWifi();
+#endif
+#if HAS_ETHERNET
// Initialize Ethernet
initEthernet();
#endif
+#endif
#ifdef ARCH_ESP32
// Start web server thread.
@@ -938,4 +941,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
-}
\ No newline at end of file
+}
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index cb5c27b49..bb079e5c0 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -21,7 +21,7 @@
#include
#ifdef ARCH_ESP32
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "modules/esp32/StoreForwardModule.h"
#include
#include
diff --git a/src/mesh/api/WiFiServerAPI.h b/src/mesh/api/WiFiServerAPI.h
index 11b494d23..e436a177d 100644
--- a/src/mesh/api/WiFiServerAPI.h
+++ b/src/mesh/api/WiFiServerAPI.h
@@ -22,4 +22,4 @@ class WiFiServerPort : public APIServerPort
explicit WiFiServerPort(int port);
};
-void initApiServer(int port = 4403);
+void initApiServer(int port = 4403);
\ No newline at end of file
diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp
index 2ea2a76a5..4ca37a256 100644
--- a/src/mesh/http/ContentHandler.cpp
+++ b/src/mesh/http/ContentHandler.cpp
@@ -5,7 +5,7 @@
#include "main.h"
#include "mesh/http/ContentHelper.h"
#include "mesh/http/WebServer.h"
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "mqtt/JSON.h"
#include "power.h"
#include "sleep.h"
diff --git a/src/mesh/http/ContentHandler.h b/src/mesh/http/ContentHandler.h
index 903d5ee08..987e3ffef 100644
--- a/src/mesh/http/ContentHandler.h
+++ b/src/mesh/http/ContentHandler.h
@@ -1,5 +1,4 @@
#pragma once
-
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer);
// Declare some handler functions for the various URLs on the server
@@ -34,4 +33,4 @@ class HttpAPI : public PhoneAPI
protected:
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() override { return true; } // FIXME, be smarter about this
-};
+};
\ No newline at end of file
diff --git a/src/mesh/http/ContentHelper.cpp b/src/mesh/http/ContentHelper.cpp
index 249dcbde6..8f283932b 100644
--- a/src/mesh/http/ContentHelper.cpp
+++ b/src/mesh/http/ContentHelper.cpp
@@ -1,6 +1,6 @@
#include "mesh/http/ContentHelper.h"
-//#include
-//#include "main.h"
+// #include
+// #include "main.h"
void replaceAll(std::string &str, const std::string &from, const std::string &to)
{
diff --git a/src/mesh/http/WebServer.cpp b/src/mesh/http/WebServer.cpp
index 2b045c0be..7814f2c29 100644
--- a/src/mesh/http/WebServer.cpp
+++ b/src/mesh/http/WebServer.cpp
@@ -2,7 +2,7 @@
#include "NodeDB.h"
#include "graphics/Screen.h"
#include "main.h"
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "sleep.h"
#include
#include
@@ -210,4 +210,4 @@ void initWebServer()
} else {
LOG_ERROR("Web Servers Failed! ;-( \n");
}
-}
+}
\ No newline at end of file
diff --git a/src/mesh/http/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp
similarity index 94%
rename from src/mesh/http/WiFiAPClient.cpp
rename to src/mesh/wifi/WiFiAPClient.cpp
index cc8d4b168..06573fd60 100644
--- a/src/mesh/http/WiFiAPClient.cpp
+++ b/src/mesh/wifi/WiFiAPClient.cpp
@@ -1,17 +1,22 @@
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"
#include "configuration.h"
#include "main.h"
#include "mesh/api/WiFiServerAPI.h"
-#include "mesh/http/WebServer.h"
#include "mqtt/MQTT.h"
#include "target_specific.h"
-#include
#include
#include
+#ifndef ARCH_RP2040
+#include "mesh/http/WebServer.h"
+#include
#include
+static void WiFiEvent(WiFiEvent_t event);
+#else
+#include
+#endif
#ifndef DISABLE_NTP
#include
@@ -19,8 +24,6 @@
using namespace concurrency;
-static void WiFiEvent(WiFiEvent_t event);
-
// NTP
WiFiUDP ntpUDP;
@@ -44,78 +47,6 @@ Syslog syslog(syslogClient);
Periodic *wifiReconnect;
-static int32_t reconnectWiFi()
-{
- const char *wifiName = config.network.wifi_ssid;
- const char *wifiPsw = config.network.wifi_psk;
-
- if (config.network.wifi_enabled && needReconnect) {
-
- if (!*wifiPsw) // Treat empty password as no password
- wifiPsw = NULL;
-
- needReconnect = false;
-
- // Make sure we clear old connection credentials
- WiFi.disconnect(false, true);
- LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
-
- delay(5000);
-
- if (!WiFi.isConnected()) {
- WiFi.begin(wifiName, wifiPsw);
- }
- }
-
-#ifndef DISABLE_NTP
- if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
- LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
- if (timeClient.update()) {
- LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
-
- struct timeval tv;
- tv.tv_sec = timeClient.getEpochTime();
- tv.tv_usec = 0;
-
- perhapsSetRTC(RTCQualityNTP, &tv);
- lastrun_ntp = millis();
-
- } else {
- LOG_DEBUG("NTP Update failed\n");
- }
- }
-#endif
-
- if (config.network.wifi_enabled && !WiFi.isConnected()) {
- return 1000; // check once per second
- } else {
- return 300000; // every 5 minutes
- }
-}
-
-bool isWifiAvailable()
-{
-
- if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
- return true;
- } else {
- return false;
- }
-}
-
-// Disable WiFi
-void deinitWifi()
-{
- LOG_INFO("WiFi deinit\n");
-
- if (isWifiAvailable()) {
- WiFi.disconnect(true);
- WiFi.mode(WIFI_MODE_NULL);
- LOG_INFO("WiFi Turned Off\n");
- // WiFi.printDiag(Serial);
- }
-}
-
static void onNetworkConnected()
{
if (!APStartupComplete) {
@@ -158,7 +89,9 @@ static void onNetworkConnected()
syslog.enable();
}
+#ifndef ARCH_RP2040
initWebServer();
+#endif
initApiServer();
APStartupComplete = true;
@@ -169,6 +102,89 @@ static void onNetworkConnected()
mqtt->reconnect();
}
+static int32_t reconnectWiFi()
+{
+ const char *wifiName = config.network.wifi_ssid;
+ const char *wifiPsw = config.network.wifi_psk;
+
+ if (config.network.wifi_enabled && needReconnect) {
+
+ if (!*wifiPsw) // Treat empty password as no password
+ wifiPsw = NULL;
+
+ needReconnect = false;
+
+ // Make sure we clear old connection credentials
+#ifdef ARCH_ESP32
+ WiFi.disconnect(false, true);
+#else
+ WiFi.disconnect(false);
+#endif
+ LOG_INFO("Reconnecting to WiFi access point %s\n", wifiName);
+
+ delay(5000);
+
+ if (!WiFi.isConnected()) {
+ WiFi.begin(wifiName, wifiPsw);
+ }
+ }
+
+#ifndef DISABLE_NTP
+ if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
+ LOG_DEBUG("Updating NTP time from %s\n", config.network.ntp_server);
+ if (timeClient.update()) {
+ LOG_DEBUG("NTP Request Success - Setting RTCQualityNTP if needed\n");
+
+ struct timeval tv;
+ tv.tv_sec = timeClient.getEpochTime();
+ tv.tv_usec = 0;
+
+ perhapsSetRTC(RTCQualityNTP, &tv);
+ lastrun_ntp = millis();
+
+ } else {
+ LOG_DEBUG("NTP Update failed\n");
+ }
+ }
+#endif
+
+ if (config.network.wifi_enabled && !WiFi.isConnected()) {
+ return 1000; // check once per second
+ } else {
+#ifdef ARCH_RP2040
+ onNetworkConnected(); // will only do anything once
+#endif
+ return 300000; // every 5 minutes
+ }
+}
+
+bool isWifiAvailable()
+{
+
+ if (config.network.wifi_enabled && (config.network.wifi_ssid[0])) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// Disable WiFi
+void deinitWifi()
+{
+ LOG_INFO("WiFi deinit\n");
+
+ if (isWifiAvailable()) {
+#ifdef ARCH_ESP32
+ WiFi.disconnect(true, false);
+#else
+ WiFi.disconnect(true);
+#endif
+ WiFi.mode(WIFI_OFF);
+ LOG_INFO("WiFi Turned Off\n");
+ // WiFi.printDiag(Serial);
+ }
+}
+
// Startup WiFi
bool initWifi()
{
@@ -177,10 +193,10 @@ bool initWifi()
const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk;
- createSSLCert();
-
+#ifndef ARCH_RP2040
+ createSSLCert(); // For WebServer
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
-
+#endif
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
@@ -189,17 +205,17 @@ bool initWifi()
getMacAddr(dmac);
snprintf(ourHost, sizeof(ourHost), "Meshtastic-%02x%02x", dmac[4], dmac[5]);
- WiFi.mode(WIFI_MODE_STA);
+ WiFi.mode(WIFI_STA);
WiFi.setHostname(ourHost);
- WiFi.onEvent(WiFiEvent);
- WiFi.setAutoReconnect(true);
- WiFi.setSleep(false);
if (config.network.address_mode == meshtastic_Config_NetworkConfig_AddressMode_STATIC &&
config.network.ipv4_config.ip != 0) {
WiFi.config(config.network.ipv4_config.ip, config.network.ipv4_config.gateway, config.network.ipv4_config.subnet,
- config.network.ipv4_config.dns,
- config.network.ipv4_config.dns); // Wifi wants two DNS servers... set both to the same value
+ config.network.ipv4_config.dns);
}
+#ifndef ARCH_RP2040
+ WiFi.onEvent(WiFiEvent);
+ WiFi.setAutoReconnect(true);
+ WiFi.setSleep(false);
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
@@ -218,7 +234,7 @@ bool initWifi()
wifiDisconnectReason = info.wifi_sta_disconnected.reason;
},
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
-
+#endif
LOG_DEBUG("JOINING WIFI soon: ssid=%s\n", wifiName);
wifiReconnect = new Periodic("WifiConnect", reconnectWiFi);
}
@@ -229,6 +245,7 @@ bool initWifi()
}
}
+#ifndef ARCH_RP2040
// Called by the Espressif SDK to
static void WiFiEvent(WiFiEvent_t event)
{
@@ -369,8 +386,9 @@ static void WiFiEvent(WiFiEvent_t event)
break;
}
}
+#endif
uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
-}
+}
\ No newline at end of file
diff --git a/src/mesh/http/WiFiAPClient.h b/src/mesh/wifi/WiFiAPClient.h
similarity index 79%
rename from src/mesh/http/WiFiAPClient.h
rename to src/mesh/wifi/WiFiAPClient.h
index 0c08c567b..6625d3e46 100644
--- a/src/mesh/http/WiFiAPClient.h
+++ b/src/mesh/wifi/WiFiAPClient.h
@@ -5,7 +5,7 @@
#include
#include
-#ifdef ARCH_ESP32
+#if defined(HAS_WIFI) && !defined(ARCH_PORTDUINO)
#include
#endif
@@ -19,4 +19,4 @@ void deinitWifi();
bool isWifiAvailable();
-uint8_t getWifiDisconnectReason();
+uint8_t getWifiDisconnectReason();
\ No newline at end of file
diff --git a/src/modules/AdminModule.h b/src/modules/AdminModule.h
index eb06e7b83..6ecc88829 100644
--- a/src/modules/AdminModule.h
+++ b/src/modules/AdminModule.h
@@ -1,7 +1,7 @@
#pragma once
#include "ProtobufModule.h"
-#ifdef ARCH_ESP32
-#include "mesh/http/WiFiAPClient.h"
+#if HAS_WIFI
+#include "mesh/wifi/WiFiAPClient.h"
#endif
/**
@@ -50,4 +50,4 @@ class AdminModule : public ProtobufModule
void reboot(int32_t seconds);
};
-extern AdminModule *adminModule;
+extern AdminModule *adminModule;
\ No newline at end of file
diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp
index 29a634922..a97aa5255 100644
--- a/src/mqtt/MQTT.cpp
+++ b/src/mqtt/MQTT.cpp
@@ -7,9 +7,9 @@
#include "mesh/Router.h"
#include "mesh/generated/meshtastic/mqtt.pb.h"
#include "mesh/generated/meshtastic/telemetry.pb.h"
-#include "mesh/http/WiFiAPClient.h"
#include "sleep.h"
#if HAS_WIFI
+#include "mesh/wifi/WiFiAPClient.h"
#include
#endif
#include "mqtt/JSON.h"
diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp
index 833e058d8..7da41512e 100644
--- a/src/platform/esp32/main-esp32.cpp
+++ b/src/platform/esp32/main-esp32.cpp
@@ -7,7 +7,7 @@
#include "nimble/NimbleBluetooth.h"
#endif
#include "BleOta.h"
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "meshUtils.h"
#include "sleep.h"
diff --git a/src/sleep.cpp b/src/sleep.cpp
index b0f4aec88..464486d00 100644
--- a/src/sleep.cpp
+++ b/src/sleep.cpp
@@ -11,7 +11,7 @@
#ifdef ARCH_ESP32
#include "esp32/pm.h"
#include "esp_pm.h"
-#include "mesh/http/WiFiAPClient.h"
+#include "mesh/wifi/WiFiAPClient.h"
#include "rom/rtc.h"
#include
#include
diff --git a/variants/rpipicow/platformio.ini b/variants/rpipicow/platformio.ini
index 3228e4c24..4c8cf992d 100644
--- a/variants/rpipicow/platformio.ini
+++ b/variants/rpipicow/platformio.ini
@@ -8,8 +8,10 @@ upload_protocol = picotool
build_flags = ${rp2040_base.build_flags}
-DRPI_PICO
-Ivariants/rpipicow
- -DDEBUG_RP2040_PORT=Serial
-DHW_SPI1_DEVICE
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
+ -fexceptions # for exception handling in MQTT
+build_src_filter = ${rp2040_base.build_src_filter} +
lib_deps =
- ${rp2040_base.lib_deps}
\ No newline at end of file
+ ${rp2040_base.lib_deps}
+ ${networking_base.lib_deps}
\ No newline at end of file
diff --git a/variants/rpipicow/variant.h b/variants/rpipicow/variant.h
index abbd1c465..c48b901ac 100644
--- a/variants/rpipicow/variant.h
+++ b/variants/rpipicow/variant.h
@@ -4,6 +4,10 @@
#define ARDUINO_ARCH_AVR
+#ifndef HAS_WIFI
+#define HAS_WIFI 1
+#endif
+
#define USE_SH1106 1
// default I2C pins:
@@ -46,4 +50,4 @@
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
-#endif
+#endif
\ No newline at end of file