📄 pcm.c
字号:
/***********************************************************************
* $Workfile: pcm.c $
* $Revision: 1.0 $
* $Author: AnvikE $
* $Date: Jul 03 2003 17:32:18 $
*
* Project: sdk75401 BSP (board support package)
*
* Description:
*
*
* Revision History:
* $Log:
***********************************************************************
*
* Copyright (c) 2002 Sharp Microelectronics of the Americas
*
* All rights reserved
*
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
**********************************************************************/
/*
* kev75401 board specific code
* location - [sharpmcu/software/csps/lh754xx/bsps/kev75401/include]
*/
#include "kev75401.h"
/*
* kev75401 pcm specific code
* location - .
*/
#include "pcm.h"
/*
* chip specific timer0 driver
* location - [sharpmcu/software/csps/lh754xx/include]
*/
#include "lh754xx_timer0_driver.h"
/*
* chip specific timer1/2 driver
* location - [sharpmcu/software/csps/lh754xx/include]
*/
#include "lh754xx_timer_driver.h"
/*
* application specific audio clip
* location - .
*/
#include "tone_1khz_pcm.h"
#include "majorscale_pcm.h"
#include "birthday_pcm.h"
/* current sound clip being played */
STATIC UNS_32 clip = 0;
/* current sample within the clip */
STATIC UNS_32 sample = 0;
/* pcm tp pwm audio driver */
STATIC PCM_DRIVER_T audio;
/* Create some types for accessing the device */
#define SPL ((TIMER0_REGS_T*)TIMER0_BASE)
#define NEG ((TIMER_REGS_T*)TIMER1_BASE)
#define POS ((TIMER_REGS_T*)TIMER2_BASE)
/************************************************************************
*
* Function: pcm_init_codec
*
* Purpose:
* Init the pcm codec.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
void pcm_init_codec (void* callback,
UNS_32 mode)
{
/* Array of sound clips */
static PCM_SOUND_CLIP_T sound[3];
/* name of the clip */
sound[0].name = (CHAR*)majorscale;
/* title of the clip */
sound[0].title = (CHAR*)"major scale-16bps-11025Hz\n";
/* size of the clip */
sound[0].size = (INT_32)majorscale_size;
/* rate at which the clip was sampled */
sound[0].sample_rate = (INT_32)11025;
/* full scale voltage value for 16 bit sample */
sound[0].full_scale_value = (UNS_32)32768;
/* each sample is 16bits or 2 bytes */
sound[0].sample_size = 2;
/* set up the maximum sample size */
sound[0].sample_mask = 0x7FFF;
/* name of the clip */
sound[1].name = (CHAR*)tone_1khz_pcm;
/* title of the clip */
sound[1].title = (CHAR*)"1Khz tone-16bps-8000Hz\n";
/* size of the clip */
sound[1].size = (INT_32)tone_1khz_size;
/* rate at which the clip was sampled */
sound[1].sample_rate = (INT_32)8000;
/* full scale voltage value for 16 bit sample */
sound[1].full_scale_value = (UNS_32)32768;
/* each sample is 16bits or 2 bytes */
sound[1].sample_size = 2;
/* set up the maximum sample size */
sound[1].sample_mask = 0x7FFF;
/* name of the clip */
sound[2].name = (CHAR*)birthday_pcm;
/* title of the clip */
sound[2].title = (CHAR*)"Rock and Roll-8bps-8000Hz\n";
/* size of the clip */
sound[2].size = (INT_32)23470;
/* rate at which the clip was sampled */
sound[2].sample_rate = (INT_32)8000;
/* full scale voltage value for 8 bit sample */
sound[2].full_scale_value = (UNS_32)128;
/* each sample is 16bits or 1 bytes */
sound[2].sample_size = 1;
/* set up the maximum sample size */
sound[2].sample_mask = 0x7F;
/* bind the sound clips into the driver */
audio.sound = sound;
/* init the max number of clips */
audio.nclips = 3;
/* bind the callback function */
audio.cb = (PFV)callback;
/* set up the filter mode - differential or single ended */
audio.mode = mode;
}
/************************************************************************
*
* Function: pcm_to_pwm_sample
*
* Purpose:
* Write a new PCM value to the to timer using a differential topology.
*
* Processing:
* Reads new sample from a PCM buffer, and writes the new value
* to the cmp0 register (on-time) on the timer.
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
void pcm_to_pwm_sample (void)
{
register INT_16 data;
register UNS_16 duty;
register UNS_32 full_scale_cnt = audio.sound[clip].full_scale_value;
register INT_32 max_cnts = audio.sound[clip].cnts_per_pulse;
register UNS_32 bytes_per_sample = audio.sound[clip].sample_size;
register UNS_16 size_mask = audio.sound[clip].sample_mask;
register UNS_32 mode = audio.mode;
/* Stop and clear the the timer */
SPL->ctrl &= ~_SBF(1,1);
/* Clear the timer */
SPL->ctrl |= _SBF(0,1);
if (bytes_per_sample == 1)
{
/* Get the new data sample */
data = *(INT_8*)&audio.sound[clip].name[sample];
/* Convert to unipolar format */
if(data < 0)
{
data ^= 0xFF;
data += 1;
/* Calculate the duty cycle in terms of counts */
duty = ((((UNS_8)data)*max_cnts)/(full_scale_cnt-1))+1;
if (data >= (full_scale_cnt-1))
{
duty = max_cnts-2;
}
else if (data < 10)
{
duty = 2;
}
duty &= size_mask;
/* write the data to differnt pins depeneding
on the mode */
if (mode == PCM_DIFFERENTIAL)
{
POS->cmp0 = (UNS_8)((max_cnts>>1)-(duty>>1));
NEG->cmp0 = (UNS_8)((duty>>1)+(max_cnts>>1));
}
else
{
POS->cmp0 = (UNS_8)(max_cnts>>1)-(duty>>1);
NEG->cmp0 = (UNS_8)(max_cnts>>1)-(duty>>1);
}
}
else
{
/* Calculate the duty cycle in terms of counts */
duty = ((((UNS_8)data)*max_cnts)/full_scale_cnt)+1;
if (data >= full_scale_cnt)
{
duty = max_cnts-2;
}
else if (data < 10)
{
duty = 2;
}
duty &= size_mask;
/* write the data to differnt pins depeneding
on the mode */
if (mode == PCM_DIFFERENTIAL)
{
POS->cmp0 = (UNS_8)((duty>>1)+(max_cnts>>1));
NEG->cmp0 = (UNS_8)((max_cnts>>1)-(duty>>1));
}
else
{
POS->cmp0 = (UNS_8)((duty>>1)+(max_cnts>>1));
NEG->cmp0 = (UNS_8)((duty>>1)+(max_cnts>>1));
}
}
}
else
{
/* Get the new data sample */
data = *(INT_16*)&audio.sound[clip].name[sample];
/* Convert to unipolar format */
if(data < 0)
{
data ^= 0xFFFF;
data += 1;
/* Calculate the duty cycle in terms of counts */
duty = ((((UNS_16)data)*max_cnts)/(full_scale_cnt-1))+1;
if (data >= (full_scale_cnt-1))
{
duty = max_cnts-2;
}
else if (data < 10)
{
duty = 2;
}
duty &= size_mask;
/* write the data to differnt pins depeneding
on the mode */
if (mode == PCM_DIFFERENTIAL)
{
POS->cmp0 = (UNS_16)((max_cnts>>1)-(duty>>1));
NEG->cmp0 = (UNS_16)((duty>>1)+(max_cnts>>1));
}
else
{
POS->cmp0 = (UNS_16)(max_cnts>>1)-(duty>>1);
NEG->cmp0 = (UNS_16)(max_cnts>>1)-(duty>>1);
}
}
else
{
/* Calculate the duty cycle in terms of counts */
duty = ((((UNS_16)data)*max_cnts)/full_scale_cnt)+1;
if (data >= full_scale_cnt)
{
duty = max_cnts-2;
}
else if (data < 10)
{
duty = 2;
}
duty &= size_mask;
/* write the data to differnt pins depeneding
on the mode */
if (mode == PCM_DIFFERENTIAL)
{
POS->cmp0 = (UNS_16)((duty>>1)+(max_cnts>>1));
NEG->cmp0 = (UNS_16)((max_cnts>>1)-(duty>>1));
}
else
{
POS->cmp0 = (UNS_16)((duty>>1)+(max_cnts>>1));
NEG->cmp0 = (UNS_16)((duty>>1)+(max_cnts>>1));
}
}
}
/* Update the sample index - so we can get the next
data value from the audio file */
if (sample < audio.sound[clip].size)
{
sample += bytes_per_sample;
}
else
{
if (audio.cb != NULL)
{
/* signal to host that the clip is done */
(*(PFV)audio.cb)();
}
sample = 0;
}
/* Clear the interrupt */
SPL->status = 0xFF;
/* Start the timer */
SPL->ctrl |= _SBF(1,1);
}
/************************************************************************
*
* Function: pcm_start_codec
*
* Purpose:
* Starts the pcm codec running.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
void pcm_start_codec (INT_32 new_clip,
INT_32 bit_clk_rate,
INT_32 n_oversamples)
{
UNS_32 sample_rate = 0;
/* set the sample to be played */
clip = new_clip;
/* reset the current sample counter */
sample = 0;
/* Set up the scaling factors which are used for over sampling
the pcm code */
sample_rate = audio.sound[new_clip].sample_rate;
audio.sound[new_clip].cnts_per_pulse =
(bit_clk_rate/sample_rate)/n_oversamples;
/* Clear the counter */
SPL->ctrl |= _SBF(0,1);
/* Clear interrupts */
SPL->status = 0xFF;
/* Start the timer */
SPL->ctrl |= _SBF(1,1);
/* Start the pwm */
NEG->ctrl |= _SBF(1,1);
POS->ctrl |= _SBF(1,1);
}
/************************************************************************
*
* Function: pcm_stop_codec
*
* Purpose:
* Stops the pcm codec from running.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
void pcm_stop_codec (void)
{
/* Stop the pwm */
NEG->ctrl &= ~_SBF(1,1);
POS->ctrl &= ~_SBF(1,1);
/* Stop the sample timer */
SPL->ctrl &= ~_SBF(1,1);
/* Clear the counter */
SPL->ctrl |= _SBF(0,1);
/* Clear interrupts */
SPL->status = 0xFF;
/* reset the sample counter */
sample = 0;
/* reset the current sample counter */
clip = 0;
}
/************************************************************************
*
* Function: pcm_get_sample_rate
*
* Purpose:
* Rturns the rate that the current sound clip was sampled.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
UNS_32 pcm_get_sample_rate (INT_32 clip)
{
return ((UNS_32)audio.sound[clip].sample_rate);
}
/************************************************************************
*
* Function: pcm_get_clip_name
*
* Purpose:
* Rturns the name of the sound clip was sampled.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
CHAR* pcm_get_clip_name (INT_32 clip)
{
return ((CHAR*)audio.sound[clip].title);
}
/************************************************************************
*
* Function: pcm_get_clip_name
*
* Purpose:
* Rturns the name of the sound clip was sampled.
*
* Processing:
*
* Parameters:
* None
*
* Outputs:
* None
*
* Returns:
* None
*
* Notes:
*
************************************************************************/
UNS_32 pcm_get_max_clips (void)
{
return (audio.nclips);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -