Skip to content

Commit

Permalink
feat: Support for simulating ATtinyx5 (e.g. ATtiny85) timers #64
Browse files Browse the repository at this point in the history
close #64
  • Loading branch information
urish committed Nov 14, 2020
1 parent e11bb93 commit 0e4e8de
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 12 deletions.
27 changes: 27 additions & 0 deletions src/peripherals/timer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,33 @@ describe('timer', () => {
expect(cpu.cycles).toEqual(3);
});

it('should support overriding TIFR/TOV and TIMSK/TOIE bits (issue #64)', () => {
const cpu = new CPU(new Uint16Array(0x1000));
const timer = new AVRTimer(cpu, {
...timer0Config,

// The following values correspond ATtiny85 config:
TOV: 2,
OCFA: 2,
OCFB: 8,
TOIE: 2,
OCIEA: 16,
OCIEB: 8,
});
cpu.writeData(TCNT0, 0xff);
cpu.writeData(TCCR0B, CS00); // Set prescaler to 1
timer.tick();
cpu.data[TIMSK0] = 2;
cpu.data[SREG] = 0x80; // SREG: I-------
cpu.cycles = 1;
timer.tick();
const tcnt = cpu.readData(TCNT0);
expect(tcnt).toEqual(2); // TCNT should be 2 (one tick above + 2 cycles for interrupt)
expect(cpu.data[TIFR0] & 2).toEqual(0);
expect(cpu.pc).toEqual(0x20);
expect(cpu.cycles).toEqual(3);
});

it('should not generate an overflow interrupt when global interrupts disabled', () => {
const cpu = new CPU(new Uint16Array(0x1000));
const timer = new AVRTimer(cpu, timer0Config);
Expand Down
45 changes: 33 additions & 12 deletions src/peripherals/timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ const timer01Dividers = {
7: 0, // TODO: External clock source on T0 pin. Clock on rising edge.
};

const TOV = 1;
const OCFA = 2;
const OCFB = 4;

const TOIE = 1;
const OCIEA = 2;
const OCIEB = 4;

type u8 = number;
type u16 = number;

Expand All @@ -45,6 +37,9 @@ interface TimerDividers {

export interface AVRTimerConfig {
bits: 8 | 16;
dividers: TimerDividers;

// Interrupt vectors
captureInterrupt: u8;
compAInterrupt: u8;
compBInterrupt: u8;
Expand All @@ -61,7 +56,15 @@ export interface AVRTimerConfig {
TCCRC: u8;
TIMSK: u8;

dividers: TimerDividers;
// TIFR bits
TOV: u8;
OCFA: u8;
OCFB: u8;

// TIMSK bits
TOIE: u8;
OCIEA: u8;
OCIEB: u8;

// Output compare pins
compPortA: u16;
Expand All @@ -70,6 +73,19 @@ export interface AVRTimerConfig {
compPinB: u8;
}

/** These are differnet for some devices (e.g. ATtiny85) */
const defaultTimerBits = {
// TIFR bits
TOV: 1,
OCFA: 2,
OCFB: 4,

// TIMSK bits
TOIE: 1,
OCIEA: 2,
OCIEB: 4,
};

export const timer0Config: AVRTimerConfig = {
bits: 8,
captureInterrupt: 0, // not available
Expand All @@ -90,6 +106,7 @@ export const timer0Config: AVRTimerConfig = {
compPinA: 6,
compPortB: portDConfig.PORT,
compPinB: 5,
...defaultTimerBits,
};

export const timer1Config: AVRTimerConfig = {
Expand All @@ -112,6 +129,7 @@ export const timer1Config: AVRTimerConfig = {
compPinA: 1,
compPortB: portBConfig.PORT,
compPinB: 2,
...defaultTimerBits,
};

export const timer2Config: AVRTimerConfig = {
Expand Down Expand Up @@ -143,6 +161,7 @@ export const timer2Config: AVRTimerConfig = {
compPinA: 3,
compPortB: portDConfig.PORT,
compPinB: 3,
...defaultTimerBits,
};

/* All the following types and constants are related to WGM (Waveform Generation Mode) bits: */
Expand Down Expand Up @@ -365,12 +384,13 @@ export class AVRTimer {
this.timerUpdated();
}
if ((timerMode === TimerMode.Normal || timerMode === TimerMode.FastPWM) && val > newVal) {
this.TIFR |= TOV;
this.TIFR |= this.config.TOV;
}
}
this.tcntUpdated = false;
if (this.cpu.interruptsEnabled && this.pendingInterrupt) {
const { TIFR, TIMSK } = this;
const { TOV, OCFA, OCFB, TOIE, OCIEA, OCIEB } = this.config;
if (TIFR & TOV && TIMSK & TOIE) {
avrInterrupt(this.cpu, this.config.ovfInterrupt);
this.TIFR &= ~TOV;
Expand Down Expand Up @@ -398,7 +418,7 @@ export class AVRTimer {
value--;
if (!value && !this.tcntUpdated) {
this.countingUp = true;
this.TIFR |= TOV;
this.TIFR |= this.config.TOV;
}
}
delta--;
Expand All @@ -410,6 +430,7 @@ export class AVRTimer {
const value = this.tcnt;

if (this.ocrA && value === this.ocrA) {
const { TOV, OCFA } = this.config;
this.TIFR |= OCFA;
if (this.timerMode === TimerMode.CTC) {
// Clear Timer on Compare Match (CTC) Mode
Expand All @@ -421,7 +442,7 @@ export class AVRTimer {
}
}
if (this.ocrB && value === this.ocrB) {
this.TIFR |= OCFB;
this.TIFR |= this.config.OCFB;
if (this.compB) {
this.updateCompPin(this.compB, 'B');
}
Expand Down

0 comments on commit 0e4e8de

Please sign in to comment.