Mistake on this page?
Report an issue in GitHub or email us
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 */
69 class USBAudio: protected USBDevice {
70 public:
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  */
138  void disconnect();
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  */
175  bool read_ready();
176 
177  /**
178  * Wait until the audio read channel is open
179  */
180  void read_wait_ready();
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  */
218  bool write_ready();
219 
220  /**
221  * Wait until the audio write channel is open
222  */
223  void write_wait_ready();
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 
253 protected:
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 
265 private:
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
322 
323  // callback receive 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
void attach_rx(mbed::Callback< void(AudioEvent)> &cb)
attach a Callback to Rx Done
void attach(mbed::Callback< void()> &cb)
Attach a Callback to update the volume.
bool write(uint8_t *buf, uint32_t size)
Write audio data.
The EventFlags class is used to control event flags or wait for event flags other threads control...
Definition: EventFlags.h:53
void write_nb(uint8_t *buf, uint32_t size, uint32_t *actual)
Nonblocking audio data write.
bool read(uint8_t *buf, uint32_t size)
Read audio data.
bool write_ready()
Check if the audio write channel is open.
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.
Abstract interface to physical USB hardware.
Definition: USBPhy.h:82
float get_volume()
Get current volume between 0.0 and 1.0.
void connect()
Connect USBAudio.
USBAudio example.
Definition: USBAudio.h:69
Core USB Device driver.
Definition: USBDevice.h:38
virtual ~USBAudio()
Destroy this object.
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.
bool read_ready()
Check if the audio read channel is open.
virtual void callback_state_change(DeviceState new_state)
Called when USB changes state.
void read_wait_ready()
Wait until the audio read channel is open.
virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted)
Called by USBDevice on data stage completion.
virtual void callback_request(const setup_packet_t *setup)
Called by USBDevice on Endpoint0 request.
void disconnect()
Disconnect USBAudio.
void attach_tx(mbed::Callback< void(AudioEvent)> &cb)
attach a Callback to Tx Done
Callback class based on template specialization.
Definition: Callback.h:53
void write_wait_ready()
Wait until the audio write channel is open.
uint32_t read_overflows(bool clear=false)
Return the number read packets dropped due to overflow.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.