From 753e445b4be0726ef30dd4fec401c50cca9f0f25 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Sat, 14 Mar 2020 21:38:18 +0100 Subject: [PATCH] Initial I2C bus implementation. --- devices/i2c.h | 78 +++++++++++++++++++++++++++++++++++++++++++++ devices/viacuda.cpp | 2 +- devices/viacuda.h | 3 +- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 devices/i2c.h diff --git a/devices/i2c.h b/devices/i2c.h new file mode 100644 index 0000000..b01816f --- /dev/null +++ b/devices/i2c.h @@ -0,0 +1,78 @@ +/* +DingusPPC - The Experimental PowerPC Macintosh emulator +Copyright (C) 2018-20 divingkatae and maximum + (theweirdo) spatium + +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/** @file I2C bus emulation. + + Author: Max Poliakovski + */ + +#ifndef I2C_H +#define I2C_H + +#include + +/** Base class for I2C devices */ +class I2CDevice { +public: + virtual void start_transaction() = 0; + virtual bool send_byte(uint8_t data) = 0; + virtual bool receive_byte(uint8_t *p_data) = 0; +}; + +/** Base class for I2C hosts */ +class I2CBus { +public: + I2CBus() { this->dev_list.clear(); }; + ~I2CBus() { this->dev_list.clear(); }; + + virtual bool register_device(uint8_t dev_addr, I2CDevice *dev_obj) { + if (!this->dev_list[dev_addr]) { + return false; /* device address already taken */ + } + this->dev_list[dev_addr] = dev_obj; + return true; + }; + + virtual void start_transaction(uint8_t dev_addr) { + if (this->dev_list[dev_addr]) { + this->dev_list[dev_addr]->start_transaction(); + } + }; + + virtual bool send_byte(uint8_t dev_addr, uint8_t data) { + if (!this->dev_list[dev_addr]) { + return false; /* no device -> no acknowledge */ + } + return this->dev_list[dev_addr]->send_byte(data); + }; + + virtual bool receive_byte(uint8_t dev_addr, uint8_t *p_data) { + if (!this->dev_list[dev_addr]) { + return false; /* no device -> no acknowledge */ + } + return this->dev_list[dev_addr]->receive_byte(p_data); + }; + +protected: + std::vector dev_list; /* list of registered I2C devices */ +}; + +#endif /* I2C_H */ diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index c3d5ac9..bd5c2ef 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -129,7 +129,7 @@ void ViaCuda::write(int reg, uint8_t value) void ViaCuda::print_enabled_ints() { - static char *via_int_src[] = { "CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1" }; + const char *via_int_src[] = { "CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1" }; for (int i = 0; i < 7; i++) { if (this->via_regs[VIA_IER] & (1 << i)) diff --git a/devices/viacuda.h b/devices/viacuda.h index 2fb9262..c1eaf34 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -47,6 +47,7 @@ along with this program. If not, see . #include "hwcomponent.h" #include "nvram.h" +#include "i2c.h" /** VIA register offsets. */ enum { @@ -100,7 +101,7 @@ enum { }; -class ViaCuda : public HWComponent +class ViaCuda : public HWComponent, public I2CBus { public: ViaCuda();