/***************************************************************************
 * Copyright (C) 2026 Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
 * The AI-generated portions may be considered public domain (CC0-1.0)
 * and not subject to the project's licence. The human contributor has
 * reviewed and verified that the code is correct.
 *
 * SPDX-License-Identifier: MIT and CC0-1.0
 **************************************************************************/

#include <stdint.h>

#include "gpio.h"
#include "system_core_v_mcu.h"
#include "tx_api.h"
#include "uart_driver.h"

#define DEMO_STACK_SIZE     1024U
#define DEMO_BYTE_POOL_SIZE 4096U
/*
 * LED[0] on Nexys A7 = IO pad 11 = GPIO/apbio pin 4 (MUX=2).
 * Verified in the quick-start guide and the 2022 nexys-pin-table.csv used to
 * synthesise the pre-built bitfile (io_pad = gpio_pin + 7).
 */
#define DEMO_LED_PIN        4U
#define DEMO_LED_MASK       (1UL << DEMO_LED_PIN)

/* Assemble the version banner string at compile time from tx_api.h constants. */
#define _TX_STR(x)  #x
#define TX_STR(x)   _TX_STR(x)
#define TX_VERSION_STRING \
    "v" TX_STR(THREADX_MAJOR_VERSION) \
    "." TX_STR(THREADX_MINOR_VERSION) \
    "." TX_STR(THREADX_PATCH_VERSION) \
    "." TX_STR(THREADX_BUILD_VERSION)

static const char banner[] =
    "\r\nEclipse ThreadX for OpenHW CORE-V MCU " TX_VERSION_STRING "\r\n"
    "Copyright (c) 2026 Eclipse ThreadX Contributors\r\n\r\n";

static TX_THREAD blinky_thread;
static TX_THREAD uart_thread;
static TX_BYTE_POOL byte_pool;
static uint8_t memory_area[DEMO_BYTE_POOL_SIZE];

static void demo_error_loop(void)
{
    /* MISRA deviation: intentional infinite loop used as a fault sink. */
    for (;;)
    {
    }
}

static void blinky_thread_entry(ULONG arg)
{
    TX_PARAMETER_NOT_USED(arg);

    /* Configure LED[0] as push-pull output (sets pad-mux to FUNC_C = 2). */
    gpio_set_output((uint32_t)DEMO_LED_MASK);

    for (;;)
    {
        gpio_set((uint32_t)DEMO_LED_MASK);
        tx_thread_sleep(100U);              /* 1 s on  (100 ticks × 10 ms) */
        gpio_clear((uint32_t)DEMO_LED_MASK);
        tx_thread_sleep(100U);              /* 1 s off */
    }
}

static void uart_thread_entry(ULONG arg)
{
    TX_PARAMETER_NOT_USED(arg);

    uart_write_str(0U, banner);
    for (;;)
    {
        uart_write_str(0U, ".");
        tx_thread_sleep(100U);
    }
}

void tx_application_define(void *first_unused_memory)
{
    CHAR *stack_ptr = TX_NULL;
    UINT status;

    TX_PARAMETER_NOT_USED(first_unused_memory);

    status = tx_byte_pool_create(&byte_pool, "demo pool", memory_area, DEMO_BYTE_POOL_SIZE);
    if (status != TX_SUCCESS)
    {
        demo_error_loop();
    }

    status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT);
    if (status != TX_SUCCESS)
    {
        demo_error_loop();
    }

    status = tx_thread_create(&blinky_thread, "blinky", blinky_thread_entry, 0U,
                              stack_ptr, DEMO_STACK_SIZE, 1U, 1U,
                              TX_NO_TIME_SLICE, TX_AUTO_START);
    if (status != TX_SUCCESS)
    {
        demo_error_loop();
    }

    status = tx_byte_allocate(&byte_pool, (VOID **)&stack_ptr, DEMO_STACK_SIZE, TX_NO_WAIT);
    if (status != TX_SUCCESS)
    {
        demo_error_loop();
    }

    status = tx_thread_create(&uart_thread, "uart", uart_thread_entry, 0U,
                              stack_ptr, DEMO_STACK_SIZE, 2U, 2U,
                              TX_NO_TIME_SLICE, TX_AUTO_START);
    if (status != TX_SUCCESS)
    {
        demo_error_loop();
    }
}

int main(void)
{
    system_init();
    tx_kernel_enter();
    return 0;
}
