Add ProDOS date/time support

This commit is contained in:
Terence Boldt 2020-12-15 21:05:12 -05:00
parent bf2d93e22b
commit 9c0b548aab
5 changed files with 137 additions and 44 deletions

View File

@ -1,4 +1,4 @@
ca65 V2.19 - Git 59c58ac ca65 V2.19 - Git 59c58acb
Main file : Driver.asm Main file : Driver.asm
Current file: Driver.asm Current file: Driver.asm

View File

@ -16,6 +16,7 @@ InputByte = $c08e
OutputByte = $c08d OutputByte = $c08d
ReadBlockCommand = $01 ReadBlockCommand = $01
WriteBlockCommand = $02 WriteBlockCommand = $02
GetTimeCommand = $03
NibbleStorage = $1d NibbleStorage = $1d
.org STARTSLOT .org STARTSLOT
@ -85,7 +86,16 @@ GetStatus:
; ProDOS Read Block Command ; ProDOS Read Block Command
ReadBlock: ReadBlock:
lda #ReadBlockCommand ldy #$00 ;Get the current time on each block read for now
lda #GetTimeCommand
jsr SendByte
getTimeByte:
jsr GetByte
sta $bf90,y
iny
cpy #$04
bne getTimeByte
lda #ReadBlockCommand ;read the block after setting the clock
jsr SendByte jsr SendByte
lda BlockLo lda BlockLo
jsr SendByte jsr SendByte

Binary file not shown.

View File

@ -13,7 +13,7 @@ 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 1. DONE - Build initial prototype that reads/writes virtual hard drive
2. DONE - Create firmware to make the card a bootable device 2. DONE - Create firmware to make the card a bootable device
3. DONE - Fix board with updated second prototype PCB 3. DONE - Fix board with updated second prototype PCB
4. Add ProDOS clock driver 4. DONE - Add ProDOS clock driver
5. Add RPi terminal access 5. Add RPi terminal access
6. Add web service call support 6. Add web service call support
7. Proxy VNC connection, rendering as Apple II compatible graphics 7. Proxy VNC connection, rendering as Apple II compatible graphics

View File

@ -1,13 +1,15 @@
package main package main
import ( import (
//"time"
"periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpioreg" "periph.io/x/periph/conn/gpio/gpioreg"
"periph.io/x/periph/host" "periph.io/x/periph/host"
"fmt" "fmt"
"os" "os"
"time"
"errors"
) )
var edgeTimeout time.Duration
var out_write gpio.PinIO var out_write gpio.PinIO
var out_read gpio.PinIO var out_read gpio.PinIO
@ -26,7 +28,11 @@ var in_bit2 gpio.PinIO
var in_bit1 gpio.PinIO var in_bit1 gpio.PinIO
var in_bit0 gpio.PinIO var in_bit0 gpio.PinIO
func readNibble() byte { const ReadBlockCommand = 1
const WriteBlockCommand = 2
const GetTimeCommand = 3
func readNibble() (byte, error) {
// let the Apple II know we are ready to read // let the Apple II know we are ready to read
//fmt.Printf("let the Apple II know we are ready to read\n") //fmt.Printf("let the Apple II know we are ready to read\n")
out_read.Out(gpio.Low) out_read.Out(gpio.Low)
@ -34,7 +40,10 @@ func readNibble() byte {
// wait for the Apple II to write // wait for the Apple II to write
//fmt.Printf("wait for the Apple II to write\n") //fmt.Printf("wait for the Apple II to write\n")
for in_write.Read() == gpio.High { for in_write.Read() == gpio.High {
in_write.WaitForEdge(-1) 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 // get a nibble of data
@ -66,24 +75,34 @@ func readNibble() byte {
// wait for the Apple II to finish writing // wait for the Apple II to finish writing
//fmt.Printf("wait for the Apple II to finish writing\n") //fmt.Printf("wait for the Apple II to finish writing\n")
for in_write.Read() == gpio.Low { for in_write.Read() == gpio.Low {
in_write.WaitForEdge(-1) 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 return nibble, nil
} }
func readByte() byte { func readByte() (byte, error) {
data := byte(0) data, err := readNibble()
data = readNibble() << byte(4) data = data << byte(4)
data += readNibble() if err != nil { return 0, err }
return data highNibble, err := readNibble()
if err != nil { return 0, err }
data += highNibble
//fmt.Printf("R%02X ", data)
return data, nil
} }
func writeNibble(data byte) { func writeNibble(data byte) error {
// wait for the Apple II to be ready to read // wait for the Apple II to be ready to read
//fmt.Printf("wait for the Apple II to be ready to read\n") //fmt.Printf("wait for the Apple II to be ready to read\n")
for in_read.Read() == gpio.High { for in_read.Read() == gpio.High {
in_read.WaitForEdge(-1) 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 bit3 := gpio.Low
@ -118,23 +137,35 @@ func writeNibble(data byte) {
// wait for the Apple II to finsih reading // wait for the Apple II to finsih reading
//fmt.Printf("wait for the Apple II to finsih reading\n") //fmt.Printf("wait for the Apple II to finsih reading\n")
for in_read.Read() == gpio.Low { for in_read.Read() == gpio.Low {
in_read.WaitForEdge(-1) 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 // let the Apple II know we are done writing
//fmt.Printf("let the Apple II know we are done writing\n") //fmt.Printf("let the Apple II know we are done writing\n")
out_write.Out(gpio.High) out_write.Out(gpio.High)
return nil
} }
func writeByte(data byte) { func writeByte(data byte) error {
writeNibble(data >> 4) //fmt.Printf("W%02X ", data)
writeNibble(data & 15) err := writeNibble(data >> 4)
if err != nil { return err }
err = writeNibble(data & 15)
if err != nil { return err }
return nil
} }
func readBlock(buffer []byte) { func readBlock(buffer []byte) error {
for i := 0; i < 512; i++ { for i := 0; i < 512; i++ {
writeByte(buffer[i]) err := writeByte(buffer[i])
if err != nil { return err }
} }
return nil
} }
func dumpBlock(buffer []byte) { func dumpBlock(buffer []byte) {
@ -143,10 +174,14 @@ func dumpBlock(buffer []byte) {
} }
} }
func writeBlock(buffer []byte) { func writeBlock(buffer []byte) error {
var err error
for i := 0; i < 512; i++ { for i := 0; i < 512; i++ {
buffer[i] = readByte() buffer[i], err = readByte()
if err != nil { return err }
} }
return nil
} }
func main() { func main() {
@ -169,11 +204,17 @@ func main() {
in_bit1 = gpioreg.ByName("GPIO13") in_bit1 = gpioreg.ByName("GPIO13")
in_bit0 = gpioreg.ByName("GPIO6") 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") fmt.Printf("Starting Apple II RPi...\n")
fileName := "Total Replay v4.0-rc.1.hdv" fileName := os.Args[1]
file, err := os.OpenFile(fileName, os.O_RDWR, 0755) file, err := os.OpenFile(fileName, os.O_RDWR, 0755)
if err != nil { if err != nil {
//log.Fatal(err) fmt.Printf("ERROR: %s", err.Error())
os.Exit(1)
} }
//if err := f.Close(); err != nil { //if err := f.Close(); err != nil {
//log.Fatal(err) //log.Fatal(err)
@ -187,34 +228,76 @@ func main() {
//dumpBlock(buffer) //dumpBlock(buffer)
for { for {
command := readByte(); //fmt.Printf("Check for command")
if (command == 1) {
blockLow := readByte(); command,err := readByte();
blockHigh := readByte(); if err != nil {
//fmt.Printf("Timed out waiting for command\n")
} else {
switch command {
case ReadBlockCommand:
blockLow,_ := readByte();
blockHigh,_ := readByte();
var block int64 var block int64
block = int64(blockHigh) * 256 + int64(blockLow) block = int64(blockHigh) * 256 + int64(blockLow)
fmt.Printf("Read block %d\n", block) fmt.Printf("Read block %d\n", block)
file.ReadAt(buffer, int64(block) * 512) file.ReadAt(buffer, int64(block) * 512)
//dumpBlock(buffer) //dumpBlock(buffer)
readBlock(buffer) readBlock(buffer)
} break
if (command == 2) { case WriteBlockCommand:
blockLow := readByte(); blockLow,_ := readByte();
blockHigh := readByte(); blockHigh,_ := readByte();
var block int64 var block int64
block = int64(blockHigh) * 256 + int64(blockLow) block = int64(blockHigh) * 256 + int64(blockLow)
fmt.Printf("Write block %d\n", block) fmt.Printf("Write block %d\n", block)
writeBlock(buffer) writeBlock(buffer)
file.WriteAt(buffer, int64(block) * 512) file.WriteAt(buffer, int64(block) * 512)
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
}
} }
} }
} }