i6502/acia6551.go

177 lines
2.8 KiB
Go
Raw Normal View History

2014-08-17 14:49:22 +00:00
package i6502
2014-08-17 15:18:14 +00:00
const (
aciaData = iota
aciaStatus
aciaCommand
aciaControl
)
2014-08-17 14:49:22 +00:00
/*
ACIA 6551 Serial IO
2014-08-18 14:37:51 +00:00
This Asynchronous Communications Interface Adapater can be
directly attached to the 6502's address and data busses.
It provides serial IO.
The supplied Rx and Tx channels can be used to read and wirte
data to the ACIA 6551.
2014-08-17 14:49:22 +00:00
*/
type Acia6551 struct {
2014-08-19 14:40:31 +00:00
rx byte
tx byte
2014-08-17 20:36:01 +00:00
2014-08-17 15:18:14 +00:00
commandData byte
controlData byte
rxFull bool
txEmpty bool
rxIrqEnabled bool
txIrqEnabled bool
2014-08-17 20:36:01 +00:00
overrun bool
2014-08-29 11:49:08 +00:00
output chan []byte
2014-08-17 14:49:22 +00:00
}
2014-08-29 11:49:08 +00:00
func NewAcia6551(output chan []byte) (*Acia6551, error) {
acia := &Acia6551{output: output}
2014-08-17 15:18:14 +00:00
acia.Reset()
return acia, nil
2014-08-17 14:49:22 +00:00
}
2014-08-17 15:18:14 +00:00
func (a *Acia6551) Size() uint16 {
// We have a only 4 addresses, Data, Status, Command and Control
2014-08-17 14:49:22 +00:00
return 0x04
}
2014-08-17 20:36:01 +00:00
// Emulates a hardware reset
2014-08-17 15:18:14 +00:00
func (a *Acia6551) Reset() {
2014-08-19 14:40:31 +00:00
a.rx = 0
2014-08-17 15:18:14 +00:00
a.rxFull = false
2014-08-19 14:40:31 +00:00
a.tx = 0
2014-08-17 15:18:14 +00:00
a.txEmpty = true
a.rxIrqEnabled = false
a.txIrqEnabled = false
2014-08-17 20:36:01 +00:00
a.overrun = false
a.setControl(0)
a.setCommand(0)
2014-08-17 15:18:14 +00:00
}
2014-08-17 20:36:01 +00:00
func (a *Acia6551) setControl(data byte) {
2014-08-19 14:40:31 +00:00
a.controlData = data
2014-08-17 14:49:22 +00:00
}
2014-08-17 20:36:01 +00:00
func (a *Acia6551) setCommand(data byte) {
2014-08-19 14:40:31 +00:00
a.commandData = data
a.rxIrqEnabled = (data & 0x02) != 0
a.txIrqEnabled = ((data & 0x04) != 0) && ((data & 0x08) != 1)
}
func (a *Acia6551) statusRegister() byte {
status := byte(0)
if a.rxFull {
status |= 0x08
}
if a.txEmpty {
status |= 0x10
}
if a.overrun {
status |= 0x04
}
return status
}
// Implements io.Reader, for external programs to read TX'ed data from
// the serial output.
func (a *Acia6551) Read(p []byte) (n int, err error) {
2014-08-29 11:49:08 +00:00
if len(p) == 0 {
return 0, nil
}
if a.txEmpty {
return 0, nil
} else {
a.txEmpty = true
copy(p, []byte{a.tx})
// TODO: Handle txInterrupt
return 1, nil
}
2014-08-19 14:40:31 +00:00
}
// Implements io.Writer, for external programs to write to the
// ACIA's RX
func (a *Acia6551) Write(p []byte) (n int, err error) {
for _, b := range p {
a.rxWrite(b)
}
return len(p), nil
2014-08-17 20:36:01 +00:00
}
2014-08-18 14:37:51 +00:00
// Used by the AddressBus to read data from the ACIA 6551
2014-08-19 14:40:31 +00:00
func (a *Acia6551) ReadByte(address uint16) byte {
2014-08-17 20:36:01 +00:00
switch address {
case aciaData:
2014-08-19 14:40:31 +00:00
return a.rxRead()
2014-08-17 20:36:01 +00:00
case aciaStatus:
2014-08-19 14:40:31 +00:00
return a.statusRegister()
2014-08-17 20:36:01 +00:00
case aciaCommand:
2014-08-19 14:40:31 +00:00
return a.commandData
2014-08-17 20:36:01 +00:00
case aciaControl:
2014-08-19 14:40:31 +00:00
return a.controlData
2014-08-17 20:36:01 +00:00
}
return 0x00
}
2014-08-19 14:40:31 +00:00
// Used by the AddressBus to write data to the ACIA 6551
func (a *Acia6551) WriteByte(address uint16, data byte) {
2014-08-17 20:36:01 +00:00
switch address {
case aciaData:
2014-08-19 14:40:31 +00:00
a.txWrite(data)
2014-08-17 20:36:01 +00:00
case aciaStatus:
2014-08-19 14:40:31 +00:00
a.Reset()
2014-08-17 20:36:01 +00:00
case aciaCommand:
2014-08-19 14:40:31 +00:00
a.setCommand(data)
2014-08-17 20:36:01 +00:00
case aciaControl:
2014-08-19 14:40:31 +00:00
a.setControl(data)
2014-08-17 20:36:01 +00:00
}
2014-08-17 14:49:22 +00:00
}
2014-08-19 14:40:31 +00:00
func (a *Acia6551) rxRead() byte {
a.overrun = false
a.rxFull = false
return a.rx
}
func (a *Acia6551) rxWrite(data byte) {
// Oh no, overrun. Set the appropriate status
if a.rxFull {
a.overrun = true
}
a.rx = data
a.rxFull = true
// TODO: Interrupts
}
func (a *Acia6551) txWrite(data byte) {
2014-08-29 11:49:08 +00:00
a.output <- []byte{data}
2014-08-19 14:40:31 +00:00
a.tx = data
2014-08-29 11:49:08 +00:00
// a.txEmpty = false
2014-08-19 14:40:31 +00:00
}