arduino-audio-tools
I2SRP2040-MBED.h
1 #pragma once
2 
3 #include "AudioTools/CoreAudio/AudioI2S/I2SConfig.h"
4 #if defined(RP2040_MBED)
5 #include "RP2040-I2S.h"
6 
7 #define IS_I2S_IMPLEMENTED
8 
9 namespace audio_tools {
10 
11 //#if !defined(ARDUINO_ARCH_MBED_RP2040)
12 //static ::I2S I2S;
13 //#endif
14 
21 class I2SDriverRP2040MBED {
22  friend class I2SStream;
23 
24  public:
26  I2SConfigStd defaultConfig(RxTxMode mode) {
27  I2SConfigStd c(mode);
28  return c;
29  }
30 
32  bool setAudioInfo(AudioInfo) { return false; }
33 
35  bool begin(RxTxMode mode = TX_MODE) {
36  TRACED();
37  return begin(defaultConfig(mode));
38  }
39 
41  bool begin(I2SConfigStd cfg) {
42  TRACEI();
43  this->cfg = cfg;
44  cfg.logInfo();
45  if (cfg.rx_tx_mode != TX_MODE) {
46  LOGE("Unsupported mode: only TX_MODE is supported");
47  return false;
48  }
49  if (!I2S.setBCLK(cfg.pin_bck)) {
50  LOGE("Could not set bck pin: %d", cfg.pin_bck);
51  return false;
52  }
53  if (!I2S.setDATA(cfg.pin_data)) {
54  LOGE("Could not set data pin: %d", cfg.pin_data);
55  return false;
56  }
57  if (cfg.bits_per_sample != 16) {
58  LOGE("Unsupported bits_per_sample: %d", (int)cfg.bits_per_sample);
59  return false;
60  }
61 
62  if (cfg.channels < 1 || cfg.channels > 2) {
63  LOGE("Unsupported channels: '%d' - only 2 is supported", (int)cfg.channels);
64  return false;
65  }
66 
67  int rate = cfg.sample_rate;
68  if (cfg.channels == 1) {
69  rate = rate / 2;
70  }
71 
72  if (!I2S.begin(rate)) {
73  LOGE("Could not start I2S");
74  return false;
75  }
76  return true;
77  }
78 
80  void end() { I2S.end(); }
81 
83  I2SConfigStd config() { return cfg; }
84 
86  size_t writeBytes(const void *src, size_t size_bytes) {
87  TRACED();
88  size_t result = 0;
89  int16_t *p16 = (int16_t *)src;
90 
91  if (cfg.channels == 1) {
92  int samples = size_bytes / 2;
93  // multiply 1 channel into 2
94  int16_t buffer[samples * 2]; // from 1 byte to 2 bytes
95  for (int j = 0; j < samples; j++) {
96  buffer[j * 2] = p16[j];
97  buffer[j * 2 + 1] = p16[j];
98  }
99  result = I2S.write((const uint8_t *)buffer, size_bytes * 2) * 2;
100  } else if (cfg.channels == 2) {
101  result = I2S.write((const uint8_t *)src, size_bytes) * 4;
102  }
103  return result;
104  }
105 
106  size_t readBytes(void *dest, size_t size_bytes) {
107  TRACEE();
108  size_t result = 0;
109  return result;
110  }
111 
112  int availableForWrite() {
113  int result = 0;
114  if (cfg.channels == 1) {
115  // it should be a multiple of 2
116  result = I2S.availableForWrite() / 2 * 2;
117  // return half of it because we double when writing
118  result = result / 2;
119  } else {
120  // it should be a multiple of 4
121  result = I2S.availableForWrite() / 4 * 4;
122  }
123  if (result < 4) {
124  result = 0;
125  }
126  return result;
127  }
128 
129  int available() { return 0; }
130 
131  void flush() { return I2S.flush(); }
132 
133  protected:
134  I2SConfigStd cfg;
135 
136  // blocking write
137  void writeSample(int16_t sample) {
138  int written = I2S.write(sample);
139  while (!written) {
140  delay(5);
141  LOGW("written: %d ", written);
142  written = I2S.write(sample);
143  }
144  }
145 
146  int writeSamples(int samples, int16_t *values) {
147  int result = 0;
148  for (int j = 0; j < samples; j++) {
149  int16_t sample = values[j];
150  writeSample(sample);
151  writeSample(sample);
152  result++;
153  }
154  return result;
155  }
156 };
157 
158 using I2SDriver = I2SDriverRP2040MBED;
159 
160 } // namespace audio_tools
161 
162 #endif
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:872
size_t writeSamples(Print *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition: AudioTypes.h:506