#define  INCLUDE_FROM_MINIMAL_C
#include "Minimal.h"
#include "guitar_tuner.h"
#include <util/delay.h>
#include <string.h>
#include <stdbool.h>

volatile bool note_ready = false;
char usb_note[8];  // buffer for USB

int main(void)
{
    SetupHardware();
    GlobalInterruptEnable();

    init_guitar_tuner();
    char note[8] = {0}; // main note buffer

    for (;;)
    {
        // Always poll USB stack
        USB_USBTask();

        // Fill note buffer if button pressed
        loop_guitar_tuner(note);

        // Only send if note is valid
        if (note[0] != '\0')
        {
            // Turn LED on while sending
            turn_led2_on();

            // Non-blocking send
            USB_Manage_In(note);

            turn_led2_off();

            // Reset note for next cycle
            note[0] = '\0';
        }
    }
}

/** Non-blocking USB IN write */
void USB_Manage_In(char* note)
{
    Endpoint_SelectEndpoint(IN_EPADDR);

    if (Endpoint_IsINReady())
    {
        Endpoint_Write_Stream_LE(note, strlen(note), NULL);
        Endpoint_ClearIN();
    }
}


/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
#if (ARCH == ARCH_AVR8)
	/* Disable watchdog if enabled by bootloader/fuses */
	MCUSR &= ~(1 << WDRF);
	wdt_disable();

	/* Disable clock division */
	clock_prescale_set(clock_div_1);
#elif (ARCH == ARCH_XMEGA)
	/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
	XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
	XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);

	/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
	XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
	XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);

	PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
#endif

	/* Hardware Initialization */
	USB_Init();
}

/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
}

/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
 *  the status LEDs.
 */
void EVENT_USB_Device_Disconnect(void)
{
}

/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
 *  of the USB device after enumeration - the device endpoints are configured.
 */
void EVENT_USB_Device_ConfigurationChanged(void)
{
    bool endpointConfigured = Endpoint_ConfigureEndpoint(IN_EPADDR, EP_TYPE_BULK, IN_EPSIZE, 1);
    if (!endpointConfigured) {
        // Handle configuration failure, e.g., by returning or logging
        return;
    }}

/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
 *  the device from the USB host before passing along unhandled control requests to the library for processing
 *  internally.
 */
void EVENT_USB_Device_ControlRequest(void)
{
}