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;
|
||||
#define PMU_IRQ 35
|
||||
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";
|
||||
int updatePort = 80;
|
||||
|
@ -75,6 +76,13 @@ const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL,
|
|||
"DFM17", // 0x0D
|
||||
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
|
||||
#define SONDEHUB_STATION_UPDATE_TIME (60*60*1000) // 60 min
|
||||
|
@ -83,18 +91,19 @@ WiFiClient shclient; // Sondehub v2
|
|||
int shImportInterval = 0;
|
||||
char shImport = 0;
|
||||
unsigned long time_last_update = 0;
|
||||
#endif
|
||||
/* SH_LOC_OFF: never send position information 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_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.
|
||||
*/
|
||||
// same constants used for SondeHub and APRS
|
||||
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) */
|
||||
#define MIN_LOC_AUTO_DIST 200 /* meter */
|
||||
#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 ) )
|
||||
#endif
|
||||
extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2);
|
||||
|
||||
// KISS over TCP for communicating with APRSdroid
|
||||
|
@ -745,7 +754,7 @@ struct st_configitems config_list[] = {
|
|||
{"mp3h.rxbw", 0, &sonde.config.mp3h.rxbw},
|
||||
{"ephftp", 39, &sonde.config.ephftp},
|
||||
/* APRS settings */
|
||||
{"call", 8, sonde.config.call},
|
||||
{"call", 9, sonde.config.call},
|
||||
{"passcode", 0, &sonde.config.passcode},
|
||||
/* KISS tnc settings */
|
||||
{"kisstnc.active", 0, &sonde.config.kisstnc.active},
|
||||
|
@ -760,6 +769,9 @@ struct st_configitems config_list[] = {
|
|||
{"tcp.active", -3, &sonde.config.tcpfeed.active},
|
||||
{"tcp.host", 63, sonde.config.tcpfeed.host},
|
||||
{"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.highrate", 0, &sonde.config.tcpfeed.highrate},
|
||||
#if FEATURE_CHASEMAPPER
|
||||
|
@ -2008,13 +2020,13 @@ void handlePMUirq() {
|
|||
button2.pressed = KP_MID;
|
||||
button2.keydownTime = my_millis();
|
||||
}
|
||||
pmu_irq = false;
|
||||
if(pmu_irq!=2) { pmu_irq = 0; }
|
||||
axp.clearIRQ();
|
||||
xSemaphoreGive( axpSemaphore );
|
||||
}
|
||||
} else {
|
||||
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
|
||||
axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON);
|
||||
axp.setDCDC3Voltage(3300);
|
||||
pmu_irq = 2; // IRQ pin is not connected on Core2
|
||||
} else {
|
||||
// GPS on T-Beam, buzzer on M5 Core2
|
||||
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
|
||||
|
@ -2182,11 +2195,13 @@ void setup()
|
|||
axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1);
|
||||
axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1);
|
||||
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
||||
if (sonde.config.button2_axp) {
|
||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
||||
attachInterrupt(PMU_IRQ, [] {
|
||||
pmu_irq = true;
|
||||
}, FALLING);
|
||||
if (sonde.config.button2_axp ) {
|
||||
if(pmu_irq !=2) {
|
||||
pinMode(PMU_IRQ, INPUT_PULLUP);
|
||||
attachInterrupt(PMU_IRQ, [] {
|
||||
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_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 );
|
||||
axp.clearIRQ();
|
||||
|
@ -2601,6 +2616,10 @@ void loopDecoder() {
|
|||
sondehub_finish_data(&shclient, s, &sonde.config.sondehub);
|
||||
#endif
|
||||
}
|
||||
// Send own position periodically
|
||||
if(sonde.config.tcpfeed.active) {
|
||||
aprs_station_update();
|
||||
}
|
||||
// always send data, even if not valid....
|
||||
if (rdzclient.connected()) {
|
||||
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
|
||||
// Sondehub v2 DB related codes
|
||||
/*
|
||||
|
|
|
@ -42,10 +42,13 @@ var cfgs = [
|
|||
[ "axudp.idformat", "DFM ID format"],
|
||||
[ "axudp.highrate", "Rate limit"],
|
||||
[ "tcp.active", "APRS TCP active"],
|
||||
[ "tcp.host", "ARPS TCP host"],
|
||||
[ "tcp.host", "APRS TCP host"],
|
||||
[ "tcp.port", "APRS TCP port"],
|
||||
[ "tcp.idformat", "DFM ID format"],
|
||||
[ "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.active", "MQTT active (needs reboot)"],
|
||||
[ "mqtt.id", "MQTT client ID"],
|
||||
|
|
|
@ -43,7 +43,7 @@ const char *fingerprintText[]={
|
|||
/* global variables from RX_FSK.ino */
|
||||
int getKeyPressEvent();
|
||||
int handlePMUirq();
|
||||
extern bool pmu_irq;
|
||||
extern uint8_t pmu_irq;
|
||||
extern SX1278FSK sx1278;
|
||||
|
||||
/* Task model:
|
||||
|
@ -542,10 +542,10 @@ uint16_t Sonde::waitRXcomplete() {
|
|||
uint16_t res=0;
|
||||
uint32_t t0 = millis();
|
||||
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 ) {
|
||||
handlePMUirq();
|
||||
goto rxloop;
|
||||
if(pmu_irq!=2) goto rxloop;
|
||||
}
|
||||
if( rxtask.receiveResult == RX_UPDATERSSI ) {
|
||||
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?
|
||||
char call[10]; // APRS callsign
|
||||
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 tcpfeed; // target for APRS-IS TCP connections
|
||||
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 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) {
|
||||
SondeData *s = &(si->d);
|
||||
*b=0;
|
||||
aprsstr_append(b, usercall);
|
||||
aprsstr_append(b, ">");
|
||||
const char *destcall="APRRDZ";
|
||||
// const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg";
|
||||
aprsstr_append(b, destcall);
|
||||
// uncompressed
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
void aprs_gencrctab(void);
|
||||
int aprsstr_mon2raw(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);
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue