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.

Partial IPC emulation is possible and works quite nice, the Q68 can work as a proof for that - To my knowledge (and without looking into the code), the Q68 SMSQ/E implementation catches only the keyboard matrix scan and the BEEP command to the IPC in MT.IPCOM, which makes it work with 99% of QL software.

There are, however, some subtile pitfalls in that approach: While IPC comms on an original QL works based on pure polling, the Q68 PS/2 interface needs interrupts enabled for the emulation - KEYROW scans with disabled interrupts thus simply don't work on a Q68, so, games and other software that completely disable the OS won't work properly there. On the other hand, a keyrow scan on the Q68 (it's a simple table lookup) is blazingly fast compared to the same thing on a QL which needs a complete round trip to the IPC.

But that's an acceptable trade-off between accepting slight incompatibilities and insanely complicated emulation of old hardware, IMHO.

tofro wrote:Partial IPC emulation is possible and works quite nice, the Q68 can work as a proof for that - To my knowledge (and without looking into the code), the Q68 SMSQ/E implementation catches only the keyboard matrix scan and the BEEP command to the IPC in MT.IPCOM, which makes it work with 99% of QL software.

There are, however, some subtile pitfalls in that approach: While IPC comms on an original QL works based on pure polling, the Q68 PS/2 interface needs interrupts enabled for the emulation - KEYROW scans with disabled interrupts thus simply don't work on a Q68, so, games and other software that completely disable the OS won't work properly there. On the other hand, a keyrow scan on the Q68 (it's a simple table lookup) is blazingly fast compared to the same thing on a QL which needs a complete round trip to the IPC.

But that's an acceptable trade-off between accepting slight incompatibilities and insanely complicated emulation of old hardware, IMHO.

Tobias

Great data and along the lines how I was expecting it to work. Given a different uC to handle such things and it being interfaced via a small dual port RAM, it would be an easy thing to keep an 8-byte (8x8 bit) representation of the emulated keyboard matrix in the dual port RAM for the QL side MT.IPCOM emulation to look into whenever it wants, and it could hardly be faster than that BTW how does Q68 handle BEEP? I wonder if anyone looked into the IPC code to find out how it generates sound from the various parameters given... I've noticed there is a 'get random' MT.IPCOM command, is it used by the OS to generate random numbers?

tofro wrote:While IPC comms on an original QL works based on pure polling, the Q68 PS/2 interface needs interrupts enabled for the emulation - KEYROW scans with disabled interrupts thus simply don't work on a Q68, so, games and other software that completely disable the OS won't work properly there.

For clarification: The Q68 PS/2 keyboard interface has no own interrupt - it is only polled with the 50/60 Hz interrupt.I think keyrow emulation could be implemented to work with interrupts disabled, by polling the PS/2 interface (maybe more than just once) on each call.

If I remember correctly, the few games which have keyboards issues on the Q68, access the 8302 on hardware level, not just disable interrupts. It were adventures, no timing reasons.

Nasta wrote:I wonder if anyone looked into the IPC code to find out how it generates sound from the various parameters given...

I did, a long time ago. The code is really weird, I think I remember that the BEEP code relied on uninitialised registers, so it‘s basically impossible to emulate 100% correctly. Or I didn‘t understand it 100%, which is always a possibility

I've noticed there is a 'get random' MT.IPCOM command, is it used by the OS to generate random numbers?

Nasta wrote:I've noticed there is a 'get random' MT.IPCOM command, is it used by the OS to generate random numbers?

Not sure what OS you are asking about. For Sinclair QDOS, it doesn't use it (although in theory software could call it directly). QDOS mainly uses command 1 to get the IPC status (50 times per second) and the command to retrieve keystrokes from the IPC keyboard queue (this is different from keyrow). Games and the KEYROW and BEEP commands also call the IPC to directly scan a key row and to start and stop sound. Also, I guess the BAUD command would send the BAUD IPC command.

M68008 wrote:Games and the KEYROW and BEEP commands also call the IPC to directly scan a key row and to start and stop sound.

To my surprise, during Q68 testing, no games were found which directly access the IPC for sound. Do you know any games that do?I was at first considering to implement the IPC inside the Q68 FPGA, but after it was seemingly not needed for sound, I decided not to spend time there.

To my other surprise, the few games which were found to directly access the IPC for keyboard, were not action/arcade games but adventures.

I'm trying to somewhat systematize the internal workings of the 8302 ULA in another thread.

There are a few remaining unknowns, one has to do with the IPC communications, mostly the 'interface interrupt'. Apparently this was not used due to problems with the IPC software, but the Minerva source comments state that it was implemented for Hermes. Has anyone looked into the MT.IPCOM code deep enough to have any good input on this topic?

Also, there are still questions about microdrive operation, which are not actually explained in the microdrive emulation topic elsewhere on this board. The 'mystery' is that the ULA hardware uses only one register to do a parallel to serial conversion, i.e. it is done one byte at a time, but drives both data lines of the microdrive. On read, both data lines are de-serialized and the results are separately loaded into two bytes, presumably to be decoded in software to 1 actual data byte. I have not been able to find a good description on how this is done, including how the ULA recognizes when to start de-serializing the signals. So, again, any input on this would be highly welcome in the 8302 topic.