This project began with the purchase of a compact USB keyboard with three keys from AliExpress, seemingly without any specific purpose in mind. The original software required for this keyboard was provided as a .exe file, which I downloaded from a Google Drive repository. However, since I don't have access to a Windows PC to test it, I'm quite certain that most antivirus software would not approve of it.
I decided to open it and try to program it myself.
Change keyboard config rotating the encoder while is pressed
The core of the board features a wch-ic CH552G microcontroller, three buttons, a rotary encoder, and three addressable LEDs.
This firmware uses the Arduino platform to simplify the build process. I built it on a MacBook Pro with an M1 chip.
ch552g_mini_keyboard.ino
.
To enter bootloader mode, CH552G require connect pin P3.6 to vcc with a 10K pull-up resistor. To do this:
// Go in bootloader more if connected with encoder button pressed
if (!digitalRead(PIN_BTN_ENC))
{
NEO_writeHue(0, NEO_CYAN, NEO_BRIGHT_KEYS); // set led1 to cyan
NEO_writeHue(1, NEO_BLUE, NEO_BRIGHT_KEYS); // set led2 to blue
NEO_writeHue(2, NEO_MAG, NEO_BRIGHT_KEYS); // set led3 to magenta
NEO_update(); // update pixels
BOOT_now(); // jump to bootloader
}
This firmware as can setup keyboard in different configuration. Edit configuration.cpp to change it To change configuration keep press rotary encoder and change configuration.
On configurtion is possible to send keyboard or mous event and setup automatic cycle rutine
Current configuration
const keyboard_configuration_t configurations[NUM_CONFIGURATION] = {
{
.button = { // Configuration copy paste keyboard
[BTN_1] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {KEY_LEFT_CTRL, 'c'}, // ctrl + c
.length = 2, // Lengh of sequence
.delay = 0 // no delay
}
},
[BTN_2] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {KEY_LEFT_CTRL, 'v'}, // ctrl + v
.length = 2, // Lengh of sequence
.delay = 0 // no delay
}
},
[BTN_3] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {KEY_LEFT_CTRL, 'z'}, // ctrl + z
.length = 2, // Lengh of sequence
.delay = 0 // no delay
}
},
[ENC_CW] = { // scroll up
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_DOWN,
.value = 2
}
},
.length = 1,
.delay = 0,
.keypress = 0 // Valore della pressione del tasto del mouse
}
},
[ENC_CCW] = { // scroll down
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_UP,
.value = 2
}
},
.length = 1,
.delay = 0,
.keypress = 0 // Valore della pressione del tasto del mouse
}
},
[BTN_ENC] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = keyboard_press_enc,
},
}
},
{ // Configuration photoshop
.button = { //
[BTN_1] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {'e'}, // e
.length = 1, // Lengh of sequence
.delay = 0 // no delay
}
},
[BTN_2] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {'s'}, // s
.length = 1, // Lengh of sequence
.delay = 0 // no delay
}
},
[BTN_3] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = LEFT_CLICK,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[ENC_CW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_UP,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[ENC_CCW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_DOWN,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[BTN_ENC] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = keyboard_press_enc,
},
}
},
{ // Configuration game
.button = { //
[BTN_1] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {'a','a','a','a'}, // multi a
.length = 4, // Lengh of sequence
.delay = 50 // no delay
}
},
[BTN_2] = {
.type = BUTTON_SEQUENCE,
.function.sequence = {
.sequence = {'b','b','b','b','b','b','b','b'}, // multi b
.length = 8, // Lengh of sequence
.delay = 50 // no delay
}
},
[BTN_3] = {
.type = BUTTON_MOUSE,
.function.mouse = { //multi click
.mouse_event_sequence = {
{
.type = LEFT_CLICK,
.value = 1
},
{
.type = LEFT_CLICK,
.value = 1
},
{
.type = LEFT_CLICK,
.value = 1
},
{
.type = LEFT_CLICK,
.value = 1
},
{
.type = LEFT_CLICK,
.value = 1
}
},
.length = 5,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[ENC_CW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_UP,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[ENC_CCW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_DOWN,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = KEY_LEFT_ALT // Valore della pressione del tasto del mouse
}
},
[BTN_ENC] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = keyboard_press_enc,
},
}
},
{ // Automatic keyboard
.button = { //
[BTN_1] = {
.type = BUTTON_AUTO_KEYBOARD,
.function.sequence = {
.sequence = {'#', 'i', 'n', 'c', 'l', 'u', 'd', 'e', ' ', '<', 's', 't', 'd', 'i', 'o', '.', 'h', '>', '\n', '\n', 'i', 'n', 't', ' ', 'm', 'a', 'i', 'n', '(', ')', '\n', '{', '\n', ' ', ' ', ' ', 'p', 'r', 'i', 'n', 't', 'f', '(', '"', 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '"', ')', ';', '\n', '\n', ' ', ' ', ' ', 'r', 'e', 't', 'u', 'r', 'n', ' ', '0', ';', '\n', '}', '\n'}, // multi a
.length = 73, // Lengh of sequence
.delay = 50 // no delay
}
},
[BTN_2] = {
.type = BUTTON_AUTO_MOUSE,
.function.mouse = { //multi click
.mouse_event_sequence = {
{
.type = UP,
.value = 40
},
{
.type = RIGH,
.value = 40
},
{
.type = DOWN,
.value = 40
},
{
.type = LEFT,
.value = 40
}
},
.length = 4,
.delay = 50,
.keypress = 0 // Valore della pressione del tasto del mouse
}
},
[BTN_3] = {
.type = BUTTON_NULL,
},
[ENC_CW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_UP,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = 0 // Valore della pressione del tasto del mouse
}
},
[ENC_CCW] = {
.type = BUTTON_MOUSE,
.function.mouse = {
.mouse_event_sequence = {
{
.type = SCROLL_DOWN,
.value = 1
}
},
.length = 1,
.delay = 0,
.keypress = 0 // Valore della pressione del tasto del mouse
}
},
[BTN_ENC] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = keyboard_press_enc,
},
}
},
{ //Menu configuration
.button = { // Configurtion copy paste keyboard
[BTN_1] = {
.type = BUTTON_NULL,
},
[BTN_2] = {
.type = BUTTON_NULL,
},
[BTN_3] = {
.type = BUTTON_NULL,
},
[ENC_CW] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = button_menu_up,
},
[ENC_CCW] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = button_menu_down,
},
[BTN_ENC] = {
.type = BUTTON_FUNCTION,
.function.functionPointer = keyboard_press_enc,
},
}
},
};
Here are the resources I used for reprogramming the firmware:
This work is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License. (http://creativecommons.org/licenses/by-sa/3.0/)