Enable input on the serial port

This commit is contained in:
jn 2023-02-01 20:12:21 +01:00
parent e6af577da5
commit 727dc8e0d2
6 changed files with 77 additions and 4 deletions

View File

@ -13,7 +13,8 @@ CFILES = src/main.c \
src/keyboard.c \
src/mmu.c \
src/mouse.c \
src/screen.c
src/screen.c \
src/serial.c
FOX32ROM_IN = fox32.rom
FOX32ROM_OUT = fox32rom.h

View File

@ -28,6 +28,9 @@ Writing to this register outputs the lowest 8 bits as a byte on the debug
serial port (stdout in case of the fox32 emulator). If necessary, the CPU is
stalled long enough to ensure that the byte is output rather than discarded.
Reading from this register gets a byte of input from the serial port, if
available, or zero otherwise.
## 0x80000000: Display

View File

@ -16,6 +16,7 @@
#include "framebuffer.h"
#include "keyboard.h"
#include "mouse.h"
#include "serial.h"
bool bus_requests_exit = false;
@ -29,6 +30,11 @@ extern mouse_t mouse;
int bus_io_read(void *user, uint32_t *value, uint32_t port) {
(void) user;
switch (port) {
case 0x00000000: { // serial port
*value = serial_get();
break;
};
case 0x80000000 ... 0x8000031F: { // overlay port
uint8_t overlay_number = port & 0x000000FF;
uint8_t setting = (port & 0x0000FF00) >> 8;
@ -152,9 +158,8 @@ int bus_io_read(void *user, uint32_t *value, uint32_t port) {
int bus_io_write(void *user, uint32_t value, uint32_t port) {
(void) user;
switch (port) {
case 0x00000000: { // terminal output port
putchar((int) value);
fflush(stdout);
case 0x00000000: { // serial port
serial_put(value);
break;
};

View File

@ -16,6 +16,7 @@
#include "keyboard.h"
#include "mouse.h"
#include "screen.h"
#include "serial.h"
#include "../fox32rom.h"
@ -110,6 +111,8 @@ int main(int argc, char *argv[]) {
ScreenDraw();
}
serial_init();
tick_start = SDL_GetTicks();
tick_end = SDL_GetTicks();

56
src/serial.c Normal file
View File

@ -0,0 +1,56 @@
#include <sys/select.h>
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <stdbool.h>
#include <stdlib.h>
static struct termios saved_tios;
static bool is_terminal = false;
static void exit_handler(void) {
if (is_terminal)
tcsetattr(0, TCSANOW, &saved_tios);
}
void serial_init(void) {
struct termios tios;
if (tcgetattr(0, &tios) != -1) {
is_terminal = 1;
saved_tios = tios;
atexit(exit_handler);
}
if (is_terminal) {
tios.c_lflag &= ~(ICANON|ECHO);
tcsetattr(0, TCSANOW, &tios);
}
}
int serial_get(void) {
fd_set readfds;
int fd = STDIN_FILENO;
struct timeval tm = { 0, 0 };
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
int ready = select(fd + 1, &readfds, NULL, NULL, &tm);
if (ready == 1 && FD_ISSET(fd, &readfds)) {
char c;
int ret = read(fd, &c, 1);
if (ret == 1)
return c;
}
return 0;
}
void serial_put(int value) {
putchar((int) value);
fflush(stdout);
}

5
src/serial.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
void serial_init(void);
int serial_get(void);
void serial_put(int value);