2
\$\begingroup\$

Rookie Drive is a cartridge for MSX computers that has a CH376 USB host/device controller and one USB-A connector.

enter image description here

The two CH376 ports are mapped to two of the Z80 ports in 8 bit parallel mode. Pretty simple (from a developer perspective at least).

The original BIOS supplied in the cartridge ROM configures the CH376 in host mode and allows working with disk image files thanks to the dedicated file management features of that chip.

I wanted to develop my own BIOS ROM to work with floppy disk drives instead, and to help in that the maker of the cartridge sent me this:

enter image description here

That's a CH376 module from LC Technologies soldered to an Arduino board. The Arduino runs a very simple server program that listens for commands on the serial port, these commands are for reading and writing the CH376 ports.

enter image description here

So from my MSX emulator I hook on reads and writes to the dedicated Z80 ports, send the appropriate commands to the Arduino via serial port, wait for it to finish, and return the resulting data (if any) to the emulated Z80. That's somehow complex and slow, but it works and allows me to do cross-development.

I finished the floppy disk BIOS project a few years ago, thus so far so good. And (thanks for your patience) here comes the problem I'm having now.

Since the CH376 also supports working in device mode (it's compatible with the CH372) I wanted to experiment by setting the chip in that mode. So that's the prototype C# code I wrote (ch is an instance of a class that handles the communication with the Arduino and thus with the chip):

ch.WriteCommand(CHECK_EXIST);
ch.WriteData(0x57);
var data = ch.ReadData();
if(data != 0xA8) {
    throw new Exception("CH372 hardware not found!");
}

ch.WriteCommand(RESET_ALL);
Thread.Sleep(50);

ch.WriteCommand(SET_USB_ID);
ch.WriteData(0x34);
ch.WriteData(0x12);
ch.WriteData(0x78);
ch.WriteData(0x56);

ch.WriteCommand(SET_USB_MODE);
ch.WriteData(2);
for (int i = 50; i >= 0; i--)
{
    if (ch.ReadData() == CMD_RET_SUCCESS)
        break;

    if(i == 0)
        throw new Exception("Timeout on set USB mode");

    Thread.Sleep(1);
}

ch.WriteCommand(CHK_SUSPEND);
ch.WriteData(0x10);
ch.WriteData(0x04);

while(true)
{
    var intstatus = ch.ReadStatus();
    if ((intstatus & 0x80) != 0)
        continue;

    ch.WriteCommand(GET_STATUS);
    var status = ch.ReadData();
                
    if(status == USB_INT_USB_SUSPEND)
    {
        Debug.WriteLine("Disconnected!");
        ch.WriteCommand(ENTER_SLEEP);
        continue;
    }
                    
    if(status == USB_INT_WAKE_UP)
    {
        Debug.WriteLine("Connected!");
    }
    else
    {
        Debug.WriteLine($"Interrupt received: {status}");
        //TODO: Handle interrupt
    }

    ch.WriteCommand(UNLOCK_USB);
}

So I connected the Arduino board to my PC via the USB-B port as usual, but this time I also connected it to another port of the PC via the USB-A port (instead of connecting a device); I ran the code expecting the PC to detect the CH376 as a device... but that didn't happen. The PC did nothing. I expected at least an "Unrecognized device" notice.

Worth noting that the SET_USB_MODE command I'm running sets the CH376 in "device mode with internal firmware", according to the datasheet this means that the chip itself handles all the device setup and initial configuration (by communicating with the host via endpoint 0) and I just need to wait for IN/OUT requests on the bulk and interrupt pipes that the chip provides.

Also I have verified that the cable I'm using is a good one, it's not one of these "charge only" cables. If that helps it's an USB A-C cable, and the computer is a MacBook running Windows 10 via Bootcamp.

Connections and disconnections of the cable work as expected (I receive the "connected" and "disconnected" notifications), but I'm not receiving any other kind of interrupt from the chip.

So, what's going on here? Why isn't the PC even detecting the CH376 as a plugged USB device? Thinks I can think of:

  • A problem with the Arduino or the module I'm using (unlikely, as evertyhing works fine when I configure the chip in host mode)
  • There's some difference in the physical configuration needed for the module relative to working in host mode (also unlikely I think, D+ and D- of the chip are connected directly to the USB port and I can't think of any other connection possibility)
  • I'm misunderstanding some part of how the CH376 is supposed to work in device mode (likely)
  • There's something wrong or missing in my code (also likely, but I can't see what could it be)

And that's what I have, at this point I'm really stuck. Any hint will be much appreciated.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I have found that it works in these cases:

  • I connect the board to a PC (instead of connecting it to a Mac).
  • I connect the board to the Mac through an USB hub (instead of directly to the computer port).

So it looks like some kind of incompatibility between the CH376, or the module holding it, with the Mac. If anyone can provide more details about what's going on I'll accept the answer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.