comparison modulator.c @ 28:600a394629e6

Use 8 bit auto pull otherwise the PIOs jitter (due to DMA contention I guess?) Don't need to unroll the PIO loops. Create PIo function to reset each PIO. Check the DMA IRQ is for us - we get unknown IRQs which need to be ignored or things break.
author Daniel O'Connor <darius@dons.net.au>
date Thu, 27 Feb 2025 13:58:37 +1030
parents e1d8fe3e418a
children babdb5376356
comparison
equal deleted inserted replaced
27:e1d8fe3e418a 28:600a394629e6
69 69
70 // Pulse shape data 70 // Pulse shape data
71 uint8_t pulse_data[65536] __attribute__((aligned(4))); 71 uint8_t pulse_data[65536] __attribute__((aligned(4)));
72 // Pulse control data 72 // Pulse control data
73 uint8_t pulse_ctrl[65536] __attribute__((aligned(4))); 73 uint8_t pulse_ctrl[65536] __attribute__((aligned(4)));
74 // DMA transfer size for above
75 unsigned transfercount;
76
74 // PWM slice for PRF timer 77 // PWM slice for PRF timer
75 unsigned slice_num = 0; 78 unsigned slice_num = 0;
76 79
77 // PIO for pulse generation 80 // PIO for pulse generation
78 PIO pulse_pio = pio0; 81 PIO pulse_pio = pio0;
88 static int ctrl_dma_chan; 91 static int ctrl_dma_chan;
89 // Ctrl SM 92 // Ctrl SM
90 uint ctrl_sm; 93 uint ctrl_sm;
91 // Instruction offset for ctrl PIO program 94 // Instruction offset for ctrl PIO program
92 uint ctrl_pio_sm_offset; 95 uint ctrl_pio_sm_offset;
96
97 // Trigger SM
98 uint trigger_sm;
93 99
94 /* 100 /*
95 * Use a DMA channel to feed PIO0 SM0 with pulse data. 101 * Use a DMA channel to feed PIO0 SM0 with pulse data.
96 * Each DMA transfer is a single pulse. 102 * Each DMA transfer is a single pulse.
97 * 103 *
102 * pulse (or not if it should stop). ie reset the PIO state machine 108 * pulse (or not if it should stop). ie reset the PIO state machine
103 * back to waiting for an edge and re-arm the DMA. 109 * back to waiting for an edge and re-arm the DMA.
104 */ 110 */
105 void 111 void
106 dma_handler(void) { 112 dma_handler(void) {
113 uint32_t tmp;
114
115 if (!dma_channel_get_irq0_status(dac_dma_chan)) {
116 //printf("Mystery DMA IRQ\n");
117 return;
118 }
119
107 // Clear the interrupt request. 120 // Clear the interrupt request.
108 dma_hw->ints0 = 1u << dac_dma_chan; 121 dma_hw->ints0 = 1u << dac_dma_chan;
109 122 if (((tmp = dma_channel_hw_addr(dac_dma_chan)->transfer_count)) != 0)
110 #if 0 123 printf("DAC transfers %lu\n", tmp);
111 printf("DAC transfers %lu\n", dma_channel_hw_addr(dac_dma_chan)->transfer_count); 124 if (((tmp = dma_channel_hw_addr(ctrl_dma_chan)->transfer_count)) != 0)
112 printf("Ctrl transfers %lu\n", dma_channel_hw_addr(ctrl_dma_chan)->transfer_count); 125 printf("Ctrl transfers %lu\n", tmp);
113 #endif
114 126
115 // Reset DAQ & ctrl PIO SMs so they are waiting for a trigger 127 // Reset DAQ & ctrl PIO SMs so they are waiting for a trigger
116 pio_sm_exec(pulse_pio, dac_sm, pio_encode_jmp(dac_pio_sm_offset)); 128 pio_sm_exec_wait_blocking(pulse_pio, dac_sm, dac_reset_instr(dac_pio_sm_offset));
117 pio_sm_exec(pulse_pio, ctrl_sm, pio_encode_jmp(ctrl_pio_sm_offset)); 129 pio_sm_exec_wait_blocking(pulse_pio, ctrl_sm, ctrl_reset_instr(ctrl_pio_sm_offset));
130
131 // Abort any existing DMA
132 // Have to do a song and dance for the IRQ generating one due
133 // to errata RP2350-E5
134 dma_channel_set_irq0_enabled(dac_dma_chan, false);
135 dma_channel_abort(dac_dma_chan);
136 dma_channel_acknowledge_irq0(dac_dma_chan);
137 dma_channel_set_irq0_enabled(dac_dma_chan, true);
138 dma_channel_abort(ctrl_dma_chan);
118 139
119 // Setup next pulse data & ctrl DMA addresses 140 // Setup next pulse data & ctrl DMA addresses
120 dma_channel_wait_for_finish_blocking(dac_dma_chan); 141 dma_channel_set_read_addr(dac_dma_chan, pulse_data, false);
121 dma_channel_set_read_addr(dac_dma_chan, pulse_data, true); 142 dma_channel_set_trans_count(dac_dma_chan, transfercount, true);
122 dma_channel_wait_for_finish_blocking(ctrl_dma_chan); 143
123 dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, true); 144 // Disable and resync/enable DAQ & ctrl PIO SMs so they are waiting for a trigger
145 pio_set_sm_mask_enabled(pulse_pio, 1u << dac_sm | 1u << ctrl_sm, false);
146 pio_enable_sm_mask_in_sync(pulse_pio, 1u << dac_sm | 1u << ctrl_sm);
147
148 // Setup next pulse data & ctrl DMA addresses
149 dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, false);
150 dma_channel_set_trans_count(ctrl_dma_chan, transfercount, true);
124 } 151 }
125 152
126 void 153 void
127 pwm_wrap(void) { 154 pwm_wrap(void) {
128 pwm_clear_irq(slice_num); 155 pwm_clear_irq(slice_num);
215 printf("dcscale = %s\n", tmps); 242 printf("dcscale = %s\n", tmps);
216 243
217 memset(pulse_data, 0, datalen); 244 memset(pulse_data, 0, datalen);
218 memset(pulse_ctrl, 0, datalen); 245 memset(pulse_ctrl, 0, datalen);
219 idx = 0; 246 idx = 0;
247 #if 0
248 for (uint16_t i = 0; i < 255 * 200; i++)
249 data[idx++] = i / 200;
250
251 printf("Dummy done\n");
252 return idx;
253 #endif
254 #if 0
255 data[idx++] = 255;
256 data[idx++] = 0;
257 data[idx++] = 0;
258 data[idx++] = 0;
259 data[idx++] = 0;
260 data[idx++] = 128;
261 data[idx++] = 128;
262 data[idx++] = 0;
263 data[idx++] = 0;
264 data[idx++] = 0;
265 data[idx++] = 0;
266 data[idx++] = 0;
267 data[idx++] = 255;
268 #endif
220 269
221 // Up slew 270 // Up slew
222 for (uint16_t i = 0; i < slew1; i++) { 271 for (uint16_t i = 0; i < slew1; i++) {
223 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1))); 272 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1)));
224 } 273 }
347 } 396 }
348 now = get_absolute_time(); 397 now = get_absolute_time();
349 unsigned long long diff = absolute_time_diff_us(then, now); 398 unsigned long long diff = absolute_time_diff_us(then, now);
350 printf("Pulse computation took %lld usec and created %lu samples - %.1f nsec/sample\n", 399 printf("Pulse computation took %lld usec and created %lu samples - %.1f nsec/sample\n",
351 diff, idx, (float)diff * 1000.0 / idx); 400 diff, idx, (float)diff * 1000.0 / idx);
352 unsigned transfers = (idx + 3) >> 2; 401 transfercount = ((idx + 3) >> 2);
353 printf("Using %u transfers\n", transfers); 402 printf("Using %u transfers\n", transfercount);
354 //__breakpoint(); 403 //__breakpoint();
355 404
356 // Load the DAC program, and configure a free state machine 405 // Load the DAC program, and configure a free state machine
357 // to run the program. 406 // to run the program.
358 dac_pio_sm_offset = pio_add_program(pulse_pio, &dac_program); 407 dac_pio_sm_offset = pio_add_program(pulse_pio, &dac_program);
377 dma_channel_configure( 426 dma_channel_configure(
378 dac_dma_chan, 427 dac_dma_chan,
379 &dac_dmac, 428 &dac_dmac,
380 &pulse_pio->txf[dac_sm], // Write address 429 &pulse_pio->txf[dac_sm], // Write address
381 pulse_data, // Pulse data 430 pulse_data, // Pulse data
382 transfers, // Transfer count 431 transfercount, // Transfer count
383 true // Start transfer 432 true // Start transfer
384 ); 433 );
385 434
386 // Tell the DMA to raise IRQ line 0 when the channel finishes a block 435 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
387 dma_channel_set_irq0_enabled(dac_dma_chan, true); 436 dma_channel_set_irq0_enabled(dac_dma_chan, true);
411 dma_channel_configure( 460 dma_channel_configure(
412 ctrl_dma_chan, 461 ctrl_dma_chan,
413 &ctrl_dmac, 462 &ctrl_dmac,
414 &pulse_pio->txf[ctrl_sm], // Write address 463 &pulse_pio->txf[ctrl_sm], // Write address
415 pulse_ctrl, // Ctrl data 464 pulse_ctrl, // Ctrl data
416 transfers, // Transfer count 465 transfercount, // Transfer count
417 true // Start transfer 466 true // Start transfer
418 ); 467 );
419 // No IRQ, piggyback on the data one 468 // No IRQ, piggyback on the data one
420 469
421 #ifdef WITH_TRIGGER 470 #ifdef WITH_TRIGGER
424 uint trigger_pio_sm_offset = pio_add_program(pulse_pio, &trigger_program); 473 uint trigger_pio_sm_offset = pio_add_program(pulse_pio, &trigger_program);
425 if (trigger_pio_sm_offset < 0) { 474 if (trigger_pio_sm_offset < 0) {
426 printf("Unable to load trigger program\n"); 475 printf("Unable to load trigger program\n");
427 __breakpoint(); 476 __breakpoint();
428 } 477 }
429 uint trigger_sm = pio_claim_unused_sm(pulse_pio, true); 478 trigger_sm = pio_claim_unused_sm(pulse_pio, true);
430 trigger_program_init(pulse_pio, trigger_sm, trigger_pio_sm_offset, TRIGIN_GPIO, 1); 479 trigger_program_init(pulse_pio, trigger_sm, trigger_pio_sm_offset, TRIGIN_GPIO, 1);
431 #endif 480 #endif
432 481
433 // Start & sync all state machines 482 // Start & sync all state machines
434 // This is necessary to avoid any jitter and to make the 483 // This is necessary to avoid any jitter and to make the
435 // trigger sync work correctly 484 // trigger sync work correctly
436 pio_enable_sm_mask_in_sync(pulse_pio, 485 pio_enable_sm_mask_in_sync(pulse_pio, 0
437 1u << dac_sm | 486 | 1u << dac_sm
438 1u << ctrl_sm | 487 | 1u << ctrl_sm
439 #ifdef WITH_TRIGGER 488 #ifdef WITH_TRIGGER
440 1u << trigger_sm 489 | 1u << trigger_sm
441 #endif 490 #endif
442 ); 491 );
443 // 492 //
444 // Setup PWM 493 // Setup PWM
445 // Used here to output a trigger which gets fed back into the trigger SM 494 // Used here to output a trigger which gets fed back into the trigger SM