0% found this document useful (0 votes)
16 views3 pages

Arduino Joystick HID Report Code

The document defines structures and functions for reading button and axis values and sending reports via USB HID to emulate a joystick. It contains defines for the number of buttons and axes, structures for joystick reports, and functions for setting/clearing buttons, reading inputs, and sending reports.

Uploaded by

dinew66518
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views3 pages

Arduino Joystick HID Report Code

The document defines structures and functions for reading button and axis values and sending reports via USB HID to emulate a joystick. It contains defines for the number of buttons and axes, structures for joystick reports, and functions for setting/clearing buttons, reading inputs, and sending reports.

Uploaded by

dinew66518
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#undef DEBUG

#define NUM_BUTTONS 40 // you don't need to change this value


#define NUM_AXES 8 // 6 axes to UNO, and 8 to MEGA. If you are using UNO,
don't need to change this value.

typedef struct joyReport_t {


int16_t axis[NUM_AXES];
uint8_t button[(NUM_BUTTONS + 7) / 8]; // 8 buttons per byte
} joyReport_t;

joyReport_t joyReport;

uint8_t btn[12];
int fulloff = 0;
void setup(void);
void loop(void);
void setButton(joyReport_t *joy, uint8_t button);
void clearButton(joyReport_t *joy, uint8_t button);
void sendJoyReport(joyReport_t *report);

void setup()
{
//set pin to input Button
for ( int portId = 02; portId < 13; portId ++ )
{
pinMode( portId, INPUT_PULLUP);
}
[Link](115200);
delay(200);

for (uint8_t ind = 0; ind < 8; ind++) {


[Link][ind] = ind * 1000;
}
for (uint8_t ind = 0; ind < sizeof([Link]); ind++) {
[Link][ind] = 0;
}
}

// Send an HID report to the USB interface


void sendJoyReport(struct joyReport_t *report)
{
#ifndef DEBUG
[Link]((uint8_t *)report, sizeof(joyReport_t));
#else
// dump human readable output for debugging
for (uint8_t ind = 0; ind < NUM_AXES; ind++) {
[Link]("axis[");
[Link](ind);
[Link]("]= ");
[Link](report->axis[ind]);
[Link](" ");
}
[Link]();
for (uint8_t ind = 0; ind < NUM_BUTTONS / 8; ind++) {
[Link]("button[");
[Link](ind);
[Link]("]= ");
[Link](report->button[ind], HEX);
[Link](" ");
}
[Link]();
#endif
}

// turn a button on
void setButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;

joy->button[index] |= 1 << bit;


}

// turn a button off


void clearButton(joyReport_t *joy, uint8_t button)
{
uint8_t index = button / 8;
uint8_t bit = button - 8 * index;

joy->button[index] &= ~(1 << bit);


}

/*
Read Digital port for Button
Read Analog port for axis
*/
void loop()
{

for (int bt = 1; bt < 13; bt ++)


{
// btn[bt] = digitalRead(bt + 1);
btn[bt] = LOW;
}

for (int on = 01; on < 13; on++)


{
if (btn[on] == LOW)
{
setButton(&joyReport, on + 16);

delay(1);
}
for (int on = 01; on < 13; on++)
{
if (btn[on] == HIGH)
{
clearButton(&joyReport, on + 16);
}

}
}
[Link][0] = map(analogRead(0), 0, 1023, -32768, 32767 );
[Link][1] = map(analogRead(1), 0, 1023, -32768, 32767 );
[Link][2] = 0;
[Link][3] = 0;
[Link][4] = 0;
[Link][5] = 0;
[Link][6] = 0;
[Link][7] = 0;
[Link][8] = 0;

//Send Data to HID


sendJoyReport(&joyReport);

delay(35);
fulloff = 0;
}

Common questions

Powered by AI

Resetting axis values and button statuses in 'setup' initializes the joystick to a known state at start-up, ensuring predictable behavior from the outset and avoiding residual data errors. Dynamic updates in 'loop', however, reflect the real-time status of the joystick, reacting instantly to user inputs. This dual approach is critical; initialization ensures stability when the system first runs, while dynamic updates maintain responsiveness to user interactions during operation, keeping the interface aligned with actual control demands.

Conditional compilation using '#ifndef DEBUG' enhances code versatility by allowing different code paths based on compilation conditions, supporting both development and release environments. In release mode, it sends raw data for minimal overhead and maximum compatibility with USB HID standards. However, in debug mode ('#else'), it prints human-readable debug information to serial output, aiding in troubleshooting. This versatility ensures efficient operation by optimizing performance for end-use while providing detailed diagnostics when developing and testing.

The setup function is crucial for initializing the program and hardware settings, ensuring that all input pins are correctly configured to read button statuses (using INPUT_PULLUP) and preparing the serial communication at a baud rate of 115200. It also initializes axis values to a predefined state and clears button arrays to ensure there is no residual data from previous operations. These initializations assure that the system starts from a known baseline before entering the main loop, crucial for consistent and predictable operation.

The loop function is responsible for continuously updating the joystick data by reading digital inputs from buttons and analog inputs from axes. It processes each button by setting the corresponding bit in the 'joyReport' if it is pressed, or clearing it if not, via the 'setButton' and 'clearButton' functions. This loop ensures that digital button states are consistently checked and updated, reflecting real-time changes in the joystick's condition. It then sends the updated joystick report via 'sendJoyReport', allowing real-time transmission of state data.

The struct 'joyReport_t' integrates multiple types of input, namely axis states and button statuses, into a single unified data structure, facilitating consistent and coherent packaging of HID data. The array 'axis[NUM_AXES]' stores analog movement data, while the array 'button' uses packed bytes to efficiently store the binary state of numerous buttons. This consolidation allows for a single communication packet encompassing all input types, simplifying the data handling and protocol interpretation on receiving systems, and ensuring swift and synchronized updates across all peripheral controls.

The mapping function translates 10-bit analog input values, which range from 0 to 1023, into the range of -32768 to 32767 suitable for joystick axes using the 'map' function. This conversion is necessary because joystick interfaces typically interpret axis values within this wider signed range to better capture movement details. Such mapping allows the raw input values to be converted into a format compatible with what applications or drivers expect for USB HID joystick communication, ensuring accurate and meaningful control signals.

The delay functions in the code introduce a controlled pause in code execution, impacting the timing of input readings and report sending. The delay before starting the loop allows stabilization of serial communication. The subsequent delay after sending a report ('delay(35)') helps regulate the rate at which joystick data is communicated, preventing data flooding the interface. These carefully placed delays ensure that inputs are read and outputs are sent at predictable intervals, essential for maintaining synchronized interaction with connected systems.

In release mode, 'sendJoyReport' forwards the entire 'joyReport_t' data structure to the USB interface using 'Serial.write'. This allows the joystick data to be communicated uninterrupted. When in debugging mode, indicated by the preprocessor condition '#ifdef DEBUG', it prints human-readable outputs of all axes and button states to the serial monitor, facilitating troubleshooting and verification of the program's operation. This dual functionality enables efficient operation and debugging based on the compilation mode.

The 'setButton' and 'clearButton' functions use bitwise operations to efficiently manage button states. 'setButton' calculates the byte (index) and the specific bit within that byte to modify, then uses a bitwise OR operation '|=' to set the appropriate bit, thus turning the button "on". Conversely, 'clearButton' uses a bitwise AND with the NOT of the desired bit to clear it, effectively turning the button "off". These operations allow control over individual button states within compact storage space, enabling scalable button management without excessive memory usage.

NUM_BUTTONS and NUM_AXES are used to define the size of the elements in the 'joyReport_t' structure, which enables a joystick interface to properly interpret button and axis data. NUM_BUTTONS determines the number of bits allocated for button statuses, calculated by 'NUM_BUTTONS + 7 / 8' to fit eight buttons per byte, while NUM_AXES specifies how many axis readings can be stored in the 'axis' array. These definitions allow the code to accommodate different hardware capabilities, such as differing numbers of buttons and axes supported by devices like the Arduino UNO and MEGA.

You might also like