Commit 08de7578 authored by Dean Camera's avatar Dean Camera
Browse files

Changed AudioInput and AudioOutput demos to reload the next sample via an...

Changed AudioInput and AudioOutput demos to reload the next sample via an interrupt rather than polling the sample timer.
parent 55538dce
......@@ -63,8 +63,6 @@ int main(void)
for (;;)
{
ProcessNextSample();
Audio_Device_USBTask(&Microphone_Audio_Interface);
USB_USBTask();
}
......@@ -91,17 +89,14 @@ void SetupHardware(void)
ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | MIC_IN_ADC_MUX_MASK);
}
/** Processes the next audio sample by reading the last ADC conversion and writing it to the audio
* interface, each time the sample reload timer period elapses to give a constant sample rate.
*/
void ProcessNextSample(void)
/** 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 if the sample reload timer period has elapsed, and that the USB bus is ready for a new sample */
if ((TIFR0 & (1 << OCF0A)) && Audio_Device_IsReadyForNextSample(&Microphone_Audio_Interface))
if (Audio_Device_IsReadyForNextSample(&Microphone_Audio_Interface))
{
/* Clear the sample reload timer compare flag, ready for the next interval */
TIFR0 |= (1 << OCF0A);
int16_t AudioSample;
#if defined(USE_TEST_TONE)
......@@ -126,6 +121,8 @@ void ProcessNextSample(void)
Audio_Device_WriteSample16(&Microphone_Audio_Interface, AudioSample);
}
Endpoint_SelectEndpoint(PrevEndpoint);
}
/** Event handler for the library USB Connection event. */
......@@ -134,6 +131,7 @@ void EVENT_USB_Device_Connect(void)
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
TIMSK0 = (1 << OCIE0A);
OCR0A = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
......
......@@ -77,7 +77,6 @@
/* Function Prototypes: */
void SetupHardware(void);
void ProcessNextSample(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
......
......@@ -63,8 +63,6 @@ int main(void)
for (;;)
{
ProcessNextSample();
Audio_Device_USBTask(&Speaker_Audio_Interface);
USB_USBTask();
}
......@@ -85,35 +83,31 @@ void SetupHardware(void)
USB_Init();
}
/** Processes the next audio sample by reading the last ADC conversion and writing it to the audio
* interface, each time the sample reload timer period elapses to give a constant sample rate.
*/
void ProcessNextSample(void)
/** ISR to handle the reloading of the PWM timer with the next sample. */
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
/* Check if the sample reload timer period has elapsed, and that the USB bus is ready for a new sample */
if ((TIFR0 & (1 << OCF0A)) && Audio_Device_IsSampleReceived(&Speaker_Audio_Interface))
{
/* Clear the sample reload timer compare flag, ready for the next interval */
TIFR0 |= (1 << OCF0A);
uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
if (Audio_Device_IsSampleReceived(&Speaker_Audio_Interface))
{
/* Retrieve the signed 16-bit left and right audio samples, convert to 8-bit */
int8_t LeftSample_8Bit = (Audio_Device_ReadSample16(&Speaker_Audio_Interface) >> 8);
int8_t RightSample_8Bit = (Audio_Device_ReadSample16(&Speaker_Audio_Interface) >> 8);
int8_t LeftSample_8Bit = (Audio_Device_ReadSample16(&Speaker_Audio_Interface) >> 8);
int8_t RightSample_8Bit = (Audio_Device_ReadSample16(&Speaker_Audio_Interface) >> 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);
int8_t MixedSample_8Bit = (((int16_t)LeftSample_8Bit + (int16_t)RightSample_8Bit) >> 1);
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Load the sample into the PWM timer channel */
OCR3A = (MixedSample_8Bit ^ (1 << 7));
#elif defined(AUDIO_OUT_STEREO)
#elif defined(AUDIO_OUT_STEREO)
/* Load the dual 8-bit samples into the PWM timer channels */
OCR3A = (LeftSample_8Bit ^ (1 << 7));
OCR3B = (RightSample_8Bit ^ (1 << 7));
#elif defined(AUDIO_OUT_PORTC)
#elif defined(AUDIO_OUT_PORTC)
/* Load the 8-bit mixed sample into PORTC */
PORTC = MixedSample_8Bit;
#endif
#endif
uint8_t LEDMask = LEDS_NO_LEDS;
......@@ -129,6 +123,8 @@ void ProcessNextSample(void)
LEDs_SetAllLEDs(LEDMask);
}
Endpoint_SelectEndpoint(PrevEndpoint);
}
/** Event handler for the library USB Connection event. */
......@@ -137,27 +133,28 @@ void EVENT_USB_Device_Connect(void)
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
TIMSK0 = (1 << OCIE0A);
OCR0A = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Set speaker as output */
DDRC |= (1 << 6);
#elif defined(AUDIO_OUT_STEREO)
#elif defined(AUDIO_OUT_STEREO)
/* Set speakers as outputs */
DDRC |= ((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
#elif defined(AUDIO_OUT_PORTC)
/* Set PORTC as outputs */
DDRC |= 0xFF;
#endif
#endif
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
/* PWM speaker timer initialization */
TCCR3A = ((1 << WGM30) | (1 << COM3A1) | (1 << COM3A0)
| (1 << COM3B1) | (1 << COM3B0)); // Set on match, clear on TOP
TCCR3B = ((1 << WGM32) | (1 << CS30)); // Fast 8-Bit PWM, F_CPU speed
#endif
#endif
}
/** Event handler for the library USB Disconnection event. */
......@@ -168,21 +165,21 @@ void EVENT_USB_Device_Disconnect(void)
/* Stop the sample reload timer */
TCCR0B = 0;
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
/* Stop the PWM generation timer */
TCCR3B = 0;
#endif
#endif
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Set speaker as input to reduce current draw */
DDRC &= ~(1 << 6);
#elif defined(AUDIO_OUT_STEREO)
DDRC &= ~(1 << 6);
#elif defined(AUDIO_OUT_STEREO)
/* Set speakers as inputs to reduce current draw */
DDRC &= ~((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
DDRC &= ~((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
/* Set PORTC low */
PORTC = 0x00;
#endif
PORTC = 0x00;
#endif
}
/** Event handler for the library USB Configuration Changed event. */
......
......@@ -64,7 +64,6 @@
/* Function Prototypes: */
void SetupHardware(void);
void ProcessNextSample(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
......
......@@ -51,7 +51,6 @@ int main(void)
for (;;)
{
USB_Audio_Task();
USB_USBTask();
}
}
......@@ -86,6 +85,7 @@ void EVENT_USB_Device_Connect(void)
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
TIMSK0 = (1 << OCIE0A);
OCR0A = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
......@@ -145,26 +145,17 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
}
}
/** 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);
/* 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);
int16_t AudioSample;
#if defined(USE_TEST_TONE)
......@@ -197,5 +188,7 @@ void USB_Audio_Task(void)
Endpoint_ClearIN();
}
}
Endpoint_SelectEndpoint(PrevEndpoint);
}
......@@ -77,7 +77,6 @@
/* Function Prototypes: */
void SetupHardware(void);
void USB_Audio_Task(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
......
......@@ -51,7 +51,6 @@ int main(void)
for (;;)
{
USB_Audio_Task();
USB_USBTask();
}
}
......@@ -80,27 +79,28 @@ void EVENT_USB_Device_Connect(void)
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Sample reload timer initialization */
OCR0A = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
TIMSK0 = (1 << OCIE0A);
OCR0A = (F_CPU / 8 / AUDIO_SAMPLE_FREQUENCY) - 1;
TCCR0A = (1 << WGM01); // CTC mode
TCCR0B = (1 << CS01); // Fcpu/8 speed
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Set speaker as output */
DDRC |= (1 << 6);
#elif defined(AUDIO_OUT_STEREO)
DDRC |= (1 << 6);
#elif defined(AUDIO_OUT_STEREO)
/* Set speakers as outputs */
DDRC |= ((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
DDRC |= ((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
/* Set PORTC as outputs */
DDRC |= 0xFF;
#endif
DDRC |= 0xFF;
#endif
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
/* PWM speaker timer initialization */
TCCR3A = ((1 << WGM30) | (1 << COM3A1) | (1 << COM3A0)
| (1 << COM3B1) | (1 << COM3B0)); // Set on match, clear on TOP
TCCR3B = ((1 << WGM32) | (1 << CS30)); // Fast 8-Bit PWM, F_CPU speed
#endif
TCCR3A = ((1 << WGM30) | (1 << COM3A1) | (1 << COM3A0)
| (1 << COM3B1) | (1 << COM3B0)); // Set on match, clear on TOP
TCCR3B = ((1 << WGM32) | (1 << CS30)); // Fast 8-Bit PWM, F_CPU speed
#endif
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
......@@ -110,20 +110,20 @@ void EVENT_USB_Device_Disconnect(void)
{
/* Stop the timers */
TCCR0B = 0;
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
#if (defined(AUDIO_OUT_MONO) || defined(AUDIO_OUT_STEREO))
TCCR3B = 0;
#endif
#endif
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Set speaker as input to reduce current draw */
DDRC &= ~(1 << 6);
#elif defined(AUDIO_OUT_STEREO)
DDRC &= ~(1 << 6);
#elif defined(AUDIO_OUT_STEREO)
/* Set speakers as inputs to reduce current draw */
DDRC &= ~((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
DDRC &= ~((1 << 6) | (1 << 5));
#elif defined(AUDIO_OUT_PORTC)
/* Set PORTC low */
PORTC = 0x00;
#endif
PORTC = 0x00;
#endif
/* Indicate streaming audio interface not selected */
StreamingAudioInterfaceSelected = false;
......@@ -171,34 +171,23 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
}
}
/** Task to manage the Audio interface, reading in audio samples from the host, and outputting them to the speakers/LEDs as
* desired.
*/
void USB_Audio_Task(void)
/** ISR to handle the reloading of the PWM timer 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);
/* Check if the current endpoint can be read from (contains a packet) and that the next sample should be read */
if (Endpoint_IsOUTReceived() && (TIFR0 & (1 << OCF0A)))
/* Check if the current endpoint can be read from (contains a packet) and the host is sending data */
if (Endpoint_IsOUTReceived() && StreamingAudioInterfaceSelected)
{
/* Clear the sample reload timer */
TIFR0 |= (1 << OCF0A);
/* 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_Word_LE() >> 8);
int8_t RightSample_8Bit = ((int16_t)Endpoint_Read_Word_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);
int8_t MixedSample_8Bit = (((int16_t)LeftSample_8Bit + (int16_t)RightSample_8Bit) >> 1);
/* Check to see if the bank is now empty */
if (!(Endpoint_IsReadWriteAllowed()))
......@@ -207,17 +196,17 @@ void USB_Audio_Task(void)
Endpoint_ClearOUT();
}
#if defined(AUDIO_OUT_MONO)
#if defined(AUDIO_OUT_MONO)
/* Load the sample into the PWM timer channel */
OCR3A = (MixedSample_8Bit ^ (1 << 7));
#elif defined(AUDIO_OUT_STEREO)
#elif defined(AUDIO_OUT_STEREO)
/* Load the dual 8-bit samples into the PWM timer channels */
OCR3A = (LeftSample_8Bit ^ (1 << 7));
OCR3B = (RightSample_8Bit ^ (1 << 7));
#elif defined(AUDIO_OUT_PORTC)
#elif defined(AUDIO_OUT_PORTC)
/* Load the 8-bit mixed sample into PORTC */
PORTC = MixedSample_8Bit;
#endif
#endif
uint8_t LEDMask = LEDS_NO_LEDS;
......@@ -233,5 +222,7 @@ void USB_Audio_Task(void)
LEDs_SetAllLEDs(LEDMask);
}
Endpoint_SelectEndpoint(PrevEndpoint);
}
......@@ -63,7 +63,6 @@
/* Function Prototypes: */
void SetupHardware(void);
void USB_Audio_Task(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
......
......@@ -97,8 +97,8 @@
bool DataOUTPipeDoubleBank; /**< Indicates if the HID interface's OUT data pipe should use double banking. */
uint8_t HIDInterfaceProtocol; /**< HID interface protocol value to match against if a specific
* boot subclass protocol is required, a value from the \ref HID_BootProtocols_t
* enum.
* boot subclass protocol is required, a protocol value from the
* \ref HID_Descriptor_ClassSubclassProtocol_t enum.
*/
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
HID_ReportInfo_t* HIDParserData; /**< HID parser data to store the parsed HID report data, when boot protocol
......
......@@ -57,6 +57,7 @@
* - Better algorithm to extract and convert the internal device serial number into a string descriptor (if present)
* - All USB class drivers are now automatically included when LUFA/Drivers/USB.h is included, and no longer need to be seperately included
* - All LowLevel demos changed to use the constants and types defined in the USB class drivers
* - Changed AudioInput and AudioOutput demos to reload the next sample via an interrupt rather than polling the sample timer
*
* <b>Fixed:</b>
* - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment