#!/bin/bash

# due-arduino-build.sh - Jordan Hazen, jnh at vt11.net (fetcher) 
# v0.1 - 2014-09-05
#  Compile and flash Arduino Sketch for Due/Udoo from command-line
#  released to public domain
#
# Derived from Daniel Bovensiepen's Ruby script
#   ( http://blog.mruby.sh/201303161453.html )
#
# Tested only on UDOO board, with Udoo-patched bossac
# Flash procedure may need adjustment for standalone Arduino Due
#
# "undefined reference to `_sbrk'" and similar warnings are normal
# (these appear on Arduino GUI too)

FLASH=false    # erase & flash SAM3X?
CPBIN=true     # save final .bin file to project dir?
RMTMP=false    # remove temporary compile directory?
NEWAR=false    # rebuild Arduino libs each time?

UART="ttymxc3"

PRELINK=/tmp/Arduino-core.a

BUILD_DIR="/tmp/arduino-build-$$"

# Arduino Application Folder
ARDUINO_DIR="/opt/arduino-1.5.4"

# Standard Paths for build process
SAM_DIR="${ARDUINO_DIR}/hardware/arduino/sam"
BIN_DIR="${ARDUINO_DIR}/hardware/tools/arm-none-eabi/bin"
TARGET_DIR="${SAM_DIR}/variants/arduino_due_x"
ARDUINO_SRC="${SAM_DIR}/cores/arduino"

# C Flags
CFLAGS_1="-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500"
CFLAGS_2="-fno-rtti -fno-exceptions"   # Used for C++ files only
CFLAGS_3="-Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=154 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON -DUSB_MANUFACTURER=\"Unknown\" -DUSB_PRODUCT=\"Udoo-SAM3X\""

INCLUDES="-I${SAM_DIR}/system/libsam -I${SAM_DIR}/system/CMSIS/CMSIS/Include/ -I${SAM_DIR}/system/CMSIS/Device/ATMEL/ -I${SAM_DIR}/cores/arduino -I${TARGET_DIR}"

C_FILES="WInterrupts.c syscalls_sam3.c cortex_handlers.c wiring.c wiring_digital.c itoa.c wiring_shift.c wiring_analog.c hooks.c iar_calls_sam3.c"

CPP_FILES="main.cpp WString.cpp RingBuffer.cpp UARTClass.cpp cxxabi-compat.cpp USARTClass.cpp USB/CDC.cpp USB/HID.cpp USB/USBCore.cpp Reset.cpp Stream.cpp Print.cpp WMath.cpp IPAddress.cpp wiring_pulse.cpp"

function add_to_lib () {
  if ! ${BIN_DIR}/arm-none-eabi-ar rcs ${BUILD_DIR}/core.a ${BUILD_DIR}/$1; then exit 1; fi
}

function flash () {
  echo "Erasing SAM3X and Uploading $1 ..."
  ${ARDUINO_DIR}/hardware/tools/bossac --port=${UART} -U false -e -w -v -b $1 -R
}

if [ .$1 = . -o .$1 = .-h ]; then
 echo "usage: `basename $0` [-f] [-s] [-r] [-n] sketch-file.ino"
 echo "        -f = erase and flash SAM3X"
 echo "        -s = save compiled .bin file to project directory"
 echo "        -r = remove temporary build directory after compiling"
 echo "        -n = force recompile of Arduino library files"
 exit 1
fi

while [ .${1:0:1} = .- ]; do
 if [ .$1 = .-n ]; then NEWAR=true
 elif [ .$1 = .-f ]; then FLASH=true
 elif [ .$1 = .-r ]; then RMTMP=true
 elif [ .$1 = .-s ]; then CPBIN=true
 else
   echo "Unknown option $1"
   exit 1
 fi
  shift
done

if [ "${1:(-3)}" = "bin" -a $FLASH = true ]; then
  flash $1
  exit 0
fi

if [ -e ${BUILD_DIR} ]; then
  echo "${BUILD_DIR} already exists -- please remove first."
  exit 1
fi

mkdir ${BUILD_DIR}

if [ $NEWAR = true -o ! -f $PRELINK ]; then

 echo "CC (Arduino library C Files)"
 for src_file in ${C_FILES}; do
   obj_file="${src_file%.*}.o"
   if ! ${BIN_DIR}/arm-none-eabi-gcc ${CFLAGS_1} ${CFLAGS_3} ${INCLUDES} ${ARDUINO_SRC}/${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
   add_to_lib $obj_file
 done
 
 echo "CC (Arduino library CPP Files)"
 for src_file in ${CPP_FILES}; do
   obj_file=`echo "${src_file%.*}.o" | sed 's/USB\///'`
   if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${ARDUINO_SRC}/${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
   add_to_lib $obj_file
 done

 echo "CC (variant)"
 if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${TARGET_DIR}/variant.cpp -o ${BUILD_DIR}/variant.cpp.o; then exit 1; fi
 add_to_lib variant.cpp.o

 cp ${BUILD_DIR}/core.a $PRELINK

else

 cd $BUILD_DIR
 cp $PRELINK core.a
 ar x core.a syscalls_sam3.o
 cd -

fi

echo "CPP/INO (User Files)"
for src_file in $*; do
  if [ ! -f $src_file ]; then
     echo "Source file $src_file not found!"
     exit 1
  fi
  obj_file="${src_file%.*}.o"

  if [ "${src_file:(-3)}" = "ino" ]; then
    TMPF=${BUILD_DIR}/tmp.${src_file}.cpp
    cat <<EOI >$TMPF
#include "Arduino.h"
EOI
    cat ${src_file} >>$TMPF
    src_file=$TMPF
  fi

  if ! ${BIN_DIR}/arm-none-eabi-g++ ${CFLAGS_1} ${CFLAGS_2} ${CFLAGS_3} ${INCLUDES} ${src_file} -o ${BUILD_DIR}/${obj_file}; then exit 1; fi
  add_to_lib $obj_file
done

SKETCH=${1%.*}

echo "LD"
# Link User specific things and Arduino Specific things together
if ! ${BIN_DIR}/arm-none-eabi-g++ -Os -Wl,--gc-sections -mcpu=cortex-m3 -T${TARGET_DIR}/linker_scripts/gcc/flash.ld -Wl,-Map,${BUILD_DIR}/${SKETCH}.map -o ${BUILD_DIR}/${SKETCH}.elf -L${BUILD_DIR} -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group ${BUILD_DIR}/syscalls_sam3.o ${BUILD_DIR}/${SKETCH}.o ${TARGET_DIR}/libsam_sam3x8e_gcc_rel.a ${BUILD_DIR}/core.a -Wl,--end-group; then exit 1; fi

echo "BIN ${SKETCH}.bin"
if ! ${BIN_DIR}/arm-none-eabi-objcopy -O binary ${BUILD_DIR}/${SKETCH}.elf ${BUILD_DIR}/${SKETCH}.bin; then exit 1; fi

echo
echo "Binary file is ready to upload:"
du -sb ${BUILD_DIR}/${SKETCH}.bin

if [ $CPBIN = true ]; then
  cp ${BUILD_DIR}/${SKETCH}.bin .
fi

if [ $FLASH = true ]; then
  # Upload to Board
  flash ${BUILD_DIR}/${SKETCH}.bin
fi

if [ .$RMTMP = .true ]; then
  rm -rf ${BUILD_DIR}
fi

#-possible extra includes to add after Arduino.h above-
#include "stdbool.h"
