kopia lustrzana https://github.com/ArjanteMarvelde/uSDR-pico
updates lcd, monitor
rodzic
9984e43c16
commit
fbe0e50663
79
dsp.c
79
dsp.c
|
@ -37,24 +37,6 @@
|
|||
|
||||
#include "dsp.h"
|
||||
|
||||
/* Test sine waves 1, 2 and 4 kHz (@ 62.5kS/s rate) *
|
||||
uint16_t wave1[64] =
|
||||
{
|
||||
500,549,597,645,691,735,777,817,853,886,915,940,961,978,990,997,999,997,990,978,961,940,915,886,853,817,777,735,691,645,597,549,
|
||||
500,450,402,354,308,264,222,182,146,113,84,59,38,21,9,2,0,2,9,21,38,59,84,113,146,182,222,264,308,354,402,450
|
||||
};
|
||||
uint16_t wave2[64] =
|
||||
{
|
||||
500,597,691,777,853,915,961,990,999,990,961,915,853,777,691,597,500,402,308,222,146,84,38,9,0,9,38,84,146,222,308,402,
|
||||
500,597,691,777,853,915,961,990,999,990,961,915,853,777,691,597,500,402,308,222,146,84,38,9,0,9,38,84,146,222,308,402
|
||||
};
|
||||
uint16_t wave4[64] =
|
||||
{
|
||||
500,691,853,961,999,961,853,691,500,308,146,38,0,38,146,308,500,691,853,961,999,961,853,691,500,308,146,38,0,38,146,308,
|
||||
500,691,853,961,999,961,853,691,500,308,146,38,0,38,146,308,500,691,853,961,999,961,853,691,500,308,146,38,0,38,146,308
|
||||
};
|
||||
*/
|
||||
|
||||
/*
|
||||
* DAC_RANGE defines PWM cycle, determining DAC resolution and PWM frequency.
|
||||
* DAC resolution = Vcc / DAC_RANGE
|
||||
|
@ -63,12 +45,14 @@ uint16_t wave4[64] =
|
|||
* ADC is 12 bit, so resolution is by definition 4096
|
||||
*/
|
||||
#define DAC_RANGE 250
|
||||
#define DAC_BIAS DAC_RANGE/2
|
||||
#define ADC_RANGE 4096
|
||||
#define ADC_BIAS ADC_RANGE/2
|
||||
|
||||
/*
|
||||
* Callback timeout, determines frequency of TX and RX loops
|
||||
* Exact time is obtained by passing the value negative.
|
||||
* Callback timeout and inter-core FIFO commands.
|
||||
* The timer value in usec determines frequency of TX and RX loops
|
||||
* Exact time is obtained by passing the value as negative
|
||||
* Here we use 16us (62.5 kHz == PWM freq/4 [or 8])
|
||||
*/
|
||||
#define DSP_US 16
|
||||
|
@ -78,7 +62,7 @@ uint16_t wave4[64] =
|
|||
|
||||
/*
|
||||
* Low pass filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/)
|
||||
* for sample rates 62.500 , 31.250 or 15.625 kHz , stopband appr -40dB
|
||||
* for sample rates 62.500 , 31.250 or 15.625 kHz , stopband is appr -40dB
|
||||
* 8 bit precision, so divide sum by 256
|
||||
*/
|
||||
int16_t lpf3_62[15] = { 3, 3, 5, 7, 9, 10, 11, 11, 11, 10, 9, 7, 5, 3, 3}; // Pass: 0-3000, Stop: 6000-31250
|
||||
|
@ -92,7 +76,10 @@ volatile uint16_t dac_iq, dac_audio;
|
|||
volatile bool tx_enabled;
|
||||
|
||||
|
||||
/* CORE1: RX branch */
|
||||
/*
|
||||
* CORE1:
|
||||
* Execute RX branch signal processing
|
||||
*/
|
||||
volatile int16_t i_s[15], q_s[15], i_dc, q_dc, i_prev;
|
||||
bool rx(void)
|
||||
{
|
||||
|
@ -147,13 +134,6 @@ bool rx(void)
|
|||
i_s[14] = (sample + i_prev)/2; // Correct for phase difference with Q samples
|
||||
i_prev = sample; // Remember last sample for next I-phase
|
||||
|
||||
/*
|
||||
* Hilbert transform: A0 = 2/128, A2 = 8/128, A4 = 21/128, A6 = 79/128
|
||||
*/
|
||||
// qh = (q_s[0]-q_s[14])/64 +
|
||||
// (q_s[2]-q_s[12])/16 +
|
||||
// (q_s[4]-q_s[10])/8 + (q_s[4]-q_s[10])*5/128 +
|
||||
// (q_s[6]-q_s[ 8])/8 - (q_s[6]-q_s[8])/128 + (q_s[6]-q_s[8])/2;
|
||||
/*
|
||||
* Classic Hilbert transform 15 taps, 12 bits (see Iowa Hills):
|
||||
*/
|
||||
|
@ -166,7 +146,7 @@ bool rx(void)
|
|||
* Add 250 offset and send to audio DAC output
|
||||
*/
|
||||
sample = (i_s[7] - qh)/16;
|
||||
pwm_set_chan_level(dac_audio, PWM_CHAN_A, DAC_RANGE/2 + sample);
|
||||
pwm_set_chan_level(dac_audio, PWM_CHAN_A, DAC_BIAS + sample);
|
||||
|
||||
q_phase = true; // Next: Q branch
|
||||
}
|
||||
|
@ -175,7 +155,10 @@ bool rx(void)
|
|||
}
|
||||
|
||||
|
||||
/* CORE1: TX branch */
|
||||
/*
|
||||
* CORE1:
|
||||
* Execute TX branch signal processing
|
||||
*/
|
||||
volatile int16_t a_s_pre[15], a_s[15], a_dc;
|
||||
bool tx(void)
|
||||
{
|
||||
|
@ -228,14 +211,17 @@ bool tx(void)
|
|||
* Write I and Q to QSE DACs, phase is 7 back.
|
||||
* Need to multiply AC with DAC_RANGE/ADC_RANGE (appr 1/16, but compensate for losses)
|
||||
*/
|
||||
pwm_set_chan_level(dac_iq, PWM_CHAN_A, DAC_RANGE/2 + (a_s[7]/8));
|
||||
pwm_set_chan_level(dac_iq, PWM_CHAN_B, DAC_RANGE/2 + (qh/8));
|
||||
pwm_set_chan_level(dac_iq, PWM_CHAN_A, DAC_BIAS + (a_s[7]/8));
|
||||
pwm_set_chan_level(dac_iq, PWM_CHAN_B, DAC_BIAS + (qh/8));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* CORE1: Timing loop, triggered through inter-core fifo */
|
||||
/*
|
||||
* CORE1:
|
||||
* Timing loop, triggered through inter-core fifo
|
||||
*/
|
||||
void dsp_loop()
|
||||
{
|
||||
uint32_t cmd;
|
||||
|
@ -243,7 +229,7 @@ void dsp_loop()
|
|||
while(1)
|
||||
{
|
||||
cmd = multicore_fifo_pop_blocking(); // Wait for fifo output
|
||||
if (cmd == DSP_TX)
|
||||
if (cmd == DSP_TX) // Change to switch(cmd) when more commands added
|
||||
tx();
|
||||
else
|
||||
rx();
|
||||
|
@ -251,7 +237,11 @@ void dsp_loop()
|
|||
}
|
||||
|
||||
|
||||
/* CORE0: Timer callback, triggers core1 through inter-core fifo */
|
||||
/*
|
||||
* CORE0:
|
||||
* Timer callback, triggers core1 through inter-core fifo.
|
||||
* Either TX or RX, but could do both when testing in loopback on I+Q channels.
|
||||
*/
|
||||
struct repeating_timer dsp_timer;
|
||||
bool dsp_callback(struct repeating_timer *t)
|
||||
{
|
||||
|
@ -264,18 +254,21 @@ bool dsp_callback(struct repeating_timer *t)
|
|||
}
|
||||
|
||||
|
||||
/* CORE0: Initialize dsp context and spawn core1 process */
|
||||
/*
|
||||
* CORE0:
|
||||
* Initialize dsp context and spawn core1 process
|
||||
*/
|
||||
void dsp_init()
|
||||
{
|
||||
uint16_t slice_num;
|
||||
|
||||
/* Initialize DACs */
|
||||
// gpio_set_function(0, GPIO_FUNC_PWM); // GP0 is PWM for I DAC (Slice 0, Channel A)
|
||||
// gpio_set_function(1, GPIO_FUNC_PWM); // GP1 is PWM for Q DAC (Slice 0, Channel B)
|
||||
// dac_iq = pwm_gpio_to_slice_num(0); // Get PWM slice for GP0 (Same for GP1)
|
||||
// pwm_set_clkdiv_int_frac (dac_iq, 1, 0); // clock divide by 1
|
||||
// pwm_set_wrap(dac_iq, DAC_RANGE); // Set cycle length
|
||||
// pwm_set_enabled(dac_iq, true); // Set the PWM running
|
||||
gpio_set_function(0, GPIO_FUNC_PWM); // GP0 is PWM for I DAC (Slice 0, Channel A)
|
||||
gpio_set_function(1, GPIO_FUNC_PWM); // GP1 is PWM for Q DAC (Slice 0, Channel B)
|
||||
dac_iq = pwm_gpio_to_slice_num(0); // Get PWM slice for GP0 (Same for GP1)
|
||||
pwm_set_clkdiv_int_frac (dac_iq, 1, 0); // clock divide by 1
|
||||
pwm_set_wrap(dac_iq, DAC_RANGE); // Set cycle length
|
||||
pwm_set_enabled(dac_iq, true); // Set the PWM running
|
||||
|
||||
gpio_set_function(2, GPIO_FUNC_PWM); // GP2 is PWM for Audio DAC (Slice 1, Channel A)
|
||||
dac_audio = pwm_gpio_to_slice_num(2); // Find PWM slice for GP2
|
||||
|
|
63
lcd.c
63
lcd.c
|
@ -10,6 +10,7 @@
|
|||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "hardware/timer.h"
|
||||
|
@ -64,6 +65,8 @@
|
|||
#define I2C0_SDA 8
|
||||
#define I2C0_SCL 9
|
||||
|
||||
uint8_t lcd_buf[2][16]; // Buffer, y={0,1}, x={0..15}
|
||||
uint8_t lcd_x, lcd_y;
|
||||
|
||||
void lcd_init(void)
|
||||
{
|
||||
|
@ -93,11 +96,20 @@ void lcd_ctrl(uint8_t cmd, uint8_t x, uint8_t y)
|
|||
switch(cmd)
|
||||
{
|
||||
case LCD_CLEAR:
|
||||
for (lcd_x=0; lcd_x<16; lcd_x++)
|
||||
{
|
||||
lcd_buf[0][lcd_x] = ' ';
|
||||
lcd_buf[1][lcd_x] = ' ';
|
||||
}
|
||||
lcd_y = 0x00;
|
||||
lcd_x = 0x00;
|
||||
txdata[1] = LCD_CLEARDISPLAY;
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(1530);
|
||||
break;
|
||||
case LCD_HOME:
|
||||
lcd_y = 0x00;
|
||||
lcd_x = 0x00;
|
||||
txdata[1] = LCD_RETURNHOME;
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(39);
|
||||
|
@ -111,46 +123,63 @@ void lcd_ctrl(uint8_t cmd, uint8_t x, uint8_t y)
|
|||
sleep_us(39);
|
||||
break;
|
||||
case LCD_GOTO: // 2-row is 0x00-0x27 per row, only 0x00-0x1F are visible
|
||||
lcd_y = y&0x01;
|
||||
lcd_x = x&0x0f;
|
||||
if (y==1)
|
||||
txdata[1] = (x&0x0f) | 0xc0;
|
||||
txdata[1] = lcd_x | 0xc0;
|
||||
else
|
||||
txdata[1] = (x&0x0f) | 0x80;
|
||||
txdata[1] = lcd_x | 0x80;
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(39);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_write(uint8_t *s, uint8_t len)
|
||||
void lcd_put(uint8_t c)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *p;
|
||||
uint8_t txdata[8];
|
||||
|
||||
uint8_t txdata[3];
|
||||
|
||||
lcd_buf[lcd_y][lcd_x]=c;
|
||||
lcd_x = (lcd_x<15)?(lcd_x + 1):lcd_x;
|
||||
txdata[0] = 0x40;
|
||||
p=s;
|
||||
for (i=0; i<len; i++)
|
||||
{
|
||||
txdata[1] = *p++;
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(43);
|
||||
}
|
||||
txdata[1] = c;
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(43);
|
||||
}
|
||||
|
||||
void lcd_write(uint8_t *s)
|
||||
{
|
||||
uint8_t i, len;
|
||||
uint8_t txdata[18];
|
||||
|
||||
len = strlen(s);
|
||||
len = (len>(16-lcd_x))?(16-lcd_x):len;
|
||||
txdata[0] = 0x40;
|
||||
for(i=0; i<len; i++)
|
||||
{
|
||||
lcd_buf[lcd_y][lcd_x++]=s[i];
|
||||
txdata[i+1]=s[i];
|
||||
}
|
||||
i2c_write_blocking(i2c0, I2C_LCD, txdata, len+1, false);
|
||||
sleep_us(43);
|
||||
}
|
||||
|
||||
|
||||
void lcd_test(void)
|
||||
{
|
||||
uint8_t chr[16];
|
||||
uint8_t chr[17];
|
||||
int i, j;
|
||||
|
||||
chr[16] = 0;
|
||||
lcd_ctrl(LCD_CLEAR,0,0);
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
for(j=0; j<16; j++) chr[j] = (uint8_t)(16*i+j);
|
||||
lcd_ctrl(LCD_GOTO,0,0);
|
||||
lcd_write(chr, 16);
|
||||
lcd_write(chr);
|
||||
sleep_ms(800);
|
||||
lcd_ctrl(LCD_GOTO,0,1);
|
||||
lcd_write(chr, 16);
|
||||
lcd_write(chr);
|
||||
}
|
||||
lcd_ctrl(LCD_CLEAR,0,0);
|
||||
}
|
3
lcd.h
3
lcd.h
|
@ -20,7 +20,8 @@
|
|||
|
||||
void lcd_init(void);
|
||||
void lcd_ctrl(uint8_t cmd, uint8_t x, uint8_t y);
|
||||
void lcd_write(uint8_t *s, uint8_t len);
|
||||
void lcd_put(uint8_t c);
|
||||
void lcd_write(uint8_t *s);
|
||||
void lcd_test(void);
|
||||
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ void mon_init()
|
|||
|
||||
void mon_read(uint32_t timeout)
|
||||
{
|
||||
int i = 0;
|
||||
static int i = 0;
|
||||
int c = getchar_timeout_us(timeout);
|
||||
switch (c)
|
||||
{
|
||||
|
|
25
uSDR.c
25
uSDR.c
|
@ -26,11 +26,11 @@
|
|||
#include "monitor.h"
|
||||
|
||||
|
||||
uint8_t display1[16];
|
||||
uint8_t display2[16];
|
||||
|
||||
|
||||
/* LED TIMER definition and callback */
|
||||
/*
|
||||
* LED TIMER definition and callback routine
|
||||
*/
|
||||
struct repeating_timer led_timer;
|
||||
bool led_callback(struct repeating_timer *t)
|
||||
{
|
||||
|
@ -44,7 +44,6 @@ bool led_callback(struct repeating_timer *t)
|
|||
|
||||
int main()
|
||||
{
|
||||
|
||||
/* Initialize LED pin output */
|
||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||
|
@ -55,27 +54,23 @@ int main()
|
|||
si_init(); // VFO control unit
|
||||
lcd_init(); // LCD output unit
|
||||
dsp_init(); // Signal processing unit
|
||||
mon_init();
|
||||
mon_init(); // Monitor shell on stdio
|
||||
|
||||
SI_SETFREQ(0, 2*7074000UL); // Set freq to 2*7074 kHz
|
||||
SI_SETPHASE(0,2); // Set phase to 180deg
|
||||
si_evaluate(); // Commit setting
|
||||
|
||||
lcd_test(); // Test LCD character set
|
||||
//lcd_test(); // Test LCD character set
|
||||
|
||||
lcd_ctrl(LCD_GOTO, 0, 0);
|
||||
sprintf(display1, " 7074.0 kHz");
|
||||
lcd_write(display1,11);
|
||||
lcd_ctrl(LCD_GOTO, 0, 0); // Go to (col, row)
|
||||
lcd_write(" 7074.0 kHz USB"); // Max 16 char per line!
|
||||
lcd_ctrl(LCD_GOTO, 1, 0);
|
||||
lcd_ctrl(LCD_CURSOR, 1, 0);
|
||||
lcd_ctrl(LCD_CURSOR, 1, 0); // Switch cursor on
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Check for monitor input */
|
||||
mon_read(100000L); // Wait max 100msec
|
||||
|
||||
/* Check whether VFO settings have changed */
|
||||
si_evaluate();
|
||||
mon_read(100000L); // Check monitor input, wait max 100msec
|
||||
si_evaluate(); // Check VFO settings
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Ładowanie…
Reference in New Issue