Skip to content

Instantly share code, notes, and snippets.

@steev
Created July 5, 2020 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steev/330336c08d13a779f1ab5805174479ba to your computer and use it in GitHub Desktop.
Save steev/330336c08d13a779f1ab5805174479ba to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
from numpy import *
import subprocess
import time
POSITIVE=True
NEGATIVE=False
HINGE_ALIGNED_WITH_GRAVITY_THRESHOLD = cos(radians(15))
HINGE_AXIS = array((0,1,0), dtype=float)
ROT_HINGE_90 = array((
( 0, 0, 1),
( 0, 1, 0),
( -1, 0, 0)
), dtype=float)
ROT_HINGE_180 = array((
( -1, 0, 0),
( 0, 1, 0),
( 0, 0, -1)
), dtype=float)
class NotReliable(ValueError):
pass
def read_axis_sysfs(location, axis):
return int(open("/sys/bus/iio/devices/iio:device0/in_accel_%s_%s_raw" % (axis, location)).read()) / 1024.0
def read_values():
try:
# lines = subprocess.check_output("sudo ectool motionsense", shell=True).split(b"\n")
base = array([int(value)/1024.0 for value in lines[1].split(b":")[1].split(b"\t")])
lid = array([int(value)/1024.0 for value in lines[2].split(b":")[1].split(b"\t")])
except Exception:
base = array((
read_axis_sysfs("base","x"),
read_axis_sysfs("base","y"),
read_axis_sysfs("base","z")
))
lid = array((
read_axis_sysfs("lid","x"),
read_axis_sysfs("lid","y"),
read_axis_sysfs("lid","z")
))
return base, lid
def cosine_of_angle_diff(v1, v2):
return (v1.dot(v2)) / (linalg.norm(v1) * linalg.norm(v1))
def rotate(v, matrix):
rotated = v.dot(matrix)
rotated /= linalg.norm(rotated) #normalize
return rotated
def lid_angle(base, lid):
lid_to_base = cosine_of_angle_diff(base, lid)
base_to_hinge = cosine_of_angle_diff(base, HINGE_AXIS)
if abs(base_to_hinge) > HINGE_ALIGNED_WITH_GRAVITY_THRESHOLD:
raise NotReliable("Hinge too close to vertical")
base_to_hinge **= 2
denominator = 1 - base_to_hinge
if denominator < 0.01:
raise NotReliable("denominator too small")
ang_lid_to_base = arccos((lid_to_base - base_to_hinge) / denominator)
if isnan(ang_lid_to_base):
raise NotReliable("arccos is nan for some reason")
#since we have 2 solutions for this problem, we have to determine which side the lid is on
v = rotate(base, ROT_HINGE_90)
cos_lid_90 = cosine_of_angle_diff(v, lid)
v = rotate(v, ROT_HINGE_180)
cos_lid_270 = cosine_of_angle_diff(v, lid)
if cos_lid_270 > cos_lid_90:
ang_lid_to_base = -ang_lid_to_base;
if ang_lid_to_base < 0:
ang_lid_to_base += pi*2
return ang_lid_to_base
xrandr_rotation = ""
old_xrandr_rotation = ""
ctm = {
"normal": " 1 0 0 0 1 0 0 0 1",
"left": " 0 -1 1 1 0 0 0 0 1",
"inverted": "-1 0 1 0 -1 1 0 0 1",
"right": " 0 1 0 -1 0 1 0 0 1",
}
while 1:
base, lid = read_values()
try:
angle_spot = "%6.02fdeg" % degrees(lid_angle(base, lid))
except ValueError as e:
angle_spot = repr(e)
max_axis, max_value = max(enumerate(lid), key=lambda axis: abs(axis[1]))
max_axis = "xyz"[max_axis]
screen_direction_str = "%s%s" % (max_axis, "-+"[max_value>0])
try:
if screen_direction_str.startswith("y") or float(angle_spot[:-3]) > 200.0:
subprocess.call("florence show", shell=True) # Show Florence
subprocess.call("xinput disable 8", shell=True) # Disable Touchpad
subprocess.call("xinput disable 6", shell=True) # Disable cros_ec kb
else:
subprocess.call("xinput enable 8", shell=True) # Enable Touchpad
subprocess.call("xinput enable 6", shell=True) # Enable cros_ec kb
subprocess.call("florence hide", shell=True) # Hide Florence
except ValueError:
# probably being opened, so don't die on arcos is nan.
pass
try:
xrandr_rotation = {
("x", NEGATIVE): "normal",
("y", NEGATIVE): "left",
("x", POSITIVE): "inverted",
("y", POSITIVE): "right",
#("z", NEGATIVE): , #up
#("z", POSITIVE): , #down
}[(max_axis,max_value > 0)]
if old_xrandr_rotation != xrandr_rotation:
subprocess.call("xrandr --display :0 --output eDP-0 --rotate %s" % xrandr_rotation, shell=True)
subprocess.call("xinput set-prop 'Elan Touchscreen' 'Coordinate Transformation Matrix' %s" % ctm[xrandr_rotation], shell = True)
old_xrandr_rotation = xrandr_rotation
except KeyError:
#screen probably pointing up or down
pass
print(screen_direction_str, angle_spot, base, lid)
time.sleep(0.20)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment