Files
ds3231/README.md
BlackMark 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

72 lines
3.2 KiB
Markdown

# ds3231
Maxim DS3231 RTC driver on [libavr](https://git.blackmark.me/avr/libavr):
clock and alarm read/write, alarm interrupts, oscillator-stop detection,
die temperature. One source runs on every libavr chip — TWI hardware on
the mega328P, open-drain software I2C on the tinies. All bus errors
surface as `std::expected`.
```cpp
using bus = dev::i2c<{.frequency = 100_kHz}>;
using rtc = ds3231::device<bus>;
auto now = rtc::read_clock(); // result<date_time>
(void)rtc::set_alarm1({}, ds3231::alarm1_rate::once_per_second);
```
`example/main.cpp` is the full tour. Build with a libavr checkout:
```sh
LIBAVR_ROOT=/path/to/libavr cmake --preset attiny85-generated
cmake --build --preset attiny85-generated
```
Presets cover attiny85/atmega328p in both libavr modes (generated and
reflect). The legacy yazoalfa-based driver lives on the `master` branch.
## Atmel Studio
`master` carries a Studio solution, so this branch does too: `ide/ds3231.atsln`
builds `example/main.cpp` for both parts the presets cover, each to a
**byte-identical `.text`** against the CMake build — 1242 B on the ATmega328P,
1212 B on the ATtiny85 — with the flags mirrored by hand. CMake remains the
build system.
`avrdevice` is a project-level property in Studio, so a part means a project, not
a configuration: `ide/atmega328p/` and `ide/attiny85/`. They need separate
directories rather than separate names — Studio builds into `<project
dir>/<Configuration>` whatever `OutputDirectory` says, so two projects sharing
one directory would also share one `example/main.o`, and building one after the
other without a rebuild would link the other part's object.
Studio expects libavr checked out **beside this repo** and finds it at
`$(MSBuildProjectDirectory)\..\..\libavr\include` — anchored to the project,
because a plain relative path is resolved against the generated makefile's
directory (the configuration's output directory), not the project's. There is no
`LIBAVR_ROOT` escape hatch: a variable exported in a shell is invisible to Studio
launched from the Start menu. It also needs a GCC 16.1 toolchain registered as
flavour `avr-g++-16.1.0`, nothing older reaching `-std=c++26`.
One generated file is required before the project will load, and one command
checks the flags have not drifted (both from libavr's `tools/atmelstudio/`):
```sh
for mcu in atmega328p attiny85; do
case $mcu in atmega328p) device=ATmega328P;; attiny85) device=ATtiny85;; esac
python ../libavr/tools/atmelstudio/componentinfo.py \
"ide/$mcu/ds3231-$mcu.componentinfo.xml" --device "$device"
python ../libavr/tools/atmelstudio/check-flags.py --solution ide/ds3231.atsln \
--project "ds3231-$mcu" \
--compile-commands "build/$mcu-generated/compile_commands.json" \
--log "build/as-$mcu.log"
done
```
One reference describes one part, hence `--project`. Release is what the gate
compares, the presets defining no debug build; Debug carries the `-Og
-gdwarf-4` pair libavr's own debug preset uses.
Differences from legacy: weekday-rate alarms now actually set the DY bit
(the old `setAlarmHelper` always cleared it), reads/writes are single
coherent bus transactions, and errors are reported instead of ignored.