MicroDexed is a compatible 6-operator-FM-synth based on the Teensy(-3.6/-4.0) Microcontroller. https://www.parasitstudio.de
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.

593 lines
19KB

  1. /*
  2. MicroDexed
  3. MicroDexed is a port of the Dexed sound engine
  4. (https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield.
  5. Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android
  6. (c)2018,2019 H. Wirtz <wirtz@parasitstudio.de>
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 3 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software Foundation,
  17. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include <Arduino.h>
  20. #include <limits.h>
  21. #include "config.h"
  22. #include "dexed.h"
  23. #include "dexed_sysex.h"
  24. #include "UI.h"
  25. #ifdef I2C_DISPLAY // selecting sounds by encoder, button and display
  26. elapsedMillis ui_back_to_main;
  27. void handle_ui(void)
  28. {
  29. if (ui_back_to_main >= UI_AUTO_BACK_MS && (ui_state != UI_MAIN && ui_state != UI_EFFECTS_FILTER && ui_state != UI_EFFECTS_DELAY))
  30. {
  31. enc[0].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
  32. enc_val[0] = enc[0].read();
  33. ui_show_main();
  34. }
  35. if (autostore >= AUTOSTORE_MS && (ui_main_state == UI_MAIN_VOICE_SELECTED || ui_main_state == UI_MAIN_BANK_SELECTED))
  36. {
  37. switch (ui_main_state)
  38. {
  39. case UI_MAIN_VOICE_SELECTED:
  40. ui_main_state = UI_MAIN_VOICE;
  41. break;
  42. case UI_MAIN_BANK_SELECTED:
  43. ui_main_state = UI_MAIN_BANK;
  44. break;
  45. }
  46. }
  47. for (uint8_t i = 0; i < NUM_ENCODER; i++)
  48. {
  49. but[i].update();
  50. if (but[i].fallingEdge())
  51. long_button_pressed = 0;
  52. if (but[i].risingEdge())
  53. {
  54. uint32_t button_released = long_button_pressed;
  55. if (button_released > LONG_BUTTON_PRESS)
  56. {
  57. // long pressing of button detected
  58. #ifdef DEBUG
  59. Serial.print(F("Long button pressing detected for button "));
  60. Serial.println(i, DEC);
  61. #endif
  62. switch (i)
  63. {
  64. case 0: // long press for left button
  65. break;
  66. case 1: // long press for right button
  67. switch (ui_state)
  68. {
  69. case UI_MAIN:
  70. ui_main_state = UI_MAIN_FILTER_RES;
  71. enc[i].write(effect_filter_resonance);
  72. enc_val[i] = enc[i].read();
  73. ui_show_effects_filter();
  74. break;
  75. case UI_EFFECTS_FILTER:
  76. ui_main_state = UI_MAIN_DELAY_TIME;
  77. enc[i].write(effect_delay_time);
  78. enc_val[i] = enc[i].read();
  79. ui_show_effects_delay();
  80. break;
  81. case UI_EFFECTS_DELAY:
  82. ui_main_state = UI_MAIN_VOICE;
  83. enc[i].write(configuration.voice);
  84. enc_val[i] = enc[i].read();
  85. ui_show_main();
  86. break;
  87. }
  88. break;
  89. }
  90. }
  91. else
  92. {
  93. // Button pressed
  94. switch (i)
  95. {
  96. case 0: // left button pressed
  97. switch (ui_state)
  98. {
  99. case UI_MAIN:
  100. enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
  101. enc_val[i] = enc[i].read();
  102. ui_show_volume();
  103. break;
  104. case UI_VOLUME:
  105. enc[i].write(configuration.midi_channel);
  106. enc_val[i] = enc[i].read();
  107. ui_show_midichannel();
  108. break;
  109. case UI_MIDICHANNEL:
  110. enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
  111. enc_val[i] = enc[i].read();
  112. ui_show_main();
  113. break;
  114. }
  115. break;
  116. case 1: // right button pressed
  117. switch (ui_state)
  118. {
  119. case UI_MAIN:
  120. switch (ui_main_state)
  121. {
  122. case UI_MAIN_BANK:
  123. case UI_MAIN_BANK_SELECTED:
  124. ui_main_state = UI_MAIN_VOICE;
  125. enc[i].write(configuration.voice);
  126. enc_val[i] = enc[i].read();
  127. break;
  128. case UI_MAIN_VOICE:
  129. case UI_MAIN_VOICE_SELECTED:
  130. ui_main_state = UI_MAIN_BANK;
  131. enc[i].write(configuration.bank);
  132. enc_val[i] = enc[i].read();
  133. break;
  134. }
  135. ui_show_main();
  136. break;
  137. case UI_EFFECTS_FILTER:
  138. case UI_EFFECTS_DELAY:
  139. switch (ui_main_state)
  140. {
  141. case UI_MAIN_FILTER_RES:
  142. ui_main_state = UI_MAIN_FILTER_CUT;
  143. enc[i].write(effect_filter_cutoff);
  144. enc_val[i] = enc[i].read();
  145. ui_show_effects_filter();
  146. break;
  147. case UI_MAIN_FILTER_CUT:
  148. ui_main_state = UI_MAIN_FILTER_RES;
  149. enc[i].write(effect_filter_resonance);
  150. enc_val[i] = enc[i].read();
  151. ui_show_effects_filter();
  152. break;
  153. case UI_MAIN_DELAY_TIME:
  154. ui_main_state = UI_MAIN_DELAY_FEEDBACK;
  155. enc[i].write(effect_delay_feedback);
  156. enc_val[i] = enc[i].read();
  157. ui_show_effects_delay();
  158. break;
  159. case UI_MAIN_DELAY_VOLUME:
  160. ui_main_state = UI_MAIN_DELAY_TIME;
  161. enc[i].write(effect_delay_time);
  162. enc_val[i] = enc[i].read();
  163. ui_show_effects_delay();
  164. break;
  165. case UI_MAIN_DELAY_FEEDBACK:
  166. ui_main_state = UI_MAIN_DELAY_VOLUME;
  167. enc[i].write(effect_delay_volume);
  168. enc_val[i] = enc[i].read();
  169. ui_show_effects_delay();
  170. break;
  171. }
  172. break;
  173. }
  174. }
  175. }
  176. #ifdef DEBUG
  177. Serial.print(F("Button "));
  178. Serial.println(i, DEC);
  179. #endif
  180. }
  181. if (enc[i].read() == enc_val[i])
  182. continue;
  183. else
  184. {
  185. switch (i)
  186. {
  187. case 0: // left encoder moved
  188. float tmp;
  189. switch (ui_state)
  190. {
  191. case UI_MAIN:
  192. case UI_VOLUME:
  193. if (enc[i].read() <= 0)
  194. enc[i].write(0);
  195. else if (enc[i].read() >= ENC_VOL_STEPS)
  196. enc[i].write(ENC_VOL_STEPS);
  197. enc_val[i] = enc[i].read();
  198. //set_volume(float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100, configuration.pan);
  199. tmp = (float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100) - configuration.vol;
  200. soften_volume.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
  201. soften_volume.steps = SOFTEN_VALUE_CHANGE_STEPS;
  202. #ifdef DEBUG
  203. Serial.print(F("Setting soften volume from: "));
  204. Serial.print(configuration.vol, 5);
  205. Serial.print(F("/Volume step: "));
  206. Serial.print(soften_volume.steps);
  207. Serial.print(F("/Volume diff: "));
  208. Serial.println(soften_volume.diff, 5);
  209. #endif
  210. eeprom_write();
  211. ui_show_volume();
  212. break;
  213. case UI_MIDICHANNEL:
  214. if (enc[i].read() <= 0)
  215. enc[i].write(0);
  216. else if (enc[i].read() >= 16)
  217. enc[i].write(16);
  218. configuration.midi_channel = enc[i].read();
  219. eeprom_write();
  220. ui_show_midichannel();
  221. break;
  222. }
  223. break;
  224. case 1: // right encoder moved
  225. switch (ui_state)
  226. {
  227. case UI_VOLUME:
  228. ui_state = UI_MAIN;
  229. lcd.clear();
  230. enc[1].write(configuration.voice);
  231. eeprom_write();
  232. ui_show_main();
  233. break;
  234. case UI_MAIN:
  235. switch (ui_main_state)
  236. {
  237. case UI_MAIN_BANK:
  238. ui_main_state = UI_MAIN_BANK_SELECTED;
  239. case UI_MAIN_BANK_SELECTED:
  240. if (enc[i].read() <= 0)
  241. enc[i].write(0);
  242. else if (enc[i].read() > max_loaded_banks - 1)
  243. enc[i].write(max_loaded_banks - 1);
  244. configuration.bank = enc[i].read();
  245. get_voice_names_from_bank(configuration.bank);
  246. load_sysex(configuration.bank, configuration.voice);
  247. eeprom_write();
  248. break;
  249. case UI_MAIN_VOICE:
  250. ui_main_state = UI_MAIN_VOICE_SELECTED;
  251. case UI_MAIN_VOICE_SELECTED:
  252. if (enc[i].read() <= 0)
  253. {
  254. if (configuration.bank > 0)
  255. {
  256. enc[i].write(MAX_VOICES - 1);
  257. configuration.bank--;
  258. get_voice_names_from_bank(configuration.bank);
  259. }
  260. else
  261. enc[i].write(0);
  262. }
  263. else if (enc[i].read() > MAX_VOICES - 1)
  264. {
  265. if (configuration.bank < MAX_BANKS - 1)
  266. {
  267. enc[i].write(0);
  268. configuration.bank++;
  269. get_voice_names_from_bank(configuration.bank);
  270. }
  271. else
  272. enc[i].write(MAX_VOICES - 1);
  273. }
  274. configuration.voice = enc[i].read();
  275. load_sysex(configuration.bank, configuration.voice);
  276. eeprom_write();
  277. break;
  278. }
  279. ui_show_main();
  280. break;
  281. case UI_EFFECTS_FILTER:
  282. switch (ui_main_state)
  283. {
  284. case UI_MAIN_FILTER_RES:
  285. if (enc[i].read() <= 0)
  286. enc[i].write(0);
  287. else if (enc[i].read() >= ENC_FILTER_RES_STEPS)
  288. enc[i].write(ENC_FILTER_RES_STEPS);
  289. enc_val[i] = enc[i].read();
  290. effect_filter_resonance = enc[i].read();
  291. tmp = 1.0 - (float(map(enc[i].read(), 0, ENC_FILTER_RES_STEPS, 0, 100)) / 100) - dexed->fx.Reso;
  292. soften_filter_res.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
  293. soften_filter_res.steps = SOFTEN_VALUE_CHANGE_STEPS;
  294. #ifdef DEBUG
  295. Serial.print(F("Setting soften filter-resonance from: "));
  296. Serial.print(dexed->fx.Reso, 5);
  297. Serial.print(F("/Filter-Resonance step: "));
  298. Serial.print(soften_filter_res.steps);
  299. Serial.print(F("/Filter-Resonance diff: "));
  300. Serial.println(soften_filter_res.diff, 5);
  301. #endif
  302. break;
  303. case UI_MAIN_FILTER_CUT:
  304. if (enc[i].read() <= 0)
  305. enc[i].write(0);
  306. else if (enc[i].read() >= ENC_FILTER_CUT_STEPS)
  307. enc[i].write(ENC_FILTER_CUT_STEPS);
  308. enc_val[i] = enc[i].read();
  309. effect_filter_cutoff = enc[i].read();
  310. tmp = 1.0 - (float(map(enc[i].read(), 0, ENC_FILTER_CUT_STEPS, 0, 100)) / 100) - dexed->fx.Cutoff;
  311. soften_filter_cut.diff = tmp / SOFTEN_VALUE_CHANGE_STEPS;
  312. soften_filter_cut.steps = SOFTEN_VALUE_CHANGE_STEPS;
  313. #ifdef DEBUG
  314. Serial.print(F("Setting soften filter-cutoff from: "));
  315. Serial.print(dexed->fx.Cutoff, 5);
  316. Serial.print(F("/Filter-Cutoff step: "));
  317. Serial.print(soften_filter_cut.steps);
  318. Serial.print(F("/Filter-Cutoff diff: "));
  319. Serial.println(soften_filter_cut.diff, 5);
  320. #endif
  321. break;
  322. }
  323. ui_show_effects_filter();
  324. break;
  325. case UI_EFFECTS_DELAY:
  326. switch (ui_main_state)
  327. {
  328. case UI_MAIN_DELAY_TIME:
  329. if (enc[i].read() <= 0)
  330. enc[i].write(0);
  331. else if (enc[i].read() > ENC_DELAY_TIME_STEPS)
  332. enc[i].write(ENC_DELAY_TIME_STEPS);
  333. effect_delay_time = enc[i].read();;
  334. delay1.delay(0, mapfloat(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0.0, DELAY_MAX_TIME));
  335. #ifdef DEBUG
  336. Serial.print(F("Setting delay time to: "));
  337. Serial.println(map(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0, DELAY_MAX_TIME));
  338. #endif
  339. break;
  340. case UI_MAIN_DELAY_FEEDBACK:
  341. if (enc[i].read() <= 0)
  342. enc[i].write(0);
  343. else if (enc[i].read() > ENC_DELAY_FB_STEPS)
  344. enc[i].write(ENC_DELAY_FB_STEPS);
  345. effect_delay_feedback = enc[i].read();
  346. mixer1.gain(1, mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
  347. #ifdef DEBUG
  348. Serial.print(F("Setting delay feedback to: "));
  349. Serial.println(mapfloat(float(effect_delay_feedback), 0, ENC_DELAY_FB_STEPS, 0.0, 1.0));
  350. #endif
  351. break;
  352. case UI_MAIN_DELAY_VOLUME:
  353. if (enc[i].read() <= 0)
  354. enc[i].write(0);
  355. else if (enc[i].read() > ENC_DELAY_VOLUME_STEPS)
  356. enc[i].write(ENC_DELAY_VOLUME_STEPS);
  357. effect_delay_volume = enc[i].read();
  358. float tmp_vol = mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0);
  359. //mixer2.gain(0, 1.0 - mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delay tap1 signal (with added feedback)
  360. mixer2.gain(0, 1.0 - tmp_vol); // delay tap1 signal (with added feedback)
  361. mixer2.gain(1, tmp_vol); // delay tap1 signal (with added feedback)
  362. mixer2.gain(2, tmp_vol); // delay tap1 signal
  363. #ifdef DEBUG
  364. Serial.print(F("Setting delay volume to: "));
  365. Serial.println(effect_delay_volume);
  366. #endif
  367. break;
  368. }
  369. ui_show_effects_delay();
  370. break;
  371. }
  372. break;
  373. }
  374. #ifdef DEBUG
  375. Serial.print(F("Encoder "));
  376. Serial.print(i, DEC);
  377. Serial.print(F(": "));
  378. Serial.println(enc[i].read(), DEC);
  379. #endif
  380. }
  381. enc_val[i] = enc[i].read();
  382. }
  383. }
  384. void ui_show_main(void)
  385. {
  386. if (ui_state != UI_MAIN)
  387. {
  388. lcd.clear();
  389. }
  390. lcd.show(0, 0, 2, configuration.bank);
  391. lcd.show(0, 2, 1, " ");
  392. strip_extension(bank_names[configuration.bank], bank_name);
  393. if (ui_main_state == UI_MAIN_BANK || ui_main_state == UI_MAIN_BANK_SELECTED)
  394. {
  395. lcd.show(0, 2, 1, "[");
  396. lcd.show(0, 3, 8, bank_name);
  397. lcd.show(0, 11, 1, "]");
  398. }
  399. else
  400. {
  401. lcd.show(0, 2, 1, " ");
  402. lcd.show(0, 3, 8, bank_name);
  403. lcd.show(0, 11, 1, " ");
  404. }
  405. lcd.show(1, 0, 2, configuration.voice + 1);
  406. lcd.show(1, 2, 1, " ");
  407. if (ui_main_state == UI_MAIN_VOICE || ui_main_state == UI_MAIN_VOICE_SELECTED)
  408. {
  409. lcd.show(1, 2, 1, "[");
  410. lcd.show(1, 3, 10, voice_names[configuration.voice]);
  411. lcd.show(1, 14, 1, "]");
  412. }
  413. else
  414. {
  415. lcd.show(1, 2, 1, " ");
  416. lcd.show(1, 3, 10, voice_names[configuration.voice]);
  417. lcd.show(1, 14, 1, " ");
  418. }
  419. ui_state = UI_MAIN;
  420. }
  421. void ui_show_volume(void)
  422. {
  423. uint8_t pos;
  424. static uint8_t old_pos;
  425. ui_back_to_main = 0;
  426. // erase old marker and show new marker
  427. pos = map(configuration.vol * 100 + 0.5, 0, 100, 0, LCD_CHARS - 1);
  428. if (ui_state != UI_VOLUME)
  429. {
  430. lcd.clear();
  431. lcd.show(0, 0, LCD_CHARS - 1, "Volume");
  432. lcd.show(1, pos, 1, "*");
  433. old_pos = pos;
  434. }
  435. // show value
  436. lcd.show(0, LCD_CHARS - 3, 3, (configuration.vol * 100 + 0.5));
  437. if (pos != old_pos)
  438. {
  439. lcd.show(1, pos, 1, "*");
  440. lcd.show(1, old_pos, 1, " ");
  441. old_pos = pos;
  442. }
  443. ui_state = UI_VOLUME;
  444. }
  445. void ui_show_midichannel(void)
  446. {
  447. ui_back_to_main = 0;
  448. if (ui_state != UI_MIDICHANNEL)
  449. {
  450. lcd.clear();
  451. lcd.show(0, 0, LCD_CHARS, "MIDI Channel");
  452. }
  453. if (configuration.midi_channel == MIDI_CHANNEL_OMNI)
  454. lcd.show(1, 0, 4, "OMNI");
  455. else
  456. {
  457. lcd.show(1, 0, 2, configuration.midi_channel);
  458. if (configuration.midi_channel == 1)
  459. lcd.show(1, 2, 2, " ");
  460. }
  461. ui_state = UI_MIDICHANNEL;
  462. }
  463. void ui_show_effects_filter(void)
  464. {
  465. if (ui_state != UI_EFFECTS_FILTER)
  466. {
  467. lcd.clear();
  468. lcd.show(0, 0, LCD_CHARS, "Filter");
  469. lcd.show(1, 0, 4, "Res:");
  470. lcd.show(1, 8, 4, "Cut:");
  471. }
  472. lcd.show(1, 5, 2, map(effect_filter_resonance, 0, ENC_FILTER_RES_STEPS, 0, 99));
  473. lcd.show(1, 13, 2, map(effect_filter_cutoff, 0, ENC_FILTER_CUT_STEPS, 0, 99));
  474. if (ui_main_state == UI_MAIN_FILTER_RES)
  475. {
  476. lcd.show(1, 4, 1, "[");
  477. lcd.show(1, 7, 1, "]");
  478. }
  479. else
  480. {
  481. lcd.show(1, 4, 1, " ");
  482. lcd.show(1, 7, 1, " ");
  483. }
  484. if (ui_main_state == UI_MAIN_FILTER_CUT)
  485. {
  486. lcd.show(1, 12, 1, "[");
  487. lcd.show(1, 15, 1, "]");
  488. }
  489. else
  490. {
  491. lcd.show(1, 12, 1, " ");
  492. lcd.show(1, 15, 1, " ");
  493. }
  494. ui_state = UI_EFFECTS_FILTER;
  495. }
  496. void ui_show_effects_delay(void)
  497. {
  498. if (ui_state != UI_EFFECTS_DELAY)
  499. {
  500. lcd.clear();
  501. lcd.show(0, 0, 5, "Delay");
  502. lcd.show(0, 6, 2, "T:");
  503. lcd.show(0, 14, 2, "ms");
  504. lcd.show(1, 0, 3, "FB:");
  505. lcd.show(1, 8, 5, "Vol:");
  506. }
  507. lcd.show(0, 9, 4, map(effect_delay_time, 0, ENC_DELAY_TIME_STEPS, 0, DELAY_MAX_TIME));
  508. lcd.show(1, 4, 2, map(effect_delay_feedback, 0, ENC_DELAY_FB_STEPS, 0, 99));
  509. lcd.show(1, 13, 2, map(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0, 99));
  510. if (ui_main_state == UI_MAIN_DELAY_TIME)
  511. {
  512. lcd.show(0, 8, 1, "[");
  513. lcd.show(0, 13, 1, "]");
  514. }
  515. else
  516. {
  517. lcd.show(0, 8, 1, " ");
  518. lcd.show(0, 13, 1, " ");
  519. }
  520. if (ui_main_state == UI_MAIN_DELAY_FEEDBACK)
  521. {
  522. lcd.show(1, 3, 1, "[");
  523. lcd.show(1, 6, 1, "]");
  524. }
  525. else
  526. {
  527. lcd.show(1, 3, 1, " ");
  528. lcd.show(1, 6, 1, " ");
  529. }
  530. if (ui_main_state == UI_MAIN_DELAY_VOLUME)
  531. {
  532. lcd.show(1, 12, 1, "[");
  533. lcd.show(1, 15, 1, "]");
  534. }
  535. else
  536. {
  537. lcd.show(1, 12, 1, " ");
  538. lcd.show(1, 15, 1, " ");
  539. }
  540. ui_state = UI_EFFECTS_DELAY;
  541. }
  542. #endif
  543. float mapfloat(float val, float in_min, float in_max, float out_min, float out_max)
  544. {
  545. return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
  546. }