mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-13 00:25:26 +00:00
Seemingly navigate I2C correctly.
This commit is contained in:
@@ -24,7 +24,7 @@ void Bus::set_data(bool pulled) {
|
|||||||
bool Bus::data() {
|
bool Bus::data() {
|
||||||
bool result = data_;
|
bool result = data_;
|
||||||
if(peripheral_bits_) {
|
if(peripheral_bits_) {
|
||||||
result |= !(peripheral_response_ & 0x200);
|
result |= !(peripheral_response_ & 0x80);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -41,34 +41,51 @@ void Bus::set_clock_data(bool clock_pulled, bool data_pulled) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool prior_clock = clock_;
|
||||||
const bool prior_data = data_;
|
const bool prior_data = data_;
|
||||||
clock_ = clock_pulled;
|
clock_ = clock_pulled;
|
||||||
data_ = data_pulled;
|
data_ = data_pulled;
|
||||||
|
|
||||||
if(clock_) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(prior_data != data_) {
|
if(!clock_ && prior_data != data_) {
|
||||||
|
// Data transition outside of a clock cycle => start or stop.
|
||||||
|
in_bit_ = false;
|
||||||
if(data_) {
|
if(data_) {
|
||||||
// logger.info().append("S");
|
logger.info().append("S");
|
||||||
signal(Event::Start);
|
signal(Event::Start);
|
||||||
} else {
|
} else {
|
||||||
// logger.info().append("P");
|
logger.info().append("W");
|
||||||
signal(Event::Stop);
|
signal(Event::Stop);
|
||||||
}
|
}
|
||||||
} else {
|
} else if(clock_ != prior_clock) {
|
||||||
if(peripheral_bits_) {
|
// Bits: wait until the falling edge of the cycle.
|
||||||
--peripheral_bits_;
|
if(!clock_) {
|
||||||
peripheral_response_ <<= 1;
|
// Rising edge: clock period begins.
|
||||||
}
|
in_bit_ = true;
|
||||||
|
} else if(in_bit_) {
|
||||||
|
// Falling edge: clock period ends (assuming it began; otherwise this is prep, post-start bit).
|
||||||
|
in_bit_ = false;
|
||||||
|
|
||||||
if(data_) {
|
if(data_) {
|
||||||
// logger.info().append("0");
|
logger.info().append("0");
|
||||||
signal(Event::Zero);
|
signal(Event::Zero);
|
||||||
} else {
|
} else {
|
||||||
// logger.info().append("1");
|
logger.info().append("1");
|
||||||
signal(Event::One);
|
signal(Event::One);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +99,7 @@ void Bus::signal(Event event) {
|
|||||||
const auto acknowledge = [&]() {
|
const auto acknowledge = [&]() {
|
||||||
// Post an acknowledgement bit.
|
// Post an acknowledgement bit.
|
||||||
peripheral_response_ = 0;
|
peripheral_response_ = 0;
|
||||||
peripheral_bits_ = 2;
|
peripheral_bits_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto set_state = [&](State state) {
|
const auto set_state = [&](State state) {
|
||||||
@@ -93,11 +110,10 @@ void Bus::signal(Event event) {
|
|||||||
|
|
||||||
const auto enqueue = [&](std::optional<uint8_t> next) {
|
const auto enqueue = [&](std::optional<uint8_t> next) {
|
||||||
if(next) {
|
if(next) {
|
||||||
peripheral_response_ = static_cast<uint16_t>((*next) << 1);
|
peripheral_response_ = static_cast<uint16_t>(*next);
|
||||||
peripheral_bits_ = 9;
|
peripheral_bits_ = 8;
|
||||||
set_state(State::PostingByte);
|
set_state(State::AwaitingByteAcknowledge);
|
||||||
} else {
|
} else {
|
||||||
acknowledge();
|
|
||||||
set_state(State::AwaitingAddress);
|
set_state(State::AwaitingAddress);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -123,7 +139,6 @@ void Bus::signal(Event event) {
|
|||||||
|
|
||||||
case State::CollectingAddress:
|
case State::CollectingAddress:
|
||||||
capture_bit();
|
capture_bit();
|
||||||
|
|
||||||
if(input_count_ == 8) {
|
if(input_count_ == 8) {
|
||||||
auto pair = peripherals_.find(uint8_t(input_) & 0xfe);
|
auto pair = peripherals_.find(uint8_t(input_) & 0xfe);
|
||||||
if(pair != peripherals_.end()) {
|
if(pair != peripherals_.end()) {
|
||||||
@@ -132,8 +147,7 @@ void Bus::signal(Event event) {
|
|||||||
|
|
||||||
if(input_&1) {
|
if(input_&1) {
|
||||||
acknowledge();
|
acknowledge();
|
||||||
set_state(State::PostingByte);
|
set_state(State::CompletingWriteAcknowledge);
|
||||||
// enqueue(active_peripheral_->read());
|
|
||||||
} else {
|
} else {
|
||||||
acknowledge();
|
acknowledge();
|
||||||
set_state(State::ReceivingByte);
|
set_state(State::ReceivingByte);
|
||||||
@@ -145,11 +159,9 @@ void Bus::signal(Event event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case State::ReceivingByte:
|
case State::ReceivingByte:
|
||||||
// Run down the clock on the acknowledge bit.
|
if(event == Event::FinishedOutput) {
|
||||||
if(peripheral_bits_) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_bit();
|
capture_bit();
|
||||||
if(input_count_ == 8) {
|
if(input_count_ == 8) {
|
||||||
active_peripheral_->write(static_cast<uint8_t>(input_));
|
active_peripheral_->write(static_cast<uint8_t>(input_));
|
||||||
@@ -158,13 +170,24 @@ void Bus::signal(Event event) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::PostingByte:
|
case State::CompletingWriteAcknowledge:
|
||||||
// Finish whatever is enqueued.
|
if(event != Event::FinishedOutput) {
|
||||||
if(peripheral_bits_) {
|
break;
|
||||||
return;
|
}
|
||||||
|
enqueue(active_peripheral_->read());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::AwaitingByteAcknowledge:
|
||||||
|
if(event == Event::FinishedOutput) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(event != Event::Zero) {
|
||||||
|
logger.info().append("Peripheral byte not acknowledged");
|
||||||
|
state_ = State::AwaitingAddress;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new byte (including its acknowledge bit).
|
// Add a new byte if there is one.
|
||||||
enqueue(active_peripheral_->read());
|
enqueue(active_peripheral_->read());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool data_ = false;
|
bool data_ = false;
|
||||||
bool clock_ = false;
|
bool clock_ = false;
|
||||||
|
bool in_bit_ = false;
|
||||||
std::unordered_map<int, Peripheral *> peripherals_;
|
std::unordered_map<int, Peripheral *> peripherals_;
|
||||||
|
|
||||||
uint16_t input_ = 0xffff;
|
uint16_t input_ = 0xffff;
|
||||||
@@ -48,7 +49,7 @@ private:
|
|||||||
int peripheral_bits_ = 0;
|
int peripheral_bits_ = 0;
|
||||||
|
|
||||||
enum class Event {
|
enum class Event {
|
||||||
Zero, One, Start, Stop,
|
Zero, One, Start, Stop, FinishedOutput,
|
||||||
};
|
};
|
||||||
void signal(Event);
|
void signal(Event);
|
||||||
|
|
||||||
@@ -56,7 +57,9 @@ private:
|
|||||||
AwaitingAddress,
|
AwaitingAddress,
|
||||||
CollectingAddress,
|
CollectingAddress,
|
||||||
|
|
||||||
PostingByte,
|
CompletingWriteAcknowledge,
|
||||||
|
AwaitingByteAcknowledge,
|
||||||
|
|
||||||
ReceivingByte,
|
ReceivingByte,
|
||||||
} state_ = State::AwaitingAddress;
|
} state_ = State::AwaitingAddress;
|
||||||
};
|
};
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
//
|
//
|
||||||
// CMOSRAM.hpp
|
// CMOSRAM.hpp
|
||||||
// Clock Signal
|
// Clock Signal
|
||||||
//
|
//
|
||||||
// Created by Thomas Harte on 20/03/2024.
|
// Created by Thomas Harte on 20/03/2024.
|
||||||
// Copyright © 2024 Thomas Harte. All rights reserved.
|
// Copyright © 2024 Thomas Harte. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../../Components/I2C/I2C.hpp"
|
#include "../../../Components/I2C/I2C.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace Archimedes {
|
namespace Archimedes {
|
||||||
|
|
||||||
struct CMOSRAM: public I2C::Peripheral {
|
struct CMOSRAM: public I2C::Peripheral {
|
||||||
@@ -18,16 +19,40 @@ struct CMOSRAM: public I2C::Peripheral {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<uint8_t> read() override {
|
std::optional<uint8_t> read() override {
|
||||||
return 0;
|
// VERY TEMPORARY. For now, borrowed from Arcem.
|
||||||
|
// To replace with whatever the system-written default is.
|
||||||
|
static constexpr uint8_t defaults[] = {
|
||||||
|
0x00, 0x83, 0x55, 0x16, 0x14, 0x09, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0x14, 0x00, 0x6f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d,
|
||||||
|
0x00, 0xfe, 0x00, 0xeb, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x10, 0x50, 0x20, 0x08, 0x0a, 0x2c,
|
||||||
|
0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x5c, 0x13, 0x00, 0x00, 0x04, 0xfd, 0x08, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
static_assert(sizeof(defaults) == 256);
|
||||||
|
|
||||||
|
const uint8_t result = defaults[address_];
|
||||||
|
++address_;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(uint8_t value) override {
|
void write(uint8_t value) override {
|
||||||
if(expecting_address_) {
|
if(expecting_address_) {
|
||||||
address_ = value;
|
address_ = value;
|
||||||
|
expecting_address_ = false;
|
||||||
} else {
|
} else {
|
||||||
printf("Write to %d\n", address_);
|
|
||||||
++address_;
|
++address_;
|
||||||
// TODO: write to RAM.
|
// TODO: write.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user