ui_drone.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #include <stddef.h>
  2. #include "ui.h"
  3. #include <string.h>
  4. #include "adc.h"
  5. #include "button.h"
  6. #include "system.h"
  7. #include "unicore-mx/stm32/gpio.h"
  8. #include "unicore-mx/stm32/rcc.h"
  9. #include "pot.h"
  10. #include "dac.h"
  11. #include "settings.h"
  12. #include "timer.h"
  13. #define CENTER_X ((int)(52))
  14. #define CENTER_Y ((int)(50))
  15. #define NEUTRAL 2
  16. static void ui_sequencer_action(struct display_menu_entry *e, uint8_t b);
  17. static void ui_master_action(struct display_menu_entry *e, uint8_t b);
  18. static void ui_bpm_action(struct display_menu_entry *e, uint8_t b);
  19. static void ui_pattern_save_action(struct display_menu_entry *e, uint8_t b);
  20. static void main_menu_prepare(struct display_menu *m);
  21. extern struct display_menu PatternMenu;
  22. static void ui_submenu_action(struct display_menu_entry *e, uint8_t b)
  23. {
  24. ui_display_menu(e->arg);
  25. }
  26. struct display_menu MainMenu = {
  27. .entry_n = 7,
  28. .render = main_menu_prepare,
  29. .entry = {
  30. { ENTRY_TYPE_BOOL, "Sequencer", ui_sequencer_action, .min = 0, .max = 0, .step = 0, NULL, .arg = NULL },
  31. { ENTRY_TYPE_DEC, "Volume: ", ui_master_action, 0, 100, 2, NULL, NULL },
  32. { ENTRY_TYPE_DEC, "BPM: ", ui_bpm_action, 30, 300, 1, NULL, NULL },
  33. { ENTRY_TYPE_DEC, "Pattern :", NULL, 0, MAX_PATTERNS, 1, NULL, NULL },
  34. { ENTRY_TYPE_DEC, "Pattern Len:", NULL, 8, MAX_PATTERN_LEN, 8, NULL, NULL },
  35. { ENTRY_TYPE_TEXT, "Edit Pattern", ui_submenu_action, 0, 0, 0, NULL, &PatternMenu},
  36. { ENTRY_TYPE_TEXT, "Save Pattern", ui_pattern_save_action, 0, 0, 0, NULL, NULL},
  37. }
  38. };
  39. struct display_menu *CurrentMenu = &MainMenu;
  40. extern volatile uint32_t jiffies;
  41. static uint32_t drone_xy_gain = 1;
  42. #if 0
  43. static void ui_return(uint8_t press, int hold)
  44. {
  45. display_clear(NULL);
  46. clear_input_callback();
  47. ui_display_menu(&MainMenu);
  48. }
  49. static void ui_action_interrupt(uint8_t press, int hold)
  50. {
  51. if (press == '+') {
  52. clear_keepalive();
  53. display_clear(NULL);
  54. display_text(5, "Interrupted!");
  55. set_input_callback(ui_return);
  56. }
  57. }
  58. static void display_drone(int line, uint16_t val)
  59. {
  60. char txt[] = "0000";
  61. if (val >= 1000)
  62. txt[0] = '0' + val / 1000;
  63. val %= 1000;
  64. if (val != 0)
  65. txt[3] = '0' + val % 10;
  66. if (val > 9)
  67. txt[2] = '0' + ((val / 10) % 10);
  68. if (val > 99)
  69. txt[1] = '0' + (val / 100);
  70. display_text(line, txt);
  71. }
  72. static void display_thousand(uint32_t val)
  73. {
  74. char txt[4] = "000";
  75. txt[0] = '0' + val / 100;
  76. txt[1] = '0' + (val % 100) / 10;
  77. txt[2] = '0' + (val % 10);
  78. display_text(6, txt);
  79. }
  80. static void display_volume(void)
  81. {
  82. display_thousand(pot_get_master());
  83. }
  84. void ui_drone_xy_poll(void)
  85. {
  86. uint16_t x = 0, y = 0;
  87. char TXT[]="Bender!";
  88. static uint32_t bend_update = 0;
  89. int X, Y;
  90. char bgain[4] = "000";
  91. rcc_periph_clock_enable(RCC_GPIOA);
  92. gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1 | GPIO2);
  93. adc_pin_val(2, &x);
  94. adc_pin_val(1, &y);
  95. X = (100 * x) / 4096;
  96. Y = (100 * y) / 4096;
  97. if (((X > CENTER_X) && ((X - CENTER_X) > NEUTRAL)) || ((X < CENTER_X) && ((CENTER_X - X) > NEUTRAL))) {
  98. int off = X - CENTER_X;
  99. pot_offset(0, off/10);
  100. }
  101. if (((Y > CENTER_Y) && ((Y - CENTER_Y) > NEUTRAL)) || ((Y < CENTER_Y) && ((CENTER_Y - Y) > NEUTRAL))) {
  102. int off = Y - CENTER_Y;
  103. pot_offset(1, off/10);
  104. }
  105. led_beat(((jiffies / 100) % 8) + 1);
  106. display_text(4, TXT);
  107. display_drone(5, pot_get(0));
  108. display_drone(6, pot_get(1));
  109. bgain[0] = '0' + drone_xy_gain / 100;
  110. bgain[1] = '0' + (drone_xy_gain % 100) / 10;
  111. bgain[2] = '0' + (drone_xy_gain % 10);
  112. display_text(7, bgain);
  113. }
  114. void ui_bender_poll(void)
  115. {
  116. uint16_t x = 0, y = 0;
  117. char TXT[]="Bender!";
  118. static uint32_t bend_update = 0;
  119. int X, Y;
  120. char bgain[4] = "000";
  121. rcc_periph_clock_enable(RCC_GPIOA);
  122. gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO1 | GPIO2);
  123. adc_pin_val(2, &x);
  124. adc_pin_val(1, &y);
  125. X = (100 * x) / 4096;
  126. Y = (100 * y) / 4096;
  127. pot_set(0, X);
  128. pot_set(1, Y);
  129. led_beat(((jiffies / 100) % 8) + 1);
  130. display_text(4, TXT);
  131. display_drone(5, pot_get(0));
  132. display_drone(6, pot_get(1));
  133. bgain[0] = '0' + drone_xy_gain / 100;
  134. bgain[1] = '0' + (drone_xy_gain % 100) / 10;
  135. bgain[2] = '0' + (drone_xy_gain % 10);
  136. display_text(7, bgain);
  137. }
  138. static void ui_gain_input(uint8_t press, int hold)
  139. {
  140. if (press == '+') {
  141. display_clear(NULL);
  142. display_text(5, "Interrupted!");
  143. clear_keepalive();
  144. set_input_callback(ui_return);
  145. return;
  146. }
  147. if (press == 'U') {
  148. if (drone_xy_gain < 10)
  149. drone_xy_gain++;
  150. }
  151. if (press == 'D') {
  152. if (drone_xy_gain > 0)
  153. drone_xy_gain--;
  154. }
  155. ui_drone_xy_poll();
  156. }
  157. static void ui_drone_xy(const void *arg)
  158. {
  159. set_input_callback(ui_gain_input);
  160. set_keepalive(ui_drone_xy_poll);
  161. display_clear(NULL);
  162. ui_drone_xy_poll();
  163. }
  164. static void ui_bender(const void *arg)
  165. {
  166. set_input_callback(ui_gain_input);
  167. set_keepalive(ui_bender_poll);
  168. display_clear(NULL);
  169. ui_bender_poll();
  170. }
  171. static void ui_mastervol_input(uint8_t press, int hold)
  172. {
  173. int master_vol = pot_get_master();
  174. if (press == 'U')
  175. if (master_vol < 100)
  176. pot_set_master(master_vol + 5);
  177. if (press == 'D') {
  178. if (master_vol > 4)
  179. pot_set_master(master_vol - 5);
  180. }
  181. if (press == '+') {
  182. display_clear(NULL);
  183. clear_input_callback();
  184. ui_display_menu(&MainMenu);
  185. return;
  186. }
  187. display_text(5, "Master Volume");
  188. display_volume();
  189. }
  190. static void ui_mastervol(const void *arg)
  191. {
  192. set_input_callback(ui_mastervol_input);
  193. display_clear(NULL);
  194. display_text(5, "Master Volume");
  195. display_volume();
  196. }
  197. static void ui_bpm_input(uint8_t press, int hold)
  198. {
  199. uint32_t sys_bpm = timer_get_bpm();
  200. if (press == 'U') {
  201. if (sys_bpm < 300) {
  202. timer_stop();
  203. timer_set_bpm();
  204. led_beat(1);
  205. settings_save();
  206. timer_set_beat(1);
  207. timer_set_beat(1);
  208. timer_start();
  209. }
  210. }
  211. if (press == 'D') {
  212. if (sys_bpm > 60) {
  213. timer_stop();
  214. timer_set_bpm(sys_bpm - 1);
  215. led_beat(1);
  216. settings_save();
  217. timer_set_beat(1);
  218. timer_start();
  219. }
  220. }
  221. if (press == '*') {
  222. display_clear(NULL);
  223. clear_input_callback();
  224. ui_display_menu(&MainMenu);
  225. return;
  226. }
  227. display_text(5, " BPM ");
  228. display_thousand(timer_get_bpm());
  229. }
  230. static void ui_bpm(const void *arg)
  231. {
  232. set_input_callback(ui_bpm_input);
  233. display_clear(NULL);
  234. display_text(5, " BPM ");
  235. display_thousand(timer_get_bpm());
  236. }
  237. static void ui_bytebeat_input(uint8_t press, int hold) {
  238. if (press == '+') {
  239. display_clear(NULL);
  240. clear_input_callback();
  241. clear_keepalive();
  242. ui_display_menu(&MainMenu);
  243. }
  244. }
  245. #define PLAY_SIZE 512
  246. static uint8_t bb_buffer[PLAY_SIZE];
  247. void ui_bytebeat_keepalive(void)
  248. {
  249. static uint32_t t = 0;
  250. int r = 0;
  251. for(r = 0;;t++) {
  252. while (dac_is_busy())
  253. WFI();
  254. bb_buffer[r++] = (t<<1)|(t>>4)*(((t>>12)|(t>>13)|(t>>6) | ((t>>2)|(t>>4))|(t<<1)|(t<<12)|((t<<5)&~(t>>22))));
  255. if (r >= PLAY_SIZE) {
  256. dac_play_direct(bb_buffer, r);
  257. break;
  258. }
  259. }
  260. }
  261. static void ui_bytebeat(const void *arg)
  262. {
  263. set_input_callback(ui_bytebeat_input);
  264. display_clear(NULL);
  265. display_text(5, " Bytebeat! ");
  266. set_keepalive(ui_bytebeat_keepalive);
  267. }
  268. const struct display_menu DroneMenu = {
  269. .entry_n = 2,
  270. .entry = {
  271. { "Drone X, Y ", ui_drone_xy, NULL},
  272. { "Bender ", ui_bender, NULL},
  273. { "", NULL, NULL}
  274. }
  275. };
  276. const struct display_menu SettingsMenu = {
  277. .entry_n = 1,
  278. .entry = {
  279. { "TODO", ui_submenu, &MainMenu },
  280. { "", NULL, NULL}
  281. }
  282. };
  283. #endif
  284. static void ui_sequencer_action(struct display_menu_entry *e, uint8_t b)
  285. {
  286. if (Settings->sequencer_on) {
  287. timer_set_beat(1);
  288. timer_start();
  289. } else {
  290. led_beat(0);
  291. drone_mute();
  292. timer_stop();
  293. }
  294. }
  295. static void ui_master_action(struct display_menu_entry *e, uint8_t b)
  296. {
  297. pot_sync(2);
  298. }
  299. static void ui_bpm_action(struct display_menu_entry *e, uint8_t b)
  300. {
  301. timer_stop();
  302. timer_set_bpm();
  303. led_beat(1);
  304. timer_set_beat(1);
  305. timer_start();
  306. }
  307. static void ui_pattern_save_action(struct display_menu_entry *e, uint8_t b)
  308. {
  309. display_clear();
  310. display_scroll(NULL, 0);
  311. display_text(5, "Saving to FLASH");
  312. settings_save();
  313. ui_display_menu(&MainMenu);
  314. }
  315. static void main_menu_prepare(struct display_menu *m)
  316. {
  317. if (m != &MainMenu)
  318. return;
  319. MainMenu.entry[0].var = &Settings->sequencer_on;
  320. MainMenu.entry[1].var = &Settings->levels[2];
  321. MainMenu.entry[2].var = &Settings->bpm;
  322. MainMenu.entry[3].var = &Settings->current_pattern;
  323. MainMenu.entry[4].var = &(Settings->drums[Settings->current_pattern].len);
  324. }
  325. extern void ui_pattern_menu_action(struct display_menu_entry *e, uint8_t b);