#!/bin/sh
# @Author: lance
# @Copyright:	www.shuyz.com
# @Date:   2015-11-07 14:48:31
# @Last Modified by:   lance
# @Last Modified time: 2015-11-07 21:04:21


# Configure a high PWM freq at which there is no flicker
# Calculate the freq here: http://devbraindom.blogspot.com/2013/03/eliminate-led-screen-flicker-with-intel.html
# In the example below the freq is set to 1500Hz
PWM_REG=0xc8254					# address of the reg to configure freq
PWM_DFT='freq 852' 				# the default freq pattern from read command
PWM_DFT_VAL=0x035400b4			# the default reg value of freq
PWM_VAL=0x7d007d				# reg value to provide the freq
XB_VAL_FILE=/var/lib/xbacklight # file to remember last backlight value

XBMAX=80	# max brightness
XBMIN=1 	# min brightness, do not set it to 0 if you are not sure about the result
XINT=5		# initical brightness, DO NEVER SET THIS TO 0!
XSTEP=2		# step
XBRIGHTNESS=/sys/class/backlight/intel_backlight/brightness

INTEL_REG=/usr/bin/intel_reg
BC=/usr/bin/bc
AWK=/usr/bin/awk
SUDO=/usr/bin/sudo

# The backlight may be set to max on startup after change freq
# we use systemd-backlight to do the trick
SYSTEM_BACKLIGHT=/usr/lib/systemd/systemd-backlight
XBNAME=backlight:intel_backlight

# This function has return value, do not add other echos
init_freq()
{
    cvstr=$($SUDO $INTEL_REG read $PWM_REG)

    if [[ $cvstr == *$PWM_DFT* ]]; then
        $SUDO $INTEL_REG write $PWM_REG $PWM_VAL
        echo 1
    else
        echo 0
    fi
}

reset_freq()
{
	echo 'reset freq to default' $PWM_DFT_VAL
    $SUDO $INTEL_REG write $PWM_REG $PWM_DFT_VAL
}

get_freq()
{
	cvstr=$($SUDO $INTEL_REG read $PWM_REG)
	echo 'current backlight PWM freq is ' $cvstr
}

set_xbacklight()
{
	xbval=$1
	echo 'attempt to set backlight to ' $xbval

	# make sure it's digits
	if ! [[ $xbval =~ ^[0-9.]+$ ]] ; then
		xbval=$XBMIN
	fi

	# remove the dots
	xbval=$(printf "%.0f\n" $xbval)

	if [ $xbval -gt $XBMAX ]; then
		xbval=$XBMAX
	fi

	if [ $xbval -lt $XBMIN ]; then
		xbval=$XBMIN
    fi

    init_freq

	echo 'backlight value is set to ' $xbval
    $SUDO tee $XBRIGHTNESS <<< $xbval
	$SUDO sh -c "echo $xbval > $XB_VAL_FILE; chmod 777 $XB_VAL_FILE" # This script will be called by both root and normal users
}

init_xbacklight()
{
	intval=$XINT

	if [ -f $XB_VAL_FILE ]; then
		intval=$(cat $XB_VAL_FILE)
    fi

	chg=$(init_freq)

	# only init if freq changes
	if ! [[ $chg -eq 0 ]]; then
		echo 'freq changed, restore backlight.'

        # fix max backlight when change freq
        # use systemd-backlight to set it to min then restore our value
        if [ -f $SYSTEM_BACKLIGHT ]; then
			# set to a small value fo systemd-backlight will remember it
            set_xbacklight $XINT
            
            $SUDO $SYSTEM_BACKLIGHT save $XBNAME
        	$SUDO $SYSTEM_BACKLIGHT load $XBNAME
		fi
        
        set_xbacklight $intval
	else
        if ! [[ $# -eq 0 ]]; then
            echo 'set brightness to write init value.'
            set_xbacklight $XINT
        else
            # auto fix max brightness
            cval=$(cat $XBRIGHTNESS)
            if [[ $cval -gt $XBMAX ]]; then
                echo 'current brightness value too high, reset'
                set_xbacklight $intval
            else
                echo 'nothing changed.' 
            fi
        fi
	fi
}

get_backlight()
{
	cval=$(cat $XBRIGHTNESS)
	echo 'current backlight value is ' $cval

	get_freq	
}

inc_xbacklight()
{
	cval=$(cat $XBRIGHTNESS)
	cval=$(echo $cval '+' $XSTEP '+0.1' | $BC)

	echo 'trying to increase backlight to ' $cval
	set_xbacklight $cval
}

dec_xbacklight()
{
	cval=$(cat $XBRIGHTNESS)
	cval=$(echo $cval'-' $XSTEP '+0.1'| $BC)

	echo 'trying to decrease backlight to ' $cval
	set_xbacklight $cval
}

check_cmds()
{
	if [ ! -f $BC ]; then
		echo 'command bc is not found!'
		exit 1
	fi

	if [ ! -f $AWK ]; then
		echo 'command awk is not found!'
		exit 1
	fi

	if [ ! -f $INTEL_REG ]; then
		echo 'command intel_reg is not found!'
		exit 1
    fi

	if [ ! -f $SUDO ]; then
		echo 'command sudo is not found!'
		exit 1
    fi

	if [ ! -f $XBRIGHTNESS ]; then
        echo 'brightness interface is not found!'
		exit 1
    fi
}

check_cmds

if [ $# -eq 0 ]; then 
	echo 'no parameters are specified, init backlight as default.'
    init_xbacklight
    exit 0
fi

if [[ $1 = "init" ]]; then
	init_xbacklight
elif [[ $1 = 'reset' ]]; then
    reset_freq
elif [[ $1 = 'freq' ]]; then
	get_freq
elif [[ $1 = 'inc' ]]; then
	inc_xbacklight
elif [[ $1 = 'dec' ]]; then
	dec_xbacklight
elif [[ $1 = 'min' ]]; then
	set_xbacklight $XBMIN
elif [[ $1 = 'max' ]]; then
	set_xbacklight $XBMAX
elif [[ $1 = 'set' ]]; then
	set_xbacklight $2
elif [[ $1 = 'fix' ]]; then
    init_xbacklight force
elif [[ $1 = 'get' ]]; then
    get_backlight
else
	echo 'script help:'
	echo 'init      init PWM freq and restore backlight'
	echo 'reset     reset backlight to default value'
	echo 'freq      read the value PWM freq reg'
	echo 'inc       increase backlight'
	echo 'dec       decrease backlight'
	echo 'min       set min backlight'
	echo 'max       set max backlight'
	echo 'set [val] specify the backlight value'
    echo 'fix       fix the brightness if set to 0(bind to shortcut)'
	echo 'get       read current backlight value'
fi


