Fix compress_value#4
Open
MrPaschenko wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix
compress_value: IR transmit produced 16× too-short timings for all pulses > 2032 µsSummary
The Ocrustar/ElkSmart pulse encoder in
server.pydivided every timing value by 16 before LEB128-encoding it. This is only correct for small values. For any pulse longer than 2032 µs — which includes the lead-in mark and inter-frame gaps of essentially every IR signal — the device firmware interprets the encoded bytes as raw microseconds, so the transmitted timing came out ~16× too short.The result was an un-decodable carrier envelope: the IR LED still lit up, but no receiver could decode the signal. In practice this meant Ocrustar transmit (both synthesized protocol codes and captured/replayed signals) never produced a working IR command.
Root cause
compress_valueused a single code path that always appliedround(value / 16)and then LEB128-encoded the result. The correct encoding has two regimes:round(µs / 16)(device decodes asbyte × 16)So e.g. a Sony 2400 µs start pulse was transmitted as ~150 µs, and 45 ms inter-frame gaps as ~2.8 ms.
Fix
Reimplemented
compress_valueto match the two-regime behavior. Round-trip verified: 2400 / 9000 / 45000 / 58992 µs now decode to their exact values; small values stay within the normal ±8 µs (16 µs quantization).How it was found
Reproduced with real hardware: an Ocrustar USB IR blaster (D552 variant, PID
0x0132) transmitting to a Sony Bravia TV (RMT-TX450E remote). Symptoms were a flashing IR LED but zero response from the TV, for both generated SIRC codes and signals captured from the original remote — which pointed at a timing/encoding corruption rather than wrong command data or carrier frequency.The bug and fix were diagnosed and generated with Claude Opus 4.8 (Claude Code).
Reference for the correct implementation
Verified against the upstream Android app's shipping driver,
ElkSmartUsbProtocolFormatter.compressValueUs():https://github.com/iodn/android-ir-blaster/blob/master/android/app/src/main/kotlin/org/nslabs/irblaster/usb/ElkSmartUsbProtocolFormatter.kt
Testing