Skip to content

Instantly share code, notes, and snippets.

@NT7S
Last active July 5, 2021 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NT7S/0738b6cea1c7d71d9c1f3ddfc1c98197 to your computer and use it in GitHub Desktop.
Save NT7S/0738b6cea1c7d71d9c1f3ddfc1c98197 to your computer and use it in GitHub Desktop.
JTEncode example with two different buffers
// Si5351_WSPR
//
// Simple WSPR beacon for Arduino Uno, with the Etherkit Si5351A Breakout
// Board by Jason Milldrum NT7S.
//
// Original code based on Feld Hell beacon for Arduino by Mark
// Vandewettering K6HX, adapted for the Si5351A by Robert
// Liesenfeld AK6L <ak6l@ak6l.org>. Timer setup
// code by Thomas Knutsen LA3PNA.
//
// Time code adapted from the TimeSerial.ino example from the Time library.
// Hardware Requirements
// ---------------------
// This firmware should be able to run on most Arduino microcontrollers, since it solely relies
// on the millis() function for timing.
//
// Required Libraries
// ------------------
// Etherkit Si5351 (Library Manager)
// Etherkit JTEncode (Library Manager)
// Time (Library Manager)
// Wire (Arduino Standard Library)
//
// License
// -------
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject
// to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#include <si5351.h>
#include <JTEncode.h>
#include <int.h>
#include <TimeLib.h>
constexpr uint8_t TONE_SPACING = 146; // ~1.46 Hz
constexpr uint16_t WSPR_INTERVAL = 683;
constexpr uint8_t SYMBOL_COUNT = WSPR_SYMBOL_COUNT;
constexpr uint32_t CORRECTION = 0; // Change this for your ref osc
constexpr char TIME_HEADER = 'T'; // Header tag for Serial time sync message
constexpr char TIME_REQUEST = 7; // ASCII bell character requests a time sync message
constexpr uint8_t TX_LED_PIN = 25;
constexpr uint8_t SYNC_LED_PIN = 13;
// Global variables
Si5351 si5351;
JTEncode jtencode;
uint64_t freq = 10140200UL; // Change this
char call[13] = "NT7S"; // Change this
char loc[7] = "CN85NM"; // Change this
uint8_t dbm = 30;
uint8_t tx_buffer_1[SYMBOL_COUNT];
uint8_t tx_buffer_2[SYMBOL_COUNT];
uint32_t timer_expire = UINT32_MAX;
// Global variables used in ISRs
volatile bool proceed = false;
// Loop through the string, transmitting one character at a time.
void encode(uint8_t * buf)
{
uint8_t i;
//jtencode.wspr_encode(call, loc, dbm, tx_buffer_1);
timer_expire = millis() + WSPR_INTERVAL;
// Reset the tone to 0 and turn on the output
si5351.set_clock_pwr(SI5351_CLK0, 1);
digitalWrite(TX_LED_PIN, LOW);
// Now do the rest of the message
for(i = 0; i < SYMBOL_COUNT; i++)
{
si5351.set_freq((freq * 100) + (buf[i] * TONE_SPACING), SI5351_CLK0);
while(millis() < timer_expire);
timer_expire = millis() + WSPR_INTERVAL;
}
// Turn off the output
si5351.set_clock_pwr(SI5351_CLK0, 0);
digitalWrite(TX_LED_PIN, HIGH);
}
void processSyncMessage()
{
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER))
{
pctime = Serial.parseInt();
if( pctime >= DEFAULT_TIME)
{ // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the Serial port
}
}
}
time_t requestSync()
{
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to Serial mesg
}
void setup()
{
// Use the Arduino's on-board LED as a keying indicator.
pinMode(TX_LED_PIN, OUTPUT);
pinMode(SYNC_LED_PIN, OUTPUT);
digitalWrite(TX_LED_PIN, HIGH);
digitalWrite(SYNC_LED_PIN, LOW);
Serial.begin(115200);
while(!Serial);
// Set time sync provider
setSyncProvider(requestSync); //set function to call when sync required
// Initialize the Si5351
// Change the 2nd parameter in init if using a ref osc other
// than 25 MHz
si5351.init(SI5351_CRYSTAL_LOAD_0PF, 0, CORRECTION);
// Set CLK0 output
si5351.set_freq(freq * 100, SI5351_CLK0);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_8MA); // Set for max power
si5351.set_clock_pwr(SI5351_CLK0, 0); // Disable the clock initially
jtencode.wspr_encode(call, loc, dbm, tx_buffer_1);
jtencode.wspr_encode("NT7S/X", "CN84AB", 23, tx_buffer_2);
// PrintBuffer(tx_buffer_1);
// PrintBuffer(tx_buffer_2);
}
void loop()
{
if(Serial.available())
{
processSyncMessage();
}
if(timeStatus() == timeSet)
{
digitalWrite(SYNC_LED_PIN, HIGH); // LED on if synced
}
else
{
digitalWrite(SYNC_LED_PIN, LOW); // LED off if needs refresh
}
// Trigger every 10th minute
// WSPR should start on the 1st second of the minute, but there's a slight delay
// in this code because it is limited to 1 second resolution.
// if(timeSet && timeStatus() == timeSet && minute() % 2 == 0 && second() == 0)
if(timeSet && timeStatus() == timeSet && (minute() % 10 == 0 || minute() % 10 == 4) && second() == 0)
{
encode(tx_buffer_1);
delay(1000);
}
if(timeSet && timeStatus() == timeSet && (minute() % 10 == 2 || minute() % 10 == 6) && second() == 0)
{
encode(tx_buffer_2);
delay(1000);
}
//delay(100);
}
void PrintBuffer(uint8_t * buf)
{
for(uint8_t i = 0; i < SYMBOL_COUNT; ++i)
{
Serial.print(buf[i]);
}
Serial.println();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment