fix(meade): accept the unsigned site longitude INDI sends - #304
Draft
rbhbokka wants to merge 1 commit into
Draft
Conversation
Regression from OpenAstroTech#291. readLongitude() uses Cursor::signed3(), which makes the sign mandatory, but INDI sends ":Sg121*53#" unsigned for a site 121d53' west. The command is answered "0" and the mount keeps whatever longitude it had. An unsigned Meade site longitude is the legacy count running westward from Greenwich, so it folds into the east-positive range the mount stores by negating modulo a full circle. Not by 180 - value, which is what the (dead) Longitude::ParseFromMeade computes and what MeadeProtocol.hpp described: that reflection turns a 121d53' west site into 58d07' east, exactly 180 degrees -- 12 hours of local sidereal time -- from where it belongs. None of this is visible in readback, because :Gg# applies the inverse of whatever the setter did, so a wrong convention round-trips perfectly; it was verified instead by comparing :XGL# against an independently computed LST. Also reject values outside one full circle and minutes above 59. Nothing downstream did: core::Longitude(int, int, int) never calls checkHours(), and EEPROMStore::storeLongitude clamps degrees*100 into an int16, which destroys the mod-360 equivalence and persists a genuinely wrong site across reboots. The arithmetic is widened to long, which also removes a signed overflow that was undefined behaviour on the 16-bit AVR target from ":Sg545*69#" onward. The signed form is deliberately left exactly as it is. Which hemisphere its sign denotes is a separate question, contested by OpenAstroTech#296, and this change does not answer it. Known limitation, documented in the code and in MeadeProtocol.hpp: a west longitude under one degree still loses its sign, because MeadeLongitude carries the sign only in `degrees`. Fixing that means letting the struct hold the sign separately. Co-authored-by: Claude <noreply@anthropic.com>
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.
Regression from #291. Draft, because it also raises a protocol-convention question I'd like a maintainer to rule on — see the last section, and note that #296 asserts the opposite convention for the signed form.
The defect
readLongitude()usesCursor::signed3(), which makes the sign mandatory. INDI sends:Sg121*53#unsigned for a site 121°53′ west, so the command is answered0and the mount silently keeps whatever longitude it had.Captured off the wire on an INDI connect to an OpenAstroExplorer:
An unsigned Meade site longitude is the legacy count running westward from Greenwich, so it folds into the east-positive range the mount stores by negating modulo a full circle.
Not by
180 - value. That is the other reflection — the one that puts Greenwich at 180 — and it is what the (now dead)Longitude::ParseFromMeadecomputes and whatMeadeProtocol.hppdescribed. It turns a 121°53′ west site into 58°07′ east: exactly 180°, i.e. 12 hours of local sidereal time, from where it belongs, which mispoints every subsequent GOTO.None of this is visible in readback —
:Gg#applies the inverse of whatever the setter did, so a wrong convention round-trips perfectly. It was verified instead by comparing:XGL#against an independently computed LST.Also fixed
Range validation.
digits(3, …)accepted 0..999 and the wrap was a singleif, not a loop, so:Sg600*00#yielded −240°. Nothing downstream caught it:core::Longitude(int, int, int)never callscheckHours(), andEEPROMStore::storeLongitudeclampsdegrees * 100into anint16(±327.67°) — that clamp destroys the mod-360 equivalence and persists a genuinely wrong site across reboots. Values outside one full circle, and minutes above 59, are now refused.Signed overflow on AVR. The arcminute arithmetic is widened to
long.intis 16-bit on ATmega2560, sodeg * 60 + mmexceededINT16_MAXfrom:Sg545*69#onward — undefined behaviour in an-O2build, and it did diverge between 16- and 32-bit targets. The range check also prevents reaching it; both are in.Deliberately unchanged
The signed form. Which hemisphere its sign denotes is a separate question —
MeadeProtocol.hppsays negative goes east, the deadLongitude::ParseFromMeadeimplemented that, #291 dropped it, and #296 proposes restoring it. This change passes signed values through exactly asdevelopdoes and adds a test pinning that, so the discussion starts from a documented baseline. I have no evidence either way for the signed form and am not trying to settle it here.Known limitation
A west longitude under one degree (
000*01..000*59) still loses its sign, becauseMeadeLongitudecarries the sign only indegreesand-0is unrepresentable. There is aKNOWN LIMITATIONcomment at the exact spot and a test named for it. The structural fix isfix/meade-sign-of-zero, which gives all three coordinate structs a real sign channel; I kept it out of this PR to keep the convention argument separable from the struct change.The question for maintainers
MeadeProtocol.hppcurrently documents the unsigned form as "0 to 360 going WEST with 180 at Greenwich. So 369 is 179W and 1 is 179E." No live code implements that, and it disagrees with what INDI puts on the wire. This PR updates that block to match observed client behaviour. If the document is right and INDI is wrong, this PR is wrong too — please say so and I'll close it.Verification
pio test -e native: 281 pass (269 ondevelop+ 12 added, none removed or weakened). An exhaustive sweep of all 21,600 unsigned wire values decodes exactly, except the 59 in the documented sub-degree band. Builds clean under-Werrorforoaeboardv1andramps;avr-g++ -mmcu=atmega2560 -Werror -Wconversionclean on the parser.File overlap
Same two files as #303 (
:SG), in different blocks, andfix/meade-sign-of-zerorewrites the three readers this touches. All are independently mergeable; whichever lands second gets a trivial rebase from me.