Engineers Garage

  • Electronic Projects & Tutorials
    • Electronic Projects
      • Arduino Projects
      • AVR
      • Raspberry pi
      • ESP8266
      • BeagleBone
      • 8051 Microcontroller
      • ARM
      • PIC Microcontroller
      • STM32
    • Tutorials
      • Audio Electronics
      • Battery Management
      • Brainwave
      • Electric Vehicles
      • EMI/EMC/RFI
      • Hardware Filters
      • IoT tutorials
      • Power Tutorials
      • Python
      • Sensors
      • USB
      • VHDL
    • Circuit Design
    • Project Videos
    • Components
  • Articles
    • Tech Articles
    • Insight
    • Invention Stories
    • How to
    • What Is
  • News
    • Electronic Product News
    • Business News
    • Company/Start-up News
    • DIY Reviews
    • Guest Post
  • Forums
    • EDABoard.com
    • Electro-Tech-Online
    • EG Forum Archive
  • DigiKey Store
    • Cables, Wires
    • Connectors, Interconnect
    • Discrete
    • Electromechanical
    • Embedded Computers
    • Enclosures, Hardware, Office
    • Integrated Circuits (ICs)
    • Isolators
    • LED/Optoelectronics
    • Passive
    • Power, Circuit Protection
    • Programmers
    • RF, Wireless
    • Semiconductors
    • Sensors, Transducers
    • Test Products
    • Tools
  • Learn
    • eBooks/Tech Tips
    • Design Guides
    • Learning Center
    • Tech Toolboxes
    • Webinars & Digital Events
  • Resources
    • Digital Issues
    • EE Training Days
    • LEAP Awards
    • Podcasts
    • Webinars / Digital Events
    • White Papers
    • Engineering Diversity & Inclusion
    • DesignFast
  • Guest Post Guidelines
  • Advertise
  • Subscribe

Atmega 32u4 Based USB Microphone (Part 16/25)

By Amanpreet Singh February 11, 2017

A microphone is a device that senses the sound waves and sends the digitized audio signals to the computer. The commonly used microphones have a 3.5 mm jack for audio input to the computer. Nowadays USB interface is also gaining popularity for interfacing audio devices with the computer. Even a lot of microphones and portable speakers nowadays have USB connector for interfacing with the computers. When USB interface is used by an audio device for connecting with the computer, the audio stream also needs to be sent according to the USB protocol.

In this project, a typical audio jack input of a regular microphone is replaced with the USB interface to connect with a computer. In order to send an audio stream to the computer according to USB protocol, there needs a controller chip that could accept the analog signal (electrical signal generated from sensing audio waves) and digitize it and forward it to the computer according to the USB protocol. As a controller chip 8-bit USB AVR – Atmega 32u4 is used in the project. The AVR based Lightweight USB Framework (LUFA) is used as the firmware of the chip which is modified to accept analog audio input and send out the USB encoded digitized audio stream.

In the USB protocol, there is a separate device class for audio devices – Audio Class 1.0 . The open-source LUFA framework has the drivers for audio class devices as well. With the use of LUFA firmware, the device driver code to implement USB protocol is not needed to be written explicitly. Modifying the firmware code to customize the functioning of the Audio Class driver will be all sufficient.

The project uses Arduino Pro Micro as the controller board which connects with a personal computer by on-board USB port and USB cable. The board accepts the analog audio signal from an analog input pin connecting to Audio Out wire of the microphone.

Prototype of Arduino based DIY USB Microphone

Fig. 1: Prototype of Arduino based DIY USB Microphone 

PREREQUISITES

This project is based on Arduino Pro Micro which has the USB AVR – Atmega 32u4 as the sitting MCU. In order to understand this project, one must have basic knowledge of the AVR microcontrollers and the embedded C programming for AVRs. WinAVR Studio is used to write, edit and compile the project code, so closely following the project shall require familiarizing with the above stated IDE as well. Though LUFA framework takes care of implementing the USB protocol and has APIs to abstract the lower level codes, understanding USB protocol is recommended to understand how actually the project is working. In fact, if anyone has already worked on some other microcontroller, it will not be much pain to understand and follow this project as the project code is about getting analog input to the AVR microcontroller and modifying the LUFA device driver for audio class to customize the device functioning.

COMPONENTS REQUIRED

1. Arduino Pro Micro

2. Breadboard

3. Connecting wires

4. Micro USB cable

5. Any regular microphone

SOFTWARE TOOLS REQUIRED

1. WinAVR Studio

2. AVR Dude

3. LUFA Firmware

BLOCK DIAGRAM

Block Diagram of Arduino based DIY USB Microphone

Fig. 2: Block Diagram of Arduino based DIY USB Microphone 

CIRCUIT CONNECTIONS

The project is built on Arduino Pro Micro and uses Atmega 32u4 as the USB controller chip. The Audio jack of a microphone has three wires – VCC, Ground and Analog Out. The VCC and Ground wires are connected with the common VCC and ground of the circuit respectively. The Audio Out wire of the microphone is connected with the A0 analog pin (Pin 7 of Port F on Arduino Pro Micro). The board is connected to the computer from using USB cable. The program code for the project is burnt to the Arduino Pro Micro using AVR Dude.

HOW THE PROJECT WORKS

In this project the USB protocol is implemented by the LUFA framework. For configuring the controller chip to work as USB microphone, the  Audio Class Driver of the LUFA framework will be used. The Audio Class 1.0 driver takes care of the transfers between the host device and the audio devices like microphone, speaker and USB Connect-able musical instrument.

When a USB device is attached to the host (PC), the host sends request for configuration details in the form of control transfer. The connected device has to respond with appropriate descriptors to get configured and ready for further operations. Only after configuration, the device can communicate with the host in the form of interrupt, isochronous or bulk transfers for executing the operations for which the device has been made. In case of microphone, after configuring with the host device, it has to communicate with the host in the form of isochronous transfers as audio data is a kind of time sensitive information. The process of identification and configuration of the device with the host is called enumeration.

A microphone is an audio class USB device and LUFA framework has Audio class related modules  in the LUFA-Source-Folder /LUFA/Drivers/USB/Class/Device folder. Other device class related module are also in the same folder. The LUFA framework has demo projects for different USB device classes in the LUFA-Source-FolderDemosDeviceClassDriver folder. For implementing the project, demo project for audio input provided in the LUFA framework will be modified and complied. The demo project for audio input is in the LUFA-Source-FolderDemosDeviceClassDriverAudioInput folder. The folder contains AudioInput.c file which will be modified to implement the project.

How AudioInput.c identifies device as microphone

The AudioInput.c uses Microphone_Audio_Interface interface in Audio_Device_USBTask() function which is being imported from the AudioClassDevice.c (from LUFA-Source-Folder LUFADriversUSBClassDevice) to configure the device as microphone. The interface abstracts the low-level descriptor codes and identifies the device as microphone through ControlInterfaceNumber and StreamingInterfaceNumber variables.

Image of Arduino based DIY USB Microphone

Fig. 3: Image of Arduino based DIY USB Microphone 

Microphone Specific Report Descriptors

Similar to any  HID device, the audio class device also has to exchange data with the host which should be structured in the form of reports. The report descriptor defines the report structure. A report descriptor contains the information needed by host to determine the data format and how the data should be processed by the host. Therefore, a report descriptor basically structure the data that needs to be exchanged with the host according to the USB protocol.

For working like a microphone, the audio device also needs to respond with proper descriptors in response to the requests made by the host. An audio class device has the following descriptors associated with it

1) Device Descriptor

2) Configuration Descriptor

3) Audio Control (AC) Interface Descriptors

4) Audio Control (AC) Endpoint descriptors

5) Audio Streaming Interface Descriptors

6) Audio Streaming Endpoint Descriptors

The device descriptor and configuration descriptor for the audio input device are defined in the descriptor.h file in the same folder with definitions in the descriptor.c file of the same folder. The Audio Control (AC) interface, Audio Stream (AS) interface and Audio Stream (AS) Endpoint descriptors are defined for the audio input device and are defined within the configuration descriptor. The descriptors get the usage report item values from the AudioClassCommon.h (file located in LUFA-Source-FolderLUFADriversUSBClassCommon folder). The AudioInput.c imports AudioInput.h which imports USB.h. USB.h imports AudioCLass.h. In AudioClass.h is imported AudioClassDevice.h if the USB_CAN_BE_DEVICE is true for the controller chip to being a USB device not the host. The AudioClassDevice.h imports AudioClassCommon.h where the Audio Class device specific descriptor fields have been defined.

The Audio device class can respond to the following Audio Class requests defined in AudioClassCommon.h.

Screenshot of Audio Class requests defined in AudioClassCommon.h File

Fig. 4: Screenshot of Audio Class requests defined in AudioClassCommon.h File

The sub class within Audio Class device are defined in the following manner -:

Screenshot of sub class within Audio Class device

Fig. 5: Screenshot of sub class within Audio Class device

The Audio Control subtypes are defined in the following manner -:

Screenshot of Audio Control subtypes

Fig. 6: Screenshot of Audio Control subtypes

The Audio Streaming subtypes are defined in the following manner -:

Screenshot of Audio Streaming subtypes

Fig. 7: Screenshot of Audio Streaming subtypes

The generic AC interface descriptor is defined in the following manner -:

Screenshot of generic AC interface descriptor

Fig. 8: Screenshot of generic AC interface descriptor

The Audio Class specific AC interface descriptor is defined in the following manner -:

Screenshot of Audio Class specific AC interface descriptor

Fig. 9: Screenshot of Audio Class specific AC interface descriptor

 

The generic Audio Stream Interface descriptor is defined in the following manner -:

Screenshot of generic Audio Stream Interface descriptor

Fig. 10: Screenshot of generic Audio Stream Interface descriptor 

 

The Audio Class specific Stream Interface descriptor is defined in the following manner -:

Screenshot of Audio Class specific Stream Interface descriptor

Fig. 11: Screenshot of Audio Class specific Stream Interface descriptor

The generic Audio Stream Endpoint descriptor is defined in the following manner -:

Screenshot of generic Audio Stream Endpoint descriptor

Fig. 12: Screenshot of generic Audio Stream Endpoint descriptor

 

The Audio Class specific Stream Endpoint descriptor is defined in the following manner -:

Screenshot of Audio Class specific Stream Endpoint descriptor

Fig. 13: Screenshot of Audio Class specific Stream Endpoint descriptor

The report item values defined for the above-stated descriptors are taken from the “USB Device Class Definitions for Audio devices” provided by the USB Implementers Forum. The Host can access these report descriptors by requesting the device using GET_REPORT request. This report is transmitted using Control Transfer Type of the USB protocol.

HOW THE DEVICE WORKS

A regular microphone with an inbuilt amplifier will be interfaced to the microcontroller using Analog input pin. The microcontroller will convert the audio signals taken from the microphone to digital data using inbuilt ADC (Analog to Digital Conversion) functionality.

To sample or convert the analog signal at regular intervals, the internal timer of Atmega32u4 will be used. The most commonly used sampling frequencies for audio conversion are 44.1 KHz, 48 KHz, 88.2 KHz, or 96 KHz. A 48 KHz sampling frequency will be used. This simply means one sample after every 20.83 microseconds.

Screenshot of Microphone Detection on Windows

Fig. 14: Screenshot of LUFA Library Folder on Windows

The timer will be used in CTC (Clear Timer on Compare) mode and inside the compare interrupt, the audio signal will be sampled and the digital data will be sent to the host. In the CTC mode, there are two values, one is SET value and another one is process value. Once the process value become equal (or more than) the SET value, the process value is reset.

The demo code for Audio Input given in the LUFA framework will be used to more or less extent as it is. Some minor modifications like commenting out unused features and defining the analog input pin in AppConfig.h file will be needed to be done.

PROGRAMMING GUIDE

For building the project download the LUFA framework from the github.com. The demo project provided with the LUFA framework is modified to make the project. In the extracted LUFA zip file, open Demos/Device/ClassDriver/AudioInput folder. The folder has the following files and folders.

Screenshot of LUFA Library Folder on Windows

Of these, AudioInput.h, AudioInput.c, Appconfig.h (inside Config folder) and Makefile needs to be modified for this project. The modified files (provided at the bottom of the article in zip format) can also be downloaded from the engineersgarage and replaced with the original files. Either open the files in WinAVR Studio or Notepad++ and modify original files or replace files with the already modified one. The modified or replaced AudioInput.c needs to be compiled from within the LUFA’s Source folder to get the object code.

Modifying AudioInput.h

The AudioInput.h library file is imported in the AudioInput.c file and includes a set of additional libraries and defines the constants and functions needed for the device operation. These include the additional libraries for the joystick, button and LEDs which should be commented out as the project is not using these features. So open AudioInput.h and make the following changes – :

• Comment the #include library statements for Joystick.h, LEDS.h, and Buttons.h ( We are commenting these libraries as we are not using any joystick, buttons board and LED board)

• Comment the #define statements for LEDMASK_USB_NOTREADY, LEDMASK_USB_ENUMERATING, LEDMASK_USB_READY, LEDMASK_USB_ERROR

Save the file with changes.

Modifying AudioInput.C file

Again in the AudioInput.c, the code sections for Joystick, button board and LEDs need to be commented out. So open AudioInput.c and make the following changes -:

• In the main loop, comment the LEDs_SetAllLEDs()

• In SetupHardware() function, comment the Joystick_Init(), LEDs_Init(), Buttons_Init()

• In EVENT_USB_Device_Connect() function, comment the LEDs_SetAllLEDs()

• In EVENT_USB_Device_Disconnect() function, comment LEDs_SetAllLEDs()

• In EVENT_USB_Device_ConfigurationChanged() function, comment the LEDs_SetAllLEDs()

In AudioInput.c the main() function executes the functioning of the device. Inside the main function only the statement for LEDs has to be commented out. The main function will have the following bodyInside the infinite for loop the Audio_Device_USBTask() function is called where Microphone_Audio_Interface interface is passed as parameter. The interface identifies the device as microphone and abstracts the low level program code specific to Audio Class Device. The function is coming from the AudioClassDevice.c module (located in LUFA/Drivers/USB/Class/Device/ folder) and is used for general management task for a given audio class interface, required for the correct operation of the interface. It should be called in the main program loop, before the master USB management task USB_USBTask(). The  USB_USBTask() is the main USB management task. The USB driver requires this task to be executed continuously when the USB system is active (device attached in host mode, or attached to a host in device mode) in order to manage USB communications. The function is defined in USBTask.c (Located in LUFA-Source-FolderLUFADriversUSBCore folder).

The timer gets initialized and set to CTC mode with defined time period inside the EVENT_USB_Device_Connect() function. When the USB device is plugged, this function gets executed and the timer gets initialized. The EVENT_USB_Device_Connect() function has the following body.

In the body of the function, the timer 0 is selected by setting the OCIE0A bit of the timer mask register. In this way, the Timer/Counter0 Compare Match A interrupt is enabled. The corresponding interrupt is executed. if a Compare Match in Timer/Counter0 occurs, i.e., when the OCF0A bit is set in the Timer/Counter 0 Interrupt Flag Register – TIFR0. The value in Output Compare Register A is set according to the CPU frequency and sampling rate by passing a value in OCR0A register. By setting the WGM01 bit in the Timer Control register A (TCCR0A), the CTC mode is selected. Finally by setting the CS01 bit in the Timer Control Register B (TCCR0B), the clock source is set to 1/8 of the CPU clock.

The timer stops when the device is unplugged from the host. The timer stop statement can be found in EVENT_USB_Device_Disconnect() function. The EVENT_USB_Device_Disconnect() function has the following body.

In the body of the function, the timer control register B (responsible for setting clock source) is cleared to stop the timer. These timer settings are important to set the sampling rate of the audio stream.

The most important function is the ISR (Interrupt Service Routine) for the timer compare interrupt. In this function, the analog signal is sampled and the digital data obtained after conversion is sent to host. The function is declared inside this file with the heading ISR (TIMER0_COMPA_vect, ISR_BLOCK). There are some statements inside this function that are not required and can be removed. That is the #if defined(USE_TEST_TONE) and its corresponding statements. These statements were used to generate a square wave in order to test the functioning and can be removed. Also, remove the #else and last #endif statement. So the interrupt service routine will have the following body -:

The interrupt service routine samples 16-bit audio data at every execution of the interrupt routine.

Modifying AppConfig.h file

The ADC input pin for the microcontroller can be set inside the file AppConfig.h. This file is located inside the Config folder. Inside this file, there is statement #define MIC_IN_ADC_CHANNEL that defines the input channel for the Analog to Digital Conversion. By default, analog channel 2 is selected. This will be changed to analog channel 7 which is at pin PF7 (A0) of the Arduino Pro Micro. So the statement needs to be defined with value 7. Also, the #define USE_TEST_TONE statement can be commented as any square wave will not be generated for testing of the device.

Save the file and create Make file for the project.

Modifying Make File

In the AudioInput folder there is a make file that needs to be edited. The file can be edited using Notepad++. The following information needs to be edited – :

• MCU = atmega32u4

• ARCH = AVR8

• BOARD = LEONARDO

 

• F_CPU = 16000000

Save the file and exit. Now all the files are edited completely for the basic USB microphone project.

Compiling AudioInput.c

For compiling the source code, WinAVR Programmers Notepad or Arduino IDE can be used. Open the modified AudioInput.c file and compile the code.

BURNING HEX CODE

The hex file is generated on compiling the AudioInput.c file. For burning the object code to microcontroller open the Command Prompt, change the current directory to the directory containing the Hex file. This can be done using command: CD <address of the directory>. Now reset the Arduino and instantly run the command: : avrdude -v -p atmega32u4 -c avr109 -P COM20 -b 57600 -D -Uflash:w:AudioInput.hex:i after replacing the COM Port with the recognized one.

If the uploading process is successful, the Arduino will be shown as Audio In Demo under the Sounds tab in the Device Manager. There is no need of installing any driver in the computer as Generic Audio Class device driver is used for the project implementation.

TESTING

For testing, connect the analog output of the amplifier to the A0 (PF7) pin of the microcontroller. The amplifier can be powered from the Arduino Pro Micro board using VCC and Ground pins.

Use any recording tool to record and test the device. On Windows 7, Sound recorder can be used.

In the next project – Atmega 32u4 Based USB Speaker, learn how to make another Audio Class Device that will be an USB Speaker.

Project Source Code

###


/*

             LUFA Library

     Copyright (C) Dean Camera, 2015.


  dean [at] fourwalledcubicle [dot] com

           www.lufa-lib.org

*/


/*

  Copyright 2015  Dean Camera (dean [at] fourwalledcubicle [dot] com)
  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.


  The author disclaims all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.

*/


/** file

 *

 *  Main source file for the AudioInput demo. This file contains the main tasks of

 *  the demo and is responsible for the initial application hardware configuration.

 */


#include "AudioInput.h"


/** LUFA Audio Class driver interface configuration and state information. This structure is

 *  passed to all Audio Class driver functions, 
so that multiple instances of the same class

 *  within a device can be differentiated from one another.

 */

USB_ClassInfo_Audio_Device_t Microphone_Audio_Interface =

{

.Config =

{

.ControlInterfaceNumber   = INTERFACE_ID_AudioControl,

.StreamingInterfaceNumber = INTERFACE_ID_AudioStream,

.DataINEndpoint           =

{

.Address          = AUDIO_STREAM_EPADDR,

.Size             = AUDIO_STREAM_EPSIZE,

.Banks            = 2,

},

},

};


/** Current audio sampling frequency of the streaming audio endpoint. */

static uint32_t CurrentAudioSampleFrequency = 48000;



/** Main program entry point. This routine contains the overall program flow, including initial

 *  setup of all components and the main program loop.

 */

int main(void)

{

SetupHardware();


//LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

GlobalInterruptEnable();


for (;;)

{

Audio_Device_USBTask(&Microphone_Audio_Interface);

USB_USBTask();

}

}


/** Configures the board hardware and chip peripherals for the demo's functionality. */

void SetupHardware(void)

{

#if (ARCH == ARCH_AVR8)

/* Disable watchdog if enabled by bootloader/fuses */

MCUSR &= ~(1 << WDRF);

wdt_disable();


/* Disable clock division */

clock_prescale_set(clock_div_1);

#endif


/* Hardware Initialization */

// LEDs_Init();

// Buttons_Init();

ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);

ADC_SetupChannel(MIC_IN_ADC_CHANNEL);

USB_Init();


/* Start the ADC conversion in free running mode */

ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_GET_CHANNEL_MASK(MIC_IN_ADC_CHANNEL));

}


/** ISR to handle the reloading of the data endpoint with the next sample. */

ISR(TIMER0_COMPA_vect, ISR_BLOCK)

{

uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();


/* Check that the USB bus is ready for the next sample to write */

if (Audio_Device_IsReadyForNextSample(&Microphone_Audio_Interface))

{

int16_t AudioSample;



/* Audio sample is ADC value scaled to fit the entire range */

AudioSample = ((SAMPLE_MAX_RANGE / ADC_MAX_RANGE) * ADC_GetResult());


#if defined(MICROPHONE_BIASED_TO_HALF_RAIL)

/* Microphone is biased to half rail voltage, subtract the bias from the sample value */

AudioSample -= (SAMPLE_MAX_RANGE / 2);

#endif


Audio_Device_WriteSample16(&Microphone_Audio_Interface, AudioSample);

}


Endpoint_SelectEndpoint(PrevEndpoint);

}


/** Event handler for the library USB Connection event. */

void EVENT_USB_Device_Connect(void)

{

//LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);


/* Sample reload timer initialization */

TIMSK0  = (1 << OCIE0A);

OCR0A   = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);

TCCR0A  = (1 << WGM01);  // CTC mode

TCCR0B  = (1 << CS01);   // Fcpu/8 speed

}


/** Event handler for the library USB Disconnection event. */

void EVENT_USB_Device_Disconnect(void)

{

/* Stop the sample reload timer */

TCCR0B = 0;


//LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

}


/** Event handler for the library USB Configuration Changed event. */

void EVENT_USB_Device_ConfigurationChanged(void)

{

bool ConfigSuccess = true;


ConfigSuccess &= Audio_Device_ConfigureEndpoints(&Microphone_Audio_Interface);


//LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);

}


/** Event handler for the library USB Control Request reception event. */

void EVENT_USB_Device_ControlRequest(void)

{

Audio_Device_ProcessControlRequest(&Microphone_Audio_Interface);

}


/** Audio class driver callback for the setting and retrieval 
of streaming endpoint properties. This callback must be implemented

 *  in the user application to handle property manipulations on streaming audio endpoints.

 *

 *  When the DataLength parameter is NULL, this callback should only 
indicate whether the specified operation is valid for

 *  the given endpoint index, and should return as fast as possible.
 When non-NULL, this value may be altered for GET operations

 *  to indicate the size of the retrieved data.

 *

 *  note The length of the retrieved data stored into the Data buffer
 on GET operations should not exceed the initial value

 *        of the c DataLength parameter.

 *

 *  param[in,out] AudioInterfaceInfo  Pointer to a structure 
containing an Audio Class configuration and state.

 *  param[in]     EndpointProperty    Property of the endpoint to get or set, 
a value from Audio_ClassRequests_t.

 *  param[in]     EndpointAddress     Address of the streaming endpoint 
whose property is being referenced.

 *  param[in]     EndpointControl     Parameter of the endpoint to get or set, 
a value from Audio_EndpointControls_t.

 *  param[in,out] DataLength          For SET operations, the length of the parameter 
data to set. For GET operations, the maximum

 *                                     length of the retrieved data. When NULL, 
the function should return whether the given property

 *                                     and parameter is valid for the requested endpoint
 without reading or modifying the Data buffer.

 *  param[in,out] Data                Pointer to a location where the parameter
 data is stored for SET operations, or where

 *                                     the retrieved data is to be stored for GET operations.

 *

 *  return Boolean c true if the property get/set was successful, c false otherwise

 */

bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,

                                                  const uint8_t EndpointProperty,

                                                  const uint8_t EndpointAddress,

                                                  const uint8_t EndpointControl,

                                                  uint16_t* const DataLength,

                                                  uint8_t* Data)

{

/* Check the requested endpoint to see if a supported endpoint is being manipulated */

if (EndpointAddress == Microphone_Audio_Interface.Config.DataINEndpoint.Address)

{

/* Check the requested control to see if a supported control is being manipulated */

if (EndpointControl == AUDIO_EPCONTROL_SamplingFreq)

{

switch (EndpointProperty)

{

case AUDIO_REQ_SetCurrent:

/* Check if we are just testing for a valid property, or actually adjusting it */

if (DataLength != NULL)

{

/* Set the new sampling frequency to the value given by the host */

CurrentAudioSampleFrequency = (((uint32_t)Data[2] << 16) | ((uint32_t)Data[1] << 8) | (uint32_t)Data[0]);


/* Adjust sample reload timer to the new frequency */

OCR0A = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);

}


return true;

case AUDIO_REQ_GetCurrent:

/* Check if we are just testing for a valid property, or actually reading it */

if (DataLength != NULL)

{

*DataLength = 3;


Data[2] = (CurrentAudioSampleFrequency >> 16);

Data[1] = (CurrentAudioSampleFrequency >> 8);

Data[0] = (CurrentAudioSampleFrequency &  0xFF);

}


return true;

}

}

}


return false;

}


/** Audio class driver callback for the setting and retrieval of 
streaming interface properties. This callback must be implemented

 *  in the user application to handle property manipulations on streaming audio interfaces.

 *

 *  When the DataLength parameter is NULL, this callback should only 
indicate whether the specified operation is valid for

 *  the given entity and should return as fast as possible. When non-NULL,
 this value may be altered for GET operations

 *  to indicate the size of the retrieved data.

 *

 *  note The length of the retrieved data stored into the Data buffer 
on GET operations should not exceed the initial value

 *        of the c DataLength parameter.

 *

 *  param[in,out] AudioInterfaceInfo  Pointer to a structure 
containing an Audio Class configuration and state.

 *  param[in]     Property            Property of the interface 
to get or set, a value from Audio_ClassRequests_t.

 *  param[in]     EntityAddress       Address of the audio entity whose property is being referenced.

 *  param[in]     Parameter           Parameter of the entity to get or set, 
specific to each type of entity (see USB Audio specification).

 *  param[in,out] DataLength          For SET operations, the length of the parameter 
data to set. For GET operations, the maximum

 *                                     length of the retrieved data. When NULL, 
the function should return whether the given property

 *                                     and parameter is valid for the requested 
endpoint without reading or modifying the Data buffer.

 *  param[in,out] Data                Pointer to a location where 
the parameter data is stored for SET operations, or where

 *                                     the retrieved data is to be stored for GET operations.

 *

 *  return Boolean c true if the property GET/SET was successful, c false otherwise

 */

bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,

                                                   const uint8_t Property,

                                                   const uint8_t EntityAddress,

                                                   const uint16_t Parameter,

                                                   uint16_t* const DataLength,

                                                   uint8_t* Data)

{

/* No audio interface entities in the device descriptor, thus no properties to get or set. */

return false;

}

###

 


Project Datasheet

https://www.engineersgarage.com/wp-content/uploads/2019/10/AudioInput.zip


Project Video


Filed Under: Electronic Projects

 

Next Article

← Previous Article
Next Article →

Questions related to this article?
👉Ask and discuss on Electro-Tech-Online.com and EDAboard.com forums.



Tell Us What You Think!! Cancel reply

You must be logged in to post a comment.

EE TECH TOOLBOX

“ee
Tech Toolbox: Internet of Things
Explore practical strategies for minimizing attack surfaces, managing memory efficiently, and securing firmware. Download now to ensure your IoT implementations remain secure, efficient, and future-ready.

EE Learning Center

EE Learning Center
“engineers
EXPAND YOUR KNOWLEDGE AND STAY CONNECTED
Get the latest info on technologies, tools and strategies for EE professionals.

HAVE A QUESTION?

Have a technical question about an article or other engineering questions? Check out our engineering forums EDABoard.com and Electro-Tech-Online.com where you can get those questions asked and answered by your peers!


RSS EDABOARD.com Discussions

  • surge+EMI filter
  • Input impedance matching network
  • How to preserve hierarchical instance names like \adder_1/U1 in flattened gate-level netlist in Design Compiler?
  • Can anyone provide a guide or tutorial for Candece simulation?
  • Voltage mode pushpull is a nonsense SMPS?

RSS Electro-Tech-Online.com Discussions

  • Can I make two inputs from one??
  • Photo interrupter Connections
  • Is AI making embedded software developers more productive?
  • Why can't I breadboard this oscillator?
  • Cataract Lens Options?

Featured – RPi Python Programming (27 Part)

  • RPi Python Programming 21: The SIM900A AT commands
  • RPi Python Programming 22: Calls & SMS using a SIM900A GSM-GPRS modem
  • RPi Python Programming 23: Interfacing a NEO-6MV2 GPS module with Raspberry Pi
  • RPi Python Programming 24: I2C explained
  • RPi Python Programming 25 – Synchronous serial communication in Raspberry Pi using I2C protocol
  • RPi Python Programming 26 – Interfacing ADXL345 accelerometer sensor with Raspberry Pi

Recent Articles

  • GigaDevice launches GD32C231 MCU series with 48MHz Cortex-M23 core and 64KB Flash
  • Advanced Energy releases 425 W CF-rated medical power supply in 3.5 x 6 x 1.5-inch format”
  • LEM combines shunt and Hall effect sensing in 2000 A current measurement unit
  • What is AWS IoT Core and when should you use it?
  • AC-DC power supply extends voltage range to 800 V DC

EE ENGINEERING TRAINING DAYS

engineering

Submit a Guest Post

submit a guest post
Engineers Garage
  • Analog IC TIps
  • Connector Tips
  • Battery Power Tips
  • DesignFast
  • EDABoard Forums
  • EE World Online
  • Electro-Tech-Online Forums
  • EV Engineering
  • Microcontroller Tips
  • Power Electronic Tips
  • Sensor Tips
  • Test and Measurement Tips
  • 5G Technology World
  • Subscribe to our newsletter
  • About Us
  • Contact Us
  • Advertise

Copyright © 2025 WTWH Media LLC. All Rights Reserved. The material on this site may not be reproduced, distributed, transmitted, cached or otherwise used, except with the prior written permission of WTWH Media
Privacy Policy

Search Engineers Garage

  • Electronic Projects & Tutorials
    • Electronic Projects
      • Arduino Projects
      • AVR
      • Raspberry pi
      • ESP8266
      • BeagleBone
      • 8051 Microcontroller
      • ARM
      • PIC Microcontroller
      • STM32
    • Tutorials
      • Audio Electronics
      • Battery Management
      • Brainwave
      • Electric Vehicles
      • EMI/EMC/RFI
      • Hardware Filters
      • IoT tutorials
      • Power Tutorials
      • Python
      • Sensors
      • USB
      • VHDL
    • Circuit Design
    • Project Videos
    • Components
  • Articles
    • Tech Articles
    • Insight
    • Invention Stories
    • How to
    • What Is
  • News
    • Electronic Product News
    • Business News
    • Company/Start-up News
    • DIY Reviews
    • Guest Post
  • Forums
    • EDABoard.com
    • Electro-Tech-Online
    • EG Forum Archive
  • DigiKey Store
    • Cables, Wires
    • Connectors, Interconnect
    • Discrete
    • Electromechanical
    • Embedded Computers
    • Enclosures, Hardware, Office
    • Integrated Circuits (ICs)
    • Isolators
    • LED/Optoelectronics
    • Passive
    • Power, Circuit Protection
    • Programmers
    • RF, Wireless
    • Semiconductors
    • Sensors, Transducers
    • Test Products
    • Tools
  • Learn
    • eBooks/Tech Tips
    • Design Guides
    • Learning Center
    • Tech Toolboxes
    • Webinars & Digital Events
  • Resources
    • Digital Issues
    • EE Training Days
    • LEAP Awards
    • Podcasts
    • Webinars / Digital Events
    • White Papers
    • Engineering Diversity & Inclusion
    • DesignFast
  • Guest Post Guidelines
  • Advertise
  • Subscribe