Skip to content

feat(emulator): add the ATtiny85 MCU profile (P6.2) - #334

Merged
ttbombadil merged 2 commits into
feature/browser-emulationfrom
feat/p6-2-attiny85-profile
Oct 24, 2026
Merged

ttbombadil merged 2 commits into
feature/browser-emulationfrom
feat/p6-2-attiny85-profile

Conversation

@ttbombadil

Copy link
Copy Markdown
Collaborator

Paket

P6.2 MCU-Profil ATtiny85 (L). Basis ist feature/browser-emulation (alle Vorgänger gemergt).

Umgesetzt

packages/avr-emulator/src/mcu/attiny85.ts, exportiert als ATTINY85. Grundlage sind Spike P0.5 und avr/iotnx5.h; die Adressen sind I/O-Adressen + 0x20, die Vektoren haben je ein Wort (Vektor n an Wortadresse n).

  • Speicher: 8 KiB Flash, 512 B SRAM ab 0x60, RAMEND 0x25F, 512 B EEPROM.
  • Port B: INT0 an PB2 (ISC in MCUCR), PCINT0 an PB0–PB5.
  • Timer 0 mit eigenen Registern und Vektoren: OC0A an PB0, OC0B an PB1, T0 an PB2.
  • Timer 1: ATtinyTimer1 von avr8js.
  • ADC: 4 Kanäle (ADC0–3 an PB5, PB2, PB4, PB3); Referenzen VCC, AREF, 1,1 V und 2,56 V. REFS2 liest das Profil selbst an Bit 4.
  • EEPROM mit Schreibzeiten für 8 MHz (je 1,8 ms Löschen und Schreiben); avr8js setzt sie für 16 MHz.
  • Watchdog (WDTCR, MCUSR, Vektor 12) und Taktteiler (CLKPR 0x46).
  • Kein USART: Serial ist ein Software-UART (P6.3).
  • McuPeripherals.timers darf jetzt auch den ATtiny-Timer 1 enthalten (Index = Timernummer).

Funde in avr8js 0.21.1 (README des Pakets, Abschnitt „corrections and known differences“):

  1. REFS2 an Bit 3 statt 4: bekannt aus dem Spike, im Profil korrigiert.
  2. GIMSK/GIFR geteilt: INT0 und PCINT nutzen auf dem ATtiny85 dieselben Register. avr8js verdrahtet GIMSK nur für INT0 und GIFR nur für PCINT. Ein Schreiben von PCIE löste deshalb einen anstehenden Pin-Change nicht aus, und eine 1 in INTF0 löschte INT0 nicht. Im Profil korrigiert: Es umhüllt beide Hooks.
  3. Timer-1-PWM (offen): ATtinyTimer1 rechnet den PWM-Modus phasenkorrekt und erzeugt bei gesetztem CTC1 kein Signal an OC1x. Genau so konfiguriert ATTinyCore analogWrite an PB1/PB4. Die Register stimmen, und das Tastverhältnis in UnoSim kommt aus ihnen (P1.5). Ein Sketch, der den Pegel eines Timer-1-PWM-Pins liest, sieht dagegen LOW.

Tests: tests/attiny85-profile.test.ts mit 13 Fällen und drei ATTinyCore-Fixtures (attiny85-tiny_probe, tiny_interrupts, tiny_watchdog). Die Sketches legen ihre Ergebnisse im EEPROM ab, damit der Test ohne Software-UART-Decoder auskommt. Geprüft werden:

  • Speicher, Peripherie, delay(587);
  • ADC mit drei Referenzen: 512, 465 und 200 (mit avr8js allein 102);
  • Timer-1-Register, Timer-0-Fast-PWM-Tastverhältnis;
  • INT0 (nur steigende Flanken), PCINT (jede Flanke) und beide Korrekturen an GIMSK/GIFR auf Registerebene;
  • Watchdog-Reset mit WDRF, EEPROM-Schreibzeit.

Abnahmeevidenz

  • npm run test:unit: App 3562 Tests, Emulator 648 Tests (7 s von 45 s).
  • check, lint, knip und check:docs grün; Pre-Push mit Sonar grün (S1848 und S5906 behoben).

Abweichungen vom Plan

  • Spanne für delay(587): Der Spike nannte 586–588 ms, das war zu eng. millis() springt nur beim Überlauf von Timer 0 (alle 2,048 ms), daher hinkt jede Ablesung bis zu 2,048 ms hinterher. Abgeleitet ergeben sich 585–589 ms, gemessen wurden 585.
  • Registrierung: Das Profil ist noch nicht in mcuProfile registriert. Der bestehende Test packages/avr-emulator/tests/atmega328p-boards.test.ts:39–41 schreibt fest, dass der ATtiny85 noch kein Profil und keine Board-Hardware hat. Ihn zu ändern liegt außerhalb der Freigabe. Die Registrierung kommt mit der Board-Hardware (P6.4); dazu stelle ich die Frage gesondert.

Geänderte bestehende Tests

Keine.

Für Menschen

Die Meldungen der drei Funde an avr8js (wokwi/avr8js) sind nach außen gerichtet und gehören einem Menschen. Plan P6.2 sieht das für REFS2 bereits vor.

🤖 Generated with Claude Code

ttbombadil and others added 2 commits October 23, 2026 19:57
Port B with INT0 and PCINT0, timer 0 with its own registers and one-word
vectors, the ATtiny timer 1, a four-channel ADC that reads REFS2 at bit 4,
EEPROM timed for 8 MHz, watchdog and clock prescaler. INT0 and the pin-change
interrupt share GIMSK and GIFR, which avr8js wires for one of them only; the
profile wraps both hooks. Registered with the board hardware in P6.4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant