tofro wrote:Nasta wrote:MT.IPCOM is a great example as I wonder how often it is used in applications - and I would bet mostly in OS extensions like Toolkit II etc, as there are higher level OS calls that may use it to produce sound or check keyboard rows for pressed keys.
MT.IPCOM actually is the only way to do those two things (keyboard direct scan, joystick input, BEEPing) in an at least somewhat HW-independent way, even on SMSQ/E. All the QL gamers would be quite unhappy without this call (not abstracting these two things is actually a serious omission in SMSQ/E, as all newer QL derivates had to at least somewhat emulate IPC communications in order to implement direct keyboard scan and sound. Even the Q68 does it.
Very important knowledge. What would the particular functions be that you think need to be emulated?
Nasta wrote:Most of serial and even microdrive code sits behind an abstraction layer. Programs that do microdrive direct sector access (so is everything that checks copy-protection), however, have to access the hardware directly. But running copy-protected microdrives is maybe not a thing that happens often nowadays
Yes, that was my line of reasoning too. Keyboard input seems to be the most important part.
The next one is the matter of being able to read the clock 'counter' but that can actually be emulated in hardware in several different ways. If I remember correctly, the clock is set using OS calls so that part of the hardware would not be emulated.
One possible implementation of new hardware would be a different uC interfaced to the bus via a small dual port RAM. While those tend to be expensive (but could possibly be implemented in a FPGA along with other logic), it opens up a whole lot of new options, in particular regarding ports, HID and storage devices, and with some speed too.
The point is, of course, to rather re-write portions of MT.IPCOM (and in fact given more advanced hardware the actual new code might be easier to write!) than attempt to exactly emulate or re-implement an 8302/IPC. I do think some form of IPC (but largely invisible) is a great asset, though not always practical in terms of developing the firmware that runs on it. Given that it, and the corresponding firmware on the QL side would have to be written anew, it sort of intuitively makes one think of approximately squaring the number of bugs one can produce but then, it can also be very powerful.
A long time ago when fast serial ports were all the rage I though up a piece of hardware that had the 68681 DUART (or better) serial chip on it, some RAM and a dedicated 68008 CPU connected to the QL bus via a dual port RAM and some logic. The reason for this was that if you really wanted the port to go fast, the UART chip needed quite a lot of tending by the CPU and that would slow things down on the QL side. So, the idea was for the other 68008 to have it's own interrupt system and just pass buffered data to the QL side via the dual port RAM. The interesting part was that the 'other' 68008 did not have a ROM but would rather start from bootstrap code that would be loaded from the QL side via the dual port RAM, then the rest of the code would be loaded and after that the dual port RAM would be used to communicate data.
This had the advantage of using all the usual development tools and familiar assembler, plus it was all mostly software defined so lots of things could be done. The ampunt of dual port RAM needed is actually small (1k would be enough) and this could be mapped into a convenient place on the QL side. The whole point is to have enough space for some 'mailbox' and circular buffers. Initially, the second CPU is kept in a reset state while the QL side sets up the bootstrap code etc.
That being said, while something like the IPC is laughably slow compared to the 68008, the 68008 is equally slow at these sorts of stupid but fast sort of tasks compared to even very cheap modern 8-bit uCs, but the same idea is quite difficult to do with modern uC chips as they have built-in flash that is pre-programmed (or can be programmed in circuit but with difficulty and/or risk of 'bricking' the hardware) and accessed exclusively as program memory and constant data in the interest of speed, plus the required tool-set is usually PC based. I am aware of less than a handful that are bootstrapped and run from RAM, but willing to be corrected.
Later on as I was thinking about GoldFire, I came up with the idea of adding a whole second CPU, which some may say is a combination of blasphemy and overkill but as strange as it sounds, if the CPU is a 68040 or 60 (some limitation the combination of the two apply) the added price comes down to the actual CPU and board space plus power supply alone. It is a GREAT pity that it's not as easy to implement that idea with 'lesser' members of the family. It comes down to how they can be made to share the bus. Up to and below 68030, the CPU assumes bus ownership and an external device can indeed ask it to relinquish the bus but if this is a second CPU you can't actually know if it REALLY needs the bus (as there may be code and data caching involved) unless you take away the bus from one CPU and give it to the other using external logic, only to find out the other CPU is 'sleeping' and waiting for an interrupt, so the very act of 'testing' it for the need to use the bus was a waste of time for the previous owner of the bus which might have needed to continue using it. The 68040 and 060 and the MCF5102 ColdFire (which is actually a derivative of the 68EC040) request the bus from an external arbiter to begin with and do not assume bus ownership, so external hardware can implement as fair a bus sharing mechanism as one is willing to design, and the chips are essentially run in parallel. The availability of fairly large caches and the fact that most low level IO handling routines are actually short, makes it possible for the entire code to end up running from cache, requiring no access of the bus save for actual data transfers, which can make this sort of thing incredibly flexible and efficient (though care should be taken to sort out interrupts and forcing the CPUs to keep memory data consistency, which actually is not that difficult).
For lesser members of the 68k family, things get rather inefficient if you want to keep them simple (example above with 'testing' the need for bus access), or complex hardware-wise if you want to keep them efficient. In the latter case, each CPU has a separate bus with it's own set of devices on it, and bus bridge hardware to connect the buses to each other when one CPU wants access to the other one's bus, which is usually detected by a decoder - one's CPU bus is mapped into the other's address space and the other way around. This way the arbitrating logic knows when which CPU wants what and can decide when which one can do it or has to wait, on a cycle by cycle basis. The bus bridge can however become a fairly involved piece of hardware as it's also the ideal point to implement, say, a RAM controller- and it would need a rather large number of signals either way, assume 2x 32-bit data bus and not much fewer address lines - on both sides. It does not get drastically simpler even if the second CPU is a much lesser thing like a uC though the required pin count can get lower.