Put JT9 interleave table in prog mem, other RAM tweaks

pull/11/head
Jason Milldrum 2017-03-15 23:16:02 -07:00
rodzic 1ad4cc41ba
commit 70cab9ef44
5 zmienionych plików z 166 dodań i 164 usunięć

Wyświetl plik

@ -6,7 +6,7 @@ Please feel free to use the issues feature of GitHub if you run into problems or
Hardware Requirements and Setup
-------------------------------
This library has been written for the Arduino platform and has been successfully tested on the Arduino Uno and an Uno clone. Since the library itself does not access the hardware, there is no reason it should not run on any Arduino model of recent vintage.
This library has been written for the Arduino platform and has been successfully tested on the Arduino Uno and an Uno clone. Since the library itself does not access the hardware, there is no reason it should not run on any Arduino model of recent vintage as long as it has at least 2 kB of RAM.
How To Install
--------------
@ -14,9 +14,13 @@ The best way to install the library is via the Arduino Library Manager, which is
If you need to or would like to install the library in the old way, then you can download a copy of the library in a ZIP file. Download a ZIP file of the library from the GitHub repository by going to [this page](https://github.com/etherkit/JTEncode/releases) and clicking the "Source code (zip)" link under the latest release. Finally, open the Arduino IDE, select menu Sketch > Import Library... > Add Library..., and select the ZIP that you just downloaded.
RAM Usage
---------
Most of the encoding functions need to manipulate multiple arrays of symbols in RAM at the same time, and therefore are quite RAM intensive. Care has been taken to put as much data into program memory as is possible, but the encoding functions still can cause problems with the low RAM microcontrollers such as the ATmegaxx8 series. If you are using these, then please be sure to call them only once when a transmit buffer needs to be created or changed, and call them separately of other subroutine calls. When using other microcontrollers that have more RAM, such as most of the ARM ICs, this won't be as much of a problem. If you see unusual freezes, that almost certainly indicates a RAM shortage.
Example
-------
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/FSQ modes.
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 conjunction 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/FSQ modes.
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.
@ -29,58 +33,58 @@ An instance of the JTEncode object is created:
On sketch startup, the mode parameters are set based on which mode is currently selected (by the DEFAULT_MODE define):
// Set the proper frequency, tone spacing, symbol count, and
// timer CTC depending on mode
// tone delay depending on mode
switch(cur_mode)
{
case MODE_JT9:
freq = JT9_DEFAULT_FREQ;
ctc = JT9_CTC;
symbol_count = JT9_SYMBOL_COUNT; // From the library defines
tone_spacing = JT9_TONE_SPACING;
tone_delay = JT9_DELAY;
break;
case MODE_JT65:
freq = JT65_DEFAULT_FREQ;
ctc = JT65_CTC;
symbol_count = JT65_SYMBOL_COUNT; // From the library defines
tone_spacing = JT65_TONE_SPACING;
tone_delay = JT65_DELAY;
break;
case MODE_JT4:
freq = JT4_DEFAULT_FREQ;
ctc = JT4_CTC;
symbol_count = JT4_SYMBOL_COUNT; // From the library defines
tone_spacing = JT4_TONE_SPACING;
tone_delay = JT4_DELAY;
break;
case MODE_WSPR:
freq = WSPR_DEFAULT_FREQ;
ctc = WSPR_CTC;
symbol_count = WSPR_SYMBOL_COUNT; // From the library defines
tone_spacing = WSPR_TONE_SPACING;
tone_delay = WSPR_DELAY;
break;
case MODE_FSQ_2:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_2_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_2_DELAY;
break;
case MODE_FSQ_3:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_3_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_3_DELAY;
break;
case MODE_FSQ_4_5:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_4_5_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_4_5_DELAY;
break;
case MODE_FSQ_6:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_6_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_6_DELAY;
break;
}
Note that the number of channel symbols for each mode is defined in the library, so you can use those defines to initialize your own symbol array sizes.
During transmit, the proper class method is chosen based on the desired mode, then the transmit symbol buffer and the other mode information is set:
Before transmit, the proper class method is chosen based on the desired mode, then the transmit symbol buffer and the other mode information is set:
// Set the proper frequency and timer CTC depending on mode
switch(cur_mode)
@ -95,26 +99,25 @@ During transmit, the proper class method is chosen based on the desired mode, th
jtencode.jt4_encode(message, tx_buffer);
break;
case MODE_WSPR:
call.toUpperCase();
jtencode.wspr_encode(call, loc, dbm, tx_buffer);
break;
case MODE_FSQ_2:
case MODE_FSQ_3:
case MODE_FSQ_4_5:
case MODE_FSQ_6:
call.toLowerCase();
jtencode.fsq_dir_encode(call, "n0call", " ", "hello world", tx_buffer);
break;
}
As mentioned above, it is best if the message encoding functions are called only when needed, in its own subroutine.
Once the channel symbols have been generated, it is a simple matter of transmitting them in sequence, each the correct amount of time:
// Now transmit the channel symbols
for(i = 0; i < symbol_count; i++)
{
si5351.set_freq((freq * 100) + (tx_buffer[i] * tone_spacing), 0, SI5351_CLK0);
proceed = false;
while(!proceed);
delay(tone_delay);
}
Public Methods
@ -122,7 +125,7 @@ Public Methods
### jt65_encode()
```
/*
* jt65_encode(char * message, 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.
@ -136,7 +139,7 @@ Public Methods
### jt9_encode()
```
/*
* jt9_encode(char * message, 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.
@ -151,7 +154,7 @@ Public Methods
### jt4_encode()
```
/*
* jt4_encode(char * message, 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.
@ -166,7 +169,7 @@ Public Methods
### wspr_encode()
```
/*
* wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
* wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
*
@ -182,7 +185,7 @@ Public Methods
### fsq_encode()
```
/*
* fsq_encode(char * from_call, char * message, uint8_t * symbols)
* fsq_encode(const char * from_call, const char * message, uint8_t * symbols)
*
* Takes an arbitrary message and returns a FSQ channel symbol table.
*
@ -198,7 +201,7 @@ Public Methods
### fsq_dir_encode()
```
/*
* fsq_dir_encode(char * from_call, char * to_call, char cmd, char * message, uint8_t * symbols)
* fsq_dir_encode(const char * from_call, const char * to_call, const char cmd, const char * message, uint8_t * symbols)
*
* Takes an arbitrary message and returns a FSQ channel symbol table.
*
@ -231,23 +234,25 @@ Changelog
---------
* v1.1.2
Fix buffer bug in _jt_message_prep()_ that caused messages of 11 chars to lock up the processor
* Fix buffer bug in _jt_message_prep()_ that caused messages of 11 chars to lock up the processor
* Made a handful of changes to make the library more friendly to ATmegaxx8 processors
* Rewrote example sketch to be generically compatible with most Arduino platforms
* v1.1.1
Update example sketch for Si5351Arduino v2.0.0
* Update example sketch for Si5351Arduino v2.0.0
* v1.1.0
Added FSQ
* Added FSQ
* v1.0.1
Fixed a bug in _jt65_interleave()_ that was causing a buffer overrun.
* Fixed a bug in _jt65_interleave()_ that was causing a buffer overrun.
* v1.0.0
Initial Release
* Initial Release
License
-------

Wyświetl plik

@ -47,19 +47,19 @@
#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 // ~1.74 Hz
#define FSQ_TONE_SPACING 879 // ~8.79 Hz
#define JT9_CTC 9000 // CTC value for JT9-1
#define JT65_CTC 5812 // CTC value for JT65A
#define JT4_CTC 3578 // CTC value for JT4A
#define WSPR_CTC 10672 // CTC value for WSPR
#define FSQ_2_CTC 7812 // CTC value for 2 baud FSQ
#define FSQ_3_CTC 5208 // CTC value for 3 baud FSQ
#define FSQ_4_5_CTC 3472 // CTC value for 4.5 baud FSQ
#define FSQ_6_CTC 2604 // CTC value for 6 baud FSQ
#define JT9_DELAY 576 // Delay value for JT9-1
#define JT65_DELAY 371 // Delay in ms for JT65A
#define JT4_DELAY 229 // Delay value for JT4A
#define WSPR_DELAY 683 // Delay value for WSPR
#define FSQ_2_DELAY 500 // Delay value for 2 baud FSQ
#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 JT9_DEFAULT_FREQ 14080800UL
#define JT65_DEFAULT_FREQ 14078500UL
#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
@ -87,25 +87,41 @@ uint8_t dbm = 27;
uint8_t tx_buffer[255];
enum mode cur_mode = DEFAULT_MODE;
uint8_t symbol_count;
uint16_t ctc, tone_spacing;
// Global variables used in ISRs
volatile bool proceed = false;
// Timer interrupt vector. This toggles the variable we use to gate
// each column of output to ensure accurate timing. Called whenever
// Timer1 hits the count set below in setup().
ISR(TIMER1_COMPA_vect)
{
proceed = true;
}
uint16_t tone_delay, tone_spacing;
// Loop through the string, transmitting one character at a time.
void encode()
{
uint8_t i;
// Clear out the old transmit buffer
// Reset the tone to the base frequency and turn on the output
si5351.output_enable(SI5351_CLK0, 1);
digitalWrite(LED_PIN, HIGH);
// Now transmit the channel symbols
if(cur_mode == MODE_FSQ_2 || cur_mode == MODE_FSQ_3 || cur_mode == MODE_FSQ_4_5 || cur_mode == MODE_FSQ_6)
{
uint8_t j = 0;
while(tx_buffer[j++] != 0xff);
symbol_count = j - 1;
}
for(i = 0; i < symbol_count; i++)
{
si5351.set_freq((freq * 100) + (tx_buffer[i] * tone_spacing), SI5351_CLK0);
delay(tone_delay);
}
// Turn off the output
si5351.output_enable(SI5351_CLK0, 0);
digitalWrite(LED_PIN, LOW);
}
void set_tx_buffer()
{
// Clear out the transmit buffer
memset(tx_buffer, 0, 255);
// Set the proper frequency and timer CTC depending on mode
@ -130,38 +146,15 @@ void encode()
jtencode.fsq_dir_encode(call, "n0call", ' ', "hello world", tx_buffer);
break;
}
// Reset the tone to the base frequency and turn on the output
si5351.output_enable(SI5351_CLK0, 1);
digitalWrite(LED_PIN, HIGH);
// Now transmit the channel symbols
if(cur_mode == MODE_FSQ_2 || cur_mode == MODE_FSQ_3 || cur_mode == MODE_FSQ_4_5 || cur_mode == MODE_FSQ_6)
{
uint8_t j = 0;
while(tx_buffer[j++] != 0xff)
{
}
symbol_count = j - 1;
}
for(i = 0; i < symbol_count; i++)
{
si5351.set_freq((freq * 100) + (tx_buffer[i] * tone_spacing), SI5351_CLK0);
proceed = false;
while(!proceed);
}
// Turn off the output
si5351.output_enable(SI5351_CLK0, 0);
digitalWrite(LED_PIN, LOW);
}
void setup()
{
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
// Use the Arduino's on-board LED as a keying indicator.
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
@ -170,80 +163,65 @@ void setup()
pinMode(BUTTON, INPUT_PULLUP);
// Set the mode to use
cur_mode = MODE_WSPR;
cur_mode = MODE_JT65;
// Set the proper frequency, tone spacing, symbol count, and
// timer CTC depending on mode
// tone delay depending on mode
switch(cur_mode)
{
case MODE_JT9:
freq = JT9_DEFAULT_FREQ;
ctc = JT9_CTC;
symbol_count = JT9_SYMBOL_COUNT; // From the library defines
tone_spacing = JT9_TONE_SPACING;
tone_delay = JT9_DELAY;
break;
case MODE_JT65:
freq = JT65_DEFAULT_FREQ;
ctc = JT65_CTC;
symbol_count = JT65_SYMBOL_COUNT; // From the library defines
tone_spacing = JT65_TONE_SPACING;
tone_delay = JT65_DELAY;
break;
case MODE_JT4:
freq = JT4_DEFAULT_FREQ;
ctc = JT4_CTC;
symbol_count = JT4_SYMBOL_COUNT; // From the library defines
tone_spacing = JT4_TONE_SPACING;
tone_delay = JT4_DELAY;
break;
case MODE_WSPR:
freq = WSPR_DEFAULT_FREQ;
ctc = WSPR_CTC;
symbol_count = WSPR_SYMBOL_COUNT; // From the library defines
tone_spacing = WSPR_TONE_SPACING;
tone_delay = WSPR_DELAY;
break;
case MODE_FSQ_2:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_2_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_2_DELAY;
break;
case MODE_FSQ_3:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_3_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_3_DELAY;
break;
case MODE_FSQ_4_5:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_4_5_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_4_5_DELAY;
break;
case MODE_FSQ_6:
freq = FSQ_DEFAULT_FREQ;
ctc = FSQ_6_CTC;
tone_spacing = FSQ_TONE_SPACING;
tone_delay = FSQ_6_DELAY;
break;
}
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0, 0);
// Set CLK0 output
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power if desired
si5351.output_enable(SI5351_CLK0, 0); // Disable the clock initially
// Set up Timer1 for interrupts every symbol period.
noInterrupts(); // Turn off interrupts.
TCCR1A = 0; // Set entire TCCR1A register to 0; disconnects
// interrupt output pins, sets normal waveform
// mode. We're just using Timer1 as a counter.
TCNT1 = 0; // Initialize counter value to 0.
TCCR1B = (1 << CS12) | // Set CS12 and CS10 bit to set prescale
(1 << CS10) | // to /1024
(1 << WGM12); // turn on CTC
// which gives, 64 us ticks
TIMSK1 = (1 << OCIE1A); // Enable timer compare interrupt.
OCR1A = ctc; // Set up interrupt trigger count;
interrupts(); // Re-enable interrupts.
// Encode the message in the transmit buffer
// This is RAM intensive and should be done separately from other subroutines
set_tx_buffer();
}
void loop()
@ -255,7 +233,6 @@ void loop()
if (digitalRead(BUTTON) == LOW)
{
encode();
delay(50); //delay to avoid extra triggers
}
}

Wyświetl plik

@ -29,6 +29,10 @@
#include <stdint.h>
#include <stdio.h>
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
#include <avr/pgmspace.h>
#endif
#include "Arduino.h"
// Define an upper bound on the number of glyphs. Defining it this
@ -45,7 +49,7 @@ JTEncode::JTEncode(void)
}
/*
* jt65_encode(char * msg, uint8_t * symbols)
* jt65_encode(const char * msg, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
@ -55,7 +59,7 @@ JTEncode::JTEncode(void)
* Ensure that you pass a uint8_t array of size JT65_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt65_encode(char * msg, uint8_t * symbols)
void JTEncode::jt65_encode(const char * msg, uint8_t * symbols)
{
char message[14];
memset(message, 0, 14);
@ -89,7 +93,7 @@ void JTEncode::jt65_encode(char * msg, uint8_t * symbols)
}
/*
* jt9_encode(char * msg, uint8_t * symbols)
* jt9_encode(const char * msg, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
@ -99,7 +103,7 @@ void JTEncode::jt65_encode(char * msg, uint8_t * symbols)
* Ensure that you pass a uint8_t array of size JT9_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt9_encode(char * msg, uint8_t * symbols)
void JTEncode::jt9_encode(const char * msg, uint8_t * symbols)
{
char message[14];
memset(message, 0, 14);
@ -138,7 +142,7 @@ void JTEncode::jt9_encode(char * msg, uint8_t * symbols)
}
/*
* jt4_encode(char * msg, uint8_t * symbols)
* jt4_encode(const char * msg, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
* a channel symbol table.
@ -148,7 +152,7 @@ void JTEncode::jt9_encode(char * msg, uint8_t * symbols)
* Ensure that you pass a uint8_t array of size JT4_SYMBOL_COUNT to the method.
*
*/
void JTEncode::jt4_encode(char * msg, uint8_t * symbols)
void JTEncode::jt4_encode(const char * msg, uint8_t * symbols)
{
char message[14];
memset(message, 0, 14);
@ -180,7 +184,7 @@ void JTEncode::jt4_encode(char * msg, uint8_t * symbols)
}
/*
* wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
* wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
*
* Takes an arbitrary message of up to 13 allowable characters and returns
*
@ -191,11 +195,17 @@ void JTEncode::jt4_encode(char * msg, uint8_t * symbols)
* Ensure that you pass a uint8_t array of size WSPR_SYMBOL_COUNT to the method.
*
*/
void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbols)
void JTEncode::wspr_encode(const char * call, const char * loc, const uint8_t dbm, uint8_t * symbols)
{
char call_[7];
char loc_[5];
uint8_t dbm_ = dbm;
memcpy(call_, call, 6);
memcpy(loc_, loc, 4);
// Ensure that the message text conforms to standards
// --------------------------------------------------
wspr_message_prep(call, loc, dbm);
wspr_message_prep(call_, loc_, dbm_);
// Bit packing
// -----------
@ -217,7 +227,7 @@ void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbo
}
/*
* fsq_encode(cahr * from_call, char * message, uint8_t * symbols)
* fsq_encode(const char * from_call, const char * message, uint8_t * symbols)
*
* Takes an arbitrary message and returns a FSQ channel symbol table.
*
@ -228,7 +238,7 @@ void JTEncode::wspr_encode(char * call, char * loc, uint8_t dbm, uint8_t * symbo
* plus 5 characters to the method. Terminated in 0xFF.
*
*/
void JTEncode::fsq_encode(char * from_call, char * message, uint8_t * symbols)
void JTEncode::fsq_encode(const char * from_call, const char * message, uint8_t * symbols)
{
char tx_buffer[155];
char * tx_message;
@ -302,7 +312,7 @@ void JTEncode::fsq_encode(char * from_call, char * message, uint8_t * symbols)
}
/*
* fsq_dir_encode(char * from_call, char * to_call, char cmd, char * message, uint8_t * symbols)
* fsq_dir_encode(const char * from_call, const char * to_call, const char cmd, const char * message, uint8_t * symbols)
*
* Takes an arbitrary message and returns a FSQ channel symbol table.
*
@ -315,7 +325,7 @@ void JTEncode::fsq_encode(char * from_call, char * message, uint8_t * symbols)
* plus 5 characters to the method. Terminated in 0xFF.
*
*/
void JTEncode::fsq_dir_encode(char * from_call, char * to_call, char cmd, char * message, uint8_t * symbols)
void JTEncode::fsq_dir_encode(const char * from_call, const char * to_call, const char cmd, const char * message, uint8_t * symbols)
{
char tx_buffer[155];
char * tx_message;
@ -532,7 +542,8 @@ void JTEncode::wspr_message_prep(char * call, char * loc, uint8_t dbm)
loc[i] = toupper(loc[i]);
if(!(isdigit(loc[i]) || (loc[i] >= 'A' && loc[i] <= 'R')))
{
loc = "AA00";
memcpy(loc, "AA00", 5);
//loc = "AA00";
}
}
@ -725,38 +736,18 @@ void JTEncode::jt65_interleave(uint8_t * s)
void JTEncode::jt9_interleave(uint8_t * s)
{
uint8_t i, j, k, n;
uint8_t i, j;
uint8_t d[JT9_BIT_COUNT];
uint8_t j0[JT9_BIT_COUNT];
k = 0;
// Build the interleave table
for(i = 0; i < 255; i++)
// Do the interleave
for(i = 0; i < JT9_BIT_COUNT; i++)
{
n = 0;
for(j = 0; j < 8; j++)
{
n = (n << 1) + ((i >> j) & 1);
}
if(n < 206)
{
j0[k] = n;
k++;
}
if(k >= 206)
{
break;
}
}
// Now do the interleave
for(i = 0; i < 206; i++)
{
d[j0[i]] = s[i];
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
j = pgm_read_byte(&jt9i[i]);
d[j] = s[i];
#else
d[jt9i[i]] = s[i];
#endif
}
memcpy(s, d, JT9_BIT_COUNT);
@ -972,9 +963,10 @@ void JTEncode::convolve(uint8_t * c, uint8_t * s, uint8_t message_size, uint8_t
void JTEncode::rs_encode(uint8_t * data, uint8_t * symbols)
{
// Adapted from wrapkarn.c in the WSJT-X source code
unsigned int dat1[12];
unsigned int b[51];
unsigned int i;
uint8_t dat1[12];
uint8_t b[51];
uint8_t sym[JT65_ENCODE_COUNT];
uint8_t i;
// Reverse data order for the Karn codec.
for(i = 0; i < 12; i++)
@ -988,13 +980,15 @@ void JTEncode::rs_encode(uint8_t * data, uint8_t * symbols)
// Move parity symbols and data into symbols array, in reverse order.
for (i = 0; i < 51; i++)
{
symbols[50 - i] = b[i];
sym[50 - i] = b[i];
}
for (i = 0; i < 12; i++)
{
symbols[i + 51] = dat1[11 - i];
sym[i + 51] = dat1[11 - i];
}
memcpy(symbols, sym, JT65_ENCODE_COUNT);
}
uint8_t JTEncode::crc8(const char * text)
@ -1006,7 +1000,11 @@ uint8_t JTEncode::crc8(const char * text)
for(i = 0; i < strlen(text); i++)
{
ch = text[i];
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
crc = pgm_read_byte(&(crc8_table[(crc) ^ ch]));
#else
crc = crc8_table[(crc) ^ ch];
#endif
crc &= 0xFF;
}

Wyświetl plik

@ -27,7 +27,7 @@
#include "Arduino.h"
#include <stdint.h>
#include <avr/pgmspace.h>
//#include <avr/pgmspace.h>
#define JT65_SYMBOL_COUNT 126
#define JT9_SYMBOL_COUNT 85
@ -185,16 +185,35 @@ const uint8_t crc8_table[] PROGMEM = {
0xfa, 0xfd, 0xf4, 0xf3
};
const uint8_t jt9i[JT9_BIT_COUNT] PROGMEM = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0x10, 0x90, 0x50, 0x30, 0xb0, 0x70,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0x18, 0x98, 0x58, 0x38, 0xb8, 0x78,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0x14, 0x94, 0x54, 0x34, 0xb4, 0x74,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0x1c, 0x9c, 0x5c, 0x3c, 0xbc, 0x7c,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0x12, 0x92, 0x52, 0x32, 0xb2, 0x72,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0x1a, 0x9a, 0x5a, 0x3a, 0xba, 0x7a,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0x16, 0x96, 0x56, 0x36, 0xb6, 0x76,
0x0e, 0x8e, 0x4e, 0x2e, 0xae, 0x6e, 0x1e, 0x9e, 0x5e, 0x3e, 0xbe, 0x7e, 0x01,
0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0x11, 0x91, 0x51, 0x31, 0xb1, 0x71, 0x09,
0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0x19, 0x99, 0x59, 0x39, 0xb9, 0x79, 0x05,
0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0x15, 0x95, 0x55, 0x35, 0xb5, 0x75, 0x0d,
0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0x1d, 0x9d, 0x5d, 0x3d, 0xbd, 0x7d, 0x03,
0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0x13, 0x93, 0x53, 0x33, 0xb3, 0x73, 0x0b,
0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0x1b, 0x9b, 0x5b, 0x3b, 0xbb, 0x7b, 0x07,
0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0x17, 0x97, 0x57, 0x37, 0xb7, 0x77, 0x0f,
0x8f, 0x4f, 0x2f, 0xaf, 0x6f, 0x1f, 0x9f, 0x5f, 0x3f, 0xbf, 0x7f
};
class JTEncode
{
public:
JTEncode(void);
void jt65_encode(char *, uint8_t *);
void jt9_encode(char *, uint8_t *);
void jt4_encode(char *, uint8_t *);
void wspr_encode(char *, char *, uint8_t, uint8_t *);
void fsq_encode(char *, char *, uint8_t *);
void fsq_dir_encode(char *, char *, char, char *, uint8_t *);
void jt65_encode(const char *, uint8_t *);
void jt9_encode(const char *, uint8_t *);
void jt4_encode(const char *, uint8_t *);
void wspr_encode(const char *, const char *, const uint8_t, uint8_t *);
void fsq_encode(const char *, const char *, uint8_t *);
void fsq_dir_encode(const char *, const char *, const char, const char *, uint8_t *);
private:
uint8_t jt_code(char);
uint8_t wspr_code(char);

Wyświetl plik

@ -6,7 +6,10 @@
#ifndef INT_H_
#define INT_H_
typedef unsigned int data_t;
#include <stdint.h>
typedef uint8_t data_t;
//typedef unsigned int data_t;
#define MODNN(x) modnn(rs,x)
#define MM (rs->mm)