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.

383 lines
12KB

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