From 6503a4b99c24b7b7a89252326f36edadc17f9948 Mon Sep 17 00:00:00 2001 From: Zeal8bit Date: Sat, 18 Nov 2023 10:24:48 +0800 Subject: [PATCH] serial: define an interface for user programs The interface is implemented on the Zeal 8-bit computer. It mainly allows changing the mode attribute, to switch to RAW mode (no LR -> CRLF conversion) --- kernel_headers/sdcc/include/zos_serial.h | 44 ++++++++++++++++++ kernel_headers/z88dk-z80asm/zos_serial.asm | 53 +++++++++++++++++++++ target/zeal8bit/include/uart_h.asm | 28 ++++++++--- target/zeal8bit/uart.asm | 54 ++++++++++++++++++---- 4 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 kernel_headers/sdcc/include/zos_serial.h create mode 100644 kernel_headers/z88dk-z80asm/zos_serial.asm diff --git a/kernel_headers/sdcc/include/zos_serial.h b/kernel_headers/sdcc/include/zos_serial.h new file mode 100644 index 0000000..23cdaa2 --- /dev/null +++ b/kernel_headers/sdcc/include/zos_serial.h @@ -0,0 +1,44 @@ +/* SPDX-FileCopyrightText: 2023 Zeal 8-bit Computer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * This file represents the Serial interface. + * THIS INTERFACE IS SUBJECT TO CHANGE. + */ + + +/** + * IOCTL commands for the serial device. + */ +typedef enum { + SERIAL_CMD_GET_ATTR = 0x80, + SERIAL_CMD_SET_ATTR, + + SERIAL_CMD_GET_BAUDRATE, + SERIAL_CMD_SET_BAUDRATE, + + SERIAL_GET_TIMEOUT, + SERIAL_SET_TIMEOUT, + + SERIAL_GET_BLOCKING, + SERIAL_SET_BLOCKING, + + SERIAL_CMD_LAST +} ser_cmd_t; + + +/** + * Attributes bitmap to use with SERIAL_CMD_GET_ATTR/SERIAL_CMD_SET_ATTR commands + */ +#define SERIAL_ATTR_MODE_RAW (1 << 0) +#define SERIAL_ATTR_RSVD1 (1 << 1) +#define SERIAL_ATTR_RSVD2 (1 << 2) +#define SERIAL_ATTR_RSVD3 (1 << 3) +#define SERIAL_ATTR_RSVD4 (1 << 4) +#define SERIAL_ATTR_RSVD5 (1 << 5) +#define SERIAL_ATTR_RSVD6 (1 << 6) +#define SERIAL_ATTR_RSVD7 (1 << 7) diff --git a/kernel_headers/z88dk-z80asm/zos_serial.asm b/kernel_headers/z88dk-z80asm/zos_serial.asm new file mode 100644 index 0000000..a281111 --- /dev/null +++ b/kernel_headers/z88dk-z80asm/zos_serial.asm @@ -0,0 +1,53 @@ + +; SPDX-FileCopyrightText: 2023 Zeal 8-bit Computer +; +; SPDX-License-Identifier: Apache-2.0 + + IFNDEF ZOS_SERIAL_H + DEFINE ZOS_SERIAL_H + + ; This file represents the minimal interface for a serial driver. + ; If any command below is not supported, the driver should return + ; ERR_NOT_SUPPORTED. + + ; IOCTL commands the driver should implement + DEFGROUP { + ; Get the serial driver attributes. + ; Parameter: + ; DE - Address to fill with the 16-bit attribute + SERIAL_CMD_GET_ATTR = 0x80, ; See attribute group below + + ; Set the serial driver attributes. + ; Parameter: + ; DE - 16-bit attributes to set (NOT AN ADDRESS/POINTER) + SERIAL_CMD_SET_ATTR, + + + SERIAL_CMD_GET_BAUDRATE, + SERIAL_CMD_SET_BAUDRATE, + + + SERIAL_GET_TIMEOUT, + SERIAL_SET_TIMEOUT, + + + SERIAL_GET_BLOCKING, + SERIAL_SET_BLOCKING, + + ; Number of commands above + SERIAL_CMD_COUNT + } + + ; Serial driver attribute bitmap to use with SERIAL_CMD_GET_ATTR command + DEFGROUP { + SERIAL_ATTR_MODE_RAW = 1 << 0, + SERIAL_ATTR_RSVD1 = 1 << 1, + SERIAL_ATTR_RSVD2 = 1 << 2, + SERIAL_ATTR_RSVD3 = 1 << 3, + SERIAL_ATTR_RSVD4 = 1 << 4, + SERIAL_ATTR_RSVD5 = 1 << 5, + SERIAL_ATTR_RSVD6 = 1 << 6, + SERIAL_ATTR_RSVD7 = 1 << 7 + } + + ENDIF ; ZOS_SERIAL_H \ No newline at end of file diff --git a/target/zeal8bit/include/uart_h.asm b/target/zeal8bit/include/uart_h.asm index 5b95913..d63fdaa 100644 --- a/target/zeal8bit/include/uart_h.asm +++ b/target/zeal8bit/include/uart_h.asm @@ -5,16 +5,34 @@ IFNDEF UART_H DEFINE UART_H - INCLUDE "drivers/video_text_h.asm" - - ; UART commands + ; UART commands, start at 0x80 to allow drivers to also handle the video commands (when UART is STDOUT) DEFGROUP { - UART_SET_BAUDRATE = CMD_COUNT, + ; The attributes bits are defines below + UART_CMD_GET_ATTR = 0x80, + UART_CMD_SET_ATTR, + + ; The values for the baudrates are defined below + UART_CMD_GET_BAUDRATE, + UART_CMD_SET_BAUDRATE, + + UART_GET_TIMEOUT, UART_SET_TIMEOUT, + + UART_GET_BLOCKING, UART_SET_BLOCKING, + UART_CMD_LAST } + ; UART attributes + DEFC UART_ATTR_MODE_RAW = 1 << 0 + DEFC UART_ATTR_RSVD1 = 1 << 1 + DEFC UART_ATTR_RSVD2 = 1 << 2 + DEFC UART_ATTR_RSVD3 = 1 << 3 + DEFC UART_ATTR_RSVD4 = 1 << 4 + DEFC UART_ATTR_RSVD5 = 1 << 5 + DEFC UART_ATTR_RSVD6 = 1 << 6 + DEFC UART_ATTR_RSVD7 = 1 << 7 ; Baudrates for receiving bytes from the UART DEFC UART_BAUDRATE_57600 = 0 @@ -22,9 +40,7 @@ DEFC UART_BAUDRATE_19200 = 4 DEFC UART_BAUDRATE_9600 = 10 - ; Default baudrate for UART DEFC UART_BAUDRATE_DEFAULT = UART_BAUDRATE_57600 - ENDIF ; UART_H diff --git a/target/zeal8bit/uart.asm b/target/zeal8bit/uart.asm index 50e6a61..bce8e30 100644 --- a/target/zeal8bit/uart.asm +++ b/target/zeal8bit/uart.asm @@ -9,6 +9,7 @@ INCLUDE "uart_h.asm" INCLUDE "interrupt_h.asm" INCLUDE "utils_h.asm" + INCLUDE "drivers/video_text_h.asm" EXTERN zos_sys_remap_de_page_2 @@ -40,9 +41,9 @@ uart_init: call pio_init - ; Configure the UART to convert LF to CRLF when sending bytes - ld a, 1 - ld (_uart_convert_lf), a + ; Configure the UART to convert LF to CRLF when sending bytes (not RAW) + xor a + ld (_uart_raw), a ; Initialize the escape sequence ld hl, ('[' << 8) | 0x1b @@ -71,6 +72,9 @@ uart_init: call zos_log_warning ENDIF + ELSE + ld a, 1 + ld (_uart_raw), a ENDIF ; CONFIG_TARGET_STDOUT_UART ; Currently, the driver doesn't need to do anything special for open, close or de-init @@ -121,7 +125,11 @@ _no_mmu_msg: DEFM "no-MMU Kernel build\n", 0 uart_ioctl: ; Check that the command number is correct ld a, c - cp UART_SET_BAUDRATE + cp UART_CMD_GET_ATTR + jr z, _uart_ioctl_get_attr + cp UART_CMD_SET_ATTR + jr z, _uart_ioctl_set_attr + cp UART_CMD_SET_BAUDRATE jr z, _uart_ioctl_set_baud IF CONFIG_TARGET_STDOUT_UART @@ -130,7 +138,7 @@ uart_ioctl: cp CMD_SET_COLORS jr z, _uart_ioctl_set_colors cp CMD_SET_CURSOR_XY - jr z, _uart_ioctl_set_cursor + jp z, _uart_ioctl_set_cursor cp CMD_CLEAR_SCREEN jp z, _uart_clear_screen ENDIF ; CONFIG_TARGET_STDOUT_UART @@ -138,6 +146,32 @@ uart_ioctl: _uart_ioctl_not_supported: ld a, ERR_NOT_SUPPORTED ret + + ; Return the current attributes (currently only a single one) in the given buffer +_uart_ioctl_get_attr: + IF CONFIG_KERNEL_TARGET_HAS_MMU + ; Remap DE to page 2 if it was in page 3 + call zos_sys_remap_de_page_2 + ENDIF + ; Single bit at the moment: RAW/not-RAW. In other words, do we re-interpret LF to CRLF? + ld a, (_uart_raw) + ld (de), a + ; Ignore higher bits for now, return success + xor a + ret + + + ; Set the UART attributes, consider DE as the VALUE, not a pointer +_uart_ioctl_set_attr: + ; Only consider the first bit of attributes (RAW mode) + ld a, e + and 1 + ld (_uart_raw), a + ; Return success + xor a + ret + + _uart_ioctl_set_baud: ; Command is correct, check that the parameter is correct ld a, e @@ -159,7 +193,6 @@ _uart_ioctl_valid: _uart_ioctl_get_area: IF CONFIG_KERNEL_TARGET_HAS_MMU - ; Remap DE to page 2 if it was in page 3 call zos_sys_remap_de_page_2 ENDIF ; Let's say that the text area is 80x40 @@ -397,10 +430,10 @@ uart_send_byte: cp '\n' jr nz, _uart_send_byte_raw ; Check if we have to convert LF to CRLF - ld a, (_uart_convert_lf) + ld a, (_uart_raw) or a ld a, '\n' - jr z, _uart_send_byte_raw + jr nz, _uart_send_byte_raw ld a, '\r' call _uart_send_byte_raw ld a, '\n' @@ -721,8 +754,9 @@ _stdout_save_restore_position: SECTION DRIVER_BSS _uart_baudrate: DEFS 1 - ; When set to 1, LF will be convert to CRLF when sending bytes -_uart_convert_lf: DEFS 1 + ; When set to 1, bytes will be sent as-is to through UART. When set to 0, + ; LF will NOT be convert to CRLF when sending bytes +_uart_raw: DEFS 1 _uart_esc_seq: DEFS 10 _uart_esc_seq_end: