updates lcd, monitor

pull/13/head
ArjanteMarvelde 2021-04-08 22:32:27 +02:00
rodzic 9984e43c16
commit fbe0e50663
5 zmienionych plików z 95 dodań i 77 usunięć

79
dsp.c
Wyświetl plik

@ -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
Wyświetl plik

@ -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
Wyświetl plik

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

Wyświetl plik

@ -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
Wyświetl plik

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