-
Notifications
You must be signed in to change notification settings - Fork 4
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
Support a F83 RTC and test it on GEOS #103
Comments
My understanding is the following: The GEOS communicates on the cassette port and expects an F83 RTC device. In other words, GEOS expects to be communicating with an I2C device with a specific address and a specific memory map. Therefore, the M2M framework would need to emulate a "virtual" F83 RTC device, while at the same time communicating with the "real" RTC on the board. Essentially, the M2M framework would be the "man-in-the-middle". |
However, much simpler is to re-use MiSTer's emulation The MiSTer emulation file expects a 65-bit signal containing the current date/time, with the following format (see file
The M2M framework would then continuously make sure this signal has the correct value, by appropriate communication with whatever RTC is present on the MEGA65 board. |
This is part of issue #103. Changes to CORE: * Instantiate MiSTer file rtcF83 and connect to tape port. This is used by the GEOS software. Changes to M2M: * Add i2c_controller.vhd. This allows QNICE firmware to communicate with any I2C device, via the framework device ID C_DEV_I2C. Interconnection between CORE and M2M: With this commit, the CORE expects the current date/time to be delivered via the QNICE general purpose register main_qnice_gp_reg_i. TODO: The QNICE firmware should (after reset) read the current date/time from the RTC device (the actual I2C address and register map is board dependent), and then write the date/time value in this generic format: -- Contents of RTC (see user_io.cpp in Main_MiSTer): -- Bits 7 - 0 : Seconds (BCD format, 0x00-0x60) -- Bits 15 - 8 : Minutes (BCD format, 0x00-0x59) -- Bits 23 - 16 : Hours (BCD format, 0x00-0x23) -- Bits 31 - 24 : DayOfMonth (BCD format, 0x01-0x31) -- Bits 39 - 32 : Month (BCD format, 0x01-0x12) -- Bits 47 - 40 : Year (BCD format, 0x00-0x99) -- Bits 55 - 48 : DayOfWeek (0x00-0x06) -- Bits 63 - 56 : 0x40 -- Bit 64 : Toggle flag. Flip whenever the values are changed
After several attempts I have come to the conclusion that the following "hybrid" approach is best: Firstly, the M2M framework (VHDL part) will provide a generic QNICE-memory-mapped interface to the I2C bus. In other words, via QNICE reads/writes to framework device ID C_DEV_I2C it is possible to initiate reads and writes to an arbitrary I2C device. Secondly, the Core makes use of the same interface as on MiSTer, i.e. a 65-bit generic value describing the current date/time in BCD format. This value only needs to be presented once after reset, the core will maintain (i.e. keep up-to-date) its own local copy of the current date/time. What is left (i.e. still not done), is a purely QNICE firmware task:
The benefit of this approach is that the same QNICE register map can be used from the monitor to debug / verify / communicate with (any) I2C devices on the board. Since the next step is a firmware task, I'm reassigning to @sy2002 |
There should also be some menu options. E.g. some users might actually have a real RTC connected via the tape port (just like on a "real" C64), while others would use the onboard RTC (i.e. emulate the GEOS-compatible RTC). There is also the "confusion" about the "original" RTC on the R3 board, and a "modified" RTC. I don't know if it's possible to auto-detect which is the case. Probably, but if not, the user would have to make the selection. Other TODOs for the VHDL part:
|
On the R4 board, the following sequence of operations will read out the date/time from the RTC:
Similar sequence (with few alterations) should work for both R3 variants. |
One idea to auto-detect the RTC, is to monitor bit 2 of value 0x70F1 (Status.2 = NACK). This bit is set when there is no device responding. |
Regarding detecting the board revision, I propose to use the SysInfo record. Specifically to introduce a new record: C_SYS_BOARD with value 0x0040. Then address 0 could be one of: R3 : 0x0003 The VHDL part would then be responsible for populating the correct value (based on the generic G_BOARD). |
The following lists the various I2C busses on the various board. For each bus there is a separate pair of SCL/SDA pins on the FPGA. The naming of the busses is from the schematic. R3:
R4:
R5:
In order to support RTC on the R3 board, we must be able to communicate with both the "FPGA" bus (the internal RTC), and the "Grove" bus (the external RTC connected via PMOD). |
@MJoergen : Makes sense for me - let's make it so. We already have a poll-loop in the firmware, so the firmware can rather easily ensure that the output signal stays updated. I am not sure if we should use |
Since we agree so far, I've now merged the branch "mfj_rtc_support" into the "develop" branch. |
Since this whole RTC feature is very much core-dependent, I was thinking about having the necessary QNICE firmware be placed in the core-specific file We could do that as a first step, and if we see a recurring pattern for other cores, then we can refactor as needed. |
I am not fully getting why the firmware is core specific? If we had a new dedicated VHDL signal that is provided in main.vhd and that is for example formatted like the MiSTer format: Couldn't the CPP take it from there? And then the firmware would be non-core-specific? "Formatting" or "converting" this 64 bit std_logic_vector would be something that happened inside main.vhd (or mega65.vhd) and the firmware just make sure that it is updated at least 10x per second or so. |
My bad. I agree with you. The process of reading the date/time from the (board-specific) RTC and converting to the "generic" date/time format is completely core-independent. It is only the subsequent processing of this generic date/time information from the framework, which is core-specific. So the question remains, whether this should be presented as part of the |
Since this is our "first" use of I2C, there are some architectural choices to be made. Specifically, should we support e.g. the Audio DAC? The Audio DAC works differently on the three boards, and it's connected differently too (i.e. different I2C bus and different I2C address). If we want to support the Audio DAC, should the "knowledge" of connectivity of the Audio DAC (i.e. which I2C bus and I2C address to use) be placed in VHDL and abstracted away, or should the QNICE firmware be in full control? Since we're currently only using the I2C interface for the RTC, this decision is conveniently postponed. But the current implementation provides no abstraction, and expects the QNICE firmware to be in full control / knowledge of which devices (e.g. Audio DAC) are connected to which I2C busses and with which I2C addresses. |
If technically possible at all going forward (and I admittedly did not think it through) I would prefer a completely board-revision agnostic firmware: Everything should be abstracted away on the VHDL part of the house. Now... ...this is my wishful thinking. You @MJoergen decide what is feasible at all. And since I will not be able to work at this issue any time soon: Feel free to refactor everything you've done so far and yes, we should add a dedicated (64-bit?) signal for RTC to the framework. |
I understand your point of view. This will require some thought, because there are many ways to do this. But I understand that the firmware just "wants" the date/time somehow, without having to worry about the implementation (i.e. board specific) details. This is really the same requirement the core has. If this is done completely, then the firmware need not be involved at all. Thinking out loud: The VHDL code could implement a small state machine that (upon request, e.g. after reset) goes through a pre-defined (but board-specific) set of reads/writes. This will be interfacing with the RTC module over the I2C bus using the new QNICE-to-I2C wrapper (implemented in So I will have three (or so) sets of QNICE accesses (read/writes), written in a small table, and fed into a small state machine. This entity would be called The only thing missing here is how to arbitrate between this new However, if I connect the arbiter only to the QNICE-2-I2C wrapper (instead of the entire general QNICE memory mapped I/O), then the QNICE firmware will not be impacted (assuming it is not itself speaking with the I2C devices). Then the memory location In conclusion, that is entirely doable, and the work so far is not in vain. I'm re-assigning to myself again. |
👍🏻 Sounds promising :-) |
@MJoergen ✅ WORKS IN GEOS, see screenshot: One needs to install the RTC driver by copying the driver file on the local GEOS boot disk: |
@MJoergen Please decide if you consider this as a long hanging fruit for 5.1. If not, then remove the 5.1 surge label.
This issue needs the following M2M hardware abstraction first, so that the three different RTCs on the MEGA65 are abstracted away from the C64 core (and so that other cores such as the ZX Spectrum can leverage the RTC, too):
sy2002#29
Information on how to support an RTC on the C64
The text was updated successfully, but these errors were encountered: