diff --git a/dsp.c b/dsp.c index ce0abb1..c9d4cf7 100644 --- a/dsp.c +++ b/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"); - } -*/ diff --git a/dsp.h b/dsp.h index abaf9c2..2d83d4e 100644 --- a/dsp.h +++ b/dsp.h @@ -13,10 +13,6 @@ * */ -#define DSP_FFT 1 - - - /* * Callback timeout is TIM_US, value in usec diff --git a/dsp_fft.c b/dsp_fft.c index 3bdd1f8..adaeb3a 100644 --- a/dsp_fft.c +++ b/dsp_fft.c @@ -53,7 +53,7 @@ * */ - +#include "uSDR.h" /* * FFT buffer allocation diff --git a/dsp_tim.c b/dsp_tim.c index 3332bb1..b401d93 100644 --- a/dsp_tim.c +++ b/dsp_tim.c @@ -28,6 +28,7 @@ * */ +#include "uSDR.h" /* * Low pass FIR filters Fc=3, 7 and 15 kHz (see http://t-filter.engineerjs.com/) diff --git a/hmi.c b/hmi.c index c4c32da..571bc7b 100644 --- a/hmi.c +++ b/hmi.c @@ -29,10 +29,11 @@ #include #include #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< 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 } diff --git a/monitor.c b/monitor.c index f47445d..88e7dd3 100644 --- a/monitor.c +++ b/monitor.c @@ -14,6 +14,7 @@ #include #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 diff --git a/relay.c b/relay.c index 4703780..c38b2fe 100644 --- a/relay.c +++ b/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); diff --git a/si5351.c b/si5351.c index 40b39e3..325fa5b 100644 --- a/si5351.c +++ b/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; diff --git a/uSDR.c b/uSDR.c index ebe0bbf..d85135b 100644 --- a/uSDR.c +++ b/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 diff --git a/uSDR.h b/uSDR.h new file mode 100644 index 0000000..c2c4188 --- /dev/null +++ b/uSDR.h @@ -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