#!/bin/sh
# Usage: update.sh firmware.hex
#

AVRDUDE_bin=/usr/bin/avrdude
AVRDUDE_cnf=/etc/avrdude.conf

#AVRDUDE_bin=~/local/bin/avrdude
#AVRDUDE_cnf=~/work/avrdude/avrdude_gpio.conf

printUsageAndExit(){
  echo "Usage: $0 firmware.hex"
  exit 1
}

# Validate arguments
if [ "$#" -ne 1 ]; then
  printUsageAndExit
fi

if ! [ -e $1 ]; then 
  echo "File $1 does not exist"
  printUsageAndExit
fi

# The device to program
DEVICE=atmega324pb

# The hex file to use is fed from the command line
FLASHFILE=$1

# Extended fuse byte
# - Brown out=2.7V
EFUSE=0xFD

# High fuse byte
# - Serial programming enabled
# - Preserve EEPROM during chip erase
# - Boot flash size=256
HFUSE=0xD7

# Low fuse byte
# - External crystal 8< MHz 
LFUSE=0xCE

# Lock byte
# - Further programming and verification disabled
# - SPM prohibited (LPM needed to store e.g. crc-table in flash)
LOCK=0x28

# Reset GPIO's (i.e. unexport them...)
echo  10 > /sys/class/gpio/unexport # RESET
echo   2 > /sys/class/gpio/unexport # SCLK
echo  11 > /sys/class/gpio/unexport # MISO
echo 129 > /sys/class/gpio/unexport # MOSI

# Do update
# -C Specify configuration file
# -p Specify target part
# -c Which programmer to use. In our case, a bitbang SPI defined in the configuration file
#
# -e Chip erase
# -U (1) Program the device
#     flash: Write to flash memory
#     w:     Write opration
#     file:  Name of the file to program
#     i:     Intel hex format
# -U (2,3,4) Write fuse bytes 
#     efuse: Extended fuse byte 
#     hfuse: High fuse byte
#     lfuse: Low fuse byte
#     w:     Write opration
#     0xXX:  The byte to program
#     m:     Immediate mode: Use bytes from the command line
# -U (5)     Write lock byte
#     lock:  Lock byte 
#     w:     Write opration
#     0xXX:  The byte to program
#     m:     Immediate mode: Use bytes from the command line
$AVRDUDE_bin -C $AVRDUDE_cnf -p $DEVICE -c avrdude_ub20 -e -U flash:w:$FLASHFILE:i -U efuse:w:$EFUSE:m -U hfuse:w:$HFUSE:m -U lfuse:w:$LFUSE:m -U lock:w:$LOCK:m

# Validate programming result
RET=$?
if [ $RET -ne 0 ]; then
  echo "Error while programming device. Error code $RET"
  exit 1
fi

exit 0

