kopia lustrzana https://github.com/sp9skp/spdxl
7125 wiersze
200 KiB
C
7125 wiersze
200 KiB
C
/*
|
|
* dxlAPRS toolchain
|
|
*
|
|
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
|
|
* Modified by SP9SKP, SQ2DK
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
|
|
#define X2C_int32
|
|
#define X2C_index32
|
|
#ifndef X2C_H_
|
|
#include "X2C.h"
|
|
#endif
|
|
#define sondeudp_C_
|
|
#ifndef soundctl_H_
|
|
#include "soundctl.h"
|
|
#endif
|
|
#ifndef udp_H_
|
|
#include "udp.h"
|
|
#endif
|
|
#ifndef osi_H_
|
|
#include "osi.h"
|
|
#endif
|
|
#include <osic.h>
|
|
#ifndef mlib_H_
|
|
#include "mlib.h"
|
|
#endif
|
|
#ifndef aprsstr_H_
|
|
#include "aprsstr.h"
|
|
#endif
|
|
#ifndef rsc_H_
|
|
#include "rsc.h"
|
|
#endif
|
|
#include <stdio.h>
|
|
|
|
#include <time.h>
|
|
#include "sondetypes.h"
|
|
|
|
/* demodulate RS92 sonde (2400bit/s manchester)
|
|
and SRS-C34 (2400Bd AFSK 2000/3800Hz
|
|
and DFM06 (2500bit/s manchester)
|
|
and RS41 (4800Bd GFSK) and send as AXUDP by OE5DXL */
|
|
/*FROM fcntl IMPORT creat, open; */
|
|
/*IMPORT reedsolomon; */
|
|
/* link init_rs_char.o decode_rs_char.o */
|
|
/* gcc -o sondeudp Lib.o aprsstr.o filesize.o flush.o osi.o ptty.o rsc.o sondeudp.o soundctl.o symlink.o tcp.o timec.o udp.o init_rs_char.o decode_rs_char.o /usr/local/xds/lib/x86/libts.a /usr/local/xds/lib/x86/libxds.a -lm */
|
|
#define sondeudp_MAXCHAN 64
|
|
|
|
#define sondeudp_CONTEXTLIFE 3600
|
|
/* seconds till forget context after last heared */
|
|
|
|
#define sondeudp_ADCBYTES 2
|
|
|
|
#define sondeudp_MAXLEN 9
|
|
/* data frame size c34 */
|
|
|
|
#define sondeudp_ADCBUFLEN 4096
|
|
|
|
#define sondeudp_BAUDSAMP 65536
|
|
|
|
#define sondeudp_PLLSHIFT 1024
|
|
|
|
#define sondeudp_RAD 1.7453292519943E-2
|
|
|
|
#define sondeudp_DFIRLEN 64
|
|
|
|
#define sondeudp_AFIRLEN 32
|
|
|
|
#define sondeudp_AOVERSAMP 16
|
|
/*16*/
|
|
|
|
#define sondeudp_ASYNBITS 10
|
|
|
|
static char sondeudp_CALIBFRAME = 'e';
|
|
|
|
static char sondeudp_GPSFRAME = 'g';
|
|
|
|
static char sondeudp_UNKNOWN = 'h';
|
|
|
|
static char sondeudp_DATAFRAME = 'i';
|
|
|
|
#define sondeudp_DOVERSAMP 16
|
|
|
|
#define sondeudp_CIDTIMEOUT 3600
|
|
/* s to delete c34 sonde id */
|
|
|
|
#define sondeudp_DFIDTIMEOUT 900
|
|
/* s to delete dfm sonde id */
|
|
|
|
#define sondeudp_FLEN6 264
|
|
/* dfm06 frame len */
|
|
|
|
#define sondeudp_DFMSYN 0x45CF
|
|
/* frame sync sequence */
|
|
|
|
#define sondeudp_FLENRS41 520
|
|
/* rs41 frame len */
|
|
|
|
#define sondeudp_FLEN10 101
|
|
/* M10 framelen */
|
|
#define sondeudp_M10SYN 0x649F20.
|
|
/* M10 sync */
|
|
|
|
#define sondeudp_FLEN20 70
|
|
/* M20 framelen */
|
|
#define sondeudp_M10SYN 0x4520
|
|
/* M20 sync */
|
|
|
|
|
|
/*
|
|
rs41x 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60
|
|
rs41 0x10, 0xB6, 0xCA, 0x11, 0x22, 0x96, 0x12, 0xF8
|
|
*/
|
|
#define sondeudp_RHEAD41 "000010000110110101010011100010000100010001101001010\
|
|
0100000011111"
|
|
|
|
static uint8_t sondeudp_EXOR41[64] = {150U,131U,62U,81U,177U,73U,8U,152U,
|
|
50U,5U,89U,14U,249U,68U,198U,38U,33U,96U,194U,234U,121U,93U,
|
|
109U,161U,84U,105U,71U,12U,220U,232U,92U,241U,247U,118U,130U,
|
|
127U,7U,153U,162U,44U,147U,124U,48U,99U,245U,16U,46U,97U,
|
|
208U,188U,180U,182U,6U,170U,244U,35U,120U,110U,59U,174U,191U,
|
|
123U,76U,193U};
|
|
|
|
typedef char FILENAME[1024];
|
|
|
|
typedef char CNAMESTR[9];
|
|
|
|
typedef float AFIRTAB[512];
|
|
|
|
typedef float DFIRTAB[1024];
|
|
|
|
typedef float DFIR[64];
|
|
|
|
struct UDPTX;
|
|
|
|
typedef struct UDPTX * pUDPTX;
|
|
|
|
struct UDPTX {
|
|
pUDPTX next;
|
|
uint32_t ip;
|
|
uint32_t destport;
|
|
int32_t udpfd;
|
|
};
|
|
|
|
|
|
struct R92;
|
|
|
|
|
|
struct R92 {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float noise;
|
|
float bitlev;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
uint32_t headerrs;
|
|
char rxbuf[256];
|
|
AFIRTAB afirtab;
|
|
int32_t asynst[10];
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
};
|
|
|
|
struct MP3;
|
|
|
|
struct MP3 {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
float noise0;
|
|
float bitlev0;
|
|
float noise;
|
|
float bitlev;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char rev;
|
|
char headok;
|
|
float lastu;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
char rxbuf[120],rxprev[120];
|
|
AFIRTAB afirtab;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
uint32_t synp;
|
|
char synbuf[64];
|
|
char fixbytes[101];
|
|
uint8_t fixcnt[520];
|
|
};
|
|
|
|
|
|
struct R41;
|
|
|
|
struct R41 {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
float noise0;
|
|
float bitlev0;
|
|
float noise;
|
|
float bitlev;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char rev;
|
|
char headok;
|
|
float lastu;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
char rxbuf[520];
|
|
AFIRTAB afirtab;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
uint32_t synp;
|
|
char synbuf[64];
|
|
char fixbytes[520];
|
|
uint8_t fixcnt[520];
|
|
};
|
|
|
|
|
|
//Added ------------------------------ by SQ2DK
|
|
|
|
unsigned int pok=1,nok=1,cnt=1;
|
|
|
|
struct PILS;
|
|
|
|
struct PILS {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
float noise0;
|
|
float bitlev0;
|
|
float noise;
|
|
float bitlev;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char rev;
|
|
char headok;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
float lastu;
|
|
char rxbuf[56+6]; //only 55 required
|
|
AFIRTAB afirtab;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
uint32_t synp;
|
|
char synbuf[64];
|
|
char fixbytes[56]; //not sure what for
|
|
uint8_t fixcnt[56];
|
|
time_t lastfr;
|
|
double poklat;
|
|
double poklon;
|
|
double pokalt;
|
|
|
|
|
|
|
|
// int16_t configequalizer;
|
|
};
|
|
//-------------------------------------------------------
|
|
|
|
|
|
struct DFM6;
|
|
struct DFM6 {
|
|
char enabled;
|
|
uint32_t lastsent;
|
|
uint32_t numcnt;
|
|
uint32_t idcnt0;
|
|
uint32_t idcnt1;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float noise;
|
|
float bitlev;
|
|
float lastu;
|
|
char polarity;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxp;
|
|
char rxbuf[264+6];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
char cb[56];
|
|
char ch[56];
|
|
char db1[104];
|
|
char db2[104];
|
|
char dh1[104];
|
|
char dh2[104];
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
char id[12];
|
|
int frnr;
|
|
int sonde_typ;
|
|
uint32_t SNL;
|
|
uint32_t SNH;
|
|
uint32_t SNT;
|
|
uint32_t SN;
|
|
uint32_t SN6;
|
|
uint32_t SN9;
|
|
uint32_t SN15;
|
|
int yr; int mon; int day;
|
|
int hr; int min; float sek;
|
|
double lat; double lon; double alt;
|
|
double newlat; double newlon; double newalt;
|
|
double prevlat; double prevlon; double prevalt;
|
|
double dir; double horiV; double vertV;
|
|
float meas24[5];
|
|
float status[2];
|
|
char newsonde;
|
|
int ok;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct M10;
|
|
|
|
|
|
struct M10 {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float bitlev;
|
|
float noise;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxb;
|
|
uint32_t rxp;
|
|
char rxbuf[101];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
};
|
|
|
|
struct M20;
|
|
|
|
|
|
struct M20 {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float bitlev;
|
|
float noise;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxb;
|
|
uint32_t rxp;
|
|
char rxbuf[70];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
};
|
|
|
|
|
|
struct SCID;
|
|
|
|
|
|
struct ATMS;
|
|
struct ATMS {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float bitlev;
|
|
float noise;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxb;
|
|
uint32_t rxp;
|
|
char rxbuf[300];
|
|
char synbuf[100];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
|
|
float noise0;
|
|
float bitlev0;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t synp;
|
|
char frame[100];
|
|
char rev;
|
|
char headok;
|
|
char id[15];
|
|
float freq;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IMS;
|
|
struct IMS {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float bitlev;
|
|
float noise;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxb;
|
|
uint32_t rxp;
|
|
char rxbuf[300];
|
|
char synbuf[100];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
|
|
float noise0;
|
|
float bitlev0;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbitc;
|
|
uint32_t synp;
|
|
char frame[100];
|
|
char rev;
|
|
char headok;
|
|
char id[15];
|
|
float freq;
|
|
|
|
};
|
|
|
|
|
|
struct SCID;
|
|
|
|
|
|
struct SCID {
|
|
CNAMESTR id;
|
|
CNAMESTR idcheck;
|
|
uint32_t idtime;
|
|
uint32_t idcnt;
|
|
};
|
|
|
|
struct C34;
|
|
struct C34 {
|
|
char enabled;
|
|
struct SCID id34;
|
|
struct SCID id50;
|
|
uint32_t idtime;
|
|
uint32_t idcnt;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t leveldcd;
|
|
float sqmed[2];
|
|
float afskhighpass;
|
|
float freq;
|
|
float left;
|
|
float tcnt;
|
|
float afskmidfreq;
|
|
float afmid;
|
|
float noise;
|
|
float bitlev;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char c50;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbytec;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
char rxbuf[9+6];
|
|
AFIRTAB afirtab;
|
|
int32_t asynst[10];
|
|
DFIRTAB dfirtab;
|
|
DFIR dfir;
|
|
uint32_t dfin;
|
|
uint32_t confignyquist;
|
|
uint32_t configafskshift;
|
|
uint32_t configafskmid;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
uint32_t txbaud;
|
|
uint32_t dcdclock;
|
|
float hipasscap;
|
|
uint32_t tused;
|
|
};
|
|
|
|
struct IMET;
|
|
struct IMET {
|
|
char enabled;
|
|
struct SCID imet;
|
|
// struct SCID id50;
|
|
uint32_t idtime;
|
|
uint32_t idcnt;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t leveldcd;
|
|
float sqmed[2];
|
|
float afskhighpass;
|
|
float freq;
|
|
float left;
|
|
float tcnt;
|
|
float afskmidfreq;
|
|
float afmid;
|
|
float noise;
|
|
float bitlev;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
// char c50;
|
|
uint32_t rxbyte;
|
|
uint32_t rxbytec;
|
|
uint32_t rxbitc;
|
|
uint32_t rxp;
|
|
char rxbuf[9+6];
|
|
AFIRTAB afirtab;
|
|
int32_t asynst[10];
|
|
DFIRTAB dfirtab;
|
|
DFIR dfir;
|
|
uint32_t dfin;
|
|
uint32_t confignyquist;
|
|
uint32_t configafskshift;
|
|
uint32_t configafskmid;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
uint32_t txbaud;
|
|
uint32_t dcdclock;
|
|
float hipasscap;
|
|
uint32_t tused;
|
|
|
|
};
|
|
|
|
struct SKPP;
|
|
struct SKPP {
|
|
char enabled;
|
|
int32_t pllshift;
|
|
int32_t baudfine;
|
|
int32_t manchestd;
|
|
float bitlev;
|
|
float noise;
|
|
float lastu;
|
|
char cbit;
|
|
char oldd;
|
|
char plld;
|
|
char lastmanch;
|
|
char txok;
|
|
uint32_t rxb;
|
|
uint32_t rxp;
|
|
char rxbuf[200];
|
|
AFIRTAB afirtab;
|
|
uint32_t synword;
|
|
uint32_t demodbaud;
|
|
uint32_t configbaud;
|
|
};
|
|
|
|
|
|
|
|
|
|
struct CHAN;
|
|
|
|
|
|
struct CHAN {
|
|
int32_t adcmax;
|
|
int32_t adcmin;
|
|
int32_t adcdc;
|
|
float afir[32];
|
|
int32_t configequalizer;
|
|
pUDPTX udptx;
|
|
uint32_t squelch;
|
|
uint32_t mycallc;
|
|
char myssid;
|
|
struct R92 r92;
|
|
struct R41 r41;
|
|
struct DFM6 dfm6;
|
|
struct C34 c34;
|
|
struct PILS pils; //added for pilot sonde SQ2DK
|
|
struct M10 m10;
|
|
struct M20 m20;
|
|
struct IMET imet;
|
|
struct MP3 mp3;
|
|
struct SKPP skpp;
|
|
struct IMS ims;
|
|
struct ATMS atms;
|
|
|
|
char nr;
|
|
char freq[10];
|
|
char pfreq[10];
|
|
unsigned int st;
|
|
|
|
};
|
|
|
|
static int32_t soundfd;
|
|
|
|
static int32_t debfd;
|
|
|
|
static char abortonsounderr;
|
|
|
|
static char verb;
|
|
|
|
static char verb2;
|
|
|
|
static uint32_t dfmidchg;
|
|
|
|
static uint32_t getst;
|
|
|
|
static uint32_t afin;
|
|
static uint32_t afinR41;
|
|
static uint32_t afinPS;
|
|
static uint32_t afinMP3;
|
|
|
|
static uint32_t soundbufs;
|
|
|
|
static uint32_t adcrate;
|
|
|
|
static uint32_t adcbuflen;
|
|
|
|
static uint32_t adcbufrd;
|
|
|
|
static uint32_t adcbufsamps;
|
|
|
|
static uint32_t fragmentsize;
|
|
|
|
static FILENAME soundfn;
|
|
|
|
static struct CHAN chan[64];
|
|
|
|
static uint32_t adcbufsampx;
|
|
|
|
static uint32_t maxchannels;
|
|
|
|
static uint32_t cfgchannels;
|
|
|
|
static short adcbuf[4096];
|
|
|
|
static uint32_t dfmnametyp;
|
|
|
|
static uint16_t CRCTAB[256];
|
|
|
|
|
|
|
|
static void Error(char text[], uint32_t text_len)
|
|
{
|
|
X2C_PCOPY((void **)&text,text_len);
|
|
osi_WrStr(text, text_len);
|
|
osi_WrStrLn(" error abort", 13ul);
|
|
X2C_ABORT();
|
|
X2C_PFREE(text);
|
|
} /* end Error() */
|
|
|
|
|
|
static void Hamming(float f[], uint32_t f_len)
|
|
{
|
|
uint32_t i;
|
|
uint32_t tmp;
|
|
tmp = f_len-1;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
f[i] = f[i]*(0.54f+0.46f*osic_cos(3.1415926535898f*(X2C_DIVR((float)
|
|
i,(float)(1UL+(f_len-1))))));
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
} /* end Hamming() */
|
|
|
|
|
|
static void initdfir(DFIRTAB dfirtab, uint32_t fg)
|
|
{
|
|
uint32_t f;
|
|
uint32_t i;
|
|
float t[512];
|
|
float e;
|
|
float f1;
|
|
uint32_t tmp;
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
t[i] = 0.5f;
|
|
} /* end for */
|
|
f1 = X2C_DIVR((float)(fg*64UL),(float)adcrate);
|
|
tmp = (uint32_t)X2C_TRUNCC(f1,0UL,X2C_max_longcard)+1UL;
|
|
f = 1UL;
|
|
if (f<=tmp) for (;; f++) {
|
|
e = 1.0f;
|
|
if (f==(uint32_t)X2C_TRUNCC(f1,0UL,X2C_max_longcard)+1UL) {
|
|
e = f1-(float)(uint32_t)X2C_TRUNCC(f1,0UL,X2C_max_longcard);
|
|
}
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
t[i] = t[i]+e*osic_cos(X2C_DIVR(3.1415926535898f*(float)(i*f),512.0f));
|
|
} /* end for */
|
|
if (f==tmp) break;
|
|
} /* end for */
|
|
Hamming(t, 512ul);
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
t[i] = t[i]*(0.54f+0.46f*osic_cos(3.1415926535898f*(X2C_DIVR((float)i,512.0f))));
|
|
} /* end for */
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
dfirtab[511UL+i] = t[i];
|
|
dfirtab[511UL-i] = t[i];
|
|
} /* end for */
|
|
} /* end initdfir() */
|
|
|
|
static void initafir(AFIRTAB atab, uint32_t F0, uint32_t F1, float eq)
|
|
{
|
|
uint32_t f;
|
|
uint32_t i;
|
|
float t[256];
|
|
float f10;
|
|
float f00;
|
|
float e;
|
|
uint32_t tmp;
|
|
f00 = X2C_DIVR((float)(F0*32UL),(float)adcrate);
|
|
f10 = X2C_DIVR((float)(F1*32UL),(float)adcrate);
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
t[i] = 0.0f;
|
|
} /* end for */
|
|
tmp = (uint32_t)X2C_TRUNCC(f10,0UL,X2C_max_longcard)+1UL;
|
|
f = (uint32_t)X2C_TRUNCC(f00,0UL,X2C_max_longcard);
|
|
if (f<=tmp) for (;; f++) {
|
|
e = 1.0f+eq*((X2C_DIVR((float)f,X2C_DIVR((float)((F0+F1)*32UL), (float)adcrate)))*2.0f-1.0f);
|
|
/*
|
|
e:=1.0 + eq*(FLOAT(f)/FLOAT((F0+F1)*AFIRLEN DIV adcrate)*2.0-1.0);
|
|
*/
|
|
if (e<0.0f) e = 0.0f;
|
|
if (f==(uint32_t)X2C_TRUNCC(f00,0UL,X2C_max_longcard)) {
|
|
e = e*(1.0f-(f00-(float)(uint32_t)X2C_TRUNCC(f00,0UL,X2C_max_longcard)));
|
|
}
|
|
if (f==(uint32_t)X2C_TRUNCC(f10,0UL,X2C_max_longcard)+1UL) {
|
|
e = e*(f10-(float)(uint32_t)X2C_TRUNCC(f10,0UL, X2C_max_longcard));
|
|
}
|
|
/*
|
|
IF eq<>0 THEN IO.WrFixed(e,2,2);IO.WrLn; END;
|
|
*/
|
|
if (f==0UL) {
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
t[i] = t[i]+e*0.5f;
|
|
} /* end for */
|
|
}
|
|
else {
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
t[i] = t[i]+e*osic_cos(X2C_DIVR(3.1415926535898f*(float)(i*f),
|
|
256.0f));
|
|
} /* end for */
|
|
}
|
|
if (f==tmp) break;
|
|
} /* end for */
|
|
Hamming(t, 256ul);
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
atab[255UL+i] = t[i];
|
|
atab[255UL-i] = t[i];
|
|
} /* end for */
|
|
if (F0>0UL) {
|
|
/* make dc level zero */
|
|
e = 0.0f;
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
e = e+atab[i];
|
|
} /* end for */
|
|
e = X2C_DIVR(e,512.0f);
|
|
for (i = 0UL; i<=511UL; i++) {
|
|
atab[i] = atab[i]-e;
|
|
} /* end for */
|
|
}
|
|
/*
|
|
IO.WrLn;
|
|
FOR i:=0 TO HIGH(atab) DO IO.WrFixed(atab[i], 2,8) END;
|
|
IO.WrLn;
|
|
*/
|
|
/*
|
|
IF eq<>0.0 THEN
|
|
debfd:=FIO.Create("/tmp/ta.raw");
|
|
FOR i:=0 TO HIGH(atab) DO f:=VAL(INTEGER, atab[i]*1000.0);
|
|
FIO.WrBin(debfd,f,2) END;
|
|
FIO.Close(debfd);
|
|
END;
|
|
*/
|
|
} /* end initafir() */
|
|
|
|
|
|
static void OpenSound(void)
|
|
{
|
|
int32_t s;
|
|
int32_t i;
|
|
soundfd = osi_OpenRW(soundfn, 1024ul);
|
|
if (soundfd>=0L) {
|
|
if (maxchannels<2UL) {
|
|
i = samplesize(soundfd, 16UL); /* 8, 16 */
|
|
i = channels(soundfd, maxchannels+1UL); /* 1, 2 */
|
|
i = setfragment(soundfd, fragmentsize); /* 2^bufsize * 65536*bufs*/
|
|
if (i) {
|
|
osi_WrStr("sound setfragment returns ", 27ul);
|
|
osic_WrINT32((uint32_t)i, 1UL);
|
|
osic_WrLn();
|
|
}
|
|
i = sampelrate(soundfd, adcrate); /* 8000..48000 */
|
|
s = (int32_t)getsampelrate(soundfd);
|
|
if (s!=(int32_t)adcrate) {
|
|
osi_WrStr("sound device returns ", 22ul);
|
|
osic_WrINT32((uint32_t)s, 1UL);
|
|
osi_WrStrLn("Hz!", 4ul);
|
|
}
|
|
}
|
|
}
|
|
else if (abortonsounderr) {
|
|
osi_WrStr(soundfn, 1024ul);
|
|
Error(" open", 6ul);
|
|
}
|
|
} /* end OpenSound() */
|
|
|
|
|
|
static char packcall(char cs[], uint32_t cs_len,
|
|
uint32_t * cc, char * ssid)
|
|
{
|
|
uint32_t s;
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char c;
|
|
char packcall_ret;
|
|
X2C_PCOPY((void **)&cs,cs_len);
|
|
cs[cs_len-1] = 0;
|
|
*cc = 0UL;
|
|
s = 0UL;
|
|
i = 0UL;
|
|
for (j = 0UL; j<=5UL; j++) {
|
|
*cc = *cc*37UL;
|
|
c = cs[i];
|
|
if ((uint8_t)c>='A' && (uint8_t)c<='Z') {
|
|
*cc += ((uint32_t)(uint8_t)c-65UL)+1UL;
|
|
++i;
|
|
}
|
|
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
*cc += ((uint32_t)(uint8_t)c-48UL)+27UL;
|
|
++i;
|
|
}
|
|
else if (c && c!='-') {
|
|
packcall_ret = 0;
|
|
goto label;
|
|
}
|
|
} /* end for */
|
|
if (cs[i]=='-') {
|
|
/* ssid */
|
|
++i;
|
|
c = cs[i];
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
s += (uint32_t)(uint8_t)c-48UL;
|
|
++i;
|
|
c = cs[i];
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
s = (s*10UL+(uint32_t)(uint8_t)c)-48UL;
|
|
}
|
|
}
|
|
if (s>15UL) {
|
|
packcall_ret = 0;
|
|
goto label;
|
|
}
|
|
}
|
|
else if (cs[i]) {
|
|
packcall_ret = 0;
|
|
goto label;
|
|
}
|
|
*ssid = (char)s;
|
|
packcall_ret = *cc>0UL;
|
|
label:;
|
|
X2C_PFREE(cs);
|
|
return packcall_ret;
|
|
} /* end packcall() */
|
|
|
|
|
|
static int32_t GetIp(char h[], uint32_t h_len, uint32_t * ip,
|
|
uint32_t * port)
|
|
{
|
|
uint32_t p;
|
|
uint32_t n;
|
|
uint32_t i;
|
|
char ok0;
|
|
int32_t GetIp_ret;
|
|
X2C_PCOPY((void **)&h,h_len);
|
|
p = 0UL;
|
|
h[h_len-1] = 0;
|
|
*ip = 0UL;
|
|
for (i = 0UL; i<=4UL; i++) {
|
|
n = 0UL;
|
|
ok0 = 0;
|
|
while ((uint8_t)h[p]>='0' && (uint8_t)h[p]<='9') {
|
|
ok0 = 1;
|
|
n = (n*10UL+(uint32_t)(uint8_t)h[p])-48UL;
|
|
++p;
|
|
}
|
|
if (!ok0) {
|
|
GetIp_ret = -1L;
|
|
goto label;
|
|
}
|
|
if (i<3UL) {
|
|
if (h[p]!='.' || n>255UL) {
|
|
GetIp_ret = -1L;
|
|
goto label;
|
|
}
|
|
*ip = *ip*256UL+n;
|
|
}
|
|
else if (i==3UL) {
|
|
*ip = *ip*256UL+n;
|
|
if (h[p]!=':' || n>255UL) {
|
|
GetIp_ret = -1L;
|
|
goto label;
|
|
}
|
|
}
|
|
else if (n>65535UL) {
|
|
GetIp_ret = -1L;
|
|
goto label;
|
|
}
|
|
*port = n;
|
|
++p;
|
|
} /* end for */
|
|
GetIp_ret = openudp();
|
|
label:;
|
|
X2C_PFREE(h);
|
|
return GetIp_ret;
|
|
} /* end GetIp() */
|
|
|
|
|
|
static void Config(void)
|
|
{
|
|
uint32_t c;
|
|
uint32_t i;
|
|
struct R92 * anonym;
|
|
struct R41 * anonym0;
|
|
struct DFM6 * anonym1;
|
|
struct C34 * anonym2;
|
|
struct PILS * anonym5;
|
|
struct M10 * anonym6;
|
|
struct M20 * anonym7;
|
|
struct IMET * anonym8;
|
|
struct MP3 * anonym9;
|
|
|
|
struct SKPP * anonym11;
|
|
struct IMS * anonym12;
|
|
struct ATMS * anonym13;
|
|
|
|
for (c = 0UL; c<=63UL; c++) {
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[c].r92;
|
|
anonym->configbaud = 4800UL;
|
|
anonym->demodbaud = (2UL*anonym->configbaud*65536UL)/adcrate;
|
|
initafir(anonym->afirtab, 0UL, 2800UL,X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
//initafir(anonym->afirtab, 0UL, 12600UL,X2C_DIVR((float)chan[c].configequalizer,100.0f)); //12600
|
|
anonym->baudfine = 0L;
|
|
anonym->noise = 0.0f;
|
|
anonym->bitlev = 0.0f;
|
|
anonym->cbit = 0;
|
|
anonym->rxp = 0UL;
|
|
anonym->rxbitc = 0UL;
|
|
anonym->manchestd = 0L;
|
|
anonym->lastmanch = 0;
|
|
anonym->rxbyte = 0UL;
|
|
for (i = 0UL; i<=9UL; i++) {
|
|
anonym->asynst[i] = 0L;
|
|
} /* end for */
|
|
}
|
|
{ /* with */
|
|
struct R41 * anonym0 = &chan[c].r41;
|
|
anonym0->configbaud = 4800UL;
|
|
anonym0->demodbaud = (2UL*anonym0->configbaud*65536UL)/adcrate;
|
|
initafir(anonym0->afirtab, 0UL, 2800UL, X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
anonym0->baudfine = 0L;
|
|
anonym0->noise = 0.0f;
|
|
anonym0->bitlev = 0.0f;
|
|
anonym0->cbit = 0;
|
|
anonym0->rxp = 0UL;
|
|
anonym0->rxbitc = 0UL;
|
|
anonym0->rxbyte = 0UL;
|
|
anonym0->synp = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct MP3 * anonym9 = &chan[c].mp3;
|
|
anonym9->configbaud = 2400UL;
|
|
anonym9->demodbaud = (2UL*anonym9->configbaud*65536UL)/adcrate;
|
|
initafir(anonym9->afirtab, 0UL, 2400UL, X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
anonym9->baudfine = 0L;
|
|
anonym9->noise = 0.0f;
|
|
anonym9->bitlev = 0.0f;
|
|
anonym9->cbit = 0;
|
|
anonym9->rxp = 0UL;
|
|
anonym9->rxbitc = 0UL;
|
|
anonym9->rxbyte = 0UL;
|
|
anonym9->synp = 0UL;
|
|
}
|
|
|
|
{ // with
|
|
struct PILS * anonym5 = &chan[c].pils;
|
|
anonym5->configbaud = 4804UL;
|
|
anonym5->demodbaud = (2UL*anonym5->configbaud*65536UL)/adcrate; //4800
|
|
// initafir(anonym5->afirtab, 0UL, 2200UL, X2C_DIVR((float)(chan[c].configequalizer+120),100.0f)); //V9
|
|
initafir(anonym5->afirtab, 0UL, 2200UL, X2C_DIVR((float)(chan[c].configequalizer+60),100.0f)); //v10
|
|
// initafir(anonym5->afirtab, 0UL, 9600UL, X2C_DIVR((float)(chan[c].configequalizer),100.0f));
|
|
anonym5->baudfine = 0L;
|
|
anonym5->noise = 0.0f;
|
|
anonym5->bitlev = 0.0f;
|
|
anonym5->cbit = 0;
|
|
anonym5->rxp = 0UL;
|
|
anonym5->rxbitc = 0UL;
|
|
anonym5->rxbyte = 0UL;
|
|
anonym5->synp = 0UL;
|
|
anonym5->poklat=-1;
|
|
anonym5->poklon=-1;
|
|
|
|
}
|
|
|
|
|
|
{ /* with */
|
|
struct DFM6 * anonym1 = &chan[c].dfm6;
|
|
anonym1->configbaud = 2500UL;
|
|
anonym1->demodbaud = (2UL*anonym1->configbaud*65536UL)/adcrate;
|
|
initafir(anonym1->afirtab, 0UL, 1900UL, X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
anonym1->baudfine = 0L;
|
|
anonym1->noise = 0.0f;
|
|
anonym1->bitlev = 0.0f;
|
|
anonym1->cbit = 0;
|
|
anonym1->rxp = 264UL; /* out of fram, wait for sync */
|
|
anonym1->manchestd = 0L;
|
|
anonym1->polarity = 0;
|
|
anonym1->numcnt = 0UL;
|
|
anonym1->txok = 0;
|
|
anonym1->newsonde=1;
|
|
}
|
|
|
|
{ /* with */
|
|
struct M10 * anonym6 = &chan[c].m10;
|
|
anonym6->configbaud = 9600UL;
|
|
anonym6->demodbaud = (2UL*anonym6->configbaud*65536UL)/adcrate;
|
|
initafir(anonym6->afirtab, 0UL, 5200UL, X2C_DIVR((float)chan[c].configequalizer,100.0f)); //5200
|
|
anonym6->baudfine = 0L;
|
|
anonym6->noise = 0.0f;
|
|
anonym6->bitlev = 0.0f;
|
|
anonym6->cbit = 0;
|
|
anonym6->rxp = 101UL; /* out of fram, wait for sync */
|
|
anonym6->manchestd = 0L;
|
|
anonym6->txok = 0;
|
|
}
|
|
|
|
{ /* with */
|
|
struct M20 * anonym7 = &chan[c].m20;
|
|
anonym7->configbaud = 9600UL;
|
|
anonym7->demodbaud = (2UL*anonym7->configbaud*65536UL)/adcrate;
|
|
initafir(anonym7->afirtab, 0UL, 6000UL, X2C_DIVR((float)chan[c].configequalizer,100.0f)); //5200
|
|
anonym7->baudfine = 0L;
|
|
anonym7->noise = 0.0f;
|
|
anonym7->bitlev = 0.0f;
|
|
anonym7->cbit = 0;
|
|
anonym7->rxp = 70UL; /* out of fram, wait for sync */
|
|
anonym7->manchestd = 0L;
|
|
anonym7->txok = 0;
|
|
}
|
|
{ /* with */
|
|
struct IMS * anonym12 = &chan[c].ims;
|
|
anonym12->configbaud = 2400UL;
|
|
anonym12->demodbaud = (2UL*anonym12->configbaud*65536UL)/adcrate;
|
|
initafir(anonym12->afirtab, 0UL, 4800UL, X2C_DIVR((float)chan[c].configequalizer,100.0f)); //5200
|
|
anonym12->baudfine = 0L;
|
|
anonym12->noise = 0.0f;
|
|
anonym12->bitlev = 0.0f;
|
|
anonym12->cbit = 0;
|
|
anonym12->rxp = 70UL; /* out of fram, wait for sync */
|
|
anonym12->manchestd = 0L;
|
|
anonym12->txok = 0;
|
|
}
|
|
{ /* with */
|
|
struct ATMS * anonym13 = &chan[c].atms;
|
|
anonym13->configbaud = 2400UL;
|
|
anonym13->demodbaud = (2UL*anonym13->configbaud*65536UL)/adcrate;
|
|
initafir(anonym13->afirtab, 0UL, 5600UL, X2C_DIVR((float)chan[c].configequalizer,100.0f)); //5200
|
|
anonym13->baudfine = 0L;
|
|
anonym13->noise = 0.0f;
|
|
anonym13->bitlev = 0.0f;
|
|
anonym13->cbit = 0;
|
|
anonym13->rxp = 0UL; /* out of fram, wait for sync */
|
|
anonym13->manchestd = 0L;
|
|
anonym13->txok = 0;
|
|
}
|
|
|
|
{ /* with */
|
|
struct C34 * anonym2 = &chan[c].c34;
|
|
anonym2->txbaud = (anonym2->configbaud*65536UL)/adcrate;
|
|
anonym2->demodbaud = anonym2->txbaud*2UL;
|
|
anonym2->afskmidfreq = X2C_DIVR((float)anonym2->configafskmid*2.0f,(float)adcrate);
|
|
initafir(anonym2->afirtab,
|
|
(anonym2->configafskmid-anonym2->configafskshift/2UL)-anonym2->configbaud/4UL, anonym2->configafskmid+anonym2->configafskshift/2UL+anonym2->configbaud/4UL, X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
initdfir(anonym2->dfirtab,(anonym2->configbaud*anonym2->confignyquist)/100UL);
|
|
anonym2->baudfine = 0L;
|
|
anonym2->left = 0.0f;
|
|
anonym2->tcnt = 0.0f;
|
|
anonym2->freq = 0.0f;
|
|
anonym2->dfin = 0UL;
|
|
anonym2->cbit = 0;
|
|
anonym2->rxp = 0UL;
|
|
anonym2->rxbitc = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct IMET * anonym2 = &chan[c].imet;
|
|
anonym2->txbaud = (anonym2->configbaud*65536UL)/adcrate;
|
|
anonym2->demodbaud = anonym2->txbaud*2UL;
|
|
anonym2->afskmidfreq = X2C_DIVR((float)anonym2->configafskmid*2.0f,(float)adcrate);
|
|
initafir(anonym2->afirtab,
|
|
(anonym2->configafskmid-anonym2->configafskshift/2UL)-anonym2->configbaud/4UL, anonym2->configafskmid+anonym2->configafskshift/2UL+anonym2->configbaud/4UL, X2C_DIVR((float)chan[c].configequalizer,100.0f));
|
|
initdfir(anonym2->dfirtab,(anonym2->configbaud*anonym2->confignyquist)/100UL);
|
|
anonym2->baudfine = 0L;
|
|
anonym2->left = 0.0f;
|
|
anonym2->tcnt = 0.0f;
|
|
anonym2->freq = 0.0f;
|
|
anonym2->dfin = 0UL;
|
|
anonym2->cbit = 0;
|
|
anonym2->rxp = 0UL;
|
|
anonym2->rxbitc = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct SKPP * anonym11 = &chan[c].skpp;
|
|
anonym11->configbaud = 9600UL;
|
|
anonym11->demodbaud = (2UL*anonym11->configbaud*65536UL)/adcrate;
|
|
initafir(anonym11->afirtab, 0UL, 5200UL, X2C_DIVR((float)chan[c].configequalizer,100.0f)); //5200
|
|
anonym11->baudfine = 0L;
|
|
anonym11->noise = 0.0f;
|
|
anonym11->bitlev = 0.0f;
|
|
anonym11->cbit = 0;
|
|
anonym11->rxp = 101UL; /* out of fram, wait for sync */
|
|
anonym11->manchestd = 0L;
|
|
anonym11->txok = 0;
|
|
}
|
|
|
|
} /* end for */
|
|
} /* end Config() */
|
|
|
|
|
|
static void Parms(void)
|
|
{
|
|
char err;
|
|
FILENAME mixfn;
|
|
FILENAME h1;
|
|
FILENAME h;
|
|
uint32_t ch;
|
|
uint32_t cnum;
|
|
int32_t inum;
|
|
uint32_t channel;
|
|
pUDPTX utx;
|
|
char chanset;
|
|
char mycall[11];
|
|
uint32_t myc;
|
|
char mys;
|
|
struct R92 * anonym;
|
|
struct R41 * anonym0;
|
|
struct DFM6 * anonym1;
|
|
struct C34 * anonym2;
|
|
struct CHAN * anonym3;
|
|
/* set only 1 chan */
|
|
struct CHAN * anonym4;
|
|
struct PILS * anonym5;
|
|
struct M10 * anonym6;
|
|
struct M20 * anonym7;
|
|
struct IMET * anonym8;
|
|
struct MP3 * anonym9;
|
|
struct SKPP * anonym11;
|
|
struct IMS * anonym12;
|
|
struct ATMS * anonym13;
|
|
err = 0;
|
|
abortonsounderr = 0;
|
|
adcrate = 22050UL;
|
|
adcbuflen = 1024UL;
|
|
fragmentsize = 11UL;
|
|
maxchannels = 0UL;
|
|
cfgchannels = 1UL; /* fix 1 channel */
|
|
debfd = -1L;
|
|
chanset = 0;
|
|
dfmnametyp = 0UL;
|
|
dfmidchg = 2UL; /* minutes no tx if dfm name change */
|
|
for (channel = 0UL; channel<=63UL; channel++) {
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[channel].r92;
|
|
anonym->enabled = 1;
|
|
anonym->pllshift = 1024L;
|
|
}
|
|
{ /* with */
|
|
struct R41 * anonym0 = &chan[channel].r41;
|
|
anonym0->enabled = 1;
|
|
anonym0->pllshift = 1024L;
|
|
}
|
|
{ /* with */
|
|
struct MP3 * anonym0 = &chan[channel].mp3;
|
|
anonym0->enabled = 1;
|
|
anonym0->pllshift = 1024L;
|
|
}
|
|
|
|
{ // with
|
|
struct PILS * anonym5 = &chan[channel].pils;
|
|
anonym5->enabled = 1;
|
|
anonym5->pllshift = 1024L;
|
|
}
|
|
{ /* with */
|
|
struct DFM6 * anonym1 = &chan[channel].dfm6;
|
|
anonym1->enabled = 1;
|
|
anonym1->pllshift = 1024L;
|
|
anonym1->idcnt0 = 0UL;
|
|
anonym1->idcnt1 = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct C34 * anonym2 = &chan[channel].c34;
|
|
anonym2->enabled = 1;
|
|
anonym2->pllshift = 4096L;
|
|
anonym2->confignyquist = 65UL;
|
|
anonym2->afskhighpass = 0.0f;
|
|
anonym2->configbaud = 2400UL;
|
|
anonym2->configafskshift = 1800UL;
|
|
anonym2->configafskmid = 3800UL;
|
|
anonym2->id34.id[0] = 0;
|
|
anonym2->id34.idcheck[0] = 0;
|
|
anonym2->id34.idtime = 0UL;
|
|
anonym2->id34.idcnt = 0UL;
|
|
anonym2->id50.id[0] = 0;
|
|
anonym2->id50.idcheck[0] = 0;
|
|
anonym2->id50.idtime = 0UL;
|
|
anonym2->id50.idcnt = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct IMET * anonym8 = &chan[channel].imet;
|
|
anonym8->enabled = 1;
|
|
anonym8->pllshift = 4096L;
|
|
anonym8->confignyquist = 65UL;
|
|
anonym8->afskhighpass = 0.0f;
|
|
anonym8->configbaud = 2400UL;
|
|
anonym8->configafskshift = 1800UL;
|
|
anonym8->configafskmid = 3800UL;
|
|
anonym8->imet.id[0] = 0;
|
|
anonym8->imet.idcheck[0] = 0;
|
|
anonym8->imet.idtime = 0UL;
|
|
anonym8->imet.idcnt = 0UL;
|
|
anonym8->imet.id[0] = 0;
|
|
anonym8->imet.idcheck[0] = 0;
|
|
anonym8->imet.idtime = 0UL;
|
|
anonym8->imet.idcnt = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct M10 * anonym6 = &chan[channel].m10;
|
|
anonym6->enabled = 1;
|
|
anonym6->pllshift = 4096L;
|
|
}
|
|
{ /* with */
|
|
struct M20 * anonym7 = &chan[channel].m20;
|
|
anonym7->enabled = 1;
|
|
anonym7->pllshift = 4096L;
|
|
}
|
|
{ /* with */
|
|
struct IMS * anonym12 = &chan[channel].ims;
|
|
anonym12->enabled = 1;
|
|
anonym12->pllshift = 4096L;
|
|
}
|
|
{ /* with */
|
|
struct ATMS * anonym13 = &chan[channel].atms;
|
|
anonym13->enabled = 1;
|
|
anonym13->pllshift = 4096L;
|
|
}
|
|
|
|
{ /* with */
|
|
struct CHAN * anonym3 = &chan[channel];
|
|
anonym3->configequalizer = 0L;
|
|
anonym3->udptx = 0;
|
|
anonym3->mycallc = 0UL;
|
|
}
|
|
{ /* with */
|
|
struct SKPP * anonym11 = &chan[channel].skpp;
|
|
anonym11->enabled = 1;
|
|
anonym11->pllshift = 4096L;
|
|
}
|
|
|
|
} /* end for */
|
|
channel = 0UL;
|
|
X2C_COPY("/dev/dsp",9ul,soundfn,1024u);
|
|
X2C_COPY("/dev/mixer",11ul,mixfn,1024u);
|
|
for (;;) {
|
|
osi_NextArg(h, 1024ul);
|
|
if (h[0U]==0) break;
|
|
if ((h[0U]=='-' && h[1U]) && h[2U]==0) {
|
|
if (h[1U]=='a') abortonsounderr = 1;
|
|
else if (h[1U]=='3') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].c34.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].c34.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='9') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].r92.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].r92.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='4') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].r41.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].r41.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='6') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].dfm6.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].dfm6.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='1') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].m10.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].m10.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='2') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].m20.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].m20.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
|
|
else if (h[1U]=='5') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].imet.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].imet.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
|
|
//---------------pilot sonde
|
|
else if (h[1U]=='8') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].pils.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].pils.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
|
|
//---------------pilot sonde^
|
|
|
|
else if (h[1U]=='A') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].mp3.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].mp3.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='B') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].ims.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].ims.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='E') {
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
chan[channel].ims.enabled = 0;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].atms.enabled = 0;
|
|
} /* end for */
|
|
}
|
|
}
|
|
|
|
|
|
else if (h[1U]=='N') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &dfmnametyp)) err = 1;
|
|
dfmnametyp += 512UL;
|
|
}
|
|
else if (h[1U]=='n') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &dfmnametyp)) err = 1;
|
|
dfmnametyp += 256UL;
|
|
}
|
|
else if (h[1U]=='c') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &cnum)) err = 1;
|
|
if (cnum>=63UL) Error("maxchannels 0..max", 19ul);
|
|
cfgchannels = cnum;
|
|
if (cfgchannels>0UL) maxchannels = cfgchannels-1UL;
|
|
}
|
|
else if (h[1U]=='C') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &cnum)) err = 1;
|
|
if (cnum>1UL) Error("channel 0 to max", 17ul);
|
|
channel = cnum;
|
|
chanset = 1;
|
|
}
|
|
else if (h[1U]=='D') {
|
|
osi_NextArg(h1, 1024ul);
|
|
debfd = osi_OpenWrite(h1, 1024ul);
|
|
}
|
|
else if (h[1U]=='e') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToInt(h, 1024ul, &inum)) err = 1;
|
|
if (labs(inum)>999L) Error("equalizer -999..999", 20ul);
|
|
chan[channel].configequalizer = inum;
|
|
}
|
|
else if (h[1U]=='f') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &cnum)) err = 1;
|
|
if (cnum<8000UL || cnum>96000UL) {
|
|
Error("sampelrate 8000..96000", 23ul);
|
|
}
|
|
adcrate = cnum;
|
|
}
|
|
else if (h[1U]=='F') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &cnum)) err = 1;
|
|
chan[channel].c34.configafskmid = cnum;
|
|
}
|
|
else if (h[1U]=='G') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &dfmidchg)) err = 1;
|
|
}
|
|
else if (h[1U]=='l') {
|
|
osi_NextArg(h, 1024ul);
|
|
if (!aprsstr_StrToCard(h, 1024ul, &cnum)) err = 1;
|
|
if (cnum>=16UL && cnum<=4096UL) adcbuflen = cnum;
|
|
else Error("sound buffer out of range", 26ul);
|
|
}
|
|
else if (h[1U]=='o') osi_NextArg(soundfn, 1024ul);
|
|
else if (h[1U]=='I') {
|
|
osi_NextArg(mycall, 11ul);
|
|
if (!packcall(mycall, 11ul, &myc, &mys)) {
|
|
Error("-I illegall Callsign + ssid", 28ul);
|
|
}
|
|
if (chanset) {
|
|
{ /* with */
|
|
struct CHAN * anonym4 = &chan[channel];
|
|
anonym4->mycallc = myc;
|
|
anonym4->myssid = mys;
|
|
}
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
chan[ch].mycallc = myc;
|
|
chan[ch].myssid = mys;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='u') {
|
|
osi_NextArg(h, 1024ul);
|
|
osic_alloc((char * *) &utx, sizeof(struct UDPTX));
|
|
if (utx==0) Error("udp socket out of memory", 25ul);
|
|
utx->udpfd = GetIp(h, 1024ul, &utx->ip, &utx->destport);
|
|
if (utx->udpfd<0L) Error("cannot open udp socket", 23ul);
|
|
if (chanset) {
|
|
/* set only 1 chan */
|
|
utx->next = chan[channel].udptx;
|
|
chan[channel].udptx = utx;
|
|
}
|
|
else {
|
|
/* use before -C set both */
|
|
for (ch = 0UL; ch<=63UL; ch++) {
|
|
utx->next = chan[ch].udptx;
|
|
chan[ch].udptx = utx;
|
|
} /* end for */
|
|
}
|
|
}
|
|
else if (h[1U]=='v') verb = 1;
|
|
else if (h[1U]=='V') {
|
|
verb = 1;
|
|
verb2 = 1;
|
|
}
|
|
else {
|
|
if (h[1U]=='h') {
|
|
osi_WrStrLn("oss Mono/Stereo up to 64 Channel RS92, RS41, C34, C50 Sonde Demodulator to raw Frames", 86ul);
|
|
osi_WrStrLn("sent via UDP to \'sondemod\' decoder, more demodulators may send to same decoder", 79ul);
|
|
osi_WrStrLn("Stereo used for 2 Rx for 2 Sondes or 1 Sonde with Antenna-Diversity", 68ul);
|
|
osi_WrStrLn(" -1 disable M10 decoding (use -C before to select 1 channel)", 73ul);
|
|
osi_WrStrLn(" -2 disable M20 decoding (use -C before to select 1 channel)", 73ul);
|
|
osi_WrStrLn(" -3 disable SRSC34/50 decoding (use -C before to select 1 channel)", 79ul);
|
|
osi_WrStrLn(" -4 disable RS41 decoding (use -C before to select 1 channel)", 74ul);
|
|
osi_WrStrLn(" -5 disable IMET decoding (use -C before to select 1 channel)", 74ul);
|
|
osi_WrStrLn(" -6 disable DFM06 decoding (use -C before to select 1 channel)", 75ul);
|
|
osi_WrStrLn(" -8 disable PILOTSONDE decoding (use -C before to select 1 channel)", 74ul);
|
|
osi_WrStrLn(" -9 disable RS92 decoding (use -C before to select 1 channel)", 74ul);
|
|
osi_WrStrLn(" -A disable MP3 decoding (use -C before to select 1 channel)", 73ul);
|
|
osi_WrStrLn(" -B disable IMS decoding (use -C before to select 1 channel)", 73ul);
|
|
osi_WrStrLn(" -E disable ATMS decoding (use -C before to select 1 channel)", 73ul);
|
|
osi_WrStrLn(" -a abort on sounddevice error else retry to open (USB audio...)", 77ul);
|
|
osi_WrStrLn(" -c <num> maxchannels, 0 for automatic channel number recognition", 72ul);
|
|
osi_WrStrLn(" -C <num> channel parameters follow (repeat for each channel)", 68ul);
|
|
osi_WrStrLn(" -D <filename> write raw soundcard input data to file or pipe", 63ul);
|
|
osi_WrStrLn(" for debug or chaining demodulators (equalizer diversity)", 73ul);
|
|
osi_WrStrLn(" -e <num> demod equalizer (0) 100=6db/oct highpass (-999..999)", 69ul);
|
|
osi_WrStrLn(" -C <n> before -e sets channel number", 53ul);
|
|
osi_WrStrLn(" -f <num> adcrate (22050) (8000..96000)", 46ul);
|
|
osi_WrStrLn(" -G <minutes> no tx if DFMxx Name changes (2)", 48ul);
|
|
osi_WrStrLn(" -h help", 21ul);
|
|
osi_WrStrLn(" -I <call> mycall + ssid (use -C before to select 1 channel)", 66ul);
|
|
osi_WrStrLn(" -l <num> adcbuflen (256)", 32ul);
|
|
osi_WrStrLn(" -N <num> 0..255 generate DFM-ID from serial no. in first frame (see -v)", 79ul);
|
|
osi_WrStrLn(" enter first byte in decimal \"AC00070\" -N 172", 61ul);
|
|
osi_WrStrLn(" -n <num> same as -N but try old methode too", 51ul);
|
|
osi_WrStrLn(" -o <filename> oss devicename (/dev/dsp) or raw/wav audio file or pipe /dev/stdin", 83ul);
|
|
osi_WrStrLn(" -u <x.x.x.x:destport> send rx data in udp (to sondemod), -C <n> before sets", 77ul);
|
|
osi_WrStrLn(" channel number, maybe repeated for more destinations", 69ul);
|
|
osi_WrStrLn(" -V very verbous, with some hex dumps", 50ul);
|
|
osi_WrStrLn(" -v verbous, (CRC-checked Sondename)", 49ul);
|
|
osi_WrStrLn("example: sondeudp -f 16000 -o /dev/dsp -c 2 -C 0 -e 50 -u 127.0.0.1:4000", 73ul);
|
|
X2C_ABORT();
|
|
}
|
|
err = 1;
|
|
}
|
|
}
|
|
else err = 1;
|
|
if (err) break;
|
|
}
|
|
if (err) {
|
|
osi_WrStr(">", 2ul);
|
|
osi_WrStr(h, 1024ul);
|
|
osi_WrStrLn("< use -h", 9ul);
|
|
X2C_ABORT();
|
|
}
|
|
if (adcbuflen*(maxchannels+1UL)>4096UL) {
|
|
adcbuflen = 4096UL/(maxchannels+1UL);
|
|
}
|
|
Config();
|
|
OpenSound();
|
|
} /* end Parms() */
|
|
|
|
|
|
static void sendudp(char data[], uint32_t data_len, int32_t len,
|
|
uint32_t ip, uint32_t destport, int32_t udpfd)
|
|
{
|
|
int32_t i;
|
|
X2C_PCOPY((void **)&data,data_len);
|
|
i = udpsend(udpfd, data, len, destport, ip);
|
|
X2C_PFREE(data);
|
|
} /* end sendudp() */
|
|
|
|
|
|
static void WrdB(int32_t volt)
|
|
{
|
|
if (volt>0L) {
|
|
osic_WrFixed(osic_ln((float)volt)*8.685889638f-96.4f, 1L, 6UL);
|
|
osi_WrStr("dB", 3ul);
|
|
}
|
|
} /* end WrdB() */
|
|
|
|
|
|
static void WrQ(float lev, float noise)
|
|
{
|
|
if (lev>0.0f) {
|
|
noise = X2C_DIVR(noise*200.0f,lev);
|
|
if (noise>100.0f) noise = 100.0f;
|
|
else if (noise<=0.0f) noise = 0.0f;
|
|
osic_WrINT32((uint32_t)(100L-(int32_t)X2C_TRUNCI(noise,
|
|
X2C_min_longint,X2C_max_longint)), 3UL);
|
|
osi_WrStr("%", 2ul);
|
|
}
|
|
} /* end WrQ() */
|
|
|
|
|
|
static void WrQuali(float q)
|
|
{
|
|
if (q>0.0f) {
|
|
q = 100.5f-q*200.0f;
|
|
if (q<0.0f) q = 0.0f;
|
|
osi_WrStr(" q:", 4ul);
|
|
osic_WrINT32((uint32_t)osi_realint(q), 2UL);
|
|
}
|
|
} /* end WrQuali() */
|
|
|
|
|
|
static void Wrtune(int32_t volt, int32_t max0)
|
|
{
|
|
int32_t u;
|
|
if (max0>0L && max0>labs(volt)) {
|
|
u = (volt*100L)/max0;
|
|
if (labs(u)>0L) {
|
|
osi_WrStr(" f:", 4ul);
|
|
osic_WrINT32((uint32_t)u, 2UL);
|
|
}
|
|
else osi_WrStr(" ", 6ul);
|
|
}
|
|
} /* end Wrtune() */
|
|
|
|
|
|
static float noiselevel1(float bitlev, float noise)
|
|
/* 0.0 perfect, ~0.25 noise only*/
|
|
{
|
|
if (bitlev==0.0f) return 0.0f;
|
|
else return X2C_DIVR(noise,bitlev);
|
|
return 0;
|
|
} /* end noiselevel() */
|
|
|
|
|
|
|
|
static float noiselevel(uint32_t channel)
|
|
/* 0.0 perfect, ~0.25 noise only*/
|
|
{
|
|
struct C34 * anonym;
|
|
{ /* with */
|
|
struct C34 * anonym = &chan[channel].c34;
|
|
if (anonym->sqmed[1]==anonym->sqmed[0]) return 0.0f;
|
|
else {
|
|
return X2C_DIVR(anonym->noise,(float)fabs(anonym->sqmed[1]-anonym->sqmed[0]));
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end noiselevel() */
|
|
|
|
static float noiselevelIMET(uint32_t channel)
|
|
/* 0.0 perfect, ~0.25 noise only*/
|
|
{
|
|
struct IMET * anonym;
|
|
{ /* with */
|
|
struct IMET * anonym = &chan[channel].imet;
|
|
if (anonym->sqmed[1]==anonym->sqmed[0]) return 0.0f;
|
|
else {
|
|
return X2C_DIVR(anonym->noise,(float)fabs(anonym->sqmed[1]-anonym->sqmed[0]));
|
|
}
|
|
}
|
|
return 0;
|
|
} /* end noiselevel() */
|
|
|
|
|
|
// Fir(afin,
|
|
// (uint32_t)((anonym->baudfine&65535L)/4096L),
|
|
// 16UL,
|
|
// chan[m].afir,
|
|
// 32ul,
|
|
// anonym->afirtab,
|
|
// 512ul);
|
|
static float Fir(uint32_t in, uint32_t sub, uint32_t step, float fir[], uint32_t fir_len, float firtab[], uint32_t firtab_len)
|
|
{
|
|
float s;
|
|
uint32_t i;
|
|
s = 0.0f;
|
|
i = sub;
|
|
uint32_t dfl=fir_len-1;
|
|
uint32_t dftl=firtab_len-1;
|
|
|
|
do {
|
|
s = s+fir[in]*firtab[i];
|
|
++in;
|
|
if (in>dfl) in = 0UL;
|
|
i += step;
|
|
} while (i<=dftl);
|
|
return s;
|
|
} /* end Fir() */
|
|
|
|
|
|
|
|
static void alludp(pUDPTX utx, uint32_t len, char buf[], uint32_t buf_len)
|
|
{
|
|
X2C_PCOPY((void **)&buf,buf_len);
|
|
while (utx) {
|
|
if (utx->udpfd>=0L) {
|
|
sendudp(buf, buf_len, (int32_t)len, utx->ip, utx->destport,
|
|
utx->udpfd);
|
|
}
|
|
utx = utx->next;
|
|
}
|
|
X2C_PFREE(buf);
|
|
} /* end alludp() */
|
|
|
|
|
|
static int32_t reedsolomon92(char buf[], uint32_t buf_len)
|
|
{
|
|
uint32_t i;
|
|
int32_t res;
|
|
char b[256];
|
|
uint32_t eraspos[24];
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
b[i] = 0;
|
|
} /* end for */
|
|
for (i = 0UL; i<=209UL; i++) {
|
|
b[230UL-i] = buf[i+6UL];
|
|
} /* end for */
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
b[254UL-i] = buf[i+216UL];
|
|
} /* end for */
|
|
res = decodersc(b, eraspos, 0L);
|
|
if (res>0L && res<=12L) {
|
|
for (i = 0UL; i<=209UL; i++) {
|
|
buf[i+6UL] = b[230UL-i];
|
|
} /* end for */
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
buf[i+216UL] = b[254UL-i];
|
|
} /* end for */
|
|
}
|
|
return res;
|
|
} /* end reedsolomon92() */
|
|
|
|
|
|
static char crcrs(const char frame[], uint32_t frame_len,
|
|
int32_t from, int32_t to)
|
|
{
|
|
uint16_t crc;
|
|
int32_t i;
|
|
int32_t tmp;
|
|
crc = 0xFFFFU;
|
|
tmp = to-3L;
|
|
i = from;
|
|
if (i<=tmp) for (;; i++) {
|
|
crc = X2C_LSH(crc,16,-8)^CRCTAB[(uint32_t)((crc^(uint16_t)(uint8_t)frame[i])&0xFFU)];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
return frame[to-1L]==(char)crc && frame[to-2L]==(char)X2C_LSH(crc,
|
|
16,-8);
|
|
} /* end crcrs() */
|
|
|
|
static uint16_t sondeudp_POLYNOM = 0x1021U;
|
|
|
|
void printCnDT(uint32_t m){
|
|
|
|
int hours, minutes, seconds, day, month, year;
|
|
time_t now;
|
|
time(&now);
|
|
struct tm *local = localtime(&now);
|
|
|
|
printf("%02i: (%04d-%02d-%02d %02d:%02d:%02d):",m+1,local->tm_year + 1900,local->tm_mon + 1,local->tm_mday,local->tm_hour, local->tm_min, local->tm_sec);
|
|
}
|
|
|
|
|
|
static void decodeframe92(uint32_t m)
|
|
{
|
|
uint32_t len;
|
|
uint32_t p;
|
|
uint32_t j;
|
|
int32_t corr;
|
|
struct CHAN * anonym;
|
|
corr = reedsolomon92(chan[m].r92.rxbuf, 256ul);
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].r92.rxbuf[0U] = (char)(anonym->mycallc>>24);
|
|
chan[m].r92.rxbuf[1U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].r92.rxbuf[2U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].r92.rxbuf[3U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].r92.rxbuf[4U] = anonym->myssid;
|
|
}
|
|
alludp(anonym->udptx, 240UL, chan[m].r92.rxbuf, 256ul);
|
|
}
|
|
if (verb) {
|
|
|
|
|
|
|
|
p = 6UL;
|
|
if (chan[m].r92.rxbuf[6U]=='e') {
|
|
++p;
|
|
len = (uint32_t)(uint8_t)chan[m].r92.rxbuf[7U]*2UL+2UL;
|
|
/* +crc */
|
|
++p;
|
|
if (maxchannels>0UL) {
|
|
printCnDT(m);
|
|
}
|
|
osi_WrStr("R92 ", 5ul);
|
|
if (8UL+len>240UL || !crcrs(chan[m].r92.rxbuf, 256ul, 8L,
|
|
(int32_t)(8UL+len))) osi_WrStr("---- crc err ", 15ul);
|
|
else {
|
|
j = 4UL;
|
|
while ((uint8_t)chan[m].r92.rxbuf[8UL+j]>=' ') {
|
|
osi_WrStr((char *) &chan[m].r92.rxbuf[8UL+j], 1u/1u);
|
|
++j;
|
|
}
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrINT32((uint32_t)(uint8_t)
|
|
chan[m].r92.rxbuf[8U]+(uint32_t)(uint8_t)
|
|
chan[m].r92.rxbuf[9U]*256UL, 4UL);
|
|
}
|
|
/* IF m>0 THEN WrStr(" ") END; */
|
|
WrdB(chan[m].adcmax);
|
|
WrQ(chan[m].r92.bitlev, chan[m].r92.noise);
|
|
if (corr<0L) osi_WrStr(" -R", 4ul);
|
|
else if (corr>0L && corr<=12L) {
|
|
osi_WrStr(" +", 3ul);
|
|
osic_WrINT32((uint32_t)corr, 1UL);
|
|
osi_WrStr("R", 2ul);
|
|
}
|
|
Wrtune(chan[m].adcdc, chan[m].adcmax);
|
|
osi_WrStrLn("", 1ul);
|
|
}
|
|
}
|
|
} /* end decodeframe92() */
|
|
|
|
|
|
static double latlong(uint32_t val, char c50)
|
|
{
|
|
double hf;
|
|
double hr;
|
|
hr = (double)(val%0x080000000UL);
|
|
if (c50) hr = X2C_DIVL(hr,1.E+7);
|
|
else hr = X2C_DIVL(hr,1.E+6);
|
|
hf = (double)(uint32_t)X2C_TRUNCC(hr,0UL,X2C_max_longcard);
|
|
hr = hf+X2C_DIVL(hr-hf,0.6);
|
|
if (val>=0x080000000UL) hr = -hr;
|
|
return hr;
|
|
} /* end latlong() */
|
|
|
|
|
|
static char hex(uint32_t n)
|
|
{
|
|
n = n&15UL;
|
|
if (n<10UL) return (char)(n+48UL);
|
|
else return (char)(n+55UL);
|
|
return 0;
|
|
} /* end hex() */
|
|
|
|
/*------------------------------ RS41 */
|
|
|
|
static void sendrs41(uint32_t m)
|
|
{
|
|
struct CHAN * anonym;
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].r41.rxbuf[0U] = (char)(anonym->mycallc>>24);
|
|
chan[m].r41.rxbuf[1U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].r41.rxbuf[2U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].r41.rxbuf[3U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].r41.rxbuf[4U] = anonym->myssid;
|
|
chan[m].r41.rxbuf[5U] = 0;
|
|
chan[m].r41.rxbuf[6U] = 0;
|
|
}
|
|
alludp(anonym->udptx, 520UL, chan[m].r41.rxbuf, 520ul);
|
|
}
|
|
} /* end sendrs41() */
|
|
|
|
|
|
static double atang2(double x, double y)
|
|
{
|
|
double w;
|
|
if (fabs(x)>fabs(y)) {
|
|
w = (double)osic_arctan((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-osic_arctan((float)(X2C_DIVL(x,
|
|
y))));
|
|
if (y<0.0) w = w-3.1415926535898;
|
|
}
|
|
else w = 0.0;
|
|
return w;
|
|
} /* end atang2() */
|
|
|
|
#define sondeudp_EARTHA 6.378137E+6
|
|
|
|
#define sondeudp_EARTHB 6.3567523142452E+6
|
|
|
|
#define sondeudp_E2 6.6943799901413E-3
|
|
|
|
#define sondeudp_EARTHAB 4.2841311513312E+4
|
|
|
|
|
|
static void wgs84r(double x, double y, double z,
|
|
double * lat, double * long0,
|
|
double * heig)
|
|
{
|
|
double sl;
|
|
double ct;
|
|
double st;
|
|
double t;
|
|
double rh;
|
|
double xh;
|
|
double h;
|
|
h = x*x+y*y;
|
|
if (h>0.0) {
|
|
rh = (double)osic_sqrt((float)h);
|
|
xh = x+rh;
|
|
*long0 = atang2(xh, y)*2.0;
|
|
if (*long0>3.1415926535898) *long0 = *long0-6.2831853071796;
|
|
t = (double)osic_arctan((float)(X2C_DIVL(z*1.003364089821,
|
|
rh)));
|
|
st = (double)osic_sin((float)t);
|
|
ct = (double)osic_cos((float)t);
|
|
*lat = (double)osic_arctan((float)
|
|
(X2C_DIVL(z+4.2841311513312E+4*st*st*st,
|
|
rh-4.269767270718E+4*ct*ct*ct)));
|
|
sl = (double)osic_sin((float)*lat);
|
|
*heig = X2C_DIVL(rh,(double)osic_cos((float)*lat))-(double)(X2C_DIVR(6.378137E+6f,
|
|
osic_sqrt((float)(1.0-6.6943799901413E-3*sl*sl))));
|
|
}
|
|
else {
|
|
*lat = 0.0;
|
|
*long0 = 0.0;
|
|
*heig = 0.0;
|
|
}
|
|
/* lat:=atan(z/(rh*(1.0 - E2))); */
|
|
/* heig:=sqrt(h + z*z) - EARTHA; */
|
|
} /* end wgs84r() */
|
|
|
|
|
|
static int32_t getint32(const char frame[], uint32_t frame_len,
|
|
uint32_t p)
|
|
{
|
|
uint32_t n;
|
|
uint32_t i;
|
|
n = 0UL;
|
|
for (i = 3UL;; i--) {
|
|
n = n*256UL+(uint32_t)(uint8_t)frame[p+i];
|
|
if (i==0UL) break;
|
|
} /* end for */
|
|
return (int32_t)n;
|
|
} /* end getint32() */
|
|
|
|
|
|
static uint32_t getcard16(const char frame[], uint32_t frame_len,
|
|
uint32_t p)
|
|
{
|
|
return (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
|
frame[p+1UL];
|
|
} /* end getcard16() */
|
|
|
|
|
|
static int32_t getint16(const char frame[], uint32_t frame_len,
|
|
uint32_t p)
|
|
{
|
|
uint32_t n;
|
|
n = (uint32_t)(uint8_t)frame[p]+256UL*(uint32_t)(uint8_t)
|
|
frame[p+1UL];
|
|
if (n>=32768UL) return (int32_t)(n-65536UL);
|
|
return (int32_t)n;
|
|
} /* end getint16() */
|
|
|
|
|
|
/*---------------------- M10 */
|
|
|
|
static uint16_t crcm10(int32_t len, const char buf[], uint32_t buf_len)
|
|
{
|
|
int32_t i;
|
|
uint16_t s;
|
|
uint16_t t;
|
|
uint16_t b;
|
|
uint16_t cs;
|
|
int32_t tmp;
|
|
cs = 0U;
|
|
tmp = len-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
b = (uint16_t)(uint32_t)(uint8_t)buf[i];
|
|
b = X2C_LSH(b,16,-1)|X2C_LSH(b&0x1U,16,7);
|
|
b = b^X2C_LSH(b,16,-2)&0xFFU;
|
|
t = cs&0x3FU|X2C_LSH((cs^X2C_LSH(cs,16,-2)^X2C_LSH(cs,16,-4))&0x1U,16,
|
|
6)|X2C_LSH((X2C_LSH(cs,16,-1)^X2C_LSH(cs,16,-3)^X2C_LSH(cs,
|
|
16,-5))&0x1U,16,7);
|
|
s = X2C_LSH(cs,16,-7)&0xFFU;
|
|
s = (s^X2C_LSH(s,16,-2))&0xFFU;
|
|
cs = X2C_LSH(cs&0xFFU,16,8)|b^t^s;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
return (uint16_t)cs;
|
|
} /* end crcm10() */
|
|
|
|
|
|
static uint32_t m10card(const char b[], uint32_t b_len, int32_t pos, int32_t len)
|
|
{
|
|
int32_t i;
|
|
uint32_t n;
|
|
int32_t tmp;
|
|
n = 0UL;
|
|
tmp = len-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
n = n*256UL+(uint32_t)(uint8_t)b[pos+i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
return n;
|
|
} /* end m10card() */
|
|
|
|
typedef uint32_t SET256[8];
|
|
|
|
static float sondeudp_DEGMUL = 8.3819036711397E-8f;
|
|
|
|
#define sondeudp_VMUL 0.005
|
|
|
|
static SET256 sondeudp_HSET = {0x03FFFFF0UL,0x00000003UL,0x00000000UL,
|
|
0x00000018UL,0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL}; /* not hexlist known bytes */
|
|
|
|
static SET256 _cnst1 = {0x03FFFFF0UL,0x00000003UL,0x00000000UL,0x00000018UL,
|
|
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL};
|
|
|
|
static void WrChan(int32_t c)
|
|
{
|
|
if (maxchannels>0UL) {
|
|
printf("%02i:",c+1);
|
|
}
|
|
} /* end WrChan() */
|
|
|
|
|
|
|
|
// Temperatur Sensor
|
|
// NTC-Thermistor Shibaura PB5-41E
|
|
//
|
|
float M10get_Temp(uint32_t m) {
|
|
// NTC-Thermistor Shibaura PB5-41E
|
|
// T00 = 273.15 + 0.0 , R00 = 15e3
|
|
// T25 = 273.15 + 25.0 , R25 = 5.369e3
|
|
// B00 = 3450.0 Kelvin // 0C..100C, poor fit low temps
|
|
// [ T/C , R/1e3 ] ( [P__-43]/2.0 ):
|
|
// [ -50.0 , 204.0 ]
|
|
// [ -45.0 , 150.7 ]
|
|
// [ -40.0 , 112.6 ]
|
|
// [ -35.0 , 84.90 ]
|
|
// [ -30.0 , 64.65 ]
|
|
// [ -25.0 , 49.66 ]
|
|
// [ -20.0 , 38.48 ]
|
|
// [ -15.0 , 30.06 ]
|
|
// [ -10.0 , 23.67 ]
|
|
// [ -5.0 , 18.78 ]
|
|
// [ 0.0 , 15.00 ]
|
|
// [ 5.0 , 12.06 ]
|
|
// [ 10.0 , 9.765 ]
|
|
// [ 15.0 , 7.955 ]
|
|
// [ 20.0 , 6.515 ]
|
|
// [ 25.0 , 5.370 ]
|
|
// [ 30.0 , 4.448 ]
|
|
// [ 35.0 , 3.704 ]
|
|
// [ 40.0 , 3.100 ]
|
|
// -> Steinhart–Hart coefficients (polyfit):
|
|
float p0 = 1.07303516e-03,
|
|
p1 = 2.41296733e-04,
|
|
p2 = 2.26744154e-06,
|
|
p3 = 6.52855181e-08;
|
|
// T/K = 1/( p0 + p1*ln(R) + p2*ln(R)^2 + p3*ln(R)^3 )
|
|
|
|
// range/scale 0, 1, 2: // M10-pcb
|
|
float Rs[3] = { 12.1e3 , 36.5e3 , 475.0e3 }; // bias/series
|
|
float Rp[3] = { 1e20 , 330.0e3 , 3000.0e3 }; // parallel, Rp[0]=inf
|
|
|
|
uint8_t scT; // {0,1,2}, range/scale voltage divider
|
|
uint16_t ADC_RT; // ADC12 P6.7(A7) , adr_0377h,adr_0376h
|
|
uint16_t Tcal[2]; // adr_1000h[scT*4]
|
|
|
|
float adc_max = 4095.0; // ADC12
|
|
float x, R;
|
|
float T = 0; // T/Kelvin
|
|
|
|
struct M10 * anonym = &chan[m].m10;
|
|
|
|
scT = (unsigned char)anonym->rxbuf[0x3E]; // adr_0455h
|
|
ADC_RT = ((unsigned char)anonym->rxbuf[0x40] << 8) | (unsigned char)anonym->rxbuf[0x3F];
|
|
ADC_RT -= 0xA000;
|
|
Tcal[0] = ((unsigned char)anonym->rxbuf[0x42] << 8) | (unsigned char)anonym->rxbuf[0x41];
|
|
Tcal[1] = ((unsigned char)anonym->rxbuf[0x44] << 8) | (unsigned char)anonym->rxbuf[0x43];
|
|
|
|
x = (adc_max-ADC_RT)/ADC_RT; // (Vcc-Vout)/Vout
|
|
if (scT < 3) R = Rs[scT] /( x - Rs[scT]/Rp[scT] );
|
|
else R = -1;
|
|
|
|
if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
|
/*
|
|
// if (option_verbose >= 3 && csO) { // on-chip temperature
|
|
uint16_t ADC_Ti_raw = (anonym->rxbuf[0x49] << 8) | anonym->rxbuf[0x48]; // int.temp.diode, ref: 4095->1.5V
|
|
float vti, ti;
|
|
// INCH1A (temp.diode), slau144
|
|
vti = ADC_Ti_raw/4095.0 * 1.5; // V_REF+ = 1.5V, no calibration
|
|
ti = (vti-0.986)/0.00355; // 0.986/0.00355=277.75, 1.5/4095/0.00355=0.1032
|
|
fprintf(stdout, " (Ti:%.1fC)", ti);
|
|
// SegmentA-Calibration:
|
|
//ui16_t T30 = adr_10e2h; // CAL_ADC_15T30
|
|
//ui16_t T85 = adr_10e4h; // CAL_ADC_15T85
|
|
//float tic = (ADC_Ti_raw-T30)*(85.0-30.0)/(T85-T30) + 30.0;
|
|
//fprintf(stdout, " (Tic:%.1fC)", tic);
|
|
// }
|
|
*/
|
|
return T - 273.15; // Celsius
|
|
}
|
|
/*
|
|
frame[0x32]: adr_1074h
|
|
frame[0x33]: adr_1075h
|
|
frame[0x34]: adr_1076h
|
|
frame[0x35..0x37]: TBCCR1 ; relHumCap-freq
|
|
frame[0x38]: adr_1078h
|
|
frame[0x39]: adr_1079h
|
|
frame[0x3A]: adr_1077h
|
|
frame[0x3B]: adr_100Ch
|
|
frame[0x3C..3D]: 0
|
|
frame[0x3E]: scale_index ; scale/range-index
|
|
frame[0x3F..40] = ADC12_A7 | 0xA000, V_R+=AVcc ; Thermistor
|
|
frame[0x41]: adr_1000h[scale_index*4]
|
|
frame[0x42]: adr_1000h[scale_index*4+1]
|
|
frame[0x43]: adr_1000h[scale_index*4+2]
|
|
frame[0x44]: adr_1000h[scale_index*4+3]
|
|
frame[0x45..46]: ADC12_A5/4, V_R+=2.5V
|
|
frame[0x47]: ADC12_A2/16 , V_R+=2.5V
|
|
frame[0x48..49]: ADC12_iT, V_R+=1.5V (int.Temp.diode)
|
|
frame[0x4C..4D]: ADC12_A6, V_R+=2.5V
|
|
frame[0x4E..4F]: ADC12_A3, V_R+=AVcc
|
|
frame[0x50..54]: 0;
|
|
frame[0x55..56]: ADC12_A1, V_R+=AVcc
|
|
frame[0x57..58]: ADC12_A0, V_R+=AVcc
|
|
frame[0x59..5A]: ADC12_A4, V_R+=AVcc // ntc2: R(25C)=2.2k, Rs=22.1e3 (relHumCap-Temp)
|
|
frame[0x5B]:
|
|
frame[0x5C]: adr_108Eh
|
|
frame[0x5D]: adr_1082h (SN)
|
|
frame[0x5E]: adr_1083h (SN)
|
|
frame[0x5F]: adr_1084h (SN)
|
|
frame[0x60]: adr_1080h (SN)
|
|
frame[0x61]: adr_1081h (SN)
|
|
*/
|
|
float M10get_Tntc2(uint32_t m) {
|
|
// SMD ntc
|
|
float Rs = 22.1e3; // P5.6=Vcc
|
|
// float R25 = 2.2e3;
|
|
// float b = 3650.0; // B/Kelvin
|
|
// float T25 = 25.0 + 273.15; // T0=25C, R0=R25=5k
|
|
// -> Steinhart–Hart coefficients (polyfit):
|
|
float p0 = 4.42606809e-03,
|
|
p1 = -6.58184309e-04,
|
|
p2 = 8.95735557e-05,
|
|
p3 = -2.84347503e-06;
|
|
float T = 0.0; // T/Kelvin
|
|
uint16_t ADC_ntc2; // ADC12 P6.4(A4)
|
|
float x, R;
|
|
struct M10 * anonym = &chan[m].m10;
|
|
|
|
// if (csOK)
|
|
// {
|
|
ADC_ntc2 = ((unsigned char)anonym->rxbuf[0x5A] << 8) | (unsigned char)anonym->rxbuf[0x59];
|
|
x = (4095.0 - ADC_ntc2)/ADC_ntc2; // (Vcc-Vout)/Vout
|
|
R = Rs / x;
|
|
//if (R > 0) T = 1/(1/T25 + 1/b * log(R/R25));
|
|
if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
|
// }
|
|
return T - 273.15;
|
|
}
|
|
|
|
// Humidity Sensor
|
|
// U.P.S.I.
|
|
//
|
|
#define FREQ_CAPCLK (8e6/2) // 8 MHz XT2 crystal, InputDivider IDx=01 (/2)
|
|
#define LN2 0.693147181
|
|
#define ADR_108A 1000.0 // 0x3E8=1000
|
|
|
|
float get_count_RH(uint32_t m) { // capture 1000 rising edges
|
|
struct M10 * anonym = &chan[m].m10;
|
|
uint32_t TBCCR1_1000 = anonym->rxbuf[0x35] | (anonym->rxbuf[0x36]<<8) | (anonym->rxbuf[0x37]<<16);
|
|
return TBCCR1_1000 / ADR_108A;
|
|
}
|
|
float get_TLC555freq(uint32_t m) {
|
|
return FREQ_CAPCLK / get_count_RH(m);
|
|
}
|
|
|
|
|
|
static void decodeframe10(uint32_t m){
|
|
uint32_t week;
|
|
uint32_t tow;
|
|
uint32_t cs;
|
|
uint32_t i;
|
|
int32_t ci;
|
|
double dir;
|
|
double v;
|
|
double vv;
|
|
double vn;
|
|
double ve;
|
|
double alt;
|
|
double lon;
|
|
double lat;
|
|
float vbat;
|
|
float temp1,temp2;
|
|
uint32_t time0;
|
|
uint32_t id;
|
|
char ids[201];
|
|
//char s[201+6];
|
|
char s[400];
|
|
float fq555;
|
|
char typ=1;
|
|
|
|
struct M10 * anonym;
|
|
struct CHAN * anonym0; /* call if set */
|
|
{ /* with */
|
|
struct M10 * anonym = &chan[m].m10;
|
|
cs = (uint32_t)crcm10(99L, anonym->rxbuf, 101ul);
|
|
if (cs==m10card(anonym->rxbuf, 101ul, 99L, 2L)) {
|
|
/* crc ok */
|
|
if(((unsigned char)anonym->rxbuf[1]==0x8f || (unsigned char)anonym->rxbuf[1]==0x9f) && (unsigned char)anonym->rxbuf[2]==0x20){
|
|
if((unsigned char)anonym->rxbuf[1]==0x8f) typ=3;
|
|
tow = m10card(anonym->rxbuf, 101ul, 10L, 4L);
|
|
week = m10card(anonym->rxbuf, 101ul, 32L, 2L);
|
|
time0 = tow/1000UL+week*604800UL+315964800UL;
|
|
if (verb2) {
|
|
osi_WrStr(" ", 2ul);
|
|
aprsstr_DateToStr(time0, s, 201ul);
|
|
osi_WrStr(s, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
}
|
|
temp1=M10get_Temp(m);
|
|
temp2=M10get_Tntc2(m);
|
|
fq555 = get_TLC555freq(m);
|
|
vbat=(float)((256*(unsigned char)anonym->rxbuf[70]+(unsigned char)anonym->rxbuf[69])*0.00668);
|
|
lat = (double)m10card(anonym->rxbuf, 101ul, 14L,4L)*8.3819036711397E-8;
|
|
lon = (double)m10card(anonym->rxbuf, 101ul, 18L,4L)*8.3819036711397E-8;
|
|
alt = (double)m10card(anonym->rxbuf, 101ul, 22L, 4L)*0.001;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 4L, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
ve = (double)ci*0.005;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 6L, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
vn = (double)ci*0.005;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 8L, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
vv = (double)ci*0.005;
|
|
v = (double)osic_sqrt((float)(ve*ve+vn*vn));
|
|
// hor speed
|
|
dir = atang2(vn, ve)*5.7295779513082E+1;
|
|
if (dir<0.0) dir = 360.0+dir;
|
|
}
|
|
else if((unsigned char)anonym->rxbuf[1]==0xAF && (unsigned char)anonym->rxbuf[2]==0x02){
|
|
typ=2;
|
|
int tim=m10card(anonym->rxbuf, 101ul, 0x15, 3L);
|
|
int dat=m10card(anonym->rxbuf, 101ul, 0x18, 3L);
|
|
time0 = 2678400*(dat%10000)/100 +86400*dat/10000 +3600*(tim/10000)+60*((tim%10000)/100)+ ((tim%100)/1); //tow/1000UL+week*604800UL+315964800UL;
|
|
if (verb2) {
|
|
osi_WrStr(" ", 2ul);
|
|
aprsstr_DateToStr(time0, s, 201ul);
|
|
osi_WrStr(s, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
}
|
|
temp1=M10get_Temp(m);
|
|
temp2=M10get_Tntc2(m);
|
|
fq555 = get_TLC555freq(m);
|
|
vbat=(float)((256*(unsigned char)anonym->rxbuf[70]+(unsigned char)anonym->rxbuf[69])*0.00668);
|
|
lat = (double)m10card(anonym->rxbuf, 101ul, 0x04,4L)*1e-6;
|
|
lon = (double)m10card(anonym->rxbuf, 101ul, 0x08,4L)*1e-6;
|
|
alt = (double)m10card(anonym->rxbuf, 101ul, 0x0c, 3L)*0.01;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 0x0f, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
ve = (double)ci*0.005;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 0x11, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
vn = (double)ci*0.005;
|
|
ci = (int32_t)m10card(anonym->rxbuf, 101ul, 0x13, 2L);
|
|
if (ci>32767L) ci -= 65536L;
|
|
vv = (double)ci*0.005;
|
|
v = (double)osic_sqrt((float)(ve*ve+vn*vn));
|
|
// hor speed
|
|
dir = atang2(vn, ve)*5.7295779513082E+1;
|
|
if (dir<0.0) dir = 360.0+dir;
|
|
}
|
|
|
|
|
|
int i,j,k,l;
|
|
unsigned int byte;
|
|
unsigned char sn_bytes[5];
|
|
char SN[12];
|
|
|
|
for (i = 0; i < 11; i++) SN[i] = ' '; SN[11] = '\0';
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
byte = anonym->rxbuf[0x5d + i];
|
|
sn_bytes[i] = byte;
|
|
}
|
|
|
|
byte = sn_bytes[2];
|
|
sprintf(SN, "%1X%02u", (byte>>4)&0xF, byte&0xF);
|
|
j=atoi(SN);
|
|
k=(int)(j/25);
|
|
l=j-k*25;
|
|
byte = sn_bytes[3] | (sn_bytes[4]<<8);
|
|
sprintf(SN+3, "%1X%1u%04u", sn_bytes[0]&0xF, (byte>>13)&0x7, byte&0x1FFF);
|
|
sprintf(ids,SN);
|
|
ids[9U] = 0;
|
|
|
|
/* get ID */
|
|
if (verb) {
|
|
//WrChan((int32_t)m);
|
|
printCnDT(m);
|
|
osi_WrStr("M10 ", 5ul);
|
|
osi_WrStr(ids, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)lat, 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)lon, 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)alt, 1L, 1UL);
|
|
osi_WrStr("m ", 3ul);
|
|
osic_WrFixed((float)(v*3.6), 1L, 1UL);
|
|
osi_WrStr("km/h ", 6ul);
|
|
osic_WrFixed((float)dir, 0L, 1UL);
|
|
osi_WrStr("deg ", 5ul);
|
|
osic_WrFixed((float)vv, 1L, 1UL);
|
|
osi_WrStr("m/s ", 5ul);
|
|
osic_WrFixed((float)vbat, 1L, 1UL);
|
|
osi_WrStr("V T1:", 6ul);
|
|
osic_WrFixed((float)temp1, 1L, 1UL);
|
|
osi_WrStr("C T2:", 6ul);
|
|
osic_WrFixed((float)temp2, 1L, 1UL);
|
|
osi_WrStr("C ", 3ul);
|
|
}
|
|
struct CHAN * anonym0 = &chan[m];
|
|
s[0U] = (char)(anonym0->mycallc>>24);
|
|
s[1U] = (char)(anonym0->mycallc>>16&255UL);
|
|
s[2U] = (char)(anonym0->mycallc>>8&255UL);
|
|
s[3U] = (char)(anonym0->mycallc&255UL);
|
|
if (anonym0->mycallc>0UL) s[4U] = anonym0->myssid;
|
|
else s[4U] = '\020';
|
|
s[5]=','+typ;
|
|
for(i=0;i<6;i++) //qrg
|
|
s[i+6]=chan[m].freq[i];
|
|
s[12]=',';
|
|
for(i=0;i<9;i++) //nazwa
|
|
s[i+13]=ids[i];
|
|
s[22]=0;
|
|
//if( lat>-90.0 && lat<90.0 && lon>=-180.0 && lon<=180.0 && alt>0.0 && alt<45000.0 && dir>=0 && dir<361 && v>=0 && v<600 && vv>-200 && vv<200 && vbat>0 && vbat<10 && temp1>-270.0 && temp1<100.0 && temp2>-270.0 && temp2<100.0){
|
|
if( lat>-90.0 && lat<90.0 && lon>=-180.0 && lon<=180.0 && alt>0.0 && alt<45000.0 && dir>=0 && dir<361 && v>=0 && v<600 && vv>-200 && vv<200 && vbat>0 && vbat<10){
|
|
sprintf(s,"%s,%012lu,%09.5f,%010.5f,%05.0f,%03.0f,%05.1f,%05.1f,%05.2f,%06.1f,%06.1f,%06.0f\n",s,time0,lat,lon,alt,dir,v,vv,vbat,temp1,temp2,fq555);
|
|
alludp(chan[m].udptx, 105, s, 105);
|
|
}
|
|
}
|
|
else if (verb) {
|
|
/*build tx frame */
|
|
WrChan((int32_t)m);
|
|
osi_WrStr("M10 crc error", 14ul);
|
|
}
|
|
if (verb) {
|
|
WrdB(chan[m].adcmax-chan[m].adcmin);
|
|
WrQuali(noiselevel1(anonym->bitlev, anonym->noise));
|
|
Wrtune(chan[m].adcmax+chan[m].adcmin, chan[m].adcmax-chan[m].adcmin);
|
|
}
|
|
if (verb2) {
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
if (i%10UL==0UL) osi_WrStrLn("", 1ul);
|
|
osic_WrINT32(m10card(anonym->rxbuf, 101ul,
|
|
(int32_t)(48UL+i*2UL), 2L), 6UL);
|
|
osi_WrStr(" ", 2ul);
|
|
} /* end for */
|
|
for (i = 0UL; i<=100UL; i++) {
|
|
if (i%24UL==0UL) osi_WrStrLn("", 1ul);
|
|
if (X2C_INL(i,256,_cnst1)) osi_WrStr(" . ", 4ul);
|
|
else osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[i], 3UL);
|
|
} /* end for */
|
|
}
|
|
if (verb) osi_WrStrLn("", 1ul);
|
|
}
|
|
} /* end decodeframe10() */
|
|
|
|
|
|
static void demodbyte10(uint32_t m, char d)
|
|
{
|
|
struct M10 * anonym;
|
|
{ /* with */
|
|
struct M10 * anonym = &chan[m].m10;
|
|
/*WrInt(ORD(d),1); Flush(); */
|
|
anonym->synword = anonym->synword*2UL+(uint32_t)d;
|
|
if (anonym->rxp>=101UL) {
|
|
if ((anonym->synword&16777215UL)==6594336UL) {
|
|
anonym->rxp = 3UL;
|
|
anonym->rxb = 0UL;
|
|
anonym->rxbuf[0U] = 0x64;
|
|
anonym->rxbuf[1U] = 0x9f;
|
|
anonym->rxbuf[2U] = 0x20;
|
|
}
|
|
if ((anonym->synword&16777215UL)==6598402UL) { //gtop
|
|
anonym->rxp = 3UL;
|
|
anonym->rxb = 0UL;
|
|
anonym->rxbuf[0U] = 0x64;
|
|
anonym->rxbuf[1U] = 0xAF;
|
|
anonym->rxbuf[2U] = 0x02;
|
|
}
|
|
if ((anonym->synword&16777215UL)==6590240UL) { //M2K2
|
|
anonym->rxp = 3UL;
|
|
anonym->rxb = 0UL;
|
|
anonym->rxbuf[0U] = 0x64;
|
|
anonym->rxbuf[1U] = 0x8F;
|
|
anonym->rxbuf[2U] = 0x20;
|
|
}
|
|
|
|
|
|
}
|
|
else {
|
|
/*WrStr(" -syn- "); */
|
|
++anonym->rxb;
|
|
if (anonym->rxb>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)(anonym->synword&255UL);
|
|
anonym->rxb = 0UL;
|
|
++anonym->rxp;
|
|
if (anonym->rxp==101UL) decodeframe10(m);
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbyte10() */
|
|
|
|
static void demodbit10(uint32_t m, float u, float u0)
|
|
{
|
|
char bit;
|
|
char d;
|
|
float ua;
|
|
struct M10 * anonym;
|
|
/*IF manchestd>20000 THEN */
|
|
/*WrInt(VAL(INTEGER, u), 8); Flush; */
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct M10 * anonym = &chan[m].m10;
|
|
/*WrInt(manchestd DIV 256, 1); WrStr("("); WrInt(ORD(lastmanch),1);
|
|
WrInt(ORD(d),1);WrStr(")"); Flush(); */
|
|
/*WrInt(ORD(lastmanch<>d),1); Flush(); */
|
|
/*END; */
|
|
if (anonym->lastmanch==d) {
|
|
anonym->manchestd += (32767L-anonym->manchestd)/16L;
|
|
}
|
|
bit = d!=anonym->lastmanch;
|
|
if (anonym->manchestd>0L) {
|
|
demodbyte10(m, bit);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.02f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.05f;
|
|
}
|
|
/*quality*/
|
|
anonym->lastmanch = d;
|
|
anonym->manchestd = -anonym->manchestd;
|
|
}
|
|
} /* end demodbit10() */
|
|
|
|
|
|
static void demod10(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct M10 * anonym;
|
|
/*
|
|
IF debfd>=0 THEN
|
|
ui:=VAL(INTEGER, u*0.002);
|
|
WrBin(debfd, ui, 2);
|
|
END;
|
|
*/
|
|
{ /* with */
|
|
struct M10 * anonym = &chan[m].m10;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
demodbit10(m, u, anonym->lastu);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demod10() */
|
|
|
|
|
|
/*---------------------- M10 */
|
|
|
|
/*---------------------- M20 */
|
|
|
|
#define pos_SN20 18
|
|
|
|
float M20get_Temp(uint32_t m) {
|
|
float p0 = 1.07303516e-03,
|
|
p1 = 2.41296733e-04,
|
|
p2 = 2.26744154e-06,
|
|
p3 = 6.52855181e-08;
|
|
// T/K = 1/( p0 + p1*ln(R) + p2*ln(R)^2 + p3*ln(R)^3 )
|
|
|
|
// range/scale 0, 1, 2: // M10-pcb
|
|
float Rs[3] = { 12.1e3 , 36.5e3 , 475.0e3 }; // bias/series
|
|
float Rp[3] = { 1e20 , 330.0e3 , 3000.0e3 }; // parallel, Rp[0]=inf
|
|
|
|
uint8_t scT; // {0,1,2}, range/scale voltage divider
|
|
uint16_t ADC_RT; // ADC12 P6.7(A7) , adr_0377h,adr_0376h
|
|
uint16_t Tcal[2]; // adr_1000h[scT*4]
|
|
|
|
float adc_max = 4095.0; // ADC12
|
|
float x, R;
|
|
float T = 0; // T/Kelvin
|
|
struct M20 * anonym = &chan[m].m20;
|
|
|
|
scT = 0; //(unsigned char)anonym->rxbuf[0x3E]; // adr_0455h
|
|
ADC_RT = ((unsigned char)anonym->rxbuf[0x05] << 8) | (unsigned char)anonym->rxbuf[0x04];
|
|
|
|
printf("TEST: %04x\n",ADC_RT);
|
|
// ADC_RT -= 0xA000;
|
|
// Tcal[0] = ((unsigned char)anonym->rxbuf[0x42] << 8) | (unsigned char)anonym->rxbuf[0x41];
|
|
// Tcal[1] = ((unsigned char)anonym->rxbuf[0x44] << 8) | (unsigned char)anonym->rxbuf[0x43];
|
|
|
|
x = (adc_max-ADC_RT)/ADC_RT; // (Vcc-Vout)/Vout
|
|
if (scT < 3) R = Rs[scT] /( x - Rs[scT]/Rp[scT] );
|
|
else R = -1;
|
|
|
|
if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
|
return (T - 273.15); // Celsius
|
|
}
|
|
|
|
float M20get_Tntc2(uint32_t m) {
|
|
// SMD ntc
|
|
float Rs = 22.1e3; // P5.6=Vcc
|
|
float R25 = 2.2e3;
|
|
float b = 3650.0; // B/Kelvin
|
|
float T25 = 25.0 + 273.15; // T0=25C, R0=R25=5k
|
|
// -> Steinhart–Hart coefficients (polyfit):
|
|
float p0 = 4.42606809e-03,
|
|
p1 = -6.58184309e-04,
|
|
p2 = 8.95735557e-05,
|
|
p3 = -2.84347503e-06;
|
|
float T = 0.0; // T/Kelvin
|
|
uint16_t ADC_ntc2; // ADC12 P6.4(A4)
|
|
float x, R;
|
|
struct M20 * anonym = &chan[m].m10;
|
|
|
|
// if (csOK)
|
|
// {
|
|
ADC_ntc2 = ((unsigned char)anonym->rxbuf[0x07] << 8) | (unsigned char)anonym->rxbuf[0x06];
|
|
x = (4095.0 - ADC_ntc2)/ADC_ntc2; // (Vcc-Vout)/Vout
|
|
R = Rs / x;
|
|
if (R > 0) T = 1/(1/T25 + 1/b * log(R/R25));
|
|
//if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
|
// }
|
|
return T - 273.15;
|
|
}
|
|
|
|
|
|
static void decodeframe20(uint32_t m)
|
|
{
|
|
uint32_t week;
|
|
uint32_t tow;
|
|
uint32_t cs;
|
|
uint32_t i;
|
|
int32_t ci;
|
|
double dir;
|
|
double v;
|
|
double vv;
|
|
double vn;
|
|
double ve;
|
|
double alt;
|
|
double lon;
|
|
double lat;
|
|
float vbat;
|
|
float temp1,temp2;
|
|
float psb=0.0;
|
|
uint32_t time0;
|
|
uint32_t id;
|
|
int k;
|
|
char ids[201];
|
|
//char s[201+6];
|
|
char s[400];
|
|
struct M20 * anonym;
|
|
struct CHAN * anonym0; /* call if set */
|
|
{ /* with */
|
|
struct M20 * anonym = &chan[m].m20;
|
|
cs = (uint32_t)crcm10(68L, anonym->rxbuf, 70ul);
|
|
// printf("[0]:%02x:%02x CS:%04x\n",(unsigned char)anonym->rxbuf[68],(unsigned char)anonym->rxbuf[69],cs);
|
|
|
|
|
|
if (((unsigned char)anonym->rxbuf[0]==0x45 && (unsigned char)anonym->rxbuf[1]==0x20) && cs==m10card(anonym->rxbuf, 70ul, 68L, 2L)) {
|
|
/* crc ok */
|
|
printf("\n");
|
|
for(k=0;k<70;k++)
|
|
printf("%02x",(unsigned char)anonym->rxbuf[k]);
|
|
printf("\n");
|
|
|
|
|
|
tow=0;
|
|
tow=(unsigned char)anonym->rxbuf[15];
|
|
tow<<=8;
|
|
tow|=(unsigned char)anonym->rxbuf[16];
|
|
tow<<=8;
|
|
tow|=(unsigned char)anonym->rxbuf[17];
|
|
|
|
unsigned char w[4];
|
|
week=0;
|
|
|
|
if((unsigned char)anonym->rxbuf[64]==0 && (unsigned char)anonym->rxbuf[65]==0 && (unsigned char)anonym->rxbuf[66]==0) { psb=50.0; }
|
|
|
|
|
|
|
|
|
|
week= (((unsigned char)anonym->rxbuf[27]>>4)&0x0f)*1000 ;
|
|
week+= ((unsigned char)anonym->rxbuf[27])&0x0f;
|
|
week+= (((unsigned char)anonym->rxbuf[26]>>4)&0x0f)*100 ;
|
|
week+= (((unsigned char)anonym->rxbuf[26])&0x0f)*10;
|
|
/*
|
|
time0 = tow/1000UL+week*604800UL+315964800UL;
|
|
if (verb2) {
|
|
osi_WrStr(" ", 2ul);
|
|
aprsstr_DateToStr(time0, s, 201ul);
|
|
osi_WrStr(s, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
}
|
|
*/
|
|
time0 = tow+week*604800000UL+315964800UL;
|
|
if (verb2) {
|
|
osi_WrStr(" ", 2ul);
|
|
aprsstr_DateToStr(time0/1000, s, 201ul);
|
|
osi_WrStr(s, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
}
|
|
|
|
|
|
vbat=(float)3.3-(255-(unsigned char)anonym->rxbuf[38])*0.012654321;
|
|
lat = (double)m10card(anonym->rxbuf, 70ul, 28L,4L)*0.000001;
|
|
lon = (double)m10card(anonym->rxbuf, 70ul, 32L,4L)*0.000001;
|
|
alt = (double)m10card(anonym->rxbuf, 70ul, 8L, 3L)*0.01;
|
|
|
|
//ci = (int32_t)m10card(anonym->rxbuf, 70, 0x0b, 2L);
|
|
|
|
ci=0xff&anonym->rxbuf[0x0b]; ci<<=8; ci|= 0xff& anonym->rxbuf[0x0c];
|
|
// printf("TEST: %04x\n",ci);
|
|
if (ci>32767L) ci -= 65536L;
|
|
ve = (double)ci/ 1e2;
|
|
//ci = (int32_t)m10card(anonym->rxbuf, 70, 0x0d, 2L);
|
|
// ci=(int32_t)anonym->rxbuf[0x0e]<<8 | anonym->rxbuf[0x0d];
|
|
ci=0xff&anonym->rxbuf[0x0d]; ci<<=8; ci|=0xff& anonym->rxbuf[0x0e];
|
|
|
|
if (ci>32767L) ci -= 65536L;
|
|
vn = (double)ci/ 1e2;
|
|
//ci = (int32_t)m10card(anonym->rxbuf, 70, 0x18, 2L);
|
|
// ci=(int32_t)anonym->rxbuf[0x19]<<8 | anonym->rxbuf[0x18];
|
|
ci=0xff&anonym->rxbuf[0x18]; ci<<=8; ci|=0xff& anonym->rxbuf[0x19];
|
|
// printf("TEST: %04x\n\n",ci);
|
|
if (ci>32767L) ci -= 65536L;
|
|
vv = (double)ci/ 1e2;
|
|
v = (double)osic_sqrt((float)(ve*ve+vn*vn));
|
|
// hor speed
|
|
dir = atang2(vn, ve)*5.7295779513082E+1;
|
|
if (dir<0.0) dir = 360.0+dir;
|
|
|
|
|
|
/* int i,j,k,l;
|
|
unsigned int byte;
|
|
unsigned char sn_bytes[5];
|
|
char SN[12];
|
|
|
|
for (i = 0; i < 11; i++) SN[i] = ' '; SN[11] = '\0';
|
|
|
|
for (i = 0; i < 5; i++) {
|
|
byte = anonym->rxbuf[46 + i];
|
|
sn_bytes[i] = byte;
|
|
}
|
|
*/
|
|
unsigned long bSN;
|
|
unsigned long sn1,sn2,sn3,sn1a;
|
|
bSN=(anonym->rxbuf[pos_SN20]<<16) & 0xff0000 | (anonym->rxbuf[pos_SN20+1]<<8) &0xff00 | (anonym->rxbuf[pos_SN20+2]) & 0xff;
|
|
sn1a =(bSN>>16)&0x7f;
|
|
sn1=100*(int)(sn1a/12)+ sn1a%12+1;
|
|
sn3 =((bSN>>5)&0x1f)<<11 | ((bSN >>10)&0x3f) | (bSN & 0x1f)<<6;
|
|
|
|
sprintf(ids,"%03u2%05u\n",sn1,sn3);
|
|
ids[9U] = 0;
|
|
|
|
// temp1=M20get_Temp(m);
|
|
temp2=M20get_Tntc2(m);
|
|
if (verb) {
|
|
//WrChan((int32_t)m);
|
|
printCnDT(m);
|
|
if(psb>10)
|
|
osi_WrStr("PS20 ", 5ul);
|
|
else
|
|
osi_WrStr("M20 ", 5ul);
|
|
osi_WrStr(ids, 201ul);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)lat, 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)lon, 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)alt, 1L, 1UL);
|
|
osi_WrStr("m ", 3ul);
|
|
osic_WrFixed((float)(v*3.6), 1L, 1UL);
|
|
osi_WrStr("km/h ", 6ul);
|
|
osic_WrFixed((float)dir, 0L, 1UL);
|
|
osi_WrStr("deg ", 5ul);
|
|
osic_WrFixed((float)vv, 1L, 1UL);
|
|
osi_WrStr("m/s ", 5ul);
|
|
osic_WrFixed((float)vbat, 1L, 1UL);
|
|
osi_WrStr("V T1:", 6ul);
|
|
osic_WrFixed((float)temp1, 1L, 1UL);
|
|
osi_WrStr("C T2:", 6ul);
|
|
osic_WrFixed((float)temp2, 1L, 1UL);
|
|
osi_WrStr("C ", 3ul);
|
|
}
|
|
struct CHAN * anonym0 = &chan[m];
|
|
s[0U] = (char)(anonym0->mycallc>>24);
|
|
s[1U] = (char)(anonym0->mycallc>>16&255UL);
|
|
s[2U] = (char)(anonym0->mycallc>>8&255UL);
|
|
s[3U] = (char)(anonym0->mycallc&255UL);
|
|
if (anonym0->mycallc>0UL) s[4U] = anonym0->myssid;
|
|
else s[4U] = '\020';
|
|
s[5]=',';
|
|
for(i=0;i<6;i++) //qrg
|
|
s[i+6]=chan[m].freq[i];
|
|
s[12]=',';
|
|
for(i=0;i<9;i++) //nazwa
|
|
s[i+13]=ids[i];
|
|
s[22]=0;
|
|
printf("\n");
|
|
if( lat>-90.0 && lat<90.0 && lon>=-180.0 && lon<=180.0 && alt>0.0 && alt<45000.0){
|
|
sprintf(s,"%s,%012lu,%09.5f,%010.5f,%05.0f,%03.0f,%05.1f,%05.1f,%05.2f,%06.1f,%06.1f\n",s,time0,lat,lon,alt,dir,v,vv,(vbat+psb),temp1,temp2);
|
|
alludp(chan[m].udptx, 100, s, 100);
|
|
}
|
|
}
|
|
else if (verb2) {
|
|
/*build tx frame */
|
|
WrChan((int32_t)m);
|
|
osi_WrStr("M20 crc error", 14ul);
|
|
}
|
|
if (verb2) {
|
|
WrdB(chan[m].adcmax-chan[m].adcmin);
|
|
WrQuali(noiselevel1(anonym->bitlev, anonym->noise));
|
|
Wrtune(chan[m].adcmax+chan[m].adcmin, chan[m].adcmax-chan[m].adcmin);
|
|
}
|
|
if (verb2) {
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
if (i%10UL==0UL) osi_WrStrLn("", 1ul);
|
|
osic_WrINT32(m10card(anonym->rxbuf, 101ul,
|
|
(int32_t)(48UL+i*2UL), 2L), 6UL);
|
|
osi_WrStr(" ", 2ul);
|
|
} /* end for */
|
|
for (i = 0UL; i<=100UL; i++) {
|
|
if (i%24UL==0UL) osi_WrStrLn("", 1ul);
|
|
if (X2C_INL(i,256,_cnst1)) osi_WrStr(" . ", 4ul);
|
|
else osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[i], 3UL);
|
|
} /* end for */
|
|
}
|
|
if (verb2) osi_WrStrLn("", 1ul);
|
|
}
|
|
} /* end decodeframe20() */
|
|
|
|
|
|
|
|
static void demodbyte20(uint32_t m, char d)
|
|
{
|
|
struct M20 * anonym;
|
|
{ /* with */
|
|
struct M20 * anonym = &chan[m].m20;
|
|
/*WrInt(ORD(d),1); Flush(); */
|
|
anonym->synword = anonym->synword*2UL+(uint32_t)d;
|
|
if (anonym->rxp>=70UL) {
|
|
if ((anonym->synword&0xffff)==0x4520) {
|
|
anonym->rxp = 2UL;
|
|
anonym->rxb = 0UL;
|
|
anonym->rxbuf[0U] = 0x45;
|
|
anonym->rxbuf[1U] = 0x20;
|
|
}
|
|
}
|
|
else {
|
|
/*WrStr(" -syn- "); */
|
|
++anonym->rxb;
|
|
if (anonym->rxb>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)(anonym->synword&0xff);
|
|
anonym->rxb = 0UL;
|
|
++anonym->rxp;
|
|
if (anonym->rxp==70UL) decodeframe20(m);
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbyte10() */
|
|
|
|
static void demodbit20(uint32_t m, float u, float u0)
|
|
{
|
|
char bit;
|
|
char d;
|
|
float ua;
|
|
struct M20 * anonym;
|
|
/*IF manchestd>20000 THEN */
|
|
/*WrInt(VAL(INTEGER, u), 8); Flush; */
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct M20 * anonym = &chan[m].m20;
|
|
/*WrInt(manchestd DIV 256, 1); WrStr("("); WrInt(ORD(lastmanch),1);
|
|
WrInt(ORD(d),1);WrStr(")"); Flush(); */
|
|
/*WrInt(ORD(lastmanch<>d),1); Flush(); */
|
|
/*END; */
|
|
if (anonym->lastmanch==d) {
|
|
anonym->manchestd += (32767L-anonym->manchestd)/16L;
|
|
}
|
|
bit = d!=anonym->lastmanch;
|
|
if (anonym->manchestd>0L) {
|
|
demodbyte20(m, bit);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.02f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.05f;
|
|
}
|
|
/*quality*/
|
|
anonym->lastmanch = d;
|
|
anonym->manchestd = -anonym->manchestd;
|
|
}
|
|
} /* end demodbit10() */
|
|
|
|
|
|
static void demod20(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct M20 * anonym;
|
|
/*
|
|
IF debfd>=0 THEN
|
|
ui:=VAL(INTEGER, u*0.002);
|
|
WrBin(debfd, ui, 2);
|
|
END;
|
|
*/
|
|
{ /* with */
|
|
struct M20 * anonym = &chan[m].m20;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
demodbit20(m, u, anonym->lastu);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
}
|
|
|
|
|
|
/*---------------------- M20 */
|
|
|
|
/* IMS ---------------------- */
|
|
|
|
|
|
#define IMS_FLEN 150
|
|
#define MAX_DEG 254
|
|
|
|
typedef struct {
|
|
uint32_t f;
|
|
uint32_t ord;
|
|
uint8_t alpha;
|
|
} GF_t;
|
|
|
|
static uint8_t exp_a[256],
|
|
log_a[256];
|
|
|
|
typedef struct {
|
|
uint8_t N;
|
|
uint8_t t;
|
|
uint8_t R; // RS: R=2t, BCH: R<=mt
|
|
uint8_t K; // K=N-R
|
|
uint8_t b;
|
|
uint8_t g[MAX_DEG+1]; // ohne g[] eventuell als init_return
|
|
} RS_t;
|
|
|
|
|
|
static RS_t RS256 = { 255, 12, 24, 231, 0, {0}};
|
|
static RS_t BCH64 = { 63, 2, 12, 51, 1, {0}};
|
|
|
|
static RS_t RS;
|
|
static GF_t GF;
|
|
|
|
static GF_t GF64BCH = { 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
|
64, // 2^6
|
|
0x02 }; // generator: alpha = X
|
|
|
|
static
|
|
int GF_deg(uint32_t p) {
|
|
uint32_t d = 31;
|
|
if (p == 0) return -1; /* deg(0) = -infty */
|
|
else {
|
|
while (d && !(p & (1<<d))) d--; /* d<32, 1L = 1 */
|
|
}
|
|
return d;
|
|
}
|
|
|
|
static uint8_t GF_mul(uint8_t p, uint8_t q) {
|
|
uint32_t x;
|
|
if ((p == 0) || (q == 0)) return 0;
|
|
x = (uint32_t)log_a[p] + log_a[q];
|
|
return exp_a[x % (GF.ord-1)]; // a^(ord-1) = 1
|
|
}
|
|
|
|
static uint8_t GF_inv(uint8_t p) {
|
|
if (p == 0) return 0; // DIV_BY_ZERO
|
|
return exp_a[GF.ord-1-log_a[p]]; // a^(ord-1) = 1
|
|
}
|
|
|
|
static
|
|
uint8_t poly_eval(uint8_t poly[], uint8_t x) {
|
|
int n;
|
|
uint8_t xn, y;
|
|
|
|
y = poly[0];
|
|
if (x != 0) {
|
|
for (n = 1; n < GF.ord-1; n++) {
|
|
xn = exp_a[(n*log_a[x]) % (GF.ord-1)];
|
|
y ^= GF_mul(poly[n], xn);
|
|
}
|
|
}
|
|
return y;
|
|
}
|
|
|
|
static
|
|
uint8_t GF2m_mul(uint8_t a, uint8_t b) {
|
|
uint32_t aa = a;
|
|
uint8_t ab = 0;
|
|
int i, m = GF_deg(b);
|
|
|
|
if (b & 1) ab = a;
|
|
|
|
for (i = 0; i < m; i++) {
|
|
aa = (aa << 1); // a = a * X
|
|
if (GF_deg(aa) == GF_deg(GF.f))
|
|
aa ^= GF.f; // a = a - GF.f
|
|
b >>= 1;
|
|
if (b & 1) ab ^= (uint8_t)aa; /* b_{i+1} > 0 ? */
|
|
}
|
|
return ab;
|
|
}
|
|
|
|
static
|
|
int GF_genTab(GF_t gf, uint8_t expa[], uint8_t loga[]) {
|
|
int i, j;
|
|
uint8_t b;
|
|
|
|
// GF.f = f;
|
|
// GF.ord = 1 << GF_deg(GF.f);
|
|
|
|
b = 0x01;
|
|
for (i = 0; i < gf.ord; i++) {
|
|
expa[i] = b; // b_i = a^i
|
|
b = GF2m_mul(gf.alpha, b);
|
|
}
|
|
|
|
loga[0] = -00; // log(0) = -inf
|
|
for (i = 1; i < gf.ord; i++) {
|
|
b = 0x01; j = 0;
|
|
while (b != i) {
|
|
b = GF2m_mul(gf.alpha, b);
|
|
j++;
|
|
if (j > gf.ord-1) {
|
|
return -1; // a not primitive
|
|
}
|
|
} // j = log_a(i)
|
|
loga[i] = j;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rs_init_BCH64() {
|
|
int i, check_gen;
|
|
|
|
GF = GF64BCH;
|
|
check_gen = GF_genTab( GF, exp_a, log_a);
|
|
|
|
RS = BCH64; // N=63, t=2, b=1
|
|
for (i = 0; i <= MAX_DEG; i++) RS.g[i] = 0;
|
|
|
|
// g(X)=X^12+X^10+X^8+X^5+X^4+X^3+1
|
|
// =(X^6+X+1)(X^6+X^4+X^2+X+1)
|
|
RS.g[0] = RS.g[3] = RS.g[4] = RS.g[5] = RS.g[8] = RS.g[10] = RS.g[12] = 1;
|
|
|
|
return check_gen;
|
|
}
|
|
|
|
static
|
|
int syndromes(uint8_t cw[], uint8_t *S) {
|
|
int i, errors = 0;
|
|
uint8_t a_i;
|
|
|
|
// syndromes: e_j=S(alpha^(b+i))
|
|
for (i = 0; i < 2*RS.t; i++) {
|
|
a_i = exp_a[(RS.b+i) % (GF.ord-1)]; // alpha^(b+i)
|
|
S[i] = poly_eval(cw, a_i);
|
|
if (S[i]) errors = 1;
|
|
}
|
|
return errors;
|
|
}
|
|
|
|
static
|
|
int poly_deg(uint8_t p[]) {
|
|
int n = MAX_DEG;
|
|
while (p[n] == 0 && n > 0) n--;
|
|
if (p[n] == 0) n--; // deg(0) = -inf
|
|
return n;
|
|
}
|
|
|
|
static
|
|
int poly_divmod(uint8_t p[], uint8_t q[], uint8_t *d, uint8_t *r) {
|
|
int deg_p, deg_q; // p(x) = q(x)d(x) + r(x)
|
|
int i; // deg(r) < deg(q)
|
|
uint8_t c;
|
|
|
|
deg_p = poly_deg(p);
|
|
deg_q = poly_deg(q);
|
|
|
|
if (deg_q < 0) return -1; // DIV_BY_ZERO
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) d[i] = 0;
|
|
for (i = 0; i <= MAX_DEG; i++) r[i] = 0;
|
|
|
|
|
|
c = GF_mul( p[deg_p], GF_inv(q[deg_q]));
|
|
|
|
if (deg_q == 0) {
|
|
for (i = 0; i <= deg_p; i++) d[i] = GF_mul(p[i], c);
|
|
for (i = 0; i <= MAX_DEG; i++) r[i] = 0;
|
|
}
|
|
else if (deg_p == 0) {
|
|
for (i = 0; i <= MAX_DEG; i++) {
|
|
d[i] = 0;
|
|
r[i] = 0;
|
|
}
|
|
}
|
|
else if (deg_p < deg_q) {
|
|
for (i = 0; i <= MAX_DEG; i++) d[i] = 0;
|
|
for (i = 0; i <= deg_p; i++) r[i] = p[i]; // r(x)=p(x), deg(r)<deg(q)
|
|
for (i = deg_p+1; i <= MAX_DEG; i++) r[i] = 0;
|
|
}
|
|
else {
|
|
for (i = 0; i <= deg_p; i++) r[i] = p[i];
|
|
while (deg_p >= deg_q) {
|
|
d[deg_p-deg_q] = c;
|
|
for (i = 0; i <= deg_q; i++) {
|
|
r[deg_p-i] ^= GF_mul( q[deg_q-i], c);
|
|
}
|
|
while (r[deg_p] == 0 && deg_p > 0) deg_p--;
|
|
if (r[deg_p] == 0) deg_p--;
|
|
if (deg_p >= 0) c = GF_mul( r[deg_p], GF_inv(q[deg_q]));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
int poly_add(uint8_t a[], uint8_t b[], uint8_t *sum) {
|
|
int i;
|
|
uint8_t c[MAX_DEG+1];
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) {
|
|
c[i] = a[i] ^ b[i];
|
|
}
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { sum[i] = c[i]; }
|
|
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
int poly_mul(uint8_t a[], uint8_t b[], uint8_t *ab) {
|
|
int i, j;
|
|
uint8_t c[MAX_DEG+1];
|
|
|
|
if (poly_deg(a)+poly_deg(b) > MAX_DEG) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { c[i] = 0; }
|
|
|
|
for (i = 0; i <= poly_deg(a); i++) {
|
|
for (j = 0; j <= poly_deg(b); j++) {
|
|
c[i+j] ^= GF_mul(a[i], b[j]);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { ab[i] = c[i]; }
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static
|
|
int polyGF_lfsr(int deg, uint8_t S[],
|
|
uint8_t *Lambda, uint8_t *Omega ) {
|
|
// BCH/RS/LFSR: deg=t,
|
|
// S(x)Lambda(x) = Omega(x) mod x^(2t)
|
|
int i;
|
|
uint8_t r0[MAX_DEG+1], r1[MAX_DEG+1], r2[MAX_DEG+1],
|
|
s0[MAX_DEG+1], s1[MAX_DEG+1], s2[MAX_DEG+1],
|
|
quo[MAX_DEG+1];
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { Lambda[i] = 0; }
|
|
for (i = 0; i <= MAX_DEG; i++) { Omega[i] = 0; }
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { r0[i] = S[i]; }
|
|
for (i = 0; i <= MAX_DEG; i++) { r1[i] = 0; } r1[2*deg] = 1; //x^2t
|
|
s0[0] = 1; for (i = 1; i <= MAX_DEG; i++) { s0[i] = 0; }
|
|
s1[0] = 0; for (i = 1; i <= MAX_DEG; i++) { s1[i] = 0; }
|
|
for (i = 0; i <= MAX_DEG; i++) { r2[i] = 0; }
|
|
for (i = 0; i <= MAX_DEG; i++) { s2[i] = 0; }
|
|
|
|
while ( poly_deg(r1) >= deg ) {
|
|
poly_divmod(r0, r1, quo, r2);
|
|
for (i = 0; i <= MAX_DEG; i++) { r0[i] = r1[i]; }
|
|
for (i = 0; i <= MAX_DEG; i++) { r1[i] = r2[i]; }
|
|
|
|
poly_mul(quo, s1, s2);
|
|
poly_add(s0, s2, s2);
|
|
for (i = 0; i <= MAX_DEG; i++) { s0[i] = s1[i]; }
|
|
for (i = 0; i <= MAX_DEG; i++) { s1[i] = s2[i]; }
|
|
}
|
|
|
|
// deg > 0:
|
|
for (i = 0; i <= MAX_DEG; i++) { Omega[i] = r1[i]; }
|
|
for (i = 0; i <= MAX_DEG; i++) { Lambda[i] = s1[i]; }
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rs_decode_bch_gf2t2(uint8_t cw[], uint8_t *err_pos, uint8_t *err_val) {
|
|
// binary 2-error correcting BCH
|
|
|
|
uint8_t x, gamma,
|
|
S[MAX_DEG+1],
|
|
L[MAX_DEG+1], L2,
|
|
Lambda[MAX_DEG+1],
|
|
Omega[MAX_DEG+1];
|
|
|
|
int i, n, errors = 0;
|
|
|
|
|
|
for (i = 0; i < RS.t; i++) { err_pos[i] = 0; }
|
|
for (i = 0; i < RS.t; i++) { err_val[i] = 0; }
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { S[i] = 0; }
|
|
errors = syndromes(cw, S);
|
|
// wenn S(x)=0 , dann poly_divmod(cw, RS.g, d, rem): rem=0
|
|
|
|
if (errors) {
|
|
polyGF_lfsr(RS.t, S, Lambda, Omega);
|
|
gamma = Lambda[0];
|
|
if (gamma) {
|
|
for (i = poly_deg(Lambda); i >= 0; i--) Lambda[i] = GF_mul(Lambda[i], GF_inv(gamma));
|
|
for (i = poly_deg(Omega) ; i >= 0; i--) Omega[i] = GF_mul( Omega[i], GF_inv(gamma));
|
|
}
|
|
else {
|
|
errors = -2;
|
|
return errors;
|
|
}
|
|
|
|
// GF(2)-BCH, t=2:
|
|
// S1 = S[0]
|
|
// S1^2 = S2 , S2^2 = S4
|
|
// L(x) = 1 + L1 x + L2 x^2 (1-2 errors)
|
|
// L1 = S1 , L2 = (S3 + S1^3)/S1
|
|
if ( RS.t == 2 ) {
|
|
|
|
for (i = 0; i <= MAX_DEG; i++) { L[i] = 0; }
|
|
L[0] = 1;
|
|
L[1] = S[0];
|
|
L2 = GF_mul(S[0], S[0]); L2 = GF_mul(L2, S[0]); L2 ^= S[2];
|
|
L2 = GF_mul(L2, GF_inv(S[0]));
|
|
L[2] = L2;
|
|
|
|
if (S[1] != GF_mul(S[0],S[0]) || S[3] != GF_mul(S[1],S[1])) {
|
|
errors = -2;
|
|
return errors;
|
|
}
|
|
if (L[1] != Lambda[1] || L[2] != Lambda[2] ) {
|
|
errors = -2;
|
|
return errors;
|
|
}
|
|
}
|
|
|
|
n = 0;
|
|
for (i = 1; i < GF.ord ; i++) { // Lambda(0)=1
|
|
x = (uint8_t)i; // roll-over
|
|
if (poly_eval(Lambda, x) == 0) {
|
|
// error location index
|
|
err_pos[n] = log_a[GF_inv(x)];
|
|
// error value; bin-BCH: err_val=1
|
|
err_val[n] = 1; // = forney(x, Omega, Lambda);
|
|
n++;
|
|
}
|
|
if (n >= poly_deg(Lambda)) break;
|
|
}
|
|
|
|
if (n < poly_deg(Lambda)) errors = -1; // uncorrectable errors
|
|
else {
|
|
errors = n;
|
|
for (i = 0; i < errors; i++) cw[err_pos[i]] ^= err_val[i];
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
|
|
static int decodeframeIMS(uint32_t m){
|
|
uint32_t week;
|
|
uint32_t tow;
|
|
uint32_t cs;
|
|
uint32_t i;
|
|
int32_t ci;
|
|
double dir;
|
|
double v;
|
|
double vv;
|
|
double vn;
|
|
double ve;
|
|
double alt;
|
|
double lon;
|
|
double lat;
|
|
float vbat;
|
|
float temp1,temp2;
|
|
uint32_t time0;
|
|
uint32_t id;
|
|
int k;
|
|
uint16_t cnt;
|
|
uint32_t tmpf;
|
|
char sntxt[12]={0,0};
|
|
char frs[10];
|
|
char txtt[100];
|
|
|
|
float *fcfg = (float *)&tmpf;
|
|
double vH,freq;
|
|
|
|
|
|
char s[400];
|
|
struct IMS * anonym;
|
|
struct CHAN * anonym0; /* call if set */
|
|
{
|
|
struct IMS * anonym = &chan[m].ims;
|
|
cnt=(anonym->frame[3]&0xff)<<8 | anonym->frame[4]&0xff;
|
|
|
|
if(cnt%2==0){
|
|
tmpf=(anonym->frame[0x20]&0xff)<<24 | (anonym->frame[0x21]&0xff)<<16 | (anonym->frame[0x22]&0xff)<<8 | (anonym->frame[0x23]&0xff);
|
|
lat=(double)tmpf;
|
|
tmpf=(anonym->frame[0x24]&0xff)<<24 | (anonym->frame[0x25]&0xff)<<16 | (anonym->frame[0x26]&0xff)<<8 | (anonym->frame[0x27]&0xff);
|
|
lon=(double)tmpf;
|
|
tmpf=(anonym->frame[0x28]&0xff)<<16 | (anonym->frame[0x29]&0xff)<<8 | (anonym->frame[0x2a]&0xff);
|
|
alt=(double)tmpf/100.0;
|
|
int latdeg = (int)lat / 1e6;
|
|
lat=(double)(lat/1e6-latdeg)*100/60.0 + latdeg;
|
|
int londeg = (int)lon / 1e6;
|
|
lon=(double)(lon/1e6-londeg)*100/60.0 + londeg;
|
|
tmpf=(anonym->frame[0x30]&0xff)<<8 | (anonym->frame[0x31]&0xff);
|
|
dir=(double)tmpf/100.0;
|
|
tmpf=(anonym->frame[0x32]&0xff)<<8 | (anonym->frame[0x33]&0xff);
|
|
vH=(double)tmpf/1.944e2;
|
|
|
|
|
|
}
|
|
if(cnt%64==15){
|
|
float fq;
|
|
tmpf=(anonym->frame[0x09]&0xff)<<24 | (anonym->frame[0x0a]&0xff)<<16 | (anonym->frame[0x07]&0xff)<<8 | (anonym->frame[0x08]&0xff);
|
|
anonym->freq=400.0+(*fcfg)/10;
|
|
}
|
|
else if(cnt%16==0){
|
|
tmpf=(anonym->frame[0x09]&0xff)<<24 | (anonym->frame[0x0a]&0xff)<<16 | (anonym->frame[0x07]&0xff)<<8 | (anonym->frame[0x08]&0xff);
|
|
float sn=-1;
|
|
sn=*fcfg;
|
|
sprintf(sntxt,"IMS%.0f",sn);
|
|
strcpy(anonym->id,sntxt);
|
|
anonym->id[9]=0;
|
|
}
|
|
if(strlen(anonym->id)>0) {
|
|
if(lat>100 || lat<0 || lon>100 || lon<0 || alt<1 || alt>40000) return 0;
|
|
if(cnt%16!=0) anonym->id[0]='i';
|
|
sprintf(txtt,"%s%05u%07.0f%08.0f%05.0f%03.0f%04.0f%06.0fXXXXXXXXXXXXXX",anonym->id,cnt,lat*100000,lon*100000,alt,dir,((vH+200.0)*10.0),anonym->freq*1000);
|
|
strcpy(anonym->frame,txtt);
|
|
printf("%02i: %s Fr:%05u %3.3fMHz Lat:%4.5f Lon:%4.5f Alt:%05.1f Dir:%3.1f vH:%3.1f \n",m,anonym->id,cnt,anonym->freq,lat,lon,alt,dir,vH);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void sendIMS(uint32_t m)
|
|
{
|
|
uint32_t i;
|
|
int k;
|
|
struct CHAN * anonym;
|
|
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].ims.frame[62U] = (char)(anonym->mycallc>>24);
|
|
chan[m].ims.frame[63U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].ims.frame[64U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].ims.frame[65U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].ims.frame[66U] = anonym->myssid;
|
|
chan[m].ims.frame[67U] = 0;
|
|
|
|
chan[m].ims.frame[68U] = chan[m].freq[0];
|
|
chan[m].ims.frame[69U] = chan[m].freq[1];
|
|
chan[m].ims.frame[70U] = chan[m].freq[2];
|
|
chan[m].ims.frame[71U] = chan[m].freq[3];
|
|
chan[m].ims.frame[72U] = chan[m].freq[4];
|
|
chan[m].ims.frame[73U] = chan[m].freq[5];
|
|
}
|
|
alludp(chan[m].udptx, 74UL, chan[m].ims.frame, 74ul);
|
|
}
|
|
} /* end sendpils() */
|
|
|
|
|
|
|
|
int bips(char* frame_rawbits, uint8_t *frame_bits,uint16_t len) {
|
|
|
|
uint16_t tmp=0,i,j,k;
|
|
uint8_t b;
|
|
|
|
k=0;
|
|
for(i=0;i<len;i+=2){
|
|
tmp=0;
|
|
tmp=((uint8_t)frame_rawbits[i]<<8) | ((uint8_t)frame_rawbits[i+1]);
|
|
b=0;
|
|
for(j=0;j<8;j++){
|
|
b<<=1;
|
|
if((tmp&0xc000)==0xc000 || (tmp&0xc000)==0x0000) {b|=1;}// printf("1");}
|
|
|
|
tmp<<=2;
|
|
}
|
|
frame_bits[k]=b;
|
|
k++;
|
|
}
|
|
}
|
|
|
|
#define MAX_DEG 254
|
|
|
|
uint16_t calcpar(uint16_t v){ // word value to compute the parity of
|
|
|
|
v ^= v >> 16;
|
|
v ^= v >> 8;
|
|
v ^= v >> 4;
|
|
v &= 0xf;
|
|
return ((0x6996 >> v) & 1);
|
|
}
|
|
|
|
int IMSraw2frame(char *in, char *out){
|
|
uint16_t i,j,k,jj;
|
|
uint16_t val1,val2,bch;
|
|
uint64_t buff;
|
|
uint16_t p1, p2;
|
|
uint64_t tmpl;
|
|
|
|
int errors;
|
|
uint8_t cw[63+1], // BCH(63,51), t=2
|
|
err_pos[4],
|
|
err_val[4];
|
|
uint8_t block_err[6];
|
|
int block, check_err;
|
|
int par=1, par_alt=1;
|
|
|
|
rs_init_BCH64();
|
|
|
|
for(i=0;i<3;i++) out[i]=in[i];
|
|
|
|
buff=0;
|
|
j=3;
|
|
k=3;
|
|
for(i=0;i<12;i++){
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff);
|
|
|
|
val1=(buff>>(16+i*2))&0xffff;
|
|
p1=(buff>>(15+i*2))&1;
|
|
|
|
buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff);
|
|
|
|
val2=(buff>>(7+i*2))&0xffff;
|
|
p2=(buff>>(6+i*2))&1;
|
|
|
|
buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff);
|
|
bch=(buff>>(2+i*2))&0xfff;
|
|
buff<<=8;
|
|
|
|
|
|
tmpl=val1; tmpl<<=1;
|
|
tmpl|=p1; tmpl<<=16;
|
|
tmpl|=val2; tmpl<<=1;
|
|
tmpl|=p2; tmpl<<=12;
|
|
tmpl|=bch;
|
|
|
|
for (jj = 0; jj < 46; jj++) {
|
|
cw[jj] =tmpl&0x01;
|
|
tmpl>>=1;
|
|
}
|
|
for (jj = 46; jj < 63; jj++) cw[jj] = 0;
|
|
|
|
errors = rs_decode_bch_gf2t2(cw, err_pos, err_val);
|
|
|
|
if (errors >= 0) {
|
|
check_err = 0;
|
|
for (jj = 46; jj < 63; jj++) { if (cw[jj] != 0) check_err = 0x1; }
|
|
par = 1;
|
|
for (jj = 13; jj < 13+16; jj++) par ^= cw[jj];
|
|
if (cw[12] != par) check_err |= 0x100;
|
|
par = 1;
|
|
for (jj = 30; jj < 30+16; jj++) par ^= cw[jj];
|
|
if (cw[29] != par) check_err |= 0x10;
|
|
if (check_err) errors = -3;
|
|
}
|
|
if (errors >= 0) {
|
|
|
|
val1=0;val2=0;
|
|
for(jj=0;jj<16;jj++) {
|
|
val1<<=1;
|
|
val1|=cw[45-jj]&1;
|
|
}
|
|
for(jj=17;jj<33;jj++) { val2<<=1; val2|=cw[45-jj]&1; }
|
|
|
|
}
|
|
if (errors < 0) { return 0; block_err[block] = 0xE; printf("E2: "); }
|
|
else { block_err[block] = errors; }
|
|
|
|
|
|
|
|
|
|
|
|
out[k++]=(val1>>8)&0xff;
|
|
out[k++]=(val1)&0xff;
|
|
out[k++]=(val2>>8)&0xff;
|
|
out[k++]=(val2)&0xff;
|
|
|
|
|
|
if(i==5){
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
buff|=(uint8_t)(in[j++]%0xff); buff<<=8;
|
|
out[k++]=0xFB;
|
|
out[k++]=0x62;
|
|
out[k++]=0x30;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void demodbyteIMS(uint32_t m, char d)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t revc;
|
|
uint32_t normc;
|
|
|
|
|
|
char tmp[100],tmp1[100];
|
|
char s[400];
|
|
struct IMS * anonym;
|
|
{ /* with */
|
|
struct IMS * anonym = &chan[m].ims;
|
|
if (anonym->rxp==0UL) {
|
|
anonym->synbuf[anonym->synp] = d;
|
|
i = anonym->synp;
|
|
++anonym->synp;
|
|
if (anonym->synp>47UL) anonym->synp = 0UL;
|
|
j = 48UL;
|
|
normc = 0UL;
|
|
revc = 0UL;
|
|
do {
|
|
--j;
|
|
if (("010101010100101011010100110010110011010100110010"[j]=='1')==anonym->synbuf[i]) ++normc;
|
|
else ++revc;
|
|
if (i==0UL) i = 47UL;
|
|
else --i;
|
|
} while (!(j==0UL || normc>1UL && revc>1UL));
|
|
anonym->headok = normc==0UL || revc==0UL;
|
|
anonym->rev = normc<revc;
|
|
if (j==0UL) {
|
|
anonym->rxbuf[0UL]=0b01010101; //fill in first 3 bytes )as we lost it for header
|
|
anonym->rxbuf[1UL]=0b01001010; //recovery of first bytes for crc calcs
|
|
anonym->rxbuf[2UL]=0b11010100;
|
|
anonym->rxbuf[3UL]=0b11001011;
|
|
anonym->rxbuf[4UL]=0b00110101;
|
|
anonym->rxbuf[5UL]=0b00110010;
|
|
anonym->rxp = 6UL;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
else {
|
|
anonym->rxbyte = anonym->rxbyte*2UL+1UL*(uint32_t)(d!=anonym->rev);
|
|
|
|
++anonym->rxbitc;
|
|
if (anonym->rxbitc>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)((uint8_t)anonym->rxbyte);
|
|
++anonym->rxp;
|
|
if (anonym->rxp>=IMS_FLEN) { // if full sentence received
|
|
anonym->rxbuf[IMS_FLEN]=0;
|
|
|
|
bips(anonym->rxbuf, tmp,IMS_FLEN);
|
|
if(IMSraw2frame(tmp,anonym->frame)){
|
|
decodeframeIMS(m);
|
|
sendIMS(m);
|
|
|
|
}else printf("ERR\n");
|
|
anonym->rxp = 0UL;
|
|
}
|
|
if (anonym->rxp==80UL) {
|
|
anonym->bitlev0 = anonym->bitlev;
|
|
/* save quality before end of shortst frame */
|
|
anonym->noise0 = anonym->noise;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void demodbitIMS(uint32_t m, float u)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct IMS * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct IMS * anonym = &chan[m].ims;
|
|
demodbyteIMS(m, d);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
}
|
|
|
|
|
|
static void demodIMS(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct IMS * anonym;
|
|
{ /* with */
|
|
struct IMS * anonym = &chan[m].ims;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (chan[m].ims.enabled) demodbitIMS(m, u);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
}
|
|
|
|
|
|
/* -------------------------IMS */
|
|
|
|
/* _________________________ATMS */
|
|
|
|
#define ATMS_FLEN 53
|
|
#define CRCATMS 0x8005
|
|
|
|
static void sendATMS(uint32_t m)
|
|
{
|
|
uint32_t i;
|
|
int k;
|
|
struct CHAN * anonym;
|
|
|
|
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].atms.frame[62U] = (char)(anonym->mycallc>>24);
|
|
chan[m].atms.frame[63U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].atms.frame[64U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].atms.frame[65U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].atms.frame[66U] = anonym->myssid;
|
|
chan[m].atms.frame[67U] = 0;
|
|
|
|
chan[m].atms.frame[68U] = chan[m].freq[0];
|
|
chan[m].atms.frame[69U] = chan[m].freq[1];
|
|
chan[m].atms.frame[70U] = chan[m].freq[2];
|
|
chan[m].atms.frame[71U] = chan[m].freq[3];
|
|
chan[m].atms.frame[72U] = chan[m].freq[4];
|
|
chan[m].atms.frame[73U] = chan[m].freq[5];
|
|
}
|
|
alludp(chan[m].udptx, 73UL, chan[m].atms.frame, 73ul);
|
|
///osi_WrStrLn("sending UDP data...",19UL);
|
|
}
|
|
} /* end sendpils() */
|
|
|
|
|
|
|
|
uint16_t crc_atms(const void *data, size_t length) {
|
|
|
|
size_t i, j;
|
|
unsigned int value=0;
|
|
const unsigned char *x = (const unsigned char *)data;
|
|
for(i = 0; i < length; i++) {
|
|
value ^= x[i] << 8;
|
|
for(j = 0; j < 8; j++) {
|
|
if(value & 0x8000)
|
|
value = (value << 1) ^ 0x8005;
|
|
else
|
|
value <<= 1;
|
|
}
|
|
}
|
|
return value ;
|
|
|
|
}
|
|
|
|
static void demodbyteATMS(uint32_t m, char d)
|
|
{
|
|
uint32_t j,t;
|
|
uint32_t i;
|
|
uint32_t revc;
|
|
uint32_t normc;
|
|
uint16_t crc;
|
|
char txtt[100];
|
|
|
|
|
|
char tmp[100],tmp1[100];
|
|
char s[400];
|
|
struct ATMS * anonym;
|
|
{ /* with */
|
|
struct ATMS * anonym = &chan[m].atms;
|
|
if (anonym->rxp==0UL) {
|
|
anonym->synbuf[anonym->synp] = d;
|
|
i = anonym->synp;
|
|
++anonym->synp;
|
|
if (anonym->synp>79UL) anonym->synp = 0UL;
|
|
j = 80UL;
|
|
normc = 0UL;
|
|
revc = 0UL;
|
|
do {
|
|
--j;
|
|
if (("01010101010101010101010101010101010101010101010101010101010101010010110111010100"[j]=='1')==anonym->synbuf[i]) ++normc;
|
|
else ++revc;
|
|
if (i==0UL) i = 79UL;
|
|
else --i;
|
|
} while (!(j==0UL || normc>1UL && revc>1UL));
|
|
anonym->headok = normc==0UL || revc==0UL;
|
|
anonym->rev = normc<revc;
|
|
if (j==0UL) {
|
|
anonym->rxbuf[0UL]=0x45; //fill in first 3 bytes )as we lost it for header
|
|
anonym->rxbuf[1UL]=0xd4; //recovery of first bytes for crc calcs
|
|
anonym->rxp = 2UL;
|
|
}
|
|
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
else {
|
|
anonym->rxbyte = anonym->rxbyte*2UL+1UL*(uint32_t)(d!=anonym->rev);
|
|
++anonym->rxbitc;
|
|
if (anonym->rxbitc>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)((uint8_t)anonym->rxbyte);
|
|
++anonym->rxp;
|
|
if (anonym->rxp>=ATMS_FLEN) { // if full sentence received
|
|
anonym->rxbuf[ATMS_FLEN]=0;
|
|
crc=anonym->rxbuf[ATMS_FLEN-2]<<8|anonym->rxbuf[ATMS_FLEN-1];
|
|
if(crc==crc_atms(anonym->rxbuf+2,ATMS_FLEN-4)){
|
|
|
|
|
|
sendATMS(m);
|
|
for(t=0;t<ATMS_FLEN;t++){
|
|
anonym->frame[t]=anonym->rxbuf[t];
|
|
}
|
|
|
|
int d,m,y,hr,mn,sec;
|
|
float lat,lon,alt;
|
|
uint16_t cnt,tmp,sn;
|
|
uint64_t tmpl;
|
|
|
|
d=anonym->rxbuf[21]; d>>=1; d&=0x1f;
|
|
tmp=(0xff&anonym->rxbuf[22])<<8 | 0xff&anonym->rxbuf[23]; tmp>>=6; y=0x3f&tmp;
|
|
m=anonym->rxbuf[23]; m>>=2; m&=0xf;
|
|
|
|
tmp=(0xff&anonym->rxbuf[21])<<8 | 0xff&anonym->rxbuf[22]; tmp>>=4; hr=0x1f&tmp;
|
|
tmp=(0xff&anonym->rxbuf[23])<<8 | 0xff&anonym->rxbuf[24]; tmp>>=5; mn=0x3f&tmp;
|
|
tmp=(0xff&anonym->rxbuf[24])<<8 | 0xff&anonym->rxbuf[25]; tmp>>=7; sec=0x3f&tmp;
|
|
|
|
tmp=(0xff&anonym->rxbuf[43])<<8 | anonym->rxbuf[44]; cnt=0x07ff&tmp;
|
|
tmpl=(0xff&anonym->rxbuf[29])<<16 | (0xff&anonym->rxbuf[30])<<8 | 0xff&anonym->rxbuf[31]; tmpl>>=5; alt=0xffff&tmpl;
|
|
tmpl=(0xff&anonym->rxbuf[40])<<16 | (0xff&anonym->rxbuf[41])<<8 | 0xff&anonym->rxbuf[42]; tmpl>>=6; sn=0xffff&tmpl;
|
|
|
|
tmpl=0xff&anonym->rxbuf[31]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[32]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[33]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[34]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[35];
|
|
tmpl>>=5;
|
|
tmpl&=0xffffffff;
|
|
int latdeg = (int)tmpl / 1e6;
|
|
float latmin = (float)(tmpl/1e6-latdeg)*100/60.0;
|
|
lat = (float)latdeg+latmin;
|
|
|
|
tmpl=0xff&anonym->rxbuf[35]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[36]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[37]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[38]; tmpl<<=8;
|
|
tmpl|= 0xff&anonym->rxbuf[39];
|
|
tmpl>>=5;
|
|
tmpl&=0xffffffff;
|
|
int londeg = (int)tmpl / 1e6;
|
|
float lonmin = (double)(tmpl/1e6-londeg)*100/60.0;
|
|
lon = (float)londeg+lonmin;
|
|
sprintf(txtt,"AT%02i%05u%02i%02i%02i%02i%02i%02i%05.0f%07.0f%08.0f",y,sn,y,m,d,hr,mn,sec,alt,lat*100000,lon*100000);
|
|
strcpy(anonym->frame,txtt);
|
|
|
|
printf("%02i: AT%02u%05u 20%02i-%02i-%02i %02i:%02i:%02i %5u alt:%f lat:%f lon:%f \n",m,y,sn,y,m,d,hr,mn,sec,cnt,alt,lat,lon);
|
|
|
|
|
|
}
|
|
else printf("CRC ERR\n");
|
|
|
|
anonym->rxp = 0UL;
|
|
}
|
|
if (anonym->rxp==40UL) {
|
|
anonym->bitlev0 = anonym->bitlev;
|
|
/* save quality before end of shortst frame */
|
|
anonym->noise0 = anonym->noise;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void demodbitATMS(uint32_t m, float u)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct ATMS * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct ATMS * anonym = &chan[m].atms;
|
|
// if(d) printf("1"); else printf("0");
|
|
demodbyteATMS(m, d);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
}
|
|
|
|
|
|
static void demodATMS(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct ATMS * anonym;
|
|
{ /* with */
|
|
struct ATMS * anonym = &chan[m].atms;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (chan[m].atms.enabled) demodbitATMS(m, u);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*SKPP --------------------- */
|
|
|
|
static void demodbyteSKPP(uint32_t m, char d)
|
|
{
|
|
|
|
uint32_t cs;
|
|
|
|
struct SKPP * anonym;
|
|
{ /* with */
|
|
struct SKPP * anonym = &chan[m].skpp;
|
|
/*WrInt(ORD(d),1); Flush(); */
|
|
anonym->synword = anonym->synword*2UL+(uint32_t)d;
|
|
if (anonym->rxp>=70UL) {
|
|
if ((anonym->synword&0xfffffff)==0xAA534b50) {
|
|
anonym->rxp = 4UL;
|
|
anonym->rxb = 0UL;
|
|
anonym->rxbuf[0U] = 0xaa;
|
|
anonym->rxbuf[1U] = 0x53;
|
|
anonym->rxbuf[2U] = 0x4b;
|
|
anonym->rxbuf[3U] = 0x50;
|
|
}
|
|
}
|
|
else {
|
|
++anonym->rxb;
|
|
if (anonym->rxb>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)(anonym->synword&0xff);
|
|
anonym->rxb = 0UL;
|
|
++anonym->rxp;
|
|
if (anonym->rxp==SKPFRL)
|
|
cs = (uint32_t)crcm10(SKPFRL-2, anonym->rxbuf, SKPFRL);
|
|
if(cs==m10card(anonym->rxbuf, SKPFRL, SKPFRL-2, 2L))
|
|
alludp(chan[m].udptx, SKPFRL, anonym->rxbuf, SKPFRL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void demodbitSKPP(uint32_t m, float u, float u0)
|
|
{
|
|
char bit;
|
|
char d;
|
|
float ua;
|
|
struct SKPP * anonym;
|
|
/*IF manchestd>20000 THEN */
|
|
/*WrInt(VAL(INTEGER, u), 8); Flush; */
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct SKPP * anonym = &chan[m].skpp;
|
|
/*WrInt(manchestd DIV 256, 1); WrStr("("); WrInt(ORD(lastmanch),1);
|
|
WrInt(ORD(d),1);WrStr(")"); Flush(); */
|
|
/*WrInt(ORD(lastmanch<>d),1); Flush(); */
|
|
/*END; */
|
|
if (anonym->lastmanch==d) {
|
|
anonym->manchestd += (32767L-anonym->manchestd)/16L;
|
|
}
|
|
bit = d!=anonym->lastmanch;
|
|
if (anonym->manchestd>0L) {
|
|
demodbyteSKPP(m, bit);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.02f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.05f;
|
|
}
|
|
/*quality*/
|
|
anonym->lastmanch = d;
|
|
anonym->manchestd = -anonym->manchestd;
|
|
}
|
|
} /* end demodbit10() */
|
|
|
|
|
|
static void demodSKPP(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct SKPP * anonym;
|
|
/*
|
|
IF debfd>=0 THEN
|
|
ui:=VAL(INTEGER, u*0.002);
|
|
WrBin(debfd, ui, 2);
|
|
END;
|
|
*/
|
|
{ /* with */
|
|
struct SKPP * anonym = &chan[m].skpp;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
demodbitSKPP(m, u, anonym->lastu);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
}
|
|
|
|
|
|
static void FskSKPP(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct SKPP * anonym;
|
|
{ /* with */
|
|
struct SKPP * anonym = &chan[m].skpp;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L), 16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demodSKPP(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------SKPP */
|
|
|
|
//-----------------------------------------------------------------------------------------------------
|
|
//PILOTSONDE
|
|
//-----------------------------------------------------------------------------------------------------
|
|
|
|
#define EOF_INT 0x1000000
|
|
int sample_rate = 0, bits_sample = 0;
|
|
unsigned long sample_count = 0;
|
|
double bitgrenze = 0;
|
|
int wlen;
|
|
int *sample_buff = NULL;
|
|
int par=1, par_alt=1;
|
|
|
|
int read_signed_sample(FILE *fp) { // int = i32_t
|
|
int byte, i, sample, s=0; // EOF -> 0x1000000
|
|
|
|
byte = fgetc(fp);
|
|
if (byte == EOF) return EOF_INT;
|
|
if (i == 0) sample = byte;
|
|
|
|
if (bits_sample == 16) {
|
|
byte = fgetc(fp);
|
|
if (byte == EOF) return EOF_INT;
|
|
if (i == 0) sample += byte << 8;
|
|
}
|
|
|
|
|
|
if (bits_sample == 8) s = sample-128; // 8bit: 00..FF, centerpoint 0x80=128
|
|
if (bits_sample == 16) s = (short)sample;
|
|
|
|
sample_count++;
|
|
|
|
return s;
|
|
}
|
|
|
|
int read_filter_sample(FILE *fp) {
|
|
int i; // wenn sample_buff[] ein 8N1-byte umfasst,
|
|
int s0, s, y; // mit (max+min)/2 Mittelwert bestimmen;
|
|
static int min, max; // Glaettung durch lowpass/moving average empfohlen
|
|
|
|
s = read_signed_sample(fp);
|
|
if (s == EOF_INT) return EOF_INT;
|
|
|
|
sample_count--;
|
|
|
|
s0 = sample_buff[sample_count % wlen];
|
|
sample_buff[sample_count % wlen] = s;
|
|
|
|
y = 0;
|
|
if (sample_count > wlen-1) {
|
|
|
|
if (s < min) min = s;
|
|
else {
|
|
if (s0 <= min) {
|
|
min = sample_buff[0];
|
|
for (i = 1; i < wlen; i++) {
|
|
if (sample_buff[i] < min) min = sample_buff[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (s > max) max = s;
|
|
else {
|
|
if (s0 >= max) {
|
|
max = sample_buff[0];
|
|
for (i = 1; i < wlen; i++) {
|
|
if (sample_buff[i] > max) max = sample_buff[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
y = sample_buff[(sample_count+wlen-1)%wlen] - (min+max)/2;
|
|
|
|
}
|
|
else if (sample_count == wlen-1) {
|
|
min = sample_buff[0];
|
|
max = sample_buff[0];
|
|
for (i = 1; i < wlen; i++) {
|
|
if (sample_buff[i] < min) min = sample_buff[i];
|
|
if (sample_buff[i] > max) max = sample_buff[i];
|
|
}
|
|
y = sample_buff[(sample_count+wlen-1)%wlen] - (min+max)/2;
|
|
}
|
|
|
|
sample_count++;
|
|
|
|
return y;
|
|
}
|
|
|
|
int read_bits_fsk(FILE *fp, int *bit, int *len,float samples_per_bit,int option_dc,int option_res,int option_inv) {
|
|
static int sample;
|
|
int n, y0;
|
|
float l, x1;
|
|
static float x0;
|
|
|
|
n = 0;
|
|
do{
|
|
y0 = sample;
|
|
|
|
if (option_dc) sample = read_filter_sample(fp);
|
|
else sample = read_signed_sample(fp);
|
|
|
|
if (sample == EOF_INT) return EOF;
|
|
//sample_count++;
|
|
par_alt = par;
|
|
par = (sample >= 0) ? 1 : -1; // 8bit: 0..127,128..255 (-128..-1,0..127)
|
|
n++;
|
|
} while (par*par_alt > 0);
|
|
|
|
if (!option_res) l = (float)n / samples_per_bit;
|
|
else { // genauere Bitlaengen-Messung
|
|
x1 = sample/(float)(sample-y0); // hilft bei niedriger sample rate
|
|
l = (n+x0-x1) / samples_per_bit; // meist mehr frames (nicht immer)
|
|
x0 = x1;
|
|
}
|
|
|
|
*len = (int)(l+0.5);
|
|
|
|
if (!option_inv) *bit = (1+par_alt)/2; // oben 1, unten -1
|
|
else *bit = (1-par_alt)/2; // sdr#<rev1381?, invers: unten 1, oben -1
|
|
// *bit = (1+inv*par_alt)/2; // ausser inv=0
|
|
|
|
/* Y-offset ? */
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
static void decPIL(){
|
|
|
|
pos = FRAMESTART;
|
|
|
|
while (!read_bits_fsk(fp, &bit, &len)) {
|
|
|
|
if (len == 0) { // reset_frame();
|
|
if (pos > (pos_GPSdate+7)*BITS) {
|
|
for (i = pos; i < BITFRAME_LEN; i++) frame_bits[i] = 0x30 + 0;
|
|
print_frame(pos);//byte_count
|
|
header_found = 0;
|
|
pos = FRAMESTART;
|
|
}
|
|
//inc_bufpos();
|
|
//buf[bufpos] = 'x';
|
|
continue; // ...
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
inc_bufpos();
|
|
buf[bufpos] = 0x30 + bit; // Ascii
|
|
|
|
if (!header_found) {
|
|
header_found = compare2();
|
|
//if (header_found) fprintf(stdout, "[%c] ", header_found>0?'+':'-');
|
|
if (header_found < 0) option_inv ^= 0x1;
|
|
// printf("[%c] ", option_inv?'-':'+');
|
|
}
|
|
else {
|
|
frame_bits[pos] = 0x30 + bit; // Ascii
|
|
pos++;
|
|
|
|
if (pos == BITFRAME_LEN) {
|
|
print_frame(pos);//FRAME_LEN
|
|
header_found = 0;
|
|
pos = FRAMESTART;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (header_found && option_b==1) {
|
|
bitstart = 1;
|
|
|
|
while ( pos < BITFRAME_LEN ) {
|
|
if (read_rawbit(fp, &bit) == EOF) break;
|
|
frame_bits[pos] = 0x30 + bit;
|
|
pos++;
|
|
}
|
|
frame_bits[pos] = '\0';
|
|
print_frame(pos);//FRAME_LEN
|
|
|
|
header_found = 0;
|
|
pos = FRAMESTART;
|
|
}
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
static void sendpils(uint32_t m)
|
|
{
|
|
uint32_t i;
|
|
struct CHAN * anonym;
|
|
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].pils.rxbuf[0U] = (char)(anonym->mycallc>>24);
|
|
chan[m].pils.rxbuf[1U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].pils.rxbuf[2U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].pils.rxbuf[3U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].pils.rxbuf[4U] = anonym->myssid;
|
|
chan[m].pils.rxbuf[5U] = 0;
|
|
chan[m].pils.rxbuf[6U] = 0;
|
|
|
|
chan[m].pils.rxbuf[55U] = chan[m].freq[0];
|
|
chan[m].pils.rxbuf[56U] = chan[m].freq[1];
|
|
chan[m].pils.rxbuf[57U] = chan[m].freq[2];
|
|
chan[m].pils.rxbuf[58U] = chan[m].freq[3];
|
|
chan[m].pils.rxbuf[59U] = chan[m].freq[4];
|
|
chan[m].pils.rxbuf[60U] = chan[m].freq[5];
|
|
}
|
|
alludp(chan[m].udptx, 55UL+6UL, chan[m].pils.rxbuf, 66ul);
|
|
///osi_WrStrLn("sending UDP data...",19UL);
|
|
}
|
|
} /* end sendpils() */
|
|
|
|
static int32_t getint32r(const char frame[], uint32_t frame_len, uint32_t p)
|
|
{
|
|
uint32_t n;
|
|
uint32_t i;
|
|
n = 0UL;
|
|
for (i = 0UL;; i++) {
|
|
n = n*256UL+(uint32_t)(uint8_t)frame[p+i];
|
|
if (i==3UL) break;
|
|
} /* end for */
|
|
return (int32_t)n;
|
|
} /* end getint32() */
|
|
|
|
|
|
static int32_t getint16r(const char frame[], uint32_t frame_len, uint32_t p)
|
|
{
|
|
uint32_t n;
|
|
n = (uint32_t)(uint8_t)frame[p+1UL]+256UL*(uint32_t)(uint8_t)
|
|
frame[p];
|
|
if (n>=32768UL) return (int32_t)(n-65536UL);
|
|
return (int32_t)n;
|
|
} /* end getint16() */
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
//taken from https://github.com/rs1729/RS/blob/master/m10/pilotsonde/m12.c
|
|
|
|
int crc16poly = 0xA001;
|
|
|
|
unsigned int crc16rev(unsigned char bytes[], int len) {
|
|
unsigned int rem = 0xFFFF; // init value: crc(0xAAAAAA;init:0xFFFF)=0x3FAF
|
|
int i, j;
|
|
for (i = 0; i < len; i++) {
|
|
rem = rem ^ bytes[i];
|
|
for (j = 0; j < 8; j++) {
|
|
if (rem & 0x0001) {
|
|
rem = (rem >> 1) ^ crc16poly;
|
|
}
|
|
else {
|
|
rem = (rem >> 1);
|
|
}
|
|
rem &= 0xFFFF;
|
|
}
|
|
}
|
|
return rem;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
static void demodbytepilot(uint32_t m, char d)
|
|
{
|
|
// -- - Modyfikacja na Pilot sonde ==
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t revc;
|
|
uint32_t normc;
|
|
uint32_t cz_1;
|
|
unsigned int crc = 0x0000;
|
|
|
|
uint16_t offs;
|
|
double lat;
|
|
double long0;
|
|
double heig;
|
|
int ok;
|
|
|
|
|
|
struct PILS * anonym;
|
|
|
|
{ /* with */
|
|
|
|
//Look for pilot sonde header
|
|
|
|
struct PILS * anonym = &chan[m].pils;
|
|
if (anonym->rxp==0UL) {
|
|
anonym->synbuf[anonym->synp] = d;
|
|
i = anonym->synp;
|
|
++anonym->synp;
|
|
if (anonym->synp>39UL) anonym->synp = 0UL;
|
|
j = 40UL; //30 bytes in header (3*10)
|
|
normc = 0UL;
|
|
revc = 0UL;
|
|
do {
|
|
--j;
|
|
if (("0010101011001010101100101010110100000001"[j]=='1')==anonym->synbuf[i]) ++normc;
|
|
else ++revc;
|
|
if (i==0UL) i = 39UL;
|
|
else --i;
|
|
} while (!(j==0UL || normc>4UL && revc>4UL));
|
|
anonym->headok = normc==0UL || revc==0UL;
|
|
anonym->rev = normc<revc;
|
|
if (j==0UL) {
|
|
anonym->rxbuf[0UL]=0xAA; //fill in first 3 bytes )as we lost it for header
|
|
anonym->rxbuf[1UL]=0xAA; //recovery of first bytes for crc calcs
|
|
anonym->rxbuf[2UL]=0xAA;
|
|
anonym->rxbuf[3UL]=0x01;
|
|
anonym->rxp = 4UL;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
else {
|
|
//ignore first and last bytes (stop and start) and save remaining bites in reverse order to byte.
|
|
if ((anonym->rxbitc > 0UL) && (anonym->rxbitc < 9UL)) {
|
|
anonym->rxbyte = (anonym->rxbyte>>1UL)+128UL*(uint32_t)(d!=anonym->rev);
|
|
}
|
|
++anonym->rxbitc; //increase bit number
|
|
|
|
if (anonym->rxbitc>=10UL) { // when 10 bits (1+8+1) received
|
|
anonym->rxbuf[anonym->rxp] = (anonym->rxbyte); //save received byte to buffer
|
|
++anonym->rxp; // increase byte number
|
|
if (anonym->rxp>=50UL) { // if full sentence received
|
|
crc = (anonym->rxbuf[48UL]<<8UL) | anonym->rxbuf[49UL];
|
|
if (verb) {
|
|
/* if (maxchannels>0UL) {
|
|
printf("%02i:",m+1);
|
|
}
|
|
*/
|
|
printCnDT(m);
|
|
osi_WrStr("PS ",4UL);
|
|
}
|
|
|
|
if (verb) { //information on signal quality
|
|
WrdB(chan[m].adcmax);
|
|
WrQ(anonym->bitlev0, anonym->noise0);
|
|
Wrtune(chan[m].adcdc, chan[m].adcmax);
|
|
// osi_WrStrLn("",0UL);
|
|
}
|
|
anonym->rxp = 0UL;
|
|
|
|
|
|
offs=6UL; //offset - for first position
|
|
lat=(double)getint32r(anonym->rxbuf,55UL,offs)*0.000001;
|
|
long0=(double)getint32r(anonym->rxbuf,55UL,offs+4UL)*0.000001;
|
|
heig=(double)getint32r(anonym->rxbuf,55UL,offs+8UL)*.01;
|
|
cnt++;
|
|
|
|
|
|
if (crc == crc16rev(anonym->rxbuf, 48UL) && lat>0 && lat<89.9 && long0>0 && long0<179.9 && heig>1 && heig<35000) {
|
|
anonym->poklat=lat;
|
|
anonym->poklon=long0;
|
|
anonym->pokalt=heig;
|
|
anonym->lastfr=time(NULL);
|
|
//if (verb) osi_WrStr(" CRC [OK+] ",12UL);
|
|
if (verb) { //if more verbous print lat/long/h
|
|
pok++;
|
|
osi_WrStrLn("",0UL);
|
|
osi_WrStr(" Lat=",5ul);
|
|
osic_WrFixed((float)(lat), 6L, 1UL);
|
|
osi_WrStr(" Long=", 6ul);
|
|
osic_WrFixed((float)(long0), 6L, 1UL);
|
|
osi_WrStr(" height=", 9ul);
|
|
osic_WrFixed((float)heig, 1L, 1UL);
|
|
osi_WrStrLn("m ", 3ul);
|
|
printf("BR: %li:%li\r\n",anonym->configbaud,anonym->baudfine);
|
|
}
|
|
for (cz_1 = 49UL; cz_1>1UL; cz_1--) {anonym->rxbuf[cz_1+5UL] = anonym->rxbuf[cz_1];} //move cells by 5 up
|
|
sendpils(m);
|
|
} //crc ok
|
|
else {
|
|
if (verb) osi_WrStrLn(" parity error",14UL);
|
|
//if position not too far from last good one....
|
|
|
|
ok=0;
|
|
if(time(NULL)-anonym->lastfr<=60){
|
|
if ((fabs(anonym->poklat-lat)<0.003f) && (fabs(anonym->poklon-long0)<0.003f) && (abs(anonym->pokalt-heig)<1500))
|
|
ok=1;
|
|
}else if ((time(NULL)-anonym->lastfr>60) && (time(NULL)-anonym->lastfr<=1800)){
|
|
if ((fabs(anonym->poklat-lat)<0.03f) && (fabs(anonym->poklon-long0)<0.03f) && (abs(anonym->pokalt-heig)<4500))
|
|
ok=1;
|
|
}
|
|
|
|
if (ok || (anonym->poklat==-1 && anonym->poklon==-1 && lat>0 && lat<89.9 && long0>0 && long0<179.9 && heig>1 && heig<35000)) {
|
|
|
|
anonym->poklat=(lat+anonym->poklat)/2;
|
|
anonym->poklon=(long0+anonym->poklon)/2;
|
|
anonym->pokalt=(heig+anonym->pokalt)/2;
|
|
anonym->lastfr=time(NULL);
|
|
|
|
if (verb) {
|
|
nok++;
|
|
osi_WrStr(" !Lat=",6ul);
|
|
osic_WrFixed((float)(lat), 6L, 1UL);
|
|
osi_WrStr(" !Long=", 7ul);
|
|
osic_WrFixed((float)(long0), 6L, 1UL);
|
|
osi_WrStr(" !height=", 10ul);
|
|
osic_WrFixed((float)heig, 1L, 1UL);
|
|
osi_WrStr("m ", 3ul);
|
|
printf("***BR: %li:%li\r\n",anonym->configbaud,anonym->baudfine);
|
|
}
|
|
|
|
for (cz_1 = 49UL; cz_1>1UL; cz_1--) {anonym->rxbuf[cz_1+5UL] = anonym->rxbuf[cz_1];} //move cells by 5 up
|
|
sendpils(m); //send data to sondemod
|
|
}
|
|
}
|
|
// printf("OK: %u, NOK:%u, CNT:%u CAL:%u\r\n",pok,nok,cnt,(unsigned int)(100*pok/nok));
|
|
}
|
|
|
|
if (anonym->rxp==48UL) {
|
|
anonym->bitlev0 = anonym->bitlev;
|
|
/* save quality before end of shortst frame */
|
|
anonym->noise0 = anonym->noise;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbytepilot() */
|
|
|
|
static void demodbitpilot(uint32_t m, float u)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct PILS * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct PILS * anonym = &chan[m].pils;
|
|
demodbytepilot(m, d);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
/*quality*/
|
|
} /* end demodbitpilot() */
|
|
|
|
|
|
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
//-----------------------------------------------------------------------------------------------------
|
|
//PILOTSONDE
|
|
//
|
|
//-----------------------------------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------------------------------
|
|
|
|
|
|
static void posrs41(const char b[], uint32_t b_len, uint32_t p)
|
|
{
|
|
double dir;
|
|
double vu;
|
|
double ve;
|
|
double vn;
|
|
double vz;
|
|
double vy;
|
|
double vx;
|
|
double heig;
|
|
double long0;
|
|
double lat;
|
|
double z;
|
|
double y;
|
|
double x;
|
|
x = (double)getint32(b, b_len, p)*0.01;
|
|
y = (double)getint32(b, b_len, p+4UL)*0.01;
|
|
z = (double)getint32(b, b_len, p+8UL)*0.01;
|
|
wgs84r(x, y, z, &lat, &long0, &heig);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)(X2C_DIVL(lat,1.7453292519943E-2)), 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)(X2C_DIVL(long0,1.7453292519943E-2)), 5L, 1UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)heig, 0L, 1UL);
|
|
osi_WrStr("m ", 3ul);
|
|
/*speed */
|
|
vx = (double)getint16(b, b_len, p+12UL)*0.01;
|
|
vy = (double)getint16(b, b_len, p+14UL)*0.01;
|
|
vz = (double)getint16(b, b_len, p+16UL)*0.01;
|
|
vn = (-(vx*(double)osic_sin((float)lat)*(double)
|
|
osic_cos((float)long0))-vy*(double)
|
|
osic_sin((float)lat)*(double)osic_sin((float)
|
|
long0))+vz*(double)osic_cos((float)lat);
|
|
ve = -(vx*(double)osic_sin((float)long0))+vy*(double)
|
|
osic_cos((float)long0);
|
|
vu = vx*(double)osic_cos((float)lat)*(double)
|
|
osic_cos((float)long0)+vy*(double)
|
|
osic_cos((float)lat)*(double)osic_sin((float)
|
|
long0)+vz*(double)osic_sin((float)lat);
|
|
dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2);
|
|
if (dir<0.0) dir = 360.0+dir;
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed(osic_sqrt((float)(vn*vn+ve*ve))*3.6f, 1L, 1UL);
|
|
osi_WrStr("km/h ", 6ul);
|
|
osic_WrFixed((float)dir, 0L, 1UL);
|
|
osi_WrStr("deg ", 5ul);
|
|
osic_WrFixed((float)vu, 1L, 1UL);
|
|
osi_WrStr("m/s", 4ul);
|
|
} /* end posrs41() */
|
|
|
|
|
|
static int32_t reedsolomon41(char buf[], uint32_t buf_len,
|
|
uint32_t len2)
|
|
{
|
|
uint32_t i;
|
|
int32_t res1;
|
|
/*tb1, */
|
|
int32_t res;
|
|
char b1[256];
|
|
char b[256];
|
|
uint32_t eraspos[24];
|
|
uint32_t tmp;
|
|
for (i = 0UL; i<=255UL; i++) {
|
|
b[i] = 0;
|
|
b1[i] = 0;
|
|
} /* end for */
|
|
tmp = len2;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
b[230UL-i] = buf[i*2UL+56UL];
|
|
b1[230UL-i] = buf[i*2UL+57UL];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
b[254UL-i] = buf[i+8UL];
|
|
b1[254UL-i] = buf[i+32UL];
|
|
} /* end for */
|
|
/*tb1:=b; */
|
|
res = decodersc(b, eraspos, 0L);
|
|
/*FOR i:=0 TO HIGH(b) DO */
|
|
/*IF tb1[i]<>b[i] THEN WrHex(ORD(tb1[i]),4);WrHex(ORD(b[i]),4);
|
|
WrInt(i, 4); WrStr("=pos "); END; */
|
|
/*END; */
|
|
/*tb1:=b1; */
|
|
res1 = decodersc(b1, eraspos, 0L);
|
|
/*FOR i:=0 TO HIGH(b) DO */
|
|
/*IF tb1[i]<>b1[i] THEN WrHex(ORD(tb1[i]),4);WrHex(ORD(b1[i]),4);
|
|
WrInt(i, 4); WrStr("=pos1 "); END; */
|
|
/*END; */
|
|
if (res>0L && res<=12L) {
|
|
tmp = len2;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
buf[i*2UL+56UL] = b[230UL-i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
buf[i+8UL] = b[254UL-i];
|
|
} /* end for */
|
|
}
|
|
if (res1>0L && res1<=12L) {
|
|
tmp = len2;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
buf[i*2UL+57UL] = b1[230UL-i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
for (i = 0UL; i<=23UL; i++) {
|
|
buf[i+32UL] = b1[254UL-i];
|
|
} /* end for */
|
|
}
|
|
if (res<0L || res1<0L) return -1L;
|
|
else return res+res1;
|
|
return 0;
|
|
} /* end reedsolomon41() */
|
|
|
|
static uint16_t sondeudp_POLYNOM0 = 0x1021U;
|
|
|
|
|
|
static void decode41(uint32_t m)
|
|
{
|
|
uint32_t try0;
|
|
uint32_t posok;
|
|
uint32_t nameok;
|
|
uint32_t len;
|
|
uint32_t p;
|
|
uint32_t i;
|
|
char ch;
|
|
char typ;
|
|
char aux;
|
|
char allok;
|
|
int32_t repl;
|
|
int32_t corr;
|
|
struct R41 * anonym;
|
|
uint32_t tmp;
|
|
{ /* with */
|
|
struct R41 * anonym = &chan[m].r41;
|
|
try0 = 0UL;
|
|
do {
|
|
allok = 1;
|
|
nameok = 0UL;
|
|
posok = 0UL;
|
|
corr = 0L;
|
|
repl = 0L;
|
|
if (try0>0UL) {
|
|
if (try0>1UL) {
|
|
for (i = 0UL; i<=519UL; i++) {
|
|
if (anonym->fixcnt[i]>=10U) {
|
|
/* replace stable bytes */
|
|
anonym->rxbuf[i] = anonym->fixbytes[i];
|
|
++repl;
|
|
}
|
|
} /* end for */
|
|
}
|
|
corr = reedsolomon41(anonym->rxbuf, 520ul, 131UL);
|
|
/* try short frame */
|
|
if (corr<0L) {
|
|
corr = reedsolomon41(anonym->rxbuf, 520ul, 230UL);
|
|
/* may bo long frame */
|
|
}
|
|
}
|
|
p = 57UL;
|
|
aux = 0;
|
|
for (;;) {
|
|
if (p+4UL>=519UL) break;
|
|
typ = anonym->rxbuf[p];
|
|
++p;
|
|
len = (uint32_t)(uint8_t)anonym->rxbuf[p]+2UL;
|
|
++p;
|
|
if (p+len>=519UL) break;
|
|
/*
|
|
WrStrLn("");
|
|
FOR i:=0 TO len+1 DO WrHex(ORD(rxbuf[p+i-2]),3) ;
|
|
IF i MOD 16=15 THEN WrStrLn(""); END; END;
|
|
WrStrLn("");
|
|
*/
|
|
if (!crcrs(anonym->rxbuf, 520ul, (int32_t)p,(int32_t)(p+len))) {
|
|
/* crc error */
|
|
allok = 0;
|
|
break;
|
|
}
|
|
if (verb2) {
|
|
osi_WrStrLn("", 1ul);
|
|
osi_WrStrLn("", 1ul);
|
|
osi_WrStr("start ID length data... crc [", 30ul);
|
|
osi_WrHex((p-2UL)/256UL, 0UL);
|
|
osi_WrHex(p-2UL, 3UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[p-2UL], 3UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[p-1UL], 0UL);
|
|
osi_WrStrLn("]", 2ul);
|
|
tmp = len-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[p+i], 3UL);
|
|
if ((i&15UL)==15UL) osi_WrStrLn("", 1ul);
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
osi_WrStrLn("", 1ul);
|
|
osi_WrStrLn("", 1ul);
|
|
}
|
|
tmp = (p+len)-1UL;
|
|
i = p-2UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
/* update fixbyte statistics */
|
|
if (anonym->fixbytes[i]==anonym->rxbuf[i]) {
|
|
if (anonym->fixcnt[i]<255U) ++anonym->fixcnt[i];
|
|
}
|
|
else {
|
|
anonym->fixbytes[i] = anonym->rxbuf[i];
|
|
anonym->fixcnt[i] = 0U;
|
|
}
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
if (typ=='y') nameok = p;
|
|
else if (typ=='{') {
|
|
/* ELSIF typ=CHR(7AH) THEN */
|
|
/* WrStrLn("7A frame"); */
|
|
/* ELSIF typ=CHR(7CH) THEN */
|
|
/* WrStrLn("7C frame"); */
|
|
/*WrInt(getint32(rxbuf, p+2) DIV 1000 MOD 86400 , 10);
|
|
WrStr("=gpstime "); */
|
|
/* ELSIF typ=CHR(7DH) THEN */
|
|
/* WrStrLn("7D frame"); */
|
|
posok = p;
|
|
}
|
|
else if (typ=='~') aux = 1;
|
|
/* ELSIF typ=CHR(76H) THEN */
|
|
/* WrStrLn("76 frame"); */
|
|
/* ELSE EXIT END; */
|
|
/* WrInt(getint16(rxbuf, 3BH), 0); */
|
|
/* WrStr(" ");WrHex(ORD(typ), 0);WrStr(" ");
|
|
WrHex(p DIV 256, 0);WrHex(p, 0); */
|
|
/* WrStr(" "); */
|
|
if (typ=='v') break;
|
|
p += len;
|
|
}
|
|
++try0;
|
|
} while (!(allok || try0>2UL));
|
|
if (verb && nameok>0UL) {
|
|
if (maxchannels>0UL) {
|
|
printCnDT(m);
|
|
}
|
|
osi_WrStr("R41 ", 5ul);
|
|
for (i = 0UL; i<=7UL; i++) {
|
|
ch = anonym->rxbuf[nameok+2UL+i];
|
|
if ((uint8_t)ch>' ' && (uint8_t)ch<'\177') {
|
|
osi_WrStr((char *) &ch, 1u/1u);
|
|
}
|
|
} /* end for */
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrINT32((uint32_t)getint16(anonym->rxbuf, 520ul, nameok),
|
|
1UL);
|
|
if (posok>0UL) posrs41(anonym->rxbuf, 520ul, posok);
|
|
if (anonym->rxbuf[nameok+23UL]==0) {
|
|
osi_WrStr(" ", 2ul);
|
|
osic_WrFixed((float)(getcard16(anonym->rxbuf, 520ul,
|
|
nameok+26UL)/64UL+40000UL)*0.01f, 2L, 1UL);
|
|
osi_WrStr("MHz", 4ul);
|
|
}
|
|
if (aux) osi_WrStr(" +Aux", 6ul);
|
|
if (!((allok || posok>0UL) || aux)) {
|
|
osi_WrStr(" ---- crc err ", 16ul);
|
|
}
|
|
WrdB(chan[m].adcmax);
|
|
WrQ(anonym->bitlev0, anonym->noise0);
|
|
/*WrStrLn(""); */
|
|
/*FOR i:=0 TO HIGH(rxbuf) DO WrHex(ORD(rxbuf[i]),3) ;
|
|
IF i MOD 16=15 THEN WrStrLn(""); END; END; */
|
|
if (repl>0L) {
|
|
osi_WrStr(" x", 3ul);
|
|
osic_WrINT32((uint32_t)repl, 1UL);
|
|
}
|
|
if (corr<0L) osi_WrStr(" -R", 4ul);
|
|
else if (corr>0L) {
|
|
osi_WrStr(" +", 3ul);
|
|
osic_WrINT32((uint32_t)corr, 1UL);
|
|
osi_WrStr("R", 2ul);
|
|
}
|
|
Wrtune(chan[m].adcdc, chan[m].adcmax);
|
|
osi_WrStrLn("", 1ul);
|
|
// printf("BR: %li:%li\r\n",anonym->configbaud,anonym->baudfine);
|
|
}
|
|
}
|
|
// printf("NAMEOK:%i\n",nameok);
|
|
if (allok)
|
|
sendrs41(m);
|
|
} /* end decode41() */
|
|
|
|
#define sondeudp_MAXHEADERR 4
|
|
|
|
static uint8_t _cnst[64] = {150U,131U,62U,81U,177U,73U,8U,152U,50U,5U,89U,
|
|
14U,249U,68U,198U,38U,33U,96U,194U,234U,121U,93U,109U,161U,
|
|
84U,105U,71U,12U,220U,232U,92U,241U,247U,118U,130U,127U,7U,
|
|
153U,162U,44U,147U,124U,48U,99U,245U,16U,46U,97U,208U,188U,
|
|
180U,182U,6U,170U,244U,35U,120U,110U,59U,174U,191U,123U,76U,
|
|
193U};
|
|
|
|
static void demodbyte41(uint32_t m, char d)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t revc;
|
|
uint32_t normc;
|
|
/*WrStr(CHR(ORD(d)+48)); */
|
|
struct R41 * anonym;
|
|
{ /* with */
|
|
struct R41 * anonym = &chan[m].r41;
|
|
if (anonym->rxp==0UL) {
|
|
anonym->synbuf[anonym->synp] = d;
|
|
i = anonym->synp;
|
|
++anonym->synp;
|
|
if (anonym->synp>63UL) anonym->synp = 0UL;
|
|
j = 56UL;
|
|
normc = 0UL;
|
|
revc = 0UL;
|
|
do {
|
|
--j;
|
|
if (("0000100001101101010100111000100001000100011010010100100000011111"[j]=='1')==anonym->synbuf[i]) ++normc;
|
|
else ++revc;
|
|
if (i==0UL) i = 63UL;
|
|
else --i;
|
|
} while (!(j==24UL || normc>4UL && revc>4UL));
|
|
anonym->headok = normc==0UL || revc==0UL;
|
|
anonym->rev = normc<revc;
|
|
if (j==24UL) anonym->rxp = 7UL;
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
else {
|
|
anonym->rxbyte = anonym->rxbyte/2UL+128UL*(uint32_t)
|
|
(d!=anonym->rev);
|
|
++anonym->rxbitc;
|
|
if (anonym->rxbitc>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (char)((uint8_t)
|
|
anonym->rxbyte^(uint8_t)_cnst[anonym->rxp&63UL]);
|
|
++anonym->rxp;
|
|
if (anonym->rxp>=519UL) {
|
|
decode41(m);
|
|
anonym->rxp = 0UL;
|
|
}
|
|
if (anonym->rxp==200UL) {
|
|
anonym->bitlev0 = anonym->bitlev;
|
|
/* save quality before end of shortst frame */
|
|
anonym->noise0 = anonym->noise;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbyte41() */
|
|
|
|
|
|
static void demodbit41(uint32_t m, float u)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct R41 * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct R41 * anonym = &chan[m].r41;
|
|
demodbyte41(m, d);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
/*quality*/
|
|
} /* end demodbit41() */
|
|
|
|
|
|
|
|
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
|
#define BYTE_TO_BINARY(byte) \
|
|
(byte & 0x80 ? '1' : '0'), \
|
|
(byte & 0x40 ? '1' : '0'), \
|
|
(byte & 0x20 ? '1' : '0'), \
|
|
(byte & 0x10 ? '1' : '0'), \
|
|
(byte & 0x08 ? '1' : '0'), \
|
|
(byte & 0x04 ? '1' : '0'), \
|
|
(byte & 0x02 ? '1' : '0'), \
|
|
(byte & 0x01 ? '1' : '0')
|
|
|
|
unsigned char reverse(unsigned char b) {
|
|
|
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
uint16_t crc_mp3(uint8_t buf[], int st,int len)
|
|
{
|
|
uint16_t crc = 0xFFFF;
|
|
|
|
for (int pos = st; pos < len; pos++) {
|
|
crc ^= (uint16_t)buf[pos]; // XOR byte into least sig. byte of crc
|
|
|
|
for (int i = 8; i != 0; i--) { // Loop over each bit
|
|
if ((crc & 0x0001) != 0) { // If the LSB is set
|
|
crc >>= 1; // Shift right and XOR 0xA001
|
|
crc ^= 0xA001;
|
|
}
|
|
else // Else LSB is not set
|
|
crc >>= 1; // Just shift right
|
|
}
|
|
}
|
|
// Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
|
|
return crc;
|
|
}
|
|
|
|
static void sendmp3(uint32_t m)
|
|
{
|
|
uint32_t i;
|
|
struct CHAN * anonym;
|
|
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[m];
|
|
if (anonym->mycallc>0UL) {
|
|
chan[m].mp3.rxbuf[103U] = (char)(anonym->mycallc>>24);
|
|
chan[m].mp3.rxbuf[104U] = (char)(anonym->mycallc>>16&255UL);
|
|
chan[m].mp3.rxbuf[105U] = (char)(anonym->mycallc>>8&255UL);
|
|
chan[m].mp3.rxbuf[106U] = (char)(anonym->mycallc&255UL);
|
|
chan[m].mp3.rxbuf[107U] = anonym->myssid;
|
|
chan[m].mp3.rxbuf[108U] = 0;
|
|
|
|
chan[m].mp3.rxbuf[109U] = chan[m].freq[0];
|
|
chan[m].mp3.rxbuf[110U] = chan[m].freq[1];
|
|
chan[m].mp3.rxbuf[111U] = chan[m].freq[2];
|
|
chan[m].mp3.rxbuf[112U] = chan[m].freq[3];
|
|
chan[m].mp3.rxbuf[113U] = chan[m].freq[4];
|
|
chan[m].mp3.rxbuf[114U] = chan[m].freq[5];
|
|
}
|
|
alludp(chan[m].udptx, 115UL, chan[m].mp3.rxbuf, 115ul);
|
|
///osi_WrStrLn("sending UDP data...",19UL);
|
|
}
|
|
} /* end sendpils() */
|
|
|
|
|
|
|
|
static void demodbytemp3(uint32_t m, char d)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t revc;
|
|
uint32_t normc;
|
|
uint32_t cz_1;
|
|
unsigned int crc = 0x0000;
|
|
uint16_t offs;
|
|
double lat;
|
|
double long0;
|
|
double heig;
|
|
int ok;
|
|
|
|
struct MP3 * anonym;
|
|
{
|
|
struct MP3 * anonym = &chan[m].mp3;
|
|
if (anonym->rxp==0UL) {
|
|
anonym->synbuf[anonym->synp] = d;
|
|
i = anonym->synp;
|
|
++anonym->synp;
|
|
if (anonym->synp>47UL) anonym->synp = 0UL;
|
|
j = 48UL;
|
|
normc = 0UL;
|
|
revc = 0UL;
|
|
do {
|
|
--j;
|
|
if (("011001100110011001100110011001100110010101010101"[j]=='1')==anonym->synbuf[i]) ++normc;
|
|
else ++revc;
|
|
if (i==0UL) i = 47UL;
|
|
else --i;
|
|
} while (!(j==0UL || normc>1UL && revc>1UL));
|
|
anonym->headok = normc==0UL || revc==0UL;
|
|
anonym->rev = normc<revc;
|
|
if (j==0UL) {
|
|
anonym->rxbuf[0UL]=0b10011001;
|
|
anonym->rxbuf[1UL]=0b10011001;
|
|
anonym->rxbuf[2UL]=0b10011001;
|
|
anonym->rxbuf[3UL]=0b10011001;
|
|
anonym->rxbuf[4UL]=0b10011010;
|
|
anonym->rxbuf[5UL]=0b10101010;
|
|
anonym->rxp = 6UL;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
else {
|
|
uint8_t tmpD[155];
|
|
anonym->rxbyte = anonym->rxbyte/2UL+128UL*(uint32_t)
|
|
(d!=anonym->rev);
|
|
++anonym->rxbitc;
|
|
|
|
if (anonym->rxbitc>=8UL) {
|
|
anonym->rxbuf[anonym->rxp] = (anonym->rxbyte);
|
|
++anonym->rxp;
|
|
int ntsf=0;
|
|
|
|
if (anonym->rxp>=102UL) {
|
|
int s,q,p;
|
|
uint16_t tmpb;
|
|
p=0;
|
|
for(s=0;s<102;s+=2){
|
|
tmpb=0;
|
|
tmpb=(anonym->rxbuf[s]&0xff)<<8 | (anonym->rxbuf[s+1]&0xff);
|
|
tmpD[p]=0;
|
|
for(q=0;q<8;q++){
|
|
tmpD[p]<<=1;
|
|
if((tmpb & 0xC000) == 0x8000) {
|
|
tmpD[p]|=1;
|
|
}
|
|
|
|
switch(tmpb & 0xC000){
|
|
case 0xC000:
|
|
case 0x0000:
|
|
anonym->rxp = 0UL; anonym->rxbitc = 0UL;
|
|
break;
|
|
}
|
|
tmpb<<=2;
|
|
}
|
|
p++;
|
|
}
|
|
for(s=0;s<51;s++){
|
|
uint8_t calc,t1,t2;
|
|
calc=reverse(tmpD[s]&0xff);
|
|
t1=calc>>4 &0b00001111;
|
|
t2=calc<<4 &0b11110000;
|
|
calc=0;calc=t1|t2;
|
|
tmpD[s]=calc;
|
|
}
|
|
uint16_t crc=tmpD[49] | tmpD[50]<<8;
|
|
if(crc==crc_mp3(&tmpD,4,49)){
|
|
sendmp3(m);
|
|
}
|
|
else
|
|
printf("MP3 CRC ERR\n");
|
|
anonym->rxp = 0UL;
|
|
}
|
|
if (anonym->rxp==50UL) {
|
|
anonym->bitlev0 = anonym->bitlev;
|
|
anonym->noise0 = anonym->noise;
|
|
}
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbytemp3() */
|
|
|
|
|
|
|
|
static void demodbitmp3(uint32_t m, float u)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct MP3 * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct MP3 * anonym = &chan[m].mp3;
|
|
demodbytemp3(m, d);
|
|
/*quality*/
|
|
ua = (float)fabs(u)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
/*quality*/
|
|
} /* end demodbitmp3() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*------------------------------ RS92 */
|
|
/*
|
|
PROCEDURE stobyte92(m:CARDINAL; b:CHAR);
|
|
VAR e:SET8;
|
|
BEGIN
|
|
WITH chan[m].r92 DO
|
|
rxbuf[rxp]:=b;
|
|
IF rxp<5 THEN
|
|
e:=CAST(SET8, b)/CAST(SET8, 2AH);
|
|
WHILE e<>SET8{} DO
|
|
IF e*SET8{0}<>SET8{} THEN INC(headerrs) END;
|
|
e:=SHIFT(e, -1);
|
|
END;
|
|
IF headerrs>rxp THEN (* allow 0 bit errors on first byte *)
|
|
headerrs:=0;
|
|
rxp:=0;
|
|
ELSE INC(rxp) END;
|
|
ELSE INC(rxp) END;
|
|
IF rxp>=240 THEN
|
|
headerrs:=0;
|
|
rxp:=0;
|
|
decodeframe92(m);
|
|
END;
|
|
END;
|
|
END stobyte92;
|
|
*/
|
|
|
|
static void stobyte92(uint32_t m, char b)
|
|
{
|
|
struct R92 * anonym;
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[m].r92;
|
|
anonym->rxbuf[anonym->rxp] = b;
|
|
if (anonym->rxp>=5UL || b=='*') ++anonym->rxp;
|
|
else anonym->rxp = 0UL;
|
|
if (anonym->rxp>=240UL) {
|
|
anonym->rxp = 0UL;
|
|
decodeframe92(m);
|
|
}
|
|
}
|
|
} /* end stobyte92() */
|
|
|
|
|
|
static void demodbyte92(uint32_t m, char d)
|
|
{
|
|
uint32_t maxi;
|
|
uint32_t i;
|
|
int32_t max0;
|
|
int32_t n;
|
|
struct R92 * anonym;
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[m].r92;
|
|
anonym->rxbyte = anonym->rxbyte/2UL+256UL*(uint32_t)d;
|
|
max0 = 0L;
|
|
maxi = 0UL;
|
|
for (i = 0UL; i<=9UL; i++) {
|
|
n = anonym->asynst[i]-anonym->asynst[(i+1UL)%10UL];
|
|
if (labs(n)>labs(max0)) {
|
|
max0 = n;
|
|
maxi = i;
|
|
}
|
|
} /* end for */
|
|
if (anonym->rxbitc==maxi) {
|
|
if (max0<0L) {
|
|
anonym->rxbyte = (uint32_t)((uint32_t)anonym->rxbyte^0xFFUL);
|
|
}
|
|
stobyte92(m, (char)(anonym->rxbyte&255UL));
|
|
}
|
|
if (d) {
|
|
anonym->asynst[anonym->rxbitc]
|
|
+= (32767L-anonym->asynst[anonym->rxbitc])/16L;
|
|
}
|
|
else {
|
|
anonym->asynst[anonym->rxbitc]
|
|
-= (32767L+anonym->asynst[anonym->rxbitc])/16L;
|
|
}
|
|
anonym->rxbitc = (anonym->rxbitc+1UL)%10UL;
|
|
}
|
|
/*FOR i:=0 TO HIGH(asynst) DO WrInt(asynst[i], 8) END; WrStrLn(""); */
|
|
} /* end demodbyte92() */
|
|
|
|
|
|
static void demodbit92(uint32_t m, float u, float u0)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct R92 * anonym;
|
|
d = u>=u0;
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[m].r92;
|
|
if (anonym->lastmanch==u0<0.0f) {
|
|
anonym->manchestd += (32767L-anonym->manchestd)/16L;
|
|
}
|
|
anonym->lastmanch = d;
|
|
anonym->manchestd = -anonym->manchestd;
|
|
/*WrInt(manchestd,8); */
|
|
if (anonym->manchestd<0L) {
|
|
demodbyte92(m, d);
|
|
/*WrInt(VAL(INTEGER, u0*0.001), 4); WrStr("/");
|
|
WrInt(VAL(INTEGER, u*0.001), 0); */
|
|
/*quality*/
|
|
ua = (float)fabs(u-u0)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
}
|
|
/*quality*/
|
|
} /* end demodbit92() */
|
|
|
|
|
|
static void demod92(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct R92 * anonym;
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[m].r92;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (anonym->enabled) demodbit92(m, u, anonym->lastu);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demod92() */
|
|
|
|
|
|
static void demod41(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct R41 * anonym;
|
|
{ /* with */
|
|
struct R41 * anonym = &chan[m].r41;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (chan[m].r41.enabled) demodbit41(m, u);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demod41() */
|
|
|
|
|
|
static void demodMP3(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct MP3 * anonym;
|
|
{ /* with */
|
|
struct MP3 * anonym = &chan[m].mp3;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (chan[m].mp3.enabled) demodbitmp3(m, u);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demodmp3() */
|
|
|
|
|
|
|
|
static void demodPS(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct PILS * anonym;
|
|
{ /* with */
|
|
struct PILS * anonym = &chan[m].pils;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
if (chan[m].pils.enabled) demodbitpilot(m, u);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demodPS() */
|
|
|
|
|
|
|
|
|
|
static void Fsk(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct R92 * anonym;
|
|
{ /* with */
|
|
struct R92 * anonym = &chan[m].r92;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
//static float Fir(uint32_t in, uint32_t sub, uint32_t step, float fir[], uint32_t fir_len, float firtab[], uint32_t firtab_len)
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L),16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demod92(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk() */
|
|
|
|
|
|
static void Fsk41(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct R41 * anonym;
|
|
{ /* with */
|
|
struct R41 * anonym = &chan[m].r41;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afinR41, (uint32_t)((anonym->baudfine&65535L)/4096L),16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demod41(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk() */
|
|
|
|
static void FskMP3(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct MP3 * anonym;
|
|
{ /* with */
|
|
struct MP3 * anonym = &chan[m].mp3;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afinMP3, (uint32_t)((anonym->baudfine&65535L)/4096L),16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demodMP3(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end FskMP3() */
|
|
|
|
|
|
static void FskPS(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct PILS * anonym;
|
|
{
|
|
struct PILS * anonym = &chan[m].pils;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afinPS, (uint32_t)((anonym->baudfine&65535L)/4096L),16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demodPS(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} // end Fsk()
|
|
|
|
|
|
static void Fsk10(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct M10 * anonym;
|
|
{ /* with */
|
|
struct M10 * anonym = &chan[m].m10;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L), 16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demod10(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk10() */
|
|
|
|
static void Fsk20(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct M20 * anonym;
|
|
{ /* with */
|
|
struct M20 * anonym = &chan[m].m20;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L), 16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demod20(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk10() */
|
|
|
|
static void FskIMS(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct IMS * anonym;
|
|
{ /* with */
|
|
struct IMS * anonym = &chan[m].ims;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L), 16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demodIMS(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk10() */
|
|
|
|
static void FskATMS(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct ATMS * anonym;
|
|
{ /* with */
|
|
struct ATMS * anonym = &chan[m].atms;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L), 16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demodATMS(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk10() */
|
|
|
|
|
|
/*------------------------------ DFM06 */
|
|
|
|
static void deinterleave(const char b[], uint32_t b_len,
|
|
uint32_t base, uint32_t len, char db[],
|
|
uint32_t db_len)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t tmp;
|
|
for (j = 0UL; j<=7UL; j++) {
|
|
tmp = len-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
db[i*8UL+j] = b[base+len*j+i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
} /* end for */
|
|
} /* end deinterleave() */
|
|
|
|
|
|
static char hamcorr(char b[], uint32_t b_len, uint32_t d,
|
|
uint32_t h)
|
|
{
|
|
uint32_t e;
|
|
e = (uint32_t)((b[d]==b[d+2UL])!=(b[h]==b[h+2UL]))+2UL*(uint32_t)
|
|
((b[d+1UL]==b[d+2UL])!=(b[h+1UL]==b[h+2UL]))+4UL*(uint32_t)
|
|
((b[d+3UL]==b[h])!=(b[h+1UL]==b[h+2UL]));
|
|
/* hamming matrix multiplication */
|
|
if (e>4UL) b[(h+e)-4UL] = !b[(h+e)-4UL];
|
|
else if (e>0UL) b[(d+e)-1UL] = !b[(d+e)-1UL];
|
|
/* IF e<>0 THEN WrStr("<");WrInt(e, 1);WrStr(">") END; */
|
|
e = (uint32_t)b[d]+(uint32_t)b[d+1UL]+(uint32_t)
|
|
b[d+2UL]+(uint32_t)b[d+3UL]+(uint32_t)b[h]+(uint32_t)
|
|
b[h+1UL]+(uint32_t)b[h+2UL]+(uint32_t)b[h+3UL];
|
|
return !(e&1);
|
|
/* 1 bit checksum */
|
|
} /* end hamcorr() */
|
|
|
|
|
|
static char hamming(const char b[], uint32_t b_len, uint32_t len, char db[], uint32_t db_len)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t tmp;
|
|
tmp = db_len-1;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
db[i] = 0;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
tmp = len-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
for (j = 0UL; j<=3UL; j++) {
|
|
db[i*4UL+j] = b[i*8UL+j];
|
|
} /* end for */
|
|
for (j = 0UL; j<=3UL; j++) {
|
|
db[i*4UL+j+len*4UL] = b[i*8UL+j+4UL];
|
|
} /* end for */
|
|
if (!hamcorr(db, db_len, i*4UL, i*4UL+len*4UL)) return 0;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
return 1;
|
|
/*
|
|
0000 0000
|
|
0001 1110
|
|
0010 1101
|
|
0011 0011
|
|
0100 1011
|
|
0101 0101
|
|
0110 0110
|
|
0111 1000
|
|
1000 0111
|
|
1001 1001
|
|
1010 1010
|
|
1011 0100
|
|
1100 1100
|
|
1101 0010
|
|
1110 0001
|
|
1111 1111
|
|
*/
|
|
} /* end hamming() */
|
|
|
|
|
|
static uint32_t bits2val_org(const char b[], uint32_t b_len, uint32_t from, uint32_t len)
|
|
{
|
|
uint32_t n;
|
|
n = 0UL;
|
|
while (len>0UL) {
|
|
n = n*2UL+(uint32_t)b[from];
|
|
++from;
|
|
--len;
|
|
}
|
|
return n;
|
|
} /* end bits2val() */
|
|
|
|
/*
|
|
static void wh(uint32_t x)
|
|
{
|
|
char tmp;
|
|
x = x&15UL;
|
|
if (x<10UL) osi_WrStr((char *)(tmp = (char)(x+48UL),&tmp), 1u/1u);
|
|
else osi_WrStr((char *)(tmp = (char)(x+55UL),&tmp), 1u/1u);
|
|
}
|
|
*/
|
|
/* end wh() */
|
|
|
|
#define B 8 // codeword: 8 bit
|
|
#define S 4 // davon 4 bit data
|
|
|
|
char dat_str[9][13+1];
|
|
|
|
uint8_t H[4][8] = // Parity-Check
|
|
{{ 0, 1, 1, 1, 1, 0, 0, 0},
|
|
{ 1, 0, 1, 1, 0, 1, 0, 0},
|
|
{ 1, 1, 0, 1, 0, 0, 1, 0},
|
|
{ 1, 1, 1, 0, 0, 0, 0, 1}};
|
|
uint8_t He[8] = { 0x7, 0xB, 0xD, 0xE, 0x8, 0x4, 0x2, 0x1}; // Spalten von H:
|
|
|
|
|
|
uint32_t bits2val(uint8_t *bits, int len) { // big endian
|
|
int j;
|
|
uint32_t val;
|
|
if ((len < 0) || (len > 32)) return -1;
|
|
val = 0;
|
|
for (j = 0; j < len; j++) {
|
|
val |= (bits[j] << (len-1-j));
|
|
}
|
|
return val;
|
|
}
|
|
/*
|
|
|
|
void deinterleave(char *str, int L, uint8_t *block) {
|
|
int i, j;
|
|
for (j = 0; j < B; j++) { // L = 7, 13
|
|
for (i = 0; i < L; i++) {
|
|
if (str[L*j+i] >= 0x30 && str[L*j+i] <= 0x31) {
|
|
block[B*i+j] = str[L*j+i] - 0x30; // ASCII -> bit
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
int check(uint8_t code[8]) {
|
|
int i, j; // Bei Demodulierung durch Nulldurchgaenge, wenn durch Fehler ausser Takt,
|
|
uint32_t synval = 0; // verschieben sich die bits. Fuer Hamming-Decode waere es besser,
|
|
uint8_t syndrom[4]; // sync zu Beginn mit Header und dann Takt beibehalten fuer decision.
|
|
int ret=0;
|
|
|
|
for (i = 0; i < 4; i++) { // S = 4
|
|
syndrom[i] = 0;
|
|
for (j = 0; j < 8; j++) { // B = 8
|
|
syndrom[i] ^= H[i][j] & code[j];
|
|
}
|
|
}
|
|
synval = bits2val(syndrom, 4);
|
|
if (synval) {
|
|
ret = -1;
|
|
for (j = 0; j < 8; j++) { // 1-bit-error
|
|
if (synval == He[j]) { // reicht auf databits zu pruefen, d.h.
|
|
ret = j+1; // (systematischer Code) He[0..3]
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else ret = 0;
|
|
if (ret > 0) code[ret-1] ^= 0x1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
char nib2chr(uint8_t nib) {
|
|
char c = '_';
|
|
if (nib < 0x10) {
|
|
if (nib < 0xA) c = 0x30 + nib;
|
|
else c = 0x41 + nib-0xA;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
int dat_out(uint8_t *dat_bits,uint32_t m) {
|
|
int i, ret = 0;
|
|
static int fr_id;
|
|
// int jahr = 0, monat = 0, tag = 0, std = 0, min = 0;
|
|
int frnr = 0;
|
|
int msek = 0;
|
|
double lat = 0, lon = 0, alt = 0;
|
|
int nib;
|
|
int dvv; // signed/unsigned 16bit
|
|
|
|
fr_id = bits2val(dat_bits+48, 4);
|
|
|
|
//printf("DFM FI:%02i ",fr_id);
|
|
|
|
if (fr_id >= 0 && fr_id <= 8) {
|
|
for (i = 0; i < 13; i++) {
|
|
nib = bits2val(dat_bits+4*i, 4);
|
|
dat_str[fr_id][i] = nib2chr(nib);
|
|
}
|
|
dat_str[fr_id][13] = '\0';
|
|
}
|
|
|
|
if (fr_id == 0) {
|
|
// chan[m].dfm6.start = 1;
|
|
frnr = bits2val(dat_bits+24, 8);
|
|
chan[m].dfm6.frnr = frnr;
|
|
}
|
|
|
|
if (fr_id == 1) {
|
|
// 00..31: ? GPS-Sats in Sicht?
|
|
msek = bits2val(dat_bits+32, 16);
|
|
chan[m].dfm6.sek = msek/1000.0;
|
|
// chan[m].dfm6.frnr=sek+min*60+hr*3600+day*86400;
|
|
}
|
|
|
|
if (fr_id == 2) {
|
|
lat = bits2val(dat_bits, 32);
|
|
lat=lat/1e7;
|
|
chan[m].dfm6.newlat = lat;
|
|
dvv = (short)bits2val(dat_bits+32, 16); // (short)? zusammen mit dir sollte unsigned sein
|
|
chan[m].dfm6.horiV = dvv/1e2;
|
|
}
|
|
|
|
if (fr_id == 3) {
|
|
lon = bits2val(dat_bits, 32);
|
|
lon = lon/1e7;
|
|
chan[m].dfm6.newlon = lon;
|
|
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
|
|
chan[m].dfm6.dir = dvv/1e2;
|
|
}
|
|
|
|
if (fr_id == 4) {
|
|
alt = bits2val(dat_bits, 32);
|
|
alt = alt/1e2;
|
|
chan[m].dfm6.newalt = alt;
|
|
dvv = (short)bits2val(dat_bits+32, 16); // signed
|
|
chan[m].dfm6.vertV = dvv/1e2;
|
|
}
|
|
|
|
if (fr_id == 5) {
|
|
}
|
|
|
|
if (fr_id == 6) {
|
|
}
|
|
|
|
if (fr_id == 7) {
|
|
}
|
|
|
|
if (fr_id == 8) {
|
|
chan[m].dfm6.yr = bits2val(dat_bits, 12);
|
|
chan[m].dfm6.mon = bits2val(dat_bits+12, 4);
|
|
chan[m].dfm6.day = bits2val(dat_bits+16, 5);
|
|
chan[m].dfm6.hr = bits2val(dat_bits+21, 5);
|
|
chan[m].dfm6.min = bits2val(dat_bits+26, 6);
|
|
|
|
if(chan[m].dfm6.newsonde==1){ // gdy nowa, przypisujemy jak leci
|
|
chan[m].dfm6.prevlat = chan[m].dfm6.newlat;
|
|
chan[m].dfm6.prevlon = chan[m].dfm6.newlon;
|
|
chan[m].dfm6.prevalt = chan[m].dfm6.newalt;
|
|
chan[m].dfm6.newsonde=0;
|
|
ret=-2; // dane niepewne, więc oznaczamy jako bledne (z jednej ramki, nikomu korona nie spadnie a i tak czekamy na symbol sondy)
|
|
}
|
|
|
|
if(chan[m].dfm6.newalt<1 || chan[m].dfm6.newalt >40000 || // gdy za duży błąd z usrednionych danych
|
|
(fabs(chan[m].dfm6.prevlat-chan[m].dfm6.newlat)>0.05)||
|
|
(fabs(chan[m].dfm6.prevlon-chan[m].dfm6.newlon)>0.05)||
|
|
(abs(chan[m].dfm6.prevalt-chan[m].dfm6.newalt)>500)){
|
|
ret=-2; // dane bledne
|
|
chan[m].dfm6.sonde_typ = 0;
|
|
printf("R1\n");
|
|
}
|
|
else
|
|
ret = fr_id;
|
|
|
|
chan[m].dfm6.prevlat = (chan[m].dfm6.newlat + chan[m].dfm6.lat)/2; // usrednianie poprzednich i obecnych danych
|
|
chan[m].dfm6.prevlon = (chan[m].dfm6.newlon + chan[m].dfm6.lon)/2;
|
|
chan[m].dfm6.prevalt = (chan[m].dfm6.newalt + chan[m].dfm6.alt)/2;
|
|
|
|
chan[m].dfm6.lat = chan[m].dfm6.newlat; // odebrane jako aktualne
|
|
chan[m].dfm6.lon = chan[m].dfm6.newlon;
|
|
chan[m].dfm6.alt = chan[m].dfm6.newalt;
|
|
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// DFM-06 (NXP8)
|
|
float fl20(int d) { // float20
|
|
int val, p;
|
|
float f;
|
|
p = (d>>16) & 0xF;
|
|
val = d & 0xFFFF;
|
|
f = val/(float)(1<<p);
|
|
return f;
|
|
}
|
|
/*
|
|
float flo20(int d) {
|
|
int m, e;
|
|
float f1, f;
|
|
m = d & 0xFFFF;
|
|
e = (d >> 16) & 0xF;
|
|
f = m / pow(2,e);
|
|
return f;
|
|
}
|
|
*/
|
|
|
|
// DFM-09 (STM32)
|
|
float fl24(int d) { // float24
|
|
int val, p;
|
|
float f;
|
|
p = (d>>20) & 0xF;
|
|
val = d & 0xFFFFF;
|
|
f = val/(float)(1<<p);
|
|
return f;
|
|
}
|
|
|
|
// temperature approximation
|
|
float get_Temp(float *meas) { // meas[0..4]
|
|
// NTC-Thermistor EPCOS B57540G0502
|
|
// R/T No 8402, R25=Ro=5k
|
|
// B0/100=3450
|
|
// 1/T = 1/To + 1/B log(r) , r=R/Ro
|
|
// GRAW calibration data -80C..+40C on EEPROM ?
|
|
// meas0 = g*(R + Rs)
|
|
// meas3 = g*Rs , Rs: dfm6:10k, dfm9:20k
|
|
// meas4 = g*Rf , Rf=220k
|
|
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 g = meas[4]/Rf;
|
|
float R = (meas[0]-meas[3]) / g; // meas[0,3,4] > 0 ?
|
|
float T = 0; // T/Kelvin
|
|
if (R > 0) T = 1/(1/T0 + 1/BB0 * log(R/R0));
|
|
return T - 273.15; // Celsius
|
|
// DFM-06: meas20 * 16 = meas24
|
|
// -> (meas24[0]-meas24[3])/meas24[4]=(meas20[0]-meas20[3])/meas20[4]
|
|
}
|
|
|
|
// temperature approximation
|
|
float get_Temp2(float *meas) { // meas[0..4]
|
|
// NTC-Thermistor EPCOS B57540G0502
|
|
// R/T No 8402, R25=Ro=5k
|
|
// B0/100=3450
|
|
// 1/T = 1/To + 1/B log(r) , r=R/Ro
|
|
// GRAW calibration data -80C..+40C on EEPROM ?
|
|
// meas0 = g*(R+Rs)+ofs
|
|
// meas3 = g*Rs+ofs , Rs: dfm6:10k, dfm9:20k
|
|
// meas4 = g*Rf+ofs , Rf=220k
|
|
float f = meas[0],
|
|
f1 = meas[3],
|
|
f2 = meas[4];
|
|
float BB0 = 3260.0; // B/Kelvin, fit -55C..+40C
|
|
float T0 = 25 + 273.15; // t0=25C
|
|
float R0 = 5.0e3; // R0=R25=5k
|
|
float Rf2 = 220e3; // Rf2 = Rf = 220k
|
|
float g_o = f2/Rf2; // approx gain
|
|
float Rs_o = f1/g_o; // = Rf2 * f1/f2;
|
|
float Rf1 = Rs_o; // Rf1 = Rs: dfm6:10k, dfm9:20k
|
|
float g = g_o; // gain
|
|
float Rb = 0.0; // offset
|
|
float R = 0; // thermistor
|
|
float T = 0; // T/Kelvin
|
|
|
|
if ( 8e3 < Rs_o && Rs_o < 12e3) Rf1 = 10e3; // dfm6
|
|
else if (18e3 < Rs_o && Rs_o < 22e3) Rf1 = 20e3; // dfm9
|
|
g = (f2 - f1) / (Rf2 - Rf1);
|
|
Rb = (f1*Rf2-f2*Rf1)/(f2-f1); // ofs/g
|
|
|
|
R = (f-f1)/g; // meas[0,3,4] > 0 ?
|
|
if (R > 0) T = 1/(1/T0 + 1/BB0 * log(R/R0));
|
|
|
|
//printf(" (Rso: %.1f , Rb: %.1f)", Rs_o/1e3, Rb/1e3);
|
|
|
|
return T - 273.15;
|
|
// DFM-06: meas20 * 16 = meas24
|
|
}
|
|
|
|
float get_Temp4(float *meas) { // meas[0..4]
|
|
// NTC-Thermistor EPCOS B57540G0502
|
|
// [ T/C , R/R25 , alpha ] :
|
|
// [ -55.0 , 51.991 , 6.4 ]
|
|
// [ -50.0 , 37.989 , 6.2 ]
|
|
// [ -45.0 , 28.07 , 5.9 ]
|
|
// [ -40.0 , 20.96 , 5.7 ]
|
|
// [ -35.0 , 15.809 , 5.5 ]
|
|
// [ -30.0 , 12.037 , 5.4 ]
|
|
// [ -25.0 , 9.2484 , 5.2 ]
|
|
// [ -20.0 , 7.1668 , 5.0 ]
|
|
// [ -15.0 , 5.5993 , 4.9 ]
|
|
// [ -10.0 , 4.4087 , 4.7 ]
|
|
// [ -5.0 , 3.4971 , 4.6 ]
|
|
// [ 0.0 , 2.7936 , 4.4 ]
|
|
// [ 5.0 , 2.2468 , 4.3 ]
|
|
// [ 10.0 , 1.8187 , 4.2 ]
|
|
// [ 15.0 , 1.4813 , 4.0 ]
|
|
// [ 20.0 , 1.2136 , 3.9 ]
|
|
// [ 25.0 , 1.0000 , 3.8 ]
|
|
// [ 30.0 , 0.82845 , 3.7 ]
|
|
// [ 35.0 , 0.68991 , 3.6 ]
|
|
// [ 40.0 , 0.57742 , 3.5 ]
|
|
// -> Steinhart–Hart coefficients (polyfit):
|
|
float p0 = 1.09698417e-03,
|
|
p1 = 2.39564629e-04,
|
|
p2 = 2.48821437e-06,
|
|
p3 = 5.84354921e-08;
|
|
// T/K = 1/( p0 + p1*ln(R) + p2*ln(R)^2 + p3*ln(R)^3 )
|
|
float Rf = 220e3; // Rf = 220k
|
|
float g = meas[4]/Rf;
|
|
float R = (meas[0]-meas[3]) / g; // meas[0,3,4] > 0 ?
|
|
float T = 0; // T/Kelvin
|
|
if (R > 0) T = 1/( p0 + p1*log(R) + p2*log(R)*log(R) + p3*log(R)*log(R)*log(R) );
|
|
return T - 273.15; // Celsius
|
|
// DFM-06: meas20 * 16 = meas24
|
|
// -> (meas24[0]-meas24[3])/meas24[4]=(meas20[0]-meas20[3])/meas20[4]
|
|
}
|
|
|
|
|
|
#define SNbit 0x0100
|
|
int conf_out(uint8_t *conf_bits,uint32_t m) {
|
|
int ret = 0;
|
|
int val;
|
|
uint8_t conf_id;
|
|
uint8_t hl;
|
|
uint32_t SN6, SN, snt;
|
|
static int chAbit, chA[2];
|
|
static int chCbit, chC[2];
|
|
static int chDbit, chD[2];
|
|
static int ch7bit, ch7[2];
|
|
static uint32_t SN_A, SN_C, SN_D, SN_7;
|
|
static uint8_t max_ch;
|
|
static uint8_t nul_ch;
|
|
static uint8_t sn2_ch, sn_ch;
|
|
static uint32_t SN_X;
|
|
static int chXbit, chX[2];
|
|
static uint8_t dfm6typ;
|
|
|
|
conf_id = bits2val(conf_bits, 4);
|
|
|
|
if (conf_id > 4 && bits2val(conf_bits+8, 4*5) == 0) nul_ch = bits2val(conf_bits, 8);
|
|
|
|
|
|
dfm6typ = ((nul_ch & 0xF0)==0x50) && (nul_ch & 0x0F);
|
|
if (dfm6typ && (chan[m].dfm6.sonde_typ & 0x0F) > 6)
|
|
{ // reset if 0x5A, 0x5B (DFM-06)
|
|
chan[m].dfm6.sonde_typ = 0;
|
|
max_ch = conf_id;
|
|
printf("R2\n");
|
|
}
|
|
|
|
if (conf_id > 4 && conf_id > max_ch) max_ch = conf_id; // mind. 5 Kanaele // reset? lower 0xsCaaaab?
|
|
if (conf_id > 4 && conf_id == (nul_ch>>4)+1){
|
|
if(conf_id==6){
|
|
chan[m].dfm6.SN6=bits2val(conf_bits+4,24);
|
|
chan[m].dfm6.ok=1;
|
|
sprintf(chan[m].dfm6.id,"D6%08x", chan[m].dfm6.SN6);
|
|
dfm6typ=0x06;
|
|
}else{
|
|
sn2_ch = bits2val(conf_bits, 8);
|
|
snt=bits2val(conf_bits+8, 16);
|
|
if(sn2_ch!=chan[m].dfm6.SNT) {chan[m].dfm6.SNT=sn2_ch; chan[m].dfm6.SNL=0;chan[m].dfm6.SNH=0; chan[m].dfm6.SN6=0; } //jesli inny typ - reset numeru sondy
|
|
switch(bits2val(conf_bits+24, 4)){
|
|
case 0:
|
|
if((snt<<16)!=chan[m].dfm6.SNH) {chan[m].dfm6.SNH=snt<<16; chan[m].dfm6.SN6=0; chan[m].dfm6.ok=0;}
|
|
else chan[m].dfm6.ok=1;
|
|
break;
|
|
case 1:
|
|
if(snt!=chan[m].dfm6.SNL) {chan[m].dfm6.SNL=snt;chan[m].dfm6.SN6=0;}
|
|
else chan[m].dfm6.ok=1;
|
|
break;
|
|
default:
|
|
chan[m].dfm6.SNT=0; chan[m].dfm6.SNL=0; chan[m].dfm6.SNH=0; chan[m].dfm6.SN6=0; chan[m].dfm6.ok=0; // reset
|
|
}
|
|
|
|
//printf("\nSN T:%02x\n",(sn2_ch & 0xFF));
|
|
if ((sn2_ch & 0xFF) == 0xAC ) dfm6typ=0x9; //DFM-9
|
|
if ((sn2_ch & 0xFF) == 0xCC || (sn2_ch & 0xFF) == 0xBC) dfm6typ=0xD; //DFM17
|
|
if ((sn2_ch & 0x0F) == 0x0 ) dfm6typ=0xF; //DFM15
|
|
|
|
chan[m].dfm6.sonde_typ=dfm6typ;
|
|
|
|
|
|
if(chan[m].dfm6.SNT!=0 && chan[m].dfm6.SNL!=0 && chan[m].dfm6.SNH!=0)
|
|
{ chan[m].dfm6.SN6=chan[m].dfm6.SNH | chan[m].dfm6.SNL; sprintf(chan[m].dfm6.id,"D%1X%08u", dfm6typ,chan[m].dfm6.SN6);}
|
|
else{chan[m].dfm6.id[0]=0; chan[m].dfm6.SN6=0;}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (conf_id >= 0 && conf_id <= 4) {
|
|
val = bits2val(conf_bits+4, 4*6);
|
|
chan[m].dfm6.meas24[conf_id] = fl24(val);
|
|
// DFM-09 (STM32): 24bit 0exxxxx
|
|
// DFM-06 (NXP8): 20bit 0exxxx0
|
|
// fl20(bits2val(conf_bits+4, 4*5))
|
|
// = fl20(exxxx)
|
|
// = fl24(exxxx0)/2^4
|
|
// meas20 * 16 = meas24
|
|
}
|
|
|
|
// STM32-status: Bat, MCU-Temp
|
|
if ((chan[m].dfm6.sonde_typ & 0xF) == 0xA) { // DFM-09 (STM32)
|
|
if (conf_id == 0x5) { // voltage
|
|
val = bits2val(conf_bits+8, 4*4);
|
|
chan[m].dfm6.status[0] = val/1000.0;
|
|
}
|
|
if (conf_id == 0x6) { // T-intern (STM32)
|
|
val = bits2val(conf_bits+8, 4*4);
|
|
chan[m].dfm6.status[1] = val/100.0;
|
|
}
|
|
}
|
|
|
|
int dig=0;
|
|
int ii;
|
|
|
|
for(ii=2;ii<strlen(chan[m].dfm6.id);ii++){
|
|
if(chan[m].dfm6.id[ii]>57 || chan[m].dfm6.id[ii]<48) dig=1;
|
|
}
|
|
|
|
|
|
if(strlen(chan[m].dfm6.id)<5 || dig){
|
|
time_t t = time(NULL);
|
|
struct tm tm = *localtime(&t);
|
|
int czas=tm.tm_mon + 1 + tm.tm_mday;
|
|
|
|
chan[m].dfm6.id[0]='D';
|
|
chan[m].dfm6.id[1]='6';
|
|
chan[m].dfm6.id[2]='D';
|
|
chan[m].dfm6.id[3]='X';
|
|
chan[m].dfm6.id[4]=65+tm.tm_hour;
|
|
chan[m].dfm6.id[5]=65+(int)(czas/25);
|
|
chan[m].dfm6.id[6]=65+czas%25;
|
|
chan[m].dfm6.id[7]=chan[m].freq[2];//rxb[58];
|
|
chan[m].dfm6.id[8]=chan[m].freq[3];//rxb[59];
|
|
chan[m].dfm6.id[9]=chan[m].freq[4];//rxb[60];
|
|
chan[m].dfm6.id[10]=0;
|
|
}
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
void print_gpx(uint32_t m) {
|
|
int i, j;
|
|
char typp;
|
|
|
|
|
|
if((chan[m].dfm6.id[0]!='D')||(chan[m].dfm6.id[1]!='6')&&(chan[m].dfm6.id[1]!='9')&&(chan[m].dfm6.id[1]!='F')&&(chan[m].dfm6.id[1]!='D'))
|
|
chan[m].dfm6.id[0]=0;
|
|
|
|
|
|
printf("%02d: (%04i-%02i-%02i %02i:%02i:%02i)", m+1, chan[m].dfm6.yr,chan[m].dfm6.mon,chan[m].dfm6.day, chan[m].dfm6.hr,chan[m].dfm6.min,(int)chan[m].dfm6.sek );
|
|
printf(":DFM %s %04d ",chan[m].dfm6.id,chan[m].dfm6.frnr);
|
|
printf("lat: %.6f ", chan[m].dfm6.lat);
|
|
printf("lon: %.6f ", chan[m].dfm6.lon);
|
|
printf("alt: %.1f ", chan[m].dfm6.alt);
|
|
printf("vH: %5.2f ", chan[m].dfm6.horiV);
|
|
printf("D: %5.1f ", chan[m].dfm6.dir);
|
|
printf("vV: %5.2f ", chan[m].dfm6.vertV);
|
|
float t = get_Temp(chan[m].dfm6.meas24);
|
|
float t4 = get_Temp4(chan[m].dfm6.meas24);
|
|
if (t > -270.0) printf("T=%.1fC ", t);
|
|
if (t4 > -270.0) printf("T4=%.1fC ", t4);
|
|
if ((chan[m].dfm6.sonde_typ & 0xFF) == 9) {
|
|
printf("U: %.2fV ", chan[m].dfm6.status[0]);
|
|
printf("Ti: %.2fC ", chan[m].dfm6.status[1]-270.0);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static char sendDFM(uint32_t m){
|
|
char s[200];
|
|
char tmp[50];
|
|
char ret=0;
|
|
s[0]=0;
|
|
char i;
|
|
|
|
|
|
|
|
if (strlen(chan[m].dfm6.id)>5){
|
|
|
|
sprintf(tmp, chan[m].dfm6.id);
|
|
tmp[10]=0;
|
|
|
|
if(chan[m].dfm6.ok==1) {tmp[0]='E'; printf("OK ****\n");}
|
|
|
|
strcat(s,tmp);
|
|
|
|
sprintf(tmp,"%04d", chan[m].dfm6.frnr);
|
|
tmp[4]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%08.0f", chan[m].dfm6.lat*1000000);
|
|
tmp[8]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%09.0f", chan[m].dfm6.lon*1000000);
|
|
tmp[9]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%05.0f", chan[m].dfm6.alt);
|
|
tmp[5]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%05.0f", chan[m].dfm6.horiV*100);
|
|
tmp[5]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%04.0f", chan[m].dfm6.dir*10);
|
|
tmp[4]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%05.0f", chan[m].dfm6.vertV*100);
|
|
tmp[5]=0;
|
|
strcat(s,tmp);
|
|
|
|
tmp[0] = chan[m].freq[0];
|
|
tmp[1] = chan[m].freq[1];
|
|
tmp[2] = chan[m].freq[2];
|
|
tmp[3] = chan[m].freq[3];
|
|
tmp[4] = chan[m].freq[4];
|
|
tmp[5] = chan[m].freq[5];
|
|
tmp[6] = 0;
|
|
|
|
if(strlen(tmp)>2)
|
|
strcat(s,tmp);
|
|
else
|
|
strcat(s,"000000");
|
|
|
|
float t = get_Temp(chan[m].dfm6.meas24);
|
|
if (t > -270.0) {
|
|
sprintf(tmp,"%04.0f", (t+273)*10);
|
|
tmp[4]=0;
|
|
}
|
|
else sprintf(tmp,"0000");
|
|
strcat(s,tmp);
|
|
|
|
if ((chan[m].dfm6.sonde_typ & 0xFF) == 9) {
|
|
sprintf(tmp,"%04.0f", chan[m].dfm6.status[0]*100);
|
|
tmp[4]=0;
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%05.0f", chan[m].dfm6.status[1]*100);
|
|
tmp[5]=0;
|
|
}
|
|
else sprintf(tmp,"000000000");
|
|
strcat(s,tmp);
|
|
sprintf(tmp,"%4d%02d%02d%02d%02d%02.0f",chan[m].dfm6.yr, chan[m].dfm6.mon, chan[m].dfm6.day, chan[m].dfm6.hr, chan[m].dfm6.min, chan[m].dfm6.sek);
|
|
|
|
tmp[16]=0;
|
|
strcat(s,tmp);
|
|
|
|
tmp[0] = (char)(chan[m].mycallc>>24);
|
|
tmp[1] = (char)(chan[m].mycallc>>16&255UL);
|
|
tmp[2] = (char)(chan[m].mycallc>>8&255UL);
|
|
tmp[3] = (char)(chan[m].mycallc&255UL);
|
|
if (chan[m].mycallc>0UL) tmp[4] = chan[m].myssid;
|
|
else tmp[4] = '\020';
|
|
strcat(s,tmp);
|
|
|
|
alludp(chan[m].udptx, 88+5, s, 88+5);
|
|
chan[m].dfm6.ok=0;
|
|
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void decodeframe6(uint32_t m)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
uint32_t rt;
|
|
|
|
char ret0,ret1,ret2;
|
|
|
|
int frid = -1;
|
|
|
|
char s[101+6];
|
|
char tx;
|
|
struct DFM6 * anonym;
|
|
/* build tx frame */
|
|
struct DFM6 * anonym0;
|
|
struct CHAN * anonym1; /* my call if set */
|
|
{ /* with */
|
|
struct DFM6 * anonym = &chan[m].dfm6;
|
|
deinterleave(anonym->rxbuf, 264ul, 0UL, 7UL, anonym->ch, 56ul);
|
|
deinterleave(anonym->rxbuf, 264ul, 56UL, 13UL, anonym->dh1, 104ul);
|
|
deinterleave(anonym->rxbuf, 264ul, 160UL, 13UL, anonym->dh2, 104ul);
|
|
|
|
ret0=hamming(anonym->dh1, 104ul, 13UL, anonym->db1, 104ul);
|
|
ret1=hamming(anonym->dh2, 104ul, 13UL, anonym->db2,104ul);
|
|
ret2=hamming(anonym->ch, 56ul, 7UL, anonym->cb, 56ul);
|
|
|
|
if((osic_time()-anonym->lastsent)>600){ //gdy za dlugo nie bylo ramki, kasowanie i liczenie od nowa
|
|
chan[m].dfm6.newsonde=1;
|
|
anonym->lastsent=osic_time();
|
|
chan[m].dfm6.id[0]=0;
|
|
}
|
|
|
|
if(chan[m].dfm6.newsonde==0){
|
|
for(i=0;i<6;i++)
|
|
if(chan[m].freq[0]!=chan[m].pfreq[0])
|
|
chan[m].dfm6.newsonde=1;
|
|
}
|
|
|
|
if(chan[m].dfm6.newsonde){
|
|
for(i=0;i<6;i++)
|
|
chan[m].pfreq[0]=chan[m].freq[0];
|
|
}
|
|
|
|
if(ret2>0)
|
|
conf_out(anonym->cb,m);
|
|
if(ret0>0){
|
|
frid = dat_out(anonym->db1,m);
|
|
if (frid == 8){
|
|
anonym->lastsent=osic_time();
|
|
print_gpx(m);
|
|
sendDFM(m);
|
|
}
|
|
else if(frid==-2){
|
|
printf("ERR:");
|
|
print_gpx(m);
|
|
chan[m].dfm6.id[0]=0;
|
|
}
|
|
}
|
|
if(ret1>0){
|
|
frid = dat_out(anonym->db2,m);
|
|
if (frid == 8){
|
|
anonym->lastsent=osic_time();
|
|
print_gpx(m);
|
|
sendDFM(m);
|
|
}
|
|
else if(frid==-2){
|
|
printf("ERR:");
|
|
print_gpx(m);
|
|
chan[m].dfm6.id[0]=0;
|
|
}
|
|
|
|
}
|
|
}
|
|
} /* end decodeframe6() */
|
|
|
|
|
|
static void demodbyte6(uint32_t m, char d)
|
|
{
|
|
/* WrInt(ORD(d),1); */
|
|
struct DFM6 * anonym;
|
|
{ /* with */
|
|
struct DFM6 * anonym = &chan[m].dfm6;
|
|
anonym->synword = anonym->synword*2UL+(uint32_t)d;
|
|
if (anonym->rxp>=264UL) {
|
|
if ((anonym->synword&65535UL)==17871UL) anonym->rxp = 0UL;
|
|
else if ((anonym->synword&65535UL)==47664UL) {
|
|
/* inverse start sequence found */
|
|
anonym->polarity = !anonym->polarity;
|
|
anonym->rxp = 0UL;
|
|
}
|
|
}
|
|
else {
|
|
anonym->rxbuf[anonym->rxp] = d;
|
|
++anonym->rxp;
|
|
if (anonym->rxp==264UL) decodeframe6(m);
|
|
}
|
|
}
|
|
} /* end demodbyte6() */
|
|
|
|
|
|
static void demodbit6(uint32_t m, float u, float u0)
|
|
{
|
|
char d;
|
|
float ua;
|
|
struct DFM6 * anonym;
|
|
d = u>=u0;
|
|
{ /* with */
|
|
struct DFM6 * anonym = &chan[m].dfm6;
|
|
if (anonym->lastmanch==u0<0.0f) {
|
|
anonym->manchestd += (32767L-anonym->manchestd)/16L;
|
|
}
|
|
anonym->lastmanch = d;
|
|
anonym->manchestd = -anonym->manchestd;
|
|
/*WrInt(manchestd,8); */
|
|
if (anonym->manchestd<0L) {
|
|
/*=polarity*/
|
|
demodbyte6(m, d!=anonym->polarity);
|
|
/*quality*/
|
|
ua = (float)fabs(u-u0)-anonym->bitlev;
|
|
anonym->bitlev = anonym->bitlev+ua*0.005f;
|
|
anonym->noise = anonym->noise+((float)fabs(ua)-anonym->noise)*0.02f;
|
|
}
|
|
}
|
|
/*quality*/
|
|
} /* end demodbit6() */
|
|
|
|
|
|
static void demod6(float u, uint32_t m)
|
|
{
|
|
char d;
|
|
struct DFM6 * anonym;
|
|
/*
|
|
IF debfd>=0 THEN
|
|
ui:=VAL(INTEGER, u*0.002);
|
|
WrBin(debfd, ui, 2);
|
|
END;
|
|
*/
|
|
{ /* with */
|
|
struct DFM6 * anonym = &chan[m].dfm6;
|
|
d = u>=0.0f;
|
|
if (anonym->cbit) {
|
|
demodbit6(m, u, anonym->lastu);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
anonym->lastu = u;
|
|
}
|
|
else anonym->plld = d;
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demod6() */
|
|
|
|
|
|
static void Fsk6(uint32_t m)
|
|
{
|
|
float ff;
|
|
int32_t lim;
|
|
struct DFM6 * anonym;
|
|
{ /* with */
|
|
struct DFM6 * anonym = &chan[m].dfm6;
|
|
lim = (int32_t)anonym->demodbaud;
|
|
for (;;) {
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
ff = Fir(afin, (uint32_t)((anonym->baudfine&65535L)/4096L),16UL, chan[m].afir, 32ul, anonym->afirtab, 512ul);
|
|
demod6(ff, m);
|
|
}
|
|
anonym->baudfine += lim;
|
|
lim = 0L;
|
|
if (anonym->baudfine<131072L) break;
|
|
}
|
|
}
|
|
} /* end Fsk6() */
|
|
|
|
/*------------------------------ C34 C50 */
|
|
|
|
static void demodframe34(uint32_t channel)
|
|
{
|
|
uint32_t val;
|
|
uint32_t sum2;
|
|
uint32_t sum1;
|
|
uint32_t i;
|
|
double hr;
|
|
char s[101+6];
|
|
char ok0;
|
|
struct C34 * anonym;
|
|
struct CHAN * anonym0; /* call if set */
|
|
char tmp;
|
|
{ /* with */
|
|
struct C34 * anonym = &chan[channel].c34;
|
|
sum1 = 0UL;
|
|
sum2 = 65791UL;
|
|
for (i = 2UL; i<=6UL; i++) {
|
|
sum1 += (uint32_t)(uint8_t)anonym->rxbuf[i];
|
|
sum2 -= (uint32_t)(uint8_t)anonym->rxbuf[i]*(7UL-i);
|
|
} /* end for */
|
|
sum1 = sum1&255UL;
|
|
sum2 = sum2&255UL;
|
|
ok0 = sum1==(uint32_t)(uint8_t)
|
|
anonym->rxbuf[7U] && sum2==(uint32_t)(uint8_t)
|
|
anonym->rxbuf[8U];
|
|
if (anonym->tused+3600UL<osic_time()) {
|
|
anonym->id34.id[0U] = 0; /* timed out context */
|
|
anonym->id50.id[0U] = 0;
|
|
}
|
|
if (verb && ok0 || verb2) {
|
|
if (maxchannels>0UL) {
|
|
//printf("%02i:",channel+1);
|
|
printCnDT(channel);
|
|
}
|
|
if (anonym->c50) {
|
|
osi_WrStr("C50 ", 5ul);
|
|
osi_WrStr(anonym->id50.id, 9ul);
|
|
}
|
|
else {
|
|
osi_WrStr("C34 ", 5ul);
|
|
osi_WrStr(anonym->id34.id, 9ul);
|
|
}
|
|
WrdB(chan[channel].adcmax);
|
|
WrQuali(noiselevel(channel));
|
|
Wrtune(chan[channel].adcdc, chan[channel].adcmax);
|
|
osi_WrStr(" [", 3ul);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[2U], 2UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[3U], 2UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[4U], 2UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[5U], 2UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[6U], 2UL);
|
|
osi_WrStr(" ", 2ul);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[7U], 2UL);
|
|
osi_WrHex((uint32_t)(uint8_t)anonym->rxbuf[8U], 2UL);
|
|
osi_WrStr("] ", 3ul);
|
|
}
|
|
if (ok0) {
|
|
/* chksum ok */
|
|
val = (uint32_t)(uint8_t)anonym->rxbuf[6U]+(uint32_t)
|
|
(uint8_t)anonym->rxbuf[5U]*256UL+(uint32_t)(uint8_t)
|
|
anonym->rxbuf[4U]*65536UL+(uint32_t)(uint8_t)
|
|
anonym->rxbuf[3U]*16777216UL;
|
|
hr = (double)*X2C_CAST(&val,uint32_t,float,float *);
|
|
if (anonym->c50) {
|
|
if (anonym->id50.idtime+3600UL<osic_time()) {
|
|
anonym->id50.id[0U] = 0;
|
|
anonym->id50.idcheck[0U] = 0;
|
|
anonym->id50.idcnt = 0UL;
|
|
}
|
|
/* remove old id */
|
|
switch ((unsigned)anonym->rxbuf[2U]) {
|
|
case '\003':
|
|
/*
|
|
CHR(02H): hr:=CAST(REAL, CAST(SET32,
|
|
val)/SET32{0..31});
|
|
IF verb THEN WrStr("baro ");
|
|
WrFixed(hr, 2, 0); WrStr(""); END;
|
|
*/
|
|
if (hr<99.9 && hr>(-99.9)) {
|
|
if (verb) {
|
|
osi_WrStr("tmp1 ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("oC", 3ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\004':
|
|
if (hr<99.9 && hr>(-99.9)) {
|
|
if (verb) {
|
|
osi_WrStr("tmp2 ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("oC", 3ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\005':
|
|
if (hr<99.9 && hr>(-99.9)) {
|
|
if (verb) {
|
|
osi_WrStr("tmp3 ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("oC", 3ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\020':
|
|
if (hr<=100.0 && hr>=0.0) {
|
|
if (verb) {
|
|
osi_WrStr("hum ", 5ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("%", 2ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\024':
|
|
if (verb) {
|
|
osi_WrStr("date", 5ul);
|
|
aprsstr_IntToStr((int32_t)(val%1000000UL+1000000UL), 1UL,
|
|
s, 101ul);
|
|
s[0U] = ' ';
|
|
osi_WrStr(s, 101ul);
|
|
}
|
|
break;
|
|
case '\025':
|
|
if (verb) {
|
|
aprsstr_TimeToStr((val/10000UL)*3600UL+((val%10000UL)
|
|
/100UL)*60UL+val%100UL, s, 101ul);
|
|
osi_WrStr("time ", 6ul);
|
|
osi_WrStr(s, 101ul);
|
|
}
|
|
break;
|
|
case '\026':
|
|
hr = latlong(val, anonym->c50);
|
|
if (hr<89.9 && hr>(-89.9)) {
|
|
if (verb) {
|
|
osi_WrStr("lat ", 6ul);
|
|
osic_WrFixed((float)hr, 5L, 0UL);
|
|
}
|
|
}
|
|
break;
|
|
case '\027':
|
|
hr = latlong(val, anonym->c50);
|
|
if (hr<180.0 && hr>(-180.0)) {
|
|
if (verb) {
|
|
osi_WrStr("long ", 6ul);
|
|
osic_WrFixed((float)hr, 5L, 0UL);
|
|
}
|
|
}
|
|
break;
|
|
case '\030':
|
|
hr = (double)((float)val*0.1f);
|
|
if (hr<50000.0) {
|
|
if (verb) {
|
|
osi_WrStr("alti ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("m", 2ul);
|
|
}
|
|
}
|
|
break;
|
|
case 'd': /* 66H 67H 68H 89H 6BH seem to be fixed too */
|
|
strncpy(s,"SC50",101u);
|
|
s[4U] = hex(val/4096UL&7UL);
|
|
s[5U] = hex(val/256UL);
|
|
s[6U] = hex(val/16UL);
|
|
s[7U] = hex(val);
|
|
s[8U] = 0;
|
|
s[9U] = 0;
|
|
if (verb) {
|
|
osi_WrStr("numb ", 6ul);
|
|
osi_WrStr((char *) &s[4U], 1u/1u);
|
|
osi_WrStr((char *) &s[5U], 1u/1u);
|
|
osi_WrStr((char *) &s[6U], 1u/1u);
|
|
osi_WrStr((char *) &s[7U], 1u/1u);
|
|
osi_WrStr((char *) &s[8U], 1u/1u);
|
|
}
|
|
/* check name, if changed may be checksum error or 2 sondes on same frequency */
|
|
if (aprsstr_StrCmp(anonym->id50.idcheck, 9ul, s, 101ul)) {
|
|
++anonym->id50.idcnt; /* got same name again */
|
|
}
|
|
else {
|
|
/* new name so check if wrong */
|
|
aprsstr_Assign(anonym->id50.idcheck, 9ul, s, 101ul);
|
|
anonym->idcnt = 1UL;
|
|
}
|
|
if (anonym->id50.idcnt>2UL || anonym->id50.id[0U]==0) {
|
|
/* first name or safe new name */
|
|
memcpy(anonym->id50.id,anonym->id50.idcheck,9u);
|
|
anonym->id50.idtime = osic_time();
|
|
}
|
|
anonym->tused = osic_time();
|
|
break;
|
|
default:;
|
|
if (verb2) {
|
|
/*WrStr("????");*/
|
|
osic_WrINT32(val, 12UL);
|
|
osic_WrINT32(val/65536UL, 7UL);
|
|
osic_WrINT32(val&65535UL, 7UL);
|
|
osic_WrFixed((float)hr, 2L, 10UL);
|
|
osi_WrStr(" ", 2ul);
|
|
for (i = 31UL;; i--) {
|
|
osi_WrStr((char *)(tmp = (char)
|
|
(48UL+(uint32_t)X2C_IN(i,32,(uint32_t)val)),&tmp),
|
|
1u/1u);
|
|
if (i==0UL) break;
|
|
} /* end for */
|
|
}
|
|
break;
|
|
} /* end switch */
|
|
}
|
|
else {
|
|
/* SC34 */
|
|
if (anonym->id34.idtime+3600UL<osic_time()) {
|
|
anonym->id34.id[0U] = 0;
|
|
anonym->id34.idcheck[0U] = 0;
|
|
anonym->id34.idcnt = 0UL;
|
|
}
|
|
/* remove old id */
|
|
switch ((unsigned)anonym->rxbuf[2U]) {
|
|
case '\003':
|
|
if (hr<99.9 && hr>(-99.9)) {
|
|
if (verb) {
|
|
osi_WrStr("tmp1 ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("oC", 3ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\007':
|
|
if (hr<99.9 && hr>(-99.9)) {
|
|
if (verb) {
|
|
osi_WrStr("dewp ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("oC", 3ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\024':
|
|
if (verb) {
|
|
osi_WrStr("date", 5ul);
|
|
aprsstr_IntToStr((int32_t)(val%1000000UL+1000000UL), 1UL,
|
|
s, 101ul);
|
|
s[0U] = ' ';
|
|
osi_WrStr(s, 101ul);
|
|
}
|
|
break;
|
|
case '\025':
|
|
if (verb) {
|
|
aprsstr_TimeToStr((val/10000UL)*3600UL+((val%10000UL)
|
|
/100UL)*60UL+val%100UL, s, 101ul);
|
|
osi_WrStr("time ", 6ul);
|
|
osi_WrStr(s, 101ul);
|
|
}
|
|
break;
|
|
case '\026':
|
|
hr = latlong(val, anonym->c50);
|
|
if (hr<89.9 && hr>(-89.9)) {
|
|
if (verb) {
|
|
osi_WrStr("lati ", 6ul);
|
|
osic_WrFixed((float)hr, 5L, 0UL);
|
|
}
|
|
}
|
|
break;
|
|
case '\027':
|
|
hr = latlong(val, anonym->c50);
|
|
if (hr<180.0 && hr>(-180.0)) {
|
|
if (verb) {
|
|
osi_WrStr("long ", 6ul);
|
|
osic_WrFixed((float)hr, 5L, 0UL);
|
|
}
|
|
}
|
|
break;
|
|
case '\030':
|
|
hr = (double)((float)val*0.1f);
|
|
if (hr<50000.0) {
|
|
if (verb) {
|
|
osi_WrStr("alti ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("m", 2ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\031':
|
|
hr = (double)((float)val*0.1852f);
|
|
/*1.609*/ /*1.852*/ /* guess knots or miles */
|
|
if (hr<1000.0) {
|
|
if (verb) {
|
|
osi_WrStr("wind ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("km/h", 5ul);
|
|
}
|
|
}
|
|
break;
|
|
case '\032':
|
|
hr = (double)((float)val*0.1f);
|
|
if (hr>=0.0 && hr<=360.0) {
|
|
if (verb) {
|
|
osi_WrStr("wdir ", 6ul);
|
|
osic_WrFixed((float)hr, 1L, 0UL);
|
|
osi_WrStr("deg", 4ul);
|
|
}
|
|
}
|
|
break;
|
|
case 'd':
|
|
strncpy(s,"SC34",101u);
|
|
/* build a name from seems like serial number */
|
|
s[4U] = hex(val/65536UL);
|
|
s[5U] = hex(val/4096UL);
|
|
s[6U] = hex(val/256UL);
|
|
s[7U] = hex(val/16UL);
|
|
s[8U] = hex(val);
|
|
s[9U] = 0;
|
|
if (verb) {
|
|
osi_WrStr("numb ", 6ul);
|
|
osi_WrStr((char *) &s[4U], 1u/1u);
|
|
osi_WrStr((char *) &s[5U], 1u/1u);
|
|
osi_WrStr((char *) &s[6U], 1u/1u);
|
|
osi_WrStr((char *) &s[7U], 1u/1u);
|
|
osi_WrStr((char *) &s[8U], 1u/1u);
|
|
}
|
|
/* check name, if changed may be checksum error or 2 sondes on same frequency */
|
|
if (aprsstr_StrCmp(anonym->id34.idcheck, 9ul, s, 101ul)) {
|
|
++anonym->id34.idcnt; /* got same name again */
|
|
}
|
|
else {
|
|
/* new name so check if wrong */
|
|
aprsstr_Assign(anonym->id34.idcheck, 9ul, s, 101ul);
|
|
anonym->idcnt = 1UL;
|
|
}
|
|
if (anonym->id34.idcnt>3UL || anonym->id34.id[0U]==0) {
|
|
/* first name or safe new name */
|
|
memcpy(anonym->id34.id,anonym->id34.idcheck,9u);
|
|
anonym->id34.idtime = osic_time();
|
|
}
|
|
anonym->tused = osic_time();
|
|
break;
|
|
default:;
|
|
if (verb2) {
|
|
osi_WrStr("????", 5ul);
|
|
osic_WrINT32(val, 12UL);
|
|
osic_WrFixed((float)hr, 2L, 10UL);
|
|
}
|
|
break;
|
|
} /* end switch */
|
|
}
|
|
/* build tx frame */
|
|
if ((anonym->c50 && anonym->id50.id[0U])
|
|
&& aprsstr_StrCmp(anonym->id50.idcheck, 9ul, anonym->id50.id,
|
|
9ul) || (!anonym->c50 && anonym->id34.id[0U])
|
|
&& aprsstr_StrCmp(anonym->id34.idcheck, 9ul, anonym->id34.id,
|
|
9ul)) {
|
|
/* stop sending if ambigous id */
|
|
if (anonym->c50) {
|
|
for (i = 0UL; i<=8UL; i++) {
|
|
s[i] = anonym->id50.id[i];
|
|
} /* end for */
|
|
}
|
|
else {
|
|
for (i = 0UL; i<=8UL; i++) {
|
|
s[i] = anonym->id34.id[i];
|
|
} /* end for */
|
|
}
|
|
s[9U] = 0;
|
|
{ /* with */
|
|
struct CHAN * anonym0 = &chan[channel];
|
|
s[10U] = (char)(anonym0->mycallc>>24);
|
|
s[11U] = (char)(anonym0->mycallc>>16&255UL);
|
|
s[12U] = (char)(anonym0->mycallc>>8&255UL);
|
|
s[13U] = (char)(anonym0->mycallc&255UL);
|
|
if (anonym0->mycallc>0UL) s[14U] = anonym0->myssid;
|
|
else s[14U] = '\020';
|
|
}
|
|
for (i = 0UL; i<=6UL; i++) {
|
|
s[i+15UL] = anonym->rxbuf[i+2UL]; /* payload */
|
|
} /* end for */
|
|
|
|
s[22] = chan[channel].freq[0];
|
|
s[23] = chan[channel].freq[1];
|
|
s[24] = chan[channel].freq[2];
|
|
s[25] = chan[channel].freq[3];
|
|
s[26] = chan[channel].freq[4];
|
|
s[27] = chan[channel].freq[5];
|
|
|
|
|
|
|
|
alludp(chan[channel].udptx, 22UL+6, s, 101ul+6);
|
|
}
|
|
else if (verb) {
|
|
if (anonym->c50) {
|
|
if (anonym->id50.id[0U]) {
|
|
osi_WrStr(" changing name ", 16ul);
|
|
osi_WrStr(anonym->id50.id, 9ul);
|
|
osi_WrStr("<->", 4ul);
|
|
osi_WrStr(anonym->id50.idcheck, 9ul);
|
|
}
|
|
}
|
|
else if (anonym->id34.id[0U]) {
|
|
osi_WrStr(" changing name ", 16ul);
|
|
osi_WrStr(anonym->id34.id, 9ul);
|
|
osi_WrStr("<->", 4ul);
|
|
osi_WrStr(anonym->id34.idcheck, 9ul);
|
|
}
|
|
}
|
|
}
|
|
else if (verb2) {
|
|
/*build tx frame */
|
|
osi_WrStr("---- chksum ", 13ul);
|
|
osi_WrHex(sum1, 2UL);
|
|
osi_WrHex(sum2, 2UL);
|
|
}
|
|
if (verb2 || ok0 && verb) osi_WrStrLn("", 1ul);
|
|
}
|
|
/* name(9) 0C call(5) playload(7) */
|
|
} /* end demodframe34() */
|
|
|
|
|
|
static void demodbit34(uint32_t channel, char d)
|
|
{
|
|
/*IF NOT verb THEN WrInt(ORD(d),1); END; */
|
|
struct C34 * anonym;
|
|
d = !d;
|
|
{ /* with */
|
|
struct C34 * anonym = &chan[channel].c34;
|
|
anonym->rxbytec = anonym->rxbytec*2UL+(uint32_t)d;
|
|
if ((anonym->rxbytec&268435455UL)==234942462UL) {
|
|
/* c34 1110 0000 0000 1110 1111 1111 1110*/
|
|
anonym->c50 = 0;
|
|
anonym->rxp = 2UL;
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
|
|
|
|
else if ((anonym->rxbytec&2097151UL)==3070UL) {
|
|
/*IF NOT verb THEN WrStrLn(""); END; */
|
|
/* c50 0 0000 0000 1011 1111 1110 */
|
|
anonym->c50 = 1;
|
|
anonym->rxp = 2UL;
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
/*IF NOT verb THEN WrStrLn(""); END; */
|
|
if ((anonym->c50 || anonym->rxbitc) || !d) {
|
|
if (anonym->rxbitc<=8UL) {
|
|
/* databits */
|
|
anonym->rxbyte = (anonym->rxbyte&255UL)/2UL;
|
|
if (d) anonym->rxbyte += 128UL;
|
|
++anonym->rxbitc;
|
|
}
|
|
else if (anonym->rxp>0UL) {
|
|
/* byte ready */
|
|
anonym->rxbitc = 0UL;
|
|
anonym->rxbuf[anonym->rxp] = (char)anonym->rxbyte;
|
|
/*WrHex(rxbyte, 3); */
|
|
++anonym->rxp;
|
|
if (anonym->rxp>8UL) {
|
|
/*IF NOT verb THEN WrStr("*"); END; */
|
|
demodframe34(channel);
|
|
anonym->rxp = 0UL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* end demodbit34() */
|
|
|
|
|
|
static void demod34(float u, uint32_t channel)
|
|
{
|
|
char d;
|
|
struct C34 * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct C34 * anonym = &chan[channel].c34;
|
|
if (anonym->cbit) {
|
|
demodbit34(channel, d);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
/*squelch*/
|
|
anonym->sqmed[d] = anonym->sqmed[d]+(u-anonym->sqmed[d])*0.05f;
|
|
anonym->noise = anonym->noise+((float)fabs(u-anonym->sqmed[d])
|
|
-anonym->noise)*0.05f;
|
|
}
|
|
else {
|
|
/*squelch*/
|
|
anonym->plld = d;
|
|
}
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
} /* end demod34() */
|
|
|
|
|
|
static void Afsk(uint32_t channel)
|
|
{
|
|
float ff;
|
|
float b;
|
|
float a;
|
|
float d;
|
|
float mid;
|
|
float right;
|
|
struct C34 * anonym;
|
|
{ /* with */
|
|
struct C34 * anonym = &chan[channel].c34;
|
|
right = Fir(afin, 0UL, 16UL, chan[channel].afir, 32ul, anonym->afirtab,512ul);
|
|
if (anonym->left<0.0f!=right<0.0f) {
|
|
d = X2C_DIVR(anonym->left,anonym->left-right);
|
|
a = (float)(uint32_t)X2C_TRUNCC(d*16.0f+0.5f,0UL,X2C_max_longcard);
|
|
b = a*0.0625f;
|
|
if ((uint32_t)X2C_TRUNCC(a,0UL,
|
|
X2C_max_longcard)>0UL && (uint32_t)X2C_TRUNCC(a,0UL,X2C_max_longcard)<16UL) {
|
|
mid = Fir(afin, 16UL-(uint32_t)X2C_TRUNCC(a,0UL, X2C_max_longcard), 16UL, chan[channel].afir, 32ul,anonym->afirtab, 512ul);
|
|
if (anonym->left<0.0f!=mid<0.0f) {
|
|
d = (X2C_DIVR(anonym->left,anonym->left-mid))*b;
|
|
}
|
|
else d = b+(X2C_DIVR(mid,mid-right))*(1.0f-b);
|
|
}
|
|
if (anonym->tcnt+d!=0.0f) {
|
|
anonym->freq = X2C_DIVR(1.0f,anonym->tcnt+d);
|
|
}
|
|
anonym->tcnt = 0.0f-d;
|
|
}
|
|
anonym->tcnt = anonym->tcnt+1.0f;
|
|
anonym->left = right;
|
|
anonym->dfir[anonym->dfin] = anonym->freq-anonym->afskmidfreq;
|
|
anonym->dfin = anonym->dfin+1UL&63UL;
|
|
anonym->baudfine += (int32_t)anonym->demodbaud;
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
if (anonym->baudfine<65536L) {
|
|
/* normal alway true */
|
|
ff = Fir(anonym->dfin, (uint32_t)(16L-anonym->baudfine/4096L), 16UL, anonym->dfir, 64ul, anonym->dfirtab, 1024ul);
|
|
demod34(ff, channel);
|
|
}
|
|
}
|
|
}
|
|
} /* end Afsk() */
|
|
|
|
|
|
|
|
static void demodbitIMET(uint32_t channel, char d)
|
|
{
|
|
/*IF NOT verb THEN WrInt(ORD(d),1); END; */
|
|
struct IMET * anonym;
|
|
d = !d;
|
|
{ /* with */
|
|
struct IMET * anonym = &chan[channel].imet;
|
|
anonym->rxbytec = anonym->rxbytec*2UL+(uint32_t)d;
|
|
if ((anonym->rxbytec&0xFFFFFFFF)==0x3FFFFD01) {
|
|
/* IMET 111111111111111111110100000001*/
|
|
// anonym->imet = 1;
|
|
anonym->rxp = 2UL;
|
|
anonym->rxbitc = 0UL;
|
|
}
|
|
|
|
if (anonym->rxbitc || !d) {
|
|
if (anonym->rxbitc<=8UL) {
|
|
/* databits */
|
|
anonym->rxbyte = (anonym->rxbyte&255UL)/2UL;
|
|
if (d) anonym->rxbyte += 128UL;
|
|
++anonym->rxbitc;
|
|
}
|
|
else if (anonym->rxp>0UL) {
|
|
/* byte ready */
|
|
anonym->rxbitc = 0UL;
|
|
anonym->rxbuf[anonym->rxp] = (char)anonym->rxbyte;
|
|
/*WrHex(rxbyte, 3); */
|
|
++anonym->rxp;
|
|
if (anonym->rxp>8UL) {
|
|
// demodframeIMET(channel);
|
|
anonym->rxp = 0UL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void demodIMET(float u, uint32_t channel)
|
|
{
|
|
char d;
|
|
struct IMET * anonym;
|
|
d = u>=0.0f;
|
|
{ /* with */
|
|
struct IMET * anonym = &chan[channel].imet;
|
|
if (anonym->cbit) {
|
|
demodbitIMET(channel, d);
|
|
if (d!=anonym->oldd) {
|
|
if (d==anonym->plld) anonym->baudfine += anonym->pllshift;
|
|
else anonym->baudfine -= anonym->pllshift;
|
|
anonym->oldd = d;
|
|
}
|
|
/*squelch*/
|
|
anonym->sqmed[d] = anonym->sqmed[d]+(u-anonym->sqmed[d])*0.05f;
|
|
anonym->noise = anonym->noise+((float)fabs(u-anonym->sqmed[d])-anonym->noise)*0.05f;
|
|
}
|
|
else {
|
|
/*squelch*/
|
|
anonym->plld = d;
|
|
}
|
|
anonym->cbit = !anonym->cbit;
|
|
}
|
|
}
|
|
|
|
|
|
static void AfskIMET(uint32_t channel)
|
|
{
|
|
float ff;
|
|
float b;
|
|
float a;
|
|
float d;
|
|
float mid;
|
|
float right;
|
|
struct IMET * anonym;
|
|
{ /* with */
|
|
struct IMET * anonym = &chan[channel].imet;
|
|
right = Fir(afin, 0UL, 16UL, chan[channel].afir, 32ul, anonym->afirtab,512ul);
|
|
if (anonym->left<0.0f!=right<0.0f) {
|
|
d = X2C_DIVR(anonym->left,anonym->left-right);
|
|
a = (float)(uint32_t)X2C_TRUNCC(d*16.0f+0.5f,0UL,X2C_max_longcard);
|
|
b = a*0.0625f;
|
|
if ((uint32_t)X2C_TRUNCC(a,0UL,
|
|
X2C_max_longcard)>0UL && (uint32_t)X2C_TRUNCC(a,0UL,X2C_max_longcard)<16UL) {
|
|
mid = Fir(afin, 16UL-(uint32_t)X2C_TRUNCC(a,0UL, X2C_max_longcard), 16UL, chan[channel].afir, 32ul,anonym->afirtab, 512ul);
|
|
if (anonym->left<0.0f!=mid<0.0f) {
|
|
d = (X2C_DIVR(anonym->left,anonym->left-mid))*b;
|
|
}
|
|
else d = b+(X2C_DIVR(mid,mid-right))*(1.0f-b);
|
|
}
|
|
if (anonym->tcnt+d!=0.0f) {
|
|
anonym->freq = X2C_DIVR(1.0f,anonym->tcnt+d);
|
|
}
|
|
anonym->tcnt = 0.0f-d;
|
|
}
|
|
anonym->tcnt = anonym->tcnt+1.0f;
|
|
anonym->left = right;
|
|
anonym->dfir[anonym->dfin] = anonym->freq-anonym->afskmidfreq;
|
|
anonym->dfin = anonym->dfin+1UL&63UL;
|
|
anonym->baudfine += (int32_t)anonym->demodbaud;
|
|
if (anonym->baudfine>=65536L) {
|
|
anonym->baudfine -= 65536L;
|
|
if (anonym->baudfine<65536L) {
|
|
/* normal alway true */
|
|
ff = Fir(anonym->dfin, (uint32_t)(16L-anonym->baudfine/4096L), 16UL, anonym->dfir, 64ul, anonym->dfirtab, 1024ul);
|
|
demodIMET(ff, channel);
|
|
}
|
|
}
|
|
}
|
|
} /* end Afsk() */
|
|
|
|
|
|
static void getadc(void)
|
|
{
|
|
int32_t sl;
|
|
int32_t l;
|
|
int32_t max0[64];
|
|
int32_t min0[64];
|
|
uint32_t ch;
|
|
uint32_t c;
|
|
unsigned int i;
|
|
struct CHAN * anonym;
|
|
uint32_t tmp,pos;
|
|
int chno;
|
|
char tmps[10];
|
|
char mod=0;
|
|
|
|
struct R92 * anonymz;
|
|
struct R41 * anonym0;
|
|
struct DFM6 * anonym1;
|
|
struct C34 * anonym2;
|
|
struct PILS * anonym5;
|
|
struct M10 * anonym6;
|
|
struct M20 * anonym7;
|
|
struct IMET * anonym8;
|
|
struct MP3 * anonym9;
|
|
|
|
struct SKPP * anonym11;
|
|
struct IMS * anonym12;
|
|
struct ATMS * anonym13;
|
|
|
|
c = 0UL;
|
|
mod=0;
|
|
do {
|
|
mod=0;
|
|
if (adcbufrd>=adcbufsamps) {
|
|
adcbufrd = 0UL;
|
|
l = osi_RdBin(soundfd, (char *)adcbuf, 8192u/1u, adcbuflen*2UL);
|
|
|
|
sprintf(tmps,"%c%c%c%c\n",adcbuf[0],adcbuf[1],adcbuf[2],adcbuf[3]);
|
|
|
|
|
|
if(tmps[0]=='9' && tmps[1]=='S' && tmps[2]=='K' && tmps[3]=='P'){ //freq table
|
|
//printf("Update channel table\n");
|
|
pos=4;
|
|
mod=1;
|
|
chno=0;
|
|
|
|
while(adcbuf[pos]!=0){
|
|
chno=(int)(((char)adcbuf[pos]-48)*10+((char)adcbuf[pos+1]-48)-1);
|
|
if(chno<0) break;
|
|
|
|
struct R92 * anonymz = &chan[chno].r92;
|
|
anonymz->rxp = 0UL;
|
|
anonymz->rxbitc = 0UL;
|
|
anonymz->rxbyte = 0UL;
|
|
anonymz->enabled =0;
|
|
struct R41 * anonym0 = &chan[chno].r41;
|
|
anonym0->rxp = 0UL;
|
|
anonym0->rxbitc = 0UL;
|
|
anonym0->rxbyte = 0UL;
|
|
anonym0->enabled =0;
|
|
struct MP3 * anonym9 = &chan[chno].mp3;
|
|
anonym9->rxp = 0UL;
|
|
anonym9->rxbitc = 0UL;
|
|
anonym9->rxbyte = 0UL;
|
|
anonym9->enabled =0;
|
|
struct PILS * anonym5 = &chan[chno].pils;
|
|
anonym5->rxp = 0UL;
|
|
anonym5->rxbitc = 0UL;
|
|
anonym5->rxbyte = 0UL;
|
|
anonym5->enabled =0;
|
|
struct DFM6 * anonym1 = &chan[chno].dfm6;
|
|
anonym1->rxp = 264UL;
|
|
anonym1->enabled =0;
|
|
struct M10 * anonym6 = &chan[chno].m10;
|
|
anonym6->rxp = 101UL;
|
|
anonym6->enabled =0;
|
|
struct M20 * anonym7 = &chan[chno].m20;
|
|
anonym7->rxp = 70UL;
|
|
anonym7->enabled =0;
|
|
struct C34 * anonym2 = &chan[chno].c34;
|
|
anonym2->rxp = 0UL;
|
|
anonym2->enabled =0;
|
|
struct IMET * anonym8 = &chan[chno].imet;
|
|
anonym8->rxp = 0UL;
|
|
anonym8->enabled =0;
|
|
struct SKPP * anonym11 = &chan[chno].skpp;
|
|
anonym11->rxp = 0UL;
|
|
anonym11->enabled =0;
|
|
struct IMS * anonym12 = &chan[chno].ims;
|
|
anonym12->rxp = 0UL;
|
|
anonym12->enabled =0;
|
|
struct ATMS * anonym13 = &chan[chno].ims;
|
|
anonym13->rxp = 0UL;
|
|
anonym13->enabled =0;
|
|
|
|
|
|
chan[chno].freq[0]=adcbuf[pos+2];
|
|
chan[chno].freq[1]=adcbuf[pos+3];
|
|
chan[chno].freq[2]=adcbuf[pos+4];
|
|
chan[chno].freq[3]=adcbuf[pos+5];
|
|
chan[chno].freq[4]=adcbuf[pos+6];
|
|
chan[chno].freq[5]=adcbuf[pos+7];
|
|
chan[chno].freq[6]=0;
|
|
chan[chno].st=(unsigned int)((adcbuf[pos+8])&0xff)-65;
|
|
|
|
switch(chan[chno].st){
|
|
case 0:
|
|
anonym6->enabled =1;
|
|
anonym7->enabled =1;
|
|
anonym2->enabled =1;
|
|
anonym0->enabled =1;
|
|
anonym1->enabled =1;
|
|
anonym5->enabled =1;
|
|
anonymz->enabled =1;
|
|
anonym9->enabled =1;
|
|
anonym11->enabled =1;
|
|
anonym12->enabled =1;
|
|
|
|
break;
|
|
case ST_M10:
|
|
case ST_M10GT:
|
|
case ST_M2K2:
|
|
anonym6->enabled =1;
|
|
break;
|
|
case ST_M20:
|
|
anonym7->enabled =1;
|
|
case ST_C34:
|
|
case ST_C50:
|
|
anonym2->enabled =1;
|
|
break;
|
|
case ST_RS41:
|
|
case ST_RS41SGM:
|
|
anonym0->enabled =1;
|
|
break;
|
|
case ST_DFM6:
|
|
case ST_DFM9:
|
|
case ST_DFM15:
|
|
case ST_DFM17:
|
|
anonym1->enabled =1;
|
|
break;
|
|
case ST_PIL:
|
|
anonym5->enabled =1;
|
|
break;
|
|
case ST_RS92:
|
|
anonymz->enabled =1;
|
|
break;
|
|
case ST_MP3:
|
|
anonym9->enabled =1;
|
|
break;
|
|
|
|
|
|
|
|
case ST_SKP:
|
|
anonym11->enabled =1;
|
|
break;
|
|
case ST_IMS:
|
|
anonym12->enabled =1;
|
|
break;
|
|
case ST_ATMS:
|
|
anonym13->enabled =1;
|
|
break;
|
|
}
|
|
|
|
pos+=9;
|
|
}
|
|
}else if(mod==0){
|
|
adcbufsamps = 0UL;
|
|
if (l<0L) {
|
|
if (abortonsounderr) Error("Sounddevice Failure", 20ul);
|
|
else {
|
|
osic_Close(soundfd);
|
|
usleep(100000UL);
|
|
OpenSound();
|
|
return;
|
|
}
|
|
}
|
|
if (l<2L) return;
|
|
adcbufsamps = (uint32_t)(l/2L);
|
|
if (debfd>=0L) {
|
|
osi_WrBin(debfd, (char *)adcbuf, 8192u/1u, adcbufsamps*2UL);
|
|
}
|
|
tmp = maxchannels;
|
|
ch = 0UL;
|
|
if (ch<=tmp) for (;; ch++) {
|
|
chan[ch].adcdc += (max0[ch]+min0[ch])/2L-chan[ch].adcdc>>4;
|
|
chan[ch].adcmax += (max0[ch]-min0[ch])-chan[ch].adcmax>>4;
|
|
max0[ch] = -32768L;
|
|
min0[ch] = 32767L;
|
|
if (ch==tmp) break;
|
|
} /* end for */
|
|
adcbufsampx = X2C_max_longcard;
|
|
}
|
|
}
|
|
sl = (int32_t)adcbuf[adcbufrd];
|
|
if (cfgchannels==0UL && (sl&1)) {
|
|
//auto channels channel 0 //WrInt(lastc, 1); WrStrLn(" ch1");
|
|
if (adcbufsampx!=X2C_max_longcard) {
|
|
ch = (adcbufrd-adcbufsampx)-1UL;
|
|
/*WrInt(ch, 1); WrStrLn(" ch"); */
|
|
if (ch<63UL) {
|
|
/* if (verb && maxchannels!=ch && mod==0) {
|
|
osi_WrStr("channels changed from ", 23ul);
|
|
osic_WrINT32(maxchannels+1UL, 0UL);
|
|
osi_WrStr(" to ", 5ul);
|
|
osic_WrINT32(ch+1UL, 0UL);
|
|
osi_WrStrLn("", 1ul);
|
|
}
|
|
*/
|
|
maxchannels = ch;
|
|
}
|
|
}
|
|
adcbufsampx = adcbufrd;
|
|
c = 0UL;
|
|
}
|
|
sl = (int32_t)((uint32_t)sl&0xFFFFFFFEUL);
|
|
if (sl==0L) ++chan[c].squelch;
|
|
else chan[c].squelch = 0UL;
|
|
sl -= chan[c].adcdc;
|
|
++adcbufrd;
|
|
chan[c].afir[afin] = (float)(sl-chan[c].adcdc);
|
|
if (sl>max0[c]) max0[c] = sl;
|
|
if (sl<min0[c]) min0[c] = sl;
|
|
++c;
|
|
} while (c<=maxchannels);
|
|
afin = afin+1UL&31UL;
|
|
afinR41=afin;
|
|
afinPS=afin;
|
|
afinMP3=afin;
|
|
tmp = maxchannels;
|
|
c = 0UL;
|
|
if (c<=tmp) for (;; c++) {
|
|
{ /* with */
|
|
struct CHAN * anonym = &chan[c];
|
|
if (anonym->squelch<64UL) {
|
|
/* squelch open */
|
|
if (anonym->r92.enabled) Fsk(c);
|
|
if (anonym->r41.enabled) Fsk41(c);
|
|
if (anonym->mp3.enabled) FskMP3(c);
|
|
if (anonym->pils.enabled) FskPS(c);
|
|
if (anonym->c34.enabled) Afsk(c);
|
|
// if (anonym->imet.enabled) AfskIMET(c);
|
|
if (anonym->dfm6.enabled) Fsk6(c);
|
|
if (anonym->m10.enabled) Fsk10(c);
|
|
if (anonym->m20.enabled) Fsk20(c);
|
|
if (anonym->skpp.enabled) FskSKPP(c);
|
|
if (anonym->ims.enabled) FskIMS(c);
|
|
if (anonym->atms.enabled) FskATMS(c);
|
|
|
|
}
|
|
}
|
|
if (c==tmp) break;
|
|
} /* end for */
|
|
} /* end getadc() */
|
|
|
|
static uint16_t sondeudp_POLY = 0x1021U;
|
|
|
|
|
|
static void Gencrctab(void)
|
|
{
|
|
uint16_t j;
|
|
uint16_t i;
|
|
uint16_t crc;
|
|
for (i = 0U; i<=255U; i++) {
|
|
crc = (uint16_t)(i*256U);
|
|
for (j = 0U; j<=7U; j++) {
|
|
if ((0x8000U & crc)) crc = X2C_LSH(crc,16,1)^0x1021U;
|
|
else crc = X2C_LSH(crc,16,1);
|
|
} /* end for */
|
|
CRCTAB[i] = X2C_LSH(crc,16,-8)|X2C_LSH(crc,16,8);
|
|
} /* end for */
|
|
} /* end Gencrctab() */
|
|
|
|
|
|
X2C_STACK_LIMIT(100000l)
|
|
extern int main(int argc, char **argv)
|
|
{
|
|
X2C_BEGIN(&argc,argv,1,4000000l,8000000l);
|
|
if (sizeof(FILENAME)!=1024) X2C_ASSERT(0);
|
|
if (sizeof(CNAMESTR)!=9) X2C_ASSERT(0);
|
|
aprsstr_BEGIN();
|
|
osi_BEGIN();
|
|
Gencrctab();
|
|
memset((char *)chan,(char)0,sizeof(struct CHAN [64]));
|
|
Parms();
|
|
initrsc();
|
|
getst = 0UL;
|
|
afin = 0UL;
|
|
soundbufs = 0UL;
|
|
adcbufrd = 0UL;
|
|
adcbufsamps = 0UL;
|
|
adcbufsampx = X2C_max_longcard;
|
|
|
|
for (;;) getadc();
|
|
X2C_EXIT();
|
|
return 0;
|
|
}
|
|
|
|
X2C_MAIN_DEFINITION
|