Skip to content

Commit

Permalink
First WSPR-modulated emission. Start checking.
Browse files Browse the repository at this point in the history
  • Loading branch information
RPiks committed Nov 16, 2023
1 parent 6c5ad45 commit 78a9431
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 51 deletions.
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ pico_sdk_init()

add_executable(pico-wspr-tx)

pico_generate_pio_header(pico-wspr-tx ${CMAKE_CURRENT_LIST_DIR}/pico-hf-oscillator/piodco/dco.pio)

target_sources(pico-wspr-tx PUBLIC
${CMAKE_CURRENT_LIST_DIR}/pico-hf-oscillator/lib/assert.c
${CMAKE_CURRENT_LIST_DIR}/pico-hf-oscillator/piodco/piodco.c
${CMAKE_CURRENT_LIST_DIR}/TxChannel/TxChannel.c
${CMAKE_CURRENT_LIST_DIR}/WSPRbeacon/thirdparty/WSPRutility.c
${CMAKE_CURRENT_LIST_DIR}/WSPRbeacon/thirdparty/nhash.c
${CMAKE_CURRENT_LIST_DIR}/WSPRbeacon/WSPRbeacon.c
${CMAKE_CURRENT_LIST_DIR}/debug/logutils.c
${CMAKE_CURRENT_LIST_DIR}/init.c
${CMAKE_CURRENT_LIST_DIR}/core1.c
${CMAKE_CURRENT_LIST_DIR}/main.c
)

Expand Down
79 changes: 65 additions & 14 deletions TxChannel/TxChannel.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,28 @@
///////////////////////////////////////////////////////////////////////////////
#include "TxChannel.h"

TxChannelContext *pTX = NULL;

void __not_in_flash_func (TxChannelISR)(void)
static TxChannelContext *spTX = NULL;
static void __not_in_flash_func (TxChannelISR)(void)
{
if(!pTX)
PioDco *pDCO = spTX->_p_oscillator;

uint8_t byte;
const int n2send = TxChannelPop(spTX, &byte);
if(n2send)
{
pTX->_tm_future_call += 500LL;
goto EXIT;
PioDCOSetFreq(pDCO, spTX->_u32_dialfreqhz,
byte * FREQ_STEP_MILLIHERTZ);
}

pTX->_pf_modulator(FREQ_STEP_MILLIHERTZ, pTX->_u8byte_buffer[pTX->_ix_output++]);
pTX->_tm_future_call += pTX->_bit_period_us;
spTX->_tm_future_call += spTX->_bit_period_us;

EXIT:
hw_clear_bits(&timer_hw->intr, 1U<<pTX->_timer_alarm_num);
timer_hw->alarm[pTX->_timer_alarm_num] = (uint32_t)pTX->_tm_future_call;
hw_clear_bits(&timer_hw->intr, 1U<<spTX->_timer_alarm_num);
timer_hw->alarm[spTX->_timer_alarm_num] = (uint32_t)spTX->_tm_future_call;

/* LED debug signal */
static int tick = 0;
gpio_put(PICO_DEFAULT_LED_PIN, ++tick & 1);
}

/// @brief Initializes a TxChannel context. Starts ISR.
Expand All @@ -73,25 +79,70 @@ void __not_in_flash_func (TxChannelISR)(void)
/// @param pfmodulator Ptr to low level real-time modulator function.
/// @return the Context.
TxChannelContext *TxChannelInit(const uint32_t bit_period_us, uint8_t timer_alarm_num,
void *pfmodulator)
PioDco *pDCO)
{
assert_(pfmodulator);
assert_(pDCO);
assert_(bit_period_us > 10);

TxChannelContext *p = calloc(1, sizeof(TxChannelContext));
assert_(p);

spTX = p;

p->_bit_period_us = bit_period_us;
p->_timer_alarm_num = timer_alarm_num;
p->_pf_modulator = pfmodulator;
p->_p_oscillator = pDCO;

hw_set_bits(&timer_hw->inte, 1U << p->_timer_alarm_num);
irq_set_exclusive_handler(TIMER_IRQ_0, TxChannelISR);
irq_set_priority(TIMER_IRQ_0, 0x00);
irq_set_enabled(TIMER_IRQ_0, true);

p->_tm_future_call = timer_hw->timerawl + 500LL;
p->_tm_future_call = timer_hw->timerawl + 10000LL;
timer_hw->alarm[p->_timer_alarm_num] = (uint32_t)p->_tm_future_call;

return p;
}

uint8_t TxChannelPending(TxChannelContext *pctx)
{
return 256 + pctx->_ix_input - pctx->_ix_output;
}

int TxChannelPush(TxChannelContext *pctx, uint8_t *psrc, int n)
{
uint8_t *pdst = pctx->_pbyte_buffer;
while(n-- && pctx->_ix_input != pctx->_ix_output)
{
pdst[pctx->_ix_input++] = *psrc++;
}

return n;
}

int TxChannelPop(TxChannelContext *pctx, uint8_t *pdst)
{
if(pctx->_ix_input != pctx->_ix_output)
{
*pdst = pctx->_pbyte_buffer[pctx->_ix_output++];

return 1;
}

return 0;
}

void TxChannelClear(TxChannelContext *pctx)
{
pctx->_ix_input = pctx->_ix_output = 0;
}

void TxChannelStart(TxChannelContext *pctx)
{
pctx->_b_allowtx = YES;
}

void TxChannelStop(TxChannelContext *pctx)
{
pctx->_b_allowtx = NO;
}
20 changes: 14 additions & 6 deletions TxChannel/TxChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "hardware/clocks.h"
#include "pico/stdlib.h"
#include "../pico-hf-oscillator/lib/assert.h"
#include <piodco.h>

#define FREQ_STEP_MILLIHERTZ 1465

Expand All @@ -64,17 +65,24 @@ typedef struct
uint32_t _bit_period_us;

uint8_t _timer_alarm_num;
uint8_t _b_allowtx;

uint8_t _u8byte_buffer[256];
uint8_t _ix_input, _ix_output;
uint8_t _pbyte_buffer[256];

int (*_pf_modulator)(uint32_t frq_step, uint8_t shift_val);
int (*_pf_setPTT)(uint8_t bptt_state);
PioDco *_p_oscillator;
uint32_t _u32_dialfreqhz;

} TxChannelContext;

TxChannelContext *TxChannelInit(const uint32_t bit_period_us, uint8_t timer_alarm_num,
void *pfmodulator);
void __not_in_flash_func (TxChannelISR)(void);
TxChannelContext *TxChannelInit(const uint32_t bit_period_us,
uint8_t timer_alarm_num, PioDco *pDCO);

uint8_t TxChannelPending(TxChannelContext *pctx);
int TxChannelPush(TxChannelContext *pctx, uint8_t *psrc, int n);
int TxChannelPop(TxChannelContext *pctx, uint8_t *pdst);
void TxChannelClear(TxChannelContext *pctx);
void TxChannelStart(TxChannelContext *pctx);
void TxChannelStop(TxChannelContext *pctx);

#endif
18 changes: 15 additions & 3 deletions WSPRbeacon/WSPRbeacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
#include <WSPRutility.h>

WSPRbeaconContext *WSPRbeaconInit(const char *pcallsign, const char *pgridsquare, int txpow_dbm,
void *pfsk4modulator)
PioDco *pdco)
{
assert_(pdco);

WSPRbeaconContext *p = calloc(1, sizeof(WSPRbeaconContext));
assert_(p);

strncpy(p->_pu8_callsign, pcallsign, sizeof(p->_pu8_callsign));
strncpy(p->_pu8_locator, pgridsquare, sizeof(p->_pu8_locator));
p->_u8_txpower = txpow_dbm;

p->_pTX = TxChannelInit(682667, 0, pfsk4modulator);
p->_pTX = TxChannelInit(682667, 0, pdco);
assert_(p->_pTX);

return p;
Expand All @@ -21,7 +23,7 @@ WSPRbeaconContext *WSPRbeaconInit(const char *pcallsign, const char *pgridsquare
void WSPRbeaconSetDialFreq(WSPRbeaconContext *pctx, uint32_t freq_hz)
{
assert_(pctx);
pctx->_u32_dialfreqhz = freq_hz;
pctx->_pTX->_u32_dialfreqhz = freq_hz;
}

int WSPRbeaconCreatePacket(WSPRbeaconContext *pctx)
Expand All @@ -30,3 +32,13 @@ int WSPRbeaconCreatePacket(WSPRbeaconContext *pctx)

wspr_encode(pctx->_pu8_callsign, pctx->_pu8_locator, pctx->_u8_txpower, pctx->_pu8_outbuf);
}

int WSPRbeaconSendPacket(const WSPRbeaconContext *pctx)
{
assert_(pctx);
assert_(pctx->_pTX);
assert_(pctx->_pTX->_u32_dialfreqhz > 1100 * kHz);

memcpy(pctx->_pTX->_pbyte_buffer, pctx->_pu8_outbuf, WSPR_SYMBOL_COUNT);
pctx->_pTX->_ix_input += WSPR_SYMBOL_COUNT;
}
5 changes: 1 addition & 4 deletions WSPRbeacon/WSPRbeacon.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,13 @@ typedef struct
uint8_t _pu8_outbuf[256];

TxChannelContext *_pTX;
uint32_t _u32_dialfreqhz;

} WSPRbeaconContext;

WSPRbeaconContext *WSPRbeaconInit(const char *pcallsign, const char *pgridsquare, int txpow_dbm,
void *pfsk4modulator);
PioDco *pdco);
void WSPRbeaconSetDialFreq(WSPRbeaconContext *pctx, uint32_t freq_hz);
int WSPRbeaconCreatePacket(WSPRbeaconContext *pctx);
int WSPRbeaconSendPacket(const WSPRbeaconContext *pctx);

//int WSPRbeaconFSK4mod(uint8_t bits_per_sample, uint8_t sample_val);

#endif
28 changes: 28 additions & 0 deletions core1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

#include <stdint.h>

#include "pico-hf-oscillator/lib/assert.h"
#include <piodco.h>
#include "defines.h"

extern PioDco DCO;

/* This is the code of dedicated core.
We deal with extremely precise real-time task. */
void Core1Entry()
{
const uint32_t clkhz = PLL_SYS_MHZ * MHz;
const uint32_t freq_hz = WSPR_DIAL_FREQ_HZ + WSPR_SHIFT_FREQ_HZ;

/* Initialize DCO */
assert_(0 == PioDCOInit(&DCO, 6, clkhz));

/* Run DCO. */
PioDCOStart(&DCO);

/* Set initial freq. */
assert_(0 == PioDCOSetFreq(&DCO, freq_hz, 0u));

/* Run the main DCO algorithm. It spins forever. */
PioDCOWorker(&DCO);
}
32 changes: 32 additions & 0 deletions defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,36 @@
#define DEBUGPRINTF(x) { }
#endif

#define FALSE 0 /* Something is false. */
#define TRUE 1 /* Something is true. */
#define BAD 0 /* Something is bad. */
#define GOOD 1 /* Something is good. */
#define INVALID 0 /* Something is invalid. */
#define VALID 1 /* Something is valid. */
#define NO 0 /* The answer is no. */
#define YES 1 /* The answer is yes. */
#define OFF 0 /* Turn something off. */
#define ON 1 /* Turn something on. */

#define RAM __not_in_flash_func /* Place time-critical func in RAM */
#define RAM_A __not_in_flash("A") /* Place time-critical var in RAM */

/* A macro for arithmetic right shifts, with casting of the argument. */
#define iSAR(arg, rcount) (((int32_t)(arg)) >> (rcount))

/* A macro of multiplication guarantees of doing so using 1 ASM command. */
#define iMUL32ASM(a,b) __mul_instruction((int32_t)(a), (int32_t)(b))

/* Performing the square by ASM. */
#define iSquare32ASM(x) (iMUL32ASM((x), (x)))

/* Hardware defs. */
#define kHz 1000UL
#define MHz 1000000UL
#define PLL_SYS_MHZ 270UL

/* WSPR defs. */
#define WSPR_DIAL_FREQ_HZ 7040000UL
#define WSPR_SHIFT_FREQ_HZ 88UL

#endif
22 changes: 22 additions & 0 deletions init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "pico/stdlib.h"
#include "hardware/clocks.h"

#include "defines.h"

void InitPicoHW(void)
{
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);

const uint32_t clkhz = PLL_SYS_MHZ * 1000000L;
set_sys_clock_khz(clkhz / kHz, true);

clock_configure(clk_peri, 0,
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
PLL_SYS_MHZ * MHZ,
PLL_SYS_MHZ * MHZ);
}
42 changes: 18 additions & 24 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,44 +61,37 @@

#include "debug/logutils.h"

PioDco DCO;

int FSK4mod(uint32_t frq_step_millihz, uint8_t shift_index);
void InitPicoHW(void);
void Core1Entry(void);

int main()
{
DEBUGPRINTF("\n");
sleep_ms(1000);
DEBUGPRINTF("Pico-WSPR-tx start.");

InitPicoHW();

DEBUGPRINTF("WSPR beacon init...");
WSPRbeaconContext *pWB = WSPRbeaconInit("R2BDY", "KO85", 6, FSK4mod);
WSPRbeaconContext *pWB = WSPRbeaconInit("R2BDY/QRPX", "KO85", 6, &DCO);
WSPRbeaconSetDialFreq(pWB, WSPR_DIAL_FREQ_HZ + WSPR_SHIFT_FREQ_HZ);
DEBUGPRINTF("OK");

DEBUGPRINTF("Create packet...");
WSPRbeaconCreatePacket(pWB);
DEBUGPRINTF("OK");

sleep_ms(100);

int row = 0;
do
{
for(int i = 0; i < 16; ++i)
{
const int j = i + row * 16;
printf("%X ", pWB->_pu8_outbuf[j]);
if(161 == j)
{
row = -1;
break;
}
}
printf("\n");
if(-1 == row)
break;
++row;
DEBUGPRINTF("Start oscillator on Core #1...");
multicore_launch_core1(Core1Entry);
DEBUGPRINTF("OK");

DEBUGPRINTF("Sending WSPR packet...");
WSPRbeaconSendPacket(pWB);

} while (true);

for(;;)
{
DEBUGPRINTF("tick.");
Expand All @@ -108,6 +101,7 @@ int main()

int FSK4mod(uint32_t frq_step_millihz, uint8_t shift_index)
{

PioDCOSetFreq(&DCO, WSPR_DIAL_FREQ_HZ + WSPR_SHIFT_FREQ_HZ,
frq_step_millihz * shift_index);
return 0;
}
}

0 comments on commit 78a9431

Please sign in to comment.