Commit Graph

55 Commits

Author SHA1 Message Date
925106394b build: the filed i2c cost comes back, -70 B on the tiny85
1316 -> 1246. libavr took the finding this repo filed when its pin last moved:
the shared transaction ladder's cost was never the ladder but the argument
list reaching it - AVR passes eight bytes in call-clobbered registers and the
rest in call-saved ones, so twelve bytes made every forwarder save four it
never reads. A write has no read span, so the write path now passes eight.

Worth recording that the candidate this repo suggested was measured and
rejected upstream, and the numbers filed from here are why: it wins 66 B on a
driver like this one and charges a single-byte reader 20, which is a class
rather than one program.

The mega328P does not move at 1480 - its TWI backend has its own ladder and
was never charged. Net over the whole 22-commit advance the tiny85 is +8 B,
and all of it is the bit-period fix that made the wire rate stop following the
inliner.

Sixteen tests green, cross-mode identity held on both chips.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 06:22:23 +02:00
bd604ec288 build: the libavr pin advances, and the tiny85 image grows 78 B
43fc479 -> aec9955. The mega328P does not move at 1480 B - it drives the RTC
from the TWI block, which neither change touches. The tiny85 has no TWI, so
dev::i2c resolves to the bit-banged master there and takes both:

  cb40a13, the bit period                      1238 -> 1262  (+24)
  943ffbe, one call shape over every master    1262 -> 1316  (+54)

The first is a bug being paid for. software_master delayed a fixed quarter
period and let its own instructions make up the rest of the bit, so the rate
on the wire followed the inliner; each bit now delays a low and a high phase
net of what that phase already spends. The DS3231 is a 400 kHz part and this
example asks for 100, so nothing here was out of spec - the bytes buy a rate
that no longer moves when the image does.

The second is a trade, and it is worth writing down which way it went. The
shared ladder is smaller than the two it replaced - run_transfer is 232 B
against read_regs 162 + write_regs 102 + stop 30 - but the call-site thunks
that marshal spans into it cost 116 B where the specialised ladders were
inlined, so a driver making both calls nets +54. Filed upstream with these
numbers rather than worked around here: which way the trade falls is a
property of the consumer's mix, and that is the library owner's call.

Size re-recorded in the two places that state it. Four presets green,
cross-mode identity held on both chips.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 02:17:44 +02:00
176f78c2e9 test: the README's cross-mode claim is now checked, not just stated
The pin advances to the commit that gives consumers the gate's own image
comparison, and the claim written into this README a few commits ago - 1480 B
and 1238 B, byte-identical across the two modes - is registered against it.
Both chips compare clean over every loadable section.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 20:49:59 +02:00
6e179fbac6 test: the example's size stops being a number nobody holds
Every other port in the fleet states its image size and is held to it; this
one stated none, so a library advance could move `clock` and no check would
say a word - which is exactly what the size claim was built after. The two
numbers are what the presets build today, byte-identical across generated
and reflect, and the README now says both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 19:20:24 +02:00
53ff3f1258 build: the libavr pin advances over the inlined vector
The vector that inlines its handler is the one advance that could reach a
driver on the two-wire bus, and it does not reach this one: `clock` drives
the bus from the foreground, so it is byte-identical across the advance in
all four modes - 1238 B on the attiny85, 1480 B on the atmega328p.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 19:08:07 +02:00
a02b051ab4 chore: machine-local state has a home here too
Guidance rule 15 puts every machine-local artefact under a gitignored local/,
and this repo could only have committed one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 03:32:52 +02:00
923c118c6d test: the format and ASCII rules stop being a habit, and the stated sizes stop drifting
libavr's guidance binds this repo too, and until now nothing here checked it -
`ctest` runs `libavr_format_test()` over this tree's own sources now (rules 11
and 33), skipping rather than passing where clang-format is absent. It caught
drift on its first run: a file written this week and edited after formatting.

Where the README states a measured size, `libavr_size_claim_test()` holds it to
the image and holds the image to the prose: advancing the library pin moved
three of these across the fleet with nothing saying so, and re-recording one
now requires the sentence that quotes it to move too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 23:02:40 +02:00
5b6bff8346 build: the libavr pin advances to the sweep's own record
Documentation only - the guideline sweep's condensed entry, the three measured
facts about class-type constants it produced, and the port filings it left
open. No header, tool or generated input moves, so every image is untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:02:55 +02:00
2e9c929a19 fix: an alarm's interrupt could be turned on and never off, and nothing tested any of it
`set_alarm1/2`'s `enable_interrupt = false` did nothing at all - it skipped the
control-register write rather than clearing A1IE/A2IE - and there was no other
way to clear them, so an alarm armed once with its interrupt on drove INT/SQW
for good. It is `alarm_interrupt::off` now and it clears the bit, with
`listen_alarm1/2()` and `mute_alarm1/2()` beside it for a caller that arms once
and changes its mind later. The bare bool went with it (rule 37): `set_alarm1(at,
rate, false)` said nothing at the point of use.

`bool SetWeekday` was the same shape one level up - `device<bus, false>` names
nothing - and its two writers disagreed about what it meant: `write_date`
skipped the weekday register, `write_clock` stamped a placeholder 1 into it, so
a program that turned the maintenance off still had the register overwritten
and no way to set it. `weekday_source::external` now means the register is the
program's, in both writers.

test/consteval.cpp is the battery this driver never had, over the arithmetic
that has no bus in it: the BCD round trip across every representable value and
its nibble layout, the hours register in both formats including all four
noon/midnight cases, Sakamoto's weekday against six calendar dates (leap day,
the day after it, and 2100's missing leap), and both alarms' rate encodings
transcribed against 19-5170 Table 2 - including that alarm 2's masks sit one
place below alarm 1's, which is the property that makes one distribution loop
wrong for the other. Red-green: two assertions fire on a flipped DY bit.

Beside it, one decode rather than two: `read_clock` and `read_time` spelled the
seconds/minutes/hours triplet out separately (rule 6).

Every image byte-identical on both chips in both modes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 15:40:52 +02:00
572d38feef build: the libavr pin advances past the audit sweep, and the extents get counted
The pin crosses libavr's phase-6 close and the guideline sweep behind it;
the example is byte-identical on both chips in both modes.

The port's own sweep found rule 36 in seven places, and the fix had to be
measured rather than applied. Sakamoto's month offsets as a `std::to_array`
local cost **+348 bytes** on a 1480-byte image - an automatic class-type
constant inside a `constexpr` function is given an address and built per
call, which outlined `weekday()` whole and pulled in `__do_copy_data` and
`__udivmodhi4`; `static constexpr` is what folds it, and emits no symbol at
all. The six register buffers cost +4 as `to_array`, which materialises its
argument array before copying where an aggregate initialiser stores each
element as it is computed - so those take CTAD, which counts the extent and
keeps the direct initialisation. Both spellings are rule 36; only one is
free.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 14:40:20 +02:00
bea81c97e0 editor: clangd and cmake work from a committed vscode workspace
The three files libavr's consumers carry: .vscode/settings.json names the
atmega328p-generated database and passes --query-driver, .clangd holds the
stand-ins clang needs for GCC's AVR dialect -- and no database, because this
driver is made to be vendored and the file travels with it -- and
extensions.json names the two extensions. The libavr pin advances to the
editor-audit fixes, without which every TU inherits device.hpp's
alias-shadowing errors. The preset builds green from the pin and clangd
reports zero errors on the example TU.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 16:48:26 +02:00
87e1f5e8a1 build: the libavr pin advances past phase 6, and the driver takes the bus whole
The register sugar now rides the bus's own master role - device<Bus>
resolves avr::i2c::device<typename Bus::master, bus_address>, so a
consumer keeps handing over its declared dev::i2c<...> unchanged - and
the DS3231's hardwired 0x68 is a named constant. The example's four
discards became the LED's own error signal (a failed seed or a failed
alarm clear holds it dark, the same word a stuck bus says), the tree is
reformatted under InsertBraces, the sources are ASCII, and the README's
stale Studio byte counts are replaced by the claim its check-flags gate
holds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 11:46:10 +02:00
2909d0bc6c build: the libavr pin advances past the consumer-report fixes
timer::engine gains stop()/start() and a runtime TOP, adc gains
disable()/enable(), and libavr_programming_targets() stops leaving .fuse bytes
in the flash HEX. Every one of them is additive, and this port adopts none of
them yet: its 1 built image comes out byte-identical across the pin change,
which is what the advance is here to keep true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 23:18:55 +02:00
c49ada8a71 build: the libavr pin advances to the v9 era
Built and tested against it in a clean checkout of this port, through its own
submodule rather than a working-tree override, so the pin is what was proved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 18:46:36 +02:00
5c14c340e0 build: the libavr pin advances over the trait projection
The de-string-2 pass upstream: every peripheral block behind generated
instance traits, the string layer gone. Nothing here changes — both
examples rebuild byte-identically across modes at their recorded sizes
(tiny85 1212 B, mega328P 1242 B).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 19:59:11 +02:00
52ef7cb791 build: the libavr pin advances to current main
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 07:24:09 +02:00
c023b5ed31 build: the libavr pin advances to current main
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 06:48:36 +02:00
d219b299f4 build: libavr rides as the pinned submodule
The submodule replaces FetchContent and the unpinned forge fallback;
LIBAVR_ROOT stays as the tandem-development override, the presets take the
toolchain file from the submodule, and the Studio project's include path
anchors there — correct by construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 00:29:38 +02:00
0ecd53856b ide: the attiny85 beside the atmega328p, one directory each
The presets cover both parts, so the solution should too. Studio carries
avrdevice as a project property, so a part is a project rather than a
configuration, and both build example/main.cpp to a .text byte-identical to
their CMake counterpart: 1242 B on the mega, 1212 B on the tiny, each with the
architecture its own object file says.

They need separate directories, not just separate names. Studio builds into
<project dir>/<Configuration> whatever OutputDirectory claims — setting it per
project creates the directory and then ignores it — so two projects in one
directory share example/main.o. Verified rather than assumed: with both in ide/,
the single shared object read avr:25 while the mega's ELF read avr:5, so a
build of one after the other without a rebuild links the wrong part's object.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 19:51:50 +02:00
dc89d0779a ide: the Atmel Studio solution master has, on the libavr port
master opens in Studio, so this branch should too. The solution builds
example/main.cpp — the port's only executable, the driver itself being an
INTERFACE library — for the ATmega328P that solution targeted, and the
acceptance is not that it builds but that it builds the same firmware: .text
comes out byte-identical to CMake's at 1242 B.

One project, one chip. Studio carries avrdevice as a project property, so the
attiny85 half of the presets would need a second project rather than a second
configuration; CMake stays the build system and covers both.

libavr is found beside this repo, anchored to the project directory rather than
written relative to the generated makefile, which runs from the configuration's
output directory. No LIBAVR_ROOT: a variable exported in a shell is invisible to
Studio launched from the Start menu.

Both configurations verified headless with LIBAVR_ROOT unset, and the flag
mirror checked against the CMake build's own compile_commands.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 19:33:39 +02:00
cdca5219d0 Rewrite on libavr
Same driver surface as the yazoalfa version — clock and alarm get/set,
alarm interrupts, flag check/clear — plus oscillator-stop detection and
die temperature. One source for tiny85 (software I2C) and mega328P (TWI),
built against libavr in both generated and reflect mode, byte-identical
.text across modes. Errors surface as std::expected instead of being
dropped; weekday-rate alarms now really set the DY bit (legacy cleared
it); multi-register access is one coherent bus transaction. Legacy stays
on master.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-18 01:09:43 +02:00
8a6170cb10 Add get alarm helper to reduce code duplication 2020-05-17 20:11:35 +02:00
21f9215bba Implement getting alarm times 2020-05-17 20:06:13 +02:00
dfd2289aef Reduce code duplication 2020-05-17 19:54:46 +02:00
14e608d397 Implement setting alarms 2020-05-17 19:41:53 +02:00
1bc7e66389 Move alarm rate from inside details to visible namespace 2020-05-17 19:19:28 +02:00
ff52f4f152 Implement checking and clearing alarm 2020-05-17 19:10:16 +02:00
3029c3cfe0 Add wrapper to write complete register 2020-05-17 18:59:38 +02:00
c3f9aa6a13 Automatically deduce register address by type 2020-05-17 18:59:19 +02:00
db5197b3b1 Add more flag operator overloads 2020-05-17 18:57:26 +02:00
2a90cdee18 Add time equality check operators 2020-05-17 11:49:30 +02:00
1388412d70 Change interface to only pass i2c backend driver into class 2020-05-16 19:52:22 +02:00
a946746960 Remove legacy rtc lib 2020-05-16 17:59:38 +02:00
16249914c2 Adapt to moved type submodule 2020-05-16 17:43:55 +02:00
11211be9b9 Implement setting date-time 2020-05-16 17:25:00 +02:00
8c50aa4688 Implement setting time 2020-05-16 17:19:54 +02:00
a65b30f9df Fix partial writing to only write to a range instead of until the end 2020-05-16 17:19:25 +02:00
cd5317db5b Implement setting RTC date 2020-05-16 17:03:30 +02:00
92096b6101 Add helper to allow writing partial register data 2020-05-16 17:02:54 +02:00
80cce4671f Implement optional automatic setting of day of week 2020-05-16 17:01:19 +02:00
c728d99f97 Fix default value for day field in time register 2020-05-16 16:59:54 +02:00
8e653ebd44 Add default init for registers 2020-05-16 16:00:27 +02:00
54b8917705 Implement modern C++ driver base 2020-05-15 19:47:44 +02:00
2768009720 Remove twi library and switch to i2c library submodule 2020-05-15 11:50:11 +02:00
04af54e7c8 Remove C time API glue from driver 2020-05-15 10:20:56 +02:00
9303fbf5b5 Fix clock path 2020-05-15 09:40:08 +02:00
727a974504 Fix warnings 2020-05-15 09:25:48 +02:00
b3364f0b88 Add gitignore, clang-format and license file 2020-05-15 09:20:23 +02:00
22a74d0b77 Imported changes from example branch 2017-12-17 10:55:25 +01:00
8e2e18128b Exported code as submodule 2017-12-17 10:48:59 +01:00