iokbd keysc: space optimizations for SH3

* Reduce the keyboard queue size from 64 to 32, which is more than
  enough even for real-time games with multiple key presses.
* Pack the driver_event_t structure of the keyboard driver to make it 4
  bytes rather than 6 bytes. Combined with the previous item, this saves
  256 bytes off the BSS section (which is 3% of the SH3's static RAM).
* As part of a debugging attempt, updated the watchdog delay code in
  iokbd_delay() to make it usable in the current version of gint.
* Restored port registers more aggressively in iokbd_row().
This commit is contained in:
Lephe 2020-07-08 20:01:58 +02:00
parent 03715344a4
commit a99bffe7f4
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
4 changed files with 35 additions and 28 deletions

View file

@ -117,12 +117,12 @@ enum
/* Size of the buffer event queue, can be customized using gint's configure /* Size of the buffer event queue, can be customized using gint's configure
script before compiling the library. Better be a power of 2. */ script before compiling the library. Better be a power of 2. */
#ifndef KEYBOARD_QUEUE_SIZE #ifndef KEYBOARD_QUEUE_SIZE
#define KEYBOARD_QUEUE_SIZE 64 #define KEYBOARD_QUEUE_SIZE 32
#endif #endif
/* Keyboard frequency analysis, must be at least 64 for the keyboard to work, /* Keyboard frequency analysis, must be at least 64 for the keyboard to work,
and at most 32768 for the extra timer to support it. Better if a power of 2. and at most 32768 for the extra timer to support it. Better if a power of 2.
TODO: Add a configure or runtime setting for KEYBOARD_SCAN_FREQUENCY */ TODO: Add a runtime setting for KEYBOARD_SCAN_FREQUENCY */
#ifndef KEYBOARD_SCAN_FREQUENCY #ifndef KEYBOARD_SCAN_FREQUENCY
#define KEYBOARD_SCAN_FREQUENCY 128 #define KEYBOARD_SCAN_FREQUENCY 128
#endif #endif

View file

@ -25,7 +25,7 @@ GINLINE const tlb_data_t *tlb_data(uint way, uint E)
return (void *)addr; return (void *)addr;
} }
/* tlb_mapped_memort() - count amount of mapped memory */ /* tlb_mapped_memory() - count amount of mapped memory */
void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram) void tlb_mapped_memory(uint32_t *p_rom, uint32_t *p_ram)
{ {
uint32_t rom = 0, ram = 0; uint32_t rom = 0, ram = 0;

View file

@ -21,26 +21,30 @@ static void iokbd_delay(void)
); );
#if 0 #if 0
/* Watchdog delay version */ uint8_t volatile *WTCSRr = (void *)0xffffff86;
uint16_t volatile *WTCSRw = (void *)0xffffff86;
uint16_t volatile *WTCNTw = (void *)0xffffff84;
/* Watchdog delay version, each of the values between this and 0xff
account for 256 clock cycles on Pphi. This is roughly equivalent to
2048 nop, lasting ~70 µs */
const int delay = 0xf4; const int delay = 0xf4;
/* Disable the watchdog timer interrupt and reset configuration */ /* Disable the watchdog timer interrupt and reset configuration */
INTC.IPRB.BIT._WDT = 0; *WTCSRw = 0xa500;
WDT.WTCSR.WRITE = 0xa500;
/* Set the delay, input on Pphi / 256 and start counting */ /* Set the delay, input on Pphi / 256 and start counting */
WDT.WTCNT.WRITE = 0x5a00 | (delay & 0xff); *WTCNTw = 0x5a00 | (delay & 0xff);
WDT.WTCSR.WRITE = 0xa505; *WTCSRw = 0xa505;
WDT.WTCSR.WRITE = 0xa585; *WTCSRw = 0xa585;
/* Actively wait for overflow, then clear the interrupt flag */ /* Actively wait for overflow, then clear the interrupt flag */
while((WDT.WTCSR.READ.BYTE & 0x08) == 0); while((*WTCSRr & 0x08) == 0);
WDT.WTCSR.WRITE = 0xa500 | (WDT.WTCSR.READ.BYTE & 0xf7); *WTCSRw = 0xa500 | (*WTCSRr & 0xf7);
/* Reset configuration, counter, and re-enabled interrupt */ /* Reset configuration, counter, and re-enabled interrupt */
WDT.WTCSR.WRITE = 0xa500; *WTCSRw = 0xa500;
WDT.WTCSR.WRITE = 0x5a00; *WTCNTw = 0x5a00;
INTC.IPRB.BIT._WDT = GINT_INTP_WDT;
#endif #endif
} }
@ -52,6 +56,11 @@ uint8_t iokbd_row(int row)
if((unsigned)row > 9) return 0x00; if((unsigned)row > 9) return 0x00;
row ^= 1; row ^= 1;
int orig_PBCR = PFC.PBCR;
int orig_PMCR = PFC.PMCR;
int orig_PBDR = PFC.PBDR;
int orig_PMDR = PFC.PMDR;
/* This will enable output (01) on @row, input (10) everywhere else */ /* This will enable output (01) on @row, input (10) everywhere else */
uint16_t ctrl_mask = 0x0003 << ((row & 7) * 2); uint16_t ctrl_mask = 0x0003 << ((row & 7) * 2);
/* Enable output (0) on @row, input (1) everywhere else */ /* Enable output (0) on @row, input (1) everywhere else */
@ -81,25 +90,23 @@ uint8_t iokbd_row(int row)
/* Set @row to 0, everything else to 1 */ /* Set @row to 0, everything else to 1 */
PFC.PBDR = 0xff; PFC.PBDR = 0xff;
PFC.PMDR = PFC.PMDR & data_mask; PFC.PMDR = PFC.PMDR & data_mask;
iokbd_delay();
} }
/* Now read the input data from the keyboard! */ /* Now read the input data from the keyboard! */
uint8_t input = ~PFC.PADR; uint8_t input = ~PFC.PADR;
iokbd_delay(); iokbd_delay();
/* Reset the port configuration. I don't know why the intermediate step /* Reset the port configuration */
is necessary; refer to SimLo's documentation. */ PFC.PBCR = orig_PBCR;
PFC.PBCR = 0xaaaa; PFC.PMCR = orig_PMCR;
PFC.PMCR = (PFC.PMCR & 0xff00) | 0x00aa;
iokbd_delay();
PFC.PBCR = 0x5555;
PFC.PMCR = (PFC.PMCR & 0xff00) | 0x0055;
iokbd_delay(); iokbd_delay();
/* Now also reset the data registers. This was forgotten from SimLo's /* Now also reset the data registers. This was forgotten from SimLo's
CheckKeyRow() and blows up everything. */ CheckKeyRow() and blows up everything. */
PFC.PBDR = 0x00; PFC.PBDR = orig_PBDR;
PFC.PMDR = PFC.PMDR & 0xf0; PFC.PMDR = orig_PMDR;
iokbd_delay();
return input; return input;
} }

View file

@ -38,9 +38,9 @@ GDATA static uint8_t current[12] = { 0 };
typedef struct typedef struct
{ {
uint16_t time; /* Locally unique time identifier */ uint16_t time; /* Locally unique time identifier */
uint8_t row; /* Row number */
uint8_t changed; /* Keys that changed state */ uint8_t changed; /* Keys that changed state */
uint8_t kind; /* Type of change, either KEYEV_DOWN or KEYEV_UP */ uint8_t row :4; /* Row number */
uint8_t kind :4; /* Type of change, either KEYEV_DOWN or KEYEV_UP */
} driver_event_t; } driver_event_t;
@ -103,7 +103,7 @@ static void keysc_frame(void)
if(!diff) continue; if(!diff) continue;
/* Update internal status if the event could be pushed */ /* Update internal status if the event could be pushed */
driver_event_t ev = { time, row, diff, KEYEV_UP }; driver_event_t ev = { time, diff, row, KEYEV_UP };
if(!buffer_push(ev)) state[row] &= scan[row]; if(!buffer_push(ev)) state[row] &= scan[row];
} }
for(int row = 0; row < 12; row++) for(int row = 0; row < 12; row++)
@ -111,7 +111,7 @@ static void keysc_frame(void)
int diff = scan[row] & ~state[row]; int diff = scan[row] & ~state[row];
if(!diff) continue; if(!diff) continue;
driver_event_t ev = { time, row, diff, KEYEV_DOWN }; driver_event_t ev = { time, diff, row, KEYEV_DOWN };
if(!buffer_push(ev)) state[row] |= scan[row]; if(!buffer_push(ev)) state[row] |= scan[row];
} }
} }