Mbed OS Reference
Loading...
Searching...
No Matches
USBAudio.h
1/*
2 * Copyright (c) 2018-2019, Arm Limited and affiliates.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef USBAudio_H
19#define USBAudio_H
20
21/* These headers are included for child class. */
22#include "USBDescriptor.h"
23#include "USBDevice_Types.h"
24
25#include "USBDevice.h"
26#include "Callback.h"
27#include "OperationList.h"
28#include "ByteBuffer.h"
29#include "rtos/EventFlags.h"
30
31/** \defgroup drivers-public-api-usb USB
32 * \ingroup drivers-public-api
33 */
34
35/**
36 * \defgroup drivers_USBAudio USBAudio class
37 * \ingroup drivers-public-api-usb
38 * @{
39 */
40
41
42/**
43* USBAudio example
44*
45* @code
46* #include "mbed.h"
47* #include "USBAudio.h"
48*
49* // Audio loopback example use:
50* // 1. Select "Mbed Audio" as your sound device
51* // 2. Play a song or audio file
52* // 3. Record the output using a program such as Audacity
53*
54* int main() {
55*
56* USBAudio audio(true, 44100, 2, 44100, 2);
57*
58* printf("Looping audio\r\n");
59* static uint8_t buf[128];
60* while (true) {
61* if (!audio.read(buf, sizeof(buf))) {
62* memset(buf, 0, sizeof(buf));
63* }
64* audio.write(buf, sizeof(buf));
65* }
66* }
67* @endcode
68*/
69class USBAudio: protected USBDevice {
70public:
71
72 enum AudioEvent {
73 Start,
74 Transfer,
75 End
76 };
77
78 /**
79 * Basic constructor
80 *
81 * Construct this object optionally connecting.
82 *
83 * @note Do not use this constructor in derived classes.
84 *
85 * @param connect Call connect on initialization
86 * @param frequency_rx frequency in Hz (default: 48000)
87 * @param channel_count_rx channel number (1 or 2) (default: 1)
88 * @param frequency_tx frequency in Hz (default: 8000)
89 * @param channel_count_tx channel number (1 or 2) (default: 1)
90 * @param buffer_ms time audio can be buffered without overflowing in milliseconds
91 * @param vendor_id Your vendor_id
92 * @param product_id Your product_id
93 * @param product_release Your product_release
94 */
95 USBAudio(bool connect = true, uint32_t frequency_rx = 48000, uint8_t channel_count_rx = 1, uint32_t frequency_tx = 8000, uint8_t channel_count_tx = 1, uint32_t buffer_ms = 10, uint16_t vendor_id = 0x7bb8, uint16_t product_id = 0x1111, uint16_t product_release = 0x0100);
96
97 /**
98 * Fully featured constructor
99 *
100 * Construct this object with the supplied USBPhy and parameters. The user
101 * this object is responsible for calling connect() or init().
102 *
103 * @note Derived classes must use this constructor and call init() or
104 * connect() themselves. Derived classes should also call deinit() in
105 * their destructor. This ensures that no interrupts can occur when the
106 * object is partially constructed or destroyed.
107 *
108 * @param phy USB phy to use
109 * @param frequency_rx frequency in Hz (default: 48000)
110 * @param channel_count_rx channel number (1 or 2) (default: 1)
111 * @param frequency_tx frequency in Hz (default: 8000)
112 * @param channel_count_tx channel number (1 or 2) (default: 1)
113 * @param buffer_ms time audio can be buffered without overflowing in milliseconds
114 * @param vendor_id Your vendor_id
115 * @param product_id Your product_id
116 * @param product_release Your product_release
117 */
118 USBAudio(USBPhy *phy, uint32_t frequency_rx, uint8_t channel_count_rx, uint32_t frequency_tx, uint8_t channel_count_tx, uint32_t buffer_ms, uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
119
120 /**
121 * Destroy this object
122 *
123 * Any classes which inherit from this class must call deinit
124 * before this destructor runs.
125 */
126 virtual ~USBAudio();
127
128 /**
129 * Connect USBAudio
130 */
131 void connect();
132
133 /**
134 * Disconnect USBAudio
135 *
136 * This unblocks all calls to read_ready and write_ready.
137 */
139
140 /**
141 * Read audio data
142 *
143 * @param buf pointer on a buffer which will be filled with audio data
144 * @param size size to read
145 *
146 * @returns true if successful
147 */
148 bool read(uint8_t *buf, uint32_t size);
149
150 /**
151 * Nonblocking audio data read
152 *
153 * Read the available audio data.
154 *
155 * @param buf pointer on a buffer which will be filled with audio data
156 * @param size size to read
157 * @param actual size actually read
158 * @note This function is safe to call from USBAudio callbacks.
159 */
160 void read_nb(uint8_t *buf, uint32_t size, uint32_t *actual);
161
162 /**
163 * Return the number read packets dropped due to overflow
164 *
165 * @param clear Reset the overflow count back to 0
166 * @return Number of packets dropped due to overflow
167 */
168 uint32_t read_overflows(bool clear = false);
169
170 /**
171 * Check if the audio read channel is open
172 *
173 * @return true if the audio read channel open, false otherwise
174 */
176
177 /**
178 * Wait until the audio read channel is open
179 */
181
182 /**
183 * Write audio data
184 *
185 * @param buf pointer to audio data to write
186 * @param size size to write
187 *
188 * @returns true if successful
189 */
190 bool write(uint8_t *buf, uint32_t size);
191
192 /**
193 * Nonblocking audio data write
194 *
195 * Write the available audio data.
196 *
197 * @param buf pointer to audio data to write
198 * @param size size to write
199 * @param actual actual size written
200 * @note This function is safe to call from USBAudio callbacks.
201 */
202 void write_nb(uint8_t *buf, uint32_t size, uint32_t *actual);
203
204 /**
205 * Return the number write packets not sent due to underflow
206 *
207 * @param clear Reset the underflow count back to 0
208 * @return Number of packets that should have been
209 * sent but weren't due to overflow
210 */
211 uint32_t write_underflows(bool clear = false);
212
213 /**
214 * Check if the audio write channel is open
215 *
216 * @return true if the audio write channel open, false otherwise
217 */
219
220 /**
221 * Wait until the audio write channel is open
222 */
224
225 /**
226 * Get current volume between 0.0 and 1.0
227 *
228 * @returns volume
229 */
230 float get_volume();
231
232 /** Attach a Callback to update the volume
233 *
234 * @param cb Callback to attach
235 *
236 */
237 void attach(mbed::Callback<void()> &cb);
238
239 /** attach a Callback to Tx Done
240 *
241 * @param cb Callback to attach
242 *
243 */
244 void attach_tx(mbed::Callback<void(AudioEvent)> &cb);
245
246 /** attach a Callback to Rx Done
247 *
248 * @param cb Callback to attach
249 *
250 */
251 void attach_rx(mbed::Callback<void(AudioEvent)> &cb);
252
253protected:
254
255 virtual void callback_state_change(DeviceState new_state);
256 virtual void callback_request(const setup_packet_t *setup);
257 virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted);
258 virtual void callback_set_configuration(uint8_t configuration);
259 virtual void callback_set_interface(uint16_t interface, uint8_t alternate);
260
261 virtual const uint8_t *string_iproduct_desc();
262 virtual const uint8_t *string_iinterface_desc();
263 virtual const uint8_t *configuration_desc(uint8_t index);
264
265private:
266
267 class AsyncWrite;
268 class AsyncRead;
269
270 enum ChannelState {
271 Powerdown,
272 Closed,
273 Opened
274 };
275
276 void _init(uint32_t frequency_rx, uint8_t channel_count_rx, uint32_t frequency_tx, uint8_t channel_count_tx, uint32_t buffer_ms);
277
278 /*
279 * Call to rebuild the configuration descriptor
280 *
281 * This function should be called on creation or when any
282 * value that is part of the configuration descriptor
283 * changes.
284 * @note This function uses ~200 bytes of stack so
285 * make sure your stack is big enough for it.
286 */
287 void _build_configuration_desc();
288
289 void _receive_change(ChannelState new_state);
290 void _receive_isr();
291 void _send_change(ChannelState new_state);
292 void _send_isr_start();
293 void _send_isr_next_sync();
294 void _send_isr();
295
296 // has connect been called
297 bool _connected;
298
299 // audio volume
300 float _volume;
301
302 // mute state
303 uint8_t _mute;
304
305 // Volume Current Value
306 uint16_t _vol_cur;
307
308 // Volume Minimum Value
309 uint16_t _vol_min;
310
311 // Volume Maximum Value
312 uint16_t _vol_max;
313
314 // Volume Resolution
315 uint16_t _vol_res;
316
317 // callback to update volume
318 mbed::Callback<void()> _update_vol;
319
320 // callback transmit Done
321 mbed::Callback<void(AudioEvent)> _tx_done;
322
323 // callback receive Done
324 mbed::Callback<void(AudioEvent)> _rx_done;
325
326 // Number of times data was dropped due to an overflow
327 uint32_t _rx_overflow;
328
329 // Number of times data was not sent due to an underflow
330 uint32_t _tx_underflow;
331
332 // frequency in Hz
333 uint32_t _tx_freq;
334 uint32_t _rx_freq;
335
336 // mono, stereo,...
337 uint8_t _rx_channel_count;
338 uint8_t _tx_channel_count;
339
340 bool _tx_idle;
341 uint16_t _tx_frame_fract;
342 uint16_t _tx_whole_frames_per_xfer;
343 uint16_t _tx_fract_frames_per_xfer;
344
345 // size of the maximum packet for the isochronous endpoint
346 uint16_t _tx_packet_size_max;
347 uint16_t _rx_packet_size_max;
348
349 // Buffer used for the isochronous transfer
350 uint8_t *_tx_packet_buf;
351 uint8_t *_rx_packet_buf;
352
353 // Holding buffer
354 ByteBuffer _tx_queue;
355 ByteBuffer _rx_queue;
356
357 // State of the audio channels
358 ChannelState _tx_state;
359 ChannelState _rx_state;
360
361
362 // sample - a single PCM audio sample
363 // frame - a group of samples from each channel
364 // packet - a group of frames sent over USB in one transfer
365
366 // Blocking primitives
367 OperationList<AsyncWrite> _write_list;
368 OperationList<AsyncRead> _read_list;
369 rtos::EventFlags _flags;
370
371 // endpoint numbers
372 usb_ep_t _episo_out; // rx endpoint
373 usb_ep_t _episo_in; // tx endpoint
374
375 // channel config in the configuration descriptor: master, left, right
376 uint16_t _channel_config_rx;
377 uint16_t _channel_config_tx;
378
379 // configuration descriptor
380 uint8_t _config_descriptor[183];
381
382 // buffer for control requests
383 uint8_t _control_receive[2];
384
385};
386
387/** @}*/
388
389#endif
USBAudio example.
Definition: USBAudio.h:69
void write_nb(uint8_t *buf, uint32_t size, uint32_t *actual)
Nonblocking audio data write.
virtual void callback_request(const setup_packet_t *setup)
Called by USBDevice on Endpoint0 request.
void connect()
Connect USBAudio.
void read_nb(uint8_t *buf, uint32_t size, uint32_t *actual)
Nonblocking audio data read.
uint32_t write_underflows(bool clear=false)
Return the number write packets not sent due to underflow.
virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted)
Called by USBDevice on data stage completion.
void attach(mbed::Callback< void()> &cb)
Attach a Callback to update the volume.
virtual void callback_state_change(DeviceState new_state)
Called when USB changes state.
virtual ~USBAudio()
Destroy this object.
bool write(uint8_t *buf, uint32_t size)
Write audio data.
void attach_rx(mbed::Callback< void(AudioEvent)> &cb)
attach a Callback to Rx Done
void attach_tx(mbed::Callback< void(AudioEvent)> &cb)
attach a Callback to Tx Done
uint32_t read_overflows(bool clear=false)
Return the number read packets dropped due to overflow.
void write_wait_ready()
Wait until the audio write channel is open.
bool write_ready()
Check if the audio write channel is open.
void disconnect()
Disconnect USBAudio.
void read_wait_ready()
Wait until the audio read channel is open.
USBAudio(USBPhy *phy, uint32_t frequency_rx, uint8_t channel_count_rx, uint32_t frequency_tx, uint8_t channel_count_tx, uint32_t buffer_ms, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
Fully featured constructor.
USBAudio(bool connect=true, uint32_t frequency_rx=48000, uint8_t channel_count_rx=1, uint32_t frequency_tx=8000, uint8_t channel_count_tx=1, uint32_t buffer_ms=10, uint16_t vendor_id=0x7bb8, uint16_t product_id=0x1111, uint16_t product_release=0x0100)
Basic constructor.
bool read_ready()
Check if the audio read channel is open.
bool read(uint8_t *buf, uint32_t size)
Read audio data.
float get_volume()
Get current volume between 0.0 and 1.0.
Core USB Device driver.
Definition: USBDevice.h:38
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
Callback class based on template specialization.
Definition: Callback.h:53
The EventFlags class is used to control event flags or wait for event flags other threads control.
Definition: EventFlags.h:53