add signal strength meter

This commit is contained in:
Kyle Isom 2023-10-07 13:38:17 -07:00
parent 63faf519c1
commit e5cf44c3a6
14 changed files with 414 additions and 148 deletions

View File

@ -1,3 +1,4 @@
#BOARD := featheresp32
BOARD := sparkfun_esp32micromod BOARD := sparkfun_esp32micromod
FIRMWARE := .pioenvs/$(BOARD)/firmware.bin FIRMWARE := .pioenvs/$(BOARD)/firmware.bin
SOURCES := \ SOURCES := \

View File

@ -2,7 +2,7 @@
#define KIMODEM_PREFS_H #define KIMODEM_PREFS_H
namespace config { namespace Config {
// Networking // Networking
@ -14,6 +14,11 @@ void SetStartTryConnecting(bool opt);
// Misc. // Misc.
bool EnableMeter();
void SetEnableMeter(bool opt);
// Misc. control
void FactoryDefaults(); void FactoryDefaults();
} }

View File

@ -6,29 +6,20 @@
#define ANSI_CLEAR_SCREEN "\33[2J" #define ANSI_CLEAR_SCREEN "\33[2J"
/* namespace Display {
class Display {
public:
Display();
void Clear(); void Init();
void Draw(); void Clear();
bool HasDisplay(); void Clear(bool hint);
void Draw();
bool HasDisplay();
void Print(const char *);
void Println(const char *);
void SetCursor(int16_t x, int16_t y);
} // namespace Display
void Print(const char *);
void Println(const char *);
void SetCursor(int16_t x, int16_t y);
};
*/
#if defined(ADAFRUIT_OLED)
#include "internal/DisplayAdafruitOLED.h"
#else
#include "internal/DisplayNone.h"
#endif #endif
static Display display;
#endif

20
include/WiFiMeter.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef KIMODEM_WIFI_METER_H
#define KIMODEM_WIFI_METER_H
#include <Arduino.h>
namespace Meter {
void Begin();
void Enable();
void Disable();
void Update();
}
#endif

View File

@ -10,6 +10,7 @@ bool SetupWiFi();
bool Autoconnect(Dictionary &pb); bool Autoconnect(Dictionary &pb);
bool Autoconnect(Dictionary &pb, bool reset); bool Autoconnect(Dictionary &pb, bool reset);
bool TryConnect(Dictionary &pb); bool TryConnect(Dictionary &pb);
void WiFiRefresh(Dictionary &pb);
#endif #endif

View File

@ -1,26 +0,0 @@
#ifndef KIMODEM_ADAFRUIT_OLED_H
#define KIMODEM_ADAFRUIT_OLED_H
#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
class Display {
public:
Display();
void Clear();
void Draw();
bool HasDisplay();
void Print(const char *);
void Println(const char *);
void SetCursor(int16_t x, int16_t y);
private:
Adafruit_SSD1306 oled;
};
#endif

View File

@ -1,20 +0,0 @@
#ifndef KIMODEM_DISPLAY_SERIAL
#define KIMODEM_DISPLAY_SERIAL
#include <Arduino.h>
class Display {
public:
Display() {};
void Clear();
void Draw();
bool HasDisplay();
void Print(const char *);
void Println(const char *);
void SetCursor(int16_t x, int16_t y);
};
#endif

View File

@ -13,6 +13,8 @@ framework = arduino
platform = espressif32 platform = espressif32
monitor_speed = 115200 monitor_speed = 115200
extra_scripts = scripts/download_fs.py extra_scripts = scripts/download_fs.py
monitor_filters =
esp32_exception_decoder
[env:featheresp32] [env:featheresp32]
board = featheresp32 board = featheresp32
@ -27,7 +29,13 @@ lib_deps =
board = sparkfun_esp32micromod board = sparkfun_esp32micromod
build_flags = build_flags =
-DSPARKFUN_HYPERDISPLAY -DSPARKFUN_HYPERDISPLAY
-DDISPLAY_NONE -DAPA102_ENABLED
lib_deps =
sparkfun/SparkFun HyperDisplay@^2.0.1
sparkfun/SparkFun HyperDisplay ILI9341@^1.0.0
sparkfun/SparkFun HyperDisplay 4DLCD-320240@^1.0.0
pololu/APA102@^3.0.0
[env:d1mini] [env:d1mini]
board = wemos_d1_mini32 board = wemos_d1_mini32

View File

@ -1,8 +1,9 @@
#include <Preferences.h> #include <Preferences.h>
#include "prefs.h"
#include "Config.h"
namespace config { namespace Config {
static bool isLoaded = false; static bool isLoaded = false;
@ -61,6 +62,22 @@ SetStartTryConnecting(bool opt)
} }
bool
EnableMeter()
{
checkReady();
return preferences.getBool("WCM", true);
}
void
SetEnableMeter(bool opt)
{
checkReady();
preferences.putBool("WCM", opt);
}
void void
FactoryDefaults() FactoryDefaults()
{ {

View File

@ -5,64 +5,84 @@
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> #include <Adafruit_SSD1306.h>
#include "internal/DisplayAdafruitOLED.h" #include "Display.h"
static Adafruit_SSD1306 oled(SSD1306_SWITCHCAPVCC, 0x3C); namespace Display {
static Adafruit_SSD1306 oled(SSD1306_SWITCHCAPVCC, 0x3C);
void
Display::Display() Init()
: oled(oled)
{ {
Serial.println("initialized display"); oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.display();
oled.clearDisplay();
oled.setTextSize(1); oled.setTextSize(1);
oled.setTextColor(SSD1306_WHITE); oled.setTextColor(WHITE);
oled.fillScreen(BLACK);
oled.display();
Serial.println("DISP INIT");
}
void
Clear()
{
Clear(false);
} }
void void
Display::Clear() Clear(bool hint)
{ {
this->oled.clearDisplay(); oled.clearDisplay();
this->SetCursor(0, 0); SetCursor(0, 0);
this->Draw(); oled.display();
} }
void void
Display::Draw() Draw()
{ {
this->oled.display(); oled.display();
} }
bool bool
Display::HasDisplay() HasDisplay()
{ {
return true; return true;
} }
void void
Display::Print(const char *s) Print(const char *s)
{ {
this->oled.print(s); oled.print(s);
Serial.print(s);
oled.display();
} }
void void
Display::Println(const char *s) Println(const char *s)
{ {
this->oled.println(s); oled.println(s);
Serial.println(s);
oled.display();
} }
void void
Display::SetCursor(int16_t x, int16_t y) SetCursor(int16_t x, int16_t y)
{ {
this->oled.setCursor(x, y); oled.setCursor(x, y);
} }
#endif } // namespace Display
#endif

View File

@ -0,0 +1,88 @@
#if defined(SPARKFUN_HYPERDISPLAY)
#include <Arduino.h>
#include <HyperDisplay_4DLCD-320240_4WSPI.h>
#include "Display.h"
namespace Display {
static LCD320240_4WSPI tft;
static ILI9341_color_18_t defaultColor;
static uint16_t line = 0;
void
Init()
{
tft.begin(D1, D0, PWM0, SPI, 32000000);
tft.setInterfacePixelFormat(ILI9341_PXLFMT_18);
tft.clearDisplay();
defaultColor = tft.rgbTo18b(255, 255, 255);
tft.setCurrentWindowColorSequence((color_t)&defaultColor);
}
void
Clear()
{
Clear(false);
}
void
Clear(bool hint)
{
if (hint) {
return;
}
tft.clearDisplay();
SetCursor(0, 0);
line = 0;
}
void
Draw()
{
}
bool
HasDisplay()
{
return true;
}
void
Print(const char *s)
{
tft.print(s);
Serial.print(s);
}
void
Println(const char *s)
{
tft.println(s);
Serial.println(s);
line++;
SetCursor(0, line*10);
}
void
SetCursor(int16_t x, int16_t y)
{
tft.setTextCursor(x, y);
}
} // namespace Display
#endif

132
src/WiFiMeter.cc Normal file
View File

@ -0,0 +1,132 @@
#include <Arduino.h>
#include <WiFi.h>
#include "Config.h"
#include "WiFiMeter.h"
namespace Meter {
static bool enabled = false;
#if defined(APA102_ENABLED)
#include <APA102.h>
constexpr uint8_t APA102_DATA = 25;
constexpr uint8_t APA102_CLOCK = 15;
constexpr uint8_t APA102_COUNT = 6;
constexpr uint8_t APA102_BRIGHTNESS = 5;
APA102<APA102_DATA, APA102_CLOCK> ledBar;
static void
setLED(uint8_t brightness)
{
brightness = brightness & 0x1f;
ledBar.sendColor(0, 0, 255, brightness);
}
static void
clearBar()
{
ledBar.startFrame();
for (int i = 0; i < APA102_COUNT; i++) {
setLED(0);
}
ledBar.endFrame(APA102_COUNT);
}
static void
setLedCount(uint8_t on)
{
ledBar.startFrame();
for (int i = 0; i < APA102_COUNT; i++) {
if (i >= on) {
setLED(0);
} else {
setLED(APA102_BRIGHTNESS);
}
}
ledBar.endFrame(APA102_CLOCK);
}
void
Begin()
{
enabled = Config::EnableMeter();
}
void
Enable()
{
enabled = true;
Config::SetEnableMeter(true);
}
void
Disable()
{
enabled = false;
Config::SetEnableMeter(false);
}
void
Update()
{
if (!enabled) {
return;
}
int8_t rssi;
uint8_t count = 0;
if (WiFi.status() != WL_CONNECTED) {
rssi = -127;
} else {
rssi = WiFi.RSSI();
}
if (rssi >= -30) {
count = 6;
} else if (rssi >= -55) {
count = 5;
} else if (rssi >= -67) {
count = 4;
} else if (rssi >= -70) {
count = 3;
} else if (rssi >= -80) {
count = 2;
} else if (rssi >= -90) {
count = 1;
} else {
count = 0;
}
setLedCount(count);
}
#else
void Begin() {}
void Enable() {}
void Disable() {}
void Update() {}
#endif
}

View File

@ -2,10 +2,11 @@
#include <WiFi.h> #include <WiFi.h>
#include <string.h> #include <string.h>
#include "Config.h"
#include "Dictionary.h" #include "Dictionary.h"
#include "Display.h" #include "Display.h"
#include "WiFiMeter.h"
#include "TLV.h" #include "TLV.h"
#include "prefs.h"
#include "WiFiMgr.h" #include "WiFiMgr.h"
@ -14,6 +15,10 @@
#define CONN_WAIT 250 #define CONN_WAIT 250
static TLV::Record ssidrec;
static TLV::Record wpakeyrec;
bool bool
SetupWiFi() SetupWiFi()
{ {
@ -27,32 +32,30 @@ tryConnect(const char *ssid, const char *wpakey)
{ {
size_t waitedFor = 0; size_t waitedFor = 0;
Serial.print("CONNECT "); Display::Print("CONNECT ");
Serial.println(ssid); Display::Println(ssid);
WiFi.begin(ssid, wpakey); WiFi.begin(ssid, wpakey);
while ((WiFi.status() != WL_CONNECTED) && (waitedFor < MAX_WAIT)) { while ((WiFi.status() != WL_CONNECTED) && (waitedFor < MAX_WAIT)) {
waitedFor += CONN_WAIT; waitedFor += CONN_WAIT;
if ((waitedFor % 1000) == 0) { if ((waitedFor % 1000) == 0) {
Serial.print("."); Display::Print(".");
} }
delay(250); delay(250);
} }
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED) {
Serial.print("MODEM ADDR "); Display::Clear(true);
Serial.println(WiFi.localIP()); Display::Print("SSID: ");
Display::Println(ssid);
display.Clear(); Display::Print("IP: ");
display.Print("SSID: "); Display::Println(WiFi.localIP().toString().c_str());
display.Println(ssid);
display.Print("IP: "); Config::SetLastSSID(ssid);
display.Println(WiFi.localIP().toString().c_str());
display.Draw();
return true; return true;
} }
Serial.println("CARRIER SIGNAL LOST"); Display::Println("CARRIER SIGNAL LOST");
return false; return false;
} }
@ -60,30 +63,28 @@ tryConnect(const char *ssid, const char *wpakey)
bool bool
TryConnect(Dictionary &pb) TryConnect(Dictionary &pb)
{ {
TLV::Record ssid;
TLV::Record wpakey;
uint8_t *cursor; uint8_t *cursor;
if ((ssid.Len = config::LastSSID(ssid.Val, 32)) != 0) { if ((ssidrec.Len = Config::LastSSID(ssidrec.Val, 32)) != 0) {
Serial.print("LAST SSID: "); Display::Print("LAST SSID: ");
Serial.println(ssid.Val); Display::Println(ssidrec.Val);
if (pb.Lookup(ssid.Val, ssid.Len, wpakey)) { if (pb.Lookup(ssidrec.Val, ssidrec.Len, wpakeyrec)) {
if (tryConnect((const char *)ssid.Val, (const char *)wpakey.Val)) { if (tryConnect((const char *)ssidrec.Val, (const char *)wpakeyrec.Val)) {
return true; return true;
} }
} else { } else {
Serial.println("WPAKEY NOT FOUND"); Display::Println("WPAKEY NOT FOUND");
} }
} }
while ((cursor != NULL) && (cursor[0] != TAG_EMPTY)) { while ((cursor != NULL) && (cursor[0] != TAG_EMPTY)) {
TLV::ReadFromMemory(ssid, cursor); TLV::ReadFromMemory(ssidrec, cursor);
TLV::SkipRecord(ssid, cursor); TLV::SkipRecord(ssidrec, cursor);
TLV::ReadFromMemory(wpakey, cursor); TLV::ReadFromMemory(wpakeyrec, cursor);
TLV::SkipRecord(ssid, cursor); TLV::SkipRecord(wpakeyrec, cursor);
if (tryConnect(ssid.Val, wpakey.Val)) { if (tryConnect(ssidrec.Val, wpakeyrec.Val)) {
return true; return true;
} }
} }
@ -103,16 +104,16 @@ tryConnect(Dictionary &pb, int network)
return false; return false;
} }
Serial.print("MODEM: CHECK "); Display::Print("MODEM: CHECK ");
Serial.print(ssid); Display::Print(ssid);
Serial.print(": "); Display::Print(": ");
if (!pb.Lookup(ssid, uint8_t(ssidLen), password)) { if (!pb.Lookup(ssid, uint8_t(ssidLen), password)) {
Serial.println("NOT FOUND"); Display::Println("NOT FOUND");
return false; return false;
} }
Serial.println("CONNECTING"); Display::Println("CONNECTING");
return tryConnect(ssid, password.Val); return tryConnect(ssid, password.Val);
} }
@ -129,15 +130,15 @@ Autoconnect(Dictionary &pb, bool reset)
int networkCount = 0; int networkCount = 0;
int network = 0; int network = 0;
Serial.println("MODEM: TRY AUTOCONNECT"); Display::Println("MODEM: TRY AUTOCONNECT");
if (reset) { if (reset) {
Serial.println("RADIO RESET"); Display::Println("RADIO RESET");
SetupWiFi(); SetupWiFi();
WiFi.disconnect(); WiFi.disconnect();
delay(1000); delay(1000);
} else { } else {
Serial.println("NO RESET"); Display::Println("NO RESET");
} }
networkCount = WiFi.scanNetworks(); networkCount = WiFi.scanNetworks();
@ -147,7 +148,31 @@ Autoconnect(Dictionary &pb, bool reset)
} }
} }
Serial.println("NO CARRIER"); Display::Println("NO CARRIER");
return false; return false;
} }
bool
Reconnect(Dictionary &pb)
{
if (!tryConnect(ssidrec.Val, wpakeyrec.Val)) {
return TryConnect(pb);
}
return true;
}
void
WiFiRefresh(Dictionary &pb)
{
Meter::Update();
if (WiFi.status() == WL_CONNECTED) {
return;
}
Display::Println("CARRIER SIGNAL LOST: ATC");
Reconnect(pb);
}

View File

@ -2,10 +2,11 @@
#include <SPIFFS.h> #include <SPIFFS.h>
#include "Arena.h" #include "Arena.h"
#include "Config.h"
#include "Dictionary.h" #include "Dictionary.h"
#include "Display.h" #include "Display.h"
#include "WiFiMgr.h" #include "WiFiMgr.h"
#include "prefs.h" #include "WiFiMeter.h"
#include "homenet.h" #include "homenet.h"
@ -23,31 +24,31 @@ setupPhonebook()
size_t fileSize = pbFile.size(); size_t fileSize = pbFile.size();
bool ok = false; bool ok = false;
Serial.print("DAT FILE "); Display::Print("DAT FILE ");
Serial.print(fileSize); Display::Print(String(fileSize).c_str());
Serial.println("B"); Display::Println("B");
if (fileSize == 0) { if (fileSize == 0) {
Serial.println("INIT PHONEBOOK"); Display::Println("INIT PHONEBOOK");
phonebook.Set(HOME_SSID, HOME_SSIDLEN, HOME_WPA, HOME_WPALEN); phonebook.Set(HOME_SSID, HOME_SSIDLEN, HOME_WPA, HOME_WPALEN);
if (WriteArena(arena, pbFilePath) == 0) { if (WriteArena(arena, pbFilePath) == 0) {
ok = true; ok = true;
} }
pbFile.close(); pbFile.close();
config::SetLastSSID(HOME_SSID); Config::SetLastSSID(HOME_SSID);
return ok; return ok;
} }
fileSize = fileSize > PHONEBOOK_SIZE ? PHONEBOOK_SIZE : fileSize; fileSize = fileSize > PHONEBOOK_SIZE ? PHONEBOOK_SIZE : fileSize;
Serial.print("LOAD PHONEBOOK "); Display::Print("LOAD PHONEBOOK ");
if (fileSize != pbFile.read(phonebookBuffer, fileSize)) { if (fileSize != pbFile.read(phonebookBuffer, fileSize)) {
Serial.println("FAILED"); Display::Println("FAILED");
pbFile.close(); pbFile.close();
return false; return false;
} }
Serial.println("OK"); Display::Println("OK");
pbFile.close(); pbFile.close();
phonebook.DumpKVPairs(); phonebook.DumpKVPairs();
return true; return true;
@ -56,32 +57,35 @@ setupPhonebook()
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
while (!Serial) ; Display::Init();
display.Clear(); Display::Println("MODEM BOOT");
Display::Clear();
Serial.println("MODEM BOOT"); Display::Println("MODEM BOOT");
InitializeArena(arena); InitializeArena(arena);
NewStaticArena(arena, phonebookBuffer, PHONEBOOK_SIZE); NewStaticArena(arena, phonebookBuffer, PHONEBOOK_SIZE);
Meter::Begin();
Meter::Enable();
while (true); Display::Println("SPIFFS INIT");
if (!SPIFFS.begin(true) && !SPIFFS.begin(false)) { if (!SPIFFS.begin(true) && !SPIFFS.begin(false)) {
Serial.println("SPIFFS BEGIN FAIL"); Display::Println("SPIFFS BEGIN FAIL");
while (true) ; while (true) ;
} }
setupPhonebook(); setupPhonebook();
if (config::StartTryConnecting()) { if (Config::StartTryConnecting()) {
Display::Println("AUTO ATC");
if (!TryConnect(phonebook)) { if (!TryConnect(phonebook)) {
Autoconnect(phonebook); Autoconnect(phonebook);
} }
} }
Serial.println("MODEM READY"); Display::Println("MODEM READY");
} }
void loop() { void loop() {
// put your main code here, to run repeatedly: delay(1000);
Meter::Update();
} }