summaryrefslogtreecommitdiff
path: root/keyboards
diff options
context:
space:
mode:
authorjpetermans <tibcmhhm@gmail.com>2017-05-08 15:13:02 -0700
committerjpetermans <tibcmhhm@gmail.com>2017-05-08 15:13:02 -0700
commit5df74f3ba73f18f6bbd13b82a3a960c86fa592e1 (patch)
tree12bc6f8e3acacbcb36f116334e530c1b179902cf /keyboards
parent2c5b5519706e72022f83054d3e3249e3cd4bd1f3 (diff)
updated keymap for new led functions
Diffstat (limited to 'keyboards')
-rw-r--r--keyboards/infinity60/keymaps/jpetermans/Makefile2
-rw-r--r--keyboards/infinity60/keymaps/jpetermans/keymap.c280
-rw-r--r--keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h78
-rw-r--r--keyboards/infinity60/keymaps/jpetermans/readme.md79
4 files changed, 240 insertions, 199 deletions
diff --git a/keyboards/infinity60/keymaps/jpetermans/Makefile b/keyboards/infinity60/keymaps/jpetermans/Makefile
index 225e4cad40..df3d1e952f 100644
--- a/keyboards/infinity60/keymaps/jpetermans/Makefile
+++ b/keyboards/infinity60/keymaps/jpetermans/Makefile
@@ -1,5 +1,3 @@
-#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
-#BOOTMAGIC_ENABLE = yes
ifndef QUANTUM_DIR
include ../../../../Makefile
diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c
index 6f14b66cba..1afb7c067f 100644
--- a/keyboards/infinity60/keymaps/jpetermans/keymap.c
+++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c
@@ -1,6 +1,5 @@
#include "infinity60.h"
#include "led_controller.h"
-#include "keymap_jpetermans.h"
//Helpful Defines
#define _______ KC_TRNS
@@ -12,8 +11,33 @@
#define _MEDIA 3
#define _TILDE 4
+//IS31 chip has 8 available led pages, using 0 for all leds and 7 for single toggles
+#define max_pages 6
+
+enum ic60_keycodes {
+ NUMPAD,
+ FNAV,
+ MEDIA,
+ TILDE,
+ CTLALTDEL,
+ BACKLIGHT,
+ BRIGHT,
+ DIM,
+ BREATH,
+ ALL,
+ GAME,
+ MODE_SINGLE,
+ MODE_PAGE,
+ MODE_FLASH
+};
+
+uint8_t current_layer_global = 0;
+uint8_t led_mode_global = MODE_SINGLE;
+uint8_t backlight_status_global = 1; //init on/off state of backlight
+uint32_t led_layer_state = 0;
+
/* ==================================
- * KEYMAPS
+ * KEYMAPS
* ==================================*/
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@@ -35,19 +59,10 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL, KC_BSLS,KC_NO,\
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSPC, \
TT(_FNAV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_ENT, \
- F(1), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_RSFT,KC_NO, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,F(TILDE),KC_NO, \
KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,TG(_NUMPAD),MO(_MEDIA), KC_RCTL \
),
- /* F-, arrow, and media keys */
- [_FNAV] = KEYMAP( \
- KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\
- KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \
- _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \
- _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \
- _______,_______,_______, _______, F(0),KC_NLCK,_______,_______ \
- ),
-
/* numpad */
[_NUMPAD] = KEYMAP( \
_______,_______,_______,_______,_______,_______,_______, KC_P7, KC_P8, KC_P9, KC_PSLS, _______,_______,_______,KC_NO,\
@@ -57,12 +72,21 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______,_______,_______, MO(_BASE), _______,_______,_______,_______ \
),
+ /* F-, arrow, and media keys */
+ [_FNAV] = KEYMAP( \
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,KC_NO,\
+ KC_CAPS,_______,_______,_______,_______,_______,_______,KC_PGUP,KC_UP,KC_PGDN,KC_PSCR,_______,_______,KC_DEL, \
+ _______,M(0),KC_BTN2,_______,_______,_______,KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_INS,_______,_______, \
+ _______,KC_APP,KC_BTN1,KC_CALC,_______,_______,KC_END,_______,_______,_______,_______,_______,KC_NO, \
+ _______,_______,_______, _______, F(CTLALTDEL),KC_NLCK,_______,_______ \
+ ),
+
/* media */
[_MEDIA] = KEYMAP( \
- _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\
+ _______,F(MODE_SINGLE),F(MODE_PAGE),F(MODE_FLASH),_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\
_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\
- _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \
- _______,_______,F(2),F(3),F(4),F(5),F(6),F(7), KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \
+ _______,_______,_______,_______,_______,F(GAME),_______, _______, _______, _______,_______, _______,_______, \
+ _______,_______,F(ALL) ,F(BRIGHT),F(DIM),F(BACKLIGHT),_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \
_______,_______,_______, KC_MPLY, _______,_______, _______,_______ \
),
/* ~ */
@@ -91,21 +115,20 @@ enum function_id {
enum macro_id {
ACTION_LEDS_ALL,
ACTION_LEDS_GAME,
- ACTION_LEDS_NAV,
- ACTION_LEDS_MEDIA,
- ACTION_LEDS_NUMPAD,
- ACTION_LEDS_TEST
+ ACTION_LEDS_BACKLIGHT,
+ ACTION_LEDS_BRIGHT,
+ ACTION_LEDS_DIM,
+ ACTION_LEDS_BREATH,
+ ACTION_LEDS_SINGLE,
+ ACTION_LEDS_PAGE,
+ ACTION_LEDS_FLASH,
};
-
+
/* ==================================
- * LED MAPPING
+ * LED MAPPING
* ==================================*/
/*
- Configuring led control can be done as
- 1. full keyboard at a time - define led array, or
- 2. individual led - send specific led address (defined in keymap.h)
-
Infinity60 LED MAP
11 12 13 14 15 16 17 18 21 22 23 24 25 26 27*
28 31 32 33 34 35 36 37 38 41 42 43 44 45
@@ -113,163 +136,182 @@ enum macro_id {
63 64 65 66 67 68 71 72 73 74 75 76 77*
78 81 82 83 84 85 86 87
*Unused in Alphabet Layout
-
- The full keyboard arrays map to the mcu's LED pages
- (8 available) desribed in led_controller.c
-
- 0x24 (pcb row 1) is first byte of PWM portion of LED page
- 0x34 (pcb row 2) is 17th byte of PWM portion of LED page
- array translates to row and column positions
*/
-//LED Layer indicator (1 per layer 3-7)
-const uint8_t led_single_layer[5] = {
- 12,13,14,15,16
-};
-//LED Page 1 - All off
-//LED Page 2 - All on
-//LED Page 3 - _Nav
-const uint8_t led_nav[33] = {
- 11,12,13,14,15,16,17,18,21,22,23,24,25,
- 28, 37,38,41,42,45,
- 46,47,48, 54,55,56,57,58,
- 64,65,66, 71,
- 84,85
-};
-//LED Page 4 - _Numpad
-const uint8_t led_numpad[17] = {
+//======== full page arrays =========
+//LED Page 1 - _Numpad
+//any change in array size needs to be mirrored in matrix_init_user
+uint8_t led_numpad[16] = {
18,21,22,23,
37,38,41,42,
55,56,57,58,
- 72,73,74,75,
- 85
+ 72,73,74,75
};
-//LED Page 5 - _Media
-const uint8_t led_media[12] = {
- 23,24,25,
- 38,
- 55,56,57,
- 73,74,75,
- 83, 86
+//LED Page 2 - _Nav
+uint8_t led_nav[12] = {
+ 38,
+ 47,48, 55,56,57,
+ 64,65,66
};
-//LED Page 6 - _Game
-const uint8_t led_game[5] = {
- //row 1
+//LED Page 3 - _Media
+uint8_t led_media[15] = {
+ 12,13,14, 23,24,25,
+ 65,66,67,68, 73,74,75,
+ 83, 86
+};
+//LED Page 4 - _Game "WASD"
+uint8_t led_game[5] = {
11,
- //row 2
- //row 3
- 32,
- //row 4
- 47, 48,
- //row 5
- 51
- //row 6
- //row 7
- //row 8
+ 32,
+ 47,48,51
};
+//======== qmk functions =========
const uint16_t fn_actions[] = {
- [0] = ACTION_KEY(LALT(LCTL(KC_DEL))),
- [1] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT),
- [2] = ACTION_FUNCTION(ACTION_LEDS_ALL),
- [3] = ACTION_FUNCTION(ACTION_LEDS_GAME),
- [4] = ACTION_FUNCTION(ACTION_LEDS_MEDIA),
- [5] = ACTION_FUNCTION(ACTION_LEDS_NAV),
- [6] = ACTION_FUNCTION(ACTION_LEDS_NUMPAD),
- [7] = ACTION_FUNCTION(ACTION_LEDS_TEST)
-
-
+ [CTLALTDEL] = ACTION_KEY(LALT(LCTL(KC_DEL))),
+ [TILDE] = ACTION_LAYER_MODS(_TILDE, MOD_LSFT),
+ [ALL] = ACTION_FUNCTION(ACTION_LEDS_ALL),
+ [GAME] = ACTION_FUNCTION(ACTION_LEDS_GAME),
+ [BACKLIGHT] = ACTION_FUNCTION(ACTION_LEDS_BACKLIGHT),
+ [BRIGHT] = ACTION_FUNCTION(ACTION_LEDS_BRIGHT),
+ [DIM] = ACTION_FUNCTION(ACTION_LEDS_DIM),
+ [BREATH] = ACTION_FUNCTION(ACTION_LEDS_BREATH),
+ [MODE_SINGLE] = ACTION_FUNCTION(ACTION_LEDS_SINGLE),
+ [MODE_PAGE] = ACTION_FUNCTION(ACTION_LEDS_PAGE),
+ [MODE_FLASH] = ACTION_FUNCTION(ACTION_LEDS_FLASH),
};
/* custom action function */
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
- (void)opt;
msg_t msg;
+
switch(id) {
case ACTION_LEDS_ALL:
if(record->event.pressed) {
- // signal the LED controller thread
+ led_mode_global = led_mode_global == ALL ? MODE_SINGLE : ALL;
msg=(TOGGLE_ALL << 8) | 0;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
- case ACTION_LEDS_GAME:
+
+ case ACTION_LEDS_BACKLIGHT:
if(record->event.pressed) {
- // signal the LED controller thread
- msg=(TOGGLE_LAYER_LEDS << 8) | 6;
+ backlight_status_global ^= 1;
+ msg=(TOGGLE_BACKLIGHT << 8) | (backlight_status_global);
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
- case ACTION_LEDS_MEDIA:
+
+ case ACTION_LEDS_GAME:
if(record->event.pressed) {
- // signal the LED controller thread
- msg=(TOGGLE_LAYER_LEDS << 8) | 5;
+ led_mode_global = led_mode_global == GAME ? MODE_SINGLE : GAME;
+
+ msg=(DISPLAY_PAGE << 8) | 4;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
- case ACTION_LEDS_NAV:
+
+ case ACTION_LEDS_BRIGHT:
if(record->event.pressed) {
- // signal the LED controller thread
- msg=(OFF_LED << 8) | 12;
+ msg=(STEP_BRIGHTNESS << 8) | 1;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
- case ACTION_LEDS_NUMPAD:
+
+ case ACTION_LEDS_DIM:
if(record->event.pressed) {
- // signal the LED controller thread
- msg=(ON_LED << 8) | 12;
+ msg=(STEP_BRIGHTNESS << 8) | 0;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
- case ACTION_LEDS_TEST:
+
+ case ACTION_LEDS_BREATH:
if(record->event.pressed) {
- // signal the LED controller thread
- msg=(TOGGLE_LED << 8) | 12;
+ msg=(TOGGLE_BREATH << 8) | 0;
chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
}
break;
+
+ //set led_mode for matrix_scan to toggle leds
+ case ACTION_LEDS_SINGLE:
+ led_mode_global = MODE_SINGLE;
+ break;
+ case ACTION_LEDS_PAGE:
+ led_mode_global = MODE_PAGE;
+ break;
+ case ACTION_LEDS_FLASH:
+ led_mode_global = MODE_FLASH;
+ break;
+
}
}
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
- switch(id) {
- case 0:
- if (record->event.pressed) {
- }
- break;
- case 1:
- if (record->event.pressed) {
- }
- break;
- }
return MACRO_NONE;
};
+bool process_record_user (uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
// Runs just one time when the keyboard initializes.
void matrix_init_user(void) {
xprintf("init start");
led_controller_init();
-//TODO: do pages need to be written at init or ok on demand?
-/* Write pages */
- write_led_page(3, led_nav, 33);
- chThdSleepMilliseconds(5);
+ // Write predefined led pages.
+ write_led_page(_NUMPAD, led_numpad, 16);
+ chThdSleepMilliseconds(10);
- write_led_page(4, led_numpad, 17);
- chThdSleepMilliseconds(5);
+ write_led_page(_FNAV, led_nav, 12);
+ chThdSleepMilliseconds(10);
- write_led_page(5, led_media, 12);
- chThdSleepMilliseconds(5);
+ write_led_page(_MEDIA, led_media, 15);
+ chThdSleepMilliseconds(10);
- write_led_page(6, led_game, 5);
- chThdSleepMilliseconds(5);
+ write_led_page(4, led_game, 5);
+ chThdSleepMilliseconds(1000);
};
-// Runs constantly in the background, in a loop.
+// Loops constantly in the background.
void matrix_scan_user(void) {
+ uint8_t page;
+ uint8_t led_pin_byte;
+ msg_t msg;
-};
+ if (backlight_status_global == 0) {//backlight is off, skip the rest
+ return;
+ }
+
+ if (led_layer_state != layer_state && led_mode_global != GAME && led_mode_global != ALL) {
+ //check mode
+ //Turn on layer indicator or page depending on mode
+ switch(led_mode_global) {
+ case MODE_FLASH: //flash preset page leds then single indicator
+ page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state);
+ msg=(DISPLAY_PAGE << 8) | (page);
+ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
+ chThdSleepMilliseconds(500);
+ //flow to display single layer leds
+
+ case MODE_SINGLE: //light layer indicators for all active layers
+ led_pin_byte = layer_state & 0xFF;
+ msg=(DISPLAY_PAGE << 8) | 7;
+ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
+ msg=(1<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);
+ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
+ break;
+
+ case MODE_PAGE: //display pre-defined led page
+ page = biton32(layer_state) > max_pages ? 7 : biton32(layer_state);
+ msg=(DISPLAY_PAGE << 8) | (page);
+ chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);
+ break;
+ }
+ led_layer_state = layer_state;
+ }
+}
diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h b/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h
deleted file mode 100644
index 240374423c..0000000000
--- a/keyboards/infinity60/keymaps/jpetermans/keymap_jpetermans.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* LED layout mainly based on default Standard configuration
- * ,-----------------------------------------------------------.
- * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \ | ` |
- * |-----------------------------------------------------------|
- * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| Bksp|
- * |-----------------------------------------------------------|
- * |Caps | A| S| D| F| G| H| J| K| L| ;| '|Enter |
- * |-----------------------------------------------------------|
- * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
- * |-----------------------------------------------------------'
- * | LCtl|LGui|LAlt | Space | RAlt|RGui|RMenu|RCtl|
- * `-----------------------------------------------------------'
-*/
-
-
-#define ADDR_LED_ESC 0x24
-#define ADDR_LED_1 0x25
-#define ADDR_LED_2 0x26
-#define ADDR_LED_3 0x27
-#define ADDR_LED_4 0x28
-#define ADDR_LED_5 0x29
-#define ADDR_LED_6 0x2A
-#define ADDR_LED_7 0x2B
-#define ADDR_LED_8 0x34
-#define ADDR_LED_9 0x35
-#define ADDR_LED_0 0x36
-#define ADDR_LED_MINS 0x37
-#define ADDR_LED_EQL 0x38
-#define ADDR_LED_BSLS 0x39
-//#define ADDR_LED_GRV 0x3A //not used by Alphabet layout
-#define ADDR_LED_TAB 0x3B
-#define ADDR_LED_Q 0x44
-#define ADDR_LED_W 0x45
-#define ADDR_LED_E 0x46
-#define ADDR_LED_R 0x47
-#define ADDR_LED_T 0x48
-#define ADDR_LED_Y 0x49
-#define ADDR_LED_U 0x4A
-#define ADDR_LED_I 0x4B
-#define ADDR_LED_O 0x54
-#define ADDR_LED_P 0x55
-#define ADDR_LED_LBRC 0x56
-#define ADDR_LED_RBRC 0x57
-#define ADDR_LED_BSPC 0x58
-#define ADDR_LED_CAPS 0x59
-#define ADDR_LED_A 0x5A
-#define ADDR_LED_S 0x5B
-#define ADDR_LED_D 0x64
-#define ADDR_LED_F 0x65
-#define ADDR_LED_G 0x66
-#define ADDR_LED_H 0x67
-#define ADDR_LED_J 0x68
-#define ADDR_LED_K 0x69
-#define ADDR_LED_L 0x6A
-#define ADDR_LED_SCLN 0x6B
-#define ADDR_LED_QUOT 0x74
-#define ADDR_LED_ENT 0x75
-#define ADDR_LED_LSFT 0x76
-#define ADDR_LED_Z 0x77
-#define ADDR_LED_X 0x78
-#define ADDR_LED_C 0x79
-#define ADDR_LED_V 0x7A
-#define ADDR_LED_B 0x7B
-#define ADDR_LED_N 0x84
-#define ADDR_LED_M 0x85
-#define ADDR_LED_COMM 0x86
-#define ADDR_LED_DOT 0x87
-#define ADDR_LED_SLSH 0x88
-#define ADDR_LED_RSFT 0x89
-//#define ADDR_LED_FN0 0x8A //not used by Alphabet layout
-#define ADDR_LED_LCTL 0x8B
-#define ADDR_LED_LGUI 0x94
-#define ADDR_LED_LALT 0x95
-#define ADDR_LED_SPC 0x96
-#define ADDR_LED_RALT 0x97
-#define ADDR_LED_RGUI 0x98
-#define ADDR_LED_MENU 0x99
-#define ADDR_LED_RCTL 0x9A
diff --git a/keyboards/infinity60/keymaps/jpetermans/readme.md b/keyboards/infinity60/keymaps/jpetermans/readme.md
new file mode 100644
index 0000000000..9c5b89173c
--- /dev/null
+++ b/keyboards/infinity60/keymaps/jpetermans/readme.md
@@ -0,0 +1,79 @@
+Backlight for Infinity60
+========================
+
+## Led Controller Specs
+
+The Infinity60 pcb uses the IS31FL3731C matrix LED driver from ISSI [datasheet](http://www.issi.com/WW/pdf/31FL3731C.pdf). The IS31 has the ability to control two led matrices (A & B), each matrix controlling 9 pins, each pin controlling 8 leds. The Infinity only utilizes matrix A.
+
+Infinity60 LED MAP:
+digits mean "row" and "col", i.e. 45 means C4-5 in the IS31 datasheet, matrix A
+```c
+ 11 12 13 14 15 16 17 18 21 22 23 24 25 26 27*
+ 28 31 32 33 34 35 36 37 38 41 42 43 44 45
+ 46 47 48 51 52 53 54 55 56 57 58 61 62
+ 63 64 65 66 67 68 71 72 73 74 75 76 77*
+ 78 81 82 83 84 85 86 87
+```
+*Unused in Alphabet Layout
+
+The IS31 includes 8 pages (or frames) 0-7 and each page consists of 0xB4 (144) bytes
+- **0 - 17** LED control (on/off). 18 pins which alternate between A and B matrices (CA1, CB1, CA2, CB2, ..). Each byte controls the 8 leds on that pin with bits (8 to 1).
+- **18 - 35** Blink control. Same as LED control above, but sets blink on/off.
+- **36 - 143** PWM control. One byte per LED, sets PWM from 0 to 255. Same as above, the register alternates bytes between the A & B matrices.
+
+## Led Controller Code
+led_controller.c sets up ability to write led layers at startup or control leds on demand as part of fn_actions. By default led_controller.c assumes page 0 will be used for full on/off and page 7 for controlling individual leds. The remaining 6 pages (1-6) are free to preset led maps at init or on demand. Communication with the IS31 is primarily done through the led_mailbox using chMBPost described further below under "Sending messages in Keymap.c"
+
+One function is available to directly control leds:
+```
+write_led_page(page#, array of leds by address, # of leds in array)
+```
+This function saves a full page using a supplied array of led locations such as:
+```
+uint8_t led_numpad[16] = {
+ 18,21,22,23,
+ 37,38,41,42,
+ 55,56,57,58,
+ 72,73,74,75
+}
+write_led_page(5, led_numpad, 16);
+```
+
+Remaining led control is done through the led mailbox using these message types.
+- **SET_FULL_ROW** - 3 bytes: row#, message type, 8-bit mask. Sets all leds on one pin per the bit mask.
+- **OFF_LED** - 2 bytes: message type, led address. Turn off specific led.
+- **ON_LED** - 2 bytes: message type, led address. Turn on specific led.
+- **TOGGLE_LED** - 2 bytes: message type, led address. Toggle specific led on/off.
+- **BLINK_OFF_LED** - 2 bytes: message type, led address. Set blink off for specific led.
+- **BLINK_ON_LED** - 2 bytes: message type, led address. Set blink on for specific led.
+- **BLINK_TOGGLE_LED** - 2 bytes: message type, led address. Toggle blink for specific led.
+- **TOGGLE_ALL** - 2 bytes: message type, not used. Turn on/off full backlight.
+- **TOGGLE_BACKLIGHT** - 2 bytes: message type, on/off. Sets backlight completely off, no leds will display.
+- **DISPLAY_PAGE** - 2 bytes: message type, page to display. Switch to specific pre-set page.
+- **RESET_PAGE** - 2 bytes: message type, page to reset. Reset/erase specific page.
+- **TOGGLE_NUM_LOCK** - 2 bytes: message type, on/off (NUM_LOCK_LED_ADDRESS). Toggle numlock on/off. Usually run with the `set_leds` function to check state of numlock or capslock. If all leds are on (e.i. TOGGLE_ALL) then this sets numlock to blink instead (this is still a little buggy if toggling on/off quickly).
+- **TOGGLE_CAPS_LOCK** - 2 bytes: message type, on/off (CAPS_LOCK_LED_ADDRESS). Same as numlock.
+- **STEP_BRIGHTNESS** - 2 bytes: message type, and step up (1) or step down (0). Increase or decrease led brightness.
+
+## Sending messages in Keymap.c
+Sending an action to the led mailbox is done using chMBPost with the following form.
+```
+chMBPost(&led_mailbox, message, timeout);
+```
+- &led_mailbox - pointer to led mailbox
+- message - up to 4 bytes but most messages use only 2. First byte (LSB) is the message to process, the second byte is type. The third is only used to pass row information in SET_FULL_ROW. The fourth byte is currently unused.
+-timeout is usually TIME_IMMEDIATE
+
+An example:
+1. set the message to be sent. First byte (LSB) is the led address, and second is the message type
+`msg=(ON_LED << 8) | 42;`
+2. send msg to the led mailbox
+`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);`
+
+Another:
+`msg=(BLINK_TOGGLE_LED << 8) | 46;`
+`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);`
+
+Finally, SET_FULL_ROW requires an extra byte with row information in the message so sending this message looks like:
+`msg=(row<<16) | (SET_FULL_ROW << 8) | (led_pin_byte);`
+`chMBPost(&led_mailbox, msg, TIME_IMMEDIATE);`