Update UC3 platform driver support to use the bitmasks defined in the header files...
[pub/USBasp.git] / Demos / Device / LowLevel / AudioInput / AudioInput.c
index eb29f34..e00b693 100644 (file)
@@ -1,21 +1,21 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
-              
+     Copyright (C) Dean Camera, 2011.
+
   dean [at] fourwalledcubicle [dot] com
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
 
-  Permission to use, copy, modify, distribute, and sell this 
+  Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
   software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in 
+  without fee, provided that the above copyright notice appear in
   all copies and that both that the copyright notice and this
   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 
+  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 disclaim all warranties with regard to this
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
 #include "AudioInput.h"
 
 /** Flag to indicate if the streaming audio alternative interface has been selected by the host. */
 #include "AudioInput.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.
@@ -48,10 +52,9 @@ int main(void)
 
        LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
        sei();
 
        LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
        sei();
-       
+
        for (;;)
        {
        for (;;)
        {
-               USB_Audio_Task();
                USB_USBTask();
        }
 }
                USB_USBTask();
        }
 }
@@ -65,13 +68,14 @@ void SetupHardware(void)
 
        /* Disable clock division */
        clock_prescale_set(clock_div_1);
 
        /* Disable clock division */
        clock_prescale_set(clock_div_1);
-       
+
        /* Hardware Initialization */
        LEDs_Init();
        /* Hardware Initialization */
        LEDs_Init();
+       Buttons_Init();
        ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);
        ADC_SetupChannel(MIC_IN_ADC_CHANNEL);
        USB_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 | MIC_IN_ADC_MUX_MASK);
 }
        /* Start the ADC conversion in free running mode */
        ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | MIC_IN_ADC_MUX_MASK);
 }
@@ -85,7 +89,8 @@ void EVENT_USB_Device_Connect(void)
        LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
 
        /* Sample reload timer initialization */
        LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
 
        /* Sample reload timer initialization */
-       OCR0A   = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
+       TIMSK0  = (1 << OCIE0A);
+       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
 }
@@ -120,11 +125,11 @@ void EVENT_USB_Device_ConfigurationChanged(void)
        LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
 }
 
        LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
 }
 
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific
- *  control requests that are not handled internally by the USB library (including the Audio class-specific
- *  requests) so that they can be handled appropriately for the application.
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ *  the device from the USB host before passing along unhandled control requests to the library for processing
+ *  internally.
  */
  */
-void EVENT_USB_Device_UnhandledControlRequest(void)
+void EVENT_USB_Device_ControlRequest(void)
 {
        /* Process General and Audio specific control requests */
        switch (USB_ControlRequest.bRequest)
 {
        /* Process General and Audio specific control requests */
        switch (USB_ControlRequest.bRequest)
@@ -134,47 +139,111 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
                        {
                                Endpoint_ClearSETUP();
                        if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
                        {
                                Endpoint_ClearSETUP();
-                               
+                               Endpoint_ClearStatusStage();
+
                                /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */
                                StreamingAudioInterfaceSelected = ((USB_ControlRequest.wValue) != 0);
                                /* Check if the host is enabling the audio interface (setting AlternateSetting to 1) */
                                StreamingAudioInterfaceSelected = ((USB_ControlRequest.wValue) != 0);
-                               
+                       }
+
+                       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;
                                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_DESCRIPTOR_DIR_IN | AUDIO_STREAM_EPNUM)) && (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 == (ENDPOINT_DESCRIPTOR_DIR_IN | 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;
        }
 }
 
        }
 }
 
-/** Task to manage the Audio interface, reading in ADC samples from the microphone, and them to the host. */
-void USB_Audio_Task(void)
+/** ISR to handle the reloading of the data endpoint with the next sample. */
+ISR(TIMER0_COMPA_vect, ISR_BLOCK)
 {
 {
-       /* Device must be connected and configured for the task to run */
-       if (USB_DeviceState != DEVICE_STATE_Configured)
-         return;
-
-       /* Check to see if the streaming interface is selected, if not the host is not receiving audio */
-       if (!(StreamingAudioInterfaceSelected))
-         return;
+       uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
 
        /* Select the audio stream endpoint */
        Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);
 
        /* Select the audio stream endpoint */
        Endpoint_SelectEndpoint(AUDIO_STREAM_EPNUM);
-       
-       /* Check if the current endpoint can be written to and that the next sample should be stored */
-       if (Endpoint_IsINReady() && (TIFR0 & (1 << OCF0A)))
+
+       /* Check if the current endpoint can be written to and that the audio interface is enabled */
+       if (Endpoint_IsINReady() && StreamingAudioInterfaceSelected)
        {
        {
-               /* Clear the sample reload timer */
-               TIFR0 |= (1 << OCF0A);
-
-               /* Audio sample is ADC value scaled to fit the entire range */
-               int16_t 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);
+               int16_t AudioSample;
+
+               #if defined(USE_TEST_TONE)
+                       static uint8_t SquareWaveSampleCount;
+                       static int16_t CurrentWaveValue;
+                       
+                       /* In test tone mode, generate a square wave at 1/256 of the sample rate */
+                       if (SquareWaveSampleCount++ == 0xFF)
+                         CurrentWaveValue ^= 0x8000;
+                       
+                       /* Only generate audio if the board button is being pressed */
+                       AudioSample = (Buttons_GetStatus() & BUTTONS_BUTTON1) ? CurrentWaveValue : 0;
+               #else
+                       /* 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          
                #endif
 
                /* Write the sample to the buffer */
                #endif
 
                /* Write the sample to the buffer */
-               Endpoint_Write_Word_LE(AudioSample);
+               Endpoint_Write_16_LE(AudioSample);
 
                /* Check to see if the bank is now full */
                if (!(Endpoint_IsReadWriteAllowed()))
 
                /* Check to see if the bank is now full */
                if (!(Endpoint_IsReadWriteAllowed()))
@@ -183,4 +252,7 @@ void USB_Audio_Task(void)
                        Endpoint_ClearIN();
                }
        }
                        Endpoint_ClearIN();
                }
        }
+
+       Endpoint_SelectEndpoint(PrevEndpoint);
 }
 }
+