/*
LUFA Library
- Copyright (C) Dean Camera, 2010.
+ Copyright (C) Dean Camera, 2015.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ 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
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
- The author disclaim all warranties with regard to this
+ 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
#include "AudioOutput.h"
/** Flag to indicate if the streaming audio alternative interface has been selected by the host. */
-bool StreamingAudioInterfaceSelected = false;
+static bool StreamingAudioInterfaceSelected = false;
+
+/** 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.
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
- sei();
+ GlobalInterruptEnable();
for (;;)
{
/** 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();
/* Sample reload timer initialization */
TIMSK0 = (1 << OCIE0A);
- OCR0A = ((F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1);
+ OCR0A = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
bool ConfigSuccess = true;
/* Setup Audio Stream Endpoint */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPNUM, EP_TYPE_ISOCHRONOUS, ENDPOINT_DIR_OUT,
- AUDIO_STREAM_EPSIZE, ENDPOINT_BANK_DOUBLE);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(AUDIO_STREAM_EPADDR, EP_TYPE_ISOCHRONOUS, AUDIO_STREAM_EPSIZE, 2);
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
}
break;
+ case AUDIO_REQ_GetStatus:
+ /* Get Status request can be directed at either the interface or endpoint, neither is currently used
+ * according to the latest USB Audio 1.0 standard, but must be ACKed with no data when requested */
+ if ((USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) ||
+ (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT)))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case AUDIO_REQ_SetCurrent:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT))
+ {
+ /* Extract out the relevant request information to get the target Endpoint address and control being set */
+ uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
+ uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
+
+ /* Only handle SET CURRENT requests to the audio endpoint's sample frequency property */
+ if ((EndpointAddress == AUDIO_STREAM_EPADDR) && (EndpointControl == AUDIO_EPCONTROL_SamplingFreq))
+ {
+ uint8_t SampleRate[3];
+
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(SampleRate, sizeof(SampleRate));
+ Endpoint_ClearIN();
+
+ /* Set the new sampling frequency to the value given by the host */
+ CurrentAudioSampleFrequency = (((uint32_t)SampleRate[2] << 16) | ((uint32_t)SampleRate[1] << 8) | (uint32_t)SampleRate[0]);
+
+ /* Adjust sample reload timer to the new frequency */
+ OCR0A = ((F_CPU / 8 / CurrentAudioSampleFrequency) - 1);
+ }
+ }
+
+ break;
+ case AUDIO_REQ_GetCurrent:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT))
+ {
+ /* Extract out the relevant request information to get the target Endpoint address and control being retrieved */
+ uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
+ uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
+
+ /* Only handle GET CURRENT requests to the audio endpoint's sample frequency property */
+ if ((EndpointAddress == AUDIO_STREAM_EPADDR) && (EndpointControl == AUDIO_EPCONTROL_SamplingFreq))
+ {
+ uint8_t SampleRate[3];
+
+ /* Convert the sampling rate value into the 24-bit format the host expects for the property */
+ SampleRate[2] = (CurrentAudioSampleFrequency >> 16);
+ SampleRate[1] = (CurrentAudioSampleFrequency >> 8);
+ SampleRate[0] = (CurrentAudioSampleFrequency & 0xFF);
+
+ Endpoint_ClearSETUP();
+ Endpoint_Write_Control_Stream_LE(SampleRate, sizeof(SampleRate));
+ Endpoint_ClearOUT();
+ }
+ }
+
+ break;
}
}
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
/* Select the audio stream endpoint */
- Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);
+ Endpoint_SelectEndpoint(AUDIO_STREAM_EPADDR);
/* Check if the current endpoint can be read from (contains a packet) and the host is sending data */
if (Endpoint_IsOUTReceived() && StreamingAudioInterfaceSelected)
{
/* Retrieve the signed 16-bit left and right audio samples, convert to 8-bit */
- int8_t LeftSample_8Bit = ((int16_t)Endpoint_Read_Word_LE() >> 8);
- int8_t RightSample_8Bit = ((int16_t)Endpoint_Read_Word_LE() >> 8);
+ int8_t LeftSample_8Bit = ((int16_t)Endpoint_Read_16_LE() >> 8);
+ int8_t RightSample_8Bit = ((int16_t)Endpoint_Read_16_LE() >> 8);
/* Mix the two channels together to produce a mono, 8-bit sample */
int8_t MixedSample_8Bit = (((int16_t)LeftSample_8Bit + (int16_t)RightSample_8Bit) >> 1);
LEDs_SetAllLEDs(LEDMask);
}
-
+
Endpoint_SelectEndpoint(PrevEndpoint);
}