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.

306 lines
7.9KB

  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. #include "tides/ui.h"
  29. #include "stmlib/system/storage.h"
  30. #include "stmlib/system/system_clock.h"
  31. #include "tides/cv_scaler.h"
  32. #include "tides/generator.h"
  33. namespace tides {
  34. const int32_t kLongPressDuration = 1000;
  35. using namespace stmlib;
  36. Storage<0x801fc00, 4> mode_storage;
  37. void Ui::Init(Generator* generator, CvScaler* cv_scaler) {
  38. factory_testing_switch_.Init();
  39. leds_.Init();
  40. switches_.Init();
  41. mode_ = factory_testing_switch_.Read()
  42. ? UI_MODE_NORMAL
  43. : UI_MODE_FACTORY_TESTING;
  44. generator_ = generator;
  45. cv_scaler_ = cv_scaler;
  46. if (!mode_storage.ParsimoniousLoad(&settings_, &version_token_)) {
  47. mode_counter_ = 1;
  48. range_counter_ = 2;
  49. generator->set_sync(false);
  50. } else {
  51. mode_counter_ = settings_.mode;
  52. range_counter_ = 2 - settings_.range;
  53. generator->set_sync(settings_.sync);
  54. }
  55. UpdateMode();
  56. UpdateRange();
  57. leds_.set_value(32768, 32768);
  58. }
  59. void Ui::SaveState() {
  60. settings_.mode = generator_->mode();
  61. settings_.range = generator_->range();
  62. settings_.sync = generator_->sync();
  63. mode_storage.ParsimoniousSave(settings_, &version_token_);
  64. }
  65. const uint16_t thresholds[ADC_CHANNEL_LAST][2] = {
  66. { 0, 64000 },
  67. { 16384, 49152 },
  68. { 16384, 49152 },
  69. { 4096, 61440 },
  70. { 4096, 61440 },
  71. { 4096, 61440 },
  72. { 4096, 61440 },
  73. };
  74. void Ui::UpdateFactoryTestingFlags(
  75. uint8_t gate_input_flags,
  76. const uint16_t* adc_values) {
  77. red_ = switches_.pressed(1);
  78. green_ = switches_.pressed(0);
  79. orange_ = gate_input_flags & CONTROL_GATE;
  80. orange_ |= gate_input_flags & CONTROL_FREEZE;
  81. orange_ |= gate_input_flags & CONTROL_CLOCK;
  82. for (uint16_t i = 0; i < ADC_CHANNEL_LAST; ++i) {
  83. uint16_t value = adc_values[i];
  84. if (i == ADC_CHANNEL_FM_ATTENUVERTER) {
  85. value = ~value;
  86. }
  87. green_ |= value < thresholds[i][0];
  88. if (i == 0) {
  89. orange_ |= value > thresholds[i][1];
  90. } else {
  91. red_ |= value > thresholds[i][1];
  92. }
  93. }
  94. }
  95. void Ui::Poll() {
  96. system_clock.Tick();
  97. switches_.Debounce();
  98. for (uint8_t i = 0; i < kNumSwitches; ++i) {
  99. if (switches_.just_pressed(i)) {
  100. queue_.AddEvent(CONTROL_SWITCH, i, 0);
  101. press_time_[i] = system_clock.milliseconds();
  102. }
  103. if (switches_.pressed(i) && press_time_[i] != 0) {
  104. int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
  105. if (pressed_time > kLongPressDuration) {
  106. queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
  107. press_time_[i] = 0;
  108. }
  109. }
  110. if (switches_.released(i) && press_time_[i] != 0) {
  111. queue_.AddEvent(
  112. CONTROL_SWITCH,
  113. i,
  114. system_clock.milliseconds() - press_time_[i] + 1);
  115. press_time_[i] = 0;
  116. }
  117. }
  118. switch (mode_) {
  119. case UI_MODE_NORMAL:
  120. {
  121. GeneratorMode mode = generator_->mode();
  122. leds_.set_mode(mode == GENERATOR_MODE_AR, mode == GENERATOR_MODE_AD);
  123. GeneratorRange range = generator_->range();
  124. switch (range) {
  125. case GENERATOR_RANGE_LOW:
  126. leds_.set_rate(0, 65535);
  127. break;
  128. case GENERATOR_RANGE_MEDIUM:
  129. if (generator_->sync()) {
  130. leds_.set_rate(8192, 16384);
  131. } else {
  132. leds_.set_rate(0);
  133. }
  134. break;
  135. case GENERATOR_RANGE_HIGH:
  136. leds_.set_rate(65535, 0);
  137. break;
  138. }
  139. bool blink_rate_led = generator_->sync() && \
  140. system_clock.milliseconds() & 128;
  141. if (blink_rate_led) {
  142. leds_.set_rate(0);
  143. }
  144. }
  145. break;
  146. case UI_MODE_CALIBRATION_C2:
  147. leds_.set_mode(true);
  148. leds_.set_rate(65535);
  149. leds_.set_value(65535);
  150. break;
  151. case UI_MODE_CALIBRATION_C4:
  152. leds_.set_mode(false, true);
  153. leds_.set_rate(0, 65535);
  154. leds_.set_value(0, 65535);
  155. break;
  156. case UI_MODE_PAQUES:
  157. leds_.set_mode(true, false);
  158. leds_.set_rate(65535, 0);
  159. leds_.set_value(65535, 0);
  160. break;
  161. case UI_MODE_FACTORY_TESTING:
  162. if (orange_) {
  163. leds_.set_mode(true, true);
  164. leds_.set_rate(65535, 65535);
  165. leds_.set_value(65535, 65535);
  166. } else if (red_) {
  167. leds_.set_mode(true, 0);
  168. leds_.set_rate(65535, 0);
  169. leds_.set_value(65535, 0);
  170. } else if (green_) {
  171. leds_.set_mode(false, true);
  172. leds_.set_rate(0, 65535);
  173. leds_.set_value(0, 65535);
  174. } else {
  175. leds_.set_mode(false, false);
  176. leds_.set_rate(0, 0);
  177. leds_.set_value(0, 0);
  178. }
  179. break;
  180. }
  181. leds_.Write();
  182. }
  183. inline void Ui::UpdateMode() {
  184. uint8_t i = mode_counter_ & 3;
  185. if (i == 3) {
  186. i = 1;
  187. }
  188. generator_->set_mode(static_cast<GeneratorMode>(i));
  189. SaveState();
  190. }
  191. inline void Ui::UpdateRange() {
  192. uint8_t i = range_counter_ & 3;
  193. if (i == 3) {
  194. i = 1;
  195. }
  196. generator_->set_range(static_cast<GeneratorRange>(2 - i));
  197. SaveState();
  198. }
  199. void Ui::FlushEvents() {
  200. queue_.Flush();
  201. }
  202. void Ui::OnSwitchPressed(const Event& e) {
  203. switch (e.control_id) {
  204. case 0:
  205. break;
  206. case 1:
  207. break;
  208. }
  209. }
  210. void Ui::OnSwitchReleased(const Event& e) {
  211. if (mode_ == UI_MODE_FACTORY_TESTING) {
  212. return;
  213. } else if (mode_ == UI_MODE_PAQUES) {
  214. mode_ = UI_MODE_NORMAL;
  215. } else if (mode_ == UI_MODE_CALIBRATION_C2) {
  216. if (e.data > kLongPressDuration) {
  217. ++long_press_counter_;
  218. }
  219. if (e.control_id == 0) {
  220. cv_scaler_->CaptureCalibrationValues();
  221. mode_ = UI_MODE_CALIBRATION_C4;
  222. } else {
  223. mode_ = UI_MODE_NORMAL;
  224. }
  225. } else if (mode_ == UI_MODE_CALIBRATION_C4) {
  226. mode_ = UI_MODE_NORMAL;
  227. if (e.control_id == 0) {
  228. cv_scaler_->Calibrate();
  229. } else if (e.control_id == 1 && long_press_counter_ == 1 &&
  230. e.data > kLongPressDuration) {
  231. mode_ = UI_MODE_PAQUES;
  232. }
  233. } else {
  234. long_press_counter_ = 0;
  235. switch (e.control_id) {
  236. case 0:
  237. if (e.data > kLongPressDuration &&
  238. cv_scaler_->can_enter_calibration()) {
  239. mode_ = UI_MODE_CALIBRATION_C2;
  240. } else {
  241. ++mode_counter_;
  242. UpdateMode();
  243. }
  244. break;
  245. case 1:
  246. if (e.data > kLongPressDuration) {
  247. generator_->set_sync(!generator_->sync());
  248. SaveState();
  249. } else {
  250. ++range_counter_;
  251. UpdateRange();
  252. }
  253. break;
  254. }
  255. }
  256. }
  257. void Ui::DoEvents() {
  258. while (queue_.available()) {
  259. Event e = queue_.PullEvent();
  260. if (e.control_type == CONTROL_SWITCH) {
  261. if (e.data == 0) {
  262. OnSwitchPressed(e);
  263. } else {
  264. OnSwitchReleased(e);
  265. }
  266. }
  267. }
  268. if (queue_.idle_time() > 1000) {
  269. queue_.Touch();
  270. }
  271. }
  272. } // namespace tides