Custom board configurations#

The board presets (ArduinoUnoSimulation, etc.) cover the most common cases, but any AVR 8-bit device can be modelled because all peripheral register addresses are fully configurable.

Using AvrTestSimulation directly#

using Avr8Sharp.TestKit;

var sim = AvrTestSimulation.Create(flashSize: 0x4000, sramBytes: 256)
    .WithFrequency(8_000_000)
    .WithHex(hex)
    .AddGpio(myPortConfig, out var portA)
    .AddTimer(myTimer0Config, out var timer0)
    .AddUsart(myUsartConfig, out var serial);

Peripheral configs#

Each peripheral accepts a config struct that maps it to the correct registers for your target chip.

GPIO port#

var portConfig = new AvrPortConfig(
    pin: 0x09, ddr: 0x0A, port: 0x0B,
    pinChange: new AvrPinChangeInterrupt(...),
    externalInterrupts: [...]);

Timer#

Timers are configured with AvrTimerConfig, which takes the register addresses, interrupt vectors (as word addresses), comparator pins, and prescaler table:

var timerConfig = new AvrTimerConfig(
    bits: 8,
    dividers: AvrTimer.Timer01Dividers,
    overflowInterrupt:    0x12,
    comparatorAInterrupt: 0x14,
    ...
    tccra: 0x44, tccrb: 0x45,
    tcnt:  0x46, ocra:  0x47, ...);

For chips that share a single TCCR register (e.g. ATtiny85 TC1), map tccra to an unused address (e.g. R0 = 0x00 which reads as 0 in well-behaved code) and tccrb to the real register — see ATtiny85Simulation for a worked example.

USART#

var usartConfig = new AvrUsartConfig(
    rxCompleteInterrupt: 0x26,
    dataRegisterEmptyInterrupt: 0x28,
    txCompleteInterrupt: 0x2A,
    udr: 0xC6, ucsra: 0xC0, ucsrb: 0xC1, ucsrc: 0xC2,
    ubrrl: 0xC4, ubrrh: 0xC5);

EEPROM#

var eepromConfig = new AvrEepromConfig(
    eepromReadyInterrupt: 0x2C,   // word address of EE_RDY vector
    eecr: 0x3F, eedr: 0x40, eearl: 0x41, eearh: 0x42,
    eraseCycles: 28800, writeCycles: 28800);

sim.AddEeprom(eepromConfig, eepromSize: 1024);

Creating a reusable preset#

Subclass AvrTestSimulation to create a reusable board class:

public sealed class ATmega32Simulation : AvrTestSimulation
{
    private const int Flash = 0x8000;
    private const int Sram  = 2048;

    public AvrIoPort PortA { get; }
    public AvrIoPort PortB { get; }
    public SerialProbe Serial { get; }

    public ATmega32Simulation() : base(Flash, Sram)
    {
        WithFrequency(16_000_000);
        AddGpio(PortAConfig, out var a); PortA = a;
        AddGpio(AvrIoPort.PortBConfig, out var b); PortB = b;
        AddUsart(AvrUsart.Usart0Config, out var serial); Serial = serial;
    }

    // ... define PortAConfig from the ATmega32 datasheet
}