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