PSoC4 : UART + Capsense Tuner

タッチセンサの感度調整ツール「CapsenseTuner」で、I2C通信を使う例はよく見ます。サンプルもI2C通信のみしかありません。でもUARTにも対応していて、CapsenseTunerでも接続先をUARTに設定することができます。サイトにも、できるよと情報があるのですが、実際のプログラムやプロジェクトの細かい設定までは、説明が見つかりません。

いろいろやってみたところ、うまく動いたのでメモしておきます。

#include "cy_pdl.h"
#include "cybsp.h"
#include "cycfg.h"
#include "cycfg_capsense.h"
#include "cy_gpio.h"

#define CAPSENSE_INTR_PRIORITY    (3u)  // psoc4 priority = 0~3
#define CY_ASSERT_FAILED          (0u)

static void initialize_capsense_uart(void);
static void capsense_isr(void);

#define MAX_S 6
uint8_t led = 0;
uint8_t touch_status[MAX_S] = { 0 };
uint8_t touch[MAX_S] = { 0 };

cy_stc_scb_uart_context_t CYBSP_UART_context;


void TunerSend(void * context)
{
    uint8_t uartTxHeader[] = {0x0Du, 0x0Au};
    uint8_t uartTxTail[] = {0x00u, 0xFFu, 0xFFu};
    (void)context;
    Cy_SCB_UART_PutArrayBlocking(CYBSP_UART_HW, &(uartTxHeader[0u]), sizeof(uartTxHeader));
    Cy_SCB_UART_PutArrayBlocking(CYBSP_UART_HW, (uint8_t *)&cy_capsense_tuner, sizeof(cy_capsense_tuner));
    Cy_SCB_UART_PutArrayBlocking(CYBSP_UART_HW, uartTxTail, sizeof(uartTxTail));
}

void TunerReceive(uint8_t ** packet, uint8_t ** tunerPacket, void * context)
{
    uint32_t i;
    (void) context;
    static uint32_t dataIndex = 0u;
    static uint8_t commandPacket[16u] = {0u};
    while(0u != Cy_SCB_UART_GetNumInRxFifo(CYBSP_UART_HW))
    {
        commandPacket[dataIndex++] = (uint8_t)Cy_SCB_UART_Get(CYBSP_UART_HW);
        if (CY_CAPSENSE_COMMAND_PACKET_SIZE <= dataIndex)
        {
            if (CY_CAPSENSE_COMMAND_OK == Cy_CapSense_CheckTunerCmdIntegrity(&commandPacket[0u]))
            {
                /* Found a correct command, reset data index and assign pointers to buffers */
                dataIndex = 0u;
                *tunerPacket = (uint8_t *)&cy_capsense_tuner;
                *packet = &commandPacket[0u];
                break;
            }
            else
            {
                /* Command is not correct, remove the first byte in commandPacket FIFO */
                dataIndex--;
                for(i = 0u; i < (CY_CAPSENSE_COMMAND_PACKET_SIZE - 1u); i++)
                {
                    commandPacket[i] = commandPacket[i + 1u];
                }
            }
        }
    }
}

int main(void) {
    cy_rslt_t result;

    // Initialize Device and Peripherals
    result = cybsp_init();
    if (result != CY_RSLT_SUCCESS) {
        CY_ASSERT(0);
    }

    // Enable Global Interrupts
    __enable_irq();

    // StartUp LED
    for (int i = 0; i < 10; i++) {
        Cy_GPIO_Write(P1_2_PORT, P1_2_NUM, 1);
        Cy_SysLib_Delay(25);
        Cy_GPIO_Write(P1_2_PORT, P1_2_NUM, 0);
        Cy_SysLib_Delay(50);
    }

    // CAPSENSE & UART
    initialize_capsense_uart();


    // CAPSENSE First SCAN
    Cy_CapSense_ScanAllWidgets(&cy_capsense_context);

    // Loop
    for (;;) {
        //
        if (CY_CAPSENSE_NOT_BUSY == Cy_CapSense_IsBusy(&cy_capsense_context)) {

            // CAPSENSE Process all widgets
            Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);

            led = 0;
            for (int i = 0; i < MAX_S; i++) {
                if (0 != Cy_CapSense_IsWidgetActive(i, &cy_capsense_context)) {
                    if (touch_status[i] == 0) {
                        touch_status[i] = 1;
                        touch[i] = 1;
                    } else {
                        touch[i] = 0;
                    }
                } else {
                    touch[i] = 0;
                    touch_status[i] = 0;
                }
                if (touch[i] == 1) {
                    led = 1;
                }
            }
            if (led == 1) {
                Cy_GPIO_Write(P1_2_PORT, P1_2_NUM, 1);
            } else {
                Cy_GPIO_Write(P1_2_PORT, P1_2_NUM, 0);
            }

            // CAPSENSE Tuner
            Cy_CapSense_RunTuner(&cy_capsense_context);

            // CAPSENSE Start the next scan
            Cy_CapSense_ScanAllWidgets(&cy_capsense_context);

       }
    }

}



// CAPSENSE
static void initialize_capsense_uart(void) {
	//CAPSENSE
    cy_capsense_status_t status = CY_CAPSENSE_STATUS_SUCCESS;
    const cy_stc_sysint_t capsense_interrupt_config = {
            .intrSrc = CYBSP_CSD_IRQ, .intrPriority = CAPSENSE_INTR_PRIORITY, };

    status = Cy_CapSense_Init(&cy_capsense_context);

    if (CY_CAPSENSE_STATUS_SUCCESS == status) {
        Cy_SysInt_Init(&capsense_interrupt_config, capsense_isr);
        NVIC_ClearPendingIRQ(capsense_interrupt_config.intrSrc);
        NVIC_EnableIRQ(capsense_interrupt_config.intrSrc);
        status = Cy_CapSense_Enable(&cy_capsense_context);
    }

    // UART
    // Register communication CALLBACKS
    cy_capsense_context.ptrInternalContext->ptrTunerSendCallback = TunerSend;
    cy_capsense_context.ptrInternalContext->ptrTunerReceiveCallback = TunerReceive;
    Cy_SCB_UART_Init(CYBSP_UART_HW, &CYBSP_UART_config, &CYBSP_UART_context);
    Cy_SCB_UART_Enable(CYBSP_UART_HW);
}

static void capsense_isr(void) {
    Cy_CapSense_InterruptHandler(CYBSP_CSD_HW, &cy_capsense_context);
}