Merge branch 'main' into fullbyte

This commit is contained in:
Terence Boldt 2020-12-29 19:54:54 -05:00
commit fcf8e36eec
10 changed files with 291 additions and 208 deletions

12
Apple2/driver_assemble.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
ca65 Driver.asm --listing Driver.lst
ld65 Driver.o -o Driver.bin -t none
ca65 Firmware.asm -D STARTSLOT=\$c000 -o Slot0.o
ca65 Firmware.asm -D STARTSLOT=\$c100 -o Slot1.o --listing Firmware1.lst
ca65 Firmware.asm -D STARTSLOT=\$c200 -o Slot2.o --listing Firmware2.lst
ca65 Firmware.asm -D STARTSLOT=\$c300 -o Slot3.o --listing Firmware3.lst
ca65 Firmware.asm -D STARTSLOT=\$c400 -o Slot4.o --listing Firmware4.lst
ca65 Firmware.asm -D STARTSLOT=\$c500 -o Slot5.o --listing Firmware5.lst
ca65 Firmware.asm -D STARTSLOT=\$c600 -o Slot6.o --listing Firmware6.lst
ca65 Firmware.asm -D STARTSLOT=\$c700 -o Slot7.o --listing Firmware7.lst
ld65 Slot0.o Slot1.o Slot2.o Slot3.o Slot4.o Slot5.o Slot6.o Slot7.o -o Firmware.bin -t none

View File

@ -1,12 +0,0 @@
#!/bin/sh
ca65 Driver.asm --listing Driver.lst
ld65 Driver.o -o Driver.bin -t none
ca65 Firmware.asm -D STARTSLOT=\$c000 -o Slot0.o
ca65 Firmware.asm -D STARTSLOT=\$c100 -o Slot1.o
ca65 Firmware.asm -D STARTSLOT=\$c200 -o Slot2.o
ca65 Firmware.asm -D STARTSLOT=\$c300 -o Slot3.o
ca65 Firmware.asm -D STARTSLOT=\$c400 -o Slot4.o
ca65 Firmware.asm -D STARTSLOT=\$c500 -o Slot5.o
ca65 Firmware.asm -D STARTSLOT=\$c600 -o Slot6.o
ca65 Firmware.asm -D STARTSLOT=\$c700 -o Slot7.o
ld65 Slot0.o Slot1.o Slot2.o Slot3.o Slot4.o Slot5.o Slot6.o Slot7.o -o Firmware.bin -t none

View File

@ -1,11 +0,0 @@
ldx #$50 ;slot 5 for this test
start: lda #$80 ;set read flag low (ready to read)
sta $c08d,x ;bit 1 low for writing values
waitwl: lda $c08e,x ;bit 0 low for reading values
bmi waitwl ;wait for write flag low
jsr $fde3 ;print nibble of data
lda #$c0 ;set read flag high (done reading)
sta $c08d,x
waitwh: lda $c08e,x
bpl waitwh ;wait for write flag high
bmi start ;go around againg for next nibble

View File

@ -1,3 +0,0 @@
#!/bin/sh
ca65 test.asm
ld65 test.o -o test.bin -t none

View File

@ -13,8 +13,8 @@ This is an early stage project. Currently one board has been assembled and teste
1. DONE - Build initial prototype that reads/writes virtual hard drive
2. DONE - Create firmware to make the card a bootable device
3. DONE - Fix board with updated second prototype PCB
4. DONE - Add ProDOS clock driver
5. Add RPi terminal access
4. WORKING - Add ProDOS clock driver (real driver later, for now just directly sets values)
5. WORKING - Add RPi terminal access (does not keep context between commands yet)
6. Add web service call support
7. Proxy VNC connection, rendering as Apple II compatible graphics
8. Create new schematic/PCB with faster data transfer

View File

@ -1,14 +1,18 @@
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"
"strings"
"time"
"errors"
)
var edgeTimeout time.Duration
var out_write gpio.PinIO
@ -31,230 +35,74 @@ var in_bit0 gpio.PinIO
const ReadBlockCommand = 1
const WriteBlockCommand = 2
const GetTimeCommand = 3
const ChangeDriveCommand = 4
const ExecCommand = 5
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")
out_read.Out(gpio.Low)
// wait for the Apple II to write
//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")
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")
var nibble byte
nibble = 0
bit3 := in_bit3.Read()
bit2 := in_bit2.Read()
bit1 := in_bit1.Read()
bit0 := in_bit0.Read()
if bit3 == gpio.High {
nibble += 8
}
if bit2 == gpio.High {
nibble += 4
}
if bit1 == gpio.High {
nibble += 2
}
if bit0 == gpio.High {
nibble += 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) {
//fmt.Printf("Timed out reading nibble -- write stuck low\n")
return 0, errors.New("Timed out reading nibble -- write stuck low")
}
}
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")
for in_read.Read() == gpio.High {
if !in_read.WaitForEdge(edgeTimeout) {
//fmt.Printf("Timed out writing nibble -- read stuck high\n")
return errors.New("Timed out writing nibble -- read stuck high")
}
}
bit3 := gpio.Low
bit2 := gpio.Low
bit1 := gpio.Low
bit0 := gpio.Low
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
//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")
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")
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
}
var debug bool = false
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")
initGpio()
in_write.In(gpio.PullDown, gpio.BothEdges)
in_read.In(gpio.PullDown, gpio.BothEdges)
edgeTimeout = time.Second * 5
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)
}
//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")
if debug {
fmt.Printf("Check for command\n")
}
command,err := readByte();
command, err := readByte()
if err != nil {
//fmt.Printf("Timed out waiting for command\n")
} else {
switch command {
case ReadBlockCommand:
blockLow,_ := readByte();
blockHigh,_ := readByte();
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)
break
case WriteBlockCommand:
blockLow,_ := readByte();
blockHigh,_ := readByte();
}
func handleWriteBlockCommand(file *os.File) {
blockLow, _ := readByte()
blockHigh, _ := readByte()
buffer := make([]byte, 512)
var block int64
block = int64(blockHigh)*256 + int64(blockLow)
@ -263,10 +111,30 @@ func main() {
writeBlock(buffer)
file.WriteAt(buffer, int64(block)*512)
file.Sync()
break
case GetTimeCommand:
/*
49041 ($BF91) 49040 ($BF90)
}
func handleExecCommand() {
fmt.Printf("Reading command to execute...\n")
linuxCommand,err := readString()
fmt.Printf("Command to run: %s\n", linuxCommand)
cmd := exec.Command("bash", "-c", linuxCommand)
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() {
/* 49041 ($BF91) 49040 ($BF90)
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
@ -297,9 +165,238 @@ func main() {
writeByte(bf91)
writeByte(bf92)
writeByte(bf93)
break
}
}
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) {
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) {
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
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 nibble -- write stuck high\n")
}
return 0, errors.New("Timed out reading nibble -- write stuck high\n")
}
}
// get a nibble of data
if debug {
fmt.Printf("get a nibble of data\n")
}
var nibble byte
nibble = 0
bit3 := in_bit3.Read()
bit2 := in_bit2.Read()
bit1 := in_bit1.Read()
bit0 := in_bit0.Read()
if bit3 == gpio.High {
nibble += 8
}
if bit2 == gpio.High {
nibble += 4
}
if bit1 == gpio.High {
nibble += 2
}
if bit0 == gpio.High {
nibble += 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 nibble -- write stuck low\n")
}
return 0, errors.New("Timed out reading nibble -- write stuck low")
}
}
return nibble, nil
}
func writeNibble(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 nibble -- read stuck high\n")
}
return errors.New("Timed out writing nibble -- read stuck high")
}
}
bit3 := gpio.Low
bit2 := gpio.Low
bit1 := gpio.Low
bit0 := gpio.Low
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 nibble -- read stuck low\n")
}
return errors.New("Timed out writing nibble -- 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
}