Optimize matrix scanning (#343)

example_keyboards
Eric Tang 9 years ago committed by Jack Humbert
parent d66aa0abf9
commit aaa758f1d3

@ -51,11 +51,11 @@ A problem arises when you start pressing more than one key at a time. Looking at
x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1)
| | | | | | | |
x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3)
Remember that this ^ is still connected to row1 Remember that this ^ is still connected to row1
The data we get from that is: The data we get from that is:
col0: 0b11 col0: 0b11
col1: 0b11 col1: 0b11
│└row0 │└row0
@ -73,7 +73,7 @@ Which isn't accurate, since we only have 3 keys pressed down, not all 4. This be
│ │ | │ │ │ | │
(key2) (key3) (key2) (key3) (key2) (key3) (key2) (key3)
! ! ! ! ! ! ! !
row1 ─────┴────────┘ row1 ─────┴────────┘ row1 ─────┴────────┘ row1 ─────┴────────┘
In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|` In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|`
@ -89,10 +89,10 @@ Now when we press the three keys, invoking what would be a ghosting scenario:
│ │ │ │ │ │ │ │
(key2) (┌─┘3) (key2) (┌─┘3) (key2) (┌─┘3) (key2) (┌─┘3)
! ! ! ! ! ! ! !
row1 ─────┴────────┘ x row1 ─────┴────────┘ row1 ─────┴────────┘ x row1 ─────┴────────┘
Things act as they should! Which will get us the following data: Things act as they should! Which will get us the following data:
col0: 0b01 col0: 0b01
col1: 0b11 col1: 0b11
│└row0 │└row0
@ -106,7 +106,7 @@ The firmware can then use this correct data to detect what it should do, and eve
When starting this, you should have all of your stabilisers and keyswitches already installed (and optionally keycaps). If you're using a Cherry-type stabiliser (plate-mounted only, obviously), you'll need to install that before your keyswitches. If you're using Costar ones, you can installed them afterwards. When starting this, you should have all of your stabilisers and keyswitches already installed (and optionally keycaps). If you're using a Cherry-type stabiliser (plate-mounted only, obviously), you'll need to install that before your keyswitches. If you're using Costar ones, you can installed them afterwards.
To make things easier on yourself, make sure all of the keyswitches are oriented the same way (if they can be - not all layouts support this). Despite this, it's important to remember that the contacts on the keyswitches are completely symmetrical. We'll be using the keyswitch's left side contact for wiring the rows, and the right side one for wiring the columns. To make things easier on yourself, make sure all of the keyswitches are oriented the same way (if they can be - not all layouts support this). Despite this, it's important to remember that the contacts on the keyswitches are completely symmetrical. We'll be using the keyswitch's left side contact for wiring the rows, and the right side one for wiring the columns.
Get your soldering iron heated-up and collect the rest of the materials from the part list at the beginning of the guide. Place your keyboard so that the bottoms of the keyswitches are accessible - it may be a good idea to place it on a cloth to protect your keyswitches/keycaps. Get your soldering iron heated-up and collect the rest of the materials from the part list at the beginning of the guide. Place your keyboard so that the bottoms of the keyswitches are accessible - it may be a good idea to place it on a cloth to protect your keyswitches/keycaps.
@ -155,7 +155,7 @@ When all of the diodes are completely soldered, it's a good idea to quickly insp
### Soldering the columns ### Soldering the columns
You'll have some options in the next process - it's a good idea to insulate the column wires (since the diodes aren't), but if you're careful enough, you can use exposed wires for the columns - it's not recommended, though. If you're using single-cored wire, stripping the plastic off of the whole wire and feeding it back on is probably the best option, but can be difficult depending on the size and materials. You'll want to leave parts of the wire exposed where you're going to be solder it onto the keyswitch. You'll have some options in the next process - it's a good idea to insulate the column wires (since the diodes aren't), but if you're careful enough, you can use exposed wires for the columns - it's not recommended, though. If you're using single-cored wire, stripping the plastic off of the whole wire and feeding it back on is probably the best option, but can be difficult depending on the size and materials. You'll want to leave parts of the wire exposed where you're going to be solder it onto the keyswitch.
If you're using stranded wire, it's probably easiest to just use a lot of small wires to connect each keyswitch along the column. It's possible to use one and melt through the insulation, but this isn't recommended, will produce even more harmful fumes, and can ruin your soldering iron. If you're using stranded wire, it's probably easiest to just use a lot of small wires to connect each keyswitch along the column. It's possible to use one and melt through the insulation, but this isn't recommended, will produce even more harmful fumes, and can ruin your soldering iron.
@ -195,15 +195,13 @@ You'll want to navigate to the `keyboard/<project_name>/` folder by typing, like
#### config.h #### config.h
The first thing we're going to want to modify is the `config.h` file. On line 32 and 33, you'll see `MATRIX_ROWS` and `MATRIX_COLS` - set both these variables to however many rows and columns you have on your keyboard. The first thing you're going to want to modify is the `config.h` file. Find `MATRIX_ROWS` and `MATRIX_COLS` and them to match the dimensions of your keyboard's matrix.
On line 38 and 39 you'll see the `COLS` and `ROWS` definitions - this is where you'll enter the pins you used, in order (left-to-right when looking at the top of the keyboard, but right-to-left when looking at the bottom).
There are some other variables that you'll be able to modify (lines 23-29), but it's not necessary to do that now (or ever, really). Farther down are `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`. Change their definitions to match how you wired up your matrix (looking from the top of the keyboard, the rows run top-to-bottom and the columns run left-to-right). Likewise, change the definition of `UNUSED_PINS` to match the pins you did not use (this will save power).
#### \<project_name\>.h #### \<project_name\>.h
The next file you'll want to look at is `<project_name>.h`. You're going to want to rewrite the `KEYMAP` definition - the format and syntax here is extremely important, so pay attention to how things are setup. The first half of the definition are considered the arguments - this is the format that you'll be following in your keymap later on, so you'll want to have as many k*xy* variables here as you do keys. The second half is the part that the firmware actually looks at, and will contain gaps depending on how you wired your matrix. The next file you'll want to look at is `<project_name>.h`. You're going to want to rewrite the `KEYMAP` definition - the format and syntax here is extremely important, so pay attention to how things are setup. The first half of the definition are considered the arguments - this is the format that you'll be following in your keymap later on, so you'll want to have as many k*xy* variables here as you do keys. The second half is the part that the firmware actually looks at, and will contain gaps depending on how you wired your matrix.
We'll dive into how this will work with the following example. Say we have a keyboard like this: We'll dive into how this will work with the following example. Say we have a keyboard like this:
@ -230,7 +228,7 @@ The middle column is unused on the bottom row in this example. Our `KEYMAP` defi
{ \ { \
{ k00, k01, k02 }, \ { k00, k01, k02 }, \
{ k10, KC_NO, k11 }, \ { k10, KC_NO, k11 }, \
} }
Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring. Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring.
@ -251,7 +249,7 @@ This would require our `KEYMAP` definition to look like this:
{ \ { \
{ k00, k01, k02 }, \ { k00, k01, k02 }, \
{ k10, k11, KC_NO }, \ { k10, k11, KC_NO }, \
} }
Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `KEYMAP` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it. Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `KEYMAP` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it.

@ -35,8 +35,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Planck PCB default pin-out // Planck PCB default pin-out
// Change this to how you wired your keyboard // Change this to how you wired your keyboard
// COLS: Left to right, ROWS: Top to bottom // COLS: Left to right, ROWS: Top to bottom
#define COLS (int []){ B0, B1, B2, B3, B7, D0, B6, F7, F6, F5, F4, F1 } #define MATRIX_ROW_PINS { F0, D6, D4, D5 }
#define ROWS (int []){ F0, D6, D4, D5 } #define MATRIX_COL_PINS { B0, B1, B2, B3, B7, D0, B6, F7, F6, F5, F4, F1 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -48,7 +49,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -41,15 +41,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
* *
*/ */
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 } #define MATRIX_ROW_PINS { D0, D5, B5, B6, C6 }
#define ROWS (int []){ D0, D5, B5, B6, C6 } #define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */ /* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
@ -62,17 +63,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Locking resynchronize hack */ /* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE #define LOCKING_RESYNC_ENABLE
/* /*
* Force NKRO * Force NKRO
* *
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.) * makefile for this to work.)
* *
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset. * until the next keyboard reset.
* *
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage. * fully operational during normal computer usage.
* *
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
@ -90,7 +91,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* the keyboard. They are best used in combination with the HID Listen program, * the keyboard. They are best used in combination with the HID Listen program,
* found here: https://www.pjrc.com/teensy/hid_listen.html * found here: https://www.pjrc.com/teensy/hid_listen.html
* *
* The options below allow the magic key functionality to be changed. This is * The options below allow the magic key functionality to be changed. This is
* useful if your keyboard/keypad is missing keys and you want magic key support. * useful if your keyboard/keypad is missing keys and you want magic key support.
* *
*/ */

@ -42,14 +42,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
* *
*/ */
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 } #define MATRIX_ROW_PINS { D0, D5, B5, B6, B3 }
#define ROWS (int []){ D0, D5, B5, B6, B3 } #define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */ /* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST

@ -36,11 +36,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Change this to how you wired your keyboard // Change this to how you wired your keyboard
// COLS: Left to right, ROWS: Top to bottom // COLS: Left to right, ROWS: Top to bottom
#if defined(ATREUS_ASTAR) #if defined(ATREUS_ASTAR)
#define COLS (int []){ D7, C6, B5, B4, E6, D4, B6, F6, F7, D6, B7 } # define MATRIX_ROW_PINS { D0, D1, D3, D2 }
#define ROWS (int []){ D0, D1, D3, D2 } # define MATRIX_COL_PINS { D7, C6, B5, B4, E6, D4, B6, F6, F7, D6, B7 }
# define UNUSED_PINS
#elif defined(ATREUS_TEENSY2) #elif defined(ATREUS_TEENSY2)
#define COLS (int []){ F6, F5, F4, B7, B6, B5, B4, B3, B2, B1, B0} # define MATRIX_ROW_PINS { D0, D1, D2, D3 }
#define ROWS (int []){ D0, D1, D2, D3 } # define MATRIX_COL_PINS { F6, F5, F4, B7, B6, B5, B4, B3, B2, B1, B0 }
# define UNUSED_PINS
#endif #endif
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
@ -53,7 +55,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define BACKLIGHT_LEVELS 3 //#define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -32,19 +32,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 5 #define MATRIX_ROWS 5
#define MATRIX_COLS 16 #define MATRIX_COLS 16
// COLS: Left to right, ROWS: Top to bottom // ROWS: Top to bottom, COLS: Left to right
/* Column pin configuration /* Column pin configuration
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* pin: B3 F1 F4 F5 F6 C7 C6 B6 B5 B4 D7 D6 D4 F7 B0 B1 * pin: B3 F1 F4 F5 F6 C7 C6 B6 B5 B4 D7 D6 D4 F7 B0 B1
*/ */
#define COLS (int []){ B3, F1, F4, F5, F6, C7, C6, B6, B5, B4, D7, D6, D4, F7, B0, B1 } #define MATRIX_COL_PINS { B3, F1, F4, F5, F6, C7, C6, B6, B5, B4, D7, D6, D4, F7, B0, B1 }
/* Row pin configuration
/* Row pin configuration * row: 0 1 2 3 4
* row: 0 1 2 3 4 * pin: D1 D0 D2 D5 D3
* pin: D1 D0 D2 D5 D3 */
*/ #define MATRIX_ROW_PINS { D1, D0, D2, D5, D3 }
#define ROWS (int []){ D1, D0, D2, D5, D3 } #define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -53,7 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -32,19 +32,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 10 #define MATRIX_ROWS 10
#define MATRIX_COLS 8 #define MATRIX_COLS 8
// COLS: Left to right, ROWS: Top to bottom // ROWS: Top to bottom, COLS: Left to right
/* Row pin configuration
* row: 0 1 2 3 4 5 6 7 8 9
* pin: B2 C7 C6 B6 B5 B0 B3 D5 D3 D2
*/
#define MATRIX_ROW_PINS { B2, C7, C6, B6, B5, B0, B3, D5, D3, D2 }
/* Column pin configuration /* Column pin configuration
* col: 0 1 2 3 4 5 6 7 * col: 0 1 2 3 4 5 6 7
* pin: F0 F1 F4 F5 F6 F7 E6 B1 * pin: F0 F1 F4 F5 F6 F7 E6 B1
*/ */
#define COLS (int []){ F0, F1, F4, F5, F6, F7, E6, B1 } #define MATRIX_COL_PINS { F0, F1, F4, F5, F6, F7, E6, B1 }
#define UNUSED_PINS
/* Row pin configuration
* row: 0 1 2 3 4 5 6 7 8 9
* pin: B2 C7 C6 B6 B5 B0 B3 D5 D3 D2
*/
#define ROWS (int []){ B2, C7, C6, B6, B5, B0, B3, D5, D3, D2 }
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -53,7 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -32,19 +32,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 5 #define MATRIX_ROWS 5
#define MATRIX_COLS 4 #define MATRIX_COLS 4
// COLS: Left to right, ROWS: Top to bottom // ROWS: Top to bottom, COLS: Left to right
/* Row pin configuration
* row: 0 1 2 3 4
* pin:
*/
#define MATRIX_ROW_PINS { B0, D3, D5, D4, D6 }
/* Column pin configuration /* Column pin configuration
* col: 0 1 2 3 * col: 0 1 2 3
* pin: F4 E6 B1 D2 * pin: F4 E6 B1 D2
*/ */
#define COLS (int []){ F4, E6, B1, D2 } #define MATRIX_COL_PINS { F4, E6, B1, D2 }
#define UNUSED_PINS
/* Row pin configuration
* row: 0 1 2 3 4
* pin:
*/
#define ROWS (int []){ B0, D3, D5, D4, D6 }
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -53,7 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Number of backlighting levels */ /* Number of backlighting levels */
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3

@ -41,15 +41,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
* *
*/ */
#define COLS (int []){ F0, F1, E6, C7, C6, B6, D4, B1, B7, B5, B4, D7, D6, B3 } #define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 }
#define ROWS (int []){ D0, D1, D2, D3, D5 } #define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B7, B5, B4, D7, D6, B3 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */ /* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
@ -62,17 +63,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Locking resynchronize hack */ /* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE #define LOCKING_RESYNC_ENABLE
/* /*
* Force NKRO * Force NKRO
* *
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.) * makefile for this to work.)
* *
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset. * until the next keyboard reset.
* *
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage. * fully operational during normal computer usage.
* *
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
@ -90,7 +91,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* the keyboard. They are best used in combination with the HID Listen program, * the keyboard. They are best used in combination with the HID Listen program,
* found here: https://www.pjrc.com/teensy/hid_listen.html * found here: https://www.pjrc.com/teensy/hid_listen.html
* *
* The options below allow the magic key functionality to be changed. This is * The options below allow the magic key functionality to be changed. This is
* useful if your keyboard/keypad is missing keys and you want magic key support. * useful if your keyboard/keypad is missing keys and you want magic key support.
* *
*/ */

@ -30,11 +30,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* key matrix size */ /* key matrix size */
#define MATRIX_ROWS 4 #define MATRIX_ROWS 4
#define MATRIX_COLS 13 #define MATRIX_COLS 13
/* Planck PCB default pin-out */ /* Planck PCB default pin-out */
#define COLS (int []){F4, D7, B5, B6, C6, C7, D4, D6, D5, D0, D1, D2, B0} #define MATRIX_ROW_PINS { F0, F1, F5, B4 }
#define ROWS (int []){F0, F1, F5, B4} #define MATRIX_COL_PINS { F4, D7, B5, B6, C6, C7, D4, D6, D5, D0, D1, D2, B0 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -46,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -33,8 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_COLS 12 #define MATRIX_COLS 12
/* Planck PCB default pin-out */ /* Planck PCB default pin-out */
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } #define MATRIX_ROW_PINS { D0, D5, B5, B6 }
#define ROWS (int []){ D0, D5, B5, B6 } #define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -46,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -33,8 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_COLS 12 #define MATRIX_COLS 12
/* Planck PCB default pin-out */ /* Planck PCB default pin-out */
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } #define MATRIX_ROW_PINS { D0, D5, B5, B6 }
#define ROWS (int []){ D0, D5, B5, B6 } #define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -46,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -33,8 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_COLS 12 #define MATRIX_COLS 12
/* Planck PCB default pin-out */ /* Planck PCB default pin-out */
#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } #define MATRIX_ROW_PINS { D2, D5, B5, B6, D3 }
#define ROWS (int []){ D2, D5, B5, B6, D3 } #define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -46,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 3 #define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE

@ -33,8 +33,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_COLS 8 #define MATRIX_COLS 8
// See note in retro_refit.h for an explanation of how this matrix is wired up // See note in retro_refit.h for an explanation of how this matrix is wired up
#define COLS (int []){ B0, B1, B2, B3, D2, D3, C7, D5 } #define MATRIX_ROW_PINS { D4, D7, B4, B5, B6, F7, F6, F5, F4, F1, F0 }
#define ROWS (int []){ D4, D7, B4, B5, B6, F7, F6, F5, F4, F1, F0 } #define MATRIX_COL_PINS { B0, B1, B2, B3, D2, D3, C7, D5 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
@ -46,7 +47,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BACKLIGHT_LEVELS 0 #define BACKLIGHT_LEVELS 0
/* Set 0 if debouncing isn't needed */ /* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ /* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE #define LOCKING_SUPPORT_ENABLE
@ -119,4 +120,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define NO_ACTION_MACRO //#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION //#define NO_ACTION_FUNCTION
#endif #endif

@ -1,70 +1,74 @@
#ifndef CONFIG_DEFINITIONS_H #ifndef CONFIG_DEFINITIONS_H
#define CONFIG_DEFINITIONS_H #define CONFIG_DEFINITIONS_H
#define B0 0x20 /* diode directions */
#define B1 0x21 #define COL2ROW 0
#define B2 0x22 #define ROW2COL 1
#define B3 0x23 /* I/O pins */
#define B4 0x24 #define B0 { .input_addr = 3, .bit = 0 }
#define B5 0x25 #define B1 { .input_addr = 3, .bit = 1 }
#define B6 0x26 #define B2 { .input_addr = 3, .bit = 2 }
#define B7 0x27 #define B3 { .input_addr = 3, .bit = 3 }
#define C0 0x30 #define B4 { .input_addr = 3, .bit = 4 }
#define C1 0x31 #define B5 { .input_addr = 3, .bit = 5 }
#define C2 0x32 #define B6 { .input_addr = 3, .bit = 6 }
#define C3 0x33 #define B7 { .input_addr = 3, .bit = 7 }
#define C4 0x34 #define C0 { .input_addr = 6, .bit = 0 }
#define C5 0x35 #define C1 { .input_addr = 6, .bit = 1 }
#define C6 0x36 #define C2 { .input_addr = 6, .bit = 2 }
#define C7 0x37 #define C3 { .input_addr = 6, .bit = 3 }
#define D0 0x40 #define C4 { .input_addr = 6, .bit = 4 }
#define D1 0x41 #define C5 { .input_addr = 6, .bit = 5 }
#define D2 0x42 #define C6 { .input_addr = 6, .bit = 6 }
#define D3 0x43 #define C7 { .input_addr = 6, .bit = 7 }
#define D4 0x44 #define D0 { .input_addr = 9, .bit = 0 }
#define D5 0x45 #define D1 { .input_addr = 9, .bit = 1 }
#define D6 0x46 #define D2 { .input_addr = 9, .bit = 2 }
#define D7 0x47 #define D3 { .input_addr = 9, .bit = 3 }
#define E0 0x50 #define D4 { .input_addr = 9, .bit = 4 }
#define E1 0x51 #define D5 { .input_addr = 9, .bit = 5 }
#define E2 0x52 #define D6 { .input_addr = 9, .bit = 6 }
#define E3 0x53 #define D7 { .input_addr = 9, .bit = 7 }
#define E4 0x54 #define E0 { .input_addr = 0xC, .bit = 0 }
#define E5 0x55 #define E1 { .input_addr = 0xC, .bit = 1 }
#define E6 0x56 #define E2 { .input_addr = 0xC, .bit = 2 }
#define E7 0x57 #define E3 { .input_addr = 0xC, .bit = 3 }
#define F0 0x60 #define E4 { .input_addr = 0xC, .bit = 4 }
#define F1 0x61 #define E5 { .input_addr = 0xC, .bit = 5 }
#define F2 0x62 #define E6 { .input_addr = 0xC, .bit = 6 }
#define F3 0x63 #define E7 { .input_addr = 0xC, .bit = 7 }
#define F4 0x64 #define F0 { .input_addr = 0xF, .bit = 0 }
#define F5 0x65 #define F1 { .input_addr = 0xF, .bit = 1 }
#define F6 0x66 #define F2 { .input_addr = 0xF, .bit = 2 }
#define F7 0x67 #define F3 { .input_addr = 0xF, .bit = 3 }
#define F4 { .input_addr = 0xF, .bit = 4 }
#define COL2ROW 0x0 #define F5 { .input_addr = 0xF, .bit = 5 }
#define ROW2COL 0x1 #define F6 { .input_addr = 0xF, .bit = 6 }
#define F7 { .input_addr = 0xF, .bit = 7 }
/* USART configuration */
#ifdef BLUETOOTH_ENABLE #ifdef BLUETOOTH_ENABLE
#ifdef __AVR_ATmega32U4__ # ifdef __AVR_ATmega32U4__
#define SERIAL_UART_BAUD 9600 # define SERIAL_UART_BAUD 9600
#define SERIAL_UART_DATA UDR1 # define SERIAL_UART_DATA UDR1
#define SERIAL_UART_UBRR ((F_CPU/(16UL*SERIAL_UART_BAUD))-1) # define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
#define SERIAL_UART_RXD_VECT USART1_RX_vect # define SERIAL_UART_RXD_VECT USART1_RX_vect
#define SERIAL_UART_TXD_READY (UCSR1A&(1<<UDRE1)) # define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
#define SERIAL_UART_INIT() do { \ # define SERIAL_UART_INIT() do { \
UBRR1L = (uint8_t) SERIAL_UART_UBRR; /* baud rate */ \ /* baud rate */ \
UBRR1H = (uint8_t) (SERIAL_UART_UBRR>>8); /* baud rate */ \ UBRR1L = SERIAL_UART_UBRR; \
UCSR1B = (1<<TXEN1); /* TX: enable */ \ /* baud rate */ \
UCSR1C = (0<<UPM11) | (0<<UPM10) | /* parity: none(00), even(01), odd(11) */ \ UBRR1H = SERIAL_UART_UBRR >> 8; \
(0<<UCSZ12) | (1<<UCSZ11) | (1<<UCSZ10); /* data-8bit(011) */ \ /* enable TX */ \
sei(); \ UCSR1B = _BV(TXEN1); \
} while(0) /* 8-bit data */ \
#else UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
# error "USART configuration is needed." sei(); \
} while(0)
# else
# error "USART configuration is needed."
#endif #endif
// I'm fairly sure these aren't needed, but oh well - Jack // I'm fairly sure these aren't needed, but oh well - Jack
/* /*
@ -113,4 +117,3 @@
#endif #endif
#endif #endif

@ -1,6 +1,6 @@
/* /*
Copyright 2012 Jun Wako Copyright 2012 Jun Wako
Generated by planckkeyboard.com (2014 Jack Humbert) Copyright 2014 Jack Humbert
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -15,300 +15,211 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
* scan matrix
*/
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include "wait.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include "matrix.h" #include "matrix.h"
#ifndef DEBOUNCE #ifdef MATRIX_HAS_GHOST
# define DEBOUNCE 10 # error "The universal matrix.c file cannot be used for this keyboard."
#endif #endif
static uint8_t debouncing = DEBOUNCE;
/* matrix state(1:on, 0:off) */ #ifndef DEBOUNCING_DELAY
static matrix_row_t matrix[MATRIX_ROWS]; # define DEBOUNCING_DELAY 5
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
#if DIODE_DIRECTION == ROW2COL
static matrix_row_t matrix_reversed[MATRIX_COLS];
static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
#endif #endif
static const io_pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
#if MATRIX_COLS > 16 static const io_pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#define SHIFTER 1UL /* matrix state */
#if DIODE_DIRECTION == COL2ROW
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t debouncing_matrix[MATRIX_ROWS];
#else #else
#define SHIFTER 1 static matrix_col_t matrix[MATRIX_COLS];
static matrix_col_t debouncing_matrix[MATRIX_COLS];
#endif #endif
static int8_t debouncing_delay = -1;
#if DIODE_DIRECTION == COL2ROW
static void toggle_row(uint8_t row);
static matrix_row_t read_cols(void); static matrix_row_t read_cols(void);
static void init_cols(void); #else
static void unselect_rows(void); static void toggle_col(uint8_t col);
static void select_row(uint8_t row); static matrix_col_t read_rows(void);
#endif
__attribute__ ((weak)) __attribute__ ((weak))
void matrix_init_quantum(void) { void matrix_init_quantum(void) {
} }
__attribute__ ((weak)) __attribute__ ((weak))
void matrix_scan_quantum(void) { void matrix_scan_quantum(void) {
} }
inline uint8_t matrix_rows(void) {
uint8_t matrix_rows(void)
{
return MATRIX_ROWS; return MATRIX_ROWS;
} }
inline uint8_t matrix_cols(void) {
uint8_t matrix_cols(void)
{
return MATRIX_COLS; return MATRIX_COLS;
} }
void matrix_init(void) void matrix_init(void) {
{ /* frees PORTF by setting the JTD bit twice within four cycles */
// To use PORTF disable JTAG with writing JTD bit twice within four cycles. MCUCR |= _BV(JTD);
MCUCR |= (1<<JTD); MCUCR |= _BV(JTD);
MCUCR |= (1<<JTD); /* initializes the I/O pins */
#if DIODE_DIRECTION == COL2ROW
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
// initialize row and col /* DDRxn */
unselect_rows(); _SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
init_cols(); toggle_row(r);
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
matrix_debouncing[i] = 0;
} }
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* PORTxn */
_SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
}
#else
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* DDRxn */
_SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
toggle_col(c);
}
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* PORTxn */
_SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
}
#endif
matrix_init_quantum(); matrix_init_quantum();
} }
uint8_t matrix_scan(void)
{
#if DIODE_DIRECTION == COL2ROW #if DIODE_DIRECTION == COL2ROW
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { uint8_t matrix_scan(void) {
select_row(i); for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
_delay_us(30); // without this wait read unstable value. toggle_row(r);
matrix_row_t cols = read_cols(); matrix_row_t state = read_cols();
if (matrix_debouncing[i] != cols) { if (debouncing_matrix[r] != state) {
matrix_debouncing[i] = cols; debouncing_matrix[r] = state;
if (debouncing) { debouncing_delay = DEBOUNCING_DELAY;
debug("bounce!: "); debug_hex(debouncing); debug("\n");
}
debouncing = DEBOUNCE;
} }
unselect_rows(); toggle_row(r);
} }
if (debouncing_delay >= 0) {
if (debouncing) { dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
if (--debouncing) { --debouncing_delay;
_delay_ms(1); if (debouncing_delay >= 0) {
} else { wait_ms(1);
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = matrix_debouncing[i];
}
} }
} else {
#else for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
for (uint8_t i = 0; i < MATRIX_COLS; i++) { matrix[r] = debouncing_matrix[r];
select_row(i);
_delay_us(30); // without this wait read unstable value.
matrix_row_t rows = read_cols();
if (matrix_reversed_debouncing[i] != rows) {
matrix_reversed_debouncing[i] = rows;
if (debouncing) {
debug("bounce!: "); debug_hex(debouncing); debug("\n");
} }
debouncing = DEBOUNCE;
} }
unselect_rows();
} }
if (debouncing) {
if (--debouncing) {
_delay_ms(1);
} else {
for (uint8_t i = 0; i < MATRIX_COLS; i++) {
matrix_reversed[i] = matrix_reversed_debouncing[i];
}
}
}
for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
matrix_row_t row = 0;
for (uint8_t x = 0; x < MATRIX_COLS; x++) {
row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
}
matrix[y] = row;
}
#endif
matrix_scan_quantum(); matrix_scan_quantum();
return 1; return 1;
} }
bool matrix_is_modified(void) static void toggle_row(uint8_t row) {
{ /* PINxn */
if (debouncing) return false; _SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit);
return true;
} }
inline static matrix_row_t read_cols(void) {
bool matrix_is_on(uint8_t row, uint8_t col) matrix_row_t state = 0;
{ for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
return (matrix[row] & ((matrix_row_t)1<col)); /* PINxn */
if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) {
state |= (matrix_row_t)1 << c;
}
}
return state;
} }
inline matrix_row_t matrix_get_row(uint8_t row) {
matrix_row_t matrix_get_row(uint8_t row)
{
return matrix[row]; return matrix[row];
} }
void matrix_print(void) #else
{ uint8_t matrix_scan(void) {
print("\nr/c 0123456789ABCDEF\n"); for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
for (uint8_t row = 0; row < MATRIX_ROWS; row++) { toggle_col(c);
phex(row); print(": "); matrix_col_t state = read_rows();
pbin_reverse16(matrix_get_row(row)); if (debouncing_matrix[c] != state) {
print("\n"); debouncing_matrix[c] = state;
debouncing_delay = DEBOUNCING_DELAY;
}
toggle_col(c);
} }
} if (debouncing_delay >= 0) {
dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
uint8_t matrix_key_count(void) --debouncing_delay;
{ if (debouncing_delay >= 0) {
uint8_t count = 0; wait_ms(1);
for (uint8_t i = 0; i < MATRIX_ROWS; i++) { }
count += bitpop16(matrix[i]); else {
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
matrix[c] = debouncing_matrix[c];
}
}
} }
return count; matrix_scan_quantum();
return 1;
} }
static void init_cols(void) static void toggle_col(uint8_t col) {
{ /* PINxn */
int B = 0, C = 0, D = 0, E = 0, F = 0; _SFR_IO8(col_pins[col].input_addr) = _BV(col_pins[col].bit);
}
#if DIODE_DIRECTION == COL2ROW static matrix_col_t read_rows(void) {
for(int x = 0; x < MATRIX_COLS; x++) { matrix_col_t state = 0;
int col = COLS[x]; for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
#else /* PINxn */
for(int x = 0; x < MATRIX_ROWS; x++) { if (!(_SFR_IO8(row_pins[r].input_addr) & _BV(row_pins[r].bit))) {
int col = ROWS[x]; state |= (matrix_col_t)1 << r;
#endif }
if ((col & 0xF0) == 0x20) {
B |= (1<<(col & 0x0F));
} else if ((col & 0xF0) == 0x30) {
C |= (1<<(col & 0x0F));
} else if ((col & 0xF0) == 0x40) {
D |= (1<<(col & 0x0F));
} else if ((col & 0xF0) == 0x50) {
E |= (1<<(col & 0x0F));
} else if ((col & 0xF0) == 0x60) {
F |= (1<<(col & 0x0F));
}
} }
DDRB &= ~(B); PORTB |= (B); return state;
DDRC &= ~(C); PORTC |= (C);
DDRD &= ~(D); PORTD |= (D);
DDRE &= ~(E); PORTE |= (E);
DDRF &= ~(F); PORTF |= (F);
} }
static matrix_row_t read_cols(void) matrix_row_t matrix_get_row(uint8_t row) {
{ matrix_row_t state = 0;
matrix_row_t result = 0; matrix_col_t mask = (matrix_col_t)1 << row;
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
if (matrix[c] & mask) {
state |= (matrix_row_t)1 << c;
}
}
return state;
}
#if DIODE_DIRECTION == COL2ROW
for(int x = 0; x < MATRIX_COLS; x++) {
int col = COLS[x];
#else
for(int x = 0; x < MATRIX_ROWS; x++) {
int col = ROWS[x];
#endif #endif
if ((col & 0xF0) == 0x20) { bool matrix_is_modified(void) {
result |= (PINB&(1<<(col & 0x0F)) ? 0 : (SHIFTER<<x)); if (debouncing_delay >= 0) return false;
} else if ((col & 0xF0) == 0x30) { return true;
result |= (PINC&(1<<(col & 0x0F)) ? 0 : (SHIFTER<<x));
} else if ((col & 0xF0) == 0x40) {
result |= (PIND&(1<<(col & 0x0F)) ? 0 : (SHIFTER<<x));
} else if ((col & 0xF0) == 0x50) {
result |= (PINE&(1<<(col & 0x0F)) ? 0 : (SHIFTER<<x));
} else if ((col & 0xF0) == 0x60) {
result |= (PINF&(1<<(col & 0x0F)) ? 0 : (SHIFTER<<x));
}
}
return result;
} }
static void unselect_rows(void) bool matrix_is_on(uint8_t row, uint8_t col) {
{ return matrix_get_row(row) & (matrix_row_t)1 << col;
int B = 0, C = 0, D = 0, E = 0, F = 0; }
#if DIODE_DIRECTION == COL2ROW void matrix_print(void) {
for(int x = 0; x < MATRIX_ROWS; x++) { dprintln("Human-readable matrix state:");
int row = ROWS[x]; for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
#else dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r)));
for(int x = 0; x < MATRIX_COLS; x++) {
int row = COLS[x];
#endif
if ((row & 0xF0) == 0x20) {
B |= (1<<(row & 0x0F));
} else if ((row & 0xF0) == 0x30) {
C |= (1<<(row & 0x0F));
} else if ((row & 0xF0) == 0x40) {
D |= (1<<(row & 0x0F));
} else if ((row & 0xF0) == 0x50) {
E |= (1<<(row & 0x0F));
} else if ((row & 0xF0) == 0x60) {
F |= (1<<(row & 0x0F));
}
} }
DDRB &= ~(B); PORTB |= (B);
DDRC &= ~(C); PORTC |= (C);
DDRD &= ~(D); PORTD |= (D);
DDRE &= ~(E); PORTE |= (E);
DDRF &= ~(F); PORTF |= (F);
} }
static void select_row(uint8_t row) uint8_t matrix_key_count(void) {
{ uint8_t count = 0;
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
#if DIODE_DIRECTION == COL2ROW count += bitpop16(matrix_get_row(r));
int row_pin = ROWS[row]; }
#else return count;
int row_pin = COLS[row]; }
#endif
if ((row_pin & 0xF0) == 0x20) {
DDRB |= (1<<(row_pin & 0x0F));
PORTB &= ~(1<<(row_pin & 0x0F));
} else if ((row_pin & 0xF0) == 0x30) {
DDRC |= (1<<(row_pin & 0x0F));
PORTC &= ~(1<<(row_pin & 0x0F));
} else if ((row_pin & 0xF0) == 0x40) {
DDRD |= (1<<(row_pin & 0x0F));
PORTD &= ~(1<<(row_pin & 0x0F));
} else if ((row_pin & 0xF0) == 0x50) {
DDRE |= (1<<(row_pin & 0x0F));
PORTE &= ~(1<<(row_pin & 0x0F));
} else if ((row_pin & 0xF0) == 0x60) {
DDRF |= (1<<(row_pin & 0x0F));
PORTF &= ~(1<<(row_pin & 0x0F));
}
}

@ -41,15 +41,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
* *
*/ */
#define COLS (int []){ F1, F0, B0 } #define MATRIX_ROW_PINS { D0, D5 }
#define ROWS (int []){ D0, D5 } #define MATRIX_COL_PINS { F1, F0, B0 }
#define UNUSED_PINS
/* COL2ROW or ROW2COL */ /* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW #define DIODE_DIRECTION COL2ROW
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5 #define DEBOUNCING_DELAY 5
/* define if matrix has ghost (lacks anti-ghosting diodes) */ /* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST //#define MATRIX_HAS_GHOST
@ -62,17 +63,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Locking resynchronize hack */ /* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE #define LOCKING_RESYNC_ENABLE
/* /*
* Force NKRO * Force NKRO
* *
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.) * makefile for this to work.)
* *
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset. * until the next keyboard reset.
* *
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage. * fully operational during normal computer usage.
* *
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
@ -90,7 +91,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* the keyboard. They are best used in combination with the HID Listen program, * the keyboard. They are best used in combination with the HID Listen program,
* found here: https://www.pjrc.com/teensy/hid_listen.html * found here: https://www.pjrc.com/teensy/hid_listen.html
* *
* The options below allow the magic key functionality to be changed. This is * The options below allow the magic key functionality to be changed. This is
* useful if your keyboard/keypad is missing keys and you want magic key support. * useful if your keyboard/keypad is missing keys and you want magic key support.
* *
*/ */

@ -114,9 +114,7 @@ bool suspend_wakeup_condition(void)
matrix_power_up(); matrix_power_up();
matrix_scan(); matrix_scan();
matrix_power_down(); matrix_power_down();
for (uint8_t r = 0; r < MATRIX_ROWS; r++) { if (matrix_key_count()) return true;
if (matrix_get_row(r)) return true;
}
return false; return false;
} }
@ -146,4 +144,3 @@ ISR(WDT_vect)
} }
} }
#endif #endif

@ -105,15 +105,13 @@ void bootmagic(void)
} }
} }
static bool scan_keycode(uint8_t keycode) static bool scan_keycode(uint8_t keycode) {
{ for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
matrix_row_t matrix_row = matrix_get_row(r); matrix_row_t matrix_row = matrix_get_row(r);
for (uint8_t c = 0; c < MATRIX_COLS; c++) { for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
if (matrix_row & ((matrix_row_t)1<<c)) { if (matrix_row & (matrix_row_t)1 << c) {
if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) { keypos_t key = (keypos_t){ .row = r, .col = c };
return true; if (keycode == keymap_key_to_keycode(0, key)) return true;
}
} }
} }
} }

@ -1,5 +1,5 @@
/* /*
Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com> Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -27,13 +27,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "command.h" #include "command.h"
#include "util.h" #include "util.h"
#include "sendchar.h" #include "sendchar.h"
#include "eeconfig.h"
#include "backlight.h"
#ifdef BOOTMAGIC_ENABLE #ifdef BOOTMAGIC_ENABLE
#include "bootmagic.h" # include "bootmagic.h"
#else #else
#include "magic.h" # include "magic.h"
#endif #endif
#include "eeconfig.h"
#include "backlight.h"
#ifdef MOUSEKEY_ENABLE #ifdef MOUSEKEY_ENABLE
# include "mousekey.h" # include "mousekey.h"
#endif #endif
@ -41,40 +41,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "ps2_mouse.h" # include "ps2_mouse.h"
#endif #endif
#ifdef SERIAL_MOUSE_ENABLE #ifdef SERIAL_MOUSE_ENABLE
#include "serial_mouse.h" # include "serial_mouse.h"
#endif #endif
#ifdef ADB_MOUSE_ENABLE #ifdef ADB_MOUSE_ENABLE
#include "adb.h" # include "adb.h"
#endif #endif
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
static bool has_ghost_in_row(uint8_t row) static bool is_row_ghosting(uint8_t row){
{ matrix_row_t state = matrix_get_row(row);
matrix_row_t matrix_row = matrix_get_row(row); /* no ghosting happens when only one key in the row is pressed */
// No ghost exists when less than 2 keys are down on the row if (!(state - 1 & state)) return false;
if (((matrix_row - 1) & matrix_row) == 0) /* ghosting occurs when two keys in the same column are pressed */
return false; for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
if (r != row && matrix_get_row(r) & state) return true;
// Ghost occurs when the row shares column line with other row
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
if (i != row && (matrix_get_row(i) & matrix_row))
return true;
} }
return false; return false;
} }
#endif #endif
__attribute__ ((weak))
void matrix_setup(void) {
}
__attribute__ ((weak)) void matrix_setup(void) {} void keyboard_setup(void) {
void keyboard_setup(void)
{
matrix_setup(); matrix_setup();
} }
void keyboard_init(void) void keyboard_init(void) {
{
timer_init(); timer_init();
matrix_init(); matrix_init();
#ifdef PS2_MOUSE_ENABLE #ifdef PS2_MOUSE_ENABLE
@ -86,104 +81,87 @@ void keyboard_init(void)
#ifdef ADB_MOUSE_ENABLE #ifdef ADB_MOUSE_ENABLE
adb_mouse_init(); adb_mouse_init();
#endif #endif
#ifdef BOOTMAGIC_ENABLE #ifdef BOOTMAGIC_ENABLE
bootmagic(); bootmagic();
#else #else
magic(); magic();
#endif #endif
#ifdef BACKLIGHT_ENABLE #ifdef BACKLIGHT_ENABLE
backlight_init(); backlight_init();
#endif #endif
#if defined(NKRO_ENABLE) && defined(FORCE_NKRO) #if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
keyboard_nkro = true; keyboard_nkro = true;
#endif #endif
} }
/* /* does routine keyboard jobs */
* Do keyboard routine jobs: scan mantrix, light LEDs, ... void keyboard_task(void) {
* This is repeatedly called as fast as possible. static matrix_row_t previous_matrix[MATRIX_ROWS];
*/
void keyboard_task(void)
{
static matrix_row_t matrix_prev[MATRIX_ROWS];
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
static matrix_row_t matrix_ghost[MATRIX_ROWS]; static matrix_row_t deghosting_matrix[MATRIX_ROWS];
#endif #endif
static uint8_t led_status = 0; static uint8_t led_status = 0;
matrix_row_t matrix_row = 0;
matrix_row_t matrix_change = 0;
matrix_scan(); matrix_scan();
for (uint8_t r = 0; r < MATRIX_ROWS; r++) { for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
matrix_row = matrix_get_row(r); matrix_row_t state = matrix_get_row(r);
matrix_change = matrix_row ^ matrix_prev[r]; matrix_row_t changes = state ^ previous_matrix[r];
if (matrix_change) { if (changes) {
#ifdef MATRIX_HAS_GHOST #ifdef MATRIX_HAS_GHOST
if (has_ghost_in_row(r)) { if (is_row_ghosting(r)) {
/* Keep track of whether ghosted status has changed for /* debugs the deghosting mechanism */
* debugging. But don't update matrix_prev until un-ghosted, or /* doesn't update previous_matrix until the ghosting has stopped
* the last key would be lost. * in order to prevent the last key from being lost
*/ */
if (debug_matrix && matrix_ghost[r] != matrix_row) { if (debug_matrix && deghosting_matrix[r] != state) {
matrix_print(); matrix_print();
} }
matrix_ghost[r] = matrix_row; deghosting_matrix[r] = state;
continue; continue;
} }
matrix_ghost[r] = matrix_row; deghosting_matrix[r] = state;
#endif #endif
if (debug_matrix) matrix_print(); if (debug_matrix) matrix_print();
for (uint8_t c = 0; c < MATRIX_COLS; c++) { for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
if (matrix_change & ((matrix_row_t)1<<c)) { matrix_row_t mask = (matrix_row_t)1 << c;
action_exec((keyevent_t){ if (changes & mask) {
.key = (keypos_t){ .row = r, .col = c }, keyevent_t event;
.pressed = (matrix_row & ((matrix_row_t)1<<c)), event.key = (keypos_t){ .row = r, .col = c };
.time = (timer_read() | 1) /* time should not be 0 */ event.pressed = state & mask;
}); /* the time should not be 0 */
// record a processed key event.time = timer_read() | 1;
matrix_prev[r] ^= ((matrix_row_t)1<<c); action_exec(event);
// process a key per task call /* records the processed key event */
goto MATRIX_LOOP_END; previous_matrix[r] ^= mask;
/* processes one key event per call */
goto event_processed;
} }
} }
} }
} }
// call with pseudo tick event when no real key event. /* sends tick events when the keyboard is idle */
action_exec(TICK); action_exec(TICK);
event_processed:
MATRIX_LOOP_END:
#ifdef MOUSEKEY_ENABLE #ifdef MOUSEKEY_ENABLE
// mousekey repeat & acceleration /* repeats and accelerates the mouse keys */
mousekey_task(); mousekey_task();
#endif #endif
#ifdef PS2_MOUSE_ENABLE #ifdef PS2_MOUSE_ENABLE
ps2_mouse_task(); ps2_mouse_task();
#endif #endif
#ifdef SERIAL_MOUSE_ENABLE #ifdef SERIAL_MOUSE_ENABLE
serial_mouse_task(); serial_mouse_task();
#endif #endif
#ifdef ADB_MOUSE_ENABLE #ifdef ADB_MOUSE_ENABLE
adb_mouse_task(); adb_mouse_task();
#endif #endif
/* updates the LEDs */
// update LED
if (led_status != host_keyboard_leds()) { if (led_status != host_keyboard_leds()) {
led_status = host_keyboard_leds(); led_status = host_keyboard_leds();
keyboard_set_leds(led_status); keyboard_set_leds(led_status);
} }
} }
void keyboard_set_leds(uint8_t leds) void keyboard_set_leds(uint8_t leds) {
{ if (debug_keyboard) dprintf("Keyboard LEDs state: %x\n", leds);
if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
led_set(leds); led_set(leds);
} }

@ -14,59 +14,68 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MATRIX_H #ifndef MATRIX_H
#define MATRIX_H #define MATRIX_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#if MATRIX_COLS <= 8
#if (MATRIX_COLS <= 8) typedef uint8_t matrix_row_t;
typedef uint8_t matrix_row_t; #elif MATRIX_COLS <= 16
#elif (MATRIX_COLS <= 16) typedef uint16_t matrix_row_t;
typedef uint16_t matrix_row_t; #elif MATRIX_COLS <= 32
#elif (MATRIX_COLS <= 32) typedef uint32_t matrix_row_t;
typedef uint32_t matrix_row_t;
#else #else
#error "MATRIX_COLS: invalid value" # error "There are too many columns."
#endif #endif
#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col)) #if DIODE_DIRECTION == ROW2COL
# if MATRIX_ROWS <= 8
typedef uint8_t matrix_col_t;
# elif MATRIX_ROWS <= 16
typedef uint16_t matrix_col_t;
# elif MATRIX_ROWS <= 32
typedef uint32_t matrix_col_t;
# else
# error "There are too many rows."
# endif
#endif
typedef struct {
uint8_t input_addr:4;
uint8_t bit:4;
} io_pin_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* counts the number of rows in the matrix */
/* number of matrix rows */
uint8_t matrix_rows(void); uint8_t matrix_rows(void);
/* number of matrix columns */ /* counts the number of columns in the matrix */
uint8_t matrix_cols(void); uint8_t matrix_cols(void);
/* should be called at early stage of startup before matrix_init.(optional) */ /* sets up the matrix before matrix_init */
void matrix_setup(void); void matrix_setup(void);
/* intialize matrix for scaning. */ /* intializes the matrix */
void matrix_init(void); void matrix_init(void);
/* scan all key states on matrix */ /* scans the entire matrix */
uint8_t matrix_scan(void); uint8_t matrix_scan(void);
/* whether modified from previous scan. used after matrix_scan. */ /* checks if the matrix has been modified */
bool matrix_is_modified(void) __attribute__ ((deprecated)); bool matrix_is_modified(void) __attribute__ ((deprecated));
/* whether a swtich is on */ /* checks if a key is pressed */
bool matrix_is_on(uint8_t row, uint8_t col); bool matrix_is_on(uint8_t row, uint8_t col);
/* matrix state on row */ /* inspects the state of a row in the matrix */
matrix_row_t matrix_get_row(uint8_t row); matrix_row_t matrix_get_row(uint8_t row);
/* print matrix for debug */ /* prints the matrix for debugging */
void matrix_print(void); void matrix_print(void);
/* counts the total number of keys pressed */
uint8_t matrix_key_count(void);
/* power control */ /* controls power to the matrix */
void matrix_power_up(void); void matrix_power_up(void);
void matrix_power_down(void); void matrix_power_down(void);
/* executes code for Quantum */
/* keyboard-specific setup/loop functionality */
void matrix_init_quantum(void); void matrix_init_quantum(void);
void matrix_scan_quantum(void); void matrix_scan_quantum(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

Loading…
Cancel
Save