diff options
author | Michael L. Walker <michael.l.walker@intel.com> | 2018-04-12 08:16:35 -0700 |
---|---|---|
committer | Jack Humbert <jack.humb@gmail.com> | 2018-04-12 13:14:48 -0400 |
commit | 22215a0e920a237faabdfa1b8826cd110ab20c3b (patch) | |
tree | 4681e0cb65cbc69f3bed16165de620dc6511d653 /quantum/audio | |
parent | 5319667c5504ab28b5bdb6f81ae22ecfec5e4a46 (diff) | |
download | qmk_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.c | 188 |
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 |
299 | ISR(TIMER3_COMPA_vect) | 339 | ISR(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 |
481 | ISR(TIMER1_COMPA_vect) | 521 | ISR(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 |