mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-04-21 21:51:15 +02:00
Compare commits
112 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
88d654129a | ||
![]() |
b88c9a314b | ||
![]() |
e4c3f34fb0 | ||
![]() |
b520f9ace8 | ||
![]() |
d8c4f979cc | ||
![]() |
d63f5893da | ||
![]() |
d307e1a5b1 | ||
![]() |
65f8fa3cf7 | ||
![]() |
6c566bd530 | ||
![]() |
99060bec15 | ||
![]() |
63feaa0c2e | ||
![]() |
a59ad1d39b | ||
![]() |
30fb3d0ea6 | ||
![]() |
a3d4082384 | ||
![]() |
0739ca624c | ||
![]() |
bb1ce45dfe | ||
![]() |
9193e9c6f2 | ||
![]() |
3fbb6f3823 | ||
![]() |
f546e5d17d | ||
![]() |
8393963650 | ||
![]() |
20a9ec0087 | ||
![]() |
b3d9e98e68 | ||
![]() |
6698550dbd | ||
![]() |
18041e2547 | ||
![]() |
0538a28f9e | ||
![]() |
1ade3ade8e | ||
![]() |
80b4aa95cd | ||
![]() |
6eef811cd6 | ||
![]() |
e2c100ae7f | ||
![]() |
a6e86587ae | ||
![]() |
93ab101be4 | ||
![]() |
cc41652e6f | ||
![]() |
ed63eb3e8c | ||
![]() |
db4f16754f | ||
![]() |
74e20cb8cc | ||
![]() |
3146cc8c99 | ||
![]() |
4a50e33acd | ||
![]() |
d12bfaabf6 | ||
![]() |
04cecb1955 | ||
![]() |
a5284aa770 | ||
![]() |
bbcf041b5a | ||
![]() |
12e16b807a | ||
![]() |
92fb4a85df | ||
![]() |
1259687902 | ||
![]() |
d8976def97 | ||
![]() |
e9ee025e21 | ||
![]() |
912f356650 | ||
![]() |
631f140c48 | ||
![]() |
71cef2cd6c | ||
![]() |
1b71b4a333 | ||
![]() |
5e33e516a2 | ||
![]() |
5adc95b6e1 | ||
![]() |
acc3e588d8 | ||
![]() |
a571fe16f5 | ||
![]() |
903efe5353 | ||
![]() |
e4af127e55 | ||
![]() |
6bbfee44e7 | ||
![]() |
9843a79a86 | ||
![]() |
80c06f3e53 | ||
![]() |
554305290e | ||
![]() |
e6751c262d | ||
![]() |
92838da349 | ||
![]() |
a884d69308 | ||
![]() |
7bc4e6d180 | ||
![]() |
a0bd0ddd98 | ||
![]() |
b8632a305b | ||
![]() |
b89ca68cb4 | ||
![]() |
0f3eaa6d17 | ||
![]() |
5854b4ec0d | ||
![]() |
9599db8307 | ||
![]() |
cf19dc6151 | ||
![]() |
0e868b5ad5 | ||
![]() |
8a49e954ce | ||
![]() |
3b13d21e63 | ||
![]() |
4eaa0b3353 | ||
![]() |
64c3b69454 | ||
![]() |
83bcfd3065 | ||
![]() |
61bd3c62d8 | ||
![]() |
2846938c5f | ||
![]() |
0050688255 | ||
![]() |
03daabeae8 | ||
![]() |
e93cecfae3 | ||
![]() |
0150060f1e | ||
![]() |
42b10e85f1 | ||
![]() |
cff730cafc | ||
![]() |
f6b94aec97 | ||
![]() |
c156b72bee | ||
![]() |
f27f644a7e | ||
![]() |
5b880fc052 | ||
![]() |
a12641bf39 | ||
![]() |
01bef4060e | ||
![]() |
b4b3659458 | ||
![]() |
7a83fb3eae | ||
![]() |
66f71c2040 | ||
![]() |
95b78f3cd9 | ||
![]() |
421d0438f3 | ||
![]() |
be37025d42 | ||
![]() |
17c12f5957 | ||
![]() |
f7eb6a73b4 | ||
![]() |
b84213b3e4 | ||
![]() |
356f1f2f0f | ||
![]() |
42acb48004 | ||
![]() |
1f7be611d8 | ||
![]() |
13fc38fe73 | ||
![]() |
2639a93b6f | ||
![]() |
7ea74f19a5 | ||
![]() |
7f21902e21 | ||
![]() |
d7aadf48f9 | ||
![]() |
5ae3e32d63 | ||
![]() |
ef053f9c52 | ||
![]() |
3ed1ad4d73 | ||
![]() |
c14da52f46 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,5 +1,5 @@
|
|||||||
fw/project/lcmxo2/*.sty linguist-generated
|
fw/project/lcmxo2/*.sty linguist-generated
|
||||||
fw/rtl/serv/* -linguist-vendored
|
fw/rtl/serv/* linguist-vendored
|
||||||
fw/rtl/vendor/** -linguist-vendored
|
fw/rtl/vendor/** -linguist-vendored
|
||||||
fw/rtl/vendor/lcmxo2/generated/* linguist-generated
|
fw/rtl/vendor/lcmxo2/generated/* linguist-generated
|
||||||
hw/pcb/*.html linguist-generated
|
hw/pcb/*.html linguist-generated
|
||||||
|
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@ -1,2 +1 @@
|
|||||||
github: polprzewodnikowy
|
|
||||||
ko_fi: polprzewodnikowy
|
ko_fi: polprzewodnikowy
|
||||||
|
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
4.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Possible solution**
|
|
||||||
Not obligatory, but suggest a fix/reason for the bug.
|
|
58
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
title: "[SC64][BUG] "
|
||||||
|
labels: ["bug"]
|
||||||
|
assignees:
|
||||||
|
- Polprzewodnikowy
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: checkboxes
|
||||||
|
id: sanity-check
|
||||||
|
attributes:
|
||||||
|
label: Is your issue really a bug?
|
||||||
|
description: |
|
||||||
|
Issue tracker in this repository is for **BUG REPORTS ONLY**.
|
||||||
|
|
||||||
|
Make sure your problem is caused by the firmware/PC app and **not** by the software you're running on the flashcart.
|
||||||
|
|
||||||
|
Errors in the documentation are also considered a bug.
|
||||||
|
|
||||||
|
If your issue is related to the menu then report it in the [N64FlashcartMenu] repository.
|
||||||
|
|
||||||
|
[N64FlashcartMenu]: https://github.com/Polprzewodnikowy/N64FlashcartMenu
|
||||||
|
options:
|
||||||
|
- label: I understand the difference between flashcart firmware, N64FlashcartMenu and `sc64deployer` PC app.
|
||||||
|
required: true
|
||||||
|
- label: I found a bug in FPGA HDL (`/fw/rtl`)
|
||||||
|
- label: I found a bug in MCU app (`/sw/controller`)
|
||||||
|
- label: I found a bug in N64 bootloader (`/sw/bootloader`)
|
||||||
|
- label: I found a bug in PC app (`/sw/deployer`)
|
||||||
|
- label: I found a bug in initial programming script (`/sw/tools/primer.py`)
|
||||||
|
- label: I found an error in documentation (`/docs`)
|
||||||
|
- label: I found an issue elsewhere
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Firmware version
|
||||||
|
placeholder: v2.20.2
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: |
|
||||||
|
Tell us what you noticed as a bug, and what is your expected outcome.
|
||||||
|
The more detailed the description is the better.
|
||||||
|
If applicable please attach screenshots and/or video showing the problem.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: deployer-info
|
||||||
|
attributes:
|
||||||
|
label: Output logs from `sc64deployer info`
|
||||||
|
description: If possible, please copy and paste the output from the command specified above.
|
||||||
|
render: shell
|
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +1,5 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: GitHub Discussions
|
|
||||||
url: https://github.com/Polprzewodnikowy/SummerCart64/discussions
|
|
||||||
about: Please use for QUESTIONS, conversations or discussions.
|
|
||||||
- name: N64brew Discord
|
- name: N64brew Discord
|
||||||
url: https://discord.gg/8xvRPqCAFC
|
url: https://discord.gg/8VNMKhxqQn
|
||||||
about: Alternative channel for asking QUESTIONS.
|
about: The go-to community to ask about SummerCart64
|
||||||
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: enhancement
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
20
.github/PULL_REQUEST_TEMPLATE/default.md
vendored
20
.github/PULL_REQUEST_TEMPLATE/default.md
vendored
@ -1,20 +0,0 @@
|
|||||||
**Description**
|
|
||||||
Provide a headline summary of your changes in the Title above.
|
|
||||||
Describe your changes in detail.
|
|
||||||
|
|
||||||
**Related Issue**
|
|
||||||
This project only accepts pull requests related to open issues.
|
|
||||||
If suggesting a change, please discuss it in an issue first.
|
|
||||||
If fixing a bug, there should be an issue describing it with steps to reproduce.
|
|
||||||
Please link to the issue here:
|
|
||||||
|
|
||||||
**Motivation and Context**
|
|
||||||
Why is this change required? What problem does it solve?
|
|
||||||
If it fixes an open issue, please link to the issue here.
|
|
||||||
|
|
||||||
**How Has This Been Tested?**
|
|
||||||
Please describe in detail how you tested your changes.
|
|
||||||
Include details of your testing environment, and the tests you ran to see how your change affects other areas of the code, etc.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help demonstrate your feature/bugfix.
|
|
117
.github/workflows/build.yml
vendored
117
.github/workflows/build.yml
vendored
@ -2,7 +2,7 @@ name: build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
@ -18,7 +18,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download SummerCart64 repository
|
- name: Download SummerCart64 repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set package version
|
- name: Set package version
|
||||||
uses: frabert/replace-string-action@v2
|
uses: frabert/replace-string-action@v2
|
||||||
@ -28,13 +30,19 @@ jobs:
|
|||||||
string: '${{ github.ref_name }}'
|
string: '${{ github.ref_name }}'
|
||||||
replace-with: '-'
|
replace-with: '-'
|
||||||
|
|
||||||
|
- name: Retrieve the Lattice Diamond license from secrets and decode it
|
||||||
|
run: echo $LICENSE | base64 --decode > fw/project/lcmxo2/license.dat
|
||||||
|
env:
|
||||||
|
LICENSE: ${{ secrets.LATTICE_DIAMOND_LICENSE_BASE64 }}
|
||||||
|
|
||||||
- name: Build firmware
|
- name: Build firmware
|
||||||
run: ./docker_build.sh release --force-clean
|
run: ./docker_build.sh release --force-clean
|
||||||
env:
|
env:
|
||||||
|
MAC_ADDRESS: ${{ secrets.LATTICE_DIAMOND_MAC_ADDRESS }}
|
||||||
SC64_VERSION: ${{ steps.version.outputs.replaced }}
|
SC64_VERSION: ${{ steps.version.outputs.replaced }}
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: sc64-pkg-${{ steps.version.outputs.replaced }}
|
name: sc64-pkg-${{ steps.version.outputs.replaced }}
|
||||||
path: |
|
path: |
|
||||||
@ -52,32 +60,43 @@ jobs:
|
|||||||
build-deployer:
|
build-deployer:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
version: [windows, windows-32bit, linux, macos]
|
||||||
include:
|
include:
|
||||||
- os: windows-latest
|
- version: windows
|
||||||
executable: sc64deployer.exe
|
os: windows-latest
|
||||||
name: sc64-deployer-windows
|
executable: target/release/sc64deployer.exe
|
||||||
options: -c -a -f
|
package-name: sc64-deployer-windows
|
||||||
extension: zip
|
package-params: -c -a -f
|
||||||
|
package-extension: zip
|
||||||
|
|
||||||
- os: ubuntu-latest
|
- version: windows-32bit
|
||||||
linux-packages: libudev-dev
|
os: windows-latest
|
||||||
executable: sc64deployer
|
build-params: --target=i686-pc-windows-msvc
|
||||||
name: sc64-deployer-linux
|
executable: target/i686-pc-windows-msvc/release/sc64deployer.exe
|
||||||
options: -czf
|
package-name: sc64-deployer-windows-32bit
|
||||||
extension: tar.gz
|
package-params: -c -a -f
|
||||||
|
package-extension: zip
|
||||||
|
|
||||||
- os: macos-latest
|
- version: linux
|
||||||
executable: sc64deployer
|
os: ubuntu-latest
|
||||||
name: sc64-deployer-macos
|
apt-packages: libudev-dev
|
||||||
options: -czf
|
executable: target/release/sc64deployer
|
||||||
extension: tgz
|
package-name: sc64-deployer-linux
|
||||||
|
package-params: -czf
|
||||||
|
package-extension: tar.gz
|
||||||
|
|
||||||
|
- version: macos
|
||||||
|
os: macos-latest
|
||||||
|
executable: target/release/sc64deployer
|
||||||
|
package-name: sc64-deployer-macos
|
||||||
|
package-params: -czf
|
||||||
|
package-extension: tgz
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download SummerCart64 repository
|
- name: Download SummerCart64 repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set package version
|
- name: Set package version
|
||||||
uses: frabert/replace-string-action@v2
|
uses: frabert/replace-string-action@v2
|
||||||
@ -87,32 +106,66 @@ jobs:
|
|||||||
string: '${{ github.ref_name }}'
|
string: '${{ github.ref_name }}'
|
||||||
replace-with: '-'
|
replace-with: '-'
|
||||||
|
|
||||||
- name: Install linux packages
|
- name: Install apt packages
|
||||||
if: matrix.linux-packages
|
if: matrix.apt-packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install ${{ matrix.linux-packages }}
|
sudo apt-get -y install ${{ matrix.apt-packages }}
|
||||||
|
|
||||||
- name: Build deployer
|
- name: Build deployer
|
||||||
run: cargo b -r
|
run: cargo b -r ${{ matrix.build-params }}
|
||||||
working-directory: sw/deployer
|
working-directory: sw/deployer
|
||||||
|
|
||||||
- name: Package executable
|
- name: Package executable
|
||||||
run: |
|
run: |
|
||||||
mkdir package
|
mkdir -p ./package
|
||||||
cd target/release
|
cp ${{ matrix.executable }} ./package/
|
||||||
tar ${{ matrix.options }} ../../package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }} ${{ matrix.executable }}
|
cd ./package
|
||||||
|
tar ${{ matrix.package-params }} ./${{ matrix.package-name }}-${{ steps.version.outputs.replaced }}.${{ matrix.package-extension }} *
|
||||||
working-directory: sw/deployer
|
working-directory: sw/deployer
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.name }}-${{ steps.version.outputs.replaced }}
|
name: ${{ matrix.package-name }}-${{ steps.version.outputs.replaced }}
|
||||||
path: sw/deployer/package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }}
|
path: sw/deployer/package/${{ matrix.package-name }}-${{ steps.version.outputs.replaced }}.${{ matrix.package-extension }}
|
||||||
|
|
||||||
- name: Upload release assets
|
- name: Upload release assets
|
||||||
if: github.event_name == 'release' && github.event.action == 'created'
|
if: github.event_name == 'release' && github.event.action == 'created'
|
||||||
uses: softprops/action-gh-release@v0.1.15
|
uses: softprops/action-gh-release@v0.1.15
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
sw/deployer/package/${{ matrix.name }}-${{ steps.version.outputs.replaced }}.${{ matrix.extension }}
|
sw/deployer/package/${{ matrix.package-name }}-${{ steps.version.outputs.replaced }}.${{ matrix.package-extension }}
|
||||||
|
|
||||||
|
publish-website:
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download SummerCart64 repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Copy BOM file to the website folder
|
||||||
|
run: cp ./hw/pcb/sc64v2_bom.html ./web
|
||||||
|
|
||||||
|
- name: Setup GitHub pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
|
|
||||||
|
- name: Upload website artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: ./web
|
||||||
|
|
||||||
|
- name: Publish website from uploaded artifact
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
|
82
README.md
82
README.md
@ -1,25 +1,43 @@
|
|||||||
# SummerCart64 - a fully open source Nintendo 64 flashcart
|
# SummerCart64 - a fully open source N64 flashcart
|
||||||
[<img src="assets/sc64_logo.svg" />](assets/sc64_logo.svg)
|
[<img src="assets/sc64_logo.svg" />](assets/sc64_logo.svg)
|
||||||
|
|
||||||
|
**For non-technical description of the SummerCart64, please head to the https://summercart64.dev website!**
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- 64 MiB SDRAM memory for game and save data
|
|
||||||
- 16 MiB FLASH memory for bootloader and extended game data
|
- **ROM and Save Memory On-board**
|
||||||
- 8 kiB on-chip buffer for general use
|
- 64 MiB SDRAM memory for game and save data (enough memory to support every retail game without compromise)
|
||||||
- ~23.8 MiB/s peak transfer rate USB interface for data upload/download and debug functionality
|
- 16 MiB FLASH memory for bootloader and extended game data (with extended memory flashcart supports game ROMs up to 78 MiB)
|
||||||
- ~23.8 MiB/s peak transfer rate SD card interface
|
|
||||||
- EEPROM, SRAM and FlashRAM save types with automatic writeback to SD card
|
- **Game Saves**
|
||||||
- Battery backed real time clock (RTC)
|
- EEPROM 4k/16k, SRAM and FlashRAM save types with an automatic writeback to the SD card (no reset button press required)
|
||||||
- Status LED and button for general use
|
|
||||||
- 64DD add-on emulation
|
- **Hardware-Dependent Game Features**
|
||||||
- IS-Viewer 64 debug interface
|
- 64DD add-on emulation
|
||||||
- N64 bootloader with support for IPL3 registers spoofing and loading menu from SD card
|
- Battery backed real time clock (RTC)
|
||||||
- Dedicated open source menu written specifically for this flashcart - [N64FlashcartMenu](https://github.com/Polprzewodnikowy/N64FlashcartMenu)
|
|
||||||
- Enhanced [UltraCIC_C](https://github.com/jago85/UltraCIC_C) emulation with automatic region switching and programmable seed/checksum values
|
- **Menu**
|
||||||
- PC app for communicating with flashcart (game/save data upload/download, feature enable control and debug terminal)
|
- Dedicated open source menu written specifically for this flashcart - [N64FlashcartMenu](https://github.com/Polprzewodnikowy/N64FlashcartMenu)
|
||||||
- [UNFLoader](https://github.com/buu342/N64-UNFLoader) support
|
|
||||||
- Initial programming via UART header or dedicated JTAG/SWD interfaces
|
- **Game Development**
|
||||||
- Software and firmware updatable via USB interface
|
- ~23.8 MiB/s peak transfer rate SD card interface
|
||||||
- 3D printable plastic shell
|
- ~23.8 MiB/s peak transfer rate USB interface for data upload/download and debug functionality
|
||||||
|
- PC app to access the flashcart features:
|
||||||
|
- Game/save data upload/download
|
||||||
|
- Feature enable control
|
||||||
|
- Debug terminal
|
||||||
|
- Access to the SD card
|
||||||
|
- Firmware update
|
||||||
|
- [UNFLoader](https://github.com/buu342/N64-UNFLoader) support
|
||||||
|
- IS-Viewer 64 debug interface (fixed 64 kiB buffer with a movable base address)
|
||||||
|
- 8 kiB on-chip buffer for general use
|
||||||
|
- Status LED and button for general use
|
||||||
|
- [UltraCIC_C](https://github.com/jago85/UltraCIC_C) emulation with automatic region switching and programmable seed/checksum values
|
||||||
|
- N64 bootloader with support for IPL3 registers spoofing and loading menu from SD card
|
||||||
|
|
||||||
|
- **Cartridge Production**
|
||||||
|
- Initial programming via UART header or via dedicated JTAG/SWD interfaces
|
||||||
|
- 3D printable shell
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -35,30 +53,22 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Help / Q&A
|
|
||||||
|
|
||||||
For any questions related to this project, please use [*Discussions*](https://github.com/Polprzewodnikowy/SummerCart64/discussions) tab in GitHub repository.
|
|
||||||
Using discussions tab is highly encouraged as it allows to have centralized knowledge database accessible for everyone interested in this project.
|
|
||||||
|
|
||||||
I'm also active at [N64brew](https://discord.gg/WqFgNWf) Discord server as `korgeaux` but keep in mind that [*Discussions*](https://github.com/Polprzewodnikowy/SummerCart64/discussions) tab is a preferred option.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## How do I get one?
|
## How do I get one?
|
||||||
|
|
||||||
One option is to ask in `#summer-cart-64` channel on [N64brew](https://discord.gg/WqFgNWf) Discord server if someone is making a group order.
|
Most up to date information about purchasing/manufacturing options is available on https://summercart64.dev website!
|
||||||
|
|
||||||
If you want to order it yourself then I've prepared all necessary manufacturing files on the [PCBWay Shared Project](https://www.pcbway.com/project/shareproject/SC64_an_open_source_Nintendo_64_flashcart_14b9688a.html) site.
|
If you want to order it yourself then I've prepared all necessary manufacturing files on the [PCBWay Shared Project](https://www.pcbway.com/project/member/shareproject/?bmbno=1046ED64-8AEE-44) site.
|
||||||
|
|
||||||
**Full disclosure**: for every order made through [this link](https://www.pcbway.com/project/shareproject/SC64_an_open_source_Nintendo_64_flashcart_14b9688a.html) I will receive 10% of PCB manufacturing and PCB assembly service cost (price of the components is not included in the split). This is a great way of supporting further project development.
|
|
||||||
|
|
||||||
**Be careful**: this is an advanced project and it is assumed that you have enough knowledge about electronics.
|
**Be careful**: this is an advanced project and it is assumed that you have enough knowledge about electronics.
|
||||||
Selecting wrong options or giving PCB manufacturer wrong information might result in an undesired time and/or money loss.
|
Selecting wrong options or giving PCB manufacturer wrong information might result in an undesired time and/or money loss.
|
||||||
Boards also come unprogrammed from the manufacturer - you need to do **initial programming step** yourself after receiving the board.
|
Boards also come unprogrammed from the manufacturer - you need to do **initial programming step** yourself after receiving the board.
|
||||||
|
**Price of the components is not included in the initial quote at the checkout** - manufacturer will contact you later with updated price.
|
||||||
To avoid problems _**please**_ read **both** [build guide](./docs/06_build_guide.md) and description on the shared project page **in full**.
|
To avoid problems _**please**_ read **both** [build guide](./docs/06_build_guide.md) and description on the shared project page **in full**.
|
||||||
If you have even slightest doubt about the ordering or programming process, it is better to leave it to someone experienced - ask in the Discord server mentioned above if that's the case.
|
If you have even slightest doubt about the ordering or programming process, it is better to leave it to someone experienced - ask in the [N64brew Discord server](https://discord.gg/8VNMKhxqQn) if that's the case.
|
||||||
|
|
||||||
If you don't need a physical product but still want to support me then check my [GitHub sponsors](https://github.com/sponsors/Polprzewodnikowy) page.
|
**Full disclosure**: for every order made through [this link](https://www.pcbway.com/project/member/shareproject/?bmbno=1046ED64-8AEE-44) I will receive 10% of PCB manufacturing and PCB assembly service cost (price of the components is not included in the split). This is a great way of supporting further project development.
|
||||||
|
|
||||||
|
If you don't need a physical product but still want to support me then check the sponsor links on the [official website](https://summercart64.dev).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -82,8 +92,10 @@ If you don't need a physical product but still want to support me then check my
|
|||||||
|
|
||||||
This project wouldn't be possible without these contributions:
|
This project wouldn't be possible without these contributions:
|
||||||
|
|
||||||
- [64drive](https://64drive.retroactive.be) orders being on permanent hold long before creating this repository.
|
- [64drive](https://64drive.retroactive.be) ([archived](https://web.archive.org/web/20240406215731/https://64drive.retroactive.be/)) orders being on permanent hold long before creating this repository.
|
||||||
- [EverDrive-64 X7](https://krikzz.com/our-products/cartridges/ed64x7.html) being disappointment for homebrew development (slow USB upload, unjustified price and overcomplicated SD card access).
|
- [EverDrive-64 X7](https://krikzz.com/our-products/cartridges/ed64x7.html) being disappointment for homebrew development (slow USB upload, unjustified price and overcomplicated SD card access).
|
||||||
|
- Context: Both aforementioned products were priced at $199 in 2020. 64drive features made it a vastly more useful tool for homebrew development.
|
||||||
|
Since then, 64drive had never been restocked and EverDrive-64 X7 price was lowered to $159 (as of May 2024).
|
||||||
- [Jan Goldacker (@jago85)](https://github.com/jago85) and his projects:
|
- [Jan Goldacker (@jago85)](https://github.com/jago85) and his projects:
|
||||||
- [Brutzelkarte](https://github.com/jago85/Brutzelkarte_FPGA) providing solid base for starting this project and sparking hope for true open source N64 flashcarts.
|
- [Brutzelkarte](https://github.com/jago85/Brutzelkarte_FPGA) providing solid base for starting this project and sparking hope for true open source N64 flashcarts.
|
||||||
- [UltraCIC_C](https://github.com/jago85/UltraCIC_C) reimplementation for easy integration in modern microcontrollers. Thanks also goes to everyone involved in N64 CIC reverse engineering.
|
- [UltraCIC_C](https://github.com/jago85/UltraCIC_C) reimplementation for easy integration in modern microcontrollers. Thanks also goes to everyone involved in N64 CIC reverse engineering.
|
||||||
|
34
build.sh
34
build.sh
@ -17,7 +17,8 @@ TOP_FILES=(
|
|||||||
FILES=(
|
FILES=(
|
||||||
"./assets/*"
|
"./assets/*"
|
||||||
"./docs/*"
|
"./docs/*"
|
||||||
"./hw/pcb/sc64_hw_v2.0a_bom.html"
|
"./hw/pcb/LICENSE"
|
||||||
|
"./hw/pcb/sc64v2_bom.html"
|
||||||
"./hw/pcb/sc64v2.kicad_pcb"
|
"./hw/pcb/sc64v2.kicad_pcb"
|
||||||
"./hw/pcb/sc64v2.kicad_pro"
|
"./hw/pcb/sc64v2.kicad_pro"
|
||||||
"./hw/pcb/sc64v2.kicad_sch"
|
"./hw/pcb/sc64v2.kicad_sch"
|
||||||
@ -27,6 +28,8 @@ FILES=(
|
|||||||
"./README.md"
|
"./README.md"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
HAVE_COMMIT_INFO=false
|
||||||
|
|
||||||
BUILT_BOOTLOADER=false
|
BUILT_BOOTLOADER=false
|
||||||
BUILT_CONTROLLER=false
|
BUILT_CONTROLLER=false
|
||||||
BUILT_CIC=false
|
BUILT_CIC=false
|
||||||
@ -36,9 +39,24 @@ BUILT_RELEASE=false
|
|||||||
|
|
||||||
FORCE_CLEAN=false
|
FORCE_CLEAN=false
|
||||||
|
|
||||||
|
get_last_commit_info () {
|
||||||
|
if [ "$HAVE_COMMIT_INFO" = true ]; then return; fi
|
||||||
|
|
||||||
|
SAFE_DIRECTORY="-c safe.directory=$(pwd)"
|
||||||
|
|
||||||
|
GIT_BRANCH=$(git $SAFE_DIRECTORY rev-parse --abbrev-ref HEAD)
|
||||||
|
GIT_TAG=$(git $SAFE_DIRECTORY describe --tags 2> /dev/null)
|
||||||
|
GIT_SHA=$(git $SAFE_DIRECTORY rev-parse HEAD)
|
||||||
|
GIT_MESSAGE=$(git $SAFE_DIRECTORY log --oneline --format=%B -n 1 HEAD | head -n 1)
|
||||||
|
|
||||||
|
HAVE_COMMIT_INFO=true
|
||||||
|
}
|
||||||
|
|
||||||
build_bootloader () {
|
build_bootloader () {
|
||||||
if [ "$BUILT_BOOTLOADER" = true ]; then return; fi
|
if [ "$BUILT_BOOTLOADER" = true ]; then return; fi
|
||||||
|
|
||||||
|
get_last_commit_info
|
||||||
|
|
||||||
pushd sw/bootloader > /dev/null
|
pushd sw/bootloader > /dev/null
|
||||||
if [ "$FORCE_CLEAN" = true ]; then
|
if [ "$FORCE_CLEAN" = true ]; then
|
||||||
make clean
|
make clean
|
||||||
@ -83,6 +101,8 @@ build_cic () {
|
|||||||
build_fpga () {
|
build_fpga () {
|
||||||
if [ "$BUILT_FPGA" = true ]; then return; fi
|
if [ "$BUILT_FPGA" = true ]; then return; fi
|
||||||
|
|
||||||
|
build_cic
|
||||||
|
|
||||||
pushd fw/project/lcmxo2 > /dev/null
|
pushd fw/project/lcmxo2 > /dev/null
|
||||||
if [ "$FORCE_CLEAN" = true ]; then
|
if [ "$FORCE_CLEAN" = true ]; then
|
||||||
rm -rf ./impl1/
|
rm -rf ./impl1/
|
||||||
@ -96,6 +116,8 @@ build_fpga () {
|
|||||||
build_update () {
|
build_update () {
|
||||||
if [ "$BUILT_UPDATE" = true ]; then return; fi
|
if [ "$BUILT_UPDATE" = true ]; then return; fi
|
||||||
|
|
||||||
|
get_last_commit_info
|
||||||
|
|
||||||
build_bootloader
|
build_bootloader
|
||||||
build_controller
|
build_controller
|
||||||
build_cic
|
build_cic
|
||||||
@ -161,6 +183,14 @@ if test $# -eq 0; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
print_time () {
|
||||||
|
echo "Build took $SECONDS seconds"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap "echo \"Build failed\"; print_time" ERR
|
||||||
|
|
||||||
|
SECONDS=0
|
||||||
|
|
||||||
TRIGGER_BOOTLOADER=false
|
TRIGGER_BOOTLOADER=false
|
||||||
TRIGGER_CONTROLLER=false
|
TRIGGER_CONTROLLER=false
|
||||||
TRIGGER_CIC=false
|
TRIGGER_CIC=false
|
||||||
@ -211,3 +241,5 @@ if [ "$TRIGGER_CIC" = true ]; then build_cic; fi
|
|||||||
if [ "$TRIGGER_FPGA" = true ]; then build_fpga; fi
|
if [ "$TRIGGER_FPGA" = true ]; then build_fpga; fi
|
||||||
if [ "$TRIGGER_UPDATE" = true ]; then build_update; fi
|
if [ "$TRIGGER_UPDATE" = true ]; then build_update; fi
|
||||||
if [ "$TRIGGER_RELEASE" = true ]; then build_release; fi
|
if [ "$TRIGGER_RELEASE" = true ]; then build_release; fi
|
||||||
|
|
||||||
|
print_time
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.8"
|
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.10"
|
||||||
|
BUILDER_PLATFORM="linux/x86_64"
|
||||||
|
|
||||||
pushd $(dirname $0) > /dev/null
|
pushd $(dirname $0) > /dev/null
|
||||||
|
|
||||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
||||||
GIT_TAG=$(git describe --tags 2> /dev/null)
|
|
||||||
GIT_SHA=$(git rev-parse HEAD)
|
|
||||||
GIT_MESSAGE=$(git log --oneline --format=%B -n 1 HEAD | head -n 1)
|
|
||||||
|
|
||||||
if [ -t 1 ]; then
|
if [ -t 1 ]; then
|
||||||
DOCKER_OPTIONS="-it"
|
DOCKER_OPTIONS="-it"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SECONDS=0
|
|
||||||
|
|
||||||
docker run \
|
docker run \
|
||||||
$DOCKER_OPTIONS \
|
$DOCKER_OPTIONS \
|
||||||
--rm \
|
--rm \
|
||||||
@ -23,20 +17,13 @@ docker run \
|
|||||||
-v "$(pwd)"/fw/project/lcmxo2/license.dat:/flexlm/license.dat \
|
-v "$(pwd)"/fw/project/lcmxo2/license.dat:/flexlm/license.dat \
|
||||||
-v "$(pwd)":/workdir \
|
-v "$(pwd)":/workdir \
|
||||||
-h=`hostname` \
|
-h=`hostname` \
|
||||||
-e GIT_BRANCH="$GIT_BRANCH" \
|
|
||||||
-e GIT_TAG="$GIT_TAG" \
|
|
||||||
-e GIT_SHA="$GIT_SHA" \
|
|
||||||
-e GIT_MESSAGE="$GIT_MESSAGE" \
|
|
||||||
-e SC64_VERSION=${SC64_VERSION:-""} \
|
-e SC64_VERSION=${SC64_VERSION:-""} \
|
||||||
|
--platform $BUILDER_PLATFORM \
|
||||||
$BUILDER_IMAGE \
|
$BUILDER_IMAGE \
|
||||||
./build.sh $@
|
./build.sh $@
|
||||||
|
|
||||||
BUILD_ERROR=$?
|
BUILD_RESULT=$?
|
||||||
|
|
||||||
echo "Build took $SECONDS seconds"
|
|
||||||
|
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
|
|
||||||
if [ $BUILD_ERROR -ne 0 ]; then
|
exit $BUILD_RESULT
|
||||||
exit -1
|
|
||||||
fi
|
|
||||||
|
@ -1,50 +1,38 @@
|
|||||||
- [First time setup on PC](#first-time-setup-on-pc)
|
- [First time setup](#first-time-setup)
|
||||||
- [Firmware backup/update](#firmware-backupupdate)
|
- [Standalone mode (Running menu and games on the N64)](#standalone-mode-running-menu-and-games-on-the-n64)
|
||||||
- [Running menu in standalone mode](#running-menu-in-standalone-mode)
|
- [Developer mode (Uploading ROMs from the PC, and more)](#developer-mode-uploading-roms-from-the-pc-and-more)
|
||||||
- [Uploading game and/or save from PC](#uploading-game-andor-save-from-pc)
|
- [Uploading game and/or save from PC](#uploading-game-andor-save-from-pc)
|
||||||
- [Downloading save to PC](#downloading-save-to-pc)
|
- [Downloading save to PC](#downloading-save-to-pc)
|
||||||
- [Running 64DD games from PC](#running-64dd-games-from-pc)
|
- [Running 64DD games from PC](#running-64dd-games-from-pc)
|
||||||
- [Direct boot option](#direct-boot-option)
|
- [Direct boot option](#direct-boot-option)
|
||||||
- [Debug terminal on PC](#debug-terminal-on-pc)
|
- [Debug terminal on PC](#debug-terminal-on-pc)
|
||||||
|
- [Firmware backup/update](#firmware-backupupdate)
|
||||||
- [LED blink patters](#led-blink-patters)
|
- [LED blink patters](#led-blink-patters)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## First time setup on PC
|
# First time setup
|
||||||
|
|
||||||
**Windows platform: replace `./sc64deployer` in examples below with `sc64deployer.exe`**
|
## Standalone mode (Running menu and games on the N64)
|
||||||
|
|
||||||
1. Download the latest deployer tool (`sc64-deployer-{os}-{version}.{ext}`) and firmware (`sc64-firmware-{version}.bin`) from GitHub releases page
|
|
||||||
2. Extract deployer tool package contents to a folder and place firmware file inside it
|
|
||||||
3. Connect SC64 device to your computer with USB type C cable
|
|
||||||
4. Run `./sc64deployer list` to check if device is detected in the system
|
|
||||||
5. Update SC64 firmware to the latest version with `./sc64deployer firmware update sc64-firmware-{version}.bin`
|
|
||||||
6. Run `./sc64deployer info` to check if update process finished successfully and SC64 is detected correctly
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Firmware backup/update
|
|
||||||
|
|
||||||
Keeping SC64 firmware up to date is highly recommended.
|
|
||||||
`sc64deployer` application is tightly coupled with specific firmware versions and will error out when it detects unsupported firmware version.
|
|
||||||
|
|
||||||
To download and backup current version of the SC64 firmware run `./sc64deployer firmware backup sc64-firmware-backup.bin`
|
|
||||||
|
|
||||||
To update SC64 firmware run `./sc64deployer firmware update sc64-firmware-{version}.bin`
|
|
||||||
|
|
||||||
To print firmware metadata run `./sc64deployer firmware info sc64-firmware-{version}.bin`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Running menu in standalone mode
|
|
||||||
|
|
||||||
Menu, as known from 64drive or EverDrive-64, is developed in another repository: [N64FlashcartMenu](https://github.com/Polprzewodnikowy/N64FlashcartMenu).
|
Menu, as known from 64drive or EverDrive-64, is developed in another repository: [N64FlashcartMenu](https://github.com/Polprzewodnikowy/N64FlashcartMenu).
|
||||||
Download latest version from [here](https://github.com/Polprzewodnikowy/N64FlashcartMenu/releases) and put `sc64menu.n64` file in the root directory of the SD card.
|
Download latest version from [here](https://github.com/Polprzewodnikowy/N64FlashcartMenu/releases) and put `sc64menu.n64` file in the root directory of the SD card.
|
||||||
|
Additionally, follow the instructions in the N64FlashcartMenu repository for more information about thr SD card setup and extra functionality.
|
||||||
When N64 is powered on menu is automatically loaded from the SD card. Supported file system formats are FAT32 and exFAT.
|
When N64 is powered on menu is automatically loaded from the SD card. Supported file system formats are FAT32 and exFAT.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Uploading game and/or save from PC
|
## Developer mode (Uploading ROMs from the PC, and more)
|
||||||
|
|
||||||
|
**Windows platform: replace `./sc64deployer` in examples below with `sc64deployer.exe`**
|
||||||
|
|
||||||
|
1. Download the latest deployer tool (`sc64-deployer-{os}-{version}.{ext}`) from the GitHub releases page
|
||||||
|
2. Extract deployer tool package contents to a folder
|
||||||
|
3. Connect SC64 device to your computer with USB type C cable
|
||||||
|
4. Run `./sc64deployer list` to check if device is detected in the system
|
||||||
|
5. Follow instructions below for specific use cases
|
||||||
|
|
||||||
|
### Uploading game and/or save from PC
|
||||||
|
|
||||||
`./sc64deployer upload path_to_rom.n64 --save-type eeprom4k --save path_to_save.sav`
|
`./sc64deployer upload path_to_rom.n64 --save-type eeprom4k --save path_to_save.sav`
|
||||||
|
|
||||||
@ -53,18 +41,14 @@ Application will try to autodetect used save type so explicitly setting save typ
|
|||||||
Check included help in the application to list available save types.
|
Check included help in the application to list available save types.
|
||||||
Arguments `--save-type` and/or `--save` can be omitted if game doesn't require any save or you want to start with fresh save file.
|
Arguments `--save-type` and/or `--save` can be omitted if game doesn't require any save or you want to start with fresh save file.
|
||||||
|
|
||||||
---
|
### Downloading save to PC
|
||||||
|
|
||||||
## Downloading save to PC
|
|
||||||
|
|
||||||
`./sc64deployer download save path_to_save.sav`
|
`./sc64deployer download save path_to_save.sav`
|
||||||
|
|
||||||
Replace `path_to_save.sav` with appropriate value.
|
Replace `path_to_save.sav` with appropriate value.
|
||||||
Command will raise error when no save type is currently enabled in the SC64 device.
|
Command will raise error when no save type is currently enabled in the SC64 device.
|
||||||
|
|
||||||
---
|
### Running 64DD games from PC
|
||||||
|
|
||||||
## Running 64DD games from PC
|
|
||||||
|
|
||||||
64DD games require DDIPL ROM and disk images.
|
64DD games require DDIPL ROM and disk images.
|
||||||
To run disk game type `./sc64deployer 64dd path_to_ddipl.n64 path_to_disk_1.ndd path_to_disk_2.ndd`.
|
To run disk game type `./sc64deployer 64dd path_to_ddipl.n64 path_to_disk_1.ndd path_to_disk_2.ndd`.
|
||||||
@ -79,31 +63,38 @@ Make sure retail and development disks formats aren't mixed together.
|
|||||||
If disk game supports running in conjunction with cartridge game then `--rom path_to_rom.n64` argument can be added to command above.
|
If disk game supports running in conjunction with cartridge game then `--rom path_to_rom.n64` argument can be added to command above.
|
||||||
N64 will boot cartridge game instead of 64DD IPL.
|
N64 will boot cartridge game instead of 64DD IPL.
|
||||||
|
|
||||||
---
|
### Direct boot option
|
||||||
|
|
||||||
## Direct boot option
|
|
||||||
|
|
||||||
If booting game through included bootloader isn't a desired option then flashcart can be put in special mode that omits this step.
|
If booting game through included bootloader isn't a desired option then flashcart can be put in special mode that omits this step.
|
||||||
Pass `--direct` option in `upload` or `64dd` command to disable bootloader during boot and console reset.
|
Pass `--direct` option in `upload` or `64dd` command to disable bootloader during boot and console reset.
|
||||||
This option is useful only for very specific cases (e.g. testing custom IPL3 or running SC64 on top of GameShark).
|
This option is useful only for very specific cases (e.g. testing custom IPL3 or running SC64 on top of GameShark).
|
||||||
TV type cannot be forced when direct boot mode is enabled.
|
TV type cannot be forced when direct boot mode is enabled.
|
||||||
|
|
||||||
---
|
### Debug terminal on PC
|
||||||
|
|
||||||
## Debug terminal on PC
|
|
||||||
|
|
||||||
`sc64deployer` application supports UNFLoader protocol and has same functionality implemented as aforementioned program.
|
`sc64deployer` application supports UNFLoader protocol and has same functionality implemented as aforementioned program.
|
||||||
Type `./sc64deployer debug` to activate it.
|
Type `./sc64deployer debug` to activate it.
|
||||||
|
|
||||||
|
### Firmware backup/update
|
||||||
|
|
||||||
|
Keeping SC64 firmware up to date is strongly recommended.
|
||||||
|
`sc64deployer` application is tightly coupled with specific firmware versions and will error out when it detects unsupported firmware version.
|
||||||
|
|
||||||
|
To download and backup current version of the SC64 firmware run `./sc64deployer firmware backup sc64-firmware-backup.bin`
|
||||||
|
|
||||||
|
To update SC64 firmware run `./sc64deployer firmware update sc64-firmware-{version}.bin`
|
||||||
|
|
||||||
|
To print firmware metadata run `./sc64deployer firmware info sc64-firmware-{version}.bin`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## LED blink patters
|
# LED blink patters
|
||||||
|
|
||||||
LED on SC64 board can blink in certain situations. Most of them during normal use are related to SD card access. Here's list of blink patterns:
|
LED on SC64 board can blink in certain situations. Most of them during normal use are related to SD card access. Here's list of blink patterns:
|
||||||
|
|
||||||
| Pattern | Meaning |
|
| Pattern | Meaning |
|
||||||
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
|
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
|
||||||
| Nx [Short ON - Short OFF] | SD card access is in progress (initialization or data read/write) or save writeback is in progress |
|
| Irregular | SD card access is in progress (initialization or data read/write) or save writeback was finished |
|
||||||
| Nx [Medium ON - Long OFF] | CIC region did not match, please power off console and power on again |
|
| Nx [Medium ON - Long OFF] | CIC region did not match, please power off console and power on again |
|
||||||
| 2x [Very short ON - Short OFF] | Pattern used during firmware update process, it means that specific part of firmware has started programming |
|
| 2x [Very short ON - Short OFF] | Pattern used during firmware update process, it means that specific part of firmware has started programming |
|
||||||
| 10x [Very short ON - Very short OFF] | Firmware has been successfully updated |
|
| 10x [Very short ON - Very short OFF] | Firmware has been successfully updated |
|
||||||
@ -112,4 +103,4 @@ LED on SC64 board can blink in certain situations. Most of them during normal us
|
|||||||
Nx means that blink count is varied.
|
Nx means that blink count is varied.
|
||||||
|
|
||||||
LED blinking on SD card access can be disabled through `sc64deployer` application.
|
LED blinking on SD card access can be disabled through `sc64deployer` application.
|
||||||
Please refer to included help for option to change the LED behavior.
|
Please refer to the included help for option to change the LED behavior.
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
- [Internal memory map](#internal-memory-map)
|
- [Internal memory map](#internal-memory-map)
|
||||||
- [PI memory map](#pi-memory-map)
|
- [PI memory map](#pi-memory-map)
|
||||||
- [Address decoding limitations](#address-decoding-limitations)
|
- [Address decoding limitations](#address-decoding-limitations)
|
||||||
- [Flash mapped sections](#flash-mapped-sections)
|
- [Flash mapped sections](#flash-mapped-sections)
|
||||||
- [SC64 registers](#sc64-registers)
|
- [SC64 registers](#sc64-registers)
|
||||||
- [`0x1FFF_0000`: **STATUS/COMMAND**](#0x1fff_0000-statuscommand)
|
- [`0x1FFF_0000`: **SCR**](#0x1fff_0000-scr)
|
||||||
- [`0x1FFF_0004`: **DATA0** and `0x1FFF_0008`: **DATA1**](#0x1fff_0004-data0-and-0x1fff_0008-data1)
|
- [`0x1FFF_0004`: **DATA0** / `0x1FFF_0008`: **DATA1**](#0x1fff_0004-data0--0x1fff_0008-data1)
|
||||||
- [`0x1FFF_000C`: **IDENTIFIER**](#0x1fff_000c-identifier)
|
- [`0x1FFF_000C`: **IDENTIFIER**](#0x1fff_000c-identifier)
|
||||||
- [`0x1FFF_0010`: **KEY**](#0x1fff_0010-key)
|
- [`0x1FFF_0010`: **KEY**](#0x1fff_0010-key)
|
||||||
|
- [`0x1FFF_0014`: **IRQ**](#0x1fff_0014-irq)
|
||||||
|
- [`0x1FFF_0018`: **AUX**](#0x1fff_0018-aux)
|
||||||
- [Command execution flow](#command-execution-flow)
|
- [Command execution flow](#command-execution-flow)
|
||||||
|
- [Without interrupt](#without-interrupt)
|
||||||
|
- [With interrupt](#with-interrupt)
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Internal memory map
|
|
||||||
|
# Internal memory map
|
||||||
|
|
||||||
This mapping is used internally by FPGA/μC and when accessing flashcart from USB side.
|
This mapping is used internally by FPGA/μC and when accessing flashcart from USB side.
|
||||||
|
|
||||||
@ -21,17 +25,17 @@ This mapping is used internally by FPGA/μC and when accessing flashcart from US
|
|||||||
| Flash [1] | `0x0400_0000` | 16 MiB | RW/R | Flash |
|
| Flash [1] | `0x0400_0000` | 16 MiB | RW/R | Flash |
|
||||||
| Data buffer | `0x0500_0000` | 8 kiB | RW | BlockRAM |
|
| Data buffer | `0x0500_0000` | 8 kiB | RW | BlockRAM |
|
||||||
| EEPROM | `0x0500_2000` | 2 kiB | RW | BlockRAM |
|
| EEPROM | `0x0500_2000` | 2 kiB | RW | BlockRAM |
|
||||||
| 64DD buffer | `0x0500_2800` | 256 bytes | RW | BlockRAM |
|
| 64DD/MCU buffer | `0x0500_2800` | 1 kiB | RW | BlockRAM |
|
||||||
| FlashRAM buffer [2] | `0x0500_2900` | 128 bytes | R | BlockRAM |
|
| FlashRAM buffer [2] | `0x0500_2C00` | 128 bytes | R | BlockRAM |
|
||||||
| N/A [3] | `0x0500_2980` | to `0x07FF_FFFF` | R | N/A |
|
| N/A [3] | `0x0500_2C80` | to `0x07FF_FFFF` | R | N/A |
|
||||||
|
|
||||||
- Note [1]: Flash memory region `0x04E0_0000` - `0x04FD_FFFF` is write protected as it contains N64 bootloader. This section can be overwritten only via firmware update process.
|
- Note [1]: Flash memory region `0x04E0_0000` - `0x04FD_FFFF` is write protected as it contains N64 bootloader. This section can be overwritten only via firmware update process.
|
||||||
- Note [2]: Due to BlockRAM usage optimization this section is read only.
|
- Note [2]: Due to BlockRAM usage optimization this section is read only.
|
||||||
- Note [3]: Read returns `0`. Maximum accessibe address space is 128 MiB.
|
- Note [3]: Read returns `0`. Maximum accessible address space is 128 MiB.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PI memory map
|
|
||||||
|
# PI memory map
|
||||||
|
|
||||||
This mapping is used when accessing flashcart from N64 side.
|
This mapping is used when accessing flashcart from N64 side.
|
||||||
|
|
||||||
@ -49,13 +53,13 @@ This mapping is used when accessing flashcart from N64 side.
|
|||||||
| ROM shadow [7] | `0x1FFC_0000` | 128 kiB | R | `0x04FE_0000` | Flash | mem bus | SC64 register access is enabled |
|
| ROM shadow [7] | `0x1FFC_0000` | 128 kiB | R | `0x04FE_0000` | Flash | mem bus | SC64 register access is enabled |
|
||||||
| Data buffer | `0x1FFE_0000` | 8 kiB | RW | `0x0500_0000` | Block RAM | mem bus | SC64 register access is enabled |
|
| Data buffer | `0x1FFE_0000` | 8 kiB | RW | `0x0500_0000` | Block RAM | mem bus | SC64 register access is enabled |
|
||||||
| EEPROM | `0x1FFE_2000` | 2 kiB | RW | `0x0500_2000` | Block RAM | mem bus | SC64 register access is enabled |
|
| EEPROM | `0x1FFE_2000` | 2 kiB | RW | `0x0500_2000` | Block RAM | mem bus | SC64 register access is enabled |
|
||||||
| 64DD buffer [8] | `0x1FFE_2800` | 256 bytes | RW | `0x0500_2800` | Block RAM | mem bus | SC64 register access is enabled |
|
| 64DD/MCU buffer [8] | `0x1FFE_2800` | 1 kiB | RW | `0x0500_2800` | Block RAM | mem bus | SC64 register access is enabled |
|
||||||
| FlashRAM buffer [8] | `0x1FFE_2900` | 128 bytes | R | `0x0500_2900` | Block RAM | mem bus | SC64 register access is enabled |
|
| FlashRAM buffer [8] | `0x1FFE_2C00` | 128 bytes | R | `0x0500_2C00` | Block RAM | mem bus | SC64 register access is enabled |
|
||||||
| SC64 registers | `0x1FFF_0000` | 20 bytes | RW | N/A | Flashcart Interface | reg bus | SC64 register access is enabled |
|
| SC64 registers | `0x1FFF_0000` | 28 bytes | RW | N/A | Flashcart Interface | reg bus | SC64 register access is enabled |
|
||||||
|
|
||||||
- Note [1]: 64DD IPL share SDRAM memory space with ROM (last 4 MiB minus 128 kiB for saves). Write access is always disabled for this section.
|
- Note [1]: 64DD IPL share SDRAM memory space with ROM (last 4 MiB minus 128 kiB for saves). Write access is always disabled for this section.
|
||||||
- Note [2]: SRAM and FlashRAM save types share SDRAM memory space with ROM (last 128 kiB).
|
- Note [2]: SRAM and FlashRAM save types share SDRAM memory space with ROM (last 128 kiB).
|
||||||
- Note [3]: 32 kiB chunks are accesed at `0x0800_0000`, `0x0804_0000` and `0x0808_0000`.
|
- Note [3]: 32 kiB chunks are accessed at `0x0800_0000`, `0x0804_0000` and `0x0808_0000`.
|
||||||
- Note [4]: FlashRAM read access is multiplexed between mem and reg bus, writes are always mapped to reg bus.
|
- Note [4]: FlashRAM read access is multiplexed between mem and reg bus, writes are always mapped to reg bus.
|
||||||
- Note [5]: Write access is available when `ROM_WRITE_ENABLE` config is enabled.
|
- Note [5]: Write access is available when `ROM_WRITE_ENABLE` config is enabled.
|
||||||
- Note [6]: This address overlaps last 128 kiB of ROM space allowing SRAM and FlashRAM save types to work with games occupying almost all of ROM space (for example Pokemon Stadium 2). Reads are redirected to last 128 kiB of flash.
|
- Note [6]: This address overlaps last 128 kiB of ROM space allowing SRAM and FlashRAM save types to work with games occupying almost all of ROM space (for example Pokemon Stadium 2). Reads are redirected to last 128 kiB of flash.
|
||||||
@ -80,59 +84,69 @@ Special commands are provided for performing flash erase and program.
|
|||||||
During those operations avoid accessing flash mapped sections.
|
During those operations avoid accessing flash mapped sections.
|
||||||
Data read will be corrupted and erase/program operations slows down.
|
Data read will be corrupted and erase/program operations slows down.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## SC64 registers
|
|
||||||
|
# SC64 registers
|
||||||
|
|
||||||
SC64 contains small register region used for communication between N64 and controller code running on the μC.
|
SC64 contains small register region used for communication between N64 and controller code running on the μC.
|
||||||
Protocol is command based with support for up to 256 diferrent commands and two 32-bit argument/result values per operation.
|
Protocol is command based with support for up to 256 different commands and two 32-bit argument/result values per operation.
|
||||||
Support for interrupts is provided but currently no command relies on it, 64DD IRQ is handled separately.
|
Command execution finish can be optionally signaled with "cart interrupt"
|
||||||
|
|
||||||
| name | address | size | access | usage |
|
| name | address | size | access | usage |
|
||||||
| ------------------ | ------------- | ------- | ------ | ---------------------------------- |
|
| -------------- | ------------- | ------- | ------ | -------------------------------- |
|
||||||
| **STATUS/COMMAND** | `0x1FFF_0000` | 4 bytes | RW | Command execution and status |
|
| **SCR** | `0x1FFF_0000` | 4 bytes | RW | Command execution and status |
|
||||||
| **DATA0** | `0x1FFF_0004` | 4 bytes | RW | Command argument/result 0 |
|
| **DATA0** | `0x1FFF_0004` | 4 bytes | RW | Command argument/result 0 |
|
||||||
| **DATA1** | `0x1FFF_0008` | 4 bytes | RW | Command argument/result 1 |
|
| **DATA1** | `0x1FFF_0008` | 4 bytes | RW | Command argument/result 1 |
|
||||||
| **IDENTIFIER** | `0x1FFF_000C` | 4 bytes | RW | Flashcart identifier and IRQ clear |
|
| **IDENTIFIER** | `0x1FFF_000C` | 4 bytes | RW | Flashcart identifier |
|
||||||
| **KEY** | `0x1FFF_0010` | 4 bytes | W | SC64 register access lock/unlock |
|
| **KEY** | `0x1FFF_0010` | 4 bytes | W | SC64 register access lock/unlock |
|
||||||
|
| **IRQ** | `0x1FFF_0014` | 4 bytes | W | IRQ clear and enable |
|
||||||
|
| **AUX** | `0x1FFF_0018` | 4 bytes | RW | Auxiliary interrupt data channel |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `0x1FFF_0000`: **STATUS/COMMAND**
|
### `0x1FFF_0000`: **SCR**
|
||||||
|
|
||||||
| name | bits | access | meaning |
|
| name | bits | access | meaning |
|
||||||
| ------------- | ------ | ------ | ----------------------------------------------------- |
|
| ----------------- | ------ | ------ | ------------------------------------------------------------ |
|
||||||
| `CMD_BUSY` | [31] | R | `1` if dispatched command is pending/executing |
|
| `CMD_BUSY` | [31] | R | `1` if dispatched command is pending/executing |
|
||||||
| `CMD_ERROR` | [30] | R | `1` if last executed command returned with error code |
|
| `CMD_ERROR` | [30] | R | `1` if last executed command returned with error code |
|
||||||
| `IRQ_PENDING` | [29] | R | `1` if flashcart has raised an interrupt |
|
| `BTN_IRQ_PENDING` | [29] | R | `1` if flashcart has raised a "button pressed" interrupt |
|
||||||
| N/A | [28:8] | N/A | Unused, write `0` for future compatibility |
|
| `BTN_IRQ_MASK` | [28] | R | `1` means "button pressed" interrupt is enabled (always `1`) |
|
||||||
| `CMD_ID` | [7:0] | RW | Command ID to be executed |
|
| `CMD_IRQ_PENDING` | [27] | R | `1` if flashcart has raised a "command finish" interrupt |
|
||||||
|
| `CMD_IRQ_MASK` | [26] | R | `1` means "command finish" interrupt is enabled (always `1`) |
|
||||||
|
| `USB_IRQ_PENDING` | [25] | R | `1` if flashcart has raised an "USB not empty" interrupt |
|
||||||
|
| `USB_IRQ_MASK` | [24] | R | `1` means "USB not empty" interrupt is enabled |
|
||||||
|
| `AUX_IRQ_PENDING` | [23] | R | `1` if flashcart has raised an "AUX not empty" interrupt |
|
||||||
|
| `AUX_IRQ_MASK` | [22] | R | `1` means "AUX not empty" interrupt is enabled |
|
||||||
|
| N/A | [21:9] | N/A | Unused, write `0` for future compatibility |
|
||||||
|
| `CMD_IRQ_REQUEST` | [8] | RW | Raise cart interrupt signal when command finishes execution |
|
||||||
|
| `CMD_ID` | [7:0] | RW | Command ID to be executed |
|
||||||
|
|
||||||
Note: Write to this register raises `CMD_BUSY` bit and clears `CMD_ERROR` bit. Flashcart then will start executing provided command.
|
Note: Write to this register raises `CMD_BUSY` bit and clears `CMD_ERROR` bit. Flashcart then will start executing provided command.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `0x1FFF_0004`: **DATA0** and `0x1FFF_0008`: **DATA1**
|
### `0x1FFF_0004`: **DATA0** / `0x1FFF_0008`: **DATA1**
|
||||||
|
|
||||||
| name | bits | access | meaning |
|
| name | bits | access | meaning |
|
||||||
| --------- | ------ | ------ | ---------------------------------- |
|
| --------- | ------ | ------ | ---------------------------------- |
|
||||||
| `DATA0/1` | [31:0] | RW | Command argument (W) or result (R) |
|
| `DATA0/1` | [31:0] | RW | Command argument (W) or result (R) |
|
||||||
|
|
||||||
Note: Result is valid only when command has executed and `CMD_BUSY` bit is reset. When `CMD_ERROR` is set then **DATA0** register contains error code.
|
Note: Result is valid only when command has finished execution and `CMD_BUSY` bit is reset.
|
||||||
|
When `CMD_ERROR` is set then **DATA0** register contains error code.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `0x1FFF_000C`: **IDENTIFIER**
|
### `0x1FFF_000C`: **IDENTIFIER**
|
||||||
|
|
||||||
| name | bits | access | meaning |
|
| name | bits | access | meaning |
|
||||||
| ------------ | ------ | ------ | ------------------------------------------------- |
|
| ------------ | ------ | ------ | ----------------------------------- |
|
||||||
| `IDENTIFIER` | [31:0] | RW | Flashcart identifier (ASCII `SCv2`) and IRQ clear |
|
| `IDENTIFIER` | [31:0] | R | Flashcart identifier (ASCII `SCv2`) |
|
||||||
|
|
||||||
Note: Writing any value to this register will clear pending flashcart interrupt.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `0x1FFF_0010`: **KEY**
|
### `0x1FFF_0010`: **KEY**
|
||||||
|
|
||||||
| name | bits | access | meaning |
|
| name | bits | access | meaning |
|
||||||
| ----- | ------ | ------ | ------------------------------------------ |
|
| ----- | ------ | ------ | ------------------------------------------ |
|
||||||
@ -140,19 +154,86 @@ Note: Writing any value to this register will clear pending flashcart interrupt.
|
|||||||
|
|
||||||
Note: By default from cold boot (power on) or console reset (NMI) flashcart will disable access to SC64 specific memory regions.
|
Note: By default from cold boot (power on) or console reset (NMI) flashcart will disable access to SC64 specific memory regions.
|
||||||
**KEY** register is always enabled and listening for writes regardless of lock/unlock state.
|
**KEY** register is always enabled and listening for writes regardless of lock/unlock state.
|
||||||
To enable SC64 registers it is necesarry to provide sequence of values to this register.
|
To enable SC64 registers it is necessary to provide sequence of values to this register.
|
||||||
Value `0x00000000` will reset sequencer state.
|
Value `0x00000000` will reset sequencer state.
|
||||||
Two consequentive writes of values `0x5F554E4C` and `0x4F434B5F` will unlock all SC64 registers if flashcart is in lock state.
|
Two consecutive writes of values `0x5F554E4C` and `0x4F434B5F` will unlock all SC64 registers if flashcart is in lock state.
|
||||||
Value `0xFFFFFFFF` will lock all SC64 registers if flashcart is in unlock state.
|
Value `0xFFFFFFFF` will lock all SC64 registers if flashcart is in unlock state.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Command execution flow
|
### `0x1FFF_0014`: **IRQ**
|
||||||
|
|
||||||
1. Check if command is already executing by reading `CMD_BUSY` bit in **STATUS/COMMAND** register (optional).
|
| name | bits | access | meaning |
|
||||||
|
| ----------------- | ------- | ------ | ---------------------------------------------- |
|
||||||
|
| `BTN_CLEAR` | [31] | W | Write `1` to clear "button pressed" interrupt |
|
||||||
|
| `CMD_CLEAR` | [30] | W | Write `1` to clear "command finish" interrupt |
|
||||||
|
| `USB_CLEAR` | [29] | W | Write `1` to clear "USB not empty" interrupt |
|
||||||
|
| `AUX_CLEAR` | [28] | W | Write `1` to clear "AUX not empty" interrupt |
|
||||||
|
| N/A | [27:12] | N/A | Unused, write `0` for future compatibility |
|
||||||
|
| `USB_IRQ_DISABLE` | [11] | W | Write `1` to disable "USB not empty" interrupt |
|
||||||
|
| `USB_IRQ_ENABLE` | [10] | W | Write `1` to enable "USB not empty" interrupt |
|
||||||
|
| `AUX_IRQ_DISABLE` | [9] | W | Write `1` to disable "AUX not empty" interrupt |
|
||||||
|
| `AUX_IRQ_ENABLE` | [8] | W | Write `1` to enable "AUX not empty" interrupt |
|
||||||
|
| N/A | [7:0] | N/A | Unused, write `0` for future compatibility |
|
||||||
|
|
||||||
|
Note: All interrupts are cleared and disabled when any of the following events occur:
|
||||||
|
- Hard reset
|
||||||
|
- NMI reset
|
||||||
|
- SC64 registers lock
|
||||||
|
|
||||||
|
SC64 interrupts are completely disabled when register access is not enabled.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `0x1FFF_0018`: **AUX**
|
||||||
|
|
||||||
|
This register can be used as a very simple interface to the PC via USB.
|
||||||
|
Writing to this register generates an USB transfer with the contents of the written data.
|
||||||
|
New data available in the register are signaled via cart interrupt that needs to be enabled beforehand by setting `AUX_IRQ_ENABLE` bit in the **IRQ** register.
|
||||||
|
Status can be also manually polled by checking `AUX_IRQ_PENDING` bit in **SCR** register.
|
||||||
|
Interrupt needs to be acknowledged by setting `AUX_CLEAR` bit in the **IRQ** register.
|
||||||
|
There is no flow control, use this register as a ping-pong interface.
|
||||||
|
For example, PC sends AUX data, N64 receives interrupt, reads the data then writes to this register with a response.
|
||||||
|
This flow can be reversed if needed - N64 can be the initiating side.
|
||||||
|
|
||||||
|
| name | bits | access | meaning |
|
||||||
|
| ------ | ------ | ------ | -------------- |
|
||||||
|
| `DATA` | [31:0] | RW | Arbitrary data |
|
||||||
|
|
||||||
|
This register is used by the upload process in the `sc64deployer` to notify running app on the N64 about certain events.
|
||||||
|
All `DATA` values with upper 8 bits set to `1` (`0xFFxxxxxx`) are reserved for internal use by the SC64.
|
||||||
|
Refrain from using these values in your app for uses other than listed below.
|
||||||
|
Currently defined reserved `DATA` values are:
|
||||||
|
|
||||||
|
- `0xFF000000` - **Ping** - no-op command to test if app running on the N64 is listening to the AUX events.
|
||||||
|
- `0xFF000001` - **Halt** - causes the running app to stop all activity and wait in preparation for uploading new ROM to the SC64.
|
||||||
|
App still should listen to the AUX interrupt and respond to other messages.
|
||||||
|
- `0xFF000002` - **Reboot** - causes the running app to perform soft reboot by reloading IPL3 from the ROM and start executing it.
|
||||||
|
|
||||||
|
App running on the N64 shall respond to the AUX message with the same `DATA` value as incoming event for all events listed above, unless it's specified otherwise.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Command execution flow
|
||||||
|
|
||||||
|
### Without interrupt
|
||||||
|
|
||||||
|
1. Check if command is already executing by reading `CMD_BUSY` bit in **SCR** register (optional).
|
||||||
2. Write command argument values to **DATA0** and **DATA1** registers, can be skipped if command doesn't require it.
|
2. Write command argument values to **DATA0** and **DATA1** registers, can be skipped if command doesn't require it.
|
||||||
3. Write command ID to **STATUS/COMMAND** register.
|
3. Write command ID to **SCR** register.
|
||||||
4. Wait for `CMD_BUSY` bit in **STATUS/COMMAND** register to go low.
|
4. Wait for `CMD_BUSY` bit in **SCR** register to go low.
|
||||||
5. Check if `CMD_ERROR` bit in **STATUS/COMMAND** is set:
|
5. Check if `CMD_ERROR` bit in **SCR** is set:
|
||||||
|
- If error is set then read **DATA0** register containing error code.
|
||||||
|
- If error is not set then read **DATA0** and **DATA1** registers containing command result values, can be skipped if command doesn't return any values.
|
||||||
|
|
||||||
|
### With interrupt
|
||||||
|
|
||||||
|
1. Check if command is already executing by reading `CMD_BUSY` bit in **SCR** register (optional).
|
||||||
|
2. Write command argument values to **DATA0** and **DATA1** registers, can be skipped if command doesn't require it.
|
||||||
|
3. Write command ID to **SCR** register and set `CMD_IRQ_REQUEST` bit high.
|
||||||
|
4. Wait for cart interrupt.
|
||||||
|
5. Check (in cart interrupt handler) if `CMD_IRQ_PENDING` bit in **SCR** register is set high.
|
||||||
|
6. Clear interrupt by setting `CMD_CLEAR` bit high in the **IRQ** register.
|
||||||
|
7. Check if `CMD_ERROR` bit in **SCR** is set:
|
||||||
- If error is set then read **DATA0** register containing error code.
|
- If error is set then read **DATA0** register containing error code.
|
||||||
- If error is not set then read **DATA0** and **DATA1** registers containing command result values, can be skipped if command doesn't return any values.
|
- If error is not set then read **DATA0** and **DATA1** registers containing command result values, can be skipped if command doesn't return any values.
|
||||||
|
@ -4,27 +4,28 @@
|
|||||||
|
|
||||||
## N64 commands
|
## N64 commands
|
||||||
|
|
||||||
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
||||||
| --- | --------------------- | -------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
|
| --- | --------------------- | ------------- | ------------ | ---------------- | -------------- | ------------------------------------------------------------ |
|
||||||
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
||||||
| `V` | **VERSION_GET** | --- | --- | major/minor | revision | Get flashcart firmware version |
|
| `V` | **VERSION_GET** | --- | --- | major/minor | revision | Get flashcart firmware version |
|
||||||
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
||||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
||||||
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||||
| `A` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
| `A` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
||||||
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
||||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
||||||
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
||||||
| `M` | **USB_WRITE** | pi_address | length/type | --- | --- | Send data from from flashcart to USB |
|
| `M` | **USB_WRITE** | pi_address | length/type | --- | --- | Send data from from flashcart to USB |
|
||||||
| `u` | **USB_READ_STATUS** | --- | --- | read_status/type | length | Get USB read status and type/length |
|
| `u` | **USB_READ_STATUS** | --- | --- | read_status/type | length | Get USB read status and type/length |
|
||||||
| `U` | **USB_WRITE_STATUS** | --- | --- | write_status | --- | Get USB write status |
|
| `U` | **USB_WRITE_STATUS** | --- | --- | write_status | --- | Get USB write status |
|
||||||
| `i` | **SD_CARD_OP** | pi_address | operation | --- | return_data | Perform special operation on SD card |
|
| `i` | **SD_CARD_OP** | pi_address | operation | --- | return_data | Perform special operation on the SD card |
|
||||||
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation |
|
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation |
|
||||||
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart |
|
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from the SD card to flashcart memory space |
|
||||||
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card |
|
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from the flashcart memory space to the SD card |
|
||||||
| `D` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
|
| `D` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
|
||||||
| `w` | **WRITEBACK_PENDING** | --- | --- | pending_status | --- | Get save writeback status (is write queued to the SD card) |
|
| `w` | **WRITEBACK_PENDING** | --- | --- | pending_status | --- | Get save writeback status (is write queued to the SD card) |
|
||||||
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
||||||
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
||||||
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
||||||
| `P` | **FLASH_ERASE_BLOCK** | pi_address | --- | --- | --- | Start flash block erase |
|
| `P` | **FLASH_ERASE_BLOCK** | pi_address | --- | --- | --- | Start flash block erase |
|
||||||
|
| `%` | **DIAGNOSTIC_GET** | diagnostic_id | --- | --- | value | Get diagnostic data |
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
- [PC -\> SC64 packets](#pc---sc64-packets)
|
- [PC -\> SC64 packets](#pc---sc64-packets)
|
||||||
- [**`CMD`** packet](#cmd-packet)
|
- [**`CMD`** packet](#cmd-packet)
|
||||||
- [SC64 -\> PC packets](#sc64---pc-packets)
|
- [SC64 -\> PC packets](#sc64---pc-packets)
|
||||||
- [**`RSP`/`ERR`** packets](#rsperr-packets)
|
- [**`CMP`/`ERR`** packets](#cmperr-packets)
|
||||||
- [**`PKT`** packet](#pkt-packet)
|
- [**`PKT`** packet](#pkt-packet)
|
||||||
- [Supported commands](#supported-commands)
|
- [Supported commands](#supported-commands)
|
||||||
- [`v`: **IDENTIFIER\_GET**](#v-identifier_get)
|
- [`v`: **IDENTIFIER\_GET**](#v-identifier_get)
|
||||||
@ -43,13 +43,33 @@
|
|||||||
- [`arg0` (type)](#arg0-type)
|
- [`arg0` (type)](#arg0-type)
|
||||||
- [`arg1` (length)](#arg1-length-2)
|
- [`arg1` (length)](#arg1-length-2)
|
||||||
- [`data` (data)](#data-data-1)
|
- [`data` (data)](#data-data-1)
|
||||||
|
- [`X`: **AUX\_WRITE**](#x-aux_write)
|
||||||
|
- [`arg0` (data)](#arg0-data)
|
||||||
|
- [`i`: **SD\_CARD\_OP**](#i-sd_card_op)
|
||||||
|
- [`arg0` (address)](#arg0-address-2)
|
||||||
|
- [`arg1` (operation)](#arg1-operation)
|
||||||
|
- [`response` (result/status)](#response-resultstatus)
|
||||||
|
- [Available SD card operations](#available-sd-card-operations)
|
||||||
|
- [SD card status](#sd-card-status)
|
||||||
|
- [`s`: **SD\_READ**](#s-sd_read)
|
||||||
|
- [`arg0` (address)](#arg0-address-3)
|
||||||
|
- [`arg1` (sector\_count)](#arg1-sector_count)
|
||||||
|
- [`data` (sector)](#data-sector)
|
||||||
|
- [`response` (result)](#response-result)
|
||||||
|
- [`S`: **SD\_WRITE**](#s-sd_write)
|
||||||
|
- [`arg0` (address)](#arg0-address-4)
|
||||||
|
- [`arg1` (sector\_count)](#arg1-sector_count-1)
|
||||||
|
- [`data` (sector)](#data-sector-1)
|
||||||
|
- [`response` (result)](#response-result-1)
|
||||||
- [`D`: **DD\_SET\_BLOCK\_READY**](#d-dd_set_block_ready)
|
- [`D`: **DD\_SET\_BLOCK\_READY**](#d-dd_set_block_ready)
|
||||||
- [`arg0` (error)](#arg0-error)
|
- [`arg0` (error)](#arg0-error)
|
||||||
- [`W`: **WRITEBACK\_ENABLE**](#w-writeback_enable)
|
- [`W`: **WRITEBACK\_ENABLE**](#w-writeback_enable)
|
||||||
- [Asynchronous packets](#asynchronous-packets)
|
- [Asynchronous packets](#asynchronous-packets)
|
||||||
|
- [`X`: **AUX\_DATA**](#x-aux_data)
|
||||||
|
- [`data` (data)](#data-data-2)
|
||||||
- [`B`: **BUTTON**](#b-button)
|
- [`B`: **BUTTON**](#b-button)
|
||||||
- [`U`: **DATA**](#u-data)
|
- [`U`: **DATA**](#u-data)
|
||||||
- [`data` (data)](#data-data-2)
|
- [`data` (data)](#data-data-3)
|
||||||
- [`G`: **DATA\_FLUSHED**](#g-data_flushed)
|
- [`G`: **DATA\_FLUSHED**](#g-data_flushed)
|
||||||
- [`D`: **DISK\_REQUEST**](#d-disk_request)
|
- [`D`: **DISK\_REQUEST**](#d-disk_request)
|
||||||
- [`data` (disk\_info/block\_data)](#data-disk_infoblock_data)
|
- [`data` (disk\_info/block\_data)](#data-disk_infoblock_data)
|
||||||
@ -108,29 +128,29 @@ Packet data length is derived from the argument if specific command supports it.
|
|||||||
|
|
||||||
| identifier | description |
|
| identifier | description |
|
||||||
| ---------- | ---------------------------------------- |
|
| ---------- | ---------------------------------------- |
|
||||||
| `RSP` | Success response to the received command |
|
| `CMP` | Success response to the received command |
|
||||||
| `ERR` | Error response to the received command |
|
| `ERR` | Error response to the received command |
|
||||||
| `PKT` | Asynchronous data packet |
|
| `PKT` | Asynchronous data packet |
|
||||||
|
|
||||||
SC64 sends response packet `RSP`/`ERR` to almost every command received from the PC.
|
SC64 sends response packet `CMP`/`ERR` to almost every command received from the PC.
|
||||||
Fourth byte is the same as in the command that triggered the response.
|
Fourth byte is the same as in the command that triggered the response.
|
||||||
If command execution was not successful, then `RSP` identifier is replaced by the `ERR` identifier.
|
If command execution was not successful, then `CMP` identifier is replaced by the `ERR` identifier.
|
||||||
|
|
||||||
SC64 can also send `PKT` packet at any time as a response to action triggered by the N64 or the flashcart itself.
|
SC64 can also send `PKT` packet at any time as a response to action triggered by the N64 or the flashcart itself.
|
||||||
Fourth byte denotes packet ID listed in the [asynchronous packets](#asynchronous-packets) section.
|
Fourth byte denotes packet ID listed in the [asynchronous packets](#asynchronous-packets) section.
|
||||||
|
|
||||||
#### **`RSP`/`ERR`** packets
|
#### **`CMP`/`ERR`** packets
|
||||||
|
|
||||||
General structure of packet:
|
General structure of packet:
|
||||||
| offset | type | description |
|
| offset | type | description |
|
||||||
| ------ | -------------------- | ---------------------- |
|
| ------ | -------------------- | ---------------------- |
|
||||||
| `0` | char[3] | `RSP`/`ERR` identifier |
|
| `0` | char[3] | `CMP`/`ERR` identifier |
|
||||||
| `3` | char[1] | Command ID |
|
| `3` | char[1] | Command ID |
|
||||||
| `4` | uint32_t | Response data length |
|
| `4` | uint32_t | Response data length |
|
||||||
| `8` | uint8_t[data_length] | Response data (if any) |
|
| `8` | uint8_t[data_length] | Response data (if any) |
|
||||||
|
|
||||||
`RSP`/`ERR` packet is sent as a response to the command sent by the PC.
|
`CMP`/`ERR` packet is sent as a response to the command sent by the PC.
|
||||||
`ERR` response might contain no (or undefined) data in the arbitrary data field compared to regular `RSP` packet.
|
`ERR` response might contain no (or undefined) data in the arbitrary data field compared to regular `CMP` packet.
|
||||||
|
|
||||||
#### **`PKT`** packet
|
#### **`PKT`** packet
|
||||||
|
|
||||||
@ -148,29 +168,33 @@ Available packet IDs are listed in the [asynchronous packets](#asynchronous-pack
|
|||||||
|
|
||||||
## Supported commands
|
## Supported commands
|
||||||
|
|
||||||
| id | name | arg0 | arg1 | data | response | description |
|
| id | name | arg0 | arg1 | data | response | description |
|
||||||
| --- | ----------------------------------------------- | ------------ | ------------- | ---- | ---------------- | ------------------------------------------------------------- |
|
| --- | ----------------------------------------------- | ------------ | ------------- | ------ | ---------------- | -------------------------------------------------------------- |
|
||||||
| `v` | [**IDENTIFIER_GET**](#v-identifier_get) | --- | --- | --- | identifier | Get flashcart identifier `SCv2` |
|
| `v` | [**IDENTIFIER_GET**](#v-identifier_get) | --- | --- | --- | identifier | Get flashcart identifier `SCv2` |
|
||||||
| `V` | [**VERSION_GET**](#v-version_get) | --- | --- | --- | version | Get flashcart firmware version |
|
| `V` | [**VERSION_GET**](#v-version_get) | --- | --- | --- | version | Get flashcart firmware version |
|
||||||
| `R` | [**STATE_RESET**](#r-state_reset) | --- | --- | --- | --- | Reset flashcart state (CIC params and config options) |
|
| `R` | [**STATE_RESET**](#r-state_reset) | --- | --- | --- | --- | Reset flashcart state (CIC params and config options) |
|
||||||
| `B` | [**CIC_PARAMS_SET**](#b-cic_params_set) | cic_params_0 | cic_params_1 | --- | --- | Set CIC emulation parameters (disable/seed/checksum) |
|
| `B` | [**CIC_PARAMS_SET**](#b-cic_params_set) | cic_params_0 | cic_params_1 | --- | --- | Set CIC emulation parameters (disable/seed/checksum) |
|
||||||
| `c` | [**CONFIG_GET**](#c-config_get) | config_id | --- | --- | config_value | Get config option |
|
| `c` | [**CONFIG_GET**](#c-config_get) | config_id | --- | --- | config_value | Get config option |
|
||||||
| `C` | [**CONFIG_SET**](#c-config_set) | config_id | config_value | --- | --- | Set config option |
|
| `C` | [**CONFIG_SET**](#c-config_set) | config_id | config_value | --- | --- | Set config option |
|
||||||
| `a` | [**SETTING_GET**](#a-setting_get) | setting_id | --- | --- | setting_value | Get persistent setting option |
|
| `a` | [**SETTING_GET**](#a-setting_get) | setting_id | --- | --- | setting_value | Get persistent setting option |
|
||||||
| `A` | [**SETTING_SET**](#a-setting_set) | setting_id | setting_value | --- | --- | Set persistent setting option |
|
| `A` | [**SETTING_SET**](#a-setting_set) | setting_id | setting_value | --- | --- | Set persistent setting option |
|
||||||
| `t` | [**TIME_GET**](#t-time_get) | --- | --- | --- | time | Get current RTC value |
|
| `t` | [**TIME_GET**](#t-time_get) | --- | --- | --- | time | Get current RTC value |
|
||||||
| `T` | [**TIME_SET**](#t-time_set) | time_0 | time_1 | --- | --- | Set new RTC value |
|
| `T` | [**TIME_SET**](#t-time_set) | time_0 | time_1 | --- | --- | Set new RTC value |
|
||||||
| `m` | [**MEMORY_READ**](#m-memory_read) | address | length | --- | data | Read data from specified memory address |
|
| `m` | [**MEMORY_READ**](#m-memory_read) | address | length | --- | data | Read data from specified memory address |
|
||||||
| `M` | [**MEMORY_WRITE**](#m-memory_write) | address | length | data | --- | Write data to specified memory address |
|
| `M` | [**MEMORY_WRITE**](#m-memory_write) | address | length | data | --- | Write data to specified memory address |
|
||||||
| `U` | [**USB_WRITE**](#u-usb_write) | type | length | data | N/A | Send data to be received by app running on N64 (no response!) |
|
| `U` | [**USB_WRITE**](#u-usb_write) | type | length | data | N/A | Send data to be received by app running on N64 (no response!) |
|
||||||
| `D` | [**DD_SET_BLOCK_READY**](#d-dd_set_block_ready) | error | --- | --- | --- | Notify flashcart about 64DD block readiness |
|
| `X` | [**AUX_WRITE**](#x-aux_write) | data | --- | --- | --- | Send small auxiliary data to be received by app running on N64 |
|
||||||
| `W` | [**WRITEBACK_ENABLE**](#w-writeback_enable) | --- | --- | --- | --- | Enable save writeback through USB packet |
|
| `i` | [**SD_CARD_OP**](#i-sd_card_op) | address | operation | --- | result/status | Perform special operation on the SD card |
|
||||||
| `p` | **FLASH_WAIT_BUSY** | wait | --- | --- | erase_block_size | Wait until flash ready / Get flash block erase size |
|
| `s` | [**SD_READ**](#s-sd_read) | address | sector_count | sector | result | Read sectors from the SD card to flashcart memory space |
|
||||||
| `P` | **FLASH_ERASE_BLOCK** | address | --- | --- | --- | Start flash block erase |
|
| `S` | [**SD_WRITE**](#s-sd_write) | address | sector_count | sector | result | Write sectors from the flashcart memory space to the SD card |
|
||||||
| `f` | **FIRMWARE_BACKUP** | address | --- | --- | status/length | Backup firmware to specified memory address |
|
| `D` | [**DD_SET_BLOCK_READY**](#d-dd_set_block_ready) | error | --- | --- | --- | Notify flashcart about 64DD block readiness |
|
||||||
| `F` | **FIRMWARE_UPDATE** | address | length | --- | status | Update firmware from specified memory address |
|
| `W` | [**WRITEBACK_ENABLE**](#w-writeback_enable) | --- | --- | --- | --- | Enable save writeback through USB packet |
|
||||||
| `?` | **DEBUG_GET** | --- | --- | --- | debug_data | Get internal FPGA debug info |
|
| `p` | **FLASH_WAIT_BUSY** | wait | --- | --- | erase_block_size | Wait until flash ready / Get flash block erase size |
|
||||||
| `%` | **STACK_USAGE_GET** | --- | --- | --- | stack_usage | Get per task stack usage |
|
| `P` | **FLASH_ERASE_BLOCK** | address | --- | --- | --- | Start flash block erase |
|
||||||
|
| `f` | **FIRMWARE_BACKUP** | address | --- | --- | status/length | Backup firmware to specified memory address |
|
||||||
|
| `F` | **FIRMWARE_UPDATE** | address | length | --- | status | Update firmware from specified memory address |
|
||||||
|
| `?` | **DEBUG_GET** | --- | --- | --- | debug_data | Get internal FPGA debug info |
|
||||||
|
| `%` | **DIAGNOSTIC_GET** | --- | --- | --- | diagnostic_data | Get diagnostic data |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -218,7 +242,7 @@ _This command does not require arguments or data._
|
|||||||
_This command does not send response data._
|
_This command does not send response data._
|
||||||
|
|
||||||
This command is used to reset most of the config options to default state (same as on power-up).
|
This command is used to reset most of the config options to default state (same as on power-up).
|
||||||
Additionally, CIC emulation is enabled and 6102/7101 seed/checksum values are set.
|
Additionally, CIC emulation is enabled, 6102/7101 seed/checksum values are set and SD card lock is released.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -328,16 +352,16 @@ Use this command to set value of persistent setting option. Available persistent
|
|||||||
_This command does not require arguments or data._
|
_This command does not require arguments or data._
|
||||||
|
|
||||||
#### `response` (time)
|
#### `response` (time)
|
||||||
| offset | type | description |
|
| offset | type | description |
|
||||||
| ------ | ------- | ------------------------------------ |
|
| ------ | ------- | --------------------------------------- |
|
||||||
| `0` | uint8_t | Weekday (1 - 7), 1 represents Monday |
|
| `0` | uint8_t | Weekday (1 - 7), 1 represents Monday |
|
||||||
| `1` | uint8_t | Hours (0 - 23) |
|
| `1` | uint8_t | Hours (0 - 23) |
|
||||||
| `2` | uint8_t | Minutes (0 - 59) |
|
| `2` | uint8_t | Minutes (0 - 59) |
|
||||||
| `3` | uint8_t | Seconds (0 - 59) |
|
| `3` | uint8_t | Seconds (0 - 59) |
|
||||||
| `4` | uint8_t | _Unused_ (returns zero) |
|
| `4` | uint8_t | Century (0 - 7), 0 represents year 1900 |
|
||||||
| `5` | uint8_t | Year (0 - 99) |
|
| `5` | uint8_t | Year (0 - 99) |
|
||||||
| `6` | uint8_t | Month (1 - 12) |
|
| `6` | uint8_t | Month (1 - 12) |
|
||||||
| `7` | uint8_t | Day (1 - 31) |
|
| `7` | uint8_t | Day (1 - 31) |
|
||||||
|
|
||||||
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format.
|
Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decimal) format.
|
||||||
|
|
||||||
@ -356,12 +380,12 @@ Date/time values use the [BCD](https://en.wikipedia.org/wiki/Binary-coded_decima
|
|||||||
| `[7:0]` | Seconds (0 - 59) |
|
| `[7:0]` | Seconds (0 - 59) |
|
||||||
|
|
||||||
#### `arg1` (time_1)
|
#### `arg1` (time_1)
|
||||||
| bits | description |
|
| bits | description |
|
||||||
| --------- | -------------- |
|
| --------- | --------------------------------------- |
|
||||||
| `[31:24]` | _Unused_ |
|
| `[31:24]` | Century (0 - 7), 0 represents year 1900 |
|
||||||
| `[23:16]` | Year (0 - 99) |
|
| `[23:16]` | Year (0 - 99) |
|
||||||
| `[15:8]` | Month (1 - 12) |
|
| `[15:8]` | Month (1 - 12) |
|
||||||
| `[7:0]` | Day (1 - 31) |
|
| `[7:0]` | Day (1 - 31) |
|
||||||
|
|
||||||
_This command does not send response data._
|
_This command does not send response data._
|
||||||
|
|
||||||
@ -439,7 +463,7 @@ Writes bytes to the specified memory address. Please refer to the [internal memo
|
|||||||
|
|
||||||
_This command does not send response data._
|
_This command does not send response data._
|
||||||
|
|
||||||
_This command does not send `RSP`/`ERR` packet response!_
|
_This command does not send `CMP`/`ERR` packet response!_
|
||||||
|
|
||||||
This command notifies N64 that data is waiting to be acknowledged.
|
This command notifies N64 that data is waiting to be acknowledged.
|
||||||
If N64 side doesn't acknowledge data via [`m` **USB_READ**](./02_n64_commands.md#m-usb_read) N64 command within 1 second then data is flushed and [`G` **DATA_FLUSHED**](#asynchronous-packets) asynchronous packet is sent to the PC.
|
If N64 side doesn't acknowledge data via [`m` **USB_READ**](./02_n64_commands.md#m-usb_read) N64 command within 1 second then data is flushed and [`G` **DATA_FLUSHED**](#asynchronous-packets) asynchronous packet is sent to the PC.
|
||||||
@ -447,6 +471,125 @@ If N64 acknowledge the request, then data is written to the flashcart memory to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `X`: **AUX_WRITE**
|
||||||
|
|
||||||
|
**Send small auxiliary data to be received by app running on N64**
|
||||||
|
|
||||||
|
#### `arg0` (data)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `[31:0]` | Data |
|
||||||
|
|
||||||
|
_This command does not send response data._
|
||||||
|
|
||||||
|
This command puts 32 bits of data to the AUX register accessible from the N64 side, and generates cart interrupt (if enabled).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `i`: **SD_CARD_OP**
|
||||||
|
|
||||||
|
**Perform special operation on the SD card**
|
||||||
|
|
||||||
|
#### `arg0` (address)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `[31:0]` | Address |
|
||||||
|
|
||||||
|
#### `arg1` (operation)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `[31:0]` | Operation |
|
||||||
|
|
||||||
|
#### `response` (result/status)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| `0` | uint32_t | Operation result (valid values are listed in the [sd_error_t](../sw/controller/src/sd.h) enum) |
|
||||||
|
| `4` | uint32_t | SD card status (always returned and valid regardless of the SD card operation result) |
|
||||||
|
|
||||||
|
This command performs special operation on the SD card. When operation result is not `SD_OK`, then `ERR` packet is returned.
|
||||||
|
PC and N64 cannot use the SD card interface at the same time. Lock mechanism is implemented to prevent data corruption.
|
||||||
|
SD card access is locked when PC or N64 requests SD card initialization, and unlocked when the card is uninitialized.
|
||||||
|
Lock is also released when certain conditions occur - when N64 side lock is active then it is released when the console is powered off
|
||||||
|
and save writeback operation is not pending. PC side lock is released when USB interface is in reset state, or the USB cable is unplugged.
|
||||||
|
|
||||||
|
#### Available SD card operations
|
||||||
|
| operation | description |
|
||||||
|
| --------- | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| `0` | Init SD card |
|
||||||
|
| `1` | Deinit SD card |
|
||||||
|
| `2` | Get SD card status |
|
||||||
|
| `3` | Get SD card info (loads CSD and CID registers to a specified address, data length is 32 bytes) |
|
||||||
|
| `4` | Turn on byte swap |
|
||||||
|
| `5` | Turn off byte swap |
|
||||||
|
|
||||||
|
#### SD card status
|
||||||
|
| bits | description |
|
||||||
|
| -------- | -------------------------------------------------------------------------- |
|
||||||
|
| `[31:5]` | _Unused_ |
|
||||||
|
| `[4]` | `0` - Byte swap disabled, `1` - Byte swap enabled (valid when initialized) |
|
||||||
|
| `[3]` | `0` - 25 MHz clock, `1` - 50 MHz clock (valid when initialized) |
|
||||||
|
| `[2]` | `0` - Byte addressed, `1` - Sector addressed (valid when initialized) |
|
||||||
|
| `[1]` | `0` - SD card not initialized, `1` - SD card initialized |
|
||||||
|
| `[0]` | `0` - SD card not inserted, `1` - SD card inserted |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `s`: **SD_READ**
|
||||||
|
|
||||||
|
**Read sectors from the SD card to flashcart memory space**
|
||||||
|
|
||||||
|
#### `arg0` (address)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `[31:0]` | Address |
|
||||||
|
|
||||||
|
#### `arg1` (sector_count)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ------------ |
|
||||||
|
| `[31:0]` | Sector count |
|
||||||
|
|
||||||
|
#### `data` (sector)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | --------------- |
|
||||||
|
| `0` | uint32_t | Starting sector |
|
||||||
|
|
||||||
|
#### `response` (result)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| `0` | uint32_t | Operation result (valid values are listed in the [sd_error_t](../sw/controller/src/sd.h) enum) |
|
||||||
|
|
||||||
|
This command reads sectors from the SD card to a specified memory address. When operation result is not `SD_OK`, then `ERR` packet is returned.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `S`: **SD_WRITE**
|
||||||
|
|
||||||
|
**Write sectors from the flashcart memory space to the SD card**
|
||||||
|
|
||||||
|
#### `arg0` (address)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ----------- |
|
||||||
|
| `[31:0]` | Address |
|
||||||
|
|
||||||
|
#### `arg1` (sector_count)
|
||||||
|
| bits | description |
|
||||||
|
| -------- | ------------ |
|
||||||
|
| `[31:0]` | Sector count |
|
||||||
|
|
||||||
|
#### `data` (sector)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | --------------- |
|
||||||
|
| `0` | uint32_t | Starting sector |
|
||||||
|
|
||||||
|
#### `response` (result)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| `0` | uint32_t | Operation result (valid values are listed in the [sd_error_t](../sw/controller/src/sd.h) enum) |
|
||||||
|
|
||||||
|
This command writes sectors from a specified memory address to the SD card. When operation result is not `SD_OK`, then `ERR` packet is returned.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `D`: **DD_SET_BLOCK_READY**
|
### `D`: **DD_SET_BLOCK_READY**
|
||||||
|
|
||||||
**Notify flashcart about 64DD block readiness**
|
**Notify flashcart about 64DD block readiness**
|
||||||
@ -482,6 +625,7 @@ Save data is sent via [**SAVE_WRITEBACK**](#s-save_writeback) asynchronous packe
|
|||||||
|
|
||||||
| id | name | data | description |
|
| id | name | data | description |
|
||||||
| --- | --------------------------------------- | -------------------- | --------------------------------------------------------------------- |
|
| --- | --------------------------------------- | -------------------- | --------------------------------------------------------------------- |
|
||||||
|
| `X` | [**AUX_DATA**](#x-aux_data) | data | Data was written to the `AUX` register from the N64 side |
|
||||||
| `B` | [**BUTTON**](#b-button) | --- | Button on the back of the SC64 was pressed |
|
| `B` | [**BUTTON**](#b-button) | --- | Button on the back of the SC64 was pressed |
|
||||||
| `U` | [**DATA**](#u-data) | data | Data sent from the N64 |
|
| `U` | [**DATA**](#u-data) | data | Data sent from the N64 |
|
||||||
| `G` | [**DATA_FLUSHED**](#g-data_flushed) | --- | Data from [`U` **USB_WRITE**](#u-usb_write) USB command was discarded |
|
| `G` | [**DATA_FLUSHED**](#g-data_flushed) | --- | Data from [`U` **USB_WRITE**](#u-usb_write) USB command was discarded |
|
||||||
@ -490,6 +634,20 @@ Save data is sent via [**SAVE_WRITEBACK**](#s-save_writeback) asynchronous packe
|
|||||||
| `S` | [**SAVE_WRITEBACK**](#s-save_writeback) | save_contents | Flushed save data |
|
| `S` | [**SAVE_WRITEBACK**](#s-save_writeback) | save_contents | Flushed save data |
|
||||||
| `F` | [**UPDATE_STATUS**](#f-update_status) | progress | Firmware update progress |
|
| `F` | [**UPDATE_STATUS**](#f-update_status) | progress | Firmware update progress |
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `X`: **AUX_DATA**
|
||||||
|
|
||||||
|
**Data was written to the `AUX` register from the N64 side**
|
||||||
|
|
||||||
|
This packet is sent when N64 writes to the `AUX` register in the SC64 register block.
|
||||||
|
|
||||||
|
#### `data` (data)
|
||||||
|
| offset | type | description |
|
||||||
|
| ------ | -------- | ----------- |
|
||||||
|
| `0` | uint32_t | Data |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `B`: **BUTTON**
|
### `B`: **BUTTON**
|
||||||
|
@ -133,9 +133,10 @@ type: *enum* | default: `0`
|
|||||||
- `4` - FlashRAM 1 Mib save is enabled
|
- `4` - FlashRAM 1 Mib save is enabled
|
||||||
- `5` - SRAM 768 kib save is enabled
|
- `5` - SRAM 768 kib save is enabled
|
||||||
- `6` - SRAM 1 Mib save is enabled
|
- `6` - SRAM 1 Mib save is enabled
|
||||||
|
- `7` - FakeFlashRAM 1 Mib save is enabled (write/erase timings are not emulated and erase before write is not required)
|
||||||
|
|
||||||
Use this setting for selecting save type that will be emulated. Only one save type can be enabled.
|
Use this setting for selecting save type that will be emulated. Only one save type can be enabled.
|
||||||
Any successful write to this config will disable automatic save writeback to USB or SD card when previously enabled.
|
Any successful write to this config will disable automatic save writeback to the USB or SD card if previously enabled.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
Docker method is a preferred option.
|
Docker method is a preferred option.
|
||||||
Run `./docker_build.sh release` to build all firmware/software and generate release package.
|
Run `./docker_build.sh release` to build all firmware/software and generate release package.
|
||||||
For other options run script without any command to print help.
|
For other options run script without any command to print help about available options.
|
||||||
|
|
||||||
#### Lattice Diamond license
|
#### Lattice Diamond license
|
||||||
|
|
||||||
Lattice Diamond software is used to build FPGA bitstream, a free 1 year license is necessary to run the build process.
|
Lattice Diamond software is used to build the FPGA bitstream.
|
||||||
Repository already contains license attached to fake MAC address `F8:12:34:56:78:90` (path to the license: `fw/project/lcmxo2/license.dat`).
|
A free 1 year license is necessary to run the build process.
|
||||||
If the license expires, it is required to request new license from Lattice webpage.
|
You can request personal license from the [Lattice website](https://www.latticesemi.com/Support/Licensing).
|
||||||
New license can be attached to aforementioned MAC address or any other address.
|
Build script expects license file to be present in this path: `fw/project/lcmxo2/license.dat`.
|
||||||
In case of non default MAC address it is possible to provide it via `MAC_ADDRESS` environment variable.
|
Since build is done inside docker container it is required to pass the MAC address, linked with the license file, to a container.
|
||||||
For example: `MAC_ADDRESS=AB:00:00:00:00:00 ./docker_build.sh release`.
|
Build script expects it in the `MAC_ADDRESS` environment variable.
|
||||||
|
For example, run `MAC_ADDRESS=AB:00:00:00:00:00 ./docker_build.sh release` command to start the building process if your license is attached to `AB:00:00:00:00:00` MAC address.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
- [Video guide](#video-guide)
|
||||||
- [Step by step guide how to make SC64](#step-by-step-guide-how-to-make-sc64)
|
- [Step by step guide how to make SC64](#step-by-step-guide-how-to-make-sc64)
|
||||||
- [**PCB manufacturing data**](#pcb-manufacturing-data)
|
- [**PCB manufacturing data**](#pcb-manufacturing-data)
|
||||||
- [**PCB requirements**](#pcb-requirements)
|
- [**PCB requirements**](#pcb-requirements)
|
||||||
@ -6,10 +7,16 @@
|
|||||||
- [**Putting it together**](#putting-it-together)
|
- [**Putting it together**](#putting-it-together)
|
||||||
- [**Initial programming**](#initial-programming)
|
- [**Initial programming**](#initial-programming)
|
||||||
- [**Troubleshooting**](#troubleshooting)
|
- [**Troubleshooting**](#troubleshooting)
|
||||||
- [*`primer.py` threw error on `Bootloader -> SC64 FLASH` step*](#primerpy-threw-error-on-bootloader---sc64-flash-step)
|
- [*`primer.py` threw `No SC64 USB device found` error*](#primerpy-threw-no-sc64-usb-device-found-error)
|
||||||
|
- [*`primer.py` threw `SDRAM test error...` message*](#primerpy-threw-sdram-test-error-message)
|
||||||
|
- [*`primer.py` threw other error message*](#primerpy-threw-other-error-message)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Video guide
|
||||||
|
|
||||||
|
[](https://www.youtube.com/watch?v=t6hyCFpwqz8 "How to build and program the SummerCart64")
|
||||||
|
|
||||||
## Step by step guide how to make SC64
|
## Step by step guide how to make SC64
|
||||||
|
|
||||||
All necessary manufacturing files are packaged in every `sc64-extra-{version}.zip` file in GitHub releases.
|
All necessary manufacturing files are packaged in every `sc64-extra-{version}.zip` file in GitHub releases.
|
||||||
@ -40,7 +47,7 @@ Please download latest release before proceeding with the instructions.
|
|||||||
|
|
||||||
### **Components**
|
### **Components**
|
||||||
|
|
||||||
1. Locate interactive BOM file inside `hw/pcb` folder
|
1. Locate the interactive BOM file inside `hw/pcb` folder
|
||||||
2. Order all parts listed in the BOM file or use PCB assembly service together with your PCB order
|
2. Order all parts listed in the BOM file or use PCB assembly service together with your PCB order
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -49,7 +56,7 @@ Please download latest release before proceeding with the instructions.
|
|||||||
|
|
||||||
1. Locate `.stl` files inside `hw/shell` folder
|
1. Locate `.stl` files inside `hw/shell` folder
|
||||||
2. Use these files in the slicer and 3D printer of your choice or order ready made prints from 3D printing company
|
2. Use these files in the slicer and 3D printer of your choice or order ready made prints from 3D printing company
|
||||||
3. Find matching screws, go to discussions tab for community recommendations
|
3. For screws, M2x10 works great for the top two holes while M2x8 fits well in the bottom two
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -73,6 +80,7 @@ You will require the following hardware:
|
|||||||
- A USB to UART (serial) adapter (with 3.3V signaling is required, e.g. TTL-232R-3V3).
|
- A USB to UART (serial) adapter (with 3.3V signaling is required, e.g. TTL-232R-3V3).
|
||||||
|
|
||||||
You will require the following applications and packages:
|
You will require the following applications and packages:
|
||||||
|
- [Latest FTDI drivers](https://ftdichip.com/drivers/)
|
||||||
- [FT_PROG](https://ftdichip.com/utilities/#ft_prog) - FTDI FT232H EEPROM programming software.
|
- [FT_PROG](https://ftdichip.com/utilities/#ft_prog) - FTDI FT232H EEPROM programming software.
|
||||||
- [Python 3](https://www.python.org/downloads/) with `pip3` - necessary for initial programming script: `primer.py` (Windows install: check option add python to PATH).
|
- [Python 3](https://www.python.org/downloads/) with `pip3` - necessary for initial programming script: `primer.py` (Windows install: check option add python to PATH).
|
||||||
- [`sc64-extra-{version}.zip`](https://github.com/Polprzewodnikowy/SummerCart64/releases) - programming scripts and firmware files, download the latest version.
|
- [`sc64-extra-{version}.zip`](https://github.com/Polprzewodnikowy/SummerCart64/releases) - programming scripts and firmware files, download the latest version.
|
||||||
@ -80,10 +88,11 @@ You will require the following applications and packages:
|
|||||||
**Programming must be done in specific order for `primer.py` script to work correctly.**
|
**Programming must be done in specific order for `primer.py` script to work correctly.**
|
||||||
|
|
||||||
Preparations:
|
Preparations:
|
||||||
1. Install FT_PROG.
|
1. Install latest FTDI drivers (especially on Windows 10).
|
||||||
2. Install Python 3.
|
2. Install FT_PROG.
|
||||||
3. Unpack `sc64-extra-{version}.zip` into a folder.
|
3. Install Python 3.
|
||||||
4. Open terminal and navigate to the folder you've unpacked SC64 files.
|
4. Unpack `sc64-extra-{version}.zip` into a folder.
|
||||||
|
5. Open terminal and navigate to the folder you've unpacked SC64 files.
|
||||||
|
|
||||||
First, program the ***FT232H EEPROM***:
|
First, program the ***FT232H EEPROM***:
|
||||||
1. Connect the SC64 board to your PC with a USB-C cable.
|
1. Connect the SC64 board to your PC with a USB-C cable.
|
||||||
@ -115,9 +124,21 @@ Congratulations! Your SC64 flashcart should be ready for use!
|
|||||||
|
|
||||||
### **Troubleshooting**
|
### **Troubleshooting**
|
||||||
|
|
||||||
#### *`primer.py` threw error on `Bootloader -> SC64 FLASH` step*
|
#### *`primer.py` threw `No SC64 USB device found` error*
|
||||||
|
|
||||||
This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step.
|
This issue can be attributed to incorrectly programmed FT232H EEPROM in the first programming step.
|
||||||
Check again in `FT_PROG` application if device was configured properly.
|
Check again in `FT_PROG` application if device was configured properly.
|
||||||
|
Make sure default FTDI drivers are installed for the SC64 in the device manager (only on Windows OS).
|
||||||
|
Make sure you have correct access to `/dev/ttyUSBx` device and `ftdi_sio` and `usbserial` modules are loaded (only on Linux OS).
|
||||||
|
|
||||||
|
#### *`primer.py` threw `SDRAM test error...` message*
|
||||||
|
|
||||||
|
This issue shows up when there's a problem with the connection to the SDRAM chip or the chip itself is malfunctioning.
|
||||||
|
Check for any solder bridges and unconnected pins on U8/U9 chips.
|
||||||
Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode.
|
Once FPGA and microcontroller has been programmed successfully `primer.py` script needs to be run in special mode.
|
||||||
Please use command `python3 primer.py COMx sc64-firmware-{version}.bin --bootloader-only` to try programming bootloader again.
|
Please use command `python3 primer.py COMx sc64-firmware-{version}.bin --bootloader-only` to test SDRAM again and continue bootloader programming process.
|
||||||
|
|
||||||
|
#### *`primer.py` threw other error message*
|
||||||
|
Due to multiple possible causes of the problem it's best to start visually inspecting SC64's board for any defects, like bad solder work or chips soldered backwards.
|
||||||
|
If visual inspection didn't yield any obvious culprits then next step would be to check if everything is connected correctly.
|
||||||
|
Check if TX/RX signals aren't swapped and if SC64 is getting power from the USB cable. Best place to check supply voltage are the exposed test pads on the left of U8 chip.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SummerCart64 - a fully open source Nintendo 64 flashcart
|
# SummerCart64 - a fully open source N64 flashcart
|
||||||
[<img src="../assets/sc64_logo.svg" />](../assets/sc64_logo.svg)
|
[<img src="../assets/sc64_logo.svg" />](../assets/sc64_logo.svg)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
2
fw/project/lcmxo2/.gitignore
vendored
2
fw/project/lcmxo2/.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
.recovery
|
.recovery
|
||||||
*.dir/
|
*.dir/
|
||||||
*.ccl
|
*.ccl
|
||||||
|
*.dat
|
||||||
*.dmp
|
*.dmp
|
||||||
*.html
|
*.html
|
||||||
*.ini
|
*.ini
|
||||||
@ -11,6 +12,7 @@
|
|||||||
*.tcl
|
*.tcl
|
||||||
*.tpf
|
*.tpf
|
||||||
*.trc
|
*.trc
|
||||||
|
*.txt
|
||||||
*.xml
|
*.xml
|
||||||
impl*/
|
impl*/
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ set -e
|
|||||||
|
|
||||||
source $bindir/diamond_env
|
source $bindir/diamond_env
|
||||||
|
|
||||||
|
printf "[$(hostname)]\nSYSTEM=Linux\nCORENUM=$(nproc --all)\n" > $(dirname $0)/multicore.txt
|
||||||
|
|
||||||
diamondc build.tcl
|
diamondc build.tcl
|
||||||
|
|
||||||
MINIMUM_FREQ=$(cat impl1/sc64_impl1.twr \
|
MINIMUM_FREQ=$(cat impl1/sc64_impl1.twr \
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
FEATURE LSC_BASE lattice 8.0 11-feb-2024 uncounted 1303CFE67866 \
|
|
||||||
VENDOR_STRING="ispLEVER BASE" HOSTID=f81234567890
|
|
||||||
FEATURE LSC_SYNPLIFY lattice 8.0 11-feb-2024 uncounted B52A4FF71CC8 \
|
|
||||||
VENDOR_STRING="ispLEVER System with Synplicity" \
|
|
||||||
HOSTID=f81234567890
|
|
||||||
FEATURE LSC_SYNPLIFYPRO1 lattice 10.0 11-feb-2024 uncounted \
|
|
||||||
30EA214E8213 VENDOR_STRING="ispLEVER System with Synplicity \
|
|
||||||
Pro 1" HOSTID=f81234567890
|
|
||||||
FEATURE LSC_ADVANCED_DSP lattice 10.0 11-feb-2024 uncounted \
|
|
||||||
1BFB494C1D0D VENDOR_STRING="ispLEVER DSP" HOSTID=f81234567890
|
|
||||||
FEATURE LSC_DIAMOND_A lattice 10.0 11-feb-2024 uncounted 1067C09C10BA \
|
|
||||||
VENDOR_STRING="Diamond Free" HOSTID=f81234567890
|
|
||||||
FEATURE LSC_PROGRAMMER_MATURE lattice 10.0 11-feb-2024 uncounted \
|
|
||||||
4559F34D65AB VENDOR_STRING=Programmer HOSTID=f81234567890
|
|
||||||
FEATURE LSC_ADVANCED_ORCA lattice 9.0 11-feb-2024 uncounted \
|
|
||||||
CC7BBC2A3A16 VENDOR_STRING="ispORCA System" \
|
|
||||||
HOSTID=f81234567890
|
|
||||||
|
|
||||||
INCREMENT latticemsim mgcld 2023.09 11-feb-2024 0 6FE612FBCA60340B3076 \
|
|
||||||
VENDOR_STRING=672C91AB HOSTID=f81234567890 ISSUER="ModelSIM Lattice" \
|
|
||||||
SN=284862648 SIGN2="1E93 D015 CA8E 6012 81DA 3394 F0EA 3C2F 5482 24AB \
|
|
||||||
F903 2C13 A952 2697 2AF4 0819 2FA9 8CE8 CC9B 329B F71E C11F C29E A733 \
|
|
||||||
3D18 B2C3 7983 70EA 2885 F23E"
|
|
||||||
|
|
16
fw/project/lcmxo2/release.sty
generated
16
fw/project/lcmxo2/release.sty
generated
@ -97,9 +97,9 @@
|
|||||||
<Property name="PROP_MAP_RegRetiming" value="True" time="0"/>
|
<Property name="PROP_MAP_RegRetiming" value="True" time="0"/>
|
||||||
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_TimingDriven" value="False" time="0"/>
|
<Property name="PROP_MAP_TimingDriven" value="True" time="0"/>
|
||||||
<Property name="PROP_MAP_TimingDrivenNodeRep" value="False" time="0"/>
|
<Property name="PROP_MAP_TimingDrivenNodeRep" value="False" time="0"/>
|
||||||
<Property name="PROP_MAP_TimingDrivenPack" value="False" time="0"/>
|
<Property name="PROP_MAP_TimingDrivenPack" value="True" time="0"/>
|
||||||
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||||
<Property name="PROP_PARSTA_AutoTiming" value="True" time="0"/>
|
<Property name="PROP_PARSTA_AutoTiming" value="True" time="0"/>
|
||||||
<Property name="PROP_PARSTA_CheckUnconstrainedConns" value="False" time="0"/>
|
<Property name="PROP_PARSTA_CheckUnconstrainedConns" value="False" time="0"/>
|
||||||
@ -118,15 +118,15 @@
|
|||||||
<Property name="PROP_PAR_NewRouteParDes" value="NBR" time="0"/>
|
<Property name="PROP_PAR_NewRouteParDes" value="NBR" time="0"/>
|
||||||
<Property name="PROP_PAR_PARClockSkew" value="Off" time="0"/>
|
<Property name="PROP_PAR_PARClockSkew" value="Off" time="0"/>
|
||||||
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
||||||
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
|
<Property name="PROP_PAR_ParMultiNodeList" value="multicore.txt" time="0"/>
|
||||||
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
||||||
<Property name="PROP_PAR_PlcIterParDes" value="16" time="0"/>
|
<Property name="PROP_PAR_PlcIterParDes" value="32" time="0"/>
|
||||||
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
||||||
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
|
<Property name="PROP_PAR_PrefErrorOut" value="True" time="0"/>
|
||||||
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
|
<Property name="PROP_PAR_RemoveDir" value="True" time="0"/>
|
||||||
<Property name="PROP_PAR_RouteDlyRedParDes" value="0" time="0"/>
|
<Property name="PROP_PAR_RouteDlyRedParDes" value="10" time="0"/>
|
||||||
<Property name="PROP_PAR_RoutePassParDes" value="20" time="0"/>
|
<Property name="PROP_PAR_RoutePassParDes" value="100" time="0"/>
|
||||||
<Property name="PROP_PAR_RouteResOptParDes" value="0" time="0"/>
|
<Property name="PROP_PAR_RouteResOptParDes" value="6" time="0"/>
|
||||||
<Property name="PROP_PAR_RoutingCDP" value="1" time="0"/>
|
<Property name="PROP_PAR_RoutingCDP" value="1" time="0"/>
|
||||||
<Property name="PROP_PAR_RoutingCDR" value="1" time="0"/>
|
<Property name="PROP_PAR_RoutingCDR" value="1" time="0"/>
|
||||||
<Property name="PROP_PAR_RunParWithTrce" value="False" time="0"/>
|
<Property name="PROP_PAR_RunParWithTrce" value="False" time="0"/>
|
||||||
@ -173,7 +173,7 @@
|
|||||||
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
|
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
|
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
|
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfFrequency" value="110" time="0"/>
|
<Property name="PROP_SYN_EdfFrequency" value="100" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfGSR" value="False" time="0"/>
|
<Property name="PROP_SYN_EdfGSR" value="False" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
|
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
|
||||||
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
|
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
<Options/>
|
<Options/>
|
||||||
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="synplify" default_strategy="release">
|
<Implementation title="impl1" dir="impl1" description="impl1" synthesis="synplify" default_strategy="release">
|
||||||
<Options VerilogStandard="System Verilog" def_top="top" top="top"/>
|
<Options VerilogStandard="System Verilog" def_top="top" top="top"/>
|
||||||
|
<Source name="../../rtl/memory/dma_scb.sv" type="Verilog" type_short="Verilog">
|
||||||
|
<Options VerilogStandard="System Verilog"/>
|
||||||
|
</Source>
|
||||||
<Source name="../../rtl/memory/mem_bus.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/memory/mem_bus.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
@ -12,6 +15,9 @@
|
|||||||
<Source name="../../rtl/sd/sd_scb.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/sd/sd_scb.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
<Source name="../../rtl/usb/usb_scb.sv" type="Verilog" type_short="Verilog">
|
||||||
|
<Options VerilogStandard="System Verilog"/>
|
||||||
|
</Source>
|
||||||
<Source name="../../rtl/fifo/fifo_bus.sv" type="Verilog" type_short="Verilog">
|
<Source name="../../rtl/fifo/fifo_bus.sv" type="Verilog" type_short="Verilog">
|
||||||
<Options VerilogStandard="System Verilog"/>
|
<Options VerilogStandard="System Verilog"/>
|
||||||
</Source>
|
</Source>
|
||||||
|
@ -96,6 +96,9 @@ IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
|||||||
IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "sdram_ras" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sdram_ras" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "sdram_we" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sdram_we" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "test_point[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "test_point[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "test_point[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "usb_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "usb_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "usb_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "usb_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "usb_miosi[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "usb_miosi[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
@ -194,6 +197,9 @@ LOCATE COMP "sdram_dqm[0]" SITE "97" ;
|
|||||||
LOCATE COMP "sdram_dqm[1]" SITE "73" ;
|
LOCATE COMP "sdram_dqm[1]" SITE "73" ;
|
||||||
LOCATE COMP "sdram_ras" SITE "94" ;
|
LOCATE COMP "sdram_ras" SITE "94" ;
|
||||||
LOCATE COMP "sdram_we" SITE "96" ;
|
LOCATE COMP "sdram_we" SITE "96" ;
|
||||||
|
LOCATE COMP "test_point[0]" SITE "23" ;
|
||||||
|
LOCATE COMP "test_point[1]" SITE "24" ;
|
||||||
|
LOCATE COMP "test_point[2]" SITE "25" ;
|
||||||
LOCATE COMP "usb_clk" SITE "12" ;
|
LOCATE COMP "usb_clk" SITE "12" ;
|
||||||
LOCATE COMP "usb_cs" SITE "11" ;
|
LOCATE COMP "usb_cs" SITE "11" ;
|
||||||
LOCATE COMP "usb_miosi[0]" SITE "22" ;
|
LOCATE COMP "usb_miosi[0]" SITE "22" ;
|
||||||
@ -208,8 +214,48 @@ LOCATE COMP "usb_miso" SITE "10" ;
|
|||||||
LOCATE COMP "usb_pwrsav" SITE "2" ;
|
LOCATE COMP "usb_pwrsav" SITE "2" ;
|
||||||
SYSCONFIG SDM_PORT=DISABLE I2C_PORT=ENABLE ;
|
SYSCONFIG SDM_PORT=DISABLE I2C_PORT=ENABLE ;
|
||||||
VOLTAGE 3.300 V;
|
VOLTAGE 3.300 V;
|
||||||
FREQUENCY NET "clk" 100.000000 MHz PAR_ADJ 10.000000 ;
|
FREQUENCY NET "clk" 100.000000 MHz ;
|
||||||
BLOCK PATH TO PORT "mcu_int" ;
|
BLOCK PATH TO PORT "mcu_int" ;
|
||||||
BLOCK PATH TO PORT "n64_irq" ;
|
BLOCK PATH TO PORT "n64_irq" ;
|
||||||
BLOCK PATH FROM PORT "usb_pwrsav" ;
|
BLOCK PATH FROM PORT "usb_pwrsav" ;
|
||||||
BLOCK PATH FROM PORT "sd_det" ;
|
BLOCK PATH FROM PORT "sd_det" ;
|
||||||
|
DEFINE PORT GROUP "sdram_output" "sdram_cs"
|
||||||
|
"sdram_ras"
|
||||||
|
"sdram_cas"
|
||||||
|
"sdram_we"
|
||||||
|
"sdram_ba[1]"
|
||||||
|
"sdram_ba[0]"
|
||||||
|
"sdram_a[12]"
|
||||||
|
"sdram_a[11]"
|
||||||
|
"sdram_a[10]"
|
||||||
|
"sdram_a[9]"
|
||||||
|
"sdram_a[8]"
|
||||||
|
"sdram_a[7]"
|
||||||
|
"sdram_a[6]"
|
||||||
|
"sdram_a[5]"
|
||||||
|
"sdram_a[4]"
|
||||||
|
"sdram_a[3]"
|
||||||
|
"sdram_a[2]"
|
||||||
|
"sdram_a[1]"
|
||||||
|
"sdram_a[0]"
|
||||||
|
"sdram_dqm[1]"
|
||||||
|
"sdram_dqm[0]" ;
|
||||||
|
DEFINE PORT GROUP "sdram_bidir" "sdram_dq[15]"
|
||||||
|
"sdram_dq[14]"
|
||||||
|
"sdram_dq[13]"
|
||||||
|
"sdram_dq[12]"
|
||||||
|
"sdram_dq[11]"
|
||||||
|
"sdram_dq[10]"
|
||||||
|
"sdram_dq[9]"
|
||||||
|
"sdram_dq[8]"
|
||||||
|
"sdram_dq[7]"
|
||||||
|
"sdram_dq[6]"
|
||||||
|
"sdram_dq[5]"
|
||||||
|
"sdram_dq[4]"
|
||||||
|
"sdram_dq[3]"
|
||||||
|
"sdram_dq[2]"
|
||||||
|
"sdram_dq[1]"
|
||||||
|
"sdram_dq[0]" ;
|
||||||
|
INPUT_SETUP GROUP "sdram_bidir"INPUT_DELAY 5.400000 ns HOLD -2.500000 ns CLKNET "clk" CLK_OFFSET -0.250000 X ;
|
||||||
|
CLOCK_TO_OUT GROUP "sdram_output" OUTPUT_DELAY 1.500000 ns MIN 0.800000 ns CLKNET "clk" CLKOUT PORT "sdram_clk" ;
|
||||||
|
CLOCK_TO_OUT GROUP "sdram_bidir" OUTPUT_DELAY 1.500000 ns MIN 0.800000 ns CLKNET "clk" CLKOUT PORT "sdram_clk" ;
|
||||||
|
@ -1,35 +1,29 @@
|
|||||||
interface fifo_bus ();
|
interface fifo_bus ();
|
||||||
|
|
||||||
logic rx_empty;
|
logic rx_empty;
|
||||||
logic rx_almost_empty;
|
|
||||||
logic rx_read;
|
logic rx_read;
|
||||||
logic [7:0] rx_rdata;
|
logic [7:0] rx_rdata;
|
||||||
|
|
||||||
logic tx_full;
|
logic tx_full;
|
||||||
logic tx_almost_full;
|
|
||||||
logic tx_write;
|
logic tx_write;
|
||||||
logic [7:0] tx_wdata;
|
logic [7:0] tx_wdata;
|
||||||
|
|
||||||
modport controller (
|
modport controller (
|
||||||
input rx_empty,
|
input rx_empty,
|
||||||
input rx_almost_empty,
|
|
||||||
output rx_read,
|
output rx_read,
|
||||||
input rx_rdata,
|
input rx_rdata,
|
||||||
|
|
||||||
input tx_full,
|
input tx_full,
|
||||||
input tx_almost_full,
|
|
||||||
output tx_write,
|
output tx_write,
|
||||||
output tx_wdata
|
output tx_wdata
|
||||||
);
|
);
|
||||||
|
|
||||||
modport fifo (
|
modport fifo (
|
||||||
output rx_empty,
|
output rx_empty,
|
||||||
output rx_almost_empty,
|
|
||||||
input rx_read,
|
input rx_read,
|
||||||
output rx_rdata,
|
output rx_rdata,
|
||||||
|
|
||||||
output tx_full,
|
output tx_full,
|
||||||
output tx_almost_full,
|
|
||||||
input tx_write,
|
input tx_write,
|
||||||
input tx_wdata
|
input tx_wdata
|
||||||
);
|
);
|
||||||
|
@ -11,16 +11,12 @@ module fifo_junction (
|
|||||||
dev_bus.tx_wdata = cfg_bus.tx_write ? cfg_bus.tx_wdata : dma_bus.tx_wdata;
|
dev_bus.tx_wdata = cfg_bus.tx_write ? cfg_bus.tx_wdata : dma_bus.tx_wdata;
|
||||||
|
|
||||||
cfg_bus.rx_empty = dev_bus.rx_empty;
|
cfg_bus.rx_empty = dev_bus.rx_empty;
|
||||||
cfg_bus.rx_almost_empty = dev_bus.rx_almost_empty;
|
|
||||||
cfg_bus.rx_rdata = dev_bus.rx_rdata;
|
cfg_bus.rx_rdata = dev_bus.rx_rdata;
|
||||||
cfg_bus.tx_full = dev_bus.tx_full;
|
cfg_bus.tx_full = dev_bus.tx_full;
|
||||||
cfg_bus.tx_almost_full = dev_bus.tx_almost_full;
|
|
||||||
|
|
||||||
dma_bus.rx_empty = dev_bus.rx_empty;
|
dma_bus.rx_empty = dev_bus.rx_empty;
|
||||||
dma_bus.rx_almost_empty = dev_bus.rx_almost_empty;
|
|
||||||
dma_bus.rx_rdata = dev_bus.rx_rdata;
|
dma_bus.rx_rdata = dev_bus.rx_rdata;
|
||||||
dma_bus.tx_full = dev_bus.tx_full;
|
dma_bus.tx_full = dev_bus.tx_full;
|
||||||
dma_bus.tx_almost_full = dev_bus.tx_almost_full;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -360,7 +360,8 @@ module mcu_top (
|
|||||||
REG_DEBUG_0,
|
REG_DEBUG_0,
|
||||||
REG_DEBUG_1,
|
REG_DEBUG_1,
|
||||||
REG_CIC_0,
|
REG_CIC_0,
|
||||||
REG_CIC_1
|
REG_CIC_1,
|
||||||
|
REG_AUX
|
||||||
} reg_address_e;
|
} reg_address_e;
|
||||||
|
|
||||||
logic bootloader_skip;
|
logic bootloader_skip;
|
||||||
@ -370,8 +371,12 @@ module mcu_top (
|
|||||||
|
|
||||||
logic dd_bm_ack;
|
logic dd_bm_ack;
|
||||||
|
|
||||||
|
logic [31:0] debug_buffer;
|
||||||
|
|
||||||
logic cic_invalid_region;
|
logic cic_invalid_region;
|
||||||
|
|
||||||
|
logic aux_pending;
|
||||||
|
|
||||||
|
|
||||||
// Register read logic
|
// Register read logic
|
||||||
|
|
||||||
@ -394,13 +399,13 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_USB_SCR: begin
|
REG_USB_SCR: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= {
|
||||||
2'd0,
|
1'd0,
|
||||||
|
usb_scb.fifo_flush_busy,
|
||||||
usb_scb.pwrsav,
|
usb_scb.pwrsav,
|
||||||
usb_scb.reset_state,
|
usb_scb.reset_state,
|
||||||
usb_scb.tx_count,
|
usb_scb.tx_count,
|
||||||
usb_scb.rx_count,
|
usb_scb.rx_count,
|
||||||
2'b00,
|
3'b000,
|
||||||
usb_scb.reset_pending,
|
|
||||||
~fifo_bus.tx_full,
|
~fifo_bus.tx_full,
|
||||||
~fifo_bus.rx_empty,
|
~fifo_bus.rx_empty,
|
||||||
1'b0
|
1'b0
|
||||||
@ -459,7 +464,9 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_CFG_CMD: begin
|
REG_CFG_CMD: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= {
|
||||||
23'd0,
|
19'd0,
|
||||||
|
aux_pending,
|
||||||
|
3'd0,
|
||||||
n64_scb.cfg_pending,
|
n64_scb.cfg_pending,
|
||||||
n64_scb.cfg_cmd
|
n64_scb.cfg_cmd
|
||||||
};
|
};
|
||||||
@ -474,7 +481,7 @@ module mcu_top (
|
|||||||
18'd0,
|
18'd0,
|
||||||
n64_scb.flashram_write_or_erase,
|
n64_scb.flashram_write_or_erase,
|
||||||
n64_scb.flashram_sector_or_all,
|
n64_scb.flashram_sector_or_all,
|
||||||
n64_scb.flashram_sector,
|
n64_scb.flashram_page,
|
||||||
n64_scb.flashram_pending,
|
n64_scb.flashram_pending,
|
||||||
1'b0
|
1'b0
|
||||||
};
|
};
|
||||||
@ -506,7 +513,7 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_RTC_TIME_1: begin
|
REG_RTC_TIME_1: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= {
|
||||||
8'd0,
|
7'd0, n64_scb.rtc_rdata[42],
|
||||||
n64_scb.rtc_rdata[41:34],
|
n64_scb.rtc_rdata[41:34],
|
||||||
3'd0, n64_scb.rtc_rdata[33:29],
|
3'd0, n64_scb.rtc_rdata[33:29],
|
||||||
2'd0, n64_scb.rtc_rdata[25:20]
|
2'd0, n64_scb.rtc_rdata[25:20]
|
||||||
@ -644,14 +651,18 @@ module mcu_top (
|
|||||||
end
|
end
|
||||||
|
|
||||||
REG_DEBUG_0: begin
|
REG_DEBUG_0: begin
|
||||||
reg_rdata <= n64_scb.pi_debug[31:0];
|
reg_rdata <= n64_scb.pi_debug_address;
|
||||||
|
debug_buffer <= {
|
||||||
|
6'd0,
|
||||||
|
n64_scb.pi_debug_direction,
|
||||||
|
n64_scb.pi_debug_rw_count,
|
||||||
|
n64_scb.cic_debug_step,
|
||||||
|
n64_scb.pi_debug_fifo_flags
|
||||||
|
};
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_DEBUG_1: begin
|
REG_DEBUG_1: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= debug_buffer;
|
||||||
28'd0,
|
|
||||||
n64_scb.pi_debug[35:32]
|
|
||||||
};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_CIC_0: begin
|
REG_CIC_0: begin
|
||||||
@ -669,6 +680,10 @@ module mcu_top (
|
|||||||
REG_CIC_1: begin
|
REG_CIC_1: begin
|
||||||
reg_rdata <= n64_scb.cic_checksum[31:0];
|
reg_rdata <= n64_scb.cic_checksum[31:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
REG_AUX: begin
|
||||||
|
reg_rdata <= n64_scb.aux_rdata;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -680,9 +695,10 @@ module mcu_top (
|
|||||||
mem_start <= 1'b0;
|
mem_start <= 1'b0;
|
||||||
mem_stop <= 1'b0;
|
mem_stop <= 1'b0;
|
||||||
|
|
||||||
usb_scb.write_buffer_flush <= 1'b0;
|
|
||||||
usb_scb.reset_ack <= 1'b0;
|
|
||||||
usb_scb.fifo_flush <= 1'b0;
|
usb_scb.fifo_flush <= 1'b0;
|
||||||
|
usb_scb.write_buffer_flush <= 1'b0;
|
||||||
|
usb_scb.reset_on_ack <= 1'b0;
|
||||||
|
usb_scb.reset_off_ack <= 1'b0;
|
||||||
|
|
||||||
usb_dma_scb.start <= 1'b0;
|
usb_dma_scb.start <= 1'b0;
|
||||||
usb_dma_scb.stop <= 1'b0;
|
usb_dma_scb.stop <= 1'b0;
|
||||||
@ -698,7 +714,10 @@ module mcu_top (
|
|||||||
|
|
||||||
n64_scb.cfg_done <= 1'b0;
|
n64_scb.cfg_done <= 1'b0;
|
||||||
n64_scb.cfg_error <= 1'b0;
|
n64_scb.cfg_error <= 1'b0;
|
||||||
n64_scb.cfg_irq <= 1'b0;
|
|
||||||
|
n64_scb.btn_irq <= 1'b0;
|
||||||
|
n64_scb.usb_irq <= 1'b0;
|
||||||
|
n64_scb.aux_irq <= 1'b0;
|
||||||
|
|
||||||
n64_scb.flashram_done <= 1'b0;
|
n64_scb.flashram_done <= 1'b0;
|
||||||
|
|
||||||
@ -729,6 +748,10 @@ module mcu_top (
|
|||||||
cic_invalid_region <= 1'b1;
|
cic_invalid_region <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (n64_scb.aux_pending) begin
|
||||||
|
aux_pending <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
mcu_int <= 1'b0;
|
mcu_int <= 1'b0;
|
||||||
sd_scb.clock_mode <= 2'd0;
|
sd_scb.clock_mode <= 2'd0;
|
||||||
@ -753,6 +776,7 @@ module mcu_top (
|
|||||||
n64_scb.cic_region <= 1'b0;
|
n64_scb.cic_region <= 1'b0;
|
||||||
n64_scb.cic_seed <= 8'h3F;
|
n64_scb.cic_seed <= 8'h3F;
|
||||||
n64_scb.cic_checksum <= 48'hA536C0F1D859;
|
n64_scb.cic_checksum <= 48'hA536C0F1D859;
|
||||||
|
aux_pending <= 1'b0;
|
||||||
end else if (reg_write) begin
|
end else if (reg_write) begin
|
||||||
case (address)
|
case (address)
|
||||||
REG_MEM_ADDRESS: begin
|
REG_MEM_ADDRESS: begin
|
||||||
@ -769,11 +793,11 @@ module mcu_top (
|
|||||||
end
|
end
|
||||||
|
|
||||||
REG_USB_SCR: begin
|
REG_USB_SCR: begin
|
||||||
{
|
n64_scb.usb_irq <= reg_wdata[31];
|
||||||
usb_scb.write_buffer_flush,
|
usb_scb.write_buffer_flush <= reg_wdata[5];
|
||||||
usb_scb.reset_ack,
|
usb_scb.reset_off_ack <= reg_wdata[4];
|
||||||
usb_scb.fifo_flush
|
usb_scb.reset_on_ack <= reg_wdata[3];
|
||||||
} <= {reg_wdata[5:4], reg_wdata[0]};
|
usb_scb.fifo_flush <= reg_wdata[0];
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_USB_DMA_ADDRESS: begin
|
REG_USB_DMA_ADDRESS: begin
|
||||||
@ -819,10 +843,13 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_CFG_CMD: begin
|
REG_CFG_CMD: begin
|
||||||
{
|
{
|
||||||
n64_scb.cfg_irq,
|
n64_scb.btn_irq,
|
||||||
n64_scb.cfg_error,
|
n64_scb.cfg_error,
|
||||||
n64_scb.cfg_done
|
n64_scb.cfg_done
|
||||||
} <= reg_wdata[11:9];
|
} <= reg_wdata[11:9];
|
||||||
|
if (reg_wdata[13]) begin
|
||||||
|
aux_pending <= 1'b0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_FLASHRAM_SCR: begin
|
REG_FLASHRAM_SCR: begin
|
||||||
@ -848,6 +875,7 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_RTC_TIME_1: begin
|
REG_RTC_TIME_1: begin
|
||||||
n64_scb.rtc_wdata_valid <= 1'b1;
|
n64_scb.rtc_wdata_valid <= 1'b1;
|
||||||
|
n64_scb.rtc_wdata[42] <= reg_wdata[24];
|
||||||
n64_scb.rtc_wdata[41:34] <= reg_wdata[23:16];
|
n64_scb.rtc_wdata[41:34] <= reg_wdata[23:16];
|
||||||
n64_scb.rtc_wdata[33:29] <= reg_wdata[12:8];
|
n64_scb.rtc_wdata[33:29] <= reg_wdata[12:8];
|
||||||
n64_scb.rtc_wdata[25:20] <= reg_wdata[5:0];
|
n64_scb.rtc_wdata[25:20] <= reg_wdata[5:0];
|
||||||
@ -945,6 +973,11 @@ module mcu_top (
|
|||||||
REG_CIC_1: begin
|
REG_CIC_1: begin
|
||||||
n64_scb.cic_checksum[31:0] <= reg_wdata;
|
n64_scb.cic_checksum[31:0] <= reg_wdata;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
REG_AUX: begin
|
||||||
|
n64_scb.aux_irq <= 1'b1;
|
||||||
|
n64_scb.aux_wdata <= reg_wdata;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
31
fw/rtl/memory/dma_scb.sv
Normal file
31
fw/rtl/memory/dma_scb.sv
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
interface dma_scb ();
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
logic stop;
|
||||||
|
logic busy;
|
||||||
|
logic direction;
|
||||||
|
logic byte_swap;
|
||||||
|
logic [26:0] starting_address;
|
||||||
|
logic [26:0] transfer_length;
|
||||||
|
|
||||||
|
modport controller (
|
||||||
|
output start,
|
||||||
|
output stop,
|
||||||
|
input busy,
|
||||||
|
output direction,
|
||||||
|
output byte_swap,
|
||||||
|
output starting_address,
|
||||||
|
output transfer_length
|
||||||
|
);
|
||||||
|
|
||||||
|
modport dma (
|
||||||
|
input start,
|
||||||
|
input stop,
|
||||||
|
output busy,
|
||||||
|
input direction,
|
||||||
|
input byte_swap,
|
||||||
|
input starting_address,
|
||||||
|
input transfer_length
|
||||||
|
);
|
||||||
|
|
||||||
|
endinterface
|
@ -36,11 +36,11 @@ module memory_bram (
|
|||||||
eeprom_selected = 1'b0;
|
eeprom_selected = 1'b0;
|
||||||
dd_selected = 1'b0;
|
dd_selected = 1'b0;
|
||||||
flashram_selected = 1'b0;
|
flashram_selected = 1'b0;
|
||||||
if (mem_bus.address[25:24] == 2'b01 && mem_bus.address[23:14] == 10'd0) begin
|
if (mem_bus.address[26:24] == 3'h5) begin
|
||||||
buffer_selected = mem_bus.address[13] == 1'b0;
|
buffer_selected = (mem_bus.address[23:0] >= 24'h00_0000 && mem_bus.address[23:0] < 24'h00_2000);
|
||||||
eeprom_selected = mem_bus.address[13:11] == 3'b100;
|
eeprom_selected = (mem_bus.address[23:0] >= 24'h00_2000 && mem_bus.address[23:0] < 24'h00_2800);
|
||||||
dd_selected = mem_bus.address[13:8] == 6'b101000;
|
dd_selected = (mem_bus.address[23:0] >= 24'h00_2800 && mem_bus.address[23:0] < 24'h00_2C00);
|
||||||
flashram_selected = mem_bus.address[13:7] == 7'b1010010;
|
flashram_selected = (mem_bus.address[23:0] >= 24'h00_2C00 && mem_bus.address[23:0] < 24'h00_2C80);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -112,26 +112,26 @@ module memory_bram (
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// DD memory
|
// 64DD/MCU buffer memory
|
||||||
|
|
||||||
logic [15:0] dd_bram [0:127];
|
logic [15:0] dd_bram [0:511];
|
||||||
logic [15:0] dd_bram_rdata;
|
logic [15:0] dd_bram_rdata;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (write && dd_selected) begin
|
if (write && dd_selected) begin
|
||||||
dd_bram[mem_bus.address[7:1]] <= mem_bus.wdata;
|
dd_bram[mem_bus.address[9:1]] <= mem_bus.wdata;
|
||||||
end
|
end
|
||||||
if (n64_scb.dd_write) begin
|
if (n64_scb.dd_write) begin
|
||||||
dd_bram[n64_scb.dd_address] <= n64_scb.dd_wdata;
|
dd_bram[{2'b00, n64_scb.dd_address}] <= n64_scb.dd_wdata;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
dd_bram_rdata <= dd_bram[mem_bus.address[7:1]];
|
dd_bram_rdata <= dd_bram[mem_bus.address[9:1]];
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
n64_scb.dd_rdata <= dd_bram[n64_scb.dd_address];
|
n64_scb.dd_rdata <= dd_bram[{2'b00, n64_scb.dd_address}];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,36 +1,3 @@
|
|||||||
interface dma_scb ();
|
|
||||||
|
|
||||||
logic start;
|
|
||||||
logic stop;
|
|
||||||
logic busy;
|
|
||||||
logic direction;
|
|
||||||
logic byte_swap;
|
|
||||||
logic [26:0] starting_address;
|
|
||||||
logic [26:0] transfer_length;
|
|
||||||
|
|
||||||
modport controller (
|
|
||||||
output start,
|
|
||||||
output stop,
|
|
||||||
input busy,
|
|
||||||
output direction,
|
|
||||||
output byte_swap,
|
|
||||||
output starting_address,
|
|
||||||
output transfer_length
|
|
||||||
);
|
|
||||||
|
|
||||||
modport dma (
|
|
||||||
input start,
|
|
||||||
input stop,
|
|
||||||
output busy,
|
|
||||||
input direction,
|
|
||||||
input byte_swap,
|
|
||||||
input starting_address,
|
|
||||||
input transfer_length
|
|
||||||
);
|
|
||||||
|
|
||||||
endinterface
|
|
||||||
|
|
||||||
|
|
||||||
module memory_dma (
|
module memory_dma (
|
||||||
input clk,
|
input clk,
|
||||||
input reset,
|
input reset,
|
||||||
@ -41,213 +8,382 @@ module memory_dma (
|
|||||||
mem_bus.controller mem_bus
|
mem_bus.controller mem_bus
|
||||||
);
|
);
|
||||||
|
|
||||||
// DMA start/stop control
|
// Start/stop logic
|
||||||
|
|
||||||
logic dma_start;
|
logic dma_start;
|
||||||
logic dma_stop;
|
logic dma_stop;
|
||||||
|
|
||||||
always_comb begin
|
always_ff @(posedge clk) begin
|
||||||
dma_start = dma_scb.start && !dma_scb.stop && !dma_scb.busy;
|
dma_start <= 1'b0;
|
||||||
dma_stop = dma_scb.stop;
|
if (dma_scb.stop) begin
|
||||||
|
dma_stop <= 1'b1;
|
||||||
|
end else if (dma_scb.start) begin
|
||||||
|
dma_start <= 1'b1;
|
||||||
|
dma_stop <= 1'b0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// Remaining counter and FIFO enable
|
// Memory bus controller
|
||||||
|
|
||||||
logic [26:0] remaining;
|
typedef enum bit [1:0] {
|
||||||
logic trx_enabled;
|
MEM_BUS_STATE_IDLE,
|
||||||
|
MEM_BUS_STATE_WAIT,
|
||||||
|
MEM_BUS_STATE_TRANSFER
|
||||||
|
} e_mem_bus_state;
|
||||||
|
|
||||||
|
e_mem_bus_state mem_bus_state;
|
||||||
|
e_mem_bus_state next_mem_bus_state;
|
||||||
|
|
||||||
|
logic mem_bus_wdata_ready;
|
||||||
|
logic mem_bus_wdata_empty;
|
||||||
|
logic mem_bus_wdata_end;
|
||||||
|
logic [1:0] mem_bus_wdata_valid;
|
||||||
|
logic [15:0] mem_bus_wdata_buffer;
|
||||||
|
|
||||||
|
logic mem_bus_rdata_ready;
|
||||||
|
logic mem_bus_rdata_ack;
|
||||||
|
logic mem_bus_rdata_end;
|
||||||
|
logic [1:0] mem_bus_rdata_valid;
|
||||||
|
logic [15:0] mem_bus_rdata_buffer;
|
||||||
|
|
||||||
|
logic [26:0] mem_bus_remaining_bytes;
|
||||||
|
logic mem_bus_last_transfer;
|
||||||
|
logic mem_bus_almost_last_transfer;
|
||||||
|
logic mem_bus_unaligned_start;
|
||||||
|
logic mem_bus_unaligned_end;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
mem_bus_state <= MEM_BUS_STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
mem_bus_state <= next_mem_bus_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
trx_enabled = remaining > 27'd0;
|
next_mem_bus_state = mem_bus_state;
|
||||||
|
|
||||||
|
mem_bus_last_transfer = (mem_bus_remaining_bytes == 27'd0);
|
||||||
|
mem_bus_almost_last_transfer = (mem_bus_remaining_bytes <= 27'd2);
|
||||||
|
|
||||||
|
mem_bus_wdata_end = mem_bus_last_transfer;
|
||||||
|
mem_bus_wdata_valid = (mem_bus_unaligned_end && mem_bus_almost_last_transfer) ? 2'b10 :
|
||||||
|
mem_bus_unaligned_start ? 2'b01 :
|
||||||
|
2'b11;
|
||||||
|
|
||||||
|
case (mem_bus_state)
|
||||||
|
MEM_BUS_STATE_IDLE: begin
|
||||||
|
if (dma_start) begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_WAIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MEM_BUS_STATE_WAIT: begin
|
||||||
|
if (dma_stop || mem_bus_last_transfer) begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_IDLE;
|
||||||
|
end else if (mem_bus_wdata_ready || !mem_bus_wdata_empty || mem_bus_rdata_ready) begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_TRANSFER;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MEM_BUS_STATE_TRANSFER: begin
|
||||||
|
if (mem_bus.ack) begin
|
||||||
|
if (dma_stop || mem_bus_last_transfer) begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_IDLE;
|
||||||
|
end else if (!(mem_bus_wdata_ready || !mem_bus_wdata_empty || mem_bus_rdata_ready)) begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_WAIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
next_mem_bus_state = MEM_BUS_STATE_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
mem_bus_rdata_ack <= 1'b0;
|
||||||
|
|
||||||
|
if (mem_bus.ack) begin
|
||||||
|
mem_bus.request <= 1'b0;
|
||||||
|
mem_bus.address <= (mem_bus.address + 26'd2);
|
||||||
|
mem_bus_rdata_ack <= 1'b1;
|
||||||
|
mem_bus_rdata_end <= mem_bus_last_transfer;
|
||||||
|
mem_bus_rdata_valid <= mem_bus.wmask;
|
||||||
|
mem_bus_rdata_buffer <= mem_bus.rdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (mem_bus_wdata_ready) begin
|
||||||
|
mem_bus_wdata_empty <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
case (mem_bus_state)
|
||||||
|
MEM_BUS_STATE_IDLE: begin
|
||||||
|
mem_bus.request <= 1'b0;
|
||||||
|
mem_bus_rdata_end <= 1'b1;
|
||||||
|
if (dma_start) begin
|
||||||
|
mem_bus.write <= dma_scb.direction;
|
||||||
|
mem_bus.address <= {dma_scb.starting_address[26:1], 1'b0};
|
||||||
|
mem_bus_remaining_bytes <= dma_scb.transfer_length;
|
||||||
|
mem_bus_unaligned_start <= dma_scb.starting_address[0];
|
||||||
|
mem_bus_unaligned_end <= (dma_scb.starting_address[0] ^ dma_scb.transfer_length[0]);
|
||||||
|
mem_bus_rdata_end <= 1'b0;
|
||||||
|
mem_bus_wdata_empty <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MEM_BUS_STATE_WAIT: begin
|
||||||
|
if (!dma_stop && !mem_bus_last_transfer) begin
|
||||||
|
if (mem_bus_wdata_ready || !mem_bus_wdata_empty || mem_bus_rdata_ready) begin
|
||||||
|
mem_bus.request <= 1'b1;
|
||||||
|
mem_bus_unaligned_start <= 1'b0;
|
||||||
|
mem_bus.wdata <= (dma_scb.byte_swap ? {mem_bus_wdata_buffer[7:0], mem_bus_wdata_buffer[15:8]} : mem_bus_wdata_buffer);
|
||||||
|
mem_bus.wmask <= 2'b11;
|
||||||
|
mem_bus_remaining_bytes <= (mem_bus_remaining_bytes - 27'd2);
|
||||||
|
if (mem_bus_unaligned_end && mem_bus_almost_last_transfer) begin
|
||||||
|
mem_bus.wmask <= 2'b10;
|
||||||
|
mem_bus_remaining_bytes <= (mem_bus_remaining_bytes - 27'd1);
|
||||||
|
end
|
||||||
|
if (mem_bus_unaligned_start) begin
|
||||||
|
mem_bus.wmask <= 2'b01;
|
||||||
|
mem_bus_remaining_bytes <= (mem_bus_remaining_bytes - 27'd1);
|
||||||
|
end
|
||||||
|
mem_bus_wdata_empty <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MEM_BUS_STATE_TRANSFER: begin
|
||||||
|
if (!dma_stop && !mem_bus_last_transfer) begin
|
||||||
|
if (mem_bus.ack && (mem_bus_wdata_ready || !mem_bus_wdata_empty || mem_bus_rdata_ready)) begin
|
||||||
|
mem_bus.request <= 1'b1;
|
||||||
|
mem_bus.wdata <= (dma_scb.byte_swap ? {mem_bus_wdata_buffer[7:0], mem_bus_wdata_buffer[15:8]} : mem_bus_wdata_buffer);
|
||||||
|
mem_bus.wmask <= 2'b11;
|
||||||
|
mem_bus_remaining_bytes <= (mem_bus_remaining_bytes - 27'd2);
|
||||||
|
if (mem_bus_unaligned_end && mem_bus_almost_last_transfer) begin
|
||||||
|
mem_bus.wmask <= 2'b10;
|
||||||
|
mem_bus_remaining_bytes <= (mem_bus_remaining_bytes - 27'd1);
|
||||||
|
end
|
||||||
|
mem_bus_wdata_empty <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// RX FIFO controller
|
// RX FIFO controller
|
||||||
|
|
||||||
logic [1:0] rx_wmask;
|
typedef enum bit [1:0] {
|
||||||
logic rx_rdata_pop;
|
RX_FIFO_BUS_STATE_IDLE,
|
||||||
logic rx_rdata_shift;
|
RX_FIFO_BUS_STATE_TRANSFER_1,
|
||||||
logic rx_rdata_valid;
|
RX_FIFO_BUS_STATE_TRANSFER_2,
|
||||||
logic [15:0] rx_buffer;
|
RX_FIFO_BUS_STATE_ACK
|
||||||
logic rx_buffer_valid;
|
} e_rx_fifo_bus_state;
|
||||||
logic [1:0] rx_buffer_counter;
|
|
||||||
logic [1:0] rx_buffer_valid_counter;
|
e_rx_fifo_bus_state rx_fifo_bus_state;
|
||||||
|
e_rx_fifo_bus_state next_rx_fifo_bus_state;
|
||||||
|
|
||||||
|
logic rx_fifo_shift;
|
||||||
|
logic rx_fifo_shift_delayed;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset || dma_stop) begin
|
||||||
|
rx_fifo_bus_state <= RX_FIFO_BUS_STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
rx_fifo_bus_state <= next_rx_fifo_bus_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
rx_buffer_valid = rx_buffer_valid_counter == 2'd2;
|
next_rx_fifo_bus_state = rx_fifo_bus_state;
|
||||||
|
|
||||||
|
rx_fifo_shift = 1'b0;
|
||||||
|
|
||||||
|
fifo_bus.rx_read = 1'b0;
|
||||||
|
|
||||||
|
case (rx_fifo_bus_state)
|
||||||
|
RX_FIFO_BUS_STATE_IDLE: begin
|
||||||
|
if (dma_start && dma_scb.direction) begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_TRANSFER_1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RX_FIFO_BUS_STATE_TRANSFER_1: begin
|
||||||
|
fifo_bus.rx_read = (!fifo_bus.rx_empty && mem_bus_wdata_empty && mem_bus_wdata_valid[1] && !mem_bus_wdata_end);
|
||||||
|
if ((!fifo_bus.rx_empty && mem_bus_wdata_empty) || !mem_bus_wdata_valid[1]) begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_TRANSFER_2;
|
||||||
|
rx_fifo_shift = 1'b1;
|
||||||
|
end
|
||||||
|
if (mem_bus_wdata_end) begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RX_FIFO_BUS_STATE_TRANSFER_2: begin
|
||||||
|
fifo_bus.rx_read = (!fifo_bus.rx_empty && mem_bus_wdata_valid[0]);
|
||||||
|
if (!fifo_bus.rx_empty || !mem_bus_wdata_valid[0]) begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_ACK;
|
||||||
|
rx_fifo_shift = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RX_FIFO_BUS_STATE_ACK: begin
|
||||||
|
if (mem_bus_wdata_ready) begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_TRANSFER_1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
next_rx_fifo_bus_state = RX_FIFO_BUS_STATE_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
rx_rdata_pop <= (
|
mem_bus_wdata_ready <= 1'b0;
|
||||||
!rx_rdata_pop &&
|
rx_fifo_shift_delayed <= rx_fifo_shift;
|
||||||
!fifo_bus.rx_read &&
|
|
||||||
trx_enabled &&
|
|
||||||
rx_buffer_counter < 2'd2 &&
|
|
||||||
!fifo_bus.rx_empty &&
|
|
||||||
mem_bus.write
|
|
||||||
);
|
|
||||||
rx_rdata_shift <= 1'b0;
|
|
||||||
fifo_bus.rx_read <= rx_rdata_pop;
|
|
||||||
rx_rdata_valid <= fifo_bus.rx_read;
|
|
||||||
|
|
||||||
if (dma_start) begin
|
if (rx_fifo_shift_delayed) begin
|
||||||
if (dma_scb.starting_address[0]) begin
|
if (rx_fifo_bus_state == RX_FIFO_BUS_STATE_ACK) begin
|
||||||
rx_wmask <= 2'b01;
|
mem_bus_wdata_ready <= 1'b1;
|
||||||
rx_buffer_counter <= 2'd1;
|
|
||||||
rx_buffer_valid_counter <= 2'd1;
|
|
||||||
end else begin
|
|
||||||
rx_wmask <= 2'b11;
|
|
||||||
rx_buffer_counter <= 2'd0;
|
|
||||||
rx_buffer_valid_counter <= 2'd0;
|
|
||||||
end
|
end
|
||||||
end
|
mem_bus_wdata_buffer <= {mem_bus_wdata_buffer[7:0], fifo_bus.rx_rdata};
|
||||||
|
|
||||||
if (rx_rdata_pop) begin
|
|
||||||
rx_buffer_counter <= rx_buffer_counter + 1'd1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rx_rdata_shift || rx_rdata_valid) begin
|
|
||||||
if (dma_scb.byte_swap) begin
|
|
||||||
rx_buffer <= {fifo_bus.rx_rdata, rx_buffer[15:8]};
|
|
||||||
end else begin
|
|
||||||
rx_buffer <= {rx_buffer[7:0], fifo_bus.rx_rdata};
|
|
||||||
end
|
|
||||||
rx_buffer_valid_counter <= rx_buffer_valid_counter + 1'd1;
|
|
||||||
if (remaining == 27'd0 && rx_buffer_counter == 2'd1) begin
|
|
||||||
rx_wmask <= 2'b10;
|
|
||||||
rx_rdata_shift <= 1'b1;
|
|
||||||
rx_buffer_counter <= rx_buffer_counter + 1'd1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rx_buffer_valid && !mem_bus.request) begin
|
|
||||||
rx_wmask <= 2'b11;
|
|
||||||
rx_buffer_counter <= 2'd0;
|
|
||||||
rx_buffer_valid_counter <= 2'd0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// TX FIFO controller
|
// TX FIFO controller
|
||||||
|
|
||||||
logic tx_wdata_push;
|
typedef enum bit [1:0] {
|
||||||
logic tx_wdata_first_push;
|
TX_FIFO_BUS_STATE_IDLE,
|
||||||
logic [7:0] tx_buffer;
|
TX_FIFO_BUS_STATE_WAIT,
|
||||||
logic tx_buffer_counter;
|
TX_FIFO_BUS_STATE_TRANSFER_1,
|
||||||
logic tx_buffer_ready;
|
TX_FIFO_BUS_STATE_TRANSFER_2
|
||||||
logic tx_buffer_valid;
|
} e_tx_fifo_bus_state;
|
||||||
|
|
||||||
|
e_tx_fifo_bus_state tx_fifo_bus_state;
|
||||||
|
e_tx_fifo_bus_state next_tx_fifo_bus_state;
|
||||||
|
|
||||||
|
logic tx_fifo_shift;
|
||||||
|
logic tx_fifo_waiting;
|
||||||
|
logic [1:0] tx_fifo_valid;
|
||||||
|
logic [15:0] tx_fifo_buffer;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset || dma_stop) begin
|
||||||
|
tx_fifo_bus_state <= TX_FIFO_BUS_STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
tx_fifo_bus_state <= next_tx_fifo_bus_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
fifo_bus.tx_write = tx_wdata_push;
|
next_tx_fifo_bus_state = tx_fifo_bus_state;
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
tx_fifo_shift = 1'b0;
|
||||||
tx_wdata_push <= (
|
|
||||||
!tx_wdata_push &&
|
|
||||||
trx_enabled &&
|
|
||||||
tx_buffer_valid &&
|
|
||||||
!fifo_bus.tx_full &&
|
|
||||||
!mem_bus.write
|
|
||||||
);
|
|
||||||
|
|
||||||
if (reset || dma_stop) begin
|
fifo_bus.tx_write = 1'b0;
|
||||||
tx_buffer_ready <= 1'b0;
|
fifo_bus.tx_wdata = tx_fifo_buffer[15:8];
|
||||||
tx_buffer_valid <= 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (dma_start) begin
|
case (tx_fifo_bus_state)
|
||||||
tx_wdata_first_push <= 1'b1;
|
TX_FIFO_BUS_STATE_IDLE: begin
|
||||||
tx_buffer_ready <= 1'b1;
|
if (dma_start && !dma_scb.direction) begin
|
||||||
tx_buffer_valid <= 1'b0;
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_WAIT;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (tx_buffer_ready && mem_bus.request) begin
|
|
||||||
tx_buffer_ready <= 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (mem_bus.ack) begin
|
|
||||||
tx_wdata_first_push <= 1'b0;
|
|
||||||
tx_buffer_counter <= 1'd1;
|
|
||||||
tx_buffer_valid <= 1'b1;
|
|
||||||
{fifo_bus.tx_wdata, tx_buffer} <= mem_bus.rdata;
|
|
||||||
if (tx_wdata_first_push && dma_scb.starting_address[0]) begin
|
|
||||||
fifo_bus.tx_wdata <= mem_bus.rdata[7:0];
|
|
||||||
tx_buffer_counter <= 1'd0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (tx_wdata_push) begin
|
|
||||||
tx_buffer_counter <= tx_buffer_counter - 1'd1;
|
|
||||||
fifo_bus.tx_wdata <= tx_buffer;
|
|
||||||
if (tx_buffer_counter == 1'd0) begin
|
|
||||||
tx_buffer_ready <= 1'b1;
|
|
||||||
tx_buffer_valid <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
// Remaining counter controller
|
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if (reset || dma_stop) begin
|
|
||||||
remaining <= 27'd0;
|
|
||||||
end else begin
|
|
||||||
if (dma_start) begin
|
|
||||||
remaining <= dma_scb.transfer_length;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((mem_bus.write && rx_rdata_pop) || (!mem_bus.write && tx_wdata_push)) begin
|
TX_FIFO_BUS_STATE_WAIT: begin
|
||||||
remaining <= remaining - 1'd1;
|
if (mem_bus_rdata_ack || tx_fifo_waiting) begin
|
||||||
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_TRANSFER_1;
|
||||||
|
end else if (mem_bus_rdata_end) begin
|
||||||
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_IDLE;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
TX_FIFO_BUS_STATE_TRANSFER_1: begin
|
||||||
|
fifo_bus.tx_write = (!fifo_bus.tx_full && tx_fifo_valid[1]);
|
||||||
|
if (!fifo_bus.tx_full || !tx_fifo_valid[1]) begin
|
||||||
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_TRANSFER_2;
|
||||||
|
tx_fifo_shift = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
// Mem bus controller
|
TX_FIFO_BUS_STATE_TRANSFER_2: begin
|
||||||
|
fifo_bus.tx_write = (!fifo_bus.tx_full && tx_fifo_valid[1]);
|
||||||
always_ff @(posedge clk) begin
|
if (!fifo_bus.tx_full || !tx_fifo_valid[1]) begin
|
||||||
dma_scb.busy <= mem_bus.request || trx_enabled;
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_WAIT;
|
||||||
end
|
tx_fifo_shift = 1'b1;
|
||||||
|
if (!mem_bus_rdata_ack && !tx_fifo_waiting && mem_bus_rdata_end) begin
|
||||||
always_ff @(posedge clk) begin
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_IDLE;
|
||||||
if (reset) begin
|
|
||||||
mem_bus.request <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
if (!mem_bus.request) begin
|
|
||||||
if (mem_bus.write) begin
|
|
||||||
if (rx_buffer_valid) begin
|
|
||||||
mem_bus.request <= 1'b1;
|
|
||||||
mem_bus.wmask <= rx_wmask;
|
|
||||||
mem_bus.wdata <= rx_buffer;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
if (tx_buffer_ready) begin
|
|
||||||
mem_bus.request <= 1'b1;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if (mem_bus.ack) begin
|
default: begin
|
||||||
mem_bus.request <= 1'b0;
|
next_tx_fifo_bus_state = TX_FIFO_BUS_STATE_IDLE;
|
||||||
end
|
end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (dma_start) begin
|
if (tx_fifo_shift) begin
|
||||||
mem_bus.write <= dma_scb.direction;
|
tx_fifo_valid <= {tx_fifo_valid[0], 1'bX};
|
||||||
|
tx_fifo_buffer <= {tx_fifo_buffer[7:0], 8'hXX};
|
||||||
end
|
end
|
||||||
|
|
||||||
|
case (tx_fifo_bus_state)
|
||||||
|
TX_FIFO_BUS_STATE_IDLE: begin
|
||||||
|
mem_bus_rdata_ready <= 1'b0;
|
||||||
|
tx_fifo_waiting <= 1'b0;
|
||||||
|
if (dma_start) begin
|
||||||
|
mem_bus_rdata_ready <= !dma_scb.direction;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TX_FIFO_BUS_STATE_WAIT: begin
|
||||||
|
if (mem_bus_rdata_ack || tx_fifo_waiting) begin
|
||||||
|
mem_bus_rdata_ready <= 1'b0;
|
||||||
|
tx_fifo_waiting <= 1'b0;
|
||||||
|
tx_fifo_valid <= mem_bus_rdata_valid;
|
||||||
|
tx_fifo_buffer <= mem_bus_rdata_buffer;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TX_FIFO_BUS_STATE_TRANSFER_1: begin
|
||||||
|
if (mem_bus_rdata_ack) begin
|
||||||
|
tx_fifo_waiting <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TX_FIFO_BUS_STATE_TRANSFER_2: begin
|
||||||
|
if (mem_bus_rdata_ack) begin
|
||||||
|
tx_fifo_waiting <= 1'b1;
|
||||||
|
end
|
||||||
|
if (fifo_bus.tx_write || !tx_fifo_valid[1]) begin
|
||||||
|
mem_bus_rdata_ready <= !mem_bus_rdata_end;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
|
||||||
if (dma_start) begin
|
|
||||||
mem_bus.address <= {dma_scb.starting_address[26:1], 1'b0};
|
|
||||||
end
|
|
||||||
|
|
||||||
if (mem_bus.ack) begin
|
// DMA busy indicator
|
||||||
mem_bus.address <= mem_bus.address + 2'd2;
|
|
||||||
end
|
always_ff @(posedge clk) begin
|
||||||
|
dma_scb.busy <= (
|
||||||
|
(dma_scb.start && !dma_scb.stop) ||
|
||||||
|
dma_start ||
|
||||||
|
(mem_bus_state != MEM_BUS_STATE_IDLE) ||
|
||||||
|
(rx_fifo_bus_state != RX_FIFO_BUS_STATE_IDLE) ||
|
||||||
|
(tx_fifo_bus_state != TX_FIFO_BUS_STATE_IDLE)
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -234,7 +234,7 @@ module memory_flash (
|
|||||||
if (reset) begin
|
if (reset) begin
|
||||||
state <= STATE_IDLE;
|
state <= STATE_IDLE;
|
||||||
end else begin
|
end else begin
|
||||||
if (!busy && (start || finish)) begin
|
if ((start || finish) && !busy) begin
|
||||||
counter <= counter + 1'd1;
|
counter <= counter + 1'd1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -248,6 +248,7 @@ module memory_flash (
|
|||||||
end else if (mem_bus.request) begin
|
end else if (mem_bus.request) begin
|
||||||
current_address <= {mem_bus.address[23:1], 1'b0};
|
current_address <= {mem_bus.address[23:1], 1'b0};
|
||||||
if (mem_bus.write) begin
|
if (mem_bus.write) begin
|
||||||
|
current_address[0] <= (~mem_bus.wmask[1]);
|
||||||
state <= STATE_WRITE_ENABLE;
|
state <= STATE_WRITE_ENABLE;
|
||||||
end else begin
|
end else begin
|
||||||
state <= STATE_READ_START;
|
state <= STATE_READ_START;
|
||||||
@ -263,7 +264,7 @@ module memory_flash (
|
|||||||
end
|
end
|
||||||
3'd1: begin
|
3'd1: begin
|
||||||
finish <= 1'b1;
|
finish <= 1'b1;
|
||||||
wdata <= 8'd4;
|
wdata <= 8'd5;
|
||||||
if (!busy) begin
|
if (!busy) begin
|
||||||
counter <= 3'd0;
|
counter <= 3'd0;
|
||||||
if (flash_scb.erase_pending) begin
|
if (flash_scb.erase_pending) begin
|
||||||
@ -296,7 +297,7 @@ module memory_flash (
|
|||||||
end
|
end
|
||||||
3'd4: begin
|
3'd4: begin
|
||||||
finish <= 1'b1;
|
finish <= 1'b1;
|
||||||
wdata <= 8'd4;
|
wdata <= 8'd5;
|
||||||
if (!busy) begin
|
if (!busy) begin
|
||||||
flash_scb.erase_done <= 1'b1;
|
flash_scb.erase_done <= 1'b1;
|
||||||
counter <= 3'd0;
|
counter <= 3'd0;
|
||||||
@ -314,17 +315,17 @@ module memory_flash (
|
|||||||
end
|
end
|
||||||
3'd1: begin
|
3'd1: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.address[23:16];
|
wdata <= current_address[23:16];
|
||||||
end
|
end
|
||||||
3'd2: begin
|
3'd2: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.address[15:8];
|
wdata <= current_address[15:8];
|
||||||
end
|
end
|
||||||
3'd3: begin
|
3'd3: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.address[7:0];
|
wdata <= current_address[7:0];
|
||||||
if (!busy) begin
|
if (!busy) begin
|
||||||
counter <= 3'd0;
|
counter <= 3'd0 + current_address[0];
|
||||||
state <= STATE_PROGRAM;
|
state <= STATE_PROGRAM;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -336,26 +337,33 @@ module memory_flash (
|
|||||||
3'd0: begin
|
3'd0: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.wdata[15:8];
|
wdata <= mem_bus.wdata[15:8];
|
||||||
|
if (start && !busy) begin
|
||||||
|
current_address <= current_address + 1'd1;
|
||||||
|
if (!mem_bus.wmask[0]) begin
|
||||||
|
counter <= 3'd2;
|
||||||
|
mem_bus.ack <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
3'd1: begin
|
3'd1: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.wdata[7:0];
|
wdata <= mem_bus.wdata[7:0];
|
||||||
if (!busy) begin
|
if (!busy) begin
|
||||||
mem_bus.ack <= 1'b1;
|
mem_bus.ack <= 1'b1;
|
||||||
current_address <= current_address + 2'd2;
|
current_address <= current_address + 1'd1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
3'd2: begin
|
3'd2: begin
|
||||||
if (current_address[7:0] == 8'h00) begin
|
if (current_address[7:0] == 8'h00) begin
|
||||||
state <= STATE_PROGRAM_END;
|
state <= STATE_PROGRAM_END;
|
||||||
end else if (flash_scb.erase_pending) begin
|
|
||||||
state <= STATE_PROGRAM_END;
|
|
||||||
end else if (mem_bus.request && !mem_bus.ack) begin
|
end else if (mem_bus.request && !mem_bus.ack) begin
|
||||||
if (!mem_bus.write || (mem_bus.address[23:0] != current_address)) begin
|
if (mem_bus.write && mem_bus.wmask[1] && (mem_bus.address[23:0] == current_address)) begin
|
||||||
state <= STATE_PROGRAM_END;
|
|
||||||
end else begin
|
|
||||||
counter <= 3'd0;
|
counter <= 3'd0;
|
||||||
|
end else begin
|
||||||
|
state <= STATE_PROGRAM_END;
|
||||||
end
|
end
|
||||||
|
end else if (!busy) begin
|
||||||
|
state <= STATE_PROGRAM_END;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
@ -363,8 +371,8 @@ module memory_flash (
|
|||||||
|
|
||||||
STATE_PROGRAM_END: begin
|
STATE_PROGRAM_END: begin
|
||||||
finish <= 1'b1;
|
finish <= 1'b1;
|
||||||
wdata <= 8'd4;
|
wdata <= 8'd5;
|
||||||
if (!busy) begin
|
if (finish && !busy) begin
|
||||||
counter <= 3'd0;
|
counter <= 3'd0;
|
||||||
state <= STATE_WAIT;
|
state <= STATE_WAIT;
|
||||||
end
|
end
|
||||||
@ -407,15 +415,15 @@ module memory_flash (
|
|||||||
3'd1: begin
|
3'd1: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
quad_enable <= 1'b1;
|
quad_enable <= 1'b1;
|
||||||
wdata <= mem_bus.address[23:16];
|
wdata <= current_address[23:16];
|
||||||
end
|
end
|
||||||
3'd2: begin
|
3'd2: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.address[15:8];
|
wdata <= current_address[15:8];
|
||||||
end
|
end
|
||||||
3'd3: begin
|
3'd3: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
wdata <= mem_bus.address[7:0];
|
wdata <= current_address[7:0];
|
||||||
end
|
end
|
||||||
3'd4: begin
|
3'd4: begin
|
||||||
start <= 1'b1;
|
start <= 1'b1;
|
||||||
|
@ -14,29 +14,38 @@ module memory_sdram (
|
|||||||
inout [15:0] sdram_dq
|
inout [15:0] sdram_dq
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam [2:0] CAS_LATENCY = 3'd2;
|
// in Hz
|
||||||
|
localparam real FREQUENCY = 100_000_000.0;
|
||||||
|
|
||||||
localparam real T_INIT = 100_000.0;
|
// in clocks
|
||||||
localparam real T_RC = 60.0;
|
localparam bit [2:0] CAS_LATENCY = 3'd2;
|
||||||
localparam real T_RP = 15.0;
|
|
||||||
localparam real T_RCD = 15.0;
|
|
||||||
localparam real T_MRD = 14.0;
|
|
||||||
localparam real T_REF = 7_800.0;
|
|
||||||
|
|
||||||
localparam real T_CLK = (1.0 / 100_000_000) * 1_000_000_000.0;
|
// in nanoseconds
|
||||||
localparam int C_INIT = int'((T_INIT + T_CLK - 1) / T_CLK);
|
localparam real T_INIT = 100_000.0;
|
||||||
localparam int C_RC = int'((T_RC + T_CLK - 1) / T_CLK);
|
localparam real T_MRD = 14.0;
|
||||||
localparam int C_RP = int'((T_RP + T_CLK - 1) / T_CLK);
|
localparam real T_RAS = 37.0;
|
||||||
localparam int C_RCD = int'((T_RCD + T_CLK - 1) / T_CLK);
|
localparam real T_RC = 60.0;
|
||||||
localparam int C_MRD = int'((T_MRD + T_CLK - 1) / T_CLK);
|
localparam real T_RCD = 15.0;
|
||||||
localparam int C_REF = int'((T_REF + T_CLK - 1) / T_CLK);
|
localparam real T_REF = 7_812.5;
|
||||||
|
localparam real T_RP = 15.0;
|
||||||
|
|
||||||
localparam INIT_PRECHARGE = 4'd0;
|
localparam real T_CLK = (1.0 / FREQUENCY) * 1_000_000_000.0;
|
||||||
localparam INIT_REFRESH_1 = C_RP;
|
|
||||||
localparam INIT_REFRESH_2 = C_RP + C_RC;
|
|
||||||
localparam INIT_MODE_REG = C_RP + (2 * C_RC);
|
|
||||||
localparam INIT_DONE = C_RP + (2 * C_RC) + C_MRD;
|
|
||||||
|
|
||||||
|
const bit [13:0] C_INIT = 14'(int'($ceil(T_INIT / T_CLK)));
|
||||||
|
const bit [4:0] C_MRD = 5'(int'($ceil(T_MRD / T_CLK)));
|
||||||
|
const bit [2:0] C_RAS = 3'(int'($ceil(T_RAS / T_CLK)));
|
||||||
|
const bit [4:0] C_RC = 5'(int'($ceil(T_RC / T_CLK)));
|
||||||
|
const bit [4:0] C_RCD = 5'(int'($ceil(T_RCD / T_CLK)));
|
||||||
|
const bit [13:0] C_REF = 14'(int'($ceil(T_REF / T_CLK)));
|
||||||
|
const bit [4:0] C_RP = 5'(int'($ceil(T_RP / T_CLK)));
|
||||||
|
|
||||||
|
const bit [4:0] INIT_PRECHARGE = 5'd0;
|
||||||
|
const bit [4:0] INIT_REFRESH_1 = INIT_PRECHARGE + C_RP;
|
||||||
|
const bit [4:0] INIT_REFRESH_2 = INIT_REFRESH_1 + C_RC;
|
||||||
|
const bit [4:0] INIT_MODE_REG = INIT_REFRESH_2 + C_RC;
|
||||||
|
const bit [4:0] INIT_DONE = INIT_MODE_REG + C_MRD;
|
||||||
|
|
||||||
|
// /CS, /RAS, /CAS, /WE
|
||||||
typedef enum bit [3:0] {
|
typedef enum bit [3:0] {
|
||||||
CMD_DESL = 4'b1111,
|
CMD_DESL = 4'b1111,
|
||||||
CMD_NOP = 4'b0111,
|
CMD_NOP = 4'b0111,
|
||||||
@ -58,13 +67,10 @@ module memory_sdram (
|
|||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
{sdram_cs, sdram_ras, sdram_cas, sdram_we} <= 4'(sdram_next_cmd);
|
{sdram_cs, sdram_ras, sdram_cas, sdram_we} <= 4'(sdram_next_cmd);
|
||||||
|
|
||||||
{sdram_ba, sdram_a} <= 15'd0;
|
{sdram_ba, sdram_a} <= 15'd0;
|
||||||
sdram_dqm <= 2'b00;
|
sdram_dqm <= 2'b00;
|
||||||
|
|
||||||
sdram_dq_input <= sdram_dq;
|
sdram_dq_input <= sdram_dq;
|
||||||
sdram_dq_output <= mem_bus.wdata;
|
sdram_dq_output <= mem_bus.wdata;
|
||||||
|
|
||||||
sdram_dq_output_enable <= 1'b0;
|
sdram_dq_output_enable <= 1'b0;
|
||||||
|
|
||||||
case (sdram_next_cmd)
|
case (sdram_next_cmd)
|
||||||
@ -76,19 +82,31 @@ module memory_sdram (
|
|||||||
|
|
||||||
CMD_ACT: begin
|
CMD_ACT: begin
|
||||||
{sdram_ba, sdram_a} <= mem_bus.address[25:11];
|
{sdram_ba, sdram_a} <= mem_bus.address[25:11];
|
||||||
sdram_dqm <= 2'b00;
|
|
||||||
current_active_bank_row <= mem_bus.address[25:11];
|
current_active_bank_row <= mem_bus.address[25:11];
|
||||||
end
|
end
|
||||||
|
|
||||||
CMD_PRE: begin
|
CMD_PRE: begin
|
||||||
{sdram_ba, sdram_a} <= {2'b00, 2'b00, 1'b1, 10'd0};
|
{sdram_ba, sdram_a} <= {
|
||||||
sdram_dqm <= 2'b00;
|
2'b00, // [BA1:BA0] Don't care
|
||||||
|
2'b00, // [A12:A11] Don't care
|
||||||
|
1'b1, // [A10] Precharge all banks
|
||||||
|
10'd0 // [A9:A0] Don't care
|
||||||
|
};
|
||||||
end
|
end
|
||||||
|
|
||||||
CMD_MRS: begin
|
CMD_MRS: begin
|
||||||
{sdram_ba, sdram_a} <= {2'b00, 1'b0, 1'b0, 2'b00, CAS_LATENCY, 1'b0, 3'b000};
|
{sdram_ba, sdram_a} <= {
|
||||||
sdram_dqm <= 2'b00;
|
2'b00, // [BA1:BA0] Reserved = 0
|
||||||
|
3'b000, // [A12:A10] Reserved = 0
|
||||||
|
1'b0, // [A9] Write Burst Mode = Programmed Burst Length
|
||||||
|
2'b00, // [A8:A7] Operating Mode = Standard Operation
|
||||||
|
CAS_LATENCY, // [A6:A4] Latency Mode = 2
|
||||||
|
1'b0, // [A3] Burst Type = Sequential
|
||||||
|
3'b000 // [A2:A0] Burst Length = 1
|
||||||
|
};
|
||||||
end
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -121,35 +139,51 @@ module memory_sdram (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
logic [13:0] powerup_coutner;
|
logic [13:0] refresh_counter;
|
||||||
logic powerup_done;
|
|
||||||
logic [4:0] wait_counter;
|
logic [4:0] wait_counter;
|
||||||
logic [9:0] refresh_counter;
|
logic [2:0] precharge_counter;
|
||||||
|
logic powerup_done;
|
||||||
logic pending_refresh;
|
logic pending_refresh;
|
||||||
|
logic precharge_valid;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset) begin
|
refresh_counter <= refresh_counter + 1'd1;
|
||||||
powerup_coutner <= 14'd0;
|
|
||||||
powerup_done <= 1'b0;
|
if (refresh_counter == C_INIT) begin
|
||||||
end else if (powerup_coutner < C_INIT) begin
|
refresh_counter <= 14'd0;
|
||||||
powerup_coutner <= powerup_coutner + 1'd1;
|
|
||||||
end else begin
|
|
||||||
powerup_done <= 1'b1;
|
powerup_done <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (reset || state != next_state) begin
|
if (powerup_done && refresh_counter == C_REF - 14'd1) begin
|
||||||
wait_counter <= 5'd0;
|
refresh_counter <= 14'd0;
|
||||||
end else begin
|
pending_refresh <= 1'b1;
|
||||||
wait_counter <= wait_counter + 1'd1;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (sdram_next_cmd == CMD_REF) begin
|
if (sdram_next_cmd == CMD_REF) begin
|
||||||
refresh_counter <= 10'd0;
|
|
||||||
pending_refresh <= 1'b0;
|
pending_refresh <= 1'b0;
|
||||||
end else if (refresh_counter < C_REF) begin
|
end
|
||||||
refresh_counter <= refresh_counter + 1'd1;
|
|
||||||
end else begin
|
if (reset) begin
|
||||||
pending_refresh <= 1'b1;
|
refresh_counter <= 14'd0;
|
||||||
|
powerup_done <= 1'b0;
|
||||||
|
pending_refresh <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
wait_counter <= wait_counter + 1'd1;
|
||||||
|
|
||||||
|
if (state != next_state) begin
|
||||||
|
wait_counter <= 5'd0;
|
||||||
|
end
|
||||||
|
|
||||||
|
precharge_counter <= precharge_counter + 1'd1;
|
||||||
|
|
||||||
|
if (precharge_counter >= C_RAS - 2'd2) begin
|
||||||
|
precharge_valid <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (sdram_next_cmd == CMD_ACT) begin
|
||||||
|
precharge_counter <= 3'd0;
|
||||||
|
precharge_valid <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -157,6 +191,7 @@ module memory_sdram (
|
|||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
mem_bus.ack <= 1'b0;
|
mem_bus.ack <= 1'b0;
|
||||||
|
|
||||||
read_cmd_ack_delay <= {sdram_next_cmd == CMD_READ, read_cmd_ack_delay[(CAS_LATENCY):1]};
|
read_cmd_ack_delay <= {sdram_next_cmd == CMD_READ, read_cmd_ack_delay[(CAS_LATENCY):1]};
|
||||||
|
|
||||||
if (sdram_next_cmd == CMD_WRITE || read_cmd_ack_delay[0]) begin
|
if (sdram_next_cmd == CMD_WRITE || read_cmd_ack_delay[0]) begin
|
||||||
@ -202,20 +237,20 @@ module memory_sdram (
|
|||||||
end
|
end
|
||||||
|
|
||||||
S_ACTIVATING: begin
|
S_ACTIVATING: begin
|
||||||
if (wait_counter == C_RCD) begin
|
if (wait_counter == C_RCD - 5'd2) begin
|
||||||
next_state = S_ACTIVE;
|
next_state = S_ACTIVE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_ACTIVE: begin
|
S_ACTIVE: begin
|
||||||
if (pending_refresh) begin
|
if (pending_refresh && precharge_valid) begin
|
||||||
next_state = S_PRECHARGE;
|
next_state = S_PRECHARGE;
|
||||||
sdram_next_cmd = CMD_PRE;
|
sdram_next_cmd = CMD_PRE;
|
||||||
end else if (mem_bus.request) begin
|
end else if (mem_bus.request) begin
|
||||||
if (request_in_current_active_bank_row) begin
|
if (request_in_current_active_bank_row) begin
|
||||||
next_state = S_BUSY;
|
next_state = S_BUSY;
|
||||||
sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ;
|
sdram_next_cmd = mem_bus.write ? CMD_WRITE : CMD_READ;
|
||||||
end else begin
|
end else if (precharge_valid) begin
|
||||||
next_state = S_PRECHARGE;
|
next_state = S_PRECHARGE;
|
||||||
sdram_next_cmd = CMD_PRE;
|
sdram_next_cmd = CMD_PRE;
|
||||||
end
|
end
|
||||||
@ -229,18 +264,13 @@ module memory_sdram (
|
|||||||
end
|
end
|
||||||
|
|
||||||
S_PRECHARGE: begin
|
S_PRECHARGE: begin
|
||||||
if (wait_counter == C_RP) begin
|
if (wait_counter == C_RP - 5'd2) begin
|
||||||
if (pending_refresh) begin
|
next_state = S_IDLE;
|
||||||
next_state = S_REFRESH;
|
|
||||||
sdram_next_cmd = CMD_REF;
|
|
||||||
end else begin
|
|
||||||
next_state = S_IDLE;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_REFRESH: begin
|
S_REFRESH: begin
|
||||||
if (wait_counter == C_RC) begin
|
if (wait_counter == C_RC - 5'd2) begin
|
||||||
next_state = S_IDLE;
|
next_state = S_IDLE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,7 @@ module n64_cfg (
|
|||||||
output logic irq
|
output logic irq
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef enum bit [3:0] {
|
typedef enum bit [3:0] {
|
||||||
REG_STATUS,
|
REG_STATUS,
|
||||||
REG_COMMAND,
|
REG_COMMAND,
|
||||||
REG_DATA_0_H,
|
REG_DATA_0_H,
|
||||||
@ -19,10 +19,39 @@ module n64_cfg (
|
|||||||
REG_IDENTIFIER_H,
|
REG_IDENTIFIER_H,
|
||||||
REG_IDENTIFIER_L,
|
REG_IDENTIFIER_L,
|
||||||
REG_KEY_H,
|
REG_KEY_H,
|
||||||
REG_KEY_L
|
REG_KEY_L,
|
||||||
|
REG_IRQ_H,
|
||||||
|
REG_IRQ_L,
|
||||||
|
REG_AUX_H,
|
||||||
|
REG_AUX_L
|
||||||
} e_reg;
|
} e_reg;
|
||||||
|
|
||||||
logic cfg_error;
|
logic cmd_error;
|
||||||
|
logic cmd_irq_request;
|
||||||
|
logic cmd_irq;
|
||||||
|
|
||||||
|
logic btn_irq;
|
||||||
|
logic usb_irq;
|
||||||
|
logic aux_irq;
|
||||||
|
|
||||||
|
logic btn_irq_mask;
|
||||||
|
logic cmd_irq_mask;
|
||||||
|
logic usb_irq_mask;
|
||||||
|
logic aux_irq_mask;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
irq <= (
|
||||||
|
(btn_irq && btn_irq_mask) ||
|
||||||
|
(cmd_irq && cmd_irq_mask) ||
|
||||||
|
(usb_irq && usb_irq_mask) ||
|
||||||
|
(aux_irq && aux_irq_mask)
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
btn_irq_mask = 1'b1;
|
||||||
|
cmd_irq_mask = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
reg_bus.rdata = 16'd0;
|
reg_bus.rdata = 16'd0;
|
||||||
@ -30,11 +59,18 @@ module n64_cfg (
|
|||||||
case (reg_bus.address[4:1])
|
case (reg_bus.address[4:1])
|
||||||
REG_STATUS: reg_bus.rdata = {
|
REG_STATUS: reg_bus.rdata = {
|
||||||
n64_scb.cfg_pending,
|
n64_scb.cfg_pending,
|
||||||
cfg_error,
|
cmd_error,
|
||||||
irq,
|
btn_irq,
|
||||||
13'd0
|
btn_irq_mask,
|
||||||
|
cmd_irq,
|
||||||
|
cmd_irq_mask,
|
||||||
|
usb_irq,
|
||||||
|
usb_irq_mask,
|
||||||
|
aux_irq,
|
||||||
|
aux_irq_mask,
|
||||||
|
6'd0
|
||||||
};
|
};
|
||||||
REG_COMMAND: reg_bus.rdata = {8'd0, n64_scb.cfg_cmd};
|
REG_COMMAND: reg_bus.rdata = {7'd0, cmd_irq_request, n64_scb.cfg_cmd};
|
||||||
REG_DATA_0_H: reg_bus.rdata = n64_scb.cfg_wdata[0][31:16];
|
REG_DATA_0_H: reg_bus.rdata = n64_scb.cfg_wdata[0][31:16];
|
||||||
REG_DATA_0_L: reg_bus.rdata = n64_scb.cfg_wdata[0][15:0];
|
REG_DATA_0_L: reg_bus.rdata = n64_scb.cfg_wdata[0][15:0];
|
||||||
REG_DATA_1_H: reg_bus.rdata = n64_scb.cfg_wdata[1][31:16];
|
REG_DATA_1_H: reg_bus.rdata = n64_scb.cfg_wdata[1][31:16];
|
||||||
@ -43,6 +79,10 @@ module n64_cfg (
|
|||||||
REG_IDENTIFIER_L: reg_bus.rdata = n64_scb.cfg_identifier[15:0];
|
REG_IDENTIFIER_L: reg_bus.rdata = n64_scb.cfg_identifier[15:0];
|
||||||
REG_KEY_H: reg_bus.rdata = 16'd0;
|
REG_KEY_H: reg_bus.rdata = 16'd0;
|
||||||
REG_KEY_L: reg_bus.rdata = 16'd0;
|
REG_KEY_L: reg_bus.rdata = 16'd0;
|
||||||
|
REG_IRQ_H: reg_bus.rdata = 16'd0;
|
||||||
|
REG_IRQ_L: reg_bus.rdata = 16'd0;
|
||||||
|
REG_AUX_H: reg_bus.rdata = n64_scb.aux_wdata[31:16];
|
||||||
|
REG_AUX_L: reg_bus.rdata = n64_scb.aux_wdata[15:0];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -51,48 +91,145 @@ module n64_cfg (
|
|||||||
logic lock_sequence_counter;
|
logic lock_sequence_counter;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (n64_scb.cfg_done) begin
|
n64_scb.aux_pending <= 1'b0;
|
||||||
|
|
||||||
|
if (n64_scb.cfg_pending && n64_scb.cfg_done) begin
|
||||||
n64_scb.cfg_pending <= 1'b0;
|
n64_scb.cfg_pending <= 1'b0;
|
||||||
cfg_error <= n64_scb.cfg_error;
|
cmd_irq <= cmd_irq_request;
|
||||||
|
cmd_error <= n64_scb.cfg_error;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (n64_scb.cfg_irq) begin
|
if (n64_scb.cfg_unlock) begin
|
||||||
irq <= 1'b1;
|
if (n64_scb.btn_irq) begin
|
||||||
|
btn_irq <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (n64_scb.usb_irq) begin
|
||||||
|
usb_irq <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (n64_scb.aux_irq) begin
|
||||||
|
aux_irq <= 1'b1;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (unlock_flag) begin
|
if (unlock_flag) begin
|
||||||
n64_scb.cfg_unlock <= 1'b1;
|
n64_scb.cfg_unlock <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (reset || n64_scb.n64_reset || n64_scb.n64_nmi) begin
|
if (reset) begin
|
||||||
n64_scb.cfg_unlock <= 1'b0;
|
n64_scb.cfg_unlock <= 1'b0;
|
||||||
n64_scb.cfg_pending <= 1'b0;
|
n64_scb.cfg_pending <= 1'b0;
|
||||||
n64_scb.cfg_cmd <= 8'h00;
|
n64_scb.cfg_cmd <= 8'h00;
|
||||||
irq <= 1'b0;
|
cmd_error <= 1'b0;
|
||||||
cfg_error <= 1'b0;
|
cmd_irq_request <= 1'b0;
|
||||||
|
btn_irq <= 1'b0;
|
||||||
|
cmd_irq <= 1'b0;
|
||||||
|
usb_irq <= 1'b0;
|
||||||
|
aux_irq <= 1'b0;
|
||||||
|
usb_irq_mask <= 1'b0;
|
||||||
|
aux_irq_mask <= 1'b0;
|
||||||
|
lock_sequence_counter <= 1'd0;
|
||||||
|
end else if (n64_scb.n64_reset || n64_scb.n64_nmi) begin
|
||||||
|
n64_scb.cfg_unlock <= 1'b0;
|
||||||
|
cmd_irq_request <= 1'b0;
|
||||||
|
btn_irq <= 1'b0;
|
||||||
|
cmd_irq <= 1'b0;
|
||||||
|
usb_irq <= 1'b0;
|
||||||
|
aux_irq <= 1'b0;
|
||||||
|
usb_irq_mask <= 1'b0;
|
||||||
|
aux_irq_mask <= 1'b0;
|
||||||
lock_sequence_counter <= 1'd0;
|
lock_sequence_counter <= 1'd0;
|
||||||
end else if (n64_scb.cfg_unlock) begin
|
end else if (n64_scb.cfg_unlock) begin
|
||||||
if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
|
if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
|
||||||
case (reg_bus.address[4:1])
|
case (reg_bus.address[4:1])
|
||||||
REG_COMMAND: begin
|
REG_COMMAND: begin
|
||||||
n64_scb.cfg_pending <= 1'b1;
|
if (!n64_scb.cfg_pending) begin
|
||||||
n64_scb.cfg_cmd <= reg_bus.wdata[7:0];
|
n64_scb.cfg_pending <= 1'b1;
|
||||||
cfg_error <= 1'b0;
|
cmd_error <= 1'b0;
|
||||||
|
cmd_irq_request <= reg_bus.wdata[8];
|
||||||
|
n64_scb.cfg_cmd <= reg_bus.wdata[7:0];
|
||||||
|
end
|
||||||
end
|
end
|
||||||
REG_DATA_0_H: n64_scb.cfg_rdata[0][31:16] <= reg_bus.wdata;
|
|
||||||
REG_DATA_0_L: n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
|
REG_DATA_0_H: begin
|
||||||
REG_DATA_1_H: n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
|
if (!n64_scb.cfg_pending) begin
|
||||||
REG_DATA_1_L: n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
|
n64_scb.cfg_rdata[0][31:16] <= reg_bus.wdata;
|
||||||
REG_IDENTIFIER_H: irq <= 1'b0;
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_DATA_0_L: begin
|
||||||
|
if (!n64_scb.cfg_pending) begin
|
||||||
|
n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_DATA_1_H: begin
|
||||||
|
if (!n64_scb.cfg_pending) begin
|
||||||
|
n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_DATA_1_L: begin
|
||||||
|
if (!n64_scb.cfg_pending) begin
|
||||||
|
n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_IDENTIFIER_H: begin
|
||||||
|
btn_irq <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
REG_KEY_H, REG_KEY_L: begin
|
REG_KEY_H, REG_KEY_L: begin
|
||||||
lock_sequence_counter <= lock_sequence_counter + 1'd1;
|
lock_sequence_counter <= lock_sequence_counter + 1'd1;
|
||||||
if (reg_bus.wdata != 16'hFFFF) begin
|
if (reg_bus.wdata != 16'hFFFF) begin
|
||||||
lock_sequence_counter <= 1'd0;
|
lock_sequence_counter <= 1'd0;
|
||||||
end
|
end
|
||||||
if (lock_sequence_counter == 1'd1) begin
|
if (lock_sequence_counter == 1'd1) begin
|
||||||
n64_scb.cfg_unlock <= (reg_bus.wdata != 16'hFFFF);
|
if (reg_bus.wdata == 16'hFFFF) begin
|
||||||
|
n64_scb.cfg_unlock <= 1'b0;
|
||||||
|
cmd_irq_request <= 1'b0;
|
||||||
|
btn_irq <= 1'b0;
|
||||||
|
cmd_irq <= 1'b0;
|
||||||
|
usb_irq <= 1'b0;
|
||||||
|
aux_irq <= 1'b0;
|
||||||
|
usb_irq_mask <= 1'b0;
|
||||||
|
aux_irq_mask <= 1'b0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
REG_IRQ_H: begin
|
||||||
|
btn_irq <= (reg_bus.wdata[15] ? 1'b0 : btn_irq);
|
||||||
|
cmd_irq <= (reg_bus.wdata[14] ? 1'b0 : cmd_irq);
|
||||||
|
usb_irq <= (reg_bus.wdata[13] ? 1'b0 : usb_irq);
|
||||||
|
aux_irq <= (reg_bus.wdata[12] ? 1'b0 : aux_irq);
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_IRQ_L: begin
|
||||||
|
if (reg_bus.wdata[10]) begin
|
||||||
|
usb_irq_mask <= 1'b1;
|
||||||
|
end
|
||||||
|
if (reg_bus.wdata[11]) begin
|
||||||
|
usb_irq_mask <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (reg_bus.wdata[8]) begin
|
||||||
|
aux_irq_mask <= 1'b1;
|
||||||
|
end
|
||||||
|
if (reg_bus.wdata[9]) begin
|
||||||
|
aux_irq_mask <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_AUX_H: begin
|
||||||
|
n64_scb.aux_rdata[31:16] <= reg_bus.wdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
REG_AUX_L: begin
|
||||||
|
n64_scb.aux_pending <= 1'b1;
|
||||||
|
n64_scb.aux_rdata[15:0] <= reg_bus.wdata;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,7 +6,8 @@ module n64_cic (
|
|||||||
|
|
||||||
input n64_reset,
|
input n64_reset,
|
||||||
input n64_cic_clk,
|
input n64_cic_clk,
|
||||||
inout n64_cic_dq
|
inout n64_cic_dq,
|
||||||
|
input n64_si_clk
|
||||||
);
|
);
|
||||||
|
|
||||||
// Input/output synchronization
|
// Input/output synchronization
|
||||||
@ -14,26 +15,83 @@ module n64_cic (
|
|||||||
logic [1:0] n64_reset_ff;
|
logic [1:0] n64_reset_ff;
|
||||||
logic [1:0] n64_cic_clk_ff;
|
logic [1:0] n64_cic_clk_ff;
|
||||||
logic [1:0] n64_cic_dq_ff;
|
logic [1:0] n64_cic_dq_ff;
|
||||||
|
logic [1:0] n64_si_clk_ff;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
n64_reset_ff <= {n64_reset_ff[0], n64_reset};
|
n64_reset_ff <= {n64_reset_ff[0], n64_reset};
|
||||||
n64_cic_clk_ff <= {n64_cic_clk_ff[0], n64_cic_clk};
|
n64_cic_clk_ff <= {n64_cic_clk_ff[0], n64_cic_clk};
|
||||||
n64_cic_dq_ff <= {n64_cic_dq_ff[0], n64_cic_dq};
|
n64_cic_dq_ff <= {n64_cic_dq_ff[0], n64_cic_dq};
|
||||||
|
n64_si_clk_ff <= {n64_si_clk_ff[0], n64_si_clk};
|
||||||
end
|
end
|
||||||
|
|
||||||
logic cic_reset;
|
logic cic_reset;
|
||||||
logic cic_clk;
|
logic cic_clk;
|
||||||
logic cic_dq;
|
logic cic_dq;
|
||||||
|
logic si_clk;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
cic_reset = n64_reset_ff[1];
|
cic_reset = n64_reset_ff[1];
|
||||||
cic_clk = n64_cic_clk_ff[1];
|
cic_clk = n64_cic_clk_ff[1];
|
||||||
cic_dq = n64_cic_dq_ff[1];
|
cic_dq = n64_cic_dq_ff[1];
|
||||||
|
si_clk = n64_si_clk_ff[1];
|
||||||
end
|
end
|
||||||
|
|
||||||
logic cic_dq_out;
|
logic cic_dq_out;
|
||||||
|
logic cic_dq_oe;
|
||||||
|
|
||||||
assign n64_cic_dq = cic_dq_out ? 1'bZ : 1'b0;
|
always_ff @(posedge clk) begin
|
||||||
|
cic_dq_oe <= ~cic_dq_out;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign n64_cic_dq = cic_dq_oe ? 1'b0 : 1'bZ;
|
||||||
|
|
||||||
|
|
||||||
|
// Timer (divider and counter)
|
||||||
|
|
||||||
|
logic last_si_clk;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
last_si_clk <= si_clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic si_clk_rising_edge;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
si_clk_rising_edge = cic_reset && !last_si_clk && si_clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
logic [7:0] timer_divider;
|
||||||
|
logic [11:0] timer_counter;
|
||||||
|
logic timer_start;
|
||||||
|
logic timer_clear;
|
||||||
|
logic timer_elapsed;
|
||||||
|
|
||||||
|
const bit [11:0] TIMEOUT_500MS = 12'd3815; // (62_500_000 / 32 / 256 / 2) = ~500 ms
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (si_clk_rising_edge) begin
|
||||||
|
timer_divider <= timer_divider + 1'd1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (si_clk_rising_edge && (&timer_divider) && (timer_counter > 12'd0)) begin
|
||||||
|
timer_counter <= timer_counter - 1'd1;
|
||||||
|
if (timer_counter == 12'd1) begin
|
||||||
|
timer_elapsed <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (timer_start) begin
|
||||||
|
timer_divider <= 8'd0;
|
||||||
|
timer_counter <= TIMEOUT_500MS;
|
||||||
|
timer_elapsed <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (timer_clear) begin
|
||||||
|
timer_divider <= 8'd0;
|
||||||
|
timer_counter <= 12'd0;
|
||||||
|
timer_elapsed <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// SERV RISC-V CPU
|
// SERV RISC-V CPU
|
||||||
@ -98,7 +156,6 @@ module n64_cic (
|
|||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
ram_output <= ram[ram_addr];
|
ram_output <= ram[ram_addr];
|
||||||
|
|
||||||
ibus_ack <= ibus_cycle && !ibus_ack;
|
ibus_ack <= ibus_cycle && !ibus_ack;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -110,6 +167,8 @@ module n64_cic (
|
|||||||
// Bus controller
|
// Bus controller
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
|
timer_start <= 1'b0;
|
||||||
|
timer_clear <= 1'b0;
|
||||||
n64_scb.cic_invalid_region <= 1'b0;
|
n64_scb.cic_invalid_region <= 1'b0;
|
||||||
|
|
||||||
dbus_ack <= dbus_cycle && !dbus_ack;
|
dbus_ack <= dbus_cycle && !dbus_ack;
|
||||||
@ -126,14 +185,24 @@ module n64_cic (
|
|||||||
2'b11: begin
|
2'b11: begin
|
||||||
case (dbus_addr[3:2])
|
case (dbus_addr[3:2])
|
||||||
2'b10: begin
|
2'b10: begin
|
||||||
n64_scb.cic_invalid_region <= dbus_wdata[3];
|
n64_scb.cic_invalid_region <= dbus_wdata[6];
|
||||||
|
timer_clear <= dbus_wdata[5];
|
||||||
|
timer_start <= dbus_wdata[4];
|
||||||
cic_dq_out <= dbus_wdata[0];
|
cic_dq_out <= dbus_wdata[0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
2'b11: begin
|
||||||
|
n64_scb.cic_debug_step <= dbus_wdata[3:0];
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (reset) begin
|
||||||
|
n64_scb.cic_debug_step <= 3'd0;
|
||||||
|
end
|
||||||
|
|
||||||
if (reset || !cic_reset) begin
|
if (reset || !cic_reset) begin
|
||||||
cic_dq_out <= 1'b1;
|
cic_dq_out <= 1'b1;
|
||||||
end
|
end
|
||||||
@ -159,7 +228,15 @@ module n64_cic (
|
|||||||
|
|
||||||
2'b01: dbus_rdata = n64_scb.cic_checksum[31:0];
|
2'b01: dbus_rdata = n64_scb.cic_checksum[31:0];
|
||||||
|
|
||||||
2'b10: dbus_rdata = {29'd0, cic_reset, cic_clk, cic_dq};
|
2'b10: dbus_rdata = {
|
||||||
|
28'd0,
|
||||||
|
timer_elapsed,
|
||||||
|
cic_reset,
|
||||||
|
cic_clk,
|
||||||
|
cic_dq
|
||||||
|
};
|
||||||
|
|
||||||
|
2'b11: dbus_rdata = {28'd0, n64_scb.cic_debug_step};
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
@ -8,7 +8,7 @@ module n64_flashram (
|
|||||||
);
|
);
|
||||||
|
|
||||||
localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001;
|
localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001;
|
||||||
localparam [31:0] FLASH_MODEL_ID = 32'h00C2_001D;
|
localparam [31:0] FLASH_MODEL_ID = 32'h0032_00F1;
|
||||||
|
|
||||||
typedef enum bit [7:0] {
|
typedef enum bit [7:0] {
|
||||||
CMD_STATUS_MODE = 8'hD2,
|
CMD_STATUS_MODE = 8'hD2,
|
||||||
@ -97,14 +97,14 @@ module n64_flashram (
|
|||||||
CMD_ERASE_SECTOR: begin
|
CMD_ERASE_SECTOR: begin
|
||||||
state <= STATE_STATUS;
|
state <= STATE_STATUS;
|
||||||
erase_enabled <= 1'b1;
|
erase_enabled <= 1'b1;
|
||||||
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
|
n64_scb.flashram_page <= reg_bus.wdata[9:0];
|
||||||
n64_scb.flashram_sector_or_all <= 1'b0;
|
n64_scb.flashram_sector_or_all <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
CMD_ERASE_CHIP: begin
|
CMD_ERASE_CHIP: begin
|
||||||
state <= STATE_STATUS;
|
state <= STATE_STATUS;
|
||||||
erase_enabled <= 1'b1;
|
erase_enabled <= 1'b1;
|
||||||
n64_scb.flashram_sector <= 10'd0;
|
n64_scb.flashram_page <= 10'd0;
|
||||||
n64_scb.flashram_sector_or_all <= 1'b1;
|
n64_scb.flashram_sector_or_all <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ module n64_flashram (
|
|||||||
state <= STATE_STATUS;
|
state <= STATE_STATUS;
|
||||||
status[WRITE_BUSY] <= 1'b1;
|
status[WRITE_BUSY] <= 1'b1;
|
||||||
status[WRITE_DONE] <= 1'b0;
|
status[WRITE_DONE] <= 1'b0;
|
||||||
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
|
n64_scb.flashram_page <= reg_bus.wdata[9:0];
|
||||||
n64_scb.flashram_pending <= 1'b1;
|
n64_scb.flashram_pending <= 1'b1;
|
||||||
n64_scb.flashram_write_or_erase <= 1'b0;
|
n64_scb.flashram_write_or_erase <= 1'b0;
|
||||||
n64_scb.flashram_sector_or_all <= 1'b0;
|
n64_scb.flashram_sector_or_all <= 1'b0;
|
||||||
@ -134,9 +134,9 @@ module n64_flashram (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (reg_bus.address[1] && state != STATE_BUFFER) begin
|
if (reg_bus.address[1] && state == STATE_STATUS) begin
|
||||||
status[ERASE_BUSY] <= reg_bus.wdata[ERASE_BUSY];
|
status[ERASE_DONE] <= 1'b0;
|
||||||
status[WRITE_BUSY] <= reg_bus.wdata[WRITE_BUSY];
|
status[WRITE_DONE] <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -127,12 +127,21 @@ module n64_pi (
|
|||||||
|
|
||||||
// Debug: last accessed PI address
|
// Debug: last accessed PI address
|
||||||
|
|
||||||
|
logic [15:0] pi_debug_address_buffer;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (aleh_op) begin
|
if (aleh_op) begin
|
||||||
n64_scb.pi_debug[31:16] <= n64_pi_dq_in;
|
pi_debug_address_buffer <= n64_pi_dq_in;
|
||||||
end
|
end
|
||||||
if (alel_op) begin
|
if (alel_op) begin
|
||||||
n64_scb.pi_debug[15:0] <= n64_pi_dq_in;
|
n64_scb.pi_debug_address <= {pi_debug_address_buffer, n64_pi_dq_in};
|
||||||
|
n64_scb.pi_debug_rw_count <= 17'd0;
|
||||||
|
end
|
||||||
|
if (pi_reset && (pi_mode == PI_MODE_VALID)) begin
|
||||||
|
if ((last_read && !pi_read) || (last_write && !pi_write)) begin
|
||||||
|
n64_scb.pi_debug_rw_count <= n64_scb.pi_debug_rw_count + 1'd1;
|
||||||
|
n64_scb.pi_debug_direction <= !pi_write;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -296,11 +305,11 @@ module n64_pi (
|
|||||||
.reset(reset),
|
.reset(reset),
|
||||||
|
|
||||||
.flush(reset || !pi_reset || alel_op),
|
.flush(reset || !pi_reset || alel_op),
|
||||||
|
|
||||||
.full(read_fifo_full),
|
.full(read_fifo_full),
|
||||||
.write(read_fifo_write),
|
.write(read_fifo_write),
|
||||||
.wdata(read_fifo_wdata),
|
.wdata(read_fifo_wdata),
|
||||||
|
|
||||||
.empty(read_fifo_empty),
|
.empty(read_fifo_empty),
|
||||||
.read(read_fifo_read),
|
.read(read_fifo_read),
|
||||||
.rdata(read_fifo_rdata)
|
.rdata(read_fifo_rdata)
|
||||||
@ -310,7 +319,7 @@ module n64_pi (
|
|||||||
read_fifo_read <= 1'b0;
|
read_fifo_read <= 1'b0;
|
||||||
|
|
||||||
if (!pi_reset) begin
|
if (!pi_reset) begin
|
||||||
n64_scb.pi_debug[33:32] <= 2'b00;
|
n64_scb.pi_debug_fifo_flags[1:0] <= 2'b00;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (reset || !pi_reset || alel_op) begin
|
if (reset || !pi_reset || alel_op) begin
|
||||||
@ -321,9 +330,9 @@ module n64_pi (
|
|||||||
if (read_op) begin
|
if (read_op) begin
|
||||||
if (read_fifo_empty) begin
|
if (read_fifo_empty) begin
|
||||||
read_fifo_wait <= 1'b1;
|
read_fifo_wait <= 1'b1;
|
||||||
n64_scb.pi_debug[32] <= 1'b1;
|
n64_scb.pi_debug_fifo_flags[0] <= 1'b1;
|
||||||
if (read_fifo_wait) begin
|
if (read_fifo_wait) begin
|
||||||
n64_scb.pi_debug[33] <= 1'b1;
|
n64_scb.pi_debug_fifo_flags[1] <= 1'b1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
read_fifo_read <= 1'b1;
|
read_fifo_read <= 1'b1;
|
||||||
@ -377,7 +386,7 @@ module n64_pi (
|
|||||||
write_fifo_write <= 1'b0;
|
write_fifo_write <= 1'b0;
|
||||||
|
|
||||||
if (!pi_reset) begin
|
if (!pi_reset) begin
|
||||||
n64_scb.pi_debug[35:34] <= 2'b00;
|
n64_scb.pi_debug_fifo_flags[3:2] <= 2'b00;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
@ -388,9 +397,9 @@ module n64_pi (
|
|||||||
if (write_op) begin
|
if (write_op) begin
|
||||||
if (write_fifo_full) begin
|
if (write_fifo_full) begin
|
||||||
write_fifo_wait <= 1'b1;
|
write_fifo_wait <= 1'b1;
|
||||||
n64_scb.pi_debug[34] <= 1'b1;
|
n64_scb.pi_debug_fifo_flags[2] <= 1'b1;
|
||||||
if (write_fifo_wait) begin
|
if (write_fifo_wait) begin
|
||||||
n64_scb.pi_debug[35] <= 1'b1;
|
n64_scb.pi_debug_fifo_flags[3] <= 1'b1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
write_fifo_write <= 1'b1;
|
write_fifo_write <= 1'b1;
|
||||||
@ -476,7 +485,11 @@ module n64_pi (
|
|||||||
|
|
||||||
// Reg bus controller
|
// Reg bus controller
|
||||||
|
|
||||||
|
logic reg_bus_address_increment;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
|
reg_bus_address_increment <= read_op || write_op;
|
||||||
|
|
||||||
if (aleh_op) begin
|
if (aleh_op) begin
|
||||||
reg_bus.address[16] <= n64_pi_dq_in[0];
|
reg_bus.address[16] <= n64_pi_dq_in[0];
|
||||||
end
|
end
|
||||||
@ -485,15 +498,13 @@ module n64_pi (
|
|||||||
reg_bus.address[15:0] <= n64_pi_dq_in;
|
reg_bus.address[15:0] <= n64_pi_dq_in;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (read_op || write_op) begin
|
if (reg_bus_address_increment) begin
|
||||||
reg_bus.address <= reg_bus.address + 2'd2;
|
reg_bus.address <= reg_bus.address + 2'd2;
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
always_comb begin
|
reg_bus.read <= read_op && (read_port == PORT_REG);
|
||||||
reg_bus.read = read_op && (read_port == PORT_REG);
|
reg_bus.write <= write_op && (write_port == PORT_REG);
|
||||||
reg_bus.write = write_op && (write_port == PORT_REG);
|
reg_bus.wdata <= n64_pi_dq_in;
|
||||||
reg_bus.wdata = n64_pi_dq_in;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -22,7 +22,7 @@ interface n64_scb ();
|
|||||||
|
|
||||||
logic flashram_pending;
|
logic flashram_pending;
|
||||||
logic flashram_done;
|
logic flashram_done;
|
||||||
logic [9:0] flashram_sector;
|
logic [9:0] flashram_page;
|
||||||
logic flashram_sector_or_all;
|
logic flashram_sector_or_all;
|
||||||
logic flashram_write_or_erase;
|
logic flashram_write_or_erase;
|
||||||
logic flashram_read_mode;
|
logic flashram_read_mode;
|
||||||
@ -40,19 +40,26 @@ interface n64_scb ();
|
|||||||
logic rtc_pending;
|
logic rtc_pending;
|
||||||
logic rtc_done;
|
logic rtc_done;
|
||||||
logic rtc_wdata_valid;
|
logic rtc_wdata_valid;
|
||||||
logic [41:0] rtc_rdata;
|
logic [42:0] rtc_rdata;
|
||||||
logic [41:0] rtc_wdata;
|
logic [42:0] rtc_wdata;
|
||||||
|
|
||||||
logic cfg_unlock;
|
logic cfg_unlock;
|
||||||
logic cfg_pending;
|
logic cfg_pending;
|
||||||
logic cfg_done;
|
logic cfg_done;
|
||||||
logic cfg_error;
|
logic cfg_error;
|
||||||
logic cfg_irq;
|
|
||||||
logic [7:0] cfg_cmd;
|
logic [7:0] cfg_cmd;
|
||||||
logic [31:0] cfg_rdata [0:1];
|
logic [31:0] cfg_rdata [0:1];
|
||||||
logic [31:0] cfg_wdata [0:1];
|
logic [31:0] cfg_wdata [0:1];
|
||||||
logic [31:0] cfg_identifier;
|
logic [31:0] cfg_identifier;
|
||||||
|
|
||||||
|
logic btn_irq;
|
||||||
|
logic usb_irq;
|
||||||
|
logic aux_irq;
|
||||||
|
|
||||||
|
logic aux_pending;
|
||||||
|
logic [31:0] aux_rdata;
|
||||||
|
logic [31:0] aux_wdata;
|
||||||
|
|
||||||
logic [15:0] save_count;
|
logic [15:0] save_count;
|
||||||
|
|
||||||
logic cic_invalid_region;
|
logic cic_invalid_region;
|
||||||
@ -61,10 +68,14 @@ interface n64_scb ();
|
|||||||
logic cic_region;
|
logic cic_region;
|
||||||
logic [7:0] cic_seed;
|
logic [7:0] cic_seed;
|
||||||
logic [47:0] cic_checksum;
|
logic [47:0] cic_checksum;
|
||||||
|
logic [3:0] cic_debug_step;
|
||||||
|
|
||||||
logic pi_sdram_active;
|
logic pi_sdram_active;
|
||||||
logic pi_flash_active;
|
logic pi_flash_active;
|
||||||
logic [35:0] pi_debug;
|
logic [31:0] pi_debug_address;
|
||||||
|
logic [16:0] pi_debug_rw_count;
|
||||||
|
logic pi_debug_direction;
|
||||||
|
logic [3:0] pi_debug_fifo_flags;
|
||||||
|
|
||||||
modport controller (
|
modport controller (
|
||||||
input n64_reset,
|
input n64_reset,
|
||||||
@ -84,7 +95,7 @@ interface n64_scb ();
|
|||||||
|
|
||||||
input flashram_pending,
|
input flashram_pending,
|
||||||
output flashram_done,
|
output flashram_done,
|
||||||
input flashram_sector,
|
input flashram_page,
|
||||||
input flashram_sector_or_all,
|
input flashram_sector_or_all,
|
||||||
input flashram_write_or_erase,
|
input flashram_write_or_erase,
|
||||||
|
|
||||||
@ -97,12 +108,19 @@ interface n64_scb ();
|
|||||||
input cfg_pending,
|
input cfg_pending,
|
||||||
output cfg_done,
|
output cfg_done,
|
||||||
output cfg_error,
|
output cfg_error,
|
||||||
output cfg_irq,
|
|
||||||
input cfg_cmd,
|
input cfg_cmd,
|
||||||
input cfg_rdata,
|
input cfg_rdata,
|
||||||
output cfg_wdata,
|
output cfg_wdata,
|
||||||
output cfg_identifier,
|
output cfg_identifier,
|
||||||
|
|
||||||
|
output btn_irq,
|
||||||
|
output usb_irq,
|
||||||
|
output aux_irq,
|
||||||
|
|
||||||
|
input aux_pending,
|
||||||
|
input aux_rdata,
|
||||||
|
output aux_wdata,
|
||||||
|
|
||||||
input save_count,
|
input save_count,
|
||||||
|
|
||||||
input cic_invalid_region,
|
input cic_invalid_region,
|
||||||
@ -111,8 +129,12 @@ interface n64_scb ();
|
|||||||
output cic_region,
|
output cic_region,
|
||||||
output cic_seed,
|
output cic_seed,
|
||||||
output cic_checksum,
|
output cic_checksum,
|
||||||
|
input cic_debug_step,
|
||||||
|
|
||||||
input pi_debug
|
input pi_debug_address,
|
||||||
|
input pi_debug_rw_count,
|
||||||
|
input pi_debug_direction,
|
||||||
|
input pi_debug_fifo_flags
|
||||||
);
|
);
|
||||||
|
|
||||||
modport pi (
|
modport pi (
|
||||||
@ -137,13 +159,17 @@ interface n64_scb ();
|
|||||||
|
|
||||||
output pi_sdram_active,
|
output pi_sdram_active,
|
||||||
output pi_flash_active,
|
output pi_flash_active,
|
||||||
output pi_debug
|
|
||||||
|
output pi_debug_address,
|
||||||
|
output pi_debug_rw_count,
|
||||||
|
output pi_debug_direction,
|
||||||
|
output pi_debug_fifo_flags
|
||||||
);
|
);
|
||||||
|
|
||||||
modport flashram (
|
modport flashram (
|
||||||
output flashram_pending,
|
output flashram_pending,
|
||||||
input flashram_done,
|
input flashram_done,
|
||||||
output flashram_sector,
|
output flashram_page,
|
||||||
output flashram_sector_or_all,
|
output flashram_sector_or_all,
|
||||||
output flashram_write_or_erase,
|
output flashram_write_or_erase,
|
||||||
|
|
||||||
@ -204,11 +230,18 @@ interface n64_scb ();
|
|||||||
output cfg_pending,
|
output cfg_pending,
|
||||||
input cfg_done,
|
input cfg_done,
|
||||||
input cfg_error,
|
input cfg_error,
|
||||||
input cfg_irq,
|
|
||||||
output cfg_cmd,
|
output cfg_cmd,
|
||||||
output cfg_rdata,
|
output cfg_rdata,
|
||||||
input cfg_wdata,
|
input cfg_wdata,
|
||||||
input cfg_identifier
|
input cfg_identifier,
|
||||||
|
|
||||||
|
input btn_irq,
|
||||||
|
input usb_irq,
|
||||||
|
input aux_irq,
|
||||||
|
|
||||||
|
output aux_pending,
|
||||||
|
output aux_rdata,
|
||||||
|
input aux_wdata
|
||||||
);
|
);
|
||||||
|
|
||||||
modport save_counter (
|
modport save_counter (
|
||||||
@ -225,7 +258,8 @@ interface n64_scb ();
|
|||||||
input cic_64dd_mode,
|
input cic_64dd_mode,
|
||||||
input cic_region,
|
input cic_region,
|
||||||
input cic_seed,
|
input cic_seed,
|
||||||
input cic_checksum
|
input cic_checksum,
|
||||||
|
output cic_debug_step
|
||||||
);
|
);
|
||||||
|
|
||||||
modport arbiter (
|
modport arbiter (
|
||||||
|
@ -59,6 +59,7 @@ module n64_si (
|
|||||||
// Data falling/rising event generator
|
// Data falling/rising event generator
|
||||||
|
|
||||||
logic last_si_dq_in;
|
logic last_si_dq_in;
|
||||||
|
logic si_dq_in_inhibit;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (si_clk_rising_edge) begin
|
if (si_clk_rising_edge) begin
|
||||||
@ -70,14 +71,14 @@ module n64_si (
|
|||||||
logic si_dq_rising_edge;
|
logic si_dq_rising_edge;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
si_dq_falling_edge = si_clk_rising_edge && last_si_dq_in && !si_dq_in;
|
si_dq_falling_edge = si_clk_rising_edge && last_si_dq_in && !si_dq_in && !si_dq_in_inhibit;
|
||||||
si_dq_rising_edge = si_clk_rising_edge && !last_si_dq_in && si_dq_in;
|
si_dq_rising_edge = si_clk_rising_edge && !last_si_dq_in && si_dq_in && !si_dq_in_inhibit;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// RX bit generator
|
// RX bit generator
|
||||||
|
|
||||||
logic [3:0] rx_sub_bit_counter;
|
logic [4:0] rx_sub_bit_counter;
|
||||||
logic rx_timeout;
|
logic rx_timeout;
|
||||||
logic rx_bit_valid;
|
logic rx_bit_valid;
|
||||||
logic rx_bit_data;
|
logic rx_bit_data;
|
||||||
@ -94,7 +95,7 @@ module n64_si (
|
|||||||
always_comb begin
|
always_comb begin
|
||||||
rx_timeout = si_clk_rising_edge && si_dq_in && (&rx_sub_bit_counter);
|
rx_timeout = si_clk_rising_edge && si_dq_in && (&rx_sub_bit_counter);
|
||||||
rx_bit_valid = si_dq_rising_edge;
|
rx_bit_valid = si_dq_rising_edge;
|
||||||
rx_bit_data = (rx_sub_bit_counter >= 4'd3) ? 1'b0 : 1'b1;
|
rx_bit_data = (rx_sub_bit_counter >= 5'd4) ? 1'b0 : 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ module n64_si (
|
|||||||
logic rx_stop;
|
logic rx_stop;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
rx_stop = si_clk_rising_edge && si_dq_in && (rx_sub_bit_counter == 4'd7) && (rx_bit_counter == 3'd1);
|
rx_stop = si_clk_rising_edge && si_dq_in && (rx_sub_bit_counter == 5'd15) && (rx_bit_counter == 3'd1);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -260,7 +261,8 @@ module n64_si (
|
|||||||
typedef enum bit [1:0] {
|
typedef enum bit [1:0] {
|
||||||
TX_STATE_IDLE,
|
TX_STATE_IDLE,
|
||||||
TX_STATE_DATA,
|
TX_STATE_DATA,
|
||||||
TX_STATE_STOP
|
TX_STATE_STOP,
|
||||||
|
TX_STATE_STOP_WAIT
|
||||||
} e_tx_state;
|
} e_tx_state;
|
||||||
|
|
||||||
e_tx_state tx_state;
|
e_tx_state tx_state;
|
||||||
@ -278,12 +280,14 @@ module n64_si (
|
|||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
tx_state <= TX_STATE_IDLE;
|
tx_state <= TX_STATE_IDLE;
|
||||||
|
si_dq_in_inhibit <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
case (tx_state)
|
case (tx_state)
|
||||||
TX_STATE_IDLE: begin
|
TX_STATE_IDLE: begin
|
||||||
if (tx_start) begin
|
if (tx_start) begin
|
||||||
tx_byte_counter <= 4'd0;
|
tx_byte_counter <= 4'd0;
|
||||||
tx_state <= TX_STATE_DATA;
|
tx_state <= TX_STATE_DATA;
|
||||||
|
si_dq_in_inhibit <= 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -299,7 +303,14 @@ module n64_si (
|
|||||||
TX_STATE_STOP: begin
|
TX_STATE_STOP: begin
|
||||||
tx_stop <= 1'b1;
|
tx_stop <= 1'b1;
|
||||||
if (!tx_busy && tx_stop) begin
|
if (!tx_busy && tx_stop) begin
|
||||||
|
tx_state <= TX_STATE_STOP_WAIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TX_STATE_STOP_WAIT: begin
|
||||||
|
if (!tx_busy) begin
|
||||||
tx_state <= TX_STATE_IDLE;
|
tx_state <= TX_STATE_IDLE;
|
||||||
|
si_dq_in_inhibit <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
@ -351,6 +362,7 @@ module n64_si (
|
|||||||
logic [2:0] rtc_time_weekday;
|
logic [2:0] rtc_time_weekday;
|
||||||
logic [4:0] rtc_time_month;
|
logic [4:0] rtc_time_month;
|
||||||
logic [7:0] rtc_time_year;
|
logic [7:0] rtc_time_year;
|
||||||
|
logic rtc_time_century;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
@ -366,6 +378,7 @@ module n64_si (
|
|||||||
|
|
||||||
if (!(|rtc_stopped) && !n64_scb.rtc_pending && n64_scb.rtc_wdata_valid && (tx_state != TX_STATE_DATA)) begin
|
if (!(|rtc_stopped) && !n64_scb.rtc_pending && n64_scb.rtc_wdata_valid && (tx_state != TX_STATE_DATA)) begin
|
||||||
{
|
{
|
||||||
|
rtc_time_century,
|
||||||
rtc_time_year,
|
rtc_time_year,
|
||||||
rtc_time_month,
|
rtc_time_month,
|
||||||
rtc_time_weekday,
|
rtc_time_weekday,
|
||||||
@ -382,7 +395,7 @@ module n64_si (
|
|||||||
4'd1: {rtc_time_wp, rtc_backup_wp} <= rx_byte_data[1:0];
|
4'd1: {rtc_time_wp, rtc_backup_wp} <= rx_byte_data[1:0];
|
||||||
4'd2: begin
|
4'd2: begin
|
||||||
rtc_stopped <= rx_byte_data[2:1];
|
rtc_stopped <= rx_byte_data[2:1];
|
||||||
if (rx_byte_data[2:1] == 2'b00) begin
|
if ((|rtc_stopped) && (rx_byte_data[2:1] == 2'b00)) begin
|
||||||
n64_scb.rtc_pending <= 1'b1;
|
n64_scb.rtc_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -397,6 +410,7 @@ module n64_si (
|
|||||||
4'd5: rtc_time_weekday <= rx_byte_data[2:0];
|
4'd5: rtc_time_weekday <= rx_byte_data[2:0];
|
||||||
4'd6: rtc_time_month <= rx_byte_data[4:0];
|
4'd6: rtc_time_month <= rx_byte_data[4:0];
|
||||||
4'd7: rtc_time_year <= rx_byte_data;
|
4'd7: rtc_time_year <= rx_byte_data;
|
||||||
|
4'd8: rtc_time_century <= rx_byte_data[0];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -404,6 +418,7 @@ module n64_si (
|
|||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
n64_scb.rtc_rdata = {
|
n64_scb.rtc_rdata = {
|
||||||
|
rtc_time_century,
|
||||||
rtc_time_year,
|
rtc_time_year,
|
||||||
rtc_time_month,
|
rtc_time_month,
|
||||||
rtc_time_weekday,
|
rtc_time_weekday,
|
||||||
@ -458,7 +473,7 @@ module n64_si (
|
|||||||
4'd4: tx_byte_data = {5'd0, rtc_time_weekday};
|
4'd4: tx_byte_data = {5'd0, rtc_time_weekday};
|
||||||
4'd5: tx_byte_data = {3'd0, rtc_time_month};
|
4'd5: tx_byte_data = {3'd0, rtc_time_month};
|
||||||
4'd6: tx_byte_data = rtc_time_year;
|
4'd6: tx_byte_data = rtc_time_year;
|
||||||
4'd7: tx_byte_data = 8'h01;
|
4'd7: tx_byte_data = {7'd0, rtc_time_century};
|
||||||
4'd8: tx_byte_data = {(|rtc_stopped), 7'd0};
|
4'd8: tx_byte_data = {(|rtc_stopped), 7'd0};
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -26,13 +26,19 @@ module n64_top (
|
|||||||
|
|
||||||
logic n64_dd_irq;
|
logic n64_dd_irq;
|
||||||
logic n64_cfg_irq;
|
logic n64_cfg_irq;
|
||||||
logic n64_irq_oe;
|
|
||||||
|
logic irq_data;
|
||||||
|
logic irq_dq;
|
||||||
|
logic [1:0] irq_oe;
|
||||||
|
|
||||||
|
assign irq_data = (n64_dd_irq || n64_cfg_irq);
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
n64_irq_oe <= (n64_dd_irq || n64_cfg_irq);
|
irq_dq <= (~irq_data);
|
||||||
|
irq_oe <= {irq_oe[0], irq_data};
|
||||||
end
|
end
|
||||||
|
|
||||||
assign n64_irq = n64_irq_oe ? 1'b0 : 1'bZ;
|
assign n64_irq = irq_oe[1] ? irq_dq : 1'bZ;
|
||||||
|
|
||||||
n64_reg_bus reg_bus ();
|
n64_reg_bus reg_bus ();
|
||||||
|
|
||||||
@ -112,7 +118,8 @@ module n64_top (
|
|||||||
|
|
||||||
.n64_reset(n64_reset),
|
.n64_reset(n64_reset),
|
||||||
.n64_cic_clk(n64_cic_clk),
|
.n64_cic_clk(n64_cic_clk),
|
||||||
.n64_cic_dq(n64_cic_dq)
|
.n64_cic_dq(n64_cic_dq),
|
||||||
|
.n64_si_clk(n64_si_clk)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -36,12 +36,10 @@ module sd_dat (
|
|||||||
// FIFO
|
// FIFO
|
||||||
|
|
||||||
logic rx_full;
|
logic rx_full;
|
||||||
logic rx_almost_full;
|
|
||||||
logic rx_write;
|
logic rx_write;
|
||||||
logic [7:0] rx_wdata;
|
logic [7:0] rx_wdata;
|
||||||
|
|
||||||
logic tx_empty;
|
logic tx_empty;
|
||||||
logic tx_almost_empty;
|
|
||||||
logic tx_read;
|
logic tx_read;
|
||||||
logic [7:0] tx_rdata;
|
logic [7:0] tx_rdata;
|
||||||
|
|
||||||
@ -50,12 +48,10 @@ module sd_dat (
|
|||||||
.reset(reset || sd_scb.dat_fifo_flush),
|
.reset(reset || sd_scb.dat_fifo_flush),
|
||||||
|
|
||||||
.empty(fifo_bus.rx_empty),
|
.empty(fifo_bus.rx_empty),
|
||||||
.almost_empty(fifo_bus.rx_almost_empty),
|
|
||||||
.read(fifo_bus.rx_read),
|
.read(fifo_bus.rx_read),
|
||||||
.rdata(fifo_bus.rx_rdata),
|
.rdata(fifo_bus.rx_rdata),
|
||||||
|
|
||||||
.full(rx_full),
|
.full(rx_full),
|
||||||
.almost_full(rx_almost_full),
|
|
||||||
.write(rx_write),
|
.write(rx_write),
|
||||||
.wdata(rx_wdata),
|
.wdata(rx_wdata),
|
||||||
|
|
||||||
@ -67,12 +63,10 @@ module sd_dat (
|
|||||||
.reset(reset || sd_scb.dat_fifo_flush),
|
.reset(reset || sd_scb.dat_fifo_flush),
|
||||||
|
|
||||||
.empty(tx_empty),
|
.empty(tx_empty),
|
||||||
.almost_empty(tx_almost_empty),
|
|
||||||
.read(tx_read),
|
.read(tx_read),
|
||||||
.rdata(tx_rdata),
|
.rdata(tx_rdata),
|
||||||
|
|
||||||
.full(fifo_bus.tx_full),
|
.full(fifo_bus.tx_full),
|
||||||
.almost_full(fifo_bus.tx_almost_full),
|
|
||||||
.write(fifo_bus.tx_write),
|
.write(fifo_bus.tx_write),
|
||||||
.wdata(fifo_bus.tx_wdata),
|
.wdata(fifo_bus.tx_wdata),
|
||||||
|
|
||||||
|
@ -51,7 +51,10 @@ module top (
|
|||||||
output mcu_miso,
|
output mcu_miso,
|
||||||
|
|
||||||
// Unused I/O
|
// Unused I/O
|
||||||
output n64_video_sync
|
|
||||||
|
output n64_video_sync,
|
||||||
|
|
||||||
|
output [2:0] test_point
|
||||||
);
|
);
|
||||||
|
|
||||||
logic clk;
|
logic clk;
|
||||||
@ -278,4 +281,6 @@ module top (
|
|||||||
|
|
||||||
assign n64_video_sync = 1'bZ;
|
assign n64_video_sync = 1'bZ;
|
||||||
|
|
||||||
|
assign test_point = 3'b000;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,39 +1,3 @@
|
|||||||
interface usb_scb ();
|
|
||||||
|
|
||||||
logic fifo_flush;
|
|
||||||
logic reset_pending;
|
|
||||||
logic reset_ack;
|
|
||||||
logic write_buffer_flush;
|
|
||||||
logic [10:0] rx_count;
|
|
||||||
logic [10:0] tx_count;
|
|
||||||
logic pwrsav;
|
|
||||||
logic reset_state;
|
|
||||||
|
|
||||||
modport controller (
|
|
||||||
output fifo_flush,
|
|
||||||
input reset_pending,
|
|
||||||
output reset_ack,
|
|
||||||
output write_buffer_flush,
|
|
||||||
input rx_count,
|
|
||||||
input tx_count,
|
|
||||||
input pwrsav,
|
|
||||||
input reset_state
|
|
||||||
);
|
|
||||||
|
|
||||||
modport usb (
|
|
||||||
input fifo_flush,
|
|
||||||
output reset_pending,
|
|
||||||
input reset_ack,
|
|
||||||
input write_buffer_flush,
|
|
||||||
output rx_count,
|
|
||||||
output tx_count,
|
|
||||||
output pwrsav,
|
|
||||||
output reset_state
|
|
||||||
);
|
|
||||||
|
|
||||||
endinterface
|
|
||||||
|
|
||||||
|
|
||||||
module usb_ft1248 (
|
module usb_ft1248 (
|
||||||
input clk,
|
input clk,
|
||||||
input reset,
|
input reset,
|
||||||
@ -50,27 +14,25 @@ module usb_ft1248 (
|
|||||||
);
|
);
|
||||||
|
|
||||||
logic rx_full;
|
logic rx_full;
|
||||||
logic rx_almost_full;
|
logic rx_write_delayed;
|
||||||
logic rx_write;
|
|
||||||
logic [7:0] rx_wdata;
|
logic [7:0] rx_wdata;
|
||||||
|
|
||||||
logic tx_empty;
|
logic tx_empty;
|
||||||
logic tx_almost_empty;
|
|
||||||
logic tx_read;
|
logic tx_read;
|
||||||
logic [7:0] tx_rdata;
|
logic [7:0] tx_rdata;
|
||||||
|
|
||||||
|
logic fifo_flush;
|
||||||
|
|
||||||
fifo_8kb fifo_8kb_rx_inst (
|
fifo_8kb fifo_8kb_rx_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset(reset || usb_scb.fifo_flush),
|
.reset(fifo_flush),
|
||||||
|
|
||||||
.empty(fifo_bus.rx_empty),
|
.empty(fifo_bus.rx_empty),
|
||||||
.almost_empty(fifo_bus.rx_almost_empty),
|
|
||||||
.read(fifo_bus.rx_read),
|
.read(fifo_bus.rx_read),
|
||||||
.rdata(fifo_bus.rx_rdata),
|
.rdata(fifo_bus.rx_rdata),
|
||||||
|
|
||||||
.full(rx_full),
|
.full(rx_full),
|
||||||
.almost_full(rx_almost_full),
|
.write(rx_write_delayed),
|
||||||
.write(rx_write),
|
|
||||||
.wdata(rx_wdata),
|
.wdata(rx_wdata),
|
||||||
|
|
||||||
.count(usb_scb.rx_count)
|
.count(usb_scb.rx_count)
|
||||||
@ -78,15 +40,13 @@ module usb_ft1248 (
|
|||||||
|
|
||||||
fifo_8kb fifo_8kb_tx_inst (
|
fifo_8kb fifo_8kb_tx_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.reset(reset || usb_scb.fifo_flush),
|
.reset(fifo_flush),
|
||||||
|
|
||||||
.empty(tx_empty),
|
.empty(tx_empty),
|
||||||
.almost_empty(tx_almost_empty),
|
|
||||||
.read(tx_read),
|
.read(tx_read),
|
||||||
.rdata(tx_rdata),
|
.rdata(tx_rdata),
|
||||||
|
|
||||||
.full(fifo_bus.tx_full),
|
.full(fifo_bus.tx_full),
|
||||||
.almost_full(fifo_bus.tx_almost_full),
|
|
||||||
.write(fifo_bus.tx_write),
|
.write(fifo_bus.tx_write),
|
||||||
.wdata(fifo_bus.tx_wdata),
|
.wdata(fifo_bus.tx_wdata),
|
||||||
|
|
||||||
@ -140,9 +100,10 @@ module usb_ft1248 (
|
|||||||
e_cmd cmd;
|
e_cmd cmd;
|
||||||
e_cmd next_cmd;
|
e_cmd next_cmd;
|
||||||
logic [3:0] phase;
|
logic [3:0] phase;
|
||||||
|
logic rx_write;
|
||||||
|
logic last_rx_failed;
|
||||||
logic last_tx_failed;
|
logic last_tx_failed;
|
||||||
logic reset_reply;
|
logic reset_reply;
|
||||||
logic last_reset_status;
|
|
||||||
logic [4:0] modem_status_counter;
|
logic [4:0] modem_status_counter;
|
||||||
logic write_modem_status_pending;
|
logic write_modem_status_pending;
|
||||||
logic write_buffer_flush_pending;
|
logic write_buffer_flush_pending;
|
||||||
@ -152,7 +113,9 @@ module usb_ft1248 (
|
|||||||
cmd <= next_cmd;
|
cmd <= next_cmd;
|
||||||
|
|
||||||
usb_scb.pwrsav <= !ft_pwrsav;
|
usb_scb.pwrsav <= !ft_pwrsav;
|
||||||
usb_scb.reset_state <= last_reset_status;
|
fifo_flush <= 1'b0;
|
||||||
|
|
||||||
|
rx_write_delayed <= rx_write;
|
||||||
|
|
||||||
phase <= {phase[2:0], phase[3]};
|
phase <= {phase[2:0], phase[3]};
|
||||||
if (state == STATE_IDLE) begin
|
if (state == STATE_IDLE) begin
|
||||||
@ -160,25 +123,49 @@ module usb_ft1248 (
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
|
usb_scb.fifo_flush_busy <= 1'b0;
|
||||||
|
usb_scb.reset_state <= 1'b0;
|
||||||
|
last_rx_failed <= 1'b0;
|
||||||
last_tx_failed <= 1'b0;
|
last_tx_failed <= 1'b0;
|
||||||
usb_scb.reset_pending <= 1'b0;
|
reset_reply <= 1'b0;
|
||||||
last_reset_status <= 1'b0;
|
|
||||||
modem_status_counter <= 5'd0;
|
modem_status_counter <= 5'd0;
|
||||||
write_modem_status_pending <= 1'b0;
|
write_modem_status_pending <= 1'b1;
|
||||||
write_buffer_flush_pending <= 1'b0;
|
write_buffer_flush_pending <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (usb_scb.reset_ack) begin
|
if (usb_scb.fifo_flush) begin
|
||||||
usb_scb.reset_pending <= 1'b0;
|
usb_scb.fifo_flush_busy <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (usb_scb.reset_on_ack) begin
|
||||||
reset_reply <= 1'b1;
|
reset_reply <= 1'b1;
|
||||||
write_modem_status_pending <= 1'b1;
|
write_modem_status_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (usb_scb.reset_off_ack) begin
|
||||||
|
reset_reply <= 1'b0;
|
||||||
|
write_modem_status_pending <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
if (usb_scb.write_buffer_flush) begin
|
if (usb_scb.write_buffer_flush) begin
|
||||||
write_buffer_flush_pending <= 1'b1;
|
write_buffer_flush_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (state == STATE_IDLE) begin
|
if (state == STATE_IDLE) begin
|
||||||
modem_status_counter <= modem_status_counter + 1'd1;
|
modem_status_counter <= modem_status_counter + 1'd1;
|
||||||
|
if (usb_scb.fifo_flush_busy) begin
|
||||||
|
usb_scb.fifo_flush_busy <= 1'b0;
|
||||||
|
fifo_flush <= 1'b1;
|
||||||
|
last_rx_failed <= 1'b0;
|
||||||
|
last_tx_failed <= 1'b0;
|
||||||
|
end else if (last_rx_failed && !rx_full) begin
|
||||||
|
last_rx_failed <= 1'b0;
|
||||||
|
rx_write_delayed <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ((state == STATE_DATA) && (cmd == CMD_READ) && phase[3]) begin
|
||||||
|
rx_wdata <= ft_miosi_in;
|
||||||
|
last_rx_failed <= !ft_miso && rx_full;
|
||||||
end
|
end
|
||||||
|
|
||||||
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
|
if ((state == STATE_DATA) && (cmd == CMD_WRITE) && phase[3]) begin
|
||||||
@ -187,14 +174,7 @@ module usb_ft1248 (
|
|||||||
|
|
||||||
if (!ft_miso && (state == STATE_DATA) && phase[3]) begin
|
if (!ft_miso && (state == STATE_DATA) && phase[3]) begin
|
||||||
if (cmd == CMD_READ_MODEM_STATUS) begin
|
if (cmd == CMD_READ_MODEM_STATUS) begin
|
||||||
last_reset_status <= ft_miosi_in[0];
|
usb_scb.reset_state <= ft_miosi_in[0];
|
||||||
if (!last_reset_status && ft_miosi_in[0]) begin
|
|
||||||
usb_scb.reset_pending <= 1'b1;
|
|
||||||
end
|
|
||||||
if (last_reset_status && !ft_miosi_in[0]) begin
|
|
||||||
reset_reply <= 1'b0;
|
|
||||||
write_modem_status_pending <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if (cmd == CMD_WRITE_MODEM_STATUS) begin
|
if (cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||||
write_modem_status_pending <= 1'b0;
|
write_modem_status_pending <= 1'b0;
|
||||||
@ -252,8 +232,6 @@ module usb_ft1248 (
|
|||||||
rx_write = 1'b0;
|
rx_write = 1'b0;
|
||||||
tx_read = 1'b0;
|
tx_read = 1'b0;
|
||||||
|
|
||||||
rx_wdata = ft_miosi_in;
|
|
||||||
|
|
||||||
if (!ft_miso && phase[3]) begin
|
if (!ft_miso && phase[3]) begin
|
||||||
case (state)
|
case (state)
|
||||||
STATE_STATUS: begin
|
STATE_STATUS: begin
|
||||||
@ -263,13 +241,15 @@ module usb_ft1248 (
|
|||||||
end
|
end
|
||||||
|
|
||||||
STATE_DATA: begin
|
STATE_DATA: begin
|
||||||
if (cmd == CMD_READ) begin
|
if (cmd == CMD_READ && !rx_full) begin
|
||||||
rx_write = 1'b1;
|
rx_write = 1'b1;
|
||||||
end
|
end
|
||||||
if (cmd == CMD_WRITE && !tx_empty) begin
|
if (cmd == CMD_WRITE && !tx_empty) begin
|
||||||
tx_read = 1'b1;
|
tx_read = 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -283,7 +263,7 @@ module usb_ft1248 (
|
|||||||
end else begin
|
end else begin
|
||||||
case (state)
|
case (state)
|
||||||
STATE_IDLE: begin
|
STATE_IDLE: begin
|
||||||
if (ft_pwrsav) begin
|
if (ft_pwrsav && !(usb_scb.fifo_flush || usb_scb.fifo_flush_busy || fifo_flush)) begin
|
||||||
if (write_modem_status_pending) begin
|
if (write_modem_status_pending) begin
|
||||||
next_state = STATE_SELECT;
|
next_state = STATE_SELECT;
|
||||||
next_cmd = CMD_WRITE_MODEM_STATUS;
|
next_cmd = CMD_WRITE_MODEM_STATUS;
|
||||||
@ -330,7 +310,7 @@ module usb_ft1248 (
|
|||||||
if (ft_miso) begin
|
if (ft_miso) begin
|
||||||
next_state = STATE_DESELECT;
|
next_state = STATE_DESELECT;
|
||||||
end else if (cmd == CMD_READ) begin
|
end else if (cmd == CMD_READ) begin
|
||||||
if (rx_almost_full) begin
|
if (rx_full) begin
|
||||||
next_state = STATE_DESELECT;
|
next_state = STATE_DESELECT;
|
||||||
end
|
end
|
||||||
end else if (cmd == CMD_WRITE) begin
|
end else if (cmd == CMD_WRITE) begin
|
||||||
|
37
fw/rtl/usb/usb_scb.sv
Normal file
37
fw/rtl/usb/usb_scb.sv
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
interface usb_scb ();
|
||||||
|
|
||||||
|
logic fifo_flush;
|
||||||
|
logic fifo_flush_busy;
|
||||||
|
logic write_buffer_flush;
|
||||||
|
logic [10:0] rx_count;
|
||||||
|
logic [10:0] tx_count;
|
||||||
|
logic pwrsav;
|
||||||
|
logic reset_state;
|
||||||
|
logic reset_on_ack;
|
||||||
|
logic reset_off_ack;
|
||||||
|
|
||||||
|
modport controller (
|
||||||
|
output fifo_flush,
|
||||||
|
input fifo_flush_busy,
|
||||||
|
output write_buffer_flush,
|
||||||
|
input rx_count,
|
||||||
|
input tx_count,
|
||||||
|
input pwrsav,
|
||||||
|
input reset_state,
|
||||||
|
output reset_on_ack,
|
||||||
|
output reset_off_ack
|
||||||
|
);
|
||||||
|
|
||||||
|
modport usb (
|
||||||
|
input fifo_flush,
|
||||||
|
output fifo_flush_busy,
|
||||||
|
input write_buffer_flush,
|
||||||
|
output rx_count,
|
||||||
|
output tx_count,
|
||||||
|
output pwrsav,
|
||||||
|
output reset_state,
|
||||||
|
input reset_on_ack,
|
||||||
|
input reset_off_ack
|
||||||
|
);
|
||||||
|
|
||||||
|
endinterface
|
@ -3,18 +3,19 @@ module fifo_8kb (
|
|||||||
input reset,
|
input reset,
|
||||||
|
|
||||||
output empty,
|
output empty,
|
||||||
output almost_empty,
|
|
||||||
input read,
|
input read,
|
||||||
output [7:0] rdata,
|
output [7:0] rdata,
|
||||||
|
|
||||||
output full,
|
output full,
|
||||||
output almost_full,
|
|
||||||
input write,
|
input write,
|
||||||
input [7:0] wdata,
|
input [7:0] wdata,
|
||||||
|
|
||||||
output logic [10:0] count
|
output logic [10:0] count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logic almost_empty;
|
||||||
|
logic almost_full;
|
||||||
|
|
||||||
fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst (
|
fifo_8kb_lattice_generated fifo_8kb_lattice_generated_inst (
|
||||||
.Data(wdata),
|
.Data(wdata),
|
||||||
.WrClock(clk),
|
.WrClock(clk),
|
||||||
@ -25,7 +26,7 @@ module fifo_8kb (
|
|||||||
.RPReset(reset),
|
.RPReset(reset),
|
||||||
.Q(rdata),
|
.Q(rdata),
|
||||||
.Empty(empty),
|
.Empty(empty),
|
||||||
.Full(full),
|
.Full(full),
|
||||||
.AlmostEmpty(almost_empty),
|
.AlmostEmpty(almost_empty),
|
||||||
.AlmostFull(almost_full)
|
.AlmostFull(almost_full)
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.12.1.454 */
|
/* Verilog netlist generated by SCUBA Diamond (64-bit) 3.13.0.56.2 */
|
||||||
/* Module Version: 5.7 */
|
/* Module Version: 5.7 */
|
||||||
/* C:\lscc\diamond\3.12\ispfpga\bin\nt64\scuba.exe -w -n pll_lattice_generated -lang verilog -synth synplify -arch xo2c00 -type pll -fin 50 -fclkop 100 -fclkop_tol 0.0 -fclkos 100 -fclkos_tol 0.0 -trimp 0 -phasep 0 -trimp_r -trims 0 -phases 90 -trims_r -phase_cntl STATIC -fb_mode 1 -lock */
|
/* C:\lscc\diamond\3.13\ispfpga\bin\nt64\scuba.exe -w -n pll_lattice_generated -lang verilog -synth synplify -arch xo2c00 -type pll -fin 50 -fclkop 100 -fclkop_tol 0.0 -fclkos 100 -fclkos_tol 0.0 -trimp 0 -phasep 0 -trimp_r -trims 0 -phases 270 -trims_r -phase_cntl STATIC -fb_mode 1 -lock */
|
||||||
/* Sat Mar 19 17:10:12 2022 */
|
/* Sun May 05 06:07:05 2024 */
|
||||||
|
|
||||||
|
|
||||||
`timescale 1 ns / 1 ps
|
`timescale 1 ns / 1 ps
|
||||||
@ -29,8 +29,8 @@ module pll_lattice_generated (CLKI, CLKOP, CLKOS, LOCK)/* synthesis NGD_DRC_MASK
|
|||||||
defparam PLLInst_0.CLKOS3_CPHASE = 0 ;
|
defparam PLLInst_0.CLKOS3_CPHASE = 0 ;
|
||||||
defparam PLLInst_0.CLKOS2_FPHASE = 0 ;
|
defparam PLLInst_0.CLKOS2_FPHASE = 0 ;
|
||||||
defparam PLLInst_0.CLKOS2_CPHASE = 0 ;
|
defparam PLLInst_0.CLKOS2_CPHASE = 0 ;
|
||||||
defparam PLLInst_0.CLKOS_FPHASE = 2 ;
|
defparam PLLInst_0.CLKOS_FPHASE = 6 ;
|
||||||
defparam PLLInst_0.CLKOS_CPHASE = 5 ;
|
defparam PLLInst_0.CLKOS_CPHASE = 7 ;
|
||||||
defparam PLLInst_0.CLKOP_FPHASE = 0 ;
|
defparam PLLInst_0.CLKOP_FPHASE = 0 ;
|
||||||
defparam PLLInst_0.CLKOP_CPHASE = 4 ;
|
defparam PLLInst_0.CLKOP_CPHASE = 4 ;
|
||||||
defparam PLLInst_0.PLL_LOCK_MODE = 0 ;
|
defparam PLLInst_0.PLL_LOCK_MODE = 0 ;
|
||||||
|
@ -17,8 +17,8 @@ module pll (
|
|||||||
);
|
);
|
||||||
|
|
||||||
ODDRXE oddrxe_sdram_clk_inst (
|
ODDRXE oddrxe_sdram_clk_inst (
|
||||||
.D0(1'b0),
|
.D0(1'b1),
|
||||||
.D1(1'b1),
|
.D1(1'b0),
|
||||||
.SCLK(pll_sdram_clk),
|
.SCLK(pll_sdram_clk),
|
||||||
.RST(1'b0),
|
.RST(1'b0),
|
||||||
.Q(buf_sdram_clk)
|
.Q(buf_sdram_clk)
|
||||||
|
1
fw/tests/.gitignore
vendored
Normal file
1
fw/tests/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
35
fw/tests/Makefile
Normal file
35
fw/tests/Makefile
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
RTL_DIR = ../rtl
|
||||||
|
BENCHES_DIR = benches
|
||||||
|
MOCKS_DIR = mocks
|
||||||
|
BUILD_DIR = build
|
||||||
|
SRC_DIRS = \
|
||||||
|
$(RTL_DIR)/fifo \
|
||||||
|
$(RTL_DIR)/mcu \
|
||||||
|
$(RTL_DIR)/memory \
|
||||||
|
$(RTL_DIR)/n64 \
|
||||||
|
$(RTL_DIR)/sd \
|
||||||
|
$(RTL_DIR)/serv \
|
||||||
|
$(RTL_DIR)/usb \
|
||||||
|
$(RTL_DIR)/vendor \
|
||||||
|
$(RTL_DIR) \
|
||||||
|
$(MOCKS_DIR)/vendor \
|
||||||
|
$(MOCKS_DIR)
|
||||||
|
|
||||||
|
INC_DIRS = $(addprefix -I, $(SRC_DIRS))
|
||||||
|
TEST_FILES = $(shell find "./$(BENCHES_DIR)" -not -path "$(BUILD_DIR)/*" -type f -name "*_tb.sv")
|
||||||
|
TESTS = $(addprefix $(BUILD_DIR)/, $(basename $(TEST_FILES)))
|
||||||
|
|
||||||
|
VERILATOR_FLAGS = --binary --trace --timescale 10ns/1ns -j --quiet $(INC_DIRS)
|
||||||
|
|
||||||
|
$(BUILD_DIR)/%: %.sv
|
||||||
|
@echo "[VERILATOR] $<"
|
||||||
|
@mkdir -p $@.obj
|
||||||
|
@verilator $(VERILATOR_FLAGS) -Mdir $@.obj $< > /dev/null
|
||||||
|
@$@.obj/V$(notdir $@)
|
||||||
|
|
||||||
|
tests: $(TESTS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@rm -rf ./$(BUILD_DIR)
|
||||||
|
|
||||||
|
.PHONY: tests
|
126
fw/tests/benches/memory_dma_tb.sv
Normal file
126
fw/tests/benches/memory_dma_tb.sv
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
module memory_dma_tb;
|
||||||
|
|
||||||
|
logic clk;
|
||||||
|
logic reset;
|
||||||
|
|
||||||
|
dma_scb dma_scb ();
|
||||||
|
fifo_bus fifo_bus ();
|
||||||
|
mem_bus mem_bus ();
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
logic stop;
|
||||||
|
logic direction;
|
||||||
|
logic byte_swap;
|
||||||
|
logic [26:0] starting_address;
|
||||||
|
logic [26:0] transfer_length;
|
||||||
|
|
||||||
|
logic flush;
|
||||||
|
logic rx_fill_enabled;
|
||||||
|
logic tx_drain_enabled;
|
||||||
|
|
||||||
|
memory_dma memory_dma (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.dma_scb(dma_scb),
|
||||||
|
.fifo_bus(fifo_bus),
|
||||||
|
.mem_bus(mem_bus)
|
||||||
|
);
|
||||||
|
|
||||||
|
dma_controller_mock dma_controller_mock (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.dma_scb(dma_scb),
|
||||||
|
|
||||||
|
.start(start),
|
||||||
|
.stop(stop),
|
||||||
|
.direction(direction),
|
||||||
|
.byte_swap(byte_swap),
|
||||||
|
.starting_address(starting_address),
|
||||||
|
.transfer_length(transfer_length)
|
||||||
|
);
|
||||||
|
|
||||||
|
fifo_bus_fifo_mock #(
|
||||||
|
.DEPTH(8),
|
||||||
|
.FILL_RATE(3),
|
||||||
|
.DRAIN_RATE(3)
|
||||||
|
) fifo_bus_fifo_mock (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.fifo_bus(fifo_bus),
|
||||||
|
|
||||||
|
.flush(flush),
|
||||||
|
|
||||||
|
.rx_fill_enabled(rx_fill_enabled),
|
||||||
|
.tx_drain_enabled(tx_drain_enabled)
|
||||||
|
);
|
||||||
|
|
||||||
|
memory_sdram_mock memory_sdram_mock (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.mem_bus(mem_bus)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 1'b0;
|
||||||
|
forever begin
|
||||||
|
clk = ~clk; #0.5;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b0;
|
||||||
|
#10;
|
||||||
|
reset = 1'b1;
|
||||||
|
#10;
|
||||||
|
reset = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("traces/memory_dma_tb.vcd");
|
||||||
|
|
||||||
|
#10000;
|
||||||
|
|
||||||
|
$dumpvars();
|
||||||
|
|
||||||
|
#100;
|
||||||
|
start = 1'b1;
|
||||||
|
direction = 1'b0;
|
||||||
|
byte_swap = 1'b0;
|
||||||
|
starting_address = 27'hFFF1;
|
||||||
|
transfer_length = 27'd64;
|
||||||
|
#1;
|
||||||
|
start = 1'b0;
|
||||||
|
|
||||||
|
#9;
|
||||||
|
tx_drain_enabled = 1'b1;
|
||||||
|
|
||||||
|
#490;
|
||||||
|
stop = 1'b1;
|
||||||
|
#1;
|
||||||
|
stop = 1'b0;
|
||||||
|
|
||||||
|
#165;
|
||||||
|
|
||||||
|
start = 1'b1;
|
||||||
|
direction = 1'b1;
|
||||||
|
#1;
|
||||||
|
start = 1'b0;
|
||||||
|
|
||||||
|
#9;
|
||||||
|
rx_fill_enabled = 1'b1;
|
||||||
|
|
||||||
|
#490;
|
||||||
|
stop = 1'b1;
|
||||||
|
#1;
|
||||||
|
stop = 1'b0;
|
||||||
|
|
||||||
|
#99;
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
119
fw/tests/benches/usb_ft1248_tb.sv
Normal file
119
fw/tests/benches/usb_ft1248_tb.sv
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
module usb_ft1248_tb;
|
||||||
|
|
||||||
|
logic clk;
|
||||||
|
logic reset;
|
||||||
|
|
||||||
|
usb_scb usb_scb ();
|
||||||
|
fifo_bus fifo_bus ();
|
||||||
|
|
||||||
|
logic usb_pwrsav;
|
||||||
|
logic usb_clk;
|
||||||
|
logic usb_cs;
|
||||||
|
logic usb_miso;
|
||||||
|
logic [7:0] usb_miosi;
|
||||||
|
|
||||||
|
usb_ft1248 usb_ft1248 (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
.usb_scb(usb_scb),
|
||||||
|
.fifo_bus(fifo_bus),
|
||||||
|
.usb_pwrsav(usb_pwrsav),
|
||||||
|
.usb_clk(usb_clk),
|
||||||
|
.usb_cs(usb_cs),
|
||||||
|
.usb_miso(usb_miso),
|
||||||
|
.usb_miosi(usb_miosi)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 1'b0;
|
||||||
|
forever begin
|
||||||
|
clk = ~clk; #0.5;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
reset = 1'b1;
|
||||||
|
#10;
|
||||||
|
reset = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$dumpfile("traces/usb_ft1248_tb.vcd");
|
||||||
|
|
||||||
|
$dumpvars();
|
||||||
|
|
||||||
|
usb_pwrsav = 1'b1;
|
||||||
|
usb_miso = 1'b1;
|
||||||
|
|
||||||
|
#100;
|
||||||
|
|
||||||
|
fifo_bus.tx_write = 1'b1;
|
||||||
|
#100;
|
||||||
|
fifo_bus.tx_write = 1'b0;
|
||||||
|
|
||||||
|
#103;
|
||||||
|
|
||||||
|
usb_miso = 1'b0;
|
||||||
|
#80;
|
||||||
|
usb_scb.write_buffer_flush = 1'b1;
|
||||||
|
#1;
|
||||||
|
usb_scb.write_buffer_flush = 1'b0;
|
||||||
|
#20;
|
||||||
|
usb_miso = 1'b1;
|
||||||
|
#26;
|
||||||
|
usb_miso = 1'b0;
|
||||||
|
|
||||||
|
#4430;
|
||||||
|
|
||||||
|
usb_miso = 1'b1;
|
||||||
|
#13;
|
||||||
|
usb_miso = 1'b0;
|
||||||
|
|
||||||
|
#79;
|
||||||
|
|
||||||
|
fifo_bus.rx_read = 1'b1;
|
||||||
|
#1;
|
||||||
|
fifo_bus.rx_read = 1'b0;
|
||||||
|
|
||||||
|
#10;
|
||||||
|
|
||||||
|
fifo_bus.rx_read = 1'b1;
|
||||||
|
#1;
|
||||||
|
fifo_bus.rx_read = 1'b0;
|
||||||
|
|
||||||
|
#80;
|
||||||
|
|
||||||
|
fifo_bus.rx_read = 1'b1;
|
||||||
|
#1;
|
||||||
|
fifo_bus.rx_read = 1'b0;
|
||||||
|
|
||||||
|
#200;
|
||||||
|
|
||||||
|
usb_scb.reset_on_ack = 1'b1;
|
||||||
|
#1;
|
||||||
|
usb_scb.reset_on_ack = 1'b0;
|
||||||
|
|
||||||
|
#200;
|
||||||
|
|
||||||
|
usb_scb.reset_off_ack = 1'b1;
|
||||||
|
#1;
|
||||||
|
usb_scb.reset_off_ack = 1'b0;
|
||||||
|
|
||||||
|
#200;
|
||||||
|
|
||||||
|
usb_scb.fifo_flush = 1'b1;
|
||||||
|
#1;
|
||||||
|
usb_scb.fifo_flush = 1'b0;
|
||||||
|
|
||||||
|
#3000;
|
||||||
|
|
||||||
|
usb_scb.fifo_flush = 1'b1;
|
||||||
|
#1;
|
||||||
|
usb_scb.fifo_flush = 1'b0;
|
||||||
|
|
||||||
|
#6000;
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
22
fw/tests/docker_run.sh
Executable file
22
fw/tests/docker_run.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
pushd $(dirname $0) > /dev/null
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
-it \
|
||||||
|
--rm \
|
||||||
|
--user $(id -u):$(id -g) \
|
||||||
|
-v "$(pwd)":/work \
|
||||||
|
-v "$(pwd)/../rtl":/rtl \
|
||||||
|
-e CCACHE_DIR=/tmp/ccache \
|
||||||
|
--entrypoint /bin/bash \
|
||||||
|
verilator/verilator:latest \
|
||||||
|
-c "make -j"
|
||||||
|
|
||||||
|
BUILD_ERROR=$?
|
||||||
|
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
if [ $BUILD_ERROR -ne 0 ]; then
|
||||||
|
exit -1
|
||||||
|
fi
|
39
fw/tests/mocks/dma_controller_mock.sv
Normal file
39
fw/tests/mocks/dma_controller_mock.sv
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module dma_controller_mock (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
dma_scb.controller dma_scb,
|
||||||
|
|
||||||
|
input start,
|
||||||
|
input stop,
|
||||||
|
input direction,
|
||||||
|
input byte_swap,
|
||||||
|
input [26:0] starting_address,
|
||||||
|
input [26:0] transfer_length
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
dma_scb.start <= 1'b0;
|
||||||
|
dma_scb.stop <= 1'b0;
|
||||||
|
|
||||||
|
if (reset) begin
|
||||||
|
dma_scb.direction <= 1'b0;
|
||||||
|
dma_scb.byte_swap <= 1'b0;
|
||||||
|
dma_scb.starting_address <= 27'd0;
|
||||||
|
dma_scb.transfer_length <= 27'd0;
|
||||||
|
end else begin
|
||||||
|
if (start) begin
|
||||||
|
dma_scb.start <= 1'b1;
|
||||||
|
dma_scb.direction <= direction;
|
||||||
|
dma_scb.byte_swap <= byte_swap;
|
||||||
|
dma_scb.starting_address <= starting_address;
|
||||||
|
dma_scb.transfer_length <= transfer_length;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (stop) begin
|
||||||
|
dma_scb.stop <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
145
fw/tests/mocks/fifo_bus_fifo_mock.sv
Normal file
145
fw/tests/mocks/fifo_bus_fifo_mock.sv
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
module fifo_bus_fifo_mock #(
|
||||||
|
parameter int DEPTH = 1024,
|
||||||
|
parameter int FILL_RATE = 3,
|
||||||
|
parameter int DRAIN_RATE = 3
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
fifo_bus.fifo fifo_bus,
|
||||||
|
|
||||||
|
input flush,
|
||||||
|
|
||||||
|
input rx_fill_enabled,
|
||||||
|
input tx_drain_enabled
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam int PTR_BITS = $clog2(DEPTH);
|
||||||
|
|
||||||
|
|
||||||
|
// RX FIFO mock
|
||||||
|
|
||||||
|
logic rx_full;
|
||||||
|
logic rx_write;
|
||||||
|
logic [7:0] rx_wdata;
|
||||||
|
|
||||||
|
logic [PTR_BITS:0] rx_count;
|
||||||
|
|
||||||
|
fifo_mock #(
|
||||||
|
.DEPTH(DEPTH)
|
||||||
|
) fifo_rx (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.empty(fifo_bus.rx_empty),
|
||||||
|
.read(fifo_bus.rx_read),
|
||||||
|
.rdata(fifo_bus.rx_rdata),
|
||||||
|
|
||||||
|
.full(rx_full),
|
||||||
|
.write(rx_write),
|
||||||
|
.wdata(rx_wdata),
|
||||||
|
|
||||||
|
.count(rx_count)
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam int FILL_BITS = $clog2(FILL_RATE);
|
||||||
|
logic [FILL_BITS:0] fill_counter;
|
||||||
|
logic rx_fill;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
rx_fill <= rx_fill_enabled;
|
||||||
|
end
|
||||||
|
|
||||||
|
generate;
|
||||||
|
if (FILL_RATE == 0) begin
|
||||||
|
always_comb begin
|
||||||
|
rx_write = rx_fill && !rx_full;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
always_comb begin
|
||||||
|
rx_write = rx_fill && !rx_full && (fill_counter == (FILL_BITS + 1)'(FILL_RATE));
|
||||||
|
end
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (fill_counter < (FILL_BITS + 1)'(FILL_RATE)) begin
|
||||||
|
fill_counter <= fill_counter + (FILL_BITS + 1)'('d1);
|
||||||
|
end
|
||||||
|
if (reset) begin
|
||||||
|
fill_counter <= (FILL_BITS + 1)'('d0);
|
||||||
|
end else begin
|
||||||
|
if (rx_write) begin
|
||||||
|
fill_counter <= (FILL_BITS + 1)'('d0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
rx_wdata <= 8'h01;
|
||||||
|
end else begin
|
||||||
|
if (rx_write) begin
|
||||||
|
rx_wdata <= rx_wdata + 8'h01;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// TX FIFO mock
|
||||||
|
|
||||||
|
logic tx_empty;
|
||||||
|
logic tx_read;
|
||||||
|
logic [7:0] tx_rdata;
|
||||||
|
|
||||||
|
logic [PTR_BITS:0] tx_count;
|
||||||
|
|
||||||
|
fifo_mock #(
|
||||||
|
.DEPTH(DEPTH)
|
||||||
|
) fifo_tx (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.empty(tx_empty),
|
||||||
|
.read(tx_read),
|
||||||
|
.rdata(tx_rdata),
|
||||||
|
|
||||||
|
.full(fifo_bus.tx_full),
|
||||||
|
.write(fifo_bus.tx_write),
|
||||||
|
.wdata(fifo_bus.tx_wdata),
|
||||||
|
|
||||||
|
.count(tx_count)
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam int DRAIN_BITS = $clog2(DRAIN_RATE);
|
||||||
|
logic [DRAIN_BITS:0] drain_counter;
|
||||||
|
logic tx_drain;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
tx_drain <= tx_drain_enabled;
|
||||||
|
end
|
||||||
|
|
||||||
|
generate;
|
||||||
|
if (DRAIN_RATE == 0) begin
|
||||||
|
always_comb begin
|
||||||
|
tx_read = tx_drain && !tx_empty;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
always_comb begin
|
||||||
|
tx_read = tx_drain && !tx_empty && (drain_counter == (DRAIN_BITS + 1)'(DRAIN_RATE));
|
||||||
|
end
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (drain_counter < (DRAIN_BITS + 1)'(DRAIN_RATE)) begin
|
||||||
|
drain_counter <= drain_counter + (DRAIN_BITS + 1)'('d1);
|
||||||
|
end
|
||||||
|
if (reset) begin
|
||||||
|
drain_counter <= (DRAIN_BITS + 1)'('d0);
|
||||||
|
end else begin
|
||||||
|
if (tx_read) begin
|
||||||
|
drain_counter <= (DRAIN_BITS + 1)'('d0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
endmodule
|
49
fw/tests/mocks/fifo_mock.sv
Normal file
49
fw/tests/mocks/fifo_mock.sv
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
module fifo_mock #(
|
||||||
|
parameter int DEPTH = 1024,
|
||||||
|
localparam int PTR_BITS = $clog2(DEPTH)
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
output logic empty,
|
||||||
|
input read,
|
||||||
|
output [7:0] rdata,
|
||||||
|
|
||||||
|
output logic full,
|
||||||
|
input write,
|
||||||
|
input [7:0] wdata,
|
||||||
|
|
||||||
|
output logic [PTR_BITS:0] count
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [7:0] fifo_mem [0:(DEPTH - 1)];
|
||||||
|
logic [(PTR_BITS - 1):0] fifo_rptr;
|
||||||
|
logic [(PTR_BITS - 1):0] fifo_wptr;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
full = count >= (PTR_BITS + 1)'(DEPTH);
|
||||||
|
empty = count == (PTR_BITS + 1)'('d0);
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (read) begin
|
||||||
|
rdata <= fifo_mem[fifo_rptr];
|
||||||
|
fifo_rptr <= fifo_rptr + PTR_BITS'('d1);
|
||||||
|
count <= count - (PTR_BITS + 1)'('d1);
|
||||||
|
end
|
||||||
|
if (write) begin
|
||||||
|
fifo_mem[fifo_wptr] <= wdata;
|
||||||
|
fifo_wptr <= fifo_wptr + PTR_BITS'('d1);
|
||||||
|
count <= count + (PTR_BITS + 1)'('d1);
|
||||||
|
end
|
||||||
|
if (read && write) begin
|
||||||
|
count <= count;
|
||||||
|
end
|
||||||
|
if (reset) begin
|
||||||
|
count <= (PTR_BITS + 1)'('d0);
|
||||||
|
fifo_rptr <= PTR_BITS'('d0);
|
||||||
|
fifo_wptr <= PTR_BITS'('d0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
70
fw/tests/mocks/memory_sdram_mock.sv
Normal file
70
fw/tests/mocks/memory_sdram_mock.sv
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
module memory_sdram_mock (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
mem_bus.memory mem_bus
|
||||||
|
);
|
||||||
|
|
||||||
|
logic sdram_cs;
|
||||||
|
logic sdram_ras;
|
||||||
|
logic sdram_cas;
|
||||||
|
logic sdram_we;
|
||||||
|
logic [1:0] sdram_ba;
|
||||||
|
logic [12:0] sdram_a;
|
||||||
|
logic [1:0] sdram_dqm;
|
||||||
|
logic [15:0] sdram_dq;
|
||||||
|
|
||||||
|
memory_sdram memory_sdram_inst (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.mem_bus(mem_bus),
|
||||||
|
|
||||||
|
.sdram_cs(sdram_cs),
|
||||||
|
.sdram_ras(sdram_ras),
|
||||||
|
.sdram_cas(sdram_cas),
|
||||||
|
.sdram_we(sdram_we),
|
||||||
|
.sdram_ba(sdram_ba),
|
||||||
|
.sdram_a(sdram_a),
|
||||||
|
.sdram_dqm(sdram_dqm),
|
||||||
|
.sdram_dq(sdram_dq)
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [1:0] cas_delay;
|
||||||
|
logic [15:0] data_from_sdram;
|
||||||
|
logic [15:0] data_to_sdram;
|
||||||
|
logic [15:0] sdram_dq_driven;
|
||||||
|
|
||||||
|
assign sdram_dq = sdram_dq_driven;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
cas_delay <= 2'b00;
|
||||||
|
data_from_sdram <= 16'h0102;
|
||||||
|
data_to_sdram <= 16'hFFFF;
|
||||||
|
end else begin
|
||||||
|
cas_delay <= {cas_delay[0], 1'b0};
|
||||||
|
|
||||||
|
if ({sdram_cs, sdram_ras, sdram_cas, sdram_we} == 4'b0101) begin
|
||||||
|
cas_delay[0] <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (cas_delay[1]) begin
|
||||||
|
data_from_sdram <= data_from_sdram + 16'h0202;
|
||||||
|
end
|
||||||
|
|
||||||
|
if ({sdram_cs, sdram_ras, sdram_cas, sdram_we} == 4'b0100) begin
|
||||||
|
if (!sdram_dqm[0]) data_to_sdram[7:0] <= sdram_dq[7:0];
|
||||||
|
if (!sdram_dqm[1]) data_to_sdram[15:8] <= sdram_dq[15:8];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
sdram_dq_driven = 16'hXXXX;
|
||||||
|
if (cas_delay[1]) begin
|
||||||
|
sdram_dq_driven = data_from_sdram;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
33
fw/tests/mocks/vendor/fifo_8kb.sv
vendored
Normal file
33
fw/tests/mocks/vendor/fifo_8kb.sv
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
module fifo_8kb (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
output empty,
|
||||||
|
input read,
|
||||||
|
output [7:0] rdata,
|
||||||
|
|
||||||
|
output full,
|
||||||
|
input write,
|
||||||
|
input [7:0] wdata,
|
||||||
|
|
||||||
|
output logic [10:0] count
|
||||||
|
);
|
||||||
|
|
||||||
|
fifo_mock #(
|
||||||
|
.DEPTH(1024)
|
||||||
|
) fifo_8kb (
|
||||||
|
.clk(clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
|
.empty(empty),
|
||||||
|
.read(read),
|
||||||
|
.rdata(rdata),
|
||||||
|
|
||||||
|
.full(full),
|
||||||
|
.write(write),
|
||||||
|
.wdata(wdata),
|
||||||
|
|
||||||
|
.count(count)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
2
fw/tests/traces/.gitignore
vendored
Normal file
2
fw/tests/traces/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.vcd
|
||||||
|
*.gtkw
|
2
hw/pcb/.gitignore
vendored
2
hw/pcb/.gitignore
vendored
@ -1,5 +1,7 @@
|
|||||||
|
*.lck
|
||||||
**/*-backups
|
**/*-backups
|
||||||
**/*-bak
|
**/*-bak
|
||||||
|
**/*.3dshapes
|
||||||
**/*.csv
|
**/*.csv
|
||||||
**/*.gerbers
|
**/*.gerbers
|
||||||
**/*.kicad_prl
|
**/*.kicad_prl
|
||||||
|
289
hw/pcb/LICENSE
Normal file
289
hw/pcb/LICENSE
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
CERN Open Hardware Licence Version 2 - Strongly Reciprocal
|
||||||
|
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
CERN has developed this licence to promote collaboration among
|
||||||
|
hardware designers and to provide a legal tool which supports the
|
||||||
|
freedom to use, study, modify, share and distribute hardware designs
|
||||||
|
and products based on those designs. Version 2 of the CERN Open
|
||||||
|
Hardware Licence comes in three variants: CERN-OHL-P (permissive); and
|
||||||
|
two reciprocal licences: CERN-OHL-W (weakly reciprocal) and this
|
||||||
|
licence, CERN-OHL-S (strongly reciprocal).
|
||||||
|
|
||||||
|
The CERN-OHL-S is copyright CERN 2020. Anyone is welcome to use it, in
|
||||||
|
unmodified form only.
|
||||||
|
|
||||||
|
Use of this Licence does not imply any endorsement by CERN of any
|
||||||
|
Licensor or their designs nor does it imply any involvement by CERN in
|
||||||
|
their development.
|
||||||
|
|
||||||
|
|
||||||
|
1 Definitions
|
||||||
|
|
||||||
|
1.1 'Licence' means this CERN-OHL-S.
|
||||||
|
|
||||||
|
1.2 'Compatible Licence' means
|
||||||
|
|
||||||
|
a) any earlier version of the CERN Open Hardware licence, or
|
||||||
|
|
||||||
|
b) any version of the CERN-OHL-S, or
|
||||||
|
|
||||||
|
c) any licence which permits You to treat the Source to which
|
||||||
|
it applies as licensed under CERN-OHL-S provided that on
|
||||||
|
Conveyance of any such Source, or any associated Product You
|
||||||
|
treat the Source in question as being licensed under
|
||||||
|
CERN-OHL-S.
|
||||||
|
|
||||||
|
1.3 'Source' means information such as design materials or digital
|
||||||
|
code which can be applied to Make or test a Product or to
|
||||||
|
prepare a Product for use, Conveyance or sale, regardless of its
|
||||||
|
medium or how it is expressed. It may include Notices.
|
||||||
|
|
||||||
|
1.4 'Covered Source' means Source that is explicitly made available
|
||||||
|
under this Licence.
|
||||||
|
|
||||||
|
1.5 'Product' means any device, component, work or physical object,
|
||||||
|
whether in finished or intermediate form, arising from the use,
|
||||||
|
application or processing of Covered Source.
|
||||||
|
|
||||||
|
1.6 'Make' means to create or configure something, whether by
|
||||||
|
manufacture, assembly, compiling, loading or applying Covered
|
||||||
|
Source or another Product or otherwise.
|
||||||
|
|
||||||
|
1.7 'Available Component' means any part, sub-assembly, library or
|
||||||
|
code which:
|
||||||
|
|
||||||
|
a) is licensed to You as Complete Source under a Compatible
|
||||||
|
Licence; or
|
||||||
|
|
||||||
|
b) is available, at the time a Product or the Source containing
|
||||||
|
it is first Conveyed, to You and any other prospective
|
||||||
|
licensees
|
||||||
|
|
||||||
|
i) as a physical part with sufficient rights and
|
||||||
|
information (including any configuration and
|
||||||
|
programming files and information about its
|
||||||
|
characteristics and interfaces) to enable it either to
|
||||||
|
be Made itself, or to be sourced and used to Make the
|
||||||
|
Product; or
|
||||||
|
ii) as part of the normal distribution of a tool used to
|
||||||
|
design or Make the Product.
|
||||||
|
|
||||||
|
1.8 'Complete Source' means the set of all Source necessary to Make
|
||||||
|
a Product, in the preferred form for making modifications,
|
||||||
|
including necessary installation and interfacing information
|
||||||
|
both for the Product, and for any included Available Components.
|
||||||
|
If the format is proprietary, it must also be made available in
|
||||||
|
a format (if the proprietary tool can create it) which is
|
||||||
|
viewable with a tool available to potential licensees and
|
||||||
|
licensed under a licence approved by the Free Software
|
||||||
|
Foundation or the Open Source Initiative. Complete Source need
|
||||||
|
not include the Source of any Available Component, provided that
|
||||||
|
You include in the Complete Source sufficient information to
|
||||||
|
enable a recipient to Make or source and use the Available
|
||||||
|
Component to Make the Product.
|
||||||
|
|
||||||
|
1.9 'Source Location' means a location where a Licensor has placed
|
||||||
|
Covered Source, and which that Licensor reasonably believes will
|
||||||
|
remain easily accessible for at least three years for anyone to
|
||||||
|
obtain a digital copy.
|
||||||
|
|
||||||
|
1.10 'Notice' means copyright, acknowledgement and trademark notices,
|
||||||
|
Source Location references, modification notices (subsection
|
||||||
|
3.3(b)) and all notices that refer to this Licence and to the
|
||||||
|
disclaimer of warranties that are included in the Covered
|
||||||
|
Source.
|
||||||
|
|
||||||
|
1.11 'Licensee' or 'You' means any person exercising rights under
|
||||||
|
this Licence.
|
||||||
|
|
||||||
|
1.12 'Licensor' means a natural or legal person who creates or
|
||||||
|
modifies Covered Source. A person may be a Licensee and a
|
||||||
|
Licensor at the same time.
|
||||||
|
|
||||||
|
1.13 'Convey' means to communicate to the public or distribute.
|
||||||
|
|
||||||
|
|
||||||
|
2 Applicability
|
||||||
|
|
||||||
|
2.1 This Licence governs the use, copying, modification, Conveying
|
||||||
|
of Covered Source and Products, and the Making of Products. By
|
||||||
|
exercising any right granted under this Licence, You irrevocably
|
||||||
|
accept these terms and conditions.
|
||||||
|
|
||||||
|
2.2 This Licence is granted by the Licensor directly to You, and
|
||||||
|
shall apply worldwide and without limitation in time.
|
||||||
|
|
||||||
|
2.3 You shall not attempt to restrict by contract or otherwise the
|
||||||
|
rights granted under this Licence to other Licensees.
|
||||||
|
|
||||||
|
2.4 This Licence is not intended to restrict fair use, fair dealing,
|
||||||
|
or any other similar right.
|
||||||
|
|
||||||
|
|
||||||
|
3 Copying, Modifying and Conveying Covered Source
|
||||||
|
|
||||||
|
3.1 You may copy and Convey verbatim copies of Covered Source, in
|
||||||
|
any medium, provided You retain all Notices.
|
||||||
|
|
||||||
|
3.2 You may modify Covered Source, other than Notices, provided that
|
||||||
|
You irrevocably undertake to make that modified Covered Source
|
||||||
|
available from a Source Location should You Convey a Product in
|
||||||
|
circumstances where the recipient does not otherwise receive a
|
||||||
|
copy of the modified Covered Source. In each case subsection 3.3
|
||||||
|
shall apply.
|
||||||
|
|
||||||
|
You may only delete Notices if they are no longer applicable to
|
||||||
|
the corresponding Covered Source as modified by You and You may
|
||||||
|
add additional Notices applicable to Your modifications.
|
||||||
|
Including Covered Source in a larger work is modifying the
|
||||||
|
Covered Source, and the larger work becomes modified Covered
|
||||||
|
Source.
|
||||||
|
|
||||||
|
3.3 You may Convey modified Covered Source (with the effect that You
|
||||||
|
shall also become a Licensor) provided that You:
|
||||||
|
|
||||||
|
a) retain Notices as required in subsection 3.2;
|
||||||
|
|
||||||
|
b) add a Notice to the modified Covered Source stating that You
|
||||||
|
have modified it, with the date and brief description of how
|
||||||
|
You have modified it;
|
||||||
|
|
||||||
|
c) add a Source Location Notice for the modified Covered Source
|
||||||
|
if You Convey in circumstances where the recipient does not
|
||||||
|
otherwise receive a copy of the modified Covered Source; and
|
||||||
|
|
||||||
|
d) license the modified Covered Source under the terms and
|
||||||
|
conditions of this Licence (or, as set out in subsection
|
||||||
|
8.3, a later version, if permitted by the licence of the
|
||||||
|
original Covered Source). Such modified Covered Source must
|
||||||
|
be licensed as a whole, but excluding Available Components
|
||||||
|
contained in it, which remain licensed under their own
|
||||||
|
applicable licences.
|
||||||
|
|
||||||
|
|
||||||
|
4 Making and Conveying Products
|
||||||
|
|
||||||
|
You may Make Products, and/or Convey them, provided that You either
|
||||||
|
provide each recipient with a copy of the Complete Source or ensure
|
||||||
|
that each recipient is notified of the Source Location of the Complete
|
||||||
|
Source. That Complete Source is Covered Source, and You must
|
||||||
|
accordingly satisfy Your obligations set out in subsection 3.3. If
|
||||||
|
specified in a Notice, the Product must visibly and securely display
|
||||||
|
the Source Location on it or its packaging or documentation in the
|
||||||
|
manner specified in that Notice.
|
||||||
|
|
||||||
|
|
||||||
|
5 Research and Development
|
||||||
|
|
||||||
|
You may Convey Covered Source, modified Covered Source or Products to
|
||||||
|
a legal entity carrying out development, testing or quality assurance
|
||||||
|
work on Your behalf provided that the work is performed on terms which
|
||||||
|
prevent the entity from both using the Source or Products for its own
|
||||||
|
internal purposes and Conveying the Source or Products or any
|
||||||
|
modifications to them to any person other than You. Any modifications
|
||||||
|
made by the entity shall be deemed to be made by You pursuant to
|
||||||
|
subsection 3.2.
|
||||||
|
|
||||||
|
|
||||||
|
6 DISCLAIMER AND LIABILITY
|
||||||
|
|
||||||
|
6.1 DISCLAIMER OF WARRANTY -- The Covered Source and any Products
|
||||||
|
are provided 'as is' and any express or implied warranties,
|
||||||
|
including, but not limited to, implied warranties of
|
||||||
|
merchantability, of satisfactory quality, non-infringement of
|
||||||
|
third party rights, and fitness for a particular purpose or use
|
||||||
|
are disclaimed in respect of any Source or Product to the
|
||||||
|
maximum extent permitted by law. The Licensor makes no
|
||||||
|
representation that any Source or Product does not or will not
|
||||||
|
infringe any patent, copyright, trade secret or other
|
||||||
|
proprietary right. The entire risk as to the use, quality, and
|
||||||
|
performance of any Source or Product shall be with You and not
|
||||||
|
the Licensor. This disclaimer of warranty is an essential part
|
||||||
|
of this Licence and a condition for the grant of any rights
|
||||||
|
granted under this Licence.
|
||||||
|
|
||||||
|
6.2 EXCLUSION AND LIMITATION OF LIABILITY -- The Licensor shall, to
|
||||||
|
the maximum extent permitted by law, have no liability for
|
||||||
|
direct, indirect, special, incidental, consequential, exemplary,
|
||||||
|
punitive or other damages of any character including, without
|
||||||
|
limitation, procurement of substitute goods or services, loss of
|
||||||
|
use, data or profits, or business interruption, however caused
|
||||||
|
and on any theory of contract, warranty, tort (including
|
||||||
|
negligence), product liability or otherwise, arising in any way
|
||||||
|
in relation to the Covered Source, modified Covered Source
|
||||||
|
and/or the Making or Conveyance of a Product, even if advised of
|
||||||
|
the possibility of such damages, and You shall hold the
|
||||||
|
Licensor(s) free and harmless from any liability, costs,
|
||||||
|
damages, fees and expenses, including claims by third parties,
|
||||||
|
in relation to such use.
|
||||||
|
|
||||||
|
|
||||||
|
7 Patents
|
||||||
|
|
||||||
|
7.1 Subject to the terms and conditions of this Licence, each
|
||||||
|
Licensor hereby grants to You a perpetual, worldwide,
|
||||||
|
non-exclusive, no-charge, royalty-free, irrevocable (except as
|
||||||
|
stated in subsections 7.2 and 8.4) patent licence to Make, have
|
||||||
|
Made, use, offer to sell, sell, import, and otherwise transfer
|
||||||
|
the Covered Source and Products, where such licence applies only
|
||||||
|
to those patent claims licensable by such Licensor that are
|
||||||
|
necessarily infringed by exercising rights under the Covered
|
||||||
|
Source as Conveyed by that Licensor.
|
||||||
|
|
||||||
|
7.2 If You institute patent litigation against any entity (including
|
||||||
|
a cross-claim or counterclaim in a lawsuit) alleging that the
|
||||||
|
Covered Source or a Product constitutes direct or contributory
|
||||||
|
patent infringement, or You seek any declaration that a patent
|
||||||
|
licensed to You under this Licence is invalid or unenforceable
|
||||||
|
then any rights granted to You under this Licence shall
|
||||||
|
terminate as of the date such process is initiated.
|
||||||
|
|
||||||
|
|
||||||
|
8 General
|
||||||
|
|
||||||
|
8.1 If any provisions of this Licence are or subsequently become
|
||||||
|
invalid or unenforceable for any reason, the remaining
|
||||||
|
provisions shall remain effective.
|
||||||
|
|
||||||
|
8.2 You shall not use any of the name (including acronyms and
|
||||||
|
abbreviations), image, or logo by which the Licensor or CERN is
|
||||||
|
known, except where needed to comply with section 3, or where
|
||||||
|
the use is otherwise allowed by law. Any such permitted use
|
||||||
|
shall be factual and shall not be made so as to suggest any kind
|
||||||
|
of endorsement or implication of involvement by the Licensor or
|
||||||
|
its personnel.
|
||||||
|
|
||||||
|
8.3 CERN may publish updated versions and variants of this Licence
|
||||||
|
which it considers to be in the spirit of this version, but may
|
||||||
|
differ in detail to address new problems or concerns. New
|
||||||
|
versions will be published with a unique version number and a
|
||||||
|
variant identifier specifying the variant. If the Licensor has
|
||||||
|
specified that a given variant applies to the Covered Source
|
||||||
|
without specifying a version, You may treat that Covered Source
|
||||||
|
as being released under any version of the CERN-OHL with that
|
||||||
|
variant. If no variant is specified, the Covered Source shall be
|
||||||
|
treated as being released under CERN-OHL-S. The Licensor may
|
||||||
|
also specify that the Covered Source is subject to a specific
|
||||||
|
version of the CERN-OHL or any later version in which case You
|
||||||
|
may apply this or any later version of CERN-OHL with the same
|
||||||
|
variant identifier published by CERN.
|
||||||
|
|
||||||
|
8.4 This Licence shall terminate with immediate effect if You fail
|
||||||
|
to comply with any of its terms and conditions.
|
||||||
|
|
||||||
|
8.5 However, if You cease all breaches of this Licence, then Your
|
||||||
|
Licence from any Licensor is reinstated unless such Licensor has
|
||||||
|
terminated this Licence by giving You, while You remain in
|
||||||
|
breach, a notice specifying the breach and requiring You to cure
|
||||||
|
it within 30 days, and You have failed to come into compliance
|
||||||
|
in all material respects by the end of the 30 day period. Should
|
||||||
|
You repeat the breach after receipt of a cure notice and
|
||||||
|
subsequent reinstatement, this Licence will terminate
|
||||||
|
immediately and permanently. Section 6 shall continue to apply
|
||||||
|
after any termination.
|
||||||
|
|
||||||
|
8.6 This Licence shall not be enforceable except by a Licensor
|
||||||
|
acting as such, and third party beneficiary rights are
|
||||||
|
specifically excluded.
|
31
hw/pcb/ibom.config.ini
Normal file
31
hw/pcb/ibom.config.ini
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[html_defaults]
|
||||||
|
dark_mode=1
|
||||||
|
show_pads=1
|
||||||
|
show_fabrication=0
|
||||||
|
show_silkscreen=1
|
||||||
|
redraw_on_drag=1
|
||||||
|
highlight_pin1=selected
|
||||||
|
board_rotation=0
|
||||||
|
offset_back_rotation=0
|
||||||
|
checkboxes=Sourced,Placed
|
||||||
|
bom_view=left-right
|
||||||
|
layer_view=FB
|
||||||
|
compression=1
|
||||||
|
open_browser=0
|
||||||
|
[general]
|
||||||
|
bom_dest_dir=.
|
||||||
|
bom_name_format=%f_bom
|
||||||
|
component_sort_order=C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH
|
||||||
|
component_blacklist=
|
||||||
|
blacklist_virtual=1
|
||||||
|
blacklist_empty_val=0
|
||||||
|
include_tracks=0
|
||||||
|
include_nets=0
|
||||||
|
[fields]
|
||||||
|
show_fields=Value,Footprint,Notes
|
||||||
|
group_fields=Value,Footprint
|
||||||
|
normalize_field_case=0
|
||||||
|
board_variant_field=
|
||||||
|
board_variant_whitelist=
|
||||||
|
board_variant_blacklist=
|
||||||
|
dnp_field=kicad_dnp
|
4414
hw/pcb/sc64_hw_v2.0a_bom.html
generated
4414
hw/pcb/sc64_hw_v2.0a_bom.html
generated
File diff suppressed because one or more lines are too long
95785
hw/pcb/sc64v2.kicad_pcb
95785
hw/pcb/sc64v2.kicad_pcb
File diff suppressed because it is too large
Load Diff
@ -3,14 +3,17 @@
|
|||||||
"3dviewports": [],
|
"3dviewports": [],
|
||||||
"design_settings": {
|
"design_settings": {
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"board_outline_line_width": 0.09999999999999999,
|
"apply_defaults_to_fp_fields": false,
|
||||||
"copper_line_width": 0.19999999999999998,
|
"apply_defaults_to_fp_shapes": false,
|
||||||
|
"apply_defaults_to_fp_text": false,
|
||||||
|
"board_outline_line_width": 0.1,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
"copper_text_italic": false,
|
"copper_text_italic": false,
|
||||||
"copper_text_size_h": 1.5,
|
"copper_text_size_h": 1.5,
|
||||||
"copper_text_size_v": 1.5,
|
"copper_text_size_v": 1.5,
|
||||||
"copper_text_thickness": 0.3,
|
"copper_text_thickness": 0.3,
|
||||||
"copper_text_upright": false,
|
"copper_text_upright": false,
|
||||||
"courtyard_line_width": 0.049999999999999996,
|
"courtyard_line_width": 0.05,
|
||||||
"dimension_precision": 4,
|
"dimension_precision": 4,
|
||||||
"dimension_units": 3,
|
"dimension_units": 3,
|
||||||
"dimensions": {
|
"dimensions": {
|
||||||
@ -21,7 +24,7 @@
|
|||||||
"text_position": 0,
|
"text_position": 0,
|
||||||
"units_format": 1
|
"units_format": 1
|
||||||
},
|
},
|
||||||
"fab_line_width": 0.09999999999999999,
|
"fab_line_width": 0.1,
|
||||||
"fab_text_italic": false,
|
"fab_text_italic": false,
|
||||||
"fab_text_size_h": 1.0,
|
"fab_text_size_h": 1.0,
|
||||||
"fab_text_size_v": 1.0,
|
"fab_text_size_v": 1.0,
|
||||||
@ -34,9 +37,9 @@
|
|||||||
"other_text_thickness": 0.15,
|
"other_text_thickness": 0.15,
|
||||||
"other_text_upright": false,
|
"other_text_upright": false,
|
||||||
"pads": {
|
"pads": {
|
||||||
"drill": 0.762,
|
"drill": 2.5,
|
||||||
"height": 1.524,
|
"height": 2.5,
|
||||||
"width": 1.524
|
"width": 2.5
|
||||||
},
|
},
|
||||||
"silk_line_width": 0.15,
|
"silk_line_width": 0.15,
|
||||||
"silk_text_italic": false,
|
"silk_text_italic": false,
|
||||||
@ -63,20 +66,28 @@
|
|||||||
"rule_severities": {
|
"rule_severities": {
|
||||||
"annular_width": "error",
|
"annular_width": "error",
|
||||||
"clearance": "error",
|
"clearance": "error",
|
||||||
|
"connection_width": "warning",
|
||||||
"copper_edge_clearance": "error",
|
"copper_edge_clearance": "error",
|
||||||
|
"copper_sliver": "warning",
|
||||||
"courtyards_overlap": "error",
|
"courtyards_overlap": "error",
|
||||||
"diff_pair_gap_out_of_range": "error",
|
"diff_pair_gap_out_of_range": "error",
|
||||||
"diff_pair_uncoupled_length_too_long": "error",
|
"diff_pair_uncoupled_length_too_long": "error",
|
||||||
"drill_out_of_range": "error",
|
"drill_out_of_range": "error",
|
||||||
"duplicate_footprints": "warning",
|
"duplicate_footprints": "warning",
|
||||||
"extra_footprint": "warning",
|
"extra_footprint": "warning",
|
||||||
|
"footprint": "error",
|
||||||
|
"footprint_symbol_mismatch": "warning",
|
||||||
"footprint_type_mismatch": "error",
|
"footprint_type_mismatch": "error",
|
||||||
"hole_clearance": "error",
|
"hole_clearance": "error",
|
||||||
"hole_near_hole": "error",
|
"hole_near_hole": "error",
|
||||||
|
"holes_co_located": "warning",
|
||||||
"invalid_outline": "error",
|
"invalid_outline": "error",
|
||||||
|
"isolated_copper": "warning",
|
||||||
"item_on_disabled_layer": "error",
|
"item_on_disabled_layer": "error",
|
||||||
"items_not_allowed": "error",
|
"items_not_allowed": "error",
|
||||||
"length_out_of_range": "error",
|
"length_out_of_range": "error",
|
||||||
|
"lib_footprint_issues": "warning",
|
||||||
|
"lib_footprint_mismatch": "warning",
|
||||||
"malformed_courtyard": "error",
|
"malformed_courtyard": "error",
|
||||||
"microvia_drill_out_of_range": "error",
|
"microvia_drill_out_of_range": "error",
|
||||||
"missing_courtyard": "ignore",
|
"missing_courtyard": "ignore",
|
||||||
@ -86,9 +97,14 @@
|
|||||||
"padstack": "error",
|
"padstack": "error",
|
||||||
"pth_inside_courtyard": "ignore",
|
"pth_inside_courtyard": "ignore",
|
||||||
"shorting_items": "error",
|
"shorting_items": "error",
|
||||||
|
"silk_edge_clearance": "warning",
|
||||||
"silk_over_copper": "warning",
|
"silk_over_copper": "warning",
|
||||||
"silk_overlap": "warning",
|
"silk_overlap": "warning",
|
||||||
"skew_out_of_range": "error",
|
"skew_out_of_range": "error",
|
||||||
|
"solder_mask_bridge": "ignore",
|
||||||
|
"starved_thermal": "error",
|
||||||
|
"text_height": "warning",
|
||||||
|
"text_thickness": "warning",
|
||||||
"through_hole_pad_without_hole": "error",
|
"through_hole_pad_without_hole": "error",
|
||||||
"too_many_vias": "error",
|
"too_many_vias": "error",
|
||||||
"track_dangling": "warning",
|
"track_dangling": "warning",
|
||||||
@ -97,7 +113,6 @@
|
|||||||
"unconnected_items": "error",
|
"unconnected_items": "error",
|
||||||
"unresolved_variable": "error",
|
"unresolved_variable": "error",
|
||||||
"via_dangling": "warning",
|
"via_dangling": "warning",
|
||||||
"zone_has_empty_net": "error",
|
|
||||||
"zones_intersect": "error"
|
"zones_intersect": "error"
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
@ -105,25 +120,99 @@
|
|||||||
"allow_microvias": false,
|
"allow_microvias": false,
|
||||||
"max_error": 0.005,
|
"max_error": 0.005,
|
||||||
"min_clearance": 0.127,
|
"min_clearance": 0.127,
|
||||||
"min_copper_edge_clearance": 0.19999999999999998,
|
"min_connection": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.2,
|
||||||
"min_hole_clearance": 0.254,
|
"min_hole_clearance": 0.254,
|
||||||
"min_hole_to_hole": 0.5,
|
"min_hole_to_hole": 0.5,
|
||||||
"min_microvia_diameter": 0.19999999999999998,
|
"min_microvia_diameter": 0.2,
|
||||||
"min_microvia_drill": 0.09999999999999999,
|
"min_microvia_drill": 0.1,
|
||||||
|
"min_resolved_spokes": 2,
|
||||||
"min_silk_clearance": 0.0,
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_text_height": 0.8,
|
||||||
|
"min_text_thickness": 0.08,
|
||||||
"min_through_hole_diameter": 0.3,
|
"min_through_hole_diameter": 0.3,
|
||||||
"min_track_width": 0.127,
|
"min_track_width": 0.127,
|
||||||
"min_via_annular_width": 0.13,
|
"min_via_annular_width": 0.13,
|
||||||
"min_via_diameter": 0.6,
|
"min_via_diameter": 0.6,
|
||||||
"solder_mask_clearance": 0.0,
|
"solder_mask_clearance": 0.0,
|
||||||
"solder_mask_min_width": 0.0,
|
"solder_mask_min_width": 0.0,
|
||||||
|
"solder_mask_to_copper_clearance": 0.0,
|
||||||
"use_height_for_length_calcs": true
|
"use_height_for_length_calcs": true
|
||||||
},
|
},
|
||||||
|
"teardrop_options": [
|
||||||
|
{
|
||||||
|
"td_onpadsmd": true,
|
||||||
|
"td_onroundshapesonly": false,
|
||||||
|
"td_ontrackend": false,
|
||||||
|
"td_onviapad": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"teardrop_parameters": [
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_round_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_rect_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_track_end",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
}
|
||||||
|
],
|
||||||
"track_widths": [
|
"track_widths": [
|
||||||
0.0,
|
0.0,
|
||||||
0.508,
|
0.508,
|
||||||
0.762
|
0.762
|
||||||
],
|
],
|
||||||
|
"tuning_pattern_settings": {
|
||||||
|
"diff_pair_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 1.0
|
||||||
|
},
|
||||||
|
"diff_pair_skew_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
},
|
||||||
|
"single_track_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
"via_dimensions": [
|
"via_dimensions": [
|
||||||
{
|
{
|
||||||
"diameter": 0.0,
|
"diameter": 0.0,
|
||||||
@ -133,6 +222,13 @@
|
|||||||
"zones_allow_external_fillets": false,
|
"zones_allow_external_fillets": false,
|
||||||
"zones_use_no_outline": true
|
"zones_use_no_outline": true
|
||||||
},
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
"layer_presets": [],
|
"layer_presets": [],
|
||||||
"viewports": []
|
"viewports": []
|
||||||
},
|
},
|
||||||
@ -391,14 +487,94 @@
|
|||||||
"gencad": "",
|
"gencad": "",
|
||||||
"idf": "",
|
"idf": "",
|
||||||
"netlist": "",
|
"netlist": "",
|
||||||
|
"plot": "sc64v2.gerbers/",
|
||||||
|
"pos_files": "sc64v2.gerbers/",
|
||||||
"specctra_dsn": "",
|
"specctra_dsn": "",
|
||||||
"step": "",
|
"step": "",
|
||||||
|
"svg": "",
|
||||||
"vrml": ""
|
"vrml": ""
|
||||||
},
|
},
|
||||||
"page_layout_descr_file": ""
|
"page_layout_descr_file": ""
|
||||||
},
|
},
|
||||||
"schematic": {
|
"schematic": {
|
||||||
"annotate_start_num": 0,
|
"annotate_start_num": 0,
|
||||||
|
"bom_export_filename": "",
|
||||||
|
"bom_fmt_presets": [],
|
||||||
|
"bom_fmt_settings": {
|
||||||
|
"field_delimiter": ",",
|
||||||
|
"keep_line_breaks": false,
|
||||||
|
"keep_tabs": false,
|
||||||
|
"name": "CSV",
|
||||||
|
"ref_delimiter": ",",
|
||||||
|
"ref_range_delimiter": "",
|
||||||
|
"string_delimiter": "\""
|
||||||
|
},
|
||||||
|
"bom_presets": [],
|
||||||
|
"bom_settings": {
|
||||||
|
"exclude_dnp": false,
|
||||||
|
"fields_ordered": [
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Reference",
|
||||||
|
"name": "Reference",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Value",
|
||||||
|
"name": "Value",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Datasheet",
|
||||||
|
"name": "Datasheet",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Footprint",
|
||||||
|
"name": "Footprint",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Qty",
|
||||||
|
"name": "${QUANTITY}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "DNP",
|
||||||
|
"name": "${DNP}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "#",
|
||||||
|
"name": "${ITEM_NUMBER}",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Notes",
|
||||||
|
"name": "Notes",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Description",
|
||||||
|
"name": "Description",
|
||||||
|
"show": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filter_string": "",
|
||||||
|
"group_symbols": true,
|
||||||
|
"name": "",
|
||||||
|
"sort_asc": true,
|
||||||
|
"sort_field": "Reference"
|
||||||
|
},
|
||||||
|
"connection_grid_size": 50.0,
|
||||||
"drawing": {
|
"drawing": {
|
||||||
"dashed_lines_dash_length_ratio": 12.0,
|
"dashed_lines_dash_length_ratio": 12.0,
|
||||||
"dashed_lines_gap_length_ratio": 3.0,
|
"dashed_lines_gap_length_ratio": 3.0,
|
||||||
@ -412,6 +588,11 @@
|
|||||||
"intersheets_ref_suffix": "",
|
"intersheets_ref_suffix": "",
|
||||||
"junction_size_choice": 3,
|
"junction_size_choice": 3,
|
||||||
"label_size_ratio": 0.375,
|
"label_size_ratio": 0.375,
|
||||||
|
"operating_point_overlay_i_precision": 3,
|
||||||
|
"operating_point_overlay_i_range": "~A",
|
||||||
|
"operating_point_overlay_v_precision": 3,
|
||||||
|
"operating_point_overlay_v_range": "~V",
|
||||||
|
"overbar_offset_ratio": 1.23,
|
||||||
"pin_symbol_size": 25.0,
|
"pin_symbol_size": 25.0,
|
||||||
"text_offset_ratio": 0.15
|
"text_offset_ratio": 0.15
|
||||||
},
|
},
|
||||||
@ -437,6 +618,7 @@
|
|||||||
"spice_external_command": "spice \"%I\"",
|
"spice_external_command": "spice \"%I\"",
|
||||||
"spice_model_current_sheet_as_root": true,
|
"spice_model_current_sheet_as_root": true,
|
||||||
"spice_save_all_currents": false,
|
"spice_save_all_currents": false,
|
||||||
|
"spice_save_all_dissipations": false,
|
||||||
"spice_save_all_voltages": false,
|
"spice_save_all_voltages": false,
|
||||||
"subpart_first_id": 65,
|
"subpart_first_id": 65,
|
||||||
"subpart_id_separator": 0
|
"subpart_id_separator": 0
|
||||||
@ -444,7 +626,7 @@
|
|||||||
"sheets": [
|
"sheets": [
|
||||||
[
|
[
|
||||||
"e63e39d7-6ac0-4ffd-8aa3-1841a4541b55",
|
"e63e39d7-6ac0-4ffd-8aa3-1841a4541b55",
|
||||||
""
|
"Root"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"text_variables": {}
|
"text_variables": {}
|
||||||
|
52341
hw/pcb/sc64v2.kicad_sch
52341
hw/pcb/sc64v2.kicad_sch
File diff suppressed because it is too large
Load Diff
4669
hw/pcb/sc64v2_bom.html
generated
Normal file
4669
hw/pcb/sc64v2_bom.html
generated
Normal file
File diff suppressed because one or more lines are too long
12
hw/shell/README.md
Normal file
12
hw/shell/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# SummerCart64 shell design files
|
||||||
|
|
||||||
|
This folder contains several different designs of the SummerCart64 shell and button
|
||||||
|
|
||||||
|
`./` folder contains original design made by [Mateusz Faderewski 'Polprzewodnikowy'](https://github.com/Polprzewodnikowy) in the Autodesk Fusion 360 and exported `.stl` files ready for 3D print.
|
||||||
|
|
||||||
|
`./injection mold` folder contains adapted design for injection molding process by [Mena 'Pheeeeenom'](https://github.com/Pheeeeenom).
|
||||||
|
|
||||||
|
`./button` folder contains designs for the button on the back of the SummerCart64. Designs are:
|
||||||
|
- `sc64_shell_button_b3fs-101x.stl` - for the Omron B3FS-101x button (by [Mason Stooksbury](https://github.com/MasonStooksbury))
|
||||||
|
- `sc64_shell_button_b3fs-105x.step` - for the Omron B3FS-105x button (by [Mena 'Pheeeeenom'](https://github.com/Pheeeeenom))
|
||||||
|
- `sc64_shell_button_b3fs-105x_with_end_stop.step` - for the Omron B3FS-105x button but with additional flange to prevent it from coming out of the shell (by [Mena 'Pheeeeenom'](https://github.com/Pheeeeenom))
|
BIN
hw/shell/button/sc64_shell_button_b3fs-101x.stl
Normal file
BIN
hw/shell/button/sc64_shell_button_b3fs-101x.stl
Normal file
Binary file not shown.
600
hw/shell/button/sc64_shell_button_b3fs-105x.step
Normal file
600
hw/shell/button/sc64_shell_button_b3fs-105x.step
Normal file
@ -0,0 +1,600 @@
|
|||||||
|
ISO-10303-21;
|
||||||
|
HEADER;
|
||||||
|
/* Generated by software containing ST-Developer
|
||||||
|
* from STEP Tools, Inc. (www.steptools.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
FILE_DESCRIPTION(
|
||||||
|
/* description */ (''),
|
||||||
|
/* implementation_level */ '2;1');
|
||||||
|
|
||||||
|
FILE_NAME(
|
||||||
|
/* name */ 'sc64_shell_button v3.step',
|
||||||
|
/* time_stamp */ '2024-01-03T20:51:50-06:00',
|
||||||
|
/* author */ (''),
|
||||||
|
/* organization */ (''),
|
||||||
|
/* preprocessor_version */ 'ST-DEVELOPER v20',
|
||||||
|
/* originating_system */ 'Autodesk Translation Framework v12.14.0.127',
|
||||||
|
|
||||||
|
/* authorisation */ '');
|
||||||
|
|
||||||
|
FILE_SCHEMA (('AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }'));
|
||||||
|
ENDSEC;
|
||||||
|
|
||||||
|
DATA;
|
||||||
|
#10=MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#13),#504);
|
||||||
|
#11=SHAPE_REPRESENTATION_RELATIONSHIP('SRR','None',#510,#12);
|
||||||
|
#12=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#14),#503);
|
||||||
|
#13=STYLED_ITEM('',(#522),#14);
|
||||||
|
#14=MANIFOLD_SOLID_BREP('ButtonCap',#299);
|
||||||
|
#15=CYLINDRICAL_SURFACE('',#320,3.);
|
||||||
|
#16=TOROIDAL_SURFACE('',#316,2.8,0.2);
|
||||||
|
#17=ELLIPSE('',#309,57.3219678278922,3.);
|
||||||
|
#18=ELLIPSE('',#311,57.3219678278922,3.);
|
||||||
|
#19=ELLIPSE('',#315,57.3219678278922,3.);
|
||||||
|
#20=ELLIPSE('',#322,57.3219678278922,3.);
|
||||||
|
#21=CIRCLE('',#307,3.);
|
||||||
|
#22=CIRCLE('',#313,3.);
|
||||||
|
#23=CIRCLE('',#317,2.8);
|
||||||
|
#24=CIRCLE('',#318,0.2);
|
||||||
|
#25=CIRCLE('',#319,3.);
|
||||||
|
#26=CIRCLE('',#321,3.);
|
||||||
|
#27=CIRCLE('',#323,3.);
|
||||||
|
#28=CIRCLE('',#324,3.);
|
||||||
|
#29=FACE_OUTER_BOUND('',#45,.T.);
|
||||||
|
#30=FACE_OUTER_BOUND('',#46,.T.);
|
||||||
|
#31=FACE_OUTER_BOUND('',#47,.T.);
|
||||||
|
#32=FACE_OUTER_BOUND('',#48,.T.);
|
||||||
|
#33=FACE_OUTER_BOUND('',#49,.T.);
|
||||||
|
#34=FACE_OUTER_BOUND('',#50,.T.);
|
||||||
|
#35=FACE_OUTER_BOUND('',#51,.T.);
|
||||||
|
#36=FACE_OUTER_BOUND('',#52,.T.);
|
||||||
|
#37=FACE_OUTER_BOUND('',#53,.T.);
|
||||||
|
#38=FACE_OUTER_BOUND('',#54,.T.);
|
||||||
|
#39=FACE_OUTER_BOUND('',#55,.T.);
|
||||||
|
#40=FACE_OUTER_BOUND('',#56,.T.);
|
||||||
|
#41=FACE_OUTER_BOUND('',#57,.T.);
|
||||||
|
#42=FACE_OUTER_BOUND('',#58,.T.);
|
||||||
|
#43=FACE_OUTER_BOUND('',#59,.T.);
|
||||||
|
#44=FACE_OUTER_BOUND('',#60,.T.);
|
||||||
|
#45=EDGE_LOOP('',(#187,#188,#189,#190));
|
||||||
|
#46=EDGE_LOOP('',(#191,#192,#193,#194,#195,#196,#197,#198));
|
||||||
|
#47=EDGE_LOOP('',(#199,#200,#201,#202));
|
||||||
|
#48=EDGE_LOOP('',(#203,#204,#205,#206,#207,#208,#209,#210));
|
||||||
|
#49=EDGE_LOOP('',(#211,#212,#213,#214));
|
||||||
|
#50=EDGE_LOOP('',(#215,#216,#217,#218,#219,#220));
|
||||||
|
#51=EDGE_LOOP('',(#221,#222,#223,#224));
|
||||||
|
#52=EDGE_LOOP('',(#225,#226,#227,#228));
|
||||||
|
#53=EDGE_LOOP('',(#229,#230,#231,#232));
|
||||||
|
#54=EDGE_LOOP('',(#233,#234,#235,#236));
|
||||||
|
#55=EDGE_LOOP('',(#237,#238,#239,#240));
|
||||||
|
#56=EDGE_LOOP('',(#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,
|
||||||
|
#252));
|
||||||
|
#57=EDGE_LOOP('',(#253));
|
||||||
|
#58=EDGE_LOOP('',(#254,#255,#256,#257));
|
||||||
|
#59=EDGE_LOOP('',(#258,#259,#260,#261));
|
||||||
|
#60=EDGE_LOOP('',(#262,#263,#264,#265,#266,#267,#268));
|
||||||
|
#61=LINE('',#420,#90);
|
||||||
|
#62=LINE('',#422,#91);
|
||||||
|
#63=LINE('',#424,#92);
|
||||||
|
#64=LINE('',#425,#93);
|
||||||
|
#65=LINE('',#429,#94);
|
||||||
|
#66=LINE('',#431,#95);
|
||||||
|
#67=LINE('',#432,#96);
|
||||||
|
#68=LINE('',#434,#97);
|
||||||
|
#69=LINE('',#436,#98);
|
||||||
|
#70=LINE('',#438,#99);
|
||||||
|
#71=LINE('',#439,#100);
|
||||||
|
#72=LINE('',#442,#101);
|
||||||
|
#73=LINE('',#443,#102);
|
||||||
|
#74=LINE('',#447,#103);
|
||||||
|
#75=LINE('',#449,#104);
|
||||||
|
#76=LINE('',#451,#105);
|
||||||
|
#77=LINE('',#453,#106);
|
||||||
|
#78=LINE('',#454,#107);
|
||||||
|
#79=LINE('',#455,#108);
|
||||||
|
#80=LINE('',#457,#109);
|
||||||
|
#81=LINE('',#460,#110);
|
||||||
|
#82=LINE('',#463,#111);
|
||||||
|
#83=LINE('',#466,#112);
|
||||||
|
#84=LINE('',#471,#113);
|
||||||
|
#85=LINE('',#474,#114);
|
||||||
|
#86=LINE('',#478,#115);
|
||||||
|
#87=LINE('',#488,#116);
|
||||||
|
#88=LINE('',#497,#117);
|
||||||
|
#89=LINE('',#498,#118);
|
||||||
|
#90=VECTOR('',#333,10.);
|
||||||
|
#91=VECTOR('',#334,10.);
|
||||||
|
#92=VECTOR('',#335,10.);
|
||||||
|
#93=VECTOR('',#336,10.);
|
||||||
|
#94=VECTOR('',#339,10.);
|
||||||
|
#95=VECTOR('',#340,10.);
|
||||||
|
#96=VECTOR('',#341,10.);
|
||||||
|
#97=VECTOR('',#342,10.);
|
||||||
|
#98=VECTOR('',#343,10.);
|
||||||
|
#99=VECTOR('',#344,10.);
|
||||||
|
#100=VECTOR('',#345,10.);
|
||||||
|
#101=VECTOR('',#348,10.);
|
||||||
|
#102=VECTOR('',#349,10.);
|
||||||
|
#103=VECTOR('',#352,10.);
|
||||||
|
#104=VECTOR('',#353,10.);
|
||||||
|
#105=VECTOR('',#354,10.);
|
||||||
|
#106=VECTOR('',#355,10.);
|
||||||
|
#107=VECTOR('',#356,10.);
|
||||||
|
#108=VECTOR('',#357,10.);
|
||||||
|
#109=VECTOR('',#360,10.);
|
||||||
|
#110=VECTOR('',#363,10.);
|
||||||
|
#111=VECTOR('',#366,10.);
|
||||||
|
#112=VECTOR('',#369,10.);
|
||||||
|
#113=VECTOR('',#376,10.);
|
||||||
|
#114=VECTOR('',#379,10.);
|
||||||
|
#115=VECTOR('',#384,10.);
|
||||||
|
#116=VECTOR('',#397,3.);
|
||||||
|
#117=VECTOR('',#410,10.);
|
||||||
|
#118=VECTOR('',#411,10.);
|
||||||
|
#119=VERTEX_POINT('',#418);
|
||||||
|
#120=VERTEX_POINT('',#419);
|
||||||
|
#121=VERTEX_POINT('',#421);
|
||||||
|
#122=VERTEX_POINT('',#423);
|
||||||
|
#123=VERTEX_POINT('',#427);
|
||||||
|
#124=VERTEX_POINT('',#428);
|
||||||
|
#125=VERTEX_POINT('',#430);
|
||||||
|
#126=VERTEX_POINT('',#433);
|
||||||
|
#127=VERTEX_POINT('',#435);
|
||||||
|
#128=VERTEX_POINT('',#437);
|
||||||
|
#129=VERTEX_POINT('',#441);
|
||||||
|
#130=VERTEX_POINT('',#445);
|
||||||
|
#131=VERTEX_POINT('',#446);
|
||||||
|
#132=VERTEX_POINT('',#448);
|
||||||
|
#133=VERTEX_POINT('',#450);
|
||||||
|
#134=VERTEX_POINT('',#452);
|
||||||
|
#135=VERTEX_POINT('',#459);
|
||||||
|
#136=VERTEX_POINT('',#461);
|
||||||
|
#137=VERTEX_POINT('',#465);
|
||||||
|
#138=VERTEX_POINT('',#469);
|
||||||
|
#139=VERTEX_POINT('',#473);
|
||||||
|
#140=VERTEX_POINT('',#477);
|
||||||
|
#141=VERTEX_POINT('',#481);
|
||||||
|
#142=VERTEX_POINT('',#483);
|
||||||
|
#143=VERTEX_POINT('',#487);
|
||||||
|
#144=VERTEX_POINT('',#489);
|
||||||
|
#145=VERTEX_POINT('',#491);
|
||||||
|
#146=EDGE_CURVE('',#119,#120,#61,.T.);
|
||||||
|
#147=EDGE_CURVE('',#121,#119,#62,.T.);
|
||||||
|
#148=EDGE_CURVE('',#122,#121,#63,.T.);
|
||||||
|
#149=EDGE_CURVE('',#120,#122,#64,.T.);
|
||||||
|
#150=EDGE_CURVE('',#123,#124,#65,.T.);
|
||||||
|
#151=EDGE_CURVE('',#125,#123,#66,.T.);
|
||||||
|
#152=EDGE_CURVE('',#125,#119,#67,.T.);
|
||||||
|
#153=EDGE_CURVE('',#126,#120,#68,.T.);
|
||||||
|
#154=EDGE_CURVE('',#127,#126,#69,.T.);
|
||||||
|
#155=EDGE_CURVE('',#128,#127,#70,.T.);
|
||||||
|
#156=EDGE_CURVE('',#124,#128,#71,.T.);
|
||||||
|
#157=EDGE_CURVE('',#129,#125,#72,.T.);
|
||||||
|
#158=EDGE_CURVE('',#129,#121,#73,.T.);
|
||||||
|
#159=EDGE_CURVE('',#130,#131,#74,.T.);
|
||||||
|
#160=EDGE_CURVE('',#132,#130,#75,.T.);
|
||||||
|
#161=EDGE_CURVE('',#133,#132,#76,.T.);
|
||||||
|
#162=EDGE_CURVE('',#134,#133,#77,.T.);
|
||||||
|
#163=EDGE_CURVE('',#134,#122,#78,.T.);
|
||||||
|
#164=EDGE_CURVE('',#131,#129,#79,.T.);
|
||||||
|
#165=EDGE_CURVE('',#126,#134,#80,.T.);
|
||||||
|
#166=EDGE_CURVE('',#123,#135,#81,.F.);
|
||||||
|
#167=EDGE_CURVE('',#136,#135,#21,.T.);
|
||||||
|
#168=EDGE_CURVE('',#136,#131,#82,.F.);
|
||||||
|
#169=EDGE_CURVE('',#124,#137,#83,.F.);
|
||||||
|
#170=EDGE_CURVE('',#135,#137,#17,.T.);
|
||||||
|
#171=EDGE_CURVE('',#138,#136,#18,.T.);
|
||||||
|
#172=EDGE_CURVE('',#138,#130,#84,.F.);
|
||||||
|
#173=EDGE_CURVE('',#139,#128,#85,.F.);
|
||||||
|
#174=EDGE_CURVE('',#137,#139,#22,.T.);
|
||||||
|
#175=EDGE_CURVE('',#140,#127,#86,.F.);
|
||||||
|
#176=EDGE_CURVE('',#139,#140,#19,.T.);
|
||||||
|
#177=EDGE_CURVE('',#141,#141,#23,.T.);
|
||||||
|
#178=EDGE_CURVE('',#141,#142,#24,.T.);
|
||||||
|
#179=EDGE_CURVE('',#142,#142,#25,.T.);
|
||||||
|
#180=EDGE_CURVE('',#142,#143,#87,.T.);
|
||||||
|
#181=EDGE_CURVE('',#143,#144,#26,.T.);
|
||||||
|
#182=EDGE_CURVE('',#144,#145,#20,.T.);
|
||||||
|
#183=EDGE_CURVE('',#145,#138,#27,.T.);
|
||||||
|
#184=EDGE_CURVE('',#140,#143,#28,.T.);
|
||||||
|
#185=EDGE_CURVE('',#132,#145,#88,.F.);
|
||||||
|
#186=EDGE_CURVE('',#133,#144,#89,.F.);
|
||||||
|
#187=ORIENTED_EDGE('',*,*,#146,.F.);
|
||||||
|
#188=ORIENTED_EDGE('',*,*,#147,.F.);
|
||||||
|
#189=ORIENTED_EDGE('',*,*,#148,.F.);
|
||||||
|
#190=ORIENTED_EDGE('',*,*,#149,.F.);
|
||||||
|
#191=ORIENTED_EDGE('',*,*,#150,.F.);
|
||||||
|
#192=ORIENTED_EDGE('',*,*,#151,.F.);
|
||||||
|
#193=ORIENTED_EDGE('',*,*,#152,.T.);
|
||||||
|
#194=ORIENTED_EDGE('',*,*,#146,.T.);
|
||||||
|
#195=ORIENTED_EDGE('',*,*,#153,.F.);
|
||||||
|
#196=ORIENTED_EDGE('',*,*,#154,.F.);
|
||||||
|
#197=ORIENTED_EDGE('',*,*,#155,.F.);
|
||||||
|
#198=ORIENTED_EDGE('',*,*,#156,.F.);
|
||||||
|
#199=ORIENTED_EDGE('',*,*,#157,.F.);
|
||||||
|
#200=ORIENTED_EDGE('',*,*,#158,.T.);
|
||||||
|
#201=ORIENTED_EDGE('',*,*,#147,.T.);
|
||||||
|
#202=ORIENTED_EDGE('',*,*,#152,.F.);
|
||||||
|
#203=ORIENTED_EDGE('',*,*,#159,.F.);
|
||||||
|
#204=ORIENTED_EDGE('',*,*,#160,.F.);
|
||||||
|
#205=ORIENTED_EDGE('',*,*,#161,.F.);
|
||||||
|
#206=ORIENTED_EDGE('',*,*,#162,.F.);
|
||||||
|
#207=ORIENTED_EDGE('',*,*,#163,.T.);
|
||||||
|
#208=ORIENTED_EDGE('',*,*,#148,.T.);
|
||||||
|
#209=ORIENTED_EDGE('',*,*,#158,.F.);
|
||||||
|
#210=ORIENTED_EDGE('',*,*,#164,.F.);
|
||||||
|
#211=ORIENTED_EDGE('',*,*,#165,.F.);
|
||||||
|
#212=ORIENTED_EDGE('',*,*,#153,.T.);
|
||||||
|
#213=ORIENTED_EDGE('',*,*,#149,.T.);
|
||||||
|
#214=ORIENTED_EDGE('',*,*,#163,.F.);
|
||||||
|
#215=ORIENTED_EDGE('',*,*,#164,.T.);
|
||||||
|
#216=ORIENTED_EDGE('',*,*,#157,.T.);
|
||||||
|
#217=ORIENTED_EDGE('',*,*,#151,.T.);
|
||||||
|
#218=ORIENTED_EDGE('',*,*,#166,.T.);
|
||||||
|
#219=ORIENTED_EDGE('',*,*,#167,.F.);
|
||||||
|
#220=ORIENTED_EDGE('',*,*,#168,.T.);
|
||||||
|
#221=ORIENTED_EDGE('',*,*,#150,.T.);
|
||||||
|
#222=ORIENTED_EDGE('',*,*,#169,.T.);
|
||||||
|
#223=ORIENTED_EDGE('',*,*,#170,.F.);
|
||||||
|
#224=ORIENTED_EDGE('',*,*,#166,.F.);
|
||||||
|
#225=ORIENTED_EDGE('',*,*,#159,.T.);
|
||||||
|
#226=ORIENTED_EDGE('',*,*,#168,.F.);
|
||||||
|
#227=ORIENTED_EDGE('',*,*,#171,.F.);
|
||||||
|
#228=ORIENTED_EDGE('',*,*,#172,.T.);
|
||||||
|
#229=ORIENTED_EDGE('',*,*,#156,.T.);
|
||||||
|
#230=ORIENTED_EDGE('',*,*,#173,.F.);
|
||||||
|
#231=ORIENTED_EDGE('',*,*,#174,.F.);
|
||||||
|
#232=ORIENTED_EDGE('',*,*,#169,.F.);
|
||||||
|
#233=ORIENTED_EDGE('',*,*,#155,.T.);
|
||||||
|
#234=ORIENTED_EDGE('',*,*,#175,.F.);
|
||||||
|
#235=ORIENTED_EDGE('',*,*,#176,.F.);
|
||||||
|
#236=ORIENTED_EDGE('',*,*,#173,.T.);
|
||||||
|
#237=ORIENTED_EDGE('',*,*,#177,.T.);
|
||||||
|
#238=ORIENTED_EDGE('',*,*,#178,.T.);
|
||||||
|
#239=ORIENTED_EDGE('',*,*,#179,.T.);
|
||||||
|
#240=ORIENTED_EDGE('',*,*,#178,.F.);
|
||||||
|
#241=ORIENTED_EDGE('',*,*,#179,.F.);
|
||||||
|
#242=ORIENTED_EDGE('',*,*,#180,.T.);
|
||||||
|
#243=ORIENTED_EDGE('',*,*,#181,.T.);
|
||||||
|
#244=ORIENTED_EDGE('',*,*,#182,.T.);
|
||||||
|
#245=ORIENTED_EDGE('',*,*,#183,.T.);
|
||||||
|
#246=ORIENTED_EDGE('',*,*,#171,.T.);
|
||||||
|
#247=ORIENTED_EDGE('',*,*,#167,.T.);
|
||||||
|
#248=ORIENTED_EDGE('',*,*,#170,.T.);
|
||||||
|
#249=ORIENTED_EDGE('',*,*,#174,.T.);
|
||||||
|
#250=ORIENTED_EDGE('',*,*,#176,.T.);
|
||||||
|
#251=ORIENTED_EDGE('',*,*,#184,.T.);
|
||||||
|
#252=ORIENTED_EDGE('',*,*,#180,.F.);
|
||||||
|
#253=ORIENTED_EDGE('',*,*,#177,.F.);
|
||||||
|
#254=ORIENTED_EDGE('',*,*,#161,.T.);
|
||||||
|
#255=ORIENTED_EDGE('',*,*,#185,.T.);
|
||||||
|
#256=ORIENTED_EDGE('',*,*,#182,.F.);
|
||||||
|
#257=ORIENTED_EDGE('',*,*,#186,.F.);
|
||||||
|
#258=ORIENTED_EDGE('',*,*,#160,.T.);
|
||||||
|
#259=ORIENTED_EDGE('',*,*,#172,.F.);
|
||||||
|
#260=ORIENTED_EDGE('',*,*,#183,.F.);
|
||||||
|
#261=ORIENTED_EDGE('',*,*,#185,.F.);
|
||||||
|
#262=ORIENTED_EDGE('',*,*,#162,.T.);
|
||||||
|
#263=ORIENTED_EDGE('',*,*,#186,.T.);
|
||||||
|
#264=ORIENTED_EDGE('',*,*,#181,.F.);
|
||||||
|
#265=ORIENTED_EDGE('',*,*,#184,.F.);
|
||||||
|
#266=ORIENTED_EDGE('',*,*,#175,.T.);
|
||||||
|
#267=ORIENTED_EDGE('',*,*,#154,.T.);
|
||||||
|
#268=ORIENTED_EDGE('',*,*,#165,.T.);
|
||||||
|
#269=PLANE('',#301);
|
||||||
|
#270=PLANE('',#302);
|
||||||
|
#271=PLANE('',#303);
|
||||||
|
#272=PLANE('',#304);
|
||||||
|
#273=PLANE('',#305);
|
||||||
|
#274=PLANE('',#306);
|
||||||
|
#275=PLANE('',#308);
|
||||||
|
#276=PLANE('',#310);
|
||||||
|
#277=PLANE('',#312);
|
||||||
|
#278=PLANE('',#314);
|
||||||
|
#279=PLANE('',#325);
|
||||||
|
#280=PLANE('',#326);
|
||||||
|
#281=PLANE('',#327);
|
||||||
|
#282=PLANE('',#328);
|
||||||
|
#283=ADVANCED_FACE('',(#29),#269,.F.);
|
||||||
|
#284=ADVANCED_FACE('',(#30),#270,.F.);
|
||||||
|
#285=ADVANCED_FACE('',(#31),#271,.F.);
|
||||||
|
#286=ADVANCED_FACE('',(#32),#272,.F.);
|
||||||
|
#287=ADVANCED_FACE('',(#33),#273,.F.);
|
||||||
|
#288=ADVANCED_FACE('',(#34),#274,.F.);
|
||||||
|
#289=ADVANCED_FACE('',(#35),#275,.F.);
|
||||||
|
#290=ADVANCED_FACE('',(#36),#276,.F.);
|
||||||
|
#291=ADVANCED_FACE('',(#37),#277,.F.);
|
||||||
|
#292=ADVANCED_FACE('',(#38),#278,.F.);
|
||||||
|
#293=ADVANCED_FACE('',(#39),#16,.T.);
|
||||||
|
#294=ADVANCED_FACE('',(#40),#15,.T.);
|
||||||
|
#295=ADVANCED_FACE('',(#41),#279,.T.);
|
||||||
|
#296=ADVANCED_FACE('',(#42),#280,.F.);
|
||||||
|
#297=ADVANCED_FACE('',(#43),#281,.F.);
|
||||||
|
#298=ADVANCED_FACE('',(#44),#282,.F.);
|
||||||
|
#299=CLOSED_SHELL('',(#283,#284,#285,#286,#287,#288,#289,#290,#291,#292,
|
||||||
|
#293,#294,#295,#296,#297,#298));
|
||||||
|
#300=AXIS2_PLACEMENT_3D('',#416,#329,#330);
|
||||||
|
#301=AXIS2_PLACEMENT_3D('',#417,#331,#332);
|
||||||
|
#302=AXIS2_PLACEMENT_3D('',#426,#337,#338);
|
||||||
|
#303=AXIS2_PLACEMENT_3D('',#440,#346,#347);
|
||||||
|
#304=AXIS2_PLACEMENT_3D('',#444,#350,#351);
|
||||||
|
#305=AXIS2_PLACEMENT_3D('',#456,#358,#359);
|
||||||
|
#306=AXIS2_PLACEMENT_3D('',#458,#361,#362);
|
||||||
|
#307=AXIS2_PLACEMENT_3D('',#462,#364,#365);
|
||||||
|
#308=AXIS2_PLACEMENT_3D('',#464,#367,#368);
|
||||||
|
#309=AXIS2_PLACEMENT_3D('',#467,#370,#371);
|
||||||
|
#310=AXIS2_PLACEMENT_3D('',#468,#372,#373);
|
||||||
|
#311=AXIS2_PLACEMENT_3D('',#470,#374,#375);
|
||||||
|
#312=AXIS2_PLACEMENT_3D('',#472,#377,#378);
|
||||||
|
#313=AXIS2_PLACEMENT_3D('',#475,#380,#381);
|
||||||
|
#314=AXIS2_PLACEMENT_3D('',#476,#382,#383);
|
||||||
|
#315=AXIS2_PLACEMENT_3D('',#479,#385,#386);
|
||||||
|
#316=AXIS2_PLACEMENT_3D('',#480,#387,#388);
|
||||||
|
#317=AXIS2_PLACEMENT_3D('',#482,#389,#390);
|
||||||
|
#318=AXIS2_PLACEMENT_3D('',#484,#391,#392);
|
||||||
|
#319=AXIS2_PLACEMENT_3D('',#485,#393,#394);
|
||||||
|
#320=AXIS2_PLACEMENT_3D('',#486,#395,#396);
|
||||||
|
#321=AXIS2_PLACEMENT_3D('',#490,#398,#399);
|
||||||
|
#322=AXIS2_PLACEMENT_3D('',#492,#400,#401);
|
||||||
|
#323=AXIS2_PLACEMENT_3D('',#493,#402,#403);
|
||||||
|
#324=AXIS2_PLACEMENT_3D('',#494,#404,#405);
|
||||||
|
#325=AXIS2_PLACEMENT_3D('',#495,#406,#407);
|
||||||
|
#326=AXIS2_PLACEMENT_3D('',#496,#408,#409);
|
||||||
|
#327=AXIS2_PLACEMENT_3D('',#499,#412,#413);
|
||||||
|
#328=AXIS2_PLACEMENT_3D('',#500,#414,#415);
|
||||||
|
#329=DIRECTION('axis',(0.,0.,1.));
|
||||||
|
#330=DIRECTION('refdir',(1.,0.,0.));
|
||||||
|
#331=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#332=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#333=DIRECTION('',(-1.,0.,0.));
|
||||||
|
#334=DIRECTION('',(0.,1.,0.));
|
||||||
|
#335=DIRECTION('',(1.,0.,0.));
|
||||||
|
#336=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#337=DIRECTION('center_axis',(0.,1.,0.));
|
||||||
|
#338=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||||
|
#339=DIRECTION('',(-0.0523359562429438,0.,0.998629534754574));
|
||||||
|
#340=DIRECTION('',(-1.,0.,0.));
|
||||||
|
#341=DIRECTION('',(0.,0.,1.));
|
||||||
|
#342=DIRECTION('',(0.,0.,1.));
|
||||||
|
#343=DIRECTION('',(-1.,0.,0.));
|
||||||
|
#344=DIRECTION('',(-0.0523359562429438,0.,-0.998629534754574));
|
||||||
|
#345=DIRECTION('',(-1.,0.,0.));
|
||||||
|
#346=DIRECTION('center_axis',(1.,0.,0.));
|
||||||
|
#347=DIRECTION('ref_axis',(0.,1.,0.));
|
||||||
|
#348=DIRECTION('',(0.,1.,0.));
|
||||||
|
#349=DIRECTION('',(0.,0.,1.));
|
||||||
|
#350=DIRECTION('center_axis',(0.,-1.,0.));
|
||||||
|
#351=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#352=DIRECTION('',(0.0523359562429438,0.,-0.998629534754574));
|
||||||
|
#353=DIRECTION('',(1.,0.,0.));
|
||||||
|
#354=DIRECTION('',(0.0523359562429438,0.,0.998629534754574));
|
||||||
|
#355=DIRECTION('',(1.,0.,0.));
|
||||||
|
#356=DIRECTION('',(0.,0.,1.));
|
||||||
|
#357=DIRECTION('',(1.,0.,0.));
|
||||||
|
#358=DIRECTION('center_axis',(-1.,0.,0.));
|
||||||
|
#359=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||||
|
#360=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#361=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#362=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#363=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#364=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#365=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#366=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#367=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#368=DIRECTION('ref_axis',(0.,1.,0.));
|
||||||
|
#369=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#370=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#371=DIRECTION('ref_axis',(0.0523359562429438,0.,-0.998629534754574));
|
||||||
|
#372=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#373=DIRECTION('ref_axis',(0.,1.,0.));
|
||||||
|
#374=DIRECTION('center_axis',(0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#375=DIRECTION('ref_axis',(0.0523359562429438,0.,-0.998629534754574));
|
||||||
|
#376=DIRECTION('',(0.,-1.,0.));
|
||||||
|
#377=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#378=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#379=DIRECTION('',(0.,1.,0.));
|
||||||
|
#380=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#381=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#382=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#383=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||||
|
#384=DIRECTION('',(0.,1.,0.));
|
||||||
|
#385=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#386=DIRECTION('ref_axis',(0.0523359562429438,0.,0.998629534754574));
|
||||||
|
#387=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#388=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#389=DIRECTION('center_axis',(0.,0.,-1.));
|
||||||
|
#390=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#391=DIRECTION('center_axis',(0.,-1.,0.));
|
||||||
|
#392=DIRECTION('ref_axis',(-1.,0.,0.));
|
||||||
|
#393=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#394=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#395=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#396=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#397=DIRECTION('',(0.,0.,-1.));
|
||||||
|
#398=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#399=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#400=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#401=DIRECTION('ref_axis',(0.0523359562429438,0.,0.998629534754574));
|
||||||
|
#402=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#403=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#404=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#405=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#406=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#407=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#408=DIRECTION('center_axis',(-0.998629534754574,0.,0.0523359562429438));
|
||||||
|
#409=DIRECTION('ref_axis',(0.,-1.,0.));
|
||||||
|
#410=DIRECTION('',(0.,1.,0.));
|
||||||
|
#411=DIRECTION('',(0.,1.,0.));
|
||||||
|
#412=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#413=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#414=DIRECTION('center_axis',(0.,0.,1.));
|
||||||
|
#415=DIRECTION('ref_axis',(1.,0.,0.));
|
||||||
|
#416=CARTESIAN_POINT('',(0.,0.,0.));
|
||||||
|
#417=CARTESIAN_POINT('Origin',(-32.5,40.25,8.6));
|
||||||
|
#418=CARTESIAN_POINT('',(-31.25,41.5,8.6));
|
||||||
|
#419=CARTESIAN_POINT('',(-33.75,41.5,8.6));
|
||||||
|
#420=CARTESIAN_POINT('',(-33.75,41.5,8.6));
|
||||||
|
#421=CARTESIAN_POINT('',(-31.25,39.,8.6));
|
||||||
|
#422=CARTESIAN_POINT('',(-31.25,41.5,8.6));
|
||||||
|
#423=CARTESIAN_POINT('',(-33.75,39.,8.6));
|
||||||
|
#424=CARTESIAN_POINT('',(-31.25,39.,8.6));
|
||||||
|
#425=CARTESIAN_POINT('',(-33.75,39.,8.6));
|
||||||
|
#426=CARTESIAN_POINT('Origin',(-31.25,41.5,4.6));
|
||||||
|
#427=CARTESIAN_POINT('',(-31.3117572189413,41.5,4.6));
|
||||||
|
#428=CARTESIAN_POINT('',(-31.4165727775074,41.5,6.6));
|
||||||
|
#429=CARTESIAN_POINT('',(-31.3118701541713,41.5,4.60215493256167));
|
||||||
|
#430=CARTESIAN_POINT('',(-31.25,41.5,4.6));
|
||||||
|
#431=CARTESIAN_POINT('',(-31.875,41.5,4.6));
|
||||||
|
#432=CARTESIAN_POINT('',(-31.25,41.5,4.6));
|
||||||
|
#433=CARTESIAN_POINT('',(-33.75,41.5,4.6));
|
||||||
|
#434=CARTESIAN_POINT('',(-33.75,41.5,4.6));
|
||||||
|
#435=CARTESIAN_POINT('',(-33.6882427810587,41.5,4.6));
|
||||||
|
#436=CARTESIAN_POINT('',(-31.875,41.5,4.6));
|
||||||
|
#437=CARTESIAN_POINT('',(-33.5834272224926,41.5,6.6));
|
||||||
|
#438=CARTESIAN_POINT('',(-33.6847060304338,41.5,4.66748522210396));
|
||||||
|
#439=CARTESIAN_POINT('',(-31.875,41.5,6.6));
|
||||||
|
#440=CARTESIAN_POINT('Origin',(-31.25,39.,4.6));
|
||||||
|
#441=CARTESIAN_POINT('',(-31.25,39.,4.6));
|
||||||
|
#442=CARTESIAN_POINT('',(-31.25,39.625,4.6));
|
||||||
|
#443=CARTESIAN_POINT('',(-31.25,39.,4.6));
|
||||||
|
#444=CARTESIAN_POINT('Origin',(-33.75,39.,4.6));
|
||||||
|
#445=CARTESIAN_POINT('',(-31.4165727775074,39.,6.6));
|
||||||
|
#446=CARTESIAN_POINT('',(-31.3117572189413,39.,4.6));
|
||||||
|
#447=CARTESIAN_POINT('',(-31.3152939695662,39.,4.66748522210396));
|
||||||
|
#448=CARTESIAN_POINT('',(-33.5834272224926,39.,6.6));
|
||||||
|
#449=CARTESIAN_POINT('',(-33.125,39.,6.6));
|
||||||
|
#450=CARTESIAN_POINT('',(-33.6882427810587,39.,4.6));
|
||||||
|
#451=CARTESIAN_POINT('',(-33.6881298458287,39.,4.60215493256167));
|
||||||
|
#452=CARTESIAN_POINT('',(-33.75,39.,4.6));
|
||||||
|
#453=CARTESIAN_POINT('',(-33.125,39.,4.6));
|
||||||
|
#454=CARTESIAN_POINT('',(-33.75,39.,4.6));
|
||||||
|
#455=CARTESIAN_POINT('',(-33.125,39.,4.6));
|
||||||
|
#456=CARTESIAN_POINT('Origin',(-33.75,41.5,4.6));
|
||||||
|
#457=CARTESIAN_POINT('',(-33.75,40.875,4.6));
|
||||||
|
#458=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#459=CARTESIAN_POINT('',(-31.3117572189413,43.004646818244,4.6));
|
||||||
|
#460=CARTESIAN_POINT('',(-31.3117572189413,38.8190911978746,4.6));
|
||||||
|
#461=CARTESIAN_POINT('',(-31.3117572189413,37.495353181756,4.6));
|
||||||
|
#462=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#463=CARTESIAN_POINT('',(-31.3117572189413,38.8190911978746,4.6));
|
||||||
|
#464=CARTESIAN_POINT('Origin',(-31.312152245655,37.3881823957492,4.60753755871915));
|
||||||
|
#465=CARTESIAN_POINT('',(-31.4165727775074,43.0475320290502,6.6));
|
||||||
|
#466=CARTESIAN_POINT('',(-31.4165727775074,38.8190911978746,6.6));
|
||||||
|
#467=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879));
|
||||||
|
#468=CARTESIAN_POINT('Origin',(-31.312152245655,37.3881823957492,4.60753755871915));
|
||||||
|
#469=CARTESIAN_POINT('',(-31.4165727775074,37.4524679709498,6.6));
|
||||||
|
#470=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879));
|
||||||
|
#471=CARTESIAN_POINT('',(-31.4165727775074,38.8190911978746,6.6));
|
||||||
|
#472=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6));
|
||||||
|
#473=CARTESIAN_POINT('',(-33.5834272224926,43.0475320290502,6.6));
|
||||||
|
#474=CARTESIAN_POINT('',(-33.5834272224926,41.6809088021254,6.6));
|
||||||
|
#475=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6));
|
||||||
|
#476=CARTESIAN_POINT('Origin',(-33.687847754345,43.1118176042508,4.60753755871915));
|
||||||
|
#477=CARTESIAN_POINT('',(-33.6882427810587,43.004646818244,4.6));
|
||||||
|
#478=CARTESIAN_POINT('',(-33.6882427810587,41.6809088021254,4.6));
|
||||||
|
#479=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879));
|
||||||
|
#480=CARTESIAN_POINT('Origin',(-32.5,40.25,9.9));
|
||||||
|
#481=CARTESIAN_POINT('',(-35.3,40.25,10.1));
|
||||||
|
#482=CARTESIAN_POINT('Origin',(-32.5,40.25,10.1));
|
||||||
|
#483=CARTESIAN_POINT('',(-35.5,40.25,9.9));
|
||||||
|
#484=CARTESIAN_POINT('Origin',(-35.3,40.25,9.9));
|
||||||
|
#485=CARTESIAN_POINT('Origin',(-32.5,40.25,9.9));
|
||||||
|
#486=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#487=CARTESIAN_POINT('',(-35.5,40.25,4.59999999999997));
|
||||||
|
#488=CARTESIAN_POINT('',(-35.5,40.25,4.6));
|
||||||
|
#489=CARTESIAN_POINT('',(-33.6882427810587,37.495353181756,4.6));
|
||||||
|
#490=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#491=CARTESIAN_POINT('',(-33.5834272224926,37.4524679709498,6.6));
|
||||||
|
#492=CARTESIAN_POINT('Origin',(-32.5,40.25,27.2730229235879));
|
||||||
|
#493=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6));
|
||||||
|
#494=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#495=CARTESIAN_POINT('Origin',(-32.5,40.25,10.1));
|
||||||
|
#496=CARTESIAN_POINT('Origin',(-33.687847754345,43.1118176042508,4.60753755871915));
|
||||||
|
#497=CARTESIAN_POINT('',(-33.5834272224926,41.6809088021254,6.6));
|
||||||
|
#498=CARTESIAN_POINT('',(-33.6882427810587,41.6809088021254,4.6));
|
||||||
|
#499=CARTESIAN_POINT('Origin',(-32.5,40.25,6.6));
|
||||||
|
#500=CARTESIAN_POINT('Origin',(-32.5,40.25,4.6));
|
||||||
|
#501=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#505,
|
||||||
|
'DISTANCE_ACCURACY_VALUE',
|
||||||
|
'Maximum model space distance between geometric entities at asserted c
|
||||||
|
onnectivities');
|
||||||
|
#502=UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(0.01),#505,
|
||||||
|
'DISTANCE_ACCURACY_VALUE',
|
||||||
|
'Maximum model space distance between geometric entities at asserted c
|
||||||
|
onnectivities');
|
||||||
|
#503=(
|
||||||
|
GEOMETRIC_REPRESENTATION_CONTEXT(3)
|
||||||
|
GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#501))
|
||||||
|
GLOBAL_UNIT_ASSIGNED_CONTEXT((#505,#506,#507))
|
||||||
|
REPRESENTATION_CONTEXT('','3D')
|
||||||
|
);
|
||||||
|
#504=(
|
||||||
|
GEOMETRIC_REPRESENTATION_CONTEXT(3)
|
||||||
|
GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#502))
|
||||||
|
GLOBAL_UNIT_ASSIGNED_CONTEXT((#505,#506,#507))
|
||||||
|
REPRESENTATION_CONTEXT('','3D')
|
||||||
|
);
|
||||||
|
#505=(
|
||||||
|
LENGTH_UNIT()
|
||||||
|
NAMED_UNIT(*)
|
||||||
|
SI_UNIT(.MILLI.,.METRE.)
|
||||||
|
);
|
||||||
|
#506=(
|
||||||
|
NAMED_UNIT(*)
|
||||||
|
PLANE_ANGLE_UNIT()
|
||||||
|
SI_UNIT($,.RADIAN.)
|
||||||
|
);
|
||||||
|
#507=(
|
||||||
|
NAMED_UNIT(*)
|
||||||
|
SI_UNIT($,.STERADIAN.)
|
||||||
|
SOLID_ANGLE_UNIT()
|
||||||
|
);
|
||||||
|
#508=SHAPE_DEFINITION_REPRESENTATION(#509,#510);
|
||||||
|
#509=PRODUCT_DEFINITION_SHAPE('',$,#512);
|
||||||
|
#510=SHAPE_REPRESENTATION('',(#300),#503);
|
||||||
|
#511=PRODUCT_DEFINITION_CONTEXT('part definition',#516,'design');
|
||||||
|
#512=PRODUCT_DEFINITION('sc64_shell reworked','sc64_shell reworked v10',
|
||||||
|
#513,#511);
|
||||||
|
#513=PRODUCT_DEFINITION_FORMATION('',$,#518);
|
||||||
|
#514=PRODUCT_RELATED_PRODUCT_CATEGORY('sc64_shell reworked v10',
|
||||||
|
'sc64_shell reworked v10',(#518));
|
||||||
|
#515=APPLICATION_PROTOCOL_DEFINITION('international standard',
|
||||||
|
'automotive_design',2009,#516);
|
||||||
|
#516=APPLICATION_CONTEXT(
|
||||||
|
'Core Data for Automotive Mechanical Design Process');
|
||||||
|
#517=PRODUCT_CONTEXT('part definition',#516,'mechanical');
|
||||||
|
#518=PRODUCT('sc64_shell reworked','sc64_shell reworked v10',$,(#517));
|
||||||
|
#519=PRESENTATION_STYLE_ASSIGNMENT((#523));
|
||||||
|
#520=PRESENTATION_STYLE_ASSIGNMENT((#524));
|
||||||
|
#521=PRESENTATION_STYLE_ASSIGNMENT((#525));
|
||||||
|
#522=PRESENTATION_STYLE_ASSIGNMENT((#526));
|
||||||
|
#523=SURFACE_STYLE_USAGE(.BOTH.,#527);
|
||||||
|
#524=SURFACE_STYLE_USAGE(.BOTH.,#528);
|
||||||
|
#525=SURFACE_STYLE_USAGE(.BOTH.,#529);
|
||||||
|
#526=SURFACE_STYLE_USAGE(.BOTH.,#530);
|
||||||
|
#527=SURFACE_SIDE_STYLE('',(#531));
|
||||||
|
#528=SURFACE_SIDE_STYLE('',(#532));
|
||||||
|
#529=SURFACE_SIDE_STYLE('',(#533));
|
||||||
|
#530=SURFACE_SIDE_STYLE('',(#534));
|
||||||
|
#531=SURFACE_STYLE_FILL_AREA(#535);
|
||||||
|
#532=SURFACE_STYLE_FILL_AREA(#536);
|
||||||
|
#533=SURFACE_STYLE_FILL_AREA(#537);
|
||||||
|
#534=SURFACE_STYLE_FILL_AREA(#538);
|
||||||
|
#535=FILL_AREA_STYLE('Steel - Satin',(#539));
|
||||||
|
#536=FILL_AREA_STYLE('Plastic - Translucent Matte (Blue)',(#540));
|
||||||
|
#537=FILL_AREA_STYLE('Powder Coat - Rough (White)',(#541));
|
||||||
|
#538=FILL_AREA_STYLE('Plastic - Glossy (Black)',(#542));
|
||||||
|
#539=FILL_AREA_STYLE_COLOUR('Steel - Satin',#543);
|
||||||
|
#540=FILL_AREA_STYLE_COLOUR('Plastic - Translucent Matte (Blue)',#544);
|
||||||
|
#541=FILL_AREA_STYLE_COLOUR('Powder Coat - Rough (White)',#545);
|
||||||
|
#542=FILL_AREA_STYLE_COLOUR('Plastic - Glossy (Black)',#546);
|
||||||
|
#543=COLOUR_RGB('Steel - Satin',0.627450980392157,0.627450980392157,0.627450980392157);
|
||||||
|
#544=COLOUR_RGB('Plastic - Translucent Matte (Blue)',0.188235294117647,
|
||||||
|
0.231372549019608,0.588235294117647);
|
||||||
|
#545=COLOUR_RGB('Powder Coat - Rough (White)',0.964705882352941,0.964705882352941,
|
||||||
|
0.952941176470588);
|
||||||
|
#546=COLOUR_RGB('Plastic - Glossy (Black)',0.0980392156862745,0.0980392156862745,
|
||||||
|
0.0980392156862745);
|
||||||
|
ENDSEC;
|
||||||
|
END-ISO-10303-21;
|
1367
hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step
Normal file
1367
hw/shell/button/sc64_shell_button_b3fs-105x_with_end_stop.step
Normal file
File diff suppressed because it is too large
Load Diff
27534
hw/shell/injection mold/sc64_bottom.step
Normal file
27534
hw/shell/injection mold/sc64_bottom.step
Normal file
File diff suppressed because it is too large
Load Diff
41323
hw/shell/injection mold/sc64_shell.stp
Normal file
41323
hw/shell/injection mold/sc64_shell.stp
Normal file
File diff suppressed because it is too large
Load Diff
18846
hw/shell/injection mold/sc64_top.step
Normal file
18846
hw/shell/injection mold/sc64_top.step
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ N64_ELFCOMPRESS = $(N64_BINDIR)/n64elfcompress
|
|||||||
N64_TOOL = $(N64_BINDIR)/n64tool
|
N64_TOOL = $(N64_BINDIR)/n64tool
|
||||||
PYTHON = python3
|
PYTHON = python3
|
||||||
|
|
||||||
FLAGS = -march=vr4300 -mtune=vr4300 $(USER_FLAGS)
|
FLAGS = -march=vr4300 -mtune=vr4300 -mfix4300 $(USER_FLAGS)
|
||||||
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
|
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
|
||||||
ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib
|
ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib
|
||||||
LDFLAGS = -lc -nostartfiles -Wl,--gc-sections
|
LDFLAGS = -lc -nostartfiles -Wl,--gc-sections
|
||||||
@ -31,8 +31,10 @@ SRC_FILES = \
|
|||||||
exception.S \
|
exception.S \
|
||||||
font.c \
|
font.c \
|
||||||
init.c \
|
init.c \
|
||||||
interrupt.c \
|
interrupts.c \
|
||||||
|
interrupts.S \
|
||||||
io.c \
|
io.c \
|
||||||
|
joybus.c \
|
||||||
main.c \
|
main.c \
|
||||||
menu.c \
|
menu.c \
|
||||||
reboot.S \
|
reboot.S \
|
||||||
|
@ -79,6 +79,7 @@ void boot (boot_params_t *params) {
|
|||||||
while (cpu_io_read(&SP->DMA_BUSY));
|
while (cpu_io_read(&SP->DMA_BUSY));
|
||||||
|
|
||||||
cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET);
|
cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET);
|
||||||
|
cpu_io_write(&SI->SR, 0);
|
||||||
while ((cpu_io_read(&VI->CURR_LINE) & ~(VI_CURR_LINE_FIELD)) != 0);
|
while ((cpu_io_read(&VI->CURR_LINE) & ~(VI_CURR_LINE_FIELD)) != 0);
|
||||||
cpu_io_write(&VI->V_INTR, 0x3FF);
|
cpu_io_write(&VI->V_INTR, 0x3FF);
|
||||||
cpu_io_write(&VI->H_LIMITS, 0);
|
cpu_io_write(&VI->H_LIMITS, 0);
|
||||||
@ -146,5 +147,5 @@ void boot (boot_params_t *params) {
|
|||||||
"t3"
|
"t3"
|
||||||
);
|
);
|
||||||
|
|
||||||
while (1);
|
while (true);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
@ -117,8 +116,8 @@ static void display_draw_character (char c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((char_x + FONT_WIDTH) > (SCREEN_WIDTH - BORDER_WIDTH)) {
|
if ((char_x + FONT_WIDTH) > (SCREEN_WIDTH - BORDER_WIDTH)) {
|
||||||
char_x = BORDER_WIDTH;
|
char_x -= FONT_WIDTH;
|
||||||
char_y += FONT_HEIGHT + LINE_SPACING;
|
c = '\x7F';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c < ' ') || (c > '~')) {
|
if ((c < ' ') || (c > '~')) {
|
||||||
@ -181,8 +180,12 @@ void display_init (uint32_t *background) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool display_ready (void) {
|
||||||
|
return vi_configured;
|
||||||
|
}
|
||||||
|
|
||||||
void display_vprintf (const char *fmt, va_list args) {
|
void display_vprintf (const char *fmt, va_list args) {
|
||||||
char line[256];
|
char line[1024];
|
||||||
|
|
||||||
vsniprintf(line, sizeof(line), fmt, args);
|
vsniprintf(line, sizeof(line), fmt, args);
|
||||||
display_draw_string(line);
|
display_draw_string(line);
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
void display_init (uint32_t *background);
|
void display_init (uint32_t *background);
|
||||||
|
bool display_ready (void);
|
||||||
void display_vprintf (const char *fmt, va_list args);
|
void display_vprintf (const char *fmt, va_list args);
|
||||||
void display_printf (const char* fmt, ...);
|
void display_printf (const char* fmt, ...);
|
||||||
|
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "exception.h"
|
#include "display.h"
|
||||||
|
#include "init.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "../assets/assets.h"
|
||||||
|
|
||||||
|
|
||||||
void error_display (const char *fmt, ...) {
|
void error_display (const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start(args, fmt);
|
deinit();
|
||||||
EXCEPTION_TRIGGER(TRIGGER_CODE_ERROR);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
while (1);
|
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||||
|
|
||||||
|
version_print();
|
||||||
|
display_printf("[ Runtime error ]\n");
|
||||||
|
va_start(args, fmt);
|
||||||
|
display_vprintf(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
display_printf("\n");
|
||||||
|
|
||||||
|
while (true);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#include "vr4300.h"
|
#include "vr4300.h"
|
||||||
|
|
||||||
|
|
||||||
#define WATCHDOG_TIMEOUT (5 * (93750000UL / 2))
|
|
||||||
|
|
||||||
#define ZR_OFFSET (0)
|
#define ZR_OFFSET (0)
|
||||||
#define AT_OFFSET (8)
|
#define AT_OFFSET (8)
|
||||||
#define V0_OFFSET (16)
|
#define V0_OFFSET (16)
|
||||||
@ -35,11 +33,13 @@
|
|||||||
#define SP_OFFSET (232)
|
#define SP_OFFSET (232)
|
||||||
#define S8_OFFSET (240)
|
#define S8_OFFSET (240)
|
||||||
#define RA_OFFSET (248)
|
#define RA_OFFSET (248)
|
||||||
#define C0_STATUS_OFFSET (256)
|
#define HI_OFFSET (256)
|
||||||
#define C0_CAUSE_OFFSET (260)
|
#define LO_OFFSET (264)
|
||||||
#define C0_EPC_OFFSET (264)
|
#define C0_EPC_OFFSET (272)
|
||||||
#define C0_BADVADDR_OFFSET (272)
|
#define C0_BADVADDR_OFFSET (280)
|
||||||
#define SAVE_REGISTERS_SIZE (280)
|
#define C0_STATUS_OFFSET (288)
|
||||||
|
#define C0_CAUSE_OFFSET (292)
|
||||||
|
#define SAVE_REGISTERS_SIZE (296)
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_vector
|
.section .text.exception_vector
|
||||||
@ -51,14 +51,18 @@ exception_xtlb_miss:
|
|||||||
.org 0x0080
|
.org 0x0080
|
||||||
j exception_handler
|
j exception_handler
|
||||||
|
|
||||||
|
exception_ecc:
|
||||||
|
.org 0x0100
|
||||||
|
j exception_handler
|
||||||
|
|
||||||
exception_other:
|
exception_other:
|
||||||
.org 0x0180
|
.org 0x0180
|
||||||
j exception_handler
|
j exception_handler
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_handler
|
.section .text.exception_handler
|
||||||
|
.type exception_handler, %function
|
||||||
exception_handler:
|
exception_handler:
|
||||||
.type exception_handler, %function
|
|
||||||
.set noat
|
.set noat
|
||||||
la $k0, (_esp - SAVE_REGISTERS_SIZE)
|
la $k0, (_esp - SAVE_REGISTERS_SIZE)
|
||||||
sd $zero, ZR_OFFSET($k0)
|
sd $zero, ZR_OFFSET($k0)
|
||||||
@ -91,22 +95,20 @@ exception_handler:
|
|||||||
sd $sp, SP_OFFSET($k0)
|
sd $sp, SP_OFFSET($k0)
|
||||||
sd $s8, S8_OFFSET($k0)
|
sd $s8, S8_OFFSET($k0)
|
||||||
sd $ra, RA_OFFSET($k0)
|
sd $ra, RA_OFFSET($k0)
|
||||||
|
mfhi $t0
|
||||||
|
mflo $t1
|
||||||
|
sd $t0, HI_OFFSET($k0)
|
||||||
|
sd $t1, LO_OFFSET($k0)
|
||||||
.set at
|
.set at
|
||||||
|
|
||||||
move $sp, $k0
|
move $sp, $k0
|
||||||
|
|
||||||
exception_check_type:
|
exception_check_type:
|
||||||
mfc0 $a0, C0_CAUSE
|
mfc0 $t0, C0_CAUSE
|
||||||
sw $a0, C0_CAUSE_OFFSET($k0)
|
sw $t0, C0_CAUSE_OFFSET($k0)
|
||||||
move $a1, $a0
|
andi $a0, $t0, C0_CR_EC_MASK
|
||||||
move $t0, $a0
|
srl $a0, C0_CR_EC_BIT
|
||||||
andi $t0, C0_CR_IP7
|
beqz $a0, exception_interrupt
|
||||||
andi $a0, C0_CR_EC_MASK
|
|
||||||
srl $a0, $a0, C0_CR_EC_BIT
|
|
||||||
andi $a1, C0_CR_IP_MASK
|
|
||||||
srl $a1, $a1, C0_CR_IP_BIT
|
|
||||||
bne $t0, $zero, exception_fatal
|
|
||||||
beq $a0, $zero, exception_interrupt
|
|
||||||
|
|
||||||
exception_fatal:
|
exception_fatal:
|
||||||
sd $k0, K0_OFFSET($k0)
|
sd $k0, K0_OFFSET($k0)
|
||||||
@ -117,19 +119,27 @@ exception_fatal:
|
|||||||
sd $t0, C0_EPC_OFFSET($k0)
|
sd $t0, C0_EPC_OFFSET($k0)
|
||||||
dmfc0 $t0, C0_BADVADDR
|
dmfc0 $t0, C0_BADVADDR
|
||||||
sd $t0, C0_BADVADDR_OFFSET($k0)
|
sd $t0, C0_BADVADDR_OFFSET($k0)
|
||||||
move $a2, $k0
|
move $a1, $k0
|
||||||
la $t1, exception_fatal_handler
|
jal exception_fatal_handler
|
||||||
jalr $t1
|
|
||||||
ld $t0, C0_EPC_OFFSET($k0)
|
ld $t0, C0_EPC_OFFSET($k0)
|
||||||
dmtc0 $t0, C0_EPC
|
dmtc0 $t0, C0_EPC
|
||||||
j exception_restore
|
j exception_restore
|
||||||
|
|
||||||
exception_interrupt:
|
exception_interrupt:
|
||||||
la $t1, exception_interrupt_handler
|
andi $a0, $t0, C0_CR_IP_MASK
|
||||||
jalr $t1
|
srl $a0, C0_CR_IP_BIT
|
||||||
|
mfc0 $t0, C0_STATUS
|
||||||
|
andi $t0, C0_SR_IM_MASK
|
||||||
|
srl $t0, C0_SR_IM_BIT
|
||||||
|
and $a0, $t0
|
||||||
|
jal interrupts_handler
|
||||||
|
|
||||||
exception_restore:
|
exception_restore:
|
||||||
.set noat
|
.set noat
|
||||||
|
ld $t0, HI_OFFSET($k0)
|
||||||
|
ld $t1, LO_OFFSET($k0)
|
||||||
|
mthi $t0
|
||||||
|
mtlo $t1
|
||||||
ld $at, AT_OFFSET($k0)
|
ld $at, AT_OFFSET($k0)
|
||||||
ld $v0, V0_OFFSET($k0)
|
ld $v0, V0_OFFSET($k0)
|
||||||
ld $v1, V1_OFFSET($k0)
|
ld $v1, V1_OFFSET($k0)
|
||||||
@ -162,51 +172,3 @@ exception_restore:
|
|||||||
.set at
|
.set at
|
||||||
|
|
||||||
eret
|
eret
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_enable_interrupts
|
|
||||||
exception_enable_interrupts:
|
|
||||||
.type exception_enable_interrupts, %function
|
|
||||||
.global exception_enable_interrupts
|
|
||||||
mfc0 $t0, C0_STATUS
|
|
||||||
li $t1, C0_SR_IE
|
|
||||||
or $t0, $t0, $t1
|
|
||||||
mtc0 $t0, C0_STATUS
|
|
||||||
jr $ra
|
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_disable_interrupts
|
|
||||||
exception_disable_interrupts:
|
|
||||||
.type exception_disable_interrupts, %function
|
|
||||||
.global exception_disable_interrupts
|
|
||||||
mfc0 $t0, C0_STATUS
|
|
||||||
li $t1, ~(C0_SR_IE)
|
|
||||||
and $t0, $t0, $t1
|
|
||||||
mtc0 $t0, C0_STATUS
|
|
||||||
jr $ra
|
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_enable_watchdog
|
|
||||||
exception_enable_watchdog:
|
|
||||||
.type exception_enable_watchdog, %function
|
|
||||||
.global exception_enable_watchdog
|
|
||||||
mtc0 $zero, C0_COUNT
|
|
||||||
li $t1, WATCHDOG_TIMEOUT
|
|
||||||
mtc0 $t1, C0_COMPARE
|
|
||||||
mfc0 $t0, C0_STATUS
|
|
||||||
li $t1, C0_SR_IM7
|
|
||||||
or $t0, $t0, $t1
|
|
||||||
mtc0 $t0, C0_STATUS
|
|
||||||
jr $ra
|
|
||||||
|
|
||||||
|
|
||||||
.section .text.exception_disable_watchdog
|
|
||||||
exception_disable_watchdog:
|
|
||||||
.type exception_disable_watchdog, %function
|
|
||||||
.global exception_disable_watchdog
|
|
||||||
mfc0 $t0, C0_STATUS
|
|
||||||
li $t1, ~(C0_SR_IM7)
|
|
||||||
and $t0, $t0, $t1
|
|
||||||
mtc0 $t0, C0_STATUS
|
|
||||||
mtc0 $zero, C0_COMPARE
|
|
||||||
jr $ra
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "exception_regs.h"
|
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -8,15 +7,6 @@
|
|||||||
#include "../assets/assets.h"
|
#include "../assets/assets.h"
|
||||||
|
|
||||||
|
|
||||||
#define EXCEPTION_INTERRUPT (0)
|
|
||||||
#define EXCEPTION_SYSCALL (8)
|
|
||||||
|
|
||||||
#define INTERRUPT_MASK_TIMER (1 << 7)
|
|
||||||
|
|
||||||
#define SYSCALL_CODE_MASK (0x03FFFFC0UL)
|
|
||||||
#define SYSCALL_CODE_BIT (6)
|
|
||||||
|
|
||||||
|
|
||||||
static const char *exception_get_description (uint8_t exception_code) {
|
static const char *exception_get_description (uint8_t exception_code) {
|
||||||
switch (exception_code) {
|
switch (exception_code) {
|
||||||
case 0: return "Interrupt";
|
case 0: return "Interrupt";
|
||||||
@ -41,48 +31,24 @@ static const char *exception_get_description (uint8_t exception_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
|
void exception_fatal_handler (uint32_t exception_code, exception_t *e) {
|
||||||
version_t *version = version_get();
|
|
||||||
uint32_t *instruction_address = (((uint32_t *) (e->epc.u32)) + ((e->cr & C0_CR_BD) ? 1 : 0));
|
|
||||||
|
|
||||||
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||||
|
|
||||||
display_printf("[ SC64 bootloader metadata ]\n");
|
uint32_t exception_address = e->epc.u32 + (e->cr & C0_CR_BD ? 4 : 0);
|
||||||
display_printf("branch: %s | tag: %s\n", version->git_branch, version->git_tag);
|
|
||||||
display_printf("sha: %s\n", version->git_sha);
|
|
||||||
display_printf("msg: %s\n\n", version->git_message);
|
|
||||||
|
|
||||||
if (exception_code != EXCEPTION_SYSCALL) {
|
version_print();
|
||||||
display_printf("%s\n", exception_get_description(exception_code));
|
display_printf("[ Unhandled exception ] @ 0x%08X\n", exception_address);
|
||||||
display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32);
|
display_printf("%s\n", exception_get_description(exception_code));
|
||||||
display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32);
|
display_printf(" pc: 0x%08lX sr: 0x%08lX cr: 0x%08lX va: 0x%08lX\n", e->epc.u32, e->sr, e->cr, e->badvaddr.u32);
|
||||||
display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32);
|
display_printf(" zr: 0x%08lX at: 0x%08lX v0: 0x%08lX v1: 0x%08lX\n", e->zr.u32, e->at.u32, e->v0.u32, e->v1.u32);
|
||||||
display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32);
|
display_printf(" a0: 0x%08lX a1: 0x%08lX a2: 0x%08lX a3: 0x%08lX\n", e->a0.u32, e->a1.u32, e->a2.u32, e->a3.u32);
|
||||||
display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32);
|
display_printf(" t0: 0x%08lX t1: 0x%08lX t2: 0x%08lX t3: 0x%08lX\n", e->t0.u32, e->t1.u32, e->t2.u32, e->t3.u32);
|
||||||
display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32);
|
display_printf(" t4: 0x%08lX t5: 0x%08lX t6: 0x%08lX t7: 0x%08lX\n", e->t4.u32, e->t5.u32, e->t6.u32, e->t7.u32);
|
||||||
display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32);
|
display_printf(" s0: 0x%08lX s1: 0x%08lX s2: 0x%08lX s3: 0x%08lX\n", e->s0.u32, e->s1.u32, e->s2.u32, e->s3.u32);
|
||||||
display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32);
|
display_printf(" s4: 0x%08lX s5: 0x%08lX s6: 0x%08lX s7: 0x%08lX\n", e->s4.u32, e->s5.u32, e->s6.u32, e->s7.u32);
|
||||||
display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32);
|
display_printf(" t8: 0x%08lX t9: 0x%08lX k0: 0x%08lX k1: 0x%08lX\n", e->t8.u32, e->t9.u32, e->k0.u32, e->k1.u32);
|
||||||
} else {
|
display_printf(" gp: 0x%08lX sp: 0x%08lX s8: 0x%08lX ra: 0x%08lX\n", e->gp.u32, e->sp.u32, e->s8.u32, e->ra.u32);
|
||||||
display_printf("[ Runtime error ]\n");
|
display_printf(" hi: 0x%016lX lo: 0x%016lX\n", e->hi.u64, e->lo.u64);
|
||||||
}
|
|
||||||
|
|
||||||
if (exception_code == EXCEPTION_INTERRUPT) {
|
while (true);
|
||||||
if (interrupt_mask & INTERRUPT_MASK_TIMER) {
|
|
||||||
exception_disable_watchdog();
|
|
||||||
display_printf("Still loading after 5 second limit...\n\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (exception_code == EXCEPTION_SYSCALL) {
|
|
||||||
uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT);
|
|
||||||
|
|
||||||
if (code == TRIGGER_CODE_ERROR) {
|
|
||||||
const char *fmt = (const char *) (e->a0.u32);
|
|
||||||
va_list args = *((va_list *) (e->sp.u32));
|
|
||||||
display_vprintf(fmt, args);
|
|
||||||
display_printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1);
|
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,57 @@
|
|||||||
#define EXCEPTION_H__
|
#define EXCEPTION_H__
|
||||||
|
|
||||||
|
|
||||||
#define TRIGGER_CODE_ERROR (0)
|
#include <stdint.h>
|
||||||
|
|
||||||
#define EXCEPTION_TRIGGER(code) { asm volatile ("syscall %[c]\n" :: [c] "i" (code)); }
|
|
||||||
|
|
||||||
|
|
||||||
void exception_enable_interrupts (void);
|
typedef union {
|
||||||
void exception_disable_interrupts (void);
|
uint64_t u64;
|
||||||
void exception_enable_watchdog (void);
|
struct {
|
||||||
void exception_disable_watchdog (void);
|
uint32_t u32_h;
|
||||||
|
uint32_t u32;
|
||||||
|
};
|
||||||
|
} uint64_32_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_32_t zr;
|
||||||
|
uint64_32_t at;
|
||||||
|
uint64_32_t v0;
|
||||||
|
uint64_32_t v1;
|
||||||
|
uint64_32_t a0;
|
||||||
|
uint64_32_t a1;
|
||||||
|
uint64_32_t a2;
|
||||||
|
uint64_32_t a3;
|
||||||
|
uint64_32_t t0;
|
||||||
|
uint64_32_t t1;
|
||||||
|
uint64_32_t t2;
|
||||||
|
uint64_32_t t3;
|
||||||
|
uint64_32_t t4;
|
||||||
|
uint64_32_t t5;
|
||||||
|
uint64_32_t t6;
|
||||||
|
uint64_32_t t7;
|
||||||
|
uint64_32_t s0;
|
||||||
|
uint64_32_t s1;
|
||||||
|
uint64_32_t s2;
|
||||||
|
uint64_32_t s3;
|
||||||
|
uint64_32_t s4;
|
||||||
|
uint64_32_t s5;
|
||||||
|
uint64_32_t s6;
|
||||||
|
uint64_32_t s7;
|
||||||
|
uint64_32_t t8;
|
||||||
|
uint64_32_t t9;
|
||||||
|
uint64_32_t k0;
|
||||||
|
uint64_32_t k1;
|
||||||
|
uint64_32_t gp;
|
||||||
|
uint64_32_t sp;
|
||||||
|
uint64_32_t s8;
|
||||||
|
uint64_32_t ra;
|
||||||
|
uint64_32_t hi;
|
||||||
|
uint64_32_t lo;
|
||||||
|
uint64_32_t epc;
|
||||||
|
uint64_32_t badvaddr;
|
||||||
|
uint32_t sr;
|
||||||
|
uint32_t cr;
|
||||||
|
} exception_t;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
#ifndef EXCEPTION_REGS_H__
|
|
||||||
#define EXCEPTION_REGS_H__
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint64_t u64;
|
|
||||||
struct {
|
|
||||||
uint32_t u32_h;
|
|
||||||
uint32_t u32;
|
|
||||||
};
|
|
||||||
} uint64_32_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_32_t zr;
|
|
||||||
uint64_32_t at;
|
|
||||||
uint64_32_t v0;
|
|
||||||
uint64_32_t v1;
|
|
||||||
uint64_32_t a0;
|
|
||||||
uint64_32_t a1;
|
|
||||||
uint64_32_t a2;
|
|
||||||
uint64_32_t a3;
|
|
||||||
uint64_32_t t0;
|
|
||||||
uint64_32_t t1;
|
|
||||||
uint64_32_t t2;
|
|
||||||
uint64_32_t t3;
|
|
||||||
uint64_32_t t4;
|
|
||||||
uint64_32_t t5;
|
|
||||||
uint64_32_t t6;
|
|
||||||
uint64_32_t t7;
|
|
||||||
uint64_32_t s0;
|
|
||||||
uint64_32_t s1;
|
|
||||||
uint64_32_t s2;
|
|
||||||
uint64_32_t s3;
|
|
||||||
uint64_32_t s4;
|
|
||||||
uint64_32_t s5;
|
|
||||||
uint64_32_t s6;
|
|
||||||
uint64_32_t s7;
|
|
||||||
uint64_32_t t8;
|
|
||||||
uint64_32_t t9;
|
|
||||||
uint64_32_t k0;
|
|
||||||
uint64_32_t k1;
|
|
||||||
uint64_32_t gp;
|
|
||||||
uint64_32_t sp;
|
|
||||||
uint64_32_t s8;
|
|
||||||
uint64_32_t ra;
|
|
||||||
uint32_t sr;
|
|
||||||
uint32_t cr;
|
|
||||||
uint64_32_t epc;
|
|
||||||
uint64_32_t badvaddr;
|
|
||||||
} exception_t;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
16
sw/bootloader/src/fatfs/00history.txt
vendored
16
sw/bootloader/src/fatfs/00history.txt
vendored
@ -367,3 +367,19 @@ R0.15 (November 6, 2022)
|
|||||||
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
|
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
|
||||||
Fixed a compatibility issue in identification of GPT header.
|
Fixed a compatibility issue in identification of GPT header.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.15a (November 22, 2024)
|
||||||
|
Fixed a complie error when FF_FS_LOCK != 0.
|
||||||
|
Fixed a potential issue when work FatFs concurrency with FF_FS_REENTRANT, FF_VOLUMES >= 2 and FF_FS_LOCK > 0.
|
||||||
|
Made f_setlabel() accept a volume label in Unix style volume ID when FF_STR_VOLUME_ID == 2.
|
||||||
|
Made FatFs update PercInUse field in exFAT VBR. (A preceding f_getfree() is needed for the accuracy)
|
||||||
|
|
||||||
|
1. January 9, 2025
|
||||||
|
--------------------------------------------------------------------------------------------------
|
||||||
|
FatFs fails to load the FsInfo in FAT32 volumes and the f_getfree function will always be forced
|
||||||
|
a full FAT scan which takes a long time.
|
||||||
|
|
||||||
|
This problem was appeared at R0.15a and reported via an e-mail.
|
||||||
|
|
||||||
|
To fix this problem, apply ff15a_p1.diff to the ff.c.
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#define BUFFER_BLOCKS_MAX (sizeof(SC64_BUFFERS->BUFFER) / SD_SECTOR_SIZE)
|
#define BUFFER_BLOCKS_MAX (sizeof(SC64_BUFFERS->BUFFER) / SD_SECTOR_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
sc64_error_t sc64_error_fatfs;
|
||||||
|
|
||||||
|
|
||||||
DSTATUS disk_status (BYTE pdrv) {
|
DSTATUS disk_status (BYTE pdrv) {
|
||||||
if (pdrv > 0) {
|
if (pdrv > 0) {
|
||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
@ -20,7 +23,7 @@ DSTATUS disk_status (BYTE pdrv) {
|
|||||||
sc64_sd_card_status_t sd_card_status;
|
sc64_sd_card_status_t sd_card_status;
|
||||||
|
|
||||||
if ((error = sc64_sd_card_get_status(&sd_card_status)) != SC64_OK) {
|
if ((error = sc64_sd_card_get_status(&sd_card_status)) != SC64_OK) {
|
||||||
error_display("Could not get SD card status: %d", error);
|
error_display("Could not get SD card status\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sd_card_status & SD_CARD_STATUS_INSERTED)) {
|
if (!(sd_card_status & SD_CARD_STATUS_INSERTED)) {
|
||||||
@ -38,7 +41,7 @@ DSTATUS disk_initialize (BYTE pdrv) {
|
|||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc64_sd_card_init();
|
sc64_error_fatfs = sc64_sd_card_init();
|
||||||
|
|
||||||
return disk_status(pdrv);
|
return disk_status(pdrv);
|
||||||
}
|
}
|
||||||
@ -47,13 +50,16 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
|||||||
if (pdrv > 0) {
|
if (pdrv > 0) {
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
}
|
}
|
||||||
|
if ((sector + count) > 0x100000000ULL) {
|
||||||
|
return RES_PARERR;
|
||||||
|
}
|
||||||
uint32_t *physical_address = (uint32_t *) (PHYSICAL(buff));
|
uint32_t *physical_address = (uint32_t *) (PHYSICAL(buff));
|
||||||
if (physical_address < (uint32_t *) (N64_RAM_SIZE)) {
|
if (physical_address < (uint32_t *) (N64_RAM_SIZE)) {
|
||||||
uint8_t aligned_buffer[BUFFER_BLOCKS_MAX * SD_SECTOR_SIZE] __attribute__((aligned(8)));
|
uint8_t aligned_buffer[BUFFER_BLOCKS_MAX * SD_SECTOR_SIZE] __attribute__((aligned(8)));
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
uint32_t blocks = ((count > BUFFER_BLOCKS_MAX) ? BUFFER_BLOCKS_MAX : count);
|
uint32_t blocks = ((count > BUFFER_BLOCKS_MAX) ? BUFFER_BLOCKS_MAX : count);
|
||||||
size_t length = (blocks * SD_SECTOR_SIZE);
|
size_t length = (blocks * SD_SECTOR_SIZE);
|
||||||
if (sc64_sd_read_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_read_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
if (((uint32_t) (buff) % 8) == 0) {
|
if (((uint32_t) (buff) % 8) == 0) {
|
||||||
@ -67,7 +73,7 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
|||||||
count -= blocks;
|
count -= blocks;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sc64_sd_read_sectors(physical_address, sector, count) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_read_sectors(physical_address, sector, count)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,6 +85,9 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
if (pdrv > 0) {
|
if (pdrv > 0) {
|
||||||
return RES_PARERR;
|
return RES_PARERR;
|
||||||
}
|
}
|
||||||
|
if ((sector + count) > 0x100000000ULL) {
|
||||||
|
return RES_PARERR;
|
||||||
|
}
|
||||||
uint32_t *physical_address = (uint32_t *) (PHYSICAL(buff));
|
uint32_t *physical_address = (uint32_t *) (PHYSICAL(buff));
|
||||||
if (physical_address < (uint32_t *) (N64_RAM_SIZE)) {
|
if (physical_address < (uint32_t *) (N64_RAM_SIZE)) {
|
||||||
uint8_t aligned_buffer[BUFFER_BLOCKS_MAX * SD_SECTOR_SIZE] __attribute__((aligned(8)));
|
uint8_t aligned_buffer[BUFFER_BLOCKS_MAX * SD_SECTOR_SIZE] __attribute__((aligned(8)));
|
||||||
@ -91,7 +100,7 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
memcpy(aligned_buffer, buff, length);
|
memcpy(aligned_buffer, buff, length);
|
||||||
pi_dma_write((io32_t *) (SC64_BUFFERS->BUFFER), aligned_buffer, length);
|
pi_dma_write((io32_t *) (SC64_BUFFERS->BUFFER), aligned_buffer, length);
|
||||||
}
|
}
|
||||||
if (sc64_sd_write_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_write_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
buff += length;
|
buff += length;
|
||||||
@ -99,7 +108,7 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
count -= blocks;
|
count -= blocks;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sc64_sd_write_sectors(physical_address, sector, count) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_write_sectors(physical_address, sector, count)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +131,7 @@ DWORD get_fattime(void) {
|
|||||||
sc64_rtc_time_t t;
|
sc64_rtc_time_t t;
|
||||||
|
|
||||||
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
||||||
error_display("Command TIME_GET failed: %d", error);
|
error_display("Command TIME_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
734
sw/bootloader/src/fatfs/ff.c
vendored
734
sw/bootloader/src/fatfs/ff.c
vendored
File diff suppressed because it is too large
Load Diff
67
sw/bootloader/src/fatfs/ff.h
vendored
67
sw/bootloader/src/fatfs/ff.h
vendored
@ -1,8 +1,8 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.15 /
|
/ FatFs - Generic FAT Filesystem module R0.15a /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2022, ChaN, all right reserved.
|
/ Copyright (C) 2024, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
@ -20,14 +20,15 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 80286 /* Revision ID */
|
#define FF_DEFINED 5380 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(FFCONF_DEF)
|
||||||
#include "ffconf.h" /* FatFs configuration options */
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
|
#endif
|
||||||
#if FF_DEFINED != FFCONF_DEF
|
#if FF_DEFINED != FFCONF_DEF
|
||||||
#error Wrong configuration file (ffconf.h).
|
#error Wrong configuration file (ffconf.h).
|
||||||
#endif
|
#endif
|
||||||
@ -48,18 +49,18 @@ typedef unsigned __int64 QWORD;
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
typedef uint16_t WORD; /* 16-bit unsigned */
|
||||||
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
typedef uint32_t DWORD; /* 32-bit unsigned */
|
||||||
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
typedef uint64_t QWORD; /* 64-bit unsigned */
|
||||||
typedef WORD WCHAR; /* UTF-16 character type */
|
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||||
|
|
||||||
#else /* Earlier than C99 */
|
#else /* Earlier than C99 */
|
||||||
#define FF_INTDEF 1
|
#define FF_INTDEF 1
|
||||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
typedef unsigned short WORD; /* short must be 16-bit */
|
||||||
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
typedef unsigned long DWORD; /* long must be 32-bit */
|
||||||
typedef WORD WCHAR; /* UTF-16 character type */
|
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -113,15 +114,15 @@ typedef char TCHAR;
|
|||||||
|
|
||||||
#if FF_MULTI_PARTITION /* Multiple partition configuration */
|
#if FF_MULTI_PARTITION /* Multiple partition configuration */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE pd; /* Physical drive number */
|
BYTE pd; /* Associated physical drive */
|
||||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
BYTE pt; /* Associated partition (0:Auto detect, 1-4:Forced partition) */
|
||||||
} PARTITION;
|
} PARTITION;
|
||||||
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
|
extern PARTITION VolToPart[]; /* Volume to partition mapping table */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FF_STR_VOLUME_ID
|
#if FF_STR_VOLUME_ID
|
||||||
#ifndef FF_VOLUME_STRS
|
#ifndef FF_VOLUME_STRS
|
||||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
extern const char* VolumeStr[FF_VOLUMES]; /* User defined volume ID table */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -130,12 +131,12 @@ extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
|||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
BYTE fs_type; /* Filesystem type (0:blank filesystem object) */
|
||||||
BYTE pdrv; /* Volume hosting physical drive */
|
BYTE pdrv; /* Volume hosting physical drive */
|
||||||
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
|
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] status (b0:dirty) */
|
BYTE wflag; /* win[] status (1:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* Allocation information control (b7:disabled, b0:dirty) */
|
||||||
WORD id; /* Volume mount ID */
|
WORD id; /* Volume mount ID */
|
||||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||||
WORD csize; /* Cluster size [sectors] */
|
WORD csize; /* Cluster size [sectors] */
|
||||||
@ -146,11 +147,11 @@ typedef struct {
|
|||||||
WCHAR* lfnbuf; /* LFN working buffer */
|
WCHAR* lfnbuf; /* LFN working buffer */
|
||||||
#endif
|
#endif
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
|
BYTE* dirbuf; /* Directory entry block scratch pad buffer for exFAT */
|
||||||
#endif
|
#endif
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
DWORD last_clst; /* Last allocated cluster */
|
DWORD last_clst; /* Last allocated cluster (Unknown if >= n_fatent) */
|
||||||
DWORD free_clst; /* Number of free clusters */
|
DWORD free_clst; /* Number of free clusters (Unknown if >= n_fatent-2) */
|
||||||
#endif
|
#endif
|
||||||
#if FF_FS_RPATH
|
#if FF_FS_RPATH
|
||||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||||
@ -272,24 +273,24 @@ typedef struct {
|
|||||||
/* File function return code (FRESULT) */
|
/* File function return code (FRESULT) */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FR_OK = 0, /* (0) Succeeded */
|
FR_OK = 0, /* (0) Function succeeded */
|
||||||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||||
FR_INT_ERR, /* (2) Assertion failed */
|
FR_INT_ERR, /* (2) Assertion failed */
|
||||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
FR_NOT_READY, /* (3) The physical drive does not work */
|
||||||
FR_NO_FILE, /* (4) Could not find the file */
|
FR_NO_FILE, /* (4) Could not find the file */
|
||||||
FR_NO_PATH, /* (5) Could not find the path */
|
FR_NO_PATH, /* (5) Could not find the path */
|
||||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
FR_DENIED, /* (7) Access denied due to a prohibited access or directory full */
|
||||||
FR_EXIST, /* (8) Access denied due to prohibited access */
|
FR_EXIST, /* (8) Access denied due to a prohibited access */
|
||||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
FR_NO_FILESYSTEM, /* (13) Could not find a valid FAT volume */
|
||||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
FR_MKFS_ABORTED, /* (14) The f_mkfs function aborted due to some problem */
|
||||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
FR_TIMEOUT, /* (15) Could not take control of the volume within defined period */
|
||||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated or given buffer is insufficient in size */
|
||||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
||||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||||
} FRESULT;
|
} FRESULT;
|
||||||
@ -375,7 +376,7 @@ DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
|
|||||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||||
void ff_memfree (void* mblock); /* Free memory block */
|
void ff_memfree (void* mblock); /* Free memory block */
|
||||||
#endif
|
#endif
|
||||||
#if FF_FS_REENTRANT /* Sync functions */
|
#if FF_FS_REENTRANT /* Sync functions */
|
||||||
int ff_mutex_create (int vol); /* Create a sync object */
|
int ff_mutex_create (int vol); /* Create a sync object */
|
||||||
void ff_mutex_delete (int vol); /* Delete a sync object */
|
void ff_mutex_delete (int vol); /* Delete a sync object */
|
||||||
int ff_mutex_take (int vol); /* Lock sync object */
|
int ff_mutex_take (int vol); /* Lock sync object */
|
||||||
@ -389,7 +390,7 @@ void ff_mutex_give (int vol); /* Unlock sync object */
|
|||||||
/* Flags and Offset Address */
|
/* Flags and Offset Address */
|
||||||
/*--------------------------------------------------------------*/
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
/* File access mode and open method flags (3rd argument of f_open) */
|
/* File access mode and open method flags (3rd argument of f_open function) */
|
||||||
#define FA_READ 0x01
|
#define FA_READ 0x01
|
||||||
#define FA_WRITE 0x02
|
#define FA_WRITE 0x02
|
||||||
#define FA_OPEN_EXISTING 0x00
|
#define FA_OPEN_EXISTING 0x00
|
||||||
@ -398,10 +399,10 @@ void ff_mutex_give (int vol); /* Unlock sync object */
|
|||||||
#define FA_OPEN_ALWAYS 0x10
|
#define FA_OPEN_ALWAYS 0x10
|
||||||
#define FA_OPEN_APPEND 0x30
|
#define FA_OPEN_APPEND 0x30
|
||||||
|
|
||||||
/* Fast seek controls (2nd argument of f_lseek) */
|
/* Fast seek controls (2nd argument of f_lseek function) */
|
||||||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||||
|
|
||||||
/* Format options (2nd argument of f_mkfs) */
|
/* Format options (2nd argument of f_mkfs function) */
|
||||||
#define FM_FAT 0x01
|
#define FM_FAT 0x01
|
||||||
#define FM_FAT32 0x02
|
#define FM_FAT32 0x02
|
||||||
#define FM_EXFAT 0x04
|
#define FM_EXFAT 0x04
|
||||||
|
82
sw/bootloader/src/fatfs/ffconf.h
vendored
82
sw/bootloader/src/fatfs/ffconf.h
vendored
@ -2,7 +2,7 @@
|
|||||||
/ Configurations of FatFs Module
|
/ Configurations of FatFs Module
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 80286 /* Revision ID */
|
#define FFCONF_DEF 5380 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
@ -15,7 +15,7 @@
|
|||||||
/ and optional writing functions as well. */
|
/ and optional writing functions as well. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_FS_MINIMIZE 2
|
#define FF_FS_MINIMIZE 0
|
||||||
/* This option defines minimization level to remove some basic API functions.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: Basic functions are fully enabled.
|
/ 0: Basic functions are fully enabled.
|
||||||
@ -30,46 +30,46 @@
|
|||||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_MKFS 0
|
#define FF_USE_MKFS 1
|
||||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
/* This option switches f_mkfs(). (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_FASTSEEK 0
|
#define FF_USE_FASTSEEK 0
|
||||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_EXPAND 0
|
#define FF_USE_EXPAND 0
|
||||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
/* This option switches f_expand(). (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_CHMOD 0
|
#define FF_USE_CHMOD 0
|
||||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
/* This option switches attribute control API functions, f_chmod() and f_utime().
|
||||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_LABEL 0
|
#define FF_USE_LABEL 1
|
||||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
/* This option switches volume label API functions, f_getlabel() and f_setlabel().
|
||||||
/ (0:Disable or 1:Enable) */
|
/ (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_FORWARD 0
|
#define FF_USE_FORWARD 0
|
||||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
/* This option switches f_forward(). (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_STRFUNC 0
|
#define FF_USE_STRFUNC 0
|
||||||
#define FF_PRINT_LLI 1
|
#define FF_PRINT_LLI 0
|
||||||
#define FF_PRINT_FLOAT 1
|
#define FF_PRINT_FLOAT 0
|
||||||
#define FF_STRF_ENCODE 3
|
#define FF_STRF_ENCODE 3
|
||||||
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
|
/* FF_USE_STRFUNC switches the string API functions, f_gets(), f_putc(), f_puts()
|
||||||
/ f_printf().
|
/ and f_printf().
|
||||||
/
|
/
|
||||||
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
|
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
|
||||||
/ 1: Enable without LF-CRLF conversion.
|
/ 1: Enable without LF - CRLF conversion.
|
||||||
/ 2: Enable with LF-CRLF conversion.
|
/ 2: Enable with LF - CRLF conversion.
|
||||||
/
|
/
|
||||||
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
|
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
|
||||||
/ makes f_printf() support floating point argument. These features want C99 or later.
|
/ makes f_printf() support floating point argument. These features want C99 or later.
|
||||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
|
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character
|
||||||
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
|
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
|
||||||
/ to be read/written via those functions.
|
/ to be read/written via those functions.
|
||||||
/
|
/
|
||||||
@ -118,22 +118,22 @@
|
|||||||
/* The FF_USE_LFN switches the support for LFN (long file name).
|
/* The FF_USE_LFN switches the support for LFN (long file name).
|
||||||
/
|
/
|
||||||
/ 0: Disable LFN. FF_MAX_LFN has no effect.
|
/ 0: Disable LFN. FF_MAX_LFN has no effect.
|
||||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||||
/
|
/
|
||||||
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
|
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN feature
|
||||||
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
||||||
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
|
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
|
||||||
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
|
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
|
||||||
/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
|
/ be in range of 12 to 255. It is recommended to be set 255 to fully support the LFN
|
||||||
/ specification.
|
/ specification.
|
||||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||||
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
|
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_LFN_UNICODE 0
|
#define FF_LFN_UNICODE 2
|
||||||
/* This option switches the character encoding on the API when LFN is enabled.
|
/* This option switches the character encoding on the API when LFN is enabled.
|
||||||
/
|
/
|
||||||
/ 0: ANSI/OEM in current CP (TCHAR = char)
|
/ 0: ANSI/OEM in current CP (TCHAR = char)
|
||||||
@ -156,9 +156,9 @@
|
|||||||
#define FF_FS_RPATH 0
|
#define FF_FS_RPATH 0
|
||||||
/* This option configures support for relative path.
|
/* This option configures support for relative path.
|
||||||
/
|
/
|
||||||
/ 0: Disable relative path and remove related functions.
|
/ 0: Disable relative path and remove related API functions.
|
||||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||||
/ 2: f_getcwd() function is available in addition to 1.
|
/ 2: f_getcwd() is available in addition to 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -175,7 +175,7 @@
|
|||||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||||
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
/ logical drive. Number of items must not be less than FF_VOLUMES. Valid
|
||||||
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||||
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||||
/ not defined, a user defined volume string table is needed as:
|
/ not defined, a user defined volume string table is needed as:
|
||||||
@ -188,9 +188,9 @@
|
|||||||
/* This option switches support for multiple volumes on the physical drive.
|
/* This option switches support for multiple volumes on the physical drive.
|
||||||
/ By default (0), each logical drive number is bound to the same physical drive
|
/ By default (0), each logical drive number is bound to the same physical drive
|
||||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||||
/ When this function is enabled (1), each logical drive number can be bound to
|
/ When this feature is enabled (1), each logical drive number can be bound to
|
||||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||||
/ function will be available. */
|
/ will be available. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_MIN_SS 512
|
#define FF_MIN_SS 512
|
||||||
@ -198,25 +198,25 @@
|
|||||||
/* This set of options configures the range of sector size to be supported. (512,
|
/* This set of options configures the range of sector size to be supported. (512,
|
||||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||||
/ harddisk, but a larger value may be required for on-board flash memory and some
|
/ harddisk, but a larger value may be required for on-board flash memory and some
|
||||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
|
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is
|
||||||
/ for variable sector size mode and disk_ioctl() function needs to implement
|
/ configured for variable sector size mode and disk_ioctl() needs to implement
|
||||||
/ GET_SECTOR_SIZE command. */
|
/ GET_SECTOR_SIZE command. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_LBA64 0
|
#define FF_LBA64 1
|
||||||
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
|
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
|
||||||
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
|
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_MIN_GPT 0x10000000
|
#define FF_MIN_GPT 0x10000000
|
||||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
|
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and
|
||||||
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
|
/ f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_USE_TRIM 0
|
#define FF_USE_TRIM 0
|
||||||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
||||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
/ To enable this feature, also CTRL_TRIM command should be implemented to
|
||||||
/ disk_ioctl() function. */
|
/ the disk_ioctl(). */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -240,20 +240,20 @@
|
|||||||
#define FF_FS_NORTC 0
|
#define FF_FS_NORTC 0
|
||||||
#define FF_NORTC_MON 1
|
#define FF_NORTC_MON 1
|
||||||
#define FF_NORTC_MDAY 1
|
#define FF_NORTC_MDAY 1
|
||||||
#define FF_NORTC_YEAR 2022
|
#define FF_NORTC_YEAR 2025
|
||||||
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
|
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
|
||||||
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
|
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
|
||||||
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
|
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
|
||||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added
|
||||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
/ to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
||||||
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
||||||
|
|
||||||
|
|
||||||
#define FF_FS_NOFSINFO 0
|
#define FF_FS_NOFSINFO 0
|
||||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||||
/ option, and f_getfree() function at the first time after volume mount will force
|
/ option, and f_getfree() at the first time after volume mount will force
|
||||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||||
/
|
/
|
||||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||||
@ -280,13 +280,13 @@
|
|||||||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||||
/ module itself. Note that regardless of this option, file access to different
|
/ module itself. Note that regardless of this option, file access to different
|
||||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
/ and f_fdisk(), are always not re-entrant. Only file/directory access to
|
||||||
/ to the same volume is under control of this featuer.
|
/ the same volume is under control of this featuer.
|
||||||
/
|
/
|
||||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
|
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
|
||||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||||
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
|
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(),
|
||||||
/ function, must be added to the project. Samples are available in ffsystem.c.
|
/ must be added to the project. Samples are available in ffsystem.c.
|
||||||
/
|
/
|
||||||
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
|
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
|
||||||
*/
|
*/
|
||||||
|
@ -68,7 +68,7 @@ const uint8_t font_data[96][FONT_CHAR_BYTES] = {
|
|||||||
{ 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x00, },
|
{ 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x00, },
|
||||||
{ 0x00, 0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
{ 0x00, 0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, },
|
||||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, },
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, },
|
||||||
{ 0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, },
|
{ 0x1C, 0x63, 0x63, 0x1C, 0x00, 0x00, 0x00, 0x00, },
|
||||||
{ 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, },
|
{ 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, },
|
||||||
{ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, },
|
{ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, },
|
||||||
{ 0x00, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x7C, 0x00, },
|
{ 0x00, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x7C, 0x00, },
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "exception.h"
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "sc64.h"
|
#include "sc64.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
@ -8,13 +8,15 @@
|
|||||||
|
|
||||||
init_tv_type_t __tv_type;
|
init_tv_type_t __tv_type;
|
||||||
init_reset_type_t __reset_type;
|
init_reset_type_t __reset_type;
|
||||||
|
uint32_t __entropy;
|
||||||
|
|
||||||
|
|
||||||
void init (init_tv_type_t tv_type, init_reset_type_t reset_type) {
|
void init (init_tv_type_t tv_type, init_reset_type_t reset_type, uint32_t entropy) {
|
||||||
sc64_error_t error;
|
sc64_error_t error;
|
||||||
|
|
||||||
__tv_type = tv_type;
|
__tv_type = tv_type;
|
||||||
__reset_type = reset_type;
|
__reset_type = reset_type;
|
||||||
|
__entropy = entropy;
|
||||||
|
|
||||||
sc64_unlock();
|
sc64_unlock();
|
||||||
|
|
||||||
@ -22,22 +24,22 @@ void init (init_tv_type_t tv_type, init_reset_type_t reset_type) {
|
|||||||
error_display("SC64 hardware not detected");
|
error_display("SC64 hardware not detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
exception_enable_watchdog();
|
interrupts_init();
|
||||||
exception_enable_interrupts();
|
interrupts_start_watchdog();
|
||||||
|
|
||||||
if ((error = sc64_set_config(CFG_ID_BOOTLOADER_SWITCH, false)) != SC64_OK) {
|
if ((error = sc64_set_config(CFG_ID_BOOTLOADER_SWITCH, false)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_SET [BOOTLOADER_SWITCH] failed: %d", error);
|
error_display("Command CONFIG_SET [BOOTLOADER_SWITCH] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_check()) {
|
if (test_check()) {
|
||||||
exception_disable_watchdog();
|
interrupts_stop_watchdog();
|
||||||
test_execute();
|
test_execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void deinit (void) {
|
void deinit (void) {
|
||||||
exception_disable_interrupts();
|
interrupts_stop_watchdog();
|
||||||
exception_disable_watchdog();
|
interrupts_disable();
|
||||||
|
|
||||||
sc64_lock();
|
sc64_lock();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#define INIT_H__
|
#define INIT_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
INIT_TV_TYPE_PAL = 0,
|
INIT_TV_TYPE_PAL = 0,
|
||||||
INIT_TV_TYPE_NTSC = 1,
|
INIT_TV_TYPE_NTSC = 1,
|
||||||
@ -16,9 +19,10 @@ typedef enum {
|
|||||||
|
|
||||||
extern init_tv_type_t __tv_type;
|
extern init_tv_type_t __tv_type;
|
||||||
extern init_reset_type_t __reset_type;
|
extern init_reset_type_t __reset_type;
|
||||||
|
extern uint32_t __entropy;
|
||||||
|
|
||||||
|
|
||||||
void init (init_tv_type_t tv_type, init_reset_type_t reset_type);
|
void init (init_tv_type_t tv_type, init_reset_type_t reset_type, uint32_t entropy);
|
||||||
void deinit (void);
|
void deinit (void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
#include "exception_regs.h"
|
|
||||||
|
|
||||||
|
|
||||||
void exception_interrupt_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) {
|
|
||||||
while (1);
|
|
||||||
}
|
|
58
sw/bootloader/src/interrupts.S
Normal file
58
sw/bootloader/src/interrupts.S
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "vr4300.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define WATCHDOG_TIMEOUT (5 * (93750000UL / 2))
|
||||||
|
|
||||||
|
|
||||||
|
.section .text.interrupts
|
||||||
|
|
||||||
|
|
||||||
|
.type interrupts_init, %function
|
||||||
|
.global interrupts_init
|
||||||
|
interrupts_init:
|
||||||
|
li $t1, (C0_SR_IM4 | C0_SR_IM3 | C0_SR_IE)
|
||||||
|
mfc0 $t0, C0_STATUS
|
||||||
|
or $t0, $t1
|
||||||
|
mtc0 $t0, C0_STATUS
|
||||||
|
jr $ra
|
||||||
|
|
||||||
|
|
||||||
|
.type interrupts_disable, %function
|
||||||
|
.global interrupts_disable
|
||||||
|
interrupts_disable:
|
||||||
|
li $t0, ~(C0_SR_IE)
|
||||||
|
mfc0 $v0, C0_STATUS
|
||||||
|
and $t0, $v0
|
||||||
|
mtc0 $t0, C0_STATUS
|
||||||
|
jr $ra
|
||||||
|
|
||||||
|
|
||||||
|
.type interrupts_restore, %function
|
||||||
|
.global interrupts_restore
|
||||||
|
interrupts_restore:
|
||||||
|
mtc0 $a0, C0_STATUS
|
||||||
|
jr $ra
|
||||||
|
|
||||||
|
|
||||||
|
.type interrupts_start_watchdog, %function
|
||||||
|
.global interrupts_start_watchdog
|
||||||
|
interrupts_start_watchdog:
|
||||||
|
mtc0 $zero, C0_COUNT
|
||||||
|
li $t1, WATCHDOG_TIMEOUT
|
||||||
|
mtc0 $t1, C0_COMPARE
|
||||||
|
li $t1, C0_SR_IM7
|
||||||
|
mfc0 $t0, C0_STATUS
|
||||||
|
or $t0, $t1
|
||||||
|
mtc0 $t0, C0_STATUS
|
||||||
|
jr $ra
|
||||||
|
|
||||||
|
|
||||||
|
.type interrupts_stop_watchdog, %function
|
||||||
|
.global interrupts_stop_watchdog
|
||||||
|
interrupts_stop_watchdog:
|
||||||
|
li $t1, ~(C0_SR_IM7)
|
||||||
|
mfc0 $t0, C0_STATUS
|
||||||
|
and $t0, $t1
|
||||||
|
mtc0 $t0, C0_STATUS
|
||||||
|
mtc0 $zero, C0_COMPARE
|
||||||
|
jr $ra
|
87
sw/bootloader/src/interrupts.c
Normal file
87
sw/bootloader/src/interrupts.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "display.h"
|
||||||
|
#include "sc64.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "../assets/assets.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
INTERRUPT_NONE = 0,
|
||||||
|
INTERRUPT_SW_0 = (1 << 0),
|
||||||
|
INTERRUPT_SW_1 = (1 << 1),
|
||||||
|
INTERRUPT_RCP = (1 << 2),
|
||||||
|
INTERRUPT_CART = (1 << 3),
|
||||||
|
INTERRUPT_PRENMI = (1 << 4),
|
||||||
|
INTERRUPT_HW_5 = (1 << 5),
|
||||||
|
INTERRUPT_HW_6 = (1 << 6),
|
||||||
|
INTERRUPT_TIMER = (1 << 7),
|
||||||
|
} interrupt_t;
|
||||||
|
|
||||||
|
|
||||||
|
void interrupts_handler (uint8_t interrupts) {
|
||||||
|
if (interrupts == INTERRUPT_NONE) {
|
||||||
|
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||||
|
|
||||||
|
version_print();
|
||||||
|
display_printf("[ Empty interrupt ]\n");
|
||||||
|
display_printf("There is no interrupt to handle\n");
|
||||||
|
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupts & INTERRUPT_CART) {
|
||||||
|
interrupts &= ~(INTERRUPT_CART);
|
||||||
|
|
||||||
|
sc64_irq_t irq = sc64_irq_pending();
|
||||||
|
|
||||||
|
if (irq != SC64_IRQ_NONE) {
|
||||||
|
sc64_irq_callback(irq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupts & INTERRUPT_PRENMI) {
|
||||||
|
interrupts &= ~(INTERRUPT_PRENMI);
|
||||||
|
|
||||||
|
if (display_ready()) {
|
||||||
|
display_init(NULL);
|
||||||
|
|
||||||
|
display_printf("Resetting...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupts & INTERRUPT_TIMER) {
|
||||||
|
interrupts &= ~(INTERRUPT_TIMER);
|
||||||
|
|
||||||
|
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||||
|
|
||||||
|
version_print();
|
||||||
|
display_printf("[ Watchdog timeout ]\n");
|
||||||
|
display_printf("SC64 bootloader did not finish loading in 5 seconds\n");
|
||||||
|
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interrupts != INTERRUPT_NONE) {
|
||||||
|
display_init((uint32_t *) (&assets_sc64_logo_640_240_dimmed));
|
||||||
|
|
||||||
|
version_print();
|
||||||
|
display_printf("[ Unhandled interrupt(s) ]\n");
|
||||||
|
display_printf("Pending (0x%02X):\n", interrupts);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
switch (interrupts & (1 << i)) {
|
||||||
|
case INTERRUPT_SW_0: display_printf(" (0) Software interrupt\n"); break;
|
||||||
|
case INTERRUPT_SW_1: display_printf(" (1) Software interrupt\n"); break;
|
||||||
|
case INTERRUPT_RCP: display_printf(" (2) RCP interrupt\n"); break;
|
||||||
|
case INTERRUPT_CART: display_printf(" (3) CART interrupt\n"); break;
|
||||||
|
case INTERRUPT_PRENMI: display_printf(" (4) Pre NMI interrupt\n"); break;
|
||||||
|
case INTERRUPT_HW_5: display_printf(" (5) Hardware interrupt\n"); break;
|
||||||
|
case INTERRUPT_HW_6: display_printf(" (6) Hardware interrupt\n"); break;
|
||||||
|
case INTERRUPT_TIMER: display_printf(" (7) Timer interrupt\n"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
}
|
22
sw/bootloader/src/interrupts.h
Normal file
22
sw/bootloader/src/interrupts.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef INTERRUPTS_H__
|
||||||
|
#define INTERRUPTS_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define WITH_INTERRUPTS_DISABLED(x) { \
|
||||||
|
uint32_t __sr = interrupts_disable(); \
|
||||||
|
{ x } \
|
||||||
|
interrupts_restore(__sr); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void interrupts_init (void);
|
||||||
|
uint32_t interrupts_disable (void);
|
||||||
|
void interrupts_restore (uint32_t sr);
|
||||||
|
void interrupts_start_watchdog (void);
|
||||||
|
void interrupts_stop_watchdog (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -1,8 +1,9 @@
|
|||||||
|
#include "interrupts.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "vr4300.h"
|
#include "vr4300.h"
|
||||||
|
|
||||||
|
|
||||||
static void cache_operation (uint8_t operation, uint8_t line_size, void *address, size_t length) {
|
static inline void cache_operation (const uint8_t operation, uint8_t line_size, void *address, size_t length) {
|
||||||
uint32_t cache_address = (((uint32_t) (address)) & (~(line_size - 1)));
|
uint32_t cache_address = (((uint32_t) (address)) & (~(line_size - 1)));
|
||||||
while (cache_address < ((uint32_t) (address) + length)) {
|
while (cache_address < ((uint32_t) (address) + length)) {
|
||||||
asm volatile (
|
asm volatile (
|
||||||
@ -11,7 +12,7 @@ static void cache_operation (uint8_t operation, uint8_t line_size, void *address
|
|||||||
[cache_address] "r" (cache_address)
|
[cache_address] "r" (cache_address)
|
||||||
);
|
);
|
||||||
cache_address += line_size;
|
cache_address += line_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cache_data_hit_writeback_invalidate (void *address, size_t length) {
|
void cache_data_hit_writeback_invalidate (void *address, size_t length) {
|
||||||
@ -72,26 +73,63 @@ uint32_t pi_busy (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pi_io_read (io32_t *address) {
|
uint32_t pi_io_read (io32_t *address) {
|
||||||
return cpu_io_read(address);
|
uint32_t value;
|
||||||
|
WITH_INTERRUPTS_DISABLED({
|
||||||
|
while (pi_busy());
|
||||||
|
value = cpu_io_read(address);
|
||||||
|
});
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pi_io_write (io32_t *address, uint32_t value) {
|
void pi_io_write (io32_t *address, uint32_t value) {
|
||||||
cpu_io_write(address, value);
|
WITH_INTERRUPTS_DISABLED({
|
||||||
while (pi_busy());
|
while (pi_busy());
|
||||||
|
cpu_io_write(address, value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void pi_dma_read (io32_t *address, void *buffer, size_t length) {
|
void pi_dma_read (io32_t *address, void *buffer, size_t length) {
|
||||||
cache_data_hit_writeback_invalidate(buffer, length);
|
cache_data_hit_writeback_invalidate(buffer, length);
|
||||||
cpu_io_write(&PI->PADDR, (uint32_t) (PHYSICAL(address)));
|
WITH_INTERRUPTS_DISABLED({
|
||||||
cpu_io_write(&PI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
while (pi_busy());
|
||||||
cpu_io_write(&PI->WDMA, length - 1);
|
cpu_io_write(&PI->PADDR, (uint32_t) (PHYSICAL(address)));
|
||||||
|
cpu_io_write(&PI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
||||||
|
cpu_io_write(&PI->WDMA, length - 1);
|
||||||
|
});
|
||||||
while (pi_busy());
|
while (pi_busy());
|
||||||
}
|
}
|
||||||
|
|
||||||
void pi_dma_write (io32_t *address, void *buffer, size_t length) {
|
void pi_dma_write (io32_t *address, void *buffer, size_t length) {
|
||||||
cache_data_hit_writeback(buffer, length);
|
cache_data_hit_writeback(buffer, length);
|
||||||
cpu_io_write(&PI->PADDR, (uint32_t) (PHYSICAL(address)));
|
WITH_INTERRUPTS_DISABLED({
|
||||||
cpu_io_write(&PI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
while (pi_busy());
|
||||||
cpu_io_write(&PI->RDMA, length - 1);
|
cpu_io_write(&PI->PADDR, (uint32_t) (PHYSICAL(address)));
|
||||||
|
cpu_io_write(&PI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
||||||
|
cpu_io_write(&PI->RDMA, length - 1);
|
||||||
|
});
|
||||||
while (pi_busy());
|
while (pi_busy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t si_busy (void) {
|
||||||
|
return (cpu_io_read(&SI->SR) & (SI_SR_IO_BUSY | SI_SR_DMA_BUSY));
|
||||||
|
}
|
||||||
|
|
||||||
|
void si_dma_read (void *buffer) {
|
||||||
|
cache_data_hit_writeback_invalidate(buffer, PIF_RAM_LENGTH);
|
||||||
|
WITH_INTERRUPTS_DISABLED({
|
||||||
|
while (si_busy());
|
||||||
|
cpu_io_write(&SI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
||||||
|
cpu_io_write(&SI->RDMA, (uint32_t) (PIF_RAM));
|
||||||
|
});
|
||||||
|
while (si_busy());
|
||||||
|
}
|
||||||
|
|
||||||
|
void si_dma_write (void *buffer) {
|
||||||
|
cache_data_hit_writeback(buffer, PIF_RAM_LENGTH);
|
||||||
|
WITH_INTERRUPTS_DISABLED({
|
||||||
|
while (si_busy());
|
||||||
|
cpu_io_write(&SI->MADDR, (uint32_t) (PHYSICAL(buffer)));
|
||||||
|
cpu_io_write(&SI->WDMA, (uint32_t) (PIF_RAM));
|
||||||
|
});
|
||||||
|
while (si_busy());
|
||||||
|
}
|
||||||
|
@ -202,6 +202,24 @@ typedef struct {
|
|||||||
#define PI_SR_CLR_INTR (1 << 1)
|
#define PI_SR_CLR_INTR (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
io32_t MADDR;
|
||||||
|
io32_t RDMA;
|
||||||
|
io32_t __reserved_0[2];
|
||||||
|
io32_t WDMA;
|
||||||
|
io32_t __reserved_1[1];
|
||||||
|
io32_t SR;
|
||||||
|
} si_regs_t;
|
||||||
|
|
||||||
|
#define SI_BASE (0x04800000UL)
|
||||||
|
#define SI ((si_regs_t *) SI_BASE)
|
||||||
|
|
||||||
|
#define SI_SR_DMA_BUSY (1 << 0)
|
||||||
|
#define SI_SR_IO_BUSY (1 << 1)
|
||||||
|
#define SI_SR_DMA_ERROR (1 << 3)
|
||||||
|
#define SI_SR_INTERRUPT (1 << 12)
|
||||||
|
|
||||||
|
|
||||||
#define ROM_DDIPL_BASE (0x06000000UL)
|
#define ROM_DDIPL_BASE (0x06000000UL)
|
||||||
#define ROM_DDIPL ((io32_t *) ROM_DDIPL_BASE)
|
#define ROM_DDIPL ((io32_t *) ROM_DDIPL_BASE)
|
||||||
|
|
||||||
@ -210,6 +228,14 @@ typedef struct {
|
|||||||
#define ROM_CART ((io32_t *) ROM_CART_BASE)
|
#define ROM_CART ((io32_t *) ROM_CART_BASE)
|
||||||
|
|
||||||
|
|
||||||
|
#define PIF_RAM_BASE (0x1FC007C0)
|
||||||
|
#define PIF_RAM_LENGTH (64)
|
||||||
|
#define PIF_RAM ((io32_t *) PIF_RAM_BASE)
|
||||||
|
|
||||||
|
|
||||||
|
void cache_data_hit_writeback_invalidate (void *address, size_t length);
|
||||||
|
void cache_data_hit_writeback (void *address, size_t length);
|
||||||
|
void cache_inst_hit_invalidate (void *address, size_t length);
|
||||||
uint32_t c0_count (void);
|
uint32_t c0_count (void);
|
||||||
void delay_ms (int ms);
|
void delay_ms (int ms);
|
||||||
uint32_t cpu_io_read (io32_t *address);
|
uint32_t cpu_io_read (io32_t *address);
|
||||||
@ -220,9 +246,9 @@ uint32_t pi_io_read (io32_t *address);
|
|||||||
void pi_io_write (io32_t *address, uint32_t value);
|
void pi_io_write (io32_t *address, uint32_t value);
|
||||||
void pi_dma_read (io32_t *address, void *buffer, size_t length);
|
void pi_dma_read (io32_t *address, void *buffer, size_t length);
|
||||||
void pi_dma_write (io32_t *address, void *buffer, size_t length);
|
void pi_dma_write (io32_t *address, void *buffer, size_t length);
|
||||||
void cache_data_hit_writeback_invalidate (void *address, size_t length);
|
uint32_t si_busy (void);
|
||||||
void cache_data_hit_writeback (void *address, size_t length);
|
void si_dma_read (void *buffer);
|
||||||
void cache_inst_hit_invalidate (void *address, size_t length);
|
void si_dma_write (void *buffer);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
169
sw/bootloader/src/joybus.c
Normal file
169
sw/bootloader/src/joybus.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include "io.h"
|
||||||
|
#include "joybus.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define PIF_ESCAPE_SKIP_CHANNEL (0x00)
|
||||||
|
#define PIF_ESCAPE_END_OF_FRAME (0xFE)
|
||||||
|
|
||||||
|
#define PIF_COMMAND_JOYBUS_START (1 << 0)
|
||||||
|
|
||||||
|
#define JOYBUS_CMD_INFO (0x00)
|
||||||
|
#define JOYBUS_CMD_STATE (0x01)
|
||||||
|
#define JOYBUS_CMD_RESET (0xFF)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
uint8_t skip : 1;
|
||||||
|
uint8_t reset : 1;
|
||||||
|
uint8_t length : 6;
|
||||||
|
} tx;
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
uint8_t no_device : 1;
|
||||||
|
uint8_t timeout : 1;
|
||||||
|
uint8_t length : 6;
|
||||||
|
} rx;
|
||||||
|
uint8_t cmd;
|
||||||
|
} joybus_trx_info_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
joybus_trx_info_t info;
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
uint16_t id;
|
||||||
|
uint8_t flags;
|
||||||
|
} rx;
|
||||||
|
} joybus_cmd_info_t;
|
||||||
|
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
joybus_trx_info_t info;
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
uint8_t a : 1;
|
||||||
|
uint8_t b : 1;
|
||||||
|
uint8_t z : 1;
|
||||||
|
uint8_t start : 1;
|
||||||
|
uint8_t up : 1;
|
||||||
|
uint8_t down : 1;
|
||||||
|
uint8_t left : 1;
|
||||||
|
uint8_t right : 1;
|
||||||
|
uint8_t reset : 1;
|
||||||
|
uint8_t __unused : 1;
|
||||||
|
uint8_t l : 1;
|
||||||
|
uint8_t r : 1;
|
||||||
|
uint8_t c_up : 1;
|
||||||
|
uint8_t c_down : 1;
|
||||||
|
uint8_t c_left : 1;
|
||||||
|
uint8_t c_right : 1;
|
||||||
|
int8_t x;
|
||||||
|
int8_t y;
|
||||||
|
} rx;
|
||||||
|
} joybus_cmd_state_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void joybus_clear_buffer (uint8_t *buffer) {
|
||||||
|
for (int i = 0; i < PIF_RAM_LENGTH; i++) {
|
||||||
|
buffer[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_set_starting_channel (uint8_t **ptr, int channel) {
|
||||||
|
for (int i = 0; i < channel; i++) {
|
||||||
|
**ptr = PIF_ESCAPE_SKIP_CHANNEL;
|
||||||
|
*ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *joybus_append_command (uint8_t **ptr, void *cmd, size_t length) {
|
||||||
|
((joybus_trx_info_t *) (cmd))->tx.length += 1;
|
||||||
|
uint8_t *cmd_ptr = *ptr;
|
||||||
|
memcpy(cmd_ptr, cmd, length);
|
||||||
|
*ptr += length;
|
||||||
|
return cmd_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_load_result (uint8_t *cmd_ptr, void *cmd, size_t length) {
|
||||||
|
memcpy(cmd, cmd_ptr, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_finish_frame (uint8_t **ptr) {
|
||||||
|
**ptr = PIF_ESCAPE_END_OF_FRAME;
|
||||||
|
*ptr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_perform_transaction (uint8_t *buffer) {
|
||||||
|
buffer[PIF_RAM_LENGTH - 1] = PIF_COMMAND_JOYBUS_START;
|
||||||
|
|
||||||
|
si_dma_write(buffer);
|
||||||
|
si_dma_read(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool joybus_device_present (joybus_trx_info_t *trx_info) {
|
||||||
|
return !(trx_info->rx.no_device || trx_info->rx.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool joybus_execute_command (int port, void *cmd, size_t length) {
|
||||||
|
uint8_t buffer[PIF_RAM_LENGTH] __attribute__((aligned(8)));
|
||||||
|
uint8_t *ptr = buffer;
|
||||||
|
|
||||||
|
joybus_clear_buffer(buffer);
|
||||||
|
joybus_set_starting_channel(&ptr, port);
|
||||||
|
uint8_t *cmd_ptr = joybus_append_command(&ptr, cmd, length);
|
||||||
|
joybus_finish_frame(&ptr);
|
||||||
|
joybus_perform_transaction(buffer);
|
||||||
|
joybus_load_result(cmd_ptr, cmd, length);
|
||||||
|
return joybus_device_present((joybus_trx_info_t *) (cmd_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_copy_controller_info (joybus_cmd_info_t *cmd, joybus_controller_info_t *info) {
|
||||||
|
info->id = cmd->rx.id;
|
||||||
|
info->flags = cmd->rx.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void joybus_copy_controller_state (joybus_cmd_state_t *cmd, joybus_controller_state_t *state) {
|
||||||
|
state->a = cmd->rx.a;
|
||||||
|
state->b = cmd->rx.b;
|
||||||
|
state->z = cmd->rx.z;
|
||||||
|
state->start = cmd->rx.start;
|
||||||
|
state->up = cmd->rx.up;
|
||||||
|
state->down = cmd->rx.down;
|
||||||
|
state->left = cmd->rx.left;
|
||||||
|
state->right = cmd->rx.right;
|
||||||
|
state->reset = cmd->rx.reset;
|
||||||
|
state->l = cmd->rx.l;
|
||||||
|
state->r = cmd->rx.r;
|
||||||
|
state->c_up = cmd->rx.c_up;
|
||||||
|
state->c_down = cmd->rx.c_down;
|
||||||
|
state->c_left = cmd->rx.c_left;
|
||||||
|
state->c_right = cmd->rx.c_right;
|
||||||
|
state->x = cmd->rx.x;
|
||||||
|
state->y = cmd->rx.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool joybus_get_controller_info (int port, joybus_controller_info_t *info, bool reset) {
|
||||||
|
joybus_cmd_info_t cmd = { .info = {
|
||||||
|
.cmd = reset ? JOYBUS_CMD_RESET : JOYBUS_CMD_INFO,
|
||||||
|
.rx = { .length = sizeof(cmd.rx) }
|
||||||
|
} };
|
||||||
|
|
||||||
|
if (joybus_execute_command(port, &cmd, sizeof(cmd))) {
|
||||||
|
joybus_copy_controller_info(&cmd, info);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool joybus_get_controller_state (int port, joybus_controller_state_t *state) {
|
||||||
|
joybus_cmd_state_t cmd = { .info = {
|
||||||
|
.cmd = JOYBUS_CMD_STATE,
|
||||||
|
.rx = { .length = sizeof(cmd.rx) }
|
||||||
|
} };
|
||||||
|
|
||||||
|
if (joybus_execute_command(port, &cmd, sizeof(cmd))) {
|
||||||
|
joybus_copy_controller_state(&cmd, state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
39
sw/bootloader/src/joybus.h
Normal file
39
sw/bootloader/src/joybus.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef JOYBUS_H__
|
||||||
|
#define JOYBUS_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t id;
|
||||||
|
uint8_t flags;
|
||||||
|
} joybus_controller_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool a;
|
||||||
|
bool b;
|
||||||
|
bool z;
|
||||||
|
bool start;
|
||||||
|
bool up;
|
||||||
|
bool down;
|
||||||
|
bool left;
|
||||||
|
bool right;
|
||||||
|
bool reset;
|
||||||
|
bool l;
|
||||||
|
bool r;
|
||||||
|
bool c_up;
|
||||||
|
bool c_down;
|
||||||
|
bool c_left;
|
||||||
|
bool c_right;
|
||||||
|
int8_t x;
|
||||||
|
int8_t y;
|
||||||
|
} joybus_controller_state_t;
|
||||||
|
|
||||||
|
|
||||||
|
bool joybus_get_controller_info (int port, joybus_controller_info_t *info, bool reset);
|
||||||
|
bool joybus_get_controller_state (int port, joybus_controller_state_t *state);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -3,6 +3,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "joybus.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "sc64.h"
|
#include "sc64.h"
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ void main (void) {
|
|||||||
sc64_boot_params_t sc64_boot_params;
|
sc64_boot_params_t sc64_boot_params;
|
||||||
|
|
||||||
if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) {
|
if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) {
|
||||||
error_display("Could not obtain boot info: %d", error);
|
error_display("Could not obtain boot info\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_params_t boot_params;
|
boot_params_t boot_params;
|
||||||
@ -22,6 +23,20 @@ void main (void) {
|
|||||||
boot_params.cic_seed = (sc64_boot_params.cic_seed & 0xFF);
|
boot_params.cic_seed = (sc64_boot_params.cic_seed & 0xFF);
|
||||||
boot_params.detect_cic_seed = (sc64_boot_params.cic_seed == CIC_SEED_AUTO);
|
boot_params.detect_cic_seed = (sc64_boot_params.cic_seed == CIC_SEED_AUTO);
|
||||||
|
|
||||||
|
switch (sc64_boot_params.boot_mode) {
|
||||||
|
case BOOT_MODE_ROM:
|
||||||
|
case BOOT_MODE_DDIPL: {
|
||||||
|
joybus_controller_state_t controller_state;
|
||||||
|
if (joybus_get_controller_state(0, &controller_state) && controller_state.r) {
|
||||||
|
sc64_boot_params.boot_mode = BOOT_MODE_MENU;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sc64_boot_params.boot_mode) {
|
switch (sc64_boot_params.boot_mode) {
|
||||||
case BOOT_MODE_MENU:
|
case BOOT_MODE_MENU:
|
||||||
menu_load();
|
menu_load();
|
||||||
@ -40,7 +55,7 @@ void main (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_display("Unknown boot mode selected [%d]\n", sc64_boot_params.boot_mode);
|
error_display("Unknown boot mode selected (%d)\n", sc64_boot_params.boot_mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,46 +8,68 @@
|
|||||||
#define ROM_ADDRESS (0x10000000)
|
#define ROM_ADDRESS (0x10000000)
|
||||||
|
|
||||||
|
|
||||||
|
extern sc64_error_t sc64_error_fatfs;
|
||||||
|
|
||||||
|
|
||||||
static const char *fatfs_error_codes[] = {
|
static const char *fatfs_error_codes[] = {
|
||||||
"Succeeded",
|
"No error",
|
||||||
"A hard error occurred in the low level disk I/O layer",
|
"A hard error occurred in the low level disk I/O layer",
|
||||||
"Assertion failed",
|
"Assertion failed",
|
||||||
"The physical drive cannot work",
|
"The physical drive does not work",
|
||||||
"Could not find the file",
|
"Could not find the file",
|
||||||
"Could not find the path",
|
"Could not find the path",
|
||||||
"The path name format is invalid",
|
"The path name format is invalid",
|
||||||
"Access denied due to prohibited access or directory full",
|
"Access denied due to a prohibited access or directory full",
|
||||||
"Access denied due to prohibited access",
|
"Access denied due to a prohibited access",
|
||||||
"The file/directory object is invalid",
|
"The file/directory object is invalid",
|
||||||
"The physical drive is write protected",
|
"The physical drive is write protected",
|
||||||
"The logical drive number is invalid",
|
"The logical drive number is invalid",
|
||||||
"The volume has no work area",
|
"The volume has no work area",
|
||||||
"There is no valid FAT volume",
|
"Could not find a valid FAT volume",
|
||||||
"The f_mkfs() aborted due to any problem",
|
"The f_mkfs function aborted due to some problem",
|
||||||
"Could not get a grant to access the volume within defined period",
|
"Could not take control of the volume within defined period",
|
||||||
"The operation is rejected according to the file sharing policy",
|
"The operation is rejected according to the file sharing policy",
|
||||||
"LFN working buffer could not be allocated",
|
"LFN working buffer could not be allocated or given buffer is insufficient in size",
|
||||||
"Number of open files > FF_FS_LOCK",
|
"Number of open files > FF_FS_LOCK",
|
||||||
"Given parameter is invalid",
|
"Given parameter is invalid",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define FF_CHECK(x, message, ...) { \
|
static void menu_fix_file_size (FIL *fil) {
|
||||||
fresult = x; \
|
fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
|
||||||
if (fresult != FR_OK) { \
|
}
|
||||||
error_display(message ".\nReason: %s", __VA_ARGS__ __VA_OPT__(,) fatfs_error_codes[fresult]); \
|
|
||||||
} \
|
static void menu_error_display (const char *message, FRESULT fresult) {
|
||||||
|
error_display(
|
||||||
|
" > FatFs error: %s\n"
|
||||||
|
" > SD card error: %s (%08X)\n"
|
||||||
|
"\n"
|
||||||
|
"[ %s ]\n"
|
||||||
|
" > Please insert a FAT32/exFAT formatted SD card.\n"
|
||||||
|
" > To start the menu please put \"sc64menu.n64\" file\n"
|
||||||
|
" in the top directory on the SD card.\n"
|
||||||
|
" > Latest menu version is available on the\n"
|
||||||
|
" https://menu.summercart64.dev website.\n",
|
||||||
|
fatfs_error_codes[fresult],
|
||||||
|
sc64_error_description(sc64_error_fatfs),
|
||||||
|
sc64_error_fatfs,
|
||||||
|
message
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fix_menu_file_size (FIL *fil) {
|
#define FF_CHECK(x, message) { \
|
||||||
fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS);
|
fresult = x; \
|
||||||
|
if (fresult != FR_OK) { \
|
||||||
|
menu_error_display(message, fresult); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void menu_load (void) {
|
void menu_load (void) {
|
||||||
sc64_error_t error;
|
sc64_error_t error;
|
||||||
bool writeback_pending;
|
bool writeback_pending;
|
||||||
|
sc64_sd_card_status_t sd_card_status;
|
||||||
FRESULT fresult;
|
FRESULT fresult;
|
||||||
FATFS fs;
|
FATFS fs;
|
||||||
FIL fil;
|
FIL fil;
|
||||||
@ -55,17 +77,25 @@ void menu_load (void) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) {
|
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) {
|
||||||
error_display("Command WRITEBACK_PENDING failed: %d", error);
|
error_display("Command WRITEBACK_PENDING failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
} while (writeback_pending);
|
} while (writeback_pending);
|
||||||
|
|
||||||
if ((error = sc64_writeback_disable()) != SC64_OK) {
|
if ((error = sc64_writeback_disable()) != SC64_OK) {
|
||||||
error_display("Could not disable writeback: %d", error);
|
error_display("Could not disable save writeback\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error. No SD card or invalid partition table");
|
if ((error = sc64_sd_card_get_status(&sd_card_status)) != SC64_OK) {
|
||||||
FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)");
|
error_display("Could not get SD card status\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
fix_menu_file_size(&fil);
|
}
|
||||||
|
|
||||||
|
if (!(sd_card_status & SD_CARD_STATUS_INSERTED)) {
|
||||||
|
menu_error_display("No SD card detected in the slot", FR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error");
|
||||||
|
FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable");
|
||||||
|
menu_fix_file_size(&fil);
|
||||||
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
||||||
FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
|
FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected");
|
||||||
FF_CHECK(f_close(&fil), "Could not close menu file");
|
FF_CHECK(f_close(&fil), "Could not close menu file");
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user