diff 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
line wrap: on
line diff
--- a/modulator.c	Wed Feb 26 11:03:59 2025 +1030
+++ b/modulator.c	Thu Feb 27 13:58:37 2025 +1030
@@ -71,6 +71,9 @@
 uint8_t pulse_data[65536] __attribute__((aligned(4)));
 // Pulse control data
 uint8_t pulse_ctrl[65536] __attribute__((aligned(4)));
+// DMA transfer size for above
+unsigned transfercount;
+
 // PWM slice for PRF timer
 unsigned slice_num = 0;
 
@@ -91,6 +94,9 @@
 // Instruction offset for ctrl PIO program
 uint ctrl_pio_sm_offset;
 
+// Trigger SM
+uint trigger_sm;
+
 /*
  * Use a DMA channel to feed PIO0 SM0 with pulse data.
  * Each DMA transfer is a single pulse.
@@ -104,23 +110,44 @@
  */
 void
 dma_handler(void) {
+  uint32_t tmp;
+
+  if (!dma_channel_get_irq0_status(dac_dma_chan)) {
+    //printf("Mystery DMA IRQ\n");
+    return;
+  }
+
   // Clear the interrupt request.
   dma_hw->ints0 = 1u << dac_dma_chan;
-
-#if 0
-  printf("DAC transfers %lu\n", dma_channel_hw_addr(dac_dma_chan)->transfer_count);
-  printf("Ctrl transfers %lu\n", dma_channel_hw_addr(ctrl_dma_chan)->transfer_count);
-#endif
+  if (((tmp = dma_channel_hw_addr(dac_dma_chan)->transfer_count)) != 0)
+    printf("DAC transfers %lu\n", tmp);
+  if (((tmp = dma_channel_hw_addr(ctrl_dma_chan)->transfer_count)) != 0)
+    printf("Ctrl transfers %lu\n", tmp);
 
   // Reset DAQ & ctrl PIO SMs so they are  waiting for a trigger
-  pio_sm_exec(pulse_pio, dac_sm, pio_encode_jmp(dac_pio_sm_offset));
-  pio_sm_exec(pulse_pio, ctrl_sm, pio_encode_jmp(ctrl_pio_sm_offset));
+  pio_sm_exec_wait_blocking(pulse_pio, dac_sm, dac_reset_instr(dac_pio_sm_offset));
+  pio_sm_exec_wait_blocking(pulse_pio, ctrl_sm, ctrl_reset_instr(ctrl_pio_sm_offset));
+
+  // Abort any existing DMA
+  // Have to do a song and dance for the IRQ generating one due
+  // to errata RP2350-E5
+  dma_channel_set_irq0_enabled(dac_dma_chan, false);
+  dma_channel_abort(dac_dma_chan);
+  dma_channel_acknowledge_irq0(dac_dma_chan);
+  dma_channel_set_irq0_enabled(dac_dma_chan, true);
+  dma_channel_abort(ctrl_dma_chan);
 
   // Setup next pulse data & ctrl DMA addresses
-  dma_channel_wait_for_finish_blocking(dac_dma_chan);
-  dma_channel_set_read_addr(dac_dma_chan, pulse_data, true);
-  dma_channel_wait_for_finish_blocking(ctrl_dma_chan);
-  dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, true);
+  dma_channel_set_read_addr(dac_dma_chan, pulse_data, false);
+  dma_channel_set_trans_count(dac_dma_chan, transfercount, true);
+
+  // Disable and resync/enable DAQ & ctrl PIO SMs so they are  waiting for a trigger
+  pio_set_sm_mask_enabled(pulse_pio, 1u << dac_sm | 1u << ctrl_sm, false);
+  pio_enable_sm_mask_in_sync(pulse_pio, 1u << dac_sm | 1u << ctrl_sm);
+
+  // Setup next pulse data & ctrl DMA addresses
+  dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, false);
+  dma_channel_set_trans_count(ctrl_dma_chan, transfercount, true);
 }
 
 void
@@ -217,6 +244,28 @@
   memset(pulse_data, 0, datalen);
   memset(pulse_ctrl, 0, datalen);
   idx = 0;
+#if 0
+  for (uint16_t i = 0; i < 255 * 200; i++)
+    data[idx++] = i / 200;
+
+  printf("Dummy done\n");
+  return idx;
+#endif
+#if 0
+  data[idx++] = 255;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 128;
+  data[idx++] = 128;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 0;
+  data[idx++] = 255;
+#endif
 
   // Up slew
   for (uint16_t i = 0; i < slew1; i++) {
@@ -349,8 +398,8 @@
     unsigned long long diff = absolute_time_diff_us(then, now);
     printf("Pulse computation took %lld usec and created %lu samples - %.1f nsec/sample\n",
 	   diff, idx, (float)diff * 1000.0 / idx);
-    unsigned transfers = (idx + 3) >> 2;
-    printf("Using %u transfers\n", transfers);
+    transfercount = ((idx + 3) >> 2);
+    printf("Using %u transfers\n", transfercount);
     //__breakpoint();
 
     // Load the DAC program, and configure a free state machine
@@ -379,7 +428,7 @@
         &dac_dmac,
         &pulse_pio->txf[dac_sm],   // Write address
         pulse_data,                // Pulse data
-        transfers,	           // Transfer count
+        transfercount,	           // Transfer count
         true			   // Start transfer
     );
 
@@ -413,7 +462,7 @@
         &ctrl_dmac,
         &pulse_pio->txf[ctrl_sm],  // Write address
         pulse_ctrl,                // Ctrl data
-        transfers,	           // Transfer count
+        transfercount,	           // Transfer count
         true			   // Start transfer
     );
     // No IRQ, piggyback on the data one
@@ -426,18 +475,18 @@
       printf("Unable to load trigger program\n");
       __breakpoint();
     }
-    uint trigger_sm = pio_claim_unused_sm(pulse_pio, true);
+    trigger_sm = pio_claim_unused_sm(pulse_pio, true);
     trigger_program_init(pulse_pio, trigger_sm, trigger_pio_sm_offset, TRIGIN_GPIO, 1);
 #endif
 
     // Start & sync all state machines
     // This is necessary to avoid any jitter and to make the
     // trigger sync work correctly
-    pio_enable_sm_mask_in_sync(pulse_pio,
-			       1u << dac_sm |
-			       1u << ctrl_sm |
+    pio_enable_sm_mask_in_sync(pulse_pio, 0
+			       | 1u << dac_sm
+			       | 1u << ctrl_sm
 #ifdef WITH_TRIGGER
-			       1u << trigger_sm
+			       | 1u << trigger_sm
 #endif
 			       );
     //