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