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.

420 lines
11KB

  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 "warps/ui.h"
  29. #include <algorithm>
  30. #include "stmlib/system/system_clock.h"
  31. #include "stmlib/dsp/units.h"
  32. #include "warps/cv_scaler.h"
  33. namespace warps {
  34. using namespace std;
  35. using namespace stmlib;
  36. /* static */
  37. const uint8_t Ui::palette_[10][3] = {
  38. { 0, 192, 64 },
  39. { 64, 255, 0 },
  40. { 255, 255, 0 },
  41. { 255, 64, 0 },
  42. { 255, 0, 0 },
  43. { 255, 0, 64 },
  44. { 255, 0, 255 },
  45. { 0, 0, 255 },
  46. { 0, 255, 192 },
  47. { 0, 255, 192 },
  48. };
  49. /* static */
  50. const uint8_t Ui::feature_mode_palette_[10][3] = {
  51. { 255, 64, 0 },
  52. { 0, 192, 64 },
  53. { 255, 0, 64 },
  54. { 0, 255, 192 },
  55. { 64, 255, 0 },
  56. { 0, 0, 255 },
  57. { 255, 255, 0 },
  58. { 255, 0, 255 },
  59. { 0, 255, 192 },
  60. { 255, 0, 0 },
  61. };
  62. /* static */
  63. const uint8_t Ui::freq_shifter_palette_[10][3] = {
  64. { 0, 0, 64 },
  65. { 0, 0, 255 },
  66. { 0, 255, 192 },
  67. { 0, 192, 64 },
  68. { 64, 255, 0 },
  69. { 255, 255, 0 },
  70. { 255, 192, 0 },
  71. { 255, 64, 0 },
  72. { 255, 0, 0 },
  73. { 255, 0, 0 },
  74. };
  75. const float kAlgoChangeThreshold = 0.01f;
  76. void Ui::Init(Settings* settings, CvScaler* cv_scaler, Modulator* modulator) {
  77. leds_.Init();
  78. switches_.Init();
  79. mode_ = UI_MODE_NORMAL;
  80. settings_ = settings;
  81. cv_scaler_ = cv_scaler;
  82. modulator_ = modulator;
  83. modulator_->set_feature_mode(static_cast<FeatureMode>(settings_->state().feature_mode));
  84. feature_mode_ = modulator_->feature_mode();
  85. carrier_shape_ = settings_->state().carrier_shape;
  86. UpdateSettings();
  87. last_algo_pot_ = 0.0f;
  88. feature_mode_changed_ = false;
  89. }
  90. void Ui::UpdateSettings() {
  91. modulator_->set_feature_mode(static_cast<FeatureMode>(feature_mode_));
  92. settings_->mutable_state()->feature_mode = feature_mode_;
  93. modulator_->mutable_parameters()->carrier_shape = carrier_shape_;
  94. settings_->mutable_state()->carrier_shape = carrier_shape_;
  95. }
  96. void Ui::Poll() {
  97. // Called at 1.6kHz instead of 1kHz, so the "milliseconds" clock actually runs
  98. // 1.6x faster. Not a big deal since it is used only for controlling LED
  99. // blinking rate and detecting long button presses.
  100. system_clock.Tick();
  101. switches_.Debounce();
  102. if (switches_.just_pressed(0)) {
  103. queue_.AddEvent(CONTROL_SWITCH, 0, 0);
  104. press_time_ = system_clock.milliseconds();
  105. }
  106. if (switches_.pressed(0) && \
  107. press_time_ &&
  108. (system_clock.milliseconds() - press_time_) >= 7800) {
  109. if (!feature_mode_changed_ && cv_scaler_->ready_for_calibration()) {
  110. queue_.AddEvent(CONTROL_SWITCH, 1, 0);
  111. press_time_ = 0;
  112. }
  113. }
  114. if (switches_.released(0) && press_time_) {
  115. queue_.AddEvent(
  116. CONTROL_SWITCH,
  117. 0,
  118. system_clock.milliseconds() - press_time_ + 1);
  119. }
  120. bool blink = (system_clock.milliseconds() & 127) > 64;
  121. bool slow_blink = (system_clock.milliseconds() & 255) > 128;
  122. switch (mode_) {
  123. case UI_MODE_NORMAL:
  124. {
  125. uint8_t rgb[3];
  126. float zone;
  127. const Parameters& p = modulator_->parameters();
  128. const uint8_t (*palette)[3];
  129. switch (modulator_->feature_mode()) {
  130. case FEATURE_MODE_META:
  131. zone = p.modulation_algorithm;
  132. palette = palette_;
  133. break;
  134. default:
  135. zone = p.raw_algorithm;
  136. palette = freq_shifter_palette_;
  137. break;
  138. }
  139. zone *= 8.0f;
  140. MAKE_INTEGRAL_FRACTIONAL(zone);
  141. int32_t zone_fractional_i = static_cast<int32_t>(
  142. zone_fractional * 256.0f);
  143. for (int32_t i = 0; i < 3; ++i) {
  144. int32_t a = palette[zone_integral][i];
  145. int32_t b = palette[zone_integral + 1][i];
  146. rgb[i] = a + ((b - a) * zone_fractional_i >> 8);
  147. }
  148. leds_.set_main(rgb[0], rgb[1], rgb[2]);
  149. leds_.set_osc(
  150. carrier_shape_ >= 2 ? 255 : 0,
  151. carrier_shape_ > 0 && carrier_shape_ <= 2 ? 255 : 0);
  152. }
  153. break;
  154. case UI_MODE_FEATURE_SWITCH:
  155. {
  156. const Parameters& p = modulator_->parameters();
  157. if (p.raw_algorithm_pot >= last_algo_pot_ + kAlgoChangeThreshold ||
  158. p.raw_algorithm_pot <= last_algo_pot_ - kAlgoChangeThreshold) {
  159. feature_mode_changed_ = true;
  160. }
  161. if (feature_mode_changed_) {
  162. feature_mode_ = static_cast<uint8_t>(p.raw_algorithm_pot * 8.0f + 0.5f);
  163. int8_t ramp = system_clock.milliseconds() & 127;
  164. uint8_t tri = (system_clock.milliseconds() & 255) < 128 ?
  165. 127 + ramp : 255 - ramp;
  166. leds_.set_main((feature_mode_palette_[feature_mode_][0] * tri) >> 8,
  167. (feature_mode_palette_[feature_mode_][1] * tri) >> 8,
  168. (feature_mode_palette_[feature_mode_][2] * tri) >> 8);
  169. }
  170. }
  171. break;
  172. case UI_MODE_CALIBRATION_C1:
  173. leds_.set_main(0, blink ? 255 : 0, blink ? 64 : 0);
  174. leds_.set_osc(blink ? 255 : 0, blink ? 255 : 0);
  175. break;
  176. case UI_MODE_CALIBRATION_C3:
  177. leds_.set_main(blink ? 255 : 0, 0, blink ? 32 : 0);
  178. leds_.set_osc(blink ? 255 : 0, 0);
  179. break;
  180. case UI_MODE_CALIBRATION_LOW:
  181. leds_.set_main(slow_blink ? 255 : 0, 0, 0);
  182. leds_.set_osc(slow_blink ? 255 : 0, 0);
  183. break;
  184. case UI_MODE_CALIBRATION_HIGH:
  185. leds_.set_main(0, slow_blink ? 255 : 0, 0);
  186. leds_.set_osc(0, slow_blink ? 255 : 0);
  187. break;
  188. case UI_MODE_CALIBRATION_ERROR:
  189. case UI_MODE_PANIC:
  190. leds_.set_osc(blink ? 255 : 0, 0);
  191. leds_.set_main(blink ? 255 : 0, 0, 0);
  192. break;
  193. }
  194. if (modulator_->bypass()) {
  195. uint16_t red = system_clock.milliseconds() & 4095;
  196. uint16_t green = (system_clock.milliseconds() + 1333) & 4095;
  197. uint16_t blue = (system_clock.milliseconds() + 2667) & 4095;
  198. green = green < 2048 ? green : 4095 - green;
  199. red = red < 2048 ? red : 4095 - red;
  200. blue = blue < 2048 ? blue : 4095 - blue;
  201. leds_.set_osc(255, 255);
  202. leds_.set_main(red >> 3, green >> 3, blue >> 3);
  203. }
  204. leds_.Write();
  205. }
  206. void Ui::OnSwitchPressed(const Event& e) {
  207. switch (e.control_id) {
  208. case 0:
  209. switch (mode_) {
  210. case UI_MODE_CALIBRATION_C1:
  211. CalibrateC1();
  212. break;
  213. case UI_MODE_CALIBRATION_C3:
  214. CalibrateC3();
  215. break;
  216. case UI_MODE_CALIBRATION_LOW:
  217. CalibrateLow();
  218. break;
  219. case UI_MODE_CALIBRATION_HIGH:
  220. CalibrateHigh();
  221. break;
  222. case UI_MODE_NORMAL:
  223. last_algo_pot_ = modulator_->parameters().raw_algorithm_pot;
  224. mode_ = UI_MODE_FEATURE_SWITCH;
  225. break;
  226. default:
  227. break;
  228. }
  229. break;
  230. case 1:
  231. StartCalibration();
  232. break;
  233. case 2:
  234. StartNormalizationCalibration();
  235. break;
  236. default:
  237. break;
  238. }
  239. }
  240. void Ui::OnSwitchReleased(const Event& e) {
  241. switch (e.control_id) {
  242. case 0:
  243. if (mode_ == UI_MODE_CALIBRATION_C1 ||
  244. mode_ == UI_MODE_CALIBRATION_C3 ||
  245. mode_ == UI_MODE_CALIBRATION_LOW ||
  246. mode_ == UI_MODE_CALIBRATION_HIGH) {
  247. CalibrateC1();
  248. } else if (mode_ == UI_MODE_CALIBRATION_C3) {
  249. CalibrateC3();
  250. } else {
  251. mode_ = UI_MODE_NORMAL;
  252. if (feature_mode_changed_) {
  253. feature_mode_changed_ = false;
  254. }
  255. else {
  256. carrier_shape_ = (carrier_shape_ + 1) & 3;
  257. }
  258. UpdateSettings();
  259. settings_->Save();
  260. }
  261. }
  262. }
  263. void Ui::StartCalibration() {
  264. cv_scaler_->StartCalibration();
  265. mode_ = UI_MODE_CALIBRATION_C1;
  266. }
  267. void Ui::CalibrateC1() {
  268. cv_scaler_->CalibrateC1();
  269. cv_scaler_->CalibrateOffsets();
  270. mode_ = UI_MODE_CALIBRATION_C3;
  271. }
  272. void Ui::CalibrateC3() {
  273. if (cv_scaler_->CalibrateC3()) {
  274. settings_->Save();
  275. mode_ = UI_MODE_NORMAL;
  276. } else {
  277. mode_ = UI_MODE_CALIBRATION_ERROR;
  278. }
  279. }
  280. void Ui::StartNormalizationCalibration() {
  281. cv_scaler_->StartNormalizationCalibration();
  282. mode_ = UI_MODE_CALIBRATION_LOW;
  283. }
  284. void Ui::CalibrateLow() {
  285. cv_scaler_->CalibrateLow();
  286. mode_ = UI_MODE_CALIBRATION_HIGH;
  287. }
  288. void Ui::CalibrateHigh() {
  289. if (cv_scaler_->CalibrateHigh()) {
  290. settings_->Save();
  291. mode_ = UI_MODE_NORMAL;
  292. } else {
  293. mode_ = UI_MODE_CALIBRATION_ERROR;
  294. }
  295. }
  296. void Ui::DoEvents() {
  297. while (queue_.available()) {
  298. Event e = queue_.PullEvent();
  299. if (e.control_type == CONTROL_SWITCH) {
  300. if (e.data == 0) {
  301. OnSwitchPressed(e);
  302. } else {
  303. OnSwitchReleased(e);
  304. }
  305. }
  306. }
  307. if (mode_ == UI_MODE_CALIBRATION_ERROR) {
  308. if (queue_.idle_time() > 6000) {
  309. mode_ = UI_MODE_NORMAL;
  310. }
  311. } else {
  312. if (queue_.idle_time() > 1000) {
  313. queue_.Touch();
  314. }
  315. }
  316. }
  317. uint8_t Ui::HandleFactoryTestingRequest(uint8_t command) {
  318. uint8_t argument = command & 0x1f;
  319. command = command >> 5;
  320. uint8_t reply = 0;
  321. switch (command) {
  322. case FACTORY_TESTING_READ_POT:
  323. case FACTORY_TESTING_READ_CV:
  324. reply = cv_scaler_->adc_value(argument);
  325. break;
  326. case FACTORY_TESTING_READ_NORMALIZATION:
  327. reply = cv_scaler_->normalization(argument);
  328. break;
  329. case FACTORY_TESTING_READ_GATE:
  330. return switches_.pressed(argument);
  331. break;
  332. case FACTORY_TESTING_SET_BYPASS:
  333. modulator_->set_bypass(argument);
  334. break;
  335. case FACTORY_TESTING_CALIBRATE:
  336. {
  337. switch (argument) {
  338. case 0:
  339. StartCalibration();
  340. break;
  341. case 1:
  342. CalibrateC1();
  343. break;
  344. case 2:
  345. CalibrateC3();
  346. break;
  347. case 3:
  348. StartNormalizationCalibration();
  349. break;
  350. case 4:
  351. CalibrateLow();
  352. break;
  353. case 5:
  354. CalibrateHigh();
  355. carrier_shape_ = 0;
  356. UpdateSettings();
  357. break;
  358. }
  359. }
  360. break;
  361. }
  362. return reply;
  363. }
  364. } // namespace warps