2021-10-30 13:50:00 +00:00
|
|
|
// Copyright Terence J. Boldt (c)2020-2021
|
|
|
|
// Use of this source code is governed by an MIT
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// This file is contains the main driver code for the Raspberry Pi side of
|
|
|
|
// the Apple2-IO-RPi hardware. Commands are sent from the Apple II and
|
|
|
|
// responses are sent back from the Raspberry Pi.
|
2021-05-30 11:18:39 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-10-06 12:34:18 +00:00
|
|
|
"flag"
|
2021-05-30 11:18:39 +00:00
|
|
|
"fmt"
|
|
|
|
"os"
|
2021-10-06 12:34:18 +00:00
|
|
|
"path/filepath"
|
2021-11-11 02:44:28 +00:00
|
|
|
"time"
|
2021-05-30 11:18:39 +00:00
|
|
|
|
|
|
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
|
|
|
|
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/handlers"
|
|
|
|
)
|
|
|
|
|
2021-11-25 23:45:56 +00:00
|
|
|
const resetCommand = 0
|
2021-11-03 09:33:09 +00:00
|
|
|
const readBlockCommand = 1
|
|
|
|
const writeBlockCommand = 2
|
|
|
|
const getTimeCommand = 3
|
2021-11-21 19:56:13 +00:00
|
|
|
const changeDriveCommand = 4 // not currently used
|
2021-11-03 09:33:09 +00:00
|
|
|
const execCommand = 5
|
|
|
|
const loadFileCommand = 6
|
2021-11-21 19:56:13 +00:00
|
|
|
const saveFileCommand = 7 // not implemented yet
|
2021-11-03 09:33:09 +00:00
|
|
|
const menuCommand = 8
|
2021-11-21 19:56:13 +00:00
|
|
|
const shellCommand = 9
|
2021-05-30 11:18:39 +00:00
|
|
|
|
|
|
|
func main() {
|
2021-10-06 12:34:18 +00:00
|
|
|
drive1, drive2 := getDriveFiles()
|
2021-05-30 11:18:39 +00:00
|
|
|
|
|
|
|
fmt.Printf("Starting Apple II RPi...\n")
|
|
|
|
|
2021-10-30 11:03:18 +00:00
|
|
|
comm := a2io.A2Gpio{}
|
|
|
|
|
|
|
|
handlers.SetCommunication(comm)
|
|
|
|
comm.Init()
|
2021-05-30 11:18:39 +00:00
|
|
|
|
2021-11-11 02:44:28 +00:00
|
|
|
lastCommandTime := time.Now()
|
|
|
|
|
2021-11-25 23:45:56 +00:00
|
|
|
// In case Apple II is waiting, send 0 byte to start
|
|
|
|
comm.WriteByte(0)
|
|
|
|
|
2021-05-30 11:18:39 +00:00
|
|
|
for {
|
2021-10-30 11:03:18 +00:00
|
|
|
command, err := comm.ReadByte()
|
2021-05-30 11:18:39 +00:00
|
|
|
if err == nil {
|
2021-11-11 02:44:28 +00:00
|
|
|
lastCommandTime = time.Now()
|
2021-05-30 11:18:39 +00:00
|
|
|
switch command {
|
2021-11-25 23:45:56 +00:00
|
|
|
case resetCommand:
|
|
|
|
handlers.ResetCommand()
|
2021-11-03 09:33:09 +00:00
|
|
|
case readBlockCommand:
|
2021-10-06 12:34:18 +00:00
|
|
|
handlers.ReadBlockCommand(drive1, drive2)
|
2021-11-03 09:33:09 +00:00
|
|
|
case writeBlockCommand:
|
2021-10-06 12:34:18 +00:00
|
|
|
handlers.WriteBlockCommand(drive1, drive2)
|
2021-11-03 09:33:09 +00:00
|
|
|
case getTimeCommand:
|
2021-05-30 11:18:39 +00:00
|
|
|
handlers.GetTimeCommand()
|
2021-11-03 09:33:09 +00:00
|
|
|
case execCommand:
|
2021-05-30 11:18:39 +00:00
|
|
|
handlers.ExecCommand()
|
2021-11-03 09:33:09 +00:00
|
|
|
case loadFileCommand:
|
2021-05-30 11:18:39 +00:00
|
|
|
handlers.LoadFileCommand()
|
2021-11-03 09:33:09 +00:00
|
|
|
case menuCommand:
|
2021-06-01 23:08:21 +00:00
|
|
|
handlers.MenuCommand()
|
2021-11-21 19:56:13 +00:00
|
|
|
case shellCommand:
|
|
|
|
handlers.ShellCommand()
|
2021-05-30 11:18:39 +00:00
|
|
|
}
|
2021-11-11 02:44:28 +00:00
|
|
|
// temporary workaround for busy wait loop heating up the RPi
|
|
|
|
} else if time.Since(lastCommandTime) > time.Millisecond*100 {
|
|
|
|
time.Sleep(time.Millisecond * 100)
|
2021-05-30 11:18:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-06 12:34:18 +00:00
|
|
|
|
|
|
|
func getDriveFiles() (*os.File, *os.File) {
|
|
|
|
var drive1Name string
|
|
|
|
var drive2Name string
|
|
|
|
|
|
|
|
execName, _ := os.Executable()
|
|
|
|
path := filepath.Dir(execName)
|
|
|
|
path = filepath.Join(path, "..")
|
|
|
|
path, _ = filepath.EvalSymlinks(path)
|
|
|
|
defaultFileName := filepath.Join(path, "Apple2-IO-RPi.hdv")
|
|
|
|
|
|
|
|
flag.StringVar(&drive1Name, "d1", "", "A ProDOS format drive image for drive 1")
|
|
|
|
flag.StringVar(&drive2Name, "d2", defaultFileName, "A ProDOS format drive image for drive 2 and will be used for drive 1 if drive 1 empty")
|
|
|
|
flag.Parse()
|
|
|
|
|
2021-11-03 09:33:09 +00:00
|
|
|
var drive1 *os.File
|
|
|
|
var drive2 *os.File
|
2021-10-06 12:34:18 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
if len(drive1Name) > 0 {
|
|
|
|
fmt.Printf("Opening Drive 1 as: %s\n", drive1Name)
|
|
|
|
drive1, err = os.OpenFile(drive1Name, os.O_RDWR, 0755)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("ERROR: %s", err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(drive2Name) > 0 {
|
|
|
|
if drive1 == nil {
|
|
|
|
fmt.Printf("Opening Drive 1 as: %s because Drive 1 was empty\n", drive2Name)
|
|
|
|
drive1, err = os.OpenFile(drive2Name, os.O_RDWR, 0755)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("ERROR: %s", err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fmt.Printf("Opening Drive 2 as: %s\n", drive2Name)
|
|
|
|
drive2, err = os.OpenFile(drive2Name, os.O_RDWR, 0755)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("ERROR: %s", err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if drive1 == nil {
|
|
|
|
flag.PrintDefaults()
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
return drive1, drive2
|
|
|
|
}
|