Connect to a PC

Discuss game and other programming topics not specifically covered in another forum

Moderator: Programming Moderators

User avatar
Maziac
Posts: 110
Joined: Sun Jul 09, 2017 5:56 am

Connect to a PC

Postby Maziac » Sat Dec 21, 2019 11:39 am

Hi,

I would like to connect the Next to another PC and would like to know the best way to do it.
What I would like to achieve is a kind of bidirectional socket connection or similar, also UART or RS232 would be an option.

I would like to be able to "talk" to the PC from the Z80 assembly code, i.e. sending and receiving data.
Receiving should happen in an interrupt so that the Z80 program flow does not have to actively stop to listen.

The ZX Next FPGA seems to have a UART which is used for WIFI. Can I also program this UART directly for my purposes?
Unfortunately I found very little information, only this here:
https://www.specnext.com/the-next-on-the-network/
But it focuses more on the WIFI part.

Any help and ideas appreciated.

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 3:01 pm

Yes, it’s quite straightforward. On the PC end you can use a USB FTDI serial cable (make sure to get one that operates at 3V3 TTL levels). Connect RX, TX and GND to the appropriate pins of the ESP socket (do not connect 5V or 3V3 - this is intended to power the device from the PC, and the Next is already powered!). Alternatively you can solder a socket on J18 and connect to the appropriate pins there (however you shouldn’t connect ESP and FTDI simultaneously).

Program-wise, your PC program should open whatever COM port the FTDI cable gets mapped to (check in device manager on Windows), set the baud (2,000,000 is what we usually use), and set up as 8N1 with no flow control.

At the Next end, switch to the ESP UART (there’s also a Pi UART. The ESP UART the default at boot but a previous program may have switched them). Then read the Next video mode (0..7) and use this to set the UART baud (the UART is tied to the 28MHz master clock, which runs at a slightly different clock for all eight video modes, so the prescalar adjusts for this to give an accurate baud in every mode), then the two UART ports (RX and TX) to send and receive. Both ports have flags, so you read from the TX port to see if the UART has data ready to read, and you can write to the RX port to signal you are not ready to read.

The UART has an internal buffer in the FPGA (1K I think, maybe it is 512 bytes) which can fill up quickly at 2meg, so you are best emptying it in a tight loop into a local buffer in RAM, then processing data from there.

I will follow up this reply with some nextreg and port details, and some code snippets.
Last edited by SevenFFF on Sat Dec 21, 2019 3:15 pm, edited 1 time in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 3:07 pm

CSpect emulates both ESP and Pi UARTs, so you may find it more convenient to prototype your serial code here first.

CSpect’s default mode is to emulate an internal ESP, but there is a command line switch (check the readme) to tell it to forward all serial traffic to a PC COM port instead. So for example CSpect can be configured for COM1, your PC program for COM2, then you can use a virtual COM port loopback utility to cross-connect COM1 To COM2. Alternatively you could connect two FTDI cables back to back.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 3:32 pm

Here is the pinout for the ESP port (remember to connect TX, RX and GND only, do not connect power):

Image

Serial cables are sometimes labelled ambiguously. It won’t damage anything if you connect TX and RX the wrong way round. Just try both ways, and one will work.

Here is the pinout for J15 (remember to not connect serial port to this at the same time that a ESP is pluffed into the ESP port):

Image

Here is an example 2x10 2.5mm right angle box header socket for J15:

https://www.ebay.com/itm/322324441075

Here is an example FTDI cable that has been tested (cheaper ones are available, but we have found not every cable supports every baud rate - some don't support 2 meg at all):

https://www.amazon.com/gp/product/B06ZYPLFNB
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

User avatar
Maziac
Posts: 110
Joined: Sun Jul 09, 2017 5:56 am

Re: Connect to a PC

Postby Maziac » Sat Dec 21, 2019 4:59 pm

Yes, I would really appreciate any code snippets.

Thanks for the many information so far.

Does it mean the same UART is available on 2 different connectors, CN9 and J15?

And for the Z80 SW: Is an interrupt created when the ZX receives new data?

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 5:21 pm

Hi Maziac, no problem :)

Yes, same UART is on both connectors.

There are no hardware interrupts for UART. You can read data and fill RAM circular buffer in your own VBI or line interrupt handler, or just read data and process in the main loop of your program. Whatever is best for your needs.

If you run at 28MHz there should be plenty of time to drain the FPGA buffer, process serial data and do other program tasks.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

User avatar
Maziac
Posts: 110
Joined: Sun Jul 09, 2017 5:56 am

Re: Connect to a PC

Postby Maziac » Sat Dec 21, 2019 5:52 pm

That's a pity.

I'm looking for some way to interrupt a running program.
I don't want to do that in the main program or in the vertical blank interrupt (or any other) as I don't have influence on the program.

The idea I'm after is to create an interface to my debugger IDE. That would mean I have the program being debugged, then a small piece of code for the interfacing to the IDE.
The main problem is how to interrupt a running program. I.e. you start the program from the IDE, let it run and then, in the IDE, you stop the program.

This (stop) information need to be transmitted to the ZX Next and there an interrupt need to be triggered to interrupt the running program.

If I would have to rely e.g. on the vert. blank interrupt this would mean that the original program would have to be changed because the interrupt is used there most probably for some other purposes.

But maybe it's the only way to go.

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 7:35 pm

Right now, the program being debugged needs to cooperate with the debugger. This is not necessarily such a big deal though. I have a similar debugging set up with the Zeus debugger, and it just requires a call to a routine inside the main loop. When the flags say there is no UART activity, the routine can return almost immediately.

There are things you can do with custom ROMs which will make it easier to interop with your debugging host code, but right now there is no way in the Next core to raise a separate interrupt that’s handled with a different handler.

Once the Z80N is set up for mode 2 interrupts then the program’s own mode 2 handler is always going to take the interrupt.

It’s possible to write NextZXOS drivers (.drv files) and register them with the OS to be called from the ROM during mode 1 interrupts. But these only work when mode 1 interrupts are enabled, they are not suitable for general purpose debugging when mode 2 is enabled or interrupts are completely disabled.

It could be possible to put some custom hardware on the expansion bus that raises a mode 0 or NMI interrupt, and perhaps inserts some jump instructions directly on the bus. But without support in the core, I don’t think you could do a similar thing that doesn’t involve custom hardware.

I will mention this to Allen, and see if he has some ideas or plans for future core enhancements.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

User avatar
SevenFFF
Posts: 565
Joined: Mon Jun 05, 2017 5:30 pm
Location: USA

Re: Connect to a PC

Postby SevenFFF » Sat Dec 21, 2019 10:26 pm

This is a quick demo of ParaSys, the remote debugger in Zeus, working cooperatively with Spectron 2084, the program being debugged.

Spectron is my code, and it has a small ParaSys stub built into it which is called once per frame in the main loop. The stub has just enough code to check the UART flags and download the full ParaSys client over the wire and run it, when you issue a debug command from Zeus.



The ParaSys stub is only 139 bytes, so it certainly doesn't add any appreciable overhead to the program being debugged. You can see the stub here:

https://github.com/Threetwosevensixseve ... otStub.inc

Some of this code (the PSSI stuff) relates to the ParaSys protocol which is not open and is specific to Zeus, but you can see the parts which relates to the UART comms, and hopefully get an idea of how it works. The idea is that you'd call BootTestSetup once, to set up the UART baud using the prescalar to compensate for master clock differences due to video timing. Then call BootTest every frame.

The code in BootTest does this check, and returns if there is no UART data waiting to be read. So you can see it is very lightweight.

Code: Select all

                        ld a,high UART_GetStatus        ; Are there any characters waiting?
                        in a,(low UART_GetStatus)       ; This inputs from the 16-bit address UART_GetStatus
                        and UART_mRX_DATA_READY         ; We're just interested in the DATA_READY flag
                        ret z                           ; And we return if there isn't any.
Last edited by SevenFFF on Mon Dec 23, 2019 3:13 pm, edited 1 time in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins

Alcoholics Anonymous
Posts: 775
Joined: Mon May 29, 2017 7:00 pm

Re: Connect to a PC

Postby Alcoholics Anonymous » Mon Dec 23, 2019 6:58 am

If you want a z80 interrupt to be generated by the uart so the pc can initiate a communication, you have no choice but to modify the running program. If the program is running in im2, you have to change the im2 vector table (if it has one and if the uart can operate in im2 mode), or you have to change the interrupt mode to im1 and have your own im1 routine get the interrupt first, check for uart activity and then jump into the program's interrupt routine.

This last one is somewhat promising as the divmmc watches important addresses like the 0x38 for the im1 routine and it will seemlessly page in memory separate from the normal memory space (a divmmc memort bank) and have your own program there to serve the interrupt. The running program would never know about this as your program occupies no space in main memory. However you are still not avoiding having to modify the running program.

Instead you can go a different direction. Initiate a communication from the next itself. If you want to enter the pc debugger, press the divmmc nmi button on the next. A program you write in divmmc memory will be paged in where you can do the communication with the pc. This would be completely hidden from the running program and would not need the running program to be modified at all.

Chris Kirby used this approach in his zx next debugger. You can read about in the facebook group "Spectrum Next Dev" but I will provide a few links here as well:

https://github.com/Ckirby101/NDS-NextDevSystem

Link to his most recent post on fb with video:
https://www.facebook.com/chris.kirby.77 ... 720972848/

Because the divmmc is able to watch certain addresses in the bottom 16K, you can also implement breakpoints this way. Replace a small amount of code in the running program with a call to a special address monitored by the divmmc and the divmmc will page in, allowing your monitor code to initiate communication with the pc.

The next currently has two interrupting sources: the usual frame interrupt of the ula and the new line interrupt. They both work the same way, ie mindlessly asserting /int for about 32 cycles and that's it. There might be more attention paid to interrupts and interrupt sources in the future but it is low priority unless people can find compelling reasons for it. It could be a new dma would require would require something better and that may be the catalyst.


Who is online

Users browsing this forum: No registered users and 4 guests