I've decided to use one of the Digispark modules I've to had to control my switches from PC. Digispark are tiny module in a form of USB plug, with the support for software USB (with V-USB library) already implemeted. So it looked like a perfect fit for this task to me. Most likely it could be easily ported to any other AVR-based board (adding a couple of 3.3V Zener diodes on D+/D- lines if it's 5V part, etc).
Decided to go with USB HID device class, because it's a standard class, i.e. driver should be shipped with most modern OSes.
Once I've got to try DigistumpArduino provided DigiUSB class, I've understood that it's kinda incomplete and can't be good for bi-directional USB HID communications. So I've had to rework DigiUSB communication class for my needs.
So for I didn't done PC software for it yet, but commands can be sent with a generic console tool hidapitester. Repo README page has usage example. Device accepts Livolo Remote ID & key code from USB host (i.e. PC / whatever). I'll write my own PC software for this device with more user-friendly interface soon. It will be shared on the same repo once done.
Added cross-platform control software.
With the help of Github Actions binaries for both firmware & software (currently supporting x86_64 Windows and Linux targets) are automatically compiled and uploaded to Releases section.
Digged further into original "Livolo" library and realised I think it might be implemented way better. First of all all those "high" and "low" bit are weird conception. Basically Livolo codes are actually interpreted as if there is a level transition during set bit length time. If there was a transition - it's 1, if not - it's 0. And there're always transition on each bit.
Capture (with logic analyzer) of demodulated signal from original Livolo remote:
Starts with preamble high level of ~530 uS, then each bit takes ~320 uS: same level for 320 uS means 1, transition at around the middle (~160 uS) means 0. So it reads like this:
So apart from the preamble and some timing drift this could be implemented as a simple timer configured for ~160 uS period which inverts output signal every 2 (even) periods plus inverts it on odd period if bit are 0.
Also, using hardware timer won't suffer from drift due to USB comms interrupts. So I've worked on my own transmitter code using Timer 1 (had to change Digistump core config to use timer 0 for millis like other Arduino boards) and it's much more accurate. Currently on a local branch only, will push it to Github repo once polished soon.
PS: Bit sequence are 23 bits (excluding start/preamble frame) 16 bits of remote ID followed by 7 bits of key code. At least this is how it was done in original Livolo library and seems to work well. Transmitted from MSB to LSB. Repeated 128 times in original remote vs 180 in Livolo library. ~530 uS preamble preceeds every repeated packet.
Released a new version 0.6.3 - code refactoring and improvements, some of which should improve radio accuracy. Some bugfixes, notable one fixing build for macOS, other fixed incorrect firmware version detection by a host software in some cases (OS/compiler). A a few minor fixes.