cancel
Showing results for 
Search instead for 
Did you mean: 

Help with simple gamepad USB HID

Masfeo
Visitor

Hello, for my first project with a microcontroller I'm doing a 16 button gamepad USB HID with the aid of ChatGPT. I have no idea of what I'm doing really. I'm Using a STM32f103C8T6 and  STLink V2. I made a polling version that constantly read pins and then sends a report based on "button states"; it works well, but I am interested in a more efficient way of doing it.

So I got to interrupts. I made a version that triggers on falling and rising edges, then it updates the buttons_state in the callback. It works well, but the main loop is always running and sending reports every 1 Systick (1ms I think), so I guess it has almost the same efficiency as the polling method.

My intention was to to use __WFI() instruction in the main loop to make the CPU wake up only on button press/release (EXTI interrupts); something like this:

  while (1)
  {
	  __WFI();
	  
	  uint32_t now = HAL_GetTick();
	  
	  if ((now - last_report_time) >= 1)
	  {
		  send_report(button_state);
		  last_report_time = now;
	  }
  }
}

But supposedly, SysTick might be triggering the __WFI() intruction because it's keeps sending interrupts to update the HAL tick (I think) every 1ms in theory. So even if that was the case, the program would still be much more efficient than the CPU running full always; but it does not work. __WFI() seems to be constantly ignored, and I think the CPU is not slowing down.

My idea tho, was to disable Systick to not trigger __WFI(), and just enable it when I need a 1ms timer to send the USB report. Something like;

SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //Disable Systick

  while (1)
  {
	  __WFI(); //wait for EXTI or Systick interrupt
	  
	  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //Enable Systick to get timer and 
                                                    //bypass _WFI()
	  
	  uint32_t now = HAL_GetTick();
	  
	  if ((now - last_report_time) >= 1)
	  {
		  send_report(button_state);
		  last_report_time = now;
                  
                  //If report was sent disable Systick again to wait with __WFI()
		  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; 
	  }
  }

But it also does not work. I tried many methods that ChatGPT recommended but nothing works. I also looked around on the web but wasn't able to find a solution. __WFI() keeps getting ignored, and the methods I tried are useless (do nothing) or brick my program making the "gamepad" unresponsive.

SO my main questions are:
- How can I disable Systick without disabling other interrupts (mainly EXTI)?
- Why is the __WFI() instruction not working? Are there any other interrupts in a basic gamepad USB setup that trigger __WFI() other than SysTick and EXTI?

 

Thanks for your time.

0 REPLIES 0