Skip to content

Commit 0568204

Browse files
committed
Ensure FT8 support works on ATmega procs
1 parent ea72fe0 commit 0568204

File tree

6 files changed

+125
-60
lines changed

6 files changed

+125
-60
lines changed

README.md

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Please feel free to use the issues feature of GitHub if you run into problems or
66

77
Thanks For Your Support!
88
------------------------
9-
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!
9+
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!
1010

1111
Hardware Requirements and Setup
1212
-------------------------------
@@ -28,7 +28,7 @@ There is a simple example that is placed in your examples menu under JTEncode. O
2828

2929
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.
3030

31-
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.
31+
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.
3232

3333
An instance of the JTEncode object is created:
3434

@@ -64,6 +64,12 @@ On sketch startup, the mode parameters are set based on which mode is currently
6464
tone_spacing = WSPR_TONE_SPACING;
6565
tone_delay = WSPR_DELAY;
6666
break;
67+
case MODE_FT8:
68+
freq = FT8_DEFAULT_FREQ;
69+
symbol_count = FT8_SYMBOL_COUNT; // From the library defines
70+
tone_spacing = FT8_TONE_SPACING;
71+
tone_delay = FT8_DELAY;
72+
break;
6773
case MODE_FSQ_2:
6874
freq = FSQ_DEFAULT_FREQ;
6975
tone_spacing = FSQ_TONE_SPACING;
@@ -105,6 +111,9 @@ Before transmit, the proper class method is chosen based on the desired mode, th
105111
case MODE_WSPR:
106112
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
107113
break;
114+
case MODE_FT8:
115+
jtencode.ft_encode(message, tx_buffer);
116+
break;
108117
case MODE_FSQ_2:
109118
case MODE_FSQ_3:
110119
case MODE_FSQ_4_5:
@@ -135,8 +144,8 @@ Public Methods
135144
* a channel symbol table.
136145
*
137146
* message - Plaintext Type 6 message.
138-
* symbols - Array of channel symbols to transmit retunred by the method.
139-
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
147+
* symbols - Array of channel symbols to transmit returned by the method.
148+
* Ensure that you pass a uint8_t array of at least size JT65_SYMBOL_COUNT to the method.
140149
*
141150
*/
142151
```
@@ -149,8 +158,8 @@ Public Methods
149158
* a channel symbol table.
150159
*
151160
* message - Plaintext Type 6 message.
152-
* symbols - Array of channel symbols to transmit retunred by the method.
153-
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
161+
* symbols - Array of channel symbols to transmit returned by the method.
162+
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
154163
*
155164
*/
156165
```
@@ -164,8 +173,8 @@ Public Methods
164173
* a channel symbol table.
165174
*
166175
* message - Plaintext Type 6 message.
167-
* symbols - Array of channel symbols to transmit retunred by the method.
168-
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
176+
* symbols - Array of channel symbols to transmit returned by the method.
177+
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
169178
*
170179
*/
171180
```
@@ -178,14 +187,30 @@ Public Methods
178187
* Takes an arbitrary message of up to 13 allowable characters and returns
179188
*
180189
* call - Callsign (6 characters maximum).
181-
* loc - Maidenhead grid locator (4 charcters maximum).
190+
* loc - Maidenhead grid locator (4 characters maximum).
182191
* dbm - Output power in dBm.
183-
* symbols - Array of channel symbols to transmit retunred by the method.
184-
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
192+
* symbols - Array of channel symbols to transmit returned by the method.
193+
* Ensure that you pass a uint8_t array of at least size WSPR_SYMBOL_COUNT to the method.
185194
*
186195
*/
187196
```
188197

198+
### ft8_encode()
199+
```
200+
/*
201+
* ft8_encode(const char * message, uint8_t * symbols)
202+
*
203+
* Takes an arbitrary message of up to 13 allowable characters or a telemetry message
204+
* of up to 18 hexadecimal digit (in string format) and returns a channel symbol table.
205+
* Encoded for the FT8 protocol used in WSJT-X v2.0 and beyond (79 channel symbols).
206+
*
207+
* message - Type 0.0 free text message or Type 0.5 telemetry message.
208+
* symbols - Array of channel symbols to transmit returned by the method.
209+
* Ensure that you pass a uint8_t array of at least size FT8_SYMBOL_COUNT to the method.
210+
*
211+
*/
212+
```
213+
189214
### fsq_encode()
190215
```
191216
/*
@@ -195,7 +220,7 @@ Public Methods
195220
*
196221
* from_call - Callsign of issuing station (maximum size: 20)
197222
* message - Null-terminated message string, no greater than 130 chars in length
198-
* symbols - Array of channel symbols to transmit retunred by the method.
223+
* symbols - Array of channel symbols to transmit returned by the method.
199224
* Ensure that you pass a uint8_t array of at least the size of the message
200225
* plus 5 characters to the method. Terminated in 0xFF.
201226
*
@@ -213,7 +238,7 @@ Public Methods
213238
* to_call - Callsign to which message is directed (maximum size: 20)
214239
* cmd - Directed command
215240
* message - Null-terminated message string, no greater than 100 chars in length
216-
* symbols - Array of channel symbols to transmit retunred by the method.
241+
* symbols - Array of channel symbols to transmit returned by the method.
217242
* Ensure that you pass a uint8_t array of at least the size of the message
218243
* plus 5 characters to the method. Terminated in 0xFF.
219244
*
@@ -226,16 +251,20 @@ Here are the defines, structs, and enumerations you will find handy to use with
226251

227252
Defines:
228253

229-
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, JT4_SYMBOL_COUNT, WSPR_SYMBOL_COUNT
254+
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, JT4_SYMBOL_COUNT, WSPR_SYMBOL_COUNT, FT8_SYMBOL_COUNT
230255

231256
Acknowledgements
232257
----------------
233-
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.
258+
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.
234259

235260
Also, a big thank you to Murray Greenman, ZL1BPU for working allowing me to pick his brain regarding his neat new mode FSQ.
236261

237262
Changelog
238263
---------
264+
* v1.2.0
265+
266+
* Add support for FT8 protocol (79 symbol version introduced December 2018)
267+
239268
* v1.1.3
240269

241270
* Add support for ESP8266

examples/Si5351JTDemo/Si5351JTDemo.ino

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//
2-
// Simple JT65/JT9/WSPR/FSQ beacon for Arduino, with the Etherkit
2+
// Simple JT65/JT9/JT4/FT8/WSPR/FSQ beacon for Arduino, with the Etherkit
33
// Si5351A Breakout Board, by Jason Milldrum NT7S.
44
//
55
// Transmit an abritrary message of up to 13 valid characters
6-
// (a Type 6 message) in JT65 and JT9, or a standard Type 1
7-
// message in WSPR.
6+
// (a Type 6 message) in JT65, JT9, JT4, a type 0.0 or type 0.5 FT8 message,
7+
// a FSQ message, or a standard Type 1 message in WSPR.
88
//
99
// Connect a momentary push button to pin 12 to use as the
1010
// transmit trigger. Get fancy by adding your own code to trigger
@@ -43,11 +43,12 @@
4343
#include "Wire.h"
4444

4545
// Mode defines
46-
#define JT9_TONE_SPACING 174 // ~1.74 Hz
47-
#define JT65_TONE_SPACING 269 // ~2.69 Hz
48-
#define JT4_TONE_SPACING 437 // ~4.37 Hz
49-
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
50-
#define FSQ_TONE_SPACING 879 // ~8.79 Hz
46+
#define JT9_TONE_SPACING 174 // ~1.74 Hz
47+
#define JT65_TONE_SPACING 269 // ~2.69 Hz
48+
#define JT4_TONE_SPACING 437 // ~4.37 Hz
49+
#define WSPR_TONE_SPACING 146 // ~1.46 Hz
50+
#define FSQ_TONE_SPACING 879 // ~8.79 Hz
51+
#define FT8_TONE_SPACING 625 // ~6.25 Hz
5152

5253
#define JT9_DELAY 576 // Delay value for JT9-1
5354
#define JT65_DELAY 371 // Delay in ms for JT65A
@@ -57,12 +58,14 @@
5758
#define FSQ_3_DELAY 333 // Delay value for 3 baud FSQ
5859
#define FSQ_4_5_DELAY 222 // Delay value for 4.5 baud FSQ
5960
#define FSQ_6_DELAY 167 // Delay value for 6 baud FSQ
61+
#define FT8_DELAY 159 // Delay value for FT8
6062

6163
#define JT9_DEFAULT_FREQ 14078700UL
6264
#define JT65_DEFAULT_FREQ 14078300UL
6365
#define JT4_DEFAULT_FREQ 14078500UL
6466
#define WSPR_DEFAULT_FREQ 14097200UL
6567
#define FSQ_DEFAULT_FREQ 7105350UL // Base freq is 1350 Hz higher than dial freq in USB
68+
#define FT8_DEFAULT_FREQ 14075000UL
6669

6770
#define DEFAULT_MODE MODE_JT65
6871

@@ -72,7 +75,7 @@
7275

7376
// Enumerations
7477
enum mode {MODE_JT9, MODE_JT65, MODE_JT4, MODE_WSPR, MODE_FSQ_2, MODE_FSQ_3,
75-
MODE_FSQ_4_5, MODE_FSQ_6};
78+
MODE_FSQ_4_5, MODE_FSQ_6, MODE_FT8};
7679

7780
// Class instantiation
7881
Si5351 si5351;
@@ -139,6 +142,9 @@ void set_tx_buffer()
139142
case MODE_WSPR:
140143
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
141144
break;
145+
case MODE_FT8:
146+
jtencode.ft8_encode(message, tx_buffer);
147+
break;
142148
case MODE_FSQ_2:
143149
case MODE_FSQ_3:
144150
case MODE_FSQ_4_5:
@@ -193,6 +199,12 @@ void setup()
193199
tone_spacing = WSPR_TONE_SPACING;
194200
tone_delay = WSPR_DELAY;
195201
break;
202+
case MODE_FT8:
203+
freq = FT8_DEFAULT_FREQ;
204+
symbol_count = FT8_SYMBOL_COUNT; // From the library defines
205+
tone_spacing = FT8_TONE_SPACING;
206+
tone_delay = FT8_DELAY;
207+
break;
196208
case MODE_FSQ_2:
197209
freq = FSQ_DEFAULT_FREQ;
198210
tone_spacing = FSQ_TONE_SPACING;

src/JTEncode.cpp

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ JTEncode::JTEncode(void)
5151
}
5252

5353
/*
54-
* jt65_encode(const char * msg, uint8_t * symbols)
54+
* jt65_encode(const char * message, uint8_t * symbols)
5555
*
5656
* Takes an arbitrary message of up to 13 allowable characters and returns
5757
* a channel symbol table.
5858
*
5959
* message - Plaintext Type 6 message.
60-
* symbols - Array of channel symbols to transmit retunred by the method.
61-
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
60+
* symbols - Array of channel symbols to transmit returned by the method.
61+
* Ensure that you pass a uint8_t array of at least size JT65_SYMBOL_COUNT to the method.
6262
*
6363
*/
6464
void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
@@ -95,14 +95,14 @@ void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
9595
}
9696

9797
/*
98-
* jt9_encode(const char * msg, uint8_t * symbols)
98+
* jt9_encode(const char * message, uint8_t * symbols)
9999
*
100100
* Takes an arbitrary message of up to 13 allowable characters and returns
101101
* a channel symbol table.
102102
*
103103
* message - Plaintext Type 6 message.
104-
* symbols - Array of channel symbols to transmit retunred by the method.
105-
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
104+
* symbols - Array of channel symbols to transmit returned by the method.
105+
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
106106
*
107107
*/
108108
void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
@@ -144,14 +144,14 @@ void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
144144
}
145145

146146
/*
147-
* jt4_encode(const char * msg, uint8_t * symbols)
147+
* jt4_encode(const char * message, uint8_t * symbols)
148148
*
149149
* Takes an arbitrary message of up to 13 allowable characters and returns
150150
* a channel symbol table.
151151
*
152152
* message - Plaintext Type 6 message.
153-
* symbols - Array of channel symbols to transmit retunred by the method.
154-
* Ensure that you pass a uint8_t array of size JT4_SYMBOL_COUNT to the method.
153+
* symbols - Array of channel symbols to transmit returned by the method.
154+
* Ensure that you pass a uint8_t array of at least size JT9_SYMBOL_COUNT to the method.
155155
*
156156
*/
157157
void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
@@ -191,10 +191,10 @@ void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
191191
* Takes an arbitrary message of up to 13 allowable characters and returns
192192
*
193193
* call - Callsign (6 characters maximum).
194-
* loc - Maidenhead grid locator (4 charcters maximum).
194+
* loc - Maidenhead grid locator (4 characters maximum).
195195
* dbm - Output power in dBm.
196-
* symbols - Array of channel symbols to transmit retunred by the method.
197-
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
196+
* symbols - Array of channel symbols to transmit returned by the method.
197+
* Ensure that you pass a uint8_t array of at least size WSPR_SYMBOL_COUNT to the method.
198198
*
199199
*/
200200
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
235235
*
236236
* from_call - Callsign of issuing station (maximum size: 20)
237237
* message - Null-terminated message string, no greater than 130 chars in length
238-
* symbols - Array of channel symbols to transmit retunred by the method.
238+
* symbols - Array of channel symbols to transmit returned by the method.
239239
* Ensure that you pass a uint8_t array of at least the size of the message
240240
* plus 5 characters to the method. Terminated in 0xFF.
241241
*
@@ -322,7 +322,7 @@ void JTEncode::fsq_encode(const char * from_call, const char * message, uint8_t
322322
* to_call - Callsign to which message is directed (maximum size: 20)
323323
* cmd - Directed command
324324
* message - Null-terminated message string, no greater than 100 chars in length
325-
* symbols - Array of channel symbols to transmit retunred by the method.
325+
* symbols - Array of channel symbols to transmit returned by the method.
326326
* Ensure that you pass a uint8_t array of at least the size of the message
327327
* plus 5 characters to the method. Terminated in 0xFF.
328328
*
@@ -406,28 +406,40 @@ void JTEncode::fsq_dir_encode(const char * from_call, const char * to_call, cons
406406
symbols[symbol_pos] = 0xff;
407407
}
408408

409+
/*
410+
* ft8_encode(const char * message, uint8_t * symbols)
411+
*
412+
* Takes an arbitrary message of up to 13 allowable characters or a telemetry message
413+
* of up to 18 hexadecimal digit (in string format) and returns a channel symbol table.
414+
* Encoded for the FT8 protocol used in WSJT-X v2.0 and beyond (79 channel symbols).
415+
*
416+
* message - Type 0.0 free text message or Type 0.5 telemetry message.
417+
* symbols - Array of channel symbols to transmit returned by the method.
418+
* Ensure that you pass a uint8_t array of at least size FT8_SYMBOL_COUNT to the method.
419+
*
420+
*/
409421
void JTEncode::ft8_encode(const char * msg, uint8_t * symbols)
410422
{
411-
uint8_t i;
412-
413-
char message[14];
414-
memset(message, 0, 14);
415-
strcpy(message, msg);
416-
417-
// Bit packing
418-
// -----------
419-
uint8_t c[77];
420-
memset(c, 0, 77);
421-
ft8_bit_packing(message, c);
422-
423-
// Message Encoding
424-
// ----------------
425-
uint8_t s[FT8_BIT_COUNT];
426-
ft8_encode(c, s);
427-
428-
// Merge with sync vector
429-
// ----------------------
430-
ft8_merge_sync_vector(s, symbols);
423+
uint8_t i;
424+
425+
char message[19];
426+
memset(message, 0, 19);
427+
strcpy(message, msg);
428+
429+
// Bit packing
430+
// -----------
431+
uint8_t c[77];
432+
memset(c, 0, 77);
433+
ft8_bit_packing(message, c);
434+
435+
// Message Encoding
436+
// ----------------
437+
uint8_t s[FT8_BIT_COUNT];
438+
ft8_encode(c, s);
439+
440+
// Merge with sync vector
441+
// ----------------------
442+
ft8_merge_sync_vector(s, symbols);
431443
}
432444

433445
/* Private Class Members */
@@ -586,7 +598,7 @@ void JTEncode::ft_message_prep(char * message)
586598
uint8_t i;
587599
char temp_msg[14];
588600

589-
snprintf(temp_msg, 14, "%*s", 13, message);
601+
snprintf(temp_msg, 14, "%13s", message);
590602

591603
// Convert all chars to uppercase
592604
for(i = 0; i < 13; i++)
@@ -1140,7 +1152,11 @@ void JTEncode::ft8_encode(uint8_t* codeword, uint8_t* symbols)
11401152
uint32_t nsum = 0;
11411153
for(j = 0; j < FT8_K; ++j)
11421154
{
1143-
uint8_t bits = generator_bits[i][j / 8];
1155+
#if defined(__arm__)
1156+
uint8_t bits = generator_bits[i][j / 8];
1157+
#else
1158+
uint8_t bits = pgm_read_byte(&(generator_bits[i][j / 8]));
1159+
#endif
11441160
bits <<= (j % 8);
11451161
bits &= 0x80;
11461162
bits >>= 7;

0 commit comments

Comments
 (0)