Refactor Go code into packages

This commit is contained in:
Terence Boldt 2021-05-30 07:18:39 -04:00
parent 75c953052f
commit cc560b972f
15 changed files with 538 additions and 521 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
*-bak *-bak
*.o *.o
*.DS_Store *.DS_Store
RaspberryPi/Apple2-IO-RPi RaspberryPi/apple2driver/apple2driver

View File

@ -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.

View File

@ -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
}

View 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
}

Binary file not shown.

View 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()
}
}
}
}

View 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

View 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=

View 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
}
}

View 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")
}

View 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)
}

View 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")
}
}

View 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")
}

View File

@ -1,5 +0,0 @@
module github.com/tjboldt/Apple2-IO-RPi
go 1.16
require periph.io/x/periph v3.6.7+incompatible

View File

@ -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=