Add digital repeater mode

This commit is contained in:
Atten 2022-03-13 02:50:05 +07:00
parent 7491385819
commit a5dbf60772
5 changed files with 610 additions and 98 deletions

View File

@ -10,7 +10,7 @@
#ifndef MAIN_H
#define MAIN_H
#define VERSION "0.4"
#define VERSION "0.5"
#define DEBUG
//#define DEBUG_IS
@ -33,6 +33,7 @@
#define FORMAT_SPIFFS_IF_FAILED true
#define PKGLISTSIZE 10
#define PKGTXSIZE 5
const int timeZone = 7; // Bangkok
@ -41,6 +42,7 @@ const int timeZone = 7; // Bangkok
#include <SD.h>
#include <SPIFFS.h>
#include "soc/rtc_wdt.h"
#include <AX25.h>
#include "HardwareSerial.h"
#include "EEPROM.h"
@ -99,9 +101,12 @@ typedef struct Config_Struct {
char mqtt_user[10];
char mqtt_pass[10];
char wifi_power;
uint16_t tx_timeslot;
uint16_t digi_delay;
}Configuration;
typedef struct digiTLM_struct {
typedef struct igateTLM_struct {
uint16_t Sequence;
unsigned long ParmTimeout;
unsigned long TeleTimeout;
@ -110,7 +115,7 @@ typedef struct digiTLM_struct {
uint8_t RX;
uint8_t TX;
uint8_t DROP;
}digiTLMType;
}igateTLMType;
typedef struct pkgListStruct {
time_t time;
@ -134,6 +139,23 @@ typedef struct statisticStruct {
uint32_t inet2rf;
}statusType;
typedef struct digiTLM_struct{
unsigned int Sequence;
unsigned int ParmTimeout;
unsigned int TeleTimeout;
unsigned char RxPkts;
unsigned char TxPkts;
unsigned char DropRx;
unsigned char ErPkts;
}digiTLMType;
typedef struct txQueue_struct{
bool Active;
long timeStamp;
int Delay;
char Info[300];
}txQueueType;
const char PARM[] = { "PARM.RF->INET,INET->RF,RxPkts,TxPkts,IGateDropRx" };
const char UNIT[] = { "UNIT.Pkts,Pkts,Pkts,Pkts,Pkts" };
const char EQNS[] = { "EQNS.0,1,0,0,1,0,0,1,0,0,1,0,0,1,0" };
@ -150,5 +172,7 @@ void sort(pkgListType a[], int size);
void sortPkgDesc(pkgListType a[], int size);
int processPacket(String &tnc2);
String send_fix_location();
int digiProcess(AX25Msg &Packet);
void printTime();
#endif

View File

@ -6,7 +6,7 @@
#include <driver/adc.h>
#include "esp_adc_cal.h"
#include "cppQueue.h"
//#include "ButterworthFilter.h"
#include "ButterworthFilter.h"
extern "C"
{
@ -28,7 +28,7 @@ bool hw_afsk_dac_isr = false;
Afsk *AFSK_modem;
// //กรองความถี่สูงผ่าน >300Hz HPF Butterworth Filter. 0-300Hz ช่วงความถี่ต่ำใช้กับโทน CTCSS/DCS ในวิทยุสื่อสารจะถูกรองทิ้ง
// ButterworthFilter hp_filter(300, 9600, ButterworthFilter::ButterworthFilter::Highpass, 2);
ButterworthFilter hp_filter(1300, 9600, ButterworthFilter::ButterworthFilter::Highpass, 1);
// //กรองความถี่ต่ำผ่าน <3KHz LPF Butterworth Filter. ความถี่เสียงที่มากกว่า 3.5KHz ไม่ใช่ความถี่เสียงคนพูดจะถูกกรองทิ้ง
// ButterworthFilter lp_filter(3500, 9600, ButterworthFilter::ButterworthFilter::Lowpass, 2);
@ -411,7 +411,7 @@ uint8_t AFSK_dac_isr(Afsk *afsk)
}
int hdlc_flag_count = 0;
bool hdlc_flage_end=false;
bool hdlc_flage_end = false;
static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
{
// Initialise a return value. We start with the
@ -456,7 +456,7 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
hdlc->receiving = false;
LED_RX_OFF();
hdlc_flag_count = 0;
hdlc_flage_end=false;
hdlc_flage_end = false;
}
// Everytime we receive a HDLC_FLAG, we reset the
@ -483,7 +483,7 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
hdlc->receiving = false;
LED_RX_OFF();
hdlc_flag_count = 0;
hdlc_flage_end=false;
hdlc_flage_end = false;
return ret;
}
@ -493,7 +493,7 @@ static bool hdlcParse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
if (!hdlc->receiving)
return ret;
hdlc_flage_end=true;
hdlc_flage_end = true;
// First check if what we are seeing is a stuffed bit.
// Since the different HDLC control characters like
@ -597,10 +597,19 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample)
*/
// BUTTERWORTH Filter
// afsk->iirX[0] = afsk->iirX[1];
// afsk->iirX[1] = ((int8_t)fifo_pop(&afsk->delayFifo) * currentSample) / 6.027339492F;
// afsk->iirY[0] = afsk->iirY[1];
// afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + afsk->iirY[0] * 0.6681786379F;
//Fast calcultor
int16_t tmp16t;
afsk->iirX[0] = afsk->iirX[1];
afsk->iirX[1] = ((int8_t)fifo_pop(&afsk->delayFifo) * currentSample) / 6.027339492F;
tmp16t = (int16_t)((int8_t)fifo_pop(&afsk->delayFifo) * (int8_t)currentSample);
afsk->iirX[1] = (tmp16t >> 2) + (tmp16t >> 5);
afsk->iirY[0] = afsk->iirY[1];
afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + afsk->iirY[0] * 0.6681786379F;
tmp16t = (afsk->iirY[0] >> 2) + (afsk->iirY[0] >> 3) + (afsk->iirY[0] >> 4);
afsk->iirY[1] = afsk->iirX[0] + afsk->iirX[1] + tmp16t;
// We put the sampled bit in a delay-line:
// First we bitshift everything 1 left
@ -776,6 +785,8 @@ extern bool afskSync;
long mVsum = 0;
int mVsumCount = 0;
long lastVrms=0;
bool VrmsFlag=false;
void AFSK_Poll()
{
@ -857,7 +868,7 @@ void AFSK_Poll()
adcVal = (int)pcm_in[i];
offset_new += adcVal;
offset_count++;
if (offset_count >= 192)
if (offset_count >= 192) //192
{
offset = offset_new / offset_count;
offset_count = 0;
@ -867,29 +878,47 @@ void AFSK_Poll()
}
adcVal -= offset; // Convert unsinewave to sinewave
mV = abs((int)adcVal); //mVp-p
mV = (int)((float)mV / 3.68F); // mV=(mV*625)/36848;
mVsum += powl(mV, 2);
mVsumCount++;
int8_t adcR = (int8_t)((int16_t)(adcVal >> 4)); // Reduce 12bit to 8bit
float adcF=hp_filter.Update((float)adcVal);
adcVal=(int)adcF;
if (afskSync == false)
{
mV = abs((int)adcVal); // mVp-p
mV = (int)((float)mV / 3.68F); // mV=(mV*625)/36848;
mVsum += powl(mV, 2);
mVsumCount++;
}
//int8_t adcR = (int8_t)((int16_t)(adcVal >> 4)); // Reduce 12bit to 8bit
int8_t adcR=(int8_t)(adcVal/16);
AFSK_adc_isr(AFSK_modem, adcR); // Process signal IIR
if (i % 4 == 0)
APRS_poll(); // Poll check every 1 bit
}
//Get mVrms on Sync flage 0x7E
if (hdlc_flag_count > 3 && hdlc_flage_end==true)
// Get mVrms on Sync flage 0x7E
if (afskSync == false)
{
if (mVsumCount > 1920){
mVrms = sqrtl(mVsum / mVsumCount);
mVsum=0;
mVsumCount=0;
double Vrms=(double)mVrms/1000;
dBV = 20.0F * log10(Vrms);
//dBu = 20 * log10(Vrms / 0.7746);
Serial.printf("mVrms=%d dBV=%0.1f agc=%0.2f\n",mVrms,dBV);
afskSync=true;
if (hdlc_flag_count > 3 && hdlc_flage_end == true)
{
if (mVsumCount > 960)
{
mVrms = sqrtl(mVsum / mVsumCount);
mVsum = 0;
mVsumCount = 0;
lastVrms=millis()+500;
VrmsFlag=true;
//if(millis()>lastVrms){
// double Vrms=(double)mVrms/1000;
// dBV = 20.0F * log10(Vrms);
// //dBu = 20 * log10(Vrms / 0.7746);
// Serial.printf("mVrms=%d dBV=%0.1f agc=%0.2f\n",mVrms,dBV);
//afskSync = true;
//}
}
}
if(millis()>lastVrms && VrmsFlag){
afskSync = true;
VrmsFlag=false;
}
}
}

View File

@ -188,7 +188,7 @@ inline static uint8_t sinSample(uint16_t i)
#include "driver/i2s.h"
#include "driver/dac.h"
#define SAMPLE_RATE 9580 //9600 ปรับชดเชยแซมปลิงค์ของ I2S
#define SAMPLE_RATE 9600 //9580 ปรับชดเชยแซมปลิงค์ของ I2S
#define PIN_I2S_BCLK 26
#define PIN_I2S_LRC 27
#define PIN_I2S_DIN 35

View File

@ -57,16 +57,19 @@ bool aprsUpdate = false;
boolean gotPacket = false;
AX25Msg incomingPacket;
bool lastPkg=false;
bool afskSync=false;
String lastPkgRaw="";
float dBV=0;
int mVrms=0;
bool lastPkg = false;
bool afskSync = false;
String lastPkgRaw = "";
float dBV = 0;
int mVrms = 0;
cppQueue PacketBuffer(sizeof(AX25Msg), 5, IMPLEMENTATION); // Instantiate queue
statusType status;
RTC_DATA_ATTR digiTLMType digiTLM;
RTC_DATA_ATTR igateTLMType igateTLM;
RTC_DATA_ATTR digiTLMType digiLog;
RTC_DATA_ATTR txQueueType txQueue[PKGTXSIZE];
RTC_DATA_ATTR uint8_t digiCount = 0;
Configuration config;
@ -177,6 +180,8 @@ void defaultConfig()
config.tnc_beacon = 0;
config.aprs_table = '/';
config.aprs_symbol = '&';
config.digi_delay = 2000;
config.tx_timeslot = 5000;
sprintf(config.aprs_path, "WIDE1-1");
sprintf(config.aprs_comment, "ESP32 Internet Gateway");
sprintf(config.tnc_comment, "ESP32 Build in TNC");
@ -288,6 +293,64 @@ void pkgListUpdate(char *call, bool type)
}
}
bool pkgTxUpdate(const char *info, int delay)
{
char *ecs = strstr(info, ">");
if (ecs == NULL)
return false;
// Replace
for (int i = 0; i < PKGTXSIZE; i++)
{
if (txQueue[i].Active)
{
if (!(strncmp(&txQueue[i].Info[0], info, info - ecs)))
{
strcpy(&txQueue[i].Info[0], info);
txQueue[i].Delay = delay;
txQueue[i].timeStamp = millis();
return true;
}
}
}
// Add
for (int i = 0; i < PKGTXSIZE; i++)
{
if (txQueue[i].Active == false)
{
strcpy(&txQueue[i].Info[0], info);
txQueue[i].Delay = delay;
txQueue[i].Active = true;
txQueue[i].timeStamp = millis();
break;
}
}
return true;
}
bool pkgTxSend()
{
for (int i = 0; i < PKGTXSIZE; i++)
{
if (txQueue[i].Active)
{
int decTime = millis() - txQueue[i].timeStamp;
if (decTime > txQueue[i].Delay)
{
APRS_setPreamble(350L);
APRS_sendTNC2Pkt(String(txQueue[i].Info)); // Send packet to RF
txQueue[i].Active = false;
#ifdef DEBUG_TNC
printTime();
Serial.println("TX->RF: " + String(txQueue[i].Info));
#endif
return true;
}
}
}
return false;
}
uint8_t *packetData;
//ฟังชั่นถูกเรียกมาจาก ax25_decode
void aprs_msg_callback(struct AX25Msg *msg)
@ -301,13 +364,13 @@ void aprs_msg_callback(struct AX25Msg *msg)
void printTime()
{
struct tm tmstruct;
getLocalTime(&tmstruct, 5000);
getLocalTime(&tmstruct, 5000);
Serial.print("[");
Serial.print(tmstruct.tm_hour);
Serial.print(":");
Serial.print(tmstruct.tm_min);
Serial.print(":");
Serial.print( tmstruct.tm_sec);
Serial.print(tmstruct.tm_sec);
Serial.print("]");
}
@ -467,7 +530,8 @@ void setup()
{
defaultConfig();
Serial.println("Manual Default configure!");
while(digitalRead(0) == LOW);
while (digitalRead(0) == LOW)
;
}
//ตรวจสอบคอนฟิกซ์ผิดพลาด
@ -493,7 +557,7 @@ void setup()
xTaskCreatePinnedToCore(
taskAPRS, /* Function to implement the task */
"taskAPRS", /* Name of the task */
8192, /* Stack size in words */
8192, /* Stack size in words */
NULL, /* Task input parameter */
1, /* Priority of the task */
&taskAPRSHandle, /* Task handle. */
@ -577,15 +641,11 @@ int processPacket(String &tnc2)
for (int i = 0; i < incomingPacket.rpt_count; i++)
{
tnc2 += String(",");
char *rptcall = incomingPacket.rpt_list[i].call;
tnc2 += String(rptcall);
tnc2 += String(incomingPacket.rpt_list[i].call);
if (incomingPacket.rpt_list[i].ssid > 0)
{
tnc2 += String("-");
char rssid[3];
itoa(incomingPacket.rpt_list[i].ssid, rssid, 3);
rssid[2] = 0;
tnc2 += String(rssid);
tnc2 += String(incomingPacket.rpt_list[i].ssid);
}
if (incomingPacket.rpt_flags & (1 << i))
tnc2 += "*";
@ -594,10 +654,10 @@ int processPacket(String &tnc2)
tnc2 += String((const char *)incomingPacket.info);
tnc2 += String("\n");
#ifdef DEBUG_TNC
Serial.printf("[%d] ", ++pkgTNC_count);
Serial.print(tnc2);
#endif
// #ifdef DEBUG_TNC
// Serial.printf("[%d] ", ++pkgTNC_count);
// Serial.print(tnc2);
// #endif
return tnc2.length();
}
@ -635,10 +695,12 @@ void sendIsPkgMsg(char *raw)
String tnc2Raw = String(str);
if (aprsClient.connected())
aprsClient.println(tnc2Raw); // Send packet to Inet
else
APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
if (config.tnc)
pkgTxUpdate(str, 0);
// APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
}
long timeSlot;
void taskAPRS(void *pvParameters)
{
// long start, stop;
@ -653,8 +715,9 @@ void taskAPRS(void *pvParameters)
APRS_setPreamble(300);
APRS_setTail(0);
sendTimer = millis() - (config.aprs_beacon * 1000) + 30000;
digiTLM.TeleTimeout = millis() + 60000; // 1Min
igateTLM.TeleTimeout = millis() + 60000; // 1Min
AFSKInitAct = true;
timeSlot = millis();
for (;;)
{
long now = millis();
@ -663,6 +726,20 @@ void taskAPRS(void *pvParameters)
time(&timeStamp);
vTaskDelay(10 / portTICK_PERIOD_MS);
// serviceHandle();
if (now > (timeSlot + 10))
{
if (!digitalRead(LED_PIN))
{ // RX State Fail
if (pkgTxSend())
timeSlot = millis() + config.tx_timeslot; // Tx Time Slot = 5sec.
else
timeSlot = millis();
}
else
{
timeSlot = millis() + 500;
}
}
if (digitalRead(0) == LOW)
{
@ -689,7 +766,8 @@ void taskAPRS(void *pvParameters)
if (config.tnc)
{
String tnc2Raw = send_fix_location();
APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
pkgTxUpdate(tnc2Raw.c_str(), 0);
// APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
#ifdef DEBUG_TNC
Serial.println("Manual TX: " + tnc2Raw);
#endif
@ -718,6 +796,8 @@ void taskAPRS(void *pvParameters)
if (now > (sendTimer + (config.aprs_beacon * 1000)))
{
sendTimer = now;
if (digiCount > 0)
digiCount--;
#ifdef SA818
SA818_CHECK();
#endif
@ -728,9 +808,10 @@ void taskAPRS(void *pvParameters)
String tnc2Raw = send_fix_location();
if (aprsClient.connected())
aprsClient.println(tnc2Raw); // Send packet to Inet
APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
pkgTxUpdate(tnc2Raw.c_str(), 0);
// APRS_sendTNC2Pkt(tnc2Raw); // Send packet to RF
#ifdef DEBUG_TNC
Serial.println("TX: " + tnc2Raw);
// Serial.println("TX: " + tnc2Raw);
#endif
}
}
@ -744,10 +825,10 @@ void taskAPRS(void *pvParameters)
if (config.tnc_telemetry)
{
if (digiTLM.TeleTimeout < millis())
if (igateTLM.TeleTimeout < millis())
{
digiTLM.TeleTimeout = millis() + 600000; // 10Min
if ((digiTLM.Sequence % 6) == 0)
igateTLM.TeleTimeout = millis() + 600000; // 10Min
if ((igateTLM.Sequence % 6) == 0)
{
sendIsPkgMsg((char *)&PARM[0]);
sendIsPkgMsg((char *)&UNIT[0]);
@ -755,22 +836,23 @@ void taskAPRS(void *pvParameters)
}
char rawTlm[100];
if (config.aprs_ssid == 0)
sprintf(rawTlm, "%s>APE32I:T#%03d,%d,%d,%d,%d,%d,00000000", config.aprs_mycall, digiTLM.Sequence, digiTLM.RF2INET, digiTLM.INET2RF, digiTLM.RX, digiTLM.TX, digiTLM.DROP);
sprintf(rawTlm, "%s>APE32I:T#%03d,%d,%d,%d,%d,%d,00000000", config.aprs_mycall, igateTLM.Sequence, igateTLM.RF2INET, igateTLM.INET2RF, igateTLM.RX, igateTLM.TX, igateTLM.DROP);
else
sprintf(rawTlm, "%s-%d>APE32I:T#%03d,%d,%d,%d,%d,%d,00000000", config.aprs_mycall,config.aprs_ssid, digiTLM.Sequence, digiTLM.RF2INET, digiTLM.INET2RF, digiTLM.RX, digiTLM.TX, digiTLM.DROP);
sprintf(rawTlm, "%s-%d>APE32I:T#%03d,%d,%d,%d,%d,%d,00000000", config.aprs_mycall, config.aprs_ssid, igateTLM.Sequence, igateTLM.RF2INET, igateTLM.INET2RF, igateTLM.RX, igateTLM.TX, igateTLM.DROP);
if (aprsClient.connected())
aprsClient.println(String(rawTlm)); // Send packet to Inet
else
APRS_sendTNC2Pkt(String(rawTlm)); // Send packet to RF
digiTLM.Sequence++;
if (digiTLM.Sequence > 999)
digiTLM.Sequence = 0;
digiTLM.DROP = 0;
digiTLM.INET2RF = 0;
digiTLM.RF2INET = 0;
digiTLM.RX = 0;
digiTLM.TX = 0;
if (config.tnc)
pkgTxUpdate(rawTlm, 0);
// APRS_sendTNC2Pkt(String(rawTlm)); // Send packet to RF
igateTLM.Sequence++;
if (igateTLM.Sequence > 999)
igateTLM.Sequence = 0;
igateTLM.DROP = 0;
igateTLM.INET2RF = 0;
igateTLM.RF2INET = 0;
igateTLM.RX = 0;
igateTLM.TX = 0;
// client.println(raw);
}
}
@ -784,8 +866,43 @@ void taskAPRS(void *pvParameters)
//นำข้อมูลแพ็จเกจจาก TNC ออกจากคิว
PacketBuffer.pop(&incomingPacket);
processPacket(tnc2);
lastPkg=true;
lastPkgRaw=tnc2;
if (config.tnc_digi)
{
int dlyFlag = digiProcess(incomingPacket);
if (dlyFlag > 0)
{
int digiDelay;
if (dlyFlag == 1)
{
digiDelay = 0;
}
else
{
if (config.digi_delay == 0)
{ // Auto mode
if (digiCount > 20)
digiDelay = random(5000);
else if (digiCount > 10)
digiDelay = random(3000);
else if (digiCount > 0)
digiDelay = random(1500);
else
digiDelay = random(500);
}
else
{
digiDelay = random(config.digi_delay);
}
}
String digiPkg;
processPacket(digiPkg);
pkgTxUpdate(digiPkg.c_str(), digiDelay);
}
}
lastPkg = true;
lastPkgRaw = tnc2;
// ESP_BT.println(tnc2);
status.allCount++;
@ -797,10 +914,10 @@ void taskAPRS(void *pvParameters)
{
raw = (char *)malloc(tnc2.length() + 20);
status.tncCount++;
if (tnc2.indexOf("RFONLY", 10) > 0) //PATH RFONLY จะไม่ส่งเข้า APRS-IS
if (tnc2.indexOf("RFONLY", 10) > 0) // PATH RFONLY จะไม่ส่งเข้า APRS-IS
{
status.dropCount++;
digiTLM.DROP++;
igateTLM.DROP++;
}
else
{
@ -823,23 +940,23 @@ void taskAPRS(void *pvParameters)
tnc2 = String(raw);
aprsClient.println(tnc2);
status.rf2inet++;
digiTLM.RF2INET++;
digiTLM.TX++;
igateTLM.RF2INET++;
igateTLM.TX++;
#ifdef DEBUG
printTime();
Serial.print("RF->INET ");
Serial.print("RF->INET: ");
Serial.println(tnc2);
#endif
}
else
{
status.errorCount++;
digiTLM.DROP++;
igateTLM.DROP++;
}
free(str);
}
//memset(&raw[0], 0, sizeof(raw));
// memset(&raw[0], 0, sizeof(raw));
tnc2.toCharArray(&raw[0], start_val + 1);
raw[start_val + 1] = 0;
pkgListUpdate(&raw[0], 1);
@ -961,7 +1078,7 @@ void taskNetwork(void *pvParameters)
// Serial.println("Config NTP");
// setSyncProvider(getNtpTime);
Serial.println("Contacting Time Server");
configTime(3600 * timeZone, 0, "203.150.19.26", "110.170.126.101","77.68.122.252");
configTime(3600 * timeZone, 0, "203.150.19.26", "110.170.126.101", "77.68.122.252");
vTaskDelay(3000 / portTICK_PERIOD_MS);
time_t systemTime;
time(&systemTime);
@ -998,7 +1115,7 @@ void taskNetwork(void *pvParameters)
String msg_call = "::" + src_call;
status.allCount++;
digiTLM.RX++;
igateTLM.RX++;
if (config.tnc && config.inet2rf)
{
if (line.indexOf(msg_call) <= 0) // src callsign = msg callsign ไม่ใช่หัวข้อโทรมาตร
@ -1008,14 +1125,15 @@ void taskNetwork(void *pvParameters)
if (line.indexOf("::") > 0) //ข้อความเท่านั้น
{ // message only
// raw[0] = '}';
//line.toCharArray(&raw[1], line.length());
// line.toCharArray(&raw[1], line.length());
// tncTxEnable = false;
// SerialTNC.flush();
// SerialTNC.println(raw);
APRS_sendTNC2Pkt(line); // Send out RF by TNC build in
// tncTxEnable = true;
pkgTxUpdate(line.c_str(), 0);
// APRS_sendTNC2Pkt(line); // Send out RF by TNC build in
// tncTxEnable = true;
status.inet2rf++;
digiTLM.INET2RF++;
igateTLM.INET2RF++;
printTime();
#ifdef DEBUG
Serial.print("INET->RF ");
@ -1026,7 +1144,7 @@ void taskNetwork(void *pvParameters)
}
else
{
digiTLM.DROP++;
igateTLM.DROP++;
Serial.print("INET Message TELEMETRY from ");
Serial.println(src_call);
}
@ -1061,3 +1179,277 @@ void taskNetwork(void *pvParameters)
}
}
}
int digiProcess(AX25Msg &Packet)
{
int idx, j;
uint8_t ctmp;
// if(!DIGI) return;
// if(rx_data) return;
// if(digi_timeout<aprs_delay) return;
// digi_timeout = 65530;
// aprs_delay = 65535;
j = 0;
if (Packet.len < 5)
{
digiLog.ErPkts++;
return 0; // NO DST
}
if (!strncmp(&Packet.src.call[0], "NOCALL", 6))
{
digiLog.DropRx++;
return 0;
}
if (!strncmp(&Packet.src.call[0], "MYCALL", 6))
{
digiLog.DropRx++;
return 0;
}
// Destination SSID Trace
if (Packet.dst.ssid > 0)
{
uint8_t ctmp = Packet.dst.ssid & 0x1E; // Check DSSID
if (ctmp > 15)
ctmp = 0;
if (ctmp < 8)
{ // Edit PATH Change to TRACEn-N
if (ctmp > 0)
ctmp--;
Packet.dst.ssid = ctmp;
if (Packet.rpt_count > 0)
{
for (idx = 0; idx < Packet.rpt_count; idx++)
{
if (!strcmp(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0])) // Is path same callsign
{
if (Packet.rpt_list[idx].ssid == config.aprs_ssid) // IS path same SSID
{
if (Packet.rpt_flags & (1 << idx))
{
digiLog.DropRx++;
return 0; // bypass flag *
}
Packet.rpt_flags |= (1 << idx);
return 1;
}
}
if (Packet.rpt_flags & (1 << idx))
continue;
for (j = idx; j < Packet.rpt_count; j++)
{
if (Packet.rpt_flags & (1 << j))
break;
}
// Move current part to next part
for (; j >= idx; j--)
{
int n = j + 1;
strcpy(&Packet.rpt_list[n].call[0], &Packet.rpt_list[j].call[0]);
Packet.rpt_list[n].ssid = Packet.rpt_list[j].ssid;
if (Packet.rpt_flags & (1 << j))
Packet.rpt_flags |= (1 << n);
else
Packet.rpt_flags &= ~(1 << n);
}
// Add new part
Packet.rpt_count += 1;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
return 2;
// j = 1;
// break;
}
}
else
{
idx = 0;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
Packet.rpt_count += 1;
return 2;
}
}
else
{
digiLog.DropRx++;
return 0; // NO PATH
}
}
for (idx = 0; idx < Packet.rpt_count; idx++)
{
if (!strncmp(&Packet.rpt_list[idx].call[0], "qA", 2))
{
digiLog.DropRx++;
return 0;
}
}
for (idx = 0; idx < Packet.rpt_count; idx++)
{
if (!strncmp(&Packet.rpt_list[idx].call[0], "TCP", 3))
{
digiLog.DropRx++;
return 0;
}
}
for (idx = 0; idx < Packet.rpt_count; idx++)
{
if (Packet.rpt_flags & (1 << idx))
{
if (idx == (Packet.rpt_count - 1))
digiCount++;
continue; // bypass flag *
}
if (!strncmp(&Packet.rpt_list[idx].call[0], "WIDE", 4))
{
// Check WIDEn-N
if (Packet.rpt_list[idx].ssid > 0)
{
if (Packet.rpt_flags & (1 << idx))
continue; // bypass flag *
ctmp = Packet.rpt_list[idx].ssid & 0x1F;
if (ctmp > 0)
ctmp--;
if (ctmp > 15)
ctmp = 0;
if (ctmp == 0)
{
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
j = 2;
break;
}
else
{
Packet.rpt_list[idx].ssid = ctmp;
Packet.rpt_flags &= ~(1 << idx);
j = 2;
break;
}
}
else
{
j = 2;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
break;
}
}
else if (!strncmp(&Packet.rpt_list[idx].call[0], "TRACE", 5))
{
if (Packet.rpt_flags & (1 << idx))
continue; // bypass flag *
ctmp = Packet.rpt_list[idx].ssid & 0x1F;
if (ctmp > 0)
ctmp--;
if (ctmp > 15)
ctmp = 0;
if (ctmp == 0)
{
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
j = 2;
break;
}
else
{
for (j = idx; j < Packet.rpt_count; j++)
{
if (Packet.rpt_flags & (1 << j))
break;
}
// Move current part to next part
for (; j >= idx; j--)
{
int n = j + 1;
strcpy(&Packet.rpt_list[n].call[0], &Packet.rpt_list[j].call[0]);
Packet.rpt_list[n].ssid = Packet.rpt_list[j].ssid;
if (Packet.rpt_flags & (1 << j))
Packet.rpt_flags |= (1 << n);
else
Packet.rpt_flags &= ~(1 << n);
}
// Reduce N part of TRACEn-N
Packet.rpt_list[idx + 1].ssid = ctmp;
// Add new part
Packet.rpt_count += 1;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
j = 2;
break;
}
}
else if (!strncmp(&Packet.rpt_list[idx].call[0], "RFONLY", 6))
{
j = 2;
// strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
// Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
break;
}
else if (!strncmp(&Packet.rpt_list[idx].call[0], "RELAY", 5))
{
j = 2;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
break;
}
else if (!strncmp(&Packet.rpt_list[idx].call[0], "GATE", 4))
{
j = 2;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
break;
}
else if (!strncmp(&Packet.rpt_list[idx].call[0], "ECHO", 4))
{
j = 2;
strcpy(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0]);
Packet.rpt_list[idx].ssid = config.aprs_ssid;
Packet.rpt_flags |= (1 << idx);
break;
}
else if (!strcmp(&Packet.rpt_list[idx].call[0], &config.aprs_mycall[0])) // Is path same callsign
{
ctmp = Packet.rpt_list[idx].ssid & 0x1F;
if (ctmp == config.aprs_ssid) // IS path same SSID
{
if (Packet.rpt_flags & (1 << idx))
{
digiLog.DropRx++;
break; // bypass flag *
}
Packet.rpt_flags |= (1 << idx);
j = 1;
break;
}
else
{
j = 0;
break;
}
}
else
{
j = 0;
break;
}
}
return j;
}

View File

@ -204,7 +204,7 @@ void setHTML(byte page)
webString += "<li role=\"presentation\"" + strActiveP2 + ">\n<a href=\"/data\" id=\"channel_link_api_keys\">Storage</a>\n</li>\n";
#endif
webString += "<li role=\"presentation\"" + strActiveP3 + ">\n<a href=\"/config\" id=\"channel_link_settings\">Setting</a>\n</li>\n";
webString += "<li role=\"presentation\"" + strActiveP4 + ">\n<a href=\"/service\" id=\"channel_link_service\">Server</a>\n</li>\n";
webString += "<li role=\"presentation\"" + strActiveP4 + ">\n<a href=\"/service\" id=\"channel_link_service\">Service</a>\n</li>\n";
webString += "<li role=\"presentation\"" + strActiveP5 + ">\n<a href=\"/system\" id=\"channel_link_system\">System</a>\n</li>\n";
webString += "<li role=\"presentation\"" + strActiveP7 + ">\n<a href=\"/test\" id=\"channel_link_system\">Test</a>\n</li>\n";
webString += "<li role=\"presentation\"" + strActiveP6 + ">\n<a href=\"/firmware\" id=\"channel_link_firmware\">Firmware</a>\n</li>\n";
@ -224,7 +224,7 @@ void setHTML(byte page)
webString += "<div>CPU Temp: " + String((temprature_sens_read() - 32) / 1.8, 1) + "C</div> \n";
webString += "<div>Free Heap:" + String(ESP.getFreeHeap()) + " Byte</div> \n";
String uptime = String(hour(tn), DEC) + ":" + String(minute(tn), DEC) + ":" + String(second(tn), DEC);
String uptime = String(day(tn) - 1, DEC) + "D " + String(hour(tn), DEC) + ":" + String(minute(tn), DEC) + ":" + String(second(tn), DEC);
webString += "<div>System Uptime: " + uptime + "</div> \n";
webString += "</td></tr><tr><td>\n";
@ -554,17 +554,17 @@ void handle_setting()
webString += "<div class = \"col-pad\">\n<h3>Fix Location</h3>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Latitude</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Latitude(Deg.)</label>\n";
webString += "<div class=\"col-sm-3 col-xs-6\"><input class=\"form-control\" id=\"gpsLat\" name=\"gpsLat\" type=\"text\" value=\"" + String(config.gps_lat, 5) + "\" /></div>\n";
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Longitude</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Longitude(Deg.)</label>\n";
webString += "<div class=\"col-sm-3 col-xs-6\"><input class=\"form-control\" id=\"gpsLon\" name=\"gpsLon\" type=\"text\" value=\"" + String(config.gps_lon, 5) + "\" /></div>\n";
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Altitude</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Altitude(M.)</label>\n";
webString += "<div class=\"col-sm-3 col-xs-6\"><input class=\"form-control\" id=\"gpsAlt\" name=\"gpsAlt\" type=\"text\" value=\"" + String(config.gps_alt) + "\" /></div>\n";
webString += "</div>\n";
@ -579,12 +579,12 @@ void handle_setting()
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">APRS PATH</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">APRS Path</label>\n";
webString += "<div class=\"col-sm-6 col-xs-8\"><input class=\"form-control\" id=\"aprsPath\" name=\"aprsPath\" type=\"text\" value=\"" + String(config.tnc_path) + "\" /></div>\n";
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Beacon interval</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Beacon interval(mSec)</label>\n";
webString += "<div class=\"col-sm-2 col-xs-3\"><input class=\"form-control\" id=\"beaconIntv\" name=\"beaconIntv\" type=\"text\" value=\"" + String(config.aprs_beacon) + "\" /></div>\n";
webString += "</div>\n";
@ -751,6 +751,26 @@ void handle_service()
inet2rfEn = true;
}
}
if (server.argName(i) == "digiDelay")
{
if (server.arg(i) != "")
{
if (isValidNumber(server.arg(i)))
config.digi_delay = server.arg(i).toInt();
if (config.digi_delay > 5000)
config.digi_delay = 5000;
}
}
if (server.argName(i) == "timeSlot")
{
if (server.arg(i) != "")
{
if (isValidNumber(server.arg(i)))
config.tx_timeslot = server.arg(i).toInt();
if (config.tx_timeslot > 10000)
config.tx_timeslot = 10000;
}
}
// if (server.argName(i) == "mqttEnable") {
// if (server.arg(i) != "")
@ -826,7 +846,7 @@ void handle_service()
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Pass Code</label>\n";
webString += "<div class=\"col-sm-2 col-xs-4\"><input class=\"form-control\" id=\"myPasscode\" name=\"myPasscode\" type=\"password\" value=\"" + String(config.aprs_passcode) + "\" /></div>\n";
webString += "<div class=\"col-sm-2 col-xs-4\"><input class=\"form-control\" id=\"myPasscode\" name=\"myPasscode\" type=\"password\" value=\"" + String(config.aprs_passcode) + "\" />From <a href=\"https://www.dprns.com/index.php?pid=5\">Here</a></div>\n";
webString += "</div>\n";
// webString += "<div class=\"form-group\">\n";
@ -835,7 +855,7 @@ void handle_service()
// webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">APRS Host</label>\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">APRS Server</label>\n";
webString += "<div class=\"col-sm-6 col-xs-8\"><input class=\"form-control\" id=\"aprsHost\" name=\"aprsHost\" type=\"text\" value=\"" + String(config.aprs_host) + "\" /><br />Web Service: <a href=\"http://aprs.dprns.com:14501\" target=\"_blank\">T2THAI</a></div>\n";
webString += "</div>\n";
@ -878,6 +898,53 @@ void handle_service()
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Inet->RF Enable</label>\n";
webString += "<div class=\"col-sm-4 col-xs-8\"><input class=\"field_checkbox\" id=\"inet2rfEnable\" name=\"inet2rfEnable\" type=\"checkbox\" value=\"OK\" " + inet2rfFlage + "/></div>\n";
webString += "</div>\n";
String digiFlage = "";
if (config.tnc_digi)
digiFlage = "checked";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Digi Repeager</label>\n";
webString += "<div class=\"col-sm-4 col-xs-8\"><input class=\"field_checkbox\" id=\"digiEnable\" name=\"digiEnable\" type=\"checkbox\" value=\"OK\" " + digiFlage + "/></div>\n";
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">Digi Delay(mSec)</label>\n";
webString += "<div class=\"col-sm-2 col-xs-6\"><select name=\"digiDelay\" id=\"digiDelay\">\n";
for (uint16_t delay = 0; delay <= 5000; delay += 500)
{
if (config.digi_delay == delay)
{
if (delay == 0)
webString += "<option value=\"" + String(delay) + "\" selected>Auto</option>\n";
else
webString += "<option value=\"" + String(delay) + "\" selected>" + String(delay) + "</option>\n";
}
else
{
if (delay == 0)
webString += "<option value=\"" + String(delay) + "\">Auto</option>\n";
else
webString += "<option value=\"" + String(delay) + "\">" + String(delay) + "</option>\n";
}
}
webString += "</select></div>\n";
webString += "</div>\n";
webString += "<div class=\"form-group\">\n";
webString += "<label class=\"col-sm-4 col-xs-12 control-label\">TX Time Slot(mSec)</label>\n";
webString += "<div class=\"col-sm-2 col-xs-6\"><select name=\"timeSlot\" id=\"timeSlot\">\n";
for (uint16_t delay = 0; delay <= 10000; delay += 1000)
{
if (config.tx_timeslot == delay)
{
webString += "<option value=\"" + String(delay) + "\" selected>" + String(delay) + "</option>\n";
}
else
{
webString += "<option value=\"" + String(delay) + "\">" + String(delay) + "</option>\n";
}
}
webString += "</select></div>\n";
webString += "</div>\n";
webString += "</div>\n<hr>\n"; // div aprs