Merge pull request #13 from johnfonte/dev

Dev Catchup Pull Request - johnfonte
(merge branch master with dev)

See commit history.  Primarily:
- the build process changed a bit to make things easier for the UI
- a couple key functions were added (including code for an integrated numpad)
- a whole bunch of stuff was reorganized
- work was started on changing the way layers and layer switching are handled
- things were updated for the new PCB prototype by Fredrik (bpiphany) (and diode direction is now selectable during compilation by setting some macros in src/keyboard/ergodox/options.h)

Everything tests out on the breadboard, and with the PCB as far as I can tell.  I don't know if testing has been done with a complete keyboard using the new PCB yet.
f13
Ben Blazak 2012-09-13 09:34:02 -07:00
commit f46a67d5eb
28 changed files with 1417 additions and 355 deletions

2
contrib/readme.md Normal file
View File

@ -0,0 +1,2 @@
This directory is for projects closely related to the firmware.

61
makefile Normal file
View File

@ -0,0 +1,61 @@
# -----------------------------------------------------------------------------
# makefile for the ergoDOX project
#
# This should produce a single file (probably in an archive format) for
# distribution, containing everything people will need to use the software.
#
# DEPENDENCIES: This is unabashedly dependant on various Unix commands, and
# therefore probably won't work in a Windows environment. I'm sorry... I
# don't know a good portable way to write it.
#
# TODO:
# - include doc files (and maybe render them in html)
# - include the UI stuff (once it's done)
# -----------------------------------------------------------------------------
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (MIT) (see "license.md")
# Project located at <https://github.com/benblazak/ergodox-firmware>
# -----------------------------------------------------------------------------
# the base name of the file or package to distribute
NAME := ergodox-firmware
# the branch of the git repo we're currently on
BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
# a version identifier
VERSION := $(shell git log -n 1 | grep 'commit' | cut -c 8-14)--$(shell date +'%Y%m%dT%H%M%S')
# name to use for the final distribution file or package
TARGET := $(NAME)--$(BRANCH)--$(VERSION)
# the build dir
BUILD := build
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
.PHONY: all clean dist
all: dist
clean:
git clean -dX # remove ignored files and directories
-rm -r '$(BUILD)'
dist:
# set up the build dir
-rm -r '$(BUILD)/$(TARGET)'*
-mkdir -p '$(BUILD)/$(TARGET)'
# make all subprojects
cd src; $(MAKE) all
# copy stuff to build dir
# --- from src
( cd src; \
cp firmware.hex firmware.eep firmware.map \
'../$(BUILD)/$(TARGET)' )
# make into a zip archive
( cd '$(BUILD)/$(TARGET)'; \
zip '../$(TARGET).zip' \
-r * .* \
-x '..*' )

View File

@ -377,6 +377,17 @@
## Miscellaneous
### Keyboard Testing Tools
* [Understanding Rollover]
(http://gadzikowski.com/nkeyrollover.html)
Includes 3 different tests (2 of which are web based) to see which keys are
actually registering as pressed.
* mentioned on the [Default:NKey Rollover]
(http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results)
page (on <http://geekhack.org/>)
### Typical Keyboard Information
* [Keyboard Scan Rates]

View File

@ -1,9 +1,7 @@
*~
*.swp
*.hex
*.eep
*.elf
*.hex
*.map
*.o
*.o.dep

View File

@ -9,10 +9,9 @@
#include "lib/data-types.h"
#define KEYBOARD_INCLUDE_PRIVATE
#include "ergodox/matrix.h"
#include "ergodox/mcp23018.h"
#include "ergodox/teensy-2-0.h"
#include "ergodox/mcp23018--private.h"
#include "ergodox/teensy-2-0--private.h"
/* returns

View File

@ -16,7 +16,6 @@
#include "ergodox/layout.h" // number of layers, layout
#include "ergodox/led.h" // logical led controls
#include "ergodox/matrix.h" // kb dimensions, matrix status
#include "ergodox/mcp23018.h" // (nothing right now)
#include "ergodox/teensy-2-0.h" // LED controls

View File

@ -12,9 +12,9 @@
inkscape:version="0.48.2 r9819"
version="1.1"
id="svg2"
height="398.98083"
height="416.48083"
width="950.8382"
sodipodi:docname="_circuit-diagram.svg"
sodipodi:docname="circuit-diagram.svg"
inkscape:export-filename="/home/ben/Desktop/programs/20120227--ergodox-firmware--for-the-ergodox-keyboard/src/test - circuit diagram/inkscape/_circuit-diagram.png"
inkscape:export-xdpi="150"
inkscape:export-ydpi="150">
@ -26,8 +26,8 @@
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="477.26232"
inkscape:cy="197.75046"
inkscape:cx="464.65225"
inkscape:cy="203.44926"
inkscape:document-units="px"
inkscape:current-layer="layer7"
showgrid="true"
@ -1924,22 +1924,22 @@
sodipodi:nodetypes="ccccccccccccc" />
<path
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10)"
d="M 255,127.36218 C 319.96657,67.757371 380.66023,68.094183 381.84624,86.972644 l -0.15377,7.638959"
d="M 255,127.36218 C 297.1005,68.254966 399.98689,51.202007 403.41299,89.442314 l 0.023,4.815736"
id="path7504"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10);display:inline"
d="M 234.96647,127.29296 C 300.31207,48.235689 400.85603,51.277895 403.56272,86.653429 l -0.15377,7.638959"
d="M 234.96647,127.29296 C 305.92363,44.536037 388.15055,41.329164 381.99597,85.946323 l 0.023,8.346065"
id="path7504-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7)"
d="m 195,247.36218 c -4.32571,23.55176 70.95424,57.80762 144.21458,54.72312 9.45484,-5.50003 -1.67061,-20.3897 5.26135,-28.19694 38.00964,-42.80905 -0.71668,-177.441227 11.27147,-189.245847 9.78813,-9.032436 -5.54253,-24.848413 5.08961,-28.779094 28.50706,-10.539011 62.33333,12.384603 62.61183,28.039681 l -0.0815,10.708503"
d="m 195,247.36218 c -4.32571,23.55176 70.95424,57.80762 144.21458,54.72312 9.45484,-5.50003 -1.67061,-20.3897 5.26135,-28.19694 38.00964,-42.80905 6.84799,-181.553227 13.02147,-196.245847 6.17348,-14.69262 -2.21854,-13.634877 3.33961,-21.779094 5.55815,-8.144217 62.33333,-4.615397 62.61183,28.039681 l -0.0815,10.708503"
id="path7758"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscscc" />
sodipodi:nodetypes="ccszzcc" />
<path
style="fill:none;stroke:#000077;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7);marker-end:url(#DotM-10-7)"
d="m 95.105862,247.67467 c -2.592497,38.06584 1.233202,73.99227 7.071068,109.24799"
@ -2079,32 +2079,32 @@
y="176.07817"
id="tspan9630">PWM</tspan></text>
<text
inkscape:transform-center-y="-9.2023172"
inkscape:transform-center-x="4.2210811"
transform="matrix(0.88676162,-0.46222703,0.46222703,0.88676162,0,0)"
inkscape:transform-center-y="-8.1837146"
inkscape:transform-center-x="5.960441"
transform="matrix(0.7776191,-0.62873566,0.62873566,0.7776191,0,0)"
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
x="214.90239"
y="211.07732"
x="135.67398"
y="246.92535"
id="text9938"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="214.90239"
y="211.07732"
x="135.67398"
y="246.92535"
id="tspan9636">PWM</tspan></text>
<text
inkscape:transform-center-y="-3.7829232"
inkscape:transform-center-x="-6.0157706"
transform="matrix(0.89485423,-0.4463585,0.4463585,0.89485423,0,0)"
inkscape:transform-center-y="-3.7250803"
inkscape:transform-center-x="-6.0517844"
transform="matrix(0.89909256,-0.43775858,0.43775858,0.89909256,0,0)"
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
x="221.94164"
y="223.0845"
x="227.65367"
y="215.32523"
id="text9941"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="221.94164"
y="223.0845"
x="227.65367"
y="215.32523"
id="tspan9632">PWM</tspan></text>
<text
xml:space="preserve"
@ -2693,7 +2693,11 @@
sodipodi:role="line"
id="tspan3445"
x="37.24189"
y="388.43091">- Please also see documentation (especially the notes) in the *.md files</tspan></text>
y="388.43091">- Please also see documentation (especially the notes) in the *.md files</tspan><tspan
sodipodi:role="line"
x="37.24189"
y="405.93091"
id="tspan3451">- Row and column assignments are to matrix positions, not physical positions</tspan></text>
</g>
<g
inkscape:groupmode="layer"

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 152 KiB

View File

@ -15,12 +15,11 @@
#include "lib/data-types.h"
#include "lib/key-functions.h" // for `kbfun_funptr_t`
#include "matrix.h" // for number of rows and columns, and layout
// to matrix macros
#include "matrix.h" // for number of rows and columns
// include the appropriate keyboard layout header
// for:
// - number of layers
// - possible non-default number of layers
// - possible non-default layout matrix definitions
// - possible non-default layout 'get' and 'set' definitions
#undef _str
@ -35,6 +34,12 @@
#undef _inc
// default number of layers
#ifndef KB_LAYERS
#define KB_LAYERS 10
#endif
// default layout 'get' macros and `extern` matrix declarations
//
// these are for when the matrices are stored solely in Flash. layouts

View File

@ -14,48 +14,252 @@
#include "lib/usb/usage-page/keyboard--short-names.h"
#include "lib/key-functions.h"
#define KEYBOARD_INCLUDE_PRIVATE
#include "../matrix.h"
#include "../layout.h"
// error check: everything below assumes these dimensions
#if KB_LAYERS != 1 || KB_ROWS != 12 || KB_COLUMNS != 7
#error "Expecting different keyboard dimensions"
#endif
// aliases
#define f_prrel &kbfun_press_release
#define f_toggl &kbfun_toggle
#define f_l_inc &kbfun_layer_inc
#define f_l_dec &kbfun_layer_dec
#define f_l_iex &kbfun_layer_inc_exec
#define f_l_dex &kbfun_layer_dec_exec
#define f_2kcap &kbfun_2_keys_capslock_press_release
#define f_np_to &kbfun_layermask_numpad_toggle
#define f_np_on &kbfun_layermask_numpad_on
#define f_np_of &kbfun_layermask_numpad_off
#define f_btldr &kbfun_jump_to_bootloader
uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
LAYER( // layer 0: default
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// unused
0,
// left hand
_grave, _1, _2, _3, _4, _5, _equal,
_tab, _Q, _W, _E, _R, _T, _esc,
_capsLock, _A, _S, _D, _F, _G,
_shiftL, _Z, _X, _C, _V, _B, _ctrlL,
_guiL, _arrowL, _arrowU, _arrowD, _arrowR,
_bs,
_del, _ctrlL,
_end, _home, _altL,
_grave, _1, _2, _3, _4, _5, _equal,
_bracketL, _Q, _W, _E, _R, _T, _esc,
_tab, _A, _S, _D, _F, _G,
_shiftL, _Z, _X, _C, _V, _B, 1,
_guiL, _arrowL, _arrowU, _arrowD, _arrowR,
_bs,
_del, _ctrlL,
_end, _home, _altL,
// right hand
_backslash, _6, _7, _8, _9, _0, _dash,
_bracketL, _Y, _U, _I, _O, _P, _bracketR,
_H, _J, _K, _L, _semicolon, _quote,
_ctrlR, _N, _M, _comma, _period, _slash, _shiftR,
_arrowL, _arrowD, _arrowU, _arrowR, _guiR,
_backslash, _6, _7, _8, _9, _0, _dash,
_bracketL, _Y, _U, _I, _O, _P, _bracketR,
_H, _J, _K, _L, _semicolon, _quote,
1, _N, _M, _comma, _period, _slash, _shiftR,
_arrowL, _arrowD, _arrowU, _arrowR, _guiR,
_space,
_ctrlR, _enter,
_altR, _pageU, _pageD )
_altR, _pageU, _pageD ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// unused
0,
// left hand
-1, _F1, _F2, _F3, _F4, _F5, _F11,
0, _braceL_kp, _braceR_kp, _bracketL, _bracketR, 0, _esc,
0, _semicolon, _slash, _dash, 0, _colon_kp,
2, 0, 0, 0, 0, 0, 0,
0, _arrowL, _arrowU, _arrowD, _arrowR,
_bs,
_del, _ctrlL,
_end, _home, _altL,
// right hand
_F12, _F6, _F7, _F8, _F9, _F10, 0,
2, 0, _dash, _lt_kp, _gt_kp, _currencyUnit, 0,
_backslash, 0, _parenL_kp, _parenR_kp, _equal, 0,
0, _mul_kp, 0, 0, 0, 0, 0,
_arrowL, _arrowD, _arrowU, _arrowR, 0,
_space,
_ctrlR, _enter,
_altR, _pageU, _pageD ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// unused
0,
// left hand
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0,
0, 0,
0, 0, 0,
// right hand
//------- ------- ------- ------- ------- ------- -------
0, 0, _7_kp, _8_kp, _9_kp, _div_kp, 0,
0, 0, _4_kp, _5_kp, _6_kp, _mul_kp, 0,
0, _1_kp, _2_kp, _3_kp, _sub_kp, 0,
0, 0, _0_kp, _period, 0, _add_kp, 0,
0, 0, 0, 0, 0,
0,
0, 0,
0, 0, 0 )
// ----------------------------------------------------------------------------
};
kbfun_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
LAYER_SET_ALL(NULL, &kbfun_press) // layer 0: default
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// unused
NULL,
// left hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_2kcap,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_l_inc,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel,
// right hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_l_inc,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_2kcap,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// unused
NULL,
// left hand
f_btldr,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_np_on,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel,
// right hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_np_to,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// unused
NULL,
// left hand
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL, NULL,
// right hand
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL, NULL )
// ----------------------------------------------------------------------------
};
kbfun_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
LAYER_SET_ALL(NULL, &kbfun_release) // layer 0: default
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 0: default
// unused
NULL,
// left hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_2kcap,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_l_dec,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel,
// right hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_l_dec,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_2kcap,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 1: function and symbol keys
// unused
NULL,
// left hand
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_np_of,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel,
// right hand
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
f_prrel,
f_prrel, f_prrel,
f_prrel,f_prrel,f_prrel ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 2: numpad
// unused
NULL,
// left hand
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL, NULL,
// right hand
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL, NULL ),
// ----------------------------------------------------------------------------
MATRIX_LAYER( // layer 3: nothing (just making sure unused functions
// don't get compiled out)
// unused
NULL,
// other
f_prrel, NULL, NULL, NULL, NULL, NULL, NULL,
f_toggl, NULL, NULL, NULL, NULL, NULL, NULL,
f_l_inc, NULL, NULL, NULL, NULL, NULL, NULL,
f_l_dec, NULL, NULL, NULL, NULL, NULL, NULL,
f_l_iex, NULL, NULL, NULL, NULL, NULL, NULL,
f_l_dex, NULL, NULL, NULL, NULL, NULL, NULL,
f_2kcap, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_to, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_on, NULL, NULL, NULL, NULL, NULL, NULL,
f_np_of, NULL, NULL, NULL, NULL, NULL, NULL,
f_btldr, NULL, NULL, NULL, NULL, NULL )
// ----------------------------------------------------------------------------
};

View File

@ -13,14 +13,12 @@
#include "../led.h"
#define KB_LAYERS 1 // must match what's defined in "qwerty.c"
#define kb_led_num_on() _led_1_on()
#define kb_led_num_off() _led_1_off()
#define kb_led_caps_on() _led_2_on()
#define kb_led_caps_off() _led_2_off()
#define kb_led_scroll_on() _led_3_on()
#define kb_led_scroll_off() _led_3_off()
#define kb_led_num_on() _kb_led_1_on()
#define kb_led_num_off() _kb_led_1_off()
#define kb_led_caps_on() _kb_led_2_on()
#define kb_led_caps_off() _kb_led_2_off()
#define kb_led_scroll_on() _kb_led_3_on()
#define kb_led_scroll_off() _kb_led_3_off()
#endif

View File

@ -4,8 +4,9 @@
* you should also include this file for low-level led macros, as it will
* always include the file(s) containing those
*
* - low level led macros should all start with '_led_'
* - public led macros should start with 'kb_led_'
* - low level LED macros (that have to be shared, but aren't really public)
* should all start with '_kb_led_'
* - public LED macros should start with 'kb_led_'
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -22,23 +23,23 @@
#define kb_led_state_power_on() do { \
_led_all_set_percent(0.05); \
_led_all_on(); \
_kb_led_all_set_percent(0.05); \
_kb_led_all_on(); \
} while(0)
// note: need to delay for a total of ~1 second
#define kb_led_delay_usb_init() do { \
_led_1_set_percent(0.5); \
_kb_led_1_set_percent(0.5); \
_delay_ms(333); \
_led_2_set_percent(0.5); \
_kb_led_2_set_percent(0.5); \
_delay_ms(333); \
_led_3_set_percent(0.5); \
_kb_led_3_set_percent(0.5); \
_delay_ms(333); \
} while(0)
#define kb_led_state_ready() do { \
_led_all_off(); \
_led_all_set_percent(0.5); \
_kb_led_all_off(); \
_kb_led_all_set_percent(0.5); \
} while(0)
#endif

View File

@ -19,92 +19,88 @@
extern bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS];
#ifdef KEYBOARD_INCLUDE_PRIVATE
/* mapping from spatial position to matrix position
* - spatial position: where the key is spatially, relative to
* other keys both on the keyboard and in the layout
* - matrix position: the coordinate in the matrix to which
* a key is scanned by the update functions
*
* - location numbers are in the format `row##column`, where
* both 'row' and 'column' are single digit hex numbers
* corresponding to the matrix position (which also
* corresponds to the row and column pin labels used in the
* teensy and mcp23018 files)
* - coordinates not listed are unused
*
* --- other info ---------------------------------------------
* rows x columns = positions; assigned, unassigned
* per hand: 6 x 7 = 42; 38, 4
* total: 12 x 7 = 84; 76, 8
*
* left hand : cols 0..6, rows 6..B
* right hand : cols 0..6, rows 0..5
* ------------------------------------------------------------
*/
#define LAYER( \
/* for unused positions */ \
na, \
\
/* left hand, spatial positions */ \
kB6,kB5,kB4,kB3,kB2,kB1,kB0, \
kA6,kA5,kA4,kA3,kA2,kA1,kA0, \
k96,k95,k94,k93,k92,k91, \
k86,k85,k84,k83,k82,k81,k80, \
k76,k75,k74,k73,k72, \
k64, \
k63, k60, \
k65,k62,k61, \
\
/* right hand, spatial positions */ \
k50,k51,k52,k53,k54,k55,k56, \
k40,k41,k42,k43,k44,k45,k46, \
k31,k32,k33,k34,k35,k36, \
k20,k21,k22,k23,k24,k25,k26, \
k12,k13,k14,k15,k16, \
k04, \
k00, k03, \
k01,k02,k05 ) \
\
/* matrix positions */ \
{ { k00,k01,k02,k03,k04,k05, na,}, \
{ na, na,k12,k13,k14,k15,k16,}, \
{ k20,k21,k22,k23,k24,k25,k26,}, \
{ na,k31,k32,k33,k34,k35,k36,}, \
{ k40,k41,k42,k43,k44,k45,k46,}, \
{ k50,k51,k52,k53,k54,k55,k56,}, \
{ k60,k61,k62,k63,k64,k65, na,}, \
{ na, na,k72,k73,k74,k75,k76,}, \
{ k80,k81,k82,k83,k84,k85,k86,}, \
{ na,k91,k92,k93,k94,k95,k96,}, \
{ kA0,kA1,kA2,kA3,kA4,kA5,kA6,}, \
{ kB0,kB1,kB2,kB3,kB4,kB5,kB6 } }
/* mapping from spatial position to matrix position
* - spatial position: where the key is spatially, relative to other
* keys both on the keyboard and in the layout
* - matrix position: the coordinate in the matrix to which a key is
* scanned by the update functions
*
* - location numbers are in the format `row##column`, where both 'row'
* and 'column' are single digit hex numbers corresponding to the
* matrix position (which also corresponds to the row and column pin
* labels used in the teensy and mcp23018 files)
* - coordinates not listed are unused
*
* --- other info -----------------------------------------------------
* rows x columns = positions; assigned, unassigned
* per hand: 6 x 7 = 42; 38, 4
* total: 12 x 7 = 84; 76, 8
*
* left hand : cols 0..6, rows 6..B
* right hand : cols 0..6, rows 0..5
* --------------------------------------------------------------------
*/
#define MATRIX_LAYER( \
/* for unused positions */ \
na, \
\
/* left hand, spatial positions */ \
kB6,kB5,kB4,kB3,kB2,kB1,kB0, \
kA6,kA5,kA4,kA3,kA2,kA1,kA0, \
k96,k95,k94,k93,k92,k91, \
k86,k85,k84,k83,k82,k81,k80, \
k76,k75,k74,k73,k72, \
k64, \
k63, k60, \
k65,k62,k61, \
\
/* right hand, spatial positions */ \
k50,k51,k52,k53,k54,k55,k56, \
k40,k41,k42,k43,k44,k45,k46, \
k31,k32,k33,k34,k35,k36, \
k20,k21,k22,k23,k24,k25,k26, \
k12,k13,k14,k15,k16, \
k04, \
k00, k03, \
k01,k02,k05 ) \
\
/* matrix positions */ \
{ { k00,k01,k02,k03,k04,k05, na,}, \
{ na, na,k12,k13,k14,k15,k16,}, \
{ k20,k21,k22,k23,k24,k25,k26,}, \
{ na,k31,k32,k33,k34,k35,k36,}, \
{ k40,k41,k42,k43,k44,k45,k46,}, \
{ k50,k51,k52,k53,k54,k55,k56,}, \
{ k60,k61,k62,k63,k64,k65, na,}, \
{ na, na,k72,k73,k74,k75,k76,}, \
{ k80,k81,k82,k83,k84,k85,k86,}, \
{ na,k91,k92,k93,k94,k95,k96,}, \
{ kA0,kA1,kA2,kA3,kA4,kA5,kA6,}, \
{ kB0,kB1,kB2,kB3,kB4,kB5,kB6 } }
#define LAYER_SET_ALL(na, kxx) \
LAYER( \
na, \
\
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx, \
kxx, \
kxx, kxx, \
kxx,kxx,kxx, \
\
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx, \
kxx, \
kxx, kxx, \
kxx,kxx,kxx )
#define MATRIX_LAYER_SET_ALL(na, kxx) \
LAYER( \
na, \
\
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx, \
kxx, \
kxx, kxx, \
kxx,kxx,kxx, \
\
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
kxx,kxx,kxx,kxx,kxx, \
kxx, \
kxx, kxx, \
kxx,kxx,kxx )
#endif
#endif

View File

@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: MCP23018 specific exports
* ergoDOX controller: MCP23018 specific exports : private
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -7,20 +7,16 @@
* ------------------------------------------------------------------------- */
#ifndef MCP23018_h
#define MCP23018_h
#ifndef MCP23018_h_PRIVATE
#define MCP23018_h_PRIVATE
#include "lib/data-types.h"
#include "matrix.h"
#ifdef KEYBOARD_INCLUDE_PRIVATE
#define MCP23018_TWI_ADDRESS 0b0100000
#define MCP23018_TWI_ADDRESS 0b0100000
uint8_t mcp23018_init(void);
uint8_t mcp23018_update_matrix(
bool matrix[KB_ROWS][KB_COLUMNS] );
#endif
uint8_t mcp23018_init(void);
uint8_t mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
#endif

View File

@ -11,9 +11,8 @@
#include "lib/data-types.h"
#include "lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#define KEYBOARD_INCLUDE_PRIVATE
#include "matrix.h"
#include "mcp23018.h"
#include "mcp23018--private.h"
// register addresses (see "mcp23018.md")

View File

@ -41,6 +41,11 @@
NC o14-------15+ ADDR (see note)
* notes:
* Row and column assignments are to matrix positions, which may or may
correspond to the physical position of the key: e.g. the key where `row4`
and `column2` cross will be scanned into the matrix at `[4][2]`, wherever
it happens to be located on the keyboard. Mapping from one to the other
(which only matters for defining layouts) is handled elsewhere.
* ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
* The user-defined bits are the three least significant
* I2C addresses are 7 bits long (the last bit in the byte is used for

View File

@ -0,0 +1,19 @@
/* ----------------------------------------------------------------------------
* ergoDOX controller: Teensy 2.0 specific exports : private
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef TEENSY_2_0_h_PRIVATE
#define TEENSY_2_0_h_PRIVATE
#include "matrix.h"
uint8_t teensy_init(void);
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
#endif

View File

@ -13,9 +13,9 @@
#define TWI_FREQ 400000
#include "lib/twi.h"
#define KEYBOARD_INCLUDE_PRIVATE
#include "matrix.h"
#include "teensy-2-0.h"
#include "teensy-2-0--private.h"
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
@ -123,7 +123,7 @@ uint8_t teensy_init(void) {
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
_led_all_off(); // (just to put the pins in a known state)
_kb_led_all_off(); // (just to put the pins in a known state)
TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // set and configure fast PWM

View File

@ -13,54 +13,43 @@
#include <avr/io.h> // for the register macros
#include "lib/data-types.h"
#include "matrix.h"
// LED control
#define _led_1_on() (DDRB |= (1<<6))
#define _led_1_off() (DDRB &= ~(1<<6))
#define _led_1_set(n) (OCR1B = (uint8_t)(n))
#define _led_1_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
#define _kb_led_1_on() (DDRB |= (1<<6))
#define _kb_led_1_off() (DDRB &= ~(1<<6))
#define _kb_led_1_set(n) (OCR1B = (uint8_t)(n))
#define _kb_led_1_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
//
#define _led_2_on() (DDRB |= (1<<5))
#define _led_2_off() (DDRB &= ~(1<<5))
#define _led_2_set(n) (OCR1A = (uint8_t)(n))
#define _led_2_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
#define _kb_led_2_on() (DDRB |= (1<<5))
#define _kb_led_2_off() (DDRB &= ~(1<<5))
#define _kb_led_2_set(n) (OCR1A = (uint8_t)(n))
#define _kb_led_2_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
//
#define _led_3_on() (DDRB |= (1<<7))
#define _led_3_off() (DDRB &= ~(1<<7))
#define _led_3_set(n) (OCR1C = (uint8_t)(n))
#define _led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
#define _kb_led_3_on() (DDRB |= (1<<7))
#define _kb_led_3_off() (DDRB &= ~(1<<7))
#define _kb_led_3_set(n) (OCR1C = (uint8_t)(n))
#define _kb_led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
// ---
#define _led_all_on() do { \
_led_1_on(); \
_led_2_on(); \
_led_3_on(); \
#define _kb_led_all_on() do { \
_kb_led_1_on(); \
_kb_led_2_on(); \
_kb_led_3_on(); \
} while(0)
#define _led_all_off() do { \
_led_1_off(); \
_led_2_off(); \
_led_3_off(); \
#define _kb_led_all_off() do { \
_kb_led_1_off(); \
_kb_led_2_off(); \
_kb_led_3_off(); \
} while(0)
#define _led_all_set(n) do { \
_led_1_set(n); \
_led_2_set(n); \
_led_3_set(n); \
#define _kb_led_all_set(n) do { \
_kb_led_1_set(n); \
_kb_led_2_set(n); \
_kb_led_3_set(n); \
} while(0)
#define _led_all_set_percent(n) do { \
_led_1_set_percent(n); \
_led_2_set_percent(n); \
_led_3_set_percent(n); \
#define _kb_led_all_set_percent(n) do { \
_kb_led_1_set_percent(n); \
_kb_led_2_set_percent(n); \
_kb_led_3_set_percent(n); \
} while(0)
#ifdef KEYBOARD_INCLUDE_PRIVATE
uint8_t teensy_init(void);
uint8_t teensy_update_matrix(
bool matrix[KB_ROWS][KB_COLUMNS] );
#endif
#endif

View File

@ -44,6 +44,11 @@
GND-------/
* notes:
* Row and column assignments are to matrix positions, which may or may
correspond to the physical position of the key: e.g. the key where `row4`
and `column2` cross will be scanned into the matrix at `[4][2]`, wherever
it happens to be located on the keyboard. Mapping from one to the other
(which only matters for defining layouts) is handled elsewhere.
* SCL and SDA: Need external pull-up resistors. Sometimes the Teensy
internal pull-ups are enough (see datasheet section 20.5.1), but i think
for this project we'll want external ones. The general recommendation

View File

@ -10,12 +10,10 @@
#ifndef DATA_TYPES_h
#define DATA_TYPES_h
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define bool _Bool
#define true ((bool)1)
#define false ((bool)0)
#include "data-types/linked-list.h"
#endif

View File

@ -0,0 +1,240 @@
/* ----------------------------------------------------------------------------
* linked list
*
* Notes:
* - When 'position' is used, it referes to the position of the node in the
* list, not the node's offset. E.g. the node with position == 1 is the
* first node in the list.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#include <stdlib.h>
#include "lib/data-types.h"
#include "linked-list.h"
// local macros (undefined later)
#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type))
#define _list_t linked_list_t
#define _node_t linked_list_node_t
#define _data_t LINKED_LIST_DATA_TYPE
/*
* new()
*
* Returns
* - success: a pointer to a new linked list
* - failure: NULL
*/
_list_t * linked_list_new(void) {
_NEW_POINTER(_list_t, list);
if (!list) return NULL;
list->head = NULL;
list->tail = NULL;
list->length = 0;
return list;
}
/*
* insert()
*
* Arguments
* - index: the index of the position that the new node will occupy. if index
* is negative, we set index += length (as in Python). so:
* - 0 => the first node in the list
* - 1 => the second node in the list
* - -1 => the last node in the list
* - -2 => the second from the last node in the list
* - '0' is undefined (returns 'failure')
* - out of bounds positions wrap around, so:
* - [length] => 0 => the first node in the list
* - -[length+1] => -1 => the last node in the list
*
* Returns
* - success: the pointer to the list that was passed
* - failure: NULL
*/
_list_t * linked_list_insert(_list_t * list, _data_t data, int index) {
_NEW_POINTER(_node_t, node);
if (!node) return NULL;
node->data = data;
if (list->length == 0) {
// insert as only node (no others exist yet)
list->head = node;
list->tail = node;
node->next = NULL;
} else {
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
if (index == 0) {
// insert as first node
node->next = list->head;
list->head = node;
} else if (index == list->length-1) {
// insert as last node
list->tail->next = node;
list->tail = node;
node->next = NULL;
} else {
// insert as other node
_node_t * previous = list->head;
for (int i=1; i<index; i++)
previous = previous->next;
node->next = previous->next;
previous->next = node;
}
}
list->length++;
return list;
}
/*
* peek()
*
* Arguments
* - index: [see 'insert()']
*
* Returns
* - success: the data field of the node at the given index
* - failure: (_data_t) 0
*/
_data_t linked_list_peek(_list_t * list, int index) {
// if: no nodes exist
if (list->length == 0)
return (_data_t) 0;
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
// if: last node
if (index == list->length-1)
return list->tail->data;
// else
_node_t * node = list->head;
for (int i=0; i<index; i++)
node = node->next;
return node->data;
}
/*
* pop()
*
* Arguments
* - index: [see 'insert()']
*
* Returns
* - success: the data field of the node at the given index
* - failure: (_data_t) 0
*/
_data_t linked_list_pop(_list_t * list, int index) {
// if: no nodes exist
if (list->length == 0)
return (_data_t) 0;
// find positive, in-bounds index
index = index % list->length;
if (index < 0)
index += list->length;
// vars
_data_t data;
_node_t * node;
if (index == 0) {
// pop first node
data = list->head->data;
node = list->head;
list->head = node->next;
} else {
// find the index-1'th node
_node_t * previous;
previous = list->head;
for (int i=1; i<index; i++)
previous = previous->next;
// if: last node
if (index == list->length-1)
list->tail = previous;
// pop the node at index
data = previous->next->data;
node = previous->next;
previous->next = node->next;
}
free(node);
list->length--;
return data;
}
/*
* find()
* TODO
*/
// TODO
/*
* copy()
*
* Returns
* - success: a new pointer to a (deep) copy of the list that was passed
* - failure: NULL
*/
_list_t * linked_list_copy(_list_t * list) {
_NEW_POINTER(_list_t, copy);
if (!copy) return NULL;
bool error;
_node_t * node = list->head;
for (uint8_t i=0; i<(list->length); i++) {
error = ! linked_list_insert(copy, node->data, -1);
if (error) {
linked_list_free(copy);
return NULL;
}
node = node->next;
}
return copy;
}
/*
* free()
* - Free the memory allocated to all the nodes, then free the memory allocated
* to the list.
*/
void linked_list_free(_list_t * list) {
_node_t * node;
for (uint8_t i=0; i<(list->length); i++) {
node = list->head;
list->head = list->head->next;
free(node);
}
free(list);
}
// local macros (undefined here)
#undef _NEW_POINTER
#undef _list_t
#undef _node_t
#undef _data_t

View File

@ -0,0 +1,55 @@
/* ----------------------------------------------------------------------------
* linked list : exports
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef LINKED_LIST_h
#define LINKED_LIST_h
#include "lib/data-types.h"
// default data type for the list
#ifndef LINKED_LIST_DATA_TYPE
#define LINKED_LIST_DATA_TYPE uint8_t
#endif
// structs
struct linked_list_node {
LINKED_LIST_DATA_TYPE data;
struct linked_list_node * next;
};
struct linked_list {
uint8_t length;
struct linked_list_node * head;
struct linked_list_node * tail;
};
// typedefs
typedef struct linked_list linked_list_t;
typedef struct linked_list_node linked_list_node_t;
// functions
#define _list_t linked_list_t
#define _data_t LINKED_LIST_DATA_TYPE
// TODO
_list_t * linked_list_new (void);
_list_t * linked_list_add_head (_list_t * list, _data_t data);
_list_t * linked_list_add_tail (_list_t * list, _data_t data);
_data_t linked_list_pop_head (_list_t * list);
_data_t linked_list_pop_tail (_list_t * list);
_data_t linked_list_read (_list_t * list, uint8_t position);
_list_t * linked_list_copy (_list_t * list);
void linked_list_free (_list_t * list);
// /TODO
#undef _list_t
#undef _data_t
#endif

View File

@ -0,0 +1,28 @@
/* ----------------------------------------------------------------------------
* key functions: private
*
* Things to be used only by keyfunctions. Exported any layouts would like to
* use these functions to help define their own.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef KEY_FUNCTIONS_h_PRIVATE
#define KEY_FUNCTIONS_h_PRIVATE
void _press_release(bool pressed, uint8_t keycode);
void _layer_set_current(
uint8_t value,
uint8_t * current_layer,
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS] );
void _layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] );
bool _is_pressed(uint8_t keycode);
#endif

View File

@ -11,108 +11,500 @@
* ------------------------------------------------------------------------- */
#include <avr/interrupt.h>
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types.h"
#include "lib/usb/usage-page/keyboard.h"
#include "keyboard.h"
#include "key-functions.h"
#include "key-functions--private.h"
// ----------------------------------------------------------------------------
// public functions (not for keys)
// ----------------------------------------------------------------------------
#if 0 // not being used right now
static uint8_t _inc_current_layer(uint8_t * current_layer) {
if (*current_layer < (KB_LAYERS-1))
(*current_layer)++;
else
return 1; // error: can't increase
/*
* Exec key
* - Execute the keypress or keyrelease function (if it exists) of the key at
* the current possition. Pass the keycode at the current position, and pass
* all other arguments as received
*/
void _kbfun_exec_key( KBFUN_FUNCTION_ARGS ) {
kbfun_funptr_t key_function =
( (pressed_)
? kb_layout_press_get(layer_, *row_, *col_)
: kb_layout_release_get(layer_, *row_, *col_) );
return 0; // success
if (key_function)
(*key_function)(
pressed_,
kb_layout_get(layer_, *row_, *col_),
layer_,
row_,
col_,
current_layer_,
current_layers_,
pressed_layers_ );
}
static uint8_t _dec_current_layer(uint8_t * current_layer) {
if (*current_layer > 0)
(*current_layer)--;
else
return 1; // error: can't decrease
return 0; // success
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
/*
* Generate a normal keypress or keyrelease
*
* Arguments
* - keycode: the keycode to use
* - pressed: whether to generate a keypress (true) or keyrelease (false)
*
* Note
* - Because of the way USB does things, what this actually does is either add
* or remove 'keycode' from the list of currently pressed keys, to be sent at
* the end of the current cycle (see main.c)
*/
void _press_release(bool pressed, uint8_t keycode) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: (pressed)
? (keyboard_modifier_keys |= (1<<0))
: (keyboard_modifier_keys &= ~(1<<0));
return;
case KEY_LeftShift: (pressed)
? (keyboard_modifier_keys |= (1<<1))
: (keyboard_modifier_keys &= ~(1<<1));
return;
case KEY_LeftAlt: (pressed)
? (keyboard_modifier_keys |= (1<<2))
: (keyboard_modifier_keys &= ~(1<<2));
return;
case KEY_LeftGUI: (pressed)
? (keyboard_modifier_keys |= (1<<3))
: (keyboard_modifier_keys &= ~(1<<3));
return;
case KEY_RightControl: (pressed)
? (keyboard_modifier_keys |= (1<<4))
: (keyboard_modifier_keys &= ~(1<<4));
return;
case KEY_RightShift: (pressed)
? (keyboard_modifier_keys |= (1<<5))
: (keyboard_modifier_keys &= ~(1<<5));
return;
case KEY_RightAlt: (pressed)
? (keyboard_modifier_keys |= (1<<6))
: (keyboard_modifier_keys &= ~(1<<6));
return;
case KEY_RightGUI: (pressed)
? (keyboard_modifier_keys |= (1<<7))
: (keyboard_modifier_keys &= ~(1<<7));
return;
}
// all others
for (uint8_t i=0; i<6; i++) {
if (pressed) {
if (keyboard_keys[i] == 0) {
keyboard_keys[i] = keycode;
return;
}
} else {
if (keyboard_keys[i] == keycode) {
keyboard_keys[i] = 0;
return;
}
}
}
}
/*
* Set current layer
* - Sets any keys currently set to the overall current layer to the new layer,
* and then sets the overall current layer
*
* Arguments
* - layer: the new layer value
* - current_layer: (a pointer to) the overall current layer (see main.c)
* - current_layers: (a pointer to a matrix of) the current layer for each key
* (see main.c and lib/key-functions.h)
*
* Note
* - Leaving all non-current layer values alone allows changing layers while
* maintaining a possibly enabled layer mask (as might be used to implement
* firmware enabled numlock)
*/
void _layer_set_current(
uint8_t layer,
uint8_t * current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
// if a key is set to a non-current layer, leave it
if ((*current_layers)[row][col] == *current_layer)
(*current_layers)[row][col] = layer;
(*current_layer) = layer;
}
/*
* Set layer mask
* - Sets the specified key positions to the specified layer
*/
void _layer_set_mask(
uint8_t layer,
bool positions[KB_ROWS][KB_COLUMNS],
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
// don't switch to out-of-bounds layers
if ( layer < 0 || layer >= KB_LAYERS )
return;
for (uint8_t row=0; row<KB_ROWS; row++)
for (uint8_t col=0; col<KB_COLUMNS; col++)
if (positions[row][col])
(*current_layers)[row][col] = layer;
}
/*
* Is the given keycode pressed?
*/
bool _is_pressed(uint8_t keycode) {
// modifier keys
switch (keycode) {
case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0))
return true;
case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1))
return true;
case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2))
return true;
case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3))
return true;
case KEY_RightControl: if (keyboard_modifier_keys & (1<<4))
return true;
case KEY_RightShift: if (keyboard_modifier_keys & (1<<5))
return true;
case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6))
return true;
case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7))
return true;
}
// all others
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == keycode)
return true;
return false;
}
// ----------------------------------------------------------------------------
// public functions
// ----------------------------------------------------------------------------
/*
* Press|Release
* - Generate a normal keypress or keyrelease
*/
void kbfun_press_release( KBFUN_FUNCTION_ARGS ) {
_press_release(pressed_, keycode_);
}
/*
* Toggle
* - Toggle the key pressed or unpressed
*/
void kbfun_toggle( KBFUN_FUNCTION_ARGS ) {
if (_is_pressed(keycode_))
_press_release(false, keycode_);
else
_press_release(true, keycode_);
}
/*
* Increase layer
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
}
/*
* Decrease layer
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys)
*/
void kbfun_layer_dec( KBFUN_FUNCTION_ARGS ) {
_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
}
/*
* Increase layer, Execute key
* - Increment the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_dec_exec()`
*/
void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_layer_set_current(
(*current_layer_) + keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
_kbfun_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Decrease layer, Execute key
* - Decrement the current layer by the value specified in the keymap (for all
* non-masked keys), and execute (usually press|release) the key in the same
* position on that new layer
*
* Note
* - Meant to be paired with `kbfun_layer_inc_exec()`
*/
void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
// switch layers
_layer_set_current(
(*current_layer_) - keycode_,
current_layer_,
current_layers_ );
// exececute second key (in the same position)
// - `layer_+keycode_` will be constant (under normal circumstances)
// between the press and release
_kbfun_exec_key(
pressed_, 0, layer_+keycode_,
row_, col_, current_layer_,
current_layers_, pressed_layers_ );
}
/*
* Two keys => capslock
* - When assigned to two keys (e.g. the physical left and right shift keys)
* (in both the press and release matrices), pressing and holding down one of
* the keys will make the second key toggle capslock
*
* Note
* - If either of the shifts are pressed when the second key is pressed, they
* wil be released so that capslock will register properly when pressed.
* Capslock will then be pressed and released, and the original state of the
* shifts will be restored
*/
void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
static uint8_t keys_pressed;
static bool lshift_pressed;
static bool rshift_pressed;
if (!pressed_) keys_pressed--;
// take care of the key that was actually pressed
_press_release(pressed_, keycode_);
// take care of capslock (only on the press of the 2nd key)
if (keys_pressed == 1 && pressed_) {
// save the state of left and right shift
lshift_pressed = _is_pressed(KEY_LeftShift);
rshift_pressed = _is_pressed(KEY_RightShift);
// disable both
_press_release(false, KEY_LeftShift);
_press_release(false, KEY_RightShift);
// press capslock, then release it
_press_release(true, KEY_CapsLock);
usb_keyboard_send();
_press_release(false, KEY_CapsLock);
usb_keyboard_send();
// restore the state of left and right shift
if (lshift_pressed)
_press_release(true, KEY_LeftShift);
if (rshift_pressed)
_press_release(true, KEY_RightShift);
}
if (pressed_) keys_pressed++;
}
// TODO: maybe the numpad functions (and other logical sets of functions?) need
// to be in (a) seaparate file(s).
/* ----------------------------------------------------------------------------
* Numpad functions
* - Functions to implement an embedded numpad
*
* Notes
* - The numpad is toggled by shifting (without changing the overall current
* layer) the layer of the keys specified in this function to the value
* specified in the keymap
* - When the numpad is toggled, the numlock is set to on (for active) or off
* (for inactive) as well
* - All these functions cooperate, but if more than one layer mask of this
* type is used (by a different set of functions) at the same time, the
* second will override the first, and any keys covered by both will be reset
* to the overall current layer when either is released (even if the other is
* still pressed)
* ------------------------------------------------------------------------- */
// prefix function (undefined later)
// - to keep these names reasonable in this block, and obviously not global
// outside it
// - 'L' is for 'local'
#define L(name) _kbfun_layermask_numpad__##name
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// vars
static bool L(numpad_activated) = false;
static bool L(layer_mask)[KB_ROWS][KB_COLUMNS] =
MATRIX_LAYER(
// unused
0,
// left hand
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0,
0, 0,
0, 0, 0,
// right hand
0, 0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0,
0, 0,
0, 0, 0 );
// functions
static inline void L(toggle_numlock)(void) {
_press_release(true, KEYPAD_NumLock_Clear);
usb_keyboard_send();
_press_release(false, KEYPAD_NumLock_Clear);
usb_keyboard_send();
}
static void L(toggle_numpad)(
uint8_t numpad_layer,
uint8_t current_layer,
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
if (L(numpad_activated)) {
// deactivate numpad
_layer_set_mask(current_layer, L(layer_mask), current_layers);
L(numpad_activated) = false;
// if: numlock on
if (keyboard_leds & (1<<0))
L(toggle_numlock)();
} else {
// activate numpad
_layer_set_mask(numpad_layer, L(layer_mask), current_layers);
L(numpad_activated) = true;
// if: numlock off
if (!(keyboard_leds & (1<<0)))
L(toggle_numlock)();
}
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
/*
* Numpad toggle
* - Toggles the numpad and sets numlock on (for active) or off (for inactive)
* with it, if it's not already in that state
*/
void kbfun_layermask_numpad_toggle( KBFUN_FUNCTION_ARGS ) {
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad on
* - Set the numpad on (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_on( KBFUN_FUNCTION_ARGS ) {
if (!L(numpad_activated))
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
/*
* Numpad off
* - Set the numpad off (along with numlock, if it's not already)
*/
void kbfun_layermask_numpad_off( KBFUN_FUNCTION_ARGS ) {
if (L(numpad_activated))
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
}
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
// prefix function (undefined here)
#undef L
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */
// ----------------------------------------------------------------------------
// public functions (device specific)
// ----------------------------------------------------------------------------
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {
// from PJRC (slightly modified)
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
#if MAKEFILE_BOARD == teensy-2-0
// --- for all Teensy boards
cli();
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1;
USBCON = (1<<FRZCLK); // disable USB
UCSR1B = 0;
_delay_ms(5);
// --- Teensy 2.0 specific
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
asm volatile("jmp 0x7E00");
#endif
// ----------------------------------------------------------------------------
void kbfun_press(
uint8_t keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col ) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: keyboard_modifier_keys |= (1<<0);
return;
case KEY_LeftShift: keyboard_modifier_keys |= (1<<1);
return;
case KEY_LeftAlt: keyboard_modifier_keys |= (1<<2);
return;
case KEY_LeftGUI: keyboard_modifier_keys |= (1<<3);
return;
case KEY_RightControl: keyboard_modifier_keys |= (1<<4);
return;
case KEY_RightShift: keyboard_modifier_keys |= (1<<5);
return;
case KEY_RightAlt: keyboard_modifier_keys |= (1<<6);
return;
case KEY_RightGUI: keyboard_modifier_keys |= (1<<7);
return;
}
// all others
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == 0) {
keyboard_keys[i] = keycode;
break;
}
}
void kbfun_release(
uint8_t keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col ) {
// no-op
if (keycode == 0)
return;
// modifier keys
switch (keycode) {
case KEY_LeftControl: keyboard_modifier_keys &= ~(1<<0);
return;
case KEY_LeftShift: keyboard_modifier_keys &= ~(1<<1);
return;
case KEY_LeftAlt: keyboard_modifier_keys &= ~(1<<2);
return;
case KEY_LeftGUI: keyboard_modifier_keys &= ~(1<<3);
return;
case KEY_RightControl: keyboard_modifier_keys &= ~(1<<4);
return;
case KEY_RightShift: keyboard_modifier_keys &= ~(1<<5);
return;
case KEY_RightAlt: keyboard_modifier_keys &= ~(1<<6);
return;
case KEY_RightGUI: keyboard_modifier_keys &= ~(1<<7);
return;
}
// all others
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == keycode) {
keyboard_keys[i] = 0;
break;
}
// else, function does nothing
}

View File

@ -12,16 +12,53 @@
#include "lib/data-types.h"
typedef void (*kbfun_funptr_t)(
uint8_t, uint8_t *,
uint8_t *, uint8_t * );
// --------------------------------------------------------------------
// include the appropriate 'matrix.h'
// -------
// we're not simply including 'keyboard.h' here because this header is
// meant to be included by 'keyboard/layout/*.c', which is indirectly
// included by 'keyboard.h'; and that would lead to a circular include,
// which gcc might (depending on the order of include statements it
// encounters) deal with by processing this file before 'matrix.h',
// which would give us undefined macros here
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD/matrix.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc
// --------------------------------------------------------------------
void kbfun_press(
uint8_t keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
void kbfun_release(
uint8_t keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
#define KBFUN_FUNCTION_ARGS \
bool pressed_, \
uint8_t keycode_, \
uint8_t layer_, \
uint8_t * row_, \
uint8_t * col_, \
uint8_t * current_layer_, \
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS], \
uint8_t (*pressed_layers_)[KB_ROWS][KB_COLUMNS]
typedef void (*kbfun_funptr_t)( KBFUN_FUNCTION_ARGS );
void _kbfun_exec_key ( KBFUN_FUNCTION_ARGS );
void kbfun_press_release (KBFUN_FUNCTION_ARGS);
void kbfun_toggle (KBFUN_FUNCTION_ARGS);
void kbfun_layer_inc (KBFUN_FUNCTION_ARGS);
void kbfun_layer_dec (KBFUN_FUNCTION_ARGS);
void kbfun_layer_inc_exec (KBFUN_FUNCTION_ARGS);
void kbfun_layer_dec_exec (KBFUN_FUNCTION_ARGS);
void kbfun_2_keys_capslock_press_release (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_toggle (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_on (KBFUN_FUNCTION_ARGS);
void kbfun_layermask_numpad_off (KBFUN_FUNCTION_ARGS);
void kbfun_jump_to_bootloader (KBFUN_FUNCTION_ARGS);
#endif

View File

@ -38,6 +38,14 @@
// - spec sec 9.4.11 (Standard Device Requests / Synch Frame) (pg 260)
// TODO
// - read the hid usage tables .pdf
// - read the hid device class definition .pdf
// DONE
// - read the hid usage tables .pdf
// - i think this is more for reference and implementation than
// understanding. i've copied the relevant (i think) tables ones into
// headers. the unicode usage page, i'll have to look into more later: i'm
// not sure if it can be used with keyboards. if so though, i'll have to
// look on the unicode website, or elsewhere, coz this .pdf doesn't list
// anything about them out, it just references the unicode spec.

View File

@ -11,6 +11,7 @@
#include <util/delay.h>
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types.h"
#include "lib/key-functions.h"
#include "keyboard.h"
@ -27,7 +28,12 @@ int main(void) {
kb_led_state_ready();
for (;;) {
static uint8_t current_layer = 0;
// the overall current layer
static uint8_t current_layer;
// the current layer for each key
static uint8_t current_layers[KB_ROWS][KB_COLUMNS];
// the layer each key was on when it was last pressed
static uint8_t pressed_layers[KB_ROWS][KB_COLUMNS];
// swap `kb_is_pressed` and `kb_was_pressed`, then update
bool (*temp)[KB_ROWS][KB_COLUMNS] = kb_was_pressed;
@ -36,41 +42,46 @@ int main(void) {
kb_update_matrix(*kb_is_pressed);
// call the appropriate function for each key, then send the usb report
// if necessary
// - everything else is the key function's responsibility; see the
// keyboard layout file ("keyboard/ergodox/layout/*.c") for which key
// is assigned which function (per layer), and "lib/key-functions.c"
// for their definitions
// this loop is responsible to
// - "execute" keys when they change state (call `_kbfun_exec_key()`,
// which will call the appropriate function with the appropriate
// keycode argument from the kb_layout* matrices)
// - keep track of which layers the keys were on when they were pressed
// (so they can be released using the function from that layer)
//
// note
// - everything else is the key function's responsibility
// - see the keyboard layout file ("keyboard/ergodox/layout/*.c") for
// which key is assigned which function (per layer)
// - see "lib/key-functions.c" for the function definitions
// - anything passed to the key function by reference is fair game for
// that function to modify
for (uint8_t row=0; row<KB_ROWS; row++) {
for (uint8_t col=0; col<KB_COLUMNS; col++) {
bool is_pressed = (*kb_is_pressed)[row][col];
bool was_pressed = (*kb_was_pressed)[row][col];
if (is_pressed != was_pressed) {
if (is_pressed) {
kbfun_funptr_t press_function =
kb_layout_press_get(current_layer, row, col);
if (press_function) {
(*press_function)(
kb_layout_get(current_layer, row, col),
&current_layer, &row, &col );
}
} else {
kbfun_funptr_t release_function =
kb_layout_release_get(current_layer, row, col);
if (release_function) {
(*release_function)(
kb_layout_get(current_layer, row, col),
&current_layer, &row, &col );
}
}
usb_keyboard_send();
_delay_ms(KB_DEBOUNCE_TIME);
if (is_pressed != was_pressed) {
uint8_t layer = ( (is_pressed)
? current_layers[row][col]
: pressed_layers[row][col] );
if (is_pressed)
pressed_layers[row][col] = layer;
_kbfun_exec_key(
is_pressed, 0, layer,
&row, &col, &current_layer,
&current_layers, &pressed_layers );
}
}
}
// send the USB report (even if nothing's changed)
usb_keyboard_send();
_delay_ms(KB_DEBOUNCE_TIME);
// update LEDs
if (keyboard_leds & (1<<0)) { kb_led_num_on(); }
else { kb_led_num_off(); }

View File

@ -1,5 +1,5 @@
# -----------------------------------------------------------------------------
# makefile for the ergoDOX project
# makefile for the ergoDOX firmware
#
# - .h file dependencies are automatically generated
#
@ -13,18 +13,18 @@
# -----------------------------------------------------------------------------
TARGET = firmware # the name we want for our program binary
FORMAT = ihex # the program binary's format
KEYBOARD = ergodox # keyboard model; see "src/keyboard" for what's available
LAYOUT = qwerty # keyboard layout; see "src/keyboard/*/layout" for what's
# available
TARGET := firmware # the name we want for our program binary
FORMAT := ihex # the program binary's format
KEYBOARD := ergodox # keyboard model; see "src/keyboard" for what's available
LAYOUT := qwerty # keyboard layout; see "src/keyboard/*/layout" for what's
# available
MCU = atmega32u4 # processor type (for teensy 2.0); must match real life
BOARD = teensy-2-0 # see the libraries you're using for what's available
F_CPU = 16000000 # processor speed, in Hz
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
BOARD := teensy-2-0 # see the libraries you're using for what's available
F_CPU := 16000000 # processor speed, in Hz
# firmware stuff
SRC = $(wildcard *.c)
SRC := $(wildcard *.c)
# keyboard and layout stuff
# --- remove whitespace from vars
KEYBOARD := $(strip $(KEYBOARD))
@ -48,7 +48,7 @@ SRC += $(wildcard lib-other/*/*/*.c)
OBJ = $(SRC:%.c=%.o)
CFLAGS = -mmcu=$(MCU) # processor type (teensy 2.0); must match real
CFLAGS := -mmcu=$(MCU) # processor type (teensy 2.0); must match real
# life
CFLAGS += -DF_CPU=$(F_CPU) # processor frequency; must match initialization
# in source
@ -76,21 +76,23 @@ CFLAGS += -fdata-sections # / section in the output file if the
# unused code.
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
LDFLAGS = -Wl,--relax # for some linker optimizations
LDFLAGS := -Wl,-Map=$(strip $(TARGET)).map,--cref # generate a link map, with
# a cross reference table
LDFLAGS += -Wl,--relax # for some linker optimizations
LDFLAGS += -Wl,--gc-sections # discard unused functions and data
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
GENDEPFLAGS += -MMD -MP -MF $@.dep # generate dependency files
CC = avr-gcc
OBJCOPY = avr-objcopy
SIZE = avr-size
CC := avr-gcc
OBJCOPY := avr-objcopy
SIZE := avr-size
# remove whitespace from some of the variables
TARGET := $(strip $(TARGET))
FORMAT := $(strip $(FORMAT))
TARGET := $(strip $(TARGET))
FORMAT := $(strip $(FORMAT))
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
@ -120,7 +122,7 @@ all: $(TARGET).hex $(TARGET).eep
clean:
@echo
@echo --- cleaning ---
cd .. ; git clean -dX # remove ignored files and directories
git clean -dX # remove ignored files and directories
# -----------------------------------------------------------------------------