Initial Commit of Simon code for 'C' version and Arduino Sketch version (Yes, I know they're the same thing but spare me).

This commit is contained in:
Ryan Owens 2011-03-24 16:05:35 -06:00
commit 3475e99530
19 changed files with 2617 additions and 0 deletions

556
Simon_C/Makefile Normal file
View File

@ -0,0 +1,556 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# MCU name
MCU = atmega328
# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
F_CPU = 8000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Target file name (without extension).
TARGET = Simon
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)UL
# Place -I options here
CINCS =
#---------------- Compiler Options ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#---------------- Programming Options (avrdude serial bootloader) ----------------
#"C:\arduino\hardware\tools\avr\bin\avrdude" -PCOM3 -c stk500v1 -patmega168 -b19200 -Uflash:w:Simon-PTH-v1.hex -V -F -C"C:\arduino\hardware\tools\avr\etc\avrdude.conf"
#avrdude -PCOM3 -c stk500v1 -patmega168 -b19200 -Uflash:w:Simon-PTH-v1.hex -V -F
SERIAL_AVRDUDE = avrdude
#SERIAL_AVRDUDE_CONFIG = "C:\arduino\hardware\tools\avr\etc\avrdude.conf"
SERIAL_AVRDUDE_PORT = COM3
SERIAL_AVRDUDE_SPEED = 19200
SERIAL_AVRDUDE_PROGRAMMER = stk500v1
SERIAL_AVRDUDE_FLAGS = -p $(MCU) -P $(SERIAL_AVRDUDE_PORT) -c $(SERIAL_AVRDUDE_PROGRAMMER) -b$(SERIAL_AVRDUDE_SPEED)
#SERIAL_AVRDUDE_FLAGS += -C$(SERIAL_AVRDUDE_CONFIG)
SERIAL_AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
SERIAL_AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
SERIAL_AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Programming Options (avrdude) ----------------
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
AVRDUDE_PROGRAMMER = stk200
#AVRDUDE_PROGRAMMER = ponyser
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = lpt1
#AVRDUDE_PORT = COM1
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Programming Options (STK500) ----------------
# Programming hardware: stk500 (the AVR MKII ISP version)
STK500 = stk500
# Location of STK500.exe - no trailing '\'
STK500_PATH = C:\Program Files\Atmel\AVR Tools\STK500
# The STK500 AVR ISP MKII is USB. The USB drivers must already be installed.
# Do this normally by installing AVR Studio.
STK500_PORT = USB
#-erase chip -Program Flash -Verify Flash -File name -Serial programing(ISP)
STK500_WRITE_FLASH = -e -pf -vf -if$(TARGET).hex -ms
STK500_FLAGS = -d$(MCU) -c$(STK500_PORT)
#-Set ISP frequency to 250kHz. Limit is 1/4 of internal osc which is default 1MHz
#Reduce this to 100kHz if you run into flash verification problems in low-voltage systems
STK500_FLAGS += -I250kHz
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(SRC:.c=.lst) $(ASRC:.S=.lst)
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter end
build: elf hex eep lss sym
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
#New
ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
#Old
#ELFSIZE = $(SIZE) -A $(TARGET).elf
AVRMEM = avr-mem.sh $(TARGET).elf $(MCU)
sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
$(AVRMEM) 2>/dev/null; echo; fi
sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
$(AVRMEM) 2>/dev/null; echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
program_stk500: $(TARGET).hex $(TARGET).eep
$(STK500_PATH)\$(STK500) $(STK500_FLAGS) $(STK500_WRITE_FLASH)
program_serial: $(TARGET).hex $(TARGET).eep
$(SERIAL_AVRDUDE) $(SERIAL_AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) .dep/*
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

641
Simon_C/Simon.c Normal file
View File

@ -0,0 +1,641 @@
/**
* 6-19-2007
* Copyright 2009, Spark Fun Electronics
* Nathan Seidle
* nathan at sparkfun.com
*
* Released under the Creative Commons Attribution Share-Alike 3.0 License
* http://creativecommons.org/licenses/by-sa/3.0
*
* Simon Game ported for the ATmega168
*
* Fixes and cleanup by Joshua Neal <joshua[at]trochotron.com>
*
* Generates random sequence, plays music, and displays button lights.
*
* Simon tones from Wikipedia
* - A (red, upper left) - 440Hz - 2.272ms - 1.136ms pulse
* - a (green, upper right, an octave higher than A) - 880Hz - 1.136ms,
* 0.568ms pulse
* - D (blue, lower left, a perfect fourth higher than the upper left)
* 587.33Hz - 1.702ms - 0.851ms pulse
* G (yellow, lower right, a perfect fourth higher than the lower left) -
* 784Hz - 1.276ms - 0.638ms pulse
*
* The tones are close, but probably off a bit, but they sound all right.
*
* The old version of SparkFun simon used an ATmega8. An ATmega8 ships
* with a default internal 1MHz oscillator. You will need to set the
* internal fuses to operate at the correct external 16MHz oscillator.
*
* Original Fuses:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m
*
* Command to set to fuses to use external 16MHz:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xEE:m -U hfuse:w:0xC9:m
*
* The current version of Simon uses the ATmega168. The external osciallator
* was removed to reduce component count. This version of simon relies on the
* internal default 1MHz osciallator. Do not set the external fuses.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
/* Uncomment one of the following, corresponding to the board you have. */
//#define BOARD_REV_6_25_08
//#define BOARD_REV_4_9_2009
//#define BOARD_REV_6_3_2009
#define BOARD_REV_PTH
#ifdef BOARD_REV_PTH
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 3
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 1
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 2
#define BUTTON_GREEN_PORT PIND
#define BUTTON_BLUE_PIN 4
#define BUTTON_BLUE_PORT PINB
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 4
#define BUZZER1_PORT PORTD
#define BUZZER2 7
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_PTH */
#ifdef BOARD_REV_6_25_08
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 3
#define LED_RED_PORT PORTC
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 0
#define LED_BLUE_PORT PORTC
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 2
#define BUTTON_RED_PORT PINC
#define BUTTON_GREEN_PIN 5
#define BUTTON_GREEN_PORT PINC
#define BUTTON_BLUE_PIN 1
#define BUTTON_BLUE_PORT PINC
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
#define CHIP_ATMEGA168
/* LED pin definitions */
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 0
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 1
#define BUTTON_GREEN_PORT PINB
#define BUTTON_BLUE_PIN 7
#define BUTTON_BLUE_PORT PIND
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_4_9_2009 */
#ifdef BOARD_REV_6_3_2009
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 0
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 1
#define BUTTON_GREEN_PORT PINB
#define BUTTON_BLUE_PIN 7
#define BUTTON_BLUE_PORT PIND
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_6_3_2009 */
/* Define game parameters */
#define MOVES_TO_WIN 14
#define TIME_LIMIT 3000 /* 3000ms = 3 sec */
#define sbi(port_name, pin_number) (port_name |= 1<<pin_number)
#define cbi(port_name, pin_number) \
((port_name) &= (uint8_t)~(1 << pin_number))
/* Declarations for static functions */
static void delay_us(uint16_t delay);
static void delay_ms(uint16_t delay);
static uint8_t check_button(void);
static void set_leds(uint8_t leds);
static void buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay);
static void toner(uint8_t tone, uint16_t buzz_length_ms);
static void add_to_moves(void);
static void play_moves(void);
static void play_loser(void);
static void play_winner(void);
static void ioinit(void);
/* Game state */
uint8_t moves[32];
uint8_t nmoves = 0;
ISR (SIG_OVERFLOW2)
{
/*
* Prescalar of 1024
* Clock = 16MHz
* 15,625 clicks per second
* 64us per click
*/
/* Preload timer 2 for 125 clicks. Should be 8ms per ISR call */
TCNT2 = 131; /* 256 - 125 = 131 */
}
/* General short delays, using internal timer do a fairly accurate 1us */
#ifdef CHIP_ATMEGA168
static void delay_us(uint16_t delay)
{
while (delay > 256)
{
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
TCNT0 = 0;
while ( (TIFR0 & (1<<TOV0)) == 0);
delay -= 256;
}
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
/*
* 256 - 125 = 131 : Preload timer 0 for x clicks.
* Should be 1us per click
*/
TCNT0 = 256 - delay;
while ((TIFR0 & (1<<TOV0)) == 0) {
/* do nothing */
}
}
#endif
/* General short delays */
void delay_ms(uint16_t x)
{
while (x-- > 0) {
delay_us(1000);
}
}
/* Light the given set of LEDs */
static void set_leds(uint8_t leds)
{
if ((leds & LED_RED) != 0) {
sbi(LED_RED_PORT, LED_RED_PIN);
} else {
cbi(LED_RED_PORT, LED_RED_PIN);
}
if ((leds & LED_GREEN) != 0) {
sbi(LED_GREEN_PORT, LED_GREEN_PIN);
} else {
cbi(LED_GREEN_PORT, LED_GREEN_PIN);
}
if ((leds & LED_BLUE) != 0) {
sbi(LED_BLUE_PORT, LED_BLUE_PIN);
} else {
cbi(LED_BLUE_PORT, LED_BLUE_PIN);
}
if ((leds & LED_YELLOW) != 0) {
sbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
} else {
cbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
}
}
#ifdef BOARD_REV_6_25_08
static void init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111111;
DDRC = 0b00001001; /* LEDs and Buttons */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTC = 0b00100110; /* Enable pull-ups on buttons 0,2,3 */
PORTD = 0b01000000; /* Enable pull-up on button 1 */
}
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
static void init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111100; /* button 2,3 on PB0,1 */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTB = 0b00000011; /* Enable pull-ups on buttons 2,3 */
PORTD = 0b11000000; /* Enable pull-up on button 0,1 */
}
#endif /* BOARD_REV_4_9_2009 */
#ifdef BOARD_REV_PTH
static void init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0xFF & ~(1<<BUTTON_BLUE_PIN) & ~(1<<BUTTON_RED_PIN); // Buttons are inputs, LEDs outputs
DDRC = 0x00; //All pins are open GPIOs
DDRD = 0xFF & ~(1<<BUTTON_GREEN_PIN) & ~(1<<BUTTON_YELLOW_PIN); //
//DDRB = 0b11111100; /* button 2,3 on PB0,1 */
//DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTB = (1<<BUTTON_BLUE_PIN) | (1<<BUTTON_RED_PIN); // Enable pull-ups on button
PORTC = 0xFF;
PORTD = (1<<BUTTON_GREEN_PIN) | (1<<BUTTON_YELLOW_PIN); // Enable pull-up on button
}
#endif /* BOARD_REV_PTH */
#ifdef BOARD_REV_6_3_2009
static void init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0xFF & ~(1<<BUTTON_GREEN_PIN) & ~(1<<BUTTON_RED_PIN); // Buttons are inputs, LEDs outputs
DDRC = 0x00; //All pins are open GPIOs
DDRD = 0xFF & ~(1<<BUTTON_BLUE_PIN) & ~(1<<BUTTON_YELLOW_PIN); //
PORTB = (1<<BUTTON_GREEN_PIN) | (1<<BUTTON_RED_PIN); // Enable pull-ups on button
PORTC = 0xFF;
PORTD = (1<<BUTTON_BLUE_PIN) | (1<<BUTTON_YELLOW_PIN); // Enable pull-up on button
}
#endif /* BOARD_REV_6_3_2009 */
void ioinit(void)
{
init_gpio();
/* Init timer 0 for delay_us timing (1,000,000 / 1 = 1,000,000) */
//TCCR0B = (1<<CS00); //Set Prescaler to No Prescaling. 1clk = 1us (assume we are running at internal 1MHz). CS00=1
TCCR0B = (1<<CS01); //Set Prescaler to clk/8 : 1click = 1us(assume we are running at internal 8MHz). CS01=1
//TCCR0B = (1<<CS00); /* Set Prescaler to 1. CS00=1 */
/* Init timer 2 */
ASSR = 0;
/* Set Prescaler to 1024. CS22=1, CS21=1,CS20=1 */
TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20);
TIMSK2 = (1<<TOIE2); /* Enable Timer 2 Interrupt */
sei();
}
/* Returns a '1' bit in the position corresponding to LED_RED, etc. */
uint8_t check_button(void)
{
uint8_t button_pressed = 0;
if ((BUTTON_RED_PORT & (1 << BUTTON_RED_PIN)) == 0)
button_pressed |= LED_RED;
if ((BUTTON_GREEN_PORT & (1 << BUTTON_GREEN_PIN)) == 0)
button_pressed |= LED_GREEN;
if ((BUTTON_BLUE_PORT & (1 << BUTTON_BLUE_PIN)) == 0)
button_pressed |= LED_BLUE;
if ((BUTTON_YELLOW_PORT & (1 << BUTTON_YELLOW_PIN)) == 0)
button_pressed |= LED_YELLOW;
return button_pressed;
}
/* Play the loser sound/lights */
void play_loser(void)
{
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
}
/* Play the winner sound */
static void winner_sound(void)
{
uint8_t x, y;
/* Toggle the buzzer at various speeds */
for (x = 250; x > 70; x--) {
for (y = 0; y < 3; y++) {
sbi(BUZZER2_PORT, BUZZER2);
cbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
cbi(BUZZER2_PORT, BUZZER2);
sbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
}
}
}
/* Play the winner sound and lights */
void play_winner(void)
{
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
}
/* Plays the current contents of the game moves */
static void play_moves(void)
{
uint8_t move;
for (move = 0; move < nmoves; move++) {
toner(moves[move], 150);
delay_ms(150);
}
}
/* Adds a new random button to the game sequence, by sampling the timer */
static void add_to_moves(void)
{
uint8_t new_button;
/* Use the lower 2 bits of the timer for the random value */
new_button = 1 << (TCNT2 & 0x3);
moves[nmoves++] = new_button;
}
/* Toggle buzzer every buzz_delay_us, for a duration of buzz_length_ms. */
static void buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay_us)
{
uint32_t buzz_length_us;
buzz_length_us = buzz_length_ms * (uint32_t)1000;
while (buzz_length_us > buzz_delay_us*2) {
buzz_length_us -= buzz_delay_us*2;
/* toggle the buzzer at various speeds */
cbi(BUZZER1_PORT, BUZZER1);
sbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
sbi(BUZZER1_PORT, BUZZER1);
cbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
}
}
/*
* Light an LED and play tone
*
* red, upper left: 440Hz - 2.272ms - 1.136ms pulse
* green, upper right: 880Hz - 1.136ms - 0.568ms pulse
* blue, lower left: 587.33Hz - 1.702ms - 0.851ms pulse
* yellow, lower right: 784Hz - 1.276ms - 0.638ms pulse
*/
static void toner(uint8_t which, uint16_t buzz_length_ms)
{
set_leds(which);
switch (which) {
case LED_RED:
buzz_sound(buzz_length_ms, 1136);
break;
case LED_GREEN:
buzz_sound(buzz_length_ms, 568);
break;
case LED_BLUE:
buzz_sound(buzz_length_ms, 851);
break;
case LED_YELLOW:
buzz_sound(buzz_length_ms, 638);
break;
}
/* Turn off all LEDs */
set_leds(0);
}
/* Show an "attract mode" display while waiting for user to press button. */
static void attract_mode(void)
{
while (1) {
set_leds(LED_RED);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_BLUE);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_GREEN);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_YELLOW);
delay_ms(100);
if (check_button() != 0x00)
return;
}
}
/* Wait for a button to be pressed. Returns one of led colors (LED_RED, etc.)
* if successful, 0 if timed out */
static uint8_t wait_for_button(void)
{
uint16_t time_limit = TIME_LIMIT;
uint8_t released = 0;
uint8_t old_button;
while (time_limit > 0) {
uint8_t button;
/* Implement a small bit of debouncing */
old_button = button;
button = check_button();
/*
* Make sure we've seen the previous button
* released before accepting new buttons
*/
if (button == 0)
released = 1;
if (button == old_button && released == 1) {
/* Make sure just one button is pressed */
if (button == LED_RED ||
button == LED_BLUE ||
button == LED_GREEN ||
button == LED_YELLOW) {
return button;
}
}
delay_ms(1);
time_limit--;
}
return 0; /* Timed out */
}
/* Play the game. Returns 0 if player loses, or 1 if player wins. */
static int game_mode(void)
{
nmoves = 0;
while (nmoves < MOVES_TO_WIN) {
uint8_t move;
/* Add a button to the current moves, then play them back */
add_to_moves();
play_moves();
/* Then require the player to repeat the sequence. */
for (move = 0; move < nmoves; move++) {
uint8_t choice = wait_for_button();
/* If wait timed out, player loses. */
if (choice == 0)
return 0;
toner(choice, 150);
/* If the choice is incorect, player loses. */
if (choice != moves[move]) {
return 0;
}
}
/* Player was correct, delay before playing moves */
delay_ms(1000);
}
/* player wins */
return 1;
}
int main(void)
{
/* Setup IO pins and defaults */
ioinit();
/* Main loop */
while (1) {
/* Wait for user to start game */
attract_mode();
/* Indicate the start of game play */
set_leds(LED_RED|LED_GREEN|LED_BLUE|LED_YELLOW);
delay_ms(1000);
set_leds(0);
delay_ms(250);
if (game_mode() != 0) {
/* Player won, play winner tones */
play_winner();
} else {
/* Player lost, play loser tones */
play_loser();
}
}
return(0);
}

View File

@ -0,0 +1,652 @@
/**
* 6-19-2007
* Copyright 2009, Spark Fun Electronics
* Nathan Seidle
* nathan at sparkfun.com
*
* Released under the Creative Commons Attribution Share-Alike 3.0 License
* http://creativecommons.org/licenses/by-sa/3.0
*
* Simon Game ported for the ATmega168
*
* Fixes and cleanup by Joshua Neal <joshua[at]trochotron.com>
*
* Generates random sequence, plays music, and displays button lights.
*
* Simon tones from Wikipedia
* - A (red, upper left) - 440Hz - 2.272ms - 1.136ms pulse
* - a (green, upper right, an octave higher than A) - 880Hz - 1.136ms,
* 0.568ms pulse
* - D (blue, lower left, a perfect fourth higher than the upper left)
* 587.33Hz - 1.702ms - 0.851ms pulse
* G (yellow, lower right, a perfect fourth higher than the lower left) -
* 784Hz - 1.276ms - 0.638ms pulse
*
* The tones are close, but probably off a bit, but they sound all right.
*
* The old version of SparkFun simon used an ATmega8. An ATmega8 ships
* with a default internal 1MHz oscillator. You will need to set the
* internal fuses to operate at the correct external 16MHz oscillator.
*
* Original Fuses:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m
*
* Command to set to fuses to use external 16MHz:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xEE:m -U hfuse:w:0xC9:m
*
* The current version of Simon uses the ATmega168. The external osciallator
* was removed to reduce component count. This version of simon relies on the
* internal default 1MHz osciallator. Do not set the external fuses.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
/* Uncomment one of the following, corresponding to the board you have. */
//#define BOARD_REV_6_25_08
// #define BOARD_REV_4_9_2009
//#define BOARD_REV_6_3_2009
#define BOARD_REV_PTH
#ifdef BOARD_REV_PTH
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 3
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 1
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 2
#define BUTTON_GREEN_PORT PIND
#define BUTTON_BLUE_PIN 4
#define BUTTON_BLUE_PORT PINB
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 4
#define BUZZER1_PORT PORTD
#define BUZZER2 7
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_PTH */
#ifdef BOARD_REV_6_25_08
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 3
#define LED_RED_PORT PORTC
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 0
#define LED_BLUE_PORT PORTC
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 2
#define BUTTON_RED_PORT PINC
#define BUTTON_GREEN_PIN 5
#define BUTTON_GREEN_PORT PINC
#define BUTTON_BLUE_PIN 1
#define BUTTON_BLUE_PORT PINC
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
#define CHIP_ATMEGA168
/* LED pin definitions */
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 0
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 1
#define BUTTON_GREEN_PORT PINB
#define BUTTON_BLUE_PIN 7
#define BUTTON_BLUE_PORT PIND
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_4_9_2009 */
#ifdef BOARD_REV_6_3_2009
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 0
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 1
#define BUTTON_GREEN_PORT PINB
#define BUTTON_BLUE_PIN 7
#define BUTTON_BLUE_PORT PIND
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_6_3_2009 */
/* Define game parameters */
#define MOVES_TO_WIN 13
#define TIME_LIMIT 3000 /* 3000ms = 3 sec */
#define sbi(port_name, pin_number) (port_name |= 1<<pin_number)
#define cbi(port_name, pin_number) \
((port_name) &= (uint8_t)~(1 << pin_number))
/* Declarations for static functions */
void delay_us(uint16_t delay);
void delay_ms(uint16_t delay);
uint8_t check_button(void);
void set_leds(uint8_t leds);
void buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay);
void toner(uint8_t tone, uint16_t buzz_length_ms);
void add_to_moves(void);
void play_moves(void);
void play_loser(void);
void play_winner(void);
void ioinit(void);
/* Game state */
uint8_t moves[32];
uint8_t nmoves = 0;
ISR (SIG_OVERFLOW2)
{
/*
* Prescalar of 1024
* Clock = 16MHz
* 15,625 clicks per second
* 64us per click
*/
/* Preload timer 2 for 125 clicks. Should be 8ms per ISR call */
TCNT2 = 131; /* 256 - 125 = 131 */
}
/* General short delays, using internal timer do a fairly accurate 1us */
#ifdef CHIP_ATMEGA168
void
delay_us(uint16_t delay)
{
while (delay > 256)
{
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
TCNT0 = 0;
while ( (TIFR0 & (1<<TOV0)) == 0);
delay -= 256;
}
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
/*
* 256 - 125 = 131 : Preload timer 0 for x clicks.
* Should be 1us per click
*/
TCNT0 = 256 - delay;
while ((TIFR0 & (1<<TOV0)) == 0) {
/* do nothing */
}
}
#endif
/* General short delays */
void
delay_ms(uint16_t x)
{
while (x-- > 0) {
delay_us(1000);
}
}
/* Light the given set of LEDs */
void
set_leds(uint8_t leds)
{
if ((leds & LED_RED) != 0) {
sbi(LED_RED_PORT, LED_RED_PIN);
}
else {
cbi(LED_RED_PORT, LED_RED_PIN);
}
if ((leds & LED_GREEN) != 0) {
sbi(LED_GREEN_PORT, LED_GREEN_PIN);
}
else {
cbi(LED_GREEN_PORT, LED_GREEN_PIN);
}
if ((leds & LED_BLUE) != 0) {
sbi(LED_BLUE_PORT, LED_BLUE_PIN);
}
else {
cbi(LED_BLUE_PORT, LED_BLUE_PIN);
}
if ((leds & LED_YELLOW) != 0) {
sbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
}
else {
cbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
}
}
#ifdef BOARD_REV_6_25_08
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111111;
DDRC = 0b00001001; /* LEDs and Buttons */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTC = 0b00100110; /* Enable pull-ups on buttons 0,2,3 */
PORTD = 0b01000000; /* Enable pull-up on button 1 */
}
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111100; /* button 2,3 on PB0,1 */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTB = 0b00000011; /* Enable pull-ups on buttons 2,3 */
PORTD = 0b11000000; /* Enable pull-up on button 0,1 */
}
#endif /* BOARD_REV_4_9_2009 */
#ifdef BOARD_REV_PTH
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11101101; /* LEDs and Buttons */
DDRC = 0b11111111; /* LEDs and Buttons */
DDRD = 0b10111011; /* LEDs, buttons, buzzer, TX/RX */
PORTB = 0b00010010; /* Enable pull-ups on buttons 1,4 */
//PORTC = 0b00100110; /* Enable pull-ups on buttons 0,2,3 */
PORTD = 0b01000100; /* Enable pull-up on button 1 */
}
#endif
void
ioinit(void)
{
init_gpio();
//Set Timer 0 Registers to Default Setting to over-ride the timer initialization made in the init() function of the Arduino Wiring libary (Wiring.c in the hardware/core/arduino folder)
TCCR0A = 0;
TIMSK0 = 0;
/* Init timer 0 for delay_us timing (1,000,000 / 1 = 1,000,000) */
//TCCR0B = (1<<CS00); /* Set Prescaler to 1. CS00=1 */
TCCR0B = (1<<CS01); /* Set Prescaler to 1. CS00=1 */
/* Init timer 2 */
ASSR = 0;
/* Set Prescaler to 1024. CS22=1, CS21=1,CS20=1 */
TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20);
TIMSK2 = (1<<TOIE2); /* Enable Timer 2 Interrupt */
cli(); //We don't use any interrupt functionality. Let's turn it off so Arduino doesn't screw around with it!
}
/* Returns a '1' bit in the position corresponding to LED_RED, etc. */
uint8_t
check_button(void)
{
uint8_t button_pressed = 0;
if ((BUTTON_RED_PORT & (1 << BUTTON_RED_PIN)) == 0)
button_pressed |= LED_RED;
if ((BUTTON_GREEN_PORT & (1 << BUTTON_GREEN_PIN)) == 0)
button_pressed |= LED_GREEN;
if ((BUTTON_BLUE_PORT & (1 << BUTTON_BLUE_PIN)) == 0)
button_pressed |= LED_BLUE;
if ((BUTTON_YELLOW_PORT & (1 << BUTTON_YELLOW_PIN)) == 0)
button_pressed |= LED_YELLOW;
return button_pressed;
}
/* Play the loser sound/lights */
void
play_loser(void)
{
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
}
/* Play the winner sound */
void
winner_sound(void)
{
uint8_t x, y;
/* Toggle the buzzer at various speeds */
for (x = 250; x > 70; x--) {
for (y = 0; y < 3; y++) {
sbi(BUZZER2_PORT, BUZZER2);
cbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
cbi(BUZZER2_PORT, BUZZER2);
sbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
}
}
}
/* Play the winner sound and lights */
void
play_winner(void)
{
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
}
/* Plays the current contents of the game moves */
void
play_moves(void)
{
uint8_t move;
for (move = 0; move < nmoves; move++) {
toner(moves[move], 150);
delay_ms(150);
}
}
/* Adds a new random button to the game sequence, by sampling the timer */
void
add_to_moves(void)
{
uint8_t new_button;
/* Use the lower 2 bits of the timer for the random value */
new_button = 1 << (TCNT2 & 0x3);
moves[nmoves++] = new_button;
}
/* Toggle buzzer every buzz_delay_us, for a duration of buzz_length_ms. */
void
buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay_us)
{
uint32_t buzz_length_us;
buzz_length_us = buzz_length_ms * (uint32_t)1000;
while (buzz_length_us > buzz_delay_us*2) {
buzz_length_us -= buzz_delay_us*2;
/* toggle the buzzer at various speeds */
cbi(BUZZER1_PORT, BUZZER1);
sbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
sbi(BUZZER1_PORT, BUZZER1);
cbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
}
}
/*
* Light an LED and play tone
*
* red, upper left: 440Hz - 2.272ms - 1.136ms pulse
* green, upper right: 880Hz - 1.136ms - 0.568ms pulse
* blue, lower left: 587.33Hz - 1.702ms - 0.851ms pulse
* yellow, lower right: 784Hz - 1.276ms - 0.638ms pulse
*/
void
toner(uint8_t which, uint16_t buzz_length_ms)
{
set_leds(which);
switch (which) {
case LED_RED:
buzz_sound(buzz_length_ms, 1136);
break;
case LED_GREEN:
buzz_sound(buzz_length_ms, 568);
break;
case LED_BLUE:
buzz_sound(buzz_length_ms, 851);
break;
case LED_YELLOW:
buzz_sound(buzz_length_ms, 638);
break;
}
/* Turn off all LEDs */
set_leds(0);
}
/* Show an "attract mode" display while waiting for user to press button. */
void
attract_mode(void)
{
while (1) {
set_leds(LED_RED);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_BLUE);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_GREEN);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_YELLOW);
delay_ms(100);
if (check_button() != 0x00)
return;
}
}
/* Wait for a button to be pressed. Returns one of led colors (LED_RED, etc.)
* if successful, 0 if timed out */
uint8_t
wait_for_button(void)
{
uint16_t time_limit = TIME_LIMIT;
uint8_t released = 0;
uint8_t old_button;
while (time_limit > 0) {
uint8_t button;
/* Implement a small bit of debouncing */
old_button = button;
button = check_button();
/*
* Make sure we've seen the previous button
* released before accepting new buttons
*/
if (button == 0)
released = 1;
if (button == old_button && released == 1) {
/* Make sure just one button is pressed */
if (button == LED_RED ||
button == LED_BLUE ||
button == LED_GREEN ||
button == LED_YELLOW) {
return button;
}
}
delay_ms(1);
time_limit--;
}
return 0; /* Timed out */
}
/* Play the game. Returns 0 if player loses, or 1 if player wins. */
int
game_mode(void)
{
nmoves = 0;
while (nmoves < MOVES_TO_WIN) {
uint8_t move;
/* Add a button to the current moves, then play them back */
add_to_moves();
play_moves();
/* Then require the player to repeat the sequence. */
for (move = 0; move < nmoves; move++) {
uint8_t choice = wait_for_button();
/* If wait timed out, player loses. */
if (choice == 0)
return 0;
toner(choice, 150);
/* If the choice is incorect, player loses. */
if (choice != moves[move]) {
return 0;
}
}
/* Player was correct, delay before playing moves */
delay_ms(1000);
}
/* player wins */
return 1;
}
void setup()
{
}
void loop()
{
/* Setup IO pins and defaults */
ioinit();
play_winner();
/* Main loop */
while (1) {
/* Wait for user to start game */
attract_mode();
/* Indicate the start of game play */
set_leds(LED_RED|LED_GREEN|LED_BLUE|LED_YELLOW);
delay_ms(1000);
set_leds(0);
delay_ms(250);
/* Play game and handle result */
if (game_mode() != 0) {
/* Player won, play winner tones */
play_winner();
}
else {
/* Player lost, play loser tones */
play_loser();
}
}
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,666 @@
/**
* 6-19-2007
* Copyright 2009, Spark Fun Electronics
* Nathan Seidle
* nathan at sparkfun.com
*
* Released under the Creative Commons Attribution Share-Alike 3.0 License
* http://creativecommons.org/licenses/by-sa/3.0
*
* Simon Game ported for the ATmega168
*
* Fixes and cleanup by Joshua Neal <joshua[at]trochotron.com>
*
* Generates random sequence, plays music, and displays button lights.
*
* Simon tones from Wikipedia
* - A (red, upper left) - 440Hz - 2.272ms - 1.136ms pulse
* - a (green, upper right, an octave higher than A) - 880Hz - 1.136ms,
* 0.568ms pulse
* - D (blue, lower left, a perfect fourth higher than the upper left)
* 587.33Hz - 1.702ms - 0.851ms pulse
* G (yellow, lower right, a perfect fourth higher than the lower left) -
* 784Hz - 1.276ms - 0.638ms pulse
*
* The tones are close, but probably off a bit, but they sound all right.
*
* The old version of SparkFun simon used an ATmega8. An ATmega8 ships
* with a default internal 1MHz oscillator. You will need to set the
* internal fuses to operate at the correct external 16MHz oscillator.
*
* Original Fuses:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xE1:m -U hfuse:w:0xD9:m
*
* Command to set to fuses to use external 16MHz:
* avrdude -p atmega8 -P lpt1 -c stk200 -U lfuse:w:0xEE:m -U hfuse:w:0xC9:m
*
* The current version of Simon uses the ATmega168. The external osciallator
* was removed to reduce component count. This version of simon relies on the
* internal default 1MHz osciallator. Do not set the external fuses.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
/* Uncomment one of the following, corresponding to the board you have. */
//#define BOARD_REV_6_25_08
// #define BOARD_REV_4_9_2009
#define BOARD_REV_PTH
#ifdef BOARD_REV_PTH
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 3
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 1
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 2
#define BUTTON_GREEN_PORT PIND
#define BUTTON_BLUE_PIN 4
#define BUTTON_BLUE_PORT PINB
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 4
#define BUZZER1_PORT PORTD
#define BUZZER2 7
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_PTH */
#ifdef BOARD_REV_6_25_08
#define CHIP_ATMEGA168
#define LED_RED (1 << 0)
#define LED_GREEN (1 << 1)
#define LED_BLUE (1 << 2)
#define LED_YELLOW (1 << 3)
/* LED pin definitions */
#define LED_RED_PIN 3
#define LED_RED_PORT PORTC
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
#define LED_BLUE_PIN 0
#define LED_BLUE_PORT PORTC
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 2
#define BUTTON_RED_PORT PINC
#define BUTTON_GREEN_PIN 5
#define BUTTON_GREEN_PORT PINC
#define BUTTON_BLUE_PIN 1
#define BUTTON_BLUE_PORT PINC
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
#define CHIP_ATMEGA168
/* LED pin definitions */
#define LED_BLUE_PIN 5
#define LED_BLUE_PORT PORTB
#define LED_YELLOW_PIN 5
#define LED_YELLOW_PORT PORTD
#define LED_RED_PIN 2
#define LED_RED_PORT PORTB
#define LED_GREEN_PIN 2
#define LED_GREEN_PORT PORTD
/* Button pin definitions */
#define BUTTON_RED_PIN 0
#define BUTTON_RED_PORT PINB
#define BUTTON_GREEN_PIN 1
#define BUTTON_GREEN_PORT PINB
#define BUTTON_BLUE_PIN 7
#define BUTTON_BLUE_PORT PIND
#define BUTTON_YELLOW_PIN 6
#define BUTTON_YELLOW_PORT PIND
/* Buzzer pin definitions */
#define BUZZER1 3
#define BUZZER1_PORT PORTD
#define BUZZER2 4
#define BUZZER2_PORT PORTD
#endif /* BOARD_REV_4_9_2009 */
/* Define game parameters */
#define MOVES_TO_WIN 13
#define TIME_LIMIT 3000 /* 3000ms = 3 sec */
#define sbi(port_name, pin_number) (port_name |= 1<<pin_number)
#define cbi(port_name, pin_number) \
((port_name) &= (uint8_t)~(1 << pin_number))
/* Declarations for static functions */
#include "WProgram.h"
void
delay_us(uint16_t delay);
void
delay_ms(uint16_t x);
void
set_leds(uint8_t leds);
void
init_gpio(void);
void
init_gpio(void);
void
init_gpio(void);
void
ioinit(void);
uint8_t
check_button(void);
void
play_loser(void);
void
winner_sound(void);
void
play_winner(void);
void
play_moves(void);
void
add_to_moves(void);
void
buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay_us);
void
toner(uint8_t which, uint16_t buzz_length_ms);
void
attract_mode(void);
uint8_t
wait_for_button(void);
int
game_mode(void);
void setup();
void loop();
void delay_us(uint16_t delay);
void delay_ms(uint16_t delay);
uint8_t check_button(void);
void set_leds(uint8_t leds);
void buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay);
void toner(uint8_t tone, uint16_t buzz_length_ms);
void add_to_moves(void);
void play_moves(void);
void play_loser(void);
void play_winner(void);
void ioinit(void);
/* Game state */
uint8_t moves[32];
uint8_t nmoves = 0;
ISR (SIG_OVERFLOW2)
{
/*
* Prescalar of 1024
* Clock = 16MHz
* 15,625 clicks per second
* 64us per click
*/
/* Preload timer 2 for 125 clicks. Should be 8ms per ISR call */
TCNT2 = 131; /* 256 - 125 = 131 */
}
/* General short delays, using internal timer do a fairly accurate 1us */
#ifdef CHIP_ATMEGA168
void
delay_us(uint16_t delay)
{
while (delay > 256)
{
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
TCNT0 = 0;
while ( (TIFR0 & (1<<TOV0)) == 0);
delay -= 256;
}
TIFR0 = (1<<TOV0); /* Clear any interrupt flags on Timer0 */
/*
* 256 - 125 = 131 : Preload timer 0 for x clicks.
* Should be 1us per click
*/
TCNT0 = 256 - delay;
while ((TIFR0 & (1<<TOV0)) == 0) {
/* do nothing */
}
}
#endif
/* General short delays */
void
delay_ms(uint16_t x)
{
while (x-- > 0) {
delay_us(1000);
}
}
/* Light the given set of LEDs */
void
set_leds(uint8_t leds)
{
if ((leds & LED_RED) != 0) {
sbi(LED_RED_PORT, LED_RED_PIN);
}
else {
cbi(LED_RED_PORT, LED_RED_PIN);
}
if ((leds & LED_GREEN) != 0) {
sbi(LED_GREEN_PORT, LED_GREEN_PIN);
}
else {
cbi(LED_GREEN_PORT, LED_GREEN_PIN);
}
if ((leds & LED_BLUE) != 0) {
sbi(LED_BLUE_PORT, LED_BLUE_PIN);
}
else {
cbi(LED_BLUE_PORT, LED_BLUE_PIN);
}
if ((leds & LED_YELLOW) != 0) {
sbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
}
else {
cbi(LED_YELLOW_PORT, LED_YELLOW_PIN);
}
}
#ifdef BOARD_REV_6_25_08
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111111;
DDRC = 0b00001001; /* LEDs and Buttons */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTC = 0b00100110; /* Enable pull-ups on buttons 0,2,3 */
PORTD = 0b01000000; /* Enable pull-up on button 1 */
}
#endif /* BOARD_REV_6_25_08 */
#ifdef BOARD_REV_4_9_2009
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11111100; /* button 2,3 on PB0,1 */
DDRD = 0b00111110; /* LEDs, buttons, buzzer, TX/RX */
PORTB = 0b00000011; /* Enable pull-ups on buttons 2,3 */
PORTD = 0b11000000; /* Enable pull-up on button 0,1 */
}
#endif /* BOARD_REV_4_9_2009 */
#ifdef BOARD_REV_PTH
void
init_gpio(void)
{
/* 1 = output, 0 = input */
DDRB = 0b11101101; /* LEDs and Buttons */
DDRC = 0b11111111; /* LEDs and Buttons */
DDRD = 0b10111011; /* LEDs, buttons, buzzer, TX/RX */
PORTB = 0b00010010; /* Enable pull-ups on buttons 1,4 */
//PORTC = 0b00100110; /* Enable pull-ups on buttons 0,2,3 */
PORTD = 0b01000100; /* Enable pull-up on button 1 */
}
#endif
void
ioinit(void)
{
init_gpio();
//Set Timer 0 Registers to Default Setting to over-ride the timer initialization made in the init() function of the Arduino Wiring libary (Wiring.c in the hardware/core/arduino folder)
TCCR0A = 0;
TIMSK0 = 0;
/* Init timer 0 for delay_us timing (1,000,000 / 1 = 1,000,000) */
//TCCR0B = (1<<CS00); /* Set Prescaler to 1. CS00=1 */
TCCR0B = (1<<CS01); /* Set Prescaler to 1. CS00=1 */
/* Init timer 2 */
ASSR = 0;
/* Set Prescaler to 1024. CS22=1, CS21=1,CS20=1 */
TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20);
TIMSK2 = (1<<TOIE2); /* Enable Timer 2 Interrupt */
cli(); //We don't use any interrupt functionality. Let's turn it off so Arduino doesn't screw around with it!
}
/* Returns a '1' bit in the position corresponding to LED_RED, etc. */
uint8_t
check_button(void)
{
uint8_t button_pressed = 0;
if ((BUTTON_RED_PORT & (1 << BUTTON_RED_PIN)) == 0)
button_pressed |= LED_RED;
if ((BUTTON_GREEN_PORT & (1 << BUTTON_GREEN_PIN)) == 0)
button_pressed |= LED_GREEN;
if ((BUTTON_BLUE_PORT & (1 << BUTTON_BLUE_PIN)) == 0)
button_pressed |= LED_BLUE;
if ((BUTTON_YELLOW_PORT & (1 << BUTTON_YELLOW_PIN)) == 0)
button_pressed |= LED_YELLOW;
return button_pressed;
}
/* Play the loser sound/lights */
void
play_loser(void)
{
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
set_leds(LED_RED|LED_GREEN);
buzz_sound(255, 1500);
set_leds(LED_BLUE|LED_YELLOW);
buzz_sound(255, 1500);
}
/* Play the winner sound */
void
winner_sound(void)
{
uint8_t x, y;
/* Toggle the buzzer at various speeds */
for (x = 250; x > 70; x--) {
for (y = 0; y < 3; y++) {
sbi(BUZZER2_PORT, BUZZER2);
cbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
cbi(BUZZER2_PORT, BUZZER2);
sbi(BUZZER1_PORT, BUZZER1);
delay_us(x);
}
}
}
/* Play the winner sound and lights */
void
play_winner(void)
{
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
set_leds(LED_GREEN|LED_BLUE);
winner_sound();
set_leds(LED_RED|LED_YELLOW);
winner_sound();
}
/* Plays the current contents of the game moves */
void
play_moves(void)
{
uint8_t move;
for (move = 0; move < nmoves; move++) {
toner(moves[move], 150);
delay_ms(150);
}
}
/* Adds a new random button to the game sequence, by sampling the timer */
void
add_to_moves(void)
{
uint8_t new_button;
/* Use the lower 2 bits of the timer for the random value */
new_button = 1 << (TCNT2 & 0x3);
moves[nmoves++] = new_button;
}
/* Toggle buzzer every buzz_delay_us, for a duration of buzz_length_ms. */
void
buzz_sound(uint16_t buzz_length_ms, uint16_t buzz_delay_us)
{
uint32_t buzz_length_us;
buzz_length_us = buzz_length_ms * (uint32_t)1000;
while (buzz_length_us > buzz_delay_us*2) {
buzz_length_us -= buzz_delay_us*2;
/* toggle the buzzer at various speeds */
cbi(BUZZER1_PORT, BUZZER1);
sbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
sbi(BUZZER1_PORT, BUZZER1);
cbi(BUZZER2_PORT, BUZZER2);
delay_us(buzz_delay_us);
}
}
/*
* Light an LED and play tone
*
* red, upper left: 440Hz - 2.272ms - 1.136ms pulse
* green, upper right: 880Hz - 1.136ms - 0.568ms pulse
* blue, lower left: 587.33Hz - 1.702ms - 0.851ms pulse
* yellow, lower right: 784Hz - 1.276ms - 0.638ms pulse
*/
void
toner(uint8_t which, uint16_t buzz_length_ms)
{
set_leds(which);
switch (which) {
case LED_RED:
buzz_sound(buzz_length_ms, 1136);
break;
case LED_GREEN:
buzz_sound(buzz_length_ms, 568);
break;
case LED_BLUE:
buzz_sound(buzz_length_ms, 851);
break;
case LED_YELLOW:
buzz_sound(buzz_length_ms, 638);
break;
}
/* Turn off all LEDs */
set_leds(0);
}
/* Show an "attract mode" display while waiting for user to press button. */
void
attract_mode(void)
{
while (1) {
set_leds(LED_RED);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_BLUE);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_GREEN);
delay_ms(100);
if (check_button() != 0x00)
return;
set_leds(LED_YELLOW);
delay_ms(100);
if (check_button() != 0x00)
return;
}
}
/* Wait for a button to be pressed. Returns one of led colors (LED_RED, etc.)
* if successful, 0 if timed out */
uint8_t
wait_for_button(void)
{
uint16_t time_limit = TIME_LIMIT;
uint8_t released = 0;
uint8_t old_button;
while (time_limit > 0) {
uint8_t button;
/* Implement a small bit of debouncing */
old_button = button;
button = check_button();
/*
* Make sure we've seen the previous button
* released before accepting new buttons
*/
if (button == 0)
released = 1;
if (button == old_button && released == 1) {
/* Make sure just one button is pressed */
if (button == LED_RED ||
button == LED_BLUE ||
button == LED_GREEN ||
button == LED_YELLOW) {
return button;
}
}
delay_ms(1);
time_limit--;
}
return 0; /* Timed out */
}
/* Play the game. Returns 0 if player loses, or 1 if player wins. */
int
game_mode(void)
{
nmoves = 0;
while (nmoves < MOVES_TO_WIN) {
uint8_t move;
/* Add a button to the current moves, then play them back */
add_to_moves();
play_moves();
/* Then require the player to repeat the sequence. */
for (move = 0; move < nmoves; move++) {
uint8_t choice = wait_for_button();
/* If wait timed out, player loses. */
if (choice == 0)
return 0;
toner(choice, 150);
/* If the choice is incorect, player loses. */
if (choice != moves[move]) {
return 0;
}
}
/* Player was correct, delay before playing moves */
delay_ms(1000);
}
/* player wins */
return 1;
}
void setup()
{
}
void loop()
{
/* Setup IO pins and defaults */
ioinit();
play_winner();
/* Main loop */
while (1) {
/* Wait for user to start game */
attract_mode();
/* Indicate the start of game play */
set_leds(LED_RED|LED_GREEN|LED_BLUE|LED_YELLOW);
delay_ms(1000);
set_leds(0);
delay_ms(250);
/* Play game and handle result */
if (game_mode() != 0) {
/* Player won, play winner tones */
play_winner();
}
else {
/* Player lost, play loser tones */
play_loser();
}
}
}
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}

View File

@ -0,0 +1 @@
:00000001FF

Binary file not shown.

View File

@ -0,0 +1,101 @@
:100000000C9434000C9451000C9451000C94510049
:100010000C9451000C9451000C9451000C9451001C
:100020000C9451000C9453000C9451000C9451000A
:100030000C9451000C9451000C9451000C945100FC
:100040000C946A020C9451000C9451000C945100D1
:100050000C9451000C9451000C9451000C945100DC
:100060000C9451000C94510011241FBECFEFD4E02A
:10007000DEBFCDBF11E0A0E0B1E0E2E3F6E002C0F8
:1000800005900D92A030B107D9F711E0A0E0B1E0E2
:1000900001C01D92AA32B107E1F70E9465020C94DB
:1000A00017030C9400001F920F920FB60F921124A9
:1000B0008F9383E88093B2008F910F900FBE0F90C3
:1000C0001F9018959C0181E006C085BB16BCA89BBB
:1000D000FECF2050314091E021303907B0F781E068
:1000E00085BB822F819586BDA89BFECF0895CF93B7
:1000F000DF93EC0105C088EE93E00E946200219737
:100100002097C9F7DF91CF91089580FF02C02A9A06
:1001100001C02A9881FF02C05B9A01C05B9882FFF0
:1001200002C02D9A01C02D9883FF02C05D9A0895E8
:100130005D98089583B18695809581704A9B826011
:100140001C9B84604E9B886008951F93CF93DF9320
:10015000CAEFD0E011C05F9A5C98CE010E946200A5
:100160005F985C9ACE010E9462001F5F133099F77E
:100170002197C634D10511F010E0EDCFDF91CF917A
:100180001F91089586E00E9485000E94A50089E0E5
:100190000E9485000E94A50086E00E9485000E94C2
:1001A000A50089E00E9485000E94A50008956F9235
:1001B0007F928F929F92AF92BF92CF92DF92EF92F7
:1001C000FF920F931F93CF93DF93EB01A0E0B0E07A
:1001D000BC01CD0128EE33E040E050E00E94F8027F
:1001E0007B018C01CE01880F991F5C01CC24DD249A
:1001F0006624772443016A187B088C089D080EC08A
:10020000E60CF71C081D191D5C985F9ACE010E9430
:1002100062005C9A5F98CE010E946200AE14BF0437
:10022000C006D10668F3DF91CF911F910F91FF9027
:10023000EF90DF90CF90BF90AF909F908F907F9086
:100240006F90089583E00E9485008FEF90E06CED41
:1002500075E00E94D7008CE00E9485008FEF90E04F
:100260006CED75E00E94D70083E00E9485008FEF5F
:1002700090E06CED75E00E94D7008CE00E94850054
:100280008FEF90E06CED75E00E94D70008951F930A
:10029000CF93DF93182FEB010E948500123071F08D
:1002A000133018F41130B9F405C0143059F0183077
:1002B00091F40CC0CE0160E774E00BC0CE0168E39E
:1002C00072E007C0CE0163E573E003C0CE016EE7C4
:1002D00072E00E94D70080E00E948500DF91CF91FC
:1002E0001F9108951F9310E00EC0E12FF0E0E05041
:1002F000FF4F808166E970E00E94470186E990E047
:100300000E9477001F5F80912001181770F31F91E2
:10031000089581E00E94850084E690E00E947700C5
:100320000E949A00882309F584E00E94850084E6F3
:1003300090E00E9477000E949A008823B1F482E046
:100340000E94850084E690E00E9477000E949A0057
:10035000882359F488E00E94850084E690E00E949A
:1003600077000E949A008823A1F20895EF92FF92ED
:100370000F931F93DF93CF930F92CDB7DEB7198200
:1003800038EBE32E3BE0F32E0E949A00182F8823CF
:1003900011F481E08983101759F4E981E13041F4C7
:1003A000113099F0143089F0123079F0183069F07A
:1003B00081E090E00E9477000894E108F108E114E0
:1003C000F10411F0012FE0CF10E0812F0F90CF91B9
:1003D000DF911F910F91FF90EF9008950F931F935E
:1003E000CF93DF9310922001C1E0D0E02EC0809126
:1003F000B200E22FF0E0E050FF4F8370AE0102C088
:10040000440F551F8A95E2F740832F5F2093200108
:100410000E94720100E011C00E94B601182F8823CB
:10042000D9F066E970E00E944701E02FF0E0E0506B
:10043000FF4F8081181781F40F5F8091200108170A
:1004400058F388EE93E00E947700209120012D3030
:1004500070F221E030E002C020E030E0C901DF911D
:10046000CF911F910F9108958DEE84B98FEF87B9C9
:100470008BEB8AB982E185B984E48BB914BC109204
:100480006E0082E085BD1092B60087E08093B100D7
:1004900081E080937000F8940E94C2000E9489015C
:1004A0008FE00E94850088EE93E00E94770080E054
:1004B0000E9485008AEF90E00E9477000E94EE0182
:1004C000892B51F70E942201E9CF0E94BE020E94AF
:1004D0003402FDCF1F920F920FB60F9211242F936B
:1004E0003F934F935F936F937F938F939F93AF93BC
:1004F000BF93209125013091260140912701509111
:10050000280170912901DA01C9010296A11DB11DCE
:10051000672F6A5F6D3730F06D57DA01C9010396B6
:10052000A11DB11D6093290180932501909326019F
:10053000A0932701B093280180912101909122017D
:10054000A0912301B09124010196A11DB11D8093BA
:10055000210190932201A0932301B0932401BF9124
:10056000AF919F918F917F916F915F914F913F914B
:100570002F910F900FBE0F901F901895789484B50F
:10058000826084BD84B5816084BD85B5826085BD8F
:1005900085B5816085BDEEE6F0E080818160808375
:1005A000E1E8F0E0808182608083808181608083E7
:1005B000E0E8F0E0808181608083E1EBF0E0808121
:1005C00084608083E0EBF0E0808181608083EAE7F3
:1005D000F0E080818460808380818260808380817C
:1005E000816080838081806880831092C10008953B
:1005F000629FD001739FF001829FE00DF11D649F07
:10060000E00DF11D929FF00D839FF00D749FF00D92
:10061000659FF00D9927729FB00DE11DF91F639F33
:10062000B00DE11DF91FBD01CF0111240895F8940B
:02063000FFCFFA
:00000001FF

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Simon_Sketch/applet/core.a Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.