bozimmerman / Zimodem

ESP8266/ESP32/Arduino custom modem<->internet simulator with lots of features
Apache License 2.0
413 stars 91 forks source link

Using Zimodem/c64net from cc65? #26

Closed MartinEmrich closed 5 years ago

MartinEmrich commented 5 years ago

Hi!

Just dusted off my good old C64 and soldering iron, and built myself a c64net adapter (using this schematic: https://www.c64-wiki.de/wiki/Wifi-Adapter (the schematic at the bottom).

I got the demo programs included in Zimodem working, and took a look at some telnet BBSes... Yay!

Now I try to write some software to use it, using cc65, I want to interact with a service running on my PC.

I use some code found here: https://coronax.wordpress.com/2015/01/06/figuring-out-commodore-64-rs-232/ (the last comment at the bottom of the page). Apparently the cbmk* functions are wrappers around the Kernal routines, essentially doing the same as OPEN 2,.., PRINT#2, GET#2 etc.

But I run in some issues: as soon as the connection to my server (simple TCP service running on my PC) is established, I sometimes receive junk characters, sometimes I see parts of the text sent by the server. Looks like baud rate/handshake/transmission issues. (I rule out ASCII/PETSCII conversion issues, I only send the string "alive" so far, some times it is even received correctly)

Now I am confused:

Thanks,

Martin

bozimmerman commented 5 years ago
  1. Yes. The kernal routines should work fine. The sample disk that comes with the firmware uses the kernal in both BASIC (in some examples) and ML (in most).
  2. You'll have to compare the pin assignments of your schematic with ours to answer that first question. 2a. No, the C64 kernal does not manage hardware handshaking, you need to do that by hand. The typical way is to watch the two buffer index registers to see how full or empty the buffer is, and alter the UP pins accordingly.
  3. AFAIK, the kernal doesn't manage software handshaking either. Also needs to be done manually. I've tried SWHS in programs like Novaterm in ATF1 mode, and it definitely works. Novaterm can also prove hardware HS as well.
  4. Can't help you there, man., as I only program Commodore software on Commodore computers (and then use a conversion tool to publish on github).
bozimmerman commented 5 years ago

Oh, the earlier problem definitely sounds like a baud rate issue, but it might also be a buffer overflow issue? It's hard to say from way over here.

MartinEmrich commented 5 years ago

Thanks... Buffer issues are unlikely, my little TCP test service sends only a few bytes.

But my current assumption is that the code generated by cc65 somehow meddles around with interrupts or timing, conflicting with the kernal serial routines. I'll investigate in that direction.

MartinEmrich commented 5 years ago

I made some progress, maybe someone will find this helpful:

I had no success with using the Kernal routines from my C program. I also had issues from BASIC; while INPUT# works fine, repeatedly calling GET# also returned garbled characters.

Then I found a serial driver for cc65 at https://github.com/nanoflite/c64-up2400-cc65. The catch: it only supports 2400baud. It apparently also only works if the Kernal serial routines have not been initialized, so I was unable to switch Zimodem from 1200 to 2400baud "on the fly" first.

I thus switched my board to 2400baud permanently via the USB terminal on my PC (open serial monitor with 1200baud, enter ATB2400, switch to 2400baud, then enter AT&W to save permanently).

Now this little program works:

#include <conio.h>
#include <stdio.h>
#include <unistd.h>
#include <serial.h>
#include <string.h>

void test_port()
{
    /* Warning: c64-up2400 _only_ supports 2400baud (source: 
       https://modelrail.otenko.com/electronics/commodore-64-serial-interface-to-arduino) */

    const struct ser_params sp = {SER_BAUD_2400, SER_BITS_8, SER_STOP_1, SER_PAR_NONE, SER_HS_NONE};
    unsigned char i = 0;
    const unsigned char *cmd = "ATI5\r\n";
    unsigned char rc = 0;
    unsigned char c = 0;

    printf("Loading driver...");
    rc = ser_load_driver("c64-up2400.ser");
    printf("Result: %u\n", rc);
    if (rc != 0)
    {
        printf("Loading failed, aborting.");
        /* check if the driver is on your floppy with the correct name:
           c64-up2400.ser (all caps on LOAD"$",8) */
        return;
    }

    // open serial port
    rc = ser_open(&sp);
    printf("ser_open rc=%u\n", rc);

    // enable serial (Source: http://www.cbmstuff.com/forum/printthread.php?tid=353)
    rc = ser_ioctl(1, NULL);
    printf("ser_ioctl rc=%u\n", rc);

    // send some command
    i = 0;
    do
    {
        do
        {
            rc = ser_put(cmd[i]);
            if (rc == SER_ERR_OVERFLOW)
            {
                printf("overflow\r");
            }
        } while (rc == SER_ERR_OVERFLOW);
        ++i;
    } while (cmd[i] != 0);

    printf("sent %s\n", cmd);

    // read response
    while (1)
    {
        rc = ser_get(&c);
        if (rc != SER_ERR_NO_DATA)
        {
            printf("%c", c);
            //printf("Got: %c (0x%02x)\r", c, c);
        }
    }
}

void main()
{
    test_port();
}

Cheers, Martin