audio_pwm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /* Copyright 2016 Jack Humbert
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  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. #include <stdio.h>
  17. #include <string.h>
  18. //#include <math.h>
  19. #include <avr/pgmspace.h>
  20. #include <avr/interrupt.h>
  21. #include <avr/io.h>
  22. #include "print.h"
  23. #include "audio.h"
  24. #include "keymap.h"
  25. #include "eeconfig.h"
  26. #define PI 3.14159265
  27. #define CPU_PRESCALER 8
  28. #ifndef STARTUP_SONG
  29. # define STARTUP_SONG SONG(STARTUP_SOUND)
  30. #endif
  31. float startup_song[][2] = STARTUP_SONG;
  32. // Timer Abstractions
  33. // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
  34. // Turn on/off 3A interputs, stopping/enabling the ISR calls
  35. #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
  36. #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
  37. // TCCR3A: Timer/Counter #3 Control Register
  38. // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
  39. #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
  40. #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
  41. #define NOTE_PERIOD ICR3
  42. #define NOTE_DUTY_CYCLE OCR3A
  43. #ifdef PWM_AUDIO
  44. # include "wave.h"
  45. # define SAMPLE_DIVIDER 39
  46. # define SAMPLE_RATE (2000000.0 / SAMPLE_DIVIDER / 2048)
  47. // Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap
  48. float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  49. uint16_t place_int = 0;
  50. bool repeat = true;
  51. #endif
  52. void delay_us(int count) {
  53. while (count--) {
  54. _delay_us(1);
  55. }
  56. }
  57. int voices = 0;
  58. int voice_place = 0;
  59. float frequency = 0;
  60. int volume = 0;
  61. long position = 0;
  62. float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  63. int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  64. bool sliding = false;
  65. float place = 0;
  66. uint8_t* sample;
  67. uint16_t sample_length = 0;
  68. // float freq = 0;
  69. bool playing_notes = false;
  70. bool playing_note = false;
  71. float note_frequency = 0;
  72. float note_length = 0;
  73. uint8_t note_tempo = TEMPO_DEFAULT;
  74. float note_timbre = TIMBRE_DEFAULT;
  75. uint16_t note_position = 0;
  76. float (*notes_pointer)[][2];
  77. uint16_t notes_count;
  78. bool notes_repeat;
  79. float notes_rest;
  80. bool note_resting = false;
  81. uint16_t current_note = 0;
  82. uint8_t rest_counter = 0;
  83. #ifdef VIBRATO_ENABLE
  84. float vibrato_counter = 0;
  85. float vibrato_strength = .5;
  86. float vibrato_rate = 0.125;
  87. #endif
  88. float polyphony_rate = 0;
  89. static bool audio_initialized = false;
  90. audio_config_t audio_config;
  91. uint16_t envelope_index = 0;
  92. void audio_init() {
  93. // Check EEPROM
  94. if (!eeconfig_is_enabled()) {
  95. eeconfig_init();
  96. }
  97. audio_config.raw = eeconfig_read_audio();
  98. #ifdef PWM_AUDIO
  99. PLLFRQ = _BV(PDIV2);
  100. PLLCSR = _BV(PLLE);
  101. while (!(PLLCSR & _BV(PLOCK)))
  102. ;
  103. PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */
  104. /* Init a fast PWM on Timer4 */
  105. TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */
  106. TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */
  107. OCR4A = 0;
  108. /* Enable the OC4A output */
  109. DDRC |= _BV(PORTC6);
  110. DISABLE_AUDIO_COUNTER_3_ISR; // Turn off 3A interputs
  111. TCCR3A = 0x0; // Options not needed
  112. TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC
  113. OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback
  114. #else
  115. // Set port PC6 (OC3A and /OC4A) as output
  116. DDRC |= _BV(PORTC6);
  117. DISABLE_AUDIO_COUNTER_3_ISR;
  118. // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
  119. // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
  120. // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
  121. // Clock Select (CS3n) = 0b010 = Clock / 8
  122. TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
  123. TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
  124. #endif
  125. audio_initialized = true;
  126. }
  127. void audio_startup() {
  128. if (audio_config.enable) {
  129. PLAY_SONG(startup_song);
  130. }
  131. }
  132. void stop_all_notes() {
  133. if (!audio_initialized) {
  134. audio_init();
  135. }
  136. voices = 0;
  137. #ifdef PWM_AUDIO
  138. DISABLE_AUDIO_COUNTER_3_ISR;
  139. #else
  140. DISABLE_AUDIO_COUNTER_3_ISR;
  141. DISABLE_AUDIO_COUNTER_3_OUTPUT;
  142. #endif
  143. playing_notes = false;
  144. playing_note = false;
  145. frequency = 0;
  146. volume = 0;
  147. for (uint8_t i = 0; i < 8; i++) {
  148. frequencies[i] = 0;
  149. volumes[i] = 0;
  150. }
  151. }
  152. void stop_note(float freq) {
  153. if (playing_note) {
  154. if (!audio_initialized) {
  155. audio_init();
  156. }
  157. #ifdef PWM_AUDIO
  158. freq = freq / SAMPLE_RATE;
  159. #endif
  160. for (int i = 7; i >= 0; i--) {
  161. if (frequencies[i] == freq) {
  162. frequencies[i] = 0;
  163. volumes[i] = 0;
  164. for (int j = i; (j < 7); j++) {
  165. frequencies[j] = frequencies[j + 1];
  166. frequencies[j + 1] = 0;
  167. volumes[j] = volumes[j + 1];
  168. volumes[j + 1] = 0;
  169. }
  170. break;
  171. }
  172. }
  173. voices--;
  174. if (voices < 0) voices = 0;
  175. if (voice_place >= voices) {
  176. voice_place = 0;
  177. }
  178. if (voices == 0) {
  179. #ifdef PWM_AUDIO
  180. DISABLE_AUDIO_COUNTER_3_ISR;
  181. #else
  182. DISABLE_AUDIO_COUNTER_3_ISR;
  183. DISABLE_AUDIO_COUNTER_3_OUTPUT;
  184. #endif
  185. frequency = 0;
  186. volume = 0;
  187. playing_note = false;
  188. }
  189. }
  190. }
  191. #ifdef VIBRATO_ENABLE
  192. float mod(float a, int b) {
  193. float r = fmod(a, b);
  194. return r < 0 ? r + b : r;
  195. }
  196. float vibrato(float average_freq) {
  197. # ifdef VIBRATO_STRENGTH_ENABLE
  198. float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
  199. # else
  200. float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
  201. # endif
  202. vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0 / average_freq)), VIBRATO_LUT_LENGTH);
  203. return vibrated_freq;
  204. }
  205. #endif
  206. ISR(TIMER3_COMPA_vect) {
  207. if (playing_note) {
  208. #ifdef PWM_AUDIO
  209. if (voices == 1) {
  210. // SINE
  211. OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2;
  212. // SQUARE
  213. // if (((int)place) >= 1024){
  214. // OCR4A = 0xFF >> 2;
  215. // } else {
  216. // OCR4A = 0x00;
  217. // }
  218. // SAWTOOTH
  219. // OCR4A = (int)place / 4;
  220. // TRIANGLE
  221. // if (((int)place) >= 1024) {
  222. // OCR4A = (int)place / 2;
  223. // } else {
  224. // OCR4A = 2048 - (int)place / 2;
  225. // }
  226. place += frequency;
  227. if (place >= SINE_LENGTH) place -= SINE_LENGTH;
  228. } else {
  229. int sum = 0;
  230. for (int i = 0; i < voices; i++) {
  231. // SINE
  232. sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2;
  233. // SQUARE
  234. // if (((int)places[i]) >= 1024){
  235. // sum += 0xFF >> 2;
  236. // } else {
  237. // sum += 0x00;
  238. // }
  239. places[i] += frequencies[i];
  240. if (places[i] >= SINE_LENGTH) places[i] -= SINE_LENGTH;
  241. }
  242. OCR4A = sum;
  243. }
  244. #else
  245. if (voices > 0) {
  246. float freq;
  247. if (polyphony_rate > 0) {
  248. if (voices > 1) {
  249. voice_place %= voices;
  250. if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
  251. voice_place = (voice_place + 1) % voices;
  252. place = 0.0;
  253. }
  254. }
  255. # ifdef VIBRATO_ENABLE
  256. if (vibrato_strength > 0) {
  257. freq = vibrato(frequencies[voice_place]);
  258. } else {
  259. # else
  260. {
  261. # endif
  262. freq = frequencies[voice_place];
  263. }
  264. } else {
  265. if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440 / frequencies[voices - 1] / 12 / 2)) {
  266. frequency = frequency * pow(2, 440 / frequency / 12 / 2);
  267. } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440 / frequencies[voices - 1] / 12 / 2)) {
  268. frequency = frequency * pow(2, -440 / frequency / 12 / 2);
  269. } else {
  270. frequency = frequencies[voices - 1];
  271. }
  272. # ifdef VIBRATO_ENABLE
  273. if (vibrato_strength > 0) {
  274. freq = vibrato(frequency);
  275. } else {
  276. # else
  277. {
  278. # endif
  279. freq = frequency;
  280. }
  281. }
  282. if (envelope_index < 65535) {
  283. envelope_index++;
  284. }
  285. freq = voice_envelope(freq);
  286. if (freq < 30.517578125) freq = 30.52;
  287. NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
  288. NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
  289. }
  290. #endif
  291. }
  292. // SAMPLE
  293. // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]);
  294. // place_int++;
  295. // if (place_int >= sample_length)
  296. // if (repeat)
  297. // place_int -= sample_length;
  298. // else
  299. // DISABLE_AUDIO_COUNTER_3_ISR;
  300. if (playing_notes) {
  301. #ifdef PWM_AUDIO
  302. OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0;
  303. place += note_frequency;
  304. if (place >= SINE_LENGTH) place -= SINE_LENGTH;
  305. #else
  306. if (note_frequency > 0) {
  307. float freq;
  308. # ifdef VIBRATO_ENABLE
  309. if (vibrato_strength > 0) {
  310. freq = vibrato(note_frequency);
  311. } else {
  312. # else
  313. {
  314. # endif
  315. freq = note_frequency;
  316. }
  317. if (envelope_index < 65535) {
  318. envelope_index++;
  319. }
  320. freq = voice_envelope(freq);
  321. NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
  322. NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
  323. } else {
  324. NOTE_PERIOD = 0;
  325. NOTE_DUTY_CYCLE = 0;
  326. }
  327. #endif
  328. note_position++;
  329. bool end_of_note = false;
  330. if (NOTE_PERIOD > 0)
  331. end_of_note = (note_position >= (note_length / NOTE_PERIOD * 0xFFFF));
  332. else
  333. end_of_note = (note_position >= (note_length * 0x7FF));
  334. if (end_of_note) {
  335. current_note++;
  336. if (current_note >= notes_count) {
  337. if (notes_repeat) {
  338. current_note = 0;
  339. } else {
  340. #ifdef PWM_AUDIO
  341. DISABLE_AUDIO_COUNTER_3_ISR;
  342. #else
  343. DISABLE_AUDIO_COUNTER_3_ISR;
  344. DISABLE_AUDIO_COUNTER_3_OUTPUT;
  345. #endif
  346. playing_notes = false;
  347. return;
  348. }
  349. }
  350. if (!note_resting && (notes_rest > 0)) {
  351. note_resting = true;
  352. note_frequency = 0;
  353. note_length = notes_rest;
  354. current_note--;
  355. } else {
  356. note_resting = false;
  357. #ifdef PWM_AUDIO
  358. note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
  359. note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
  360. #else
  361. envelope_index = 0;
  362. note_frequency = (*notes_pointer)[current_note][0];
  363. note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
  364. #endif
  365. }
  366. note_position = 0;
  367. }
  368. }
  369. if (!audio_config.enable) {
  370. playing_notes = false;
  371. playing_note = false;
  372. }
  373. }
  374. void play_note(float freq, int vol) {
  375. if (!audio_initialized) {
  376. audio_init();
  377. }
  378. if (audio_config.enable && voices < 8) {
  379. DISABLE_AUDIO_COUNTER_3_ISR;
  380. // Cancel notes if notes are playing
  381. if (playing_notes) stop_all_notes();
  382. playing_note = true;
  383. envelope_index = 0;
  384. #ifdef PWM_AUDIO
  385. freq = freq / SAMPLE_RATE;
  386. #endif
  387. if (freq > 0) {
  388. frequencies[voices] = freq;
  389. volumes[voices] = vol;
  390. voices++;
  391. }
  392. #ifdef PWM_AUDIO
  393. ENABLE_AUDIO_COUNTER_3_ISR;
  394. #else
  395. ENABLE_AUDIO_COUNTER_3_ISR;
  396. ENABLE_AUDIO_COUNTER_3_OUTPUT;
  397. #endif
  398. }
  399. }
  400. void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) {
  401. if (!audio_initialized) {
  402. audio_init();
  403. }
  404. if (audio_config.enable) {
  405. DISABLE_AUDIO_COUNTER_3_ISR;
  406. // Cancel note if a note is playing
  407. if (playing_note) stop_all_notes();
  408. playing_notes = true;
  409. notes_pointer = np;
  410. notes_count = n_count;
  411. notes_repeat = n_repeat;
  412. notes_rest = n_rest;
  413. place = 0;
  414. current_note = 0;
  415. #ifdef PWM_AUDIO
  416. note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
  417. note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
  418. #else
  419. note_frequency = (*notes_pointer)[current_note][0];
  420. note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
  421. #endif
  422. note_position = 0;
  423. #ifdef PWM_AUDIO
  424. ENABLE_AUDIO_COUNTER_3_ISR;
  425. #else
  426. ENABLE_AUDIO_COUNTER_3_ISR;
  427. ENABLE_AUDIO_COUNTER_3_OUTPUT;
  428. #endif
  429. }
  430. }
  431. #ifdef PWM_AUDIO
  432. void play_sample(uint8_t* s, uint16_t l, bool r) {
  433. if (!audio_initialized) {
  434. audio_init();
  435. }
  436. if (audio_config.enable) {
  437. DISABLE_AUDIO_COUNTER_3_ISR;
  438. stop_all_notes();
  439. place_int = 0;
  440. sample = s;
  441. sample_length = l;
  442. repeat = r;
  443. ENABLE_AUDIO_COUNTER_3_ISR;
  444. }
  445. }
  446. #endif
  447. void audio_toggle(void) {
  448. audio_config.enable ^= 1;
  449. eeconfig_update_audio(audio_config.raw);
  450. }
  451. void audio_on(void) {
  452. audio_config.enable = 1;
  453. eeconfig_update_audio(audio_config.raw);
  454. }
  455. void audio_off(void) {
  456. audio_config.enable = 0;
  457. eeconfig_update_audio(audio_config.raw);
  458. }
  459. #ifdef VIBRATO_ENABLE
  460. // Vibrato rate functions
  461. void set_vibrato_rate(float rate) { vibrato_rate = rate; }
  462. void increase_vibrato_rate(float change) { vibrato_rate *= change; }
  463. void decrease_vibrato_rate(float change) { vibrato_rate /= change; }
  464. # ifdef VIBRATO_STRENGTH_ENABLE
  465. void set_vibrato_strength(float strength) { vibrato_strength = strength; }
  466. void increase_vibrato_strength(float change) { vibrato_strength *= change; }
  467. void decrease_vibrato_strength(float change) { vibrato_strength /= change; }
  468. # endif /* VIBRATO_STRENGTH_ENABLE */
  469. #endif /* VIBRATO_ENABLE */
  470. // Polyphony functions
  471. void set_polyphony_rate(float rate) { polyphony_rate = rate; }
  472. void enable_polyphony() { polyphony_rate = 5; }
  473. void disable_polyphony() { polyphony_rate = 0; }
  474. void increase_polyphony_rate(float change) { polyphony_rate *= change; }
  475. void decrease_polyphony_rate(float change) { polyphony_rate /= change; }
  476. // Timbre function
  477. void set_timbre(float timbre) { note_timbre = timbre; }
  478. // Tempo functions
  479. void set_tempo(uint8_t tempo) { note_tempo = tempo; }
  480. void decrease_tempo(uint8_t tempo_change) { note_tempo += tempo_change; }
  481. void increase_tempo(uint8_t tempo_change) {
  482. if (note_tempo - tempo_change < 10) {
  483. note_tempo = 10;
  484. } else {
  485. note_tempo -= tempo_change;
  486. }
  487. }
  488. //------------------------------------------------------------------------------
  489. // Override these functions in your keymap file to play different tunes on
  490. // startup and bootloader jump
  491. __attribute__((weak)) void play_startup_tone() {}
  492. __attribute__((weak)) void play_goodbye_tone() {}
  493. //------------------------------------------------------------------------------