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 "frames/ui.h"
30 
31 #include <algorithm>
32 
33 #include "frames/keyframer.h"
34 #include "frames/poly_lfo.h"
35 #include "frames/euclidean.h"
36 
37 namespace frames {
38 
39 using namespace std;
40 using namespace stmlib;
41 
42 const uint16_t kAdcThreshold = 1 << (16 - 10);  // 10 bits
43 const int32_t kLongPressDuration = 800;
44 const int32_t kVeryLongPressDuration = 2000;
45 const uint16_t kKeyframeGridTolerance = 2048;
46 const uint8_t kDividersSteps = 7;
47 const uint16_t kDeadZone = 2048; // 0..32767
48 
Init(Keyframer * keyframer,PolyLfo * poly_lfo,Euclidean euclidean[kNumChannels])49 void Ui::Init(Keyframer* keyframer, PolyLfo* poly_lfo, Euclidean euclidean[kNumChannels]) {
50   factory_testing_switch_.Init();
51   channel_leds_.Init();
52   keyframe_led_.Init();
53   rgb_led_.Init();
54   switches_.Init();
55   adc_.Init(false);
56 
57   fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0);
58 
59   keyframer_ = keyframer;
60   poly_lfo_ = poly_lfo;
61   euclidean_ = euclidean;
62   mode_ = factory_testing_switch_.Read()
63       ? UI_MODE_SPLASH
64       : UI_MODE_FACTORY_TESTING;
65   animation_counter_ = 0;
66   ignore_releases_ = 0;
67   active_slot_ = 0;
68 
69   FindNearestKeyframe();
70   active_keyframe_lock_ = false;
71 
72   feature_mode_ = static_cast<FeatureMode>(keyframer_->feature_mode_);
73   for (int i=0; i<kNumChannels; i++) {
74     euclidean_[i].set_length(keyframer_->euclidean_length_[i]);
75     euclidean_[i].set_shape(keyframer_->euclidean_shape_[i]);
76   }
77 
78   sequencer_step = 0;
79   step_divider = 1;
80   step_random = 0;
81   shift_divider = 1;
82   shift_random = 0;
83   feedback_random = 0;
84   active_registers = kMaxRegisters;
85   for (int i=0; i<kMaxRegisters; i++)
86     shift_register[i] = 0;
87 }
88 
TryCalibration()89 void Ui::TryCalibration() {
90   if (switches_.pressed_immediate(1)) {
91     keyframer_->Calibrate(frame_modulation());
92     FlushEvents();
93   }
94 }
95 
Poll()96 void Ui::Poll() {
97   switches_.Debounce();
98 
99   for (uint8_t i = 0; i < kNumSwitches; ++i) {
100     if (switches_.just_pressed(i)) {
101       queue_.AddEvent(CONTROL_SWITCH, i, 0);
102       press_time_[i] = system_clock.milliseconds();
103       detect_very_long_press_[i] = false;
104     }
105     if (switches_.pressed(i)) {
106       int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
107 
108       if (!detect_very_long_press_[i]) {
109         if (pressed_time > kLongPressDuration) {
110           queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
111           detect_very_long_press_[i] = true;
112         }
113       } else {
114         if (pressed_time > kVeryLongPressDuration) {
115           queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
116           detect_very_long_press_[i] = false;
117           press_time_[i] = 0;
118         }
119       }
120     }
121 
122     if (switches_.released(i) &&
123         press_time_[i] != 0 &&
124         !detect_very_long_press_[i]) {
125       queue_.AddEvent(
126           CONTROL_SWITCH,
127           i,
128           system_clock.milliseconds() - press_time_[i] + 1);
129       press_time_[i] = 0;
130       detect_very_long_press_[i] = false;
131     }
132   }
133 
134   for (uint8_t i = 0; i <= kFrameAdcChannel; ++i) {
135     int32_t value = (31 * adc_filtered_value_[i] + adc_.value(i)) >> 5;
136     adc_filtered_value_[i] = value;
137     int32_t current_value = static_cast<int32_t>(adc_value_[i]);
138     if (value >= current_value + kAdcThreshold ||
139         value <= current_value - kAdcThreshold) {
140       queue_.AddEvent(CONTROL_POT, i, value);
141       adc_value_[i] = value;
142     }
143   }
144 
145   switch (mode_) {
146     case UI_MODE_SPLASH:
147       animation_counter_ += 128;
148       channel_leds_.set_channel(0, (animation_counter_ + 49152) >> 8);
149       channel_leds_.set_channel(1, (animation_counter_ + 32768) >> 8);
150       channel_leds_.set_channel(2, (animation_counter_ + 16384) >> 8);
151       channel_leds_.set_channel(3, (animation_counter_ + 0) >> 8);
152       rgb_led_.set_color(255, 255, 255);
153       break;
154 
155   case UI_MODE_FEATURE_SWITCH:
156       animation_counter_ += 1024;
157       rgb_led_.set_color(255, 255, 255);
158       rgb_led_.Dim(animation_counter_);
159 
160       for (int i=0; i<4; i++)
161         channel_leds_.set_channel(i, 0);
162 
163       switch (feature_mode_) {
164       case FEAT_MODE_KEYFRAMER:
165         break;
166       case FEAT_MODE_KEYFRAME_LOOPER:
167         rgb_led_.set_color(255, 0, 0);
168         rgb_led_.Dim(animation_counter_);
169         break;
170       case FEAT_MODE_SEQ_MAIN:
171         channel_leds_.set_channel(0, 255); break;
172       case FEAT_MODE_SEQ_SHIFT_REGISTER:
173         channel_leds_.set_channel(1, 255); break;
174       case FEAT_MODE_SEQ_STEP_EDIT:
175         break;
176       case FEAT_MODE_POLY_LFO:
177         channel_leds_.set_channel(2, 255); break;
178       case FEAT_MODE_EUCLIDEAN:
179         channel_leds_.set_channel(3, 255); break;
180       }
181 
182       break;
183 
184     case UI_MODE_SAVE_CONFIRMATION:
185       animation_counter_ -= 256;
186       if (active_slot_ == 0) {
187         channel_leds_.set_channel(0, (animation_counter_ + 0) >> 8);
188         channel_leds_.set_channel(1, (animation_counter_ + 16384) >> 8);
189         channel_leds_.set_channel(2, (animation_counter_ + 32768) >> 8);
190         channel_leds_.set_channel(3, (animation_counter_ + 49152) >> 8);
191       } else {
192         for (int i=0; i<4; i++)
193           channel_leds_.set_channel(i, active_slot_ == i+1 ?
194                                     animation_counter_ >> 8 : 0);
195       }
196       rgb_led_.set_color(0, 255, 0);
197       break;
198 
199     case UI_MODE_ERASE_CONFIRMATION:
200       animation_counter_ -= 256;
201       if (active_slot_ == 0) {
202         channel_leds_.set_channel(0, (animation_counter_ + 0) >> 8);
203         channel_leds_.set_channel(1, (animation_counter_ + 16384) >> 8);
204         channel_leds_.set_channel(2, (animation_counter_ + 32768) >> 8);
205         channel_leds_.set_channel(3, (animation_counter_ + 49152) >> 8);
206       } else {
207         for (int i=0; i<4; i++)
208           channel_leds_.set_channel(i, active_slot_ == i+1 ?
209                                     animation_counter_ >> 8 : 0);
210       }
211       rgb_led_.set_color(255, 0, 0);
212       break;
213 
214     case UI_MODE_FACTORY_TESTING:
215       channel_leds_.set_channel(0, keyframer_->level(0) >> 8);
216       channel_leds_.set_channel(1, keyframer_->level(1) >> 8);
217       channel_leds_.set_channel(2, keyframer_->level(2) >> 8);
218       channel_leds_.set_channel(3, keyframer_->level(3) >> 8);
219       if (frame() < 4096) {
220         rgb_led_.set_color(255, 0, 0);
221       } else if (frame() > 61440) {
222         rgb_led_.set_color(0, 255, 0);
223       } else {
224         uint8_t v = frame_modulation() >> 8;
225         rgb_led_.set_color(0, 0, v);
226       }
227       if (test_led_) {
228         keyframe_led_.High();
229       } else {
230         keyframe_led_.Low();
231       }
232       break;
233 
234     case UI_MODE_NORMAL:
235 
236       if (feature_mode_ == FEAT_MODE_POLY_LFO) {
237         channel_leds_.set_channel(0, poly_lfo_->level(0));
238         channel_leds_.set_channel(1, poly_lfo_->level(1));
239         channel_leds_.set_channel(2, poly_lfo_->level(2));
240         channel_leds_.set_channel(3, poly_lfo_->level(3));
241         rgb_led_.set_color(poly_lfo_->color());
242         if (poly_lfo_->level(0) > 128) {
243           keyframe_led_.High();
244         } else {
245           keyframe_led_.Low();
246         }
247       } else if (feature_mode_ == FEAT_MODE_EUCLIDEAN) {
248         channel_leds_.set_channel(0, euclidean_[0].level());
249         channel_leds_.set_channel(1, euclidean_[1].level());
250         channel_leds_.set_channel(2, euclidean_[2].level());
251         channel_leds_.set_channel(3, euclidean_[3].level());
252       } else if (feature_mode_ == FEAT_MODE_SEQ_STEP_EDIT) {
253         channel_leds_.set_channel(0, keyframer_->level(0) >> 8);
254         channel_leds_.set_channel(1, keyframer_->level(1) >> 8);
255         channel_leds_.set_channel(2, keyframer_->level(2) >> 8);
256         channel_leds_.set_channel(3, keyframer_->level(3) >> 8);
257         rgb_led_.set_color(keyframer_->color());
258 
259         ++keyframe_led_pwm_counter_;
260         if ((keyframe_led_pwm_counter_ & 15) >= 15) {
261           keyframe_led_.High();
262         } else {
263           keyframe_led_.Low();
264         }
265         break;
266       } else if (feature_mode_ == FEAT_MODE_SEQ_SHIFT_REGISTER) {
267         channel_leds_.set_channel(0, shift_register[0] >> 8);
268         channel_leds_.set_channel(1, shift_register[1] >> 8);
269         channel_leds_.set_channel(2, shift_register[2] >> 8);
270         channel_leds_.set_channel(3, shift_register[3] >> 8);
271         rgb_led_.set_color(keyframer_->color());
272 
273         if (active_keyframe_ == -1) {
274           keyframe_led_.Low();
275         } else {
276           animation_counter_ += 256;
277           int32_t distance = frame() - \
278             keyframer_->keyframe(active_keyframe_).timestamp;
279           distance = min(distance * distance >> 18, int32_t(15));
280           ++keyframe_led_pwm_counter_;
281           if ((keyframe_led_pwm_counter_ & 15) >= distance) {
282             keyframe_led_.High();
283           } else {
284             keyframe_led_.Low();
285           }
286           if (active_keyframe_lock_) {
287             if (animation_counter_ & 0x8000) {
288               keyframe_led_.High();
289             } else {
290               keyframe_led_.Low();
291             }
292           }
293         }
294       } else {
295         channel_leds_.set_channel(0, keyframer_->level(0) >> 8);
296         channel_leds_.set_channel(1, keyframer_->level(1) >> 8);
297         channel_leds_.set_channel(2, keyframer_->level(2) >> 8);
298         channel_leds_.set_channel(3, keyframer_->level(3) >> 8);
299         rgb_led_.set_color(keyframer_->color());
300         if (active_keyframe_ == -1) {
301           keyframe_led_.Low();
302         } else {
303           animation_counter_ += 256;
304           int32_t distance = frame() - \
305             keyframer_->keyframe(active_keyframe_).timestamp;
306           distance = min(distance * distance >> 18, int32_t(15));
307           ++keyframe_led_pwm_counter_;
308           if ((keyframe_led_pwm_counter_ & 15) >= distance) {
309             keyframe_led_.High();
310           } else {
311             keyframe_led_.Low();
312           }
313           if (active_keyframe_lock_) {
314             if (animation_counter_ & 0x8000) {
315               keyframe_led_.High();
316             } else {
317               keyframe_led_.Low();
318             }
319           }
320         }
321       }
322       break;
323 
324     case UI_MODE_EDIT_LENGTH:
325       channel_leds_.set_channel(0, euclidean_[0].level());
326       channel_leds_.set_channel(1, euclidean_[1].level());
327       channel_leds_.set_channel(2, euclidean_[2].level());
328       channel_leds_.set_channel(3, euclidean_[3].level());
329       rgb_led_.set_color(255, 16, 32);
330     break;
331     case UI_MODE_EDIT_SHAPE:
332       channel_leds_.set_channel(0, euclidean_[0].level());
333       channel_leds_.set_channel(1, euclidean_[1].level());
334       channel_leds_.set_channel(2, euclidean_[2].level());
335       channel_leds_.set_channel(3, euclidean_[3].level());
336       rgb_led_.set_color(16, 192, 32);
337     break;
338 
339     case UI_MODE_EDIT_RESPONSE:
340     case UI_MODE_EDIT_EASING:
341       {
342         animation_counter_ += 48;
343         for (uint8_t i = 0; i < 4; ++i) {
344           channel_leds_.set_channel(i, active_channel_ == i ? 255 : 0);
345         }
346         if (mode_ == UI_MODE_EDIT_EASING) {
347           rgb_led_.set_color(255, 16, 32);
348         } else {
349           rgb_led_.set_color(16, 192, 32);
350         }
351         uint16_t brightness = active_channel_ == -1
352           ? 65535
353           : keyframer_->SampleAnimation(active_channel_,
354                                         animation_counter_,
355                                         mode_ == UI_MODE_EDIT_EASING);
356         rgb_led_.Dim(brightness);
357       }
358       break;
359   }
360 
361   rgb_led_.Write();
362   channel_leds_.Write();
363 }
364 
FlushEvents()365 void Ui::FlushEvents() {
366   queue_.Flush();
367 }
368 
OnSwitchPressed(const Event & e)369 void Ui::OnSwitchPressed(const Event& e) {
370   test_led_ = true;
371 
372   // double press -> feature switch mode
373   if ((e.control_id == 0 && switches_.pressed_immediate(1)) ||
374       (e.control_id == 1 && switches_.pressed_immediate(0))) {
375     mode_ = UI_MODE_FEATURE_SWITCH;
376     ignore_releases_ = 2;
377   }
378 }
379 
OnSwitchReleased(const Event & e)380 void Ui::OnSwitchReleased(const Event& e) {
381   if (mode_ == UI_MODE_FACTORY_TESTING) {
382     test_led_ = false;
383   } else  {
384     if (active_keyframe_lock_) {
385       active_keyframe_lock_ = false;
386       FindNearestKeyframe();
387       return;
388     }
389 
390     // hack for double presses
391     if (ignore_releases_ > 0) {
392       ignore_releases_--;
393       return;
394     }
395 
396     switch (e.control_id) {
397       case SWITCH_ADD_FRAME:
398         if (e.data > kVeryLongPressDuration) {
399           mode_ = UI_MODE_SAVE_CONFIRMATION;
400         } else if (e.data > kLongPressDuration) {
401           if (feature_mode_ == FEAT_MODE_KEYFRAMER ||
402               feature_mode_ == FEAT_MODE_KEYFRAME_LOOPER) {
403             mode_ = UI_MODE_EDIT_EASING;
404             active_channel_ = -1;
405           } else if (feature_mode_ == FEAT_MODE_EUCLIDEAN) {
406             mode_ = UI_MODE_EDIT_LENGTH;
407           } else if (feature_mode_ == FEAT_MODE_SEQ_MAIN) {
408             keyframer_->Randomize();
409           }
410         } else {
411           if (mode_ == UI_MODE_NORMAL &&
412               (feature_mode_ == FEAT_MODE_KEYFRAMER ||
413                feature_mode_ == FEAT_MODE_KEYFRAME_LOOPER ||
414                feature_mode_ == FEAT_MODE_SEQ_MAIN ||
415                feature_mode_ == FEAT_MODE_SEQ_SHIFT_REGISTER)) {
416             if (active_keyframe_ == -1) {
417               keyframer_->AddKeyframe(frame(), &adc_value_[0]);
418             } else {
419               // This abandoned feature allowed to select and continue editing
420               // a keyframe with the 4 knobs on the top even when the big
421               // frame knob is being played. For that, we select the keyframe
422               // we are interested in, we press "add", and this "locks" the
423               // 4 pots at the top of the module for editing this keyframe.
424               //active_keyframe_lock_ = true;
425             }
426             FindNearestKeyframe();
427           } else if (mode_ == UI_MODE_SAVE_CONFIRMATION) {
428             // confirming save -> write to active slot
429             keyframer_->feature_mode_ = feature_mode_;
430             keyframer_->Save(active_slot_);
431             mode_ = UI_MODE_SPLASH;
432           } else if (mode_ == UI_MODE_FEATURE_SWITCH) {
433             mode_ = UI_MODE_NORMAL;
434           } else if (feature_mode_ == FEAT_MODE_POLY_LFO) {
435             poly_lfo_->Reset();
436           } else if (feature_mode_ == FEAT_MODE_SEQ_STEP_EDIT) {
437             feature_mode_ = FEAT_MODE_SEQ_MAIN;
438           } else {
439             mode_ = UI_MODE_NORMAL;
440           }
441         }
442         break;
443 
444       case SWITCH_DELETE_FRAME:
445         if (e.data > kVeryLongPressDuration) {
446           mode_ = UI_MODE_ERASE_CONFIRMATION;
447         } else if (e.data > kLongPressDuration) {
448           if (feature_mode_ == FEAT_MODE_SEQ_MAIN) {
449             feature_mode_ = FEAT_MODE_SEQ_STEP_EDIT;
450           } else if (feature_mode_ == FEAT_MODE_KEYFRAMER ||
451                      feature_mode_ == FEAT_MODE_KEYFRAME_LOOPER) {
452             mode_ = UI_MODE_EDIT_RESPONSE;
453             active_channel_ = -1;
454           } else if (feature_mode_ == FEAT_MODE_EUCLIDEAN) {
455             mode_ = UI_MODE_EDIT_SHAPE;
456           }
457         } else if (mode_ == UI_MODE_ERASE_CONFIRMATION) {
458           if (active_slot_ == 0) {
459             keyframer_->Clear();
460             FindNearestKeyframe();
461             SyncWithPots();
462             feature_mode_ = FEAT_MODE_KEYFRAMER;
463           } else {
464             keyframer_->Load(active_slot_);
465             feature_mode_ = static_cast<FeatureMode>(keyframer_->feature_mode_);
466             for (int i=0; i<kNumChannels; i++) {
467               euclidean_[i].set_length(keyframer_->euclidean_length_[i]);
468               euclidean_[i].set_shape(keyframer_->euclidean_shape_[i]);
469             }
470           }
471           mode_ = UI_MODE_SPLASH;
472         } else {
473           if (mode_ == UI_MODE_NORMAL &&
474               (feature_mode_ == FEAT_MODE_KEYFRAMER ||
475                feature_mode_ == FEAT_MODE_KEYFRAME_LOOPER ||
476                feature_mode_ == FEAT_MODE_SEQ_MAIN ||
477                feature_mode_ == FEAT_MODE_SEQ_SHIFT_REGISTER)) {
478             if (active_keyframe_ != -1) {
479               keyframer_->RemoveKeyframe(
480                   keyframer_->keyframe(active_keyframe_).timestamp);
481             }
482             FindNearestKeyframe();
483             SyncWithPots();
484           } else if (mode_ == UI_MODE_FEATURE_SWITCH) {
485             mode_ = UI_MODE_NORMAL;
486           } else if (feature_mode_ == FEAT_MODE_POLY_LFO) {
487             poly_lfo_->Randomize();
488           } else if (feature_mode_ == FEAT_MODE_SEQ_STEP_EDIT) {
489             feature_mode_ = FEAT_MODE_SEQ_MAIN;
490           } else {
491             mode_ = UI_MODE_NORMAL;
492           }
493         }
494         break;
495     }
496   }
497 }
498 
ParseShiftSequencer(uint16_t control_id,int32_t data)499   void Ui::ParseShiftSequencer(uint16_t control_id, int32_t data) {
500   // knob 1 is sequence order randomization, knobs 2 and 3
501   // are divisors for the shift register, knob 4 randomizes
502   // feedback value
503   switch (control_id) {
504   case 0:
505     if (active_keyframe_ != -1) {
506       Keyframe* k = keyframer_->mutable_keyframe(active_keyframe_);
507       k->values[0] = data;
508     } else {
509       keyframer_->set_immediate(0, data);
510     }
511     break;
512   case 1:
513     if (data < 32768) {
514       step_random = 0;
515       step_divider = (((32768 - data) * kDividersSteps >> 15) + 1) % kDividersSteps;
516     } else {
517       int16_t rnd = data - 32768;
518       rnd = (rnd * rnd) >> 15;
519       step_random = rnd >> 7;
520       step_divider = 1;
521     }
522     break;
523   case 2:
524     if (data < 32768) {
525       shift_random = 0;
526       shift_divider = (((32768 - data) * kDividersSteps >> 15) + 1) % kDividersSteps;
527     } else {
528       int16_t rnd = data - 32768;
529       rnd = (rnd * rnd) >> 15;
530       shift_random = rnd >> 7;
531       shift_divider = 1;
532     }
533     break;
534   case 3:
535     if (data < 32768) {
536       feedback_random = 0;
537       int16_t rnd = 32768 - data;
538       rnd = (rnd * rnd) >> 15;
539       sequencer_random = rnd >> 7;
540     } else {
541       int16_t rnd = data - 32768;
542       rnd = (rnd * rnd) >> 15;
543       feedback_random = rnd >> 7;
544       sequencer_random = 0;
545     }
546     break;
547     feedback_random = data >> 8;
548     break;
549   case kFrameAdcChannel:
550     if (!active_keyframe_lock_) {
551       FindNearestKeyframe();
552     }
553     // big knob also sets number of registers
554     active_registers = (data * kMaxRegisters >> 16) + 1;
555   }
556 }
557 
558 
ParsePolyLFO(uint16_t control_id,int32_t data)559 void Ui::ParsePolyLFO(uint16_t control_id, int32_t data) {
560   switch (control_id) {
561   case 0:
562     poly_lfo_->set_shape(data);
563     break;
564   case 1:
565     poly_lfo_->set_shape_spread(data);
566     break;
567   case 2:
568     poly_lfo_->set_spread(data);
569     break;
570   case 3:
571     poly_lfo_->set_coupling(data);
572     break;
573   }
574 }
575 
ParseEuclidean(uint16_t control_id,int32_t data)576 void Ui::ParseEuclidean(uint16_t control_id, int32_t data) {
577   if (mode_ == UI_MODE_EDIT_LENGTH) {
578     switch (control_id) {
579     case 0:
580     case 1:
581     case 2:
582     case 3:
583     {
584       uint8_t len = (data >> 12) + 1;
585       euclidean_[control_id].set_length(len);
586       keyframer_->euclidean_length_[control_id] = len;
587     }
588     break;
589     case kFrameAdcChannel:
590       for (int i=0; i<kNumChannels; i++)
591         euclidean_[i].set_rotate(data * i);
592       break;
593     }
594   } else if (mode_ == UI_MODE_EDIT_SHAPE) {
595     switch (control_id) {
596     case 0:
597     case 1:
598     case 2:
599     case 3:
600     {
601       euclidean_[control_id].set_shape(data);
602       keyframer_->euclidean_shape_[control_id] = data;
603     }
604     break;
605     case kFrameAdcChannel:
606       for (int i=0; i<kNumChannels; i++)
607         euclidean_[i].set_rotate(data * i);
608       break;
609     }
610   } else {
611     // normal mode or scratch or feature switch
612     switch (control_id) {
613     case 0:
614     case 1:
615     case 2:
616     case 3:
617       euclidean_[control_id].set_fill(data);
618       break;
619     case kFrameAdcChannel:
620       for (int i=0; i<kNumChannels; i++)
621         euclidean_[i].set_rotate(data * i);
622       break;
623     }
624   }
625 }
626 
OnPotChanged(const Event & e)627 void Ui::OnPotChanged(const Event& e) {
628   if (mode_ == UI_MODE_FACTORY_TESTING) {
629     switch (e.control_id) {
630       case 0:
631       case 1:
632       case 2:
633       case 3:
634         keyframer_->set_immediate(e.control_id, e.data);
635         break;
636     }
637   } else if (mode_ == UI_MODE_FEATURE_SWITCH) {
638     switch (e.control_id) {
639       case kFrameAdcChannel:
640         feature_mode_ = e.data > 60000 ?
641           FEAT_MODE_KEYFRAME_LOOPER :
642           FEAT_MODE_KEYFRAMER;
643         SyncWithPots();
644         break;
645       case 0:
646         feature_mode_ = FEAT_MODE_SEQ_MAIN;
647         SyncWithPots();
648         break;
649       case 1:
650         feature_mode_ = FEAT_MODE_SEQ_SHIFT_REGISTER;
651         SyncWithPotsShiftSequencer();
652         break;
653       case 2:
654         feature_mode_ = FEAT_MODE_POLY_LFO;
655         SyncWithPotsPolyLFO();
656         break;
657       case 3:
658         feature_mode_ = FEAT_MODE_EUCLIDEAN;
659         // TODO marche pas
660         SyncWithPotsEuclidean();
661         break;
662     }
663   } else if (mode_ == UI_MODE_SAVE_CONFIRMATION ||
664              mode_ == UI_MODE_ERASE_CONFIRMATION) {
665     switch (e.control_id) {
666     case 0:
667     case 1:
668     case 2:
669     case 3:
670       active_slot_ = e.control_id + 1;
671       break;
672     case kFrameAdcChannel:
673       active_slot_ = 0;
674     }
675   } else if (feature_mode_ == FEAT_MODE_POLY_LFO) {
676     ParsePolyLFO(e.control_id, e.data);
677   } else if (feature_mode_ == FEAT_MODE_SEQ_STEP_EDIT) {
678     switch (e.control_id) {
679       case 0:
680       case 1:
681       case 2:
682       case 3:
683         // the controls directly edit the value of the current step
684         Keyframe* k = keyframer_->mutable_keyframe(sequencer_step);
685         k->values[e.control_id] = e.data;
686     }
687 
688   } else if (feature_mode_ == FEAT_MODE_EUCLIDEAN) {
689     ParseEuclidean(e.control_id, e.data);
690 
691   } else if (feature_mode_ == FEAT_MODE_SEQ_SHIFT_REGISTER) {
692     ParseShiftSequencer(e.control_id, e.data);
693   } else {
694     switch (e.control_id) {
695       case 0:
696       case 1:
697       case 2:
698       case 3:
699         if (mode_ == UI_MODE_NORMAL || mode_ == UI_MODE_SPLASH) {
700           if (active_keyframe_ != -1) {
701             Keyframe* k = keyframer_->mutable_keyframe(active_keyframe_);
702             k->values[e.control_id] = e.data;
703           } else {
704             keyframer_->set_immediate(e.control_id, e.data);
705           }
706         } else if (mode_ == UI_MODE_EDIT_RESPONSE) {
707           active_channel_ = e.control_id;
708           keyframer_->mutable_settings(e.control_id)->response = e.data >> 8;
709         } else if (mode_ == UI_MODE_EDIT_EASING) {
710           active_channel_ = e.control_id;
711           keyframer_->mutable_settings(e.control_id)->easing_curve =    \
712             static_cast<EasingCurve>(e.data * 6 >> 16);
713         }
714         break;
715       case kFrameAdcChannel:
716         if (!active_keyframe_lock_) {
717           FindNearestKeyframe();
718         }
719         break;
720       case kFrameModulationAdcChannel:
721         break;
722     }
723   }
724 }
725 
FindNearestKeyframe()726 void Ui::FindNearestKeyframe() {
727   active_keyframe_ = keyframer_->FindNearestKeyframe(
728       frame(),
729       kKeyframeGridTolerance);
730 }
731 
SyncWithPots()732 void Ui::SyncWithPots() {
733   if (!keyframer_->num_keyframes()) {
734     for (uint8_t i = 0; i < kNumChannels; ++i) {
735       keyframer_->set_immediate(i, adc_filtered_value_[i]);
736     }
737   }
738 }
739 
SyncWithPotsShiftSequencer()740 void Ui::SyncWithPotsShiftSequencer() {
741   for (uint8_t i = 0; i < kNumChannels; ++i) {
742     ParseShiftSequencer(i, adc_value_[i]);
743   }
744 }
745 
SyncWithPotsEuclidean()746 void Ui::SyncWithPotsEuclidean() {
747   for (uint8_t i = 0; i < kNumChannels; ++i) {
748     ParseEuclidean(i, adc_value_[i]);
749   }
750 }
751 
SyncWithPotsPolyLFO()752 void Ui::SyncWithPotsPolyLFO() {
753   for (uint8_t i = 0; i < kNumChannels; ++i) {
754     ParsePolyLFO(i, adc_value_[i]);
755   }
756 }
757 
DoEvents()758 void Ui::DoEvents() {
759   while (queue_.available()) {
760     Event e = queue_.PullEvent();
761     if (e.control_type == CONTROL_SWITCH) {
762       if (e.data == 0) {
763         OnSwitchPressed(e);
764       } else {
765         OnSwitchReleased(e);
766       }
767     } else if (e.control_type == CONTROL_POT) {
768       OnPotChanged(e);
769     }
770   }
771   if (queue_.idle_time() > 500) {
772     queue_.Touch();
773     if (mode_ == UI_MODE_SPLASH) {
774       mode_ = UI_MODE_NORMAL;
775     }
776   }
777 }
778 
779 }  // namespace frames
780