Interrupt Controller module draft, bopti bugfix.

This commit is contained in:
lephe 2017-04-22 21:59:39 +02:00
parent 3214f6b797
commit a0f06fadd7
10 changed files with 573 additions and 55 deletions

1
TODO
View file

@ -16,6 +16,7 @@ Things to do before 1.0:
Things to do later:
- bopti: Implement blending modes for monochrome bitmaps
- clock: Handle overclock (relaunch clocks when overclocking)
- core: Change interrupt priority using the gint API
- core: Register more interrupts (and understand their parameters)
- core: Remove redundant code linked to environment saves
- core: Review interrupt system (again) - this one is too slow

View file

@ -75,7 +75,7 @@ typedef struct command_t
uint32_t masks[4];
// Video rams being used.
union {
// Different names, same fate. (Kingdom Hearts II)
// "Different names, same fate." (Kingdom Hearts II)
uint32_t *vram;
uint32_t *v1;
};

View file

@ -0,0 +1,489 @@
#ifndef _MODULES_INTERRUPTS
#define _MODULES_INTERRUPTS
#include <modules/macros.h>
#include <stdint.h>
//---
// Interrupt controller.
// This part is difficult to handle, because the interrupt controllers of
// SH7705 and SH7305 MPUs have virtually nothing in common. I eventually
// decided to completely split it up into two kinds of structures and
// types.
// Use the gint API, not this module, for platform-independent interrupt
// management.
//---
//---
// SH7705-related definitions.
//---
/*
mod_intc_ipc_7705_t
Interrupt priority controller. Just a bunch of 16-bit-registers that
handle the interrupt priority of all interrupt sources.
Please note that because the interrupt priority controller of the
SH7705 MPU has registers scattered everywhere in the memory, its
structure below has a different pointer for each register. On the
opposite, the SH7305 registers are all in a contiguous area thus there
is only one pointer for the whole group.
*/
typedef struct
{
volatile word_union(*IPRA,
uint TMU0 :4; /* Timer 0 */
uint TMU1 :4; /* Timer 1 */
uint TMU2 :4; /* Timer 2 */
uint RTC :4; /* Real-Time Clock */
);
volatile word_union(*IPRB,
uint WDT :4; /* Watchdog Timer */
uint REF :4; /* BSC Refresh Request, SDRAM (?) */
uint :4;
uint :4;
);
volatile word_union(*IPRC,
uint IRQ3 :4; /* Interrupt request 3 */
uint IRQ2 :4; /* Interrupt request 2 */
uint IRQ1 :4; /* Interrupt request 1 */
uint IRQ0 :4; /* Interrupt request 0 */
);
volatile word_union(*IPRD,
uint PINT0_7 :4; /* External interrupt pins 0 to 7 */
uint PINT8_15 :4; /* External interrupt pins 8 to 15 */
uint IRQ5 :4; /* Interrupt request 5 */
uint IRQ4 :4; /* Interrupt request 4 */
);
volatile word_union(*IPRE,
uint DMAC :4; /* Direct Memory Access Controller */
uint SCIF0 :4; /* Serial Communication Interface 0 */
uint SCIF2 :4; /* Serial Communication Interface 2 */
uint ADC :4; /* Analog/Decimal Converter */
);
volatile word_union(*IPRF,
uint :4;
uint :4;
uint USB :4; /* USB Controller */
uint :4;
);
volatile word_union(*IPRG,
uint TPU0 :4; /* Timer Pulse Unit 0 */
uint TPU1 :4; /* Timer Pulse Unit 1 */
uint :4;
uint :4;
);
volatile word_union(*IPRH,
uint TPU2 :4; /* Timer Pulse Unit 2 */
uint TPU3 :4; /* Timer Pulse Unit 3 */
uint :4;
uint :4;
);
} __attribute__((packed)) mod_intc_ipc_7705_t;
/*
mod_intc_icr0_7705_t
Interrupt control register 0: configuration of the NMI interrupt.
*/
typedef struct
{
word_union(,
uint const NMIL :1; /* NMI Input Level */
uint :6;
uint NMIE :1; /* NMI Edge Select */
uint :8;
);
} __attribute__((packed, aligned(2))) mod_intc_icr0_7705_t;
/*
mod_intc_icr1_7705_t
Interrupt control register 1: general interrupt configuration.
*/
typedef struct
{
word_union(,
uint MAI :1; /* Mask All Interrupts */
uint IRQLVL :1; /* Interrupt Request Level Detect */
uint BLMSK :1; /* Enable NMI when BL is set */
uint :1;
uint IRQ5E :2; /* IRQ 5 Edge Detection */
uint IRQ4E :2;
uint IRQ3E :2;
uint IRQ2E :2;
uint IRQ1E :2;
uint IRQ0E :2;
);
} __attribute__((packed, aligned(2))) mod_intc_icr1_7705_t;
/*
mod_intc_icr2_7705_t
Interrupt control register 2: individual PINT interrupt management.
*/
typedef struct
{
word_union(,
uint PINT15 :1; /* PINT15 interrupt detection level */
uint PINT14 :1;
uint PINT13 :1;
uint PINT12 :1;
uint PINT11 :1;
uint PINT10 :1;
uint PINT9 :1;
uint PINT8 :1;
uint PINT7 :1;
uint PINT6 :1;
uint PINT5 :1;
uint PINT4 :1;
uint PINT3 :1;
uint PINT2 :1;
uint PINT1 :1;
uint PINT0 :1;
);
} __attribute__((packed, aligned(2))) mod_intc_icr2_7705_t;
/*
mod_intc_pinter_7705_t
PINTER register: individual masks for all PINT interrupts.
*/
typedef struct
{
word_union(,
uint PINT15 :1; /* PINT15 interrupt enable */
uint PINT14 :1;
uint PINT13 :1;
uint PINT12 :1;
uint PINT11 :1;
uint PINT10 :1;
uint PINT9 :1;
uint PINT8 :1;
uint PINT7 :1;
uint PINT6 :1;
uint PINT5 :1;
uint PINT4 :1;
uint PINT3 :1;
uint PINT2 :1;
uint PINT1 :1;
uint PINT0 :1;
);
} __attribute__((packed, aligned(2))) mod_intc_pinter_7705_t;
/*
mod_intc_irr0_7705_t
Interrupt Request Register 0: Indicates whether interrupt requests are
being input to the various interrupt lines. Also allows to clear the
IRQ request bits in edge-detection mode.
*/
typedef struct
{
byte_union(,
uint const PINT0_7R :1; /* PINT0-7 state */
uint const PINT8_15R :1; /* PINT8-15 state */
uint IRQ5 :1; /* IRQ5 request pin state */
uint IRQ4 :1;
uint IRQ3 :1;
uint IRQ2 :1;
uint IRQ1 :1;
uint IRQ0 :1;
);
} __attribute__((packed)) mod_intc_irr0_7705_t;
/*
mod_intc_irr1_7705_t
Interrupt Request Register 1: State of SCIF0 and DMAC requests.
*/
typedef struct
{
const byte_union(,
uint TXIOR :1; /* SCIF0 TXI interrupt */
uint :1;
uint RXI0R :1; /* SCIF0 RXI interrupt */
uint ERI0R :1; /* SCIF0 ERI interrupt */
uint DEI3R :1; /* DMAC DEI3 interrupt */
uint DEI2R :1; /* DMAC DEI2 interrupt */
uint DEI1R :1; /* DMAC DEI1 interrupt */
uint DEI0R :1; /* DMAC DEI0 interrupt */
);
} __attribute__((packed)) mod_intc_irr1_7705_t;
/*
mod_intc_irr2_7705_t
Interrupt Request Register 2: State of SCIF2 and ADC requests.
*/
typedef struct
{
const byte_union(,
uint :3;
uint ADIR :1; /* AD/C ADI interrupt */
uint TXI2R :1; /* SCIF2 TXI interrupt */
uint :1;
uint RXI2R :1; /* SCIF2 RXI interrupt */
uint ERI2R :1; /* SCIF2 ERI interrupt */
);
} __attribute__((packed, aligned(2))) mod_intc_irr2_7705_t;
/*
mod_intc_7705_t
Finally the SH7705 interrupt controller.
*/
typedef struct
{
/* All interrupt priority registers */
mod_intc_ipc_7705_t iprs;
/* Control registers */
volatile mod_intc_icr0_7705_t *ICR0;
volatile mod_intc_icr1_7705_t *ICR1;
volatile mod_intc_icr2_7705_t *ICR2;
/* PINTER register */
volatile mod_intc_pinter_7705_t *PINTER;
/* Interrupt request registers */
volatile mod_intc_irr0_7705_t *IRR0;
volatile mod_intc_irr1_7705_t *IRR1;
volatile mod_intc_irr2_7705_t *IRR2;
} __attribute__((packed)) mod_intc_7705_t;
//---
// SH7305-related definitions.
//---
/*
mod_intc_ipc_7305_t
Interrupt priority controller, same idea as the previous one.
Some of the interrupt fields of the SH7305 registers, the contents of
which have been directly taken from the SH7724 documentation, have been
left unnamed because the related peripheral modules are *very* unlikely
to even exist in the SH7305, let alone be of any use to us.
*/
typedef struct
{
word_union(IPRA,
uint TMU0_0 :4; /* TMU0 Channel 0 */
uint TMU0_1 :4; /* TMU0 Channel 1 */
uint TMU0_2 :4; /* TMU0 Channel 2 */
uint IrDA :4; /* Infrared Communication */
);
pad(2);
word_union(IPRB,
uint :4; /* JPEG Processing Unit */
uint LCDC :4; /* LCD Controller */
uint DMAC1A :4; /* Direct Memory Access Controller 1 */
uint :4; /* Blending Engine Unit */
);
pad(2);
word_union(IPRC,
uint TMU1_0 :4; /* TMU1 Channel 0 */
uint TMU1_1 :4; /* TMU1 Channel 1 */
uint TMU1_2 :4; /* TMU1 Channel 2 */
uint :4; /* Sound Processing Unit */
);
pad(2);
word_union(IPRD,
uint :4;
uint MMCIF :4; /* MultiMedia Card Interface */
uint :4;
uint :4; /* ATAPI Interface */
);
pad(2);
word_union(IPRE,
uint DMAC0A :4; /* Direct Memory Access Controller 0 */
uint :4; /* Various graphical engines */
uint SCIFA3 :4; /* SCIFA channel 3 interrupt */
uint :4; /* Video Processing Unit */
);
pad(2);
word_union(IPRF,
uint KEYSC :4; /* Key Scan Interface */
uint DMACOB :4; /* DMAC0 transfer/error info */
uint USB0_1 :4; /* USB controller */
uint CMT :4; /* Compare Match Timer */
);
pad(2);
word_union(IPRG,
uint SCIF0 :4; /* SCIF0 transfer/error info */
uint SCIF1 :4; /* SCIF1 transfer/error info */
uint SCIF2 :4; /* SCIF2 transfer/error info */
uint :4; /* Video Engine Unit */
);
pad(2);
word_union(IPRH,
uint MSIOF0 :4; /* Clock-synchronized SCIF channel 0 */
uint MSIOF1 :4; /* Clock-synchronized SCIF channel 1 */
uint :4; /* I2C Interface channel 0 */
uint :4; /* I2C Interface channel 1 */
);
pad(2);
word_union(IPRI,
uint SCIFA4 :4; /* SCIFA channel 4 interrupt */
uint :4; /* MediaRAM InterConnected Buffers */
uint :4; /* Transport Stream Interface */
uint :4; /* 2D Graphics Accelerator & ICB */
);
pad(2);
word_union(IPRJ,
uint :4; /* Capture Engine Unit */
uint :4; /* Ethernet Memory Access Controller */
uint FSI :4; /* FIFO-Buffered Serial Interface */
uint SDHI1 :4; /* SD Card Host Interface channel 1 */
);
pad(2);
word_union(IPRK,
uint RTC :4; /* Real-Time Clock */
uint DMAC1B :4; /* DMAC1 transfer/error info */
uint :4; /* MediaRAM InterConnected Buffers */
uint SDHI0 :4; /* SD Card Host Interface channel 0 */
);
pad(2);
word_union(IPRL,
uint SCIFA5 :4; /* SCIFA channel 5 interrupt */
uint :4;
uint TPU :4; /* Timer-Pulse Unit */
uint :4; /* Image Extraction DMAC */
);
pad(2);
} __attribute((packed, aligned(4))) mod_intc_ipc_7305_t;
/*
mod_intc_icr0_7305_t
Interrupt Control Register 0: Detection mode of external pins.
*/
typedef struct
{
word_union(,
uint const NMIL :1; /* NMI Input Level */
uint MAI :1; /* Mask All Interrupts */
uint :4;
uint NMIB :1; /* Enable NMI when BL is set */
uint NMIE :1; /* NMI Edge Selection */
uint :2;
uint LVLMODE :1; /* Level-Sensed IRQ Retention Mode */
uint :5;
);
} __attribute__((packed, aligned(2))) mod_intc_icr0_7305_t;
/*
mod_intc_icr1_7305_t
Interrupt Control Register 1: Manages detection of IRQ interrupts
*/
typedef struct
{
word_union(,
uint IRQ0 :2; /* IRQ0 Sense (Edge) Select */
uint IRQ1 :2;
uint IRQ2 :2;
uint IRQ3 :2;
uint IRQ4 :2;
uint IRQ5 :2;
uint IRQ6 :2;
uint IRQ7 :2;
);
} __attribute__((packed, aligned(2))) mod_intc_icr1_7305_t;
/*
mod_intc_intpri00_7305_t
Interrupt Priority 00: Priority settings for IRQ interrupts.
*/
typedef struct
{
lword_union(,
uint IRQ0 :4; /* IRQ0 Interrupt Priority */
uint IRQ1 :4;
uint IRQ2 :4;
uint IRQ3 :4;
uint IRQ4 :4;
uint IRQ5 :4;
uint IRQ6 :4;
uint IRQ7 :4;
);
} __attribute((packed, aligned(4))) mod_intc_intpri00_7305_t;
/*
mod_intc_intreq00_7305_t
Interrupt Request 00: Request information of IRQ interrupts. Each of
these bits indicates whether an interrupt is being input.
mod_intc_intmsk00_7305_t
Interrupt Mask 00: Set interrupt mask for IRQ interrupts. Writing 0 to
these bits is ignored, writing 1 masks the interrupt.
mod_intc_intmskclr00_7305_t
Interrupt Mask Clear 00: Clear interrupt mask for IRQ interrupts.
Writing 0 to these bits is ignored, writing 1 clears the mask.
*/
typedef struct
{
byte_union(,
uint IRQ0 :1;
uint IRQ1 :1;
uint IRQ2 :1;
uint IRQ3 :1;
uint IRQ4 :1;
uint IRQ5 :1;
uint IRQ6 :1;
uint IRQ7 :1;
);
} __attribute__((packed)) mod_intc_irq_7305_t;
typedef mod_intc_irq_7305_t mod_intc_intreq00_7305_t;
typedef mod_intc_irq_7305_t mod_intc_intmsk00_7305_t;
typedef mod_intc_irq_7305_t mod_intc_intmskclr00_7305_t;
/*
mod_intc_7305_t
Finally the whole interrupt controller.
*/
typedef struct
{
/* Control registers */
volatile mod_intc_icr0_7305_t *ICR0;
volatile mod_intc_icr1_7305_t *ICR1;
/* Interrupt priority registers */
volatile mod_intc_intpri00_7305_t *INTPRI00;
volatile mod_intc_ipc_7305_t *iprs;
/* Interrupt mask & mask clear registers */
volatile mod_intc_intmsk00_7305_t *INTMSK00;
// volatile mod_intc_masks_7305_t *masks;
volatile mod_intc_intmskclr00_7305_t *INTMSKCLR00;
// volatile mod_intc_masks_clear_7305_t *masks_clear;
} mod_intc_7305_t;
#endif // _MODULE_INTERRUPTS

View file

@ -298,6 +298,12 @@ void getStructure(image_t *img, structure_t *s)
s->height = img->height;
s->data = (uint8_t *)img->data;
/* TODO This is the same as
column_count = (img->width + 15) >> 5;
end = (img->width & 0x0f);
end_bytes = (end + 7) >> 3;
*/
column_count = img->width >> 5;
end = img->width & 31;
end_bytes =

View file

@ -14,8 +14,8 @@ void dimage_part(int x, int y, image_t *img, int left, int top, int width,
structure_t s;
command_t command;
int actual_width;
int format = img->format, i = 0;
int actual_width, actual_height;
int format = img->format;
if(format != format_mono && format != format_mono_alpha) return;
getStructure(img, &s);
@ -33,14 +33,17 @@ void dimage_part(int x, int y, image_t *img, int left, int top, int width,
if(left + width > s.width) width = s.width - left;
if(top + height > s.height) height = s.height - top;
if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63)
if(x + width <= 0 || x > 127 || y + height <= 0 || y > 63
|| width <= 0 || height <= 0)
return;
command.top = (y < 0) ? (top - y) : top;
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
actual_height = (y + height > 64) ? (64 - y) : height;
command.bottom = top + actual_height;
command.left = ((x < 0) ? (left - x) : left) >> 5;
actual_width = (x + width > 128) ? (128 - x) : width;
command.right = ((left + actual_width + 31) >> 5) - 1;
command.right = (left + actual_width - 1) >> 5;
command.op = bopti_op_mono;
@ -49,20 +52,14 @@ void dimage_part(int x, int y, image_t *img, int left, int top, int width,
bopti_vram = display_getCurrentVRAM();
while(format)
for(int i = 0; format; format >>= 1, i++) if(format & 1)
{
if(format & 1)
{
command.x = x - left;
command.y = y - top;
command.channel = (1 << i);
command.x = x - left;
command.y = y - top;
command.channel = (1 << i);
bopti(s.data, &s, &command);
s.data += s.layer_size;
}
format >>= 1;
i++;
bopti(s.data, &s, &command);
s.data += s.layer_size;
}
}

View file

@ -15,8 +15,8 @@ void gimage_part(int x, int y, image_t *img, int left, int top, int width,
structure_t s;
command_t command;
int actual_width;
int format = img->format, i = 0;
int actual_width, actual_height;
int format = img->format;
getStructure(img, &s);
if(width < 0) width = s.width;
@ -33,14 +33,19 @@ void gimage_part(int x, int y, image_t *img, int left, int top, int width,
if(left + width > s.width) width = s.width - left;
if(top + height > s.height) height = s.height - top;
if(x + left + width <= 0 || x > 127 || y + top + height <= 0 || y > 63)
if(x + width <= 0 || x > 127 || y + height <= 0 || y > 63
|| width <= 0 || height <= 0)
return;
// command.bottom is excluded...
command.top = (y < 0) ? (top - y) : top;
command.bottom = top + ((y + height > 64) ? (64 - y) : height);
actual_height = (y + height > 64) ? (64 - y) : height;
command.bottom = top + actual_height;
// ... but command.right is included. Great.
command.left = ((x < 0) ? (left - x) : left) >> 5;
actual_width = (x + width > 128) ? (128 - x) : width;
command.right = ((left + actual_width + 31) >> 5) - 1;
command.right = (left + actual_width - 1) >> 5;
command.op = bopti_op_gray;
@ -50,20 +55,14 @@ void gimage_part(int x, int y, image_t *img, int left, int top, int width,
bopti_v1 = gray_lightVRAM();
bopti_v2 = gray_darkVRAM();
while(format)
for(int i = 0; format; format >>= 1, i++) if(format & 1)
{
if(format & 1)
{
command.x = x - left;
command.y = y - top;
command.channel = (1 << i);
command.x = x - left;
command.y = y - top;
command.channel = (1 << i);
bopti(s.data, &s, &command);
s.data += s.layer_size;
}
format >>= 1;
i++;
bopti(s.data, &s, &command);
s.data += s.layer_size;
}
}

View file

@ -1,9 +1,10 @@
#include <internals/gint.h>
#include <modules/rtc.h>
#include <modules/interrupts.h>
#include <gint.h>
#include <timer.h>
#include <7705.h>
#include <rtc.h>
#include <7705.h>
/*
gint_reg()

View file

@ -24,28 +24,49 @@ mod_rtc_t RTC;
static void mod_init_7705(void)
{
TMU.timers[0] = (void *)0xfffffe94;
TMU.timers[1] = (void *)0xfffffea0;
TMU.timers[2] = (void *)0xfffffeac;
TMU.TSTR = (void *)0xfffffe92;
TMU.TCPR2 = (void *)0xfffffeb8;
/*
INTC._7705.iprs.IPRA = (void *)0xfffffee2;
INTC._7705.iprs.IPRB = (void *)0xfffffee4;
INTC._7705.iprs.IPRC = (void *)0xa4000016;
INTC._7705.iprs.IPRD = (void *)0xa4000018;
INTC._7705.iprs.IPRE = (void *)0xa400001a;
INTC._7705.iprs.IPRF = (void *)0xa4080000;
INTC._7705.iprs.IPRG = (void *)0xa4080002;
INTC._7705.iprs.IPRH = (void *)0xa4080004;
RTC.RCR1 = (void *)0xfffffedc;
RTC.RCR2 = (void *)0xfffffede;
RTC.time = (void *)0xfffffec0;
INTC._7705.ICR0 = (void *)0xfffffee0;
INTC._7705.ICR1 = (void *)0xa4000010;
INTC._7705.ICR2 = (void *)0xa4000012;
INTC._7705.PINTER = (void *)0xa4000014;
INTC._7705.IRR0 = (void *)0xa4000004;
INTC._7705.IRR1 = (void *)0xa4000006;
INTC._7705.IRR2 = (void *)0xa4000008;
*/
TMU.timers[0] = (void *)0xfffffe94;
TMU.timers[1] = (void *)0xfffffea0;
TMU.timers[2] = (void *)0xfffffeac;
TMU.TSTR = (void *)0xfffffe92;
TMU.TCPR2 = (void *)0xfffffeb8;
RTC.RCR1 = (void *)0xfffffedc;
RTC.RCR2 = (void *)0xfffffede;
RTC.time = (void *)0xfffffec0;
}
static void mod_init_7305(void)
{
TMU.timers[0] = (void *)0xa4490008;
TMU.timers[1] = (void *)0xa4490014;
TMU.timers[2] = (void *)0xa4490020;
TMU.TSTR = (void *)0xa4490004;
TMU.TCPR2 = NULL;
// INTC._7305.iprs = (void *)0xa4080000;
RTC.RCR1 = (void *)0xa413fedc;
RTC.RCR2 = (void *)0xa413fede;
RTC.time = (void *)0xa413fec0;
TMU.timers[0] = (void *)0xa4490008;
TMU.timers[1] = (void *)0xa4490014;
TMU.timers[2] = (void *)0xa4490020;
TMU.TSTR = (void *)0xa4490004;
TMU.TCPR2 = NULL;
RTC.RCR1 = (void *)0xa413fedc;
RTC.RCR2 = (void *)0xa413fede;
RTC.time = (void *)0xa413fec0;
}
/*

View file

@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdint.h>
static unsigned int seed = 1;
static uint32_t seed = 1;
void srand(unsigned int new_seed)
{
@ -9,7 +10,10 @@ void srand(unsigned int new_seed)
int rand(void)
{
seed = 16807 * seed;
uint32_t top = ((uint32_t)1 << 31) - 1;
while(seed >= top) seed -= top;
/* TODO Or maybe seed = (16807 * seed) % ((1 << 31) - 1); */
seed = seed * 1103515245 + 12345;
// seed = seed * 1103515245 + 12345;
return seed & 0x7fffffff;
}

View file

@ -1 +1 @@
beta-0.9-349
beta-0.9-352