#!/bin/sh

# notes about lock and fuses 

# lock=3f (or FF) means allow write anything (including bootloader)
# lock=2f (or EF) means bootloader section is protected from SPM (bad! bootloader upgrade impossible)
# lock is programmed the same way as lfuse, hfuse or efuse (via avrdude, or uisp)
# atmega128 datasheet page 286
# but lock can be reset to all-1 with chip erase only (atmega128 datasheet page 288)
# bit7:6=11 (unused, apparently reads as 00 but datasheet recommends writing 1)
# BAD: bit5:4=BLB12:BLB11=10 read and write (via LPM, SPM) of bootloader section: read allowed; write not allowed
# bit5:4=BLB12:BLB11=11 read and write (via LPM, SPM) of bootloader section: allow all read/write
# bit3:2=BLB02:BLB01=11 read and write (via LPM, SPM) of application section lock features disabled (allow all)
# bit1:0=LB2:LB1=11    read/verify and write (via parallel and SPI/JTAG) lock features disabled (allow all)

# lfuse=0f (2F was used earlier, changed to faster startup after about 30 v3.3)
# bit7=0 (brownout trigger level)
# bit6=0 (BOD brownout enabled)
# bit5:4=SUT1:0=10  (slowly rising power, 65msec)
   #     SUT1:0=00  (fast rising power or BOD enabled, 4.1msec)
# bit3:0=CKSEL3:0=1111 (external crystal)

# hfuse=C4
# bit7=1 (no OCD)
# bit6=1 (JTAG disabled)
# bit5=0 (SPI prog enabled)
# bit4=0 (CKOPT) THIS MUST BE "programmed" (page 36) for 16MHz crystal
# bit3=0 (0 means EEPROM preserved on erase)
# bit2:1=BOOTSZ1:0=10 (1024words=2kbyte boot area)
# BOOTRST=0

# efuse=FF  
# bit1=1 no atmega103 compatibilty.
# bit0=1 no watchdog
# ==================

DIFFOPTS="-i -b -B -U1"

# --------------
function config_to_ecm
{
	echo "uploading config and tables. You might want to reboot (prog.pl vems.hex Etf)"
	make mtt
	cat etc/config.mtt >$SERIAL_DEV
	# the USB-RS232 happily swallows the first byte (if conn was idle for long)
	echo "Man" >$SERIAL_DEV
	cat etc/tables.mtt >$SERIAL_DEV
}

function config_from_ecm
{
	echo "verifying config and tables"
	prog.pl vems.hex Etd
        diff ${DIFFOPTS} etc/config.txt mcd.txt
        diff ${DIFFOPTS} etc/tables.txt mct.txt
	echo "========LCD content:========"
	cat mll.txt
}

# ---------------

if [ "$2" = "" ]
then
	serial=000
	echo "WARNING!!! serial number not specified, using $serial"
else
	serial=$2
fi

if [ -z "$COM_PORT" ]
then
	SERIAL_DEV=/dev/ttyS0
else
	SERIAL_DEV=$COM_PORT
fi

echo "SERIAL_DEV=${SERIAL_DEV}"

incdir=inc
mainnoid=boot/main.hex
main=boot/main-id.hex

perl bin/patch_identity.pl $serial < $mainnoid >$main

efuse=$incdir/efuse.hex
hfuse=$incdir/hfuse.hex
lfuse=$incdir/lfuse.hex
lock=$incdir/lock.hex

Ufv="-U flash:v:$main"
Uev="-U efuse:v:$efuse"
Uhv="-U hfuse:v:$hfuse"
Ulv="-U lfuse:v:$lfuse"
Ulockv="-U lock:v:$lock"

Ufusesv="$Uev $Uhv $Ulv $Ulockv"

Ufw="-U flash:w:$main"
Uew="-u -U efuse:w:$efuse"
Uhw="-u -U hfuse:w:$hfuse"
Ulw="-u -U lfuse:w:$lfuse"
Ulockw="-u -U lock:w:$lock"

# DO NOT USE in SAME COMMAND, call avrdude SEPARATELY for EACH
# lock is not necessary (should be good by default; don't touch anyway, until after everything OK!)
# Ufusesw="$Uew $Uhw $Ulw $Ulockw"
Ufusesw="$Uew $Uhw $Ulw"

# makes xfuse.hex file according to parameters if it does not exist
function make_fusehex()
{
	if [ ! -f "$1" ]
	then
		echo ":01000000"$2 > $1
		echo ":00000001FF" >> $1
	fi
}

# simple checksum: sum of bytes (stored as an extra byte) is FF
make_fusehex $lfuse 0FF0
make_fusehex $hfuse C43B
make_fusehex $efuse FF00
make_fusehex $lock 3FC0

# TODO: lock bits

avrdudeargs="-c stk200 -p m128 -v"
# read from a known good (setup) AVR:
#avrdude -c stk200 -p m128 -v -U efuse:r:$efuse -U hfuse:r:$hfuse -U lfuse:r:$lfuse 

# lock bits = 0xef prevents selfdestruction of bootloader

if [ "$1" = "w" ]
then
	echo "erase and writing boot + write fuses after:"
	avrdude $avrdudeargs -e $Ufw 
	# $Ufusesw
fi

if [ "$1" = "f" ]
then
	echo "write fuses only:"
	# avrdude is stupid, so don't write more than 1 fuses in one step
  avrdude $avrdudeargs $Uew
  avrdude $avrdudeargs $Uhw
  avrdude $avrdudeargs $Ulw
# rethink thrice how and when to write lockbits!!!
#  avrdude $avrdudeargs $Ulockw 
fi

if [ "$1" = "v" ]
then
	echo "verify fuses and boot:"
	avrdude $avrdudeargs $Ufusesv $Ufv
fi

if [ "$1" = "vf" ]
then
	echo "verify fuses:"
	avrdude $avrdudeargs $Ufusesv 
fi

if [ "$1" = "e" ]
then
	echo "chip erase, unlock:"
  avrdude $avrdudeargs -e
fi

if [ "$1" = "b" ]
then
	echo "verifying bootloader"
	# prog.pl is not very tolerant at the start-to-talk phase
	# without the 't' flag, comm just did not work with my new pl2303 USB-rs232 adapter.
	# With 't' (that really just sends 9600 baud garbage 
	# when the bootloader is already in 19200) it works.
	# very strange,  
	perl bin/prog.pl $main tf
fi

if [ "$1" = "E" ]
then
	perl bin/prog.pl vems.hex 19200 :${SERIAL_DEV} E
fi

if [ "$1" = "Et" ]
then	
	echo "bin/prog.pl vems.hex 19200 :${SERIAL_DEV} Et"
	perl bin/prog.pl vems.hex 19200 :${SERIAL_DEV} Et
fi

if [ "$1" = "Etw" ]
then
	perl bin/prog.pl vems.hex 19200 Etw
fi

	echo "uploading config"
if [ "$1" = "c" ]
then
	echo "uploading config"
	make mtt
	cat etc/config.mtt >$SERIAL_DEV
fi

if [ "$1" = "t" ]
then
	echo "uploading tables"
	make mtt
	cat etc/tables.mtt >$SERIAL_DEV
fi

if [ "$1" = "ct" ]
then
	config_to_ecm
fi

if [ "$1" = "cv" ]
then
	config_from_ecm
fi

if [ "$1" = "ctv" ]
then
	config_to_ecm
	config_from_ecm
fi

# THE END

