본문 바로가기

RaspberryPi/RP2040

RP2040 - HID Keyboard 테스트 (TinyUSB)

RP2040은 USB가 포함되어 있기 때문에 진행 하려고 했던 KeyPad 프로젝트를 위한 USB HID Keyboard 를 테스트 해 보았다.
 
기본으로 제공하는 키보드 예제 테스트 하니 잘 동작한다.

 

 

Arduino 기본 USB Keyboard 예제는 심플하고 간단해서 사용하기는 편한데 뭔가 좀더 복잡한 KeyBoard를 위해서는 아쉬운점이 있다.

#include "Keyboard.h"

const int buttonPin = 4;          // input pin for pushbutton
int previousButtonState = HIGH;   // for checking the state of a pushButton
int counter = 0;                  // button push counter

void setup() {
  // make the pushButton pin an input:
  pinMode(buttonPin, INPUT);
  // initialize control over the keyboard:
  Keyboard.begin();
}

void loop() {
  // read the pushbutton:
  int buttonState = digitalRead(buttonPin);
  // if the button state has changed,
  if ((buttonState != previousButtonState)
      // and it's currently pressed:
      && (buttonState == HIGH)) {
    // increment the button counter
    counter++;
    // type out a message
    Keyboard.print("You pressed the button ");
    Keyboard.print(counter);
    Keyboard.println(" times.");
  }
  // save the current button state for comparison next time:
  previousButtonState = buttonState;
}

 

 


좀더 다양한 기능을 사용하려면 TinyUSB를 사용하면 좋다.

 

 

컴파일 하니 에러 발생
In file included from C:\Users\jhpark\Documents\Arduino\libraries\Adafruit_TinyUSB_Library\examples\Composite\mouse_ramdisk\mouse_ramdisk.ino:17:
C:\Users\jhpark\Documents\Arduino\libraries\Adafruit_TinyUSB_Library\src/Adafruit_TinyUSB.h:31:2: error: #error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
   31 | #error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
      |  ^~~~~

 

 

 

USB Stack을 TinyUSB로 하라고 한다.

컴파일 에러 없이 잘 동작한다.

 

 

RP2040 SSM EVM 보드에 맞도록 코드를 수정해서 스위치 누를때 마다 Key 코드가 전송되도록 테스트 해보았다.

#include "Adafruit_TinyUSB.h"


// HID report descriptor using TinyUSB's template
// Single Report (no ID) descriptor
uint8_t const desc_hid_report[] =
{
  TUD_HID_REPORT_DESC_KEYBOARD()
};

// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);

uint8_t hidcode[] = { HID_KEY_A, HID_KEY_B, HID_KEY_ARROW_DOWN};
                         
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY) || defined(ARDUINO_FUNHOUSE_ESP32S2)
  bool activeState = true;
#else
  bool activeState = false;
#endif


#define PIN_BUTTON1 D10

// the setup function runs once when you press reset or power the board
void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
  // Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
  TinyUSB_Device_Init(0);
#endif

  usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
  usb_hid.begin();

  // led pin
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  pinMode(PIN_BUTTON1, INPUT_PULLUP);

  Serial.begin(115200);
  // wait until device mounted
  while( !TinyUSBDevice.mounted() ) delay(1);
}


uint8_t count=0;
uint8_t const report_id = 0;
uint8_t const modifier = 0;
int flag = 0;
uint8_t keycode[6] = {0,0,0,0,0,0};

void loop()
{
  // poll gpio once each 2 ms
  if (usb_hid.ready())
  {
    if (digitalRead(PIN_BUTTON1) == 0 )
    {
      if(flag == 0)
      {
        flag = 1;

        keycode[1] = hidcode[1];
        usb_hid.keyboardReport(report_id, modifier, keycode);
  
        Serial.print("press=");  
           
        // delay a bit before attempt to send keyboard report
        delay(50);
  
        usb_hid.keyboardRelease(0);
      }
      
    }
    else
    {
      if(flag == 1)
      {
        flag = 0;
        Serial.println("unpress"); 
      }
    }

  if(Serial.available() > 0) 
  {
    int cmd = Serial.parseInt();

    // look for the newline. That's the end of your sentence:
    if (Serial.read() == '\n')
    {
      // print the three numbers in one string as hexadecimal:
      if(cmd==1)
      {
          hidcode[1] = HID_KEY_A;

          Serial.print("KeyCode Change:");
          Serial.print(hidcode[0], HEX);
      }
      else if(cmd==2)
      {
          hidcode[1] = HID_KEY_B;

          Serial.print("KeyCode Change:");
          Serial.print(hidcode[0], HEX);
          
      }      
      Serial.print(", ");
      Serial.println(cmd, HEX);
    }
  }
   
  } 
}

// Output report callback for LED indicator such as Caplocks
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
  (void) report_id;
  (void) bufsize;

  // LED indicator is output report with only 1 byte length
  if ( report_type != HID_REPORT_TYPE_OUTPUT ) return;

  // The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
  // Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
  uint8_t ledIndicator = buffer[0];

  // turn on LED if capslock is set
  digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK);

  Serial.println("OutReport");
  
#ifdef PIN_NEOPIXEL
  pixels.fill(ledIndicator & KEYBOARD_LED_CAPSLOCK ? 0xff0000 : 0x000000);
  pixels.show();
#endif
}

 

반응형