NXP Touch Cursor example for LPCXpresso54608, modified for use with Mbed OS.

The tutorial for this example can be found here: https://os.mbed.com/blog/entry/How-to-LPCXpresso54608-touch-panel/

Revision:
0:c107a6f8c368
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 11 20:46:55 2018 +0000
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2017 NXP
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of the copyright holder nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*  Standard C Included Files */
+#include "mbed.h"
+#include <stdio.h>
+#include <string.h>
+#include "stdio_thread.h"
+#include "fsl_lcdc.h"
+#include "fsl_ft5406.h"
+#include "fsl_sctimer.h"
+#include "fsl_gpio.h"
+#include "fsl_i2c.h"
+#include "board.h"
+#include "pin_mux.h"
+#include "image.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#define APP_LCD LCD
+#define LCD_PANEL_CLK 9000000
+#define LCD_PPL 480
+#define LCD_HSW 2
+#define LCD_HFP 8
+#define LCD_HBP 43
+#define LCD_LPP 272
+#define LCD_VSW 10
+#define LCD_VFP 4
+#define LCD_VBP 12
+#define LCD_POL_FLAGS kLCDC_InvertVsyncPolarity | kLCDC_InvertHsyncPolarity
+#define IMG_HEIGHT 272
+#define IMG_WIDTH 480
+#define LCD_INPUT_CLK_FREQ CLOCK_GetFreq(kCLOCK_LCD)
+#define APP_LCD_IRQHandler LCD_IRQHandler
+#define APP_LCD_IRQn LCD_IRQn
+#define EXAMPLE_I2C_MASTER_BASE (I2C2_BASE)
+#define I2C_MASTER_CLOCK_FREQUENCY (12000000)
+#define APP_PIXEL_PER_BYTE 8
+
+#define EXAMPLE_I2C_MASTER ((I2C_Type *)EXAMPLE_I2C_MASTER_BASE)
+#define I2C_MASTER_SLAVE_ADDR_7BIT 0x7EU
+#define I2C_BAUDRATE 100000U
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+#if (defined(__CC_ARM) || defined(__GNUC__))
+__attribute__((aligned(8)))
+#elif defined(__ICCARM__)
+#pragma data_alignment = 8
+#else
+#error Toolchain not support.
+#endif
+
+void *vram_ptr = s_frameBufs;
+
+/* Frame end flag. */
+static volatile bool s_frameEndFlag;
+
+/* Color palette. */
+static const uint32_t palette[] = { 0x001F00000 }; //{0x0000001F}; //{0x001F0000U, 0x7C0003E0U};
+
+/* 32x32 pixel cursor image. */
+#if (defined(__CC_ARM) || defined(__GNUC__))
+__attribute__((aligned(4)))
+#elif defined(__ICCARM__)
+#pragma data_alignment = 4
+#else
+#error Toolchain not support.
+#endif
+static const uint8_t cursor32Img0[] = {
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 1.  */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 2.  */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 3.  */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 4.  */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 5.  */
+    0xAA, 0xAA, 0xAA, 0xFA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 6.  */
+    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 7.  */
+    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 8.  */
+    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 9.  */
+    0xAA, 0xAA, 0xAB, 0xFE, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 10  */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xEA,
+    0xAA, 0xAA, 0xAA, /* Line 11. */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
+    0xAA, 0xAA, 0xAA, /* Line 12. */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
+    0xFA, 0xAA, 0xAA, /* Line 13. */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
+    0xFE, 0xAA, 0xAA, /* Line 14. */
+    0xAA, 0xAB, 0xFB, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 15. */
+    0xAA, 0xAB, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 16. */
+    0xAA, 0xAB, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 17. */
+    0xAA, 0xAA, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 18. */
+    0xAA, 0xAA, 0xBF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 19. */
+    0xAA, 0xAA, 0xBF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 20. */
+    0xAA, 0xAA, 0xAF, 0xFF, 0xFF,
+    0xFF, 0xAA, 0xAA, /* Line 21. */
+    0xAA, 0xAA, 0xAF, 0xFF, 0xFF,
+    0xFE, 0xAA, 0xAA, /* Line 22. */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
+    0xFE, 0xAA, 0xAA, /* Line 23. */
+    0xAA, 0xAA, 0xAB, 0xFF, 0xFF,
+    0xFE, 0xAA, 0xAA, /* Line 24. */
+    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
+    0xFA, 0xAA, 0xAA, /* Line 25. */
+    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
+    0xFA, 0xAA, 0xAA, /* Line 26. */
+    0xAA, 0xAA, 0xAA, 0xFF, 0xFF,
+    0xFA, 0xAA, 0xAA, /* Line 27. */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 28. */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 29. */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 30. */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA, /* Line 31. */
+    0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+    0xAA, 0xAA, 0xAA /* Line 32. */
+};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+static void BOARD_InitPWM(void)
+{
+    sctimer_config_t config;
+    sctimer_pwm_signal_param_t pwmParam;
+    uint32_t event;
+
+    CLOCK_AttachClk(kMCLK_to_SCT_CLK);
+
+    CLOCK_SetClkDiv(kCLOCK_DivSctClk, 2, true);
+
+    SCTIMER_GetDefaultConfig(&config);
+
+    SCTIMER_Init(SCT0, &config);
+
+    pwmParam.output = kSCTIMER_Out_5;
+    pwmParam.level = kSCTIMER_HighTrue;
+    pwmParam.dutyCyclePercent = 5;
+
+    SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, CLOCK_GetFreq(kCLOCK_Sct), &event);
+}
+
+void APP_LCD_IRQHandler(void)
+{
+    uint32_t intStatus = LCDC_GetEnabledInterruptsPendingStatus(APP_LCD);
+
+    LCDC_ClearInterruptsStatus(APP_LCD, intStatus);
+
+    if (intStatus & kLCDC_VerticalCompareInterrupt)
+    {
+        s_frameEndFlag = true;
+    }
+    __DSB();
+}
+
+status_t APP_LCDC_Init(void)
+{
+    /* Initialize the display. */
+    lcdc_config_t lcdConfig;
+    lcdc_cursor_config_t cursorConfig;
+
+    LCDC_GetDefaultConfig(&lcdConfig);
+
+    lcdConfig.panelClock_Hz = LCD_PANEL_CLK;
+    lcdConfig.ppl = LCD_PPL;
+    lcdConfig.hsw = LCD_HSW;
+    lcdConfig.hfp = LCD_HFP;
+    lcdConfig.hbp = LCD_HBP;
+    lcdConfig.lpp = LCD_LPP;
+    lcdConfig.vsw = LCD_VSW;
+    lcdConfig.vfp = LCD_VFP;
+    lcdConfig.vbp = LCD_VBP;
+    lcdConfig.polarityFlags = LCD_POL_FLAGS;
+    lcdConfig.upperPanelAddr = (uint32_t)s_frameBufs;
+    lcdConfig.bpp = kLCDC_1BPP;
+    lcdConfig.display = kLCDC_DisplayTFT;
+    lcdConfig.swapRedBlue = true;  //false;
+    lcdConfig.dataFormat = kLCDC_WinCeMode;
+
+    LCDC_Init(APP_LCD, &lcdConfig, LCD_INPUT_CLK_FREQ);
+
+    LCDC_SetPalette(APP_LCD, palette, ARRAY_SIZE(palette));
+
+    /* Setup the Cursor. */
+    LCDC_CursorGetDefaultConfig(&cursorConfig);
+
+    cursorConfig.size = kLCDC_CursorSize32;
+    cursorConfig.syncMode = kLCDC_CursorSync;
+    cursorConfig.image[0] = (uint32_t *)cursor32Img0;
+
+    LCDC_SetCursorConfig(APP_LCD, &cursorConfig);
+    LCDC_ChooseCursor(APP_LCD, 0);
+
+    /* Trigger interrupt at start of every vertical back porch. */
+    LCDC_SetVerticalInterruptMode(APP_LCD, kLCDC_StartOfBackPorch);
+    LCDC_EnableInterrupts(APP_LCD, kLCDC_VerticalCompareInterrupt);
+    // NVIC_EnableIRQ(APP_LCD_IRQn);
+
+    LCDC_EnableCursor(APP_LCD, true);
+
+    LCDC_Start(APP_LCD);
+    LCDC_PowerUp(APP_LCD);
+
+    return kStatus_Success;
+}
+
+status_t APP_I2C_Init(void)
+{
+    i2c_master_config_t masterConfig;
+
+    I2C_MasterGetDefaultConfig(&masterConfig);
+
+    /* Change the default baudrate configuration */
+    masterConfig.baudRate_Bps = I2C_BAUDRATE;
+
+    /* Initialize the I2C master peripheral */
+    I2C_MasterInit(EXAMPLE_I2C_MASTER, &masterConfig, I2C_MASTER_CLOCK_FREQUENCY);
+
+    return kStatus_Success;
+}
+
+void APP_SetCursorPosition(int posX, int posY)
+{
+    posX -= 12;
+    posY -= 5;
+
+    LCDC_SetCursorPosition(APP_LCD, posX, posY);
+}
+
+int main(void)
+{
+    int cursorPosX = 0U;
+    int cursorPosY = 0U;
+
+    ft5406_handle_t touch_handle;
+    touch_event_t touch_event;
+
+    status_t status;
+
+    gpio_pin_config_t pin_config = {
+        kGPIO_DigitalOutput, 0,
+    };
+
+    /* Board pin, clock, debug console init */
+    /* attach 12 MHz clock to FLEXCOMM0 (debug console) */
+    CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
+
+    /* Route Main clock to LCD. */
+    CLOCK_AttachClk(kMCLK_to_LCD_CLK);
+
+    /* attach 12 MHz clock to FLEXCOMM2 (I2C master for touch controller) */
+    CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
+
+    CLOCK_EnableClock(kCLOCK_Gpio2);
+
+    CLOCK_SetClkDiv(kCLOCK_DivLcdClk, 1, true);
+
+    BOARD_InitPins();
+    BOARD_BootClockFROHF48M();
+    // BOARD_InitDebugConsole();
+
+    /* Set the back light PWM. */
+    BOARD_InitPWM();
+
+    // APP_FillBuffer((void *)(s_frameBufs));
+
+    status = APP_LCDC_Init();
+    if (status != kStatus_Success)
+    {
+        safe_printf("LCD init failed\n");
+    }
+    assert(status == kStatus_Success);
+
+    status = APP_I2C_Init();
+    if (status != kStatus_Success)
+    {
+        safe_printf("I2C init failed\n");
+    }
+    assert(status == kStatus_Success);
+
+    GPIO_PinInit(GPIO, 2, 27, &pin_config);
+    // GPIO_WritePinOutput(GPIO, 2, 27, 1);
+    GPIO->B[2][27] = 1;
+
+    status = FT5406_Init(&touch_handle, EXAMPLE_I2C_MASTER);
+    if (status != kStatus_Success)
+    {
+        safe_printf("Touch panel init failed\n");
+    }
+    assert(status == kStatus_Success);
+
+    uint32_t xMin = 0xbd;
+    uint32_t xMax = 0xea;
+    uint32_t yMin = 0xb7;
+    uint32_t yMax = 0x12f;
+
+    for (;;)
+    {
+        if (kStatus_Success == FT5406_GetSingleTouch(&touch_handle, &touch_event, &cursorPosX, &cursorPosY))
+        {
+            if ((touch_event == kTouch_Down) || (touch_event == kTouch_Contact))
+            {
+                /* Update cursor position */
+                APP_SetCursorPosition(cursorPosY, cursorPosX);
+                if (xMin < cursorPosX && cursorPosX < xMax && yMin < cursorPosY && cursorPosY < yMax) {
+                  safe_printf("You've clicked the button! (0x%2x, 0x%2x)\r\n", cursorPosX, cursorPosY);
+                }
+            }
+        }
+        else
+        {
+            safe_printf("error reading touch controller\r\n");
+        }
+    }
+}