aboutsummaryrefslogtreecommitdiffstats
path: root/Demos/Device
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2011-06-03 07:56:12 +0000
committerDean Camera <dean@fourwalledcubicle.com>2011-06-03 07:56:12 +0000
commit2731c3a8aef715c2ea27d541e946200bd4fc189f (patch)
treed56ff72432af73136b6c5a8c5fd9fa14da9b9852 /Demos/Device
parentc2135f2776e01842a775502c24b59d9169ffa851 (diff)
downloadlufa-2731c3a8aef715c2ea27d541e946200bd4fc189f.tar.gz
lufa-2731c3a8aef715c2ea27d541e946200bd4fc189f.tar.bz2
lufa-2731c3a8aef715c2ea27d541e946200bd4fc189f.zip
Added new callback to the Audio Class driver to allow for endpoint control manipulations such as data sample rates.
Modified the Class Driver AudioInput and AudioOutput demos to support multiple sample rates. Fixed KeyboardHost and KeyboardHostWithParser demos displaying incorrect values when numerical keys were pressed. Fix broken LowLevel audio demo descriptors. Minor documentation fixes.
Diffstat (limited to 'Demos/Device')
-rw-r--r--Demos/Device/ClassDriver/AudioInput/AudioInput.c74
-rw-r--r--Demos/Device/ClassDriver/AudioInput/Descriptors.c17
-rw-r--r--Demos/Device/ClassDriver/AudioInput/Descriptors.h5
-rw-r--r--Demos/Device/ClassDriver/AudioOutput/AudioOutput.c74
-rw-r--r--Demos/Device/ClassDriver/AudioOutput/Descriptors.c16
-rw-r--r--Demos/Device/ClassDriver/AudioOutput/Descriptors.h5
-rw-r--r--Demos/Device/LowLevel/AudioInput/Descriptors.c4
-rw-r--r--Demos/Device/LowLevel/AudioOutput/Descriptors.c4
8 files changed, 177 insertions, 22 deletions
diff --git a/Demos/Device/ClassDriver/AudioInput/AudioInput.c b/Demos/Device/ClassDriver/AudioInput/AudioInput.c
index b197588a8..58a3668e8 100644
--- a/Demos/Device/ClassDriver/AudioInput/AudioInput.c
+++ b/Demos/Device/ClassDriver/AudioInput/AudioInput.c
@@ -51,6 +51,9 @@ USB_ClassInfo_Audio_Device_t Microphone_Audio_Interface =
},
};
+/** Current audio sampling frequency of the streaming audio endpoint. */
+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.
@@ -133,7 +136,7 @@ void EVENT_USB_Device_Connect(void)
/* 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
}
@@ -163,3 +166,72 @@ 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 retreived 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] EndpointIndex Index 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 true if the property get/set was successful, false otherwise
+ */
+bool CALLBACK_Audio_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const uint8_t EndpointProperty,
+ const uint8_t EndpointIndex,
+ 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 (EndpointIndex == Microphone_Audio_Interface.Config.DataINEndpointNumber)
+ {
+ /* Check the requested control to see if a supported control is being manipulated */
+ if (EndpointControl == AUDIO_EPCONTROL_SamplingFreq)
+ {
+ /* Check the requested property to see if a supported property is being manipulated */
+ if (EndpointProperty == 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;
+ }
+ else if (EndpointProperty == 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;
+}
diff --git a/Demos/Device/ClassDriver/AudioInput/Descriptors.c b/Demos/Device/ClassDriver/AudioInput/Descriptors.c
index bd31bdb0e..6fffd05d4 100644
--- a/Demos/Device/ClassDriver/AudioInput/Descriptors.c
+++ b/Demos/Device/ClassDriver/AudioInput/Descriptors.c
@@ -54,7 +54,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
- .ProductID = 0x2047,
+ .ProductID = 0x206B,
.ReleaseNumber = VERSION_BCD(00.01),
.ManufacturerStrIndex = 0x01,
@@ -191,7 +191,9 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Audio_AudioFormat =
{
- .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t) +
+ sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates),
+ .Type = DTYPE_CSInterface},
.Subtype = AUDIO_DSUBTYPE_CSInterface_FormatType,
.FormatType = 0x01,
@@ -199,12 +201,17 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.SubFrameSize = 0x02,
.BitResolution = 16,
- .TotalDiscreteSampleRates = 1,
+
+ .TotalDiscreteSampleRates = (sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates) / sizeof(USB_Audio_SampleFreq_t))
},
.Audio_AudioFormatSampleRates =
{
- AUDIO_SAMPLE_FREQ(AUDIO_SAMPLE_FREQUENCY)
+ AUDIO_SAMPLE_FREQ(8000),
+ AUDIO_SAMPLE_FREQ(11025),
+ AUDIO_SAMPLE_FREQ(22050),
+ AUDIO_SAMPLE_FREQ(44100),
+ AUDIO_SAMPLE_FREQ(48000),
},
.Audio_StreamEndpoint =
@@ -228,7 +235,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Spc_t), .Type = DTYPE_CSEndpoint},
.Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
- .Attributes = AUDIO_EP_ACCEPTS_SMALL_PACKETS,
+ .Attributes = (AUDIO_EP_ACCEPTS_SMALL_PACKETS | AUDIO_EP_SAMPLE_FREQ_CONTROL),
.LockDelayUnits = 0x00,
.LockDelay = 0x0000
diff --git a/Demos/Device/ClassDriver/AudioInput/Descriptors.h b/Demos/Device/ClassDriver/AudioInput/Descriptors.h
index 82dbd517f..05d1fee36 100644
--- a/Demos/Device/ClassDriver/AudioInput/Descriptors.h
+++ b/Demos/Device/ClassDriver/AudioInput/Descriptors.h
@@ -51,9 +51,6 @@
*/
#define AUDIO_STREAM_EPSIZE ENDPOINT_MAX_SIZE(AUDIO_STREAM_EPNUM)
- /** Sample frequency of the data being transmitted through the streaming endpoint. */
- #define AUDIO_SAMPLE_FREQUENCY 48000
-
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
@@ -70,7 +67,7 @@
USB_Descriptor_Interface_t Audio_StreamInterface_Alt1;
USB_Audio_Descriptor_Interface_AS_t Audio_StreamInterface_SPC;
USB_Audio_Descriptor_Format_t Audio_AudioFormat;
- USB_Audio_SampleFreq_t Audio_AudioFormatSampleRates[1];
+ USB_Audio_SampleFreq_t Audio_AudioFormatSampleRates[5];
USB_Audio_Descriptor_StreamEndpoint_Std_t Audio_StreamEndpoint;
USB_Audio_Descriptor_StreamEndpoint_Spc_t Audio_StreamEndpoint_SPC;
} USB_Descriptor_Configuration_t;
diff --git a/Demos/Device/ClassDriver/AudioOutput/AudioOutput.c b/Demos/Device/ClassDriver/AudioOutput/AudioOutput.c
index dbfd10b8b..43267b2a7 100644
--- a/Demos/Device/ClassDriver/AudioOutput/AudioOutput.c
+++ b/Demos/Device/ClassDriver/AudioOutput/AudioOutput.c
@@ -51,6 +51,9 @@ USB_ClassInfo_Audio_Device_t Speaker_Audio_Interface =
},
};
+/** Current audio sampling frequency of the streaming audio endpoint. */
+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.
@@ -135,7 +138,7 @@ void EVENT_USB_Device_Connect(void)
/* 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
@@ -199,3 +202,72 @@ void EVENT_USB_Device_ControlRequest(void)
Audio_Device_ProcessControlRequest(&Speaker_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 retreived 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] EndpointIndex Index 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 true if the property get/set was successful, false otherwise
+ */
+bool CALLBACK_Audio_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const uint8_t EndpointProperty,
+ const uint8_t EndpointIndex,
+ 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 (EndpointIndex == Speaker_Audio_Interface.Config.DataOUTEndpointNumber)
+ {
+ /* Check the requested control to see if a supported control is being manipulated */
+ if (EndpointControl == AUDIO_EPCONTROL_SamplingFreq)
+ {
+ /* Check the requested property to see if a supported property is being manipulated */
+ if (EndpointProperty == 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;
+ }
+ else if (EndpointProperty == 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;
+}
diff --git a/Demos/Device/ClassDriver/AudioOutput/Descriptors.c b/Demos/Device/ClassDriver/AudioOutput/Descriptors.c
index e46c3c023..5bb0e9f11 100644
--- a/Demos/Device/ClassDriver/AudioOutput/Descriptors.c
+++ b/Demos/Device/ClassDriver/AudioOutput/Descriptors.c
@@ -54,7 +54,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
- .ProductID = 0x2046,
+ .ProductID = 0x206C,
.ReleaseNumber = VERSION_BCD(00.01),
.ManufacturerStrIndex = 0x01,
@@ -191,7 +191,9 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Audio_AudioFormat =
{
- .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t) +
+ sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates),
+ .Type = DTYPE_CSInterface},
.Subtype = AUDIO_DSUBTYPE_CSInterface_FormatType,
.FormatType = 0x01,
@@ -200,12 +202,16 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.SubFrameSize = 0x02,
.BitResolution = 16,
- .TotalDiscreteSampleRates = 1,
+ .TotalDiscreteSampleRates = (sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates) / sizeof(USB_Audio_SampleFreq_t)),
},
.Audio_AudioFormatSampleRates =
{
- AUDIO_SAMPLE_FREQ(AUDIO_SAMPLE_FREQUENCY)
+ AUDIO_SAMPLE_FREQ(8000),
+ AUDIO_SAMPLE_FREQ(11025),
+ AUDIO_SAMPLE_FREQ(22050),
+ AUDIO_SAMPLE_FREQ(44100),
+ AUDIO_SAMPLE_FREQ(48000),
},
.Audio_StreamEndpoint =
@@ -229,7 +235,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Spc_t), .Type = DTYPE_CSEndpoint},
.Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
- .Attributes = AUDIO_EP_ACCEPTS_SMALL_PACKETS,
+ .Attributes = (AUDIO_EP_ACCEPTS_SMALL_PACKETS | AUDIO_EP_SAMPLE_FREQ_CONTROL),
.LockDelayUnits = 0x00,
.LockDelay = 0x0000
diff --git a/Demos/Device/ClassDriver/AudioOutput/Descriptors.h b/Demos/Device/ClassDriver/AudioOutput/Descriptors.h
index b4b8db6a4..ca5c87386 100644
--- a/Demos/Device/ClassDriver/AudioOutput/Descriptors.h
+++ b/Demos/Device/ClassDriver/AudioOutput/Descriptors.h
@@ -51,9 +51,6 @@
*/
#define AUDIO_STREAM_EPSIZE ENDPOINT_MAX_SIZE(AUDIO_STREAM_EPNUM)
- /** Sample frequency of the data being transmitted through the streaming endpoint. */
- #define AUDIO_SAMPLE_FREQUENCY 48000
-
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
@@ -70,7 +67,7 @@
USB_Descriptor_Interface_t Audio_StreamInterface_Alt1;
USB_Audio_Descriptor_Interface_AS_t Audio_StreamInterface_SPC;
USB_Audio_Descriptor_Format_t Audio_AudioFormat;
- USB_Audio_SampleFreq_t Audio_AudioFormatSampleRates[1];
+ USB_Audio_SampleFreq_t Audio_AudioFormatSampleRates[5];
USB_Audio_Descriptor_StreamEndpoint_Std_t Audio_StreamEndpoint;
USB_Audio_Descriptor_StreamEndpoint_Spc_t Audio_StreamEndpoint_SPC;
} USB_Descriptor_Configuration_t;
diff --git a/Demos/Device/LowLevel/AudioInput/Descriptors.c b/Demos/Device/LowLevel/AudioInput/Descriptors.c
index 6c8323c56..8a63d7736 100644
--- a/Demos/Device/LowLevel/AudioInput/Descriptors.c
+++ b/Demos/Device/LowLevel/AudioInput/Descriptors.c
@@ -191,7 +191,9 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Audio_AudioFormat =
{
- .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t) +
+ sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates),
+ .Type = DTYPE_CSInterface},
.Subtype = AUDIO_DSUBTYPE_CSInterface_FormatType,
.FormatType = 0x01,
diff --git a/Demos/Device/LowLevel/AudioOutput/Descriptors.c b/Demos/Device/LowLevel/AudioOutput/Descriptors.c
index 9c57a421f..59e3af1dd 100644
--- a/Demos/Device/LowLevel/AudioOutput/Descriptors.c
+++ b/Demos/Device/LowLevel/AudioOutput/Descriptors.c
@@ -191,7 +191,9 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.Audio_AudioFormat =
{
- .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_Format_t) +
+ sizeof(ConfigurationDescriptor.Audio_AudioFormatSampleRates),
+ .Type = DTYPE_CSInterface},
.Subtype = AUDIO_DSUBTYPE_CSInterface_FormatType,
.FormatType = 0x01,