mirror of
https://github.com/tjboldt/Apple2-IO-RPi.git
synced 2024-06-08 19:29:31 +00:00
Refactor Go code into packages
This commit is contained in:
parent
75c953052f
commit
cc560b972f
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
*-bak
|
*-bak
|
||||||
*.o
|
*.o
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
RaspberryPi/Apple2-IO-RPi
|
RaspberryPi/apple2driver/apple2driver
|
||||||
|
|
|
@ -33,11 +33,11 @@ So far, this is a project and not a finished product. The current prototype is o
|
||||||
10. Update firmware with utility (not written yet) or use EPROM programmer
|
10. Update firmware with utility (not written yet) or use EPROM programmer
|
||||||
11. sudo apt install git golang
|
11. sudo apt install git golang
|
||||||
12. git clone https://github.com/tjboldt/Apple2-IO-RPi.git
|
12. git clone https://github.com/tjboldt/Apple2-IO-RPi.git
|
||||||
13. cd Apple2-IO-RPi
|
13. cd Apple2-IO-RPi/RaspberryPi/apple2driver
|
||||||
14. go get
|
14. go get
|
||||||
15. go build
|
15. go build
|
||||||
16. ./Apple2-IO-RPi Apple2-IO-RPi.hdv
|
16. ./apple2driver ../Apple2-IO-RPi.hdv
|
||||||
18. Setup the Driver as a service or to autostart via cronjob (crontab -e then add the line @reboot /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv > /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.log)
|
18. Setup the Driver as a service or to autostart via cronjob (crontab -e then add the line @reboot /home/pi/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv > /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.log)
|
||||||
|
|
||||||
## Similar Project
|
## Similar Project
|
||||||
If you prefer having Apple II peripherals control a Raspberry Pi rather than simply using the Raspberry Pi to provide storage, network access and processing to the Apple II, have a look at David Schmenk's excellent [Apple2Pi](https://github.com/dschmenk/apple2pi) project.
|
If you prefer having Apple II peripherals control a Raspberry Pi rather than simply using the Raspberry Pi to provide storage, network access and processing to the Apple II, have a look at David Schmenk's excellent [Apple2Pi](https://github.com/dschmenk/apple2pi) project.
|
||||||
|
|
|
@ -1,510 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"periph.io/x/periph/conn/gpio"
|
|
||||||
"periph.io/x/periph/conn/gpio/gpioreg"
|
|
||||||
"periph.io/x/periph/host"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
const ReadBlockCommand = 1
|
|
||||||
const WriteBlockCommand = 2
|
|
||||||
const GetTimeCommand = 3
|
|
||||||
const ChangeDriveCommand = 4
|
|
||||||
const ExecCommand = 5
|
|
||||||
const LoadFileCommand = 6
|
|
||||||
const SaveFileCommand = 7
|
|
||||||
|
|
||||||
var debug bool = false
|
|
||||||
|
|
||||||
var workingDirectory string = "/home"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
host.Init()
|
|
||||||
|
|
||||||
initGpio()
|
|
||||||
|
|
||||||
if len(os.Args) == 3 && os.Args[2] == "--debug" {
|
|
||||||
debug = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Starting Apple II RPi...\n")
|
|
||||||
|
|
||||||
fileName := os.Args[1]
|
|
||||||
|
|
||||||
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR: %s", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("Check for command\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
command, err := readByte()
|
|
||||||
if err != nil {
|
|
||||||
//fmt.Printf("Timed out waiting for command\n")
|
|
||||||
} else {
|
|
||||||
switch command {
|
|
||||||
case ReadBlockCommand:
|
|
||||||
handleReadBlockCommand(file)
|
|
||||||
case WriteBlockCommand:
|
|
||||||
handleWriteBlockCommand(file)
|
|
||||||
case GetTimeCommand:
|
|
||||||
handleGetTimeCommand()
|
|
||||||
case ExecCommand:
|
|
||||||
handleExecCommand()
|
|
||||||
case LoadFileCommand:
|
|
||||||
handleLoadFileCommand()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleReadBlockCommand(file *os.File) {
|
|
||||||
blockLow, _ := readByte()
|
|
||||||
blockHigh, _ := readByte()
|
|
||||||
|
|
||||||
buffer := make([]byte, 512)
|
|
||||||
var block int64
|
|
||||||
block = int64(blockHigh)*256 + int64(blockLow)
|
|
||||||
|
|
||||||
fmt.Printf("Read block %d\n", block)
|
|
||||||
|
|
||||||
file.ReadAt(buffer, int64(block)*512)
|
|
||||||
//dumpBlock(buffer)
|
|
||||||
err := readBlock(buffer)
|
|
||||||
if err == nil {
|
|
||||||
fmt.Printf("Read block completed\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Failed to read block\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleWriteBlockCommand(file *os.File) {
|
|
||||||
blockLow, _ := readByte()
|
|
||||||
blockHigh, _ := readByte()
|
|
||||||
|
|
||||||
buffer := make([]byte, 512)
|
|
||||||
var block int64
|
|
||||||
block = int64(blockHigh)*256 + int64(blockLow)
|
|
||||||
|
|
||||||
fmt.Printf("Write block %d\n", block)
|
|
||||||
|
|
||||||
writeBlock(buffer)
|
|
||||||
file.WriteAt(buffer, int64(block)*512)
|
|
||||||
file.Sync()
|
|
||||||
fmt.Printf("Write block completed\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleExecCommand() {
|
|
||||||
fmt.Printf("Reading command to execute...\n")
|
|
||||||
linuxCommand, err := readString()
|
|
||||||
fmt.Printf("Command to run: %s\n", linuxCommand)
|
|
||||||
if strings.HasPrefix(linuxCommand, "cd /") {
|
|
||||||
workingDirectory = strings.Replace(linuxCommand, "cd ", "", 1)
|
|
||||||
writeString("Working directory set")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(linuxCommand, "cd ") {
|
|
||||||
workingDirectory = workingDirectory + "/" + strings.Replace(linuxCommand, "cd ", "", 1)
|
|
||||||
writeString("Working directory set")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if linuxCommand == "a2help" {
|
|
||||||
writeString("\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. Running\r" +
|
|
||||||
"commands that do not exit will hang. For example, do not use ping without a\r" +
|
|
||||||
"way to limit output like -c 1.\r\r")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cmd := exec.Command("bash", "-c", linuxCommand)
|
|
||||||
cmd.Dir = workingDirectory
|
|
||||||
cmdOut, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to execute command\n")
|
|
||||||
writeString("Failed to execute command")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Printf("Command output: %s\n", cmdOut)
|
|
||||||
apple2string := strings.Replace(string(cmdOut), "\n", "\r", -1)
|
|
||||||
err = writeString(apple2string)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to send command output\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleGetTimeCommand() {
|
|
||||||
fmt.Printf("Sending date/time...\n")
|
|
||||||
/* 49041 ($BF91) 49040 ($BF90)
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
|
||||||
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
|
||||||
DATE: | year | month | day |
|
|
||||||
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
|
||||||
|
|
||||||
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
|
||||||
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
|
||||||
TIME: | hour | | minute |
|
|
||||||
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
|
||||||
|
|
||||||
49043 ($BF93) 49042 ($BF92)
|
|
||||||
*/
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
year := now.Year() % 100
|
|
||||||
month := now.Month()
|
|
||||||
day := now.Day()
|
|
||||||
hour := now.Hour()
|
|
||||||
minute := now.Minute()
|
|
||||||
|
|
||||||
bf91 := (byte(year) << 1) + (byte(month) >> 3)
|
|
||||||
bf90 := ((byte(month) & 15) << 5) + byte(day)
|
|
||||||
bf93 := byte(hour)
|
|
||||||
bf92 := byte(minute)
|
|
||||||
|
|
||||||
writeByte(bf90)
|
|
||||||
writeByte(bf91)
|
|
||||||
writeByte(bf92)
|
|
||||||
writeByte(bf93)
|
|
||||||
fmt.Printf("Send time complete\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleLoadFileCommand() {
|
|
||||||
fileName, _ := readString()
|
|
||||||
|
|
||||||
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
|
||||||
writeByte(0)
|
|
||||||
writeByte(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileInfo, _ := file.Stat()
|
|
||||||
fileSize := int(fileInfo.Size())
|
|
||||||
|
|
||||||
fmt.Printf("FileSize: %d\n", fileSize)
|
|
||||||
|
|
||||||
fileSizeHigh := byte(fileSize >> 8)
|
|
||||||
fileSizeLow := byte(fileSize & 255)
|
|
||||||
|
|
||||||
writeByte(fileSizeLow)
|
|
||||||
writeByte(fileSizeHigh)
|
|
||||||
|
|
||||||
buffer := make([]byte, fileSize)
|
|
||||||
|
|
||||||
fmt.Printf("Read file %s SizeHigh: %d SizeLow: %d\n", fileName, fileSizeHigh, fileSizeLow)
|
|
||||||
|
|
||||||
file.Read(buffer)
|
|
||||||
|
|
||||||
for i := 0; i < fileSize; i++ {
|
|
||||||
err := writeByte(buffer[i])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readBlock(buffer []byte) error {
|
|
||||||
for i := 0; i < 512; i++ {
|
|
||||||
err := writeByte(buffer[i])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeBlock(buffer []byte) error {
|
|
||||||
var err error
|
|
||||||
for i := 0; i < 512; i++ {
|
|
||||||
buffer[i], err = readByte()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func initGpio() {
|
|
||||||
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 * 5
|
|
||||||
}
|
|
||||||
|
|
||||||
func dumpBlock(buffer []byte) {
|
|
||||||
for i := 0; i < 512; i++ {
|
|
||||||
fmt.Printf("%02X ", buffer[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readString() (string, error) {
|
|
||||||
var inBytes bytes.Buffer
|
|
||||||
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
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("let the Apple II know we are ready to read\n")
|
|
||||||
}
|
|
||||||
out_read.Out(gpio.Low)
|
|
||||||
|
|
||||||
// wait for the Apple II to write
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("wait for the Apple II to write\n")
|
|
||||||
}
|
|
||||||
for in_write.Read() == gpio.High {
|
|
||||||
if !in_write.WaitForEdge(edgeTimeout) {
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("Timed out reading byte -- write stuck high\n")
|
|
||||||
}
|
|
||||||
return 0, errors.New("Timed out reading byte -- write stuck high\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get a nibble of data
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("get a byte of data\n")
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("Timed out reading byte -- write stuck low\n")
|
|
||||||
}
|
|
||||||
return 0, errors.New("Timed out reading byte -- write stuck low")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeByte(data byte) error {
|
|
||||||
// wait for the Apple II to be ready to read
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("wait for the Apple II to be ready to read\n")
|
|
||||||
}
|
|
||||||
for in_read.Read() == gpio.High {
|
|
||||||
if !in_read.WaitForEdge(edgeTimeout) {
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("Timed out writing byte -- read stuck high\n")
|
|
||||||
}
|
|
||||||
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
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("let Apple II know we're writing\n")
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("Timed out writing byte -- read stuck low\n")
|
|
||||||
}
|
|
||||||
return errors.New("Timed out writing byte -- read stuck low")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let the Apple II know we are done writing
|
|
||||||
if debug {
|
|
||||||
fmt.Printf("let the Apple II know we are done writing\n")
|
|
||||||
}
|
|
||||||
out_write.Out(gpio.High)
|
|
||||||
return nil
|
|
||||||
}
|
|
283
RaspberryPi/apple2driver/a2io/communication.go
Normal file
283
RaspberryPi/apple2driver/a2io/communication.go
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
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 * 5
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadString() (string, error) {
|
||||||
|
var inBytes bytes.Buffer
|
||||||
|
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) {
|
||||||
|
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 {
|
||||||
|
// wait for the Apple II to be ready to read
|
||||||
|
for in_read.Read() == gpio.High {
|
||||||
|
if !in_read.WaitForEdge(edgeTimeout) {
|
||||||
|
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) {
|
||||||
|
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
|
||||||
|
}
|
BIN
RaspberryPi/apple2driver/apple2driver
Executable file
BIN
RaspberryPi/apple2driver/apple2driver
Executable file
Binary file not shown.
49
RaspberryPi/apple2driver/driver.go
Normal file
49
RaspberryPi/apple2driver/driver.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/handlers"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ReadBlockCommand = 1
|
||||||
|
const WriteBlockCommand = 2
|
||||||
|
const GetTimeCommand = 3
|
||||||
|
const ChangeDriveCommand = 4
|
||||||
|
const ExecCommand = 5
|
||||||
|
const LoadFileCommand = 6
|
||||||
|
const SaveFileCommand = 7
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a2io.InitGpio()
|
||||||
|
|
||||||
|
fmt.Printf("Starting Apple II RPi...\n")
|
||||||
|
|
||||||
|
fileName := os.Args[1]
|
||||||
|
|
||||||
|
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR: %s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
command, err := a2io.ReadByte()
|
||||||
|
if err == nil {
|
||||||
|
switch command {
|
||||||
|
case ReadBlockCommand:
|
||||||
|
handlers.ReadBlockCommand(file)
|
||||||
|
case WriteBlockCommand:
|
||||||
|
handlers.WriteBlockCommand(file)
|
||||||
|
case GetTimeCommand:
|
||||||
|
handlers.GetTimeCommand()
|
||||||
|
case ExecCommand:
|
||||||
|
handlers.ExecCommand()
|
||||||
|
case LoadFileCommand:
|
||||||
|
handlers.LoadFileCommand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
RaspberryPi/apple2driver/go.mod
Normal file
5
RaspberryPi/apple2driver/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require periph.io/x/periph v3.6.8+incompatible
|
2
RaspberryPi/apple2driver/go.sum
Normal file
2
RaspberryPi/apple2driver/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
periph.io/x/periph v3.6.8+incompatible h1:lki0ie6wHtvlilXhIkabdCUQMpb5QN4Fx33yNQdqnaA=
|
||||||
|
periph.io/x/periph v3.6.8+incompatible/go.mod h1:EWr+FCIU2dBWz5/wSWeiIUJTriYv9v2j2ENBmgYyy7Y=
|
60
RaspberryPi/apple2driver/handlers/exec.go
Normal file
60
RaspberryPi/apple2driver/handlers/exec.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExecCommand() {
|
||||||
|
workingDirectory, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
workingDirectory = "/home"
|
||||||
|
a2io.WriteString("Failed to get current working directory, setting to /home\r")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Reading command to execute...\n")
|
||||||
|
linuxCommand, err := a2io.ReadString()
|
||||||
|
fmt.Printf("Command to run: %s\n", linuxCommand)
|
||||||
|
if strings.HasPrefix(linuxCommand, "cd ") {
|
||||||
|
workingDirectory = strings.Replace(linuxCommand, "cd ", "", 1)
|
||||||
|
err = os.Chdir(workingDirectory)
|
||||||
|
if err != nil {
|
||||||
|
a2io.WriteString("Failed to set working directory\r")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
a2io.WriteString("Working directory set\r")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if linuxCommand == "a2help" {
|
||||||
|
a2io.WriteString("\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. Running\r" +
|
||||||
|
"commands that do not exit will hang. For example, do not use ping without a\r" +
|
||||||
|
"way to limit output like -c 1.\r" +
|
||||||
|
"\r" +
|
||||||
|
"Built-in commands:\r" +
|
||||||
|
"a2help - display this message\r" +
|
||||||
|
"a2wifi - set up wifi\r" +
|
||||||
|
"\r")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd := exec.Command("bash", "-c", linuxCommand)
|
||||||
|
cmd.Dir = workingDirectory
|
||||||
|
cmdOut, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to execute command\n")
|
||||||
|
a2io.WriteString("Failed to execute command\r")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Command output: %s\n", cmdOut)
|
||||||
|
apple2string := strings.Replace(string(cmdOut), "\n", "\r", -1)
|
||||||
|
err = a2io.WriteString(apple2string)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to send command output\n")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
44
RaspberryPi/apple2driver/handlers/getTime.go
Normal file
44
RaspberryPi/apple2driver/handlers/getTime.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTimeCommand() {
|
||||||
|
fmt.Printf("Sending date/time...\n")
|
||||||
|
/* 49041 ($BF91) 49040 ($BF90)
|
||||||
|
|
||||||
|
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||||
|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||||
|
DATE: | year | month | day |
|
||||||
|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|
||||||
|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||||
|
TIME: | hour | | minute |
|
||||||
|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
49043 ($BF93) 49042 ($BF92)
|
||||||
|
*/
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
year := now.Year() % 100
|
||||||
|
month := now.Month()
|
||||||
|
day := now.Day()
|
||||||
|
hour := now.Hour()
|
||||||
|
minute := now.Minute()
|
||||||
|
|
||||||
|
bf91 := (byte(year) << 1) + (byte(month) >> 3)
|
||||||
|
bf90 := ((byte(month) & 15) << 5) + byte(day)
|
||||||
|
bf93 := byte(hour)
|
||||||
|
bf92 := byte(minute)
|
||||||
|
|
||||||
|
a2io.WriteByte(bf90)
|
||||||
|
a2io.WriteByte(bf91)
|
||||||
|
a2io.WriteByte(bf92)
|
||||||
|
a2io.WriteByte(bf93)
|
||||||
|
fmt.Printf("Send time complete\n")
|
||||||
|
}
|
39
RaspberryPi/apple2driver/handlers/loadFile.go
Normal file
39
RaspberryPi/apple2driver/handlers/loadFile.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadFileCommand() {
|
||||||
|
fileName, _ := a2io.ReadString()
|
||||||
|
|
||||||
|
file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR: %s\n", err.Error())
|
||||||
|
a2io.WriteByte(0)
|
||||||
|
a2io.WriteByte(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInfo, _ := file.Stat()
|
||||||
|
fileSize := int(fileInfo.Size())
|
||||||
|
|
||||||
|
fmt.Printf("FileSize: %d\n", fileSize)
|
||||||
|
|
||||||
|
fileSizeHigh := byte(fileSize >> 8)
|
||||||
|
fileSizeLow := byte(fileSize & 255)
|
||||||
|
|
||||||
|
a2io.WriteByte(fileSizeLow)
|
||||||
|
a2io.WriteByte(fileSizeHigh)
|
||||||
|
|
||||||
|
buffer := make([]byte, fileSize)
|
||||||
|
|
||||||
|
fmt.Printf("Read file %s SizeHigh: %d SizeLow: %d\n", fileName, fileSizeHigh, fileSizeLow)
|
||||||
|
|
||||||
|
file.Read(buffer)
|
||||||
|
|
||||||
|
a2io.WriteBuffer(buffer)
|
||||||
|
}
|
28
RaspberryPi/apple2driver/handlers/readBlock.go
Normal file
28
RaspberryPi/apple2driver/handlers/readBlock.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadBlockCommand(file *os.File) {
|
||||||
|
blockLow, _ := a2io.ReadByte()
|
||||||
|
blockHigh, _ := a2io.ReadByte()
|
||||||
|
|
||||||
|
buffer := make([]byte, 512)
|
||||||
|
var block int64
|
||||||
|
block = int64(blockHigh)*256 + int64(blockLow)
|
||||||
|
|
||||||
|
fmt.Printf("Read block %d\n", block)
|
||||||
|
|
||||||
|
file.ReadAt(buffer, int64(block)*512)
|
||||||
|
|
||||||
|
err := a2io.WriteBlock(buffer)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Printf("Read block completed\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Failed to read block\n")
|
||||||
|
}
|
||||||
|
}
|
24
RaspberryPi/apple2driver/handlers/writeBlock.go
Normal file
24
RaspberryPi/apple2driver/handlers/writeBlock.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteBlockCommand(file *os.File) {
|
||||||
|
blockLow, _ := a2io.ReadByte()
|
||||||
|
blockHigh, _ := a2io.ReadByte()
|
||||||
|
|
||||||
|
buffer := make([]byte, 512)
|
||||||
|
var block int64
|
||||||
|
block = int64(blockHigh)*256 + int64(blockLow)
|
||||||
|
|
||||||
|
fmt.Printf("Write block %d\n", block)
|
||||||
|
|
||||||
|
a2io.ReadBlock(buffer)
|
||||||
|
file.WriteAt(buffer, int64(block)*512)
|
||||||
|
file.Sync()
|
||||||
|
fmt.Printf("Write block completed\n")
|
||||||
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
module github.com/tjboldt/Apple2-IO-RPi
|
|
||||||
|
|
||||||
go 1.16
|
|
||||||
|
|
||||||
require periph.io/x/periph v3.6.7+incompatible
|
|
|
@ -1,2 +0,0 @@
|
||||||
periph.io/x/periph v3.6.7+incompatible h1:ZfRdHbcxVekgSJZmxp3873YpxNdWs6wg7waDCF7GB18=
|
|
||||||
periph.io/x/periph v3.6.7+incompatible/go.mod h1:EWr+FCIU2dBWz5/wSWeiIUJTriYv9v2j2ENBmgYyy7Y=
|
|
Loading…
Reference in New Issue
Block a user