1 // Copyright 2013 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.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 // -----------------------------------------------------------------------------
26 //
27 // User interface.
28 
29 #include "tides/ui.h"
30 
31 #include "stmlib/system/storage.h"
32 #include "stmlib/system/system_clock.h"
33 
34 #include "tides/cv_scaler.h"
35 #include "tides/generator.h"
36 
37 namespace tides {
38 
39 const int32_t kLongPressDuration = 1000;
40 const uint8_t kMagicNumber = 42;
41 
42 using namespace stmlib;
43 
44 Storage<0x801fc00, 4> mode_storage;
45 
Init(Generator * generator,CvScaler * cv_scaler)46 void Ui::Init(Generator* generator, CvScaler* cv_scaler) {
47   factory_testing_switch_.Init();
48   leds_.Init();
49   switches_.Init();
50   mode_ = factory_testing_switch_.Read()
51       ? UI_MODE_NORMAL
52       : UI_MODE_FACTORY_TESTING;
53 
54   ignore_releases_ = 0;
55 
56   if (switches_.pressed_immediate(1)) {
57     mode_ = UI_MODE_CALIBRATION_C2;
58     ignore_releases_ = 1;
59   }
60 
61   generator->feature_mode_ = Generator::FEAT_MODE_FUNCTION;
62 
63   generator_ = generator;
64   cv_scaler_ = cv_scaler;
65 
66   if (!mode_storage.ParsimoniousLoad(&settings_, &version_token_) ||
67       settings_.magic_number != kMagicNumber) {
68     settings_.magic_number = kMagicNumber;
69     mode_counter_ = 1;
70     range_counter_ = 2;
71     cv_scaler_->quantize_ = 0;
72     generator->set_sync(false);
73   } else {
74     mode_counter_ = settings_.mode;
75     range_counter_ = 2 - settings_.range;
76     cv_scaler_->quantize_ = settings_.quantize;
77     generator->feature_mode_ = static_cast<Generator::FeatureMode>(settings_.feature_mode);
78     generator->set_sync(settings_.sync);
79   }
80 
81   UpdateMode();
82   UpdateRange();
83   leds_.set_value(32768, 32768);
84 }
85 
SaveState()86 void Ui::SaveState() {
87   settings_.mode = generator_->mode();
88   settings_.range = generator_->range();
89   settings_.sync = generator_->sync();
90   settings_.feature_mode = generator_->feature_mode_;
91   settings_.quantize = cv_scaler_->quantize_;
92   mode_storage.ParsimoniousSave(settings_, &version_token_);
93 }
94 
95 const uint16_t thresholds[ADC_CHANNEL_LAST][2] = {
96   { 0, 64000 },
97   { 16384, 49152 },
98   { 16384, 49152 },
99   { 4096, 61440 },
100   { 4096, 61440 },
101   { 4096, 61440 },
102   { 4096, 61440 },
103 };
104 
UpdateFactoryTestingFlags(uint8_t gate_input_flags,const uint16_t * adc_values)105 void Ui::UpdateFactoryTestingFlags(
106     uint8_t gate_input_flags,
107     const uint16_t* adc_values) {
108   red_ = switches_.pressed(1);
109   green_ = switches_.pressed(0);
110   orange_ = gate_input_flags & CONTROL_GATE;
111   orange_ |= gate_input_flags & CONTROL_FREEZE;
112   orange_ |= gate_input_flags & CONTROL_CLOCK;
113 
114   for (uint16_t i = 0; i < ADC_CHANNEL_LAST; ++i) {
115     uint16_t value = adc_values[i];
116     if (i == ADC_CHANNEL_FM_ATTENUVERTER) {
117       value = ~value;
118     }
119     green_ |= value < thresholds[i][0];
120     if (i == 0) {
121       orange_ |= value > thresholds[i][1];
122     } else {
123       red_ |= value > thresholds[i][1];
124     }
125   }
126 }
127 
Poll()128 void Ui::Poll() {
129   system_clock.Tick();
130   switches_.Debounce();
131 
132   for (uint8_t i = 0; i < kNumSwitches; ++i) {
133     if (switches_.just_pressed(i)) {
134       queue_.AddEvent(CONTROL_SWITCH, i, 0);
135       press_time_[i] = system_clock.milliseconds();
136     }
137     if (switches_.pressed(i) && press_time_[i] != 0) {
138       int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
139       if (pressed_time > kLongPressDuration) {
140         queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
141         press_time_[i] = 0;
142       }
143     }
144     if (switches_.released(i) && press_time_[i] != 0) {
145       queue_.AddEvent(
146           CONTROL_SWITCH,
147           i,
148           system_clock.milliseconds() - press_time_[i] + 1);
149       press_time_[i] = 0;
150     }
151   }
152 
153   switch (mode_) {
154     case UI_MODE_FEATURE_SWITCH:
155       {
156         bool blink = system_clock.milliseconds() & 32;
157         switch (generator_->feature_mode_) {
158         case Generator::FEAT_MODE_FUNCTION:
159           leds_.set_mode(blink);
160           leds_.set_value(0);
161           leds_.set_rate(0);
162           break;
163         case Generator::FEAT_MODE_HARMONIC:
164           leds_.set_mode(0);
165           leds_.set_value(blink ? 65535 : 0);
166           leds_.set_rate(0);
167           break;
168         case Generator::FEAT_MODE_RANDOM:
169           leds_.set_mode(0);
170           leds_.set_value(0);
171           leds_.set_rate(blink ? 65535 : 0);
172           break;
173         }
174       }
175       break;
176     case UI_MODE_QUANTIZE:
177       {
178         bool led1 = cv_scaler_->quantize_ & 1;
179         bool led2 = cv_scaler_->quantize_ & 2;
180         bool led3 = cv_scaler_->quantize_ & 4;
181         uint16_t on = ((system_clock.milliseconds() & 16) &&
182                        (system_clock.milliseconds() & 8) &&
183                        (system_clock.milliseconds() & 4) &&
184                        (system_clock.milliseconds() & 2)) * 65535;
185         uint16_t off = 0;
186         leds_.set_mode(0, led1 ? on : off);
187         leds_.set_value(0, led2 ? on : off);
188         leds_.set_rate(0, led3 ? on : off);
189       }
190       break;
191     case UI_MODE_NORMAL:
192       {
193         GeneratorMode mode = generator_->mode();
194         leds_.set_mode(mode == GENERATOR_MODE_AR, mode == GENERATOR_MODE_AD);
195 
196         GeneratorRange range = generator_->range();
197         switch (range) {
198           case GENERATOR_RANGE_LOW:
199             leds_.set_rate(0, 65535);
200             break;
201           case GENERATOR_RANGE_MEDIUM:
202             if (generator_->sync()) {
203               leds_.set_rate(8192, 16384);
204             } else {
205               leds_.set_rate(0);
206             }
207             break;
208           case GENERATOR_RANGE_HIGH:
209             leds_.set_rate(65535, 0);
210             break;
211         }
212         bool blink_rate_led = generator_->sync() && \
213             system_clock.milliseconds() & 128;
214         if (blink_rate_led) {
215           leds_.set_rate(0);
216         }
217       }
218       break;
219 
220     case UI_MODE_CALIBRATION_C2:
221       leds_.set_mode(true);
222       leds_.set_rate(65535);
223       leds_.set_value(65535);
224       break;
225 
226     case UI_MODE_CALIBRATION_C4:
227       leds_.set_mode(false, true);
228       leds_.set_rate(0, 65535);
229       leds_.set_value(0, 65535);
230       break;
231 
232     case UI_MODE_FACTORY_TESTING:
233       if (orange_) {
234         leds_.set_mode(true, true);
235         leds_.set_rate(65535, 65535);
236         leds_.set_value(65535, 65535);
237       } else if (red_) {
238         leds_.set_mode(true, 0);
239         leds_.set_rate(65535, 0);
240         leds_.set_value(65535, 0);
241       } else if (green_) {
242         leds_.set_mode(false, true);
243         leds_.set_rate(0, 65535);
244         leds_.set_value(0, 65535);
245       } else {
246         leds_.set_mode(false, false);
247         leds_.set_rate(0, 0);
248         leds_.set_value(0, 0);
249       }
250       break;
251   }
252 
253   leds_.Write();
254 }
255 
UpdateMode()256 inline void Ui::UpdateMode() {
257   uint8_t i = mode_counter_ & 3;
258   if (i == 3) {
259     i = 1;
260   }
261   generator_->set_mode(static_cast<GeneratorMode>(i));
262   SaveState();
263 }
264 
UpdateRange()265 inline void Ui::UpdateRange() {
266   uint8_t i = range_counter_ & 3;
267   if (i == 3) {
268     i = 1;
269   }
270   generator_->set_range(static_cast<GeneratorRange>(2 - i));
271   SaveState();
272 }
273 
FlushEvents()274 void Ui::FlushEvents() {
275   queue_.Flush();
276 }
277 
OnSwitchPressed(const Event & e)278 void Ui::OnSwitchPressed(const Event& e) {
279   // double press -> feature switch mode
280   if ((e.control_id == 0 && switches_.pressed_immediate(1)) ||
281       (e.control_id == 1 && switches_.pressed_immediate(0))) {
282     mode_ = UI_MODE_FEATURE_SWITCH;
283     ignore_releases_ = 2;
284   }
285 }
286 
OnSwitchReleased(const Event & e)287 void Ui::OnSwitchReleased(const Event& e) {
288 
289   // hack for double presses
290   if (ignore_releases_ > 0) {
291     ignore_releases_--;
292     return;
293   }
294 
295   if (mode_ == UI_MODE_FACTORY_TESTING) {
296     return;
297   } else if (mode_ == UI_MODE_FEATURE_SWITCH) {
298     uint8_t feat = generator_->feature_mode_;
299     int8_t dir = e.control_id == 0 ? -1 : 1;
300     int8_t mode = (feat + dir) % 3;
301     if (mode == -1) mode = 2;
302     generator_->feature_mode_ = static_cast<Generator::FeatureMode>(mode);
303     UpdateMode();
304     UpdateRange();
305   } else if (mode_ == UI_MODE_QUANTIZE) {
306     if (e.data > kLongPressDuration) {
307       mode_ = UI_MODE_NORMAL;
308     } else {
309       uint8_t q = cv_scaler_->quantize_;
310       int8_t dir = e.control_id == 0 ? -1 : 1;
311       int8_t quant = (q + dir) % 8;
312       if (quant == -1) quant = 7;
313       cv_scaler_->quantize_ = quant;
314       SaveState();
315     }
316   } else if (mode_ == UI_MODE_CALIBRATION_C2) {
317     if (e.data > kLongPressDuration) {
318       ++long_press_counter_;
319     }
320     if (e.control_id == 0) {
321       cv_scaler_->CaptureCalibrationValues();
322       mode_ = UI_MODE_CALIBRATION_C4;
323     } else {
324       mode_ = UI_MODE_NORMAL;
325     }
326   } else if (mode_ == UI_MODE_CALIBRATION_C4) {
327     mode_ = UI_MODE_NORMAL;
328     if (e.control_id == 0) {
329       cv_scaler_->Calibrate();
330     }
331   } else {
332     long_press_counter_ = 0;
333     switch (e.control_id) {
334       case 0:
335         if (e.data > kLongPressDuration) {
336           mode_ = UI_MODE_QUANTIZE;
337         } else {
338           ++mode_counter_;
339           UpdateMode();
340         }
341         break;
342 
343       case 1:
344         if (e.data > kLongPressDuration) {
345           generator_->set_sync(!generator_->sync());
346           SaveState();
347         } else {
348           ++range_counter_;
349           UpdateRange();
350         }
351         break;
352     }
353   }
354 }
355 
DoEvents()356 void Ui::DoEvents() {
357   while (queue_.available()) {
358     Event e = queue_.PullEvent();
359     if (e.control_type == CONTROL_SWITCH) {
360       if (e.data == 0) {
361         OnSwitchPressed(e);
362       } else {
363         OnSwitchReleased(e);
364       }
365     }
366   }
367   if (queue_.idle_time() > 2000) {
368     queue_.Touch();
369     if (mode_ == UI_MODE_FEATURE_SWITCH)
370       mode_ = UI_MODE_NORMAL;
371   }
372 }
373 
374 }  // namespace tides
375