Compare commits

...

85 Commits

Author SHA1 Message Date
Terence Boldt 8b04a0e926
Add clock driver, remove from firmware (#168) 2024-04-18 14:23:22 -04:00
Terence Boldt 1336371b49 Update setup.sh 2024-04-02 14:56:42 -04:00
Terence Boldt 7bc130582d Fix build script 2024-03-29 12:13:39 -04:00
Terence Boldt 0f58e987f1 Update setup and instructions 2024-03-29 12:13:39 -04:00
Terence Boldt de156de730 Fix Pico build 2024-03-29 12:13:39 -04:00
Oliver Schmidt 3441a73d9d Remove useless port mirrors. 2024-02-10 09:01:05 -05:00
Oliver Schmidt ab601d0897 Adjust AT28C64B.bin path. 2024-02-10 09:01:05 -05:00
Terence Boldt aa5910cee8
Initial Pico hardware support
* Added assemble.cmd for Windows.

In the long run, some (c)make-based cross-plafrom solution seems preferable.

* Fill up the menu page just like the other pages.

* Allow to assemble for different hardware types.

The first script parameter is used to set the ca65 symbol HW_TYPE. Without parameter, HW_TYPE is set to 0.

* Avoid unwanted i/o access.

Depending on the 6502, LDA addr,X and/or STA addr,X produce additional phantom reads. In order to avoid those phantom reads to do i/o access, I used the "classic" approach of moving those reads from page $C0 to page $BF.

* Made use of BIT instruction to access InputFlags from firmware.

Doing the same for access from disk-based software would require selfmodifying code as there's not bit <addr>,x instruction.

* Removed push/pop from GetByte.

After the replacing the rol instructions with bit instructions with a recent chnage, the only reason left to save a to the stack was setting the OutputFlags. But that can be done using x.

* Added InputFlags check for consistency.

* Added support for an alternative hardware type.

The new hardware type has simple UART-type interface. Beside the two data registers, there are only the two bits to indicate readability and writability of the data registers.

* Added another comminucation interface implementation.

Use ACM CDC (or another proprietary) USB serial device for communication.

Currently VID / PID of a Raspberry Pi Pico SDK CDC UART are hardcoded - see https://github.com/raspberrypi/usb-pid

* Revert "Avoid unwanted i/o access."

Neither the original hardware type nor the alternative hardware type have any read and write i/o port share addresses. Therefore phantom reads aren't an issue with those hardware types.

This reverts commit ae5cb754fb.

* Adapt to the different error signatures on Linux.

So far the code was only tested on Windows.

* Added implementation of the alternative hardware type.

The implemenation is based on a Raspberry Pi Pico - see https://github.com/a2retrosystems/A2retroNET

The new hardware type has a simple UART-type interface. Beside the two data registers, there are only the two bits to indicate readability and writability of the data registers.

* Modify the HD image for the alternative hardware type.

It is likely desirable to have two HD images for the two hardware types. And likely the apple2driver program should default to the right one based on its protocol setting. BUt given that the HD image(s) shouldn't be part of the actual Git repo anyhow, I don't do anything about this here and now.

* Fixed shell startup (?)

At least on the alternative hardware, this "blindly sending" a reset command causes the shell to be terminated right away:
The driver acknowldges the reset command with a zero byte - and that byte ends up being read by DumpOutput causing it to branch to endOutput.

Maybe that sending a reset command is beneficial on the original hardware. Then another .if is required. Or DumpOutput shouldn't quit on reading a zero byte - the shell handler doesn't seem to send it on purpose(?)

* Upate HD image with recent shell change.

* Fix shell shutdown (?)

At least on the alternative hardware, things happen this way:
1. The shell 'exit' command has ptyOut signal outputComplete and terminate. At this point, ptyIn is still blocked up to one second in ReadCharacter - and can therefore not react on outputComplete.
2. The outputComplete handler in ShellCommand sends a zero byte. This makes on the A2 DumpOutput return and the caller send a zero byte. ShellCommand must not return here as ptyIn is still blocked.
3. The zero byte from the A2 has ptyIn return from ReadCharacter, signal userCancelled and terminate.
4. ShellCommand can now return, but it must not send a zero byte, as the A2 is not expecting it - and will therefore later misinterpret it.

Maybe the original hardware needs another handling, then differentiation of behavior in shell.go becomes necessary.

* Moved boot text out of IIgs copyright message area.

Having the boot text start at the left border of the third line makes it look nice on the cold boot screen of all Apple II's - and there's where the user sees it for some time while waiting for the RPi to come up.

* Several adjustements:

- Get latest Go version as of now.
- Nowadays (?) GitHub 'git clone' seems to only work with a GitHub account. Therefore the zip download workaround. The becomes hopefully unnecessary soon with Go module magic.
- Use 'go mod tidy' to update .sum file for now.
- Error handling for an empty drive 2 is currently not exactly great, so download Total Replay for drive 2. Unfortunately there's no stable URL as of now.
- Use $USER and $HOME instead of hardcoded values.
- Removed deprecated syslog output directives.

* Added brief fork description.

* Added ProDOS-Utilities reference.

* Reverted back to using 'git clone'.

I've no idea why git acted up the other day :-( Now, everything is back to normal...

* Ignore Pico build directory.

* Updated from https://github.com/a2retrosystems/A2retroNET

* Updated from https://github.com/a2retrosystems/A2retroNET

At this point, nothing at all is done on an A2 reset. This can likely be improved. However, Apple2-IO-RPi doesn't seem to handle A2 reset exactly gracefully anyhow.

In general, it seems desirable to introduce some simple framing protocol - like SLIP - that allows to recover from an A2 reset in the middle of an Apple2-IO-RPi command execution.

Such a framing protocol would allow to introduce different frame types. One frame type could then be an A2 reset frame sent by the A2retroNET firmware.

* Make use of brand new stable Total Replay download URL.

Thanks to 4am :-)

* Fixed typos.

* Clone upstream ProDOS-Utilities.

My ProDOS-Utilities pull request was merged.

* Added support for boards without LED.

* Updated link.

* Adjusted to the current A2retroNET hardware.

* Removed support for the Pico W.

* Updated URL.

* Updated URL.

* Make use A2Pico library.

* Added link to A2Pico.

* Remove intermediates from repo.

* Build intermediates from Pico build.

* Have LED reflect status of logic ACM connection.

* Update upstream repo references.

* Adjust build instructions.

* Update README.md

* Fix build and update dependencies

* Fix binary comparison

* Fix firware bug on classic hardware

---------

Co-authored-by: Oliver Schmidt <ol.sc@web.de>
2024-02-05 22:49:09 -05:00
Terence Boldt 729ea131db Update ProDOS to 2.4.3 2024-01-02 19:54:35 -08:00
Terence Boldt 2281d03128 Update copyright for 2024 2024-01-02 19:54:35 -08:00
Terence Boldt f6002fa7f9 Update dependencies 2023-12-04 23:29:26 -05:00
Terence Boldt 3840db1a35
Fix nano with enter key as 0x0D (#158) 2023-12-04 23:23:59 -05:00
Terence Boldt 5762cdae3e
Update bug_report.yml 2023-11-19 09:38:07 -05:00
Terence Boldt bde5767314
Fix keyboard delay (#152) 2023-11-01 20:00:21 -04:00
Terence Boldt 6edd7ecf11
Update bug_report.yml 2023-10-31 23:08:30 -04:00
Terence Boldt 8d5aa26b78
Add backoff to reduce CPU usage (fixes #141) (#151)
* Add backoff to reduce CPU usage

* Update driver version for CPU fix
2023-10-31 23:04:15 -04:00
Terence Boldt 0dbb55fda1 Add 64 bit OS support, upgrade Go, allow non-pi user 2023-10-31 21:51:06 -04:00
Terence Boldt 5db78ba3b9
Do apt update before installation
Fixes #140
2023-04-04 18:56:22 -04:00
Terence Boldt 8ef94ba5d3 Update schematic PDF 2023-03-08 09:26:35 -05:00
Terence Boldt 53377e2dc0 Add bill of materials 2023-03-08 09:26:35 -05:00
Terence Boldt d20717cc79
Update schematics for 0.1 µF caps (#136) 2023-03-01 05:53:35 -07:00
Terence Boldt cca6d43657
Update library for security fix (#135) 2023-03-01 05:33:15 -07:00
Terence Boldt 9883348baa
Add drive load (#133) 2023-02-04 19:09:57 -05:00
Terence Boldt ad6d103cca
Fix hang after shell exit (#131) 2023-01-30 20:45:24 -05:00
Terence Boldt 60a311549d
Update README.md 2023-01-28 10:23:27 -05:00
Terence Boldt 27b01d0925
Update README.md 2023-01-28 09:53:39 -05:00
Terence Boldt 554d3390d6
Set default dir to driveimage (#125) 2023-01-26 22:33:08 -05:00
Terence Boldt 813ab1caee
Change bas files to symlinks (#123) 2023-01-25 23:07:09 -05:00
Terence Boldt b10dec3e50
Add live drive regeneration and loading (#122) 2023-01-25 22:32:47 -05:00
Terence Boldt 841b11f9ae
Add graphics conversion
* Update copyright year

* Update module to add image support
2023-01-14 10:51:39 -05:00
Terence Boldt 382cfebc26
Update README.md 2023-01-08 22:50:22 -05:00
Terence Boldt 91346471ae
Update driver version 2023-01-08 22:35:15 -05:00
Terence Boldt 28dc09a877
Dynamic drive (#114)
* Fix for when not using dynamic drive
2023-01-08 18:03:57 -05:00
Terence Boldt c64f187251
Create codeql.yml 2023-01-01 10:21:22 -05:00
Terence Boldt 9c0d819f5a
Delete codacy-analysis.yml 2023-01-01 10:20:38 -05:00
Terence Boldt b507ec99a9
Create codacy.yml 2023-01-01 10:20:23 -05:00
Terence Boldt 803d5f436c
Update README.md 2022-12-31 12:40:27 -05:00
Terence Boldt d90b94f4b1 Fix compare for build 2022-12-31 12:39:15 -05:00
Terence Boldt a13866a458 Fix boot of dynamic drive 2022-12-31 12:39:15 -05:00
Terence Boldt f0e67ea5ff Fix dynamic drive 2022-12-31 12:39:15 -05:00
Terence Boldt 91efe725b7 Add dynamic drive support 2022-12-31 12:39:15 -05:00
Terence Boldt 4b7d990209 Fix security warnings in setup.sh 2022-04-27 22:50:04 -04:00
Terence Boldt ed2acd9d5f Update boot image 2022-04-27 22:36:27 -04:00
Terence Boldt da04931665 Add error handling 2022-04-27 22:36:27 -04:00
Terence Boldt 74702e2cb5 Fix setup script 2022-03-19 14:08:22 -04:00
Terence Boldt 9f85fba5ad Add setup script 2022-03-19 14:05:20 -04:00
Terence Boldt 55d94dd1f0 Update RPi.Command and driver for it 2022-03-03 22:34:45 -05:00
Terence Boldt 707c704119
Merge pull request #98 from tjboldt/binary-compare
Verify generated binaries
2022-03-02 21:58:45 -05:00
Terence Boldt d33264edf5 Fix Codacy warning 2022-03-02 21:54:28 -05:00
Terence Boldt d897149901 Verify generated binaries 2022-03-02 21:46:45 -05:00
Terence Boldt 087f5a299f
Merge pull request #97 from tjboldt/shell-version
Update version numbers
2022-03-02 08:35:43 -05:00
Terence Boldt a751737bf1 Update version numbers 2022-03-01 22:46:03 -05:00
Terence Boldt 869eb25c11
Merge pull request #96 from tjboldt/fix-vi-arrows
Fixes #94 VT100 arrow keys for application mode
2022-03-01 08:31:30 -05:00
Terence Boldt 661c2fc8f6 Fixes #94 VT100 arrow keys for application mode 2022-03-01 08:26:54 -05:00
Terence Boldt bd88d194d4 Fix #95 gerber render for PCBWay compatibility 2022-03-01 05:38:58 -05:00
Terence Boldt 9198e2ae6c
Update README.md 2022-02-28 20:59:47 -05:00
Terence Boldt b9a2eacb5d
Merge pull request #92 from tjboldt/shell-kb-fix
Fix keyboard input glitch on read
2022-02-23 22:44:18 -05:00
Terence Boldt 049e8770d2 Fix keyboard input glitch on read 2022-02-23 22:42:19 -05:00
Terence Boldt fd0f020364
Merge pull request #91 from tjboldt/shell-kb-fix
Fix #56 shell crash on key autorepeat
2022-02-22 15:49:19 -05:00
Terence Boldt 1f4c9ddf4d Fix #56 shell crash on key autorepeat 2022-02-22 15:43:54 -05:00
Terence Boldt f9dab0aff3
Update README.md 2022-02-22 10:49:36 -05:00
Terence Boldt 141d5fc691
Merge pull request #90 from hanshuebner/main
Clean up buses for aesthetics
2022-02-21 05:19:48 -05:00
Hans Huebner c280e7f829 Clean up buses for aesthetics 2022-02-21 11:02:59 +01:00
Terence Boldt 8d22144890 Update pdf to latest schematic 2022-02-20 21:53:06 -05:00
Terence Boldt 78d7b73793
Merge pull request #89 from hanshuebner/main
Name fix and contributor links
2022-02-20 16:31:49 -05:00
Hans Hübner 468dc6708b
Add contributor links 2022-02-20 22:27:21 +01:00
Hans Hübner 150177e3de
Fix name typo in README 2022-02-20 22:21:15 +01:00
Terence Boldt 00e412c552
Add contributions/thanks to README 2022-02-20 13:58:42 -05:00
Terence Boldt c03235acea Clean up ERC warnings/errors 2022-02-20 13:26:37 -05:00
Terence Boldt e1ac67974f Fix warnings and errors in PCB 2022-02-20 11:21:20 -05:00
Terence Boldt 261c523836
Merge pull request #88 from hanshuebner/main
Improve schematics
2022-02-20 09:29:20 -05:00
Hans Huebner e2a2af197a Fix AT28C64D pins, add GPIO bus 2022-02-20 09:31:20 +01:00
Hans Huebner b5bc96624f Reconnect EEPROM CE correctly, tweaks 2022-02-19 06:23:17 +01:00
Hans Huebner ea7b4b5e08 Add power nets 2022-02-18 20:18:05 +01:00
Hans Huebner 95682eb6de Add data bus 2022-02-18 17:34:16 +01:00
Hans Huebner c151b16107 Remove power wires, improve signal names 2022-02-18 12:34:56 +01:00
Hans Huebner 27c38fbff5 Apple II connector pin names and directions 2022-02-18 10:42:23 +01:00
Hans Huebner e101638de8 Ignore KiCAD backups 2022-02-18 10:03:49 +01:00
Hans Huebner a079ae3cd7 Make ERC pass 2022-02-18 10:03:15 +01:00
Hans Huebner aaefdfcc8d Add no-connects to open pins 2022-02-18 09:22:28 +01:00
Terence Boldt 37dd7b1c3b
Merge pull request #87 from tjboldt/external-power
Add sixth prototype with external power jumper
2022-02-17 20:19:43 -05:00
Terence Boldt 8efc93a317
Update README.md 2022-02-17 20:12:41 -05:00
Terence Boldt 12cdc7ea44 Update to KiCAD 6 2022-02-17 20:00:32 -05:00
Terence Boldt a1ef730dac Update README for sixth prototype 2022-02-16 21:50:16 -05:00
Terence Boldt c29232b407 Add power jumper and instructions 2022-02-16 21:45:22 -05:00
94 changed files with 26644 additions and 101532 deletions

View File

@ -22,12 +22,10 @@ body:
label: Hardware Version
description: What version of the hardware are you running?
options:
- Fifth Prototype (Purchased from Terence)
- Fifth Prototype (Self-assembled)
- Fifth Prototype (Purchased from third party)
- Fourth Prototype (Purchased from Terence)
- Fourth Prototype (Self-assembled)
- Fourth Prototype (Purchased from third party)
- RPi Pico
- Sixth Prototype (lastest classic hardware)
- Fifth Prototype (classic hardware without jumper)
- Fourth Prototype (classic hardware with EPROM)
validations:
required: true
- type: dropdown
@ -36,6 +34,8 @@ body:
label: Firmware Version
description: What version of the firmware are you running? (shown on boot screen)
options:
- 8010 (initial RPi Pico hardware)
- 0010 (classic hardware)
- 000F
- Older (not shown on boot, pre-2022-Feb-07)
validations:
@ -46,11 +46,35 @@ body:
label: Driver Version
description: What version of the driver are you running? Check with `RPI a2version`
options:
- 002D (add support for RPi Pico hardware)
- 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)
- Older (error calling RPI a2version, pre-2022-Feb-07)
validations:
required: true
- type: dropdown
id: shell-version
attributes:
label: Shell Version
description: What version of the shell are you running?`
options:
- 800F (initial RPi Pico support)
- 000F (classic hardware support)
- 000E (fix hang on exit)
- 000D (added version info)
- Older (pre-2022-Mar-01)
- Not Applicable (bug not Shell related)
validations:
required: true
- type: dropdown
id: problem-area
attributes:

View File

@ -18,4 +18,9 @@ jobs:
export PATH=$PATH:$(pwd)/.cicd
cd Apple2
./assemble.sh
- name: Compare binaries
run: |
export PATH=$PATH:$(pwd)/.cicd
cd Apple2
./compare.sh

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}}"

14
.gitignore vendored
View File

@ -1,5 +1,19 @@
*-bak
*.o
*.DS_Store
*.bin
*.lst
RaspberryPi/apple2driver/apple2driver
RaspberryPi/Apple2-IO-RPi.log
RaspberryPiPico/build/
Hardware/Apple2IORPi-backups/
RaspberryPiPico/Apple2-IO-RPi.*
RaspberryPiPico/CMakeCache.txt
RaspberryPiPico/CMakeFiles/
RaspberryPiPico/Makefile
RaspberryPiPico/_deps/
RaspberryPiPico/cmake_install.cmake
RaspberryPiPico/elf2uf2/
RaspberryPiPico/generated/
RaspberryPiPico/pico-sdk/
RaspberryPiPico/pioasm/

Binary file not shown.

140
Apple2/Clock.Driver.asm Normal file
View File

@ -0,0 +1,140 @@
; Copyright Terence J. Boldt (c)2024
; Use of this source code is governed by an MIT
; license that can be found in the LICENSE file.
; This file contains the source for the clock
; driver for the Apple2-IO-RPi
EnableWriteLang = $C08B
DisableWriteLang = $C082
ProdosJump = $BF06
ProdosClockCode = $BF07
ProdosMachineId = $BF98
PrintChar = $FDED
PrintHex = $FDE3
PrintByte = $FDDA
GetTimeCommand = $03
.org $2000
; Find Apple2-IO-RPi card
ldx #$06
ldy #$09
CheckIdBytes:
lda $C700,y ; !! Self modifying code
cmp IdBytes,y
bne NextCard
dey
bne CheckIdBytes
jmp FoundCard
NextCard:
dec CheckIdBytes+2
ldy #$09
dex
bne CheckIdBytes
CardNotFound:
ldy #$00
PrintCardNotFound:
lda TextCardNotFound,y
beq Failed
ora #$80
jsr PrintChar
iny
bne PrintCardNotFound
Failed:
rts
FoundCard:
ldy #$00
PrintCardFound:
lda TextCardFound,y
beq PrintCardNumber
ora #$80
jsr PrintChar
iny
bne PrintCardFound
PrintCardNumber:
inx
txa
jsr PrintHex
lda #$8D
jsr PrintChar
; Change driver code to point to the card
txa
ora #$C0
sta GetByte+2
sta SendByte+2
; Change destination to be ProDOS clock code location
lda ProdosClockCode
sta DriverDestination+1
lda ProdosClockCode+1
sta DriverDestination+2
; Changing RTS to JMP enables clock driver
lda #$4C ; jump instruction
sta ProdosJump
; Enable writing to language card RAM
; by triggering switch twice
lda EnableWriteLang
lda EnableWriteLang
; write driver code to language card RAM
ldy #$00
WriteDriver:
lda Driver,y
DriverDestination:
sta $D742,y ; !! this address gets modified above
iny
cpy #EndDriver-Driver+2
bne WriteDriver
; Disable writing to language card RAM
lda DisableWriteLang
; Update ProDOS Machine ID to mark clock as enabled
lda ProdosMachineId
ora #$01
sta ProdosMachineId
ldy #$00
PrintFinished:
lda TextDriverInstalled,y
beq Finished
ora #$80
jsr PrintChar
iny
bne PrintFinished
Finished:
rts
IdBytes:
.byte $E0,$20,$E0,$00,$E0,$03,$E0,$3C,$A9,$3F
TextCardFound:
.byte "Found Apple2-IO-RPi in slot ",$00
TextCardNotFound:
.byte "Apple2-IO-RPi not found",$8D,$00
TextDriverInstalled:
.byte "Apple2-IO-RPi Clock driver version 0001",$8D,$00
Driver:
lda #GetTimeCommand
SendByte:
jsr $C749 ; !! address gets modified on installation
ldy #$00
getTimeByte:
GetByte:
jsr $C743 ; !! address gets modified on installation
sta $bf90,y
iny
cpy #$04
bne getTimeByte
EndDriver:
rts

View File

@ -1,9 +1,10 @@
; 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.
; This file contains the source for the firmware
; that was formerly used to act as a pseudo-shell
; This file formerly contained the source for the
; firmware that had a pseudo command prompt
; but is now empty except required common bytes
;ProDOS Zero Page
Command = $42 ;ProDOS Command
@ -32,144 +33,41 @@ LoadFileCommand = $06
SaveFileCommand = $07
MenuCommand = $08
InputString = $fd67
PrintChar = $fded
Keyboard = $c000
ClearKeyboard = $c010
Wait = $fca8
.org SLOT*$100 + $C000
;ID bytes for booting and drive detection
cpx #$20 ;ID bytes for ProDOS and the
cpx #$00 ; Apple Autostart ROM
cpx #$20 ;ID bytes for ProDOS
cpx #$00 ;
cpx #$03 ;
cpx #$3C ;ID byte for Autostart ROM
ldx #SLOT*$10
stx $2b
stx Unit
;force EPROM to second page on boot
lda #$3f ;set all flags high and page 3 of EPROM for menu
jmp PageJump
;The following bytes must exist in this location for Pascal communications
;as they are standard pointers for entry points
.byte CommInit&$00FF ;low byte of rts for init of Pascal comms
.byte $43 ; low byte of read for Pascal comms
.byte $49 ; low byte of write for Pascal comms
.byte $4F ; low byte of rts for status of Pascal comms
CommInit:
lda #$0f ; set all flags high and page 0 for comm driver
sta OutputFlags
ldx #$00 ; set error code to 0 for success
rts
PageJump:
sta OutputFlags
jmp Start ;this jump is only called if coming in from PageJump with A=$2f
jmp Start ;this jump is only called if coming in from PageJump with A=$0f
;entry points for ProDOS
DriverEntry:
lda #$0f ;set all flags high and page 0 of EPROM
sta OutputFlags
jmp Start ; this is never called as the EPROM page changes
;load first two blocks and execute to boot
Start:
jsr $c300 ;enable 80 columns
lda #$05 ;execute command
jsr SendByte
ldy #$00
sendHelp:
lda HelpCommand,y
beq endSendHelp
jsr SendByte
iny
bne sendHelp
endSendHelp:
lda #$00
jsr SendByte
jsr DumpOutput
lda $33
pha
lda #$a4
sta $33
GetCommand:
jsr InputString
lda $0200
cmp #$8d ;skip when return found
beq GetCommand
jsr SendCommand
clc
bcc GetCommand
SendCommand:
bit ClearKeyboard
lda #$05 ;send command 5 = exec
jsr SendByte
ldy #$00
getInput:
lda $0200,y
cmp #$8d
beq sendNullTerminator
and #$7f
jsr SendByte
iny
bne getInput
sendNullTerminator:
lda #$00
jsr SendByte
DumpOutput:
jsr GetByte
bcs skipOutput
cmp #$00
beq endOutput
jsr PrintChar
skipOutput:
bit Keyboard ;check for keypress
bpl DumpOutput ;keep dumping output if no keypress
lda Keyboard ;send keypress to RPi
jsr PrintChar
and #$7f
jsr SendByte
bit ClearKeyboard
clc
bcc DumpOutput
endOutput:
rts
HelpCommand:
.byte "a2help",$00
SendByte:
pha
waitWrite:
lda InputFlags
rol
rol
bcs waitWrite
pla
sta OutputByte
lda #$1e ; set bit 0 low to indicate write started
sta OutputFlags
finishWrite:
lda InputFlags
rol
rol
bcc finishWrite
lda #$1f
sta OutputFlags
rts
GetByte:
lda #$1d ;set read flag low
sta OutputFlags
waitRead:
lda InputFlags
rol
bcc readByte
bit Keyboard ;keypress will abort waiting to read
bpl waitRead
lda #$1f ;set all flags high and exit
sta OutputFlags
sec ;failure
rts
readByte:
lda InputByte
pha
lda #$1f ;set all flags high
sta OutputFlags
finishRead:
lda InputFlags
rol
bcc finishRead
pla
clc ;success
end:
rts
@ -178,5 +76,6 @@ end:
.endrepeat
.byte 0,0 ;0000 blocks = check status
.byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
.byte 23 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
.byte DriverEntry&$00FF ;low byte of entry

View File

@ -1,195 +0,0 @@
ca65 V2.18 - N/A
Main file : CommandFirmware.asm
Current file: CommandFirmware.asm
000000r 1 ; Copyright Terence J. Boldt (c)2020-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the firmware
000000r 1 ; that was formerly used to act as a pseudo-shell
000000r 1
000000r 1 ;ProDOS Zero Page
000000r 1 Command = $42 ;ProDOS Command
000000r 1 Unit = $43 ;ProDOS unit (SDDD0000)
000000r 1 BufferLo = $44
000000r 1 BufferHi = $45
000000r 1 BlockLo = $46
000000r 1 BlockHi = $47
000000r 1
000000r 1 ; ProDOS Error Codes
000000r 1 IOError = $27
000000r 1 NoDevice = $28
000000r 1 WriteProtect = $2B
000000r 1
000000r 1 InputByte = $c08e+SLOT*$10
000000r 1 OutputByte = $c08d+SLOT*$10
000000r 1 InputFlags = $c08b+SLOT*$10
000000r 1 OutputFlags = $c087+SLOT*$10
000000r 1
000000r 1 ReadBlockCommand = $01
000000r 1 WriteBlockCommand = $02
000000r 1 GetTimeCommand = $03
000000r 1 ChangeDriveCommand = $04
000000r 1 ExecCommand = $05
000000r 1 LoadFileCommand = $06
000000r 1 SaveFileCommand = $07
000000r 1 MenuCommand = $08
000000r 1
000000r 1 InputString = $fd67
000000r 1 PrintChar = $fded
000000r 1 Keyboard = $c000
000000r 1 ClearKeyboard = $c010
000000r 1 Wait = $fca8
000000r 1
000000r 1 .org SLOT*$100 + $C000
00C700 1 ;ID bytes for booting and drive detection
00C700 1 E0 20 cpx #$20 ;ID bytes for ProDOS and the
00C702 1 E0 00 cpx #$00 ; Apple Autostart ROM
00C704 1 E0 03 cpx #$03 ;
00C706 1
00C706 1 A2 70 ldx #SLOT*$10
00C708 1 86 2B stx $2b
00C70A 1 86 43 stx Unit
00C70C 1
00C70C 1 ;force EPROM to second page on boot
00C70C 1 A9 3F lda #$3f ;set all flags high and page 3 of EPROM for menu
00C70E 1 PageJump:
00C70E 1 8D F7 C0 sta OutputFlags
00C711 1 4C 19 C7 jmp Start ;this jump is only called if coming in from PageJump with A=$2f
00C714 1
00C714 1 ;entry points for ProDOS
00C714 1 DriverEntry:
00C714 1 A9 0F lda #$0f ;set all flags high and page 0 of EPROM
00C716 1 8D F7 C0 sta OutputFlags
00C719 1
00C719 1 Start:
00C719 1 20 00 C3 jsr $c300 ;enable 80 columns
00C71C 1 A9 05 lda #$05 ;execute command
00C71E 1 20 95 C7 jsr SendByte
00C721 1 A0 00 ldy #$00
00C723 1 sendHelp:
00C723 1 B9 8E C7 lda HelpCommand,y
00C726 1 F0 06 beq endSendHelp
00C728 1 20 95 C7 jsr SendByte
00C72B 1 C8 iny
00C72C 1 D0 F5 bne sendHelp
00C72E 1 endSendHelp:
00C72E 1 A9 00 lda #$00
00C730 1 20 95 C7 jsr SendByte
00C733 1 20 6B C7 jsr DumpOutput
00C736 1
00C736 1 A5 33 lda $33
00C738 1 48 pha
00C739 1 A9 A4 lda #$a4
00C73B 1 85 33 sta $33
00C73D 1 GetCommand:
00C73D 1 20 67 FD jsr InputString
00C740 1 AD 00 02 lda $0200
00C743 1 C9 8D cmp #$8d ;skip when return found
00C745 1 F0 F6 beq GetCommand
00C747 1 20 4D C7 jsr SendCommand
00C74A 1 18 clc
00C74B 1 90 F0 bcc GetCommand
00C74D 1
00C74D 1 SendCommand:
00C74D 1 2C 10 C0 bit ClearKeyboard
00C750 1 A9 05 lda #$05 ;send command 5 = exec
00C752 1 20 95 C7 jsr SendByte
00C755 1 A0 00 ldy #$00
00C757 1 getInput:
00C757 1 B9 00 02 lda $0200,y
00C75A 1 C9 8D cmp #$8d
00C75C 1 F0 08 beq sendNullTerminator
00C75E 1 29 7F and #$7f
00C760 1 20 95 C7 jsr SendByte
00C763 1 C8 iny
00C764 1 D0 F1 bne getInput
00C766 1 sendNullTerminator:
00C766 1 A9 00 lda #$00
00C768 1 20 95 C7 jsr SendByte
00C76B 1 DumpOutput:
00C76B 1 20 B3 C7 jsr GetByte
00C76E 1 B0 07 bcs skipOutput
00C770 1 C9 00 cmp #$00
00C772 1 F0 19 beq endOutput
00C774 1 20 ED FD jsr PrintChar
00C777 1 skipOutput:
00C777 1 2C 00 C0 bit Keyboard ;check for keypress
00C77A 1 10 EF bpl DumpOutput ;keep dumping output if no keypress
00C77C 1 AD 00 C0 lda Keyboard ;send keypress to RPi
00C77F 1 20 ED FD jsr PrintChar
00C782 1 29 7F and #$7f
00C784 1 20 95 C7 jsr SendByte
00C787 1 2C 10 C0 bit ClearKeyboard
00C78A 1 18 clc
00C78B 1 90 DE bcc DumpOutput
00C78D 1 endOutput:
00C78D 1 60 rts
00C78E 1
00C78E 1 HelpCommand:
00C78E 1 61 32 68 65 .byte "a2help",$00
00C792 1 6C 70 00
00C795 1
00C795 1 SendByte:
00C795 1 48 pha
00C796 1 waitWrite:
00C796 1 AD FB C0 lda InputFlags
00C799 1 2A rol
00C79A 1 2A rol
00C79B 1 B0 F9 bcs waitWrite
00C79D 1 68 pla
00C79E 1 8D FD C0 sta OutputByte
00C7A1 1 A9 1E lda #$1e ; set bit 0 low to indicate write started
00C7A3 1 8D F7 C0 sta OutputFlags
00C7A6 1 finishWrite:
00C7A6 1 AD FB C0 lda InputFlags
00C7A9 1 2A rol
00C7AA 1 2A rol
00C7AB 1 90 F9 bcc finishWrite
00C7AD 1 A9 1F lda #$1f
00C7AF 1 8D F7 C0 sta OutputFlags
00C7B2 1 60 rts
00C7B3 1
00C7B3 1 GetByte:
00C7B3 1 A9 1D lda #$1d ;set read flag low
00C7B5 1 8D F7 C0 sta OutputFlags
00C7B8 1 waitRead:
00C7B8 1 AD FB C0 lda InputFlags
00C7BB 1 2A rol
00C7BC 1 90 0C bcc readByte
00C7BE 1 2C 00 C0 bit Keyboard ;keypress will abort waiting to read
00C7C1 1 10 F5 bpl waitRead
00C7C3 1 A9 1F lda #$1f ;set all flags high and exit
00C7C5 1 8D F7 C0 sta OutputFlags
00C7C8 1 38 sec ;failure
00C7C9 1 60 rts
00C7CA 1 readByte:
00C7CA 1 AD FE C0 lda InputByte
00C7CD 1 48 pha
00C7CE 1 A9 1F lda #$1f ;set all flags high
00C7D0 1 8D F7 C0 sta OutputFlags
00C7D3 1 finishRead:
00C7D3 1 AD FB C0 lda InputFlags
00C7D6 1 2A rol
00C7D7 1 90 FA bcc finishRead
00C7D9 1 68 pla
00C7DA 1 18 clc ;success
00C7DB 1 end:
00C7DB 1 60 rts
00C7DC 1
00C7DC 1 00 00 00 00 .repeat 251-<end
00C7E0 1 00 00 00 00
00C7E4 1 00 00 00 00
00C7E8 1 00 00 00 00
00C7EC 1 00 00 00 00
00C7F0 1 00 00 00 00
00C7F4 1 00 00 00 00
00C7F8 1 00 00 00 00
00C7FC 1 .byte 0
00C7FC 1 .endrepeat
00C7FC 1
00C7FC 1 00 00 .byte 0,0 ;0000 blocks = check status
00C7FE 1 07 .byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
00C7FF 1 14 .byte DriverEntry&$00FF ;low byte of entry
00C7FF 1

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.
@ -36,16 +36,27 @@ MenuCommand = $08
.org SLOT*$100 + $C000
;ID bytes for booting and drive detection
cpx #$20 ;ID bytes for ProDOS and the
cpx #$00 ; Apple Autostart ROM
cpx #$20 ;ID bytes for ProDOS
cpx #$00 ;
cpx #$03 ;
cpx #$3C ;ID byte for Autostart ROM
ldx #SLOT*$10
stx $2b
stx Unit
;force EPROM to second page on boot
lda #$3f ;set all flags high and page 3 of EPROM for menu
jmp PageJump
;The following bytes must exist in this location for Pascal communications
;as they are standard pointers for entry points
.byte CommInit&$00FF ;low byte of rts for init of Pascal comms
.byte CommRead&$00FF ; low byte of read for Pascal comms
.byte CommWrite&$00FF ; low byte of write for Pascal comms
.byte CommStatus&$00FF ; low byte of rts for status of Pascal comms
CommInit:
lda #$0f ; set all flags high and page 0 for comm driver
sta OutputFlags
ldx #$00 ; set error code to 0 for success
rts
PageJump:
sta OutputFlags
jmp Start ;this jump is only called if coming in from PageJump with A=$0f
@ -58,6 +69,10 @@ DriverEntry:
;load first two blocks and execute to boot
Start:
ldx #SLOT*$10
stx $2b
stx Unit
lda #$01 ;set read command
sta Command
@ -71,6 +86,21 @@ Start:
jmp $801 ;execute the block
CommRead:
jsr GetByte
ldx #$00 ; clear error code
rts
CommWrite:
jsr SendByte
ldx #$00 ; clear error code
rts
CommStatus:
ldx #$00 ; clear error code
sec ; set carry to indicate ready to read or write
rts
; ProDOS Driver code
; First check that this is the right drive
Driver:
@ -78,7 +108,7 @@ Driver:
lda Command; Check which command is being requested
beq GetStatus ;0 = Status command
cmp #ReadBlockCommand
beq ReadBlockAndSetTime
beq ReadBlock
cmp #WriteBlockCommand
beq WriteBlock
sec ;set carry as we don't support any other commands
@ -94,22 +124,7 @@ GetStatus:
rts
; ProDOS Read Block Command
ReadBlockAndSetTime:
lda BlockHi ; only get the time if block 0002
bne readBlock
lda BlockLo
cmp #$02
bne readBlock
ldy #$00 ;Get the current time on each block read for now
lda #GetTimeCommand
jsr SendByte
getTimeByte:
jsr GetByte
sta $bf90,y
iny
cpy #$04
bne getTimeByte
readBlock:
ReadBlock:
lda #ReadBlockCommand ;read the block after setting the clock
jsr SendByte
lda BlockLo
@ -161,41 +176,38 @@ write256:
rts
SendByte:
pha
waitWrite:
lda InputFlags
rol
rol
bcs waitWrite
pla
bit InputFlags
bvs SendByte
sta OutputByte
.if HW_TYPE = 0
lda #$0e ; set bit 0 low to indicate write started
sta OutputFlags
finishWrite:
lda InputFlags
rol
rol
bcc finishWrite
bit InputFlags
bvc finishWrite
lda #$0f
sta OutputFlags
.endif
rts
GetByte:
.if HW_TYPE = 0
lda #$0d ;set read flag low
sta OutputFlags
.endif
waitRead:
lda InputFlags
rol
bcs waitRead
bit InputFlags
bmi waitRead
lda InputByte
.if HW_TYPE = 0
pha
lda #$0f ;set all flags high
sta OutputFlags
finishRead:
lda InputFlags
rol
bcc finishRead
bit InputFlags
bpl finishRead
pla
.endif
end:
rts

View File

@ -1,214 +0,0 @@
ca65 V2.18 - N/A
Main file : DriveFirmware.asm
Current file: DriveFirmware.asm
000000r 1 ; Copyright Terence J. Boldt (c)2020-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the firmware
000000r 1 ; that allows the Apple II to boot from the card
000000r 1 ; and for ProDOS to recognize the card as two
000000r 1 ; hard drivers
000000r 1
000000r 1 ;ProDOS Zero Page
000000r 1 Command = $42 ;ProDOS Command
000000r 1 Unit = $43 ;ProDOS unit (SDDD0000)
000000r 1 BufferLo = $44
000000r 1 BufferHi = $45
000000r 1 BlockLo = $46
000000r 1 BlockHi = $47
000000r 1
000000r 1 ; ProDOS Error Codes
000000r 1 IOError = $27
000000r 1 NoDevice = $28
000000r 1 WriteProtect = $2B
000000r 1
000000r 1 InputByte = $c08e+SLOT*$10
000000r 1 OutputByte = $c08d+SLOT*$10
000000r 1 InputFlags = $c08b+SLOT*$10
000000r 1 OutputFlags = $c087+SLOT*$10
000000r 1
000000r 1 ReadBlockCommand = $01
000000r 1 WriteBlockCommand = $02
000000r 1 GetTimeCommand = $03
000000r 1 ChangeDriveCommand = $04
000000r 1 ExecCommand = $05
000000r 1 LoadFileCommand = $06
000000r 1 SaveFileCommand = $07
000000r 1 MenuCommand = $08
000000r 1
000000r 1 .org SLOT*$100 + $C000
00C700 1 ;ID bytes for booting and drive detection
00C700 1 E0 20 cpx #$20 ;ID bytes for ProDOS and the
00C702 1 E0 00 cpx #$00 ; Apple Autostart ROM
00C704 1 E0 03 cpx #$03 ;
00C706 1
00C706 1 A2 70 ldx #SLOT*$10
00C708 1 86 2B stx $2b
00C70A 1 86 43 stx Unit
00C70C 1
00C70C 1 ;force EPROM to second page on boot
00C70C 1 A9 3F lda #$3f ;set all flags high and page 3 of EPROM for menu
00C70E 1 PageJump:
00C70E 1 8D F7 C0 sta OutputFlags
00C711 1 4C 1C C7 jmp Start ;this jump is only called if coming in from PageJump with A=$0f
00C714 1
00C714 1 ;entry points for ProDOS
00C714 1 DriverEntry:
00C714 1 A9 0F lda #$0f ;set all flags high and page 0 of EPROM
00C716 1 8D F7 C0 sta OutputFlags
00C719 1 4C 32 C7 jmp Driver
00C71C 1
00C71C 1 ;load first two blocks and execute to boot
00C71C 1 Start:
00C71C 1 A9 01 lda #$01 ;set read command
00C71E 1 85 42 sta Command
00C720 1
00C720 1 A9 00 lda #$00 ;block 0
00C722 1 85 46 sta BlockLo
00C724 1 85 47 sta BlockHi
00C726 1 85 44 sta BufferLo ;buffer at $800
00C728 1 A9 08 lda #$08
00C72A 1 85 45 sta BufferHi
00C72C 1 20 32 C7 jsr Driver ;get the block
00C72F 1
00C72F 1 4C 01 08 jmp $801 ;execute the block
00C732 1
00C732 1 ; ProDOS Driver code
00C732 1 ; First check that this is the right drive
00C732 1 Driver:
00C732 1 A6 43 ldx Unit
00C734 1 A5 42 lda Command; Check which command is being requested
00C736 1 F0 0C beq GetStatus ;0 = Status command
00C738 1 C9 01 cmp #ReadBlockCommand
00C73A 1 F0 10 beq ReadBlockAndSetTime
00C73C 1 C9 02 cmp #WriteBlockCommand
00C73E 1 F0 54 beq WriteBlock
00C740 1 38 sec ;set carry as we don't support any other commands
00C741 1 A9 53 lda #$53 ;Invalid parameter error
00C743 1 60 rts
00C744 1
00C744 1 ; ProDOS Status Command Handler
00C744 1 GetStatus:
00C744 1 A2 FF ldx #$ff ;low byte number of blocks
00C746 1 A0 FF ldy #$ff ;high byte number of blocks
00C748 1 A9 00 lda #$0 ;zero accumulator and clear carry for success
00C74A 1 18 clc
00C74B 1 60 rts
00C74C 1
00C74C 1 ; ProDOS Read Block Command
00C74C 1 ReadBlockAndSetTime:
00C74C 1 A5 47 lda BlockHi ; only get the time if block 0002
00C74E 1 D0 18 bne readBlock
00C750 1 A5 46 lda BlockLo
00C752 1 C9 02 cmp #$02
00C754 1 D0 12 bne readBlock
00C756 1 A0 00 ldy #$00 ;Get the current time on each block read for now
00C758 1 A9 03 lda #GetTimeCommand
00C75A 1 20 C0 C7 jsr SendByte
00C75D 1 getTimeByte:
00C75D 1 20 DE C7 jsr GetByte
00C760 1 99 90 BF sta $bf90,y
00C763 1 C8 iny
00C764 1 C0 04 cpy #$04
00C766 1 D0 F5 bne getTimeByte
00C768 1 readBlock:
00C768 1 A9 01 lda #ReadBlockCommand ;read the block after setting the clock
00C76A 1 20 C0 C7 jsr SendByte
00C76D 1 A5 46 lda BlockLo
00C76F 1 20 C0 C7 jsr SendByte
00C772 1 A5 47 lda BlockHi
00C774 1 20 C0 C7 jsr SendByte
00C777 1 8A txa
00C778 1 20 C0 C7 jsr SendByte
00C77B 1 A0 00 ldy #$0
00C77D 1 20 8B C7 jsr read256
00C780 1 E6 45 inc BufferHi
00C782 1 20 8B C7 jsr read256
00C785 1 C6 45 dec BufferHi
00C787 1 A9 00 lda #$0 ;zero accumulator and clear carry for success
00C789 1 18 clc
00C78A 1 60 rts
00C78B 1
00C78B 1 read256:
00C78B 1 20 DE C7 jsr GetByte
00C78E 1 91 44 sta (BufferLo),y
00C790 1 C8 iny
00C791 1 D0 F8 bne read256
00C793 1 60 rts
00C794 1
00C794 1 ; ProDOS Write Block Command
00C794 1 WriteBlock:
00C794 1 A9 02 lda #WriteBlockCommand
00C796 1 20 C0 C7 jsr SendByte
00C799 1 A5 46 lda BlockLo
00C79B 1 20 C0 C7 jsr SendByte
00C79E 1 A5 47 lda BlockHi
00C7A0 1 20 C0 C7 jsr SendByte
00C7A3 1 8A txa
00C7A4 1 20 C0 C7 jsr SendByte
00C7A7 1 A0 00 ldy #$0
00C7A9 1 20 B7 C7 jsr write256
00C7AC 1 E6 45 inc BufferHi
00C7AE 1 20 B7 C7 jsr write256
00C7B1 1 C6 45 dec BufferHi
00C7B3 1 A9 00 lda #$0 ;zero accumulator and clear carry for success
00C7B5 1 18 clc
00C7B6 1 60 rts
00C7B7 1
00C7B7 1 write256:
00C7B7 1 B1 44 lda (BufferLo),y
00C7B9 1 20 C0 C7 jsr SendByte
00C7BC 1 C8 iny
00C7BD 1 D0 F8 bne write256
00C7BF 1 60 rts
00C7C0 1
00C7C0 1 SendByte:
00C7C0 1 48 pha
00C7C1 1 waitWrite:
00C7C1 1 AD FB C0 lda InputFlags
00C7C4 1 2A rol
00C7C5 1 2A rol
00C7C6 1 B0 F9 bcs waitWrite
00C7C8 1 68 pla
00C7C9 1 8D FD C0 sta OutputByte
00C7CC 1 A9 0E lda #$0e ; set bit 0 low to indicate write started
00C7CE 1 8D F7 C0 sta OutputFlags
00C7D1 1 finishWrite:
00C7D1 1 AD FB C0 lda InputFlags
00C7D4 1 2A rol
00C7D5 1 2A rol
00C7D6 1 90 F9 bcc finishWrite
00C7D8 1 A9 0F lda #$0f
00C7DA 1 8D F7 C0 sta OutputFlags
00C7DD 1 60 rts
00C7DE 1
00C7DE 1 GetByte:
00C7DE 1 A9 0D lda #$0d ;set read flag low
00C7E0 1 8D F7 C0 sta OutputFlags
00C7E3 1 waitRead:
00C7E3 1 AD FB C0 lda InputFlags
00C7E6 1 2A rol
00C7E7 1 B0 FA bcs waitRead
00C7E9 1 AD FE C0 lda InputByte
00C7EC 1 48 pha
00C7ED 1 A9 0F lda #$0f ;set all flags high
00C7EF 1 8D F7 C0 sta OutputFlags
00C7F2 1 finishRead:
00C7F2 1 AD FB C0 lda InputFlags
00C7F5 1 2A rol
00C7F6 1 90 FA bcc finishRead
00C7F8 1 68 pla
00C7F9 1 end:
00C7F9 1 60 rts
00C7FA 1
00C7FA 1 00 00 .repeat 251-<end
00C7FC 1 .byte 0
00C7FC 1 .endrepeat
00C7FC 1
00C7FC 1 00 00 .byte 0,0 ;0000 blocks = check status
00C7FE 1 17 .byte 23 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
00C7FF 1 14 .byte DriverEntry&$00FF ;low byte of entry
00C800 1
00C800 1

View File

@ -1,10 +1,10 @@
; 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.
; This file contains the source for the firmware
; that was formerly used to copy files from RPi
; to Apple II RAM
; This file formerly contained the source for the
; firmware that had a file access
; but is now empty except required common bytes
;ProDOS Zero Page
Command = $42 ;ProDOS Command
@ -33,122 +33,41 @@ LoadFileCommand = $06
SaveFileCommand = $07
MenuCommand = $08
InputString = $fd67
Monitor = $ff59
.org SLOT*$100 + $C000
;ID bytes for booting and drive detection
cpx #$20 ;ID bytes for ProDOS and the
cpx #$00 ; Apple Autostart ROM
cpx #$20 ;ID bytes for ProDOS
cpx #$00 ;
cpx #$03 ;
cpx #$3C ;ID byte for Autostart ROM
ldx #SLOT*$10
stx $2b
stx Unit
;force EPROM to second page on boot
lda #$3f ;set all flags high and page 3 of EPROM for menu
jmp PageJump
;The following bytes must exist in this location for Pascal communications
;as they are standard pointers for entry points
.byte CommInit&$00FF ;low byte of rts for init of Pascal comms
.byte $43 ; low byte of read for Pascal comms
.byte $49 ; low byte of write for Pascal comms
.byte $4F ; low byte of rts for status of Pascal comms
CommInit:
lda #$0f ; set all flags high and page 0 for comm driver
sta OutputFlags
ldx #$00 ; set error code to 0 for success
rts
PageJump:
sta OutputFlags
jmp Start ;this jump is only called if coming in from PageJump with A=$2f
jmp Start ;this jump is only called if coming in from PageJump with A=$0f
;entry points for ProDOS
DriverEntry:
lda #$0f ;set all flags high and page 0 of EPROM
sta OutputFlags
jmp Start ; this is never called as the EPROM page changes
;load first two blocks and execute to boot
Start:
lda #$a4
sta $33
GetFilename:
jsr InputString
LoadFile:
lda #$00
sta BufferLo
lda #$20
sta BufferHi
lda #$06 ; send command 6 = load
jsr SendByte
ldy #$00
sendFilename:
lda $0200,y
cmp #$8d
beq sendNullTerminator
and #$7f
jsr SendByte
iny
bne sendFilename
sendNullTerminator:
lda #$00
jsr SendByte
jsr GetByte
sta BlockLo ; not really a block, just using the memory space
jsr GetByte
sta BlockHi
NextPage:
lda BlockHi
beq ReadFinalPage
ldy #$00
NextByte:
jsr GetByte
sta (BufferLo),y
iny
bne NextByte
inc BufferHi
dec BlockHi
bne NextPage
ReadFinalPage:
lda BlockLo
beq ExitToMonitor
ldy #$00
NextByteFinal:
jsr GetByte
sta (BufferLo),y
iny
cpy BlockLo
bne NextByteFinal
ExitToMonitor:
jsr Monitor
SendByte:
pha
waitWrite:
lda InputFlags
rol
rol
bcs waitWrite
pla
sta OutputByte
lda #$2e ; set bit 0 low to indicate write started
sta OutputFlags
finishWrite:
lda InputFlags
rol
rol
bcc finishWrite
lda #$2f
sta OutputFlags
rts
GetByte:
lda #$2d ;set read flag low
sta OutputFlags
waitRead:
lda InputFlags
rol
bcs waitRead
lda InputByte
pha
lda #$2f ;set all flags high
sta OutputFlags
finishRead:
lda InputFlags
rol
bcc finishRead
pla
end:
rts
@ -157,6 +76,6 @@ end:
.endrepeat
.byte 0,0 ;0000 blocks = check status
.byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
.byte 23 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
.byte DriverEntry&$00FF ;low byte of entry

View File

@ -1,186 +0,0 @@
ca65 V2.18 - N/A
Main file : FileAccessFirmware.asm
Current file: FileAccessFirmware.asm
000000r 1 ; Copyright Terence J. Boldt (c)2020-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the firmware
000000r 1 ; that was formerly used to copy files from RPi
000000r 1 ; to Apple II RAM
000000r 1
000000r 1 ;ProDOS Zero Page
000000r 1 Command = $42 ;ProDOS Command
000000r 1 Unit = $43 ;ProDOS unit (SDDD0000)
000000r 1 BufferLo = $44
000000r 1 BufferHi = $45
000000r 1 BlockLo = $46
000000r 1 BlockHi = $47
000000r 1
000000r 1 ; ProDOS Error Codes
000000r 1 IOError = $27
000000r 1 NoDevice = $28
000000r 1 WriteProtect = $2B
000000r 1
000000r 1 InputByte = $c08e+SLOT*$10
000000r 1 OutputByte = $c08d+SLOT*$10
000000r 1 InputFlags = $c08b+SLOT*$10
000000r 1 OutputFlags = $c087+SLOT*$10
000000r 1
000000r 1 ReadBlockCommand = $01
000000r 1 WriteBlockCommand = $02
000000r 1 GetTimeCommand = $03
000000r 1 ChangeDriveCommand = $04
000000r 1 ExecCommand = $05
000000r 1 LoadFileCommand = $06
000000r 1 SaveFileCommand = $07
000000r 1 MenuCommand = $08
000000r 1
000000r 1 InputString = $fd67
000000r 1 Monitor = $ff59
000000r 1
000000r 1 .org SLOT*$100 + $C000
00C700 1 ;ID bytes for booting and drive detection
00C700 1 E0 20 cpx #$20 ;ID bytes for ProDOS and the
00C702 1 E0 00 cpx #$00 ; Apple Autostart ROM
00C704 1 E0 03 cpx #$03 ;
00C706 1
00C706 1 A2 70 ldx #SLOT*$10
00C708 1 86 2B stx $2b
00C70A 1 86 43 stx Unit
00C70C 1
00C70C 1 ;force EPROM to second page on boot
00C70C 1 A9 3F lda #$3f ;set all flags high and page 3 of EPROM for menu
00C70E 1 PageJump:
00C70E 1 8D F7 C0 sta OutputFlags
00C711 1 4C 19 C7 jmp Start ;this jump is only called if coming in from PageJump with A=$2f
00C714 1
00C714 1 ;entry points for ProDOS
00C714 1 DriverEntry:
00C714 1 A9 0F lda #$0f ;set all flags high and page 0 of EPROM
00C716 1 8D F7 C0 sta OutputFlags
00C719 1
00C719 1 Start:
00C719 1 A9 A4 lda #$a4
00C71B 1 85 33 sta $33
00C71D 1
00C71D 1 GetFilename:
00C71D 1 20 67 FD jsr InputString
00C720 1
00C720 1 LoadFile:
00C720 1 A9 00 lda #$00
00C722 1 85 44 sta BufferLo
00C724 1 A9 20 lda #$20
00C726 1 85 45 sta BufferHi
00C728 1 A9 06 lda #$06 ; send command 6 = load
00C72A 1 20 74 C7 jsr SendByte
00C72D 1 A0 00 ldy #$00
00C72F 1 sendFilename:
00C72F 1 B9 00 02 lda $0200,y
00C732 1 C9 8D cmp #$8d
00C734 1 F0 08 beq sendNullTerminator
00C736 1 29 7F and #$7f
00C738 1 20 74 C7 jsr SendByte
00C73B 1 C8 iny
00C73C 1 D0 F1 bne sendFilename
00C73E 1 sendNullTerminator:
00C73E 1 A9 00 lda #$00
00C740 1 20 74 C7 jsr SendByte
00C743 1
00C743 1 20 92 C7 jsr GetByte
00C746 1 85 46 sta BlockLo ; not really a block, just using the memory space
00C748 1 20 92 C7 jsr GetByte
00C74B 1 85 47 sta BlockHi
00C74D 1 NextPage:
00C74D 1 A5 47 lda BlockHi
00C74F 1 F0 10 beq ReadFinalPage
00C751 1 A0 00 ldy #$00
00C753 1 NextByte:
00C753 1 20 92 C7 jsr GetByte
00C756 1 91 44 sta (BufferLo),y
00C758 1 C8 iny
00C759 1 D0 F8 bne NextByte
00C75B 1 E6 45 inc BufferHi
00C75D 1 C6 47 dec BlockHi
00C75F 1 D0 EC bne NextPage
00C761 1 ReadFinalPage:
00C761 1 A5 46 lda BlockLo
00C763 1 F0 0C beq ExitToMonitor
00C765 1 A0 00 ldy #$00
00C767 1 NextByteFinal:
00C767 1 20 92 C7 jsr GetByte
00C76A 1 91 44 sta (BufferLo),y
00C76C 1 C8 iny
00C76D 1 C4 46 cpy BlockLo
00C76F 1 D0 F6 bne NextByteFinal
00C771 1 ExitToMonitor:
00C771 1 20 59 FF jsr Monitor
00C774 1
00C774 1 SendByte:
00C774 1 48 pha
00C775 1 waitWrite:
00C775 1 AD FB C0 lda InputFlags
00C778 1 2A rol
00C779 1 2A rol
00C77A 1 B0 F9 bcs waitWrite
00C77C 1 68 pla
00C77D 1 8D FD C0 sta OutputByte
00C780 1 A9 2E lda #$2e ; set bit 0 low to indicate write started
00C782 1 8D F7 C0 sta OutputFlags
00C785 1 finishWrite:
00C785 1 AD FB C0 lda InputFlags
00C788 1 2A rol
00C789 1 2A rol
00C78A 1 90 F9 bcc finishWrite
00C78C 1 A9 2F lda #$2f
00C78E 1 8D F7 C0 sta OutputFlags
00C791 1 60 rts
00C792 1
00C792 1 GetByte:
00C792 1 A9 2D lda #$2d ;set read flag low
00C794 1 8D F7 C0 sta OutputFlags
00C797 1 waitRead:
00C797 1 AD FB C0 lda InputFlags
00C79A 1 2A rol
00C79B 1 B0 FA bcs waitRead
00C79D 1 AD FE C0 lda InputByte
00C7A0 1 48 pha
00C7A1 1 A9 2F lda #$2f ;set all flags high
00C7A3 1 8D F7 C0 sta OutputFlags
00C7A6 1 finishRead:
00C7A6 1 AD FB C0 lda InputFlags
00C7A9 1 2A rol
00C7AA 1 90 FA bcc finishRead
00C7AC 1 68 pla
00C7AD 1 end:
00C7AD 1 60 rts
00C7AE 1
00C7AE 1 00 00 00 00 .repeat 251-<end
00C7B2 1 00 00 00 00
00C7B6 1 00 00 00 00
00C7BA 1 00 00 00 00
00C7BE 1 00 00 00 00
00C7C2 1 00 00 00 00
00C7C6 1 00 00 00 00
00C7CA 1 00 00 00 00
00C7CE 1 00 00 00 00
00C7D2 1 00 00 00 00
00C7D6 1 00 00 00 00
00C7DA 1 00 00 00 00
00C7DE 1 00 00 00 00
00C7E2 1 00 00 00 00
00C7E6 1 00 00 00 00
00C7EA 1 00 00 00 00
00C7EE 1 00 00 00 00
00C7F2 1 00 00 00 00
00C7F6 1 00 00 00 00
00C7FA 1 00 00
00C7FC 1 .byte 0
00C7FC 1 .endrepeat
00C7FC 1
00C7FC 1 00 00 .byte 0,0 ;0000 blocks = check status
00C7FE 1 07 .byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
00C7FF 1 14 .byte DriverEntry&$00FF ;low byte of entry
00C800 1
00C800 1

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.
@ -45,21 +45,32 @@ vtab = $25
BasL = $28
htab80 = $057b
.org SLOT*$100 + $C000
.org SLOT*$100 + $C000
;ID bytes for booting and drive detection
cpx #$20 ;ID bytes for ProDOS and the
cpx #$00 ; Apple Autostart ROM
cpx #$20 ;ID bytes for ProDOS
cpx #$00 ;
cpx #$03 ;
cpx #$3C ;ID byte for Autostart ROM
ldx #SLOT*$10
stx $2b
stx Unit
lda #$3f ;set all flags high and page 3 of EPROM for menu
jmp PageJump
;The following bytes must exist in this location for Pascal communications
;as they are standard pointers for entry points
.byte CommInit&$00FF ;low byte of rts for init of Pascal comms
.byte $43 ; low byte of read for Pascal comms
.byte $49 ; low byte of write for Pascal comms
.byte $4F ; low byte of rts for status of Pascal comms
CommInit:
lda #$0f ; set all flags high and page 0 for comm driver
sta OutputFlags
ldx #$00 ; set error code to 0 for success
rts
;force EPROM to second page on boot
lda #$3f ;set all flags high and page 1 of EPROMi
PageJump:
sta OutputFlags
jmp Start
jmp Start ;this jump is only called if coming in from PageJump with A=$0f
;entry points for ProDOS
DriverEntry:
@ -73,10 +84,11 @@ Start:
lda #$fd
sta $37
;jsr Home ;clear screen and show menu options
lda #$10
lda #$02
sta vtab
jsr BasCalc
ldy #$00
sty htab
PrintString:
lda Text,y
beq WaitForRPi
@ -85,10 +97,11 @@ PrintString:
iny
bne PrintString
.if HW_TYPE = 0
WaitForRPi:
lda InputFlags
rol
bcs Reset
bit InputFlags
bmi Reset
lda #$ff
jsr Wait
lda #'.'+$80
@ -108,6 +121,37 @@ Reset:
beq Ok
jmp Reset
.else
WaitForRPi:
@1:
bit InputFlags
bmi @2
lda InputByte
jmp @1
@2:
bit InputFlags
bpl @4
bvs @3
lda #ResetCommand
sta OutputByte
@3:
lda #$ff
jsr Wait
lda #'.'+$80
jsr PrintChar
jmp @2
@4:
lda #$ff
jsr Wait
@5:
bit InputFlags
bmi Ok
lda InputByte
jmp @5
.endif
Ok:
lda #$8D
jsr PrintChar
@ -121,52 +165,54 @@ Boot:
jmp PageJump
SendByte:
pha
waitWrite:
lda InputFlags
rol
rol
bcs waitWrite
pla
bit InputFlags
bvs SendByte
sta OutputByte
.if HW_TYPE = 0
lda #$3e ; set bit 0 low to indicate write started
sta OutputFlags
finishWrite:
lda InputFlags
rol
rol
bcc finishWrite
bit InputFlags
bvc finishWrite
lda #$3f
sta OutputFlags
.endif
rts
GetByte:
lda #$3d ;set read flag low
sta OutputFlags
.if HW_TYPE = 0
ldx #$3d ;set read flag low
stx OutputFlags
.endif
waitRead:
lda InputFlags
rol
bcs waitRead
bit InputFlags
bmi waitRead
lda InputByte
pha
lda #$3f ;set all flags high
sta OutputFlags
.if HW_TYPE = 0
ldx #$3f ;set all flags high
stx OutputFlags
finishRead:
lda InputFlags
rol
bcc finishRead
pla
end:
bit InputFlags
bpl finishRead
.endif
rts
; NOTE: The text below exactly fills the remaining 256 bytes of firmware
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...",$00
.if HW_TYPE = 0
.byte "Waiting for RPi FW:0011"
.else
.byte "Waiting for RPi FW:8011"
.endif
end:
.byte $00
.repeat 251-<end
.byte 0
.endrepeat
.byte 0,0 ;0000 blocks = check status
.byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
.byte DriverEntry&$00FF ;low byte of entry

View File

@ -1,193 +0,0 @@
ca65 V2.18 - N/A
Main file : MenuFirmware.asm
Current file: MenuFirmware.asm
000000r 1 ; Copyright Terence J. Boldt (c)2020-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the firmware
000000r 1 ; that displays the copyright message on boot
000000r 1 ; and checks for the RPi status to be ready before
000000r 1 ; attempting to boot
000000r 1
000000r 1 ;ProDOS Zero Page
000000r 1 Command = $42 ;ProDOS Command
000000r 1 Unit = $43 ;ProDOS unit (SDDD0000)
000000r 1 BufferLo = $44
000000r 1 BufferHi = $45
000000r 1 BlockLo = $46
000000r 1 BlockHi = $47
000000r 1
000000r 1 ; ProDOS Error Codes
000000r 1 IOError = $27
000000r 1 NoDevice = $28
000000r 1 WriteProtect = $2B
000000r 1
000000r 1 InputByte = $c08e+SLOT*$10
000000r 1 OutputByte = $c08d+SLOT*$10
000000r 1 InputFlags = $c08b+SLOT*$10
000000r 1 OutputFlags = $c087+SLOT*$10
000000r 1
000000r 1 ResetCommand = $00
000000r 1 ReadBlockCommand = $01
000000r 1 WriteBlockCommand = $02
000000r 1 GetTimeCommand = $03
000000r 1 ChangeDriveCommand = $04
000000r 1 ExecCommand = $05
000000r 1 LoadFileCommand = $06
000000r 1 SaveFileCommand = $07
000000r 1 MenuCommand = $08
000000r 1
000000r 1 Wait = $fca8
000000r 1 PrintChar = $fded
000000r 1 Home = $fc58
000000r 1 ReadChar = $fd0c
000000r 1 BasCalc = $fbc1
000000r 1 htab = $24
000000r 1 vtab = $25
000000r 1 BasL = $28
000000r 1 htab80 = $057b
000000r 1
000000r 1 .org SLOT*$100 + $C000
00C700 1 ;ID bytes for booting and drive detection
00C700 1 E0 20 cpx #$20 ;ID bytes for ProDOS and the
00C702 1 E0 00 cpx #$00 ; Apple Autostart ROM
00C704 1 E0 03 cpx #$03 ;
00C706 1
00C706 1 A2 70 ldx #SLOT*$10
00C708 1 86 2B stx $2b
00C70A 1 86 43 stx Unit
00C70C 1
00C70C 1 ;force EPROM to second page on boot
00C70C 1 A9 3F lda #$3f ;set all flags high and page 1 of EPROMi
00C70E 1 PageJump:
00C70E 1 8D F7 C0 sta OutputFlags
00C711 1 4C 19 C7 jmp Start
00C714 1
00C714 1 ;entry points for ProDOS
00C714 1 DriverEntry:
00C714 1 A9 0F lda #$0f ;set all flags high and page 0 of EPROM
00C716 1 8D F7 C0 sta OutputFlags
00C719 1 ;since the firmware page changes to 0, this falls through to the driver
00C719 1
00C719 1 Start:
00C719 1 A9 F0 lda #$f0 ;restore COUT after PR# called
00C71B 1 85 36 sta $36
00C71D 1 A9 FD lda #$fd
00C71F 1 85 37 sta $37
00C721 1 ;jsr Home ;clear screen and show menu options
00C721 1 A9 10 lda #$10
00C723 1 85 25 sta vtab
00C725 1 20 C1 FB jsr BasCalc
00C728 1 A0 00 ldy #$00
00C72A 1 PrintString:
00C72A 1 B9 B4 C7 lda Text,y
00C72D 1 F0 08 beq WaitForRPi
00C72F 1 09 80 ora #$80
00C731 1 20 ED FD jsr PrintChar
00C734 1 C8 iny
00C735 1 D0 F3 bne PrintString
00C737 1
00C737 1 WaitForRPi:
00C737 1 AD FB C0 lda InputFlags
00C73A 1 2A rol
00C73B 1 B0 0D bcs Reset
00C73D 1 A9 FF lda #$ff
00C73F 1 20 A8 FC jsr Wait
00C742 1 A9 AE lda #'.'+$80
00C744 1 20 ED FD jsr PrintChar
00C747 1 4C 37 C7 jmp WaitForRPi
00C74A 1
00C74A 1 Reset:
00C74A 1 A9 DF lda #'_'|$80
00C74C 1 20 ED FD jsr PrintChar
00C74F 1 A9 00 lda #ResetCommand
00C751 1 20 7A C7 jsr SendByte
00C754 1 A9 88 lda #$88
00C756 1 20 ED FD jsr PrintChar
00C759 1 A9 AE lda #'.'|$80
00C75B 1 20 ED FD jsr PrintChar
00C75E 1 20 98 C7 jsr GetByte
00C761 1 F0 03 beq Ok
00C763 1 4C 4A C7 jmp Reset
00C766 1
00C766 1 Ok:
00C766 1 A9 8D lda #$8D
00C768 1 20 ED FD jsr PrintChar
00C76B 1 A9 CF lda #'O'|$80
00C76D 1 20 ED FD jsr PrintChar
00C770 1 A9 CB lda #'K'|$80
00C772 1 20 ED FD jsr PrintChar
00C775 1
00C775 1 Boot:
00C775 1 A9 0F lda #$0f
00C777 1 4C 0E C7 jmp PageJump
00C77A 1
00C77A 1 SendByte:
00C77A 1 48 pha
00C77B 1 waitWrite:
00C77B 1 AD FB C0 lda InputFlags
00C77E 1 2A rol
00C77F 1 2A rol
00C780 1 B0 F9 bcs waitWrite
00C782 1 68 pla
00C783 1 8D FD C0 sta OutputByte
00C786 1 A9 3E lda #$3e ; set bit 0 low to indicate write started
00C788 1 8D F7 C0 sta OutputFlags
00C78B 1 finishWrite:
00C78B 1 AD FB C0 lda InputFlags
00C78E 1 2A rol
00C78F 1 2A rol
00C790 1 90 F9 bcc finishWrite
00C792 1 A9 3F lda #$3f
00C794 1 8D F7 C0 sta OutputFlags
00C797 1 60 rts
00C798 1
00C798 1 GetByte:
00C798 1 A9 3D lda #$3d ;set read flag low
00C79A 1 8D F7 C0 sta OutputFlags
00C79D 1 waitRead:
00C79D 1 AD FB C0 lda InputFlags
00C7A0 1 2A rol
00C7A1 1 B0 FA bcs waitRead
00C7A3 1 AD FE C0 lda InputByte
00C7A6 1 48 pha
00C7A7 1 A9 3F lda #$3f ;set all flags high
00C7A9 1 8D F7 C0 sta OutputFlags
00C7AC 1 finishRead:
00C7AC 1 AD FB C0 lda InputFlags
00C7AF 1 2A rol
00C7B0 1 90 FA bcc finishRead
00C7B2 1 68 pla
00C7B3 1 end:
00C7B3 1 60 rts
00C7B4 1
00C7B4 1 ; NOTE: The text below exactly fills the remaining 256 bytes of firmware
00C7B4 1 Text:
00C7B4 1 41 70 70 6C .byte "Apple2-IO-RPi",$8d
00C7B8 1 65 32 2D 49
00C7BC 1 4F 2D 52 50
00C7C0 1 69 8D
00C7C2 1 28 63 29 32 .byte "(c)2020-2022 Terence J. Boldt",$8d
00C7C6 1 30 32 30 2D
00C7CA 1 32 30 32 32
00C7CE 1 20 54 65 72
00C7D2 1 65 6E 63 65
00C7D6 1 20 4A 2E 20
00C7DA 1 42 6F 6C 64
00C7DE 1 74 8D
00C7E0 1 8D .byte $8d
00C7E1 1 57 61 69 74 .byte "Waiting for RPi FW:000F...",$00
00C7E5 1 69 6E 67 20
00C7E9 1 66 6F 72 20
00C7ED 1 52 50 69 20
00C7F1 1 46 57 3A 30
00C7F5 1 30 30 46 2E
00C7F9 1 2E 2E 00
00C7FC 1
00C7FC 1 00 00 .byte 0,0 ;0000 blocks = check status
00C7FE 1 07 .byte 7 ;bit set(0=status 1=read 2=write) unset(3=format, 4/5=number of volumes, 6=interruptable, 7=removable)
00C7FF 1 14 .byte DriverEntry&$00FF ;low byte of entry
00C800 1
00C800 1

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.
@ -33,6 +33,7 @@ MenuCommand = $08
InputString = $fd67
PrintChar = $fded
PrintHex = $fde3
Keyboard = $c000
ClearKeyboard = $c010
Wait = $fca8
@ -42,57 +43,80 @@ SlotL = $fe
SlotH = $ff
ESC = $9b
;macro for string with high-bit set
.macro aschi str
.repeat .strlen (str), c
.byte .strat (str, c) | $80
.endrep
.endmacro
.org $2000
ldx #$07 ; start at slot 7
DetectSlot:
; Find Apple2-IO-RPi card
ldx #$06
ldy #$09
CheckIdBytes:
lda $C700,y ; !! Self modifying code
cmp IdBytes,y
bne NextCard
dey
bne CheckIdBytes
jmp FoundCard
NextCard:
dec CheckIdBytes+2
ldy #$09
dex
bne CheckIdBytes
CardNotFound:
ldy #$00
lda #$fc
sta SlotL
PrintCardNotFound:
lda TextCardNotFound,y
beq Failed
jsr PrintChar
iny
bne PrintCardNotFound
Failed:
rts
FoundCard:
ldy #$00
PrintCardFound:
lda TextCardFound,y
beq PrintCardNumber
jsr PrintChar
iny
bne PrintCardFound
PrintCardNumber:
inx
txa
ora #$c0
sta SlotH
lda (SlotL),y
bne nextSlot
iny
lda (SlotL),y
bne nextSlot
iny
lda (SlotL),y
cmp #$17
bne nextSlot
iny
lda (SlotL),y
cmp #$14
bne nextSlot
jsr PrintHex
lda #$8D
jsr PrintChar
SetOffsetForCard:
txa
asl
asl
asl
asl
tax
clc
bcc Start
nextSlot:
dex
bne DetectSlot
rts
Start:
stx slotx + $1e01 ;set the slot for the driver
ldx #$00
copyDriver:
lda $2100,x
sta $0300,x
inx
cpx #$e6
bne copyDriver
end:
jmp $0300
.repeat 253-<end
.byte 0
.endrepeat
.org $0300
ldy #$00
PrintString:
lda Text,y
beq copyDriver
jsr PrintChar
iny
bne PrintString
copyDriver:
ldy #$00
copyDriverByte:
lda $2200,y
sta $0300,y
iny
cpy #$e6
bne copyDriverByte
;
; FIRST SAVE THE EXTERNAL COMMAND ADDRESS SO YOU WON'T
; DISCONNECT ANY PREVIOUSLY CONNECTED COMMAND.
@ -106,8 +130,58 @@ end:
STA EXTRNCMD+1 ; command handler in the
LDA #>RPI ; external command JMP
STA EXTRNCMD+2 ; vector.
RTS
;
lda #ExecCommand
jsr SendByte
ldy #$00
nextCommandByte:
lda a2help, y
beq finishCommand
jsr SendByte
iny
jmp nextCommandByte
finishCommand:
lda #$00
jsr SendByte
showVersion:
jsr GetByte
cmp #$00
beq FinishDriver
jsr PrintChar
jmp showVersion
FinishDriver:
rts
a2help:
.byte "a2help", $00
Text:
.if HW_TYPE = 0
aschi "RPI command version: 000F (classic)"
.else
aschi "RPI command version: 800F (pico)"
.endif
.byte $8d
.byte $00
IdBytes:
.byte $E0,$20,$E0,$00,$E0,$03,$E0,$3C,$A9,$3F
TextCardFound:
aschi "Found Apple2-IO-RPi in slot "
.byte $00
TextCardNotFound:
aschi "Apple2-IO-RPi not found"
.byte $8D
end:
.byte $00
.repeat 255-<end
.byte 0
.endrepeat
.org $0300
RPI: LDX #0 ;Check for our command.
NXTCHR: LDA INBUF,X ;Get first character.
ora #$20 ;Make it lower case
@ -159,18 +233,9 @@ sendNullTerminator:
jsr SendByte
DumpOutput:
jsr GetByte
bcs skipOutput
cmp #$00
beq endOutput
jsr PrintChar
skipOutput:
bit Keyboard ;check for keypress
bpl DumpOutput ;keep dumping output if no keypress
lda Keyboard ;send keypress to RPi
jsr PrintChar
and #$7f
jsr SendByte
bit ClearKeyboard
clc
bcc DumpOutput
endOutput:
@ -189,6 +254,7 @@ waitWrite:
bcs waitWrite
pla
sta OutputByte,x
.if HW_TYPE = 0
lda #$1e ; set bit 0 low to indicate write started
sta OutputFlags,x
finishWrite:
@ -198,23 +264,21 @@ finishWrite:
bcc finishWrite
lda #$1f
sta OutputFlags,x
.endif
rts
GetByte:
.if HW_TYPE = 0
lda #$1d ;set read flag low
sta OutputFlags,x
.endif
waitRead:
lda InputFlags,x
rol
bcc readByte
bit Keyboard ;keypress will abort waiting to read
bpl waitRead
lda #$1f ;set all flags high and exit
sta OutputFlags,x
sec ;failure
rts
bcs waitRead
readByte:
lda InputByte,x
.if HW_TYPE = 0
pha
lda #$1f ;set all flags high
sta OutputFlags,x
@ -223,17 +287,11 @@ finishRead:
rol
bcc finishRead
pla
.endif
clc ;success
rts
;macro for string with high-bit set
.macro aschi str
.repeat .strlen (str), c
.byte .strat (str, c) | $80
.endrep
.endmacro
CMD: aschi "rpi"
CMDLEN = 3 ;Our command length
;

Binary file not shown.

View File

@ -1,251 +0,0 @@
ca65 V2.18 - N/A
Main file : RPi.Command.asm
Current file: RPi.Command.asm
000000r 1 ; Copyright Terence J. Boldt (c)2021-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the RPI.COMMAND
000000r 1 ; application that runs on the Apple II and extends
000000r 1 ; ProDOS BASIC.SYSTEM to add the RPI command which
000000r 1 ; allows commands to be executed on the Raspberry Pi
000000r 1
000000r 1 .ORG $300
000300 1 INBUF = $200 ;GETLN input buffer.
000300 1 WAIT = $FCA8 ;Monitor wait routine.
000300 1 BELL = $FF3A ;Monitor bell routine.
000300 1 EXTRNCMD = $BE06 ;External cmd JMP vector.
000300 1 XTRNADDR = $BE50 ;Ext cmd implementation addr.
000300 1 XLEN = $BE52 ;length of command string-1.
000300 1 XCNUM = $BE53 ;CI cmd no. (ext cmd - 0).
000300 1 PBITS = $BE54 ;Command parameter bits.
000300 1 XRETURN = $FF58 ;Known RTS instruction.
000300 1 InputByte = $c08e
000300 1 OutputByte = $c08d
000300 1 InputFlags = $c08b
000300 1 OutputFlags = $c087
000300 1
000300 1 ReadBlockCommand = $01
000300 1 WriteBlockCommand = $02
000300 1 GetTimeCommand = $03
000300 1 ChangeDriveCommand = $04
000300 1 ExecCommand = $05
000300 1 LoadFileCommand = $06
000300 1 SaveFileCommand = $07
000300 1 MenuCommand = $08
000300 1
000300 1 InputString = $fd67
000300 1 PrintChar = $fded
000300 1 Keyboard = $c000
000300 1 ClearKeyboard = $c010
000300 1 Wait = $fca8
000300 1
000300 1 LastChar = $06
000300 1 SlotL = $fe
000300 1 SlotH = $ff
000300 1 ESC = $9b
000300 1
000300 1 .org $2000
002000 1 A2 07 ldx #$07 ; start at slot 7
002002 1 DetectSlot:
002002 1 A0 00 ldy #$00
002004 1 A9 FC lda #$fc
002006 1 85 FE sta SlotL
002008 1 8A txa
002009 1 09 C0 ora #$c0
00200B 1 85 FF sta SlotH
00200D 1 B1 FE lda (SlotL),y
00200F 1 D0 1C bne nextSlot
002011 1 C8 iny
002012 1 B1 FE lda (SlotL),y
002014 1 D0 17 bne nextSlot
002016 1 C8 iny
002017 1 B1 FE lda (SlotL),y
002019 1 C9 17 cmp #$17
00201B 1 D0 10 bne nextSlot
00201D 1 C8 iny
00201E 1 B1 FE lda (SlotL),y
002020 1 C9 14 cmp #$14
002022 1 D0 09 bne nextSlot
002024 1 8A txa
002025 1 0A asl
002026 1 0A asl
002027 1 0A asl
002028 1 0A asl
002029 1 AA tax
00202A 1 18 clc
00202B 1 90 04 bcc Start
00202D 1 nextSlot:
00202D 1 CA dex
00202E 1 D0 D2 bne DetectSlot
002030 1 60 rts
002031 1 Start:
002031 1 8E 48 21 stx slotx + $1e01 ;set the slot for the driver
002034 1 A2 00 ldx #$00
002036 1 copyDriver:
002036 1 BD 00 21 lda $2100,x
002039 1 9D 00 03 sta $0300,x
00203C 1 E8 inx
00203D 1 E0 E6 cpx #$e6
00203F 1 D0 F5 bne copyDriver
002041 1 end:
002041 1 4C 00 03 jmp $0300
002044 1
002044 1 00 00 00 00 .repeat 253-<end
002048 1 00 00 00 00
00204C 1 00 00 00 00
002100 1 .byte 0
002100 1 .endrepeat
002100 1
002100 1 .org $0300
000300 1 ;
000300 1 ; FIRST SAVE THE EXTERNAL COMMAND ADDRESS SO YOU WON'T
000300 1 ; DISCONNECT ANY PREVIOUSLY CONNECTED COMMAND.
000300 1 ;
000300 1 AD 07 BE LDA EXTRNCMD+1
000303 1 8D E5 03 STA NXTCMD
000306 1 AD 08 BE LDA EXTRNCMD+2
000309 1 8D E6 03 STA NXTCMD+1
00030C 1 ;
00030C 1 A9 17 LDA #<RPI ;Install the address of our
00030E 1 8D 07 BE STA EXTRNCMD+1 ; command handler in the
000311 1 A9 03 LDA #>RPI ; external command JMP
000313 1 8D 08 BE STA EXTRNCMD+2 ; vector.
000316 1 60 RTS
000317 1 ;
000317 1 A2 00 RPI: LDX #0 ;Check for our command.
000319 1 BD 00 02 NXTCHR: LDA INBUF,X ;Get first character.
00031C 1 09 20 ora #$20 ;Make it lower case
00031E 1 DD E2 03 CMP CMD,X ;Does it match?
000321 1 D0 29 BNE NOTOURS ;No, back to CI.
000323 1 E8 INX ;Next character
000324 1 E0 03 CPX #CMDLEN ;All characters yet?
000326 1 D0 F1 BNE NXTCHR ;No, read next one.
000328 1 ;
000328 1 A9 02 LDA #CMDLEN-1 ;Our cmd! Put cmd length-1
00032A 1 ;lda #$8d
00032A 1 ;sta $02ff
00032A 1 ;lda #$fe
00032A 1 8D 52 BE STA XLEN ; in CI global XLEN.
00032D 1 A9 58 LDA #<XRETURN ;Point XTRNADDR to a known
00032F 1 8D 50 BE STA XTRNADDR ; RTS since we'll handle
000332 1 A9 FF LDA #>XRETURN ; at the time we intercept
000334 1
000334 1 8D 51 BE STA XTRNADDR+1 ; our command.
000337 1 A9 00 LDA #0 ;Mark the cmd number as
000339 1 8D 53 BE STA XCNUM ; zero (external).
00033C 1 8D 54 BE STA PBITS ;And indicate no parameters
00033F 1 8D 55 BE STA PBITS+1 ; to be parsed.
000342 1 A9 8D lda #$8d
000344 1 20 ED FD jsr $fded
000347 1 A2 70 slotx: ldx #$70 ; set x to slot # in high nibble
000349 1 18 clc
00034A 1 90 04 bcc SendCommand
00034C 1 ;
00034C 1 38 NOTOURS: SEC ; ALWAYS SET CARRY IF NOT YOUR
00034D 1 6C E5 03 JMP (NXTCMD) ; CMD AND LET NEXT COMMAND TRY
000350 1 ; ; TO CLAIM IT.
000350 1
000350 1 SendCommand:
000350 1 2C 10 C0 bit ClearKeyboard
000353 1 A9 05 lda #$05 ;send command 5 = exec
000355 1 20 9B 03 jsr SendByte
000358 1 A0 03 ldy #$03 ;skip over "RPI"
00035A 1 getInput:
00035A 1 B9 00 02 lda $0200,y
00035D 1 C9 8D cmp #$8d
00035F 1 F0 08 beq sendNullTerminator
000361 1 29 7F and #$7f
000363 1 20 9B 03 jsr SendByte
000366 1 C8 iny
000367 1 D0 F1 bne getInput
000369 1 sendNullTerminator:
000369 1 A9 00 lda #$00
00036B 1 20 9B 03 jsr SendByte
00036E 1 DumpOutput:
00036E 1 20 B9 03 jsr GetByte
000371 1 B0 07 bcs skipOutput
000373 1 C9 00 cmp #$00
000375 1 F0 19 beq endOutput
000377 1 20 ED FD jsr PrintChar
00037A 1 skipOutput:
00037A 1 2C 00 C0 bit Keyboard ;check for keypress
00037D 1 10 EF bpl DumpOutput ;keep dumping output if no keypress
00037F 1 AD 00 C0 lda Keyboard ;send keypress to RPi
000382 1 20 ED FD jsr PrintChar
000385 1 29 7F and #$7f
000387 1 20 9B 03 jsr SendByte
00038A 1 2C 10 C0 bit ClearKeyboard
00038D 1 18 clc
00038E 1 90 DE bcc DumpOutput
000390 1 endOutput:
000390 1 18 clc
000391 1 6C E5 03 jmp (NXTCMD)
000394 1
000394 1 HelpCommand:
000394 1 61 32 68 65 .byte "a2help",$00
000398 1 6C 70 00
00039B 1
00039B 1 SendByte:
00039B 1 48 pha
00039C 1 waitWrite:
00039C 1 BD 8B C0 lda InputFlags,x
00039F 1 2A rol
0003A0 1 2A rol
0003A1 1 B0 F9 bcs waitWrite
0003A3 1 68 pla
0003A4 1 9D 8D C0 sta OutputByte,x
0003A7 1 A9 1E lda #$1e ; set bit 0 low to indicate write started
0003A9 1 9D 87 C0 sta OutputFlags,x
0003AC 1 finishWrite:
0003AC 1 BD 8B C0 lda InputFlags,x
0003AF 1 2A rol
0003B0 1 2A rol
0003B1 1 90 F9 bcc finishWrite
0003B3 1 A9 1F lda #$1f
0003B5 1 9D 87 C0 sta OutputFlags,x
0003B8 1 60 rts
0003B9 1
0003B9 1 GetByte:
0003B9 1 A9 1D lda #$1d ;set read flag low
0003BB 1 9D 87 C0 sta OutputFlags,x
0003BE 1 waitRead:
0003BE 1 BD 8B C0 lda InputFlags,x
0003C1 1 2A rol
0003C2 1 90 0C bcc readByte
0003C4 1 2C 00 C0 bit Keyboard ;keypress will abort waiting to read
0003C7 1 10 F5 bpl waitRead
0003C9 1 A9 1F lda #$1f ;set all flags high and exit
0003CB 1 9D 87 C0 sta OutputFlags,x
0003CE 1 38 sec ;failure
0003CF 1 60 rts
0003D0 1 readByte:
0003D0 1 BD 8E C0 lda InputByte,x
0003D3 1 48 pha
0003D4 1 A9 1F lda #$1f ;set all flags high
0003D6 1 9D 87 C0 sta OutputFlags,x
0003D9 1 finishRead:
0003D9 1 BD 8B C0 lda InputFlags,x
0003DC 1 2A rol
0003DD 1 90 FA bcc finishRead
0003DF 1 68 pla
0003E0 1 18 clc ;success
0003E1 1 60 rts
0003E2 1
0003E2 1
0003E2 1 ;macro for string with high-bit set
0003E2 1 .macro aschi str
0003E2 1 .repeat .strlen (str), c
0003E2 1 .byte .strat (str, c) | $80
0003E2 1 .endrep
0003E2 1 .endmacro
0003E2 1
0003E2 1 F2 F0 E9 CMD: aschi "rpi"
0003E5 1 CMDLEN = 3 ;Our command length
0003E5 1 ;
0003E5 1 00 00 NXTCMD: .byte 0,0 ; STORE THE NEXT EXT CMD'S
0003E7 1 ; ADDRESS HERE.
0003E7 1
0003E7 1
0003E7 1

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.
@ -38,6 +38,9 @@ ShellCommand = $09
InputString = $fd6a
StringBuffer = $0200
PrintChar = $fded
PrintHex = $FDE3
PrintByte = $FDDA
Keyboard = $c000
ClearKeyboard = $c010
Home = $fc58
@ -59,59 +62,84 @@ SlotH = $ff
ESC = $9b
.org $2000
ldx #$07 ; start at slot 7
DetectSlot:
; Find Apple2-IO-RPi card
ldx #$06
ldy #$09
CheckIdBytes:
lda $C700,y ; !! Self modifying code
cmp IdBytes,y
bne NextCard
dey
bne CheckIdBytes
jmp FoundCard
NextCard:
dec CheckIdBytes+2
ldy #$09
dex
bne CheckIdBytes
CardNotFound:
ldy #$00
lda #$fc
sta SlotL
PrintCardNotFound:
lda TextCardNotFound,y
beq Failed
ora #$80
jsr PrintChar
iny
bne PrintCardNotFound
Failed:
rts
FoundCard:
ldy #$00
PrintCardFound:
lda TextCardFound,y
beq PrintCardNumber
ora #$80
jsr PrintChar
iny
bne PrintCardFound
PrintCardNumber:
inx
txa
ora #$c0
sta SlotH
lda (SlotL),y
bne nextSlot
iny
lda (SlotL),y
bne nextSlot
iny
lda (SlotL),y
cmp #$17
bne nextSlot
iny
lda (SlotL),y
cmp #$14
bne nextSlot
jsr PrintHex
lda #$8D
jsr PrintChar
SetOffsetForCard:
txa
asl
asl
asl
asl
tax
clc
bcc Start
nextSlot:
dex
bne DetectSlot
rts
Start:
Init:
lda #$8d
jsr $c300 ; force 80 columns
ldy #$00
PrintString:
lda Text,y
beq Start
ora #$80
jsr PrintChar
iny
bne PrintString
Start:
lda LastChar
pha
bit ClearKeyboard
lda #ResetCommand
jsr SendByte
; lda #ResetCommand
; jsr SendByte
lda #ShellCommand
jsr SendByte
jsr DumpOutput
lda #ResetCommand
jsr SendByte
pla
sta LastChar
rts
DumpOutput:
jsr GetByte
bcs checkInput
cmp #$00
beq endOutput
pha
@ -132,14 +160,6 @@ DumpOutput:
jsr PrintChar
jsr SetCursor
jmp DumpOutput
checkInput:
bit Keyboard ;check for keypress
bpl DumpOutput ;keep dumping output if no keypress
lda Keyboard ;send keypress to RPi
and #$7f
jsr SendByte
bit ClearKeyboard
jmp DumpOutput
endOutput:
rts
clearScreen:
@ -182,6 +202,7 @@ waitWrite:
bcs waitWrite
pla
sta OutputByte,x
.if HW_TYPE = 0
lda #$1e ; set bit 0 low to indicate write started
sta OutputFlags,x
finishWrite:
@ -191,13 +212,14 @@ finishWrite:
bcc finishWrite
lda #$1f
sta OutputFlags,x
.endif
rts
GetByte:
bit Keyboard ; skip byte read if key pressed
bcc keyPressed
.if HW_TYPE = 0
lda #$1d ;set read flag low
sta OutputFlags,x
.endif
waitRead:
lda InputFlags,x
rol
@ -205,12 +227,29 @@ waitRead:
bit Keyboard ;keypress will abort waiting to read
bpl waitRead
keyPressed:
lda #$1f ;set all flags high and exit
lda InputFlags,x
rol
rol
bcs keyPressed
lda Keyboard ;send keypress to RPi
and #$7f
sta OutputByte,x
bit ClearKeyboard
.if HW_TYPE = 0
lda #$1c ;set write flag low too
sta OutputFlags,x
sec ;failure
rts
finishKeyPress:
lda InputFlags,x
rol
rol
bcc finishKeyPress
lda #$1d ;set flags back for reading
sta OutputFlags,x
.endif
jmp waitRead
readByte:
lda InputByte,x
.if HW_TYPE = 0
pha
lda #$1f ;set all flags high
sta OutputFlags,x
@ -219,6 +258,7 @@ finishRead:
rol
bcc finishRead
pla
.endif
clc ;success
end:
rts
@ -267,3 +307,22 @@ restoreChar:
sta (BasL),y
lda TextPage1
rts
Text:
.if HW_TYPE = 0
.byte "Apple2-IO-RPi Shell Version 0010 (classic)",$8d
.else
.byte "Apple2-IO-RPi Shell Version 8010 (pico)",$8d
.endif
.byte "(c)2020-2024 Terence J. Boldt",$8d
.byte $8d
.byte $00
IdBytes:
.byte $E0,$20,$E0,$00,$E0,$03,$E0,$3C,$A9,$3F
TextCardFound:
.byte "Found Apple2-IO-RPi in slot ",$00
TextCardNotFound:
.byte "Apple2-IO-RPi not found",$8D,$00

Binary file not shown.

View File

@ -1,274 +0,0 @@
ca65 V2.18 - N/A
Main file : Shell.asm
Current file: Shell.asm
000000r 1 ; Copyright Terence J. Boldt (c)2021-2022
000000r 1 ; Use of this source code is governed by an MIT
000000r 1 ; license that can be found in the LICENSE file.
000000r 1
000000r 1 ; This file contains the source for the SHELL
000000r 1 ; application that runs on the Apple II to talk
000000r 1 ; to the Raspberry Pi
000000r 1
000000r 1 ;ProDOS Zero Page
000000r 1 Command = $42 ;ProDOS Command
000000r 1 Unit = $43 ;ProDOS unit (SDDD0000)
000000r 1 BufferLo = $44
000000r 1 BufferHi = $45
000000r 1 BlockLo = $46
000000r 1 BlockHi = $47
000000r 1
000000r 1 ; ProDOS Error Codes
000000r 1 IOError = $27
000000r 1 NoDevice = $28
000000r 1 WriteProtect = $2B
000000r 1
000000r 1 InputByte = $c08e
000000r 1 OutputByte = $c08d
000000r 1 InputFlags = $c08b
000000r 1 OutputFlags = $c087
000000r 1
000000r 1 ResetCommand = $00
000000r 1 ReadBlockCommand = $01
000000r 1 WriteBlockCommand = $02
000000r 1 GetTimeCommand = $03
000000r 1 ChangeDriveCommand = $04
000000r 1 ExecCommand = $05
000000r 1 LoadFileCommand = $06
000000r 1 SaveFileCommand = $07
000000r 1 MenuCommand = $08
000000r 1 ShellCommand = $09
000000r 1
000000r 1 InputString = $fd6a
000000r 1 StringBuffer = $0200
000000r 1 PrintChar = $fded
000000r 1 Keyboard = $c000
000000r 1 ClearKeyboard = $c010
000000r 1 Home = $fc58
000000r 1 Wait = $fca8
000000r 1 PromptChar = $33
000000r 1 Read80Col = $c01f
000000r 1 TextPage1 = $c054
000000r 1 TextPage2 = $c055
000000r 1
000000r 1 htab = $24
000000r 1 vtab = $25
000000r 1 BasL = $28
000000r 1 htab80 = $057b
000000r 1 BasCalc = $fbc1
000000r 1
000000r 1 LastChar = $06
000000r 1 SlotL = $fe
000000r 1 SlotH = $ff
000000r 1 ESC = $9b
000000r 1
000000r 1 .org $2000
002000 1 A2 07 ldx #$07 ; start at slot 7
002002 1 DetectSlot:
002002 1 A0 00 ldy #$00
002004 1 A9 FC lda #$fc
002006 1 85 FE sta SlotL
002008 1 8A txa
002009 1 09 C0 ora #$c0
00200B 1 85 FF sta SlotH
00200D 1 B1 FE lda (SlotL),y
00200F 1 D0 1C bne nextSlot
002011 1 C8 iny
002012 1 B1 FE lda (SlotL),y
002014 1 D0 17 bne nextSlot
002016 1 C8 iny
002017 1 B1 FE lda (SlotL),y
002019 1 C9 17 cmp #$17
00201B 1 D0 10 bne nextSlot
00201D 1 C8 iny
00201E 1 B1 FE lda (SlotL),y
002020 1 C9 14 cmp #$14
002022 1 D0 09 bne nextSlot
002024 1 8A txa
002025 1 0A asl
002026 1 0A asl
002027 1 0A asl
002028 1 0A asl
002029 1 AA tax
00202A 1 18 clc
00202B 1 90 04 bcc Start
00202D 1 nextSlot:
00202D 1 CA dex
00202E 1 D0 D2 bne DetectSlot
002030 1 60 rts
002031 1 Start:
002031 1 A9 8D lda #$8d
002033 1 20 00 C3 jsr $c300 ; force 80 columns
002036 1 A5 06 lda LastChar
002038 1 48 pha
002039 1 2C 10 C0 bit ClearKeyboard
00203C 1 A9 00 lda #ResetCommand
00203E 1 20 D7 20 jsr SendByte
002041 1 A9 09 lda #ShellCommand
002043 1 20 D7 20 jsr SendByte
002046 1 20 52 20 jsr DumpOutput
002049 1 A9 00 lda #ResetCommand
00204B 1 20 D7 20 jsr SendByte
00204E 1 68 pla
00204F 1 85 06 sta LastChar
002051 1 60 rts
002052 1
002052 1 DumpOutput:
002052 1 20 F5 20 jsr GetByte
002055 1 B0 2A bcs checkInput
002057 1 C9 00 cmp #$00
002059 1 F0 39 beq endOutput
00205B 1 48 pha
00205C 1 20 54 21 jsr ClearCursor
00205F 1 68 pla
002060 1 C9 48 cmp #'H'
002062 1 F0 3A beq setColumn
002064 1 C9 56 cmp #'V'
002066 1 F0 44 beq setRow
002068 1 C9 43 cmp #'C'
00206A 1 F0 29 beq clearScreen
00206C 1 C9 54 cmp #'T'
00206E 1 F0 4A beq setTop
002070 1 C9 42 cmp #'B'
002072 1 F0 4E beq setBottom
002074 1 C9 55 cmp #'U'
002076 1 F0 52 beq moveUp
002078 1 20 ED FD jsr PrintChar
00207B 1 20 23 21 jsr SetCursor
00207E 1 4C 52 20 jmp DumpOutput
002081 1 checkInput:
002081 1 2C 00 C0 bit Keyboard ;check for keypress
002084 1 10 CC bpl DumpOutput ;keep dumping output if no keypress
002086 1 AD 00 C0 lda Keyboard ;send keypress to RPi
002089 1 29 7F and #$7f
00208B 1 20 D7 20 jsr SendByte
00208E 1 2C 10 C0 bit ClearKeyboard
002091 1 4C 52 20 jmp DumpOutput
002094 1 endOutput:
002094 1 60 rts
002095 1 clearScreen:
002095 1 20 58 FC jsr Home
002098 1 20 23 21 jsr SetCursor
00209B 1 4C 52 20 jmp DumpOutput
00209E 1 setColumn:
00209E 1 20 F5 20 jsr GetByte
0020A1 1 85 24 sta htab
0020A3 1 8D 7B 05 sta htab80
0020A6 1 20 23 21 jsr SetCursor
0020A9 1 4C 52 20 jmp DumpOutput
0020AC 1 setRow:
0020AC 1 20 F5 20 jsr GetByte
0020AF 1 85 25 sta vtab
0020B1 1 20 C1 FB jsr BasCalc
0020B4 1 20 23 21 jsr SetCursor
0020B7 1 4C 52 20 jmp DumpOutput
0020BA 1 setTop:
0020BA 1 20 F5 20 jsr GetByte
0020BD 1 85 22 sta $22
0020BF 1 4C 52 20 jmp DumpOutput
0020C2 1 setBottom:
0020C2 1 20 F5 20 jsr GetByte
0020C5 1 85 23 sta $23
0020C7 1 4C 52 20 jmp DumpOutput
0020CA 1 moveUp:
0020CA 1 C6 25 dec vtab
0020CC 1 A5 25 lda vtab
0020CE 1 20 C1 FB jsr BasCalc
0020D1 1 20 23 21 jsr SetCursor
0020D4 1 4C 52 20 jmp DumpOutput
0020D7 1
0020D7 1 SendByte:
0020D7 1 48 pha
0020D8 1 waitWrite:
0020D8 1 BD 8B C0 lda InputFlags,x
0020DB 1 2A rol
0020DC 1 2A rol
0020DD 1 B0 F9 bcs waitWrite
0020DF 1 68 pla
0020E0 1 9D 8D C0 sta OutputByte,x
0020E3 1 A9 1E lda #$1e ; set bit 0 low to indicate write started
0020E5 1 9D 87 C0 sta OutputFlags,x
0020E8 1 finishWrite:
0020E8 1 BD 8B C0 lda InputFlags,x
0020EB 1 2A rol
0020EC 1 2A rol
0020ED 1 90 F9 bcc finishWrite
0020EF 1 A9 1F lda #$1f
0020F1 1 9D 87 C0 sta OutputFlags,x
0020F4 1 60 rts
0020F5 1
0020F5 1 GetByte:
0020F5 1 2C 00 C0 bit Keyboard ; skip byte read if key pressed
0020F8 1 90 10 bcc keyPressed
0020FA 1 A9 1D lda #$1d ;set read flag low
0020FC 1 9D 87 C0 sta OutputFlags,x
0020FF 1 waitRead:
0020FF 1 BD 8B C0 lda InputFlags,x
002102 1 2A rol
002103 1 90 0C bcc readByte
002105 1 2C 00 C0 bit Keyboard ;keypress will abort waiting to read
002108 1 10 F5 bpl waitRead
00210A 1 keyPressed:
00210A 1 A9 1F lda #$1f ;set all flags high and exit
00210C 1 9D 87 C0 sta OutputFlags,x
00210F 1 38 sec ;failure
002110 1 60 rts
002111 1 readByte:
002111 1 BD 8E C0 lda InputByte,x
002114 1 48 pha
002115 1 A9 1F lda #$1f ;set all flags high
002117 1 9D 87 C0 sta OutputFlags,x
00211A 1 finishRead:
00211A 1 BD 8B C0 lda InputFlags,x
00211D 1 2A rol
00211E 1 90 FA bcc finishRead
002120 1 68 pla
002121 1 18 clc ;success
002122 1 end:
002122 1 60 rts
002123 1
002123 1 SetCursor:
002123 1 AD 7B 05 lda htab80 ;get horizontal location / 2
002126 1 4A lsr
002127 1 A8 tay
002128 1 AD 55 C0 lda TextPage2
00212B 1 90 03 bcc setChar
00212D 1 AD 54 C0 lda TextPage1
002130 1 setChar:
002130 1 B1 28 lda (BasL),y
002132 1 85 06 sta LastChar ; save so ClearCursor will pick it up
002134 1 C9 E0 cmp #$e0
002136 1 10 0C bpl lowerCase
002138 1 C9 C0 cmp #$c0
00213A 1 10 0D bpl upperCase
00213C 1 C9 A0 cmp #$a0
00213E 1 10 04 bpl symbol
002140 1 C9 80 cmp #$80
002142 1 10 0A bpl noop
002144 1 symbol:
002144 1 lowerCase:
002144 1 invert:
002144 1 49 80 eor #$80
002146 1 4C 4E 21 jmp storeChar
002149 1 upperCase:
002149 1 29 1F and #$1f
00214B 1 4C 4E 21 jmp storeChar
00214E 1 noop:
00214E 1 storeChar:
00214E 1 91 28 sta (BasL),y
002150 1 AD 54 C0 lda TextPage1
002153 1 60 rts
002154 1
002154 1 ClearCursor:
002154 1 AD 7B 05 lda htab80 ;get horizontal location / 2
002157 1 4A lsr
002158 1 A8 tay
002159 1 AD 55 C0 lda TextPage2
00215C 1 90 03 bcc restoreChar
00215E 1 AD 54 C0 lda TextPage1
002161 1 restoreChar:
002161 1 A5 06 lda LastChar
002163 1 91 28 sta (BasL),y
002165 1 AD 54 C0 lda TextPage1
002168 1 60 rts
002168 1

13
Apple2/Startup.bas Normal file
View File

@ -0,0 +1,13 @@
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 CHR$ (4)"-clock.driver"
22 PRINT CHR$ (4)"-rpi.command"

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

110
Apple2/assemble.cmd Normal file
View File

@ -0,0 +1,110 @@
@if "%1" == "" (set HW_TYPE=0) else (set HW_TYPE=%1)
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=0 -o DriveSlot0.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=1 -o DriveSlot1.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=2 -o DriveSlot2.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=3 -o DriveSlot3.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=4 -o DriveSlot4.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=5 -o DriveSlot5.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=6 -o DriveSlot6.o
@if errorlevel 1 goto exit
ca65 DriveFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=7 -o DriveSlot7.o --listing DriveFirmware.lst --list-bytes 255
@if errorlevel 1 goto exit
ld65 DriveSlot0.o DriveSlot1.o DriveSlot2.o DriveSlot3.o DriveSlot4.o DriveSlot5.o DriveSlot6.o DriveSlot7.o -o DriveFirmware.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=0 -o MenuSlot0.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=1 -o MenuSlot1.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=2 -o MenuSlot2.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=3 -o MenuSlot3.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=4 -o MenuSlot4.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=5 -o MenuSlot5.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=6 -o MenuSlot6.o
@if errorlevel 1 goto exit
ca65 MenuFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=7 -o MenuSlot7.o --listing MenuFirmware.lst --list-bytes 255
@if errorlevel 1 goto exit
ld65 MenuSlot0.o MenuSlot1.o MenuSlot2.o MenuSlot3.o MenuSlot4.o MenuSlot5.o MenuSlot6.o MenuSlot7.o -o MenuFirmware.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=0 -o CommandSlot0.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=1 -o CommandSlot1.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=2 -o CommandSlot2.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=3 -o CommandSlot3.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=4 -o CommandSlot4.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=5 -o CommandSlot5.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=6 -o CommandSlot6.o
@if errorlevel 1 goto exit
ca65 CommandFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=7 -o CommandSlot7.o --listing CommandFirmware.lst --list-bytes 255
@if errorlevel 1 goto exit
ld65 CommandSlot0.o CommandSlot1.o CommandSlot2.o CommandSlot3.o CommandSlot4.o CommandSlot5.o CommandSlot6.o CommandSlot7.o -o CommandFirmware.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=0 -o FileAccessSlot0.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=1 -o FileAccessSlot1.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=2 -o FileAccessSlot2.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=3 -o FileAccessSlot3.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=4 -o FileAccessSlot4.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=5 -o FileAccessSlot5.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=6 -o FileAccessSlot6.o
@if errorlevel 1 goto exit
ca65 FileAccessFirmware.asm -D HW_TYPE=%HW_TYPE% -D SLOT=7 -o FileAccessSlot7.o --listing FileAccessFirmware.lst --list-bytes 255
@if errorlevel 1 goto exit
ld65 FileAccessSlot0.o FileAccessSlot1.o FileAccessSlot2.o FileAccessSlot3.o FileAccessSlot4.o FileAccessSlot5.o FileAccessSlot6.o FileAccessSlot7.o -o FileAccessFirmware.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
copy /b DriveFirmware.bin + CommandFirmware.bin + FileAccessFirmware.bin + MenuFirmware.bin AT28C64B.bin
ca65 Shell.asm -D HW_TYPE=%HW_TYPE% -o Shell.o --listing Shell.lst
@if errorlevel 1 goto exit
ld65 Shell.o -o Shell.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
ca65 RPi.Command.asm -D HW_TYPE=%HW_TYPE% -o RPi.Command.o --listing RPi.Command.lst
@if errorlevel 1 goto exit
ld65 RPi.Command.o -o RPi.Command.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
ca65 Clock.Driver.asm -D HW_TYPE=%HW_TYPE% -o Clock.Driver.o --listing Clock.Driver.lst
@if errorlevel 1 goto exit
ld65 Clock.Driver.o -o Clock.Driver.bin -C ../.cicd/none.cfg
@if errorlevel 1 goto exit
cdel *.o
del DriveFirmware.bin
del MenuFirmware.bin
del CommandFirmware.bin
del FileAccessFirmware.bin
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i AT28C64B.bin -p /APPLE2.IO.RPI/AT28C64B.BIN
@if errorlevel 1 goto exit
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i Shell.bin -p /APPLE2.IO.RPI/SHELL
@if errorlevel 1 goto exit
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c put -i RPi.Command.bin -p /APPLE2.IO.RPI/RPI.COMMAND -a 0x2000
@if errorlevel 1 goto exit
ProDOS-Utilities -d ../RaspberryPi/Apple2-IO-RPi.hdv -c ls
:exit

View File

@ -1,61 +1,61 @@
#!/bin/sh
ca65 DriveFirmware.asm -D SLOT=0 -o DriveSlot0.o || exit 1
ca65 DriveFirmware.asm -D SLOT=1 -o DriveSlot1.o || exit 1
ca65 DriveFirmware.asm -D SLOT=2 -o DriveSlot2.o || exit 1
ca65 DriveFirmware.asm -D SLOT=3 -o DriveSlot3.o || exit 1
ca65 DriveFirmware.asm -D SLOT=4 -o DriveSlot4.o || exit 1
ca65 DriveFirmware.asm -D SLOT=5 -o DriveSlot5.o || exit 1
ca65 DriveFirmware.asm -D SLOT=6 -o DriveSlot6.o || exit 1
ca65 DriveFirmware.asm -D SLOT=7 -o DriveSlot7.o --listing DriveFirmware.lst --list-bytes 255 || exit 1
HW_TYPE=${1-0}
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o DriveSlot0.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o DriveSlot1.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o DriveSlot2.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o DriveSlot3.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o DriveSlot4.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o DriveSlot5.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o DriveSlot6.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o DriveSlot7.o --listing DriveFirmware.lst --list-bytes 255 || exit 1
ld65 DriveSlot0.o DriveSlot1.o DriveSlot2.o DriveSlot3.o DriveSlot4.o DriveSlot5.o DriveSlot6.o DriveSlot7.o -o DriveFirmware.bin -C ../.cicd/none.cfg || exit 1
ca65 MenuFirmware.asm -D SLOT=0 -o MenuSlot0.o || exit 1
ca65 MenuFirmware.asm -D SLOT=1 -o MenuSlot1.o || exit 1
ca65 MenuFirmware.asm -D SLOT=2 -o MenuSlot2.o || exit 1
ca65 MenuFirmware.asm -D SLOT=3 -o MenuSlot3.o || exit 1
ca65 MenuFirmware.asm -D SLOT=4 -o MenuSlot4.o || exit 1
ca65 MenuFirmware.asm -D SLOT=5 -o MenuSlot5.o || exit 1
ca65 MenuFirmware.asm -D SLOT=6 -o MenuSlot6.o || exit 1
ca65 MenuFirmware.asm -D SLOT=7 -o MenuSlot7.o --listing MenuFirmware.lst --list-bytes 255 || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o MenuSlot0.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o MenuSlot1.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o MenuSlot2.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o MenuSlot3.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o MenuSlot4.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o MenuSlot5.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o MenuSlot6.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o MenuSlot7.o --listing MenuFirmware.lst --list-bytes 255 || exit 1
ld65 MenuSlot0.o MenuSlot1.o MenuSlot2.o MenuSlot3.o MenuSlot4.o MenuSlot5.o MenuSlot6.o MenuSlot7.o -o MenuFirmware.bin -C ../.cicd/none.cfg || exit 1
ca65 CommandFirmware.asm -D SLOT=0 -o CommandSlot0.o || exit 1
ca65 CommandFirmware.asm -D SLOT=1 -o CommandSlot1.o || exit 1
ca65 CommandFirmware.asm -D SLOT=2 -o CommandSlot2.o || exit 1
ca65 CommandFirmware.asm -D SLOT=3 -o CommandSlot3.o || exit 1
ca65 CommandFirmware.asm -D SLOT=4 -o CommandSlot4.o || exit 1
ca65 CommandFirmware.asm -D SLOT=5 -o CommandSlot5.o || exit 1
ca65 CommandFirmware.asm -D SLOT=6 -o CommandSlot6.o || exit 1
ca65 CommandFirmware.asm -D SLOT=7 -o CommandSlot7.o --listing CommandFirmware.lst --list-bytes 255 || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o CommandSlot0.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o CommandSlot1.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o CommandSlot2.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o CommandSlot3.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o CommandSlot4.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o CommandSlot5.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o CommandSlot6.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o CommandSlot7.o --listing CommandFirmware.lst --list-bytes 255 || exit 1
ld65 CommandSlot0.o CommandSlot1.o CommandSlot2.o CommandSlot3.o CommandSlot4.o CommandSlot5.o CommandSlot6.o CommandSlot7.o -o CommandFirmware.bin -C ../.cicd/none.cfg || exit 1
ca65 FileAccessFirmware.asm -D SLOT=0 -o FileAccessSlot0.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=1 -o FileAccessSlot1.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=2 -o FileAccessSlot2.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=3 -o FileAccessSlot3.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=4 -o FileAccessSlot4.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=5 -o FileAccessSlot5.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=6 -o FileAccessSlot6.o || exit 1
ca65 FileAccessFirmware.asm -D SLOT=7 -o FileAccessSlot7.o --listing FileAccessFirmware.lst --list-bytes 255 || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o FileAccessSlot0.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o FileAccessSlot1.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o FileAccessSlot2.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o FileAccessSlot3.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o FileAccessSlot4.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o FileAccessSlot5.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o FileAccessSlot6.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o FileAccessSlot7.o --listing FileAccessFirmware.lst --list-bytes 255 || exit 1
ld65 FileAccessSlot0.o FileAccessSlot1.o FileAccessSlot2.o FileAccessSlot3.o FileAccessSlot4.o FileAccessSlot5.o FileAccessSlot6.o FileAccessSlot7.o -o FileAccessFirmware.bin -C ../.cicd/none.cfg || exit 1
cat \
DriveFirmware.bin CommandFirmware.bin FileAccessFirmware.bin MenuFirmware.bin \
> AT28C64B.bin
> ../RaspberryPi/driveimage/AT28C64B.bin
ca65 Shell.asm -o Shell.o --listing Shell.lst || exit 1
ld65 Shell.o -o Shell.bin -C ../.cicd/none.cfg || exit 1
ca65 Shell.asm -D HW_TYPE=$HW_TYPE -o Shell.o --listing Shell.lst || exit 1
ld65 Shell.o -o ../RaspberryPi/driveimage/Shell.bin -C ../.cicd/none.cfg || exit 1
ca65 RPi.Command.asm -o RPi.Command.o --listing RPi.Command.lst || exit 1
ld65 RPi.Command.o -o RPi.Command.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 ../RaspberryPi/driveimage/RPi.Command.bin -C ../.cicd/none.cfg || exit 1
ca65 Clock.Driver.asm -D HW_TYPE=$HW_TYPE -o Clock.Driver.o --listing Clock.Driver.lst || exit 1
ld65 Clock.Driver.o -o ../RaspberryPi/driveimage/Clock.Driver.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

59
Apple2/compare.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/sh
HW_TYPE=${1-0}
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o DriveSlot0.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o DriveSlot1.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o DriveSlot2.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o DriveSlot3.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o DriveSlot4.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o DriveSlot5.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o DriveSlot6.o || exit 1
ca65 DriveFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o DriveSlot7.o --listing DriveFirmware.lst.new --list-bytes 255 || exit 1
ld65 DriveSlot0.o DriveSlot1.o DriveSlot2.o DriveSlot3.o DriveSlot4.o DriveSlot5.o DriveSlot6.o DriveSlot7.o -o DriveFirmware.bin.new -C ../.cicd/none.cfg || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o MenuSlot0.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o MenuSlot1.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o MenuSlot2.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o MenuSlot3.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o MenuSlot4.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o MenuSlot5.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o MenuSlot6.o || exit 1
ca65 MenuFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o MenuSlot7.o --listing MenuFirmware.lst.new --list-bytes 255 || exit 1
ld65 MenuSlot0.o MenuSlot1.o MenuSlot2.o MenuSlot3.o MenuSlot4.o MenuSlot5.o MenuSlot6.o MenuSlot7.o -o MenuFirmware.bin.new -C ../.cicd/none.cfg || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o CommandSlot0.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o CommandSlot1.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o CommandSlot2.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o CommandSlot3.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o CommandSlot4.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o CommandSlot5.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o CommandSlot6.o || exit 1
ca65 CommandFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o CommandSlot7.o --listing CommandFirmware.lst.new --list-bytes 255 || exit 1
ld65 CommandSlot0.o CommandSlot1.o CommandSlot2.o CommandSlot3.o CommandSlot4.o CommandSlot5.o CommandSlot6.o CommandSlot7.o -o CommandFirmware.bin.new -C ../.cicd/none.cfg || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=0 -o FileAccessSlot0.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=1 -o FileAccessSlot1.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=2 -o FileAccessSlot2.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=3 -o FileAccessSlot3.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=4 -o FileAccessSlot4.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=5 -o FileAccessSlot5.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=6 -o FileAccessSlot6.o || exit 1
ca65 FileAccessFirmware.asm -D HW_TYPE=$HW_TYPE -D SLOT=7 -o FileAccessSlot7.o --listing FileAccessFirmware.lst.new --list-bytes 255 || exit 1
ld65 FileAccessSlot0.o FileAccessSlot1.o FileAccessSlot2.o FileAccessSlot3.o FileAccessSlot4.o FileAccessSlot5.o FileAccessSlot6.o FileAccessSlot7.o -o FileAccessFirmware.bin.new -C ../.cicd/none.cfg || exit 1
cat \
DriveFirmware.bin.new CommandFirmware.bin.new FileAccessFirmware.bin.new MenuFirmware.bin.new \
> AT28C64B.bin.new
ca65 Shell.asm -D HW_TYPE=$HW_TYPE -o Shell.o --listing Shell.lst.new || exit 1
ld65 Shell.o -o Shell.bin.new -C ../.cicd/none.cfg || exit 1
ca65 RPi.Command.asm -D HW_TYPE=$HW_TYPE -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 ../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

27
ClassicSetup.md Normal file
View File

@ -0,0 +1,27 @@
## Setup starting from scratch
1. Have PCBs made from [PCBWay](https://www.pcbway.com/project/shareproject/Apple2_IO_RPi_v6_bfa4be82.html) or 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. If you have an EPROM programmer, it is preferred to pre-populate the EEPROM with the contents of AT28C68B.bin
4. Attach Raspberry Pi Zero 2 W facing outward from the card
5. Install [Raspberry Pi OS](https://www.raspberrypi.org/software/) on microSD card using a modern computer
1. Use Raspberry Pi Imager
2. Click "Choose OS"
3. Select Other => "Raspberry Pi OS Lite (64 bit)" for the Zero 2 W
4. Click on the gear icon in the bottom right
5. Enable ssh
6. Set password
7. Configure wifi
8. Set locale settings
6. Put microSD card in the RPi
7. Install the expansion card into the Apple II
8. Power on the Apple II
9. Only if you didn't have an EPROM programmer in step 3, install firmware with utility (can be found on Apple2-IO-RPi.hdv drive image in the release on GitHub)
10. Use `ssh` to connect to the RPi using the password you configured
11. `wget --no-cache -O - https://raw.githubusercontent.com/tjboldt/Apple2-IO-RPi/main/RaspberryPi/setup.sh | bash`
## Options
You can support two drives and change their drive images.
1. Modify the `ExecStart` line in `/etc/systemd/system/apple2driver.service` and make it something like the following: `ExecStart=/home/pi/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver -d1 /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv -d2 /home/pi/Apple2-IO-RPi/RaspberryPi/TotalReplay401.hdv`
2. `sudo systemctl daemon-reload`
3. `sudo systemctl restart apple2driver.service`

View File

@ -1,214 +1,275 @@
(module "Connector:Apple II Expansion Edge Connector" (layer F.Cu) (tedit 5CA41682)
(fp_text reference REF** (at 0 0.5) (layer F.SilkS)
(footprint "Apple II Expansion Edge Connector" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 62126271)
(attr through_hole)
(fp_text reference "REF**" (at 0 0.5) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 2d345aa1-b8a7-433b-98bf-3fb90d3260bf)
)
(fp_text value "Apple II Expansion Edge Connector" (at 9.652 -5.08) (layer F.Fab)
(fp_text value "Apple II Expansion Edge Connector" (at 9.652 -5.08) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp cb7c1e3e-a32d-43a8-bf93-cbb15668bf6c)
)
(fp_text user "26 GND" (at 45.974 10.922 45) (layer F.Fab)
(fp_text user "24 DMA OUT" (at 46.609 -1.524 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 0db76d9f-bfa1-4ba2-a00c-8635e5b902ca)
)
(fp_text user "27 DMA IN" (at 42.799 11.43 45) (layer F.Fab)
(fp_text user "20 _I/O STROBE" (at 37.084 -2.413 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 181378e8-7102-4a44-b001-45175260beb8)
)
(fp_text user "28 INT IN" (at 40.386 11.303 45) (layer F.Fab)
(fp_text user "33 -12V" (at 27.813 11.176 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 18fe078b-d967-4c6b-9117-28649814e048)
)
(fp_text user "29 _NMI" (at 38.1 10.922 45) (layer F.Fab)
(fp_text user "38 @1" (at 15.621 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 1ccc5f53-065b-44e2-aaf9-75fe664f1207)
)
(fp_text user "30 _IRQ" (at 35.687 10.922 45) (layer F.Fab)
(fp_text user "26 GND" (at 45.974 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 23a565f8-c512-42e3-b944-2b21cc7ef5bf)
)
(fp_text user "31 _RES" (at 33.02 10.922 45) (layer F.Fab)
(fp_text user "22 _DMA" (at 40.767 -0.762 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 28b810e6-86c9-4816-91ac-c7dd9aeeded4)
)
(fp_text user "32 _INH" (at 30.607 10.922 45) (layer F.Fab)
(fp_text user "41 _DEVICE SELECT" (at 5.334 13.335 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 2fe78e00-e5a1-4316-afef-41db388c5a0e)
)
(fp_text user "33 -12V" (at 27.813 11.176 45) (layer F.Fab)
(fp_text user "35 N.C." (at 23.368 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 421f3112-b7c7-4f4b-9121-a3cf0cf0597e)
)
(fp_text user "34 -5V" (at 25.527 10.922 45) (layer F.Fab)
(fp_text user "21 RDY" (at 37.973 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 4b896d13-4f14-497d-8365-9269eb3a035e)
)
(fp_text user "35 N.C." (at 23.368 10.541 45) (layer F.Fab)
(fp_text user "4 A2" (at -5.588 0.127 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 4da3fa1f-77fd-49c6-99f5-f367e9469b24)
)
(fp_text user "36 7M" (at 20.701 10.541 45) (layer F.Fab)
(fp_text user "50 +12V" (at -15.494 11.43 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 52c67bfb-3c57-422e-8d95-2ce65bc81bcf)
)
(fp_text user "37 Q3" (at 18.161 10.541 45) (layer F.Fab)
(fp_text user "47 D2" (at -7.239 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 5bd3f15a-7f87-4a76-aa9b-753562cb7685)
)
(fp_text user "38 @1" (at 15.621 10.541 45) (layer F.Fab)
(fp_text user "9 A7" (at 6.985 0 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 5c74d6fb-45e5-4b04-a6d8-73b55ca609c6)
)
(fp_text user "39 USER 1" (at 12.192 11.43 45) (layer F.Fab)
(fp_text user "10 A8" (at 9.779 -0.254 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 5dad2f49-52bf-4323-96cd-ba936cc8db69)
)
(fp_text user "40 @0" (at 10.414 10.541 45) (layer F.Fab)
(fp_text user "30 _IRQ" (at 35.687 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 5f537d37-3073-4dfe-a1f3-999663d80c70)
)
(fp_text user "41 _DEVICE SELECT" (at 5.334 13.335 45) (layer F.Fab)
(fp_text user "5 A3" (at -3.048 0 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 682d5db4-e756-4510-9849-aca6de3105dd)
)
(fp_text user "42 D7" (at 5.461 10.541 45) (layer F.Fab)
(fp_text user "18 R/W" (at 30.48 -0.635 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 6a3ac14c-4a85-4667-966a-7d0148472c12)
)
(fp_text user "43 D6" (at 2.921 10.541 45) (layer F.Fab)
(fp_text user "14 A12" (at 20.193 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 6bb2e188-fcfa-466e-af33-ec436d238245)
)
(fp_text user "44 D5" (at 0.508 10.541 45) (layer F.Fab)
(fp_text user "36 7M" (at 20.701 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 72616612-d502-4e5c-8d3c-0e1b715fac0b)
)
(fp_text user "45 D4" (at -2.159 10.541 45) (layer F.Fab)
(fp_text user "1 _I/O SELECT" (at -11.303 -2.032 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 72d6ed73-8d3e-437e-84b2-89005b784042)
)
(fp_text user "46 D3" (at -4.699 10.541 45) (layer F.Fab)
(fp_text user "17 A15" (at 27.813 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 769f7a46-cfeb-4436-9562-bd91b8bb4f86)
)
(fp_text user "47 D2" (at -7.239 10.541 45) (layer F.Fab)
(fp_text user "37 Q3" (at 18.161 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 77435bfb-f684-4a28-b3ff-81961a6fba7b)
)
(fp_text user "48 D1" (at -9.906 10.541 45) (layer F.Fab)
(fp_text user "7 A5" (at 1.905 0 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 7842b5fe-f647-432a-8030-31226295c8c8)
)
(fp_text user "25 +5V" (at 48.26 -0.635 45) (layer F.Fab)
(fp_text user "3 A1" (at -8.128 -0.127 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 7e6bda94-f514-4d1a-bfa0-706ffa7f3689)
)
(fp_text user "24 DMA OUT" (at 46.609 -1.524 45) (layer F.Fab)
(fp_text user "2 A0" (at -10.668 -0.127 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 876538c4-9b2c-47e3-ba34-df230a80c897)
)
(fp_text user "23 INT OUT" (at 43.942 -1.397 45) (layer F.Fab)
(fp_text user "31 _RES" (at 33.02 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 92175624-00e7-4867-8c25-c34e7f6d0203)
)
(fp_text user "22 _DMA" (at 40.767 -0.762 45) (layer F.Fab)
(fp_text user "45 D4" (at -2.159 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 9bb71c85-174b-4e68-b9a7-85735fbf335e)
)
(fp_text user "21 RDY" (at 37.973 -0.508 45) (layer F.Fab)
(fp_text user "15 A13" (at 22.733 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp 9fbc9d84-4a3d-4b63-b1f4-b4dd3ec849e9)
)
(fp_text user "20 _I/O STROBE" (at 37.084 -2.413 45) (layer F.Fab)
(fp_text user "19 N.C." (at 32.893 -0.635 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp a059b8ed-fc88-4fcf-86c9-17e17afdc401)
)
(fp_text user "19 N.C." (at 32.893 -0.635 45) (layer F.Fab)
(fp_text user "40 @0" (at 10.414 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp a2c88edb-de77-4fcd-9cc0-119965935e0e)
)
(fp_text user "18 R/W" (at 30.48 -0.635 45) (layer F.Fab)
(fp_text user "43 D6" (at 2.921 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp a9954503-95f3-4450-9100-fb8bf25630ac)
)
(fp_text user "16 A14" (at 25.273 -0.508 45) (layer F.Fab)
(fp_text user "13 A11" (at 17.653 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp abd5b1f8-417b-4e4b-bb91-50def48c6e7b)
)
(fp_text user "17 A15" (at 27.813 -0.508 45) (layer F.Fab)
(fp_text user "11 A9" (at 12.319 -0.254 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ac1aacfb-16d3-472f-b5b3-b171dfe254ac)
)
(fp_text user "14 A12" (at 20.193 -0.508 45) (layer F.Fab)
(fp_text user "29 _NMI" (at 38.1 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ad785633-1fa5-4259-9e5f-ec4546c55a2a)
)
(fp_text user "15 A13" (at 22.733 -0.508 45) (layer F.Fab)
(fp_text user "49 D0" (at -12.446 10.668 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ae91f302-2fb7-47ca-b2fd-7d2f7c21f30b)
)
(fp_text user "13 A11" (at 17.653 -0.508 45) (layer F.Fab)
(fp_text user "28 INT IN" (at 40.386 11.303 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp aebbbda9-299a-49ff-9338-8f25d5336c0d)
)
(fp_text user "12 A10" (at 15.113 -0.508 45) (layer F.Fab)
(fp_text user "12 A10" (at 15.113 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ba907e0d-2755-4208-ab9b-bc3b980814be)
)
(fp_text user "11 A9" (at 12.319 -0.254 45) (layer F.Fab)
(fp_text user "23 INT OUT" (at 43.942 -1.397 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp cf64d670-6662-45b3-ae8c-a24f393e28a8)
)
(fp_text user "10 A8" (at 9.779 -0.254 45) (layer F.Fab)
(fp_text user "8 A6" (at 4.445 0 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp d1f57772-5ce6-4b85-bd55-bf5b4526514f)
)
(fp_poly (pts (xy 48.895 8.89) (xy 48.895 1.27) (xy -15.875 1.27) (xy -15.875 8.89)) (layer B.Mask) (width 0.15))
(fp_poly (pts (xy 48.895 8.89) (xy 48.895 1.27) (xy -15.875 1.27) (xy -15.875 8.89)) (layer F.Mask) (width 0.15))
(fp_text user "50 +12V" (at -15.494 11.43 45) (layer F.Fab)
(fp_text user "25 +5V" (at 48.26 -0.635 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp d2e4721d-0955-4b34-ac5d-27599b04c077)
)
(fp_text user "1 _I/O SELECT" (at -11.303 -2.032 45) (layer F.Fab)
(fp_text user "44 D5" (at 0.508 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp d682aa65-e29a-46ce-8d4f-dd4934c5442a)
)
(fp_text user "3 A1" (at -8.128 -0.127 45) (layer F.Fab)
(fp_text user "48 D1" (at -9.906 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp d9551730-80bd-48ee-bf3f-a3342890e676)
)
(fp_text user "5 A3" (at -3.048 0 45) (layer F.Fab)
(fp_text user "42 D7" (at 5.461 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp e78e4c02-edf4-4274-aaca-5bceeb078844)
)
(fp_text user "4 A2" (at -5.588 0.127 45) (layer F.Fab)
(fp_text user "34 -5V" (at 25.527 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ea2e338d-b9c8-4965-a217-a9a6c3864d0b)
)
(fp_text user "49 D0" (at -12.446 10.668 45) (layer F.Fab)
(fp_text user "39 USER 1" (at 12.192 11.43 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp eda8dd6b-776b-4c37-9caa-384399f3bf1f)
)
(fp_text user "2 A0" (at -10.668 -0.127 45) (layer F.Fab)
(fp_text user "32 _INH" (at 30.607 10.922 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ee84e57e-4161-403d-9a75-3302acb4f0d2)
)
(fp_text user "8 A6" (at 4.445 0 45) (layer F.Fab)
(fp_text user "46 D3" (at -4.699 10.541 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp ef6d89e8-baea-4aba-9b87-0c0cc61deae7)
)
(fp_text user "6 A4" (at -0.635 0 45) (layer F.Fab)
(fp_text user "16 A14" (at 25.273 -0.508 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp f7c813ff-d2fc-4492-8158-0c95f20233ed)
)
(fp_text user "9 A7" (at 6.985 0 45) (layer F.Fab)
(fp_text user "6 A4" (at -0.635 0 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp f7de8750-f82b-4a0f-bf9b-94727646f22a)
)
(fp_text user "7 A5" (at 1.905 0 45) (layer F.Fab)
(fp_text user "27 DMA IN" (at 42.799 11.43 45) (layer "F.Fab")
(effects (font (size 0.762 0.762) (thickness 0.127)))
(tstamp fa924129-6767-4560-b59b-3a02d5fe5c1c)
)
(fp_line (start -15.875 1.27) (end -16.51 1.27) (layer F.SilkS) (width 0.15))
(fp_line (start -15.875 7.62) (end -15.875 1.27) (layer F.SilkS) (width 0.15))
(fp_line (start 48.895 1.27) (end 49.53 1.27) (layer F.SilkS) (width 0.15))
(fp_line (start 48.895 7.62) (end 48.895 1.27) (layer F.SilkS) (width 0.15))
(pad 50 connect roundrect (at -13.97 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 49 connect roundrect (at -11.43 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 48 connect roundrect (at -8.89 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 47 connect roundrect (at -6.35 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 46 connect roundrect (at -3.81 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 45 connect roundrect (at -1.27 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 44 connect roundrect (at 1.27 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 43 connect roundrect (at 3.81 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 42 connect roundrect (at 6.35 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 41 connect roundrect (at 8.89 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 40 connect roundrect (at 11.43 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 39 connect roundrect (at 13.97 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 37 connect roundrect (at 19.05 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 38 connect roundrect (at 16.51 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 36 connect roundrect (at 21.59 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 35 connect roundrect (at 24.13 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 34 connect roundrect (at 26.67 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 33 connect roundrect (at 29.21 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 32 connect roundrect (at 31.75 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 31 connect roundrect (at 34.29 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 30 connect roundrect (at 36.83 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 29 connect roundrect (at 39.37 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 28 connect roundrect (at 41.91 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 27 connect roundrect (at 44.45 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 26 connect roundrect (at 46.99 5.08) (size 1.27 7.62) (layers B.Cu B.Mask) (roundrect_rratio 0.25))
(pad 25 connect roundrect (at 46.99 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 24 connect roundrect (at 44.45 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 23 connect roundrect (at 41.91 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 22 connect roundrect (at 39.37 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 21 connect roundrect (at 36.83 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 20 connect roundrect (at 34.29 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 19 connect roundrect (at 31.75 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 18 connect roundrect (at 29.21 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 17 connect roundrect (at 26.67 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 16 connect roundrect (at 24.13 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 15 connect roundrect (at 21.59 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 14 connect roundrect (at 19.05 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 13 connect roundrect (at 16.51 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 12 connect roundrect (at 13.97 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 11 connect roundrect (at 11.43 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 10 connect roundrect (at 8.89 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 9 connect roundrect (at 6.35 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 8 connect roundrect (at 3.81 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 7 connect roundrect (at 1.27 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 6 connect roundrect (at -1.27 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 5 connect roundrect (at -3.81 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 4 connect roundrect (at -6.35 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 3 connect roundrect (at -8.89 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 2 connect roundrect (at -11.43 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(pad 1 connect roundrect (at -13.97 5.08) (size 1.27 7.62) (layers F.Cu F.Mask) (roundrect_rratio 0.25))
(fp_poly (pts
(xy 48.895 8.89)
(xy 48.895 1.27)
(xy -15.875 1.27)
(xy -15.875 8.89)
) (layer "B.Mask") (width 0.15) (fill solid) (tstamp f55818e7-6952-4d1a-b769-53676d534ac7))
(fp_poly (pts
(xy 48.895 8.89)
(xy 48.895 1.27)
(xy -15.875 1.27)
(xy -15.875 8.89)
) (layer "F.Mask") (width 0.15) (fill solid) (tstamp 0a15b674-2ea1-4c80-87c9-48023e84e84a))
(pad "1" connect roundrect (at -13.97 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 70ad1139-50a2-4f62-960b-0274790f3382))
(pad "2" connect roundrect (at -11.43 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp ac8ecb84-75c5-4603-8c9d-a73dd2fe55aa))
(pad "3" connect roundrect (at -8.89 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 4a44d03f-3ed6-4671-a81d-65f7bbf02c9c))
(pad "4" connect roundrect (at -6.35 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 9346ede7-230c-4692-b20f-a0ec78887e90))
(pad "5" connect roundrect (at -3.81 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 6c58bef7-a109-4acd-b484-5503636af5ac))
(pad "6" connect roundrect (at -1.27 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp e7dee0a0-1bf5-4243-ac45-e9c9a7f48039))
(pad "7" connect roundrect (at 1.27 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 45047bb9-87a7-4ccc-955e-f309ddb6bb4f))
(pad "8" connect roundrect (at 3.81 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp fb789d35-2164-4089-ab99-307afe88bcea))
(pad "9" connect roundrect (at 6.35 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp ae48c831-8775-4671-a20d-037464c16f4d))
(pad "10" connect roundrect (at 8.89 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp d3079292-60d9-4a27-b0d3-92875084e9f6))
(pad "11" connect roundrect (at 11.43 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 1aaba807-e811-49c9-9d19-feb0d07d9d41))
(pad "12" connect roundrect (at 13.97 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 291d2e41-69fa-4c50-ba6f-fb2342afae58))
(pad "13" connect roundrect (at 16.51 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 3fd0a841-351f-4dc1-b3c2-1686bffa07d5))
(pad "14" connect roundrect (at 19.05 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 63ac02d9-df52-49d6-bf40-d68ede45c647))
(pad "15" connect roundrect (at 21.59 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp a35d1496-4f2a-4cec-b501-e084102ec217))
(pad "16" connect roundrect (at 24.13 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp cd5d4a39-3bf6-4df0-ae30-52287f16b6b1))
(pad "17" connect roundrect (at 26.67 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 841dcfc1-05d2-482f-8100-5ec8c2f19947))
(pad "18" connect roundrect (at 29.21 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 7bc6a781-e476-46f0-9b85-c99483575955))
(pad "19" connect roundrect (at 31.75 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 65ca96f5-0030-4115-9542-307a17c83362))
(pad "20" connect roundrect (at 34.29 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp be75b37b-9c0e-448c-a8a9-e9c9aa0a3d51))
(pad "21" connect roundrect (at 36.83 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 96f4b525-44cb-47ae-85ba-1452b6ebe244))
(pad "22" connect roundrect (at 39.37 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 46adbde6-4156-414c-a677-91a5d52c06f0))
(pad "23" connect roundrect (at 41.91 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 15c65522-24fa-4b4d-9b33-0ab7e606bd74))
(pad "24" connect roundrect (at 44.45 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 2614eab2-50de-46b0-9eda-9ba6f3213d6f))
(pad "25" connect roundrect (at 46.99 4.953) (size 1.27 7.366) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.25) (tstamp 46087030-b1b4-416d-abb4-7e66dc5f5fa0))
(pad "26" connect roundrect (at 46.99 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp a7df7acc-f6e9-4422-bcc5-4de0be2fc24b))
(pad "27" connect roundrect (at 44.45 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 1cb90ce4-cf2a-4f56-afc5-1a491c09cd7f))
(pad "28" connect roundrect (at 41.91 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 7114252f-4490-4dce-982e-4accb431f84f))
(pad "29" connect roundrect (at 39.37 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp c31541b0-05b3-4f9a-a5ca-240448e17a33))
(pad "30" connect roundrect (at 36.83 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 66bc6277-2edc-41bc-8067-43e8d3ce64b9))
(pad "31" connect roundrect (at 34.29 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 299ed31b-8320-42e3-a997-78990b515eff))
(pad "32" connect roundrect (at 31.75 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp a37318fa-8dc9-42f8-88a1-5023278e8589))
(pad "33" connect roundrect (at 29.21 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 46a60137-2053-422a-b5c5-c89257ba074c))
(pad "34" connect roundrect (at 26.67 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 550b4c3d-d7ae-47ac-897c-516108b07dc8))
(pad "35" connect roundrect (at 24.13 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 2de4b987-0841-4651-8ab8-607d0e4adada))
(pad "36" connect roundrect (at 21.59 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp f69aac93-d3de-4f65-b6b0-69b31a1eeedd))
(pad "37" connect roundrect (at 19.05 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 2023edfa-31eb-4ce8-bbfb-1b3ee06a646a))
(pad "38" connect roundrect (at 16.51 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 3a86f6c2-5c5a-4a7c-bab3-4e0a21235fed))
(pad "39" connect roundrect (at 13.97 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp edca2338-bb9e-4ddb-83b5-70fb952eb8e5))
(pad "40" connect roundrect (at 11.43 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 58ad9e6b-87fb-406b-9e91-c79663704b5d))
(pad "41" connect roundrect (at 8.89 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 2c3c7953-603d-4b95-b24a-60ee04407d91))
(pad "42" connect roundrect (at 6.35 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 98e85eeb-6efa-4e41-bb87-9aec27e50a64))
(pad "43" connect roundrect (at 3.81 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp aba98e24-5e8c-466a-9a20-6fa6c73dbb88))
(pad "44" connect roundrect (at 1.27 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 313c8e97-968d-4155-bdc2-52451d165bb8))
(pad "45" connect roundrect (at -1.27 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp e78af261-e770-4c72-a0c3-180fe00974d2))
(pad "46" connect roundrect (at -3.81 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 26fa0e55-ded5-4fdc-9c3a-463e0e15d145))
(pad "47" connect roundrect (at -6.35 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp d204374d-427d-4184-8cac-34c3c45ae776))
(pad "48" connect roundrect (at -8.89 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 06b0de7a-8452-47e4-8156-099c9b3d0d4a))
(pad "49" connect roundrect (at -11.43 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp 7076fdf9-3d9e-46dc-8021-cde9c82fa64e))
(pad "50" connect roundrect (at -13.97 4.953) (size 1.27 7.366) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.25) (tstamp a35b849b-99f9-44ef-a71c-43032176d7da))
)

View File

@ -1,34 +1,30 @@
(module Capacitor (layer F.Cu) (tedit 5FEB5EFB)
(descr "C, Disc series, Radial, pin pitch=2.50mm, , diameter*width=3.8*2.6mm^2, Capacitor, http://www.vishay.com/docs/45233/krseries.pdf")
(tags "C Disc series Radial pin pitch 2.50mm diameter 3.8mm width 2.6mm Capacitor")
(fp_text reference C1 (at 1.25 2.54) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value C (at 1.25 2.55) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text user %R (at 1.25 0) (layer F.Fab)
(effects (font (size 0.76 0.76) (thickness 0.114)))
)
(fp_line (start 3.55 -1.55) (end -1.05 -1.55) (layer F.CrtYd) (width 0.05))
(fp_line (start 3.55 1.55) (end 3.55 -1.55) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.05 1.55) (end 3.55 1.55) (layer F.CrtYd) (width 0.05))
(fp_line (start -1.05 -1.55) (end -1.05 1.55) (layer F.CrtYd) (width 0.05))
(fp_line (start 3.27 0.795) (end 3.27 1.42) (layer F.Fab) (width 0.12))
(fp_line (start 3.27 -1.42) (end 3.27 -0.795) (layer F.Fab) (width 0.12))
(fp_line (start -0.77 0.795) (end -0.77 1.42) (layer F.Fab) (width 0.12))
(fp_line (start -0.77 -1.42) (end -0.77 -0.795) (layer F.Fab) (width 0.12))
(fp_line (start -0.77 1.42) (end 3.27 1.42) (layer F.Fab) (width 0.12))
(fp_line (start -0.77 -1.42) (end 3.27 -1.42) (layer F.Fab) (width 0.12))
(fp_line (start 3.15 -1.3) (end -0.65 -1.3) (layer F.Fab) (width 0.1))
(fp_line (start 3.15 1.3) (end 3.15 -1.3) (layer F.Fab) (width 0.1))
(fp_line (start -0.65 1.3) (end 3.15 1.3) (layer F.Fab) (width 0.1))
(fp_line (start -0.65 -1.3) (end -0.65 1.3) (layer F.Fab) (width 0.1))
(pad 2 thru_hole circle (at 2.5 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask))
(pad 1 thru_hole circle (at 0 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask))
(model ${KISYS3DMOD}/Capacitor_THT.3dshapes/C_Disc_D3.8mm_W2.6mm_P2.50mm.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(footprint "Capacitor" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 621265E2)
(descr "C, Disc series, Radial, pin pitch=2.50mm, , diameter*width=3.8*2.6mm^2, Capacitor, http://www.vishay.com/docs/45233/krseries.pdf")
(tags "C Disc series Radial pin pitch 2.50mm diameter 3.8mm width 2.6mm Capacitor")
(attr through_hole)
(fp_text reference "C1" (at 1.25 2.54) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp e8ef4bbd-32e2-4ac3-86d3-eb359b36bf42)
)
(fp_text value "C" (at 1.25 2.55) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp ea4f7bd6-6821-448f-bbec-c40ded7426db)
)
(fp_text user "${REFERENCE}" (at 1.25 0) (layer "F.Fab")
(effects (font (size 0.76 0.76) (thickness 0.114)))
(tstamp e52d9220-36a6-4a8e-857e-59c3f9659ebc)
)
(fp_line (start 3.302 0.762) (end 3.302 -0.762) (layer "F.CrtYd") (width 0.12) (tstamp 40b5ab29-6809-46de-9d87-b01ea9af4068))
(fp_line (start 3.302 -0.762) (end -0.762 -0.762) (layer "F.CrtYd") (width 0.12) (tstamp 4b724a05-e8b8-4d3a-9ef8-416f22a37460))
(fp_line (start -0.762 0.762) (end 3.302 0.762) (layer "F.CrtYd") (width 0.12) (tstamp 81c671aa-d366-46b3-8f86-ff2263cc045a))
(fp_line (start -0.762 -0.762) (end -0.762 0.762) (layer "F.CrtYd") (width 0.12) (tstamp a4f1e7d6-84c2-4bf5-a525-5b5c5d3f8486))
(pad "1" thru_hole circle (at 0 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask) (tstamp 3e8745f8-3055-487c-98b3-0d559c2ad40a))
(pad "2" thru_hole circle (at 2.5 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask) (tstamp 13b54699-28a1-4e4e-a982-18a5d294cbbd))
(model "${KISYS3DMOD}/Capacitor_THT.3dshapes/C_Disc_D3.8mm_W2.6mm_P2.50mm.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(5.1.10-1-10_14)*
G04 #@! TF.CreationDate,2021-07-20T17:57:18-04:00*
G04 #@! TF.ProjectId,Apple2IORPi,4170706c-6532-4494-9f52-50692e6b6963,0.4*
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.2-0)*
G04 #@! TF.CreationDate,2022-03-01T05:34:48-05:00*
G04 #@! TF.ProjectId,Apple2IORPi,4170706c-6532-4494-9f52-50692e6b6963,0.6*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Profile,NP*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (5.1.10-1-10_14)) date 2021-07-20 17:57:18*
G04 Created by KiCad (PCBNEW (6.0.2-0)) date 2022-03-01 05:34:48*
%MOMM*%
%LPD*%
G01*
@ -15,34 +15,34 @@ G04 #@! TA.AperFunction,Profile*
G04 #@! TD*
G04 APERTURE END LIST*
D10*
X193675000Y-42545000D02*
X193040000Y-41910000D01*
X193675000Y-111125000D02*
X193675000Y-42545000D01*
X104775000Y-41910000D02*
X193040000Y-41910000D01*
X104140000Y-42545000D02*
X104775000Y-41910000D01*
X122555000Y-111760000D02*
X122555000Y-118745000D01*
X104140000Y-111125000D02*
X104140000Y-42545000D01*
X104775000Y-111760000D02*
X104140000Y-111125000D01*
X193040000Y-111760000D02*
X193675000Y-111125000D01*
X193675000Y-111125000D02*
X193675000Y-42545000D01*
X108585000Y-111760000D02*
X122555000Y-111760000D01*
X193675000Y-42545000D02*
X193040000Y-41910000D01*
X108585000Y-111760000D02*
X104775000Y-111760000D01*
X123190000Y-119380000D02*
X186690000Y-119380000D01*
X104775000Y-41910000D02*
X193040000Y-41910000D01*
X122555000Y-118745000D02*
X123190000Y-119380000D01*
X122555000Y-111760000D02*
X122555000Y-118745000D01*
X108585000Y-111760000D02*
X122555000Y-111760000D01*
X193040000Y-111760000D02*
X193675000Y-111125000D01*
X187325000Y-111760000D02*
X193040000Y-111760000D01*
X187325000Y-118745000D02*
X187325000Y-111760000D01*
X186690000Y-119380000D02*
X187325000Y-118745000D01*
X187325000Y-118745000D02*
X187325000Y-111760000D01*
X187325000Y-111760000D02*
X193040000Y-111760000D01*
X104140000Y-42545000D02*
X104775000Y-41910000D01*
X104775000Y-111760000D02*
X104140000Y-111125000D01*
M02*

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
M48
; DRILL file {KiCad (5.1.10-1-10_14)} date Tuesday, July 20, 2021 at 05:57:21 PM
; DRILL file {KiCad (6.0.2-0)} date Tuesday, March 01, 2022 at 05:32:59 am
; FORMAT={-:-/ absolute / inch / decimal}
; #@! TF.CreationDate,2021-07-20T17:57:21-04:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(5.1.10-1-10_14)
; #@! TF.CreationDate,2022-03-01T05:32:59-05:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(6.0.2-0)
; #@! TF.FileFunction,NonPlated,1,2,NPTH
FMAT,2
INCH

View File

@ -1,13 +1,16 @@
M48
; DRILL file {KiCad (5.1.10-1-10_14)} date Tuesday, July 20, 2021 at 05:57:21 PM
; DRILL file {KiCad (6.0.2-0)} date Tuesday, March 01, 2022 at 05:32:59 am
; FORMAT={-:-/ absolute / inch / decimal}
; #@! TF.CreationDate,2021-07-20T17:57:21-04:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(5.1.10-1-10_14)
; #@! TF.CreationDate,2022-03-01T05:32:59-05:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(6.0.2-0)
; #@! TF.FileFunction,Plated,1,2,PTH
FMAT,2
INCH
; #@! TA.AperFunction,Plated,PTH,ViaDrill
T1C0.0197
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T2C0.0315
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T3C0.0394
%
G90
@ -40,7 +43,6 @@ X4.9468Y-2.449
X4.962Y-2.938
X4.981Y-2.644
X5.06Y-2.4625
X5.075Y-1.9005
X5.096Y-2.1255
X5.129Y-3.458
X5.15Y-1.926
@ -338,5 +340,7 @@ X4.45Y-3.66
X4.45Y-3.76
X4.45Y-3.86
X4.45Y-3.96
X4.626Y-4.122
X4.626Y-4.222
T0
M30

View File

@ -454,6 +454,27 @@ X ~ 2 0 -150 110 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Jumper_Jumper_2_Bridged
#
DEF Jumper_Jumper_2_Bridged JP 0 0 Y N 1 F N
F0 "JP" 0 75 50 H V C CNN
F1 "Jumper_Jumper_2_Bridged" 0 -100 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Jumper*
TestPoint*2Pads*
TestPoint*Bridge*
$ENDFPLIST
DRAW
A 0 -70 100 1269 531 0 1 0 N -60 10 60 10
C -80 0 20 0 0 0 N
C 80 0 20 0 0 0 N
X A 1 -200 0 100 R 50 50 1 1 P
X B 2 200 0 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Memory_EPROM_27C256
#
DEF Memory_EPROM_27C256 U 0 20 Y Y 1 F N

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_nets": [],
"high_contrast_mode": 1,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "00010f0_80000001",
"zone_display_mode": 1
},
"meta": {
"filename": "Apple2IORPi.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -0,0 +1,477 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.049999999999999996,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.12,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"filename": "board_design_settings.json",
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rule_severitieslegacy_courtyards_overlap": false,
"rule_severitieslegacy_no_courtyard_defined": false,
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.024999999999999998,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.17779999999999999,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"use_height_for_length_calcs": true
},
"track_widths": [],
"via_dimensions": [],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "Apple2IORPi.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.1778,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.1778,
"via_diameter": 0.762,
"via_drill": 0.50038,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.1778,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "3V3",
"nets": [],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.3556,
"via_diameter": 0.762,
"via_drill": 0.50038,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.254,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "5V",
"nets": [
"Net-(J1-Pad2)"
],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.8128,
"via_diameter": 0.762,
"via_drill": 0.7112,
"wire_width": 6.0
},
{
"bus_width": 12.0,
"clearance": 0.254,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Ground",
"nets": [],
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.8128,
"via_diameter": 0.762,
"via_drill": 0.7112,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "Apple2IORPi.net",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.25,
"pin_symbol_size": 0.0,
"text_offset_ratio": 0.08
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "Pcbnew",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "./",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"89e83c2e-e90a-4a50-b278-880bac0cfb49",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
(export (version D)
(design
(source /Users/terence/source/Apple2-IO-RPi/Hardware/Apple2IORPi.sch)
(date "Tuesday, July 20, 2021 at 05:16:50 pm")
(tool "Eeschema (5.1.10-1-10_14)")
(date "Wednesday, February 16, 2022 at 09:41:09 pm")
(tool "Eeschema (5.1.12-1-10_14)")
(sheet (number 1) (name /) (tstamps /)
(title_block
(title "Apple II I/O RPi")
(company "Terence J. Boldt")
(rev 1.0)
(date 2021-03-08)
(rev 6)
(date 2022-02-16)
(source Apple2IORPi.sch)
(comment (number 1) (value "Fourth Prototype"))
(comment (number 1) (value "Sixth Prototype"))
(comment (number 2) (value "Provides storage and network for the Apple ]["))
(comment (number 3) (value "Raspberry Pi Zero W as a daughter board"))
(comment (number 3) (value "Raspberry Pi Zero W 2 as a daughter board"))
(comment (number 4) (value "Expansion card for Apple ][ computers")))))
(components
(comp (ref J0)
@ -154,7 +154,14 @@
(datasheet ~)
(libsource (lib Device) (part C) (description "Unpolarized capacitor"))
(sheetpath (names /) (tstamps /))
(tstamp 60C3A67B)))
(tstamp 60C3A67B))
(comp (ref JPINTPWR1)
(value "Open for USB power, close for bus power")
(footprint Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical)
(datasheet ~)
(libsource (lib Jumper) (part Jumper_2_Bridged) (description "Jumper, 2-pole, closed/bridged"))
(sheetpath (names /) (tstamps /))
(tstamp 6215898B)))
(libparts
(libpart (lib 74xx) (part 74LS00)
(aliases
@ -395,6 +402,19 @@
(pins
(pin (num 1) (name ~) (type passive))
(pin (num 2) (name ~) (type passive))))
(libpart (lib Jumper) (part Jumper_2_Bridged)
(description "Jumper, 2-pole, closed/bridged")
(docs ~)
(footprints
(fp Jumper*)
(fp TestPoint*2Pads*)
(fp TestPoint*Bridge*))
(fields
(field (name Reference) JP)
(field (name Value) Jumper_2_Bridged))
(pins
(pin (num 1) (name A) (type passive))
(pin (num 2) (name B) (type passive))))
(libpart (lib Memory_EPROM) (part 27C256)
(aliases
(alias 27256))
@ -444,19 +464,21 @@
(uri "/Library/Application Support/kicad/library/Connector_Generic.lib"))
(library (logical Device)
(uri "/Library/Application Support/kicad/library/Device.lib"))
(library (logical Jumper)
(uri "/Library/Application Support/kicad/library/Jumper.lib"))
(library (logical Memory_EPROM)
(uri "/Library/Application Support/kicad/library/Memory_EPROM.lib")))
(nets
(net (code 1) (name "Net-(J0-Pad1)")
(node (ref J0) (pin 1))
(node (ref U1) (pin 20))
(node (ref U2) (pin 2)))
(node (ref U2) (pin 2))
(node (ref U1) (pin 20)))
(net (code 2) (name "Net-(J0-Pad10)")
(node (ref U1) (pin 25))
(node (ref J0) (pin 10)))
(node (ref J0) (pin 10))
(node (ref U1) (pin 25)))
(net (code 3) (name "Net-(J0-Pad12)")
(node (ref J0) (pin 12))
(node (ref U1) (pin 21)))
(node (ref U1) (pin 21))
(node (ref J0) (pin 12)))
(net (code 4) (name "Net-(J0-Pad13)")
(node (ref J0) (pin 13)))
(net (code 5) (name "Net-(J0-Pad14)")
@ -476,11 +498,11 @@
(net (code 12) (name "Net-(J0-Pad22)")
(node (ref J0) (pin 22)))
(net (code 13) (name "Net-(J0-Pad24)")
(node (ref J0) (pin 24))
(node (ref J0) (pin 27)))
(node (ref J0) (pin 27))
(node (ref J0) (pin 24)))
(net (code 14) (name "Net-(J0-Pad23)")
(node (ref J0) (pin 23))
(node (ref J0) (pin 28)))
(node (ref J0) (pin 28))
(node (ref J0) (pin 23)))
(net (code 15) (name "Net-(J0-Pad29)")
(node (ref J0) (pin 29)))
(net (code 16) (name "Net-(J0-Pad30)")
@ -508,8 +530,8 @@
(net (code 27) (name "Net-(J0-Pad50)")
(node (ref J0) (pin 50)))
(net (code 28) (name "Net-(J0-Pad6)")
(node (ref U1) (pin 6))
(node (ref J0) (pin 6)))
(node (ref J0) (pin 6))
(node (ref U1) (pin 6)))
(net (code 29) (name "Net-(J0-Pad7)")
(node (ref J0) (pin 7))
(node (ref U1) (pin 5)))
@ -523,14 +545,14 @@
(node (ref U0) (pin 2))
(node (ref J0) (pin 49)))
(net (code 33) (name "Net-(J0-Pad48)")
(node (ref U0) (pin 3))
(node (ref J0) (pin 48)))
(node (ref J0) (pin 48))
(node (ref U0) (pin 3)))
(net (code 34) (name "Net-(J0-Pad47)")
(node (ref J0) (pin 47))
(node (ref U0) (pin 4)))
(net (code 35) (name "Net-(J0-Pad46)")
(node (ref J0) (pin 46))
(node (ref U0) (pin 5)))
(node (ref U0) (pin 5))
(node (ref J0) (pin 46)))
(net (code 36) (name "Net-(J0-Pad45)")
(node (ref U0) (pin 6))
(node (ref J0) (pin 45)))
@ -544,39 +566,39 @@
(node (ref U0) (pin 9))
(node (ref J0) (pin 42)))
(net (code 40) (name "Net-(U3-Pad3)")
(node (ref U4) (pin 19))
(node (ref U3) (pin 3)))
(node (ref U3) (pin 3))
(node (ref U4) (pin 19)))
(net (code 41) (name "Net-(J1-Pad10)")
(node (ref U7) (pin 6))
(node (ref J1) (pin 10)))
(node (ref J1) (pin 10))
(node (ref U7) (pin 6)))
(net (code 42) (name "Net-(J1-Pad13)")
(node (ref J1) (pin 13))
(node (ref U4) (pin 16)))
(net (code 43) (name "Net-(J1-Pad15)")
(node (ref U4) (pin 15))
(node (ref J1) (pin 15)))
(node (ref J1) (pin 15))
(node (ref U4) (pin 15)))
(net (code 44) (name "Net-(J1-Pad19)")
(node (ref U4) (pin 14))
(node (ref J1) (pin 19)))
(node (ref J1) (pin 19))
(node (ref U4) (pin 14)))
(net (code 45) (name "Net-(J1-Pad21)")
(node (ref U4) (pin 13))
(node (ref J1) (pin 21)))
(node (ref J1) (pin 21))
(node (ref U4) (pin 13)))
(net (code 46) (name "Net-(J1-Pad23)")
(node (ref U4) (pin 12))
(node (ref J1) (pin 23)))
(net (code 47) (name "Net-(J1-Pad24)")
(node (ref J1) (pin 24))
(node (ref U6) (pin 13)))
(node (ref U6) (pin 13))
(node (ref J1) (pin 24)))
(net (code 48) (name "Net-(J1-Pad26)")
(node (ref J1) (pin 26))
(node (ref U6) (pin 14)))
(node (ref U6) (pin 14))
(node (ref J1) (pin 26)))
(net (code 49) (name "Net-(J1-Pad27)")
(node (ref J1) (pin 27)))
(net (code 50) (name "Net-(J1-Pad28)")
(node (ref J1) (pin 28)))
(net (code 51) (name "Net-(J1-Pad29)")
(node (ref J1) (pin 29))
(node (ref U4) (pin 11)))
(node (ref U4) (pin 11))
(node (ref J1) (pin 29)))
(net (code 52) (name "Net-(J1-Pad3)")
(node (ref J1) (pin 3)))
(net (code 53) (name "Net-(J1-Pad31)")
@ -586,17 +608,17 @@
(node (ref U5) (pin 19))
(node (ref J1) (pin 32)))
(net (code 55) (name "Net-(J1-Pad36)")
(node (ref J1) (pin 36))
(node (ref U5) (pin 16)))
(node (ref U5) (pin 16))
(node (ref J1) (pin 36)))
(net (code 56) (name "Net-(J1-Pad37)")
(node (ref J1) (pin 37))
(node (ref U5) (pin 9)))
(node (ref U5) (pin 9))
(node (ref J1) (pin 37)))
(net (code 57) (name "Net-(J1-Pad38)")
(node (ref J1) (pin 38))
(node (ref U5) (pin 15)))
(net (code 58) (name "Net-(J1-Pad40)")
(node (ref J1) (pin 40))
(node (ref U5) (pin 12)))
(node (ref U5) (pin 12))
(node (ref J1) (pin 40)))
(net (code 59) (name "Net-(J1-Pad5)")
(node (ref J1) (pin 5)))
(net (code 60) (name "Net-(J1-Pad7)")
@ -609,14 +631,14 @@
(node (ref U1) (pin 24))
(node (ref J0) (pin 11)))
(net (code 63) (name "Net-(J1-Pad11)")
(node (ref U4) (pin 17))
(node (ref J1) (pin 11)))
(node (ref J1) (pin 11))
(node (ref U4) (pin 17)))
(net (code 64) (name "Net-(J1-Pad33)")
(node (ref U5) (pin 5))
(node (ref J1) (pin 33)))
(node (ref J1) (pin 33))
(node (ref U5) (pin 5)))
(net (code 65) (name "Net-(J1-Pad35)")
(node (ref J1) (pin 35))
(node (ref U5) (pin 6)))
(node (ref U5) (pin 6))
(node (ref J1) (pin 35)))
(net (code 66) (name "Net-(J0-Pad2)")
(node (ref U3) (pin 5))
(node (ref J0) (pin 2))
@ -625,51 +647,51 @@
(node (ref U3) (pin 6))
(node (ref U3) (pin 1)))
(net (code 68) (name "Net-(U3-Pad10)")
(node (ref U3) (pin 10))
(node (ref U3) (pin 11)))
(node (ref U3) (pin 11))
(node (ref U3) (pin 10)))
(net (code 69) (name "Net-(U3-Pad8)")
(node (ref U5) (pin 11))
(node (ref U3) (pin 8)))
(net (code 70) (name "Net-(J0-Pad41)")
(node (ref U3) (pin 9))
(node (ref U2) (pin 1))
(node (ref U8) (pin 4))
(node (ref U3) (pin 2))
(node (ref U8) (pin 1))
(node (ref J0) (pin 41)))
(node (ref J0) (pin 41))
(node (ref U3) (pin 2))
(node (ref U2) (pin 1))
(node (ref U3) (pin 9)))
(net (code 71) (name "Net-(J0-Pad3)")
(node (ref J0) (pin 3))
(node (ref U1) (pin 9))
(node (ref J0) (pin 3))
(node (ref U3) (pin 13)))
(net (code 72) (name "Net-(U2-Pad3)")
(node (ref U2) (pin 3))
(node (ref U2) (pin 5))
(node (ref U2) (pin 4))
(node (ref U2) (pin 3)))
(node (ref U2) (pin 4)))
(net (code 73) (name "Net-(U0-Pad19)")
(node (ref U0) (pin 19))
(node (ref U2) (pin 6)))
(net (code 74) (name "Net-(U0-Pad1)")
(node (ref U8) (pin 9))
(node (ref U0) (pin 1))
(node (ref U2) (pin 10))
(node (ref U2) (pin 9))
(node (ref U1) (pin 22))
(node (ref U0) (pin 1))
(node (ref U2) (pin 11))
(node (ref U2) (pin 9))
(node (ref U2) (pin 10))
(node (ref U3) (pin 4)))
(net (code 75) (name "Net-(J0-Pad18)")
(node (ref U2) (pin 13))
(node (ref U2) (pin 12))
(node (ref J0) (pin 18)))
(node (ref J0) (pin 18))
(node (ref U2) (pin 12)))
(net (code 76) (name "Net-(U1-Pad1)")
(node (ref U1) (pin 1)))
(net (code 77) (name "Net-(U1-Pad26)")
(node (ref U1) (pin 26)))
(net (code 78) (name "Net-(J1-Pad18)")
(node (ref U6) (pin 11))
(node (ref J1) (pin 18)))
(node (ref J1) (pin 18))
(node (ref U6) (pin 11)))
(net (code 79) (name "Net-(J1-Pad22)")
(node (ref U6) (pin 12))
(node (ref J1) (pin 22)))
(node (ref J1) (pin 22))
(node (ref U6) (pin 12)))
(net (code 80) (name "Net-(U6-Pad15)")
(node (ref U6) (pin 15)))
(net (code 81) (name "Net-(U6-Pad16)")
@ -679,156 +701,159 @@
(net (code 83) (name "Net-(U6-Pad18)")
(node (ref U6) (pin 18)))
(net (code 84) (name "Net-(U0-Pad16)")
(node (ref U1) (pin 13))
(node (ref U4) (pin 4))
(node (ref U7) (pin 7))
(node (ref U6) (pin 4))
(node (ref U0) (pin 16))
(node (ref U1) (pin 13))
(node (ref U6) (pin 4))
(node (ref U7) (pin 7))
(node (ref U5) (pin 7)))
(net (code 85) (name "Net-(U0-Pad11)")
(node (ref U5) (pin 18))
(node (ref U0) (pin 11))
(node (ref U1) (pin 19))
(node (ref U0) (pin 11))
(node (ref U7) (pin 18))
(node (ref U6) (pin 9))
(node (ref U4) (pin 9)))
(node (ref U4) (pin 9))
(node (ref U6) (pin 9)))
(net (code 86) (name "Net-(U1-Pad23)")
(node (ref U7) (pin 12))
(node (ref U1) (pin 23)))
(node (ref U1) (pin 23))
(node (ref U7) (pin 12)))
(net (code 87) (name "Net-(U0-Pad14)")
(node (ref U4) (pin 6))
(node (ref U7) (pin 13))
(node (ref U0) (pin 14))
(node (ref U5) (pin 13))
(node (ref U1) (pin 16))
(node (ref U6) (pin 6)))
(node (ref U4) (pin 6))
(node (ref U5) (pin 13))
(node (ref U6) (pin 6))
(node (ref U0) (pin 14)))
(net (code 88) (name "Net-(U0-Pad13)")
(node (ref U0) (pin 13))
(node (ref U6) (pin 7))
(node (ref U7) (pin 14))
(node (ref U1) (pin 17))
(node (ref U4) (pin 7))
(node (ref U6) (pin 7))
(node (ref U5) (pin 14)))
(net (code 89) (name "Net-(U7-Pad16)")
(node (ref U7) (pin 16)))
(net (code 90) (name "Net-(U0-Pad12)")
(node (ref U6) (pin 8))
(node (ref U0) (pin 12))
(node (ref U4) (pin 8))
(node (ref U7) (pin 17))
(node (ref U1) (pin 18))
(node (ref U5) (pin 17)))
(node (ref U5) (pin 17))
(node (ref U6) (pin 8))
(node (ref U7) (pin 17))
(node (ref U4) (pin 8))
(node (ref U0) (pin 12)))
(net (code 91) (name "Net-(U7-Pad19)")
(node (ref U7) (pin 19)))
(net (code 92) (name "Net-(J1-Pad16)")
(node (ref U7) (pin 2))
(node (ref J1) (pin 16)))
(node (ref J1) (pin 16))
(node (ref U7) (pin 2)))
(net (code 93) (name "Net-(U0-Pad18)")
(node (ref U4) (pin 2))
(node (ref U6) (pin 2))
(node (ref U0) (pin 18))
(node (ref U1) (pin 11))
(node (ref U5) (pin 3))
(node (ref U7) (pin 3)))
(node (ref U7) (pin 3))
(node (ref U0) (pin 18))
(node (ref U6) (pin 2))
(node (ref U5) (pin 3)))
(net (code 94) (name "Net-(U0-Pad17)")
(node (ref U0) (pin 17))
(node (ref U4) (pin 3))
(node (ref U7) (pin 4))
(node (ref U5) (pin 4))
(node (ref U1) (pin 12))
(node (ref U0) (pin 17))
(node (ref U6) (pin 3))
(node (ref U4) (pin 3)))
(node (ref U1) (pin 12)))
(net (code 95) (name "Net-(J1-Pad12)")
(node (ref J1) (pin 12))
(node (ref U7) (pin 5)))
(net (code 96) (name "Net-(U0-Pad15)")
(node (ref U0) (pin 15))
(node (ref U4) (pin 5))
(node (ref U6) (pin 5))
(node (ref U1) (pin 15))
(node (ref U5) (pin 8))
(node (ref U7) (pin 8))
(node (ref U4) (pin 5)))
(node (ref U5) (pin 8)))
(net (code 97) (name "Net-(U1-Pad2)")
(node (ref U7) (pin 15))
(node (ref U1) (pin 2)))
(net (code 98) (name "Net-(C5-Pad1)")
(node (ref U4) (pin 20))
(node (ref C6) (pin 1))
(node (ref C5) (pin 1))
(node (ref J1) (pin 1))
(node (ref U6) (pin 20))
(node (ref J1) (pin 17))
(node (ref U5) (pin 20))
(node (ref U7) (pin 20))
(node (ref U6) (pin 20))
(node (ref U4) (pin 20))
(node (ref J1) (pin 1))
(node (ref J1) (pin 17))
(node (ref C5) (pin 1))
(node (ref C8) (pin 1))
(node (ref C7) (pin 1)))
(net (code 99) (name "Net-(C1-Pad1)")
(node (ref J0) (pin 25))
(node (ref U2) (pin 14))
(node (ref U3) (pin 14))
(node (ref U0) (pin 20))
(node (ref J1) (pin 2))
(node (ref U1) (pin 28))
(node (ref C3) (pin 1))
(node (ref U8) (pin 14))
(node (ref C9) (pin 1))
(node (ref C4) (pin 1))
(node (ref J1) (pin 4))
(node (ref C2) (pin 1))
(node (ref C1) (pin 1)))
(net (code 100) (name "Net-(U6-Pad19)")
(node (ref U6) (pin 19))
(node (ref U8) (pin 3)))
(net (code 101) (name "Net-(U7-Pad11)")
(node (ref C7) (pin 1))
(node (ref U5) (pin 20)))
(net (code 99) (name "Net-(U6-Pad19)")
(node (ref U8) (pin 3))
(node (ref U6) (pin 19)))
(net (code 100) (name "Net-(U7-Pad11)")
(node (ref U8) (pin 6))
(node (ref U7) (pin 11)))
(net (code 102) (name "Net-(J0-Pad4)")
(net (code 101) (name "Net-(J0-Pad4)")
(node (ref U8) (pin 10))
(node (ref J0) (pin 4))
(node (ref U1) (pin 8)))
(net (code 103) (name "Net-(U8-Pad2)")
(node (ref U8) (pin 2))
(node (ref U8) (pin 8)))
(net (code 104) (name "Net-(U8-Pad11)")
(node (ref U1) (pin 8))
(node (ref J0) (pin 4)))
(net (code 102) (name "Net-(U8-Pad2)")
(node (ref U8) (pin 8))
(node (ref U8) (pin 2)))
(net (code 103) (name "Net-(U8-Pad11)")
(node (ref U8) (pin 11))
(node (ref U8) (pin 5)))
(net (code 105) (name "Net-(J0-Pad5)")
(net (code 104) (name "Net-(J0-Pad5)")
(node (ref U8) (pin 13))
(node (ref U1) (pin 7))
(node (ref J0) (pin 5))
(node (ref U8) (pin 13)))
(net (code 106) (name "Net-(C1-Pad2)")
(node (ref U2) (pin 7))
(node (ref C2) (pin 2))
(node (ref J0) (pin 26))
(node (ref U3) (pin 7))
(node (ref C8) (pin 2))
(node (ref C7) (pin 2))
(node (ref U8) (pin 7))
(node (ref U7) (pin 10))
(node (ref U0) (pin 10))
(node (ref C9) (pin 2))
(node (ref C3) (pin 2))
(node (ref C4) (pin 2))
(node (ref C1) (pin 2))
(node (ref C5) (pin 2))
(node (ref J0) (pin 5)))
(net (code 105) (name "Net-(C1-Pad2)")
(node (ref C6) (pin 2))
(node (ref U5) (pin 10))
(node (ref U5) (pin 1))
(node (ref J1) (pin 9))
(node (ref J1) (pin 6))
(node (ref C5) (pin 2))
(node (ref J0) (pin 26))
(node (ref C1) (pin 2))
(node (ref U7) (pin 10))
(node (ref C2) (pin 2))
(node (ref U7) (pin 1))
(node (ref C4) (pin 2))
(node (ref U0) (pin 10))
(node (ref C3) (pin 2))
(node (ref U4) (pin 1))
(node (ref U4) (pin 10))
(node (ref U3) (pin 7))
(node (ref U2) (pin 7))
(node (ref J1) (pin 14))
(node (ref U6) (pin 10))
(node (ref U6) (pin 1))
(node (ref J1) (pin 20))
(node (ref J1) (pin 39))
(node (ref J1) (pin 34))
(node (ref J1) (pin 30))
(node (ref U1) (pin 14))
(node (ref J1) (pin 25))
(node (ref U6) (pin 1)))
(net (code 107) (name "Net-(U1-Pad27)")
(node (ref U1) (pin 27))
(node (ref U8) (pin 12))
(node (ref U1) (pin 14))
(node (ref J1) (pin 30))
(node (ref C8) (pin 2))
(node (ref C7) (pin 2))
(node (ref J1) (pin 34))
(node (ref J1) (pin 39))
(node (ref J1) (pin 6))
(node (ref U8) (pin 7))
(node (ref J1) (pin 9))
(node (ref U5) (pin 1))
(node (ref C9) (pin 2))
(node (ref U5) (pin 10)))
(net (code 106) (name "Net-(U1-Pad27)")
(node (ref U2) (pin 8))
(node (ref U3) (pin 12))
(node (ref U2) (pin 8)))))
(node (ref U1) (pin 27))
(node (ref U8) (pin 12)))
(net (code 107) (name "Net-(C1-Pad1)")
(node (ref JPINTPWR1) (pin 1))
(node (ref U8) (pin 14))
(node (ref C9) (pin 1))
(node (ref U1) (pin 28))
(node (ref U2) (pin 14))
(node (ref U3) (pin 14))
(node (ref C3) (pin 1))
(node (ref U0) (pin 20))
(node (ref C4) (pin 1))
(node (ref C2) (pin 1))
(node (ref C1) (pin 1))
(node (ref J0) (pin 25)))
(net (code 108) (name "Net-(J1-Pad2)")
(node (ref J1) (pin 2))
(node (ref J1) (pin 4))
(node (ref JPINTPWR1) (pin 2)))))

Binary file not shown.

View File

@ -1,281 +0,0 @@
update=Friday, March 12, 2021 at 10:10:03 am
version=1
last_client=kicad
[general]
version=1
RootSch=
BoardNm=
[cvpcb]
version=1
NetIExt=net
[eeschema]
version=1
LibDir=
[eeschema/libraries]
[schematic_editor]
version=1
PageLayoutDescrFile=
PlotDirectoryName=./
SubpartIdSeparator=0
SubpartFirstId=65
NetFmtName=Pcbnew
SpiceAjustPassiveValues=0
LabSize=50
ERC_TestSimilarLabels=1
[pcbnew]
version=1
PageLayoutDescrFile=
LastNetListRead=Apple2IORPi.net
CopperLayerCount=2
BoardThickness=1.6
AllowMicroVias=0
AllowBlindVias=0
RequireCourtyardDefinitions=0
ProhibitOverlappingCourtyards=0
MinTrackWidth=0.1778
MinViaDiameter=0.4
MinViaDrill=0.3
MinMicroViaDiameter=0.2
MinMicroViaDrill=0.09999999999999999
MinHoleToHole=0.25
TrackWidth1=0.1778
ViaDiameter1=0.762
ViaDrill1=0.50038
dPairWidth1=0.2
dPairGap1=0.25
dPairViaGap1=0.25
SilkLineWidth=0.12
SilkTextSizeV=1
SilkTextSizeH=1
SilkTextSizeThickness=0.15
SilkTextItalic=0
SilkTextUpright=1
CopperLineWidth=0.2
CopperTextSizeV=1.5
CopperTextSizeH=1.5
CopperTextThickness=0.3
CopperTextItalic=0
CopperTextUpright=1
EdgeCutLineWidth=0.05
CourtyardLineWidth=0.05
OthersLineWidth=0.15
OthersTextSizeV=1
OthersTextSizeH=1
OthersTextSizeThickness=0.15
OthersTextItalic=0
OthersTextUpright=1
SolderMaskClearance=0
SolderMaskMinWidth=0
SolderPasteClearance=0
SolderPasteRatio=-0
[pcbnew/Layer.F.Cu]
Name=F.Cu
Type=0
Enabled=1
[pcbnew/Layer.In1.Cu]
Name=In1.Cu
Type=0
Enabled=0
[pcbnew/Layer.In2.Cu]
Name=In2.Cu
Type=0
Enabled=0
[pcbnew/Layer.In3.Cu]
Name=In3.Cu
Type=0
Enabled=0
[pcbnew/Layer.In4.Cu]
Name=In4.Cu
Type=0
Enabled=0
[pcbnew/Layer.In5.Cu]
Name=In5.Cu
Type=0
Enabled=0
[pcbnew/Layer.In6.Cu]
Name=In6.Cu
Type=0
Enabled=0
[pcbnew/Layer.In7.Cu]
Name=In7.Cu
Type=0
Enabled=0
[pcbnew/Layer.In8.Cu]
Name=In8.Cu
Type=0
Enabled=0
[pcbnew/Layer.In9.Cu]
Name=In9.Cu
Type=0
Enabled=0
[pcbnew/Layer.In10.Cu]
Name=In10.Cu
Type=0
Enabled=0
[pcbnew/Layer.In11.Cu]
Name=In11.Cu
Type=0
Enabled=0
[pcbnew/Layer.In12.Cu]
Name=In12.Cu
Type=0
Enabled=0
[pcbnew/Layer.In13.Cu]
Name=In13.Cu
Type=0
Enabled=0
[pcbnew/Layer.In14.Cu]
Name=In14.Cu
Type=0
Enabled=0
[pcbnew/Layer.In15.Cu]
Name=In15.Cu
Type=0
Enabled=0
[pcbnew/Layer.In16.Cu]
Name=In16.Cu
Type=0
Enabled=0
[pcbnew/Layer.In17.Cu]
Name=In17.Cu
Type=0
Enabled=0
[pcbnew/Layer.In18.Cu]
Name=In18.Cu
Type=0
Enabled=0
[pcbnew/Layer.In19.Cu]
Name=In19.Cu
Type=0
Enabled=0
[pcbnew/Layer.In20.Cu]
Name=In20.Cu
Type=0
Enabled=0
[pcbnew/Layer.In21.Cu]
Name=In21.Cu
Type=0
Enabled=0
[pcbnew/Layer.In22.Cu]
Name=In22.Cu
Type=0
Enabled=0
[pcbnew/Layer.In23.Cu]
Name=In23.Cu
Type=0
Enabled=0
[pcbnew/Layer.In24.Cu]
Name=In24.Cu
Type=0
Enabled=0
[pcbnew/Layer.In25.Cu]
Name=In25.Cu
Type=0
Enabled=0
[pcbnew/Layer.In26.Cu]
Name=In26.Cu
Type=0
Enabled=0
[pcbnew/Layer.In27.Cu]
Name=In27.Cu
Type=0
Enabled=0
[pcbnew/Layer.In28.Cu]
Name=In28.Cu
Type=0
Enabled=0
[pcbnew/Layer.In29.Cu]
Name=In29.Cu
Type=0
Enabled=0
[pcbnew/Layer.In30.Cu]
Name=In30.Cu
Type=0
Enabled=0
[pcbnew/Layer.B.Cu]
Name=B.Cu
Type=0
Enabled=1
[pcbnew/Layer.B.Adhes]
Enabled=1
[pcbnew/Layer.F.Adhes]
Enabled=1
[pcbnew/Layer.B.Paste]
Enabled=1
[pcbnew/Layer.F.Paste]
Enabled=1
[pcbnew/Layer.B.SilkS]
Enabled=1
[pcbnew/Layer.F.SilkS]
Enabled=1
[pcbnew/Layer.B.Mask]
Enabled=1
[pcbnew/Layer.F.Mask]
Enabled=1
[pcbnew/Layer.Dwgs.User]
Enabled=1
[pcbnew/Layer.Cmts.User]
Enabled=1
[pcbnew/Layer.Eco1.User]
Enabled=1
[pcbnew/Layer.Eco2.User]
Enabled=1
[pcbnew/Layer.Edge.Cuts]
Enabled=1
[pcbnew/Layer.Margin]
Enabled=1
[pcbnew/Layer.B.CrtYd]
Enabled=1
[pcbnew/Layer.F.CrtYd]
Enabled=1
[pcbnew/Layer.B.Fab]
Enabled=1
[pcbnew/Layer.F.Fab]
Enabled=1
[pcbnew/Layer.Rescue]
Enabled=0
[pcbnew/Netclasses]
[pcbnew/Netclasses/Default]
Name=Default
Clearance=0.1778
TrackWidth=0.1778
ViaDiameter=0.762
ViaDrill=0.50038
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/1]
Name=3V3
Clearance=0.1778
TrackWidth=0.3556
ViaDiameter=0.762
ViaDrill=0.50038
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/2]
Name=5V
Clearance=0.254
TrackWidth=0.8128
ViaDiameter=0.762
ViaDrill=0.7112
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/3]
Name=Ground
Clearance=0.254
TrackWidth=0.8128
ViaDiameter=0.762
ViaDrill=0.7112
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 254 KiB

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.

File diff suppressed because it is too large Load Diff

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

23
PicoSetup.md Normal file
View File

@ -0,0 +1,23 @@
## Setup starting from scratch
1. DIY instructions and PCB coming but it is recommended to buy a board from Ralle Palaveev
2. Attach Raspberry Pi Zero 2 W with a micro USB OTG cable
3. Install [Raspberry Pi OS](https://www.raspberrypi.org/software/) on microSD card using a modern computer
1. Use Raspberry Pi Imager
2. Click "Choose OS"
3. Select Other => "Raspberry Pi OS Lite (64 bit)" for the Zero 2 W
4. Click on the gear icon in the bottom right
5. Enable ssh
6. Set password
7. Configure wifi
8. Set locale settings
6. Put microSD card in the RPi
7. Install the expansion card into the Apple II
8. Power on the Apple II
9. Use `ssh` to connect to the RPi using the password you configured
10. `wget --no-cache -O - https://raw.githubusercontent.com/tjboldt/Apple2-IO-RPi/main/RaspberryPi/setup.sh 1 | bash`
## Options
You can support two drives and change their drive images.
1. Modify the `ExecStart` line in `/etc/systemd/system/apple2driver.service` and make it something like the following: `ExecStart=/home/pi/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver -cdc=true -d1 /home/pi/Apple2-IO-RPi/RaspberryPi/Apple2-IO-RPi.hdv -d2 /home/pi/Apple2-IO-RPi/RaspberryPi/TotalReplay401.hdv`
2. `sudo systemctl daemon-reload`
3. `sudo systemctl restart apple2driver.service`

View File

@ -4,35 +4,51 @@ Apple II expansion card using a Raspberry Pi for I/O
![Image of Board](/Hardware/Apple2IORPi.jpg)
## Purpose
The purpose of this project is to provide I/O for an Apple II series 8 bit computer via a Raspberry Pi Zero W which is powered by the Apple II expansion bus. This includes using the attached RPi Zero W for it's storage, network and processor to provide new functionality for the Apple II.
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.
## 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 (temporarily removed from firmware but will come back as a utility or dynamic virtual drive
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 /"`
## Project Status
So far, this is a project and not a finished product. The current prototype is on the fifth revision and about 20 have been assembled and tested. It is now possible for 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 about 1/4 of all available power to the expansion slots when idle and close to all available power when busy. It is not recommended to have a lot of other cards in the system at the same time. 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.
### 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.
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.
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.
### 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. This uses Oliver Schmidt's PIO code.
## Roadmap
1. Allow more than two virtual hard drives at a time
2. In-memory virtual drive representing current working directory in Linux for ease of copying files between Linux and ProDOS
3. Update GPIO library to reduce power consumption (remove busy-wait loops and use edge triggering)
4. Proper ProDOS clock driver (currently just directly sets values on block reads)
5. Bi-directional image conversion between common formats and HIRES
6. Remote code execution
7. Proxy VNC connection, rendering as Apple II compatible graphics
See [List of issues tagged roadmap](https://github.com/tjboldt/Apple2-IO-RPi/issues?q=is%3Aissue+is%3Aopen+label%3Aroadmap+author%3Atjboldt)
## Setup
[Setup card from scratch](https://github.com/tjboldt/Apple2-IO-RPi/discussions/63)
[Setup if you received a complete board from me](https://github.com/tjboldt/Apple2-IO-RPi/discussions/64)
## Setup on classic hardware
[Setup card from scratch](/ClassicSetup.md)
[Update to latest](https://github.com/tjboldt/Apple2-IO-RPi/discussions/65)
## Setup on Pico based hardware
[Setup card with Pico hardware](/PicoSetup.md)
## 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

@ -0,0 +1,151 @@
// Copyright Terence J. Boldt (c)2020-2022
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
// This file is used for communicating with the Apple II data bus via the
// GPIO ports on the Raspberry Pi
package a2io
import (
"bytes"
"errors"
"fmt"
"strings"
"time"
"go.bug.st/serial"
"go.bug.st/serial/enumerator"
)
var port serial.Port
// CDCio is a live implementation of A2Io interface
type CDCio struct {
}
// Init initializes the CDC driver on the Raspberry Pi
func (a2 CDCio) Init() {
name := ""
for {
portInfos, err := enumerator.GetDetailedPortsList()
if err == nil {
for _, portInfo := range portInfos {
if portInfo.IsUSB &&
strings.ToUpper(portInfo.VID) == "2E8A" &&
strings.ToUpper(portInfo.PID) == "000A" {
name = portInfo.Name
fmt.Printf("Found CDC port %s\n", name)
break
}
}
if name != "" {
break
}
}
time.Sleep(time.Millisecond)
}
for {
var err error
port, err = serial.Open(name, &serial.Mode{})
if err == nil {
break
}
var portErr *serial.PortError
if !errors.As(err, &portErr) ||
portErr.Code() != serial.PortNotFound &&
portErr.Code() != serial.PermissionDenied {
panic(err)
}
time.Sleep(time.Millisecond)
}
err := port.SetReadTimeout(time.Second)
if err != nil {
panic(err)
}
}
// ReadByte reads a byte from the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) ReadByte(noDelay ...bool) (byte, error) {
var data [1]byte
n, err := port.Read(data[:])
if err != nil {
return 0, err
}
if n == 0 {
return 0, errors.New("timed out reading byte")
}
return data[0], nil
}
// WriteByte writes a byte to the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) WriteByte(data byte) error {
_, err := port.Write([]byte{data})
return err
}
// ReadString reads a string from the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) ReadString() (string, error) {
var inBytes bytes.Buffer
for {
inByte, err := a2.ReadByte()
if err != nil {
return "", err
}
if inByte == 0 {
break
}
inBytes.WriteByte(inByte)
}
return inBytes.String(), nil
}
// WriteString writes a string to the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) WriteString(outString string) error {
for _, character := range outString {
err := a2.WriteByte(byte(character) | 128)
if err != nil {
fmt.Printf("Failed to write string\n")
return err
}
}
a2.WriteByte(0)
return nil
}
// WriteBlock writes 512 bytes to the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) WriteBlock(buffer []byte) error {
_, err := port.Write(buffer)
return err
}
// ReadBlock reads 512 bytes from the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) ReadBlock(buffer []byte) error {
var err error
for i := 0; i < 512; i++ {
buffer[i], err = a2.ReadByte()
if err != nil {
return err
}
}
return nil
}
// WriteBuffer writes a buffer of bytes to the Apple II via Raspberry Pi's CDC driver
func (a2 CDCio) WriteBuffer(buffer []byte) error {
_, err := port.Write(buffer)
return err
}
// SendCharacter is a pass-through to vt100 implementation
func (a2 CDCio) SendCharacter(character byte) {
sendCharacter(a2, character)
}
// ReadCharacter is a pass-through to vt100 implementation
func (a2 CDCio) ReadCharacter() (string, error) {
return readCharacter(a2)
}

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.
@ -14,6 +14,7 @@ var escapeSequence string
var operatingSystemSequence bool
var windowTop int
var windowBottom = 23
var applicationMode = false
func sendCharacter(comm A2Io, b byte) {
if b == 0x1b {
@ -63,11 +64,11 @@ func sendCharacter(comm A2Io, b byte) {
switch escapeSequence {
// Set/clear application mode for cursor
case "^[[?1h":
//applicationMode = true
applicationMode = true
escapeSequence = ""
return
case "^[[?1l":
//applicationMode = false
applicationMode = false
comm.WriteByte('T')
comm.WriteByte(0x00)
comm.WriteByte('B')
@ -219,20 +220,35 @@ 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 {
switch b {
case 0x0b: // up
s = "\033[A"
case 0x0a: // down
s = "\033[B"
case 0x15: // right
s = "\033[C"
case 0x08: // left
s = "\033[D"
case 0x0d: // return
s = string(byte(0x0a))
if applicationMode {
switch b {
case 0x0b: // up
s = "\033OA"
case 0x0a: // down
s = "\033OB"
case 0x15: // right
s = "\033OC"
case 0x08: // left
s = "\033OD"
case 0x0d: // return
s = string(byte(0x0d))
}
} else {
switch b {
case 0x0b: // up
s = "\033[A"
case 0x0a: // down
s = "\033[B"
case 0x15: // right
s = "\033[C"
case 0x08: // left
s = "\033[D"
case 0x0d: // return
s = string(byte(0x0d))
}
}
}
return s, err

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.
@ -9,15 +9,20 @@
package main
import (
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"time"
"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
@ -32,24 +37,34 @@ const menuCommand = 8
const shellCommand = 9
func main() {
drive1, drive2 := getDriveFiles()
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)
comm := a2io.A2Gpio{}
var comm a2io.A2Io
if cdc {
comm = a2io.CDCio{}
fmt.Printf("Starting communications via serial port...\n")
} else {
comm = a2io.A2Gpio{}
fmt.Printf("Starting communications via GPIO ports...\n")
}
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()
@ -60,7 +75,7 @@ func main() {
case getTimeCommand:
handlers.GetTimeCommand()
case execCommand:
handlers.ExecCommand()
handlers.ExecCommand(&drive1, &drive2)
case loadFileCommand:
handlers.LoadFileCommand()
case menuCommand:
@ -68,62 +83,66 @@ func main() {
case shellCommand:
handlers.ShellCommand()
}
// the A2Io interface should be extended in one way or another
// 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 getDriveFiles() (*os.File, *os.File) {
func getFlags() (string, string, bool) {
var drive1Name string
var drive2Name string
var cdc bool
execName, _ := os.Executable()
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
}
func logAndExitOnErr(err error) {
if err != nil {
fmt.Printf("ERROR: %s", err.Error())
os.Exit(1)
}
}

View File

@ -3,7 +3,9 @@ module github.com/tjboldt/Apple2-IO-RPi/RaspberryPi/apple2driver
go 1.16
require (
github.com/creack/pty v1.1.17
github.com/creack/pty v1.1.21
github.com/stianeikeland/go-rpio/v4 v4.6.0
github.com/tjboldt/ProDOS-Utilities v0.0.0-20210607001541-fa0e76cf84c0
github.com/tjboldt/ProDOS-Utilities v0.4.9
go.bug.st/serial v1.6.1
golang.org/x/sys v0.16.0 // indirect
)

View File

@ -1,6 +1,56 @@
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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.0.0-20210607001541-fa0e76cf84c0 h1:iH6+15jJQsUMv9yeC5m26qh8VdJeRmZiYGM1ZG4aLVI=
github.com/tjboldt/ProDOS-Utilities v0.0.0-20210607001541-fa0e76cf84c0/go.mod h1:eBQRf0U+goRbBOxzFCwRW+FZmALC8dfYaqCwcqwzi74=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tjboldt/ProDOS-Utilities v0.4.9 h1:TkrXrm6EMcB9GDHoBtfpr0/h5G6xUQf4NVX6d1YLYvg=
github.com/tjboldt/ProDOS-Utilities v0.4.9/go.mod h1:TS0/NXtEofuAaDOhRzlrHrbGAzrJXlk9IltkLswShsc=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.bug.st/serial v1.6.1 h1:VSSWmUxlj1T/YlRo2J104Zv3wJFrjHIl/T3NeruWAHY=
go.bug.st/serial v1.6.1/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
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.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
golang.org/x/image v0.15.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.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

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,79 +8,97 @@ package handlers
import (
"fmt"
"os"
"github.com/tjboldt/ProDOS-Utilities/prodos"
)
var oldFirmware = false
// 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
var err error
if !oldFirmware {
driveUnit, err = comm.ReadByte()
fmt.Printf("Drive unit: %0X\n", driveUnit)
driveUnit, err = comm.ReadByte()
if err != nil {
fmt.Printf("Drive unit not sent, assuming older firmware")
oldFirmware = true
}
if err != nil {
fmt.Printf("Failed to read block")
return 0, err
}
file := drive1
driveNumber := 1
if driveUnit >= 128 {
file = drive2
driveNumber = 2
}
slotNumber := driveUnit & 0x7F >> 4
block := int(blockHigh)*256 + int(blockLow)
fmt.Printf("Read block %d\n", block)
fmt.Printf("Read block %04X in slot %d, drive %d...", block, slotNumber, driveNumber)
buffer := prodos.ReadBlock(file, block)
buffer, err := prodos.ReadBlock(file, block)
if err != nil {
fmt.Printf("failed %s\n", err)
return 0, err
}
err = comm.WriteBlock(buffer)
if err == nil {
fmt.Printf("Read block completed\n")
fmt.Printf("succeeded\n")
} else {
fmt.Printf("Failed to read block\n")
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()
var driveUnit byte
var err error
if !oldFirmware {
driveUnit, err = comm.ReadByte()
if err != nil {
fmt.Printf("Drive unit not sent, assuming older firmware")
oldFirmware = true
}
driveUnit, err = comm.ReadByte()
if err != nil {
fmt.Printf("Failed to write block")
return err
}
file := drive1
driveNumber := 1
if driveUnit >= 128 {
file = drive2
driveNumber = 2
}
buffer := make([]byte, 512)
block := int(blockHigh)*256 + int(blockLow)
fmt.Printf("Write block %d\n", block)
slotNumber := driveUnit & 0x7F >> 4
comm.ReadBlock(buffer)
prodos.WriteBlock(file, block, buffer)
fmt.Printf("Write block completed\n")
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 err
}
fmt.Printf("...")
err = prodos.WriteBlock(file, block, buffer)
if err == nil {
fmt.Printf("succeeded\n")
} 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.
@ -10,18 +10,22 @@ package handlers
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"strconv"
"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"
@ -68,6 +72,14 @@ func ExecCommand() {
a2wifi()
return
}
if strings.HasPrefix(linuxCommand, "a2timeout") {
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)
@ -100,14 +112,7 @@ func execCommand(linuxCommand string, workingDirectory string) {
comm.WriteString("Failed to set stdout\r")
return
}
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Printf("Failed to set stdin\n")
comm.WriteString("Failed to set stdin\r")
return
}
fmt.Printf("Command output:\n")
err = cmd.Start()
if err != nil {
fmt.Printf("Failed to start command\n")
@ -115,94 +120,158 @@ func execCommand(linuxCommand string, workingDirectory string) {
return
}
outputComplete := make(chan bool)
inputComplete := make(chan bool)
userCancelled := make(chan bool)
go getStdin(stdin, outputComplete, inputComplete, userCancelled)
go getStdout(stdout, outputComplete, userCancelled)
timeout := time.After(time.Duration(execTimeoutSeconds) * time.Second)
for {
select {
case <-outputComplete:
outputComplete <- true
cmd.Wait()
comm.WriteByte(0)
return
case <-userCancelled:
userCancelled <- true
case <-timeout:
comm.WriteString("\rCancelled by apple2driver\r")
cmd.Process.Kill()
return
case <-inputComplete:
cmd.Wait()
comm.WriteByte(0)
return
}
}
}
func getStdout(stdout io.ReadCloser, outputComplete chan bool, userCancelled chan bool) {
for {
select {
case <-userCancelled:
fmt.Printf("User Cancelled stdout\n")
stdout.Close()
return
default:
bb := make([]byte, 1)
n, err := stdout.Read(bb)
if err != nil {
stdout.Close()
outputComplete <- true
return
}
if n > 0 {
b := bb[0]
comm.SendCharacter(b)
}
}
}
}
func getStdin(stdin io.WriteCloser, done chan bool, inputComplete chan bool, userCancelled chan bool) {
for {
select {
case <-done:
stdin.Close()
inputComplete <- true
return
default:
b, err := comm.ReadByte()
if err == nil {
if b == 0x00 || b == 0x03 {
stdin.Close()
userCancelled <- true
fmt.Printf("\nUser cancelled stdin\n")
return
n, stdOutErr := stdout.Read(bb)
if stdOutErr == nil {
if n > 0 {
b := bb[0]
comm.SendCharacter(b)
}
bb := make([]byte, 1)
stdin.Write(bb)
} else {
comm.WriteByte(0)
cmd.Wait()
return
}
}
}
}
func a2version() {
comm.WriteString("\rVersion: " + info.Version + "\r")
comm.WriteString("\rDriver version: " + info.Version + "\r")
}
func a2help() {
comm.WriteString("\r" +
"Built-in commands:\r" +
"------------------\r" +
"a2version - display version number\r" +
comm.WriteString("\rDriver version: " + info.Version + "\r" +
"\r" +
"Example from ] prompt:\r" +
"]RPI ls /home/pi\r" +
"\r" +
"Example from Applesoft BASIC:\r" +
"]10 PRINT CHR$(4)\"RPI ping apple.com\"\r" +
"]RUN\r" +
"\r" +
"Driver commands called with RPI:\r" +
"a2help - display this message\r" +
"a2version - display driver version\r" +
"a2wifi - set up wifi\r" +
"a2timeout - seconds to timeout commands\r" +
"A2LOWER - force lowercase for II+\r" +
"a2lower - disable force lowercase for II+\r" +
"a2lower - disable force lowercase\r" +
"a2drive - change drive images\r" +
"\r")
}
func a2timeout(linuxCommand string) {
params := strings.Fields(linuxCommand)
switch len(params) {
case 1:
comm.WriteString("\rCommand timeout: " + strconv.FormatInt(int64(execTimeoutSeconds), 10) + "\r")
case 2:
timeoutSeconds, err := strconv.ParseInt(params[1], 10, 32)
if err != nil {
comm.WriteString("\rFailed to parse timeout\r")
} else {
execTimeoutSeconds = int(timeoutSeconds)
comm.WriteString("\rCommand timeout set to: " + strconv.FormatInt(int64(execTimeoutSeconds), 10) + "\r")
}
default:
comm.WriteString("\rToo many parameters\n")
}
}
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.
@ -16,12 +16,12 @@ import (
// GetTimeCommand handles the request to get ProDOS time bytes
func GetTimeCommand() {
fmt.Printf("Sending date/time...\n")
fmt.Printf("Sending date/time...")
prodosTime := prodos.DateTimeToProDOS(time.Now())
for i := 0; i < len(prodosTime); i++ {
comm.WriteByte(prodosTime[i])
}
fmt.Printf("Send time complete\n")
fmt.Printf("%02X %02X %02X %02X\n", prodosTime[0], prodosTime[1], prodosTime[2], prodosTime[3])
}

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,16 +44,22 @@ func ShellCommand() {
for {
select {
case <-outputComplete:
fmt.Printf("Shell output complete\n")
outputComplete <- true
ptmx.Close()
cmd.Wait()
comm.WriteByte(0)
return
// return
break
case <-userCancelled:
fmt.Printf("User cancelled, killing process\n")
ptmx.Close()
cmd.Process.Kill()
comm.WriteByte(0)
// 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 = "0023"
const Version = "002D"

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

91
RaspberryPi/setup.sh Normal file
View File

@ -0,0 +1,91 @@
#!/bin/sh
sudo apt update
sudo apt install git -y
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
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
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
cd Apple2-IO-RPi/Apple2 || exit
./assemble.sh $1
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'
if [ "$1" = '1' ]; then
sudo --preserve-env=HOME --preserve-env=USER bash -c 'cat > apple2driver.service << EOF
[Unit]
Description=Apple2-IO-RPi Driver (Pico edition)
[Service]
ExecStart=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver -cdc=true
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=apple2driver
User=$USER
Group=$USER
WorkingDirectory=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver
[Install]
WantedBy=basic.target
EOF'
else
sudo --preserve-env=HOME --preserve-env=USER bash -c 'cat > apple2driver.service << EOF
[Unit]
Description=Apple2-IO-RPi Driver (Classic edition)
[Service]
ExecStart=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver/apple2driver
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=apple2driver
User=$USER
Group=$USER
WorkingDirectory=$HOME/Apple2-IO-RPi/RaspberryPi/apple2driver
[Install]
WantedBy=basic.target
EOF'
fi
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

View File

@ -0,0 +1,39 @@
set(PROJECT_NAME Apple2-IO-RPi)
cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)
project(${PROJECT_NAME} C CXX ASM)
pico_sdk_init()
add_executable(${PROJECT_NAME})
pico_add_extra_outputs(${PROJECT_NAME})
pico_enable_stdio_uart(${PROJECT_NAME} 0)
pico_enable_stdio_usb(${PROJECT_NAME} 1)
include(FetchContent)
FetchContent_Declare(a2pico
GIT_REPOSITORY https://github.com/oliverschmidt/a2pico.git
GIT_TAG main
)
FetchContent_MakeAvailable(a2pico)
set_source_files_properties(incbin.S OBJECT_DEPENDS ../RaspberryPi/driveimage/AT28C64B.bin)
add_custom_command(
WORKING_DIRECTORY ../Apple2
COMMAND ./assemble.sh 1
OUTPUT ../RaspberryPi/driveimage/AT28C64B.bin
VERBATIM
)
target_sources(${PROJECT_NAME} PRIVATE
main.c
board.c
incbin.S
)
target_link_libraries(${PROJECT_NAME} PRIVATE
pico_stdlib
pico_multicore
a2pico
)

21
RaspberryPiPico/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Oliver Schmidt (https://a2retro.de/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1 @@
The setup.sh and build.sh are here for convenience of building the Pico code directly on the RPi Zero 2 W attached to the Apple II.

78
RaspberryPiPico/board.c Normal file
View File

@ -0,0 +1,78 @@
/*
MIT License
Copyright (c) 2022 Oliver Schmidt (https://a2retro.de/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <pico/multicore.h>
#include <a2pico.h>
#include "board.h"
extern const __attribute__((aligned(4))) uint8_t firmware[];
static uint32_t page;
void __time_critical_func(board)(void) {
a2pico_init(pio0);
while (true) {
uint32_t pico = a2pico_getaddr(pio0);
uint32_t addr = pico & 0x0FFF;
uint32_t io = pico & 0x0F00; // IOSTRB or IOSEL
uint32_t strb = pico & 0x0800; // IOSTRB
uint32_t read = pico & 0x1000; // R/W
if (read) {
if (!io) { // DEVSEL
switch (addr & 0xF) {
case 0xB:
a2pico_putdata(pio0, !multicore_fifo_rvalid() << 7 |
!multicore_fifo_wready() << 6);
break;
case 0xE:
a2pico_putdata(pio0, sio_hw->fifo_rd);
break;
}
} else {
if (!strb) {
a2pico_putdata(pio0, firmware[page | addr]);
}
}
} else {
uint32_t data = a2pico_getdata(pio0);
if (!io) { // DEVSEL
switch (addr & 0xF) {
case 0x7:
page = (data & 0x30) << 7;
break;
case 0xD:
sio_hw->fifo_wr = data;
break;
}
}
}
}
}

32
RaspberryPiPico/board.h Normal file
View File

@ -0,0 +1,32 @@
/*
MIT License
Copyright (c) 2022 Oliver Schmidt (https://a2retro.de/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef _BOARD_H
#define _BOARD_H
void board(void);
#endif

4
RaspberryPiPico/build.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
PICO_SDK_PATH=~/pico-sdk/ cmake .
make

6
RaspberryPiPico/incbin.S Normal file
View File

@ -0,0 +1,6 @@
.section .time_critical.firmware
.global firmware
.type firmware, %object
.balign 4
firmware:
.incbin "../RaspberryPi/driveimage/AT28C64B.bin"

92
RaspberryPiPico/main.c Normal file
View File

@ -0,0 +1,92 @@
/*
MIT License
Copyright (c) 2022 Oliver Schmidt (https://a2retro.de/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdio.h>
#include <pico/printf.h>
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include "board.h"
#ifdef TRACE
void uart_printf(uart_inst_t *uart, const char *format, ...) {
static char buffer[0x100];
va_list va;
va_start(va, format);
vsnprintf(buffer, sizeof(buffer), format, va);
va_end(va);
buffer[0xFF] = '\0';
uart_puts(uart, buffer);
}
#endif
void main(void) {
multicore_launch_core1(board);
stdio_init_all();
stdio_set_translate_crlf(&stdio_usb, false);
#ifdef PICO_DEFAULT_LED_PIN
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
#endif
#ifdef TRACE
uart_init(uart0, 115200);
uart_set_translate_crlf(uart0, true);
gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART);
#endif
while (true) {
bool conn = stdio_usb_connected();
if (conn) {
if (multicore_fifo_rvalid()) {
uint32_t data = multicore_fifo_pop_blocking();
putchar(data);
#ifdef TRACE
uart_printf(uart0, "> %02X\n", data);
#endif
}
}
if (multicore_fifo_wready()) {
int data = getchar_timeout_us(0);
if (data != PICO_ERROR_TIMEOUT) {
multicore_fifo_push_blocking(data);
#ifdef TRACE
uart_printf(uart0, "< %02X\n", data);
#endif
}
}
#ifdef PICO_DEFAULT_LED_PIN
gpio_put(PICO_DEFAULT_LED_PIN, conn);
#endif
}
}

View File

@ -0,0 +1,73 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

7
RaspberryPiPico/setup.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib -y
cd ~
git clone https://github.com/raspberrypi/pico-sdk.git
cd ~/pico-sdk/
git submodule update --init

View File

@ -4,6 +4,7 @@
| Hardware Version | Supported |
| ---------------- | ------------------ |
| Prototype 6 | :white_check_mark: |
| Prototype 5 | :white_check_mark: |
| Prototype 4 | :white_check_mark: |
| Older prototypes | :x: |