very much in progress, rewriting in C

- decided to see if i could keep it in just C... i think that'll be
  easier, long run.  it does need a rewrite though, in a few respects

- this mid-stride checkin is because i'm leaving to visit santa barbara
  tomorrow (just for the day) and i want to make sure 1) my code is
  backed up, and 2) my code is available in case i wish to show it to
  anyone (lol :) since i'm not bringing my laptop)
partial-rewrite
Ben Blazak 2012-12-26 21:25:17 -08:00
parent 88111197c3
commit f6aa18498a
17 changed files with 4163 additions and 33 deletions

1
TODO
View File

@ -1,2 +1,3 @@
- rewrite/rework 'references.md'
- write 'firmware/coding-conventions.md'

View File

@ -1,3 +1,6 @@
# References
## Electronics Stuff
* [Resistor Color Codes]
@ -117,6 +120,13 @@
Useful overview of C++ stuff. I'd been away from it for long enough that I
needed a review.
* [Haiku : Coding Guidelines]
(https://www.haiku-os.org/development/coding-guidelines)
* [C++ Language Tutorial]
(http://www.cplusplus.com/doc/tutorial/)
(on <http://www.cplusplus.com/>)
### For the AVR
* [AVR Newbie guide]
@ -468,6 +478,8 @@
see the link; as that tool improves it will hopefully become much better),
but it works and I like it :) .
### Web Stuff
* [Raphaël—JavaScript Library]
(http://raphaeljs.com)
A library for working with SVG (and VML, on IE I think) graphics - drawing
@ -475,11 +487,55 @@
* also [on github] (https://github.com/DmitryBaranovskiy/raphael/)
* [An Introduction to the Raphaël JS Library]
(http://net.tutsplus.com/tutorials/javascript-ajax/an-introduction-to-the-raphael-js-library/)
A good tutorial, it looks like.
* [Lively Kernel]
(http://www.lively-kernel.org)
I read about this a while ago, and just remembered it again while thinking
about how I would write a keymap making thing in javascript. Not sure how
good it'd be for that specifically, but the concept is just so **awesome***!
### Other Random Stuff
* [Tutorial: Metacompilers Part 1]
(http://www.bayfronttechnologies.com/mc_tutorial.html)
Probably doesn't have anything to do with microprocessors *or* web
development (at least at the moment)... but once again, the concept is really
awesome :) . I included it here because, as I was writing in C, the thought
"I could write a script to generate this code in Python *so* easily..." went
through my head quite often.
* [Towards Moore's Law Software: Part 1 of 3]
(http://www.moserware.com/2008/04/towards-moores-law-software-part-1-of-3.html)
Great article on programming in general, and where it might be going in the
future. Along the same lines as the Metacompilers tutorial, in that it talks
about using domain specific languages. Also talks about different
programming paradigms that are being explored right now.
* [What are the available interactive languages that run in tiny memory?]
(http://stackoverflow.com/questions/1082751/what-are-the-available-interactive-languages-that-run-in-tiny-memory)
(on <http://stackoverflow.com/>)
Didn't really see anything other than ooc and FORTH that might work for an
application like this firmware, so I decided I may as well just subset C++
like everyone else, and use that. Shouldn't be too bad.
* [ooc]
(http://ooc-lang.org)
: a programming language targeting C99
This project doesn't seem like it's been very active in the last year or
so... not that it looks dead (and, acutally, I didn't check the IRC channel
or forums or anything, so I could be completely wrong), just not very active.
And the documentation's fairly incomplete (which is sad, it looks like a
really cool language :) ). If C++ weren't available on the AVR, I'd
definitly be looking into using it anyway.
-------------------------------------------------------------------------------
Copyright &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (MIT) (see "license.md")
Released under The MIT License (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

View File

@ -0,0 +1,25 @@
# Coding Conventions
## Comments
`/** ... */` comments are to be written in YAML, so they can be processed by
external tools to generate documentation, and for other purposes.
## "Namespace" prefixes
"Namespace" prefixes are prepended to variables and macros (in lower and upper
case, respectively), sometimes hierarchically, separated by `__`. I call them
what I do because this is somewhat similar to using `::` for namespace
separation as in C++.
* `KB`: from `firmware/keyboard/...`
* `MAKE`: passed to the compiler by `make` (i.e. a global option)
-------------------------------------------------------------------------------
Copyright &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

176
firmware/keyboard.h Normal file
View File

@ -0,0 +1,176 @@
/* ----------------------------------------------------------------------------
* keyboard interface
* ----------------------------------------------------------------------------
* 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 ERGODOX_FIRMWARE__FIRMWARE__KEYBOARD__H
#define ERGODOX_FIRMWARE__FIRMWARE__KEYBOARD__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
// ----------------------------------------------------------------------------
// controller
int8_t kb__init (void);
int8_t kb__update_matrix (bool matrix[MAKE__KB_ROWS][MAKE__KB_COLUMNS]);
// LED
void kb__led__on (int8_t led);
void kb__led__off (int8_t led);
void kb__led__set (int8_t led, uint8_t n);
void kb__led__set_percent (int8_t led, float n);
// -------
void kb__led__all_on (void);
void kb__led__all_off (void);
void kb__led__all_set (uint8_t n);
void kb__led__all_set_percent (float n);
// -------
void kb__led_state__power_on (void);
void kb__led_state__ready (void);
void kb__led_delay__usb_init (void);
// -------
void kb__led__set_logical(char led, bool on);
// layout
// TODO
// ----------------------------------------------------------------------------
// documentation
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// controller -----------------------------------------------------------------
/**
* name: kb__init
* description: Initialize the keyboard
* notes:
* - Should be called exactly once by `main()` before entering the run loop.
*/
/**
* name: kb__update_matrix
* description: Update the given matrix to the current state of the keyboard
* arguments:
* bool matrix[MAKE__KB_ROWS][MAKE__KB_COLUMNS]:
* a pointer to the matrix to update
*/
// ----------------------------------------------------------------------------
// LED ------------------------------------------------------------------------
/**
* &led__int8_t_led:
* The number of the LED to set. Should an integer between 1 and 5
* inclusive; behavior is undefined otherwise.
*
* notes:
* - For US keyboards, likely only LEDs 1 through 3 will be present. But the
* function should handle 4 through 5 gracefully anyway.
*
* &led__uint8_t_n:
* The brightness at which to set the LED. All values are legal. Larger
* values mean a brighter LED.
*
* &led__float_n:
* The percent of the highest possible brightness at which to set the LED.
* Should be a float between 0 and 1 inclusive; behavior is undefined
* otherwise.
*/
/**
* name: kb__led__on
* description: Set the given LED 'on'.
* arguments:
* int8_t led: *led__int8_t_led
*/
/**
* name: kb__led__off
* description: Set the given LED 'off'.
* arguments:
* int8_t led: *led__int8_t_led
*/
/**
* name: kb__led__set
* description: Set the given LED's brightness (to an absolute value).
* arguments:
* int8_t led: *led__int8_t_led
* uint8_t n: *led__uint8_t_n
*/
/**
* name: kb__led__set_percent
* description: Set the given LED's brightness (by percent).
* arguments:
* int8_t led: *led__int8_t_led
* float n: *led__float_n
*/
/**
* name: kb__led__all_on
* description: Set all the LEDs 'on'
*/
/**
* name: kb__led__all_off
* description: Set all the LEDs 'off'
*/
/**
* name: kb__led__all_set
* description: Set all the LEDs brightness (to an absolute value).
* arguments:
* uint8_t n: *led__uint8_t_n
*/
/**
* name: kb__led__all_set_percent
* description: Set all the LEDs brightness (by percent).
* arguments:
* float n: *led__float_n
*/
/**
* name: kb__led_state__power_on
* description:
* Set the LEDs to the state that indicates the keyboard just powered on.
*/
/**
* name: kb__led_state__ready
* description:
* Set the LEDs to the state that indicates the keyboard is ready to receive
* keystrokes.
*/
/**
* name: kb__led_delay__usb_init
* description:
* Delay for a total of ~1 second, to allow the host to load drivers and
* such.
*/
/**
* name: kb__led__set_logical
* description:
* Set LEDs on or off based on their meaning (e.g. 'numlock', 'capslock').
* arguments:
* char led:
* N: numlock
* C: capslock
* S: scroll lock
* O: compose
* K: kana
* bool on:
* 1: set the LED on
* 0: set the LED off
*/
// ----------------------------------------------------------------------------
// layout ---------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__FIRMWARE__KEYBOARD__H

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -0,0 +1,148 @@
# Documentation : MCP23018
## Pinout and Pin assignments
* `+` indicates connected pin
* `o` indicates unconnected pin
* `=` is used to list other things the pin is connected to
* `-`s inserted between some of the pin functions for readability
### MCP23018
Vss(GND) +01---.---28+ NC
NC +02 27+ GPA7
GPB0 +03 26+ GPA6
GPB1 +04 25+ GPA5
GPB2 +05 24+ GPA4
GPB3 +06 23+ GPA3
GPB4 +07 22+ GPA2
GPB5 +08 21+ GPA1
GPB6 +09 20+ GPA0
GPB7 +10 19+ INTA
Vdd(Vcc) +11 18+ INTB
SCL +12 17+ NC
SDA +13 16+ RESET
NC +14-------15+ ADDR
### MCP32018 Pin Assignments
power_negative Vss(GND) +01---.---28o NC
NC o02 27o GPA7
row_5 GPB0 +03 26+ GPA6 column_6
row_4 GPB1 +04 25+ GPA5 column_5
row_3 GPB2 +05 24+ GPA4 column_4
row_2 GPB3 +06 23+ GPA3 column_3
row_1 GPB4 +07 22+ GPA2 column_2
row_0 GPB5 +08 21+ GPA1 column_1
GPB6 o09 20+ GPA0 column_0
GPB7 o10 19o INTA
power_positive Vdd(Vcc) +11 18o INTB
I2C SCL +12 17o NC
I2C SDA +13 16+ RESET = Vdd(Vcc) (see note)
NC o14-------15+ ADDR = Vss(GND) (see note)
* notes:
* Row and column assignments are to matrix positions, which may or may
or may not correspond to the physical position of the key: e.g. the key
where `row_4` and `column_2` 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
indicating read/write)
* RESET (pin16) must be externally biased. Since we're not going to
trigger it ourselves, we can tie it high.
* This is not noted in the I2C Pinout Description section of the
MCP23018 datasheet, but it's true (empirically), and it is noted in
the SPI Pinout Description section, and in the MCP23017 datasheet.
* I'm not the first person who's failed to notice ;)
* <http://davidn.org/wp/?p=89>
* <http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1293498979>
## Notes about Registers
register address function (for all bits)
-------- ------- -----------------------
IODIRA 0x00 \ 1: set corresponding pin as input
IODIRB 0x01 / 0: set ................. as output
GPPUA 0x0C \ 1: set corresponding pin internal pull-up on
GPPUB 0x0D / 0: set .......................... pull-up off
GPIOA 0x12 \ read: returns the value on the port
GPIOB 0x13 / write: modifies the OLAT register
OLATA 0x14 \ read: returns the value of this register
OLATB 0x15 / write: modifies the output latches that control the
pins configured as output
* IOCON register (see datasheet section 1.6, table 1-5, register 1-8)
* BANK: bit 7; read/write; default = 0
* 1: The registers associated with each port are separated into
different banks
* 0: The registers are in the same bank (addresses are sequential)
* SEQOP: bit 5; read/write; default = 0
* 1: Sequential operation disabled, address pointer does not increment
* 0: Sequential operation enabled, address pointer increments
* notes:
* All addresses given for IOCON.BANK = 0, since that's the default value of
the bit, and that's what we'll be using.
* Initially, we want either columns or rows (see [the options file]
(../../../options.mk)) set as hi-Z without pull-ups, and the other set of
pins set as input with pull-ups. During the update function, we'll cycle
through setting the first set low and checking each pin in the second
set.
* abbreviations:
* IODIR = I/O Direction Register
* IOCON = I/O Control Register
* GPPU = GPIO Pull-Up Resistor Register
* GPIO = General Purpose I/O Port Register
* OLAT = Output Latch Register
## I&sup2;C Device Protocol (see datasheet section 1.3, figure 1-1)
S : Start OP : Device opcode
SR : Restart ADDR : Device address
P : Stop Dout : Data out from MCP23018
W : Write Din : Data in to MCP23018
R : Read
S OP W ADDR ----> Din ... Din --> P
|
|--> SR OP R Dout ... Dout ---> P
|<--------------------------|
|
|--> SR OP W ADDR ... Din --> P
|
|--> P
S OP R ----> Dout ... Dout --> P
|
|--> SR OP R Dout ... Dout ---> P
|<--------------------------|
|
|--> SR OP W ADDR Din ... Din --> P
|
|--> P
Byte and Sequential Write
-------------------------
Byte : S OP W ADDR --> Din --> P
Sequential : S OP W ADDR --> Din ... Din --> P
Byte and Sequential Read
------------------------
Byte : S OP W ADDR --> SR OP R Dout --> P
Sequential : S OP W ADDR --> SR OP R Dout ... Dout --> P
* notes:
* We'll be using sequential mode (ICON.SEQOP = 0; default) (see datasheet
section 1.3.1).
-------------------------------------------------------------------------------
Copyright &copy; 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>

View File

@ -0,0 +1,148 @@
# Documentation : Teensy 2.0
## Pinout and Pin assignments
* `+` indicates connected pin
* `o` indicates unconnected pin
* `=` is used to list other things the pin is connected to
* `-`s inserted between some of the pin functions for readability
* `OC**` pins enclosed in parenthesis had lines over them in the pinout
### Teensy 2.0
GND +---.....---+ Vcc
SS PB0 + + PF0 ADC0
SCLK PB1 + + PF1 ADC1
MOSI PB2 + + PF4 ADC4
MISO PB3 + + + + PF5 ADC5
RTS OC1C OC0A --------- PB7 + PE6 AREF + PF6 ADC6
OC0B INT0 SCL PD0 + AIN0 + PF7 ADC7
INT1 SDA PD1 + INT6 + PB6 ADC13 OC1B OC4B
RXD1 ----------- INT2 --- PD2 + + PB5 ADC12 OC1A (OC4B)
TXD1 ----------- INT3 --- PD3 + + PB4 ADC11
OC3A (OC4A) -------- PC6 + + PD7 ADC10 T0 -- OC4D
ICP3 ----- OC4A --------- PC7 +-+-+-+-+-+-+ PD6 ADC9 T1 - (OC4D) onboardLED
CTS XCK1 PD5 --/ | | | \-- PD4 ADC8 ------------ ICP1
Vcc ------------------/ | \-------------- RST
GND --------------------/
### Teensy 2.0 Pin Assignments
power_negative GND +---.....---+ Vcc power_positive
column_7 PB0 + + PF0 row_5
column_8 PB1 + + PF1 row_4
column_9 PB2 + + PF4 row_3
column_A PB3 + o o + PF5 row_2
(OC1C) LED_3 PB7 + PE6 AREF + PF6 row_1
(SCL) I2C PD0 + + PF7 row_0
(SDA) I2C PD1 + + PB6 LED_2 (OC1B)
column_B PD2 + + PB5 LED_1 (OC1A)
column_C PD3 + + PB4 = Vcc
column_D PC6 + o PD7
PC7 o-o-o-o-o-o-+ PD6 onboardLED = GND
PD5 --/ | | | \-- PD4
Vcc ----/ | \---- RST
GND-------/
* notes:
* Row and column assignments are to matrix positions, which may or may
or may not correspond to the physical position of the key: e.g. the key
where `row_4` and `column_2` 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.
* LEDs are labeled using numbers (starting with '1') instead of letters
(starting with 'A') as on the the prototype PCB by Fredrik (late 2012).
* SCL and SDA (pins D(0) and D(1)) 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 for 400kHz I&sup2;C seems to be 2.2kΩ.
## Notes about Registers
### General I/O (see datasheet section 10.2.1)
DDRxn function PORTxn function
1 output 1 drive high
0 drive low
0 input 1 internal pull-up on
0 internal pull-up off
PINxn action function
write 1 toggles the value of PORTxn
read returns the logical value (1|0) of the pin
* notes:
* Unused pins should be set as input, with internal pullup enabled in order
to give them a defined level (see datasheet section 10.2.6).
* PD6 (the onboard LED) already has a defined level (low), so there's no
reason to set internal pull-up enabled on it. If we do, it will source
current to the LED, which is fine, but unnecessary.
* Initially, we want either columns or rows (see [the options file]
(../../../options.mk)) set as hi-Z without pull-ups, and the other set of
pins set as input with pull-ups. During the update function, we'll cycle
through setting the first set low and checking each pin in the second
set.
* To set a pin hi-Z on this board, set it as input with pull-up
disabled.
* Switching the driving pins (the first set of pins) between hi-Z and
drive low (treating them as if they were open drain) seems just as
good as, and a little safer than, driving them high when they're not
active.
* We need to delay for at least 1 μs between changing the column pins and
reading the row pins. I would assume this is to allow the pins time to
stabalize.
* Thanks to [hasu] (http://geekhack.org/member.php?3412-hasu)
for the suggestion [here]
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=606415&viewfull=1#post606415),
and [PrinsValium] (http://geekhack.org/member.php?6408-PrinsValium)
for noting that his firmware had erratic behavior without the delays
[here]
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=606426&viewfull=1#post606426).
DOX tried it and confirmed that it worked for his protoype PCB (as of
3 June 2012) [here]
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=606865&viewfull=1#post606865).
Before adding a delay we were having [strange problems with ghosting]
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=605857&viewfull=1#post605857).
### PWM on ports OC1(A|B|C) (see datasheet section 14.10)
* notes: settings:
* PWM pins should be set as outputs.
* we want Waveform Generation Mode 5
(fast PWM, 8-bit)
(see table 14-5)
* set `TCCRB[4,3],TCCRA[1,0]` to `0,1,0,1`
* we want "Compare Output Mode, Fast PWM" to be `0b10`
"Clear OCnA/OCnB/OCnC on compare match, set OCnA/OCnB/OCnC at TOP"
(see table 14-3)
this way higher values of `OCR1(A|B|C)` will mean longer 'on' times for
the LEDs (provided they're hooked up to GND; other way around if they're
hooked up to Vcc)
* when in a fast PWM mode, set `TCCR1A[7,6,5,4,3,2]` to `1,0,1,0,1,0`
* we want "Clock Select Bit Description" to be `0b001`
"clkI/O/1 (No prescaling)"
(see table 14-6)
* set `TCCR1B[2,1,0]` to `0,0,1`
* LEDs will be at minimum brightness until OCR1(A|B|C) are changed
(since the default value of all the bits in those registers is 0)
* notes: behavior:
* The pins source current when on, and sink current when off. They aren't
set to high impediance for either.
* In Fast PWM mode setting `OCR1(A|B|C)` to `0` does not make the output on
`OC1(A|B|C)` constant low; just close. Per the datasheet, this isn't
true for every PWM mode.
* abbreviations:
* OCR = Output Compare Register
* TCCR = Timer/Counter Control Register
-------------------------------------------------------------------------------
Copyright &copy; 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>

View File

@ -16,13 +16,13 @@
* [2]: http://www.usb.org/developers/hidpage
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Released under The MIT License (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__KEYBOARD__H
#define ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__KEYBOARD__H
#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__KEYBOARD__H
#define ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__KEYBOARD__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

View File

@ -5,13 +5,13 @@
* getting too long). See "../keyboard.h" for definitions and everything.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Released under The MIT License (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__KEYBOARD__SHORT_NAMES__H
#define ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__KEYBOARD__SHORT_NAMES__H
#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__KEYBOARD__SHORT_NAMES__H
#define ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__KEYBOARD__SHORT_NAMES__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

View File

@ -15,13 +15,13 @@
* [2]: http://www.usb.org/developers/hidpage
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
* Released under The MIT License (see "license.md")
* Project located at <https://github.com/benblazak/ergodox-firmware>
* ------------------------------------------------------------------------- */
#ifndef ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__LED__H
#define ERGODOX_FIRMWARE__SRC__LIB__USB__USAGE_PAGE__LED__H
#ifndef ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__LED__H
#define ERGODOX_FIRMWARE__FIRMWARE__LIB__USB__USAGE_PAGE__LED__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

9
firmware/options.mk Normal file
View File

@ -0,0 +1,9 @@
# ----------------------------------------------------------------------------
# Global options
# ----------------------------------------------------------------------------
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (see "doc/license.md")
# Project located at <https://github.com/benblazak/ergodox-firmware>
# ----------------------------------------------------------------------------

View File

@ -1,23 +0,0 @@
/* ----------------------------------------------------------------------------
* Common macros
* ----------------------------------------------------------------------------
* 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 ERGODOX_FIRMWARE__SRC__LIB__MACROS__COMMON__H
#define ERGODOX_FIRMWARE__SRC__LIB__MACROS__COMMON__H
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#define STRINGIFY(s) #s
#define EXPAND_STRINGIFY(s) STRINGIFY(s)
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif // ERGODOX_FIRMWARE__SRC__LIB__MACROS__COMMON__H