Ensure FT8 support works on ATmega procs

pull/16/head
Jason Milldrum 2018-12-09 18:19:39 -08:00
rodzic ea72fe0c16
commit 05682049d1
6 zmienionych plików z 121 dodań i 56 usunięć

Wyświetl plik

@ -6,7 +6,7 @@ Please feel free to use the issues feature of GitHub if you run into problems or
Thanks For Your Support!
------------------------
If you would like to support my library development efforts, I would ask that you please consider becoming my patron on [Patreon](https://www.patreon.com/NT7S). Thank you!
If you would like to support my library development efforts, I would ask that you please consider sending a [PayPal tip](https://paypal.me/NT7S). Thank you!
Hardware Requirements and Setup
-------------------------------
@ -28,7 +28,7 @@ There is a simple example that is placed in your examples menu under JTEncode. O
To run this example, be sure to download the [Si5351Arduino](https://github.com/etherkit/Si5351Arduino) library and follow the instructions there to connect the Si5351A Breakout Board to your Arduino. In order to trigger transmissions, you will also need to connect a momentary pushbutton from pin 12 of the Arduino to ground.
The example sketch itself is fairly straightforward. JT65, JT9, JT4, WSPR, and FSQ modes are modulated in same way: phase-continuous multiple-frequency shift keying (MFSK). The message to be transmitted is passed to the JTEncode method corresponding to the desired mode, along with a pointer to an array which holds the returned channel symbols. When the pushbutton is pushed, the sketch then transmits each channel symbol sequentially as an offset from the base frequency given in the sketch define section.
The example sketch itself is fairly straightforward. JT65, JT9, JT4, FT8, WSPR, and FSQ modes are modulated in same way: phase-continuous multiple-frequency shift keying (MFSK). The message to be transmitted is passed to the JTEncode method corresponding to the desired mode, along with a pointer to an array which holds the returned channel symbols. When the pushbutton is pushed, the sketch then transmits each channel symbol sequentially as an offset from the base frequency given in the sketch define section.
An instance of the JTEncode object is created:
@ -64,6 +64,12 @@ On sketch startup, the mode parameters are set based on which mode is currently
tone_spacing = WSPR_TONE_SPACING;
tone_delay = WSPR_DELAY;
break;
case MODE_FT8:
freq = FT8_DEFAULT_FREQ;
symbol_count = FT8_SYMBOL_COUNT; // From the library defines
tone_spacing = FT8_TONE_SPACING;
tone_delay = FT8_DELAY;
break;
case MODE_FSQ_2:
freq = FSQ_DEFAULT_FREQ;
tone_spacing = FSQ_TONE_SPACING;
@ -105,6 +111,9 @@ Before transmit, the proper class method is chosen based on the desired mode, th
case MODE_WSPR:
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
break;
case MODE_FT8:
jtencode.ft_encode(message, tx_buffer);
break;
case MODE_FSQ_2:
case MODE_FSQ_3:
case MODE_FSQ_4_5:
@ -135,8 +144,8 @@ Public Methods
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT65_SYMBOL_COUNT to the method.
*
*/
```
@ -149,8 +158,8 @@ Public Methods
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
*
*/
```
@ -164,8 +173,8 @@ Public Methods
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
*
*/
```
@ -178,14 +187,30 @@ Public Methods
* Takes an arbitrary message of up to 13 allowable characters and returns
*
* call - Callsign (6 characters maximum).
* loc - Maidenhead grid locator (4 charcters maximum).
* loc - Maidenhead grid locator (4 characters maximum).
* dbm - Output power in dBm.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size WSPR_SYMBOL_COUNT to the method.
*
*/
```
### ft8_encode()
```
/*
* ft8_encode(const char * message, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters or a telemetry message
* of up to 18 hexadecimal digit (in string format) and returns a channel symbol table.
* Encoded for the FT8 protocol used in WSJT-X v2.0 and beyond (79 channel symbols).
*
* message - Type 0.0 free text message or Type 0.5 telemetry message.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size FT8_SYMBOL_COUNT to the method.
*
*/
```
### fsq_encode()
```
/*
@ -195,7 +220,7 @@ Public Methods
*
* from_call - Callsign of issuing station (maximum size: 20)
* message - Null-terminated message string, no greater than 130 chars in length
* symbols - Array of channel symbols to transmit retunred by the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least the size of the message
* plus 5 characters to the method. Terminated in 0xFF.
*
@ -213,7 +238,7 @@ Public Methods
* to_call - Callsign to which message is directed (maximum size: 20)
* cmd - Directed command
* message - Null-terminated message string, no greater than 100 chars in length
* symbols - Array of channel symbols to transmit retunred by the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least the size of the message
* plus 5 characters to the method. Terminated in 0xFF.
*
@ -226,16 +251,20 @@ Here are the defines, structs, and enumerations you will find handy to use with
Defines:
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, JT4_SYMBOL_COUNT, WSPR_SYMBOL_COUNT
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, JT4_SYMBOL_COUNT, WSPR_SYMBOL_COUNT, FT8_SYMBOL_COUNT
Acknowledgements
----------------
Many thanks to Joe Taylor K1JT for his innovative work in amateur radio. We are lucky to have him. The algorithms in this program were derived from the source code in the [WSJT](http://sourceforge.net/projects/wsjt/) suite of applications. Also, many thanks for Andy Talbot G4JNT for [his paper](http://www.g4jnt.com/JTModesBcns.htm) on the WSPR coding protocol, which helped me to understand the WSPR encoding process, which in turn helped me to understand the related JT protocols.
Many thanks to Joe Taylor K1JT for his innovative work in amateur radio. We are lucky to have him. The algorithms in this program were derived from the source code in the [WSJT-X](https://sourceforge.net/p/wsjt/) suite of applications. Also, many thanks for Andy Talbot G4JNT for [his paper](http://www.g4jnt.com/JTModesBcns.htm) on the WSPR coding protocol, which helped me to understand the WSPR encoding process, which in turn helped me to understand the related JT protocols.
Also, a big thank you to Murray Greenman, ZL1BPU for working allowing me to pick his brain regarding his neat new mode FSQ.
Changelog
---------
* v1.2.0
* Add support for FT8 protocol (79 symbol version introduced December 2018)
* v1.1.3
* Add support for ESP8266

Wyświetl plik

@ -1,10 +1,10 @@
//
// Simple JT65/JT9/WSPR/FSQ beacon for Arduino, with the Etherkit
// Simple JT65/JT9/JT4/FT8/WSPR/FSQ beacon for Arduino, with the Etherkit
// Si5351A Breakout Board, by Jason Milldrum NT7S.
//
// Transmit an abritrary message of up to 13 valid characters
// (a Type 6 message) in JT65 and JT9, or a standard Type 1
// message in WSPR.
// (a Type 6 message) in JT65, JT9, JT4, a type 0.0 or type 0.5 FT8 message,
// a FSQ message, or a standard Type 1 message in WSPR.
//
// Connect a momentary push button to pin 12 to use as the
// transmit trigger. Get fancy by adding your own code to trigger
@ -43,11 +43,12 @@
#include "Wire.h"
// Mode defines
#define JT9_TONE_SPACING 174 // ~1.74 Hz
#define JT65_TONE_SPACING 269 // ~2.69 Hz
#define JT4_TONE_SPACING 437 // ~4.37 Hz
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
#define FSQ_TONE_SPACING 879 // ~8.79 Hz
#define JT9_TONE_SPACING 174 // ~1.74 Hz
#define JT65_TONE_SPACING 269 // ~2.69 Hz
#define JT4_TONE_SPACING 437 // ~4.37 Hz
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
#define FSQ_TONE_SPACING 879 // ~8.79 Hz
#define FT8_TONE_SPACING 625 // ~6.25 Hz
#define JT9_DELAY 576 // Delay value for JT9-1
#define JT65_DELAY 371 // Delay in ms for JT65A
@ -57,12 +58,14 @@
#define FSQ_3_DELAY 333 // Delay value for 3 baud FSQ
#define FSQ_4_5_DELAY 222 // Delay value for 4.5 baud FSQ
#define FSQ_6_DELAY 167 // Delay value for 6 baud FSQ
#define FT8_DELAY 159 // Delay value for FT8
#define JT9_DEFAULT_FREQ 14078700UL
#define JT65_DEFAULT_FREQ 14078300UL
#define JT4_DEFAULT_FREQ 14078500UL
#define WSPR_DEFAULT_FREQ 14097200UL
#define FSQ_DEFAULT_FREQ 7105350UL // Base freq is 1350 Hz higher than dial freq in USB
#define FT8_DEFAULT_FREQ 14075000UL
#define DEFAULT_MODE MODE_JT65
@ -72,7 +75,7 @@
// Enumerations
enum mode {MODE_JT9, MODE_JT65, MODE_JT4, MODE_WSPR, MODE_FSQ_2, MODE_FSQ_3,
MODE_FSQ_4_5, MODE_FSQ_6};
MODE_FSQ_4_5, MODE_FSQ_6, MODE_FT8};
// Class instantiation
Si5351 si5351;
@ -139,6 +142,9 @@ void set_tx_buffer()
case MODE_WSPR:
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
break;
case MODE_FT8:
jtencode.ft8_encode(message, tx_buffer);
break;
case MODE_FSQ_2:
case MODE_FSQ_3:
case MODE_FSQ_4_5:
@ -193,6 +199,12 @@ void setup()
tone_spacing = WSPR_TONE_SPACING;
tone_delay = WSPR_DELAY;
break;
case MODE_FT8:
freq = FT8_DEFAULT_FREQ;
symbol_count = FT8_SYMBOL_COUNT; // From the library defines
tone_spacing = FT8_TONE_SPACING;
tone_delay = FT8_DELAY;
break;
case MODE_FSQ_2:
freq = FSQ_DEFAULT_FREQ;
tone_spacing = FSQ_TONE_SPACING;

Wyświetl plik

@ -51,14 +51,14 @@ JTEncode::JTEncode(void)
}
/*
* jt65_encode(const char * msg, uint8_t * symbols)
* jt65_encode(const char * message, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT65_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
@ -95,14 +95,14 @@ void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
}
/*
* jt9_encode(const char * msg, uint8_t * symbols)
* jt9_encode(const char * message, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
@ -144,14 +144,14 @@ void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
}
/*
* jt4_encode(const char * msg, uint8_t * symbols)
* jt4_encode(const char * message, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
*
* message - Plaintext Type 6 message.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size JT4_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
@ -191,10 +191,10 @@ void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
* Takes an arbitrary message of up to 13 allowable characters and returns
*
* call - Callsign (6 characters maximum).
* loc - Maidenhead grid locator (4 charcters maximum).
* loc - Maidenhead grid locator (4 characters maximum).
* dbm - Output power in dBm.
* symbols - Array of channel symbols to transmit retunred by the method.
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size WSPR_SYMBOL_COUNT to the method.
*
*/
void JTEncode::wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
@ -235,7 +235,7 @@ void JTEncode::wspr_encode(const char * call, const char * loc, const uint8_t db
*
* from_call - Callsign of issuing station (maximum size: 20)
* message - Null-terminated message string, no greater than 130 chars in length
* symbols - Array of channel symbols to transmit retunred by the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least the size of the message
* plus 5 characters to the method. Terminated in 0xFF.
*
@ -322,7 +322,7 @@ void JTEncode::fsq_encode(const char * from_call, const char * message, uint8_t
* to_call - Callsign to which message is directed (maximum size: 20)
* cmd - Directed command
* message - Null-terminated message string, no greater than 100 chars in length
* symbols - Array of channel symbols to transmit retunred by the method.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least the size of the message
* plus 5 characters to the method. Terminated in 0xFF.
*
@ -406,28 +406,40 @@ void JTEncode::fsq_dir_encode(const char * from_call, const char * to_call, cons
symbols[symbol_pos] = 0xff;
}
/*
* ft8_encode(const char * message, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters or a telemetry message
* of up to 18 hexadecimal digit (in string format) and returns a channel symbol table.
* Encoded for the FT8 protocol used in WSJT-X v2.0 and beyond (79 channel symbols).
*
* message - Type 0.0 free text message or Type 0.5 telemetry message.
* symbols - Array of channel symbols to transmit returned by the method.
* Ensure that you pass a uint8_t array of at least size FT8_SYMBOL_COUNT to the method.
*
*/
void JTEncode::ft8_encode(const char * msg, uint8_t * symbols)
{
uint8_t i;
uint8_t i;
char message[14];
memset(message, 0, 14);
strcpy(message, msg);
char message[19];
memset(message, 0, 19);
strcpy(message, msg);
// Bit packing
// -----------
uint8_t c[77];
memset(c, 0, 77);
ft8_bit_packing(message, c);
// Bit packing
// -----------
uint8_t c[77];
memset(c, 0, 77);
ft8_bit_packing(message, c);
// Message Encoding
// ----------------
uint8_t s[FT8_BIT_COUNT];
ft8_encode(c, s);
// Message Encoding
// ----------------
uint8_t s[FT8_BIT_COUNT];
ft8_encode(c, s);
// Merge with sync vector
// ----------------------
ft8_merge_sync_vector(s, symbols);
// Merge with sync vector
// ----------------------
ft8_merge_sync_vector(s, symbols);
}
/* Private Class Members */
@ -586,7 +598,7 @@ void JTEncode::ft_message_prep(char * message)
uint8_t i;
char temp_msg[14];
snprintf(temp_msg, 14, "%*s", 13, message);
snprintf(temp_msg, 14, "%13s", message);
// Convert all chars to uppercase
for(i = 0; i < 13; i++)
@ -1140,7 +1152,11 @@ void JTEncode::ft8_encode(uint8_t* codeword, uint8_t* symbols)
uint32_t nsum = 0;
for(j = 0; j < FT8_K; ++j)
{
uint8_t bits = generator_bits[i][j / 8];
#if defined(__arm__)
uint8_t bits = generator_bits[i][j / 8];
#else
uint8_t bits = pgm_read_byte(&(generator_bits[i][j / 8]));
#endif
bits <<= (j % 8);
bits &= 0x80;
bits >>= 7;

Wyświetl plik

@ -31,6 +31,10 @@
#include <stdint.h>
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
#include <avr/pgmspace.h>
#endif
#define JT65_SYMBOL_COUNT 126
#define JT9_SYMBOL_COUNT 85
#define JT4_SYMBOL_COUNT 207

Wyświetl plik

@ -3,6 +3,10 @@
#include <stdint.h>
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
#include <avr/pgmspace.h>
#endif
const uint8_t generator_bits[83][12] PROGMEM =
{
{0b10000011, 0b00101001, 0b11001110, 0b00010001, 0b10111111, 0b00110001, 0b11101010, 0b11110101, 0b00001001, 0b11110010, 0b01111111, 0b11000000},

BIN
src/generator.h.gch 100644

Plik binarny nie jest wyświetlany.