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.

441 lines
13KB

  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 "peaks/ui.h"
  29. #include "stmlib/system/storage.h"
  30. #include <algorithm>
  31. #include "peaks/calibration_data.h"
  32. namespace peaks {
  33. using namespace std;
  34. using namespace stmlib;
  35. const uint16_t kAdcThresholdUnlocked = 1 << (16 - 10); // 10 bits
  36. const uint16_t kAdcThresholdLocked = 1 << (16 - 8); // 8 bits
  37. const int32_t kLongPressDuration = 600;
  38. /* static */
  39. const ProcessorFunction Ui::function_table_[FUNCTION_LAST][2] = {
  40. { PROCESSOR_FUNCTION_ENVELOPE, PROCESSOR_FUNCTION_ENVELOPE },
  41. { PROCESSOR_FUNCTION_LFO, PROCESSOR_FUNCTION_LFO },
  42. { PROCESSOR_FUNCTION_TAP_LFO, PROCESSOR_FUNCTION_TAP_LFO },
  43. { PROCESSOR_FUNCTION_BASS_DRUM, PROCESSOR_FUNCTION_SNARE_DRUM },
  44. { PROCESSOR_FUNCTION_MINI_SEQUENCER, PROCESSOR_FUNCTION_MINI_SEQUENCER },
  45. { PROCESSOR_FUNCTION_PULSE_SHAPER, PROCESSOR_FUNCTION_PULSE_SHAPER },
  46. { PROCESSOR_FUNCTION_PULSE_RANDOMIZER, PROCESSOR_FUNCTION_PULSE_RANDOMIZER },
  47. { PROCESSOR_FUNCTION_FM_DRUM, PROCESSOR_FUNCTION_FM_DRUM },
  48. };
  49. Storage<0x8020000, 16> storage;
  50. void Ui::Init(CalibrationData* calibration_data) {
  51. calibration_data_ = calibration_data;
  52. leds_.Init();
  53. switches_.Init();
  54. adc_.Init();
  55. system_clock.Tick();
  56. fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0);
  57. fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0);
  58. fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0);
  59. fill(&snapped_[0], &snapped_[kNumAdcChannels], false);
  60. panel_gate_state_ = 0;
  61. calibrating_ = switches_.pressed_immediate(1);
  62. if (!storage.ParsimoniousLoad(&settings_, &version_token_)) {
  63. edit_mode_ = EDIT_MODE_TWIN;
  64. function_[0] = FUNCTION_ENVELOPE;
  65. function_[1] = FUNCTION_ENVELOPE;
  66. settings_.snap_mode = false;
  67. } else {
  68. edit_mode_ = static_cast<EditMode>(settings_.edit_mode);
  69. function_[0] = static_cast<Function>(settings_.function[0]);
  70. function_[1] = static_cast<Function>(settings_.function[1]);
  71. copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]);
  72. if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) {
  73. LockPots();
  74. for (uint8_t i = 0; i < 4; ++i) {
  75. processors[0].set_parameter(
  76. i,
  77. static_cast<uint16_t>(pot_value_[i]) << 8);
  78. processors[1].set_parameter(
  79. i,
  80. static_cast<uint16_t>(pot_value_[i + 4]) << 8);
  81. }
  82. }
  83. }
  84. if (switches_.pressed_immediate(SWITCH_TWIN_MODE)) {
  85. settings_.snap_mode = !settings_.snap_mode;
  86. SaveState();
  87. }
  88. ChangeControlMode();
  89. SetFunction(0, function_[0]);
  90. SetFunction(1, function_[1]);
  91. double_press_counter_ = 0;
  92. }
  93. void Ui::LockPots() {
  94. fill(
  95. &adc_threshold_[0],
  96. &adc_threshold_[kNumAdcChannels],
  97. kAdcThresholdLocked);
  98. fill(&snapped_[0], &snapped_[kNumAdcChannels], false);
  99. }
  100. void Ui::SaveState() {
  101. settings_.edit_mode = edit_mode_;
  102. settings_.function[0] = function_[0];
  103. settings_.function[1] = function_[1];
  104. copy(&pot_value_[0], &pot_value_[8], &settings_.pot_value[0]);
  105. storage.ParsimoniousSave(settings_, &version_token_);
  106. }
  107. inline void Ui::RefreshLeds() {
  108. if (calibrating_) {
  109. leds_.set_pattern(0xf);
  110. leds_.set_twin_mode(true);
  111. leds_.set_levels(0, 0);
  112. return;
  113. }
  114. uint8_t flash = (system_clock.milliseconds() >> 7) & 7;
  115. switch (edit_mode_) {
  116. case EDIT_MODE_FIRST:
  117. leds_.set_twin_mode(flash == 1);
  118. break;
  119. case EDIT_MODE_SECOND:
  120. leds_.set_twin_mode(flash == 1 || flash == 3);
  121. break;
  122. default:
  123. leds_.set_twin_mode(edit_mode_ & 1);
  124. break;
  125. }
  126. if ((system_clock.milliseconds() & 256) &&
  127. function() >= FUNCTION_FIRST_ALTERNATE_FUNCTION) {
  128. leds_.set_function(4);
  129. } else {
  130. leds_.set_function(function() & 3);
  131. }
  132. uint8_t b[2];
  133. for (uint8_t i = 0; i < 2; ++i) {
  134. switch (function_[i]) {
  135. case FUNCTION_DRUM_GENERATOR:
  136. case FUNCTION_FM_DRUM_GENERATOR:
  137. b[i] = abs(brightness_[i]) >> 8;
  138. b[i] = b[i] > 255 ? 255 : b[i];
  139. break;
  140. case FUNCTION_LFO:
  141. case FUNCTION_TAP_LFO:
  142. case FUNCTION_MINI_SEQUENCER:
  143. {
  144. int32_t brightness = int32_t(brightness_[i]) * 409 >> 8;
  145. brightness += 32768;
  146. brightness >>= 8;
  147. CONSTRAIN(brightness, 0, 255);
  148. b[i] = brightness;
  149. }
  150. break;
  151. default:
  152. b[i] = brightness_[i] >> 7;
  153. break;
  154. }
  155. }
  156. if (processors[0].function() == PROCESSOR_FUNCTION_NUMBER_STATION) {
  157. leds_.set_pattern(
  158. processors[0].number_station().digit() ^ \
  159. processors[1].number_station().digit());
  160. b[0] = processors[0].number_station().gate() ? 255 : 0;
  161. b[1] = processors[1].number_station().gate() ? 255 : 0;
  162. }
  163. leds_.set_levels(b[0], b[1]);
  164. }
  165. void Ui::PollPots() {
  166. for (uint8_t i = 0; i < kNumAdcChannels; ++i) {
  167. adc_lp_[i] = (int32_t(adc_.value(i)) + adc_lp_[i] * 7) >> 3;
  168. int32_t value = adc_lp_[i];
  169. int32_t current_value = adc_value_[i];
  170. if (value >= current_value + adc_threshold_[i] ||
  171. value <= current_value - adc_threshold_[i] ||
  172. !adc_threshold_[i]) {
  173. Event e;
  174. e.control_id = i;
  175. e.data = value;
  176. OnPotChanged(e);
  177. adc_value_[i] = value;
  178. adc_threshold_[i] = kAdcThresholdUnlocked;
  179. }
  180. }
  181. }
  182. void Ui::Poll() {
  183. system_clock.Tick();
  184. switches_.Debounce();
  185. for (uint8_t i = 0; i < kNumSwitches; ++i) {
  186. if (switches_.just_pressed(i)) {
  187. queue_.AddEvent(CONTROL_SWITCH, i, 0);
  188. press_time_[i] = system_clock.milliseconds();
  189. }
  190. if (switches_.pressed(i) && press_time_[i] != 0 && i < SWITCH_GATE_TRIG_1) {
  191. int32_t pressed_time = system_clock.milliseconds() - press_time_[i];
  192. if (pressed_time > kLongPressDuration) {
  193. if (switches_.pressed(1 - i)) {
  194. ++double_press_counter_;
  195. press_time_[0] = press_time_[1] = 0;
  196. if (double_press_counter_ == 3) {
  197. double_press_counter_ = 0;
  198. processors[0].set_function(PROCESSOR_FUNCTION_NUMBER_STATION);
  199. processors[1].set_function(PROCESSOR_FUNCTION_NUMBER_STATION);
  200. }
  201. } else {
  202. queue_.AddEvent(CONTROL_SWITCH, i, pressed_time);
  203. press_time_[i] = 0; // Inhibit next release event
  204. }
  205. }
  206. }
  207. if (switches_.released(i) && press_time_[i] != 0) {
  208. queue_.AddEvent(
  209. CONTROL_SWITCH,
  210. i,
  211. system_clock.milliseconds() - press_time_[i] + 1);
  212. }
  213. }
  214. RefreshLeds();
  215. leds_.Write();
  216. }
  217. void Ui::FlushEvents() {
  218. queue_.Flush();
  219. }
  220. void Ui::OnSwitchPressed(const Event& e) {
  221. switch (e.control_id) {
  222. case SWITCH_TWIN_MODE:
  223. break;
  224. case SWITCH_FUNCTION:
  225. break;
  226. case SWITCH_GATE_TRIG_1:
  227. panel_gate_control_[0] = true;
  228. break;
  229. case SWITCH_GATE_TRIG_2:
  230. panel_gate_control_[1] = true;
  231. break;
  232. }
  233. }
  234. void Ui::ChangeControlMode() {
  235. uint16_t parameters[4];
  236. for (int i = 0; i < 4; ++i) {
  237. parameters[i] = adc_value_[i];
  238. }
  239. if (edit_mode_ == EDIT_MODE_SPLIT) {
  240. processors[0].CopyParameters(&parameters[0], 2);
  241. processors[1].CopyParameters(&parameters[2], 2);
  242. processors[0].set_control_mode(CONTROL_MODE_HALF);
  243. processors[1].set_control_mode(CONTROL_MODE_HALF);
  244. } else if (edit_mode_ == EDIT_MODE_TWIN) {
  245. processors[0].CopyParameters(&parameters[0], 4);
  246. processors[1].CopyParameters(&parameters[0], 4);
  247. processors[0].set_control_mode(CONTROL_MODE_FULL);
  248. processors[1].set_control_mode(CONTROL_MODE_FULL);
  249. } else {
  250. processors[0].set_control_mode(CONTROL_MODE_FULL);
  251. processors[1].set_control_mode(CONTROL_MODE_FULL);
  252. }
  253. }
  254. void Ui::SetFunction(uint8_t index, Function f) {
  255. if (edit_mode_ == EDIT_MODE_SPLIT || edit_mode_ == EDIT_MODE_TWIN) {
  256. function_[0] = function_[1] = f;
  257. processors[0].set_function(function_table_[f][0]);
  258. processors[1].set_function(function_table_[f][1]);
  259. } else {
  260. function_[index] = f;
  261. processors[index].set_function(function_table_[f][index]);
  262. }
  263. }
  264. void Ui::OnSwitchReleased(const Event& e) {
  265. if (calibrating_) {
  266. if (e.control_id == SWITCH_TWIN_MODE) {
  267. // Save calibration.
  268. calibration_data_->Save();
  269. // Reset all settings to defaults.
  270. edit_mode_ = EDIT_MODE_TWIN;
  271. function_[0] = FUNCTION_ENVELOPE;
  272. function_[1] = FUNCTION_ENVELOPE;
  273. settings_.snap_mode = false;
  274. SaveState();
  275. ChangeControlMode();
  276. SetFunction(0, function_[0]);
  277. SetFunction(1, function_[1]);
  278. // Done with calibration.
  279. calibrating_ = false;
  280. }
  281. return;
  282. }
  283. switch (e.control_id) {
  284. case SWITCH_TWIN_MODE:
  285. if (e.data > kLongPressDuration) {
  286. edit_mode_ = static_cast<EditMode>(
  287. (edit_mode_ + EDIT_MODE_FIRST) % EDIT_MODE_LAST);
  288. function_[0] = function_[1];
  289. processors[0].set_function(function_table_[function_[0]][0]);
  290. processors[1].set_function(function_table_[function_[0]][1]);
  291. LockPots();
  292. } else {
  293. if (edit_mode_ <= EDIT_MODE_SPLIT) {
  294. edit_mode_ = static_cast<EditMode>(EDIT_MODE_SPLIT - edit_mode_);
  295. } else {
  296. edit_mode_ = static_cast<EditMode>(EDIT_MODE_SECOND - (edit_mode_ & 1));
  297. LockPots();
  298. }
  299. }
  300. ChangeControlMode();
  301. SaveState();
  302. break;
  303. case SWITCH_FUNCTION:
  304. {
  305. Function f = function();
  306. if (e.data > kLongPressDuration) {
  307. f = static_cast<Function>((f + FUNCTION_FIRST_ALTERNATE_FUNCTION) % FUNCTION_LAST);
  308. } else {
  309. if (f <= FUNCTION_DRUM_GENERATOR) {
  310. f = static_cast<Function>((f + 1) & 3);
  311. } else {
  312. f = static_cast<Function>(((f + 1) & 3) + FUNCTION_FIRST_ALTERNATE_FUNCTION);
  313. }
  314. }
  315. SetFunction(edit_mode_ - EDIT_MODE_FIRST, f);
  316. SaveState();
  317. }
  318. break;
  319. case SWITCH_GATE_TRIG_1:
  320. panel_gate_control_[0] = false;
  321. break;
  322. case SWITCH_GATE_TRIG_2:
  323. panel_gate_control_[1] = false;
  324. break;
  325. }
  326. }
  327. void Ui::OnPotChanged(const Event& e) {
  328. if (calibrating_) {
  329. pot_value_[e.control_id] = e.data >> 8;
  330. for (uint8_t i = 0; i < 2; ++i) {
  331. int32_t coarse = pot_value_[i * 2];
  332. int32_t fine = pot_value_[i * 2 + 1];
  333. int32_t offset = ((coarse - 128) << 3) + ((fine - 128) >> 1);
  334. calibration_data_->set_dac_offset(i, -offset);
  335. }
  336. return;
  337. }
  338. switch (edit_mode_) {
  339. case EDIT_MODE_TWIN:
  340. processors[0].set_parameter(e.control_id, e.data);
  341. processors[1].set_parameter(e.control_id, e.data);
  342. pot_value_[e.control_id] = e.data >> 8;
  343. break;
  344. case EDIT_MODE_SPLIT:
  345. if (e.control_id < 2) {
  346. processors[0].set_parameter(e.control_id, e.data);
  347. } else {
  348. processors[1].set_parameter(e.control_id - 2, e.data);
  349. }
  350. pot_value_[e.control_id] = e.data >> 8;
  351. break;
  352. case EDIT_MODE_FIRST:
  353. case EDIT_MODE_SECOND:
  354. {
  355. uint8_t index = e.control_id + (edit_mode_ - EDIT_MODE_FIRST) * 4;
  356. Processors* p = &processors[edit_mode_ - EDIT_MODE_FIRST];
  357. int16_t delta = static_cast<int16_t>(pot_value_[index]) - \
  358. static_cast<int16_t>(e.data >> 8);
  359. if (delta < 0) {
  360. delta = -delta;
  361. }
  362. if (!settings_.snap_mode || snapped_[e.control_id] || delta <= 2) {
  363. p->set_parameter(e.control_id, e.data);
  364. pot_value_[index] = e.data >> 8;
  365. snapped_[e.control_id] = true;
  366. }
  367. }
  368. break;
  369. case EDIT_MODE_LAST:
  370. break;
  371. }
  372. }
  373. void Ui::DoEvents() {
  374. while (queue_.available()) {
  375. Event e = queue_.PullEvent();
  376. if (e.control_type == CONTROL_SWITCH) {
  377. if (e.data == 0) {
  378. OnSwitchPressed(e);
  379. } else {
  380. OnSwitchReleased(e);
  381. }
  382. } else if (e.control_type == CONTROL_POT) {
  383. OnPotChanged(e);
  384. }
  385. }
  386. if (queue_.idle_time() > 1000) {
  387. queue_.Touch();
  388. }
  389. }
  390. } // namespace peaks