Syncthing + AspeQt-1.0.62.

Z najnowszej wersji AspeQt-1.0.62 (dostępna w Google Play i na Github) jestem wyjątkowo dumny pomimo, że nie ma w niej żadnych rewolucyjnych zmian:

  • Przebudowane z Qt-5.9.7 (min. API 16 = Android 4.1).
  • Poprawione błędy sterownika ftdi – działa z HSINDEX 0 = 115200bps.
  • Sprawdzanie dostępu do karty SD na Mashmallow i nowszych wersjach Androida

Jednak ta druga pozycja… to chyba najbardziej dołujący jak dotąd błąd z jakim przyszło mi się zmierzyć. Ale o co chodzi? Na nie-rootowanym Androidzie jedyna sensowna opcja obsługi portu szeregowego, a taki jest potrzebny do emulacji urządzeń SIO w 8-bitowym Atari, to tzw. usb-host mode i próba dogadania się z najpopularniejszym i najbardziej sensownym układem pozwalającym na taką komunikację, czyli FT232R firmy FTDI. Firma wypuściła w tym celu bibliotekę d2xx dla Androida, jednak nie jest ona zbyt szybka, a dodatkowo, licencja jest co najmniej problematyczna. Dawno temu odkryłem więc usb-serial-for-android. Dostęp do obiektów Javy w Qt5 i vice versa opisywałem już wcześniej – wystarczy wspomnieć, że bez JNI nie da rady tego ogarnąć, ale co zaskakujące, działa to bardzo szybko i wydajnie. Pod warunkiem, że działa ;). No i tu zaczyna się demotywująca część historii. Na niektórych urządzeniach AspeQt śmigał aż miło, ale użytkownicy zaczęli zgłaszać, że pomimo prawidłowej obsługi usb-host, na niektórych całkiem porządnych urządzeniach z Androidem nie działa. Niestety usb-serial-for-android od dwóch lat praktycznie rozwija tylko jedna osoba – Kai Morich w swoim forku – i to dzięki niemu udało się problem rozwiązać.

A teraz o moim ostatnim odkryciu: syncthing. AspeQt z HSINDEX 0 śmiga całkiem szybko, więc podmontowałem w nim na androidowym TVBoxie katalog, który przez syncthing jest synchronizowany po Wifi z laptopem i telefonem. Dzięki temu wszystko co ściągnę z internetów mogę od razu, bez skomplikowanych operacji, uruchomić na moim 8-bitowym super sprzęcie ;). Syncthing jest świetny, darmowy i bez reklam. W archowych repozytoriach są gotowe paczki dla Linuksa, a w Google Play apk dla Androida. Długo czegoś takiego szukałem:

Godot 3.1a1.

Jedno, no dobra – dwa słowa – niesamowity projekt. Nie byłem nigdy chętny do zabawy silnikami growymi, ale Godot jest wyjątkowy. W zasadzie wszystko mnie w nim zachwyca – począwszy od formy dystrybuowania – jeden plik wykonywalny, przez możliwości i ogólnie sposób pracy z programem. No i jeszcze możliwości. I zapomniałem dodać jeden ficzer: możliwości.

Język skryptowy GDScript, dla Pythonisty – miodzio. Oprócz tego pełna swoboda, może być C#, GDNative i C++, jest i edytor wizualny. Szok. Wersja alpha (niestety wersja stabilna działa tylko na sprzęcie z OpenGL ES 3.0, ale w 3.1 będzie tylko GL ES 2.0) ani razu mi się nie wysypała, nawet jednego komunikatu o błędzie!

Powyższy screen to tutorial „Tiles and Animated Sprites” HartBeast-a (super się go słucha).

Obsługa ruchu i animacji sprajta to 27 linijek w GDScript.

extends KinematicBody2D

var motion = Vector2()
const UP = Vector2(0, -1)
const GRAVITY = 20
const SPEED = 200
const JUMP_HEIGHT = -550

func _physics_process(delta):
	motion.y += GRAVITY
	if Input.is_action_pressed("ui_right"):
		motion.x = SPEED
		$Sprite.flip_h = false
		$Sprite.play("Run")
	elif Input.is_action_pressed("ui_left"):
		$Sprite.flip_h = true
		$Sprite.play("Run")
		motion.x = -SPEED
	else:
		motion.x = 0
		$Sprite.set_animation("Idle")

	if is_on_floor():
		if Input.is_action_just_pressed("ui_up"):
			motion.y = JUMP_HEIGHT

	motion = move_and_slide(motion, UP)

 

ESP32 i klon Dual shock przez BT.

Przez nieuwagę kupiłem Pada BigBen RFLX BB5152 (PS3) myśląc, że podłączę go do interfejsu TOM2 (liczyłem na to, że będzie działał lepiej od Logitecha F710). Niestety w obecnie dostępnej wersji ten pad jest tylko na bluetooth, więc nie będzie działał wcale.

A gdyby tak przez bluetooth z ESP32 podłączyć pada z PS3 do Atari? 🙂

https://github.com/greblus/esp32_ps3_bt_pad

Może się uda. W projekcie Usb Host Shield dla Arduino autor obsługuje nawet czujniki ruchu, więc jest się od kogo uczyć.

f() – swoboda argumentów.

Na początku nie wiedziałem co o tym myśleć, ale po namyśle – fajowy ten JS 😉 mimo, że użycie „arguments” w ES6 jest niezalecane ze względu na lepsiejsze . Trochę nieprzekonany jestem niestety do:

666

Ale pewnie środowisko z którego wywodzi się JS nie jest tu bez znaczenia 😉

Szeregowanie kooperacyjne w Micropythonie na ESP8266.

Ku mojemu zdziwieniu Micropython na esp8266 nie obsługuje wątków, a potrzebna mi była funkcja „sleep()”, która będzie się wykonywać równolegle do głównego wątku. Dziwne to, bo z FreeRTOS SDK wątki ponoć działają, choć całkiem możliwe, że kosztują zbyt wiele cennych zasobów potrzebnych Micropythonowi do życia. Znalazłem też info, że wynika to z ograniczeń zestawu instrukcji procesora. Cóż, FreeRTOS działa super na esp32 i niech tak zostanie. Niestety bez wątków funkcja zawłaszcza procesor licząc czas w pętli i jak chciałoby się wcześniej zasterować podłączonymi do esp8266 ustrojstwami, to trzeba by to zrobić manualnie ;). Na szczęście dostępna ilość pamięci pozwala na użycie modułu uasyncio i nieblokujących się socketów, bo to też istotne jeśli chcemy obsługiwać sprzęt przez requesty http typu <adres_ip>/onoff czy <adres_ip>/sleep=czas. Jedyny minus, to upip, którym nie zainstalujemy uasyncio ze względu na zbyt małą ilość pamięci. Trzeba to zrobić ręcznie.

import network
import usocket as socket
import errno

sta_if = network.WLAN(network.STA_IF)
addr = socket.getaddrinfo(sta_if.ifconfig()[0], 8000)[0][-1]
s = socket.socket()
s.setblocking(False)
s.bind(addr)
s.listen(1)
print('listening on', addr)

import machine
pin = machine.Pin(5, machine.Pin.OUT)
status = True; timeout = None
pin.value(status)

import uasyncio as asyncio
loop = asyncio.get_event_loop()

async def sleep(newtm):
    global status, timeout
    if timeout == newtm:
        return
    if timeout != None:
        timeout = newtm
        return
    else:
        timeout = newtm
    while timeout > 0:
        await asyncio.sleep(60)
        timeout = timeout - 60
    status = False; timeout = None
    pin.value(status)

async def worker():
    global status
    while True:
        line = None
        try:
            cl, addr = s.accept()
            print('client connected from', addr)
            cl_file = cl.makefile('rwb', 0)
            while not line:
                line = cl_file.readline()
        except OSError as exc:
            if exc.args[0] in [errno.ETIMEDOUT, errno.EAGAIN]:
                await asyncio.sleep(0)
                continue
        print(line, status)
        if 'onoff' in line:
            status = not status
            pin.value(status)
        if 'sleep' in line:
            s1 = line.find(b'sleep')+6
            s2 = line.find(b'H')-1
            try:
                timeout = int(line[s1:s2])
                loop.create_task(sleep(timeout*60))
            except ValueError:
                print('/sleep needs a numeric timeout')
        cl.close()

loop.create_task(worker())
loop.run_forever()

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

Ten sam skrypt na esp32 z użyciem _thread. Esp32 to już jednak potężna bestia, z ogromną ilością pamięci, zwłaszcza z PSRAM na pokładzie, oraz sporym zapasem mocy procesora dual-core ;).