From 37e4b219d4f65441085f1856497cf5a7279f7d1a Mon Sep 17 00:00:00 2001 From: Godzil Date: Mon, 27 Jun 2022 17:04:55 +0100 Subject: [PATCH] Add a skeleton for the interrupt controller --- source/includes/interrupt_controller.h | 32 +++++++ source/peripherals/interrupt_controller.c | 103 ++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 source/includes/interrupt_controller.h create mode 100644 source/peripherals/interrupt_controller.c diff --git a/source/includes/interrupt_controller.h b/source/includes/interrupt_controller.h new file mode 100644 index 0000000..f038cb5 --- /dev/null +++ b/source/includes/interrupt_controller.h @@ -0,0 +1,32 @@ +/******************************************************************************* + * NewOswan + * interrupt_controller.h: + * + * Created by mlt on 14/03/2022. + * Copyright (c) 2022 986-Studio. All rights reserved. + * + ******************************************************************************/ + +#ifndef __INTERRUPT_CONTROLLER_H__ +#define __INTERRUPT_CONTROLLER_H__ + +#include + +typedef enum hw_interrupt_type_t +{ + /* They are in the same order as the hardware */ + HWI_SERIAL_TX = 0, + HWI_KEY, + HWI_CART, + HWI_SERIAL_RX, + HWI_LINE_COMPARE, + HWI_VBLANK_TIMER, + HWI_VBLANK, + HWI_HBLANK_TIMER, +} hw_interrupt_type_t; + +extern device_t InterruptController; + +void trigger_interrupt(hw_interrupt_type_t type); + +#endif /* __INTERRUPT_CONTROLLER_H__ */ diff --git a/source/peripherals/interrupt_controller.c b/source/peripherals/interrupt_controller.c new file mode 100644 index 0000000..da57d4d --- /dev/null +++ b/source/peripherals/interrupt_controller.c @@ -0,0 +1,103 @@ +/******************************************************************************* + * NewOswan + * interrupt_controller.c: + * + * Created by mlt on 14/03/2022. + * Copyright (c) 2022 986-Studio. All rights reserved. + * + ******************************************************************************/ + +#include +#include + +#include +#include +#include + +/* device internal parameters */ +typedef struct ic_params_t +{ + uint8_t address_base; + uint8_t int_enable_mask; + uint8_t int_status; +} ic_params_t; + +static ic_params_t interrupt_controller; + +static uint8_t IC_IO_read(void *pdata, uint8_t port) +{ + ic_params_t *params = (ic_params_t *)pdata; + + switch(port) + { + case 0xB0: return params->address_base; + case 0xB2: return params->int_enable_mask; + case 0xB4: return params->int_status; + } + + return 0x00; +} + +static void IC_IO_write(void *pdata, uint8_t port, uint8_t value) +{ + ic_params_t *params = (ic_params_t *)pdata; + + switch(port) + { + case 0xB0: params->address_base = value; break; + case 0xB2: params->int_enable_mask = value; break; + } +} + +static void IC_IO_write_ack(void *pdata, uint8_t port, uint8_t value) +{ + ic_params_t *params = (ic_params_t *)pdata; + + // De-assert CPU interrupt accordingly to the mask in value +} + + +static void IC_init(void *params) +{ + UNUSED_PARAMETER(params); + + register_io_hook(0xB0, IC_IO_read, IC_IO_write, &interrupt_controller); + register_io_hook(0xB2, IC_IO_read, IC_IO_write, &interrupt_controller); + register_io_hook(0xB4, IC_IO_read, NULL, &interrupt_controller); + register_io_hook(0xB6, NULL, IC_IO_write_ack, &interrupt_controller); +} + +static void IC_reset() +{ + interrupt_controller.int_enable_mask = 0; + interrupt_controller.address_base = 0; +} + +static void IC_free() +{ + +} + +device_t InterruptController = +{ + .init = IC_init, + .reset = IC_reset, + .free = IC_free, + .deviceType = DT_INTERRUPT_CONTROLLER, +}; + +/* Exported functions */ +void trigger_interrupt(hw_interrupt_type_t type) +{ + uint16_t int_vector = interrupt_controller.address_base & 0xF8 + (uint8_t)type; + + /* Check that the INT is enabled */ + if ((interrupt_controller.int_enable_mask >> type) & 0x1) + { + /* TODO: Do we have to enable that even if the int is not enabled? */ + interrupt_controller.int_status |= (1 << type); + + // Fire the NEC interrupt + + } +} \ No newline at end of file