aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/include
diff options
context:
space:
mode:
authorspicyjpeg <thatspicyjpeg@gmail.com>2022-10-21 13:24:54 +0200
committerspicyjpeg <thatspicyjpeg@gmail.com>2022-10-21 13:24:54 +0200
commitb1632d7df0e840692612461a80d0e05d6a3228ed (patch)
tree2f804b26c5befa1ed360db034910c8107b8c3ee6 /libpsn00b/include
parent982df5fe197c4db2be4bffe59a05c837b7508365 (diff)
downloadpsn00bsdk-b1632d7df0e840692612461a80d0e05d6a3228ed.tar.gz
Rewrite psxsio with new API, fix compiler warnings
Diffstat (limited to 'libpsn00b/include')
-rw-r--r--libpsn00b/include/assert.h7
-rw-r--r--libpsn00b/include/psxsio.h258
2 files changed, 211 insertions, 54 deletions
diff --git a/libpsn00b/include/assert.h b/libpsn00b/include/assert.h
index eabe369..e93c983 100644
--- a/libpsn00b/include/assert.h
+++ b/libpsn00b/include/assert.h
@@ -9,6 +9,9 @@
#ifndef __ASSERT_H
#define __ASSERT_H
+void _assert_abort(const char *file, int line, const char *expr);
+void _sdk_log_inner(const char *fmt, ...);
+
#ifdef NDEBUG
#define assert(expr)
@@ -16,12 +19,10 @@
#else
-void _assert_abort(const char *file, int line, const char *expr);
-void _sdk_log_inner(const char *fmt, ...);
-
#define assert(expr) { \
if (!(expr)) _assert_abort(__FILE__, __LINE__, #expr); \
}
+
#ifdef SDK_LIBRARY_NAME
#define _sdk_log(fmt, ...) _sdk_log_inner(SDK_LIBRARY_NAME ": " fmt, ##__VA_ARGS__)
#else
diff --git a/libpsn00b/include/psxsio.h b/libpsn00b/include/psxsio.h
index 3f571d7..e0cc49b 100644
--- a/libpsn00b/include/psxsio.h
+++ b/libpsn00b/include/psxsio.h
@@ -1,64 +1,220 @@
+/*
+ * PSn00bSDK serial port library
+ * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed
+ */
+
#ifndef __PSXSIO_H
#define __PSXSIO_H
-#define SR_TXRDY 0x1
-#define SR_RXRDY 0x2
-#define SR_TXU 0x4
-#define SR_PERROR 0x8
-#define SR_OE 0x10
-#define SR_FE 0x20
-#define SR_DSR 0x80
-#define SR_CTS 0x100
-#define SR_IRQ 0x200
-
-#define SIO_TXRDY 0x1
-#define SIO_RXRDY 0x2
-#define SIO_TXU 0x4
-#define SIO_PERROR 0x8
-#define SIO_OE 0x10
-#define SIO_FE 0x20
-#define SIO_DSR 0x80
-#define SIO_CTS 0x100
-#define SIO_IRQ 0x200
-
-#define MR_CHLEN_5 0x00
-#define MR_CHLEN_6 0x04
-#define MR_CHLEN_7 0x08
-#define MR_CHLEN_8 0x0C
-#define MR_PEN 0x10
-#define MR_P_EVEN 0x30
-#define MR_SB_01 0x40
-#define MR_SB_10 0x80
-#define MR_SB_11 0xc0
-
-#define CR_TXEN 0x1
-#define CR_DTR 0x2
-#define CR_RXEN 0x4
-#define CR_BRK 0x8
-#define CR_INTRST 0x10
-#define CR_RTS 0x20
-#define CR_ERRRST 0x40
-#define CR_BUFSZ_1 0x00
-#define CR_BUFSZ_2 0x100
-#define CR_BUFSZ_4 0x200
-#define CR_BUFSZ_8 0x300
-#define CR_TXIEN 0x400
-#define CR_RXIEN 0x800
-#define CR_DSRIEN 0x1000
+#include <stdint.h>
+
+/* Register definitions (used internally) */
+
+typedef enum _SIO_StatusRegFlag {
+ SR_TXRDY = 1 << 0,
+ SR_RXRDY = 1 << 1,
+ SR_TXU = 1 << 2,
+ SR_PERROR = 1 << 3,
+ SR_OE = 1 << 4,
+ SR_FE = 1 << 5,
+ SR_DSR = 1 << 7,
+ SR_CTS = 1 << 8,
+ SR_IRQ = 1 << 9
+} SIO_StatusRegFlag;
+
+typedef enum _SIO_ModeRegFlag {
+ MR_BR_1 = 1 << 0,
+ MR_BR_16 = 2 << 0,
+ MR_BR_64 = 3 << 0,
+ MR_CHLEN_5 = 0 << 2,
+ MR_CHLEN_6 = 1 << 2,
+ MR_CHLEN_7 = 2 << 2,
+ MR_CHLEN_8 = 3 << 2,
+ MR_PEN = 1 << 4,
+ MR_P_EVEN = 1 << 5,
+ MR_SB_01 = 1 << 6,
+ MR_SB_10 = 2 << 6,
+ MR_SB_11 = 3 << 6
+} SIO_ModeRegFlag;
+
+typedef enum _SIO_ControlRegFlag {
+ CR_TXEN = 1 << 0,
+ CR_DTR = 1 << 1,
+ CR_RXEN = 1 << 2,
+ CR_BRK = 1 << 3,
+ CR_INTRST = 1 << 4,
+ CR_RTS = 1 << 5,
+ CR_ERRRST = 1 << 6,
+ CR_BUFSZ_1 = 0 << 8,
+ CR_BUFSZ_2 = 1 << 8,
+ CR_BUFSZ_4 = 2 << 8,
+ CR_BUFSZ_8 = 3 << 8,
+ CR_TXIEN = 1 << 10,
+ CR_RXIEN = 1 << 11,
+ CR_DSRIEN = 1 << 12
+} SIO_ControlRegFlag;
+
+typedef enum _SIO_FlowControl {
+ SIO_FC_NONE = 0,
+ SIO_FC_RTS_CTS = 1
+ //SIO_FC_DTR_DSR = 2
+} SIO_FlowControl;
+
+/* Public API */
#ifdef __cplusplus
extern "C" {
#endif
-int _sio_control(int cmd, int arg, int param);
-void AddSIO(int baud);
-void DelSIO(void);
+/**
+ * @brief Resets the serial port, initializes the library's internal ring
+ * buffers and installs a serial IRQ handler. The given mode value (normally
+ * MR_CHLEN_8|MR_SB_01 for 8 data bits, 1 stop bit and no parity) is copied to
+ * the SIO_MODE register. Flow control is disabled by default (see
+ * SIO_SetFlowControl() for more details).
+ *
+ * This function must be called prior to using SIO_ReadByte(), SIO_ReadSync(),
+ * SIO_WriteByte(), SIO_WriteSync() or SIO_SetFlowControl(), and must not be
+ * called from an IRQ callback.
+ *
+ * @param baud Baud rate in bits per second
+ * @param mode Binary OR of SIO_ModeRegFlag enum members
+ */
+void SIO_Init(int baud, uint16_t mode);
+
+/**
+ * @brief Resets the serial port and removes the IRQ callback added by
+ * SIO_Init(), restoring any previously installed handler.
+ */
+void SIO_Quit(void);
-void *Sio1Callback(void (*func)(void));
+/**
+ * @brief Changes the serial port's flow control mode. The following modes are
+ * available:
+ *
+ * - SIO_FC_NONE (default): do not assert RTS or DTR automatically and ignore
+ * DSR. Note that the hardware will still wait for CTS to be asserted before
+ * sending any data; there is no way to disable this behavior.
+ * - SIO_FC_RTS_CTS: assert RTS when the RX buffer is full and wait for CTS to
+ * be asserted before sending any data.
+ *
+ * The flow control mode shall only be changed while the TX and RX buffers are
+ * empty.
+ *
+ * @param mode
+ */
+void SIO_SetFlowControl(SIO_FlowControl mode);
-// ORIGINAL
-void WaitSIO(void);
-int kbhit();
+/**
+ * @brief Reads a byte from the RX buffer. If the buffer is empty, blocks
+ * indefinitely until a byte is received.
+ *
+ * WARNING: this function shall not be used in a critical section or IRQ
+ * callback as no data is sent or received while interrupts are disabled. It
+ * also lacks a timeout, so consider polling for new data using SIO_ReadByte2()
+ * or SIO_ReadSync(1) and implementing a timeout instead.
+ *
+ * @return Received byte
+ */
+int SIO_ReadByte(void);
+
+/**
+ * @brief Non-blocking variant of SIO_ReadByte(). Reads a byte from the RX
+ * buffer or returns -1 if the buffer is empty. Unlike SIO_ReadByte() this
+ * function is safe to use in a critical section (although no data will be
+ * received while interrupts are disabled).
+ *
+ * @return Received byte, -1 if no data is available
+ */
+int SIO_ReadByte2(void);
+
+/**
+ * @brief Waits for at least one byte to be available in the RX buffer (if
+ * mode = 0) or returns the length of the RX buffer (if mode = 1).
+ *
+ * WARNING: this function shall not be used in a critical section or IRQ
+ * callback as no data is sent or received while interrupts are disabled. Using
+ * SIO_ReadSync(0) is additionally discouraged as it lacks a timeout; consider
+ * polling for new data using SIO_ReadByte2() or SIO_ReadSync(1) and
+ * implementing a timeout instead.
+ *
+ * @param mode
+ * @return Number of RX bytes in the buffer
+ */
+int SIO_ReadSync(int mode);
+
+/**
+ * @brief Registers a function to be called whenever a byte is received. The
+ * received byte is appended to the RX buffer and passed as an argument to the
+ * callback. The callback will run in the exception handler's context, so it
+ * should be as fast as possible and not use any function that relies on
+ * interrupts in order to work.
+ *
+ * @param func
+ * @return Previously set callback or NULL
+ */
+void *SIO_ReadCallback(void (*func)(uint8_t));
+
+/**
+ * @brief Sends the given byte, or appends it to the TX buffer if the serial
+ * port is busy. If the buffer is full, blocks until the byte can be stored in
+ * the buffer (with a timeout).
+ *
+ * WARNING: this function shall not be used in a critical section or IRQ
+ * callback as no data is sent or received while interrupts are disabled.
+ *
+ * @param value
+ * @return Number of TX bytes previously pending, -1 in case of a timeout
+ */
+int SIO_WriteByte(uint8_t value);
+
+/**
+ * @brief Non-blocking variant of SIO_WriteByte(). Sends the given byte, or
+ * appends it to the TX buffer if the serial port is busy. If the buffer is
+ * full, returns -1 without actually sending the byte. Unlike SIO_WriteByte()
+ * this function is safe to use in a critical section (although no data will be
+ * sent while interrupts are disabled).
+ *
+ * @param value
+ * @return Number of TX bytes previously pending, -1 in case of failure
+ */
+int SIO_WriteByte2(uint8_t value);
+
+/**
+ * @brief Waits for all bytes pending in the TX buffer to be sent (if mode = 0)
+ * or returns the length of the TX buffer (if mode = 1).
+ *
+ * WARNING: this function shall not be used in a critical section or IRQ
+ * callback as no data is sent or received while interrupts are disabled.
+ *
+ * @param mode
+ * @return Number of TX bytes pending, -1 in case of a timeout (mode = 0)
+ */
+int SIO_WriteSync(int mode);
+
+/**
+ * @brief Installs a BIOS file driver to redirect TTY stdin/stdout (including
+ * BIOS messages as well as PSn00bSDK's own debug logging) to the serial port.
+ * Uses SIO_Init() internally. The port is configured for 8 data bits, 1 stop
+ * bit and no parity.
+ *
+ * This function shall only be used for debugging purposes. Picking a high baud
+ * rate is recommended as all TTY writes are blocking and bypass the TX buffer.
+ *
+ * NOTE: some executable loaders, such as Unirom and Caetla, already replace
+ * the BIOS TTY driver with a custom one. Calling AddSIO() will break the
+ * built-in TTY functionality of these loaders.
+ *
+ * @param baud Baud rate in bits per second
+ */
+void AddSIO(int baud);
+
+/**
+ * @brief Uninstalls the BIOS driver installed by AddSIO() and attempts to
+ * restore a "dummy" TTY driver. Calling this function is not recommended as
+ * any further TTY usage may crash the system.
+ */
+void DelSIO(void);
#ifdef __cplusplus
}