arduino-audio-tools
Loading...
Searching...
No Matches
PWMDriverAVR.h
1
2#pragma once
3#include "AudioToolsConfig.h"
4#if defined(USE_PWM) && defined(__AVR__)
5#include "AudioTools/CoreAudio/AudioPWM/PWMDriverBase.h"
6#include "AudioTools/CoreAudio/AudioTimer/AudioTimerAVR.h"
7
8namespace audio_tools {
9
10class PWMDriverAVR;
14static PWMDriverAVR *accessAudioPWM = nullptr;
15
26
27 public:
28 PWMDriverAVR() {
29 accessAudioPWM = this;
30 }
31
32 virtual int maxChannels() { return 2; };
33
34 // Ends the output
35 virtual void end() {
36 TRACED();
37 noInterrupts();
38 // stop timer callback
39 TCCR1B = 0;
40 // stop pwm timers
41 TCCR2A = 0;
42 interrupts(); // enable all interrupts
43
44 is_timer_started = false;
45 deleteBuffer();
46 }
47
48 void setupTimer() {
49 TRACED();
50 // CPU Frequency 16 MHz
51 // prescaler 1, 256 or 1024 => no prescaling
52 uint32_t steps =
53 F_CPU / 8 / audio_config.sample_rate; // e.g. (16000000/8/44100=>45)
54 if (steps > 65535) {
55 LOGE("requested sample rate not supported: %d - we use %d",
56 audio_config.sample_rate, F_CPU / 65536);
57 steps = 65535;
58 } else {
59 LOGD("compare match register set to %d", steps);
60 }
61
62 // setup timer intterupt
63 noInterrupts();
64 TCCR1B = 0;
65 // compare match register
66 OCR1A = steps;
67 TCCR1B |= (1 << WGM12); // CTC mode
68 // TCCR1B |= (1 << CS10); // prescaler 1
69 TCCR1B |= (1 << CS11); // prescaler 8
70 TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
71 interrupts(); // enable all interrupts
72 }
73
75 void setupPWM() {
76 TRACED();
77 audio_config.pwm_frequency = 62500;
78
79 if (audio_config.channels > 2) {
80 LOGW("Max 2 channels supported - you requested %d",
81 audio_config.channels);
82 audio_config.channels = 2;
83 }
84
85 for (int j = 0; j < audio_config.channels; j++) {
86 LOGD("Processing channel %d", j);
87 setupPin(pins[j]);
88 }
89 }
90
91 void startTimer() {}
92
93 // Timer 0 is used by Arduino!
94 // Timer 1 is used to drive output in sample_rate
95 // => only Timer2 is available for PWM
96 void setupPin(int pin) {
97 switch (pin) {
98 case 3:
99 case 11:
100 // switch PWM frequency to 62500.00 Hz
101 TCCR2B = TCCR2B & B11111000 | B00000001;
102 LOGI("PWM Frequency changed for D3 and D11");
103 break;
104
105 default:
106 LOGE("PWM Unsupported pin: %d", pin);
107 break;
108 }
109 pinMode(pin, OUTPUT);
110 }
111
112 virtual void pwmWrite(int channel, int value) {
113 analogWrite(pins[channel], value);
114 }
115
116 void logConfig() {
117 audio_config.logConfig();
118 LOGI("pwm freq: %f khz", 62.5);
119 if (audio_config.channels == 1) {
120 LOGI("output pin: %d", pins[0]);
121 } else {
122 LOGI("output pins: %d / %d", pins[0], pins[1]);
123 }
124 }
125
126 protected:
127 int pins[2] = {3, 11};
128
129 virtual int maxOutputValue() { return 255; }
130};
131
135 if (accessAudioPWM != nullptr && accessAudioPWM->is_timer_started) {
136 accessAudioPWM->playNextFrame();
137 }
138}
139
141ISR(TIMER1_COMPA_vect) {
143 TimerAlarmRepeatingDriverAVR::tickerCallback();
144}
145
146} // namespace audio_tools
147
148#endif
Base Class for all PWM drivers.
Definition PWMDriverBase.h:114
void playNextFrame()
writes the next frame to the output pins
Definition PWMDriverBase.h:274
Experimental: Audio output to PWM pins for the AVR. The AVR supports only up to 2 channels.
Definition PWMDriverAVR.h:24
void setupPWM()
Setup LED PWM.
Definition PWMDriverAVR.h:75
friend void defaultPWMAudioOutputCallback()
Definition PWMDriverAVR.h:134
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
void defaultPWMAudioOutputCallback()
Definition PWMDriverAVR.h:134
ISR(TIMER1_COMPA_vect)
timer callback: write the next frame to the pins
Definition PWMDriverAVR.h:141
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint32_t pwm_frequency
additinal info which might not be used by all processors
Definition PWMDriverBase.h:46