Skip to content

Latest commit

 

History

History
563 lines (467 loc) · 47.8 KB

README.org

File metadata and controls

563 lines (467 loc) · 47.8 KB

Readme

This is a Dactyl Manuform with a tracking ball in its right thumb cluster, a Tractyl Manuform so to speak. Unlike some other trackball Dactyl Manuforms that utilize a Teensy 2.0 I managed to cram the firmware onto a Arduino Micro even with some extra functions added in the firmware. Be aware that there is couple of hundred bytes left for hacking about. So if you want to add more custom stuff into your trackball Dactyl this one is probably not the best choice for you.

Table of contents

About this Repository

The idea and all the models come from Reddit user u/qqurn. Check out his Gitlab repository here. I only changed qqurns models in Openscad to use a different USB-C to micro-USB adapter cable and a TRS socket and single serial communication between the halfs instead of a RJ9 socket and I2C communication. I also corrected the base plate of the left half to align with the screw holes of the top.

I noticed trackball Dactyl Manuforms lack a decent idiot proof guide like the one for the Dactyl Manuform without trackball. There is also this one for a trackball model but it uses a Raspberry Pi and is a whole different model. The trackball Dactyl in this guide is intentionally made easy. You do not need to know how to code nor do you need to know much about electronics. You do not even need to open a text editor if you do not want to (although you should if you want to do some configuration) and will still end up with a good configuration with sane defaults. Just follow this guide step by step and you should have a decent trackball Dactyl Manuform in the end. This model also uses a Arduino Micro on the trackball side and a Arduino Pro Micro on the left side. This means you do not need to flash them with separate files because you need to change the bootloader in between and recompile like it is with different micro controller in the left than in the right half. Using the same firmware file for both makes things simpler.

The folder STLs contains the .stl files ready to print. The folder models contains the OpenSCAD and FreeCAD files to change the models to your liking in those programs. I added some more images that are not included in the build guide into the folder more_images.

License

Please note that the Arduino Micro pinout image and the part that is used in the image of the right sides wiring diagram is CC-BY-SA licensed. The image is work of Arduino. All other images are CC-BY-SA licensed as well.

Building guide

I wrote this guide about building the right side with the trackball. The left side is basically the same thing minus the part with the trackball.

Needed items

I apologize if most of these parts are from German ebay vendors, but this is where I got them from. I am sure you can find them from somewhere else. I list the exact amount of parts needed, for some things it makes sense to have some spare, like switches, diodes, jumper wires, ball bearings, etc. Many of the parts come in packages of a 100 or so, so you have some spares anyway.

Parts

Consumables

  • wire, you can wire this however you like. I use insulated wire with 0.5mm diameter, but I have another Dactyl which I wired with 1mm thick uninsulated wire bent into shape so the wires do not touch. (like they wired old radios in the 50s.) It is very reliable.
  • solder, it depends on personal preference, but I used solder with 1mm diameter
  • some viscous glue
  • hot glue
  • multi meter (to check for continuity, a cheap one is enough if you don’t want to use it for different things later on)
  • (optional) filler
  • (optional) some spray paint you like

Tools

  • soldering iron
  • hot glue gun
  • maybe 3D printer if you print yourself
  • small screwdriver
  • small hex keys for the screws
  • nose pliers
  • wire cutters
  • metal saw
  • electric drill
  • 3mm drill bit
  • (maybe) a round file

(optional) Enhance the 3D printed case

This step is completely optional and there are many ways of enhancing a 3D print out there, but I wanted to share this regardless. Just in case you are not that much into 3D printing there is maybe some new stuff here for you. So what I found very effective to increase the surface quality of 3D prints is filler that is spray-able. (not filler paint, it is even thicker than that.) I sand the 3D print with approx. 120 grit sandpaper before, just to make the surface a little bit smoother. Then I spray the primer on for the first time. Spray it very thin. It should not be soaking wet, because then in takes ages to dry. If it is thin enough it will be dry in 5 minutes. Then I sand the surface with 120 grit again. I don’t sand it too much but against the ‘grain’, so that the ‘hills’ are sanded off but the filler stays in the ‘valleys’. Then I spray on some filler again, wait 5 minutes and sand again. I do this 3-4 times, after that I spray filler again, but this time a bit thicker and then let it dry over night. This will give you a flat surface, where you can not see the the 3D print layers anymore. To get an ever better really shiny flat surface additional steps are needed of course, but this is a plastic casing of a keyboard, not a piano after all. After that procedure I paint the case with normal paint from the hardware store. I think there are enough videos and tutorials on how to use spraying cans, so I won’t get into that. images/after-prime.jpg images/after-paint.jpg

Wiring & Mounting

Try mounting the USB-C to micro-USB cable and the TRS socket.

It could be that they don’t fit, especially if you primed and painted the case. If they don’t fit, use a round file to widen the holes a bit. Do this first because it could be that the file ruins your paint and you have to paint that particular part again. You don’t want to paint this again when the switches and everything is mounted that’s why we do this as a first step.

Wiring diagrams

These are the wiring diagrams for the right and the left half. They will be useful in the next steps. images/wiring_right.png images/wiring_left.png

Put the hot swap sockets in place.

I learned that it is easier to put the switches in now instead of doing it later. When putting in the switches, make sure that the pins of the switches hit the sockets. If they don’t, they will bend to the side and you won’t have a connection. If you look at the hot swap sockets closely, you can see the little pins from the switches sticking out a bit on the other side. To make sure the connection works, you can check it with the multimeter. Don’t be confused, the photos I have here are from before I learned that. images/sockets-in.jpg

Solder the diodes on.

Now if you spend the few extra cents and bought diodes that are nicely packed in a row, this will pay off. Instead of bending and cutting the diodes one by one, you can bend them all at once using the edge of something. Then go berserk with the wire cutters. Cut only one side off, then it will be easier to hold them while soldering. images/diodes-in.jpg

You can alter the position of the diodes, but not the direction. (at least not without changing the QMK firmware) The black ring on the diode must point towards the horizontal line in the circuit. So either the diode is on the side of the switch with the horizontal line and the black ring pointing away from the switch, or it is on the side of the vertical line and the black ring pointing towards the switch. If you don’t know what you are doing, just stick to the images and the wiring diagram. Luckily the 3D print has some recesses where the diodes should go, so it guides you a bit. Cut the other side off when you are done soldering them.

Solder the horizontal lines.

Now solder the horizontal lines into their places. If you have bought normal (non fire resistant) wire, the insulation will melt away pretty easily. I prefer to melt it away with the soldering iron, then solder the wire onto the diode. However, this has some downsides. First of all, you can easily have soldered something that sticks to each other, but has no electrical connection. I check all of these connection with the multi meter to see if they are really connected to mitigate this and to save me the hassle of debugging this later on. Then there is the fumes, that are coming off the wire when it’s melted. They don’t smell very healthy, so be sure to open a window when doing this or have a fume hood. You can also remove the insulation here with a razor or something, which is probably the better and much nicer looking way, but then again this takes time. images/horizontal-lines.jpg

Solder the vertical lines in.

This is basically the same thing like the horizontal lines. Now you could check with the multimeter if the switch really closes the circuit. Hold it to a vertical line and a horizontal line and press the corresponding switch. Note that diodes are like a one-way-road for current. So it matters where you use the black wire or the red wire of your multimeter. Put the red wire on a wire on the side of the diode that does not have the black ring, and the black wire on a wire that is connected to the side with the black ring. If in doubt, just try to measure continuity though a diode and see with which configuration the multimeter goes ‘beep’. images/vertical-lines.jpg

Glue the hot swap sockets

Now is a good time to glue the hot swap sockets in. Notice in the photo that I soldered the wires first, which was not the best idea ever. Put a small amount of hot glue in the middle of every hot swap socket. images/hot_glue_swaps.jpg

Solder the jumper wires between the matrix and the Arduino and between the TRS socket and the Arduino.

Now use those male-female jumper wires. Cut of a bit of the male end, then solder them to the vertical and horizontal lines first. images/jumpers_to_mat.jpg On the TRS socket it does not really matter which pin you use, as long as the same wire goes to the same pin on the other side. (The color of the wiring diagram is the same on both sides, so the red line on the left side is the red line on the right side and so on.) However, use the sleeve for the ground at least, it is usually the one that is on the outside of the socket. I tend to use tip for the voltage and the ring for communication, but that is entirely up to you. When you are done, connect the wires to the Arduino. images/jumpers_to_arduino.jpg

Solder the PMW3360 trackball sensor

A short note about soldering electronics: Unlike the switches, the wires or the TRS socket for example, which are quite sturdy, small electronic boards are a bit more sensitive. You can fry them with the soldering iron. Try to put as few heat as possible into the chips. You can do this by putting the solder on the soldering iron first, then touching the place you want to solder just long enough for everything to heat up enough so the solder can flow into its place. The art here is to just put enough heat into this (if you don’t have a soldering iron with a heat setting like me, read “touch the thing you want to solder long enough” here) so that the solder flows where it should, does not form a ball and covers the pad on the pin completely. Solder the wires to the sensor first. You can solder the male ends in again, then cut them off on the other side. Make sure to cut them off low enough so the plastic lens thingy still fits. images/solder_pmw.jpg images/pmw_plastic_lense.jpg

After that connect the wires to the Arduino. Some Arduino derivatives are not delivered with pin strips soldered to the board. (but they usually come with a pin strip alongside) If so, solder the pins strips to the Arduino is a similar way you soldered the cables to the PMW3360.

Mounting and soldering the reset switch

If you want to have the reset switch in the bottom plate, drill a 3mm hole at the spot where it should go. I noticed that 4.3mm height for the reset switch is actually to high to mount it under that bracket and I broke it off. Nothing that a bit of glue can’t fix. You probably want to get even flatter ones, I had a few of those 4.3mm high ones to spare from another project, that is why I used them. images/reset_switch_in.jpg

Solder two longer wires to the reset switch on the bottom plate. images/solder_reset.jpg

Now that the PMW3360 and the TRS socket is connected, you will notice that there is no GND pin left on the Arduino. So solder one of the wires coming from the switch to the GND pin you used on the TRS socket. Connect the other wire to any of the two reset pins of the Arduino. images/reset_connect.jpg

Mount the ball bearings for the trackball.

If you bought pins for the bearings that are too long, put the bearing on the pin before sawing it off. Otherwise you could have problems putting the pins in when they are serrated from the vice or saw. Those small bearings are a very sensible part, don’t make loud noises and let them sniff your hand before touching them. Just kidding, just don’t put them in the vice and don’t put a force on the inner ring without putting the same force on the outer ring. Once you have the pins in the right length, just press them into the recesses. PLA is rather soft, so they stick in there, make some room with the soldering iron in case they don’t go in. Once they are in you can correct their position, which determines the height of the ball and the distance between the PMW3360 and the ball by heating them up with the soldering iron. Try to get the ball down as far as possible without it touching the case. images/bearings-in.jpg

Mount the M3 insert nuts

Mounting those nuts is easy if you found nuts that are big enough for the holes. You put them on your soldering iron, heat them up, then press them into the 3D print. Just make sure your soldering iron is clean from solder, otherwise solder will block the thread and screws wont go in easily. If you could not find nuts that are big enough, glue them in. Here is a trick how to get them in the right position: Pre-mount them on the bottom plate with a screw, like this:images/insert_prepare.jpg

Then put some glue on the insert nuts. Then mount the bottom plate into place, wait until the glue has dried and them remove the screws. Try to only put glue on the outside and use glue that is somewhat viscous so the glue wont flow into the inside from the bottom up and block the screw. images/inserts.jpg

Mount the M2 insert nuts

The M2 inserts and screws are for the PMW3360 sensor. Here you can mount them again to the PMW3360: images/pmw_prepare.jpg

Then you can glue them in. Note that the PMW must be mounted with the terminal holes up. (Down in this picture since the keyboard is upside down) Make sure that the plastic lense that comes with the PMW lies on that surface as flat as it can get, otherwise the ball will be too far away from it. images/pmw_in.jpg Again, let the glue dry and then remove the screws and the sensor again.

Putting everything together

Before putting everything together, test the setup first. Connection problems are way easier to fix when the parts are not mounted yet. So continue with the firmware guide below before mounting everything. The Arduino Micro has some pins on the top, which are in the way when mounting it. We do not need them, cut them off. Here is the thing in all its glory: images/done.jpg

Flashing the firmware

A word about trackball modes

What makes this firmware very special is how it handles the trackball. You can not only move the mouse pointer with it, no, you can have different modes for it. For further configuration see Other things to set in the firmware There are stacking and non-stacking modes. Non-stacking modes are the major modes (to use emacs lingo) of the trackball, only one non-stacking mode can be activated at a given time and activating one mode will deactivate the last mode. Stacking modes on the other hand are like minor modes and can be activated on top of another mode. To active a mode you use the special keycodes that this firmware provides. You can find them below.

Non-Stacking modes

Cursor mode

Moves the mouse cursor as you would expect from a trackball. This is the mode that is activated when no other mode is activated.

Dragscroll mode

Scrolls up and down and left and right like a mouse wheel from outer space.

Carret mode

Moves the carret (the pointer in text documents) when the trackball is rotated.

Custom mode

In this mode you can define four keycodes that get executed when you rotate the trackball.

Mode-Mode

One mode to rule them all! This mode activates the other modes. When the mode is active, rotate the trackball up for cursor mode, right for dragscroll mode, left for carret mode and down for integration mode.

Stacking modes

Sniping mode

Decreases the cursors sensitivity during cursor mode and carret mode, allowing you to aim for something way easier.

Integration mode

This mode keeps the movement once it is going. This mode is only available in dragscroll and carret mode. E.g. when you have integration mode activated in dragscroll mode you give the trackball a little notch and it keeps scrolling. A nudge in the other direction slows scrolling down, a nudge in the same direction makes scrolling faster.

Preparing the QMK firmware

Setting up QMK

Set up QMK for your operating system. Here is the offical instructions.

Gentoo

For Gentoo Linux I made a little guide, since the official instructions do not work very well. Skip this part and stick to the official instructions above if you do not run Gentoo.

Make sure your kernel has support for Atmega32U enabled. (gentoo-kernel-bin and unmodified gentoo-kernel have it enabled) To install the gcc for building avr programs, put

# for crossdev/ gcc-8.5 for qmk firmware
cross-avr/gcc **

into /etc/portage/package.accept_keywords or /etc/portage/package.accept_keywords/cross-avr-gcc respectively, depending on how you set up your system.

And put

# for crossdev/ gcc-8.5 for qmk firmware
>cross-avr/gcc-8.5.0-r1

into /etc/portage/package.mask or /etc/portage/package.mask/cross-avr-gcc respectively. I do not know why this is necessary, because we will order crossdev to install GCC 8.5 later, but if I do not mask the newer version, it installs the newest version of avr-gcc regardless.

Then run these commands:

# install dependencies
sudo emerge dev-vcs/git dev-python/pip
# on gentoo the python command depends on which python version has pip installed (your $PYTHON_TARGET). Run the command like this: python3.9 -m ... if your PYTHON_TARGET is 3.9
python3.x -m pip install --user qmk
# to build the toolchain for compiling for the Arduino (Micro). Anything higher than GCC 8.x is not recommended by qmk. (And you WILL have errors)
sudo crossdev --stable --g '=8.5' --target avr

Don’t bother to run qmk setup like the official guide tells you to. It would complain because our install is missing some tool chains for other micro controllers, but we only need the avr-tools for the Atmega32U. If you are done with crossdev, you can check with avr-gcc -v if you really have version 8.5.0 installed. Continue with the guide with topic Linux below.

Linux

This probably works well for Windows and Mac, too. I do not know as I haven’t tried.

# clone and prepare the QMK-Firmware repo
git clone https://github.com/Schievel1/qmk_firmware_dm_r_track.git
cd qmk_firmware_dm_r_track/
git checkout tractyl_manuform_enhance
make git-submodule
# to test if your toolchain works, compile something:
qmk compile -kb handwired/dactyl_manuform/5x6 -km default

If the compilation succeeds it will output

Linking: .build/handwired_dactyl_manuform_5x6_default.elf                                           [OK]
Creating load file for flashing: .build/handwired_dactyl_manuform_5x6_default.hex                   [OK]
Copying handwired_dactyl_manuform_5x6_default.hex to qmk_firmware folder                            [OK]
Checking file size of handwired_dactyl_manuform_5x6_default.hex                                     [OK]
 * The firmware size is fine - 19456/28672 (67%, 9216 bytes free)

And you will now have the file handwired_dactyl_manuform_5x6_default.hex in the qmk_firmware_dm_r_track folder. Delete it.

rm handwired_dactyl_manuform_5x6_default.hex

Customizing your key map

You can use the standard layout as a base. Inside your qmk_firmware_dm_r_track folder there is a folder with the key maps for the Tractyl under keymaps/handwired/tractyl_manuform/5x6_right/keymaps. This folder contains sub folders with custom sets of key maps. Now you have two choices:

  • Edit one of the existing key maps
  • Make your own key map. Copy one of the folders in keymaps/handwired/tractyl_manuform/5x6_right/keymaps in place and rename it to your liking.

OPTION 1: the hardcore way with a text editor

Key layout

Either way you will find a keymap.c file inside of those folders. This file is compiled into the actual part of the firmware that determines the keymap. Inside there is a part that looks something like this:

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_COLEMAKDHM] = LAYOUT_5x6_right(
DM_REC1,    DM_REC1, DM_PLY1, DM_REC2 , DM_PLY2 , DM_RSTP,               KC_CPI_DOWN, KC_CPI_STD , KC_CPI_UP , KC_SMO_SC , KC_0        ,KC_QUOT_MY,
KC_TAB,     KC_Q ,   KC_W   , KC_F    , KC_P    , KC_B   ,               KC_J    ,    KC_L       , KC_U      , KC_Y      , KC_SCLN_INV ,KC_QUOT_MY,
KC_ESC,     KC_A ,   KC_R   , KC_S    , KC_T    , KC_G   ,               KC_M    ,    KC_N       , KC_E      , KC_I      , KC_O        ,KC_MINS,
KC_TILD_MY, KC_Z ,   KC_X   , KC_C    , KC_D    , KC_V   ,               KC_K    ,    KC_H       , KC_COMM   , KC_DOT    , KC_SLSH     ,KC_BSLASH,
                           _______, _______,                                         _______, KC_LGUI,
                                       TD(SFT_TM),    TD(RAI_TM),          _______, KC_SPC,
                                       TD(CTL_TM),    TD(GUI_TM),          _______, KC_ENT,
                                       TD(ALT_TM),    TD(LOW_TM),          KC_BSPC, KC_DEL
),

[_LOWER] = LAYOUT_5x6_right(

KC_TILD, KC_EXLM     , KC_AT   , KC_HASH   , KC_DLR  ,KC_PERC,           KC_CIRC, KC_AMPR , KC_ASTR    , KC_LPRN  , KC_RPRN   ,           _______,
_______, KC_PGDN     , KC_HOME , KC_END    , KC_PGUP ,_______,           _______, _______ , RALT(KC_Y) , _______  , RALT(LSFT(KC_SCLN)) , _______,
_______, RALT(KC_Q)  , _______ ,RALT(KC_S) , KC_RBRC ,_______,           KC_BTN3, KC_BTN1 , RALT(KC_5) , KC_BTN2  , RALT(KC_P),           _______,
KC_F12 , KC_F1       , KC_F2   , KC_F3     , KC_F4   , KC_F5 ,           KC_F6  , KC_F7   , KC_F8      , KC_F9    , KC_F10    ,           KC_F11 ,
                            _______,_______,                             _______,_______,
                                        _______,_______,             _______,_______,
                                        _______,_______,             _______,_______,
                                        _______,_______,             _______,_______
),

[_RAISE] = LAYOUT_5x6_right(
_______, _______ , _______ , _______ , _______ ,_______,                 _______, _______      , _______      , _______     , _______     , _______,
_______,  KC_1   , KC_2    , KC_3    , KC_4    , KC_5  ,                 KC_6   , KC_7         , KC_8         , KC_9        , KC_0        , KC_QUOT,
_______, KC_LPRN , KC_RPRN , KC_LBRC , KC_RBRC ,KC_LBRC,                 KC_RBRC, LSFT(KC_LBRC),LSFT(KC_RBRC) ,LSFT(KC_COMM),LSFT(KC_DOT) ,KC_MS_BTN3,
KC_TILD, KC_EXLM , KC_AT   , KC_HASH , KC_DLR  ,KC_PERC,                 KC_CIRC, KC_AMPR      , KC_ASTR      , KC_PLUS     , KC_EQL      , KC_DEL,
                             _______,_______,                                _______,_______,
                                        _______,_______,             _______,_______,
                                        _______,_______,             _______,_______,
                                        _______,_______,             _______,_______
),
};

This represents the layout of the keys. In order to change a key, you have to exchange the keycode of that key with the one you want. Say you want to have escape on the first key in the second row. Then you would exchange KC_TAB there with KC_ESC. If you do not know the keycode of a key, you could use QMK Configurator. When you hover your mouse over a key in the keyboard image on the bottom of a page, it shows you the keys keycode in a bar a the bottom. To get special key functions like RALT(KC_Y) you can see them in the same way on the bottom in the “Quantum” tab. Here is also a reference for the keycodes used by QMK. There are a few. Please note that you can not change the amount of different keycodes or the firmware will not compile. You should also not alter the overall layout. (do not remove commas etc.)

Special key codes in this firmware
The firmware also has some additional keycodes which you can use in the matrix above like any other keycode.
KeycodeShort aliasFunction
POINTER_DEFAULT_DPI_FORWARDDPI_MODIncrease the sensitivity in cursor mode / decrease it when shift is pressed
POINTER_DEFAULT_DPI_REVERSEDPI_RMODDecrease the sensitivity in cursor mode / increase it when shift is pressed
POINTER_SNIPING_DPI_FORWARDS_D_MODIncrease the sensitivity in sniping mode / decrease it when shift is pressed
POINTER_SNIPING_DPI_REVERSES_D_RMODDecrease the sensitivity in sniping mode / increase it when shift is pressed
SNIPING_MODESNIPINGActivates sniping mode while key is pressed
SNIPING_MODE_TOGGLESNP_TOGToggles sniping mode
DRAGSCROLL_MODEDRGSCRLActivates dragscroll mode while key is pressed
DRAGSCROLL_MODE_TOGGLEDRG_TOGToggles dragscroll mode
CARRET_MODECARRETMActivates carret mode while key is pressed
CARRET_MODE_TOGGLECRT_TOGToggles carret mode
CUSTOM_MODECUSTOMMActivates custom mode while key is pressed
CUSTOM_MODE_TOGGLECST_TOGToggles custom mode
MODE_MODEMOMOActivates mode-mode while key is pressed
MODE_MODE_TOGGLEMOMO_TOGToggles mode-mode
INTEG_MODEINTEGMActivates integration mode while key is pressed
INTEG_MODE_TOGGLEITG_TOGToggles integration mode
Layers

In the above example [_COLEMAKDHM], [_LOWER] and [_RAISE] are the names of the layers. You can put in any name for the _COLEMAKDHM layer, but you have to change the #define lines at the beginning of the file accordingly.

#define _COLEMAKDHM 0

You better leave the RAISE and LOWER name like they are. You could change them, but you would have to change them everywhere in the file. To add another layer, copy and past one of the existing layers, rename it to whatever you like, e.g. _MYLAYER. Then add a new #define _MYLAYER 3 to the beginning of the file. Count the number up with every layer you add. You bind your layer to a key with the keycode MO(_MYLAYER). MO switches a layer on like the shift, CTRL etc. keys. So when you hold that key down, the layer is active. When you let go, the layer is not active. Again there are several other layer functions like TG() which toggles a layer. Look them up in QMK Configurator.

Using QMK Configurator for similar keyboard

Because editing the keycodes is somewhat tedious, I came up with a way to utilize QMK Configurator a bit for it. Go to QMK Configurator and select the handwired/tractyl_manuform/5x6_right/teensy2pp keyboard. Rename the keyboard to whatever you like and edit your keyboard to your liking. Be aware that you can not put in the custom keycodes to modify the modes of the trackball. For now give the key that should activate a trackball mode later some special keycodes so you can easily distinguish them from the others.

When you are done, export the key map as JSON and put it into the qmk_firmware folder. Then run the command

qmk json-keymap handwired-dactyl_manuform-5x6-yourfilename.json >> mykeymap.c
#or
qmk json2c handwired-dactyl_manuform-5x6-yourfilename.json >> mykeymap.c # depending on qmk version.

With “yourfilename” changed to your actual filename of course. This will generate a C source file with the name mykeymap.c out of the JSON file. It will look something like this:

#include QMK_KEYBOARD_H

/* THIS FILE WAS GENERATED!
 *
 * This file was generated by qmk-compile-json. You may or may not want to
 * edit it directly.
 */

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
	[0] = LAYOUT_5x6_right(KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL, KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS, KC_NO, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_BSLS, KC_LBRC, KC_RBRC, KC_PGUP, KC_PGDN, KC_LSFT, KC_NO, KC_NO, KC_RSFT, KC_LCTL, KC_SPC, KC_RALT, KC_LALT, MO(1), KC_ENT, LGUI_T(KC_RGUI)),
	[1] = LAYOUT_5x6_right(KC_TILD, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_DEL, RCS(KC_2), KC_F9, KC_F10, LSFT(KC_F7), LCTL(KC_R), KC_LCBR, KC_RCBR, KC_HOME, KC_INS, KC_F11, KC_F12, KC_PLUS, KC_TRNS, RCS(KC_3), RCS(KC_4), MO(2), KC_DEL, KC_LPRN, KC_RPRN, KC_LEFT, KC_UP, KC_DOWN, KC_RGHT, KC_PIPE, KC_CAPS, LSFT(KC_F8), LSFT(KC_F9), LCTL(KC_X), LCTL(KC_C), LCTL(KC_V), KC_EQL, RCS(KC_3), RCS(KC_4), LSFT(KC_F8), LSFT(KC_F9), RCS(KC_2), LCTL(KC_F2), LCTL(KC_F3), KC_PSCR, KC_END, KC_LSFT, KC_TRNS, KC_TRNS, KC_RSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
	[2] = LAYOUT_5x6_right(KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, KC_CALC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LPRN, KC_RPRN, KC_P4, KC_P5, KC_P6, KC_TRNS, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_P0, KC_P1, KC_P2, KC_P3, KC_PEQL, KC_VOLD, KC_TRNS, KC_PDOT, KC_COMM, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)
};

Where 0, 1 and 2 are the different layers. While this is horrible to read of course, these layers are perfectly valid key maps. But you have to make some changes first before you can use it in the Tractyls firmware. First of all, copy only the part that says

	LAYOUT_5x6_right(KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL, KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS, KC_NO, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_BSLS, KC_LBRC, KC_RBRC, KC_PGUP, KC_PGDN, KC_LSFT, KC_NO, KC_NO, KC_RSFT, KC_LCTL, KC_SPC, KC_RALT, KC_LALT, MO(1), KC_ENT, LGUI_T(KC_RGUI)),

into an existing Tractyl layouts keymap.c. So you will not mess up the names of the layers. Now exchange the keycodes that should modify the trackball modes with the custom keycodes from above.

Other things to set in the firmware

If you haven’t yet, you can create the file keyboards/handwired/tractyl_manuform/5x6_right/keymaps/yourkeymap/config.h. In it you can put the following lines to change the behavior of your keyboard.

#define CHARYBDIS_MINIMUM_DEFAULT_DPI 1200

The minimum sensitivity in default mode.

#define CHARYBDIS_DEFAULT_DPI_CONFIG_STEP 200

Change of the sensitivity in cursor mode each time POINTER_DEFAULT_DPI_FORWARD/ REVERSE is pressed.

#define CHARYBDIS_MINIMUM_SNIPING_DPI 400

The sensitivity in sniping mode.

#define CHARYBDIS_SNIPING_DPI_CONFIG_STEP 200

Change of the pointers sensitivity in sniping mode each time POINTER_SNIPING_DPI_FORWARD/ REVERSE is pressed.

#define CHARYBDIS_DRAGSCROLL_DPI 100

The sensitivity in dragscroll mode.

#define CHARYBDIS_DRAGSCROLL_REVERSE_X / _Y

Reverse the scroll direction in dragscroll mode for the x / y axis.

#define CHARYBDIS_CARRET_BUFFER 40

The sensitivity in carret mode. Higher number means less sensitive.

#define CHARYBDIS_CARRET_REVERSE_X / _Y

Reverse the direction in carret mode for the x / y axis.

#define CHARYBDIS_POINTER_ACCELERATION_ENABLE

Enable pointer acceleration.

#define CHARYBDIS_POINTER_ACCELERATION_FACTOR 24

Amount of pointer acceleration.

#define CUSTOM_FN_RIGHT / CUSTOM_FN_LEFT / _UP / _DOWN

Here you can define the keycode that gets executed in custom mode when the trackball is rotated to the right / left / up / down.

Compiling your firmware

Once you are done with setting up the keymap to your liking, you can generate a .hex file with the command

qmk compile -kb handwired/Tractyl_manuform/5x6_right/arduinomicro -km <name_of_your_keymap>

while being inside the qmk_firmware_dm_r_track folder. If you haven’t screwed up your keymap.c from before, this will generate a .hex-file in the qmk_firmware folder.

Flashing the compiled .hex file.

Flashing the firmware is the usual flashing of a QMK firmware. You either compiled it yourself on your computer, with the somewhat finicky setup of the key map and compilation of the keymap.c, or with the rather comfortable QMK Configurator. Either way you are going to end up with a .hex file. I have never flashed a QMK firmware onto an Arduino in Windows or Mac, but I guess it’s rather easy using QMK Toolbox.

To flash a .hex in Linux you need to do the following:

Install avrdude

On Gentoo this is sudo emerge dev-embedded/avrdude, on Ubuntu sudo apt install avrdude and I am confident someone nerdy enough to want to use such a keyboard knows how to install software on his/ her distro.

Get your device name

To get your device name in Linux you use the command dmesg | tail. This shows you the end of the log of the kernel messages, so plug in the left side of the keyboard into your USB without the right side connected to it, put your Arduino into flash mode by pressing the reset button and run dmesg | tail. This will give you some output similar to

~[26768.779976] cdc_acm 1-12:1.0: ttyACM0: USB ACM device~

Which is telling you that /dev/ttyACM0 is the device name of your Arduino. Be aware that these device names are dynamic in Linux, so it could be /dev/ttyACM1 next time, because you already have another Arduino (or some other USB/Serial device) plugged in, which already occupies /dev/ttyACM0. Depending on your distro this could also be called /dev/ttyUSB0 instead.

If you can not find your device with dmesg | tail, try finding it with

find /dev -name '*ttyACM*' # or
find /dev -name '*ttyUSB*'

It could be that the device is only accessible by root, so to get user access you can use sudo chmod 777 /dev/ttyACM0, but this will only last until you reconnect the Arduino. To get permanent rights to access the Arduino as a user, you could also find the group of the /dev/ttyACM* file with ls -la /dev | grep ttyACM, which should output something like this: crw-rw-r-- 1 root dialout ... /dev/ttyACM. Add yourself to the group dialout (in this case) to get read/write permissions with sudo usermod -a -G dialout myUserName. However, the group name dialout could again depend on the distro.

Flashing the .hex

Now with all that information, put your Arduino into flash mode again by pressing the reset button. Use the command

avrdude -v -patmega32u4 -cavr109 -P/dev/ttyACM0 -b57600 -Uflash:w:"handwired_tractyl_manuform_5x6_right_arduinomicro_yourfilenamehere.hex":i

inside the folder where your .hex file is. Where /dev/ttyACM0 depends on the device name you obtained before and the filename of the .hex file is your own filename obviously.

Sometimes flashing Arduinos is a bit tricky. If they already have a program flashed to them, you put them into flashing mode by pressing the reset switch or connecting a reset pin with ground. (Either the one on the board if present or the one you wired.) Then they are in flashing mode for a few seconds before they start running in their normal mode again. So you have to press that reset switch then run that command fast. In case you did not add yourself to the group that owns /dev/ttyACM*, it could be that you have to find the name of that device (/dev/ttyACMsomething), change its permissions and run the command. All that in a few seconds. You could chain commands together with &&, but I recommend adding yourself to that group instead. Other times you get things like avrdude: butterfly_recv(): programmer is not responding. Then it helps to tap the reset button right after pressing enter on the upload command. Then I have had it with several Arduino Pro Micros, that I had to hold the reset button for two seconds or so, then let it go, then tap it. I guess there are just too many Arduino manufacturers out there, and each of them has its own quirks. So do not panic if uploading does not work at the first try. It could certainly be that your have some problem with avrdude, but most of the times it is just that you got the timing wrong and the Arduino is not in flashing mode. Once you are done with flashing the one side, disconnect it. Then connect the other side and do the same procedure again. You use the same .hex file on both sides. When you are done, connect the USB cable to the right side and use your new keyboard!

Tap-dance keymap

QMK has a feature called Tap Dance, which is really useful for the trackball modes we have in this keyboard. With Tap Dance you can give a key different functions depending on how often you tap it. Although Tap Dance supports way more, I only copied some basic functionality over from Qurns first Tap Dance software to change between the different trackball modes. By default, CTRL switches on cursor mode, Shift carret mode and Alt dragscroll mode. Tapping the key once will activate the corresponding mode, holding it will activate its actual modifier behavior. I also put in something for the vim lovers: I found myself pressing escape when I wanted to go back to cursor mode, because for my vim-brain this is like vims normal mode. So I put this functionality on the escape key. You can flash the Tap Dance firmware using this command:

qmk compile -kb handwired/Tractyl_manuform/5x6_right/arduinomicro -km tapdance

The keymap I put in is the keymap I use, which is Dvorak. So keep in mind you might want to change that. The tap-dance functions are the key codes that start with TD( like TD(SFT_TM) for the shift tap dance functions.

Changing tap-dance functions

To change what a tap dance function does, e.g. if you want to activate dragscroll with a tap of the shift key instead of the alt key, you can edit keyboards/handwired/tractyl_manuform/5x6_right/keymaps/tapdance/tapance.c. In there you have several functions like this one:

void sfttm_finished(qk_tap_dance_state_t *state, void *user_data) {
  td_state = cur_dance(state);
  sticky_timer = timer_read32();
  activate_sft = true;
  sticky_key = true;
  switch (td_state) {
  case SINGLE_TAP:
    charybdis_set_pointer_carret_enabled(true);
    break;
  case SINGLE_HOLD:
    activate_stkeys();
    sticky_key = false;
  }
}

This is the tap dance function for activating the shift modifier and for activating the carret mode. To activate dragscroll mode instead for example, you would change the line that says charybdis_set_pointer_carret_enabled(true); into charybdis_set_pointer_dragscroll_enabled(true);. That’s all. The different functions to activate the modes are in keyboards/handwired/tractyl_manuform/tractyl_manuform.h