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.

255 lines
6.6KB

  1. // Copyright 2012 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (olivier@mutable-instruments.net)
  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. //
  16. // Settings written to eeprom
  17. #ifndef EDGES_SETTINGS_H_
  18. #define EDGES_SETTINGS_H_
  19. #include "avrlibx/avrlibx.h"
  20. #include "avrlibx/utils/op.h"
  21. #include "edges/digital_oscillator.h"
  22. #include "edges/hardware_config.h"
  23. #include "edges/timer_oscillator.h"
  24. namespace edges {
  25. static const uint16_t kHysteresisThreshold = 32;
  26. struct ChannelData {
  27. uint8_t pw;
  28. bool quantized;
  29. bool arpeggio;
  30. uint8_t num_arpeggio_steps;
  31. int8_t arpeggio_step;
  32. // What are stored are not CV values; but instead values relative to the
  33. // first note of the sequence. For example, the sequence
  34. // 1000 2000 4000 2000
  35. // is stored as:
  36. // +1000, +2000, -2000
  37. // This sequence of values is added to the current CV. This allows
  38. // transposition.
  39. int16_t arpeggio_steps[7];
  40. int16_t offset;
  41. int16_t scale;
  42. int16_t fm_offset;
  43. inline int16_t dac_to_pitch(int16_t dac_code) const {
  44. int16_t pitch = S16U12MulShift12(scale, dac_code);
  45. pitch += offset;
  46. if (pitch < 0) {
  47. pitch = 0;
  48. }
  49. if (quantized) {
  50. pitch += 64; // rounding
  51. pitch &= 0xff80;
  52. }
  53. if (pitch >= 16383) {
  54. pitch = 16383;
  55. }
  56. return pitch;
  57. }
  58. inline int16_t dac_to_fm(int16_t dac_code) const {
  59. return pw == PULSE_WIDTH_CV_CONTROLLED
  60. ? 0
  61. : S16U12MulShift12(scale, dac_code) + fm_offset;
  62. }
  63. inline int16_t arpeggio_offset() const {
  64. if (!arpeggio ||
  65. arpeggio_step == 0 ||
  66. arpeggio_step >= num_arpeggio_steps ||
  67. num_arpeggio_steps == 1) {
  68. return 0;
  69. } else {
  70. if (arpeggio_step == -1) {
  71. return arpeggio_steps[num_arpeggio_steps - 2];
  72. } else {
  73. return arpeggio_steps[arpeggio_step - 1];
  74. }
  75. }
  76. }
  77. inline void StartRecording() {
  78. num_arpeggio_steps = 1;
  79. arpeggio_step = -1; // -1 = play the step currently being recorded
  80. arpeggio = true;
  81. }
  82. inline void UpdateArpeggiatorStep(
  83. uint16_t root_dac_code,
  84. uint16_t dac_code) {
  85. if (num_arpeggio_steps > 1) {
  86. int16_t this_note = dac_to_pitch(dac_code);
  87. int16_t root_note = dac_to_pitch(root_dac_code);
  88. arpeggio_steps[num_arpeggio_steps - 2] = this_note - root_note;
  89. }
  90. }
  91. inline void StopRecording() {
  92. arpeggio_step = 0;
  93. }
  94. inline bool NextArpeggiatorStep() {
  95. if (num_arpeggio_steps < 8) {
  96. ++num_arpeggio_steps;
  97. return true;
  98. } else {
  99. StopRecording();
  100. return false;
  101. }
  102. }
  103. };
  104. struct SettingsData {
  105. ChannelData channel[4];
  106. uint8_t midi_channel;
  107. uint8_t midi_mode;
  108. };
  109. class Settings {
  110. public:
  111. Settings() { }
  112. ~Settings() { }
  113. static void Init(bool reset_to_factory_defaults);
  114. static PulseWidth pw(uint8_t channel) {
  115. return static_cast<PulseWidth>(data_.channel[channel].pw);
  116. }
  117. static bool quantized(uint8_t channel) {
  118. return data_.channel[channel].quantized;
  119. }
  120. static bool arpeggio(uint8_t channel) {
  121. return data_.channel[channel].arpeggio;
  122. }
  123. static OscillatorShape shape(uint8_t channel) {
  124. return static_cast<OscillatorShape>(data_.channel[channel].pw);
  125. }
  126. static inline uint8_t num_steps(uint8_t channel) {
  127. return data_.channel[channel].num_arpeggio_steps;
  128. }
  129. static inline int16_t dac_to_fm(uint8_t channel, int16_t dac_code) {
  130. #ifdef OCTAL_ADC
  131. return data_.channel[channel].dac_to_fm(dac_code);
  132. #else
  133. return 0;
  134. #endif // OCTAL_ADC
  135. }
  136. static int16_t dac_to_pitch(uint8_t channel, int16_t dac_code) {
  137. const ChannelData& data = data_.channel[channel];
  138. int16_t pitch = data.dac_to_pitch(dac_code);
  139. if (data.quantized) {
  140. // When pitch is quantized, apply some hysteresis to DAC code.
  141. int16_t delta = dac_code - previous_code_[channel];
  142. if (delta < 0) {
  143. delta = -delta;
  144. }
  145. if (delta < kHysteresisThreshold) {
  146. pitch = previous_pitch_[channel];
  147. } else {
  148. previous_pitch_[channel] = pitch;
  149. previous_code_[channel] = dac_code;
  150. }
  151. }
  152. return pitch + data.arpeggio_offset();
  153. }
  154. static inline uint8_t midi_channel() { return data_.midi_channel; }
  155. static inline uint8_t midi_mode() { return data_.midi_mode; }
  156. static void set_midi_channel(uint8_t midi_channel) {
  157. data_.midi_channel = midi_channel;
  158. Save();
  159. }
  160. static void ToggleMidiMode() {
  161. data_.midi_mode = (data_.midi_mode + 1) & 1;
  162. Save();
  163. }
  164. static void StepPW(uint8_t channel) {
  165. uint8_t value = data_.channel[channel].pw + 1;
  166. if (value > PULSE_WIDTH_CV_CONTROLLED) {
  167. value = PULSE_WIDTH_50;
  168. }
  169. data_.channel[channel].pw = value;
  170. }
  171. static void StepArpeggio(uint8_t channel) {
  172. ChannelData* data = &data_.channel[channel];
  173. if (data->arpeggio_step != -1) {
  174. ++data->arpeggio_step;
  175. if (data->arpeggio_step >= data->num_arpeggio_steps) {
  176. data->arpeggio_step = 0;
  177. }
  178. }
  179. }
  180. static void ToggleQuantizer(uint8_t channel) {
  181. data_.channel[channel].quantized ^= true;
  182. }
  183. static void ToggleArpeggio(uint8_t channel) {
  184. data_.channel[channel].arpeggio ^= true;
  185. }
  186. static void Calibrate(
  187. uint8_t channel,
  188. int16_t dac_code_c2,
  189. int16_t dac_code_c4,
  190. int16_t dac_code_fm) {
  191. if (dac_code_c4 != dac_code_c2) {
  192. int16_t scale = (24 * 128 * 4096L) / (dac_code_c4 - dac_code_c2);
  193. data_.channel[channel].scale = scale;
  194. data_.channel[channel].offset = (60 << 7) - \
  195. S16U12MulShift12(scale, (dac_code_c2 + dac_code_c4) >> 1);
  196. }
  197. data_.channel[channel].fm_offset = \
  198. -S16U12MulShift12(data_.channel[channel].scale, dac_code_fm);
  199. Save();
  200. }
  201. static ChannelData* mutable_channel_data(uint8_t channel) {
  202. return &data_.channel[channel];
  203. }
  204. static void Save();
  205. private:
  206. static int16_t previous_code_[kNumChannels];
  207. static int16_t previous_pitch_[kNumChannels];
  208. static int16_t pitch_bend_[kNumChannels];
  209. static SettingsData data_;
  210. DISALLOW_COPY_AND_ASSIGN(Settings);
  211. };
  212. extern Settings settings;
  213. } // namespace edges
  214. #endif // EDGES_SETTINGS_H_