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