djbottrill / ESP32-Z80-Emulator

Z80 Emulator for ESP32 including Basic and CP/M 2.2
31 stars 7 forks source link

[Question] Input-/Output-problems with the Emu on VGA32 with FabGL-Terminal #2

Closed guidol70 closed 2 years ago

guidol70 commented 2 years ago

Hi, maybe you got an idea for me? I ported the my CutDown/Junior-Version of your emulator to a TTGO VGA32 which does use FabGL-Library-Terminal for VGA-Output.

Now I want to track down some issues:

Input-Problem: On some circumstances I have to press Enter/Return twice to get it recognized. The first time after start is after the Emulator displays "Starting Z80". There I have to press enter to get a prompt. At the A> prompt when I only press Enter or press Enter after some Spaces it does work. When I give the DIR command the Cursor does go to the start of the Line after the first time I press Enter (LF?) and after the second time I press Enter (CR?) it starts the command.

Output-Problem: I could do give the command DIR serveral times (Ok with pressing twice Enter) and the output works fine. But when I start a BASIC-program with a Mandelbrot/Fractal which should output many lines it stops after some lines and I have to press any key to get further display-output.

If you got an VGA32 or would be so nice to take a look at the source - you will find it at https://github.com/guidol70/RC2014_ESP32_Z80_Emulator_VGA32

[EDIT] via the Source-Code I rerouted the emulator output to the USB-serial port of the VGA32 and there is no input/output-problem ;) So I will try to ask the author of FabGL if he has an idea :)

djbottrill commented 2 years ago

Hi Guido,

In the function portIn

change the case UART_LSR to:

case UART_LSR:  //Check for received char
  if (rxOutPtr != rxInPtr) {           //Have we received any chars?
    pIn[UART_PORT] = rxBuf[rxOutPtr];  //Put char in UART port
    rxOutPtr++;                        //Inc Output buffer pointer
    if (rxOutPtr == 1024) rxOutPtr = 0;
    bitWrite(pIn[UART_LSR], 0, 1);  //Set bit to say char can be read
  }

This may fix your problem.

The VGA32 board looks interesting, I will probably order one A.S.A.P.

guidol70 commented 2 years ago

is it correct that only the line if (rxOutPtr == 1024) rxOutPtr = 0; was added?

I did try this, but didnt get another/positive effect :(

I also did try to compile with ESP32-Core v2.0.3rc1 The SDCard did work, but Input/Output is the same. Only when not accepting the command is recognized by the first keypress the screen shows for a short time some blue lines.

[EDIT] On a v1.0.6-compile the output does work at the same time on Serial. and Terminal.

    //Check for chars to be sent
    while (txOutPtr != txInPtr) {           //Have we received any chars?
       Serial.write(txBuf[txOutPtr]);       //Send char to console
      Terminal.write(txBuf[txOutPtr]);      //Send char to Terminal
      // delay(1);
      txOutPtr++;                           //Inc Output buffer pointer
      if (txOutPtr == 1024) txOutPtr = 0;
    }

when I only do use the Serial.Read for input.

I checked the source (mine, yours and FabGL) now many times, but could find any idea for an error. I think about that FabGL may be also use some Task for the input-queue with inference with the SerialTask of the emulation, because with only serial input the emulation seem to work with double-ouput (serial and VGA-terminal).

guidol70 commented 2 years ago

This may fix your problem.

I found a fix for my Input-Problem ;) I did change the source of the Serial input and output buffer task from

void serialTask( void * parameter ) {
  Serial.println("Serial Task Started");
  int c;
  for (;;) {

    //Check for chars to be sent
    while (txOutPtr != txInPtr) {           //Have we received any chars?
      Serial.write(txBuf[txOutPtr]);        //Send char to console
      if (serverClient.connected()) serverClient.write(txBuf[txOutPtr]);
      delay(1);
      txOutPtr++;                           //Inc Output buffer pointer
      if (txOutPtr == 1024) txOutPtr = 0;
    }
    delay(1);
    // Check for Received chars
    int c = Serial.read();
    if (c >= 0) {
      rxBuf[rxInPtr] = c;
      rxInPtr++;
      if (rxInPtr == 1024) rxInPtr = 0;
    }
    delay(1);

  }
}

to

void serialTask( void * parameter ) {
  Serial.println("Serial Task Started");
  int c;
  for (;;) {

    //Check for chars to be sent
    while (txOutPtr != txInPtr) {           //Have we received any chars?
      Serial.write(txBuf[txOutPtr]);        //Send char to console
      txOutPtr++;                           //Increase Output buffer pointer
      if (txOutPtr == 1024) txOutPtr = 0;
                                }
    delay(1);

    // Check for Received chars
    if (Serial.available() > 0) {
      int c = Serial.read();
      rxBuf[rxInPtr] = c;
      rxInPtr++;
      if (rxInPtr == 1024) rxInPtr = 0;
                                }
          }

     delay(1);
                                    }

I could delete the first delay for the output and a new survey for filling the receiving buffer. Mostly did help not to check for >=0 but only for >0

This also did work on my WeMOS ESP32 (he did need the 2 last delays because he would get a kerne-panic without them), but my ESP32S2 does work without these 2 delays of 1ms between transmit and after receive.

In terms of the FabGL-Terminal I switched from the 16 color VGA16-Terminal to the Text-Terminal (non graphical) because if I use VGA16 I cant int the SDCard anymore (with spiSD nor normal SPIinit) in the new V2 version of the emulator.

The WeMOS and the ESP32S2 (Deneyap mini) do work fine with a cutdown/Jr-Version of your new V2 ;)

BTW: I do use the following diskdef for cpmtools for accessing your A.dsk (or new .dsk files):

# esp32z80
diskdef esp32z80
  seclen 512
  tracks 512
  sectrk 32
  blocksize 4096
  maxdir 512
  boottrk 0
  os 2.2
end
guidol70 commented 2 years ago

Input-/Output-problems seem to be solved - for me - with my version of the "void SerialTask"