add ability to toggle individual led by address

master
jpetermans 2017-04-07 15:58:17 -07:00
parent af13e9a12d
commit a2ac883779
3 changed files with 127 additions and 100 deletions

View File

@ -12,6 +12,10 @@
#define _MEDIA 3
#define _TILDE 4
/* ==================================
* KEYMAPS
* ==================================*/
const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Layer 0: Default Layer
* ,-----------------------------------------------------------.
@ -58,7 +62,7 @@ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,KC_MUTE, KC_VOLD, KC_VOLU,_______,KC_NO,\
_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______,_______,\
_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______, _______,_______, \
_______,_______,F(2),F(3),_______,_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \
_______,_______,F(2),F(3),F(4),_______,_______, _______, KC_MPRV, KC_MNXT,KC_MSTP, _______,KC_NO, \
_______,_______,_______, KC_MPLY, _______,_______, _______,_______ \
),
/* ~ */
@ -86,28 +90,35 @@ enum function_id {
enum macro_id {
ACTION_LEDS_ALL,
ACTION_LEDS_GAME
//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED
ACTION_LEDS_GAME,
ACTION_LED_1
};
/* ==================================
* LED MAPPING
* ==================================*/
//TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED
/*
Configuring led control can be done
Configuring led control can be done as
1. full keyboard at a time - define led array, or
2. individual - send specific led address (defined in keymap.h)
2. individual led - send specific led address (defined in keymap.h)
The arrays relate to the mcu's LED pages (8 available) desribed in led_controller.c
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
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 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
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
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
*/
//"WASD"
@ -153,7 +164,8 @@ 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)
[3] = ACTION_FUNCTION(ACTION_LEDS_GAME),
[4] = ACTION_FUNCTION(ACTION_LED_1)
};
@ -162,15 +174,21 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
(void)opt;
switch(id) {
case ACTION_LEDS_ALL:
if(record->event.pressed) {
// signal the LED controller thread
chMBPost(&led_mailbox, LED_MSG_GAME_TOGGLE, TIME_IMMEDIATE);
}
if(record->event.pressed) {
// signal the LED controller thread
chMBPost(&led_mailbox, 1, TIME_IMMEDIATE);
}
break;
case ACTION_LEDS_GAME:
if(record->event.pressed) {
// signal the LED controller thread
chMBPost(&led_mailbox, LED_MSG_ALL_TOGGLE, TIME_IMMEDIATE);
chMBPost(&led_mailbox, 2, TIME_IMMEDIATE);
}
break;
case ACTION_LED_1:
if(record->event.pressed) {
// signal the LED controller thread
chMBPost(&led_mailbox, ADDR_LED_1, TIME_IMMEDIATE);
}
break;
}
@ -179,14 +197,14 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
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;
case 0:
if (record->event.pressed) {
}
break;
case 1:
if (record->event.pressed) {
}
break;
}
return MACRO_NONE;
};

View File

@ -36,6 +36,9 @@ void led_set(uint8_t usb_led) {
GPIOA->PCOR |= (1<<5);
}
*/
//TODO: How does this test if led is set
//usb_led --> led_set(usb_led) <-- chibios/host_keyboard_leds <-- keyboard_leds from usbSetupTransfer
//keyboard_leds is enum'd in chibios/main.c
if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
// signal the LED control thread
chSysUnconditionalLock();

View File

@ -112,8 +112,8 @@ msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data) {
return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT));
}
msg_t is31_read_register(uint8_t b, uint8_t reg, uint8_t *result) {
is31_select_page(b);
msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result) {
is31_select_page(page);
tx[0] = reg;
return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 1, result, 1, US2ST(IS31_TIMEOUT));
@ -134,6 +134,7 @@ void is31_init(void) {
// software shutdown
is31_write_register(IS31_FUNCTIONREG, IS31_REG_SHUTDOWN, 0);
chThdSleepMilliseconds(10);
// TODO: This already done above, remove?
// zero function page, all registers
is31_write_data(IS31_FUNCTIONREG, full_page, 0xD + 1);
chThdSleepMilliseconds(10);
@ -159,7 +160,8 @@ static THD_FUNCTION(LEDthread, arg) {
(void)arg;
chRegSetThreadName("LEDthread");
uint8_t temp;
uint8_t i;
uint8_t temp, pwm;
uint8_t save_page, save_breath1, save_breath2;
msg_t msg, retval;
@ -170,78 +172,82 @@ static THD_FUNCTION(LEDthread, arg) {
chMBFetch(&led_mailbox, &msg, TIME_INFINITE);
// process 'msg' here
switch(msg) {
// if msg between 0-7, then process as page#, otherwise a specific LED address
xprintf("--------------------\n");
xprintf("mailbox fetch\ntemp: %X - msg: %X\n", temp, msg);
if (msg < 8) {
// read current page into 'temp'
is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp);
chThdSleepMilliseconds(1);
// If page is already in layer, switch off (layer 0)
xprintf("Layer: post-read\ntemp: %X\n", temp);
if(temp == msg) {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0);
} else {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg);
}
xprintf("Layer: post-change\ntemp: %X\n", temp);
} else {
switch(msg) {
//TODO: make this generic and able to turn on/off any address and loop through all(or current) pages
case LED_MSG_CAPS_ON:
// turn caps on on pages 1 and 2
is31_write_register(0, CAPS_LOCK_LED_ADDRESS, 0xFF);
is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0xFF);
is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0xFF);
break;
case LED_MSG_CAPS_OFF:
// turn caps off on pages 1 and 2
is31_write_register(0, CAPS_LOCK_LED_ADDRESS, 0);
is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0);
is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0);
break;
case LED_MSG_SLEEP_LED_ON:
// save current settings
is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page);
is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1);
is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2);
// use pages 7 and 8 for (hardware) breathing (assuming they're empty)
is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF);
is31_write_register(7, BREATHE_LED_ADDRESS, 0x00);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3);
retval = MSG_TIMEOUT;
temp = 6;
while(retval == MSG_TIMEOUT) {
// switch to the other page
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp);
temp = (temp == 6 ? 7 : 6);
// the times should be sufficiently long for IS31 to finish switching pages
retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000));
}
// received a message (should be a wakeup), so restore previous state
chThdSleepMilliseconds(3000); // need to wait until the page change finishes
// note: any other messages are queued
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page);
break;
case LED_MSG_SLEEP_LED_OFF:
// should not get here; wakeup should be received in the branch above
break;
case LED_MSG_ALL_TOGGLE:
// read current page into 'temp'
is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp);
chThdSleepMilliseconds(1);
// switch to 'the other' page
if(temp==2) {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0);
} else {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 2);
}
break;
case LED_MSG_GAME_TOGGLE:
// read current page into 'temp'
is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp);
chThdSleepMilliseconds(1);
// switch to 'the other' page
if(temp==1) {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0);
} else {
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1);
}
break;
//TODO: set number of layers somewhere and loop through all when setting specific led
case LED_MSG_SLEEP_LED_ON:
// save current settings
is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page);
is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1);
is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2);
// use pages 7 and 8 for (hardware) breathing (assuming they're empty)
is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF);
is31_write_register(7, BREATHE_LED_ADDRESS, 0x00);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3);
retval = MSG_TIMEOUT;
temp = 6;
while(retval == MSG_TIMEOUT) {
// switch to the other page
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp);
temp = (temp == 6 ? 7 : 6);
// the times should be sufficiently long for IS31 to finish switching pages
retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000));
}
// received a message (should be a wakeup), so restore previous state
chThdSleepMilliseconds(3000); // need to wait until the page change finishes
// note: any other messages are queued
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2);
is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page);
break;
case LED_MSG_SLEEP_LED_OFF:
// should not get here; wakeup should be received in the branch above break;
break;
default:
if(msg >= 0x24) {
xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm);
is31_read_register(0, msg, &temp);
chThdSleepMilliseconds(10);
xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm);
chThdSleepMilliseconds(10);
pwm = (temp > 0x00 ? 0x00 : 0xFF);
xprintf("pwm after: %X\n", pwm);
chThdSleepMilliseconds(10);
for(i=0; i<8; i++) {
is31_write_register(i, msg, pwm);
}
xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm);
chThdSleepMilliseconds(10);
}
break;
}
}
xprintf("--------------------\n");
}
}
/* =============
* hook into TMK
* ============= */
/* =====================
* hook into user keymap
* ===================== */
void led_controller_init(void) {
uint8_t i;