mirror of https://github.com/nealey/Simon-Says
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:
commit
3475e99530
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
:00000001FF
|
Binary file not shown.
|
@ -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.
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.
Loading…
Reference in New Issue