//*****************************************************************************
//
//! Configures the dead timers for the PWM generators.
//!
//! This function configures the dead timers for all three PWM generators based
//! on the dead time parameter.
//!
//! \return None.
//
//*****************************************************************************
void
PWMSetDeadBand(void)
{
    //
    // Set the dead band times for all three PWM generators.
    //
    PWMDeadBandEnable(PWM0_BASE, PWM_GEN_0, g_sParameters.ucDeadTime,
                      g_sParameters.ucDeadTime);
    PWMDeadBandEnable(PWM0_BASE, PWM_GEN_1, g_sParameters.ucDeadTime,
                      g_sParameters.ucDeadTime);
    PWMDeadBandEnable(PWM0_BASE, PWM_GEN_2, g_sParameters.ucDeadTime,
                      g_sParameters.ucDeadTime);

    //
    // Update the minimum PWM pulse width.
    //
    PWMSetMinPulseWidth();
}
Esempio n. 2
0
//*****************************************************************************
//
// Configure the PWM0 block with dead-band generation.  The example configures
// the PWM0 block to generate a 25% duty cycle signal on PD0 with dead-band
// generation.  This will produce a complement of PD0 on PD1 (75% duty cycle).
// The dead-band generator is set to have a 10us or 160 cycle delay
// (160cycles / 16Mhz = 10us) on the rising and falling edges of the PD0 PWM
// signal.
//
//*****************************************************************************
int
main(void)
{
    //
    // Set the clocking to run directly from the external crystal/oscillator.
    // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
    // crystal on your board.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_16MHZ);

    //
    // Set the PWM clock to the system clock.
    //
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

    //
    // Set up the serial console to use for displaying messages.  This is just
    // for this example program and is not needed for PWM operation.
    //
    InitConsole();

    //
    // Display the setup on the console.
    //
    UARTprintf("PWM ->\n");
    UARTprintf("  Module: PWM0\n");
    UARTprintf("  Pin(s): PD0 and PD1\n");
    UARTprintf("  Features: Dead-band Generation\n");
    UARTprintf("  Duty Cycle: 25%% on PD0 and 75%% on PD1\n");
    UARTprintf("  Dead-band Length: 160 cycles on rising and falling edges\n\n");
    UARTprintf("Generating PWM on PWM0 (PD0) -> ");

    //
    // The PWM peripheral must be enabled for use.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);

    //
    // For this example PWM0 is used with PortD Pins 0 and 1.  The actual port
    // and pins used may be different on your part, consult the data sheet for
    // more information.  GPIO port D needs to be enabled so these pins can be
    // used.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

    //
    // Configure the GPIO pin muxing to select PWM functions for these pins.
    // This step selects which alternate function is available for these pins.
    // This is necessary if your part supports GPIO pin function muxing.
    // Consult the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PD0_PWM0);
    GPIOPinConfigure(GPIO_PD1_PWM1);

    //
    // Configure the GPIO pad for PWM function on pins PD0 and PD1.  Consult
    // the data sheet to see which functions are allocated per pin.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0);
    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_1);

    //
    // Configure the PWM0 to count up/down without synchronization.
    // Note: Enabling the dead-band generator automatically couples the 2
    // outputs from the PWM block so we don't use the PWM synchronization.
    //
    PWMGenConfigure(PWM_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN |
                    PWM_GEN_MODE_NO_SYNC);

    //
    // Set the PWM period to 250Hz.  To calculate the appropriate parameter
    // use the following equation: N = (1 / f) * SysClk.  Where N is the
    // function parameter, f is the desired frequency, and SysClk is the
    // system clock frequency.
    // In this case you get: (1 / 250Hz) * 16MHz = 64000 cycles.  Note that
    // the maximum period you can set is 2^16 - 1.
    // TODO: modify this calculation to use the clock frequency that you are
    // using.
    //
    PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, 64000);

    //
    // Set PWM0 PD0 to a duty cycle of 25%.  You set the duty cycle as a
    // function of the period.  Since the period was set above, you can use the
    // PWMGenPeriodGet() function.  For this example the PWM will be high for
    // 25% of the time or 16000 clock cycles (64000 / 4).
    //
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_0,
                     PWMGenPeriodGet(PWM_BASE, PWM_OUT_0) / 4);

    //
    // Enable the dead-band generation on the PWM0 output signal.  PWM bit 0
    // (PD0), will have a duty cycle of 25% (set above) and PWM bit 1 will have
    // a duty cycle of 75%.  These signals will have a 10us gap between the
    // rising and falling edges.  This means that before PWM bit 1 goes high,
    // PWM bit 0 has been low for at LEAST 160 cycles (or 10us) and the same
    // before PWM bit 0 goes high.  The dead-band generator lets you specify
    // the width of the "dead-band" delay, in PWM clock cycles, before the PWM
    // signal goes high and after the PWM signal falls.  For this example we
    // will use 160 cycles (or 10us) on both the rising and falling edges of
    // PD0.  Reference the datasheet for more information on dead-band
    // generation.
    //
    PWMDeadBandEnable(PWM_BASE, PWM_GEN_0, 160, 160);

    //
    // Enable the PWM0 Bit 0 (PD0) and Bit 1 (PD1) output signals.
    //
    PWMOutputState(PWM_BASE, PWM_OUT_1_BIT | PWM_OUT_0_BIT, true);

    //
    // Enables the counter for a PWM generator block.
    //
    PWMGenEnable(PWM_BASE, PWM_GEN_0);

    //
    // Loop forever while the PWM signals are generated.
    //
    while(1)
    {
        //
        // Print out indication on the console that the program is running.
        //
        PrintRunningDots();
    }
}
Esempio n. 3
0
//*****************************************************************************
//
//! Handles the PWM1 interrupt.
//!
//! This function responds to the PWM1 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
//! PWM1 interrupt, typically by installing it in the vector table as the
//! handler for the PWM1 interrupt.
//!
//! \return None.
//
//*****************************************************************************
void
ClassDPWMHandler(void)
{
    long lStep, lNibble, lDutyCycle;

    //
    // Clear the PWM interrupt.
    //
    PWMGenIntClear(PWM_BASE, PWM_GEN_1, PWM_INT_CNT_ZERO);

    //
    // See if the startup ramp is in progress.
    //
    if(HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_STARTUP))
    {
        //
        // Decrement the ramp count.
        //
        g_ulClassDStep--;

        //
        // Increase the pulse width of the two outputs by one clock.
        //
        PWMDeadBandEnable(PWM_BASE, PWM_GEN_1, 0, g_ulClassDStep);
        PWMPulseWidthSet(PWM_BASE, PWM_OUT_2,
                         (g_ulClassDPeriod - g_ulClassDStep) / 2);

        //
        // See if this was the last step of the ramp.
        //
        if(g_ulClassDStep == 0)
        {
            //
            // Indicate that the startup ramp has completed.
            //
            HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_STARTUP) = 0;
        }

        //
        // There is nothing further to be done.
        //
        return;
    }

    //
    // See if the shutdown ramp is in progress.
    //
    if(HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_SHUTDOWN))
    {
        //
        // See if this was the last step of the ramp.
        //
        if(g_ulClassDStep == (g_ulClassDPeriod - 2))
        {
            //
            // Disable the PWM2 and PWM3 output signals.
            //
            PWMOutputState(PWM_BASE, PWM_OUT_2_BIT | PWM_OUT_3_BIT, false);

            //
            // Clear the Class-D audio flags.
            //
            g_ulClassDFlags = 0;

            //
            // Disable the PWM interrupt.
            //
            IntDisable(INT_PWM1);
        }
        else
        {
            //
            // Increment the ramp count.
            //
            g_ulClassDStep++;

            //
            // Decrease the pulse width of the two outputs by one clock.
            //
            PWMDeadBandEnable(PWM_BASE, PWM_GEN_1, 0, g_ulClassDStep);
            PWMPulseWidthSet(PWM_BASE, PWM_OUT_2,
                             (g_ulClassDPeriod - g_ulClassDStep) / 2);
        }

        //
        // There is nothing further to be done.
        //
        return;
    }

    //
    // 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 audio (it produces
    // a significant amount of harmonic aliasing) but it is fast.
    //
    lDutyCycle = (((g_pusClassDSamples[0] * (8 - (g_ulClassDStep & 7))) +
                   (g_pusClassDSamples[1] * (g_ulClassDStep & 7))) / 8);

    //
    // Adjust the magnitude of the sample based on the current volume.  Since a
    // multiplicative volume control is implemented, the volume value will
    // result in nearly linear volume adjustment if it is squared.
    //
    lDutyCycle = (((lDutyCycle - 32768) * g_lClassDVolume * g_lClassDVolume) /
                  65536) + 32768;

    //
    // Set the PWM duty cycle based on this PCM sample.
    //
    lDutyCycle = (g_ulClassDPeriod * lDutyCycle) / 65536;
    if(lDutyCycle > (g_ulClassDPeriod - 2))
    {
        lDutyCycle = g_ulClassDPeriod - 2;
    }
    if(lDutyCycle < 2)
    {
        lDutyCycle = 2;
    }
    PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, lDutyCycle);

    //
    // Increment the audio step.
    //
    g_ulClassDStep++;

    //
    // See if the next sample has been reached.
    //
    if((g_ulClassDStep & 7) == 0)
    {
        //
        // Copy the current sample to the previous sample.
        //
        g_pusClassDSamples[0] = g_pusClassDSamples[1];

        //
        // See if there is more input data.
        //
        if(g_ulClassDLength == 0)
        {
            //
            // All input data has been played, so start a shutdown to avoid a
            // pop.
            //
            g_ulClassDFlags = 0;
            HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_SHUTDOWN) = 1;
            g_ulClassDStep = 0;
        }

        //
        // See if an ADPCM stream is being played.
        //
        else if(HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_ADPCM))
        {
            //
            // See which nibble should be decoded.
            //
            if((g_ulClassDStep & 8) == 0)
            {
                //
                // Extract the lower nibble from the current byte, and skip to
                // the next byte.
                //
                lNibble = *g_pucClassDBuffer++;

                //
                // Decrement the count of bytes to be decoded.
                //
                g_ulClassDLength--;
            }
            else
            {
                //
                // Extract the upper nibble from the current byte.
                //
                lNibble = *g_pucClassDBuffer >> 4;
            }

            //
            // Compute the sample delta based on the current nibble and step
            // size.
            //
            lStep = ((((2 * (lNibble & 7)) + 1) *
                      g_pusADPCMStep[g_lClassDADPCMStepIndex]) / 16);

            //
            // Add or subtract the delta to the previous sample value, clipping
            // if necessary.
            //
            if(lNibble & 8)
            {
                lStep = g_pusClassDSamples[0] - lStep;
                if(lStep < 0)
                {
                    lStep = 0;
                }
            }
            else
            {
                lStep = g_pusClassDSamples[0] + lStep;
                if(lStep > 65535)
                {
                    lStep = 65535;
                }
            }

            //
            // Store the generated sample.
            //
            g_pusClassDSamples[1] = lStep;

            //
            // Adjust the step size index based on the current nibble, clipping
            // the value if required.
            //
            g_lClassDADPCMStepIndex += g_pcADPCMIndex[lNibble & 7];
            if(g_lClassDADPCMStepIndex < 0)
            {
                g_lClassDADPCMStepIndex = 0;
            }
            if(g_lClassDADPCMStepIndex > 88)
            {
                g_lClassDADPCMStepIndex = 88;
            }
        }

        //
        // See if a 8-bit PCM stream is being played.
        //
        else if(HWREGBITW(&g_ulClassDFlags, CLASSD_FLAG_PCM))
Esempio n. 4
0
void hardware_init(void)
{
	//Set PWM clock at the same frequency as system clock
	SysCtlPWMClockSet(SYSCTL_PWMDIV_1);

	/*
	 * Inverter system setup
	 * period : Switching Frequency : 20Khz
	 * cycle : Duty Cycle SPWM
	 * deadband : Deadband
	 */
	inv.period = SysCtlClockGet()/20000;
	inv.deadband = 25*inv.period/100;
	inv.cycle = inv.period*500/1000;

	/*
	 * Boost converter system setup
	 * period: Switching frequency: 20kHz
	 * cycle: Duty cycle
	 * deadband: Deadband
	 */
	conv.period = inv.period;
	conv.deadband = inv.deadband;
	conv.cycle = conv.period*500/1000;

	/*
	 * Setup SPWM on PWM0 GEN0 and GEN1
	 * PB6 : PWM0 GEN0
	 * PB7: PWM0 GEN1
	 */
	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

	SysCtlPeripheralReset(SYSCTL_PERIPH_PWM0);
	SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOB);

	GPIOPinConfigure(GPIO_PB6_M0PWM0);
	GPIOPinConfigure(GPIO_PB7_M0PWM1);

	GPIOPinTypePWM(GPIO_PORTB_BASE, (GPIO_PIN_6 | GPIO_PIN_7));

	PWMGenConfigure(PWM0_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_GEN_SYNC_LOCAL | PWM_GEN_MODE_FAULT_UNLATCHED | PWM_GEN_MODE_DB_NO_SYNC));
	PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, inv.period-1);
	PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, inv.cycle);
	PWMDeadBandEnable(PWM0_BASE, PWM_GEN_0, 13, 0);
	PWMGenEnable(PWM0_BASE, PWM_GEN_0);
	PWMOutputState(PWM0_BASE, PWM_OUT_0_BIT|PWM_OUT_1_BIT, true);

	PWMSyncUpdate(PWM0_BASE, PWM_OUT_0_BIT|PWM_OUT_1_BIT);

	/*
	 * Setup boost converter pwm on PWM1
	 * PA6: PWM1 GEN1
	 */
	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

	SysCtlPeripheralReset(SYSCTL_PERIPH_PWM1);
	SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOA);

	GPIOPinConfigure(GPIO_PA6_M1PWM2);	//Map PWM1, P1 OP2 to PA6
	GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6);	//Configure PA6 as PWM

	PWMGenConfigure(PWM1_BASE, PWM_GEN_1, (PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_GEN_NO_SYNC| PWM_GEN_MODE_DB_NO_SYNC));	//Configure PWM1, G1 as Down counter with no sync of updates
	PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, conv.period-1);	//Set Period of PWM1, G1
	PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2, conv.cycle);	//Set phase shift

	PWMIntEnable(PWM1_BASE, PWM_INT_GEN_1);
	PWMGenIntTrigEnable(PWM1_BASE, PWM_GEN_1, PWM_TR_CNT_LOAD|PWM_INT_CNT_LOAD);
	IntPrioritySet(INT_PWM1_1, 0x02);
	PWMOutputState(PWM1_BASE, PWM_OUT_2_BIT, true);

	PWMGenEnable(PWM1_BASE, PWM_GEN_1);

	/*
	 * Setup ISR for updating SPWM duty cycle
	 */
	uint32_t ui32TimIntSine = SysCtlClockGet()/200000;

	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);

	SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER2);

	TimerConfigure(TIMER2_BASE, TIMER_CFG_A_PERIODIC);
	TimerLoadSet(TIMER2_BASE, TIMER_A, ui32TimIntSine-1);

	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
	IntPrioritySet(INT_TIMER2A, 0x03);
	TimerEnable(TIMER2_BASE, TIMER_A);

	uint32_t ui32TimIntIcontrol = SysCtlClockGet()/40000;

	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
	SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER1);

	TimerConfigure(TIMER1_BASE, TIMER_CFG_A_PERIODIC);
	TimerLoadSet(TIMER1_BASE, TIMER_A, ui32TimIntIcontrol-1);

	TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
	IntPrioritySet(INT_TIMER1A, 0x01);
	TimerEnable(TIMER1_BASE, TIMER_A);

	/*
	 * Setup PF1 as debug pin
	 */
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

//	SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOF);

	HWREG(0x40005520) = 0x4C4F434B;
	HWREG(0x40005524) |= 0x01;
	HWREG(0x40005520) = 0x00;

	GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);

	GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);

	GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_4, GPIO_FALLING_EDGE);

	IntPrioritySet(INT_GPIOF,0x00);
	GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_4);

	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);

	/*
	 * Setup ADC
	 * Configuration currently in discussion
	 * Interrupt at end might not be necessary
	 */
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

	SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);

	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2);
	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1);
	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

	SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0);

	ADCHardwareOversampleConfigure(ADC0_BASE, 2);
	ADCSequenceDisable(ADC0_BASE, 2);

	ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_PWM1, 0x00);
	HWREG(0x4003801C) |= 0x1000;	//Sec 13.4.2 Pt 3

	ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH1);

	ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH2);

	ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH3|ADC_CTL_IE|ADC_CTL_END);

	ADCSequenceEnable(ADC0_BASE, 2);
}