aboutsummaryrefslogtreecommitdiff
path: root/src/timer.spec.ts
diff options
context:
space:
mode:
authorUri Shaked2019-11-21 17:09:40 +0200
committerUri Shaked2019-11-21 17:11:02 +0200
commitca96ec1ab43979e75c8a551e2aaddda8ad4b9e06 (patch)
tree6b591d80de7e00e1889b77f8fbad1eb1e493877c /src/timer.spec.ts
parentfix: typescript errors on TS < 3.7 (diff)
downloadavr8js-ca96ec1ab43979e75c8a551e2aaddda8ad4b9e06.tar.gz
avr8js-ca96ec1ab43979e75c8a551e2aaddda8ad4b9e06.tar.bz2
avr8js-ca96ec1ab43979e75c8a551e2aaddda8ad4b9e06.zip
feat: initial timer implementation
8-bit timers basic functionality + tests: 1. basic counting + prescaler 2. timer overflow 3. timer overflow interrupt
Diffstat (limited to 'src/timer.spec.ts')
-rw-r--r--src/timer.spec.ts84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/timer.spec.ts b/src/timer.spec.ts
new file mode 100644
index 0000000..b7d96a9
--- /dev/null
+++ b/src/timer.spec.ts
@@ -0,0 +1,84 @@
+import { CPU } from './cpu';
+import { AVRTimer, timer0Config } from './timer';
+
+describe('timer', () => {
+ let cpu: CPU;
+
+ beforeEach(() => {
+ cpu = new CPU(new Uint16Array(0x1000));
+ });
+
+ it('should update timer every tick when prescaler is 1', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x45] = 0x1; // TCCR0B.CS <- 1
+ cpu.cycles = 1;
+ timer.tick();
+ expect(cpu.data[0x46]).toEqual(1); // TCNT should be 1
+ });
+
+ it('should update timer every 64 ticks when prescaler is 3', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x45] = 0x3; // TCCR0B.CS <- 3
+ cpu.cycles = 64;
+ timer.tick();
+ expect(cpu.data[0x46]).toEqual(1); // TCNT should be 1
+ });
+
+ it('should not update timer if it has been disabled', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x45] = 0; // TCCR0B.CS <- 0
+ cpu.cycles = 100000;
+ timer.tick();
+ expect(cpu.data[0x46]).toEqual(0); // TCNT should stay 0
+ });
+
+ it('should set TOV if timer overflows', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x46] = 0xff; // TCNT0 <- 0xff
+ cpu.data[0x45] = 0x1; // TCCR0B.CS <- 1
+ cpu.cycles = 1;
+ timer.tick();
+ expect(cpu.data[0x46]).toEqual(0); // TCNT should be 0
+ expect(cpu.data[0x35]).toEqual(1); // TOV bit in TIFR
+ });
+
+ it('should generate an overflow interrupt if timer overflows and interrupts enabled', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x46] = 0xff; // TCNT0 <- 0xff
+ cpu.data[0x45] = 0x1; // TCCR0B.CS <- 1
+ cpu.data[0x6e] = 0x1; // TIMSK0: TOIE0
+ cpu.data[95] = 0x80; // SREG: I-------
+ cpu.cycles = 1;
+ timer.tick();
+ expect(cpu.data[0x46]).toEqual(0); // TCNT should be 0
+ expect(cpu.data[0x35]).toEqual(0); // TOV bit in TIFR should be clear
+ expect(cpu.pc).toEqual(0x20);
+ expect(cpu.cycles).toEqual(3);
+ });
+
+ it('should not generate an overflow interrupt when global interrupts disabled', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x46] = 0xff; // TCNT0 <- 0xff
+ cpu.data[0x45] = 0x1; // TCCR0B.CS <- 1
+ cpu.data[0x6e] = 0x1; // TIMSK0: TOIE0
+ cpu.data[95] = 0x0; // SREG: --------
+ cpu.cycles = 1;
+ timer.tick();
+ expect(cpu.data[0x35]).toEqual(1); // TOV bit in TIFR should be set
+ expect(cpu.pc).toEqual(0);
+ expect(cpu.cycles).toEqual(1);
+ });
+
+ it('should not generate an overflow interrupt when TOIE0 is clear', () => {
+ const timer = new AVRTimer(cpu, timer0Config);
+ cpu.data[0x46] = 0xff; // TCNT0 <- 0xff
+ cpu.data[0x45] = 0x1; // TCCR0B.CS <- 1
+ cpu.data[0x6e] = 0; // TIMSK0: clear
+ cpu.data[95] = 0x80; // SREG: I-------
+ cpu.cycles = 1;
+ timer.tick();
+ expect(cpu.data[0x35]).toEqual(1); // TOV bit in TIFR should be set
+ expect(cpu.pc).toEqual(0);
+ expect(cpu.cycles).toEqual(1);
+ });
+});