kopia lustrzana https://github.com/ArjanteMarvelde/uSDR-pico
rodzic
6238c98a3e
commit
a060b06065
|
@ -19,7 +19,7 @@ pico_sdk_init()
|
||||||
|
|
||||||
# Add executable. Default name is the project name, version 0.1
|
# Add executable. Default name is the project name, version 0.1
|
||||||
|
|
||||||
add_executable(uSDR uSDR.c lcd.c si5351.c dsp.c)
|
add_executable(uSDR uSDR.c lcd.c si5351.c dsp.c monitor.c)
|
||||||
|
|
||||||
pico_set_program_name(uSDR "uSDR")
|
pico_set_program_name(uSDR "uSDR")
|
||||||
pico_set_program_version(uSDR "0.1")
|
pico_set_program_version(uSDR "0.1")
|
||||||
|
@ -31,9 +31,12 @@ target_link_libraries(uSDR pico_stdlib)
|
||||||
pico_enable_stdio_uart(uSDR 0)
|
pico_enable_stdio_uart(uSDR 0)
|
||||||
pico_enable_stdio_usb(uSDR 1)
|
pico_enable_stdio_usb(uSDR 1)
|
||||||
|
|
||||||
|
|
||||||
# Add any user requested libraries
|
# Add any user requested libraries
|
||||||
target_link_libraries(uSDR
|
target_link_libraries(uSDR
|
||||||
hardware_i2c
|
pico_stdlib
|
||||||
|
pico_multicore
|
||||||
|
hardware_i2c
|
||||||
hardware_pwm
|
hardware_pwm
|
||||||
hardware_pio
|
hardware_pio
|
||||||
hardware_timer
|
hardware_timer
|
||||||
|
|
78
dsp.c
78
dsp.c
|
@ -2,11 +2,12 @@
|
||||||
* dsp.c
|
* dsp.c
|
||||||
*
|
*
|
||||||
* Created: Mar 2021
|
* Created: Mar 2021
|
||||||
* Author: Arjan
|
* Author: Arjan te Marvelde
|
||||||
*
|
*
|
||||||
* Signal processing of RX and TX branch
|
* Signal processing of RX and TX branch, to be run on the second processor core.
|
||||||
* Each branch has a dedicated timer routine that runs on set times.
|
* Each branch has a dedicated routine that must run on set times.
|
||||||
* The callback period is set with RX_US and TX_US, e.g. 16 means every 16 usec, or 62.5 kHz.
|
* The period is determined by reads from the inter-core fifo, by the dsp_loop() routine.
|
||||||
|
* This fifo is written from core0 from a 16us timer callback routine (i.e. 62.5kHz)
|
||||||
*
|
*
|
||||||
* The RX branch:
|
* The RX branch:
|
||||||
* - Sample I and Q QSD channels intermittently, and shift into I and Q delay line (31.25 kHz per channel)
|
* - Sample I and Q QSD channels intermittently, and shift into I and Q delay line (31.25 kHz per channel)
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
*
|
*
|
||||||
* The TX branch:
|
* The TX branch:
|
||||||
* - Sample the Audio input channel (62.5 kHz)
|
* - Sample the Audio input channel (62.5 kHz)
|
||||||
* - Low pass filter: Fc=4kHz
|
* - Low pass filter: Fc=3kHz
|
||||||
* - Eight rate (7.8125 kHz) to improve low F behavior of Hilbert transform
|
* - Eight rate (7.8125 kHz) to improve low F behavior of Hilbert transform
|
||||||
* - Generate Q samples by doing a Hilbert transform
|
* - Generate Q samples by doing a Hilbert transform
|
||||||
* - Push I and Q to QSE output DACs
|
* - Push I and Q to QSE output DACs
|
||||||
|
@ -27,8 +28,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/multicore.h"
|
||||||
#include "hardware/pwm.h"
|
#include "hardware/pwm.h"
|
||||||
#include "hardware/adc.h"
|
#include "hardware/adc.h"
|
||||||
|
#include "hardware/irq.h"
|
||||||
|
#include "hardware/timer.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
|
|
||||||
|
@ -65,8 +70,10 @@ uint16_t wave4[64] =
|
||||||
* Exact time is obtained by passing the value negative.
|
* Exact time is obtained by passing the value negative.
|
||||||
* Here we use 16us (62.5 kHz == PWM freq/4 [or 8])
|
* Here we use 16us (62.5 kHz == PWM freq/4 [or 8])
|
||||||
*/
|
*/
|
||||||
#define RX_US 16
|
#define DSP_US 16
|
||||||
#define TX_US 16
|
#define DSP_TX 1
|
||||||
|
#define DSP_RX 2
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Low pass filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/)
|
* Low pass filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/)
|
||||||
|
@ -84,19 +91,16 @@ volatile uint16_t dac_iq, dac_audio;
|
||||||
volatile bool tx_enabled;
|
volatile bool tx_enabled;
|
||||||
|
|
||||||
|
|
||||||
/* RX TIMER and callback */
|
/* CORE1: RX branch */
|
||||||
volatile int16_t i_s[15], q_s[15], i_dc, q_dc, i_prev;
|
volatile int16_t i_s[15], q_s[15], i_dc, q_dc, i_prev;
|
||||||
struct repeating_timer rx_timer;
|
bool rx(void)
|
||||||
bool rx_callback(struct repeating_timer *t)
|
|
||||||
{
|
{
|
||||||
static bool q_phase;
|
static bool q_phase;
|
||||||
int16_t sample;
|
int16_t sample;
|
||||||
int32_t accu;
|
int32_t accu;
|
||||||
int16_t qh;
|
int16_t qh;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (tx_enabled) return(true); // Early bailout when TX-ing
|
|
||||||
|
|
||||||
if (q_phase)
|
if (q_phase)
|
||||||
{
|
{
|
||||||
adc_select_input(1); // Q channel ADC
|
adc_select_input(1); // Q channel ADC
|
||||||
|
@ -170,19 +174,16 @@ bool rx_callback(struct repeating_timer *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TX TIMER and callback */
|
/* CORE1: TX branch */
|
||||||
volatile int16_t a_s_pre[15], a_s[15], a_dc;
|
volatile int16_t a_s_pre[15], a_s[15], a_dc;
|
||||||
struct repeating_timer tx_timer;
|
bool tx(void)
|
||||||
bool tx_callback(struct repeating_timer *t)
|
|
||||||
{
|
{
|
||||||
static int tx_phase = 0;
|
static int tx_phase = 0;
|
||||||
int16_t sample;
|
int16_t sample;
|
||||||
int32_t accu;
|
int32_t accu;
|
||||||
int16_t qh;
|
int16_t qh;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!tx_enabled) return(true);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get sample and shift into delay line
|
* Get sample and shift into delay line
|
||||||
*/
|
*/
|
||||||
|
@ -233,7 +234,37 @@ bool tx_callback(struct repeating_timer *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int dsp_init()
|
/* CORE1: Timing loop, triggered through inter-core fifo */
|
||||||
|
void dsp_loop()
|
||||||
|
{
|
||||||
|
uint32_t cmd;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
cmd = multicore_fifo_pop_blocking(); // Wait for fifo output
|
||||||
|
if (cmd == DSP_TX)
|
||||||
|
tx();
|
||||||
|
else
|
||||||
|
rx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CORE0: Timer callback, triggers core1 through inter-core fifo */
|
||||||
|
struct repeating_timer dsp_timer;
|
||||||
|
bool dsp_callback(struct repeating_timer *t)
|
||||||
|
{
|
||||||
|
//if (tx_enabled)
|
||||||
|
multicore_fifo_push_blocking(DSP_TX); // Write TX in fifo to core 1
|
||||||
|
//else
|
||||||
|
multicore_fifo_push_blocking(DSP_RX); // Write RX in fifo to core 1
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CORE0: Initialize dsp context and spawn core1 process */
|
||||||
|
void dsp_init()
|
||||||
{
|
{
|
||||||
uint16_t slice_num;
|
uint16_t slice_num;
|
||||||
|
|
||||||
|
@ -259,9 +290,8 @@ int dsp_init()
|
||||||
adc_select_input(0); // Select ADC 0
|
adc_select_input(0); // Select ADC 0
|
||||||
|
|
||||||
tx_enabled = false; // RX mode
|
tx_enabled = false; // RX mode
|
||||||
|
|
||||||
//add_repeating_timer_us(-TX_US, tx_callback, NULL, &tx_timer);
|
|
||||||
add_repeating_timer_us(-RX_US, rx_callback, NULL, &rx_timer);
|
|
||||||
|
|
||||||
return 0;
|
multicore_launch_core1(dsp_loop); // Start processing on core1
|
||||||
|
add_repeating_timer_us(-DSP_US, dsp_callback, NULL, &dsp_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
dsp.h
10
dsp.h
|
@ -1,11 +1,19 @@
|
||||||
#ifndef __DSP_H__
|
#ifndef __DSP_H__
|
||||||
#define __DSP_H__
|
#define __DSP_H__
|
||||||
|
/*
|
||||||
|
* dsp.h
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
|
* See dsp.c for more information
|
||||||
|
*/
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/adc.h"
|
#include "hardware/adc.h"
|
||||||
#include "hardware/pwm.h"
|
#include "hardware/pwm.h"
|
||||||
|
|
||||||
|
|
||||||
int dsp_init();
|
void dsp_init();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
5
lcd.c
5
lcd.c
|
@ -1,4 +1,9 @@
|
||||||
/*
|
/*
|
||||||
|
* lcd.c
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
* Grove 16x2 LCD, HD44780 chip with JHD1804 I2C interface
|
* Grove 16x2 LCD, HD44780 chip with JHD1804 I2C interface
|
||||||
* Display RAM addresses 0x00-0x1f for top row and 0x40-0x5f for bottom row
|
* Display RAM addresses 0x00-0x1f for top row and 0x40-0x5f for bottom row
|
||||||
*
|
*
|
||||||
|
|
8
lcd.h
8
lcd.h
|
@ -1,5 +1,13 @@
|
||||||
#ifndef __LCD_H__
|
#ifndef __LCD_H__
|
||||||
#define __LCD_H__
|
#define __LCD_H__
|
||||||
|
/*
|
||||||
|
* lcd.h
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
|
* See lcd.c for more information
|
||||||
|
*/
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/i2c.h"
|
#include "hardware/i2c.h"
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* monitor.c
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
|
* Command shell on stdin/stdout.
|
||||||
|
* Collects characters and parses commandstring.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
|
#include "si5351.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
|
/* Monitor definitions */
|
||||||
|
#define ENDSTDIN 255
|
||||||
|
#define CR 13
|
||||||
|
#define LF 10
|
||||||
|
#define CMD_LEN 32
|
||||||
|
|
||||||
|
|
||||||
|
char mon_cmd[CMD_LEN+1];
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t si5351_reg[200];
|
||||||
|
|
||||||
|
/* Commandstring parser */
|
||||||
|
char delim[] = " ";
|
||||||
|
#define NCMD 3
|
||||||
|
char *shell[NCMD] = {"si", "fa", "fb"};
|
||||||
|
void mon_parse(char* s)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int base, nreg, i;
|
||||||
|
|
||||||
|
p = strtok(s, delim); // Get command part of string
|
||||||
|
for (i=0; i<NCMD; i++)
|
||||||
|
if (strcmp(p, shell[i]) == 0) break;
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// Next: p = strtok(NULL, delim); (returns NULL if none left)
|
||||||
|
for (i=0; i<nreg; i++) si5351_reg[i] = 0xaa;
|
||||||
|
si_getreg(si5351_reg, (uint8_t)base, (uint8_t)nreg);
|
||||||
|
for (i=0; i<nreg; i++) printf("%02x ",(int)(si5351_reg[i]));
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("%s\n", p);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
printf("%s\n", p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mon_init()
|
||||||
|
{
|
||||||
|
/* Initialize IOs */
|
||||||
|
stdio_init_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mon_read(uint32_t timeout)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int c = getchar_timeout_us(timeout);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case PICO_ERROR_TIMEOUT: // just go-on
|
||||||
|
break;
|
||||||
|
case CR: // CR or LF:
|
||||||
|
case LF: // need to parse command string
|
||||||
|
putchar((char)c); // echo character
|
||||||
|
if (i==0) break; // already did a parse, only do it once
|
||||||
|
mon_cmd[i] = 0; // terminate command string
|
||||||
|
i=0; // reset index
|
||||||
|
mon_parse(mon_cmd); // process command
|
||||||
|
printf("Pico> "); // prompt
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ((c<32)||(c>=128)) break; // Alfanumeric?
|
||||||
|
putchar((char)c); // echo character
|
||||||
|
mon_cmd[i] = (char)c; // store in command string
|
||||||
|
if (i<CMD_LEN) i++; // check range and increment
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __MONITOR_H__
|
||||||
|
#define __MONITOR_H__
|
||||||
|
/*
|
||||||
|
* monitor.h
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
|
* See monitor.c for more information
|
||||||
|
*/
|
||||||
|
|
||||||
|
void mon_init();
|
||||||
|
void mon_read(uint32_t timeout);
|
||||||
|
|
||||||
|
#endif
|
27
si5351.c
27
si5351.c
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* si5351.c
|
* si5351.c
|
||||||
*
|
*
|
||||||
* Created: 12 Jan 2020 21:45:00
|
* Created: Jan 2020
|
||||||
* Author: Arjan
|
* Author: Arjan
|
||||||
|
|
||||||
Si5351 principle:
|
Si5351 principle:
|
||||||
=================
|
=================
|
||||||
|
@ -117,21 +117,6 @@ Control Si5351:
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
Implicit type conversion precedence:
|
|
||||||
- long double
|
|
||||||
- double
|
|
||||||
- float
|
|
||||||
- unsigned long int
|
|
||||||
- long int
|
|
||||||
- unsigned int
|
|
||||||
- int
|
|
||||||
- other
|
|
||||||
conversion is always to highest type, this is also the result of an operation.
|
|
||||||
|
|
||||||
Maximum UL = 4,294,967,295 (0xffffffff)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
|
@ -190,6 +175,7 @@ Control Si5351:
|
||||||
|
|
||||||
vfo_t vfo[2]; // 0: clk0 and clk1 1: clk2
|
vfo_t vfo[2]; // 0: clk0 and clk1 1: clk2
|
||||||
|
|
||||||
|
/* read contents of SI5351 registers, from reg to reg+len-1, output in data array */
|
||||||
int si_getreg(uint8_t *data, uint8_t reg, uint8_t len)
|
int si_getreg(uint8_t *data, uint8_t reg, uint8_t len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -304,7 +290,7 @@ void si_setmsi(uint8_t i)
|
||||||
// If in range, just set MSN registers
|
// If in range, just set MSN registers
|
||||||
// If not in range, recalculate MSi and Ri and also MSN
|
// If not in range, recalculate MSi and Ri and also MSN
|
||||||
// Set MSN, MSi and Ri registers (implicitly resets PLL)
|
// Set MSN, MSi and Ri registers (implicitly resets PLL)
|
||||||
void vfo_evaluate(void)
|
void si_evaluate(void)
|
||||||
{
|
{
|
||||||
float msn;
|
float msn;
|
||||||
|
|
||||||
|
@ -342,7 +328,7 @@ void vfo_evaluate(void)
|
||||||
|
|
||||||
|
|
||||||
// Initialize the Si5351 VFO registers
|
// Initialize the Si5351 VFO registers
|
||||||
void vfo_init(void)
|
void si_init(void)
|
||||||
{
|
{
|
||||||
uint8_t data[16]; // I2C trx buffer
|
uint8_t data[16]; // I2C trx buffer
|
||||||
|
|
||||||
|
@ -358,7 +344,7 @@ void vfo_init(void)
|
||||||
// MSN=27.2 P1=2969, P2=600000, P3=1000000
|
// MSN=27.2 P1=2969, P2=600000, P3=1000000
|
||||||
vfo[0].freq = 10000000;
|
vfo[0].freq = 10000000;
|
||||||
vfo[0].flag = 0;
|
vfo[0].flag = 0;
|
||||||
vfo[0].phase = 2;
|
vfo[0].phase = 1;
|
||||||
vfo[0].ri = 1;
|
vfo[0].ri = 1;
|
||||||
vfo[0].msi = 68;
|
vfo[0].msi = 68;
|
||||||
vfo[0].msn = 27.2;
|
vfo[0].msn = 27.2;
|
||||||
|
@ -434,6 +420,5 @@ void vfo_init(void)
|
||||||
data[0] = SI_CLK_OE;
|
data[0] = SI_CLK_OE;
|
||||||
data[1] = 0x00;
|
data[1] = 0x00;
|
||||||
i2c_write_blocking(i2c1, I2C_VFO, data, 2, false);
|
i2c_write_blocking(i2c1, I2C_VFO, data, 2, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
si5351.h
11
si5351.h
|
@ -3,8 +3,11 @@
|
||||||
/*
|
/*
|
||||||
* si5351.h
|
* si5351.h
|
||||||
*
|
*
|
||||||
* Created: 13 March 2021
|
* Created: March 2021
|
||||||
* Author: Arjan
|
* Author: Arjan
|
||||||
|
*
|
||||||
|
* See si5351.c for more information
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,13 +24,13 @@ typedef struct
|
||||||
extern vfo_t vfo[2]; // Table contains all control data for three clk outputs, but 0 and 1 are coupled in vfo[0]
|
extern vfo_t vfo[2]; // Table contains all control data for three clk outputs, but 0 and 1 are coupled in vfo[0]
|
||||||
|
|
||||||
int si_getreg(uint8_t *data, uint8_t reg, uint8_t len);
|
int si_getreg(uint8_t *data, uint8_t reg, uint8_t len);
|
||||||
void vfo_init(void);
|
void si_init(void);
|
||||||
void vfo_evaluate(void);
|
void si_evaluate(void);
|
||||||
|
|
||||||
|
|
||||||
#define SI_GETFREQ(i) ((((i)>=0)&&((i)<2))?vfo[(i)].freq:0)
|
#define SI_GETFREQ(i) ((((i)>=0)&&((i)<2))?vfo[(i)].freq:0)
|
||||||
#define SI_INCFREQ(i, d) if ((((i)>=0)&&((i)<2))&&((vfo[(i)].freq)<(150000000-(d)))) { vfo[(i)].freq += (d); vfo[(i)].flag = 1;}
|
#define SI_INCFREQ(i, d) if ((((i)>=0)&&((i)<2))&&((vfo[(i)].freq)<(150000000-(d)))) { vfo[(i)].freq += (d); vfo[(i)].flag = 1;}
|
||||||
#define SI_DECFREQ(i, d) if ((((i)>=0)&&((i)<2))&&((vfo[(i)].freq)>(d))) { (vfo[(i)].freq) -= (d); vfo[(i)].flag = 1;}
|
#define SI_DECFREQ(i, d) if ((((i)>=0)&&((i)<2))&&((vfo[(i)].freq)>(d))) { (vfo[(i)].freq) -= (d); vfo[(i)].flag = 1;}
|
||||||
#define SI_SETFREQ(i, f) if ((((i)>=0)&&((i)<2))&&((f)<150000000)) { vfo[(i)].freq = (f); vfo[(i)].flag = 1;}
|
#define SI_SETFREQ(i, f) if ((((i)>=0)&&((i)<2))&&((f)<150000000)) { vfo[(i)].freq = (f); vfo[(i)].flag = 1;}
|
||||||
|
#define SI_SETPHASE(i, p) if (((i)>=0)&&((i)<2)) {vfo[(i)].phase = ((uint8_t)p)&3; vfo[(i)].flag = 1;}
|
||||||
|
|
||||||
#endif /* _SI5351_H */
|
#endif /* _SI5351_H */
|
102
uSDR.c
102
uSDR.c
|
@ -1,7 +1,21 @@
|
||||||
|
/*
|
||||||
|
* uSDR.c
|
||||||
|
*
|
||||||
|
* Created: Mar 2021
|
||||||
|
* Author: Arjan te Marvelde
|
||||||
|
*
|
||||||
|
* The main loop of the application.
|
||||||
|
* This initializes the units that do the actual work, and then loops in the background.
|
||||||
|
* Other units are:
|
||||||
|
* - dsp.c, containing all signal processing in RX and TX branches. This part runs on the second processor core.
|
||||||
|
* - si5351.c, containing all controls for setting up the si5351 clock generator.
|
||||||
|
* - lcd.c, contains all functions to put something on the LCD
|
||||||
|
* - hmi.c, contains all functions that handle user inputs
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/pwm.h"
|
|
||||||
#include "hardware/pio.h"
|
#include "hardware/pio.h"
|
||||||
#include "hardware/timer.h"
|
#include "hardware/timer.h"
|
||||||
#include "hardware/clocks.h"
|
#include "hardware/clocks.h"
|
||||||
|
@ -9,20 +23,13 @@
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
#include "si5351.h"
|
#include "si5351.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Monitor definitions */
|
|
||||||
#define ENDSTDIN 255
|
|
||||||
#define CR 13
|
|
||||||
#define LF 10
|
|
||||||
#define CMD_LEN 32
|
|
||||||
|
|
||||||
uint8_t display1[16];
|
uint8_t display1[16];
|
||||||
uint8_t display2[16];
|
uint8_t display2[16];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* LED TIMER definition and callback */
|
/* LED TIMER definition and callback */
|
||||||
struct repeating_timer led_timer;
|
struct repeating_timer led_timer;
|
||||||
bool led_callback(struct repeating_timer *t)
|
bool led_callback(struct repeating_timer *t)
|
||||||
|
@ -35,44 +42,8 @@ bool led_callback(struct repeating_timer *t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t si5351_reg[200];
|
|
||||||
char delim[] = " ";
|
|
||||||
#define NCMD 3
|
|
||||||
char *shell[NCMD] = {"si", "fa", "fb"};
|
|
||||||
void mon_parse(char* s)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
int base, nreg, i;
|
|
||||||
|
|
||||||
p = strtok(s, delim); // Get command part of string
|
|
||||||
for (i=0; i<NCMD; i++)
|
|
||||||
if (strcmp(p, shell[i]) == 0) break;
|
|
||||||
switch(i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// Next: p = strtok(NULL, delim); (returns NULL if none left)
|
|
||||||
for (i=0; i<nreg; i++) si5351_reg[i] = 0xaa;
|
|
||||||
si_getreg(si5351_reg, (uint8_t)base, (uint8_t)nreg);
|
|
||||||
for (i=0; i<nreg; i++) printf("%02x ",(int)(si5351_reg[i]));
|
|
||||||
printf("\n");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
printf("%s\n", p);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printf("%s\n", p);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
/* Initialize IOs */
|
|
||||||
stdio_init_all();
|
|
||||||
|
|
||||||
/* Initialize LED pin output */
|
/* Initialize LED pin output */
|
||||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||||
|
@ -80,51 +51,24 @@ int main()
|
||||||
gpio_put(PICO_DEFAULT_LED_PIN, true); // Set LED on
|
gpio_put(PICO_DEFAULT_LED_PIN, true); // Set LED on
|
||||||
add_repeating_timer_ms(-1000, led_callback, NULL, &led_timer);
|
add_repeating_timer_ms(-1000, led_callback, NULL, &led_timer);
|
||||||
|
|
||||||
/* Initialize PWM */
|
/* Initialize units */
|
||||||
dsp_init();
|
si_init(); // VFO control unit
|
||||||
|
lcd_init(); // LCD output unit
|
||||||
|
dsp_init(); // Signal processing unit
|
||||||
|
|
||||||
/* Initialize Si5351 vfo */
|
|
||||||
vfo_init();
|
|
||||||
|
|
||||||
/* Initialize LCD */
|
|
||||||
lcd_init();
|
|
||||||
lcd_ctrl(LCD_GOTO, 0, 0);
|
lcd_ctrl(LCD_GOTO, 0, 0);
|
||||||
sprintf(display1, "A: 7074.0 kHz");
|
sprintf(display1, "A: 7074.0 kHz");
|
||||||
lcd_write(display1,13);
|
lcd_write(display1,13);
|
||||||
|
|
||||||
SI_SETFREQ(0, 2*7074000UL); // Set freq to 2*7074 kHz
|
SI_SETFREQ(0, 2*7074000UL); // Set freq to 2*7074 kHz
|
||||||
|
SI_SETPHASE(0,2); // Set phase to 180deg
|
||||||
|
|
||||||
/* Initialize monitor terminal */
|
|
||||||
printf("Pico> ");
|
|
||||||
int c, i=0;
|
|
||||||
char mon_cmd[CMD_LEN+1];
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* Check for monitor input */
|
/* Check for monitor input */
|
||||||
c = getchar_timeout_us(100000); // 1 try per 100 msec
|
mon_read(100000L); // Wait max 100msec
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case PICO_ERROR_TIMEOUT: // just go-on
|
|
||||||
break;
|
|
||||||
case CR: // CR or LF:
|
|
||||||
case LF: // need to parse command string
|
|
||||||
putchar((char)c); // echo character
|
|
||||||
if (i==0) break; // already did a parse, only do it once
|
|
||||||
mon_cmd[i] = 0; // terminate command string
|
|
||||||
i=0; // reset index
|
|
||||||
mon_parse(mon_cmd); // process command
|
|
||||||
printf("Pico> "); // prompt
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if ((c<32)||(c>=128)) break; // Alfanumeric?
|
|
||||||
putchar((char)c); // echo character
|
|
||||||
mon_cmd[i] = (char)c; // store in command string
|
|
||||||
if (i<CMD_LEN) i++; // check range and increment
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether VFO settings have changed */
|
/* Check whether VFO settings have changed */
|
||||||
vfo_evaluate();
|
si_evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Ładowanie…
Reference in New Issue