Robin Palotai

Source code archeology and table tennis.

Robin Palotairobinp
2025-06-16

Feedback is now provided by a blinking LED pattern.

Robin Palotairobinp
2025-06-16

So I take measurements of diff between each pair (need to take the samples in sync, to avoid getting out-of-phase samples.. it is a 1kHz changing signal), take tally of number of high diffs. First worked out which segment is which part of a digit (based on how activations change when going to next blind), then wrote code to decode based on the pattern.

Robin Palotairobinp
2025-06-16

For reasons, the LCD driver signal is fun. Each segment is controlled by the difference between the voltage on a row wire and a column wire (called Com(mon) and Seg(ment)). The avg of the difference is always zero ("good for the LCD"), but an active segment will have high peaks.

Robin Palotairobinp
2025-06-16

Dropped a shutter remote, got the 7-segment LCD ruined. Don't want to waste the whole device just because of the LCD, so built an Arduino prototype to recover the digit displayed from the LCD driver levels. Was a fun activity! Should get it prod-ready though, so it doesn't need USB power and the whole dev board to control the shutter..

Robin Palotairobinp
2025-06-12

Your personal invitation to the next event, sent as an automated mass email for efficiency purposes.

Robin Palotairobinp
2025-06-06

In retrospect:

Me: finally a Github Actions change that works smoothly
GHA: (grinning, rubs hands)

Robin Palotairobinp
2025-05-30

@reidrac do those things wear tired? I thought if not physically stressed, should stay in good condition.

Robin Palotairobinp
2025-05-15

@bouncepaw is the glass half full of half empty? It's nonEmpty!

Robin Palotairobinp
2025-05-14

@rzeta0 np, though not necessarily simpler, just different.

One thing I wouldn't do with these kind of constraints (or any complicated constraints) is to let them spread through the whole codebase.

In code that say deals with a single currency, just use some currency-unaware stuff. Where you deal with say conversions, use the typed stuff. Otherwise it will get ugly fast.

Not easy to utilise advice, but watch out.

Robin Palotairobinp
2025-05-14

@rzeta0 this GADT thing is one you can't do in say Java or other langs - basically it is like an ADT with different cases, except the type parameter will restrict which cases are actually valid.

The compiler will know that MoneyUSD x is not a valid constructor for type Money 'EUR. (Edited)

Robin Palotairobinp
2025-05-14

@rzeta0

-- you don't even need the class/instance, you can just use the renderMoney directly:

renderMoney :: Money currency -> Text
renderMoney m = case m of
MoneyEUR v -> "EUR " <> show v
MoneyUSD v -> "USD " <> show v
MoneyCHF v -> "CHF " <> show v

Of course these things come with different tradeoffs and further implications downstream.. experiment, mix and match for your usecase.

Robin Palotairobinp
2025-05-14

@rzeta0 if you don't need to support an open set of currencies, going with a closed GADT might be cleaner:

{-# Language DataKinds #-}
{-# Language GADTs #-}

data Currency = EUR | USD | CHF

data Money currency where
MoneyEUR :: Double -> Money 'EUR
MoneyUSD :: Double -> Money 'USD
MoneyCHF :: Double -> Money 'CHF

class Render currency where
render :: Money currency -> Text

instance Render 'EUR where
render (MoneyEUR v) = "EUR " <> show v

but also... (to be continued)

Robin Palotairobinp
2025-05-14

Me: now I've got all cases covered

Quickcheck: Are you sure? How about this case?

Me: that's... what a silly case that is! Wait.

Robin Palotairobinp
2025-05-12
Robin Palotairobinp
2025-05-12

Microsoft is the most secure provider ever. First you use your login to log in to the LLaaS (Login-Loop-as-a-Service) product. Then you try to randomly sign in, sign out, refresh, delete cookies, delete the browser.. the point is, if you can't log in, the hackers can neither.

Robin Palotairobinp
2025-05-05

@reidrac thank you! The ingredients and initial setup is similar to what I got, but there's some divergence after. Will try eventually.

Robin Palotairobinp
2025-05-05

@reidrac recipe or it didn't happen pls! As part of my quest of baking a bread that doesn't collapse midway.

Robin Palotairobinp
2025-04-21

And one can mangle the allowBackup=false out of the binary manifest xml, but then android doesn't let one install the debugSigned one over the original (makes sense). So first you need to uninstall original (but then the data you wanted to backup was gone). Ok, if you could start the debug-signed, perform actions, and then backup.. but then as pointed above, it doesn't really work. End of story.

Robin Palotairobinp
2025-04-21

(turns out one can't really reencode modern packages w/apktool, due to lossy info in original package.. something about attributes as integers or such - github.com/iBotPeaches/Apktool)

All in all, it was a lot of trial and error with dead ends. Trying to mod and recompile something modern would take tremendous effort and fighting with / fixing tooling. And then getting the phone to accept it. (Funnily, one can't easily take data backup. There's this encrypted db thing).

Robin Palotairobinp
2025-04-21

sign with debug key: java -jar uber-apk-signer-1.3.0.jar --apks base.apk
# adb refuses partially inconsistent sigs in multi-apk install... so resign all
java -jar uber-apk-signer-1.3.0.jar --allowResign --apks base.apk split....apk

adb install-multiple -r base-aligned-debugSigned.apk split_config.....apk

Failure [INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: Failed parse during installPackageLI: Failed to read manifest

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst