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.

496 lines
15KB

  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 "streams/ui.h"
  29. #include <algorithm>
  30. #include "stmlib/system/storage.h"
  31. #include "stmlib/system/system_clock.h"
  32. #include "streams/drivers/adc.h"
  33. #include "streams/processor.h"
  34. namespace streams {
  35. const int32_t kLongPressDuration = 1000;
  36. using namespace std;
  37. using namespace stmlib;
  38. Storage<0x801fc00, 4> ui_settings_storage;
  39. void Ui::Init(Adc* adc, CvScaler* cv_scaler, Processor* processor) {
  40. leds_.Init();
  41. switches_.Init();
  42. adc_ = adc;
  43. cv_scaler_ = cv_scaler;
  44. processor_ = processor;
  45. fill(&pot_value_[0], &pot_value_[kNumPots], 0);
  46. fill(&pot_threshold_[0], &pot_threshold_[kNumPots], 0);
  47. if (!ui_settings_storage.ParsimoniousLoad(&ui_settings_, &version_token_)) {
  48. // Flash is not formatted. Initialize.
  49. for (uint8_t i = 0; i < kNumChannels; ++i) {
  50. ui_settings_.function[i] = PROCESSOR_FUNCTION_ENVELOPE;
  51. ui_settings_.alternate[i] = false;
  52. }
  53. ui_settings_.monitor_mode = MONITOR_MODE_OUTPUT;
  54. ui_settings_.linked = false;
  55. }
  56. // Initialize from settings in flash.
  57. monitor_mode_ = static_cast<MonitorMode>(ui_settings_.monitor_mode);
  58. for (uint8_t i = 0; i < kNumChannels; ++i) {
  59. meter_[i].Init();
  60. processor_[i].set_alternate(ui_settings_.alternate[i]);
  61. processor_[i].set_linked(ui_settings_.linked);
  62. processor_[i].set_function(
  63. static_cast<ProcessorFunction>(ui_settings_.function[i]));
  64. display_mode_[i] = DISPLAY_MODE_MONITOR;
  65. }
  66. secret_handshake_counter_ = 0;
  67. factory_testing_ = switches_.pressed_immediate(SWITCH_MONITOR);
  68. }
  69. void Ui::SaveState() {
  70. ui_settings_.monitor_mode = monitor_mode_;
  71. ui_settings_.linked = processor_[0].linked();
  72. ui_settings_.function[0] = processor_[0].function();
  73. ui_settings_.function[1] = processor_[1].function();
  74. ui_settings_.alternate[0] = processor_[0].alternate();
  75. ui_settings_.alternate[1] = processor_[1].alternate();
  76. ui_settings_storage.ParsimoniousSave(ui_settings_, &version_token_);
  77. }
  78. void Ui::PaintAdaptive(uint8_t channel, int32_t sample, int32_t gain) {
  79. meter_[channel].Process(sample);
  80. if (meter_[channel].cv()) {
  81. sample = sample * lut_2164_gain[-gain >> 9] >> 15;
  82. leds_.PaintCv(channel, sample * 5 >> 2);
  83. } else {
  84. leds_.PaintPositiveBar(channel, wav_db[meter_[channel].peak() >> 7] + gain);
  85. }
  86. }
  87. void Ui::PaintMonitor(uint8_t channel) {
  88. switch (monitor_mode_) {
  89. case MONITOR_MODE_EXCITE_IN:
  90. PaintAdaptive(channel, cv_scaler_->excite_sample(channel), 0);
  91. break;
  92. case MONITOR_MODE_AUDIO_IN:
  93. PaintAdaptive(channel, cv_scaler_->audio_sample(channel), 0);
  94. break;
  95. case MONITOR_MODE_VCA_CV:
  96. leds_.PaintPositiveBar(channel, 32768 + cv_scaler_->gain_sample(channel));
  97. break;
  98. case MONITOR_MODE_OUTPUT:
  99. if (processor_[channel].function() == PROCESSOR_FUNCTION_COMPRESSOR) {
  100. leds_.PaintNegativeBar(channel, processor_[channel].gain_reduction());
  101. } else {
  102. PaintAdaptive(
  103. channel,
  104. cv_scaler_->audio_sample(channel),
  105. cv_scaler_->gain_sample(channel));
  106. }
  107. break;
  108. default:
  109. break;
  110. }
  111. }
  112. void Ui::PaintTestStatus() {
  113. int32_t value = 0;
  114. value += pot_value_[0] - 32768;
  115. value += pot_value_[1] - 32768;
  116. value += pot_value_[2] - 32768;
  117. value += pot_value_[3] - 32768;
  118. value -= cv_scaler_->excite_sample(0) > 0 ? 0 : cv_scaler_->excite_sample(0);
  119. value -= cv_scaler_->excite_sample(1) > 0 ? 0 : cv_scaler_->excite_sample(1);
  120. value -= cv_scaler_->gain_sample(0);
  121. value -= cv_scaler_->gain_sample(1);
  122. value -= cv_scaler_->audio_sample(0) - 12000;
  123. value -= cv_scaler_->audio_sample(1) - 12000;
  124. if (switches_.pressed(0)) value = -32767;
  125. if (switches_.pressed(1)) value = 32767;
  126. CONSTRAIN(value, -32767, 32767);
  127. if (value < 12288 && value > -12288) value = 0;
  128. uint8_t r = value >= 0 ? 0 : ((-1 - value) >> 7);
  129. uint8_t g = value > 0 ? (value >> 7) : 0;
  130. for (uint8_t i = 0; i < 8; ++i) {
  131. leds_.set(i, r, g);
  132. }
  133. }
  134. void Ui::PaintLeds() {
  135. leds_.Clear();
  136. if (calibrating_) {
  137. for (uint8_t i = 0; i < kNumChannels; ++i) {
  138. uint8_t red, green;
  139. if (show_offset_level_ & (1 << i)) {
  140. int32_t gain_sample = cv_scaler_->raw_gain_sample(i);
  141. bool nulled = gain_sample > 59000;
  142. green = nulled ? 255 : 0;
  143. red = nulled ? 0 : 255;
  144. } else {
  145. red = 0;
  146. green = 255;
  147. }
  148. uint8_t pattern = i == 0 ? 255 : 9;
  149. for (uint8_t j = 0; j < 4; ++j) {
  150. bool on = (pattern & (1 << j)) != 0;
  151. leds_.set(i * 4 + j, on ? red : 0, on ? green : 0);
  152. }
  153. }
  154. return;
  155. }
  156. if (factory_testing_) {
  157. PaintTestStatus();
  158. return;
  159. }
  160. for (uint8_t i = 0; i < kNumChannels; ++i) {
  161. uint8_t bank = i * 4;
  162. switch (display_mode_[i]) {
  163. case DISPLAY_MODE_FUNCTION:
  164. {
  165. bool alternate = processor_[i].alternate();
  166. uint8_t intensity = 255;
  167. if (processor_[i].linked()) {
  168. uint8_t phase = system_clock.milliseconds() >> 1;
  169. phase += i * 128;
  170. phase = phase < 128 ? phase : (255 - phase);
  171. intensity = (phase * 224 >> 7) + 32;
  172. intensity = intensity * intensity >> 8;
  173. }
  174. uint8_t function = processor_[i].function();
  175. if (function == PROCESSOR_FUNCTION_FILTER_CONTROLLER) {
  176. for (uint8_t j = 0; j < 4; ++j) {
  177. leds_.set(bank + j,
  178. alternate ? intensity : 0,
  179. alternate ? 0 : intensity);
  180. }
  181. } else if (function < PROCESSOR_FUNCTION_LORENZ_GENERATOR) {
  182. leds_.set(
  183. bank + function,
  184. alternate ? intensity : 0,
  185. alternate ? 0 : intensity);
  186. } else {
  187. uint8_t index = (processor_[i].last_gain() >> 4) * 5 >> 4;
  188. if (index > 3) index = 3;
  189. int16_t color = processor_[i].last_frequency();
  190. color = color - 128;
  191. color *= 2;
  192. if (color < 0) {
  193. if (color < -127) color = -127;
  194. leds_.set(bank + index, 255 + (color * 2), 255);
  195. } else {
  196. if (color > 127) color = 127;
  197. leds_.set(bank + index, 255, 255 - (color * 2));
  198. }
  199. }
  200. }
  201. break;
  202. case DISPLAY_MODE_MONITOR_FUNCTION:
  203. {
  204. uint8_t position = static_cast<uint8_t>(monitor_mode_);
  205. leds_.set(position * 2, 255, 0);
  206. leds_.set(position * 2 + 1, 255, 0);
  207. }
  208. break;
  209. case DISPLAY_MODE_MONITOR:
  210. PaintMonitor(i);
  211. break;
  212. }
  213. }
  214. }
  215. void Ui::Poll() {
  216. // SysTick is at 4kHz to get a fast bargraph refresh.
  217. ++divider_;
  218. if ((divider_ & 3) == 0) {
  219. system_clock.Tick();
  220. switches_.Debounce();
  221. for (uint8_t i = 0; i < kNumSwitches; ++i) {
  222. if (switches_.just_pressed(i)) {
  223. queue_.AddEvent(CONTROL_SWITCH, i, 0);
  224. press_time_[i] = system_clock.milliseconds();
  225. }
  226. if (switches_.pressed(i) && press_time_[i] != 0) {
  227. int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
  228. if (pressed_time > kLongPressDuration) {
  229. queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
  230. press_time_[i] = 0;
  231. }
  232. }
  233. if (switches_.released(i) && press_time_[i] != 0) {
  234. queue_.AddEvent(
  235. CONTROL_SWITCH,
  236. i,
  237. system_clock.milliseconds() - press_time_[i] + 1);
  238. press_time_[i] = 0;
  239. }
  240. }
  241. adc_->ScanPots();
  242. for (uint8_t i = 0; i < kNumPots; ++i) {
  243. int32_t value = adc_->pot(i);
  244. int32_t current_value = pot_value_[i];
  245. if (value >= current_value + pot_threshold_[i] ||
  246. value <= current_value - pot_threshold_[i] ||
  247. !pot_threshold_[i]) {
  248. Event e;
  249. e.control_id = i;
  250. e.data = value;
  251. queue_.AddEvent(CONTROL_POT, i, e.data);
  252. pot_value_[i] = value;
  253. pot_threshold_[i] = 256;
  254. }
  255. }
  256. }
  257. PaintLeds();
  258. leds_.Write();
  259. }
  260. void Ui::FlushEvents() {
  261. queue_.Flush();
  262. }
  263. void Ui::Link(uint8_t index) {
  264. if (processor_[0].linked()) {
  265. for (uint8_t i = 0; i < kNumChannels; ++i) {
  266. if (i != index) {
  267. display_mode_[i] = display_mode_[index];
  268. processor_[i].set_function(processor_[index].function());
  269. processor_[i].set_alternate(processor_[index].alternate());
  270. }
  271. }
  272. }
  273. }
  274. void Ui::OnPotMoved(const Event& e) {
  275. if (calibrating_) {
  276. if ((e.control_id & 1) == 0) {
  277. int32_t min = kDefaultOffset >> 1;
  278. int32_t max = 3 * min + 256;
  279. int32_t value = min + ((max - min) * e.data >> 16);
  280. cv_scaler_->set_dac_offset(e.control_id >> 1, value);
  281. show_offset_level_ |= (1 << (e.control_id >> 1));
  282. }
  283. } else {
  284. processor_[0].set_global(e.control_id, e.data);
  285. processor_[1].set_global(e.control_id, e.data);
  286. processor_[e.control_id >> 1].set_parameter(e.control_id & 1, e.data);
  287. }
  288. }
  289. void Ui::OnSwitchPressed(const Event& e) {
  290. if (factory_testing_) {
  291. if (e.control_id == SWITCH_MONITOR) {
  292. ++secret_handshake_counter_;
  293. if (secret_handshake_counter_ == 4) {
  294. factory_testing_ = false;
  295. }
  296. }
  297. return;
  298. }
  299. if (calibrating_) {
  300. cv_scaler_->SaveCalibrationData();
  301. calibrating_ = false;
  302. show_offset_level_ = 0;
  303. return;
  304. }
  305. // Double press!
  306. if ((e.control_id == SWITCH_MODE_1 && press_time_[SWITCH_MODE_2]) ||
  307. (e.control_id == SWITCH_MODE_2 && press_time_[SWITCH_MODE_1])) {
  308. press_time_[SWITCH_MODE_1] = press_time_[SWITCH_MODE_2] = 0;
  309. bool linked = !processor_[0].linked();
  310. for (uint8_t i = 0; i < kNumChannels; ++i) {
  311. display_mode_[i] = DISPLAY_MODE_FUNCTION;
  312. processor_[i].set_linked(linked);
  313. }
  314. Link(1 - e.control_id);
  315. SaveState();
  316. return;
  317. }
  318. switch (e.control_id) {
  319. case SWITCH_MONITOR:
  320. {
  321. if (display_mode_[0] == DISPLAY_MODE_MONITOR &&
  322. display_mode_[1] == DISPLAY_MODE_MONITOR) {
  323. display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR_FUNCTION;
  324. } else if (display_mode_[0] == DISPLAY_MODE_MONITOR_FUNCTION &&
  325. display_mode_[1] == DISPLAY_MODE_MONITOR_FUNCTION) {
  326. monitor_mode_ = static_cast<MonitorMode>(monitor_mode_ + 1);
  327. if (monitor_mode_ == MONITOR_MODE_LAST) {
  328. monitor_mode_ = static_cast<MonitorMode>(0);
  329. }
  330. SaveState();
  331. } else {
  332. display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR;
  333. }
  334. }
  335. break;
  336. default:
  337. break;
  338. }
  339. }
  340. void Ui::OnSwitchReleased(const Event& e) {
  341. if (factory_testing_) {
  342. return;
  343. }
  344. // Detect secret handshake for easter egg...
  345. uint8_t secret_handshake_code = e.control_id;
  346. secret_handshake_code |= e.data >= kLongPressDuration ? 2 : 0;
  347. if ((secret_handshake_counter_ & 3) == secret_handshake_code) {
  348. ++secret_handshake_counter_;
  349. if (secret_handshake_counter_ == 16) {
  350. for (uint8_t i = 0; i < kNumChannels; ++i) {
  351. processor_[i].set_alternate(false);
  352. processor_[i].set_function(PROCESSOR_FUNCTION_LORENZ_GENERATOR);
  353. }
  354. SaveState();
  355. secret_handshake_counter_ = 0;
  356. return;
  357. }
  358. } else {
  359. secret_handshake_counter_ = 0;
  360. }
  361. if (e.data >= kLongPressDuration) {
  362. // Handle long presses.
  363. switch (e.control_id) {
  364. case SWITCH_MONITOR:
  365. calibrating_ = cv_scaler_->can_calibrate();
  366. if (calibrating_) {
  367. cv_scaler_->CaptureAdcOffsets();
  368. show_offset_level_ = 0;
  369. }
  370. break;
  371. case SWITCH_MODE_1:
  372. case SWITCH_MODE_2:
  373. {
  374. processor_[e.control_id].set_alternate(
  375. !processor_[e.control_id].alternate());
  376. if (processor_[e.control_id].function() >
  377. PROCESSOR_FUNCTION_COMPRESSOR) {
  378. processor_[e.control_id].set_function(PROCESSOR_FUNCTION_ENVELOPE);
  379. }
  380. display_mode_[e.control_id] = DISPLAY_MODE_FUNCTION;
  381. int32_t other = 1 - e.control_id;
  382. if (display_mode_[other] == DISPLAY_MODE_MONITOR_FUNCTION) {
  383. display_mode_[other] = DISPLAY_MODE_MONITOR;
  384. }
  385. Link(e.control_id);
  386. SaveState();
  387. }
  388. break;
  389. }
  390. } else {
  391. switch (e.control_id) {
  392. case SWITCH_MODE_1:
  393. case SWITCH_MODE_2:
  394. {
  395. if (display_mode_[e.control_id] == DISPLAY_MODE_FUNCTION) {
  396. ProcessorFunction index = processor_[e.control_id].function();
  397. index = static_cast<ProcessorFunction>(index + 1);
  398. ProcessorFunction limit = processor_[e.control_id].alternate()
  399. ? PROCESSOR_FUNCTION_FILTER_CONTROLLER
  400. : PROCESSOR_FUNCTION_COMPRESSOR;
  401. if (index > limit) {
  402. index = static_cast<ProcessorFunction>(0);
  403. }
  404. processor_[e.control_id].set_function(index);
  405. SaveState();
  406. } else {
  407. display_mode_[e.control_id] = DISPLAY_MODE_FUNCTION;
  408. int32_t other = 1 - e.control_id;
  409. if (display_mode_[other] == DISPLAY_MODE_MONITOR_FUNCTION) {
  410. display_mode_[other] = DISPLAY_MODE_MONITOR;
  411. }
  412. }
  413. Link(e.control_id);
  414. }
  415. break;
  416. default:
  417. break;
  418. }
  419. }
  420. }
  421. void Ui::DoEvents() {
  422. bool refresh = false;
  423. while (queue_.available()) {
  424. Event e = queue_.PullEvent();
  425. if (e.control_type == CONTROL_SWITCH) {
  426. if (e.data == 0) {
  427. OnSwitchPressed(e);
  428. } else {
  429. OnSwitchReleased(e);
  430. }
  431. } else if (e.control_type == CONTROL_POT) {
  432. OnPotMoved(e);
  433. }
  434. refresh = true;
  435. }
  436. if (queue_.idle_time() > 1000) {
  437. queue_.Touch();
  438. if (display_mode_[0] == DISPLAY_MODE_MONITOR_FUNCTION &&
  439. display_mode_[1] == DISPLAY_MODE_MONITOR_FUNCTION) {
  440. display_mode_[0] = display_mode_[1] = DISPLAY_MODE_MONITOR;
  441. }
  442. refresh = true;
  443. }
  444. // Recompute processor parameters if necessary.
  445. if (refresh) {
  446. for (uint8_t i = 0; i < kNumChannels; ++i) {
  447. processor_[i].Configure();
  448. }
  449. }
  450. }
  451. } // namespace streams