Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an inaccurate, basic Archimedes. #1355

Merged
merged 235 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
235 commits
Select commit Hold shift + click to select a range
6f0ad0a
Add an empty Archimedes shell.
TomHarte Mar 4, 2024
1f43047
Loop the ARM executor into the build.
TomHarte Mar 4, 2024
79865e2
Avoid ambiguous template parameter; use standard type.
TomHarte Mar 4, 2024
61d4c69
Fix template parameter reference.
TomHarte Mar 4, 2024
0cdca12
Resolve type mismatches.
TomHarte Mar 4, 2024
1b7c364
Eliinate meaningless 'const'.
TomHarte Mar 4, 2024
0b65aa3
Add explicit assignment operator.
TomHarte Mar 4, 2024
341b705
Remove pointless check.
TomHarte Mar 4, 2024
b7a1363
Add an incorrect execution loop.
TomHarte Mar 5, 2024
3877916
Start to establish a memory map.
TomHarte Mar 5, 2024
871c546
Avoid sign change.
TomHarte Mar 5, 2024
ed586e8
Don't write to the PC with logical operations.
TomHarte Mar 5, 2024
ba5f142
Take further stab at TEQ PC, etc.
TomHarte Mar 5, 2024
fe467be
Further stick to existing type.
TomHarte Mar 5, 2024
0d666f9
Get a bit more rigorous about reporting.
TomHarte Mar 6, 2024
ed92e98
Start looking at address translation.
TomHarte Mar 6, 2024
108a056
Execution now runs into a prefetch abort loop.
TomHarte Mar 6, 2024
bbb520f
Transcribe some notes.
TomHarte Mar 6, 2024
4059905
Slightly reorder messaging.
TomHarte Mar 6, 2024
691a42d
Attempt some logical mapping.
TomHarte Mar 7, 2024
173fc93
Add a little protection logic.
TomHarte Mar 7, 2024
3405b3b
Add power-on bit, moving problems forward.
TomHarte Mar 7, 2024
38b5624
Add a little more VIDC detail.
TomHarte Mar 7, 2024
7cdceb7
Add a specific shout-out on prefetch abort, for debugging.
TomHarte Mar 7, 2024
a0f0f73
Fix MOV as unconditional branch.
TomHarte Mar 7, 2024
ae3cd92
Add a 2Mhz tick for timers.
TomHarte Mar 7, 2024
d380cec
Add timers that count.
TomHarte Mar 7, 2024
15ee84b
Fix MUL ambiguity.
TomHarte Mar 7, 2024
f5225b6
Add note to self.
TomHarte Mar 7, 2024
0e92885
Fix ad hoc popcount; ARM does carry 'backwards'.
TomHarte Mar 7, 2024
2a36d0f
Adjust user-mode test.
TomHarte Mar 7, 2024
fa8fcd2
Take another swing at popcount.
TomHarte Mar 7, 2024
f6ea442
Include various debugging detritus.
TomHarte Mar 7, 2024
9bb5dc3
Fix inclusive range.
TomHarte Mar 8, 2024
a46ec4c
Up clock rate to 24Mhz.
TomHarte Mar 8, 2024
9406a97
Add some register switch tests.
TomHarte Mar 8, 2024
ca1c3dc
Add extra comments.
TomHarte Mar 8, 2024
fdef890
Double down on uint32_t.
TomHarte Mar 8, 2024
47f7340
Start hacking in some ARM tests.
TomHarte Mar 9, 2024
08f50f3
Box in flags.
TomHarte Mar 9, 2024
d6f882a
Integrate PC and PSR, guarantee invisible register values.
TomHarte Mar 9, 2024
d059e7c
Disallow copying.
TomHarte Mar 9, 2024
a4cf862
Provide full access to stored registers.
TomHarte Mar 9, 2024
a2896b9
Test register values.
TomHarte Mar 9, 2024
4e7a63f
Do a de minimis checking of memory accesses.
TomHarte Mar 9, 2024
655b1e5
Test PSR and PC.
TomHarte Mar 10, 2024
e17700b
Permit digression for 03110002, temporarily.
TomHarte Mar 10, 2024
06a5df0
Summarise failures.
TomHarte Mar 10, 2024
fbc273f
Add invented model for tests.
TomHarte Mar 11, 2024
21278d0
Correct unaligned accesses.
TomHarte Mar 11, 2024
e9e1db7
Change LDR writeback to destination.
TomHarte Mar 11, 2024
0b42f5f
Make further test-set allowances.
TomHarte Mar 11, 2024
ccdd340
Reads also may or may not be aligned. *sigh*
TomHarte Mar 11, 2024
bd62228
The test set doesn't seem to do word rotation.
TomHarte Mar 11, 2024
336292b
Further correct R15 as a destination.
TomHarte Mar 11, 2024
830d70d
Trust tests on immediate-opcode ROR 0; limit shift by register.
TomHarte Mar 11, 2024
db49146
Figure out what's going on with TEQ.
TomHarte Mar 11, 2024
a28c97c
Simplify privilege test.
TomHarte Mar 11, 2024
ca779bc
Expand test set.
TomHarte Mar 11, 2024
e8c1e8f
Fix RSB carry; unify set_pc.
TomHarte Mar 11, 2024
e745746
Reduce magic constants.
TomHarte Mar 11, 2024
971bfb2
Unify subtractions.
TomHarte Mar 11, 2024
1ccfae8
Remove extra slashes.
TomHarte Mar 11, 2024
a5ebac1
Add RISC OS 3.11 to catalogue, while bug hunting.
TomHarte Mar 12, 2024
8b3c0ab
Take another swing at R15 as a destination.
TomHarte Mar 12, 2024
e9c5582
Add note on ambiguity to be resolved.
TomHarte Mar 12, 2024
6efc41d
Come to conclusion on R15; fix link values.
TomHarte Mar 12, 2024
c6b9155
Attempt to wire up timer interrupts.
TomHarte Mar 12, 2024
5d6bb11
Add return.
TomHarte Mar 12, 2024
2ed031e
Prepare for additional devices.
TomHarte Mar 13, 2024
6b18d77
Eliminate unused variables.
TomHarte Mar 13, 2024
7aeea53
Reduce branchiness.
TomHarte Mar 13, 2024
0e46155
Make bit masks easily testable; expand logging.
TomHarte Mar 13, 2024
4987bdf
Throw less.
TomHarte Mar 14, 2024
19fa0b8
Shush logging, momentarily.
TomHarte Mar 14, 2024
bc27e39
Fix downward block data transfers.
TomHarte Mar 15, 2024
9063852
Undo spurious text change.
TomHarte Mar 15, 2024
1815427
Add minor note on where next.
TomHarte Mar 15, 2024
9d08282
Add enough of a keyboard to respond to reset.
TomHarte Mar 15, 2024
3a899ea
Add test coverage for STM descending, proving nothing.
TomHarte Mar 15, 2024
c25d0e8
Correctly capture mode upon exception.
TomHarte Mar 15, 2024
1979d2e
Don't set interrupt flags before capture.
TomHarte Mar 16, 2024
1c1d289
Adjust IRQ/FIQ return addresses.
TomHarte Mar 16, 2024
635efd0
Clear keyboard interrupts.
TomHarte Mar 16, 2024
47e9279
Add a target for I2C activity.
TomHarte Mar 16, 2024
2712d50
Attempt some inspection.
TomHarte Mar 17, 2024
7b1f800
Extend I2C state machine.
TomHarte Mar 18, 2024
64e0254
Adjust means of waiting out address.
TomHarte Mar 18, 2024
612c9ce
Transfer logging responsibility.
TomHarte Mar 18, 2024
9d858bc
IRQ and FIQ should also store PC+4.
TomHarte Mar 18, 2024
2ad6bb0
Begin foray into disassembly.
TomHarte Mar 19, 2024
623eda7
Output branches and nops correctly.
TomHarte Mar 19, 2024
106937b
Run into the shifts wall with LDR/STR.
TomHarte Mar 19, 2024
9d08478
Document.
TomHarte Mar 19, 2024
17dbdce
Eliminate SDL/scons targets for which brew is broken.
TomHarte Mar 19, 2024
85a738a
Get rigorous on exception addresses.
TomHarte Mar 19, 2024
43a3959
Don't data abort on missing low ROM.
TomHarte Mar 19, 2024
3a2d9c6
Give user access to ROM; clean up a touch.
TomHarte Mar 20, 2024
08673ff
Switch to macro blocks of execution; flail around audio.
TomHarte Mar 20, 2024
b986add
Break apart, switching to delegates for interrupts.
TomHarte Mar 20, 2024
1341816
Break apart, switching to delegates for interrupts.
TomHarte Mar 20, 2024
f7e36a1
Merge branch 'Archimedes' of github.com:TomHarte/CLK into Archimedes
TomHarte Mar 20, 2024
208f3e2
Audio ticks are now included.
TomHarte Mar 20, 2024
389541b
Pipe further sound parameters; obey divider.
TomHarte Mar 20, 2024
a6ec870
Capture more audio detail.
TomHarte Mar 21, 2024
2d6a4d4
Add dummy retrace interrupt.
TomHarte Mar 21, 2024
417c6c4
Announce changes.
TomHarte Mar 21, 2024
847dba8
Divide input pixel rate.
TomHarte Mar 21, 2024
40b5227
Deliver all addresses to the video outputter.
TomHarte Mar 21, 2024
5c645fb
Switch to a fixed output clock; retain addresses.
TomHarte Mar 21, 2024
1f49c3b
Give sound and video somewhere to read from.
TomHarte Mar 22, 2024
2de1a2d
Install and properly clock a CRT.
TomHarte Mar 22, 2024
2ec2351
Finish the thought on magic constants.
TomHarte Mar 22, 2024
0f8bc41
Make first, faulty step into displaying a field.
TomHarte Mar 22, 2024
bbc0d8b
Count time in phase correctly.
TomHarte Mar 22, 2024
66e6285
Give ostensibly clean timing to the CRT.
TomHarte Mar 22, 2024
4ac4da9
Reduce TODOs, do _something_ with border colour.
TomHarte Mar 22, 2024
aa6acec
Don't hoard cycles per line value.
TomHarte Mar 22, 2024
4a2dcff
Endeavour to map colours properly.
TomHarte Mar 22, 2024
ae6cf69
Move responsibility for clock division; reinstate vsync interrupt.
TomHarte Mar 22, 2024
c4e6b18
Manage pixel buffers.
TomHarte Mar 22, 2024
de7b781
Add 4bpp output.
TomHarte Mar 22, 2024
fb5fdc9
Actually apply video divider.
TomHarte Mar 22, 2024
9ea3e54
Fix IRQ/FIQ return addresses.
TomHarte Mar 23, 2024
58bbce1
Avoid display errors upon back-pressure.
TomHarte Mar 23, 2024
5ccb182
Provide key states to the keyboard.
TomHarte Mar 23, 2024
eb34c38
Add very faulty key input.
TomHarte Mar 23, 2024
5967ad0
Sketch out whole protocol, albeit faulty.
TomHarte Mar 23, 2024
09a61cf
Don't expect an ACK after identifying.
TomHarte Mar 24, 2024
4215edd
Reduce noise.
TomHarte Mar 24, 2024
c720f39
Avoid implicit sign cast.
TomHarte Mar 24, 2024
55f92e2
Adjust data abort address.
TomHarte Mar 24, 2024
0e07f80
Use BACK state; accept other ACKs at any time.
TomHarte Mar 24, 2024
ccfc389
Quieten where now confident.
TomHarte Mar 24, 2024
3cf262d
Improve terminology, add more documentation.
TomHarte Mar 24, 2024
189dd17
Reguess state machine, fixing startup display.
TomHarte Mar 24, 2024
c1602cc
The keyboard and interrupts are currently trusted.
TomHarte Mar 24, 2024
3549488
Add round-trip test for status flags.
TomHarte Mar 25, 2024
6980fd7
Add further heavily-manual debugging aids.
TomHarte Mar 25, 2024
5da9e04
Simplify control flow.
TomHarte Mar 25, 2024
fa0a9aa
Eliminate 'has_moved_rom_'.
TomHarte Mar 25, 2024
ae684ed
Formally decode bank/offset/type.
TomHarte Mar 25, 2024
521fca6
Expose full bus to IOC dependents; add notes.
TomHarte Mar 25, 2024
8ba9708
Hopefully resolve the mystery of the latch writes.
TomHarte Mar 25, 2024
1154ffd
Add a 'drive in use' indicator LED.
TomHarte Mar 25, 2024
72a645e
Fix trans; take further crack at MEMC permissions.
TomHarte Mar 25, 2024
d277607
Speed up debug mode.
TomHarte Mar 26, 2024
a2d95cb
Shuffle notes.
TomHarte Mar 26, 2024
fc880ac
Double down on trans mode.
TomHarte Mar 26, 2024
b112987
Do well enough at other colour depths.
TomHarte Mar 26, 2024
f46af4b
OS 3.11 seems to be able to get into BASIC.
TomHarte Mar 26, 2024
9078fc9
Try to formalise I2C events.
TomHarte Mar 26, 2024
342d90c
Advance CMOS/I2C to a seemingly-valid read.
TomHarte Mar 26, 2024
3ba1263
Quieten.
TomHarte Mar 26, 2024
bd4ef5e
Switch to acknowledgement-after.
TomHarte Mar 26, 2024
a393167
Seemingly navigate I2C correctly.
TomHarte Mar 27, 2024
8b04d0e
Enhance and better-document I2C states.
TomHarte Mar 27, 2024
166793e
Reduce I2C chatter.
TomHarte Mar 27, 2024
f38bca3
Take another run at MEMC.
TomHarte Mar 27, 2024
0e17f38
Capture further detail.
TomHarte Mar 28, 2024
f4cf1e5
Attempt to cleave by broad reason.
TomHarte Mar 28, 2024
c04c708
Trade some depth for breadth.
TomHarte Mar 28, 2024
f175dce
Hack in some more potential debugging help.
TomHarte Mar 28, 2024
4fcb85d
Cleave off most remaining reasons for failure.
TomHarte Mar 28, 2024
2e7c1ac
Add note on confusion.
TomHarte Mar 28, 2024
740b0e3
Completely bypass ignored tests.
TomHarte Mar 28, 2024
ea6b838
Add a further category of exclusions.
TomHarte Mar 28, 2024
2ed1187
Determine a couple of further exclusions.
TomHarte Mar 28, 2024
bb339d6
Eliminate trace test; I don't think I'm going to work it through.
TomHarte Mar 28, 2024
ffb5149
Reinstate real CMOS RAM results.
TomHarte Mar 28, 2024
0ddbc67
Switch to default CMOS RAM obtained from RISC OS itself.
TomHarte Mar 29, 2024
2a14557
Be more disciplined about errant accesses.
TomHarte Mar 29, 2024
bda1783
Make new guess at non-byte IOC reads.
TomHarte Mar 29, 2024
a0fdd8f
Resolve magic constant.
TomHarte Mar 29, 2024
8a6bf84
Keyboard: log more, ignore unrecognised commands.
TomHarte Mar 30, 2024
6e64a79
Log failed SWIs.
TomHarte Mar 30, 2024
7227436
Add missing space.
TomHarte Mar 30, 2024
4882d6d
Start adding SWI detail.
TomHarte Mar 30, 2024
1f83a54
Complete list of all currently-failing SWIs.
TomHarte Mar 31, 2024
ec785f3
Add URL as comment.
TomHarte Mar 31, 2024
335d13d
Mildly improve logging, define a few more ROMs.
TomHarte Mar 31, 2024
3197964
As it continues to swell, factor out the junk.
TomHarte Mar 31, 2024
cc122a7
Add an SWI count, to aid in logging.
TomHarte Mar 31, 2024
914b88d
Fix non-debug build.
TomHarte Mar 31, 2024
0866caf
Flaws remain, but acknowledge that pixel rate is double.
TomHarte Apr 1, 2024
7de92a9
Slightly clean up shift code.
TomHarte Apr 2, 2024
7c9715f
Change mind about carry behaviour.
TomHarte Apr 2, 2024
3b62a2f
Restrict video buffer to first 512kb.
TomHarte Apr 2, 2024
609c117
Switch to English RISC OS.
TomHarte Apr 2, 2024
5536946
Add a by-eye crop. A better answer will come.
TomHarte Apr 2, 2024
b19dcfd
Take another run at shifts.
TomHarte Apr 3, 2024
dd127f6
Simplify range.
TomHarte Apr 3, 2024
41c471c
Add a force-user-aware accessor.
TomHarte Apr 5, 2024
7d8a364
Reimplement LDM and STM.
TomHarte Apr 5, 2024
002e235
Force RGB mode.
TomHarte Apr 5, 2024
3f40e40
Reduce debugging heft.
TomHarte Apr 5, 2024
2865190
Resolve video addressing issues.
TomHarte Apr 6, 2024
b821645
Capture cursor palette, switch horizontal field.
TomHarte Apr 6, 2024
cfaea7a
Add cursor within 4bpp pixel area.
TomHarte Apr 6, 2024
543b1c6
Wire mouse events to the relevant class.
TomHarte Apr 6, 2024
0092cb8
Route enough to be able to mess around.
TomHarte Apr 6, 2024
7bf831e
Add missing 'override'.
TomHarte Apr 6, 2024
ed7cd4b
Fix 8bpp output, all-modes cursor.
TomHarte Apr 7, 2024
69aeca5
Aggregate mouse deltas where possible.
TomHarte Apr 7, 2024
547dc29
Remove done TODOs.
TomHarte Apr 7, 2024
d2b077c
Start wiring in a floppy controller.
TomHarte Apr 8, 2024
ffd2982
Tie off initial values; fix FIQ usage.
TomHarte Apr 8, 2024
4f58664
Catch interrupt enables.
TomHarte Apr 8, 2024
5e502df
Forward motor and drive selection.
TomHarte Apr 8, 2024
169298a
Plumb through disk insertion.
TomHarte Apr 9, 2024
b875e34
Mention the Archimedes.
TomHarte Apr 9, 2024
8ab77a3
Attempt to even out columns.
TomHarte Apr 9, 2024
46a4ec1
Reshuffle images.
TomHarte Apr 9, 2024
ee4575b
Attempt a div.
TomHarte Apr 9, 2024
3b75eeb
Try two divs.
TomHarte Apr 9, 2024
82a2e80
Life's too short; just do it in HTML.
TomHarte Apr 9, 2024
dd24f5f
Don't latch video addresses until almost the last minute.
TomHarte Apr 10, 2024
ec73c00
Silence the routine stuff of interrupt masks.
TomHarte Apr 10, 2024
6123350
Improve state guesswork.
TomHarte Apr 10, 2024
a5a653d
Factor vsync state into IO reads.
TomHarte Apr 10, 2024
e2e951a
Fix layout.
TomHarte Apr 10, 2024
d62ea95
Make some intimation towards audio.
TomHarte Apr 10, 2024
d9d675a
Fix scan status scale.
TomHarte Apr 10, 2024
a29f246
Move to more natural position of ownership.
TomHarte Apr 10, 2024
6c6cda3
Use clocking hints.
TomHarte Apr 10, 2024
c134c7b
Fix: signal is 'flyback', not sync.
TomHarte Apr 11, 2024
88bb16f
Install proper filter frequency.
TomHarte Apr 13, 2024
7797946
Generate volume ramp.
TomHarte Apr 14, 2024
6ac6e48
Attempt audio output.
TomHarte Apr 14, 2024
30cca54
Diagnostically try for a square wave.
TomHarte Apr 14, 2024
c3d4d0e
Introduce panning, threading.
TomHarte Apr 17, 2024
06fd91f
Fix period, table lookup.
TomHarte Apr 17, 2024
140228a
Mildly reduce heft of scale read.
TomHarte Apr 17, 2024
fac94a5
Reduce MIPS. Until other performance issues can be resolved.
TomHarte Apr 17, 2024
f7337f2
Adopt 50%:50% tables throughout.
TomHarte Apr 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
name: SDL UI / scons / ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, macos-12, macos-13, macos-14, ubuntu-latest]
os: [macos-14, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
Expand Down
2 changes: 1 addition & 1 deletion Components/9918/Implementation/9918.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ void Base<personality>::posit_sprite(int sprite_number, int sprite_position, uin
}

const auto sprite_row = uint8_t(screen_row - sprite_position);
if(sprite_row < 0 || sprite_row >= sprite_height_) return;
if(sprite_row >= sprite_height_) return; // The less-than-zero case is dealt with by the cast to unsigned.

if(fetch_sprite_buffer_->active_sprite_slot == mode_timing_.maximum_visible_sprites) {
status_ |= StatusSpriteOverflow;
Expand Down
226 changes: 226 additions & 0 deletions Components/I2C/I2C.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
//
// I2C.cpp
// Clock Signal
//
// Created by Thomas Harte on 16/03/2024.
// Copyright © 2024 Thomas Harte. All rights reserved.
//

#include "I2C.hpp"

#include "../../Outputs/Log.hpp"

using namespace I2C;

namespace {

Log::Logger<Log::Source::I2C> logger;

}

void Bus::set_data(bool pulled) {
set_clock_data(clock_, pulled);
}
bool Bus::data() {
bool result = data_;
if(peripheral_bits_) {
result |= !(peripheral_response_ & 0x80);
}
return result;
}

void Bus::set_clock(bool pulled) {
set_clock_data(pulled, data_);
}
bool Bus::clock() {
return clock_;
}

void Bus::set_clock_data(bool clock_pulled, bool data_pulled) {
// Proceed only if changes are evidenced.
if(clock_pulled == clock_ && data_pulled == data_) {
return;
}

const bool prior_clock = clock_;
const bool prior_data = data_;
clock_ = clock_pulled;
data_ = data_pulled;

// If currently serialising from a peripheral then shift onwards on
// every clock trailing edge.
if(peripheral_bits_) {
// Trailing edge of clock => bit has been consumed.
if(!prior_clock && clock_) {
logger.info().append("<< %d", (peripheral_response_ >> 7) & 1);
--peripheral_bits_;
peripheral_response_ <<= 1;

if(!peripheral_bits_) {
signal(Event::FinishedOutput);
}
}
return;
}

// Not currently serialising implies listening.
if(!clock_ && prior_data != data_) {
// A data transition outside of a clock cycle implies a start or stop.
in_bit_ = false;
if(data_) {
logger.info().append("S");
signal(Event::Start);
} else {
logger.info().append("W");
signal(Event::Stop);
}
} else if(clock_ != prior_clock) {
// Bits: wait until the falling edge of the cycle.
if(!clock_) {
// Rising edge: clock period begins.
in_bit_ = true;
} else if(in_bit_) {
// Falling edge: clock period ends (assuming it began; otherwise this is a preparatory
// clock transition only, immediately after a start bit).
in_bit_ = false;

if(data_) {
logger.info().append("0");
signal(Event::Zero);
} else {
logger.info().append("1");
signal(Event::One);
}
}
}
}

void Bus::signal(Event event) {
const auto capture_bit = [&]() {
input_ = uint16_t((input_ << 1) | (event == Event::Zero ? 0 : 1));
++input_count_;
};

const auto acknowledge = [&]() {
// Post an acknowledgement bit.
peripheral_response_ = 0;
peripheral_bits_ = 1;
};

const auto set_state = [&](State state) {
state_ = state;
input_count_ = 0;
input_ = 0;
};

const auto enqueue = [&](std::optional<uint8_t> next) {
if(next) {
peripheral_response_ = static_cast<uint16_t>(*next);
peripheral_bits_ = 8;
set_state(State::AwaitingByteAcknowledge);
} else {
set_state(State::AwaitingAddress);
}
};

const auto stop = [&]() {
set_state(State::AwaitingAddress);
active_peripheral_ = nullptr;
};

// Allow start and stop conditions at any time.
if(event == Event::Start) {
set_state(State::CollectingAddress);
active_peripheral_ = nullptr;
return;
}

if(event == Event::Stop) {
if(active_peripheral_) {
active_peripheral_->stop();
}
stop();
return;
}

switch(state_) {
// While waiting for an address, don't respond to anything other than a
// start bit, which is actually dealt with above.
case State::AwaitingAddress: break;

// To collect an address: shift in eight bits, and if there's a device
// at that address then acknowledge the address and segue into a read
// or write loop.
case State::CollectingAddress:
capture_bit();
if(input_count_ == 8) {
auto pair = peripherals_.find(uint8_t(input_) & 0xfe);
if(pair != peripherals_.end()) {
active_peripheral_ = pair->second;
active_peripheral_->start(input_ & 1);

if(input_&1) {
acknowledge();
set_state(State::CompletingReadAcknowledge);
} else {
acknowledge();
set_state(State::ReceivingByte);
}
} else {
state_ = State::AwaitingAddress;
}
}
break;

// Receiving byte: wait until a scheduled acknowledgment has
// happened, then collect eight bits, then see whether the
// active peripheral will accept them. If so, acknowledge and repeat.
// Otherwise fall silent.
case State::ReceivingByte:
if(event == Event::FinishedOutput) {
return;
}
capture_bit();
if(input_count_ == 8) {
if(active_peripheral_->write(static_cast<uint8_t>(input_))) {
acknowledge();
set_state(State::ReceivingByte);
} else {
stop();
}
}
break;

// The initial state immediately after a peripheral has been started
// in read mode and the address-select acknowledgement is still
// being serialised.
//
// Once that is completed, enqueues the first byte from the peripheral.
case State::CompletingReadAcknowledge:
if(event != Event::FinishedOutput) {
break;
}
enqueue(active_peripheral_->read());
break;

// Repeating state during reading; waits until the previous byte has
// been fully serialised, and if the host acknowledged it then posts
// the next. If the host didn't acknowledge, stops the connection.
case State::AwaitingByteAcknowledge:
if(event == Event::FinishedOutput) {
break;
}
if(event != Event::Zero) {
stop();
break;
}

// Add a new byte if there is one.
enqueue(active_peripheral_->read());
break;
}
}

void Bus::add_peripheral(Peripheral *peripheral, int address) {
peripherals_[address] = peripheral;
}
82 changes: 82 additions & 0 deletions Components/I2C/I2C.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// I2C.hpp
// Clock Signal
//
// Created by Thomas Harte on 16/03/2024.
// Copyright © 2024 Thomas Harte. All rights reserved.
//

#pragma once

#include <cstdint>
#include <optional>
#include <unordered_map>

namespace I2C {

/// Provides the virtual interface for an I2C peripheral; attaching this to a bus
/// provides automatic protocol handling.
struct Peripheral {
/// Indicates that the host signalled the start condition and addressed this
/// peripheral, along with whether it indicated a read or write.
virtual void start([[maybe_unused]] bool is_read) {}

/// Indicates that the host signalled a stop.
virtual void stop() {}

/// Requests the next byte to serialise onto the I2C bus after this peripheral has
/// been started in read mode.
///
/// @returns A byte to serialise or std::nullopt if the peripheral declines to
/// continue to communicate.
virtual std::optional<uint8_t> read() { return std::nullopt; }

/// Provides a byte received from the bus after this peripheral has been started
/// in write mode.
///
/// @returns @c true if the write should be acknowledged; @c false otherwise.
virtual bool write(uint8_t) { return false; }
};

class Bus {
public:
void set_data(bool pulled);
bool data();

void set_clock(bool pulled);
bool clock();

void set_clock_data(bool clock_pulled, bool data_pulled);

void add_peripheral(Peripheral *, int address);

private:
bool data_ = false;
bool clock_ = false;
bool in_bit_ = false;
std::unordered_map<int, Peripheral *> peripherals_;

uint16_t input_ = 0xffff;
int input_count_ = -1;

Peripheral *active_peripheral_ = nullptr;
uint16_t peripheral_response_ = 0xffff;
int peripheral_bits_ = 0;

enum class Event {
Zero, One, Start, Stop, FinishedOutput,
};
void signal(Event);

enum class State {
AwaitingAddress,
CollectingAddress,

CompletingReadAcknowledge,
AwaitingByteAcknowledge,

ReceivingByte,
} state_ = State::AwaitingAddress;
};

}
2 changes: 0 additions & 2 deletions Components/Serial/Line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,7 @@ void Line<include_clock>::update_delegate(bool level) {
// Forward as many bits as occur.
Storage::Time time_left(cycles_to_forward, int(clock_rate_.as_integral()));
const int bit = level ? 1 : 0;
int bits = 0;
while(time_left >= time_left_in_bit_) {
++bits;
if(!read_delegate_->serial_line_did_produce_bit(this, bit)) {
read_delegate_phase_ = ReadDelegatePhase::WaitingForZero;
if(bit) return;
Expand Down
Loading