gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Hardware > Debugging serial bit-banging without an oscilloscope?

#141781 - tepples - Sat Sep 29, 2007 8:52 pm

I'm trying to make a GBA program so that I can use the GBA as a controller for any GameCube game, not just the ones that support the GameCube to GBA cable. This requires communicating over JOYBUS, the GameCube controller port protocol. But GBATEK states that the GBA serial chip intercepts some JOYBUS commands and sends responses before my program even sees them. Specifically, it identifies itself as a GBA (0x0004), not a GameCube controller (0x0900).

So I have to handle JOYBUS with bit-banging in general purpose mode. Google found this and this and this. I've successfully received "command" bytes from a GameCube and from a third-party GameCube to USB adapter. But when I try to respond to these command bytes, I get no result on the screen, just as if I had not plugged in the cable. Is there a way to see what is actually coming out of my GBA's serial port when I call the send_bits() function that I wrote without spending $250 to buy an oscilloscope? Has anyone tried this already who is willing to look at my code?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#141843 - truedream - Sun Sep 30, 2007 8:29 pm

tepples wrote:
I'm trying to make a GBA program so that I can use the GBA as a controller for any GameCube game, not just the ones that support the GameCube to GBA cable. This requires communicating over JOYBUS, the GameCube controller port protocol. But GBATEK states that the GBA serial chip intercepts some JOYBUS commands and sends responses before my program even sees them. Specifically, it identifies itself as a GBA (0x0004), not a GameCube controller (0x0900).

So I have to handle JOYBUS with bit-banging in general purpose mode. Google found this and this and this. I've successfully received "command" bytes from a GameCube and from a third-party GameCube to USB adapter. But when I try to respond to these command bytes, I get no result on the screen, just as if I had not plugged in the cable. Is there a way to see what is actually coming out of my GBA's serial port when I call the send_bits() function that I wrote without spending $250 to buy an oscilloscope? Has anyone tried this already who is willing to look at my code?


hi I cant help immediatly, but I have working proto of slot-2 FPGA board that also is useable as logic analyzer, the product is going to manufacturing soon, so I may send you sample ;)

I am about to twiddle with the link port myself too but this is low priority on my list right now

Antti

#141904 - KeithE - Mon Oct 01, 2007 2:13 pm

Tepples, I hope you can do this. I tried a while ago and I gave up because it didn't seem like it was possible to make the GBA respond fast enough. My work is discussed in this topic: http://forum.gbadev.org/viewtopic.php?t=9482

I have read that you can make an inexpensive logic analyzer using the parallel port of a computer, but I've never tried it.

#141906 - truedream - Mon Oct 01, 2007 2:28 pm

KeithE wrote:
Tepples, I hope you can do this. I tried a while ago and I gave up because it didn't seem like it was possible to make the GBA respond fast enough. My work is discussed in this topic: http://forum.gbadev.org/viewtopic.php?t=9482

I have read that you can make an inexpensive logic analyzer using the parallel port of a computer, but I've never tried it.


any MCU doing overage 8MIPS can handle GC joybus slave mode
in 100% software bitnbang mode.

so its doable with GBA of course by using the ext conn in GPIO
mode, if its reasonable is another question

#153763 - bluesceada - Sat Apr 05, 2008 5:14 pm

Hey you are doing the same I wanted to do.. did you get any further until now?

(but I already needed to gave up at the compiler, see another topic)

Are you trying with a direct gba<->gc cable? Because most cables have a small circuit inside that is maybe doing the wrong thing for this case? I should check what is inside mine...

Other than that, maybe you also need to first "register" the type of gamecube controller on the gamecube before being able to already send the 64bit signal of "key information".

Then if you think timings are too short you also might to use assembler to send signals, at around 16mhz, 1us is not that long.

Hm what an idea -- as I can't get the compiler to work I should maybe just look into assembler and what is available in this part.

It would be also nice, if you show your C code here you have so far, if more people see it, more people can think about optimizing it.

#153897 - tepples - Tue Apr 08, 2008 12:52 am

main.c
Code:
#include <gba.h>
#include "agbtty.h"
#include <stdio.h>


static void serial_set_gp_mode(void) {
  REG_RCNT = R_GPIO;
}

static void serial_gp_monitor(void) {
  while (1) {
    unsigned int read = REG_RCNT;
    unsigned int color = 0;
    if (read & GPIO_SI) {
      color |= RGB5( 0,31,31);
    }
    BG_PALETTE[0] = color;
  }
}

int get_bits(char *bitlens);
void send_bits(const char *bits, size_t n);


#define TIMER ((volatile u32 *)(0x04000100))
#define TMCNT(x) ((x) << 16)
// libgba and libnds differ on naming
#ifndef TIMER_ENABLE
#define TIMER_ENABLE (1 << 7)
#endif
#ifndef TIMER_CASCADE
#define TIMER_CASCADE (1 << 2)
#endif

void startTimer(void) {
  TIMER[2] = 0;
  TIMER[3] = 0;
  TIMER[3] = 0 | TMCNT(TIMER_CASCADE | TIMER_ENABLE);
  TIMER[2] = 0 | TMCNT(TIMER_ENABLE);
}

u32 readTimer(void) {
  unsigned int lo = TIMER[2] & 0xFFFF;
  unsigned int hi = TIMER[3] & 0xFFFF;

  // If the timer wrapped between reading lo and hi, reread once.
  unsigned int lo2 = TIMER[2] & 0xFFFF;
  if (lo2 < lo) {
    hi = TIMER[3] & 0xFFFF;
    lo = lo2;
  }
  return lo | (hi << 16);
}

void time_send_bits(int n) {
  char bits[65] = {0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1};
  u32 stime, etime;

  startTimer();
  stime = readTimer();
  send_bits(bits, n);
  etime = readTimer();
  siprintf(bits, "%u ", etime - stime);
  agbtty_puts(bits);
}

void test_get_bits(void) {
  char bitlens[33];
  size_t len = get_bits(bitlens);
  for (int i = 0; i < len; ++i) {
    MAP[4][7][i] = bitlens[i] < 2 ? '1' : '0';
  }
  for (int i = len; i < 30; ++i) {
    MAP[4][7][i] = ' ';
  }
  agbtty_gotoxy(0, 8);
  siprintf(bitlens, "%2u ", (unsigned int)len);
  agbtty_puts(bitlens);
}

unsigned int wait_cmd_byte(void) {
  char bitlens[33];
  get_bits(bitlens);
  unsigned int bits = 0;
  for (int i = 0; i < 8; ++i) {
    bits = (bits << 1) | (bitlens[i] < 2);
  }
  agbtty_gotoxy(6, 8);
  {
    char txt[32];
    siprintf(txt, "%02x ", bits);
    agbtty_puts(txt);
  }
  return bits;
}

int main(void)
{
  agbtty_init();
  //agbtty_init_cursor();

  REG_DISPCNT = 0 | BG0_ON | OBJ_ON;
  BG_PALETTE[  0] = RGB5(31,31, 0);
  BG_PALETTE[  1] = RGB5( 0,31, 0);
  SPRITE_PALETTE[1] = RGB5(16,16, 0);

  agbtty_puts("hello world\n\n");
  serial_set_gp_mode();
 
  time_send_bits(1);
  time_send_bits(65);
  /* difference should be close to 1024 */
 
  while (1) {
    char ctrlbits[65] = {0};
    int j = (~REG_KEYINPUT);
    ctrlbits[3] = j & KEY_START;
    ctrlbits[16] = 1;
    ctrlbits[24] = 1;
    ctrlbits[32] = 1;
    ctrlbits[40] = 1;
    ctrlbits[48] = 1;
    ctrlbits[56] = 1;
    int c = wait_cmd_byte();
    switch (c) {
    case 0:  // identify
      {
        char sig[25] = {0, 0, 0, 0, 1, 0, 0, 1,
                        0, 0, 0, 0, 0, 0, 0, 0,
                        0, 0, 0, 0, 0, 0, 0, 0, 1};
        send_bits(sig, sizeof(sig));
      }
      break;
    case 0x40:  // send buttons
      {
        send_bits(ctrlbits, 65);
      }
      break;
    }
  }
  while(1);
}


getbits.iwram.c
Code:
#include <gba_sio.h>
#include <gba_video.h>
#include <sys/types.h>

int get_bits(char *bitlens) {
  unsigned int bitno = 0, uplen = 0;
  while (REG_RCNT & GPIO_SI) { }
  BG_PALETTE[0] = RGB5(31,23, 0);
  do {
    unsigned int downlen = 0;
    uplen = 0;
    while (downlen < 60 && !(REG_RCNT & GPIO_SI)) {
      ++downlen;
    }
    while (uplen < 60 && (REG_RCNT & GPIO_SI)) {
      ++uplen;
    }
    bitlens[bitno++] = downlen;
  } while (uplen < 60 && bitno < 33);
  BG_PALETTE[0] = RGB5(31,31,31);
  return bitno;
}

#if 1
  #define SO_HI (R_GPIO | GPIO_SO_OUTPUT | GPIO_SO)
  #define SO_LO (R_GPIO | GPIO_SO_OUTPUT)
#else
  #define SO_HI (R_GPIO | GPIO_SI_OUTPUT | GPIO_SI)
  #define SO_LO (R_GPIO | GPIO_SI_OUTPUT)
#endif
void send_bits(char *bits, size_t len) {
  for (size_t i = 0; i < len; ++i) {
    unsigned int data = bits[i] ? SO_HI : SO_LO;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_HI;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = SO_LO;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
    REG_RCNT = data;
  }
  REG_RCNT = R_GPIO;
}


I was able to get get_bits working, recognizing the status bytes that Melee was sending. But I could never actually send anything, and I don't know why because I don't own a logic analyzer.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#153965 - bluesceada - Tue Apr 08, 2008 6:54 pm

I didn't read all of the code exactly, but it seems you dont test for those 24 "welcome" bits of the gamecube (0100 0000 0000 0011 0000 0010) and just check if any bits get received?

And all those
REG_RCNT = SO_HI;
REG_RCNT = SO_LO;
REG_RCNT = data;
would maybe get optimized-out by the compiler to one single "REG_RCNT = data;"
check my looking in the resulting assembler code, one time with all those lines, and one time with just the "REG_RCNT = data;"

Then: Do you send the whole 64(65)bit of data? that one array with an max. index of 65 is not really filled up?

In some days/weeks (depending on my time) I might come up with my first try..

What is also important: Do you use the correct cable? So far I didn't exactly look at the circuit which is inside my "original" gba<->gc cable..

Maybe you got some hints my me, and sorry for not reading the whole code step by step.

#153977 - tepples - Tue Apr 08, 2008 9:41 pm

bluesceada wrote:
I didn't read all of the code exactly, but it seems you dont test for those 24 "welcome" bits of the gamecube (0100 0000 0000 0011 0000 0010) and just check if any bits get received?

I think I was testing for those, but I removed it when I couldn't get any sort of response at all.

Quote:
And all those
REG_RCNT = SO_HI;
REG_RCNT = SO_LO;
REG_RCNT = data;
would maybe get optimized-out by the compiler to one single "REG_RCNT = data;"

REG_RCNT is volatile. I've already run timing tests, and the more REG_RCNT writes I put in, the longer it takes.

Quote:
Then: Do you send the whole 64(65)bit of data? that one array with an max. index of 65 is not really filled up?

I would need a logic analyzer to answer that.

Quote:
What is also important: Do you use the correct cable?

I would need a logic analyzer to answer that.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#153981 - bluesceada - Tue Apr 08, 2008 10:34 pm

I don't think you necessarily need a logic anaylzer for that... That would be trial and error coding, which is often the fastest way - okay, but also can result in working, but not really clean working code

If you are 100% sure what every part of your code does and how your connection circuit is assembled, you can in nearly all / most cases say what the hardware will do.

Anyway.... I will try it when time permits, I hope I can come up with a working code (and the way the cable has to be connected or what schematic you need to connect it) soon.

In the most simple case both the GBA input and output (whatever pins you will use for those) would need to be connected to that one wire the GC uses for Data Transfer, with 2 Diodes blocking the lines in one direction so we don't get some unwanted problems.

So I have to check what the official cables circuit does (yeh actually I need to open it up with a screwdriver then, otherwise you really just can use a logic anaylzer), they might help to do something completely different, as the GBA is normally connected to the Gamecube as not just a Controller.

#153985 - tepples - Tue Apr 08, 2008 11:49 pm

bluesceada wrote:
That would be trial and error coding

For me, it was more like trial and error and error and error and error and error and error and spend 5 hours getting no response from the system with which I'm trying to communicate and switch to working on one of my other projects coding.

Quote:
If you are 100% sure what every part of your code does

What steps would you recommend that I take to become 100% sure what every part of my code does?

Quote:
and how your connection circuit is assembled

If only I had a multimeter, the money to buy a second cable to tear apart, and the time to do this instead of my other projects...

Quote:
you can in nearly all / most cases say what the hardware will do.

In this case, I don't know what the hardware will do, especially the hardware on the other side of the cable.

Quote:
Anyway.... I will try it when time permits, I hope I can come up with a working code (and the way the cable has to be connected or what schematic you need to connect it) soon.

Good luck with your work ;-)
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#154025 - bluesceada - Wed Apr 09, 2008 5:30 pm

tepples wrote:
What steps would you recommend that I take to become 100% sure what every part of my code does?

Umm, a good programmer should know how the language works he uses in every bit. Of course if you need to code much stuff, you can't always look at everything,...

tepples wrote:

If only I had a multimeter, the money to buy a second cable to tear apart, and the time to do this instead of my other projects...

You neither need a multimeter, nor a second cable (just if the circuit is molted inside the cable, mine can just be opened by two screws) - anyways, I didn't wanted to insult you or anything..

And yeah, time is always a problem :-(

I hope I didn't sound arrogant earlier - sorry.

tepples wrote:

Good luck with your work ;-)


Thanks :-)

#154050 - sgeos - Thu Apr 10, 2008 12:49 am

bluesceada wrote:
Umm, a good programmer should know how the language works he uses in every bit.

This does not necessarily extend to knowledge of the hardware, especially when you are reverse engineering something.

bluesceada wrote:
Of course if you need to code much stuff, you can't always look at everything,...

Also, if you need to get a bunch of things done with a plethora of technologies, you don't necessarily need to do the best job with all of them. A boolean "good enough" is all you need.

-Brendan

#154061 - bluesceada - Thu Apr 10, 2008 9:25 am

sgeos wrote:
This does not necessarily extend to knowledge of the hardware, especially when you are reverse engineering something.

Ok, let's say an "embedded programmer". And reverse engineering, okay,.. but the GBA is now nearly completely specified at GBATEK.
And if you don't even know if your code is correct, you can't come down to the hardware as the cause of the problem. You are in the dark then.

And the Gamecube Controller is also well specified and lots of people used http://www.int03.co.uk/crema/hardware/gamecube/gc-control.htm to convert their NES and SNES pad to work with the Gamecube by using Microcontrollers.

The biggest problem (you could call reverse engineering) is just the standard cable inbetween, if you want to use that. (So you don't also have to do a special cable)

sgeos wrote:

Also, if you need to get a bunch of things done with a plethora of technologies, you don't necessarily need to do the best job with all of them. A boolean "good enough" is all you need.

-Brendan


Hm yeah right, but with the 16mhz you actually have to do nearly the best job with the timings the gc needs.

#154096 - tepples - Fri Apr 11, 2008 12:30 am

So are you claiming that people should look at assembly language and be able to emulate the code cycle for cycle with pencil and paper, and that that's the most efficient solution when one cannot see the output?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#154109 - bluesceada - Fri Apr 11, 2008 7:47 am

tepples wrote:
So are you claiming that people should look at assembly language and be able to emulate the code cycle for cycle with pencil and paper, and that that's the most efficient solution when one cannot see the output?


Not that much.
But one should in average know how much cycles you need to do some sort of action after it was compiled. For example, that if you use a timer, you also have to know in average the time you need for execution code after the time has end / the timer interrupt was fired etc.

And in rare cases you might also need to look at assembly, or use inline assembly in c.

You normally don't have to do that for game programming of course.
But this is a quite low latency case for the gba's hardware..

#154157 - sgeos - Sat Apr 12, 2008 1:04 am

bluesceada wrote:
And the Gamecube Controller is also well specified ...

If this problem has been solved before, then it should be relatively easy to reproduce that solution.

bluesceada wrote:
Hm yeah right, but with the 16mhz you actually have to do nearly the best job with the timings the gc needs.

Sure. The bar for "good enough" is fairly high.

bluesceada wrote:
And in rare cases you might also need to look at assembly, or use inline assembly in c.

You normally don't have to do that for game programming of course.
But this is a quite low latency case for the gba's hardware..

I agree. Dealing with low level hardware timing is inherently arcane. (From the standpoint of a software person, at least.)

-Brendan

#154160 - tepples - Sat Apr 12, 2008 1:47 am

sgeos wrote:
bluesceada wrote:
And the Gamecube Controller is also well specified ...

If this problem has been solved before, then it should be relatively easy to reproduce that solution.

The obvious roadblock comes in checking one's work, especially to see what part of a reproduced solution is incorrect.

sgeos wrote:
Dealing with low level hardware timing is inherently arcane. (From the standpoint of a software person, at least.)

Especially without the proper tools. On the NES, I have to deal with low-level hardware timing to make a raster split (the kind of thing you'd use VCOUNT for on a GBA), but then I have a reasonably accurate emulator that shows the output.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#154169 - sgeos - Sat Apr 12, 2008 4:14 am

tepples wrote:
sgeos wrote:
Dealing with low level hardware timing is inherently arcane. (From the standpoint of a software person, at least.)

Especially without the proper tools.

For what it is worth, you might consider making an itemized list of the tools you feel you need to complete the job. I'm actually not especially interested in the application, but other people might be and in theory you might be able to get enough support to get your tools. Each entry should have the following information: Problem you need to solve, proposed tool to solve the problem, cost of new tool, alternative solutions you are aware of. Others may be able to point out cheaper alternatives... and then again, maybe not. Specialized knowledge is somewhat rare, afterall.

-Brendan

#154171 - tepples - Sat Apr 12, 2008 4:28 am

In the case of emulating a GameCube controller, this would involve tools to monitor the output of a cycle-accurate GBA CPU, so as to compare the program's output to the desired output. I can think of two toolsets that might start to complete this:
  1. GBA + logic analyzer
  2. cycle accurate PC-based GBA debugger + output logging

_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#154272 - bluesceada - Sun Apr 13, 2008 11:36 pm

It's quite problematic, I didn't had much (any) time this weekend, but I looked at one of the "solutions" which was entirely written in assembler for some PIC 16F last week, but I just have very very basic knowledge of assembler at all... so it didn't really help...
But I still think that a logic analyzer or osci or good emulator still isn't necessary, though they might make it easier of course......
Maybe I have time for this at the next weekend.
// -- ok I maybe shouldnt continue to report about this -here- as it's offtopic, sorry

Btw: What kind of "specialized knowledge" are you talking about, what do you mean?

so to get on your topic now really:

So getting access to an oscilloscope shouldn't be to hard, I could get this easily at university (I still want to try this out without such options, I will not always be able to measure all things in future things, so I want to do as less trial & error as possible.)

You should also be able to ask at schools or whatever. I guess it depends on your state of life.
If you are still a student, teachers or professors should be very willed to provide support, as it will be educatable to you.

#154300 - sgeos - Mon Apr 14, 2008 8:26 am

bluesceada wrote:
Btw: What kind of "specialized knowledge" are you talking about, what do you mean?

Anything. This is a general comment that applies to all fields. The more specialized the knowledge, the harder is to find people with that knowledge who are in a position to share it.

Applied specifically to this topic, a vague "useful knowledge of hardware".

-Brendan

#154307 - bluesceada - Mon Apr 14, 2008 2:26 pm

Umm okay, specialized knowledge is for me things scientists research or really special technology like extremely exact sensors or whatever you may think about... Special software algorithms..

The GBA is far from being anything special - just some (quite) typical embedded arm-system with a display and some buttons and a link port...
And the Gamecube uses just some typical bi-directional transfer protocol, probably not a standard, but nothing very special.

But of course you are right, though I don't see this knowledge you need here as _that_ special. At least not for anybody involved in at least a bit of embedded system technology.

#154624 - bluesceada - Sat Apr 19, 2008 11:53 am

Btw, this should be exactly what you need :-)

http://tfla-01.berlios.de/