Mercurial > ~darius > hgwebdir.cgi > modulator
annotate modulator.c @ 7:4ad473648949
Copy pulse up in reverse for pulse down.
Copy first pulse for subsequent pulses.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Sun, 16 Feb 2025 10:09:05 +1030 |
parents | 5bed069f0c33 |
children | 0249d0cecac4 |
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" |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
40 |
5 | 41 // 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
|
42 // Modified to be Q20.12 rather than Q16.16 |
5 | 43 #include "q/q.h" |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
44 |
5 | 45 #include "shaped-trap.h" |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
46 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
47 static int dma_chan; |
5 | 48 uint8_t pulse_data[65536]; |
49 uint8_t pulse_ctrl[65536]; | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
50 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
51 void |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
52 dma_handler(void) { |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
53 // Clear the interrupt request. |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
54 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
|
55 // Give the channel a new wave table entry to read from, and re-trigger it |
5 | 56 //dma_channel_set_read_addr(dma_chan, shaped_trap_dat_start, true); |
57 } | |
58 | |
59 unsigned slice_num = 0; | |
60 | |
61 void | |
62 pwm_wrap(void) { | |
63 pwm_clear_irq(slice_num); | |
64 #if 0 | |
65 static unsigned state = 0; | |
66 | |
67 gpio_put(PICO_DEFAULT_LED_PIN, state); | |
68 state = !state; | |
69 #endif | |
70 | |
71 // Trigger another pulse read out | |
72 dma_channel_set_read_addr(dma_chan, pulse_data, true); | |
73 } | |
74 | |
75 // Calculate pulse shape data | |
76 // TODO: sense, gate, phase, active, T/R switch | |
77 // Could encode them as bit stream like data but more compact would be | |
78 // (say) a list of counts to toggle pins at | |
79 #define SENSE 0x01 | |
80 #define GATE 0x02 | |
81 #define PHINV 0x04 | |
82 #define PACTIVE 0x08 | |
83 | |
84 // Need to add pre/postgate/sense/phase counters | |
85 unsigned | |
86 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
|
87 uint32_t shapesamples, nsamples, idx, bit1startup, bit1stopup; |
5 | 88 q_t dcscale, stepsize; |
89 char tmps[20]; | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
90 interp_config cfg; |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
91 |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
92 // Setup lane 0 to generate index into shape table |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
93 // 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
|
94 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
95 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
|
96 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
|
97 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
|
98 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
|
99 |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
100 // Setup lane 1 to LERP each sample pair |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
101 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
102 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
|
103 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
|
104 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
|
105 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
|
106 |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
107 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
|
108 interp0->base[2] = (uintptr_t)shape; // Start of shape table |
5 | 109 |
110 dcscale = qdiv(qsub(qint(255), qint(dcofs)), qint(255)); | |
111 qsprint(dcscale, tmps, sizeof(tmps)); | |
112 printf("dcscale = %s\n", tmps); | |
113 | |
114 if (ncode == 1) { | |
115 // Number of samples for half of the pulse | |
116 // Do division first so we don't overflow Q16.16 | |
117 shapesamples = qtoi(qmul(qdiv(qint(plen), qint(100)), qint(shapelen / 2))); | |
118 // Number of samples for everything | |
119 nsamples = shapesamples * 2 + slew1 + slew2; | |
120 } else { | |
121 shapesamples = plen / 2; | |
122 nsamples = shapesamples * 2 * ncode + codegap * (ncode - 1) + slew1 + slew2; | |
123 } | |
124 | |
125 // Number of samples per step in the pulse shape | |
126 stepsize = qdiv(qint(shapesamples), qint(shapelen)); | |
127 qsprint(stepsize, tmps, sizeof(tmps)); | |
128 printf("shapelen = %d shapesamples = %lu nsamples = %lu stepsize = %s\n", shapelen, shapesamples, nsamples, tmps); | |
129 | |
130 if (nsamples > datalen) { | |
131 printf("Pulse too long (%ld > %u)\n", nsamples, datalen); | |
132 return 0; | |
133 } | |
134 if (shapesamples < 2) { | |
135 printf("Pulse too short (%lu < %d)\n", shapesamples, 2); | |
136 return 0; | |
137 } | |
138 if (qtoi(shapesamples) > 65535) { | |
139 printf("Shape too long (%u > %d)\n", qtoi(shapesamples), 65535); | |
140 return 0; | |
141 } | |
142 idx = 0; | |
143 | |
144 // Up slew | |
145 for (uint16_t i = 0; i < slew1; i++) { | |
146 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1))); | |
147 ctrl[idx] |= PACTIVE; | |
148 } | |
149 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
|
150 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
151 bit1startup = idx; |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
152 |
5 | 153 uint ctrltmp = PACTIVE; |
154 if (code[c] == '0') | |
155 ctrltmp |= PHINV; | |
156 | |
157 // Pulse up | |
158 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
|
159 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
160 data[idx++] = dcofs + qtoi(qmul(qint(shape[qtoi(qdiv(qint(i), stepsize))]), dcscale)); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
161 else |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
162 // 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
|
163 data[idx++] = data[bit1startup + i]; |
5 | 164 ctrl[idx] = ctrltmp; |
165 } | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
166 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
167 bit1stopup = idx - 1; |
5 | 168 // Pulse down |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
169 // Since the pulse is symmetrical just copy the up slope in reverse |
5 | 170 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
|
171 data[idx++] = data[bit1stopup - i]; |
5 | 172 // Could replace this with a separate loop to poke it into place |
173 // Similarly for TR switch when implemented | |
174 if (i == 0 && c == 0) | |
175 ctrl[idx] = ctrltmp | SENSE; | |
176 else | |
177 ctrl[idx] = ctrltmp; | |
178 } | |
179 | |
180 // Code gap | |
181 if (c < ncode - 1) | |
182 for (uint16_t i = 0; i < codegap; i++) { | |
183 data[idx++] = dcofs; | |
184 ctrl[idx] = ctrltmp; | |
185 } | |
186 } | |
187 | |
188 // Down slew | |
189 for (uint16_t i = 0; i < slew2; i++) { | |
190 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(slew2 - i)), qint(slew2))); | |
191 ctrl[idx] |= PACTIVE; | |
192 } | |
193 return idx - 1; | |
194 } | |
195 | |
196 // As per hello_interp.c | |
197 void interp_test(uint8_t *data, const uint8_t *shape) { | |
198 interp_config cfg; | |
199 const int uv_fractional_bits = 12; | |
200 | |
201 // Step size is 0.25 (ie stretching by 4x) | |
202 unsigned step = (1 << uv_fractional_bits) / 4; | |
203 | |
204 puts("interp_test\n"); | |
205 // Setup lane 0 to generate index into shape table | |
6 | 206 // Mask start is 0 because we use 8 bit samples |
5 | 207 cfg = interp_default_config(); |
208 interp_config_set_shift(&cfg, uv_fractional_bits); | |
209 interp_config_set_mask(&cfg, 0, 32 - uv_fractional_bits); | |
210 interp_config_set_blend(&cfg, true); | |
211 interp_set_config(interp0, 0, &cfg); | |
212 | |
213 // Setup lane 1 to LERP each sample pair | |
214 cfg = interp_default_config(); | |
215 interp_config_set_shift(&cfg, uv_fractional_bits - 8); | |
216 interp_config_set_signed(&cfg, false); | |
217 interp_config_set_cross_input(&cfg, true); // unsigned blending | |
218 interp_set_config(interp0, 1, &cfg); | |
219 | |
220 interp0->accum[0] = 0; // Initial offset into shape table | |
221 interp0->base[2] = (uintptr_t)shape; // Start of shape table | |
222 for (unsigned i = 0; i < 122 * 4; i++) { | |
223 // Get sample pair | |
224 uint8_t *sample_pair = (uint8_t *) interp0->peek[2]; | |
225 // Ask lane 1 for a LERP, using the lane 0 accumulator | |
226 interp0->base[0] = sample_pair[0]; | |
227 interp0->base[1] = sample_pair[1]; | |
228 uint32_t peek1 = interp0->peek[1]; | |
229 uint32_t add_raw1 = interp0->add_raw[1]; | |
230 data[i] = peek1; | |
231 printf("%d\t(%lu%% between %d and %d) %lu\n", | |
232 (int)peek1, | |
233 100 * (add_raw1 & 0xff) / 0xff, | |
234 sample_pair[0], sample_pair[1], | |
235 interp_get_accumulator(interp0, 0)); | |
236 interp0->add_raw[0] = step; | |
237 } | |
238 puts("done"); | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
239 } |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
240 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
241 int |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
242 main(void) { |
5 | 243 absolute_time_t then, now; |
244 | |
245 // Set sysclk to 120MHz | |
246 set_sys_clock_khz(120000, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
247 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
248 stdio_init_all(); |
5 | 249 printf("\n\n\nIniting\n"); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
250 |
5 | 251 // Needed otherwise timer related functions hang under debugging |
252 // https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639 | |
253 timer_hw->dbgpause = 0; | |
254 | |
255 gpio_init(PICO_DEFAULT_LED_PIN); | |
256 gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | |
257 | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
258 //interp_test(pulse_data, shaped_trap); |
5 | 259 |
260 uint32_t idx; | |
261 uint16_t plen = 4000; | |
262 char *code = "1110010"; | |
263 //char *code = "10"; | |
264 uint8_t codegap = 4; | |
265 uint8_t slew1 = 10; | |
266 uint8_t slew2 = 10; | |
267 uint8_t dcofs = 110; | |
268 memset(pulse_data, 0, sizeof(pulse_data)); | |
269 memset(pulse_ctrl, 0, sizeof(pulse_ctrl)); | |
270 then = get_absolute_time(); | |
271 if ((idx = compute_pulse(pulse_data, pulse_ctrl, sizeof(pulse_data), | |
272 plen, code, strlen(code), | |
273 shaped_trap, sizeof(shaped_trap), | |
274 codegap, slew1, slew2, dcofs)) == 0) { | |
275 printf("Failed to compute pulse\n"); | |
276 while (1) | |
277 ; | |
278 } | |
279 now = get_absolute_time(); | |
280 printf("Pulse computation took %lld usec and created %lu samples\n", absolute_time_diff_us(then, now), idx); | |
281 | |
282 pwm_config c = pwm_get_default_config(); | |
283 // 120MHz / 250 = 480kHz base | |
284 // Maximum divisor is only 256 which limits the low end, | |
285 // could further subdivide in the IRQ handler | |
286 pwm_config_set_clkdiv_int(&c, 250); | |
287 // 8Hz | |
288 pwm_config_set_wrap(&c, 60000 - 1); | |
289 pwm_init(slice_num, &c, true); | |
290 pwm_clear_irq(slice_num); | |
291 pwm_set_irq_enabled(slice_num, true); | |
292 irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap); | |
293 irq_set_enabled(PWM_IRQ_WRAP, true); | |
294 pwm_init(slice_num, &c, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
295 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
296 // Load the clocked_input program, and configure a free state machine |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
297 // to run the program. |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
298 PIO pio = pio0; |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
299 uint offset = pio_add_program(pio, &dac_program); |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
300 uint sm = pio_claim_unused_sm(pio, true); |
2
0d653f60dec8
Actually get data moving out.
Daniel O'Connor <darius@dons.net.au>
parents:
0
diff
changeset
|
301 // XXX: I would prefer starting at GPIO16 but in that case the top 2 |
0d653f60dec8
Actually get data moving out.
Daniel O'Connor <darius@dons.net.au>
parents:
0
diff
changeset
|
302 // bits don't seem to work |
5 | 303 // Clock divisor of 2 so it runs at 60MHz and |
304 // generates a 30MHz clock | |
305 dac_program_init(pio, sm, offset, 14, 2); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
306 |
5 | 307 // Configure a channel to write the same word (8 bits) repeatedly to PIO0 |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
308 // SM0's TX FIFO, paced by the data request signal from that peripheral. |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
309 dma_chan = dma_claim_unused_channel(true); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
310 dma_channel_config dmac = dma_channel_get_default_config(dma_chan); |
5 | 311 // XXX: need to get pulse generator to pad to 32 bits |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
312 channel_config_set_transfer_data_size(&dmac, DMA_SIZE_32); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
313 channel_config_set_read_increment(&dmac, true); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
314 channel_config_set_dreq(&dmac, DREQ_PIO0_TX0); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
315 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
316 dma_channel_configure( |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
317 dma_chan, |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
318 &dmac, |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
319 &pio0_hw->txf[0], // Write address (only need to set this once) |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
320 NULL, // Don't provide a read address yet |
5 | 321 idx >> 2, // Transfer count |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
322 false // Don't start yet |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
323 ); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
324 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
325 // Tell the DMA to raise IRQ line 0 when the channel finishes a block |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
326 dma_channel_set_irq0_enabled(dma_chan, true); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
327 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
328 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
329 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
330 irq_set_enabled(DMA_IRQ_0, true); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
331 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
332 // 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
|
333 // 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
|
334 while (true) { |
5 | 335 dma_channel_wait_for_finish_blocking(dma_chan); |
336 gpio_put(PICO_DEFAULT_LED_PIN, 1); | |
337 sleep_ms(100); | |
338 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
|
339 sleep_ms(100); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
340 } |
5 | 341 |
342 __breakpoint(); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
343 } |