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.

197 lines
5.5KB

  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. #include <stm32f10x_conf.h>
  25. #include "stmlib/utils/dsp.h"
  26. #include "stmlib/utils/ring_buffer.h"
  27. #include "stmlib/system/system_clock.h"
  28. #include "stmlib/system/uid.h"
  29. #include "yarns/drivers/dac.h"
  30. #include "yarns/drivers/gate_output.h"
  31. #include "yarns/drivers/midi_io.h"
  32. #include "yarns/drivers/system.h"
  33. #include "yarns/midi_handler.h"
  34. #include "yarns/multi.h"
  35. #include "yarns/settings.h"
  36. #include "yarns/storage_manager.h"
  37. #include "yarns/ui.h"
  38. using namespace yarns;
  39. using namespace stmlib;
  40. Dac dac;
  41. GateOutput gate_output;
  42. Ui ui;
  43. MidiIO midi_io;
  44. System sys;
  45. extern "C" {
  46. void HardFault_Handler(void) { while (1); }
  47. void MemManage_Handler(void) { while (1); }
  48. void BusFault_Handler(void) { while (1); }
  49. void UsageFault_Handler(void) { while (1); }
  50. void NMI_Handler(void) { }
  51. void SVC_Handler(void) { }
  52. void DebugMon_Handler(void) { }
  53. void PendSV_Handler(void) { }
  54. }
  55. extern "C" {
  56. uint16_t cv[4];
  57. bool gate[4];
  58. bool has_audio_sources;
  59. uint8_t audio_source[4];
  60. uint16_t factory_testing_counter;
  61. void SysTick_Handler() {
  62. // MIDI I/O, and CV/Gate refresh at 8kHz.
  63. // UI polling and LED refresh at 1kHz.
  64. static uint8_t counter;
  65. if ((++counter & 7) == 0) {
  66. ui.Poll();
  67. system_clock.Tick();
  68. }
  69. // When there is audio sources, lower the display refresh rate to 8kHz.
  70. if (has_audio_sources) {
  71. ui.PollFast();
  72. }
  73. // Try to read some MIDI input if available.
  74. if (midi_io.readable()) {
  75. midi_handler.PushByte(midi_io.ImmediateRead());
  76. }
  77. // Try to push some MIDI data out.
  78. if (midi_handler.mutable_high_priority_output_buffer()->readable()) {
  79. if (midi_io.writable()) {
  80. midi_io.Overwrite(
  81. midi_handler.mutable_high_priority_output_buffer()->ImmediateRead());
  82. }
  83. }
  84. if (midi_handler.mutable_output_buffer()->readable()) {
  85. if (midi_io.writable()) {
  86. midi_io.Overwrite(midi_handler.mutable_output_buffer()->ImmediateRead());
  87. }
  88. }
  89. // Observe that the gate output is written with a systick (0.125 ms) delay
  90. // compared to the CV output. This ensures that the CV output will have been
  91. // refreshed to the right value when the trigger/gate is sent.
  92. gate_output.Write(gate);
  93. multi.Refresh();
  94. multi.GetCvGate(cv, gate);
  95. has_audio_sources = multi.GetAudioSource(audio_source);
  96. // In calibration mode, overrides the DAC outputs with the raw calibration
  97. // table values.
  98. if (ui.calibrating()) {
  99. const Voice& voice = multi.voice(ui.calibration_voice());
  100. cv[ui.calibration_voice()] = voice.calibration_dac_code(
  101. ui.calibration_note());
  102. } else if (midi_handler.calibrating()) {
  103. const Voice& voice = multi.voice(midi_handler.calibration_voice());
  104. cv[midi_handler.calibration_voice()] = voice.calibration_dac_code(
  105. midi_handler.calibration_note());
  106. }
  107. // In UI testing mode, overrides the GATE values with timers
  108. if (ui.factory_testing()) {
  109. gate[0] = (factory_testing_counter % 800) < 400;
  110. gate[1] = (factory_testing_counter % 400) < 200;
  111. gate[2] = (factory_testing_counter % 266) < 133;
  112. gate[3] = (factory_testing_counter % 200) < 100;
  113. ++factory_testing_counter;
  114. }
  115. dac.Write(cv);
  116. }
  117. void TIM1_UP_IRQHandler(void) {
  118. // DAC refresh at 4x 48kHz.
  119. if (TIM_GetITStatus(TIM1, TIM_IT_Update) == RESET) {
  120. return;
  121. }
  122. TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
  123. dac.Cycle();
  124. uint8_t source_voice = audio_source[dac.channel()];
  125. if (source_voice != 0xff) {
  126. uint16_t audio_sample = multi.mutable_voice(source_voice)->ReadSample();
  127. dac.Write(audio_sample);
  128. } else {
  129. // Use value written there during previous CV refresh.
  130. dac.Write();
  131. }
  132. if (dac.channel() == 0) {
  133. // Internal clock refresh at 48kHz
  134. multi.RefreshInternalClock();
  135. } else if (dac.channel() == 1) {
  136. if (!has_audio_sources) {
  137. ui.PollFast();
  138. }
  139. }
  140. }
  141. }
  142. void Init() {
  143. sys.Init();
  144. settings.Init();
  145. multi.Init();
  146. ui.Init();
  147. // Load multi 0 on boot.
  148. storage_manager.LoadMulti(0);
  149. storage_manager.LoadCalibration();
  150. system_clock.Init();
  151. gate_output.Init();
  152. dac.Init();
  153. midi_io.Init();
  154. midi_handler.Init();
  155. sys.StartTimers();
  156. }
  157. int main(void) {
  158. Init();
  159. while (1) {
  160. ui.DoEvents();
  161. midi_handler.ProcessInput();
  162. multi.ProcessInternalClockEvents();
  163. multi.RenderAudio();
  164. if (midi_handler.factory_testing_requested()) {
  165. midi_handler.AcknowledgeFactoryTestingRequest();
  166. ui.StartFactoryTesting();
  167. }
  168. }
  169. }