This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123GH6PGE: how to integrate buzzer with tm4c123 controller?

Part Number: TM4C123GH6PGE
Other Parts Discussed in Thread: LM4819,

Hi,

Thank you guys for your kind support upto this point of time. I got so many solutions to my each problem that I thrown onto this forum.

I again come back with one more!

I am trying to integrate the buzzer to my TM4C123 tiva controller in the same way as done in the eval kit DK-TM4C129. 

I am using the example code provided for TM4c129 for TM4c123 with minute changes & now now my code is error free.

But after so much of excercise I am not able to get the relevant sound through my buzzer, only hissing noise is coming.

Kindly find the implemented code as below & suggest any change in methodology:

int
main(void)
{
uint32_t ui32Temp, count;


uint32_t ui32Retcode, ui32NewKey, ui32OldKey;
tContext sContext;
unsigned long input,previous;
//
// Enable lazy stacking for interrupt handlers. This allows floating-point
// instructions to be used within interrupt handlers, but at the expense of
// extra stack usage.
//
ROM_FPULazyStackingEnable();

//
// Set the system clock to run at 50MHz from the PLL.
//
/*ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
*/

g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ), 50000000);
//
// Configure the required pins for USB operation.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

ROM_GPIOPinConfigure(GPIO_PG4_USB0EPEN);
ROM_GPIOPinTypeUSBDigital(GPIO_PORTG_BASE, GPIO_PIN_4);
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
ROM_GPIOPinTypeUSBAnalog(GPIO_PORTL_BASE, GPIO_PIN_6 | GPIO_PIN_7);
ROM_GPIOPinTypeUSBAnalog(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);

ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOP);
ROM_GPIOPinConfigure(GPIO_PP2_T5CCP0);
ROM_GPIOPinTypeTimer(GPIO_PORTP_BASE, GPIO_PIN_2);

ROM_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1);
ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 1);

//

// Configure SysTick for a 100Hz interrupt.
//
ROM_SysTickPeriodSet(SysCtlClockGet() / TICKS_PER_SECOND);
ROM_SysTickEnable();
ROM_SysTickIntEnable();

//
// Enable Interrupts
//
// ROM_IntMasterEnable();


//
// Initialize the display driver.
//
CFAL96x64x16Init();
//
// Initialize the buttons driver.
//
ButtonsInit();

//
// Initialize two offscreen displays and assign the palette. These
// buffers are used by the slide menu widget to allow animation effects.
//
GrOffScreen4BPPInit(&g_sOffscreenDisplayA, g_pui8OffscreenBufA, 96, 40);
GrOffScreen4BPPPaletteSet(&g_sOffscreenDisplayA, g_pui32Palette, 0,
NUM_PALETTE_ENTRIES);
GrOffScreen4BPPInit(&g_sOffscreenDisplayB, g_pui8OffscreenBufB, 96, 40);
GrOffScreen4BPPPaletteSet(&g_sOffscreenDisplayB, g_pui32Palette, 0,
NUM_PALETTE_ENTRIES);

//
// Add the compile-time defined widgets to the widget tree.
//
WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sHeading);
WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sStatus);
WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sFileMenuWidget);

//
// Initialize the status text.
//
strcpy(g_pcStatusText, "No Device");

//
// Issue the initial paint request to the widgets then immediately call
// the widget manager to process the paint message. This ensures that the
// display is drawn as quickly as possible and saves the delay we would
// otherwise experience if we processed the paint message after mounting
// and reading the SD card.
//
WidgetPaint(WIDGET_ROOT);
WidgetMessageQueueProcess();

//
// Determine whether or not an SD Card is installed. If not, print a
// warning and have the user install one and restart.
//
// ui32Retcode = disk_initialize(0);
ui32Retcode = RES_OK;
if(ui32Retcode != RES_OK)
{
g_pcStatusLines[0] = "No SD Card Found";
g_pcStatusLines[1] = "Please insert";
g_pcStatusLines[2] = "a card and";
g_pcStatusLines[3] = "reset the board.";
ShowStatusScreen(g_pcStatusLines, 4);
//return (1);
}
else
{
g_pcStatusLines[0] = "SD Card Found";
// ShowStatusScreen(g_pcStatusLines, 1);

// Mount the file system, using logical disk 0.
//
/* f_mount(0, &g_sFatFs);
if(!FileInit())
{
return(1);
}*/
}

//

//
// Not playing anything right now.
//
/*g_ui32Flags = 0;
g_ui32SysTickCount = 0;
g_ui32LastTick = 0;
g_ui32CurrentVolume = INITIAL_VOLUME_PERCENT;*/

// PP2/PP1 are used for the speaker output.
//
/*ROM_GPIOPinConfigure(GPIO_PP2_T5CCP0);
ROM_GPIOPinTypeTimer(GPIO_PORTP_BASE, GPIO_PIN_2);
ROM_GPIOPinTypeGPIOOutput(GPIO_PORTP_BASE, GPIO_PIN_1);
ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, GPIO_PIN_1);*/

strcpy(g_pcStatusText, "Speaker configured");


//
//
//
// Configure the USB host output.
//
USBSoundInit(0, AudioEvent);
//
// Initialize audio streaming to stopped state.
//
/* StopAudio();

SoundVolumeSet(60000);
SoundInit(g_ui32SysClock);*/

SoundInit(g_ui32SysClock);
SoundVolumeSet(128);
// GenerateAudio(g_pi16AudioBuffer, AUDIO_SIZE / 2);
//SoundStart((int16_t *)g_pi16AudioBuffer, AUDIO_SIZE, 8000, SoundCallback);

strcpy(g_pcStatusText, "Speaker playing");
WidgetPaint(WIDGET_ROOT);
WidgetMessageQueueProcess();

//
// Default the old and new key to not pressed so that the first key press
// will be properly drawn on the keyboard.
//
ui32OldKey = NUM_WHITE_KEYS + NUM_BLACK_KEYS;
ui32NewKey = NUM_WHITE_KEYS + NUM_BLACK_KEYS;

/*Sound_Init(); // initialize SysTick timer and DAC
Piano_Init();*/

//
// Enter an (almost) infinite loop for reading and processing commands from
// the user.
//
while(1)
{

SoundStart((int16_t *)g_pi16AudioBuffer, AUDIO_SIZE, 8000, SoundCallback);
GenerateAudio(g_pi16AudioBuffer, AUDIO_SIZE / 2);

}

  • You cannot use the function SysCtlClockFreqSet with a TM4C123 device. Use SysCtlClockSet(). There is a note on page 488 of the TivaWare Peripheral Driver Library User's Guide.

  • sayed tausif said:
    I am not able to get the relevant sound through my buzzer

    Many here may 'not' be familiar w/your 'buzzer' - some description would prove helpful.       (especially if 'relevant' sound is sought!)      And it is noted - that 'buzzers' (rarely ... if ever) are famed  for 'pure sound.'

    Following 'jumps out' from your code:

    • // PP2/PP1    are used for the speaker output.

    Your code sets PP1 as an output - then turns it on - that's productive to (potential) sound production.    However, PP2 is set as a Timer - but only (incompletely) initialized!    (I found only 2 (repetitive) calls to that Timer - which fail to force it as you desire.)

    Now - normally a speaker or a buzzer appears as a 2-terminal device.     (thus your correct usage of PP1 & PP2)      The output sound's volume is proportional to the voltage difference between the speaker/beeper's 2 terminals - and the frequency of that applied voltage dictates the sound's pitch.     It is expected that your Timer was intended to provide (some) frequency (sound pitch) control while the off-chip DAC would provide volume control.     Alas - the failed Timer configuration - and the 'missing' DAC coding - may (rather well) explain your buzzer's 'hissing.'     While your code (is likely error-free) that code appears insufficient to produce the 'controlled sound pitch & volume' - which (may) be judged 'relevant.'

    And then further down your code:

    • /*  Sound_Init();    // initialize SysTick timer and DAC    
    •      Piano_Init();  */      (this (commented away) function grouping -  appears HIGHLY IMPACTFUL upon sound output - yet is non-operative!    (you've blocked its execution)

    It must be that key/critical portions of your 'referenced program' have not (quite) 'made it into your program's implementation' - thus 'relevant' sound - escapes along w/those 'missing code' pieces...     It is 'unclear' as to how you, 'Got so much right' - yet (appear) to have 'missed' the key, 'Connective Piece Handling (PP1 & PP2) to your (misbehaving) buzzer!'      (i.e.  'relevant' sound source ... (maybe))

  • //*****************************************************************************
    //
    // sound.c - Sound driver for the speaker on the DK-TM4C129X.
    //
    // Copyright (c) 2013-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "drivers/sound.h"
    
    #include "Sound.h"
    #include "DAC.h"
    //#include "inc/tm4c123gh6pge.h"
    #include <stdbool.h>
    #include <stdint.h>
    //#include "..//tm4c123gh6pm.h"
    
    unsigned char Index;
    unsigned short Sound_On_Flag;
    
    // 4-bit 32-element sine wave
    const unsigned char SineWave[32] = {8,9,11,12,13,14,14,15,15,15,14,14,13,12,
    																		11,9,8,7,5,4,3,2,2,1,1,1,2,2,3,4,5,7};
    
    //*****************************************************************************
    //
    //! \addtogroup sound_api
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // This structure defines the internal state of the sound driver.
    //
    //*****************************************************************************
    typedef struct
    {
        //
        // The number of clocks per PWM period.
        //
        uint32_t ui32Period;
    
        //
        // A set of flags indicating the mode of the sound driver.
        //
        volatile uint32_t ui32Flags;
    
        //
        // A pointer to the sound buffer being played.
        //
        const int16_t *pi16Buffer;
    
        //
        // The length of the sound buffer, in bytes.
        //
        uint32_t ui32Length;
    
        //
        // The current playback offset into the sound buffer.
        //
        uint32_t ui32Offset;
    
        //
        // The volume to playback the sound stream.  This is a value between 0
        // (for silence) and 256 (for full volume).
        //
        int32_t i32Volume;
    
        //
        // The previous and current sound samples, used for interpolating from
        // 8 kHz to 64 kHz sound.
        //
        int16_t pi16Samples[2];
    
        //
        // The sound step, which corresponds to the current interpolation point
        // between the previous and current sound samples.
        //
        int32_t i32Step;
    
        //
        // The current requested rate adjustment.  This is cleared when the
        // the adjustment is made.
        //
        int32_t i32RateAdjust;
    
        //
        // The callback function that indicates when half of the sound buffer has
        // bene played and is therefore ready to be refilled.
        //
        void (*pfnCallback)(uint32_t ui32Half);
    }
    tSoundState;
    
    //*****************************************************************************
    //
    // The flags that are in tSoundState.ui32Flags.
    //
    //*****************************************************************************
    #define SOUND_FLAG_STARTUP      0
    #define SOUND_FLAG_SHUTDOWN     1
    #define SOUND_FLAG_PLAY         2
    #define SOUND_FLAG_8KHZ         3
    #define SOUND_FLAG_16KHZ        4
    #define SOUND_FLAG_32KHZ        5
    #define SOUND_FLAG_64KHZ        6
    
    //*****************************************************************************
    //
    // The current state of the sound driver.
    //
    //*****************************************************************************
    static tSoundState g_sSoundState;
    
    //*****************************************************************************
    //
    //! Handles the TIMER5A interrupt.
    //!
    //! This function responds to the TIMER5A interrupt, updating the duty cycle of
    //! the output waveform in order to produce sound.  It is the application's
    //! responsibility to ensure that this function is called in response to the
    //! TIMER5A interrupt, typically by installing it in the vector table as the
    //! handler for the TIMER5A interrupt.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundIntHandler(void)
    {
        int32_t i32DutyCycle;
        char g_pcStatusText[100] = "";
        //
        // If there is an adjustment to be made, the apply it and set allow the
        // update to be done on the next load.
        //
        if(g_sSoundState.i32RateAdjust)
        {
            g_sSoundState.ui32Period += g_sSoundState.i32RateAdjust;
            g_sSoundState.i32RateAdjust = 0;
            TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
        }
    
        //
        // Clear the timer interrupt.
        //
        ROM_TimerIntClear(TIMER5_BASE, TIMER_CAPA_EVENT);
    
        //
        // See if the startup ramp is in progress.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP))
        {
            //
            // Increment the ramp count.
            //
            g_sSoundState.i32Step++;
    
            //
            // Increase the pulse width of the output by one clock.
            //
            ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step);
    
            //
            // See if this was the last step of the ramp.
            //
            if(g_sSoundState.i32Step >= (g_sSoundState.ui32Period / 2))
            {
                //
                // Indicate that the startup ramp has completed.
                //
                HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 0;
    
                //
                // Set the step back to zero for the start of audio playback.
                //
                g_sSoundState.i32Step = 0;
            }
    
            //
            // There is nothing further to be done.
            //
            return;
        }
    
        //
        // See if the shutdown ramp is in progress.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN))
        {
            //
            // See if this was the last step of the ramp.
            //
            if(g_sSoundState.i32Step == 1)
            {
                //
                // Disable the output signals.
                //
                ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
    
                //
                // Clear the sound flags.
                //
                g_sSoundState.ui32Flags = 0;
    
                //
                // Disable the speaker amp.
                //
               // ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 0);
            }
            else
            {
                //
                // Decrement the ramp count.
                //
                g_sSoundState.i32Step--;
    
                //
                // Decrease the pulse width of the output by one clock.
                //
                ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step);
            }
    
            //
            // There is nothing further to be done.
            //
            return;
        }
        strcpy(g_pcStatusText, "Speaker on");
        //
        // Compute the value of the PCM sample based on the blended average of the
        // previous and current samples.  It should be noted that linear
        // interpolation does not produce the best results with sound (it produces
        // a significant amount of harmonic aliasing) but it is fast.
        //
        i32DutyCycle =
            (((g_sSoundState.pi16Samples[0] * (8 - g_sSoundState.i32Step)) +
              (g_sSoundState.pi16Samples[1] * g_sSoundState.i32Step)) / 8);
    
        //
        // Adjust the magnitude of the sample based on the current volume.  Since a
        // multiplicative volume control is implemented, the volume value
        // results in nearly linear volume adjustment if it is squared.
        //
        i32DutyCycle = (((i32DutyCycle * g_sSoundState.i32Volume *
                          g_sSoundState.i32Volume) / 65536) + 32768);
    
        //
        // Set the PWM duty cycle based on this PCM sample.
        //
        i32DutyCycle = (g_sSoundState.ui32Period * i32DutyCycle) / 65536;
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, i32DutyCycle);
    
        //
        // Increment the sound step based on the sample rate.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 1) & 7;
            //g_sSoundState.i32Step = (g_sSoundState.i32Step - 4) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 2) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 4) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_64KHZ))
           {
               g_sSoundState.i32Step = (g_sSoundState.i32Step + 8) & 7;
           }
    
        //
        // See if the next sample has been reached.
        //
        if(g_sSoundState.i32Step == 0)
        {
            //
            // Copy the current sample to the previous sample.
            //
            g_sSoundState.pi16Samples[0] = g_sSoundState.pi16Samples[1];
    
            //
            // Get the next sample from the buffer.
            //
            g_sSoundState.pi16Samples[1] =
                g_sSoundState.pi16Buffer[g_sSoundState.ui32Offset];
    
            //
            // Increment the buffer pointer.
            //
            g_sSoundState.ui32Offset++;
            if(g_sSoundState.ui32Offset == g_sSoundState.ui32Length)
            {
                g_sSoundState.ui32Offset = 0;
            }
    
            //
            // Call the callback function if one of the half-buffers has been
            // consumed.
            //
            if(g_sSoundState.pfnCallback)
            {
                if(g_sSoundState.ui32Offset == 0)
                {
                    g_sSoundState.pfnCallback(1);
                }
                else if(g_sSoundState.ui32Offset == (g_sSoundState.ui32Length / 2))
                {
                    g_sSoundState.pfnCallback(0);
                }
            }
        }
    }
    
    //*****************************************************************************
    //
    //! Initializes the sound driver.
    //!
    //! \param ui32SysClock is the frequency of the system clock.
    //!
    //! This function initializes the sound driver, preparing it to output sound
    //! data to the speaker.
    //!
    //! The system clock should be as high as possible; lower clock rates reduces
    //! the quality of the produced sound.  For the best quality sound, the system
    //! should be clocked at 120 MHz.
    //!
    //! \note In order for the sound driver to function properly, the sound driver
    //! interrupt handler (SoundIntHandler()) must be installed into the vector
    //! table for the timer 5 subtimer A interrupt.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundInit(uint32_t ui32SysClock)
    {
        //
        // Enable the peripherals used by the sound driver.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
    
        //
        // Compute the PWM period based on the system clock.
        //
        g_sSoundState.ui32Period = ui32SysClock / 64000;
    
        //
        // Set the default volume.
        //
        g_sSoundState.i32Volume = 255;
    
        //
        // Configure the timer to run in PWM mode.
        //
        if((HWREG(TIMER5_BASE + TIMER_O_CTL) & TIMER_CTL_TBEN) == 0)
        {
            ROM_TimerConfigure(TIMER5_BASE, (TIMER_CFG_SPLIT_PAIR |
                                             TIMER_CFG_A_PWM |
                                             TIMER_CFG_B_PERIODIC));
        }
        ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period - 1);
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
        ROM_TimerControlLevel(TIMER5_BASE, TIMER_A, true);
    
        //
        // Update the timer values on timeouts and not immediately.
        //
        TimerUpdateMode(TIMER5_BASE, TIMER_A, TIMER_UP_LOAD_TIMEOUT |
                                              TIMER_UP_MATCH_TIMEOUT);
    
        //
        // Configure the timer to generate an interrupt at every time-out event.
        //
        ROM_TimerIntEnable(TIMER5_BASE, TIMER_CAPA_EVENT);
    
        //
        // Enable the timer.  At this point, the timer generates an interrupt
        // every 15.625 us.
        //
        ROM_TimerEnable(TIMER5_BASE, TIMER_A);
       // ROM_IntEnable(INT_TIMER5A);
    
        //
        // Clear the sound flags.
        //
        g_sSoundState.ui32Flags = 0;
    }
    
    //*****************************************************************************
    //
    //! Make adjustments to the sample period of the PWM audio.
    //!
    //! \param i32RateAdjust is a signed value of the adjustment to make to the
    //! current sample period.
    //!
    //! This function allows the sample period to be adjusted if the application
    //! needs to make small adjustments to the playback rate of the audio.  This
    //! should only be used to makke smaller adjustments to the sample rate since
    //! large changes cause distortion in the output.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundPeriodAdjust(int32_t i32RateAdjust)
    {
        g_sSoundState.i32RateAdjust += i32RateAdjust;
    }
    
    //*****************************************************************************
    //
    //! Starts playback of a sound stream.
    //!
    //! \param pi16Buffer is a pointer to the buffer that contains the sound to
    //! play.
    //! \param ui32Length is the length of the buffer in samples.  This should be
    //! a multiple of two.
    //! \param ui32Rate is the sound playback rate; valid values are 8000, 16000,
    //! 32000, and 64000.
    //! \param pfnCallback is the callback function that is called when either half
    //! of the sound buffer has been played.
    //!
    //! This function starts the playback of a sound stream contained in an
    //! audio ping-pong buffer.  The buffer is played repeatedly until
    //! SoundStop() is called.  Playback of the sound stream begins
    //! immediately, so the buffer should be pre-filled with the initial sound
    //! data prior to calling this function.
    //!
    //! \return Returns \b true if playback was started and \b false if it could
    //! not be started (because something is already playing).
    //
    //*****************************************************************************
    bool
    SoundStart(int16_t *pi16Buffer, uint32_t ui32Length, uint32_t ui32Rate,
               void (*pfnCallback)(uint32_t ui32Half))
    {
        //
        // Return without playing the buffer if something is already playing.
        //
       /* if(g_sSoundState.ui32Flags)
        {
            return(false);
        }*/
    
        //
        // Set the sample rate flag.
        //
        if(ui32Rate == 8000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ) = 1;
        }
        else if(ui32Rate == 16000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ) = 1;
        }
        else if(ui32Rate == 32000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ) = 1;
        }
        else if(ui32Rate == 64000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_64KHZ) = 1;
        }
        else
        {
            return(false);
        }
    
        //
        // Enable the speaker amp.
        //
        ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 1);
       // ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 1);
        //
        // Save the pointer to the buffer.
        //
        g_sSoundState.pi16Buffer = pi16Buffer;
        g_sSoundState.ui32Length = ui32Length;
    
        //
        // Save the pointer to the callback function.
        //
        g_sSoundState.pfnCallback = pfnCallback;
    
        //
        // Start playback from the beginning of the buffer.
        //
        g_sSoundState.ui32Offset = 0;
    
        //
        // Initialize the sample buffer with silence.
        //
        g_sSoundState.pi16Samples[0] = 0;
        g_sSoundState.pi16Samples[1] = 0;
    
        //
        // Start playback of the stream.
        //
        HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 1;
        HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_PLAY) = 1;
    
        //
        // Set the step for the startup ramp.
        //
        g_sSoundState.i32Step = 1;
    
        //
        // Enable the timer interrupt.
        //
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 1);
    
        //
        // Success.
        //
        return(true);
    }
    
    //*****************************************************************************
    //
    //! Stops playback of the current sound stream.
    //!
    //! This function immediately stops playback of the current sound stream.  As
    //! a result, the output is changed directly to the mid-point, possibly
    //! resulting in a pop or click.  It is then ramped down to no output,
    //! eliminating the current draw through the amplifier and speaker.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundStop(void)
    {
        //
        // See if playback is in progress.
        //
        if((g_sSoundState.ui32Flags != 0) &&
           (HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) == 0))
        {
            //
            // Temporarily disable the timer interrupt.
            //
            ROM_IntDisable(INT_TIMER5A);
    
            //
            // Clear the sound flags and set the shutdown flag (to try to avoid a
            // pop, though one may still occur based on the current position of the
            // output waveform).
            //
            g_sSoundState.ui32Flags = 0;
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) = 1;
    
            //
            // Set the shutdown step to the first.
            //
            g_sSoundState.i32Step = g_sSoundState.ui32Period / 2;
    
            //
            // Reenable the timer interrupt.
            //
            ROM_IntEnable(INT_TIMER5A);
        }
    }
    
    //*****************************************************************************
    //
    //! Determines if the sound driver is busy.
    //!
    //! This function determines if the sound driver is busy, either performing the
    //! startup or shutdown ramp for the speaker or playing a sound stream.
    //!
    //! \return Returns \b true if the sound driver is busy and \b false otherwise.
    //
    //*****************************************************************************
    bool
    SoundBusy(void)
    {
        //
        // The sound driver is busy if the sound flags are not zero.
        //
        return(g_sSoundState.ui32Flags != 0);
    }
    
    //*****************************************************************************
    //
    //! Sets the volume of the sound playback.
    //!
    //! \param i32Volume is the volume of the sound playback, specified as a value
    //! between 0 (for silence) and 255 (for full volume).
    //!
    //! This function sets the volume of the sound playback.  Setting the volume to
    //! 0 mutes the output, while setting the volume to 256 plays the sound
    //! stream without any volume adjustment (that is, full volume).
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeSet(int32_t i32Volume)
    {
        //
        // Set the volume mulitplier to be used.
        //
        g_sSoundState.i32Volume = i32Volume;
    }
    
    //*****************************************************************************
    //
    //! Increases the volume of the sound playback.
    //!
    //! \param i32Volume is the amount by which to increase the volume of the
    //! sound playback, specified as a value between 0 (for no adjustment) and 255
    //! maximum adjustment).
    //!
    //! This function increases the volume of the sound playback relative to the
    //! current volume.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeUp(int32_t i32Volume)
    {
        //
        // Compute the new volume, limiting to the maximum if required.
        //
        i32Volume = g_sSoundState.i32Volume + i32Volume;
        if(i32Volume > 255)
        {
            i32Volume = 255;
        }
    
        //
        // Set the new volume.
        //
        g_sSoundState.i32Volume = i32Volume;
    }
    
    //*****************************************************************************
    //
    //! Decreases the volume of the sound playback.
    //!
    //! \param i32Volume is the amount by which to decrease the volume of the
    //! sound playback, specified as a value between 0 (for no adjustment) and 255
    //! maximum adjustment).
    //!
    //! This function decreases the volume of the sound playback relative to the
    //! current volume.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeDown(int32_t i32Volume)
    {
        //
        // Compute the new volume, limiting to the minimum if required.
        //
        i32Volume = g_sSoundState.i32Volume - i32Volume;
        if(i32Volume < 0)
        {
            i32Volume = 0;
        }
    
        //
        // Set the new volume.
        //
        g_sSoundState.i32Volume = i32Volume;
    }
    
    // **************Sound_Init*********************
    // Initialize Systick periodic interrupts
    // Also calls DAC_Init() to initialize DAC
    // Input: none
    // Output: none
    /*void Sound_Init(void){
    	DAC_Init();          // Port B is DAC
      Index = 0;
      NVIC_ST_CTRL_R = 0;         // disable SysTick during setup
      NVIC_ST_RELOAD_R = 0x00FFFFFF; //
      NVIC_ST_CURRENT_R = 0;      // any write to current clears it
      NVIC_SYS_PRI3_R = (NVIC_SYS_PRI3_R&0x00FFFFFF)|0x20000000; // priority 1
      NVIC_ST_CTRL_R = 0x0007;  // enable SysTick with core clock and interrupts
    
    }*/
    
    // **************Sound_Tone*********************
    // Change Systick periodic interrupts to start sound output
    // Input: interrupt period
    //           Units of period are 12.5ns
    //           Maximum is 2^24-1
    //           Minimum is determined by length of ISR
    // Output: none
    /*
    void Sound_Tone(unsigned long period){
    // this routine sets the RELOAD and starts SysTick
    	Sound_On_Flag = 1;
    	NVIC_ST_RELOAD_R = period - 1; //reload value
      NVIC_ST_CURRENT_R = 0;// any write to current clears it
    }
    
    
    // **************Sound_Off*********************
    // stop outputing to DAC
    // Output: none
    void Sound_Off(void){
     // this routine stops the sound output
    	Sound_On_Flag = 0;
    	//GPIO_PORTB_DATA_R = 0;
    }
    
    
    // Interrupt service routine
    // Executed every 12.5ns*period(where period is input to Sound_Tone method)
    //Period of Sound wave = interrupt period * size of sine table (size of SineWave array)
    //size of sine table = 32
    //interrupt period = 12.5ns*period(where period is input to Sound_Tone method)
    void SysTick_Handler(void){
    		Index = (Index+1)&0x1F;  //index increments from 0 to 31 and then starts back at 0 again
    		if(Sound_On_Flag){
    			DAC_Out(SineWave[Index]);
    		}
    		else{
    			GPIO_PORTB_DATA_R = 0;
    		}
    }
    */
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    
    Thanks a lot CB1!

    with reference to "It is expected that your Timer was intended to provide (some) frequency (sound pitch) control while the off-chip DAC would provide volume control.   "

    I am not using any DAC on my circuit, but using amplifier LM4819 at the output.

    Used same circuit as speaker portion of DK-TM4C129 board & using the synth code with modifications required for TM4C123gh6pge.

    At PP2 pin, I am getting pulses but not getting any sine wave.

    Kindly suggest whether I am going in right direction? or my effort is going to be waste.

    Please find the attached reference source code usb_sound.c & with initialisation of sound driver in  sound.c

  • sayed tausif said:
    At PP2 pin, I am getting pulses  ...  but  not getting any sine wave.

    I've not the time to search/find then seriously review (both) the large code base AND schematic of the (referenced) DK-TM4C129 board.      (which you've modified - adding yet (further) variables...)

    My friend - did I not provide strong (guiding) clues - w/in that first response?      (and amplified - w/in that response's 'tag.')

    Assuming that  'PP1 & PP2'  - as listed in your initial posting of your (modified) code - remain the MCU's sole (signal initiating) connections to your 'beeper' - how do you explain (really justify)  these 2 code lines - appearing w/in your initial post?

    ROM_GPIOPinTypeTimer(GPIO_PORTP_BASE, GPIO_PIN_2);    // 1st occurrence

    ROM_GPIOPinTypeTimer(GPIO_PORTP_BASE, GPIO_PIN_2);   // 2nd occurrence

    With those two as the ONLY 'Set-Ups or Configurations' of 'PP2' - how can, 'Any Sine Wave' be expected?     (from pin PP2?)      

    Again - earlier I directed your attention to, 'Just that point' - which you have (not) directly (or effectively) addressed.

    You direct that I review (other) code - yet there were 'NO References' to that code w/in your initial posting.     (thus - how is the review of that (newly added) code relevant?)

    When attempting to 'migrate a project'  between different MCUs it is important that:

    • all key/critical functions are identified and (properly) passed on to the new design
    • the capability of the new device is 'w/in bounds' of what's required
    • the duplication of the (original's)  hardware and software (functionality & performance) proves adequate

    It is believed that your, 'project migration' falls somewhat short - upon  several of  those key measures...

    (Undescribed (as always) is the motivation for such 'project migration!'      Potentially great time/effort (may) be required - yet minus (any) 'justification of such need' - would not the usage of the (original) 'DK-TM4C129 board' - provide a (very) ready (and proven) solution?)

  • Did you correct the function call to set the system clock frequency? Here is the list of TivaWare functions that you must watch out for when changing code for a TM4C129x device to a TM4C123x device (and vice versa).

  • yes, I corrected the function call. using:
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    g_ui32SysClock = SysCtlClockGet();
  • Hi cb1,

    Sorry for not providing the exact location of the timer initialization. Here it is:
    void
    SoundInit(uint32_t ui32SysClock)
    {
    //
    // Enable the peripherals used by the sound driver.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);

    //
    // Compute the PWM period based on the system clock.
    //
    g_sSoundState.ui32Period = ui32SysClock / 64000;

    //
    // Set the default volume.
    //
    g_sSoundState.i32Volume = 255;

    //
    // Configure the timer to run in PWM mode.
    //
    if((HWREG(TIMER5_BASE + TIMER_O_CTL) & TIMER_CTL_TBEN) == 0)
    {
    ROM_TimerConfigure(TIMER5_BASE, (TIMER_CFG_SPLIT_PAIR |
    TIMER_CFG_A_PWM |
    TIMER_CFG_B_PERIODIC));
    }
    ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period - 1);
    ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
    ROM_TimerControlLevel(TIMER5_BASE, TIMER_A, true);

    //
    // Update the timer values on timeouts and not immediately.
    //
    TimerUpdateMode(TIMER5_BASE, TIMER_A, TIMER_UP_LOAD_TIMEOUT |
    TIMER_UP_MATCH_TIMEOUT);

    //
    // Configure the timer to generate an interrupt at every time-out event.
    //
    ROM_TimerIntEnable(TIMER5_BASE, TIMER_CAPA_EVENT);

    //
    // Enable the timer. At this point, the timer generates an interrupt
    // every 15.625 us.
    //
    ROM_TimerEnable(TIMER5_BASE, TIMER_A);
    // ROM_IntEnable(INT_TIMER5A);

    //
    // Clear the sound flags.
    //
    g_sSoundState.ui32Flags = 0;
    } // code ends here

    I commented ROM_IntEnable(INT_TIMER5A) because its hanging the unit.

    As far as, Migration of MCU project is concerned, I used 95% design from DK-TM4C123. Just for the purpose of audio I had no option but to choose the circuit from DK-TM4c129 board.

    Already 95% functionalities tested & working as per planned.

    Just because I had no proven circuit & code for TM4C123, I had takena risk of reusing TM4C129 speaker design because of availability of speaker library code.

    My buzzer (CDM-13008) is giving proper tone when givng 2-16 KHz sine wave through external signal generator..

    But not able to generate same sine wave through the provided code.
    I am assuming, if controller will generate the same sine wave then my buzzer will generate the tone.

    Kindly help me to find the issue.

    Your kind support may help me to cross this hurdle.
  • This response provides far more clarity than those earlier - good job!        (such IS required for your remote helper crüe to prove of much service - don't you agree?)

    And it proves true that the 'suggested answer' (marked as such by another)  - failed to provide (much) comfort - and (surely) - no 'real' answer!      (even w/system clock improperly set - your system appeared to operate - somehow that fact was missed.)

    I believe that your, 'Use of KISS' now will, 'Speed, Ease & Enhance' your 'Sine-Wave Creation' troubleshooting.

    So then - how can you Simplify - and make (far more) Systematic - your generation of a Timer-Based PWM type sine-wave?     Recall  the 'KISS' directive, 'Keep It Simple & Systematic!'    (even though - especially though - the powerful/enhancing KISS (just like LIKE) appears 'banned' here!)      (again for no good reason...)

    sayed tausif said:
    But not able to generate same sine wave through the provided code.

    This begs the question - what output, (from Timer5) 'Do you observe?'     (Minus a scope capture - much more time/effort is forced upon your helper crüe - that's NOT to your advantage - don't you agree?    Note too - your report listing 'Not able to generate' - provides NO/ZERO insight - into what Timer5 'HAS GENERATED!'     And that's critical - is it not?

    Back to (the banned here) KISS:

    • Your imported Timer Code while clever - is reasonably complex.      It is presented as, "Multi-Functional' - drives TWO Timer Sections (A & B) - and requires the use of interrupts!     Does that not (greatly) WIDEN your 'Field of Battle?'     (i.e.  to which 'enemy target' - do you direct your fire?)    [ex US Army Combat Officer here...)
    • It is likely that you will require a scope - rather than the 'buzzer alone' - to Speed & Ease your diagnosis.     Is one reasonably available?    (Does NOT have to be top performer...)
    • It will prove useful for you to (first) confirm that Timer5's PWM Mode IS performing.    (generate different PWM duty cycles - and frequencies - confirm that, 'All is proper')
    • Only after Timer5A has been 'proven' to produce satisfactory (i.e. controlled) PWM output) would I add Timer5B to the mix.     It appears that Timer5B's 'periodic' nature causes the output of Timer5A to vary - in the attempt to create some (near) sine wave.    Note that this 'modulation' of Timer5A - by Timer5B - presents much complexity - and must be carefully (and incrementally) tested & confirmed.

    Your earlier code revealed a 50MHz System Clock - and you divide that by 64,000 - to produce, 'g_sSoundState.ui32Period.'     My math reveals that to yield a frequency of ~780Hz - is that what you wanted?    And - how was that value chosen - if so.

    Your interrupts occur at 15.6µS intervals - my 'napkin' calculation shows that to be ~64KHz - again how was that chosen?    (the 'delta' between ~780Hz & ~64KHz - seems (very) wide - does it not?)

    It is suspected that some 'R-C' network is intended to 'Receive your 'varying duty' PWM Output' (to produce the varying analog levels) - yet that has not received mention.    Any and Everything - imposed between your MCU and the 'hissing' buzzer - must be (nicely) detailed!

    It is suspected that these factors - not the errant system clock - deserve your greatest attention...

  • 5102.usb_host_audio.c

    //*****************************************************************************
    //
    // sound.c - Sound driver for the speaker on the DK-TM4C129X.
    //
    // Copyright (c) 2013-2014 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_timer.h"
    #include "inc/hw_types.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "drivers/sound.h"
    
    
    
    
    #include "Sound.h"
    #include "DAC.h"
    //#include "inc/tm4c123gh6pge.h"
    #include <stdbool.h>
    #include <stdint.h>
    //#include "..//tm4c123gh6pm.h"
    
    unsigned char Index;
    unsigned short Sound_On_Flag;
    
    // 4-bit 32-element sine wave
    const unsigned char SineWave[32] = {8,9,11,12,13,14,14,15,15,15,14,14,13,12,
    																		11,9,8,7,5,4,3,2,2,1,1,1,2,2,3,4,5,7};
    uint32_t g_ui32CurrentVolume;
    //*****************************************************************************
    //
    //! \addtogroup sound_api
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // This structure defines the internal state of the sound driver.
    //
    //*****************************************************************************
    typedef struct
    {
        //
        // The number of clocks per PWM period.
        //
        uint32_t ui32Period;
    
        //
        // A set of flags indicating the mode of the sound driver.
        //
        volatile uint32_t ui32Flags;
    
        //
        // A pointer to the sound buffer being played.
        //
        const int16_t *pi16Buffer;
    
        //
        // The length of the sound buffer, in bytes.
        //
        uint32_t ui32Length;
    
        //
        // The current playback offset into the sound buffer.
        //
        uint32_t ui32Offset;
    
        //
        // The volume to playback the sound stream.  This is a value between 0
        // (for silence) and 256 (for full volume).
        //
        int32_t i32Volume;
    
        //
        // The previous and current sound samples, used for interpolating from
        // 8 kHz to 64 kHz sound.
        //
        int16_t pi16Samples[2];
    
        //
        // The sound step, which corresponds to the current interpolation point
        // between the previous and current sound samples.
        //
        int32_t i32Step;
    
        //
        // The current requested rate adjustment.  This is cleared when the
        // the adjustment is made.
        //
        int32_t i32RateAdjust;
    
        //
        // The callback function that indicates when half of the sound buffer has
        // bene played and is therefore ready to be refilled.
        //
        void (*pfnCallback)(uint32_t ui32Half);
    }
    tSoundState;
    
    //*****************************************************************************
    //
    // The flags that are in tSoundState.ui32Flags.
    //
    //*****************************************************************************
    #define SOUND_FLAG_STARTUP      0
    #define SOUND_FLAG_SHUTDOWN     1
    #define SOUND_FLAG_PLAY         2
    #define SOUND_FLAG_8KHZ         3
    #define SOUND_FLAG_16KHZ        4
    #define SOUND_FLAG_32KHZ        5
    #define SOUND_FLAG_64KHZ        6
    #define SOUND_FLAG_2KHZ        7
    #define SOUND_FLAG_4KHZ        8
    
    
    //*****************************************************************************
    //
    // The current state of the sound driver.
    //
    //*****************************************************************************
    static tSoundState g_sSoundState;
    
    //*****************************************************************************
    //
    //! Handles the TIMER5A interrupt.
    //!
    //! This function responds to the TIMER5A interrupt, updating the duty cycle of
    //! the output waveform in order to produce sound.  It is the application's
    //! responsibility to ensure that this function is called in response to the
    //! TIMER5A interrupt, typically by installing it in the vector table as the
    //! handler for the TIMER5A interrupt.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundIntHandler(void)
    {
        int32_t i32DutyCycle;
        char g_pcStatusText[100] = "";
        //
        // If there is an adjustment to be made, the apply it and set allow the
        // update to be done on the next load.
        //
        if(g_sSoundState.i32RateAdjust)
        {
            g_sSoundState.ui32Period += g_sSoundState.i32RateAdjust;
            g_sSoundState.i32RateAdjust = 0;
            TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
        }
    
        //
        // Clear the timer interrupt.
        //
        ROM_TimerIntClear(TIMER5_BASE, TIMER_CAPA_EVENT);
    
        //
        // See if the startup ramp is in progress.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP))
        {
            //
            // Increment the ramp count.
            //
            g_sSoundState.i32Step++;
    
            //
            // Increase the pulse width of the output by one clock.
            //
            ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step);
    
            //
            // See if this was the last step of the ramp.
            //
            if(g_sSoundState.i32Step >= (g_sSoundState.ui32Period / 2))
            {
                //
                // Indicate that the startup ramp has completed.
                //
                HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 0;
    
                //
                // Set the step back to zero for the start of audio playback.
                //
                g_sSoundState.i32Step = 0;
            }
    
            //
            // There is nothing further to be done.
            //
            return;
        }
    
        //
        // See if the shutdown ramp is in progress.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN))
        {
            //
            // See if this was the last step of the ramp.
            //
            if(g_sSoundState.i32Step == 1)
            {
                //
                // Disable the output signals.
                //
                ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
    
                //
                // Clear the sound flags.
                //
                g_sSoundState.ui32Flags = 0;
    
                //
                // Disable the speaker amp.
                //
               // ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 0);
            }
            else
            {
                //
                // Decrement the ramp count.
                //
                g_sSoundState.i32Step--;
    
                //
                // Decrease the pulse width of the output by one clock.
                //
                ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.i32Step);
            }
    
            //
            // There is nothing further to be done.
            //
            return;
        }
        strcpy(g_pcStatusText, "Speaker on");
        //
        // Compute the value of the PCM sample based on the blended average of the
        // previous and current samples.  It should be noted that linear
        // interpolation does not produce the best results with sound (it produces
        // a significant amount of harmonic aliasing) but it is fast.
        //
        i32DutyCycle =
            (((g_sSoundState.pi16Samples[0] * (8 - g_sSoundState.i32Step)) +
              (g_sSoundState.pi16Samples[1] * g_sSoundState.i32Step)) / 8);
    
        //
        // Adjust the magnitude of the sample based on the current volume.  Since a
        // multiplicative volume control is implemented, the volume value
        // results in nearly linear volume adjustment if it is squared.
        //
        i32DutyCycle = (((i32DutyCycle * g_sSoundState.i32Volume *
                          g_sSoundState.i32Volume) / 65536) + 32768);
    
        //
        // Set the PWM duty cycle based on this PCM sample.
        //
        i32DutyCycle = (g_sSoundState.ui32Period * i32DutyCycle) / 65536;
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, i32DutyCycle);
    
        //
        // Increment the sound step based on the sample rate.
        //
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_2KHZ))
                {
                   // g_sSoundState.i32Step = (g_sSoundState.i32Step + 1) & 7;
                    g_sSoundState.i32Step = (g_sSoundState.i32Step - 1) & 7;
                }
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_4KHZ))
            {
               // g_sSoundState.i32Step = (g_sSoundState.i32Step + 1) & 7;
                g_sSoundState.i32Step = (g_sSoundState.i32Step ) & 7;
            }
    
        if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 1) & 7;
           // g_sSoundState.i32Step = (g_sSoundState.i32Step - 4) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 2) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ))
        {
            g_sSoundState.i32Step = (g_sSoundState.i32Step + 4) & 7;
        }
        else if(HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_64KHZ))
           {
               g_sSoundState.i32Step = (g_sSoundState.i32Step + 8) & 7;
           }
    
        //
        // See if the next sample has been reached.
        //
        if(g_sSoundState.i32Step == 0)
        {
            //
            // Copy the current sample to the previous sample.
            //
            g_sSoundState.pi16Samples[0] = g_sSoundState.pi16Samples[1];
    
            //
            // Get the next sample from the buffer.
            //
            g_sSoundState.pi16Samples[1] =
                g_sSoundState.pi16Buffer[g_sSoundState.ui32Offset];
    
            //
            // Increment the buffer pointer.
            //
            g_sSoundState.ui32Offset++;
            if(g_sSoundState.ui32Offset == g_sSoundState.ui32Length)
            {
                g_sSoundState.ui32Offset = 0;
            }
    
            //
            // Call the callback function if one of the half-buffers has been
            // consumed.
            //
            if(g_sSoundState.pfnCallback)
            {
                if(g_sSoundState.ui32Offset == 0)
                {
                    g_sSoundState.pfnCallback(1);
                }
                else if(g_sSoundState.ui32Offset == (g_sSoundState.ui32Length / 2))
                {
                    g_sSoundState.pfnCallback(0);
                }
            }
        }
    }
    
    //*****************************************************************************
    //
    //! Initializes the sound driver.
    //!
    //! \param ui32SysClock is the frequency of the system clock.
    //!
    //! This function initializes the sound driver, preparing it to output sound
    //! data to the speaker.
    //!
    //! The system clock should be as high as possible; lower clock rates reduces
    //! the quality of the produced sound.  For the best quality sound, the system
    //! should be clocked at 120 MHz.
    //!
    //! \note In order for the sound driver to function properly, the sound driver
    //! interrupt handler (SoundIntHandler()) must be installed into the vector
    //! table for the timer 5 subtimer A interrupt.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundInit(uint32_t ui32SysClock)
    {
        //
        // Enable the peripherals used by the sound driver.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
    
        //
        // Compute the PWM period based on the system clock.
        //
        g_sSoundState.ui32Period = ui32SysClock / 64000;
    
        //
        // Set the default volume.
        //
        g_sSoundState.i32Volume = 255;
    
        //
        // Configure the timer to run in PWM mode.
        //
        if((HWREG(TIMER5_BASE + TIMER_O_CTL) & TIMER_CTL_TBEN) == 0)
        {
            ROM_TimerConfigure(TIMER5_BASE, (TIMER_CFG_SPLIT_PAIR |
                                             TIMER_CFG_A_PWM |
                                             TIMER_CFG_B_PERIODIC));
        }
        ROM_TimerLoadSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period - 1);
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, g_sSoundState.ui32Period);
        ROM_TimerControlLevel(TIMER5_BASE, TIMER_A, true);
    
        //
        // Update the timer values on timeouts and not immediately.
        //
        TimerUpdateMode(TIMER5_BASE, TIMER_A, TIMER_UP_LOAD_TIMEOUT |
                                              TIMER_UP_MATCH_TIMEOUT);
    
        //
        // Configure the timer to generate an interrupt at every time-out event.
        //
        ROM_TimerIntEnable(TIMER5_BASE, TIMER_CAPA_EVENT);
    
        //
        // Enable the timer.  At this point, the timer generates an interrupt
        // every 15.625 us.
        //
        ROM_TimerEnable(TIMER5_BASE, TIMER_A);
        //ROM_IntEnable(INT_TIMER5A);
    
        //
        // Clear the sound flags.
        //
        g_sSoundState.ui32Flags = 0;
    }
    
    //*****************************************************************************
    //
    //! Make adjustments to the sample period of the PWM audio.
    //!
    //! \param i32RateAdjust is a signed value of the adjustment to make to the
    //! current sample period.
    //!
    //! This function allows the sample period to be adjusted if the application
    //! needs to make small adjustments to the playback rate of the audio.  This
    //! should only be used to makke smaller adjustments to the sample rate since
    //! large changes cause distortion in the output.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundPeriodAdjust(int32_t i32RateAdjust)
    {
        g_sSoundState.i32RateAdjust += i32RateAdjust;
    }
    
    //*****************************************************************************
    //
    //! Starts playback of a sound stream.
    //!
    //! \param pi16Buffer is a pointer to the buffer that contains the sound to
    //! play.
    //! \param ui32Length is the length of the buffer in samples.  This should be
    //! a multiple of two.
    //! \param ui32Rate is the sound playback rate; valid values are 8000, 16000,
    //! 32000, and 64000.
    //! \param pfnCallback is the callback function that is called when either half
    //! of the sound buffer has been played.
    //!
    //! This function starts the playback of a sound stream contained in an
    //! audio ping-pong buffer.  The buffer is played repeatedly until
    //! SoundStop() is called.  Playback of the sound stream begins
    //! immediately, so the buffer should be pre-filled with the initial sound
    //! data prior to calling this function.
    //!
    //! \return Returns \b true if playback was started and \b false if it could
    //! not be started (because something is already playing).
    //
    //*****************************************************************************
    bool
    SoundStart(int16_t *pi16Buffer, uint32_t ui32Length, uint32_t ui32Rate,
               void (*pfnCallback)(uint32_t ui32Half))
    {
        //
        // Return without playing the buffer if something is already playing.
        //
    
        if(g_sSoundState.ui32Flags)
        {
            return(false);
        }
    
        //
        // Set the sample rate flag.
        //
        if(ui32Rate == 2000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_2KHZ) = 1;
        }
        if(ui32Rate == 4000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_4KHZ) = 1;
        }
        if(ui32Rate == 8000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_8KHZ) = 1;
        }
        else if(ui32Rate == 16000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_16KHZ) = 1;
        }
        else if(ui32Rate == 32000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_32KHZ) = 1;
        }
        else if(ui32Rate == 64000)
        {
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_64KHZ) = 1;
        }
        else
        {
            return(false);
        }
    
        //
        // Enable the speaker amp.
        //
        ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 1);
       // ROM_GPIOPinWrite(GPIO_PORTP_BASE, GPIO_PIN_1, 1);
        //
        // Save the pointer to the buffer.
        //
        g_sSoundState.pi16Buffer = pi16Buffer;
        g_sSoundState.ui32Length = ui32Length;
    
        //
        // Save the pointer to the callback function.
        //
        g_sSoundState.pfnCallback = pfnCallback;
    
        //
        // Start playback from the beginning of the buffer.
        //
        g_sSoundState.ui32Offset = 0;
    
        //
        // Initialize the sample buffer with silence.
        //
        g_sSoundState.pi16Samples[0] = 0;
        g_sSoundState.pi16Samples[1] = 0;
    
        //
        // Start playback of the stream.
        //
        HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_STARTUP) = 1;
        HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_PLAY) = 1;
    
        //
        // Set the step for the startup ramp.
        //
        g_sSoundState.i32Step = 1;
    
        //
        // Enable the timer interrupt.
        //
        ROM_TimerMatchSet(TIMER5_BASE, TIMER_A, 1);
    
        //
        // Success.
        //
        return(true);
    }
    
    //*****************************************************************************
    //
    //! Stops playback of the current sound stream.
    //!
    //! This function immediately stops playback of the current sound stream.  As
    //! a result, the output is changed directly to the mid-point, possibly
    //! resulting in a pop or click.  It is then ramped down to no output,
    //! eliminating the current draw through the amplifier and speaker.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundStop(void)
    {
        //
        // See if playback is in progress.
        //
        if((g_sSoundState.ui32Flags != 0) &&
           (HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) == 0))
        {
            //
            // Temporarily disable the timer interrupt.
            //
            ROM_IntDisable(INT_TIMER5A);
    
            //
            // Clear the sound flags and set the shutdown flag (to try to avoid a
            // pop, though one may still occur based on the current position of the
            // output waveform).
            //
            g_sSoundState.ui32Flags = 0;
            HWREGBITW(&g_sSoundState.ui32Flags, SOUND_FLAG_SHUTDOWN) = 1;
    
            //
            // Set the shutdown step to the first.
            //
            g_sSoundState.i32Step = g_sSoundState.ui32Period / 2;
    
            //
            // Reenable the timer interrupt.
            //
            ROM_IntEnable(INT_TIMER5A);
        }
    }
    
    //*****************************************************************************
    //
    //! Determines if the sound driver is busy.
    //!
    //! This function determines if the sound driver is busy, either performing the
    //! startup or shutdown ramp for the speaker or playing a sound stream.
    //!
    //! \return Returns \b true if the sound driver is busy and \b false otherwise.
    //
    //*****************************************************************************
    bool
    SoundBusy(void)
    {
        //
        // The sound driver is busy if the sound flags are not zero.
        //
        return(g_sSoundState.ui32Flags != 0);
    }
    
    //*****************************************************************************
    //
    //! Sets the volume of the sound playback.
    //!
    //! \param i32Volume is the volume of the sound playback, specified as a value
    //! between 0 (for silence) and 255 (for full volume).
    //!
    //! This function sets the volume of the sound playback.  Setting the volume to
    //! 0 mutes the output, while setting the volume to 256 plays the sound
    //! stream without any volume adjustment (that is, full volume).
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeSet(int32_t i32Volume)
    {
        //
        // Set the volume mulitplier to be used.
        //
        g_sSoundState.i32Volume = i32Volume;
    }
    
    //*****************************************************************************
    //
    //! Increases the volume of the sound playback.
    //!
    //! \param i32Volume is the amount by which to increase the volume of the
    //! sound playback, specified as a value between 0 (for no adjustment) and 255
    //! maximum adjustment).
    //!
    //! This function increases the volume of the sound playback relative to the
    //! current volume.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeUp(int32_t i32Volume)
    {
        //
        // Compute the new volume, limiting to the maximum if required.
        //
    
        i32Volume = g_sSoundState.i32Volume + i32Volume;
        if(i32Volume > 255)
        {
            i32Volume = 255;
        }
    
        //
        // Set the new volume.
        //
        g_sSoundState.i32Volume = i32Volume;
        g_ui32CurrentVolume = (g_sSoundState.i32Volume*100/256);
        SoundVolumeSet(g_sSoundState.i32Volume);
    }
    
    //*****************************************************************************
    //
    //! Decreases the volume of the sound playback.
    //!
    //! \param i32Volume is the amount by which to decrease the volume of the
    //! sound playback, specified as a value between 0 (for no adjustment) and 255
    //! maximum adjustment).
    //!
    //! This function decreases the volume of the sound playback relative to the
    //! current volume.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    SoundVolumeDown(int32_t i32Volume)
    {
        //
        // Compute the new volume, limiting to the minimum if required.
        //
    
        i32Volume = g_sSoundState.i32Volume - i32Volume;
        if(i32Volume < 0)
        {
            i32Volume = 0;
        }
    
        //
        // Set the new volume.
        //
        g_sSoundState.i32Volume = i32Volume;
        g_ui32CurrentVolume = (g_sSoundState.i32Volume*100)/256;
        SoundVolumeSet(g_sSoundState.i32Volume);
    }
    
    // **************Sound_Init*********************
    // Initialize Systick periodic interrupts
    // Also calls DAC_Init() to initialize DAC
    // Input: none
    // Output: none
    /*void Sound_Init(void){
    	DAC_Init();          // Port B is DAC
      Index = 0;
      NVIC_ST_CTRL_R = 0;         // disable SysTick during setup
      NVIC_ST_RELOAD_R = 0x00FFFFFF; //
      NVIC_ST_CURRENT_R = 0;      // any write to current clears it
      NVIC_SYS_PRI3_R = (NVIC_SYS_PRI3_R&0x00FFFFFF)|0x20000000; // priority 1
      NVIC_ST_CTRL_R = 0x0007;  // enable SysTick with core clock and interrupts
    
    }*/
    
    // **************Sound_Tone*********************
    // Change Systick periodic interrupts to start sound output
    // Input: interrupt period
    //           Units of period are 12.5ns
    //           Maximum is 2^24-1
    //           Minimum is determined by length of ISR
    // Output: none
    /*
    void Sound_Tone(unsigned long period){
    // this routine sets the RELOAD and starts SysTick
    	Sound_On_Flag = 1;
    	NVIC_ST_RELOAD_R = period - 1; //reload value
      NVIC_ST_CURRENT_R = 0;// any write to current clears it
    }
    
    
    // **************Sound_Off*********************
    // stop outputing to DAC
    // Output: none
    void Sound_Off(void){
     // this routine stops the sound output
    	Sound_On_Flag = 0;
    	//GPIO_PORTB_DATA_R = 0;
    }
    
    
    // Interrupt service routine
    // Executed every 12.5ns*period(where period is input to Sound_Tone method)
    //Period of Sound wave = interrupt period * size of sine table (size of SineWave array)
    //size of sine table = 32
    //interrupt period = 12.5ns*period(where period is input to Sound_Tone method)
    void SysTick_Handler(void){
    		Index = (Index+1)&0x1F;  //index increments from 0 to 31 and then starts back at 0 again
    		if(Sound_On_Flag){
    			DAC_Out(SineWave[Index]);
    		}
    		else{
    			GPIO_PORTB_DATA_R = 0;
    		}
    }
    */
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************
    
    Thanks a lot cb1,

    KISS worked!

    I am able to hear loud & clear beep sound.

    I am sharing the code.
    The real issue was :

    1. sound handler was not able to call automatically

    2. soundcallback function (used in synth project) replaced with audiocallback function (used in USB_audio project).

    Without your support only I am able to solve the problem.

    Thanks again!

  • Thank you - friend Sayed.    Good job - proud of you - your persistence - and (hopefully) adoption of 'KISS' (One measurable - carefully checked/confirmed step at a time) once again PAID OFF.    (Even though - especially though - 'KISS' like 'LIKE' - for obscure (and unsupportable reason) is BANNED HERE!)

    I'm not so sure that 'only' my support enabled your success.    Your solution was HIGHLY CREATIVE - you 'borrowed (proper & usable) 'bits & pieces' from other sources - and then w/some (slight) guidance ... integrated & bent those to your will.     And that's ALL YOU!

    KISS directs that our 'expecting success' - even when, 'SO MANY Balls are "In the Air" - is more 'wishful' than 'reality' based.

    Your ability to 'compartmentalize tasks' - insure that  each piece performs - and (only) then ... join them into an 'expanding whole'  is to be admired - and to  your Great CREDIT!

    Be (very) proud!      (And employ KISS often - it's FREE - and extremely powerful - even 'LIKEd!')

  • Thanks for getting encouraging words from the person with such a great experience & exposure to different fields!
    As the sound is coming perfectly, so as noise. Past whole week passed in removing noise (67KHz) coming out of speaker. Even though it is generated by timer itself, but its undesirable.
    Can you pls suggest how I can play only 8KHz sound not 67 KHz sound.
  • sayed tausif said:
    Thanks for getting encouraging words from the person with such a great experience & exposure to different fields!

    That cannot describe 'moi' - one who operates from a 'back-room' - entered (only) via passage thru an (earlier) 'back-room.'      Thanks just the same.     (Pity that  those 'e2ers' - w/'heavy (yet claimed 'superior' hands' - have chased several of us - away!)       (My holiday week return has been - merely - a  'sailing by - mirage.')

    sayed tausif said:
    Can you pls suggest how I can play only 8KHz sound  not 67 KHz sound.

    I note that 'too often' - vendor agents (likely over-stressing 'PC') - only 'agree' with poster's diagnosis.     Not this reporter!      Can your - or most any 'realistic' speaker -  reproduce 67KHz?     And - as human hearing 'tops out'  at/around 20KHz  (males even lower ... so that we can 'tune out' ... you know) how have you realized (measured) such  67KHz detection?   (Even the 'beat frequency' ... 67KHz - 8KHz - proves too high for speaker reproduction!)

    If indeed - that 67KHz proves 'real'  (but surely - unheard)  does not a 'band-pass filter' - centered @ the offending frequency - immediately 'come to mind?'

    And again - kindly tell us how (and where) you've 'probed & measured'  that  67KHz.     (that's of interest)      And - as always 'LIKE' my post - and employ 'KISS!'

  • Mistake from my side!
    I was probing the signal on eval kit not on actual board as probing is easier there.
    But when I started probing my actual hardware with the same firmware I m finding the different waveform.
    Now, I am getting 17KHz maximum frequency. But my desired sound should be of 8KHz.
    Whenever I heared the irritating noise DSO will display pulses with 17KHz. Otherwise It will remain display the pulses with 2- 4KHz frequency.
  • The relative 'brevity' of your post forces 'extra' time/effort from the (shortly departing) helper crüe.

    You (now) introduce a  '17KHz' (max) frequency.      (earlier - your desire was the production of a 'clean' 8KHz signal - only!)     (via your post,  09 July - 04:26)

    Needed detail follows:

    • Does this 17KHz signal represent an ADDED Requirement - or is it (simply) an unwanted/offending signal?     (some detail required)
    • Your writing is unclear as to whether you 'ever' achieve your 'desired sound' - at/around 8KHz.     Is 8KHz (ever) achieved?    
    • Is your (desired) 8KHz 'fleeting?'      (unwantedly disappears - w/out deliberate action - on your part)
    • Newly mentioned are, 'pulses w/ 2-4KHz frequency.'     As these are 'outside' your desired 8KHz - are these 'unwanted/offending' signals?     What have you done (changed/added) to cause their creation?
    • I don't believe that 17KHz is 'irritating' - it does approach the upper limit of human recognition.  (I cannot hear HALF of that frequency now - courtesy of  'Towed, 105mm Howitzer.')    

    It is usual that poor pcb layout - 'bread-boards' (especially bread-boards) - and physically long/unshielded signal leads/paths may cause such issues.

    Troubleshooting audio most always begins from 'Left to Right' - carefully & properly 'probing/displaying' the 'earliest' (weakest) signal generation stage - gradually moving right (to the more amplified) signal - and 'searching for the ONSET of the distorted (or otherwise) offending signal.       (I'm likely 'gone' from the forum tomorrow (chased away by e2e 'enforcers') - quick response proves best...)

  • Hi,

    Sorry if I am not able to explain you the issue properly.

    Here is the case:
    My requirement is to produce the single tone sound.
    I am configuring the timer with 8khz frequency through " SoundStart((int16_t *)g_pi16AudioBuffer, AUDIO_SIZE, 8000, SoundCallback)"
    but getting 2-4KHz sound wave when probing the microcontroller output pin.
    This low frequency sound is soothing to ears & its a desired signal.
    But the undesired sound with 17Khz is irritating to ears, it is coming along with desired signal
    And the intensity of this 17KHz signal will increase as time progresses.
    Please help me to find:
    Is it because of electronic circuitry? or some small effort in firmware will solve the problem

    Forgive me for wrong use of English words!
  • Feel (but cannot 'hear') your pain.      That's one of the (few) benefits resulting from my past service as the only 'Signal Corps' officer w/in an Air Defense (Artillery) Battalion.     Those 'big guns' (Howitzers) fired over our bachelor quarters (from miles away - shells landing equally distant - thank you, God!)     Still our windows (seriously) RATTLED in their frames!     Some 20 years later - I once, 'Drove a Test Lab crüe'  to, RUN from the lab - due to my 'blasting' a 10KHz signal - which I could not,  'Hear - AT ALL!'

    Now your MCU's Timer will generate 'square waves' - at programmable frequencies - and (most always) those are 'not pleasantly heard/received.'     I 'know nothing' of  the  'SoundStart'  project - my firm is unlikely to employ it - and it appears that 'SoundStart' is at minimum,  'Aiding & Abetting' your issue.     Do understand - my small Tech Group deals w/MCU issues on a daily basis (to include most weekends) yet we must 'Pick & Choose' our, 'Time & Effort Commitments' w/care.    (Investors demand that -and my neck is the 'first' to be chopped - if we cannot (repeatedly) 'Beat the Stock Market.')

    Square wave outputs are rich in 'harmonics' - while you seek 8KHz - your report of 17KHz is (almost) the first harmonic of 8KHz.    (16KHz IS that harmonic)     Someway - somehow - your 8KHz square-wave must be manipulated into (near) SINE WAVE form.   (Sine waves are audibly pleasing)    That manipulation - most likely - fell to 'SoundStart' - thus that is where you must focus (your) time & attention.

    Using an MCU's square wave output - in the pursuit of producing a 'Sine Wave' - normally is attempted via the MCU's PWM Output pin - which feeds a carefully programmed, 'sine-wave sequence' of PWM Duty Cycles - to a proper 'filter stage''  - which may then yield - (near) Sine Waves.     It is likely (or hoped) that your SoundStart project provided such detail.     Minus that 'properly varying PWM Duty signal' - and the following 'filter' - impure and/or unpleasant sound - is about all you may hope to achieve.     I've tried my best to 'guide you' - yet the 'fine detail' is yours - as my time here is (very) short...

    Check carefully to see if this vendor has an 'Audio Forum.'      It proves worthwhile for you to enter 'Soundstart' w/in the Forum's Search box.    (atop the forum's page ... doing so - I found '3 hits' - one being this thread!)    Be sure to read the other two - they may provide further insight...

    Your Windows based PC includes .WAV files - I believe that some may produce 'reasonably pure' sine waves - which may 'aid & inform' your development & testing.      

    Wish you well - my time here has substantially ended - 'bon chance mon ami.'

  • Sir,

    Thanks a lot for providing insight of your experience & nice tips to dig deep.

    I will try to explore further through other blogs.

    Glad to hear from you in near future!

    Good bye!!!!