From 0551403788f6a9a029daf63669a91df3b2132bb3 Mon Sep 17 00:00:00 2001 From: klaute Date: Sat, 17 Sep 2016 19:02:36 +0200 Subject: [PATCH] N3rdpad based command control manager implementation added. --- command_config.h | 110 +++++++++++++++++++++++++++ command_ctrl.c | 146 ++++++++++++++++++++++++++++++++++++ command_ctrl.h | 39 ++++++++++ command_functions.c | 179 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 474 insertions(+) create mode 100644 command_config.h create mode 100644 command_ctrl.c create mode 100644 command_ctrl.h create mode 100644 command_functions.c diff --git a/command_config.h b/command_config.h new file mode 100644 index 0000000..8f46bae --- /dev/null +++ b/command_config.h @@ -0,0 +1,110 @@ +/* + * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de + * Date: 08/2016 + * License: GPLv3 + */ + +#ifndef __COMMAND_CONFIG_H__ +#define __COMMAND_CONFIG_H__ + +/*****************************************************************************/ + +#include +#include + +#include + +#include "config_helper.h" +#include "led_matrix.h" +#include "globals.h" + +/*****************************************************************************/ + +extern uint8_t key_config[EEP_KEY_CNT][EEP_KEY_SEQ_LEN][EEP_KEY_TUPLE_LEN]; +extern uint8_t os_type; +extern uint8_t keystroke_delay; + +/*****************************************************************************/ + +void cc_getConfig(void); +void cc_setKeyConfig(void); +void cc_setLEDState(void); +void cc_setOSType(void); +void cc_startBootloader(void); +void cc_saveFullSampleCfg(void); +void cc_setKeyStrokeDelay(void); + +/*****************************************************************************/ + +#define CC_CMD_GET_CONFIG 0x0A +#define CC_CMD_SET_KEY_CONFIG 0x14 +#define CC_CMD_SET_LED_STATE 0x1E +#define CC_CMD_SET_OS_TYPE 0x28 +#define CC_CMD_START_BTLDR 0x32 +#define CC_CMD_SSKC 0x3C +#define CC_CMD_SET_KS_DELAY 0x46 +//#define CC_CMD_SET_BAUDRATE 0x32 + +/*****************************************************************************/ + +#define CC_CMD_GET_CONFIG_FUNC &cc_getConfig +#define CC_CMD_SET_KEY_CONFIG_FUNC &cc_setKeyConfig +#define CC_CMD_SET_LED_STATE_FUNC &cc_setLEDState +#define CC_CMD_SET_OS_TYPE_FUNC &cc_setOSType +#define CC_CMD_START_BTLDR_FUNC &cc_startBootloader +#define CC_CMD_SSKC_FUNC &cc_saveFullSampleCfg +#define CC_CMD_SET_KS_DELAY_FUNC &cc_setKeyStrokeDelay +//#define CC_CMD_SET_BAUDRATE_FUNC &cc_setBaudrate + +/*****************************************************************************/ + +#define CC_CMD_GET_CONFIG_DATA_TO_READ 0 +#define CC_CMD_SET_KEY_CONFIG_DATA_TO_READ 41 // Key number, 40 byte sequence data +#define CC_CMD_SET_LED_STATE_DATA_TO_READ 2 // LED number, state +#define CC_CMD_SET_OS_TYPE_DATA_TO_READ 1 // the OS type +#define CC_CMD_START_BTLDR_DATA_TO_READ 0 // start bootloader +#define CC_CMD_SSKC_DATA_TO_READ 0 // save sample key config +#define CC_CMD_SET_KS_DELAY_DATA_TO_READ 1 // the keystroke delay value + +/*****************************************************************************/ + +#define CC_READ_DATA_MAX 64 + +/*****************************************************************************/ + +uint8_t cc_commands[] = { + CC_CMD_GET_CONFIG, + CC_CMD_SET_KEY_CONFIG, + CC_CMD_SET_LED_STATE, + CC_CMD_SET_OS_TYPE, + CC_CMD_START_BTLDR, + CC_CMD_SSKC, + CC_CMD_SET_KS_DELAY, + }; + +void (*cc_cmd_functions[])() = { + CC_CMD_GET_CONFIG_FUNC, + CC_CMD_SET_KEY_CONFIG_FUNC, + CC_CMD_SET_LED_STATE_FUNC, + CC_CMD_SET_OS_TYPE_FUNC, + CC_CMD_START_BTLDR_FUNC, + CC_CMD_SSKC_FUNC, + CC_CMD_SET_KS_DELAY_FUNC, + }; + +uint8_t cc_cmd_data_to_read[] = { + CC_CMD_GET_CONFIG_DATA_TO_READ, + CC_CMD_SET_KEY_CONFIG_DATA_TO_READ, + CC_CMD_SET_LED_STATE_DATA_TO_READ, + CC_CMD_SET_OS_TYPE_DATA_TO_READ, + CC_CMD_START_BTLDR_DATA_TO_READ, + CC_CMD_SSKC_DATA_TO_READ, + CC_CMD_SET_KS_DELAY_DATA_TO_READ, + }; + +uint8_t cc_read_data[CC_READ_DATA_MAX]; + +/*****************************************************************************/ + +#endif + diff --git a/command_ctrl.c b/command_ctrl.c new file mode 100644 index 0000000..5f9878b --- /dev/null +++ b/command_ctrl.c @@ -0,0 +1,146 @@ +/* + * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de + * Date: 08/2016 + * License: GPLv3 + */ + +/*****************************************************************************/ + +#include "command_ctrl.h" + +#include "command_config.h" + +// include user specific command control configuration and function definition +#include "command_config.h" +#include "command_functions.c" + +/*****************************************************************************/ + +uint8_t cc_state = CC_STATE_READ_SOM1; + +uint8_t cc_cmd_to_call = CC_CMD_NO_CMD; + +uint8_t cc_cmd_received_correct = MSG_INCOMPLETE; + +uint8_t cc_cmd_data_read_cnt = 0; + +/*****************************************************************************/ + +void cc_init() +{ + cc_state = CC_STATE_READ_SOM1; + cc_cmd_to_call = CC_CMD_NO_CMD; + cc_cmd_data_read_cnt = 0; + cc_cmd_received_correct = MSG_INCOMPLETE; +} + +/*****************************************************************************/ + +void cc_abort() +{ + // send abort message, then init + char* tmp = " "; + sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, + MSG_TYPE_ANSWER_NOK, + MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(tmp); + cc_init(); +} + +/*****************************************************************************/ + +void cc_processData(uint8_t c) +{ + switch (cc_state) + { + //*********************************// + case CC_STATE_READ_SOM1:; + if (c == MSG_SOM1) + cc_state = CC_STATE_READ_SOM2; + else + cc_abort(); + break; + + //*********************************// + case CC_STATE_READ_SOM2:; + if (c == MSG_SOM2) + cc_state = CC_STATE_READ_CMD; + else + cc_abort(); + break; + + //*********************************// + case CC_STATE_READ_CMD:; + for (uint8_t i = 0; i < sizeof(cc_commands)/sizeof(uint8_t); i++) + { + if (cc_commands[i] == c) + { + if (cc_cmd_data_to_read[i] > 0) + cc_state = CC_STATE_READ_DATA; + else + cc_state = CC_STATE_READ_EOM1; + + cc_cmd_to_call = i; // remember the index of command to call + + break; // break the loop + } + } + break; + + //*********************************// + case CC_STATE_READ_DATA:; + // write the variable c to the input buffer + cc_read_data[cc_cmd_data_read_cnt] = c; + + if (cc_cmd_data_read_cnt >= cc_cmd_data_to_read[cc_cmd_to_call]-1) + { + cc_state = CC_STATE_READ_EOM1; + } + + cc_cmd_data_read_cnt++; + + break; + + //*********************************// + case CC_STATE_READ_EOM1:; + if (c == MSG_EOM1) + cc_state = CC_STATE_READ_EOM2; + else + cc_abort(); + break; + + //*********************************// + case CC_STATE_READ_EOM2:; + if (c == MSG_EOM2) + { + cc_cmd_received_correct = MSG_COMPLETE; + } else + cc_abort(); + break; + + default: + cc_abort(); + } + + //*********************************// + if (cc_cmd_received_correct == MSG_COMPLETE) + { + // call the function using the received data + (*cc_cmd_functions[cc_cmd_to_call])(); + // clear the read buffer + cc_clearReadDataBuffer(); + cc_init(); + } +} + +/*****************************************************************************/ + +void cc_clearReadDataBuffer() +{ + for (uint8_t i = 0; i < CC_READ_DATA_MAX; i++) + { + cc_read_data[i] = 0x00; + } +} + +/*****************************************************************************/ diff --git a/command_ctrl.h b/command_ctrl.h new file mode 100644 index 0000000..2e4f69b --- /dev/null +++ b/command_ctrl.h @@ -0,0 +1,39 @@ +/* + * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de + * Date: 08/2016 + * License: GPLv3 + */ + +#ifndef __COMMAND_CTRL_H__ +#define __COMMAND_CTRL_H__ + +#include + +/*****************************************************************************/ + +#define CC_STATE_READ_SOM1 20 +#define CC_STATE_READ_SOM2 30 +#define CC_STATE_READ_CMD 40 +#define CC_STATE_READ_DATA 50 +#define CC_STATE_READ_EOM1 60 +#define CC_STATE_READ_EOM2 70 + +/*****************************************************************************/ + +#define CC_CMD_NO_CMD 0 + +#define MSG_INCOMPLETE 10 +#define MSG_COMPLETE 20 + +/*****************************************************************************/ + +extern void USB_serialStreamWrite(char*); + +void cc_init(void); +void cc_abort(void); +void cc_processData(uint8_t); +void cc_clearReadDataBuffer(void); + +/*****************************************************************************/ + +#endif diff --git a/command_functions.c b/command_functions.c new file mode 100644 index 0000000..f09ab90 --- /dev/null +++ b/command_functions.c @@ -0,0 +1,179 @@ +/* + * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de + * Date: 08/2016 + * License: GPLv3 + */ + +/*****************************************************************************/ + +extern void USB_serialStreamWriteC(char*, uint16_t); +extern void USB_serialStreamWrite(char*); + +/*****************************************************************************/ + +// send the key configuration to the USB host +void cc_getConfig() +{ + char* sBody = " "; + sprintf(sBody, "%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_CONFIG); + USB_serialStreamWrite(sBody); + + for (uint8_t key = 0; key < EEP_KEY_CNT; key++) + { + char* sKey = " "; + sprintf(sKey, "%c", key); + USB_serialStreamWriteC(sKey, 1); + + for (uint8_t seqnum = 0; seqnum < EEP_KEY_SEQ_LEN; seqnum++) + { + char* sSeq = " "; + sprintf(sSeq, "%c%c", key_config[key][seqnum][0], key_config[key][seqnum][1]); + USB_serialStreamWriteC(sSeq, 2); + } + } + + sBody = " "; + sprintf(sBody, "%c%c", MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); + +} + +/*****************************************************************************/ + +// receive the key configuration for one key +void cc_setKeyConfig() +{ + uint8_t key = cc_read_data[0]; + + uint8_t seqnum = 0; + for (uint8_t pos = 1; pos < EEP_KEY_SEQ_LEN; pos += EEP_KEY_TUPLE_LEN) + { + key_config[key][seqnum][0] = cc_read_data[pos]; // first byte f the tuple + key_config[key][seqnum][1] = cc_read_data[pos+1]; // second byte f the tuple + seqnum++; + } + + // TODO should be called by an other function + ch_writeConfig(); + + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); + +} + +/*****************************************************************************/ + +void cc_setLEDState() +{ + uint8_t led = cc_read_data[0]; // LED number + uint8_t state = cc_read_data[1]; // state + + if (led < 0 || led >= EEP_KEY_CNT) + { + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_NOK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); + return; + } + + if (state == 0) + lm_ledOff(led); + else + lm_ledOn(led); + + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); +} + +/*****************************************************************************/ + +void cc_setOSType() +{ + cn_writeOSType(cc_read_data[0]); + + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); +} + +/*****************************************************************************/ + +void cc_startBootloader() +{ + // enable the watchdog without a time interval to use + wdt_enable(0); + + // trigger watchdog + while(1) {}; +} + +/*****************************************************************************/ + +// Wert: | 0x80 | 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 +// Wert: | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 +// Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 +// Descr: | delay | - | fn | meta | altgr | alt | ctrl | shift +// max 40 byte / 20 tupel +uint8_t sample_seq[] = { + 0x01, 0x0b, // H + 0x80, 0x0f, // delay 16 cycles + 0x00, 0x04, // a + 0x00, 0x0f, // l + 0x80, 0x80, // delay 128 cycles + 0x00, 0x0f, // l + 0x00, 0x12, // o + 0x80, 0x0f, // delay 16 cycles + 0x10, 0x00, // meta modifier + 0x80, 0x80, // delay 128 + 0x10, 0x00, // meta modifier + 0xff, 0xff, // in case that length of the sequence is less than 40 byte add a (0xff, 0xff) tuple - only allowed firmware internal + 0xff, 0xff, // one 0xff 0xff tuple is required, the other tuples are added to clean up the eeprom content + 0xff, 0xff, + 0xff, 0xff, + 0xff, 0xff, + 0xff, 0xff, + 0xff, 0xff, + 0xff, 0xff, + 0xff, 0xff, + }; + +// Example hexadecimal data: +// 2 byte: message header +// 1 byte: 0x14 = set configuration command identifier +// 1 byte: 0x00 = key number to modify +// 40 byte: sequence data (tuples) full filled using (0xff, 0xff) tuples +// 2 byte: message footer +// 3C3E1400010B80FF000A000F8080000F001280FF100080801000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D0A + +void cc_saveFullSampleCfg() +{ + for (uint8_t k = 0; k < EEP_KEY_CNT; k++) + { + for (uint8_t s = 0; s < 40; s++) + { + ch_writeKeyConfigMV(k, s, sample_seq[2*s], sample_seq[2*s+1]); + } + } + + ch_readConfig(); + + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); +} + +/*****************************************************************************/ + +void cc_setKeyStrokeDelay() +{ + ch_setKeyStrokeDelay(cc_read_data[0]); + + char* sBody = " "; + sprintf(sBody, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); + USB_serialStreamWrite(sBody); +} + +/*****************************************************************************/ +