BAR-LEDマイコンゲーム

・LEDが光ったところにあるスイッチを素早く押すという、モグラたたきゲームのような、とても簡素なゲームを作ってみた。

・ゲームは簡素だが、回路とソフトは結構複雑になってしまった。

BAR LED GAME with AT mega 168
BAR-LED GAME with ATMega 168 (CPU board)
Led Game Movin'

・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ボード)

BAR-LED GAME CPU board

(LEDとスイッチ)

LED & Switch

(バーLED)

BAR LED

※写真の回路では、バーLEDとCPUの接続を逆にしてしまったので、ファームウェアは修正してある。

ファームウェア ( led-game-mega168.c )

機能:

(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 4
volatile 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 0x00
int 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 Makefile
PROJECT=led-game-mega168
SOURCES=$(PROJECT).c
CC=avr-gcc
OBJCOPY=avr-objcopy
MMCU=atmega168
TARGETDEV=m168p
CFLAGS=-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).hex

sudo avrdude -p $(TARGETDEV) -P usb -c avrispmkII -e -U flash:w:$(PROJECT).hex

clean:

rm -f $(PROJECT).out

rm -f $(PROJECT).hex