#!/bin/bash

#
# UART Port 0	UART Port 1	RS-232	RS-422/485-4W	RS-485-2W
# GP76		GP117		H	L		L
# GP77		GP114		H	L		L
# GP80		GP115		L	L		H
# GP81		GP116		L	H		L
#

UART_GPIO_0=(76 77 80 81)
UART_GPIO_1=(117 114 115 116)
RS232_MODE=0
RS485_MODE=1
RS422_MODE=2
RS422_GPIO_MODE=(0 0 0 1)
RS485_GPIO_MODE=(0 0 1 0)
RS232_GPIO_MODE=(1 1 0 0)

declare CUR_UART

#
# Init GPIO PIN status, this function will be only executed ONCE
#
gpio_init_action()
{
	# export the gpio if it's not existed
	if [ ! -f /sys/class/gpio/gpio$1/direction ]; then
		echo $1 > /sys/class/gpio/export
		echo "out" > /sys/class/gpio/gpio$1/direction
	fi
}

gpio_init()
{
	local i;
	if [ x"$1" == x"0" ]; then
		CUR_UART=("${UART_GPIO_0[@]}")
	else
		CUR_UART=("${UART_GPIO_1[@]}")
	fi
	for ((i=0; i<${#CUR_UART[@]}; i++)); do
		gpio_init_action ${CUR_UART[$i]}
	done
}


# 
# This function will compare two arrays value in order to recognize current UART mode. 
#
diff_array()
{
	declare -a arr1=("${!1}")
	declare -a arr2=("${!2}")
	[ ${#arr1[*]} != ${#arr2[*]} ] && { echo arrays different size; exit 1; }
	for ii in ${!arr1[*]}; do
		[ "${arr1[$ii]}" == "${arr2[$ii]}" ] || { echo different element $ii; echo 1 && return; }
	done
	echo 0
}

get_uart_mode()
{
	local target_dev i
	local -a pin_array
	local -a cmp_result
	
	if [ x"$1" == x"/dev/ttyM0" ] || [ x"$1" == x"/dev/ttyM1" ]; then
		target_dev="${1##*/dev/ttyM}"
	elif [ x"$1" == x"/dev/ttyMI0" ] || [ x"$1" == x"/dev/ttyMI1" ]; then
		target_dev="${1##*/dev/ttyMI}"
        else
                usage
		exit
        fi	

	gpio_init $target_dev

	# fetch GPIO PIN status
	for ((i=0; i<${#CUR_UART[@]}; i++)); do
		pin_array[$i]=$(cat /sys/class/gpio/gpio${CUR_UART[$i]}/value)
	done
	
	# RS422/485-4W comparison
	cmp_result=$(diff_array pin_array[@] RS422_GPIO_MODE[@])
	if [ x"${cmp_result}" == x"0" ]; then
		echo "UART Port#$target_dev is in RS422/RS485-4W Mode"
		return
	fi
	# RS485-2W comparison
	cmp_result=$(diff_array pin_array[@] RS485_GPIO_MODE[@])
	if [ x"${cmp_result}" == x"0" ]; then
		echo "UART Port#$target_dev is in RS485-2W Mode"
		return
	fi
	# RS232 comparison
	cmp_result=$(diff_array pin_array[@] RS232_GPIO_MODE[@])
	if [ x"${cmp_result}" == x"0" ]; then
		echo "UART Port#$target_dev is in RS232 Mode"
		return
	fi

	echo "Cannot recognize current mode in UART Port#$target_dev"
}

set_uart_mode()
{
	local target_dev i
	
	if [ x"$1" == x"/dev/ttyM0" ] || [ x"$1" == x"/dev/ttyM1" ]; then
		target_dev="${1##*/dev/ttyM}"
	elif [ x"$1" == x"/dev/ttyMI0" ] || [ x"$1" == x"/dev/ttyMI1" ]; then
		target_dev="${1##*/dev/ttyMI}"
        else
                usage
		exit
        fi	
	gpio_init $target_dev

	case "$2" in
		$RS422_MODE) # RS-422 mode
			for ((i=0; i<${#CUR_UART[@]}; i++)); do
				echo ${RS422_GPIO_MODE[$i]} > /sys/class/gpio/gpio${CUR_UART[$i]}/value
			done
			echo "Now setting is RS422/RS485-4W mode"
		;;
		$RS485_MODE) # RS-485 mode
			for ((i=0; i<${#CUR_UART[@]}; i++)); do
				echo ${RS485_GPIO_MODE[$i]} > /sys/class/gpio/gpio${CUR_UART[$i]}/value
			done
			echo "Now setting is RS485-2W mode"
		;;
		$RS232_MODE) # RS-232 mode
			for ((i=0; i<${#CUR_UART[@]}; i++)); do
				echo ${RS232_GPIO_MODE[$i]} > /sys/class/gpio/gpio${CUR_UART[$i]}/value
			done
			echo "Now setting is RS232 mode"
		;;
		*)
			echo "Cannot recognize the mode"
		;;
	esac
}

usage()
{
	echo "Usage: $0 device-node [interface-mode]"
	echo "device-node - /dev/ttyM0 ~ /dev/ttyM1"
	echo "interface-mode :"
	echo "		none - to view now setting"
	echo "		0 - set to RS232 mode"
	echo "		1 - set to RS485-2W mode"
	echo "		2 - set to RS422/RS485-4W mode"
	echo "ex: get UART#1 current mode"
	echo "    => setinterface /dev/ttyM0 "
	echo "ex: set UART#1 to RS232 mode"
	echo "    => setinterface /dev/ttyM0 0"
}

exec_cmd()
{
	case $1 in 
	1)
	if [ x"$2" != x"/dev/ttyM0" ] && [ x"$2" != x"/dev/ttyM1" ] && [ x"$2" != x"/dev/ttyMI0" ] && [ x"$2" != x"/dev/ttyMI1" ]; then
		usage
	else		
		get_uart_mode $2
	fi
	;;
	2)
	if [ x"$2" != x"/dev/ttyM0" ] && [ x"$2" != x"/dev/ttyM1" ] && [ x"$2" != x"/dev/ttyMI0" ] && [ x"$2" != x"/dev/ttyMI1" ]; then
		usage
	elif [ x"$3" != x"0" ] && [ x"$3" != x"1" ] && [ x"$3" != x"2" ]; then
		usage
	else	
		set_uart_mode $2 $3
	fi
	;;
	*)
		usage
	;;
	esac
}

exec_cmd $# $1 $2
