Interrupt based time. Adjust tick cost when timer-0 is reconfigured (the time precision affected when timer-0 reconfigured). Keep all time in nanoseconds.

Interrupt based time. Adjust tick cost every 1 minute and when timer-0 is reconfigured (the time precision affected when timer-0 reconfigured). Keep all time in nanoseconds.
This commit is contained in:
Dmitriy
2021-12-23 22:05:21 -05:00
committed by Ron Evans
parent d0633f6228
commit 92150bd1c5
5 changed files with 141 additions and 17 deletions
+6
View File
@@ -179,6 +179,9 @@ func (pwm PWM) Configure(config PWMConfig) error {
avr.TCCR0B.Set(prescaler)
// Set the PWM mode to fast PWM (mode = 3).
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
// monotonic timer is using the same time as PWM:0
// we must adust internal settings of monotonic timer when PWM:0 settings changed
AdjustMonotonicTimer()
} else {
avr.TCCR2B.Set(prescaler)
// Set the PWM mode to fast PWM (mode = 3).
@@ -714,6 +717,9 @@ func (pwm PWM) Set(channel uint8, value uint32) {
avr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)
}
}
// monotonic timer is using the same time as PWM:0
// we must adust internal settings of monotonic timer when PWM:0 settings changed
AdjustMonotonicTimer()
case 1:
mask := interrupt.Disable()
switch channel {
+6
View File
@@ -69,6 +69,9 @@ func (pwm PWM) Configure(config PWMConfig) error {
avr.TCCR0B.Set(prescaler)
// Set the PWM mode to fast PWM (mode = 3).
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
// monotonic timer is using the same time as PWM:0
// we must adust internal settings of monotonic timer when PWM:0 settings changed
AdjustMonotonicTimer()
} else {
avr.TCCR2B.Set(prescaler)
// Set the PWM mode to fast PWM (mode = 3).
@@ -395,6 +398,9 @@ func (pwm PWM) Set(channel uint8, value uint32) {
avr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)
}
}
// monotonic timer is using the same time as PWM:0
// we must adust internal settings of monotonic timer when PWM:0 settings changed
AdjustMonotonicTimer()
case 1:
mask := interrupt.Disable()
switch channel {
+74
View File
@@ -4,6 +4,7 @@ package machine
import (
"device/avr"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
)
@@ -142,3 +143,76 @@ func (a ADC) Get() uint16 {
return uint16(avr.ADCL.Get()) | uint16(avr.ADCH.Get())<<8
}
var Ticks int64 // nanoseconds since start
var tickNanos int64 // nanoseconds per each tick
func InitMonotonicTimer() {
tickNanos = 0
Ticks = 0
interrupt.New(avr.IRQ_TIMER0_OVF, func(i interrupt.Interrupt) {
Ticks += tickNanos
})
// initial initialization of the Timer0
// - Mask interrupt
avr.TIMSK0.ClearBits(avr.TIMSK0_TOIE0 | avr.TIMSK0_OCIE0A | avr.TIMSK0_OCIE0B)
// - Write new values to TCNT2, OCR2x, and TCCR2x.
avr.TCNT0.Set(0)
avr.OCR0A.Set(0xff)
// - Set mode 3
avr.TCCR0A.Set(avr.TCCR0A_WGM00 | avr.TCCR0A_WGM01)
// - Set prescaler 1
avr.TCCR0B.Set(avr.TCCR0B_CS00)
AdjustMonotonicTimer()
// - Unmask interrupt
avr.TIMSK0.SetBits(avr.TIMSK0_TOIE0)
}
func AdjustMonotonicTimer() {
// adjust the tickNanos
tickNanos = currentTickNanos()
}
func currentTickNanos() int64 {
// this time depends on clk_IO, prescale, mode and OCR0A
// assuming the clock source is CPU clock
prescaler := int64(avr.TCCR0B.Get() & 0x7)
clock := (int64(1e12) / prescaler) / int64(CPUFrequency())
mode := avr.TCCR0A.Get() & 0x7
/*
Mode WGM02 WGM01 WGM00 Timer/Counter TOP Update of TOV Flag
Mode of Operation OCRx at Set on
0 0 0 0 Normal 0xFF Immediate MAX
1 0 0 1 PWM, Phase Correct 0xFF TOP BOTTOM
2 0 1 0 CTC OCRA Immediate MAX
3 0 1 1 Fast PWM 0xFF BOTTOM MAX
5 1 0 1 PWM, Phase Correct OCRA TOP BOTTOM
7 1 1 1 Fast PWM OCRA BOTTOM TOP
*/
switch mode {
case 0, 3:
// normal & fast PWM
// TOV0 Interrupt when moving from MAX (0xff) to 0x00
return clock * 256 / 1000
case 1:
// Phase Correct PWM
// TOV0 Interrupt when moving from MAX (0xff) to 0x00
return clock * 256 * 2 / 1000
case 2, 7:
// CTC & fast PWM
// TOV0 Interrupt when moving from MAX (OCRA) to 0x00
return clock * int64(avr.OCR0A.Get()) / 1000
case 5:
// Phase Correct PWM
// TOV0 Interrupt when moving from MAX (OCRA) to 0x00
return clock * int64(avr.OCR0A.Get()) * 2 / 1000
}
return clock / 1000 // for unknown
}