1 // Copyright 2017 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 
25 #include <stm32f37x_conf.h>
26 
27 #include "stmlib/dsp/dsp.h"
28 
29 #include "stmlib/dsp/dsp.h"
30 #include "stmlib/dsp/units.h"
31 #include "stages/chain_state.h"
32 #include "stages/drivers/dac.h"
33 #include "stages/drivers/gate_inputs.h"
34 #include "stages/drivers/serial_link.h"
35 #include "stages/drivers/system.h"
36 #include "stages/cv_reader.h"
37 #include "stages/factory_test.h"
38 #include "stages/io_buffer.h"
39 #include "stages/oscillator.h"
40 #include "stages/resources.h"
41 #include "stages/segment_generator.h"
42 #include "stages/settings.h"
43 #include "stages/ui.h"
44 
45 using namespace stages;
46 using namespace std;
47 using namespace stmlib;
48 
49 const bool skip_factory_test = false;
50 const bool test_adc_noise = false;
51 
52 ChainState chain_state;
53 CvReader cv_reader;
54 Dac dac;
55 FactoryTest factory_test;
56 GateFlags no_gate[kBlockSize];
57 GateInputs gate_inputs;
58 SegmentGenerator segment_generator[kNumChannels];
59 Oscillator oscillator[kNumChannels];
60 IOBuffer io_buffer;
61 SerialLink left_link;
62 SerialLink right_link;
63 Settings settings;
64 Ui ui;
65 
66 // Default interrupt handlers.
67 extern "C" {
68 
NMI_Handler()69 void NMI_Handler() { }
HardFault_Handler()70 void HardFault_Handler() { while (1); }
MemManage_Handler()71 void MemManage_Handler() { while (1); }
BusFault_Handler()72 void BusFault_Handler() { while (1); }
UsageFault_Handler()73 void UsageFault_Handler() { while (1); }
SVC_Handler()74 void SVC_Handler() { }
DebugMon_Handler()75 void DebugMon_Handler() { }
PendSV_Handler()76 void PendSV_Handler() { }
77 
78 }
79 
80 // SysTick and 32kHz handles
81 extern "C" {
82 
SysTick_Handler()83 void SysTick_Handler() {
84   IWDG_ReloadCounter();
85   ui.Poll();
86   if (!skip_factory_test) {
87     factory_test.Poll();
88   }
89 }
90 
91 }
92 
FillBuffer(size_t size)93 IOBuffer::Slice FillBuffer(size_t size) {
94   IOBuffer::Slice s = io_buffer.NextSlice(size);
95   gate_inputs.Read(s, size);
96   if (io_buffer.new_block()) {
97     cv_reader.Read(s.block);
98     gate_inputs.ReadNormalization(s.block);
99   }
100   return s;
101 }
102 
103 SegmentGenerator::Output out[kBlockSize];
104 
105 static float note_lp[kNumChannels] = { 0, 0, 0, 0, 0, 0 };
106 
Process(IOBuffer::Block * block,size_t size)107 void Process(IOBuffer::Block* block, size_t size) {
108   chain_state.Update(
109       *block,
110       &settings,
111       &segment_generator[0],
112       out);
113   for (size_t channel = 0; channel < kNumChannels; ++channel) {
114     bool led_state = segment_generator[channel].Process(
115         block->input_patched[channel] ? block->input[channel] : no_gate,
116         out,
117         size);
118     ui.set_slider_led(channel, led_state, 5);
119 
120     if (test_adc_noise) {
121       float note = block->cv_slider[channel];
122       ONE_POLE(note_lp[channel], note, 0.0001f);
123       float cents = (note - note_lp[channel]) * 1200.0f * 0.5f;
124       CONSTRAIN(cents, -1.0f, +1.0f)
125       for (size_t i = 0; i < size; ++i) {
126         out[i].value = cents;
127       }
128     }
129 
130     for (size_t i = 0; i < size; ++i) {
131       block->output[channel][i] = settings.dac_code(channel, out[i].value);
132     }
133   }
134 }
135 
136 
137 float ouroboros_ratios[] = {
138   0.25f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 8.0f, 8.0f
139 };
140 
141 float this_channel[kBlockSize];
142 float sum[kBlockSize];
143 float channel_amplitude[kNumChannels];
144 float previous_amplitude[kNumChannels];
145 
ProcessOuroboros(IOBuffer::Block * block,size_t size)146 void ProcessOuroboros(IOBuffer::Block* block, size_t size) {
147   const float coarse = (block->cv_slider[0] - 0.5f) * 96.0f;
148   const float fine = block->pot[0] * 2.0f - 1.0f;
149   const float f0 = SemitonesToRatio(coarse + fine) * 261.6255f / kSampleRate;
150 
151   std::fill(&sum[0], &sum[size], 0.0f);
152 
153   for (int channel = kNumChannels - 1; channel >= 0; --channel) {
154 
155     const float harmonic = block->pot[channel] * 9.999f;
156     MAKE_INTEGRAL_FRACTIONAL(harmonic);
157     harmonic_fractional = 8.0f * (harmonic_fractional - 0.5f) + 0.5f;
158     CONSTRAIN(harmonic_fractional, 0.0f, 1.0f);
159     const float ratio = channel == 0 ? 1.0f : Crossfade(
160         ouroboros_ratios[harmonic_integral],
161         ouroboros_ratios[harmonic_integral + 1],
162         harmonic_fractional);
163     const float amplitude = channel == 0
164         ? 1.0f
165         : std::max(block->cv_slider[channel], 0.0f);
166     bool trigger = false;
167     for (size_t i = 0; i < size; ++i) {
168       trigger = trigger || (block->input[channel][i] & GATE_FLAG_RISING);
169     }
170     if (trigger || !block->input_patched[channel]) {
171       channel_amplitude[channel] = 1.0f;
172     } else {
173       channel_amplitude[channel] *= 0.999f;
174     }
175     ui.set_slider_led(
176         channel, channel_amplitude[channel] * amplitude > 0.00001f, 1);
177     const float f = f0 * ratio;
178 
179     uint8_t waveshape = settings.state().segment_configuration[channel];
180     switch (waveshape) {
181       case 0:
182         oscillator[channel].Render<OSCILLATOR_SHAPE_SINE>(
183             f, 0.5f, this_channel, size);
184         break;
185       case 1:
186         oscillator[channel].Render<OSCILLATOR_SHAPE_TRIANGLE>(
187             f, 0.5f, this_channel, size);
188         break;
189       case 2:
190       case 3:
191         oscillator[channel].Render<OSCILLATOR_SHAPE_SQUARE>(
192             f, 0.5f, this_channel, size);
193         break;
194       case 4:
195         oscillator[channel].Render<OSCILLATOR_SHAPE_SAW>(
196             f, 0.5f, this_channel, size);
197         break;
198       case 5:
199         oscillator[channel].Render<OSCILLATOR_SHAPE_SQUARE>(
200             f, 0.75f, this_channel, size);
201         break;
202       case 6:
203       case 7:
204         oscillator[channel].Render<OSCILLATOR_SHAPE_SQUARE>(
205             f, 0.9f, this_channel, size);
206         break;
207     }
208 
209     ParameterInterpolator am(
210         &previous_amplitude[channel],
211         amplitude * amplitude * channel_amplitude[channel],
212         size);
213     for (size_t i = 0; i < size; ++i) {
214       sum[i] += this_channel[i] * am.Next();
215     }
216 
217     const float gain = channel == 0 ? 0.2f : 0.66f;
218     const float* source = channel == 0 ? sum : this_channel;
219     for (size_t i = 0; i < size; ++i) {
220       block->output[channel][i] = settings.dac_code(channel, source[i] * gain);
221     }
222   }
223 }
224 
Init()225 void Init() {
226   System sys;
227   sys.Init(true);
228   dac.Init(int(kSampleRate), 2);
229   gate_inputs.Init();
230   io_buffer.Init();
231 
232   bool freshly_baked = !settings.Init();
233   for (size_t i = 0; i < kNumChannels; ++i) {
234     segment_generator[i].Init();
235     oscillator[i].Init();
236   }
237   std::fill(&no_gate[0], &no_gate[kBlockSize], GATE_FLAG_LOW);
238 
239   cv_reader.Init(&settings);
240 
241   ui.Init(&settings, &chain_state);
242 
243   if (freshly_baked && !skip_factory_test) {
244     factory_test.Start(&settings, &cv_reader, &gate_inputs, &ui);
245     ui.set_factory_test(true);
246   } else {
247     chain_state.Init(&left_link, &right_link);
248   }
249 
250   sys.StartTimers();
251   dac.Start(&FillBuffer);
252 }
253 
main(void)254 int main(void) {
255   Init();
256   while (1) {
257     io_buffer.Process(factory_test.running()
258           ? &FactoryTest::ProcessFn
259           : (chain_state.ouroboros() ? &ProcessOuroboros : &Process));
260   }
261 }
262