mirror of
https://github.com/clockworkpi/uConsole.git
synced 2025-12-12 10:08:50 +01:00
add keyboard source code
This commit is contained in:
parent
5b69e9c831
commit
17269a8c72
13
Code/uconsole_keyboard/README.md
Normal file
13
Code/uconsole_keyboard/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
Arduino 1.8.13
|
||||
|
||||
http://dan.drown.org/stm32duino/package_STM32duino_index.json
|
||||
|
||||
STM32F1xx/GD32F1xx boards
|
||||
by stm32duino version 2021.2.22
|
||||
|
||||
GENERIC STM32F103R series
|
||||
|
||||
gd32f1_generic_boot20_pc13.bin
|
||||
generic_boot20_pc13.bin
|
||||
|
||||
|
||||
53
Code/uconsole_keyboard/debouncer.h
Normal file
53
Code/uconsole_keyboard/debouncer.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef DEBOUNCER_H
|
||||
#define DEBOUNCER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint8_t millis_t;
|
||||
|
||||
const millis_t DEBOUNCE_MS = 5;
|
||||
|
||||
/**
|
||||
@brief Asymmetric debouncer
|
||||
*/
|
||||
class Debouncer {
|
||||
public:
|
||||
Debouncer();
|
||||
void updateTime(millis_t delta);
|
||||
bool sample(bool value);
|
||||
private:
|
||||
millis_t timeout;
|
||||
};
|
||||
|
||||
template<typename T, T millis>
|
||||
class Timeout {
|
||||
public:
|
||||
Timeout() {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
void updateTime(millis_t delta) {
|
||||
if (timeout > delta) {
|
||||
timeout -= delta;
|
||||
} else {
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void expire() {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
bool get() const {
|
||||
return timeout == 0;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
timeout = millis;
|
||||
}
|
||||
private:
|
||||
uint16_t timeout;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
23
Code/uconsole_keyboard/debouncer.ino
Normal file
23
Code/uconsole_keyboard/debouncer.ino
Normal file
@ -0,0 +1,23 @@
|
||||
#include "debouncer.h"
|
||||
|
||||
Debouncer::Debouncer()
|
||||
: timeout(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Debouncer::updateTime(millis_t delta) {
|
||||
if (timeout > delta) {
|
||||
timeout -= delta;
|
||||
} else {
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Debouncer::sample(bool value) {
|
||||
if (value || timeout == 0) {
|
||||
timeout = DEBOUNCE_MS;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
60
Code/uconsole_keyboard/devterm.h
Normal file
60
Code/uconsole_keyboard/devterm.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef DEVTERM_H
|
||||
#define DEVTERM_H
|
||||
|
||||
#define KEY_LATENCY 1400
|
||||
#include "state.h"
|
||||
|
||||
#include <USBComposite.h>
|
||||
typedef struct key_debouncing{
|
||||
|
||||
bool deing;//debouncing
|
||||
uint16_t de_time;
|
||||
|
||||
}KEY_DEB;
|
||||
|
||||
typedef struct keyboard_lock{
|
||||
|
||||
uint16_t lock;//
|
||||
uint16_t time;//
|
||||
uint16_t begin;//
|
||||
|
||||
}KEYBOARD_LOCK;
|
||||
|
||||
typedef struct keyboard_state{
|
||||
|
||||
uint8_t layer;
|
||||
uint8_t prev_layer;
|
||||
uint8_t fn_on;
|
||||
uint8_t sf_on;//shift on
|
||||
|
||||
uint8_t backlight;//0 1 2 3
|
||||
uint8_t lock;//0 1
|
||||
|
||||
|
||||
KEYBOARD_LOCK ctrl;
|
||||
KEYBOARD_LOCK shift;
|
||||
KEYBOARD_LOCK alt;
|
||||
KEYBOARD_LOCK fn;
|
||||
|
||||
}KEYBOARD_STATE;
|
||||
|
||||
class DEVTERM {
|
||||
public:
|
||||
HIDKeyboard *Keyboard;
|
||||
HIDMouse *Mouse;
|
||||
HIDJoystick *Joystick;
|
||||
HIDConsumer *Consumer;
|
||||
KEYBOARD_STATE Keyboard_state;
|
||||
USBCompositeSerial *_Serial;
|
||||
//if not to use USBCompositeSerial,then use default Serial
|
||||
//**Serial and USBCompositeSerial can not use together, otherwise the keyboard firmware uploading will be dead**
|
||||
//and you will need to find a way out to flash the stm32duino bootloader once again
|
||||
//USBSerial *_Serial;//_Serial = &Serial;
|
||||
State *state;
|
||||
uint32_t delta;
|
||||
};
|
||||
|
||||
#define KEYBOARD_PULL 0 // 1 for PULLUP, 0 FOR PULLDOWN
|
||||
#define KEYBOARD_LED_PWM_PERIOD 200
|
||||
|
||||
#endif
|
||||
29
Code/uconsole_keyboard/glider.h
Normal file
29
Code/uconsole_keyboard/glider.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef GLIDER_H
|
||||
#define GLIDER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
class Glider {
|
||||
public:
|
||||
Glider();
|
||||
void setDirection(int8_t);
|
||||
void update(float velocity, uint16_t sustain);
|
||||
void updateSpeed(float velocity);
|
||||
void stop();
|
||||
|
||||
struct GlideResult {
|
||||
int8_t value;
|
||||
bool stopped;
|
||||
};
|
||||
GlideResult glide(uint8_t delta);
|
||||
|
||||
public:
|
||||
int8_t direction;
|
||||
float speed;
|
||||
uint16_t sustain;
|
||||
uint16_t release;
|
||||
float error;
|
||||
};
|
||||
|
||||
#endif
|
||||
60
Code/uconsole_keyboard/glider.ino
Normal file
60
Code/uconsole_keyboard/glider.ino
Normal file
@ -0,0 +1,60 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "glider.h"
|
||||
#include "math.h"
|
||||
|
||||
Glider::Glider()
|
||||
: speed(0),
|
||||
sustain(0),
|
||||
release(0),
|
||||
error(0)
|
||||
{}
|
||||
|
||||
void Glider::setDirection(int8_t direction) {
|
||||
if (this->direction != direction) {
|
||||
stop();
|
||||
}
|
||||
this->direction = direction;
|
||||
}
|
||||
|
||||
void Glider::update(float speed, uint16_t sustain) {
|
||||
this->speed = speed;
|
||||
this->sustain = sustain;
|
||||
this->release = sustain;
|
||||
}
|
||||
|
||||
void Glider::updateSpeed(float speed) {
|
||||
this->speed = speed;
|
||||
}
|
||||
|
||||
void Glider::stop() {
|
||||
this->speed = 0;
|
||||
this->sustain = 0;
|
||||
this->release = 0;
|
||||
this->error = 0;
|
||||
}
|
||||
|
||||
Glider::GlideResult Glider::glide(millis_t delta) {
|
||||
const auto alreadyStopped = speed == 0;
|
||||
|
||||
error += speed * delta;
|
||||
int8_t distance = 0;
|
||||
if (error > 0) {
|
||||
distance = clamp<int8_t>(std::ceil(error));
|
||||
}
|
||||
error -= distance;
|
||||
|
||||
if (sustain > 0) {
|
||||
const auto sustained = min(sustain, (uint16_t)delta);
|
||||
sustain -= sustained;
|
||||
} else if (release > 0) {
|
||||
const auto released = min(release, (uint16_t)delta);
|
||||
speed = speed * (release - released) / release;
|
||||
release -= released;
|
||||
} else {
|
||||
speed = 0;
|
||||
}
|
||||
|
||||
const int8_t result = direction * distance;
|
||||
return GlideResult { result, !alreadyStopped && speed == 0 };
|
||||
}
|
||||
19
Code/uconsole_keyboard/helper.h
Normal file
19
Code/uconsole_keyboard/helper.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
*
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#ifndef HELPER_H
|
||||
#define HELPER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
uint8_t read_io(uint8_t io);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
10
Code/uconsole_keyboard/helper.ino
Normal file
10
Code/uconsole_keyboard/helper.ino
Normal file
@ -0,0 +1,10 @@
|
||||
#include "helper.h"
|
||||
|
||||
|
||||
uint8_t read_io(uint8_t io) {
|
||||
if(digitalRead(io) == LOW ){
|
||||
return 0;
|
||||
}else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
83
Code/uconsole_keyboard/keyboard.h
Normal file
83
Code/uconsole_keyboard/keyboard.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
/*
|
||||
* clockworkpi devterm keyboard test2
|
||||
* able to correct scan the 8x8 keypads re-action
|
||||
*/
|
||||
|
||||
#include "devterm.h"
|
||||
|
||||
#include "keys_io_map.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MATRIX_ROWS 8
|
||||
#define MATRIX_COLS 8
|
||||
|
||||
#define MATRIX_KEYS 64 // 8*8
|
||||
|
||||
#ifndef DEBOUNCE
|
||||
# define DEBOUNCE 20
|
||||
#endif
|
||||
|
||||
enum SKEYS {
|
||||
_SELECT_KEY =0xe8, //Joystick.button(n)
|
||||
_START_KEY, //Joystick.button(n)
|
||||
_JOYSTICK_UP, //B1 //Joystick.Y()
|
||||
_JOYSTICK_DOWN, //Joystick.Y()
|
||||
_JOYSTICK_LEFT, //Joystick.X()
|
||||
_JOYSTICK_RIGHT, //Joystick.X()
|
||||
_JOYSTICK_A, //Joystick.button(1)
|
||||
_JOYSTICK_B, //Joystick.button(2)
|
||||
_JOYSTICK_X, //Joystick.button(3)
|
||||
_JOYSTICK_Y, //Joystick.button(4)
|
||||
_JOYSTICK_L,
|
||||
_JOYSTICK_R,
|
||||
_FN_KEY,
|
||||
_MOUSE_LEFT, // Mouse.press(1)
|
||||
_MOUSE_MID, // Mouse.press(2)
|
||||
_MOUSE_RIGHT, // Mouse.press(3)
|
||||
|
||||
_FN_BRIGHTNESS_UP, //USB Consumer brightness up https://github.com/torvalds/linux/blob/7fe10096c1508c7f033d34d0741809f8eecc1ed4/drivers/hid/hid-input.c#L903
|
||||
_FN_BRIGHTNESS_DOWN, //USB Consumer brightness down
|
||||
|
||||
_VOLUME_M,
|
||||
_VOLUME_P,
|
||||
_VOLUME_MUTE, //https://github.com/torvalds/linux/blob/7fe10096c1508c7f033d34d0741809f8eecc1ed4/drivers/hid/hid-input.c#L956
|
||||
_TRACKBALL_BTN,
|
||||
_FN_LOCK_KEYBOARD,
|
||||
_FN_LIGHT_KEYBOARD,
|
||||
};
|
||||
|
||||
void init_rows();
|
||||
void init_cols();
|
||||
uint8_t read_io(uint8_t io);
|
||||
|
||||
void matrix_init();
|
||||
uint8_t matrix_scan(void);
|
||||
|
||||
bool matrix_is_on(uint8_t row, uint8_t col);
|
||||
uint8_t matrix_get_row(uint8_t row) ;
|
||||
|
||||
|
||||
//void matrix_print(void);
|
||||
|
||||
|
||||
|
||||
void keyboard_task(DEVTERM*);
|
||||
void keyboard_init(DEVTERM*);
|
||||
|
||||
|
||||
#define KEY_PRESSED 1
|
||||
#define KEY_RELEASED 0
|
||||
|
||||
#define KEY_PRNT_SCRN 0xCE //Print screen - 0x88 == usb hut1_12v2.pdf keyboard code
|
||||
#define KEY_PAUSE 0xd0 // - 0x88 == usb hut1_12v2.pdf keyboard code
|
||||
|
||||
#define KEY_VOLUME_UP 0x108 // - 0x88 == usb hut1_12v2.pdf keyboard code
|
||||
#define KEY_VOLUME_DOWN 0x109 // - 0x88 == usb hut1_12v2.pdf keyboard code
|
||||
|
||||
#endif
|
||||
204
Code/uconsole_keyboard/keyboard.ino
Normal file
204
Code/uconsole_keyboard/keyboard.ino
Normal file
@ -0,0 +1,204 @@
|
||||
#include "keyboard.h"
|
||||
#include "helper.h"
|
||||
|
||||
KEY_DEB keyboard_debouncing;
|
||||
|
||||
uint8_t matrix_rows[ MATRIX_ROWS ]= {ROW1,ROW2,ROW3,ROW4,ROW5,ROW6,ROW7,ROW8};
|
||||
uint8_t matrix_cols[ MATRIX_COLS ] = {COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8};
|
||||
|
||||
/* matrix state(1:on, 0:off) */
|
||||
static uint8_t matrix[MATRIX_ROWS];
|
||||
static uint8_t matrix_debouncing[MATRIX_COLS];
|
||||
static uint8_t matrix_prev[MATRIX_ROWS];
|
||||
|
||||
uint8_t read_kbd_io(uint8_t io) {
|
||||
|
||||
#if defined KEYBOARD_PULL && KEYBOARD_PULL == 0
|
||||
if(digitalRead(io) == LOW ){
|
||||
return 0;
|
||||
}else {
|
||||
return 1;
|
||||
}
|
||||
#elif defined KEYBOARD_PULL && KEYBOARD_PULL == 1
|
||||
if(digitalRead(io) == LOW ){
|
||||
return 1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void init_rows(){
|
||||
int i;
|
||||
for(i=0;i<8;i++) {
|
||||
|
||||
#if defined KEYBOARD_PULL && KEYBOARD_PULL == 0
|
||||
pinMode(matrix_rows[i],OUTPUT);
|
||||
digitalWrite(matrix_rows[i],LOW);
|
||||
pinMode(matrix_rows[i],INPUT_PULLDOWN);
|
||||
|
||||
#elif defined KEYBOARD_PULL && KEYBOARD_PULL == 1
|
||||
pinMode(matrix_rows[i],INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void init_cols() {
|
||||
|
||||
int i;
|
||||
for(i=0;i<8;i++){
|
||||
pinMode(matrix_cols[i],OUTPUT);
|
||||
digitalWrite(matrix_cols[i],LOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void matrix_init() {
|
||||
init_cols();
|
||||
init_rows();
|
||||
|
||||
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
|
||||
matrix[i] = 0;
|
||||
matrix_debouncing[i] = 0;
|
||||
matrix_prev[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
uint8_t matrix_scan(void) {
|
||||
|
||||
uint8_t data;
|
||||
for(int col = 0; col < MATRIX_COLS;col++){
|
||||
data = 0;
|
||||
|
||||
#if defined KEYBOARD_PULL && KEYBOARD_PULL == 1
|
||||
|
||||
digitalWrite(matrix_cols[col],LOW);
|
||||
#elif defined KEYBOARD_PULL && KEYBOARD_PULL == 0
|
||||
digitalWrite(matrix_cols[col],HIGH);
|
||||
|
||||
#endif
|
||||
delayMicroseconds(700);
|
||||
|
||||
data =(
|
||||
( read_kbd_io(matrix_rows[0]) << 0 ) |
|
||||
( read_kbd_io(matrix_rows[1]) << 1 ) |
|
||||
( read_kbd_io(matrix_rows[2]) << 2 ) |
|
||||
( read_kbd_io(matrix_rows[3]) << 3 ) |
|
||||
( read_kbd_io(matrix_rows[4]) << 4 ) |
|
||||
( read_kbd_io(matrix_rows[5]) << 5 ) |
|
||||
( read_kbd_io(matrix_rows[6]) << 6 ) |
|
||||
( read_kbd_io(matrix_rows[7]) << 7 )
|
||||
);
|
||||
|
||||
#if defined KEYBOARD_PULL && KEYBOARD_PULL == 1
|
||||
digitalWrite(matrix_cols[col],HIGH);
|
||||
#elif defined KEYBOARD_PULL && KEYBOARD_PULL == 0
|
||||
digitalWrite(matrix_cols[col],LOW);
|
||||
#endif
|
||||
|
||||
if (matrix_debouncing[col] != data) {
|
||||
matrix_debouncing[col] = data;
|
||||
keyboard_debouncing.deing = true;
|
||||
keyboard_debouncing.de_time = millis();
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboard_debouncing.deing == true && ( (millis() - keyboard_debouncing.de_time) > DEBOUNCE )) {
|
||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
||||
|
||||
matrix[row] = 0;
|
||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
||||
matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col);
|
||||
}
|
||||
}
|
||||
keyboard_debouncing.deing = false;
|
||||
|
||||
}else{
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool matrix_is_on(uint8_t row, uint8_t col) {
|
||||
return (matrix[row] & (1<<col));
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t matrix_get_row(uint8_t row) {
|
||||
return matrix[row];
|
||||
}
|
||||
|
||||
|
||||
void matrix_press(DEVTERM*dv,uint8_t row,uint8_t col) {
|
||||
char buff[128];
|
||||
|
||||
if(matrix_is_on(row,col) == true ){
|
||||
sprintf(buff,"%d %d M%d pressed\n",row,col,(row+1)*10+col+1);
|
||||
//dv->_Serial->print(buff);
|
||||
keyboard_action(dv,row,col,KEY_PRESSED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void matrix_release(DEVTERM*dv,uint8_t row,uint8_t col) {
|
||||
char buff[128];
|
||||
|
||||
|
||||
if(matrix_is_on(row,col) == false ){
|
||||
sprintf(buff,"%d %d M%d released\n",row,col,(row+1)*10+col+1);
|
||||
//dv->_Serial->print(buff);
|
||||
keyboard_action(dv,row,col,KEY_RELEASED);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void keyboard_task(DEVTERM*dv)
|
||||
{
|
||||
char buff[128];
|
||||
uint8_t matrix_row = 0;
|
||||
uint8_t matrix_change = 0;
|
||||
uint8_t pressed = 0;
|
||||
|
||||
matrix_scan();
|
||||
|
||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||
matrix_row = matrix_get_row(r);
|
||||
matrix_change = matrix_row ^ matrix_prev[r];
|
||||
if (matrix_change) {
|
||||
//sprintf(buff,"matrix_row: %d %d\n",matrix_row,matrix_prev[r]);
|
||||
//dv->_Serial->print(buff);
|
||||
uint8_t col_mask = 1;
|
||||
for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
|
||||
if (matrix_change & col_mask) {
|
||||
pressed = (matrix_row & col_mask);
|
||||
if(pressed != 0) {
|
||||
matrix_press(dv,r,c);
|
||||
}else {
|
||||
matrix_release(dv,r,c);
|
||||
}
|
||||
matrix_prev[r] ^= col_mask;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void keyboard_init(DEVTERM*){
|
||||
matrix_init();
|
||||
keyboard_debouncing.deing=false;
|
||||
keyboard_debouncing.de_time = 0;
|
||||
|
||||
}
|
||||
542
Code/uconsole_keyboard/keymaps.ino
Normal file
542
Code/uconsole_keyboard/keymaps.ino
Normal file
@ -0,0 +1,542 @@
|
||||
#include "devterm.h"
|
||||
#include "keyboard.h"
|
||||
#include "keys.h"
|
||||
|
||||
#define EMP 0XFFFF
|
||||
|
||||
/*
|
||||
B1 joystick up
|
||||
B2 joystick down
|
||||
B3 joystick left
|
||||
B4 joystick right
|
||||
|
||||
B5 joystick A
|
||||
B6 joystick B
|
||||
B7 joystick X
|
||||
B8 joystick Y
|
||||
|
||||
B9 left shift
|
||||
B10 Fn
|
||||
B11 left Ctrl
|
||||
B12 Cmd
|
||||
B13 left Alt
|
||||
B14 mouse left
|
||||
B15 mouse mid
|
||||
B16 mouse right
|
||||
*/
|
||||
#define _PRINT_KEY KEY_PRNT_SCRN
|
||||
#define _PAUSE_KEY KEY_PAUSE
|
||||
|
||||
#define _LEFT_SHIFT_KEY KEY_LEFT_SHIFT
|
||||
#define _LEFT_CTRL_KEY KEY_LEFT_CTRL
|
||||
#define _CMD_KEY KEY_RIGHT_GUI
|
||||
#define _LEFT_ALT KEY_LEFT_ALT
|
||||
|
||||
#define _FN_KEY_UP_ARROW KEY_PAGE_UP
|
||||
#define _FN_KEY_DOWN_ARROW KEY_PAGE_DOWN
|
||||
#define _FN_KEY_LEFT_ARROW KEY_HOME
|
||||
#define _FN_KEY_RIGHT_ARROW KEY_END
|
||||
|
||||
|
||||
#define DEF_LAYER 0x00
|
||||
#define FN_LAYER 0x01
|
||||
|
||||
|
||||
/*
|
||||
* keyboard_maps
|
||||
* M11 - M18
|
||||
* M21 - M28
|
||||
* M31 - M38
|
||||
* M41 - M48
|
||||
* M51 - M58
|
||||
* M61 - M68
|
||||
* M71 - M78
|
||||
* M81 - M88
|
||||
*/
|
||||
const uint16_t keyboard_maps[][MATRIX_KEYS] = {
|
||||
|
||||
[DEF_LAYER] = { _SELECT_KEY,_START_KEY,_VOLUME_M,'`','[',']','-','=', \
|
||||
'1','2','3','4','5','6','7','8',\
|
||||
'9','0',KEY_ESC,KEY_TAB,EMP,EMP,EMP,EMP, \
|
||||
'q','w','e','r','t','y','u','i', \
|
||||
'o','p','a','s','d','f','g','h',\
|
||||
'j','k','l','z','x','c','v','b', \
|
||||
'n','m',',','.','/','\\',';','\'', \
|
||||
KEY_BACKSPACE,KEY_RETURN,_FN_KEY,_FN_KEY,' ',EMP,EMP,EMP},
|
||||
|
||||
[FN_LAYER] = { _PRINT_KEY,_PAUSE_KEY,_VOLUME_MUTE,'`','[',']',KEY_F11,KEY_F12, \
|
||||
KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,\
|
||||
KEY_F9,KEY_F10,_FN_LOCK_KEYBOARD,KEY_CAPS_LOCK,EMP,EMP,EMP,EMP, \
|
||||
'q','w','e','r','t','y',KEY_PAGE_UP,KEY_INSERT, \
|
||||
'o','p','a','s','d','f','g',KEY_HOME,\
|
||||
KEY_END,KEY_PAGE_DOWN,'l','z','x','c','v','b', \
|
||||
'n','m',_FN_BRIGHTNESS_DOWN,_FN_BRIGHTNESS_UP,'/','\\',';','\'', \
|
||||
KEY_DELETE,KEY_RETURN,_FN_KEY,_FN_KEY,_FN_LIGHT_KEYBOARD,EMP,EMP,EMP}
|
||||
|
||||
};
|
||||
|
||||
|
||||
static uint8_t fn_actions[MATRIX_KEYS]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
const uint16_t keys_maps[][KEYS_NUM] = {
|
||||
|
||||
[DEF_LAYER] = {KEY_UP_ARROW,KEY_DOWN_ARROW, KEY_LEFT_ARROW,KEY_RIGHT_ARROW, \
|
||||
_JOYSTICK_A,_JOYSTICK_B, _JOYSTICK_X,_JOYSTICK_Y, \
|
||||
_LEFT_SHIFT_KEY,KEY_RIGHT_SHIFT,_LEFT_CTRL_KEY, KEY_RIGHT_CTRL, \
|
||||
_LEFT_ALT, _MOUSE_LEFT, KEY_RIGHT_ALT,_MOUSE_RIGHT, \
|
||||
_TRACKBALL_BTN },
|
||||
|
||||
[FN_LAYER] = {_FN_KEY_UP_ARROW,_FN_KEY_DOWN_ARROW, _FN_KEY_LEFT_ARROW, _FN_KEY_RIGHT_ARROW, \
|
||||
_JOYSTICK_A,_JOYSTICK_B, _JOYSTICK_X,_JOYSTICK_Y, \
|
||||
_LEFT_SHIFT_KEY,KEY_RIGHT_SHIFT,_LEFT_CTRL_KEY, KEY_RIGHT_CTRL, \
|
||||
_CMD_KEY, _MOUSE_LEFT, KEY_RIGHT_ALT,_MOUSE_RIGHT, \
|
||||
_TRACKBALL_BTN },
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
const uint16_t backlight_vals[3] = {0,500,2000};
|
||||
|
||||
uint8_t check_pd2(){ // if swtich 2 in back is set to on(HIGH)
|
||||
|
||||
return digitalRead(PD2);
|
||||
}
|
||||
|
||||
void dt_kbd_set_layer(DEVTERM*dv,uint8_t new_layer) {
|
||||
|
||||
if( dv->Keyboard_state.layer != new_layer) {
|
||||
|
||||
dv->Keyboard_state.prev_layer = dv->Keyboard_state.layer;
|
||||
dv->Keyboard_state.layer = new_layer;
|
||||
}
|
||||
}
|
||||
|
||||
void dt_kbd_restore_layer(DEVTERM*dv) {
|
||||
|
||||
dv->Keyboard_state.layer = dv->Keyboard_state.prev_layer;
|
||||
|
||||
}
|
||||
|
||||
void press_any_key_to_release_lock(DEVTERM*dv, KEYBOARD_LOCK*lock, uint16_t k,uint8_t mode) {
|
||||
|
||||
|
||||
if( lock->lock > 0 ) {
|
||||
if(mode == KEY_RELEASED
|
||||
&& k != _LEFT_CTRL_KEY && k!= KEY_RIGHT_CTRL
|
||||
&& k != _LEFT_ALT && k!= KEY_RIGHT_ALT
|
||||
&& k != _LEFT_SHIFT_KEY && k!= KEY_RIGHT_SHIFT
|
||||
&& k != _FN_KEY) {
|
||||
lock->lock = 0;
|
||||
|
||||
if(lock->begin!= _FN_KEY) {
|
||||
dv->Keyboard->release(lock->begin);
|
||||
}
|
||||
lock->begin = 0;
|
||||
lock->time = 0;
|
||||
//dv->_Serial->println("ctrl lock released");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_action(DEVTERM*dv,uint8_t row,uint8_t col,uint8_t mode) {
|
||||
|
||||
uint16_t k;
|
||||
uint8_t addr;
|
||||
addr = row*MATRIX_COLS+col;
|
||||
if(dv->Keyboard_state.fn_on > 0){
|
||||
k = keyboard_maps[dv->Keyboard_state.fn_on][addr];
|
||||
fn_actions[addr] = 1;
|
||||
}else {
|
||||
k = keyboard_maps[dv->Keyboard_state.layer][addr];
|
||||
}
|
||||
|
||||
if(k == EMP){
|
||||
return;
|
||||
}
|
||||
|
||||
if(k != _FN_KEY && k != _FN_LOCK_KEYBOARD && dv->Keyboard_state.lock == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(k) {
|
||||
case KEY_CAPS_LOCK:
|
||||
if(mode == KEY_PRESSED) {
|
||||
|
||||
dv->Keyboard->press(k);
|
||||
dv->Keyboard->setAdjustForHostCapsLock(true);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
|
||||
dv->Keyboard->setAdjustForHostCapsLock(false);
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case _SELECT_KEY:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = ' ';
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(9,mode);
|
||||
}
|
||||
break;
|
||||
case _START_KEY:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = KEY_RETURN;
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(10,mode);
|
||||
}
|
||||
break;
|
||||
|
||||
case _FN_BRIGHTNESS_UP:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Consumer->press(HIDConsumer::BRIGHTNESS_UP);
|
||||
}else {
|
||||
dv->Consumer->release();
|
||||
}
|
||||
break;
|
||||
case _FN_BRIGHTNESS_DOWN:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Consumer->press(HIDConsumer::BRIGHTNESS_DOWN);
|
||||
}else {
|
||||
dv->Consumer->release();
|
||||
}
|
||||
break;
|
||||
|
||||
case _VOLUME_P:{
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Consumer->press(HIDConsumer::VOLUME_UP);
|
||||
}else {
|
||||
dv->Consumer->release();
|
||||
}
|
||||
}break;
|
||||
case _VOLUME_M:{
|
||||
if(mode == KEY_PRESSED) {
|
||||
if(dv->Keyboard_state.sf_on == 1){
|
||||
dv->Consumer->press(HIDConsumer::VOLUME_UP);
|
||||
}else{
|
||||
dv->Consumer->press(HIDConsumer::VOLUME_DOWN);
|
||||
}
|
||||
}else {
|
||||
dv->Consumer->release();
|
||||
}
|
||||
}break;
|
||||
case _VOLUME_MUTE:{
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Consumer->press(HIDConsumer::MUTE);
|
||||
}else {
|
||||
dv->Consumer->release();
|
||||
}
|
||||
}break;
|
||||
case _FN_LOCK_KEYBOARD:{
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard_state.lock = dv->Keyboard_state.lock ^ 1;
|
||||
}
|
||||
}break;
|
||||
case _FN_LIGHT_KEYBOARD: {
|
||||
//dv->_Serial->println("light keyboard");
|
||||
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard_state.backlight ++;
|
||||
if(dv->Keyboard_state.backlight >= 3) {
|
||||
dv->Keyboard_state.backlight = 0;
|
||||
}
|
||||
timer.resume();
|
||||
pwmWrite(PA8,backlight_vals[ dv->Keyboard_state.backlight ] );
|
||||
}
|
||||
}break;
|
||||
case _FN_KEY:
|
||||
if(mode == KEY_PRESSED){
|
||||
if(dv->Keyboard_state.fn.lock == 0){
|
||||
dv->Keyboard_state.fn_on = FN_LAYER;
|
||||
dv->Keyboard_state.fn.begin = k;
|
||||
}
|
||||
}else if(mode == KEY_RELEASED ) {
|
||||
if(dv->Keyboard_state.fn.lock == 0){
|
||||
for(int i=0;i<64;i++) {
|
||||
if(fn_actions[i] !=0) {
|
||||
k = keyboard_maps[dv->Keyboard_state.fn_on][i];
|
||||
dv->Keyboard->release(k);
|
||||
fn_actions[i] = 0;
|
||||
}
|
||||
}
|
||||
dv->Keyboard_state.fn_on = 0;
|
||||
}
|
||||
|
||||
dv->Keyboard_state.fn.begin = 0;
|
||||
dv->Keyboard_state.fn.time = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
|
||||
if(dv->Keyboard_state.fn_on > 0){
|
||||
fn_actions[addr] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.ctrl,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.alt,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.shift,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.fn,k,mode);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void keypad_action(DEVTERM*dv,uint8_t col,uint8_t mode) {
|
||||
|
||||
uint16_t k;
|
||||
|
||||
if(dv->Keyboard_state.fn_on > 0){
|
||||
k = keys_maps[dv->Keyboard_state.fn_on][col];
|
||||
}else {
|
||||
k = keys_maps[dv->Keyboard_state.layer][col];
|
||||
}
|
||||
|
||||
if(k == EMP){
|
||||
return;
|
||||
}
|
||||
|
||||
if(dv->Keyboard_state.lock == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(k) {
|
||||
case _LEFT_SHIFT_KEY:
|
||||
case KEY_RIGHT_SHIFT:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard_state.sf_on = 1;
|
||||
if(dv->Keyboard_state.shift.lock == 0){
|
||||
dv->Keyboard->press(k);
|
||||
dv->Keyboard_state.shift.begin=k;
|
||||
}
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard_state.sf_on = 0;
|
||||
if(dv->Keyboard_state.shift.lock == 0){
|
||||
dv->Keyboard->release(k);
|
||||
dv->Keyboard_state.shift.begin = 0;
|
||||
dv->Keyboard_state.shift.time = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case _JOYSTICK_UP:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = KEY_UP_ARROW;
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
if(mode == KEY_RELEASED){
|
||||
dv->Joystick->Y(511);
|
||||
}else {
|
||||
dv->Joystick->Y(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_DOWN:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = KEY_DOWN_ARROW;
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
if(mode == KEY_RELEASED){
|
||||
dv->Joystick->Y(511);
|
||||
}else {
|
||||
dv->Joystick->Y(1023);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_LEFT:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = KEY_LEFT_ARROW;
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
if(mode == KEY_RELEASED){
|
||||
dv->Joystick->X(511);
|
||||
}else {
|
||||
dv->Joystick->X(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_RIGHT:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = KEY_RIGHT_ARROW;
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
if(mode == KEY_RELEASED){
|
||||
dv->Joystick->X(511);
|
||||
}else {
|
||||
dv->Joystick->X(1023);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_A:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = 'j';
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(2,mode);
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_B:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = 'k';
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(3,mode);
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_X:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = 'u';
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(1,mode);
|
||||
}
|
||||
break;
|
||||
case _JOYSTICK_Y:
|
||||
if(check_pd2() == HIGH) {
|
||||
k = 'i';
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
}else {
|
||||
dv->Joystick->button(4,mode);
|
||||
}
|
||||
break;
|
||||
case _MOUSE_LEFT:
|
||||
if(mode == KEY_PRESSED){
|
||||
dv->Mouse->press(1);
|
||||
}else if(mode == KEY_RELEASED){
|
||||
dv->Mouse->release(1);
|
||||
}
|
||||
break;
|
||||
case _MOUSE_MID:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->state->pressMiddleClick();
|
||||
}else {
|
||||
if(dv->state->getScrolled() == false){
|
||||
//if no scrolling happend ,do as a normal mid mouse key click
|
||||
dv->Mouse->click(MOUSE_MIDDLE);
|
||||
}
|
||||
dv->state->releaseMiddleClick();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case _MOUSE_RIGHT:
|
||||
if(mode == KEY_PRESSED){
|
||||
dv->Mouse->press(2);
|
||||
}else if(mode == KEY_RELEASED){
|
||||
dv->Mouse->release(2);
|
||||
}
|
||||
break;
|
||||
|
||||
//_LEFT_CTRL_KEY,_CMD_KEY , _LEFT_ALT
|
||||
case _LEFT_CTRL_KEY:
|
||||
case KEY_RIGHT_CTRL:
|
||||
if(mode == KEY_PRESSED){
|
||||
if(dv->Keyboard_state.ctrl.lock == 0){
|
||||
dv->Keyboard->press(k);
|
||||
dv->Keyboard_state.ctrl.begin = k;
|
||||
}
|
||||
}else {
|
||||
if(dv->Keyboard_state.ctrl.lock == 0){
|
||||
dv->Keyboard->release(k);
|
||||
dv->Keyboard_state.ctrl.begin = 0;
|
||||
dv->Keyboard_state.ctrl.time = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case _LEFT_ALT:
|
||||
case KEY_RIGHT_ALT:
|
||||
if(mode == KEY_PRESSED){
|
||||
if(dv->Keyboard_state.alt.lock == 0){
|
||||
dv->Keyboard->press(k);
|
||||
dv->Keyboard_state.alt.begin=k;
|
||||
}
|
||||
}else {
|
||||
if(dv->Keyboard_state.alt.lock == 0){
|
||||
dv->Keyboard->release(k);
|
||||
dv->Keyboard_state.alt.begin = 0;
|
||||
dv->Keyboard_state.alt.time = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case _CMD_KEY:
|
||||
if(mode == KEY_PRESSED){
|
||||
dv->Keyboard->press(k);
|
||||
}else {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
break;
|
||||
|
||||
case _TRACKBALL_BTN:
|
||||
if(mode == KEY_PRESSED){
|
||||
dv->Mouse->press(MOUSE_MIDDLE);
|
||||
}else if(mode == KEY_RELEASED){
|
||||
dv->Mouse->release(MOUSE_MIDDLE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(mode == KEY_PRESSED) {
|
||||
dv->Keyboard->press(k);
|
||||
}else if(mode == KEY_RELEASED) {
|
||||
dv->Keyboard->release(k);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
/*
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.ctrl,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.alt,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.shift,k,mode);
|
||||
press_any_key_to_release_lock(dv,&dv->Keyboard_state.fn,k,mode);
|
||||
*/
|
||||
}
|
||||
27
Code/uconsole_keyboard/keys.h
Normal file
27
Code/uconsole_keyboard/keys.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef KEYS_H
|
||||
#define KEYS_H
|
||||
/*
|
||||
* keys include the joystick and mouse left/mid/right keys
|
||||
*/
|
||||
|
||||
#include "devterm.h"
|
||||
#include "keys_io_map.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifndef KEY_DEBOUNCE
|
||||
# define KEY_DEBOUNCE 5
|
||||
#endif
|
||||
|
||||
#define KEYS_NUM 17
|
||||
|
||||
|
||||
void keys_task(DEVTERM*);
|
||||
void keys_init(DEVTERM*);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
106
Code/uconsole_keyboard/keys.ino
Normal file
106
Code/uconsole_keyboard/keys.ino
Normal file
@ -0,0 +1,106 @@
|
||||
#include "keys.h"
|
||||
|
||||
KEY_DEB keypad_debouncing;
|
||||
|
||||
uint8_t keys_io[ KEYS_NUM ]= {KEY1,KEY2,KEY3,KEY4,KEY5,KEY6,KEY7,KEY8,KEY9,KEY10,KEY11,KEY12,KEY13,KEY14,KEY15,KEY16,KEY0};
|
||||
|
||||
/* keys state(1:on, 0:off) */
|
||||
static uint32_t keys;
|
||||
static uint32_t keys_debouncing;
|
||||
static uint32_t keys_prev;
|
||||
|
||||
void init_keys(){
|
||||
int i;
|
||||
for(i=0;i<KEYS_NUM;i++) {
|
||||
|
||||
pinMode( keys_io[i],INPUT_PULLUP);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t scan_keys(){
|
||||
uint32_t data;
|
||||
uint8_t s;
|
||||
|
||||
data = 0;
|
||||
delayMicroseconds(30);
|
||||
for(int i = 0;i < KEYS_NUM;i++) {
|
||||
|
||||
s = read_io(keys_io[i]);
|
||||
s ^= 1;
|
||||
|
||||
data |= s << i;
|
||||
|
||||
}
|
||||
|
||||
if ( keys_debouncing != data ) {
|
||||
keys_debouncing = data;
|
||||
|
||||
keypad_debouncing.deing = true;
|
||||
keypad_debouncing.de_time = millis();
|
||||
|
||||
}
|
||||
|
||||
if (keypad_debouncing.deing == true && ( (millis() - keypad_debouncing.de_time) > KEY_DEBOUNCE )) {
|
||||
keys = keys_debouncing;
|
||||
keypad_debouncing.deing = false;
|
||||
}else {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void print_keys(DEVTERM*dv) {
|
||||
char buff[128];
|
||||
|
||||
for (int i = 0; i < KEYS_NUM; i++) {
|
||||
if( keys & (1<< i) ){
|
||||
sprintf(buff,"B%d pressed\n",i+1);
|
||||
dv->_Serial->print(buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void keys_task(DEVTERM*dv){
|
||||
|
||||
scan_keys();
|
||||
|
||||
uint32_t _mask =1;
|
||||
uint32_t _change = 0;
|
||||
uint32_t _pressed = 0;
|
||||
|
||||
_change = keys ^ keys_prev;
|
||||
|
||||
if(_change) {
|
||||
|
||||
for(uint8_t c=0;c < KEYS_NUM;c++,_mask <<=1) {
|
||||
if (_change & _mask) {
|
||||
_pressed = keys & _mask;
|
||||
if(_pressed) {
|
||||
keypad_action(dv,c,KEY_PRESSED);
|
||||
}else {
|
||||
keypad_action(dv,c,KEY_RELEASED);
|
||||
}
|
||||
|
||||
keys_prev ^= _mask;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void keys_init(DEVTERM*dv){
|
||||
|
||||
init_keys();
|
||||
//center the position
|
||||
dv->Joystick->X(511);
|
||||
dv->Joystick->Y(511);
|
||||
|
||||
keypad_debouncing.deing = false;
|
||||
keypad_debouncing.de_time = 0;
|
||||
|
||||
}
|
||||
49
Code/uconsole_keyboard/keys_io_map.h
Normal file
49
Code/uconsole_keyboard/keys_io_map.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef KEYS_IO_MAP_H
|
||||
#define KEYS_IO_MAP_H
|
||||
|
||||
#define ROW1 PA0
|
||||
#define ROW2 PA1
|
||||
#define ROW3 PA2
|
||||
#define ROW4 PA3
|
||||
#define ROW5 PA4
|
||||
#define ROW6 PA5
|
||||
#define ROW7 PA6
|
||||
#define ROW8 PA7
|
||||
|
||||
#define COL1 PC0
|
||||
#define COL2 PC1
|
||||
#define COL3 PC2
|
||||
#define COL4 PC3
|
||||
#define COL5 PC4
|
||||
#define COL6 PC5
|
||||
#define COL7 PC6
|
||||
#define COL8 PC7
|
||||
|
||||
#define KEY1 PB0 //
|
||||
#define KEY2 PB1
|
||||
#define KEY3 PB2
|
||||
#define KEY4 PB3
|
||||
#define KEY5 PB4
|
||||
#define KEY6 PB5
|
||||
#define KEY7 PB6
|
||||
#define KEY8 PB7
|
||||
#define KEY9 PB8
|
||||
#define KEY10 PB9
|
||||
#define KEY11 PB10
|
||||
#define KEY12 PB11
|
||||
#define KEY13 PB12
|
||||
#define KEY14 PB13
|
||||
#define KEY15 PB14
|
||||
#define KEY16 PB15 //
|
||||
|
||||
//ball
|
||||
#define HO1 PC8
|
||||
#define HO2 PC9
|
||||
#define HO3 PC10
|
||||
#define HO4 PC11
|
||||
#define KEY0 PC12
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
56
Code/uconsole_keyboard/math.h
Normal file
56
Code/uconsole_keyboard/math.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef MATH_H
|
||||
#define MATH_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
uint32_t getDelta(uint32_t prev, uint32_t now);
|
||||
uint32_t getDelta(uint32_t prev, uint32_t now, uint32_t max);
|
||||
|
||||
template<typename T>
|
||||
T sign(T value) {
|
||||
if (value > 0) {
|
||||
return 1;
|
||||
}
|
||||
if (value < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
T clamp(U value) {
|
||||
if (value >= std::numeric_limits<T>().max()) {
|
||||
return std::numeric_limits<T>().max();
|
||||
}
|
||||
|
||||
if (value <= std::numeric_limits<T>().min()) {
|
||||
return std::numeric_limits<T>().min();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T min(T x, T y) {
|
||||
if (x < y) {
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T max(T x, T y) {
|
||||
if (x > y) {
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T hypot(T x, T y) {
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
#endif
|
||||
23
Code/uconsole_keyboard/math.ino
Normal file
23
Code/uconsole_keyboard/math.ino
Normal file
@ -0,0 +1,23 @@
|
||||
#include <limits>
|
||||
|
||||
#include "math.h"
|
||||
|
||||
uint32_t getDelta(uint32_t prev, uint32_t now) {
|
||||
uint32_t delta;
|
||||
if (now >= prev) {
|
||||
delta = now - prev;
|
||||
} else {
|
||||
delta = std::numeric_limits<uint32_t>().max() - prev - now + 1;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
uint32_t getDelta(uint32_t prev, uint32_t now, uint32_t max) {
|
||||
const auto delta = getDelta(prev, now);
|
||||
|
||||
if (delta < max) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
38
Code/uconsole_keyboard/ratemeter.h
Normal file
38
Code/uconsole_keyboard/ratemeter.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef RATEMETER_H
|
||||
#define RATEMETER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "debouncer.h"
|
||||
|
||||
class RateMeter {
|
||||
public:
|
||||
RateMeter();
|
||||
void onInterrupt();
|
||||
void tick(millis_t delta);
|
||||
void expire();
|
||||
|
||||
uint16_t delta() const;
|
||||
// Hall sensor edges per seconds.
|
||||
// stopped: 0
|
||||
// really slow => ~3
|
||||
// medium => ~30
|
||||
// fast => < 300
|
||||
// max => 1000
|
||||
float rate() const;
|
||||
|
||||
private:
|
||||
uint32_t lastTime;
|
||||
|
||||
// really Range, emperically:
|
||||
// fast => < 5_000 us,
|
||||
// medium => 20_000 - 40_000 us
|
||||
// really slow => 250_000 us
|
||||
uint32_t averageDelta;
|
||||
|
||||
static const uint16_t CUTOFF_MS = 1000;
|
||||
// Cut off after some seconds to prevent multiple timestamp overflow (~70 mins)
|
||||
Timeout<uint16_t, CUTOFF_MS> cutoff;
|
||||
};
|
||||
|
||||
#endif
|
||||
47
Code/uconsole_keyboard/ratemeter.ino
Normal file
47
Code/uconsole_keyboard/ratemeter.ino
Normal file
@ -0,0 +1,47 @@
|
||||
#include <Arduino.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include "ratemeter.h"
|
||||
#include "math.h"
|
||||
|
||||
RateMeter::RateMeter()
|
||||
: lastTime(0)
|
||||
{}
|
||||
|
||||
void RateMeter::onInterrupt() {
|
||||
const auto now = millis();
|
||||
if (cutoff.get()) {
|
||||
averageDelta = CUTOFF_MS;
|
||||
} else {
|
||||
const auto delta = getDelta(lastTime, now, CUTOFF_MS);
|
||||
averageDelta = (averageDelta + delta) / 2;
|
||||
}
|
||||
lastTime = now;
|
||||
cutoff.reset();
|
||||
}
|
||||
|
||||
void RateMeter::tick(millis_t delta) {
|
||||
cutoff.updateTime(delta);
|
||||
if (!cutoff.get()) {
|
||||
averageDelta += delta;
|
||||
}
|
||||
}
|
||||
|
||||
void RateMeter::expire() {
|
||||
cutoff.expire();
|
||||
}
|
||||
|
||||
uint16_t RateMeter::delta() const {
|
||||
return averageDelta;
|
||||
}
|
||||
|
||||
float RateMeter::rate() const {
|
||||
if (cutoff.get()) {
|
||||
return 0.0f;
|
||||
} else if (averageDelta == 0) {
|
||||
// to ensure range 0 ~ 1000.0
|
||||
return 1000.0f;
|
||||
} else {
|
||||
return 1000.0f / (float)averageDelta;
|
||||
}
|
||||
}
|
||||
37
Code/uconsole_keyboard/state.h
Normal file
37
Code/uconsole_keyboard/state.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef STATE_H
|
||||
#define STATE_H
|
||||
|
||||
#include <bitset>
|
||||
#include <array>
|
||||
#include <USBComposite.h>
|
||||
|
||||
#include "debouncer.h"
|
||||
|
||||
enum class TrackballMode : uint8_t {
|
||||
Wheel,
|
||||
Mouse,
|
||||
};
|
||||
|
||||
class State
|
||||
{
|
||||
public:
|
||||
static const uint16_t MIDDLE_CLICK_TIMEOUT_MS = 0;
|
||||
|
||||
State();
|
||||
|
||||
void tick(uint8_t delta);
|
||||
|
||||
bool fn;
|
||||
|
||||
void pressMiddleClick();
|
||||
bool releaseMiddleClick();
|
||||
bool getScrolled();
|
||||
void setScrolled();
|
||||
TrackballMode moveTrackball();
|
||||
private:
|
||||
bool middleClick;
|
||||
bool scrolled;
|
||||
Timeout<uint16_t, MIDDLE_CLICK_TIMEOUT_MS> middleClickTimeout;
|
||||
};
|
||||
|
||||
#endif
|
||||
47
Code/uconsole_keyboard/state.ino
Normal file
47
Code/uconsole_keyboard/state.ino
Normal file
@ -0,0 +1,47 @@
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "state.h"
|
||||
|
||||
State::State()
|
||||
: fn(false),
|
||||
middleClick(false),
|
||||
scrolled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void State::tick(millis_t delta)
|
||||
{
|
||||
middleClickTimeout.updateTime(delta);
|
||||
}
|
||||
void State::setScrolled() {
|
||||
if(middleClick==true){
|
||||
scrolled = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool State::getScrolled() {
|
||||
return scrolled;
|
||||
}
|
||||
|
||||
void State::pressMiddleClick() {
|
||||
middleClick = true;
|
||||
middleClickTimeout.reset();
|
||||
}
|
||||
|
||||
bool State::releaseMiddleClick() {
|
||||
middleClick = false;
|
||||
scrolled = false;
|
||||
const auto timeout = middleClickTimeout.get();
|
||||
return !timeout;
|
||||
}
|
||||
|
||||
TrackballMode State::moveTrackball() {
|
||||
middleClickTimeout.expire();
|
||||
if (middleClick) {
|
||||
return TrackballMode::Wheel;
|
||||
} else {
|
||||
return TrackballMode::Mouse;
|
||||
}
|
||||
}
|
||||
30
Code/uconsole_keyboard/tickwaiter.h
Normal file
30
Code/uconsole_keyboard/tickwaiter.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef TICKWAITER_H
|
||||
#define TICKWAITER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "math.h"
|
||||
|
||||
template<uint32_t TargetInterval>
|
||||
class TickWaiter {
|
||||
public:
|
||||
uint8_t waitForNextTick() {
|
||||
const auto last = this->last;
|
||||
const auto now = millis();
|
||||
this->last = now;
|
||||
|
||||
const auto delta = getDelta(last, now, 255);
|
||||
|
||||
if (delta >= TargetInterval) {
|
||||
return delta;
|
||||
}
|
||||
|
||||
delay(TargetInterval - delta);
|
||||
|
||||
const auto now2 = millis();
|
||||
return getDelta(last, now2, 255);
|
||||
}
|
||||
private:
|
||||
uint32_t last = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
25
Code/uconsole_keyboard/trackball.h
Normal file
25
Code/uconsole_keyboard/trackball.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef TRACKBALL_H
|
||||
#define TRACKBALL_H
|
||||
|
||||
#include "devterm.h"
|
||||
|
||||
#include "keys_io_map.h"
|
||||
|
||||
/*
|
||||
#define BOUNCE_INTERVAL 30
|
||||
#define BASE_MOVE_PIXELS 5
|
||||
#define EXPONENTIAL_BOUND 15
|
||||
#define EXPONENTIAL_BASE 1.2
|
||||
*/
|
||||
|
||||
#define RIGHT_PIN HO2
|
||||
#define LEFT_PIN HO4
|
||||
#define DOWN_PIN HO3
|
||||
#define UP_PIN HO1
|
||||
|
||||
|
||||
void trackball_init(DEVTERM*);
|
||||
void trackball_task(DEVTERM*);
|
||||
|
||||
|
||||
#endif
|
||||
130
Code/uconsole_keyboard/trackball.ino
Normal file
130
Code/uconsole_keyboard/trackball.ino
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* clockworkpi devterm trackball
|
||||
*/
|
||||
#include "keys_io_map.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <USBComposite.h>
|
||||
|
||||
|
||||
#include "trackball.h"
|
||||
|
||||
#include "ratemeter.h"
|
||||
#include "glider.h"
|
||||
#include "math.h"
|
||||
|
||||
|
||||
|
||||
enum Axis: uint8_t {
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
AXIS_NUM,
|
||||
};
|
||||
static TrackballMode lastMode;
|
||||
static int8_t distances[AXIS_NUM];
|
||||
static RateMeter rateMeter[AXIS_NUM];
|
||||
static Glider glider[AXIS_NUM];
|
||||
|
||||
static const int8_t WHEEL_DENOM = 2;
|
||||
static int8_t wheelBuffer;
|
||||
|
||||
static float rateToVelocityCurve(float input) {
|
||||
//return std::pow(std::abs(input) / 50, 1.4);
|
||||
return std::abs(input) / 30;
|
||||
}
|
||||
|
||||
template<Axis AXIS, int8_t Direction >
|
||||
static void interrupt( ) {
|
||||
distances[AXIS] += Direction;
|
||||
rateMeter[AXIS].onInterrupt();
|
||||
glider[AXIS].setDirection(Direction);
|
||||
|
||||
const auto rx = rateMeter[AXIS_X].rate();
|
||||
const auto ry = rateMeter[AXIS_Y].rate();
|
||||
|
||||
const auto rate = std::sqrt(rx * rx + ry * ry);
|
||||
const auto ratio = rateToVelocityCurve(rate) / rate;
|
||||
|
||||
const auto vx = rx * ratio;
|
||||
const auto vy = ry * ratio;
|
||||
|
||||
if (AXIS == AXIS_X) {
|
||||
glider[AXIS_X].update(vx, std::sqrt(rateMeter[AXIS_X].delta()));
|
||||
glider[AXIS_Y].updateSpeed(vy);
|
||||
|
||||
} else {
|
||||
glider[AXIS_X].updateSpeed(vx);
|
||||
glider[AXIS_Y].update(vy, std::sqrt(rateMeter[AXIS_Y].delta()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void trackball_task(DEVTERM*dv) {
|
||||
int8_t x = 0, y = 0, w = 0;
|
||||
noInterrupts();
|
||||
const auto mode = dv->state->moveTrackball();
|
||||
if (lastMode != mode) {
|
||||
rateMeter[AXIS_X].expire();
|
||||
rateMeter[AXIS_Y].expire();
|
||||
wheelBuffer = 0;
|
||||
}
|
||||
else {
|
||||
rateMeter[AXIS_X].tick(dv->delta);
|
||||
rateMeter[AXIS_Y].tick(dv->delta);
|
||||
}
|
||||
lastMode = mode;
|
||||
|
||||
switch(mode){
|
||||
case TrackballMode::Mouse: {
|
||||
const auto rX = glider[AXIS_X].glide(dv->delta);
|
||||
const auto rY = glider[AXIS_Y].glide(dv->delta);
|
||||
x = rX.value;
|
||||
y = rY.value;
|
||||
if (rX.stopped) {
|
||||
glider[AXIS_Y].stop();
|
||||
}
|
||||
if (rY.stopped) {
|
||||
glider[AXIS_Y].stop();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TrackballMode::Wheel: {
|
||||
wheelBuffer += distances[AXIS_Y];
|
||||
w = wheelBuffer / WHEEL_DENOM;
|
||||
wheelBuffer -= w * WHEEL_DENOM;
|
||||
if(w != 0){
|
||||
dv->state->setScrolled();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
distances[AXIS_X] = 0;
|
||||
distances[AXIS_Y] = 0;
|
||||
interrupts();
|
||||
|
||||
if(x !=0 || y != 0 || -w!=0) {
|
||||
dv->Mouse->move(x, y, -w);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void trackball_init(DEVTERM*dv){
|
||||
|
||||
pinMode(LEFT_PIN, INPUT);
|
||||
pinMode(UP_PIN, INPUT);
|
||||
pinMode(RIGHT_PIN, INPUT);
|
||||
pinMode(DOWN_PIN, INPUT);
|
||||
|
||||
attachInterrupt(LEFT_PIN, &interrupt<AXIS_X,-1> , ExtIntTriggerMode::CHANGE);
|
||||
attachInterrupt(RIGHT_PIN, &interrupt<AXIS_X, 1>, ExtIntTriggerMode::CHANGE);
|
||||
attachInterrupt(UP_PIN, &interrupt<AXIS_Y, -1>, ExtIntTriggerMode::CHANGE);
|
||||
attachInterrupt(DOWN_PIN, &interrupt<AXIS_Y, 1>, ExtIntTriggerMode::CHANGE);
|
||||
|
||||
}
|
||||
139
Code/uconsole_keyboard/uconsole_keyboard.ino
Normal file
139
Code/uconsole_keyboard/uconsole_keyboard.ino
Normal file
@ -0,0 +1,139 @@
|
||||
#include "keyboard.h"
|
||||
#include "keys.h"
|
||||
#include "trackball.h"
|
||||
#include "devterm.h"
|
||||
#include "tickwaiter.h"
|
||||
|
||||
#include <USBComposite.h>
|
||||
|
||||
#define SER_NUM_STR "20230307"
|
||||
|
||||
USBHID HID;
|
||||
DEVTERM dev_term;
|
||||
|
||||
const uint8_t reportDescription[] = {
|
||||
HID_CONSUMER_REPORT_DESCRIPTOR(),
|
||||
HID_KEYBOARD_REPORT_DESCRIPTOR(),
|
||||
HID_JOYSTICK_REPORT_DESCRIPTOR(),
|
||||
HID_MOUSE_REPORT_DESCRIPTOR()
|
||||
};
|
||||
|
||||
static const uint32_t LOOP_INTERVAL_MS = 0;
|
||||
static TickWaiter<LOOP_INTERVAL_MS> waiter;
|
||||
|
||||
HardwareTimer timer(1);
|
||||
//HardwareTimer ctrl_timer(4);
|
||||
|
||||
void setup() {
|
||||
USBComposite.setManufacturerString("ClockworkPI");
|
||||
USBComposite.setProductString("uConsole");
|
||||
USBComposite.setSerialString(SER_NUM_STR);
|
||||
|
||||
dev_term.Keyboard = new HIDKeyboard(HID);
|
||||
dev_term.Joystick = new HIDJoystick(HID);
|
||||
dev_term.Mouse = new HIDMouse(HID);
|
||||
dev_term.Consumer = new HIDConsumer(HID);
|
||||
|
||||
dev_term.Keyboard->setAdjustForHostCapsLock(false);
|
||||
|
||||
dev_term.state = new State();
|
||||
|
||||
dev_term.Keyboard_state.layer = 0;
|
||||
dev_term.Keyboard_state.prev_layer = 0;
|
||||
dev_term.Keyboard_state.fn_on = 0;
|
||||
dev_term.Keyboard_state.sf_on = 0;
|
||||
|
||||
//dev_term.Keyboard_state.shift = 0;
|
||||
dev_term.Keyboard_state.backlight = 0;
|
||||
dev_term.Keyboard_state.lock = 0;
|
||||
|
||||
dev_term.Keyboard_state.ctrl.lock = 0;
|
||||
dev_term.Keyboard_state.ctrl.time = 0;
|
||||
dev_term.Keyboard_state.ctrl.begin = 0;
|
||||
|
||||
dev_term.Keyboard_state.shift.lock = 0;
|
||||
dev_term.Keyboard_state.shift.time = 0;
|
||||
dev_term.Keyboard_state.shift.begin = 0;
|
||||
|
||||
dev_term.Keyboard_state.alt.lock = 0;
|
||||
dev_term.Keyboard_state.alt.time = 0;
|
||||
dev_term.Keyboard_state.alt.begin = 0;
|
||||
|
||||
dev_term.Keyboard_state.fn.lock = 0;
|
||||
dev_term.Keyboard_state.fn.time = 0;
|
||||
dev_term.Keyboard_state.fn.begin = 0;
|
||||
|
||||
dev_term._Serial = new USBCompositeSerial;
|
||||
|
||||
HID.begin(*dev_term._Serial,reportDescription, sizeof(reportDescription));
|
||||
|
||||
while(!USBComposite);//wait until usb port been plugged in to PC
|
||||
|
||||
|
||||
keyboard_init(&dev_term);
|
||||
keys_init(&dev_term);
|
||||
trackball_init(&dev_term);
|
||||
|
||||
//dev_term._Serial->println("setup done");
|
||||
|
||||
pinMode(PD2,INPUT);// switch 2 in back
|
||||
|
||||
timer.setPeriod(KEYBOARD_LED_PWM_PERIOD);
|
||||
timer.resume();
|
||||
|
||||
/*
|
||||
ctrl_timer.setPeriod(20*1000);
|
||||
ctrl_timer.attachInterrupt(1,ctrl_timer_handler);
|
||||
ctrl_timer.refresh();
|
||||
ctrl_timer.resume();
|
||||
*/
|
||||
pinMode(PA8,PWM);
|
||||
pwmWrite(PA8,0);
|
||||
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
#define LOCK_TIME 50
|
||||
|
||||
//DO NOT USE dev_term._Serial->println(""); in timer interrupt function,will block
|
||||
void check_keyboard_lock(KEYBOARD_LOCK*lock){
|
||||
if( lock->begin >0) {
|
||||
lock->time++;
|
||||
|
||||
if( lock->time>=LOCK_TIME && lock->time<200){
|
||||
lock->lock = 1;
|
||||
}
|
||||
|
||||
if( lock->time > 200){
|
||||
if(lock->begin != _FN_KEY) {
|
||||
dev_term.Keyboard->release(lock->begin);
|
||||
}
|
||||
lock->time = 0;
|
||||
lock->lock = 0;
|
||||
lock->begin = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LOCK_TIME 50
|
||||
void ctrl_timer_handler(void) {
|
||||
|
||||
check_keyboard_lock(&dev_term.Keyboard_state.ctrl);
|
||||
check_keyboard_lock(&dev_term.Keyboard_state.shift);
|
||||
check_keyboard_lock(&dev_term.Keyboard_state.alt);
|
||||
check_keyboard_lock(&dev_term.Keyboard_state.fn);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
dev_term.delta = waiter.waitForNextTick();
|
||||
dev_term.state->tick(dev_term.delta);
|
||||
|
||||
trackball_task(&dev_term);
|
||||
|
||||
keys_task(&dev_term); //keys above keyboard
|
||||
keyboard_task(&dev_term);
|
||||
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user