Skip to content

Commit

Permalink
Added AT chipset code
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas-jonsson committed Sep 5, 2024
1 parent c8bf83d commit be87bf9
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 6 deletions.
10 changes: 5 additions & 5 deletions front/sdl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ int num_devices = 0;
struct vxt_peripheral *devices[VXT_MAX_PERIPHERALS] = { NULL };
#define APPEND_DEVICE(d) { devices[num_devices++] = (d); }

// Needed for detecting turbo mode.
// Needed for detecting turbo mode on XT machines.
struct vxt_peripheral *ppi_device = NULL;

SDL_atomic_t running = {1};
Expand Down Expand Up @@ -204,7 +204,7 @@ static int emu_loop(void *ptr) {
num_cycles += res.cycles;
}

frequency = vxtu_ppi_turbo_enabled(ppi_device) ? cpu_frequency : ((double)VXT_DEFAULT_FREQUENCY / 1000000.0);
frequency = (!ppi_device || vxtu_ppi_turbo_enabled(ppi_device)) ? cpu_frequency : ((double)VXT_DEFAULT_FREQUENCY / 1000000.0);
frequency_hz = (int)(frequency * 1000000.0);
vxt_system_set_frequency(vxt, frequency_hz);
);
Expand Down Expand Up @@ -968,7 +968,7 @@ int main(int argc, char *argv[]) {

if (!ppi_device) {
printf("No PPI device!\n");
return -1;
//return -1;
}

if (!disk_controller.device) {
Expand Down Expand Up @@ -1109,7 +1109,7 @@ int main(int argc, char *argv[]) {
break;
case SDL_KEYUP:
if (e.key.keysym.sym == SDLK_F11) {
if (e.key.keysym.mod & KMOD_ALT) {
if (ppi_device && (e.key.keysym.mod & KMOD_ALT)) {
printf("Toggle turbo!\n");
SYNC(
vxt_byte data = ppi_device->io.in(VXT_GET_DEVICE_PTR(ppi_device), 0x61);
Expand Down Expand Up @@ -1150,7 +1150,7 @@ int main(int argc, char *argv[]) {
SYNC(
mhz = (double)num_cycles / 500000.0;
num_cycles = 0;
turbo = vxtu_ppi_turbo_enabled(ppi_device);
turbo = ppi_device && vxtu_ppi_turbo_enabled(ppi_device);
);

if (ticks > 10000) {
Expand Down
67 changes: 67 additions & 0 deletions modules/chipset_at/at.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2019-2024 Andreas T Jonsson <mail@andreasjonsson.se>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software in
// a product, an acknowledgment (see the following) in the product
// documentation is required.
//
// This product make use of the VirtualXT software emulator.
// Visit https://virtualxt.org for more information.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.

#include <vxt/vxtu.h>
#include <frontend.h>

static struct vxt_peripheral *pic_create(vxt_allocator *alloc, void *frontend, const char *args) {
(void)frontend; (void)args;
return vxtu_pic_create(alloc);
}

static struct vxt_peripheral *dma_create(vxt_allocator *alloc, void *frontend, const char *args) {
(void)frontend; (void)args;
return vxtu_dma_create(alloc);
}

static struct vxt_peripheral *pit_create(vxt_allocator *alloc, void *frontend, const char *args) {
(void)frontend; (void)args;
return vxtu_pit_create(alloc);
}

struct vxt_peripheral *kbc_create(vxt_allocator *alloc);
bool kbc_key_event(struct vxt_peripheral *p, enum vxtu_scancode key, bool force);
vxt_int16 kbc_generate_sample(struct vxt_peripheral *p, int freq);

static struct vxt_peripheral *kbc_setup(vxt_allocator *alloc, void *frontend, const char *args) {
(void)args;

struct vxt_peripheral *p = kbc_create(alloc);
if (!p) return NULL;

if (frontend) {
struct frontend_interface *fi = (struct frontend_interface*)frontend;
if (fi->set_keyboard_controller) {
struct frontend_keyboard_controller controller = { p, &kbc_key_event };
fi->set_keyboard_controller(&controller);
}
if (fi->set_audio_adapter) {
struct frontend_audio_adapter adapter = { p, &kbc_generate_sample };
fi->set_audio_adapter(&adapter);
}
}

return p;
}

VXTU_MODULE_ENTRIES(&pic_create, &dma_create, &pit_create, &kbc_setup)
176 changes: 176 additions & 0 deletions modules/chipset_at/kbc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright (c) 2019-2024 Andreas T Jonsson <mail@andreasjonsson.se>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software in
// a product, an acknowledgment (see the following) in the product
// documentation is required.
//
// This product make use of the VirtualXT software emulator.
// Visit https://virtualxt.org for more information.
//
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.

#include <vxt/vxtu.h>

#ifndef VXTU_PPI_TONE_VOLUME
#define VXTU_PPI_TONE_VOLUME 8192
#endif

#define MAX_EVENTS 16
#define INT64 long long

#define DATA_READY 1
#define COMMAND_READY 2

#define DISABLE_KEYBOARD_CMD 0xAD
#define ENABLE_KEYBOARD_CMD 0xAE
#define READ_INPUT_CMD 0xD0
#define WRITE_OUTPUT_CMD 0xD1

struct kbc {
vxt_byte data_port;
vxt_byte command_port;
vxt_byte port_61;

vxt_byte command;
bool keyboard_enable;

int queue_size;
enum vxtu_scancode queue[MAX_EVENTS];

INT64 spk_sample_index;
bool spk_enabled;

struct vxt_peripheral *pit;
};

static vxt_byte in(struct kbc *c, vxt_word port) {
switch (port) {
case 0x60:
{
vxt_byte data = c->data_port;
c->command_port = c->data_port = 0; // Not sure if the data port should be cleared on read?
return data;
}
case 0x61:
return c->port_61;
case 0x64:
return c->command_port;
}
return 0;
}

static void out(struct kbc *c, vxt_word port, vxt_byte data) {
if (port == 0x61) {
bool spk_enable = (data & 3) == 3;
if (spk_enable != c->spk_enabled) {
c->spk_enabled = spk_enable;
c->spk_sample_index = 0;
}

bool kb_reset = !(c->port_61 & 0xC0) && (data & 0xC0);
if (kb_reset) {
c->queue_size = 0;
c->data_port = 0xAA;
c->command_port = COMMAND_READY | DATA_READY;
vxt_system_interrupt(VXT_GET_SYSTEM(c), 1);
}

c->port_61 = data;
}
}

static vxt_error install(struct kbc *c, vxt_system *s) {
struct vxt_peripheral *p = VXT_GET_PERIPHERAL(c);
vxt_system_install_io(s, p, 0x60, 0x62);
vxt_system_install_io_at(s, p, 0x64);
vxt_system_install_timer(s, p, 1000);

for (int i = 0; i < VXT_MAX_PERIPHERALS; i++) {
struct vxt_peripheral *ip = vxt_system_peripheral(s, (vxt_byte)i);
if (ip && (vxt_peripheral_class(ip) == VXT_PCLASS_PIT)) {
c->pit = ip;
break;
}
}
return c->pit ? VXT_NO_ERROR : VXT_USER_ERROR(0);
}

static vxt_error timer(struct kbc *c, vxt_timer_id id, int cycles) {
(void)id; (void)cycles;
c->command_port |= COMMAND_READY;
if (c->keyboard_enable) {
if (c->queue_size && !(c->command_port & DATA_READY)) {
c->command_port |= DATA_READY;
c->data_port = (vxt_byte)c->queue[0];
memmove(c->queue, &c->queue[1], --c->queue_size);
vxt_system_interrupt(VXT_GET_SYSTEM(c), 1);
}
} else if (c->command == READ_INPUT_CMD) {
c->command_port |= DATA_READY;
}
return VXT_NO_ERROR;
}

static vxt_error reset(struct kbc *c) {
c->command_port = c->data_port = 0;
c->port_61 = 14;

c->spk_sample_index = 0;
c->spk_enabled = false;

c->keyboard_enable = true;
c->queue_size = 0;

return VXT_NO_ERROR;
}

static const char *name(struct kbc *c) {
(void)c; return "Keyboard Controller (Intel 8042)";
}

struct vxt_peripheral *kbc_create(vxt_allocator *alloc) VXT_PERIPHERAL_CREATE(alloc, kbc, {
PERIPHERAL->install = &install;
PERIPHERAL->reset = &reset;
PERIPHERAL->timer = &timer;
PERIPHERAL->name = &name;
PERIPHERAL->io.in = &in;
PERIPHERAL->io.out = &out;
})

bool kbc_key_event(struct vxt_peripheral *p, enum vxtu_scancode key, bool force) {
struct kbc *c = VXT_GET_DEVICE(kbc, p);
if (c->queue_size < MAX_EVENTS) {
c->queue[c->queue_size++] = key;
return true;
} else if (force) {
c->queue[MAX_EVENTS - 1] = key;
}
return false;
}

vxt_int16 kbc_generate_sample(struct vxt_peripheral *p, int freq) {
struct kbc *c = VXT_GET_DEVICE(kbc, p);

double tone_hz = vxtu_pit_get_frequency(c->pit, 2);
if (!c->spk_enabled || (tone_hz <= 0.0))
return 0;

INT64 square_wave_period = (INT64)((double)freq / tone_hz);
INT64 half_square_wave_period = square_wave_period / 2;

if (!half_square_wave_period)
return 0;
return ((++c->spk_sample_index / half_square_wave_period) % 2) ? VXTU_PPI_TONE_VOLUME : -VXTU_PPI_TONE_VOLUME;
}
4 changes: 4 additions & 0 deletions modules/chipset_at/premake5.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
files {
"at.c",
"kbc.c"
}
2 changes: 1 addition & 1 deletion modules/vga/vga.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ static vxt_error install(struct vga_video *v, vxt_system *s) {
// Try to set XT switches to VGA.
for (int i = 0; i < VXT_MAX_PERIPHERALS; i++) {
struct vxt_peripheral *ip = vxt_system_peripheral(s, (vxt_byte)i);
if (vxt_peripheral_class(ip) == VXT_PCLASS_PPI) {
if (ip && vxt_peripheral_class(ip) == VXT_PCLASS_PPI) {
vxtu_ppi_set_xt_switches(ip, vxtu_ppi_xt_switches(ip) & 0xCF);
break;
}
Expand Down

0 comments on commit be87bf9

Please sign in to comment.