#include #include #include /* 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);