/*
 * wnix, a Unix-like operating system for WebAssembly applications.
 * Copyright (C) 2025  Xavier Del Campo Romero
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef DRV_PS1_SIO_REGS_H
#define DRV_PS1_SIO_REGS_H

#include <stdint.h>

struct sio_tx_data
{
    uint32_t value :8, :24;
};

struct sio_rx_data
{
    uint8_t values[4];
};

union sio_stat
{
    struct
    {
        uint32_t
            tx_ready_started :1,
            rx_fifo_not_empty :1,
            tx_ready_finished :1,
            rx_parity_error :1,
            rx_fifo_overrun :1,
            rx_bad_stp :1,
            rx_inverted :1,
            dsr :1,
            cts :1,
            irqreq :1,
            :1,
            baudrate :15, :6;
    } bits;

    uint32_t mask;
};

union sio_mode
{
    struct
    {
        uint16_t
            baudrate_mul :2,
            len :2,
            parity_en :1,
            parity_odd :1,
            stplen :2,
            :8;
    } bits;

    uint16_t mask;
};

union sio_ctrl
{
    struct
    {
        uint16_t
            tx_en :1,
            dtr :1,
            rx_en :1,
            tx_invert :1,
            ack :1,
            rts :1,
            reset :1,
            :1,
            rx_int_mode :2,
            tx_int_en :1,
            rx_int_en :1,
            dsr_int_en :1,
            :3;
    } bits;

    uint16_t mask;
};

enum
{
    SIO_CTRL_RX_INT_1,
    SIO_CTRL_RX_INT_2,
    SIO_CTRL_RX_INT_3,
    SIO_CTRL_RX_INT_4
};

enum
{
    SIO_MODE_FACTOR_STOP,
    SIO_MODE_FACTOR_MUL1,
    SIO_MODE_FACTOR_MUL16,
    SIO_MODE_FACTOR_MUL64
};

enum
{
    SIO_MODE_LEN_5,
    SIO_MODE_LEN_6,
    SIO_MODE_LEN_7,
    SIO_MODE_LEN_8
};

enum
{
    SIO_MODE_STP_RESERVED,
    SIO_MODE_STP_1,
    SIO_MODE_STP_1_5,
    SIO_MODE_STP_2,
};

#define SIO_BASE 0x1f801050
#define SIO_REG(n) (SIO_BASE + n)
#define SIO_TX_DATA ((volatile struct sio_tx_data *)SIO_REG(0))
#define SIO_RX_DATA ((const volatile struct sio_rx_data *)SIO_REG(0))
#define SIO_STAT ((const volatile union sio_stat *)SIO_REG(4))
#define SIO_MODE ((volatile union sio_mode *)SIO_REG(8))
#define SIO_CTRL ((volatile union sio_ctrl *)SIO_REG(10))
#define SIO_BAUD (*(volatile uint16_t *)SIO_REG(14))

#endif
