kopia lustrzana https://github.com/F5OEO/WsprryPi
Clean up line endings
rodzic
cd746388f6
commit
9f133eaed5
463
wspr.c
463
wspr.c
|
@ -1,233 +1,230 @@
|
||||||
/*
|
/*
|
||||||
WSPR encoding module
|
WSPR encoding module
|
||||||
All the encoding is done here
|
All the encoding is done here
|
||||||
Thanks to K1JT, G4JNT and PE1NZZ for publishing
|
Thanks to K1JT, G4JNT and PE1NZZ for publishing
|
||||||
helping infos.
|
helping infos.
|
||||||
|
|
||||||
Encoding process is in 5 steps:
|
Encoding process is in 5 steps:
|
||||||
* bits packing of user message in 50 bits
|
* bits packing of user message in 50 bits
|
||||||
* store the 50 bits dans 11 octets (88 bits and only 81 useful)
|
* store the 50 bits dans 11 octets (88 bits and only 81 useful)
|
||||||
* convolutionnal encoding with two pariy generators (-> 162 bits)
|
* convolutionnal encoding with two pariy generators (-> 162 bits)
|
||||||
* interleaving of the 162 bits with bit-reverse technique
|
* interleaving of the 162 bits with bit-reverse technique
|
||||||
* synchronisation with a psudo-random vector to obtain the
|
* synchronisation with a psudo-random vector to obtain the
|
||||||
162 symbols defining one frequency of 4.
|
162 symbols defining one frequency of 4.
|
||||||
|
|
||||||
F8CHK 29/03/2011 */
|
F8CHK 29/03/2011 */
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "uart1.h" // terminal UART definitions
|
#include "uart1.h" // terminal UART definitions
|
||||||
#include "SDR_Cube.h" // board & processor specific definitions
|
#include "SDR_Cube.h" // board & processor specific definitions
|
||||||
#include "SDR_Cube_globals.h" // global data
|
#include "SDR_Cube_globals.h" // global data
|
||||||
#include "wspr.h" // wspr definitions and functions
|
#include "wspr.h" // wspr definitions and functions
|
||||||
|
|
||||||
char wspr_message[20]; // user beacon message to encode
|
char wspr_message[20]; // user beacon message to encode
|
||||||
unsigned char wspr_symbols[162] = {0}, // contains 162 finals symbols
|
unsigned char wspr_symbols[162] = {0}, // contains 162 finals symbols
|
||||||
wspr_encoded = 0; // to know that a message has been encoded
|
wspr_encoded = 0; // to know that a message has been encoded
|
||||||
|
|
||||||
void Code_msg(char usr_message[],unsigned long int *N, unsigned long int *M)
|
void Code_msg(char usr_message[],unsigned long int *N, unsigned long int *M)
|
||||||
{
|
{
|
||||||
unsigned long int n,
|
unsigned long int n,
|
||||||
m;
|
m;
|
||||||
unsigned int i,
|
unsigned int i,
|
||||||
j,
|
j,
|
||||||
power,
|
power,
|
||||||
callsign_length;
|
callsign_length;
|
||||||
|
|
||||||
char callsign[7] = {0}, // callsign string
|
char callsign[7] = {0}, // callsign string
|
||||||
locator[5] = {0}, // locator string
|
locator[5] = {0}, // locator string
|
||||||
power_str[3]= {0}; // power string
|
power_str[3]= {0}; // power string
|
||||||
|
|
||||||
|
|
||||||
strcpy(callsign," "); // filling with spaces
|
strcpy(callsign," "); // filling with spaces
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (usr_message[i] != ' ')
|
while (usr_message[i] != ' ')
|
||||||
{
|
{
|
||||||
callsign[i] = usr_message[i]; // extract callsign
|
callsign[i] = usr_message[i]; // extract callsign
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
callsign_length = i;
|
callsign_length = i;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (usr_message[i] != ' ')
|
while (usr_message[i] != ' ')
|
||||||
locator[j++] = usr_message[i++]; // extract locator
|
locator[j++] = usr_message[i++]; // extract locator
|
||||||
locator[j] = 0;
|
locator[j] = 0;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
j = 0;
|
j = 0;
|
||||||
while (usr_message[i] != 0)
|
while (usr_message[i] != 0)
|
||||||
power_str[j++] = usr_message[i++]; // extract power
|
power_str[j++] = usr_message[i++]; // extract power
|
||||||
power_str[j]= 0 ;
|
power_str[j]= 0 ;
|
||||||
|
|
||||||
power = atoi(power_str); // power needs to be an integer
|
power = atoi(power_str); // power needs to be an integer
|
||||||
|
|
||||||
// Place a space in first position if third character is not a digit
|
// Place a space in first position if third character is not a digit
|
||||||
if (!isdigit(callsign [2]))
|
if (!isdigit(callsign [2]))
|
||||||
{
|
{
|
||||||
for (i = callsign_length ; i > 0; i--)
|
for (i = callsign_length ; i > 0; i--)
|
||||||
callsign [i] = callsign [i -1];
|
callsign [i] = callsign [i -1];
|
||||||
callsign [0] = ' ';
|
callsign [0] = ' ';
|
||||||
}
|
}
|
||||||
|
|
||||||
// callsign encoding:
|
// callsign encoding:
|
||||||
// numbers have a value between 0 and 9
|
// numbers have a value between 0 and 9
|
||||||
// and letters a value between 10 and 35
|
// and letters a value between 10 and 35
|
||||||
// spaces a value of 36
|
// spaces a value of 36
|
||||||
n = (callsign [0]>='0' && callsign[0]<='9'?callsign[0]-'0':callsign[0]==' '?36:callsign[0]-'A'+10);
|
n = (callsign [0]>='0' && callsign[0]<='9'?callsign[0]-'0':callsign[0]==' '?36:callsign[0]-'A'+10);
|
||||||
n = n * 36 + (callsign [1]>='0' && callsign[1]<='9'?callsign[1]-'0':callsign[1]==' '?36:callsign[1]-'A'+10);
|
n = n * 36 + (callsign [1]>='0' && callsign[1]<='9'?callsign[1]-'0':callsign[1]==' '?36:callsign[1]-'A'+10);
|
||||||
n = n * 10 + (callsign [2] - '0'); // only number (0-9)
|
n = n * 10 + (callsign [2] - '0'); // only number (0-9)
|
||||||
n = 27 * n + (callsign [3]==' '?26:callsign[3]-'A'); // only space or letter
|
n = 27 * n + (callsign [3]==' '?26:callsign[3]-'A'); // only space or letter
|
||||||
n = 27 * n + (callsign [4]==' '?26:callsign[4]-'A');
|
n = 27 * n + (callsign [4]==' '?26:callsign[4]-'A');
|
||||||
n = 27 * n + (callsign [5]==' '?26:callsign[5]-'A');
|
n = 27 * n + (callsign [5]==' '?26:callsign[5]-'A');
|
||||||
|
|
||||||
// Locator encoding
|
// Locator encoding
|
||||||
m = (179 - 10 * (locator[0] - 65) - (locator[2]- 48)) * 180 + 10 * (locator[1] - 65) + locator[3] - 48;
|
m = (179 - 10 * (locator[0] - 65) - (locator[2]- 48)) * 180 + 10 * (locator[1] - 65) + locator[3] - 48;
|
||||||
|
|
||||||
// Power encoding
|
// Power encoding
|
||||||
m = m * 128 + power + 64;
|
m = m * 128 + power + 64;
|
||||||
|
|
||||||
*N = n;
|
*N = n;
|
||||||
*M = m;
|
*M = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pack_msg(unsigned long int N, unsigned long int M, unsigned char c[])
|
void Pack_msg(unsigned long int N, unsigned long int M, unsigned char c[])
|
||||||
{
|
{
|
||||||
// Bit packing
|
// Bit packing
|
||||||
// Store in 11 characters because we need 81 bits for FEC correction
|
// Store in 11 characters because we need 81 bits for FEC correction
|
||||||
c[0] = N >> 20; // Callsign
|
c[0] = N >> 20; // Callsign
|
||||||
c[1] = N >> 12;
|
c[1] = N >> 12;
|
||||||
c[2] = N >> 4;
|
c[2] = N >> 4;
|
||||||
c[3] = N ;
|
c[3] = N ;
|
||||||
c[3] = c[3] << 4;
|
c[3] = c[3] << 4;
|
||||||
|
|
||||||
c[3] = c[3] | (M >> 18); // locator and power
|
c[3] = c[3] | (M >> 18); // locator and power
|
||||||
c[4] = M >> 10;
|
c[4] = M >> 10;
|
||||||
c[5] = M >> 2;
|
c[5] = M >> 2;
|
||||||
c[6] = M & 0x03;
|
c[6] = M & 0x03;
|
||||||
c[6] = c[6] << 6;
|
c[6] = c[6] << 6;
|
||||||
|
|
||||||
c[7] = 0; // always at 0
|
c[7] = 0; // always at 0
|
||||||
c[8] = 0;
|
c[8] = 0;
|
||||||
c[9] = 0;
|
c[9] = 0;
|
||||||
c[10] = 0;
|
c[10] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generate_parity(unsigned char c[], unsigned char symbols[])
|
void Generate_parity(unsigned char c[], unsigned char symbols[])
|
||||||
{
|
{
|
||||||
unsigned long int Reg0 = 0, // 32 bits shift register
|
unsigned long int Reg0 = 0, // 32 bits shift register
|
||||||
Reg1 = 0,
|
Reg1 = 0,
|
||||||
result0,
|
result0,
|
||||||
result1;
|
result1;
|
||||||
int count1, // to count the number
|
int count1, // to count the number
|
||||||
count2, // of bits at one
|
count2, // of bits at one
|
||||||
bit_result = 0,
|
bit_result = 0,
|
||||||
i,j,k,l;
|
i,j,k,l;
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
for (j = 0; j < 11; j++) // each byte
|
for (j = 0; j < 11; j++) // each byte
|
||||||
{
|
{
|
||||||
for (i = 7; i >= 0; i--)
|
for (i = 7; i >= 0; i--)
|
||||||
{
|
{
|
||||||
Reg0 = (Reg0 << 1);
|
Reg0 = (Reg0 << 1);
|
||||||
Reg0 = Reg0 | (c[j] >> i); // each bit
|
Reg0 = Reg0 | (c[j] >> i); // each bit
|
||||||
Reg1 = Reg0;
|
Reg1 = Reg0;
|
||||||
|
|
||||||
result0 = Reg0 & POLYNOM_1; // first polynom
|
result0 = Reg0 & POLYNOM_1; // first polynom
|
||||||
count1 = 0;
|
count1 = 0;
|
||||||
|
|
||||||
for (k = 0; k < 32; k ++) // how many bit at one?
|
for (k = 0; k < 32; k ++) // how many bit at one?
|
||||||
{
|
{
|
||||||
bit_result = result0 >> k;
|
bit_result = result0 >> k;
|
||||||
if ((bit_result & 0x01) == 1)
|
if ((bit_result & 0x01) == 1)
|
||||||
count1++;
|
count1++;
|
||||||
}
|
}
|
||||||
if (count1 %2 == 1) // if number of one is odd
|
if (count1 %2 == 1) // if number of one is odd
|
||||||
symbols[l] = 1; // parity = 1
|
symbols[l] = 1; // parity = 1
|
||||||
l++;
|
l++;
|
||||||
|
|
||||||
result1 = Reg1 & POLYNOM_2; // second polynom
|
result1 = Reg1 & POLYNOM_2; // second polynom
|
||||||
count2 = 0;
|
count2 = 0;
|
||||||
|
|
||||||
for (k = 0; k < 32; k ++) // how many bit at one?
|
for (k = 0; k < 32; k ++) // how many bit at one?
|
||||||
{
|
{
|
||||||
bit_result = result1 >> k;
|
bit_result = result1 >> k;
|
||||||
if ((bit_result & 0x01) == 1)
|
if ((bit_result & 0x01) == 1)
|
||||||
count2++;
|
count2++;
|
||||||
}
|
}
|
||||||
if (count2 %2 == 1) // if number of one is odd
|
if (count2 %2 == 1) // if number of one is odd
|
||||||
symbols[l] = 1; // parity = 1
|
symbols[l] = 1; // parity = 1
|
||||||
l++;
|
l++;
|
||||||
} // end of each bit (32) loop
|
} // end of each bit (32) loop
|
||||||
} // end of each byte (11) loop
|
} // end of each byte (11) loop
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interleave(unsigned char symbols[], unsigned char symbols_interleaved[])
|
void Interleave(unsigned char symbols[], unsigned char symbols_interleaved[])
|
||||||
{
|
{
|
||||||
int i,j,k,l,P;
|
int i,j,k,l,P;
|
||||||
|
|
||||||
P = 0;
|
P = 0;
|
||||||
while (P < 162)
|
while (P < 162)
|
||||||
{
|
{
|
||||||
for (k = 0; k <= 255; k++) // bits reverse, ex: 0010 1110 --> 0111 0100
|
for (k = 0; k <= 255; k++) // bits reverse, ex: 0010 1110 --> 0111 0100
|
||||||
{
|
{
|
||||||
i = k;
|
i = k;
|
||||||
j = 0;
|
j = 0;
|
||||||
for (l = 7; l >=0; l--) // hard work is done here...
|
for (l = 7; l >=0; l--) // hard work is done here...
|
||||||
{
|
{
|
||||||
j = j | (i & 0x01) << l;
|
j = j | (i & 0x01) << l;
|
||||||
i = i >> 1;
|
i = i >> 1;
|
||||||
}
|
}
|
||||||
if (j < 162)
|
if (j < 162)
|
||||||
symbols_interleaved[j] = symbols [P++]; // range in interleaved table
|
symbols_interleaved[j] = symbols [P++]; // range in interleaved table
|
||||||
}
|
}
|
||||||
} // end of while, interleaved table is full
|
} // end of while, interleaved table is full
|
||||||
}
|
}
|
||||||
|
|
||||||
void Synchronise(unsigned char symbols_interleaved[], unsigned char symbols_wspr[])
|
void Synchronise(unsigned char symbols_interleaved[], unsigned char symbols_wspr[])
|
||||||
{
|
{
|
||||||
unsigned int sync_word [162]={
|
unsigned int sync_word [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,
|
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,
|
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,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
|
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 i;
|
int i;
|
||||||
|
|
||||||
for (i = 0;i < 162; i++)
|
for (i = 0;i < 162; i++)
|
||||||
symbols_wspr[i] = sync_word[i] + 2 * symbols_interleaved[i];
|
symbols_wspr[i] = sync_word[i] + 2 * symbols_interleaved[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void code_wspr()
|
void code_wspr()
|
||||||
{
|
{
|
||||||
unsigned char symbols_parity [162] = {0}, // contains 2*81 parity bits
|
unsigned char symbols_parity [162] = {0}, // contains 2*81 parity bits
|
||||||
symbols_interleaved [162] = {0}, // contains parity bits after interleaving
|
symbols_interleaved [162] = {0}, // contains parity bits after interleaving
|
||||||
c_packed[11]; // for bit packing
|
c_packed[11]; // for bit packing
|
||||||
|
|
||||||
unsigned long N, // for callsign
|
unsigned long N, // for callsign
|
||||||
M; // for locator and power
|
M; // for locator and power
|
||||||
|
|
||||||
|
|
||||||
Code_msg(wspr_message, &N, &M);
|
Code_msg(wspr_message, &N, &M);
|
||||||
|
|
||||||
Pack_msg (N, M, c_packed);
|
Pack_msg (N, M, c_packed);
|
||||||
|
|
||||||
Generate_parity (c_packed, symbols_parity);
|
Generate_parity (c_packed, symbols_parity);
|
||||||
|
|
||||||
Interleave (symbols_parity, symbols_interleaved);
|
Interleave (symbols_parity, symbols_interleaved);
|
||||||
|
|
||||||
Synchronise (symbols_interleaved, wspr_symbols);
|
Synchronise (symbols_interleaved, wspr_symbols);
|
||||||
|
|
||||||
wspr_encoded = 1; // a message has been encoded
|
wspr_encoded = 1; // a message has been encoded
|
||||||
|
|
||||||
sprintf(pbuf,"WSPR encoding ok\n\r");
|
sprintf(pbuf,"WSPR encoding ok\n\r");
|
||||||
putst1(pbuf);
|
putst1(pbuf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
55
wspr.h
55
wspr.h
|
@ -1,31 +1,24 @@
|
||||||
/* Functions for wspr encoding
|
/* Functions for wspr encoding
|
||||||
|
|
||||||
|
|
||||||
F8CHK 29/03/2011 */
|
F8CHK 29/03/2011 */
|
||||||
|
|
||||||
#ifndef __WSPR_H
|
#ifndef __WSPR_H
|
||||||
#define __WSPR_H
|
#define __WSPR_H
|
||||||
|
|
||||||
void Code_msg(char[], unsigned long int*, unsigned long int*); // encode callsign, locator and power
|
void Code_msg(char[], unsigned long int*, unsigned long int*); // encode callsign, locator and power
|
||||||
void Pack_msg(unsigned long int, unsigned long int, unsigned char[]);// packed 50 bits in 11 bytes
|
void Pack_msg(unsigned long int, unsigned long int, unsigned char[]);// packed 50 bits in 11 bytes
|
||||||
void Generate_parity(unsigned char[], unsigned char[]); // generate 162 parity bits
|
void Generate_parity(unsigned char[], unsigned char[]); // generate 162 parity bits
|
||||||
void Interleave( unsigned char[], unsigned char[]); // interleave the 162 parity bits
|
void Interleave( unsigned char[], unsigned char[]); // interleave the 162 parity bits
|
||||||
void Synchronise(unsigned char[], unsigned char[]); // synchronize with a pseudo random pattern
|
void Synchronise(unsigned char[], unsigned char[]); // synchronize with a pseudo random pattern
|
||||||
|
|
||||||
void code_wspr(void); // encode the wspr message
|
void code_wspr(void); // encode the wspr message
|
||||||
void go_wspr(void); // start WSPR beacon mode
|
void go_wspr(void); // start WSPR beacon mode
|
||||||
void go_wspr_tx(void); // set cube in wspr tx mode
|
void go_wspr_tx(void); // set cube in wspr tx mode
|
||||||
|
|
||||||
#define WSPR_OFFSET 1.4648 // tone separation
|
#define WSPR_OFFSET 1.4648 // tone separation
|
||||||
|
|
||||||
#define POLYNOM_1 0xf2d05351 // polynoms for
|
#define POLYNOM_1 0xf2d05351 // polynoms for
|
||||||
#define POLYNOM_2 0xe4613c47 // parity generator
|
#define POLYNOM_2 0xe4613c47 // parity generator
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue