#include #include "DigitClass.h" #define RS 12 #define EN 13 #define D4 14 #define D5 15 #define D6 16 #define D7 17 #define P1 0 #define P2 1 #define P3 2 #define P4 3 #define P5 4 #define P6 5 #define P7 6 #define P8 7 #define P9 8 #define P10 10 #define P11 9 const PROGMEM uint8_t menuTitle[] = "Password ManagerPassword SettingEEPROM Backup EEPROM Restore Calculator GAME "; const PROGMEM uint8_t errorMsg[] = { // 表示が16桁越えました 0xcb, 0xae, 0xb3, 0xbc, 0xde, 0xb6, 0xde, 0x31, 0x36, 0xb9, 0xc0, 0xba, 0xb4, 0xcf, 0xbc, 0xc0, // 0で除算をしました 0x20, 0x20, 0x30, 0xc3, 0xde, 0xbc, 0xde, 0xae, 0xbb, 0xde, 0xdd, 0xa6, 0xbc, 0xcf, 0xbc, 0xc0, // オーバーフローしました 0x20, 0x20, 0x20, 0x20, 0xb5, 0xb0, 0xca, 0xde, 0xb0, 0xcc, 0xdb, 0xb0, 0xbc, 0xcf, 0xbc, 0xc0 }; const PROGMEM uint8_t kanaMap[] = { 0xde, 0xcf, 0xd4, 0xd7, 0xc0, 0xc5, 0xca, 0xb1, 0xb6, 0xbb, 0xdc, 0xa1 }; const PROGMEM uint8_t kanaSmallMap[] ={ 0xde, 0xcf, 0xac, 0xd7, 0xc0, 0xc5, 0xca, 0xa7, 0xb6, 0xbb, 0xdc, 0xa1 }; const PROGMEM uint8_t alphaMap[] = { 0x21, 0x50, 0x54, 0x57, 0x47, 0x4a, 0x4d, 0x3a, 0x41, 0x44, 0x26, 0x2b }; const PROGMEM uint8_t alphaSmallMap[] = { 0x21, 0x70, 0x74, 0x77, 0x67, 0x6a, 0x6d, 0x3a, 0x61, 0x64, 0x26, 0x2b }; const PROGMEM uint8_t irregular[] = { 0xdc, 0xa6, 0xdd, 0xb0 }; const PROGMEM uint8_t msgKana[] = {0xb6, 0xc5, 0}; // カナ const PROGMEM uint8_t msgAlpha[] = {0xb1, 0xd9, 0xcc, 0xa7, 0xcd, 0xde, 0xaf, 0xc4, 0}; // アルファベット const PROGMEM uint8_t msgNumber[] = {0xbd, 0xb3, 0xbc, 0xde, 0}; // 数字 const PROGMEM uint8_t msgFutsu[] = {0xcc, 0xc2, 0xb3, 0}; // ふつう const PROGMEM uint8_t msgSmall[] = {0xba, 0xd3, 0xbc, 0xde, 0}; // 小文字 const PROGMEM uint8_t msgInput[] = {0xbc, 0xdd, 0xb7, 0xc4, 0xb3, 0xdb, 0xb8, 0}; // 新規登録 const PROGMEM uint8_t msgSelect[] = {0xbe, 0xdd, 0xc0, 0xb8,0}; // 選択 const PROGMEM uint8_t msgEdit[] = {0xcd, 0xdd, 0xbc, 0xad, 0xb3, 0}; // 編集 const PROGMEM uint8_t msgDelete[] = {0xbb, 0xb8, 0xbc, 0xde, 0xae, 0}; // 削除 const PROGMEM uint8_t msgMvSrc[] = {0xb2, 0xc4, 0xde, 0xb3, 0xd3, 0xc4, 0x20, 0xbe, 0xaf, 0xc3, 0xb2, 0}; // 移動元設定 const PROGMEM uint8_t msgMvDst[] = {0xb2, 0xc4, 0xde, 0xb3, 0}; // 移動 const PROGMEM uint8_t msgSearch[] = {0xb9, 0xdd, 0xbb, 0xb8, 0}; // 検索 const PROGMEM uint8_t msgResearch[] = {0xbb, 0xb2, 0xb9, 0xdd, 0xbb, 0xb8, 0}; // 再検索 const PROGMEM uint8_t msgNotFound[] = {0xd0, 0xc2, 0xb6, 0xd8, 0xcf, 0xbe, 0xdd, 0}; // 見つかりません const PROGMEM uint8_t msgEnter[] = {0xc4, 0xb3, 0xdb, 0xb8, 0}; // 登録 const PROGMEM uint8_t msgCancel[] = {0xb7, 0xac, 0xdd, 0xbe, 0xd9, 0}; // キャンセル const PROGMEM uint8_t msgPassBig[] = {0xb1, 0xd9, 0xcc, 0xa7, 0xcd, 0xde, 0xaf, 0xc4, 0x20, 0xb5, 0xb5, 0xd3, 0xbc, 0xde, 0}; // アルファベット大文字 const PROGMEM uint8_t msgPassSmall[] = {0xb1, 0xd9, 0xcc, 0xa7, 0xcd, 0xde, 0xaf, 0xc4, 0x20, 0xba, 0xd3, 0xbc, 0xde, 0}; // アルファベット小文字 const PROGMEM uint8_t msgPassMis[] = {0x4f, 0x20, 0x49, 0x20, 0x6f, 0x20, 0x6c, 0}; // O I o l const PROGMEM uint8_t msgPassLen[] = {0xd3, 0xbc, 0xde, 0xbd, 0xb3, 0}; // 文字数 const PROGMEM uint8_t msgPassUse[] = {0xc2, 0xb6, 0xb3, 0x20, 0x20, 0}; // 使う const PROGMEM uint8_t msgPassNUse[] = {0xc2, 0xb6, 0xdc, 0xc5, 0xb2, 0}; // 使わない const PROGMEM uint8_t msgEmpty[] = {0xc3, 0xde, 0xb0, 0xc0, 0xb6, 0xde, 0xb1, 0xd8, 0xcf, 0xbe, 0xdd, 0}; // データがありません const PROGMEM uint8_t msgBackup[] = {0xca, 0xde, 0xaf, 0xb8, 0xb1, 0xaf, 0xcc, 0xdf, 0xbc, 0xcf, 0xbc, 0xc0, 0}; // バックアップしました const PROGMEM uint8_t msgRestore[] = {0xd8, 0xbd, 0xc4, 0xb1, 0xbc, 0xcf, 0xbc, 0xc0, 0}; // リストアしました void (*keyIn[24])(); // 入力処理ルーチンのポインタ収納 uint8_t DEVICE_ADDRESS = 0x50; // 1010000 /* * 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 * AC |GT | 8 | 0 | × |MRC| 9 | 1 * ------------------------------- * 8 | 9 |10 |11 |12 |13 |14 |15 * ÷ | 2 | = | 6 | 7 | 4 |→ | 5 * ------------------------------- * 16 |17 |18 |19 |20 |21 |22 |23 * . |00 | 3 | + | - | % |M+ |M- */ uint8_t IP[] = {P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11}; uint8_t OP2[] = {P3, P4, P6, P7, P11}; uint8_t OP3[] = {P4, P6, P7}; uint8_t OP4[] = {P6, P7, P9, P10}; uint8_t OP5[] = {P6, P10}; uint8_t OP6[] = {P7, P9, P10, P11}; uint8_t OP7[] = {P9, P10, P11}; uint8_t keyStat[24]; uint8_t keyCode; int menuNo; // LCD int row, cursorPos, displayON, block, blinkCur, shift; void setup() { Wire.begin(); pinMode(RS, OUTPUT); pinMode(EN, OUTPUT); pinMode(D4, OUTPUT); pinMode(D5, OUTPUT); pinMode(D6, OUTPUT); pinMode(D7, OUTPUT); // ハイインピーダンスにする for(int i=0; i<11; i++) pinMode(IP[i], INPUT); randomSeed(millis()); // パスワード管理・ゲームで使用 // キーの状態初期化 for(int i=0; i<24; i++) keyStat[i] = 1; row = 0; // カーソルを一行目に cursorPos = 0; // カーソル位置 displayON = 1; // LCDの表示オン block = 0; // ブロックカーソルのオフ blinkCur = 0; // カーソルブリンクのオフ shift = 0; // ディスプレイシフトをオフ lcdInit(); } void loop() { calculator(); menu(menuNo); } /// メニュー操作 /// void menu(int no) { bool loopFlag =true; blinkOnOff(1); printTitle(no); while(loopFlag) { getKey(); switch(keyCode) { case 23: // M- if(--no == -1) no = 5; printTitle(no); break; case 22: // M+ if(++no == 6) no = 0; printTitle(no); break; case 10: // = blinkOnOff(0); if(no == 0) { pwManager(); loopFlag = false; } else if(no == 1) { setPasswd(); loopFlag = false; } else if(no == 2) { EEPROMbackup(); loopFlag = false; } else if(no == 3) { EEPROMrestore(); loopFlag = false; } else if(no == 4) { loopFlag = false; } else { invader(); loopFlag = false; } break; } } } void printTitle(int no) { int n; n = no * 16; clearDisplay(); for(int i=0; i<16; i++) putChar(pgm_read_byte(menuTitle + n + i)); if((n += 16) == 96) n = 0; setLine(1); setCursorPos(0); for(int i=0; i<16; i++) putChar(pgm_read_byte(menuTitle + n + i)); setLine(0); setCursorPos(0); } /// 電卓 /// #define STACK 5 #define ZERO " 0" String stack[STACK], curstr; DigitClass current, topst; uint8_t dispbuff[20], buff[32], dpo, ipo, dot; bool ans, stk; uint8_t errorCode; bool calcloop; void calculator() { calcloop = true; // キー入力処理ルーチンのポインタ収納 keyIn[0] = padClear; keyIn[1] = padMinus; keyIn[2] = no8; keyIn[3] = no0; keyIn[4] = padMul; keyIn[5] = padClearAll; keyIn[6] = no9; keyIn[7] = no1; keyIn[8] = padDiv; keyIn[9] = no2; keyIn[10] = padEqual; keyIn[11] = no6; keyIn[12] = no7; keyIn[13] = no4; keyIn[14] = padDelete; keyIn[15] = no5; keyIn[16] = padPoint; keyIn[17] = padWZero; keyIn[18] = no3; keyIn[19] = padAdd; keyIn[20] = padSub; keyIn[21] = padPercent; keyIn[22] = padMemPlus; keyIn[23] = padMemMinus; clearStack(); clearLine(); clearDisplay(); putStr(ZERO); setLine(1); setCursorPos(0); putStr(ZERO); while(calcloop) { getKey(); if(keyCode != 0xff) { (*keyIn[keyCode])(); setCursorPos(0); putStr(dispbuff); } } } void no0() { // 最初に0は入力できない if(dpo != 0) padNo(0); } void no1() {padNo(1);} void no2() {padNo(2);} void no3() {padNo(3);} void no4() {padNo(4);} void no5() {padNo(5);} void no6() {padNo(6);} void no7() {padNo(7);} void no8() {padNo(8);} void no9() {padNo(9);} void padNo(uint8_t no) { if(stk) // スタックPUSH直後 clearLine(); if(ans) // 演算処理後 { push(); clearLine(); } if(buff[dpo] != ' ') // 表示スペースがなくなった return; buff[ipo++] = '0' + no; ++dpo; copyLine(); } // AC 入力クリア void padClear() { clearLine(); } // → 1桁削除 void padDelete() { if(ans || stk) { clearLine(); return; } if(dpo != 0) { --dpo; --ipo; if(buff[ipo - 1] == '.') // 小数点以下を消した { --dpo; --ipo; dot = false; if((dpo == 1) && (buff[16] == '0')) clearLine(); } copyLine(); if(dpo == 0) { dispbuff[15] = '0'; // マイナスも消す if(buff[15] == '-') buff[15] = ' '; } } } // MRC スタック含め入力クリア void padClearAll() { clearStack(); clearLine(); setLine(0); setCursorPos(0); putStr(ZERO); setLine(1); } // 00 void padWZero() { if(stk) clearLine(); if(ans) { push(); clearLine(); return; } if(dpo != 0) // 最初に0は入力できない { for(int i=0; i<2; i++) { if(buff[dpo] != ' ') // 表示スペースがなくなった break; buff[ipo++] = '0'; ++dpo; } copyLine(); } } // GT マイナス符号 void padMinus() { if(ans) { clearLine(); return; } if(dpo != 0) // 最初に-は入力できない { if(buff[15] == ' ') buff[15] = '-'; else if(buff[15] == '-') buff[15] = ' '; else return; copyLine(); } } // 小数点 void padPoint() { if(stk) clearLine(); if(ans) { push(); clearLine(); } if(!dot) // すでに.は入力済み { if(buff[dpo] != ' ') // 表示スペースがなくなった return; if(dpo == 0) // 最初の. { buff[ipo++] = '0'; ++dpo; } buff[ipo++] = '.'; ++dpo; dot = true; copyLine(); } } // スタックに入れる void padEqual() { uint8_t dotpos, count; // 小数点表示を修正する if(dot) // 小数点あり { dotpos = 0; for(int i=0; i<16; i++) { if(dispbuff[i] == '.') { dotpos = i; break; } } // 末尾の0を消す count = 0; for(int i=15; i>dotpos; i--) { if(dispbuff[i] != '0') break; ++count; } if(count) { for(int i=15-count; i>=0; i--) dispbuff[i + count] = dispbuff[i]; for(int i=0; i0; i--) dispbuff[i] = dispbuff[i - 1]; dispbuff[0] = ' '; } // -0になっていたら-を取る if((dispbuff[14] == '-') && (dispbuff[15] == '0')) dispbuff[14] = ' '; } push(); } // 加算 void padAdd() { curstr = dispbuff; current.setFigure(curstr); topst.setFigure(stack[0]); if(!preProcess(¤t, &topst)) { errorCode = 0; dispError(); return; } current.acc = topst.acc + current.acc; if(setAnswer(current.getString())) pop(); } // 減算 void padSub() { curstr = dispbuff; current.setFigure(curstr); topst.setFigure(stack[0]); preProcess(¤t, &topst); current.acc = topst.acc - current.acc; if(setAnswer(current.getString())) pop(); } // 乗算 void padMul() { curstr = dispbuff; current.setFigure(curstr); topst.setFigure(stack[0]); // 数字に変換 current.setNumber(false); topst.setNumber(false); // 計算後の小数点の桁数 current.point += topst.point; // オーバーフローチェック if(topst.acc == 0) current.acc = 0; else if(abs(current.acc) < (__LONG_LONG_MAX__ / abs(topst.acc))) current.acc = topst.acc * current.acc; else { errorCode = 2; dispError(); return; } if(setAnswer(current.getString())) pop(); } // 除算 void padDiv() { curstr = dispbuff; current.setFigure(curstr); topst.setFigure(stack[0]); if(!mul(¤t, &topst)) { dispError(); return; } if(setAnswer(current.getString())) pop(); } // パーセント計算 void padPercent() { curstr = "100"; current.setFigure(curstr); topst.setFigure(stack[0]); current.setNumber(false); topst.setNumber(false); mul(¤t, &topst); curstr = current.getString(); topst.setFigure(curstr); curstr = dispbuff; current.setFigure(curstr); current.setNumber(false); topst.setNumber(false); current.point += topst.point; // オーバーフローチェック if(topst.acc == 0) current.acc = 0; else if(abs(current.acc) < (__LONG_LONG_MAX__ / abs(topst.acc))) current.acc = topst.acc * current.acc; else { errorCode = 2; dispError(); return; } setAnswer(current.getString()); ans = true; } // M- メニュー先頭へ移動 void padMemMinus() { calcloop = false; menuNo = 0; } // M+ メニュー最後へ移動 void padMemPlus() { calcloop = false; menuNo = 5; } void clearLine() { // 数値文字列作成バッファ初期化 for(int i=0; i<16; i++) buff[i] = ' '; for(int i=16; i<32; i++) buff[i] = NULL; // 表示文字列初期化 for(int i=0; i<16; i++) dispbuff[i] = ' '; dispbuff[16] = NULL; dispbuff[15] = '0'; dpo = 0; // 表示開始位置 ipo = 16; // 数値入力位置 dot = false; // 小数点の有無 ans = false; // 演算処理後 stk = false; // スタックPUSH直後 } void copyLine() { for(int i=0; i<16; i++) dispbuff[i] = buff[dpo + i]; } bool setAnswer(char* s) { int len; len = strlen(s); if(len == 0) { errorCode = 0; // 16桁越えた dispError(); return false; } clearLine(); for(int i=0; i0; i--) stack[i] = stack[i - 1]; stack[0] = dispbuff; setLine(0); setCursorPos(0); putStr(stack[0].c_str()); setLine(1); stk = true; } void pop() { for(int i=0; ipoint > b->point) { a->diff = 0; b->diff = a->point - b->point; b->point = a->point; // ずらした小数点の桁数 } else if(a->point < b->point) { a->diff = b->point - a->point; b->diff = 0; a->point = b->point; // ずらした小数点の桁数 } else { a->diff = 0; b->diff = 0; } // 数字に変換 if(!a->setNumber(true)) return false; if(!b->setNumber(true)) return false; return true; } bool mul(DigitClass* a, DigitClass* b) { long long quo, sur, w; int p = 0, n; // 数字に変換 current.setNumber(false); topst.setNumber(false); if(a->acc == 0) { errorCode = 1; return false; } quo = b->acc / a->acc; sur = b->acc % a->acc; if(sur) // 小数点以下の計算 { // 整数部の桁数を調べる w = quo; n = 0; while(true) { ++n; w /= 10; if(w == 0) break; } n = 15 - n; // .を除いて15桁 if(quo < 0) // マイナスならさらに1桁少なくなる --n; w = 0; for(int i=0; iacc; sur %= a->acc; ++p; if(sur == 0) // 割り切れた break; } // 小数部の桁数分移動 for(int i=0; ipoint - a->point; if(p < 0) // p桁増やす { for(int i=0; i<-p; i++) quo *= 10; p = 0; } a->acc = quo; a->point = p; return true; } /// パスワード管理 /// /* EEPROM 32KB 0000〜03DF データテーブル 03E0〜03F9 空き 03FA バスワードで使用する文字の種類 03FB バスワードでまぎわらしい文字使用の有無 03FC バスワードの文字数 03FD〜03FF シグネチャー 'PWM' 0400〜7FFF データ 496個 */ #define TBLEND 0x3df #define FIRSTADD 0x400 #define LASTADD 0x7fff uint8_t rwBuff[64]; String searchWord; bool result; void pwManager() { int account; uint16_t tableAdd, store, address; uint16_t mvTable, searchAdd; bool loopflag = true; // 初回のみEEPROM初期化 if((readByte(0x3fd) != 'P') || (readByte(0x3fe) != 'W') || (readByte(0x3ff) != 'M')) { //データテーブルの初期化 for(int i=0; i<64; i++) rwBuff[i] = 0xff; for(int i=0; i 0) { // 削除データスキップ while(true) { address = read2Byte(tableAdd); if(address != 0) break; tableAdd += 2; } showTitle(tableAdd); } else showInfo(msgEmpty); while(loopflag) { getKey(); switch(keyCode) { case 22: // M+ カーソル下 store = tableAdd; do { tableAdd += 2; address = read2Byte(tableAdd); } while(address == 0); // 削除データスキップ if(address != 0xffff) showTitle(tableAdd); else tableAdd = store; break; case 23: // M- カーソル上 store = tableAdd; do { if(tableAdd == 0) { address = 0xffff; break; } tableAdd -= 2; address = read2Byte(tableAdd); } while(address == 0); // 削除データスキップ if(address != 0xffff) showTitle(tableAdd); else tableAdd = store; break; case 10: // = 選択 if(account > 0) // データが存在する { showInfo(msgSelect); showDetail(); setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); } break; case 19: // + 新規登録 showInfo(msgInput); address = inputData(0xffff); if(address != 0xffff) { tableAdd = address; ++account; } showTitle(tableAdd); break; case 4: // × 編集 if(account > 0) // データが存在する { showInfo(msgEdit); inputData(tableAdd); showTitle(tableAdd); } break; case 20: // - 削除 if(account > 0) // データが存在する { showInfo(msgDelete); deleteData(tableAdd); if(--account > 0) { store = tableAdd; do { tableAdd += 2; address = read2Byte(tableAdd); } while(address == 0); // 削除データスキップ if(address != 0xffff) showTitle(tableAdd); else // 前方のデータを表示(必ずある) { tableAdd = store; do { tableAdd -= 2; address = read2Byte(tableAdd); } while(address == 0); // 削除データスキップ showTitle(tableAdd); } } else // データがなくなった { tableAdd = 0; clearDisplay(); } mvTable = 0xffff; // 移動元設定もクリア } break; case 5: // MRC 移動元設定 if(account > 0) // データが存在する { showInfo(msgMvSrc); if(mvTable == tableAdd) { showInfo(msgCancel); mvTable = 0xffff; } else mvTable = tableAdd; setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); } break; case 14: // → 移動 if((mvTable != 0xffff) && (mvTable != tableAdd) && (mvTable != tableAdd-1)) { showInfo(msgMvDst); if((tableAdd != 0) && (read2Byte(tableAdd - 2) == 0)) //移動先に削除マークがある { tableAdd -= 2; write2Byte(tableAdd, read2Byte(mvTable)); write2Byte(mvTable, 0); } else { if(mvTable > tableAdd) // 前方に移動 { address = read2Byte(mvTable); for(uint16_t i=mvTable; i>tableAdd; i-=2) write2Byte(i, read2Byte(i - 2)); write2Byte(tableAdd, address); } else // 後方に移動 { address = read2Byte(mvTable); for(uint16_t i=mvTable+2; i 0) // データが存在する { showInfo(msgSearch); clearBuff(); searchWord += " "; searchWord.toCharArray(rwBuff, 17); rwBuff[16] = ' '; // 画面にゴミが表示されないよう文字列終端を消す blinkOnOff(1); kanaInputLoop(); blinkOnOff(0); if(result) { rwBuff[16] = NULL; // 文字列終端 searchWord = rwBuff; searchWord.trim(); // 検索開始 address = searchNext(searchAdd); if(address != 0xffff) { tableAdd = address; searchAdd = address + 2; if(searchAdd > TBLEND) searchAdd = 0; } else searchAdd = 0; // 最後まで検索した } showTitle(tableAdd); } break; case 1: // GT 再検索 if(account > 0) // データが存在する { showInfo(msgResearch); address = searchNext(searchAdd); if(address != 0xffff) { tableAdd = address; searchAdd = address + 2; if(searchAdd > TBLEND) searchAdd = 0; } else searchAdd = 0; // 最後まで検索した showTitle(tableAdd); } break; case 0: // AC 終了 loopflag = false; break; } } } // 1行表示 void putLine(uint8_t* lineBuff) { setCursorPos(0); for(int i=0; i<16; i++) putChar(lineBuff[i]); } // タイトルの表示 bool showTitle(uint16_t add) { if(!read64Byte(read2Byte(add))) return false; setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); return true; } // 内容表示 void showDetail() { uint8_t *bf; bool up = true; setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); while(true) { getKey(); switch(keyCode) { case 22: // M+ カーソル下 if(up) { setLine(0); putLine(rwBuff + 32); setLine(1); putLine(rwBuff + 48); up = false; } break; case 23: // M- カーソル上 if(!up) { setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); up = true; } break; case 0: // AC 終了 return; break; } } } // メッセージ表示 void showInfo(uint8_t* msg) { uint8_t ch, c = 0; clearDisplay(); while(true) { ch = pgm_read_byte(msg + (c++)); if(ch == 0) break; putChar(ch); } delay(1000); } // 新規データ追加または既存データ編集 uint16_t inputData(uint16_t add) { uint16_t writeAdd; clearDisplay(); if(add == 0xffff) // 新規モード clearBuff(); // バッファクリア blinkOnOff(1); kanaInputLoop(); blinkOnOff(0); if(result) { if(add == 0xffff) // 空き領域検索 { writeAdd = emptySearch(); if(writeAdd == 0xffff) return 0xffff; } else writeAdd = add; write64Byte(read2Byte(writeAdd)); return writeAdd; } else return 0xffff; } // 空き領域検索 uint16_t emptySearch() { uint16_t address = 0xffff, da; // データ空き領域 for(uint16_t i=FIRSTADD; i> 8); // Address(High Byte) Wire.write(add & 0xff); // Address(Low Byte) Wire.endTransmission(); //デバイスへ1byteのデータを要求する Wire.requestFrom(DEVICE_ADDRESS, 1); while(Wire.available() == 0){} return Wire.read(); } // EEPROM1バイト書き込み void writeByte(uint16_t add, uint8_t dat) { // 対象アドレス Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(add >> 8); // Address(High Byte) Wire.write(add & 0xff); //A ddress(Low Byte) // データの書き込み Wire.write(dat); Wire.endTransmission(); delay(5); } // EEPROM2バイト読み込み uint16_t read2Byte(uint16_t add) { uint8_t value[2]; int counter = 0; // 対象アドレス Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(add >> 8); // Address(High Byte) Wire.write(add & 0xff); // Address(Low Byte) Wire.endTransmission(); //デバイスへ2byteのデータを要求する Wire.requestFrom(DEVICE_ADDRESS, 2); while(Wire.available()) value[counter++] = Wire.read(); return ((uint16_t)value[0] << 8) + value[1]; } // EEPROM2バイト書き込み void write2Byte(uint16_t add, uint16_t dat) { // 対象アドレス Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(add >> 8); // Address(High Byte) Wire.write(add & 0xff); //A ddress(Low Byte) // データの書き込み Wire.write(dat >> 8); Wire.write(dat & 0xff); Wire.endTransmission(); delay(5); } // EEPROM64バイト読み込み bool read64Byte(uint16_t add) { uint16_t address; int counter = 0; address = add; // Arduinoの送受信バッファは32バイト // なので32バイトx2で読み込む for(int i=0; i<2; i++) { // メモリアドレス Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(address >> 8); // Address(High Byte) Wire.write(address & 0xff); // Address(Low Byte) Wire.endTransmission(); // デバイスへ32byteのデータを要求する Wire.requestFrom(DEVICE_ADDRESS, 32); while(Wire.available()) rwBuff[counter++] = Wire.read(); address += 32; } if(counter < 64) return false; else return true; } // EEPROM64バイト書き込み void write64Byte(uint16_t add) { uint16_t address; int counter = 0; address = add; // 24LC256はアドレス0から64バイトごとのページ単位で書き込めるが // Arduinoの送受信バッファは32バイト // しかしアドレス指定に2バイト使うので30バイトしか書き込めない // なので分かりやすく16バイトx4で書き込むことにした for(int i=0; i<4; i++) { // メモリアドレス Wire.beginTransmission(DEVICE_ADDRESS); Wire.write(address >> 8); // Address(High Byte) Wire.write(address & 0xff); // Address(Low Byte) // 16バイトデータの書き込み for(int j=0; j<16; j++) Wire.write(rwBuff[counter++]); Wire.endTransmission(); delay(5); address += 16; } } /// 英数カナ入力 /// uint8_t *keymap, *charBuff; uint8_t inputMode; // 0..かな 1..アルファベット 2..数字 bool small, kiLoop; uint8_t preCode, charPos, curPos; int selLine; void kanaInputInit() { // キー入力処理ルーチンのポインタ収納 keyIn[0] = clearAll; // AC keyIn[1] = smallCharacter; // GT keyIn[2] = eight; keyIn[3] = zero; keyIn[4] = insert; // × keyIn[5] = cancel; // MRC keyIn[6] = nine; keyIn[7] = one; keyIn[8] = makePasswd; // ÷ keyIn[9] = two; keyIn[10] = getString; // = keyIn[11] = six; keyIn[12] = seven; keyIn[13] = four; keyIn[14] = backSpace; // → keyIn[15] = five; keyIn[16] = dotKey; keyIn[17] = wZero; keyIn[18] = three; keyIn[19] = right; // + keyIn[20] = left; // - keyIn[21] = modeChange; // % keyIn[22] = down; // M+ keyIn[23] = up; // M- } void kanaInputLoop() { preCode = 0xff; // 前回押されたキーのコード charPos = 0; // 表示する文字のインデックス inputMode = 0; // 入力文字種 small = false; // 小文字入力 keymap = kanaMap; // 使用する文字 curPos = 0; // カーソル位置 selLine = 0; // 選択中のデータの行 setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); charBuff = rwBuff; setLine(0); kiLoop = true; while(kiLoop) { getKey(); if(keyCode != 0xff) { (*keyIn[keyCode])(); } } } void zero() { preCodeCheck(0); if(inputMode == 0) printChar(0, 2); else if(inputMode == 1) printChar(0, 5); else printNumber('0'); } void one() { preCodeCheck(1); if(inputMode == 0) printChar(1, 5); else if(inputMode == 1) printChar(1, 4); else printNumber('1'); } void two() { preCodeCheck(2); if(inputMode == 2) printNumber('2'); else printChar(2, 3); } void three() { preCodeCheck(3); if(inputMode == 0) printChar(3, 5); else if(inputMode == 1) printChar(3, 4); else printNumber('3'); } void four() { preCodeCheck(4); if((inputMode == 0) && small) // かな小 { if(charPos == 2) { putChar(0xaf); // っ charBuff[curPos] = 0xaf; setCursorPos(curPos); ++charPos; } else printChar(4, 5); } else { if(inputMode == 0) printChar(4, 5); else if(inputMode == 1) printChar(4, 3); else printNumber('4'); } } void five() { preCodeCheck(5); if(inputMode == 0) printChar(5, 5); else if(inputMode == 1) printChar(5, 3); else printNumber('5'); } void six() { preCodeCheck(6); if(inputMode == 0) printChar(6, 5); else if(inputMode == 1) printChar(6, 3); else printNumber('6'); } void seven() { preCodeCheck(7); if(inputMode == 0) printChar(7, 5); else if(inputMode == 1) printChar(7, 7); else printNumber('7'); } void eight() { preCodeCheck(8); if(inputMode == 0) printChar(8, 5); else if(inputMode == 1) printChar(8, 3); else printNumber('8'); } void nine() { preCodeCheck(9); if(inputMode == 0) printChar(9, 5); else if(inputMode == 1) printChar(9, 3); else printNumber('9'); } void wZero() { uint8_t ch; preCodeCheck(14); if(inputMode == 0) { ch = pgm_read_byte(irregular + charPos); // わをんー putChar(ch); charBuff[curPos] = ch; setCursorPos(curPos); if(++charPos == 4) charPos = 0; } else if(inputMode == 1) printChar(10, 5); else { ch = 0x5b + charPos; putChar(ch); charBuff[curPos] = ch; setCursorPos(curPos); if(++charPos == 6) charPos = 0; } } void dotKey() { uint8_t ch; preCodeCheck(15); if(inputMode == 2) { ch = 0x7b + charPos; putChar(ch); charBuff[curPos] = ch; setCursorPos(curPos); if(++charPos == 5) charPos = 0; } else { preCodeCheck(15); printChar(11, 5); } } void clearAll() { setCursorPos(0); for(int i=0; i<16; i++) { putChar(' '); charBuff[i] = ' '; } curPos = 0; setCursorPos(curPos); preCode = 0xff; } void backSpace() { if(--curPos == 0xff) curPos = 0; for(int i=curPos; i<15; i++) charBuff[i] = charBuff[i + 1]; charBuff[15] = ' '; setCursorPos(0); for(int i=0; i<16; i++) putChar(charBuff[i]); setCursorPos(curPos); preCode = 0xff; } void insert() { for(int i=14; i>=curPos; i--) charBuff[i + 1] = charBuff[i]; charBuff[curPos] = ' '; setCursorPos(0); for(int i=0; i<16; i++) putChar(charBuff[i]); setCursorPos(curPos); preCode = 0xff; } void getString() { showInfo(msgEnter); clearDisplay(); result =true; kiLoop = false; } void cancel() { clearBuff(); showInfo(msgCancel); clearDisplay(); result = false; kiLoop = false; } void modeChange() { if(++inputMode == 3) inputMode = 0; if(inputMode == 0) { keymap = kanaMap; information(msgKana); } else if(inputMode == 1) { keymap = alphaMap; information(msgAlpha); } else { information(msgNumber); } charPos = 0; small = false; } void smallCharacter() { if(small) // 小文字入力 { if(inputMode == 0) keymap = kanaMap; // かな else if(inputMode == 1) keymap = alphaMap; // アルファベット information(msgFutsu); small = false; } else { if(inputMode == 0) keymap = kanaSmallMap; // かな小 else if(inputMode == 1) keymap = alphaSmallMap; // アルファベット小 information(msgSmall); small = true; } } void left() { if(--curPos == 0xff) curPos = 0; // 1桁目 setCursorPos(curPos); preCode = 0xff; } void right() { if(++curPos == 16) curPos = 15; // 16桁目 setCursorPos(curPos); preCode = 0xff; } void up() { --selLine; if(selLine == -1) { selLine = 0; return; } else if(selLine == 0) setLine(0); else if(selLine == 1) { setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); } else if(selLine == 2) setLine(0); charBuff -= 16; curPos = 0; setCursorPos(curPos); preCode = 0xff; } void down() { ++selLine; if(selLine == 1) setLine(1); else if(selLine == 2) { setLine(0); putLine(rwBuff + 32); setLine(1); putLine(rwBuff + 48); setLine(0); } else if(selLine == 3) setLine(1); else if(selLine == 4) { selLine = 3; return; } charBuff += 16; curPos = 0; setCursorPos(curPos); preCode = 0xff; } //void defaultHandle(){} void preCodeCheck(uint8_t code) { if(preCode == 0xff) { preCode = code; charPos = 0; } else if(preCode != code) { preCode = code; ++curPos; if(curPos == 16) cursorPos = 15; // 15桁目にとどまる setCursorPos(curPos); charPos = 0; } else setCursorPos(curPos); } void printChar(uint8_t code, uint8_t maxnum) { char ch; ch = pgm_read_byte(keymap + code) + charPos; putChar(ch); charBuff[curPos] = ch; setCursorPos(curPos); if(++charPos == maxnum) charPos = 0; } void printNumber(uint8_t num) { putChar(num); charBuff[curPos] = num; setCursorPos(curPos); } void information(uint8_t* msg) { uint8_t ch, i = 0; clearDisplay(); while(true) { ch = pgm_read_byte(msg + (i++)); if(ch == 0) break; putChar(ch); } delay(1000); if(selLine < 2) { setLine(0); putLine(rwBuff); setLine(1); putLine(rwBuff + 16); if(selLine == 0) setLine(0); } else { setLine(0); putLine(rwBuff + 32); setLine(1); putLine(rwBuff + 48); if(selLine == 2) setLine(0); } setCursorPos(curPos); } // パスワード生成 void makePasswd() { uint8_t kind, ch; bool ambig; int len, fig; kind = readByte(0x3fa); // ビット0..数字 1..アルファベット大文字 2..アルファベット小文字 ambig = (bool)readByte(0x3fb); // OIolを取り除く len = readByte(0x3fc); // バスワードの文字数 setCursorPos(0); for(int i=0; i<16; i++) { putChar(' '); charBuff[i] = ' '; } setCursorPos(0); // パスワード生成 for(int i=0; i 16) kind = 16; sprintf(smbf, "%02d", kind); setCursorPos(0); putStr(smbf); break; case 23: // M- if(--kind < 4) kind = 4; sprintf(smbf, "%02d", kind); setCursorPos(0); putStr(smbf); break; case 10: // = 選択 writeByte(0x3fc, kind); return; break; } } } void showSelect(uint8_t* msg) { uint8_t ch, c = 0; setLine(1); setCursorPos(0); while(true) { ch = pgm_read_byte(msg + (c++)); if(ch == 0) break; putChar(ch); } } bool selectYN() { bool flip = true; showSelect(msgPassUse); while(true) { getKey(); switch(keyCode) { case 22: // M+ カーソル下 case 23: // M- カーソル上 if(flip) { setCursorPos(0); showSelect(msgPassNUse); flip = false; } else { setCursorPos(0); showSelect(msgPassUse); flip = true; } break; case 10: // = 選択 if(flip) return true; else return false; break; } } } // EEPROMバックアップ void EEPROMbackup() { uint16_t address; clearDisplay(); // バックアップファイル初期化を指示 rwBuff[0] = 0; Wire.beginTransmission(8); for(int i=0; i<32; i++) Wire.write(rwBuff[i]); Wire.endTransmission(); // バックアップデータ送信 for(uint16_t i=0; i 10) aim = 0; setLine(1); setCursorPos(0); putChar(ino[aim]); } else if(keyCode == 19) //ショット { if(shLeft != 0) { --shLeft; count = 14; pos = enPos; while(count > 0) { if(enemy[pos] == 0) // 消された敵 while(enemy[pos] == 0) // 消された敵はスキップ ++pos; if(enemy[pos] == ' ') // 空白は無視 { ++pos; --count; continue; } if(enemy[pos] == ino[aim]) //当たり { --enLeft; // 敵1体へらす enemy[pos] = 0; // 敵消す --enPos; // 敵後退 //スコア加算 if(aim == 10) //UFO { score += 300; ufoWait = true; // ちょっとだけ画面が停止 } else { score = score + ((15 - count) * 10); // UFO出現チェック if(aim != 0) // 10の倍数に0を足してもUFOは出ない { ufoCheck += aim; if((ufoCheck % 10) == 0) { ufo = true; ufoCheck = 0; } } } break; } ++pos; --count; } } } showInfo(); // 敵移動 if(--enwt == 0) { ++enPos; if(dispBuff[0] != ' ') // 敵侵入か over = true; enwt = enWait; // 敵移動ウェイト再設定 } // ゲーム全体のウェイト while((millis() - gameWait) < 100); } } void gameOver() { uint8_t key; showScore(); setLine(1); setCursorPos(3); putStr("GAME OVER"); while(true) { getKey(); if(keyCode == 10) break; } } void showScore() { clearDisplay(); setLine(0); setCursorPos(0); putStr(msgRound); sprintf(numbuff, "%d", cRound); putStr(numbuff); setCursorPos(8); putStr(msgScore); sprintf(numbuff, "%d", score); putStr(numbuff); delay(3000); } void showInfo() { setLine(0); setCursorPos(0); putStr(msgLShot); sprintf(numbuff, "%02d", shLeft); putStr(numbuff); setCursorPos(8); putStr(msgEnemy); sprintf(numbuff, "%02d", enLeft); putStr(numbuff); } void displeft() { setLine(1); setCursorPos(1); if(cannon == 3) putChar(0); else if(cannon == 2) putChar(1); else putChar(2); } /// キー入力 /// void getKey() { uint8_t inp, ix; keyCode = 0xff; // AC pinMode(P1, INPUT_PULLUP); pinMode(P8, OUTPUT); delay(1); // 回路の安定を待つ inp = digitalRead(P1); if(inp != keyStat[0]) { if(!inp) // キーが押された keyCode = 0; keyStat[0] = inp; } pinMode(P1, INPUT); pinMode(P8, INPUT); // GT 8 0 * MRC ix = 0; pinMode(P2, INPUT_PULLUP); for(int i=1; i<6; i++) // 1〜5 { pinMode(OP2[ix], OUTPUT); delay(1); inp = digitalRead(P2); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP2[ix++], INPUT); } pinMode(P2, INPUT); // 9 1 ÷ ix = 0; pinMode(P3, INPUT_PULLUP); for(int i=6; i<9; i++) // 6〜8 { pinMode(OP3[ix], OUTPUT); delay(1); inp = digitalRead(P3); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP3[ix++], INPUT); } pinMode(P3, INPUT); // 2 = 6 7 ix = 0; pinMode(P4, INPUT_PULLUP); for(int i=9; i<13; i++) // 9〜12 { pinMode(OP4[ix], OUTPUT); delay(1); inp = digitalRead(P4); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP4[ix++], INPUT); } pinMode(P4, INPUT); // 4 → ix = 0; pinMode(P5, INPUT_PULLUP); for(int i=13; i<15; i++) // 13〜14 { pinMode(OP5[ix], OUTPUT); delay(1); inp = digitalRead(P5); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP5[ix++], INPUT); } pinMode(P5, INPUT); // 5 . 00 3 ix = 0; pinMode(P6, INPUT_PULLUP); for(int i=15; i<19; i++) // 15〜18 { pinMode(OP6[ix], OUTPUT); delay(1); inp = digitalRead(P6); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP6[ix++], INPUT); } pinMode(P6, INPUT); // + - % ix = 0; pinMode(P7, INPUT_PULLUP); for(int i=19; i<22; i++) // 19〜21 { pinMode(OP7[ix], OUTPUT); delay(1); inp = digitalRead(P7); if(inp != keyStat[i]) { if(!inp) keyCode = i; keyStat[i] = inp; } pinMode(OP7[ix++], INPUT); } pinMode(P7, INPUT); // M+ pinMode(P9, INPUT_PULLUP); pinMode(P11, OUTPUT); delay(1); inp = digitalRead(P9); if(inp != keyStat[22]) { if(!inp) keyCode = 22; keyStat[22] = inp; } pinMode(P9, INPUT); //pinMode(P11, INPUT); // M- pinMode(P10, INPUT_PULLUP); //pinMode(P11, OUTPUT); delay(1); inp = digitalRead(P10); if(inp != keyStat[23]) { if(!inp) keyCode = 23; keyStat[23] = inp; } pinMode(P10, INPUT); pinMode(P11, INPUT); } /// LCD /// void lcdInit() { digitalWrite(RS, LOW); digitalWrite(EN, LOW); delay(15); // 5Vのとき15ms待つ // HD44780の状態が不明なので確実に8ビットモードにしてから4ビットモードにする sendHalf(3); // ファンクション・セット 8ビットモード delay(5); // 4.1ms以上待つ sendHalf(3); // ファンクション・セット 8ビットモード delayMicroseconds(100); // 100μs以上待つ sendHalf(3); // 8ビットモード確定 delayMicroseconds(40); // 37μs以上待つ sendHalf(2); // ファンクション・セット 4ビットモード delayMicroseconds(40); // 37μs以上待つ instruction(0x28); // 2行表示 5×7ドット delayMicroseconds(40); // 37μs以上待つ instruction(0x0c); // ディスプレイON カーソルOFF ブリンクOFF delayMicroseconds(40); // 37μs以上待つ clearDisplay(); instruction(0x06); // カーソル右移動 表示シフトなし } void sendHalf(unsigned char ins) { digitalWrite(D4, ins & 1); digitalWrite(D5, (ins >> 1) & 1); digitalWrite(D6, (ins >> 2) & 1); digitalWrite(D7, (ins >> 3) & 1); digitalWrite(RS, LOW); delayMicroseconds(1); // 60ns以上待つ digitalWrite(EN, HIGH); delayMicroseconds(1); // 450ns以上待つ digitalWrite(EN, LOW); } void instruction(unsigned char ins) { digitalWrite(D4, (ins >> 4) & 1); digitalWrite(D5, (ins >> 5) & 1); digitalWrite(D6, (ins >> 6) & 1); digitalWrite(D7, (ins >> 7) & 1); digitalWrite(EN, HIGH); delayMicroseconds(1); // 450ns以上待つ digitalWrite(EN, LOW); digitalWrite(D4, ins & 1); digitalWrite(D5, (ins >> 1) & 1); digitalWrite(D6, (ins >> 2) & 1); digitalWrite(D7, (ins >> 3) & 1); digitalWrite(EN, HIGH); delayMicroseconds(1); // 450ns以上待つ digitalWrite(EN, LOW); } // 表示クリア&カーソルをホーム位置へ void clearDisplay() { row = 0; cursorPos = 0; digitalWrite(RS, LOW); instruction(1); // 表示クリア delay(2); // 1.52ms以上待つ } // カーソル位置設定 void setCursorPos(int x) { if(x < 0) x = 0; else if(x > 15) x = 15; cursorPos = x; if(row) x += 0x40; // 2行目 digitalWrite(RS, LOW); instruction(0x80 + x); // DDRAMアドレスセット delayMicroseconds(40); // 37μs以上待つ } // カーソル行設定 void setLine(int n) { if(n < 0) n = 0; else if(n > 1) n = 1; row = n; setCursorPos(cursorPos); } // ブリンクカーソル void blinkOnOff(int bl) // 1..ON 0..OFF { if(bl > 1) bl = 1; else if(bl < 0) bl = 0; digitalWrite(RS, LOW); instruction(0x08 | (displayON << 2) | (block << 1) | bl); // ディスプレイON/OFF delayMicroseconds(40); // 37μs以上待つ blinkCur = bl; } // ディスプレイ表示のオンオフ void displayOnOff(int onof) // 1..ON 0..OFF { if(onof > 1) onof = 1; else if(onof < 0) onof = 0; digitalWrite(RS, LOW); instruction(0x08 | (onof << 2) | (block << 1) | blinkCur); // ディスプレイON/OFF delayMicroseconds(40); // 37μs以上待つ displayON = onof; } // 1文字表示 void putChar(char c) { digitalWrite(RS, HIGH); instruction(c); // DDRAM書き込み delayMicroseconds(40); // 37μs以上待つ /* if(cursorDir == 1) // カーソル移動右方向 ++cursorPos; else // カーソル移動左方向 */ --cursorPos; } // 文字列表示 void putStr(uint8_t* str) { uint8_t* p; p = str; while(*p != 0) { putChar(*(p++)); } } // CGRAM書き込み void setCGdata(int no, char* cg) { if(no < 0) no = 0; else if(no > 7) no = 7; digitalWrite(RS, LOW); instruction(0x40 | no << 3); // CGRAMアドレスセット delayMicroseconds(40); // 37μs以上待つ /*if(cursorDir != 1) { // アドレスカウンタを自動インクリメントにする digitalWrite(RS, LOW); instruction(0x06 | shift); // エントリモードセット delayMicroseconds(40); // 37μs以上待つ }*/ // CGデータ書き込み digitalWrite(RS, HIGH); for(int i=0; i<8; i++) { instruction(0x40 | cg[i]); delayMicroseconds(40); // 37μs以上待つ } /*if(cursorDir != 1) { // アドレスカウンタをデクリメントにもどす digitalWrite(RS, LOW); instruction(0x04 | shift); // エントリモードセット delayMicroseconds(40); // 37μs以上待つ }*/ // DDRAMアクセスにもどす setCursorPos(cursorPos); }