commit 3801ee7aadf4cb73af3ca94274263c986ba3b515 Author: Dennis Brentjes Date: Sun Sep 14 19:55:43 2025 +0200 Initial commit diff --git a/docs/.obsidian/app.json b/docs/.obsidian/app.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/docs/.obsidian/app.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/docs/.obsidian/appearance.json b/docs/.obsidian/appearance.json new file mode 100644 index 0000000..4be7969 --- /dev/null +++ b/docs/.obsidian/appearance.json @@ -0,0 +1,3 @@ +{ + "theme": "obsidian" +} \ No newline at end of file diff --git a/docs/.obsidian/core-plugins.json b/docs/.obsidian/core-plugins.json new file mode 100644 index 0000000..0faa60d --- /dev/null +++ b/docs/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "footnotes": false, + "properties": false, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": true, + "bases": true, + "webviewer": false +} \ No newline at end of file diff --git a/docs/.obsidian/graph.json b/docs/.obsidian/graph.json new file mode 100644 index 0000000..42a46ec --- /dev/null +++ b/docs/.obsidian/graph.json @@ -0,0 +1,22 @@ +{ + "collapse-filter": true, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": true, + "colorGroups": [], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 1, + "close": true +} \ No newline at end of file diff --git a/docs/.obsidian/workspace.json b/docs/.obsidian/workspace.json new file mode 100644 index 0000000..0a49246 --- /dev/null +++ b/docs/.obsidian/workspace.json @@ -0,0 +1,258 @@ +{ + "main": { + "id": "b1126f19eadfbccd", + "type": "split", + "children": [ + { + "id": "2ba05487936c844b", + "type": "tabs", + "children": [ + { + "id": "5212d9065a150034", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ReBbarb.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "ReBbarb" + } + }, + { + "id": "caf6734d3835c835", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ReBbarb.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "ReBbarb" + } + }, + { + "id": "098b8cbc3b764ebf", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ReBbarb.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "ReBbarb" + } + }, + { + "id": "f235e129fc127e53", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ReBbarb.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "ReBbarb" + } + }, + { + "id": "e9e0f89b917adb89", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ReBbarb.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "ReBbarb" + } + }, + { + "id": "bd1db3e96ff15247", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "Environment/Amaranth-Hdl project setup.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "Amaranth-Hdl project setup" + } + } + ], + "currentTab": 5 + } + ], + "direction": "vertical" + }, + "left": { + "id": "41928e7bfa033c12", + "type": "split", + "children": [ + { + "id": "20b81aa7e9da9056", + "type": "tabs", + "children": [ + { + "id": "c9cf1762af2fc6d1", + "type": "leaf", + "state": { + "type": "file-explorer", + "state": { + "sortOrder": "alphabetical", + "autoReveal": false + }, + "icon": "lucide-folder-closed", + "title": "Files" + } + }, + { + "id": "41e707cc40e380be", + "type": "leaf", + "state": { + "type": "search", + "state": { + "query": "", + "matchingCase": false, + "explainSearch": false, + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical" + }, + "icon": "lucide-search", + "title": "Search" + } + }, + { + "id": "7efd4428cb796566", + "type": "leaf", + "state": { + "type": "bookmarks", + "state": {}, + "icon": "lucide-bookmark", + "title": "Bookmarks" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300 + }, + "right": { + "id": "564b72f12544e8fb", + "type": "split", + "children": [ + { + "id": "27b51e3cbd5b64f2", + "type": "tabs", + "children": [ + { + "id": "08ff37c167cba8a6", + "type": "leaf", + "state": { + "type": "backlink", + "state": { + "file": "Welcome.md", + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical", + "showSearch": false, + "searchQuery": "", + "backlinkCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-coming-in", + "title": "Backlinks for Welcome" + } + }, + { + "id": "f0d6e734ee929213", + "type": "leaf", + "state": { + "type": "outgoing-link", + "state": { + "file": "Welcome.md", + "linksCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-going-out", + "title": "Outgoing links from Welcome" + } + }, + { + "id": "58c9a6253aa57492", + "type": "leaf", + "state": { + "type": "tag", + "state": { + "sortOrder": "frequency", + "useHierarchy": true, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-tags", + "title": "Tags" + } + }, + { + "id": "2feb030bc67ed9a4", + "type": "leaf", + "state": { + "type": "outline", + "state": { + "file": "Welcome.md", + "followCursor": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-list", + "title": "Outline of Welcome" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300, + "collapsed": true + }, + "left-ribbon": { + "hiddenItems": { + "switcher:Open quick switcher": false, + "graph:Open graph view": false, + "canvas:Create new canvas": false, + "daily-notes:Open today's daily note": false, + "templates:Insert template": false, + "command-palette:Open command palette": false, + "bases:Create new base": false + } + }, + "active": "c9cf1762af2fc6d1", + "lastOpenFiles": [ + "ReBbarb.md", + "GameCube/EXI protocol.md", + "GameCube/SP1.md", + "GameCube/GameCube.md", + "GameCube", + "Investigations/external clocks.md", + "Investigations.md", + "Investigations", + "Environment", + "Environment/Amaranth-Hdl project setup.md", + "Untitled.base", + "Untitled.canvas" + ] +} \ No newline at end of file diff --git a/docs/Environment/Amaranth-Hdl project setup.md b/docs/Environment/Amaranth-Hdl project setup.md new file mode 100644 index 0000000..672e130 --- /dev/null +++ b/docs/Environment/Amaranth-Hdl project setup.md @@ -0,0 +1,10 @@ +Create a venv +`python -m venv .venv` + +Activate the venv +`. .vent/bin/activate` + +Install the dependencies +`pip install -r requirements.txt` + +You will potentially need more tooling to create the bitstream and flash the bitstream for the specific FPGA. In my case I'm working with an IceBreaker. So I've installed the `nextpnr-ice40` toolchain. Yosys is builtin to amaranth, that is why I'm running it within an venv to ensure it doesn't mess with system installed packages. diff --git a/docs/GameCube/EXI protocol.md b/docs/GameCube/EXI protocol.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/GameCube/GameCube.md b/docs/GameCube/GameCube.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/GameCube/SP1.md b/docs/GameCube/SP1.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Investigations/external clocks.md b/docs/Investigations/external clocks.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ReBbarb.md b/docs/ReBbarb.md new file mode 100644 index 0000000..c0b6f9f --- /dev/null +++ b/docs/ReBbarb.md @@ -0,0 +1,24 @@ +This project attempts to emulate the Gamecube BroadBand Adapter in an FPGA. The following things need to happen. + + - [x] [[Amaranth-Hdl project setup]] + - [x] Setup venv + - [x] Install packages + - [x] Flash Blinky on icebreaker + - [ ] Figuring out how to deal with [[external clocks]]. + - [x] How to get a clock greater than 12Mhz needed to interface with 32Mhz EXI + - [x] PLL configured to 48Mhz + - [ ] ~~48Mhz oscillator onboard? ~~ + - [ ] Check if Clock Domain Crossing is possible. + - [ ] Oversampeling approach was tedious but worked + - [ ] Interfacing with [[GameCube]] + - [ ] Figuring pinout of SP1. + - [ ] Unofficial gamecube docs? + - [ ] Make sure connecting [[SP1]] to IceBreaker is safe. + - [ ] Can we power the FPGA with the SP1? + - [ ] How much voltage do we get from SP1. + - [ ] How much current can we source? + - [ ] Figuring out basic [[EXI protocol]] + - [ ] What is the structure of the messages? + - [ ] How to know how long the message is + - [ ] Integrity checks? + - [ ] How fast do we need to respond to a message. \ No newline at end of file diff --git a/rebbarb/.gitignore b/rebbarb/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/rebbarb/.gitignore @@ -0,0 +1 @@ +build diff --git a/rebbarb/rebbarb.py b/rebbarb/rebbarb.py new file mode 100644 index 0000000..4f5468d --- /dev/null +++ b/rebbarb/rebbarb.py @@ -0,0 +1,60 @@ +from amaranth import * + +class LEDBlinker(Elaboratable): + def elaborate(self, platform): + m = Module() + + cd_sync = ClockDomain("sync") + m.domains += cd_sync + platform.lookup(platform.default_clk).attrs['GLOBAL'] = False + + locked = Signal() + pllout = Signal() + + m.submodules.pll = Instance("SB_PLL40_PAD", + p_FEEDBACK_PATH = "SIMPLE", + p_DIVR = 0, + p_DIVF = 7, + p_DIVQ = 1, + p_FILTER_RANGE = 1, + + o_LOCK = locked, + i_RESETB = 1, + i_BYPASS = 0, + i_PACKAGEPIN = platform.request("clk12", dir="-").io, + o_PLLOUTCORE = cd_sync.clk + ) + + ledr0 = platform.request("led_r") + ledg0 = platform.request("led_g") + + ledr1 = platform.request("led_r", 1) + ledg1 = platform.request("led_g", 1) + ledg2 = platform.request("led_g", 2) + ledg3 = platform.request("led_g", 3) + ledg4 = platform.request("led_g", 4) + + half_freq = int(42e6 // 2) + timer = Signal(range(half_freq + 1)) + + init = Signal() + + with m.If(init == 0): + m.d.sync += ledg0.o.eq(255) + m.d.sync += init.eq(1) + + with m.If(timer == half_freq): + m.d.sync += ledr0.o.eq(~ledr0.o) + m.d.sync += ledg0.o.eq(~ledg0.o) + m.d.sync += timer.eq(0) + with m.Else(): + m.d.sync += timer.eq(timer + 1) + + return m + +from amaranth_boards.icebreaker import ICEBreakerPlatform +from amaranth.vendor import SiliconBluePlatform; + +platform = ICEBreakerPlatform() +platform.add_resources(platform.break_off_pmod) +platform.build(LEDBlinker(), do_program=True, verbose=True, nextpnr_opts='--freq 48') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8c20c0a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +amaranth==0.5.7 +amaranth-boards @ git+https://github.com/amaranth-lang/amaranth-boards.git@7e24efe2f6e95afddd0c1b56f1a9423c48caa472 +amaranth-yosys==0.50.0.0.post115 +importlib_resources==6.5.2 +Jinja2==3.1.6 +jschon==0.11.1 +MarkupSafe==3.0.2 +pyvcd==0.4.1 +rfc3986==2.0.0 +wasmtime==36.0.0