aboutsummaryrefslogtreecommitdiff
path: root/src/peripherals/timer.ts
diff options
context:
space:
mode:
authorUri Shaked2020-04-28 23:42:20 +0300
committerUri Shaked2020-04-28 23:42:20 +0300
commitf16d9f9f48fb5e74ab10fe79a8206223342d5010 (patch)
tree0ae771f977ce51e1d34ab7f79cd6a31d918bfd12 /src/peripherals/timer.ts
parentchore: release 0.8.2 (diff)
downloadavr8js-f16d9f9f48fb5e74ab10fe79a8206223342d5010.tar.gz
avr8js-f16d9f9f48fb5e74ab10fe79a8206223342d5010.tar.bz2
avr8js-f16d9f9f48fb5e74ab10fe79a8206223342d5010.zip
fix(timer): incorrect high counter byte behavior
According to the datasheet, the value of the high byte of the counter for 16-bit timers (such as timer 1) is only updated when the low byte is being read/written. close #37
Diffstat (limited to '')
-rw-r--r--src/peripherals/timer.ts42
1 files changed, 19 insertions, 23 deletions
diff --git a/src/peripherals/timer.ts b/src/peripherals/timer.ts
index ebd7b58..04c09aa 100644
--- a/src/peripherals/timer.ts
+++ b/src/peripherals/timer.ts
@@ -191,16 +191,24 @@ export class AVRTimer {
private ocrB: u16 = 0;
private timerMode: TimerMode;
private topValue: TimerTopValue;
+ private tcnt: u16 = 0;
private tcntUpdated = false;
constructor(private cpu: CPU, private config: AVRTimerConfig) {
this.updateWGMConfig();
- this.registerHook(config.TCNT, (value: u16) => {
- this.TCNT = value;
+ this.cpu.readHooks[config.TCNT] = (addr: u8) => {
+ if (this.config.bits === 16) {
+ this.cpu.data[addr + 1] = this.tcnt >> 8;
+ }
+ return (this.cpu.data[addr] = this.tcnt & 0xff);
+ };
+
+ this.cpu.writeHooks[config.TCNT] = (value: u8) => {
+ const highByte = this.config.bits === 16 ? this.cpu.data[config.TCNT + 1] : 0;
+ this.tcnt = (highByte << 8) | value;
this.tcntUpdated = true;
- this.timerUpdated(value);
- return true;
- });
+ this.timerUpdated();
+ };
this.registerHook(config.OCRA, (value: u16) => {
// TODO implement buffering when timer running in PWM mode
this.ocrA = value;
@@ -234,19 +242,6 @@ export class AVRTimer {
this.cpu.data[this.config.TIFR] = value;
}
- get TCNT() {
- return this.config.bits === 16
- ? this.cpu.dataView.getUint16(this.config.TCNT, true)
- : this.cpu.data[this.config.TCNT];
- }
-
- set TCNT(value: u16) {
- this.cpu.data[this.config.TCNT] = value & 0xff;
- if (this.config.bits === 16) {
- this.cpu.data[this.config.TCNT + 1] = (value >> 8) & 0xff;
- }
- }
-
get TCCRA() {
return this.cpu.data[this.config.TCCRA];
}
@@ -306,12 +301,12 @@ export class AVRTimer {
if (divider && delta >= divider) {
const counterDelta = Math.floor(delta / divider);
this.lastCycle += counterDelta * divider;
- const val = this.TCNT;
+ const val = this.tcnt;
const newVal = (val + counterDelta) % (this.TOP + 1);
// A CPU write overrides (has priority over) all counter clear or count operations.
if (!this.tcntUpdated) {
- this.TCNT = newVal;
- this.timerUpdated(newVal);
+ this.tcnt = newVal;
+ this.timerUpdated();
}
const { timerMode } = this;
if (
@@ -341,12 +336,13 @@ export class AVRTimer {
}
}
- private timerUpdated(value: u8) {
+ private timerUpdated() {
+ const value = this.tcnt;
if (this.ocrA && value === this.ocrA) {
this.TIFR |= OCFA;
if (this.timerMode === TimerMode.CTC) {
// Clear Timer on Compare Match (CTC) Mode
- this.TCNT = 0;
+ this.tcnt = 0;
this.TIFR |= TOV;
}
}