mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-04-16 16:06:53 +02:00
display: add a dupdate_noint() for exceptions handlers
This commit is contained in:
parent
b0ede1d15d
commit
f8d69dd56a
6 changed files with 93 additions and 17 deletions
|
@ -152,7 +152,7 @@ typedef struct
|
||||||
gint's default font is used.
|
gint's default font is used.
|
||||||
|
|
||||||
On fx9860g, the default font is a 5x7 font very close to the system's.
|
On fx9860g, the default font is a 5x7 font very close to the system's.
|
||||||
On fxcg50, the default font is an original 10x12 font.
|
On fxcg50, the default font is an original 8x9 font.
|
||||||
|
|
||||||
@font Font to use for subsequent text rendering calls */
|
@font Font to use for subsequent text rendering calls */
|
||||||
void dfont(font_t const * font);
|
void dfont(font_t const * font);
|
||||||
|
@ -192,10 +192,22 @@ void dsize(const char *str, font_t const * font, int *w, int *h);
|
||||||
@str String to display
|
@str String to display
|
||||||
@fg Text color
|
@fg Text color
|
||||||
fx9860g: white, black, none, invert
|
fx9860g: white, black, none, invert
|
||||||
fxcg50: Any R5G6B6 color, or [color_none]
|
fxcg50: Any R5G6B6 color, or C_NONE
|
||||||
@bg Background color
|
@bg Background color
|
||||||
fx9860g: white, black, none, invert
|
fx9860g: white, black, none, invert
|
||||||
fxcg50: Any R5G6B5 color, or [color_none] */
|
fxcg50: Any R5G6B5 color, or C_NONE */
|
||||||
void dtext(int x, int y, const char *str, int fg, int bg);
|
void dtext(int x, int y, const char *str, int fg, int bg);
|
||||||
|
|
||||||
|
//---
|
||||||
|
// Advanced functions
|
||||||
|
//---
|
||||||
|
|
||||||
|
/* dupdate_noint() - Push VRAM to the display without interrupts
|
||||||
|
This function does exactly as dupdate(), but does not use interrupts and
|
||||||
|
always returns when the transfer is finished. It actively waits for the end
|
||||||
|
of the transfer and is thus bad for any general-purpose use. In fact, it is
|
||||||
|
only needed to display panic messages in exception handlers. Don't use it
|
||||||
|
unless you know precisely why you're doing it. */
|
||||||
|
void dupdate_noint(void);
|
||||||
|
|
||||||
#endif /* GINT_DISPLAY */
|
#endif /* GINT_DISPLAY */
|
||||||
|
|
|
@ -42,7 +42,6 @@ typedef enum
|
||||||
} dma_address_t;
|
} dma_address_t;
|
||||||
|
|
||||||
/* dma_transfer() - Start a data transfer on channel 0
|
/* dma_transfer() - Start a data transfer on channel 0
|
||||||
|
|
||||||
This function returns just when the transfer starts. The transfer will end
|
This function returns just when the transfer starts. The transfer will end
|
||||||
later on and the DMA will be stopped by an interrupt. Call
|
later on and the DMA will be stopped by an interrupt. Call
|
||||||
dma_transfer_wait() if you need to wait for the transfer to finish. Don't
|
dma_transfer_wait() if you need to wait for the transfer to finish. Don't
|
||||||
|
@ -59,11 +58,21 @@ void dma_transfer(dma_size_t size, uint length,
|
||||||
void *dst, dma_address_t dst_mode);
|
void *dst, dma_address_t dst_mode);
|
||||||
|
|
||||||
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish
|
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish
|
||||||
|
|
||||||
You should call this function when you need to transfer to be complete
|
You should call this function when you need to transfer to be complete
|
||||||
before continuing execution. If you are sure that the transfer is finished,
|
before continuing execution. If you are sure that the transfer is finished,
|
||||||
this is not necessary (the only way to know is to look at the DMA registers
|
this is not necessary (the only way to know is to look at the DMA registers
|
||||||
or record interrupts). */
|
or record interrupts). */
|
||||||
void dma_transfer_wait(void);
|
void dma_transfer_wait(void);
|
||||||
|
|
||||||
|
/* dma_transfer_noint() - Perform a data transfer without interrupts
|
||||||
|
This function performs a transfer much like dma_transfer(), but doesn't use
|
||||||
|
interrupts and *actively waits* for the transfer to finish, returning when
|
||||||
|
it's finished. Don't call dma_transfer_wait() after using this function.
|
||||||
|
|
||||||
|
Not using interrupts is a bad design idea for a majority of programs, and is
|
||||||
|
only ever needed to display panic messages inside exception handlers. */
|
||||||
|
void dma_transfer_noint(dma_size_t size, uint blocks,
|
||||||
|
void *src, dma_address_t src_mode,
|
||||||
|
void *dst, dma_address_t dst_mode);
|
||||||
|
|
||||||
#endif /* GINT_DMA */
|
#endif /* GINT_DMA */
|
||||||
|
|
|
@ -15,13 +15,17 @@
|
||||||
// Driver interface
|
// Driver interface
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/* dma_transfer() - Perform a data transfer */
|
/* dma_setup() - Setup the DMA in interrupt or no-interrupt mode.
|
||||||
void dma_transfer(dma_size_t size, uint blocks,
|
The first parameters are as for dma_transfer() and dma_transfer_noint(). The
|
||||||
|
last parameter indicates whether interrupts should be used.
|
||||||
|
Returns non-zero if the DMA is busy or a configuration error occurs. */
|
||||||
|
static int dma_setup(dma_size_t size, uint blocks,
|
||||||
void *src, dma_address_t src_mode,
|
void *src, dma_address_t src_mode,
|
||||||
void *dst, dma_address_t dst_mode)
|
void *dst, dma_address_t dst_mode,
|
||||||
|
int interrupts)
|
||||||
{
|
{
|
||||||
/* Safety guard: only start a transfer if there's not one running */
|
/* Safety guard: only start a transfer if there's not one running */
|
||||||
if(DMA.DMA0.CHCR.DE) return;
|
if(DMA.DMA0.CHCR.DE) return 1;
|
||||||
|
|
||||||
/* Disable DMA0 and disable the master DMA switch */
|
/* Disable DMA0 and disable the master DMA switch */
|
||||||
DMA.DMA0.CHCR.DE = 0;
|
DMA.DMA0.CHCR.DE = 0;
|
||||||
|
@ -41,7 +45,7 @@ void dma_transfer(dma_size_t size, uint blocks,
|
||||||
DMA.DMA0.CHCR.TS_10 = (size & 3);
|
DMA.DMA0.CHCR.TS_10 = (size & 3);
|
||||||
DMA.DMA0.CHCR.DM = dst_mode;
|
DMA.DMA0.CHCR.DM = dst_mode;
|
||||||
DMA.DMA0.CHCR.SM = src_mode;
|
DMA.DMA0.CHCR.SM = src_mode;
|
||||||
DMA.DMA0.CHCR.IE = 1;
|
DMA.DMA0.CHCR.IE = !!interrupts;
|
||||||
|
|
||||||
/* Prepare DMAOR by enabling the master switch and clearing the
|
/* Prepare DMAOR by enabling the master switch and clearing the
|
||||||
blocking flags. */
|
blocking flags. */
|
||||||
|
@ -49,6 +53,16 @@ void dma_transfer(dma_size_t size, uint blocks,
|
||||||
DMA.OR.AE = 0;
|
DMA.OR.AE = 0;
|
||||||
DMA.OR.NMIF = 0;
|
DMA.OR.NMIF = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dma_transfer() - Perform a data transfer */
|
||||||
|
void dma_transfer(dma_size_t size, uint blocks,
|
||||||
|
void *src, dma_address_t src_mode,
|
||||||
|
void *dst, dma_address_t dst_mode)
|
||||||
|
{
|
||||||
|
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 1)) return;
|
||||||
|
|
||||||
/* Enable channel 0, starting the DMA transfer. */
|
/* Enable channel 0, starting the DMA transfer. */
|
||||||
DMA.DMA0.CHCR.DE = 1;
|
DMA.DMA0.CHCR.DE = 1;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +74,30 @@ void dma_transfer_wait(void)
|
||||||
while(DMA.OR.DME) sleep();
|
while(DMA.OR.DME) sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dma_transfer_noint() - Perform a data transfer without interruptions */
|
||||||
|
void dma_transfer_noint(dma_size_t size, uint blocks,
|
||||||
|
void *src, dma_address_t src_mode,
|
||||||
|
void *dst, dma_address_t dst_mode)
|
||||||
|
{
|
||||||
|
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 0)) return;
|
||||||
|
|
||||||
|
/* Enable channel 0, starting the DMA transfer. */
|
||||||
|
DMA.DMA0.CHCR.DE = 1;
|
||||||
|
|
||||||
|
/* Actively wait until the transfer is finished */
|
||||||
|
while(!DMA.DMA0.CHCR.TE);
|
||||||
|
|
||||||
|
/* Disable the channel and clear the TE flag. Disable the channel first
|
||||||
|
as clearing the TE flag will allow the transfer to restart */
|
||||||
|
DMA.DMA0.CHCR.DE = 0;
|
||||||
|
DMA.DMA0.CHCR.TE = 0;
|
||||||
|
|
||||||
|
/* Clear the AE and NMIF status flags and cut the master switch */
|
||||||
|
DMA.OR.DME = 0;
|
||||||
|
DMA.OR.AE = 0;
|
||||||
|
DMA.OR.NMIF = 0;
|
||||||
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Initialization
|
// Initialization
|
||||||
//---
|
//---
|
||||||
|
|
|
@ -202,9 +202,8 @@ void r61524_win_set(uint16_t HSA, uint16_t HEA, uint16_t VSA, uint16_t VEA)
|
||||||
|
|
||||||
/* TODO: r61524: update, backlight, brightness, gamma */
|
/* TODO: r61524: update, backlight, brightness, gamma */
|
||||||
|
|
||||||
void r61524_display(uint16_t *vram, int start, int height)
|
void r61524_display(uint16_t *vram, int start, int height, int interrupts)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Move the window to the desired region, then select address 0 */
|
/* Move the window to the desired region, then select address 0 */
|
||||||
r61524_win_set(0, 395, start, start + height - 1);
|
r61524_win_set(0, 395, start, start + height - 1);
|
||||||
select(ram_address_horizontal);
|
select(ram_address_horizontal);
|
||||||
|
@ -224,10 +223,16 @@ void r61524_display(uint16_t *vram, int start, int height)
|
||||||
int blocks = 99 * (height >> 2);
|
int blocks = 99 * (height >> 2);
|
||||||
|
|
||||||
/* Now roll! */
|
/* Now roll! */
|
||||||
|
if(interrupts)
|
||||||
|
{
|
||||||
|
/* Usa a normal, interrupt-based transfer */
|
||||||
dma_transfer(DMA_32B, blocks, src, DMA_INC, dst, DMA_FIXED);
|
dma_transfer(DMA_32B, blocks, src, DMA_INC, dst, DMA_FIXED);
|
||||||
/* Wait for any previous DMA transfer to finish */
|
/* Wait for it to finish */
|
||||||
|
/* TODO: Allow r61524_display() to return early */
|
||||||
dma_transfer_wait();
|
dma_transfer_wait();
|
||||||
}
|
}
|
||||||
|
else dma_transfer_noint(DMA_32B, blocks, src, DMA_INC, dst, DMA_FIXED);
|
||||||
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Context system for this driver
|
// Context system for this driver
|
||||||
|
|
|
@ -2,8 +2,14 @@
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
//#include <gint/drivers/r61524.h>
|
//#include <gint/drivers/r61524.h>
|
||||||
|
|
||||||
/* dupdate() - push the video RAM to the display driver */
|
/* dupdate() - Push the video RAM to the display driver */
|
||||||
void dupdate(void)
|
void dupdate(void)
|
||||||
{
|
{
|
||||||
r61524_display(vram, 0, 224);
|
r61524_display(vram, 0, 224, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dupdate_noint() - Push VRAM to the display without interrupts */
|
||||||
|
void dupdate_noint(void)
|
||||||
|
{
|
||||||
|
r61524_display(vram, 0, 224, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,3 +13,9 @@ void dupdate(void)
|
||||||
{
|
{
|
||||||
t6k11_display(vram, 0, 64, 16);
|
t6k11_display(vram, 0, 64, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dupdate_noint() - Push VRAM to the display without interrupts */
|
||||||
|
void dupdate_noint(void)
|
||||||
|
{
|
||||||
|
dupdate();
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue