Hyper Pixel - Rotate

If you want touch to work properly in this orientation, this is the modified /usr/bin/hyperpixel-touch that works for me:

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
import sys
import smbus
import signal

from evdev import uinput, UInput, AbsInfo, ecodes as e
import time

cap = {
        #e.EV_REL : [e.REL_WHEEL],
        e.EV_ABS : (
                (e.ABS_X, AbsInfo(value=0, min=0, max=480, fuzz=0, flat=0, resolution=1)),
                (e.ABS_Y, AbsInfo(value=0, min=0, max=800, fuzz=0, flat=0, resolution=1)),
                (e.ABS_MT_SLOT, AbsInfo(value=0, min=0, max=1, fuzz=0, flat=0, resolution=0)),
                (e.ABS_MT_TRACKING_ID, AbsInfo(value=0, min=0, max=65535, fuzz=0, flat=0, resolution=0)),
                (e.ABS_MT_TOUCH_MAJOR, AbsInfo(value=0, min=0, max=30, fuzz=0, flat=0, resolution=0)),
                (e.ABS_MT_PRESSURE, AbsInfo(value=0, min=0, max=255, fuzz=0, flat=0, resolution=0)),
                (e.ABS_MT_POSITION_X, AbsInfo(value=0, min=0, max=480, fuzz=0, flat=0, resolution=0)),
                (e.ABS_MT_POSITION_Y, AbsInfo(value=0, min=0, max=800, fuzz=0, flat=0, resolution=0)),
        ),
        e.EV_KEY : [
                #e.BTN_LEFT, e.BTN_RIGHT,
                e.BTN_TOUCH,
        ]
}

ui = UInput(cap, name="Touchscreen")

last_status_one = last_status_two = False
last_status_x1 = last_status_y1 = last_status_x2 = last_status_y2 = 0

def write_status(x1, y1, touch_one, x2, y2, touch_two):
    global last_status_one, last_status_two, last_status_x1, last_status_y1, last_status_x2, last_status_y2


    if touch_one:
        ui.write(e.EV_ABS, e.ABS_MT_SLOT, 0)

        if not last_status_one: # Contact one press
            #print("Report: Touch 1 Start")
            ui.write(e.EV_ABS, e.ABS_MT_TRACKING_ID, 0)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_X, x1)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_Y, y1)
            ui.write(e.EV_KEY, e.BTN_TOUCH, 1)
            ui.write(e.EV_ABS, e.ABS_X, x1)
            ui.write(e.EV_ABS, e.ABS_Y, y1)

        elif not last_status_one or (x1, y1) != (last_status_x1, last_status_y1):
            if x1 != last_status_x1: ui.write(e.EV_ABS, e.ABS_X, x1)
            if y1 != last_status_y1: ui.write(e.EV_ABS, e.ABS_Y, y1)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_X, x1)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_Y, y1)

        last_status_x1 = x1
        last_status_y1 = y1

        last_status_one = True

        ui.write(e.EV_SYN, e.SYN_REPORT, 0)
        ui.syn()

    elif not touch_one and last_status_one: # Contact one release
        #print("Report: Touch 1 End")
        ui.write(e.EV_ABS, e.ABS_MT_SLOT, 0)
        ui.write(e.EV_ABS, e.ABS_MT_TRACKING_ID, -1)
        ui.write(e.EV_KEY, e.BTN_TOUCH, 0)
        last_status_one = False

        ui.write(e.EV_SYN, e.SYN_REPORT, 0)
        ui.syn()


    if touch_two:
        ui.write(e.EV_ABS, e.ABS_MT_SLOT, 1)

        if not last_status_two: # Contact one press
            #print("Report: Touch 2 Start")
            ui.write(e.EV_ABS, e.ABS_MT_TRACKING_ID, 1)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_X, x2)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_Y, y2)
            ui.write(e.EV_KEY, e.BTN_TOUCH, 1)
            ui.write(e.EV_ABS, e.ABS_X, x2)
            ui.write(e.EV_ABS, e.ABS_Y, y2)

        elif not last_status_two or (x2, y2) != (last_status_x2, last_status_y2):
            if x2 != last_status_x2: ui.write(e.EV_ABS, e.ABS_X, x2)
            if y2 != last_status_y2: ui.write(e.EV_ABS, e.ABS_Y, y2)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_X, x2)
            ui.write(e.EV_ABS, e.ABS_MT_POSITION_Y, y2)

        last_status_x2 = x2
        last_status_y2 = y2

        last_status_two = True

        ui.write(e.EV_SYN, e.SYN_REPORT, 0)
        ui.syn()

    elif not touch_two and last_status_two: # Contact one release
        #print("Report: Touch 2 End")
        ui.write(e.EV_ABS, e.ABS_MT_SLOT, 1)
        ui.write(e.EV_ABS, e.ABS_MT_TRACKING_ID, -1)
        ui.write(e.EV_KEY, e.BTN_TOUCH, 0)
        last_status_two = False

        ui.write(e.EV_SYN, e.SYN_REPORT, 0)
        ui.syn()

INT = 27 # Shared with LCD_SPI_CLK, interrupt is unreadable when the panel configuration is being sent.

ADDR = 0x5c

DELAY = 0.00001

GPIO.setmode(GPIO.BCM)
bus = smbus.SMBus(3)

def setupPins():
    GPIO.setup(INT, GPIO.IN)

ioerr_count = 0

def read_byte(address, delay=0):
    return bus.read_byte_data(0x5c,address)

def is_touch_on(x,y):
    # Pick the nearest touch lines to the coordinates
    x_line = int(x/57.2)
    y_line = int(y/60.01)

    assert ( 0 <= x_line <= 13)
    assert ( 0 <= y_line <= 7)

    # Read ADC values for those lines
    x_adc = bus.read_word_data(ADDR, x_line*2+16)
    y_adc = bus.read_word_data(ADDR, y_line*2)

    if x_adc > 100 or y_adc > 100:
        return True
    else:
        return False


touch_one_start = None
touch_two_start = None
touch_one_end = 0
touch_two_end = 0
last_x1 = last_y1 = -1
last_x2 = last_y2 = -1

def touch_finished(x1,y1,x2,y2):
    global touch_one_start, touch_two_start, touch_one_end, touch_two_end

    touch_one_dur = 0
    touch_two_dur = 0

    if touch_one_start and (x1,y1) == (0,0):
        touch_one_dur = time.time()-touch_one_start

        touch_one_end = time.time()
        touch_one_start = None

    if touch_two_start and (x2,y2) == (0,0):
        touch_two_dur = time.time()-touch_two_start

        touch_two_end = time.time()
        touch_two_start = None

def smbus_read_touch():
    global ioerr_count, touch_one_start, touch_two_start
    global last_x1, last_y1, last_x2, last_y2

    try:
        starttime = time.time()

        data = bus.read_i2c_block_data(ADDR, 0x40, 8)

        x1 = data[0] | (data[4] << 8)
        y1 = data[1] | (data[5] << 8)
        x2 = data[2] | (data[6] << 8)
        y2 = data[3] | (data[7] << 8)

        endtime = time.time()

        if x2 and y2:

            if ( touch_two_start and (x2, y2) != (last_x2, last_y2) ) or is_touch_on(x2, y2):
                if not touch_two_start:
                    touch_two_start = time.time()

            else:
                if touch_two_start:
                    touch_finished(x1,y1,x2,y2)

            last_x2 = x2
            last_y2 = y2


        if x1 and y1:

            if ( touch_one_start and (x1, y1) != (last_x1, last_y1) ) or is_touch_on(x1, y1):
                if not touch_one_start:
                    touch_one_start = time.time()
            else:
                if touch_one_start:
                    touch_finished(x1,y1,x2,y2)

            last_x1 = x1
            last_y1 = y1


        if (x2==0 and y2==0 and touch_two_start) or (x1==0 and y1==0 and touch_one_start):
            touch_finished(x1,y1,x2,y2)

        write_status(y1, 800-x1, touch_one_start is not None, y2, 800-x2, touch_two_start is not None)


    except e:
        print("Probably IOerror {}".format(e))
        ioerr_count += 1

def smbus_config_touch():
    global bus
    bus.write_byte_data(0x5c,0x6e,0b00001110)

if __name__ == "__main__":
    setupPins()

    smbus_config_touch()

    while True:
        if GPIO.input(INT) or touch_one_start or touch_two_start:
            smbus_read_touch()

        time.sleep(0.003)
1 Like