// Copyright 2025 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

#include <xs1.h>
#include <platform.h>
#include <stdbool.h>
#include <xcore/channel.h>
#include <xcore/hwtimer.h>
#include <xcore/port.h>
#include <xcore/select.h>

#include "led_handler.h"
#include "signalling.h"

#define LED_0_ON    (0x1)
#define LEDS_OFF    (0x0)

// Define the port for the LEDs.
// Initialising p_leds with PORT_LEDS connects it through the XK-EVK-XU316 XN
//   file with PORT_4C on tile[0].
// The datasheet for the XU316-1024-FB265 shows PORT_4C of tile[0] connected
//   through signals X0D14, X0D15, X0D20, and X0D21 to balls D4, D3, F1, and G2.
// The schematic for the XK-EVK-XU316 board shows that these signals connect
//   through a 74AVC4TD245 voltage level shifter to LEDs 0..3.
static port_t p_leds = PORT_LEDS;

void led_handler(chanend c_gpo)
{
    // Prepare the LED port for output
    // For simplicity, this example turns off all four LEDs initially,
    //  and only changes the state of LED 0
    port_enable(p_leds);
    uint32_t current_led_state = LEDS_OFF;
    uint32_t next_led_state    = LEDS_OFF;
    port_out(p_leds, current_led_state);

    led_signal_t led_signal = OFF;

    SELECT_RES(
        CASE_THEN(c_gpo, event_gpo_chanend)
    )
    {
        event_gpo_chanend:
            led_signal = chan_in_word(c_gpo);
            switch (led_signal) {
                case ON:
                    next_led_state = LED_0_ON;
                    break;
                case OFF:
                    next_led_state = LEDS_OFF;
                    break;
                default:
                    next_led_state = LEDS_OFF;
                    break;
            }

            if(next_led_state != current_led_state) {
                port_out(p_leds, next_led_state);
                current_led_state = next_led_state;
            }
            continue; // end of event_gpo_chanend
    } // end of select
}
