forked from Apple-2-HW/Apple2-IO-RPi
Fix Codacy lint/security warnings
This commit is contained in:
parent
c864b5e28d
commit
b37855dbfd
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -20,14 +20,14 @@ Steps to reproduce the behavior:
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Hardware (please complete the following information):**
|
||||
- Host computer [e.g. ][, ][+, //e, IIgs, etc.]
|
||||
- Additional cards [e.g. Disk ][, 80 column, TranswarpGS, etc.]
|
||||
- Apple2-IO-RPi Version [e.g. prototype 4, prototype 5]
|
||||
- Origin [e.g. Self-made, purchased without RPi, purchased with RPi]
|
||||
- Host computer (e.g. II, II+, //e, IIgs, etc.)
|
||||
- Additional cards (e.g. Disk II, 80 column, TranswarpGS, etc.)
|
||||
- Apple2-IO-RPi Version (e.g. prototype 4, prototype 5)
|
||||
- Origin (e.g. Self-made, purchased without RPi, purchased with RPi)
|
||||
- When was firmware last updated
|
||||
|
||||
**Software (please complete the following information):**
|
||||
- When was repo on the card last updated build performed
|
||||
- When was repo on the card last updated build performed
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
@ -1,14 +1,14 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: 'Feature: '
|
||||
name: Enhancement request
|
||||
about: Suggest an improvement for this project
|
||||
title: 'Enhancement: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
@ -43,7 +43,7 @@ cat \
|
||||
DriveFirmware.bin CommandFirmware.bin FileAccessFirmware.bin MenuFirmware.bin \
|
||||
> AT28C64B.bin
|
||||
|
||||
rm *.o
|
||||
rm ./*.o
|
||||
rm DriveFirmware.bin
|
||||
rm MenuFirmware.bin
|
||||
rm CommandFirmware.bin
|
||||
|
@ -115,7 +115,7 @@ the community.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
@ -123,5 +123,5 @@ enforcement ladder](https://github.com/mozilla/diversity).
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are available at
|
||||
[https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations).
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
Thanks for looking into how to contribute. You can help the following ways:
|
||||
|
||||
- Submit an Issue (Bug or Feature)
|
||||
- Send email feedback
|
||||
- Contribute code via your fork and a pull request
|
||||
- Submit an Issue (Bug or Feature)
|
||||
- Send email feedback
|
||||
- Contribute code via your fork and a pull request
|
||||
|
12
README.md
12
README.md
@ -32,8 +32,8 @@ So far, this is a project and not a finished product. The current prototype is o
|
||||
1. Have PCBs made from the gerber and drill files in the Hardware folder or email me for a blank or fully assembled board
|
||||
2. Solder chips, header and capacitors in place
|
||||
3. Attach Raspberry Pi Zero W facing outward from the card
|
||||
4. Install Raspberry Pi OS on microSD card https://www.raspberrypi.org/software/
|
||||
5. Configure wifi in boot/wpa_supplicant.conf https://howtoraspberrypi.com/how-to-raspberry-pi-headless-setup/
|
||||
4. Install [Raspberry Pi OS](https://www.raspberrypi.org/software/) on microSD card
|
||||
5. Configure wifi in [boot/wpa_supplicant.conf](https://howtoraspberrypi.com/how-to-raspberry-pi-headless-setup/)
|
||||
6. Add empty ssh file boot (for ssh access over wifi)
|
||||
7. Put microSD card in the RPi
|
||||
8. Install the expansion card into the Apple II
|
||||
@ -56,10 +56,10 @@ So far, this is a project and not a finished product. The current prototype is o
|
||||
17. `git clone https://github.com/tjboldt/Apple2-IO-RPi.git`
|
||||
18. `cd Apple2-IO-RPi/RaspberryPi/apple2driver`
|
||||
19. `go get`
|
||||
21. `go build`
|
||||
22. `./apple2driver`
|
||||
23. Optional to step above, `./apple2driver -d1 YOUR_DRIVE.hdv` (Apple2-IO-RPi.hdv is automatically selected as drive 2), or `./apple2driver -d1 YOUR_DRIVE.hdv -d2 YOUR_SECOND_DRIVE.hdv`
|
||||
24. 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 -d1 YOUR_DRIVE.hdv -d2 /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv > /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.log`)
|
||||
20. `go build`
|
||||
21. `./apple2driver`
|
||||
22. Optional to step above, `./apple2driver -d1 YOUR_DRIVE.hdv` (Apple2-IO-RPi.hdv is automatically selected as drive 2), or `./apple2driver -d1 YOUR_DRIVE.hdv -d2 YOUR_SECOND_DRIVE.hdv`
|
||||
23. 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 -d1 YOUR_DRIVE.hdv -d2 /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv > /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.log`)
|
||||
|
||||
## Setup if you received a complete board from me
|
||||
1. Put in any slot (slot 7 preferred as it is the first to boot)
|
||||
|
@ -5,8 +5,10 @@
|
||||
// This file defines the interface for communicating with the Apple II via
|
||||
// the Raspberry Pi GPIO ports but can also be mocked out for tests or
|
||||
// passed input to the user for interactive testing
|
||||
|
||||
package a2io
|
||||
|
||||
// A2Io provides an interface to send and receive data to the Apple II
|
||||
type A2Io interface {
|
||||
Init()
|
||||
WriteByte(data byte) error
|
||||
@ -17,7 +19,3 @@ type A2Io interface {
|
||||
ReadString() (string, error)
|
||||
ReadBlock(buffer []byte) error
|
||||
}
|
||||
|
||||
type A2Comm struct {
|
||||
A2Io A2Io
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// This file is used for communicating with the Apple II data bus via the
|
||||
// GPIO ports on the Raspberry Pi
|
||||
|
||||
package a2io
|
||||
|
||||
import (
|
||||
@ -19,80 +20,83 @@ import (
|
||||
|
||||
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
|
||||
var outWrite gpio.PinIO
|
||||
var outRead gpio.PinIO
|
||||
var outReserved2 gpio.PinIO
|
||||
var outReserved1 gpio.PinIO
|
||||
var outBit7 gpio.PinIO
|
||||
var outBit6 gpio.PinIO
|
||||
var outBit5 gpio.PinIO
|
||||
var outBit4 gpio.PinIO
|
||||
var outBit3 gpio.PinIO
|
||||
var outBit2 gpio.PinIO
|
||||
var outBit1 gpio.PinIO
|
||||
var outBit0 gpio.PinIO
|
||||
var inWrite gpio.PinIO
|
||||
var inRead gpio.PinIO
|
||||
var inReserved2 gpio.PinIO
|
||||
var inReserved1 gpio.PinIO
|
||||
var inBit7 gpio.PinIO
|
||||
var inBit6 gpio.PinIO
|
||||
var inBit5 gpio.PinIO
|
||||
var inBit4 gpio.PinIO
|
||||
var inBit3 gpio.PinIO
|
||||
var inBit2 gpio.PinIO
|
||||
var inBit1 gpio.PinIO
|
||||
var inBit0 gpio.PinIO
|
||||
|
||||
// A2Gpio is the live implementation of A2Io interface
|
||||
type A2Gpio struct {
|
||||
}
|
||||
|
||||
// Init initializes the GPIO ports on the Raspberry Pi
|
||||
func (a2 A2Gpio) Init() {
|
||||
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")
|
||||
outWrite = gpioreg.ByName("GPIO24")
|
||||
outRead = gpioreg.ByName("GPIO25")
|
||||
outReserved2 = gpioreg.ByName("GPIO7") //note GPIO7 and CPIO8 require extra effort to use
|
||||
outReserved1 = gpioreg.ByName("GPIO8")
|
||||
outBit7 = gpioreg.ByName("GPIO5")
|
||||
outBit6 = gpioreg.ByName("GPIO11")
|
||||
outBit5 = gpioreg.ByName("GPIO9")
|
||||
outBit4 = gpioreg.ByName("GPIO10")
|
||||
outBit3 = gpioreg.ByName("GPIO22")
|
||||
outBit2 = gpioreg.ByName("GPIO27")
|
||||
outBit1 = gpioreg.ByName("GPIO17")
|
||||
outBit0 = gpioreg.ByName("GPIO4")
|
||||
inWrite = gpioreg.ByName("GPIO23")
|
||||
inRead = gpioreg.ByName("GPIO18")
|
||||
inReserved2 = gpioreg.ByName("GPIO14")
|
||||
inReserved1 = gpioreg.ByName("GPIO15")
|
||||
inBit7 = gpioreg.ByName("GPIO12")
|
||||
inBit6 = gpioreg.ByName("GPIO16")
|
||||
inBit5 = gpioreg.ByName("GPIO20")
|
||||
inBit4 = gpioreg.ByName("GPIO21")
|
||||
inBit3 = gpioreg.ByName("GPIO26")
|
||||
inBit2 = gpioreg.ByName("GPIO19")
|
||||
inBit1 = gpioreg.ByName("GPIO13")
|
||||
inBit0 = 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)
|
||||
inWrite.In(gpio.PullDown, gpio.BothEdges)
|
||||
inRead.In(gpio.PullDown, gpio.BothEdges)
|
||||
outReserved1.Out(gpio.High)
|
||||
outReserved2.Out(gpio.High)
|
||||
outRead.Out(gpio.High)
|
||||
outWrite.Out(gpio.High)
|
||||
outBit7.Out(gpio.Low)
|
||||
outBit6.Out(gpio.Low)
|
||||
outBit5.Out(gpio.Low)
|
||||
outBit4.Out(gpio.Low)
|
||||
outBit3.Out(gpio.Low)
|
||||
outBit2.Out(gpio.Low)
|
||||
outBit1.Out(gpio.Low)
|
||||
outBit0.Out(gpio.Low)
|
||||
|
||||
edgeTimeout = time.Second
|
||||
}
|
||||
|
||||
// ReadString reads a string from the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) ReadString() (string, error) {
|
||||
var inBytes bytes.Buffer
|
||||
for {
|
||||
@ -105,9 +109,10 @@ func (a2 A2Gpio) ReadString() (string, error) {
|
||||
}
|
||||
inBytes.WriteByte(inByte)
|
||||
}
|
||||
return string(inBytes.Bytes()), nil
|
||||
return inBytes.String(), nil
|
||||
}
|
||||
|
||||
// WriteString writes a string to the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) WriteString(outString string) error {
|
||||
for _, character := range outString {
|
||||
err := a2.WriteByte(byte(character) | 128)
|
||||
@ -120,29 +125,30 @@ func (a2 A2Gpio) WriteString(outString string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadByte reads a byte from the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) ReadByte() (byte, error) {
|
||||
// let the Apple II know we are ready to read
|
||||
out_read.Out(gpio.Low)
|
||||
outRead.Out(gpio.Low)
|
||||
|
||||
// wait for the Apple II to write
|
||||
for in_write.Read() == gpio.High {
|
||||
if !in_write.WaitForEdge(edgeTimeout) {
|
||||
out_read.Out(gpio.High)
|
||||
return 0, errors.New("Timed out reading byte -- write stuck high\n")
|
||||
for inWrite.Read() == gpio.High {
|
||||
if !inWrite.WaitForEdge(edgeTimeout) {
|
||||
outRead.Out(gpio.High)
|
||||
return 0, errors.New("timed out reading byte -- write stuck high")
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
bit7 := inBit7.Read()
|
||||
bit6 := inBit6.Read()
|
||||
bit5 := inBit5.Read()
|
||||
bit4 := inBit4.Read()
|
||||
bit3 := inBit3.Read()
|
||||
bit2 := inBit2.Read()
|
||||
bit1 := inBit1.Read()
|
||||
bit0 := inBit0.Read()
|
||||
|
||||
if bit7 == gpio.High {
|
||||
data += 128
|
||||
@ -166,36 +172,37 @@ func (a2 A2Gpio) ReadByte() (byte, error) {
|
||||
data += 2
|
||||
}
|
||||
if bit0 == gpio.High {
|
||||
data += 1
|
||||
data++
|
||||
}
|
||||
|
||||
// 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)
|
||||
outRead.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")
|
||||
for inWrite.Read() == gpio.Low {
|
||||
if !inWrite.WaitForEdge(edgeTimeout) {
|
||||
return 0, errors.New("timed out reading byte -- write stuck low")
|
||||
}
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// WriteByte writes a byte to the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) WriteByte(data byte) error {
|
||||
// check if the Apple II wants to send a byte to us first
|
||||
if in_write.Read() == gpio.Low {
|
||||
out_write.Out(gpio.High)
|
||||
return errors.New("Can't write byte while byte is incoming")
|
||||
if inWrite.Read() == gpio.Low {
|
||||
outWrite.Out(gpio.High)
|
||||
return errors.New("can't write byte while byte is incoming")
|
||||
}
|
||||
|
||||
// wait for the Apple II to be ready to read
|
||||
for in_read.Read() == gpio.High {
|
||||
if !in_read.WaitForEdge(edgeTimeout) {
|
||||
out_write.Out(gpio.High)
|
||||
return errors.New("Timed out writing byte -- read stuck high")
|
||||
for inRead.Read() == gpio.High {
|
||||
if !inRead.WaitForEdge(edgeTimeout) {
|
||||
outWrite.Out(gpio.High)
|
||||
return errors.New("timed out writing byte -- read stuck high")
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,60 +218,61 @@ func (a2 A2Gpio) WriteByte(data byte) error {
|
||||
if ((data & 128) >> 7) == 1 {
|
||||
bit7 = gpio.High
|
||||
}
|
||||
out_bit7.Out(bit7)
|
||||
outBit7.Out(bit7)
|
||||
|
||||
if ((data & 64) >> 6) == 1 {
|
||||
bit6 = gpio.High
|
||||
}
|
||||
out_bit6.Out(bit6)
|
||||
outBit6.Out(bit6)
|
||||
|
||||
if ((data & 32) >> 5) == 1 {
|
||||
bit5 = gpio.High
|
||||
}
|
||||
out_bit5.Out(bit5)
|
||||
outBit5.Out(bit5)
|
||||
|
||||
if ((data & 16) >> 4) == 1 {
|
||||
bit4 = gpio.High
|
||||
}
|
||||
out_bit4.Out(bit4)
|
||||
outBit4.Out(bit4)
|
||||
|
||||
if ((data & 8) >> 3) == 1 {
|
||||
bit3 = gpio.High
|
||||
}
|
||||
out_bit3.Out(bit3)
|
||||
outBit3.Out(bit3)
|
||||
|
||||
if ((data & 4) >> 2) == 1 {
|
||||
bit2 = gpio.High
|
||||
}
|
||||
out_bit2.Out(bit2)
|
||||
outBit2.Out(bit2)
|
||||
|
||||
if ((data & 2) >> 1) == 1 {
|
||||
bit1 = gpio.High
|
||||
}
|
||||
out_bit1.Out(bit1)
|
||||
outBit1.Out(bit1)
|
||||
|
||||
if (data & 1) == 1 {
|
||||
bit0 = gpio.High
|
||||
}
|
||||
out_bit0.Out(bit0)
|
||||
outBit0.Out(bit0)
|
||||
|
||||
// let Apple II know we're writing
|
||||
out_write.Out(gpio.Low)
|
||||
outWrite.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) {
|
||||
out_write.Out(gpio.High)
|
||||
return errors.New("Timed out writing byte -- read stuck low")
|
||||
for inRead.Read() == gpio.Low {
|
||||
if !inRead.WaitForEdge(edgeTimeout) {
|
||||
outWrite.Out(gpio.High)
|
||||
return errors.New("timed out writing byte -- read stuck low")
|
||||
}
|
||||
}
|
||||
|
||||
// let the Apple II know we are done writing
|
||||
out_write.Out(gpio.High)
|
||||
outWrite.Out(gpio.High)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteBlock writes 512 bytes to the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) WriteBlock(buffer []byte) error {
|
||||
for i := 0; i < 512; i++ {
|
||||
err := a2.WriteByte(buffer[i])
|
||||
@ -276,6 +284,7 @@ func (a2 A2Gpio) WriteBlock(buffer []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadBlock reads 512 bytes from the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) ReadBlock(buffer []byte) error {
|
||||
var err error
|
||||
for i := 0; i < 512; i++ {
|
||||
@ -288,6 +297,7 @@ func (a2 A2Gpio) ReadBlock(buffer []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteBuffer writes a buffer of bytes to the Apple II via Raspberry Pi's GPIO ports
|
||||
func (a2 A2Gpio) WriteBuffer(buffer []byte) error {
|
||||
bufferSize := len(buffer)
|
||||
for i := 0; i < bufferSize; i++ {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// This file is used for mocking the GPIO code so that unit tests can be run
|
||||
// on any machine and not just a Raspberry Pi
|
||||
|
||||
package a2io
|
||||
|
||||
import (
|
||||
@ -11,6 +12,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MockIoData is used to verify tests were successful
|
||||
type MockIoData struct {
|
||||
BytesToRead []byte
|
||||
BytesWritten []byte
|
||||
@ -19,20 +21,24 @@ type MockIoData struct {
|
||||
ErrorToThrow error
|
||||
}
|
||||
|
||||
// MockIo implements A2Io to allow unit tests to run without needing GPIO functioning
|
||||
type MockIo struct {
|
||||
Data *MockIoData
|
||||
}
|
||||
|
||||
// Init is only here to complete A2Io interface
|
||||
func (mockIo MockIo) Init() {
|
||||
|
||||
}
|
||||
|
||||
// WriteByte mocks writing a byte to the Apple II
|
||||
func (mockIo MockIo) WriteByte(data byte) error {
|
||||
mockIo.Data.BytesWritten[mockIo.Data.NumberBytesWritten] = data
|
||||
mockIo.Data.NumberBytesWritten++
|
||||
return mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// WriteString mocks writing a string to the Apple II
|
||||
func (mockIo MockIo) WriteString(outString string) error {
|
||||
for i, b := range outString {
|
||||
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = byte(b)
|
||||
@ -41,6 +47,7 @@ func (mockIo MockIo) WriteString(outString string) error {
|
||||
return mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// WriteBlock mocks writing a block to the Apple II
|
||||
func (mockIo MockIo) WriteBlock(buffer []byte) error {
|
||||
for i, b := range buffer {
|
||||
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = b
|
||||
@ -49,6 +56,7 @@ func (mockIo MockIo) WriteBlock(buffer []byte) error {
|
||||
return mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// WriteBuffer mocks writing a buffer to the Apple II
|
||||
func (mockIo MockIo) WriteBuffer(buffer []byte) error {
|
||||
for i, b := range buffer {
|
||||
mockIo.Data.BytesWritten[i+mockIo.Data.NumberBytesWritten] = b
|
||||
@ -57,17 +65,19 @@ func (mockIo MockIo) WriteBuffer(buffer []byte) error {
|
||||
return mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// ReadByte mocks reading a byte from the Apple II
|
||||
func (mockIo MockIo) ReadByte() (byte, error) {
|
||||
b := mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead]
|
||||
mockIo.Data.NumberBytesRead++
|
||||
return b, mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// ReadString mocks reading a null terminated string from the Apple II
|
||||
func (mockIo MockIo) ReadString() (string, error) {
|
||||
builder := strings.Builder{}
|
||||
for {
|
||||
if mockIo.Data.NumberBytesRead > len(mockIo.Data.BytesToRead) {
|
||||
return "", errors.New("Read more data than available")
|
||||
return "", errors.New("read more data than available")
|
||||
}
|
||||
builder.WriteByte(mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead])
|
||||
mockIo.Data.NumberBytesRead++
|
||||
@ -79,9 +89,10 @@ func (mockIo MockIo) ReadString() (string, error) {
|
||||
return builder.String(), mockIo.Data.ErrorToThrow
|
||||
}
|
||||
|
||||
// ReadBlock mocks reading a 512 byte block from the Apple II
|
||||
func (mockIo MockIo) ReadBlock(buffer []byte) error {
|
||||
if mockIo.Data.NumberBytesRead+512 > len(mockIo.Data.BytesToRead) {
|
||||
return errors.New("Read more data than available")
|
||||
return errors.New("read more data than available")
|
||||
}
|
||||
for i := 0; i < 512; i++ {
|
||||
buffer[i] = mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead]
|
||||
|
@ -5,6 +5,7 @@
|
||||
// This file is only used during development for interactive testing of the
|
||||
// driver code. Simply replace `comm := a2io.A2Gpio{}` with
|
||||
// `comm := a2io.UserIo{}` in the driver.go file to allow local testing
|
||||
|
||||
package a2io
|
||||
|
||||
import (
|
||||
@ -13,28 +14,34 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UserIo implements A2Io for the purpose of debugging locally
|
||||
type UserIo struct {
|
||||
}
|
||||
|
||||
// Init is only here to complete A2Io interface
|
||||
func (userIo UserIo) Init() {
|
||||
|
||||
}
|
||||
|
||||
// WriteByte simulates writing to the Apple II but uses stdout instead
|
||||
func (userIo UserIo) WriteByte(data byte) error {
|
||||
fmt.Printf("WriteByte: %02X\n", data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteString simulates writing to the Apple II but uses stdout instead
|
||||
func (userIo UserIo) WriteString(outString string) error {
|
||||
fmt.Printf("WriteString: %s\n", strings.ReplaceAll(outString, "\r", "\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteBlock simulates writing to the Apple II but uses stdout instead
|
||||
func (userIo UserIo) WriteBlock(buffer []byte) error {
|
||||
fmt.Printf("WriteBlock:\n")
|
||||
return userIo.WriteBuffer(buffer)
|
||||
}
|
||||
|
||||
// WriteBuffer simulates writing to the Apple II but uses stdout instead
|
||||
func (userIo UserIo) WriteBuffer(buffer []byte) error {
|
||||
fmt.Printf("WriteBuffer:\n")
|
||||
for i, b := range buffer {
|
||||
@ -47,6 +54,7 @@ func (userIo UserIo) WriteBuffer(buffer []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadByte simulates reading to the Apple II but uses stdin instead
|
||||
func (userIo UserIo) ReadByte() (byte, error) {
|
||||
fmt.Printf("ReadByte: ")
|
||||
var b byte
|
||||
@ -55,6 +63,7 @@ func (userIo UserIo) ReadByte() (byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// ReadString simulates reading to the Apple II but uses stdin instead
|
||||
func (userIo UserIo) ReadString() (string, error) {
|
||||
fmt.Printf("ReadString: ")
|
||||
var s string
|
||||
@ -63,6 +72,7 @@ func (userIo UserIo) ReadString() (string, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// ReadBlock should simulate reading to the Apple II but is not yet supported
|
||||
func (userIo UserIo) ReadBlock(buffer []byte) error {
|
||||
fmt.Printf("ReadBlock: (Not supported)")
|
||||
return errors.New("ReadBlock not supported")
|
||||
|
@ -17,14 +17,14 @@ import (
|
||||
"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
|
||||
const MenuCommand = 8
|
||||
const readBlockCommand = 1
|
||||
const writeBlockCommand = 2
|
||||
const getTimeCommand = 3
|
||||
const changeDriveCommand = 4
|
||||
const execCommand = 5
|
||||
const loadFileCommand = 6
|
||||
const saveFileCommand = 7
|
||||
const menuCommand = 8
|
||||
|
||||
func main() {
|
||||
drive1, drive2 := getDriveFiles()
|
||||
@ -40,17 +40,17 @@ func main() {
|
||||
command, err := comm.ReadByte()
|
||||
if err == nil {
|
||||
switch command {
|
||||
case ReadBlockCommand:
|
||||
case readBlockCommand:
|
||||
handlers.ReadBlockCommand(drive1, drive2)
|
||||
case WriteBlockCommand:
|
||||
case writeBlockCommand:
|
||||
handlers.WriteBlockCommand(drive1, drive2)
|
||||
case GetTimeCommand:
|
||||
case getTimeCommand:
|
||||
handlers.GetTimeCommand()
|
||||
case ExecCommand:
|
||||
case execCommand:
|
||||
handlers.ExecCommand()
|
||||
case LoadFileCommand:
|
||||
case loadFileCommand:
|
||||
handlers.LoadFileCommand()
|
||||
case MenuCommand:
|
||||
case menuCommand:
|
||||
handlers.MenuCommand()
|
||||
}
|
||||
}
|
||||
@ -71,8 +71,8 @@ func getDriveFiles() (*os.File, *os.File) {
|
||||
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()
|
||||
|
||||
var drive1 *os.File = nil
|
||||
var drive2 *os.File = nil
|
||||
var drive1 *os.File
|
||||
var drive2 *os.File
|
||||
var err error
|
||||
|
||||
if len(drive1Name) > 0 {
|
||||
|
@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is used for handling ProDOS image block reading and writing
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@ -14,10 +15,11 @@ import (
|
||||
|
||||
var oldFirmware = false
|
||||
|
||||
// ReadBlockCommand handles requests to read ProDOS blocks
|
||||
func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
|
||||
blockLow, _ := comm.ReadByte()
|
||||
blockHigh, _ := comm.ReadByte()
|
||||
var driveUnit byte = 0
|
||||
var driveUnit byte
|
||||
var err error
|
||||
|
||||
if !oldFirmware {
|
||||
@ -50,11 +52,12 @@ func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
|
||||
}
|
||||
}
|
||||
|
||||
// WriteBlockCommand handles requests to write ProDOS blocks
|
||||
func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
|
||||
blockLow, _ := comm.ReadByte()
|
||||
blockHigh, _ := comm.ReadByte()
|
||||
|
||||
var driveUnit byte = 0
|
||||
var driveUnit byte
|
||||
var err error
|
||||
|
||||
if !oldFirmware {
|
||||
|
@ -3,6 +3,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is used for setting up the communications for the handlers
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@ -11,6 +12,7 @@ import (
|
||||
|
||||
var comm a2io.A2Io
|
||||
|
||||
// SetCommunication configures whether to use real or mock communications
|
||||
func SetCommunication(commIO a2io.A2Io) {
|
||||
comm = commIO
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// This file is contains the handler for executing Linux and internal
|
||||
// commands
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@ -17,6 +18,7 @@ import (
|
||||
|
||||
var forceLowercase = false
|
||||
|
||||
// ExecCommand handles requests for the Apple II executing Linux commands
|
||||
func ExecCommand() {
|
||||
workingDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -109,7 +111,6 @@ func execCommand(linuxCommand string, workingDirectory string) {
|
||||
cmd.Wait()
|
||||
comm.WriteByte(0)
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,7 +184,7 @@ func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, use
|
||||
stdin.Close()
|
||||
userCancelled <- true
|
||||
return
|
||||
} else {
|
||||
}
|
||||
if b == 13 {
|
||||
b = 10
|
||||
}
|
||||
@ -192,7 +193,6 @@ func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, use
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func a2help() {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// This file is contains the handler for retrieving the ProDOS timestamp
|
||||
// based on the current time
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@ -13,6 +14,7 @@ import (
|
||||
"github.com/tjboldt/ProDOS-Utilities/prodos"
|
||||
)
|
||||
|
||||
// GetTimeCommand handles the request to get ProDOS time bytes
|
||||
func GetTimeCommand() {
|
||||
fmt.Printf("Sending date/time...\n")
|
||||
prodosTime := prodos.DateTimeToProDOS(time.Now())
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
// This file is contains the handler for loading files directly from the
|
||||
// Raspberry Pi onto the Apple II
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
@ -11,6 +12,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// LoadFileCommand handles requests to direct read files from Linux to the Apple II
|
||||
func LoadFileCommand() {
|
||||
fileName, _ := comm.ReadString()
|
||||
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
// This file is contains the handler for displaying the menu of choices on
|
||||
// the Apple II
|
||||
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// MenuCommand handles the request to show menu options on the Apple II
|
||||
func MenuCommand() {
|
||||
fmt.Printf("Sending menu...\n")
|
||||
comm.WriteString("Apple2-IO-RPi\r" +
|
||||
|
Loading…
Reference in New Issue
Block a user