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.

261 lines
6.7KB

  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; // UI_MODE_DISPLAY_MODEL;
  40. part_ = part;
  41. cv_scaler_ = cv_scaler;
  42. part_->set_easter_egg(cv_scaler_->boot_in_easter_egg_mode());
  43. part_->set_resonator_model(ResonatorModel(cv_scaler_->resonator_model()));
  44. }
  45. void Ui::Poll() {
  46. // 1kHz.
  47. system_clock.Tick();
  48. switch_.Debounce();
  49. if (switch_.just_pressed()) {
  50. queue_.AddEvent(CONTROL_SWITCH, 0, 0);
  51. press_time_ = system_clock.milliseconds();
  52. }
  53. if (switch_.pressed() && \
  54. press_time_ &&
  55. (system_clock.milliseconds() - press_time_) >= 3000) {
  56. if (cv_scaler_->ready_for_calibration()) {
  57. queue_.AddEvent(CONTROL_SWITCH, 1, 0);
  58. press_time_ = 0;
  59. } else if (cv_scaler_->resonator_high()) {
  60. if (cv_scaler_->exciter_low()) {
  61. queue_.AddEvent(CONTROL_SWITCH, 2, 0);
  62. } else {
  63. queue_.AddEvent(CONTROL_SWITCH, 3, 0);
  64. }
  65. press_time_ = 0;
  66. }
  67. }
  68. if (switch_.released() && press_time_) {
  69. queue_.AddEvent(
  70. CONTROL_SWITCH,
  71. 0,
  72. system_clock.milliseconds() - press_time_ + 1);
  73. }
  74. bool blink = (system_clock.milliseconds() & 127) > 64;
  75. switch (mode_) {
  76. case UI_MODE_NORMAL:
  77. leds_.set_gate(part_->gate());
  78. leds_.set_exciter(
  79. lut_db_led_brightness[int32_t(part_->exciter_level() * 512.0f)]);
  80. leds_.set_resonator(
  81. lut_db_led_brightness[int32_t(part_->resonator_level() * 512.0f)]);
  82. break;
  83. case UI_MODE_CALIBRATION_1:
  84. leds_.set_gate(!blink);
  85. leds_.set_exciter(blink ? 255 : 0);
  86. leds_.set_resonator(0);
  87. break;
  88. case UI_MODE_CALIBRATION_2:
  89. leds_.set_gate(!blink);
  90. leds_.set_exciter(0);
  91. leds_.set_resonator(blink ? 255 : 0);
  92. break;
  93. case UI_MODE_PANIC:
  94. leds_.set_gate(blink);
  95. leds_.set_exciter(blink ? 255 : 0);
  96. leds_.set_resonator(blink ? 0 : 255);
  97. break;
  98. case UI_MODE_DISPLAY_MODEL:
  99. {
  100. bool blink = (system_clock.milliseconds() & 255) > 128;
  101. uint8_t count = ((system_clock.milliseconds()) >> 8) & 3;
  102. bool pulse = (count <= part_->resonator_model()) && blink;
  103. leds_.set_gate(pulse);
  104. leds_.set_exciter(pulse ? 255 : 0);
  105. leds_.set_resonator(pulse ? 255 : 0);
  106. }
  107. break;
  108. }
  109. if (part_->bypass()) {
  110. leds_.set_gate(true);
  111. leds_.set_exciter(255);
  112. leds_.set_resonator(255);
  113. }
  114. leds_.Write();
  115. }
  116. void Ui::FlushEvents() {
  117. queue_.Flush();
  118. }
  119. void Ui::OnSwitchPressed(const Event& e) {
  120. switch (e.control_id) {
  121. case 0:
  122. if (mode_ == UI_MODE_CALIBRATION_1) {
  123. CalibrateC1();
  124. } else if (mode_ == UI_MODE_CALIBRATION_2) {
  125. CalibrateC3();
  126. } else {
  127. gate_ = true;
  128. }
  129. break;
  130. case 1:
  131. mode_ = UI_MODE_CALIBRATION_1;
  132. break;
  133. case 2:
  134. part_->set_easter_egg(!part_->easter_egg());
  135. cv_scaler_->set_boot_in_easter_egg_mode(part_->easter_egg());
  136. cv_scaler_->SaveCalibration();
  137. gate_ = false;
  138. break;
  139. case 3:
  140. part_->set_resonator_model(
  141. ResonatorModel((part_->resonator_model() + 1) % 3));
  142. cv_scaler_->set_resonator_model(part_->resonator_model());
  143. cv_scaler_->SaveCalibration();
  144. gate_ = false;
  145. mode_ = UI_MODE_DISPLAY_MODEL;
  146. break;
  147. default:
  148. break;
  149. }
  150. }
  151. void Ui::OnSwitchReleased(const Event& e) {
  152. gate_ = false;
  153. }
  154. void Ui::CalibrateC1() {
  155. cv_scaler_->CalibrateC1();
  156. cv_scaler_->CalibrateOffsets();
  157. mode_ = UI_MODE_CALIBRATION_2;
  158. }
  159. void Ui::CalibrateC3() {
  160. bool success = cv_scaler_->CalibrateC3();
  161. if (success) {
  162. cv_scaler_->SaveCalibration();
  163. mode_ = UI_MODE_NORMAL;
  164. } else {
  165. mode_ = UI_MODE_PANIC;
  166. }
  167. }
  168. void Ui::DoEvents() {
  169. while (queue_.available()) {
  170. Event e = queue_.PullEvent();
  171. if (e.control_type == CONTROL_SWITCH) {
  172. if (e.data == 0) {
  173. OnSwitchPressed(e);
  174. } else {
  175. OnSwitchReleased(e);
  176. }
  177. }
  178. }
  179. if (mode_ == UI_MODE_DISPLAY_MODEL) {
  180. if (queue_.idle_time() > 4000) {
  181. mode_ = UI_MODE_NORMAL;
  182. queue_.Touch();
  183. }
  184. } else {
  185. if (queue_.idle_time() > 800 && mode_ == UI_MODE_PANIC) {
  186. mode_ = UI_MODE_NORMAL;
  187. }
  188. if (queue_.idle_time() > 1000) {
  189. queue_.Touch();
  190. }
  191. }
  192. }
  193. uint8_t Ui::HandleFactoryTestingRequest(uint8_t command) {
  194. uint8_t argument = command & 0x1f;
  195. command = command >> 5;
  196. uint8_t reply = 0;
  197. switch (command) {
  198. case FACTORY_TESTING_READ_POT:
  199. reply = cv_scaler_->pot_value(argument);
  200. break;
  201. case FACTORY_TESTING_READ_CV:
  202. reply = cv_scaler_->cv_value(argument);
  203. break;
  204. case FACTORY_TESTING_READ_GATE:
  205. if (argument == 0x00) {
  206. return gate_;
  207. } else {
  208. return cv_scaler_->gate();
  209. }
  210. break;
  211. case FACTORY_TESTING_SET_BYPASS:
  212. part_->set_bypass(argument);
  213. break;
  214. case FACTORY_TESTING_CALIBRATE:
  215. if (argument == 0) {
  216. mode_ = UI_MODE_CALIBRATION_1;
  217. } else if (argument == 1) {
  218. CalibrateC1();
  219. } else {
  220. CalibrateC3();
  221. }
  222. break;
  223. }
  224. return reply;
  225. }
  226. } // namespace elements