Mercurial > ~darius > hgwebdir.cgi > modulator
annotate modulator.c @ 9:3acdebd7eec7
Make it actually work
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Fri, 21 Feb 2025 17:27:22 +1030 |
parents | 0249d0cecac4 |
children | 98880b18bcc1 |
rev | line source |
---|---|
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
1 /****************************************************************** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
2 ******************************************************************* |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
3 ** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
4 ** This is proprietary unpublished source code, property |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
5 ** of Genesis Software. Use or disclosure without prior |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
6 ** agreement is expressly prohibited. |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
7 ** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
8 ** Copyright (c) 2021 Genesis Software, all rights reserved. |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
9 ** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
10 ******************************************************************* |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
11 ******************************************************************/ |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
12 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
13 /* |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
14 ** MODULATOR.C |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
15 ** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
16 ** Create modulation shape |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
17 ** |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
18 */ |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
19 |
5 | 20 #include <stdio.h> |
21 #include <string.h> | |
22 #include "bitstring.h" | |
23 | |
24 #pragma GCC diagnostic push | |
25 #pragma GCC diagnostic ignored "-Wtype-limits" | |
26 #pragma GCC diagnostic ignored "-Wsign-compare" | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
27 #include "pico/stdlib.h" |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
28 #include "hardware/clocks.h" |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
29 #include "hardware/dma.h" |
5 | 30 #include "hardware/interp.h" |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
31 #include "hardware/irq.h" |
5 | 32 #include "hardware/pll.h" |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
33 #include "hardware/pio.h" |
5 | 34 #include "hardware/pwm.h" |
35 #include "hardware/structs/pll.h" | |
36 #include "hardware/structs/clocks.h" | |
37 #pragma GCC diagnostic pop | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
38 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
39 #include "dac.pio.h" |
9 | 40 #include "trigger.pio.h" |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
41 |
5 | 42 // https://github.com/howerj/q |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
43 // Modified to be Q20.12 rather than Q16.16 |
5 | 44 #include "q/q.h" |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
45 |
5 | 46 #include "shaped-trap.h" |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
47 |
9 | 48 // Pulse control bits |
49 #define SENSE 0x01 | |
50 #define GATE 0x02 | |
51 #define PHINV 0x04 | |
52 #define PACTIVE 0x08 | |
53 | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
54 static int dma_chan; |
5 | 55 uint8_t pulse_data[65536]; |
56 uint8_t pulse_ctrl[65536]; | |
9 | 57 unsigned slice_num = 0; |
58 PIO pulse_pio; | |
59 uint pulse_sm; | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
60 |
9 | 61 /* |
62 * Use a DMA channel to feed PIO0 SM0 with pulse data. | |
63 * Each DMA transfer is a single pulse. | |
64 * | |
65 * The PIO state machine waits to be triggered before starting | |
66 * so we can use another state machine to look for the trigger edge. | |
67 * | |
68 * When the DMA is done the IRQ handler will configure it for the next | |
69 * pulse (or not if it should stop). ie reset the PIO state machine | |
70 * back to waiting for an edge and re-arm the DMA. | |
71 */ | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
72 void |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
73 dma_handler(void) { |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
74 // Clear the interrupt request. |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
75 dma_hw->ints0 = 1u << dma_chan; |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
76 // Give the channel a new wave table entry to read from, and re-trigger it |
5 | 77 //dma_channel_set_read_addr(dma_chan, shaped_trap_dat_start, true); |
9 | 78 // Reset pulse state machine back to waiting for trigger |
79 //pio_sm_exec(pulse_pio, pulse_sm, pio_encode_jump(0); | |
5 | 80 } |
81 | |
82 | |
83 void | |
84 pwm_wrap(void) { | |
85 pwm_clear_irq(slice_num); | |
86 #if 0 | |
87 static unsigned state = 0; | |
88 | |
89 gpio_put(PICO_DEFAULT_LED_PIN, state); | |
90 state = !state; | |
91 #endif | |
92 | |
93 // Trigger another pulse read out | |
94 dma_channel_set_read_addr(dma_chan, pulse_data, true); | |
9 | 95 gpio_put(2, 1); |
96 gpio_put(2, 0); | |
5 | 97 } |
98 | |
99 // Calculate pulse shape data | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
100 // TODO: predistortion, proper sense, gate, phase, active, T/R switch |
5 | 101 // Could encode them as bit stream like data but more compact would be |
102 // (say) a list of counts to toggle pins at | |
103 // Need to add pre/postgate/sense/phase counters | |
104 unsigned | |
105 compute_pulse(uint8_t *data, uint8_t *ctrl, unsigned datalen, uint16_t plen, char *code, uint8_t ncode, const uint8_t *shape, uint8_t shapelen, uint8_t codegap, uint8_t slew1, uint8_t slew2, uint8_t dcofs) { | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
106 uint32_t shapesamples, nsamples, idx, bit1startup, bit1stopup; |
5 | 107 q_t dcscale, stepsize; |
108 char tmps[20]; | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
109 interp_config cfg; |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
110 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
111 if (ncode == 1) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
112 // Number of samples for half of the pulse |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
113 // Do division first so we don't overflow Q16.16 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
114 shapesamples = qtoi(qmul(qdiv(qint(plen), qint(100)), qint(shapelen / 2))); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
115 // Number of samples for everything |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
116 // XXX: Need the +1 otherwise slew2 is truncated |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
117 nsamples = shapesamples * 2 + slew1 + slew2 + 1; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
118 } else { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
119 shapesamples = plen / 2; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
120 nsamples = shapesamples * 2 * ncode + codegap * (ncode - 1) + slew1 + slew2 + 1; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
121 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
122 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
123 // Number of steps per samples in the pulse shape |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
124 stepsize = qdiv(qint(shapelen), qint(shapesamples)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
125 qsprint(stepsize, tmps, sizeof(tmps)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
126 printf("shapelen = %d shapesamples = %lu nsamples = %lu stepsize = %s\n", shapelen, shapesamples, nsamples, tmps); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
127 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
128 // Check the requested pulse will not overflow given data |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
129 if (nsamples > datalen) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
130 printf("Pulse too long (%ld > %u)\n", nsamples, datalen); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
131 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
132 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
133 // Check it is not too short |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
134 if (shapesamples < 2) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
135 printf("Pulse too short (%lu < %d)\n", shapesamples, 2); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
136 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
137 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
138 // Or too long (will overflow for loop variable) |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
139 if (qtoi(shapesamples) > 65535) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
140 printf("Shape too long (%u > %d)\n", qtoi(shapesamples), 65535); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
141 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
142 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
143 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
144 // Setup interp 0 lane 0 to generate index into shape table |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
145 // Mask start is 0 because we use 8 bit samples |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
146 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
147 interp_config_set_shift(&cfg, QBITS); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
148 interp_config_set_mask(&cfg, 0, 32 - QBITS); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
149 interp_config_set_blend(&cfg, true); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
150 interp_set_config(interp0, 0, &cfg); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
151 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
152 // Setup interp 0 lane 1 to LERP each sample pair |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
153 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
154 interp_config_set_shift(&cfg, QBITS - 8); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
155 interp_config_set_signed(&cfg, false); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
156 interp_config_set_cross_input(&cfg, true); // unsigned blending |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
157 interp_set_config(interp0, 1, &cfg); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
158 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
159 // Setup interp 1 lane 0 to clamp 0-255 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
160 cfg = interp_default_config(); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
161 interp_config_set_clamp(&cfg, true); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
162 interp_config_set_shift(&cfg, 0); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
163 interp_config_set_mask(&cfg, 0, 8); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
164 interp_config_set_signed(&cfg, false); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
165 interp_set_config(interp1, 0, &cfg); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
166 interp1->base[0] = 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
167 interp1->base[1] = 255; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
168 |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
169 interp0->accum[0] = 0; // Initial offset into shape table |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
170 interp0->base[2] = (uintptr_t)shape; // Start of shape table |
5 | 171 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
172 dcscale = qdiv(qsub(qint(256), qint(dcofs)), qint(255)); |
5 | 173 qsprint(dcscale, tmps, sizeof(tmps)); |
174 printf("dcscale = %s\n", tmps); | |
175 | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
176 memset(pulse_data, 0, sizeof(pulse_data)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
177 memset(pulse_ctrl, 0, sizeof(pulse_ctrl)); |
5 | 178 idx = 0; |
179 | |
180 // Up slew | |
181 for (uint16_t i = 0; i < slew1; i++) { | |
182 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1))); | |
183 ctrl[idx] |= PACTIVE; | |
184 } | |
185 for (uint16_t c = 0; c < ncode; c++) { | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
186 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
187 bit1startup = idx; |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
188 |
5 | 189 uint ctrltmp = PACTIVE; |
190 if (code[c] == '0') | |
191 ctrltmp |= PHINV; | |
192 | |
193 // Pulse up | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
194 if (c == 0) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
195 interp0->accum[0] = 0; // Initial offset into shape table |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
196 interp0->base[2] = (uintptr_t)shape; // Start of shape table |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
197 } |
5 | 198 for (uint16_t i = 0; i < shapesamples; i++) { |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
199 if (c == 0) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
200 // Get sample pair |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
201 uint8_t *sample_pair = (uint8_t *) interp0->peek[2]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
202 // Ask lane 1 for a LERP, using the lane 0 accumulator |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
203 interp0->base[0] = sample_pair[0]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
204 interp0->base[1] = sample_pair[1]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
205 uint8_t peek = interp0->peek[1]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
206 // Apply DC offset scaling & clamp |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
207 interp1->accum[0] = dcofs + qtoi(qmul(qint(peek), dcscale)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
208 data[idx++] = interp1->peek[0]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
209 // Update interpolator for next point |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
210 interp0->add_raw[0] = stepsize; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
211 } else |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
212 // Already done it before, just copy the previous instance |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
213 data[idx++] = data[bit1startup + i]; |
5 | 214 ctrl[idx] = ctrltmp; |
215 } | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
216 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
217 bit1stopup = idx - 1; |
5 | 218 // Pulse down |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
219 // Since the pulse is symmetrical just copy the up slope in reverse |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
220 // XXX: if we had asymmetrical predistortion this wouldn't be true |
5 | 221 for (uint16_t i = 0; i < shapesamples; i++) { |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
222 data[idx++] = data[bit1stopup - i]; |
5 | 223 // Could replace this with a separate loop to poke it into place |
224 // Similarly for TR switch when implemented | |
225 if (i == 0 && c == 0) | |
226 ctrl[idx] = ctrltmp | SENSE; | |
227 else | |
228 ctrl[idx] = ctrltmp; | |
229 } | |
230 | |
231 // Code gap | |
232 if (c < ncode - 1) | |
233 for (uint16_t i = 0; i < codegap; i++) { | |
234 data[idx++] = dcofs; | |
235 ctrl[idx] = ctrltmp; | |
236 } | |
237 } | |
238 | |
239 // Down slew | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
240 for (uint16_t i = 0; i < slew2 + 1; i++) { |
5 | 241 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(slew2 - i)), qint(slew2))); |
242 ctrl[idx] |= PACTIVE; | |
243 } | |
244 return idx - 1; | |
245 } | |
246 | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
247 int |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
248 main(void) { |
5 | 249 absolute_time_t then, now; |
250 | |
251 // Set sysclk to 120MHz | |
252 set_sys_clock_khz(120000, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
253 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
254 stdio_init_all(); |
5 | 255 printf("\n\n\nIniting\n"); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
256 |
5 | 257 // Needed otherwise timer related functions hang under debugging |
258 // https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639 | |
259 timer_hw->dbgpause = 0; | |
260 | |
261 gpio_init(PICO_DEFAULT_LED_PIN); | |
262 gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | |
9 | 263 gpio_init(2); |
264 gpio_set_dir(2, GPIO_OUT); | |
265 #if 0 | |
266 for (unsigned i = 7; i < 7 + 9; i++) { | |
267 printf("GPIO %d\n", i); | |
268 gpio_init(i); | |
269 gpio_set_dir(i, GPIO_OUT); | |
270 printf("on\n"); | |
271 gpio_put(i, 1); | |
272 __breakpoint(); | |
273 printf("off\n"); | |
274 gpio_put(i, 0); | |
275 __breakpoint(); | |
276 } | |
277 #endif | |
5 | 278 |
279 uint32_t idx; | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
280 uint16_t plen; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
281 char *code; |
9 | 282 if (1) { |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
283 plen = 8000; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
284 code = "1110010"; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
285 } else { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
286 plen = 53000; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
287 code = "1"; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
288 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
289 |
5 | 290 uint8_t codegap = 4; |
291 uint8_t slew1 = 10; | |
292 uint8_t slew2 = 10; | |
293 uint8_t dcofs = 110; | |
294 then = get_absolute_time(); | |
295 if ((idx = compute_pulse(pulse_data, pulse_ctrl, sizeof(pulse_data), | |
296 plen, code, strlen(code), | |
297 shaped_trap, sizeof(shaped_trap), | |
298 codegap, slew1, slew2, dcofs)) == 0) { | |
299 printf("Failed to compute pulse\n"); | |
300 while (1) | |
301 ; | |
302 } | |
303 now = get_absolute_time(); | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
304 unsigned long long diff = absolute_time_diff_us(then, now); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
305 printf("Pulse computation took %lld usec and created %lu samples - %.1f nsec/sample\n", |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
306 diff, idx, (float)diff * 1000.0 / idx); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
307 __breakpoint(); |
9 | 308 |
309 // Load the clocked_input program, and configure a free state machine | |
310 // to run the program. | |
311 PIO pulse_pio = pio0; | |
312 uint offset = pio_add_program(pulse_pio, &dac_program); | |
313 uint pulse_sm = pio_claim_unused_sm(pulse_pio, true); | |
314 // Data is GPIO7 to GPIO14, clock is GPIO15 | |
315 // Clock divisor of 2 so it runs at 60MHz and | |
316 // generates a 30MHz clock | |
317 dac_program_init(pulse_pio, pulse_sm, offset, 7, 2); | |
318 | |
319 // Configure a channel to write 32 bits at a time to PIO0 | |
320 // SM0's TX FIFO, paced by the data request signal from that peripheral. | |
321 dma_chan = dma_claim_unused_channel(true); | |
322 dma_channel_config dmac = dma_channel_get_default_config(dma_chan); | |
323 channel_config_set_transfer_data_size(&dmac, DMA_SIZE_32); | |
324 channel_config_set_read_increment(&dmac, true); | |
325 channel_config_set_dreq(&dmac, DREQ_PIO0_TX0); | |
326 | |
327 dma_channel_configure( | |
328 dma_chan, | |
329 &dmac, | |
330 &pio0_hw->txf[0], // Write address (only need to set this once) | |
331 NULL, // Don't provide a read address yet | |
332 (idx + 1) >> 2, // Transfer count (round up to 4 bytes) | |
333 false // Don't start yet | |
334 ); | |
335 | |
336 // Tell the DMA to raise IRQ line 0 when the channel finishes a block | |
337 dma_channel_set_irq0_enabled(dma_chan, true); | |
338 | |
339 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted | |
340 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); | |
341 irq_set_enabled(DMA_IRQ_0, true); | |
342 | |
5 | 343 // 120MHz / 250 = 480kHz base |
344 // Maximum divisor is only 256 which limits the low end, | |
345 // could further subdivide in the IRQ handler | |
9 | 346 pwm_config c = pwm_get_default_config(); |
5 | 347 pwm_config_set_clkdiv_int(&c, 250); |
348 // 8Hz | |
349 pwm_config_set_wrap(&c, 60000 - 1); | |
350 pwm_init(slice_num, &c, true); | |
351 pwm_clear_irq(slice_num); | |
352 pwm_set_irq_enabled(slice_num, true); | |
353 irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap); | |
354 irq_set_enabled(PWM_IRQ_WRAP, true); | |
355 pwm_init(slice_num, &c, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
356 |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
357 // Everything else from this point is interrupt-driven. The processor has |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
358 // time to sit and think about its early retirement -- maybe open a bakery? |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
359 while (true) { |
5 | 360 dma_channel_wait_for_finish_blocking(dma_chan); |
361 gpio_put(PICO_DEFAULT_LED_PIN, 1); | |
362 sleep_ms(100); | |
363 gpio_put(PICO_DEFAULT_LED_PIN, 0); | |
2
0d653f60dec8
Actually get data moving out.
Daniel O'Connor <darius@dons.net.au>
parents:
0
diff
changeset
|
364 sleep_ms(100); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
365 } |
5 | 366 |
367 __breakpoint(); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
368 } |