# 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 | |||||
# Carlos Lamas | |||||
# | |||||
#---------------------------------------------------------------------------- | |||||
# 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". | |||||
#---------------------------------------------------------------------------- | |||||
# Following variables need to be set in <target>/Makefile: | |||||
# TARGET | |||||
# COMMON_DIR | |||||
# TARGET_DIR | |||||
# TARGET_SRC | |||||
# MCU | |||||
# F_CPU | |||||
# List C source files here. (C dependencies are automatically generated.) | |||||
SRC = tmk.c \ | |||||
SRC += keyboard.c \ | |||||
layer.c \ | layer.c \ | ||||
key_process.c \ | |||||
usb_keyboard.c \ | |||||
usb_debug.c \ | |||||
usb.c \ | |||||
jump_bootloader.c \ | |||||
print.c \ | |||||
timer.c \ | timer.c \ | ||||
print.c \ | |||||
util.c | util.c | ||||
SRC += $(TARGET_SRC) | |||||
# Option modules | # Option modules | ||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
SRC += usb_mouse.c | |||||
endif | |||||
ifdef MOUSEKEY_ENABLE | ifdef MOUSEKEY_ENABLE | ||||
SRC += mousekey.c | SRC += mousekey.c | ||||
endif | endif | ||||
ifdef PS2_MOUSE_ENABLE | ifdef PS2_MOUSE_ENABLE | ||||
SRC += ps2.c \ | SRC += ps2.c \ | ||||
ps2_mouse.c | ps2_mouse.c | ||||
endif | endif | ||||
ifdef USB_EXTRA_ENABLE | |||||
SRC += usb_extra.c | |||||
endif | |||||
ALL_SRC = $(SRC) | |||||
ALL_SRC += usb_mouse.c \ | |||||
mousekey.c \ | |||||
ps2.c \ | |||||
ps2_mouse.c \ | |||||
usb_extra.c | |||||
# C source file search path | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR) | |||||
# Output format. (can be srec, ihex, binary) | |||||
FORMAT = ihex | |||||
# Object files directory | |||||
# To put object files in current directory, use a dot (.), do NOT make | |||||
# this an empty or blank macro! | |||||
OBJDIR = . | |||||
# List C++ source files here. (C dependencies are automatically generated.) | |||||
CPPSRC = | |||||
# 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 = $(TARGET_DIR) $(COMMON_DIR) | |||||
# 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 | |||||
OPT_DEFS = | |||||
ifdef MOUSEKEY_ENABLE | |||||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||||
endif | |||||
ifdef PS2_MOUSE_ENABLE | |||||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
OPT_DEFS += -DUSB_EXTRA_ENABLE | |||||
endif | |||||
ifdef USB_NKRO_ENABLE | |||||
OPT_DEFS += -DUSB_NKRO_ENABLE | |||||
endif | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
OPT_DEFS += -DUSB_MOUSE_ENABLE | |||||
endif | |||||
# Place -D or -U options here for C sources | |||||
CDEFS = -DF_CPU=$(F_CPU)UL | |||||
CDEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for ASM sources | |||||
ADEFS = -DF_CPU=$(F_CPU) | |||||
ADEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for C++ sources | |||||
CPPDEFS = -DF_CPU=$(F_CPU)UL | |||||
#CPPDEFS += -D__STDC_LIMIT_MACROS | |||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS | |||||
CPPDEFS += $(OPT_DEFS) | |||||
#---------------- Compiler Options C ---------------- | |||||
# -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) | |||||
CFLAGS += -O$(OPT) | |||||
CFLAGS += -funsigned-char | |||||
CFLAGS += -funsigned-bitfields | |||||
CFLAGS += -ffunction-sections | |||||
CFLAGS += -fpack-struct | |||||
CFLAGS += -fshort-enums | |||||
CFLAGS += -Wall | |||||
CFLAGS += -Wstrict-prototypes | |||||
#CFLAGS += -mshort-calls | |||||
#CFLAGS += -fno-unit-at-a-time | |||||
#CFLAGS += -Wundef | |||||
#CFLAGS += -Wunreachable-code | |||||
#CFLAGS += -Wsign-compare | |||||
CFLAGS += -Wa,-adhlns=$(@:%.o=$(OBJDIR)/%.lst) | |||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
CFLAGS += $(CSTANDARD) | |||||
CFLAGS += -include config.h | |||||
#---------------- Compiler Options C++ ---------------- | |||||
# -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 | |||||
CPPFLAGS = -g$(DEBUG) | |||||
CPPFLAGS += $(CPPDEFS) | |||||
CPPFLAGS += -O$(OPT) | |||||
CPPFLAGS += -funsigned-char | |||||
CPPFLAGS += -funsigned-bitfields | |||||
CPPFLAGS += -fpack-struct | |||||
CPPFLAGS += -fshort-enums | |||||
CPPFLAGS += -fno-exceptions | |||||
CPPFLAGS += -Wall | |||||
CPPFLAGS += -Wundef | |||||
#CPPFLAGS += -mshort-calls | |||||
#CPPFLAGS += -fno-unit-at-a-time | |||||
#CPPFLAGS += -Wstrict-prototypes | |||||
#CPPFLAGS += -Wunreachable-code | |||||
#CPPFLAGS += -Wsign-compare | |||||
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst) | |||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
#CPPFLAGS += $(CSTANDARD) | |||||
CPPFLAGS += -include config.h | |||||
#---------------- Assembler Options ---------------- | |||||
# -Wa,...: tell GCC to pass this to the assembler. | |||||
# -adhlns: 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] | |||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex | |||||
# dump that will be displayed for a given single line of source input. | |||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100 | |||||
ASFLAGS += -include config.h | |||||
#---------------- 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 | |||||
# List any extra directories to look for libraries 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. | |||||
EXTRALIBDIRS = | |||||
#---------------- 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,--section-start,.data=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 | |||||
# | |||||
# Comennt out "--relax" option to avoid a error such: | |||||
# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12' | |||||
# | |||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref | |||||
LDFLAGS += -Wl,--relax | |||||
LDFLAGS += -Wl,--gc-sections | |||||
LDFLAGS += $(EXTMEMOPTS) | |||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) | |||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) | |||||
#LDFLAGS += -T linker_script.x | |||||
#---------------- Programming Options (avrdude) ---------------- | |||||
# Programming hardware | |||||
# Type: avrdude -c ? | |||||
# to get a full listing. | |||||
# | |||||
AVRDUDE_PROGRAMMER = stk500v2 | |||||
# com1 = serial port. Use lpt1 to connect to parallel port. | |||||
AVRDUDE_PORT = com1 # programmer connected to serial device | |||||
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) | |||||
#---------------- 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 | |||||
AR = avr-ar rcs | |||||
NM = avr-nm | |||||
AVRDUDE = avrdude | |||||
REMOVE = rm -f | |||||
REMOVEDIR = rm -rf | |||||
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 C: | |||||
MSG_COMPILING_CPP = Compiling C++: | |||||
MSG_ASSEMBLING = Assembling: | |||||
MSG_CLEANING = Cleaning project: | |||||
MSG_CREATING_LIBRARY = Creating library: | |||||
# Define all object files. | |||||
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) | |||||
# Define all listing files. | |||||
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) | |||||
# Compiler flags to generate dependency files. | |||||
GENDEPFLAGS = -MMD -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_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) | |||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) | |||||
# Default target. | |||||
all: begin gccversion sizebefore build sizeafter end | |||||
depend: tmk.c | |||||
@echo $< | |||||
@echo $(<F) | |||||
# $(CC) -E $(ALL_CFLAGS) $< | |||||
# Change the build target to build a HEX file or a library. | |||||
build: elf hex eep lss sym | |||||
#build: lib | |||||
elf: $(TARGET).elf | |||||
hex: $(TARGET).hex | |||||
eep: $(TARGET).eep | |||||
lss: $(TARGET).lss | |||||
sym: $(TARGET).sym | |||||
LIBNAME=lib$(TARGET).a | |||||
lib: $(LIBNAME) | |||||
# 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 | |||||
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf | |||||
ELFSIZE = $(SIZE) $(TARGET).elf | |||||
sizebefore: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ | |||||
2>/dev/null; echo; fi | |||||
sizeafter: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ | |||||
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) | |||||
# 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 | |||||
COFFCONVERT += --change-section-address .data-0x800000 | |||||
COFFCONVERT += --change-section-address .bss-0x800000 | |||||
COFFCONVERT += --change-section-address .noinit-0x800000 | |||||
COFFCONVERT += --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 -R .fuse -R .lock -R .signature $< $@ | |||||
%.eep: %.elf | |||||
@echo | |||||
@echo $(MSG_EEPROM) $@ | |||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ | |||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 | |||||
# Create extended listing file from ELF output file. | |||||
%.lss: %.elf | |||||
@echo | |||||
@echo $(MSG_EXTENDED_LISTING) $@ | |||||
$(OBJDUMP) -h -S -z $< > $@ | |||||
# Create a symbol table from ELF output file. | |||||
%.sym: %.elf | |||||
@echo | |||||
@echo $(MSG_SYMBOL_TABLE) $@ | |||||
$(NM) -n $< > $@ | |||||
# Create library from object files. | |||||
.SECONDARY : $(TARGET).a | |||||
.PRECIOUS : $(OBJ) | |||||
%.a: $(OBJ) | |||||
@echo | |||||
@echo $(MSG_CREATING_LIBRARY) $@ | |||||
$(AR) $@ $(OBJ) | |||||
# 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. | |||||
$(OBJDIR)/%.o : %.c | |||||
@echo | |||||
@echo $(MSG_COMPILING) $< | |||||
$(CC) -c $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create object files from C++ source files. | |||||
$(OBJDIR)/%.o : %.cpp | |||||
@echo | |||||
@echo $(MSG_COMPILING_CPP) $< | |||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C source files. | |||||
%.s : %.c | |||||
$(CC) -S $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C++ source files. | |||||
%.s : %.cpp | |||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@ | |||||
# Assemble: create object files from assembler source files. | |||||
$(OBJDIR)/%.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) $(ALL_SRC:%.c=$(OBJDIR)/%.o) | |||||
$(REMOVE) $(ALL_SRC:%.c=$(OBJDIR)/%.lst) | |||||
$(REMOVE) $(ALL_SRC:.c=.s) | |||||
$(REMOVE) $(ALL_SRC:.c=.d) | |||||
$(REMOVE) $(ALL_SRC:.c=.i) | |||||
$(REMOVEDIR) .dep | |||||
# Create object files directory | |||||
$(shell mkdir $(OBJDIR) 2>/dev/null) | |||||
# 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 | |||||
include $(COMMON_DIR)/Makefile.rules |
# Following variables need to be set in <target>/Makefile: | |||||
# TARGET | |||||
# COMMON_DIR | |||||
# TARGET_DIR | |||||
# TARGET_SRC | |||||
# MCU | |||||
# F_CPU | |||||
# List C source files here. (C dependencies are automatically generated.) | |||||
SRC = usb_keyboard.c \ | |||||
usb_debug.c \ | |||||
usb.c \ | |||||
jump_bootloader.c | |||||
SRC += $(TARGET_SRC) | |||||
# Option modules | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
SRC += usb_mouse.c | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
SRC += usb_extra.c | |||||
endif | |||||
# C source file search path | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/pjrc |
# Hey Emacs, this is a -*- makefile -*- | |||||
#---------------------------------------------------------------------------- | |||||
# WinAVR Makefile Template written by Eric B. Weddington, Jg 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 | |||||
# Carlos Lamas | |||||
# | |||||
#---------------------------------------------------------------------------- | |||||
# 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". | |||||
#---------------------------------------------------------------------------- | |||||
# Output format. (can be srec, ihex, binary) | |||||
FORMAT = ihex | |||||
# Object files directory | |||||
# To put object files in current directory, use a dot (.), do NOT make | |||||
# this an empty or blank macro! | |||||
OBJDIR = obj | |||||
# 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 = $(subst :, ,$(VPATH)) | |||||
# 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 | |||||
ifdef MOUSEKEY_ENABLE | |||||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||||
endif | |||||
ifdef PS2_MOUSE_ENABLE | |||||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
OPT_DEFS += -DUSB_EXTRA_ENABLE | |||||
endif | |||||
ifdef USB_NKRO_ENABLE | |||||
OPT_DEFS += -DUSB_NKRO_ENABLE | |||||
endif | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
OPT_DEFS += -DUSB_MOUSE_ENABLE | |||||
endif | |||||
# Place -D or -U options here for C sources | |||||
CDEFS = -DF_CPU=$(F_CPU)UL | |||||
CDEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for ASM sources | |||||
ADEFS = -DF_CPU=$(F_CPU) | |||||
ADEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for C++ sources | |||||
CPPDEFS = -DF_CPU=$(F_CPU)UL | |||||
#CPPDEFS += -D__STDC_LIMIT_MACROS | |||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS | |||||
CPPDEFS += $(OPT_DEFS) | |||||
#---------------- Compiler Options C ---------------- | |||||
# -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) | |||||
CFLAGS += -O$(OPT) | |||||
CFLAGS += -funsigned-char | |||||
CFLAGS += -funsigned-bitfields | |||||
CFLAGS += -ffunction-sections | |||||
CFLAGS += -fpack-struct | |||||
CFLAGS += -fshort-enums | |||||
CFLAGS += -Wall | |||||
CFLAGS += -Wstrict-prototypes | |||||
#CFLAGS += -mshort-calls | |||||
#CFLAGS += -fno-unit-at-a-time | |||||
#CFLAGS += -Wundef | |||||
#CFLAGS += -Wunreachable-code | |||||
#CFLAGS += -Wsign-compare | |||||
CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) | |||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
CFLAGS += $(CSTANDARD) | |||||
CFLAGS += -include config.h | |||||
#---------------- Compiler Options C++ ---------------- | |||||
# -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 | |||||
CPPFLAGS = -g$(DEBUG) | |||||
CPPFLAGS += $(CPPDEFS) | |||||
CPPFLAGS += -O$(OPT) | |||||
CPPFLAGS += -funsigned-char | |||||
CPPFLAGS += -funsigned-bitfields | |||||
CPPFLAGS += -fpack-struct | |||||
CPPFLAGS += -fshort-enums | |||||
CPPFLAGS += -fno-exceptions | |||||
CPPFLAGS += -Wall | |||||
CPPFLAGS += -Wundef | |||||
#CPPFLAGS += -mshort-calls | |||||
#CPPFLAGS += -fno-unit-at-a-time | |||||
#CPPFLAGS += -Wstrict-prototypes | |||||
#CPPFLAGS += -Wunreachable-code | |||||
#CPPFLAGS += -Wsign-compare | |||||
CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) | |||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
#CPPFLAGS += $(CSTANDARD) | |||||
CPPFLAGS += -include config.h | |||||
#---------------- Assembler Options ---------------- | |||||
# -Wa,...: tell GCC to pass this to the assembler. | |||||
# -adhlns: 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] | |||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex | |||||
# dump that will be displayed for a given single line of source input. | |||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100 | |||||
ASFLAGS += -include config.h | |||||
#---------------- 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 | |||||
# List any extra directories to look for libraries 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. | |||||
EXTRALIBDIRS = | |||||
#---------------- 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,--section-start,.data=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 | |||||
# | |||||
# Comennt out "--relax" option to avoid a error such: | |||||
# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12' | |||||
# | |||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref | |||||
LDFLAGS += -Wl,--relax | |||||
LDFLAGS += -Wl,--gc-sections | |||||
LDFLAGS += $(EXTMEMOPTS) | |||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) | |||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) | |||||
#LDFLAGS += -T linker_script.x | |||||
#---------------- Programming Options (avrdude) ---------------- | |||||
# Programming hardware | |||||
# Type: avrdude -c ? | |||||
# to get a full listing. | |||||
# | |||||
AVRDUDE_PROGRAMMER = stk500v2 | |||||
# com1 = serial port. Use lpt1 to connect to parallel port. | |||||
AVRDUDE_PORT = com1 # programmer connected to serial device | |||||
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) | |||||
#---------------- 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 | |||||
AR = avr-ar rcs | |||||
NM = avr-nm | |||||
AVRDUDE = avrdude | |||||
REMOVE = rm -f | |||||
REMOVEDIR = rmdir | |||||
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 C: | |||||
MSG_COMPILING_CPP = Compiling C++: | |||||
MSG_ASSEMBLING = Assembling: | |||||
MSG_CLEANING = Cleaning project: | |||||
MSG_CREATING_LIBRARY = Creating library: | |||||
# Define all object files. | |||||
OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC)))) | |||||
# Define all listing files. | |||||
LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC)))) | |||||
# Compiler flags to generate dependency files. | |||||
GENDEPFLAGS = -MMD -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_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) | |||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) | |||||
# Default target. | |||||
all: begin gccversion sizebefore build sizeafter end | |||||
# Change the build target to build a HEX file or a library. | |||||
build: elf hex eep lss sym | |||||
#build: lib | |||||
elf: $(TARGET).elf | |||||
hex: $(TARGET).hex | |||||
eep: $(TARGET).eep | |||||
lss: $(TARGET).lss | |||||
sym: $(TARGET).sym | |||||
LIBNAME=lib$(TARGET).a | |||||
lib: $(LIBNAME) | |||||
# 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 | |||||
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf | |||||
ELFSIZE = $(SIZE) $(TARGET).elf | |||||
sizebefore: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ | |||||
2>/dev/null; echo; fi | |||||
sizeafter: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ | |||||
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) | |||||
# 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 | |||||
COFFCONVERT += --change-section-address .data-0x800000 | |||||
COFFCONVERT += --change-section-address .bss-0x800000 | |||||
COFFCONVERT += --change-section-address .noinit-0x800000 | |||||
COFFCONVERT += --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 -R .fuse -R .lock -R .signature $< $@ | |||||
%.eep: %.elf | |||||
@echo | |||||
@echo $(MSG_EEPROM) $@ | |||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ | |||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 | |||||
# Create extended listing file from ELF output file. | |||||
%.lss: %.elf | |||||
@echo | |||||
@echo $(MSG_EXTENDED_LISTING) $@ | |||||
$(OBJDUMP) -h -S -z $< > $@ | |||||
# Create a symbol table from ELF output file. | |||||
%.sym: %.elf | |||||
@echo | |||||
@echo $(MSG_SYMBOL_TABLE) $@ | |||||
$(NM) -n $< > $@ | |||||
# Create library from object files. | |||||
.SECONDARY : $(TARGET).a | |||||
.PRECIOUS : $(OBJ) | |||||
%.a: $(OBJ) | |||||
@echo | |||||
@echo $(MSG_CREATING_LIBRARY) $@ | |||||
$(AR) $@ $(OBJ) | |||||
# 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. | |||||
$(OBJDIR)/%.o : %.c | |||||
@echo | |||||
@echo $(MSG_COMPILING) $< | |||||
$(CC) -c $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create object files from C++ source files. | |||||
$(OBJDIR)/%.o : %.cpp | |||||
@echo | |||||
@echo $(MSG_COMPILING_CPP) $< | |||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C source files. | |||||
%.s : %.c | |||||
$(CC) -S $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C++ source files. | |||||
%.s : %.cpp | |||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@ | |||||
# Assemble: create object files from assembler source files. | |||||
$(OBJDIR)/%.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 | |||||
$(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) $(OBJ:.o=.s) | |||||
$(REMOVE) $(OBJ:.o=.i) | |||||
$(REMOVE) -r .dep | |||||
$(REMOVEDIR) $(OBJDIR) | |||||
# Create object files directory | |||||
$(shell mkdir $(OBJDIR) 2>/dev/null) | |||||
# 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 | |||||
#---------------------------------------------------------------------------- | |||||
# 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". | |||||
#---------------------------------------------------------------------------- | |||||
# Following variables need to be set in <target>/Makefile: | # Following variables need to be set in <target>/Makefile: | ||||
# TARGET | # TARGET | ||||
# COMMON_DIR | # COMMON_DIR | ||||
oddebug.c | oddebug.c | ||||
SRC += $(TARGET_SRC) | SRC += $(TARGET_SRC) | ||||
# Option modules | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
SRC += usb_mouse.c | |||||
endif | |||||
ifdef MOUSEKEY_ENABLE | |||||
SRC += mousekey.c | |||||
endif | |||||
ifdef PS2_MOUSE_ENABLE | |||||
SRC += ps2.c \ | |||||
ps2_mouse.c | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
SRC += usb_extra.c | |||||
endif | |||||
# C source file search path | # C source file search path | ||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/usbdrv | |||||
# Output format. (can be srec, ihex, binary) | |||||
FORMAT = ihex | |||||
# Object files directory | |||||
# To put object files in current directory, use a dot (.), do NOT make | |||||
# this an empty or blank macro! | |||||
OBJDIR = obj | |||||
# 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 = $(TARGET_DIR) $(COMMON_DIR) | |||||
EXTRAINCDIRS = $(subst :, ,$(VPATH)) | |||||
# 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 | |||||
#OPT_DEFS = | |||||
ifdef MOUSEKEY_ENABLE | |||||
OPT_DEFS += -DMOUSEKEY_ENABLE | |||||
endif | |||||
ifdef PS2_MOUSE_ENABLE | |||||
OPT_DEFS += -DPS2_MOUSE_ENABLE | |||||
endif | |||||
ifdef USB_EXTRA_ENABLE | |||||
OPT_DEFS += -DUSB_EXTRA_ENABLE | |||||
endif | |||||
ifdef USB_NKRO_ENABLE | |||||
OPT_DEFS += -DUSB_NKRO_ENABLE | |||||
endif | |||||
ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||||
OPT_DEFS += -DUSB_MOUSE_ENABLE | |||||
endif | |||||
# Place -D or -U options here for C sources | |||||
CDEFS = -DF_CPU=$(F_CPU)UL | |||||
CDEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for ASM sources | |||||
ADEFS = -DF_CPU=$(F_CPU) | |||||
ADEFS += $(OPT_DEFS) | |||||
# Place -D or -U options here for C++ sources | |||||
CPPDEFS = -DF_CPU=$(F_CPU)UL | |||||
#CPPDEFS += -D__STDC_LIMIT_MACROS | |||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS | |||||
CPPDEFS += $(OPT_DEFS) | |||||
#---------------- Compiler Options C ---------------- | |||||
# -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) | |||||
CFLAGS += -O$(OPT) | |||||
CFLAGS += -funsigned-char | |||||
CFLAGS += -funsigned-bitfields | |||||
CFLAGS += -ffunction-sections | |||||
CFLAGS += -fpack-struct | |||||
CFLAGS += -fshort-enums | |||||
CFLAGS += -Wall | |||||
CFLAGS += -Wstrict-prototypes | |||||
#CFLAGS += -mshort-calls | |||||
#CFLAGS += -fno-unit-at-a-time | |||||
#CFLAGS += -Wundef | |||||
#CFLAGS += -Wunreachable-code | |||||
#CFLAGS += -Wsign-compare | |||||
CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) | |||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
CFLAGS += $(CSTANDARD) | |||||
CFLAGS += -include config.h | |||||
#---------------- Compiler Options C++ ---------------- | |||||
# -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 | |||||
CPPFLAGS = -g$(DEBUG) | |||||
CPPFLAGS += $(CPPDEFS) | |||||
CPPFLAGS += -O$(OPT) | |||||
CPPFLAGS += -funsigned-char | |||||
CPPFLAGS += -funsigned-bitfields | |||||
CPPFLAGS += -fpack-struct | |||||
CPPFLAGS += -fshort-enums | |||||
CPPFLAGS += -fno-exceptions | |||||
CPPFLAGS += -Wall | |||||
CPPFLAGS += -Wundef | |||||
#CPPFLAGS += -mshort-calls | |||||
#CPPFLAGS += -fno-unit-at-a-time | |||||
#CPPFLAGS += -Wstrict-prototypes | |||||
#CPPFLAGS += -Wunreachable-code | |||||
#CPPFLAGS += -Wsign-compare | |||||
CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst) | |||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) | |||||
#CPPFLAGS += $(CSTANDARD) | |||||
CPPFLAGS += -include config.h | |||||
#---------------- Assembler Options ---------------- | |||||
# -Wa,...: tell GCC to pass this to the assembler. | |||||
# -adhlns: 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] | |||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex | |||||
# dump that will be displayed for a given single line of source input. | |||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100 | |||||
ASFLAGS += -include config.h | |||||
#---------------- 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 | |||||
# List any extra directories to look for libraries 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. | |||||
EXTRALIBDIRS = | |||||
#---------------- 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,--section-start,.data=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 | |||||
# | |||||
# Comennt out "--relax" option to avoid a error such: | |||||
# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12' | |||||
# | |||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref | |||||
LDFLAGS += -Wl,--relax | |||||
LDFLAGS += -Wl,--gc-sections | |||||
LDFLAGS += $(EXTMEMOPTS) | |||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) | |||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) | |||||
#LDFLAGS += -T linker_script.x | |||||
#---------------- Programming Options (avrdude) ---------------- | |||||
# Programming hardware | |||||
# Type: avrdude -c ? | |||||
# to get a full listing. | |||||
# | |||||
AVRDUDE_PROGRAMMER = stk500v2 | |||||
# com1 = serial port. Use lpt1 to connect to parallel port. | |||||
AVRDUDE_PORT = com1 # programmer connected to serial device | |||||
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) | |||||
#---------------- 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 | |||||
AR = avr-ar rcs | |||||
NM = avr-nm | |||||
AVRDUDE = avrdude | |||||
REMOVE = rm -f | |||||
REMOVEDIR = rmdir | |||||
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 C: | |||||
MSG_COMPILING_CPP = Compiling C++: | |||||
MSG_ASSEMBLING = Assembling: | |||||
MSG_CLEANING = Cleaning project: | |||||
MSG_CREATING_LIBRARY = Creating library: | |||||
# Define all object files. | |||||
OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC)))) | |||||
# Define all listing files. | |||||
LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC)))) | |||||
# Compiler flags to generate dependency files. | |||||
GENDEPFLAGS = -MMD -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_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) | |||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) | |||||
# Default target. | |||||
all: begin gccversion sizebefore build sizeafter end | |||||
# Change the build target to build a HEX file or a library. | |||||
build: elf hex eep lss sym | |||||
#build: lib | |||||
elf: $(TARGET).elf | |||||
hex: $(TARGET).hex | |||||
eep: $(TARGET).eep | |||||
lss: $(TARGET).lss | |||||
sym: $(TARGET).sym | |||||
LIBNAME=lib$(TARGET).a | |||||
lib: $(LIBNAME) | |||||
# 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 | |||||
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf | |||||
ELFSIZE = $(SIZE) $(TARGET).elf | |||||
sizebefore: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ | |||||
2>/dev/null; echo; fi | |||||
sizeafter: | |||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ | |||||
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) | |||||
# 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 | |||||
COFFCONVERT += --change-section-address .data-0x800000 | |||||
COFFCONVERT += --change-section-address .bss-0x800000 | |||||
COFFCONVERT += --change-section-address .noinit-0x800000 | |||||
COFFCONVERT += --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 -R .fuse -R .lock -R .signature $< $@ | |||||
%.eep: %.elf | |||||
@echo | |||||
@echo $(MSG_EEPROM) $@ | |||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ | |||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 | |||||
# Create extended listing file from ELF output file. | |||||
%.lss: %.elf | |||||
@echo | |||||
@echo $(MSG_EXTENDED_LISTING) $@ | |||||
$(OBJDUMP) -h -S -z $< > $@ | |||||
# Create a symbol table from ELF output file. | |||||
%.sym: %.elf | |||||
@echo | |||||
@echo $(MSG_SYMBOL_TABLE) $@ | |||||
$(NM) -n $< > $@ | |||||
# Create library from object files. | |||||
.SECONDARY : $(TARGET).a | |||||
.PRECIOUS : $(OBJ) | |||||
%.a: $(OBJ) | |||||
@echo | |||||
@echo $(MSG_CREATING_LIBRARY) $@ | |||||
$(AR) $@ $(OBJ) | |||||
# 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. | |||||
$(OBJDIR)/%.o : %.c | |||||
@echo | |||||
@echo $(MSG_COMPILING) $< | |||||
$(CC) -c $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create object files from C++ source files. | |||||
$(OBJDIR)/%.o : %.cpp | |||||
@echo | |||||
@echo $(MSG_COMPILING_CPP) $< | |||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C source files. | |||||
%.s : %.c | |||||
$(CC) -S $(ALL_CFLAGS) $< -o $@ | |||||
# Compile: create assembler files from C++ source files. | |||||
%.s : %.cpp | |||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@ | |||||
# Assemble: create object files from assembler source files. | |||||
$(OBJDIR)/%.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 | |||||
$(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) $(OBJ:.o=.s) | |||||
$(REMOVE) $(OBJ:.o=.i) | |||||
$(REMOVE) -r .dep | |||||
$(REMOVEDIR) $(OBJDIR) | |||||
# Create object files directory | |||||
$(shell mkdir $(OBJDIR) 2>/dev/null) | |||||
# 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 | |||||
VPATH = $(TARGET_DIR):$(COMMON_DIR):$(COMMON_DIR)/vusb:$(COMMON_DIR)/vusb/usbdrv |
# 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 | |||||
# Carlos Lamas | |||||
# | |||||
#---------------------------------------------------------------------------- | |||||
# 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". | |||||
#---------------------------------------------------------------------------- | |||||
# Target file name (without extension). | # Target file name (without extension). | ||||
TARGET = tmk_hhkb | |||||
TARGET = hhkb | |||||
# Directory common source filess exist | # Directory common source filess exist | ||||
COMMON_DIR = .. | COMMON_DIR = .. | ||||
TARGET_DIR = . | TARGET_DIR = . | ||||
# keyboard dependent files | # keyboard dependent files | ||||
TARGET_SRC = keymap.c \ | |||||
matrix.c | |||||
TARGET_SRC = tmk.c \ | |||||
key_process.c \ | |||||
host_pjrc.c \ | |||||
keymap.c \ | |||||
matrix.c \ | |||||
led.c | |||||
# MCU name, you MUST set this to match the board you are using | # MCU name, you MUST set this to match the board you are using | ||||
USB_NKRO_ENABLE = yes # USB Nkey Rollover | USB_NKRO_ENABLE = yes # USB Nkey Rollover | ||||
include $(COMMON_DIR)/Makefile.pjrc | |||||
include $(COMMON_DIR)/Makefile.common | include $(COMMON_DIR)/Makefile.common |
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <avr/pgmspace.h> | #include <avr/pgmspace.h> | ||||
#include "usb_keyboard.h" | |||||
#include "keyboard.h" | |||||
#include "usb_keycodes.h" | #include "usb_keycodes.h" | ||||
#include "print.h" | #include "print.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
// define a condition to enter special function mode | // define a condition to enter special function mode | ||||
bool keymap_is_special_mode(uint8_t fn_bits) | bool keymap_is_special_mode(uint8_t fn_bits) | ||||
{ | { | ||||
return (usb_keyboard_mods == (BIT_LCTRL | BIT_LSHIFT | BIT_LALT | BIT_LGUI)); | |||||
return keyboard_get_mods() == (BIT_LSHIFT | BIT_RSHIFT) || keyboard_get_mods() == (BIT_LCTRL | BIT_RSHIFT); | |||||
} | } |
#include "usb_keycodes.h" | |||||
#include "host.h" | |||||
#include "led.h" | |||||
#include "keyboard.h" | |||||
#include "print.h" | |||||
static report_keyboard_t report0; | |||||
static report_keyboard_t report1; | |||||
report_keyboard_t *keyboard_report = &report0; | |||||
report_keyboard_t *keyboard_report_prev = &report1; | |||||
void keyboard_set_led(uint8_t usb_led) | |||||
{ | |||||
led_set(usb_led); | |||||
} | |||||
void keyboard_send(void) | |||||
{ | |||||
host_keyboard_send(keyboard_report); | |||||
} | |||||
void keyboard_add_key(uint8_t code) | |||||
{ | |||||
int8_t i = 0; | |||||
int8_t empty = -1; | |||||
for (; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report_prev->keys[i] == code) { | |||||
keyboard_report->keys[i] = code; | |||||
break; | |||||
} | |||||
if (empty == -1 && keyboard_report_prev->keys[i] == KB_NO && keyboard_report->keys[i] == KB_NO) { | |||||
empty = i; | |||||
} | |||||
} | |||||
if (i == REPORT_KEYS && empty != -1) { | |||||
keyboard_report->keys[empty] = code; | |||||
} | |||||
} | |||||
void keyboard_add_mod_bit(uint8_t mod) | |||||
{ | |||||
keyboard_report->mods |= mod; | |||||
} | |||||
void keyboard_set_mods(uint8_t mods) | |||||
{ | |||||
keyboard_report->mods = mods; | |||||
} | |||||
void keyboard_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
keyboard_add_mod_bit(MOD_BIT(code)); | |||||
} else { | |||||
keyboard_add_key(code); | |||||
} | |||||
} | |||||
void keyboard_swap_report(void) | |||||
{ | |||||
report_keyboard_t *tmp = keyboard_report_prev; | |||||
keyboard_report_prev = keyboard_report; | |||||
keyboard_report = tmp; | |||||
} | |||||
void keyboard_clear_report(void) | |||||
{ | |||||
keyboard_report->mods = 0; | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
} | |||||
uint8_t keyboard_has_anykey(void) | |||||
{ | |||||
uint8_t cnt = 0; | |||||
for (int i = 0; i < REPORT_KEYS; i++) { | |||||
if (keyboard_report->keys[i]) | |||||
cnt++; | |||||
} | |||||
return cnt; | |||||
} | |||||
uint8_t *keyboard_get_keys(void) | |||||
{ | |||||
return keyboard_report->keys; | |||||
} | |||||
uint8_t keyboard_get_mods(void) | |||||
{ | |||||
return keyboard_report->mods; | |||||
} |
#ifndef KEYBOARD_H | |||||
#define KEYBOARD_H | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include "host.h" | |||||
/* keyboard Modifiers in boot protocol report */ | |||||
#define BIT_LCTRL (1<<0) | |||||
#define BIT_LSHIFT (1<<1) | |||||
#define BIT_LALT (1<<2) | |||||
#define BIT_LGUI (1<<3) | |||||
#define BIT_RCTRL (1<<4) | |||||
#define BIT_RSHIFT (1<<5) | |||||
#define BIT_RALT (1<<6) | |||||
#define BIT_RGUI (1<<7) | |||||
#define BIT_LCTL BIT_LCTRL | |||||
#define BIT_RCTL BIT_RCTRL | |||||
#define BIT_LSFT BIT_LSHIFT | |||||
#define BIT_RSFT BIT_RSHIFT | |||||
extern report_keyboard_t *keyboard_report; | |||||
extern report_keyboard_t *keyboard_report_prev; | |||||
void keyboard_set_led(uint8_t led); | |||||
void keyboard_send(void); | |||||
void keyboard_add_key(uint8_t key); | |||||
void keyboard_add_mod_bit(uint8_t mod); | |||||
void keyboard_set_mods(uint8_t mods); | |||||
void keyboard_add_code(uint8_t code); | |||||
void keyboard_swap_report(void); | |||||
void keyboard_clear_report(void); | |||||
uint8_t keyboard_has_anykey(void); | |||||
uint8_t *keyboard_get_keys(void); | |||||
uint8_t keyboard_get_mods(void); | |||||
#endif | |||||
#include "keymap_skel.h" | #include "keymap_skel.h" | ||||
#include "usb_keyboard.h" | |||||
#include "keyboard.h" | |||||
#include "debug.h" | #include "debug.h" | ||||
#include "timer.h" | #include "timer.h" | ||||
#include "layer.h" | #include "layer.h" | ||||
debug(" -> "); debug_hex(current_layer); debug("\n"); | debug(" -> "); debug_hex(current_layer); debug("\n"); | ||||
} | } | ||||
} else { | } else { | ||||
if (usb_keyboard_has_key()) { // other keys is pressed | |||||
if (keyboard_has_anykey()) { // other keys is pressed | |||||
uint8_t _fn_to_send = BIT_SUBT(fn_bits, sent_fn); | uint8_t _fn_to_send = BIT_SUBT(fn_bits, sent_fn); | ||||
if (_fn_to_send) { | if (_fn_to_send) { | ||||
debug("Fn case: 4(send Fn before other key pressed)\n"); | debug("Fn case: 4(send Fn before other key pressed)\n"); | ||||
// send only Fn key first | // send only Fn key first | ||||
usb_keyboard_swap_report(); | |||||
usb_keyboard_clear_report(); | |||||
usb_keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys | |||||
usb_keyboard_set_mods(last_mods); | |||||
usb_keyboard_send(); | |||||
usb_keyboard_swap_report(); | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys | |||||
keyboard_set_mods(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= _fn_to_send; | sent_fn |= _fn_to_send; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// add Fn keys to send | // add Fn keys to send | ||||
//usb_keyboard_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys | |||||
//keyboard_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys | |||||
} | } | ||||
} else { // Fn state is changed(edge) | } else { // Fn state is changed(edge) | ||||
uint8_t fn_changed = 0; | uint8_t fn_changed = 0; | ||||
// pressed Fn | // pressed Fn | ||||
if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) { | if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) { | ||||
debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); | debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); | ||||
if (usb_keyboard_has_key()) { | |||||
if (keyboard_has_anykey()) { | |||||
debug("Fn case: 5(pressed Fn with other key)\n"); | debug("Fn case: 5(pressed Fn with other key)\n"); | ||||
sent_fn |= fn_changed; | sent_fn |= fn_changed; | ||||
} else if (fn_changed & sent_fn) { // pressed same Fn in a row | } else if (fn_changed & sent_fn) { // pressed same Fn in a row | ||||
if (BIT_SUBT(fn_changed, sent_fn)) { // layer not used && Fn not sent | if (BIT_SUBT(fn_changed, sent_fn)) { // layer not used && Fn not sent | ||||
debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n"); | debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n"); | ||||
// send only Fn key first | // send only Fn key first | ||||
usb_keyboard_swap_report(); | |||||
usb_keyboard_clear_report(); | |||||
usb_keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys | |||||
usb_keyboard_set_mods(last_mods); | |||||
usb_keyboard_send(); | |||||
usb_keyboard_swap_report(); | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys | |||||
keyboard_set_mods(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= fn_changed; | sent_fn |= fn_changed; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
last_fn = fn_bits; | last_fn = fn_bits; | ||||
last_mods = usb_keyboard_mods; | |||||
last_mods = keyboard_report->mods; | |||||
last_timer = timer_read(); | last_timer = timer_read(); | ||||
} | } | ||||
// send Fn keys | // send Fn keys | ||||
for (uint8_t i = 0; i < 8; i++) { | for (uint8_t i = 0; i < 8; i++) { | ||||
if ((sent_fn & fn_bits) & (1<<i)) { | if ((sent_fn & fn_bits) & (1<<i)) { | ||||
usb_keyboard_add_code(keymap_fn_keycode(1<<i)); | |||||
keyboard_add_code(keymap_fn_keycode(1<<i)); | |||||
} | } | ||||
} | } | ||||
} | } |
#ifndef LED_H | |||||
#define LED_H | |||||
#include "stdint.h" | |||||
/* keyboard LEDs */ | |||||
#define USB_LED_NUM_LOCK 0 | |||||
#define USB_LED_CAPS_LOCK 1 | |||||
#define USB_LED_SCROLL_LOCK 2 | |||||
#define USB_LED_COMPOSE 3 | |||||
#define USB_LED_KANA 4 | |||||
void led_set(uint8_t usb_led); | |||||
#endif |
#define ENDPOINT_HALT 0 | #define ENDPOINT_HALT 0 | ||||
#define TEST_MODE 2 | #define TEST_MODE 2 | ||||
// LEDS | |||||
#define USB_LED_NUM_LOCK 0 | |||||
#define USB_LED_CAPS_LOCK 1 | |||||
#define USB_LED_SCROLL_LOCK 2 | |||||
#define USB_LED_COMPOSE 3 | |||||
#define USB_LED_KANA 4 | |||||
#endif | #endif |
#define KEYS_MAX KBD_REPORT_KEYS | #define KEYS_MAX KBD_REPORT_KEYS | ||||
#endif | #endif | ||||
#define BIT_LCTRL (1<<0) | |||||
#define BIT_LSHIFT (1<<1) | |||||
#define BIT_LALT (1<<2) | |||||
#define BIT_LGUI (1<<3) | |||||
#define BIT_RCTRL (1<<4) | |||||
#define BIT_RSHIFT (1<<5) | |||||
#define BIT_RALT (1<<6) | |||||
#define BIT_RGUI (1<<7) | |||||
#define BIT_LCTL BIT_LCTRL | |||||
#define BIT_RCTL BIT_RCTRL | |||||
#define BIT_LSFT BIT_LSHIFT | |||||
#define BIT_RSFT BIT_RSHIFT | |||||
typedef struct report { | typedef struct report { | ||||
uint8_t keys[KEYS_MAX]; | uint8_t keys[KEYS_MAX]; |
# keyboard dependent files | # keyboard dependent files | ||||
TARGET_SRC = main.c \ | TARGET_SRC = main.c \ | ||||
keyboard.c \ | |||||
mousekey.c \ | |||||
layer.c \ | |||||
keymap.c \ | keymap.c \ | ||||
matrix.c \ | matrix.c \ | ||||
led.c \ | |||||
ps2.c \ | ps2.c \ | ||||
host_vusb.c \ | host_vusb.c \ | ||||
print.c \ | |||||
util.c \ | |||||
timer.c \ | |||||
usart_print.c | usart_print.c | ||||
OPT_DEFS = -DDEBUG_LEVEL=0 | OPT_DEFS = -DDEBUG_LEVEL=0 | ||||
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # | ||||
#MOUSEKEY_ENABLE = yes # Mouse keys | |||||
MOUSEKEY_ENABLE = yes # Mouse keys | |||||
#USB_EXTRA_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) | #USB_EXTRA_ENABLE = yes # Enhanced feature for Windows(Audio control and System control) | ||||
#USB_NKRO_ENABLE = yes # USB Nkey Rollover | #USB_NKRO_ENABLE = yes # USB Nkey Rollover | ||||
include $(COMMON_DIR)/Makefile.vusb | include $(COMMON_DIR)/Makefile.vusb | ||||
include $(COMMON_DIR)/Makefile.common |
# Name: Makefile | |||||
# Project: hid-mouse example | |||||
# Author: Christian Starkjohann | |||||
# Creation Date: 2008-04-07 | |||||
# Tabsize: 4 | |||||
# Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH | |||||
# License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) | |||||
# This Revision: $Id: Makefile 692 2008-11-07 15:07:40Z cs $ | |||||
DEVICE = atmega168 | |||||
F_CPU = 16000000 # in Hz | |||||
FUSE_L = # see below for fuse values for particular devices | |||||
FUSE_H = | |||||
#AVRDUDE = avrdude -c usbasp -p $(DEVICE) # edit this line for your programmer | |||||
AVRDUDE = avrdude -P COM1 -b 19200 -c arduino -p $(DEVICE) | |||||
CFLAGS = -Iusbdrv -I. -DDEBUG_LEVEL=1 | |||||
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o | |||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE) | |||||
############################################################################## | |||||
# Fuse values for particular devices | |||||
############################################################################## | |||||
# If your device is not listed here, go to | |||||
# http://palmavr.sourceforge.net/cgi-bin/fc.cgi | |||||
# and choose options for external crystal clock and no clock divider | |||||
# | |||||
################################## ATMega8 ################################## | |||||
# ATMega8 FUSE_L (Fuse low byte): | |||||
# 0x9f = 1 0 0 1 1 1 1 1 | |||||
# ^ ^ \ / \--+--/ | |||||
# | | | +------- CKSEL 3..0 (external >8M crystal) | |||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) | |||||
# | +------------------ BODEN (BrownOut Detector enabled) | |||||
# +-------------------- BODLEVEL (2.7V) | |||||
# ATMega8 FUSE_H (Fuse high byte): | |||||
# 0xc9 = 1 1 0 0 1 0 0 1 <-- BOOTRST (boot reset vector at 0x0000) | |||||
# ^ ^ ^ ^ ^ ^ ^------ BOOTSZ0 | |||||
# | | | | | +-------- BOOTSZ1 | |||||
# | | | | + --------- EESAVE (don't preserve EEPROM over chip erase) | |||||
# | | | +-------------- CKOPT (full output swing) | |||||
# | | +---------------- SPIEN (allow serial programming) | |||||
# | +------------------ WDTON (WDT not always on) | |||||
# +-------------------- RSTDISBL (reset pin is enabled) | |||||
# | |||||
############################## ATMega48/88/168 ############################## | |||||
# ATMega*8 FUSE_L (Fuse low byte): | |||||
# 0xdf = 1 1 0 1 1 1 1 1 | |||||
# ^ ^ \ / \--+--/ | |||||
# | | | +------- CKSEL 3..0 (external >8M crystal) | |||||
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled) | |||||
# | +------------------ CKOUT (if 0: Clock output enabled) | |||||
# +-------------------- CKDIV8 (if 0: divide by 8) | |||||
# ATMega*8 FUSE_H (Fuse high byte): | |||||
# 0xde = 1 1 0 1 1 1 1 0 | |||||
# ^ ^ ^ ^ ^ \-+-/ | |||||
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V) | |||||
# | | | | + --------- EESAVE (preserve EEPROM over chip erase) | |||||
# | | | +-------------- WDTON (if 0: watchdog always on) | |||||
# | | +---------------- SPIEN (allow serial programming) | |||||
# | +------------------ DWEN (debug wire enable) | |||||
# +-------------------- RSTDISBL (reset pin is enabled) | |||||
# | |||||
############################## ATTiny25/45/85 ############################### | |||||
# ATMega*5 FUSE_L (Fuse low byte): | |||||
# 0xef = 1 1 1 0 1 1 1 1 | |||||
# ^ ^ \+/ \--+--/ | |||||
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz) | |||||
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power) | |||||
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled) | |||||
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide) | |||||
# ATMega*5 FUSE_H (Fuse high byte): | |||||
# 0xdd = 1 1 0 1 1 1 0 1 | |||||
# ^ ^ ^ ^ ^ \-+-/ | |||||
# | | | | | +------ BODLEVEL 2..0 (brownout trigger level -> 2.7V) | |||||
# | | | | +---------- EESAVE (preserve EEPROM on Chip Erase -> not preserved) | |||||
# | | | +-------------- WDTON (watchdog timer always on -> disable) | |||||
# | | +---------------- SPIEN (enable serial programming -> enabled) | |||||
# | +------------------ DWEN (debug wire enable) | |||||
# +-------------------- RSTDISBL (disable external reset -> enabled) | |||||
# | |||||
################################ ATTiny2313 ################################# | |||||
# ATTiny2313 FUSE_L (Fuse low byte): | |||||
# 0xef = 1 1 1 0 1 1 1 1 | |||||
# ^ ^ \+/ \--+--/ | |||||
# | | | +------- CKSEL 3..0 (clock selection -> crystal @ 12 MHz) | |||||
# | | +--------------- SUT 1..0 (BOD enabled, fast rising power) | |||||
# | +------------------ CKOUT (clock output on CKOUT pin -> disabled) | |||||
# +-------------------- CKDIV8 (divide clock by 8 -> don't divide) | |||||
# ATTiny2313 FUSE_H (Fuse high byte): | |||||
# 0xdb = 1 1 0 1 1 0 1 1 | |||||
# ^ ^ ^ ^ \-+-/ ^ | |||||
# | | | | | +---- RSTDISBL (disable external reset -> enabled) | |||||
# | | | | +-------- BODLEVEL 2..0 (brownout trigger level -> 2.7V) | |||||
# | | | +-------------- WDTON (watchdog timer always on -> disable) | |||||
# | | +---------------- SPIEN (enable serial programming -> enabled) | |||||
# | +------------------ EESAVE (preserve EEPROM on Chip Erase -> not preserved) | |||||
# +-------------------- DWEN (debug wire enable) | |||||
# symbolic targets: | |||||
help: | |||||
@echo "This Makefile has no default rule. Use one of the following:" | |||||
@echo "make hex ....... to build main.hex" | |||||
@echo "make program ... to flash fuses and firmware" | |||||
@echo "make fuse ...... to flash the fuses" | |||||
@echo "make flash ..... to flash the firmware (use this on metaboard)" | |||||
@echo "make clean ..... to delete objects and hex file" | |||||
hex: main.hex | |||||
program: flash fuse | |||||
# rule for programming fuse bits: | |||||
fuse: | |||||
@[ "$(FUSE_H)" != "" -a "$(FUSE_L)" != "" ] || \ | |||||
{ echo "*** Edit Makefile and choose values for FUSE_L and FUSE_H!"; exit 1; } | |||||
$(AVRDUDE) -U hfuse:w:$(FUSE_H):m -U lfuse:w:$(FUSE_L):m | |||||
# rule for uploading firmware: | |||||
flash: main.hex | |||||
$(AVRDUDE) -U flash:w:main.hex:i | |||||
# rule for deleting dependent files (those which can be built by Make): | |||||
clean: | |||||
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s | |||||
# Generic rule for compiling C files: | |||||
.c.o: | |||||
$(COMPILE) -c $< -o $@ | |||||
# Generic rule for assembling Assembler source files: | |||||
.S.o: | |||||
$(COMPILE) -x assembler-with-cpp -c $< -o $@ | |||||
# "-x assembler-with-cpp" should not be necessary since this is the default | |||||
# file type for the .S (with capital S) extension. However, upper case | |||||
# characters are not always preserved on Windows. To ensure WinAVR | |||||
# compatibility define the file type manually. | |||||
# Generic rule for compiling C to assembler, used for debugging only. | |||||
.c.s: | |||||
$(COMPILE) -S $< -o $@ | |||||
# file targets: | |||||
# Since we don't want to ship the driver multipe times, we copy it into this project: | |||||
usbdrv: | |||||
cp -r ../usbdrv . | |||||
main.elf: usbdrv $(OBJECTS) # usbdrv dependency only needed because we copy it | |||||
$(COMPILE) -o main.elf $(OBJECTS) | |||||
main.hex: main.elf | |||||
rm -f main.hex main.eep.hex | |||||
avr-objcopy -j .text -j .data -O ihex main.elf main.hex | |||||
avr-size main.hex | |||||
# debugging targets: | |||||
disasm: main.elf | |||||
avr-objdump -d main.elf | |||||
cpp: | |||||
$(COMPILE) -E main.c |
usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); | usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); | ||||
kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; | kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; | ||||
} | } | ||||
/* | |||||
if (kbuf_head != kbuf_tail) { | |||||
if (usbInterruptIsReady()) { | |||||
usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); | |||||
kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; | |||||
} | |||||
} | |||||
*/ | |||||
} | } | ||||
void host_keyboard_send(report_keyboard_t *report) | void host_keyboard_send(report_keyboard_t *report) | ||||
print("kbuf: "); phex(kbuf_head); phex(kbuf_tail); print("\n"); | print("kbuf: "); phex(kbuf_head); phex(kbuf_tail); print("\n"); | ||||
} else { | } else { | ||||
print("kbuf: full\n"); | print("kbuf: full\n"); | ||||
// hmm... | |||||
/* | |||||
matrix_init(); | |||||
kbuf_head = 0; | |||||
kbuf_tail = 0; | |||||
*/ | |||||
} | } | ||||
} | } | ||||
#include "usb_keycodes.h" | |||||
#include "host.h" | |||||
#include "ps2.h" | |||||
#include "usb.h" | |||||
#include "keyboard.h" | |||||
#include "print.h" | |||||
static report_keyboard_t report0; | |||||
static report_keyboard_t report1; | |||||
static report_keyboard_t *report = &report0; | |||||
static report_keyboard_t *report_prev = &report1; | |||||
void keyboard_set_led(uint8_t usb_led) | |||||
{ | |||||
uint8_t ps2_led = 0; | |||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_SCROLL_LOCK); | |||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_NUM_LOCK); | |||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_CAPS_LOCK); | |||||
print("ps2_led: "); phex(ps2_led); print("\n"); | |||||
ps2_host_set_led(ps2_led); | |||||
} | |||||
void keyboard_send(void) | |||||
{ | |||||
host_keyboard_send(report); | |||||
} | |||||
bool keyboard_has_key(void) | |||||
{ | |||||
for (int i = 0; i < REPORT_KEYS; i++) { | |||||
if (report->keys[i]) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
void keyboard_add_mod(uint8_t mod) | |||||
{ | |||||
report->mods |= mod; | |||||
} | |||||
void keyboard_add_key(uint8_t code) | |||||
{ | |||||
int8_t i = 0; | |||||
int8_t empty = -1; | |||||
for (; i < REPORT_KEYS; i++) { | |||||
if (report_prev->keys[i] == code) { | |||||
report->keys[i] = code; | |||||
break; | |||||
} | |||||
if (empty == -1 && report_prev->keys[i] == KB_NO && report->keys[i] == KB_NO) { | |||||
empty = i; | |||||
} | |||||
} | |||||
if (i == REPORT_KEYS && empty != -1) { | |||||
report->keys[empty] = code; | |||||
} | |||||
} | |||||
void keyboard_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
keyboard_add_mod(code); | |||||
} else { | |||||
keyboard_add_key(code); | |||||
} | |||||
} | |||||
void keyboard_swap_report(void) | |||||
{ | |||||
report_keyboard_t *tmp = report_prev; | |||||
report_prev = report; | |||||
report = tmp; | |||||
} | |||||
void keyboard_clear_report(void) | |||||
{ | |||||
report->mods = 0; | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
report->keys[i] = 0; | |||||
} | |||||
} | |||||
report_keyboard_t *keyboard_report(void) | |||||
{ | |||||
return report; | |||||
} | |||||
report_keyboard_t *keyboard_report_prev(void) | |||||
{ | |||||
return report_prev; | |||||
} |
#ifndef KEYBOARD_H | |||||
#define KEYBOARD_H | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include "host.h" | |||||
void keyboard_set_led(uint8_t led); | |||||
void keyboard_send(void); | |||||
bool keyboard_has_key(void); | |||||
void keyboard_add_mod(uint8_t mod); | |||||
void keyboard_add_key(uint8_t key); | |||||
void keyboard_add_code(uint8_t code); | |||||
void keyboard_swap_report(void); | |||||
void keyboard_clear_report(void); | |||||
report_keyboard_t *keyboard_report(void); | |||||
report_keyboard_t *keyboard_report_prev(void); | |||||
#endif | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <avr/pgmspace.h> | #include <avr/pgmspace.h> | ||||
#include "usb_keyboard.h" | |||||
#include "usb_keycodes.h" | #include "usb_keycodes.h" | ||||
#include "keyboard.h" | |||||
#include "print.h" | #include "print.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "util.h" | #include "util.h" | ||||
// define a condition to enter special function mode | // define a condition to enter special function mode | ||||
bool keymap_is_special_mode(uint8_t fn_bits) | bool keymap_is_special_mode(uint8_t fn_bits) | ||||
{ | { | ||||
return usb_keyboard_mods == (BIT_LSHIFT | BIT_RSHIFT) || usb_keyboard_mods == (BIT_LCTRL | BIT_RSHIFT); | |||||
return keyboard_get_mods() == (BIT_LSHIFT | BIT_RSHIFT) || keyboard_get_mods() == (BIT_LCTRL | BIT_RSHIFT); | |||||
} | } |
#include "keymap_skel.h" | |||||
#include "keyboard.h" | |||||
#include "debug.h" | |||||
#include "timer.h" | |||||
#include "layer.h" | |||||
/* | |||||
* Parameters: | |||||
* ENTER_DELAY |=======| | |||||
* SEND_FN_TERM |================| | |||||
* | |||||
* Fn key processing cases: | |||||
* 1. release Fn after SEND_FN_TERM. | |||||
* Layer sw ___________|~~~~~~~~~~~|___ | |||||
* Fn press ___|~~~~~~~~~~~~~~~~~~~|___ | |||||
* Fn send ___________________________ | |||||
* | |||||
* 2. release Fn during SEND_FN_TERM.(not layer used) | |||||
* Layer sw ___________|~~~~~~|________ | |||||
* Fn press ___|~~~~~~~~~~~~~~|________ | |||||
* Fn key send __________________|~|______ | |||||
* other key press ___________________________ | |||||
* other key send ___________________________ | |||||
* | |||||
* 3. release Fn during SEND_FN_TERM.(layer used) | |||||
* Layer sw ___________|~~~~~~|________ | |||||
* Fn press ___|~~~~~~~~~~~~~~|________ | |||||
* Fn key send ___________________________ | |||||
* Fn send ___________________________ | |||||
* other key press _____________|~~|__________ | |||||
* other key send _____________|~~|__________ | |||||
* | |||||
* 4. press other key during ENTER_DELAY. | |||||
* Layer sw ___________________________ | |||||
* Fn key press ___|~~~~~~~~~|_____________ | |||||
* Fn key send ______|~~~~~~|_____________ | |||||
* other key press ______|~~~|________________ | |||||
* other key send _______|~~|________________ | |||||
* | |||||
* 5. press Fn while press other key. | |||||
* Layer sw ___________________________ | |||||
* Fn key press ___|~~~~~~~~~|_____________ | |||||
* Fn key send ___|~~~~~~~~~|_____________ | |||||
* other key press ~~~~~~~|___________________ | |||||
* other key send ~~~~~~~|___________________ | |||||
* | |||||
* 6. press Fn twice quickly and keep holding down.(repeat) | |||||
* Layer sw ___________________________ | |||||
* Fn key press ___|~|____|~~~~~~~~~~~~~~~~ | |||||
* Fn key send _____|~|__|~~~~~~~~~~~~~~~~ | |||||
*/ | |||||
// LAYER_ENTER_DELAY: prevent from moving new layer | |||||
#define LAYER_ENTER_DELAY 10 | |||||
// LAYER_SEND_FN_TERM: send keycode if release key in this term | |||||
#define LAYER_SEND_FN_TERM 40 | |||||
uint8_t default_layer = 0; | |||||
uint8_t current_layer = 0; | |||||
static bool layer_used = false; | |||||
static uint8_t new_layer(uint8_t fn_bits); | |||||
uint8_t layer_get_keycode(uint8_t row, uint8_t col) | |||||
{ | |||||
uint8_t code = keymap_get_keycode(current_layer, row, col); | |||||
// normal key or mouse key | |||||
if ((IS_KEY(code) || IS_MOUSEKEY(code))) { | |||||
layer_used = true; | |||||
} | |||||
return code; | |||||
} | |||||
// bit substract b from a | |||||
#define BIT_SUBT(a, b) (a&(a^b)) | |||||
void layer_switching(uint8_t fn_bits) | |||||
{ | |||||
// layer switching | |||||
static uint8_t last_fn = 0; | |||||
static uint8_t last_mods = 0; | |||||
static uint16_t last_timer = 0; | |||||
static uint8_t sent_fn = 0; | |||||
if (fn_bits == last_fn) { // Fn state is not changed | |||||
if (fn_bits == 0) { | |||||
// do nothing | |||||
} else { | |||||
if (timer_elapsed(last_timer) > LAYER_ENTER_DELAY) { | |||||
uint8_t _layer_to_switch = new_layer(BIT_SUBT(fn_bits, sent_fn)); | |||||
if (current_layer != _layer_to_switch) { // not switch layer yet | |||||
debug("Fn case: 1,2,3(LAYER_ENTER_DELAY passed)\n"); | |||||
debug("Switch Layer: "); debug_hex(current_layer); | |||||
current_layer = _layer_to_switch; | |||||
layer_used = false; | |||||
debug(" -> "); debug_hex(current_layer); debug("\n"); | |||||
} | |||||
} else { | |||||
if (keyboard_has_key()) { // other keys is pressed | |||||
uint8_t _fn_to_send = BIT_SUBT(fn_bits, sent_fn); | |||||
if (_fn_to_send) { | |||||
debug("Fn case: 4(send Fn before other key pressed)\n"); | |||||
// send only Fn key first | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys | |||||
keyboard_add_mod(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= _fn_to_send; | |||||
} | |||||
} | |||||
} | |||||
// add Fn keys to send | |||||
//keyboard_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys | |||||
} | |||||
} else { // Fn state is changed(edge) | |||||
uint8_t fn_changed = 0; | |||||
debug("fn_bits: "); debug_bin(fn_bits); debug("\n"); | |||||
debug("sent_fn: "); debug_bin(sent_fn); debug("\n"); | |||||
debug("last_fn: "); debug_bin(last_fn); debug("\n"); | |||||
debug("last_mods: "); debug_hex(last_mods); debug("\n"); | |||||
debug("last_timer: "); debug_hex16(last_timer); debug("\n"); | |||||
// pressed Fn | |||||
if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) { | |||||
debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); | |||||
if (keyboard_has_key()) { | |||||
debug("Fn case: 5(pressed Fn with other key)\n"); | |||||
sent_fn |= fn_changed; | |||||
} else if (fn_changed & sent_fn) { // pressed same Fn in a row | |||||
if (timer_elapsed(last_timer) > LAYER_ENTER_DELAY) { | |||||
debug("Fn case: 6(repate2)\n"); | |||||
// time passed: not repeate | |||||
sent_fn &= ~fn_changed; | |||||
} else { | |||||
debug("Fn case: 6(repate)\n"); | |||||
} | |||||
} | |||||
} | |||||
// released Fn | |||||
if ((fn_changed = BIT_SUBT(last_fn, fn_bits))) { | |||||
debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); | |||||
if (timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) { | |||||
//if (!layer_used && BIT_SUBT(fn_changed, sent_fn)) { // layer not used && Fn not sent | |||||
if (BIT_SUBT(fn_changed, sent_fn)) { // layer not used && Fn not sent | |||||
debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n"); | |||||
// send only Fn key first | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys | |||||
keyboard_add_mod(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= fn_changed; | |||||
} | |||||
} | |||||
debug("Switch Layer(released Fn): "); debug_hex(current_layer); | |||||
current_layer = new_layer(BIT_SUBT(fn_bits, sent_fn)); | |||||
layer_used = false; | |||||
debug(" -> "); debug_hex(current_layer); debug("\n"); | |||||
} | |||||
last_fn = fn_bits; | |||||
last_mods = keyboard_report()->mods; | |||||
last_timer = timer_read(); | |||||
} | |||||
// send Fn keys | |||||
for (uint8_t i = 0; i < 8; i++) { | |||||
if ((sent_fn & fn_bits) & (1<<i)) { | |||||
keyboard_add_code(keymap_fn_keycode(1<<i)); | |||||
} | |||||
} | |||||
} | |||||
inline | |||||
static uint8_t new_layer(uint8_t fn_bits) | |||||
{ | |||||
return (fn_bits ? keymap_fn_layer(fn_bits) : default_layer); | |||||
} |
#include "stdint.h" | |||||
#include "ps2.h" | |||||
#include "led.h" | |||||
void led_set(uint8_t usb_led) | |||||
{ | |||||
uint8_t ps2_led = 0; | |||||
if (usb_led & (1<<USB_LED_SCROLL_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_SCROLL_LOCK); | |||||
if (usb_led & (1<<USB_LED_NUM_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_NUM_LOCK); | |||||
if (usb_led & (1<<USB_LED_CAPS_LOCK)) | |||||
ps2_led |= (1<<PS2_LED_CAPS_LOCK); | |||||
ps2_host_set_led(ps2_led); | |||||
} |
// do nothing | // do nothing | ||||
} | } | ||||
else if (IS_MOD(code)) { | else if (IS_MOD(code)) { | ||||
keyboard_add_mod(MOD_BIT(code)); | |||||
keyboard_add_mod_bit(MOD_BIT(code)); | |||||
} | } | ||||
else if (IS_KEY(code)) { | else if (IS_KEY(code)) { | ||||
keyboard_add_key(code); | keyboard_add_key(code); |
#include "util.h" | #include "util.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "ps2.h" | #include "ps2.h" | ||||
#include "usb_keyboard.h" | |||||
#include "keyboard.h" | |||||
#include "matrix_skel.h" | #include "matrix_skel.h" | ||||