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.

376 lines
10KB

  1. // Copyright 2012 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. #include <avr/eeprom.h>
  16. #include "avrlib/adc.h"
  17. #include "avrlib/boot.h"
  18. #include "avrlib/op.h"
  19. #include "avrlib/watchdog_timer.h"
  20. #include "grids/clock.h"
  21. #include "grids/hardware_config.h"
  22. #include "grids/pattern_generator.h"
  23. using namespace avrlib;
  24. using namespace grids;
  25. Leds leds;
  26. Inputs inputs;
  27. AdcInputScanner adc;
  28. ShiftRegister shift_register;
  29. MidiInput midi;
  30. enum Parameter {
  31. PARAMETER_NONE,
  32. PARAMETER_WAITING,
  33. PARAMETER_CLOCK_RESOLUTION,
  34. PARAMETER_TAP_TEMPO,
  35. PARAMETER_SWING,
  36. PARAMETER_GATE_MODE,
  37. PARAMETER_OUTPUT_MODE,
  38. PARAMETER_CLOCK_OUTPUT
  39. };
  40. uint32_t tap_duration = 0;
  41. uint8_t led_pattern ;
  42. uint8_t led_off_timer;
  43. int8_t swing_amount;
  44. volatile Parameter parameter = PARAMETER_NONE;
  45. volatile bool long_press_detected = false;
  46. const uint8_t kUpdatePeriod = F_CPU / 32 / 8000;
  47. inline void UpdateLeds() {
  48. uint8_t pattern;
  49. if (parameter == PARAMETER_NONE) {
  50. if (led_off_timer) {
  51. --led_off_timer;
  52. if (!led_off_timer) {
  53. led_pattern = 0;
  54. }
  55. }
  56. pattern = led_pattern;
  57. if (pattern_generator.tap_tempo()) {
  58. if (pattern_generator.on_beat()) {
  59. pattern |= LED_CLOCK;
  60. }
  61. } else {
  62. if (pattern_generator.on_first_beat()) {
  63. pattern |= LED_CLOCK;
  64. }
  65. }
  66. } else {
  67. pattern = LED_CLOCK;
  68. switch (parameter) {
  69. case PARAMETER_CLOCK_RESOLUTION:
  70. pattern |= LED_BD >> pattern_generator.clock_resolution();
  71. break;
  72. case PARAMETER_CLOCK_OUTPUT:
  73. if (pattern_generator.output_clock()) {
  74. pattern |= LED_ALL;
  75. }
  76. break;
  77. case PARAMETER_SWING:
  78. if (pattern_generator.swing()) {
  79. pattern |= LED_ALL;
  80. }
  81. break;
  82. case PARAMETER_OUTPUT_MODE:
  83. if (pattern_generator.output_mode() == OUTPUT_MODE_DRUMS) {
  84. pattern |= LED_ALL;
  85. }
  86. break;
  87. case PARAMETER_TAP_TEMPO:
  88. if (pattern_generator.tap_tempo()) {
  89. pattern |= LED_ALL;
  90. }
  91. break;
  92. case PARAMETER_GATE_MODE:
  93. if (pattern_generator.gate_mode()) {
  94. pattern |= LED_ALL;
  95. }
  96. }
  97. }
  98. leds.Write(pattern);
  99. }
  100. inline void UpdateShiftRegister() {
  101. static uint8_t previous_state = 0;
  102. if (pattern_generator.state() != previous_state) {
  103. previous_state = pattern_generator.state();
  104. shift_register.Write(previous_state);
  105. if (!previous_state) {
  106. // Switch off the LEDs, but not now.
  107. led_off_timer = 200;
  108. } else {
  109. // Switch on the LEDs with a new pattern.
  110. led_pattern = pattern_generator.led_pattern();
  111. led_off_timer = 0;
  112. }
  113. }
  114. }
  115. uint8_t ticks_granularity[] = { 6, 3, 1 };
  116. inline void HandleClockResetInputs() {
  117. static uint8_t previous_inputs;
  118. uint8_t inputs_value = ~inputs.Read();
  119. uint8_t num_ticks = 0;
  120. uint8_t increment = ticks_granularity[pattern_generator.clock_resolution()];
  121. // CLOCK
  122. if (clock.bpm() < 40 && !clock.locked()) {
  123. if ((inputs_value & INPUT_CLOCK) && !(previous_inputs & INPUT_CLOCK)) {
  124. num_ticks = increment;
  125. }
  126. if (!(inputs_value & INPUT_CLOCK) && (previous_inputs & INPUT_CLOCK)) {
  127. pattern_generator.ClockFallingEdge();
  128. }
  129. if (midi.readable()) {
  130. uint8_t byte = midi.ImmediateRead();
  131. if (byte == 0xf8) {
  132. num_ticks = 1;
  133. } else if (byte == 0xfa) {
  134. pattern_generator.Reset();
  135. }
  136. }
  137. } else {
  138. clock.Tick();
  139. clock.Wrap(swing_amount);
  140. if (clock.raising_edge()) {
  141. num_ticks = increment;
  142. }
  143. if (clock.past_falling_edge()) {
  144. pattern_generator.ClockFallingEdge();
  145. }
  146. }
  147. // RESET
  148. if ((inputs_value & INPUT_RESET) && !(previous_inputs & INPUT_RESET)) {
  149. pattern_generator.Reset();
  150. // !! HACK AHEAD !!
  151. //
  152. // Earlier versions of the firmware retriggered the outputs whenever a
  153. // RESET signal was received. This allowed for nice drill'n'bass effects,
  154. // but made synchronization with another sequencer a bit glitchy (risk of
  155. // double notes at the beginning of a pattern). It was later decided
  156. // to remove this behaviour and make the RESET transparent (just set the
  157. // step index without producing any trigger) - similar to the MIDI START
  158. // message. However, the factory testing script relies on the old behaviour.
  159. // To solve this problem, we reproduce this behaviour the first 5 times the
  160. // module is powered. After the 5th power-on (or settings change) cycle,
  161. // this odd behaviour disappears.
  162. if (pattern_generator.factory_testing() ||
  163. clock.bpm() >= 40 ||
  164. clock.locked()) {
  165. pattern_generator.Retrigger();
  166. clock.Reset();
  167. }
  168. }
  169. previous_inputs = inputs_value;
  170. if (num_ticks) {
  171. swing_amount = pattern_generator.swing_amount();
  172. pattern_generator.TickClock(num_ticks);
  173. }
  174. }
  175. enum SwitchState {
  176. SWITCH_STATE_JUST_PRESSED = 0xfe,
  177. SWITCH_STATE_PRESSED = 0x00,
  178. SWITCH_STATE_JUST_RELEASED = 0x01,
  179. SWITCH_STATE_RELEASED = 0xff
  180. };
  181. inline void HandleTapButton() {
  182. static uint8_t switch_state = 0xff;
  183. static uint16_t switch_hold_time = 0;
  184. switch_state = switch_state << 1;
  185. if (inputs.Read() & INPUT_SW_RESET) {
  186. switch_state |= 1;
  187. }
  188. if (switch_state == SWITCH_STATE_JUST_PRESSED) {
  189. if (parameter == PARAMETER_NONE) {
  190. if (!pattern_generator.tap_tempo()) {
  191. pattern_generator.Reset();
  192. if (pattern_generator.factory_testing() ||
  193. clock.bpm() >= 40 ||
  194. clock.locked()) {
  195. clock.Reset();
  196. }
  197. } else {
  198. uint32_t new_bpm = (F_CPU * 60L) / (32L * kUpdatePeriod * tap_duration);
  199. if (new_bpm >= 30 && new_bpm <= 480) {
  200. clock.Update(new_bpm, pattern_generator.clock_resolution());
  201. clock.Reset();
  202. clock.Lock();
  203. } else {
  204. clock.Unlock();
  205. }
  206. tap_duration = 0;
  207. }
  208. }
  209. switch_hold_time = 0;
  210. } else if (switch_state == SWITCH_STATE_PRESSED) {
  211. ++switch_hold_time;
  212. if (switch_hold_time == 500) {
  213. long_press_detected = true;
  214. }
  215. }
  216. }
  217. ISR(TIMER2_COMPA_vect, ISR_NOBLOCK) {
  218. static uint8_t switch_debounce_prescaler;
  219. ++tap_duration;
  220. ++switch_debounce_prescaler;
  221. if (switch_debounce_prescaler >= 10) {
  222. // Debounce RESET/TAP switch and perform switch action.
  223. HandleTapButton();
  224. switch_debounce_prescaler = 0;
  225. }
  226. HandleClockResetInputs();
  227. adc.Scan();
  228. pattern_generator.IncrementPulseCounter();
  229. UpdateShiftRegister();
  230. UpdateLeds();
  231. }
  232. static int16_t pot_values[8];
  233. void ScanPots() {
  234. if (long_press_detected) {
  235. if (parameter == PARAMETER_NONE) {
  236. // Freeze pot values
  237. for (uint8_t i = 0; i < 8; ++i) {
  238. pot_values[i] = adc.Read8(i);
  239. }
  240. parameter = PARAMETER_WAITING;
  241. } else {
  242. parameter = PARAMETER_NONE;
  243. pattern_generator.SaveSettings();
  244. }
  245. long_press_detected = false;
  246. }
  247. if (parameter == PARAMETER_NONE) {
  248. uint8_t bpm = adc.Read8(ADC_CHANNEL_TEMPO);
  249. bpm = U8U8MulShift8(bpm, 220) + 20;
  250. if (bpm != clock.bpm() && !clock.locked()) {
  251. clock.Update(bpm, pattern_generator.clock_resolution());
  252. }
  253. PatternGeneratorSettings* settings = pattern_generator.mutable_settings();
  254. settings->options.drums.x = ~adc.Read8(ADC_CHANNEL_X_CV);
  255. settings->options.drums.y = ~adc.Read8(ADC_CHANNEL_Y_CV);
  256. settings->options.drums.randomness = ~adc.Read8(ADC_CHANNEL_RANDOMNESS_CV);
  257. settings->density[0] = ~adc.Read8(ADC_CHANNEL_BD_DENSITY_CV);
  258. settings->density[1] = ~adc.Read8(ADC_CHANNEL_SD_DENSITY_CV);
  259. settings->density[2] = ~adc.Read8(ADC_CHANNEL_HH_DENSITY_CV);
  260. } else {
  261. for (uint8_t i = 0; i < 8; ++i) {
  262. int16_t value = adc.Read8(i);
  263. int16_t delta = value - pot_values[i];
  264. if (delta < 0) {
  265. delta = -delta;
  266. }
  267. if (delta > 32) {
  268. pot_values[i] = value;
  269. switch (i) {
  270. case ADC_CHANNEL_BD_DENSITY_CV:
  271. parameter = PARAMETER_CLOCK_RESOLUTION;
  272. pattern_generator.set_clock_resolution((255 - value) >> 6);
  273. clock.Update(clock.bpm(), pattern_generator.clock_resolution());
  274. pattern_generator.Reset();
  275. break;
  276. case ADC_CHANNEL_SD_DENSITY_CV:
  277. parameter = PARAMETER_TAP_TEMPO;
  278. pattern_generator.set_tap_tempo(!(value & 0x80));
  279. if (!pattern_generator.tap_tempo()) {
  280. clock.Unlock();
  281. }
  282. break;
  283. case ADC_CHANNEL_HH_DENSITY_CV:
  284. parameter = PARAMETER_SWING;
  285. pattern_generator.set_swing(!(value & 0x80));
  286. break;
  287. case ADC_CHANNEL_X_CV:
  288. parameter = PARAMETER_OUTPUT_MODE;
  289. pattern_generator.set_output_mode(!(value & 0x80) ? 1 : 0);
  290. break;
  291. case ADC_CHANNEL_Y_CV:
  292. parameter = PARAMETER_GATE_MODE;
  293. pattern_generator.set_gate_mode(!(value & 0x80));
  294. break;
  295. case ADC_CHANNEL_RANDOMNESS_CV:
  296. parameter = PARAMETER_CLOCK_OUTPUT;
  297. pattern_generator.set_output_clock(!(value & 0x80));
  298. break;
  299. }
  300. }
  301. }
  302. }
  303. }
  304. void Init() {
  305. sei();
  306. UCSR0B = 0;
  307. leds.set_mode(DIGITAL_OUTPUT);
  308. inputs.set_mode(DIGITAL_INPUT);
  309. inputs.EnablePullUpResistors();
  310. clock.Init();
  311. adc.Init();
  312. adc.set_num_inputs(ADC_CHANNEL_LAST);
  313. Adc::set_reference(ADC_DEFAULT);
  314. Adc::set_alignment(ADC_LEFT_ALIGNED);
  315. pattern_generator.Init();
  316. shift_register.Init();
  317. midi.Init();
  318. TCCR2A = _BV(WGM21);
  319. TCCR2B = 3;
  320. OCR2A = kUpdatePeriod - 1;
  321. TIMSK2 |= _BV(1);
  322. }
  323. int main(void) {
  324. ResetWatchdog();
  325. Init();
  326. clock.Update(120, pattern_generator.clock_resolution());
  327. while (1) {
  328. // Use any spare cycles to read the CVs and update the potentiometers
  329. ScanPots();
  330. }
  331. }