]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/audio/audio_pwm.c
Convert keymap to compact version
[qmk_firmware.git] / quantum / audio / audio_pwm.c
1 #include <stdio.h>
2 #include <string.h>
3 //#include <math.h>
4 #include <avr/pgmspace.h>
5 #include <avr/interrupt.h>
6 #include <avr/io.h>
7 #include "print.h"
8 #include "audio.h"
9 #include "keymap.h"
10
11 #include "eeconfig.h"
12
13 #define PI 3.14159265
14
15 #define CPU_PRESCALER 8
16
17
18 // Timer Abstractions
19
20 // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
21 // Turn on/off 3A interputs, stopping/enabling the ISR calls
22 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
23 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
24
25
26 // TCCR3A: Timer/Counter #3 Control Register
27 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
28 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
29 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
30
31
32 #define NOTE_PERIOD ICR3
33 #define NOTE_DUTY_CYCLE OCR3A
34
35
36 #ifdef PWM_AUDIO
37     #include "wave.h"
38     #define SAMPLE_DIVIDER 39
39     #define SAMPLE_RATE (2000000.0/SAMPLE_DIVIDER/2048)
40     // Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap
41
42     float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43     uint16_t place_int = 0;
44     bool repeat = true;
45 #endif
46
47 void delay_us(int count) {
48   while(count--) {
49     _delay_us(1);
50   }
51 }
52
53 int voices = 0;
54 int voice_place = 0;
55 float frequency = 0;
56 int volume = 0;
57 long position = 0;
58
59 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
60 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
61 bool sliding = false;
62
63 float place = 0;
64
65 uint8_t * sample;
66 uint16_t sample_length = 0;
67 // float freq = 0;
68
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
82 uint8_t current_note = 0;
83 uint8_t rest_counter = 0;
84
85 #ifdef VIBRATO_ENABLE
86 float vibrato_counter = 0;
87 float vibrato_strength = .5;
88 float vibrato_rate = 0.125;
89 #endif
90
91 float polyphony_rate = 0;
92
93 static bool audio_initialized = false;
94
95 audio_config_t audio_config;
96
97 uint16_t envelope_index = 0;
98
99 void audio_init() {
100
101     // Check EEPROM
102     if (!eeconfig_is_enabled())
103     {
104         eeconfig_init();
105     }
106     audio_config.raw = eeconfig_read_audio();
107
108     #ifdef PWM_AUDIO
109
110         PLLFRQ = _BV(PDIV2);
111         PLLCSR = _BV(PLLE);
112         while(!(PLLCSR & _BV(PLOCK)));
113         PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */
114
115         /* Init a fast PWM on Timer4 */
116         TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */
117         TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */
118         OCR4A = 0;
119
120         /* Enable the OC4A output */
121         DDRC |= _BV(PORTC6);
122
123         DISABLE_AUDIO_COUNTER_3_ISR; // Turn off 3A interputs
124
125         TCCR3A = 0x0; // Options not needed
126         TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC
127         OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback
128
129     #else
130
131         // Set port PC6 (OC3A and /OC4A) as output
132         DDRC |= _BV(PORTC6);
133
134         DISABLE_AUDIO_COUNTER_3_ISR;
135
136                 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
137                 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
138                 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
139                 // Clock Select (CS3n) = 0b010 = Clock / 8
140         TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
141         TCCR3B = (1 << WGM33)  | (1 << WGM32)  | (0 << CS32)  | (1 << CS31) | (0 << CS30);
142
143     #endif
144
145     audio_initialized = true;
146 }
147
148 void stop_all_notes() {
149     if (!audio_initialized) {
150         audio_init();
151     }
152     voices = 0;
153     #ifdef PWM_AUDIO
154             DISABLE_AUDIO_COUNTER_3_ISR;
155     #else
156         DISABLE_AUDIO_COUNTER_3_ISR;
157         DISABLE_AUDIO_COUNTER_3_OUTPUT;
158     #endif
159
160     playing_notes = false;
161     playing_note = false;
162     frequency = 0;
163     volume = 0;
164
165     for (uint8_t i = 0; i < 8; i++)
166     {
167         frequencies[i] = 0;
168         volumes[i] = 0;
169     }
170 }
171
172 void stop_note(float freq)
173 {
174     if (playing_note) {
175         if (!audio_initialized) {
176             audio_init();
177         }
178         #ifdef PWM_AUDIO
179             freq = freq / SAMPLE_RATE;
180         #endif
181         for (int i = 7; i >= 0; i--) {
182             if (frequencies[i] == freq) {
183                 frequencies[i] = 0;
184                 volumes[i] = 0;
185                 for (int j = i; (j < 7); j++) {
186                     frequencies[j] = frequencies[j+1];
187                     frequencies[j+1] = 0;
188                     volumes[j] = volumes[j+1];
189                     volumes[j+1] = 0;
190                 }
191                 break;
192             }
193         }
194         voices--;
195         if (voices < 0)
196             voices = 0;
197         if (voice_place >= voices) {
198             voice_place = 0;
199         }
200         if (voices == 0) {
201             #ifdef PWM_AUDIO
202                 DISABLE_AUDIO_COUNTER_3_ISR;
203             #else
204                 DISABLE_AUDIO_COUNTER_3_ISR;
205                 DISABLE_AUDIO_COUNTER_3_OUTPUT;
206             #endif
207             frequency = 0;
208             volume = 0;
209             playing_note = false;
210         }
211     }
212 }
213
214 #ifdef VIBRATO_ENABLE
215
216 float mod(float a, int b)
217 {
218     float r = fmod(a, b);
219     return r < 0 ? r + b : r;
220 }
221
222 float vibrato(float average_freq) {
223     #ifdef VIBRATO_STRENGTH_ENABLE
224         float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
225     #else
226         float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
227     #endif
228     vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
229     return vibrated_freq;
230 }
231
232 #endif
233
234 ISR(TIMER3_COMPA_vect)
235 {
236     if (playing_note) {
237         #ifdef PWM_AUDIO
238             if (voices == 1) {
239                 // SINE
240                 OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2;
241
242                 // SQUARE
243                 // if (((int)place) >= 1024){
244                 //     OCR4A = 0xFF >> 2;
245                 // } else {
246                 //     OCR4A = 0x00;
247                 // }
248
249                 // SAWTOOTH
250                 // OCR4A = (int)place / 4;
251
252                 // TRIANGLE
253                 // if (((int)place) >= 1024) {
254                 //     OCR4A = (int)place / 2;
255                 // } else {
256                 //     OCR4A = 2048 - (int)place / 2;
257                 // }
258
259                 place += frequency;
260
261                 if (place >= SINE_LENGTH)
262                     place -= SINE_LENGTH;
263
264             } else {
265                 int sum = 0;
266                 for (int i = 0; i < voices; i++) {
267                     // SINE
268                     sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2;
269
270                     // SQUARE
271                     // if (((int)places[i]) >= 1024){
272                     //     sum += 0xFF >> 2;
273                     // } else {
274                     //     sum += 0x00;
275                     // }
276
277                     places[i] += frequencies[i];
278
279                     if (places[i] >= SINE_LENGTH)
280                         places[i] -= SINE_LENGTH;
281                 }
282                 OCR4A = sum;
283             }
284         #else
285             if (voices > 0) {
286                 float freq;
287                 if (polyphony_rate > 0) {
288                     if (voices > 1) {
289                         voice_place %= voices;
290                         if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
291                             voice_place = (voice_place + 1) % voices;
292                             place = 0.0;
293                         }
294                     }
295                     #ifdef VIBRATO_ENABLE
296                     if (vibrato_strength > 0) {
297                         freq = vibrato(frequencies[voice_place]);
298                     } else {
299                     #else
300                     {
301                     #endif
302                         freq = frequencies[voice_place];
303                     }
304                 } else {
305                     if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
306                         frequency = frequency * pow(2, 440/frequency/12/2);
307                     } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
308                         frequency = frequency * pow(2, -440/frequency/12/2);
309                     } else {
310                         frequency = frequencies[voices - 1];
311                     }
312
313
314                     #ifdef VIBRATO_ENABLE
315                     if (vibrato_strength > 0) {
316                         freq = vibrato(frequency);
317                     } else {
318                     #else
319                     {
320                     #endif
321                         freq = frequency;
322                     }
323                 }
324
325                 if (envelope_index < 65535) {
326                     envelope_index++;
327                 }
328                 freq = voice_envelope(freq);
329
330                 if (freq < 30.517578125)
331                     freq = 30.52;
332                 NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
333                 NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
334             }
335         #endif
336     }
337
338     // SAMPLE
339     // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]);
340
341     // place_int++;
342
343     // if (place_int >= sample_length)
344     //     if (repeat)
345     //         place_int -= sample_length;
346     //     else
347     //         DISABLE_AUDIO_COUNTER_3_ISR;
348
349
350     if (playing_notes) {
351         #ifdef PWM_AUDIO
352             OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0;
353
354             place += note_frequency;
355             if (place >= SINE_LENGTH)
356                 place -= SINE_LENGTH;
357         #else
358             if (note_frequency > 0) {
359                 float freq;
360
361                 #ifdef VIBRATO_ENABLE
362                 if (vibrato_strength > 0) {
363                     freq = vibrato(note_frequency);
364                 } else {
365                 #else
366                 {
367                 #endif
368                     freq = note_frequency;
369                 }
370
371                 if (envelope_index < 65535) {
372                     envelope_index++;
373                 }
374                 freq = voice_envelope(freq);
375
376                 NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
377                 NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
378             } else {
379                 NOTE_PERIOD = 0;
380                 NOTE_DUTY_CYCLE = 0;
381             }
382         #endif
383
384
385         note_position++;
386         bool end_of_note = false;
387         if (NOTE_PERIOD > 0)
388             end_of_note = (note_position >= (note_length / NOTE_PERIOD * 0xFFFF));
389         else
390             end_of_note = (note_position >= (note_length * 0x7FF));
391         if (end_of_note) {
392             current_note++;
393             if (current_note >= notes_count) {
394                 if (notes_repeat) {
395                     current_note = 0;
396                 } else {
397                     #ifdef PWM_AUDIO
398                         DISABLE_AUDIO_COUNTER_3_ISR;
399                     #else
400                         DISABLE_AUDIO_COUNTER_3_ISR;
401                         DISABLE_AUDIO_COUNTER_3_OUTPUT;
402                     #endif
403                     playing_notes = false;
404                     return;
405                 }
406             }
407             if (!note_resting && (notes_rest > 0)) {
408                 note_resting = true;
409                 note_frequency = 0;
410                 note_length = notes_rest;
411                 current_note--;
412             } else {
413                 note_resting = false;
414                 #ifdef PWM_AUDIO
415                     note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
416                     note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
417                 #else
418                     envelope_index = 0;
419                     note_frequency = (*notes_pointer)[current_note][0];
420                     note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
421                 #endif
422             }
423             note_position = 0;
424         }
425
426     }
427
428     if (!audio_config.enable) {
429         playing_notes = false;
430         playing_note = false;
431     }
432 }
433
434 void play_note(float freq, int vol) {
435
436     if (!audio_initialized) {
437         audio_init();
438     }
439
440         if (audio_config.enable && voices < 8) {
441             DISABLE_AUDIO_COUNTER_3_ISR;
442
443             // Cancel notes if notes are playing
444             if (playing_notes)
445                 stop_all_notes();
446
447             playing_note = true;
448
449             envelope_index = 0;
450
451             #ifdef PWM_AUDIO
452                 freq = freq / SAMPLE_RATE;
453             #endif
454             if (freq > 0) {
455                 frequencies[voices] = freq;
456                 volumes[voices] = vol;
457                 voices++;
458             }
459
460             #ifdef PWM_AUDIO
461                 ENABLE_AUDIO_COUNTER_3_ISR;
462             #else
463                 ENABLE_AUDIO_COUNTER_3_ISR;
464                 ENABLE_AUDIO_COUNTER_3_OUTPUT;
465             #endif
466         }
467
468 }
469
470 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
471 {
472
473     if (!audio_initialized) {
474         audio_init();
475     }
476
477         if (audio_config.enable) {
478
479             DISABLE_AUDIO_COUNTER_3_ISR;
480
481                 // Cancel note if a note is playing
482             if (playing_note)
483                 stop_all_notes();
484
485             playing_notes = true;
486
487             notes_pointer = np;
488             notes_count = n_count;
489             notes_repeat = n_repeat;
490             notes_rest = n_rest;
491
492             place = 0;
493             current_note = 0;
494
495             #ifdef PWM_AUDIO
496                 note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
497                 note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
498             #else
499                 note_frequency = (*notes_pointer)[current_note][0];
500                 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
501             #endif
502             note_position = 0;
503
504
505             #ifdef PWM_AUDIO
506                 ENABLE_AUDIO_COUNTER_3_ISR;
507             #else
508                 ENABLE_AUDIO_COUNTER_3_ISR;
509                 ENABLE_AUDIO_COUNTER_3_OUTPUT;
510             #endif
511         }
512
513 }
514
515 #ifdef PWM_AUDIO
516 void play_sample(uint8_t * s, uint16_t l, bool r) {
517     if (!audio_initialized) {
518         audio_init();
519     }
520
521     if (audio_config.enable) {
522         DISABLE_AUDIO_COUNTER_3_ISR;
523         stop_all_notes();
524         place_int = 0;
525         sample = s;
526         sample_length = l;
527         repeat = r;
528
529         ENABLE_AUDIO_COUNTER_3_ISR;
530     }
531 }
532 #endif
533
534
535 void audio_toggle(void) {
536     audio_config.enable ^= 1;
537     eeconfig_update_audio(audio_config.raw);
538 }
539
540 void audio_on(void) {
541     audio_config.enable = 1;
542     eeconfig_update_audio(audio_config.raw);
543 }
544
545 void audio_off(void) {
546     audio_config.enable = 0;
547     eeconfig_update_audio(audio_config.raw);
548 }
549
550 #ifdef VIBRATO_ENABLE
551
552 // Vibrato rate functions
553
554 void set_vibrato_rate(float rate) {
555     vibrato_rate = rate;
556 }
557
558 void increase_vibrato_rate(float change) {
559     vibrato_rate *= change;
560 }
561
562 void decrease_vibrato_rate(float change) {
563     vibrato_rate /= change;
564 }
565
566 #ifdef VIBRATO_STRENGTH_ENABLE
567
568 void set_vibrato_strength(float strength) {
569     vibrato_strength = strength;
570 }
571
572 void increase_vibrato_strength(float change) {
573     vibrato_strength *= change;
574 }
575
576 void decrease_vibrato_strength(float change) {
577     vibrato_strength /= change;
578 }
579
580 #endif  /* VIBRATO_STRENGTH_ENABLE */
581
582 #endif /* VIBRATO_ENABLE */
583
584 // Polyphony functions
585
586 void set_polyphony_rate(float rate) {
587     polyphony_rate = rate;
588 }
589
590 void enable_polyphony() {
591     polyphony_rate = 5;
592 }
593
594 void disable_polyphony() {
595     polyphony_rate = 0;
596 }
597
598 void increase_polyphony_rate(float change) {
599     polyphony_rate *= change;
600 }
601
602 void decrease_polyphony_rate(float change) {
603     polyphony_rate /= change;
604 }
605
606 // Timbre function
607
608 void set_timbre(float timbre) {
609     note_timbre = timbre;
610 }
611
612 // Tempo functions
613
614 void set_tempo(uint8_t tempo) {
615     note_tempo = tempo;
616 }
617
618 void decrease_tempo(uint8_t tempo_change) {
619     note_tempo += tempo_change;
620 }
621
622 void increase_tempo(uint8_t tempo_change) {
623     if (note_tempo - tempo_change < 10) {
624         note_tempo = 10;
625     } else {
626         note_tempo -= tempo_change;
627     }
628 }
629
630
631 //------------------------------------------------------------------------------
632 // Override these functions in your keymap file to play different tunes on
633 // startup and bootloader jump
634 __attribute__ ((weak))
635 void play_startup_tone()
636 {
637 }
638
639 __attribute__ ((weak))
640 void play_goodbye_tone()
641 {
642 }
643 //------------------------------------------------------------------------------