I can compile and run the code on the 316_mc dev kit. I successfully got the 3 onboard LEDs to toggle when I press the 3 push buttons. But the the basic HID functionality is not working. When, I connect the USB port to my PC, it makes the sound like a new device got plugged in, but it is not showing in device manager and it does not pop up as a USB audio device in Windows. I seem to be stuck in the while(1) loop in UserHIDPoll()
Here is my code for user_hid.xc:
Code: Select all
#include <xs1.h>
#include <platform.h>
#include "xua_conf.h"
#include "user_hid.h"
#include "xua_hid_report.h"
on tile[0]: out port db_leds = XS1_PORT_4F;
#if HID_CONTROLS > 0
in port p_sw = on tile[XUD_TILE] : XS1_PORT_4E;
#define P_GPI_BUTA_SHIFT 0x00
#define P_GPI_BUTA_MASK (1<<P_GPI_BUTA_SHIFT)
#define P_GPI_BUTB_SHIFT 0x01
#define P_GPI_BUTB_MASK (1<<P_GPI_BUTB_SHIFT)
#define P_GPI_BUTC_SHIFT 0x02
#define P_GPI_BUTC_MASK (1<<P_GPI_BUTC_SHIFT)
/* Write HID Report Data into hidData array
*
* Bits are as follows:
* 0: Play/Pause
* 1: Scan Next Track
* 2: Scan Prev Track
* 3: Volume Up
* 4: Volume Down
* 5: Mute
*/
unsigned multicontrol_count = 0;
unsigned wait_counter = 0;
#define THRESH 1
#define MULTIPRESS_WAIT_MS 200
#define HIDBUTTONS_POLL_MS 1
#define HID_CONTROL_PLAYPAUSE 0x01
#define HID_CONTROL_NEXT 0x02
#define HID_CONTROL_PREV 0x04
#define HID_CONTROL_VOLUP 0x08
#define HID_CONTROL_VOLDN 0x10
#define HID_CONTROL_MUTE 0x20
typedef enum
{
STATE_IDLE = 0x00,
STATE_PLAY = 0x01,
STATE_NEXTPREV = 0x02,
}t_controlState;
t_controlState state;
unsigned lastA;
static unsigned char lastHidData;
void UserHIDPoll()
{
state = STATE_IDLE;
unsigned char hidData = 0;
db_leds <: 0xF; // all 4 leds on
while (1) {
delay_milliseconds(HIDBUTTONS_POLL_MS);
if (hidIsChangePending(0)) {
continue;
}
// Variables for buttons a, b, c
unsigned a, b, c, tmp;
p_sw :> tmp;
// Buttons are active low
tmp = ~tmp;
a = (tmp & (P_GPI_BUTA_MASK))>>P_GPI_BUTA_SHIFT;
b = (tmp & (P_GPI_BUTB_MASK))>>P_GPI_BUTB_SHIFT;
c = (tmp & (P_GPI_BUTC_MASK))>>P_GPI_BUTC_SHIFT;
if(a) {
db_leds <: 0xE; // led 0 off
}
if(b) {
db_leds <: 0xD; // led 1 off
}
if(c) {
db_leds <: 0xB; // led 2 off
}
hidData = 0;
if(1)
{
// Assign buttons A and B to Vol Down/Up
hidData |= a * HID_CONTROL_VOLDN;
hidData |= b * HID_CONTROL_VOLUP;
hidData |= c * HID_CONTROL_MUTE;
}
else
{
// Assign buttons A and B to play for single tap, next/prev for double tap
if(b)
{
multicontrol_count++;
wait_counter = 0;
lastA = 0;
}
else if(a)
{
multicontrol_count++;
wait_counter = 0;
lastA = 1;
}
else
{
if(multicontrol_count > THRESH)
{
state++;
}
wait_counter++;
if(wait_counter > (MULTIPRESS_WAIT_MS / HIDBUTTONS_POLL_MS))
{
if(state == STATE_PLAY)
{
hidData = HID_CONTROL_PLAYPAUSE;
}
else if(state == STATE_NEXTPREV)
{
if(lastA)
hidData = HID_CONTROL_PREV;
else
hidData = HID_CONTROL_NEXT;
}
state = STATE_IDLE;
}
db_leds <: 0x0; // leds off
multicontrol_count = 0;
}
}
if (hidData == lastHidData) {
continue;
}
unsafe {
volatile unsigned char * unsafe lastHidDataUnsafe = &lastHidData;
*lastHidDataUnsafe = hidData;
hidSetChangePending(0);
}
}
}
size_t UserHIDGetData( const unsigned id, unsigned char hidData[ HID_MAX_DATA_BYTES ])
{
db_leds <: 0x7; // led 3 off
// There is only one report, so the id parameter is ignored
hidData[0] = lastHidData;
// One byte of data is always returned
return 1;
}
void UserHIDInit( void )
{
UserHIDPoll();
}
#endif // HID_CONTROLS > 0
I can tell the UserHIDGetData() function never runs. Does anyone know how the endpoint 0 gets notified that the HID data state has changed?
If anyone can help that would be great, I can't find any documentation on this. The only HID example in the lib_xud folder uses AN00129 which is from 2016 and does not seem to be relevant to the new tools. That example says to make a task in main for handling the HID.
In the lib_xua folder, main.xc doesn't have a task for handling HID, it just says this:
Code: Select all
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif