// Simple Feld Hell beacon for Arduino with Si5351 // ******************************************************************** // * using new version of library by Jason Milldrum NT7S * // * possible output frequencies up to VHF * // * modified and extended by DJ7OO in 10/2019 * // * Ajout CW et divers petits aménagements par F6IDT (04-2021) * // ******************************************************************** // // Original Feld Hell code for Arduino by Mark Vandewettering K6HX, // adapted for the Si5351A by Robert Liesenfeld AK6L . // Timer setup code by Thomas Knutsen LA3PNA. // // Copyright (c) 2015 Robert Liesenfeld AK6L // http://appnotes.etherkit.com/2015/08/arduino-feld-hell-beacon- // on-the-si5351a-breakout-board/?print=print #include #include "Wire.h" // Define variables. Si5351 si5351; uint64_t freq = 144620000; // output frequency 144.620 MHz //uint64_t freq = 14074000; // output frequency 14.074 MHz uint64_t cal = 77000; // cal augmente, freq diminue int audioPin = 12; // Sortie BF et branchement facultatif d'un buzzer piézo int TXPin = 13; // Sortie vers optocoupleur manip TX int PTTPin = 6; // Sortie passage en émission via un relais (PTT) int TunePin = 7; // BP pour émission d'une porteuse continue int ToneFreq = 980; // Tonalité en Hz (ancien standard Feld-Hell) // Si5351 SCL = A5 Branchement I2C // Si5351 SDA = A4 Branchement I2C #define N_MORSE (sizeof(morsetab)/sizeof(morsetab[0])) #define SPEED (12) #define DOTLEN (1200/SPEED) #define DASHLEN (3*(1200/SPEED)) // This variable must be defined 'volatile' to avoid some compiler // optimizations, which would render the interrupt timing useless. volatile bool proceed = false; // Define the structure of a glyph typedef struct glyph { char ch ; word col[7] ; } Glyph ; // Build the Feld Hell "font". This is declared PROGMEM to save // memory on the Arduino; this data will be stored in program // flash instead of loaded in memory. This makes accesses slower // and more complicated, but this is a small price to pay for the // memory savings. const Glyph glyphtab[] PROGMEM = { {' ', {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, {'A', {0x07fc, 0x0e60, 0x0c60, 0x0e60, 0x07fc, 0x0000, 0x0000}}, {'B', {0x0c0c, 0x0ffc, 0x0ccc, 0x0ccc, 0x0738, 0x0000, 0x0000}}, {'C', {0x0ffc, 0x0c0c, 0x0c0c, 0x0c0c, 0x0c0c, 0x0000, 0x0000}}, {'D', {0x0c0c, 0x0ffc, 0x0c0c, 0x0c0c, 0x07f8, 0x0000, 0x0000}}, {'E', {0x0ffc, 0x0ccc, 0x0ccc, 0x0c0c, 0x0c0c, 0x0000, 0x0000}}, {'F', {0x0ffc, 0x0cc0, 0x0cc0, 0x0c00, 0x0c00, 0x0000, 0x0000}}, {'G', {0x0ffc, 0x0c0c, 0x0c0c, 0x0ccc, 0x0cfc, 0x0000, 0x0000}}, {'H', {0x0ffc, 0x00c0, 0x00c0, 0x00c0, 0x0ffc, 0x0000, 0x0000}}, {'I', {0x0000, 0x0c0c, 0x0ffc, 0x0c0c, 0x0000, 0x0000, 0x0000}}, {'J', {0x003c, 0x000c, 0x000c, 0x000c, 0x0ffc, 0x0000, 0x0000}}, {'K', {0x0ffc, 0x00c0, 0x00e0, 0x0330, 0x0e1c, 0x0000, 0x0000}}, {'L', {0x0ffc, 0x000c, 0x000c, 0x000c, 0x000c, 0x0000, 0x0000}}, {'M', {0x0ffc, 0x0600, 0x0300, 0x0600, 0x0ffc, 0x0000, 0x0000}}, {'N', {0x0ffc, 0x0700, 0x01c0, 0x0070, 0x0ffc, 0x0000, 0x0000}}, {'O', {0x0ffc, 0x0c0c, 0x0c0c, 0x0c0c, 0x0ffc, 0x0000, 0x0000}}, {'P', {0x0c0c, 0x0ffc, 0x0ccc, 0x0cc0, 0x0780, 0x0000, 0x0000}}, {'Q', {0x0ffc, 0x0c0c, 0x0c3c, 0x0ffc, 0x000f, 0x0000, 0x0000}}, {'R', {0x0ffc, 0x0cc0, 0x0cc0, 0x0cf0, 0x079c, 0x0000, 0x0000}}, {'S', {0x078c, 0x0ccc, 0x0ccc, 0x0ccc, 0x0c78, 0x0000, 0x0000}}, {'T', {0x0c00, 0x0c00, 0x0ffc, 0x0c00, 0x0c00, 0x0000, 0x0000}}, {'U', {0x0ff8, 0x000c, 0x000c, 0x000c, 0x0ff8, 0x0000, 0x0000}}, {'V', {0x0ffc, 0x0038, 0x00e0, 0x0380, 0x0e00, 0x0000, 0x0000}}, {'W', {0x0ff8, 0x000c, 0x00f8, 0x000c, 0x0ff8, 0x0000, 0x0000}}, {'X', {0x0e1c, 0x0330, 0x01e0, 0x0330, 0x0e1c, 0x0000, 0x0000}}, {'Y', {0x0e00, 0x0380, 0x00fc, 0x0380, 0x0e00, 0x0000, 0x0000}}, {'Z', {0x0c1c, 0x0c7c, 0x0ccc, 0x0f8c, 0x0e0c, 0x0000, 0x0000}}, {'0', {0x07f8, 0x0c0c, 0x0c0c, 0x0c0c, 0x07f8, 0x0000, 0x0000}}, {'1', {0x0300, 0x0600, 0x0ffc, 0x0000, 0x0000, 0x0000, 0x0000}}, {'2', {0x061c, 0x0c3c, 0x0ccc, 0x078c, 0x000c, 0x0000, 0x0000}}, {'3', {0x0006, 0x1806, 0x198c, 0x1f98, 0x00f0, 0x0000, 0x0000}}, {'4', {0x1fe0, 0x0060, 0x0060, 0x0ffc, 0x0060, 0x0000, 0x0000}}, {'5', {0x000c, 0x000c, 0x1f8c, 0x1998, 0x18f0, 0x0000, 0x0000}}, {'6', {0x07fc, 0x0c66, 0x18c6, 0x00c6, 0x007c, 0x0000, 0x0000}}, {'7', {0x181c, 0x1870, 0x19c0, 0x1f00, 0x1c00, 0x0000, 0x0000}}, {'8', {0x0f3c, 0x19e6, 0x18c6, 0x19e6, 0x0f3c, 0x0000, 0x0000}}, {'9', {0x0f80, 0x18c6, 0x18cc, 0x1818, 0x0ff0, 0x0000, 0x0000}}, {'*', {0x018c, 0x0198, 0x0ff0, 0x0198, 0x018c, 0x0000, 0x0000}}, {'.', {0x001c, 0x001c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, {'?', {0x1800, 0x1800, 0x19ce, 0x1f00, 0x0000, 0x0000, 0x0000}}, {'!', {0x1f9c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}}, {'(', {0x01e0, 0x0738, 0x1c0e, 0x0000, 0x0000, 0x0000, 0x0000}}, {')', {0x1c0e, 0x0738, 0x01e0, 0x0000, 0x0000, 0x0000, 0x0000}}, {'#', {0x0330, 0x0ffc, 0x0330, 0x0ffc, 0x0330, 0x0000, 0x0000}}, {'$', {0x078c, 0x0ccc, 0x1ffe, 0x0ccc, 0x0c78, 0x0000, 0x0000}}, {'/', {0x001c, 0x0070, 0x01c0, 0x0700, 0x1c00, 0x0000, 0x0000}}, } ; // Define an upper bound on the number of glyphs. Defining it this // way allows adding characters without having to update a hard-coded // upper bound. #define NGLYPHS (sizeof(glyphtab)/sizeof(glyphtab[0])) // MORSE ******************************************************** struct t_mtab { char c, pat; } ; struct t_mtab morsetab[] = { {'+', 42}, {'-', 97}, {'=', 49}, {'.', 106}, {',', 115}, {'?', 76}, {'/', 41}, {'A', 6}, {'B', 17}, {'C', 21}, {'D', 9}, {'E', 2}, {'F', 20}, {'G', 11}, {'H', 16}, {'I', 4}, {'J', 30}, {'K', 13}, {'L', 18}, {'M', 7}, {'N', 5}, {'O', 15}, {'P', 22}, {'Q', 27}, {'R', 10}, {'S', 8}, {'T', 3}, {'U', 12}, {'V', 24}, {'W', 14}, {'X', 25}, {'Y', 29}, {'Z', 19}, {'1', 62}, {'2', 60}, {'3', 56}, {'4', 48}, {'5', 32}, {'6', 33}, {'7', 35}, {'8', 39}, {'9', 47}, {'0', 63} } ; // 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; } // This is the heart of the beacon. Given a character, it finds the // appropriate glyph and toggles output from the Si5351A to key the // Feld Hell signal. void encodechar(int ch) { int i, x, y, fch; word fbits; for (i=0; i