Browse Source

feat: CH552 based firmware

master
Brett Bender 3 years ago
parent
commit
43e0addc51
19 changed files with 1101 additions and 8 deletions
  1. +56
    -0
      CH552/CH552.ino
  2. +284
    -0
      CH552/src/userUsbHidKeyboard/USBHIDKeyboard.c
  3. +77
    -0
      CH552/src/userUsbHidKeyboard/USBHIDKeyboard.h
  4. +88
    -0
      CH552/src/userUsbHidKeyboard/USBconstant.c
  5. +27
    -0
      CH552/src/userUsbHidKeyboard/USBconstant.h
  6. +485
    -0
      CH552/src/userUsbHidKeyboard/USBhandler.c
  7. +61
    -0
      CH552/src/userUsbHidKeyboard/USBhandler.h
  8. +22
    -7
      README.md
  9. +0
    -0
      RP2040/lib/adafruit_debouncer.mpy
  10. +0
    -0
      RP2040/lib/adafruit_hid/__init__.mpy
  11. +0
    -0
      RP2040/lib/adafruit_hid/consumer_control.mpy
  12. +0
    -0
      RP2040/lib/adafruit_hid/consumer_control_code.mpy
  13. +0
    -0
      RP2040/lib/adafruit_hid/keyboard.mpy
  14. +0
    -0
      RP2040/lib/adafruit_hid/keyboard_layout_base.mpy
  15. +0
    -0
      RP2040/lib/adafruit_hid/keyboard_layout_us.mpy
  16. +0
    -0
      RP2040/lib/adafruit_hid/keycode.mpy
  17. +0
    -0
      RP2040/lib/adafruit_hid/mouse.mpy
  18. +0
    -0
      RP2040/lib/adafruit_ticks.mpy
  19. +1
    -1
      RP2040/main.py

+ 56
- 0
CH552/CH552.ino View File

@ -0,0 +1,56 @@
/*
Pedal to Key takes in 2 (drum pedal) inputs and turns
them into two separate key presses
Created in 2023
by Brett Bender for Will Dean of UW-Stout PONG
This code is licensed under the MIT License
*/
#ifndef USER_USB_RAM
#error "This program needs to be compiled with a USER USB setting"
#endif
#include "src/userUsbHidKeyboard/USBHIDKeyboard.h"
#define BUTTON1_PIN 33
#define BUTTON1_CHAR 'd'
#define BUTTON2_PIN 32
#define BUTTON2_CHAR 'k'
bool button1PressPrev = false;
bool button2PressPrev = false;
void setup() {
USBInit();
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
}
void loop() {
//button 1 is mapped to letter 'd'
bool button1Press = !digitalRead(BUTTON1_PIN);
if (button1PressPrev != button1Press) {
button1PressPrev = button1Press;
if (button1Press) {
Keyboard_press(BUTTON1_CHAR);
} else {
Keyboard_release(BUTTON1_CHAR);
}
}
//button 2 is mapped to letter 'd'
bool button2Press = !digitalRead(BUTTON2_PIN);
if (button2PressPrev != button2Press) {
button2PressPrev = button2Press;
if (button2Press) {
Keyboard_press(BUTTON2_CHAR);
} else {
Keyboard_release(BUTTON2_CHAR);
}
}
delay(50); //naive debouncing
}

+ 284
- 0
CH552/src/userUsbHidKeyboard/USBHIDKeyboard.c View File

@ -0,0 +1,284 @@
#include <stdint.h>
#include <stdbool.h>
#include "include/ch5xx.h"
#include "include/ch5xx_usb.h"
#include "USBconstant.h"
#include "USBhandler.h"
extern __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[];
extern __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[];
volatile __xdata uint8_t UpPoint1_Busy = 0; //Flag of whether upload pointer is busy
__xdata uint8_t HIDKey[8] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
#define SHIFT 0x80
__code uint8_t _asciimap[128] =
{
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e|SHIFT, // !
0x34|SHIFT, // "
0x20|SHIFT, // #
0x21|SHIFT, // $
0x22|SHIFT, // %
0x24|SHIFT, // &
0x34, // '
0x26|SHIFT, // (
0x27|SHIFT, // )
0x25|SHIFT, // *
0x2e|SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33|SHIFT, // :
0x33, // ;
0x36|SHIFT, // <
0x2e, // =
0x37|SHIFT, // >
0x38|SHIFT, // ?
0x1f|SHIFT, // @
0x04|SHIFT, // A
0x05|SHIFT, // B
0x06|SHIFT, // C
0x07|SHIFT, // D
0x08|SHIFT, // E
0x09|SHIFT, // F
0x0a|SHIFT, // G
0x0b|SHIFT, // H
0x0c|SHIFT, // I
0x0d|SHIFT, // J
0x0e|SHIFT, // K
0x0f|SHIFT, // L
0x10|SHIFT, // M
0x11|SHIFT, // N
0x12|SHIFT, // O
0x13|SHIFT, // P
0x14|SHIFT, // Q
0x15|SHIFT, // R
0x16|SHIFT, // S
0x17|SHIFT, // T
0x18|SHIFT, // U
0x19|SHIFT, // V
0x1a|SHIFT, // W
0x1b|SHIFT, // X
0x1c|SHIFT, // Y
0x1d|SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23|SHIFT, // ^
0x2d|SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f|SHIFT, // {
0x31|SHIFT, // |
0x30|SHIFT, // }
0x35|SHIFT, // ~
0 // DEL
};
typedef void( *pTaskFn)( void );
void delayMicroseconds(uint16_t us);
void USBInit(){
USBDeviceCfg(); //Device mode configuration
USBDeviceEndPointCfg(); //Endpoint configuration
USBDeviceIntCfg(); //Interrupt configuration
UEP0_T_LEN = 0;
UEP1_T_LEN = 0; //Pre-use send length must be cleared
UEP2_T_LEN = 0;
}
void USB_EP1_IN(){
UEP1_T_LEN = 0;
UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; // Default NAK
UpPoint1_Busy = 0; //Clear busy flag
}
void USB_EP1_OUT(){
if ( U_TOG_OK ) // Discard unsynchronized packets
{
}
}
uint8_t USB_EP1_send(){
uint16_t waitWriteCount = 0;
waitWriteCount = 0;
while (UpPoint1_Busy){//wait for 250ms or give up
waitWriteCount++;
delayMicroseconds(5);
if (waitWriteCount>=50000) return 0;
}
for (uint8_t i=0;i<sizeof(HIDKey);i++){ //load data for upload
Ep1Buffer[64+i] = HIDKey[i];
}
UEP1_T_LEN = sizeof(HIDKey); //data length
UpPoint1_Busy = 1;
UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //upload data and respond ACK
return 1;
}
uint8_t Keyboard_press(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
HIDKey[0] |= (1<<(k-128));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
//setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
HIDKey[0] |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (HIDKey[2] != k && HIDKey[3] != k &&
HIDKey[4] != k && HIDKey[5] != k &&
HIDKey[6] != k && HIDKey[7] != k) {
for (i=2; i<8; i++) {
if (HIDKey[i] == 0x00) {
HIDKey[i] = k;
break;
}
}
if (i == 8) {
//setWriteError();
return 0;
}
}
USB_EP1_send();
return 1;
}
uint8_t Keyboard_release(uint8_t k) {
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
HIDKey[0] &= ~(1<<(k-128));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
HIDKey[0] &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i=2; i<8; i++) {
if (0 != k && HIDKey[i] == k) {
HIDKey[i] = 0x00;
}
}
USB_EP1_send();
return 1;
}
void Keyboard_releaseAll(void){
for (uint8_t i=0;i<sizeof(HIDKey);i++){ //load data for upload
HIDKey[i] = 0;
}
USB_EP1_send();
}
uint8_t Keyboard_write(uint8_t c){
uint8_t p = Keyboard_press(c); // Keydown
Keyboard_release(c); // Keyup
return p; // just return the result of press() since release() almost always returns 1
}
uint8_t Keyboard_getLEDStatus(){
return Ep1Buffer[0]; //The only info we gets
}

+ 77
- 0
CH552/src/userUsbHidKeyboard/USBHIDKeyboard.h View File

@ -0,0 +1,77 @@
#ifndef __USB_HID_KBD_H__
#define __USB_HID_KBD_H__
#include <stdint.h>
#include "include/ch5xx.h"
#include "include/ch5xx_usb.h"
#define KEY_LEFT_CTRL 0x80
#define KEY_LEFT_SHIFT 0x81
#define KEY_LEFT_ALT 0x82
#define KEY_LEFT_GUI 0x83
#define KEY_RIGHT_CTRL 0x84
#define KEY_RIGHT_SHIFT 0x85
#define KEY_RIGHT_ALT 0x86
#define KEY_RIGHT_GUI 0x87
#define KEY_UP_ARROW 0xDA
#define KEY_DOWN_ARROW 0xD9
#define KEY_LEFT_ARROW 0xD8
#define KEY_RIGHT_ARROW 0xD7
#define KEY_BACKSPACE 0xB2
#define KEY_TAB 0xB3
#define KEY_RETURN 0xB0
#define KEY_ESC 0xB1
#define KEY_INSERT 0xD1
#define KEY_DELETE 0xD4
#define KEY_PAGE_UP 0xD3
#define KEY_PAGE_DOWN 0xD6
#define KEY_HOME 0xD2
#define KEY_END 0xD5
#define KEY_CAPS_LOCK 0xC1
#define KEY_F1 0xC2
#define KEY_F2 0xC3
#define KEY_F3 0xC4
#define KEY_F4 0xC5
#define KEY_F5 0xC6
#define KEY_F6 0xC7
#define KEY_F7 0xC8
#define KEY_F8 0xC9
#define KEY_F9 0xCA
#define KEY_F10 0xCB
#define KEY_F11 0xCC
#define KEY_F12 0xCD
#define KEY_F13 0xF0
#define KEY_F14 0xF1
#define KEY_F15 0xF2
#define KEY_F16 0xF3
#define KEY_F17 0xF4
#define KEY_F18 0xF5
#define KEY_F19 0xF6
#define KEY_F20 0xF7
#define KEY_F21 0xF8
#define KEY_F22 0xF9
#define KEY_F23 0xFA
#define KEY_F24 0xFB
#ifdef __cplusplus
extern "C" {
#endif
void USBInit(void);
uint8_t Keyboard_press(uint8_t k);
uint8_t Keyboard_release(uint8_t k);
void Keyboard_releaseAll(void);
uint8_t Keyboard_write(uint8_t c);
uint8_t Keyboard_getLEDStatus();
#ifdef __cplusplus
} // extern "C"
#endif
#endif

+ 88
- 0
CH552/src/userUsbHidKeyboard/USBconstant.c View File

@ -0,0 +1,88 @@
#include "USBconstant.h"
//Device descriptor
__code uint8_t DevDesc[] = {
0x12,0x01,
0x10,0x01, //USB spec release number in BCD format, USB1.1 (0x10, 0x01).
0x00,0x00,0x00, //bDeviceClass, bDeviceSubClass, bDeviceProtocol
DEFAULT_ENDP0_SIZE, //bNumConfigurations
0x09,0x12,0x5D,0xC5, // VID PID
0x00,0x01, //version
0x01,0x02,0x03, //bString
0x01 //bNumConfigurations
};
__code uint16_t DevDescLen = sizeof(DevDesc);
__code uint8_t CfgDesc[] ={
0x09,0x02,sizeof(CfgDesc) & 0xff,sizeof(CfgDesc) >> 8,
0x01,0x01,0x00,0x80,0x64, //Configuration descriptor (1 interface)
// Interface 1 (HID) descriptor
0x09,0x04,0x00,0x00,0x02,0x03,0x01,0x01,0x00, // HID Keyboard, 2 endpoints
0x09,0x21,0x10,0x01,0x21,0x01,0x22,sizeof(ReportDesc) & 0xff,sizeof(ReportDesc) >> 8, //HID Descriptor
0x07,0x05,0x01,0x03,0x08,0x00,0x0A, //endpoint descriptor
0x07,0x05,0x81,0x03,0x08,0x00,0x0A, //endpoint descriptor
};
__code uint16_t ReportDescLen = sizeof(ReportDesc);
__code uint8_t ReportDesc[] ={
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x08, // REPORT_COUNT (8)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0xff, // LOGICAL_MAXIMUM (255)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0xc0 // END_COLLECTION
};
__code uint16_t CfgDescLen = sizeof(CfgDesc);
//String Descriptors
__code uint8_t LangDes[]={0x04,0x03,0x09,0x04}; //Language Descriptor
__code uint16_t LangDesLen = sizeof(LangDes);
__code uint8_t SerDes[]={ //Serial String Descriptor
0x14,0x03,
'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,' ',0x00,'k',0x00,'b',0x00,'d',0x00
};
__code uint16_t SerDesLen = sizeof(SerDes);
__code uint8_t Prod_Des[]={ //Produce String Descriptor
0x16,0x03,
'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,'d',0x00,
'u',0x00,'i',0x00,'n',0x00,'o',0x00
};
__code uint16_t Prod_DesLen = sizeof(Prod_Des);
__code uint8_t Manuf_Des[]={
0x0E,0x03,
'D',0x00,'e',0x00,'q',0x00,'i',0x00,'n',0x00,'g',0x00,
};
__code uint16_t Manuf_DesLen = sizeof(Manuf_Des);

+ 27
- 0
CH552/src/userUsbHidKeyboard/USBconstant.h View File

@ -0,0 +1,27 @@
#ifndef __USB_CONST_DATA_H__
#define __USB_CONST_DATA_H__
#include <stdint.h>
#include "include/ch5xx.h"
#include "include/ch5xx_usb.h"
#define EP0_ADDR 0
#define EP1_ADDR 10
extern __code uint8_t DevDesc[];
extern __code uint8_t CfgDesc[];
extern __code uint8_t LangDes[];
extern __code uint8_t ReportDesc[];
extern __code uint8_t SerDes[];
extern __code uint8_t Prod_Des[];
extern __code uint8_t Manuf_Des[];
extern __code uint16_t DevDescLen;
extern __code uint16_t CfgDescLen;
extern __code uint16_t LangDesLen;
extern __code uint16_t ReportDescLen;
extern __code uint16_t SerDesLen;
extern __code uint16_t Prod_DesLen;
extern __code uint16_t Manuf_DesLen;
#endif

+ 485
- 0
CH552/src/userUsbHidKeyboard/USBhandler.c View File

@ -0,0 +1,485 @@
#include "USBhandler.h"
#include "USBconstant.h"
//Keyboard functions:
void USB_EP2_IN();
void USB_EP2_OUT();
__xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8];
__xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64), IN and OUT buffer, must be even address
#if (EP1_ADDR+128) > USER_USB_RAM
#error "This program needs more USB RAM. Increase this setting in the menu."
#endif
uint16_t SetupLen;
uint8_t SetupReq,UsbConfig;
__code uint8_t *pDescr;
volatile uint8_t usbMsgFlags=0; // uint8_t usbMsgFlags copied from VUSB
inline void NOP_Process(void) {}
void USB_EP0_SETUP(){
uint8_t len = USB_RX_LEN;
if(len == (sizeof(USB_SETUP_REQ)))
{
SetupLen = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL);
len = 0; // Default is success and upload 0 length
SetupReq = UsbSetupBuf->bRequest;
usbMsgFlags = 0;
if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )//Not standard request
{
//here is the commnunication starts, refer to usbFunctionSetup of USBtiny
//or usb_setup in usbtiny
switch( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ))
{
case USB_REQ_TYP_VENDOR:
{
switch( SetupReq )
{
default:
len = 0xFF; //command not supported
break;
}
break;
}
case USB_REQ_TYP_CLASS:
{
switch( SetupReq )
{
default:
len = 0xFF; //command not supported
break;
}
break;
}
default:
len = 0xFF; //command not supported
break;
}
}
else //Standard request
{
switch(SetupReq) //Request ccfType
{
case USB_GET_DESCRIPTOR:
switch(UsbSetupBuf->wValueH)
{
case 1: //Device Descriptor
pDescr = DevDesc; //Put Device Descriptor into outgoing buffer
len = DevDescLen;
break;
case 2: //Configure Descriptor
pDescr = CfgDesc;
len = CfgDescLen;
break;
case 3:
if(UsbSetupBuf->wValueL == 0)
{
pDescr = LangDes;
len = LangDesLen;
}
else if(UsbSetupBuf->wValueL == 1)
{
pDescr = Manuf_Des;
len = Manuf_DesLen;
}
else if(UsbSetupBuf->wValueL == 2)
{
pDescr = Prod_Des;
len = Prod_DesLen;
}
else if(UsbSetupBuf->wValueL == 3)
{
pDescr = SerDes;
len = SerDesLen;
}
else
{
len = 0xff;
}
break;
case 0x22:
if(UsbSetupBuf->wValueL == 0){
pDescr = ReportDesc;
len = ReportDescLen;
}
else
{
len = 0xff;
}
break;
default:
len = 0xff; // Unsupported descriptors or error
break;
}
if (len != 0xff){
if ( SetupLen > len )
{
SetupLen = len; // Limit length
}
len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //transmit length for this packet
for (uint8_t i=0;i<len;i++){
Ep0Buffer[i] = pDescr[i];
}
SetupLen -= len;
pDescr += len;
}
break;
case USB_SET_ADDRESS:
SetupLen = UsbSetupBuf->wValueL; // Save the assigned address
break;
case USB_GET_CONFIGURATION:
Ep0Buffer[0] = UsbConfig;
if ( SetupLen >= 1 )
{
len = 1;
}
break;
case USB_SET_CONFIGURATION:
UsbConfig = UsbSetupBuf->wValueL;
break;
case USB_GET_INTERFACE:
break;
case USB_SET_INTERFACE:
break;
case USB_CLEAR_FEATURE: //Clear Feature
if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Clear the device featuee.
{
if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 )
{
if( CfgDesc[ 7 ] & 0x20 )
{
// wake up
}
else
{
len = 0xFF; //Failed
}
}
else
{
len = 0xFF; //Failed
}
}
else if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// endpoint
{
switch( UsbSetupBuf->wIndexL )
{
case 0x84:
UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x04:
UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
case 0x83:
UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x03:
UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
case 0x82:
UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x02:
UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
case 0x81:
UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK;
break;
case 0x01:
UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK;
break;
default:
len = 0xFF; // Unsupported endpoint
break;
}
}
else
{
len = 0xFF; // Unsupported for non-endpoint
}
break;
case USB_SET_FEATURE: // Set Feature
if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Set the device featuee.
{
if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 )
{
if( CfgDesc[ 7 ] & 0x20 )
{
// suspend
//while ( XBUS_AUX & bUART0_TX ); //Wait till uart0 sending complete
//SAFE_MOD = 0x55;
//SAFE_MOD = 0xAA;
//WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; //wake up by USB or RXD0/1 signal
//PCON |= PD; //sleep
//SAFE_MOD = 0x55;
//SAFE_MOD = 0xAA;
//WAKE_CTRL = 0x00;
}
else
{
len = 0xFF; // Failed
}
}
else
{
len = 0xFF; // Failed
}
}
else if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP ) //endpoint
{
if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 )
{
switch( ( ( uint16_t )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL )
{
case 0x84:
UEP4_CTRL = UEP4_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint4 IN STALL
break;
case 0x04:
UEP4_CTRL = UEP4_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint4 OUT Stall
break;
case 0x83:
UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint3 IN STALL
break;
case 0x03:
UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint3 OUT Stall
break;
case 0x82:
UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint2 IN STALL
break;
case 0x02:
UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint2 OUT Stall
break;
case 0x81:
UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint1 IN STALL
break;
case 0x01:
UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint1 OUT Stall
default:
len = 0xFF; // Failed
break;
}
}
else
{
len = 0xFF; // Failed
}
}
else
{
len = 0xFF; // Failed
}
break;
case USB_GET_STATUS:
Ep0Buffer[0] = 0x00;
Ep0Buffer[1] = 0x00;
if ( SetupLen >= 2 )
{
len = 2;
}
else
{
len = SetupLen;
}
break;
default:
len = 0xff; // Failed
break;
}
}
}
else
{
len = 0xff; //Wrong packet length
}
if(len == 0xff)
{
SetupReq = 0xFF;
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;//STALL
}
else if(len <= DEFAULT_ENDP0_SIZE) // Tx data to host or send 0-length packet
{
UEP0_T_LEN = len;
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK
}
else
{
UEP0_T_LEN = 0; // Tx data to host or send 0-length packet
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK
}
}
void USB_EP0_IN(){
switch(SetupReq)
{
case USB_GET_DESCRIPTOR:
{
uint8_t len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //send length
for (uint8_t i=0;i<len;i++){
Ep0Buffer[i] = pDescr[i];
}
//memcpy( Ep0Buffer, pDescr, len );
SetupLen -= len;
pDescr += len;
UEP0_T_LEN = len;
UEP0_CTRL ^= bUEP_T_TOG; //Switch between DATA0 and DATA1
}
break;
case USB_SET_ADDRESS:
USB_DEV_AD = USB_DEV_AD & bUDA_GP_BIT | SetupLen;
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
break;
default:
UEP0_T_LEN = 0; // End of transaction
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
break;
}
}
void USB_EP0_OUT(){
{
UEP0_T_LEN = 0;
UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_NAK; //Respond Nak
}
}
#pragma save
#pragma nooverlay
void USBInterrupt(void) { //inline not really working in multiple files in SDCC
if(UIF_TRANSFER) {
// Dispatch to service functions
uint8_t callIndex=USB_INT_ST & MASK_UIS_ENDP;
switch (USB_INT_ST & MASK_UIS_TOKEN) {
case UIS_TOKEN_OUT:
{//SDCC will take IRAM if array of function pointer is used.
switch (callIndex) {
case 0: EP0_OUT_Callback(); break;
case 1: EP1_OUT_Callback(); break;
case 2: EP2_OUT_Callback(); break;
case 3: EP3_OUT_Callback(); break;
case 4: EP4_OUT_Callback(); break;
default: break;
}
}
break;
case UIS_TOKEN_SOF:
{//SDCC will take IRAM if array of function pointer is used.
switch (callIndex) {
case 0: EP0_SOF_Callback(); break;
case 1: EP1_SOF_Callback(); break;
case 2: EP2_SOF_Callback(); break;
case 3: EP3_SOF_Callback(); break;
case 4: EP4_SOF_Callback(); break;
default: break;
}
}
break;
case UIS_TOKEN_IN:
{//SDCC will take IRAM if array of function pointer is used.
switch (callIndex) {
case 0: EP0_IN_Callback(); break;
case 1: EP1_IN_Callback(); break;
case 2: EP2_IN_Callback(); break;
case 3: EP3_IN_Callback(); break;
case 4: EP4_IN_Callback(); break;
default: break;
}
}
break;
case UIS_TOKEN_SETUP:
{//SDCC will take IRAM if array of function pointer is used.
switch (callIndex) {
case 0: EP0_SETUP_Callback(); break;
case 1: EP1_SETUP_Callback(); break;
case 2: EP2_SETUP_Callback(); break;
case 3: EP3_SETUP_Callback(); break;
case 4: EP4_SETUP_Callback(); break;
default: break;
}
}
break;
}
UIF_TRANSFER = 0; // Clear interrupt flag
}
// Device mode USB bus reset
if(UIF_BUS_RST) {
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
USB_DEV_AD = 0x00;
UIF_SUSPEND = 0;
UIF_TRANSFER = 0;
UIF_BUS_RST = 0; // Clear interrupt flag
}
// USB bus suspend / wake up
if (UIF_SUSPEND) {
UIF_SUSPEND = 0;
if ( USB_MIS_ST & bUMS_SUSPEND ) { // Suspend
//while ( XBUS_AUX & bUART0_TX ); // Wait for Tx
//SAFE_MOD = 0x55;
//SAFE_MOD = 0xAA;
//WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO; // Wake up by USB or RxD0
//PCON |= PD; // Chip sleep
//SAFE_MOD = 0x55;
//SAFE_MOD = 0xAA;
//WAKE_CTRL = 0x00;
} else { // Unexpected interrupt, not supposed to happen !
USB_INT_FG = 0xFF; // Clear interrupt flag
}
}
}
#pragma restore
void USBDeviceCfg()
{
USB_CTRL = 0x00; //Clear USB control register
USB_CTRL &= ~bUC_HOST_MODE; //This bit is the device selection mode
USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; //USB device and internal pull-up enable, automatically return to NAK before interrupt flag is cleared during interrupt
USB_DEV_AD = 0x00; //Device address initialization
// USB_CTRL |= bUC_LOW_SPEED;
// UDEV_CTRL |= bUD_LOW_SPEED; //Run for 1.5M
USB_CTRL &= ~bUC_LOW_SPEED;
UDEV_CTRL &= ~bUD_LOW_SPEED; //Select full speed 12M mode, default mode
#if defined(CH551) || defined(CH552) || defined(CH549)
UDEV_CTRL = bUD_PD_DIS; // Disable DP/DM pull-down resistor
#endif
#if defined(CH559)
UDEV_CTRL = bUD_DP_PD_DIS; // Disable DP/DM pull-down resistor
#endif
UDEV_CTRL |= bUD_PORT_EN; //Enable physical port
}
void USBDeviceIntCfg()
{
USB_INT_EN |= bUIE_SUSPEND; //Enable device hang interrupt
USB_INT_EN |= bUIE_TRANSFER; //Enable USB transfer completion interrupt
USB_INT_EN |= bUIE_BUS_RST; //Enable device mode USB bus reset interrupt
USB_INT_FG |= 0x1F; //Clear interrupt flag
IE_USB = 1; //Enable USB interrupt
EA = 1; //Enable global interrupts
}
void USBDeviceEndPointCfg()
{
UEP1_DMA = (uint16_t) Ep1Buffer; //Endpoint 1 data transfer address
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; //Endpoint 2 automatically flips the sync flag, IN transaction returns NAK, OUT returns ACK
UEP0_DMA = (uint16_t) Ep0Buffer; //Endpoint 0 data transfer address
UEP4_1_MOD = 0XC0; //endpoint1 TX RX enable
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //Manual flip, OUT transaction returns ACK, IN transaction returns NAK
}

+ 61
- 0
CH552/src/userUsbHidKeyboard/USBhandler.h View File

@ -0,0 +1,61 @@
#ifndef __USB_HANDLER_H__
#define __USB_HANDLER_H__
#include <stdint.h>
#include "include/ch5xx.h"
#include "include/ch5xx_usb.h"
#include "USBconstant.h"
extern __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[];
extern __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[];
extern uint16_t SetupLen;
extern uint8_t SetupReq,UsbConfig;
extern const __code uint8_t *pDescr;
#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
// Out
#define EP0_OUT_Callback USB_EP0_OUT
#define EP1_OUT_Callback USB_EP1_OUT
#define EP2_OUT_Callback NOP_Process
#define EP3_OUT_Callback NOP_Process
#define EP4_OUT_Callback NOP_Process
// SOF
#define EP0_SOF_Callback NOP_Process
#define EP1_SOF_Callback NOP_Process
#define EP2_SOF_Callback NOP_Process
#define EP3_SOF_Callback NOP_Process
#define EP4_SOF_Callback NOP_Process
// IN
#define EP0_IN_Callback USB_EP0_IN
#define EP1_IN_Callback USB_EP1_IN
#define EP2_IN_Callback NOP_Process
#define EP3_IN_Callback NOP_Process
#define EP4_IN_Callback NOP_Process
// SETUP
#define EP0_SETUP_Callback USB_EP0_SETUP
#define EP1_SETUP_Callback NOP_Process
#define EP2_SETUP_Callback NOP_Process
#define EP3_SETUP_Callback NOP_Process
#define EP4_SETUP_Callback NOP_Process
#ifdef __cplusplus
extern "C" {
#endif
void USBInterrupt(void);
void USBDeviceCfg();
void USBDeviceIntCfg();
void USBDeviceEndPointCfg();
#ifdef __cplusplus
} // extern "C"
#endif
#endif

+ 22
- 7
README.md View File

@ -3,19 +3,34 @@
A simple script that turns a pin into a keypress
## Built With
## RP2040 Version
### Built With
- Circuit Python
- Adafruit HID
- Adafruit Debouncer
- Adafruit Ticks
## Usage
### Wiring
### Usage
#### Wiring
| Pico Pin | Audio Jack |
| ---- | ---- |
| GP1 | LEFT/RIGHT |
| GND | GROUND |
| -------- | ---------- |
| GP5 | LEFT/RIGHT |
| GND | GROUND |
## CH552 Version
### Built With
- CH5XXDuino
- ArduinoIDE
### Usage
#### Programming
As long as your CH552 chip is blank, you may upload the firmware directly by selecting the port in
Arduino IDE and pressing upload. Otherwise, you will need to hold the `BOOT` button and insert the USB
into your computer.
If you need the change the character that is pressed by the board, you may do so by adjusting the
definitions near the top of the `.ino` file.
## Licensing


lib/adafruit_debouncer.mpy → RP2040/lib/adafruit_debouncer.mpy View File


lib/adafruit_hid/__init__.mpy → RP2040/lib/adafruit_hid/__init__.mpy View File


lib/adafruit_hid/consumer_control.mpy → RP2040/lib/adafruit_hid/consumer_control.mpy View File


lib/adafruit_hid/consumer_control_code.mpy → RP2040/lib/adafruit_hid/consumer_control_code.mpy View File


lib/adafruit_hid/keyboard.mpy → RP2040/lib/adafruit_hid/keyboard.mpy View File


lib/adafruit_hid/keyboard_layout_base.mpy → RP2040/lib/adafruit_hid/keyboard_layout_base.mpy View File


lib/adafruit_hid/keyboard_layout_us.mpy → RP2040/lib/adafruit_hid/keyboard_layout_us.mpy View File


lib/adafruit_hid/keycode.mpy → RP2040/lib/adafruit_hid/keycode.mpy View File


lib/adafruit_hid/mouse.mpy → RP2040/lib/adafruit_hid/mouse.mpy View File


lib/adafruit_ticks.mpy → RP2040/lib/adafruit_ticks.mpy View File


main.py → RP2040/main.py View File


Loading…
Cancel
Save