jeol-t330a/modules/ph00524/emu/i8255.go

103 lines
1.6 KiB
Go
Raw Normal View History

2024-08-16 10:31:59 +00:00
package main
import "log"
// i8255 is a generic Intel 8255-compatible I/O controller chip.
//
// Only mode 0 is supported.
type i8255 struct {
pa, pb, pc uint8
onOut func(port i8255Port)
onIn func(port i8255Port)
}
type i8255Port string
const (
PA i8255Port = "PA"
PB i8255Port = "PB"
PC i8255Port = "PC"
)
func (i *i8255) getPort(p i8255Port) uint8 {
switch p {
case PA:
return i.pa
case PB:
return i.pb
case PC:
return i.pc
default:
log.Fatalf("invalid port")
return 0
}
}
func (i *i8255) Out(addr, value uint8) {
switch addr {
case 0:
i.pa = value
if i.onOut != nil {
i.onOut(PA)
}
case 1:
i.pb = value
if i.onOut != nil {
i.onOut(PB)
}
case 2:
i.pc = value
if i.onOut != nil {
i.onOut(PC)
}
case 3:
if (value >> 7) == 0 {
// BSR mode
bitno := (value >> 1) & 0b111
bitval := value & 1
if bitval == 1 {
i.pc |= (1 << bitno)
} else {
i.pc &= 0xff ^ (1 << bitno)
}
} else {
// Input/Output mode
gaMode := (value >> 5) & 0b11
gbMode := (value >> 5) & 0b11
if gaMode != 0 {
log.Fatalf("I8255 implementation only supports mode 0 on Port A")
}
if gbMode != 0 {
log.Fatalf("I8255 implementation only supports mode 0 on Port B")
}
// Don't care about the rest (input/output settings per group/port).
}
default:
log.Printf("I8255: invalid out")
}
}
func (i *i8255) In(addr uint8) uint8 {
switch addr {
case 0:
if i.onIn != nil {
i.onIn(PA)
}
return i.pa
case 1:
if i.onIn != nil {
i.onIn(PB)
}
return i.pb
case 2:
if i.onIn != nil {
i.onIn(PC)
}
return i.pc
default:
log.Printf("I8255: invalid in")
return 0
}
}