How to rotate X41t screen with gravity sensor(hdaps)

From ThinkWiki
Jump to: navigation, search

X41 Tablet

The X41t has a acceleration sensor build in. Originally it can protect the hard drive, if Laptop is falling down. See the HDAPS Page. Now lets use that for funny stuff like emulate a joystick for Neverball [1]. Or we use it for a very useful thing: Rotating the screen by recognizing where is downward. Like a lot of handy tools, like mobiles, mp3 player or photo cameras.

Basic concept is the following: 
-Rotate the screen and the stylus to the steepest decent direction.
-Rotate only in stylus mode.
-Rotate only if it is really necessary.
-Rotate only if it cants more than 10 degrees.
-An easy program.

There are other programs witch can do that, but I have not found one that works out off the box. And I can not understand that much python. So I tried it out myself. I have written a set of small shell scripts that rotates the screen of the X41 Tablet by using the gravity sensor coordinates and some ACPI events. It consist of two parts, fist the main part that contains the code for deciding and rotating and the second part which starts and stops the fist one. Maybe some one can make suggestions to get this in a real deamon style.

I have tested it on an x41t with ubuntu 8.04 with the standard kernel 2.6.24-19-generic.

sudo apt-get install x11-xserver-utils wacom-tools should install all stuff.

First Part. Usually this is saved as /etc/acpi/x41t_gravity

#!/bin/bash 
 
#usage: just start or kill it

#load configuration
. /etc/gravity/gravity.conf

get_orientation(){
    string=`cat /sys/devices/platform/hdaps/position`
    string=`echo $string | tr -d '[=-=][:blank:][=(=][=)=]'`
    x=`echo $string | awk -v FS="," '{print $1}'`
    y=`echo $string | awk -v FS="," '{print $2}'`
    dx=`expr $x - $x_horizontal`		#dx away from middle
    dy=`expr $y - $y_horizontal`		#dy away form the middle
    
     #get actual orientation from last rotation, saved in a file :
    if [ ! -f /tmp/actual_orientation.txt ];then
    	echo 0 > /tmp/actual_orientation.txt		#0 means normal orientation
    fi
    actual_orientation=`cat /tmp/actual_orientation.txt`
}

prepare_rotate(){
            echo "Nothing to prepare. I can rotate now."
	    #ps -A | grep compiz.real && (kwin --replace)&	#because compiz sometimes crashes. 
 }

do_rotate(){
	    prepare_rotate
	    #rotate screen
	    xrandr -o $1
	    #rotate stylus
 	    case $1 in
    		right)
    		    /usr/bin/xsetwacom set stylus rotate 1;;
		left)
		    /usr/bin/xsetwacom set stylus rotate 2;;
		inverted)	
		    /usr/bin/xsetwacom set stylus rotate 3;;
    		*)
		    /usr/bin/xsetwacom set stylus rotate 0;;
	    esac
	    #save the orientation			
	    echo $1 > /tmp/actual_orientation.txt
}

######### Main ########################

while [ true ]; do
    get_orientation    
     if [ `expr $dx \* $dx` -ge `expr $dy \* $dy` ];then #checks for the absolute greater value 
 	if [ $dx -gt $eps ] && [ ! $actual_orientation = right ] ;then #check if the screen have to rotate
	    do_rotate right
	elif [ $dx -lt -$eps ] && [ ! $actual_orientation = left ];then #check if the screen have to rotate
	    do_rotate left
	fi
    else
	if [ $dy -gt $eps ] && [ ! $actual_orientation = normal ];then #check if the screen have to rotate
	    do_rotate normal
	elif [ $dy -lt -$eps ] && [ ! $actual_orientation = inverted ];then #check if the screen have to rotate
	    do_rotate inverted
	fi
    fi
    sleep 1
done

exit 0


Second Part. Usually this is saved as /etc/acpi/x41t_control_gravity.sh

#!/bin/bash 

#load configuration
. /etc/gravity/gravity.conf

################ set DISPLAY ####################
#export DISPLAY=$Default_DISPLAY		#a work around for right DISPLAY varialbe (I do not like it).
#export XAUTHORITY=$Default_XAUTHORITY         #THIS GIVED ME AN ERROR SO I COMMENTED IT: wbonx
#xset -display $DISPLAY dpms
################# Main ##########################

if [ ! $1 ] || [ ! $1 = start ];then
    killall x41t_gravity		#return to normal state
    xrandr -o normal 
    /usr/bin/xsetwacom set stylus rotate 0
    rm /tmp/actual_orientation.txt
elif [ $1 = start ];then
    #check for the kernel modul for gyroscope
    lsmod | grep hdaps || modprobe hdaps
    lsmod | grep hdaps || exit 1
    (/etc/acpi/x41t_gravity)&		#will be endless repeated (kill see up)
fi

exit 0

Some settings that have to tune. Usually this is saved as /etc/gravity/gravity.conf

x_horizontal=433	#horizontal position, get it by calibration
y_horizontal=390	#just read the value in /sys/devices/platform/hdaps/position
			#the first value is x, second one is y

eps=40			#define a neighbourhood interpreted as horizontal

Default_DISPLAY=":0.0"
Default_XAUTHORITY=/home/smjb0803/.Xauthority


Now lets begin! Just add two ACPI events, first to start the x41t_gravity, second for ending it.

Fist. Usually this is saved as /etc/acpi/events/x41t-swivel-down.

# /etc/acpi/events/x41t-swivel-down
# called when tablet head swivels down
event=ibm/hotkey HKEY 00000080 00005009
action=/etc/acpi/x41t_control_gravity.sh start

Second. Usually this is saved as /etc/acpi/events/x41t-swivel-up.

# /etc/acpi/events/x41t-swivel-up
# called when tablet head swivels up
event=ibm/hotkey HKEY 00000080 0000500a
action=/etc/acpi/x41t_control_gravity.sh stop

And restart the ACPID.

 sudo /etc/init.d/acpid restart

That`s it. Have fun and make suggestions. Please use it only if you trust in it. On personal risk. You have to prevent losing data. --Jonasbergel 09:27, 16 October 2008 (CEST)