・LEDが光ったところにあるスイッチを素早く押すという、モグラたたきゲームのような、とても簡素なゲームを作ってみた。
・ゲームは簡素だが、回路とソフトは結構複雑になってしまった。
・CPUボードと電池ボックスは下層に収納して、コンパクト感を演出?
・もっと大きなLEDやスイッチにすれば、文化祭のゲームコーナーに出品して人気になるかもしれない。
マイコン ATMEL ATmega168P-20PU
オプトサプライ10バーLEDアレイ 3色(緑5黄3赤2)タイプ OSX10201-GYR1
φ5mmLED (色はお好みで)×4個
圧電サウンダ(他励振) Murata PKM13EPYH4000-A0
カーボン抵抗器 470Ω x 14個、10kΩ
積層セラミックコンデンサ 0.1uF x 5個
ピンヘッダ 2x3 ( ISP用 )
タクトスイッチ 5個
スライドスイッチ
ピンヘッダ 1x12(4、4、1、1、2に分割して使用)
ボックスコネクタ 4本用×2、1本用×4
電池ボックス 単三型3本用
電池スナップ
ユニバーサル基板 70mm x 45mm ×3枚
スペーサ類 適宜
(CPUボード)
(LEDとスイッチ)
(バーLED)
※写真の回路では、バーLEDとCPUの接続を逆にしてしまったので、ファームウェアは修正してある。
機能:
(1)スライドスイッチを入れると、バーLEDが順に点灯し、すべてのLEDが点灯する。
(2)バーLEDのすべてのLEDが点滅する。
(3)スタートスイッチを押すと、ゲーム開始。
(4)点灯しているLEDの下にあるスイッチを押すと、得点が1点加算され、バーLEDが得点の数だけ点灯する。
(5)間違ったボタンを押すと、得点は0になる。
(6)得点が10点になると、音とともにバーLEDが短い間隔で点灯する。
(7)スタートスイッチを押すと、バーLEDが点滅し、待機状態になる。(2)に戻る。
(4)〜(6)の間でスタートスイッチを押すと、(2)に戻る。
//// led-game-mega168.c// //// Created by kaimunantai on 2013/10/20.//// TARGET : ATmega168//// [ Output ]// LED 1,2,3,4 : PB2, PB3, PB4, PB5// Buzzer : PB1// 10-BAR LED 0-9 : PD0, PD1, PD3, PD4, PB6, PB7, PD5, PD6, PD7, PB0// LED No.// 0 1 2 3 4 5 6 7 8 9//// [ Input ]// Switch 1, 2, 3, 4 : PC0, PC1, PC2, PC3// Start switch : PD2(INT0)//#include <avr/io.h>#include <avr/interrupt.h>#include <stdlib.h>void wait(volatile unsigned long i){ while( i-- > 0 );}void InitPort(void)// Initialize I/O Ports{ DDRB = 0xff; // PORTB Output : all PORTC = 0xff; // pull up reg enable DDRC = ~( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) ); // PC0,1,2,3 : Input, Others: Output PORTD = 0xff; // pull up reg enable DDRD = ~(1<<PD2); // PD2 : Input, Others: Output }#define Led1On() ( PORTB |= (1<<PB2) )#define Led2On() ( PORTB |= (1<<PB3) )#define Led3On() ( PORTB |= (1<<PB4) )#define Led4On() ( PORTB |= (1<<PB5) )#define Led1Off() ( PORTB &= ~(1<<PB2) )#define Led2Off() ( PORTB &= ~(1<<PB3) )#define Led3Off() ( PORTB &= ~(1<<PB4) )#define Led4Off() ( PORTB &= ~(1<<PB5) )#define Buz() ( PORTB ^= (1<<PB1) )#define IsStartSwOn() ( !(PIND & (1<<PD2)) )#define IsSw1On() ( (~PINC) & (1<<PC0) )#define IsSw2On() ( (~PINC) & (1<<PC1) )#define IsSw3On() ( (~PINC) & (1<<PC2) )#define IsSw4On() ( (~PINC) & (1<<PC3) )#define IsSwOn() ( (~PINC) & ( (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) ) )#define BarLed0Off() (PORTD &= ~(1<<PD0) )#define BarLed0On() (PORTD |= (1<<PD0) )#define BarLed0() (PORTD ^= (1<<PD0) )#define BarLed1Off() (PORTD &= ~(1<<PD1) )#define BarLed1On() (PORTD |= (1<<PD1) )#define BarLed1() (PORTD ^= (1<<PD1) )#define BarLed2Off() (PORTD &= ~(1<<PD3) )#define BarLed2On() (PORTD |= (1<<PD3) )#define BarLed2() (PORTD ^= (1<<PD3) )#define BarLed3Off() (PORTD &= ~(1<<PD4) )#define BarLed3On() (PORTD |= (1<<PD4) )#define BarLed3() (PORTD ^= (1<<PD4) )#define BarLed4Off() (PORTB &= ~(1<<PB6) )#define BarLed4On() (PORTB |= (1<<PB6) )#define BarLed4() (PORTB ^= (1<<PB6) )#define BarLed5Off() (PORTB &= ~(1<<PB7) )#define BarLed5On() (PORTB |= (1<<PB7) )#define BarLed5() (PORTB ^= (1<<PB7) )#define BarLed6Off() (PORTD &= ~(1<<PD5) )#define BarLed6On() (PORTD |= (1<<PD5) )#define BarLed6() (PORTD ^= (1<<PD5) )#define BarLed7Off() (PORTD &= ~(1<<PD6) )#define BarLed7On() (PORTD |= (1<<PD6) )#define BarLed7() (PORTD ^= (1<<PD6) )#define BarLed8Off() (PORTD &= ~(1<<PD7) )#define BarLed8On() (PORTD |= (1<<PD7) )#define BarLed8() (PORTD ^= (1<<PD7) )#define BarLed9Off() (PORTB &= ~(1<<PB0) )#define BarLed9On() (PORTB |= (1<<PB0) )#define BarLed9() (PORTB ^= (1<<PB0) )void Led1234(unsigned char pattern){ if (pattern & 0b00000001) { Led1On(); } else { Led1Off(); } if (pattern & (0b00000010)) { Led2On(); } else { Led2Off(); } if (pattern & (0b00000100)) { Led3On(); } else { Led3Off(); } if (pattern & (0b00001000)) { Led4On(); } else { Led4Off(); }}void BarLed(unsigned int number){ switch (number) { case 0: BarLed0Off(); BarLed1Off(); BarLed2Off(); BarLed3Off(); BarLed4Off(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 1: BarLed0On(); BarLed1Off(); BarLed2Off(); BarLed3Off(); BarLed4Off(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 2: BarLed0On(); BarLed1On(); BarLed2Off(); BarLed3Off(); BarLed4Off(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 3: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3Off(); BarLed4Off(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 4: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4Off(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 5: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5Off(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 6: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5On(); BarLed6Off(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 7: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5On(); BarLed6On(); BarLed7Off(); BarLed8Off(); BarLed9Off(); break; case 8: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5On(); BarLed6On(); BarLed7On(); BarLed8Off(); BarLed9Off(); break; case 9: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5On(); BarLed6On(); BarLed7On(); BarLed8On(); BarLed9Off(); break; case 10: BarLed0On(); BarLed1On(); BarLed2On(); BarLed3On(); BarLed4On(); BarLed5On(); BarLed6On(); BarLed7On(); BarLed8On(); BarLed9On(); break; default: BarLed0(); BarLed1(); BarLed2(); BarLed3(); BarLed4(); BarLed5(); BarLed6(); BarLed7(); BarLed8(); BarLed9(); }}void Beep(unsigned int period, volatile unsigned int length)// Buzzer ON/OFF{ volatile unsigned int i; while (length-- > 0) { Buz(); for ( i = 0; i < period; i++); }}unsigned char GenerateNumber(){ static unsigned char number = 0; number += (unsigned char)(rand() % 3 + 1); if (number > 4) { number -= 4; } return number;}void GameOver(void){ volatile unsigned int i; BarLed(10); Beep(2, 1000); BarLed(0); Beep(10, 200);}void OpeningDemo(void){ volatile unsigned int i; Led1234(0b0000); for (i = 0; i <= 10; i++) { BarLed(i); wait(5000); Beep(11 - i ,100); }}// Phase Identifier of Sequence#define PHASE_READY 0#define PHASE_GAME_START 1#define PHASE_GAME_GENERATE_NUMBER 2#define PHASE_GAME_HIT_OR_MISS 3#define PHASE_GAME_OVER 4volatile unsigned int Phase = PHASE_READY;void InitInt0(void)// Initialize Interrupt (INT0){ EIMSK |= (1<<INT0); // INT0 interrupt enable EICRA |= (1<<ISC01) | (0<<ISC00); // The falling edge ofINT0 or INT1 sei(); // Enabel Interrupt}ISR(INT0_vect){ switch (Phase) { case PHASE_READY: Phase = PHASE_GAME_START; break; default: BarLed(0); Phase = PHASE_READY; } while(IsStartSwOn());}#define FLAG_HIT 0x01#define FLAG_MISS 0x00int main(void){ volatile unsigned int i; // Timing Counter volatile unsigned char answer; // LED Lighting Position number 1,2,3,4 volatile unsigned int ishit; // Flag of HIT or MISS volatile unsigned int score = 0; // Score InitPort(); InitInt0(); OpeningDemo(); while (IsStartSwOn()); // wait for StartSwitch off while (1) { switch (Phase) { case PHASE_READY : score = 0; Led1234(0b0000); BarLed(11); wait(10000);// Blink Bar LED break; case PHASE_GAME_START : score = 0; Beep(8,1024); Phase = PHASE_GAME_GENERATE_NUMBER; break; case PHASE_GAME_GENERATE_NUMBER : // Generate Lighting LED number answer = GenerateNumber(); Led1234((1<<(answer - 1))); BarLed(score); Phase = PHASE_GAME_HIT_OR_MISS; break; case PHASE_GAME_HIT_OR_MISS : for (ishit = FLAG_MISS, i = 0; i < 20000; i++) { if (IsSwOn()) { if (answer == 1 && IsSw1On()) { Beep(2, 1024); ishit = FLAG_HIT; break; } else if (answer == 2 && IsSw2On()) { Beep(4, 512); ishit = FLAG_HIT; break; } else if (answer == 3 && IsSw3On()) { Beep(8, 256); ishit = FLAG_HIT; break; } else if (answer == 4 && IsSw4On()) { Beep(16, 128); ishit = FLAG_HIT; break; } else { // MISS ! ishit = FLAG_MISS; break; } } } if (ishit == FLAG_HIT) { if (score >=0 && score < 10) { score++; Phase = PHASE_GAME_GENERATE_NUMBER; } else { Phase = PHASE_GAME_OVER; } } else { Beep(128, 128); if (Phase != PHASE_READY) { Phase = PHASE_GAME_GENERATE_NUMBER; } score = 0; } while (IsSwOn()); break; case PHASE_GAME_OVER : // Game OVER GameOver(); break; default : score = 0; BarLed(0); } } return 0;}Makefile
# AVR-GCC MakefilePROJECT=led-game-mega168SOURCES=$(PROJECT).cCC=avr-gccOBJCOPY=avr-objcopyMMCU=atmega168TARGETDEV=m168pCFLAGS=-mmcu=$(MMCU) -Wall$(PROJECT).hex: $(PROJECT).out$(OBJCOPY) -j .text -O ihex $(PROJECT).out $(PROJECT).hex
$(PROJECT).out: $(SOURCES)$(CC) $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program: $(PROJECT).hexsudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex
clean:rm -f $(PROJECT).out
rm -f $(PROJECT).hex