summaryrefslogtreecommitdiff
path: root/src/Serial.c
blob: 10bb90f0113633b8bd0daaf4480677e2b6fbae10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "Serial.h"
#include "Interrupts.h"
#include <psxsio.h>
#include <stdarg.h>
#include <stdio.h>
#include <psxbios.h>
#include <psx.h>
#include <stddef.h>
#include "reception.h"

fifo rx;

static void sio_handler_callback(void)
{
    while (SIOCheckInBuffer())
    {
        const unsigned char in = SIOReadByte();
        size_t aux = rx.pending;

        if (++aux >= sizeof rx.buf / sizeof *rx.buf)
            aux = 0;

        if (aux != rx.processed)
        {
            rx.buf[aux] = in;
            rx.pending = aux;
            reception_ev();
        }
        else
        {
            printf("fifo full\n");
            rx.full = true;
        }
    }

    SIOAcknowledgeInterrupt();
}

void SerialInit(void)
{
    enum
    {
        SPEC_COUNTER_BECOMES_ZERO = 0x0001,
        SPEC_INTERRUPTED = 0x0002,
        SPEC_EOF = 0x0004,
        SPEC_FILE_WAS_CLOSED = 0x0008,
        SPEC_CMD_ACK = 0x0010,
        SPEC_CMD_COMPLETED = 0x0020,
        SPEC_DATA_READY = 0x0040,
        SPEC_DATA_END = 0x0080,
        SPEC_TIMEOUT = 0x0100,
        SPEC_UNKNOWN_CMD = 0x0200,
        SPEC_END_READ_BUFFER = 0x0400,
        SPEC_END_WRITE_BUFFER = 0x0800,
        SPEC_GENERAL_INTERRUPT = 0x1000,
        SPEC_NEW_DEVICE = 0x2000,
        SPEC_SYS_CALL_INSTR = 0x4000,
        SPEC_ERROR = 0x8000,
        SPEC_PREV_WRITE_ERROR = 0x8001,
        SPEC_DOMAIN_ERROR_LIBMATH = 0x0301,
        SPEC_RANGE_ERROR_LIBMATH = 0x0302
    };

    enum
    {
        SIO_CLASS = 0xF000000B,
        TRIGGER_CALLBACK = 0x1000,
        BAUD_RATE = 115200
    };

    const int not_crit = EnterCriticalSection();

    EnterCriticalSection();

    SIOReset();
    SIOStart(BAUD_RATE);

    IMASK |= 1 << INT_SIO;

    void sio_handler(void);
    const int sio_handle = OpenEvent(SIO_CLASS, SPEC_GENERAL_INTERRUPT, TRIGGER_CALLBACK, sio_handler_callback);

    if (sio_handle != -1)
        EnableEvent(sio_handle);

    SIOEnableRXInterrupt();

    if (not_crit)
        ExitCriticalSection();
}

void SerialWrite(const unsigned char byte)
{
    SIOSendByte(byte);
}