Ocean-240.2-Emulator/okean240/tmr8253.go
2026-03-04 23:57:39 +03:00

153 lines
2.9 KiB
Go

package okean240
/*
Timer config byte: [sc1:0][rl1:0][m2:0][bcd]
sc1:0 - timer No
rl=01-LSB, 10-MSB, 11-LSB+MSB
mode 000 - intr on fin,
001 - one shot,
x10 - rate gen,
x11 - sq wave
*/
// Timer work modes
const (
TimerModeIntOnFin = iota
TimerModeOneShot
TimerModeRateGen
TimerModeSqWave
)
// Timer load counter modes
const (
TimerRLMsbLsb = iota
TimerRLLsb
TimerRLMsb
TimerRLLsbMsb
)
type Timer8253Ch struct {
rl byte // load mode
mode byte // counter mode
bcd bool // decimal/BCD load mode
load uint16 // value to count from
counter uint16 // timer counter
fb bool // first byte load flag
started bool // true if timer started
fired bool
}
type Timer8253 struct {
//chNo byte
channel [3]Timer8253Ch
}
type Timer8253Interface interface {
//Init()
Configure(value byte)
Load(chNo int, value byte)
Counter(chNo int) uint16
Fired(chNo int) bool
Start(chNo int) bool
}
func NewTimer8253() *Timer8253 {
return &Timer8253{
//chNo: 0,
channel: [3]Timer8253Ch{
{0, 0, false, 0, 0, true, false, false},
{0, 0, false, 0, 0, true, false, false},
{0, 0, false, 0, 0, true, false, false},
},
}
}
func (t *Timer8253) Tick(chNo int) {
tmr := &t.channel[chNo]
if tmr.started {
tmr.counter--
if tmr.counter == 0 {
switch tmr.mode {
case TimerModeIntOnFin:
{
tmr.started = false
tmr.fired = true
}
case TimerModeOneShot:
tmr.started = false
case TimerModeRateGen:
tmr.started = false
case TimerModeSqWave:
{
tmr.started = true
tmr.counter = tmr.load
tmr.fired = true
}
}
}
}
}
func (t *Timer8253) Counter(chNo int) uint16 {
return t.channel[chNo].counter
}
func (t *Timer8253) Fired(chNo int) bool {
f := t.channel[chNo].fired
if f {
t.channel[chNo].fired = false
}
return f
}
func (t *Timer8253) Start(chNo int) bool {
return t.channel[chNo].started
}
func (t *Timer8253) Configure(value byte) {
chNo := (value & 0xC0) >> 6
rl := value & 0x30 >> 4
t.channel[chNo].started = false
t.channel[chNo].rl = rl
t.channel[chNo].mode = (value & 0x0E) >> 1
t.channel[chNo].fb = true
t.channel[chNo].bcd = value&0x01 == 1
t.channel[chNo].load = 0
}
func (t *Timer8253) Load(chNo byte, value byte) {
timer := &t.channel[chNo]
switch timer.rl {
case TimerRLMsbLsb:
// MSB+LSB
if timer.fb {
// MSB
timer.load = uint16(value) << 8
timer.fb = false
} else {
// LSB
timer.load |= uint16(value)
timer.started = true
}
case TimerRLLsb:
// LSB Only
timer.load = (timer.load & 0xff00) | uint16(value)
timer.started = true
case TimerRLMsb:
// MSB Only
timer.load = (timer.load & 0x00ff) | (uint16(value) << 8)
timer.started = true
case TimerRLLsbMsb:
// LSB+MSB
if timer.fb {
// LSB
timer.load = uint16(value)
timer.fb = false
} else {
// MSB
timer.load = (uint16(value) << 8) | (timer.load & 0x00ff)
timer.started = true
timer.counter = timer.load
}
}
}