Variant for superhet + amplifier
This commit is contained in:
		
							parent
							
								
									1fe4633601
								
							
						
					
					
						commit
						36ca06f31b
					
				
					 3 changed files with 85 additions and 347 deletions
				
			
		|  | @ -37,7 +37,7 @@ blocks: | |||
|   id: variable | ||||
|   parameters: | ||||
|     comment: '' | ||||
|     value: '88_200_000' | ||||
|     value: '94_600_000' | ||||
|   states: | ||||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|  | @ -70,7 +70,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [640, 336.0] | ||||
|     coordinate: [832, 336.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: analog_wfm_rcv_pll_0 | ||||
|  | @ -88,7 +88,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [640, 440.0] | ||||
|     coordinate: [832, 440.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: audio_sink_0 | ||||
|  | @ -105,7 +105,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [928, 448.0] | ||||
|     coordinate: [1120, 448.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: blocks_message_debug_0 | ||||
|  | @ -120,7 +120,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [928, 32.0] | ||||
|     coordinate: [1120, 32.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: blocks_probe_rate_0 | ||||
|  | @ -140,7 +140,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [640, 40.0] | ||||
|     coordinate: [832, 40.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: low_pass_filter_0 | ||||
|  | @ -164,7 +164,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [928, 284.0] | ||||
|     coordinate: [1120, 284.0] | ||||
|     rotation: 0 | ||||
|     state: enabled | ||||
| - name: osmosdr_source_0 | ||||
|  | @ -374,7 +374,7 @@ blocks: | |||
|     freq7: 100e6 | ||||
|     freq8: 100e6 | ||||
|     freq9: 100e6 | ||||
|     gain0: '30' | ||||
|     gain0: '0' | ||||
|     gain1: '10' | ||||
|     gain10: '10' | ||||
|     gain11: '10' | ||||
|  | @ -618,7 +618,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [640, 232.0] | ||||
|     coordinate: [832, 232.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: qtgui_time_sink_x_0_0 | ||||
|  | @ -676,7 +676,7 @@ blocks: | |||
|     marker9: '-1' | ||||
|     name: '"FM Demodulation"' | ||||
|     nconnections: '1' | ||||
|     size: '512' | ||||
|     size: '128' | ||||
|     srate: samp_rate // (2 ** 3) | ||||
|     stemplot: 'False' | ||||
|     style1: '1' | ||||
|  | @ -715,7 +715,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [1128, 312.0] | ||||
|     coordinate: [1320, 312.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: qtgui_waterfall_sink_x_0_0 | ||||
|  | @ -776,7 +776,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [640, 128.0] | ||||
|     coordinate: [832, 128.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| - name: qtgui_waterfall_sink_x_0_0_0_0 | ||||
|  | @ -837,7 +837,7 @@ blocks: | |||
|     bus_sink: false | ||||
|     bus_source: false | ||||
|     bus_structure: null | ||||
|     coordinate: [928, 184.0] | ||||
|     coordinate: [1120, 184.0] | ||||
|     rotation: 0 | ||||
|     state: true | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ target_link_libraries( | |||
|   pico_stdlib | ||||
|   pico_util | ||||
|   hardware_divider | ||||
|   hardware_adc | ||||
|   hardware_dma | ||||
|   hardware_pio | ||||
|   hardware_pwm | ||||
|  |  | |||
							
								
								
									
										405
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										405
									
								
								src/main.c
									
									
									
									
									
								
							|  | @ -4,6 +4,7 @@ | |||
| #include <pico/util/queue.h> | ||||
| 
 | ||||
| #include <hardware/clocks.h> | ||||
| #include <hardware/adc.h> | ||||
| #include <hardware/dma.h> | ||||
| #include <hardware/gpio.h> | ||||
| #include <hardware/pll.h> | ||||
|  | @ -28,20 +29,19 @@ | |||
| #define INIT_FREQ 94600000 | ||||
| #define INIT_GAIN 127 | ||||
| 
 | ||||
| #define LO_PIN 9 | ||||
| #define RX_PIN 13 | ||||
| #define FB_PIN 5 | ||||
| #define LO_PIN 21 | ||||
| #define RX_PIN 26 | ||||
| #define PSU_PIN 23 | ||||
| 
 | ||||
| #define PIO pio1 | ||||
| #define SM_LO 0 | ||||
| #define SM_FB 1 | ||||
| #define SM_RX 2 | ||||
| #define SM_AD 3 | ||||
| 
 | ||||
| #define IQ_SAMPLES 32 | ||||
| #define IQ_BLOCK_LEN (2 * IQ_SAMPLES) | ||||
| #define IQ_QUEUE_LEN 8 | ||||
| #define IQ_QUEUE_LEN 4 | ||||
| 
 | ||||
| #define ADC_RATE (2 * MHZ) | ||||
| #define DECIMATE 8 | ||||
| 
 | ||||
| /*
 | ||||
|  * NOTE: Must have 256 phases with 256 bytes each. | ||||
|  | @ -61,39 +61,19 @@ static uint32_t lo_phase[LO_NUM_PHASES][LO_PHASE_WORDS] | |||
| 
 | ||||
| static uint32_t nco_addr = (uint32_t)lo_phase; | ||||
| 
 | ||||
| #define DECIMATE 16 | ||||
| #define RX_BITS_DEPTH 8 | ||||
| #define RX_WORDS (1 << (RX_BITS_DEPTH - 2)) | ||||
| #define RX_STRIDE (2 * DECIMATE) | ||||
| 
 | ||||
| static_assert(RX_WORDS >= 2 * RX_STRIDE, "RX_WORDS >= 2 * RX_STRIDE"); | ||||
| 
 | ||||
| static uint32_t rx_cos[RX_WORDS] __attribute__((__aligned__(1 << RX_BITS_DEPTH))); | ||||
| 
 | ||||
| #define NUM_GAINS 29 | ||||
| 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, | ||||
| 				372, 386, 402, 421, 434, 439, 445, 480, 496 }; | ||||
| static int sample_rate = INIT_SAMPLE_RATE; | ||||
| static int max_amplitude = CLK_SYS_HZ / INIT_SAMPLE_RATE / 2; | ||||
| static int max_amplitude_mul = 65536 / (CLK_SYS_HZ / INIT_SAMPLE_RATE / 2); | ||||
| static int gain = INIT_GAIN; | ||||
| static int frequency = INIT_FREQ; | ||||
| 
 | ||||
| static int dma_ch_rx1 = -1; | ||||
| static int dma_ch_rx2 = -1; | ||||
| 
 | ||||
| static int dma_ch_nco1 = -1; | ||||
| static int dma_ch_nco2 = -1; | ||||
| static int dma_ch_nco3 = -1; | ||||
| static int dma_ch_mix = -1; | ||||
| 
 | ||||
| static int dma_ch_samp_cos = -1; | ||||
| 
 | ||||
| static int dma_t_samp = -1; | ||||
| 
 | ||||
| static int dma_ch_in_cos = -1; | ||||
| 
 | ||||
| static queue_t iq_queue; | ||||
| static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN]; | ||||
| static size_t iq_queue_pos = 0; | ||||
|  | @ -101,9 +81,6 @@ static size_t iq_queue_pos = 0; | |||
| static uint32_t rnd = 0; | ||||
| 
 | ||||
| static int origin_lo = -1; | ||||
| static int origin_rx = -1; | ||||
| static int origin_fb = -1; | ||||
| static int origin_ad = 0; | ||||
| 
 | ||||
| inline static __unused uint32_t rnd_next() | ||||
| { | ||||
|  | @ -124,8 +101,8 @@ static void init_lo() | |||
| 	gpio_disable_pulls(LO_PIN); | ||||
| 	pio_gpio_init(PIO, LO_PIN); | ||||
| 
 | ||||
| 	gpio_set_drive_strength(LO_PIN, GPIO_DRIVE_STRENGTH_12MA); | ||||
| 	gpio_set_slew_rate(LO_PIN, GPIO_SLEW_RATE_FAST); | ||||
| 	gpio_set_drive_strength(LO_PIN, GPIO_DRIVE_STRENGTH_2MA); | ||||
| 	gpio_set_slew_rate(LO_PIN, GPIO_SLEW_RATE_SLOW); | ||||
| 
 | ||||
| 	const uint16_t insn[] = { | ||||
| 		pio_encode_out(pio_pindirs, 1), | ||||
|  | @ -156,136 +133,6 @@ static void init_lo() | |||
| 	pio_sm_exec_wait_blocking(PIO, SM_LO, pio_encode_set(pio_pins, 0)); | ||||
| } | ||||
| 
 | ||||
| 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_encode_delay(0),
 | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_program_t prog = { | ||||
| 		.instructions = insn, | ||||
| 		.length = sizeof(insn) / sizeof(*insn), | ||||
| 		.origin = origin_fb, | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_sm_restart(PIO, SM_FB); | ||||
| 	pio_sm_clear_fifos(PIO, SM_FB); | ||||
| 
 | ||||
| 	if (pio_can_add_program(PIO, &prog)) | ||||
| 		origin_fb = 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, origin_fb, origin_fb + prog.length - 1); | ||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||
| 	pio_sm_init(PIO, SM_FB, origin_fb, &pc); | ||||
| 
 | ||||
| 	pio_sm_set_consecutive_pindirs(PIO, SM_FB, FB_PIN, 1, GPIO_OUT); | ||||
| } | ||||
| 
 | ||||
| static void init_rx() | ||||
| { | ||||
| 	gpio_disable_pulls(RX_PIN); | ||||
| 	pio_gpio_init(PIO, RX_PIN); | ||||
| 
 | ||||
| 	const uint16_t insn[] = { | ||||
| 		pio_encode_in(pio_pins, 1) | pio_encode_delay(0), | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_program_t prog = { | ||||
| 		.instructions = insn, | ||||
| 		.length = sizeof(insn) / sizeof(*insn), | ||||
| 		.origin = origin_rx, | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_sm_restart(PIO, SM_RX); | ||||
| 	pio_sm_clear_fifos(PIO, SM_RX); | ||||
| 
 | ||||
| 	if (pio_can_add_program(PIO, &prog)) | ||||
| 		origin_rx = pio_add_program(PIO, &prog); | ||||
| 
 | ||||
| 	pio_sm_config pc = pio_get_default_sm_config(); | ||||
| 	sm_config_set_in_pins(&pc, RX_PIN); | ||||
| 	sm_config_set_wrap(&pc, origin_rx, origin_rx + prog.length - 1); | ||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||
| 	sm_config_set_fifo_join(&pc, PIO_FIFO_JOIN_RX); | ||||
| 	sm_config_set_in_shift(&pc, false, true, 32); | ||||
| 	pio_sm_init(PIO, SM_RX, origin_rx, &pc); | ||||
| 
 | ||||
| 	pio_sm_set_consecutive_pindirs(PIO, SM_RX, RX_PIN, 1, GPIO_IN); | ||||
| } | ||||
| 
 | ||||
| static const uint32_t samp_insn = 16; | ||||
| 
 | ||||
| static void init_ad() | ||||
| { | ||||
| 	const uint16_t insn[] = { | ||||
| 		pio_encode_out(pio_pc, 4), // 0000 +0
 | ||||
| 		pio_encode_jmp_x_dec(0),   // 0001 +1
 | ||||
| 		pio_encode_jmp_x_dec(0),   // 0010 +1
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 0011 +2
 | ||||
| 		pio_encode_jmp_x_dec(0),   // 0100 +1
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 0101 +2
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 0110 +2
 | ||||
| 		pio_encode_jmp_y_dec(1),   // 0111 +2 +1
 | ||||
| 		pio_encode_jmp_x_dec(0),   // 1000 +1
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 1001 +2
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 1010 +2
 | ||||
| 		pio_encode_jmp_y_dec(1),   // 1011 +2 +1
 | ||||
| 		pio_encode_jmp_y_dec(0),   // 1100 +2
 | ||||
| 		pio_encode_jmp_y_dec(1),   // 1101 +2 +1
 | ||||
| 		pio_encode_jmp_y_dec(1),   // 1110 +2 +1
 | ||||
| 		pio_encode_jmp_y_dec(3),   // 1111 +2 +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_y, 0), | ||||
| 		pio_encode_set(pio_x, 0), | ||||
| 		pio_encode_jmp_y_dec(21), | ||||
| 		pio_encode_jmp_x_dec(22), | ||||
| 		pio_encode_out(pio_pc, 4), | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_program_t prog = { | ||||
| 		.instructions = insn, | ||||
| 		.length = sizeof(insn) / sizeof(*insn), | ||||
| 		.origin = origin_ad, | ||||
| 	}; | ||||
| 
 | ||||
| 	pio_sm_restart(PIO, SM_AD); | ||||
| 	pio_sm_clear_fifos(PIO, SM_AD); | ||||
| 
 | ||||
| 	if (pio_can_add_program(PIO, &prog)) | ||||
| 		pio_add_program(PIO, &prog); | ||||
| 
 | ||||
| 	pio_sm_config pc = pio_get_default_sm_config(); | ||||
| 	sm_config_set_wrap(&pc, origin_ad, origin_ad + 15); | ||||
| 	sm_config_set_clkdiv_int_frac(&pc, 1, 0); | ||||
| 	sm_config_set_in_shift(&pc, false, true, 32); | ||||
| 	sm_config_set_out_shift(&pc, false, true, 32); | ||||
| 	pio_sm_init(PIO, SM_AD, origin_ad, &pc); | ||||
| } | ||||
| 
 | ||||
| static void lo_generate_phase(uint32_t *buf, size_t len, uint32_t step, uint32_t phase) | ||||
| { | ||||
| 	for (size_t i = 0; i < len; i++) { | ||||
|  | @ -313,37 +160,13 @@ static void rx_lo_init(double freq) | |||
| 
 | ||||
| static void rf_rx_start() | ||||
| { | ||||
| 	dma_ch_rx1 = dma_claim_unused_channel(true); | ||||
| 	dma_ch_rx2 = dma_claim_unused_channel(true); | ||||
| 
 | ||||
| 	dma_ch_nco1 = dma_claim_unused_channel(true); | ||||
| 	dma_ch_nco2 = dma_claim_unused_channel(true); | ||||
| 	dma_ch_nco3 = dma_claim_unused_channel(true); | ||||
| 	dma_ch_mix = dma_claim_unused_channel(true); | ||||
| 
 | ||||
| 	dma_ch_samp_cos = dma_claim_unused_channel(true); | ||||
| 
 | ||||
| 	dma_channel_config dma_conf; | ||||
| 
 | ||||
| 	/* Copy PDM bitstream into decimator. */ | ||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_rx1); | ||||
| 	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, SM_RX, GPIO_IN)); | ||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_rx2); | ||||
| 	dma_channel_configure(dma_ch_rx1, &dma_conf, &PIO->txf[SM_AD], &PIO->rxf[SM_RX], UINT_MAX, | ||||
| 			      false); | ||||
| 
 | ||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_rx2); | ||||
| 	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, SM_RX, GPIO_IN)); | ||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_rx1); | ||||
| 	dma_channel_configure(dma_ch_rx2, &dma_conf, &PIO->txf[SM_AD], &PIO->rxf[SM_RX], UINT_MAX, | ||||
| 			      false); | ||||
| 
 | ||||
| 	/* Step the NCO. */ | ||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_nco1); | ||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||
|  | @ -382,191 +205,105 @@ static void rf_rx_start() | |||
| 	dma_channel_configure(dma_ch_mix, &dma_conf, &PIO->txf[SM_LO], lo_phase, LO_PHASE_WORDS, | ||||
| 			      false); | ||||
| 
 | ||||
| 	/* Trigger accumulator values push. */ | ||||
| 	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_read_increment(&dma_conf, false); | ||||
| 	channel_config_set_write_increment(&dma_conf, false); | ||||
| 	channel_config_set_high_priority(&dma_conf, true); | ||||
| 	channel_config_set_dreq(&dma_conf, dma_get_timer_dreq(dma_t_samp)); | ||||
| 	dma_channel_configure(dma_ch_samp_cos, &dma_conf, &PIO->sm[SM_AD].instr, &samp_insn, | ||||
| 			      UINT_MAX, false); | ||||
| 
 | ||||
| 	init_ad(); | ||||
| 	init_lo(); | ||||
| 	init_fb(); | ||||
| 	init_rx(); | ||||
| 
 | ||||
| 	dma_channel_start(dma_ch_rx1); | ||||
| 	dma_channel_start(dma_ch_nco1); | ||||
| 	dma_channel_start(dma_ch_samp_cos); | ||||
| 
 | ||||
| 	pio_set_sm_mask_enabled(PIO, 0x0f, true); | ||||
| 	pio_sm_set_enabled(PIO, SM_LO, true); | ||||
| } | ||||
| 
 | ||||
| static void rf_rx_stop(void) | ||||
| { | ||||
| 	pio_set_sm_mask_enabled(PIO, 0x0f, false); | ||||
| 	pio_sm_set_enabled(PIO, SM_LO, false); | ||||
| 
 | ||||
| 	sleep_us(10); | ||||
| 
 | ||||
| 	dma_channel_clear_chain_to(dma_ch_rx1); | ||||
| 	dma_channel_clear_chain_to(dma_ch_rx2); | ||||
| 	dma_channel_clear_chain_to(dma_ch_nco1); | ||||
| 	dma_channel_clear_chain_to(dma_ch_nco2); | ||||
| 	dma_channel_clear_chain_to(dma_ch_nco3); | ||||
| 	dma_channel_clear_chain_to(dma_ch_mix); | ||||
| 	dma_channel_clear_chain_to(dma_ch_samp_cos); | ||||
| 
 | ||||
| 	dma_channel_abort(dma_ch_rx1); | ||||
| 	dma_channel_abort(dma_ch_rx2); | ||||
| 	dma_channel_abort(dma_ch_nco1); | ||||
| 	dma_channel_abort(dma_ch_nco2); | ||||
| 	dma_channel_abort(dma_ch_nco3); | ||||
| 	dma_channel_abort(dma_ch_mix); | ||||
| 	dma_channel_abort(dma_ch_samp_cos); | ||||
| 
 | ||||
| 	dma_channel_cleanup(dma_ch_rx1); | ||||
| 	dma_channel_cleanup(dma_ch_rx2); | ||||
| 	dma_channel_cleanup(dma_ch_nco1); | ||||
| 	dma_channel_cleanup(dma_ch_nco2); | ||||
| 	dma_channel_cleanup(dma_ch_nco3); | ||||
| 	dma_channel_cleanup(dma_ch_mix); | ||||
| 	dma_channel_cleanup(dma_ch_samp_cos); | ||||
| 
 | ||||
| 	dma_channel_unclaim(dma_ch_rx1); | ||||
| 	dma_channel_unclaim(dma_ch_rx2); | ||||
| 	dma_channel_unclaim(dma_ch_nco1); | ||||
| 	dma_channel_unclaim(dma_ch_nco2); | ||||
| 	dma_channel_unclaim(dma_ch_nco3); | ||||
| 	dma_channel_unclaim(dma_ch_mix); | ||||
| 	dma_channel_unclaim(dma_ch_samp_cos); | ||||
| 
 | ||||
| 	dma_ch_rx1 = -1; | ||||
| 	dma_ch_rx2 = -1; | ||||
| 	dma_ch_nco1 = -1; | ||||
| 	dma_ch_nco2 = -1; | ||||
| 	dma_ch_nco3 = -1; | ||||
| 	dma_ch_mix = -1; | ||||
| 	dma_ch_samp_cos = -1; | ||||
| } | ||||
| 
 | ||||
| struct IQ { | ||||
| 	int I, Q; | ||||
| }; | ||||
| 
 | ||||
| inline static const uint32_t *next_stride() | ||||
| inline static int nextQ(void) | ||||
| { | ||||
| 	static int tail = 0; | ||||
| 	static int dc = 0; | ||||
| 
 | ||||
| 	int head, delta; | ||||
| 	int x = adc_fifo_get_blocking(); | ||||
| 	int Q = ((x << 16) - dc) >> 16; | ||||
| 	dc += Q; | ||||
| 
 | ||||
| loop: | ||||
| 	head = (dma_hw->ch[dma_ch_in_cos].write_addr >> 2) & (RX_WORDS - 1); | ||||
| 	delta = head - tail; | ||||
| 
 | ||||
| 	if (delta < 0) | ||||
| 		delta += RX_WORDS; | ||||
| 
 | ||||
| 	if (delta < RX_STRIDE) | ||||
| 		goto loop; | ||||
| 
 | ||||
| 	const uint32_t *stride = rx_cos + tail; | ||||
| 
 | ||||
| 	tail = (tail + RX_STRIDE) & (RX_WORDS - 1); | ||||
| 
 | ||||
| 	return stride; | ||||
| } | ||||
| 
 | ||||
| inline static int nextQ(const uint32_t **stride) | ||||
| { | ||||
| 	int x2 = *(*stride)++; | ||||
| 	int x1 = *(*stride)++; | ||||
| 
 | ||||
| 	return x2 + x2 + x1 + max_amplitude; | ||||
| 	return Q; | ||||
| } | ||||
| 
 | ||||
| inline static struct IQ next_sample() | ||||
| { | ||||
| 	int I = 0, Q = 0; | ||||
| 
 | ||||
| 	const uint32_t *stride = next_stride(); | ||||
| 	int x07 = nextQ(); | ||||
| 	I += 36 * x07; | ||||
| 	Q += 36 * x07; | ||||
| 
 | ||||
| 	int x15 = nextQ(&stride); | ||||
| 	I += 93 * x15; | ||||
| 	Q += 39 * x15; | ||||
| 	int x06 = nextQ(); | ||||
| 	I += 0 * x06; | ||||
| 	Q += 51 * x06; | ||||
| 
 | ||||
| 	int x14 = nextQ(&stride); | ||||
| 	I += 71 * x14; | ||||
| 	Q += 71 * x14; | ||||
| 	int x05 = nextQ(); | ||||
| 	I += -36 * x05; | ||||
| 	Q += 36 * x05; | ||||
| 
 | ||||
| 	int x13 = nextQ(&stride); | ||||
| 	I += 39 * x13; | ||||
| 	Q += 93 * x13; | ||||
| 	int x04 = nextQ(); | ||||
| 	I += -51 * x04; | ||||
| 	Q += 0 * x04; | ||||
| 
 | ||||
| 	int x12 = nextQ(&stride); | ||||
| 	I += 0 * x12; | ||||
| 	Q += 101 * x12; | ||||
| 	int x03 = nextQ(); | ||||
| 	I += -36 * x03; | ||||
| 	Q += -36 * x03; | ||||
| 
 | ||||
| 	int x11 = nextQ(&stride); | ||||
| 	I += -39 * x11; | ||||
| 	Q += 93 * x11; | ||||
| 	int x02 = nextQ(); | ||||
| 	I += 0 * x02; | ||||
| 	Q += -51 * x02; | ||||
| 
 | ||||
| 	int x10 = nextQ(&stride); | ||||
| 	I += -71 * x10; | ||||
| 	Q += 71 * x10; | ||||
| 	int x01 = nextQ(); | ||||
| 	I += 36 * x01; | ||||
| 	Q += -36 * x01; | ||||
| 
 | ||||
| 	int x09 = nextQ(&stride); | ||||
| 	I += -93 * x09; | ||||
| 	Q += 39 * x09; | ||||
| 
 | ||||
| 	int x08 = nextQ(&stride); | ||||
| 	I += -101 * x08; | ||||
| 	Q += 0 * x08; | ||||
| 
 | ||||
| 	int x07 = nextQ(&stride); | ||||
| 	I += -93 * x07; | ||||
| 	Q += -39 * x07; | ||||
| 
 | ||||
| 	int x06 = nextQ(&stride); | ||||
| 	I += -71 * x06; | ||||
| 	Q += -71 * x06; | ||||
| 
 | ||||
| 	int x05 = nextQ(&stride); | ||||
| 	I += -39 * x05; | ||||
| 	Q += -93 * x05; | ||||
| 
 | ||||
| 	int x04 = nextQ(&stride); | ||||
| 	I += 0 * x04; | ||||
| 	Q += -101 * x04; | ||||
| 
 | ||||
| 	int x03 = nextQ(&stride); | ||||
| 	I += 39 * x03; | ||||
| 	Q += -93 * x03; | ||||
| 
 | ||||
| 	int x02 = nextQ(&stride); | ||||
| 	I += 71 * x02; | ||||
| 	Q += -71 * x02; | ||||
| 
 | ||||
| 	int x01 = nextQ(&stride); | ||||
| 	I += 93 * x01; | ||||
| 	Q += -39 * x01; | ||||
| 
 | ||||
| 	int x00 = nextQ(&stride); | ||||
| 	I += 101 * x00; | ||||
| 	int x00 = nextQ(); | ||||
| 	I += 51 * x00; | ||||
| 	Q += 0 * x00; | ||||
| 
 | ||||
| 	I *= gain; | ||||
| 	I /= 1024; | ||||
| 	I *= max_amplitude_mul; | ||||
| 	I += 127.4 * (1 << 16); | ||||
| 	I /= (1 << 16); | ||||
| 	I >>= 8; | ||||
| 	I += 127.4 * 256; | ||||
| 	I >>= 8; | ||||
| 
 | ||||
| 	Q *= gain; | ||||
| 	Q /= 1024; | ||||
| 	Q *= max_amplitude_mul; | ||||
| 	Q += 127.4 * (1 << 16); | ||||
| 	Q /= (1 << 16); | ||||
| 	Q >>= 8; | ||||
| 	Q += 127.4 * 256; | ||||
| 	Q >>= 8; | ||||
| 
 | ||||
| 	return (struct IQ){ I, Q }; | ||||
| } | ||||
|  | @ -617,11 +354,11 @@ static void run_command(uint8_t cmd, uint32_t arg) | |||
| 		rx_lo_init(frequency + sample_rate); | ||||
| 	} else if (0x02 == cmd) { | ||||
| 		/* Set the rate at which IQ sample pairs are sent */ | ||||
| 		if (arg > (ADC_RATE / DECIMATE)) | ||||
| 			arg = ADC_RATE / DECIMATE; | ||||
| 
 | ||||
| 		sample_rate = arg; | ||||
| 		max_amplitude = CLK_SYS_HZ / sample_rate / 2; | ||||
| 		max_amplitude_mul = 65536 / max_amplitude; | ||||
| 		dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | ||||
| 		rx_lo_init(frequency + sample_rate); | ||||
| 		adc_set_clkdiv(96.0f * ((float)ADC_RATE / (sample_rate * DECIMATE)) - 1.0f); | ||||
| 	} else if (0x04 == cmd) { | ||||
| 		/* Set the tuner gain level */ | ||||
| 		gain = INIT_GAIN * powf(10.0f, arg / 200.0f); | ||||
|  | @ -664,18 +401,6 @@ static void do_rx() | |||
| 	rf_rx_start(); | ||||
| 	sleep_us(100); | ||||
| 
 | ||||
| 	dma_ch_in_cos = dma_claim_unused_channel(true); | ||||
| 
 | ||||
| 	dma_channel_config dma_conf; | ||||
| 
 | ||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_in_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, true); | ||||
| 	channel_config_set_ring(&dma_conf, GPIO_OUT, RX_BITS_DEPTH); | ||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_AD, false)); | ||||
| 	dma_channel_configure(dma_ch_in_cos, &dma_conf, rx_cos, &PIO->rxf[SM_AD], UINT_MAX, true); | ||||
| 
 | ||||
| 	multicore_launch_core1(rf_rx); | ||||
| 
 | ||||
| 	const uint8_t *block; | ||||
|  | @ -708,18 +433,24 @@ done: | |||
| 	multicore_reset_core1(); | ||||
| 
 | ||||
| 	rf_rx_stop(); | ||||
| 
 | ||||
| 	dma_channel_clear_chain_to(dma_ch_in_cos); | ||||
| 	dma_channel_abort(dma_ch_in_cos); | ||||
| 	dma_channel_cleanup(dma_ch_in_cos); | ||||
| 	dma_channel_unclaim(dma_ch_in_cos); | ||||
| 	dma_ch_in_cos = -1; | ||||
| } | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
| 	vreg_set_voltage(VREG_VOLTAGE); | ||||
| 
 | ||||
| 	/* Step the USB PLL up to 192 MHz and overclock ADC with it. */ | ||||
| 	pll_init(pll_usb, 1, 1536 * MHZ, 4, 2); | ||||
| 
 | ||||
| 	clock_configure(clk_usb, 0, CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, | ||||
| 			4 * USB_CLK_KHZ * KHZ, USB_CLK_KHZ * KHZ); | ||||
| 
 | ||||
| 	clock_configure(clk_adc, 0, CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, | ||||
| 			4 * USB_CLK_KHZ * KHZ, 4 * USB_CLK_KHZ * KHZ); | ||||
| 
 | ||||
| 	/* Adjust system clock as well. */ | ||||
| 	set_sys_clock_khz(CLK_SYS_HZ / KHZ, true); | ||||
| 
 | ||||
| 	clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, CLK_SYS_HZ, | ||||
| 			CLK_SYS_HZ); | ||||
| 
 | ||||
|  | @ -735,10 +466,16 @@ int main() | |||
| 
 | ||||
| 	queue_init(&iq_queue, sizeof(uint8_t *), IQ_QUEUE_LEN); | ||||
| 
 | ||||
| 	rx_lo_init(frequency + sample_rate); | ||||
| 	/* Init ADC */ | ||||
| 	adc_init(); | ||||
| 	gpio_disable_pulls(RX_PIN); | ||||
| 	adc_gpio_init(RX_PIN); | ||||
| 	adc_select_input(RX_PIN - 26); | ||||
| 	adc_fifo_setup(true, true, 1, false, false); | ||||
| 	adc_set_clkdiv(96.0f * ((ADC_RATE / ((float)sample_rate / DECIMATE)) - 1.0f) - 1.0f); | ||||
| 	adc_run(true); | ||||
| 
 | ||||
| 	dma_t_samp = dma_claim_unused_timer(true); | ||||
| 	dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | ||||
| 	rx_lo_init(frequency + sample_rate); | ||||
| 
 | ||||
| 	while (true) { | ||||
| 		if (check_command() > 0) { | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue