/* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 2011,2012 Giovanni Di Sirio. This file is part of ChibiOS/RT. ChibiOS/RT 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 3 of the License, or (at your option) any later version. ChibiOS/RT 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 . */ /** * @file templates/chconf.h * @brief Configuration file template. * @details A copy of this file must be placed in each project directory, it * contains the application specific kernel settings. * * @addtogroup config * @details Kernel related settings and hooks. * @{ */ #ifndef _CHCONF_H_ #define _CHCONF_H_ /*===========================================================================*/ /** * @name Kernel parameters and options * @{ */ /*===========================================================================*/ /** * @brief System tick frequency. * @details Frequency of the system timer that drives the system ticks. This * setting also defines the system tick time unit. */ #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__) #define CH_FREQUENCY 1000 #endif /** * @brief Round robin interval. * @details This constant is the number of system ticks allowed for the * threads before preemption occurs. Setting this value to zero * disables the preemption for threads with equal priority and the * round robin becomes cooperative. Note that higher priority * threads can still preempt, the kernel is always preemptive. * * @note Disabling the round robin preemption makes the kernel more compact * and generally faster. */ #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__) #define CH_TIME_QUANTUM 20 #endif /** * @brief Managed RAM size. * @details Size of the RAM area to be managed by the OS. If set to zero * then the whole available RAM is used. The core memory is made * available to the heap allocator and/or can be used directly through * the simplified core memory allocator. * * @note In order to let the OS manage the whole RAM the linker script must * provide the @p __heap_base__ and @p __heap_end__ symbols. * @note Requires @p CH_USE_MEMCORE. */ #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__) #define CH_MEMCORE_SIZE 0 #endif /** * @brief Idle thread automatic spawn suppression. * @details When this option is activated the function @p chSysInit() * does not spawn the idle thread automatically. The application has * then the responsibility to do one of the following: * - Spawn a custom idle thread at priority @p IDLEPRIO. * - Change the main() thread priority to @p IDLEPRIO then enter * an endless loop. In this scenario the @p main() thread acts as * the idle thread. * . * @note Unless an idle thread is spawned the @p main() thread must not * enter a sleep state. */ #if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__) #define CH_NO_IDLE_THREAD FALSE #endif /** @} */ /*===========================================================================*/ /** * @name Performance options * @{ */ /*===========================================================================*/ /** * @brief OS optimization. * @details If enabled then time efficient rather than space efficient code * is used when two possible implementations exist. * * @note This is not related to the compiler optimization options. * @note The default is @p TRUE. */ #if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__) #define CH_OPTIMIZE_SPEED TRUE #endif /** @} */ /*===========================================================================*/ /** * @name Subsystem options * @{ */ /*===========================================================================*/ /** * @brief Threads registry APIs. * @details If enabled then the registry APIs are included in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__) #define CH_USE_REGISTRY TRUE #endif /** * @brief Threads synchronization APIs. * @details If enabled then the @p chThdWait() function is included in * the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) #define CH_USE_WAITEXIT TRUE #endif /** * @brief Semaphores APIs. * @details If enabled then the Semaphores APIs are included in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) #define CH_USE_SEMAPHORES TRUE #endif /** * @brief Semaphores queuing mode. * @details If enabled then the threads are enqueued on semaphores by * priority rather than in FIFO order. * * @note The default is @p FALSE. Enable this if you have special requirements. * @note Requires @p CH_USE_SEMAPHORES. */ #if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__) #define CH_USE_SEMAPHORES_PRIORITY FALSE #endif /** * @brief Atomic semaphore API. * @details If enabled then the semaphores the @p chSemSignalWait() API * is included in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_SEMAPHORES. */ #if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__) #define CH_USE_SEMSW TRUE #endif /** * @brief Mutexes APIs. * @details If enabled then the mutexes APIs are included in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) #define CH_USE_MUTEXES TRUE #endif /** * @brief Conditional Variables APIs. * @details If enabled then the conditional variables APIs are included * in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_MUTEXES. */ #if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__) #define CH_USE_CONDVARS TRUE #endif /** * @brief Conditional Variables APIs with timeout. * @details If enabled then the conditional variables APIs with timeout * specification are included in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_CONDVARS. */ #if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__) #define CH_USE_CONDVARS_TIMEOUT TRUE #endif /** * @brief Events Flags APIs. * @details If enabled then the event flags APIs are included in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) #define CH_USE_EVENTS TRUE #endif /** * @brief Events Flags APIs with timeout. * @details If enabled then the events APIs with timeout specification * are included in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_EVENTS. */ #if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) #define CH_USE_EVENTS_TIMEOUT TRUE #endif /** * @brief Synchronous Messages APIs. * @details If enabled then the synchronous messages APIs are included * in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) #define CH_USE_MESSAGES TRUE #endif /** * @brief Synchronous Messages queuing mode. * @details If enabled then messages are served by priority rather than in * FIFO order. * * @note The default is @p FALSE. Enable this if you have special requirements. * @note Requires @p CH_USE_MESSAGES. */ #if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__) #define CH_USE_MESSAGES_PRIORITY FALSE #endif /** * @brief Mailboxes APIs. * @details If enabled then the asynchronous messages (mailboxes) APIs are * included in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_SEMAPHORES. */ #if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) #define CH_USE_MAILBOXES TRUE #endif /** * @brief I/O Queues APIs. * @details If enabled then the I/O queues APIs are included in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__) #define CH_USE_QUEUES TRUE #endif /** * @brief Core Memory Manager APIs. * @details If enabled then the core memory manager APIs are included * in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__) #define CH_USE_MEMCORE TRUE #endif /** * @brief Heap Allocator APIs. * @details If enabled then the memory heap allocator APIs are included * in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or * @p CH_USE_SEMAPHORES. * @note Mutexes are recommended. */ #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) #define CH_USE_HEAP TRUE #endif /** * @brief C-runtime allocator. * @details If enabled the the heap allocator APIs just wrap the C-runtime * @p malloc() and @p free() functions. * * @note The default is @p FALSE. * @note Requires @p CH_USE_HEAP. * @note The C-runtime may or may not require @p CH_USE_MEMCORE, see the * appropriate documentation. */ #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__) #define CH_USE_MALLOC_HEAP FALSE #endif /** * @brief Memory Pools Allocator APIs. * @details If enabled then the memory pools allocator APIs are included * in the kernel. * * @note The default is @p TRUE. */ #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) #define CH_USE_MEMPOOLS TRUE #endif /** * @brief Dynamic Threads APIs. * @details If enabled then the dynamic threads creation APIs are included * in the kernel. * * @note The default is @p TRUE. * @note Requires @p CH_USE_WAITEXIT. * @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS. */ #if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__) #define CH_USE_DYNAMIC TRUE #endif /** @} */ /*===========================================================================*/ /** * @name Debug options * @{ */ /*===========================================================================*/ /** * @brief Debug option, system state check. * @details If enabled the correct call protocol for system APIs is checked * at runtime. * * @note The default is @p FALSE. */ #if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__) #define CH_DBG_SYSTEM_STATE_CHECK TRUE #endif /** * @brief Debug option, parameters checks. * @details If enabled then the checks on the API functions input * parameters are activated. * * @note The default is @p FALSE. */ #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) #define CH_DBG_ENABLE_CHECKS TRUE #endif /** * @brief Debug option, consistency checks. * @details If enabled then all the assertions in the kernel code are * activated. This includes consistency checks inside the kernel, * runtime anomalies and port-defined checks. * * @note The default is @p FALSE. */ #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) #define CH_DBG_ENABLE_ASSERTS TRUE #endif /** * @brief Debug option, trace buffer. * @details If enabled then the context switch circular trace buffer is * activated. * * @note The default is @p FALSE. */ #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) #define CH_DBG_ENABLE_TRACE TRUE #endif /** * @brief Debug option, stack checks. * @details If enabled then a runtime stack check is performed. * * @note The default is @p FALSE. * @note The stack check is performed in a architecture/port dependent way. * It may not be implemented or some ports. * @note The default failure mode is to halt the system with the global * @p panic_msg variable set to @p NULL. */ #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) #define CH_DBG_ENABLE_STACK_CHECK TRUE #endif /** * @brief Debug option, stacks initialization. * @details If enabled then the threads working area is filled with a byte * value when a thread is created. This can be useful for the * runtime measurement of the used stack. * * @note The default is @p FALSE. */ #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__) #define CH_DBG_FILL_THREADS TRUE #endif /** * @brief Debug option, threads profiling. * @details If enabled then a field is added to the @p Thread structure that * counts the system ticks occurred while executing the thread. * * @note The default is @p TRUE. * @note This debug option is defaulted to TRUE because it is required by * some test cases into the test suite. */ #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) #define CH_DBG_THREADS_PROFILING TRUE #endif /** @} */ /*===========================================================================*/ /** * @name Kernel hooks * @{ */ /*===========================================================================*/ /** * @brief Threads descriptor structure extension. * @details User fields added to the end of the @p Thread structure. */ #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__) #define THREAD_EXT_FIELDS \ /* Add threads custom fields here.*/ #endif /** * @brief Threads initialization hook. * @details User initialization code added to the @p chThdInit() API. * * @note It is invoked from within @p chThdInit() and implicitly from all * the threads creation APIs. */ #if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) #define THREAD_EXT_INIT_HOOK(tp) { \ /* Add threads initialization code here.*/ \ } #endif /** * @brief Threads finalization hook. * @details User finalization code added to the @p chThdExit() API. * * @note It is inserted into lock zone. * @note It is also invoked when the threads simply return in order to * terminate. */ #if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__) #define THREAD_EXT_EXIT_HOOK(tp) { \ /* Add threads finalization code here.*/ \ } #endif /** * @brief Context switch hook. * @details This hook is invoked just before switching between threads. */ #if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__) #define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \ /* System halt code here.*/ \ } #endif /** * @brief Idle Loop hook. * @details This hook is continuously invoked by the idle thread loop. */ #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) #define IDLE_LOOP_HOOK() { \ /* Idle loop code here.*/ \ } #endif /** * @brief System tick event hook. * @details This hook is invoked in the system tick handler immediately * after processing the virtual timers queue. */ #if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__) #define SYSTEM_TICK_EVENT_HOOK() { \ /* System tick event code here.*/ \ } #endif /** * @brief System halt hook. * @details This hook is invoked in case to a system halting error before * the system is halted. */ #if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) #define SYSTEM_HALT_HOOK() { \ /* System halt code here.*/ \ } #endif /** @} */ /*===========================================================================*/ /* Port-specific settings (override port settings defaulted in chcore.h). */ /*===========================================================================*/ #endif /* _CHCONF_H_ */ /** @} */ '>436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
# Hand-Wiring Guide

## Preamble: How a Keyboard Matrix Works (and why we need diodes)

The collapsible section below covers why keyboards are wired the way they are, as outlined in this guide.  It isn't required reading to make your own hand wired keyboard, but provides background information.

<details>

<summary>Click for details</summary>

Without a matrix circuit each switch would require its own wire directly to the controller.

Simply put, when the circuit is arranged in rows and columns, if a key is pressed, a column wire makes contact with a row wire and completes a circuit. The keyboard controller detects this closed circuit and registers it as a key press.

The microcontroller will be setup up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example:

        Column 0 being scanned     Column 1 being scanned
                  x                                   x
                 col0     col1              col0     col1
                  |        |                 |        |
        row0 ---(key0)---(key1)    row0 ---(key0)---(key1)
                  |        |                 |        |
        row1 ---(key2)---(key3)    row1 ---(key2)---(key3)

The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column.

When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected:

        Column 0 being scanned     Column 1 being scanned
                  x                                   x
                 col0     col1              col0     col1
                  |        |                 |        |
      x row0 ---(-+-0)---(key1)    row0 ---(-+-0)---(key1)
                  |        |                 |        |
        row1 ---(key2)---(key3)    row1 ---(key2)---(key3)

We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is

    col0: 0b01
    col1: 0b00
            │└row0
            └row1

A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious:

        Column 0 being scanned     Column 1 being scanned
                  x                                   x
                 col0     col1              col0     col1
                  |        |                 |        |
      x row0 ---(-+-0)---(-+-1)  x row0 ---(-+-0)---(-+-1)
                  |        |                 |        |
      x row1 ---(key2)---(-+-3)  x row1 ---(key2)---(-+-3)

      Remember that this ^ is still connected to row1

The data we get from that is:

    col0: 0b11
    col1: 0b11
            │└row0
            └row1

Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this;

        Column 0 being scanned     Column 1 being scanned
                    x                                   x
                  col0      col1              col0     col1
                    │        │                 |        │
                 (key0)   (key1)            (key0)   (key1)
                  ! │      ! │               ! |      ! │
        row0 ─────┴────────┘ │     row0 ─────┴────────┘ │
                    │        │                 |        │
                 (key2)   (key3)            (key2)   (key3)
                  !        !                 !        !
        row1 ─────┴────────┘       row1 ─────┴────────┘

In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|`

Now when we press the three keys, invoking what would be a ghosting scenario:

        Column 0 being scanned     Column 1 being scanned
                    x                                   x
                  col0      col1              col0     col1
                    │        │                 │        │
                 (┌─┤0)   (┌─┤1)            (┌─┤0)   (┌─┤1)
                  ! │      ! │               ! │      ! │
      x row0 ─────┴────────┘ │   x row0 ─────┴────────┘ │
                    │        │                 │        │
                 (key2)   (┌─┘3)            (key2)   (┌─┘3)
                  !        !                 !        !
        row1 ─────┴────────┘     x row1 ─────┴────────┘

Things act as they should! Which will get us the following data:

    col0: 0b01
    col1: 0b11
            │└row0
            └row1

The firmware can then use this correct data to detect what it should do, and eventually, what signals it needs to send to the OS.

Further reading:
- [Wikipedia article](https://en.wikipedia.org/wiki/Keyboard_matrix_circuit)
- [Deskthority article](https://deskthority.net/wiki/Keyboard_matrix)
- [Keyboard Matrix Help by Dave Dribin (2000)](https://www.dribin.org/dave/keyboard/one_html/)
- [How Key Matrices Works by PCBheaven](http://pcbheaven.com/wikipages/How_Key_Matrices_Works/) (animated examples)
- [How keyboards work - QMK documentation](how_keyboards_work.md)

</details>


## Parts list

You will need: (where *x* is the number of keys on your planned keyboard)

* QMK compatible microcontroller board (Teensy, Pro-Micro, QMK Proton C etc.)
* *x* keyswitches (MX, Matias, Gateron, etc)
* *x* through hole diodes
* Keyboard plate and plate mount stabilisers
* Wire
* Soldering iron
* Rosin-cored solder
* Adequate ventilation/a fan
* Wire cutters/snippers

Optional but useful:

* Wire strippers/a sharp knife
* Tweezers and/or small needle nose pliers
* Soldering station/Helping hands

## Starting the build

There are many ways to hand wire a PCB matrix, this guide will describe the fundamentals as well as some recommended ways to go about it.

As we are dealing with hand wiring, it is assumed that you already have a plate.  If you are planning a completely custom layout, tools such as [ai03 Plate Generator](https://kbplate.ai03.me/) and [Swillkb Plate & Case Builder](http://builder.swillkb.com/) can help when designing one.

Start by installing the switches and stabilisers in the plate. Depending on the thickness and material this may also involve hot gluing it in place.

## Planning the matrix

If you are following a pre-existing handwire guide (e.g. for the keyboards in the [handwire firmware section](https://github.com/qmk/qmk_firmware/tree/master/keyboards/handwired) you can skip this step, just ensure you wire the matrix as described.

What you want to achieve is one leg from each switch being attached to the corresponding switches next to it (rows) and the other leg being attached to the switches above and below it (columns) and a diode to one of the legs, mosy commonly this will be the leg attached to the rows, and the diode will face away from it (Column to Row) i.e. with the wire furthest from the black line on the diode connected to the switch (as current will only travel in one direction through a diode)