2#if defined(ARDUINO_ARCH_TANGNANO20K)
5#if TANGNANO20K_PWM_AUDIO
21class PWMDriverTangNanoTimer :
public PWMDriverBase {
23 PWMDriverTangNanoTimer() {
LOGD(
"PWMDriverTangNanoTimer"); }
26 virtual void end()
override {
29 is_timer_started =
false;
30 for (
int j = 0; j < pins.size(); j++) {
43 virtual void startTimer()
override {
45 if (!is_timer_started) {
46 ticker.setCallbackParameter(
this);
47 int sample_rate = effectiveOutputSampleRate();
48 if (isDecimateActive()) {
49 LOGI(
"Using reduced sample rate: %d", sample_rate);
52 ticker.begin(defaultPWMAudioOutputCallback, sample_rate, HZ);
57 virtual void setupPWM() {
59 if (audio_config.pwm_frequency == 0) {
62 analogWriteResolution(audio_config.resolution);
64 pins.resize(audio_config.channels);
65 for (
int j = 0; j < audio_config.channels; j++) {
66 int gpio = audio_config.pins()[j];
67 LOGI(
"PWM Pin: %d", gpio);
69 analogWriteFrequency(gpio, audio_config.pwm_frequency);
70 analogWrite(gpio, maxOutputValue() / 2);
75 virtual void setupTimer() {}
80 virtual int maxOutputValue() {
return (1 << audio_config.resolution) - 1; }
84 virtual void pwmWrite(
int channel,
int value) {
85 analogWrite(pins[channel], value);
90 PWMDriverTangNanoTimer *self = (PWMDriverTangNanoTimer *)obj;
91 if (self !=
nullptr) {
92 self->playNextFrame();
97#if TANGNANO20K_PWM_AUDIO
108class PWMDriverTangNano :
public PWMDriverBase {
110 PWMDriverTangNano() {
LOGD(
"PWMDriverTangNano"); }
120 virtual void end()
override {
123 is_timer_started =
false;
128 virtual size_t write(
const uint8_t *data,
size_t len)
override {
129 if (!is_timer_started)
return 0;
130 if (audio_config.bits_per_sample == 16) {
131 return ::PWMAudio.write(data, len);
134 int bytes = bytesPerSample();
135 size_t samples = len / bytes;
138 while (pos < samples) {
139 size_t n = min(samples - pos, (
size_t)64);
140 for (
size_t j = 0; j < n; j++) {
141 tmp[j] = toInt16(data + (pos + j) * bytes);
143 ::PWMAudio.write((
const uint8_t *)tmp, n *
sizeof(int16_t));
146 return samples * bytes;
150 virtual int availableForWrite()
override {
151 return ::PWMAudio.availableForWrite() / 2 * bytesPerSample();
154 int effectiveOutputSampleRate()
override {
return audio_config.sample_rate; }
157 virtual void setupPWM() {
159 if (audio_config.pwm_frequency == 0) {
162 PWMAudioConfig cfg = ::PWMAudio.defaultConfig();
163 cfg.sampleRate = audio_config.sample_rate;
164 cfg.channels = audio_config.channels;
165 cfg.pwmRate = audio_config.pwm_frequency;
167 int frames = audio_config.buffer_size * audio_config.buffers /
168 (audio_config.channels * bytesPerSample());
169 if (frames > 0xFFFF) frames = 0xFFFF;
170 if (frames > 0) cfg.ringSamples = frames;
171 is_timer_started = ::PWMAudio.begin(cfg);
172 if (!is_timer_started) {
173 LOGE(
"PWMAudio.begin failed");
178 virtual void setupTimer() {}
179 virtual void startTimer() {}
180 virtual int maxChannels() {
return 2; };
181 virtual int maxOutputValue() {
return 0xFFFF; }
182 virtual void pwmWrite(
int channel,
int value) {}
183 bool isDecimateActive()
override {
return false; }
184 int decimation()
override {
return 1; }
187 int bytesPerSample() {
188 return audio_config.bits_per_sample == 24 ?
sizeof(
int24_t)
189 : audio_config.bits_per_sample / 8;
192 int16_t toInt16(
const uint8_t *data) {
193 switch (audio_config.bits_per_sample) {
195 return (int16_t)(*(int8_t *)data) << 8;
197 return (int32_t)(*(
int24_t *)data) >> 8;
199 return (*(int32_t *)data) >> 16;
201 return *(int16_t *)data;
#define OUTPUT
Definition Arduino.h:38
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
PWMDriverAVR PWMDriver
Platform-specific PWM driver alias for AVR.
Definition PWMDriverAVR.h:13
constexpr const _Ep * end(initializer_list< _Ep > __il) noexcept
Definition InitializerList.h:63
#define PWM_AUDIO_FREQUENCY
Definition tangnano20k.h:23
#define PIN_PWM_COUNT
Definition tangnano20k.h:21