Experiment with a superhet approach
This commit is contained in:
		
							parent
							
								
									46c061f177
								
							
						
					
					
						commit
						38b7ec34f6
					
				
					 4 changed files with 256 additions and 297 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -1,2 +1,3 @@ | ||||||
| /build/ | /build/ | ||||||
| /grc/*.py | /grc/*.py | ||||||
|  | /src/.clangd | ||||||
|  |  | ||||||
|  | @ -374,7 +374,7 @@ blocks: | ||||||
|     freq7: 100e6 |     freq7: 100e6 | ||||||
|     freq8: 100e6 |     freq8: 100e6 | ||||||
|     freq9: 100e6 |     freq9: 100e6 | ||||||
|     gain0: '30' |     gain0: '0' | ||||||
|     gain1: '10' |     gain1: '10' | ||||||
|     gain10: '10' |     gain10: '10' | ||||||
|     gain11: '10' |     gain11: '10' | ||||||
|  |  | ||||||
							
								
								
									
										500
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										500
									
								
								src/main.c
									
									
									
									
									
								
							|  | @ -23,20 +23,25 @@ | ||||||
| 
 | 
 | ||||||
| #define VREG_VOLTAGE VREG_VOLTAGE_1_20 | #define VREG_VOLTAGE VREG_VOLTAGE_1_20 | ||||||
| #define CLK_SYS_HZ (300 * MHZ) | #define CLK_SYS_HZ (300 * MHZ) | ||||||
|  | 
 | ||||||
|  | #define LO_PIN 9 | ||||||
|  | #define RX_PIN 10 | ||||||
|  | #define FB_PIN 11 | ||||||
| #define PSU_PIN 23 | #define PSU_PIN 23 | ||||||
| 
 | 
 | ||||||
|  | #define PIO pio1 | ||||||
|  | #define LO_SM 0 | ||||||
|  | #define FB_SM 1 | ||||||
|  | #define RX_SM 2 | ||||||
|  | #define AD_SM 3 | ||||||
|  | 
 | ||||||
| #define IQ_SAMPLES 32 | #define IQ_SAMPLES 32 | ||||||
| #define IQ_BLOCK_LEN (2 * IQ_SAMPLES) | #define IQ_BLOCK_LEN (2 * IQ_SAMPLES) | ||||||
| #define IQ_QUEUE_LEN 4 | #define IQ_QUEUE_LEN 4 | ||||||
| 
 | 
 | ||||||
| #define XOR_ADDR 0x1000 |  | ||||||
| #define LO_COS_ACCUMULATOR (&pio1->sm[2].pinctrl) |  | ||||||
| #define LO_SIN_ACCUMULATOR (&pio1->sm[3].pinctrl) |  | ||||||
| 
 |  | ||||||
| #define LO_BITS_DEPTH 15 | #define LO_BITS_DEPTH 15 | ||||||
| #define LO_WORDS (1 << (LO_BITS_DEPTH - 2)) | #define LO_WORDS (1 << (LO_BITS_DEPTH - 2)) | ||||||
| static uint32_t lo_cos[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); | static uint32_t lo_cos[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); | ||||||
| static uint32_t lo_sin[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); |  | ||||||
| 
 | 
 | ||||||
| #define DECIMATE 4 | #define DECIMATE 4 | ||||||
| #define RX_STRIDE (2 * IQ_SAMPLES * DECIMATE) | #define RX_STRIDE (2 * IQ_SAMPLES * DECIMATE) | ||||||
|  | @ -46,36 +51,32 @@ static uint32_t lo_sin[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH)) | ||||||
| static_assert(RX_STRIDE * 4 < RX_WORDS, "RX_STRIDE * 4 < RX_WORDS"); | static_assert(RX_STRIDE * 4 < RX_WORDS, "RX_STRIDE * 4 < RX_WORDS"); | ||||||
| 
 | 
 | ||||||
| static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(1 << RX_BITS_DEPTH))); | static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(1 << RX_BITS_DEPTH))); | ||||||
| static uint32_t rx_sin[RX_WORDS] __attribute__((__aligned__(1 << RX_BITS_DEPTH))); |  | ||||||
| 
 | 
 | ||||||
| #define INIT_SAMPLE_RATE 100000 | #define INIT_SAMPLE_RATE 100000 | ||||||
| #define INIT_FREQ 94600000 | #define INIT_FREQ 94600000 | ||||||
|  | #define INIT_GAIN 127 | ||||||
| 
 | 
 | ||||||
| #define NUM_GAINS 29 | #define NUM_GAINS 29 | ||||||
| static int gains[NUM_GAINS] = { 0,   9,	  14,  27,  37,	 77,  87,  125, 144, 157, | static int gains[NUM_GAINS] = { 0,   9,	  14,  27,  37,	 77,  87,  125, 144, 157, | ||||||
| 				166, 197, 207, 229, 254, 280, 297, 328, 338, 364, | 				166, 197, 207, 229, 254, 280, 297, 328, 338, 364, | ||||||
| 				372, 386, 402, 421, 434, 439, 445, 480, 496 }; | 				372, 386, 402, 421, 434, 439, 445, 480, 496 }; | ||||||
| static int sample_rate = INIT_SAMPLE_RATE; | static int sample_rate = INIT_SAMPLE_RATE; | ||||||
|  | static int gain = INIT_GAIN; | ||||||
| 
 | 
 | ||||||
| #define SIN_PHASE (0u) | #define SIN_PHASE (0u) | ||||||
| #define COS_PHASE (3u << 30) | #define COS_PHASE (3u << 30) | ||||||
| 
 | 
 | ||||||
| /* rx -> cp -> cos -> sin -> pio_cos -> pio_sin -> rx ... */ | static int dma_ch_rx1 = -1; | ||||||
| static int dma_ch_rx = -1; | static int dma_ch_rx2 = -1; | ||||||
| static int dma_ch_cp = -1; | 
 | ||||||
| static int dma_ch_cos = -1; | static int dma_ch_mix1 = -1; | ||||||
| static int dma_ch_sin = -1; | static int dma_ch_mix2 = -1; | ||||||
| static int dma_ch_pio_cos = -1; |  | ||||||
| static int dma_ch_pio_sin = -1; |  | ||||||
| 
 | 
 | ||||||
| static int dma_ch_samp_trig = -1; |  | ||||||
| static int dma_ch_samp_cos = -1; | static int dma_ch_samp_cos = -1; | ||||||
| static int dma_ch_samp_sin = -1; |  | ||||||
| 
 | 
 | ||||||
| static int dma_t_samp = -1; | static int dma_t_samp = -1; | ||||||
| 
 | 
 | ||||||
| static int dma_ch_in_cos = -1; | static int dma_ch_in_cos = -1; | ||||||
| static int dma_ch_in_sin = -1; |  | ||||||
| 
 | 
 | ||||||
| static queue_t iq_queue; | static queue_t iq_queue; | ||||||
| static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN]; | static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN]; | ||||||
|  | @ -89,108 +90,119 @@ inline static uint32_t rnd_next() | ||||||
| 	return rnd; | 	return rnd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void bias_set_gain(int gain) | static void init_lo() | ||||||
| { | { | ||||||
| 	if (gain > 9) | 	gpio_disable_pulls(LO_PIN); | ||||||
| 		gain = 9; | 	pio_gpio_init(PIO, LO_PIN); | ||||||
| 	else if (gain < 0) |  | ||||||
| 		gain = 0; |  | ||||||
| 
 | 
 | ||||||
| 	pio1->sm[0].execctrl = (pio1->sm[0].execctrl & ~PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS) | | 	gpio_set_drive_strength(LO_PIN, GPIO_DRIVE_STRENGTH_12MA); | ||||||
| 			       ((19 - gain) << PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB); | 	gpio_set_slew_rate(LO_PIN, GPIO_SLEW_RATE_FAST); | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void bias_init(int in_pin, int out_pin) |  | ||||||
| { |  | ||||||
| 	gpio_disable_pulls(in_pin); |  | ||||||
| 	gpio_disable_pulls(out_pin); |  | ||||||
| 
 |  | ||||||
| 	pio_gpio_init(pio1, out_pin); |  | ||||||
| 
 |  | ||||||
| 	gpio_set_input_hysteresis_enabled(in_pin, false); |  | ||||||
| 	gpio_set_drive_strength(out_pin, GPIO_DRIVE_STRENGTH_2MA); |  | ||||||
| 	gpio_set_slew_rate(out_pin, GPIO_SLEW_RATE_SLOW); |  | ||||||
| 
 | 
 | ||||||
| 	const uint16_t insn[] = { | 	const uint16_t insn[] = { | ||||||
| 		pio_encode_in(pio_pins, 1), | 		pio_encode_out(pio_pindirs, 1), | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 		pio_encode_in(pio_pins, 1), |  | ||||||
| 
 |  | ||||||
| 		pio_encode_mov(pio_x, pio_isr), |  | ||||||
| 		pio_encode_mov(pio_isr, pio_null), |  | ||||||
| 
 |  | ||||||
| 		pio_encode_jmp_x_dec(11), |  | ||||||
| 		pio_encode_mov_not(pio_pins, pio_pins) | pio_encode_sideset(1, 1), |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_program_t prog = { | 	pio_program_t prog = { | ||||||
| 		.instructions = insn, | 		.instructions = insn, | ||||||
| 		.length = sizeof(insn) / sizeof(*insn), | 		.length = sizeof(insn) / sizeof(*insn), | ||||||
| 		.origin = 10, | 		.origin = -1, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_sm_set_enabled(pio1, 0, false); | 	pio_sm_restart(PIO, LO_SM); | ||||||
| 	pio_sm_restart(pio1, 0); | 	pio_sm_clear_fifos(PIO, LO_SM); | ||||||
| 	pio_sm_clear_fifos(pio1, 0); |  | ||||||
| 
 | 
 | ||||||
| 	if (pio_can_add_program(pio1, &prog)) | 	if (pio_can_add_program(PIO, &prog)) | ||||||
| 		pio_add_program(pio1, &prog); | 		prog.origin = pio_add_program(PIO, &prog); | ||||||
| 
 | 
 | ||||||
| 	pio_sm_config pc = pio_get_default_sm_config(); | 	pio_sm_config pc = pio_get_default_sm_config(); | ||||||
| 	sm_config_set_in_shift(&pc, false, false, 32); | 	sm_config_set_out_pins(&pc, LO_PIN, 1); | ||||||
| 	sm_config_set_sideset(&pc, 1, false, true); | 	sm_config_set_set_pins(&pc, LO_PIN, 1); | ||||||
| 	sm_config_set_sideset_pins(&pc, out_pin); |  | ||||||
| 	sm_config_set_in_pins(&pc, in_pin); |  | ||||||
| 	sm_config_set_out_pins(&pc, out_pin, 1); |  | ||||||
| 	sm_config_set_set_pins(&pc, out_pin, 1); |  | ||||||
| 
 |  | ||||||
| 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | ||||||
| 
 |  | ||||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||||
| 	pio_sm_init(pio1, 0, prog.origin, &pc); | 	sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_TX); | ||||||
|  | 	sm_config_set_out_shift(&pc, false, true, 32); | ||||||
|  | 	pio_sm_init(PIO, LO_SM, prog.origin, &pc); | ||||||
| 
 | 
 | ||||||
| 	pio_sm_set_consecutive_pindirs(pio1, 0, out_pin, 1, GPIO_OUT); | 	pio_sm_set_consecutive_pindirs(PIO, LO_SM, LO_PIN, 1, GPIO_OUT); | ||||||
| 
 | 	pio_sm_exec_wait_blocking(PIO, LO_SM, pio_encode_set(pio_pins, 0)); | ||||||
| 	pio_sm_set_enabled(pio1, 0, true); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void watch_init(int in_pin) | static void init_fb() | ||||||
| { | { | ||||||
|  | 	gpio_disable_pulls(FB_PIN); | ||||||
|  | 	pio_gpio_init(PIO, FB_PIN); | ||||||
|  | 
 | ||||||
|  | 	// NOTE: Not sure if this is ideal.
 | ||||||
|  | 	hw_set_bits(&PIO->input_sync_bypass, 1u << RX_PIN); | ||||||
|  | 
 | ||||||
|  | 	gpio_set_input_hysteresis_enabled(RX_PIN, false); | ||||||
|  | 	gpio_set_drive_strength(FB_PIN, GPIO_DRIVE_STRENGTH_2MA); | ||||||
|  | 	gpio_set_slew_rate(FB_PIN, GPIO_SLEW_RATE_SLOW); | ||||||
|  | 
 | ||||||
|  | 	const uint16_t insn[] = { | ||||||
|  | 		pio_encode_mov_not(pio_pins, pio_pins) | pio_encode_sideset(1, 1) | | ||||||
|  | 			pio_encode_delay(0), | ||||||
|  | 		pio_encode_nop() | pio_encode_sideset(1, 0), | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	pio_program_t prog = { | ||||||
|  | 		.instructions = insn, | ||||||
|  | 		.length = sizeof(insn) / sizeof(*insn), | ||||||
|  | 		.origin = -1, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	pio_sm_restart(PIO, FB_SM); | ||||||
|  | 	pio_sm_clear_fifos(PIO, FB_SM); | ||||||
|  | 
 | ||||||
|  | 	if (pio_can_add_program(PIO, &prog)) | ||||||
|  | 		prog.origin = pio_add_program(PIO, &prog); | ||||||
|  | 
 | ||||||
|  | 	pio_sm_config pc = pio_get_default_sm_config(); | ||||||
|  | 	sm_config_set_sideset(&pc, 1, false, true); | ||||||
|  | 	sm_config_set_in_pins(&pc, RX_PIN); | ||||||
|  | 	sm_config_set_out_pins(&pc, FB_PIN, 1); | ||||||
|  | 	sm_config_set_set_pins(&pc, FB_PIN, 1); | ||||||
|  | 	sm_config_set_sideset_pins(&pc, FB_PIN); | ||||||
|  | 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | ||||||
|  | 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||||
|  | 	pio_sm_init(PIO, FB_SM, prog.origin, &pc); | ||||||
|  | 
 | ||||||
|  | 	pio_sm_set_consecutive_pindirs(PIO, FB_SM, FB_PIN, 1, GPIO_OUT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void init_rx() | ||||||
|  | { | ||||||
|  | 	gpio_disable_pulls(RX_PIN); | ||||||
|  | 	pio_gpio_init(PIO, RX_PIN); | ||||||
|  | 
 | ||||||
| 	const uint16_t insn[] = { | 	const uint16_t insn[] = { | ||||||
| 		pio_encode_in(pio_pins, 1), | 		pio_encode_in(pio_pins, 1), | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_program_t prog = { | 	pio_program_t prog = { | ||||||
| 		.instructions = insn, | 		.instructions = insn, | ||||||
| 		.length = 1, | 		.length = sizeof(insn) / sizeof(*insn), | ||||||
| 		.origin = 6, | 		.origin = -1, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_sm_set_enabled(pio1, 1, false); | 	pio_sm_restart(PIO, RX_SM); | ||||||
| 	pio_sm_restart(pio1, 1); | 	pio_sm_clear_fifos(PIO, RX_SM); | ||||||
| 	pio_sm_clear_fifos(pio1, 1); |  | ||||||
| 
 | 
 | ||||||
| 	if (pio_can_add_program(pio1, &prog)) | 	if (pio_can_add_program(PIO, &prog)) | ||||||
| 		pio_add_program(pio1, &prog); | 		prog.origin = pio_add_program(PIO, &prog); | ||||||
| 
 | 
 | ||||||
| 	pio_sm_config pc = pio_get_default_sm_config(); | 	pio_sm_config pc = pio_get_default_sm_config(); | ||||||
| 	sm_config_set_in_pins(&pc, in_pin); | 	sm_config_set_in_pins(&pc, RX_PIN); | ||||||
| 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | ||||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||||
| 	sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_RX); | 	sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_RX); | ||||||
| 	sm_config_set_in_shift(&pc, false, true, 32); | 	sm_config_set_in_shift(&pc, false, true, 32); | ||||||
| 	pio_sm_init(pio1, 1, prog.origin, &pc); | 	pio_sm_init(PIO, RX_SM, prog.origin, &pc); | ||||||
| 
 | 
 | ||||||
| 	pio_sm_set_enabled(pio1, 1, true); | 	pio_sm_set_consecutive_pindirs(PIO, RX_SM, RX_PIN, 1, GPIO_IN); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void adder_init() | static void init_ad() | ||||||
| { | { | ||||||
| 	const uint16_t insn[] = { | 	const uint16_t insn[] = { | ||||||
| 		pio_encode_jmp_y_dec(1), | 		pio_encode_jmp_y_dec(1), | ||||||
|  | @ -200,6 +212,16 @@ static void adder_init() | ||||||
| 
 | 
 | ||||||
| 		/* Avoid Y-- on wrap. */ | 		/* Avoid Y-- on wrap. */ | ||||||
| 		pio_encode_out(pio_pc, 2), | 		pio_encode_out(pio_pc, 2), | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * Should wrap here. | ||||||
|  | 		 * Jump to this portion must be inserted from the outside. | ||||||
|  | 		 */ | ||||||
|  | 		pio_encode_in(pio_y, 32), | ||||||
|  | 		pio_encode_in(pio_x, 32), | ||||||
|  | 		pio_encode_set(pio_x, 0), | ||||||
|  | 		pio_encode_set(pio_y, 0), | ||||||
|  | 		pio_encode_jmp(1), | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_program_t prog = { | 	pio_program_t prog = { | ||||||
|  | @ -208,28 +230,18 @@ static void adder_init() | ||||||
| 		.origin = 0, | 		.origin = 0, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	pio_sm_set_enabled(pio1, 2, false); | 	pio_sm_restart(PIO, AD_SM); | ||||||
| 	pio_sm_set_enabled(pio1, 3, false); | 	pio_sm_clear_fifos(PIO, AD_SM); | ||||||
| 
 | 
 | ||||||
| 	pio_sm_restart(pio1, 2); | 	if (pio_can_add_program(PIO, &prog)) | ||||||
| 	pio_sm_restart(pio1, 3); | 		pio_add_program(PIO, &prog); | ||||||
| 
 |  | ||||||
| 	pio_sm_clear_fifos(pio1, 2); |  | ||||||
| 	pio_sm_clear_fifos(pio1, 3); |  | ||||||
| 
 |  | ||||||
| 	if (pio_can_add_program(pio1, &prog)) |  | ||||||
| 		pio_add_program(pio1, &prog); |  | ||||||
| 
 | 
 | ||||||
| 	pio_sm_config pc = pio_get_default_sm_config(); | 	pio_sm_config pc = pio_get_default_sm_config(); | ||||||
| 	sm_config_set_wrap(&pc, prog.origin, prog.origin + prog.length - 1); | 	sm_config_set_wrap(&pc, prog.origin, prog.origin + 5 - 1); | ||||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||||
| 	sm_config_set_in_shift(&pc, false, true, 32); | 	sm_config_set_in_shift(&pc, false, true, 32); | ||||||
| 	sm_config_set_out_shift(&pc, false, true, 32); | 	sm_config_set_out_shift(&pc, false, true, 32); | ||||||
| 	pio_sm_init(pio1, 2, prog.origin + prog.length - 1, &pc); | 	pio_sm_init(PIO, AD_SM, prog.origin + 1, &pc); | ||||||
| 	pio_sm_init(pio1, 3, prog.origin + prog.length - 1, &pc); |  | ||||||
| 
 |  | ||||||
| 	pio_sm_set_enabled(pio1, 2, true); |  | ||||||
| 	pio_sm_set_enabled(pio1, 3, true); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define STEP_BASE ((UINT_MAX + 1.0) / CLK_SYS_HZ) | #define STEP_BASE ((UINT_MAX + 1.0) / CLK_SYS_HZ) | ||||||
|  | @ -283,195 +295,125 @@ static void rx_lo_init(double req_freq, bool align) | ||||||
| 		freq = round(freq / step_hz) * step_hz; | 		freq = round(freq / step_hz) * step_hz; | ||||||
| 
 | 
 | ||||||
| 	lo_generate(lo_cos, freq, COS_PHASE); | 	lo_generate(lo_cos, freq, COS_PHASE); | ||||||
| 	lo_generate(lo_sin, freq, SIN_PHASE); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const uint32_t samp_insn[4] __attribute__((__aligned__(16))); | static const uint32_t samp_insn = 5; | ||||||
| static const uint32_t samp_insn[4] = { |  | ||||||
| 	0x4040, /* IN Y, 32 */ |  | ||||||
| 	0x4020, /* IN X, 32 */ |  | ||||||
| 	0xe040, /* SET Y, 0 */ |  | ||||||
| 	0xe020, /* SET X, 0 */ |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| static uint32_t null, one = 1; | static void rf_rx_start() | ||||||
| 
 |  | ||||||
| static void rf_rx_start(int rx_pin, int bias_pin) |  | ||||||
| { | { | ||||||
| 	dma_ch_rx = dma_claim_unused_channel(true); | 	dma_ch_rx1 = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_cp = dma_claim_unused_channel(true); | 	dma_ch_rx2 = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_cos = dma_claim_unused_channel(true); | 
 | ||||||
| 	dma_ch_sin = dma_claim_unused_channel(true); | 	dma_ch_mix1 = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_pio_cos = dma_claim_unused_channel(true); | 	dma_ch_mix2 = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_pio_sin = dma_claim_unused_channel(true); |  | ||||||
| 
 | 
 | ||||||
| 	dma_ch_samp_cos = dma_claim_unused_channel(true); | 	dma_ch_samp_cos = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_samp_sin = dma_claim_unused_channel(true); |  | ||||||
| 	dma_ch_samp_trig = dma_claim_unused_channel(true); |  | ||||||
| 
 | 
 | ||||||
| 	dma_t_samp = dma_claim_unused_timer(true); | 	dma_t_samp = dma_claim_unused_timer(true); | ||||||
| 
 | 
 | ||||||
| 	dma_channel_config dma_conf; | 	dma_channel_config dma_conf; | ||||||
| 
 | 
 | ||||||
| 	/* Read received word into accumulator I. */ | 	/* Copy PDM bitstream into decimator. */ | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_rx); | 	dma_conf = dma_channel_get_default_config(dma_ch_rx1); | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); | 	channel_config_set_read_increment(&dma_conf, false); | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); | 	channel_config_set_write_increment(&dma_conf, false); | ||||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(pio1, 1, false)); | 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, RX_SM, GPIO_IN)); | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_cp); | 	channel_config_set_chain_to(&dma_conf, dma_ch_rx2); | ||||||
| 	dma_channel_configure(dma_ch_rx, &dma_conf, LO_COS_ACCUMULATOR, &pio1->rxf[1], 1, false); | 	dma_channel_configure(dma_ch_rx1, &dma_conf, &PIO->txf[AD_SM], &PIO->rxf[RX_SM], UINT_MAX, | ||||||
| 
 |  | ||||||
| 	/* Copy accumulator I to accumulator Q. */ |  | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_cp); |  | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); |  | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_cos); |  | ||||||
| 	dma_channel_configure(dma_ch_cp, &dma_conf, LO_SIN_ACCUMULATOR, LO_COS_ACCUMULATOR, 1, |  | ||||||
| 			      false); | 			      false); | ||||||
| 
 | 
 | ||||||
| 	/* Read lo_cos into accumulator I with XOR. */ | 	dma_conf = dma_channel_get_default_config(dma_ch_rx2); | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_cos); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
|  | 	channel_config_set_read_increment(&dma_conf, false); | ||||||
|  | 	channel_config_set_write_increment(&dma_conf, false); | ||||||
|  | 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, RX_SM, GPIO_IN)); | ||||||
|  | 	channel_config_set_chain_to(&dma_conf, dma_ch_rx1); | ||||||
|  | 	dma_channel_configure(dma_ch_rx2, &dma_conf, &PIO->txf[AD_SM], &PIO->rxf[RX_SM], UINT_MAX, | ||||||
|  | 			      false); | ||||||
|  | 
 | ||||||
|  | 	/* Drive the LO capacitor. */ | ||||||
|  | 	dma_conf = dma_channel_get_default_config(dma_ch_mix1); | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
| 	channel_config_set_read_increment(&dma_conf, true); | 	channel_config_set_read_increment(&dma_conf, true); | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); | 	channel_config_set_write_increment(&dma_conf, false); | ||||||
| 	channel_config_set_ring(&dma_conf, false, LO_BITS_DEPTH); | 	channel_config_set_ring(&dma_conf, GPIO_IN, LO_BITS_DEPTH); | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_sin); | 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, LO_SM, GPIO_OUT)); | ||||||
| 	dma_channel_configure(dma_ch_cos, &dma_conf, LO_COS_ACCUMULATOR + XOR_ADDR / 4, lo_cos, 1, | 	channel_config_set_chain_to(&dma_conf, dma_ch_mix2); | ||||||
| 			      false); | 	dma_channel_configure(dma_ch_mix1, &dma_conf, &PIO->txf[LO_SM], lo_cos, UINT_MAX, false); | ||||||
| 
 | 
 | ||||||
| 	/* Read lo_sin into accumulator Q with XOR. */ | 	dma_conf = dma_channel_get_default_config(dma_ch_mix2); | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_sin); |  | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
| 	channel_config_set_read_increment(&dma_conf, true); | 	channel_config_set_read_increment(&dma_conf, true); | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); | 	channel_config_set_write_increment(&dma_conf, false); | ||||||
| 	channel_config_set_ring(&dma_conf, false, LO_BITS_DEPTH); | 	channel_config_set_ring(&dma_conf, GPIO_IN, LO_BITS_DEPTH); | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_pio_cos); | 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, LO_SM, GPIO_OUT)); | ||||||
| 	dma_channel_configure(dma_ch_sin, &dma_conf, LO_SIN_ACCUMULATOR + XOR_ADDR / 4, lo_sin, 1, | 	channel_config_set_chain_to(&dma_conf, dma_ch_mix1); | ||||||
| 			      false); | 	dma_channel_configure(dma_ch_mix2, &dma_conf, &PIO->txf[LO_SM], lo_cos, UINT_MAX, false); | ||||||
| 
 |  | ||||||
| 	/* Copy mixed I accumulator to PIO adder I. */ |  | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_pio_cos); |  | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); |  | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(pio1, 2, true)); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_pio_sin); |  | ||||||
| 	dma_channel_configure(dma_ch_pio_cos, &dma_conf, &pio1->txf[2], LO_COS_ACCUMULATOR, 1, |  | ||||||
| 			      false); |  | ||||||
| 
 |  | ||||||
| 	/* Copy mixed Q accumulator to PIO adder Q. */ |  | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_pio_sin); |  | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); |  | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(pio1, 3, true)); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_rx); |  | ||||||
| 	dma_channel_configure(dma_ch_pio_sin, &dma_conf, &pio1->txf[3], LO_SIN_ACCUMULATOR, 1, |  | ||||||
| 			      false); |  | ||||||
| 
 | 
 | ||||||
| 	/* Pacing timer for the sampling script trigger channel. */ | 	/* Pacing timer for the sampling script trigger channel. */ | ||||||
| 	dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | 	dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | ||||||
| 
 | 
 | ||||||
| 	/* Sampling trigger channel. */ | 	/* Trigger accumulator values push. */ | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_samp_trig); | 	dma_conf = dma_channel_get_default_config(dma_ch_samp_cos); | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); | 	channel_config_set_read_increment(&dma_conf, false); | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); | 	channel_config_set_write_increment(&dma_conf, false); | ||||||
|  | 	channel_config_set_ring(&dma_conf, false, 4); | ||||||
|  | 	channel_config_set_high_priority(&dma_conf, true); | ||||||
| 	channel_config_set_dreq(&dma_conf, dma_get_timer_dreq(dma_t_samp)); | 	channel_config_set_dreq(&dma_conf, dma_get_timer_dreq(dma_t_samp)); | ||||||
| 	channel_config_set_high_priority(&dma_conf, true); | 	dma_channel_configure(dma_ch_samp_cos, &dma_conf, &PIO->sm[AD_SM].instr, &samp_insn, | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_samp_cos); | 			      UINT_MAX, false); | ||||||
| 	dma_channel_configure(dma_ch_samp_trig, &dma_conf, &null, &one, 1, false); |  | ||||||
| 
 | 
 | ||||||
| 	/* Trigger I accumulator values push. */ | 	init_lo(); | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_samp_cos); | 	init_fb(); | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	init_rx(); | ||||||
| 	channel_config_set_read_increment(&dma_conf, true); | 	init_ad(); | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_ring(&dma_conf, false, 4); |  | ||||||
| 	channel_config_set_high_priority(&dma_conf, true); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_samp_sin); |  | ||||||
| 	dma_channel_configure(dma_ch_samp_cos, &dma_conf, &pio1->sm[2].instr, samp_insn, 4, false); |  | ||||||
| 
 | 
 | ||||||
| 	/* Trigger Q accumulator values push. */ | 	dma_channel_start(dma_ch_rx1); | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_samp_sin); | 	dma_channel_start(dma_ch_mix1); | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	dma_channel_start(dma_ch_samp_cos); | ||||||
| 	channel_config_set_read_increment(&dma_conf, true); |  | ||||||
| 	channel_config_set_write_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_ring(&dma_conf, false, 4); |  | ||||||
| 	channel_config_set_high_priority(&dma_conf, true); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_samp_trig); |  | ||||||
| 	dma_channel_configure(dma_ch_samp_sin, &dma_conf, &pio1->sm[3].instr, samp_insn, 4, false); |  | ||||||
| 
 | 
 | ||||||
| 	bias_init(rx_pin, bias_pin); | 	pio_sm_set_enabled(PIO, LO_SM, true); | ||||||
| 	adder_init(); | 	pio_sm_set_enabled(PIO, FB_SM, true); | ||||||
| 
 | 	pio_sm_set_enabled(PIO, RX_SM, true); | ||||||
| 	dma_channel_start(dma_ch_rx); | 	pio_sm_set_enabled(PIO, AD_SM, true); | ||||||
| 	dma_channel_start(dma_ch_samp_trig); |  | ||||||
| 	watch_init(rx_pin); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void rf_rx_stop(void) | static void rf_rx_stop(void) | ||||||
| { | { | ||||||
| 	pio_sm_set_enabled(pio1, 0, false); | 	pio_sm_set_enabled(PIO, LO_SM, false); | ||||||
| 	pio_sm_set_enabled(pio1, 1, false); | 	pio_sm_set_enabled(PIO, FB_SM, false); | ||||||
| 	pio_sm_set_enabled(pio1, 2, false); | 	pio_sm_set_enabled(PIO, RX_SM, false); | ||||||
| 	pio_sm_set_enabled(pio1, 3, false); | 	pio_sm_set_enabled(PIO, AD_SM, false); | ||||||
| 
 |  | ||||||
| 	pio_sm_restart(pio1, 0); |  | ||||||
| 	pio_sm_restart(pio1, 1); |  | ||||||
| 	pio_sm_restart(pio1, 2); |  | ||||||
| 	pio_sm_restart(pio1, 3); |  | ||||||
| 
 |  | ||||||
| 	pio_sm_clear_fifos(pio1, 0); |  | ||||||
| 	pio_sm_clear_fifos(pio1, 1); |  | ||||||
| 	pio_sm_clear_fifos(pio1, 2); |  | ||||||
| 	pio_sm_clear_fifos(pio1, 3); |  | ||||||
| 
 | 
 | ||||||
| 	sleep_us(10); | 	sleep_us(10); | ||||||
| 
 | 
 | ||||||
| 	dma_channel_abort(dma_ch_rx); | 	dma_channel_abort(dma_ch_rx1); | ||||||
| 	dma_channel_abort(dma_ch_cp); | 	dma_channel_abort(dma_ch_rx2); | ||||||
| 	dma_channel_abort(dma_ch_cos); | 	dma_channel_abort(dma_ch_mix1); | ||||||
| 	dma_channel_abort(dma_ch_sin); | 	dma_channel_abort(dma_ch_mix2); | ||||||
| 	dma_channel_abort(dma_ch_pio_cos); |  | ||||||
| 	dma_channel_abort(dma_ch_pio_sin); |  | ||||||
| 	dma_channel_abort(dma_ch_samp_cos); | 	dma_channel_abort(dma_ch_samp_cos); | ||||||
| 	dma_channel_abort(dma_ch_samp_sin); |  | ||||||
| 	dma_channel_abort(dma_ch_samp_trig); |  | ||||||
| 
 | 
 | ||||||
| 	dma_channel_cleanup(dma_ch_rx); | 	dma_channel_cleanup(dma_ch_rx1); | ||||||
| 	dma_channel_cleanup(dma_ch_cp); | 	dma_channel_cleanup(dma_ch_rx2); | ||||||
| 	dma_channel_cleanup(dma_ch_cos); | 	dma_channel_cleanup(dma_ch_mix1); | ||||||
| 	dma_channel_cleanup(dma_ch_sin); | 	dma_channel_cleanup(dma_ch_mix2); | ||||||
| 	dma_channel_cleanup(dma_ch_pio_cos); |  | ||||||
| 	dma_channel_cleanup(dma_ch_pio_sin); |  | ||||||
| 	dma_channel_cleanup(dma_ch_samp_cos); | 	dma_channel_cleanup(dma_ch_samp_cos); | ||||||
| 	dma_channel_cleanup(dma_ch_samp_sin); |  | ||||||
| 	dma_channel_cleanup(dma_ch_samp_trig); |  | ||||||
| 
 | 
 | ||||||
| 	dma_channel_unclaim(dma_ch_rx); | 	dma_channel_unclaim(dma_ch_rx1); | ||||||
| 	dma_channel_unclaim(dma_ch_cp); | 	dma_channel_unclaim(dma_ch_rx2); | ||||||
| 	dma_channel_unclaim(dma_ch_cos); | 	dma_channel_unclaim(dma_ch_mix1); | ||||||
| 	dma_channel_unclaim(dma_ch_sin); | 	dma_channel_unclaim(dma_ch_mix2); | ||||||
| 	dma_channel_unclaim(dma_ch_pio_cos); |  | ||||||
| 	dma_channel_unclaim(dma_ch_pio_sin); |  | ||||||
| 	dma_channel_unclaim(dma_ch_samp_cos); | 	dma_channel_unclaim(dma_ch_samp_cos); | ||||||
| 	dma_channel_unclaim(dma_ch_samp_sin); |  | ||||||
| 	dma_channel_unclaim(dma_ch_samp_trig); |  | ||||||
| 
 | 
 | ||||||
| 	dma_timer_unclaim(dma_t_samp); | 	dma_timer_unclaim(dma_t_samp); | ||||||
| 
 | 
 | ||||||
| 	dma_ch_rx = -1; | 	dma_ch_rx1 = -1; | ||||||
| 	dma_ch_cp = -1; | 	dma_ch_rx2 = -1; | ||||||
| 	dma_ch_cos = -1; | 	dma_ch_mix1 = -1; | ||||||
| 	dma_ch_sin = -1; | 	dma_ch_mix2 = -1; | ||||||
| 	dma_ch_pio_cos = -1; |  | ||||||
| 	dma_ch_pio_sin = -1; |  | ||||||
| 	dma_ch_samp_cos = -1; | 	dma_ch_samp_cos = -1; | ||||||
| 	dma_ch_samp_sin = -1; |  | ||||||
| 	dma_ch_samp_trig = -1; |  | ||||||
| 
 | 
 | ||||||
| 	dma_t_samp = -1; | 	dma_t_samp = -1; | ||||||
| } | } | ||||||
|  | @ -491,6 +433,8 @@ static void rf_rx(void) | ||||||
| 		int head = (dma_hw->ch[dma_ch_in_cos].write_addr - base) / 4; | 		int head = (dma_hw->ch[dma_ch_in_cos].write_addr - base) / 4; | ||||||
| 		int delta = (head < pos ? head + RX_WORDS : head) - pos; | 		int delta = (head < pos ? head + RX_WORDS : head) - pos; | ||||||
| 
 | 
 | ||||||
|  | 		sleep_us(10); | ||||||
|  | 
 | ||||||
| 		while (delta < RX_STRIDE) { | 		while (delta < RX_STRIDE) { | ||||||
| 			sleep_us(1); | 			sleep_us(1); | ||||||
| 			head = (dma_hw->ch[dma_ch_in_cos].write_addr - base) / 4; | 			head = (dma_hw->ch[dma_ch_in_cos].write_addr - base) / 4; | ||||||
|  | @ -498,7 +442,6 @@ static void rf_rx(void) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const uint32_t *cos_ptr = rx_cos + pos; | 		const uint32_t *cos_ptr = rx_cos + pos; | ||||||
| 		const uint32_t *sin_ptr = rx_sin + pos; |  | ||||||
| 
 | 
 | ||||||
| 		pos = (pos + RX_STRIDE) & (RX_WORDS - 1); | 		pos = (pos + RX_STRIDE) & (RX_WORDS - 1); | ||||||
| 
 | 
 | ||||||
|  | @ -511,57 +454,34 @@ static void rf_rx(void) | ||||||
| 		 */ | 		 */ | ||||||
| 		int64_t max_amplitude = CLK_SYS_HZ / 2; | 		int64_t max_amplitude = CLK_SYS_HZ / 2; | ||||||
| 
 | 
 | ||||||
| 		/*
 |  | ||||||
| 		 * Since the waveform is normally half of the time |  | ||||||
| 		 * above zero, we can halve once more. |  | ||||||
| 		 * |  | ||||||
| 		 * This is not perfect, so we do not max out the base |  | ||||||
| 		 * gain but keep it slightly below the maximum to make |  | ||||||
| 		 * sure we do not overshoot often. |  | ||||||
| 		 */ |  | ||||||
| 		max_amplitude /= 2; |  | ||||||
| 
 |  | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * We are allowing the counters to only go as high | 		 * We are allowing the counters to only go as high | ||||||
| 		 * as sampling rate. | 		 * as sampling rate, but the I/Q conversion splits | ||||||
|  | 		 * samples between two channels. | ||||||
| 		 */ | 		 */ | ||||||
| 		max_amplitude /= sample_rate; | 		max_amplitude /= sample_rate * 2; | ||||||
| 
 | 
 | ||||||
| 		for (int i = 0; i < IQ_SAMPLES; i++) { | 		for (int i = 0; i < IQ_SAMPLES; i++) { | ||||||
| 			int sI = 0, sQ = 0; | 			int sI = 0, sQ = 0; | ||||||
| 
 | 
 | ||||||
| 			/*
 | 			/* Convert to I/Q signal. */ | ||||||
| 			 * I: +I1 -I3 +Q2 -Q4 | 
 | ||||||
| 			 * Q: +Q1 -Q3 -I2 +I4 |  | ||||||
| 			 */ |  | ||||||
| 			sI += *cos_ptr++; | 			sI += *cos_ptr++; | ||||||
| 			sI -= *cos_ptr++; | 			sI -= *cos_ptr++; | ||||||
| 
 | 
 | ||||||
| 			sQ -= *cos_ptr++; |  | ||||||
| 			sQ += *cos_ptr++; |  | ||||||
| 
 |  | ||||||
| 			sI -= *cos_ptr++; |  | ||||||
| 			sI += *cos_ptr++; |  | ||||||
| 
 |  | ||||||
| 			sQ += *cos_ptr++; | 			sQ += *cos_ptr++; | ||||||
| 			sQ -= *cos_ptr++; | 			sQ -= *cos_ptr++; | ||||||
| 
 | 
 | ||||||
| 			sQ += *sin_ptr++; | 			sI -= *cos_ptr++; | ||||||
| 			sQ -= *sin_ptr++; | 			sI += *cos_ptr++; | ||||||
| 
 | 
 | ||||||
| 			sI += *sin_ptr++; | 			sQ -= *cos_ptr++; | ||||||
| 			sI -= *sin_ptr++; | 			sQ += *cos_ptr++; | ||||||
| 
 |  | ||||||
| 			sQ -= *sin_ptr++; |  | ||||||
| 			sQ += *sin_ptr++; |  | ||||||
| 
 |  | ||||||
| 			sI -= *sin_ptr++; |  | ||||||
| 			sI += *sin_ptr++; |  | ||||||
| 
 | 
 | ||||||
| 			int64_t I = sI; | 			int64_t I = sI; | ||||||
| 			int64_t Q = sQ; | 			int64_t Q = sQ; | ||||||
| 
 | 
 | ||||||
| 			I *= 127; | 			I *= gain; | ||||||
| 			I -= (max_amplitude * 181) / 256; | 			I -= (max_amplitude * 181) / 256; | ||||||
| 			I /= max_amplitude; | 			I /= max_amplitude; | ||||||
| 
 | 
 | ||||||
|  | @ -572,7 +492,7 @@ static void rf_rx(void) | ||||||
| 
 | 
 | ||||||
| 			*blockptr++ = (uint8_t)I + 128; | 			*blockptr++ = (uint8_t)I + 128; | ||||||
| 
 | 
 | ||||||
| 			Q *= 127; | 			Q *= gain; | ||||||
| 			Q -= (max_amplitude * 181) / 256; | 			Q -= (max_amplitude * 181) / 256; | ||||||
| 			Q /= max_amplitude; | 			Q /= max_amplitude; | ||||||
| 
 | 
 | ||||||
|  | @ -591,7 +511,6 @@ static void rf_rx(void) | ||||||
| 		/* Randomize LO phase in the next word. */ | 		/* Randomize LO phase in the next word. */ | ||||||
| 		for (int i = 0; i < 8; i++) { | 		for (int i = 0; i < 8; i++) { | ||||||
| 			lo_tweak(lo_cos, COS_PHASE); | 			lo_tweak(lo_cos, COS_PHASE); | ||||||
| 			lo_tweak(lo_sin, SIN_PHASE); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -600,18 +519,22 @@ static void run_command(uint8_t cmd, uint32_t arg) | ||||||
| { | { | ||||||
| 	if (0x01 == cmd) { | 	if (0x01 == cmd) { | ||||||
| 		/* Tune to a new center frequency */ | 		/* Tune to a new center frequency */ | ||||||
| 		rx_lo_init(arg - sample_rate, true); | 		rx_lo_init(arg + sample_rate, true); | ||||||
| 	} else if (0x02 == cmd) { | 	} else if (0x02 == cmd) { | ||||||
| 		/* Set the rate at which IQ sample pairs are sent */ | 		/* Set the rate at which IQ sample pairs are sent */ | ||||||
| 		sample_rate = arg; | 		sample_rate = arg; | ||||||
| 		dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | 		dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | ||||||
| 		rx_lo_init(arg - sample_rate, true); | 		rx_lo_init(arg + sample_rate, true); | ||||||
| 	} else if (0x04 == cmd) { | 	} else if (0x04 == cmd) { | ||||||
| 		/* Set the tuner gain level */ | 		/* Set the tuner gain level */ | ||||||
| 		bias_set_gain((arg + 14) / 30); | 		gain = INIT_GAIN * powf(10.0f, arg / 200.0f); | ||||||
| 	} else if (0x0d == cmd) { | 	} else if (0x0d == cmd) { | ||||||
| 		/* Set tuner gain by the tuner's gain index */ | 		/* Set tuner gain by the tuner's gain index */ | ||||||
| 		bias_set_gain((gains[arg] + 14) / 30); | 
 | ||||||
|  | 		if (arg >= NUM_GAINS) | ||||||
|  | 			arg = NUM_GAINS - 1; | ||||||
|  | 
 | ||||||
|  | 		gain = INIT_GAIN * powf(10.0f, gains[arg] / 200.0f); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -639,13 +562,12 @@ static int check_command(void) | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void do_rx(int rx_pin, int bias_pin) | static void do_rx() | ||||||
| { | { | ||||||
| 	rf_rx_start(rx_pin, bias_pin); | 	rf_rx_start(); | ||||||
| 	sleep_us(100); | 	sleep_us(100); | ||||||
| 
 | 
 | ||||||
| 	dma_ch_in_cos = dma_claim_unused_channel(true); | 	dma_ch_in_cos = dma_claim_unused_channel(true); | ||||||
| 	dma_ch_in_sin = dma_claim_unused_channel(true); |  | ||||||
| 
 | 
 | ||||||
| 	dma_channel_config dma_conf; | 	dma_channel_config dma_conf; | ||||||
| 
 | 
 | ||||||
|  | @ -653,19 +575,9 @@ static void do_rx(int rx_pin, int bias_pin) | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); | 	channel_config_set_read_increment(&dma_conf, false); | ||||||
| 	channel_config_set_write_increment(&dma_conf, true); | 	channel_config_set_write_increment(&dma_conf, true); | ||||||
| 	channel_config_set_ring(&dma_conf, true, RX_BITS_DEPTH); | 	channel_config_set_ring(&dma_conf, GPIO_OUT, RX_BITS_DEPTH); | ||||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(pio1, 2, false)); | 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, AD_SM, false)); | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_in_sin); | 	dma_channel_configure(dma_ch_in_cos, &dma_conf, rx_cos, &PIO->rxf[AD_SM], UINT_MAX, true); | ||||||
| 	dma_channel_configure(dma_ch_in_cos, &dma_conf, rx_cos, &pio1->rxf[2], 2, false); |  | ||||||
| 
 |  | ||||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_in_sin); |  | ||||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); |  | ||||||
| 	channel_config_set_read_increment(&dma_conf, false); |  | ||||||
| 	channel_config_set_write_increment(&dma_conf, true); |  | ||||||
| 	channel_config_set_ring(&dma_conf, true, RX_BITS_DEPTH); |  | ||||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(pio1, 3, false)); |  | ||||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_in_cos); |  | ||||||
| 	dma_channel_configure(dma_ch_in_sin, &dma_conf, rx_sin, &pio1->rxf[3], 2, true); |  | ||||||
| 
 | 
 | ||||||
| 	multicore_launch_core1(rf_rx); | 	multicore_launch_core1(rf_rx); | ||||||
| 
 | 
 | ||||||
|  | @ -696,13 +608,9 @@ done: | ||||||
| 	rf_rx_stop(); | 	rf_rx_stop(); | ||||||
| 
 | 
 | ||||||
| 	dma_channel_abort(dma_ch_in_cos); | 	dma_channel_abort(dma_ch_in_cos); | ||||||
| 	dma_channel_abort(dma_ch_in_sin); |  | ||||||
| 	dma_channel_cleanup(dma_ch_in_cos); | 	dma_channel_cleanup(dma_ch_in_cos); | ||||||
| 	dma_channel_cleanup(dma_ch_in_sin); |  | ||||||
| 	dma_channel_unclaim(dma_ch_in_cos); | 	dma_channel_unclaim(dma_ch_in_cos); | ||||||
| 	dma_channel_unclaim(dma_ch_in_sin); |  | ||||||
| 	dma_ch_in_cos = -1; | 	dma_ch_in_cos = -1; | ||||||
| 	dma_ch_in_sin = -1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int main() | int main() | ||||||
|  | @ -734,7 +642,7 @@ int main() | ||||||
| 			fwrite(header, sizeof header, 1, stdout); | 			fwrite(header, sizeof header, 1, stdout); | ||||||
| 			fflush(stdout); | 			fflush(stdout); | ||||||
| 
 | 
 | ||||||
| 			do_rx(10, 11); | 			do_rx(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		sleep_ms(10); | 		sleep_ms(10); | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								tools/clangd.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tools/clangd.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | #!/usr/bin/env python | ||||||
|  | 
 | ||||||
|  | import os.path | ||||||
|  | import sys | ||||||
|  | from glob import glob | ||||||
|  | 
 | ||||||
|  | import click | ||||||
|  | import yaml | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @click.command() | ||||||
|  | def clangd(): | ||||||
|  |     """Generate .clangd file for local development.""" | ||||||
|  | 
 | ||||||
|  |     assert "PICO_SDK_PATH" in os.environ, "PICO_SDK_PATH not set" | ||||||
|  | 
 | ||||||
|  |     pico_sdk_path = os.path.realpath(os.environ["PICO_SDK_PATH"]) | ||||||
|  |     cwd = os.path.realpath(os.getcwd()) | ||||||
|  | 
 | ||||||
|  |     includes = [ | ||||||
|  |         *glob(f"{pico_sdk_path}/src/common/*/include"), | ||||||
|  |         *glob(f"{pico_sdk_path}/src/rp2040/*/include"), | ||||||
|  |         *glob(f"{pico_sdk_path}/src/rp2_common/*/include"), | ||||||
|  |         f"{pico_sdk_path}/lib/tinyusb/src", | ||||||
|  |         *glob(f"{cwd}/src/**/include", recursive=True), | ||||||
|  |         f"{cwd}/build/generated/pico_base", | ||||||
|  |         f"{cwd}/build/sdk", | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     flags = [ | ||||||
|  |         "-Wall", | ||||||
|  |         "-Wextra", | ||||||
|  |         "-xc", | ||||||
|  |         "-DCFG_TUSB_MCU=OPT_MCU_RP2040", | ||||||
|  |         "-I/usr/arm-none-eabi/include", | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     yaml.safe_dump( | ||||||
|  |         { | ||||||
|  |             "CompileFlags": { | ||||||
|  |                 "Compiler": "arm-none-eabi-gcc", | ||||||
|  |                 "Add": [*flags, *[f"-I{inc}" for inc in includes]], | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         sys.stdout, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     clangd() | ||||||
		Loading…
	
		Reference in a new issue