warn1="WARNING: do NOT power-down while saving/copying!"
img="[kernel+initrd]"

eth_off() {
        local x
        let x=`devmem 0x3000000a 16`
        x=$((x & ~0x4 | 0x8))
        devmem 0xfffff400 32 0x00000400
        devmem 0x3000000a 16 $x
}

eth_on() {
        local x
        let x=`devmem 0x3000000a 16`
        x=$((x & ~0x8 | 0x4))
        devmem 0xfffff404 32 0x00000c00
        devmem 0x3000000a 16 $x
}

attime() {
	local x sec tenths
	let x=`devmem 0x3000000c`
	sec=$((x / 100000))
	tenths=$((x % 100000 / 1000))
	printf "%d.%02d" $sec $tenths
}

usb_off() {
	devmem 0xfffff404 32 0x200 #PIO disable
	devmem 0xfffff414 32 0x200 #output disable
	devmem 0xfffff434 32 0x200 #Clear output data
	devmem 0xfffffc14 32 0x000000 #periph clock disable
	devmem 0xfffffc2c 32 0x10073E01 #disable PLL B
	#devmem 0xfffffc04 32 0x240 #System clock disable
	#devmem 0x500004 32 0x80
}

usb_on() {
	devmem 0xfffff400 32 0x200 #PIO enable
	devmem 0xfffff410 32 0x200 #Output enable
	devmem 0xfffff430 32 0x200 #Set output data
	devmem 0xfffffc10 32 0x100000 #Periph clock enable
	devmem 0xfffffc2c 32 0x10073E01 #Enable PLL B
	devmem 0xfffffc00 32 0x240 #System clock enable
	devmem 0x500004 32 0x80
}

usbload() {
	usb_on
	mount -t tmpfs tmpfs /lib/modules
	tar -x -z -f /modules.tar.gz -C /
	modprobe scsi_mod
	modprobe sd_mod
        modprobe nls_base
	modprobe usbcore
	modprobe ohci-hcd
	modprobe usb_storage
	modprobe smsc95xx
	umount /lib/modules
}

sdload() {
	mount -t tmpfs tmpfs /lib/modules
	tar -x -z -f /modules.tar.gz -C /
	modprobe mmc_core
	modprobe at91_mci
	modprobe mmc_block
	umount /lib/modules
	sleep .5
}

nandsave() {
        echo "$warn1"
        echo -n "Saving [initrd] to NAND ... "

	mount -o remount,ro /
	sync
	dd if=/dev/ram0 of=/dev/nbd2 bs=131072 count=20 >/dev/null 2>&1
	sync
	mount -o remount,rw /
        echo "done"
}

sdsave() {
        echo "$warn1"
        echo -n "Saving [initrd] to mSD ... "

	sdload
	mount -o remount,ro /
	sync
	dd if=/dev/ram0 of=/dev/mmcblk0p3 bs=131072 count=20 >/dev/null 2>&1
	sync
	mount -o remount,rw /
        echo "done"
}

save() {
	eval `ts4200ctl -i`
	let bootdev=$bootdev
	if [ "$bootdev" -eq 0 ]; then
		nandsave
	else
		sdsave
	fi
}

sd2nand() {
	echo "$warn1"
        echo -n "Copying $img mSD --> NAND ... "

	dd if=/dev/mmcblk0p2 of=/tmp/image bs=512 count=5119 >/dev/null 2>&1
	dd if=/tmp/image of=/dev/nbd1 bs=512 count=5119 >/dev/null 2>&1
	sync
        rm /tmp/image
        wait

	dd if=/dev/mmcblk0p3 of=/tmp/image bs=131072 count=20 >/dev/null 2>&1
	dd if=/tmp/image of=/dev/nbd2 bs=131072 count=20 >/dev/null 2>&1
	sync
        rm /tmp/image
        echo "done"
}

nand2sd() {
        echo "$warn1"
        echo "Copying $img NAND --> mSD ... "
	dd if=/dev/nbd1 of=/tmp/image bs=512 count=5119 >/dev/null 2>&1
	dd if=/tmp/image of=/dev/mmcblk0p2 bs=512 count=5119 >/dev/null 2>&1
	sync
        rm /tmp/image
        wait

	dd if=/dev/nbd2 of=/tmp/image bs=131072 count=20 >/dev/null 2>&1
	dd if=/tmp/image of=/dev/mmcblk0p3 bs=131072 count=20 >/dev/null 2>&1
	sync
        rm /tmp/image
        echo "done"
}



#Usage: setdiopin <pin> <1,0,Z>
#pin can be paXX/pbXX/pcXX for CPU pins, or 0 to 31 for FPGA pins
setdiopin() {
	local bit base addr
	if [ `expr match "$1" '[Pp]'` -eq 1 ] ; then 
		bit=${1:2}
		let bit="1 << bit"
		case $1 in
		PA*|pa*)
			base=0xfffff400
			;;
		PB*|pb*)
			base=0xfffff600
			;;
		PC*|pc*)
			base=0xfffff800
			;;
		esac
		case $2 in
		0)
			devmem $base 32 $bit
			let addr="base + 0x10"
			devmem $addr 32 $bit
			let addr="base + 0x34"
			devmem $addr 32 $bit
			;;
		1)
			devmem $base 32 $bit
			let addr="base + 0x10"
			devmem $addr 32 $bit
			let addr="base + 0x30"
			devmem $addr 32 $bit
			;;
		z|Z)
			devmem $base 32 $bit
			let addr="base + 0x14"
			devmem $addr 32 $bit
			;;
		a|A)
			let addr="base + 0x04"
			devmem $addr 32 $bit
			let addr="base + 0x74"
			devmem $addr 32 $bit
			;;
		b|B)
			let addr="base + 0x04"
			devmem $addr 32 $bit
			let addr="base + 0x70"
			devmem $addr 32 $bit
			;;
		esac
	else	
		if [ -z "$dio_out" ]; then
	      	        eval `ts4200ctl --getdioreg`
        	fi
	        case $2 in
        	0)
                	let diodir="diodir | (1<<$1)"
	                let dio_out="dio_out & ~(1<<$1)"
	                ;;
	        1)
	                let diodir="diodir | (1<<$1)"
	                let dio_out="dio_out | (1<<$1)"
       	        	;;
	        z|Z)
	                let diodir="diodir & ~(1<<$1)"
	                ;;
	        esac
	        ts4200ctl --setdio $dio_out --setdiodir $diodir
	fi
}

#Usage: getdiopin <pin>
#pin can be paXX/pbXX/pcXX for CPU pins, or 0 to 31 for FPGA pins
getdiopin() {
        local x dio bit 
        eval `ts4200ctl --getdio`
	bit=$1
	if [ `expr match "$1" '[Pp]'` -eq 1 ] ; then 
		bit=${1:2}
	fi
	case $1 in
	PA*|pa*)
		dio=`devmem 0xfffff43c 32`
		;;
	PB*|pb*)
		dio=`devmem 0xfffff63c 32`
		;;
	PC*|pc*)
		dio=`devmem 0xfffff83c 32`
		;;
	esac
        let x="(dio >> $bit) & 0x1"
        echo $x
        return $x
}

getadc() {
	local x i addr
	setdiopin pc0 z
	setdiopin pc1 z
	setdiopin pc2 z
	setdiopin pc3 z
	devmem 0xfffffc10 32 0x20 # enable ADC clk
	devmem 0xfffe0004 32 0x07070700 # config
	devmem 0xfffe0010 32 0xf # enable all channels
	devmem 0xfffe0000 32 0x2 # start sampling
	let x=0 # wait for conversion:
	while [ $x -ne 15 ]; do
		let x=`devmem 0xfffe001c`
		let x="x & 0xf"
	done
	let i=0
	while [ $i -ne 4 ]; do
		let addr="0xfffe0030 + 4 * i"
		let x=`devmem $addr 32`
		let x="x << 22"
		let x="x / 1301505"
		echo "chan$i=${x}"
		let i="i + 1"
	done
	devmem 0xfffffc14 32 0x20 # disable ADC clk
}

pc104on() {
	devmem 0x30000020 16 0x181
}

pc104off() {
	devmem 0x30000020 16 0x0
}

setupclk() {

	eval `ts4200ctl --getrtc`

	# We make a reasonable default date available here, if the RTC isn't
	# being cooperative.  If the RTC is at least there, we program the RTC
	# with the default date.

	if [ "$rtc_oscillator_ok" -eq 0 ]; then date 010100002001; fi

	if [ "$rtc_present" -eq 1 ]; then

		if [ "$rtc_oscillator_ok" -eq 0 ]; then ts4200ctl --setrtc; fi

		eval `ts4200ctl --set512` # Enable the RTC's 512 Hz output for the FPGA-based watchdog.

		if [ "$rtc_512hz_out" -eq 1 ]; then # Set the FPGA to use the input.

		    let x=`devmem 0x3000000a 16`
		    let x=$((x | 0x200))
		    devmem 0x3000000a 16 $x
		fi
	fi
}

tshelp() {
	echo "usbload - Load USB kernel drivers"
	echo "sdload - Load SD kernel drivers"
	echo "eth_off - Turn Ethernet off (eth_on turns it back on)"
	echo "usb_off - Disable USB host (usb_on or usbload to reenable)"
	echo "getadc - print analog input values in mV (assumes 3.3V AN_VREF"
	echo "setdiopin <pin> <1,0,Z,A,B> - set DIO pin"
	echo "getdiopin <pin> - get DIO input state"
	echo "example: 'setdiopin PC3 A' muxes pin PC3 to peripheral A"
	echo "save - save initrd back to boot device (SD or onboard flash)"
	echo "sd2nand - Copy kernel and initrd from SD card to NAND"
	echo "nand2sd - Copy kernel and initrd from NAND to SD card"
	echo "sdsave - Save initrd to SD card"
	echo "nandsave - Save initrd to NAND"
	echo "exit - boot SD card (if present) or filesystem mounted at /mnt/root" 
}
