How to build your very own keyboard firmware

John^2

05 Apr 2016, 03:04

That backslash DID allow me to compile, but I am still getting outputs of random characters; so it is probably still something else I messed up. Thank you for the help though!

Bloodhoundje

22 Apr 2016, 14:18

Hi everyone,

I have recently gotten interested in building my own little keyboard. I am a left handed mouse user with RSI and was annoyed by the fact that there is no right handed version of the Razer orbweaver.
I designed a small 22 keys ergoboard. For the software part I decided to follow the guide from this topic.

After following the guide and modifying the files (gh60) to suit a 22 key-board I keep running into errors while trying to compile:

Code: Select all

keymap_poker.c:21: error: 'KC_K00' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K01' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K02' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K03' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K04' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K11' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K12' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K13' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K14' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K15' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K21' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K22' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K23' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K24' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K25' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K31' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K32' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K33' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K34' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K35' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K43' undeclared here (not in a function)
keymap_poker.c:21: error: 'KC_K45' undeclared here (not in a function)
make: *** [obj_gh60_lufa/keymap_poker.o] Error 1
The files I have modified for my keyboard:

matrix.c

Code: Select all

#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"


#ifndef DEBOUNCE
#   define DEBOUNCE	5
#endif
static uint8_t debouncing = DEBOUNCE;

/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

static matrix_row_t read_cols(void);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);


inline
uint8_t matrix_rows(void)
{
    return MATRIX_ROWS;
}

inline
uint8_t matrix_cols(void)
{
    return MATRIX_COLS;
}

void matrix_init(void)
{
    // initialize row and col
    unselect_rows();
    init_cols();

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
        matrix[i] = 0;
        matrix_debouncing[i] = 0;
    }
}

uint8_t matrix_scan(void)
{
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        select_row(i);
        _delay_us(30);  // without this wait read unstable value.
        matrix_row_t cols = read_cols();
        if (matrix_debouncing[i] != cols) {
            matrix_debouncing[i] = cols;
            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_ROWS; i++) {
                matrix[i] = matrix_debouncing[i];
            }
        }
    }

    return 1;
}

bool matrix_is_modified(void)
{
    if (debouncing) return false;
    return true;
}

inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
    return (matrix[row] & ((matrix_row_t)1<<col));
}

inline
matrix_row_t matrix_get_row(uint8_t row)
{
    return matrix[row];
}

void matrix_print(void)
{
    print("\nr/c 0123456789ABCDEF\n");
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        phex(row); print(": ");
        pbin_reverse16(matrix_get_row(row));
        print("\n");
    }
}

uint8_t matrix_key_count(void)
{
    uint8_t count = 0;
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        count += bitpop16(matrix[i]);
    }
    return count;
}


/* Column pin configuration Bloodhoundje
 * col: 0   1   2   3   4   5  
 * pin: B0  B1  B2  B3  B7  D0 
 */
static void  init_cols(void)
{
    // Input with pull-up(DDR:0, PORT:1)
	DDRD  &= ~(1<<0);
	PORTD |=  (1<<0);
			
	DDRB  &= ~(1<<7 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
	PORTB |=  (1<<7 | 1<<3 | 1<<2 | 1<<1 | 1<<0);

}

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

/* Row pin configuration Bloodhoundje
 * row: 0   1   2   3   4
 * pin: D1  D2  D3  C6  C7
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect

    DDRD  &= ~0b00001110;
    PORTD &= ~0b00001110;
		
    DDRC  &= ~0b11000000;
    PORTC &= ~0b11000000;
}

static void select_row(uint8_t row)
{
    // Output low(DDR:1, PORT:0) to select
    switch (row) {
        case 0:
            DDRD  |= (1<<1);
            PORTD &= ~(1<<1);
            break;
        case 1:
            DDRD  |= (1<<2);
            PORTD &= ~(1<<2);
            break;
        case 2:
            DDRD  |= (1<<3);
            PORTD &= ~(1<<3);
            break;
        case 3:
            DDRC  |= (1<<6);
            PORTC &= ~(1<<6);
            break;
        case 4:
            DDRC  |= (1<<7);
            PORTC &= ~(1<<7);
            break;
    }
}

config.h

Code: Select all

#ifndef CONFIG_H
#define CONFIG_H


/* USB Device descriptor parameter */
#define VENDOR_ID       0xFEED
#define PRODUCT_ID      0x6060
#define DEVICE_VER      0x0001
#define MANUFACTURER    -
#define PRODUCT         Bloodhoundje
#define DESCRIPTION     Right Handed Gamepad For Left Handed Mouse Users

/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 6

/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST

/* Set 0 if debouncing isn't needed */
#define DEBOUNCE    5

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/* key combination for command */
#define IS_COMMAND() ( \
    keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)



/*
 * Feature disable options
 *  These options are also useful to firmware size reduction.
 */

/* disable debug print */
//#define NO_DEBUG

/* disable print */
//#define NO_PRINT

/* disable action features */
#define NO_ACTION_LAYER
#define NO_ACTION_TAPPING
#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION

#endif
led.c

Code: Select all

#include <avr/io.h>
#include "stdint.h"
#include "led.h"


void led_set(uint8_t usb_led)
{
    if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
        // output low
        DDRD |= (1<<4);
        PORTD &= ~(1<<4);
    } else {
        // Hi-Z
        DDRB &= ~(1<<4);
        PORTB &= ~(1<<4);
    }
}
keymap_common.h

Code: Select all

#ifndef KEYMAP_COMMON_H
#define KEYMAP_COMMON_H

#include <stdint.h>
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "keycode.h"
#include "action.h"
#include "action_macro.h"
#include "report.h"
#include "host.h"
#include "print.h"
#include "debug.h"
#include "keymap.h"


extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];

/*
 Matrix col/row mapping

 ,-----------------------------------.
 |    |0/4 |0/3 |0/2 |0/1 |    |0/0  |
 |-----------------------------------|
 |1/5   |1/4 |1/3 |1/2 |1/1 |        |
 |-----------------------------------|
 |2/5    |2/4 |2/3 |2/2 |2/1 |       |
 |-----------------------------------|
 |3/5     |3/4 |3/3 |3/2 |3/1 |      |
 |-----------------------------------|
 |4/5      |     4/3 |               |
 `-----------------------------------'
 */
#define KEYMAP( \
K00, K01, K02, K03, K04, \
K11, K12, K13, K14, K15, \
K21, K22, K23, K24, K25, \
K31, K32, K33, K34, K35, \
K43, K45 \
) { \
	{KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_NO	}, \
	{KC_NO,    KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15 }, \
	{KC_NO,    KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25 }, \
	{KC_NO,    KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35 }, \
	{KC_NO,    KC_NO,    KC_NO,    KC_##K43, KC_NO,    KC_##K45 } \
}


#endif
keymap_poker.c

Code: Select all

#include "keymap_common.h"

 const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
 Matrix col/row mapping

 ,-----------------------------------.
 |    |0/4 |0/3 |0/2 |0/1 |    |0/0  |
 |-----------------------------------|
 |1/5   |1/4 |1/3 |1/2 |1/1 |        |
 |-----------------------------------|
 |2/5    |2/4 |2/3 |2/2 |2/1 |       |
 |-----------------------------------|
 |3/5     |3/4 |3/3 |3/2 |3/1 |      |
 |-----------------------------------|
 |4/5      |     4/3 |               |
 `-----------------------------------'
 */

/* 0: Special keyboard */ 
KEYMAP(    1,   2,   3,   4,   PAUS, \
		TAB, Q,   W,   E,   R,   \
		G,   A,   S,   D,   F,   \
		LSFT,Z,   X,   C,   V,   \
		LCTL,     SPC),
};

 const uint16_t PROGMEM fn_actions[] = {};
I have rebuild the files 3 times now with the guide, thinking I probally made a small typing mistake somewhere.
My assumption is I am misinterpreting the way the 'KEYMAP' function works. It would be awesome if someone could point me in the right direction.

Once the keyboard is complete I will make the STL files available for anyone who wants to build one ofcourse (it's fully 3d printable for printers with 12cm*12cm*12cm work surface or larger :mrgreen: ).

User avatar
Ray

22 Apr 2016, 17:20

Do you have keymap_poker.c in the "SRC = ..." list in the Makefile?

Bloodhoundje

22 Apr 2016, 17:25

Ray wrote: Do you have keymap_poker.c in the "SRC = ..." list in the Makefile?

Yes I do, my Makefile is as follow:

Code: Select all

#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
#                Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
#               (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
#            have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
#             have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
#               (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
#                (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging, 
#              with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
#                   bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# Target file name (without extension).
TARGET = gh60_lufa

# Directory common source filess exist
TMK_DIR = ../../tmk_core

# Directory keyboard dependent files exist
TARGET_DIR = .

# project specific files
SRC =	keymap_common.c \
	matrix.c \
	led.c

ifdef KEYMAP
    SRC := keymap_$(KEYMAP).c $(SRC)
else
    SRC := keymap_poker.c $(SRC)
endif

CONFIG_H = config.h


# MCU name
#MCU = at90usb1287
MCU = atmega32u4

# Processor frequency.
#     This will define a symbol, F_CPU, in all source code files equal to the
#     processor frequency in Hz. You can then use this symbol in your source code to
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
#     automatically to create a 32-bit value in your source code.
#
#     This will be an integer division of F_USB below, as it is sourced by
#     F_USB after it has run through any CPU prescalers. Note that this value
#     does not *change* the processor frequency - it should merely be updated to
#     reflect the processor speed set externally so that the code can use accurate
#     software delays.
F_CPU = 16000000


#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Input clock frequency.
#     This will define a symbol, F_USB, in all source code files equal to the
#     input clock frequency (before any prescaling is performed) in Hz. This value may
#     differ from F_CPU if prescaling is used on the latter, and is required as the
#     raw input clock is fed directly to the PLL sections of the AVR for high speed
#     clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
#     at the end, this will be done automatically to create a 32-bit value in your
#     source code.
#
#     If no clock division is performed on the input clock inside the AVR (via the
#     CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)

# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Boot Section Size in *bytes*
#   Teensy halfKay   512
#   Teensy++ halfKay 1024
#   Atmel DFU loader 4096
#   LUFA bootloader  4096
#   USBaspLoader     2048
OPT_DEFS += -DBOOTLOADER_SIZE=4096


# Build Options
#   comment out to disable the options.
#
BOOTMAGIC_ENABLE = yes	# Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes	# Mouse keys(+4700)
EXTRAKEY_ENABLE = yes	# Audio control and System control(+450)
CONSOLE_ENABLE = yes	# Console for debug(+400)
COMMAND_ENABLE = yes    # Commands for debug and configuration
#SLEEP_LED_ENABLE = yes  # Breathing sleep LED during USB suspend
NKRO_ENABLE = yes	# USB Nkey Rollover - not yet supported in LUFA


# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)

include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk
If I run Makefile on the non modified files it completes without errors. Only after having modified the files in my previous post it refuses to compile.

Also After removing the 'ifdef KEYMAP' from the makefile and directly adding keymap_poker.c to the SRC list as:

Code: Select all

# project specific files
SRC =	keymap_common.c \
	matrix.c \
	led.c \
     keymap_poker.c 
The same compiling error occurs.

User avatar
Ray

22 Apr 2016, 18:05

I tried your files (minus matrix.c and led.c) and it compiles fine. No clue where your error comes from. Maybe someone else can help.

Bloodhoundje

24 Apr 2016, 13:18

I have tried replacing the matrix.c and led.c with the original files to see if this might fix the issue. No luck again, exactly the same error.

I am trying to compile the files with the latest version of win avr-gcc under windows 8.1. Tried it on both my desktop and laptop to make sure the issue isnt caused by a corrupted installer.

Is there anyone else who uses win avr-gcc? Or are there people using cygwin?

User avatar
beltet

25 Apr 2016, 00:49

Hi.
I have now almost made my first custom TMK board.
But I have one remaining problem....

The goal is to make a 5x5 keypad, had some errors when compiling but sorted them out. And the keyboard works... almost...

The thing is that row 4(every key) buttons activates their entire coloumn. I have tried to degub the wiring, but it seems like it should be. So I think it is the matrix.c that is the problem. I post it here for reference:

Code: Select all

/*
Copyright 2012 Jun Wako <wakojun@gmail.com>

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
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
 * scan matrix
 */
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"


#ifndef DEBOUNCE
#   define DEBOUNCE	5
#endif
static uint8_t debouncing = DEBOUNCE;

/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
static matrix_row_t matrix_debouncing[MATRIX_ROWS];

static matrix_row_t read_cols(void);
static void init_cols(void);
static void unselect_rows(void);
static void select_row(uint8_t row);


inline
uint8_t matrix_rows(void)
{
    return MATRIX_ROWS;
}

inline
uint8_t matrix_cols(void)
{
    return MATRIX_COLS;
}

void matrix_init(void)
{
    // initialize row and col
    unselect_rows();
    init_cols();

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
        matrix[i] = 0;
        matrix_debouncing[i] = 0;
    }
}

uint8_t matrix_scan(void)
{
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        select_row(i);
        _delay_us(30);  // without this wait read unstable value.
        matrix_row_t cols = read_cols();
        if (matrix_debouncing[i] != cols) {
            matrix_debouncing[i] = cols;
            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_ROWS; i++) {
                matrix[i] = matrix_debouncing[i];
            }
        }
    }

    return 1;
}

bool matrix_is_modified(void)
{
    if (debouncing) return false;
    return true;
}

inline
bool matrix_is_on(uint8_t row, uint8_t col)
{
    return (matrix[row] & ((matrix_row_t)1<<col));
}

inline
matrix_row_t matrix_get_row(uint8_t row)
{
    return matrix[row];
}

void matrix_print(void)
{
    print("\nr/c 0123456789ABCDEF\n");
    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
        phex(row); print(": ");
        pbin_reverse16(matrix_get_row(row));
        print("\n");
    }
}

uint8_t matrix_key_count(void)
{
    uint8_t count = 0;
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        count += bitpop16(matrix[i]);
    }
    return count;
}

/* Column pin configuration
 * col: 0   1   2   3   4   5   6   7   8   9   10  11  12  13
 * pin: F0  F1  E6  C7  C6  B6  D4  B1  B0  B5  B4  D7  D6  B3  (Rev.A)
 * pin:                                 B7                      (Rev.B)
 */
static void  init_cols(void)
{
    // Input with pull-up(DDR:0, PORT:1)
    DDRE  &= ~(1<<6);
    PORTE |=  (1<<6);
    DDRD  &= ~(1<<0 | 1<<4 | 1<<7);
    PORTD |=  (1<<0 | 1<<4 | 1<<7);
    DDRC  &= ~(1<<6);
    PORTC |=  (1<<6);
}

static matrix_row_t read_cols(void)
{
    return (PINE&(1<<6) ? 0 : (1<<0)) |
           (PIND&(1<<7) ? 0 : (1<<1)) |
           (PINC&(1<<6) ? 0 : (1<<2)) |
           (PIND&(1<<4) ? 0 : (1<<3)) |
           (PIND&(1<<0) ? 0 : (1<<4));
           
}

/* Row pin configuration
 * row: 0   1   2   3   4
 * pin: D0  D1  D2  D3  D5
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect
    DDRF  &= ~0b01111000;
    PORTF &= ~0b01111000;
	DDRB  &= ~0b00000010;
    PORTB &= ~0b00000010;
}

static void select_row(uint8_t row)
{
    // Output low(DDR:1, PORT:0) to select
    switch (row) {
        case 0:
            DDRF  |= (1<<4);
            PORTF &= ~(1<<4);
            break;
        case 1:
            DDRF  |= (1<<5);
            PORTF &= ~(1<<5);
            break;
        case 2:
            DDRF  |= (1<<6);
            PORTF &= ~(1<<6);
            break;
        case 3:
            DDRF  |= (1<<7);
            PORTF &= ~(1<<7);
            break;
        case 4:
            DDRB  |= (1<<1);
            PORTB &= ~(1<<1);
            break;
    }
}
Hopefully you can point me where the problem is.

Bloodhoundje

25 Apr 2016, 01:00

beltet wrote: Hi.
I have now almost made my first custom TMK board.
But I have one remaining problem....

The goal is to make a 5x5 keypad, had some errors when compiling but sorted them out. And the keyboard works... almost...

The thing is that row 4(every key) buttons activates their entire coloumn. I have tried to degub the wiring, but it seems like it should be. So I think it is the matrix.c that is the problem. I post it here for reference:

..............

Hopefully you can point me where the problem is.
It seems like the rows have been set wrong:


static void unselect_rows(void)
{
// Hi-Z(DDR:0, PORT:0) to unselect
DDRF &= ~0b01111000; you are selecting rows 6,5,4,3
PORTF &= ~0b01111000;
DDRB &= ~0b00000010; you are selecting row 1
PORTB &= ~0b00000010;
}

static void select_row(uint8_t row)
{
// Output low(DDR:1, PORT:0) to select
switch (row) {

case 0:
DDRF |= (1<<4);
PORTF &= ~(1<<4);
break;
case 1:
DDRF |= (1<<5);
PORTF &= ~(1<<5);
break;
case 2:
DDRF |= (1<<6);
PORTF &= ~(1<<6);
break;
case 3:
DDRF |= (1<<7);
PORTF &= ~(1<<7);
break;

case 4:
DDRB |= (1<<1);
PORTB &= ~(1<<1);
break;
}


I think you have to replace case 0-3 with port 6,5,4,3 or fix the binary so it matches the ports you are trying to use in the cases 0-3

User avatar
beltet

25 Apr 2016, 23:17

Bloodhoundje wrote:
beltet wrote: Hi.
Spoiler:
I have now almost made my first custom TMK board.
But I have one remaining problem....

The goal is to make a 5x5 keypad, had some errors when compiling but sorted them out. And the keyboard works... almost...

The thing is that row 4(every key) buttons activates their entire coloumn. I have tried to degub the wiring, but it seems like it should be. So I think it is the matrix.c that is the problem. I post it here for reference:

..............

Hopefully you can point me where the problem is.
Spoiler:
It seems like the rows have been set wrong:


static void unselect_rows(void)
{
// Hi-Z(DDR:0, PORT:0) to unselect
DDRF &= ~0b01111000; you are selecting rows 6,5,4,3
PORTF &= ~0b01111000;
DDRB &= ~0b00000010; you are selecting row 1
PORTB &= ~0b00000010;
}

static void select_row(uint8_t row)
{
// Output low(DDR:1, PORT:0) to select
switch (row) {

case 0:
DDRF |= (1<<4);
PORTF &= ~(1<<4);
break;
case 1:
DDRF |= (1<<5);
PORTF &= ~(1<<5);
break;
case 2:
DDRF |= (1<<6);
PORTF &= ~(1<<6);
break;
case 3:
DDRF |= (1<<7);
PORTF &= ~(1<<7);
break;

case 4:
DDRB |= (1<<1);
PORTB &= ~(1<<1);
break;
}


I think you have to replace case 0-3 with port 6,5,4,3 or fix the binary so it matches the ports you are trying to use in the cases 0-3

Aaaah, great thanks! I fell into the hole of counting without the zero. Thanks for spotting that for me.

e_l_tang

26 Apr 2016, 08:18

After one row is selected, why are all the rows unselected afterwards? Isn't it only necessary to unselect the one that was selected?

User avatar
flabbergast

26 Apr 2016, 08:24

Yes, but the function unselect_rows doesn't know which one is selected. IMO, with this function structure, it's computationally more expensive to keep track of which row is selected (and pass it as a function parameter, and require another switch() or some ifs), than just switch them all off. Statements like the ones currently in unselect_rows only take a very few assembly instructions.

Kanzakisol

26 Apr 2016, 22:51

Hoping someone could help a beginner out, I was reading through this thread and was trying to build a prototype for a single row 5 button keyboard. I'm building it on a breadboard first to test, but I'm having issues with only the number 3 being spammed (col 3 in my code). I'm not really sure what's the issue (whether it's my physical setup or code) here's my setup
http://imgur.com/CPCbcdq
and my gh60 files. Thanks for any help (also I'm using Teensy ++2.0)!
Attachments
gh60.zip
(618.84 KiB) Downloaded 183 times

e_l_tang

27 Apr 2016, 01:33

Thanks, @flabbergast. That's what I suspected. I have one more question. Why is PORTx modified when rows are selected and unselected? Isn't it enough just to modify DDRx?

e_l_tang

27 Apr 2016, 08:57

@Kanzakisol The function in led.c is trying to use pin B2. You have to either use to a different pin or comment out everything in that function.
Last edited by e_l_tang on 28 Apr 2016, 00:33, edited 1 time in total.

User avatar
flabbergast

27 Apr 2016, 10:44

In this case, it is not necessary to zero the PORTx bits, because both places that access PORTx want the bits to be zero. I suppose it is just for completeness, in case something else in the code modifies PORTx bits.

Bloodhoundje

27 Apr 2016, 11:19

I still keep running into the same compiling errors, could someone try to compile the customized gh60 files for me? Would like to know if it compiles (if it does the .hex file is appreciated :) ), and if it doesnt compile I would like to know what's the error message you receive.

Hopefully with that information I can troubleshoot and figure out what is going wrong for me right now.

I have attached a .rar file with the gh60 folder in it.
Thanks in advance for helping me figure this out and getting my keyboard to work :).
Attachments
gh60_modified.rar
Modified gh60 keyboard files for my small keyboard
(314.76 KiB) Downloaded 164 times

User avatar
flabbergast

27 Apr 2016, 15:33

You are missing some hashes, here's a modified keymap_common.h that compiles for me: https://gist.github.com/7a7008e64eb5615 ... 16283a19d1

Bloodhoundje

27 Apr 2016, 15:52

flabbergast wrote: You are missing some hashes, here's a modified keymap_common.h that compiles for me: https://gist.github.com/7a7008e64eb5615 ... 16283a19d1
Thank you very much flabbergast, that indeed was the issue. Just compiled flawlessly and my keyboard is up and running :mrgreen: .

Will soon post 3d files etc for if anyone else wants to attempt building one :)

Kanzakisol

27 Apr 2016, 17:51

@Flabbergast Thanks! That fixed the issue of constantly outputting the 3, however, I still can't get the keyboard to work. None of the buttons work even after compiling and uploading. At this point I'm thinking maybe it's my physical setup? Any ideas?

e_l_tang

27 Apr 2016, 21:35

@Kanzakisol @flabbergast never replied to any of your comments. Are you replying to my comment?

Kanzakisol

27 Apr 2016, 22:30

lol whoops! yes I was replying to you guess my eye strayed a line too low.

e_l_tang

28 Apr 2016, 00:38

@Kanzakisol It appears that the three diodes towards the bottom of your image are backwards. The black stripe on each diode marks the side into which current cannot enter. Why did you use them in the first place, though? You don't need them because you have one row.

Kanzakisol

29 Apr 2016, 16:31

@Eric-T sorry fell off the grid there. Those were actually resistors which makes it even more embarrassing because they 1) shouldn't have been configured that way and 2) from what I read the teensy doesn't need pull-up resistors lol. Though it's good to know that I actually didn't need diodes for the row (was really unsure if I did). I ended up fixing it but the final solution ended up being redoing my piss poor soldering job. Works like a charm now!

sachin3767

12 May 2016, 15:12

Hi,

I followed all the steps and made the necessary changes in each file. However, I am now getting the below error message. I have taken a snippet of the CMD prompt screen.

thanks,

"avr-gcc.exe - Application Error
The application was unable to start correctly (0xc0000142). Click OK to close the application"


C:\tmk_keyboard-master\tmk_keyboard-master\keyboard\
six_key_pad>make -f Makefile
0 [main] sh 14808 sync_with_child: child 1164(0x164) died before initializ
ation with status code 0xC0000142
224 [main] sh 14808 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 5856 sync_with_child: child 6476(0x164) died before initializa
tion with status code 0xC0000142
194 [main] sh 5856 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 12832 sync_with_child: child 12136(0x164) died before initiali
zation with status code 0xC0000142
186 [main] sh 12832 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 7432 sync_with_child: child 12716(0x164) died before initializ
ation with status code 0xC0000142
149 [main] sh 7432 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 11512 sync_with_child: child 12636(0x164) died before initiali
zation with status code 0xC0000142
555 [main] sh 11512 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


mkdir -p obj_gh60_lufa
Compiling C: keymap_poker.c
avr-gcc -c -mmcu=atmega32u4 -gdwarf-2 -DF_CPU=16000000UL -DINTERRUPT_CONTROL_END
POINT -DBOOTLOADER_SIZE=4096 -DF_USB=16000000UL -DARCH=ARCH_AVR8 -DUSB_DEVICE_ON
LY -DUSE_FLASH_DESCRIPTORS -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB
_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DFIXED_N
UM_CONFIGURATIONS=1 -DPROTOCOL_LUFA -DBOOTMAGIC_ENABLE -DMOUSEKEY_ENABLE -DMOUSE
_ENABLE -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DVERSION= -Os -funs
igned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-
small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-
prototypes -Wa,-adhlns=obj_gh60_lufa/keymap_poker.lst -I. -I../../tmk_core -I../
../tmk_core/protocol/lufa -I../../tmk_core/protocol/lufa/LUFA-git -I../../tmk_co
re/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_gh60_lufa_keymap_po
ker.o.d keymap_poker.c -o obj_gh60_lufa/keymap_poker.o
make: *** [obj_gh60_lufa/keymap_poker.o] Error -1073741502

sachin3767

12 May 2016, 15:26

sachin3767 wrote:
Spoiler:
Hi,

I followed all the steps and made the necessary changes in each file. However, I am now getting the below error message. I have taken a snippet of the CMD prompt screen.

thanks,

"avr-gcc.exe - Application Error
The application was unable to start correctly (0xc0000142). Click OK to close the application"


C:\tmk_keyboard-master\tmk_keyboard-master\keyboard\
six_key_pad>make -f Makefile
0 [main] sh 14808 sync_with_child: child 1164(0x164) died before initializ
ation with status code 0xC0000142
224 [main] sh 14808 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 5856 sync_with_child: child 6476(0x164) died before initializa
tion with status code 0xC0000142
194 [main] sh 5856 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 12832 sync_with_child: child 12136(0x164) died before initiali
zation with status code 0xC0000142
186 [main] sh 12832 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 7432 sync_with_child: child 12716(0x164) died before initializ
ation with status code 0xC0000142
149 [main] sh 7432 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable
0 [main] sh 11512 sync_with_child: child 12636(0x164) died before initiali
zation with status code 0xC0000142
555 [main] sh 11512 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable

-------- begin --------
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


mkdir -p obj_gh60_lufa
Compiling C: keymap_poker.c
avr-gcc -c -mmcu=atmega32u4 -gdwarf-2 -DF_CPU=16000000UL -DINTERRUPT_CONTROL_END
POINT -DBOOTLOADER_SIZE=4096 -DF_USB=16000000UL -DARCH=ARCH_AVR8 -DUSB_DEVICE_ON
LY -DUSE_FLASH_DESCRIPTORS -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB
_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DFIXED_N
UM_CONFIGURATIONS=1 -DPROTOCOL_LUFA -DBOOTMAGIC_ENABLE -DMOUSEKEY_ENABLE -DMOUSE
_ENABLE -DEXTRAKEY_ENABLE -DCONSOLE_ENABLE -DCOMMAND_ENABLE -DVERSION= -Os -funs
igned-char -funsigned-bitfields -ffunction-sections -fdata-sections -fno-inline-
small-functions -fpack-struct -fshort-enums -fno-strict-aliasing -Wall -Wstrict-
prototypes -Wa,-adhlns=obj_gh60_lufa/keymap_poker.lst -I. -I../../tmk_core -I../
../tmk_core/protocol/lufa -I../../tmk_core/protocol/lufa/LUFA-git -I../../tmk_co
re/common -std=gnu99 -include config.h -MMD -MP -MF .dep/obj_gh60_lufa_keymap_po
ker.o.d keymap_poker.c -o obj_gh60_lufa/keymap_poker.o
make: *** [obj_gh60_lufa/keymap_poker.o] Error -1073741502
Ignore my previous post... I found the solution immediately after posting it.

I had to downgrade a DLL file. See this link and comment: http://smallshire.org.uk/sufficientlysm ... mment-6021

User avatar
flabbergast

12 May 2016, 19:28

@matt3o - could you please please please please update the first post to say that people should *not* use winavr anymore?
It does not work on the newer windowses, produces almost indecipherable errors, and the command line tools that come with it mess up other things as well (someone had "a problem with an ARM toolchain", and the culprit was an old winavr installation).
https://github.com/tmk/tmk_keyboard/issues/99

User avatar
Halvar

12 May 2016, 22:01

@flabbergast: what's your recommendation for Windows then? Atmel has a set of command line tools for download on their site here:

http://www.atmel.com/tools/atmelavrtool ... ndows.aspx

but I have never got around to try it.

Atmel Studio seems pretty good, but it has a totally different workflow (MS Build tools instead of MAKE), which makes it hard to work together on the same software with Linux developers, and impossible for beginners to follow matt3o's tutorial on TMK.

It would be nice to get away from WinAVR, but it still pretty easy to install and it's not too hard to google the necessary patches for newer Windows versions.

Matt_

12 May 2016, 22:23

When I was playing with TMK, I built a Linux VM just for that, with the latest version of Ubuntu in Virtualbox. Quick to setup even for a noob, and everything you need to build the firmware is installed with two command lines.

User avatar
flabbergast

12 May 2016, 23:52

I don't use windows actively, so I can't really tell... perhaps someone else would chip in? There are a few recommended ones in that github bug report.

This looks very nice and recent, just a zip to unpack and no installer which puts who-knows-what-where. I'll try on my wife's laptop.

{It is just that the questions of this type come up about twice a month both here and on GH... and it's usually relatively new people who don't know what to google for.}

User avatar
flabbergast

13 May 2016, 00:57

I like to go vanilla with installations, so:

1) Installed cygwin (one package to select on top of the 'recommended' installation is make; I also installed git). This is really an installer. After installation, the "Cygwin64 Terminal" icon drops one into a familiar shell (oh the relief...)

2) Downloaded avr-gcc. That's a zip, so just unpack it somewhere (I used d:\avr-gcc). Add d:\avr-gcc\bin to PATH (google. it's in 'advanced system settings' -> 'environment variables')

After this {EDIT: probably a reboot}, I just downloaded and unpacked tmk_keyboard, go into cygwin shell, cd to tmk_keyboard_master/keyboard/gh60 and run make. Compiles fine.

However Jack Humbert seems to recommend the inferno tools.

Post Reply

Return to “Workshop”