Files

copied
Last update 6 years 3 months by Olivier Gillet
Filestides
..
bootloader
drivers
easter_egg
hardware_design
resources
test
__init__.py
cv_scaler.cc
cv_scaler.h
generator.cc
generator.h
makefile
plotter.cc
plotter.h
resources.cc
resources.h
tides.cc
ui.cc
ui.h
ui.cc
// 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 "tides/ui.h" #include "stmlib/system/storage.h" #include "stmlib/system/system_clock.h" #include "tides/cv_scaler.h" #include "tides/generator.h" namespace tides { const int32_t kLongPressDuration = 1000; using namespace stmlib; Storage<0x801fc00, 4> mode_storage; void Ui::Init(Generator* generator, CvScaler* cv_scaler) { factory_testing_switch_.Init(); leds_.Init(); switches_.Init(); mode_ = factory_testing_switch_.Read() ? UI_MODE_NORMAL : UI_MODE_FACTORY_TESTING; generator_ = generator; cv_scaler_ = cv_scaler; if (!mode_storage.ParsimoniousLoad(&settings_, &version_token_)) { mode_counter_ = 1; range_counter_ = 2; generator->set_sync(false); } else { mode_counter_ = settings_.mode; range_counter_ = 2 - settings_.range; generator->set_sync(settings_.sync); } UpdateMode(); UpdateRange(); leds_.set_value(32768, 32768); } void Ui::SaveState() { settings_.mode = generator_->mode(); settings_.range = generator_->range(); settings_.sync = generator_->sync(); mode_storage.ParsimoniousSave(settings_, &version_token_); } const uint16_t thresholds[ADC_CHANNEL_LAST][2] = { { 0, 64000 }, { 16384, 49152 }, { 16384, 49152 }, { 4096, 61440 }, { 4096, 61440 }, { 4096, 61440 }, { 4096, 61440 }, }; void Ui::UpdateFactoryTestingFlags( uint8_t gate_input_flags, const uint16_t* adc_values) { red_ = switches_.pressed(1); green_ = switches_.pressed(0); orange_ = gate_input_flags & CONTROL_GATE; orange_ |= gate_input_flags & CONTROL_FREEZE; orange_ |= gate_input_flags & CONTROL_CLOCK; for (uint16_t i = 0; i < ADC_CHANNEL_LAST; ++i) { uint16_t value = adc_values[i]; if (i == ADC_CHANNEL_FM_ATTENUVERTER) { value = ~value; } green_ |= value < thresholds[i][0]; if (i == 0) { orange_ |= value > thresholds[i][1]; } else { red_ |= value > thresholds[i][1]; } } } void Ui::Poll() { 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; } } switch (mode_) { case UI_MODE_NORMAL: { GeneratorMode mode = generator_->mode(); leds_.set_mode(mode == GENERATOR_MODE_AR, mode == GENERATOR_MODE_AD); GeneratorRange range = generator_->range(); switch (range) { case GENERATOR_RANGE_LOW: leds_.set_rate(0, 65535); break; case GENERATOR_RANGE_MEDIUM: if (generator_->sync()) { leds_.set_rate(8192, 16384); } else { leds_.set_rate(0); } break; case GENERATOR_RANGE_HIGH: leds_.set_rate(65535, 0); break; } bool blink_rate_led = generator_->sync() && \ system_clock.milliseconds() & 128; if (blink_rate_led) { leds_.set_rate(0); } } break; case UI_MODE_CALIBRATION_C2: leds_.set_mode(true); leds_.set_rate(65535); leds_.set_value(65535); break; case UI_MODE_CALIBRATION_C4: leds_.set_mode(false, true); leds_.set_rate(0, 65535); leds_.set_value(0, 65535); break; case UI_MODE_PAQUES: leds_.set_mode(true, false); leds_.set_rate(65535, 0); leds_.set_value(65535, 0); break; case UI_MODE_FACTORY_TESTING: if (orange_) { leds_.set_mode(true, true); leds_.set_rate(65535, 65535); leds_.set_value(65535, 65535); } else if (red_) { leds_.set_mode(true, 0); leds_.set_rate(65535, 0); leds_.set_value(65535, 0); } else if (green_) { leds_.set_mode(false, true); leds_.set_rate(0, 65535); leds_.set_value(0, 65535); } else { leds_.set_mode(false, false); leds_.set_rate(0, 0); leds_.set_value(0, 0); } break; } leds_.Write(); } inline void Ui::UpdateMode() { uint8_t i = mode_counter_ & 3; if (i == 3) { i = 1; } generator_->set_mode(static_cast<GeneratorMode>(i)); SaveState(); } inline void Ui::UpdateRange() { uint8_t i = range_counter_ & 3; if (i == 3) { i = 1; } generator_->set_range(static_cast<GeneratorRange>(2 - i)); SaveState(); } void Ui::FlushEvents() { queue_.Flush(); } void Ui::OnSwitchPressed(const Event& e) { switch (e.control_id) { case 0: break; case 1: break; } } void Ui::OnSwitchReleased(const Event& e) { if (mode_ == UI_MODE_FACTORY_TESTING) { return; } else if (mode_ == UI_MODE_PAQUES) { mode_ = UI_MODE_NORMAL; } else if (mode_ == UI_MODE_CALIBRATION_C2) { if (e.data > kLongPressDuration) { ++long_press_counter_; } if (e.control_id == 0) { cv_scaler_->CaptureCalibrationValues(); mode_ = UI_MODE_CALIBRATION_C4; } else { mode_ = UI_MODE_NORMAL; } } else if (mode_ == UI_MODE_CALIBRATION_C4) { mode_ = UI_MODE_NORMAL; if (e.control_id == 0) { cv_scaler_->Calibrate(); } else if (e.control_id == 1 && long_press_counter_ == 1 && e.data > kLongPressDuration) { mode_ = UI_MODE_PAQUES; } } else { long_press_counter_ = 0; switch (e.control_id) { case 0: if (e.data > kLongPressDuration && cv_scaler_->can_enter_calibration()) { mode_ = UI_MODE_CALIBRATION_C2; } else { ++mode_counter_; UpdateMode(); } break; case 1: if (e.data > kLongPressDuration) { generator_->set_sync(!generator_->sync()); SaveState(); } else { ++range_counter_; UpdateRange(); } break; } } } void Ui::DoEvents() { while (queue_.available()) { Event e = queue_.PullEvent(); if (e.control_type == CONTROL_SWITCH) { if (e.data == 0) { OnSwitchPressed(e); } else { OnSwitchReleased(e); } } } if (queue_.idle_time() > 1000) { queue_.Touch(); } } } // namespace tides
Report a bug