Skip to content

Commit 41c9411

Browse files
committed
Fix macro define A0 in KA9Q lib that conflicts with common Arduino port def
1 parent 75827c9 commit 41c9411

File tree

8 files changed

+779
-55
lines changed

8 files changed

+779
-55
lines changed

COPYING

Lines changed: 621 additions & 0 deletions
Large diffs are not rendered by default.

JTEncode.cpp

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ JTEncode::JTEncode(void)
4747
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
4848
*
4949
*/
50-
5150
void JTEncode::jt65_encode(char * message, uint8_t * symbols)
5251
{
5352
// Ensure that the message text conforms to standards
@@ -88,7 +87,6 @@ void JTEncode::jt65_encode(char * message, uint8_t * symbols)
8887
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
8988
*
9089
*/
91-
9290
void JTEncode::jt9_encode(char * message, uint8_t * symbols)
9391
{
9492
// Ensure that the message text conforms to standards
@@ -123,6 +121,44 @@ void JTEncode::jt9_encode(char * message, uint8_t * symbols)
123121
jt9_merge_sync_vector(a, symbols);
124122
}
125123

124+
/*
125+
* jt9_encode(char * message, uint8_t * symbols)
126+
*
127+
* Takes an arbitrary message of up to 13 allowable characters and returns
128+
* a channel symbol table.
129+
*
130+
* message - Plaintext Type 6 message.
131+
* symbols - Array of channel symbols to transmit retunred by the method.
132+
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
133+
*
134+
*/
135+
void JTEncode::jt4_encode(char * message, uint8_t * symbols)
136+
{
137+
// Ensure that the message text conforms to standards
138+
// --------------------------------------------------
139+
jt_message_prep(message);
140+
141+
// Bit packing
142+
// -----------
143+
uint8_t c[13];
144+
jt9_bit_packing(message, c);
145+
146+
// Convolutional Encoding
147+
// ---------------------
148+
uint8_t s[JT4_SYMBOL_COUNT];
149+
convolve(c, s, 13, JT4_BIT_COUNT);
150+
151+
// Interleaving
152+
// ------------
153+
jt9_interleave(s);
154+
memmove(s + 1, s, JT4_BIT_COUNT);
155+
s[0] = 0; // Append a 0 bit to start of sequence
156+
157+
// Merge with sync vector
158+
// ----------------------
159+
jt4_merge_sync_vector(s, symbols);
160+
}
161+
126162
/*
127163
* wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
128164
*
@@ -135,7 +171,6 @@ void JTEncode::jt9_encode(char * message, uint8_t * symbols)
135171
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
136172
*
137173
*/
138-
139174
void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
140175
{
141176
// Ensure that the message text conforms to standards
@@ -655,6 +690,27 @@ void JTEncode::jt9_merge_sync_vector(uint8_t * g, uint8_t * symbols)
655690
}
656691
}
657692

693+
void JTEncode::jt4_merge_sync_vector(uint8_t * g, uint8_t * symbols)
694+
{
695+
uint8_t i;
696+
const uint8_t sync_vector[JT4_SYMBOL_COUNT] =
697+
{0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0,
698+
0, 0, 0, 0, 1, 1, 0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,1,
699+
0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0,
700+
1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,
701+
0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
702+
1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1,
703+
1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
704+
0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1,
705+
1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
706+
0, 1, 1, 1, 1, 0, 1, 0, 1};
707+
708+
for(i = 0; i < JT4_SYMBOL_COUNT; i++)
709+
{
710+
symbols[i] = sync_vector[i] + (2 * g[i]);
711+
}
712+
}
713+
658714
void JTEncode::wspr_merge_sync_vector(uint8_t * g, uint8_t * symbols)
659715
{
660716
uint8_t i;

JTEncode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@
2828

2929
#define JT65_SYMBOL_COUNT 126
3030
#define JT9_SYMBOL_COUNT 85
31+
#define JT4_SYMBOL_COUNT 207
3132
#define WSPR_SYMBOL_COUNT 162
3233

3334
#define JT65_ENCODE_COUNT 63
3435
#define JT9_ENCODE_COUNT 69
3536

3637
#define JT9_BIT_COUNT 206
38+
#define JT4_BIT_COUNT 206
3739
#define WSPR_BIT_COUNT 162
3840

3941
class JTEncode
@@ -42,6 +44,7 @@ class JTEncode
4244
JTEncode(void);
4345
void jt65_encode(char *, uint8_t *);
4446
void jt9_encode(char *, uint8_t *);
47+
void jt4_encode(char *, uint8_t *);
4548
void wspr_encode(char *, char *, uint8_t, uint8_t *);
4649
private:
4750
uint8_t jt_code(char);
@@ -59,6 +62,7 @@ class JTEncode
5962
void jt_gray_code(uint8_t *, uint8_t);
6063
void jt65_merge_sync_vector(uint8_t *, uint8_t *);
6164
void jt9_merge_sync_vector(uint8_t *, uint8_t *);
65+
void jt4_merge_sync_vector(uint8_t *, uint8_t *);
6266
void wspr_merge_sync_vector(uint8_t *, uint8_t *);
6367
void convolve(uint8_t *, uint8_t *, uint8_t, uint8_t);
6468
void rs_encode(uint8_t *, uint8_t *);

README.md

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
JT65/JT9/WSPR Encoder Library for Arduino
2-
=========================================
3-
This library very simply generates a set of channel symbols for JT65, JT9, or WSPR based on the user providing a properly formatted Type 6 message for JT65 or JT9 (which is 13 valid characters) or a callsign, Maidenhead grid locator, and power output for WSPR. When paired with a synthesizer that can output frequencies in fine, phase-continuous tuning steps (such as the Si5351), then a beacon or telemetry transmitter can be created which can change the transmitted characters as needed from the Arduino.
1+
JT65/JT9/JT4/WSPR Encoder Library for Arduino
2+
=============================================
3+
This library very simply generates a set of channel symbols for JT65, JT9, JT4, or WSPR based on the user providing a properly formatted Type 6 message for JT65, JT9, or JT4 (which is 13 valid characters) or a callsign, Maidenhead grid locator, and power output for WSPR. When paired with a synthesizer that can output frequencies in fine, phase-continuous tuning steps (such as the Si5351), then a beacon or telemetry transmitter can be created which can change the transmitted characters as needed from the Arduino.
44

55
Please feel free to use the issues feature of GitHub if you run into problems or have suggestions for important features to implement.
66

@@ -16,11 +16,11 @@ Include the JTEncode library into your instance of the Arduino IDE. Download a Z
1616

1717
Example
1818
-------
19-
There is a simple example that is placed in your examples menu under JTEncode. Open this to see how to incorporate this library with your code. The example provided with with the library is meant to be used in conjuction with the [Etherkit Si5351A Breakout Board](https://www.etherkit.com/rf-modules/si5351a-breakout-board.html), although it could be modified to use with other synthesizers which meet the technical requirements of the JT65/JT9/WSPR modes.
19+
There is a simple example that is placed in your examples menu under JTEncode. Open this to see how to incorporate this library with your code. The example provided with with the library is meant to be used in conjuction with the [Etherkit Si5351A Breakout Board](https://www.etherkit.com/rf-modules/si5351a-breakout-board.html), although it could be modified to use with other synthesizers which meet the technical requirements of the JT65/JT9/JT4/WSPR modes.
2020

2121
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.
2222

23-
The example sketch itself is fairly straightforward. JT65, JT9, and WSPR 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.
23+
The example sketch itself is fairly straightforward. JT65, JT9, JT4, and WSPR 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.
2424

2525
An instance of the JTEncode object is created:
2626

@@ -44,6 +44,12 @@ On sketch startup, the mode parameters are set based on which mode is currently
4444
symbol_count = JT65_SYMBOL_COUNT; // From the library defines
4545
tone_spacing = JT65_TONE_SPACING;
4646
break;
47+
case MODE_JT4:
48+
freq = JT4_DEFAULT_FREQ;
49+
ctc = JT4_CTC;
50+
symbol_count = JT4_SYMBOL_COUNT; // From the library defines
51+
tone_spacing = JT4_TONE_SPACING;
52+
break;
4753
case MODE_WSPR:
4854
freq = WSPR_DEFAULT_FREQ;
4955
ctc = WSPR_CTC;
@@ -65,12 +71,15 @@ During transmit, the proper class method is chosen based on the desired mode, th
6571
case MODE_JT65:
6672
jtencode.jt65_encode(message, tx_buffer);
6773
break;
74+
case MODE_JT4:
75+
jtencode.jt4_encode(message, tx_buffer);
76+
break;
6877
case MODE_WSPR:
6978
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
7079
break;
7180
}
7281

73-
Once the channel symbols have been generate, it is a simple matter of transmitting them in sequence, each of the correct amount of time:
82+
Once the channel symbols have been generated, it is a simple matter of transmitting them in sequence, each the correct amount of time:
7483

7584
// Now transmit the channel symbols
7685
for(i = 0; i < symbol_count; i++)
@@ -111,6 +120,21 @@ Public Methods
111120
*/
112121
```
113122

123+
###jt4_encode()
124+
```
125+
/*
126+
* jt4_encode(char * message, uint8_t * symbols)
127+
*
128+
* Takes an arbitrary message of up to 13 allowable characters and returns
129+
* a channel symbol table.
130+
*
131+
* message - Plaintext Type 6 message.
132+
* symbols - Array of channel symbols to transmit retunred by the method.
133+
* Ensure that you pass a uint8_t array of size JT4_SYMBOL_COUNT to the method.
134+
*
135+
*/
136+
```
137+
114138
###wspr_encode()
115139
```
116140
/*
@@ -132,8 +156,16 @@ Here are the defines, structs, and enumerations you will find handy to use with
132156

133157
Defines:
134158

135-
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, WSPR_SYMBOL_COUNT
159+
JT65_SYMBOL_COUNT, JT9_SYMBOL_COUNT, JT4_SYMBOL_COUNT, WSPR_SYMBOL_COUNT
136160

137161
Acknowledgements
138162
----------------
139163
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.
164+
165+
License
166+
-------
167+
JTEncode is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
168+
169+
JTEncode is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
170+
171+
You should have received a copy of the GNU General Public License along with JTEncode. If not, see <http://www.gnu.org/licenses/>.

encode_rs_int.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ void JTEncode::encode_rs_int(void *p, data_t *data, data_t *parity)
3838
{
3939
struct rs *rs = (struct rs *)p;
4040

41-
#undef A0
42-
#define A0 (NN) /* Special reserved value encoding zero in index form */
41+
#undef A_0
42+
#define A_0 (NN) /* Special reserved value encoding zero in index form */
4343

4444
{
4545
int i, j;
@@ -49,7 +49,7 @@ void JTEncode::encode_rs_int(void *p, data_t *data, data_t *parity)
4949

5050
for(i=0;i<NN-NROOTS-PAD;i++){
5151
feedback = INDEX_OF[data[i] ^ parity[0]];
52-
if(feedback != A0){ /* feedback term is non-zero */
52+
if(feedback != A_0){ /* feedback term is non-zero */
5353
#ifdef UNNORMALIZED
5454
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
5555
* always be for the polynomials constructed by init_rs()
@@ -61,7 +61,7 @@ void JTEncode::encode_rs_int(void *p, data_t *data, data_t *parity)
6161
}
6262
/* Shift */
6363
memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
64-
if(feedback != A0)
64+
if(feedback != A_0)
6565
parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
6666
else
6767
parity[NROOTS-1] = 0;

0 commit comments

Comments
 (0)