Following up from the last project, the CW Beacon - I have re-written the code to use a set of Varicode for PSK31 symbols and to switch the frequency output by phase (0 or 180deg).
Reception on Mac cocoaModem software
This is the Arduino code.
Code
// BCN_PSK Beacon for PSK31
// V2 7-3-17
// thanks to F0GOJ for principles of the code
// AD9850
// W_CLK 8
// FQ_UD 9
// DATA 10
// RESET 11
// LCD I2C bus (16x2)
// SDA = A4
// SCL = A5
// ADS9850 and LCD I2C libraries
#include "ADS9850.h"
#include "LiquidCrystal_I2C.h"
// AD9850 pins
#define W_CLK 8
#define FQ_UD 9
#define DATA 10
#define RESET 11
// chose address of 0x27 or 0x3F for LCD
#define LCDADDR 0x27
//#define LCDADDR 0x3F
#define LCDCOLS 16
#define LCDROWS 2
// init freqs
#define STARTHZ 7070000
#define STARTCHZ 0
#define BAUD 32
// psk varicode and index of length
int pskVaricode[2][128] = {
{ 683, 731, 749, 887, 747, 863, 751, 765, 767, 239,
29, 879, 733, 31, 885, 939, 759, 757, 941, 943,
859, 875, 877, 855, 891, 893, 951, 853, 861, 955,
763, 895, 1, 511, 351, 501, 475, 725, 699, 383,
251, 247, 367, 479, 117, 53, 87, 431, 183, 189,
237, 255, 375, 347, 363, 429, 427, 439, 245, 445,
493, 85, 471, 687, 701, 125, 235, 173, 181, 119,
219, 253, 341, 127, 509, 381, 215, 187, 221, 171,
213, 477, 175, 111, 109, 343, 437, 349, 373, 379,
685, 503, 495, 507, 703, 365, 735, 11, 95, 47,
45, 3, 61, 91, 43, 13, 491, 191, 27, 59, 15, 7, 63,
447, 21, 23, 5, 55, 123, 107, 223, 93, 469, 695,
443, 693, 727, 949
},
{ 10, 10, 10, 10, 10, 10, 10, 10, 10,
8, 5, 10, 10, 5, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 1, 9, 9, 9, 9, 10, 10,
9, 8, 8, 9, 9, 7, 6, 7, 9, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 8, 9, 9, 7, 9, 10,
10, 7, 8, 8, 8, 7, 8, 8, 9, 7, 9, 9,
8, 8, 8, 8, 8, 9, 8, 7, 7, 9, 9, 9, 9,
9, 10, 9, 9, 9, 10, 9, 10, 4, 7, 6, 6,
2, 6, 7, 6, 4, 9, 8, 5, 6, 4, 3, 6, 9,
5, 5, 3, 6, 7, 7, 8, 7, 9, 10, 9, 10, 10, 10
}
};
// beacon message to send
char msg[] = "Beacon de M0IFA...";
// freq in Hz and cHz
long freqHz = STARTHZ; // frequency Hz
long freqChz = STARTCHZ; // sub freuency cHz
// repeat time (ms)
long repeat = 2000;
// ads (analog-output digital synthesiser) object
ADS9850 ads;
// lcd object
LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDROWS);
void setup() {
// init LCD
lcd.begin();
//init AD9850
ads.begin(W_CLK, FQ_UD, DATA, RESET); // initialise synthesiser, pins
dispMsg(0, 0, "BCNPSK");
dispFreq(7, 0, freqHz + freqChz / 100, 2); // display FREQ xxxxxx.xx kHz col 5 row 0
dispMsg(0, 1, msg); // out msg
}
void loop() {
// send message at frequency
sendMsg(freqHz, freqChz, msg);
delay(repeat); // repeat
}
// send message
void sendMsg(long fHz, long fChz, char m[]) {
int c, vCode, bits;
uint8_t phase;
phase = 0x00;
// Idle is zeroes so only phase inversion
for (int n = 0; n < BAUD; n++) {
phase = phase ^ 0x10; // XOR toggle b4 1 0000 <-> 0 0000
ads.setFreq(fHz, fChz, phase);
delay((961 + BAUD) / BAUD); // fix baud rate
}
c = 0;
while (m[c] != '\0') {
vCode = pskVaricode[0][m[c]]; // Get PSK varicode
bits = pskVaricode[1][m[c]]; // Get PSK varicode length
vCode <<= 2; // add 00 on lsb for char space
bits += 1; // msb to 0
//send char in psk
for (int n = bits; n >= 0; n--) { // msb 1st, bits to 0
if (bitRead(vCode, n) == 0) // 0 | 1 ?
phase = phase ^ 0x10; // XOR toggle b4 1 0000 <-> 0 0000
ads.setFreq(fHz, fChz, phase); // transmit
delay((961 + BAUD) / BAUD); // set speed
}
c++;
}
phase = 0x00;
// Idle is zeroes so only phase inversion
for (int n = 0; n < BAUD; n++) {
phase = phase ^ 0x10; // XOR toggle b4 1 0000 <-> 0 0000
ads.setFreq(fHz, fChz, phase);
delay((961 + BAUD) / BAUD); // fix baud rate
}
// end of message
ads.down();
}
// display freq at c)ol, r)ow, f (cHz), to d decimal places (kHz)
void dispFreq(uint8_t c, uint8_t r, uint64_t f, uint8_t d) {
lcd.setCursor(c, r);
lcd.print((float)f / 1000, d); // convert to float & kHz
lcd.print("kHz ");
}
// display msg *m at c)ol, r)ow
void dispMsg(uint8_t c, uint8_t r, char *m) {
lcd.setCursor(c, r);
lcd.print(m);
}
No comments:
Post a Comment