Capsense buttons and Slider, output to Serial over i2c and tft display

main.cpp

Committer:
reedas
Date:
2019-12-02
Revision:
1:cf461b359823
Parent:
0:4ad2c16b6e43

File content as of revision 1:cf461b359823:

#include "mbed.h"
#include "GUI.h"
#include "cy8ckit_028_tft.h"
#define Cy_SysLib_Delay wait_ms
#include "cy_pdl.h"
#include "cycfg_capsense.h"
#include "cycfg.h"

DigitalOut ledGreen(LED_GREEN);
DigitalOut ledRed(LED_RED);
DigitalOut ledBlue(LED_BLUE);


/* Macros for switch press status */
#define BTN_PRESSED        (0u)
#define BTN_RELEASED       (1u)

/***************************************************************************
* Global constants
***************************************************************************/
#define SLIDER_NUM_TOUCH                        (1u)    /* Number of touches on the slider */
#define LED_OFF                                 (1u) 
#define LED_ON                                  (0u)
#define CAPSENSE_SCAN_PERIOD_MS                 (20u)   /* milliseconds */


/***************************************
* Function Prototypes
**************************************/
void RunCapSenseScan(void);
void InitTunerCommunication(void);
void ProcessTouchStatus(void);
void EZI2C_InterruptHandler(void);
void CapSense_InterruptHandler(void);
void CapSenseEndOfScanCallback(cy_stc_active_scan_sns_t * ptrActiveScan);
void InitCapSenseClock(void);


/*******************************************************************************
* Interrupt configuration
*******************************************************************************/
const cy_stc_sysint_t CapSense_ISR_cfg =
{
    .intrSrc = CYBSP_CSD_IRQ,
    .intrPriority = 4u
};

const cy_stc_sysint_t EZI2C_ISR_cfg = {
    .intrSrc = CYBSP_CSD_COMM_IRQ,
    .intrPriority = 3u
};


/*******************************************************************************
* Global variables
*******************************************************************************/
Semaphore capsense_sem;
EventQueue queue;
cy_stc_scb_ezi2c_context_t EZI2C_context;
uint32_t prevBtn0Status = 0u; 
uint32_t prevBtn1Status = 0u;
uint32_t prevSliderPos = 0u;

/*****************************************************************************
* Function Name: RunCapSenseScan()
******************************************************************************
* Summary:
*   This function starts the scan, and processes the touch status. It is
* periodically called by an event dispatcher. 
*
*****************************************************************************/
void RunCapSenseScan(void)
{
    Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
    capsense_sem.acquire();          
    Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);
    Cy_CapSense_RunTuner(&cy_capsense_context);
    ProcessTouchStatus();     
}


/*******************************************************************************
* Function Name: InitTunerCommunication
********************************************************************************
*
* Summary:
*   This function performs the following functions:
*       - Initializes SCB block for operation in EZI2C mode
*       - Configures EZI2C pins
*       - Configures EZI2C clock
*       - Sets communication data buffer to CapSense data structure
*
*******************************************************************************/
void InitTunerCommunication(void)
{
    /* Initialize EZI2C pins */
    Cy_GPIO_Pin_Init(CYBSP_EZI2C_SCL_PORT, CYBSP_EZI2C_SCL_PIN, &CYBSP_EZI2C_SCL_config);
    Cy_GPIO_Pin_Init(CYBSP_EZI2C_SDA_PORT, CYBSP_EZI2C_SDA_PIN, &CYBSP_EZI2C_SDA_config);
    
    /* Configure the peripheral clock for EZI2C */
    Cy_SysClk_PeriphAssignDivider(PCLK_SCB3_CLOCK, CY_SYSCLK_DIV_8_BIT, 1U);
    Cy_SysClk_PeriphDisableDivider(CY_SYSCLK_DIV_8_BIT, 1U);
    Cy_SysClk_PeriphSetDivider(CY_SYSCLK_DIV_8_BIT, 1U, 7U);
    Cy_SysClk_PeriphEnableDivider(CY_SYSCLK_DIV_8_BIT, 1U);
    
    Cy_SCB_EZI2C_Init(CYBSP_CSD_COMM_HW, &CYBSP_CSD_COMM_config, &EZI2C_context);

    /* Initialize and enable EZI2C interrupts */
    Cy_SysInt_Init(&EZI2C_ISR_cfg, &EZI2C_InterruptHandler);
    NVIC_EnableIRQ(EZI2C_ISR_cfg.intrSrc);

    /* Set up communication data buffer to CapSense data structure to be exposed
     * to I2C master at primary slave address request.
     */
    Cy_SCB_EZI2C_SetBuffer1(CYBSP_CSD_COMM_HW, (uint8 *)&cy_capsense_tuner,
        sizeof(cy_capsense_tuner), sizeof(cy_capsense_tuner), &EZI2C_context);

    /* Enable EZI2C block */
    Cy_SCB_EZI2C_Enable(CYBSP_CSD_COMM_HW);
}


/*******************************************************************************
* Function Name: ProcessTouchStatus
********************************************************************************
*
* Summary:
*   Controls the LED status according to the status of CapSense widgets and
*   prints the status to serial terminal.
*
*******************************************************************************/
void ProcessTouchStatus(void)
{
    uint32_t currSliderPos;    
    uint32_t currBtn0Status = Cy_CapSense_IsSensorActive(CY_CAPSENSE_BUTTON0_WDGT_ID, CY_CAPSENSE_BUTTON0_SNS0_ID, &cy_capsense_context);        
    uint32_t currBtn1Status = Cy_CapSense_IsSensorActive(CY_CAPSENSE_BUTTON1_WDGT_ID, CY_CAPSENSE_BUTTON1_SNS0_ID, &cy_capsense_context);       
    cy_stc_capsense_touch_t *sldrTouch = Cy_CapSense_GetTouchInfo(CY_CAPSENSE_LINEARSLIDER0_WDGT_ID, &cy_capsense_context);
    char outputString[80];
    if(currBtn0Status != prevBtn0Status)
    {
        printf("Button_0 status: %u\r\n", currBtn0Status);
        sprintf(outputString,"  Button_0 status: %u   ", currBtn0Status);
        GUI_SetTextAlign(GUI_TA_HCENTER);
        GUI_DispStringAt(outputString, 160, 60);
        prevBtn0Status = currBtn0Status;
    }
    
    if(currBtn1Status != prevBtn1Status)
    {
        printf("Button_1 status: %u\r\n", currBtn1Status);
        sprintf(outputString,"  Button_1 status: %u   ", currBtn1Status);
        GUI_SetTextAlign(GUI_TA_HCENTER);
        GUI_DispStringAt(outputString, 160, 80);
        prevBtn1Status = currBtn1Status;
    } 

    if (sldrTouch->numPosition == SLIDER_NUM_TOUCH)
    {       
        currSliderPos = sldrTouch->ptrPosition->x;

        if(currSliderPos != prevSliderPos)
        {
            printf("Slider position: %u\r\n", currSliderPos);
            sprintf(outputString,"  Slider position: %u   ", currSliderPos);
            GUI_SetTextAlign(GUI_TA_HCENTER);
            GUI_DispStringAt(outputString, 160, 100);
            prevSliderPos = currSliderPos;
        }
    }

    ledRed = (currBtn0Status || currBtn1Status || (sldrTouch->numPosition == SLIDER_NUM_TOUCH)) ? LED_ON : LED_OFF;
}


/*******************************************************************************
* Function Name: EZI2C_InterruptHandler
********************************************************************************
* Summary:
*   Wrapper function for handling interrupts from EZI2C block. 
*
*******************************************************************************/
void EZI2C_InterruptHandler(void)
{
    Cy_SCB_EZI2C_Interrupt(CYBSP_CSD_COMM_HW, &EZI2C_context);
}

/*****************************************************************************
* Function Name: CapSense_InterruptHandler()
******************************************************************************
* Summary:
*  Wrapper function for handling interrupts from CSD block.
*
*****************************************************************************/
void CapSense_InterruptHandler(void)
{
    Cy_CapSense_InterruptHandler(CYBSP_CSD_HW, &cy_capsense_context);
}


/*****************************************************************************
* Function Name: CapSenseEndOfScanCallback()
******************************************************************************
* Summary:
*  This function releases a semaphore to indicate end of a CapSense scan.
*
* Parameters:
*  cy_stc_active_scan_sns_t* : pointer to active sensor details.
*
*****************************************************************************/
void CapSenseEndOfScanCallback(cy_stc_active_scan_sns_t * ptrActiveScan)
{
    capsense_sem.release();
}


/*****************************************************************************
* Function Name: InitCapSenseClock()
******************************************************************************
* Summary:
*  This function configures the peripheral clock for CapSense.  
*
*****************************************************************************/
void InitCapSenseClock(void)
{
    Cy_SysClk_PeriphAssignDivider(PCLK_CSD_CLOCK, CYBSP_CSD_CLK_DIV_HW, CYBSP_CSD_CLK_DIV_NUM);
    Cy_SysClk_PeriphDisableDivider(CYBSP_CSD_CLK_DIV_HW, CYBSP_CSD_CLK_DIV_NUM);
    Cy_SysClk_PeriphSetDivider(CYBSP_CSD_CLK_DIV_HW, CYBSP_CSD_CLK_DIV_NUM, 0u);
    Cy_SysClk_PeriphEnableDivider(CYBSP_CSD_CLK_DIV_HW, CYBSP_CSD_CLK_DIV_NUM);
}

/*****************************************************************************
* Function Name: main()
******************************************************************************
* Summary:
*   Main function that starts a thread for CapSense scan and enters a forever
*   wait state. 
*
*****************************************************************************/
int main(void)
{
    /* Turn off both red and green LEDs */
    ledGreen = LED_OFF;
    ledRed = LED_OFF;
    ledBlue = LED_OFF; 
    char outputString[80];
    
    /* Initialize EmWin driver*/
    GUI_Init();
    /* Set font size, foreground and background Colours */
    GUI_SetFont(GUI_FONT_16B_1);
    GUI_SetColor(GUI_WHITE);
    GUI_SetBkColor(GUI_BLACK);

    GUI_Clear();
    GUI_SetTextAlign(GUI_TA_HCENTER);
    GUI_DispStringAt("Capsense Demo", 160, 20);

 /* Configure AMUX bus for CapSense */
    init_cycfg_routing();
    
    /* Configure PERI clocks for CapSense */
    InitCapSenseClock(); 
    
    InitTunerCommunication();
    
    /* Initialize the CSD HW block to the default state. */
    cy_status status = Cy_CapSense_Init(&cy_capsense_context);
    if(CY_RET_SUCCESS != status)
    {
        printf("CapSense initialization failed. Status code: %u\r\n", status);
        sprintf(outputString,"CapSense initialization failed. Status code: %u", status);
        GUI_SetTextAlign(GUI_TA_HCENTER);
        GUI_DispStringAt(outputString, 160, 40);
        wait(osWaitForever);
    }
    
    /* Initialize CapSense interrupt */
    Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler);
    NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc);
    NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc);

    /* Initialize the CapSense firmware modules. */
    Cy_CapSense_Enable(&cy_capsense_context);
    Cy_CapSense_RegisterCallback(CY_CAPSENSE_END_OF_SCAN_E, CapSenseEndOfScanCallback, &cy_capsense_context);
    
    /* Create a thread to run CapSense scan periodically using an event queue
     * dispatcher.
     */
    Thread thread(osPriorityNormal, OS_STACK_SIZE, NULL, "CapSense Scan Thread");
    thread.start(callback(&queue, &EventQueue::dispatch_forever));
    queue.call_every(CAPSENSE_SCAN_PERIOD_MS, RunCapSenseScan);

    /* Initiate scan immediately since the first call of RunCapSenseScan()
     * happens CAPSENSE_SCAN_PERIOD_MS after the event queue dispatcher has
     * started. 
     */
    Cy_CapSense_ScanAllWidgets(&cy_capsense_context); 
    
    printf("\r\nApplication has started. Touch any CapSense button or slider.\r\n");
    sprintf(outputString,"\r\nApplication has started.\r\n Touch any CapSense button or slider.");
    GUI_SetTextAlign(GUI_TA_HCENTER);
    GUI_DispStringAt(outputString, 160, 180);
    wait(osWaitForever);
    
}