From 4dd13016e4e9d1c6e116c32bb28db8249ad49730 Mon Sep 17 00:00:00 2001 From: LongHairedHacker Date: Sun, 15 Jul 2018 14:54:33 +0200 Subject: [PATCH] Working fully automatic wspr beacon --- firmware/Makefile | 4 +-- firmware/include/timer.h | 39 ++++++++++++++++++++ firmware/include/uart.h | 58 ++++++++++++++++++++++++++++++ firmware/main.c | 31 +++++++++++++--- firmware/scripts/time_sync.py | 25 +++++++++++++ firmware/timer.c | 14 ++++++++ firmware/uart.c | 68 +++++++++++++++++++++++++++++++++++ 7 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 firmware/include/timer.h create mode 100644 firmware/include/uart.h create mode 100644 firmware/scripts/time_sync.py create mode 100644 firmware/timer.c create mode 100644 firmware/uart.c diff --git a/firmware/Makefile b/firmware/Makefile index ee09faf..167c148 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -4,8 +4,8 @@ ISPPORT ?= /dev/kaboard VERSION = 0.1 -HEADERS = include/twi.h include/si5351.h include/wspr.h -SRC = main.c twi.c si5351.c wspr.c +HEADERS = include/twi.h include/timer.h include/uart.h include/si5351.h include/wspr.h +SRC = main.c twi.c timer.c uart.c si5351.c wspr.c TARGET = cube-kl OBJDIR = bin diff --git a/firmware/include/timer.h b/firmware/include/timer.h new file mode 100644 index 0000000..e4103e6 --- /dev/null +++ b/firmware/include/timer.h @@ -0,0 +1,39 @@ +#ifndef TIMER_H_ +#define TIMER_H_ TIMER_H_ + +#include +#include +#include + + +extern volatile uint32_t timestamp; +extern volatile uint16_t milliseconds; + +/* + * Timer setting: + * MCU running at 16MHz: + * Prescaler is 64 which results in 250000 ticks per second + * Preloading the counter with 6 leads to 1000 overflow interrupts per second + * or one overflow every millisecond. + */ + +static inline void timer_init(void) { + TCNT0 = 6; //Preload for 250 ticks to overflow + TIMSK |= (1 << TOIE0); + TCCR0 = (1 << CS00) | (1 << CS01); // Prescaler 64 + timestamp = 0; + milliseconds = 0; +} + +static inline void timer_set(uint32_t stamp) { + TCCR0 &= ~((1 << CS00) | (1 << CS01)); // stop the timer + + TCNT0 = 6; //Preload for 250 ticks to overflow + timestamp = stamp; + milliseconds = 0; + + TCCR0 = (1 << CS00) | (1 << CS01); // Restart timer +} + + +#endif diff --git a/firmware/include/uart.h b/firmware/include/uart.h new file mode 100644 index 0000000..13e85e4 --- /dev/null +++ b/firmware/include/uart.h @@ -0,0 +1,58 @@ +#ifndef UART_H_ +#define UART_H_ UART_H_ + +#include +#include +#include + +#include + + +//#define BAUD 76800UL // baudrate +#define BAUD 38400UL +#define UART_TIMEOUT 100 // Timeout in ms + +// Some calculations ... +#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // Rounding magic +#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Real baudrate +#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) + +#if ((BAUD_ERROR<950) || (BAUD_ERROR>1050)) // Make sure your UBRR_VAL will work + #error Baudrate error is bigger then 1% ! +#endif + +extern uint8_t uart_timed_out; + +void uart_init(void); +uint8_t uart_getc_timeout(void); +uint8_t uart_get_line(char buffer[], uint8_t maxlen); + + +static inline void uart_putc(uint8_t data) { + UDR = data; // write byte to data register + while (!(UCSRA & (1<< UDRE))); // waiting for the uart to finish transmission + UCSRA |= (1 << UDRE); +} + +static inline void uart_puts(char *data) { + uint8_t i; + for(i = 0; i < strlen(data); i++) { + uart_putc(data[i]); + } +} + +static inline uint8_t uart_getc(void) { + while (!(UCSRA & (1< #include +#include "timer.h" +#include "uart.h" #include "twi.h" #include "si5351.h" #include "wspr.h" int main(void) { + uart_init(); twi_init(); + timer_init(); + + sei(); + si5351_init(25000000, 800000000, 500000000); si5351_ms_set_source(SI5351_MS0, SI5351_PLLA); - - //si5351_ms_set_freq(SI5351_MS0, 7040100); //si5351_ms_enable_output(SI5351_MS0); //si5351_ms_write_params(SI5351_MS0, WSPR_SYMBOLS[3]); uint8_t wspr_buffer[WSPR_LENGTH]; - wspr_encode("DL1SSK", "JN39", 27, wspr_buffer); - wspr_transmit(SI5351_MS0, wspr_buffer); + + char line[16]; + while(1) { + uint8_t res = 0; + while(res != 1) { + uart_puts("?\n"); + res = uart_get_line(line, 16); + } + + uint32_t realtime = strtoul(line,NULL,10); + timer_set(realtime); + uart_puts("Time set\n"); + + while(timestamp % 120 != 1) { + _delay_ms(25); + } + + wspr_transmit(SI5351_MS0, wspr_buffer); + uart_puts("Transmission send\n"); + } while(1); diff --git a/firmware/scripts/time_sync.py b/firmware/scripts/time_sync.py new file mode 100644 index 0000000..790de5e --- /dev/null +++ b/firmware/scripts/time_sync.py @@ -0,0 +1,25 @@ +#/usr/bin/env python3 + +import serial +import time + +def main(): + ser = serial.Serial('/dev/kaboard', 38400, timeout=10) + ser.flush() + + while True: + line = ser.readline() + while len(line) == 0: + line = ser.readline() + + line = line.decode("ascii")[:-1] + print("[%s] >> %s" % (time.strftime('%H:%m:%S'), line)) + if line == "?": + timestamp = "%d\n" % int(time.time()) + print("[%s] << %s" % (time.strftime('%H:%m:%S'),timestamp[:-1])) + ser.write(timestamp.encode('ascii')) + + + +if __name__ == '__main__': + main() diff --git a/firmware/timer.c b/firmware/timer.c new file mode 100644 index 0000000..febcdb4 --- /dev/null +++ b/firmware/timer.c @@ -0,0 +1,14 @@ +#include "timer.h" + +volatile uint32_t timestamp; +volatile uint16_t milliseconds; + +ISR(TIMER0_OVF_vect) { + TCNT0 = 6; //Preload for 250 ticks to overflow + + milliseconds++; + if(milliseconds > 999) { + timestamp++; + milliseconds = 0; + } +} diff --git a/firmware/uart.c b/firmware/uart.c new file mode 100644 index 0000000..d7ffeb4 --- /dev/null +++ b/firmware/uart.c @@ -0,0 +1,68 @@ +#include "uart.h" + +uint8_t uart_timed_out = 0; + +void uart_init(void) { + UBRRH = UBRR_VAL >> 8; //Setting baudrate + UBRRL = UBRR_VAL & 0xFF; + + UCSRB |= (1< 0)) { + if(delays == 0) { + retries--; + } + delays = (delays + 1) % 250; + _delay_us(4); + } + + if(retries > 0) { + uart_timed_out = 0; + return UDR; + } + + uart_timed_out = 1; + return 0; +} + +uint8_t uart_get_line(char buffer[], uint8_t maxlen) { + char t = 0; + uint8_t pos = 0; + buffer[0] = 0; + + //maxlen needs to be at least big enough for one character + null byte. + if(maxlen < 2) { + return 0; + } + + uart_clear_time_out(); + + while(pos < maxlen && t != '\n' && !uart_has_timed_out()) { + t = uart_getc_timeout(); + buffer[pos] = t; + pos++; + } + + // We passed the loop at least once, so pos can not be 0 + if(buffer[pos-1] != '\n') { + return 0; + } + buffer[pos-1] = 0; + return 1; +} \ No newline at end of file