Skip to content

Instantly share code, notes, and snippets.

@sugarflower
Last active April 10, 2024 11:20
Show Gist options
  • Save sugarflower/4e2ddfb0978ef5626752d84ec0dcd4ab to your computer and use it in GitHub Desktop.
Save sugarflower/4e2ddfb0978ef5626752d84ec0dcd4ab to your computer and use it in GitHub Desktop.

現在の進捗的な。
しかしRaspberry Pi picoをArduinoで使うとストレージをマウントして書き込みを行う、これが開発環境と反りが良くないので pi picoでの調整はここまでにしてM5atom S3にバトンを渡そうと思う。

Qiitaのこちらの記事などが参考になる。

現在シフトキーが効かないという問題が起きていてあと一歩というところ。

KeyboardLayout.hでSHIFTを0x100にdefineする部分を網羅できていなかったので追記で対応とします。

KeyboardLayout_ja_JP.cpp

#include "KeyboardLayout.h"

extern const uint16_t KeyboardLayout_ja_JP[128] PROGMEM =
{
    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,	    // SOH
    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,	// !
    0x1f|SHIFT,	// " 
    0x20|SHIFT,	// #
    0x21|SHIFT,	// $
    0x22|SHIFT,	// %
    0x23|SHIFT,	// &
    0x24|SHIFT,	// '
    0x25|SHIFT,	// (
    0x26|SHIFT,	// )
    0x34|SHIFT,	// *
    0x33|SHIFT,	// +
    0x36,   	// ,
    0x2d,	    // -
    0x36,	    // .
    0x38,	    // /
    0x27,	    // 0
    0x1e,	    // 1
    0x1f,	    // 2
    0x20,	    // 3
    0x21,	    // 4
    0x22,	    // 5
    0x23,	    // 6
    0x24,	    // 7
    0x25,	    // 8
    0x26,	    // 9
    0x34,	    // :
    0x33,	    // ;
    0x36|SHIFT,	// <
    0x2d|SHIFT,	// =
    0x37|SHIFT,	// >
    0x38|SHIFT,	// ?
    0x2f,	    // @
    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
    0x30,	    // [
    0x89,	    // bslash
    0x31,	    // ]
    0x2e,	    // ^
    0x87|SHIFT,	// _
    0x2f|SHIFT,	// `
    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
    0x30|SHIFT,	// {
    0x89|SHIFT,	// |
    0x31|SHIFT,	// }
    0x2e|SHIFT,	// ~
    0x00	    // DEL
};

Keyboard.h

/*
  Keyboard.h

  Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
  Main Arduino Library Copyright (c) 2015, Arduino LLC
  Original code (pre-library): Copyright (c) 2011, Peter Barrett

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#pragma once

#include <Arduino.h>

//================================================================================
//================================================================================
//  Keyboard

// Modifiers
#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

// Misc keys
#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_MENU          0xED // "Keyboard Application" in USB standard
#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_PRINT_SCREEN  0xCE // Print Screen / SysRq
#define KEY_SCROLL_LOCK   0xCF
#define KEY_PAUSE         0xD0 // Pause / Break

// Numeric keypad
#define KEY_NUM_LOCK      0xDB
#define KEY_KP_SLASH      0xDC
#define KEY_KP_ASTERISK   0xDD
#define KEY_KP_MINUS      0xDE
#define KEY_KP_PLUS       0xDF
#define KEY_KP_ENTER      0xE0
#define KEY_KP_1          0xE1
#define KEY_KP_2          0xE2
#define KEY_KP_3          0xE3
#define KEY_KP_4          0xE4
#define KEY_KP_5          0xE5
#define KEY_KP_6          0xE6
#define KEY_KP_7          0xE7
#define KEY_KP_8          0xE8
#define KEY_KP_9          0xE9
#define KEY_KP_0          0xEA
#define KEY_KP_DOT        0xEB

// Function keys
#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


// Cpnsumer keys, taken from TinyUSB

// Power Control
#define KEY_POWER                              0x0030
#define KEY_RESET                              0x0031
#define KEY_SLEEP                              0x0032

// Screen Brightness
#define KEY_BRIGHTNESS_INCREMENT               0x006F
#define KEY_BRIGHTNESS_DECREMENT               0x0070

// These HID usages operate only on mobile systems (battery powered) and
// require Windows 8 (build 8302 or greater).
#define KEY_WIRELESS_RADIO_CONTROLS            0x000C
#define KEY_WIRELESS_RADIO_BUTTONS             0x00C6
#define KEY_WIRELESS_RADIO_LED                 0x00C7
#define KEY_WIRELESS_RADIO_SLIDER_SWITCH       0x00C8

// Media Control
#define KEY_PLAY_PAUSE                         0x00CD
#define KEY_SCAN_NEXT                          0x00B5
#define KEY_SCAN_PREVIOUS                      0x00B6
#define KEY_STOP                               0x00B7
#define KEY_VOLUME                             0x00E0
#define KEY_MUTE                               0x00E2
#define KEY_BASS                               0x00E3
#define KEY_TREBLE                             0x00E4
#define KEY_BASS_BOOST                         0x00E5
#define KEY_VOLUME_INCREMENT                   0x00E9
#define KEY_VOLUME_DECREMENT                   0x00EA
#define KEY_BASS_INCREMENT                     0x0152
#define KEY_BASS_DECREMENT                     0x0153
#define KEY_TREBLE_INCREMENT                   0x0154
#define KEY_TREBLE_DECREMENT                   0x0155

// Application Launcher
#define KEY_AL_CONSUMER_CONTROL_CONFIGURATION  0x0183
#define KEY_AL_EMAIL_READER                    0x018A
#define KEY_AL_CALCULATOR                      0x0192
#define KEY_AL_LOCAL_BROWSER                   0x0194

// Browser/Explorer Specific
#define KEY_AC_SEARCH                          0x0221
#define KEY_AC_HOME                            0x0223
#define KEY_AC_BACK                            0x0224
#define KEY_AC_FORWARD                         0x0225
#define KEY_AC_STOP                            0x0226
#define KEY_AC_REFRESH                         0x0227
#define KEY_AC_BOOKMARKS                       0x022A

// Mouse Horizontal scroll
#define KEY_AC_PAN                             0x0238


// Supported keyboard layouts
/*
extern const uint8_t KeyboardLayout_de_DE[];
extern const uint8_t KeyboardLayout_en_US[];
extern const uint8_t KeyboardLayout_es_ES[];
extern const uint8_t KeyboardLayout_fr_FR[];
extern const uint8_t KeyboardLayout_it_IT[];
extern const uint8_t KeyboardLayout_pt_PT[];
extern const uint8_t KeyboardLayout_sv_SE[];
extern const uint8_t KeyboardLayout_da_DK[];
extern const uint8_t KeyboardLayout_ja_JP[];
*/
extern const uint16_t KeyboardLayout_ja_JP[];


// Low level key report: up to 6 keys and shift, ctrl etc at once
typedef struct
{
  uint8_t modifiers;
  uint8_t reserved;
  uint8_t keys[6];
} KeyReport;

class HID_Keyboard : public Print
{
protected:
  KeyReport _keyReport;
  //const uint8_t *_asciimap;
  const uint16_t *_asciimap;
  virtual void sendReport(KeyReport* keys) = 0;
  virtual void sendConsumerReport(uint16_t key) = 0;

public:
  HID_Keyboard(void);
  //void begin(const uint8_t *layout = KeyboardLayout_en_US);
  void begin(const uint16_t *layout = KeyboardLayout_ja_JP);
  void end(void);
  size_t write(uint8_t k);
  size_t write(const uint8_t *buffer, size_t size);
  size_t press(uint8_t k);
  size_t release(uint8_t k);
  void releaseAll(void);
  size_t consumerPress(uint16_t k);
  size_t consumerRelease();

  typedef void(*LedCallbackFcn)(bool numlock, bool capslock, bool scrolllock, bool compose, bool kana, void *cbData);
  void onLED(LedCallbackFcn fcn, void *cbData = nullptr);
  LedCallbackFcn _ledCB;
  void * _ledCBdata;
};

Keyboard.cpp

/*
  Keyboard.cpp

  Modified by Earle F. Philhower, III <earlephilhower@yahoo.com>
  Main Arduino Library Copyright (c) 2015, Arduino LLC
  Original code (pre-library): Copyright (c) 2011, Peter Barrett

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Keyboard.h"
#include "KeyboardLayout.h"
#include <RP2040USB.h>

#include "tusb.h"
#include "class/hid/hid_device.h"

//================================================================================
//================================================================================
//  Keyboard

HID_Keyboard::HID_Keyboard(void) {
    bzero(&_keyReport, sizeof(_keyReport));
    _asciimap = KeyboardLayout_ja_JP;
    //_asciimap = KeyboardLayout_en_US;
    _ledCB = nullptr;
}

//void HID_Keyboard::begin(const uint8_t *layout) {
void HID_Keyboard::begin(const uint16_t *layout) {
    _asciimap = layout;
}

void HID_Keyboard::end(void) {
}

// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report.  Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t HID_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
		_keyReport.modifiers |= (1<<(k-128));
		k = 0;
	} else {				// it's a printing key
		//k = pgm_read_byte(_asciimap + k);
        uint16_t c = _asciimap[k];

		//if (!k) {
		if (!c) {
			setWriteError();
			return 0;
		}
        
		//if ((k & ALT_GR) == ALT_GR) {
		if ((c & ALT_GR) == ALT_GR) {
			_keyReport.modifiers |= 0x40;   // AltGr = right Alt
			//k &= 0x3F;

		//} else if ((k & SHIFT) == SHIFT) {
		} 

        if ((c & SHIFT) == SHIFT) {
			_keyReport.modifiers |= 0x02;	// the left shift modifier
			//k &= 0x7F;
		}
        /*
		if (k == ISO_REPLACEMENT) {
			k = ISO_KEY;
		}
        */

        k = (uint8_t)(c & 0xff);
	}

	// Add k to the key report only if it's not already present
	// and if there is an empty slot.
	if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
		_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
		_keyReport.keys[4] != k && _keyReport.keys[5] != k) {

		for (i=0; i<6; i++) {
			if (_keyReport.keys[i] == 0x00) {
				_keyReport.keys[i] = k;
				break;
			}
		}
		if (i == 6) {
			setWriteError();
			return 0;
		}
	}
	sendReport(&_keyReport);
	return 1;
}

// release() takes the specified key out of the persistent key report and
// sends the report.  This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t HID_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
		_keyReport.modifiers &= ~(1<<(k-128));
		k = 0;

	} else {				// it's a printing key
		//k = pgm_read_byte(_asciimap + k);
        uint16_t c = _asciimap[k];
		//if (!k) {
        //
		if (!c) {
			return 0;
		}

		//if ((k & ALT_GR) == ALT_GR) {
		if ((c & ALT_GR) == ALT_GR) {
			_keyReport.modifiers &= ~(0x40);   // AltGr = right Alt
			//c &= 0x3F;
			//k &= 0x3F;

		//} else if ((k & SHIFT) == SHIFT) {
		} 

        if ((c & SHIFT) == SHIFT) {
			_keyReport.modifiers &= ~(0x02);	// the left shift modifier
			//k &= 0x7F;
		}
        /*
		if (k == ISO_REPLACEMENT) {
			k = ISO_KEY;
		}
        */

        k = (uint8_t)(c & 0xff);
	}

	// 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=0; i<6; i++) {
		if (0 != k && _keyReport.keys[i] == k) {
			_keyReport.keys[i] = 0x00;
		}
	}

	sendReport(&_keyReport);
	return 1;
}

size_t HID_Keyboard::consumerPress(uint16_t k)
{
    sendConsumerReport(k);
    return 1;
}

size_t HID_Keyboard::consumerRelease()
{
    sendConsumerReport(0);
    return 1;
}

void HID_Keyboard::releaseAll(void)
{
	_keyReport.keys[0] = 0;
	_keyReport.keys[1] = 0;
	_keyReport.keys[2] = 0;
	_keyReport.keys[3] = 0;
	_keyReport.keys[4] = 0;
	_keyReport.keys[5] = 0;
	_keyReport.modifiers = 0;
	sendReport(&_keyReport);
}

size_t HID_Keyboard::write(uint8_t c)
{
	uint8_t p = press(c);  // Keydown
	delay(10);
	release(c);            // Keyup
	delay(10);
	return p;              // just return the result of press() since release() almost always returns 1
}

size_t HID_Keyboard::write(const uint8_t *buffer, size_t size) {
	size_t n = 0;
	while (size--) {
		if (*buffer != '\r') {
			if (write(*buffer)) {
				n++;
			} else {
				break;
			}
		}
		buffer++;
	}
	return n;
}

void HID_Keyboard::onLED(LedCallbackFcn fcn, void *cbData) {
    _ledCB = fcn;
    _ledCBdata = cbData;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment