diff options
| author | jpetermans <tibcmhhm@gmail.com> | 2017-04-10 17:36:47 -0700 |
|---|---|---|
| committer | jpetermans <tibcmhhm@gmail.com> | 2017-04-10 17:36:47 -0700 |
| commit | dda858c437e2fd0336f070ccb5d1f6e412815d9a (patch) | |
| tree | fb94cde2ebfd5cef5b90520efc84aab94ec75f03 | |
| parent | a2ac8837790030b771744402aac8d8ab0e1967aa (diff) | |
| download | qmk_firmware-dda858c437e2fd0336f070ccb5d1f6e412815d9a.tar.gz qmk_firmware-dda858c437e2fd0336f070ccb5d1f6e412815d9a.zip | |
revised led controller code to allow for more options
unable to switch picture displays
| -rw-r--r-- | keyboards/infinity60/keymaps/jpetermans/keymap.c | 103 | ||||
| -rw-r--r-- | keyboards/infinity60/led.c | 4 | ||||
| -rw-r--r-- | keyboards/infinity60/led_controller.c | 333 | ||||
| -rw-r--r-- | keyboards/infinity60/led_controller.h | 33 |
4 files changed, 340 insertions, 133 deletions
diff --git a/keyboards/infinity60/keymaps/jpetermans/keymap.c b/keyboards/infinity60/keymaps/jpetermans/keymap.c index c7145ed78..cfc288916 100644 --- a/keyboards/infinity60/keymaps/jpetermans/keymap.c +++ b/keyboards/infinity60/keymaps/jpetermans/keymap.c | |||
| @@ -98,8 +98,6 @@ enum macro_id { | |||
| 98 | * LED MAPPING | 98 | * LED MAPPING |
| 99 | * ==================================*/ | 99 | * ==================================*/ |
| 100 | 100 | ||
| 101 | //TODO: ACTION_LED_LAYER which reads current layer and turns on appropriate LED | ||
| 102 | |||
| 103 | /* | 101 | /* |
| 104 | Configuring led control can be done as | 102 | Configuring led control can be done as |
| 105 | 1. full keyboard at a time - define led array, or | 103 | 1. full keyboard at a time - define led array, or |
| @@ -121,43 +119,50 @@ enum macro_id { | |||
| 121 | array translates to row and column positions | 119 | array translates to row and column positions |
| 122 | */ | 120 | */ |
| 123 | 121 | ||
| 124 | //"WASD" | 122 | //LED Layer indicator (1 per layer 3-7) |
| 125 | const uint8_t led_game[72] = { | 123 | const uint8_t led_single_layer[5] = { |
| 126 | 0x24, | 124 | 12,13,14,15,16 |
| 127 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 128 | 0x34, | ||
| 129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 130 | 0x44, | ||
| 131 | 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 132 | 0x54, | ||
| 133 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, | ||
| 134 | 0x64, | ||
| 135 | 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 136 | 0x74, | ||
| 137 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 138 | 0x84, | ||
| 139 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 140 | 0x94, | ||
| 141 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 142 | }; | 125 | }; |
| 143 | 126 | //LED Page 1 - All off | |
| 144 | const uint8_t led_all[72] = { | 127 | //LED Page 2 - All on |
| 145 | 0x24, | 128 | //LED Page 3 - _Nav |
| 146 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 129 | const uint8_t led_nav[33] = { |
| 147 | 0x34, | 130 | 11,12,13,14,15,16,17,18,21,22,23,24,25, |
| 148 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 131 | 28, 37,38,41,42,45, |
| 149 | 0x44, | 132 | 46,47,48, 54,55,56,57,58, |
| 150 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 133 | 64,65,66, 71, |
| 151 | 0x54, | 134 | 84,85 |
| 152 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 135 | }; |
| 153 | 0x64, | 136 | //LED Page 4 - _Numpad |
| 154 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 137 | const uint8_t led_numpad[17] = { |
| 155 | 0x74, | 138 | 18,21,22,23, |
| 156 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 139 | 37,38,41,42, |
| 157 | 0x84, | 140 | 55,56,57,58, |
| 158 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 141 | 72,73,74,75, |
| 159 | 0x94, | 142 | 85 |
| 160 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | 143 | }; |
| 144 | //LED Page 5 - _Media | ||
| 145 | const uint8_t led_media[12] = { | ||
| 146 | 23,24,25, | ||
| 147 | 38, | ||
| 148 | 55,56,57, | ||
| 149 | 73,74,75, | ||
| 150 | 83, 86 | ||
| 151 | }; | ||
| 152 | //LED Page 6 - _Game | ||
| 153 | const uint8_t led_game[5] = { | ||
| 154 | //row 1 | ||
| 155 | 11, | ||
| 156 | //row 2 | ||
| 157 | //row 3 | ||
| 158 | 32, | ||
| 159 | //row 4 | ||
| 160 | 47, 48, | ||
| 161 | //row 5 | ||
| 162 | 51 | ||
| 163 | //row 6 | ||
| 164 | //row 7 | ||
| 165 | //row 8 | ||
| 161 | }; | 166 | }; |
| 162 | 167 | ||
| 163 | const uint16_t fn_actions[] = { | 168 | const uint16_t fn_actions[] = { |
| @@ -172,17 +177,20 @@ const uint16_t fn_actions[] = { | |||
| 172 | /* custom action function */ | 177 | /* custom action function */ |
| 173 | void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { | 178 | void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { |
| 174 | (void)opt; | 179 | (void)opt; |
| 180 | msg_t msg; | ||
| 175 | switch(id) { | 181 | switch(id) { |
| 176 | case ACTION_LEDS_ALL: | 182 | case ACTION_LEDS_ALL: |
| 177 | if(record->event.pressed) { | 183 | if(record->event.pressed) { |
| 178 | // signal the LED controller thread | 184 | // signal the LED controller thread |
| 179 | chMBPost(&led_mailbox, 1, TIME_IMMEDIATE); | 185 | msg=(TOGGLE_LED << 8) | 12; |
| 186 | chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); | ||
| 180 | } | 187 | } |
| 181 | break; | 188 | break; |
| 182 | case ACTION_LEDS_GAME: | 189 | case ACTION_LEDS_GAME: |
| 183 | if(record->event.pressed) { | 190 | if(record->event.pressed) { |
| 184 | // signal the LED controller thread | 191 | // signal the LED controller thread |
| 185 | chMBPost(&led_mailbox, 2, TIME_IMMEDIATE); | 192 | msg=(TOGGLE_LAYER_LEDS << 8) | 5; |
| 193 | chMBPost(&led_mailbox, msg, TIME_IMMEDIATE); | ||
| 186 | } | 194 | } |
| 187 | break; | 195 | break; |
| 188 | case ACTION_LED_1: | 196 | case ACTION_LED_1: |
| @@ -212,19 +220,22 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||
| 212 | 220 | ||
| 213 | // Runs just one time when the keyboard initializes. | 221 | // Runs just one time when the keyboard initializes. |
| 214 | void matrix_init_user(void) { | 222 | void matrix_init_user(void) { |
| 215 | uint8_t j; | ||
| 216 | 223 | ||
| 217 | led_controller_init(); | 224 | led_controller_init(); |
| 218 | 225 | ||
| 219 | //TODO: do pages need to be written at init or ok on demand? | 226 | //TODO: do pages need to be written at init or ok on demand? |
| 220 | /* Write pages */ | 227 | /* Write pages */ |
| 221 | for(j=0; j<8; j++) { | 228 | write_led_page(3, led_nav, 33); |
| 222 | is31_write_data(1,(uint8_t *)(led_game+(9*j)),9); | ||
| 223 | chThdSleepMilliseconds(5); | 229 | chThdSleepMilliseconds(5); |
| 224 | is31_write_data(2,(uint8_t *)(led_all+(9*j)),9); | 230 | |
| 231 | write_led_page(4, led_numpad, 17); | ||
| 225 | chThdSleepMilliseconds(5); | 232 | chThdSleepMilliseconds(5); |
| 226 | } | ||
| 227 | 233 | ||
| 234 | write_led_page(5, led_media, 12); | ||
| 235 | chThdSleepMilliseconds(5); | ||
| 236 | |||
| 237 | write_led_page(6, led_game, 5); | ||
| 238 | chThdSleepMilliseconds(5); | ||
| 228 | }; | 239 | }; |
| 229 | 240 | ||
| 230 | // Runs constantly in the background, in a loop. | 241 | // Runs constantly in the background, in a loop. |
diff --git a/keyboards/infinity60/led.c b/keyboards/infinity60/led.c index 815a529fc..d2f554549 100644 --- a/keyboards/infinity60/led.c +++ b/keyboards/infinity60/led.c | |||
| @@ -42,12 +42,12 @@ void led_set(uint8_t usb_led) { | |||
| 42 | if (usb_led & (1<<USB_LED_CAPS_LOCK)) { | 42 | if (usb_led & (1<<USB_LED_CAPS_LOCK)) { |
| 43 | // signal the LED control thread | 43 | // signal the LED control thread |
| 44 | chSysUnconditionalLock(); | 44 | chSysUnconditionalLock(); |
| 45 | chMBPostI(&led_mailbox, LED_MSG_CAPS_ON); | 45 | chMBPostI(&led_mailbox, 0x59); |
| 46 | chSysUnconditionalUnlock(); | 46 | chSysUnconditionalUnlock(); |
| 47 | } else { | 47 | } else { |
| 48 | // signal the LED control thread | 48 | // signal the LED control thread |
| 49 | chSysUnconditionalLock(); | 49 | chSysUnconditionalLock(); |
| 50 | chMBPostI(&led_mailbox, LED_MSG_CAPS_OFF); | 50 | chMBPostI(&led_mailbox, 0x59); |
| 51 | chSysUnconditionalUnlock(); | 51 | chSysUnconditionalUnlock(); |
| 52 | } | 52 | } |
| 53 | } | 53 | } |
diff --git a/keyboards/infinity60/led_controller.c b/keyboards/infinity60/led_controller.c index e0350bd93..03f061a20 100644 --- a/keyboards/infinity60/led_controller.c +++ b/keyboards/infinity60/led_controller.c | |||
| @@ -57,7 +57,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 57 | * The usual Caps Lock position is C4-6, so the address is | 57 | * The usual Caps Lock position is C4-6, so the address is |
| 58 | * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ | 58 | * 0x24 + (4-1)*0x10 + (8-1) = 0x59 */ |
| 59 | #if !defined(CAPS_LOCK_LED_ADDRESS) | 59 | #if !defined(CAPS_LOCK_LED_ADDRESS) |
| 60 | #define CAPS_LOCK_LED_ADDRESS 0x59 | 60 | #define CAPS_LOCK_LED_ADDRESS 0x46 |
| 61 | #endif | ||
| 62 | |||
| 63 | #if !defined(NUM_LOCK_LED_ADDRESS) | ||
| 64 | #define NUM_LOCK_LED_ADDRESS 0x85 | ||
| 61 | #endif | 65 | #endif |
| 62 | 66 | ||
| 63 | /* Which LED should breathe during sleep */ | 67 | /* Which LED should breathe during sleep */ |
| @@ -85,12 +89,21 @@ uint8_t full_page[0xB4+1] = {0}; | |||
| 85 | // LED mask (which LEDs are present, selected by bits) | 89 | // LED mask (which LEDs are present, selected by bits) |
| 86 | // See page comment above, control alternates CA matrix/CB matrix | 90 | // See page comment above, control alternates CA matrix/CB matrix |
| 87 | // IC60 pcb uses only CA matrix. | 91 | // IC60 pcb uses only CA matrix. |
| 88 | // Each byte is a control pin for 8 leds 8-1 | 92 | // Each byte is a control pin for 8 leds ordered 8-1 |
| 89 | const uint8_t is31_ic60_leds_mask[0x12] = { | 93 | const uint8_t is31_ic60_leds_mask[0x12] = { |
| 90 | 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, | 94 | 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, |
| 91 | 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x00 | 95 | 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x00 |
| 92 | }; | 96 | }; |
| 93 | 97 | ||
| 98 | // array to hold brightness pwm steps | ||
| 99 | const uint8_t pwm_levels[5] = { | ||
| 100 | 0x00, 0x16, 0x4E, 0xA1, 0xFF | ||
| 101 | }; | ||
| 102 | |||
| 103 | // array to write to pwm register | ||
| 104 | uint8_t pwm_reg_array[9] = {0}; | ||
| 105 | |||
| 106 | |||
| 94 | /* ============================ | 107 | /* ============================ |
| 95 | * communication functions | 108 | * communication functions |
| 96 | * ============================ */ | 109 | * ============================ */ |
| @@ -109,6 +122,7 @@ msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data) { | |||
| 109 | is31_select_page(page); | 122 | is31_select_page(page); |
| 110 | tx[0] = reg; | 123 | tx[0] = reg; |
| 111 | tx[1] = data; | 124 | tx[1] = data; |
| 125 | xprintf("page display: %X\n", page); | ||
| 112 | return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); | 126 | return i2cMasterTransmitTimeout(&I2CD1, IS31_ADDR_DEFAULT, tx, 2, NULL, 0, US2ST(IS31_TIMEOUT)); |
| 113 | } | 127 | } |
| 114 | 128 | ||
| @@ -160,98 +174,267 @@ static THD_FUNCTION(LEDthread, arg) { | |||
| 160 | (void)arg; | 174 | (void)arg; |
| 161 | chRegSetThreadName("LEDthread"); | 175 | chRegSetThreadName("LEDthread"); |
| 162 | 176 | ||
| 163 | uint8_t i; | 177 | uint8_t i, page; |
| 164 | uint8_t temp, pwm; | 178 | |
| 165 | uint8_t save_page, save_breath1, save_breath2; | 179 | //persistent status variables |
| 180 | uint8_t backlight_status, lock_status, led_step, active_layer; | ||
| 181 | uint8_t led_control_reg[0x13] = {0};//led control register start address + 0x12 bytes | ||
| 182 | |||
| 183 | //mailbox variables | ||
| 184 | uint8_t temp, msg_type, msg_led; | ||
| 185 | msg_t msg; | ||
| 186 | |||
| 187 | /* //control register variables | ||
| 188 | uint8_t page, save_page, save_breath1, save_breath2; | ||
| 166 | msg_t msg, retval; | 189 | msg_t msg, retval; |
| 190 | */ | ||
| 191 | |||
| 192 | // initialize persistent variables | ||
| 193 | backlight_status = 0; | ||
| 194 | lock_status = 0;//TODO: does keyboard remember locks? | ||
| 195 | led_step = 4; //full brightness | ||
| 196 | active_layer = 0; | ||
| 167 | 197 | ||
| 168 | while(true) { | 198 | while(true) { |
| 169 | // wait for a message (asynchronous) | 199 | // wait for a message (asynchronous) |
| 170 | // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't | 200 | // (messages are queued (up to LED_MAILBOX_NUM_MSGS) if they can't |
| 171 | // be processed right away) | 201 | // be processed right away) |
| 172 | chMBFetch(&led_mailbox, &msg, TIME_INFINITE); | 202 | chMBFetch(&led_mailbox, &msg, TIME_INFINITE); |
| 203 | msg_type = (msg >> 8) & 0xFF; //first byte is msg type | ||
| 204 | msg_led = (msg) & 0xFF; //second byte is action information | ||
| 173 | 205 | ||
| 174 | // process 'msg' here | ||
| 175 | // if msg between 0-7, then process as page#, otherwise a specific LED address | ||
| 176 | xprintf("--------------------\n"); | 206 | xprintf("--------------------\n"); |
| 177 | xprintf("mailbox fetch\ntemp: %X - msg: %X\n", temp, msg); | 207 | xprintf("mailbox fetch\nmsg: %X\n", msg); |
| 178 | if (msg < 8) { | 208 | xprintf("type: %X - led: %X\n", msg_type, msg_led); //test if msg_type is 1 or 2 bytes after mask |
| 179 | 209 | switch (msg_type){ | |
| 180 | // read current page into 'temp' | 210 | case KEY_LIGHT: |
| 181 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); | 211 | //TODO: lighting key led on keypress |
| 182 | chThdSleepMilliseconds(1); | 212 | break; |
| 183 | // If page is already in layer, switch off (layer 0) | 213 | |
| 184 | xprintf("Layer: post-read\ntemp: %X\n", temp); | 214 | case TOGGLE_LED: |
| 185 | if(temp == msg) { | 215 | //TODO: toggle existing indicator off, or let user do this, but write frame 7 for every led change |
| 186 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); | 216 | //turn on single led, msg_led = row/col of led |
| 187 | } else { | 217 | set_led_bit(led_control_reg, msg_led, 1); |
| 188 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg); | 218 | |
| 189 | } | 219 | is31_write_data (7, led_control_reg, 0x12+1); |
| 190 | xprintf("Layer: post-change\ntemp: %X\n", temp); | 220 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); |
| 191 | 221 | active_layer = 7; | |
| 192 | } else { | 222 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); |
| 193 | 223 | xprintf("page display: %X\n", temp); | |
| 194 | switch(msg) { | 224 | break; |
| 195 | //TODO: make this generic and able to turn on/off any address and loop through all(or current) pages | 225 | |
| 196 | //TODO: set number of layers somewhere and loop through all when setting specific led | 226 | case TOGGLE_ALL: |
| 197 | case LED_MSG_SLEEP_LED_ON: | 227 | xprintf("TOGGLE_ALL\n"); |
| 198 | // save current settings | 228 | //msg_led = unused, TODO: consider using msg_led to toggle layer display |
| 199 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); | 229 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); |
| 200 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); | 230 | |
| 201 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); | 231 | xprintf("temp: %X\n", temp); |
| 202 | // use pages 7 and 8 for (hardware) breathing (assuming they're empty) | 232 | //if LED_ALL is on then toggle off, any other layer, turn on LED_ALL |
| 203 | is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); | 233 | if(temp == 1) { |
| 204 | is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); | 234 | xprintf("page display true: %X\n", temp); |
| 205 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); | 235 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 0); |
| 206 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); | 236 | } else { |
| 207 | retval = MSG_TIMEOUT; | 237 | xprintf("page display false: %X\n", temp); |
| 208 | temp = 6; | 238 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 1); |
| 209 | while(retval == MSG_TIMEOUT) { | 239 | } |
| 210 | // switch to the other page | 240 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); |
| 211 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); | 241 | xprintf("page display: %X\n", temp); |
| 212 | temp = (temp == 6 ? 7 : 6); | 242 | break; |
| 213 | // the times should be sufficiently long for IS31 to finish switching pages | 243 | |
| 214 | retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); | 244 | case TOGGLE_BACKLIGHT: |
| 245 | //msg_led = unused | ||
| 246 | backlight_status ^= 1; | ||
| 247 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); | ||
| 248 | active_layer = temp; | ||
| 249 | |||
| 250 | page = backlight_status == 0 ? 0 : active_layer; | ||
| 251 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, page); | ||
| 252 | break; | ||
| 253 | |||
| 254 | case TOGGLE_LAYER_LEDS://show layer indicator or full map of layer keys. | ||
| 255 | //TODO: change so user can flag which they want, indiv or full map in fn_actions | ||
| 256 | //msg_led = layer to toggle on | ||
| 257 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &temp); | ||
| 258 | |||
| 259 | if(temp == msg_led) { | ||
| 260 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); | ||
| 261 | active_layer = 7; | ||
| 262 | } else { | ||
| 263 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, msg_led); | ||
| 264 | active_layer = msg_led; | ||
| 265 | } | ||
| 266 | break; | ||
| 267 | |||
| 268 | case TOGGLE_LOCK_LED: | ||
| 269 | //msg_led = 0-3 for lock flags | ||
| 270 | lock_status ^= msg_led; //TODO: confirm toggling works and doesn't get out of sync | ||
| 271 | set_lock_leds(led_control_reg, lock_status); | ||
| 272 | break; | ||
| 273 | |||
| 274 | case MODE_BREATH: | ||
| 275 | break; | ||
| 276 | case STEP_BRIGHTNESS: | ||
| 277 | //pwm_levels[] bounds checking, loop through array | ||
| 278 | //TODO: find a cleaner way to walk through this logic | ||
| 279 | if (msg_led == 0) { | ||
| 280 | if (led_step == 0) { | ||
| 281 | led_step = 4; | ||
| 282 | } else { | ||
| 283 | led_step--; | ||
| 215 | } | 284 | } |
| 216 | // received a message (should be a wakeup), so restore previous state | 285 | } else { |
| 217 | chThdSleepMilliseconds(3000); // need to wait until the page change finishes | 286 | if (led_step == 4) { |
| 218 | // note: any other messages are queued | 287 | led_step = 0; |
| 219 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); | 288 | } else { |
| 220 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); | 289 | led_step++; |
| 221 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); | 290 | } |
| 222 | break; | 291 | } |
| 223 | case LED_MSG_SLEEP_LED_OFF: | 292 | |
| 224 | // should not get here; wakeup should be received in the branch above break; | 293 | //TODO: this seems a messy way to populate the pwm register |
| 225 | break; | 294 | //populate the 9 byte rows to be written to each pin, first byte is register (pin) address |
| 226 | default: | 295 | for(i=1; i<9; i++) { |
| 227 | if(msg >= 0x24) { | 296 | pwm_reg_array[i]=pwm_levels[led_step]; |
| 228 | xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); | 297 | } |
| 298 | for(i=0; i<8; i++) { | ||
| 299 | pwm_reg_array[0] = 0x24 + (i * 0x10);//first byte of 9 bytes must be register address | ||
| 300 | is31_write_data(0, pwm_reg_array, 9); | ||
| 301 | chThdSleepMilliseconds(5); | ||
| 302 | } | ||
| 303 | break; | ||
| 304 | |||
| 305 | /* case LED_MSG_SLEEP_LED_ON: | ||
| 306 | // save current settings | ||
| 307 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, &save_page); | ||
| 308 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, &save_breath1); | ||
| 309 | is31_read_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, &save_breath2); | ||
| 310 | // use pages 7 and 8 for (hardware) breathing (assuming they're empty) | ||
| 311 | is31_write_register(6, BREATHE_LED_ADDRESS, 0xFF); | ||
| 312 | is31_write_register(7, BREATHE_LED_ADDRESS, 0x00); | ||
| 313 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (6<<4)|6); | ||
| 314 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); | ||
| 315 | retval = MSG_TIMEOUT; | ||
| 316 | temp = 6; | ||
| 317 | while(retval == MSG_TIMEOUT) { | ||
| 318 | // switch to the other page | ||
| 319 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, temp); | ||
| 320 | temp = (temp == 6 ? 7 : 6); | ||
| 321 | // the times should be sufficiently long for IS31 to finish switching pages | ||
| 322 | retval = chMBFetch(&led_mailbox, &msg, MS2ST(temp == 6 ? 4000 : 6000)); | ||
| 323 | } | ||
| 324 | // received a message (should be a wakeup), so restore previous state | ||
| 325 | chThdSleepMilliseconds(3000); // need to wait until the page change finishes | ||
| 326 | // note: any other messages are queued | ||
| 327 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, save_breath1); | ||
| 328 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, save_breath2); | ||
| 329 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, save_page); | ||
| 330 | break; | ||
| 331 | case LED_MSG_SLEEP_LED_OFF: | ||
| 332 | // should not get here; wakeup should be received in the branch above break; | ||
| 333 | break; | ||
| 334 | default: | ||
| 335 | //TODO: individual led state unchanged if page arrays are selected in code above | ||
| 336 | //avoidable if full pages are written on the fly | ||
| 337 | //or use pg8 for individual leds, have pointer to currently on led address for toggling | ||
| 338 | if (msg == 0x59 || msg == 0x84) { | ||
| 339 | //toggle lock keys on all layers | ||
| 340 | for (i=0,i<8,i++) { | ||
| 229 | is31_read_register(0, msg, &temp); | 341 | is31_read_register(0, msg, &temp); |
| 230 | chThdSleepMilliseconds(10); | ||
| 231 | xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); | ||
| 232 | chThdSleepMilliseconds(10); | ||
| 233 | pwm = (temp > 0x00 ? 0x00 : 0xFF); | 342 | pwm = (temp > 0x00 ? 0x00 : 0xFF); |
| 234 | xprintf("pwm after: %X\n", pwm); | 343 | is31_write_register(i,msg,pwm); |
| 235 | chThdSleepMilliseconds(10); | 344 | } |
| 236 | for(i=0; i<8; i++) { | 345 | |
| 237 | is31_write_register(i, msg, pwm); | 346 | } else if(msg >= 0x24) { |
| 238 | } | 347 | xprintf("Power pre-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); |
| 239 | xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); | 348 | is31_read_register(7, msg, &temp); |
| 240 | chThdSleepMilliseconds(10); | 349 | xprintf("Post-read\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); |
| 350 | if (msg == active_led) { | ||
| 351 | //toggle led power | ||
| 352 | pwm = (temp > 0x00 ? 0x00 : 0xFF); | ||
| 353 | |||
| 354 | //Use 8th led page for individual led indicators | ||
| 355 | is31_write_register(7, msg, pwm); | ||
| 356 | } else { | ||
| 357 | is31_write_register(7, active_led, 0x00); | ||
| 358 | is31_write_register(7, msg, 0xFF); | ||
| 359 | } | ||
| 360 | xprintf("Power post-change\ntemp: %X - msg: %X - pwm: %X\n", temp, msg, pwm); | ||
| 361 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_PICTDISP, 7); | ||
| 241 | } | 362 | } |
| 242 | break; | 363 | break; |
| 243 | } | 364 | */ |
| 244 | } | 365 | } |
| 245 | xprintf("--------------------\n"); | 366 | xprintf("--------------------\n"); |
| 246 | } | 367 | } |
| 247 | } | 368 | } |
| 369 | |||
| 370 | |||
| 371 | /* ======================== | ||
| 372 | * led bit processing | ||
| 373 | * ======================== */ | ||
| 374 | void set_led_bit (uint8_t *led_control_reg, uint8_t msg_led, uint8_t toggle_on) { | ||
| 375 | uint8_t row_byte, column_bit; | ||
| 376 | //msg_led tens column is pin#, A-control register is every other 8 bits | ||
| 377 | //ones column is bit position in 8-bit mask | ||
| 378 | //control register will be one bit shifted into position along register's full 0x12 bytes | ||
| 379 | ////first byte is register address 0x00 | ||
| 380 | row_byte = ((msg_led / 10) % 10 - 1 ) * 2 + 1; | ||
| 381 | column_bit = 1<<(msg_led % 10 - 1); | ||
| 382 | |||
| 383 | if (toggle_on) { | ||
| 384 | led_control_reg[row_byte] |= 1<<(column_bit); | ||
| 385 | } else { | ||
| 386 | led_control_reg[row_byte] &= ~1<<(column_bit); | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | void set_lock_leds(uint8_t *led_control_reg, uint8_t lock_status) { | ||
| 391 | uint8_t i; | ||
| 392 | |||
| 393 | switch (lock_status) { | ||
| 394 | case 1: | ||
| 395 | set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1);//TODO: define lock addresses by matrix#, and loop for all frames | ||
| 396 | set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 0); | ||
| 397 | break; | ||
| 398 | case 2: | ||
| 399 | set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 0); | ||
| 400 | set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); | ||
| 401 | break; | ||
| 402 | case 3: | ||
| 403 | set_led_bit(led_control_reg, NUM_LOCK_LED_ADDRESS, 1); | ||
| 404 | set_led_bit(led_control_reg, CAPS_LOCK_LED_ADDRESS, 1); | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | |||
| 408 | for(i=1; i<8; i++) { //keep LED_OFF layer all off, including locks | ||
| 409 | is31_write_data (i, led_control_reg, 0x12+1); | ||
| 410 | chThdSleepMilliseconds(5); | ||
| 411 | } | ||
| 412 | } | ||
| 413 | |||
| 414 | void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count) { | ||
| 415 | //TODO: init function that accepts array of led addresses and sets them by row | ||
| 416 | uint8_t i; | ||
| 417 | uint8_t row, col; | ||
| 418 | uint8_t temp_control_reg[0x13] = {0};//led control register start address + 0x12 bytes | ||
| 419 | xprintf("-------------\n"); | ||
| 420 | xprintf("write page %X\n", page); | ||
| 421 | |||
| 422 | for(i=0;i<led_count;i++){ | ||
| 423 | row = ((led_array[i] / 10) % 10 - 1 ) * 2 + 1;//includes 1 byte shift for 0x00 address | ||
| 424 | col = 1<<(led_array[i] % 10 - 1); | ||
| 425 | |||
| 426 | temp_control_reg[row] |= 1<<(col); | ||
| 427 | } | ||
| 428 | |||
| 429 | is31_write_data(page, temp_control_reg, 0x13); | ||
| 430 | xprintf("-------------\n"); | ||
| 431 | } | ||
| 248 | /* ===================== | 432 | /* ===================== |
| 249 | * hook into user keymap | 433 | * hook into user keymap |
| 250 | * ===================== */ | 434 | * ===================== */ |
| 251 | void led_controller_init(void) { | 435 | void led_controller_init(void) { |
| 252 | uint8_t i; | 436 | uint8_t i; |
| 253 | 437 | ||
| 254 | xprintf("led_controller_init"); | ||
| 255 | /* initialise I2C */ | 438 | /* initialise I2C */ |
| 256 | /* I2C pins */ | 439 | /* I2C pins */ |
| 257 | palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL | 440 | palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATIVE_2); // PTB0/I2C0/SCL |
| @@ -275,14 +458,18 @@ void led_controller_init(void) { | |||
| 275 | is31_write_data(i, full_page, 1+0x12); | 458 | is31_write_data(i, full_page, 1+0x12); |
| 276 | } | 459 | } |
| 277 | 460 | ||
| 461 | //set Display Option Register so all pwm intensity is controlled from Frame 1 | ||
| 462 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_DISPLAYOPT, IS31_REG_DISPLAYOPT_INTENSITY_SAME); | ||
| 463 | |||
| 278 | /* enable breathing when the displayed page changes */ | 464 | /* enable breathing when the displayed page changes */ |
| 279 | // Fade-in Fade-out, time = 26ms * 2^N, N=3 | 465 | // Fade-in Fade-out, time = 26ms * 2^N, N=3 |
| 280 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (3<<4)|3); | 466 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL1, (3<<4)|3); |
| 281 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); | 467 | is31_write_register(IS31_FUNCTIONREG, IS31_REG_BREATHCTRL2, IS31_REG_BREATHCTRL2_ENABLE|3); |
| 282 | 468 | ||
| 283 | // clean up the capslock LED | 469 | // clean up the lock LEDs |
| 284 | is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); | 470 | //TODO: adjust for new addressing and additional frames |
| 285 | is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); | 471 | //is31_write_register(1, CAPS_LOCK_LED_ADDRESS, 0); |
| 472 | //is31_write_register(2, CAPS_LOCK_LED_ADDRESS, 0); | ||
| 286 | 473 | ||
| 287 | /* more time consuming LED processing should be offloaded into | 474 | /* more time consuming LED processing should be offloaded into |
| 288 | * a thread, with asynchronous messaging. */ | 475 | * a thread, with asynchronous messaging. */ |
diff --git a/keyboards/infinity60/led_controller.h b/keyboards/infinity60/led_controller.h index 7db02389f..75819ec4e 100644 --- a/keyboards/infinity60/led_controller.h +++ b/keyboards/infinity60/led_controller.h | |||
| @@ -26,12 +26,15 @@ msg_t is31_write_data(uint8_t page, uint8_t *buffer, uint8_t size); | |||
| 26 | msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data); | 26 | msg_t is31_write_register(uint8_t page, uint8_t reg, uint8_t data); |
| 27 | msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); | 27 | msg_t is31_read_register(uint8_t page, uint8_t reg, uint8_t *result); |
| 28 | 28 | ||
| 29 | /* ========================= | 29 | /* ============================ |
| 30 | * init functions | 30 | * init functions/definitions |
| 31 | * ========================= */ | 31 | * ============================*/ |
| 32 | 32 | ||
| 33 | void led_controller_init(void); | 33 | void led_controller_init(void); |
| 34 | 34 | ||
| 35 | #define CAPS_LOCK_LED_ADDRESS 0x46 | ||
| 36 | #define NUM_LOCK_LED_ADDRESS 0x85 | ||
| 37 | |||
| 35 | /* ============================= | 38 | /* ============================= |
| 36 | * IS31 chip related definitions | 39 | * IS31 chip related definitions |
| 37 | * ============================= */ | 40 | * ============================= */ |
| @@ -82,20 +85,26 @@ void led_controller_init(void); | |||
| 82 | 85 | ||
| 83 | #define IS31_TIMEOUT 10000 // needs to be long enough to write a whole page | 86 | #define IS31_TIMEOUT 10000 // needs to be long enough to write a whole page |
| 84 | 87 | ||
| 85 | /* ============================== | 88 | /* ======================================== |
| 86 | * LED Thread related definitions | 89 | * LED Thread related definitions/functions |
| 87 | * ============================== */ | 90 | * ========================================*/ |
| 88 | 91 | ||
| 89 | extern mailbox_t led_mailbox; | 92 | extern mailbox_t led_mailbox; |
| 90 | 93 | ||
| 94 | void set_led_bit (uint8_t *led_control_reg, uint8_t led_msg, uint8_t toggle_on); | ||
| 95 | void set_lock_leds (uint8_t *led_control_reg, uint8_t lock_status); | ||
| 96 | void write_led_page (uint8_t page, const uint8_t *led_array, uint8_t led_count); | ||
| 97 | |||
| 91 | // constants for signaling the LED controller thread | 98 | // constants for signaling the LED controller thread |
| 92 | enum led_msg_t { | 99 | enum led_msg_t { |
| 93 | LED_MSG_CAPS_ON, | 100 | KEY_LIGHT, |
| 94 | LED_MSG_CAPS_OFF, | 101 | TOGGLE_LED, |
| 95 | LED_MSG_SLEEP_LED_ON, | 102 | TOGGLE_ALL, |
| 96 | LED_MSG_SLEEP_LED_OFF, | 103 | TOGGLE_BACKLIGHT, |
| 97 | LED_MSG_ALL_TOGGLE, | 104 | TOGGLE_LAYER_LEDS, |
| 98 | LED_MSG_GAME_TOGGLE | 105 | TOGGLE_LOCK_LED, |
| 106 | MODE_BREATH, | ||
| 107 | STEP_BRIGHTNESS | ||
| 99 | }; | 108 | }; |
| 100 | 109 | ||
| 101 | #endif /* _LED_CONTROLLER_H_ */ | 110 | #endif /* _LED_CONTROLLER_H_ */ |
