> For the complete documentation index, see [llms.txt](https://docs.aic-eec.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aic-eec.com/interfacing-with-infineon-psoc-tm-edge/basic-mcu-interfacing/workshops/gpio-integration.md).

# GPIO Integration

## Lab 4: รวมทุกอย่าง — POT ควบคุม LED Blink Rate

#### วัตถุประสงค์

* **Integration**: รวมความรู้จาก Lab 1-3 (LED, Button, ADC)
* **Real Application**: สร้าง Interactive LED Controller
* **State Machine**: จัดการหลาย input/output พร้อมกัน

#### จะได้เรียนรู้อะไร

* **Multiple Inputs:** จัดการ POT + Button พร้อมกัน
* **Value Mapping:** แปลงค่า POT เป็น delay time
* **Mode Switching:** สลับโหมดด้วย button
* **Non-Blocking Design:** ทำหลายอย่างพร้อมกัน

***

### Application Design

```bash
┌─────────────────────────────────────────────────────────────────┐
│                  Interactive LED Controller                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   INPUTS:                                                       │
│   ════════                                                      │
│   POT (P15_1)     ────►  LED Blink Rate                         │
│   └─ 0%   = 1000ms (ช้าสุด)                                       │
│   └─ 50%  = 525ms                                               │
│   └─ 100% = 50ms  (เร็วสุด)                                       │
│                                                                 │
│   Button (USER_BTN1) ────►  Toggle Mode                         │
│   └─ Active LOW (กด = 0)                                        │
│   └─ Debounce 50ms                                              │
│                                                                 │
│   MODES:                                                        │
│   ═══════                                                       │
│   MODE_NORMAL:  LED blinks at POT-controlled speed              │
│   MODE_FAST:    LED blinks at 2x speed (delay / 2)              │
│                                                                 │
│   OUTPUT:                                                       │
│   ═══════                                                       │
│   LED (USER_LED1) ────►  Blinks based on calculated delay       │
│   Serial Terminal ────►  Real-time ASCII status bar             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

### Lab 4.1 : Code Implementation

#### Step 1: Macros Configuration

```c
#include "cybsp.h"
#include "retarget_io_init.h"
#include <stdbool.h>

/*******************************************************************************
 * Macros
 ******************************************************************************/
/* System Configuration */
#define CM55_BOOT_WAIT_TIME_USEC    (10U)

/* ADC Configuration */
#define SAR_ADC_INDEX               (0U)
#define SAR_ADC_SEQUENCER           (0U)
#define SAR_ADC_CHANNEL             (0U)
#define SAR_ADC_VREF_MV             (1800U)
#define ADC_READ_INTERVAL_MS        (100U)

/* Button Configuration */
#define USER_BTN_PORT               CYBSP_USER_BTN1_PORT
#define USER_BTN_PIN                CYBSP_USER_BTN1_PIN
#define DEBOUNCE_DELAY_MS           (50U)

/* Button is Active LOW: pressed = 0 */
#define IS_BUTTON_PRESSED()         (Cy_GPIO_Read(USER_BTN_PORT, USER_BTN_PIN) == 0)

/* LED Control Macros (Active LOW on PSoC Edge E84) */
#define LED_ON()                    Cy_GPIO_Clr(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)
#define LED_OFF()                   Cy_GPIO_Set(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)
#define LED_TOGGLE()                Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)

/* LED Blink Speed Limits */
#define BLINK_DELAY_MIN_MS          (50U)
#define BLINK_DELAY_MAX_MS          (1000U)
```

#### Step 2: Mode Definition

```c
/* Mode Definitions */
typedef enum {
    MODE_NORMAL = 0,    // LED blinks at POT-controlled speed
    MODE_FAST   = 1     // LED blinks at 2x speed
} led_mode_t;

/* Global Variables */
static bool adc_initialized = false;
static led_mode_t current_mode = MODE_NORMAL;
static uint32_t mode_change_count = 0;
```

#### Step 3: Helper Functions

**read\_button\_with\_debounce() - Delay-Based Debounce**

> **หมายเหตุ:** PSoC Edge ไม่มี `Cy_SysLib_GetTimerTick()` จึงใช้ Delay-Based Debounce แทน

```c
/*******************************************************************************
* Function Name: read_button_with_debounce
********************************************************************************
* Summary:
*   Reads the user button with software debouncing.
*   Uses delay-based debounce suitable for PSoC Edge.
*
* Return:
*   bool - true if a valid button press was detected
*******************************************************************************/
static bool read_button_with_debounce(void)
{
    static bool last_state = false;

    bool current_state = IS_BUTTON_PRESSED();

    /* Detect rising edge (button just pressed) */
    if (current_state && !last_state)
    {
        /* Wait for debounce period */
        Cy_SysLib_Delay(DEBOUNCE_DELAY_MS);

        /* Re-read to confirm button is still pressed */
        if (IS_BUTTON_PRESSED())
        {
            last_state = true;
            return true;
        }
    }

    /* Update state when button is released */
    if (!current_state)
    {
        last_state = false;
    }

    return false;
}
```

**map\_pot\_to\_delay() - แปลงค่า POT เป็น Delay**

```c
/*******************************************************************************
* Function Name: map_pot_to_delay
********************************************************************************
* Summary:
*   Maps potentiometer percentage (0-100%) to LED blink delay.
*   Inverted mapping: higher pot value = faster blink
*
*   Formula: delay = MAX - (percentage * (MAX - MIN) / 100)
*
*   Examples:
*     0%   → 1000ms (slowest)
*     50%  → 525ms
*     100% → 50ms   (fastest)
*
* Parameters:
*   pot_percentage - Potentiometer reading as percentage (0-100)
*
* Return:
*   uint32_t - Delay in milliseconds (50-1000)
*******************************************************************************/
static uint32_t map_pot_to_delay(uint8_t pot_percentage)
{
    uint32_t delay;

    /* Map 0-100% to 1000-50ms (inverted) */
    delay = BLINK_DELAY_MAX_MS - ((uint32_t)pot_percentage *
            (BLINK_DELAY_MAX_MS - BLINK_DELAY_MIN_MS) / 100);

    /* Ensure minimum delay */
    if (delay < BLINK_DELAY_MIN_MS)
    {
        delay = BLINK_DELAY_MIN_MS;
    }

    return delay;
}
```

**print\_status\_bar() - ASCII Status Bar**

```c
/*******************************************************************************
* Function Name: print_status_bar
********************************************************************************
* Summary:
*   Prints an ASCII status bar showing potentiometer percentage,
*   current delay, and operating mode.
*******************************************************************************/
static void print_status_bar(uint8_t percentage, uint32_t delay_ms, led_mode_t mode)
{
    int i;
    int bar_length = percentage / 5;  /* 0-20 characters */

    printf("\r[");

    for (i = 0; i < 20; i++)
    {
        if (i < bar_length)
        {
            printf("#");
        }
        else
        {
            printf("-");
        }
    }

    printf("] %3d%% | %4lums | %s     ",
           percentage,
           (unsigned long)delay_ms,
           (mode == MODE_FAST) ? "FAST" : "NORMAL");

    fflush(stdout);
}
```

#### Step 4: Main Function (Non-Blocking Design)

```c
/*******************************************************************************
* Main Function
*******************************************************************************/
int main(void)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    int16_t voltage_mv;
    uint8_t percentage;
    uint32_t base_delay;
    uint32_t actual_delay;
    uint32_t elapsed_time = 0;
    uint32_t last_toggle_time = 0;
    uint32_t last_adc_time = 0;

    /* Initialize the device and board peripherals */
    result = cybsp_init();
    if (CY_RSLT_SUCCESS != result) handle_app_error();

    __enable_irq();
    init_retarget_io();

    /* Clear screen */
    printf("\x1b[2J\x1b[;H");
    printf("***********************************************************\r\n");
    printf("        PSOC Edge MCU: Interactive LED Controller          \r\n");
    printf("***********************************************************\r\n\n");

    /* Initialize SAR ADC */
    result = init_adc();
    if (CY_RSLT_SUCCESS != result)
    {
        printf("ADC initialization failed!\r\n");
        handle_app_error();
    }

    /* Print instructions */
    printf("Controls:\r\n");
    printf("  - Potentiometer (P15_1): Adjust LED blink speed\r\n");
    printf("  - Button (USER_BTN1):    Toggle Normal/Fast mode\r\n\n");
    printf("Speed Range: 50ms (fast) to 1000ms (slow)\r\n");
    printf("Fast Mode:   2x speed (half delay)\r\n\n");

    /* Enable CM55 */
    Cy_SysEnableCM55(MXCM55, CY_CM55_APP_BOOT_ADDR, CM55_BOOT_WAIT_TIME_USEC);

    /* Initial ADC read */
    voltage_mv = read_potentiometer_mv();
    percentage = get_pot_percentage(voltage_mv);
    base_delay = map_pot_to_delay(percentage);
    actual_delay = base_delay;

    printf("Starting LED Controller...\r\n\n");

    for(;;)
    {
        /* 1. Check button for mode toggle */
        if (read_button_with_debounce())
        {
            /* Toggle mode */
            current_mode = (current_mode == MODE_NORMAL) ? MODE_FAST : MODE_NORMAL;
            mode_change_count++;

            printf("\n>>> Mode changed to: %s (count: %lu)\r\n\n",
                   (current_mode == MODE_FAST) ? "FAST" : "NORMAL",
                   (unsigned long)mode_change_count);
        }

        /* 2. Read ADC periodically (every 100ms) */
        if ((elapsed_time - last_adc_time) >= ADC_READ_INTERVAL_MS)
        {
            voltage_mv = read_potentiometer_mv();
            percentage = get_pot_percentage(voltage_mv);
            base_delay = map_pot_to_delay(percentage);

            /* 3. Apply mode multiplier */
            if (current_mode == MODE_FAST)
            {
                actual_delay = base_delay / 2;
                if (actual_delay < BLINK_DELAY_MIN_MS / 2)
                {
                    actual_delay = BLINK_DELAY_MIN_MS / 2;
                }
            }
            else
            {
                actual_delay = base_delay;
            }

            /* Print status bar */
            print_status_bar(percentage, actual_delay, current_mode);

            last_adc_time = elapsed_time;
        }

        /* 4. Toggle LED based on calculated delay */
        if ((elapsed_time - last_toggle_time) >= actual_delay)
        {
            LED_TOGGLE();
            last_toggle_time = elapsed_time;
        }

        /* 5. Small delay for loop timing */
        Cy_SysLib_Delay(10);
        elapsed_time += 10;
    }
}
```

***

### 4. Flowchart

```bash
┌─────────────────────────────────────────────────────────────────┐
│              Interactive LED Controller Flowchart               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌──────────────────┐                                          │
│   │      START       │                                          │
│   └────────┬─────────┘                                          │
│            │                                                    │
│            ▼                                                    │
│   ┌──────────────────┐                                          │
│   │  cybsp_init()    │                                          │
│   │  init_adc()      │                                          │
│   │  Enable CM55     │                                          │
│   └────────┬─────────┘                                          │
│            │                                                    │
│            ▼                                                    │
│   ╔══════════════════════════════════════════════════════╗      │
│   ║                    MAIN LOOP                         ║      │
│   ╠══════════════════════════════════════════════════════╣      │
│   ║                                                      ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  1. Check Button (with debounce)            │     ║      │
│   ║  │     If pressed: Toggle MODE                 │     ║      │
│   ║  │     MODE_NORMAL ←→ MODE_FAST                │     ║      │
│   ║  └─────────────────────────────────────────────┘     ║      │
│   ║                        │                             ║      │
│   ║                        ▼                             ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  2. Read ADC (every 100ms)                  │     ║      │
│   ║  │     percentage = get_pot_percentage()       │     ║      │
│   ║  │     base_delay = map_pot_to_delay()         │     ║      │
│   ║  └─────────────────────────────────────────────┘     ║      │
│   ║                        │                             ║      │
│   ║                        ▼                             ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  3. Apply Mode Multiplier                   │     ║      │
│   ║  │     NORMAL: actual_delay = base_delay       │     ║      │
│   ║  │     FAST:   actual_delay = base_delay / 2   │     ║      │
│   ║  └─────────────────────────────────────────────┘     ║      │
│   ║                        │                             ║      │
│   ║                        ▼                             ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  4. Toggle LED (if delay elapsed)           │     ║      │
│   ║  │     LED_TOGGLE()                            │     ║      │
│   ║  └─────────────────────────────────────────────┘     ║      │
│   ║                        │                             ║      │
│   ║                        ▼                             ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  5. Print Status Bar                        │     ║      │
│   ║  │     [####----] 50% | 525ms | NORMAL         │     ║      │
│   ║  └─────────────────────────────────────────────┘     ║      │
│   ║                        │                             ║      │
│   ║                        ▼                             ║      │
│   ║  ┌─────────────────────────────────────────────┐     ║      │
│   ║  │  6. Delay 10ms + elapsed_time += 10         │     ║      │
│   ║  └────────────────────┬────────────────────────┘     ║      │
│   ║                       │                              ║      │
│   ╚═══════════════════════╪══════════════════════════════╝      │
│                           │                                     │
│                           └──────────► (repeat)                 │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

### 5. State Diagram

```bash
┌─────────────────────────────────────────────────────────────────┐
│                     Mode State Machine                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌──────────────────┐       Button Press      ┌──────────────┐ │
│   │                  │ ◄─────────────────────► │              │ │
│   │   MODE_NORMAL    │                         │  MODE_FAST   │ │
│   │    (1x speed)    │                         │  (2x speed)  │ │
│   │                  │                         │              │ │
│   └──────────────────┘                         └──────────────┘ │
│          │                                            │         │
│          │                                            │         │
│          ▼                                            ▼         │
│   LED Delay = POT delay                 LED Delay = POT delay/2 │
│   (50ms - 1000ms)                       (25ms - 500ms)          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

***

### 6. ตัวอย่าง Output

```bash
***********************************************************
        PSOC Edge MCU: Interactive LED Controller
***********************************************************

Controls:
  - Potentiometer (P15_1): Adjust LED blink speed
  - Button (USER_BTN1):    Toggle Normal/Fast mode

Speed Range: 50ms (fast) to 1000ms (slow)
Fast Mode:   2x speed (half delay)

Starting LED Controller...

[--------------------]   0% | 1000ms | NORMAL
[#####---------------]  25% |  762ms | NORMAL
[##########----------]  50% |  525ms | NORMAL

>>> Mode changed to: FAST (count: 1)

[##########----------]  50% |  262ms | FAST
[###############-----]  75% |  143ms | FAST
[####################] 100% |   25ms | FAST

>>> Mode changed to: NORMAL (count: 2)

[####################] 100% |   50ms | NORMAL
```

***

### <mark style="color:blue;">Program Code ทั้งหมด</mark>

```c
/*******************************************************************************
* File Name        : main.c
*
* Description      : GPIO Integration - Interactive LED Controller
*                    Combines Button + LED + ADC (Potentiometer)
*
* Features:
*   - Potentiometer controls LED blink speed (50ms - 1000ms)
*   - Button toggles between Normal and Fast mode (2x speed)
*   - Non-blocking design pattern
*   - Real-time ASCII status bar display
*
*******************************************************************************/

/*******************************************************************************
* Header Files
*******************************************************************************/
#include "cybsp.h"
#include "retarget_io_init.h"
#include <stdbool.h>

/*******************************************************************************
 * Macros
 ******************************************************************************/
/* System Configuration */
#define CM55_BOOT_WAIT_TIME_USEC    (10U)

/* ADC Configuration */
#define SAR_ADC_INDEX               (0U)
#define SAR_ADC_SEQUENCER           (0U)
#define SAR_ADC_CHANNEL             (0U)
#define SAR_ADC_VREF_MV             (1800U)
#define ADC_READ_INTERVAL_MS        (100U)

/* Button Configuration */
#define USER_BTN_PORT               CYBSP_USER_BTN1_PORT
#define USER_BTN_PIN                CYBSP_USER_BTN1_PIN
#define DEBOUNCE_DELAY_MS           (50U)

/* Button is Active LOW: pressed = 0 */
#define IS_BUTTON_PRESSED()         (Cy_GPIO_Read(USER_BTN_PORT, USER_BTN_PIN) == 0)

/* LED Control Macros */
#define LED_ON()                    Cy_GPIO_Clr(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)
#define LED_OFF()                   Cy_GPIO_Set(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)
#define LED_TOGGLE()                Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN)

/* LED Blink Speed Limits */
#define BLINK_DELAY_MIN_MS          (50U)
#define BLINK_DELAY_MAX_MS          (1000U)

/* Mode Definitions */
typedef enum {
    MODE_NORMAL = 0,
    MODE_FAST   = 1
} led_mode_t;

/*******************************************************************************
* Global Variables
*******************************************************************************/
static bool adc_initialized = false;
static led_mode_t current_mode = MODE_NORMAL;
static uint32_t mode_change_count = 0;

/*******************************************************************************
* Function Prototypes
*******************************************************************************/
static cy_rslt_t init_adc(void);
static int16_t read_potentiometer_mv(void);
static uint8_t get_pot_percentage(int16_t voltage_mv);
static bool read_button_with_debounce(void);
static uint32_t map_pot_to_delay(uint8_t pot_percentage);
static void print_status_bar(uint8_t percentage, uint32_t delay_ms, led_mode_t mode);

/*******************************************************************************
* Function Name: init_adc
********************************************************************************
* Summary:
*   Initializes the SAR ADC using autonomous analog control.
*
* Return:
*   cy_rslt_t - CY_RSLT_SUCCESS if initialization successful
*******************************************************************************/
static cy_rslt_t init_adc(void)
{
    cy_rslt_t result;

    result = Cy_AutAnalog_Init(&autonomous_analog_init);

    if (CY_AUTANALOG_SUCCESS != result)
    {
        return result;
    }

    Cy_AutAnalog_SetInterruptMask(CY_AUTANALOG_INT_SAR0_RESULT);
    Cy_AutAnalog_StartAutonomousControl();

    adc_initialized = true;
    return CY_RSLT_SUCCESS;
}

/*******************************************************************************
* Function Name: read_potentiometer_mv
********************************************************************************
* Summary:
*   Reads the potentiometer value from ADC and converts to millivolts.
*
* Return:
*   int16_t - Voltage in millivolts (0-1800 mV)
*******************************************************************************/
static int16_t read_potentiometer_mv(void)
{
    int32_t adc_count;
    int16_t voltage_mv;

    adc_count = Cy_AutAnalog_SAR_ReadResult(SAR_ADC_INDEX,
                                            CY_AUTANALOG_SAR_INPUT_GPIO,
                                            SAR_ADC_CHANNEL);

    voltage_mv = Cy_AutAnalog_SAR_CountsTo_mVolts(SAR_ADC_INDEX,
                                                   false,
                                                   SAR_ADC_SEQUENCER,
                                                   CY_AUTANALOG_SAR_INPUT_GPIO,
                                                   SAR_ADC_CHANNEL,
                                                   SAR_ADC_VREF_MV,
                                                   adc_count);

    return voltage_mv;
}

/*******************************************************************************
* Function Name: get_pot_percentage
********************************************************************************
* Summary:
*   Converts potentiometer voltage to percentage (0-100%).
*
* Parameters:
*   voltage_mv - Input voltage in millivolts
*
* Return:
*   uint8_t - Percentage value (0-100)
*******************************************************************************/
static uint8_t get_pot_percentage(int16_t voltage_mv)
{
    int32_t percentage;

    if (voltage_mv < 0)
    {
        voltage_mv = 0;
    }
    else if (voltage_mv > SAR_ADC_VREF_MV)
    {
        voltage_mv = SAR_ADC_VREF_MV;
    }

    percentage = ((int32_t)voltage_mv * 100) / SAR_ADC_VREF_MV;

    return (uint8_t)percentage;
}

/*******************************************************************************
* Function Name: read_button_with_debounce
********************************************************************************
* Summary:
*   Reads the user button with software debouncing.
*   Uses delay-based debounce suitable for PSoC Edge.
*
* Return:
*   bool - true if a valid button press was detected
*******************************************************************************/
static bool read_button_with_debounce(void)
{
    static bool last_state = false;

    bool current_state = IS_BUTTON_PRESSED();

    /* Detect rising edge (button just pressed) */
    if (current_state && !last_state)
    {
        /* Wait for debounce period */
        Cy_SysLib_Delay(DEBOUNCE_DELAY_MS);

        /* Re-read to confirm button is still pressed */
        if (IS_BUTTON_PRESSED())
        {
            last_state = true;
            return true;
        }
    }

    /* Update state when button is released */
    if (!current_state)
    {
        last_state = false;
    }

    return false;
}

/*******************************************************************************
* Function Name: map_pot_to_delay
********************************************************************************
* Summary:
*   Maps potentiometer percentage (0-100%) to LED blink delay.
*   0% = slowest (1000ms), 100% = fastest (50ms)
*   Inverted mapping: higher pot value = faster blink
*
* Parameters:
*   pot_percentage - Potentiometer reading as percentage (0-100)
*
* Return:
*   uint32_t - Delay in milliseconds (50-1000)
*******************************************************************************/
static uint32_t map_pot_to_delay(uint8_t pot_percentage)
{
    uint32_t delay;

    /* Map 0-100% to 1000-50ms (inverted) */
    /* delay = MAX - (percentage * (MAX - MIN) / 100) */
    delay = BLINK_DELAY_MAX_MS - ((uint32_t)pot_percentage *
            (BLINK_DELAY_MAX_MS - BLINK_DELAY_MIN_MS) / 100);

    /* Ensure minimum delay */
    if (delay < BLINK_DELAY_MIN_MS)
    {
        delay = BLINK_DELAY_MIN_MS;
    }

    return delay;
}

/*******************************************************************************
* Function Name: print_status_bar
********************************************************************************
* Summary:
*   Prints an ASCII status bar showing potentiometer percentage,
*   current delay, and operating mode.
*
* Parameters:
*   percentage - Current pot percentage
*   delay_ms   - Current blink delay in ms
*   mode       - Current operating mode
*******************************************************************************/
static void print_status_bar(uint8_t percentage, uint32_t delay_ms, led_mode_t mode)
{
    int i;
    int bar_length = percentage / 5;  /* 0-20 characters */

    printf("\r[");

    for (i = 0; i < 20; i++)
    {
        if (i < bar_length)
        {
            printf("#");
        }
        else
        {
            printf("-");
        }
    }

    printf("] %3d%% | %4lums | %s     ",
           percentage,
           (unsigned long)delay_ms,
           (mode == MODE_FAST) ? "FAST" : "NORMAL");

    fflush(stdout);
}

/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
*   Main function - GPIO Integration Demo
*
*   Features:
*   - Potentiometer controls LED blink speed (50-1000ms)
*   - Button toggles between Normal and Fast mode
*   - Fast mode doubles the blink speed (halves the delay)
*   - Real-time ASCII status bar display
*
* Return:
*   int
*******************************************************************************/
int main(void)
{
    cy_rslt_t result = CY_RSLT_SUCCESS;
    int16_t voltage_mv;
    uint8_t percentage;
    uint32_t base_delay;
    uint32_t actual_delay;
    uint32_t elapsed_time = 0;
    uint32_t last_toggle_time = 0;
    uint32_t last_adc_time = 0;

    /* Initialize the device and board peripherals */
    result = cybsp_init();

    if (CY_RSLT_SUCCESS != result)
    {
        handle_app_error();
    }

    /* Enable global interrupts */
    __enable_irq();

    /* Initialize retarget-io middleware */
    init_retarget_io();

    /* Clear screen */
    printf("\x1b[2J\x1b[;H");
    printf("***********************************************************\r\n");
    printf("        PSOC Edge MCU: Interactive LED Controller          \r\n");
    printf("***********************************************************\r\n\n");

    /* Initialize SAR ADC */
    result = init_adc();

    if (CY_RSLT_SUCCESS != result)
    {
        printf("ADC initialization failed!\r\n");
        handle_app_error();
    }

    /* Print instructions */
    printf("Controls:\r\n");
    printf("  - Potentiometer (P15_1): Adjust LED blink speed\r\n");
    printf("  - Button (USER_BTN1):    Toggle Normal/Fast mode\r\n\n");
    printf("Speed Range: 50ms (fast) to 1000ms (slow)\r\n");
    printf("Fast Mode:   2x speed (half delay)\r\n\n");

    /* Enable CM55 */
    Cy_SysEnableCM55(MXCM55, CY_CM55_APP_BOOT_ADDR, CM55_BOOT_WAIT_TIME_USEC);

    /* Initial ADC read */
    voltage_mv = read_potentiometer_mv();
    percentage = get_pot_percentage(voltage_mv);
    base_delay = map_pot_to_delay(percentage);
    actual_delay = base_delay;

    printf("Starting LED Controller...\r\n\n");

    for(;;)
    {
        /* Check button for mode toggle */
        if (read_button_with_debounce())
        {
            /* Toggle mode */
            if (current_mode == MODE_NORMAL)
            {
                current_mode = MODE_FAST;
            }
            else
            {
                current_mode = MODE_NORMAL;
            }

            mode_change_count++;

            printf("\n>>> Mode changed to: %s (count: %lu)\r\n\n",
                   (current_mode == MODE_FAST) ? "FAST" : "NORMAL",
                   (unsigned long)mode_change_count);
        }

        /* Read ADC periodically */
        if ((elapsed_time - last_adc_time) >= ADC_READ_INTERVAL_MS)
        {
            voltage_mv = read_potentiometer_mv();
            percentage = get_pot_percentage(voltage_mv);
            base_delay = map_pot_to_delay(percentage);

            /* Apply mode multiplier */
            if (current_mode == MODE_FAST)
            {
                actual_delay = base_delay / 2;
                if (actual_delay < BLINK_DELAY_MIN_MS / 2)
                {
                    actual_delay = BLINK_DELAY_MIN_MS / 2;
                }
            }
            else
            {
                actual_delay = base_delay;
            }

            /* Print status bar */
            print_status_bar(percentage, actual_delay, current_mode);

            last_adc_time = elapsed_time;
        }

        /* Toggle LED based on calculated delay */
        if ((elapsed_time - last_toggle_time) >= actual_delay)
        {
            LED_TOGGLE();
            last_toggle_time = elapsed_time;
        }

        /* Small delay for loop timing */
        Cy_SysLib_Delay(10);
        elapsed_time += 10;
    }
}
/* [] END OF FILE */
```

***

### 7. แบบฝึกหัด

#### Exercise 1: Three Modes (Triple Speed)

{% hint style="info" %}
**Hint**

```c
/* Mode Definitions */
typedef enum {
    MODE_NORMAL = 0,
    MODE_FAST   = 1,
    MODE_ULTRA  = 2
} led_mode_t;

/* In button handler */
if (read_button_with_debounce())
{
    current_mode = (current_mode + 1) % 3;  /* Cycle: 0→1→2→0 */

    const char* mode_names[] = {"NORMAL", "FAST (2x)", "ULTRA (4x)"};
    printf("\n>>> Mode: %s\r\n", mode_names[current_mode]);
}

/* Apply mode multiplier */
uint32_t divider[] = {1, 2, 4};
actual_delay = base_delay / divider[current_mode];
if (actual_delay < 25) {
   actual_delay = 25;
}
```

{% endhint %}

#### Exercise 2: LED Brightness Pattern

{% hint style="info" %}
**Hint**

สร้าง pattern เช่น heartbeat (สั้น-สั้น-ยาว)

```c
/* Heartbeat pattern: short-short-long pause */
static uint8_t beat_phase = 0;
static uint32_t beat_delays[] = {100, 100, 100, 100, 500};  /* 5 phases */

if ((elapsed_time - last_toggle_time) >= beat_delays[beat_phase])
{
    LED_TOGGLE();
    last_toggle_time = elapsed_time;
    beat_phase = (beat_phase + 1) % 5;
}
```

{% endhint %}

***

***
