mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-18 10:01:57 -05:00
4de778c4e7
The WSPR message is unpacked into a symbol per byte array which is processed by encoding a whole number of bytes of message, this requires the output array to be bigger than the number of symbols to accommodate extra values that are not part of the message due to rounding up to whole bytes. I.e. 176 (11*8*2) elements to contain the 162 symbols. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6532 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
313 lines
8.3 KiB
C
313 lines
8.3 KiB
C
/*
|
|
Functions used by wsprsim
|
|
*/
|
|
#include "wsprsim_utils.h"
|
|
#include "wsprd_utils.h"
|
|
#include "nhash.h"
|
|
#include "fano.h"
|
|
|
|
char get_locator_character_code(char ch) {
|
|
if( ch >=48 && ch <=57 ) { //0-9
|
|
return ch-48;
|
|
}
|
|
if( ch == 32 ) { //space
|
|
return 36;
|
|
}
|
|
if( ch >= 65 && ch <= 82 ) { //A-Z
|
|
return ch-65;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
char get_callsign_character_code(char ch) {
|
|
if( ch >=48 && ch <=57 ) { //0-9
|
|
return ch-48;
|
|
}
|
|
if( ch == 32 ) { //space
|
|
return 36;
|
|
}
|
|
if( ch >= 65 && ch <= 90 ) { //A-Z
|
|
return ch-55;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
long unsigned int pack_grid4_power(char *grid4, int power) {
|
|
long unsigned int m;
|
|
|
|
m=(179-10*grid4[0]-grid4[2])*180+10*grid4[1]+grid4[3];
|
|
m=m*128+power+64;
|
|
return m;
|
|
}
|
|
|
|
long unsigned int pack_call(char *callsign) {
|
|
int i;
|
|
long unsigned int n;
|
|
char call6[6];
|
|
memset(call6,32,sizeof(char)*6);
|
|
// callsign is 6 characters in length. Exactly.
|
|
size_t call_len = strlen(callsign);
|
|
if( call_len > 6 ) {
|
|
return 0;
|
|
}
|
|
if( isdigit(*(callsign+2)) ) {
|
|
for (i=0; i<6; i++) {
|
|
if( callsign[i] == 0 ) {
|
|
call6[i]=32;
|
|
} else {
|
|
call6[i]=*(callsign+i);
|
|
}
|
|
}
|
|
} else if( isdigit(*(callsign+1)) ) {
|
|
for (i=0; i<6; i++) {
|
|
if( i==0 || callsign[i-1]==0 ) {
|
|
call6[i]=32;
|
|
} else {
|
|
call6[i]=*(callsign+i-1);
|
|
}
|
|
}
|
|
}
|
|
for (i=0; i<6; i++) {
|
|
call6[i]=get_callsign_character_code(call6[i]);
|
|
}
|
|
n = call6[0];
|
|
n = n*36+call6[1];
|
|
n = n*10+call6[2];
|
|
n = n*27+call6[3]-10;
|
|
n = n*27+call6[4]-10;
|
|
n = n*27+call6[5]-10;
|
|
return n;
|
|
}
|
|
|
|
void pack_prefix(char *callsign, int32_t *n, int32_t *m, int32_t *nadd ) {
|
|
size_t i;
|
|
char *call6;
|
|
call6=malloc(sizeof(char)*6);
|
|
memset(call6,32,sizeof(char)*6);
|
|
size_t i1=strcspn(callsign,"/");
|
|
|
|
if( callsign[i1+2] == 0 ) {
|
|
//single char suffix
|
|
for (i=0; i<i1; i++) {
|
|
call6[i]=callsign[i];
|
|
}
|
|
*n=pack_call(call6);
|
|
*nadd=1;
|
|
int nc = callsign[i1+1];
|
|
if( nc >= 48 && nc <= 57 ) {
|
|
*m=nc-48;
|
|
} else if ( nc >= 65 && nc <= 90 ) {
|
|
*m=nc-65+10;
|
|
} else {
|
|
*m=38;
|
|
}
|
|
*m=60000-32768+*m;
|
|
} else if( callsign[i1+3]==0 ) {
|
|
//two char suffix
|
|
for (i=0; i<i1; i++) {
|
|
call6[i]=callsign[i];
|
|
}
|
|
*n=pack_call(call6);
|
|
*nadd=1;
|
|
*m=10*(callsign[i1+1]-48)+(callsign[i1+2]-48);
|
|
*m=60000 + 26 + *m;
|
|
} else {
|
|
char* pfx=strtok(callsign,"/");
|
|
call6=strtok(NULL," ");
|
|
*n=pack_call(call6);
|
|
size_t plen=strlen(pfx);
|
|
if( plen ==1 ) {
|
|
*m=36;
|
|
*m=37*(*m)+36;
|
|
} else if( plen == 2 ) {
|
|
*m=36;
|
|
} else {
|
|
*m=0;
|
|
}
|
|
for (i=0; i<plen; i++) {
|
|
int nc = callsign[i];
|
|
if( nc >= 48 && nc <= 57 ) {
|
|
nc=nc-48;
|
|
} else if ( nc >= 65 && nc <= 90 ) {
|
|
nc=nc-65+10;
|
|
} else {
|
|
nc=36;
|
|
}
|
|
*m=37*(*m)+nc;
|
|
}
|
|
*nadd=0;
|
|
if( *m > 32768 ) {
|
|
*m=*m-32768;
|
|
*nadd=1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void interleave(unsigned char *sym)
|
|
{
|
|
unsigned char tmp[162];
|
|
unsigned char p, i, j;
|
|
|
|
p=0;
|
|
i=0;
|
|
while (p<162) {
|
|
j=((i * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
|
|
if (j < 162 ) {
|
|
tmp[j]=sym[p];
|
|
p=p+1;
|
|
}
|
|
i=i+1;
|
|
}
|
|
for (i=0; i<162; i++) {
|
|
sym[i]=tmp[i];
|
|
}
|
|
}
|
|
|
|
int get_wspr_channel_symbols(char* rawmessage, char* hashtab, unsigned char* symbols) {
|
|
int m=0, n=0, ntype=0;
|
|
int i, j, ihash;
|
|
unsigned char pr3[162]=
|
|
{1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,
|
|
0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,
|
|
0,0,0,0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1,
|
|
1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,
|
|
0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0,
|
|
0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1,
|
|
0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1,
|
|
0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0,
|
|
0,0};
|
|
int nu[10]={0,-1,1,0,-1,2,1,0,-1,1};
|
|
char *callsign, *grid, *powstr;
|
|
char grid4[5], message[23];
|
|
|
|
memset(message,0,sizeof(char)*23);
|
|
i=0;
|
|
while ( rawmessage[i] != 0 && i<23 ) {
|
|
message[i]=rawmessage[i];
|
|
i++;
|
|
}
|
|
|
|
size_t i1=strcspn(message," ");
|
|
size_t i2=strcspn(message,"/");
|
|
size_t i3=strcspn(message,"<");
|
|
size_t i4=strcspn(message,">");
|
|
size_t mlen=strlen(message);
|
|
|
|
// Use the presence and/or absence of "<" and "/" to decide what
|
|
// type of message. No sanity checks! Beware!
|
|
|
|
if( (i1>3) & (i1<7) & (i2==mlen) & (i3==mlen) ) {
|
|
// Type 1 message: K9AN EN50 33
|
|
// xxnxxxx xxnn nn
|
|
callsign = strtok(message," ");
|
|
grid = strtok(NULL," ");
|
|
powstr = strtok(NULL," ");
|
|
int power = atoi(powstr);
|
|
n = pack_call(callsign);
|
|
|
|
for (i=0; i<4; i++) {
|
|
grid4[i]=get_locator_character_code(*(grid+i));
|
|
}
|
|
m = pack_grid4_power(grid4,power);
|
|
|
|
} else if ( i3 == 0 && i4 < mlen ) {
|
|
// Type 3: <K1ABC> EN50WC 33
|
|
// <PJ4/K1ABC> FK52UD 37
|
|
// send hash instead of callsign to make room for 6 char grid.
|
|
// if 4-digit locator is specified, 2 spaces are added to the end.
|
|
callsign=strtok(message,"<> ");
|
|
grid=strtok(NULL," ");
|
|
powstr=strtok(NULL," ");
|
|
int power = atoi(powstr);
|
|
if( power < 0 ) power=0;
|
|
if( power > 60 ) power=60;
|
|
power=power+nu[power%10];
|
|
ntype=-(power+1);
|
|
ihash=nhash(callsign,strlen(callsign),(uint32_t)146);
|
|
m=128*ihash + ntype + 64;
|
|
|
|
char grid6[6];
|
|
memset(grid6,32,sizeof(char)*6);
|
|
j=strlen(grid);
|
|
for(i=0; i<j-1; i++) {
|
|
grid6[i]=grid[i+1];
|
|
}
|
|
grid6[5]=grid[0];
|
|
n=pack_call(grid6);
|
|
} else if ( i2 < mlen ) { // just looks for a right slash
|
|
// Type 2: PJ4/K1ABC 37
|
|
callsign=strtok(message," ");
|
|
if( strlen(callsign) < i2 ) return 0; //guards against pathological case
|
|
powstr=strtok(NULL," ");
|
|
int power = atoi(powstr);
|
|
if( power < 0 ) power=0;
|
|
if( power > 60 ) power=60;
|
|
power=power+nu[power%10];
|
|
int n1, ng, nadd;
|
|
pack_prefix(callsign, &n1, &ng, &nadd);
|
|
ntype=power + 1 + nadd;
|
|
m=128*ng+ntype+64;
|
|
n=n1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
// pack 50 bits + 31 (0) tail bits into 11 bytes
|
|
unsigned char it, data[11];
|
|
memset(data,0,sizeof(char)*11);
|
|
it=0xFF & (n>>20);
|
|
data[0]=it;
|
|
it=0xFF & (n>>12);
|
|
data[1]=it;
|
|
it=0xFF & (n>>4);
|
|
data[2]=it;
|
|
it= ((n&(0x0F))<<4) + ((m>>18)&(0x0F));
|
|
data[3]=it;
|
|
it=0xFF & (m>>10);
|
|
data[4]=it;
|
|
it=0xFF & (m>>2);
|
|
data[5]=it;
|
|
it=(m & 0x03)<<6 ;
|
|
data[6]=it;
|
|
data[7]=0;
|
|
data[8]=0;
|
|
data[9]=0;
|
|
data[10]=0;
|
|
|
|
if( printdata ) {
|
|
printf("Data is :");
|
|
for (i=0; i<11; i++) {
|
|
printf("%02X ",data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
// make sure that the 11-byte data vector is unpackable
|
|
// unpack it with the routine that the decoder will use and display
|
|
// the result. let the operator decide whether it worked.
|
|
// char hashtab[32768][13];
|
|
// memset(hashtab,0,sizeof(char)*32768*13);
|
|
|
|
char *check_call_loc_pow, *check_callsign;
|
|
check_call_loc_pow=malloc(sizeof(char)*23);
|
|
check_callsign=malloc(sizeof(char)*13);
|
|
signed char check_data[11];
|
|
memcpy(check_data,data,sizeof(char)*11);
|
|
unpk_(check_data,hashtab,check_call_loc_pow,check_callsign);
|
|
// printf("Will decode as: %s\n",check_call_loc_pow);
|
|
|
|
unsigned int nbytes=11; // The message with tail is packed into almost 11 bytes.
|
|
unsigned char channelbits[nbytes*8*2]; /* 162 rounded up */
|
|
memset(channelbits,0,sizeof channelbits);
|
|
|
|
encode(channelbits,data,nbytes);
|
|
|
|
interleave(channelbits);
|
|
|
|
for (i=0; i<162; i++) {
|
|
symbols[i]=2*channelbits[i]+pr3[i];
|
|
}
|
|
|
|
return 1;
|
|
}
|