Browse Source

Implemented wspr test

wspr-beacon
Sebastian 2 years ago
parent
commit
2bc9b77ac4
7 changed files with 106 additions and 30 deletions
  1. +2
    -2
      firmware/Makefile
  2. +10
    -1
      firmware/include/si5351.h
  3. +45
    -0
      firmware/include/wspr.h
  4. +7
    -6
      firmware/main.c
  5. +6
    -4
      firmware/scripts/wspr_params.py
  6. +22
    -17
      firmware/si5351.c
  7. +14
    -0
      firmware/wspr.c

+ 2
- 2
firmware/Makefile View File

@ -4,8 +4,8 @@ ISPPORT ?= /dev/kaboard
VERSION = 0.1
HEADERS = include/twi.h include/si5351.h
SRC = main.c twi.c si5351.c
HEADERS = include/twi.h include/si5351.h include/wspr.h
SRC = main.c twi.c si5351.c wspr.c
TARGET = cube-kl
OBJDIR = bin


+ 10
- 1
firmware/include/si5351.h View File

@ -31,6 +31,11 @@ enum si5351_reg {
};
struct si5351_params {
uint32_t p1;
uint32_t p2;
uint32_t p3;
};
static inline uint8_t si5351_write8(uint8_t reg, uint8_t value) {
uint8_t data[3] = {reg, value};
@ -42,8 +47,12 @@ void si5351_ms_enable_output(enum si5351_multisynth synth);
void si5351_ms_disable_output(enum si5351_multisynth synth);
void si5351_ms_set_source(enum si5351_multisynth synth, enum si5351_pll pll);
void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq);
uint8_t si5351_write_params(uint8_t base, uint32_t p1, uint32_t p2, uint32_t p3);
uint8_t si5351_write_params(uint8_t base, struct si5351_params params);
static inline void si5351_ms_write_params(enum si5351_multisynth synth, struct si5351_params params) {
si5351_write_params(SI5351_MULTISYNTH_BASE[synth], params);
}
#endif

+ 45
- 0
firmware/include/wspr.h View File

@ -0,0 +1,45 @@
#ifndef __WSPR_H__
#define __WSPR_H__ __WSPR_H__
#include <stdint.h>
#include "si5351.h"
// For PLL with 800MHz
static const struct si5351_params WSPR_SYMBOLS[4] = {
// 7040100.000000: 113 + 44687 / 70401
// actual: 7040100.000000
{14033, 17455, 70401},
// 7040101.464844: 113 + 447801 / 705503
// actual: 7040101.464844
{14033, 172785, 705503},
// 7040102.929688: 113 + 38515 / 60682
// actual: 7040102.929688
{14033, 14678, 60682},
// 7040104.394531: 113 + 123233 / 194166
// actual: 7040104.394531
{14033, 46378, 194166},
};
static const uint8_t WSPR_LENGTH = 162;
static const uint16_t WSPR_PERIOD = 683;
// DL1SSK at JN39we
static uint8_t default_wspr_msg[162] = {
1, 1, 0, 0, 2, 0, 0, 2, 1, 0, 0, 0, 1, 3, 3, 2, 2, 2, 3, 2, 0, 1, 0, 3, 1, 1, 1, 0, 2,
2, 0, 2, 2, 0, 3, 0, 0, 1, 0, 3, 2, 0, 0, 0, 0, 0, 3, 0, 1, 1, 0, 0, 3, 1, 2, 1, 0, 2,
2, 3, 1, 2, 1, 2, 2, 2, 2, 3, 3, 2, 1, 2, 1, 2, 1, 2, 3, 2, 0, 3, 2, 0, 1, 0, 3, 3, 0,
2, 2, 1, 1, 2, 1, 0, 1, 0, 2, 0, 1, 2, 2, 2, 0, 0, 3, 2, 2, 3, 0, 0, 1, 3, 3, 2, 3, 3,
0, 2, 3, 1, 2, 1, 0, 2, 2, 3, 3, 3, 0, 2, 2, 0, 2, 1, 2, 1, 2, 0, 1, 3, 0, 0, 0, 0, 0,
2, 0, 3, 1, 0, 1, 2, 3, 1, 2, 2, 2, 1, 1, 0, 0, 2
};
void wspr_transmit(enum si5351_multisynth synth, uint8_t *msg);
#endif

+ 7
- 6
firmware/main.c View File

@ -3,6 +3,7 @@
#include "twi.h"
#include "si5351.h"
#include "wspr.h"
int main(void) {
@ -10,15 +11,15 @@ int main(void) {
si5351_init(25000000, 800000000, 500000000);
si5351_ms_set_source(SI5351_MS0, SI5351_PLLA);
uint32_t base = 7165000;
uint32_t ppm_err = 9;
uint32_t err = base * ppm_err / 1000000;
uint32_t target = base - err;
si5351_ms_set_freq(SI5351_MS0, target);
si5351_ms_enable_output(SI5351_MS0);
//si5351_ms_set_freq(SI5351_MS0, 7040100);
//si5351_ms_enable_output(SI5351_MS0);
//si5351_ms_write_params(SI5351_MS0, WSPR_SYMBOLS[3]);
wspr_transmit(SI5351_MS0, default_wspr_msg);
while(1);


+ 6
- 4
firmware/scripts/wspr_params.py View File

@ -3,7 +3,7 @@ from fractions import Fraction
from math import floor
PLL_FREQ = 900.0 * 10**6
PLL_FREQ = 800.0 * 10**6
SYMBOL_COUNT = 4
# http://www.g4jnt.com/wspr_coding_process.pdf
@ -17,7 +17,7 @@ MAX_DENOM = 0x0FFFFF
def main():
print("struct si5351_params wspr_symbols[%d] = {" % SYMBOL_COUNT)
print("struct si5351_params WSPR_SYMBOLS[%d] = {" % SYMBOL_COUNT)
for i in range(0, SYMBOL_COUNT):
symbol_freq = Fraction(BASE_FREQ) + Fraction(i) * FREQ_SHIFT
@ -30,15 +30,17 @@ def main():
c = divider.denominator
print("\t// %f: %d + %d / %d" % (symbol_freq, a, b, c))
actual = PLL_FREQ / (a + b/c)
print("\t// actual: %f" % actual)
# See https://www.silabs.com/documents/public/application-notes/AN619.pdf
p1 = 128 * a + floor(128 * b/c) + 512
p1 = 128 * a + floor(128 * b/c) - 512
p2 = 128 * b - c * floor(128 * b/c)
p3 = c
print("\t{%d, %d, %d}," % (p1, p2, p3))
print("}")
print("};")
if __name__ == '__main__':
main()

+ 22
- 17
firmware/si5351.c View File

@ -27,10 +27,13 @@ void si5351_init(uint32_t freq_xtal, uint32_t freq_a, uint32_t freq_b) {
uint32_t c = 0x0FFFFF;
uint32_t a = (uint32_t) fdiv;
uint32_t b = (uint32_t) ((uint64_t) rm * (uint64_t) c / (uint64_t) freq_xtal);
uint32_t p1 = 128 * a + (128 * b / c) - 512;
uint32_t p2 = 128 * b - c * (128 * b / c);
uint32_t p3 = c;
si5351_write_params(SI5351_PLL_BASE_ADDR[i], p1, p2, p3);
struct si5351_params params = {
128 * a + (128 * b / c) - 512,
128 * b - c * (128 * b / c),
c
};
si5351_write_params(SI5351_PLL_BASE_ADDR[i], params);
}
}
@ -64,25 +67,27 @@ void si5351_ms_set_freq(enum si5351_multisynth synth, uint32_t freq) {
uint32_t a = fdiv;
uint32_t b = (uint32_t) ((uint64_t) rm * (uint64_t) c / freq);
uint32_t p1 = 128 * a + (128 * b / c) - 512;
uint32_t p2 = 128 * b - c * (128 * b / c);
uint32_t p3 = c;
si5351_write_params(SI5351_MULTISYNTH_BASE[synth], p1, p2, p3);
struct si5351_params params = {
128 * a + (128 * b / c) - 512,
128 * b - c * (128 * b / c),
c
};
si5351_write_params(SI5351_MULTISYNTH_BASE[synth], params);
}
uint8_t si5351_write_params(uint8_t base, uint32_t p1, uint32_t p2, uint32_t p3) {
uint8_t si5351_write_params(uint8_t base, struct si5351_params params) {
uint8_t data[9] = {
base,
(p3 & 0x00FF00) >> 8,
p3 & 0x0000FF,
(p1 & 0x030000) >> 16,
(p1 & 0x00FF00) >> 8,
p1 & 0x0000FF,
((p3 & 0x0F0000) >> 12) | ((p2 & 0x0F0000) >> 16),
(p2 & 0x00FF00) >> 8,
p2 & 0x0000FF
(params.p3 & 0x00FF00) >> 8,
params.p3 & 0x0000FF,
(params.p1 & 0x030000) >> 16,
(params.p1 & 0x00FF00) >> 8,
params.p1 & 0x0000FF,
((params.p3 & 0x0F0000) >> 12) | ((params.p2 & 0x0F0000) >> 16),
(params.p2 & 0x00FF00) >> 8,
params.p2 & 0x0000FF
};
return twi_write(SI5351_ADDRESS, data, 9);
}

+ 14
- 0
firmware/wspr.c View File

@ -0,0 +1,14 @@
#include "wspr.h"
#include <util/delay.h>
void wspr_transmit(enum si5351_multisynth synth, uint8_t *msg) {
si5351_ms_enable_output(synth);
for(uint8_t i = 0; i < WSPR_LENGTH; i++) {
uint8_t sym = msg[i];
si5351_ms_write_params(synth, WSPR_SYMBOLS[sym]);
_delay_ms(WSPR_PERIOD);
}
si5351_ms_disable_output(synth);
}

Loading…
Cancel
Save