最近開ける場面ではノート開いてコーディングしてる気がします。
使ってる電車が基本座れないくらい利用客が多いのですが
それでも開けるのは LOOX U の小ささのお陰とも言えます。
お絵描き学習用に買ったはずなのにいつのまにか、
グラフィックアプリ以外にインストールしてるものが
開発環境とその補助ツールのみという構成になっていました。
劣悪な初期型キーボードな固体なのでコーディングに不便はありますが
慣れ親しんでる言語でなら(ソラで書けば)なんとか
入力に対するストレスは抑えられる感じです。
閑話休題。
演算と描画の分離を終えました。
有限状態機械(FSM)でキーパッド状態を表し、
入力により状態遷移が行われます。
その下層に位置する演算部(Keypad)と描画部(Keycur)が処理の実態です。
挙動は一昨日思い付きで GMC4GBA に似せてしまいました。
似せずに被ってた箇所もあれば、違う挙動をする部分も勿論あります。
コードは一切参照してないので似てたら全くの偶然ということで。
K PORT を(劣化)シミュレートしてます。
CPUがKA命令で値を見る際は K PORT 上の入力エッジを拾い、
入力があったらGet関数で数値データを取る、という風に扱うような想定の作りです。
内部変数では入力値をビットで持ってますが、CPU処理の負担を緩和するという意味で、
変換済みの数値データ(数字キーデータ)を取得することを可能としています。
リソースが用意でき次第、コンソールとの置き換えを想定して組んではいますが、
実際のところ足踏みを揃えてみないと見えてこない問題もあるかも知れませんので
暫定バージョンという位置付けでお願いします。
main.c
/*--------------------------------------------------------------------------------- Key FSM test version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #include <nds.h> #include <stdio.h> #include "Key.h" #include "Keypad.h"//KPORT データの取得確認用にインクルード //--------------------------------------------------------------------------------- int main(void) { //--------------------------------------------------------------------------------- consoleDemoInit(); Key_Init(); while(1) { swiWaitForVBlank(); scanKeys(); Key_Update(); printf("\x01b[20;0H%08X", Keypad_GetKeypadValue()); } } //---------------------------------------------------------------------------------
Key.h
/*--------------------------------------------------------------------------------- Key FSM header version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #ifndef _KEY_H_ #define _KEY_H_ #ifdef __cplusplus extern "C" { #endif void Key_Init(void); void Key_Update(void); void Key_Clear(void); #ifdef __cplusplus } #endif #endif // _KEY_H_
KeyPrivate.h
/*--------------------------------------------------------------------------------- Key FSM private header version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #ifndef _KEY_PRIVATE_H_ #define _KEY_PRIVATE_H_ #include <nds/ndstypes.h> #include <nds/arm9/input.h> #include "Keypad.h" typedef enum{ KEY_FSM_DOWN, KEY_FSM_HELD, KEY_FSM_UP, KEY_FSM_MOVE, KEY_FSM_NULL }KEY_FSM; typedef struct{ u16 act; }KeyFsm; #ifdef __cplusplus extern "C" { #endif //遷移トリガー bool key_IsDown(void); bool key_IsHeld(void); bool key_IsUp(void); bool key_IsMove(void); void key_CheckState(void); //振る舞い void key_Null(void); void key_Move(void); void key_Down(void); void key_Up(void); void key_DoAction(void); #ifdef __cplusplus } #endif #endif // _KEY_PRIVATE_H_
Key.c
/*--------------------------------------------------------------------------------- Key FSM routine version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #include "KeyPrivate.h" static KeyFsm st_key_fsm = {KEY_FSM_NULL}; //--------------------------------------------------------------------------------- bool key_IsDown(void) { //--------------------------------------------------------------------------------- return (keysDown() & KEY_A) ? true:false; } //--------------------------------------------------------------------------------- bool key_IsHeld(void) { //--------------------------------------------------------------------------------- return (keysHeld() & KEY_A) ? true:false; } //--------------------------------------------------------------------------------- bool key_IsUp(void) { //--------------------------------------------------------------------------------- return (keysUp() & KEY_A) ? true:false; } //--------------------------------------------------------------------------------- bool key_IsMove(void) { //--------------------------------------------------------------------------------- bool ans = false; if((keysDown() & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) || (keysHeld() & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT))){ ans = true; } return ans; } //--------------------------------------------------------------------------------- void key_CheckState(void) { //--------------------------------------------------------------------------------- if(key_IsDown()){ st_key_fsm.act = KEY_FSM_DOWN; }else if(key_IsHeld()){ st_key_fsm.act = KEY_FSM_HELD; }else if(key_IsUp()){ st_key_fsm.act = KEY_FSM_UP; }else if(key_IsMove()){ st_key_fsm.act = KEY_FSM_MOVE; }else{ // key_IsNull() st_key_fsm.act = KEY_FSM_NULL; } } //--------------------------------------------------------------------------------- void key_Down(void) { //--------------------------------------------------------------------------------- Keypad_Send(); } //--------------------------------------------------------------------------------- void key_Held(void) { //--------------------------------------------------------------------------------- Keypad_Send(); } //--------------------------------------------------------------------------------- void key_Up(void) { //--------------------------------------------------------------------------------- Keypad_Stop(); } //--------------------------------------------------------------------------------- void key_Move(void) { //--------------------------------------------------------------------------------- Keycur_Move(); } //--------------------------------------------------------------------------------- void key_Null(void) { //--------------------------------------------------------------------------------- Keypad_Stop(); } //--------------------------------------------------------------------------------- void key_DoAction(void) { //--------------------------------------------------------------------------------- switch(st_key_fsm.act){ case KEY_FSM_DOWN: key_Down(); break; case KEY_FSM_HELD: key_Held(); break; case KEY_FSM_UP: key_Up(); break; case KEY_FSM_MOVE: key_Move(); break; default: // KEY_FSM_NULL key_Null(); break; } } //--------------------------------------------------------------------------------- void Key_Update(void) { //--------------------------------------------------------------------------------- key_CheckState(); key_DoAction(); } //--------------------------------------------------------------------------------- void Key_Clear(void) { //--------------------------------------------------------------------------------- Keypad_Clear(); keysSetRepeat(20, 10); } //--------------------------------------------------------------------------------- void Key_Init(void) { //--------------------------------------------------------------------------------- Keycur_Init(); Key_Clear(); } //---------------------------------------------------------------------------------
Keypad.h
/*--------------------------------------------------------------------------------- Keypad module header version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #ifndef _KEYPAD_H_ #define _KEYPAD_H_ #include <nds/ndstypes.h> #ifdef __cplusplus extern "C" { #endif //画面初期化用、描画関数 void Keycur_Init(void); //Key FSM 用、状態動作関数 void Keypad_Send(void); void Keypad_Stop(void); void Keycur_Move(void); void Keypad_Clear(void); //CPU・モニタ用、関数 // キーパッド入力状態、取得関数 bool Keypad_IsKeypadDown(void); bool Keypad_IsKeypadHeld(void); bool Keypad_IsKeypadUp(void); //キーパッド入力データ(数字キーデータ)取得関数 // 入力があった場合、入力データ(ビットデータでなく数値データ)を得る関数 // 数字キーはニブル値、ファンクションキーはバイト値、入力無し(NULL)はFFが返る。 u8 Keypad_GetKeypadValue(void); #ifdef __cplusplus } #endif #endif // _KEYPAD_H_
KeypadPrivate.h
/*--------------------------------------------------------------------------------- Keypad module private header version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #ifndef _KEYPAD_PRIVATE_H_ #define _KEYPAD_PRIVATE_H_ #include "Keypad.h" #include <nds/arm9/input.h> #include <stdio.h> typedef enum{ // keypad idx min KEYPAD_MIN_X = 0, KEYPAD_MIN_Y = 0, // keypad idx max KEYPAD_MAX_X = 4, KEYPAD_MAX_Y = 3, // keypad array size KEYPAD_SIZE_X = 5, KEYPAD_SIZE_Y = 4, // keypad def pos KEYPAD_DEF_X = 4, KEYPAD_DEF_Y = 4 }KEYPAD_STAT; #ifdef __cplusplus extern "C" { #endif int keycur_GetCursorX(void); int keycur_GetCursorY(void); void keycur_ClearCursor(void); #ifdef __cplusplus } #endif #endif // _KEYPAD_PRIVATE_H_
Keypad.c
/*--------------------------------------------------------------------------------- Keypad module routine version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #include "KeypadPrivate.h" //--------------------------------------------------------------------------------- typedef enum{ KEYPAD_0 = 0x00, KEYPAD_1 = 0x01, KEYPAD_2 = 0x02, KEYPAD_3 = 0x03, KEYPAD_4 = 0x04, KEYPAD_5 = 0x05, KEYPAD_6 = 0x06, KEYPAD_7 = 0x07, KEYPAD_8 = 0x08, KEYPAD_9 = 0x09, KEYPAD_A = 0x0A, KEYPAD_B = 0x0B, KEYPAD_C = 0x0C, KEYPAD_D = 0x0D, KEYPAD_E = 0x0E, KEYPAD_F = 0x0F, KEYPAD_A_SET = 0x10, KEYPAD_INCR = 0x11, KEYPAD_RUN = 0x12, KEYPAD_RESET = 0x13, KEYPAD_NULL = 0xFF }KEYPAD_VAL; const static u8 keypad_matrix[KEYPAD_SIZE_Y][KEYPAD_SIZE_X] = { {KEYPAD_C, KEYPAD_D, KEYPAD_E, KEYPAD_F, KEYPAD_A_SET}, {KEYPAD_8, KEYPAD_9, KEYPAD_A, KEYPAD_B, KEYPAD_INCR}, {KEYPAD_4, KEYPAD_5, KEYPAD_6, KEYPAD_7, KEYPAD_RUN}, {KEYPAD_0, KEYPAD_1, KEYPAD_2, KEYPAD_3, KEYPAD_RESET} }; /* kport 内部ビットデータ構造 実機は 1ニブル 5ポート で入力を得てるようなので(回路図を見る限りでは)、 近い構造で入力データを持つものとする。 u8型、5配列としなかったのは扱いやすさの為。 u32 bit n 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 kport n 00 01 02 03 04 bit n 03 02 01 00 03 02 01 00 03 02 01 00 03 02 01 00 03 02 01 00 keypad 00 04 08 0C 01 05 09 0D 02 06 0A 0E 03 07 0B 0F AS IN RN RS */ //#define BIT(n) (1 << (n)) typedef enum{ KPORT_NULL = 0, KPORT_A_SET = BIT(0), KPORT_INCR = BIT(1), KPORT_RUN = BIT(2), KPORT_RESET = BIT(3), KPORT_F = BIT(4), KPORT_B = BIT(5), KPORT_7 = BIT(6), KPORT_3 = BIT(7), KPORT_E = BIT(8), KPORT_A = BIT(9), KPORT_6 = BIT(10), KPORT_2 = BIT(11), KPORT_D = BIT(12), KPORT_9 = BIT(13), KPORT_5 = BIT(14), KPORT_1 = BIT(15), KPORT_C = BIT(16), KPORT_8 = BIT(17), KPORT_4 = BIT(18), KPORT_0 = BIT(19) }KPORT_VAL; const static u32 kport_matrix[KEYPAD_SIZE_Y][KEYPAD_SIZE_X] = { {KPORT_C, KPORT_D, KPORT_E, KPORT_F, KPORT_A_SET}, {KPORT_8, KPORT_9, KPORT_A, KPORT_B, KPORT_INCR}, {KPORT_4, KPORT_5, KPORT_6, KPORT_7, KPORT_RUN}, {KPORT_0, KPORT_1, KPORT_2, KPORT_3, KPORT_RESET} }; typedef struct{ u32 kport_val; u32 kport_old; }KeypadStatus; static KeypadStatus st_keypad = {KPORT_NULL, KPORT_NULL}; u32 keypad_GetKPortValue(void); u32 keypad_GetKPortOld(void); void keypad_SetKPortValue(u32 kport_val); void keypad_ClearKPortValue(void); //--------------------------------------------------------------------------------- u32 keypad_GetKPortValue(void){ //--------------------------------------------------------------------------------- return st_keypad.kport_val; } //--------------------------------------------------------------------------------- u32 keypad_GetKPortOld(void){ //--------------------------------------------------------------------------------- return st_keypad.kport_old; } //--------------------------------------------------------------------------------- void keypad_SetKPortValue(u32 kport_val){ //--------------------------------------------------------------------------------- st_keypad.kport_old = st_keypad.kport_val; st_keypad.kport_val = kport_val; } //--------------------------------------------------------------------------------- void keypad_ClearKPortValue(void){ //--------------------------------------------------------------------------------- keypad_SetKPortValue(KPORT_NULL); keypad_SetKPortValue(KPORT_NULL); } //--------------------------------------------------------------------------------- bool Keypad_IsKeypadDown(void){ //--------------------------------------------------------------------------------- return ((keypad_GetKPortValue()) & (~keypad_GetKPortOld())) ? true:false; } //--------------------------------------------------------------------------------- bool Keypad_IsKeypadHeld(void){ //--------------------------------------------------------------------------------- return ((keypad_GetKPortValue()) & (keypad_GetKPortOld())) ? true:false; } //--------------------------------------------------------------------------------- bool Keypad_IsKeypadUp(void){ //--------------------------------------------------------------------------------- return ((~keypad_GetKPortValue()) & (keypad_GetKPortOld())) ? true:false; } //--------------------------------------------------------------------------------- u8 Keypad_GetKeypadValue(void){ //--------------------------------------------------------------------------------- u8 keypad_val; u32 kport_val; kport_val = keypad_GetKPortValue(); switch(kport_val){ case KPORT_0: keypad_val = KEYPAD_0; break; case KPORT_1: keypad_val = KEYPAD_1; break; case KPORT_2: keypad_val = KEYPAD_2; break; case KPORT_3: keypad_val = KEYPAD_3; break; case KPORT_4: keypad_val = KEYPAD_4; break; case KPORT_5: keypad_val = KEYPAD_5; break; case KPORT_6: keypad_val = KEYPAD_6; break; case KPORT_7: keypad_val = KEYPAD_7; break; case KPORT_8: keypad_val = KEYPAD_8; break; case KPORT_9: keypad_val = KEYPAD_9; break; case KPORT_A: keypad_val = KEYPAD_A; break; case KPORT_B: keypad_val = KEYPAD_B; break; case KPORT_C: keypad_val = KEYPAD_C; break; case KPORT_D: keypad_val = KEYPAD_D; break; case KPORT_E: keypad_val = KEYPAD_E; break; case KPORT_F: keypad_val = KEYPAD_F; break; case KPORT_A_SET: keypad_val = KEYPAD_A_SET; break; case KPORT_INCR: keypad_val = KEYPAD_INCR; break; case KPORT_RUN: keypad_val = KEYPAD_RUN; break; case KPORT_RESET: keypad_val = KEYPAD_RESET; break; default: keypad_val = KEYPAD_NULL; break; } return keypad_val; } //--------------------------------------------------------------------------------- void Keypad_Clear(void){ //--------------------------------------------------------------------------------- keypad_ClearKPortValue(); keycur_ClearCursor(); } //--------------------------------------------------------------------------------- void Keypad_Send(void){ //--------------------------------------------------------------------------------- keypad_SetKPortValue(kport_matrix[keycur_GetCursorY() - KEYPAD_DEF_Y][keycur_GetCursorX() - KEYPAD_DEF_X]); } //--------------------------------------------------------------------------------- void Keypad_Stop(void){ //--------------------------------------------------------------------------------- keypad_SetKPortValue(KPORT_NULL); } //---------------------------------------------------------------------------------
Keycur.c
/*--------------------------------------------------------------------------------- Keycur module routine version 0.01 Oct 16, 2009 (C)2009 REGEKATSU ---------------------------------------------------------------------------------*/ #include "KeypadPrivate.h" //--------------------------------------------------------------------------------- typedef enum{ // keypad str pos KEYSTR_DEF_X = 2, KEYSTR_DEF_Y = 18, // cur def pos KEYCUR_DEF_X = 0, KEYCUR_DEF_Y = 3 }KEYCUR_STAT; const static char *keystr_matrix[KEYPAD_SIZE_Y][KEYPAD_SIZE_X] = { {"C ", "D ", "E ", "F ", "A_SET"}, {"8 ", "9 ", "A ", "B ", "INCR "}, {"4 ", "5 ", "6 ", "7 ", "RUN "}, {"0 ", "1 ", "2 ", "3 ", "RESET"} }; typedef struct{ int cur_x; int cur_y; }KeycurStatus; static KeycurStatus st_keycur = {KEYPAD_DEF_X + KEYCUR_DEF_X, KEYPAD_DEF_Y + KEYCUR_DEF_Y}; void keycur_SetCursorX(int cur_x); void keycur_SetCursorY(int cur_y); void keycur_DrawCursor(bool is_draw); void keycur_DrawString(bool is_draw); void keycur_ClearCursorValue(void); //--------------------------------------------------------------------------------- void keycur_SetCursorX(int cur_x){ //--------------------------------------------------------------------------------- st_keycur.cur_x = cur_x; } //--------------------------------------------------------------------------------- void keycur_SetCursorY(int cur_y){ //--------------------------------------------------------------------------------- st_keycur.cur_y = cur_y; } //--------------------------------------------------------------------------------- int keycur_GetCursorX(void){ //--------------------------------------------------------------------------------- return st_keycur.cur_x; } //--------------------------------------------------------------------------------- int keycur_GetCursorY(void){ //--------------------------------------------------------------------------------- return st_keycur.cur_y; } //--------------------------------------------------------------------------------- void keycur_DrawCursor(bool is_draw){ //--------------------------------------------------------------------------------- switch(is_draw){ case true: printf("\x1b[%d;%dH>", keycur_GetCursorY(), keycur_GetCursorX() * 2); break; case false: printf("\x1b[%d;%dH ", keycur_GetCursorY(), keycur_GetCursorX() * 2); break; } } //--------------------------------------------------------------------------------- void keycur_DrawString(bool is_draw){ //--------------------------------------------------------------------------------- switch(is_draw){ case true: printf("\x1b[%d;%dH%s", KEYSTR_DEF_Y, KEYSTR_DEF_X, keystr_matrix[keycur_GetCursorY() - KEYPAD_DEF_Y][keycur_GetCursorX() - KEYPAD_DEF_X]); break; case false: printf("\x1b[%d;%dH ", KEYSTR_DEF_Y, KEYSTR_DEF_X); break; } } //--------------------------------------------------------------------------------- void keycur_ClearCursorValue(void){ //--------------------------------------------------------------------------------- keycur_SetCursorX(KEYPAD_DEF_X + KEYCUR_DEF_X); keycur_SetCursorY(KEYPAD_DEF_Y + KEYCUR_DEF_Y); } //--------------------------------------------------------------------------------- void keycur_ClearCursor(void){ //--------------------------------------------------------------------------------- keycur_DrawCursor(false); keycur_DrawString(false); keycur_ClearCursorValue(); keycur_DrawCursor(true); keycur_DrawString(true); } //--------------------------------------------------------------------------------- void Keycur_Move(void){ //--------------------------------------------------------------------------------- static u32 kdr; kdr = keysDownRepeat(); if(kdr & KEY_RIGHT){ keycur_DrawCursor(false); keycur_DrawString(false); if(keycur_GetCursorX() < (KEYPAD_DEF_X + KEYPAD_MAX_X)){ keycur_SetCursorX(keycur_GetCursorX() + 1); }else{ keycur_SetCursorX(KEYPAD_DEF_X + KEYPAD_MIN_X); } keycur_DrawCursor(true); keycur_DrawString(true); } if(kdr & KEY_DOWN){ keycur_DrawCursor(false); keycur_DrawString(false); if(keycur_GetCursorY() < (KEYPAD_DEF_Y + KEYPAD_MAX_Y)){ keycur_SetCursorY(keycur_GetCursorY() + 1); }else{ keycur_SetCursorY(KEYPAD_DEF_Y + KEYPAD_MIN_Y); } keycur_DrawCursor(true); keycur_DrawString(true); } if(kdr & KEY_LEFT){ keycur_DrawCursor(false); keycur_DrawString(false); if(keycur_GetCursorX() > (KEYPAD_DEF_X + KEYPAD_MIN_X)){ keycur_SetCursorX(keycur_GetCursorX() - 1); }else{ keycur_SetCursorX(KEYPAD_DEF_X + KEYPAD_MAX_X); } keycur_DrawCursor(true); keycur_DrawString(true); } if(kdr & KEY_UP){ keycur_DrawCursor(false); keycur_DrawString(false); if(keycur_GetCursorY() > (KEYPAD_DEF_Y + KEYPAD_MIN_Y)){ keycur_SetCursorY(keycur_GetCursorY() - 1); }else{ keycur_SetCursorY(KEYPAD_DEF_Y + KEYPAD_MAX_Y); } keycur_DrawCursor(true); keycur_DrawString(true); } } //--------------------------------------------------------------------------------- void Keycur_Init(void){ //--------------------------------------------------------------------------------- printf("\x1b[%d;%dH C D E F A_SET\n", KEYPAD_DEF_Y , KEYPAD_DEF_X * 2); printf("\x1b[%d;%dH 8 9 A B INCR \n", KEYPAD_DEF_Y + 1, KEYPAD_DEF_X * 2); printf("\x1b[%d;%dH 4 5 6 7 RUN \n", KEYPAD_DEF_Y + 2, KEYPAD_DEF_X * 2); printf("\x1b[%d;%dH 0 1 2 3 RESET\n", KEYPAD_DEF_Y + 3, KEYPAD_DEF_X * 2); } //---------------------------------------------------------------------------------