mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-22 13:04:53 +00:00
Cherry Picking Stuff from develop...
This commit is contained in:
parent
220859d0aa
commit
7396d0f241
@ -1 +1 @@
|
|||||||
cd protobufs && ..\nanopb-0.4.6\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
|
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.6 to be located in the"
|
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
|
||||||
echo "firmware root directory if the following step fails, you should download the correct"
|
echo "firmware root directory if the following step fails, you should download the correct"
|
||||||
echo "prebuilt binaries for your computer into nanopb-0.4.6"
|
echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
||||||
|
|
||||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||||
cd protobufs
|
cd protobufs
|
||||||
../nanopb-0.4.6/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
|
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
|
||||||
|
|
||||||
#echo "Regenerating protobuf documentation - if you see an error message"
|
#echo "Regenerating protobuf documentation - if you see an error message"
|
||||||
#echo "you can ignore it unless doing a new protobuf release to github."
|
#echo "you can ignore it unless doing a new protobuf release to github."
|
||||||
|
@ -182,6 +182,9 @@ Power::Power() : OSThread("Power")
|
|||||||
{
|
{
|
||||||
statusHandler = {};
|
statusHandler = {};
|
||||||
low_voltage_counter = 0;
|
low_voltage_counter = 0;
|
||||||
|
#ifdef DEBUG_HEAP
|
||||||
|
lastheap = ESP.getFreeHeap();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Power::analogInit()
|
bool Power::analogInit()
|
||||||
|
@ -117,6 +117,20 @@ float AirTime::utilizationTXPercent()
|
|||||||
return (float(sum) / float(MS_IN_HOUR)) * 100;
|
return (float(sum) / float(MS_IN_HOUR)) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the amount of minutes we have to be silent before we can send again
|
||||||
|
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
|
||||||
|
{
|
||||||
|
float newTxPercent = txPercent;
|
||||||
|
for (int8_t i = MINUTES_IN_HOUR-1; i >= 0; --i) {
|
||||||
|
newTxPercent -= ((float)this->utilizationTX[i] / (MS_IN_MINUTE * MINUTES_IN_HOUR / 100));
|
||||||
|
if (newTxPercent < dutyCycle)
|
||||||
|
return MINUTES_IN_HOUR-1-i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MINUTES_IN_HOUR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AirTime::AirTime() : concurrency::OSThread("AirTime"),airtimes({}) {
|
AirTime::AirTime() : concurrency::OSThread("AirTime"),airtimes({}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define PERIODS_TO_LOG 8
|
#define PERIODS_TO_LOG 8
|
||||||
#define MINUTES_IN_HOUR 60
|
#define MINUTES_IN_HOUR 60
|
||||||
#define SECONDS_IN_MINUTE 60
|
#define SECONDS_IN_MINUTE 60
|
||||||
|
#define MS_IN_MINUTE (SECONDS_IN_MINUTE * 1000)
|
||||||
#define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000)
|
#define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000)
|
||||||
|
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ class AirTime : private concurrency::OSThread
|
|||||||
uint32_t getSecondsPerPeriod();
|
uint32_t getSecondsPerPeriod();
|
||||||
uint32_t getSecondsSinceBoot();
|
uint32_t getSecondsSinceBoot();
|
||||||
uint32_t *airtimeReport(reportTypes reportType);
|
uint32_t *airtimeReport(reportTypes reportType);
|
||||||
|
uint8_t getSilentMinutes(float txPercent, float dutyCycle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool firstTime = true;
|
bool firstTime = true;
|
||||||
|
@ -35,6 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "mesh/Channels.h"
|
#include "mesh/Channels.h"
|
||||||
#include "mesh/generated/deviceonly.pb.h"
|
#include "mesh/generated/deviceonly.pb.h"
|
||||||
#include "modules/TextMessageModule.h"
|
#include "modules/TextMessageModule.h"
|
||||||
|
#include "modules/esp32/StoreForwardModule.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -95,17 +96,17 @@ static uint16_t displayWidth, displayHeight;
|
|||||||
|
|
||||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
// The screen is bigger so use bigger fonts
|
// The screen is bigger so use bigger fonts
|
||||||
#define FONT_SMALL ArialMT_Plain_16
|
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||||
#define FONT_MEDIUM ArialMT_Plain_24
|
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
|
||||||
#define FONT_LARGE ArialMT_Plain_24
|
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||||
#else
|
#else
|
||||||
#ifdef OLED_RU
|
#ifdef OLED_RU
|
||||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||||
#else
|
#else
|
||||||
#define FONT_SMALL ArialMT_Plain_10
|
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
|
||||||
#endif
|
#endif
|
||||||
#define FONT_MEDIUM ArialMT_Plain_16
|
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||||
#define FONT_LARGE ArialMT_Plain_24
|
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define fontHeight(font) ((font)[1] + 1) // height is position 1
|
#define fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||||
@ -465,7 +466,11 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *no
|
|||||||
{
|
{
|
||||||
char usersString[20];
|
char usersString[20];
|
||||||
sprintf(usersString, "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
sprintf(usersString, "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||||
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
|
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||||
|
#else
|
||||||
display->drawFastImage(x, y, 8, 8, imgUser);
|
display->drawFastImage(x, y, 8, 8, imgUser);
|
||||||
|
#endif
|
||||||
display->drawString(x + 10, y - 2, usersString);
|
display->drawString(x + 10, y - 2, usersString);
|
||||||
display->drawString(x + 11, y - 2, usersString);
|
display->drawString(x + 11, y - 2, usersString);
|
||||||
}
|
}
|
||||||
@ -513,11 +518,12 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Draw status when gps is disabled by PMU
|
//Draw status when gps is disabled by PMU
|
||||||
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps){
|
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||||
String displayLine = "";
|
{
|
||||||
displayLine = "GPS disabled";
|
|
||||||
int16_t xPos = display->getStringWidth(displayLine);
|
|
||||||
#ifdef HAS_PMU
|
#ifdef HAS_PMU
|
||||||
|
String displayLine = "GPS disabled";
|
||||||
|
int16_t xPos = display->getStringWidth(displayLine);
|
||||||
|
|
||||||
if (!config.position.gps_enabled){
|
if (!config.position.gps_enabled){
|
||||||
display->drawString(x + xPos, y, displayLine);
|
display->drawString(x + xPos, y, displayLine);
|
||||||
#ifdef GPS_POWER_TOGGLE
|
#ifdef GPS_POWER_TOGGLE
|
||||||
@ -860,29 +866,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
drawColumns(display, x, y, fields);
|
drawColumns(display, x, y, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void _screen_header()
|
|
||||||
{
|
|
||||||
if (!disp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Message count
|
|
||||||
//snprintf(buffer, sizeof(buffer), "#%03d", ttn_get_count() % 1000);
|
|
||||||
//display->setTextAlignment(TEXT_ALIGN_LEFT);
|
|
||||||
//display->drawString(0, 2, buffer);
|
|
||||||
|
|
||||||
// Datetime
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->drawString(display->getWidth()/2, 2, gps.getTimeStr());
|
|
||||||
|
|
||||||
// Satellite count
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
|
||||||
char buffer[10];
|
|
||||||
display->drawString(display->getWidth() - SATELLITE_IMAGE_WIDTH - 4, 2, itoa(gps.satellites.value(), buffer, 10));
|
|
||||||
display->drawXbm(display->getWidth() - SATELLITE_IMAGE_WIDTH, 0, SATELLITE_IMAGE_WIDTH, SATELLITE_IMAGE_HEIGHT, SATELLITE_IMAGE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// #ifdef RAK4630
|
// #ifdef RAK4630
|
||||||
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
|
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
|
||||||
// dispdev_oled(address, sda, scl), ui(&dispdev)
|
// dispdev_oled(address, sda, scl), ui(&dispdev)
|
||||||
@ -1414,8 +1397,32 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
// Draw the channel name
|
// Draw the channel name
|
||||||
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
|
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
|
||||||
// Draw our hardware ID to assist with bluetooth pairing
|
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
|
||||||
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
|
if (moduleConfig.store_forward.enabled) {
|
||||||
|
if (millis() - storeForwardModule->lastHeartbeat > (storeForwardModule->heartbeatInterval * 1200)) { //no heartbeat, overlap a bit
|
||||||
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1);
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL2);
|
||||||
|
#else
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgQuestion);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1);
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8, imgSFL2);
|
||||||
|
#else
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8, imgSF);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1);
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL2);
|
||||||
|
#else
|
||||||
|
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
|
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
|
||||||
|
|
||||||
// Draw any log messages
|
// Draw any log messages
|
||||||
|
@ -12,6 +12,18 @@ const uint8_t imgPower[] PROGMEM = { 0x40, 0x40, 0x40, 0x58, 0x48, 0x08,
|
|||||||
const uint8_t imgUser[] PROGMEM = { 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C };
|
const uint8_t imgUser[] PROGMEM = { 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C };
|
||||||
const uint8_t imgPositionEmpty[] PROGMEM = { 0x20, 0x30, 0x28, 0x24, 0x42, 0xFF };
|
const uint8_t imgPositionEmpty[] PROGMEM = { 0x20, 0x30, 0x28, 0x24, 0x42, 0xFF };
|
||||||
const uint8_t imgPositionSolid[] PROGMEM = { 0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF };
|
const uint8_t imgPositionSolid[] PROGMEM = { 0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF };
|
||||||
const uint8_t imgInfo[] PROGMEM = { 0xFF, 0x81, 0x81, 0xB5, 0xB5, 0x81, 0x81, 0xFF };
|
|
||||||
|
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||||
|
const uint8_t imgQuestionL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff };
|
||||||
|
const uint8_t imgQuestionL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
|
||||||
|
const uint8_t imgInfoL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff };
|
||||||
|
const uint8_t imgInfoL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
|
||||||
|
const uint8_t imgSFL1[] PROGMEM = { 0xb6, 0x8f, 0x19, 0x11, 0x31, 0xe3, 0xc2, 0x01, 0x01, 0xf9, 0xf9, 0x89, 0x89, 0x89, 0x09, 0xeb};
|
||||||
|
const uint8_t imgSFL2[] PROGMEM = { 0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x00, 0x0f, 0x0f, 0x00, 0x08, 0x08, 0x08, 0x0f};
|
||||||
|
#else
|
||||||
|
const uint8_t imgInfo[] PROGMEM = { 0xff, 0x81, 0x00, 0xfb, 0xfb, 0x00, 0x81, 0xff };
|
||||||
|
const uint8_t imgQuestion[] PROGMEM = { 0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, 0xdf };
|
||||||
|
const uint8_t imgSF[] PROGMEM = { 0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "img/icon.xbm"
|
#include "img/icon.xbm"
|
||||||
|
@ -162,6 +162,7 @@ void NodeDB::installDefaultConfig()
|
|||||||
config.has_network = true;
|
config.has_network = true;
|
||||||
config.has_bluetooth = true;
|
config.has_bluetooth = true;
|
||||||
config.lora.tx_enabled = true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
config.lora.tx_enabled = true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||||
|
config.lora.override_duty_cycle = false;
|
||||||
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
|
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
|
||||||
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST;
|
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST;
|
||||||
config.lora.hop_limit = HOP_RELIABLE;
|
config.lora.hop_limit = HOP_RELIABLE;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "Channels.h"
|
#include "Channels.h"
|
||||||
#include "CryptoEngine.h"
|
#include "CryptoEngine.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
|
#include "MeshRadio.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@ -187,6 +188,18 @@ ErrorCode Router::send(MeshPacket *p)
|
|||||||
{
|
{
|
||||||
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal
|
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal
|
||||||
|
|
||||||
|
// Abort sending if we are violating the duty cycle
|
||||||
|
if (!config.lora.override_duty_cycle && myRegion->dutyCycle != 100) {
|
||||||
|
float hourlyTxPercent = airTime->utilizationTXPercent();
|
||||||
|
if (hourlyTxPercent > myRegion->dutyCycle) {
|
||||||
|
uint8_t silentMinutes = airTime->getSilentMinutes(hourlyTxPercent, myRegion->dutyCycle);
|
||||||
|
DEBUG_MSG("WARNING: Duty cycle limit exceeded. Aborting send for now, you can send again in %d minutes.\n", silentMinutes);
|
||||||
|
Routing_Error err = Routing_Error_DUTY_CYCLE_LIMIT;
|
||||||
|
abortSendAndNak(err, p);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0;
|
// PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0;
|
||||||
// assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with
|
// assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with
|
||||||
// assert
|
// assert
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "mesh/http/WiFiAPClient.h"
|
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "concurrency/Periodic.h"
|
#include "concurrency/Periodic.h"
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh/http/WebServer.h"
|
#include "mesh/http/WebServer.h"
|
||||||
@ -37,9 +37,9 @@ bool APStartupComplete = 0;
|
|||||||
|
|
||||||
unsigned long lastrun_ntp = 0;
|
unsigned long lastrun_ntp = 0;
|
||||||
|
|
||||||
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
||||||
|
|
||||||
static Periodic *wifiReconnect;
|
Periodic *wifiReconnect;
|
||||||
|
|
||||||
static int32_t reconnectWiFi()
|
static int32_t reconnectWiFi()
|
||||||
{
|
{
|
||||||
@ -56,29 +56,15 @@ static int32_t reconnectWiFi()
|
|||||||
// Make sure we clear old connection credentials
|
// Make sure we clear old connection credentials
|
||||||
WiFi.disconnect(false, true);
|
WiFi.disconnect(false, true);
|
||||||
|
|
||||||
DEBUG_MSG("... Reconnecting to WiFi access point %s\n",wifiName);
|
DEBUG_MSG("Reconnecting to WiFi access point %s\n",wifiName);
|
||||||
|
|
||||||
int n = WiFi.scanNetworks();
|
|
||||||
|
|
||||||
if (n > 0) {
|
|
||||||
for (int i = 0; i < n; ++i) {
|
|
||||||
DEBUG_MSG("Found WiFi network %s, signal strength %d\n", WiFi.SSID(i).c_str(), WiFi.RSSI(i));
|
|
||||||
yield();
|
|
||||||
}
|
|
||||||
WiFi.mode(WIFI_MODE_STA);
|
WiFi.mode(WIFI_MODE_STA);
|
||||||
WiFi.begin(wifiName, wifiPsw);
|
WiFi.begin(wifiName, wifiPsw);
|
||||||
} else {
|
|
||||||
DEBUG_MSG("No networks found during site survey. Rebooting MCU...\n");
|
|
||||||
screen->startRebootScreen();
|
|
||||||
rebootAtMsec = millis() + 5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_NTP
|
#ifndef DISABLE_NTP
|
||||||
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
|
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
|
||||||
DEBUG_MSG("Updating NTP time\n");
|
DEBUG_MSG("Updating NTP time from %s\n",config.network.ntp_server);
|
||||||
if (timeClient.update()) {
|
if (timeClient.update()) {
|
||||||
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
|
||||||
|
|
||||||
@ -129,7 +115,7 @@ static void onNetworkConnected()
|
|||||||
{
|
{
|
||||||
if (!APStartupComplete) {
|
if (!APStartupComplete) {
|
||||||
// Start web server
|
// Start web server
|
||||||
DEBUG_MSG("... Starting network services\n");
|
DEBUG_MSG("Starting network services\n");
|
||||||
|
|
||||||
// start mdns
|
// start mdns
|
||||||
if (!MDNS.begin("Meshtastic")) {
|
if (!MDNS.begin("Meshtastic")) {
|
||||||
@ -168,6 +154,8 @@ bool initWifi()
|
|||||||
|
|
||||||
createSSLCert();
|
createSSLCert();
|
||||||
|
|
||||||
|
esp_wifi_set_storage(WIFI_STORAGE_RAM); // Disable flash storage for WiFi credentials
|
||||||
|
|
||||||
if (!*wifiPsw) // Treat empty password as no password
|
if (!*wifiPsw) // Treat empty password as no password
|
||||||
wifiPsw = NULL;
|
wifiPsw = NULL;
|
||||||
|
|
||||||
@ -194,7 +182,7 @@ bool initWifi()
|
|||||||
|
|
||||||
WiFi.onEvent(
|
WiFi.onEvent(
|
||||||
[](WiFiEvent_t event, WiFiEventInfo_t info) {
|
[](WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
Serial.print("\nWiFi lost connection. Reason: ");
|
Serial.print("WiFi lost connection. Reason: ");
|
||||||
Serial.println(info.wifi_sta_disconnected.reason);
|
Serial.println(info.wifi_sta_disconnected.reason);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -221,91 +209,137 @@ bool initWifi()
|
|||||||
// Called by the Espressif SDK to
|
// Called by the Espressif SDK to
|
||||||
static void WiFiEvent(WiFiEvent_t event)
|
static void WiFiEvent(WiFiEvent_t event)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("************ [WiFi-event] event: %d ************\n", event);
|
DEBUG_MSG("WiFi-Event %d: ", event);
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SYSTEM_EVENT_WIFI_READY:
|
case ARDUINO_EVENT_WIFI_READY:
|
||||||
DEBUG_MSG("WiFi interface ready\n");
|
DEBUG_MSG("WiFi interface ready\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_SCAN_DONE:
|
case ARDUINO_EVENT_WIFI_SCAN_DONE:
|
||||||
DEBUG_MSG("Completed scan for access points\n");
|
DEBUG_MSG("Completed scan for access points\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_START:
|
case ARDUINO_EVENT_WIFI_STA_START:
|
||||||
DEBUG_MSG("WiFi station started\n");
|
DEBUG_MSG("WiFi station started\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_STOP:
|
case ARDUINO_EVENT_WIFI_STA_STOP:
|
||||||
DEBUG_MSG("WiFi station stopped\n");
|
DEBUG_MSG("WiFi station stopped\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_CONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||||
DEBUG_MSG("Connected to access point\n");
|
DEBUG_MSG("Connected to access point\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
DEBUG_MSG("Disconnected from WiFi access point\n");
|
DEBUG_MSG("Disconnected from WiFi access point\n");
|
||||||
WiFi.disconnect(false, true);
|
WiFi.disconnect(false, true);
|
||||||
needReconnect = true;
|
needReconnect = true;
|
||||||
wifiReconnect->setIntervalFromNow(1000);
|
wifiReconnect->setIntervalFromNow(1000);
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
|
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||||
DEBUG_MSG("Authentication mode of access point has changed\n");
|
DEBUG_MSG("Authentication mode of access point has changed\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
DEBUG_MSG("Obtained IP address: ");
|
DEBUG_MSG("Obtained IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
onNetworkConnected();
|
onNetworkConnected();
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_LOST_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
|
DEBUG_MSG("Obtained IP6 address: ");
|
||||||
|
Serial.println(WiFi.localIPv6());
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||||
DEBUG_MSG("Lost IP address and IP address is reset to 0\n");
|
DEBUG_MSG("Lost IP address and IP address is reset to 0\n");
|
||||||
WiFi.disconnect(false, true);
|
WiFi.disconnect(false, true);
|
||||||
needReconnect = true;
|
needReconnect = true;
|
||||||
wifiReconnect->setIntervalFromNow(1000);
|
wifiReconnect->setIntervalFromNow(1000);
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
|
case ARDUINO_EVENT_WPS_ER_SUCCESS:
|
||||||
DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
|
DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_WPS_ER_FAILED:
|
case ARDUINO_EVENT_WPS_ER_FAILED:
|
||||||
DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n");
|
DEBUG_MSG("WiFi Protected Setup (WPS): failed in enrollee mode\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
|
case ARDUINO_EVENT_WPS_ER_TIMEOUT:
|
||||||
DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n");
|
DEBUG_MSG("WiFi Protected Setup (WPS): timeout in enrollee mode\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_WPS_ER_PIN:
|
case ARDUINO_EVENT_WPS_ER_PIN:
|
||||||
DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n");
|
DEBUG_MSG("WiFi Protected Setup (WPS): pin code in enrollee mode\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_START:
|
case ARDUINO_EVENT_WPS_ER_PBC_OVERLAP:
|
||||||
|
DEBUG_MSG("WiFi Protected Setup (WPS): push button overlap in enrollee mode\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_WIFI_AP_START:
|
||||||
DEBUG_MSG("WiFi access point started\n");
|
DEBUG_MSG("WiFi access point started\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_STOP:
|
case ARDUINO_EVENT_WIFI_AP_STOP:
|
||||||
DEBUG_MSG("WiFi access point stopped\n");
|
DEBUG_MSG("WiFi access point stopped\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_STACONNECTED:
|
case ARDUINO_EVENT_WIFI_AP_STACONNECTED:
|
||||||
DEBUG_MSG("Client connected\n");
|
DEBUG_MSG("Client connected\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_STADISCONNECTED:
|
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:
|
||||||
DEBUG_MSG("Client disconnected\n");
|
DEBUG_MSG("Client disconnected\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_STAIPASSIGNED:
|
case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:
|
||||||
DEBUG_MSG("Assigned IP address to client\n");
|
DEBUG_MSG("Assigned IP address to client\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_AP_PROBEREQRECVED:
|
case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED:
|
||||||
DEBUG_MSG("Received probe request\n");
|
DEBUG_MSG("Received probe request\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_GOT_IP6:
|
case ARDUINO_EVENT_WIFI_AP_GOT_IP6:
|
||||||
DEBUG_MSG("IPv6 is preferred\n");
|
DEBUG_MSG("IPv6 is preferred\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_START:
|
case ARDUINO_EVENT_WIFI_FTM_REPORT:
|
||||||
|
DEBUG_MSG("Fast Transition Management report\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_START:
|
||||||
DEBUG_MSG("Ethernet started\n");
|
DEBUG_MSG("Ethernet started\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_STOP:
|
case ARDUINO_EVENT_ETH_STOP:
|
||||||
DEBUG_MSG("Ethernet stopped\n");
|
DEBUG_MSG("Ethernet stopped\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||||
DEBUG_MSG("Ethernet connected\n");
|
DEBUG_MSG("Ethernet connected\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
DEBUG_MSG("Ethernet disconnected\n");
|
DEBUG_MSG("Ethernet disconnected\n");
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
DEBUG_MSG("Obtained IP address (SYSTEM_EVENT_ETH_GOT_IP)\n");
|
DEBUG_MSG("Obtained IP address (ARDUINO_EVENT_ETH_GOT_IP)\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||||
|
DEBUG_MSG("Obtained IP6 address (ARDUINO_EVENT_ETH_GOT_IP6)\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_SC_SCAN_DONE:
|
||||||
|
DEBUG_MSG("SmartConfig: Scan done\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_SC_FOUND_CHANNEL:
|
||||||
|
DEBUG_MSG("SmartConfig: Found channel\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_SC_GOT_SSID_PSWD:
|
||||||
|
DEBUG_MSG("SmartConfig: Got SSID and password\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_SC_SEND_ACK_DONE:
|
||||||
|
DEBUG_MSG("SmartConfig: Send ACK done\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_INIT:
|
||||||
|
DEBUG_MSG("Provisioning: Init\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_DEINIT:
|
||||||
|
DEBUG_MSG("Provisioning: Stopped\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_START:
|
||||||
|
DEBUG_MSG("Provisioning: Started\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_END:
|
||||||
|
DEBUG_MSG("Provisioning: End\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_CRED_RECV:
|
||||||
|
DEBUG_MSG("Provisioning: Credentials received\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_CRED_FAIL:
|
||||||
|
DEBUG_MSG("Provisioning: Credentials failed\n");
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_PROV_CRED_SUCCESS:
|
||||||
|
DEBUG_MSG("Provisioning: Credentials success\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include "concurrency/Periodic.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
@ -8,6 +9,9 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern bool needReconnect;
|
||||||
|
extern concurrency::Periodic *wifiReconnect;
|
||||||
|
|
||||||
/// @return true if wifi is now in use
|
/// @return true if wifi is now in use
|
||||||
bool initWifi();
|
bool initWifi();
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
|||||||
void AdminModule::handleSetOwner(const User &o)
|
void AdminModule::handleSetOwner(const User &o)
|
||||||
{
|
{
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
|
bool licensed_changed = false;
|
||||||
|
|
||||||
if (*o.long_name) {
|
if (*o.long_name) {
|
||||||
changed |= strcmp(owner.long_name, o.long_name);
|
changed |= strcmp(owner.long_name, o.long_name);
|
||||||
@ -210,12 +211,14 @@ void AdminModule::handleSetOwner(const User &o)
|
|||||||
}
|
}
|
||||||
if (owner.is_licensed != o.is_licensed) {
|
if (owner.is_licensed != o.is_licensed) {
|
||||||
changed = 1;
|
changed = 1;
|
||||||
|
licensed_changed = true;
|
||||||
owner.is_licensed = o.is_licensed;
|
owner.is_licensed = o.is_licensed;
|
||||||
|
config.lora.override_duty_cycle = owner.is_licensed; // override duty cycle for licensed operators
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
|
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
|
||||||
service.reloadOwner(!hasOpenEditTransaction);
|
service.reloadOwner(!hasOpenEditTransaction);
|
||||||
saveChanges(SEGMENT_DEVICESTATE);
|
licensed_changed ? saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE) : saveChanges(SEGMENT_DEVICESTATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,11 +451,15 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
if (this->destSelect) {
|
if (this->destSelect) {
|
||||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||||
display->setColor(BLACK);
|
display->setColor(BLACK);
|
||||||
|
display->drawStringf(1 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||||
}
|
}
|
||||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||||
// used chars right aligned
|
// used chars right aligned
|
||||||
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
|
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
|
||||||
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
|
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
|
||||||
|
if (this->destSelect) {
|
||||||
|
display->drawString(x + display->getWidth() - display->getStringWidth(buffer) - 1, y + 0, buffer);
|
||||||
|
}
|
||||||
display->setColor(WHITE);
|
display->setColor(WHITE);
|
||||||
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor));
|
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor));
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,27 +71,22 @@ void run_codec2(void* parameter)
|
|||||||
// 4 bytes of header in each frame hex c0 de c2 plus the bitrate
|
// 4 bytes of header in each frame hex c0 de c2 plus the bitrate
|
||||||
memcpy(audioModule->tx_encode_frame,&audioModule->tx_header,sizeof(audioModule->tx_header));
|
memcpy(audioModule->tx_encode_frame,&audioModule->tx_header,sizeof(audioModule->tx_header));
|
||||||
|
|
||||||
|
DEBUG_MSG("Starting codec2 task\n");
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
uint32_t tcount = ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(10000));
|
uint32_t tcount = ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(10000));
|
||||||
|
|
||||||
if (tcount != 0) {
|
if (tcount != 0) {
|
||||||
if (audioModule->radio_state == RadioState::tx) {
|
if (audioModule->radio_state == RadioState::tx) {
|
||||||
|
|
||||||
// Apply the TX filter
|
|
||||||
for (int i = 0; i < audioModule->adc_buffer_size; i++)
|
for (int i = 0; i < audioModule->adc_buffer_size; i++)
|
||||||
audioModule->speech[i] = (int16_t)hp_filter.Update((float)audioModule->speech[i]);
|
audioModule->speech[i] = (int16_t)hp_filter.Update((float)audioModule->speech[i]);
|
||||||
|
|
||||||
// Encode the audio
|
|
||||||
codec2_encode(audioModule->codec2, audioModule->tx_encode_frame + audioModule->tx_encode_frame_index, audioModule->speech);
|
codec2_encode(audioModule->codec2, audioModule->tx_encode_frame + audioModule->tx_encode_frame_index, audioModule->speech);
|
||||||
|
|
||||||
//increment the pointer where the encoded frame must be saved
|
|
||||||
audioModule->tx_encode_frame_index += audioModule->encode_codec_size;
|
audioModule->tx_encode_frame_index += audioModule->encode_codec_size;
|
||||||
|
|
||||||
//If it this is reached we have a ready trasnmission frame
|
|
||||||
if (audioModule->tx_encode_frame_index == (audioModule->encode_frame_size + sizeof(audioModule->tx_header)))
|
if (audioModule->tx_encode_frame_index == (audioModule->encode_frame_size + sizeof(audioModule->tx_header)))
|
||||||
{
|
{
|
||||||
//Transmit it
|
DEBUG_MSG("Sending %d codec2 bytes\n", audioModule->encode_frame_size);
|
||||||
DEBUG_MSG("♪♫♪ Sending %d codec2 bytes\n", audioModule->encode_frame_size);
|
|
||||||
audioModule->sendPayload();
|
audioModule->sendPayload();
|
||||||
audioModule->tx_encode_frame_index = sizeof(audioModule->tx_header);
|
audioModule->tx_encode_frame_index = sizeof(audioModule->tx_header);
|
||||||
}
|
}
|
||||||
@ -99,10 +94,8 @@ void run_codec2(void* parameter)
|
|||||||
if (audioModule->radio_state == RadioState::rx) {
|
if (audioModule->radio_state == RadioState::rx) {
|
||||||
size_t bytesOut = 0;
|
size_t bytesOut = 0;
|
||||||
if (memcmp(audioModule->rx_encode_frame, &audioModule->tx_header, sizeof(audioModule->tx_header)) == 0) {
|
if (memcmp(audioModule->rx_encode_frame, &audioModule->tx_header, sizeof(audioModule->tx_header)) == 0) {
|
||||||
// Make a cycle to get each codec2 frame from the received frame
|
|
||||||
for (int i = 4; i < audioModule->rx_encode_frame_index; i += audioModule->encode_codec_size)
|
for (int i = 4; i < audioModule->rx_encode_frame_index; i += audioModule->encode_codec_size)
|
||||||
{
|
{
|
||||||
//Decode the codec2 frame
|
|
||||||
codec2_decode(audioModule->codec2, audioModule->output_buffer, audioModule->rx_encode_frame + i);
|
codec2_decode(audioModule->codec2, audioModule->output_buffer, audioModule->rx_encode_frame + i);
|
||||||
i2s_write(I2S_PORT, &audioModule->output_buffer, audioModule->adc_buffer_size, &bytesOut, pdMS_TO_TICKS(500));
|
i2s_write(I2S_PORT, &audioModule->output_buffer, audioModule->adc_buffer_size, &bytesOut, pdMS_TO_TICKS(500));
|
||||||
}
|
}
|
||||||
@ -112,10 +105,8 @@ void run_codec2(void* parameter)
|
|||||||
codec2_set_lpc_post_filter(tmp_codec2, 1, 0, 0.8, 0.2);
|
codec2_set_lpc_post_filter(tmp_codec2, 1, 0, 0.8, 0.2);
|
||||||
int tmp_encode_codec_size = (codec2_bits_per_frame(tmp_codec2) + 7) / 8;
|
int tmp_encode_codec_size = (codec2_bits_per_frame(tmp_codec2) + 7) / 8;
|
||||||
int tmp_adc_buffer_size = codec2_samples_per_frame(tmp_codec2);
|
int tmp_adc_buffer_size = codec2_samples_per_frame(tmp_codec2);
|
||||||
// Make a cycle to get each codec2 frame from the received frame
|
|
||||||
for (int i = 4; i < audioModule->rx_encode_frame_index; i += tmp_encode_codec_size)
|
for (int i = 4; i < audioModule->rx_encode_frame_index; i += tmp_encode_codec_size)
|
||||||
{
|
{
|
||||||
//Decode the codec2 frame
|
|
||||||
codec2_decode(tmp_codec2, audioModule->output_buffer, audioModule->rx_encode_frame + i);
|
codec2_decode(tmp_codec2, audioModule->output_buffer, audioModule->rx_encode_frame + i);
|
||||||
i2s_write(I2S_PORT, &audioModule->output_buffer, tmp_adc_buffer_size, &bytesOut, pdMS_TO_TICKS(500));
|
i2s_write(I2S_PORT, &audioModule->output_buffer, tmp_adc_buffer_size, &bytesOut, pdMS_TO_TICKS(500));
|
||||||
}
|
}
|
||||||
@ -128,8 +119,15 @@ void run_codec2(void* parameter)
|
|||||||
|
|
||||||
AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP), concurrency::OSThread("AudioModule")
|
AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP), concurrency::OSThread("AudioModule")
|
||||||
{
|
{
|
||||||
|
// moduleConfig.audio.codec2_enabled = true;
|
||||||
|
// moduleConfig.audio.i2s_ws = 13;
|
||||||
|
// moduleConfig.audio.i2s_sd = 15;
|
||||||
|
// moduleConfig.audio.i2s_din = 22;
|
||||||
|
// moduleConfig.audio.i2s_sck = 14;
|
||||||
|
// moduleConfig.audio.ptt_pin = 39;
|
||||||
|
|
||||||
if ((moduleConfig.audio.codec2_enabled) && (myRegion->audioPermitted)) {
|
if ((moduleConfig.audio.codec2_enabled) && (myRegion->audioPermitted)) {
|
||||||
DEBUG_MSG("♪♫♪ Setting up codec2 in mode %u", (moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
DEBUG_MSG("Setting up codec2 in mode %u", (moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
||||||
codec2 = codec2_create((moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
codec2 = codec2_create((moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1);
|
||||||
memcpy(tx_header.magic,c2_magic,sizeof(c2_magic));
|
memcpy(tx_header.magic,c2_magic,sizeof(c2_magic));
|
||||||
tx_header.mode = (moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1;
|
tx_header.mode = (moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE) - 1;
|
||||||
@ -141,7 +139,7 @@ AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP),
|
|||||||
DEBUG_MSG(" using %d frames of %d bytes for a total payload length of %d bytes\n", encode_frame_num, encode_codec_size, encode_frame_size);
|
DEBUG_MSG(" using %d frames of %d bytes for a total payload length of %d bytes\n", encode_frame_num, encode_codec_size, encode_frame_size);
|
||||||
xTaskCreate(&run_codec2, "codec2_task", 30000, NULL, 5, &codec2HandlerTask);
|
xTaskCreate(&run_codec2, "codec2_task", 30000, NULL, 5, &codec2HandlerTask);
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("♪♫♪ Codec2 disabled (AudioModule %d, Region %s, permitted %d)\n", moduleConfig.audio.codec2_enabled, myRegion->name, myRegion->audioPermitted);
|
DEBUG_MSG("Codec2 disabled (AudioModule %d, Region %s, permitted %d)\n", moduleConfig.audio.codec2_enabled, myRegion->name, myRegion->audioPermitted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +173,7 @@ int32_t AudioModule::runOnce()
|
|||||||
esp_err_t res;
|
esp_err_t res;
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
// Set up I2S Processor configuration. This will produce 16bit samples at 8 kHz instead of 12 from the ADC
|
// Set up I2S Processor configuration. This will produce 16bit samples at 8 kHz instead of 12 from the ADC
|
||||||
DEBUG_MSG("♪♫♪ Initializing I2S SD: %d DIN: %d WS: %d SCK:%d\n", moduleConfig.audio.i2s_sd, moduleConfig.audio.i2s_din, moduleConfig.audio.i2s_ws, moduleConfig.audio.i2s_sck);
|
DEBUG_MSG("Initializing I2S SD: %d DIN: %d WS: %d SCK: %d\n", moduleConfig.audio.i2s_sd, moduleConfig.audio.i2s_din, moduleConfig.audio.i2s_ws, moduleConfig.audio.i2s_sck);
|
||||||
i2s_config_t i2s_config = {
|
i2s_config_t i2s_config = {
|
||||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | (moduleConfig.audio.i2s_sd ? I2S_MODE_RX : 0) | (moduleConfig.audio.i2s_din ? I2S_MODE_TX : 0)),
|
.mode = (i2s_mode_t)(I2S_MODE_MASTER | (moduleConfig.audio.i2s_sd ? I2S_MODE_RX : 0) | (moduleConfig.audio.i2s_din ? I2S_MODE_TX : 0)),
|
||||||
.sample_rate = 8000,
|
.sample_rate = 8000,
|
||||||
@ -191,7 +189,7 @@ int32_t AudioModule::runOnce()
|
|||||||
};
|
};
|
||||||
res = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
|
res = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
|
||||||
if(res != ESP_OK)
|
if(res != ESP_OK)
|
||||||
DEBUG_MSG("♪♫♪ Failed to install I2S driver: %d\n", res);
|
DEBUG_MSG("Failed to install I2S driver: %d\n", res);
|
||||||
|
|
||||||
const i2s_pin_config_t pin_config = {
|
const i2s_pin_config_t pin_config = {
|
||||||
.bck_io_num = moduleConfig.audio.i2s_sck,
|
.bck_io_num = moduleConfig.audio.i2s_sck,
|
||||||
@ -201,16 +199,16 @@ int32_t AudioModule::runOnce()
|
|||||||
};
|
};
|
||||||
res = i2s_set_pin(I2S_PORT, &pin_config);
|
res = i2s_set_pin(I2S_PORT, &pin_config);
|
||||||
if(res != ESP_OK)
|
if(res != ESP_OK)
|
||||||
DEBUG_MSG("♪♫♪ Failed to set I2S pin config: %d\n", res);
|
DEBUG_MSG("Failed to set I2S pin config: %d\n", res);
|
||||||
|
|
||||||
res = i2s_start(I2S_PORT);
|
res = i2s_start(I2S_PORT);
|
||||||
if(res != ESP_OK)
|
if(res != ESP_OK)
|
||||||
DEBUG_MSG("♪♫♪ Failed to start I2S: %d\n", res);
|
DEBUG_MSG("Failed to start I2S: %d\n", res);
|
||||||
|
|
||||||
radio_state = RadioState::rx;
|
radio_state = RadioState::rx;
|
||||||
|
|
||||||
// Configure PTT input
|
// Configure PTT input
|
||||||
DEBUG_MSG("♪♫♪ Initializing PTT on Pin %u\n", moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN);
|
DEBUG_MSG("Initializing PTT on Pin %u\n", moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN);
|
||||||
pinMode(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN, INPUT);
|
pinMode(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN, INPUT);
|
||||||
|
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
@ -219,19 +217,19 @@ int32_t AudioModule::runOnce()
|
|||||||
// Check if PTT is pressed. TODO hook that into Onebutton/Interrupt drive.
|
// Check if PTT is pressed. TODO hook that into Onebutton/Interrupt drive.
|
||||||
if (digitalRead(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN) == HIGH) {
|
if (digitalRead(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN) == HIGH) {
|
||||||
if (radio_state == RadioState::rx) {
|
if (radio_state == RadioState::rx) {
|
||||||
DEBUG_MSG("♪♫♪ PTT pressed, switching to TX\n");
|
DEBUG_MSG("PTT pressed, switching to TX\n");
|
||||||
radio_state = RadioState::tx;
|
radio_state = RadioState::tx;
|
||||||
e.frameChanged = true;
|
e.frameChanged = true;
|
||||||
this->notifyObservers(&e);
|
this->notifyObservers(&e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (radio_state == RadioState::tx) {
|
if (radio_state == RadioState::tx) {
|
||||||
|
DEBUG_MSG("PTT released, switching to RX\n");
|
||||||
if (tx_encode_frame_index > sizeof(tx_header)) {
|
if (tx_encode_frame_index > sizeof(tx_header)) {
|
||||||
// Send the incomplete frame
|
// Send the incomplete frame
|
||||||
DEBUG_MSG("♪♫♪ Sending %d codec2 bytes (incomplete)\n", tx_encode_frame_index);
|
DEBUG_MSG("Sending %d codec2 bytes (incomplete)\n", tx_encode_frame_index);
|
||||||
sendPayload();
|
sendPayload();
|
||||||
}
|
}
|
||||||
DEBUG_MSG("♪♫♪ PTT released, switching to RX\n");
|
|
||||||
tx_encode_frame_index = sizeof(tx_header);
|
tx_encode_frame_index = sizeof(tx_header);
|
||||||
radio_state = RadioState::rx;
|
radio_state = RadioState::rx;
|
||||||
e.frameChanged = true;
|
e.frameChanged = true;
|
||||||
@ -260,7 +258,7 @@ int32_t AudioModule::runOnce()
|
|||||||
}
|
}
|
||||||
return 100;
|
return 100;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("♪♫♪ Audio Module Disabled\n");
|
DEBUG_MSG("Audio Module Disabled\n");
|
||||||
return INT32_MAX;
|
return INT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +266,7 @@ int32_t AudioModule::runOnce()
|
|||||||
|
|
||||||
MeshPacket *AudioModule::allocReply()
|
MeshPacket *AudioModule::allocReply()
|
||||||
{
|
{
|
||||||
auto reply = allocDataPacket(); // Allocate a packet for sending
|
auto reply = allocDataPacket();
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +284,7 @@ void AudioModule::sendPayload(NodeNum dest, bool wantReplies)
|
|||||||
p->to = dest;
|
p->to = dest;
|
||||||
p->decoded.want_response = wantReplies;
|
p->decoded.want_response = wantReplies;
|
||||||
|
|
||||||
p->want_ack = false; // Audio is shoot&forget. TODO: Is this really suppressing retransmissions?
|
p->want_ack = false; // Audio is shoot&forget. No need to wait for ACKs.
|
||||||
p->priority = MeshPacket_Priority_MAX; // Audio is important, because realtime
|
p->priority = MeshPacket_Priority_MAX; // Audio is important, because realtime
|
||||||
|
|
||||||
p->decoded.payload.size = tx_encode_frame_index;
|
p->decoded.payload.size = tx_encode_frame_index;
|
||||||
|
@ -40,6 +40,9 @@ class Power : private concurrency::OSThread
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t low_voltage_counter;
|
uint8_t low_voltage_counter;
|
||||||
|
#ifdef DEBUG_HEAP
|
||||||
|
uint32_t lastheap;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Power *power;
|
extern Power *power;
|
||||||
|
Loading…
Reference in New Issue
Block a user