Mercurial > ~darius > hgwebdir.cgi > modulator
annotate modulator.c @ 8:0249d0cecac4
Use interpolator to compute pulse up.
Use interpolator to clamp values.
Calculate speed.
Do memory clear in routine to be more honest about the speed.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Sun, 16 Feb 2025 14:36:33 +1030 |
parents | 4ad473648949 |
children | 3acdebd7eec7 |
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 | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
76 // TODO: predistortion, proper sense, gate, phase, active, T/R switch |
5 | 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 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
92 if (ncode == 1) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
93 // 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
|
94 // 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
|
95 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
|
96 // Number of samples for everything |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
97 // 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
|
98 nsamples = shapesamples * 2 + slew1 + slew2 + 1; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
99 } else { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
100 shapesamples = plen / 2; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
101 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
|
102 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
103 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
104 // 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
|
105 stepsize = qdiv(qint(shapelen), qint(shapesamples)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
106 qsprint(stepsize, tmps, sizeof(tmps)); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
107 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
|
108 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
109 // 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
|
110 if (nsamples > datalen) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
111 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
|
112 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
113 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
114 // Check it is not too short |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
115 if (shapesamples < 2) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
116 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
|
117 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
118 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
119 // 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
|
120 if (qtoi(shapesamples) > 65535) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
121 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
|
122 return 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
123 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
124 |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
125 // 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
|
126 // 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
|
127 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
128 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
|
129 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
|
130 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
|
131 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
|
132 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
133 // 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
|
134 cfg = interp_default_config(); |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
135 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
|
136 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
|
137 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
|
138 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
|
139 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
140 // 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
|
141 cfg = interp_default_config(); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
142 interp_config_set_clamp(&cfg, true); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
143 interp_config_set_shift(&cfg, 0); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
144 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
|
145 interp_config_set_signed(&cfg, false); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
146 interp_set_config(interp1, 0, &cfg); |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
147 interp1->base[0] = 0; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
148 interp1->base[1] = 255; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
149 |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
150 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
|
151 interp0->base[2] = (uintptr_t)shape; // Start of shape table |
5 | 152 |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
153 dcscale = qdiv(qsub(qint(256), qint(dcofs)), qint(255)); |
5 | 154 qsprint(dcscale, tmps, sizeof(tmps)); |
155 printf("dcscale = %s\n", tmps); | |
156 | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
157 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
|
158 memset(pulse_ctrl, 0, sizeof(pulse_ctrl)); |
5 | 159 idx = 0; |
160 | |
161 // Up slew | |
162 for (uint16_t i = 0; i < slew1; i++) { | |
163 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(i)), qint(slew1))); | |
164 ctrl[idx] |= PACTIVE; | |
165 } | |
166 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
|
167 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
168 bit1startup = idx; |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
169 |
5 | 170 uint ctrltmp = PACTIVE; |
171 if (code[c] == '0') | |
172 ctrltmp |= PHINV; | |
173 | |
174 // Pulse up | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
175 if (c == 0) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
176 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
|
177 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
|
178 } |
5 | 179 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
|
180 if (c == 0) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
181 // Get sample pair |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
182 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
|
183 // 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
|
184 interp0->base[0] = sample_pair[0]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
185 interp0->base[1] = sample_pair[1]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
186 uint8_t peek = interp0->peek[1]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
187 // Apply DC offset scaling & clamp |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
188 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
|
189 data[idx++] = interp1->peek[0]; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
190 // Update interpolator for next point |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
191 interp0->add_raw[0] = stepsize; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
192 } else |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
193 // 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
|
194 data[idx++] = data[bit1startup + i]; |
5 | 195 ctrl[idx] = ctrltmp; |
196 } | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
197 if (c == 0) |
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
198 bit1stopup = idx - 1; |
5 | 199 // Pulse down |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
200 // 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
|
201 // XXX: if we had asymmetrical predistortion this wouldn't be true |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
202 // In that case probably best to do a single pulse up/down, then |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
203 // add predistortion and copy it to other bits |
5 | 204 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
|
205 data[idx++] = data[bit1stopup - i]; |
5 | 206 // Could replace this with a separate loop to poke it into place |
207 // Similarly for TR switch when implemented | |
208 if (i == 0 && c == 0) | |
209 ctrl[idx] = ctrltmp | SENSE; | |
210 else | |
211 ctrl[idx] = ctrltmp; | |
212 } | |
213 | |
214 // Code gap | |
215 if (c < ncode - 1) | |
216 for (uint16_t i = 0; i < codegap; i++) { | |
217 data[idx++] = dcofs; | |
218 ctrl[idx] = ctrltmp; | |
219 } | |
220 } | |
221 | |
222 // Down slew | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
223 for (uint16_t i = 0; i < slew2 + 1; i++) { |
5 | 224 data[idx++] = qtoi(qdiv(qmul(qint(dcofs), qint(slew2 - i)), qint(slew2))); |
225 ctrl[idx] |= PACTIVE; | |
226 } | |
227 return idx - 1; | |
228 } | |
229 | |
230 // As per hello_interp.c | |
231 void interp_test(uint8_t *data, const uint8_t *shape) { | |
232 interp_config cfg; | |
233 const int uv_fractional_bits = 12; | |
234 | |
235 // Step size is 0.25 (ie stretching by 4x) | |
236 unsigned step = (1 << uv_fractional_bits) / 4; | |
237 | |
238 puts("interp_test\n"); | |
239 // Setup lane 0 to generate index into shape table | |
6 | 240 // Mask start is 0 because we use 8 bit samples |
5 | 241 cfg = interp_default_config(); |
242 interp_config_set_shift(&cfg, uv_fractional_bits); | |
243 interp_config_set_mask(&cfg, 0, 32 - uv_fractional_bits); | |
244 interp_config_set_blend(&cfg, true); | |
245 interp_set_config(interp0, 0, &cfg); | |
246 | |
247 // Setup lane 1 to LERP each sample pair | |
248 cfg = interp_default_config(); | |
249 interp_config_set_shift(&cfg, uv_fractional_bits - 8); | |
250 interp_config_set_signed(&cfg, false); | |
251 interp_config_set_cross_input(&cfg, true); // unsigned blending | |
252 interp_set_config(interp0, 1, &cfg); | |
253 | |
254 interp0->accum[0] = 0; // Initial offset into shape table | |
255 interp0->base[2] = (uintptr_t)shape; // Start of shape table | |
256 for (unsigned i = 0; i < 122 * 4; i++) { | |
257 // Get sample pair | |
258 uint8_t *sample_pair = (uint8_t *) interp0->peek[2]; | |
259 // Ask lane 1 for a LERP, using the lane 0 accumulator | |
260 interp0->base[0] = sample_pair[0]; | |
261 interp0->base[1] = sample_pair[1]; | |
262 uint32_t peek1 = interp0->peek[1]; | |
263 uint32_t add_raw1 = interp0->add_raw[1]; | |
264 data[i] = peek1; | |
265 printf("%d\t(%lu%% between %d and %d) %lu\n", | |
266 (int)peek1, | |
267 100 * (add_raw1 & 0xff) / 0xff, | |
268 sample_pair[0], sample_pair[1], | |
269 interp_get_accumulator(interp0, 0)); | |
270 interp0->add_raw[0] = step; | |
271 } | |
272 puts("done"); | |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
273 } |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
274 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
275 int |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
276 main(void) { |
5 | 277 absolute_time_t then, now; |
278 | |
279 // Set sysclk to 120MHz | |
280 set_sys_clock_khz(120000, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
281 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
282 stdio_init_all(); |
5 | 283 printf("\n\n\nIniting\n"); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
284 |
5 | 285 // Needed otherwise timer related functions hang under debugging |
286 // https://github.com/raspberrypi/pico-sdk/issues/1152#issuecomment-1418248639 | |
287 timer_hw->dbgpause = 0; | |
288 | |
289 gpio_init(PICO_DEFAULT_LED_PIN); | |
290 gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | |
291 | |
7
4ad473648949
Copy pulse up in reverse for pulse down.
Daniel O'Connor <darius@dons.net.au>
parents:
6
diff
changeset
|
292 //interp_test(pulse_data, shaped_trap); |
5 | 293 |
294 uint32_t idx; | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
295 uint16_t plen; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
296 char *code; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
297 if (0) { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
298 plen = 8000; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
299 code = "1110010"; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
300 } else { |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
301 plen = 53000; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
302 code = "1"; |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
303 } |
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
304 |
5 | 305 uint8_t codegap = 4; |
306 uint8_t slew1 = 10; | |
307 uint8_t slew2 = 10; | |
308 uint8_t dcofs = 110; | |
309 then = get_absolute_time(); | |
310 if ((idx = compute_pulse(pulse_data, pulse_ctrl, sizeof(pulse_data), | |
311 plen, code, strlen(code), | |
312 shaped_trap, sizeof(shaped_trap), | |
313 codegap, slew1, slew2, dcofs)) == 0) { | |
314 printf("Failed to compute pulse\n"); | |
315 while (1) | |
316 ; | |
317 } | |
318 now = get_absolute_time(); | |
8
0249d0cecac4
Use interpolator to compute pulse up.
Daniel O'Connor <darius@dons.net.au>
parents:
7
diff
changeset
|
319 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
|
320 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
|
321 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
|
322 __breakpoint(); |
5 | 323 pwm_config c = pwm_get_default_config(); |
324 // 120MHz / 250 = 480kHz base | |
325 // Maximum divisor is only 256 which limits the low end, | |
326 // could further subdivide in the IRQ handler | |
327 pwm_config_set_clkdiv_int(&c, 250); | |
328 // 8Hz | |
329 pwm_config_set_wrap(&c, 60000 - 1); | |
330 pwm_init(slice_num, &c, true); | |
331 pwm_clear_irq(slice_num); | |
332 pwm_set_irq_enabled(slice_num, true); | |
333 irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_wrap); | |
334 irq_set_enabled(PWM_IRQ_WRAP, true); | |
335 pwm_init(slice_num, &c, true); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
336 |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
337 // 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
|
338 // to run the program. |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
339 PIO pio = pio0; |
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
340 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
|
341 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
|
342 // 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
|
343 // bits don't seem to work |
5 | 344 // Clock divisor of 2 so it runs at 60MHz and |
345 // generates a 30MHz clock | |
346 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
|
347 |
5 | 348 // 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
|
349 // 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
|
350 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
|
351 dma_channel_config dmac = dma_channel_get_default_config(dma_chan); |
5 | 352 // 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
|
353 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
|
354 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
|
355 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
|
356 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
357 dma_channel_configure( |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
358 dma_chan, |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
359 &dmac, |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
360 &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
|
361 NULL, // Don't provide a read address yet |
5 | 362 idx >> 2, // Transfer count |
3
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
363 false // Don't start yet |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
364 ); |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
365 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
366 // 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
|
367 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
|
368 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
369 // 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
|
370 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
|
371 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
|
372 |
b10097c3383d
DMA test data repeatedly into PIO FIFO
Daniel O'Connor <darius@dons.net.au>
parents:
2
diff
changeset
|
373 // 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
|
374 // 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
|
375 while (true) { |
5 | 376 dma_channel_wait_for_finish_blocking(dma_chan); |
377 gpio_put(PICO_DEFAULT_LED_PIN, 1); | |
378 sleep_ms(100); | |
379 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
|
380 sleep_ms(100); |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
381 } |
5 | 382 |
383 __breakpoint(); | |
0
a55e39064a71
First commit of code that compiles.
Daniel O'Connor <darius@dons.net.au>
parents:
diff
changeset
|
384 } |