mirror of
https://github.com/tjboldt/Apple2-IO-RPi.git
synced 2024-06-08 04:29:32 +00:00
Add mock IO and initial tests
This commit is contained in:
parent
fb1f6f6deb
commit
9604c465da
|
@ -1,292 +1,16 @@
|
||||||
package a2io
|
package a2io
|
||||||
|
|
||||||
import (
|
type A2Io interface {
|
||||||
"bytes"
|
Init()
|
||||||
"errors"
|
WriteByte(data byte) error
|
||||||
"fmt"
|
WriteString(outString string) error
|
||||||
"time"
|
WriteBlock(buffer []byte) error
|
||||||
|
WriteBuffer(buffer []byte) error
|
||||||
"periph.io/x/periph/conn/gpio"
|
ReadByte() (byte, error)
|
||||||
"periph.io/x/periph/conn/gpio/gpioreg"
|
ReadString() (string, error)
|
||||||
"periph.io/x/periph/host"
|
ReadBlock(buffer []byte) error
|
||||||
)
|
|
||||||
|
|
||||||
var edgeTimeout time.Duration
|
|
||||||
|
|
||||||
var out_write gpio.PinIO
|
|
||||||
var out_read gpio.PinIO
|
|
||||||
var out_reserved2 gpio.PinIO
|
|
||||||
var out_reserved1 gpio.PinIO
|
|
||||||
var out_bit7 gpio.PinIO
|
|
||||||
var out_bit6 gpio.PinIO
|
|
||||||
var out_bit5 gpio.PinIO
|
|
||||||
var out_bit4 gpio.PinIO
|
|
||||||
var out_bit3 gpio.PinIO
|
|
||||||
var out_bit2 gpio.PinIO
|
|
||||||
var out_bit1 gpio.PinIO
|
|
||||||
var out_bit0 gpio.PinIO
|
|
||||||
var in_write gpio.PinIO
|
|
||||||
var in_read gpio.PinIO
|
|
||||||
var in_reserved2 gpio.PinIO
|
|
||||||
var in_reserved1 gpio.PinIO
|
|
||||||
var in_bit7 gpio.PinIO
|
|
||||||
var in_bit6 gpio.PinIO
|
|
||||||
var in_bit5 gpio.PinIO
|
|
||||||
var in_bit4 gpio.PinIO
|
|
||||||
var in_bit3 gpio.PinIO
|
|
||||||
var in_bit2 gpio.PinIO
|
|
||||||
var in_bit1 gpio.PinIO
|
|
||||||
var in_bit0 gpio.PinIO
|
|
||||||
|
|
||||||
func InitGpio() {
|
|
||||||
host.Init()
|
|
||||||
|
|
||||||
out_write = gpioreg.ByName("GPIO24")
|
|
||||||
out_read = gpioreg.ByName("GPIO25")
|
|
||||||
out_reserved2 = gpioreg.ByName("GPIO7") //note GPIO7 and CPIO8 require extra effort to use
|
|
||||||
out_reserved1 = gpioreg.ByName("GPIO8")
|
|
||||||
out_bit7 = gpioreg.ByName("GPIO5")
|
|
||||||
out_bit6 = gpioreg.ByName("GPIO11")
|
|
||||||
out_bit5 = gpioreg.ByName("GPIO9")
|
|
||||||
out_bit4 = gpioreg.ByName("GPIO10")
|
|
||||||
out_bit3 = gpioreg.ByName("GPIO22")
|
|
||||||
out_bit2 = gpioreg.ByName("GPIO27")
|
|
||||||
out_bit1 = gpioreg.ByName("GPIO17")
|
|
||||||
out_bit0 = gpioreg.ByName("GPIO4")
|
|
||||||
in_write = gpioreg.ByName("GPIO23")
|
|
||||||
in_read = gpioreg.ByName("GPIO18")
|
|
||||||
in_reserved2 = gpioreg.ByName("GPIO14")
|
|
||||||
in_reserved1 = gpioreg.ByName("GPIO15")
|
|
||||||
in_bit7 = gpioreg.ByName("GPIO12")
|
|
||||||
in_bit6 = gpioreg.ByName("GPIO16")
|
|
||||||
in_bit5 = gpioreg.ByName("GPIO20")
|
|
||||||
in_bit4 = gpioreg.ByName("GPIO21")
|
|
||||||
in_bit3 = gpioreg.ByName("GPIO26")
|
|
||||||
in_bit2 = gpioreg.ByName("GPIO19")
|
|
||||||
in_bit1 = gpioreg.ByName("GPIO13")
|
|
||||||
in_bit0 = gpioreg.ByName("GPIO6")
|
|
||||||
|
|
||||||
in_write.In(gpio.PullDown, gpio.BothEdges)
|
|
||||||
in_read.In(gpio.PullDown, gpio.BothEdges)
|
|
||||||
out_reserved1.Out(gpio.High)
|
|
||||||
out_reserved2.Out(gpio.High)
|
|
||||||
out_read.Out(gpio.High)
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
out_bit7.Out(gpio.Low)
|
|
||||||
out_bit6.Out(gpio.Low)
|
|
||||||
out_bit5.Out(gpio.Low)
|
|
||||||
out_bit4.Out(gpio.Low)
|
|
||||||
out_bit3.Out(gpio.Low)
|
|
||||||
out_bit2.Out(gpio.Low)
|
|
||||||
out_bit1.Out(gpio.Low)
|
|
||||||
out_bit0.Out(gpio.Low)
|
|
||||||
|
|
||||||
edgeTimeout = time.Second
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadString() (string, error) {
|
type A2Comm struct {
|
||||||
var inBytes bytes.Buffer
|
A2Io A2Io
|
||||||
for {
|
|
||||||
inByte, err := ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if inByte == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
inBytes.WriteByte(inByte)
|
|
||||||
}
|
|
||||||
return string(inBytes.Bytes()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteString(outString string) error {
|
|
||||||
for _, character := range outString {
|
|
||||||
err := WriteByte(byte(character) | 128)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to write string\n")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WriteByte(0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadByte() (byte, error) {
|
|
||||||
// let the Apple II know we are ready to read
|
|
||||||
out_read.Out(gpio.Low)
|
|
||||||
|
|
||||||
// wait for the Apple II to write
|
|
||||||
for in_write.Read() == gpio.High {
|
|
||||||
if !in_write.WaitForEdge(edgeTimeout) {
|
|
||||||
out_read.Out(gpio.High)
|
|
||||||
return 0, errors.New("Timed out reading byte -- write stuck high\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a nibble of data
|
|
||||||
var data byte
|
|
||||||
data = 0
|
|
||||||
bit7 := in_bit7.Read()
|
|
||||||
bit6 := in_bit6.Read()
|
|
||||||
bit5 := in_bit5.Read()
|
|
||||||
bit4 := in_bit4.Read()
|
|
||||||
bit3 := in_bit3.Read()
|
|
||||||
bit2 := in_bit2.Read()
|
|
||||||
bit1 := in_bit1.Read()
|
|
||||||
bit0 := in_bit0.Read()
|
|
||||||
|
|
||||||
if bit7 == gpio.High {
|
|
||||||
data += 128
|
|
||||||
}
|
|
||||||
if bit6 == gpio.High {
|
|
||||||
data += 64
|
|
||||||
}
|
|
||||||
if bit5 == gpio.High {
|
|
||||||
data += 32
|
|
||||||
}
|
|
||||||
if bit4 == gpio.High {
|
|
||||||
data += 16
|
|
||||||
}
|
|
||||||
if bit3 == gpio.High {
|
|
||||||
data += 8
|
|
||||||
}
|
|
||||||
if bit2 == gpio.High {
|
|
||||||
data += 4
|
|
||||||
}
|
|
||||||
if bit1 == gpio.High {
|
|
||||||
data += 2
|
|
||||||
}
|
|
||||||
if bit0 == gpio.High {
|
|
||||||
data += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// let the Apple II know we are done reading
|
|
||||||
//fmt.Printf("let the Apple II know we are done reading\n")
|
|
||||||
out_read.Out(gpio.High)
|
|
||||||
|
|
||||||
// wait for the Apple II to finish writing
|
|
||||||
//fmt.Printf("wait for the Apple II to finish writing\n")
|
|
||||||
for in_write.Read() == gpio.Low {
|
|
||||||
if !in_write.WaitForEdge(edgeTimeout) {
|
|
||||||
return 0, errors.New("Timed out reading byte -- write stuck low")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteByte(data byte) error {
|
|
||||||
// check if the Apple II wants to send a byte to us first
|
|
||||||
if in_write.Read() == gpio.Low {
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
return errors.New("Can't write byte while byte is incoming")
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for the Apple II to be ready to read
|
|
||||||
for in_read.Read() == gpio.High {
|
|
||||||
if !in_read.WaitForEdge(edgeTimeout) {
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
return errors.New("Timed out writing byte -- read stuck high")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bit7 := gpio.Low
|
|
||||||
bit6 := gpio.Low
|
|
||||||
bit5 := gpio.Low
|
|
||||||
bit4 := gpio.Low
|
|
||||||
bit3 := gpio.Low
|
|
||||||
bit2 := gpio.Low
|
|
||||||
bit1 := gpio.Low
|
|
||||||
bit0 := gpio.Low
|
|
||||||
|
|
||||||
if ((data & 128) >> 7) == 1 {
|
|
||||||
bit7 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit7.Out(bit7)
|
|
||||||
|
|
||||||
if ((data & 64) >> 6) == 1 {
|
|
||||||
bit6 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit6.Out(bit6)
|
|
||||||
|
|
||||||
if ((data & 32) >> 5) == 1 {
|
|
||||||
bit5 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit5.Out(bit5)
|
|
||||||
|
|
||||||
if ((data & 16) >> 4) == 1 {
|
|
||||||
bit4 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit4.Out(bit4)
|
|
||||||
|
|
||||||
if ((data & 8) >> 3) == 1 {
|
|
||||||
bit3 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit3.Out(bit3)
|
|
||||||
|
|
||||||
if ((data & 4) >> 2) == 1 {
|
|
||||||
bit2 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit2.Out(bit2)
|
|
||||||
|
|
||||||
if ((data & 2) >> 1) == 1 {
|
|
||||||
bit1 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit1.Out(bit1)
|
|
||||||
|
|
||||||
if (data & 1) == 1 {
|
|
||||||
bit0 = gpio.High
|
|
||||||
}
|
|
||||||
out_bit0.Out(bit0)
|
|
||||||
|
|
||||||
// let Apple II know we're writing
|
|
||||||
out_write.Out(gpio.Low)
|
|
||||||
|
|
||||||
// wait for the Apple II to finsih reading
|
|
||||||
//fmt.Printf("wait for the Apple II to finsih reading\n")
|
|
||||||
for in_read.Read() == gpio.Low {
|
|
||||||
if !in_read.WaitForEdge(edgeTimeout) {
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
return errors.New("Timed out writing byte -- read stuck low")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let the Apple II know we are done writing
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteBlock(buffer []byte) error {
|
|
||||||
for i := 0; i < 512; i++ {
|
|
||||||
err := WriteByte(buffer[i])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadBlock(buffer []byte) error {
|
|
||||||
var err error
|
|
||||||
for i := 0; i < 512; i++ {
|
|
||||||
buffer[i], err = ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteBuffer(buffer []byte) error {
|
|
||||||
bufferSize := len(buffer)
|
|
||||||
for i := 0; i < bufferSize; i++ {
|
|
||||||
err := WriteByte(buffer[i])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
295
RaspberryPi/apple2driver/a2io/gpio.go
Normal file
295
RaspberryPi/apple2driver/a2io/gpio.go
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
package a2io
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"periph.io/x/periph/conn/gpio"
|
||||||
|
"periph.io/x/periph/conn/gpio/gpioreg"
|
||||||
|
"periph.io/x/periph/host"
|
||||||
|
)
|
||||||
|
|
||||||
|
var edgeTimeout time.Duration
|
||||||
|
|
||||||
|
var out_write gpio.PinIO
|
||||||
|
var out_read gpio.PinIO
|
||||||
|
var out_reserved2 gpio.PinIO
|
||||||
|
var out_reserved1 gpio.PinIO
|
||||||
|
var out_bit7 gpio.PinIO
|
||||||
|
var out_bit6 gpio.PinIO
|
||||||
|
var out_bit5 gpio.PinIO
|
||||||
|
var out_bit4 gpio.PinIO
|
||||||
|
var out_bit3 gpio.PinIO
|
||||||
|
var out_bit2 gpio.PinIO
|
||||||
|
var out_bit1 gpio.PinIO
|
||||||
|
var out_bit0 gpio.PinIO
|
||||||
|
var in_write gpio.PinIO
|
||||||
|
var in_read gpio.PinIO
|
||||||
|
var in_reserved2 gpio.PinIO
|
||||||
|
var in_reserved1 gpio.PinIO
|
||||||
|
var in_bit7 gpio.PinIO
|
||||||
|
var in_bit6 gpio.PinIO
|
||||||
|
var in_bit5 gpio.PinIO
|
||||||
|
var in_bit4 gpio.PinIO
|
||||||
|
var in_bit3 gpio.PinIO
|
||||||
|
var in_bit2 gpio.PinIO
|
||||||
|
var in_bit1 gpio.PinIO
|
||||||
|
var in_bit0 gpio.PinIO
|
||||||
|
|
||||||
|
type A2Gpio struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) Init() {
|
||||||
|
host.Init()
|
||||||
|
|
||||||
|
out_write = gpioreg.ByName("GPIO24")
|
||||||
|
out_read = gpioreg.ByName("GPIO25")
|
||||||
|
out_reserved2 = gpioreg.ByName("GPIO7") //note GPIO7 and CPIO8 require extra effort to use
|
||||||
|
out_reserved1 = gpioreg.ByName("GPIO8")
|
||||||
|
out_bit7 = gpioreg.ByName("GPIO5")
|
||||||
|
out_bit6 = gpioreg.ByName("GPIO11")
|
||||||
|
out_bit5 = gpioreg.ByName("GPIO9")
|
||||||
|
out_bit4 = gpioreg.ByName("GPIO10")
|
||||||
|
out_bit3 = gpioreg.ByName("GPIO22")
|
||||||
|
out_bit2 = gpioreg.ByName("GPIO27")
|
||||||
|
out_bit1 = gpioreg.ByName("GPIO17")
|
||||||
|
out_bit0 = gpioreg.ByName("GPIO4")
|
||||||
|
in_write = gpioreg.ByName("GPIO23")
|
||||||
|
in_read = gpioreg.ByName("GPIO18")
|
||||||
|
in_reserved2 = gpioreg.ByName("GPIO14")
|
||||||
|
in_reserved1 = gpioreg.ByName("GPIO15")
|
||||||
|
in_bit7 = gpioreg.ByName("GPIO12")
|
||||||
|
in_bit6 = gpioreg.ByName("GPIO16")
|
||||||
|
in_bit5 = gpioreg.ByName("GPIO20")
|
||||||
|
in_bit4 = gpioreg.ByName("GPIO21")
|
||||||
|
in_bit3 = gpioreg.ByName("GPIO26")
|
||||||
|
in_bit2 = gpioreg.ByName("GPIO19")
|
||||||
|
in_bit1 = gpioreg.ByName("GPIO13")
|
||||||
|
in_bit0 = gpioreg.ByName("GPIO6")
|
||||||
|
|
||||||
|
in_write.In(gpio.PullDown, gpio.BothEdges)
|
||||||
|
in_read.In(gpio.PullDown, gpio.BothEdges)
|
||||||
|
out_reserved1.Out(gpio.High)
|
||||||
|
out_reserved2.Out(gpio.High)
|
||||||
|
out_read.Out(gpio.High)
|
||||||
|
out_write.Out(gpio.High)
|
||||||
|
out_bit7.Out(gpio.Low)
|
||||||
|
out_bit6.Out(gpio.Low)
|
||||||
|
out_bit5.Out(gpio.Low)
|
||||||
|
out_bit4.Out(gpio.Low)
|
||||||
|
out_bit3.Out(gpio.Low)
|
||||||
|
out_bit2.Out(gpio.Low)
|
||||||
|
out_bit1.Out(gpio.Low)
|
||||||
|
out_bit0.Out(gpio.Low)
|
||||||
|
|
||||||
|
edgeTimeout = time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) ReadString() (string, error) {
|
||||||
|
var inBytes bytes.Buffer
|
||||||
|
for {
|
||||||
|
inByte, err := a2.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if inByte == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
inBytes.WriteByte(inByte)
|
||||||
|
}
|
||||||
|
return string(inBytes.Bytes()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) WriteString(outString string) error {
|
||||||
|
for _, character := range outString {
|
||||||
|
err := a2.WriteByte(byte(character) | 128)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to write string\n")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a2.WriteByte(0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) ReadByte() (byte, error) {
|
||||||
|
// let the Apple II know we are ready to read
|
||||||
|
out_read.Out(gpio.Low)
|
||||||
|
|
||||||
|
// wait for the Apple II to write
|
||||||
|
for in_write.Read() == gpio.High {
|
||||||
|
if !in_write.WaitForEdge(edgeTimeout) {
|
||||||
|
out_read.Out(gpio.High)
|
||||||
|
return 0, errors.New("Timed out reading byte -- write stuck high\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a nibble of data
|
||||||
|
var data byte
|
||||||
|
data = 0
|
||||||
|
bit7 := in_bit7.Read()
|
||||||
|
bit6 := in_bit6.Read()
|
||||||
|
bit5 := in_bit5.Read()
|
||||||
|
bit4 := in_bit4.Read()
|
||||||
|
bit3 := in_bit3.Read()
|
||||||
|
bit2 := in_bit2.Read()
|
||||||
|
bit1 := in_bit1.Read()
|
||||||
|
bit0 := in_bit0.Read()
|
||||||
|
|
||||||
|
if bit7 == gpio.High {
|
||||||
|
data += 128
|
||||||
|
}
|
||||||
|
if bit6 == gpio.High {
|
||||||
|
data += 64
|
||||||
|
}
|
||||||
|
if bit5 == gpio.High {
|
||||||
|
data += 32
|
||||||
|
}
|
||||||
|
if bit4 == gpio.High {
|
||||||
|
data += 16
|
||||||
|
}
|
||||||
|
if bit3 == gpio.High {
|
||||||
|
data += 8
|
||||||
|
}
|
||||||
|
if bit2 == gpio.High {
|
||||||
|
data += 4
|
||||||
|
}
|
||||||
|
if bit1 == gpio.High {
|
||||||
|
data += 2
|
||||||
|
}
|
||||||
|
if bit0 == gpio.High {
|
||||||
|
data += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// let the Apple II know we are done reading
|
||||||
|
//fmt.Printf("let the Apple II know we are done reading\n")
|
||||||
|
out_read.Out(gpio.High)
|
||||||
|
|
||||||
|
// wait for the Apple II to finish writing
|
||||||
|
//fmt.Printf("wait for the Apple II to finish writing\n")
|
||||||
|
for in_write.Read() == gpio.Low {
|
||||||
|
if !in_write.WaitForEdge(edgeTimeout) {
|
||||||
|
return 0, errors.New("Timed out reading byte -- write stuck low")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) WriteByte(data byte) error {
|
||||||
|
// check if the Apple II wants to send a byte to us first
|
||||||
|
if in_write.Read() == gpio.Low {
|
||||||
|
out_write.Out(gpio.High)
|
||||||
|
return errors.New("Can't write byte while byte is incoming")
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for the Apple II to be ready to read
|
||||||
|
for in_read.Read() == gpio.High {
|
||||||
|
if !in_read.WaitForEdge(edgeTimeout) {
|
||||||
|
out_write.Out(gpio.High)
|
||||||
|
return errors.New("Timed out writing byte -- read stuck high")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bit7 := gpio.Low
|
||||||
|
bit6 := gpio.Low
|
||||||
|
bit5 := gpio.Low
|
||||||
|
bit4 := gpio.Low
|
||||||
|
bit3 := gpio.Low
|
||||||
|
bit2 := gpio.Low
|
||||||
|
bit1 := gpio.Low
|
||||||
|
bit0 := gpio.Low
|
||||||
|
|
||||||
|
if ((data & 128) >> 7) == 1 {
|
||||||
|
bit7 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit7.Out(bit7)
|
||||||
|
|
||||||
|
if ((data & 64) >> 6) == 1 {
|
||||||
|
bit6 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit6.Out(bit6)
|
||||||
|
|
||||||
|
if ((data & 32) >> 5) == 1 {
|
||||||
|
bit5 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit5.Out(bit5)
|
||||||
|
|
||||||
|
if ((data & 16) >> 4) == 1 {
|
||||||
|
bit4 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit4.Out(bit4)
|
||||||
|
|
||||||
|
if ((data & 8) >> 3) == 1 {
|
||||||
|
bit3 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit3.Out(bit3)
|
||||||
|
|
||||||
|
if ((data & 4) >> 2) == 1 {
|
||||||
|
bit2 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit2.Out(bit2)
|
||||||
|
|
||||||
|
if ((data & 2) >> 1) == 1 {
|
||||||
|
bit1 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit1.Out(bit1)
|
||||||
|
|
||||||
|
if (data & 1) == 1 {
|
||||||
|
bit0 = gpio.High
|
||||||
|
}
|
||||||
|
out_bit0.Out(bit0)
|
||||||
|
|
||||||
|
// let Apple II know we're writing
|
||||||
|
out_write.Out(gpio.Low)
|
||||||
|
|
||||||
|
// wait for the Apple II to finsih reading
|
||||||
|
//fmt.Printf("wait for the Apple II to finsih reading\n")
|
||||||
|
for in_read.Read() == gpio.Low {
|
||||||
|
if !in_read.WaitForEdge(edgeTimeout) {
|
||||||
|
out_write.Out(gpio.High)
|
||||||
|
return errors.New("Timed out writing byte -- read stuck low")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let the Apple II know we are done writing
|
||||||
|
out_write.Out(gpio.High)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) WriteBlock(buffer []byte) error {
|
||||||
|
for i := 0; i < 512; i++ {
|
||||||
|
err := a2.WriteByte(buffer[i])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) ReadBlock(buffer []byte) error {
|
||||||
|
var err error
|
||||||
|
for i := 0; i < 512; i++ {
|
||||||
|
buffer[i], err = a2.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a2 A2Gpio) WriteBuffer(buffer []byte) error {
|
||||||
|
bufferSize := len(buffer)
|
||||||
|
for i := 0; i < bufferSize; i++ {
|
||||||
|
err := a2.WriteByte(buffer[i])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
85
RaspberryPi/apple2driver/a2io/mockio.go
Normal file
85
RaspberryPi/apple2driver/a2io/mockio.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
package a2io
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockIoData struct {
|
||||||
|
BytesToRead []byte
|
||||||
|
BytesWritten []byte
|
||||||
|
byteRead int
|
||||||
|
byteWritten int
|
||||||
|
ErrorToThrow error
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockIo struct {
|
||||||
|
Data *MockIoData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) Init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) WriteByte(data byte) error {
|
||||||
|
mockIo.Data.BytesWritten[mockIo.Data.byteWritten] = data
|
||||||
|
mockIo.Data.byteWritten++
|
||||||
|
return mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) WriteString(outString string) error {
|
||||||
|
for i, b := range outString {
|
||||||
|
mockIo.Data.BytesWritten[i+mockIo.Data.byteWritten] = byte(b)
|
||||||
|
}
|
||||||
|
mockIo.Data.byteWritten += len(outString)
|
||||||
|
return mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) WriteBlock(buffer []byte) error {
|
||||||
|
for i, b := range buffer {
|
||||||
|
mockIo.Data.BytesWritten[i+mockIo.Data.byteWritten] = b
|
||||||
|
}
|
||||||
|
mockIo.Data.byteWritten += len(buffer)
|
||||||
|
return mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) WriteBuffer(buffer []byte) error {
|
||||||
|
for i, b := range buffer {
|
||||||
|
mockIo.Data.BytesWritten[i+mockIo.Data.byteWritten] = b
|
||||||
|
}
|
||||||
|
mockIo.Data.byteWritten += len(buffer)
|
||||||
|
return mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) ReadByte() (byte, error) {
|
||||||
|
b := mockIo.Data.BytesToRead[mockIo.Data.byteRead]
|
||||||
|
mockIo.Data.byteRead++
|
||||||
|
return b, mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) ReadString() (string, error) {
|
||||||
|
builder := strings.Builder{}
|
||||||
|
for {
|
||||||
|
if mockIo.Data.byteRead > len(mockIo.Data.BytesToRead) {
|
||||||
|
return "", errors.New("Read more data than available")
|
||||||
|
}
|
||||||
|
builder.WriteByte(mockIo.Data.BytesToRead[mockIo.Data.byteRead])
|
||||||
|
mockIo.Data.byteRead++
|
||||||
|
if mockIo.Data.BytesToRead[mockIo.Data.byteRead] == 0 {
|
||||||
|
mockIo.Data.byteRead++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.String(), mockIo.Data.ErrorToThrow
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mockIo MockIo) ReadBlock(buffer []byte) error {
|
||||||
|
if mockIo.Data.byteRead+512 > len(mockIo.Data.BytesToRead) {
|
||||||
|
return errors.New("Read more data than available")
|
||||||
|
}
|
||||||
|
for i := 0; i < 512; i++ {
|
||||||
|
buffer[i] = mockIo.Data.BytesToRead[mockIo.Data.byteRead]
|
||||||
|
mockIo.Data.byteRead++
|
||||||
|
}
|
||||||
|
return mockIo.Data.ErrorToThrow
|
||||||
|
}
|
|
@ -24,10 +24,13 @@ func main() {
|
||||||
|
|
||||||
fmt.Printf("Starting Apple II RPi...\n")
|
fmt.Printf("Starting Apple II RPi...\n")
|
||||||
|
|
||||||
a2io.InitGpio()
|
comm := a2io.A2Gpio{}
|
||||||
|
|
||||||
|
handlers.SetCommunication(comm)
|
||||||
|
comm.Init()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
command, err := a2io.ReadByte()
|
command, err := comm.ReadByte()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
switch command {
|
switch command {
|
||||||
case ReadBlockCommand:
|
case ReadBlockCommand:
|
||||||
|
|
78
RaspberryPi/apple2driver/handlers/block.go
Normal file
78
RaspberryPi/apple2driver/handlers/block.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
||||||
|
)
|
||||||
|
|
||||||
|
var oldFirmware = false
|
||||||
|
|
||||||
|
func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
|
||||||
|
blockLow, _ := comm.ReadByte()
|
||||||
|
blockHigh, _ := comm.ReadByte()
|
||||||
|
var driveUnit byte = 0
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if !oldFirmware {
|
||||||
|
driveUnit, err = comm.ReadByte()
|
||||||
|
fmt.Printf("Drive unit: %0X\n", driveUnit)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Drive unit not sent, assuming older firmware")
|
||||||
|
oldFirmware = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file := drive1
|
||||||
|
|
||||||
|
if driveUnit >= 128 {
|
||||||
|
file = drive2
|
||||||
|
}
|
||||||
|
|
||||||
|
block := int(blockHigh)*256 + int(blockLow)
|
||||||
|
|
||||||
|
fmt.Printf("Read block %d\n", block)
|
||||||
|
|
||||||
|
buffer := prodos.ReadBlock(file, block)
|
||||||
|
|
||||||
|
err = comm.WriteBlock(buffer)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Printf("Read block completed\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Failed to read block\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
|
||||||
|
blockLow, _ := comm.ReadByte()
|
||||||
|
blockHigh, _ := comm.ReadByte()
|
||||||
|
|
||||||
|
var driveUnit byte = 0
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if !oldFirmware {
|
||||||
|
driveUnit, err = comm.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Drive unit not sent, assuming older firmware")
|
||||||
|
oldFirmware = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file := drive1
|
||||||
|
|
||||||
|
if driveUnit >= 128 {
|
||||||
|
file = drive2
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]byte, 512)
|
||||||
|
|
||||||
|
block := int(blockHigh)*256 + int(blockLow)
|
||||||
|
|
||||||
|
fmt.Printf("Write block %d\n", block)
|
||||||
|
|
||||||
|
comm.ReadBlock(buffer)
|
||||||
|
prodos.WriteBlock(file, block, buffer)
|
||||||
|
fmt.Printf("Write block completed\n")
|
||||||
|
}
|
11
RaspberryPi/apple2driver/handlers/communication.go
Normal file
11
RaspberryPi/apple2driver/handlers/communication.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
var comm a2io.A2Io
|
||||||
|
|
||||||
|
func SetCommunication(commIO a2io.A2Io) {
|
||||||
|
comm = commIO
|
||||||
|
}
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var forceLowercase = false
|
var forceLowercase = false
|
||||||
|
@ -17,11 +15,11 @@ func ExecCommand() {
|
||||||
workingDirectory, err := os.Getwd()
|
workingDirectory, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
workingDirectory = "/home"
|
workingDirectory = "/home"
|
||||||
a2io.WriteString("Failed to get current working directory, setting to /home\r")
|
comm.WriteString("Failed to get current working directory, setting to /home\r")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Reading command to execute...\n")
|
fmt.Printf("Reading command to execute...\n")
|
||||||
linuxCommand, err := a2io.ReadString()
|
linuxCommand, err := comm.ReadString()
|
||||||
if forceLowercase {
|
if forceLowercase {
|
||||||
linuxCommand = strings.ToLower(linuxCommand)
|
linuxCommand = strings.ToLower(linuxCommand)
|
||||||
}
|
}
|
||||||
|
@ -30,10 +28,10 @@ func ExecCommand() {
|
||||||
workingDirectory = strings.Replace(linuxCommand, "cd ", "", 1)
|
workingDirectory = strings.Replace(linuxCommand, "cd ", "", 1)
|
||||||
err = os.Chdir(workingDirectory)
|
err = os.Chdir(workingDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a2io.WriteString("Failed to set working directory\r")
|
comm.WriteString("Failed to set working directory\r")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a2io.WriteString("Working directory set\r")
|
comm.WriteString("Working directory set\r")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if linuxCommand == "a2help" {
|
if linuxCommand == "a2help" {
|
||||||
|
@ -68,14 +66,14 @@ func execCommand(linuxCommand string, workingDirectory string) {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to set stdout\n")
|
fmt.Printf("Failed to set stdout\n")
|
||||||
a2io.WriteString("Failed to set stdout\r")
|
comm.WriteString("Failed to set stdout\r")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("Command output:\n")
|
fmt.Printf("Command output:\n")
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to start command\n")
|
fmt.Printf("Failed to start command\n")
|
||||||
a2io.WriteString("Failed to start command\r")
|
comm.WriteString("Failed to start command\r")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,12 +96,12 @@ func execCommand(linuxCommand string, workingDirectory string) {
|
||||||
case <-outputComplete:
|
case <-outputComplete:
|
||||||
outputComplete <- true
|
outputComplete <- true
|
||||||
case <-userCancelled:
|
case <-userCancelled:
|
||||||
a2io.WriteString("^C\r")
|
comm.WriteString("^C\r")
|
||||||
cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
return
|
return
|
||||||
case <-inputComplete:
|
case <-inputComplete:
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
a2io.WriteByte(0)
|
comm.WriteByte(0)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -173,7 +171,7 @@ func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, use
|
||||||
inputComplete <- true
|
inputComplete <- true
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
b, err := a2io.ReadByte()
|
b, err := comm.ReadByte()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if b == 3 {
|
if b == 3 {
|
||||||
stdin.Close()
|
stdin.Close()
|
||||||
|
@ -192,7 +190,7 @@ func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, use
|
||||||
}
|
}
|
||||||
|
|
||||||
func a2help() {
|
func a2help() {
|
||||||
a2io.WriteString("\r" +
|
comm.WriteString("\r" +
|
||||||
"This is a pseudo shell. Each command is executed as a process. The cd command\r" +
|
"This is a pseudo shell. Each command is executed as a process. The cd command\r" +
|
||||||
"is intercepted and sets the working directory for the next command.\r" +
|
"is intercepted and sets the working directory for the next command.\r" +
|
||||||
"\r" +
|
"\r" +
|
||||||
|
@ -205,11 +203,11 @@ func a2help() {
|
||||||
|
|
||||||
func a2lower() {
|
func a2lower() {
|
||||||
forceLowercase = true
|
forceLowercase = true
|
||||||
a2io.WriteString("All commands will be converted to lowercase\r")
|
comm.WriteString("All commands will be converted to lowercase\r")
|
||||||
}
|
}
|
||||||
|
|
||||||
func a2wifi() {
|
func a2wifi() {
|
||||||
a2io.WriteString("\r" +
|
comm.WriteString("\r" +
|
||||||
"Usage: a2wifi list\r" +
|
"Usage: a2wifi list\r" +
|
||||||
" a2wifi select SSID PASSWORD\r" +
|
" a2wifi select SSID PASSWORD\r" +
|
||||||
"\r")
|
"\r")
|
||||||
|
@ -222,7 +220,7 @@ func a2wifiList() string {
|
||||||
func a2wifiSelect(linuxCommand string) (string, error) {
|
func a2wifiSelect(linuxCommand string) (string, error) {
|
||||||
params := strings.Fields(linuxCommand)
|
params := strings.Fields(linuxCommand)
|
||||||
if len(params) != 4 {
|
if len(params) != 4 {
|
||||||
a2io.WriteString("\rIncorrect number of parameters. Usage: a2wifi select SSID PASSWORD\r\r")
|
comm.WriteString("\rIncorrect number of parameters. Usage: a2wifi select SSID PASSWORD\r\r")
|
||||||
return "", errors.New("Incorrect number of parameters. Usage: a2wifi select SSID PASSWORD")
|
return "", errors.New("Incorrect number of parameters. Usage: a2wifi select SSID PASSWORD")
|
||||||
}
|
}
|
||||||
ssid := params[2]
|
ssid := params[2]
|
||||||
|
@ -244,8 +242,8 @@ func sendCharacter(b byte) {
|
||||||
if b == 9 { // convert TAB to spaces
|
if b == 9 { // convert TAB to spaces
|
||||||
b = ' '
|
b = ' '
|
||||||
b += 128
|
b += 128
|
||||||
a2io.WriteByte(b)
|
comm.WriteByte(b)
|
||||||
}
|
}
|
||||||
b |= 128
|
b |= 128
|
||||||
a2io.WriteByte(b)
|
comm.WriteByte(b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ func GetTimeCommand() {
|
||||||
prodosTime := prodos.DateTimeToProDOS(time.Now())
|
prodosTime := prodos.DateTimeToProDOS(time.Now())
|
||||||
|
|
||||||
for i := 0; i < len(prodosTime); i++ {
|
for i := 0; i < len(prodosTime); i++ {
|
||||||
a2io.WriteByte(prodosTime[i])
|
comm.WriteByte(prodosTime[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Send time complete\n")
|
fmt.Printf("Send time complete\n")
|
||||||
|
|
|
@ -3,18 +3,16 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadFileCommand() {
|
func LoadFileCommand() {
|
||||||
fileName, _ := a2io.ReadString()
|
fileName, _ := comm.ReadString()
|
||||||
|
|
||||||
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
fmt.Printf("ERROR: %s\n", err.Error())
|
||||||
a2io.WriteByte(0)
|
comm.WriteByte(0)
|
||||||
a2io.WriteByte(0)
|
comm.WriteByte(0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,11 +24,11 @@ func LoadFileCommand() {
|
||||||
fileSizeHigh := byte(fileSize >> 8)
|
fileSizeHigh := byte(fileSize >> 8)
|
||||||
fileSizeLow := byte(fileSize & 255)
|
fileSizeLow := byte(fileSize & 255)
|
||||||
|
|
||||||
err = a2io.WriteByte(fileSizeLow)
|
err = comm.WriteByte(fileSizeLow)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = a2io.WriteByte(fileSizeHigh)
|
err = comm.WriteByte(fileSizeHigh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,5 +39,5 @@ func LoadFileCommand() {
|
||||||
|
|
||||||
file.Read(buffer)
|
file.Read(buffer)
|
||||||
|
|
||||||
a2io.WriteBuffer(buffer)
|
comm.WriteBuffer(buffer)
|
||||||
}
|
}
|
||||||
|
|
26
RaspberryPi/apple2driver/handlers/loadFile_test.go
Normal file
26
RaspberryPi/apple2driver/handlers/loadFile_test.go
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadFileCommandReturnZeroLengthOnFileNotFound(t *testing.T) {
|
||||||
|
mockIoData := a2io.MockIoData{
|
||||||
|
BytesToRead: []byte("FILE_DOES_NOT_EXIST\x00"),
|
||||||
|
BytesWritten: make([]byte, 1000),
|
||||||
|
}
|
||||||
|
|
||||||
|
mockIo := a2io.MockIo{Data: &mockIoData}
|
||||||
|
|
||||||
|
SetCommunication(&mockIo)
|
||||||
|
|
||||||
|
LoadFileCommand()
|
||||||
|
|
||||||
|
got := mockIoData.BytesWritten
|
||||||
|
|
||||||
|
if got[0] != 0 && got[1] != 0 {
|
||||||
|
t.Errorf("MenuCommand() sent = %s; want 00", got)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,13 +2,11 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func MenuCommand() {
|
func MenuCommand() {
|
||||||
fmt.Printf("Sending menu...\n")
|
fmt.Printf("Sending menu...\n")
|
||||||
a2io.WriteString("Apple2-IO-RPi\r" +
|
comm.WriteString("Apple2-IO-RPi\r" +
|
||||||
"(c)2020-2021 Terence J. Boldt\r" +
|
"(c)2020-2021 Terence J. Boldt\r" +
|
||||||
"\r" +
|
"\r" +
|
||||||
"Select an option:\r" +
|
"Select an option:\r" +
|
||||||
|
|
28
RaspberryPi/apple2driver/handlers/menu_test.go
Normal file
28
RaspberryPi/apple2driver/handlers/menu_test.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMenuCommand(t *testing.T) {
|
||||||
|
mockIoData := a2io.MockIoData{
|
||||||
|
ErrorToThrow: nil,
|
||||||
|
BytesWritten: make([]byte, 1000),
|
||||||
|
}
|
||||||
|
|
||||||
|
mockIo := a2io.MockIo{Data: &mockIoData}
|
||||||
|
|
||||||
|
SetCommunication(&mockIo)
|
||||||
|
|
||||||
|
MenuCommand()
|
||||||
|
|
||||||
|
want := "Apple2-IO-RPi"
|
||||||
|
got := string(mockIoData.BytesWritten)
|
||||||
|
|
||||||
|
if strings.Index(got, want) != 0 {
|
||||||
|
t.Errorf("MenuCommand() sent = %s; want startsWith %s", got, want)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
|
||||||
)
|
|
||||||
|
|
||||||
var oldFirmware = false
|
|
||||||
|
|
||||||
func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
|
|
||||||
blockLow, _ := a2io.ReadByte()
|
|
||||||
blockHigh, _ := a2io.ReadByte()
|
|
||||||
var driveUnit byte = 0
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if !oldFirmware {
|
|
||||||
driveUnit, err = a2io.ReadByte()
|
|
||||||
fmt.Printf("Drive unit: %0X\n", driveUnit)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Drive unit not sent, assuming older firmware")
|
|
||||||
oldFirmware = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file := drive1
|
|
||||||
|
|
||||||
if driveUnit >= 128 {
|
|
||||||
file = drive2
|
|
||||||
}
|
|
||||||
|
|
||||||
var block int
|
|
||||||
block = int(blockHigh)*256 + int(blockLow)
|
|
||||||
|
|
||||||
fmt.Printf("Read block %d\n", block)
|
|
||||||
|
|
||||||
buffer := prodos.ReadBlock(file, block)
|
|
||||||
|
|
||||||
err = a2io.WriteBlock(buffer)
|
|
||||||
if err == nil {
|
|
||||||
fmt.Printf("Read block completed\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Failed to read block\n")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
||||||
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
|
||||||
)
|
|
||||||
|
|
||||||
func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
|
|
||||||
blockLow, _ := a2io.ReadByte()
|
|
||||||
blockHigh, _ := a2io.ReadByte()
|
|
||||||
|
|
||||||
var driveUnit byte = 0
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if !oldFirmware {
|
|
||||||
driveUnit, err = a2io.ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Drive unit not sent, assuming older firmware")
|
|
||||||
oldFirmware = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file := drive1
|
|
||||||
|
|
||||||
if driveUnit >= 128 {
|
|
||||||
file = drive2
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := make([]byte, 512)
|
|
||||||
var block int
|
|
||||||
block = int(blockHigh)*256 + int(blockLow)
|
|
||||||
|
|
||||||
fmt.Printf("Write block %d\n", block)
|
|
||||||
|
|
||||||
a2io.ReadBlock(buffer)
|
|
||||||
prodos.WriteBlock(file, block, buffer)
|
|
||||||
fmt.Printf("Write block completed\n")
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user