キースキャン処理
んー、もしかして row と column って逆なのかな。チャージの意味も逆かもしれないなぁ。
バグがあったので修正。
typedef int key_scan_code_t; #define KS_POWER 0xad /* Power key */ #define CS2_ADDRESS 0x08000000 #define KBDCOL_L (CS2_ADDRESS + 0x00) /* Write */ #define KBDCOL_U (CS2_ADDRESS + 0x04) /* Write */ #define KBDCHARGE (CS2_ADDRESS + 0x08) /* Write */ #define KBDDATA (CS2_ADDRESS + 0x08) /* Read */ #define MAXPRESS 10 /* キー同時最大押下数 */ #define NCOLUMN 12 /* キーマトリックス桁数 */ #define NROW 7 /* キーマトリックス行数 */ #define KEYWAIT 10 /* wait (ms?) (OS Timer のカウンタで KEYWAIT * 4000 分待つ) */ /* * キースキャンコードテーブル * * 0x30d0-0x30e8: copy 8192 * 16 (=128Ki) byte from address 0(ROM) to 0xa00a0000(SDRAM). * キースキャンコードのテーブルは SDRAM 上では 0xa00a1758 に存在するので、 * ROM 上のアドレスに変換すると 0x1758 になる。 */ static const key_scan_code_t key_scan_code_tbl[NCOLUMN][NROW] = { { 0x84, 0x31, 0x33, 0x35, 0x36, 0x37, 0x39, }, { 0x30, 0x08, 0x00, 0xdb, 0xd6, 0x00, 0x32, }, { 0x34, 0x52, 0x59, 0x38, 0x49, 0x4f, 0x50, }, { 0x00, 0xd8, 0xd7, 0x09, 0x51, 0x45, 0x54, }, { 0x47, 0x55, 0x4a, 0x4b, 0x00, 0x00, 0x00, }, { 0x00, 0x00, 0x57, 0x53, 0x46, 0x56, 0x48, }, { 0x4d, 0x4c, 0x00, 0x00, 0xd5, 0x00, 0xde, }, { 0x41, 0x44, 0x43, 0x42, 0x4e, 0x2e, 0x00, }, { 0x0d, 0x00, 0xdc, 0x00, 0xab, 0x5a, 0x58, }, { 0x2d, 0x20, 0x2f, 0x00, 0x8b, 0x00, 0x00, }, { 0xd9, 0x85, 0xdd, 0xcf, 0x00, 0xa7, 0xa8, }, { 0x2c, 0x8c, 0x8a, 0x8d, 0x00, 0xda, 0x00, }, }; /** * \brief * 押下キーを検出して、キーバッファに押下キースキャンコードを格納する。 * * キーマトリックスを走査し押下キーを検出して、keybuf に押下キーの * スキャンコードを格納する。<br> * また、キーマトリックス走査の他に GPIO<95> のレベルを取得し Hi レベルで * あれば電源キーのスキャンコードを keybuf に格納する。<br> * 押下キーが nkeybuf に指定された値、もしくはコンパイル時に指定された値 * (MAXPRESS) よりも多く検出された場合、キー押下は無かったものとして扱われる。 * * \param nkeybuf キーバッファ数 * \param keybuf キースキャンコードを格納するメモリ領域へのポインタ。 * 呼び出し側で nkeybuf 個数分のメモリを確保しなければならない。 * \return 押下キー数 */ int keyscan(int nkeybuf, key_scan_code_t *keybuf) { struct { int col; int row; } key[MAXPRESS]; key_scan_code_t *keybufp; int row, col; int npress; int data; int powerkey; int i; _ASSERT(0 < nkeybuf); _ASSERT(keybuf != NULL); if (nkeybuf > MAXPRESS) nkeybuf = MAXPRESS; /* get GPIO<95> level sense (maybe check power-key pressed...) */ powerkey = GPIO_GPLR(95); npress = 0; for (col = 0; col < NCOLUMN; col++) { /* deselect column# and charge */ CSR_WRITE1(KBDCOL_L, 0); CSR_WRITE1(KBDCOL_U, 0); CSR_WRITE1(KBDCHARGE, 1); delay(KEYWAIT); /* discharge & select scan column# */ CSR_WRITE1(KBDCHARGE, 0); if (col < 8/*NCHAR_BIT*/) { CSR_WRITE1(KBDCOL_L, 1U << col); CSR_WRITE1(KBDCOL_U, 0); } else { CSR_WRITE1(KBDCOL_L, 0); CSR_WRITE1(KBDCOL_U, 1U << (col - 8)); } delay(KEYWAIT); for (row = 0; row < NROW; row++) { CSR_WRITE1(KBDCHARGE, 0); data = CSR_READ1(KBDDATA); if ((data >> row) & 1) { /* detect key press */ if (npress >= MAXPRESS) { npress = 0; goto nokeypress; } key[npress].col = col; key[npress].row = row; npress++; } } } if (npress >= nkeybuf) { npress = 0; goto nokeypress; } keybufp = keybuf; if (powerkey) { if (npress + 1 >= nkeybuf) { npress = 0; goto nokeypress; } keybufp++; } /* column/row -> key scan code */ for (i = 0; i < npress; i++) { keybufp[i] = key_scan_code_tbl[key[i].col][key[i].row]; } if (powerkey) { keybuf[0] = KS_POWER; npress++; } nokeypress: /* deselect column# and charge */ CSR_WRITE1(KBDCOL_L, 0); CSR_WRITE1(KBDCOL_U, 0); CSR_WRITE1(KBDCHARGE, 1); delay(KEYWAIT); /* discharge for power management */ CSR_WRITE1(KBDCHARGE, 0); return npress; }