diff --git a/RaspberryPi/Driver.go b/RaspberryPi/Driver.go index 31b38f4..32c1eb5 100644 --- a/RaspberryPi/Driver.go +++ b/RaspberryPi/Driver.go @@ -1,14 +1,17 @@ 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" - "fmt" - "os" "time" - "errors" ) + var edgeTimeout time.Duration var out_write gpio.PinIO @@ -31,23 +34,259 @@ var in_bit0 gpio.PinIO const ReadBlockCommand = 1 const WriteBlockCommand = 2 const GetTimeCommand = 3 +const ChangeDriveCommand = 4 +const ExecCommand = 5 + +var debug bool = false + +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() + } + } + } +} + +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) + readBlock(buffer) +} + +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() +} + +func handleExecCommand() { + linuxCommand,err := readString() + cmd := exec.Command("bash", "-c", linuxCommand) + cmdOut, err := cmd.Output() + if err != nil { + fmt.Printf("Failed to execute command\n") + } + writeString(cmdOut) +} + +func handleGetTimeCommand() { + /* 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) +} + +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("GPIO5") + out_read = gpioreg.ByName("GPIO11") + out_commandWrite = gpioreg.ByName("GPIO9") + out_commandRead = 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("GPIO12") + in_read = gpioreg.ByName("GPIO16") + in_commandWrite = gpioreg.ByName("GPIO20") + in_commandRead = 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) + + edgeTimeout = time.Second * 5 +} + +func dumpBlock(buffer []byte) { + for i := 0; i < 512; i++ { + fmt.Printf("%02X ", buffer[i]) + } +} + +func readString() (string, error) { + inByte := byte(0) + var inBytes bytes.Buffer + var err error + for inByte == 0 { + inByte,err = readByte() + if err != nil { + return "", err + } + inBytes.WriteByte(inByte) + } + return string(inBytes.Bytes()), nil +} + +func writeString(outBytes []byte) error { + for outByte := range outBytes { + err := writeByte(byte(outByte)) + if err != nil { + return err + } + } + writeByte(0) + return nil +} + +func readByte() (byte, error) { + data, err := readNibble() + data = data << byte(4) + if err != nil { + return 0, err + } + highNibble, err := readNibble() + if err != nil { + return 0, err + } + data += highNibble + //fmt.Printf("R%02X ", data) + return data, nil +} + +func writeByte(data byte) error { + //fmt.Printf("W%02X ", data) + err := writeNibble(data >> 4) + if err != nil { + return err + } + err = writeNibble(data & 15) + if err != nil { + return err + } + + return nil +} func readNibble() (byte, error) { // let the Apple II know we are ready to read - //fmt.Printf("let the Apple II know we are ready to read\n") + 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 - //fmt.Printf("wait for the Apple II to write\n") + if debug { + fmt.Printf("wait for the Apple II to write\n") + } for in_write.Read() == gpio.High { if !in_write.WaitForEdge(edgeTimeout) { - //fmt.Printf("Timed out reading nibble -- write stuck high\n") + if debug { + fmt.Printf("Timed out reading nibble -- write stuck high\n") + } return 0, errors.New("Timed out reading nibble -- write stuck high\n") } } // get a nibble of data - //fmt.Printf("get a nibble of data\n") + if debug { + fmt.Printf("get a nibble of data\n") + } var nibble byte nibble = 0 bit3 := in_bit3.Read() @@ -76,7 +315,9 @@ func readNibble() (byte, error) { //fmt.Printf("wait for the Apple II to finish writing\n") for in_write.Read() == gpio.Low { if !in_write.WaitForEdge(edgeTimeout) { - //fmt.Printf("Timed out reading nibble -- write stuck low\n") + if debug { + fmt.Printf("Timed out reading nibble -- write stuck low\n") + } return 0, errors.New("Timed out reading nibble -- write stuck low") } } @@ -84,23 +325,16 @@ func readNibble() (byte, error) { return nibble, nil } -func readByte() (byte, error) { - data, err := readNibble() - data = data << byte(4) - if err != nil { return 0, err } - highNibble, err := readNibble() - if err != nil { return 0, err } - data += highNibble - //fmt.Printf("R%02X ", data) - return data, nil -} - func writeNibble(data byte) error { // wait for the Apple II to be ready to read - //fmt.Printf("wait for the Apple II to be ready to read\n") + 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) { - //fmt.Printf("Timed out writing nibble -- read stuck high\n") + if debug { + fmt.Printf("Timed out writing nibble -- read stuck high\n") + } return errors.New("Timed out writing nibble -- read stuck high") } } @@ -130,176 +364,26 @@ func writeNibble(data byte) error { out_bit0.Out(bit0) // let Apple II know we're writing - //fmt.Printf("let Apple II know we're writing\n") + 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) { - //fmt.Printf("Timed out writing nibble -- read stuck low\n") + if debug { + fmt.Printf("Timed out writing nibble -- read stuck low\n") + } return errors.New("Timed out writing nibble -- read stuck low") } } // let the Apple II know we are done writing - //fmt.Printf("let the Apple II know we are done writing\n") + if debug { + fmt.Printf("let the Apple II know we are done writing\n") + } out_write.Out(gpio.High) return nil } - -func writeByte(data byte) error { - //fmt.Printf("W%02X ", data) - err := writeNibble(data >> 4) - if err != nil { return err } - err = writeNibble(data & 15) - if err != nil { return err } - - return nil -} - -func readBlock(buffer []byte) error { - for i := 0; i < 512; i++ { - err := writeByte(buffer[i]) - if err != nil { return err } - } - - return nil -} - -func dumpBlock(buffer []byte) { - for i := 0; i < 512; i++ { - fmt.Printf("%02X ", buffer[i]) - } -} - -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 main() { - host.Init() - - out_write = gpioreg.ByName("GPIO5") - out_read = gpioreg.ByName("GPIO11") - out_commandWrite = gpioreg.ByName("GPIO9") - out_commandRead = 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("GPIO12") - in_read = gpioreg.ByName("GPIO16") - in_commandWrite = gpioreg.ByName("GPIO20") - in_commandRead = 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) - - edgeTimeout = time.Second * 5 - - 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) - } - //if err := f.Close(); err != nil { - //log.Fatal(err) - //} - - //for in_write.Read() == gpio.Low { - // in_write.WaitForEdge(-1) - //} - buffer := make([]byte, 512) - //file.ReadAt(buffer, int64(0) * 512) - //dumpBlock(buffer) - - for { - //fmt.Printf("Check for command") - - command,err := readByte(); - if err != nil { - //fmt.Printf("Timed out waiting for command\n") - } else { - switch command { - case ReadBlockCommand: - blockLow,_ := readByte(); - blockHigh,_ := readByte(); - - - var block int64 - block = int64(blockHigh) * 256 + int64(blockLow) - - fmt.Printf("Read block %d\n", block) - - - file.ReadAt(buffer, int64(block) * 512) - //dumpBlock(buffer) - readBlock(buffer) - break - case WriteBlockCommand: - blockLow,_ := readByte(); - blockHigh,_ := readByte(); - - - 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() - break - case GetTimeCommand: - /* - 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) - break - } - } - } -} -