vxKernel/src/drivers/mpu/sh/sh7305/keysc/keysc.c

135 lines
4.7 KiB
C

#include "vhex/drivers/mpu/sh/sh7305/keysc.h"
#include "vhex/drivers/mpu/sh/sh7305/intc.h"
#include "vhex/driver.h"
/* define the private KeyScan context structure */
struct keysc_ctx {
struct __sh7305_keysc_s keysc;
uint16_t iprf;
};
/* hardware configuration call */
/* __keysc_configure() : configure the SH7305_KEYSC module */
static void __keysc_configure(struct keysc_ctx *ctx)
{
/* configure the scan control
<> enable the SH7305_KEYSC interruption (0xbe0)
<> set undocumented bit _O to 0 (Casio's configuration)
<> set undocumented bit _1 to 0 (Casio's configuration) */
ctx->keysc.KIUCNTREG.KEYIE = 1;
ctx->keysc.KIUCNTREG._0 = 0;
ctx->keysc.KIUCNTREG._1 = 0;
/* configure the key-bounce fix setting
<> enable the key-bounce "fix"
<> set the undocumented bit _0 to 0b100 (Casio's configuration)
<> set the undocumented bit _1 to 0b010 (Casio's configuration) */
ctx->keysc.KIAUTOFIXREG.KEYBE = 1;
ctx->keysc.KIAUTOFIXREG._0 = 0b100;
ctx->keysc.KIAUTOFIXREG._1 = 0b010;
/* configure the scan mode
<> set undocumented bit _O to 0 (Casio's configuration)
<> set undocumented bit _1 to 0 (Casio's configuration)
<> set undocumented bit _2 to 1 (Casio's configuration) */
ctx->keysc.KIUMODEREG._0 = 0;
ctx->keysc.KIUMODEREG._1 = 0;
ctx->keysc.KIUMODEREG._2 = 1;
/* configure the interrupt setting
This part is wierd because I cannot explain why this configurates
generate the whanted behaviour (generate interrupt when a falling
or a pressed or a rising edge is detected on any keys).
This configuration has been discovered by practicing a lot a blind
test with the hardware. */
ctx->keysc.KIUINTREG.KYCPU_IE = 0b0000010;
/* configure the time between each interrupt
<> remove time between interruption (Casio's configuration) */
ctx->keysc.KIUWSETREG.TIME = 0x05;
/* configure the interval value between each scan
<> use the Casio's configuration */
ctx->keysc.KIUINTERVALREG = 0x0098;
/* configure the key output ???? */
ctx->keysc.KYOUTDR.KYO5DT = 0b11;
ctx->keysc.KYOUTDR.KYO4DT = 0b11;
ctx->keysc.KYOUTDR.KYO3DT = 0b11;
ctx->keysc.KYOUTDR.KYO2DT = 0b11;
ctx->keysc.KYOUTDR.KYO1DT = 0b11;
ctx->keysc.KYOUTDR.KYO0DT = 0b11;
/* configure the key input setting
<> enable F1, SHIFT, ALPHA, xoT, div, 7, 4, 1, 0
<> enable F2, OPT, sqrt, log, FD, 8, 5, 2, .
<> enable F3, var, ^, ln, (, 9, 6, 3, expo
<> enable F4, menu, exit, sin, ), del, x, +, (-)
<> enable F5, <, down, cos, [,], %, -, EXE
<> enable F6, up, >, tan, ->
<> enable AC/ON */
ctx->keysc.KYINDR.KYDIR6 = 1;
ctx->keysc.KYINDR.KYDIR5 = 1;
ctx->keysc.KYINDR.KYDIR4 = 1;
ctx->keysc.KYINDR.KYDIR3 = 1;
ctx->keysc.KYINDR.KYDIR2 = 1;
ctx->keysc.KYINDR.KYDIR1 = 1;
ctx->keysc.KYINDR.KYDIR0 = 1;
/* set the interrupt level (max) */
ctx->iprf = 0b1111;
/* intall the KEYSC interupt handler */
extern void sh7305_keysc_inth(void);
sh7305_intc_install_inth(0xbe0, &sh7305_keysc_inth, 64);
}
/* __keysc_hsave() : save hardware information */
static void __keysc_hsave(struct keysc_ctx *ctx)
{
ctx->keysc.KIUCNTREG.word = SH7305_KEYSC.KIUCNTREG.word;
ctx->keysc.KIAUTOFIXREG.word = SH7305_KEYSC.KIAUTOFIXREG.word;
ctx->keysc.KIUMODEREG.word = SH7305_KEYSC.KIUMODEREG.word;
ctx->keysc.KIUINTREG.word = SH7305_KEYSC.KIUINTREG.word;
ctx->keysc.KIUWSETREG.word = SH7305_KEYSC.KIUWSETREG.word;
ctx->keysc.KIUINTERVALREG = SH7305_KEYSC.KIUINTERVALREG;
ctx->keysc.KYOUTDR.word = SH7305_KEYSC.KYOUTDR.word;
ctx->keysc.KYINDR.word = SH7305_KEYSC.KYINDR.word;
ctx->iprf = SH7305_INTC._IPRX->IPRF.KEYSC;
}
/* __keysc_hrestore() : restore hadware information */
static void __keysc_hrestore(struct keysc_ctx *ctx)
{
/* force mask the SH7305_KEYSC module, otherwise the module will crash */
SH7305_INTC._MSK->IMR5.KEYSC = 1;
SH7305_INTC._IPRX->IPRF.KEYSC = 0b0000;
/* restore registers */
SH7305_KEYSC.KIUCNTREG.word = ctx->keysc.KIUCNTREG.word;
SH7305_KEYSC.KIAUTOFIXREG.word = ctx->keysc.KIAUTOFIXREG.word;
SH7305_KEYSC.KIUMODEREG.word = ctx->keysc.KIUMODEREG.word;
SH7305_KEYSC.KIUINTREG.word = ctx->keysc.KIUINTREG.word;
SH7305_KEYSC.KIUWSETREG.word = ctx->keysc.KIUWSETREG.word;
SH7305_KEYSC.KIUINTERVALREG = ctx->keysc.KIUINTERVALREG;
SH7305_KEYSC.KYOUTDR.word = ctx->keysc.KYOUTDR.word;
SH7305_KEYSC.KYINDR.word = ctx->keysc.KYINDR.word;
/* enable keysc interuption */
SH7305_INTC._IPRX->IPRF.KEYSC = ctx->iprf;
SH7305_INTC._MSKCLR->IMR5.KEYSC = 1;
}
/* declare the KEYSC driver */
struct vhex_driver drv_keysc = {
.name = "KEYSC",
.hsave = (void*)&__keysc_hsave,
.hrestore = (void*)&__keysc_hrestore,
.configure = (void*)&__keysc_configure,
.state_size = sizeof(struct keysc_ctx)
};
VHEX_DECLARE_DRIVER(03, drv_keysc);