494 lines
15 KiB
C++
494 lines
15 KiB
C++
|
|
/*
|
||
|
|
* File: Menu.cpp
|
||
|
|
*
|
||
|
|
* Created on 22 avril 2022, 17:11
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "Menu.h"
|
||
|
|
|
||
|
|
const char* Menu::modeStr[6] = {"WSPR", "RTTY", "FT8", "HELL", "CW", "IAMBIC"};
|
||
|
|
|
||
|
|
const char* Menu::bandStr[7] = {"160m", "80m", "60m", "40m", "30m", "20m", "free frequency"};
|
||
|
|
|
||
|
|
Menu::Menu() :
|
||
|
|
exitFlag(false),
|
||
|
|
con(new Console())
|
||
|
|
{
|
||
|
|
anchor = this;
|
||
|
|
pinMode(MENU_PIN, INPUT_PULLUP); // GP6 avec résistance interne activée
|
||
|
|
tabfreq[0] = {1838100, -50};
|
||
|
|
tabfreq[1] = {3570100, -150};
|
||
|
|
tabfreq[2] = {5288700, -200};
|
||
|
|
tabfreq[3] = {7040100, -300};
|
||
|
|
tabfreq[4] = {10140200, -400};
|
||
|
|
tabfreq[5] = {14097100, -550};
|
||
|
|
}
|
||
|
|
|
||
|
|
Menu::Menu(const Menu& orig) {
|
||
|
|
}
|
||
|
|
|
||
|
|
Menu::~Menu() {
|
||
|
|
anchor = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::run() {
|
||
|
|
exitFlag = false;
|
||
|
|
if (digitalRead(MENU_PIN) == 0) {
|
||
|
|
EEPROM.begin(sizeof (config));
|
||
|
|
EEPROM.get(0, cfg);
|
||
|
|
Serial.println(F("help command for info"));
|
||
|
|
while (exitFlag == false) {
|
||
|
|
con->run();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Serial.println(F("\nConsole exit"));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::setup() {
|
||
|
|
|
||
|
|
con->onCmd("call", _call_);
|
||
|
|
con->onCmd("freq", _freq_);
|
||
|
|
con->onCmd("minute",_minute_);
|
||
|
|
con->onCmd("offset", _offset_);
|
||
|
|
con->onCmd("gpsbaud", _gpsbaud_);
|
||
|
|
con->onCmd("dbm", _dbm_);
|
||
|
|
con->onCmd("mail", _mail_);
|
||
|
|
con->onCmd("show", _show_);
|
||
|
|
con->onCmd("raz", _raz_);
|
||
|
|
con->onCmd("restart", _restart_);
|
||
|
|
con->onCmd("save", _save_);
|
||
|
|
con->onCmd("exit", _exit_);
|
||
|
|
con->onCmd("help", _help_);
|
||
|
|
con->onCmd("scan", _scan_);
|
||
|
|
con->onCmd("loc", _loc_);
|
||
|
|
con->onCmd("mode", _mode_);
|
||
|
|
con->onCmd("band", _band_);
|
||
|
|
con->onCmd("iambic", _iambic_);
|
||
|
|
con->onCmd("nmea", _nmea_);
|
||
|
|
con->onCmd("wpm", _wpm_);
|
||
|
|
con->onCmd("follow", _follow_);
|
||
|
|
con->onCmd("enigma", _enigma_);
|
||
|
|
|
||
|
|
con->onUnknown(_unknown);
|
||
|
|
con->start();
|
||
|
|
this->run();
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_exit_(ArgList& L, Stream& S) {
|
||
|
|
anchor->exitFlag = true;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_help_(ArgList& L, Stream& S) {
|
||
|
|
S.println(F("Available commands"));
|
||
|
|
S.println(F("Set transmission frequency : freq 7040100"));
|
||
|
|
S.println(F("Set offset value : offset -200"));
|
||
|
|
S.println(F("Set callsign : call F4XYZ"));
|
||
|
|
S.println(F("Set locator : loc JN07"));
|
||
|
|
S.println(F("Set mode wspr rtty ft8 hell cw iaùmbic : mode wspr"));
|
||
|
|
S.println(F("Set band 160,80m,60m,40m,30m,20m,freq : band 40m"));
|
||
|
|
S.println(F("Set modulo in minutes : minute 10"));
|
||
|
|
S.println(F("Set follow mode : follow 1"));
|
||
|
|
S.println(F("Set cw words per minute : wpm 15"));
|
||
|
|
S.println(F("Set iambic mode : iambic B"));
|
||
|
|
S.println(F("Set enigma mode 0 or 1 : enigma 1"));
|
||
|
|
S.println(F("Set transmission power (dBm) : dbm 10"));
|
||
|
|
S.println(F("Set email address : mail f4xyz at example.com"));
|
||
|
|
S.println(F("Set gps baud rate : gpsbaud 9600"));
|
||
|
|
S.println(F("Scan I2C bus : scan"));
|
||
|
|
S.println(F("Show nmea frame 0 or 1 : nmea 1"));
|
||
|
|
S.println(F("Save current configuration to EEPROM : save"));
|
||
|
|
S.println(F("Display current configuration : show"));
|
||
|
|
S.println(F("Reset all parameters to default : raz"));
|
||
|
|
S.println(F("Restart RPI pico : restart"));
|
||
|
|
S.println(F("Show this help message : help"));
|
||
|
|
S.println(F("Exit menu : exit"));
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool Menu::acceptCmd(String cmd, int longMin, int longMax) {
|
||
|
|
|
||
|
|
if (cmd.length() >= longMin && cmd.length() <= longMax) {
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
Serial.println("Erreur");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_unknown(String& L, Stream& S) {
|
||
|
|
S.print(L);
|
||
|
|
S.println(" : command not found");
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_call_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 4, 9);
|
||
|
|
if (ret == true) {
|
||
|
|
p.toUpperCase();
|
||
|
|
size_t len = strlen(p.c_str());
|
||
|
|
|
||
|
|
if (len < sizeof (cfg.call)) {
|
||
|
|
//memcpy(anchor->cfg.call, p.c_str(), len);
|
||
|
|
//anchor->cfg.call[len] = '\0'; // Ajout manuel du terminateur
|
||
|
|
strcpy(anchor->cfg.call, p.c_str());
|
||
|
|
S.printf("Callsign set to: %s\n\r", anchor->cfg.call);
|
||
|
|
} else {
|
||
|
|
S.println(F("Callsign too long. Max 9 characters."));
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid callsign format."));
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_loc_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 4, 4);
|
||
|
|
if (ret == true) {
|
||
|
|
p.toUpperCase();
|
||
|
|
strcpy(anchor->cfg.locator, p.c_str());
|
||
|
|
S.printf("Locator set to: %s\n\r", anchor->cfg.locator);
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid locator format ex JN07"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_mode_(ArgList& L, Stream& S) {
|
||
|
|
String p = L.getNextArg();
|
||
|
|
p.toLowerCase(); // Normalise la casse pour comparaison
|
||
|
|
if (p == "wspr") {
|
||
|
|
anchor->cfg.mode = WSPR;
|
||
|
|
} else if (p == "rtty") {
|
||
|
|
anchor->cfg.mode = RTTY;
|
||
|
|
} else if (p == "ft8") {
|
||
|
|
anchor->cfg.mode = FT8;
|
||
|
|
} else if (p == "hell") {
|
||
|
|
anchor->cfg.mode = HELL;
|
||
|
|
} else if (p == "cw") {
|
||
|
|
anchor->cfg.mode = CW;
|
||
|
|
} else if (p == "iambic") {
|
||
|
|
anchor->cfg.mode = IAMBIC;
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid mode syntax. Example: mode wspr"));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
// Affiche le mode sélectionné
|
||
|
|
S.printf("Mode set to: %s\n\r", modeStr[anchor->cfg.mode]);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_band_(ArgList& L, Stream& S) {
|
||
|
|
String p = L.getNextArg();
|
||
|
|
p.toLowerCase(); // Normalise la casse pour comparaison
|
||
|
|
if (p == "160m") {
|
||
|
|
anchor->cfg.band = M160;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[0].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[0].offset;
|
||
|
|
} else if (p == "80m") {
|
||
|
|
anchor->cfg.band = M80;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[1].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[1].offset;
|
||
|
|
} else if (p == "60m") {
|
||
|
|
anchor->cfg.band = M60;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[2].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[2].offset;
|
||
|
|
} else if (p == "40m") {
|
||
|
|
anchor->cfg.band = M40;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[3].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[3].offset;
|
||
|
|
} else if (p == "30m") {
|
||
|
|
anchor->cfg.band = M30;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[4].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[4].offset;
|
||
|
|
} else if (p == "20m") {
|
||
|
|
anchor->cfg.band = M20;
|
||
|
|
anchor->cfg.freq = anchor->tabfreq[5].freq;
|
||
|
|
anchor->cfg.offset = anchor->tabfreq[5].offset;
|
||
|
|
} else if (p == "freq") {
|
||
|
|
anchor->cfg.band = FREQ;
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid mode syntax. Example: band 40m"));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
// Affiche le mode sélectionné
|
||
|
|
S.printf("Band set to: %s\n\r", bandStr[anchor->cfg.band]);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//manque le test de la fréquence max supportée par le RPI
|
||
|
|
void Menu::_freq_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 6, 8);
|
||
|
|
if (ret == true) {
|
||
|
|
uint32_t freqValue = p.toInt(); // Conversion de la chaîne en entier
|
||
|
|
anchor->cfg.freq = freqValue; // Sauvegarde dans la structure
|
||
|
|
S.printf("Frequency set to: %lu Hz\n\r", anchor->cfg.freq);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_minute_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 2);
|
||
|
|
if (ret == true) {
|
||
|
|
uint8_t minuteValue = (uint8_t) p.toInt(); // Conversion en entier 8 bits
|
||
|
|
anchor->cfg.minute = minuteValue; // Sauvegarde dans la structure
|
||
|
|
S.printf("Minute modulo set to: %u\n\r", anchor->cfg.minute);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_wpm_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 2);
|
||
|
|
if (ret == true) {
|
||
|
|
uint8_t wpm = (uint8_t) p.toInt(); // Conversion en entier 8 bits
|
||
|
|
anchor->cfg.wpm = wpm; // Sauvegarde dans la structure
|
||
|
|
S.printf("WPM set to: %u\n\r", anchor->cfg.wpm);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//facteur de correction
|
||
|
|
void Menu::_offset_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 5);
|
||
|
|
if (ret == true) {
|
||
|
|
int32_t offsetValue = p.toInt(); // Conversion en entier signé
|
||
|
|
anchor->cfg.offset = offsetValue; // Sauvegarde dans la structure
|
||
|
|
S.printf("Offset set to: %ld\n\r", anchor->cfg.offset);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_gpsbaud_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 4, 5);
|
||
|
|
if (ret == true) {
|
||
|
|
uint32_t baudValue = p.toInt(); // Conversion en entier non signé
|
||
|
|
anchor->cfg.baud = baudValue; // Sauvegarde dans la structure
|
||
|
|
S.printf("GPS baudrate set to: %lu\n\r", anchor->cfg.baud);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//les valeurs de dbm sont normalisées la table pour vérification
|
||
|
|
void Menu::_dbm_(ArgList& L, Stream& S) {
|
||
|
|
String p = L.getNextArg();
|
||
|
|
bool ret = anchor->acceptCmd(p, 1, 2);
|
||
|
|
|
||
|
|
if (ret == true) {
|
||
|
|
int inputValue = p.toInt();
|
||
|
|
|
||
|
|
// Tableau des puissances disponibles
|
||
|
|
const uint8_t dbmTable[] = {
|
||
|
|
0, 3, 7, 10, 13, 17, 20, 23, 27, 30,
|
||
|
|
33, 37, 40, 43, 47, 50, 53, 57, 60
|
||
|
|
};
|
||
|
|
const size_t tableSize = sizeof(dbmTable) / sizeof(dbmTable[0]);
|
||
|
|
|
||
|
|
// Recherche de la valeur la plus proche
|
||
|
|
uint8_t closest = dbmTable[0];
|
||
|
|
int minDiff = abs(inputValue - dbmTable[0]);
|
||
|
|
|
||
|
|
for (size_t i = 1; i < tableSize; ++i) {
|
||
|
|
int diff = abs(inputValue - dbmTable[i]);
|
||
|
|
if (diff < minDiff) {
|
||
|
|
minDiff = diff;
|
||
|
|
closest = dbmTable[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Mise à jour de la configuration
|
||
|
|
anchor->cfg.dbm = closest;
|
||
|
|
S.printf("Transmission power set to: %u dBm (closest to %d)\n\r", closest, inputValue);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_mail_(ArgList& L, Stream& S) {
|
||
|
|
String arg;
|
||
|
|
bool ret;
|
||
|
|
String p = "";
|
||
|
|
while (!(arg = L.getNextArg()).isEmpty()) {
|
||
|
|
p = p + arg + " ";
|
||
|
|
}
|
||
|
|
ret = anchor->acceptCmd(p, 3, 30);
|
||
|
|
p.toUpperCase();
|
||
|
|
size_t len = strlen(p.c_str());
|
||
|
|
if (len < sizeof (anchor->cfg.mail)) {
|
||
|
|
//memcpy(anchor->cfg.mail, p.c_str(), len);
|
||
|
|
//anchor->cfg.mail[len] = '\0'; // Ajout manuel du terminateur
|
||
|
|
strcpy(anchor->cfg.mail, p.c_str());
|
||
|
|
S.printf("Email set to: %s\n\r", anchor->cfg.mail);
|
||
|
|
} else {
|
||
|
|
S.println(F("Email too long. Max 30 characters."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_nmea_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 1);
|
||
|
|
if (ret == true) {
|
||
|
|
int val = p.toInt(); // Conversion en entier
|
||
|
|
if (val == 0 || val == 1) {
|
||
|
|
anchor->cfg.nmeaEnabled = (val == 1); // Affectation booléenne
|
||
|
|
|
||
|
|
S.printf("Nmea frame debug %s\n\r", anchor->cfg.nmeaEnabled ? "enabled" : "disabled");
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid value. Use 0 to disable or 1 to enable nmea debug."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_iambic_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 1);
|
||
|
|
if (ret == true) {
|
||
|
|
char val = toupper(p[0]); // Conversion en char
|
||
|
|
if (val == 'A' || val == 'B') {
|
||
|
|
anchor->cfg.bicmd = val; // Affectation booléenne
|
||
|
|
|
||
|
|
S.printf("Iambic type %c\n\r", anchor->cfg.bicmd);
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid value. Use A or B type for iambic paddle."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_follow_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 1);
|
||
|
|
if (ret == true) {
|
||
|
|
int val = p.toInt(); // Conversion en entier
|
||
|
|
if (val == 0 || val == 1) {
|
||
|
|
anchor->cfg.follow = (val == 1); // Affectation booléenne
|
||
|
|
|
||
|
|
S.printf("Follow is %s\n\r", anchor->cfg.follow ? "enabled" : "disabled");
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid value. Use 0 to disable or 1 to enable follow mode."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_enigma_(ArgList& L, Stream& S) {
|
||
|
|
String p;
|
||
|
|
bool ret;
|
||
|
|
p = L.getNextArg();
|
||
|
|
ret = anchor->acceptCmd(p, 1, 1);
|
||
|
|
if (ret == true) {
|
||
|
|
int val = p.toInt(); // Conversion en entier
|
||
|
|
if (val == 0 || val == 1) {
|
||
|
|
anchor->cfg.enigma = (val == 1); // Affectation booléenne
|
||
|
|
|
||
|
|
S.printf("Enigma is %s\n\r", anchor->cfg.enigma ? "enabled" : "disabled");
|
||
|
|
} else {
|
||
|
|
S.println(F("Invalid value. Use 0 to disable or 1 to enable enigma mode."));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_show_(ArgList& L, Stream& S) {
|
||
|
|
S.println("Current configuration :");
|
||
|
|
S.printf(" freq : %lu Hz\n\r", anchor->cfg.freq);
|
||
|
|
S.printf(" offset : %ld\n\r", anchor->cfg.offset);
|
||
|
|
S.printf(" call : %s\n\r", anchor->cfg.call);
|
||
|
|
S.printf(" locator : %s\n\r", anchor->cfg.locator);
|
||
|
|
S.printf(" dbm : %u dBm\n\r", anchor->cfg.dbm);
|
||
|
|
S.printf(" mode : %s\n\r", modeStr[anchor->cfg.mode]);
|
||
|
|
S.printf(" band : %s\n\r", bandStr[anchor->cfg.band]);
|
||
|
|
S.printf(" wpm : %u\n\r", anchor->cfg.wpm);
|
||
|
|
S.printf(" iambic mode : %c\n\r", anchor->cfg.bicmd);
|
||
|
|
S.printf(" Enigma is : %s\n\r", anchor->cfg.enigma ? "ON" : "OFF");
|
||
|
|
S.printf(" mail : %s\n\r", anchor->cfg.mail);
|
||
|
|
S.printf(" minute : %u min\n\r", anchor->cfg.minute);
|
||
|
|
S.printf(" Gps baud rate : %u\n\r", anchor->cfg.baud);
|
||
|
|
S.printf(" Nmea debug is : %s\n\r", anchor->cfg.nmeaEnabled ? "ON" : "OFF");
|
||
|
|
S.printf(" Follow is : %s\n\r", anchor->cfg.follow ? "ON" : "OFF");
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_save_(ArgList& L, Stream& S) {
|
||
|
|
EEPROM.put(0, anchor->cfg);
|
||
|
|
EEPROM.commit();
|
||
|
|
Serial.println("Configuration saved.");
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_raz_(ArgList& L, Stream& S) {
|
||
|
|
|
||
|
|
anchor->cfg.freq = 7040100; // Fréquence par défaut
|
||
|
|
anchor->cfg.offset = -200; // Fréquence par défaut
|
||
|
|
strcpy(anchor->cfg.call, "NOCALL"); // Indicatif par défaut
|
||
|
|
anchor->cfg.dbm = 10; // Puissance par défaut
|
||
|
|
strcpy(anchor->cfg.mail, "none@example.com"); // Email par défaut
|
||
|
|
strcpy(anchor->cfg.locator, "JN07"); // Locator par défaut
|
||
|
|
anchor->cfg.minute = 6; // Durée par défaut
|
||
|
|
anchor->cfg.baud=9600; //9600 bauds
|
||
|
|
anchor->cfg.mode=WSPR;
|
||
|
|
anchor->cfg.nmeaEnabled=false;
|
||
|
|
anchor->cfg.wpm=12;
|
||
|
|
anchor->cfg.bicmd='A';
|
||
|
|
anchor->cfg.follow=0;
|
||
|
|
anchor->cfg.enigma=0;
|
||
|
|
anchor->cfg.band = FREQ;
|
||
|
|
Serial.println("Configuration has been reset to default values.");
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::_restart_(ArgList& L, Stream& S) {
|
||
|
|
watchdog_reboot(0, 0, 0); // Redémarre immédiatement
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void Menu::_scan_(ArgList& L, Stream& S) {
|
||
|
|
anchor->scanI2C();
|
||
|
|
}
|
||
|
|
|
||
|
|
void Menu::scanI2C() {
|
||
|
|
Serial.println(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f");
|
||
|
|
for (uint8_t row = 0; row < 8; row++) {
|
||
|
|
Serial.printf("%02x: ", row << 4);
|
||
|
|
for (uint8_t col = 0; col < 16; col++) {
|
||
|
|
uint8_t address = (row << 4) | col;
|
||
|
|
Wire.beginTransmission(address);
|
||
|
|
uint8_t error = Wire.endTransmission();
|
||
|
|
|
||
|
|
if (error == 0) {
|
||
|
|
Serial.printf("%02x ", address);
|
||
|
|
} else if (error == 4) {
|
||
|
|
Serial.print("UU "); // Bus error
|
||
|
|
} else {
|
||
|
|
Serial.print("-- ");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Serial.println();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
Menu* Menu::anchor = NULL;
|
||
|
|
|