From 1bbcd81870c662f76b2a885064e5c1afae32e98e Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 15 Sep 2015 21:56:42 -0600 Subject: [PATCH] Add more music, better sound --- Firmware/Old-Simon_C/Makefile | 1112 ++++++++++++------------ Firmware/Old-Simon_C/Simon.c | 1282 ++++++++++++++-------------- Firmware/Simon_Says/Simon_Says.ino | 373 +++++--- 3 files changed, 1444 insertions(+), 1323 deletions(-) diff --git a/Firmware/Old-Simon_C/Makefile b/Firmware/Old-Simon_C/Makefile index f949a91..29ea664 100644 --- a/Firmware/Old-Simon_C/Makefile +++ b/Firmware/Old-Simon_C/Makefile @@ -1,556 +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 -# 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 - - - +# 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 +# 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 + + + diff --git a/Firmware/Old-Simon_C/Simon.c b/Firmware/Old-Simon_C/Simon.c index 110bbf8..2c14726 100644 --- a/Firmware/Old-Simon_C/Simon.c +++ b/Firmware/Old-Simon_C/Simon.c @@ -1,641 +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 - * - * 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 -#include - -/* 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< 256) - { - TIFR0 = (1< 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< 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); -} - +/** + * 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 + * + * 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 +#include + +/* 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< 256) + { + TIFR0 = (1< 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< 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); +} + diff --git a/Firmware/Simon_Says/Simon_Says.ino b/Firmware/Simon_Says/Simon_Says.ino index b23a0c7..60982db 100644 --- a/Firmware/Simon_Says/Simon_Says.ino +++ b/Firmware/Simon_Says/Simon_Says.ino @@ -75,34 +75,12 @@ void setup() pinMode(BUZZER1, OUTPUT); pinMode(BUZZER2, OUTPUT); - //Mode checking - gameMode = MODE_MEMORY; // By default, we're going to play the memory game - - // Check to see if the lower right button is pressed - if (checkButton() == CHOICE_YELLOW) play_beegees(); - - // Check to see if upper right button is pressed - if (checkButton() == CHOICE_GREEN) - { - gameMode = MODE_BATTLE; //Put game into battle mode - - //Turn on the upper right (green) LED - setLEDs(CHOICE_GREEN); - toner(CHOICE_GREEN, 150); - - setLEDs(CHOICE_RED | CHOICE_BLUE | CHOICE_YELLOW); // Turn on the other LEDs until you release button - - while(checkButton() != CHOICE_NONE) ; // Wait for user to stop pressing button - - //Now do nothing. Battle mode will be serviced in the main routine - } - - play_winner(); // After setup is complete, say hello to the world + play_greeting(); // After setup is complete, say hello to the world } void loop() { - attractMode(); // Blink lights while waiting for user to press a button + byte button = attractMode(); // Blink lights while waiting for user to press a button // Indicate the start of game play setLEDs(CHOICE_RED | CHOICE_GREEN | CHOICE_BLUE | CHOICE_YELLOW); // Turn all LEDs on @@ -110,20 +88,28 @@ void loop() setLEDs(CHOICE_OFF); // Turn off LEDs delay(250); - if (gameMode == MODE_MEMORY) - { + switch (button) { + case CHOICE_RED: // Play memory game and handle result if (play_memory() == true) - play_winner(); // Player won, play winner tones + play_march(); // Player won, play winner tones else play_loser(); // Player lost, play loser tones - } + break; - if (gameMode == MODE_BATTLE) - { + case CHOICE_GREEN: play_battle(); // Play game until someone loses play_loser(); // Player lost, play loser tones + break; + + case CHOICE_BLUE: + play_getlucky(); + break; + + case CHOICE_YELLOW: + play_beegees(); + break; } } @@ -273,12 +259,14 @@ byte wait_for_button(void) // Returns a '1' bit in the position corresponding to CHOICE_RED, CHOICE_GREEN, etc. byte checkButton(void) { - if (digitalRead(BUTTON_RED) == 0) return(CHOICE_RED); - else if (digitalRead(BUTTON_GREEN) == 0) return(CHOICE_GREEN); - else if (digitalRead(BUTTON_BLUE) == 0) return(CHOICE_BLUE); - else if (digitalRead(BUTTON_YELLOW) == 0) return(CHOICE_YELLOW); + byte choice = 0; + + if (digitalRead(BUTTON_RED) == 0) choice |= CHOICE_RED; + else if (digitalRead(BUTTON_GREEN) == 0) choice |= CHOICE_GREEN; + else if (digitalRead(BUTTON_BLUE) == 0) choice |= CHOICE_BLUE; + else if (digitalRead(BUTTON_YELLOW) == 0) choice |= CHOICE_YELLOW; - return(CHOICE_NONE); // If no button is pressed, return none + return choice; } // Light an LED and play tone @@ -294,16 +282,16 @@ void toner(byte which, int buzz_length_ms) switch(which) { case CHOICE_RED: - buzz_sound(buzz_length_ms, 1136); + playNote(4, 0, buzz_length_ms); break; case CHOICE_GREEN: - buzz_sound(buzz_length_ms, 568); + playNote(4, 1, buzz_length_ms); break; case CHOICE_BLUE: - buzz_sound(buzz_length_ms, 851); + playNote(4, 3, buzz_length_ms); break; case CHOICE_YELLOW: - buzz_sound(buzz_length_ms, 638); + playNote(4, 7, buzz_length_ms); break; } @@ -311,43 +299,28 @@ void toner(byte which, int buzz_length_ms) } // Toggle buzzer every buzz_delay_us, for a duration of buzz_length_ms. -void buzz_sound(int buzz_length_ms, int buzz_delay_us) +void buzz_sound(int buzz_length_ms, unsigned int freq) { - // Convert total play time from milliseconds to microseconds - long buzz_length_us = buzz_length_ms * (long)1000; - - // Loop until the remaining play time is less than a single buzz_delay_us - while (buzz_length_us > (buzz_delay_us * 2)) - { - buzz_length_us -= buzz_delay_us * 2; //Decrease the remaining play time - - // Toggle the buzzer at various speeds - digitalWrite(BUZZER1, LOW); - digitalWrite(BUZZER2, HIGH); - delayMicroseconds(buzz_delay_us); - - digitalWrite(BUZZER1, HIGH); - digitalWrite(BUZZER2, LOW); - delayMicroseconds(buzz_delay_us); - } + tone(BUZZER2, freq, buzz_length_ms); + delay(buzz_length_ms); } // Play the winner sound and lights -void play_winner(void) +void play_greeting(void) { setLEDs(CHOICE_GREEN | CHOICE_BLUE); - winner_sound(); + greeting_sound(); setLEDs(CHOICE_RED | CHOICE_YELLOW); - winner_sound(); + greeting_sound(); setLEDs(CHOICE_GREEN | CHOICE_BLUE); - winner_sound(); + greeting_sound(); setLEDs(CHOICE_RED | CHOICE_YELLOW); - winner_sound(); + greeting_sound(); } // Play the winner sound // This is just a unique (annoying) sound we came up with, there is no magic to it -void winner_sound(void) +void greeting_sound(void) { // Toggle the buzzer at various speeds for (byte x = 250 ; x > 70 ; x--) @@ -355,11 +328,9 @@ void winner_sound(void) for (byte y = 0 ; y < 3 ; y++) { digitalWrite(BUZZER2, HIGH); - digitalWrite(BUZZER1, LOW); delayMicroseconds(x); digitalWrite(BUZZER2, LOW); - digitalWrite(BUZZER1, HIGH); delayMicroseconds(x); } } @@ -369,96 +340,246 @@ void winner_sound(void) void play_loser(void) { setLEDs(CHOICE_RED | CHOICE_GREEN); - buzz_sound(255, 1500); + buzz_sound(255, 220); setLEDs(CHOICE_BLUE | CHOICE_YELLOW); - buzz_sound(255, 1500); + buzz_sound(255, 220); setLEDs(CHOICE_RED | CHOICE_GREEN); - buzz_sound(255, 1500); + buzz_sound(255, 220); setLEDs(CHOICE_BLUE | CHOICE_YELLOW); - buzz_sound(255, 1500); + buzz_sound(255, 220); } // Show an "attract mode" display while waiting for user to press button. -void attractMode(void) +byte attractMode(void) { - while(1) - { - setLEDs(CHOICE_RED); - delay(100); - if (checkButton() != CHOICE_NONE) return; + byte led = 0; + byte button = 0; - setLEDs(CHOICE_BLUE); + for (; button == 0;) { + setLEDs(1 << led); delay(100); - if (checkButton() != CHOICE_NONE) return; - - setLEDs(CHOICE_GREEN); - delay(100); - if (checkButton() != CHOICE_NONE) return; - - setLEDs(CHOICE_YELLOW); - delay(100); - if (checkButton() != CHOICE_NONE) return; + button = checkButton(); + led = (led + 1) % 4; } + + return button; } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // The following functions are related to Beegees Easter Egg only -// Notes in the melody. Each note is about an 1/8th note, "0"s are rests. -int melody[] = { - NOTE_G4, NOTE_A4, 0, NOTE_C5, 0, 0, NOTE_G4, 0, 0, 0, - NOTE_E4, 0, NOTE_D4, NOTE_E4, NOTE_G4, 0, - NOTE_D4, NOTE_E4, 0, NOTE_G4, 0, 0, - NOTE_D4, 0, NOTE_E4, 0, NOTE_G4, 0, NOTE_A4, 0, NOTE_C5, 0}; +const unsigned int freqs[] = { + 3520, // A + 3729, // A# + 3951, // B + 2093, // C + 2217, // C# + 2349, // D + 2489, // D# + 2637, // E + 2794, // F + 2960, // F# + 3136, // G + 3322, // G# +}; -int noteDuration = 115; // This essentially sets the tempo, 115 is just about right for a disco groove :) -int LEDnumber = 0; // Keeps track of which LED we are on during the beegees loop +const int scale[] = { + 0, 2, 3, 5, 7, 8, 10 +}; + +void +playNote(int octave, int note, int duration) +{ + unsigned int freq; + int i; + + if (note >= 0) { + freq = freqs[note]; + for (i = octave; i < 7; i += 1) { + freq /= 2; + } + + tone(BUZZER2, freq, duration); + setLEDs(note + 1); + } + delay(duration); + setLEDs(0); +} + +void +play(int bpm, char *tune) +{ + unsigned int baseDuration = 60000 / bpm; + int duration = baseDuration; + int baseOctave = 4; + int octave = baseOctave; + + int note = -2; + + char *p = tune; + + digitalWrite(BUZZER1, LOW); // setup the "BUZZER1" side of the buzzer to stay low, while we play the tone on the other pin. + for (; *p; p += 1) { + boolean playNow = false; + + switch (*p) { + case '>': + octave = baseOctave + 1; + break; + case '<': + octave = baseOctave - 1; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + playNow = true; + note = scale[*p - 'A']; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + playNow = true; + octave += 1; + note = scale[*p - 'a']; + break; + case '_': + playNow = true; + note = -1; + break; + } + + // Check for sharps or flats + switch (*(p+1)) { + case '#': + case '+': + note += 1; + if (note == 12) { + octave += 1; + note = 0; + } + p += 1; + break; + case '-': + note -= 1; + if (note == -1) { + octave -= 1; + note = 11; + } + p += 1; + break; + } + + // Check for octave + switch (*(p+1)) { + case ',': + octave -= 1; + p += 1; + break; + case '\'': + octave += 1; + p += 1; + break; + } + + // Check for duration + switch (*(p+1)) { + case '2': + duration *= 2; + p += 1; + break; + case '4': + duration *= 4; + p += 1; + break; + case '.': + duration += duration / 2; + p += 1; + break; + } + + if (playNow) { + playNote(octave, note, duration); + note = -1; + octave = baseOctave; + duration = baseDuration; + } + + if (checkButton()) { + noTone(BUZZER2); + return; + } + } + if (note >= 0) { + playNote(octave, note, duration); + } + noTone(BUZZER2); +} // Do nothing but play bad beegees music // This function is activated when user holds bottom right button during power up void play_beegees() { - //Turn on the bottom right (yellow) LED - setLEDs(CHOICE_YELLOW); - toner(CHOICE_YELLOW, 150); - - setLEDs(CHOICE_RED | CHOICE_GREEN | CHOICE_BLUE); // Turn on the other LEDs until you release button - - while(checkButton() != CHOICE_NONE) ; // Wait for user to stop pressing button - - setLEDs(CHOICE_NONE); // Turn off LEDs - - delay(1000); // Wait a second before playing song - - digitalWrite(BUZZER1, LOW); // setup the "BUZZER1" side of the buzzer to stay low, while we play the tone on the other pin. - - while(checkButton() == CHOICE_NONE) //Play song until you press a button - { - // iterate over the notes of the melody: - for (int thisNote = 0; thisNote < 32; thisNote++) { - changeLED(); - tone(BUZZER2, melody[thisNote],noteDuration); - // to distinguish the notes, set a minimum time between them. - // the note's duration + 30% seems to work well: - int pauseBetweenNotes = noteDuration * 1.30; - delay(pauseBetweenNotes); - // stop the tone playing: - noTone(BUZZER2); - } + while(checkButton() == CHOICE_NONE) { + play(104 * 4, "E-F_a-__E-2__C_B-,CE-_B-,C_E-__B-,_C_E-_F_a-_"); } } -// Each time this function is called the board moves to the next LED -void changeLED(void) +void lplay(unsigned int tempo, char *tune, int count) { - setLEDs(1 << LEDnumber); // Change the LED - - LEDnumber++; // Goto the next LED - if(LEDnumber > 3) LEDnumber = 0; // Wrap the counter if needed + int i; + + for (i = 0; i < count; i += 1) { + play(tempo * 3, tune); + } } +void play_march() +{ + const int tempo = 80; + + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "E-G-,B-,", 5); + play(tempo * 4, "B-"); + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "E-G-,B-,", 5); + play(tempo * 4, "B-"); + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "GB-,D", 6); + + lplay(tempo * 4, "dGB-", 6); + lplay(tempo * 4, "dGB-", 6); + lplay(tempo * 4, "dGB-", 6); + lplay(tempo * 4, "e-G-B-", 5); + play(tempo * 4, "B-"); + lplay(tempo * 4, "G-B-,F", 6); + lplay(tempo * 4, "E-G-,B-,", 5); + play(tempo * 4, "B-"); + lplay(tempo * 4, "GB-,D", 6); + lplay(tempo * 4, "GB-,D", 6); + + return; +} +void play_getlucky() +{ + while (checkButton() == CHOICE_NONE) { + play(116 * 4, ("_______B__B_A_F+_" + "_______d__d_c+_A_" + "_______f+__f+_e_c+_" + "_______e__e_d_B_")); + } +}