Arduino键盘

cpp 复制代码
/*
  Newtle Kim Keyboard Project #3
  
  Macro Keyboard for MAC

  Reads an digital input on pin 4 for Encoder Switch
  Connect the encoder CLK to pin 2, DT to pin 3.

  This example code is in the public domain.

  Please refer to the video below for details on how to make it in detail.
  https://www.youtube.com/@newtlekim/videos

  3Dmodeling : 

  All designs and sources are open, but be sure to list the sources.
  Source : https://www.youtube.com/@newtlekim
  
  Put the keywords below in parentheses.
  Keyboard.release() 

  KEY_LEFT_GUI : ⌘ Command
  KEY_LEFT_CTRL : ⌃ Control
  KEY_LEFT_ALT : ⌥ Option
  32 : Space
  KEY_LEFT_SHIFT : Shift
  KEY_CAPS_LOCK : Capslock
  KEY_TAB Tab : Tab
  KEY_ESC : ESC

*/

#include <Keyboard.h>

const uint8_t Keyboard_Volume_Down_MUTE = 0x7f;
const uint8_t Keyboard_Volume_Up_RAW = 0x80;
const uint8_t Keyboard_Volume_Down_RAW = 0x81;


#define CLK 2    // CLK D2
#define DT 3     // DT D3
#define SW 4     // Encoder Switch D4

int counter = 0;
int currentStateCLK;     
int lastStateCLK;    

void setup() {  
  Keyboard.begin();
  pinMode(A1, INPUT_PULLUP);
  pinMode(A2, INPUT_PULLUP);
  
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(CLK,INPUT);
	pinMode(DT,INPUT);

  pinMode(SW,INPUT_PULLUP);
	lastStateCLK = digitalRead(CLK);
	attachInterrupt(0, updateEncoder, CHANGE);
	attachInterrupt(1, updateEncoder, CHANGE);
}


void loop() {
  int sensorVal = digitalRead(SW);

  if (sensorVal == LOW) {
    detachInterrupt(0);
    detachInterrupt(1);
    Keyboard.pressRaw(Keyboard_Volume_Down_MUTE);
    delay(500);
    Keyboard.releaseRaw(Keyboard_Volume_Down_MUTE);
    attachInterrupt(0, updateEncoder, CHANGE);
	  attachInterrupt(1, updateEncoder, CHANGE);
  }
  //9 Key 
  digitalWrite(5, LOW);
  if (digitalRead(A1)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_ALT); // ^ 
    Keyboard.press(KEY_LEFT_GUI); //Command
    Keyboard.press(KEY_ESC); // ESC
    delay(500);
  }
  digitalWrite(5, HIGH);

  digitalWrite(6, LOW);

  // 8 key 
  if (digitalRead(A1)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(KEY_LEFT_SHIFT); //shift
    Keyboard.press('5'); // 5
  }
  // 4 key
  if (digitalRead(A2)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_CTRL); // Ctl
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press('q'); // ESC
    delay(500);
  }
  digitalWrite(6, HIGH);

  digitalWrite(7, LOW);

  if (digitalRead(A1)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(KEY_LEFT_SHIFT); //shift
    Keyboard.press('4'); // 4
    delay(100);
    Keyboard.press(32); // space
    delay(500);
  } 

  if (digitalRead(A2)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_CTRL); //Ctl
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press('f'); // f
    delay(500);
  } 
  digitalWrite(7, HIGH);

  digitalWrite(8, LOW);

  // 6 key
  if (digitalRead(A1))  Keyboard.releaseAll();
  else {
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(KEY_LEFT_SHIFT); //shift
    Keyboard.press('4'); // 4
    delay(500);
  }
  // 2key
  if (digitalRead(A2)) Keyboard.releaseAll();
  else{
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(KEY_LEFT_ALT); // Option
    Keyboard.press('d'); // d
    delay(500);
  }
  digitalWrite(8, HIGH);

  digitalWrite(9, LOW);
  // 5 key
  if (digitalRead(A1)){
    Keyboard.releaseAll();
  } 
  else{
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(KEY_LEFT_SHIFT); //Shift
    Keyboard.press('3'); // space
    delay(500);
  } 

  // 1 Key
  if (digitalRead(A2)){
    Keyboard.releaseAll();
  } 
  else {
    Keyboard.press(KEY_LEFT_CTRL); //control
    Keyboard.press(KEY_LEFT_GUI); //⌘
    Keyboard.press(32); // space
    delay(500);
  }
  digitalWrite(9, HIGH);
  
}

void updateEncoder(){   
	currentStateCLK = digitalRead(CLK);
  
	if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

	
		if (digitalRead(DT) != currentStateCLK) {
      delay(10);
      Keyboard.pressRaw(Keyboard_Volume_Up_RAW);
      Keyboard.releaseRaw(Keyboard_Volume_Up_RAW);
    }
		else {
      delay(10);
      Keyboard.pressRaw(Keyboard_Volume_Down_RAW);
      Keyboard.releaseRaw(Keyboard_Volume_Down_RAW);
 		} 

    
	}

	lastStateCLK = currentStateCLK;
}

Keyboard.h

cpp 复制代码
/*
  Keyboard.h

  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
*/

#ifndef KEYBOARD_h
#define KEYBOARD_h

#include "HID.h"

#if !defined(_USING_HID)

#warning "Using legacy HID core (non pluggable)"

#else

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

#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



// 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[];

// 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 Keyboard_ : public Print
{
private:
  KeyReport _keyReport;
  const uint8_t *_asciimap;
  void sendReport(KeyReport* keys);
public:
  Keyboard_(void);
  void begin(const uint8_t *layout = KeyboardLayout_en_US);
  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);
  
  size_t writeRaw(uint8_t k);
  size_t pressRaw(uint8_t k);
  size_t releaseRaw(uint8_t k);	
  void releaseAll(void);
};
extern Keyboard_ Keyboard;



#endif
#endif

Keyboard.cpp

cpp 复制代码
/*
  Keyboard.cpp

  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"

#if defined(_USING_HID)

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

static const uint8_t _hidReportDescriptor[] PROGMEM = {

    //  Keyboard
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 47
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    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)
    0x75, 0x01,                    //   REPORT_SIZE (1)

    0x95, 0x08,                    //   REPORT_COUNT (8)
    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, 0x73,                    //   LOGICAL_MAXIMUM (115)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)

    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x73,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0,                          // END_COLLECTION
};

Keyboard_::Keyboard_(void)
{
	static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
	HID().AppendDescriptor(&node);
	_asciimap = KeyboardLayout_en_US;
}

void Keyboard_::begin(const uint8_t *layout)
{
	_asciimap = layout;
}

void Keyboard_::end(void)
{
}

void Keyboard_::sendReport(KeyReport* keys)
{
	HID().SendReport(2,keys,sizeof(KeyReport));
}

uint8_t USBPutChar(uint8_t c);

// 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 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);
		if (!k) {
			setWriteError();
			return 0;
		}
		if ((k & ALT_GR) == ALT_GR) {
			_keyReport.modifiers |= 0x40;   // AltGr = right Alt
			k &= 0x3F;
		} else if ((k & SHIFT) == SHIFT) {
			_keyReport.modifiers |= 0x02;	// the left shift modifier
			k &= 0x7F;
		}
		if (k == ISO_REPLACEMENT) {
			k = ISO_KEY;
		}
	}

	// 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 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);
		if (!k) {
			return 0;
		}
		if ((k & ALT_GR) == ALT_GR) {
			_keyReport.modifiers &= ~(0x40);   // AltGr = right Alt
			k &= 0x3F;
		} else if ((k & SHIFT) == SHIFT) {
			_keyReport.modifiers &= ~(0x02);	// the left shift modifier
			k &= 0x7F;
		}
		if (k == ISO_REPLACEMENT) {
			k = ISO_KEY;
		}
	}

	// 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;
}

void 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 Keyboard_::write(uint8_t c)
{
	uint8_t p = press(c);	// Keydown
	release(c);		// Keyup
	return p;		// just return the result of press() since release() almost always returns 1
}

size_t 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;
}

size_t Keyboard_::pressRaw(uint8_t k) 
{
	uint8_t i;
	
	// 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;
}


// releaseRaw() 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 Keyboard_::releaseRaw(uint8_t k) 
{
	uint8_t i;
	
	// 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 Keyboard_::writeRaw(uint8_t c)
{
	uint8_t p = pressRaw(c);  // Keydown
	releaseRaw(c);            // Keyup
	return p;              // just return the result of press() since releaseRaw() almost always returns 1
}


Keyboard_ Keyboard;

#endif
相关推荐
QiLinkOS7 小时前
第三视觉理解徐玉生与他的商业活动(30)
大数据·c++·人工智能·算法·开源协议
mit6.8247 小时前
阅读的核心,是再读
c++
upgrador9 小时前
基础知识:C++ STL构造函数的左闭右开惯例及其实现原理
开发语言·c++
凯瑟琳.奥古斯特11 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展
林中青木12 小时前
CT重构原理及C++代码实现
c++·计算机视觉·重构
满天星830357712 小时前
Protobuf的介绍及使用
c++
☆cwlulu12 小时前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu
卷无止境12 小时前
C++ 存储类说明符(Storage Class Specifier)大横评
c++·后端
卷无止境12 小时前
C++ 编程的一大坑:非常量全局变量是"万恶之源"
c++·后端
C语言小火车12 小时前
C++ 快速排序(Quick Sort)深度精讲:分治思想、Lomuto 分区法及三数取中优化,面试手撕必会
c语言·开发语言·c++·面试·排序算法·快速排序