# file: Makefile
#
# Example Makefile for a
# typical Nios program:
#
#   peripheral_test.ic
#
# ex:set noexpandtab:
#
# +---------------------------
# | How To Use This Makefile
# |
# | 1. Make a new directory with
# |    your project's .c and .h
# |    (and maybe .s) files
# |
# | 2. Copy this Makefile to it,
# |    and change the following
# |    variables as needed:
# |      PROGRAM_NAME -- base name for your program
# |      OBJECTS      -- list of .o files, which implies
# |                      the .c files and .s source files
# |      CINCLUDES    -- all your .h files
# |      AINCLUDES    -- all your .s include files
# |
# | 3. Type "make all" to build the project,
# |    or "make run" to make it and nios-run it.
# |


# +--------------------------
# | Project Files
# +--------------------------

# |
# | Program name -- the base for all
# | the output files including .srec and .out.
# |

SDK_ROOT = .
sopc_builder = ./
sopc_kit_nios = /opt/cdk4nios
PROGRAM_NAME = TomCat

# |
# | Assembly Include Files
# |
# | In this makefile, every C (.c) file
# | depends on every header file (.h)
# | in the CINCLUDES section, and every
# | assembly file (.s) depends on
# | each and every assembly-header (also .s)
# | in the AINCLUDES section


AINCLUDES =  \
	$(SDK_ROOT)/inc/nios.s \


CINCLUDES =  \
	$(SDK_ROOT)/inc/excalibur.h

# |
# | Object files
# |
# | The rules below will find the .c or .s files needed
# | to make each of these .o object files.
# |
# | This list will all go to the linker to make the
# | final binary.
# |
# | (This makefile follows the unusual convention
# | of appending .o after the original file name,
# | rather than replacing the file-type extension.
# | This makes it a)easier to identify a file's
# | history from its name, and b)easier to set
# | up implicit rules to generate them.
# |

OBJECTS =  \
	$(OBJ)/TomCat.cpp.o \
	$(OBJ)/tc_vars.cpp.o \
	$(OBJ)/hardware_t.cpp.o \
	$(OBJ)/display_t.cpp.o \
	$(OBJ)/floatstr_t.cpp.o \
        $(OBJ)/flash_t.cpp.o \
	$(OBJ)/signal_t.cpp.o \
	$(OBJ)/commif_t.cpp.o \
	$(OBJ)/userif_t.cpp.o \
	$(OBJ)/opsys_t.cpp.o \
	$(OBJ)/uart_rxchar.s.o \
	$(OBJ)/uart_txchar.s.o \
	$(OBJ)/uart_txstring.s.o \
	$(OBJ)/nios_setup.s.o \
	$(OBJ)/nios_delay.s.o \
	$(OBJ)/nios_close.s.o \
	$(OBJ)/nios_fstat.s.o \
	$(OBJ)/nios_sbrk.s.o \
	$(OBJ)/nios_lseek.s.o \
	$(OBJ)/nios_isatty.s.o \
	$(OBJ)/nios_jumptostart.s.o \
	$(OBJ)/nios_isrmanager.s.o \
	$(OBJ)/nios_copyrange.s.o \
	$(OBJ)/nios_zerorange.s.o \
	$(OBJ)/nios_uart.c.o \
	$(OBJ)/nios_cwpmanager.s.o \
	$(OBJ)/nios_more_cstubs.c.o \
	$(OBJ)/nios_math1.s.o \
	$(OBJ)/nios_mul.s.o \

# +----------------------
# | Anchor point:
# |  the SOPC Builder sdk directory
# |  generated for this project
# |
# | This example makefile happens to
# | be located at
# |
# |    <your quartus project><your nios cpu>_sdk/src/makefile_example
# |
# | so the sdk root is at ../..

SDK_ROOT = .
# 
#
#
# +--------------------------------
# | First, some traditional defines
# | for our particular tool chain
# |

GNU_TOOLS_PREFIX = nios-elf
AS = $(GNU_TOOLS_PREFIX)-as
CC = $(GNU_TOOLS_PREFIX)-gcc
AR = $(GNU_TOOLS_PREFIX)-ar
LD = $(GNU_TOOLS_PREFIX)-ld
OC = $(GNU_TOOLS_PREFIX)-objcopy
NM = $(GNU_TOOLS_PREFIX)-nm
OD = $(GNU_TOOLS_PREFIX)-objdump

NR = nios-run

# | A special echo that prints prettily

E = echo \\\# `date +%Y.%m.%d.%H:%M:%S` ---

# |
# | To keep things tidy, we stash all
# | object (.o) files into a directory
# | named "obj"
# |

OBJ = ./obj

# |
# | And the source directory? Is right here.
# |

SRC = ./src

# |
# | It is a Nios 32. Change it to 16 for Nios 16.
# |

M = 32

# +-----------------------------------
# | Include paths and such
# | If you have more directories of .h files,
# | add them here.
# |
# | We put in ../inc, ../../inc, and so on so
# | that it will look "up and over" to the sopc_builder
# | generated files, or other nearby inc dirs.
# |
# | Note that it uses "-I <dir>" format, which
# | is legal for both as and gcc.
# |

INCLUDE_PATHS = \
		-I $(SDK_ROOT)/inc \
		-I ./src \
		-I ./inc \
#		-I ../inc \
#		-I ../../inc \
#		-I ../../../inc \

# +------------------------------------
# | Switches for the compiler, the assembler,
# | and the linker
# |

ASFlags = \
		$(INCLUDE_PATHS) \
		--defsym __nios$(M)__=1 \
		-m$(M)

CCFlags = \
		$(INCLUDE_PATHS) \
		-W -g2 -c -O2 \
		-mno-zero-extend \
		-m$(M)

# -mdcache \

# +----------------------------------------
# | Rules
# |
# | These implicit rules treat all your .s
# | and all your .c files the same.
# |
# | "default" comes first so that if you just
# | type "make" it is the default target.
# |

default : ucl
	@$(E) .
	@$(E) . Built $(PROGRAM_NAME)_flash.ucl, $(PROGRAM_NAME)_ram.ucl
	@$(E) . try "make help" for more information
	@$(E) .

$(OBJ)/%.s.o : lib/%.s $(AINCLUDES)
	@$(E) Assembling $<
	@$(AS) $(ASFlags) $< -o $@

$(OBJ)/%.c.o : lib/%.c $(CINCLUDES)
	@$(E) Compiling lib $<
	@$(CC) $(CCFlags) $< -o $@


obj/%.cpp.o : src/%.cpp $(CINCLUDES)
	@$(E) Compiling $(CC) $(CCFlags) -D_Debug_ $< -o $@
	@$(CC) $(CCFlags) $< -o $@

$(OBJ) :
	@$(E) Making $@/ directory
	@mkdir $@

.PHONY: clean
clean : $(OBJ)
	@$(E) Removing objects
	@rm -rf $(OBJ)/*
	@rm -f $(PROGRAM_NAME).flash
	@rm -f $(PROGRAM_NAME).ram
	@rm -f ./ucl/$(PROGRAM_NAME)_flash.ucl
	@rm -f ./ucl/$(PROGRAM_NAME)_ram.ucl


# +-------------------------------------
# | Linking
# |
# | This is the most involved command line.
# | It was taken from the output of "nios-build"
# | and splayed out into an easier-to-read form.
# |
# | It references a linker script out in the sopc_builder
# | directory, and also makes sure that the first thing
# | in the file is a branch to "_start". (Usually
# | the routine named _start does a bunch of useful
# | initialization before your main() routine is called.)
# |
# | Note the use of GCC_VER -- this is because some of
# | the libraries are stashed in a version-named directory.
# |
# | Explanation of switches to the linker:
# |
# |   -e _start -u _start
# |       the entry point. _start() does the setup
# |       for Nios and then calls main().
# |
# |   -g
# |       include debug info in .out file. Does NOT
# |       increase the size of your S-Record.
# |
# |   -T (path to ld script)
# |       A "linker script" which knows about your memory
# |       map, by using symbols like nasys_program_mem from
# |       excalibur.s.
# |
# |   (path to nios_jumptostart.s.o)
# |       A "program prefix" that we at the front of
# |       every Nios program. It contains a jump to
# |       _start, and the ascii signature "Nios".
# |
# |   --start-group -l nios32 -l c -l m -l gcc --end-group
# |       The linker treats this a set of libraries
# |       to scan repeatedly until no new references are
# |       resolved. (The libraries sometimes refer to each
# |       other, so multiple passes are needed.) Each
# |       -l option is taken as lib(something).a, so the
# |       above line really looks for libnios32.1, libc.a,
# |       libm.a, and libgcc.a.
# |
# |   -L(various paths)
# |       Places the linker might look for libraries
# |

GCC_VER = $(shell nios-elf-gcc --version)
LFLAGS = \
		-e _start \
		-u _start \
		-g \
		-T $(sopc_builder)/bin/excalibur.ld \
		$(SDK_ROOT)/obj/nios_jumptostart.s.o \
		--start-group \
			-l c \
			-l m \
			-l gcc \
		--end-group \
		-L$(sopc_kit_nios)/nios-elf/lib/m32 \
		-L$(sopc_kit_nios)/lib/gcc-lib/nios-elf/$(GCC_VER)/m32 \
		-L./lib \

# -L$(sopc_kit_nios)/nios-elf/lib/m$(M) \
# -L$(sopc_kit_nios)/lib/gcc-lib/nios-elf/$(GCC_VER)/m$(M) \
# -l gcc
# |
# | Note about -L's above:
# |
# | we look in the quartus-3.0-and-later place, sopc_kit_nios,
# | and also in the pre-3.0 place, sopc_builder, for the compiler
# | libraries
# |

# |
# | Rule for making .out file from
# | the objects. The OBJECTS variable
# | must come before the LFLAGS, because
# | the LFLAGS has the libraries. The linker
# | needs to know which library routines you've
# | referenced from your code before scanning
# | them and deciding which parts to use.
# |

$(OBJ)/$(PROGRAM_NAME).out : $(OBJ) $(OBJECTS)
	@$(E) Linking $@
	@$(E) $(OBJECTS) $(LFLAGS) -o $(OBJ)/$(PROGRAM_NAME).out
	@$(LD) $(OBJECTS) $(LFLAGS) -o $(OBJ)/$(PROGRAM_NAME).out 

# |
# | S-Record
# |
# | We like Nios programs to be in an S-Record
# | for use by nios-run or SOPC Builder memory
# | contents
# |
# | The S-Record is the only output file that
# | we dont stash tidily into the obj folder
# |

$(PROGRAM_NAME).srec : $(OBJ)/$(PROGRAM_NAME).out $(OBJ)/flash_copy.hex $(sopc_builder)/startup/flash_header.sh
	@$(E) Converting $(PROGRAM_NAME) to S-Record
	@$(OC) -O srec $(OBJ)/$(PROGRAM_NAME).out $(OBJ)/$(PROGRAM_NAME).srec 
	@$(OD) $(OBJ)/$(PROGRAM_NAME).out -p | sed -n 's/^ *filesz \([^ ]*\).*/\1/p' | $(sopc_builder)/startup/flash_header.sh > $(PROGRAM_NAME).flash
	@grep S2 $(OBJ)/flash_copy.hex >> $(PROGRAM_NAME).flash
	@printf "#\n# Main program\n#\n" >> $(PROGRAM_NAME).flash
	@echo "r00800000-00040100" >> $(PROGRAM_NAME).flash
	@cat $(OBJ)/$(PROGRAM_NAME).srec >> $(PROGRAM_NAME).flash
	@unix2dos $(PROGRAM_NAME).flash
	@echo "r0" | cat - $(OBJ)/$(PROGRAM_NAME).srec | unix2dos > $(PROGRAM_NAME).ram


# |
# | Flash loader
# |
# | The loader is the startup code which
# | copies the compiled program from flash to RAM
# | end executes it.
# | Here it is custom-build to move exactly the required size.
# | The size is queried by objdump of the already linked program, 
# | written into a temporary header which gets referenced 
# | when assembling the loader.
# |

$(OBJ)/flash_copy.hex : $(OBJ)/$(PROGRAM_NAME).out $(sopc_builder)/startup/flash_copy.s
	@$(E) Assembling loader
	@$(OD) $(OBJ)/$(PROGRAM_NAME).out -p | sed -n 's/^ *filesz \([^ ]*\).*/.equ filesz, \1/p' > $(OBJ)/filesize.s
	@$(AS) $(ASFlags) -I $(OBJ) $(sopc_builder)/startup/flash_copy.s -o $(OBJ)/flash_copy.o
	@$(LD) -Ttext=0x40000 $(OBJ)/flash_copy.o -o $(OBJ)/flash_copy.out
	@$(OC) -O srec $(OBJ)/flash_copy.out $(OBJ)/flash_copy.hex

$(OBJ)/flash_copy.srec : $(OBJ)/flash_copy.out
	@$(OC) -O srec $(OBJ)/flash_copy.out $(OBJ)/flash_copy.srec

$(OBJ)/flash_copy.bin : $(OBJ)/flash_copy.out
	@$(OC) -O binary --only-section .text --pad-to 0x40100 $(OBJ)/flash_copy.out $(OBJ)/flash_copy.bin


# |
# | Compressed firmware images
# |
# | We use the now mandatory program "uclpack" to compress
# | RAM and Flash image.
# |

$(OBJ)/$(PROGRAM_NAME).bin : $(OBJ)/$(PROGRAM_NAME).out
	@$(OC) -O binary $(OBJ)/$(PROGRAM_NAME).out $(OBJ)/$(PROGRAM_NAME).bin

$(PROGRAM_NAME)_ram.ucl : $(OBJ)/$(PROGRAM_NAME).bin
	@uclpack --best --2e -b8000000 $(OBJ)/$(PROGRAM_NAME).bin ./ucl/$(PROGRAM_NAME)_ram.ucl

$(PROGRAM_NAME)_flash.ucl : $(OBJ)/$(PROGRAM_NAME).bin $(OBJ)/flash_copy.bin
	@cat $(OBJ)/flash_copy.bin $(OBJ)/$(PROGRAM_NAME).bin > $(OBJ)/flash.bin
	@uclpack --best --2e -b8000000 $(OBJ)/flash.bin ./ucl/$(PROGRAM_NAME)_flash.ucl


# |
# | Handy auxilliary files
# |

$(OBJ)/$(PROGRAM_NAME).nm : $(OBJ)/$(PROGRAM_NAME).out
	@$(E) Making $(PROGRAM_NAME).nm
	@$(NM) $(OBJ)/$(PROGRAM_NAME).out | sort > $(OBJ)/$(PROGRAM_NAME).nm

$(OBJ)/$(PROGRAM_NAME).objdump : $(OBJ)/$(PROGRAM_NAME).out
	@$(E) Making $(PROGRAM_NAME).objdump
	@$(OD) $(OBJ)/$(PROGRAM_NAME).out -d --source > $(OBJ)/$(PROGRAM_NAME).objdump

# +-------------------------------------
# | Shortcut Targets
# |

.PHONY: ucl
ucl : $(PROGRAM_NAME)_ram.ucl $(PROGRAM_NAME)_flash.ucl

.PHONY: srec
srec : $(PROGRAM_NAME).srec

.PHONY: out
out : $(OBJ)/$(PROGRAM_NAME).out

.PHONY: flash
flash : srec aux
	./flashloader.sh

.PHONY: ram
ram : srec aux
	./ramloader.sh

.PHONY: aux
aux : $(OBJ)/$(PROGRAM_NAME).nm $(OBJ)/$(PROGRAM_NAME).objdump

.PHONY: all
all : srec ucl aux

.PHONY: doc
doc :
	$(DOXYGEN) Doxyfile

.PHONY: release
release : clean all 
	@zip release TomCat.* ramloader.* flashloader.* WelecUpdate.* easyloader readme.txt Makefile 
	@zip -r release ./ucl/flashloader.* ./ucl/ramloader.* ./ucl/*.ucl ./ucl/GERMSloader.pl
	@zip -r release ./script/flashloader.* ./script/ramloader.* ./script/GERMSloader.pl
	@zip -r release ./src/*.h ./src/*.cpp
	@zip -r release ./doc/*.txt ./doc/*.ods ./doc/*.xls ./doc/*.pdf
	@zip -r release ./screenshot/*.cpp ./screenshot/*.h ./screenshot/*.exe ./screenshot/w2000a-screenshot ./screenshot/scrsh.* ./screenshot/README.txt ./screenshot/Makefile

.PHONY: help
help :
	@echo 
	@echo Program name: $(PROGRAM_NAME)
	@echo 
	@echo Available makefile targets:
	@echo
	@echo "  make all   -- compile, link, and convert to S-Record, generate .nm and .objdump files"
	@echo "  make clean -- erase intermediate files"
	@echo "  make ucl   -- compile, link, and convert to compressed .ucl upload files"
	@echo "  make ram   -- make all and load to RAM"
	@echo "  make flash -- make all and load to flash"
	@echo "  make srec  -- compile, link, and convert to S-Record"
	@echo 
	@echo "  make out   -- only make the .out file"
	@echo "  make aux   -- generate .nm and .objdump files"
	@echo

# end of file
