CC2530: CC2530 is not Working with 2 buttons

Part Number: CC2530
Other Parts Discussed in Thread: Z-STACK,

Hi Guys,

I´m working with custom board to implement two switch buttons, S1 (P0.4) and S2 (P0.1), I cloned  S1 (SW6) to S2 to implement it. I see in the HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR ) and special registers also (with IAR Registers Panel) that when I pressed S1 and S2 the respective code associated with each works (hits) to some extent in the code.

I observing, using breakpoints, that in the HalKeyPoll for both buttons the lines HAL_PUSH_BUTTON1() and HAL_PUSH_BUTTON2() are reached. Its cause the Key values 0x20 (correct value) and 0x60 (0x20 + 0x040). After it both buttons provoke the same effects in the application, the lines are simultaneous reached keys & HAL_KEY_SW_6 and keys & HAL_KEY_SW_7.

I no have idea how to fix it. Someone, please can help me?

Note: I using Z-Stack Home 1.2.2a.44539, after implement it I´ll upgrade to Z-Stack 3.0.1.

Bellow I including all those configuration that have correlation on the S1 and S2 (hal_board_cfg.h, hal_key.c, hal_key.h and OnBoard.c)

hal_board_cfg.h

/* S1 */
#define PUSH1_BV          BV(4)
#define PUSH1_SBIT        P0_4

/* S2 */
#define PUSH2_BV          BV(1)
#define PUSH2_SBIT        P0_1

#define PUSH1_POLARITY    ACTIVE_HIGH
#define PUSH2_POLARITY    ACTIVE_HIGH

hal_key.h

/* Interrupt option - Enable or disable */
#define HAL_KEY_INTERRUPT_DISABLE    0x00
#define HAL_KEY_INTERRUPT_ENABLE     0x01

/* Key state - shift or nornal */
#define HAL_KEY_STATE_NORMAL          0x00
#define HAL_KEY_STATE_SHIFT           0x01

#define HAL_KEY_SW_1 0x01  // Joystick up
#define HAL_KEY_SW_2 0x02  // Joystick right
#define HAL_KEY_SW_5 0x04  // Joystick center
#define HAL_KEY_SW_4 0x10  // Joystick left
#define HAL_KEY_SW_3 0x08  // Joystick down ant 10

#define HAL_KEY_SW_6 0x20  // Button S2 
#define HAL_KEY_SW_7 0x40  // Button S1 

hal_key.c

/**************************************************************************************************
 * @fn      HalKeyConfig
 *
 * @brief   Configure the Key serivce
 *
 * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
 *          cback - pointer to the CallBack function
 *
 * @return  None
 **************************************************************************************************/
void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
{
  /* Enable/Disable Interrupt or */
  Hal_KeyIntEnable = interruptEnable;

  /* Register the callback fucntion */
  pHalKeyProcessFunction = cback;

  /* Determine if interrupt is enable or not */
  if (Hal_KeyIntEnable)
  {
    /* Rising/Falling edge configuratinn */
    PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);    /* Clear the edge bit */
    /* For falling edge, the bit must be set. */
  #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
    PICTL |= HAL_KEY_SW_6_EDGEBIT;
  #endif
  
    /* Interrupt configuration:
     * - Enable interrupt generation at the port
     * - Enable CPU interrupt
     * - Clear any pending interrupt
     */
    HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;
    HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;
    HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT);


   /* Rising/Falling edge configuratinn */
    PICTL &= ~(HAL_KEY_SW_7_EDGEBIT);    /* Clear the edge bit */
    /* For falling edge, the bit must be set. */
  #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE)
    PICTL |= HAL_KEY_SW_7_EDGEBIT;
  #endif

	HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT;
    HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT;
    HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT);

    /* Rising/Falling edge configuratinn */

    /* Interrupt configuration:
     * - Enable interrupt generation at the port
     * - Enable CPU interrupt
     * - Clear any pending interrupt
     */

    /* Do this only after the hal_key is configured - to work with sleep stuff */
    if (HalKeyConfigured == TRUE)
    {
      osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
    }
  }
  else    /* Interrupts NOT enabled */
  {
    //HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
    HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
	osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
	
	//HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */
    HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT);   /* Clear interrupt enable bit */
	osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
	
  }

  /* Key now is configured */
  HalKeyConfigured = TRUE;
}


/**************************************************************************************************
 * @fn      HalKeyRead
 *
 * @brief   Read the current value of a key
 *
 * @param   None
 *
 * @return  keys - current keys status
 **************************************************************************************************/
uint8 HalKeyRead ( void )
{
  uint8 keys = 0;

	if (HAL_PUSH_BUTTON1())
	{
		keys |= HAL_KEY_SW_6; 
	} 
	
	if (HAL_PUSH_BUTTON2())
	{
		keys |= HAL_KEY_SW_7;
	}
  return keys;
}


/**************************************************************************************************
 * @fn      HalKeyPoll
 *
 * @brief   Called by hal_driver to poll the keys
 *
 * @param   None
 *
 * @return  None
 **************************************************************************************************/
void HalKeyPoll (void)
{
  uint8 keys = 0;
 
  /* If interrupts are not enabled, previous key status and current key status
   * are compared to find out if a key has changed status.
   */
  if (!Hal_KeyIntEnable)
  {
    if (keys == halKeySavedKeys)
    {
      /* Exit - since no keys have changed */
      return;
    }
    /* Store the current keys for comparation next time */
    halKeySavedKeys = keys;
  }
  else
  {
    /* Key interrupt handled here */
  }


	if (HAL_PUSH_BUTTON1())
  {
		keys |= HAL_KEY_SW_6; 
  } 
  

	if (HAL_PUSH_BUTTON2())
  {
		keys |= HAL_KEY_SW_7; 
  }

	
  /* Invoke Callback if new keys were depressed */
  if (keys && (pHalKeyProcessFunction))
  {
    (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
  }
}

/**************************************************************************************************
 * @fn      halProcessKeyInterrupt
 *
 * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
 *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
 *
 * @param
 *
 * @return
 **************************************************************************************************/
void halProcessKeyInterrupt (void)
{
  bool valid=FALSE;

  if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
  {
    HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
    valid = TRUE;
	
  }
  
  if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)  /* Interrupt Flag has been set */
  {
    HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */
    valid = TRUE;

  }

  if (valid)
  {
    osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
  }
}

OnBoard.c

void OnBoard_KeyCallback ( uint8 keys, uint8 state )
{
  uint8 shift;
  (void)state;

  shift = (keys & HAL_KEY_SW_6) ? true : false;
 // shift = (keys & HAL_KEY_SW_7) ? true : false;

  if ( OnBoard_SendKeys( keys, shift ) != ZSuccess )
  {
    // Process SW1 here
    if ( keys & HAL_KEY_SW_1 )  // Switch 1
    {
    }
    // Process SW2 here
    if ( keys & HAL_KEY_SW_2 )  // Switch 2
    {
    }
    // Process SW3 here
    if ( keys & HAL_KEY_SW_3 )  // Switch 3
    {
    }
    // Process SW4 here
    if ( keys & HAL_KEY_SW_4 )  // Switch 4
    {
    }
    // Process SW5 here
    if ( keys & HAL_KEY_SW_5 )  // Switch 5
    {
    }
    // Process SW6 here
    if ( keys & HAL_KEY_SW_6 )  // Switch 6
    {
    }
	 // Process SW7 here
    if ( keys & HAL_KEY_SW_7 )  // Switch 7
    {
    }
  }
}

  • Hi Alexander,

    HAL_PUSH_BUTTON1 should return HAL_KEY_SW_6 (0x20) and HAL_PUSH_BUTTON2 should return HAL_KEY_SW_7 (0x40).  HAL_KEY_SW_6 | HAL_KEY_SW_7 (0x60) should not be returned unless both HAL_PUSH_BUTTON1 and HAL_PUSH_BUTTON2 return true.  You should check your hardware lines to confirm that pushing one button does not somehow change the state of both input pins. Make sure to remove all joystick/joykey code (since it is not being used) and modify zclSample*_HandleKeys in zcl_sample*.c accordingly.

    As the UI has changed between Z-Stack HA 1.2.2a and 3.0.x, I recommend you upgrade and evaluate whether behavior changes on the newer stack.

    Regards,
    Ryan  

  • Hi Ryan, I´m happy to hear you!

    I´ll make two external physical button, inspired by SmartRF05EB to connect to my custom board to do exhaustive tests today. But I would like to explain better What exaclty I have see.

    I have use currently optocoupler to interface with CC2530, and two ways (PUSH1_SBIT/ P0_4 and PUSH2_SBIT/ P0_1)  are completely isolated.  

    I thinks there is something wrong with my code, the breakpoint hits correctly when I pressed S1 and S2, HAL_ISR_Function is reached when pressed S2 HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT and HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT when I pressed S1. 

    The stranger behavior occurs in the HalKeyPoll. For each one S1 or S2 buttons are pressed the BUTTON1 and BUTTON 2 are reached sequentially, and it causes incorrect Key values. As you can see in the PICs bellow:

    SW7 - Hit - after I pressed S1

    SW6 - Hit - after I pressed S2

    HalKeyPoll behavior when I pressed S1 or S2

    SW7

    SW6

  • HalKeyPoll uses HAL_PUSH_BUTTONX to determine if the pin states are active or not based on the determined polarity.  Given your register values and the hal_board_cfg.h configuration I would expect both to return true at any time.  This could be some issue involving optimization from the IAR compiler.  I recommend working around the issue by using an if else statement or remove the need for polling entirely and depend solely on interrupt operation.

    Regards,
    Ryan

  • Can you attach your hal_key.c and what you define “HAL_PUSH_BUTTON1” and “HAL_PUSH_BUTTON2”?

  • Hi Ryan,

    I totally Igree with you about some issue involving IAR compiler.

    I tried to use interrupt register as working around, but after the interrupt is reached ( HAL_ISR_FUNCTION) for P0_4 or P0_1, in the hal_key.c, the register HAL_KEY_SW_6_PXIFG clear this interrupt, I made some test to comment out it and include the clear procedure inside the hallKeyPool function but I didn´t have success. 

    I used also else statement as working aroud but, when i included after this always the Button1 is reached for SW6 or SW7 interrupts.

    if (HAL_PUSH_BUTTON1())
    {
    keys |= HAL_KEY_SW_6;

    } else if (HAL_PUSH_BUTTON2())
    {
    keys |= HAL_KEY_SW_7;
    }

    Note: I changed the Sx and SWx correlation, right now S1 is triggering SW6 and S2 triggering SW7. 

  • Hi Mr YK, as you requested me cloud you see attached the hal_key.c 

    Note: When I cloned the SW6 code lines to include the SW7 I have some doubts if i need to clone this line in the  OnBoard.c (OnBoard_KeyCallback function):

    shift = (keys & HAL_KEY_SW_6) ? true : false;

  • Unfortunately I do not have any further suggestions at the moment.

    Regards,
    Ryan

  • Sorry mr YK. I Forgot to include the file!

    2388.hal_key.c
    /**************************************************************************************************
      Filename:       hal_key.c
      Revised:        $Date: 2010-09-15 19:02:45 -0700 (Wed, 15 Sep 2010) $
      Revision:       $Revision: 23815 $
    
      Description:    This file contains the interface to the HAL KEY Service.
    
    
      Copyright 2006-2010 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    /*********************************************************************
     NOTE: If polling is used, the hal_driver task schedules the KeyRead()
           to occur every 100ms.  This should be long enough to naturally
           debounce the keys.  The KeyRead() function remembers the key
           state of the previous poll and will only return a non-zero
           value if the key state changes.
    
     NOTE: If interrupts are used, the KeyRead() function is scheduled
           25ms after the interrupt occurs by the ISR.  This delay is used
           for key debouncing.  The ISR disables any further Key interrupt
           until KeyRead() is executed.  KeyRead() will re-enable Key
           interrupts after executing.  Unlike polling, when interrupts
           are enabled, the previous key state is not remembered.  This
           means that KeyRead() will return the current state of the keys
           (not a change in state of the keys).
    
     NOTE: If interrupts are used, the KeyRead() fucntion is scheduled by
           the ISR.  Therefore, the joystick movements will only be detected
           during a pushbutton interrupt caused by S1 or the center joystick
           pushbutton.
    
     NOTE: When a switch like S1 is pushed, the S1 signal goes from a normally
           high state to a low state.  This transition is typically clean.  The
           duration of the low state is around 200ms.  When the signal returns
           to the high state, there is a high likelihood of signal bounce, which
           causes a unwanted interrupts.  Normally, we would set the interrupt
           edge to falling edge to generate an interrupt when S1 is pushed, but
           because of the signal bounce, it is better to set the edge to rising
           edge to generate an interrupt when S1 is released.  The debounce logic
           can then filter out the signal bounce.  The result is that we typically
           get only 1 interrupt per button push.  This mechanism is not totally
           foolproof because occasionally, signal bound occurs during the falling
           edge as well.  A similar mechanism is used to handle the joystick
           pushbutton on the DB.  For the EB, we do not have independent control
           of the interrupt edge for the S1 and center joystick pushbutton.  As
           a result, only one or the other pushbuttons work reasonably well with
           interrupts.  The default is the make the S1 switch on the EB work more
           reliably.
    
    *********************************************************************/
    
    /**************************************************************************************************
     *                                            INCLUDES
     **************************************************************************************************/
    #include "hal_mcu.h"
    #include "hal_defs.h"
    #include "hal_types.h"
    #include "hal_board.h"
    #include "hal_drivers.h"
    #include "hal_adc.h"
    #include "hal_key.h"
    #include "osal.h"
    
    #if (defined HAL_KEY) && (HAL_KEY == TRUE)
    
    /**************************************************************************************************
     *                                              MACROS
     **************************************************************************************************/
    
    /**************************************************************************************************
     *                                            CONSTANTS
     **************************************************************************************************/
    #define HAL_KEY_RISING_EDGE   0
    #define HAL_KEY_FALLING_EDGE  1
    
    #define HAL_KEY_DEBOUNCE_VALUE  100
    
    /* CPU port interrupt */
    #define HAL_KEY_CPU_PORT_0_IF P0IF
    #define HAL_KEY_CPU_PORT_2_IF P2IF
    
    /* edge interrupt */
    #define HAL_KEY_SW_6_EDGEBIT  BV(0)
    #define HAL_KEY_SW_6_EDGE     HAL_KEY_RISING_EDGE
    
    #define HAL_KEY_SW_7_EDGEBIT  BV(0)
    #define HAL_KEY_SW_7_EDGE     HAL_KEY_RISING_EDGE
    
    
    /* SW_6 - S1 settings at P0.1 */
    // - Definitions
    
    #define HAL_KEY_SW_6_ENABLE
    #define HAL_KEY_SW_6_PORT   P0
    #define HAL_KEY_SW_6_BIT    BV(1)
    #define HAL_KEY_SW_6_SEL    P0SEL
    #define HAL_KEY_SW_6_DIR    P0DIR
    
    /* SW_6 interrupts */
    
    #define HAL_KEY_SW_6_IEN      IEN1  /* CPU interrupt mask register */
    #define HAL_KEY_SW_6_IENBIT   BV(5) /* IEN1/P0IE Mask bit for all of Port_0 */
    #define HAL_KEY_SW_6_ICTL     P0IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_6_ICTLBIT  BV(1) /* P0IEN - P0.1 enable/disable bit */
    #define HAL_KEY_SW_6_PXIFG    P0IFG /* Interrupt flag at source */
    
    
    /* SW_7 - S2 settings at P0.4 */
    //- Definitions
    
    #define HAL_KEY_SW_7_ENABLE
    #define HAL_KEY_SW_7_PORT   P0
    #define HAL_KEY_SW_7_BIT    BV(4)
    #define HAL_KEY_SW_7_SEL    P0SEL
    #define HAL_KEY_SW_7_DIR    P0DIR
    
    
    /* SW_7 interrupts */
    #define HAL_KEY_SW_7_IEN      IEN1  /* CPU interrupt mask register */
    #define HAL_KEY_SW_7_IENBIT   BV(5) /* IEN1/P0IE Mask bit for all of Port_0 */
    #define HAL_KEY_SW_7_ICTL     P0IEN /* Port Interrupt Control register */
    #define HAL_KEY_SW_7_ICTLBIT  BV(4) /* P0IEN - P0.4 enable/disable bit */
    #define HAL_KEY_SW_7_PXIFG    P0IFG /* Interrupt flag at source */
    
    
    /* Joy stick move at P2.0 */
    
    
    /* edge interrupt */
    
    
    /* Joy move interrupts */
    
    
    /**************************************************************************************************
     *                                            TYPEDEFS
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     *                                        GLOBAL VARIABLES
     **************************************************************************************************/
    static uint8 halKeySavedKeys;     /* used to store previous key state in polling mode */
    static halKeyCBack_t pHalKeyProcessFunction;
    static uint8 HalKeyConfigured;
    bool Hal_KeyIntEnable;            /* interrupt enable/disable flag */
    
    /**************************************************************************************************
     *                                        FUNCTIONS - Local
     **************************************************************************************************/
    void halProcessKeyInterrupt(void);
    uint8 halGetJoyKeyInput(void);
    uint8 halGetSWKeyInput(void);
    
    
    
    /**************************************************************************************************
     *                                        FUNCTIONS - API
     **************************************************************************************************/
    
    
    /**************************************************************************************************
     * @fn      HalKeyInit
     *
     * @brief   Initilize Key Service
     *
     * @param   none
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyInit( void )
    {
      /* Initialize previous key to 0 */
      halKeySavedKeys = 0;
    
      HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
      
      HAL_KEY_SW_7_SEL &= ~(HAL_KEY_SW_7_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_7_DIR &= ~(HAL_KEY_SW_7_BIT);    /* Set pin direction to Input */
    
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    
    /**************************************************************************************************
     * @fn      HalKeyConfig
     *
     * @brief   Configure the Key serivce
     *
     * @param   interruptEnable - TRUE/FALSE, enable/disable interrupt
     *          cback - pointer to the CallBack function
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
    
      /* Register the callback fucntion */
      pHalKeyProcessFunction = cback;
    
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
        /* Rising/Falling edge configuratinn */
        PICTL &= ~(HAL_KEY_SW_6_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_6_EDGEBIT;
      #endif
      
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
        HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;
        HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT);
    
    
       /* Rising/Falling edge configuratinn */
        PICTL &= ~(HAL_KEY_SW_7_EDGEBIT);    /* Clear the edge bit */
        /* For falling edge, the bit must be set. */
      #if (HAL_KEY_SW_7_EDGE == HAL_KEY_FALLING_EDGE)
        PICTL |= HAL_KEY_SW_7_EDGEBIT;
      #endif
    
    	HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT;
        HAL_KEY_SW_7_IEN |= HAL_KEY_SW_7_IENBIT;
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT);
    
        /* Rising/Falling edge configuratinn */
    
        /* Interrupt configuration:
         * - Enable interrupt generation at the port
         * - Enable CPU interrupt
         * - Clear any pending interrupt
         */
    
        /* Do this only after the hal_key is configured - to work with sleep stuff */
        if (HalKeyConfigured == TRUE)
        {
          osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
        }
      }
      else    /* Interrupts NOT enabled */
      {
        //HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
    	osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
    	
    	//HAL_KEY_SW_7_ICTL &= ~(HAL_KEY_SW_7_ICTLBIT); /* don't generate interrupt */
        HAL_KEY_SW_7_IEN &= ~(HAL_KEY_SW_7_IENBIT);   /* Clear interrupt enable bit */
    	osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
    	
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyRead
     *
     * @brief   Read the current value of a key
     *
     * @param   None
     *
     * @return  keys - current keys status
     **************************************************************************************************/
    uint8 HalKeyRead ( void )
    {
      uint8 keys = 0;
    
    	if (HAL_PUSH_BUTTON1())
    	{
    		keys |= HAL_KEY_SW_6; 
    	} 
    	
    	if (HAL_PUSH_BUTTON2())
    	{
    		keys |= HAL_KEY_SW_7;
    	}
      return keys;
    }
    
    
    /**************************************************************************************************
     * @fn      HalKeyPoll
     *
     * @brief   Called by hal_driver to poll the keys
     *
     * @param   None
     *
     * @return  None
     **************************************************************************************************/
    void HalKeyPoll (void)
    {
      uint8 keys = 0;
     
      /* If interrupts are not enabled, previous key status and current key status
       * are compared to find out if a key has changed status.
       */
      if (!Hal_KeyIntEnable)
      {
        if (keys == halKeySavedKeys)
        {
          /* Exit - since no keys have changed */
          return;
        }
        /* Store the current keys for comparation next time */
        halKeySavedKeys = keys;
      }
      else
      {
        /* Key interrupt handled here */
      }
    
    
    	if (HAL_PUSH_BUTTON1())
      {
    		keys |= HAL_KEY_SW_6; 
                    
      } 
      
      if (HAL_PUSH_BUTTON2())
      {
    		keys |= HAL_KEY_SW_7; 
      }
      
    
    
    	
      /* Invoke Callback if new keys were depressed */
      if (keys && (pHalKeyProcessFunction))
      {
        (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
      }
    }
    
    /**************************************************************************************************
     * @fn      halProcessKeyInterrupt
     *
     * @brief   Checks to see if it's a valid key interrupt, saves interrupt driven key states for
     *          processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later.
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
    	
      }
      
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)  /* Interrupt Flag has been set */
      {
        HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /* Clear Interrupt Flag */
        valid = TRUE;
    
      }
    
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
      }
    }
    
    
    
    /**************************************************************************************************
     * @fn      halGetSWKeyInput
     *
     * @brief   Map the multiple keys interrupts.
     *
     * @param   None
     *
     * @return  keys - current joy key status
     **************************************************************************************************/
    uint8 halGetSWKeyInput(void)
    {
      /* The joystick control is encoded as an analog voltage.
       * Read the Multiple Key Interrrupt value and map it to correct key.
       */
     uint8 ksave0 = 0;
     uint8 ksave1;
    
      /* Keep on reading the two consecutive key decisions are the same. */
      do
      {
    	ksave1 = ksave0;    /* save previouse key reading */
    
        if (HAL_PUSH_BUTTON1())
        {
           ksave0 |= HAL_KEY_SW_6;
        }
        else if(HAL_PUSH_BUTTON2())
        {
          ksave0 |= HAL_KEY_SW_7;
        }
    
      } while (ksave0 != ksave1);
    
      return ksave0;
    }
    
    /**************************************************************************************************
     * @fn      HalKeyEnterSleep
     *
     * @brief  - Get called to enter sleep mode
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    void HalKeyEnterSleep ( void )
    {
    }
    
    /**************************************************************************************************
     * @fn      HalKeyExitSleep
     *
     * @brief   - Get called when sleep is over
     *
     * @param
     *
     * @return  - return saved keys
     **************************************************************************************************/
    uint8 HalKeyExitSleep ( void )
    {
      /* Wake up and read keys */
      return ( HalKeyRead () );
    }
    
    /***************************************************************************************************
     *                                    INTERRUPT SERVICE ROUTINE
     ***************************************************************************************************/
    
    /**************************************************************************************************
     * @fn      halKeyPort0Isr
     *
     * @brief   Port0 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
    {
      HAL_ENTER_ISR();
    
      if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT )
      {
        halProcessKeyInterrupt();
    	
      /*
    	Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
      HAL_KEY_SW_6_PXIFG = 0;
      HAL_KEY_CPU_PORT_0_IF = 0;
      
      }
      
    
      if (HAL_KEY_SW_7_PXIFG & HAL_KEY_SW_7_BIT)
      {
        halProcessKeyInterrupt();
      /*
        Clear the CPU interrupt flag for Port_0
        PxIFG has to be cleared before PxIF
      */
     
      HAL_KEY_SW_7_PXIFG = 0;
      HAL_KEY_CPU_PORT_0_IF = 0;
      }
        
      CLEAR_SLEEP_MODE();
      HAL_EXIT_ISR();
    }
    
    
    /**************************************************************************************************
     * @fn      halKeyPort2Isr
     *
     * @brief   Port2 ISR
     *
     * @param
     *
     * @return
     **************************************************************************************************/
    HAL_ISR_FUNCTION( halKeyPort2Isr, P2INT_VECTOR )
    {
    
    }
    
    #else
    
    
    void HalKeyInit(void){}
    void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){}
    uint8 HalKeyRead(void){ return 0;}
    void HalKeyPoll(void){}
    
    #endif /* HAL_KEY */
    
    
    
    
    
    /**************************************************************************************************
    **************************************************************************************************/
    
    
    
    

  • Ryan, thanks a lot. Today I´ll finish the auxiliary hardware to test buttons according SMARTRF05 as I had promised you!

    About IAR working around, do you see another way to check it without HAL_KEY_SW_6_PXIFG flags?

  • Your hal_key.c looks good. What are defines of your PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT? I suggest you using scope to monitor S1 and S2 signal when you set breakpoint and debug into "if (HAL_PUSH_BUTTON1())..." and "if (HAL_PUSH_BUTTON2())..." in hallKeyPool.

  • Mr Yk,

    Regarding the Push Button Configuration (PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT) defined in the hal_board_cfg.h, you can see in the code below:

    Soon, I´ll iforme you more details about the Signal observed in SCOPE when S1 and S2 are pressed.

    Br,
    Alex
    /* ------------------------------------------------------------------------------------------------
     *                                    Push Button Configuration
     * ------------------------------------------------------------------------------------------------
     */
    
    #define ACTIVE_LOW        !
    #define ACTIVE_HIGH       !!    /* double negation forces result to be '1' */
    
    
    /* S1 */
    #define PUSH1_BV          BV(1)
    #define PUSH1_SBIT        P0_1
    #define PUSH1_POLARITY    ACTIVE_HIGH
    
    /* S2 */
    #define PUSH2_BV          BV(4)
    #define PUSH2_SBIT        P0_4
    #define PUSH2_POLARITY    ACTIVE_HIGH
  • Your (PUSH1_BV/PUSH1_SBIT and PUSH2_BV/PUSH2_SBIT) definitions look good. Next, you should use scope to check signal and debug it.

  • Mr YK.

    I did the test using my custom board and SmartRF05 BB and I saw see the same effects or behavior in the HalKeyPoll, as I told before PUSH_BUTTON1 and PUSH_BUTTON2) were triggered senquencially. I prefed to take off my custom board and using SCOPE over SmartRF05 BB.

    I cant see any electrical behavior that explain the main problem! 

    As you can see bellow:

    SmartRF05 BB - Scope definitions and measurements.

    S1 and S2 Scope Measurement without SOC GPIO PINs Connections (P0_1 and P0_4)

    S1 and S2 Scope Measurement with SOC GPIO PINs Connected (P0_1 and P0_4)

    S1 Pressed - Observed during KeyPoll breakpoint was reached

    S2 Pressed - Observed during KeyPoll breakpoint was reached

  • Try to set breakpoints on "if (HAL_PUSH_BUTTON1())" and "if (HAL_PUSH_BUTTON2())" in your key_poll function. Then, press S1 or S2 to check values of P0_1 and P0_4 in your watch window and check P0.1 and P0.4 pins on scope at the same time to see the voltage level on those two pins and their reading.

  • Hi Mr. Yk.

    As you told me I seted breakpoints on if (HAL_PUSH_BUTTON1())" and "if (HAL_PUSH_BUTTON2()) and saw that at this moment P0_1 and P0_4 kept presenting value = 1 (Active state). Even I pressing both buttons. 

    Please, can you give me an idea what is causing the P0_1/P0_4 always present value one?

     

    Breakpoint at HAL_PUSH_BUTTON1()/HAL_PUSH_BUTTON2() and P0_1/P0_4 status - S1 or S2 are pressed:

    S1 Pressed - Electrical Signal during breakpoint at HAL_PUSH_BUTTON1()/HAL_PUSH_BUTTON2()

  • Can you check what values of P0SEL and P0DIR are when you debug this?

  • Mr Yk, 

    I got P0SEL and P0DIR status during the breakpoints as you requested me. In additional I have include the port activation according my application file. 

    Port activation settings - App file 

        App profile 1 - EndPoint 1
    	
        P0SEL &= (~BV(0)); // LED GREEN CIRC. 1
        P1SEL &= (~BV(4)); // RELAY CIRC. 1 
        P0DIR |= (BV(0)); 
        P1DIR |= (BV(4)); 
    
    
    	App profile 2 - EndPoint 2
    	
    	P0SEL &= (~BV(5)); // LED GREEN CIRC 2
        P1SEL &= (~BV(5)|BV(6)); // RELAY CIRC 2 and RESET SWITCH
    	P0DIR |= (BV(5)); 
    	P1DIR |= (BV(5)|BV(6)); 

  • So, what values of P0SEL and P0DIR are when you debug this?

  • Sorry Mr YK, I cant past the PIC before, I dint know why the insert file doesn't work for me.

    P0SEL&P0DIR Before breakpoints 

    P0SEL&P0DIR after breakpoints reached.

    BR,

    Alex

  • You should check why bit4 of P0SEL is set to 1.

  • Mr YK, I try to find in my code why SELP0_4 is set to 1 but I dind´t  find anything to explain it. Do you have any idea?

    Would you can see bellow PICs of my attempt to find.

    BR,

    Alex

  • You can try to debug step. Y step before and after key initialization to see where P0SEL is changed.

  • Mr YK,

    As you advise-me I have debug set by step into key initialization and I found the code line that starts P0SEL_4 on the MT UART Inicialization procedure at specific line PxOUT &= ~HAL_UART_Px_RTS (Flow Control).

    I follow those steps to found it:

    Hal_key.c
    .
    .
    .
    OSAL.c
    osal_init_system

    OSAL_AZh0004.c
    MT_TaskInit( taskID++ );

    MT_TASK.c
    MT_UartInit();
    void MT_UartInit ()
    if (config->flowControl)
    PxOUT &= ~HAL_UART_Px_RTS

    Mr Yk, please, Would you can advise me how do I change this behavior without damaging UART communication?

  • Disable flow control to now using P0.4.

  • Hi Mr Yk,

    Thanks a lot for your assistance!

    I comment out the flow control procedure and P0SEL_4 stoped changing from zero to one, as you can see below, but I still have the double selection of Button 1 and Button 2 on HallKeyPoll. I can´t found nothing to explain it. 

    note:

    Sorry for my wrong information before about the location, it is called from hal_uart.c and located at _hal_uart_dma.c.

    _hal_uart_dma.c
    HalUARTOpenDMA
    if (config->flowControl)

  • Since both value of P0_1 and P0_4 are 1, it is normal to see both if statements are hit. Since you set both S1 and S2 to active high, you should check your HW to know why you only press S1 but both S1 and S2 go to high  level.

  • Mr YK,

    I changed from my device to SmartRF05 BB at the beginning, to not include other variables!

    After you last post I changed the PUSH1_POLARITY and PUSH2_POLARITY  from  ACTIVE_HIGH to ACTIVE_LOW and after it the both statements (button 1 and Button 2) are HIT, Sorry my mistake is here after you advise how to fix P0SEL_4, running only when I make double click in the button!

    Do you have and Idea why the statements are hit only when I do double click on the buttons?

     

  • Maybe due to button debounce. If you try to press button longer, can it hit with only one press?

  • Mr Yk! I´m very happy!

    Wonderful, at this moment everything working!

    About double click, I fixed it change the HAL_KEY_SW_X_EDGE form HAL_KEY_RISING_EDGE to HAL_KEY_FALLING_EDGE!

    just to summarize to ALL the changes, considering my configurations conditions, for future queries:

    - Comment out flow control on _hal_uart_dma.c, to fix P0SEL_4 that was always active (high level)

    - Make sure you are using key state configuration at PUSHX_POLARITY correctly, in my case ACTIVE_LOW

    - Make sure you are using key transaction signal correctly at HAL_KEY_SW_X_EDGE correctly, in my case HAL_KEY_FALLING_EDGE

    Thank you very much!!!!

    You are the best!!!

    BR,

    Alex

  • It's good to know it works now. Please help to mark this thread as answered. Thanks.