# Hyper Pixel - Rotate

**URL:** <https://forums.pimoroni.com/t/hyper-pixel-rotate/5276>\
**Category:** Support\
**Created:** [July 11, 2017, 10:01am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276 "2017-07-11T10:01:20Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![MarcJennings](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/marcjennings/32/2142_2.png) [@MarcJennings](https://forums.pimoroni.com/u/MarcJennings)\
**Post date:** [July 11, 2017, 10:01am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/1 "2017-07-11T10:01:20Z")

</div>

Hi,  
Is it possible to configure the hyper pixel to operate in portrait orientation, please? I had a brief play with the config.txt values (rotate and the setup line at the bottom) but it didn’t go at all according to plan - I just ended up with a tiny desktop across the middle 1/3 of the display with lots of artefacting in the remaining display.  
Thanks  
Marc

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 10:35am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/2 "2017-07-11T10:35:02Z")

</div>

You know what, I think I just cracked it.

Try:

```auto
display_rotate=1
framebuffer_width=480
framebuffer_height=800

```

The touchscreen will be totally wonky, though, and wont respond to any config.txt settings :(

---

<div class="post-metadata">

**Author:** ![MarcJennings](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/marcjennings/32/2142_2.png) [@MarcJennings](https://forums.pimoroni.com/u/MarcJennings)\
**Post date:** [July 11, 2017, 10:36am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/3 "2017-07-11T10:36:43Z")

</div>

Thanks @gadgetoid, I just saw those lines at the same time! This always happens to me - post a question and then find the answer in a few minutes anyway!

Now to get an fbi session working to output images to the screen

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 11:01am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/4 "2017-07-11T11:01:19Z")

</div>

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

```auto
#!/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)

```

---

<div class="post-metadata">

**Author:** ![MarcJennings](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/marcjennings/32/2142_2.png) [@MarcJennings](https://forums.pimoroni.com/u/MarcJennings)\
**Post date:** [July 11, 2017, 11:14am UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/5 "2017-07-11T11:14:50Z")

</div>

Great stuff, thanks. I’ll give it a go tonight but for the time being I am just making a static display for my home automation to give me some sensor data, outputting pillow images via FBI

---

<div class="post-metadata">

**Author:** ![MarcJennings](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/marcjennings/32/2142_2.png) [@MarcJennings](https://forums.pimoroni.com/u/MarcJennings)\
**Post date:** [July 11, 2017, 12:43pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/6 "2017-07-11T12:43:33Z")

</div>

OK so it may be a hardware fault, but I’m going to try putting the defaults back. Seems like when the display gets warm the brightness and stability of the image goes to pot. I’ll report back when 1) it’s cooled down a bit, 2) I’ve reset defaults, and 3) tried with my other screen.

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 2:21pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/7 "2017-07-11T14:21:00Z")

</div>

Maybe you can help me with this one too…  
I have my Hyperpixel display mounted in landscape, but in the opposite rotation to the default. Could you point out to me where you changed the file to correctly align the touch values (unless it’s the obvious “`cap = {`…” addition, in which case I haven’t the foggiest.)?  
Dankeschon!

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 2:29pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/8 "2017-07-11T14:29:02Z")

</div>

If you’re rotating 180degrees then you need to mirror the touch input. You can leave basically everything as it is, just change:

> <https://github.com/pimoroni/hyperpixel/blob/master/requirements/usr/bin/hyperpixel-touch#L263>

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

```

The X and Y coordinates are inverted here, which is effectively a 180 degree rotation. So if you un-invert (am I making up words now?) them all it should work!

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 3:19pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/9 "2017-07-11T15:19:36Z")

</div>

I’ve ran out of languages I know how to say thank you in, so here’s something I made up instead:  
Hnkotanyu.

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 3:32pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/10 "2017-07-11T15:32:46Z")

</div>

Apologies for once again requesting your assistance, but it seems flipping them simply ‘mirrors’ the touch screen input to below the screen. I.E: Imaging the screen and then flip a copy of it over the bottom vertice to become the touch input. It’s the right way around (I presume), but just translated a screen width downwards on a 2D plane.

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 3:47pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/11 "2017-07-11T15:47:10Z")

</div>

You can just pass the raw x1 and y1 values in.

If you change `800 - x1` to `x1 - 800` you will, indeed, end up with a range from `-800 to 0`. I should have been clearer, but I wanted you to experiment ;P

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 4:22pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/12 "2017-07-11T16:22:18Z")

</div>

Haha, I appreciate the experimentation, but I didn’t switch them like that. ;)  
I switched both `800` and `450` around within both values; though it’s a little difficult to keep testing since my Hyperpixel is in my garden shed and I’m controlling it via VNC. The rain doesn’t agree with my hair though…  
Gimme a while for the rain to die down and I’ll keep experimenting. :3

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 4:23pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/13 "2017-07-11T16:23:10Z")

</div>

I don’t fancy your chances… you might have to just dig a tunnel to the garden shed! It’s bucketing it down out here.

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 5:09pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/14 "2017-07-11T17:09:16Z")

</div>

OK; I got rather wet in the process, but I’ve managed to document my results!

> 800 - 480 : 800 - 480 - Both X and Y are inverted,  
> 480 - 800 : 800 - 480 - Box X and Y are inverted and the touch screen box is off the bottom left of the screen,  
> 480 - 800 : 480 - 800 - Same as the prior test,  
> 800 - 480 : 480 - 800 - Same as the first test.

o\_0

Either the laws of physics are bending in my shed, or the rain is getting to me…  
I’m going to go with the rain.

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 5:10pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/15 "2017-07-11T17:10:54Z")

</div>

You missed the permutations without subtraction!

Note: Help I’m stuck in a warehouse because I didn’t… wait a minute, I think I packed my rain coat!

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 5:18pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/16 "2017-07-11T17:18:04Z")

</div>

I would help, but I don’t have much warehouse expertise… I just brave it without a coat, but then again, I am only going 5 or so metres. Under trees.  
And I didn’t even recognise that those negatives did anything! I’m so used to typing in plain English with this forum that I though it was just a comment!  
P.S: You know, you’re pretty evil making me go out in this weather to test different variations! The things I do for scientific method…

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 5:34pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/17 "2017-07-11T17:34:55Z")

</div>

They don’t call me Evil Gee for no reason ;)

I’m planning to- at least try - to clean up the hyperpixel-touch binary and add support for rotation 90, 180 and 270 degree rotation.

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 6:08pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/18 "2017-07-11T18:08:24Z")

</div>

You know what my next Google review of Pimoroni will be? "Pimoroni Support Team: Evil swashbuckling geniuses that take pleasure in forcing people out in the cold rain to find solutions."  
Well, I’m still trying! I’ll get it eventually!  
I’ll let you know when I figure it out eventually; it may be a while. :)

---

<div class="post-metadata">

**Author:** ![gadgetoid](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/gadgetoid/32/13_2.png) [@gadgetoid](https://forums.pimoroni.com/u/gadgetoid)\
**Post date:** [July 11, 2017, 6:09pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/19 "2017-07-11T18:09:37Z")

</div>

See this is how we’ll find out that what I think is the answer doesn’t work at all because I’m a fool and haven’t _actually_ checked!

---

<div class="post-metadata">

**Author:** ![RaspberryPicardBox](https://sea2.discourse-cdn.com/flex016/user_avatar/forums.pimoroni.com/raspberrypicardbox/32/7454_2.png) [@RaspberryPicardBox](https://forums.pimoroni.com/u/RaspberryPicardBox)\
**Post date:** [July 11, 2017, 6:18pm UTC](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276/20 "2017-07-11T18:18:37Z")

</div>

Please tell me not… Well! I need to buy an umbrella.

[Next page](https://forums.pimoroni.com/t/hyper-pixel-rotate/5276.md?page=2)
