### One-time liquid level calibration with Em_EEPROM (Cy_CapSense_IsLlwCalibrationValid) Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Shows the three steps for one-time liquid level calibration: EEPROM configuration, EEPROM initialization, and the start of the calibration routine. The first block defines Em_EEPROM parameters and storage; the second initializes Em_EEPROM and asserts on failure; the third initializes CAPSENSE, sets up the interrupt, and begins reading factory-calibrated values from EEPROM. The example is incomplete at the end of the third block. ```c #define CY_ASSERT_FAILED (0u) /* Emulated EEPROM Configuration details. All the sizes mentioned are in bytes. * For details on how to configure these values refer to cy_em_eeprom.h. The * middleware documentation is provided in Emulated EEPROM API Reference Manual. * The user can access it from the Documentation section in the Quick Panel. */ #define WD_CDAC_PARMS_SIZE (1u+ 1u +1u +2u) // Status+CRef+CFine+CComp_div #define TOTAL_WD_CDAC_PARMS_SIZE (CY_CAPSENSE_TOTAL_WIDGET_COUNT * WD_CDAC_PARMS_SIZE) #define SNS_CDAC_PARMS_SIZE (CY_CAPSENSE_SENSOR_COUNT * 1u) // CComp #define TOTAL_CDAC_PARMS_SIZE (TOTAL_WD_CDAC_PARMS_SIZE + SNS_CDAC_PARMS_SIZE) /* Logical Size of Emulated EEPROM in bytes */ #define LOGICAL_EM_EEPROM_SIZE TOTAL_CDAC_PARMS_SIZE #define LOGICAL_EM_EEPROM_START (0u) #define EEPROM_VALID (1u) #define EEPROM_STATE_OFFSET (0u) #define EEPROM_DATA_OFFSET (1u) cy_stc_eeprom_context_t em_eeprom_context; uint8_t eeprom_data[LOGICAL_EM_EEPROM_SIZE]; /*If enabled (1 - enabled, 0 - disabled), a checksum (stored in a row) is calculated on each row of data, * while a redundant copy of Em_EEPROM is stored in another location. * When data is read, first the checksum is checked. If that checksum is bad, and the redundant copy's checksum is good, the copy is restored. */ #define REDUNDANT_COPY (1u) /*If enabled (1 - enabled, 0 - disabled), the blocking writes to nvm are used in the design. * Otherwise, non-blocking nvm writes are used. From the user's perspective, * the behavior of blocking and non-blocking writes are the same - the difference is that * the non-blocking writes do not block the interrupts. Note Non-blocking nvm write is only supported by PSoC 6. */ #define BLOCKING_WRITE (1u) /*The higher the factor is, the more nvm is used, but a higher number of erase/write cycles can be done on Em_EEPROM. * Multiply this number by the datasheet write endurance spec to determine the max of write cycles. * The amount of wear leveling from 1 to 10. 1 means no wear leveling is used. */ #define WEAR_LEVELLING_FACTOR (2u) /*Simple mode, when enabled (1 - enabled, 0 - disabled), * means no additional service information is stored by the Em_EEPROM middleware * like checksums, headers, a number of writes, etc. */ #define SIMPLE_MODE (0u) #define EM_EEPROM_SIZE ((TOTAL_CDAC_PARMS_SIZE % CY_EM_EEPROM_FLASH_SIZEOF_ROW) ? ((TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) + 1) * CY_EM_EEPROM_FLASH_SIZEOF_ROW : (TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) * CY_EM_EEPROM_FLASH_SIZEOF_ROW) #define EM_EEPROM_PHYSICAL_SIZE (CY_EM_EEPROM_GET_PHYSICAL_SIZE(EM_EEPROM_SIZE, SIMPLE_MODE, WEAR_LEVELLING_FACTOR, REDUNDANT_COPY)) cy_stc_eeprom_context_t em_eeprom_context; static cy_stc_eeprom_config_t em_eeprom_config = { .eepromSize = EM_EEPROM_SIZE, /* 256 bytes */ .blockingWrite = BLOCKING_WRITE, /* Blocking writes enabled */ .redundantCopy = REDUNDANT_COPY, /* Redundant copy enabled */ .wearLevelingFactor = WEAR_LEVELLING_FACTOR, /* Wear levelling factor of 2 */ .simpleMode = SIMPLE_MODE, /* Simple mode disabled */ }; /* EEPROM storage Emulated EEPROM flash. */ CY_ALIGN( CY_EM_EEPROM_FLASH_SIZEOF_ROW) const uint8_t em_eeprom_storage[EM_EEPROM_PHYSICAL_SIZE] = { 0u }; ``` ```c cy_en_em_eeprom_status_t em_eeprom_status; /* Initialize the flash start address in Emulated EEPROM configuration structure*/ em_eeprom_config.userFlashStartAddr = (uint32_t)em_eeprom_storage; /* Initialize Emulated EEPROM */ em_eeprom_status = Cy_Em_EEPROM_Init(&em_eeprom_config, &em_eeprom_context); /* Emulated EEPROM init failed. Stop program execution */ if (em_eeprom_status != CY_EM_EEPROM_SUCCESS) { CY_ASSERT(CY_ASSERT_FAILED); } ``` ```c uint8_t *ptr_eeprom_data = 0; uint32_t wd_id; Cy_CapSense_Init(&cy_capsense_context); /* Initialize interrupt */ Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc); NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc); /* Read the factory calibrated values from EEPROM*/ Cy_Em_EEPROM_Read(LOGICAL_EM_EEPROM_START, eeprom_data, ``` -------------------------------- ### Include and Initialize Configuration in MBED OS Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/index.html Include the cycfg.h header and call the resource initialization function at the start of the main function when creating a custom project. ```c #include "cycfg.h" init_cycfg_all(); ``` -------------------------------- ### One-time calibration with Cy_CapSense_ReadWidgetCdacParam() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html One-time calibration example for Cy_CapSense_ReadWidgetCdacParam(). Step 1 defines Emulated EEPROM configuration macros and storage. Step 2 initializes Emulated EEPROM with Cy_Em_EEPROM_Init(). Step 3 starts the calibration by initializing CAPSENSE and the interrupt. ```c #define CY_ASSERT_FAILED (0u) /* Emulated EEPROM Configuration details. All the sizes mentioned are in bytes. * For details on how to configure these values refer to cy_em_eeprom.h. The * middleware documentation is provided in Emulated EEPROM API Reference Manual. * The user can access it from the Documentation section in the Quick Panel. */ #define WD_CDAC_PARMS_SIZE (1u+ 1u +1u +2u) // Status+CRef+CFine+CComp_div #define TOTAL_WD_CDAC_PARMS_SIZE (CY_CAPSENSE_TOTAL_WIDGET_COUNT * WD_CDAC_PARMS_SIZE) #define SNS_CDAC_PARMS_SIZE (CY_CAPSENSE_SENSOR_COUNT * 1u) // CComp #define TOTAL_CDAC_PARMS_SIZE (TOTAL_WD_CDAC_PARMS_SIZE + SNS_CDAC_PARMS_SIZE) /* Logical Size of Emulated EEPROM in bytes */ #define LOGICAL_EM_EEPROM_SIZE TOTAL_CDAC_PARMS_SIZE #define LOGICAL_EM_EEPROM_START (0u) #define EEPROM_VALID (1u) #define EEPROM_STATE_OFFSET (0u) #define EEPROM_DATA_OFFSET (1u) cy_stc_eeprom_context_t em_eeprom_context; uint8_t eeprom_data[LOGICAL_EM_EEPROM_SIZE]; /*If enabled (1 - enabled, 0 - disabled), a checksum (stored in a row) is calculated on each row of data, * while a redundant copy of Em_EEPROM is stored in another location. * When data is read, first the checksum is checked. If that checksum is bad, and the redundant copy's checksum is good, the copy is restored. */ #define REDUNDANT_COPY (1u) /*If enabled (1 - enabled, 0 - disabled), the blocking writes to nvm are used in the design. * Otherwise, non-blocking nvm writes are used. From the user's perspective, * the behavior of blocking and non-blocking writes are the same - the difference is that * the non-blocking writes do not block the interrupts. Note Non-blocking nvm write is only supported by PSoC 6. */ #define BLOCKING_WRITE (1u) /*The higher the factor is, the more nvm is used, but a higher number of erase/write cycles can be done on Em_EEPROM. * Multiply this number by the datasheet write endurance spec to determine the max of write cycles. * The amount of wear leveling from 1 to 10. 1 means no wear leveling is used. */ #define WEAR_LEVELLING_FACTOR (2u) /*Simple mode, when enabled (1 - enabled, 0 - disabled), * means no additional service information is stored by the Em_EEPROM middleware * like checksums, headers, a number of writes, etc. */ #define SIMPLE_MODE (0u) #define EM_EEPROM_SIZE ((TOTAL_CDAC_PARMS_SIZE % CY_EM_EEPROM_FLASH_SIZEOF_ROW) ? ((TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) + 1) * CY_EM_EEPROM_FLASH_SIZEOF_ROW : (TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) * CY_EM_EEPROM_FLASH_SIZEOF_ROW) #define EM_EEPROM_PHYSICAL_SIZE (CY_EM_EEPROM_GET_PHYSICAL_SIZE(EM_EEPROM_SIZE, SIMPLE_MODE, WEAR_LEVELLING_FACTOR, REDUNDANT_COPY)) cy_stc_eeprom_context_t em_eeprom_context; static cy_stc_eeprom_config_t em_eeprom_config = { .eepromSize = EM_EEPROM_SIZE, /* 256 bytes */ .blockingWrite = BLOCKING_WRITE, /* Blocking writes enabled */ .redundantCopy = REDUNDANT_COPY, /* Redundant copy enabled */ .wearLevelingFactor = WEAR_LEVELLING_FACTOR, /* Wear levelling factor of 2 */ .simpleMode = SIMPLE_MODE, /* Simple mode disabled */ }; /* EEPROM storage Emulated EEPROM flash. */ CY_ALIGN( CY_EM_EEPROM_FLASH_SIZEOF_ROW) const uint8_t em_eeprom_storage[EM_EEPROM_PHYSICAL_SIZE] = { 0u }; ``` ```c cy_en_em_eeprom_status_t em_eeprom_status; /* Initialize the flash start address in Emulated EEPROM configuration structure*/ em_eeprom_config.userFlashStartAddr = (uint32_t)em_eeprom_storage; /* Initialize Emulated EEPROM */ em_eeprom_status = Cy_Em_EEPROM_Init(&em_eeprom_config, &em_eeprom_context); /* Emulated EEPROM init failed. Stop program execution */ if (em_eeprom_status != CY_EM_EEPROM_SUCCESS) { CY_ASSERT(CY_ASSERT_FAILED); } ``` ```c uint8_t *ptr_eeprom_data = 0; uint32_t wd_id; Cy_CapSense_Init(&cy_capsense_context); /* Initialize interrupt */ ``` -------------------------------- ### Pipeline scan and process with Cy_CapSense_ProcessWidget() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Pipeline implementation example for Cy_CapSense_ProcessWidget(). It scans the first widget, then in a loop scans the next widget and processes the previous one. Uses Cy_CapSense_ScanSlots() for fifth-generation platforms and Cy_CapSense_ScanWidget() for fourth-generation, with error handling via CY_ASSERT(0u). ```c /*...*/ currentWidgetIndex = 0u; /* The first widget scan start */ #if (CY_CAPSENSE_PLATFORM_BLOCK_FIFTH_GEN || CY_CAPSENSE_PLATFORM_BLOCK_FIFTH_GEN_LP) if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanSlots( cy_capsense_context.ptrWdConfig[currentWidgetIndex].firstSlotId, cy_capsense_context.ptrWdConfig[currentWidgetIndex].numSlots, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } #else /* CY_CAPSENSE_PLATFORM_BLOCK_FOURTH_GEN */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanWidget(currentWidgetIndex, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } #endif for (;;) { if (CY_CAPSENSE_NOT_BUSY == Cy_CapSense_IsBusy(&cy_capsense_context)) { /* Store the current widget index */ previousWidgetIndex = currentWidgetIndex; /* Go to the next widget */ currentWidgetIndex++; if (currentWidgetIndex == CY_CAPSENSE_WIDGET_COUNT) { /* Reset the current widget index to start scan from the first one */ currentWidgetIndex = 0u; } /* The next widget scan start */ #if (CY_CAPSENSE_PLATFORM_BLOCK_FIFTH_GEN || CY_CAPSENSE_PLATFORM_BLOCK_FIFTH_GEN_LP) if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanSlots( cy_capsense_context.ptrWdConfig[currentWidgetIndex].firstSlotId, cy_capsense_context.ptrWdConfig[currentWidgetIndex].numSlots, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } #else /* CY_CAPSENSE_PLATFORM_BLOCK_FOURTH_GEN */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanWidget(currentWidgetIndex, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } #endif /* Process the previous widget while scanning the next one */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ProcessWidget(previousWidgetIndex, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } } } /*...*/ ``` -------------------------------- ### Cy_CapSense_ScanExt Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Starts a conversion on the pre-configured sensor. ```APIDOC ## Cy_CapSense_ScanExt ### Description Starts a conversion on the pre-configured sensor. ### Function Signature cy_capsense_status_t Cy_CapSense_ScanExt (cy_stc_capsense_context_t *context) ### Parameters - **context** (cy_stc_capsense_context_t *) - Required - Pointer to the CAPSENSE™ context structure. ### Return Value - **cy_capsense_status_t** - Status of the operation. ``` -------------------------------- ### One-time calibration with Cy_CapSense_SetWidgetCalibrationState Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Full example for one-time calibration using Cy_CapSense_SetWidgetCalibrationState. Includes Emulated EEPROM configuration, initialization, and reading factory calibrated values. Requires fifth-generation low power CAPSENSE™ and PSoC 6 for non-blocking writes. ```c #define CY_ASSERT_FAILED (0u) /* Emulated EEPROM Configuration details. All the sizes mentioned are in bytes. * For details on how to configure these values refer to cy_em_eeprom.h. The * middleware documentation is provided in Emulated EEPROM API Reference Manual. * The user can access it from the Documentation section in the Quick Panel. */ #define WD_CDAC_PARMS_SIZE (1u+ 1u +1u +2u) // Status+CRef+CFine+CComp_div #define TOTAL_WD_CDAC_PARMS_SIZE (CY_CAPSENSE_TOTAL_WIDGET_COUNT * WD_CDAC_PARMS_SIZE) #define SNS_CDAC_PARMS_SIZE (CY_CAPSENSE_SENSOR_COUNT * 1u) // CComp #define TOTAL_CDAC_PARMS_SIZE (TOTAL_WD_CDAC_PARMS_SIZE + SNS_CDAC_PARMS_SIZE) /* Logical Size of Emulated EEPROM in bytes */ #define LOGICAL_EM_EEPROM_SIZE TOTAL_CDAC_PARMS_SIZE #define LOGICAL_EM_EEPROM_START (0u) #define EEPROM_VALID (1u) #define EEPROM_STATE_OFFSET (0u) #define EEPROM_DATA_OFFSET (1u) cy_stc_eeprom_context_t em_eeprom_context; uint8_t eeprom_data[LOGICAL_EM_EEPROM_SIZE]; /*If enabled (1 - enabled, 0 - disabled), a checksum (stored in a row) is calculated on each row of data, * while a redundant copy of Em_EEPROM is stored in another location. * When data is read, first the checksum is checked. If that checksum is bad, and the redundant copy's checksum is good, the copy is restored. */ #define REDUNDANT_COPY (1u) /*If enabled (1 - enabled, 0 - disabled), the blocking writes to nvm are used in the design. * Otherwise, non-blocking nvm writes are used. From the user's perspective, * the behavior of blocking and non-blocking writes are the same - the difference is that * the non-blocking writes do not block the interrupts. Note Non-blocking nvm write is only supported by PSoC 6. */ #define BLOCKING_WRITE (1u) /*The higher the factor is, the more nvm is used, but a higher number of erase/write cycles can be done on Em_EEPROM. * Multiply this number by the datasheet write endurance spec to determine the max of write cycles. * The amount of wear leveling from 1 to 10. 1 means no wear leveling is used. */ #define WEAR_LEVELLING_FACTOR (2u) /*Simple mode, when enabled (1 - enabled, 0 - disabled), * means no additional service information is stored by the Em_EEPROM middleware * like checksums, headers, a number of writes, etc. */ #define SIMPLE_MODE (0u) #define EM_EEPROM_SIZE ((TOTAL_CDAC_PARMS_SIZE % CY_EM_EEPROM_FLASH_SIZEOF_ROW) ? ((TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) + 1) * CY_EM_EEPROM_FLASH_SIZEOF_ROW : (TOTAL_CDAC_PARMS_SIZE / CY_EM_EEPROM_FLASH_SIZEOF_ROW) * CY_EM_EEPROM_FLASH_SIZEOF_ROW) #define EM_EEPROM_PHYSICAL_SIZE (CY_EM_EEPROM_GET_PHYSICAL_SIZE(EM_EEPROM_SIZE, SIMPLE_MODE, WEAR_LEVELLING_FACTOR, REDUNDANT_COPY)) cy_stc_eeprom_context_t em_eeprom_context; static cy_stc_eeprom_config_t em_eeprom_config = { .eepromSize = EM_EEPROM_SIZE, /* 256 bytes */ .blockingWrite = BLOCKING_WRITE, /* Blocking writes enabled */ .redundantCopy = REDUNDANT_COPY, /* Redundant copy enabled */ .wearLevelingFactor = WEAR_LEVELLING_FACTOR, /* Wear levelling factor of 2 */ .simpleMode = SIMPLE_MODE, /* Simple mode disabled */ }; /* EEPROM storage Emulated EEPROM flash. */ CY_ALIGN( CY_EM_EEPROM_FLASH_SIZEOF_ROW) const uint8_t em_eeprom_storage[EM_EEPROM_PHYSICAL_SIZE] = { 0u }; ``` ```c cy_en_em_eeprom_status_t em_eeprom_status; /* Initialize the flash start address in Emulated EEPROM configuration structure*/ em_eeprom_config.userFlashStartAddr = (uint32_t)em_eeprom_storage; /* Initialize Emulated EEPROM */ em_eeprom_status = Cy_Em_EEPROM_Init(&em_eeprom_config, &em_eeprom_context); /* Emulated EEPROM init failed. Stop program execution */ if (em_eeprom_status != CY_EM_EEPROM_SUCCESS) { CY_ASSERT(CY_ASSERT_FAILED); } ``` ```c uint8_t *ptr_eeprom_data = 0; uint32_t wd_id; Cy_CapSense_Init(&cy_capsense_context); /* Initialize interrupt */ Cy_Sys_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc); NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc); /* Read the factory calibrated values from EEPROM*/ Cy_Em_EEPROM_Read(LOGICAL_EM_EEPROM_START, eeprom_data, LOGICAL_EM_EEPROM_SIZE, &em_eeprom_context); ``` -------------------------------- ### Cy_CapSense_ProcessSensorExt() pipeline example Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Pipeline implementation for sensor scanning and processing using Cy_CapSense_ScanSensor, Cy_CapSense_IsBusy, Cy_CapSense_ProcessSensorExt, and Cy_CapSense_ProcessWidgetExt. It scans the next sensor while processing the previous one, and handles errors with CY_ASSERT(0u). ```c /*...*/ currentSenorsIndex = 0u; /* The first sensor scan start */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanSensor(CY_CAPSENSE_TOUCHPAD0_WDGT_ID, currentSenorsIndex, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } for (;;) { if (CY_CAPSENSE_NOT_BUSY == Cy_CapSense_IsBusy(&cy_capsense_context)) { /* Store the current sensor index */ previousSensorIndex = currentSenorsIndex; /* Go to the next sensor */ currentSenorsIndex++; if (currentSenorsIndex == cy_capsense_context.ptrWdConfig[CY_CAPSENSE_TOUCHPAD0_WDGT_ID].numSns) { /* Reset sensor index to start from the first sensor */ currentSenorsIndex = 0u; } /* The next sensor scan start */ Cy_CapSense_ScanSensor(CY_CAPSENSE_TOUCHPAD0_WDGT_ID, currentSenorsIndex, &cy_capsense_context); /* Process the previous sensor while scanning the next one */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ProcessSensorExt(CY_CAPSENSE_TOUCHPAD0_WDGT_ID, previousSensorIndex, CY_CAPSENSE_PROCESS_ALL, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } previousSensorIndex++; if (previousSensorIndex == cy_capsense_context.ptrWdConfig[CY_CAPSENSE_TOUCHPAD0_WDGT_ID].numSns) { /* All widget sensors are processed, therefore process only widget-related task */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ProcessWidgetExt(CY_CAPSENSE_TOUCHPAD0_WDGT_ID, CY_CAPSENSE_PROCESS_STATUS, &cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } } } } /*...*/ ``` -------------------------------- ### UART synchronization with Cy_CapSense_RunTuner() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Steps 2-6 of the UART synchronization example for Cy_CapSense_RunTuner(). Requires an SCB resource named "UART" configured in UART mode with matching Tuner tool settings. The callbacks TunerSend and TunerReceive must be registered, and the main loop periodically calls Cy_CapSense_RunTuner() to enable monitoring and parameter changes. ```c cy_stc_scb_uart_context_t UART_context; ``` ```c void UART_Interrupt(void) { Cy_SCB_UART_Interrupt(UART_HW, &UART_context); } ``` ```c void TunerSend(void * context) { uint8_t uartTxHeader[] = {0x0Du, 0x0Au}; uint8_t uartTxTail[] = {0x00u, 0xFFu, 0xFFu}; (void)context; Cy_SCB_UART_PutArrayBlocking(UART_HW, &(uartTxHeader[0u]), sizeof(uartTxHeader)); Cy_SCB_UART_PutArrayBlocking(UART_HW, (uint8_t *)&cy_capsense_tuner, sizeof(cy_capsense_tuner)); Cy_SCB_UART_PutArrayBlocking(UART_HW, &(uartTxTail[0u]), sizeof(uartTxTail)); /* Blocking wait for transfer completion */ while (!Cy_SCB_UART_IsTxComplete(UART_HW)) { } } ``` ```c void TunerReceive(uint8_t ** packet, uint8_t ** tunerPacket, void * context) { uint32_t i; (void)context; static uint32_t dataIndex = 0u; static uint8_t commandPacket[CY_CAPSENSE_COMMAND_PACKET_SIZE] = {0u}; uint32_t numBytes; while(0u != Cy_SCB_UART_GetNumInRingBuffer(UART_HW, &UART_context)) { numBytes = Cy_SCB_UART_GetNumInRingBuffer(UART_HW, &UART_context); /* Calculate number of bytes to read from ring buffer */ if ((CY_CAPSENSE_COMMAND_PACKET_SIZE - dataIndex) < numBytes) { numBytes = CY_CAPSENSE_COMMAND_PACKET_SIZE - dataIndex; } /* Add received data to the end of commandPacket */ Cy_SCB_UART_Receive(UART_HW, &commandPacket[dataIndex], numBytes, &UART_context); dataIndex += numBytes; 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 buffer */ dataIndex--; for (i = 0u; i < (CY_CAPSENSE_COMMAND_PACKET_SIZE - 1u); i++) { commandPacket[i] = commandPacket[i + 1u]; } } } } } ``` ```c /*...*/ /* Define UART ring buffer size to hold extra tuner command packets. * Additional byte is required by the UART ring buffer implementation. */ #define UART_RINGBUFFER_SIZE (CY_CAPSENSE_COMMAND_PACKET_SIZE * 2u + 1u) static uint8_t uartRingBuffer[UART_RINGBUFFER_SIZE]; const cy_stc_sysint_t uart_intr_config = { .intrSrc = UART_IRQ, .intrPriority = 2u, }; /* Register communication callbacks */ cy_capsense_context.ptrInternalContext->ptrTunerSendCallback = TunerSend; cy_capsense_context.ptrInternalContext->ptrTunerReceiveCallback = TunerReceive; /* Configure and enable UART communication */ Cy_SCB_UART_Init(UART_HW, &UART_config, &UART_context); Cy_SysInt_Init(&uart_intr_config, UART_Interrupt); NVIC_EnableIRQ(uart_intr_config.intrSrc); Cy_SCB_UART_StartRingBuffer(UART_HW, uartRingBuffer, UART_RINGBUFFER_SIZE, &UART_context); Cy_SCB_UART_Enable(UART_HW); /* Initialize the firmware modules. */ if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_Enable(&cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } for (;;) { if (CY_CAPSENSE_NOT_BUSY == Cy_CapSense_IsBusy(&cy_capsense_context)) { if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ProcessAllWidgets(&cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } /* * Cy_CapSense_RunTuner() calls periodically communication callbacks * for hence the Tuner tool are able to monitor sensor signals/statuses * and change the parameters for easy tuning. */ (void)Cy_CapSense_RunTuner(&cy_capsense_context); if (CY_CAPSENSE_STATUS_SUCCESS != Cy_CapSense_ScanAllWidgets(&cy_capsense_context)) { /* Insert the error handle code here, for instance as below */ CY_ASSERT(0u); } } } } /*...*/ ``` -------------------------------- ### Configure and run Autonomous mode low-power scanning with Cy_CapSense_ConfigureMsclpWotTimer() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Configure the hardware for Autonomous mode (Wake On Touch) while the device is in Deep Sleep power mode. Set the number of scans via wotTimeout (default 100) and the interval between low-power frames via Cy_CapSense_ConfigureMsclpWotTimer() (default 100000 us). The loop starts scanning all low-power widgets with Cy_CapSense_ScanAllLpSlots(), enters Deep Sleep while busy, and checks for active widgets to decide the next action. ```c /* * Scenario: Configure the hardware to perform scanning * in Autonomous mode (Wake On Touch), while the device is in Deep Sleep power mode. */ /* * Option: Configure the number of scans performed in Autonomous mode. * The number of scans performed in Autonomous mode can be configured by * writing to the wotTimeout field. The default value is 100 scans. */ cy_capsense_context.ptrInternalContext->wotTimeout = 60u; /* * Option: Configure the interval between low-power frames. * The interval between scans in Autonomous mode can be configured by using * Cy_CapSense_ConfigureMsclpWotTimer() function. This interval is inserted * before each scan, so the first scan starts only after the first interval * passes. The default value is 100000 us. */ Cy_CapSense_ConfigureMsclpWotTimer(80000u, &cy_capsense_context); for (;;) { /* * This call starts scanning all low-power widgets. The scan is performed autonomously, * so the Deep Sleep transition is allowed. */ Cy_CapSense_ScanAllLpSlots(&cy_capsense_context); while (CY_CAPSENSE_NOT_BUSY != Cy_CapSense_IsBusy(&cy_capsense_context)) { Cy_SysPm_CpuEnterDeepSleep (); } if (0u != Cy_CapSense_IsAnyLpWidgetActive(&cy_capsense_context)) { /* A touch is detected on a low-power widget, so switch the state machine to activate the widgets scan */ } else { /* No activity, so run the LP scan again or perform a single active widget scan for the baseline update (to compensate temperature drift, etc.) */ } } ``` -------------------------------- ### Time-multiplexing CAPSENSE and CSDADC with Cy_CapSense_Save() and Cy_CapSense_Restore() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Example of sharing the CAPSENSE HW block between CAPSENSE and CSDADC middleware. Declares interrupt configuration variables, defines interrupt handlers, and shows the main flow that initializes, saves, restores, and switches between the two middleware contexts. ```c const cy_stc_sysint_t CapSense_ISR_cfg = { .intrSrc = csd_interrupt_IRQn, /* Interrupt source is the CSD interrupt */ .intrPriority = 7u, /* Interrupt priority is 7 */ }; ``` ```c const cy_stc_sysint_t CSDADC_ISR_cfg = { .intrSrc = csd_interrupt_IRQn, /* Interrupt source is the CSD interrupt */ .intrPriority = 7u, /* Interrupt priority is 7 */ }; ``` ```c void CapSense_InterruptHandler(void) { Cy_CapSense_InterruptHandler(CapSense_HW, &cy_capsense_context); } ``` ```c static void CSDADC_Interrupt(void) { Cy_CSDADC_InterruptHandler(CSD0, &cy_csd_0_context); } ``` ```c /* ... */ /* Initialize CAPSENSE MW */ Cy_CapSense_Init(&cy_capsense_context); Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc); NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc); Cy_CapSense_Enable(&cy_capsense_context); Cy_CapSense_Save(&cy_capsense_context); /* Initialize CSDADC MW */ Cy_CSDADC_Init(&CapSense_csdadc_config, &cy_csdadc_context); Cy_SysInt_Init(&CSDADC_ISR_cfg, &CSDADC_Interrupt); NVIC_ClearPendingIRQ(CSDADC_ISR_cfg.intrSrc); NVIC_EnableIRQ(CSDADC_ISR_cfg.intrSrc); Cy_CSDADC_Enable(&cy_csdadc_context); Cy_CSDADC_Save(&cy_csdadc_context); for (;;) { /* Switch to CAPSENSE MW */ Cy_CapSense_Restore(&cy_capsense_context); Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); /* Perform sensing operation */ Cy_CapSense_Save(&cy_capsense_context); /* Switch to CSDADC MW */ Cy_CSDADC_Restore(&cy_csdadc_context); Cy_SysInt_Init(&CSDADC_ISR_cfg, &CSDADC_Interrupt); /* Do CSDADC measurement operation */ Cy_CSDADC_Save(&cy_csdadc_context); } ``` -------------------------------- ### Cy_CapSense_SetupWidget Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Performs the initialization required to scan the specified widget. ```APIDOC ## Cy_CapSense_SetupWidget ### Description Performs the initialization required to scan the specified widget. ### Function Signature cy_capsense_status_t Cy_CapSense_SetupWidget(uint32_t widgetId, cy_stc_capsense_context_t *context) ### Parameters - **widgetId** (uint32_t) - Identifier of the widget to initialize. - **context** (cy_stc_capsense_context_t*) - Pointer to the CAPSENSE context structure. ### Return Value - **cy_capsense_status_t** - Status of the initialization. ``` -------------------------------- ### Cy_CapSense_SetupWidgetExt Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Performs extended initialization for the specified widget and also performs initialization required for a specific sensor in the widget. ```APIDOC ## Cy_CapSense_SetupWidgetExt ### Description Performs extended initialization for the specified widget and also performs initialization required for a specific sensor in the widget. ### Function Signature cy_capsense_status_t Cy_CapSense_SetupWidgetExt (uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t *context) ### Parameters - **widgetId** (uint32_t) - Required - The widget ID. - **sensorId** (uint32_t) - Required - The sensor ID within the widget. - **context** (cy_stc_capsense_context_t *) - Required - Pointer to the CAPSENSE™ context structure. ### Return Value - **cy_capsense_status_t** - Status of the operation. ``` -------------------------------- ### Cy_CapSense_SetupWidget() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Performs the initialization required to scan the specified widget. This function is deprecated and kept for backward compatibility only; use Cy_CapSense_ScanWidget() instead. It configures the CSD HW block and prepares the middleware for scanning the specified widget. ```APIDOC ## Cy_CapSense_SetupWidget() ### Description Performs the initialization required to scan the specified widget. This function is deprecated and kept for backward compatibility only; use Cy_CapSense_ScanWidget() instead. It configures the CSD HW block and prepares the middleware for scanning the specified widget. ### Function Signature cy_capsense_status_t Cy_CapSense_SetupWidget(uint32_t widgetId, cy_stc_capsense_context_t *context) ### Parameters - **widgetId** (uint32_t) - Required - Specifies the ID number of the widget. A macro for the widget ID can be found in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. - **context** (cy_stc_capsense_context_t *) - Required - The pointer to the CAPSENSE context structure. ### Returns - **CY_CAPSENSE_STATUS_SUCCESS** - The operation is successfully completed. - **CY_CAPSENSE_STATUS_BAD_PARAM** - The widget is invalid or if the specified widget is disabled. - **CY_CAPSENSE_STATUS_INVALID_STATE** - The previous scanning is not completed and the CSD HW block is busy. any other spurious error occurred. ### Notes - This function is deprecated, it will become obsolete in upcoming major version of middleware. It is kept for backward compatibility only. The Cy_CapSense_ScanWidget() function should be used instead. - This function does not start sensor scanning. The Cy_CapSense_Scan() function must be called to start the scan sensors in the widget. - If this function is called more than once, it does not break the middleware operation, but only the last initialized widget is in effect. - The status of a sensor scan must be checked using the Cy_CapSense_IsBusy() function prior to starting a next scan or setting up another widget. - This function is available only for the fourth-generation CAPSENSE. ``` -------------------------------- ### Cy_CapSense_GetParam Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Gets a value of the specified parameter from the cy_capsense_tuner structure. ```APIDOC ## Cy_CapSense_GetParam ### Description Gets a value of the specified parameter from the cy_capsense_tuner structure. ### Function Signature cy_capsense_status_t Cy_CapSense_GetParam (uint32_t paramId, uint32_t *value, const void *ptrTuner, const cy_stc_capsense_context_t *context) ### Parameters - **paramId** (uint32_t) - Required - The parameter ID to get. - **value** (uint32_t *) - Required - Pointer to store the parameter value. - **ptrTuner** (const void *) - Required - Pointer to the tuner structure. - **context** (const cy_stc_capsense_context_t *) - Required - Pointer to the CAPSENSE™ context structure. ### Return Value - **cy_capsense_status_t** - Status of the operation. ``` -------------------------------- ### Cy_CapSense_ConfigureMsclpTimer() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Configures the wakeup timer value for Active mode. The wakeup timer interval is introduced before each scan frame start. Use the function to implement different Active scan refresh rates. ```APIDOC ## Cy_CapSense_ConfigureMsclpTimer() ### Description Configures the wakeup timer value for Active mode. The wakeup timer interval is introduced before each scan frame start. Use the function to implement different Active scan refresh rates (for instance an Active mode with the 128 Hz refresh rate and an Active Low Refresh Rate mode with the 32 Hz refresh rate). ### Function Signature cy_capsense_status_t Cy_CapSense_ConfigureMsclpTimer(uint32_t wakeupTimer, cy_stc_capsense_context_t *context) ### Parameters - **wakeupTimer** (uint32_t) - Required - The desired wakeup timer value in microseconds. - **context** (cy_stc_capsense_context_t *) - Required - The pointer to the CAPSENSE context structure cy_stc_capsense_context_t. ### Returns - **CY_CAPSENSE_STATUS_SUCCESS** - The operation is performed successfully. - **CY_CAPSENSE_STATUS_BAD_PARAM** - The input parameter is invalid. ### Notes - This function is available only for the fifth-generation low power CAPSENSE. - The minimum wakeup time value is corresponding to one ILO cycle (25us for 40KHz ILO). - The maximum wakeup time value depends on actual ILO frequency and can be set to a value, corresponding to 2^16 ILO cycles (1638400us for 40KHz ILO). - If the timer value exceeds 2^16 ILO cycles, it would be set to the maximum possible value. - The real wakeup time interval depends on ILO frequency which have a big tolerance (above +/- 50 %), see device datasheets. - In order to improve the timer accuracy, use Cy_CapSense_IloCompensate() function. ### Function Usage ```c /* * Scenario: Scan all Active widgets in Low Refresh mode at 30 Hz (30 samples per second). * This saves power due to entering Deep Sleep power mode during scanning. * The timer value can be calculated as follows: ((1000 / refresh rate) - frame scan duration). * To achieve the desired refresh rate, configure the wake-up timer to insert the 32-ms delay * before scanning, given the frame scan duration equals 1ms. */ /* Define the 32-ms delay for the wake-up timer **/ #define ALR_INTERVAL_US (32000u) /* Configure the hardware wake-up timer */ Cy_CapSense_ConfigureMsclpTimer(ALR_INTERVAL_US, &cy_capsense_context); for (;;) { /* * This call starts scanning with a delay inserted before scanning. * Scanning will be performed autonomously after a delay is inserted by the internal wake-up timer. */ Cy_CapSense_ScanAllSlots(&cy_capsense_context); /* To save power, move the device to Deep Sleep */ while (CY_CAPSENSE_NOT_BUSY != Cy_CapSense_IsBusy(&cy_capsense_context)) { Cy_SysPm_CpuEnterDeepSleep (); } Cy_CapSense_ProcessAllWidgets(&cy_capsense_context); if (0u != Cy_CapSense_IsAnyWidgetActive(&cy_capsense_context)) { /* Touch on widget is detected */ } } ``` ``` -------------------------------- ### Cy_CapSense_ScanSlots() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Initiates a scan for the specified slots in the CAPSENSE™ middleware. The function starts scanning from the given slot ID and scans the specified number of slots. It is available for fifth-generation and fifth-generation low power CAPSENSE™. ```APIDOC ## Cy_CapSense_ScanSlots() ### Description Initiates a scan for the specified slots in the CAPSENSE™ middleware. The function starts scanning from the given slot ID and scans the specified number of slots. It is available for fifth-generation and fifth-generation low power CAPSENSE™. ### Parameters - **startSlotId** (uint32_t) - Required - The slot ID the scan of the specified frame will be started from. - **numberSlots** (uint32_t) - Required - The number of slots in the specified frame will be scanned. - **context** (cy_stc_capsense_context_t *) - Required - The pointer to the CAPSENSE™ context structure. ### Returns - **CY_CAPSENSE_STATUS_SUCCESS** - The operation is performed successfully. - **CY_CAPSENSE_STATUS_BAD_PARAM** - The input parameter is invalid. - **CY_CAPSENSE_STATUS_HW_BUSY** - The HW is busy with the previous scan. - **CY_CAPSENSE_STATUS_MIXED_SENSORS** - The requested sensors types can't be scanned in one frame (in autonomous mode). ### Usage Notes - If the middleware is busy, do not initiate a new scan or set up widgets. Use the Cy_CapSense_IsBusy() function to check HW busyness at a particular moment. Use the Cy_CapSense_MwState() function to verify if MW executes any firmware tasks related to initialization, scanning, and processing at a particular moment. - This function is available for the fifth-generation and fifth-generation low power CAPSENSE™. ``` -------------------------------- ### Cy_CapSense_InitializeAllStatuses Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Performs initialization of all statuses and related modules including debounce counters and touch positions of all the widgets. ```APIDOC ## Cy_CapSense_InitializeAllStatuses ### Description Performs initialization of all statuses and related modules including debounce counters and touch positions of all the widgets. ### Function Signature void Cy_CapSense_InitializeAllStatuses(const cy_stc_capsense_context_t *context) ### Parameters - **context** (const cy_stc_capsense_context_t *) - Pointer to the CAPSENSE™ context structure. ### Returns - **void** - This function does not return a value. ``` -------------------------------- ### Cy_CapSense_Init() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Initializes the CAPSENSE™ middleware by capturing and configuring the hardware blocks to their default state. Must be called before any other CAPSENSE™ middleware function. ```APIDOC ## Cy_CapSense_Init() ### Description Captures HW blocks (one or more) for CAPSENSE™ operations and configures them to the default state. Call this function with the application program prior to calling any other function of the middleware. ### Function Signature cy_capsense_status_t Cy_CapSense_Init(cy_stc_capsense_context_t *context) ### Parameters - **context** (cy_stc_capsense_context_t*) - Required - The pointer to the CAPSENSE™ context structure generated by the CAPSENSE™ Configurator tool. The structure contains both CAPSENSE™ configuration and internal data and is used during the whole CAPSENSE™ operation. ### Returns - **cy_capsense_status_t** - Returns the status of the initialization process. If CY_CAPSENSE_STATUS_SUCCESS is not received, some of the initialization fails, the middleware may not operate as expected, and repeating of initialization is required. ### Function Usage ```c /* Capture the HW block and initialize it to the default state. */ Cy_CapSense_Init(&cy_capsense_context); /* Initialize interrupt */ Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc); NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc); /* Initialize the firmware modules. */ Cy_CapSense_Enable(&cy_capsense_context); ``` ### Notes - The 'cy_capsense_context' variable is declared in the cycfg_capsense.h file. - The CapSense_ISR_cfg variable should be declared by the application program according to the examples in the documentation. - For MSCLP HW, only the msclp_interrupt_lp_IRQn vector is supported. - The CAPSENSE™ interrupt handler should be declared as shown in the documentation. ``` -------------------------------- ### Cy_CapSense_Enable() Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__high__level.html Initializes the CAPSENSE firmware modules. Call after Cy_CapSense_Init() and interrupt configuration. Returns status of initialization. ```APIDOC ## Cy_CapSense_Enable() ### Description Initializes the CAPSENSE firmware modules. Call the Cy_CapSense_Init() function and configure CAPSENSE HW block interrupts prior to calling this function. The function performs configuration integrity check, pre-calculates internal register values, configures the HW block, executes auto-tuning if selected, calibrates sensors, performs scanning, and initializes baselines and filter histories. ### Function Signature cy_capsense_status_t Cy_CapSense_Enable(cy_stc_capsense_context_t *context) ### Parameters - **context** (cy_stc_capsense_context_t *) - Required - The pointer to the CAPSENSE context structure. ### Returns - **cy_capsense_status_t** - Returns the status of the initialization process. If CY_CAPSENSE_STATUS_SUCCESS is not received, some of the initialization fails. ### Function Usage ```c /* Capture the HW block and initialize it to the default state. */ Cy_CapSense_Init(&cy_capsense_context); /* Initialize interrupt */ Cy_SysInt_Init(&CapSense_ISR_cfg, &CapSense_InterruptHandler); NVIC_ClearPendingIRQ(CapSense_ISR_cfg.intrSrc); NVIC_EnableIRQ(CapSense_ISR_cfg.intrSrc); /* Initialize the firmware modules. */ Cy_CapSense_Enable(&cy_capsense_context); ``` ### Notes - The 'cy_capsense_context' variable is declared in cycfg_capsense.h. - The CapSense_ISR_cfg variable should be declared by the application program according to the examples provided. - The CAPSENSE interrupt handler should be declared by the application program. - The CapSense_HW pointer is defined in cycfg_peripherals.h as _HW. ``` -------------------------------- ### Cy_CapSense_InitializeAllBaselines Source: https://infineon.github.io/capsense/capsense_api_reference_manual/html/group__group__capsense__low__level.html Initializes the baselines of all the sensors of all active widgets. ```APIDOC ## Cy_CapSense_InitializeAllBaselines ### Description Initializes the baselines of all the sensors of all active widgets. ### Function Signature cy_capsense_status_t Cy_CapSense_InitializeAllBaselines(cy_stc_capsense_context_t *context) ### Parameters - **context** (cy_stc_capsense_context_t *) - Pointer to the CAPSENSE™ context structure. ### Returns - **cy_capsense_status_t** - Status code indicating success or failure. ```