Experimental: Modified DFM handling (DFM17 vs DFM09P for 0xC), untested

This commit is contained in:
Hansi, dl9rdz 2023-04-13 13:13:01 +00:00
parent 7a1b97cacf
commit 40f1ab731a
6 changed files with 101 additions and 23 deletions

View File

@ -19,14 +19,18 @@
#include "src/Display.h"
#include "src/Scanner.h"
#include "src/geteph.h"
#ifdef FEATURE_RS92
#include "src/rs92gps.h"
#endif
#include "src/aprs.h"
#include "src/ShFreqImport.h"
#include "src/RS41.h"
#include "src/DFM.h"
#include "src/json.h"
#if FEATURE_CHASEMAPPER
#include "src/Chasemapper.h"
#endif
//#include "NimBLEDevice.h"
#if FEATURE_MQTT
#include "src/mqtt.h"
@ -67,6 +71,9 @@ WiFiClient client;
/* Sonde.h: enum SondeType { STYPE_DFM,, STYPE_RS41, STYPE_RS92, STYPE_M10M20, STYPE_M10, STYPE_M20, STYPE_MP3H }; */
const char *sondeTypeStrSH[NSondeTypes] = { "DFM", "RS41", "RS92", "Mxx"/*never sent*/, "M10", "M20", "MRZ" };
#if 0
// not used any more
const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL,
"DFM06", // 0x06
"PS15", // 0x07
@ -77,6 +84,7 @@ const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL,
"DFM17", // 0x0D
NULL, NULL
};
#endif
// Times in ms, i.e. station: 10 minutes, mobile: 20 seconds
#define APRS_STATION_UPDATE_TIME (10*60*1000)
@ -1878,12 +1886,17 @@ void heap_caps_alloc_failed_hook(size_t requested_size, uint32_t caps, const cha
void setup()
{
char buf[12];
// Open serial communications and wait for port to open:
Serial.begin(/*921600 */115200);
for (int i = 0; i < 39; i++) {
int v = gpio_get_level((gpio_num_t)i);
Serial.printf("%d:%d ", i, v);
}
//NimBLEDevice::init("NimBLE-Arduino");
//NimBLEServer* pServer = NimBLEDevice::createServer();;
Serial.println("");
#ifdef ESP_MEM_DEBUG
esp_err_t error = heap_caps_register_failed_alloc_callback(heap_caps_alloc_failed_hook);
@ -2960,6 +2973,7 @@ void loopWifiScan() {
sonde.setIP(localIPstr.c_str(), false);
sonde.updateDisplayIP();
wifi_state = WIFI_CONNECTED;
#if FEATURE_RS92
bool hasRS92 = false;
for (int i = 0; i < MAXSONDE; i++) {
if (sonde.sondeList[i].type == STYPE_RS92) hasRS92 = true;
@ -2969,6 +2983,7 @@ void loopWifiScan() {
if (ephstate == EPH_PENDING) ephstate = EPH_ERROR;
get_eph("/brdc");
}
#endif
delay(3000);
}
enableNetwork(true);
@ -3639,11 +3654,14 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub *
}
/* if there is a subtype (DFM only) */
if ( TYPE_IS_DFM(s->type) && s->d.subtype > 0 && s->d.subtype < 16 ) {
const char *t = dfmSubtypeStrSH[s->d.subtype];
// as in https://github.com/projecthorus/radiosonde_auto_rx/blob/e680221f69a568e1fdb24e76db679233f32cb027/auto_rx/autorx/sonde_specific.py#L84
if (t) sprintf(w, "\"subtype\": \"%s\",", t);
else sprintf(w, "\"subtype\": \"DFMx%X\",", s->d.subtype); // Unknown subtype
if ( TYPE_IS_DFM(s->type) && s->d.subtype > 0 ) {
if( (s->d.subtype&0xF) != DFM_UNK) {
const char *t = dfmSubtypeLong[s->d.subtype&0xF];
sprintf(w, "\"subtype\": \"%s\",", t);
}
else {
sprintf(w, "\"subtype\": \"DFMx%X\",", s->d.subtype>>4); // Unknown subtype
}
w += strlen(w);
} else if ( s->type == STYPE_RS41 ) {
char buf[11];

View File

@ -16,6 +16,13 @@
#define MAXIDAGE 1800
const char *dfmSubtypeLong[] = { "", "DFMxx", "DFM06", "DFM06P", "PS15",
"DFM09", "DFM09P", "DFM17", "DFM17P"};
const char *dfmSubtypeShort[] = { "", "DFMx", "DFM6", "DF6P", "PS15",
"DFM9", "DF9P", "DF17", "D17P"};
/*
* observed DAT patterns for DFM-9:
* A: 0+1; 2+3; 4+5; 6+7; 8+0 => keep frame in shadowFrame
@ -44,7 +51,10 @@ static struct st_dfmstat {
uint8_t nameregtop;
uint8_t lastdat;
uint8_t cycledone; // 0=no; 1=OK, 2=partially/with errors
float meas[5+2];
float meas[9];
uint16_t measok; // Bit-mask showing which meas entries have been received
uint8_t ptu_chan; // always the max channel. used as subtype before, but 0xC can be DFM09 (with P) or DFM17 (w/o P)
uint8_t sensP; // P channel in data (0xC DMF09 (but not 0xC DFM17), 0xD DFM17P, 0x8 DFM6P (but not PS15) (0 or 1)
} dfmstate;
decoderSetupCfg DFMSetupCfg {
@ -280,8 +290,12 @@ void DFM::finddfname(uint8_t *b)
snprintf(sd->id, 10, "D%x ", id);
memcpy(sd->ser, sd->id+1, 9);
sd->validID = true;
sd->subtype = (st>>4)&0x0F;
strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
//sd->subtype = (st>>4)&0x0F;
//strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
// Subtype is set later, as we need more data to distingish 0xC DFM09P and DFM17
sd->subtype = 0;
dfmstate.ptu_chan = (st>>4)&0x0F;
strcpy(sd->typestr, "DFM");
return;
}
dfmstate.lastfrcnt = 0;
@ -332,8 +346,12 @@ void DFM::finddfname(uint8_t *b)
Serial.println(sd->id);
memcpy(sd->ser, sd->id+1, 9);
sd->validID = true;
sd->subtype = (st>>4)&0x0F;
strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
//sd->subtype = (st>>4)&0x0F;
//strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5);
// Subtype is set later, as we need more data to distingish 0xC DFM09P and DFM17
sd->subtype = 0;
dfmstate.ptu_chan = (st>>4)&0x0F;
strcpy(sd->typestr, "DFM");
}
if(dfmstate.nameregok==i) {
Serial.print(" ID OK");
@ -361,13 +379,13 @@ void DFM::finddfname(uint8_t *b)
static float get_Temp() {
SondeData *si = &(sonde.si()->d);
if(!si->validID) { // type not yet known, so don't try to decode
if(!si->subtype) { // type not yet known, so don't try to decode
return NAN;
}
float f = dfmstate.meas[0],
f1 = dfmstate.meas[3],
f2 = dfmstate.meas[4];
if(si->subtype >= 0x0C) {
if(dfmstate.sensP) {
f = dfmstate.meas[1];
f1 = dfmstate.meas[5];
f2 = dfmstate.meas[6];
@ -377,7 +395,8 @@ static float get_Temp() {
float BB0 = 3260.0; // B/Kelvin, fit -55C..+40C
float T0 = 25 + 273.15; // t0=25C
float R0 = 5.0e3; // R0=R25=5k
float Rf = 220e3; // Rf = 220k
float Rf = 220e3; // Rf = 220k, for DFM17: 332k
if( si->subtype==DFM_17 || si->subtype==DFM_17P ) Rf = 332e3;
float g = f2/Rf;
float R = (f-f1) / g; // meas[0,3,4] > 0 ?
float T = 0; // T/Kelvin
@ -398,16 +417,41 @@ void DFM::decodeCFG(uint8_t *cfg)
finddfname(cfg);
// get meas
uint8_t conf_id = (*cfg)>>4;
if(conf_id<=6) {
if(conf_id<=8) {
uint32_t val = (cfg[1]<<12) | (cfg[2]<<4) | cfg[3];
uint8_t exp = cfg[0] & 0xF;
dfmstate.meas[conf_id] = val / (float)(1<<exp);
dfmstate.measok |= (1 << conf_id);
Serial.printf("meas %d is %f (%d,%d)\n", conf_id, dfmstate.meas[conf_id], val, exp);
}
// get type (if we have an ID, but no type yet, and (needed only for 0xC), meas[6])
if( si->validID && si->subtype==0 && (dfmstate.measok & (1<<6)) ) {
switch(dfmstate.ptu_chan) {
case 0x6: si->subtype = DFM_06; break;
case 0x7: case 0x8:
si->subtype = DFM_06P; dfmstate.sensP = 1; break; // (TODO: OR PS15)
case 0xA: si->subtype = DFM_09; break;
case 0xB: si->subtype = DFM_17; break;
case 0xC: // DFM-09P or DFM-17
if(dfmstate.meas[6]<220e3) { si->subtype = DFM_09P; dfmstate.sensP = 1; }
else si->subtype = DFM_17;
break;
case 0xD: si->subtype = DFM_17P; dfmstate.sensP = 1; break;
default: si->subtype = DFM_UNK;
}
if( si->subtype == DFM_UNK ) {
snprintf(si->typestr, 5, "DFx%x", dfmstate.ptu_chan);
si->subtype |= (dfmstate.ptu_chan<<4);
} else {
strcpy(si->typestr, dfmSubtypeShort[si->subtype]);
}
}
// get batt
if(si->validID && si->subtype>=0x0A) {
if(si->validID && dfmstate.ptu_chan>=0x0A && si->subtype>0 ) {
// otherwise don't try, as we might not have the right type yet...
int cid = (si->subtype >= 0x0C) ? 0x7 : 0x5;
int cid = (dfmstate.sensP) ? 0x7 : 0x5;
if(conf_id == cid) {
uint16_t val = cfg[1]<<8 | cfg[2];
si->batteryVoltage = val / 1000.0;

View File

@ -20,6 +20,11 @@
#define DFM_NORMAL 0
#define DFM_INVERSE 1
enum DFMSubtype { DFM_UNDEF, DFM_UNK, DFM_06, DFM_06P, DFM_PS15, DFM_09, DFM_09P, DFM_17, DFM_17P };
extern const char *dfmSubtypeLong[];
extern const char *dfmSubtypeShort[];
/* Main class */
class DFM : public DecoderBase
{

View File

@ -3,7 +3,9 @@
#include "Sonde.h"
#include "RS41.h"
#if FEATURE_RS92
#include "RS92.h"
#endif
#include "DFM.h"
#include "M10M20.h"
#include "MP3H.h"
@ -431,7 +433,9 @@ void Sonde::setup() {
dfm.setup( sondeList[rxtask.currentSonde].freq * 1000000, sondeList[rxtask.currentSonde].type );
break;
case STYPE_RS92:
#ifdef FEATURE_RS92
rs92.setup( sondeList[rxtask.currentSonde].freq * 1000000);
#endif
break;
case STYPE_M10:
case STYPE_M20:
@ -462,7 +466,9 @@ void Sonde::receive() {
res = rs41.receive();
break;
case STYPE_RS92:
#ifdef FEATURE_RS92
res = rs92.receive();
#endif
break;
case STYPE_M10:
case STYPE_M20:
@ -562,7 +568,9 @@ rxloop:
rs41.waitRXcomplete();
break;
case STYPE_RS92:
#ifdef FEATURE_RS92
rs92.waitRXcomplete();
#endif
break;
case STYPE_M10:
case STYPE_M20:

View File

@ -1,19 +1,22 @@
#include "json.h"
#include "RS41.h"
#include "DFM.h"
extern const char *sondeTypeStrSH[];
extern const char *dfmSubtypeStrSH[];
//extern const char *dfmSubtypeStrSH[];
static char typestr[11];
const char *getType(SondeInfo *si) {
if( si->type == STYPE_RS41 ) {
if ( RS41::getSubtype(typestr, 11, si) == 0 ) return typestr;
} else if ( TYPE_IS_DFM(si->type) && si->d.subtype > 0 && si->d.subtype < 16 ) {
const char *t = dfmSubtypeStrSH[si->d.subtype];
if(t) return t;
sprintf(typestr, "DFMx%X", si->d.subtype);
return typestr;
} else if ( TYPE_IS_DFM(si->type) && si->d.subtype > 0 ) {
const char *t = dfmSubtypeLong[si->d.subtype & 0xf];
if( (si->d.subtype & 0xf) == DFM_UNK) {
sprintf(typestr, "DFMx%X", si->d.subtype>>4);
return typestr;
}
return t;
}
return sondeTypeStrSH[sonde.realType(si)];
}

View File

@ -1,4 +1,4 @@
const char *version_name = "rdzTTGOsonde";
const char *version_id = "devel20230104";
const char *version_id = "devel20230413";
const int SPIFFS_MAJOR=2;
const int SPIFFS_MINOR=17;