Author Topic: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK  (Read 2596 times)

0 Members and 1 Guest are viewing this topic.

Offline richfiles

  • Thread Starter
  • Posts: 222
  • Location: MN, USA
167927-0

I have a keyboard project that's sat rather... stagnant for almost a year. The main keyboard is complete, and has been for a year, save for firmware. A sin, I know... The issue is that I'm a hardware guy... The last programming I dis was on a TI-89 calculator, and before that, on the Commodore 128. All I ever knew was BASIC, and even that's been a decade and a half since I even looked at it. I picked up this keyboard project, as well as a project to build a Kerbal Space Program instrument/control panel, to make myself learn C... Only I've not made much progress. Things got busy at work, I got on a roll working on the KSP controller, I got injured at work, then my motherboard died... All in all, a full year has passed since I "finished" my keyboard. It still has no firmware, and though I did finally get the plate to build the number pad, I still have not finished it yet.

My goals are:

A: To initially get a functioning firmware on my main keyboard, so I can ACTUALLY USE IT!
B: To figure out a way to be able to poll/not poll a port expander over I2C, based on the logic level of a "sense" signal.

So, here's my progress so far.

First, I've made up a nice layout worksheet that has all the electrical rows and columns identified not he physical layout. It's top down view, so it'll be useful for defining my key layout too.

167929-1

So, I did start with the TMK firmware. If it can do everything I need it to do, then I'll stick with it, but there's always the option of re-flashing the keyboard with something else in the future if I can't integrate the hot swappable port expander functionality into the code. The code for my Column and Row pin definitions are below:

Code: [Select]
/* Column pin configuration
 * col: 0   1   2   3   4   5   6   7   8   9   10  11  12
 * pin: F0  F1  F4  F5  F6  D4  D5  D2  B7  B3  B2  B1  B0

Code: [Select]
/* Row pin configuration
 * row: 0   1   2   3   4   5   6
 * pin: F7  B6  B5  B4  C7  C6  D3

I have a VERY dense matrix of 13x7. It was necessary to keep enough I/O pins open for the Caps Lock LED, Backlight LED PWM, a pair of I2C pins, and the numpad sense pin. The sense pin detects if the number pad is attached, and whether or not it should poll the numpad's port expander over I2C. I figure, software is changeable, so I can re-do code later, once I actually have the number pad built, and have half a clue what the heck I'm actually doing.

Anyway, since I had to keep the matrix small, That super dense layout has almost no gaps, and row 6 is actually a tight cluster of keys in the top right corner. An alteration part way in resulted in the very top right key having a completely nonsensical matrix position, because the change was literally a bodge. Only three intersections in the entire matrix go unused (c0-r6, c1-r6, and c12-r4). This means my matrix does not directly conform to the physical key layout in some areas (all of Row 6 is in the top right corner, and the bottom row is "electrically" compressed to the left, and then includes the keys physically in the bottom right corner well).

Now, I'm stumped at my current place in the code...

What have not figured out yet, is whether the matrix definitions need to be ordered by electrical sequence, or if the values are arbitrary, and allow for physical sequence (as long as the row and column values are correctly defined). The obviously functional way is to lay the matrix out electrically. This seems to be what's assumed with most keyboards, as most keyboards physical layout and electrical layout probably match.

My question then is which (either, or both, or neither, or 42   ;D ) would be correct?

Electrically based layout:
Code: [Select]
#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, \
    K40, K41, K42, K43, K44, K45, K46, K47, K48, K49, K4A, K4B,     \
    K50, K51, K52, K53, K54, K55, K56, K57, K58, K59, K5A, K5B, K5C, \
              K62, K63, K64, K65, K66, K67, K68, K69, K6A, K6B, K6C  \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C }, \
    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C }, \
    { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47, KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_NO    }, \
    { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57, KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C }, \
    { KC_NO,    KC_NO,    KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67, KC_##K68, KC_##K69, KC_##K6A, KC_##K6B, KC_##K6C }  \
}

or...

Physically based layout
Code: [Select]
#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K62, K6B, K6C, K65, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K63,      K69, K6A, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K64,      K67, K68, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C,           K5C, K66, \
    K40,      K41, K42, K43, K44, K45, K46, K47, K48, K49, K4A, K4B,           K5A, K5B, \
    K50, K51, K52,                K53,                K54, K55, K56,      K57, K58, K59  \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K62, KC_##K6B, KC_##K6C, KC_##K65 }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K63, KC_NO,    KC_##K69, KC_##K6A }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K64, KC_NO,    KC_##K67, KC_##K68 }, \
    { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_NO,    KC_NO,    KC_##K5C, KC_##K66 }, \
    { KC_##K40, KC_NO,    KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47, KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_NO,    KC_NO,    KC_##K5A, KC_##K5B}, \
    { KC_##K50, KC_##K51, KC_##K52, KC_NO,    KC_NO,    KC_NO,    KC_##K53, KC_NO,    KC_NO,    KC_NO,    KC_##K54, KC_##K55, KC_##K56, KC_NO,    KC_##K57, KC_##K58, KC_##K59 }  \

}

My question is, are the values entered into the table above dependent on position in the list, or just by content. It'd be FAR easier to follow the second layout, but I don't know if it screws with the code to mix and match rows and columns onto different lines in the list like that, or whether it's all good, as long as the numbers match.

My understanding of the code, is that those lists are not "technically" even different lines... That they are basically one long continuous list, with breaks to make it easier to read. What I don't know is whether the code expects to read the list strictly sequentially, the same way it's scanning the matrix, or whether the code is simply defining the physical layout of the key map and defining what matrix intersection applies to the physical layout. I'm confused!

Basically, is the code:

A: expecting all the rows and columns to be in a neat and orderly incrementing layout (all the columns, in order, 0 to the maximum, for row 0, then repeating for row 1, 2, 3... and so on)

or

B: Is this list arbitrarily defining the row/column intersection values for the (later to be entered) keymap, based on the row and column numbers entered. Basically, saying "I want this layout to have r0-c0 through r0-c12, then r6-c3, r6-c11, r6-c12, and finally r6-c5 in the first physical row of keys"... Basically, so later, when I enter the keymap, it knows that ESC is r0-c0, F1-F12 is r0-c1 through r0-c12, and that F13 is r6c3, F14 is r6-c11, F15 is r6-c12, and the media EJECT key is r6-c5 (using my top row as an example).

Does that make sense?   :confused:

I suppose I should also add, I know software is flexible, and I can always integrate new features later on. For now, I just wanna get my keyboard up and running. It's been a YEAR! Numberpad detachment/attachment is something that can be dealt with after the fact. For now, I just want things up and running. I haven't even wired the numberpad yet.

In the long term though, I want to have the code check whether pin E6 changes states. Depending on whether it is high or low, I want to have it scan a 6x6 matrix on a port expander connected over I2C, or to skip the I2C part of the code altogether and ignore that part of the matrix. I don't yet know how I would go about doing this in the code, and I don't even know if this firmware can even be modded to support it at all. Of course, that's the nice thing about software... There's always room for change. I just don't know how.  :rolleyes:

I think, for the transistor driven under-lighting LEDs in each switch housing, I just want to have a default minimum brightness setting at power up, and the option to change the brightness with the keyboard. I already have the max brightness current limited to stay under the USB max current, but I think at power up it'd be wise to keep total draw under 200 mA, and then let the keyboard negotiate 500 mA if you increase brightness... Again, I imagine it's possible, but I don't know if TMK can do it, or how easy it'd be to mod that functionality in. I just don't want the keyboard to require an external power source to power all the LEDs, nor do I want it to trigger "The USB device is drawing too much power" warnings. It'd be nice if it were possible to cap max brightness based on USB power negotiation. I know devices can request up to 500 mA, but initial connections default to 100 mA (if the devices play friendly with he protocol).
« Last Edit: Sun, 07 May 2017, 18:15:30 by richfiles »
"75% + 1" Keyboard with "Danger Zone" keycaps and magnetically detachable Number Pad. Dyed Gateron Blue switches with amber sub lighting. Blue anodized plate and wood trim. (Firmware in Progress)
Bluetooth Apple //c keyboard with Alps SKCM Amber Switches. (Build in Progress)

Offline richfiles

  • Thread Starter
  • Posts: 222
  • Location: MN, USA
Re: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK
« Reply #1 on: Tue, 09 May 2017, 11:21:32 »
You know... I think for the sakes of just getting this thing up and running, I'm going to select option A, even though layout wise, it's unintuitive. It's intuitive in terms of electrical layout, not physical layout. That's because my electrical matrix kinda jumps around all over the place on the right side of the keyboard, where row 6 and the end of row 5 are all jumbled up into the right two columns.

I guess I KNOW sticking with the electrical layout WOULD work, and I can stick with the electrical layout with the character map as well. I just never got an answer in regards to if a physical layout based map would work, or if it'd "confuse' the firmware.
"75% + 1" Keyboard with "Danger Zone" keycaps and magnetically detachable Number Pad. Dyed Gateron Blue switches with amber sub lighting. Blue anodized plate and wood trim. (Firmware in Progress)
Bluetooth Apple //c keyboard with Alps SKCM Amber Switches. (Build in Progress)

Offline Tactile

  • Posts: 1435
  • Location: Portland, OR
Re: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK
« Reply #2 on: Tue, 09 May 2017, 12:04:16 »
I don't know if this will help but here's a bit of the *.h file for my GH60 Rev C for you to look at. I'm using QMK instead of TMK but for this example I don't think that matters. Especially note the key at the right end of the top row; the way the PCB is designed electrically this one is "out of sequence". And also note that I had to swap two switches to get the split right shift to work the way I wanted, again to accommodate the electrical design of the PCB.
Code: [Select]
/* GH60 keymap definition macro
 * K2C, K31 and  K3C are extra keys for ISO
 *
 * This has been modified by me to match the physical layout of my GH60c
 * All extra keys have been removed and ##K3C/##K3D reversed here
 * to match my keyboard (FN is on the outside, right shift is inside)
 * K49 at the right end of the top row is the split backspace
 * and we have a 7U spacebar with only 3 switches on either side
 */
#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K49, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, \
    K30,      K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
    K40, K41, K42,           K45,                          K4B, K4C, K4D  \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D }, \
    { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_NO, KC_##K2D }, \
    { KC_##K30, KC_NO, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3D, KC_##K3C }, \
    { KC_##K40, KC_##K41, KC_##K42, KC_NO,    KC_NO,    KC_##K45, KC_NO,    KC_NO,    KC_NO,    KC_##K49, KC_NO, KC_##K4B, KC_##K4C, KC_##K4D }  \
}
REΛLFORCE

Offline richfiles

  • Thread Starter
  • Posts: 222
  • Location: MN, USA
Re: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK
« Reply #3 on: Wed, 10 May 2017, 11:25:06 »
That's some interesting information to absorb. It seems arbitrary order is acceptable in QMK... What is actually different than QMK and TMK? Regardless, my plan is simply to try it, hopefully very soon. I'm beyond tired of this keyboard being a paperweight, and would like to see some life in it. Definitely appreciate the info!  :thumb:

Now to figure out if there's an simple way to insert an I2C port expander scan into the matrix scan, that ONLY occurs if a port if a particular input is set to a desired logic level...
"75% + 1" Keyboard with "Danger Zone" keycaps and magnetically detachable Number Pad. Dyed Gateron Blue switches with amber sub lighting. Blue anodized plate and wood trim. (Firmware in Progress)
Bluetooth Apple //c keyboard with Alps SKCM Amber Switches. (Build in Progress)

Offline Tactile

  • Posts: 1435
  • Location: Portland, OR
Re: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK
« Reply #4 on: Wed, 10 May 2017, 18:33:36 »
What is actually different than QMK and TMK?

The QMK (which is based on TMK) people have added quite a few features. The only reason I'm using QMK on my GH60 is for the lights. The GH60 Rev C is not fully backlit but it does have a few LEDs. I want to be able to control the lights for layer indication, etc. and I just couldn't figure how to do that in TMK. QMK makes it easy, even for a dummy like me, to control the LEDs.
REΛLFORCE

Offline richfiles

  • Thread Starter
  • Posts: 222
  • Location: MN, USA
Re: TMK for a Hot-Splittable Keyboard? Trying to Understand TMK
« Reply #5 on: Wed, 10 May 2017, 20:40:57 »
Hmm... I'm only controlling a Caps Lock LED and a single unified backlight PWM. I'm going to have to control the numberpad backlight LEDs separately from the main keyboard's PWM pin. I'd have to control it over I2C. I have some small I2C DAC boards that I think would be ideal to control the numberpad LEDs by just commanding them to a particular level. There will be unused matrix positions on the number pad, so I could potentially use those for control of individual LEDs if I wanted to make indicators on the number pad someday. I have three spare matrix positions on the main keyboard. As of this moment, I'm not using any of those spare matrix positions for anything at all.

Being able to hot swap the I2C is going to be absolutely necessary for the numberpad to be able to detach and attach. What I really need, I think, is to have the ability to "skip" part of the matrix scan, based on whether the sense signal is high or low. No idea if TMK or QMK has any chance of being able to be modified to make checking a port expander over I2C an optional check, based on a conditional test.
"75% + 1" Keyboard with "Danger Zone" keycaps and magnetically detachable Number Pad. Dyed Gateron Blue switches with amber sub lighting. Blue anodized plate and wood trim. (Firmware in Progress)
Bluetooth Apple //c keyboard with Alps SKCM Amber Switches. (Build in Progress)