Exemplo n.º 1
1
//*****************************************************************************
//
// The interrupt handler for the for PWM0 interrupts.
//
//*****************************************************************************
void
PWM0IntHandler(void)
{
    //
    // Clear the PWM0 LOAD interrupt flag.  This flag gets set when the PWM
    // counter gets reloaded.
    //
    PWMGenIntClear(PWM_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);

    //
    // If the duty cycle is less or equal to 75% then add 0.1% to the duty
    // cycle.  Else, reset the duty cycle to 0.1% cycles.  Note that 64 is
    // 0.01% of the period (64000 cycles).
    //
    if((PWMPulseWidthGet(PWM_BASE, PWM_OUT_0) + 64) <=
       ((PWMGenPeriodGet(PWM_BASE, PWM_GEN_0) * 3) / 4))
    {
        PWMPulseWidthSet(PWM_BASE, PWM_OUT_0,
                         PWMPulseWidthGet(PWM_BASE, PWM_OUT_0) + 64);
    }
    else
    {
        PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 64);
    }
}
Exemplo n.º 2
0
void PWMGen1Handler()
{
	PWMGenIntClear(PWM0_BASE, PWM_GEN_1, PWM_INT_CNT_LOAD);

	if (!camera_DBSelected)
	{
		camera_DBSelected = 1;
		uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_ALT_SELECT,
		UDMA_MODE_PINGPONG, (void*) (ADC0_BASE + ADC_O_SSFIFO3),
				camera_DoubleBuffer[camera_DBSelected], CAMERA_SAMPLES);
        // switch camera input to near camera
	    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
        current_Camera = FAR;
	}
	if (camera_DBSelected)
	{
		camera_DBSelected = 0;
		uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT,
		UDMA_MODE_PINGPONG, (void*) (ADC0_BASE + ADC_O_SSFIFO3),
				camera_DoubleBuffer[camera_DBSelected], CAMERA_SAMPLES);
        // switch camera input to far camera
	    ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);
        current_Camera = NEAR;
	}
}
Exemplo n.º 3
0
// Upon the PWM rising edge, the current system time is measured, a counter is incremented
// and the number of pulses generated to that point is checked.
void transponder_pulse_isr(void)
{
	PWMGenIntClear(PWM0_BASE, PWM_GEN_2, PWM_INT_CNT_LOAD);

	if(g_transponder_pulse_count >= 0)
		g_transponder_times[g_transponder_pulse_count] = stopwatch_get_time_us(&g_transponder_stopwatch);	//TODO: consider if the response hasnt occured

	g_transponder_pulse_count++;
	stopwatch_start(&g_transponder_stopwatch);

	if (g_transponder_pulse_count >= g_num_pulses)
		PWMGenDisable(PWM0_BASE, PWM_GEN_2);
}
Exemplo n.º 4
0
// Save as the first airspeed pulse gen ISR as above, however
// The PWM module is disabled after 3 pulses are generated
void airspeed_pulse_isr_gpio_test_b(void)
{
	PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);


	if(g_airspeed_pulse_count >= 1)
		// Proccess last latency measurement
		g_airspeed_times[g_airspeed_pulse_count] = stopwatch_get_time_us(&g_airspeed_stopwatch);

	// Increment the pulse count if output is currently enabled and disable output
	// if two pulses have been generated
	g_airspeed_pulse_count += 1 - test_b_output_toggle();
	stopwatch_start(&g_airspeed_stopwatch);

	if (g_airspeed_pulse_count >= MAX_NUM_PULSES)
		PWMGenDisable(PWM0_BASE, PWM_GEN_0);
}
Exemplo n.º 5
0
// Upon the PWM rising edge, the current system time is measured, a counter is incremented
// and the number of pulses generated to that point is checked.
void airspeed_pulse_isr(void)
{
	PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_LOAD);

	//GPIOPinWrite(GPIO_PORTC_BASE, (1<<2), (1<<2)); // debug

	if(g_airspeed_pulse_count >= 0)
		// Proccess last latency measurement
		g_airspeed_times[g_airspeed_pulse_count] = stopwatch_get_time_us(&g_airspeed_stopwatch);

	g_airspeed_pulse_count++;
	stopwatch_start(&g_airspeed_stopwatch);

	if (g_airspeed_pulse_count >= g_num_pulses)
		PWMGenDisable(PWM0_BASE, PWM_GEN_0);

	//GPIOPinWrite(GPIO_PORTC_BASE, (1<<2), ~(1<<2)); // debug
}
Exemplo n.º 6
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))
Exemplo n.º 7
0
//--------------------------------
extern "C" void OnPWM1Gen1Interrupt(void) {
	PWMGenIntClear(PWM1_BASE, PWM_GEN_1, PWM_INT_CNT_LOAD);
	if (g_pTheStepper) {
		g_pTheStepper->OnInterrupt();
	}
}
Exemplo n.º 8
0
//*****************************************************************************
//
//! Handles the PWM interrupt.
//!
//! This function is called as a result of the interrupt generated by the PWM
//! module when the counter reaches zero.  If an updated PWM frequency or duty
//! cycle is available, they will be updated in the hardware by this function.
//!
//! \return None.
//
//*****************************************************************************
void
PWM0IntHandler(void)
{
    //
    // Clear the PWM interrupt.  This is done twice since the clear will be
    // ignored by hardware if it occurs on the same cycle as another interrupt
    // event; the second clear takes care of the case wehre the first gets
    // ignored.
    //
    PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);
    PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);

    //
    // Increment the count of PWM periods.
    //
    g_ulPWMPeriodCount++;

    //
    // See if it is time for a new PWM duty cycle, based on the correct number
    // of PWM periods passing and the availability of new duty cycle values.
    //
    if((g_ulPWMPeriodCount > g_sParameters.ucUpdateRate) &&
       (HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_DUTY_CYCLE) == 1))
    {
        //
        // See if the PWM frequency needs to be updated.
        //
        if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_FREQUENCY) == 1)
        {
            //
            // Set the new PWM period in each of the PWM generators.
            //
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, g_ulPWMClock);
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, g_ulPWMClock);
            PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, g_ulPWMClock);

            //
            // Indicate that the PWM frequency has been updated.
            //
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_FREQUENCY) = 0;
        }

        //
        // Update the duty cycle.
        //
        PWMUpdateDutyCycle();

        //
        // Clear the duty cycle update flag.
        //
        HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_DUTY_CYCLE) = 0;
    }

    //
    // If the required number of PWM periods have expired, request an update of
    // the duty cycle computations.
    //
    if(g_ulPWMPeriodCount >= (g_sParameters.ucUpdateRate + 1))
    {
        if(g_sParameters.ucModulationType == MOD_TYPE_SINE)
        {
            //
            // Trigger the waveform update software interrupt.
            //
            HWREG(NVIC_SW_TRIG) = INT_PWM0_1 - 16;
        }
        else
        {
            //
            // Reduce the PWM period count based on the number of updates that
            // would have occurred if the motor drive was running.
            //
            PWMReducePeriodCount((PWMGetPeriodCount() /
                                 (g_sParameters.ucUpdateRate + 1)) *
                                 (g_sParameters.ucUpdateRate + 1));

        }
    }

    //
    // Increment the millisecond counter.  By adding 1000 for each PWM
    // interrupt, it will take one millisecond for the counter to reach the PWM
    // frequency.
    //
    g_ulPWMMillisecondCount += 1000;

    //
    // See if a millisecond has expired.
    //
    if(g_ulPWMMillisecondCount >= g_ulPWMFrequency)
    {
        //
        // Trigger the millisecond software interrupt.
        //
        HWREG(NVIC_SW_TRIG) = INT_PWM0_2 - 16;

        //
        // Decrement the millisecond counter by the PWM frequency, which
        // corresponds to one millisecond.
        //
        g_ulPWMMillisecondCount -= g_ulPWMFrequency;

        //
        // Run the precharge state machine.
        // Note:  The minimum precharge define (in pwm_ctrl.h) must account
        // for all states in this simple state machine.
        //
        if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_PRECHARGE) == 1)
        {
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_NEW_PRECHARGE) = 0;
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_A) = 1;
        }
        else if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_A) == 1)
        {
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_A) = 0;
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_B) = 1;
            PWMOutputState(PWM0_BASE, PWM_OUT_1_BIT, true);
        }
        else if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_B) == 1)
        {
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_B) = 0;
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_C) = 1;
            PWMOutputState(PWM0_BASE, PWM_OUT_3_BIT, true);
        }
        else if(HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_C) == 1)
        {
            HWREGBITW(&g_ulPWMFlags, PWM_FLAG_SET_OUTPUT_C) = 0;
            PWMOutputState(PWM0_BASE, PWM_OUT_5_BIT, true);
        }
    }
}
Exemplo n.º 9
0
//*****************************************************************************
//
//! Initializes the PWM control routines.
//!
//! This function initializes the PWM module and the control routines,
//! preparing them to produce PWM waveforms to drive the power module.
//!
//! \return None.
//
//*****************************************************************************
void
PWMInit(void)
{
    //
    // Make the PWM pins be peripheral function.
    //
    GPIOPinTypePWM(PIN_PHASEA_LOW_PORT,
                   PIN_PHASEA_LOW_PIN | PIN_PHASEA_HIGH_PIN);
    GPIOPinTypePWM(PIN_PHASEB_LOW_PORT,
                   PIN_PHASEB_LOW_PIN | PIN_PHASEB_HIGH_PIN);
    GPIOPinTypePWM(PIN_PHASEC_LOW_PORT,
                   PIN_PHASEC_LOW_PIN | PIN_PHASEC_HIGH_PIN);

    //
    // Configure the three PWM generators for up/down counting mode,
    // synchronous updates, and to stop at zero on debug events.
    //
    PWMGenConfigure(PWM0_BASE, PWM_GEN_0, (PWM_GEN_MODE_UP_DOWN |
                                           PWM_GEN_MODE_SYNC |
                                           PWM_GEN_MODE_DBG_STOP));
    PWMGenConfigure(PWM0_BASE, PWM_GEN_1, (PWM_GEN_MODE_UP_DOWN |
                                           PWM_GEN_MODE_SYNC |
                                           PWM_GEN_MODE_DBG_STOP));
    PWMGenConfigure(PWM0_BASE, PWM_GEN_2, (PWM_GEN_MODE_UP_DOWN |
                                           PWM_GEN_MODE_SYNC |
                                           PWM_GEN_MODE_DBG_STOP));

    //
    // Set the initial duty cycles to 50%.
    //
    g_ulPWMDutyCycleA = 32768;
    g_ulPWMDutyCycleB = 32768;
    g_ulPWMDutyCycleC = 32768;

    //
    // Configure the PWM period, duty cycle, and dead band.  The initial period
    // is 1 KHz (for triggering the ADC), which will be increased when the
    // motor starts running.
    //
    PWMClearDeadBand();
    PWMSetFrequency();
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, PWM_CLOCK / 1000);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, PWM_CLOCK / 1000);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_2, PWM_CLOCK / 1000);
    PWMUpdateDutyCycle();

    //
    // Enable the PWM generators.
    //
    PWMGenEnable(PWM0_BASE, PWM_GEN_0);
    PWMGenEnable(PWM0_BASE, PWM_GEN_1);
    PWMGenEnable(PWM0_BASE, PWM_GEN_2);

    //
    // Synchronize the time base of the generators.
    //
    PWMSyncTimeBase(PWM0_BASE, PWM_GEN_0_BIT | PWM_GEN_1_BIT | PWM_GEN_2_BIT);

    //
    // Configure an interrupt on the zero event of the first generator, and an
    // ADC trigger on the load event of the first generator.
    //
    PWMGenIntClear(PWM0_BASE, PWM_GEN_0, PWM_INT_CNT_ZERO);
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_0,
                        PWM_INT_CNT_ZERO | PWM_TR_CNT_LOAD);
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_1, 0);
    PWMGenIntTrigEnable(PWM0_BASE, PWM_GEN_2, 0);
    PWMIntEnable(PWM0_BASE, PWM_INT_GEN_0);
    IntEnable(INT_PWM0_0);
    IntEnable(INT_PWM0_1);
    IntEnable(INT_PWM0_2);

    //
    // Set all six PWM outputs to go to the inactive state when a fault event
    // occurs (which includes debug events).
    //
    PWMOutputFault(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
                               PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
                   true);

    //
    // Disable all six PWM outputs.
    //
    PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
                               PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
                   false);

    //
    // Ensure that all outputs are not-inverted.
    //
    PWMOutputInvert(PWM0_BASE, (PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM_OUT_2_BIT |
                                PWM_OUT_3_BIT | PWM_OUT_4_BIT | PWM_OUT_5_BIT),
                    false);
}