| 
							- // Copyright 2013 Olivier Gillet.
 - //
 - // Author: Olivier Gillet (ol.gillet@gmail.com)
 - //
 - // Permission is hereby granted, free of charge, to any person obtaining a copy
 - // of this software and associated documentation files (the "Software"), to deal
 - // in the Software without restriction, including without limitation the rights
 - // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 - // copies of the Software, and to permit persons to whom the Software is
 - // furnished to do so, subject to the following conditions:
 - // 
 - // The above copyright notice and this permission notice shall be included in
 - // all copies or substantial portions of the Software.
 - // 
 - // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 - // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 - // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 - // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 - // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 - // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 - // THE SOFTWARE.
 - // 
 - // See http://creativecommons.org/licenses/MIT/ for more information.
 - //
 - // -----------------------------------------------------------------------------
 - //
 - // User interface.
 - 
 - #include "streams/ui.h"
 - 
 - #include <algorithm>
 - 
 - #include "stmlib/system/storage.h"
 - #include "stmlib/system/system_clock.h"
 - 
 - #include "streams/drivers/adc.h"
 - #include "streams/processor.h"
 - 
 - namespace streams {
 - 
 - const int32_t kLongPressDuration = 1000;
 - 
 - using namespace std;
 - using namespace stmlib;
 - 
 - Storage<0x801fc00, 4> ui_settings_storage;
 - 
 - void Ui::Init(Adc* adc, CvScaler* cv_scaler, Processor* processor) {
 -   leds_.Init();
 -   switches_.Init();
 -   adc_ = adc;
 -   cv_scaler_ = cv_scaler;
 -   processor_ = processor;
 -   
 -   fill(&pot_value_[0], &pot_value_[kNumPots], 0);
 -   fill(&pot_threshold_[0], &pot_threshold_[kNumPots], 0);
 -   
 -   if (!ui_settings_storage.ParsimoniousLoad(&ui_settings_, &version_token_)) {
 -     // Flash is not formatted. Initialize.
 -     for (uint8_t i = 0; i < kNumChannels; ++i) {
 -       ui_settings_.function[i] = PROCESSOR_FUNCTION_ENVELOPE;
 -       ui_settings_.alternate[i] = false;
 -     }
 -     ui_settings_.monitor_mode = MONITOR_MODE_OUTPUT;
 -     ui_settings_.linked = false;
 -   }
 -   
 -   // Initialize from settings in flash.
 -   monitor_mode_ = static_cast<MonitorMode>(ui_settings_.monitor_mode);
 -   for (uint8_t i = 0; i < kNumChannels; ++i) {
 -     meter_[i].Init();
 -     processor_[i].set_alternate(ui_settings_.alternate[i]);
 -     processor_[i].set_linked(ui_settings_.linked);
 -     processor_[i].set_function(
 -         static_cast<ProcessorFunction>(ui_settings_.function[i]));
 -     display_mode_[i] = DISPLAY_MODE_MONITOR;
 -   }
 -   
 -   secret_handshake_counter_ = 0;
 -   factory_testing_ = switches_.pressed_immediate(SWITCH_MONITOR);
 - }
 - 
 - void Ui::SaveState() {
 -   ui_settings_.monitor_mode = monitor_mode_;
 -   ui_settings_.linked = processor_[0].linked();
 -   ui_settings_.function[0] = processor_[0].function();
 -   ui_settings_.function[1] = processor_[1].function();
 -   ui_settings_.alternate[0] = processor_[0].alternate();
 -   ui_settings_.alternate[1] = processor_[1].alternate();
 -   ui_settings_storage.ParsimoniousSave(ui_settings_, &version_token_);
 - }
 - 
 - void Ui::PaintAdaptive(uint8_t channel, int32_t sample, int32_t gain) {
 -   meter_[channel].Process(sample);
 -   if (meter_[channel].cv()) {
 -     sample = sample * lut_2164_gain[-gain >> 9] >> 15;
 -     leds_.PaintCv(channel, sample * 5 >> 2);
 -   } else {
 -     leds_.PaintPositiveBar(channel, wav_db[meter_[channel].peak() >> 7] + gain);
 -   }
 - }
 - 
 - void Ui::PaintMonitor(uint8_t channel) {
 -   switch (monitor_mode_) {
 -     case MONITOR_MODE_EXCITE_IN:
 -       PaintAdaptive(channel, cv_scaler_->excite_sample(channel), 0);
 -       break;
 -       
 -     case MONITOR_MODE_AUDIO_IN:
 -       PaintAdaptive(channel, cv_scaler_->audio_sample(channel), 0);
 -       break;
 -       
 -     case MONITOR_MODE_VCA_CV:
 -       leds_.PaintPositiveBar(channel, 32768 + cv_scaler_->gain_sample(channel));
 -       break;
 -     
 -     case MONITOR_MODE_OUTPUT:
 -       if (processor_[channel].function() == PROCESSOR_FUNCTION_COMPRESSOR) {
 -         leds_.PaintNegativeBar(channel, processor_[channel].gain_reduction());
 -       } else {
 -         PaintAdaptive(
 -             channel,
 -             cv_scaler_->audio_sample(channel),
 -             cv_scaler_->gain_sample(channel));
 -       }
 -       break;
 -       
 -     default:
 -       break;
 -   }
 - }
 - 
 - void Ui::PaintTestStatus() {
 -   int32_t value = 0;
 -   value += pot_value_[0] - 32768;
 -   value += pot_value_[1] - 32768;
 -   value += pot_value_[2] - 32768;
 -   value += pot_value_[3] - 32768;
 -   value -= cv_scaler_->excite_sample(0) > 0 ? 0 : cv_scaler_->excite_sample(0);
 -   value -= cv_scaler_->excite_sample(1) > 0 ? 0 : cv_scaler_->excite_sample(1);
 -   value -= cv_scaler_->gain_sample(0);
 -   value -= cv_scaler_->gain_sample(1);
 -   value -= cv_scaler_->audio_sample(0) - 12000;
 -   value -= cv_scaler_->audio_sample(1) - 12000;
 -   if (switches_.pressed(0)) value = -32767;
 -   if (switches_.pressed(1)) value = 32767;
 -   CONSTRAIN(value, -32767, 32767);
 -   if (value < 12288 && value > -12288) value = 0;
 -   uint8_t r = value >= 0 ? 0 : ((-1 - value) >> 7);
 -   uint8_t g = value > 0 ? (value >> 7) : 0;
 -   for (uint8_t i = 0; i < 8; ++i) {
 -     leds_.set(i, r, g);
 -   }
 - }
 - 
 - void Ui::PaintLeds() {
 -   leds_.Clear();
 -   
 -   if (calibrating_) {
 -     for (uint8_t i = 0; i < kNumChannels; ++i) {
 -       uint8_t red, green;
 -       if (show_offset_level_ & (1 << i)) {
 -         int32_t gain_sample = cv_scaler_->raw_gain_sample(i);
 -         bool nulled = gain_sample > 59000;
 -         green = nulled ? 255 : 0;
 -         red = nulled ? 0 : 255;
 -       } else {
 -         red = 0;
 -         green = 255;
 -       }
 -       uint8_t pattern = i == 0 ? 255 : 9;
 -       for (uint8_t j = 0; j < 4; ++j) {
 -         bool on = (pattern & (1 << j)) != 0;
 -         leds_.set(i * 4 + j, on ? red : 0, on ? green : 0);
 -       }
 -     }
 -     return;
 -   }
 -   
 -   if (factory_testing_) {
 -     PaintTestStatus();
 -     return;
 -   }
 -   
 -   for (uint8_t i = 0; i < kNumChannels; ++i) {
 -     uint8_t bank = i * 4;
 -     switch (display_mode_[i]) {
 -       case DISPLAY_MODE_FUNCTION:
 -         {
 -           bool alternate = processor_[i].alternate();
 -           uint8_t intensity = 255;
 -           if (processor_[i].linked()) {
 -             uint8_t phase = system_clock.milliseconds() >> 1;
 -             phase += i * 128;
 -             phase = phase < 128 ? phase : (255 - phase);
 -             intensity = (phase * 224 >> 7) + 32;
 -             intensity = intensity * intensity >> 8;
 -           }
 -           uint8_t function = processor_[i].function();
 -           if (function == PROCESSOR_FUNCTION_FILTER_CONTROLLER) {
 -             for (uint8_t j = 0; j < 4; ++j) {
 -               leds_.set(bank + j,
 -                   alternate ? intensity : 0,
 -                   alternate ? 0 : intensity);
 -             }
 -           } else if (function < PROCESSOR_FUNCTION_LORENZ_GENERATOR) {
 -             leds_.set(
 -                 bank + function,
 -                 alternate ? intensity : 0,
 -                 alternate ? 0 : intensity);
 -           } else {
 -             uint8_t index = (processor_[i].last_gain() >> 4) * 5 >> 4;
 -             if (index > 3) index = 3;
 -             int16_t color = processor_[i].last_frequency();
 -             color = color - 128;
 -             color *= 2;
 -             if (color < 0) {
 -               if (color < -127) color = -127;
 -               leds_.set(bank + index, 255 + (color * 2), 255);
 -             } else {
 -               if (color > 127) color = 127;
 -               leds_.set(bank + index, 255, 255 - (color * 2));
 -             }
 -           }
 -         }
 -         break;
 -         
 -       case DISPLAY_MODE_MONITOR_FUNCTION:
 -         {
 -           uint8_t position = static_cast<uint8_t>(monitor_mode_);
 -           leds_.set(position * 2, 255, 0);
 -           leds_.set(position * 2 + 1, 255, 0);
 -         }
 -         break;
 -       
 -       case DISPLAY_MODE_MONITOR:
 -         PaintMonitor(i);
 -         break;
 -     }
 -   }
 - }
 - 
 - void Ui::Poll() {
 -   // SysTick is at 4kHz to get a fast bargraph refresh.
 -   ++divider_;
 -   if ((divider_ & 3) == 0) {
 -     system_clock.Tick();
 -     switches_.Debounce();
 -   
 -     for (uint8_t i = 0; i < kNumSwitches; ++i) {
 -       if (switches_.just_pressed(i)) {
 -         queue_.AddEvent(CONTROL_SWITCH, i, 0);
 -         press_time_[i] = system_clock.milliseconds();
 -       }
 -       if (switches_.pressed(i) && press_time_[i] != 0) {
 -         int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
 -         if (pressed_time > kLongPressDuration) {
 -           queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
 -           press_time_[i] = 0;
 -         }
 -       }
 -       if (switches_.released(i) && press_time_[i] != 0) {
 -         queue_.AddEvent(
 -             CONTROL_SWITCH,
 -             i,
 -             system_clock.milliseconds() - press_time_[i] + 1);
 -         press_time_[i] = 0;
 -       }
 -     }
 -   
 -     adc_->ScanPots();
 -     for (uint8_t i = 0; i < kNumPots; ++i) {
 -       int32_t value = adc_->pot(i);
 -       int32_t current_value = pot_value_[i];
 -       if (value >= current_value + pot_threshold_[i] ||
 -           value <= current_value - pot_threshold_[i] ||
 -           !pot_threshold_[i]) {
 -         Event e;
 -         e.control_id = i;
 -         e.data = value;
 -         queue_.AddEvent(CONTROL_POT, i, e.data);
 -         pot_value_[i] = value;
 -         pot_threshold_[i] = 256;
 -       }
 -     }
 -   }
 -   PaintLeds();
 -   leds_.Write();
 - }
 - 
 - void Ui::FlushEvents() {
 -   queue_.Flush();
 - }
 - 
 - void Ui::Link(uint8_t index) {
 -   if (processor_[0].linked()) {
 -     for (uint8_t i = 0; i < kNumChannels; ++i) {
 -       if (i != index) {
 -         display_mode_[i] = display_mode_[index];
 -         processor_[i].set_function(processor_[index].function());
 -         processor_[i].set_alternate(processor_[index].alternate());
 -       }
 -     }
 -   }
 - }
 - 
 - void Ui::OnPotMoved(const Event& e) {
 -   if (calibrating_) {
 -     if ((e.control_id & 1) == 0) {
 -       int32_t min = kDefaultOffset >> 1;
 -       int32_t max = 3 * min + 256;
 -       int32_t value = min + ((max - min) * e.data >> 16);
 -       cv_scaler_->set_dac_offset(e.control_id >> 1, value);
 -       show_offset_level_ |= (1 << (e.control_id >> 1));
 -     }
 -   } else {
 -     processor_[0].set_global(e.control_id, e.data);
 -     processor_[1].set_global(e.control_id, e.data);
 -     processor_[e.control_id >> 1].set_parameter(e.control_id & 1, e.data);
 -   }
 - }
 - 
 - void Ui::OnSwitchPressed(const Event& e) {
 -   if (factory_testing_) {
 -     if (e.control_id == SWITCH_MONITOR) {
 -       ++secret_handshake_counter_;
 -       if (secret_handshake_counter_ == 4) {
 -         factory_testing_ = false;
 -       }
 -     }
 -     return;
 -   }
 -   if (calibrating_) {
 -     cv_scaler_->SaveCalibrationData();
 -     calibrating_ = false;
 -     show_offset_level_ = 0;
 -     return;
 -   }
 -   // Double press!
 -   if ((e.control_id == SWITCH_MODE_1 && press_time_[SWITCH_MODE_2]) ||
 -       (e.control_id == SWITCH_MODE_2 && press_time_[SWITCH_MODE_1])) {
 -     press_time_[SWITCH_MODE_1] = press_time_[SWITCH_MODE_2] = 0;
 -     bool linked = !processor_[0].linked();
 -     for (uint8_t i = 0; i < kNumChannels; ++i) {
 -       display_mode_[i] = DISPLAY_MODE_FUNCTION;
 -       processor_[i].set_linked(linked);
 -     }
 -     Link(1 - e.control_id);
 -     SaveState();
 -     return;
 -   }
 -   
 -   switch (e.control_id) {
 -     case SWITCH_MONITOR:
 -       {
 -         if (display_mode_[0] == DISPLAY_MODE_MONITOR &&
 -             display_mode_[1] == DISPLAY_MODE_MONITOR) {
 -           display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR_FUNCTION;
 -         } else if (display_mode_[0] == DISPLAY_MODE_MONITOR_FUNCTION &&
 -                    display_mode_[1] == DISPLAY_MODE_MONITOR_FUNCTION) {
 -           monitor_mode_ = static_cast<MonitorMode>(monitor_mode_ + 1);
 -           if (monitor_mode_ == MONITOR_MODE_LAST) {
 -             monitor_mode_ = static_cast<MonitorMode>(0);
 -           }
 -           SaveState();
 -         } else {
 -           display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR;
 -         }
 -       }
 -       break;
 -       
 -     default:
 -       break;
 -   }
 - }
 - 
 - void Ui::OnSwitchReleased(const Event& e) {
 -   if (factory_testing_) {
 -     return;
 -   }
 -   
 -   // Detect secret handshake for easter egg...
 -   uint8_t secret_handshake_code = e.control_id;
 -   secret_handshake_code |= e.data >= kLongPressDuration ? 2 : 0;
 -   if ((secret_handshake_counter_ & 3) == secret_handshake_code) {
 -     ++secret_handshake_counter_;
 -     if (secret_handshake_counter_ == 16) {
 -       for (uint8_t i = 0; i < kNumChannels; ++i) {
 -         processor_[i].set_alternate(false);
 -         processor_[i].set_function(PROCESSOR_FUNCTION_LORENZ_GENERATOR);
 -       }
 -       SaveState();
 -       secret_handshake_counter_ = 0;
 -       return;
 -     }
 -   } else {
 -     secret_handshake_counter_ = 0;
 -   }
 -   
 -   if (e.data >= kLongPressDuration) {
 -     // Handle long presses.
 -     switch (e.control_id) {
 -       case SWITCH_MONITOR:
 -         calibrating_ = cv_scaler_->can_calibrate();
 -         if (calibrating_) {
 -           cv_scaler_->CaptureAdcOffsets();
 -           show_offset_level_ = 0;
 -         }
 -         break;
 -         
 -       case SWITCH_MODE_1:
 -       case SWITCH_MODE_2:
 -         {
 -           processor_[e.control_id].set_alternate(
 -               !processor_[e.control_id].alternate());
 -           if (processor_[e.control_id].function() >
 -               PROCESSOR_FUNCTION_COMPRESSOR) {
 -             processor_[e.control_id].set_function(PROCESSOR_FUNCTION_ENVELOPE);
 -           }
 -           display_mode_[e.control_id] = DISPLAY_MODE_FUNCTION;
 -           int32_t other = 1 - e.control_id;
 -           if (display_mode_[other] == DISPLAY_MODE_MONITOR_FUNCTION) {
 -             display_mode_[other] = DISPLAY_MODE_MONITOR;
 -           }
 -           Link(e.control_id);
 -           SaveState();
 -         }
 -         break;
 -     }
 -   } else {
 -     switch (e.control_id) {
 -       case SWITCH_MODE_1:
 -       case SWITCH_MODE_2:
 -         {
 -           if (display_mode_[e.control_id] == DISPLAY_MODE_FUNCTION) {
 -             ProcessorFunction index = processor_[e.control_id].function();
 -             index = static_cast<ProcessorFunction>(index + 1);
 -             ProcessorFunction limit = processor_[e.control_id].alternate()
 -                 ? PROCESSOR_FUNCTION_FILTER_CONTROLLER
 -                 : PROCESSOR_FUNCTION_COMPRESSOR;
 -             if (index > limit) {
 -               index = static_cast<ProcessorFunction>(0);
 -             }
 -             processor_[e.control_id].set_function(index);
 -             SaveState();
 -           } else {
 -             display_mode_[e.control_id] = DISPLAY_MODE_FUNCTION;
 -             int32_t other = 1 - e.control_id;
 -             if (display_mode_[other] == DISPLAY_MODE_MONITOR_FUNCTION) {
 -               display_mode_[other] = DISPLAY_MODE_MONITOR;
 -             }
 -           }
 -           Link(e.control_id);
 -         }
 -         break;
 -       
 -       default:
 -         break;
 -     }
 -   }
 - }
 - 
 - void Ui::DoEvents() {
 -   bool refresh = false;
 -   while (queue_.available()) {
 -     Event e = queue_.PullEvent();
 -     if (e.control_type == CONTROL_SWITCH) {
 -       if (e.data == 0) {
 -         OnSwitchPressed(e);
 -       } else {
 -         OnSwitchReleased(e);
 -       }
 -     } else if (e.control_type == CONTROL_POT) {
 -       OnPotMoved(e);
 -     }
 -     refresh = true;
 -   }
 -   if (queue_.idle_time() > 1000) {
 -     queue_.Touch();
 -     if (display_mode_[0] == DISPLAY_MODE_MONITOR_FUNCTION && 
 -         display_mode_[1] == DISPLAY_MODE_MONITOR_FUNCTION) {
 -        display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR;   
 -     }
 -     refresh = true;
 -   }
 -   
 -   // Recompute processor parameters if necessary.
 -   if (refresh) {
 -     for (uint8_t i = 0; i < kNumChannels; ++i) {
 -       processor_[i].Configure();
 -     }
 -   }
 - }
 - 
 - }  // namespace streams
 
 
  |