First WSPR-modulated emission. Start checking.

gps_test
roman 2023-11-16 21:08:18 +03:00
rodzic 6c5ad458ce
commit 78a9431387
9 zmienionych plików z 201 dodań i 52 usunięć

Wyświetl plik

@ -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
)

Wyświetl plik

@ -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.
@ -73,25 +79,70 @@ EXIT:
/// @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;
}

Wyświetl plik

@ -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
@ -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

Wyświetl plik

@ -3,8 +3,10 @@
#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);
@ -12,7 +14,7 @@ WSPRbeaconContext *WSPRbeaconInit(const char *pcallsign, const char *pgridsquare
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;
@ -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)
@ -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;
}

Wyświetl plik

@ -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
core1.c 100644
Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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
init.c 100644
Wyświetl plik

@ -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);
}

44
main.c
Wyświetl plik

@ -61,7 +61,11 @@
#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()
{
@ -69,36 +73,25 @@ int main()
sleep_ms(1000);
DEBUGPRINTF("Pico-WSPR-tx start.");
DEBUGPRINTF("WSPR beacon init...");
WSPRbeaconContext *pWB = WSPRbeaconInit("R2BDY", "KO85", 6, FSK4mod);
DEBUGPRINTF("OK");
InitPicoHW();
DEBUGPRINTF("WSPR beacon init...");
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.");
@ -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;
}
}