#!/bin/bash

[ "$#" -ne 2 ] && {
	echo "This script acts as a wrapper around I2C commands in order to do direct memory reads of the GSC."
	echo "It will output the i2c response in an i2cdump type format."
	echo
	echo "Usage: $0 <offset> <length>"
	echo
	echo "Example usage to read all 2000(0x7d0) peripheral register values:"
	echo "	$0 0x100 0x7d0"
	exit 1
}

# Store inputs
BUS=0
ADDR=0x5e
OFFSET=$1
LENGTH=$2

# Misc variables
COUNT=0
PAGE=0
PRINTVAL=0x0000
REMAINDER=0
HIGH=
RETURN=

# Calculate initial page number based on passed in offset
PAGE=$((OFFSET / 0x100))
OFFSET=$((OFFSET % 0x100))

echo "      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f     0123456789abcdef"
while [[ $COUNT -ne $LENGTH ]]; do
	# Set the page number accordingly
	i2cset -f -y 0 0x20 0x16 $PAGE

	# Do either a full i2cdump or specify a range if bytes aren't a 0x100 aligned block
	if [[ $(($LENGTH - $COUNT)) -lt 0x100 || $OFFSET -ne 0 ]]; then
		HIGH=$(($LENGTH - $COUNT - 1 + $OFFSET))
		# Record remainder for i2c 0x100 upper range limit
		if [[ $HIGH -gt 0x100 ]]; then
			REMAINDER=$(($HIGH + 1 - 0x100))
		else
			REMAINDER=0
		fi

		RETURN=$(i2cdump -f -y -r ${OFFSET}-$(($HIGH - $REMAINDER)) 0 $ADDR b | grep ':')
		COUNT=$(($HIGH - $REMAINDER - $OFFSET + 1 + $COUNT))
		OFFSET=0
	else
		RETURN=$(i2cdump -f -y 0 $ADDR b | grep ':')
		COUNT=$(($COUNT + 0x100))
	fi

	if [[ "$RETURN" ]]; then # Only print reads
		# Format output to be continuous and account for page increase
		echo "$RETURN" | while read x; do
			printf "%04x" "$((0x$(echo $x | cut -d':' -f1) + $((PAGE * 0x100))))"
			echo ":${x##*:}"
		done
	fi

	# Increase the page count
	((++PAGE))
done
