Compare commits

...

5 commits

Author SHA1 Message Date
orangerot
2f5d42d89a feat(doom): mouse support 2025-11-27 03:42:36 +01:00
orangerot
5037b72832 fix(Makefile): create build/boot/doom directory 2025-11-27 03:10:24 +01:00
orangerot
94c7c03bc8 feat: port PureDOOM to KarlOS 2025-11-27 03:10:24 +01:00
orangerot
0112bce1a3 feat(console): render mouse + click on text to execute command 2025-11-20 11:11:04 +01:00
orangerot
0829e56fb5 feat: ps2 mouse driver + event listener 2025-11-20 11:10:21 +01:00
14 changed files with 49089 additions and 20 deletions

View file

@ -30,8 +30,10 @@ KERNEL_SOURCES_x86_64 := \
KERNEL_SOURCES := \ KERNEL_SOURCES := \
src/acpi.c \ src/acpi.c \
src/console.c \ src/console.c \
src/doom.c \
src/framebuffer.c \ src/framebuffer.c \
src/kernel.c \ src/kernel.c \
src/mouse.c \
src/pci.c \ src/pci.c \
src/ram.c \ src/ram.c \
src/tar.c \ src/tar.c \
@ -67,6 +69,10 @@ clean:
rm -f $(KERNEL_DEPFILES) rm -f $(KERNEL_DEPFILES)
rm -f $(KERNEL_TARGET) rm -f $(KERNEL_TARGET)
build/src/doom.o: src/doom.[cS] | build/src build/src/small3dlib
@printf "CC -sse %s\n" $@
@"$(CC)" -std=c17 -Wall -ggdb -ffreestanding -nostdlib -mno-red-zone -mcmodel=kernel -mno-mmx -mno-80387 -MMD -MP -c -o $@ $< $(CPPFLAGS)
build/src/%.o: src/%.[cS] | build/src build/src/small3dlib build/src/%.o: src/%.[cS] | build/src build/src/small3dlib
@printf "CC %s\n" $@ @printf "CC %s\n" $@
@"$(CC)" $(CFLAGS) -MMD -MP -c -o $@ $< $(CPPFLAGS) @"$(CC)" $(CFLAGS) -MMD -MP -c -o $@ $< $(CPPFLAGS)
@ -79,7 +85,7 @@ $(KERNEL_TARGET): $(KERNEL_OBJECTS) kernel.ld | build/boot/sys
@printf "LD %s\n" $@ @printf "LD %s\n" $@
@"$(LD)" -T kernel.ld $(LDFLAGS) -o $@ $(KERNEL_OBJECTS) @"$(LD)" -T kernel.ld $(LDFLAGS) -o $@ $(KERNEL_OBJECTS)
build/disk.img: $(KERNEL_TARGET) kernel.json bootboot.cfg build/boot/font.sff build/disk.img: $(KERNEL_TARGET) kernel.json bootboot.cfg build/boot/font.sff build/boot/doom/doom1.wad
$(MKBOOTIMG) kernel.json $@ $(MKBOOTIMG) kernel.json $@
build: build:
@ -94,6 +100,13 @@ build/src/small3dlib:
build/boot: build/boot:
mkdir -p $@ mkdir -p $@
build/boot/doom:
mkdir -p $@
build/boot/doom/doom1.wad: doom1.wad build/boot build/boot/doom
@printf "CP %s\n" $@
@cp $< $@
build/boot/font.sff: font.sff build/boot build/boot/font.sff: font.sff build/boot
@printf "CP %s\n" $@ @printf "CP %s\n" $@
@cp $< $@ @cp $< $@

BIN
doom1.wad Normal file

Binary file not shown.

48601
include/PureDOOM.h Normal file

File diff suppressed because it is too large Load diff

18
include/mouse.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef KARLOS_MOUSED_H
#define KARLOS_MOUSED_H
#include <stdbool.h>
#include <stdint.h>
#define MOUSE_BUTTON_MIDDLE (1 << 2)
#define MOUSE_BUTTON_RIGHT (1 << 1)
#define MOUSE_BUTTON_LEFT (1 << 0)
void on_mouse_event(int8_t mouse_x, int8_t mouse_y, uint8_t buttons);
typedef void (*mouse_event_listener)(int8_t mouse_x, int8_t mouse_y, uint8_t buttons);
void register_mouse_event_listener(mouse_event_listener ls);
void unregister_mouse_event_listener(mouse_event_listener ls);
#endif // KARLOS_MOUSED_H

View file

@ -17,6 +17,7 @@ struct tar_header {
uint8_t link_indicator; uint8_t link_indicator;
char *link_name; char *link_name;
void *data; void *data;
char *cur;
}; };
int tar_get_file(const char *name, struct tar_header *hd_out); int tar_get_file(const char *name, struct tar_header *hd_out);

View file

@ -26,7 +26,9 @@ bool window_put(struct window *win, unsigned int row, unsigned int col, glyph g)
void window_scroll(struct window *win); void window_scroll(struct window *win);
void window_clear(struct window *win); void window_clear(struct window *win);
void window_clear_row(struct window *win, unsigned int row); void window_clear_row(struct window *win, unsigned int row);
void glyph_to_framebuffer(struct window *win, unsigned int cx, unsigned int cy, glyph chr, bool invert_color);
void window_glyph_to_framebuffer(struct window *win, unsigned int row, unsigned int col, bool invert_color); void window_glyph_to_framebuffer(struct window *win, unsigned int row, unsigned int col, bool invert_color);
glyph window_get(struct window *win, unsigned int row, unsigned int col); glyph window_get(struct window *win, unsigned int row, unsigned int col);
void window_redraw(struct window *win);
void window_get_position(unsigned int x, unsigned int y, unsigned int *row, unsigned int *col);
#endif #endif

View file

@ -1,5 +1,6 @@
#include "interpreter.h" #include "interpreter.h"
#include "keyboard.h" #include "keyboard.h"
#include "mouse.h"
#include "std.h" #include "std.h"
#include "console.h" #include "console.h"
#include "framebuffer.h" #include "framebuffer.h"
@ -30,6 +31,11 @@ int cout_cursor_y;
int cin_cursor_x; int cin_cursor_x;
int cin_cursor_y; int cin_cursor_y;
int mouse_x;
int mouse_y;
bool clicked = false;
void console_editor_key_event_listener(enum editor_key_event_kind kind, uint32_t codepoint); void console_editor_key_event_listener(enum editor_key_event_kind kind, uint32_t codepoint);
void console_init(void) void console_init(void)
@ -62,11 +68,41 @@ void cin_clear() {
window_glyph_to_framebuffer(&cin_win, cin_cursor_y, cin_cursor_x, true); window_glyph_to_framebuffer(&cin_win, cin_cursor_y, cin_cursor_x, true);
} }
void console_mouse_event_listener(int8_t rel_x, int8_t rel_y, uint8_t buttons) {
mouse_x += rel_x;
mouse_y -= rel_y;
window_redraw(&cout_win);
window_redraw(&cin_win);
if (clicked && (buttons & MOUSE_BUTTON_LEFT) == 0) {
printf("clicked\n");
unsigned int row,col;
glyph chr;
window_get_position(mouse_x, mouse_y, &row, &col);
// window_put(&cout_win, row, col, '#');
// chr = window_get(&cout_win, row, col);
do {
chr = window_get(&cout_win, row, col);
cin_putc(chr);
col++;
} while (chr != ' ' && chr != 0 && col < cout_win.num_cols);
cin_putc('\n');
}
glyph_to_framebuffer(&cout_win, mouse_x, mouse_y, '<', false);
fb_refresh();
clicked = buttons & MOUSE_BUTTON_LEFT;
}
void console_start(void) void console_start(void)
{ {
cout_clear(); cout_clear();
cin_clear(); cin_clear();
mouse_y = 20;
mouse_x = 20;
register_editor_key_event_listener(console_editor_key_event_listener); register_editor_key_event_listener(console_editor_key_event_listener);
register_mouse_event_listener(console_mouse_event_listener);
} }
void console_stop(void) void console_stop(void)
@ -74,6 +110,7 @@ void console_stop(void)
// TODO make sure that printf() doesn't result in stuff being drawn on screen // TODO make sure that printf() doesn't result in stuff being drawn on screen
// for as long as the console is stopped! // for as long as the console is stopped!
unregister_editor_key_event_listener(console_editor_key_event_listener); unregister_editor_key_event_listener(console_editor_key_event_listener);
unregister_mouse_event_listener(console_mouse_event_listener);
} }
void cout_putc(uint32_t c) void cout_putc(uint32_t c)

261
src/doom.c Normal file
View file

@ -0,0 +1,261 @@
#include <stdint.h>
#include "ram.h"
#include "framebuffer.h"
#include "keyboard.h"
#include "time.h"
#include "std.h"
#include "tar.h"
#include "mouse.h"
#define DOOM_IMPLEMENTATION
#include "PureDOOM.h"
#define WIDTH 320
#define HEIGHT 200
void* my_malloc(int size) {
// printf("malloc\n");
struct ram_buffer_requirements req;
req.align = 0;
req.limit4gb = 0;
req.size = size;
struct ppn ppn;
// FIX: only allocatesd 4096??? see impl
if (!ram_alloc_buffer(&ppn, req)) {
printf("fb: Unable to allocate backbuffer.\n");
return 0;
}
return pa_to_pointer(pa_from_ppn(ppn));
}
void my_free(void *ptr) {
(void) ptr;
}
void my_printf(const char *str) {
(void) str;
printf("%s", str);
// fb_damage(region.rect);
fb_refresh();
}
void my_gettime(int *sec, int *usec) {
Time t = time_current();
*sec = t.sec;
*usec = TIME_TO_NS(t) / 1000;
}
struct tar_header file_handles[64] = {0};
size_t file_handles_num = 0;
void* my_open(const char* filename, const char* mode) {
(void) mode;
if (!tar_get_file(filename, &file_handles[file_handles_num]))
return 0;
file_handles[file_handles_num].cur = file_handles[file_handles_num].data;
// return (void*) file_handles_num++;
return &file_handles[file_handles_num++];
}
void my_close(void* handle) {
(void) handle;
}
int my_read(void* handle, void *buf, int count) {
memcpy(buf, ((struct tar_header*) handle)->cur, count);
((struct tar_header*) handle)->cur += count;
return count;
}
int my_write(void* handle, const void *buf, int count) {
(void) handle;
(void) buf;
(void) count;
return count;
}
int my_seek(void* handle, int offset, doom_seek_t origin) {
struct tar_header *file = handle;
switch (origin) {
case DOOM_SEEK_CUR:
file->cur += offset;
break;
case DOOM_SEEK_END:
file->cur = file->data + file->size + offset;
break;
case DOOM_SEEK_SET:
file->cur = file->data + offset;
break;
}
return 0;
}
int my_tell(void* handle) {
struct tar_header *file = handle;
return file->cur - (char*) file->data;
}
int my_eof(void* handle) {
(void) handle;
return 0;
}
char* my_getenv(const char* var) {
(void) var;
return "doom";
}
doom_key_t key_to_doom_key[] = {
[KEY_TAB] = DOOM_KEY_TAB,
[KEY_ENTER] = DOOM_KEY_ENTER,
[KEY_ESCAPE] = DOOM_KEY_ESCAPE,
[KEY_SPACE] = DOOM_KEY_SPACE,
[KEY_COMMA] = DOOM_KEY_COMMA,
[KEY_MINUS] = DOOM_KEY_MINUS,
[KEY_PERIOD] = DOOM_KEY_PERIOD,
[KEY_0] = DOOM_KEY_0,
[KEY_1] = DOOM_KEY_1,
[KEY_2] = DOOM_KEY_2,
[KEY_3] = DOOM_KEY_3,
[KEY_4] = DOOM_KEY_4,
[KEY_5] = DOOM_KEY_5,
[KEY_6] = DOOM_KEY_6,
[KEY_7] = DOOM_KEY_7,
[KEY_8] = DOOM_KEY_8,
[KEY_9] = DOOM_KEY_9,
[KEY_EQUALS] = DOOM_KEY_EQUALS,
[KEY_A] = DOOM_KEY_A,
[KEY_B] = DOOM_KEY_B,
[KEY_C] = DOOM_KEY_C,
[KEY_D] = DOOM_KEY_D,
[KEY_E] = DOOM_KEY_E,
[KEY_F] = DOOM_KEY_F,
[KEY_G] = DOOM_KEY_G,
[KEY_H] = DOOM_KEY_H,
[KEY_I] = DOOM_KEY_I,
[KEY_J] = DOOM_KEY_J,
[KEY_K] = DOOM_KEY_K,
[KEY_L] = DOOM_KEY_L,
[KEY_M] = DOOM_KEY_M,
[KEY_N] = DOOM_KEY_N,
[KEY_O] = DOOM_KEY_O,
[KEY_P] = DOOM_KEY_P,
[KEY_Q] = DOOM_KEY_Q,
[KEY_R] = DOOM_KEY_R,
[KEY_S] = DOOM_KEY_S,
[KEY_T] = DOOM_KEY_T,
[KEY_U] = DOOM_KEY_U,
[KEY_V] = DOOM_KEY_V,
[KEY_W] = DOOM_KEY_W,
[KEY_X] = DOOM_KEY_X,
[KEY_Y] = DOOM_KEY_Y,
[KEY_Z] = DOOM_KEY_Z,
[KEY_BACKSPACE] = DOOM_KEY_BACKSPACE,
[KEY_ARROW_LEFT] = DOOM_KEY_LEFT_ARROW,
[KEY_ARROW_UP] = DOOM_KEY_UP_ARROW,
[KEY_ARROW_RIGHT] = DOOM_KEY_RIGHT_ARROW,
[KEY_ARROW_DOWN] = DOOM_KEY_DOWN_ARROW,
[KEY_F1] = DOOM_KEY_F1,
[KEY_F2] = DOOM_KEY_F2,
[KEY_F3] = DOOM_KEY_F3,
[KEY_F4] = DOOM_KEY_F4,
[KEY_F5] = DOOM_KEY_F5,
[KEY_F6] = DOOM_KEY_F6,
[KEY_F7] = DOOM_KEY_F7,
[KEY_F8] = DOOM_KEY_F8,
[KEY_F9] = DOOM_KEY_F9,
[KEY_F10] = DOOM_KEY_F10,
[KEY_F11] = DOOM_KEY_F11,
[KEY_F12] = DOOM_KEY_F12,
[KEY_PAUSE] = DOOM_KEY_PAUSE,
};
void doom_key_event_listener(enum keycode code, bool pressed) {
if (pressed) {
doom_key_down(key_to_doom_key[code]);
if (code == KEY_SPACE) doom_button_down(DOOM_LEFT_BUTTON);
if (code == KEY_ARROW_LEFT) doom_mouse_move(-10, 0);
if (code == KEY_ARROW_RIGHT) doom_mouse_move(10, 0);
} else {
doom_key_up(key_to_doom_key[code]);
if (code == KEY_SPACE) doom_button_up(DOOM_LEFT_BUTTON);
}
}
void doom_mouse_event_listener(int8_t mouse_x, int8_t mouse_y, uint8_t buttons) {
static uint8_t mouse_btn_left_old = 0;
static uint8_t mouse_btn_middle_old = 0;
static uint8_t mouse_btn_right_old = 0;
doom_mouse_move(mouse_x * 20, mouse_y * 20);
if (!mouse_btn_left_old && (buttons & MOUSE_BUTTON_LEFT )) doom_button_down(DOOM_LEFT_BUTTON);
if (!mouse_btn_middle_old && (buttons & MOUSE_BUTTON_MIDDLE)) doom_button_down(DOOM_MIDDLE_BUTTON);
if (!mouse_btn_right_old && (buttons & MOUSE_BUTTON_RIGHT )) doom_button_down(DOOM_RIGHT_BUTTON);
if (mouse_btn_left_old && !(buttons & MOUSE_BUTTON_LEFT )) doom_button_up(DOOM_LEFT_BUTTON);
if (mouse_btn_middle_old && !(buttons & MOUSE_BUTTON_MIDDLE)) doom_button_up(DOOM_MIDDLE_BUTTON);
if (mouse_btn_right_old && !(buttons & MOUSE_BUTTON_RIGHT )) doom_button_up(DOOM_RIGHT_BUTTON);
mouse_btn_left_old = buttons & MOUSE_BUTTON_LEFT;
mouse_btn_middle_old = buttons & MOUSE_BUTTON_MIDDLE;
mouse_btn_right_old = buttons & MOUSE_BUTTON_RIGHT;
}
void doom_start(void)
{
struct fb_region region;
struct rect desiredRect = RECT_XYWH(
0,
0,
WIDTH,
HEIGHT);
fb_access_region(desiredRect, &region);
register_raw_key_event_listener(doom_key_event_listener);
register_mouse_event_listener(doom_mouse_event_listener);
doom_set_malloc(my_malloc, my_free);
doom_set_print(my_printf);
doom_set_gettime(my_gettime);
doom_set_file_io(
my_open,
my_close,
my_read,
my_write,
my_seek,
my_tell,
my_eof
);
doom_set_getenv(my_getenv);
doom_set_default_int("key_up", DOOM_KEY_W);
doom_set_default_int("key_down", DOOM_KEY_S);
doom_set_default_int("key_strafeleft", DOOM_KEY_A);
doom_set_default_int("key_straferight", DOOM_KEY_D);
doom_set_default_int("key_use", DOOM_KEY_E);
doom_init(0, 0, 0); // arguments have to be 0; we dont need response file
while (true)
{
doom_update();
const uint32_t* framebuffer = (uint32_t*) doom_get_framebuffer(4 /* RGBA */);
char *rowPointer = region.pointer;
for (int y = region.rect.y1; y < region.rect.y2; y++) {
uint32_t *pixel = (uint32_t *)rowPointer;
for (int x = region.rect.x1; x < region.rect.x2; x++) {
fb_set_px(x, y, *(struct color*) &framebuffer[y * WIDTH + x]);
// *pixel = (framebuffer[y * WIDTH + x] >> 8) | 0xFF000000;
pixel++;
}
rowPointer += region.stride;
}
fb_damage(region.rect);
fb_refresh();
}
}

View file

@ -20,7 +20,7 @@ static void interpreter_timer_callback(Timer *timer) {
extern void (*task)(void); extern void (*task)(void);
void interpret_handle_input_line(const uint8_t *s) { void interpret_handle_input_line(const uint8_t *s) {
printf(">>> %s\n", s); printf(">>> %s\n", s);
if (memcmp(s, "echo", 4) == 0) { if (memcmp(s, "echo", 4) == 0) {
s += 4; s += 4;
@ -91,6 +91,9 @@ void interpret_handle_input_line(const uint8_t *s) {
} else if (memcmp(s, "city", 4) == 0) { } else if (memcmp(s, "city", 4) == 0) {
extern void city_main(void); extern void city_main(void);
task = city_main; task = city_main;
} else if (memcmp(s, "doom", 4) == 0) {
extern void doom_start(void);
task = doom_start;
} else if (memcmp(s, "help", 4) == 0 || memcmp(s, "?", 1) == 0) { } else if (memcmp(s, "help", 4) == 0 || memcmp(s, "?", 1) == 0) {
printf("The following commands are available:\n"); printf("The following commands are available:\n");
printf("help -- Print this information to the screen\n"); printf("help -- Print this information to the screen\n");

View file

@ -82,15 +82,15 @@ void _start() {
console_stop(); console_stop();
// HACK Clear the screen // HACK Clear the screen
struct fb_region region; // struct fb_region region;
struct rect desiredRect = RECT_XYWH( // struct rect desiredRect = RECT_XYWH(
0, 0, // 0, 0,
fb_width(), // fb_width(),
fb_height()); // fb_height());
fb_access_region(desiredRect, &region); // fb_access_region(desiredRect, &region);
memset(region.pointer, 0, region.stride * region.rect.y2); // memset(region.pointer, 0, region.stride * region.rect.y2);
fb_damage(region.rect); // fb_damage(region.rect);
fb_refresh(); // fb_refresh();
task(); task();
task = NULL; task = NULL;

31
src/mouse.c Normal file
View file

@ -0,0 +1,31 @@
#include "std.h"
#include <stdint.h>
#include "mouse.h"
#define NUM_LISTENERS 10
mouse_event_listener listeners[NUM_LISTENERS];
size_t num_listeners = 0;
void register_mouse_event_listener(mouse_event_listener ls) {
ASSERT(num_listeners < NUM_LISTENERS);
listeners[num_listeners++] = ls;
}
void unregister_mouse_event_listener(mouse_event_listener ls) {
for (size_t i = 0; i < num_listeners; i++) {
if (listeners[i] == ls) {
num_listeners--;
for (size_t j = i; j < num_listeners; j++) {
listeners[j] = listeners[j+1];
}
return;
}
}
}
void on_mouse_event(int8_t mouse_x, int8_t mouse_y, uint8_t buttons) {
for (size_t i = 0; i < num_listeners; i++) {
listeners[i](mouse_x, mouse_y, buttons);
}
}

View file

@ -4,6 +4,7 @@
#include "std.h" #include "std.h"
#include "console.h" #include "console.h"
#include "unicode.h" #include "unicode.h"
#include "x86_64/uart.h"
#include "x86_64/interrupt.h" #include "x86_64/interrupt.h"
@ -80,7 +81,7 @@ static void linebuf_flush(void) {
int int_state = int_disable(); int int_state = int_disable();
for (unsigned int i = 0; i < current_buffer_position; i++) { for (unsigned int i = 0; i < current_buffer_position; i++) {
// TODO // TODO
// serial_write_char(linebuf[i]); uart_write_char(linebuf[i]);
cout_putc(linebuf[i]); cout_putc(linebuf[i]);
} }
current_buffer_position = 0; current_buffer_position = 0;

View file

@ -121,6 +121,34 @@ static struct rect display_from_font(
} }
// #define WINDOW_USE_REPLACEMENT_CHAR // #define WINDOW_USE_REPLACEMENT_CHAR
struct rect glyph_to_framebuffer_norefresh(struct window *win,
unsigned int cx, unsigned int cy, glyph chr, bool invert_color) {
struct rect rect;
if (chr == 0) { chr = ' '; }
struct sff_glyph_offset off = sff_find_glyph(&font_file, chr);
if (SFF_GLYPH_FOUND(off)) {
rect = display_from_font(win, cx, cy, off, invert_color);
} else {
#if defined(WINDOW_USE_REPLACEMENT_CHAR)
off = sff_find_glyph(&font_file, UNICODE_REPLACEMENT_CHARACTER);
ASSERT(SFF_GLYPH_FOUND(off));
rect = display_from_font(win, cx, cy, off, invert_color);
#else
ASSERT(font_file.char_width >= 8 && font_file.char_height >= 18);
rect = display_err_unicode_hex(win, cx, cy, chr, invert_color);
#endif
}
return rect;
}
void glyph_to_framebuffer(struct window *win,
unsigned int cx, unsigned int cy, glyph chr, bool invert_color)
{
struct rect rect = glyph_to_framebuffer_norefresh(win, cx, cy, chr, invert_color);
fb_damage(rect);
//fb_refresh();
}
struct rect window_glyph_to_framebuffer_norefresh(struct window *win, struct rect window_glyph_to_framebuffer_norefresh(struct window *win,
unsigned int row, unsigned int col, bool invert_color) unsigned int row, unsigned int col, bool invert_color)
@ -226,3 +254,22 @@ glyph window_get(struct window *win, unsigned int row, unsigned int col) {
return win->data[row * win->num_cols + col]; return win->data[row * win->num_cols + col];
} }
void window_redraw(struct window *win) {
struct fb_region region;
fb_access_region(win->rect, &region);
for (unsigned row = 0; row < RECT_HEIGHT(region.rect); row++) {
memset((char *)region.pointer + region.stride * row, 0, 4 * RECT_WIDTH(region.rect));
}
fb_damage(region.rect);
for (unsigned int row = 0; row < win->num_rows; row++) {
for(unsigned int col = 0; col < win->num_cols; col++) {
window_put(win, row, col, win->data[row * win->num_cols + col]);
}
}
}
void window_get_position(unsigned int x, unsigned int y, unsigned int *row, unsigned int *col) {
*row = y / font_file.char_height;
*col = x / font_file.char_width;
}

View file

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include "cpu.h" #include "cpu.h"
#include "mouse.h"
#include "std.h" #include "std.h"
#include "x86_64/apic.h" #include "x86_64/apic.h"
#include "x86_64/asm.h" #include "x86_64/asm.h"
@ -252,15 +253,57 @@ void port1_handler(void) {
#endif #endif
} }
#define MOUSE_PACKET_Y_OVERFLOW 7
#define MOUSE_PACKET_X_OVERFLOW 6
#define MOUSE_PACKET_Y_SIGN 5
#define MOUSE_PACKET_X_SIGN 4
#define MOUSE_PACKET_ONE 3
#define MOUSE_PACKET_BUTTON_MIDDLE 2
#define MOUSE_PACKET_BUTTON_RIGHT 1
#define MOUSE_PACKET_BUTTON_LEFT 0
size_t mouse_packet_byte = 0;
union {
uint8_t arr[3];
struct mouse_packet {
uint8_t buttons, x, y;
} mouse;
} mouse;
void port2_handler(void) { void port2_handler(void) {
if (!ps2_can_read()) { if (!ps2_can_read()) {
// Assume spurious interrupt. Maybe from another device? // Assume spurious interrupt. Maybe from another device?
return; return;
} }
uint8_t data = ps2_read_data(); uint8_t data = ps2_read_data();
(void)data; DEBUG_PRINTF("keycode from port 2: %X8\n", data);
DEBUG_PRINTF("keycode from port 2: %X8\n", data); if ((mouse_packet_byte == 0) && ((data & (1 << MOUSE_PACKET_ONE)) == 0)) {
return;
}
int8_t x = mouse.mouse.x - ((mouse.mouse.buttons << 4) & 0x100);
int8_t y = mouse.mouse.y - ((mouse.mouse.buttons << 3) & 0x100);
mouse.arr[mouse_packet_byte++] = data;
if (mouse_packet_byte == 3) {
mouse_packet_byte = 0;
on_mouse_event(x, y, mouse.mouse.buttons & (MOUSE_BUTTON_MIDDLE | MOUSE_BUTTON_RIGHT | MOUSE_BUTTON_LEFT));
DEBUG_PRINTF(
"mouse event: %u %u %u %u %u %u %u, X: %d, Y: %d, [%u, %u]\n",
mouse.mouse.buttons >> MOUSE_PACKET_Y_OVERFLOW & 1,
mouse.mouse.buttons >> MOUSE_PACKET_X_OVERFLOW & 1,
mouse.mouse.buttons >> MOUSE_PACKET_Y_SIGN & 1,
mouse.mouse.buttons >> MOUSE_PACKET_X_SIGN & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_MIDDLE & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_RIGHT & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_LEFT & 1,
x,
y,
mouse.mouse.x,
mouse.mouse.y
);
}
} }
#define PS2_INIT_PRINT #define PS2_INIT_PRINT
@ -282,14 +325,14 @@ void ps2_init() {
/* Flush Outputbuffer */ /* Flush Outputbuffer */
ps2_empty_output_buffer(); ps2_empty_output_buffer();
/* Set Configbyte */ /* Set Configbyte */
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ); config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
config_byte &= ~(1 << CONFIG_BIT_PORT1_INT_ENABLED); config_byte &= ~(1 << CONFIG_BIT_PORT1_INT_ENABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT1_CLOCK_DISABLED); config_byte &= ~(1 << CONFIG_BIT_PORT1_CLOCK_DISABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT1_TRANSLATION); config_byte &= ~(1 << CONFIG_BIT_PORT1_TRANSLATION);
ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte); ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte);
/* Selftest */ /* Selftest */
uint8_t test = ps2_cmd_response(CMD_TEST); uint8_t test = ps2_cmd_response(CMD_TEST);
PS2_TEST("self-test", test, 0x55); PS2_TEST("self-test", test, 0x55);
@ -299,7 +342,8 @@ void ps2_init() {
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ); config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
bool port_2_enabled = ((config_byte >> 5) & 1) == 0; bool port_2_enabled = ((config_byte >> 5) & 1) == 0;
if (port_2_enabled) { if (port_2_enabled) {
ps2_write_cmd(CMD_PORT2_DISABLE); DEBUG_PRINTF("port 2 enabled\n");
ps2_write_cmd(CMD_PORT2_DISABLE);
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ); config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
config_byte &= ~(1 << CONFIG_BIT_PORT2_INT_ENABLED); config_byte &= ~(1 << CONFIG_BIT_PORT2_INT_ENABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT2_CLOCK_DISABLED); config_byte &= ~(1 << CONFIG_BIT_PORT2_CLOCK_DISABLED);
@ -338,6 +382,16 @@ void ps2_init() {
ps2_write_data(0xFF); ps2_write_data(0xFF);
ps2_read_data(); ps2_read_data();
// TODO reset port 2 // TODO reset port 2
if (port_2_enabled) {
ps2_write_cmd(0xD4);
ps2_write_data(0xFF);
// ps2_read_data();
ps2_empty_output_buffer();
ps2_write_cmd(0xD4);
ps2_write_data(0xF4);
ps2_empty_output_buffer();
// ps2_read_data();
}
/* Enable interrupts */ /* Enable interrupts */
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ); config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
@ -348,5 +402,5 @@ void ps2_init() {
ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte); ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte);
/* Flush Outputbuffer again because it doesn't work otherwise */ /* Flush Outputbuffer again because it doesn't work otherwise */
//ps2_empty_output_buffer(); ps2_empty_output_buffer();
} }