diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 89dcf23..c9f0dc5 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -227,7 +227,7 @@ const char *handleQRGPost(AsyncWebServerRequest *request) { const char *tstr = tstring.c_str(); const char *sstr = sstring.c_str(); Serial.printf("Processing a=%s, f=%s, t=%s, site=%s\n", active ? "YES" : "NO", fstr, tstr, sstr); - char typech = (tstr[2] == '4' ? '4' : tstr[2] == '9' ? 'R' : tstr[0]=='M' ? 'M' : tstr[3]); // a bit ugly + char typech = (tstr[2] == '4' ? '4' : tstr[2] == '9' ? 'R' : tstr[0] == 'M' ? 'M' : tstr[3]); // a bit ugly file.printf("%3.3f %c %c %s\n", atof(fstr), typech, active ? '+' : '-', sstr); } file.close(); @@ -338,14 +338,16 @@ void addSondeStatus(char *ptr, int i) struct tm ts; SondeInfo *s = &sonde.sondeList[i]; strcat(ptr, ""); - sprintf(ptr + strlen(ptr), "\n", - s->freq, sondeTypeStr[s->type], - s->validID ? s->id : "", - s->lat, s->lon, s->alt); + sprintf(ptr + strlen(ptr), "\n", s->lat, s->lon, s->alt); const time_t t = s->time; ts = *gmtime(&t); - sprintf(ptr + strlen(ptr), "", - s->frame, s->sats, ts.tm_year+1900, ts.tm_mon+1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec+s->sec); + sprintf(ptr + strlen(ptr), "", + s->frame, s->sats, ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec + s->sec); sprintf(ptr + strlen(ptr), "", s->lat, s->lon); @@ -1497,8 +1499,7 @@ void loopDecoder() { // first check if ID and position lat+lonis ok SondeInfo *s = &sonde.sondeList[rxtask.receiveSonde]; if (s->validID && ((s->validPos & 0x03) == 0x03)) { - const char *str = aprs_senddata(s->lat, s->lon, s->alt, s->hs, s->dir, s->vs, sondeTypeStr[s->type], s->id, "TE0ST", - sonde.config.udpfeed.symbol); + const char *str = aprs_senddata(s, sonde.config.call, sonde.config.udpfeed.symbol); if (connected) { char raw[201]; int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN); diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 62f5e9f..96c51eb 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,2 +1,2 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20191101"; +const char *version_id = "devel20191102"; diff --git a/libraries/SondeLib/DFM.cpp b/libraries/SondeLib/DFM.cpp index cd0de38..a0fad81 100644 --- a/libraries/SondeLib/DFM.cpp +++ b/libraries/SondeLib/DFM.cpp @@ -183,7 +183,9 @@ void DFM::decodeCFG(uint8_t *cfg) if(idgood==3) { uint32_t dfmid = (highid<<16) | lowid; Serial.print("DFM-09 ID: "); Serial.print(dfmid); - snprintf(sonde.si()->id, 10, "%d", dfmid); + snprintf(sonde.si()->ser, 10, "%d", dfmid); + // dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number + snprintf(sonde.si()->id, 9, "DF6%05X", dfmid&0xfffff); sonde.si()->validID = true; } } diff --git a/libraries/SondeLib/Display.cpp b/libraries/SondeLib/Display.cpp index aec3bf8..5d86097 100644 --- a/libraries/SondeLib/Display.cpp +++ b/libraries/SondeLib/Display.cpp @@ -24,7 +24,7 @@ extern bool axp192_found; SPIClass spiDisp(HSPI); -const char *sondeTypeStr[NSondeTypes] = { "DFM6", "DFM9", "RS41", "RS92", "M10 " }; +const char *sondeTypeStr[NSondeTypes] = { "DFM6", "DFM9", "RS41", "RS92", "M10" }; byte myIP_tiles[8*11]; static uint8_t ap_tile[8]={0x00,0x04,0x22,0x92, 0x92, 0x22, 0x04, 0x00}; @@ -256,7 +256,7 @@ void U8x8Display::welcome() { drawString(8 - strlen(version_name) / 2, 0, version_name); drawString(8 - strlen(version_id) / 2, 2, version_id); setFont(FONT_SMALL); - drawString(0, 4, "RS41,RS92,DFM6/9"); + drawString(0, 4, "RS41/92,DFM,M10"); drawString(0, 6, "by Hansi, DL9RDZ"); } @@ -427,10 +427,10 @@ void ILI9225Display::welcome() { setFont(5); int l=3*22; if(sonde.config.tft_orient&1) { - drawString(0, 1*22, "RS41,RS92,DFM6/9"); + drawString(0, 1*22, "RS41/92,DFM6/9,M10"); } else { drawString(0, 1*22, "RS41,RS92,"); - drawString(0, 2*22, "DFM6/9"); + drawString(0, 2*22, "DFM6/9,M10"); l+=22; } drawString(0, l, version_id); @@ -945,18 +945,21 @@ void Display::drawID(DispEntry *de) { if(!de->extra || de->extra[0]=='s') { // real serial number, as printed on sonde - drawString(de, sonde.si()->id); + drawString(de, sonde.si()->ser); } else if (de->extra[0]=='a') { - // autorx sonde number ("DF9" and last 6 digits of real serial number - strcpy(buf, sonde.si()->id); - memcpy(buf, "DF9", 3); - drawString(de, buf); + // autorx sonde number ("DF9" and last 6 digits of real serial number) + if(sonde.si()->type == STYPE_DFM09) { + int n = strlen(sonde.si()->ser) - 6; + if(n<0) n=0; + memcpy(buf, "DF9", 3); + memcpy(buf+3, sonde.si()->ser+n, 6); + drawString(de, buf); + } else { + drawString(de, sonde.si()->ser); + } } else { // dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number - uint32_t id = atoi(sonde.si()->id); - id = id&0xfffff; - snprintf(buf, 16, "DF6%05X", id); - drawString(de, buf); + drawString(de, sonde.si()->id); } } void Display::drawRSSI(DispEntry *de) { diff --git a/libraries/SondeLib/M10.cpp b/libraries/SondeLib/M10.cpp index b94d976..004c979 100644 --- a/libraries/SondeLib/M10.cpp +++ b/libraries/SondeLib/M10.cpp @@ -18,33 +18,10 @@ #endif -#if 0 -static double atang2(double x, double y) -{ - double w; - if (fabs(x)>fabs(y)) { - w = (double)atan((float)(X2C_DIVL(y,x))); - if (x<0.0) { - if (y>0.0) w = 3.1415926535898+w; - else w = w-3.1415926535898; - } - } - else if (y!=0.0) { - w = (double)(1.5707963267949f-atan((float)(X2C_DIVL(x, - y)))); - if (y<0.0) w = w-3.1415926535898; - } - else w = 0.0; - return w; -} /* end atang2() */ -#endif - -static byte data1[512]={0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x10}; -static byte data2[512]={0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x10}; +static byte data1[512]; static byte *dataptr=data1; static uint8_t rxbitc; -static int32_t asynst[10]={0}; static uint16_t rxbyte; static int rxp=0; static int haveNewFrame = 0; @@ -239,6 +216,10 @@ static int16_t getint16(uint8_t *data) { return (int16_t)(data[1]|((uint16_t)data[0]<<8)); } +static char dez(uint8_t nr) { + nr = nr%10; + return '0'+nr; +} static char hex(uint8_t nr) { nr = nr&0x0f; if(nr<10) return '0'+nr; @@ -294,6 +275,17 @@ bool M10::decodeframeM10(uint8_t *data) { ids[8] = hex(id); ids[9] = 0; strncpy(sonde.si()->id, ids, 10); + ids[0] = hex(data[95]/16); + ids[1] = dez((data[95]&0x0f)/10); + ids[2] = dez((data[95]&0x0f)); + ids[3] = dez(data[93]); + ids[4] = dez(id>>13); + id &= 0x1fff; + ids[5] = dez(id/1000); + ids[6] = dez((id/100)%10); + ids[7] = dez((id/10)%10); + ids[8] = dez(id%10); + strncpy(sonde.si()->ser, ids, 10); sonde.si()->validID = true; Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id); // ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal diff --git a/libraries/SondeLib/RS41.cpp b/libraries/SondeLib/RS41.cpp index 63264df..d885806 100644 --- a/libraries/SondeLib/RS41.cpp +++ b/libraries/SondeLib/RS41.cpp @@ -427,6 +427,8 @@ int RS41::decode41(byte *data, int maxlen) sonde.si()->type=STYPE_RS41; strncpy(sonde.si()->id, (const char *)(data+p+2), 8); sonde.si()->id[8]=0; + strncpy(sonde.si()->ser, (const char *)(data+p+2), 8); + sonde.si()->ser[8]=0; sonde.si()->validID=true; } // TODO: some more data diff --git a/libraries/SondeLib/RS92.cpp b/libraries/SondeLib/RS92.cpp index 3c6cdd1..5d777ed 100644 --- a/libraries/SondeLib/RS92.cpp +++ b/libraries/SondeLib/RS92.cpp @@ -622,6 +622,7 @@ int RS92::waitRXcomplete() { si->dir = gpx.vD; si->validPos = 0x3f; memcpy(si->id, gpx.id, 9); + memcpy(si->ser, gpx.id, 9); si->validID = true; si->frame = gpx.frnr; si->sats = gpx.k; diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index 54f5541..51a1843 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -70,6 +70,7 @@ void Sonde::defaultConfig() { config.touch_thresh = 70; config.led_pout = 9; config.power_pout = -1; + config.spectrum=10; // Try autodetecting board type // Seems like on startup, GPIO4 is 1 on v1 boards, 0 on v2.1 boards? config.gps_rxd = -1; @@ -112,6 +113,7 @@ void Sonde::defaultConfig() { config.oled_rst = 14; config.tft_rs = 2; config.tft_cs = 0; + config.spectrum = -1; // no spectrum for now on large display } else { // OLED display, pins 21,22 ok... config.disptype = 0; @@ -131,6 +133,7 @@ void Sonde::defaultConfig() { config.oled_rst = 22; config.tft_rs = 2; config.tft_cs = 0; + config.spectrum = -1; // no spectrum for now on large display } } } else { @@ -151,7 +154,6 @@ void Sonde::defaultConfig() { config.display[2]=-1; config.startfreq=400; config.channelbw=10; - config.spectrum=10; config.marker=0; config.showafc=0; config.freqofs=0; @@ -191,6 +193,7 @@ void Sonde::setConfig(const char *cfg) { if(config.noisefloor==0) config.noisefloor=-130; } else if(strcmp(cfg,"call")==0) { strncpy(config.call, val, 9); + config.call[9]=0; } else if(strcmp(cfg,"passcode")==0) { strncpy(config.passcode, val, 9); } else if(strcmp(cfg,"button_pin")==0) { diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index 3135cde..2f6b186 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -2,8 +2,6 @@ #ifndef Sonde_h #define Sonde_h -#include "aprs.h" - // RX_TIMEOUT: no header detected // RX_ERROR: header detected, but data not decoded (crc error, etc.) // RX_OK: header and data ok @@ -51,6 +49,42 @@ extern const char *RXstr[]; enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41, STYPE_RS92, STYPE_M10 }; extern const char *sondeTypeStr[NSondeTypes]; +typedef struct st_sondeinfo { + // receiver configuration + bool active; + SondeType type; + float freq; + // decoded ID + char id[10]; + char ser[12]; + bool validID; + char launchsite[18]; + // decoded position + float lat; // latitude + float lon; // longitude + float alt; // altitude + float vs; // vertical speed + float hs; // horizontal speed + float dir; // 0..360 + uint8_t sats; // number of sats + uint8_t validPos; // bit pattern for validity of above 6 fields + // decoded GPS time + uint32_t time; + uint16_t sec; + uint32_t frame; + bool validTime; + // RSSI from receiver + int rssi; // signal strength + int32_t afc; // afc correction value + // statistics + uint8_t rxStat[20]; + uint32_t rxStart; // millis() timestamp of continuous rx start + uint32_t norxStart; // millis() timestamp of continuous no rx start + uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display + int8_t lastState; // -1: disabled; 0: norx; 1: rx +} SondeInfo; +// rxStat: 3=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1] 5=no valid position[°] + // Used for interacting with the RX background task typedef struct st_RXTask { // Variables set by Arduino main loop to value >=0 for requesting @@ -84,6 +118,29 @@ struct st_dfmconfig { int rxbw; }; + +enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO }; + +struct st_feedinfo { + bool active; + int type; // 0:UDP(axudp), 1:TCP(aprs.fi) + char host[64]; + int port; + char symbol[3]; + int lowrate; + int highrate; + int lowlimit; + int idformat; // 0: dxl 1: real 2: auto +}; + +// maybe extend for external Bluetooth interface? +// internal bluetooth consumes too much memory +struct st_kisstnc { + bool active; + int idformat; +}; + + typedef struct st_rdzconfig { // hardware configuration int button_pin; // PIN port number menu button (+128 for touch mode) @@ -120,48 +177,13 @@ typedef struct st_rdzconfig { struct st_dfmconfig dfm; // data feed configuration // for now, one feed for each type is enough, but might get extended to more? - char call[9]; // APRS callsign + char call[10]; // APRS callsign char passcode[9]; // APRS passcode 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) } RDZConfig; -typedef struct st_sondeinfo { - // receiver configuration - bool active; - SondeType type; - float freq; - // decoded ID - char id[10]; - bool validID; - char launchsite[18]; - // decoded position - float lat; // latitude - float lon; // longitude - float alt; // altitude - float vs; // vertical speed - float hs; // horizontal speed - float dir; // 0..360 - uint8_t sats; // number of sats - uint8_t validPos; // bit pattern for validity of above 6 fields - // decoded GPS time - uint32_t time; - uint16_t sec; - uint32_t frame; - bool validTime; - // RSSI from receiver - int rssi; // signal strength - int32_t afc; // afc correction value - // statistics - uint8_t rxStat[20]; - uint32_t rxStart; // millis() timestamp of continuous rx start - uint32_t norxStart; // millis() timestamp of continuous no rx start - uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display - int8_t lastState; // -1: disabled; 0: norx; 1: rx -} SondeInfo; -// rxStat: 3=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1] 5=no valid position[°] - #define MAXSONDE 99 diff --git a/libraries/SondeLib/aprs.cpp b/libraries/SondeLib/aprs.cpp index bfa73fc..0b7b14b 100644 --- a/libraries/SondeLib/aprs.cpp +++ b/libraries/SondeLib/aprs.cpp @@ -8,7 +8,7 @@ */ #include -#include +#include #include //#include //#include @@ -274,8 +274,8 @@ static uint32_t dao91(double x) char b[201]; char raw[201]; -char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym) -{ +char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) { +// float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym, const char *comm) *b=0; aprsstr_append(b, usercall); aprsstr_append(b, ">"); @@ -284,39 +284,43 @@ char * aprs_senddata(float lat, float lon, float alt, float speed, float dir, fl // uncompressed aprsstr_append(b, ":;"); char tmp[10]; - snprintf(tmp,10,"%s ",objname); + snprintf(tmp,10,"%s ",s->id); aprsstr_append(b, tmp); aprsstr_append(b, "*"); - // TODO: time - //aprsstr_append_data(time, ds); - aprsstr_append(b, "121212z"); + // time int 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]); + int sec = s->time % 86400; + snprintf(b+i, APRS_MAXLEN-1, "%02d%02d%02dz", sec/(60*60), (sec%(60*60))/60, sec%60); 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]); -#if 1 - if(speed>0.5) { + //aprsstr_append_data(time, ds); + int lati = abs((int)s->lat); + int latm = (fabs(s->lat)-lati)*6000; + snprintf(b+i, APRS_MAXLEN-i, "%02d%02d.%02d%c%c", lati, latm/100, latm%100, s->lat<0?'S':'N', sym[0]); + i = strlen(b); + int loni = abs((int)s->lon); + int lonm = (fabs(s->lon)-loni)*6000; + snprintf(b+i, APRS_MAXLEN-i, "%03d%02d.%02d%c%c", loni, lonm/100, lonm%100, s->lon<0?'W':'E', sym[1]); + if(s->hs>0.5) { i=strlen(b); - snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(dir+1.5), realcard(speed*1.0/KNOTS+0.5)); + snprintf(b+i, APRS_MAXLEN-i, "%03d/%03d", realcard(s->dir+1.5), realcard(s->hs*1.0/KNOTS+0.5)); } -#endif - if(alt>0.5) { + if(s->alt>0.5) { i=strlen(b); - snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(alt*FEET+0.5)); + snprintf(b+i, APRS_MAXLEN-i, "/A=%06d", realcard(s->alt*FEET+0.5)); } -#if 1 int dao=1; if(dao) { i=strlen(b); - snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(lat), 33+dao91(lon)); + snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(s->lat), 33+dao91(s->lon)); } -#endif - const char *comm="&test"; + strcat(b, "&"); + char comm[100]; + snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, s->freq, sondeTypeStr[s->type]); strcat(b, comm); + if(s->type==STYPE_M10||s->type==STYPE_DFM06||s->type==STYPE_DFM09) { + snprintf(comm, 100, " ser=%s", s->ser); + strcat(b, comm); + } return b; } diff --git a/libraries/SondeLib/aprs.h b/libraries/SondeLib/aprs.h index 5f993fd..6ac8b8e 100644 --- a/libraries/SondeLib/aprs.h +++ b/libraries/SondeLib/aprs.h @@ -1,34 +1,14 @@ #ifndef _aprs_h #define _aprs_h - -enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO }; - -struct st_feedinfo { - bool active; - int type; // 0:UDP(axudp), 1:TCP(aprs.fi) - char host[64]; - int port; - char symbol[3]; - int lowrate; - int highrate; - int lowlimit; - int idformat; // 0: dxl 1: real 2: auto -}; - -// maybe extend for external Bluetooth interface? -// internal bluetooth consumes too much memory -struct st_kisstnc { - bool active; - int idformat; -}; +#include "Sonde.h" #define APRS_MAXLEN 201 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_senddata(float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym); +char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym); #endif
%3.3f MHz, Type: %s
ID: %s
QTH: %.6f,%.6f h=%.0fm
%3.3f MHz, Type: %s
ID: %s", s->freq, sondeTypeStr[s->type], + s->validID ? s->id : ""); + if (s->validID && (s->type == STYPE_DFM06 || s->type == STYPE_DFM09 || s->type == STYPE_M10)) { + sprintf(ptr + strlen(ptr), " (ser: %s)", s->ser); + } + sprintf(ptr + strlen(ptr), "
QTH: %.6f,%.6f h=%.0fm
Frame# %d, Sats=%d, %04d-%02d-%02d %02d:%02d:%02d %d
Frame# %d, Sats=%d, %04d-%02d-%02d %02d:%02d:%02d
GEO-App - ", s->lat, s->lon); sprintf(ptr + strlen(ptr), "WX.DL2MF.de - ", s->id); sprintf(ptr + strlen(ptr), "OSM