Added transmitter code

pull/1/head
Robert Östling 2017-08-29 19:06:20 +02:00
rodzic 5d6cc31fbc
commit 74218716e3
2 zmienionych plików z 164 dodań i 0 usunięć

Wyświetl plik

@ -8,3 +8,18 @@ Code for the WSPR protocol
Currently only simple callsigns and 4-symbol locators are accepted. Power is
in dBm.
## arduino_ad9851.ino
Arduino program to actually transmit the data generated by `encode.py` using
an AD9851 module.
**Note**: if you use the square wave output (QOUT1 or its inverse QOUT2),
make sure to tune the comparator voltage to achieve a reasonable duty cycle.
If followed by a class E amplifier this is about 45% for maximum power output
(anywhere near 50% should be OK). I use a DC voltmeter and approximate the
duty cycle with V/5, so that a measured 2V reading translates into a 40% duty
cycle.
You could of course also take either of the sine wave outputs (ZOUT1, ZOUT2)
and amplify or feed directly into a low-pass filter to the antenna.

149
arduino_ad9851.ino 100644
Wyświetl plik

@ -0,0 +1,149 @@
/* AD9851 module WSPR transmitter
* Robert Östling SM0YSR 2017-08-29
*
* Use the encode.py script to generate the data to transmit, then paste it
* into msg = { ... } below.
*
* You may also want to tweak the frequency:
*/
// Set TX frequency
#define F_BASE 3594086.0
//#define F_BASE 10140186.0
byte msg[162] = { /* output of encode.py */ };
byte pin_button = 2; // button that pulls LOW to start transmitting
// internal pull-up is enabled, so just short to GND
// This is just for timing, after the button is
// pressed the system will go into an infinite loop
// transmitting every 10 minutes.
byte pin_key = 3; // "keyer" output, HIGH = enable TX
byte pin_reset = 4; // DDS reset pin
byte pin_load = 5; // DDS load pin
byte pin_clock = 6; // DDS clock pin
byte pin_data = 7; // DDS data pin
byte pin_led = 13; // Arduino LED
/*
Left side of module (with LED facing up, at upper right corner):
VCC
W_CLK (clock)
FU_UD (load)
DATA (data)
RESET (reset)
GND
QOUT1
QOUT2
ZOUT1
ZOUT2
*/
// Encoded frequency table for the 4 FSK tones
// This is pre-computed so that it can be sent directly to the DDS
unsigned long fsk[4] = {
(unsigned long)((F_BASE * 4294967296.0) / 180e6),
(unsigned long)(((F_BASE + 1.0*1.4648) * 4294967296.0) / 180e6),
(unsigned long)(((F_BASE + 2.0*1.4648) * 4294967296.0) / 180e6),
(unsigned long)(((F_BASE + 3.0*1.4648) * 4294967296.0) / 180e6)
};
void write_bit(byte x) {
if(x) {
digitalWrite(pin_clock, LOW);
digitalWrite(pin_data, HIGH);
digitalWrite(pin_clock, HIGH);
digitalWrite(pin_data, LOW);
} else {
digitalWrite(pin_clock, LOW);
digitalWrite(pin_data, LOW);
digitalWrite(pin_clock, HIGH);
}
}
void write_byte(byte x) {
for(byte i=0; i<8; i++) {
write_bit(x&1);
x >>= 1;
}
}
void set_frequency_word(unsigned long w) {
digitalWrite(pin_load, LOW);
for(byte i=0; i<32; i++) {
write_bit(w&1);
w >>= 1;
}
write_byte(0x09);
digitalWrite(pin_load, HIGH);
}
void setup() {
pinMode(pin_reset, OUTPUT);
pinMode(pin_load, OUTPUT);
pinMode(pin_clock, OUTPUT);
pinMode(pin_data, OUTPUT);
pinMode(pin_led, OUTPUT);
pinMode(pin_key, OUTPUT);
pinMode(pin_button, INPUT_PULLUP);
digitalWrite(pin_reset, LOW);
digitalWrite(pin_clock, LOW);
digitalWrite(pin_data, LOW);
digitalWrite(pin_load, LOW);
digitalWrite(pin_led, LOW);
digitalWrite(pin_key, LOW);
delay(2000);
digitalWrite(pin_reset, HIGH);
delay(5);
digitalWrite(pin_reset, LOW);
delay(5);
digitalWrite(pin_clock, HIGH);
delay(5);
digitalWrite(pin_clock, LOW);
delay(5);
digitalWrite(pin_load, HIGH);
delay(5);
digitalWrite(pin_load, LOW);
delay(5);
// Arbitrary
set_frequency_word(fsk[0]);
}
// Infinite transmit loop, one message every 10 minutes
void tx() {
int i;
unsigned long t0 = millis();
while(1) {
digitalWrite(pin_key, HIGH);
for (i=0; i<162; i++) {
set_frequency_word(fsk[msg[i]]);
double target =
t0 + (unsigned long)(((double)(i+1))*(1000.0*8192.0/12000.0));
digitalWrite(pin_led, (i&1));
while(millis() < target);
}
digitalWrite(pin_key, LOW);
digitalWrite(pin_led, LOW);
t0 += 600000UL;
while(millis() < t0);
}
}
void loop() {
// Wait for button press, then start infinite loop
if (digitalRead(pin_button) == LOW) {
tx();
// this will never be reached
}
}