kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
ax25 aprs beacon; irq-less pmu button for m5stack
rodzic
7eb4291408
commit
949ac6f75f
|
@ -43,7 +43,8 @@ AsyncWebServer server(80);
|
||||||
AXP20X_Class axp;
|
AXP20X_Class axp;
|
||||||
#define PMU_IRQ 35
|
#define PMU_IRQ 35
|
||||||
SemaphoreHandle_t axpSemaphore;
|
SemaphoreHandle_t axpSemaphore;
|
||||||
bool pmu_irq = false;
|
// 0: cleared; 1: set; 2: do not check, also query state of axp via i2c on each loop
|
||||||
|
uint8_t pmu_irq = 0;
|
||||||
|
|
||||||
const char *updateHost = "rdzsonde.mooo.com";
|
const char *updateHost = "rdzsonde.mooo.com";
|
||||||
int updatePort = 80;
|
int updatePort = 80;
|
||||||
|
@ -75,6 +76,13 @@ const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
"DFM17", // 0x0D
|
"DFM17", // 0x0D
|
||||||
NULL, NULL
|
NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Times in ms, i.e. station: 10 minutes, mobile: 20 seconds
|
||||||
|
//#define APRS_STATION_UPDATE_TIME (10*60*1000)
|
||||||
|
//#define APRS_MOBILE_STATION_UPDATE_TIME (20*1000)
|
||||||
|
#define APRS_STATION_UPDATE_TIME (10*1000)
|
||||||
|
#define APRS_MOBILE_STATION_UPDATE_TIME (10*1000)
|
||||||
|
unsigned long time_last_aprs_update = 0;
|
||||||
|
|
||||||
#if FEATURE_SONDEHUB
|
#if FEATURE_SONDEHUB
|
||||||
#define SONDEHUB_STATION_UPDATE_TIME (60*60*1000) // 60 min
|
#define SONDEHUB_STATION_UPDATE_TIME (60*60*1000) // 60 min
|
||||||
|
@ -83,18 +91,19 @@ WiFiClient shclient; // Sondehub v2
|
||||||
int shImportInterval = 0;
|
int shImportInterval = 0;
|
||||||
char shImport = 0;
|
char shImport = 0;
|
||||||
unsigned long time_last_update = 0;
|
unsigned long time_last_update = 0;
|
||||||
|
#endif
|
||||||
/* SH_LOC_OFF: never send position information to SondeHub
|
/* SH_LOC_OFF: never send position information to SondeHub
|
||||||
SH_LOC_FIXED: send fixed position (if specified in config) to sondehub
|
SH_LOC_FIXED: send fixed position (if specified in config) to sondehub
|
||||||
SH_LOC_CHASE: always activate chase mode and send GPS position (if available)
|
SH_LOC_CHASE: always activate chase mode and send GPS position (if available)
|
||||||
SH_LOC_AUTO: if there is no valid GPS position, or GPS position < MIN_LOC_AUTO_DIST away from known fixed position: use FIXED mode
|
SH_LOC_AUTO: if there is no valid GPS position, or GPS position < MIN_LOC_AUTO_DIST away from known fixed position: use FIXED mode
|
||||||
otherwise, i.e. if there is a valid GPS position and (either no fixed position in config, or GPS position is far away from fixed position), use CHASE mode.
|
otherwise, i.e. if there is a valid GPS position and (either no fixed position in config, or GPS position is far away from fixed position), use CHASE mode.
|
||||||
*/
|
*/
|
||||||
|
// same constants used for SondeHub and APRS
|
||||||
enum { SH_LOC_OFF, SH_LOC_FIXED, SH_LOC_CHASE, SH_LOC_AUTO };
|
enum { SH_LOC_OFF, SH_LOC_FIXED, SH_LOC_CHASE, SH_LOC_AUTO };
|
||||||
/* auto mode is chase if valid GPS position and (no fixed location entered OR valid GPS position and distance in lat/lon deg to fixed location > threshold) */
|
/* auto mode is chase if valid GPS position and (no fixed location entered OR valid GPS position and distance in lat/lon deg to fixed location > threshold) */
|
||||||
#define MIN_LOC_AUTO_DIST 200 /* meter */
|
#define MIN_LOC_AUTO_DIST 200 /* meter */
|
||||||
#define SH_LOC_AUTO_IS_CHASE ( gpsPos.valid && ( (isnan(sonde.config.rxlat) || isnan(sonde.config.rxlon) ) || \
|
#define SH_LOC_AUTO_IS_CHASE ( gpsPos.valid && ( (isnan(sonde.config.rxlat) || isnan(sonde.config.rxlon) ) || \
|
||||||
calcLatLonDist( gpsPos.lat, gpsPos.lon, sonde.config.rxlat, sonde.config.rxlon ) > MIN_LOC_AUTO_DIST ) )
|
calcLatLonDist( gpsPos.lat, gpsPos.lon, sonde.config.rxlat, sonde.config.rxlon ) > MIN_LOC_AUTO_DIST ) )
|
||||||
#endif
|
|
||||||
extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2);
|
extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2);
|
||||||
|
|
||||||
// KISS over TCP for communicating with APRSdroid
|
// KISS over TCP for communicating with APRSdroid
|
||||||
|
@ -745,7 +754,7 @@ struct st_configitems config_list[] = {
|
||||||
{"mp3h.rxbw", 0, &sonde.config.mp3h.rxbw},
|
{"mp3h.rxbw", 0, &sonde.config.mp3h.rxbw},
|
||||||
{"ephftp", 39, &sonde.config.ephftp},
|
{"ephftp", 39, &sonde.config.ephftp},
|
||||||
/* APRS settings */
|
/* APRS settings */
|
||||||
{"call", 8, sonde.config.call},
|
{"call", 9, sonde.config.call},
|
||||||
{"passcode", 0, &sonde.config.passcode},
|
{"passcode", 0, &sonde.config.passcode},
|
||||||
/* KISS tnc settings */
|
/* KISS tnc settings */
|
||||||
{"kisstnc.active", 0, &sonde.config.kisstnc.active},
|
{"kisstnc.active", 0, &sonde.config.kisstnc.active},
|
||||||
|
@ -760,6 +769,9 @@ struct st_configitems config_list[] = {
|
||||||
{"tcp.active", -3, &sonde.config.tcpfeed.active},
|
{"tcp.active", -3, &sonde.config.tcpfeed.active},
|
||||||
{"tcp.host", 63, sonde.config.tcpfeed.host},
|
{"tcp.host", 63, sonde.config.tcpfeed.host},
|
||||||
{"tcp.port", 0, &sonde.config.tcpfeed.port},
|
{"tcp.port", 0, &sonde.config.tcpfeed.port},
|
||||||
|
{"tcp.chase", 0, &sonde.config.chase},
|
||||||
|
{"tcp.comment", 30, sonde.config.comment},
|
||||||
|
{"tcp.bcall", 9, sonde.config.bcall},
|
||||||
{"tcp.idformat", -2, &sonde.config.tcpfeed.idformat},
|
{"tcp.idformat", -2, &sonde.config.tcpfeed.idformat},
|
||||||
{"tcp.highrate", 0, &sonde.config.tcpfeed.highrate},
|
{"tcp.highrate", 0, &sonde.config.tcpfeed.highrate},
|
||||||
#if FEATURE_CHASEMAPPER
|
#if FEATURE_CHASEMAPPER
|
||||||
|
@ -2008,13 +2020,13 @@ void handlePMUirq() {
|
||||||
button2.pressed = KP_MID;
|
button2.pressed = KP_MID;
|
||||||
button2.keydownTime = my_millis();
|
button2.keydownTime = my_millis();
|
||||||
}
|
}
|
||||||
pmu_irq = false;
|
if(pmu_irq!=2) { pmu_irq = 0; }
|
||||||
axp.clearIRQ();
|
axp.clearIRQ();
|
||||||
xSemaphoreGive( axpSemaphore );
|
xSemaphoreGive( axpSemaphore );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.println("handlePMIirq() called. THIS SHOULD NOT HAPPEN w/o button2_axp set");
|
Serial.println("handlePMIirq() called. THIS SHOULD NOT HAPPEN w/o button2_axp set");
|
||||||
pmu_irq = false; // prevent main loop blocking
|
pmu_irq = 0; // prevent main loop blocking
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2171,6 +2183,7 @@ void setup()
|
||||||
// Display backlight on M5 Core2
|
// Display backlight on M5 Core2
|
||||||
axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON);
|
axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON);
|
||||||
axp.setDCDC3Voltage(3300);
|
axp.setDCDC3Voltage(3300);
|
||||||
|
pmu_irq = 2; // IRQ pin is not connected on Core2
|
||||||
} else {
|
} else {
|
||||||
// GPS on T-Beam, buzzer on M5 Core2
|
// GPS on T-Beam, buzzer on M5 Core2
|
||||||
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
|
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
|
||||||
|
@ -2182,11 +2195,13 @@ void setup()
|
||||||
axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1);
|
axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1);
|
||||||
axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1);
|
axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1);
|
||||||
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
||||||
if (sonde.config.button2_axp) {
|
if (sonde.config.button2_axp ) {
|
||||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
if(pmu_irq !=2) {
|
||||||
attachInterrupt(PMU_IRQ, [] {
|
pinMode(PMU_IRQ, INPUT_PULLUP);
|
||||||
pmu_irq = true;
|
attachInterrupt(PMU_IRQ, [] {
|
||||||
}, FALLING);
|
pmu_irq = 1;
|
||||||
|
}, FALLING);
|
||||||
|
}
|
||||||
//axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
|
//axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
|
||||||
axp.enableIRQ( AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 );
|
axp.enableIRQ( AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 );
|
||||||
axp.clearIRQ();
|
axp.clearIRQ();
|
||||||
|
@ -2601,6 +2616,10 @@ void loopDecoder() {
|
||||||
sondehub_finish_data(&shclient, s, &sonde.config.sondehub);
|
sondehub_finish_data(&shclient, s, &sonde.config.sondehub);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
// Send own position periodically
|
||||||
|
if(sonde.config.tcpfeed.active) {
|
||||||
|
aprs_station_update();
|
||||||
|
}
|
||||||
// always send data, even if not valid....
|
// always send data, even if not valid....
|
||||||
if (rdzclient.connected()) {
|
if (rdzclient.connected()) {
|
||||||
Serial.println("Sending position via TCP as rdzJSON");
|
Serial.println("Sending position via TCP as rdzJSON");
|
||||||
|
@ -3445,6 +3464,46 @@ void loop() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aprs_station_update() {
|
||||||
|
int chase = sonde.config.chase;
|
||||||
|
// automatically decided if CHASE or FIXED mode is used (for config AUTO)
|
||||||
|
if (chase == SH_LOC_AUTO) {
|
||||||
|
if (SH_LOC_AUTO_IS_CHASE) chase = SH_LOC_CHASE; else chase = SH_LOC_FIXED;
|
||||||
|
}
|
||||||
|
unsigned long time_now = millis();
|
||||||
|
unsigned long time_delta = time_now - time_last_aprs_update;
|
||||||
|
unsigned long update_time = (chase == SH_LOC_CHASE) ? APRS_MOBILE_STATION_UPDATE_TIME : APRS_STATION_UPDATE_TIME;
|
||||||
|
if(time_delta < update_time) return;
|
||||||
|
Serial.println("Update is due!!");
|
||||||
|
|
||||||
|
float lat, lon;
|
||||||
|
if(chase == SH_LOC_FIXED) {
|
||||||
|
// fixed location
|
||||||
|
lat = sonde.config.rxlat;
|
||||||
|
lon = sonde.config.rxlon;
|
||||||
|
if(isnan(lat) || isnan(lon)) return;
|
||||||
|
} else {
|
||||||
|
if (gpsPos.valid && gpsPos.lat != 0 && gpsPos.lon != 0) {
|
||||||
|
lat = gpsPos.lat;
|
||||||
|
lon = gpsPos.lon;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.printf("Really updating!! (bcall is %s)", sonde.config.bcall);
|
||||||
|
time_last_aprs_update = time_now;
|
||||||
|
char *bcn = aprs_send_beacon(sonde.config.bcall, lat, lon, "/O");
|
||||||
|
if ( tcpclient.disconnected()) {
|
||||||
|
tcpclient.connect(sonde.config.tcpfeed.host, sonde.config.tcpfeed.port);
|
||||||
|
}
|
||||||
|
if ( tcpclient.connected() ) {
|
||||||
|
strcat(bcn, "\r\n");
|
||||||
|
Serial.println("****BEACON****");
|
||||||
|
Serial.print(bcn);
|
||||||
|
tcpclient.write(bcn, strlen(bcn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if FEATURE_SONDEHUB
|
#if FEATURE_SONDEHUB
|
||||||
// Sondehub v2 DB related codes
|
// Sondehub v2 DB related codes
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -42,10 +42,13 @@ var cfgs = [
|
||||||
[ "axudp.idformat", "DFM ID format"],
|
[ "axudp.idformat", "DFM ID format"],
|
||||||
[ "axudp.highrate", "Rate limit"],
|
[ "axudp.highrate", "Rate limit"],
|
||||||
[ "tcp.active", "APRS TCP active"],
|
[ "tcp.active", "APRS TCP active"],
|
||||||
[ "tcp.host", "ARPS TCP host"],
|
[ "tcp.host", "APRS TCP host"],
|
||||||
[ "tcp.port", "APRS TCP port"],
|
[ "tcp.port", "APRS TCP port"],
|
||||||
[ "tcp.idformat", "DFM ID format"],
|
[ "tcp.idformat", "DFM ID format"],
|
||||||
[ "tcp.highrate", "Rate limit"],
|
[ "tcp.highrate", "Rate limit"],
|
||||||
|
[ "tcp.bcall", "APRS location beacon call"],
|
||||||
|
[ "tcp.chase", "APRS location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)"],
|
||||||
|
[ "tcp.comment", "APRS location comment"],
|
||||||
[ "", "MQTT data feed configuration", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/MQTT-configuration"],
|
[ "", "MQTT data feed configuration", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/MQTT-configuration"],
|
||||||
[ "mqtt.active", "MQTT active (needs reboot)"],
|
[ "mqtt.active", "MQTT active (needs reboot)"],
|
||||||
[ "mqtt.id", "MQTT client ID"],
|
[ "mqtt.id", "MQTT client ID"],
|
||||||
|
|
|
@ -43,7 +43,7 @@ const char *fingerprintText[]={
|
||||||
/* global variables from RX_FSK.ino */
|
/* global variables from RX_FSK.ino */
|
||||||
int getKeyPressEvent();
|
int getKeyPressEvent();
|
||||||
int handlePMUirq();
|
int handlePMUirq();
|
||||||
extern bool pmu_irq;
|
extern uint8_t pmu_irq;
|
||||||
extern SX1278FSK sx1278;
|
extern SX1278FSK sx1278;
|
||||||
|
|
||||||
/* Task model:
|
/* Task model:
|
||||||
|
@ -542,10 +542,10 @@ uint16_t Sonde::waitRXcomplete() {
|
||||||
uint16_t res=0;
|
uint16_t res=0;
|
||||||
uint32_t t0 = millis();
|
uint32_t t0 = millis();
|
||||||
rxloop:
|
rxloop:
|
||||||
while( !pmu_irq && rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); }
|
while( (pmu_irq!=1) && rxtask.receiveResult==0xFFFF && millis()-t0 < 3000) { delay(50); }
|
||||||
if( pmu_irq ) {
|
if( pmu_irq ) {
|
||||||
handlePMUirq();
|
handlePMUirq();
|
||||||
goto rxloop;
|
if(pmu_irq!=2) goto rxloop;
|
||||||
}
|
}
|
||||||
if( rxtask.receiveResult == RX_UPDATERSSI ) {
|
if( rxtask.receiveResult == RX_UPDATERSSI ) {
|
||||||
rxtask.receiveResult = 0xFFFF;
|
rxtask.receiveResult = 0xFFFF;
|
||||||
|
|
|
@ -287,6 +287,9 @@ typedef struct st_rdzconfig {
|
||||||
// for now, one feed for each type is enough, but might get extended to more?
|
// for now, one feed for each type is enough, but might get extended to more?
|
||||||
char call[10]; // APRS callsign
|
char call[10]; // APRS callsign
|
||||||
int passcode; // APRS passcode
|
int passcode; // APRS passcode
|
||||||
|
int chase;
|
||||||
|
char bcall[10]; // APRS position beacon call
|
||||||
|
char comment[32];
|
||||||
struct st_feedinfo udpfeed; // target for AXUDP messages
|
struct st_feedinfo udpfeed; // target for AXUDP messages
|
||||||
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
|
struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections
|
||||||
struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid)
|
struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid)
|
||||||
|
|
|
@ -258,13 +258,43 @@ static uint32_t dao91(double x)
|
||||||
|
|
||||||
char b[251];
|
char b[251];
|
||||||
//char raw[201];
|
//char raw[201];
|
||||||
|
const char *destcall="APRRDZ";
|
||||||
|
|
||||||
|
char *aprs_send_beacon(const char *usercall, float lat, float lon, const char *sym) {
|
||||||
|
*b = 0;
|
||||||
|
aprsstr_append(b, usercall);
|
||||||
|
aprsstr_append(b, ">");
|
||||||
|
aprsstr_append(b, destcall);
|
||||||
|
#if 0
|
||||||
|
aprsstr_append(b, ":/"); // / is report with timestamp
|
||||||
|
int i = strlen(b);
|
||||||
|
int sec = 0; // TODO: NOW!!!
|
||||||
|
snprintf(b+i, APRS_MAXLEN, "%02d%02d%02dh", sec/(60*60), (sec%(60*60))/60, sec%60);
|
||||||
|
#else
|
||||||
|
// report without timestamp
|
||||||
|
aprsstr_append(b, ":!"); // ! is report w/p timestamp
|
||||||
|
#endif
|
||||||
|
// lat
|
||||||
|
i = strlen(b);
|
||||||
|
int lati = abs((int)lat);
|
||||||
|
int latm = (fabs(lat)-lati)*6000;
|
||||||
|
snprintf(b+i, APRS_MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, lat<0?'S':'N', sym[0]);
|
||||||
|
// lon
|
||||||
|
i = strlen(b);
|
||||||
|
int loni = abs((int)lon);
|
||||||
|
int lonm = (fabs(lon)-loni)*6000;
|
||||||
|
snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, lon<0?'W':'E', sym[1]);
|
||||||
|
// maybe add alt
|
||||||
|
// maybe add DAO?
|
||||||
|
sprintf(b + strlen(b), "%s", version_name);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) {
|
char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) {
|
||||||
SondeData *s = &(si->d);
|
SondeData *s = &(si->d);
|
||||||
*b=0;
|
*b=0;
|
||||||
aprsstr_append(b, usercall);
|
aprsstr_append(b, usercall);
|
||||||
aprsstr_append(b, ">");
|
aprsstr_append(b, ">");
|
||||||
const char *destcall="APRRDZ";
|
|
||||||
// const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg";
|
// const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg";
|
||||||
aprsstr_append(b, destcall);
|
aprsstr_append(b, destcall);
|
||||||
// uncompressed
|
// uncompressed
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
void aprs_gencrctab(void);
|
void aprs_gencrctab(void);
|
||||||
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
|
int aprsstr_mon2raw(const char *mon, char raw[], int raw_len);
|
||||||
int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len);
|
int aprsstr_mon2kiss(const char *mon, char raw[], int raw_len);
|
||||||
|
char *aprs_send_beacon(const char *call, float lat, float lon, const char *sym);
|
||||||
char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym);
|
char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym);
|
||||||
|
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue