blob: 8c8e623dc7fca1d25f453da0a908a6d35997d8ea [file] [log] [blame]
/**
* \file
*
* \brief Audio sample processing functions
*
* Copyright (C) 2011 Atmel Corporation. All rights reserved.
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel AVR product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include "compiler.h"
#include "preprocessor.h"
#include "board.h"
#include "conf_example.h"
#include "conf_usb.h"
#include "gpio.h"
#include "sample_processor.h"
#include "dac.h"
void sample_processor_init(void)
{
/* Create DAC configuration:
* - 1V from bandgap as reference, left adjusted channel value
* - one active DAC channel, no internal output
* - conversions triggered by event channel 0
* - 1 us conversion intervals
*/
struct dac_config dac_conf;
dac_set_conversion_parameters(&dac_conf, DAC_REF_BANDGAP, DAC_ADJ_LEFT);
dac_set_active_channel(&dac_conf, SPEAKER_DAC_CHANNEL, 0);
dac_set_conversion_trigger(&dac_conf, SPEAKER_DAC_CHANNEL, 0);
dac_set_conversion_interval(&dac_conf, 1);
dac_write_configuration(&SPEAKER_DAC, &dac_conf);
dac_enable(&SPEAKER_DAC);
// Configure timer/counter to generate events at sample rate.
sysclk_enable_module(SYSCLK_PORT_C, SYSCLK_TC0);
TCC0.PER = (sysclk_get_per_hz() / UDI_AUDIO_SAMPLE_RATE) - 1;
// Configure event channel 0 to generate events upon T/C overflow.
sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
EVSYS.CH0MUX = EVSYS_CHMUX_TCC0_OVF_gc;
// Start the timer/counter.
TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
}
void sample_processor_output_samples(uint16_t *samples, uint8_t count)
{
// Process each sample in the datastream
for (uint8_t i = 0; i < count; i += 2)
{
// Two channels (left and right) are encoded together to form a sample pair
int16_t sample_left = le16_to_cpu(samples[i]);
int16_t sample_right = le16_to_cpu(samples[i + 1]);
// Perform simple mono mixing of the two channels
int16_t sample_mono = ((sample_left >> 1) + (sample_right >> 1));
// Wait for the DAC to become ready to accept the next sample
dac_wait_for_channel_ready(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL);
// Output mixed sample - output should be unsigned, so we have to offset half the
// total range (flip highest bit) to get the correct sample value for the DAC
dac_set_channel_value(&SPEAKER_DAC, SPEAKER_DAC_CHANNEL, sample_mono ^ (1 << 15));
}
}