Improve LO synthesis precision to 17.9 Hz
This commit is contained in:
		
							parent
							
								
									f7d2dd3629
								
							
						
					
					
						commit
						24d6acdb53
					
				
					 1 changed files with 33 additions and 20 deletions
				
			
		
							
								
								
									
										53
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								src/main.c
									
									
									
									
									
								
							|  | @ -39,9 +39,17 @@ | |||
| #define IQ_BLOCK_LEN (2 * IQ_SAMPLES) | ||||
| #define IQ_QUEUE_LEN 8 | ||||
| 
 | ||||
| #define LO_BITS_DEPTH 15 | ||||
| #define LO_WORDS (1 << (LO_BITS_DEPTH - 2)) | ||||
| static uint32_t lo_cos[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); | ||||
| #define LO_NUM_PHASES 64 | ||||
| #define LO_PHASE_BITS 10 | ||||
| #define LO_PHASE_WORDS (1 << (LO_PHASE_BITS - 2)) | ||||
| #define LO_COS_PHASES 4096 | ||||
| #define LO_EFFECTIVE_BITS (32 * LO_PHASE_WORDS * LO_COS_PHASES) | ||||
| 
 | ||||
| static uint32_t lo_phase[LO_NUM_PHASES][LO_PHASE_WORDS] | ||||
| 	__attribute__((__aligned__(LO_NUM_PHASES * 4 * LO_PHASE_WORDS))); | ||||
| 
 | ||||
| static const uint32_t *lo_cos_phases[LO_COS_PHASES] | ||||
| 	__attribute__((__aligned__(1 << LO_PHASE_BITS))); | ||||
| 
 | ||||
| #define DECIMATE 4 | ||||
| #define RX_STRIDE (2 * IQ_SAMPLES * DECIMATE) | ||||
|  | @ -63,9 +71,6 @@ static int gains[NUM_GAINS] = { 0,   9,	  14,  27,  37,	 77,  87,  125, 144, 157 | |||
| static int sample_rate = INIT_SAMPLE_RATE; | ||||
| static int gain = INIT_GAIN; | ||||
| 
 | ||||
| #define SIN_PHASE (0u) | ||||
| #define COS_PHASE (3u << 30) | ||||
| 
 | ||||
| static int dma_ch_rx1 = -1; | ||||
| static int dma_ch_rx2 = -1; | ||||
| 
 | ||||
|  | @ -245,19 +250,16 @@ static void init_ad() | |||
| } | ||||
| 
 | ||||
| #define STEP_BASE ((UINT_MAX + 1.0) / CLK_SYS_HZ) | ||||
| static uint32_t freq_step = 1; | ||||
| 
 | ||||
| static void lo_generate(uint32_t *buf, double freq, uint32_t phase) | ||||
| static void lo_generate_phase(uint32_t *buf, size_t len, uint32_t step, uint32_t phase) | ||||
| { | ||||
| 	freq_step = STEP_BASE * freq; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < LO_WORDS; i++) { | ||||
| 	for (size_t i = 0; i < len; i++) { | ||||
| 		uint32_t bits = 0; | ||||
| 
 | ||||
| 		for (int j = 0; j < 32; j++) { | ||||
| 			bits |= phase >> 31; | ||||
| 			bits <<= 1; | ||||
| 			phase += freq_step; | ||||
| 			phase += step; | ||||
| 		} | ||||
| 
 | ||||
| 		buf[i] = bits; | ||||
|  | @ -266,13 +268,25 @@ static void lo_generate(uint32_t *buf, double freq, uint32_t phase) | |||
| 
 | ||||
| static void rx_lo_init(double req_freq, bool align) | ||||
| { | ||||
| 	const double step_hz = (double)CLK_SYS_HZ / (8 << LO_BITS_DEPTH); | ||||
| 	const double step_hz = (double)CLK_SYS_HZ / (LO_EFFECTIVE_BITS / 2.0); | ||||
| 	double freq = req_freq; | ||||
| 
 | ||||
| 	if (align) | ||||
| 		freq = round(freq / step_hz) * step_hz; | ||||
| 
 | ||||
| 	lo_generate(lo_cos, freq, COS_PHASE); | ||||
| 	uint32_t step = STEP_BASE * freq; | ||||
| 
 | ||||
| 	for (uint32_t i = 0; i < LO_NUM_PHASES; i++) | ||||
| 		lo_generate_phase(lo_phase[i], LO_PHASE_WORDS, step, | ||||
| 				  i << (__builtin_clz(LO_NUM_PHASES) + 1)); | ||||
| 
 | ||||
| 	uint32_t phase_step = step * 32 * LO_PHASE_WORDS; | ||||
| 	uint32_t phase = 0; | ||||
| 
 | ||||
| 	for (uint32_t i = 0; i < LO_COS_PHASES; i++) { | ||||
| 		lo_cos_phases[i] = lo_phase[phase >> (__builtin_clz(LO_NUM_PHASES) + 1)]; | ||||
| 		phase += phase_step; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static const uint32_t samp_insn = 5; | ||||
|  | @ -315,19 +329,18 @@ static void rf_rx_start() | |||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||
| 	channel_config_set_read_increment(&dma_conf, true); | ||||
| 	channel_config_set_write_increment(&dma_conf, false); | ||||
| 	channel_config_set_ring(&dma_conf, GPIO_IN, LO_BITS_DEPTH); | ||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, LO_SM, GPIO_OUT)); | ||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_mix2); | ||||
| 	dma_channel_configure(dma_ch_mix1, &dma_conf, &PIO->txf[LO_SM], lo_cos, UINT_MAX, false); | ||||
| 	channel_config_set_ring(&dma_conf, GPIO_IN, LO_PHASE_BITS); | ||||
| 	dma_channel_configure(dma_ch_mix1, &dma_conf, &dma_hw->ch[dma_ch_mix2].al3_read_addr_trig, | ||||
| 			      lo_cos_phases, 1, false); | ||||
| 
 | ||||
| 	dma_conf = dma_channel_get_default_config(dma_ch_mix2); | ||||
| 	channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_32); | ||||
| 	channel_config_set_read_increment(&dma_conf, true); | ||||
| 	channel_config_set_write_increment(&dma_conf, false); | ||||
| 	channel_config_set_ring(&dma_conf, GPIO_IN, LO_BITS_DEPTH); | ||||
| 	channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, LO_SM, GPIO_OUT)); | ||||
| 	channel_config_set_chain_to(&dma_conf, dma_ch_mix1); | ||||
| 	dma_channel_configure(dma_ch_mix2, &dma_conf, &PIO->txf[LO_SM], lo_cos, UINT_MAX, false); | ||||
| 	dma_channel_configure(dma_ch_mix2, &dma_conf, &PIO->txf[LO_SM], NULL, LO_PHASE_WORDS, | ||||
| 			      false); | ||||
| 
 | ||||
| 	/* Pacing timer for the sampling script trigger channel. */ | ||||
| 	dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue