How to build your very own keyboard firmware

ROFLmonster

08 Feb 2015, 19:30

but this library is written in C++
This is correct. I can't seem to find any I2C libraries like the one from Adafruit, so you'll either have to find an alternative or use a bare LCD without the I2C, like the ones here:
http://www.adafruit.com/products/398
http://www.adafruit.com/products/399
https://www.sparkfun.com/products/10862
But those will require quite a few pins. (6 for the text, 3 for the backlight, 9 in total without VCC/GND/contrast) So you might want to use a Teensy++ 2.0 which will give you more than enough pins, and use AVR libraries for the HD44780 driver. (Google it.)
If i understand correctly your are using FN keys to change RBG values for your strip
If you look in my keymap I have only 2 layers. One default for a normal qwerty layout, and a second one that is for F1-F12, media keys, etc, etc. To change the color I need to activate said layer (FN0) and press FN1-FN7.
So to change to orange for example I need to press FN1 while on the second layer, holding FN0.
ACTION_FUNCTION can take 2 parameters, but for the id parameter, what are the different "values" that id can take?
'id' takes whatever you put after 'ACTION_FUNCTION()'. If you put 'ACTION_FUNCTION(5)', then id=5.
I just made it easier for me to define each 'backlight mode' as a number, like you see in the beginning of my keymap file:

Code: Select all

#define BACKLIGHT_MODE1 1
#define BACKLIGHT_MODE2 2
#define BACKLIGHT_MODE3 3
#define BACKLIGHT_MODE4 4
.....
So when I write 'ACTION_FUNCTION(BACKLIGHT_MODE2)' I actually mean 'ACTION_FUNCTION(2)', so I basically ask if 'id' equals 2 (case BACKLIGHT_MODE2 means 'if(id==BACKLIGHT_MODE2)'). It's an unsigned integer in the size of one byte. (u=unsigned, int=integer, 8=8 bits.) So it can take any number from 0 to 255. (2^3=256)
I asked about BACKLIGHT_MODE2 and not just FN2 because BACKLIGHT_MODE2 is what gets passed, since FN2 has no value.
[2] = ACTION_FUNCTION(BACKLIGHT_MODE2) means send 'BACKLIGHT_MODE2' to 'ACTION_FUNCTION' when FN[2] is pressed.

I don't use switch case often, but I think that'll work too. If not you can always put curly brackets between cases.

Code: Select all

switch (id)
      {
       case FN1:
      {
        lcd.print("FN1 activated");
        lcd.setbacklight(RED);   
        break;
      }
       case FN2:
      {
        lcd.print("FN2 activated");
        lcd.setbacklight(GREEN);
        break;
       }
....

Kaibz

09 Feb 2015, 00:20

Once thank you very much for your very clear explanations and your links.
I'm going to need some time to process all this.
I wish you all the best.

Eafin

15 Feb 2015, 18:28

Hi, I'm having a bit of trouble getting my space bar to work. I'm not sure it's a software issue and I don't think it's a hardware issue either as I've checked for shorts and used several diodes just to be sure. Could someone take a look at my code and make sure it's correct though?

Keymap

Code: Select all

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = KEYMAP( /* Base */
	TAB,     Q,    W,     E,      R,      T,      Y,       U,        I,           O,            P,          BSPC,
	LCTL,   A,    S,      D,      F,       G,      H,       J,        K,          L,            SCLN,   QUOT,
	LSFT,    Z,    X,      C,      V,       B,      N,       M,       COMM, DOT,      UP,        FN3,
	ESC,     PAUS,  LGUI,  LALT,  FN2,  SPC,  FN1,  SLSH,  LEFT,   DOWN,  RGHT), 
[1] = KEYMAP( /* Raise/FN1 */
    GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, TRNS,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MINS, EQL, LBRC, RBRC, BSLS,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MPRV, MPLY, MNXT),
[2] = KEYMAP( /* Lower */
    FN23, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, FN20, TRNS,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN21, FN22, FN24, FN25, FN26,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, VOLU, TRNS,
    TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, VOLD, TRNS)
};

const uint16_t PROGMEM fn_actions[] = {
[1] = ACTION_LAYER_MOMENTARY(1),  // first fn layer
[2] = ACTION_LAYER_MOMENTARY(2),  // second fn layer
[3] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),

[11] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
[12] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
[13] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
[14] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
[15] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
[16] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
[17] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
[18] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
[19] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
[20] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
[21] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
[22] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
[23] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
[24] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
[25] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
[26] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),


};
Matrix

Code: Select all

#include "print.h" 
#include "debug.h" 
#include "util.h" 
#include "matrix.h" 

#ifndef DEBOUNCE 
# define DEBOUNCE 10 
#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; 
} 

static void init_cols(void) 
{ 
    DDRB &= ~(1<<6 | 1<<5 | 1<<4); 
    PORTB |= (1<<6 | 1<<5 | 1<<4); 
    DDRD &= ~(1<<7 | 1<<6 | 1<<4); 
    PORTD |= (1<<7 | 1<<6 | 1<<4); 
    DDRF &= ~(1<<0 | 1<<1 | 1<<4 | 1<<5 | 1<<6 | 1<<7); 
    PORTF |= (1<<0 | 1<<1 | 1<<4 | 1<<5 | 1<<6 | 1<<7); 
} 
static matrix_row_t read_cols(void) 
{ 
    return (PIND&(1<<4) ? 0 : (1<<0)) | 
    (PIND&(1<<6) ? 0 : (1<<1)) | 
    (PIND&(1<<7) ? 0 : (1<<2)) | 
    (PINB&(1<<4) ? 0 : (1<<3)) | 
    (PINB&(1<<5) ? 0 : (1<<4)) | 
    (PINB&(1<<6) ? 0 : (1<<5)) | 
    (PINF&(1<<7) ? 0 : (1<<6)) | 
    (PINF&(1<<6) ? 0 : (1<<7)) | 
    (PINF&(1<<5) ? 0 : (1<<8)) | 
    (PINF&(1<<4) ? 0 : (1<<9)) | 
    (PINF&(1<<1) ? 0 : (1<<10)) | 
    (PINF&(1<<0) ? 0 : (1<<11)); 
} 
static void unselect_rows(void) 
{ 
    DDRB &= ~(1<<1 | 1<<2 | 1<<3 | 1<<7); 
    PORTB |= (1<<1 | 1<<2 | 1<<3 | 1<<7); 
}
static void select_row(uint8_t row) 
{
    switch (row) 
    {
        case 0: 
            DDRB |= (1<<1); 
            PORTB &= ~(1<<1); 
            break; 
        case 1: 
            DDRB |= (1<<2); 
            PORTB &= ~(1<<2); 
            break; 
        case 2: 
            DDRB |= (1<<3); 
            PORTB &= ~(1<<3); 
            break; 
        case 3: 
            DDRB |= (1<<7); 
            PORTB &= ~(1<<7); 
            break; 
    }
}
Keymap Common

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[];


/* GH60 keymap definition macro
 * K2C, K31 and  K3C are extra keys for ISO
 */
#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
    K30, K31, K32, K33, K34, K35, K37, K38, K39, K3A, K3B \
) { \
    { 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_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, }, \
    { 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_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_NO, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B } \
}
Config

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    Jack
#define PRODUCT         Planck
#define DESCRIPTION     t.m.k. keyboard firmware for Planck

/* key matrix size */
#define MATRIX_ROWS 4
#define MATRIX_COLS 12

/* 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)) \
)
Thank you very much

ROFLmonster

15 Feb 2015, 19:09

Try switching between the K35 and KC_NO, calling it K36, instead. I had some problems with my 2u keys, too and just 'playing around' with the keys solved it.

Eafin

15 Feb 2015, 19:28

Hmm, will this work correctly though? My spacebar is wired on column 5.
Edit: haha this actually worked! It seemed very counterintuitive but somehow worked out. Thanks for your advice.

ROFLmonster

15 Feb 2015, 21:50

It's because you have to look at it like a mirror. When you look at your board from the bottom to see how your matrix is wired it's actually mirrored from how you'd actually use it.

That's just my theory, glad to see it worked!

Kaibz

18 Feb 2015, 03:51

Hi,

I've been trying to make a very simple 5X2 matrix on a breadboard as a test before building my keyboard Image


Now i have spent 8 hours straight trying to understand why i can not get the second row (lower) to work, i mean no key is outputed on the screen, but row number one works perfectly. Of course i have checked every single component and connection,but i'm almost sure it's a software issue as, at some point i think i managed to enable the debug mode and i got random keys displayed pressing keys on the second row.

when i compile i don't get any errors but i get a warning which is:

keymap_poker.c:5: warning: excess elements in array initializer
keymap_poker.c:5: warning: (near initialization for 'keymaps[0][0]')
keymap_poker.c:5: warning: excess elements in array initializer
keymap_poker.c:5: warning: (near initialization for 'keymaps[0][0]')
keymap_poker.c:5: warning: excess elements in array initializer
keymap_poker.c:5: warning: (near initialization for 'keymaps[0][0]')
keymap_poker.c:5: warning: excess elements in array initializer
keymap_poker.c:5: warning: (near initialization for 'keymaps[0][0]')
keymap_poker.c:5: warning: excess elements in array initializer
keymap_poker.c:5: warning: (near initialization for 'keymaps[0][0]')

I get this warning 10 times and this is the exact number of keys i have so i suppose something is wrong there. But i also wonder if it's not coming from my compiler itself, i'm on windows 7 64 bits, using Cygwin to launch the makefile, i'm using winAvr, i use a Teensy 2.0 and use teensyloader.My collums are wired to B0, B1, B2, B3 and D1 and the rows to F0 and B6.

Would anyone be kind enough to compile for me and see it the warnings are the same? Or tell me if these warnings could reveal what is wrong?

I have uploaded the rar file containing everything in my tmk_keyboard-master\keyboard\gh60 folder.
Attachments
gh60.rar
(15.77 KiB) Downloaded 244 times

User avatar
Halvar

18 Feb 2015, 09:52

I can't compile AVR stuff here, but from looking at the code here are some things you could check:

If this is right:

config.h

Code: Select all

#define MATRIX_ROWS 2
#define MATRIX_COLS 5
then the KEYMAP definition in keymap_common.h should be

Code: Select all

#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09 \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04 }, \ 
    { KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09 }  \
}
and in keymap_poker.c, there seems to be a comma too much, it should be like this:

Code: Select all

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KEYMAP(1,   2,   3,   4,   5, \
		6,   7,   8,   9,   0)
};

Kaibz

18 Feb 2015, 14:20

Halvar,

I am actually very very happy right now as your code does work and it compiles perfectly and both rows work as they should.
You made my day Sir, a thousand Thanks to You.

User avatar
Halvar

18 Feb 2015, 15:31

Glad to hear that, congrats!

Craig K.

01 Mar 2015, 23:50

matt3o wrote: Exit. Open the terminal go to the gh60 directory and run:
what do you mean by open the terminal and go to the directory

ROFLmonster

02 Mar 2015, 06:31

He means change to the directory where your makefile is. If you're on Windows use Cygwin. To change directory type in 'cd' no quotes and just drag the gh60 folder to the Cygwin window and press enter. Then run make -f Makefile and you're compiling.

seankeyboard

02 Mar 2015, 16:51

Hey guys how do you create a macro ie like ctrl+v or win+e. Also how do I make a key that does something with a long click and other with a fast click kind of like the FN tap but with keys and macros. Thanks everyone!

araif

02 Mar 2015, 17:18

for creating a macro that "clicks" ctrl+v, put a FN to a key, like FN1 and add to your fn_actions[] array a call to

Code: Select all

	[1] = ACTION_MACRO(CTRLV),                          // CTRL+v
you should define CTRLV as an enum macro_id

Code: Select all

enum macro_id {
	CTRLV
}
then define the macro logic:

Code: Select all

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	switch (id) {
	case CTRLV:
		return (record->event.pressed ?
		        MACRO( D(LCTRL), T(V), U(LCTRL), END ) :
		        MACRO_NONE );
       }
}
I'm not really sure how to address your second question though. maybe a definition like

Code: Select all

	[1] = ACTION_LAYER_TAP(2, ACTION_MACRO(CTRLV)),  // to Fn1 overlay 2
will suffice.

seankeyboard

02 Mar 2015, 22:02

araif wrote: for creating a macro that "clicks" ctrl+v, put a FN to a key, like FN1 and add to your fn_actions[] array a call to

Code: Select all

	[1] = ACTION_MACRO(CTRLV),                          // CTRL+v
you should define CTRLV as an enum macro_id

Code: Select all

enum macro_id {
	CTRLV
}
then define the macro logic:

Code: Select all

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	switch (id) {
	case CTRLV:
		return (record->event.pressed ?
		        MACRO( D(LCTRL), T(V), U(LCTRL), END ) :
		        MACRO_NONE );
       }
}
I'm not really sure how to address your second question though. maybe a definition like

Code: Select all

	[1] = ACTION_LAYER_TAP(2, ACTION_MACRO(CTRLV)),  // to Fn1 overlay 2
will suffice.

Could you explain this part for me please.

Code: Select all

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	switch (id) {
	case CTRLV:
		return (record->event.pressed ?
		        MACRO( D(LCTRL), T(V), U(LCTRL), END ) :
		        MACRO_NONE );
       }
}

araif

02 Mar 2015, 22:12

seankeyboard wrote: Could you explain this part for me please.

Code: Select all

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	switch (id) {
	case CTRLV:
		return (record->event.pressed ?
		        MACRO( D(LCTRL), T(V), U(LCTRL), END ) :
		        MACRO_NONE );
       }
}
what you don't understand? also read doc/keymap.md section 2.3

seankeyboard

02 Mar 2015, 22:15

araif wrote:
seankeyboard wrote: Could you explain this part for me please.

Code: Select all

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	switch (id) {
	case CTRLV:
		return (record->event.pressed ?
		        MACRO( D(LCTRL), T(V), U(LCTRL), END ) :
		        MACRO_NONE );
       }
}
what you don't understand? also read doc/keymap.md section 2.3
what is after the D, T, and U

if I wanted to make a 3 key macro what would that look like

araif

02 Mar 2015, 22:17

seankeyboard wrote: what is after the D, T, and U

if I wanted to make a 3 key macro what would that look like
have you read the documentation I pointed out?

Code: Select all

2.3 Macro action
***TBD***

`Macro` action indicates complex key strokes.
    MACRO(MACRO( D(LSHIFT), D(D), END ) U(D), U(LSHIFT), END )
    MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )

#### 2.3.1 Macro Commands
- **I()**   change interval of stroke.
- **D()**   press key
- **U()**   release key
- **T()**   type key(press and release)
- **W()**   wait
- **END**   end mark

#### 2.3.2 Examples

***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.

seankeyboard

02 Mar 2015, 22:24

araif wrote:
seankeyboard wrote: what is after the D, T, and U

if I wanted to make a 3 key macro what would that look like
have you read the documentation I pointed out?

Code: Select all

2.3 Macro action
***TBD***

`Macro` action indicates complex key strokes.
    MACRO(MACRO( D(LSHIFT), D(D), END ) U(D), U(LSHIFT), END )
    MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )

#### 2.3.1 Macro Commands
- **I()**   change interval of stroke.
- **D()**   press key
- **U()**   release key
- **T()**   type key(press and release)
- **W()**   wait
- **END**   end mark

#### 2.3.2 Examples

***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.
I just read it, on your example how come V isnt released, also is "wait" measured in milliseconds

araif

02 Mar 2015, 22:30

seankeyboard wrote: I just read it, on your example how come V isnt released, also is "wait" measured in milliseconds
Yes wait is measured in milliseconds, see common/action_macro.h.

I don't want to appear rude but you should really read the doc again because you are asking things that are already answered there.

seankeyboard

02 Mar 2015, 22:33

araif wrote:
seankeyboard wrote: I just read it, on your example how come V isnt released, also is "wait" measured in milliseconds
Yes wait is measured in milliseconds, see common/action_macro.h.

I don't want to appear rude but you should really read the doc again because you are asking things that are already answered there.
Thanks for the help, I still dont know why it isnt released though.

araif

02 Mar 2015, 22:38

seankeyboard wrote: Thanks for the help, I still dont know why it isnt released though.
you are welcome. 8-)

seankeyboard

03 Mar 2015, 19:46

araif wrote:
seankeyboard wrote: Thanks for the help, I still dont know why it isnt released though.
you are welcome. 8-)
hrrm i used what you wrote and i tried to look over the code but couldnt get the macros to work, i even looked at some other examples on github. do i need to #include something somewhere else?
It compiles but doesnt do anything, when i assigned a macro for a tap it disables fn and the macro doesnt work

Code: Select all

enum macro_id {
	CTRLV,
	CTRLC,
};

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
	keyevent_t event = record->event;
	switch (id) {
	case CTRLV:
		return event.pressed ?
			MACRO(D(LCTRL), T(V), U(LCTRL), END) :
			MACRO_NONE;
	case CTRLC:
		return event.pressed ?
			MACRO(D(LCTRL), T(C), U(LCTRL), END) :
			MACRO_NONE;
	}
	return MACRO_NONE;
}

	[2] = ACTION_LAYER_TAP_KEY(3, FN20),       //  i have also tried typing it out
        [20] = ACTION_MACRO(CTRLV)
Also could someone help me set up leds please? I will be using pwm pin 12 to power 47 leds in parallel.
I would like it to have it as a toggle as on and off. Thanks a bunch!
Last edited by seankeyboard on 03 Mar 2015, 21:12, edited 1 time in total.

araif

03 Mar 2015, 21:08

seankeyboard wrote:

Code: Select all


	[2] = ACTION_LAYER_TAP_KEY(3, FN20),       //  i have also tried typing it out
        [20] = ACTION_MACRO(CTRLV)

are you sure it compiles correctly?

that quoted code should be, probably:

Code: Select all

   [2] = ACTION_LAYER_TAP_KEY(3, KC_FN20), 
   [20] = ACTION_MACRO(CTRLV)

ROFLmonster

03 Mar 2015, 21:36

seankeyboard wrote:
araif wrote:
seankeyboard wrote: Thanks for the help, I still dont know why it isnt released though.
you are welcome. 8-)
Also could someone help me set up leds please? I will be using pwm pin 12 to power 47 leds in parallel.
I would like it to have it as a toggle as on and off. Thanks a bunch!
Yeah I wouldn't recommend it. 47 LEDs in parallel will take almost a full amp (970mA assuming 20mA for each LED) off a single I/O pin.
Not only the VCC/GND pins can put out up to 400mA but even the USB port (2.0) won't be able to supply that kind of current.

Unless you have a certain circuit to supply that kind of power.

seankeyboard

03 Mar 2015, 22:04

I will have it pwn controlled so probably 10/255 or something really low like that. So it wouldn't be 20ma per led. I just dont know how to write the code

User avatar
nowai

09 Mar 2015, 11:18

Hi, I finished my Planck build a few days ago and I have one strange problem:

When the keyboard is plugged in during boot (or reboot) it's not working. However its still listed as a keyboard and as a usb device in the device manager (and its "working properly"). After replugging or restarting the teensy everything works again. I'm using Jacks prebuilt files from here https://github.com/jackhumbert/tmk_keyb ... ard/planck

This happens on my Surface Pro 3 (Win8.1) my old Asus Laptop (Win7) and my Desktop PC (Win8.1)
Any help would be appreciated. Thank you!!

ROFLmonster

09 Mar 2015, 16:55

nowai wrote: Hi, I finished my Planck build a few days ago and I have one strange problem:

When the keyboard is plugged in during boot (or reboot) it's not working. However its still listed as a keyboard and as a usb device in the device manager (and its "working properly"). After replugging or restarting the teensy everything works again. I'm using Jacks prebuilt files from here https://github.com/jackhumbert/tmk_keyb ... ard/planck

This happens on my Surface Pro 3 (Win8.1) my old Asus Laptop (Win7) and my Desktop PC (Win8.1)
Any help would be appreciated. Thank you!!
Fount this issue which is exactly what you describe:
https://github.com/tmk/tmk_keyboard/issues/58
It suggests using the normal Makefile instead of the PJRC one from what I understand.

Also try to disable NKRO (in the Makefile put NKRO_ENABLE = no) since it doesn't work on boot, might be what causing the issue.

User avatar
nowai

09 Mar 2015, 17:47

ROFLmonster wrote: Fount this issue which is exactly what you describe:
https://github.com/tmk/tmk_keyboard/issues/58
It suggests using the normal Makefile instead of the PJRC one from what I understand.

Also try to disable NKRO (in the Makefile put NKRO_ENABLE = no) since it doesn't work on boot, might be what causing the issue.
Wow, thanks! That was easy! This solved the problem for my SP3 and my Laptop, even with NKRO still activated.

But for some reason my desktop pc completely refuses to boot with the keyboard attached when its flashed with the normal Makefile (with and without nkro). It froze at the BIOS selection screen and unfroze the moment I detached the keyboard.
Any idea whats going on here?

ROFLmonster

09 Mar 2015, 19:18

nowai wrote:
ROFLmonster wrote: Fount this issue which is exactly what you describe:
https://github.com/tmk/tmk_keyboard/issues/58
It suggests using the normal Makefile instead of the PJRC one from what I understand.

Also try to disable NKRO (in the Makefile put NKRO_ENABLE = no) since it doesn't work on boot, might be what causing the issue.
Wow, thanks! That was easy! This solved the problem for my SP3 and my Laptop, even with NKRO still activated.

But for some reason my desktop pc completely refuses to boot with the keyboard attached when its flashed with the normal Makefile (with and without nkro). It froze at the BIOS selection screen and unfroze the moment I detached the keyboard.
Any idea whats going on here?
Hmm that's a bit more tricky. Might have to wait to hasu or someone more knowledgeable to reply. Try taking a look at the differences between the fork you linked and the original. Maybe even try to modify tmk's firmware to your setup and see if it's working.

Edit: try disabling NKRO completely. I know that it causes issues in the bios. Might be it.
Last edited by ROFLmonster on 09 Mar 2015, 19:31, edited 1 time in total.

Post Reply

Return to “Workshop”