Merge branch 'main' into merge-pico

This commit is contained in:
Terence Boldt 2024-02-04 23:39:13 -05:00
commit 3f7ea8b76a
46 changed files with 698 additions and 152 deletions

View File

@ -49,6 +49,14 @@ body:
label: Driver Version
description: What version of the driver are you running? Check with `RPI a2version`
options:
- 002C (fix nano editor)
- 002B (fix keyboard delay)
- 002A (reduce CPU usage)
- 0029 (fix hang after shell exit)
- 0028 (add live drive loading and regeneration)
- 0027 (add dynamic drive support)
- 0026 (add error handling)
- 0025 (update RPi.command)
- 0024 (fix VT100 arrow keys)
- 0023 (replaced periph.io with rpio)
- 0022 (added version info)
@ -61,6 +69,7 @@ body:
label: Shell Version
description: What version of the shell are you running?`
options:
- 000E (fix hang on exit)
- 000D (added version info)
- Older (pre-2022-Mar-01)
- Not Applicable (bug not Shell related)

View File

@ -1,3 +1,8 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
@ -10,25 +15,32 @@ name: Codacy Security Scan
on:
push:
branches: [ main ]
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
branches: [ "main" ]
schedule:
- cron: '35 10 * * 0'
- cron: '33 3 * * 3'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@1.1.0
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
@ -44,6 +56,6 @@ jobs:
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v1
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: results.sarif

76
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '27 10 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2020-2022
; Copyright Terence J. Boldt (c)2020-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2020-2022
; Copyright Terence J. Boldt (c)2020-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2020-2022
; Copyright Terence J. Boldt (c)2020-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2020-2022
; Copyright Terence J. Boldt (c)2020-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.
@ -188,7 +188,7 @@ finishRead:
Text:
.byte "Apple2-IO-RPi",$8d
.byte "(c)2020-2022 Terence J. Boldt",$8d
.byte "(c)2020-2024 Terence J. Boldt",$8d
.byte $8d
.byte "Waiting for RPi FW:000F..."
end:

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2021-2022
; Copyright Terence J. Boldt (c)2021-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
; Copyright Terence J. Boldt (c)2021-2022
; Copyright Terence J. Boldt (c)2021-2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.
@ -115,8 +115,6 @@ Start:
lda #ShellCommand
jsr SendByte
jsr DumpOutput
lda #ResetCommand
jsr SendByte
pla
sta LastChar
rts
@ -292,7 +290,7 @@ restoreChar:
rts
Text:
.byte "Apple2-IO-RPi Shell Version 000D",$8d
.byte "(c)2020-2022 Terence J. Boldt",$8d
.byte "Apple2-IO-RPi Shell Version 000E",$8d
.byte "(c)2020-2024 Terence J. Boldt",$8d
.byte $8d
.byte $00

14
Apple2/Startup.bas Normal file
View File

@ -0,0 +1,14 @@
10 HOME
11 PRINT "Apple2-IO-RPi"
12 PRINT "(c)2021-2024 Terence J. Boldt"
13 PRINT
14 PRINT "This drive is dynamically generated"
15 PRINT "from the current working directory on"
16 PRINT "the Raspberry Pi and is in RAM only."
17 PRINT
18 PRINT "To start a shell to the RPi, type:"
19 PRINT "-shell"
20 PRINT
21 PRINT "To add RPI command to ProDOS, type:"
22 PRINT "-rpi.command"
23 PRINT

View File

@ -1,5 +1,5 @@
10 HOME
100 PRINT CHR$ (4)"BLOAD AT28C64B.BIN,A$2000"
100 PRINT CHR$ (4)"BLOAD AT28C64B,A$2000"
200 PRINT "Program the firmare in slot #"
300 INPUT SL
400 FW = 8192 + 256 * SL: REM Firmware source
@ -15,9 +15,11 @@
1010 POKE PS,PG * 16 + 15: REM Set firmware page
1020 FOR X = 0 TO 255
1030 A = PEEK (FW + PG * 2048 + X)
1035 B = PEEK (EP + X): REM Skip if unchanged
1037 IF (A = B) THEN GOTO 1045
1040 POKE EP + X,A
1041 B = PEEK (EP + X)
1042 IF (B < > A) THEN GOTO 1041
1042 IF (B < > A) THEN GOTO 1041: REM Wait for write
1045 HTAB (X / 256) * 39 + 1
1046 INVERSE : PRINT " ";: NORMAL
1050 NEXT X

View File

@ -43,21 +43,16 @@ ld65 FileAccessSlot0.o FileAccessSlot1.o FileAccessSlot2.o FileAccessSlot3.o Fil
cat \
DriveFirmware.bin CommandFirmware.bin FileAccessFirmware.bin MenuFirmware.bin \
> AT28C64B.bin
> ../RaspberryPi/driveimage/AT28C64B.bin
ca65 Shell.asm -D HW_TYPE=$HW_TYPE -o Shell.o --listing Shell.lst || exit 1
ld65 Shell.o -o Shell.bin -C ../.cicd/none.cfg || exit 1
ld65 Shell.o -o ../RaspberryPi/driveimage/Shell.bin -C ../.cicd/none.cfg || exit 1
ca65 RPi.Command.asm -D HW_TYPE=$HW_TYPE -o RPi.Command.o --listing RPi.Command.lst || exit 1
ld65 RPi.Command.o -o RPi.Command.bin -C ../.cicd/none.cfg || exit 1
ld65 RPi.Command.o -o ../RaspberryPi/driveimage/RPi.Command.bin -C ../.cicd/none.cfg || exit 1
rm ./*.o
rm DriveFirmware.bin
rm MenuFirmware.bin
rm CommandFirmware.bin
rm FileAccessFirmware.bin
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i AT28C64B.bin -p /APPLE2.IO.RPI/AT28C64B.BIN || exit 1
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i Shell.bin -p /APPLE2.IO.RPI/SHELL || exit 1
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i RPi.Command.bin -p /APPLE2.IO.RPI/RPI.COMMAND -a 0x2000 || exit 1
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c ls

View File

@ -50,8 +50,8 @@ ca65 RPi.Command.asm -o RPi.Command.o --listing RPi.Command.lst.new || exit 1
ld65 RPi.Command.o -o RPi.Command.bin.new -C ../.cicd/none.cfg || exit 1
rm ./*.o
diff RPi.Command.bin RPi.Command.bin.new || exit 1
diff AT28C64B.bin AT28C64B.bin.new || exit 1
diff Shell.bin Shell.bin.new || exit 1
diff ../RaspberryPi/driveimage/RPi.Command.bin RPi.Command.bin.new || exit 1
diff ../RaspberryPi/driveimage/AT28C64B.bin AT28C64B.bin.new || exit 1
diff ../RaspberryPi/driveimage/Shell.bin Shell.bin.new || exit 1
rm ./*.new

View File

@ -2215,7 +2215,6 @@
)
)
(junction (at 81.28 125.73) (diameter 0) (color 0 0 0 0)
(uuid 015f5586-ba76-4a98-9114-f5cd2c67134d)
)
@ -5372,6 +5371,17 @@
(pin "1" (uuid 23ce4381-b2cf-485f-a79a-4eaeb44b0849))
(pin "2" (uuid 5c798329-52d9-4807-96d1-e4addb44a953))
(pin "3" (uuid 1ab7faf5-43ab-4823-ac26-34babc931942))
(pin "4" (uuid a6beaca2-6c47-4b64-b05b-68e01b124788))
(pin "5" (uuid 1105c92a-881e-46d4-8e4b-9bde4c23e61b))
(pin "6" (uuid 8fc34fe0-9484-4245-8205-553010f1b481))
(pin "10" (uuid c2aa5992-2edc-40ca-a38b-d7fae7282fe7))
(pin "8" (uuid adc84294-f335-43bc-9753-ab775be88116))
(pin "9" (uuid 6a40c532-5374-49ce-976b-f54013e33342))
(pin "11" (uuid 42a24e3d-88de-4ad2-b4a4-aa8239aeb395))
(pin "12" (uuid 11da2dcc-4454-4c7e-8c58-2bce3eaa5144))
(pin "13" (uuid 2e13be03-f7c2-4a62-b785-e7ae915b9e7f))
(pin "14" (uuid da86aea1-9c30-4f7e-997a-033cdf91b7de))
(pin "7" (uuid 4c3530f0-d981-4724-9a3e-7368587db9a8))
)
(symbol (lib_id "Device:C") (at 340.36 214.63 0) (unit 1)
@ -5380,7 +5390,7 @@
(property "Reference" "C3" (id 0) (at 343.281 213.4616 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "C" (id 1) (at 343.281 215.773 0)
(property "Value" "0.1 µF" (id 1) (at 343.281 215.773 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 341.3252 218.44 0)
@ -5399,7 +5409,7 @@
(property "Reference" "C4" (id 0) (at 363.601 213.4616 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "C" (id 1) (at 363.601 215.773 0)
(property "Value" "0.1 µF" (id 1) (at 363.601 215.773 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 361.6452 218.44 0)
@ -5418,7 +5428,7 @@
(property "Reference" "C2" (id 0) (at 355.981 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 355.981 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 355.981 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 354.0252 168.91 0)
@ -5437,7 +5447,7 @@
(property "Reference" "C1" (id 0) (at 347.091 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 347.091 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 347.091 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 345.1352 168.91 0)
@ -5456,7 +5466,7 @@
(property "Reference" "C5" (id 0) (at 364.871 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 364.871 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 364.871 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 362.9152 168.91 0)
@ -5475,7 +5485,7 @@
(property "Reference" "C6" (id 0) (at 373.761 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 373.761 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 373.761 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 371.8052 168.91 0)
@ -5499,9 +5509,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 90.17 115.57 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid cc16c7ae-9c92-4444-9ea3-06f9ccc367be))
(pin "2" (uuid 2b647539-7ba0-4b65-8202-c7f85d2d58f9))
(pin "3" (uuid 50ca56df-1595-45f9-a7e0-251682b904b5))
(pin "4" (uuid a103831a-5a8a-4886-aa57-f8b2b69f26ae))
(pin "5" (uuid 7749be9c-17a6-4091-9298-3d5fa8df10ec))
(pin "6" (uuid 3bcb06a4-6607-4f1e-a0cd-7aa6ae9163ca))
(pin "10" (uuid c0e76e7a-0fb4-4013-8aaa-29cb294ffe58))
(pin "8" (uuid 5f137c12-6ab8-4995-ba1f-413f9ce9e2c2))
(pin "9" (uuid c1755b79-9175-43f1-afda-82992afcaef2))
(pin "11" (uuid a8681920-4d26-4021-a997-9f1f2b834c00))
(pin "12" (uuid 285a9aee-c73d-49dd-accb-b4fd7574646c))
(pin "13" (uuid 4f3dc6d3-051d-45c5-b2dd-3963bfe3689b))
(pin "14" (uuid 639e36f7-111e-4b5a-8bf9-f055939534d4))
(pin "7" (uuid e6c23048-abcc-4757-8a23-cb990a469883))
)
(symbol (lib_id "74xx:74LS32") (at 156.21 116.84 0) (unit 3)
@ -5515,9 +5536,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 156.21 116.84 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 779317f9-cc98-4e89-9a76-f28baf44b6fa))
(pin "2" (uuid 49c409f4-fd27-4e2c-832f-c60bfbac5d4e))
(pin "3" (uuid 8dcb9ab7-4947-44c1-ac89-22253862dff0))
(pin "4" (uuid 66e60965-5117-4e25-ad7f-b2cf278ec2ac))
(pin "5" (uuid fb6bac8b-0e2c-4da6-818b-d1ea7142ed6e))
(pin "6" (uuid 94865cfd-0c49-41e6-8a13-a58a16d75bbc))
(pin "10" (uuid 4b8e4218-9740-4574-b59e-9bff3b6ae8ff))
(pin "8" (uuid 1ac84470-ff35-4e92-8c90-2205b203daf4))
(pin "9" (uuid 221d5d88-9b3c-4368-a294-8824ee031e92))
(pin "11" (uuid b847d6d8-0cff-4347-b9db-69f5fbae9fce))
(pin "12" (uuid 1f3f8181-e232-4518-9c68-ff0472233c70))
(pin "13" (uuid e8a48dd8-df61-4c94-9f94-7d52814e8ba7))
(pin "14" (uuid 1bd2c934-42cb-4949-88cd-f950c843d8cb))
(pin "7" (uuid d08e8d45-1956-48ad-8bf9-f281b2d51657))
)
(symbol (lib_id "74xx:74LS32") (at 90.17 128.27 0) (unit 4)
@ -5531,9 +5563,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 90.17 128.27 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 585e2bc6-286c-4625-8fd6-b5232bd11ab7))
(pin "2" (uuid 0cb58e87-1a6a-4bb6-bc79-815fbe53ac1e))
(pin "3" (uuid e80cdefa-a788-4379-9e16-8fce6a58c8f6))
(pin "4" (uuid 6925452e-3b67-4990-985b-e7d15d56a159))
(pin "5" (uuid 0dcdf4ae-d8c6-4c94-bd47-80574ee9be6c))
(pin "6" (uuid 6bd577a4-e8c5-4ffc-8ac8-8560490f35cf))
(pin "10" (uuid d04405d3-f64d-4059-a328-9c543c6b5b15))
(pin "8" (uuid 13dbb77d-77d9-4fa7-a371-954174333f4c))
(pin "9" (uuid c9730515-2c30-423f-be43-60d2694a504a))
(pin "11" (uuid c40083a4-145c-4ae4-9fae-3a0ea9941f61))
(pin "12" (uuid 63605522-e38d-450e-bf96-6c4425233163))
(pin "13" (uuid c6c30a7a-cde8-4cf9-9ed4-49502cc4e875))
(pin "14" (uuid 9d1413a3-2a21-4384-81c0-ccdb307d1530))
(pin "7" (uuid 81b0a24d-d7da-4f8b-b867-b8bfdf8f37a3))
)
(symbol (lib_id "74xx:74LS00") (at 66.04 91.44 0) (unit 1)
@ -5550,6 +5593,17 @@
(pin "1" (uuid a1353da8-7c89-45ab-8a28-9598589a1ee1))
(pin "2" (uuid 663afe67-91e0-47d7-9990-df9e79fade04))
(pin "3" (uuid de28b31e-94a2-4f20-b1a8-765f5ea36c3d))
(pin "4" (uuid 928ed566-e3f5-4b4a-8fbe-74e8d4fb243c))
(pin "5" (uuid 0111e7f3-1514-4ad6-99e9-7dcf9686622c))
(pin "6" (uuid 2e30ebe3-0f45-4c48-a2c8-2a32a4994456))
(pin "10" (uuid 81fada83-e47f-4376-9c67-24de0fe6ca83))
(pin "8" (uuid 2a20ddeb-7832-46d2-9069-b4a9751b83f9))
(pin "9" (uuid 723a7bad-bd47-43ad-a59c-9873ea940efa))
(pin "11" (uuid b911021d-57a0-4580-bfb0-1c066032b8e2))
(pin "12" (uuid b2977fbf-6144-4357-8280-a40f093efff3))
(pin "13" (uuid 9d0af54b-1546-4921-9c0f-c0db7d734ba3))
(pin "14" (uuid 59a11a98-19e7-4d62-aed2-d3e3d3ae09c4))
(pin "7" (uuid b6a54b1c-e858-415d-b3a3-5977d8636f54))
)
(symbol (lib_id "74xx:74LS00") (at 86.36 91.44 0) (unit 2)
@ -5563,9 +5617,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74ls00" (id 3) (at 86.36 91.44 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid f6e35044-4b94-4656-ad69-ecbdce343488))
(pin "2" (uuid b05d6dae-4161-42fd-90cb-fcbb1d75834f))
(pin "3" (uuid 978c0384-e1bf-42a4-8c02-2d11be0ea0f4))
(pin "4" (uuid ab17ec18-2f5f-445a-8747-86764dc204e3))
(pin "5" (uuid 4c5ec9dc-5867-41c9-9129-01962654b6ac))
(pin "6" (uuid 62d49ae3-b4dd-497f-84dc-640f11d71890))
(pin "10" (uuid c462dede-8070-4817-bf28-efd02b5a8971))
(pin "8" (uuid 8548fb42-2440-4cb0-9164-af5f85371f01))
(pin "9" (uuid 2f8df34c-29f4-42dd-ab8c-4368a809795a))
(pin "11" (uuid 9d83d9ee-f9be-4cba-b423-fb184e0ae57f))
(pin "12" (uuid d25d0f52-0689-4fa0-a1db-a9b35e9053eb))
(pin "13" (uuid e3ff334a-b52c-4eff-82fa-a3036b75a900))
(pin "14" (uuid a18d26ab-a8eb-467c-bf6b-1d8aa89f73ed))
(pin "7" (uuid 6433ba4d-ba73-46d7-8c1d-6ecfcb83d21a))
)
(symbol (lib_id "Memory_EPROM:27C256") (at 119.38 227.33 0) (unit 1)
@ -5620,9 +5685,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74ls00" (id 3) (at 72.39 125.73 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 827cdd9c-0f24-485d-a074-76e4898269fd))
(pin "2" (uuid ee4941d0-c696-4b20-b624-cfc438e02399))
(pin "3" (uuid daf39040-e60c-47e8-ad5f-568518b98138))
(pin "4" (uuid 8e678bf1-fca0-4b04-afa2-9eccdc69dbd7))
(pin "5" (uuid d761a1eb-f270-421f-a96e-8b0854e4136b))
(pin "6" (uuid c012cfb6-f253-4bfd-b42d-737662112798))
(pin "10" (uuid 799282ec-97a5-4c03-8ff7-5165af090737))
(pin "8" (uuid f0a24549-c201-4561-a7f5-2fab088eeebf))
(pin "9" (uuid 143dfd14-68b7-4903-809b-91db1fa3ee07))
(pin "11" (uuid 47c1541a-2e10-4704-88f5-e800260f6e7f))
(pin "12" (uuid 52529a02-0f01-49f9-a2c0-65389efd06ad))
(pin "13" (uuid 5e78440e-17f6-4b50-a177-2b94125a82ee))
(pin "14" (uuid c919295a-a8fd-4a7e-ab91-0ba222db2c02))
(pin "7" (uuid fb2920c4-9db1-4fb4-bdfa-c66fa60d5493))
)
(symbol (lib_id "74xx:74LS00") (at 68.58 113.03 0) (unit 4)
@ -5636,9 +5712,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74ls00" (id 3) (at 68.58 113.03 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 47fc3e6f-4fa5-4a44-bc28-18ea9d413f48))
(pin "2" (uuid 9d776279-8d51-4909-b91c-2d921b28aea1))
(pin "3" (uuid 44c4ea58-6a8c-412a-894a-499d6c6bcd28))
(pin "4" (uuid c0cc858c-1ac0-4e47-a87d-831903da6485))
(pin "5" (uuid 520224a7-0742-4623-93b1-a64ea9bac558))
(pin "6" (uuid 8439ba08-cf8f-46b9-97a3-bee8b8140101))
(pin "10" (uuid 0da0253b-2d8e-4be8-89c3-d91561e68264))
(pin "8" (uuid 2cccba94-6af0-4db6-9859-9c6d8766db42))
(pin "9" (uuid 632c7690-294f-4f86-874a-68cdd78546fc))
(pin "11" (uuid 94a1c51b-a034-4b45-9e36-ba1013a3987a))
(pin "12" (uuid 203c9db7-77c7-46e3-a0b2-661683ca12ae))
(pin "13" (uuid 14c0c4df-db41-4e93-b67d-f5abc3579115))
(pin "14" (uuid 2530330e-6f34-4a7d-96c2-412c7f6ba5a0))
(pin "7" (uuid cd76d690-4a74-415f-98a3-e347bab9112f))
)
(symbol (lib_id "74xx:74LS245") (at 280.67 143.51 0) (unit 1)
@ -5722,6 +5809,18 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74ls00" (id 3) (at 349.25 205.74 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 0af3f124-b086-4e09-8910-867a54fb902e))
(pin "2" (uuid 36481291-c445-4b6e-a0f5-4b847e913cc2))
(pin "3" (uuid 06879bef-7dca-4c07-8423-61e400b818d1))
(pin "4" (uuid b1ebe26b-706c-4647-a118-dd9e69ab3dcd))
(pin "5" (uuid 8c974c5d-de55-4739-812c-e8c86779636d))
(pin "6" (uuid 1db1348d-3a28-408b-9a6a-17d88088093e))
(pin "10" (uuid 422b8b8b-73c3-442c-9f0e-50e3358cafc2))
(pin "8" (uuid d059b2fe-df4b-4abe-aadf-3d7556a7a4c5))
(pin "9" (uuid eebf3a91-ed09-4598-923d-0b9b08a601de))
(pin "11" (uuid dcfc1971-7ca9-421c-a4a6-5b6591e1dbd6))
(pin "12" (uuid 22b98e35-08c1-4501-a2b9-8bc8ab2275d9))
(pin "13" (uuid 2b53118c-2082-4f55-ae49-9f37e43af075))
(pin "14" (uuid 86095ba6-cf04-49c5-ad87-9313ad0c0254))
(pin "7" (uuid 848470c0-08b9-4de1-9d57-0deb204c083d))
)
@ -5741,6 +5840,18 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 368.3 205.74 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid c0f1c945-6874-4014-a83d-0f6b6946c10d))
(pin "2" (uuid c922b84c-fdae-4822-bc74-51e2f0091599))
(pin "3" (uuid 013ba537-0898-41c0-ab98-f571839324a5))
(pin "4" (uuid b425d8be-6f1f-42bf-aba9-0485beb0893a))
(pin "5" (uuid 1ec025a8-272d-4aaf-8873-7ee352a7601b))
(pin "6" (uuid d66853de-cdae-44f9-a7b7-f6fae7089b01))
(pin "10" (uuid 69211dfd-08b1-4298-86f6-6c1c7028c2c1))
(pin "8" (uuid d0a3dc94-fe74-4e63-a3f4-b7d8ea3146ca))
(pin "9" (uuid 531b09b0-b58f-43ef-b797-6771a3678427))
(pin "11" (uuid 57890c2e-f822-4e96-9441-8d5554ddcb7d))
(pin "12" (uuid 564e2c18-086d-4c75-8c16-6524598c7a20))
(pin "13" (uuid 065dcee7-58ad-4d5b-9d41-dfa23110c919))
(pin "14" (uuid 6de5780e-d3a1-4f4a-bcab-bc01cd2647d6))
(pin "7" (uuid 0a541000-633e-4d44-83c4-a3e87d3866a2))
)
@ -5751,7 +5862,7 @@
(property "Reference" "C8" (id 0) (at 391.541 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 391.541 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 391.541 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 389.5852 168.91 0)
@ -5770,7 +5881,7 @@
(property "Reference" "C7" (id 0) (at 382.651 163.9316 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "100n" (id 1) (at 382.651 166.243 0)
(property "Value" "0.1 µF" (id 1) (at 382.651 166.243 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 380.6952 168.91 0)
@ -5798,6 +5909,18 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 387.35 205.74 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid c5143a00-e900-48a2-a82d-8db4bfd865a0))
(pin "2" (uuid ebfee597-bd5a-4ffb-89b9-587f48338994))
(pin "3" (uuid 09c79adc-28a8-4e51-8128-d754716a170e))
(pin "4" (uuid b2fdd67a-60fd-4990-9077-d1b55326bdee))
(pin "5" (uuid 827e2adc-b461-42c3-af09-816ee467a3bd))
(pin "6" (uuid 298ce0ee-439b-4e8d-bc30-aa5fb9e369c3))
(pin "10" (uuid 8beaf6c8-70da-4e34-a8d9-c19984e365e6))
(pin "8" (uuid d7944521-3d5e-49c8-a8dd-41ddb103e3c7))
(pin "9" (uuid ed7ec5e0-772b-4067-a0dd-9d4aaace7bde))
(pin "11" (uuid bb590ecc-1d81-4a92-9ffa-f97f4e946635))
(pin "12" (uuid eba9f422-9820-4127-8838-e1aa945452a0))
(pin "13" (uuid aa74d806-1e5e-43f8-985e-a85442e69653))
(pin "14" (uuid 299dfa84-9cf0-4f6a-9013-42286bd3c900))
(pin "7" (uuid c2b1410a-a360-4692-88f0-3a5b1b0dcdef))
)
@ -5808,7 +5931,7 @@
(property "Reference" "C9" (id 0) (at 381.381 213.4616 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Value" "C" (id 1) (at 381.381 215.773 0)
(property "Value" "0.1 µF" (id 1) (at 381.381 215.773 0)
(effects (font (size 1.27 1.27)) (justify left))
)
(property "Footprint" "Apple2:Capacitor" (id 2) (at 379.4252 218.44 0)
@ -5835,6 +5958,17 @@
(pin "1" (uuid 84871e25-7c51-4425-803d-10248cf5465a))
(pin "2" (uuid 685bb84c-eae4-40c2-9c2f-cba074809328))
(pin "3" (uuid 78634ab1-d719-4068-a89b-45f47e2076c3))
(pin "4" (uuid 567f7042-d9fb-4361-bf03-6483971112c6))
(pin "5" (uuid 1bc6b6dc-ee63-4354-b489-92c7d6bb4211))
(pin "6" (uuid 3f215145-bfe7-4a68-ad90-8cbdda2580bc))
(pin "10" (uuid 95de4035-6921-4bb6-840b-8e36a0528adc))
(pin "8" (uuid 063d5f8b-a783-4436-b79b-5b06b508d557))
(pin "9" (uuid af14cbc5-ee2e-4b16-b94d-e470cd3e7de9))
(pin "11" (uuid 1c3fae3d-ee70-4956-bc9d-df2fd97dff76))
(pin "12" (uuid 92555cb8-91aa-45fb-b36e-3f927632fcd0))
(pin "13" (uuid 623569cf-093e-4ba0-8c9c-d119eab4db50))
(pin "14" (uuid 84d3ab77-db52-435a-a10e-c64a356624a5))
(pin "7" (uuid e6691274-2384-4c5c-a526-e73d660c8a76))
)
(symbol (lib_id "74xx:74LS32") (at 166.37 173.99 0) (unit 2)
@ -5848,9 +5982,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 166.37 173.99 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 86b9f6f8-30f6-4109-b9f2-05502cabf2d1))
(pin "2" (uuid 30f58a07-5295-444c-b944-00c318261c71))
(pin "3" (uuid b90fac15-f593-430d-986d-f94f4f25b5e6))
(pin "4" (uuid d62e9911-44e3-43f2-a3c8-820f8a779b1b))
(pin "5" (uuid 98ce6dcc-02a8-4aac-9f23-0d5ec09c4a8b))
(pin "6" (uuid 554b12f8-26e8-4f25-90de-cda584823f93))
(pin "10" (uuid ba25ed3c-4fad-4d9a-9150-a2a0c6b0f6ac))
(pin "8" (uuid 64ce92d3-36ca-41fe-81f0-888ab6024bb2))
(pin "9" (uuid 5fc6acc2-0a13-4d3e-886f-7fff983e203c))
(pin "11" (uuid 0de695a5-ba13-49f1-b412-7b224e80c525))
(pin "12" (uuid d41e1d4a-5bb4-4dc2-84cf-37f242167dae))
(pin "13" (uuid 8ef92343-2136-44d8-9781-a6ea74675f54))
(pin "14" (uuid 5894e791-846d-49cc-93b9-4235860a1728))
(pin "7" (uuid 28015c5a-9751-45f3-a262-39894bf94f5e))
)
(symbol (lib_id "74xx:74LS32") (at 116.84 161.29 0) (unit 3)
@ -5864,9 +6009,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 116.84 161.29 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 5e1ada16-d441-4bb1-9830-6feb5505fa37))
(pin "2" (uuid 73ee99cb-5d2b-42cb-a871-58c6d5ae1c45))
(pin "3" (uuid a4d49be3-7c4d-4703-806b-3f833e5f4813))
(pin "4" (uuid 881294d0-a3bc-4b96-bd86-02d283f0f9e7))
(pin "5" (uuid b2d75c93-4786-4ff5-b6d7-be8255674889))
(pin "6" (uuid a8674c98-f340-420f-a76d-5e5c09b947c2))
(pin "10" (uuid f97b357c-8f2f-40ec-95c1-e90493fbe567))
(pin "8" (uuid 0ad8c54b-ca57-4539-9f6e-a4a9cfb1c85d))
(pin "9" (uuid f9e83731-f733-40e4-9c7f-6906aaf7d750))
(pin "11" (uuid f268e04d-92b2-479f-823d-01b8c7150451))
(pin "12" (uuid 152af408-bc70-4346-b666-adb4ff286957))
(pin "13" (uuid 04db0548-1aea-4ef1-87ff-7133ec0b3e85))
(pin "14" (uuid 402cce49-a56b-47df-8c2d-3be1e145d710))
(pin "7" (uuid aadabbc7-d36f-45be-84e6-732196d89054))
)
(symbol (lib_id "74xx:74LS32") (at 116.84 176.53 0) (unit 4)
@ -5880,9 +6036,20 @@
(property "Datasheet" "http://www.ti.com/lit/gpn/sn74LS32" (id 3) (at 116.84 176.53 0)
(effects (font (size 1.27 1.27)) hide)
)
(pin "1" (uuid 22238ad7-3b76-4dd8-8931-ed0c96e725d4))
(pin "2" (uuid 7541e0c2-4634-4e24-8a00-2661ddd213be))
(pin "3" (uuid 6def11f1-0cee-42b0-8cf0-b29618f38d71))
(pin "4" (uuid d0e18661-bc79-4ba2-b3db-e6c62bb2b9ff))
(pin "5" (uuid 519f749d-7093-4709-9035-d64cf025eade))
(pin "6" (uuid 8c9432db-4bdc-4e35-a29a-0527bb21fa1e))
(pin "10" (uuid 60afb76b-d313-4f08-ae1e-4f0b1ccaa3d9))
(pin "8" (uuid 611a300a-c234-4dcf-abe4-3d5788490b07))
(pin "9" (uuid 224a70ee-268f-4d96-babe-de78686ad59b))
(pin "11" (uuid c40f273a-9dba-43e0-822d-6ff127715a8a))
(pin "12" (uuid bf19533b-16de-47f5-a9b4-645f328f4dfe))
(pin "13" (uuid 55488c96-5c7c-42e8-84b2-a8e477480d1b))
(pin "14" (uuid 15a47401-5c1b-4090-850f-5a486fc4248e))
(pin "7" (uuid 066f5967-c4fb-4809-9a8c-87bedb61ee98))
)
(symbol (lib_id "Jumper:Jumper_2_Bridged") (at 170.18 27.94 0) (unit 1)
@ -6324,31 +6491,31 @@
(reference "#PWR0103") (unit 1) (value "GND") (footprint "")
)
(path "/00000000-0000-0000-0000-00005fb85911"
(reference "C1") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C1") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fb849d8"
(reference "C2") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C2") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fb81404"
(reference "C3") (unit 1) (value "C") (footprint "Apple2:Capacitor")
(reference "C3") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fb82906"
(reference "C4") (unit 1) (value "C") (footprint "Apple2:Capacitor")
(reference "C4") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fb8694d"
(reference "C5") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C5") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fb87862"
(reference "C6") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C6") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-000060a87587"
(reference "C7") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C7") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-000060a58951"
(reference "C8") (unit 1) (value "100n") (footprint "Apple2:Capacitor")
(reference "C8") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-000060c3a67b"
(reference "C9") (unit 1) (value "C") (footprint "Apple2:Capacitor")
(reference "C9") (unit 1) (value "0.1 µF") (footprint "Apple2:Capacitor")
)
(path "/00000000-0000-0000-0000-00005fa0a8c3"
(reference "J0") (unit 1) (value "Apple II Expansion Bus") (footprint "Apple2:Apple II Expansion Edge Connector")

Binary file not shown.

12
Hardware/BOM.csv Normal file
View File

@ -0,0 +1,12 @@
Part,Quantity,Supplier Part #,Supplier
74LS32,2,595-SN74LS32N,Mouser
74LS00,1,595-SN74LS00N,Mouser
74LS245,1,595-SN74LS245N,Mouser
74LVC245,2,595-SN74LVC245AN,Mouser
74LVC374,2,595-SN74LVC374AN,Mouser
28C64B,1,556-AT28C64B15PU,Mouser
0.1µF Capacitor,9,594-K104K15X7RF5TH5,Mouser
2x20 GPIO Female Header,1,2222,Adafruit
14 Pin DIP Socket,3,571-1-2199298-3,Mouser
20 Pin DIP Socket,5,571-1-2199298-6,Mouser
28 Pin DIP Socket,1,571-1-2199299-2,Mouser
1 Part Quantity Supplier Part # Supplier
2 74LS32 2 595-SN74LS32N Mouser
3 74LS00 1 595-SN74LS00N Mouser
4 74LS245 1 595-SN74LS245N Mouser
5 74LVC245 2 595-SN74LVC245AN Mouser
6 74LVC374 2 595-SN74LVC374AN Mouser
7 28C64B 1 556-AT28C64B15PU Mouser
8 0.1µF Capacitor 9 594-K104K15X7RF5TH5 Mouser
9 2x20 GPIO Female Header 1 2222 Adafruit
10 14 Pin DIP Socket 3 571-1-2199298-3 Mouser
11 20 Pin DIP Socket 5 571-1-2199298-6 Mouser
12 28 Pin DIP Socket 1 571-1-2199299-2 Mouser

BIN
Hardware/BOM.pdf Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2022 Terence J. Boldt
Copyright (c) 2020-2024 Terence J. Boldt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,25 +1,56 @@
# Apple2-IO-RPi
Apple II expansion card using a Raspberry Pi for I/O
1. See the [upstream repo](https://github.com/tjboldt/Apple2-IO-RPi) for the original, full info.
![Image of Board](/Hardware/Apple2IORPi.jpg)
2. This fork is based on [A2Pico](https://github.com/oliverschmidt/a2pico).
## Purpose
The purpose of this project is to provide I/O for an Apple II series 8 bit computer via a Raspberry Pi Zero 2 W which is powered by the Apple II expansion bus. This includes using the attached RPi Zero 2 W for it's storage, network and processor to provide new functionality for the Apple II.
## Installing
## Features
1. Boot message which waits for RPi to be ready
2. ProDOS bootable drive from image stored on RPi
3. Linux bash shell to the RPi from the Apple II including some VT100 support via `-SHELL` from ProDOS
4. Load binary files directly from the RPi to the II (via dynamic virtual drive of current working directory on the RPi)
5. Update Apple II firmware in place from image on RPi (note, this is done per slot)
6. Supports two drive images at the same time
7. Supports "RPI" command from BASIC to execute Linux commands from the command prompt or inside BASIC programs: `10 PRINT CHR$(4);"RPI ls -al /"`
1. Flash [Apple2-IO-RPi.uf2](https://github.com/oliverschmidt/apple2-io-rpi/releases/latest/download/Apple2-IO-RPi.uf2) to the Raspberry Pi Pico.
## Project Status
2. Execute steps __5.)__ - __8.)__ and __10.)__ on [Setup new card from scratch](https://github.com/tjboldt/Apple2-IO-RPi/discussions/63).
### Classic Hardware
So far, this is still a project and not a finished product. The current prototype is on the sixth revision. I have sold about 60 boards including previous prototypes. There are more than 100 in the wild between self made and ones purchased in places like eBay that were made by others. The sixth prototype is functionally equivalent to the fifth, other than a new jumper to select internal/external power.
3. Execute `wget --no-cache -O - https://raw.githubusercontent.com/oliverschmidt/apple2-io-rpi/main/RaspberryPi/setup.sh | bash`
The card enables the Apple II to boot from and write to virtual hard drive images stored on the RPi in any slot (except slot 3), execute Linux commands from Applesoft BASIC and run a bash shell with VT100 emulation. The code has very few tests and is incomplete. Note that currently the firmware assumes an 80 column card is in slot 3 and than you have lowercase support. Most development has been done with an enhanced Apple //e with the card in slot 7. If you have other drive controllers earlier in the boot cycle, you can still boot from the Apple2-IO-RPi. For example, if the card was in slot 4, you could type `PR#4` from the BASIC prompt to boot the card. Note that the Raspberry Pi Zero W (and W 2) consume 170 - 250 mA and there is only 500 mA available to all expansion slots according to Apple. It is not recommended to have a lot of other cards in the system at the same time. With the sixth revision of the prototype, it is possible to remove the power jumper and run the RPi on an external USB power source. If configured for external power, note that the card's firmware will hang on boot without USB power on as the latch chips are powered by the 3.3V output of the RPi.
## Using
If you have a problem or idea for enhancement, log an issue [here](https://github.com/tjboldt/Apple2-IO-RPi/issues) or start a [discussion](https://github.com/tjboldt/Apple2-IO-RPi/discussions/categories/general). I recommend starring/watching the project for updates on GitHub. You are welcome to fork the project and submit pull requests which I will review. The latest version has an in-memory virtual drive representing current working directory in Linux for ease of copying files between Linux and ProDOS when the drive 1 is not specified as a file.
1. Access the two ProDOS 8 drives either via cold boot or `PR#n`.
### Pico Hardware
Ralle Palaveev has a version of the hardware that uses a RPi Pico to handle firmware and communications to the host over USB.
2. Make sure to check out `SHELL` and `RPI.COMMAND` in drive 1.
## Roadmap
See [List of issues tagged roadmap](https://github.com/tjboldt/Apple2-IO-RPi/issues?q=is%3Aissue+is%3Aopen+label%3Aroadmap+author%3Atjboldt)
## Building
## Setup on classic hardware
[Setup card from scratch](https://github.com/tjboldt/Apple2-IO-RPi/discussions/63)
1. Build the project in `/RaspberryPiPico` (requires the [Raspberry Pico C/C++ SDK](https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html)).
[Setup if you received a complete board from me](https://github.com/tjboldt/Apple2-IO-RPi/discussions/64)
2. Execute `go build` in `/RaspberryPi/apple2driver` (requires [Go](https://go.dev/)).
[Update to latest](https://github.com/tjboldt/Apple2-IO-RPi/discussions/65)
## Setup on Pico based hardware
[Setup card with Pico hardware](https://github.com/tjboldt/Apple2-IO-RPi/discussions/162)
## Contributions/Thanks
- Hans Hübner ([@hanshuebner](https://github.com/hanshuebner)) for help cleaning up schematics
- Scott ([@figital](https://github.com/figital)) for assembling early prototypes and recommending the AT28C64B chip
- Brokencodez for help with 3.3V conversion
- David Schmenk ([@dschmenk](https://github.com/dschmenk)) for creating his Apple2Pi project, proving that Raspberry Pi can be powered by the Apple II expansion bus
- Wyatt Wong ([@wyatt-wong](https://github.com/wyatt-wong)) for testing with multiple cards
- ([@Abysmal](https://github.com/Abysmal)) for shell and rpi.command testing
- ([@bfranske](https://github.com/bfranske)) for suggesting adding the 5V jumper
- Tim Boldt ([@timboldt](https://github.com/timboldt)) for recommending removing sysfs based GPIO code
- Oliver Schmidt ([@oliverschmidt])(https://github.com/oliverschmidt/apple2-io-rpi/)) for writing the Pico PIO and firmware
- Ralle Palaveev ([@rallepalaveev](https://github.com/rallepalaveev/a2pico)) for Pico hardware design
## Similar Project
If you prefer having Apple II peripherals control a Raspberry Pi rather than simply using the Raspberry Pi to provide storage, network access and processing to the Apple II, have a look at David Schmenk's excellent [Apple2Pi](https://github.com/dschmenk/apple2pi) project. I am often asked about differences between these two projects. They are similar in some ways but essentially opposite. The Apple2Pi is meant for the primary machine to be the RPi, using the Apple II for it's peripherals. The Apple2-IO-RPi is meant to have the Apple II as the primary machine and just use the RPi for its processing, storage and network.

Binary file not shown.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2021-2022
// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -15,7 +15,7 @@ type A2Io interface {
WriteString(outString string) error
WriteBlock(buffer []byte) error
WriteBuffer(buffer []byte) error
ReadByte() (byte, error)
ReadByte(noDelay ...bool) (byte, error)
ReadString() (string, error)
ReadBlock(buffer []byte) error
SendCharacter(character byte)

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -154,17 +154,26 @@ func (a2 A2Gpio) WriteString(outString string) error {
}
// ReadByte reads a byte from the Apple II via Raspberry Pi's GPIO ports
func (a2 A2Gpio) ReadByte() (byte, error) {
func (a2 A2Gpio) ReadByte(noDelay ...bool) (byte, error) {
// let the Apple II know we are ready to read
outRead.Low()
// wait for the Apple II to write
startTime := time.Now()
lastSleepTime := time.Now()
sleepDuration := 10
for inWrite.Read() == 1 {
if time.Since(startTime) > edgeTimeout {
outRead.High()
return 0, errors.New("timed out reading byte -- write stuck high")
}
if time.Since(lastSleepTime) > edgeTimeout/10 {
if len(noDelay) == 0 || !noDelay[0] {
sleepDuration *= 3;
}
time.Sleep(time.Millisecond * time.Duration(sleepDuration));
lastSleepTime = time.Now()
}
}
// get a nibble of data
@ -211,10 +220,19 @@ func (a2 A2Gpio) ReadByte() (byte, error) {
// wait for the Apple II to finish writing
//fmt.Printf("wait for the Apple II to finish writing\n")
startTime = time.Now()
lastSleepTime = time.Now()
sleepDuration = 10
for inWrite.Read() == 0 {
if time.Since(startTime) > edgeTimeout {
return 0, errors.New("timed out reading byte -- write stuck low")
}
if time.Since(lastSleepTime) > edgeTimeout/10 {
if len(noDelay) == 0 || !noDelay[0] {
sleepDuration *= 3;
}
time.Sleep(time.Millisecond * time.Duration(sleepDuration));
lastSleepTime = time.Now()
}
}
return data, nil
@ -230,11 +248,18 @@ func (a2 A2Gpio) WriteByte(data byte) error {
// wait for the Apple II to be ready to read
startTime := time.Now()
lastSleepTime := time.Now()
sleepDuration := 10
for inRead.Read() == 1 {
if time.Since(startTime) > edgeTimeout {
outWrite.High()
return errors.New("timed out writing byte -- read stuck high")
}
if time.Since(lastSleepTime) > edgeTimeout/10 {
sleepDuration *= 3;
time.Sleep(time.Millisecond * time.Duration(sleepDuration));
lastSleepTime = time.Now()
}
}
if ((data & 128) >> 7) == 1 {
@ -291,11 +316,18 @@ func (a2 A2Gpio) WriteByte(data byte) error {
// wait for the Apple II to finsih reading
//fmt.Printf("wait for the Apple II to finsih reading\n")
startTime = time.Now()
lastSleepTime = time.Now()
sleepDuration = 10
for inRead.Read() == 0 {
if time.Since(startTime) > edgeTimeout {
outWrite.High()
return errors.New("timed out writing byte -- read stuck low")
}
if time.Since(lastSleepTime) > edgeTimeout/10 {
sleepDuration *= 3;
time.Sleep(time.Millisecond * time.Duration(sleepDuration));
lastSleepTime = time.Now()
}
}
// let the Apple II know we are done writing

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2021-2022
// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -66,7 +66,7 @@ func (mockIo MockIo) WriteBuffer(buffer []byte) error {
}
// ReadByte mocks reading a byte from the Apple II
func (mockIo MockIo) ReadByte() (byte, error) {
func (mockIo MockIo) ReadByte(noDelay ...bool) (byte, error) {
b := mockIo.Data.BytesToRead[mockIo.Data.NumberBytesRead]
mockIo.Data.NumberBytesRead++
return b, mockIo.Data.ErrorToThrow

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2021-2022
// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -55,7 +55,7 @@ func (userIo UserIo) WriteBuffer(buffer []byte) error {
}
// ReadByte simulates reading to the Apple II but uses stdin instead
func (userIo UserIo) ReadByte() (byte, error) {
func (userIo UserIo) ReadByte(noDelay ...bool) (byte, error) {
fmt.Printf("ReadByte: ")
var b byte
fmt.Scanf("%x", &b)

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2021-2022
// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -220,7 +220,7 @@ func sendCharacter(comm A2Io, b byte) {
}
func readCharacter(comm A2Io) (string, error) {
b, err := comm.ReadByte()
b, err := comm.ReadByte(true)
var s = string(b)
if err == nil {
if applicationMode {
@ -234,7 +234,7 @@ func readCharacter(comm A2Io) (string, error) {
case 0x08: // left
s = "\033OD"
case 0x0d: // return
s = string(byte(0x0a))
s = string(byte(0x0d))
}
} else {
switch b {
@ -247,7 +247,7 @@ func readCharacter(comm A2Io) (string, error) {
case 0x08: // left
s = "\033[D"
case 0x0d: // return
s = string(byte(0x0a))
s = string(byte(0x0d))
}
}
}

View File

@ -0,0 +1,36 @@
// Copyright Terence J. Boldt (c)2023-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
// This file is used for handling ProDOS image generation
package drive
import (
"fmt"
"os"
"path/filepath"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
// GetDriveImageDirectory gets the default directory for driveimage
func GetDriveImageDirectory() (string, error) {
exec, err := os.Executable()
if err != nil {
fmt.Printf("ERROR: %s", err.Error())
return "", err
}
driveImageDirectory := filepath.Join(filepath.Dir(filepath.Dir(exec)), "driveimage")
return driveImageDirectory, nil
}
// GenerateDriveFromDirectory regenerates a ProDOS drive from a host directory
func GenerateDriveFromDirectory(volumeName string, directory string) (prodos.ReaderWriterAt, error) {
drive := prodos.NewMemoryFile(0x2000000)
fmt.Printf("Generating Drive in memory from: %s\n", directory)
prodos.CreateVolume(drive, volumeName, 65535)
err := prodos.AddFilesFromHostDirectory(drive, directory, "/"+volumeName+"/", true)
return drive, err
}

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -19,8 +19,10 @@ import (
"go.bug.st/serial"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/a2io"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/drive"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/handlers"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/info"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
const resetCommand = 0
@ -35,7 +37,13 @@ const menuCommand = 8
const shellCommand = 9
func main() {
drive1, drive2, cdc := getFlags()
drive1Name, drive2Name, cdc := getFlags()
drive1, drive2 := getDriveFiles(drive1Name, drive2Name)
driveImageDir, err := drive.GetDriveImageDirectory()
if err == nil {
os.Chdir(driveImageDir)
}
fmt.Printf("Starting Apple II RPi v%s...\n", info.Version)
@ -49,15 +57,12 @@ func main() {
handlers.SetCommunication(comm)
comm.Init()
lastCommandTime := time.Now()
// In case Apple II is waiting, send 0 byte to start
comm.WriteByte(0)
for {
command, err := comm.ReadByte()
if err == nil {
lastCommandTime = time.Now()
switch command {
case resetCommand:
handlers.ResetCommand()
@ -68,7 +73,7 @@ func main() {
case getTimeCommand:
handlers.GetTimeCommand()
case execCommand:
handlers.ExecCommand()
handlers.ExecCommand(&drive1, &drive2)
case loadFileCommand:
handlers.LoadFileCommand()
case menuCommand:
@ -77,20 +82,20 @@ func main() {
handlers.ShellCommand()
}
// the A2Io interface should be extended in one way or another
// to encapsulate this, e.g. by a ReadByte variant / parameter
// to encapsulate this, e.g. by a ReadByte variant / parameter
} else if cdc {
var portErr *serial.PortError
if errors.As(err, &portErr) && portErr.Code() == serial.PortClosed {
comm.Init()
}
// temporary workaround for busy wait loop heating up the RPi
} else if time.Since(lastCommandTime) > time.Millisecond*100 {
time.Sleep(time.Millisecond * 100)
} else {
time.Sleep(time.Millisecond * 200)
}
}
}
func getFlags() (*os.File, *os.File, bool) {
func getFlags() (string, string, bool) {
var drive1Name string
var drive2Name string
var cdc bool
@ -99,48 +104,43 @@ func getFlags() (*os.File, *os.File, bool) {
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.StringVar(&drive2Name, "d2", "", "A ProDOS format drive image for drive 2 and will be used for drive 1 if drive 1 empty")
flag.BoolVar(&cdc, "cdc", false, "Use ACM CDC serial device")
flag.Parse()
var drive1 *os.File
var drive2 *os.File
return drive1Name, drive2Name, cdc
}
func getDriveFiles(drive1Name string, drive2Name string) (prodos.ReaderWriterAt, prodos.ReaderWriterAt) {
var drive1 prodos.ReaderWriterAt
var drive2 prodos.ReaderWriterAt
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)
}
logAndExitOnErr(err)
} else {
directory, err := drive.GetDriveImageDirectory()
logAndExitOnErr(err)
drive1, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI", directory)
logAndExitOnErr(err)
}
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)
fmt.Printf("Opening Drive 2 as: %s\n", drive2Name)
drive2, err = os.OpenFile(drive2Name, os.O_RDWR, 0755)
logAndExitOnErr(err)
}
return drive1, drive2, cdc
}
func logAndExitOnErr(err error) {
if err != nil {
fmt.Printf("ERROR: %s", err.Error())
os.Exit(1)
}
}

View File

@ -3,8 +3,9 @@ module github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver
go 1.16
require (
github.com/creack/pty v1.1.18
github.com/creack/pty v1.1.21
github.com/stianeikeland/go-rpio/v4 v4.6.0
github.com/tjboldt/ProDOS-Utilities v0.3.0
github.com/tjboldt/ProDOS-Utilities v0.4.8
golang.org/x/image v0.14.0 // indirect
go.bug.st/serial v1.3.5
)

View File

@ -1,6 +1,41 @@
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/stianeikeland/go-rpio/v4 v4.6.0 h1:eAJgtw3jTtvn/CqwbC82ntcS+dtzUTgo5qlZKe677EY=
github.com/stianeikeland/go-rpio/v4 v4.6.0/go.mod h1:A3GvHxC1Om5zaId+HqB3HKqx4K/AqeckxB7qRjxMK7o=
github.com/tjboldt/ProDOS-Utilities v0.3.0 h1:nlBvrGtvAV7KBfxiSkXHdosmDLEYAXMq955P8NL0qiE=
github.com/tjboldt/ProDOS-Utilities v0.3.0/go.mod h1:eBQRf0U+goRbBOxzFCwRW+FZmALC8dfYaqCwcqwzi74=
github.com/tjboldt/ProDOS-Utilities v0.4.8 h1:hW4gHliqTjKCep6jXX4Z59pkVhB+OyVJPWM5X3N+ybs=
github.com/tjboldt/ProDOS-Utilities v0.4.8/go.mod h1:tk5Cd5WSoogNF+XRMjEPuWeU1vVuqdJexn23s5ev/fU=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -8,13 +8,12 @@ package handlers
import (
"fmt"
"os"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
// ReadBlockCommand handles requests to read ProDOS blocks
func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
func ReadBlockCommand(drive1 prodos.ReaderWriterAt, drive2 prodos.ReaderWriterAt) (int, error) {
blockLow, _ := comm.ReadByte()
blockHigh, _ := comm.ReadByte()
var driveUnit byte
@ -24,7 +23,7 @@ func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
if err != nil {
fmt.Printf("Failed to read block")
return
return 0, err
}
file := drive1
@ -35,28 +34,30 @@ func ReadBlockCommand(drive1 *os.File, drive2 *os.File) {
driveNumber = 2
}
slotNumber := driveUnit &0x7F >> 4
slotNumber := driveUnit & 0x7F >> 4
block := int(blockHigh)*256 + int(blockLow)
fmt.Printf("Read block %04X in slot %d, drive %d...", block, slotNumber, driveNumber)
buffer,err := prodos.ReadBlock(file, block)
buffer, err := prodos.ReadBlock(file, block)
if err != nil {
fmt.Printf("failed %s\n",err)
return
fmt.Printf("failed %s\n", err)
return 0, err
}
err = comm.WriteBlock(buffer)
if err == nil {
fmt.Printf("succeeded\n")
} else {
fmt.Printf("failed %s\n",err)
fmt.Printf("failed %s\n", err)
}
return block, nil
}
// WriteBlockCommand handles requests to write ProDOS blocks
func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
func WriteBlockCommand(drive1 prodos.ReaderWriterAt, drive2 prodos.ReaderWriterAt) error {
blockLow, _ := comm.ReadByte()
blockHigh, _ := comm.ReadByte()
@ -66,7 +67,7 @@ func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
driveUnit, err = comm.ReadByte()
if err != nil {
fmt.Printf("Failed to write block")
return
return err
}
file := drive1
@ -81,14 +82,14 @@ func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
block := int(blockHigh)*256 + int(blockLow)
slotNumber := driveUnit &0x7F >> 4
slotNumber := driveUnit & 0x7F >> 4
fmt.Printf("Write block %04X in slot %d, drive %d...", block, slotNumber, driveNumber)
err = comm.ReadBlock(buffer)
if err != nil {
fmt.Printf("failed %s\n",err)
return
fmt.Printf("failed %s\n", err)
return err
}
fmt.Printf("...")
@ -98,4 +99,6 @@ func WriteBlockCommand(drive1 *os.File, drive2 *os.File) {
} else {
fmt.Printf("failed\n")
}
return nil
}

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2021-2022
// Copyright Terence J. Boldt (c)2021-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -16,14 +16,16 @@ import (
"strings"
"time"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/drive"
"github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver/info"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
var forceLowercase = false
var execTimeoutSeconds = int(10)
// ExecCommand handles requests for the Apple II executing Linux commands
func ExecCommand() {
func ExecCommand(drive1 *prodos.ReaderWriterAt, drive2 *prodos.ReaderWriterAt) {
workingDirectory, err := os.Getwd()
if err != nil {
workingDirectory = "/home"
@ -74,6 +76,10 @@ func ExecCommand() {
a2timeout(linuxCommand)
return
}
if strings.HasPrefix(linuxCommand, "a2drive") {
a2drive(linuxCommand, drive1, drive2)
return
}
if linuxCommand == "a2prompt" {
prompt := fmt.Sprintf("A2IO:%s ", workingDirectory)
comm.WriteString(prompt)
@ -160,6 +166,7 @@ func a2help() {
"a2timeout - seconds to timeout commands\r" +
"A2LOWER - force lowercase for II+\r" +
"a2lower - disable force lowercase\r" +
"a2drive - change drive images\r" +
"\r")
}
@ -182,6 +189,89 @@ func a2timeout(linuxCommand string) {
}
}
func a2drive(linuxCommand string, drive1 *prodos.ReaderWriterAt, drive2 *prodos.ReaderWriterAt) {
params := strings.Fields(linuxCommand)
if len(params) < 3 {
showa2DriveUsage()
return
}
driveNumber, err := strconv.ParseInt(params[1], 10, 32)
if err != nil {
comm.WriteString("\rFailed to parse drive number\r")
showa2DriveUsage()
return
}
if params[2] == "regen" {
directory, err := drive.GetDriveImageDirectory()
if err != nil {
comm.WriteString("\rFailed to parse source directory\r")
return
}
if len(params) > 3 {
directory = params[3]
}
switch driveNumber {
case 1:
*drive1, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI", directory)
if err != nil {
comm.WriteString("\rFailed to regenerate drive 1\r")
return
}
comm.WriteString("\rDrive 1 regenerated\r")
case 2:
*drive2, err = drive.GenerateDriveFromDirectory("APPLE2.IO.RPI2", directory)
if err != nil {
comm.WriteString("\rFailed to regenerate drive 2\r")
return
}
comm.WriteString("\rDrive 2 regenerated\r")
default:
comm.WriteString("\rOnly drives 1 or 2 are supported\r")
showa2DriveUsage()
return
}
}
if params[2] == "load" {
if len(params) != 4 {
comm.WriteString("\rMust specify a drive image to load\r")
showa2DriveUsage()
return
}
imageFileName := params[3]
switch driveNumber {
case 1:
*drive1, err = os.OpenFile(imageFileName, os.O_RDWR, 0755)
if err != nil {
comm.WriteString("\rFailed to load drive 1\r")
return
}
comm.WriteString("\rDrive 1 loaded\r")
case 2:
*drive2, err = os.OpenFile(imageFileName, os.O_RDWR, 0755)
if err != nil {
comm.WriteString("\rFailed to load drive 2\r")
return
}
comm.WriteString("\rDrive 2 loaded\r")
default:
comm.WriteString("\rOnly drives 1 or 2 are supported\r")
showa2DriveUsage()
return
}
}
}
func showa2DriveUsage() {
comm.WriteString("\rUsage: a2drive DRIVENUMBER [regen [PATH] | load FILENAME]\rExamples: a2drive 1 regen ~/Apple2-IO-RPi/RaspberryPi/driveimage\r a2drive 2 load /home/pi/Games.hdv\r")
}
func a2lower(enable bool) {
forceLowercase = enable
comm.WriteString(fmt.Sprintf("All commands will be converted to lowercase: %t\r", forceLowercase))

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -15,7 +15,7 @@ import (
func MenuCommand() {
fmt.Printf("Sending menu...\n")
comm.WriteString("Apple2-IO-RPi\r" +
"(c)2020-2021 Terence J. Boldt\r" +
"(c)2020-2024 Terence J. Boldt\r" +
"\r" +
"Select an option:\r" +
"\r" +

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -17,6 +17,7 @@ import (
// ShellCommand handles requests for the Apple II executing a Linux shell
func ShellCommand() {
fmt.Printf("Shell started\n")
cmd := exec.Command("bash", "-i")
cmd.Env = append(os.Environ(),
"TERM=vt100",
@ -43,7 +44,10 @@ func ShellCommand() {
for {
select {
case <-outputComplete:
fmt.Printf("Shell output complete\n")
outputComplete <- true
ptmx.Close()
cmd.Wait()
comm.WriteByte(0)
// return
break
@ -54,6 +58,8 @@ func ShellCommand() {
// comm.WriteByte(0)
return
case <-inputComplete:
fmt.Printf("Shell input complete\n")
ptmx.Close()
cmd.Wait()
comm.WriteByte(0)
return

View File

@ -1,4 +1,4 @@
// Copyright Terence J. Boldt (c)2020-2022
// Copyright Terence J. Boldt (c)2020-2024
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
@ -8,4 +8,4 @@ package info
// Version is the hexadecimal version number that
// should be incremented with each driver update
const Version = "0026"
const Version = "002C"

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
../../Apple2/Startup.bas

View File

@ -0,0 +1 @@
../../Apple2/Update.Firmware.bas

View File

@ -1,34 +1,56 @@
#!/bin/sh
sudo apt update
sudo apt install git -y
wget https://golang.org/dl/go1.19.linux-armv6l.tar.gz
sudo tar -C /usr/local -xzf go1.19.linux-armv6l.tar.gz
if [ "$(uname -m)" = 'aarch64' ]; then
if [ ! -f go1.21.3.linux-arm64.tar.gz ]; then
wget https://go.dev/dl/go1.21.3.linux-arm64.tar.gz
sudo tar -C /usr/local -xzf go1.21.3.linux-arm64.tar.gz
fi
else
if [ ! -f go1.21.3.linux-arm6l.tar.gz ]; then
wget https://golang.org/dl/go1.21.3.linux-armv6l.tar.gz
sudo tar -C /usr/local -xzf go1.21.3.linux-armv6l.tar.gz
fi
fi
if [ -f "/usr/bin/go" ]; then
sudo rm /usr/bin/go
fi
sudo ln -s /usr/local/go/bin/go /usr/bin/go
git clone https://github.com/tjboldt/ProDOS-Utilities.git
if [ ! -d "ProDOS-Utilities" ]; then
git clone https://github.com/tjboldt/ProDOS-Utilities.git
fi
cd ProDOS-Utilities || exit
go mod tidy
go build
cd ~ || exit
if [ -L "/usr/bin/ProDOS-Utilities" ]; then
sudo rm /usr/bin/ProDOS-Utilities
fi
sudo ln -s $HOME/ProDOS-Utilities/ProDOS-Utilities /usr/bin/ProDOS-Utilities
git clone https://github.com/oliverschmidt/Apple2-IO-RPi.git
if [ ! -d "Apple2-IO-RPi" ]; then
git clone https://github.com/tjboldt/Apple2-IO-RPi.git
fi
cd Apple2-IO-RPi/RaspberryPi/apple2driver || exit
go mod tidy
go build
sudo apt install cc65 vim -y
cd ~ || exit
sudo bash -c 'cat > /boot/config.txt << EOF
disable_splash=1
dtoverlay=disable-bt
boot_delay=0
EOF'
sudo bash -c 'echo " quiet" >> /boot/cmdline.txt'
wget https://github.com/a2-4am/4cade/releases/latest/download/Total.Replay.hdv
sudo --preserve-env=HOME --preserve-env=USER bash -c 'cat > /etc/systemd/system/apple2driver.service << EOF
sudo --preserve-env=HOME --preserve-env=USER bash -c 'cat > apple2driver.service << EOF
[Unit]
Description=Apple2-IO-RPi Driver
[Service]
ExecStart=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver -cdc -d1 $HOME/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv -d2 $HOME/Total.Replay.hdv
ExecStart=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=apple2driver
User=$USER
Group=$USER
@ -37,8 +59,11 @@ WorkingDirectory=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver
[Install]
WantedBy=basic.target
EOF'
sudo mv apple2driver.service /etc/systemd/system/apple2driver.service
sudo chown root:root /etc/systemd/system/apple2driver.service
sudo systemctl start apple2driver
sudo systemctl enable apple2driver
sudo systemctl disable avahi-daemon.service
sudo systemctl disable triggerhappy.service
sudo systemctl disable raspi-config.service
sudo systemctl daemon-reload