// PB0–PB3: LEDs
// PB4: Button 1 > Engine (PB6)
// PB5: Button 2 > Steam (PB7)
// PB6: Engine
// PB7: Steam

#ifndef MCU_H
#define MCU_H

#define DDR_OUTPUT_MASK 0xCF
#define true 1
#define false 0

#include <stdint.h>
#include <stdio.h>

typedef uint8_t REG8;

typedef struct {
    REG8 DDR;
    REG8 PORT;
    REG8 PIN;
} GPIO_Port;

GPIO_Port PORTB;

static inline void show_board()
{
    printf("LEDs: ");
    for (int i = 0; i < 4; i++) {
        if (PORTB.DDR & (1 << i))
            printf("%s ", (PORTB.PORT & (1 << i)) ? "●" : "○");
        else
            printf("- ");
    }
    printf(" | Button: ");
    for (int i = 4; i < 6; i++) {
        if (!(PORTB.DDR & (1 << i)))
            printf("%s ", (PORTB.PIN & (1 << i)) ? "●" : "○");
        else
            printf("- ");
    }
    printf(" | Engine: %s",
           (PORTB.
            DDR & (1 << 6)) ? ((PORTB.PORT & (1 << 6)) ? "[@]" : "[ ]") : "-");
    printf(" | Steam: %s",
           (PORTB.
            DDR & (1 << 7)) ? ((PORTB.PORT & (1 << 7)) ? "[~]" : "[ ]") : "-");

    printf("\r");
    fflush(stdout);
}

static inline void init_board(int mode)
{
    if (mode == 0) {
        PORTB.DDR = 0x00;
        PORTB.PORT = 0x00;
        PORTB.PIN = 0x00;
    } else if (mode == 1) {
        PORTB.DDR = 0xCF;
        PORTB.PORT = 0x00;
        PORTB.PIN = 0x00;
    }
}

static inline void set_button(int pin, int state)
{
    if (!(PORTB.DDR & (1 << pin))) {
        if (state)
            PORTB.PIN |= (1 << pin);
        else
            PORTB.PIN &= ~(1 << pin);

        if (pin == 4) {
            if (state)
                PORTB.PORT |= (1 << 6);
            else
                PORTB.PORT &= ~(1 << 6);
        }

        if (pin == 5) {
            if (state)
                PORTB.PORT |= (1 << 7);
            else
                PORTB.PORT &= ~(1 << 7);
        }
    }
}

static inline void set_led(int index, int state)
{
    if (index >= 0 && index <= 3 && (PORTB.DDR & (1 << index))) {
        if (state)
            PORTB.PORT |= (1 << index);
        else
            PORTB.PORT &= ~(1 << index);
    }
}

static inline void debug_registers()
{
    printf("\nDDR:  0x%02X\n", PORTB.DDR);
    printf("PORT: 0x%02X\n", PORTB.PORT);
    printf("PIN:  0x%02X\n", PORTB.PIN);
}

#endif
