Search code examples
cembeddedavr

Understanding data structure in usbjoy library from v-usb project


good day to you all.

I am trying to make my own joystick, so I have been looking for references and then I found usbjoy project from v-usb wiki page (http://vusb.wikidot.com/project:usbjoy).

Then, I found data structure for buttons, taken from common.h in zip file from the website.

typedef struct
{
  uchar x; //Byte-0, ユ (0...255)
  uchar y; //Byte-1, Y (0...255)
        uchar z; //Byte-2, Handle-1 (0...255)
  uchar p; //Byte-3, Handle-2 (0...255)

  union {
    uchar buttons; //Byte-4, buttons 8
    struct
    {
      uchar btn1:    1; //0, 1
      uchar btn2:    1; //0, 1
      uchar btn3:    1; //0, 1
      uchar btn4:    1; //0, 1
      uchar btn5:    1; //0, 1
      uchar btn6:    1; //0, 1
      uchar btn7:    1; //0, 1
      uchar btn8:    1; //0, 1
    } b;
  } u;
        union {
    uchar but; //Byte-5, buttons 4
    struct
    {
      uchar btn9:    1; //0, 1
      uchar btn10:   1; //0, 1
      uchar btn11:   1; //0, 1
      uchar btn12:   1; //0, 1
      uchar padding: 4; //Not use
                } b;
  } w;
} t_PsxController;

I understand that x and y are for left analog pad, z and p are for right analog pad, and u and w are for buttons. My questions are:

  1. Why are u and w declared as unions?
  2. Will the struct inside the unions ever be used?
  3. What is the size of t_PsxController?
  4. And finally, what do colons in uchar btn1: 1; and codes below it mean?

Solution

  • t_PsxController is a struct 6 bytes in size. Each byte is numbered in the comments of the code you posted. The colon : in some of the lines directs the compiler to devote a certain number of bits (1 or 4 in this example) to the item, rather than an entire byte. This makes each of the unions only 1 byte long.

    t_PsxController controller;
    

    will declare a struct called controller that you can use later. It is 6 bytes long.

    To access members of the struct, use the . dot operator. The identifier you use will determine which member of the union you are accessing. E.g.,

    controller.x = 23; // assigns a value to the byte 0
    controller.u.b.btn1 = 1; // assigns a 1 to the first bit of the byte 4
    uchar x = controller.u.buttons; // assigns 128 to x
    

    You may want to use a pointer to controller at some point, especially when passing into a function. You then need to use the -> operator as well as the . dot.

    t_PsxController *ctlr = controller;
    
    ctlr->u.b.btn2 = 1; // Now ctlr->u.buttons is 192