aboutsummaryrefslogtreecommitdiff
path: root/quantum/audio
diff options
context:
space:
mode:
authorMichael L. Walker <michael.l.walker@intel.com>2018-04-12 08:16:35 -0700
committerJack Humbert <jack.humb@gmail.com>2018-04-12 13:14:48 -0400
commit22215a0e920a237faabdfa1b8826cd110ab20c3b (patch)
tree4681e0cb65cbc69f3bed16165de620dc6511d653 /quantum/audio
parent5319667c5504ab28b5bdb6f81ae22ecfec5e4a46 (diff)
downloadqmk_firmware-22215a0e920a237faabdfa1b8826cd110ab20c3b.tar.gz
qmk_firmware-22215a0e920a237faabdfa1b8826cd110ab20c3b.zip
Added support for audio using pins C4, C5, B6, B7
Diffstat (limited to 'quantum/audio')
-rw-r--r--quantum/audio/audio.c188
1 files changed, 114 insertions, 74 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index 85220e163..3c6d18c4f 100644
--- a/quantum/audio/audio.c
+++ b/quantum/audio/audio.c
@@ -35,44 +35,81 @@
35// Timer Abstractions 35// Timer Abstractions
36// ----------------------------------------------------------------------------- 36// -----------------------------------------------------------------------------
37 37
38// TIMSK3 - Timer/Counter #3 Interrupt Mask Register 38//Currently we support timers 1 and 3 used at the sime time, channels A-C,
39// Turn on/off 3A interputs, stopping/enabling the ISR calls 39//pins PB5, PB6, PB7, PC4, PC5, and PC6
40#ifdef C6_AUDIO 40#if defined(C6_AUDIO)
41 #define CPIN_AUDIO
42 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC6);
43 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
41 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A) 44 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
42 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A) 45 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
43#endif
44
45#ifdef B5_AUDIO
46 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
47 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
48#endif
49
50// TCCR3A: Timer/Counter #3 Control Register
51// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
52
53#ifdef C6_AUDIO
54 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1); 46 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
55 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0)); 47 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
48 #define TIMER_3_PERIOD ICR3
49 #define TIMER_3_DUTY_CYCLE OCR3A
50 #define TIMER3_AUDIO_vect TIMER3_COMPA_vect
56#endif 51#endif
57 52#if defined(C5_AUDIO)
58#ifdef B5_AUDIO 53 #define CPIN_AUDIO
59 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1); 54 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC5);
60 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0)); 55 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3B1) | (0 << COM3B0) | (1 << WGM31) | (0 << WGM30);
56 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3B)
57 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3B)
58 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3B1);
59 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3B1) | _BV(COM3B0));
60 #define TIMER_3_PERIOD ICR3
61 #define TIMER_3_DUTY_CYCLE OCR3B
62 #define TIMER3_AUDIO_vect TIMER3_COMPB_vect
61#endif 63#endif
62 64#if defined(C4_AUDIO)
63// Fast PWM Mode Controls 65 #define CPIN_AUDIO
64 66 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC4);
65#ifdef C6_AUDIO 67 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3C1) | (0 << COM3C0) | (1 << WGM31) | (0 << WGM30);
68 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3C)
69 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3C)
70 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3C1);
71 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3C1) | _BV(COM3C0));
66 #define TIMER_3_PERIOD ICR3 72 #define TIMER_3_PERIOD ICR3
67 #define TIMER_3_DUTY_CYCLE OCR3A 73 #define TIMER_3_DUTY_CYCLE OCR3C
74 #define TIMER3_AUDIO_vect TIMER3_COMPC_vect
68#endif 75#endif
69 76
70#ifdef B5_AUDIO 77#if defined(B5_AUDIO)
78 #define BPIN_AUDIO
79 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB5);
80 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
81 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
82 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
83 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
84 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
71 #define TIMER_1_PERIOD ICR1 85 #define TIMER_1_PERIOD ICR1
72 #define TIMER_1_DUTY_CYCLE OCR1A 86 #define TIMER_1_DUTY_CYCLE OCR1A
87 #define TIMER1_AUDIO_vect TIMER1_COMPA_vect
88#endif
89#if defined(B6_AUDIO)
90 #define BPIN_AUDIO
91 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB6);
92 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
93 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1B)
94 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1B)
95 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1B1);
96 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1B1) | _BV(COM1B0));
97 #define TIMER_1_PERIOD ICR1
98 #define TIMER_1_DUTY_CYCLE OCR1B
99 #define TIMER1_AUDIO_vect TIMER1_COMPB_vect
100#endif
101#if defined(B7_AUDIO)
102 #define BPIN_AUDIO
103 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB7);
104 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1C1) | (0 << COM1C0) | (1 << WGM11) | (0 << WGM10);
105 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1C)
106 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1C)
107 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1C1);
108 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1C1) | _BV(COM1C0));
109 #define TIMER_1_PERIOD ICR1
110 #define TIMER_1_DUTY_CYCLE OCR1C
111 #define TIMER1_AUDIO_vect TIMER1_COMPC_vect
73#endif 112#endif
74
75
76// ----------------------------------------------------------------------------- 113// -----------------------------------------------------------------------------
77 114
78 115
@@ -147,47 +184,51 @@ void audio_init()
147 184
148 if (!audio_initialized) { 185 if (!audio_initialized) {
149 186
150 // Set port PC6 (OC3A and /OC4A) as output 187 // Set audio ports as output
151 188 #ifdef CPIN_AUDIO
152 #ifdef C6_AUDIO 189 CPIN_SET_DIRECTION
153 DDRC |= _BV(PORTC6);
154 //#else
155 // DDRC |= _BV(PORTC6); // Why is PC6 being set as output low, if C6_audio isn't defined?
156 // PORTC &= ~_BV(PORTC6);
157 #endif 190 #endif
158 191 #ifdef BPIN_AUDIO
159 #ifdef B5_AUDIO 192 BPIN_SET_DIRECTION
160 DDRB |= _BV(PORTB5);
161 //#else
162 // DDRB |= _BV(PORTB5); // Same as with PC6
163 // PORTB &= ~_BV(PORTB5);
164 #endif 193 #endif
165 194
166 #ifdef C6_AUDIO 195 #ifdef CPIN_AUDIO
167 DISABLE_AUDIO_COUNTER_3_ISR; 196 DISABLE_AUDIO_COUNTER_3_ISR;
168 #endif 197 #endif
169 198 #ifdef BPIN_AUDIO
170 #ifdef B5_AUDIO
171 DISABLE_AUDIO_COUNTER_1_ISR; 199 DISABLE_AUDIO_COUNTER_1_ISR;
172 #endif 200 #endif
173 201
174 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers 202 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
175 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 203 // Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation
176 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) 204 // OC3A -- PC6
177 // Clock Select (CS3n) = 0b010 = Clock / 8 205 // OC3B -- PC5
206 // OC3C -- PC4
207 // OC1A -- PB5
208 // OC1B -- PB6
209 // OC1C -- PB7
210
211 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A)
212 // OCR3A - PC6
213 // OCR3B - PC5
214 // OCR3C - PC4
215 // OCR1A - PB5
216 // OCR1B - PB6
217 // OCR1C - PB7
178 218
179 #ifdef C6_AUDIO 219 // Clock Select (CS3n) = 0b010 = Clock / 8
180 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); 220 #ifdef CPIN_AUDIO
221 INIT_AUDIO_COUNTER_3
181 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); 222 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
223 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
224 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
182 #endif 225 #endif
183 226 #ifdef BPIN_AUDIO
184 #ifdef B5_AUDIO 227 INIT_AUDIO_COUNTER_1
185 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
186 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10); 228 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
187
188 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER)); 229 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
189 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre); 230 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
190 #endif 231 #endif
191 232
192 audio_initialized = true; 233 audio_initialized = true;
193 } 234 }
@@ -207,13 +248,12 @@ void stop_all_notes()
207 } 248 }
208 voices = 0; 249 voices = 0;
209 250
210 251 #ifdef CPIN_AUDIO
211 #ifdef C6_AUDIO
212 DISABLE_AUDIO_COUNTER_3_ISR; 252 DISABLE_AUDIO_COUNTER_3_ISR;
213 DISABLE_AUDIO_COUNTER_3_OUTPUT; 253 DISABLE_AUDIO_COUNTER_3_OUTPUT;
214 #endif 254 #endif
215 255
216 #ifdef B5_AUDIO 256 #ifdef BPIN_AUDIO
217 DISABLE_AUDIO_COUNTER_1_ISR; 257 DISABLE_AUDIO_COUNTER_1_ISR;
218 DISABLE_AUDIO_COUNTER_1_OUTPUT; 258 DISABLE_AUDIO_COUNTER_1_OUTPUT;
219 #endif 259 #endif
@@ -259,11 +299,11 @@ void stop_note(float freq)
259 voice_place = 0; 299 voice_place = 0;
260 } 300 }
261 if (voices == 0) { 301 if (voices == 0) {
262 #ifdef C6_AUDIO 302 #ifdef CPIN_AUDIO
263 DISABLE_AUDIO_COUNTER_3_ISR; 303 DISABLE_AUDIO_COUNTER_3_ISR;
264 DISABLE_AUDIO_COUNTER_3_OUTPUT; 304 DISABLE_AUDIO_COUNTER_3_OUTPUT;
265 #endif 305 #endif
266 #ifdef B5_AUDIO 306 #ifdef BPIN_AUDIO
267 DISABLE_AUDIO_COUNTER_1_ISR; 307 DISABLE_AUDIO_COUNTER_1_ISR;
268 DISABLE_AUDIO_COUNTER_1_OUTPUT; 308 DISABLE_AUDIO_COUNTER_1_OUTPUT;
269 #endif 309 #endif
@@ -295,15 +335,15 @@ float vibrato(float average_freq) {
295 335
296#endif 336#endif
297 337
298#ifdef C6_AUDIO 338#ifdef CPIN_AUDIO
299ISR(TIMER3_COMPA_vect) 339ISR(TIMER3_AUDIO_vect)
300{ 340{
301 float freq; 341 float freq;
302 342
303 if (playing_note) { 343 if (playing_note) {
304 if (voices > 0) { 344 if (voices > 0) {
305 345
306 #ifdef B5_AUDIO 346 #ifdef BPIN_AUDIO
307 float freq_alt = 0; 347 float freq_alt = 0;
308 if (voices > 1) { 348 if (voices > 1) {
309 if (polyphony_rate == 0) { 349 if (polyphony_rate == 0) {
@@ -477,10 +517,10 @@ ISR(TIMER3_COMPA_vect)
477} 517}
478#endif 518#endif
479 519
480#ifdef B5_AUDIO 520#ifdef BPIN_AUDIO
481ISR(TIMER1_COMPA_vect) 521ISR(TIMER1_AUDIO_vect)
482{ 522{
483 #if defined(B5_AUDIO) && !defined(C6_AUDIO) 523 #if defined(BPIN_AUDIO) && !defined(CPIN_AUDIO)
484 float freq = 0; 524 float freq = 0;
485 525
486 if (playing_note) { 526 if (playing_note) {
@@ -627,10 +667,10 @@ void play_note(float freq, int vol) {
627 } 667 }
628 668
629 if (audio_config.enable && voices < 8) { 669 if (audio_config.enable && voices < 8) {
630 #ifdef C6_AUDIO 670 #ifdef CPIN_AUDIO
631 DISABLE_AUDIO_COUNTER_3_ISR; 671 DISABLE_AUDIO_COUNTER_3_ISR;
632 #endif 672 #endif
633 #ifdef B5_AUDIO 673 #ifdef BPIN_AUDIO
634 DISABLE_AUDIO_COUNTER_1_ISR; 674 DISABLE_AUDIO_COUNTER_1_ISR;
635 #endif 675 #endif
636 676
@@ -648,12 +688,12 @@ void play_note(float freq, int vol) {
648 voices++; 688 voices++;
649 } 689 }
650 690
651 #ifdef C6_AUDIO 691 #ifdef CPIN_AUDIO
652 ENABLE_AUDIO_COUNTER_3_ISR; 692 ENABLE_AUDIO_COUNTER_3_ISR;
653 ENABLE_AUDIO_COUNTER_3_OUTPUT; 693 ENABLE_AUDIO_COUNTER_3_OUTPUT;
654 #endif 694 #endif
655 #ifdef B5_AUDIO 695 #ifdef BPIN_AUDIO
656 #ifdef C6_AUDIO 696 #ifdef CPIN_AUDIO
657 if (voices > 1) { 697 if (voices > 1) {
658 ENABLE_AUDIO_COUNTER_1_ISR; 698 ENABLE_AUDIO_COUNTER_1_ISR;
659 ENABLE_AUDIO_COUNTER_1_OUTPUT; 699 ENABLE_AUDIO_COUNTER_1_OUTPUT;
@@ -676,10 +716,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
676 716
677 if (audio_config.enable) { 717 if (audio_config.enable) {
678 718
679 #ifdef C6_AUDIO 719 #ifdef CPIN_AUDIO
680 DISABLE_AUDIO_COUNTER_3_ISR; 720 DISABLE_AUDIO_COUNTER_3_ISR;
681 #endif 721 #endif
682 #ifdef B5_AUDIO 722 #ifdef BPIN_AUDIO
683 DISABLE_AUDIO_COUNTER_1_ISR; 723 DISABLE_AUDIO_COUNTER_1_ISR;
684 #endif 724 #endif
685 725
@@ -701,12 +741,12 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
701 note_position = 0; 741 note_position = 0;
702 742
703 743
704 #ifdef C6_AUDIO 744 #ifdef CPIN_AUDIO
705 ENABLE_AUDIO_COUNTER_3_ISR; 745 ENABLE_AUDIO_COUNTER_3_ISR;
706 ENABLE_AUDIO_COUNTER_3_OUTPUT; 746 ENABLE_AUDIO_COUNTER_3_OUTPUT;
707 #endif 747 #endif
708 #ifdef B5_AUDIO 748 #ifdef BPIN_AUDIO
709 #ifndef C6_AUDIO 749 #ifndef CPIN_AUDIO
710 ENABLE_AUDIO_COUNTER_1_ISR; 750 ENABLE_AUDIO_COUNTER_1_ISR;
711 ENABLE_AUDIO_COUNTER_1_OUTPUT; 751 ENABLE_AUDIO_COUNTER_1_OUTPUT;
712 #endif 752 #endif