(OGS) Powersaving through software

Third party OS images and hardware mods
Post Reply
prokrypt
Posts: 1
Joined: Sun Feb 28, 2021 7:02 am
languages_spoken: Englisch
ODROIDs: Odroid Go, Odroid Go Super, Odroid XU4
Has thanked: 3 times
Been thanked: 2 times
Contact:

(OGS) Powersaving through software

Post by prokrypt »

Hi! I'm making a list of software configuration/hacks to save power on the Odroid Go Super (possibly works on Odroid Go Advance too). If anyone has anything to add, please do so!~

Confirmed
  • (obvious) reduce/zero brightness of backlight. This saves a bit of power (or more, depending on your normal preferred brightness levels). Note: due to the type of screen, you will not be able to see anything at all once the backlight is off, unless you shine a super duper bright flashlight on a corner.

    Code: Select all

    echo 0 > /sys/class/backlight/backlight/brightness
  • (not-so-obvious) disable audio (set playback path to OFF). This saves a suprisingly large amount of power. Volume is reset to max when you turn it back on (SPK, HP, SPK_HP), so be sure to save volume levels beforehand to restore!~

    Code: Select all

    amixer sset "Playback Path" OFF
  • (probably not obvious) reduce polling rate of gamepad & analog sticks (normally at "10"). Saves a bit of power.

    Code: Select all

    echo 50 > /sys/devices/platform/odroidgo3-joypad/poll_interval
  • disable all cpu cores except for 1. Saves tiny bit of power

    Code: Select all

    tee /sys/devices/system/cpu/cpu[123]/online <<< 0
  • disable annoying blinking blue led, perhaps turning it into a more useful card read/write activity indicator?

    Code: Select all

    echo mmc0 > /sys/class/leds/blue\:heartbeat/trigger
Unconfirmed or possibly not working right
  • modify journald to keep logs in memory and not write them to disk.
  • suspend mode. Looks like USB does not resume properly and just disappears from the system after resume.
  • cpu governor/frequency control. Haven't experimented with this yet, as it probably makes only a tiny bit of difference.
  • different microsd card. Probably makes a little difference, but too small of a difference to measure, and it's not software-related anyways!
My own changes/hacks:
  • installed triggerhappy (input daemon)
  • disabled power button through /etc/systemd/logind.conf
  • disabled audiopath (or whatever it was called) daemon that controls volume+output selection (headphone/speaker)
  • created hacks and hotkeys through triggerhappy to handle headphone insertion, volume changes...
  • clicking power button toggles backlight (optional: lower brightness instead of turning it off)
  • holding power button for over 1 second initiates shutdown
  • clicking both volume buttons turns off audio for considerable power savings.
  • *unrelated, but still pretty cool/fun* create input controls for console apps, writing a hacky bash script to implement key repeating.
Possible future changes/hacks:
  • backlight toggling/dimming on idle, and restore when activity is detected
  • turn off audio automagically if no audio is playing
  • blink certain patterns on blue led to indicate mute status
Last edited by prokrypt on Sat Mar 06, 2021 2:32 am, edited 3 times in total.
These users thanked the author prokrypt for the post (total 2):
TheRuck (Thu Mar 04, 2021 12:56 pm) • Christian_Haitian (Sun Mar 07, 2021 2:22 am)

macc24
Posts: 30
Joined: Sun Sep 20, 2020 11:31 pm
languages_spoken: english polish
ODROIDs: GoA-BE, GoS
Has thanked: 6 times
Been thanked: 15 times
Contact:

Re: (OGS) Powersaving through software

Post by macc24 »

Disabling GPU or downclocking it and setting powersave governor to cpu would help too
These users thanked the author macc24 for the post:
prokrypt (Fri Mar 05, 2021 2:55 am)

mad_ady
Posts: 9373
Joined: Wed Jul 15, 2015 5:00 pm
languages_spoken: english
ODROIDs: XU4, C1+, C2, C4, N1, N2, H2, Go, Go Advance
Location: Bucharest, Romania
Has thanked: 599 times
Been thanked: 659 times
Contact:

Re: (OGS) Powersaving through software

Post by mad_ady »

*unrelated, but still pretty cool/fun* create input controls for console apps, writing a hacky bash script to implement key repeating.
Check out this project to remap keys: https://github.com/mad-ady/antimicro-nonX
These users thanked the author mad_ady for the post:
prokrypt (Sun Mar 07, 2021 1:45 am)

Christian_Haitian
Posts: 46
Joined: Sat Nov 10, 2018 10:40 pm
languages_spoken: english
ODROIDs: Go, Go Advance
Has thanked: 19 times
Been thanked: 23 times
Contact:

Re: (OGS) Powersaving through software

Post by Christian_Haitian »

If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
These users thanked the author Christian_Haitian for the post:
prokrypt (Sun Mar 07, 2021 1:45 am)
A jack of all trades is a master of none, but oftentimes better than a master of one

macc24
Posts: 30
Joined: Sun Sep 20, 2020 11:31 pm
languages_spoken: english polish
ODROIDs: GoA-BE, GoS
Has thanked: 6 times
Been thanked: 15 times
Contact:

Re: (OGS) Powersaving through software

Post by macc24 »

Christian_Haitian wrote:
Sun Mar 07, 2021 12:52 am
If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
This code would run much better if it was written in C, as synchronous reads, which are easiest to do on event devices are perfect for this usecase

valadaa48
Posts: 288
Joined: Mon Feb 17, 2020 1:35 pm
languages_spoken: english
ODROIDs: odroid go advance
Has thanked: 38 times
Been thanked: 94 times
Contact:

Re: (OGS) Powersaving through software

Post by valadaa48 »

macc24 wrote:
Thu Mar 11, 2021 5:21 am
Christian_Haitian wrote:
Sun Mar 07, 2021 12:52 am
If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
This code would run much better if it was written in C, as synchronous reads, which are easiest to do on event devices are perfect for this usecase
Ha, I wrote oga_events really quickly to get something going. I didn't think it would end up in so many spots, at least the name didn't get mangled =)

I think I will actually open source ogage as there's little sense in keeping it private, clones be damned!

It's written in rust and uses epoll. I don't know rust very well but in principle it's pretty low-pro and is prob how I would have implemented it in C. It uses ~0% cpu and I think like 2-4MB of mem.

Give me a bit to clean it up and I'll post it.

EDIT: here you go https://github.com/valadaa48/ogage good luck and don't make fun of my rust code please
These users thanked the author valadaa48 for the post (total 3):
odroid (Thu Mar 11, 2021 9:44 am) • shanti (Thu Mar 11, 2021 10:49 am) • Christian_Haitian (Thu Mar 11, 2021 8:02 pm)

Christian_Haitian
Posts: 46
Joined: Sat Nov 10, 2018 10:40 pm
languages_spoken: english
ODROIDs: Go, Go Advance
Has thanked: 19 times
Been thanked: 23 times
Contact:

Re: (OGS) Powersaving through software

Post by Christian_Haitian »

valadaa48 wrote:
Thu Mar 11, 2021 9:24 am
macc24 wrote:
Thu Mar 11, 2021 5:21 am
Christian_Haitian wrote:
Sun Mar 07, 2021 12:52 am
If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
This code would run much better if it was written in C, as synchronous reads, which are easiest to do on event devices are perfect for this usecase
Ha, I wrote oga_events really quickly to get something going. I didn't think it would end up in so many spots, at least the name didn't get mangled =)

I think I will actually open source ogage as there's little sense in keeping it private, clones be damned!

It's written in rust and uses epoll. I don't know rust very well but in principle it's pretty low-pro and is prob how I would have implemented it in C. It uses ~0% cpu and I think like 2-4MB of mem.

Give me a bit to clean it up and I'll post it.

EDIT: here you go https://github.com/valadaa48/ogage good luck and don't make fun of my rust code please
Thanks alot Val. Took me a little research to understand rust. You’re using a command named light in this program to control brightness but it doesn’t seem to exist in Ubuntu. Is it a program you create or a program that exist in Void?
A jack of all trades is a master of none, but oftentimes better than a master of one

valadaa48
Posts: 288
Joined: Mon Feb 17, 2020 1:35 pm
languages_spoken: english
ODROIDs: odroid go advance
Has thanked: 38 times
Been thanked: 94 times
Contact:

Re: (OGS) Powersaving through software

Post by valadaa48 »

Christian_Haitian wrote:
Fri Mar 12, 2021 12:59 pm
valadaa48 wrote:
Thu Mar 11, 2021 9:24 am
macc24 wrote:
Thu Mar 11, 2021 5:21 am
Christian_Haitian wrote:
Sun Mar 07, 2021 12:52 am
If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
This code would run much better if it was written in C, as synchronous reads, which are easiest to do on event devices are perfect for this usecase
Ha, I wrote oga_events really quickly to get something going. I didn't think it would end up in so many spots, at least the name didn't get mangled =)

I think I will actually open source ogage as there's little sense in keeping it private, clones be damned!

It's written in rust and uses epoll. I don't know rust very well but in principle it's pretty low-pro and is prob how I would have implemented it in C. It uses ~0% cpu and I think like 2-4MB of mem.

Give me a bit to clean it up and I'll post it.

EDIT: here you go https://github.com/valadaa48/ogage good luck and don't make fun of my rust code please
Thanks alot Val. Took me a little research to understand rust. You’re using a command named light in this program to control brightness but it doesn’t seem to exist in Ubuntu. Is it a program you create or a program that exist in Void?
I think light is a great app for controlling brightness and I use it on all of my systems including desktop and laptop. If you have trouble getting it compiled/added to Ubuntu you can always replace the commands with something else or even just read/write to the respective sys files.
These users thanked the author valadaa48 for the post:
Christian_Haitian (Sun Mar 14, 2021 1:39 pm)

macc24
Posts: 30
Joined: Sun Sep 20, 2020 11:31 pm
languages_spoken: english polish
ODROIDs: GoA-BE, GoS
Has thanked: 6 times
Been thanked: 15 times
Contact:

Re: (OGS) Powersaving through software

Post by macc24 »

valadaa48 wrote:
Thu Mar 11, 2021 9:24 am
Ha, I wrote oga_events really quickly to get something going. I didn't think it would end up in so many spots, at least the name didn't get mangled =)
I think I will actually open source ogage as there's little sense in keeping it private, clones be damned!
It's written in rust and uses epoll. I don't know rust very well but in principle it's pretty low-pro and is prob how I would have implemented it in C. It uses ~0% cpu and I think like 2-4MB of mem.
Give me a bit to clean it up and I'll post it.
EDIT: here you go https://github.com/valadaa48/ogage good luck and don't make fun of my rust code please
I wrote a quick and dirty program to convert from gamepad events to keyboard and mouse.
It uses almost no resources and is missing analog input support but it kinda works
https://github.com/Maccraft123/joy2key/ ... /joy2key.c

The best thing is that I use sway to handle hotkeys xDD

Christian_Haitian
Posts: 46
Joined: Sat Nov 10, 2018 10:40 pm
languages_spoken: english
ODROIDs: Go, Go Advance
Has thanked: 19 times
Been thanked: 23 times
Contact:

Re: (OGS) Powersaving through software

Post by Christian_Haitian »

valadaa48 wrote:
Fri Mar 12, 2021 11:26 pm
Christian_Haitian wrote:
Fri Mar 12, 2021 12:59 pm
valadaa48 wrote:
Thu Mar 11, 2021 9:24 am
macc24 wrote:
Thu Mar 11, 2021 5:21 am
Christian_Haitian wrote:
Sun Mar 07, 2021 12:52 am
If anyone is using the oga_events.py hotkey daemon created by valadaa48, you can greatly reduce cpu usage of it by adding a small sleep of 0.001 to it. It reduced cpu usage from almost as high as 91 percent down to at most 28 percent since it would constantly read gamepad inputs. It doesn’t seem to impact the responsiveness of the script very much either. See the code below.

Code: Select all

#!/usr/bin/env python3

import evdev
import asyncio
import time
from subprocess import check_output

pwrkey = evdev.InputDevice("/dev/input/event0")
odroidgo2_joypad = evdev.InputDevice("/dev/input/event2")
sound = evdev.InputDevice("/dev/input/event2")

brightness_path = "/sys/devices/platform/backlight/backlight/backlight/brightness"
max_brightness = int(open("/sys/devices/platform/backlight/backlight/backlight/max_brightness", "r").read())

class Power:
    pwr = 116

class Joypad:
    l1 = 310
    r1 = 311

    up = 544
    down = 545
    left = 546
    right = 547

    f1 = 704
    f2 = 705
    f3 = 709


def runcmd(cmd, *args, **kw):
    print(f">>> {cmd}")
    check_output(cmd, *args, **kw)

def brightness(direction):
    with open(brightness_path, "r+") as f:
        cur = int(f.read())
        adj = max(1, int(cur * 0.13))
        cur = max(0, min(cur + adj * direction, max_brightness))
        f.seek(0, 0)
        f.write(f"{cur}")

async def handle_event(device):
    async for event in device.async_read_loop():
        if device.name == "rk8xx_pwrkey":
            keys = odroidgo2_joypad.active_keys()
            if event.value == 1 and event.code == Power.pwr: # pwr
                if Joypad.f3 in keys:
                    runcmd("/bin/systemctl poweroff || true", shell=True)
                else:
                    runcmd("/bin/systemctl suspend || true", shell=True)

        elif device.name == "GO-Advance Gamepad" or device.name == "GO-Super Gamepad":
            keys = odroidgo2_joypad.active_keys()
            #print(keys)
            if event.value == 1 and Joypad.f3 in keys:
                if event.code == Joypad.left:
                    runcmd("/usr/bin/amixer -q sset Playback 1%-", shell=True)
                elif event.code == Joypad.right:
                    runcmd("/usr/bin/amixer -q sset Playback 1%+", shell=True)
                elif event.code == Joypad.up:
                    brightness(1)
                elif event.code == Joypad.down:
                    brightness(-1)
                elif event.code == Joypad.l1:
                    runcmd("/usr/local/bin/perfnorm", shell=True)
                elif event.code == Joypad.r1:
                    runcmd("/usr/local/bin/perfmax", shell=True)

        time.sleep(0.001)

def run():
    asyncio.ensure_future(handle_event(pwrkey))
    asyncio.ensure_future(handle_event(odroidgo2_joypad))
    asyncio.ensure_future(handle_event(sound))

    loop = asyncio.get_event_loop()
    loop.run_forever()

if __name__ == "__main__": # admire
    run()
This code would run much better if it was written in C, as synchronous reads, which are easiest to do on event devices are perfect for this usecase
Ha, I wrote oga_events really quickly to get something going. I didn't think it would end up in so many spots, at least the name didn't get mangled =)

I think I will actually open source ogage as there's little sense in keeping it private, clones be damned!

It's written in rust and uses epoll. I don't know rust very well but in principle it's pretty low-pro and is prob how I would have implemented it in C. It uses ~0% cpu and I think like 2-4MB of mem.

Give me a bit to clean it up and I'll post it.

EDIT: here you go https://github.com/valadaa48/ogage good luck and don't make fun of my rust code please
Thanks alot Val. Took me a little research to understand rust. You’re using a command named light in this program to control brightness but it doesn’t seem to exist in Ubuntu. Is it a program you create or a program that exist in Void?
I think light is a great app for controlling brightness and I use it on all of my systems including desktop and laptop. If you have trouble getting it compiled/added to Ubuntu you can always replace the commands with something else or even just read/write to the respective sys files.
So for Ubuntu, I ended up finding a similar app named brightnessctl that functions similarly. It works well with slight modification for ogage. Thanks again for open sourcing that. It's extremely light on resources and the learning curve for rust isn't too bad.
These users thanked the author Christian_Haitian for the post:
valadaa48 (Sun Mar 14, 2021 1:56 pm)
A jack of all trades is a master of none, but oftentimes better than a master of one

Post Reply

Return to “Projects”

Who is online

Users browsing this forum: No registered users and 3 guests