arduino-audio-tools
Loading...
Searching...
No Matches
I2SDriverTangNano.h
Go to the documentation of this file.
1#pragma once
2
5#if defined(ARDUINO_ARCH_TANGNANO20K)
6// The core defines a global I2SConfig which would be ambiguous with
7// audio_tools::I2SConfig because of the automatic using namespace
8#define I2SConfig TangNanoI2SConfig
9#include <I2STangNano.h>
10#undef I2SConfig
11
12#define IS_I2S_IMPLEMENTED
13
14namespace audio_tools {
15
26class I2SDriverTangNano : public I2SDriverBase {
27 friend class I2SStream;
28
29 public:
31 I2SConfigStd defaultConfig(RxTxMode mode) {
32 I2SConfigStd c(mode);
33 return c;
34 }
35
37 bool setAudioInfo(AudioInfo info) { return info.equals(cfg); }
38
40 bool begin(RxTxMode mode = TX_MODE) { return begin(defaultConfig(mode)); }
41
43 bool begin(I2SConfigStd cfg) {
44 TRACEI();
45 if (is_active) end();
46 this->cfg = cfg;
47 cfg.logInfo();
48
49 if (!cfg.is_master) {
50 LOGE("Only master mode is supported");
51 return false;
52 }
53 if (cfg.i2s_format != I2S_STD_FORMAT &&
54 cfg.i2s_format != I2S_PHILIPS_FORMAT) {
55 LOGE("Only the I2S (Philips) format is supported");
56 return false;
57 }
58 if (cfg.channels < 1 || cfg.channels > 2) {
59 LOGE("Unsupported channels: %d", cfg.channels);
60 return false;
61 }
62
63 TangNanoI2SConfig tang_cfg;
64 tang_cfg.sampleRate = cfg.sample_rate;
65 tang_cfg.channels = cfg.channels;
66 switch (cfg.rx_tx_mode) {
67 case TX_MODE:
68 tang_cfg.mode = I2S_MODE_OUTPUT;
69 break;
70 case RX_MODE:
71 tang_cfg.mode = I2S_MODE_INPUT;
72 break;
73 default:
74 tang_cfg.mode = I2S_MODE_DUPLEX;
75 break;
76 }
77 switch (cfg.bits_per_sample) {
78 case 8:
79 tang_cfg.bits = I2S_BITS_8;
80 break;
81 case 16:
82 tang_cfg.bits = I2S_BITS_16;
83 break;
84 case 24:
85#ifdef USE_3BYTE_INT24
86 tang_cfg.bits = I2S_BITS_24;
87#else
88 // int24_4bytes_t is stored as a left aligned 32 bit value
89 tang_cfg.bits = I2S_BITS_32;
90#endif
91 break;
92 case 32:
93 tang_cfg.bits = I2S_BITS_32;
94 break;
95 default:
96 LOGE("Unsupported bits_per_sample: %d", cfg.bits_per_sample);
97 return false;
98 }
99 if (cfg.buffer_size > 0 && cfg.buffer_count > 0) {
100 // buffer size is in bytes: the ring buffer is in frames
101 int frame_size = cfg.channels * bytesPerSample();
102 int frames = cfg.buffer_size * cfg.buffer_count / frame_size;
103 if (frames > 0xFFFF) frames = 0xFFFF;
104 tang_cfg.ringSamples = frames;
105 }
106
107 ::I2S.begin(tang_cfg);
108 is_active = true;
109 return true;
110 }
111
113 void end() {
114 ::I2S.end();
115 is_active = false;
116 }
117
119 I2SConfigStd config() { return cfg; }
120
122 size_t writeBytes(const void *src, size_t size_bytes) {
123 return ::I2S.write((const uint8_t *)src, size_bytes);
124 }
125
126 size_t readBytes(void *dest, size_t size_bytes) {
127 return ::I2S.readBytes((uint8_t *)dest, size_bytes);
128 }
129
131 int availableForWrite() {
132 return ::I2S.availableForWrite() * cfg.channels * bytesPerSample();
133 }
134
135 int available() { return ::I2S.available(); }
136
137 void flush() { ::I2S.flush(); }
138
139 protected:
140 I2SConfigStd cfg;
141 bool is_active = false;
142
144 int bytesPerSample() {
145 return cfg.bits_per_sample == 24 ? sizeof(int24_t)
146 : cfg.bits_per_sample / 8;
147 }
148};
149
150using I2SDriver = I2SDriverTangNano;
151
152} // namespace audio_tools
153
154#endif
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define LOGE(...)
Definition AudioLoggerIDF.h:30
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
int24_4bytes_t int24_t
Definition int24_t.h:12
I2SDriverESP32 I2SDriver
Definition I2SDriverESP32.h:418
constexpr const _Ep * end(initializer_list< _Ep > __il) noexcept
Definition InitializerList.h:63
constexpr const _Ep * begin(initializer_list< _Ep > __il) noexcept
Definition InitializerList.h:55