Sample driver
package be.lmenten.avr.core.driver.eeprom;
import be.lmenten.avr.core.Core;
import be.lmenten.avr.core.analysis.AccessEvent;
import be.lmenten.avr.core.analysis.AccessEventListener;
import be.lmenten.avr.core.data.CoreData;
import be.lmenten.avr.core.data.CoreRegister;
import be.lmenten.avr.core.driver.DriverBase;
public class EepromDriver
extends DriverBase
implements AccessEventListener
{
private final CoreRegister EECR;
private final CoreRegister EEARL;
private final CoreRegister EEARH;
private final CoreRegister EEDR;
private final int interruptVector;
// ------------------------------------------------------------------------
private boolean writePending;
private int writeMode;
private double programmingTime;
private long ticksCount;
private long interruptsCount;
// ========================================================================
// = Constructor ==========================================================
// ========================================================================
public EepromDriver( Core core )
{
super( core );
EECR = core.getRegister( "EECR" );
EECR.addAccessListener( this );
EEARL = core.getRegister( "EEARL" );
EEARH = core.getRegister( "EEARH" );
EEDR = core.getRegister( "EEDR" );
interruptVector = core.getDescriptor().getInterruptVector( "EE_READY" );
}
// ========================================================================
// = Driver interface =====================================================
// ========================================================================
/**
* Returns a unique ID for this driver instance.
*/
@Override
public String getId()
{
return "Eeprom";
}
// ------------------------------------------------------------------------
/**
* Every time the core is reset, this method is called. Default values
* for I/O register is normal set by the core itself but may be set
* here.
*/
@Override
public void onReset()
{
writePending = false;
writeMode = 0b00;
programmingTime = 0.0d;
ticksCount = 0l;
interruptsCount = 0l;
}
/**
* After every instruction simulation, this method is called.
*/
@Override
public void onTick( long ticksCount )
{
// --------------------------------------------------------------------
// - Master write enable time out -------------------------------------
// --------------------------------------------------------------------
if( writePending )
{
if( ((ticksCount - this.ticksCount) > 4)
|| (core.getInterruptsCount() != this.interruptsCount) )
{
EECR.bit( "EEMPE" );
writePending = false;
}
return;
}
// --------------------------------------------------------------------
// - Simulate eeprom programming time ---------------------------------
// --------------------------------------------------------------------
if( EECR.bit( "EEPE" )
&& (ticksCount - this.ticksCount) >= core.tickToMillis( programmingTime ) )
{
EECR.bit( "EEPE", false );
if( EECR.bit("EEIE") )
{
core.interrupt( interruptVector );
}
}
}
// ========================================================================
// = AccessEventListener interface ========================================
// ========================================================================
/**
* EECR (control register) content has changed.
*/
@Override
public void onAccessEvent( AccessEvent event )
{
// --------------------------------------------------------------------
// - Eeprom read ------------------------------------------------------
// --------------------------------------------------------------------
if( EECR.bit( "EERE" ) )
{
int address = ((EEARH.getData() & 0xFF) << 8) | (EEARL.getData() & 0xFF);
CoreData data = core.getEepromCell( address );
EEDR.silentSetData( data.getData() );
core.updateClockCyclesCounter( 4l );
}
// --------------------------------------------------------------------
// - Eeprom write -----------------------------------------------------
// --------------------------------------------------------------------
else if( EECR.bit("EEMPE") && ! EECR.bit( "EEPE" ) )
{
writeMode = EECR.bits( "EEPM1", "EEPM0" );
writePending = true;
}
else if( writePending && EECR.bit("EEPE") )
{
int address = ((EEARH.getData() & 0xFF) << 8) | (EEARL.getData() & 0xFF);
CoreData data = core.getEepromCell( address );
switch( writeMode )
{
// ------------------------------------------------------------
case 0b00: // Atomic erase and write
programmingTime = 1.8d;
data.silentSetData( 0 );
case 0b10: // Write only
programmingTime += 1.8d;
data.silentSetData( EEDR.getData() );
writePending = false;
core.updateClockCyclesCounter( 2l );
break;
// ------------------------------------------------------------
case 0b01: // Erase only
programmingTime = 1.8d;
data.silentSetData( 0 );
writePending = false;
core.updateClockCyclesCounter( 2l );
break;
// ------------------------------------------------------------
case 0b11:
default:
throw new RuntimeException( "Invalid eeprom write mode" );
}
}
}
}