Skip to content

Commit

Permalink
Add support for slave display info over raw hid
Browse files Browse the repository at this point in the history
  • Loading branch information
BlankSourceCode committed Jun 11, 2019
1 parent 34c0a30 commit 3ae0977
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
117 changes: 115 additions & 2 deletions keyboards/lily58/keymaps/blanksourcecode/keymap.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include "ssd1306.h"
#endif

// Add headers for raw hid communication
#include <split_scomm.h>
#include "raw_hid.h"

extern keymap_config_t keymap_config;
extern rgblight_config_t rgblight_config;
extern uint8_t is_master;
Expand Down Expand Up @@ -228,6 +232,70 @@ void matrix_scan_user(void) {
iota_gfx_task();
}

// HID input
bool is_hid_connected = false; // Flag indicating if we have a PC connection yet
uint8_t screen_max_count = 0; // Number of info screens we can scroll through (set by connecting node script)
uint8_t screen_show_index = 0; // Current index of the info screen we are displaying
uint8_t screen_data_buffer[SERIAL_SCREEN_BUFFER_LENGTH - 1] = {0}; // Buffer used to store the screen data sent by connected node script
int screen_data_index = 0; // Current index into the screen_data_buffer that we should write to

void raw_hid_send_screen_index(void) {
// Send the current info screen index to the connected node script so that it can pass back the new data
uint8_t send_data[32] = {0};
send_data[0] = screen_show_index + 1; // Add one so that we can distinguish it from a null byte
raw_hid_send(send_data, sizeof(send_data));
}

void raw_hid_receive(uint8_t *data, uint8_t length) {
// PC connected, so set the flag to show a message on the master display
is_hid_connected = true;

// Initial connections use '1' in the first byte to indicate this
if (length > 1 && data[0] == 1) {
// New connection so restart screen_data_buffer
screen_data_index = 0;

// The second byte is the number of info screens the connected node script allows us to scroll through
screen_max_count = data[1];
if (screen_show_index >= screen_max_count) {
screen_show_index = 0;
}

// Tell the connection which info screen we want to look at initially
raw_hid_send_screen_index();
return;
}

// Otherwise the data we receive is one line of the screen to show on the display
if (length >= 21) {
// Copy the data into our buffer and increment the number of lines we have got so far
memcpy((char*)&screen_data_buffer[screen_data_index * 21], data, 21);
screen_data_index++;

// Once we reach 4 lines, we have a full screen
if (screen_data_index == 4) {
// Reset the buffer back to receive the next full screen data
screen_data_index = 0;

// Now get ready to transfer the whole 4 lines to the slave side of the keyboard.
// First clear the transfer buffer with spaces just in case.
memset((char*)&serial_slave_screen_buffer[0], ' ', sizeof(serial_slave_screen_buffer));

// Copy in the 4 lines of screen data, but start at index 1, we use index 0 to indicate a connection in the slave code
memcpy((char*)&serial_slave_screen_buffer[1], screen_data_buffer, sizeof(screen_data_buffer));

// Set index 0 to indicate a connection has been established
serial_slave_screen_buffer[0] = 1;

// Make sure to zero terminate the buffer
serial_slave_screen_buffer[sizeof(serial_slave_screen_buffer) - 1] = 0;

// Indicate that the screen data has changed and needs transferring to the slave side
hid_screen_change = true;
}
}
}

// Screen printing
char layer_state_str[20];
const char *write_layer(void) {
Expand Down Expand Up @@ -268,15 +336,34 @@ const char *write_rgb(void) {
return rbf_info_str;
}

char hid_info_str[20];
const char *write_hid(void) {
snprintf(hid_info_str, sizeof(hid_info_str), "%s", is_hid_connected ? "connected." : " ");
return hid_info_str;
}

void write_slave_info_screen(struct CharacterMatrix *matrix) {
if (serial_slave_screen_buffer[0] > 0) {
// If the first byte of the buffer is non-zero we should have a full set of data to show,
// So we copy it into the display
matrix_write(matrix, (char*)serial_slave_screen_buffer + 1);
} else {
// Otherwise we just draw the logo
matrix_write_ln(matrix, "");
matrix_write(matrix, read_logo());
}
}

void matrix_render_user(struct CharacterMatrix *matrix) {
if (is_master) {
// Show layer and rgb values on the master side
matrix_write_ln(matrix, write_layer());
matrix_write_ln(matrix, " ");
matrix_write_ln(matrix, write_rgb());
matrix_write(matrix, write_hid()); // Add if we have a connection established
} else {
// Show the logo on the slave side
matrix_write(matrix, read_logo());
// Show the logo or screen info on the slave side
write_slave_info_screen(matrix);
}
}

Expand Down Expand Up @@ -451,6 +538,32 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Rotary Encoder
void encoder_update_user(uint8_t index, bool clockwise) {
switch (biton32(layer_state)) {
case _RGB: {
// On the RGB layer we control the screen display with the encoder
if (clockwise) {
// Increment and loop back to beginning if we go over the max
screen_show_index++;
if (screen_show_index >= screen_max_count) {
screen_show_index = 0;
}
} else {
// Decrement and loop back to the end if we are about to go below zero,
// Be careful since index is unsigned.
if (screen_show_index == 0) {
screen_show_index = screen_max_count - 1;
} else {
screen_show_index--;
}
}

// If we have a connection we should tell it about the change,
// Otherwise it will be notified when it first connects instead.
if (is_hid_connected) {
raw_hid_send_screen_index();
}
break;
}

default: {
// Page up and Page down on all layers
if (clockwise) {
Expand Down
5 changes: 5 additions & 0 deletions keyboards/lily58/keymaps/blanksourcecode/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ SRC += ./glcdfont.c \
./lib/logo_reader.c \

TAP_DANCE_ENABLE = yes

RAW_ENABLE = yes # Enable RAW HID communication to PC

Link_Time_Optimization = yes # Reduce size of firmware by optimizing at link time
EXTRAFLAGS += -flto
14 changes: 14 additions & 0 deletions keyboards/lily58/rev1/split_scomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@

uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
uint8_t volatile serial_slave_screen_buffer[SERIAL_SCREEN_BUFFER_LENGTH] = {0};
uint8_t volatile status_com = 0;
uint8_t volatile status1 = 0;
uint8_t volatile status2 = 0;
uint8_t slave_buffer_change_count = 0;
uint8_t s_change_old = 0xff;
uint8_t s_change_new = 0xff;
bool volatile hid_screen_change = false;

SSTD_t transactions[] = {
#define GET_SLAVE_STATUS 0
Expand All @@ -37,6 +40,12 @@ SSTD_t transactions[] = {
{ (uint8_t *)&status1,
0, NULL,
sizeof(serial_slave_buffer), (uint8_t *)serial_slave_buffer
},
#define PUT_SLAVE_SCREEN 3
/* master is transfering screen data to slave */
{ (uint8_t *)&status2,
sizeof(serial_slave_screen_buffer), (uint8_t *)serial_slave_screen_buffer,
0, NULL
}
};

Expand Down Expand Up @@ -73,6 +82,11 @@ int serial_update_buffers(int master_update)
smatstatus = TRANSACTION_END; // dummy status
}

if (hid_screen_change) {
soft_serial_transaction(PUT_SLAVE_SCREEN);
hid_screen_change = false;
}

if( !master_update && !need_retry) {
status = soft_serial_transaction(GET_SLAVE_STATUS);
} else {
Expand Down
3 changes: 3 additions & 0 deletions keyboards/lily58/rev1/split_scomm.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
// Buffers for master - slave communication
#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
#define SERIAL_MASTER_BUFFER_LENGTH MATRIX_ROWS/2
#define SERIAL_SCREEN_BUFFER_LENGTH (/*SSD1306_MatrixCols*/21 * /*SSD1306_MatrixRows*/4 + /*Extra IsEnabledBit*/1)

extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
extern volatile uint8_t serial_slave_screen_buffer[SERIAL_SCREEN_BUFFER_LENGTH];
extern uint8_t slave_buffer_change_count;
extern volatile bool hid_screen_change; // Flag marking if the screen data is dirty and needs transferring to slave

void serial_master_init(void);
void serial_slave_init(void);
Expand Down

0 comments on commit 3ae0977

Please sign in to comment.