bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
- if (bt_enabled) bt_start();
+ if (bt_enabled && !console_active) bt_start();
return true;
} else {
return false;
bool bt_enabled = false;
bool bt_allow_pairing = false;
+ #define M_FRQ_S 27388122
+ #define M_FRQ_R 27388061
+ bool console_active = false;
+ bool sx1276_installed = false;
+
#if defined(__AVR_ATmega1284P__)
#define PLATFORM PLATFORM_AVR
#define MCU_VARIANT MCU_1284P
--- /dev/null
+#include <FS.h>
+#include <SPIFFS.h>
+#include <WiFi.h>
+#include <WebServer.h>
+
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#include "esp32c3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/rtc.h"
+#else
+#error Target CONFIG_IDF_TARGET is not supported
+#endif
+
+// Replace with your network credentials
+const char* ssid = "RNode Test";
+const char* password = "somepass";
+
+WebServer server(80);
+
+void console_dbg(String msg) {
+ Serial.print("[Webserver] ");
+ Serial.println(msg);
+}
+
+bool exists(String path){
+ bool yes = false;
+ File file = SPIFFS.open(path, "r");
+ if(!file.isDirectory()){
+ yes = true;
+ }
+ file.close();
+ return yes;
+}
+
+String console_get_content_type(String filename) {
+ if (server.hasArg("download")) {
+ return "application/octet-stream";
+ } else if (filename.endsWith(".htm")) {
+ return "text/html";
+ } else if (filename.endsWith(".html")) {
+ return "text/html";
+ } else if (filename.endsWith(".css")) {
+ return "text/css";
+ } else if (filename.endsWith(".js")) {
+ return "application/javascript";
+ } else if (filename.endsWith(".png")) {
+ return "image/png";
+ } else if (filename.endsWith(".gif")) {
+ return "image/gif";
+ } else if (filename.endsWith(".jpg")) {
+ return "image/jpeg";
+ } else if (filename.endsWith(".ico")) {
+ return "image/x-icon";
+ } else if (filename.endsWith(".xml")) {
+ return "text/xml";
+ } else if (filename.endsWith(".pdf")) {
+ return "application/x-pdf";
+ } else if (filename.endsWith(".zip")) {
+ return "application/x-zip";
+ } else if (filename.endsWith(".gz")) {
+ return "application/x-gzip";
+ }
+ return "text/plain";
+}
+
+bool console_serve_file(String path) {
+ console_dbg("Request for: "+path);
+ if (path.endsWith("/")) {
+ path += "index.html";
+ }
+
+ String content_type = console_get_content_type(path);
+ String pathWithGz = path + ".gz";
+ if (exists(pathWithGz) || exists(path)) {
+ if (exists(pathWithGz)) {
+ path += ".gz";
+ }
+
+ File file = SPIFFS.open(path, "r");
+ console_dbg("Serving file to client");
+ server.streamFile(file, content_type);
+ file.close();
+
+ console_dbg("File serving done");
+ return true;
+ }
+
+ console_dbg("Error: Could not open file for serving");
+ return false;
+}
+
+void console_register_pages() {
+ server.onNotFound([]() {
+ if (!console_serve_file(server.uri())) {
+ server.send(404, "text/plain", "Not Found");
+ }
+ });
+}
+
+void console_start() {
+ Serial.println("");
+ console_dbg("Starting Access Point...");
+ // WiFi.softAP(ssid, password);
+ WiFi.softAP(bt_devname, password);
+ delay(150);
+ IPAddress ip(10, 0, 0, 1);
+ IPAddress nm(255, 255, 255, 0);
+ WiFi.softAPConfig(ip, ip, nm);
+
+ if(!SPIFFS.begin(true)){
+ console_dbg("Error: Could not mount SPIFFS");
+ return;
+ } else {
+ console_dbg("SPIFFS Ready");
+ }
+
+ console_register_pages();
+ server.begin();
+ led_indicate_console();
+}
+
+void console_loop(){
+ server.handleClient();
+
+ // Internally, this yields the thread and allows
+ // other tasks to run.
+ delay(5);
+}
+
+// void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
+// Serial.printf("Listing directory: %s\r\n", dirname);
+
+// File root = fs.open(dirname);
+// if(!root){
+// Serial.println("- failed to open directory");
+// return;
+// }
+// if(!root.isDirectory()){
+// Serial.println(" - not a directory");
+// return;
+// }
+
+// File file = root.openNextFile();
+// while(file){
+// if(file.isDirectory()){
+// Serial.print(" DIR : ");
+// Serial.println(file.name());
+// if(levels){
+// listDir(fs, file.path(), levels -1);
+// }
+// } else {
+// Serial.print(" FILE: ");
+// Serial.print(file.name());
+// Serial.print("\tSIZE: ");
+// Serial.println(file.size());
+// }
+// file = root.openNextFile();
+// }
+// }
+
+// void readFile(fs::FS &fs, const char * path){
+// Serial.printf("Reading file: %s\r\n", path);
+
+// File file = fs.open(path);
+// if(!file || file.isDirectory()){
+// Serial.println("− failed to open file for reading");
+// return;
+// }
+
+// Serial.println("− read from file:");
+// while(file.available()){
+// Serial.write(file.read());
+// }
+// }
--- /dev/null
+<!doctype html>
+<html>
+<head>
+<style type="text/css">
+ :root{--background-body:#fff;--background:#efefef;--background-alt:#f7f7f7;--selection:#9e9e9e;--text-main:#363636;--text-bright:#000;--text-muted:#70777f;--links:#0076d1;--focus:#0096bfab;--border:#dbdbdb;--code:#000;--animation-duration:0.1s;--button-base:#d0cfcf;--button-hover:#9b9b9b;--scrollbar-thumb:rgb(170, 170, 170);--scrollbar-thumb-hover:var(--button-hover);--form-placeholder:#949494;--form-text:#1d1d1d;--variable:#39a33c;--highlight:#ff0;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23161f27'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E")}div.top_menu{font-size:1.1em}div.lang_menu{margin-bottom:0.35em}@media (prefers-color-scheme: dark){:root{--background-body:#202b38;--background:#161f27;--background-alt:#1a242f;--selection:#1c76c5;--text-main:#dbdbdb;--text-bright:#fff;--text-muted:#a9b1ba;--links:#41adff;--focus:#0096bfab;--border:#526980;--code:#ffbe85;--animation-duration:0.1s;--button-base:#0c151c;--button-hover:#040a0f;--scrollbar-thumb:var(--button-hover);--scrollbar-thumb-hover:rgb(0, 0, 0);--form-placeholder:#a9a9a9;--form-text:#fff;--variable:#d941e2;--highlight:#efdb43;--select-arrow:url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23efefef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E")}}html{scrollbar-color:rgb(170, 170, 170) #fff;scrollbar-color:var(--scrollbar-thumb) var(--background-body);scrollbar-width:thin}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}@media (prefers-color-scheme: dark){html{scrollbar-color:#040a0f #202b38;scrollbar-color:var(--scrollbar-thumb) var(--background-body)}}body{font-family:system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif;line-height:1.4;max-width:800px;margin:20px auto;padding:0 10px;word-wrap:break-word;color:#363636;color:var(--text-main);background:#fff;background:var(--background-body);text-rendering:optimizeLegibility}@media (prefers-color-scheme: dark){body{background:#202b38;background:var(--background-body)}}@media (prefers-color-scheme: dark){body{color:#dbdbdb;color:var(--text-main)}}li{margin-top:0.5em;margin-bottom:0.5em}button{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){button{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}}input{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){input{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}}textarea{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}@media (prefers-color-scheme: dark){textarea{transition:background-color 0.1s linear, border-color 0.1s linear, color 0.1s linear, box-shadow 0.1s linear, transform 0.1s ease;transition:background-color var(--animation-duration) linear, border-color var(--animation-duration) linear, color var(--animation-duration) linear, box-shadow var(--animation-duration) linear, transform var(--animation-duration) ease}}h1{font-size:2.2em;margin-top:0}h1,h2,h3,h4,h5,h6{margin-bottom:12px;margin-top:24px}h1{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h1{color:#fff;color:var(--text-bright)}}h2{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h2{color:#fff;color:var(--text-bright)}}h3{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h3{color:#fff;color:var(--text-bright)}}h4{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h4{color:#fff;color:var(--text-bright)}}h5{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h5{color:#fff;color:var(--text-bright)}}h6{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){h6{color:#fff;color:var(--text-bright)}}strong{color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){strong{color:#fff;color:var(--text-bright)}}b,h1,h2,h3,h4,h5,h6,strong,th{font-weight:600}q::before{content:none}q::after{content:none}blockquote{border-left:4px solid #0096bfab;border-left:4px solid var(--focus);margin:1.5em 0;padding:0.5em 1em;font-style:italic}@media (prefers-color-scheme: dark){blockquote{border-left:4px solid #0096bfab;border-left:4px solid var(--focus)}}q{border-left:4px solid #0096bfab;border-left:4px solid var(--focus);margin:1.5em 0;padding:0.5em 1em;font-style:italic}@media (prefers-color-scheme: dark){q{border-left:4px solid #0096bfab;border-left:4px solid var(--focus)}}blockquote > footer{font-style:normal;border:0}blockquote cite{font-style:normal}address{font-style:normal}a[href^='mailto\:']::before{content:'📧 '}a[href^='tel\:']::before{content:'📞 '}a[href^='sms\:']::before{content:'💬 '}mark{background-color:#ff0;background-color:var(--highlight);border-radius:2px;padding:0 2px;color:#000}@media (prefers-color-scheme: dark){mark{background-color:#efdb43;background-color:var(--highlight)}}a > code,a > strong{color:inherit}button,input[type='submit'],input[type='reset'],input[type='button'],input[type='checkbox'],input[type='range'],input[type='radio'],select{cursor:pointer}input,select{display:block}[type='checkbox'],[type='radio']{display:initial}input{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){input{background-color:#161f27;background-color:var(--background)}}@media (prefers-color-scheme: dark){input{color:#fff;color:var(--form-text)}}button{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){button{background-color:#161f27;background-color:var(--background)}}@media (prefers-color-scheme: dark){button{color:#fff;color:var(--form-text)}}textarea{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){textarea{background-color:#161f27;background-color:var(--background)}}@media (prefers-color-scheme: dark){textarea{color:#fff;color:var(--form-text)}}select{color:#1d1d1d;color:var(--form-text);background-color:#efefef;background-color:var(--background);font-family:inherit;font-size:inherit;margin-right:6px;margin-bottom:6px;padding:10px;border:none;border-radius:6px;outline:none}@media (prefers-color-scheme: dark){select{background-color:#161f27;background-color:var(--background)}}@media (prefers-color-scheme: dark){select{color:#fff;color:var(--form-text)}}button{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){button{background-color:#0c151c;background-color:var(--button-base)}}input[type='submit']{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type='submit']{background-color:#0c151c;background-color:var(--button-base)}}input[type='reset']{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type='reset']{background-color:#0c151c;background-color:var(--button-base)}}input[type='button']{background-color:#d0cfcf;background-color:var(--button-base);padding-right:30px;padding-left:30px}@media (prefers-color-scheme: dark){input[type='button']{background-color:#0c151c;background-color:var(--button-base)}}button:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){button:hover{background:#040a0f;background:var(--button-hover)}}input[type='submit']:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type='submit']:hover{background:#040a0f;background:var(--button-hover)}}input[type='reset']:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type='reset']:hover{background:#040a0f;background:var(--button-hover)}}input[type='button']:hover{background:#9b9b9b;background:var(--button-hover)}@media (prefers-color-scheme: dark){input[type='button']:hover{background:#040a0f;background:var(--button-hover)}}input[type='color']{min-height:2rem;padding:8px;cursor:pointer}input[type='checkbox'],input[type='radio']{height:1em;width:1em}input[type='radio']{border-radius:100%}input{vertical-align:top}label{vertical-align:middle;margin-bottom:4px;display:inline-block}input:not([type='checkbox']):not([type='radio']),input[type='range'],select,button,textarea{-webkit-appearance:none}textarea{display:block;margin-right:0;box-sizing:border-box;resize:vertical}textarea:not([cols]){width:100%}textarea:not([rows]){min-height:40px;height:140px}select{background:#efefef url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23161f27'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat;padding-right:35px}@media (prefers-color-scheme: dark){select{background:#161f27 url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23efefef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat}}@media (prefers-color-scheme: dark){select{background:#161f27 url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23efefef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat}}@media (prefers-color-scheme: dark){select{background:#161f27 url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23efefef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat}}@media (prefers-color-scheme: dark){select{background:#161f27 url("data:image/svg+xml;charset=utf-8,%3C?xml version='1.0' encoding='utf-8'?%3E %3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' height='62.5' width='116.9' fill='%23efefef'%3E %3Cpath d='M115.3,1.6 C113.7,0 111.1,0 109.5,1.6 L58.5,52.7 L7.4,1.6 C5.8,0 3.2,0 1.6,1.6 C0,3.2 0,5.8 1.6,7.4 L55.5,61.3 C56.3,62.1 57.3,62.5 58.4,62.5 C59.4,62.5 60.5,62.1 61.3,61.3 L115.2,7.4 C116.9,5.8 116.9,3.2 115.3,1.6Z'/%3E %3C/svg%3E") calc(100% - 12px) 50% / 12px no-repeat;background:var(--background) var(--select-arrow) calc(100% - 12px) 50% / 12px no-repeat}}select::-ms-expand{display:none}select[multiple]{padding-right:10px;background-image:none;overflow-y:auto}input:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){input:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}}select:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){select:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}}button:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){button:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}}textarea:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}@media (prefers-color-scheme: dark){textarea:focus{box-shadow:0 0 0 2px #0096bfab;box-shadow:0 0 0 2px var(--focus)}}input[type='checkbox']:active,input[type='radio']:active,input[type='submit']:active,input[type='reset']:active,input[type='button']:active,input[type='range']:active,button:active{transform:translateY(2px)}button:disabled,input:disabled,select:disabled,textarea:disabled{cursor:not-allowed;opacity:0.5}::-moz-placeholder{color:#949494;color:var(--form-placeholder)}:-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::-ms-input-placeholder{color:#949494;color:var(--form-placeholder)}::placeholder{color:#949494;color:var(--form-placeholder)}@media (prefers-color-scheme: dark){::-moz-placeholder{color:#a9a9a9;color:var(--form-placeholder)}:-ms-input-placeholder{color:#a9a9a9;color:var(--form-placeholder)}::-ms-input-placeholder{color:#a9a9a9;color:var(--form-placeholder)}::placeholder{color:#a9a9a9;color:var(--form-placeholder)}}fieldset{border:1px #0096bfab solid;border:1px var(--focus) solid;border-radius:6px;margin:0 0 12px;padding:10px}@media (prefers-color-scheme: dark){fieldset{border:1px #0096bfab solid;border:1px var(--focus) solid}}legend{font-size:0.9em;font-weight:600}input[type='range']{margin:10px 0;padding:10px 0;background:transparent}input[type='range']:focus{outline:none}input[type='range']::-webkit-slider-runnable-track{width:100%;height:9.5px;-webkit-transition:0.2s;transition:0.2s;background:#efefef;background:var(--background);border-radius:3px}@media (prefers-color-scheme: dark){input[type='range']::-webkit-slider-runnable-track{background:#161f27;background:var(--background)}}input[type='range']::-webkit-slider-thumb{box-shadow:0 1px 1px #000, 0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border);-webkit-appearance:none;margin-top:-7px}@media (prefers-color-scheme: dark){input[type='range']::-webkit-slider-thumb{background:#526980;background:var(--border)}}input[type='range']:focus::-webkit-slider-runnable-track{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type='range']:focus::-webkit-slider-runnable-track{background:#161f27;background:var(--background)}}input[type='range']::-moz-range-track{width:100%;height:9.5px;-moz-transition:0.2s;transition:0.2s;background:#efefef;background:var(--background);border-radius:3px}@media (prefers-color-scheme: dark){input[type='range']::-moz-range-track{background:#161f27;background:var(--background)}}input[type='range']::-moz-range-thumb{box-shadow:1px 1px 1px #000, 0 0 1px #0d0d0d;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}@media (prefers-color-scheme: dark){input[type='range']::-moz-range-thumb{background:#526980;background:var(--border)}}input[type='range']::-ms-track{width:100%;height:9.5px;background:transparent;border-color:transparent;border-width:16px 0;color:transparent}input[type='range']::-ms-fill-lower{background:#efefef;background:var(--background);border:0.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000, 0 0 1px #0d0d0d}@media (prefers-color-scheme: dark){input[type='range']::-ms-fill-lower{background:#161f27;background:var(--background)}}input[type='range']::-ms-fill-upper{background:#efefef;background:var(--background);border:0.2px solid #010101;border-radius:3px;box-shadow:1px 1px 1px #000, 0 0 1px #0d0d0d}@media (prefers-color-scheme: dark){input[type='range']::-ms-fill-upper{background:#161f27;background:var(--background)}}input[type='range']::-ms-thumb{box-shadow:1px 1px 1px #000, 0 0 1px #0d0d0d;border:1px solid #000;height:20px;width:20px;border-radius:50%;background:#dbdbdb;background:var(--border)}@media (prefers-color-scheme: dark){input[type='range']::-ms-thumb{background:#526980;background:var(--border)}}input[type='range']:focus::-ms-fill-lower{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type='range']:focus::-ms-fill-lower{background:#161f27;background:var(--background)}}input[type='range']:focus::-ms-fill-upper{background:#efefef;background:var(--background)}@media (prefers-color-scheme: dark){input[type='range']:focus::-ms-fill-upper{background:#161f27;background:var(--background)}}a{text-decoration:none;color:#0076d1;color:var(--links)}@media (prefers-color-scheme: dark){a{color:#41adff;color:var(--links)}}a:hover{text-decoration:underline}code{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){code{color:#ffbe85;color:var(--code)}}@media (prefers-color-scheme: dark){code{background:#161f27;background:var(--background)}}samp{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){samp{color:#ffbe85;color:var(--code)}}@media (prefers-color-scheme: dark){samp{background:#161f27;background:var(--background)}}time{background:#efefef;background:var(--background);color:#000;color:var(--code);padding:2.5px 5px;border-radius:6px;font-size:1em}@media (prefers-color-scheme: dark){time{color:#ffbe85;color:var(--code)}}@media (prefers-color-scheme: dark){time{background:#161f27;background:var(--background)}}pre > code{padding:10px;display:block;overflow-x:auto}var{color:#39a33c;color:var(--variable);font-style:normal;font-family:monospace}@media (prefers-color-scheme: dark){var{color:#d941e2;color:var(--variable)}}kbd{background:#efefef;background:var(--background);border:1px solid #dbdbdb;border:1px solid var(--border);border-radius:2px;color:#363636;color:var(--text-main);padding:2px 4px}@media (prefers-color-scheme: dark){kbd{color:#dbdbdb;color:var(--text-main)}}@media (prefers-color-scheme: dark){kbd{border:1px solid #526980;border:1px solid var(--border)}}@media (prefers-color-scheme: dark){kbd{background:#161f27;background:var(--background)}}img,video{max-width:100%;height:auto}hr{border:none;border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}@media (prefers-color-scheme: dark){hr{border-top:1px solid #526980;border-top:1px solid var(--border)}}table{border-collapse:collapse;margin-bottom:10px;width:100%;table-layout:fixed}table caption{text-align:left}td,th{padding:6px;text-align:left;vertical-align:top;word-wrap:break-word}thead{border-bottom:1px solid #dbdbdb;border-bottom:1px solid var(--border)}@media (prefers-color-scheme: dark){thead{border-bottom:1px solid #526980;border-bottom:1px solid var(--border)}}tfoot{border-top:1px solid #dbdbdb;border-top:1px solid var(--border)}@media (prefers-color-scheme: dark){tfoot{border-top:1px solid #526980;border-top:1px solid var(--border)}}tbody tr:nth-child(even){background-color:#efefef;background-color:var(--background)}@media (prefers-color-scheme: dark){tbody tr:nth-child(even){background-color:#161f27;background-color:var(--background)}}tbody tr:nth-child(even) button{background-color:#f7f7f7;background-color:var(--background-alt)}@media (prefers-color-scheme: dark){tbody tr:nth-child(even) button{background-color:#1a242f;background-color:var(--background-alt)}}tbody tr:nth-child(even) button:hover{background-color:#fff;background-color:var(--background-body)}@media (prefers-color-scheme: dark){tbody tr:nth-child(even) button:hover{background-color:#202b38;background-color:var(--background-body)}}::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;background:var(--background);border-radius:6px}@media (prefers-color-scheme: dark){::-webkit-scrollbar-track{background:#161f27;background:var(--background)}}::-webkit-scrollbar-thumb{background:rgb(170, 170, 170);background:var(--scrollbar-thumb);border-radius:6px}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb{background:#040a0f;background:var(--scrollbar-thumb)}}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb{background:#040a0f;background:var(--scrollbar-thumb)}}::-webkit-scrollbar-thumb:hover{background:#9b9b9b;background:var(--scrollbar-thumb-hover)}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb:hover{background:rgb(0, 0, 0);background:var(--scrollbar-thumb-hover)}}@media (prefers-color-scheme: dark){::-webkit-scrollbar-thumb:hover{background:rgb(0, 0, 0);background:var(--scrollbar-thumb-hover)}}::-moz-selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}::selection{background-color:#9e9e9e;background-color:var(--selection);color:#000;color:var(--text-bright)}@media (prefers-color-scheme: dark){::-moz-selection{color:#fff;color:var(--text-bright)}::selection{color:#fff;color:var(--text-bright)}}@media (prefers-color-scheme: dark){::-moz-selection{background-color:#1c76c5;background-color:var(--selection)}::selection{background-color:#1c76c5;background-color:var(--selection)}}details{display:flex;flex-direction:column;align-items:flex-start;background-color:#f7f7f7;background-color:var(--background-alt);padding:10px 10px 0;margin:1em 0;border-radius:6px;overflow:hidden}@media (prefers-color-scheme: dark){details{background-color:#1a242f;background-color:var(--background-alt)}}details[open]{padding:10px}details > :last-child{margin-bottom:0}details[open] summary{margin-bottom:10px}summary{display:list-item;background-color:#efefef;background-color:var(--background);padding:10px;margin:-10px -10px 0;cursor:pointer;outline:none}@media (prefers-color-scheme: dark){summary{background-color:#161f27;background-color:var(--background)}}summary:focus,summary:hover{text-decoration:underline}details > :not(summary){margin-top:0}summary::-webkit-details-marker{color:#363636;color:var(--text-main)}@media (prefers-color-scheme: dark){summary::-webkit-details-marker{color:#dbdbdb;color:var(--text-main)}}dialog{background-color:#f7f7f7;background-color:var(--background-alt);color:#363636;color:var(--text-main);border:none;border-radius:6px;border-color:#dbdbdb;border-color:var(--border);padding:10px 30px}@media (prefers-color-scheme: dark){dialog{border-color:#526980;border-color:var(--border)}}@media (prefers-color-scheme: dark){dialog{color:#dbdbdb;color:var(--text-main)}}@media (prefers-color-scheme: dark){dialog{background-color:#1a242f;background-color:var(--background-alt)}}dialog > header:first-child{background-color:#efefef;background-color:var(--background);border-radius:6px 6px 0 0;margin:-10px -30px 10px;padding:10px;text-align:center}@media (prefers-color-scheme: dark){dialog > header:first-child{background-color:#161f27;background-color:var(--background)}}dialog::-webkit-backdrop{background:#0000009c;-webkit-backdrop-filter: blur(4px);backdrop-filter: blur(4px)}dialog::backdrop{background:#0000009c;-webkit-backdrop-filter: blur(4px);backdrop-filter: blur(4px)}footer{border-top:1px solid #dbdbdb;border-top:1px solid var(--border);padding-top:10px;color:#70777f;color:var(--text-muted)}@media (prefers-color-scheme: dark){footer{color:#a9b1ba;color:var(--text-muted)}}@media (prefers-color-scheme: dark){footer{border-top:1px solid #526980;border-top:1px solid var(--border)}}body > footer{margin-top:40px}@media print{body,button,code,details,input,pre,summary,textarea{background-color:#fff}button,input,textarea{border:1px solid #000}body,button,code,footer,h1,h2,h3,h4,h5,h6,input,pre,strong,summary,textarea{color:#000}summary::marker{color:#000}summary::-webkit-details-marker{color:#000}tbody tr:nth-child(even){background-color:#f2f2f2}a{color:#00f;text-decoration:underline}}
+</style>
+<meta charset="utf-8"/>
+<title>RNode Bootstrap Console</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
#define MAX_PKT_LENGTH 255
+bool lora_preinit_done = false;
+
LoRaClass::LoRaClass() :
_spiSettings(8E6, MSBFIRST, SPI_MODE0),
_ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
setTimeout(0);
}
-int LoRaClass::begin(long frequency)
-{
+bool LoRaClass::preInit() {
// setup pins
pinMode(_ss, OUTPUT);
// set SS high
digitalWrite(_ss, HIGH);
+
+ SPI.begin();
+
+ // check version
+ uint8_t version = readRegister(REG_VERSION);
+ if (version != 0x12) {
+ return false;
+ }
+
+ lora_preinit_done = true;
+ return true;
+}
+int LoRaClass::begin(long frequency)
+{
if (_reset != -1) {
pinMode(_reset, OUTPUT);
delay(10);
}
- // start SPI
- SPI.begin();
-
- // check version
- uint8_t version = readRegister(REG_VERSION);
- if (version != 0x12) {
- return 0;
+ if (!lora_preinit_done) {
+ if (!preInit()) {
+ return false;
+ }
}
// put in sleep mode
}
}
+uint8_t LoRaClass::getTxPower() {
+ byte txp = readRegister(REG_PA_CONFIG);
+ return txp;
+}
+
void LoRaClass::setFrequency(long frequency) {
_frequency = frequency;
void idle();
void sleep();
+ bool preInit();
+ uint8_t getTxPower();
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
uint32_t getFrequency();
void setFrequency(long frequency);
bool packet_ready = false;
#endif
-// TODO: Implement
-bool console_active = true;
-
void setup() {
#if MCU_VARIANT == MCU_ESP32
boot_seq();
// Set chip select, reset and interrupt
// pins for the LoRa module
LoRa.setPins(pin_cs, pin_reset, pin_dio);
+
+ if (LoRa.preInit()) {
+ sx1276_installed = true;
+ uint32_t lfr = LoRa.getFrequency();
+ if (lfr == 0) {
+ // Normal boot
+ } else if (lfr == M_FRQ_R) {
+ // Quick reboot
+ #if HAS_CONSOLE
+ if (rtc_get_reset_reason(0) == POWERON_RESET) {
+ console_active = true;
+ }
+ #endif
+ } else {
+ // Unknown boot
+ }
+ LoRa.setFrequency(M_FRQ_S);
+ } else {
+ sx1276_installed = false;
+ }
#if HAS_DISPLAY
disp_ready = display_init();
bt_init_ran = true;
#endif
- kiss_indicate_reset();
-
if (console_active) {
console_start();
+ } else {
+ kiss_indicate_reset();
}
#endif
// Validate board health, EEPROM and config
validate_status();
+
+ LoRa.setFrequency(0);
}
void lora_receive() {
if (eeprom_product_valid() && eeprom_model_valid() && eeprom_hwrev_valid()) {
if (eeprom_checksum_valid()) {
eeprom_ok = true;
- #if PLATFORM == PLATFORM_ESP32
- if (device_init()) {
+ if (sx1276_installed) {
+ #if PLATFORM == PLATFORM_ESP32
+ if (device_init()) {
+ hw_ready = true;
+ } else {
+ hw_ready = false;
+ }
+ #else
hw_ready = true;
- } else {
- hw_ready = false;
- }
- #else
- hw_ready = true;
- #endif
-
+ #endif
+ } else {
+ hw_ready = false;
+ Serial.write("No SX1276/SX1278 radio module found\r\n");
+ #if HAS_DISPLAY
+ if (disp_ready) {
+ device_init_done = true;
+ update_display();
+ }
+ #endif
+ }
+
if (hw_ready && eeprom_have_conf()) {
eeprom_conf_load();
op_mode = MODE_TNC;
}
#if MCU_VARIANT == MCU_ESP32
- buffer_serial();
- if (!fifo_isempty(&serialFIFO)) serial_poll();
+ // if (!console_active) {
+ buffer_serial();
+ if (!fifo_isempty(&serialFIFO)) serial_poll();
+ // }
#else
if (!fifo_isempty_locked(&serialFIFO)) serial_poll();
#endif
#endif
#if HAS_BLUETOOTH
- if (bt_ready) update_bt();
+ if (!console_active && bt_ready) update_bt();
#endif
}
int8_t led_notready_direction = 0;
unsigned long led_notready_ticks = 0;
unsigned long led_standby_wait = 350;
+ unsigned long led_console_wait = 1;
unsigned long led_notready_wait = 200;
#else
}
}
+ void led_indicate_console() {
+ npset(0x60, 0x00, 0x60);
+ // led_standby_ticks++;
+
+ // if (led_standby_ticks > led_console_wait) {
+ // led_standby_ticks = 0;
+
+ // if (led_standby_value <= led_standby_min) {
+ // led_standby_direction = 1;
+ // } else if (led_standby_value >= led_standby_max) {
+ // led_standby_direction = -1;
+ // }
+
+ // uint8_t led_standby_intensity;
+ // led_standby_value += led_standby_direction;
+ // int led_standby_ti = led_standby_value - led_standby_lng;
+
+ // if (led_standby_ti < 0) {
+ // led_standby_intensity = 0;
+ // } else if (led_standby_ti > led_standby_cut) {
+ // led_standby_intensity = led_standby_cut;
+ // } else {
+ // led_standby_intensity = led_standby_ti;
+ // }
+ // npset(led_standby_intensity, 0x00, led_standby_intensity);
+ // }
+ }
+
#else
void led_indicate_standby() {
led_standby_ticks++;
#endif
}
}
+
+ void led_indicate_console() {
+ led_indicate_standby();
+ }
#endif
#endif
}
}
+int getTxPower() {
+ uint8_t txp = LoRa.getTxPower();
+ return (int)txp;
+}
+
void setTXPower() {
if (radio_online) {
if (model == MODEL_A2) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);