You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
5.6KB

  1. // Copyright 2014 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. #include "elements/ui.h"
  29. #include <algorithm>
  30. #include "stmlib/system/system_clock.h"
  31. #include "elements/cv_scaler.h"
  32. #include "elements/dsp/part.h"
  33. namespace elements {
  34. using namespace std;
  35. using namespace stmlib;
  36. void Ui::Init(Part* part, CvScaler* cv_scaler) {
  37. leds_.Init();
  38. switch_.Init();
  39. mode_ = UI_MODE_NORMAL;
  40. part_ = part;
  41. cv_scaler_ = cv_scaler;
  42. part_->set_easter_egg(cv_scaler_->boot_in_easter_egg_mode());
  43. }
  44. void Ui::Poll() {
  45. // 1kHz.
  46. system_clock.Tick();
  47. switch_.Debounce();
  48. if (switch_.just_pressed()) {
  49. queue_.AddEvent(CONTROL_SWITCH, 0, 0);
  50. press_time_ = system_clock.milliseconds();
  51. }
  52. if (switch_.pressed() && \
  53. press_time_ &&
  54. (system_clock.milliseconds() - press_time_) >= 5000) {
  55. if (cv_scaler_->ready_for_calibration()) {
  56. queue_.AddEvent(CONTROL_SWITCH, 1, 0);
  57. press_time_ = 0;
  58. } else if (cv_scaler_->easter_egg()) {
  59. queue_.AddEvent(CONTROL_SWITCH, 2, 0);
  60. press_time_ = 0;
  61. }
  62. }
  63. if (switch_.released() && press_time_) {
  64. queue_.AddEvent(
  65. CONTROL_SWITCH,
  66. 0,
  67. system_clock.milliseconds() - press_time_ + 1);
  68. }
  69. bool blink = (system_clock.milliseconds() & 127) > 64;
  70. switch (mode_) {
  71. case UI_MODE_NORMAL:
  72. leds_.set_gate(part_->gate());
  73. leds_.set_exciter(
  74. lut_db_led_brightness[int32_t(part_->exciter_level() * 512.0f)]);
  75. leds_.set_resonator(
  76. lut_db_led_brightness[int32_t(part_->resonator_level() * 512.0f)]);
  77. break;
  78. case UI_MODE_CALIBRATION_1:
  79. leds_.set_gate(!blink);
  80. leds_.set_exciter(blink ? 255 : 0);
  81. leds_.set_resonator(0);
  82. break;
  83. case UI_MODE_CALIBRATION_2:
  84. leds_.set_gate(!blink);
  85. leds_.set_exciter(0);
  86. leds_.set_resonator(blink ? 255 : 0);
  87. break;
  88. case UI_MODE_PANIC:
  89. leds_.set_gate(blink);
  90. leds_.set_exciter(blink ? 255 : 0);
  91. leds_.set_resonator(blink ? 0 : 255);
  92. break;
  93. }
  94. if (part_->bypass()) {
  95. leds_.set_gate(true);
  96. leds_.set_exciter(255);
  97. leds_.set_resonator(255);
  98. }
  99. leds_.Write();
  100. }
  101. void Ui::FlushEvents() {
  102. queue_.Flush();
  103. }
  104. void Ui::OnSwitchPressed(const Event& e) {
  105. switch (e.control_id) {
  106. case 0:
  107. if (mode_ == UI_MODE_CALIBRATION_1) {
  108. CalibrateC1();
  109. } else if (mode_ == UI_MODE_CALIBRATION_2) {
  110. CalibrateC3();
  111. } else {
  112. gate_ = true;
  113. }
  114. break;
  115. case 1:
  116. mode_ = UI_MODE_CALIBRATION_1;
  117. break;
  118. case 2:
  119. part_->set_easter_egg(!part_->easter_egg());
  120. cv_scaler_->set_boot_in_easter_egg_mode(part_->easter_egg());
  121. cv_scaler_->SaveCalibration();
  122. gate_ = false;
  123. break;
  124. default:
  125. break;
  126. }
  127. }
  128. void Ui::OnSwitchReleased(const Event& e) {
  129. gate_ = false;
  130. }
  131. void Ui::CalibrateC1() {
  132. cv_scaler_->CalibrateC1();
  133. cv_scaler_->CalibrateOffsets();
  134. mode_ = UI_MODE_CALIBRATION_2;
  135. }
  136. void Ui::CalibrateC3() {
  137. bool success = cv_scaler_->CalibrateC3();
  138. if (success) {
  139. cv_scaler_->SaveCalibration();
  140. mode_ = UI_MODE_NORMAL;
  141. } else {
  142. mode_ = UI_MODE_PANIC;
  143. }
  144. }
  145. void Ui::DoEvents() {
  146. while (queue_.available()) {
  147. Event e = queue_.PullEvent();
  148. if (e.control_type == CONTROL_SWITCH) {
  149. if (e.data == 0) {
  150. OnSwitchPressed(e);
  151. } else {
  152. OnSwitchReleased(e);
  153. }
  154. }
  155. }
  156. if (queue_.idle_time() > 800 && mode_ == UI_MODE_PANIC) {
  157. mode_ = UI_MODE_NORMAL;
  158. }
  159. if (queue_.idle_time() > 1000) {
  160. queue_.Touch();
  161. }
  162. }
  163. uint8_t Ui::HandleFactoryTestingRequest(uint8_t command) {
  164. uint8_t argument = command & 0x1f;
  165. command = command >> 5;
  166. uint8_t reply = 0;
  167. switch (command) {
  168. case FACTORY_TESTING_READ_POT:
  169. reply = cv_scaler_->pot_value(argument);
  170. break;
  171. case FACTORY_TESTING_READ_CV:
  172. reply = cv_scaler_->cv_value(argument);
  173. break;
  174. case FACTORY_TESTING_READ_GATE:
  175. if (argument == 0x00) {
  176. return gate_;
  177. } else {
  178. return cv_scaler_->gate();
  179. }
  180. break;
  181. case FACTORY_TESTING_SET_BYPASS:
  182. part_->set_bypass(argument);
  183. break;
  184. case FACTORY_TESTING_CALIBRATE:
  185. if (argument == 0) {
  186. mode_ = UI_MODE_CALIBRATION_1;
  187. } else if (argument == 1) {
  188. CalibrateC1();
  189. } else {
  190. CalibrateC3();
  191. }
  192. break;
  193. }
  194. return reply;
  195. }
  196. } // namespace elements