comparison modulator.c @ 16:56a79dce90e9

Commit WIP ctrl code
author Daniel O'Connor <darius@dons.net.au>
date Tue, 25 Feb 2025 13:31:27 +1030
parents e9d12b36cfcc
children a249e4727b01
comparison
equal deleted inserted replaced
15:bf483219cb12 16:56a79dce90e9
3 ** 3 **
4 ** This is proprietary unpublished source code, property 4 ** This is proprietary unpublished source code, property
5 ** of Genesis Software. Use or disclosure without prior 5 ** of Genesis Software. Use or disclosure without prior
6 ** agreement is expressly prohibited. 6 ** agreement is expressly prohibited.
7 ** 7 **
8 ** Copyright (c) 2021 Genesis Software, all rights reserved. 8 ** Copyright (c) 2025 Genesis Software, all rights reserved.
9 ** 9 **
10 ******************************************************************* 10 *******************************************************************
11 ******************************************************************/ 11 ******************************************************************/
12 12
13 /* 13 /*
17 ** 17 **
18 */ 18 */
19 19
20 #include <stdio.h> 20 #include <stdio.h>
21 #include <string.h> 21 #include <string.h>
22 #include "bitstring.h"
23 22
24 #pragma GCC diagnostic push 23 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Wtype-limits" 24 #pragma GCC diagnostic ignored "-Wtype-limits"
26 #pragma GCC diagnostic ignored "-Wsign-compare" 25 #pragma GCC diagnostic ignored "-Wsign-compare"
27 #include "pico/stdlib.h" 26 #include "pico/stdlib.h"
35 #include "hardware/structs/pll.h" 34 #include "hardware/structs/pll.h"
36 #include "hardware/structs/clocks.h" 35 #include "hardware/structs/clocks.h"
37 #pragma GCC diagnostic pop 36 #pragma GCC diagnostic pop
38 37
39 #include "dac.pio.h" 38 #include "dac.pio.h"
39 #include "ctrl.pio.h"
40 #include "trigger.pio.h" 40 #include "trigger.pio.h"
41 41
42 // https://github.com/howerj/q 42 // https://github.com/howerj/q
43 // Modified to be Q20.12 rather than Q16.16 43 // Modified to be Q20.12 rather than Q16.16
44 #include "q/q.h" 44 #include "q/q.h"
45 45
46 #include "shaped-trap.h" 46 #include "shaped-trap.h"
47 47
48 // Base of DAC pins 48 // Base of DAC pins
49 #define DACOUT_GPIO 7 49 #define DACOUT_GPIO 7
50 // Base of ctrl pins
51 #define CTRLOUT_GPIO 16
50 // PWM output pin 52 // PWM output pin
51 #define TRIGOUT_GPIO 22 53 #define TRIGOUT_GPIO 23
52 // PIO SM trigger input pin (connected to above for testing) 54 // PIO SM trigger input pin (connected to above for testing)
53 #define TRIGIN_GPIO 27 55 #define TRIGIN_GPIO 27
54 56
55 // Pulse control bits 57 // Pulse control bits
56 #define SENSE 0x01 58 #define PACTIVE 0x01
57 #define GATE 0x02 59 #define PHINV 0x02
58 #define PHINV 0x04 60 #define SENSE1 0x04
59 #define PACTIVE 0x08 61 #define SENSE2 0x08
60 62 #define GATE 0x10
61 // DMA channel to feed DAC PIO 63 #define TRSW 0x20
62 static int dma_chan; 64
63 // Pulse shape data 65 // Pulse shape data
64 uint8_t pulse_data[65536]; 66 uint8_t pulse_data[65536] __attribute__((aligned(4)));
65 // Pulse control data 67 // Pulse control data
66 uint8_t pulse_ctrl[65536]; 68 uint8_t pulse_ctrl[65536] __attribute__((aligned(4)));
67 // PWM slice for PRF timer 69 // PWM slice for PRF timer
68 unsigned slice_num = 0; 70 unsigned slice_num = 0;
69 // DAC PIO 71
72 // PIO for pulse generation
70 PIO pulse_pio = pio0; 73 PIO pulse_pio = pio0;
74
75 // DMA channel to feed DAC PIO
76 static int dac_dma_chan;
71 // DAC SM 77 // DAC SM
72 uint pulse_sm; 78 uint dac_sm;
73 // Instruction offset for DAC PIO program 79 // Instruction offset for DAC PIO program
74 uint pulse_pio_sm_offset; 80 uint dac_pio_sm_offset;
81
82 // DMA channel to feed ctrl PIO
83 static int ctrl_dma_chan;
84 // Ctrl SM
85 uint ctrl_sm;
86 // Instruction offset for ctrl PIO program
87 uint ctrl_pio_sm_offset;
88
75 /* 89 /*
76 * Use a DMA channel to feed PIO0 SM0 with pulse data. 90 * Use a DMA channel to feed PIO0 SM0 with pulse data.
77 * Each DMA transfer is a single pulse. 91 * Each DMA transfer is a single pulse.
78 * 92 *
79 * The PIO state machine waits to be triggered before starting 93 * The PIO state machine waits to be triggered before starting
84 * back to waiting for an edge and re-arm the DMA. 98 * back to waiting for an edge and re-arm the DMA.
85 */ 99 */
86 void 100 void
87 dma_handler(void) { 101 dma_handler(void) {
88 // Clear the interrupt request. 102 // Clear the interrupt request.
89 dma_hw->ints0 = 1u << dma_chan; 103 dma_hw->ints0 = 1u << dac_dma_chan;
90 104
91 // Reset DAQ PIO SM so it is waiting for a trigger 105 // Disabled for now, manual trigger only
92 pio_sm_exec(pulse_pio, pulse_sm, pio_encode_jmp(pulse_pio_sm_offset)); 106 #if 0
93 107 // Reset DAQ & ctrl PIO SMs so they are waiting for a trigger
94 // Setup next pulse DMA address 108 pio_sm_exec(pulse_pio, dac_sm, pio_encode_jmp(dac_pio_sm_offset));
95 dma_channel_set_read_addr(dma_chan, pulse_data, true); 109 pio_sm_exec(pulse_pio, ctrl_sm, pio_encode_jmp(ctrl_pio_sm_offset));
110
111 // Setup next pulse data & ctrl DMA addresses
112 dma_channel_set_read_addr(dac_dma_chan, pulse_data, true);
113 dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, true);
114 #endif
96 } 115 }
97 116
98 117
99 void 118 void
100 pwm_wrap(void) { 119 pwm_wrap(void) {
101 pwm_clear_irq(slice_num); 120 pwm_clear_irq(slice_num);
121
122 // Reset DAQ & ctrl PIO SMs so they are waiting for a trigger
123 pio_sm_exec(pulse_pio, dac_sm, pio_encode_jmp(dac_pio_sm_offset));
124 pio_sm_exec(pulse_pio, ctrl_sm, pio_encode_jmp(ctrl_pio_sm_offset));
125
126 printf("DAC: transfers %lu\n", dma_channel_hw_addr(dac_dma_chan)->transfer_count);
127 printf("DAC: transfers %lu\n", dma_channel_hw_addr(ctrl_dma_chan)->transfer_count);
128
129 // Setup next pulse data & ctrl DMA addresses
130 dma_channel_wait_for_finish_blocking(dac_dma_chan);
131 dma_channel_set_read_addr(dac_dma_chan, pulse_data, true);
132 dma_channel_wait_for_finish_blocking(ctrl_dma_chan);
133 dma_channel_set_read_addr(ctrl_dma_chan, pulse_ctrl, true);
134
135 // Manually trigger DAQ SM (cleared by SM)
136 pio0->irq_force = 1 << 0;
137
138 // 'scope trigger
139 gpio_put(2, 1);
140 gpio_put(2, 0);
102 } 141 }
103 142
104 // Calculate pulse shape data 143 // Calculate pulse shape data
105 // TODO: predistortion, proper sense, gate, phase, active, T/R switch 144 // TODO: predistortion, proper sense, gate, phase, active, T/R switch
106 // Could encode them as bit stream like data but more compact would be 145 // Could encode them as bit stream like data but more compact would be
176 215
177 dcscale = qdiv(qsub(qint(256), qint(dcofs)), qint(255)); 216 dcscale = qdiv(qsub(qint(256), qint(dcofs)), qint(255));
178 qsprint(dcscale, tmps, sizeof(tmps)); 217 qsprint(dcscale, tmps, sizeof(tmps));
179 printf("dcscale = %s\n", tmps); 218 printf("dcscale = %s\n", tmps);
180 219
181 memset(pulse_data, 0, sizeof(pulse_data)); 220 memset(pulse_data, 0, datalen);
182 memset(pulse_ctrl, 0, sizeof(pulse_ctrl)); 221 memset(pulse_ctrl, 0, datalen);
183 idx = 0; 222 idx = 0;
184 223
185 // Up slew 224 // Up slew
186 for (uint16_t i = 0; i < slew1; i++) { 225 for (uint16_t i = 0; i < slew1; i++) {
187 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1))); 226 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1)));
226 for (uint16_t i = 0; i < shapesamples; i++) { 265 for (uint16_t i = 0; i < shapesamples; i++) {
227 data[idx++] = data[bit1stopup - i]; 266 data[idx++] = data[bit1stopup - i];
228 // Could replace this with a separate loop to poke it into place 267 // Could replace this with a separate loop to poke it into place
229 // Similarly for TR switch when implemented 268 // Similarly for TR switch when implemented
230 if (i == 0 && c == 0) 269 if (i == 0 && c == 0)
231 ctrl[idx] = ctrltmp | SENSE; 270 ctrl[idx] = ctrltmp | SENSE1;
232 else 271 else
233 ctrl[idx] = ctrltmp; 272 ctrl[idx] = ctrltmp;
234 } 273 }
235 274
236 // Code gap 275 // Code gap
246 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(slew2 - i)), qint(slew2))); 285 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(slew2 - i)), qint(slew2)));
247 ctrl[idx] |= PACTIVE; 286 ctrl[idx] |= PACTIVE;
248 } 287 }
249 288
250 data[idx++] = 0; 289 data[idx++] = 0;
251 290 ctrl[idx] = 0;
252 return idx; 291
292 return idx + 1;
253 } 293 }
254 294
255 int 295 int
256 main(void) { 296 main(void) {
257 absolute_time_t then, now; 297 absolute_time_t then, now;
270 gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); 310 gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
271 gpio_init(2); 311 gpio_init(2);
272 gpio_set_dir(2, GPIO_OUT); 312 gpio_set_dir(2, GPIO_OUT);
273 313
274 #if 0 314 #if 0
315 // GPIO tester to check breadboard wiring
275 for (unsigned i = 7; i < 7 + 9; i++) { 316 for (unsigned i = 7; i < 7 + 9; i++) {
276 printf("GPIO %d\n", i); 317 printf("GPIO %d\n", i);
277 gpio_init(i); 318 gpio_init(i);
278 gpio_set_dir(i, GPIO_OUT); 319 gpio_set_dir(i, GPIO_OUT);
279 printf("on\n"); 320 printf("on\n");
315 diff, idx, (float)diff * 1000.0 / idx); 356 diff, idx, (float)diff * 1000.0 / idx);
316 //__breakpoint(); 357 //__breakpoint();
317 358
318 // Load the DAC program, and configure a free state machine 359 // Load the DAC program, and configure a free state machine
319 // to run the program. 360 // to run the program.
320 pulse_pio_sm_offset = pio_add_program(pulse_pio, &dac_program); 361 dac_pio_sm_offset = pio_add_program(pulse_pio, &dac_program);
321 pulse_sm = pio_claim_unused_sm(pulse_pio, true); 362 if (dac_pio_sm_offset < 0) {
363 printf("Unable to load DAC program\n");
364 __breakpoint();
365 }
366 dac_sm = pio_claim_unused_sm(pulse_pio, true);
322 // Data is GPIO7 to GPIO14, clock is GPIO15 367 // Data is GPIO7 to GPIO14, clock is GPIO15
323 // Clock divisor of 2 so it runs at 60MHz and 368 // Clock divisor of 2 so it runs at 60MHz and
324 // generates a 30MHz clock 369 // generates a 30MHz clock
325 dac_program_init(pulse_pio, pulse_sm, pulse_pio_sm_offset, DACOUT_GPIO, 2); 370 dac_program_init(pulse_pio, dac_sm, dac_pio_sm_offset, DACOUT_GPIO, 2);
326 371
327 // Configure a channel to write 32 bits at a time to PIO0 372 // Configure a channel to write 32 bits at a time to PIO0
328 // SM0's TX FIFO, paced by the data request signal from that peripheral. 373 // SM0's TX FIFO, paced by the data request signal from that peripheral.
329 dma_chan = dma_claim_unused_channel(true); 374 dac_dma_chan = dma_claim_unused_channel(true);
330 dma_channel_config dmac = dma_channel_get_default_config(dma_chan); 375 dma_channel_config dac_dmac = dma_channel_get_default_config(dac_dma_chan);
331 channel_config_set_transfer_data_size(&dmac, DMA_SIZE_32); 376 channel_config_set_transfer_data_size(&dac_dmac, DMA_SIZE_32);
332 channel_config_set_read_increment(&dmac, true); 377 channel_config_set_read_increment(&dac_dmac, true);
333 channel_config_set_dreq(&dmac, DREQ_PIO0_TX0); 378 channel_config_set_dreq(&dac_dmac, PIO_DREQ_NUM(pulse_pio, dac_sm, true));
334 379
335 dma_channel_configure( 380 dma_channel_configure(
336 dma_chan, 381 dac_dma_chan,
337 &dmac, 382 &dac_dmac,
338 &pio0_hw->txf[0], // Write address (only need to set this once) 383 &pulse_pio->txf[dac_sm], // Write address
339 NULL, // Don't provide a read address yet 384 pulse_data, // Pulse data
340 (idx + 3) >> 2, // Transfer count (round up to 4 bytes) 385 (idx + 3) >> 2, // Transfer count (round up to 4 bytes)
341 false // Don't start yet 386 true // Start, SM will wait for trigger
342 ); 387 );
343 388
344 // Tell the DMA to raise IRQ line 0 when the channel finishes a block 389 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
345 dma_channel_set_irq0_enabled(dma_chan, true); 390 dma_channel_set_irq0_enabled(dac_dma_chan, true);
346 391
347 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted 392 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
348 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); 393 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
349 irq_set_enabled(DMA_IRQ_0, true); 394 irq_set_enabled(DMA_IRQ_0, true);
350 395
396 // Load the ctrl program, and configure a free state machine
397 // to run the program.
398 ctrl_pio_sm_offset = pio_add_program(pulse_pio, &ctrl_program);
399 if (ctrl_pio_sm_offset < 0) {
400 printf("Unable to load ctrl program\n");
401 __breakpoint();
402 }
403 ctrl_sm = pio_claim_unused_sm(pulse_pio, true);
404 ctrl_program_init(pulse_pio, ctrl_sm, ctrl_pio_sm_offset, CTRLOUT_GPIO, 2);
405
406 // Configure a channel to write 32 bits at a time to PIO0
407 // SM0's TX FIFO, paced by the data request signal from that peripheral.
408 ctrl_dma_chan = dma_claim_unused_channel(true);
409 dma_channel_config ctrl_dmac = dma_channel_get_default_config(ctrl_dma_chan);
410 channel_config_set_transfer_data_size(&ctrl_dmac, DMA_SIZE_32);
411 channel_config_set_read_increment(&ctrl_dmac, true);
412 channel_config_set_dreq(&ctrl_dmac, PIO_DREQ_NUM(pulse_pio, ctrl_sm, true));
413
414 dma_channel_configure(
415 ctrl_dma_chan,
416 &ctrl_dmac,
417 &pulse_pio->txf[ctrl_sm], // Write address
418 pulse_ctrl, // Ctrl data
419 (idx + 3) >> 2, // Transfer count (round up to 4 bytes)
420 true // Start, SM will wait for trigger
421 );
422 // No IRQ, piggyback on the data one
423
424 #if 0
351 // Load the trigger program, and configure a free state machine 425 // Load the trigger program, and configure a free state machine
352 // to run the program. 426 // to run the program.
353 uint trigger_pio_sm_offset = pio_add_program(pulse_pio, &trigger_program); 427 uint trigger_pio_sm_offset = pio_add_program(pulse_pio, &trigger_program);
428 if (trigger_pio_sm_offset < 0) {
429 printf("Unable to load trigger program\n");
430 __breakpoint();
431 }
354 uint trigger_sm = pio_claim_unused_sm(pulse_pio, true); 432 uint trigger_sm = pio_claim_unused_sm(pulse_pio, true);
355 trigger_program_init(pulse_pio, trigger_sm, trigger_pio_sm_offset, TRIGIN_GPIO, 2); 433 trigger_program_init(pulse_pio, trigger_sm, trigger_pio_sm_offset, TRIGIN_GPIO, 2);
356 434 #endif
357 // 435 //
358 // Setup PWM 436 // Setup PWM
359 // Used here to output a trigger which gets fed back into the trigger SM 437 // Used here to output a trigger which gets fed back into the trigger SM
360 // 438 //
361 // 120MHz / 250 = 480kHz base 439 // 120MHz / 250 = 480kHz base
375 pwm_set_enabled(slice_num, 1); 453 pwm_set_enabled(slice_num, 1);
376 pwm_set_irq_enabled(slice_num, true); 454 pwm_set_irq_enabled(slice_num, true);
377 irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap); 455 irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap);
378 irq_set_enabled(PWM_IRQ_WRAP, true); 456 irq_set_enabled(PWM_IRQ_WRAP, true);
379 457
380 // Setup next pulse DMA address
381 // XXX: This works but telling dma_channel_configure above to start
382 // immediately does not
383 dma_channel_set_read_addr(dma_chan, pulse_data, true);
384
385 // Everything else from this point is interrupt-driven. The processor has 458 // Everything else from this point is interrupt-driven. The processor has
386 // time to sit and think about its early retirement -- maybe open a bakery? 459 // time to sit and think about its early retirement -- maybe open a bakery?
387 while (true) { 460 while (true) {
388 gpio_put(PICO_DEFAULT_LED_PIN, 1); 461 gpio_put(PICO_DEFAULT_LED_PIN, 1);
389 sleep_ms(100); 462 sleep_ms(100);