Add extra LUFA TAR archive export exclusions.
[pub/USBasp.git] / Demos / Device / LowLevel / AudioOutput / AudioOutput.c
index 8260732..813108a 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2011.
+     Copyright (C) Dean Camera, 2012.
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
-  Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2012  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
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
 #include "AudioOutput.h"
 
 /** Flag to indicate if the streaming audio alternative interface has been selected by the host. */
 #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.
 
 /** Main program entry point. This routine contains the overall program flow, including initial
  *  setup of all components and the main program loop.
@@ -80,7 +84,7 @@ void EVENT_USB_Device_Connect(void)
 
        /* Sample reload timer initialization */
        TIMSK0 = (1 << OCIE0A);
 
        /* 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
 
        TCCR0A = (1 << WGM01);  // CTC mode
        TCCR0B = (1 << CS01);   // Fcpu/8 speed
 
@@ -168,6 +172,66 @@ void EVENT_USB_Device_ControlRequest(void)
                        }
 
                        break;
                        }
 
                        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 == (ENDPOINT_DIR_OUT | AUDIO_STREAM_EPNUM)) && (EndpointControl == AUDIO_EPCONTROL_SamplingFreq))
+                               {
+                                       uint8_t SampleRate[3];
+
+                                       Endpoint_ClearSETUP();
+                                       Endpoint_Read_Control_Stream_LE(SampleRate, sizeof(SampleRate));
+                                       Endpoint_ClearOUT();
+
+                                       /* 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_HOSTTODEVICE | 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 == (ENDPOINT_DIR_OUT | AUDIO_STREAM_EPNUM)) && (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;
        }
 }
 
        }
 }
 
@@ -183,8 +247,8 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
        if (Endpoint_IsOUTReceived() && StreamingAudioInterfaceSelected)
        {
                /* Retrieve the signed 16-bit left and right audio samples, convert to 8-bit */
        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);
 
                /* 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);
@@ -222,7 +286,7 @@ ISR(TIMER0_COMPA_vect, ISR_BLOCK)
 
                LEDs_SetAllLEDs(LEDMask);
        }
 
                LEDs_SetAllLEDs(LEDMask);
        }
-       
+
        Endpoint_SelectEndpoint(PrevEndpoint);
 }
 
        Endpoint_SelectEndpoint(PrevEndpoint);
 }