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
Signed by: Lephenixnoir
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
script before compiling the library. Better be a power of 2. */
#ifndef KEYBOARD_QUEUE_SIZE
#define KEYBOARD_QUEUE_SIZE 64
#define KEYBOARD_QUEUE_SIZE 32
#endif
/* 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.
TODO: Add a configure or runtime setting for KEYBOARD_SCAN_FREQUENCY */
TODO: Add a runtime setting for KEYBOARD_SCAN_FREQUENCY */
#ifndef KEYBOARD_SCAN_FREQUENCY
#define KEYBOARD_SCAN_FREQUENCY 128
#endif

View File

@ -21,11 +21,11 @@ GINLINE const tlb_addr_t *tlb_addr(uint way, uint E)
/* tlb_data() - get the P4 address of a TLB data entry */
GINLINE const tlb_data_t *tlb_data(uint way, uint E)
{
uint32_t addr = 0xf3000000 | (E << 12) | (way << 8);
uint32_t addr = 0xf3000000 | (E << 12) | (way << 8);
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)
{
uint32_t rom = 0, ram = 0;

View File

@ -21,26 +21,30 @@ static void iokbd_delay(void)
);
#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;
/* Disable the watchdog timer interrupt and reset configuration */
INTC.IPRB.BIT._WDT = 0;
WDT.WTCSR.WRITE = 0xa500;
*WTCSRw = 0xa500;
/* Set the delay, input on Pphi / 256 and start counting */
WDT.WTCNT.WRITE = 0x5a00 | (delay & 0xff);
WDT.WTCSR.WRITE = 0xa505;
WDT.WTCSR.WRITE = 0xa585;
*WTCNTw = 0x5a00 | (delay & 0xff);
*WTCSRw = 0xa505;
*WTCSRw = 0xa585;
/* Actively wait for overflow, then clear the interrupt flag */
while((WDT.WTCSR.READ.BYTE & 0x08) == 0);
WDT.WTCSR.WRITE = 0xa500 | (WDT.WTCSR.READ.BYTE & 0xf7);
while((*WTCSRr & 0x08) == 0);
*WTCSRw = 0xa500 | (*WTCSRr & 0xf7);
/* Reset configuration, counter, and re-enabled interrupt */
WDT.WTCSR.WRITE = 0xa500;
WDT.WTCSR.WRITE = 0x5a00;
INTC.IPRB.BIT._WDT = GINT_INTP_WDT;
*WTCSRw = 0xa500;
*WTCNTw = 0x5a00;
#endif
}
@ -52,6 +56,11 @@ uint8_t iokbd_row(int row)
if((unsigned)row > 9) return 0x00;
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 */
uint16_t ctrl_mask = 0x0003 << ((row & 7) * 2);
/* 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 */
PFC.PBDR = 0xff;
PFC.PMDR = PFC.PMDR & data_mask;
iokbd_delay();
}
/* Now read the input data from the keyboard! */
uint8_t input = ~PFC.PADR;
iokbd_delay();
/* Reset the port configuration. I don't know why the intermediate step
is necessary; refer to SimLo's documentation. */
PFC.PBCR = 0xaaaa;
PFC.PMCR = (PFC.PMCR & 0xff00) | 0x00aa;
iokbd_delay();
PFC.PBCR = 0x5555;
PFC.PMCR = (PFC.PMCR & 0xff00) | 0x0055;
/* Reset the port configuration */
PFC.PBCR = orig_PBCR;
PFC.PMCR = orig_PMCR;
iokbd_delay();
/* Now also reset the data registers. This was forgotten from SimLo's
CheckKeyRow() and blows up everything. */
PFC.PBDR = 0x00;
PFC.PMDR = PFC.PMDR & 0xf0;
PFC.PBDR = orig_PBDR;
PFC.PMDR = orig_PMDR;
iokbd_delay();
return input;
}

View File

@ -38,9 +38,9 @@ GDATA static uint8_t current[12] = { 0 };
typedef struct
{
uint16_t time; /* Locally unique time identifier */
uint8_t row; /* Row number */
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;
@ -103,7 +103,7 @@ static void keysc_frame(void)
if(!diff) continue;
/* 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];
}
for(int row = 0; row < 12; row++)
@ -111,7 +111,7 @@ static void keysc_frame(void)
int diff = scan[row] & ~state[row];
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];
}
}