Porting the Frosty Flake to VIA

So I want to preface this by saying that I am not a programmer. Not by any means. I am also not an electrical engeneer. I’m just a dude that really likes keyboards. Like, a lot. Okay, with that being said, let’s continue.

For those that don’t know, the Frosty Flake is a custom PCB to control the CoolerMaster Quick Fire Rapid. I got mine from 1upkeyboards but as far as I know, they are no longer being produced. The Frosty Flake was designed to use the TMK Keyboard Firmware but was later ported to QMK. I’m not going to get into QMK in this post but it’s definitely worth looking into in your own time.

Introducing VIA

Any way, fast forward some amount of years and along comes VIA. VIA1 is an extreamly user friendly way of configuring your keyboard that uses QMK as the backend. You used to have to write your keymaps in a text editor, or use something like the QMK Configurator. Obviously not everyone has the time to learn how to write a keyboard layout in C and the QMK Configurator can be a bit overwhelming. That’s where VIA comes in.

My personal Rama Works Koyu keyboard layout as seen in VIA(/photos/via.png) .

Up until recently I’ve personally coded all of my keyboard layouts using a keymap.c file as is the way it’s done with QMK. I then compiled my layout and flashed my keyboard with it. Maybe I was just stuck in my old ways. Maybe it’s because I didn’t know that I could still program MT(MOD_LCTL, KC_ESC)2 using VIA. I don’t know. But the other day I decided that I was going to give VIA a try. And I’m really glad that I did. Not only can I do everything that I did writing my own layouts, but I no longer had to compile and flash the new layout every time I wanted to change a single key or whatever. Everything can be done in the software and in real time. This is also very appealing to my less technically inclined friends that I have been building keyboards for recently.

So I decided that I wanted all of my keyboards to be flashed with VIA for consistency. But a problem arose… Not all of my keyboards had a VIA keymap that I could just flash. So what do I do? Give up? Well, yes, usually. BUT NOT THIS TIME!!!! I wanted to see if I could figure out how to port my keyboard by myself, and that’s exactly what I did!

Getting Started

So like I said at the beginning, I am not a programmer nor have any idea what I’m doing when it comes to circuit boards and the like. I know how to solder keyboard switches to a PCB and that’s about it. But I was determined! I wanted to do this, and so I did.

The first thing I did was just look and see if anyone had done this already. No one had, so my next step was to see how I would go about porting. I searched “Port Keyboard to VIA” and the first link was from the VIAL Wiki. This is perfect! I thought. This is going to be easy!

Step One: Writing the VIA layout

The first step was to write the the VIA layout. This was easy since I already knew how to do that.

#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_tkl(\
                 KC_ESC, KC_F1,  KC_F2,  KC_F3,  KC_F4,  KC_F5,  KC_F6,  KC_F7,  KC_F8,  KC_F9,  KC_F10, KC_F11,  KC_F12,             KC_PSCR, KC_SLCK, KC_PAUS, \
                 KC_GRV, KC_1,   KC_2,   KC_3,   KC_4,   KC_5,   KC_6,   KC_7,   KC_8,   KC_9,   KC_0,   KC_MINS, KC_EQL,  KC_BSPC,   KC_INS,  KC_HOME, KC_PGUP, \ KC_TAB, KC_Q,   KC_W,   KC_E,   KC_R,   KC_T,   KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,   KC_LBRC, KC_RBRC, KC_BSLS,   KC_DEL,  KC_END,  KC_PGDN, \
                 KC_CAPS,KC_A,   KC_S,   KC_D,   KC_F,   KC_G,   KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,KC_QUOT,          KC_ENT, \
                 KC_LSFT,KC_NUBS,KC_Z,   KC_X,   KC_C,   KC_V,   KC_B,   KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,          KC_RSFT,            KC_UP, \
                 KC_LCTL,KC_LGUI,KC_LALT,                KC_SPC,                                 KC_RALT,KC_RGUI, KC_APP,  KC_RCTL,   KC_LEFT, KC_DOWN, KC_RGHT  ),

[1] = LAYOUT_tkl(\
       _______, _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______, _______,  _______,             _______, _______, _______, \
       _______, _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______, _______,  _______,   _______,  _______, _______, \
       _______, _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______, _______, _______,   _______,  _______,  _______, \
       _______,_______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,_______,          _______, \
       _______,_______,_______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,_______, _______,          _______,            _______, \
       _______,_______,_______,                _______,                                 _______,    _______ , _______,  _______,   _______, _______, _______
       ),

[2] = LAYOUT_tkl(\
       _______, _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______,  _______, _______,  _______,             _______, _______, _______, \
       _______, _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______, _______,  _______,   _______,  _______, _______, \
       _______, _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______, _______, _______,   _______,  _______,  _______, \
       _______,_______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,_______,          _______, \
       _______,_______,_______,   _______,   _______,   _______,   _______,   _______,   _______,   _______,_______, _______,          _______,            _______, \
       _______,_______,_______,                _______,                                 _______,    _______ , _______,  _______,   _______, _______, _______
       ),
};

Now I had to flash the QMK keymap to my Frosty Flake with the normal make bpiphany/frosty_flake:via but I kept getting an error that I didn’t understand. shell quantum/dynamic_keymap.c:87:1: error: static assertion failed: "Dynamic keymaps are configured to used more EEPROM than is available." I had no idea what that meant. I did some searching around the QMK discord but couldn’t really find anything helpful. Until I finally stumbled upon a Reddit post with a similar error. It turns out that by default, VIA uses 4 dynamic keymaps by default. The EEPROM on the Frosty Flake cannot handle that many dynamic keymaps so I had to add #define DYNAMIC_KEYMAP_LAYER_COUNT 3 to the config.h file for the Frosty Flake. After doing that, everything compiled correctly with no errors!

Okay, now we are getting somewhere! What’s next!

Step 2: Making a Keyboard-Layout-Editor layout

Alright that sounds easy enough. “At this point you will need to correlate physical keyboard to the switch matrix.” What? What does that even mean?! Yeah, I had no idea what I was supposed to be doing. So I literally gussed. Believe it or not it totally…. didn’t work at all. So I did some digging. Again I have no idea what I’m doing when it comes to electrical things. But I found the frosty_flake.h file which had the following code:

/* Matrix col/row mapping (TKL) 
  ,----.    ,-------------------. ,-------------------. ,-------------------. ,--------------.
  | J6 |    | I4 | H4 | H2 | H6 | | A7 | E6 | D2 | D4 | | B4 | B7 | B6 | B0 | | C7 | C5 | A5 |
  `----'    `-------------------' `-------------------' `-------------------' `--------------'
  ,-------------------------------------------------------------------------. ,--------------.
  | J4 | J7 | I7 | H7 | G7 | G4 | F4 | F7 | E7 | D7 | R7 | R4 | E4 |     B2 | | L4 | O4 | Q4 |
  |-------------------------------------------------------------------------| |--------------|
  | J2   | J5 | I5 | H5 | G5 | G2 | F2 | F5 | E5 | D5 | R5 | R2 | E2 |   B3 | | K4 | O7 | Q7 |
  |-------------------------------------------------------------------------| '--------------'
  | O5    | J3 | I3 | H3 | G3 | G6 | F6 | F3 | E3 | D3 | R3 | R6 |       B1 |
  |-------------------------------------------------------------------------|      ,----.
  | N2      | J1 | I1 | H1 | G1 | G0 | F0 | F1 | E1 | D1 | R0 |          N3 |      | O6 |
  |-------------------------------------------------------------------------| ,--------------.
  | A4 | P2 | C6 |                  K6                  | C0 | M3 | D0 | A1 | | O0 | K0 | L0 |
  `-------------------------------------------------------------------------' `--------------'
*/

#define LAYOUT_tkl( \
  KJ6,      KI4, KH4, KH2, KH6, KA7, KE6, KD2, KD4, KB4, KB7, KB6, KB0,   KC7, KC5, KA5, \
  KJ4, KJ7, KI7, KH7, KG7, KG4, KF4, KF7, KE7, KD7, KR7, KR4, KE4, KB2,   KL4, KO4, KQ4, \
  KJ2, KJ5, KI5, KH5, KG5, KG2, KF2, KF5, KE5, KD5, KR5, KR2, KE2, KB3,   KK4, KO7, KQ7, \
  KI2, KJ3, KI3, KH3, KG3, KG6, KF6, KF3, KE3, KD3, KR3, KR6,      KB1,                  \
  KN2, KI6, KJ1, KI1, KH1, KG1, KG0, KF0, KF1, KE1, KD1, KR0,      KN3,        KO6,      \
  KA4, KP2, KC6,                KK6,                KC0, KM3, KD0, KA1,   KO0, KK0, KL0  \) \ { \ /*        0        1        2        3        4        5        6        7        */ \ /* A */ { KC_NO,   KA1,     KC_NO,   KC_NO,   KA4,     KA5,     KC_NO,   KA7,     }, \ /* B */ { KB0,     KB1,     KB2,     KB3,     KB4,     KC_NO,   KB6,     KB7,     }, \ /* C */ { KC0,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC5,     KC6,     KC7,     }, \ /* D */ { KD0,     KD1,     KD2,     KD3,     KD4,     KD5,     KC_NO,   KD7,     }, \
/* E */ { KC_NO,   KE1,     KE2,     KE3,     KE4,     KE5,     KE6,     KE7,     }, \
/* F */ { KF0,     KF1,     KF2,     KF3,     KF4,     KF5,     KF6,     KF7,     }, \
/* G */ { KG0,     KG1,     KG2,     KG3,     KG4,     KG5,     KG6,     KG7,     }, \
/* H */ { KC_NO,   KH1,     KH2,     KH3,     KH4,     KH5,     KH6,     KH7,     }, \
/* I */ { KC_NO,   KI1,     KI2,     KI3,     KI4,     KI5,     KI6,     KI7,     }, \
/* J */ { KC_NO,   KJ1,     KJ2,     KJ3,     KJ4,     KJ5,     KJ6,     KJ7,     }, \
/* K */ { KK0,     KC_NO,   KC_NO,   KC_NO,   KK4,     KC_NO,   KK6,     KC_NO,   }, \
/* L */ { KL0,     KC_NO,   KC_NO,   KC_NO,   KL4,     KC_NO,   KC_NO,   KC_NO,   }, \
/* M */ { KC_NO,   KC_NO,   KC_NO,   KM3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* N */ { KC_NO,   KC_NO,   KN2,     KN3,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* O */ { KO0,     KC_NO,   KC_NO,   KC_NO,   KO4,     KC_NO,   KO6,     KO7,     }, \
/* P */ { KC_NO,   KC_NO,   KP2,     KC_NO,   KC_NO,   KC_NO,   KC_NO,   KC_NO,   }, \
/* Q */ { KC_NO,   KC_NO,   KC_NO,   KC_NO,   KQ4,     KC_NO,   KC_NO,   KQ7,     }, \
/* R */ { KR0,     KC_NO,   KR2,     KR3,     KR4,     KR5,     KR6,     KR7,     }, \
}

After staring at this for longer than I care to admit, I was finally able to make the KLE file.

The KLE file for the Frosty Flake’s switch matrix(/photos/kle.jpeg) Which resulted in the following switch matrix in VIA What the Switch Matrix looks like in VIA(/photos/matrix.jpeg)

I then had to download the .JSON file that KLE creates and add some information to it, like so:

{
    "name": "Frosty Flake",
    "vendorId": "0xFEED",
    "productId": "0x6060",
    "lighting": "none",
    "matrix": {
        "rows": 18,
        "cols": 8
    },
    "layouts": {
        "keymap":[
  [
    "9,6",
    {
      "x": 1
    },
    "8,4",
    "7,4",
    "7,2",
    "7,6",
    {
      "x": 0.5
    },
    "0,7",
    "4,6",
    "3,2",
    "3,4",
    {
      "x": 0.5
    },
    "1,4",
    "1,7",
    "1,6",
    "1,0",
    {
      "x": 0.25
    },
    "2,7",
    "2,5",
    "0,5"
  ],
  [
    {
      "y": 0.5
    },
    "9,4",
    "9,7",
    "8,7",
    "7,7",
    "6,7",
    "6,4",
    "5,4",
    "5,7",
    "4,7",
    "3,7",
    "17,7",
    "17,4",
    "4,4",
    {
      "w": 2
    },
    "1,2",
    {
      "x": 0.25
    },
    "11,4",
    "14,4",
    "16,4"
  ],
  [
    {
      "w": 1.5
    },
    "9,2",
    "9,5",
    "8,5",
    "7,5",
    "6,5",
    "6,2",
    "5,2",
    "5,5",
    "4,5",
    "3,5",
    "17,5",
    "17,2",
    "4,2",
    {
      "w": 1.5
    },
    "1,3",
    {
      "x": 0.25
    },
    "10,4",
    "14,7",
    "16,7"
  ],
  [
    {
      "w": 1.75
    },
    "8,2",
    "9,3",
    "8,3",
    "7,3",
    "6,3",
    "6,6",
    "5,6",
    "5,3",
    "4,3",
    "3,3",
    "17,3",
    "17,6",
    {
      "w": 2.25
    },
    "1,1"
  ],
  [
    {
      "w": 2.25
    },
    "13,2",
    "9,1",
    "8,1",
    "7,1",
    "6,1",
    "6,0",
    "5,0",
    "5,1",
    "4,1",
    "3,1",
    "17,0",
    {
      "w": 2.75
    },
    "13,3",
    {
      "x": 1.25
    },
    "14,6"
  ],
  [
    {
      "w": 1.25
    },
    "0,4",
    {
      "w": 1.25
    },
    "15,2",
    {
      "w": 1.25
    },
    "2,6",
    {
      "w": 6.25
    },
    "10,6",
    {
      "w": 1.25
    },
    "2,0",
    {
      "w": 1.25
    },
    "12,3",
    {
      "w": 1.25
    },
    "3,0",
    {
      "w": 1.25
    },
    "0,1",
    {
      "x": 0.25
    },
    "14,0",
    "10,0",
    "11,0"
  ]
] 
    }
}

So now what? Well, nothing, that’s technically it. I just had to sideload the json into VIA and it worked. The Frosty Flake working correctly under VIA And that’s basically it. That’s how I ported an unsupported keyboard to VIA. I know it’s not a crazy feat but I’m still proud of myself. I was able to solve all the problems that I had and make it work. I could end it there but I went a step further and ported the Frosty Flake (and others) to VIAL aswell. But I’ll probably talk more about that at a later date.

NOTE: At the time of writing this the Frosty Flake is only officially supported by VIAL as my pull request has still yet to be merged to the QMK repo.


  1. And also VIAL. An open source alternative to VIA. ↩︎

  2. This allows the assigned key, in my case Caps Lock, to act as Left Control when held and Esc when tapped. This is insanely useful to me as an avid Vim user. ↩︎