#include #include #include #define I2C_ADDRESS 0x3C SSD1306AsciiAvrI2c oled; IRsend irsend; uint8_t IP[4] = {8, 7, 6, 5}; uint8_t OP[5] = {9, 10, 11, 12, 13}; uint8_t keyStat[5][4]; uint8_t keyin; const PROGMEM uint8_t keytable[] = { 11, 18, 12, 13, 9, 7, 14, 8, 6, 4, 10, 5, 3, 1, 15, 2, 16, 0, 17, 99 }; uint8_t mode = 0; void setup() { for(int i=0; i<4; i++) pinMode(IP[i], INPUT_PULLUP); for(int i=0; i<5; i++) pinMode(OP[i], INPUT); //ハイインピーダンスにする //キーの状態リセット for(int i=0; i<5; i++) for(int j=0; j<4; j++) keyStat[i][j] = 1; oled.begin(&Adafruit128x64, I2C_ADDRESS); oled.setFont(ZevvPeep8x16); oled.setScrollMode(SCROLL_MODE_AUTO); oled.clear(); } void loop() { switch(mode) { case 0: menu(); break; case 1: remocon(); break; case 2: calculator(); break; case 3: hexconv(); break; case 4: invader(); break; } } void menu() { uint8_t key, no = 1; bool loop = true; oled.clear(); selectMenu(no); while(loop) { key = getkey(); switch(key) { case 7: //8 if(--no == 0) no = 4; selectMenu(no); break; case 15: //2 if(++no == 5) no = 1; selectMenu(no); break; case 14: //Enter loop = false; break; } } mode = no; } void selectMenu(uint8_t sel) { oled.setInvertMode(0); oled.setCursor(0, 0); oled.print("Remote control"); oled.setCursor(0, 2); oled.print("Calculator"); oled.setCursor(0, 4); oled.print("HEX Converter"); oled.setCursor(0, 6); oled.print("Digital Invader"); oled.setInvertMode(1); switch(sel) { case 1: oled.setCursor(0, 0); oled.print("Remote control"); break; case 2: oled.setCursor(0, 2); oled.print("Calculator"); break; case 3: oled.setCursor(0, 4); oled.print("HEX Converter"); break; case 4: oled.setCursor(0, 6); oled.print("Digital Invader"); break; } oled.setInvertMode(0); } void remocon() { bool loop = true; uint8_t key; oled.clear(); oled.println("Push any key"); while(loop) { key = getkey(); switch(key) { case 2: //- 入力切替 oled.println("INPUT"); sendIR(0xA50, 12); break; case 10: //BS 戻る oled.println("BACK"); sendIR(0x62E9, 15); break; case 3: // / デジタル oled.println("DIGITAL"); sendIR(0x26E9, 15); break; case 0: //* BS oled.println("BS"); sendIR(0x1AE9, 15); break; case 6: //+ 2画面 oled.println("TWO"); sendIR(0x7725, 15); break; case 7: //8 ↑ oled.println("UP"); sendIR(0x2F0, 12); break; case 15: //2 ↓ oled.println("DOWN"); sendIR(0xAF0, 12); break; case 8: //6 → oled.println("RIGHT"); sendIR(0xCD0, 12); break; case 9: //4 ← oled.println("LEFT"); sendIR(0x2D0, 12); break; case 11: //5 決定 oled.println("OK"); sendIR(0xA70, 12); break; case 4: //9 音量+ oled.println("SOUND+"); sendIR(0x490, 12); break; case 12: //3 音量− oled.println("SOUND-"); sendIR(0xC90, 12); break; case 5: //7 チャンネル+ oled.println("CHANNEL+"); sendIR(0x90, 12); break; case 13: //1 チャンネル− oled.println("CHANNEL-"); sendIR(0x890, 12); break; case 17: //0 d oled.println("d"); sendIR(0x54E9, 15); break; case 16: //000 番組表 oled.println("PROGRAM"); sendIR(0x6D25, 15); break; case 14: //Enter 電源 oled.println("POWER"); sendIR(0xA90, 12); break; case 1: //NumLock リモコンのルーチンから抜ける loop = false; mode = 0; break; } } } void sendIR(int code, int nbit) { for (int i = 0; i < 3; i++) { irsend.sendSony(code, nbit); delay(40); } } void calculator() { uint8_t key, num, ope = 0; float fnum = 0, reg = 0, dot = 0; bool nextin = false; oled.clear(); oled.set2X(); oled.setCursor(0, 4); oled.print(0.0f); while(true) { key = getkey(); if(key == 255) continue; num = pgm_read_byte(keytable + key); if((num >= 0) && (num < 10)) //数字 { oled.setCursor(0, 4); if(nextin) { oled.clearToEOL(); fnum = 0.0f; nextin = false; } if(dot != 0) { if(dot < 1000.0f) //小数点以下二桁まで { fnum += (float)num / dot; dot *= 10.0f; } } else fnum = fnum * 10 + (float)num; if(fnum > 99999999.0f) fnum = 99999999.0f; oled.print(fnum); } else if(num == 17) //. { dot = 10.0f; } else if(num == 18) //NumLock { mode = 0; break; } else { dot = 0; switch(num) { case 10: //BS ope = 0; oled.setCursor(0, 0); oled.print(" "); oled.setCursor(0, 4); oled.clearToEOL(); fnum = 0.0f; reg = 0.0f; oled.print(fnum); break; case 11: //* if(ope != 0) { fnum = operation(fnum, reg, ope); reg = 0; oled.setCursor(0, 4); oled.print(fnum); } ope = 1; oled.setCursor(0, 0); oled.print("*"); reg = fnum; nextin = true; break; case 12: //- if(ope != 0) { fnum = operation(fnum, reg, ope); reg = 0; oled.setCursor(0, 4); oled.print(fnum); } ope = 2; oled.setCursor(0, 0); oled.print("-"); reg = fnum; nextin = true; break; case 13: // / if(ope != 0) { fnum = operation(fnum, reg, ope); reg = 0; oled.setCursor(0, 4); oled.print(fnum); } ope = 3; oled.setCursor(0, 0); oled.print("/"); reg = fnum; nextin = true; break; case 14: //+ if(ope != 0) { fnum = operation(fnum, reg, ope); reg = 0; oled.setCursor(0, 4); oled.print(fnum); } ope = 4; oled.setCursor(0, 0); oled.print("+"); reg = fnum; nextin = true; break; case 15: //Enter if(ope != 0) { fnum = operation(fnum, reg, ope); reg = 0; ope = 0; nextin = true; } oled.setCursor(0, 0); oled.print(" "); oled.setCursor(0, 4); oled.print(fnum); break; } } } oled.set1X(); } float operation(float a, float b, uint8_t ope) { float ret; switch(ope) { case 1: ret = b * a; break; case 2: ret = b - a; break; case 3: ret = b / a; break; case 4: ret = b + a; break; } return ret; } void hexconv() { uint8_t key, num, base = 0; uint32_t digit = 0; oled.clear(); oled.set2X(); oled.setCursor(0, 0); oled.print("DEC"); oled.setCursor(0, 4); oled.print(0); while(true) { key = getkey(); if(key == 255) continue; num = pgm_read_byte(keytable + key); if(num == 18) //NumLock { mode = 0; break; } if(num == 15) //Enter { if(++base == 3) base = 0; oled.clear(); if(base == 0) { oled.setCursor(0, 0); oled.print("DEC"); oled.setCursor(0, 4); oled.print(digit, DEC); } else if(base == 1) { oled.setCursor(0, 0); oled.print("HEX"); oled.setCursor(0, 4); oled.print(digit, HEX); } else if(base == 2) { oled.setCursor(0, 0); oled.print("BIN"); oled.setCursor(0, 5); oled.set1X(); oled.print(digit, BIN); oled.set2X(); } continue; } if((num >= 0) && (num < 10)) //数字 { if(base == 0) //10 { digit = digit * 10 + num; if(digit > 0xFFFF) digit = 0xFFFF; oled.setCursor(0, 4); oled.clearToEOL(); oled.print(digit, DEC); } else if(base == 1) //16 { digit = digit * 16 + num; if(digit > 0xFFFF) digit = 0xFFFF; oled.setCursor(0, 4); oled.clearToEOL(); oled.print(digit, HEX); } else //2 { if(num < 2) { digit = digit * 2 + num; if(digit > 0xFFFF) digit = 0xFFFF; oled.setCursor(0, 4); oled.clearToEOL(); oled.setCursor(0, 5); oled.set1X(); oled.print(digit, BIN); oled.set2X(); } } } else if((num > 10) && (num < 18)) //A-F { if(base == 1) //16 { switch(num) { case 13: // / A digit = digit * 16 + 10; break; case 11: // * B digit = digit * 16 + 11; break; case 12: // - C digit = digit * 16 + 12; break; case 14: // + D digit = digit * 16 + 13; break; case 16: // 000 E digit = digit * 16 + 14; break; case 17: // . F digit = digit * 16 + 15; break; } if(digit > 0xFFFF) digit = 0xFFFF; oled.setCursor(0, 4); oled.clearToEOL(); oled.print(digit, HEX); } } else if(num == 10) //BS { digit = 0; oled.setCursor(0, 4); oled.clearToEOL(); oled.print(0); } } oled.set1X(); } uint8_t cannon, aim, es, ew, ewait, shl, enl, rn; uint16_t score; bool clr, over; char ino[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'n', ' '}; uint8_t enemy[28]; uint32_t gameWait; void invader() { randomSeed(analogRead(17)); //未接続ピンのノイズを利用 cannon = 3; //砲台の数 aim = 0; //照準初期値 shl = 30; //ショット残りの数 enl = 16; //敵残りの数 es = 0; //敵表示開始位置 ew = 15; //敵移動ウェイト ewait = ew; rn = 1; //ラウンド数 score = 0; //スコア clr = false; //ラウンドクリア over = false; //ゲームオーバーフラグ oled.set2X(); oled.clear(); //敵生成 for(int i=0; i<6; i++) enemy[i] = 11; for(int i=6; i<22; i++) enemy[i] = random(9); for(int i=22; i<28; i++) enemy[i] = 11; showScore(); while(true) { oled.setCursor(0, 2); oled.print(ino[aim]); displeft(); //砲台数表示 gameLoop(); if(clr) { showScore(); //敵生成 for(int i=6; i<22; i++) enemy[i] = random(9); cannon = 3; //砲台の数 aim = 0; //照準初期値 shl = 30; //ショット残りの数 enl = 16; //敵残りの数 es = 0; //敵表示開始位置 --ew; //敵移動ウェイト ewait = ew; ++rn; //ラウンド数 clr = false; } else if(over) { gameOver(); break; } } } void gameLoop() { uint8_t key, po, sv, head, ufochk = 0; bool ufo = false, tame = false; while(true) { gameWait = millis(); if(enl == 0) { clr = true; break; } //敵表示 oled.setCursor(24, 2); po = es; for(int i=0; i<6; i++) { while(enemy[po] == 12) //消された敵 ++po; if(i == 0) head = enemy[po]; //敵侵入判定に使用 else if((i == 5) && ufo) { if(enemy[po] < 10) enemy[po] = 10; ufo = false; } oled.print(ino[enemy[po++]]); if(tame) //UFOを撃った { oled.invertDisplay(true); delay(300); oled.invertDisplay(false); tame = false; } } //敵侵入チェック if(over) { if(--cannon == 0) break; else over = false; aim = 0; oled.setCursor(0, 2); oled.print(ino[aim]); showScore(); displeft(); //砲台数表示 es = 0; } key = getkey(); if(key == 9) //照準 { if(++aim > 10) aim = 0; oled.setCursor(0, 2); oled.print(ino[aim]); } else if(key == 10) //ショット { if(shl == 0) //撃ち尽くした { over = true; break; } po = es; for(int i=0; i<6; i++) //当たり判定 { while(enemy[po] == 12) //消された敵 ++po; if(enemy[po] == aim) //当たり { if(i == 0) head = 12; //先頭の敵を消した enemy[po] = 12; //敵消す --es; //敵後退 --enl; //敵残り //スコア加算 if(aim == 10) //UFO { score += 300; tame = true; } else if(aim != 0) { score += (i + 1) * 10; //UFO出現チェック ufochk += aim; if((ufochk % 10) == 0) { ufo = true; ufochk = 0; } } break; } ++po; } --shl; //ショット残り } //敵移動 if(--ewait == 0) { ++es; if(head < 11) //敵侵入 over = true; ewait = ew; //敵移動ウェイト } //ゲーム全体のウェイト while((millis() - gameWait) < 100); } } void gameOver() { uint8_t key; oled.clear(); oled.setCursor(0, 2); oled.print(rn); oled.print("-"); oled.print(score); oled.set1X(); oled.setCursor(0, 6); oled.print("GAME OVER"); while(true) { key = getkey(); if(key == 255) continue; if(key ==1) //NumLock { mode = 0; break; } } } void showScore() { oled.clear(); oled.setCursor(0, 2); oled.print(rn); oled.print("-"); oled.print(score); delay(3000); } void displeft() { oled.setCursor(16, 2); oled.print(" "); oled.set1X(); if(cannon > 2) { oled.setCursor(16, 2); oled.print("-"); } if(cannon > 1) { oled.setCursor(16, 3); oled.print("-"); } oled.setCursor(16, 4); oled.print("-"); oled.set2X(); } uint8_t getkey() { uint8_t value = 255; for(int i=0; i<5; i++) { pinMode(OP[i], OUTPUT); digitalWrite(OP[i], LOW); delay(1); //信号線の状態が安定するのを待つ for(int j=0; j<4; j++) { keyin = digitalRead(IP[j]); if(keyin != keyStat[i][j]) { if(!keyin) value = i * 4 + j; keyStat[i][j] = keyin; } } pinMode(OP[i], INPUT); //ハイインピーダンスにする } return value; }