// 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 "some_gpo.h"
#include "kws_labels.h"

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

void some_gpo(chanend c_gpo, port p_leds)
{
    // 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);

    // Prepare a timer to sustain the LED output
    hwtimer_t t_sustain = hwtimer_alloc();
    const uint32_t SUSTAIN_DURATION = 85000000; // 850ms in 10ns ticks
    bool sustaining = false;

    kwd_label_indices_t led_signal = UNKNOWN;

    SELECT_RES(
        CASE_THEN(c_gpo, event_gpo_chanend),
        CASE_GUARD_THEN(t_sustain, sustaining, event_sustain_timer_trigger)
    )
    {
        event_gpo_chanend:
            led_signal = chan_in_word(c_gpo);
            if(!sustaining) {
                switch (led_signal) {
                    case LEFT:
                        next_led_state = LED_3_ON;
                        break;
                    case RIGHT:
                        next_led_state = LED_0_ON;
                        break;
                    case UNKNOWN:
                        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;

                    if(next_led_state != LEDS_OFF) {
                        sustaining = true;
                        hwtimer_set_trigger_time(t_sustain, hwtimer_get_time(t_sustain) + SUSTAIN_DURATION);
                    }
                }
            }
            continue; // end of event_gpo_chanend

        event_sustain_timer_trigger:
            hwtimer_clear_trigger_time(t_sustain);
            sustaining = false;
            continue; // end of event_sustain_timer_trigger
    } // end of select
}
