Пример #1
0
int
read_pins(struct header_pin pins[], uint16_t length, uint8_t *buf) {
  static char bnone[] = "\"x\"";
  uint16_t i = 0;

  int l;
  for(l=0;l<length;l++) {
    if( l > 0)
      buf[i++] = ',';
    printf("pin %d: %d\n", l, pins[l].config);
    if( pins[l].config == CONFIG_NOT_USED) {
      memcpy(buf+i, bnone, sizeof(bnone)-1);
      i+= sizeof(bnone)-1;
    } else if( pins[l].config == CONFIG_OUTPUT ) {
      if( MAP_GPIOPinRead(pins[l].base, pins[l].pin) == 0x00 ) {
	buf[i++] = '2';
      } else {
	buf[i++] = '3';
      }
    } else {
      if( MAP_GPIOPinRead(pins[l].base, pins[l].pin) == 0x00 ) {
	buf[i++] = '0';
      } else {
	buf[i++] = '1';
      }
    }
  }
  return i;
}
Пример #2
0
//*****************************************************************************
//! Wait while the safe mode pin is being held high and blink the system led
//! with the specified period
//*****************************************************************************
static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
    _u32 count;
    for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
         ((period * count) < wait_time); count++) {
        // toogle the led
        MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
        UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
    }
    return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
}
Пример #3
0
//*****************************************************************************
//! Check for the safe mode pin
//*****************************************************************************
static bool safe_mode_boot (void) {
    _u32 count = 0;
    while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
           ((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
        // toogle the led
        MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
        UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
    }
    mperror_deinit_sfe_pin();
    return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
}
Пример #4
0
pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
{
    pio_type retval = 1, base = pio_base[ port ];

    switch( op )
    {
    case PLATFORM_IO_PORT_SET_VALUE:
        MAP_GPIOPinWrite( base, 0xFF, pinmask );
        break;

    case PLATFORM_IO_PIN_SET:
        MAP_GPIOPinWrite( base, pinmask, pinmask );
        break;

    case PLATFORM_IO_PIN_CLEAR:
        MAP_GPIOPinWrite( base, pinmask, 0 );
        break;

    case PLATFORM_IO_PORT_DIR_INPUT:
        pinmask = 0xFF;
    case PLATFORM_IO_PIN_DIR_INPUT:
        MAP_GPIOPinTypeGPIOInput( base, pinmask );
        break;

    case PLATFORM_IO_PORT_DIR_OUTPUT:
        pinmask = 0xFF;
    case PLATFORM_IO_PIN_DIR_OUTPUT:
        MAP_GPIOPinTypeGPIOOutput( base, pinmask );
        break;

    case PLATFORM_IO_PORT_GET_VALUE:
        retval = MAP_GPIOPinRead( base, 0xFF );
        break;

    case PLATFORM_IO_PIN_GET:
        retval = MAP_GPIOPinRead( base, pinmask ) ? 1 : 0;
        break;

    case PLATFORM_IO_PIN_PULLUP:
    case PLATFORM_IO_PIN_PULLDOWN:
        MAP_GPIOPadConfigSet( base, pinmask, GPIO_STRENGTH_8MA, op == PLATFORM_IO_PIN_PULLUP ? GPIO_PIN_TYPE_STD_WPU : GPIO_PIN_TYPE_STD_WPD );
        break;

    case PLATFORM_IO_PIN_NOPULL:
        MAP_GPIOPadConfigSet( base, pinmask, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD );
        break;

    default:
        retval = 0;
        break;
    }
    return retval;
}
Пример #5
0
int arch_GpioRead(uint_t nPort, uint_t nPin)
{

	if (MAP_GPIOPinRead(arch_GpioPortBase(nPort), BITMASK(nPin)))
		return 1;
	return 0;
}
Пример #6
0
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
 * or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
 * to 3 minutes in length, but must be called at least a few dozen microseconds
 * before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
    // cache the port and bit of the pin in order to speed up the
    // pulse width measuring loop and achieve finer resolution.  calling
    // digitalRead() instead yields much coarser resolution.
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    uint32_t portBase = (uint32_t) portBASERegister(port);
	uint8_t stateMask = (state ? bit : 0);

    // convert the timeout from microseconds to a number of times through
    // the initial loop; it takes 11 clock cycles per iteration.
    unsigned long numloops = 0;
    unsigned long maxloops = microsecondsToClockCycles(timeout) / 11;

    // wait for any previous pulse to end
    while (MAP_GPIOPinRead(portBase, bit) == stateMask)
        if (numloops++ == maxloops)
            return 0;

    // wait for the pulse to start
    while (MAP_GPIOPinRead(portBase, bit) != stateMask)
        if (numloops++ == maxloops)
            return 0;

    // wait for the pulse to stop
    unsigned long start = micros();

    while (MAP_GPIOPinRead(portBase, bit) == stateMask) {
        if (numloops++ == maxloops)
            return 0;
    }
    unsigned long end = micros();
    unsigned long result = end - start;
    return(result);
    // convert the reading to microseconds. The loop has been determined
    // to be 13 clock cycles long and have about 11 clocks between the edge
    // and the start of the loop. There will be some error introduced by
    // the interrupt handlers.
    //return clockCyclesToMicroseconds(width * 13 + 11);
}
Пример #7
0
//*****************************************************************************
//
//! MicroPhone Control Routine
//!
//! \param  pValue - pointer to a memory structure that is passed 
//!         to the interrupt handler.
//!
//! \return None
//
//*****************************************************************************
void MicroPhoneControl(void* pValue)
{
    int iCount=0;
    unsigned long ulPin5Val = 1; 
    
    //Check whether GPIO Level is Stable As No Debouncing Circuit in LP
    for(iCount=0;iCount<3;iCount++)
    {
        osi_Sleep(200);
        ulPin5Val = MAP_GPIOPinRead(GPIOA1_BASE,GPIO_PIN_5);
        if(ulPin5Val)
        {
            //False Alarm
            return;
        }
    }
    if (g_ucMicStartFlag ==  0)
    {
        for(iCount = 0; iCount<3; iCount++)
        {
            //Blink LED 3 times to Indicate ON
            GPIO_IF_LedOff(MCU_GREEN_LED_GPIO);
            osi_Sleep(50);
            GPIO_IF_LedOn(MCU_GREEN_LED_GPIO);
            osi_Sleep(50);
        }
         g_ucMicStartFlag = 1;
        
     }
     else
     {
        //Blink LED 3 times to Indicate OFF
        for(iCount = 0; iCount<3; iCount++)
        {
            GPIO_IF_LedOn(MCU_GREEN_LED_GPIO);
            osi_Sleep(50);
            GPIO_IF_LedOff(MCU_GREEN_LED_GPIO);
            osi_Sleep(50);
        }
        g_ucMicStartFlag = 0;
     }
    
     //Enable GPIO Interrupt 
     MAP_GPIOIntClear(GPIOA1_BASE,GPIO_PIN_5);
     MAP_IntPendClear(INT_GPIOA1);
     MAP_IntEnable(INT_GPIOA1);
     MAP_GPIOIntEnable(GPIOA1_BASE,GPIO_PIN_5);

}
static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear )
{
  unsigned long portbase = pio_base[ PLATFORM_IO_GET_PORT( resnum ) ];
  u8 pinmask = 1 << PLATFORM_IO_GET_PIN( resnum );

  if( MAP_GPIOPinRead( portbase, pinmask ) != 0 )
    return 0;
  if( MAP_GPIOPinIntStatus( portbase, true ) & pinmask )
  {
    if( clear )
      MAP_GPIOPinIntClear( portbase, pinmask );
    return 1;
  }
  return 0;
}
Пример #9
0
/// \method value([value])
/// Get or set the digital logic level of the pin:
///
///   - With no arguments, return 0 or 1 depending on the logic level of the pin.
///   - With `value` given, set the logic level of the pin.  `value` can be
///   anything that converts to a boolean.  If it converts to `True`, the pin
///   is set high, otherwise it is set low.
STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) {
    pin_obj_t *self = args[0];
    if (n_args == 1) {
        // get the pin value
        return MP_OBJ_NEW_SMALL_INT(MAP_GPIOPinRead(self->port, self->bit) ? 1 : 0);
    } else {
        // set the pin value
        if (mp_obj_is_true(args[1])) {
            MAP_GPIOPinWrite(self->port, self->bit, self->bit);
        } else {
            MAP_GPIOPinWrite(self->port, self->bit, 0);
        }
        return mp_const_none;
    }
}
Пример #10
0
//*****************************************************************************
//
// CheckBoardRevision uses PD1 with a weak pull down resistor to detect the
// development board hardware revision. Code for the LM4F board can run on the
// TM4C, but not vice versa. This function checks for the board verion and
// warns the user if they are using the wrong board / software.
//
// The EK-LM4F232 (green) board uses an analog accelorometer. The DK-TM4C123G
//(red) board uses a digitial I2C 9 axis accel, mag, gyro.
//
//*****************************************************************************
void
CheckBoardRevision(void)
{
    uint32_t ui32BoardType;
    tContext sDisplayContext;
    //
    // Check if board is TM4C123G (red) or LM4F232 (green). This code
    // should not be run on green board.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    MAP_GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_DIR_MODE_IN);
    MAP_GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_1,
                         GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPD);
    ui32BoardType=MAP_GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_1);
    if(ui32BoardType==0)
    {
        //
        // The board is green, print error message and hang.
        //
        CFAL96x64x16Init();
        GrContextInit(&sDisplayContext, &g_sCFAL96x64x16);
        GrContextForegroundSet(&sDisplayContext, ClrWhite);
        GrContextFontSet(&sDisplayContext, g_psFontFixed6x8);
        GrStringDrawCentered(&sDisplayContext, "ERROR:", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 4, 0);
        GrStringDrawCentered(&sDisplayContext, "Due to different", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 20, false);
        GrStringDrawCentered(&sDisplayContext, "hardware this", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 30, false);
        GrStringDrawCentered(&sDisplayContext, "code cannot run", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 40, false);
        GrStringDrawCentered(&sDisplayContext, "on this board", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 50, false);
        GrStringDrawCentered(&sDisplayContext, "Try diff code.", -1,
                             GrContextDpyWidthGet(&sDisplayContext) / 2, 60, false);
        while(1)
        {
            // Hang here.
        }
    }
    else
    {
        //
        // The board is red, exit & continue as normal.
        //
        return ;
    }
}
Пример #11
0
void cc3200_leds(enum cc3200_led leds, enum cc3200_led_state s) {
  long v;
  leds &= (RED | GREEN | AMBER);
  switch (s) {
    case ON:
      v = ~0;
      break;
    case OFF:
      v = 0;
      break;
    case TOGGLE:
      v = ~(MAP_GPIOPinRead(GPIOA1_BASE, leds));
      break;
    default:
      return;
  }
  MAP_GPIOPinWrite(GPIOA1_BASE, leds, (v & leds));
}
static void gpio_common_handler( int port )
{
  u32 base = pio_base[ port ];
  u8 pin, pinmask;
  u32 ibe = HWREG( base + GPIO_O_IBE );
  u32 iev = HWREG( base + GPIO_O_IEV );

  // Check each pin in turn
  for( pin = 0, pinmask = 1; pin < 8; pin ++, pinmask <<= 1 )
    if( HWREG( base + GPIO_O_MIS ) & pinmask ) // interrupt on pin
    {
      if( MAP_GPIOPinRead( base, pinmask ) && ( ( ibe & pinmask ) || ( iev & pinmask ) ) ) // high level and posedge interrupt enabled 
        cmn_int_handler( INT_GPIO_POSEDGE, PLATFORM_IO_ENCODE( port, pin, 0 ) );
      else if( ( ibe & pinmask ) || !( iev & pinmask ) ) // low level and negedge interrupt enabled
        cmn_int_handler( INT_GPIO_NEGEDGE, PLATFORM_IO_ENCODE( port, pin, 0 ) );
      HWREG( base + GPIO_O_ICR ) = pinmask;
    }
}
Пример #13
0
//****************************************************************************
//
//! Set a value to the specified GPIO pin
//!
//! \param ucPin is the GPIO pin to be set (0:39)
//! \param uiGPIOPort is the GPIO port address
//! \param ucGPIOPin is the GPIO pin of the specified port
//!
//! This function
//!    1. Gets a value of the specified GPIO pin
//!
//! \return value of the GPIO pin
//
//****************************************************************************
unsigned char
GPIO_IF_Get(unsigned char ucPin,
             unsigned int uiGPIOPort,
             unsigned char ucGPIOPin)
{
    unsigned char ucGPIOValue;
    long lGPIOStatus;

    //
    // Invoke the API to Get the value
    //
    lGPIOStatus =  MAP_GPIOPinRead(uiGPIOPort,ucGPIOPin);

    //
    // Set the corresponding bit in the bitmask
    //
    ucGPIOValue = lGPIOStatus >> (ucPin % 8);
    return ucGPIOValue;
}
Пример #14
0
//*****************************************************************************
//
//! Initializes the GPIO pins used by the board pushbuttons.
//!
//! This function must be called during application initialization to
//! configure the GPIO pins to which the pushbuttons are attached.  It enables
//! the port used by the buttons and configures each button GPIO as an input
//! with a weak pull-up.
//!
//! \return None.
//
//*****************************************************************************
void
ButtonsInit(void)
{
    //
    // Enable the GPIO port to which the pushbuttons are connected.
    //
    MAP_SysCtlPeripheralEnable(BUTTONS_GPIO_PERIPH);

    //
    // Set each of the button GPIO pins as an input with a pull-up.
    //
    MAP_GPIODirModeSet(BUTTONS_GPIO_BASE, ALL_BUTTONS, GPIO_DIR_MODE_IN);
    MAP_GPIOPadConfigSet(BUTTONS_GPIO_BASE, ALL_BUTTONS,
                         GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    //
    // Initialize the debounced button state with the current state read from
    // the GPIO bank.
    //
    g_ui8ButtonStates = MAP_GPIOPinRead(BUTTONS_GPIO_BASE, ALL_BUTTONS);
}
Пример #15
0
STATIC uint8_t pin_get_value (const pin_obj_t* self) {
    uint32_t value;
    bool setdir = false;
    if (self->mode == PIN_TYPE_OD || self->mode == GPIO_DIR_MODE_ALT_OD) {
        setdir = true;
        // configure the direction to IN for a moment in order to read the pin value
        MAP_GPIODirModeSet(self->port, self->bit, GPIO_DIR_MODE_IN);
    }
    // now get the value
    value = MAP_GPIOPinRead(self->port, self->bit);
    if (setdir) {
        // set the direction back to output
        MAP_GPIODirModeSet(self->port, self->bit, GPIO_DIR_MODE_OUT);
        if (self->value) {
            MAP_GPIOPinWrite(self->port, self->bit, self->bit);
        } else {
            MAP_GPIOPinWrite(self->port, self->bit, 0);
        }
    }
    // return it
    return value ? 1 : 0;
}
Пример #16
0
// common interrupt handler
STATIC void EXTI_Handler(uint port) {
    uint32_t bits = MAP_GPIOIntStatus(port, true);
    MAP_GPIOIntClear(port, bits);

    // might be that we have more than one pin interrupt pending
    // therefore we must loop through all of the 8 possible bits
    for (int i = 0; i < 8; i++) {
        uint32_t bit = (1 << i);
        if (bit & bits) {
            pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_board_pins_locals_dict, port, bit);
            if (self->irq_trigger == (PYB_PIN_FALLING_EDGE | PYB_PIN_RISING_EDGE)) {
                // read the pin value (hoping that the pin level has remained stable)
                self->irq_flags = MAP_GPIOPinRead(self->port, self->bit) ? PYB_PIN_RISING_EDGE : PYB_PIN_FALLING_EDGE;
            } else {
                // same as the triggers
                self->irq_flags = self->irq_trigger;
            }
            mp_irq_handler(mp_irq_find(self));
            // always clear the flags after leaving the user handler
            self->irq_flags = 0;
        }
    }
}
Пример #17
0
//*****************************************************************************
//
// Called by the NVIC as a SysTick interrupt, which is used to generate the
// sample interval
//
//*****************************************************************************
void
SysTickIntHandler()
{
	unsigned char sw_pin_status;

	// get pressure data
	BMP180DataRead(&g_sBMP180Inst, BMP180AppCallback, &g_sBMP180Inst);

	// SW debounce
	sw_pin_status = ~((unsigned char)(MAP_GPIOPinRead(SW_BASE, (SW1|SW2))));

	if ( (sw_pin_status & SW1) != (sw_state & SW1) ){
		sw1_debounce_count++;
		if (sw1_debounce_count >= SW_DEBOUNCE_CNT){
			sw_state = (sw_state & ~SW1) | (sw_pin_status & SW1);
			sw1_debounce_count = 0;
		}
	}else{
		sw1_debounce_count = 0;
	}

	if ( (sw_pin_status & SW2) != (sw_state & SW2) ){
		sw2_debounce_count++;
		if (sw2_debounce_count >= SW_DEBOUNCE_CNT){
			sw_state = (sw_state & ~SW2) | (sw_pin_status & SW2);
			sw2_debounce_count = 0;
		}
	}else{
		sw2_debounce_count = 0;
	}






}
Пример #18
0
//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************
int
main(void)
{
	uint32_t ui32_Period, ui32_PWM=0, ui32_PWM_step = 40, ui32_PWM_min=2000, ui32_PWM_max=4000;
	uint32_t ui32_sw1;
    uint32_t ui32_sw2;
    //
    // 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.
    //
    //MAP_FPUEnable();
    //MAP_FPULazyStackingEnable();

    //
    // Set the clocking to run directly from the crystal.
    //
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    //
    // Enable the GPIO pins for the LED (PF2).
    //
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    
    // Configure UART
    InitConsole();

    
    // -----------------------------------------------------------------
    // Configure PWM for servo control
    // -----------------------------------------------------------------
    // follow page 1240 of the datasheet:
    ui32_Period = (MAP_SysCtlClockGet()/8) / 50; //PWM frequency 50HZ, T=20ms
    // GOTO middle of servo in the beginning
    ui32_PWM = ui32_PWM_min + (ui32_PWM_max - ui32_PWM_min) / 2;
    ui32_PWM_max = ui32_Period*.1;
    ui32_PWM_min = ui32_Period*.05;
    
    //Configure PWM Clock to match system
	MAP_SysCtlPWMClockSet(SYSCTL_PWMDIV_8);
    
    // Enable system clock for PWM0 module
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
  
    // Enable the GPIO port that is used for the PWM outputs
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    //Configure PB5,PB5 Pins as PWM
    MAP_GPIOPinConfigure(GPIO_PB4_M0PWM2);
    MAP_GPIOPinConfigure(GPIO_PB5_M0PWM3);
    MAP_GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_4);
    MAP_GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_5);
    
    //Configure PWM Options
    MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1 , PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);
    
    //
    // Set the PWM period to 50Hz.  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 / 50Hz) * 16MHz/8div = 40000 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(PWM0_BASE, PWM_GEN_1, ui32_Period);
    
    //Set PWM duty - 25% and 75%
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, ui32_PWM);
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3, ui32_PWM);
    
    // Enable the PWM generator
    MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_1);

    // Turn on the Output pins
    MAP_PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT | PWM_OUT_3_BIT, true);
    
    
    // -----------------------------------------------------------------
    // Enable PORTF and Configure SW1 and SW2 as input
    // -----------------------------------------------------------------
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIO_PORTF_LOCK_R = 0x4C4F434B;   // unlock GPIO Port F
    GPIO_PORTF_CR_R = 0x1F;           // allow changes to PF4-0
    MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, (GPIO_PIN_4 | GPIO_PIN_0), GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    MAP_GPIODirModeSet(GPIO_PORTF_BASE, (GPIO_PIN_4 | GPIO_PIN_0), GPIO_DIR_MODE_IN);

    //
    // Loop forever echoing data through the UART.
    //
    while(1)
    {
		// Get buttons:
		ui32_sw1 = MAP_GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4);
		ui32_sw2 = MAP_GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0);
		// if pressing SW1 on LaunchPad TM4C123G
		if( ui32_sw1 == 0 )
		{
			if(ui32_PWM >= ui32_PWM_min+ui32_PWM_step) {
				ui32_PWM -= ui32_PWM_step;
			}
		}
		if( ui32_sw2 == 0 )
		{
			if(ui32_PWM <= ui32_PWM_max-ui32_PWM_step) {
				ui32_PWM += ui32_PWM_step;
			}
		}
		
		UARTprintf("Period: %d, PWM: %d\n", ui32_Period, ui32_PWM);
		MAP_SysCtlDelay(2000000);
		
		MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2 , ui32_Period - ui32_PWM);
		MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3 , ui32_PWM);
    }
}
Пример #19
0
void SpeakerControl(void* pValue)
{
    int iCount=0;
    unsigned long ulPin6Val = 1;
  long lRetVal = -1;
    
    //Check whether GPIO Level is Stable As No Debouncing Circuit in LP
    for(iCount=0;iCount<3;iCount++)
    {
        osi_Sleep(200);
        ulPin6Val = MAP_GPIOPinRead(GPIOA2_BASE,GPIO_PIN_6);
        if(ulPin6Val)
        {
            //False Alarm
            return;
        }
    }
    
    if (g_ucSpkrStartFlag ==  0)
    {
#ifndef MULTICAST   
        //Un Register mDNS Service.
    lRetVal = sl_NetAppMDNSUnRegisterService((signed char *)CC3200_MDNS_NAME,\
                          (unsigned char)strlen((const char *)CC3200_MDNS_NAME));
    if(lRetVal < 0)
    {
      UART_PRINT("Unable to unregister MDNS service\n\r");
    }
    //Registering for the mDNS service.              
    lRetVal = sl_NetAppMDNSRegisterService((signed char *)CC3200_MDNS_NAME, \
                          (unsigned char)strlen((const char *)CC3200_MDNS_NAME),\
                          (signed char *)"multicast",\
                          (unsigned char)strlen((const char *)"multicast"),\
                           AUDIO_PORT,1000,0);    
    if(lRetVal < 0)
    {
      UART_PRINT("Unable to register MDNS service\n\r");
      LOOP_FOREVER();
    }
#endif 
        
        //Blink LED 3 times to Indicate ON
        for(iCount = 0; iCount<3; iCount++)
        {
            GPIO_IF_LedOff(MCU_ORANGE_LED_GPIO);
            osi_Sleep(50);
            GPIO_IF_LedOn(MCU_ORANGE_LED_GPIO);
            osi_Sleep(50);
        }                     
        g_ucSpkrStartFlag = 1;
    }
    else
    {
        //Un Register mDNS Service.
    lRetVal = sl_NetAppMDNSUnRegisterService((signed char *)CC3200_MDNS_NAME,\
                           (unsigned char)strlen((const char *)CC3200_MDNS_NAME));        
    if(lRetVal < 0)
    {
      UART_PRINT("Unable to unregister MDNS service\n\r");
    }
        //Blink LED 3 times to Indicate OFF
        for(iCount = 0; iCount<3; iCount++)
        {
            GPIO_IF_LedOn(MCU_ORANGE_LED_GPIO);
            osi_Sleep(50);
            GPIO_IF_LedOff(MCU_ORANGE_LED_GPIO);
            osi_Sleep(50);
        }
        g_ucSpkrStartFlag = 0;            
    }
    
    //Enable GPIO Interrupt
    MAP_GPIOIntClear(GPIOA2_BASE,GPIO_PIN_6);
    MAP_IntPendClear(INT_GPIOA2);
    MAP_IntEnable(INT_GPIOA2);
    MAP_GPIOIntEnable(GPIOA2_BASE,GPIO_PIN_6);
}
Пример #20
0
static bool safe_boot_request_start (uint32_t wait_time) {
    if (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) {
        UtilsDelay(UTILS_DELAY_US_TO_COUNT(wait_time * 1000));
    }
    return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
}
Пример #21
0
//*****************************************************************************
//
// Required by lwIP library to support any host-related timer functions.
//
//*****************************************************************************
void
lwIPHostTimerHandler(void)
{
    uint32_t ui32Idx, ui32NewIPAddress;

    //
    // Get the current IP address.
    //
    ui32NewIPAddress = lwIPLocalIPAddrGet();

    //
    // See if the IP address has changed.
    //
    if(ui32NewIPAddress != g_ui32IPAddress)
    {
        //
        // See if there is an IP address assigned.
        //
        if(ui32NewIPAddress == 0xffffffff)
        {
            //
            // Indicate that there is no link.
            //
            UARTprintf("Waiting for link.\n");
        }
        else if(ui32NewIPAddress == 0)
        {
            //
            // There is no IP address, so indicate that the DHCP process is
            // running.
            //
            UARTprintf("Waiting for IP address.\n");
        }
        else
        {
            //
            // Display the new IP address.
            //
            //UARTprintf("IP Address: ");
            //DisplayIPAddress(ui32NewIPAddress);
            //UARTprintf("\nOpen a browser and enter the IP address.\n");
        }

        //
        // Save the new IP address.
        //
        g_ui32IPAddress = ui32NewIPAddress;

        //
        // Turn GPIO off.
        //
        MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, ~GPIO_PIN_1);
    }

    //
    // If there is not an IP address.
    //
    if((ui32NewIPAddress == 0) || (ui32NewIPAddress == 0xffffffff))
    {
        //
        // Loop through the LED animation.
        //

        for(ui32Idx = 1; ui32Idx < 17; ui32Idx++)
        {

            //
            // Toggle the GPIO
            //
            MAP_GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1,
                    (MAP_GPIOPinRead(GPIO_PORTN_BASE, GPIO_PIN_1) ^
                     GPIO_PIN_1));

            SysCtlDelay(120000000/(ui32Idx << 1));
        }
    }
}
Пример #22
0
long ReadWlanInterruptPin(void)
{
  return MAP_GPIOPinRead(SPI_GPIO_IRQ_BASE, SPI_IRQ_PIN);
}
Пример #23
0
int gpio_get(int pin)
{
	return MAP_GPIOPinRead(TO_BASE(pin), TO_PIN(pin));
}
Пример #24
0
int main()
{
	//
	// 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.
	//
	MAP_FPUEnable();
	MAP_FPULazyStackingEnable();

	//
	// Set the clocking to run from the PLL at 50MHZ, change to SYSCTL_SYSDIV_2_5 for 80MHz if neeeded
	//
	MAP_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
	MAP_IntMasterDisable();

	//
	// Initialize the SW2 button
	//
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	//
	// Unlock PF0 so we can change it to a GPIO input
	// Once we have enabled (unlocked) the commit register then re-lock it
	// to prevent further changes.  PF0 is muxed with NMI thus a special case.
	//
	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
	HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
	HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
	MAP_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0);
	MAP_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA , GPIO_PIN_TYPE_STD_WPU);

	//
	// Initialize the communication layer with a default UART setting
	//
	AbstractComm * comm = NULL;
	AbstractComm * uart_comm = new UARTComm();
	purpinsComm communication(uart_comm);

	//
	// Initialize the robot object
	//
	purpinsRobot purpins;

	//
	// Initialize the EEPROM
	//
	purpinsSettings settings;

	//
	// Initialize the MPU6050-based IMU
	//
	mpudata_t mpu;
	//unsigned long sample_rate = 10 ;
	//mpu9150_init(0, sample_rate, 0);
	memset(&mpu, 0, sizeof(mpudata_t));

	//
	// Get the current processor clock frequency.
	//
	ulClockMS = MAP_SysCtlClockGet() / (3 * 1000);
	//unsigned long loop_delay = (1000 / sample_rate) - 2;

	//
	// Configure SysTick to occur 1000 times per second
	//
	MAP_SysTickPeriodSet(MAP_SysCtlClockGet() / SYSTICKS_PER_SECOND);
	MAP_SysTickIntEnable();
	MAP_SysTickEnable();

	MAP_IntMasterEnable();

	//
	// Load the settings from EEPROM
	//
	// Load the robot's ID
	settings.get(PP_SETTING_ID, &id, sizeof(uint32_t));
	// Load the motors' PID gains
	settings.get(PP_SETTING_LEFT_PID, purpins.leftPIDGains(), sizeof(PIDGains));
	settings.get(PP_SETTING_RIGHT_PID, purpins.rightPIDGains(), sizeof(PIDGains));
	// Load the communication type
	uint32_t comm_type;
	settings.get(PP_SETTING_COMM_TYPE, &comm_type, sizeof(uint32_t));
	// Holding SW2 at startup forces USB Comm
	if(comm_type != PP_COMM_TYPE_USB && MAP_GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0) == 1)
	{
		if(comm_type == PP_COMM_TYPE_CC3000)
		{
			comm = new WiFiComm();
			// Load network and server settings
			settings.get(PP_SETTING_NETWORK_DATA, (static_cast<WiFiComm*>(comm))->network(), sizeof(Network));
			settings.get(PP_SETTING_SERVER_DATA, (static_cast<WiFiComm*>(comm))->server(), sizeof(Server));
			// Set WiFiComm as the underlying communication layer
			communication.setCommLayer(comm);
		}
		else if(comm_type == PP_COMM_TYPE_ESP8266)
		{
			// TODO
		}
		else if(comm_type == PP_COMM_TYPE_XBEE)
		{
			// TODO
		}
	}

	//
	// Communication variables and stuff
	//
	uint8_t sensors_pack[SENSORS_PACK_SIZE];
	bool send_pack = false;
	unsigned long sensor_streaming_millis = 0;
	unsigned long last_millis = millis();

	uint8_t data[SERIAL_BUFFER_SIZE];
	size_t data_size;
	uint8_t action;

	//
	// Main loop, just managing communications
	//
	while(1)
	{
		//
		// Check for a new action
		//
		action = communication.getMsg(data, data_size);

		// If we got an action...
		if(action > 0)
		{
			// Process it!!!
			if(action == PP_ACTION_GET_VERSION)
			{
				uint8_t version = VERSION;
				communication.sendMsg(PP_ACTION_GET_VERSION, (void*)(&version), 1);
			}
			else if(action == PP_ACTION_DRIVE)
			{
				RobotSpeed speed;
				memcpy(&speed, data, sizeof(speed));
				purpins.setSpeed(&speed);
				communication.sendAck(PP_ACTION_DRIVE);
			}
			else if(action == PP_ACTION_DRIVE_MOTORS)
			{
				MotorSpeeds motor_speeds;
				memcpy(&motor_speeds, data, sizeof(motor_speeds));
				purpins.setMotorSpeeds(&motor_speeds);
				communication.sendAck(PP_ACTION_DRIVE_MOTORS);
			}
			else if(action == PP_ACTION_DRIVE_PWM)
			{
				MotorPWMs motor_pwms;
				memcpy(&motor_pwms, data, sizeof(motor_pwms));
				purpins.setPWM(&motor_pwms);
				communication.sendAck(PP_ACTION_DRIVE_PWM);
			}
			else if(action == PP_ACTION_GET_ODOMETRY)
			{
				Pose odometry;
				purpins.getOdometry(&odometry);
				communication.sendMsg(PP_ACTION_GET_ODOMETRY, (void*)(&odometry), sizeof(odometry));
			}
			else if(action == PP_ACTION_GET_MOTOR_SPEEDS)
			{
				MotorSpeeds speed;
				purpins.getMotorSpeeds(&speed);
				communication.sendMsg(PP_ACTION_GET_MOTOR_SPEEDS, (void*)(&speed), sizeof(speed));
			}
			else if(action == PP_ACTION_GET_ENCODER_PULSES)
			{
				EncoderPulses encoder_pulses;
				purpins.getEncoderTicks(&encoder_pulses);
				communication.sendMsg(PP_ACTION_GET_ENCODER_PULSES, (void*)(&encoder_pulses), sizeof(encoder_pulses));
			}
			else if(action == PP_ACTION_GET_IMU)
			{
				IMU imu_data;
				imu_data.orientation_x = mpu.fusedQuat[0];
				imu_data.orientation_y = mpu.fusedQuat[1];
				imu_data.orientation_z = mpu.fusedQuat[2];
				imu_data.orientation_w = mpu.fusedQuat[4];
				imu_data.linear_acceleration_x = mpu.calibratedAccel[0];
				imu_data.linear_acceleration_y = mpu.calibratedAccel[1];
				imu_data.linear_acceleration_z = mpu.calibratedAccel[2];
				imu_data.angular_velocity_x = mpu.calibratedMag[0];
				imu_data.angular_velocity_y = mpu.calibratedMag[1];
				imu_data.angular_velocity_z = mpu.calibratedMag[2];
				communication.sendMsg(PP_ACTION_GET_IMU, (void*)(&imu_data), sizeof(imu_data));
			}
			else if(action == PP_ACTION_GET_IR_SENSORS)
			{
				// TODO: Add the IR sensors
			}
			else if(action == PP_ACTION_GET_GAS_SENSOR)
			{
				// TODO: Add the gas sensor
			}
			else if(action == PP_ACTION_SET_SENSORS_PACK)
			{
				bool ok = true;
				memset(sensors_pack, 0, SENSORS_PACK_SIZE);
				if(data_size > SENSORS_PACK_SIZE)
				{
					communication.error(PP_ERROR_BUFFER_SIZE);
					ok = false;
					break;
				}
				for(unsigned int i=0 ; i<data_size ; i++)
				{
					if(data[i] < PP_ACTION_GET_ODOMETRY || data[i] > PP_ACTION_GET_GAS_SENSOR)
					{
						communication.error(PP_ERROR_SENSOR_UNKNOWN);
						ok = false;
						break;
					}
				}
				if(ok)
				{
					memcpy(sensors_pack, data, data_size);
					communication.sendAck(PP_ACTION_SET_SENSORS_PACK);
				}
			}
			else if(action == PP_ACTION_GET_SENSORS_PACK)
			{
				send_pack = true;
			}
			else if(action == PP_ACTION_SET_SENSOR_STREAMING)
			{
				float sensor_streaming_frequency;
				memcpy(&sensor_streaming_frequency, data, sizeof(sensor_streaming_frequency));
				sensor_streaming_millis = 1/sensor_streaming_frequency * 1000;
				communication.sendAck(PP_ACTION_SET_SENSOR_STREAMING);
			}
			else if(action == PP_ACTION_SET_GLOBAL_POSE)
			{
				Pose pose;
				memcpy(&pose, data, sizeof(pose));
				purpins.setGlobalPose(&pose);
				communication.sendAck(PP_ACTION_SET_GLOBAL_POSE);
			}
			else if(action == PP_ACTION_SET_NEIGHBORS_POSES)
			{
				// TODO: Finish this
			}
			else if(action == PP_ACTION_SET_ID)
			{
				memcpy(&id, data, sizeof(id));
				settings.save(PP_SETTING_ID, data, sizeof(uint32_t));
				communication.sendAck(PP_ACTION_SET_ID);
			}
			else if(action == PP_ACTION_GET_ID)
			{
				communication.sendMsg(PP_ACTION_GET_ID, (void*)(&id), sizeof(id));
			}
			else if(action == PP_ACTION_SET_PID_GAINS)
			{
				memcpy(purpins.leftPIDGains(), data, sizeof(PIDGains));
				memcpy(purpins.rightPIDGains(), data+sizeof(PIDGains), sizeof(PIDGains));
				settings.save(PP_SETTING_LEFT_PID, data, sizeof(PIDGains));
				settings.save(PP_SETTING_RIGHT_PID, data+sizeof(PIDGains), sizeof(PIDGains));
				communication.sendAck(PP_ACTION_SET_PID_GAINS);
			}
			else if(action == PP_ACTION_GET_PID_GAINS)
			{
				memcpy(data, purpins.leftPIDGains(), sizeof(PIDGains));
				memcpy(data+sizeof(PIDGains), purpins.rightPIDGains(), sizeof(PIDGains));
				communication.sendMsg(PP_ACTION_GET_ID, (void*)(data), 2*sizeof(PIDGains));
			}
			else if(action == PP_ACTION_SET_SERVER_DATA)
			{
				settings.save(PP_SETTING_SERVER_DATA, data, sizeof(Server));
				communication.sendAck(PP_ACTION_SET_SERVER_DATA);
			}
			else if(action == PP_ACTION_GET_SERVER_DATA)
			{
				settings.get(PP_SETTING_SERVER_DATA, data, sizeof(Server));
				communication.sendMsg(PP_ACTION_GET_SERVER_DATA, (void*)(data), sizeof(Server));
			}
			else if(action == PP_ACTION_SET_NETWORK_DATA)
			{
				settings.save(PP_SETTING_NETWORK_DATA, data, sizeof(Network));
				communication.sendAck(PP_ACTION_SET_NETWORK_DATA);
			}
			else if(action == PP_ACTION_GET_NETWORK_DATA)
			{
				settings.get(PP_SETTING_NETWORK_DATA, data, sizeof(Network));
				communication.sendMsg(PP_ACTION_GET_NETWORK_DATA, (void*)(data), sizeof(Network));
			}
			else if(action == PP_ACTION_SET_COMM_TYPE)
			{
				memcpy(&comm_type, data, sizeof(comm_type));
				if(comm_type != communication.type())
				{
					if(comm_type == PP_COMM_TYPE_USB)
					{
						communication.setCommLayer(uart_comm);
						if(comm != NULL) delete comm;
					}
					if(comm_type == PP_COMM_TYPE_CC3000)
					{
						if(comm != NULL) delete comm;
						comm = new WiFiComm();
						// Load network and server settings
						settings.get(PP_SETTING_NETWORK_DATA, (static_cast<WiFiComm*>(comm))->network(), sizeof(Network));
						settings.get(PP_SETTING_SERVER_DATA, (static_cast<WiFiComm*>(comm))->server(), sizeof(Server));
						// Set WiFiComm as the underlying communication layer
						communication.setCommLayer(comm);
					}
					else if(comm_type == PP_COMM_TYPE_ESP8266)
					{
						// TODO
					}
					else if(comm_type == PP_COMM_TYPE_XBEE)
					{
						// TODO
					}
					else
					{
						communication.error(PP_ERROR_COMM_UNKNOWN);
					}
					communication.sendAck(PP_ACTION_SET_COMM_TYPE);
				}
			}

		} // if(action > 0)

		//
		// Manage sensor streaming
		//
		unsigned long current_millis = millis();
		if(send_pack || (sensor_streaming_millis > 0 && (current_millis - last_millis) >= sensor_streaming_millis))
		{
			size_t size = 0;
			for(int i=0 ; i<SENSORS_PACK_SIZE ; i++)
			{
				if(sensors_pack[i] == 0) break;

				if(sensors_pack[i] == PP_ACTION_GET_ODOMETRY)
				{
					Pose odometry;
					purpins.getOdometry(&odometry);
					memcpy(data+size, &odometry, sizeof(odometry));
					size += sizeof(odometry);
				}
				else if(sensors_pack[i] == PP_ACTION_GET_MOTOR_SPEEDS)
				{
					MotorSpeeds speed;
					purpins.getMotorSpeeds(&speed);
					memcpy(data+size, &speed, sizeof(speed));
					size += sizeof(speed);
				}
				else if(sensors_pack[i] == PP_ACTION_GET_ENCODER_PULSES)
				{
					EncoderPulses encoder_pulses;
					purpins.getEncoderTicks(&encoder_pulses);
					memcpy(data+size, &encoder_pulses, sizeof(encoder_pulses));
					size += sizeof(encoder_pulses);
				}
				else if(sensors_pack[i] == PP_ACTION_GET_IMU)
				{
					IMU imu_data;
					imu_data.orientation_x = mpu.fusedQuat[0];
					imu_data.orientation_y = mpu.fusedQuat[1];
					imu_data.orientation_z = mpu.fusedQuat[2];
					imu_data.orientation_w = mpu.fusedQuat[4];
					imu_data.linear_acceleration_x = mpu.calibratedAccel[0];
					imu_data.linear_acceleration_y = mpu.calibratedAccel[1];
					imu_data.linear_acceleration_z = mpu.calibratedAccel[2];
					imu_data.angular_velocity_x = mpu.calibratedMag[0];
					imu_data.angular_velocity_y = mpu.calibratedMag[1];
					imu_data.angular_velocity_z = mpu.calibratedMag[2];
					memcpy(data+size, &imu_data, sizeof(imu_data));
					size += sizeof(imu_data);
				}
				else if(sensors_pack[i] == PP_ACTION_GET_IR_SENSORS)
				{
					// TODO: Add the IR sensors
				}
				else if(sensors_pack[i] == PP_ACTION_GET_GAS_SENSOR)
				{
					// TODO: Add the gas sensor
				}
			}

			communication.sendMsg(PP_ACTION_GET_SENSORS_PACK, (void*)(data), size);
			last_millis = current_millis;
			send_pack = false;

		} // if(send_pack ...

	} // while(1)

	return 0;
}
Пример #25
0
//*****************************************************************************
//
//! Polls the current state of the buttons and determines which have changed.
//!
//! \param pui8Delta points to a character that will be written to indicate
//! which button states changed since the last time this function was called.
//! This value is derived from the debounced state of the buttons.
//! \param pui8RawState points to a location where the raw button state will
//! be stored.
//!
//! This function should be called periodically by the application to poll the
//! pushbuttons.  It determines both the current debounced state of the buttons
//! and also which buttons have changed state since the last time the function
//! was called.
//!
//! In order for button debouncing to work properly, this function should be
//! caled at a regular interval, even if the state of the buttons is not needed
//! that often.
//!
//! If button debouncing is not required, the the caller can pass a pointer
//! for the \e pui8RawState parameter in order to get the raw state of the
//! buttons.  The value returned in \e pui8RawState will be a bit mask where
//! a 1 indicates the buttons is pressed.
//!
//! \return Returns the current debounced state of the buttons where a 1 in the
//! button ID's position indicates that the button is pressed and a 0
//! indicates that it is released.
//
//*****************************************************************************
uint8_t
ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8RawState)
{
    uint32_t ui32Delta;
    uint32_t ui32Data;
    static uint8_t ui8SwitchClockA = 0;
    static uint8_t ui8SwitchClockB = 0;

    //
    // Read the raw state of the push buttons.  Save the raw state
    // (inverting the bit sense) if the caller supplied storage for the
    // raw value.
    //
    ui32Data = (MAP_GPIOPinRead(BUTTONS_GPIO_BASE, ALL_BUTTONS));
    if(pui8RawState) {
        *pui8RawState = (uint8_t)~ui32Data;
    }

    //
    // Determine the switches that are at a different state than the debounced
    // state.
    //
    ui32Delta = ui32Data ^ g_ui8ButtonStates;

    //
    // Increment the clocks by one.
    //
    ui8SwitchClockA ^= ui8SwitchClockB;
    ui8SwitchClockB = ~ui8SwitchClockB;

    //
    // Reset the clocks corresponding to switches that have not changed state.
    //
    ui8SwitchClockA &= ui32Delta;
    ui8SwitchClockB &= ui32Delta;

    //
    // Get the new debounced switch state.
    //
    g_ui8ButtonStates &= ui8SwitchClockA | ui8SwitchClockB;
    g_ui8ButtonStates |= (~(ui8SwitchClockA | ui8SwitchClockB)) & ui32Data;

    //
    // Determine the switches that just changed debounced state.
    //
    ui32Delta ^= (ui8SwitchClockA | ui8SwitchClockB);

    //
    // Store the bit mask for the buttons that have changed for return to
    // caller.
    //
    if(pui8Delta) {
        *pui8Delta = (uint8_t)ui32Delta;
    }

    //
    // Return the debounced buttons states to the caller.  Invert the bit
    // sense so that a '1' indicates the button is pressed, which is a
    // sensible way to interpret the return value.
    //
    return(~g_ui8ButtonStates);
}