⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcm.c

📁 sharp s Lh75401 PWM audio的例子
💻 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 + -