kopia lustrzana https://github.com/ArjanteMarvelde/uSDR-pico
V3.09
Solved I2C issue Added uSDR.h containing the system wide definitions.pull/13/head
rodzic
dff1711b96
commit
a712c1c29b
91
dsp.c
91
dsp.c
|
@ -24,11 +24,11 @@
|
|||
#include "hardware/timer.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "dsp.h"
|
||||
#include "hmi.h"
|
||||
#include "fix_fft.h"
|
||||
|
||||
#define GP_PTT 15 // PTT pin 20 (GPIO 15)
|
||||
|
||||
volatile bool tx_enabled; // TX branch active
|
||||
volatile uint32_t dsp_overrun; // Overrun counter
|
||||
|
@ -354,14 +354,14 @@ bool __not_in_flash_func(dsp_callback)(repeating_timer_t *t)
|
|||
if (tx_enabled)
|
||||
{
|
||||
A_buf[dsp_active][dsp_tick] = (int16_t)(tx_agc*adc_result[2]);
|
||||
pwm_set_gpio_level(21, I_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output I to DAC
|
||||
pwm_set_gpio_level(20, Q_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output Q to DAC
|
||||
pwm_set_gpio_level(DAC_I, I_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output I to DAC
|
||||
pwm_set_gpio_level(DAC_Q, Q_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output Q to DAC
|
||||
}
|
||||
else
|
||||
{
|
||||
I_buf[dsp_active][dsp_tick] = (int16_t)(rx_agc*adc_result[1]);
|
||||
Q_buf[dsp_active][dsp_tick] = (int16_t)(rx_agc*adc_result[0]);
|
||||
pwm_set_gpio_level(22, A_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output A to DAC
|
||||
pwm_set_gpio_level(DAC_A, A_buf[dsp_active][dsp_tick] + DAC_BIAS); // Output A to DAC
|
||||
}
|
||||
|
||||
// When sample buffer is full, move pointer to next and signal the DSP loop
|
||||
|
@ -378,12 +378,12 @@ bool __not_in_flash_func(dsp_callback)(repeating_timer_t *t)
|
|||
if (tx_enabled)
|
||||
{
|
||||
a_sample = tx_agc * adc_result[2]; // Store A for DSP use
|
||||
pwm_set_gpio_level(21, i_sample); // Output I to DAC
|
||||
pwm_set_gpio_level(20, q_sample); // Output Q to DAC
|
||||
pwm_set_gpio_level(DAC_I, i_sample); // Output I to DAC
|
||||
pwm_set_gpio_level(DAC_Q, q_sample); // Output Q to DAC
|
||||
}
|
||||
else
|
||||
{
|
||||
pwm_set_gpio_level(22, a_sample); // Output Q to DAC
|
||||
pwm_set_gpio_level(DAC_A, a_sample); // Output Q to DAC
|
||||
q_sample = rx_agc * adc_result[0]; // Store Q for DSP use
|
||||
i_sample = rx_agc * adc_result[1]; // Store I for DSP use
|
||||
}
|
||||
|
@ -413,15 +413,15 @@ void __not_in_flash_func(dsp_loop)()
|
|||
* default mode is free running,
|
||||
* A and B pins are output
|
||||
*/
|
||||
gpio_set_function(20, GPIO_FUNC_PWM); // GP20 is PWM for Q DAC (Slice 2, Channel A)
|
||||
gpio_set_function(21, GPIO_FUNC_PWM); // GP21 is PWM for I DAC (Slice 2, Channel B)
|
||||
dac_iq = pwm_gpio_to_slice_num(20); // Get PWM slice for GP20 (Same for GP21)
|
||||
gpio_set_function(DAC_Q, GPIO_FUNC_PWM); // GP20 is PWM for Q DAC (Slice 2, Channel A)
|
||||
gpio_set_function(DAC_I, GPIO_FUNC_PWM); // GP21 is PWM for I DAC (Slice 2, Channel B)
|
||||
dac_iq = pwm_gpio_to_slice_num(DAC_Q); // Get PWM slice for GP20 (Same for GP21)
|
||||
pwm_set_clkdiv_int_frac (dac_iq, 1, 0); // clock divide by 1: full system clock
|
||||
pwm_set_wrap(dac_iq, DAC_RANGE-1); // Set cycle length; nr of counts until wrap, i.e. 125/DAC_RANGE MHz
|
||||
pwm_set_enabled(dac_iq, true); // Set the PWM running
|
||||
|
||||
gpio_set_function(22, GPIO_FUNC_PWM); // GP22 is PWM for Audio DAC (Slice 3, Channel A)
|
||||
dac_audio = pwm_gpio_to_slice_num(22); // Find PWM slice for GP22
|
||||
gpio_set_function(DAC_A, GPIO_FUNC_PWM); // GP22 is PWM for Audio DAC (Slice 3, Channel A)
|
||||
dac_audio = pwm_gpio_to_slice_num(DAC_A); // Find PWM slice for GP22
|
||||
pwm_set_clkdiv_int_frac (dac_audio, 1, 0); // clock divide by 1: full system clock
|
||||
pwm_set_wrap(dac_audio, DAC_RANGE-1); // Set cycle length; nr of counts until wrap, i.e. 125/DAC_RANGE MHz
|
||||
pwm_set_enabled(dac_audio, true); // Set the PWM running
|
||||
|
@ -431,9 +431,9 @@ void __not_in_flash_func(dsp_loop)()
|
|||
* samples are stored in array through IRQ callback
|
||||
*/
|
||||
adc_init(); // Initialize ADC to known state
|
||||
adc_gpio_init(26); // GP26 is ADC 0 for Q channel
|
||||
adc_gpio_init(27); // GP27 is ADC 1 for I channel
|
||||
adc_gpio_init(28); // GP28 is ADC 2 for Audio channel
|
||||
adc_gpio_init(ADC_Q); // ADC GPIO for Q channel
|
||||
adc_gpio_init(ADC_I); // ADC GPIO for I channel
|
||||
adc_gpio_init(ADC_A); // ADC GPIO for Audio channel
|
||||
adc_set_round_robin(0x01+0x02+0x04); // Sequence ADC 0-1-2 (GP 26, 27, 28) free running
|
||||
adc_select_input(0); // Start with ADC0
|
||||
adc_fifo_setup(true,true,3,false,false); // IRQ result, DMA req, fifo thr=3: xfer per 3 x 16 bits
|
||||
|
@ -506,7 +506,7 @@ void __not_in_flash_func(dsp_loop)()
|
|||
rx(); // Do RX signal processing
|
||||
}
|
||||
|
||||
/////// This is a trap, ptt remains active after once asserted: to be checked!
|
||||
/** !!! This is a trap, ptt remains active after once asserted: TO BE CHECKED! **/
|
||||
tx_enabled = vox_active || ptt_active; // Check RX or TX
|
||||
|
||||
#if DSP_FFT == 1
|
||||
|
@ -527,63 +527,4 @@ void dsp_init()
|
|||
|
||||
|
||||
|
||||
/* DMA EXAMPLE, should convert to chained DMA to reload after 3 words
|
||||
// Init GPIO for analogue use: hi-Z, no pulls, disable digital input buffer.
|
||||
adc_gpio_init(26 + CAPTURE_CHANNEL);
|
||||
|
||||
adc_init();
|
||||
adc_select_input(CAPTURE_CHANNEL);
|
||||
adc_fifo_setup(
|
||||
true, // Write each completed conversion to the sample FIFO
|
||||
true, // Enable DMA data request (DREQ)
|
||||
1, // DREQ (and IRQ) asserted when at least 1 sample present
|
||||
false, // We won't see the ERR bit because of 8 bit reads; disable.
|
||||
true // Shift each sample to 8 bits when pushing to FIFO
|
||||
);
|
||||
|
||||
// Divisor of 0 -> full speed. Free-running capture with the divider is
|
||||
// equivalent to pressing the ADC_CS_START_ONCE button once per `div + 1`
|
||||
// cycles (div not necessarily an integer). Each conversion takes 96
|
||||
// cycles, so in general you want a divider of 0 (hold down the button
|
||||
// continuously) or > 95 (take samples less frequently than 96 cycle
|
||||
// intervals). This is all timed by the 48 MHz ADC clock.
|
||||
adc_set_clkdiv(0);
|
||||
|
||||
printf("Arming DMA\n");
|
||||
sleep_ms(1000);
|
||||
// Set up the DMA to start transferring data as soon as it appears in FIFO
|
||||
uint dma_chan = dma_claim_unused_channel(true);
|
||||
dma_channel_config cfg = dma_channel_get_default_config(dma_chan);
|
||||
|
||||
// Reading from constant address, writing to incrementing byte addresses
|
||||
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
|
||||
channel_config_set_read_increment(&cfg, false);
|
||||
channel_config_set_write_increment(&cfg, true);
|
||||
|
||||
// Pace transfers based on availability of ADC samples
|
||||
channel_config_set_dreq(&cfg, DREQ_ADC);
|
||||
|
||||
dma_channel_configure(dma_chan, &cfg,
|
||||
capture_buf, // dst
|
||||
&adc_hw->fifo, // src
|
||||
CAPTURE_DEPTH, // transfer count
|
||||
true // start immediately
|
||||
);
|
||||
|
||||
printf("Starting capture\n");
|
||||
adc_run(true);
|
||||
|
||||
// Once DMA finishes, stop any new conversions from starting, and clean up
|
||||
// the FIFO in case the ADC was still mid-conversion.
|
||||
dma_channel_wait_for_finish_blocking(dma_chan);
|
||||
printf("Capture finished\n");
|
||||
adc_run(false);
|
||||
adc_fifo_drain();
|
||||
|
||||
// Print samples to stdout so you can display them in pyplot, excel, matlab
|
||||
for (int i = 0; i < CAPTURE_DEPTH; ++i) {
|
||||
printf("%-3d, ", capture_buf[i]);
|
||||
if (i % 10 == 9)
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
|
4
dsp.h
4
dsp.h
|
@ -13,10 +13,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define DSP_FFT 1
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Callback timeout is TIM_US, value in usec
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uSDR.h"
|
||||
|
||||
/*
|
||||
* FFT buffer allocation
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "uSDR.h"
|
||||
|
||||
/*
|
||||
* Low pass FIR filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/)
|
||||
|
|
13
hmi.c
13
hmi.c
|
@ -29,10 +29,11 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "lcd.h"
|
||||
#include "hmi.h"
|
||||
#include "dsp.h"
|
||||
|
@ -40,15 +41,8 @@
|
|||
#include "relay.h"
|
||||
|
||||
/*
|
||||
* GPIO assignments
|
||||
* GPIO masks
|
||||
*/
|
||||
#define GP_ENC_A 2
|
||||
#define GP_ENC_B 3
|
||||
#define GP_AUX_0 6 // Enter, Confirm
|
||||
#define GP_AUX_1 7 // Escape, Cancel
|
||||
#define GP_AUX_2 8 // Left move
|
||||
#define GP_AUX_3 9 // Right move
|
||||
#define GP_PTT 15
|
||||
#define GP_MASK_IN ((1<<GP_ENC_A)|(1<<GP_ENC_B)|(1<<GP_AUX_0)|(1<<GP_AUX_1)|(1<<GP_AUX_2)|(1<<GP_AUX_3)|(1<<GP_PTT))
|
||||
#define GP_MASK_PTT (1<<GP_PTT)
|
||||
|
||||
|
@ -340,7 +334,6 @@ void hmi_evaluate(void)
|
|||
dsp_setvox(hmi_sub[HMI_S_VOX]);
|
||||
dsp_setagc(hmi_sub[HMI_S_AGC]);
|
||||
relay_setband(hmi_bpf[hmi_sub[HMI_S_BPF]]);
|
||||
sleep_ms(1); // I2C doesn't work without...
|
||||
relay_setattn(hmi_pre[hmi_sub[HMI_S_PRE]]);
|
||||
hmi_update = false;
|
||||
}
|
||||
|
|
2
hmi.h
2
hmi.h
|
@ -9,8 +9,6 @@
|
|||
* See hmi.c for more information
|
||||
*/
|
||||
|
||||
#define CARRIER_OFFSET 3500
|
||||
|
||||
extern bool ptt_active;
|
||||
|
||||
void hmi_init(void);
|
||||
|
|
49
lcd.c
49
lcd.c
|
@ -4,11 +4,10 @@
|
|||
* Created: Mar 2021
|
||||
* Author: Arjan te Marvelde
|
||||
*
|
||||
* --> Set I2C address below!
|
||||
* --> Select LCD_TYPE below!
|
||||
*
|
||||
* Driver for 16x2 HD44780 based LCD displays.
|
||||
* There exist many different types, so you may need to adapt some of the code.
|
||||
* => LCD Address and Type are chosen in uSDR.h!
|
||||
*
|
||||
* This file contains the driver for 16x2 HD44780 based LCD displays.
|
||||
* Many different types exist, so you may need to adapt some of the code.
|
||||
* Most notably the startup sequence and the way bytes are sent over the I2C interface.
|
||||
* But also the register mappings as described below.
|
||||
*
|
||||
|
@ -46,19 +45,10 @@
|
|||
#include "hardware/i2c.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "lcd.h"
|
||||
|
||||
/** User selectable definitions **/
|
||||
// Set I2C address for your device
|
||||
#define I2C_LCD 0x3E // Grove: 0x3E, 8574 backpack: 0x20..0x27
|
||||
|
||||
// Select LCD type to match your device,
|
||||
// or define a new one when code changes are needed.
|
||||
#define LCD_1804 0 // Seeed / Grove
|
||||
#define LCD_8574_ADA 1 // Adafruit I2C backpack
|
||||
#define LCD_8574_GEN 2 // Generic I2C backpack
|
||||
#define LCD_TYPE LCD_1804
|
||||
|
||||
|
||||
/** Generic HD44780 interface **/
|
||||
// commands
|
||||
|
@ -100,19 +90,20 @@
|
|||
#define LCD_5x8DOTS 0x00
|
||||
|
||||
/** I2C interface specific mappings **/
|
||||
// 1804-based specific bitmasks
|
||||
// 1804-based specific bitmasks (Seeed/Grove)
|
||||
#define LCD_COMMAND 0x80
|
||||
#define LCD_DATA 0x40
|
||||
#define LCD_INIT_1804 (LCD_FUNCTIONSET | LCD_8BITMODE | LCD_2LINE | LCD_5x8DOTS)
|
||||
|
||||
|
||||
// 8574-based specific bitmasks
|
||||
// 8574-based specific bitmasks (Adafruit)
|
||||
#define LCD_COMMAND_ADA 0x00
|
||||
#define LCD_DATA_ADA 0x02
|
||||
#define LCD_BACKLIGHT_ADA 0x80
|
||||
#define LCD_ENABLE_ADA 0x04
|
||||
#define LCD_INIT_ADA (LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS)
|
||||
|
||||
// 8574-based specific bitmasks (Generic)
|
||||
#define LCD_COMMAND_GEN 0x00
|
||||
#define LCD_DATA_GEN 0x01
|
||||
#define LCD_ENABLE_GEN 0x04
|
||||
|
@ -131,9 +122,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/** Other definitions **/
|
||||
#define LCD_DELAY 100 // Delay for regular write
|
||||
|
||||
|
||||
/*
|
||||
* User defined (CGRAM) characters
|
||||
|
@ -164,8 +152,7 @@ void lcd_sendbyte(uint8_t command, uint8_t data)
|
|||
// Write command/data flag and data byte
|
||||
txdata[0] = (command?LCD_COMMAND:LCD_DATA);
|
||||
txdata[1] = data;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, txdata, 2, false);
|
||||
sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, txdata, 2, false);
|
||||
#endif
|
||||
|
||||
#if LCD_TYPE == LCD_8574_ADA
|
||||
|
@ -175,15 +162,15 @@ void lcd_sendbyte(uint8_t command, uint8_t data)
|
|||
|
||||
// Write high nibble
|
||||
high |= LCD_ENABLE_ADA;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &high, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &high, 1, false);
|
||||
high &= ~LCD_ENABLE_ADA;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &high, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &high, 1, false);
|
||||
|
||||
// Write low nibble
|
||||
low |= LCD_ENABLE_ADA;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &low, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &low, 1, false);
|
||||
low &= ~LCD_ENABLE_ADA;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &low, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &low, 1, false);
|
||||
#endif
|
||||
|
||||
#if LCD_TYPE == LCD_8574_GEN
|
||||
|
@ -193,15 +180,15 @@ void lcd_sendbyte(uint8_t command, uint8_t data)
|
|||
|
||||
// Write high nibble
|
||||
high |= LCD_ENABLE_GEN;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &high, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &high, 1, false);
|
||||
high &= ~LCD_ENABLE_GEN;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &high, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &high, 1, false);
|
||||
|
||||
// Write low nibble
|
||||
low |= LCD_ENABLE_GEN;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &low, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &low, 1, false);
|
||||
low &= ~LCD_ENABLE_GEN;
|
||||
i2c_write_blocking(i2c1, I2C_LCD, &low, 1, false); sleep_us(LCD_DELAY);
|
||||
i2c_put_data(i2c1, I2C_LCD, &low, 1, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <string.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "lcd.h"
|
||||
#include "si5351.h"
|
||||
#include "dsp.h"
|
||||
|
@ -21,12 +22,15 @@
|
|||
#include "monitor.h"
|
||||
|
||||
|
||||
// Some special character ASCII codes
|
||||
#define CR 13
|
||||
#define LF 10
|
||||
#define SP 32
|
||||
|
||||
#define CMD_LEN 80
|
||||
#define CMD_ARGS 16
|
||||
|
||||
|
||||
char mon_cmd[CMD_LEN+1]; // Command string buffer
|
||||
char *argv[CMD_ARGS]; // Argument pointers
|
||||
int nargs; // Nr of arguments
|
||||
|
|
17
relay.c
17
relay.c
|
@ -25,12 +25,11 @@
|
|||
#include "pico/stdlib.h"
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "relay.h"
|
||||
|
||||
|
||||
/* I2C address and pins */
|
||||
#define I2C_RX 0x21
|
||||
#define I2C_BPF 0x20
|
||||
|
||||
|
||||
|
||||
void relay_setband(int val)
|
||||
|
@ -39,8 +38,8 @@ void relay_setband(int val)
|
|||
int ret;
|
||||
|
||||
data[0] = ((uint8_t)val)&0x1f;
|
||||
if (i2c_write_blocking(i2c1, I2C_BPF, data, 1, false) < 0)
|
||||
i2c_write_blocking(i2c1, I2C_BPF, data, 1, false);
|
||||
if (i2c_put_data(i2c1, I2C_BPF, data, 1, false) < 0)
|
||||
i2c_put_data(i2c1, I2C_BPF, data, 1, false);
|
||||
sleep_ms(1);
|
||||
}
|
||||
|
||||
|
@ -49,7 +48,7 @@ int relay_getband(void)
|
|||
uint8_t data[2];
|
||||
int ret;
|
||||
|
||||
ret = i2c_read_blocking(i2c1, I2C_BPF, data, 1, false);
|
||||
ret = i2c_get_data(i2c1, I2C_BPF, data, 1, false);
|
||||
if (ret>=0)
|
||||
ret=data[0];
|
||||
return(ret);
|
||||
|
@ -60,8 +59,8 @@ void relay_setattn(int val)
|
|||
uint8_t data[2];
|
||||
|
||||
data[0] = ((uint8_t)val)&0x07;
|
||||
if (i2c_write_blocking(i2c1, I2C_RX, data, 1, false) < 0)
|
||||
i2c_write_blocking(i2c1, I2C_RX, data, 1, false);
|
||||
if (i2c_put_data(i2c1, I2C_RX, data, 1, false) < 0)
|
||||
i2c_put_data(i2c1, I2C_RX, data, 1, false);
|
||||
sleep_ms(1);
|
||||
}
|
||||
|
||||
|
@ -70,7 +69,7 @@ int relay_getattn(void)
|
|||
uint8_t data[2];
|
||||
int ret;
|
||||
|
||||
ret = i2c_read_blocking(i2c1, I2C_RX, data, 1, false);
|
||||
ret = i2c_get_data(i2c1, I2C_RX, data, 1, false);
|
||||
if (ret>=0)
|
||||
ret=data[0];
|
||||
return(ret);
|
||||
|
|
38
si5351.c
38
si5351.c
|
@ -149,9 +149,10 @@ Control Si5351 (see AN619):
|
|||
#include "hardware/i2c.h"
|
||||
#include "hardware/timer.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "si5351.h"
|
||||
|
||||
#define I2C_VFO 0x60 // I2C address
|
||||
|
||||
// SI5351 register address definitions
|
||||
#define SI_CLK_OE 3
|
||||
|
@ -234,14 +235,14 @@ void si_enable(int i, bool en)
|
|||
if ((i<0)||(i>1)) return; // Check VFO range
|
||||
|
||||
data[0] = SI_CLK_OE; // Read OE register
|
||||
i2c_write_blocking(i2c0, I2C_VFO, &data[0], 1, true);
|
||||
i2c_put_data(i2c0, I2C_VFO, &data[0], 1, true);
|
||||
i2c_read_blocking(i2c0, I2C_VFO, &data[1], 1, false);
|
||||
|
||||
if (i==0)
|
||||
data[1] = en ? data[1]&~SI_VFO0_DISABLE : data[1]|SI_VFO0_DISABLE; // clk0 and clk1
|
||||
else
|
||||
data[1] = en ? data[1]&~SI_VFO1_DISABLE : data[1]|SI_VFO1_DISABLE; // clk2
|
||||
i2c_write_blocking(i2c0, I2C_VFO, &data[0], 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, &data[0], 2, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -251,9 +252,9 @@ int si_getreg(uint8_t *data, uint8_t reg, uint8_t len)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_write_blocking(i2c0, I2C_VFO, ®, 1, true);
|
||||
ret = i2c_put_data(i2c0, I2C_VFO, ®, 1, true);
|
||||
if (ret<0) printf ("I2C write error\n");
|
||||
ret = i2c_read_blocking(i2c0, I2C_VFO, data, len, false);
|
||||
ret = i2c_get_data(i2c0, I2C_VFO, data, len, false);
|
||||
if (ret<0) printf ("I2C read error\n");
|
||||
return(len);
|
||||
}
|
||||
|
@ -299,7 +300,7 @@ void si_setmsn(int i)
|
|||
data[6] = ((SI_PLL_C & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16);
|
||||
data[7] = (P2 & 0x0000FF00) >> 8;
|
||||
data[8] = (P2 & 0x000000FF);
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 9, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 9, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -338,59 +339,56 @@ void si_setmsi(int i)
|
|||
data[6] = 0x00;
|
||||
data[7] = 0x00;
|
||||
data[8] = 0x00;
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 9, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 9, false);
|
||||
|
||||
// If vfo[0] also set clk 1 and phase offset, (integer mode(?) and high drive current for low phase noise).
|
||||
if (i==0)
|
||||
{
|
||||
data[0] = SI_SYNTH_MS1; // Same data in synthesizer
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 9, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 9, false);
|
||||
|
||||
if ((vfo[0].phase==PH090)||(vfo[0].phase==PH270)) // Phase is 90 or 270 deg?
|
||||
{
|
||||
data[0] = SI_CLK1_PHOFF;
|
||||
data[1] = vfo[0].msi; // offset == MSi for 90deg
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
}
|
||||
else // Phase is 0 or 180 deg
|
||||
{
|
||||
data[0] = SI_CLK1_PHOFF;
|
||||
data[1] = 0; // offset == 0 for 0deg
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
}
|
||||
sleep_us(500);
|
||||
if ((vfo[0].phase==PH180)||(vfo[0].phase==PH270)) // Phase is 180 or 270 deg?
|
||||
{
|
||||
data[0] = SI_CLK0_CTL; // set the invert flag
|
||||
data[1] = SI_VFO0CTL; // CLK0: nonINV
|
||||
data[2] = SI_VFO0CTL | SI_CLK_INV; // CLK1: INV
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 3, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 3, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = SI_CLK0_CTL; // set the invert flag
|
||||
data[1] = SI_VFO0CTL; // CLK0: nonINV
|
||||
data[2] = SI_VFO0CTL; // CLK1: nonINV
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 3, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 3, false);
|
||||
}
|
||||
|
||||
// Reset PLL A (use with care, this causes a click)
|
||||
sleep_us(500);
|
||||
data[0] = SI_PLL_RESET;
|
||||
data[1] = SI_PLLA_RST|SI_PLLB_RST;
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = SI_CLK2_CTL; // set the invert flag
|
||||
data[1] = SI_VFO1CTL; // CLK2: nonINV
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
|
||||
// Reset PLL B (use with care, this causes a click)
|
||||
sleep_us(500);
|
||||
data[0] = SI_PLL_RESET;
|
||||
data[1] = SI_PLLA_RST|SI_PLLB_RST;
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -457,14 +455,14 @@ void si_init(void)
|
|||
// Disable spread spectrum (startup state is undefined)
|
||||
data[0] = SI_SS_EN;
|
||||
data[1] = 0x00;
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 2, false);
|
||||
|
||||
// First time init of clock control registers
|
||||
data[0] = SI_CLK0_CTL;
|
||||
data[1] = SI_VFO0CTL;
|
||||
data[2] = SI_VFO0CTL;
|
||||
data[3] = SI_VFO1CTL;
|
||||
i2c_write_blocking(i2c0, I2C_VFO, data, 4, false);
|
||||
i2c_put_data(i2c0, I2C_VFO, data, 4, false);
|
||||
|
||||
// Initialize VFO values
|
||||
vfo[0].freq = 7074000;
|
||||
|
|
29
uSDR.c
29
uSDR.c
|
@ -22,6 +22,7 @@
|
|||
#include "hardware/timer.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "uSDR.h"
|
||||
#include "hmi.h"
|
||||
#include "lcd.h"
|
||||
#include "dsp.h"
|
||||
|
@ -30,15 +31,30 @@
|
|||
#include "relay.h"
|
||||
|
||||
|
||||
#define I2C0_SDA 16
|
||||
#define I2C0_SCL 17
|
||||
#define I2C1_SDA 18
|
||||
#define I2C1_SCL 19
|
||||
|
||||
/*
|
||||
* Wrappers around i2c_write_blocking() and i2c_read_blocking()
|
||||
* The SDK functions return too soon, potentially causing overlapping calls
|
||||
*/
|
||||
|
||||
int i2c_put_data(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop)
|
||||
{
|
||||
int r = i2c_write_blocking(i2c, addr, src, len, nostop);
|
||||
sleep_us(I2C_LINGER_US);
|
||||
return(r);
|
||||
}
|
||||
|
||||
int i2c_get_data(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop)
|
||||
{
|
||||
int r = i2c_read_blocking(i2c, addr, dst, len, nostop);
|
||||
sleep_us(I2C_LINGER_US);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LED TIMER definition and callback routine
|
||||
*/
|
||||
#define LED_MS 1000
|
||||
struct repeating_timer led_timer;
|
||||
bool led_callback(struct repeating_timer *t)
|
||||
{
|
||||
|
@ -49,11 +65,11 @@ bool led_callback(struct repeating_timer *t)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scheduler callback function.
|
||||
* This executes every LOOP_MS.
|
||||
*/
|
||||
#define LOOP_MS 100
|
||||
semaphore_t loop_sem;
|
||||
struct repeating_timer loop_timer;
|
||||
bool loop_callback(struct repeating_timer *t)
|
||||
|
@ -66,6 +82,7 @@ bool loop_callback(struct repeating_timer *t)
|
|||
int main()
|
||||
{
|
||||
/*
|
||||
* Main loop rnning on Core 0
|
||||
* Optional: increase core voltage (normally 1.1V)
|
||||
* Optional: overclock the CPU to 250MHz (normally 125MHz)
|
||||
* Note that clk_peri (e.g. I2C) is derived from the SYS PLL
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef __USDR_H__
|
||||
#define __USDR_H__
|
||||
/*
|
||||
* uSDR.h
|
||||
*
|
||||
* Created: Aug 2022
|
||||
* Author: Arjan te Marvelde
|
||||
*
|
||||
* This file contains the system-wide definitions and platform services.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
|
||||
/* Set this to 1 when FFT engine must be used */
|
||||
|
||||
#define DSP_FFT 1
|
||||
|
||||
|
||||
/* GPIO (pin) assignments */
|
||||
|
||||
#define GP_ENC_A 2 // Pin 4: Encoder channel A
|
||||
#define GP_ENC_B 3 // Pin 5: Encoder channel B
|
||||
#define GP_AUX_0 6 // Pin 9: Enter, Confirm
|
||||
#define GP_AUX_1 7 // Pin 10: Escape, Cancel
|
||||
#define GP_AUX_2 8 // Pin 11: Left move
|
||||
#define GP_AUX_3 9 // Pin 12: Right move
|
||||
#define GP_PTT 15 // Pin 20: PTT line (low is active)
|
||||
#define I2C0_SDA 16 // Pin 21: I2C channel 0 - data
|
||||
#define I2C0_SCL 17 // Pin 22: I2C channel 0 - clock
|
||||
#define I2C1_SDA 18 // Pin 24: I2C channel 1 - data
|
||||
#define I2C1_SCL 19 // Pin 25: I2C channel 1 - clock
|
||||
#define DAC_Q 20 // Pin 26: PWM DAC Q channel
|
||||
#define DAC_I 21 // Pin 27: PWM DAC I channel
|
||||
#define DAC_A 22 // Pin 29: PWM DAC Audio channel
|
||||
#define ADC_Q 26 // Pin 31: ADC 0
|
||||
#define ADC_I 27 // Pin 32: ADC 1
|
||||
#define ADC_A 28 // Pin 34: ADC 2
|
||||
|
||||
|
||||
|
||||
/* Timer values */
|
||||
|
||||
#define LED_MS 1000 // LED flashing, half cycle duration
|
||||
#define LOOP_MS 100 // Core 0 main loop timer (see also uSDR.c)
|
||||
|
||||
|
||||
/* I2C addresses */
|
||||
|
||||
#define I2C_RX 0x21 // Expander on Rx board
|
||||
#define I2C_BPF 0x20 // Expander on Filter board
|
||||
#define I2C_VFO 0x60 // Si5351A
|
||||
#define I2C_LCD 0x3E // Grove: 0x3E, 8574 backpack range: 0x20..0x27
|
||||
|
||||
|
||||
/* I2C wrapper functions (blocking write and read) */
|
||||
|
||||
#define I2C_LINGER_US 200 // Linger time added after i2c SDK functions
|
||||
|
||||
int i2c_put_data(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop);
|
||||
int i2c_get_data(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop);
|
||||
|
||||
|
||||
/* LCD type selection (see also lcd.c) */
|
||||
|
||||
#define LCD_1804 0 // Type 0: Seeed / Grove
|
||||
#define LCD_8574_ADA 1 // Type 1: Adafruit I2C backpack
|
||||
#define LCD_8574_GEN 2 // Type 2: Generic I2C backpack
|
||||
#define LCD_TYPE LCD_1804 // Active selection
|
||||
|
||||
|
||||
|
||||
#endif
|
Ładowanie…
Reference in New Issue