1

I'm working on an adaptation of Jason Leyrer's Guitar Hero Library for Arduino. My version is for a DJ Hero controller, and I've also borrowed some code from this Arduino forum thread: topic=120527 (sorry can't post links yet).

The protocol is i2c and I am successfully reading data from it, however I'm not 100% sure what to do with the data.

The buttons are fine, as they are mapped to just one bit in a given byte. However the other controls are a combination of 4, 5 and 6 bit longs.

The format according to Wiibrew is like so:

Table of DJ Hero dataframe format

  • BE is for Euphoria button
  • CS : Crossfade Slider, lower is left and upper is right
  • SX and SY are the black analog stick.
  • ED is the Effect Dial
  • RTT is the turntable on the right as a 6-bit signed integer (positive = CW; negative = CCW)
  • RBG,RBR,RBB are the Green, Red and Blue buttons on the right
  • LTT is the turntable on the left as a 6-bit signed integer (positive = CW; negative = CCW)
  • LBG,LBR,LBB are the Green, Red and Blue buttons on the left

I'm trying to do this:

 signed long DJ_ED()
{
  pack5 ED;
  ED[0] = (DJ_buf[3] >> 5) & 1;
  ED[1] = (DJ_buf[3] >> 6) & 1;
  ED[2] = (DJ_buf[3] >> 7) & 1;
  ED[3] = (DJ_buf[2] >> 5) & 1;
  ED[4] = (DJ_buf[2] >> 6) & 1;

  return ED;
}

Where pack5 is the following:

#define packet5
union pack5
{
   signed long value;
   int ints[5];
};

but I'm getting the following error:

no match for 'operator[]' (operand types are 'pack5' and 'int')

What am I doing wrong?

2
  • Why are you not using a bitwise struct? Jul 28, 2015 at 19:31
  • @IgnacioVazquez-Abrams tbh I'm not very experienced in C and don't really know what I'm doing! Is a bitwise struct the same as a bitfield?
    – rozling
    Jul 28, 2015 at 20:03

1 Answer 1

1

You are using a union so you have to specify which part of the union you want. Your function should read:

 signed long DJ_ED()
{
  pack5 ED;
  ED.ints[0] = (DJ_buf[3] >> 5) & 1;
  ED.ints[1] = (DJ_buf[3] >> 6) & 1;
  ED.ints[2] = (DJ_buf[3] >> 7) & 1;
  ED.ints[3] = (DJ_buf[2] >> 5) & 1;
  ED.ints[4] = (DJ_buf[2] >> 6) & 1;

  return ED.value;
}

It still looks wrong because you are only putting a single bit into those 5 bytes (because of the & 1). And 5 x int will be a lot longer than one signed long.


The code below seems to match the data structure you posted an image of:

struct packedFields
{
  // byte 0
  unsigned int sx      : 5;
  unsigned int rtt_4_3 : 3;

  // byte 1
  unsigned int sy      : 5;
  unsigned int rtt_2_1 : 3;

  // byte 2
  unsigned int rtt_5   : 1;
  unsigned int cs      : 4;
  unsigned int ed_4_3  : 2;  
  unsigned int rtt_0   : 1;

  // byte 3
  unsigned int ltt_4_0  : 5;
  unsigned int ed       : 3;

  // byte 4
  unsigned int ltt_5    : 1;
  unsigned int rbr      : 1;
  unsigned int b_plus   : 1;
  unsigned int filler_2 : 1;
  unsigned int b_minus  : 1;
  unsigned int lbr      : 1;
  unsigned int filler_1 : 2;

  // byte 5
  unsigned int filler_4 : 2;
  unsigned int rbb      : 1;
  unsigned int lbg      : 1;
  unsigned int be       : 1;
  unsigned int rbg      : 1;
  unsigned int filler_3 : 1;
  unsigned int lbb      : 1;

};

union packedFieldsUnion
  {
  packedFields a;
  byte b [6];
  };

void doSomethingWithTheFields (packedFieldsUnion & theFields);  // prototype
void doSomethingWithTheFields (packedFieldsUnion & theFields)
  {
  theFields.a.rtt_4_3 = 3;
  theFields.a.ltt_4_0 = 2;
  }  // end of doSomethingWithTheFields

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  Serial.print (F("packedFields sized = "));
  Serial.println (sizeof (packedFields));

  packedFieldsUnion foo;
  memset (&foo, 0, sizeof foo);

  doSomethingWithTheFields (foo);

  Serial.println (F("-- packedFields bytes --"));
  for (int i = 0; i < sizeof foo; i++)
    Serial.println ((int) foo.b [i], HEX);

  }  // end of setup

void loop ()
  {
  }  // end of loop

I have a bitwise struct, as Ignacio Vazquez-Abrams suggested. Testing indicates you put the low-order bits first. Then I made a union of this struct and 6 bytes. You can't fit the whole thing into a signed long anyway (a long is 4 bytes) so that part of your code was doomed to fail.

A small bit of test code proves that the bits are being accessed in the correct way. You still need to fiddle around with things like RTT which has individual bits scattered in different places.


If you look at the data format you posted there are 6 bytes, not 5. They are numbered 0, 1, 2, 3, 4, 5. A total of six of them.

3
  • ... hit enter too early! This has saved me at least an evening or two so I greatly appreciate the effort. I hope you don't mind if I ask a follow-up question... since I'm trying to make this into a library I'm planning on passing foo to my library functions which I've named DJ_funcs.ino. I'm presuming declaring foo globally here would be a no-no? Is there a best practise here?
    – rozling
    Jul 28, 2015 at 23:04
  • Just pass it by reference. See amended post above, I show an example of doing that.
    – Nick Gammon
    Jul 29, 2015 at 0:17
  • Hi @nick-gammon, sorry I thought I replied to your above comment! I checked it late at night and ended up practically falling asleep in front of the laptop... your revision was extremely helpful but I'm still having trouble connecting the dots. I've made a post on the arduino forum; any help I can get is hugely appreciated!
    – rozling
    Jul 30, 2015 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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