# Changes, version by version The short version: this package has been published three times, and the two announcements after the first one do not appear to have reached the sane-devel archive. This file is the long form, so that the list messages can stay short. Every number below was measured on the device unless it says otherwise. The run numbers refer to a numbered log kept alongside the work; they are quoted so that a claim can be traced to one capture rather than to a memory. | version | date | headline | |---|---|---| | 1 | 2026-08-25 | first publication | | 2 | 2026-08-28 | white level, period-2 ripple, black level | | 3 | 2026-09-03 | geometry and full width; motor path and lamp | | 3a | 2026-09-04 | documentation only: the tone curve is described correctly | --- ## Version 3a — 2026-09-04 (documentation only) No code, no patch change: the binary and `a320e-genesys.patch` are byte for byte those of version 3. Two statements in the README were wrong and are corrected, both about the tone curve. - **The knee was described as if it were still there.** It was removed before version 2 shipped (measured on a printed original: it gave the top third of the range a slope five times shallower than the rest). The README kept the old sentence, including the claim that the curve "never clips" — the current curve does clip, on 19 pixels out of 3.6 million on a real original, and that is the trade that was deliberately made. - **The curve was described as a straight gain.** The gamma table is the backend's own curve for this sensor, gamma 2.2, with its entries multiplied by 1.40 and clipped. The transfer is `out = min(1, 1.40 * raw^(1/2.2))`. One measurement was added to the black-level limitation while checking the above, because it answers the question a reader would ask next: the black level being 8x / 15x / 31x the vendor's does **not** show up as a raised black floor in the image. On the same original in the same position, the vendor's image is an affine map of this driver's over the whole scale — constant term +0.6 DN on green and blue, -7.4 DN on red, worst residual 3.2 DN across the 2-99 % quantiles. The red difference is the vendor's black point (they push 0.224 % of the red channel to exactly zero; this driver pushes none), not a floor of ours. --- ## Version 3 — 2026-09-03 Two groups of work, neither of which changes the image on a correctly calibrated scan. They change what the hardware does while producing it. ### Geometry and scan area (2026-08-29 … 2026-09-01) These were finished after version 2 was published but were never announced. - **The x scale was 0.75 % long and is now 0.9991 ± 0.0001**, measured with a ruler across the bed at 200, 400 and 800 dpi. The sensor's real pitch is about 403 dpi against the ASIC's 400-dpi pixel grid. The correction is in the millimetre-to-pixel conversions (`a320e_x_scale`, `low.cpp`), deliberately **not** in `optical_resolution`, which has to stay 400: it is the grid that the decimation, the shading data and the calibration widths are all counted on. What remains is a ±0.4 % position dependence across the width. - **The whole bed is scannable**: 304.8 × 431.8 mm, verified at 200, 400 and 800 dpi. The shading window now spans the full width, which is what removed the black tail and the comb of stripes at the right-hand edge. - **Consequence for the user, stated plainly in the README:** the white calibration target must now be at least 305 mm wide. This scanner has no internal white strip — its lid backing is nearly black (64.8 DN against a white sheet's 252.6 in the vendor's own captures) — so the white reference is whatever lies on the glass at the front edge. A3 paper is 8 mm too narrow. ### Motor path and lamp (2026-09-02 … 2026-09-03) - **The lamp now goes out when the carriage starts back**, as the vendor's driver does. `CommandSetGl124::save_power` is an empty function upstream, so nothing turned it off before; measured delay from the last image byte to `LAMPPWR = 0` is +0.22 s. - **The motor acceleration curve is now the vendor's measured table, not a model.** The old curve came from `create_slope_table_for_speed`'s constant- acceleration formula; the new one is 191 entries read out of the vendor's own captures. One table, cut at each resolution's plateau, reproduces the vendor entry for entry at 100/200/300/400/800 dpi and to within 0.12 % in a single entry at 600 dpi. STEPNO now comes out as the vendor's value at all six resolutions instead of two steps long. Measured on the device (interleaved A/B, three pairs, audio recorded): the image, its geometry and the return timeline are unchanged; the movement before the image is 26 ms shorter, which is the only measure that sees the change at all. - **`FWDSTEP` and `BWDSTEP` are now written per phase** — 128 in the image session, 1 in the stationary calibration sessions, 80 elsewhere — which is the vendor's three-layer arrangement. Upstream's gl124 branch never wrote the fields at all, so the initialisation value stood in all eleven sessions. - **`FSTPSEL` is no longer tied to `STEPSEL`.** They are separate fields of `0xa0` serving different movements; at 600 dpi the vendor writes `0x0a` where the shared value produced `0x12`. - **The slope tables are loaded at their full 512-entry length**, as the vendor does. Nothing reads past the entries in use today, so this is defensive: the addresses are fixed and only `table.size()` bytes were written, leaving the tail as whatever the previous session put there. - **`FASTNO` and `FSHDEC` follow the scan table**, which is what the vendor and the four other ASIC branches do; gl124 was the only one tying them to the fast table. ### What was deliberately not adopted Four differences against the vendor were traced to structure rather than to a wrong value, and copying the value would have been the wrong fix. They are listed because the reasoning is more useful than the outcome: - **`FWDSTEP` in the shading phase** (ours 80, the vendor's 1): `FWDSTEP` is the backtracking step count, and the shading session sets `DISABLE_BUFFER_FULL_MOVE`, i.e. `ACDCDIS`, i.e. backtracking off. The value is dead in that phase on our side and live on the vendor's. - **`FSHDEC` = 1**: the vendor stops the scan without a deceleration ramp because AGOHOME takes the carriage over immediately. Without AGOHOME that is a stop with no brake. - **`FMOVDEC` = 1**: it addresses table 5, which the gl124 branch never uploads, for an auto-go-home this driver does not use. - **`FMOVNO` = 512 and the vendor's fast profile**: tried on the device and measured — nothing changed, because table 4 is the fast-feed table and gl124 never sets `FASTFED`. The vendor's feed is a separate fast move; ours happens inside the scan session. The last three, plus the missing `HOME_TABLE` upload, are properties of the gl124 branch rather than of this scanner, and they are reported to sane-devel separately. --- ## Version 2 — 2026-08-28 The announcement for this version does not appear in the list archive. Its content, in short: - **White level.** Images came out at roughly 70 % of the brightness they should have. Version 1's README explained this as a design consequence of the shading divisor; that explanation was wrong. Plain paper reads 1.36× the internal reference, so the calibration white landed at 174 of 255. The fix is in the gamma table — which the ASIC evaluates after the shading division, where overflow clips instead of wrapping — as a straight 1.40× up to 90 % with a linear knee into the top tenth. Result 233/234/235 against the vendor's 251/254/255. At 16 bpp the gamma table is left out and the data stays linear. - **Period-2 ripple** dropped from 13 DN to 0.4–1.3 DN. The cause was the sign of the offset parity, not the sensor. - **Black level** is 8× / 15× / 31× the vendor's (R/G/B). Not fixed, but the cause is identified: the offset search stays on positive codes while the vendor goes negative. All three were found the same way: by putting the same sheet through this driver and the vendor's Windows driver without opening the lid, with the USB device passed through to a VM. --- ## Version 1 — 2026-08-25 First publication, following Ralph Little's reply on sane-devel (2026-08-22, message 040366).