How to build your very own keyboard firmware

User avatar
Muirium
µ

25 Jun 2015, 22:16

gangolfus wrote: Hello Gurus - I'm having an issue with this firmware and I am hoping someone can point me in the right direction.

For one of my columns, when I press the top key, the rest of the keys in that column also fire.
eg, Press F5: F5/6/y/g/b all fire

I am also having a similar problem another column, but where all the keys in the row after fire.
eg. Press Right Arrow: Right Arrow/0/./Enter all fire

Do these sound like programming problems or electrical problems?

Any guidance is greatly appreciated!
Check your diodes are all the same polarity across the whole matrix. Hardware I understand, software not so much!

User avatar
hasu

27 Jun 2015, 05:00

Why do you read bit2 of PortB three times? Is this intentional?

Code: Select all

(PINB&(1<<2) ? 0 : (1<<14)) |
(PINB&(1<<2) ? 0 : (1UL<<15)) |
(PINB&(1<<2) ? 0 : (1UL<<16)) |
Apparently if you have more than 14 columns, all columns past 14 must us 1UL in read_cols function.
I think you can write (1<<15) but not completely sure.

User avatar
klikkyklik

27 Jun 2015, 05:56

Hasu is mostly correct, other than you're repeating the same bit read (1<<2) on PINB four times, which is an error in logic. Fix the redundant bit read on PINB first and go from there.

What is matrix_row_t declared as?

gangolfus

27 Jun 2015, 06:49

Sorry, the code I supplied was a copy/paste example, not my actual code. I have edited my edit with my actual working code.

Independent of what is supposed to occur, with "(PINC&(1<<3) ? 0 : (1<<15))" the rest of the keys in the row would fire. With "(PINC&(1<<3) ? 0 : (1UL<<15))" they would not. I would not expect it to be like this, but it was in my case.

User avatar
LeandreN

27 Jun 2015, 09:43

Okay, so i found out that the problem might be the compiler. I get this message when i just use the plain GH60 folder from the full TMK firmware package.

Image

User avatar
flabbergast

27 Jun 2015, 12:07

LeandreN wrote: Okay, so i found out that the problem might be the compiler. I get this message when i just use the plain GH60 folder from the full TMK firmware package.
I don't have windows to test, so this may be off. I think it's more likely the problem is not with the compiler per-se, but with the cygwin stuff that comes bundled with with (like shell, make, etc...). The reason is that the error is issued by the shell (/usr/bin/sh), not avr-gcc itself.

Winavr is quite old (2010). So cygwin that comes with it is also old.

If you have time and energy, I would try to install first "normal" cygwin and dev tools (make, ...) by itself, and then also get newer avr-gcc compiler, for instance from here.

chanlol

27 Jun 2015, 13:10

I wanna to build a keyboard firmware for Mx1800 but I have no idea of code :(

mcturtles

30 Jun 2015, 19:41

Hey guys/gals, having issues when I go to make the makefile. It's telling me the parameter name is missing in my Keymap and then (as a result I assume), the keymap_poker is throwing a whole bunch of errors.

This is the output from "make"

This is my Keymap code snippet:

Code: Select all

#define KEYMAP( \
    K00, K01, \
    K10, K11, \
) { \  \\This is where I get the "parameter name missing" error
    { KC_##K00, KC_##K01 }, \
    { KC_##K10, KC_##K11 } \
}
And this is my keymap_poker code:

Code: Select all

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    KEYMAP(1, 2, \
           3, 4),
};

const uint16_t PROGMEM fn_actions[] = {

};
I'm just building a 2x2 test board for right now, that's why there are so few keys.

Any help would be very much appreciated!

mcturtles

30 Jun 2015, 21:39

scottc wrote:
flabbergast wrote:
scottc wrote: To me it sounds like you might've set up something that caused an infinite loop. Did you include your keymap within your keymap definition or something like that? Maybe copy a fresh version of the source code and apply your changes bit by bit to see what causes that error.
I would think that compilers can deal with this kind of problems. Also - the first complaint about fork is actually _before_ the compiler runs (before ---begin---). But you may be right.

LeandreN - you should definitely try compiling first without any modification to sources.
Oh, good point. I didn't read the output very carefully but it does indeed look like the error is from Make, not the compiler. So I agree - try to compile the firmware without any changes first.

I searched around a bit for this error and it was hinted that it might be a dodgy GCC-AVR install.


Hey, don't know if you're still looking for a solution, but I was having the same issue and "sebastor"s post in this thread fixed it for me.

User avatar
flabbergast

30 Jun 2015, 21:58

mcturtles wrote:

Code: Select all

#define KEYMAP( \
    K00, K01, \
    K10, K11, \
) { \  \\This is where I get the "parameter name missing" error
    { KC_##K00, KC_##K01 }, \
    { KC_##K10, KC_##K11 } \
}
In case you haven't solved this yet, the problem is that there should be no comma after K11:

Code: Select all

    K10, K11 \
) { \  \\This is where I get the "parameter name missing" error

gangolfus

01 Jul 2015, 17:46

Alright geniuses, my keyboard is fully functional, so on to the next part of my project: backlighting.

I purchased white LEDs from maxkeyboard (http://www.maxkeyboard.com/max-keyboard ... 0-pcs.html) and contacted their customer service who told me the are rated IF=20mA Min 3.0V Max 3.6V, IF=5mA Min 2.7 Max 3.3.

My full size keyboard is made of 20 columns and 6 rows (105 Leds). My thought is that I would wire up each column in series, then wire all the columns in parallel. I plan to drive it all using a Femtobuck (https://www.sparkfun.com/products/12937, not yet purchased) and a 19V/.5A power supply (TBD, not yet purchased).

Each column has 4-6 Leds, so I would need 1.5k, 820, and 220 ohm resisters respectively. Ultimately the control pin on the Femtobuck will be connected to my TMK controlled Teensy++ 2.0 and a function layer key to toggle the backlight on/off.

Are there any glaring issues with my plans? Are there better ways to do what I'm trying to accomplish? Any critique/help is greatly appreciated.

User avatar
flabbergast

01 Jul 2015, 18:35

gangolfus wrote: Alright geniuses, my keyboard is fully functional, so on to the next part of my project: backlighting.

I purchased white LEDs from maxkeyboard (http://www.maxkeyboard.com/max-keyboard ... 0-pcs.html) and contacted their customer service who told me the are rated IF=20mA Min 3.0V Max 3.6V, IF=5mA Min 2.7 Max 3.3.

My full size keyboard is made of 20 columns and 6 rows (105 Leds). My thought is that I would wire up each column in series, then wire all the columns in parallel. I plan to drive it all using a Femtobuck (https://www.sparkfun.com/products/12937, not yet purchased) and a 19V/.5A power supply (TBD, not yet purchased).

Each column has 4-6 Leds, so I would need 1.5k, 820, and 220 ohm resisters respectively. Ultimately the control pin on the Femtobuck will be connected to my TMK controlled Teensy++ 2.0 and a function layer key to toggle the backlight on/off.

Are there any glaring issues with my plans? Are there better ways to do what I'm trying to accomplish? Any critique/help is greatly appreciated.
You seem to want to do things in a more complicated way than usual ;)

"Normally" (i.e. on backlit keyboards that I've seen), each LED is wired as

Code: Select all

                         /--  LED --- resistor --\
<USB 5V> --- transistor ----  LED --- resistor --- <ground>
                         \--    ...              /
... and the transistor is wired to a microcontroller pin which can turn it on and off. Dimming is done using PWM on that pin.

FemtoBuck has a couple of disadvantages in this case - you'll need an extra power supply with relatively high voltage ( forward_voltage_of_a_LED * number_of_LEDs_in_series + 1V ). You won't need resistors (current limiting is the job of FemtoBuck), except at columns which have less LEDs (the current that FemtoBuck provides will "split" to individual columns, and unless they present exactly the same resistance, it will not split equally, so the brightness would be different). And it's a big piece of circuit.

I might be wrong since I've just read about FemtoBuck on sparkfun's wiring page ...

gangolfus

01 Jul 2015, 20:12

My concern with connecting straight to the Teensy was power draw.

Leds could draw:
.020A * 3.6V * 105 = 7.56W
.020A * 3.3V * 105 = 6.93W
.020A * 3.0V * 105 = 6.3W
.005A * 3.3V * 105 = 1.73W
.005A * 3.0V * 105 = 1.575W
.005A * 2.7V * 105 = 1.4175W

USB is spec'd at .5A * 5V = 2.5W.

I would love to ditch the Femtobuck and external power supply, but how do I ensure I don't burn up my Teensy? What kind of transistor would I need?

User avatar
flabbergast

01 Jul 2015, 20:36

You might want to think of the transistor as an "on/off switch" for the LEDs. The current to LEDs goes straight from the USB. It doesn't go through teensy at all.

Yea, you should limit the current through LEDs with resistors so that the total draw of the keyboard is < 500mA. Teensy itself accounts for 20 - 30mA.

I don't know which exact transistors are used in keyboards (I don't have one open right now). But here's an actual circuit like that: http://cdn.sparkfun.com/datasheets/Kits/PowerIR-v11.pdf
(The reason why is this wired like it is is precisely the fact that the LED in there takes more current on full power than a microcontroller can supply.)

gangolfus

02 Jul 2015, 06:03

Ok, so instead of the Femtobuck and external power supply, lets say I get a 2N2222 transistor, hook that up to a PWM pin on the Teensy then wire all the leds+470 ohm resistors in parallel. Should this setup work?

How would I go about controlling this setup using this firmware?

User avatar
flabbergast

02 Jul 2015, 07:59

gangolfus wrote: Ok, so instead of the Femtobuck and external power supply, lets say I get a 2N2222 transistor, hook that up to a PWM pin on the Teensy then wire all the leds+470 ohm resistors in parallel. Should this setup work?
Yes, that should work. I've had a look at Poker II PCB and that's exactly how it is wired. You probably also want a resistor between the Teensy pin and the base of the transistor (so that if something goes wrong with the transistor, it won't kill the teensy).
gangolfus wrote: How would I go about controlling this setup using this firmware?
It will behave as you would normally control a LED - pulling the pin high will turn the LEDs on, pulling it low will turn the LEDs off. If you want a dimmer light, use PWM (e.g. if the duty cycle is 50%, the pin is high only for 50% of the time, so the LEDs will be dimmer).

If a firmware supports backlight (e.g. TMK or easyAVR do), they normally expect precisely this behaviour.

Try the setup on a breadboard if you can.

chanlol

03 Jul 2015, 02:22

Does anyone have build firmware for Leeku 1800 PCB ? I have no idea writing codes:(

Natemiester

06 Jul 2015, 21:32

Hello you fine, knowledgeable people. First off, thank you Matt3o for this guide. It was a lifesaver. Secondly, do any of you guys know what might cause an entire column to fire at once? My custom keyboard works, but whenever I wiggle the teensy in the wrong way, it will outpupt "2wsx", which are all connected in one row. If I continue to hold the teensy in that position, it starts just printing out "x" repeatedly. There's a strip of tape underneath my teensy, that should be insulating it. Any ideas?

User avatar
flabbergast

06 Jul 2015, 21:50

Not that I'm fine or knowledgeable ;) but check your electrical connections, especially the wire for that column, and the wire that goes from that column to teensy.

The way firmware usually works is that it periodically grounds (=logic 0) each row in turn, and scans each column to see if it's high (=logic 1, default state, switch not pressed), or grounded ( => switch at the intersection of that column and the grounded row is pressed). If the whole column seems firing at once, it means that the wire for that column is grounded for the duration of scanning, independently of switches and of what the teensy is doing with rows.

Natemiester

06 Jul 2015, 22:25

Thanks for the explanation! I think the pin might be getting grounded to my case, as I can't make it fire when I have the top of the board out of my metal case, only when placed in it. Now, the entire case is covered in plasti-dip, so I thought it was insulated, but I'll see what happens if I put additional electrical tape underneath where the teensy is.

EDIT: Definitely not the case. I got the firing when the board was outside the case. I'm going to see what happens if I resolder the wire onto another switch in the column.

User avatar
hbar

22 Jul 2015, 18:45

A quick question here after a search didn't find anything of use to me: can Hasu's code be used as a PS/2-USB converter which supports an additional trackpoint? I guess I'm asking whether or not the code can be configured to read essentially two PS/2 devices (a keyboard and a trackpoint) and make both available as USB devices. Now that I've disassembled my M from 1987 and discovered that it's desperately in need of that rivet/bolt replacement mod, I might just as well convert it to USB and add a trackpoint in the process.

ħ

User avatar
Ray

22 Jul 2015, 20:23

I am not sure, but i guess it doesn't support it out of the box. For the trackpoint, I have

Code: Select all

PS2_MOUSE_ENABLE = yes
PS2_USE_USART = yes
in the Makefile.
And you need a PS2_USE_xxx to set which way you want to read the PS/2 from the keyboard. So I guess there's no option for two different PS/2 inputs in his firmware. At least I don't see a way to differentiate them.

But I know the older IBM trackpoints have PS/2 input as well as output, to daisy-chain two Trackpoints. I don't know if you can daisy-chain non-mouse PS/2 devices through them, though. Probably not...

If you do the mod, pls share. My M needs some form of easy mousecontrol as well, but there is not much room right below the alphas. Anywhere else yes, but not where you expect a trackpoint.

Morinaka

26 Jul 2015, 00:56

I'm converting an Acorn Electron keyboard matrix to USB with the Teensy as the converter. I've wired up the board to the Teensy (in a temporary way) and altered the firmware like your guide suggests, compiled and put it on the Teensy.

This is the diagram http://i.imgur.com/e2ZOi15.png for the keyboard circuit from the original service manual. The board has 22 pins that just connected to the computer via a ribbon cable, i replaced that with pin headers http://imgur.com/mnAloMp, did that same thing on the Teensy as well http://i.imgur.com/6Uq6Tpw.jpg, i've literally just connected the two with push on breadboard wires for now until i know the firmware works.

Anyway nothing happens, the board shows up in windows device manager and when i press the caps lock key on my main board the LED on the Electron board lights as well, so something is working and that shows the teensy is "talking" to the keyboard. I decided to check continuity with my multimeter and noticed with i bypassed a column's diode that column would type and work, so if i bypassed D1 i could use the 1QAZ keys.

I did a little searching and it seems one other persons has converted this board but using mbed and a different board, here is the custom firmware for it if that helps. The comments in the code suggest the voltage drops on active keys and i think the gh60 tmk firmware works on active high?

My matrix.c file

Code: Select all

/* Column pin configuration
 * col: 0   1   2   3   4   5   6   7   8   9   10  11  12  13
 * pin: F7  B6  B5  B4  D7  C7  C6  D3  D2  D1  D0  B7  B3  B2  (Rev.A)
 */
static void  init_cols(void)
{
    // Input with pull-up(DDR:0, PORT:1)
    DDRF  &= ~(1<<7);
    PORTF |=  (1<<7);
    DDRD  &= ~(1<<7 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
    PORTD |=  (1<<7 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
    DDRC  &= ~(1<<7 | 1<<6);
    PORTC |=  (1<<7 | 1<<6);
    DDRB  &= ~(1<<7 | 1<<6 | 1<< 5 | 1<<4 | 1<<3 | 1<<2);
    PORTB |=  (1<<7 | 1<<6 | 1<< 5 | 1<<4 | 1<<3 | 1<<2);
}

static matrix_row_t read_cols(void)
{
    return (PINF&(1<<7) ? 0 : (1<<0)) |
           (PINB&(1<<6) ? 0 : (1<<1)) |
           (PINB&(1<<5) ? 0 : (1<<2)) |
           (PINB&(1<<4) ? 0 : (1<<3)) |
           (PIND&(1<<7) ? 0 : (1<<4)) |
           (PINC&(1<<7) ? 0 : (1<<5)) |
           (PINC&(1<<6) ? 0 : (1<<6)) |
           (PIND&(1<<3) ? 0 : (1<<7)) |
           (PIND&(1<<2) ? 0 : (1<<8)) |
           (PIND&(1<<1) ? 0 : (1<<9)) |
           (PIND&(1<<0) ? 0 : (1<<10)) |
           (PINB&(1<<7) ? 0 : (1<<11)) |
           (PINB&(1<<3) ? 0 : (1<<12)) |
           (PINB&(1<<2) ? 0 : (1<<13));
}

/* Row pin configuration
 * row: 0   1   2   3   4
 * pin: F0  F1  F4  F5  F6
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect
    DDRF  &= ~0b01110011;
    PORTF &= ~0b01110011;
}

static void select_row(uint8_t row)
{
    // Output low(DDR:1, PORT:0) to select
    switch (row) {
        case 0:
            DDRF  |= (1<<0);
            PORTF &= ~(1<<0);
            break;
        case 1:
            DDRF  |= (1<<1);
            PORTF &= ~(1<<1);
            break;
        case 2:
            DDRF  |= (1<<4);
            PORTF &= ~(1<<4);
            break;
        case 3:
            DDRF  |= (1<<5);
            PORTF &= ~(1<<5);
            break;
        case 4:
            DDRF  |= (1<<6);
            PORTF &= ~(1<<6);
            break;
    }
}
keymap_poker.c file

Code: Select all

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* 0: qwerty */
    KEYMAP(
        ESC,  1,   2,   3,   4,   5,   6,   7,   8,    9,   0,    MINS, NUHS, NUBS, \
        CAPS, Q,   W,   E,   R,   T,   Y,   U,   I,    O,   P,    LBRC, RBRC, COPY, \
        LCTL, A,   S,   D,   F,   G,   H,   J,   K,    L,   SCLN, QUOT, ENT,        \
        LSFT, Z,   X,   C,   V,   B,   N,   M,   COMM, DOT, SLSH, RSFT, DEL,  SPC,  \
        FN0),
    /* 1: FN 1 - Toggle Layer */
    KEYMAP(
		TRNS, F1,   F2,   F3,   F4,   F5,   F6,   F7,   F8,   F9,   F10,  TRNS, LEFT, RGHT, \
        TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, UP,   DOWN, TRNS, \
        TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,       \
        TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, \
        TRNS),
};
const uint16_t PROGMEM fn_actions[] = {
    /* Custom Acorn Electron Layout - FN[0] */
    [0] = ACTION_LAYER_TOGGLE(1)     // BREAK key will toggle FN layer 0 and 1
    //[1] = ACTION_LAYER_MOMENTARY(2),  // This means that the FN[1] key will trigger the layer (2) with a ACTION_LAYER_MOMENTARY action.
    //[2] = ACTION_LAYER_TAP_KEY(1, KC_ESC)
    //[1] = ACTION_DEFAULT_LAYER_SET(0),  // set qwerty layout
};
and my keymap_common.h custom map

Code: Select all

/* Acorn Electron keymap definition macro
 * K4D is the BREAK key, it is just a switch so not really part of the matrix
 * but it will be nice to have to mapped to something
 */
#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    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, K2C,      \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
                                                                     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_##K2C, KC_NO    }, \
    { 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_##K3D }, \
    { KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##K4D }  \
}
I hope that's enough information so someone can understand and try to help me, thanks in advance for any help.

User avatar
Muirium
µ

26 Jul 2015, 13:10

Sounds like you've got the software working. But before I go repeating myself, I'll link instead.

User avatar
Ray

26 Jul 2015, 13:52

on that keyboard, the columns are outputs, while the rows are read as inputs. And yes, low on a row means a closed switch.
So you have to change rows and columns in software.

And unlike the gh60, you have to care about ghosting. Hasu's firmware can do that for you, I think. But obviously it isn't nkro

User avatar
Halvar

26 Jul 2015, 14:14

In your matrix.c file, you're using the same pins for rows and columns that Matteo used in his example. Is that on purpose? Did you wire your board to the Teensy in the same way?

For example, you have only four rows on you keyboard, and you're using a five row matrix.

As far as diodes are concerned: The firmware has the input pins on input / pull-up-active , so they will be on +5V level when all keyboard switches are open (unpressed). When scanning, a row is selected by pulling it down to GND level, so the technical current direction when a switch is closed is from column pin to row pin to pull the column pin down to GND. Unfortunately, if the schematics that you linked is right, the diodes block that direction.

There are two ways to resolve this:
1) change the directions of all diodes in your keyboard matrix. I would also take out the four 15K pullup-resistors in that case.
or
2) swap rows vs. columns in the firmware: make the rows the columns and vice-versa -- probably the easiest way, with the small disadvantage that polling the whole keyboard takes longer. Should be fast enough nevertheless. The pullup resistors suggest that this was also how the original controller worked.

Morinaka

26 Jul 2015, 16:11

Halvar wrote: In your matrix.c file, you're using the same pins for rows and columns that Matteo used in his example. Is that on purpose? Did you wire your board to the Teensy in the same way?

For example, you have only four rows on you keyboard, and you're using a five row matrix.
The number of rows and columns were pretty similar to the guide so it just seemed logical to me to use the same or similar layout for this. I set up a five row matrix because i wanted to use the BREAK key for something, in my case as a FN0 for a second layer. The BREAK key is just on its own with its own pin and goes low when pressed, on the Acorn Electron this key goes directly to a RESET pin on a 6502A processor and reboots the whole machine.
Halvar wrote: 1) change the directions of all diodes in your keyboard matrix. I would also take out the four 15K pullup-resistors in that case.
or
2) swap rows vs. columns in the firmware: make the rows the columns and vice-versa -- probably the easiest way, with the small disadvantage that polling the whole keyboard takes longer. Should be fast enough nevertheless. The pullup resistors suggest that this was also how the original controller worked.
1) I might do the first option later on as it would be a more permanent fix, would you replace the resistors with wire links or just remove so there is no 5V on lines?

2) How would i alter the firmware to achieve that? While the firmware is great and all the documentation seems pretty sparse (to me at least) on how to alter it for things like you suggest. I'm familiar with programming but not the syntax of the AVR IO libraries or able to do lots of C bitwise stuff in my head.

I just tried this in the matrix.c but only some of the keys will output but not what they should, the BREAK key outputs the 4rfv column in one go.

Code: Select all

/* Row pin configuration
 * row: 0   1   2   3   4
 * pin: F0  F1  F4  F5  F6
 */
static void  init_cols(void)
{
    // Input with pull-up(DDR:0, PORT:1)
    DDRF  &= ~(1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
    PORTF |=  (1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
}

static matrix_row_t read_cols(void)
{
    return (PINF&(1<<0) ? 0 : (1<<0)) |
           (PINF&(1<<1) ? 0 : (1<<1)) |
           (PINF&(1<<4) ? 0 : (1<<2)) |
           (PINF&(1<<5) ? 0 : (1<<3)) |
           (PINF&(1<<6) ? 0 : (1<<4));
}

/* Column pin configuration
 * col: 0   1   2   3   4   5   6   7   8   9   10  11  12  13
 * pin: F7  B6  B5  B4  D7  C7  C6  D3  D2  D1  D0  B7  B3  B2  (Rev.A)
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect
    DDRF  &= ~0b10000000;
    PORTF &= ~0b10000000;
    DDRD  &= ~0b10001111;
    PORTD &= ~0b10001111;
    DDRC  &= ~0b11000000;
    PORTC &= ~0b11000000;
    DDRB  &= ~0b11111100;
    PORTB &= ~0b11111100;
}

static void select_row(uint8_t row)
{
    // Output low(DDR:1, PORT:0) to select
    switch (row) {
        case 0:
            DDRF  |= (1<<7);
            PORTF &= ~(1<<7);
            break;
        case 1:
            DDRD  |= (1<<7);
            PORTD &= ~(1<<7);
            break;
        case 2:
            DDRD  |= (1<<3);
            PORTD &= ~(1<<3);
            break;
        case 3:
            DDRD  |= (1<<2);
            PORTD &= ~(1<<2);
            break;
        case 4:
            DDRD  |= (1<<1);
            PORTD &= ~(1<<1);
            break;
        case 5:
            DDRD  |= (1<<0);
            PORTD &= ~(1<<0);
            break;
        case 6:
            DDRC  |= (1<<7);
            PORTC &= ~(1<<7);
            break;
        case 7:
            DDRC  |= (1<<6);
            PORTC &= ~(1<<6);
            break;
        case 8:
            DDRB  |= (1<<7);
            PORTB &= ~(1<<7);
            break;
        case 9:
            DDRB  |= (1<<6);
            PORTB &= ~(1<<6);
            break;
        case 10:
            DDRB  |= (1<<5);
            PORTB &= ~(1<<5);
            break;
        case 11:
            DDRB  |= (1<<4);
            PORTB &= ~(1<<4);
            break;
        case 12:
            DDRB  |= (1<<3);
            PORTB &= ~(1<<3);
            break;
        case 13:
            DDRB  |= (1<<2);
            PORTB &= ~(1<<2);
            break;
    }
}

User avatar
Halvar

26 Jul 2015, 20:22

Morinaka wrote: 1) I might do the first option later on as it would be a more permanent fix, would you replace the resistors with wire links or just remove so there is no 5V on lines?
No no, you'd have to just remove them, if you bridge them nothing will work (EDIT:) you might destroy something, as Ray rightly stated.
2) How would i alter the firmware to achieve that? While the firmware is great and all the documentation seems pretty sparse (to me at least) on how to alter it for things like you suggest. I'm familiar with programming but not the syntax of the AVR IO libraries or able to do lots of C bitwise stuff in my head.

I just tried this in the matrix.c but only some of the keys will output but not what they should, the BREAK key outputs the 4rfv column in one go.
Looks good to me except for the function select_row() where the rows seem to be in the wrong order.
Last edited by Halvar on 26 Jul 2015, 22:05, edited 1 time in total.

User avatar
Ray

26 Jul 2015, 20:42

the matrix.c looks like it is mostly correct, now you have to change your KEYMAP macro in keymap_poker.c (edit: keymap_common.h). For that, make the first part to look like your keyboard. The second part needs to be 14 pairs of curly braces, each containing 5 "values".
After that, change your layout in keymap_poker.c to match the format of the first part of the KEYMAP macro you just did before.

Edit: and don't bridge the pullups! you might fry your µC (or at least damage some outputs if you set them low - and short them out). Or if you do the rest right, it will only fry the protection diodes.

Morinaka

27 Jul 2015, 13:01

Halvar wrote: No no, you'd have to just remove them, if you bridge them nothing will work (EDIT:) you might destroy something, as Ray rightly stated.
Noted, thanks both of you.
Halvar wrote: Looks good to me except for the function select_row() where the rows seem to be in the wrong order.
Ray wrote: the matrix.c looks like it is mostly correct, now you have to change your KEYMAP macro in keymap_poker.c (edit: keymap_common.h). For that, make the first part to look like your keyboard. The second part needs to be 14 pairs of curly braces, each containing 5 "values".
After that, change your layout in keymap_poker.c to match the format of the first part of the KEYMAP macro you just did before.
Thanks for this, took me a little while but i figured out how to make it work. I also had two wires hooked up wrong so i fixed that as well. Typing this post on the keyboard now even if it is a little awkward, really need to put a backspace key somewhere on it. Thank you both very much for you help with this.

This is what my keymap in the keymap_common.h looks like now

Code: Select all

#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    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, K2C,      \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
                                                                     K4D  \
) { \
    { KC_##K00, KC_##K10, KC_##K20, KC_##K30, KC_##K30 }, \
    { KC_##K01, KC_##K11, KC_##K21, KC_##K31, KC_NO }, \
    { KC_##K02, KC_##K12, KC_##K22, KC_##K32, KC_NO }, \
    { KC_##K03, KC_##K13, KC_##K23, KC_##K33, KC_NO }, \
    { KC_##K04, KC_##K14, KC_##K24, KC_##K34, KC_NO }, \
    { KC_##K05, KC_##K15, KC_##K25, KC_##K35, KC_NO }, \
    { KC_##K06, KC_##K16, KC_##K26, KC_##K36, KC_NO }, \
    { KC_##K07, KC_##K17, KC_##K27, KC_##K37, KC_NO }, \
    { KC_##K08, KC_##K18, KC_##K28, KC_##K38, KC_NO }, \
    { KC_##K09, KC_##K19, KC_##K29, KC_##K39, KC_NO }, \
    { KC_##K0A, KC_##K1A, KC_##K2A, KC_##K3A, KC_NO }, \
    { KC_##K0B, KC_##K1B, KC_##K2B, KC_NO,    KC_NO }, \
    { KC_##K0C, KC_##K1C, KC_##K2C, KC_##K3C, KC_NO }, \
    { KC_##K0D, KC_##K1D, KC_NO,    KC_##K3D, KC_##K4D } \
}
I have a software question that might not even be possible to do with USB HID. This keyboard is non-standard as you can see from this photo particularly some of the punctuation keys. Is it possible to change the firmware to make the keycaps match the output on screen? So if i do shift+semicolon to get + instead of the usual :

The keymap.md file talks of action keys and macros, could i use those to accomplish this?

Post Reply

Return to “Workshop”