Merge branch 'dev': rewrites, reorganizations, and fixes

new usb library (my attempt at implementing mouse keys and nkro) in (slow)
progress

a few larger things
- new makefile
- added descriptions to most entries in the references.md file
- moved keyboard layouts to program space
- updated for DOX's PCB! :)  see the last PCB update checkin for details
f13
Ben Blazak 2012-06-01 01:10:21 -07:00
commit 088fcd5136
47 changed files with 2763 additions and 1905 deletions

6
.gitignore vendored
View File

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

View File

@ -1,319 +0,0 @@
## Electronics Stuff
* [Resistor Color Codes]
(http://www.ladyada.net/wiki/lib/exe/fetch.php?hash=a2c6a9&w=501&h=785&media=http%3A%2F%2Fwww.ladyada.net%2Fimages%2Fmetertutorial%2Frescolorcode.jpg)
: image
* from [the Multimeter Tutorial]
(http://www.ladyada.net/learn/multimeter/resistance.html)
(on <http://ladyada.net/>)
* [Schematic Symbols]
(http://img.docstoccdn.com/thumb/orig/28066054.png)
: image
* [Vcc, Vdd, Vss, etc.]
(http://encyclobeamia.solarbotics.net/articles/vxx.html)
* [Very Basic Circuits]
(http://www.seattlerobotics.org/encoder/mar97/basics.html)
: column by Kevin Ross for Encoder
* [Powering Light Emitting Diodes(LEDs)]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
* can also be reached via <http://thewolfstone.com/>
-> [ENTER] ('http://thewolfstone.com/Welcome/Home.html)
-> [Wolfstone's Haunted Halloween Page]
(http://thewolfstone.com/_ar/Halloween.html)
-> [technology]
(http://wolfstone.halloweenhost.com/Navigation/TechBase.html)
-> [powering LEDs]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
* [All About Circuits : Reference]
(http://www.allaboutcircuits.com/vol_5/index.html)
* [Effects of Varying I2C Pull-Up Resistors]
(http://dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html) : article by Wayne Truchsess
## C Stuff
* [comp.lang.c Frequently Asked Questions]
(http://c-faq.com/index.html)
* [The C Preprocessor]
(http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC1)
(on <http://gcc.gnu.org/>)
* [C Library Reference]
(http://www.cplusplus.com/reference/)
(on <http://cplusplus.com>)
* [C Operators/Expressions]
(http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/expressions.html)
(on <http://www.lix.polytechnique.fr/>)
* [Bitwise Operators in C and C++: A Tutorial]
(http://www.cprogramming.com/tutorial/bitwise_operators.html)
(on <http://cprogramming.com/>)
* [AVR Tutorials - \[TUT\] \[C\] Bit manipulation (AKA "Programming 101")]
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=37871&start=0)
* [In C++ is "const" after type ID acceptable?]
(http://stackoverflow.com/questions/988069/in-c-is-const-after-type-id-acceptable)
(on <http://stackoverflow.com/>)
* [Arrays and pointers in C]
(http://www.ibiblio.org/pub/languages/fortran/append-c.html)
(on <http://www.ibiblio.org/>)
* [how to use array of function pointers?]
(http://stackoverflow.com/questions/252748/how-to-use-array-of-function-pointers)
(on <http://stackoverflow.com/>)
* [The Function Pointer Tutorials]
(http://www.newty.de/fpt/index.html)
* [C preprocessor and concatenation]
(http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation)
(on <http://stackoverflow.com/>)
* [The New C: Inline Functions]
(http://drdobbs.com/184401540)
by Randy Meyers
(on <http://drdobbs.com/>)
### For the AVR
* [AVR Newbie guide]
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70673)
by stu_san (on <http://www.avrfreaks.net/>)
* [AVR Libc Library Reference]
(http://www.nongnu.org/avr-libc/user-manual/modules.html)
* [avr-libc/include/avr/iom32u4.h]
(http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iom32u4.h?revision=2288&root=avr-libc&view=markup)
: list of registers and associated bit numbers for ATmega32U4
* [A Brief Tutorial on Programming the AVR without Arduino]
(https://www.mainframe.cx/~ckuethe/avr-c-tutorial/)
by Chris Kuethe
## Protocol Stuff
### I&sup2;C
* [Arduino I&sup2;C Expansion IO]
(http://www.neufeld.newton.ks.us/electronics/?p=241)
(from [Keith's Electronics Blog]
(http://www.neufeld.newton.ks.us/electronics/))
* [Arduino Playground :: Wire Library, Explored]
(http://arduino.cc/playground/Main/WireLibraryDetailedReference)
### USB
* About Keyboard [Scan Codes]
(http://geekhack.org/showwiki.php?title=Scan+Codes)
(on <http://geekhack.org/>)
* [USB - boot mode, NKRO, compatibility, etc...]
(http://geekhack.org/showthread.php?13162-USB-boot-mode-NKRO-compatibility-etc/page2)
: old thread by [Soarer]
(http://geekhack.org/member.php?4274-Soarer)
(on <http://geekhack.org/>)
* [USB 2.0 Specification]
(http://www.usb.org/developers/docs/usb_20_101111.zip)
: zip (from <http://www.usb.org/developers/docs/>)
* [HID Device Class Definition]
(http://www.usb.org/developers/devclass_docs/HID1_11.pdf)
: pdf (from <http://www.usb.org/developers/hidpage>)
* HID = Human Interface Device
* [HID Usage Tables]
(http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf)
: pdf (from <http://www.usb.org/developers/hidpage>)
## Other People's Code
### Keyboard Firmware
* zip: [Phantom Firmware from PrinsValium]
(http://geekhack.org/attachment.php?attachmentid=38982&d=1327895092)
* mentioned in the [Building Phantom Hardware and Firmware Mods]
(http://geekhack.org/showwiki.php?title=Island:26742)
article (on <http://geekhack.org/>)
* github: [tmk / tmk_keyboard]
(https://github.com/tmk/tmk_keyboard)
* forked by [Pyrolistical / tmk_keyboard]
(https://github.com/Pyrolistical/tmk_keyboard/tree/master/fourway)
* mentioned in the [KeyPoard]
(http://geekhack.org/showwiki.php?title=Island:26845)
article on <http://geekhack.org/>
* forked by [riffautae / tmk_keyboard]
(https://github.com/riffautae/tmk_keyboard)
* mentioned on the [Teensy Keyboard Firmware Discussion]
(http://geekhack.org/showthread.php?26730-Teensy-Keyboard-Firmware-Discussion/page2)
thread on <http://geekhack.org/>
* github: [humblehacker / keyboard]
(https://github.com/humblehacker/keyboard)
* mentioned on [the humblehacker keyboard website]
(http://humblehacker.com/keyboard/)
* mentioned on [the humblehacker geekhack page]
(http://geekhack.org/showwiki.php?title=Island:6292)
* mentioned on [the designer's blog]
(http://humblehacker.com/blog/)
### USB Libraries
* [LUFA (2012) (Lightweight USB Framework for AVRs)]
(http://www.fourwalledcubicle.com/LUFA.php)
### TWI Libraries
* github: [TWI library in C]
(https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
: (arduino / Arduino / libraries / Wire / utility)
* zip: [i2cmaster]
(http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
(by Peter Fleury, on [his homepage]
(http://homepage.hispeed.ch/peterfleury/))
* forum: [Interfacing MCP23018 io expander via Arduino]
(http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282150189)
: contains a quick MCP23017 library in C++
* github: [maniacbug / Arduino / libraries / MCP23018]
(https://github.com/maniacbug/Arduino/tree/master/libraries/MCP23018)
: library in C++
### USB
* zip: [PJRC: usb_keyboard]
(http://pjrc.com/teensy/usb_keyboard.zip)
* mentioned on [the PJRC website]
(http://pjrc.com/teensy/usb_keyboard.html)
### Other
* zip: [PJRC: blinky]
(http://pjrc.com/teensy/blinky.zip)
* mentioned on [the PJRC website]
(http://pjrc.com/teensy/gcc.html)
## Hardware Documentation
* [Microchip: Analog & Interface Product Selector Guide]
(http://ww1.microchip.com/downloads/en/DeviceDoc/21060z.pdf)
* from [the Microchip website (MCP23017 product listing page)]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
* [MCP23017 / MCP23S17 Data Sheet]
(http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf)
* from [the Microchip website]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
* [MCP23018 / MCP23S18 Data Sheet]
(http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf)
* from [the Microchip website]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en537375)
* [Teensy 2.0 (ATMEGA32U4) Data Sheet]
(http://pjrc.com/teensy/atmega32u4.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy++ 2.0 (AT90USB1286) Data Sheet]
(http://pjrc.com/teensy/at90usb1286.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy 2.0 Pin Assignments, Using C]
(http://pjrc.com/teensy/card2a.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy 2.0 Pin Assignments, Using Arduino]
(http://pjrc.com/teensy/card2b.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Cherry MX Series Keyswitches : Specifications]
(http://www.cherrycorp.com/english/switches/key/mx.htm)
## Miscellaneous
### Documentation and Design Tools
* [Markdown: Syntax]
(http://daringfireball.net/projects/markdown/syntax)
* [KiCAD Tutorial]
(http://teholabs.com/knowledge/kicad.html)
(on <http://teholabs.com/>)
* mentioned on the [circuit/block-diagram drawing]
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
question (on <http://stackoverflow.com/>)
* [Ti_k_Z and PGF]
(http://www.texample.net/tikz/)
: a TeX graphics package
* mentioned on the [circuit/block-diagram drawing]
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
question (on <http://stackoverflow.com/>)
* [Documentation (for version 2010-09-28)]
(http://www.texample.net/media/pgf/builds/pgfmanualCVS2010-09-28.pdf)
: pdf
* [Example: Block diagram line junctions]
(http://www.texample.net/tikz/examples/line-junctions/)
* [Inkscape : Connector tool tutorial]
(http://wiki.inkscape.org/wiki/index.php/UsingTheConnectorTool)
### Typical Keyboard Information
* [Keyboard Scan Rates]
(http://geekhack.org/showwiki.php?title=Keyboard+scan+rates)
list (on <http://geekhack.org/>)
-------------------------------------------------------------------------------
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

@ -4,14 +4,49 @@
[ergodox keyboard]: http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard
## About this File
If you're viewing this on github, please note that directory links will only
work if you're viewing this from the directory, and file links will only work
if you're viewing this as a file. This is true for all the '.md' files here.
The limitation is due to the way github addresses directories and files, and
the fact that Markdown doesn't have any way (that I know of) to rewrite the
URLs as would be required.
## About this Project
This project is definitely in beta, but I'll do my best to keep the 'master'
branch working. Please see the source (and especially the accompanying '*.md'
files) for documentation.
branch working. Please see the source (and especially the accompanying '.md'
files) for documentation. And [references.md] (references.md) contains lots of
good links, along with descriptions.
If you're just trying to compile, jump to the bottom of the file and read the
[Dependencies] (#dependencies-for-building-from-source) section. Once that's
taken care of, navigate to the [src] (src) directory, compile using Make, and
fire up your teensy loader to transfer the '.hex' file. Just to be safe, you
should also check the '.eep' file. If it's larger than 0 bytes, you need to
load it too.
If you're looking to hack on the source, or just feel like reading it, you
probably don't need much direction for a small project like this. I'll try to
write more later (for people who are new to AVR programming, like I was when I
started this project), but for now:
* [src/lib] (src/lib) is for generally useful stuff. The TWI and USB libraries
are in there, along with the file containing basic key press and release
functions.
* [src/keyboard] (src/keyboard) is for keyboard specific stuff. All the chip
initialization code is there, along with the layout files, the software
matrix to hardware matrix mapping, and hardware specific documentation.
* [src/main.c] (src/main.c) ties it all together.
Open issues and such are tracked [on github]
(/benblazak/ergodox-firmware/issues).
## Notes
### (2012-04-11)
### (2012-04-11) (first major release on branch 'main')
As of now, it looks like we have a working 6-KRO keyboard firmware for a Teensy
2.0 with a MCP23018 I/O expander. It's scanning at ~167 Hz, most of which is
spent communicating over I&sup2;C. This should be fast enough, I think.
@ -43,7 +78,12 @@ buy!), please stop by. :) .
* See the PJRC [Getting Started] (http://pjrc.com/teensy/first_use.html) page
for instructions on how to set up an AVR programming environment. This
project uses C (not Arduino).
project uses C (not Arduino), and Make. I'm compiling with GNU tools under
Ubuntu, but other environments (especially [WinAVR]
(http://winavr.sourceforge.net/) under Windows) should work too.
* I also assume that you are using [git] (http://git-scm.com/) (for `make
clean`).
-------------------------------------------------------------------------------

454
references.md Normal file
View File

@ -0,0 +1,454 @@
## Electronics Stuff
* [Resistor Color Codes]
(http://www.ladyada.net/wiki/lib/exe/fetch.php?hash=a2c6a9&w=501&h=785&media=http%3A%2F%2Fwww.ladyada.net%2Fimages%2Fmetertutorial%2Frescolorcode.jpg)
: image
* from [the Multimeter Tutorial]
(http://www.ladyada.net/learn/multimeter/resistance.html)
(on <http://ladyada.net/>)
* [Schematic Symbols]
(http://img.docstoccdn.com/thumb/orig/28066054.png)
: image
* [Vcc, Vdd, Vss, etc.]
(http://encyclobeamia.solarbotics.net/articles/vxx.html)
A neat little discussion of the symbols and where they came from.
* [Very Basic Circuits]
(http://www.seattlerobotics.org/encoder/mar97/basics.html)
: column by Kevin Ross for Encoder
Includes a short thing about pull-up resistors.
* [Powering Light Emitting Diodes(LEDs)]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
Can you use one resistor for multiple parallel LEDs? No. Or, you can, but
it's not the best idea.
* can also be reached via <http://thewolfstone.com/>
-> [ENTER] ('http://thewolfstone.com/Welcome/Home.html)
-> [Wolfstone's Haunted Halloween Page]
(http://thewolfstone.com/_ar/Halloween.html)
-> [technology]
(http://wolfstone.halloweenhost.com/Navigation/TechBase.html)
-> [powering LEDs]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
* [All About Circuits : Reference]
(http://www.allaboutcircuits.com/vol_5/index.html)
Looks like a great collection of info; didn't get to read much of it.
* [Effects of Varying I2C Pull-Up Resistors]
(http://dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html) : article by Wayne Truchsess
Great discussion on the topic, with oscilloscope graphs. The practical
takeaway is that 4.7kΩ is a good value for 100kHz I&sup2;C, and 2.2kΩ is good
for 400kHz.
## C Stuff
* [comp.lang.c Frequently Asked Questions]
(http://c-faq.com/index.html)
Really good information, if they happen to address the question you have.
* [The C Preprocessor]
(http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC1)
(on <http://gcc.gnu.org/>)
One of my main references.
* [The GNU C Preprocessor]
(http://tigcc.ticalc.org/doc/cpp.html#SEC27)
A modified version on a different site. Has a few really useful things that
I don't think I saw in the official documentation.
* [C Library Reference]
(http://www.cplusplus.com/reference/)
(on <http://cplusplus.com>)
* [C Operators/Expressions]
(http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/expressions.html)
(on <http://www.lix.polytechnique.fr/>)
* [Bitwise Operators in C and C++: A Tutorial]
(http://www.cprogramming.com/tutorial/bitwise_operators.html)
(on <http://cprogramming.com/>)
* [AVR Tutorials - \[TUT\] \[C\] Bit manipulation (AKA "Programming 101")]
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=37871&start=0)
* [In C++ is "const" after type ID acceptable?]
(http://stackoverflow.com/questions/988069/in-c-is-const-after-type-id-acceptable)
(on <http://stackoverflow.com/>)
* [Arrays and pointers in C]
(http://www.ibiblio.org/pub/languages/fortran/append-c.html)
(on <http://www.ibiblio.org/>)
* [how to use array of function pointers?]
(http://stackoverflow.com/questions/252748/how-to-use-array-of-function-pointers)
(on <http://stackoverflow.com/>)
* [The Function Pointer Tutorials]
(http://www.newty.de/fpt/index.html)
* [C preprocessor and concatenation]
(http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation)
(on <http://stackoverflow.com/>)
* [The New C: Inline Functions]
(http://drdobbs.com/184401540)
by Randy Meyers
(on <http://drdobbs.com/>)
* [gcc: why the -lm flag is needed to link the math library?]
(http://stackoverflow.com/questions/4606301/gcc-why-the-lm-flag-is-needed-to-link-the-math-library)
(on <http://stackoverflow.com/>)
### For the AVR
* [AVR Newbie guide]
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70673)
by stu_san (on <http://www.avrfreaks.net/>)
Didn't read much of it, but it looks like a great collection of info.
* [AVR Libc Library Reference]
(http://www.nongnu.org/avr-libc/user-manual/modules.html)
One of my main references.
* [AVR : Data in Program Space]
(http://www.nongnu.org/avr-libc/user-manual/pgmspace.html)
How to use '<avr/pgmspace.h>'.
* [avr-libc/include/avr/iom32u4.h]
(http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iom32u4.h?revision=2288&root=avr-libc&view=markup)
List of registers and associated bit numbers for the ATmega32U4
* [A Brief Tutorial on Programming the AVR without Arduino]
(https://www.mainframe.cx/~ckuethe/avr-c-tutorial/)
by Chris Kuethe
Goes over a bunch of stuff pretty generally. Useful to me because it was
talking about exactly what I was trying to do (e.g. program the thing
directly instead of messing around with gratuitous libraries).
* [Optimisations of AVR programs using avr-gcc]
(http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html)
About compiling and stuff.
* [Using the EEPROM memory in AVR-GCC]
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38417)
: tutorial by [Dean Camera] (http://fourwalledcubicle.com/AboutMe.php)
(on <http://www.avrfreaks.net/>)
The EEPROM is non-volatile data memory that can withstand 100,000 writes and
is byte accessible from within the program. On the Teensy 2.0 there's only
1,024 bytes of it though (compared to 32,256 bytes of flash, and 2,560 bytes
of RAM), so you have to use it sparingly. It's useful because flash
(program) memory is not really something that's meant to be written to (it
can only withstand 10,000 writes, and has to be written in pages using
instructions meant for the bootloader), and RAM is volatile.
* updated version available as a pdf at
[Four Walled Cubicle : AVR Articles]
(http://www.fourwalledcubicle.com/AVRArticles.php), along with a few
other good articles on AVR programming
## Protocol Stuff
### I&sup2;C
* [Arduino I&sup2;C Expansion IO]
(http://www.neufeld.newton.ks.us/electronics/?p=241)
(from [Keith's Electronics Blog]
(http://www.neufeld.newton.ks.us/electronics/))
Didn't use this much, but it's nice (if you're using the Arduino 'Wire'
library), and it has pictures.
* [Arduino Playground :: Wire Library, Explored]
(http://arduino.cc/playground/Main/WireLibraryDetailedReference)
More about the Wire library. If you're not using interrupts, I think you'll
be better off looking throught the datasheet and writing your own trivial
library in C. It really is trivial, almost all the code is in the datasheet
(at least for the ATmega32U4), and it'll make more sense to you that way :) .
### USB
* About Keyboard [Scan Codes]
(http://geekhack.org/showwiki.php?title=Scan+Codes)
(on <http://geekhack.org/>)
Interesting discussion. For practical purposes, if you're just dealing with
USB, you can skip this and go straight to the keyboard usage page in the HID
Usage Tables (see below).
* [USB - boot mode, NKRO, compatibility, etc...]
(http://geekhack.org/showthread.php?13162-USB-boot-mode-NKRO-compatibility-etc/page2)
: old thread by [Soarer]
(http://geekhack.org/member.php?4274-Soarer)
(on <http://geekhack.org/>)
Discussion about getting NKRO to work over USB and still be compatible with
various BIOSs.
* [USB 2.0 Specification]
(http://www.usb.org/developers/docs/usb_20_101111.zip)
: zip (from <http://www.usb.org/developers/docs/>)
* [HID Device Class Definition]
(http://www.usb.org/developers/devclass_docs/HID1_11.pdf)
: pdf (from <http://www.usb.org/developers/hidpage>)
* HID = Human Interface Device
* [HID Usage Tables]
(http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf)
: pdf (from <http://www.usb.org/developers/hidpage>)
## Other People's Code
### Keyboard Firmware
* zip: [Phantom Firmware from PrinsValium]
(http://geekhack.org/attachment.php?attachmentid=38982&d=1327895092)
Pretty basic (unless I'm missing nuances, which is entirely possible).
Helped me a lot when I was learning how to initialize stuff on the Teensy.
* mentioned in the [Building Phantom Hardware and Firmware Mods]
(http://geekhack.org/showwiki.php?title=Island:26742)
article (on <http://geekhack.org/>)
* github: [tmk / tmk_keyboard]
(https://github.com/tmk/tmk_keyboard)
Firmware by [hasu] (http://geekhack.org/member.php?3412-hasu) on geekhack.
Supports NKRO and mouse movements.
* forked by [Pyrolistical / tmk_keyboard]
(https://github.com/Pyrolistical/tmk_keyboard/tree/master/fourway)
* mentioned in the [KeyPoard]
(http://geekhack.org/showwiki.php?title=Island:26845)
article on <http://geekhack.org/>
* forked by [riffautae / tmk_keyboard]
(https://github.com/riffautae/tmk_keyboard)
* mentioned on the [Teensy Keyboard Firmware Discussion]
(http://geekhack.org/showthread.php?26730-Teensy-Keyboard-Firmware-Discussion/page2)
thread on <http://geekhack.org/>
* github: [humblehacker / keyboard]
(https://github.com/humblehacker/keyboard)
Looks like it has some cool ideas, but I haven't read through it well enough
to know what's going on.
* mentioned on [the humblehacker keyboard website]
(http://humblehacker.com/keyboard/)
* mentioned on [the humblehacker geekhack page]
(http://geekhack.org/showwiki.php?title=Island:6292)
* mentioned on [the designer's blog]
(http://humblehacker.com/blog/)
### USB Libraries
* [LUFA (2012) (Lightweight USB Framework for AVRs)]
(http://www.fourwalledcubicle.com/LUFA.php)
Very well known USB library for AVRs. And it looks like it be really good
too, but the documentation is hard to get into, and the examples don't seem
to have enough explanation for me, since I don't have any background in what
USB is doing in the first place.
* zip: [PJRC: usb_keyboard]
(http://pjrc.com/teensy/usb_keyboard.zip)
From the [LUFA Library : Alternative USB AVR Stacks]
(http://www.fourwalledcubicle.com/files/LUFA/Doc/110528/html/_page__alternative_stacks.html)
page: "Not so much a complete stack as a collection of USB enabled demos,
this library is specifically designed for the PJRC Teensy line of USB AVRs,
and thus may need to be modified for other USB AVR chips. These minimal code
samples shows the inner workings of the USB controller, without all the
abstraction present in most other USB AVR stacks."
* mentioned on [the PJRC website]
(http://pjrc.com/teensy/usb_keyboard.html)
* [V-USB]
(http://vusb.wikidot.com/driver-api)
From the [LUFA Library : Alternative USB AVR Stacks]
(http://www.fourwalledcubicle.com/files/LUFA/Doc/110528/html/_page__alternative_stacks.html)
page: "Well regarded and complete USB 1.1 software stack for several AVR
models, implementing Low Speed HID. Used in many commercial and
non-commercial designs, with user-submitted projects available for viewing on
the company's website. Uses C language code mixed with assembly for
time-critical sections."
Also, it has really good documentation.
### TWI Libraries
* github: [TWI library in C]
(https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
: (arduino / Arduino / libraries / Wire / utility)
Well done (as far as I can tell) and complete (includes code for interrupt
handling). Meant to be used through the Arduino 'Wire' library interface,
but you can use it alone as well. The version on github pulls in a whole
bunch of Arduino dependencies though, if you're just going to use the
library look for an older version that doesn't (like the one included in the
version of Arduino in the Ubuntu 11.10 repos).
* zip: [i2cmaster]
(http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
(by Peter Fleury, on [his homepage]
(http://homepage.hispeed.ch/peterfleury/))
Good I2C library. Includes stuff both in assembly and C (though, I didn't
look at the assembly code). I still think you're better off writing your
own, it's not that hard and you'll understand it better. Also, this library
is under the GPL (from what it says on his site; couldn't find a licence in
the code).
* forum: [Interfacing MCP23018 io expander via Arduino]
(http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282150189)
Contains a quick MCP23017 library in C++. Didn't end up looking at it too
hard.
* github: [maniacbug / Arduino / libraries / MCP23018]
(https://github.com/maniacbug/Arduino/tree/master/libraries/MCP23018)
Library in C++. Don't think I ended up looking through this one at all.
### Other
* [Soarer's Converter (XT/AT/PS2/Terminal to USB Converter with NKRO)]
(http://geekhack.org/showwiki.php?title=Island:17458)
No code for the part that talks over USB though. Code only available for the
tools that allow you to change the keymap and stuff, I think.
* zip: [PJRC: blinky]
(http://pjrc.com/teensy/blinky.zip)
Little baby example project for the Teensy. Quite nice.
* mentioned on [the PJRC website]
(http://pjrc.com/teensy/gcc.html)
## Hardware Documentation
* [Microchip: Analog & Interface Product Selector Guide]
(http://ww1.microchip.com/downloads/en/DeviceDoc/21060z.pdf)
* from [the Microchip website (MCP23017 product listing page)]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
* [MCP23017 / MCP23S17 Data Sheet]
(http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf)
* from [the Microchip website]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
* [MCP23018 / MCP23S18 Data Sheet]
(http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf)
* from [the Microchip website]
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en537375)
* [Teensy 2.0 (ATMEGA32U4) Data Sheet]
(http://pjrc.com/teensy/atmega32u4.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy++ 2.0 (AT90USB1286) Data Sheet]
(http://pjrc.com/teensy/at90usb1286.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy 2.0 Pin Assignments, Using C]
(http://pjrc.com/teensy/card2a.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Teensy 2.0 Pin Assignments, Using Arduino]
(http://pjrc.com/teensy/card2b.pdf)
* from [the PJRC website]
(http://pjrc.com/teensy/datasheets.html)
* [Cherry MX Series Keyswitches : Specifications]
(http://www.cherrycorp.com/english/switches/key/mx.htm)
## Miscellaneous
### Typical Keyboard Information
* [Keyboard Scan Rates]
(http://geekhack.org/showwiki.php?title=Keyboard+scan+rates)
list (on <http://geekhack.org/>)
Keyboards seem to typically scan at rates from a little below 100Hz to about
300Hz, with the most common values a little below 100Hz. The [PJRC
usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.html) example
documentation has a limit of 1000 packets (so 500 presses -> releases) per
second, but says that even that speed might overwhelm host software, which
expects keystrokes to come much more slowly. And, a debounce time of 5ms
(which is the spec'ed high value for Cherry MX switches) would give us a max
scan rate of 200Hz.
### Other Awesome Keyboard Projects
* [My DIY keyboard collection ( or how I became a KB-geek...)]
(http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html)
: post by [suka] (http://deskthority.net/suka-u434/)
on <http://deskthority.net/>
If I ever decide to do a keyboard completely by myself, I'm going back to
this link and starting with this. Looks really well done.
* linked to in [a post]
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=582593&viewfull=1#post582593)
on the ergoDOX geekhack thread
### Documentation and Design Tools
* [Markdown: Syntax]
(http://daringfireball.net/projects/markdown/syntax)
A necessity if your code is on github :) .
* [KiCAD Tutorial]
(http://teholabs.com/knowledge/kicad.html)
(on <http://teholabs.com/>)
I like the tool. Didn't need the functionality just for a little circuit
diagram though, so I forwent the learning curve and used Inkscape.
* mentioned on the [circuit/block-diagram drawing]
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
question (on <http://stackoverflow.com/>)
* [Ti<i>k</i>Z and PGF]
(http://www.texample.net/tikz/)
: a TeX graphics package
This is really cool. And I wish i knew more about LaTeX (and all its
variations) so that it would have been time effective for me to use it. If I
ever need to do automatic diagram generation, I'm going to give this a more
serious try.
* mentioned on the [circuit/block-diagram drawing]
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
question (on <http://stackoverflow.com/>)
* [Documentation (for version 2010-09-28)]
(http://www.texample.net/media/pgf/builds/pgfmanualCVS2010-09-28.pdf)
: pdf
* [Example: Block diagram line junctions]
(http://www.texample.net/tikz/examples/line-junctions/)
* [Inkscape : Connector tool tutorial]
(http://wiki.inkscape.org/wiki/index.php/UsingTheConnectorTool)
The open source vector graphics tool. Not the _best_ for diagrams (though,
see the link; as that tool improves it will hopefully become much better),
but it works and I like it :) .
-------------------------------------------------------------------------------
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

@ -1,96 +0,0 @@
/* ----------------------------------------------------------------------------
* key functions: code
* ----------------------------------------------------------------------------
* 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 "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types.h"
#include "lib/usb/keyboard-usage-page.h"
#include "keyboard.h"
// ----------------------------------------------------------------------------
#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
return 0; // success
}
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
}
#endif
// ----------------------------------------------------------------------------
void kbfun_press(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col ) {
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 ) {
for (uint8_t i=0; i<6; i++)
if (keyboard_keys[i] == *keycode) {
keyboard_keys[i] = 0;
break;
}
}
void kbfun_mod_press(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col ) {
switch (*keycode) {
case KEY_LeftControl: keyboard_modifier_keys |= (1<<0); break;
case KEY_LeftShift: keyboard_modifier_keys |= (1<<1); break;
case KEY_LeftAlt: keyboard_modifier_keys |= (1<<2); break;
case KEY_LeftGUI: keyboard_modifier_keys |= (1<<3); break;
case KEY_RightControl: keyboard_modifier_keys |= (1<<4); break;
case KEY_RightShift: keyboard_modifier_keys |= (1<<5); break;
case KEY_RightAlt: keyboard_modifier_keys |= (1<<6); break;
case KEY_RightGUI: keyboard_modifier_keys |= (1<<7); break;
}
}
void kbfun_mod_release(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col ) {
switch (*keycode) {
case KEY_LeftControl: keyboard_modifier_keys &= ~(1<<0); break;
case KEY_LeftShift: keyboard_modifier_keys &= ~(1<<1); break;
case KEY_LeftAlt: keyboard_modifier_keys &= ~(1<<2); break;
case KEY_LeftGUI: keyboard_modifier_keys &= ~(1<<3); break;
case KEY_RightControl:keyboard_modifier_keys &= ~(1<<4); break;
case KEY_RightShift: keyboard_modifier_keys &= ~(1<<5); break;
case KEY_RightAlt: keyboard_modifier_keys &= ~(1<<6); break;
case KEY_RightGUI: keyboard_modifier_keys &= ~(1<<7); break;
}
}

View File

@ -1,6 +1,7 @@
/* ----------------------------------------------------------------------------
* keyboard specific exports
* use this file to include the keyboard you're compiling for
*
* Different keyboards are included by modifying a variable in the makefile.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -8,5 +9,14 @@
* ------------------------------------------------------------------------- */
#include "keyboard/ergodox.h" // only supported keyboard right now
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc

View File

@ -14,10 +14,22 @@
#include "lib/data-types.h"
#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
// note:
// - see your keyswitch specification for the necessary value. for
// cherry mx switches, the switch bounce time is speced to be <= 5ms.
// it looks like most switches are speced to be between 5 and 8 ms.
// - if timing is important, balance this value with the main() loop
// run time (~5ms, last i checked, nearly all of it in the i2c
// update() function)
#define KB_DEBOUNCE_TIME 5 // in ms
uint8_t kb_init(void);
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);

View File

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -1,94 +0,0 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout specific code
* ----------------------------------------------------------------------------
* 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 "lib/data-types.h"
#include "lib/usb/keyboard-usage-page.h"
#include "key-functions.h"
#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
// TODO (before release): put more effort into this
uint8_t kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
{ // layer 0: default
// right hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 0 */ { 0, KEY_6_Caret, KEY_7_Ampersand, KEY_8_Asterisk, KEY_9_LeftParenthesis, KEY_0_RightParenthesis, KEY_Dash_Underscore }, /* 0 */
/* 1 */ { 0, KEY_y_Y, KEY_u_U, KEY_i_I, KEY_o_O, KEY_p_P, KEY_LeftBracket_LeftBrace }, /* 1 */
/* 2 */ { 0,/*unused*/ KEY_h_H, KEY_j_J, KEY_k_K, KEY_l_L, KEY_Semicolon_Colon, KEY_SingleQuote_DoubleQuote }, /* 2 */
/* 3 */ { 0, KEY_n_N, KEY_m_M, KEY_Comma_LessThan, KEY_Period_GreaterThan, KEY_Slash_Question, KEY_RightShift }, /* 3 */
/* 4 */ { 0,/*unused*/ 0,/*unused*/ KEY_UpArrow, KEY_DownArrow, KEY_Backslash_Pipe, KEY_RightBracket_RightBrace, 0 }, /* 4 */
/* 5 */ { 0,/*unused*/ KEY_RightControl, KEY_RightAlt, KEY_PageUp, KEY_PageDown, KEY_ReturnEnter, KEY_Spacebar }, /* 5 */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
// left hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 6 */ { KEY_Equal_Plus, KEY_1_Exclamation, KEY_2_At, KEY_3_Pound, KEY_4_Dollar, KEY_5_Percent, 0 }, /* 6 */
/* 7 */ { KEY_Tab, KEY_q_Q, KEY_w_W, KEY_e_E, KEY_r_R, KEY_t_T, 0 }, /* 7 */
/* 8 */ { KEY_CapsLock, KEY_a_A, KEY_s_S, KEY_d_D, KEY_f_F, KEY_g_G, 0/*unused*/ }, /* 8 */
/* 9 */ { KEY_LeftShift, KEY_z_Z, KEY_x_X, KEY_c_C, KEY_v_V, KEY_b_B, 0 }, /* 9 */
/* A */ { 0, KEY_GraveAccent_Tilde, KEY_Backslash_Pipe, KEY_LeftArrow, KEY_RightArrow, 0,/*unused*/ 0/*unused*/ }, /* A */
/* B */ { KEY_DeleteBackspace, KEY_DeleteForward, KEY_End, KEY_Home, KEY_LeftAlt, KEY_LeftControl, 0/*unused*/ } /* B */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
}
};
kbfun_funptr_t kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
{ // layer 0: default
// right hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 0 */ { NULL, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press }, /* 0 */
/* 1 */ { NULL, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press }, /* 1 */
/* 2 */ { NULL,/*unused*/ &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press }, /* 2 */
/* 3 */ { NULL, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_mod_press }, /* 3 */
/* 4 */ { NULL,/*unused*/ NULL,/*unused*/ &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL }, /* 4 */
/* 5 */ { NULL,/*unused*/ &kbfun_mod_press, &kbfun_mod_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press }, /* 5 */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
// left hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 6 */ { &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL }, /* 6 */
/* 7 */ { &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL }, /* 7 */
/* 8 */ { &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL/*unused*/ }, /* 8 */
/* 9 */ { &kbfun_mod_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL }, /* 9 */
/* A */ { NULL, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, NULL,/*unused*/ NULL/*unused*/ }, /* A */
/* B */ { &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_press, &kbfun_mod_press, &kbfun_mod_press, NULL/*unused*/ } /* B */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
}
};
kbfun_funptr_t kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
{ // layer 0: default
// right hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 0 */ { NULL, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release }, /* 0 */
/* 1 */ { NULL, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release }, /* 1 */
/* 2 */ { NULL,/*unused*/ &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release }, /* 2 */
/* 3 */ { NULL, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_mod_release }, /* 3 */
/* 4 */ { NULL,/*unused*/ NULL,/*unused*/ &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL }, /* 4 */
/* 5 */ { NULL,/*unused*/ &kbfun_mod_release, &kbfun_mod_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release }, /* 5 */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
// left hand
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
/* 6 */ { &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL }, /* 6 */
/* 7 */ { &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL }, /* 7 */
/* 8 */ { &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL/*unused*/ }, /* 8 */
/* 9 */ { &kbfun_mod_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL }, /* 9 */
/* A */ { NULL, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, NULL,/*unused*/ NULL/*unused*/ }, /* A */
/* B */ { &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_release, &kbfun_mod_release, &kbfun_mod_release, NULL/*unused*/ } /* B */
/* 0 -------------------------- 1 -------------------------- 2 -------------------------- 3 -------------------------- 4 -------------------------- 5 -------------------------- 6 -------------------------- */
}
};

View File

@ -1,5 +1,7 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout specific exports
* ergoDOX layout : exports
*
* Different layouts are included by modifying a variable in the makefile.
* ----------------------------------------------------------------------------
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
* Released under The MIT License (MIT) (see "license.md")
@ -9,20 +11,113 @@
#ifndef LAYOUT_h
#define LAYOUT_h
#include <avr/pgmspace.h>
#include "lib/data-types.h"
#include "lib/key-functions.h" // for `kbfun_funptr_t`
#include "key-functions.h"
#include "matrix.h" // for number of rows and columns, and layout
// to matrix macros
#include "matrix.h"
// include the appropriate keyboard layout header
// for:
// - number of layers
// - possible non-default layout matrix definitions
// - possible non-default layout 'get' and 'set' definitions
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(layout/MAKEFILE_KEYBOARD_LAYOUT.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc
#define KB_LAYERS 1 // must match what's defined in "layout.c"
extern uint8_t
kb_layout [KB_LAYERS][KB_ROWS][KB_COLUMNS];
extern kbfun_funptr_t
kb_layout_press [KB_LAYERS][KB_ROWS][KB_COLUMNS];
extern kbfun_funptr_t
kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
// default layout 'get' macros and `extern` matrix declarations
//
// these are for when the matrices are stored solely in Flash. layouts
// may redefine them if they wish and use RAM, EEPROM, or any
// combination of the three, as long as they maintain the same
// interface.
//
// - if the macro is overridden, the matrix declaration must be too,
// and vice versa.
//
// - 'set' functions are optional, and should be defined in the layout
// specific '.h'. they'll require the use of the EEPROM, possibly in
// clever conjunction with one of the other two memories (since the
// EEPROM is small). custom key functions will also need to be
// written.
//
// - to override these macros with real functions, set the macro equal
// to itself (e.g. `#define kb_layout_get kb_layout_get`) and provide
// function prototypes in the layout specific '.h'
#ifndef kb_layout_get
extern uint8_t PROGMEM \
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_get(layer,row,column) \
( (uint8_t) \
pgm_read_byte(&( \
_kb_layout[layer][row][column] )) )
#endif
#ifndef kb_layout_press_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_press_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_press[layer][row][column] )) )
#endif
#ifndef kb_layout_release_get
extern kbfun_funptr_t PROGMEM \
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_release_get(layer,row,column) \
( (kbfun_funptr_t) \
pgm_read_word(&( \
_kb_layout_release[layer][row][column] )) )
#endif
// default logical LED macros (all defined to nothing)
#ifndef kb_led_num_on
#define kb_led_num_on()
#endif
#ifndef kb_led_num_off
#define kb_led_num_off()
#endif
#ifndef kb_led_caps_on
#define kb_led_caps_on()
#endif
#ifndef kb_led_caps_off
#define kb_led_caps_off()
#endif
#ifndef kb_led_scroll_on
#define kb_led_scroll_on()
#endif
#ifndef kb_led_scroll_off
#define kb_led_scroll_off()
#endif
#ifndef kb_led_compose_on
#define kb_led_compose_on()
#endif
#ifndef kb_led_compose_off
#define kb_led_compose_off()
#endif
#ifndef kb_led_kana_on
#define kb_led_kana_on()
#endif
#ifndef kb_led_kana_off
#define kb_led_kana_off()
#endif
#endif

View File

@ -0,0 +1,39 @@
# Documentation : layout
Different layouts are included by modifying a variable in the makefile.
To write a new one:
* You must implement everything defined in [layout.h] (layout.h). Take a look
at existing layouts in the 'layout' subdir.
* Currently, see [qwerty.c] (layout/qwerty.c) and [qwerty.h]
(layout/qwerty.h). The latter is only important if you want more than
one layer. And I still need to write the functions to make that possible
(though that shouldn't be hard, I just haven't gotten to it yet). But
(at least for the QWERTY and Dvorak layouts I'd really like to include)
if you indicate it clealy in the layout, and provide complete
initializations for `kb_layout[][][]`, `kb_layout_press[][][]`, and
`kb_layout_release[][][]`, I'll make sure it gets working.
* The number of layers must be defined in the layout *.h file.
* Use `0` for no-operation (unused) keys, and `NULL` for no-operation (unused)
functions.
* See [matrix.md] (matrix.md) for how the key matrix maps to hardware.
* See [keyboard-usage-page--short-names.h]
(../../lib/_usb/keyboard-usage-page--short-names.h) for available keycodes.
* See [key-functions.c] (../../lib/_key-functions.c) for what functions keys
can call.
* See [_defaults.h] (layout/_defaults.h) for default function layers and
aliases.
## notes
* Each full layer takes 420 bytes of memory, wherever it's stored. (The matrix
size is 12x7, keycodes are 1 byte each, and function pointers are 2 bytes
each.)
-------------------------------------------------------------------------------
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,61 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout : QWERTY
*
* This is an overly basic implementation. It needs to be replaced.
* ----------------------------------------------------------------------------
* 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 <avr/pgmspace.h>
#include "lib/data-types.h"
#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
uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
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,
// 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,
_space,
_ctrlR, _enter,
_altR, _pageU, _pageD )
};
kbfun_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
LAYER_SET_ALL(NULL, &kbfun_press) // layer 0: default
};
kbfun_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
LAYER_SET_ALL(NULL, &kbfun_release) // layer 0: default
};

View File

@ -0,0 +1,26 @@
/* ----------------------------------------------------------------------------
* ergoDOX layout : QWERTY : 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 LAYOUT_QWERTY_h
#define LAYOUT_QWERTY_h
#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()
#endif

View File

@ -0,0 +1,45 @@
/* ----------------------------------------------------------------------------
* led stuff that isn't microprocessor or layout specific
*
* 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_'
* ----------------------------------------------------------------------------
* 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 LED_h
#define LED_h
#include <util/delay.h>
#include "teensy-2-0.h" // for low-level led macros
#define kb_led_state_power_on() do { \
_led_all_set_percent(0.05); \
_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); \
_delay_ms(333); \
_led_2_set_percent(0.5); \
_delay_ms(333); \
_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); \
} while(0)
#endif

View File

@ -19,5 +19,90 @@
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
* - 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 } }
#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 )
#endif
#endif

View File

@ -1,27 +0,0 @@
# Documentation : Keyboard Matrix
## Matrix [row##column] assignments
* row and column numbers are in hex
* coordinates without brackets are unused
* left and right hands are mostly the same except that `row += 6` for the left
....... rows x columns = positions; assigned, unassigned .......
....... per hand: 6 x 7 = 42; 38, 4 .......
....... total: 12 x 7 = 84; 76, 8 .......
----------------------------------------------------------------------------
[60][61][62][63][64][65][66] [00][01][02][03][04][05][06]
[70][71][72][73][74][75][76] [10][11][12][13][14][15][16]
[80][81][82][83][84][85] 86 20 [21][22][23][24][25][26]
[90][91][92][93][94][95][96] [30][31][32][33][34][35][36]
[A0][A1][A2][A3][A4] A5 A6 40 41 [42][43][44][45][46]
[B0] B6 50 [56]
[B1] [B5] [51] [55]
[B2][B3][B4] [52][53][54]
-------------------------------------------------------------------------------
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

@ -8,9 +8,8 @@
#include <util/twi.h>
#include "lib/data-types.h"
#include "lib/teensy-2-0/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#include "lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
#define KEYBOARD_INCLUDE_PRIVATE
#include "matrix.h"
@ -45,25 +44,26 @@ uint8_t mcp23018_init(void) {
// set pin direction
// - unused : input : 1
// - rows : output : 0
// - columns : input : 1
// - row : input : 1
// - column : output : 0
twi_start();
ret = twi_send(TWI_ADDR_WRITE);
if (ret) goto out; // make sure we got an ACK
twi_send(IODIRA);
twi_send(0b11000000); // IODIRA
twi_send(0b11111111); // IODIRB
twi_send(0b11111111); // IODIRA
twi_send(0b10000000); // IODIRB
twi_stop();
// set pull-up
// - unused : on : 1
// - rows : off : 0
// - columns : on : 1
// - rows : on : 1
// - columns : off : 0
twi_start();
twi_send(TWI_ADDR_WRITE);
ret = twi_send(TWI_ADDR_WRITE);
if (ret) goto out; // make sure we got an ACK
twi_send(GPPUA);
twi_send(0b11000000); // GPPUA
twi_send(0b11111111); // GPPUB
twi_send(0b11111111); // GPPUA
twi_send(0b10000000); // GPPUB
twi_stop();
// set logical value (doesn't matter on inputs)
@ -71,7 +71,8 @@ uint8_t mcp23018_init(void) {
// - rows : high (hi-Z) : 1
// - columns : high (hi-Z) : 1
twi_start();
twi_send(TWI_ADDR_WRITE);
ret = twi_send(TWI_ADDR_WRITE);
if (ret) goto out; // make sure we got an ACK
twi_send(OLATA);
twi_send(0b11111111); //OLATA
twi_send(0b11111111); //OLATB
@ -108,34 +109,34 @@ uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
}
// update our part of the matrix
for (uint8_t row=0x6; row<=0xB; row++) {
// set active row low : 0
// set other rows high (hi-Z) : 1
for (uint8_t col=0; col<=6; col++) {
// set active column low : 0
// set other columns high (hi-Z) : 1
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(OLATA);
twi_send( 0b11111111 & ~(1<<(row-6)) );
twi_send(OLATB);
twi_send( 0xFF & ~(1<<col) );
twi_stop();
// read column data
// read row data
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(GPIOB);
twi_send(GPIOA);
twi_start();
twi_send(TWI_ADDR_READ);
twi_read(&data);
twi_stop();
// update matrix
for (uint8_t col=0; col<=6; col++)
matrix[row][col] = !( data & (1<<col) );
for (uint8_t row=0x6; row<=0xB; row++)
matrix[row][col] = !( data & (1<<(row-6)) );
}
// set all rows high (hi-Z) : 1
// set all columns high (hi-Z) : 1
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(GPIOA);
twi_send(0b11111111);
twi_send(GPIOB);
twi_send(0xFF);
twi_stop();
return ret; // success

View File

@ -41,18 +41,18 @@
NC o14-------15+ ADDR (see note)
* notes:
* 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>
* 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
@ -69,28 +69,28 @@
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
* 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.
* We want the row pins set as output high (hi-Z) without pull-ups initially,
and the column pins set as input with pull-ups. We'll cycle through
driving the row pins low and checking the column pins in the update
function.
* All addresses given for IOCON.BANK = 0, since that's the default value of
the bit, and that's what we'll be using.
* We want the column pins set as output high (hi-Z) without pull-ups
initially, and the row pins set as input with pull-ups. We'll cycle
through driving the column pins low and checking the row pins in the
update function.
* 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
* 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)
@ -130,8 +130,8 @@
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).
* We'll be using sequential mode (ICON.SEQOP = 0; default) (see datasheet
section 1.3.1).
-------------------------------------------------------------------------------

View File

@ -8,10 +8,9 @@
#include <avr/io.h>
#include "lib/data-types.h"
#define TWI_FREQ 400000
#include "lib/teensy-2-0/twi.h"
#include "lib/twi.h"
#define KEYBOARD_INCLUDE_PRIVATE
#include "matrix.h"
@ -37,19 +36,50 @@
* movable, and either are referenced explicitly or have macros defined for
* them elsewhere.
* - note: if you change pin assignments, please be sure to update
* "teensy-2-0.md".
* "teensy-2-0.md", and the '.svg' circuit diagram.
*/
// --- helpers
#define TEENSYPIN_WRITE(register, operation, pin) \
_TEENSYPIN_WRITE(register, operation, pin)
#define _TEENSYPIN_WRITE(register, operation, pin_letter, pin_number) \
#define teensypin_write(register, operation, pin) \
_teensypin_write(register, operation, pin)
#define _teensypin_write(register, operation, pin_letter, pin_number) \
((register##pin_letter) operation (1<<(pin_number)))
#define TEENSYPIN_READ(pin) \
_TEENSYPIN_READ(pin)
#define _TEENSYPIN_READ(pin_letter, pin_number) \
#define teensypin_read(pin) \
_teensypin_read(pin)
#define _teensypin_read(pin_letter, pin_number) \
((PIN##pin_letter) & (1<<(pin_number)))
#define teensypin_write_all_unused(register, operation) \
do { \
teensypin_write(register, operation, UNUSED_0); \
teensypin_write(register, operation, UNUSED_1); \
teensypin_write(register, operation, UNUSED_2); \
teensypin_write(register, operation, UNUSED_3); \
teensypin_write(register, operation, UNUSED_4); \
teensypin_write(register, operation, UNUSED_5); } \
while(0)
#define teensypin_write_all_row(register, operation) \
do { \
teensypin_write(register, operation, ROW_0); \
teensypin_write(register, operation, ROW_1); \
teensypin_write(register, operation, ROW_2); \
teensypin_write(register, operation, ROW_3); \
teensypin_write(register, operation, ROW_4); \
teensypin_write(register, operation, ROW_5); } \
while(0)
#define teensypin_write_all_column(register, operation) \
do { \
teensypin_write(register, operation, COLUMN_0); \
teensypin_write(register, operation, COLUMN_1); \
teensypin_write(register, operation, COLUMN_2); \
teensypin_write(register, operation, COLUMN_3); \
teensypin_write(register, operation, COLUMN_4); \
teensypin_write(register, operation, COLUMN_5); \
teensypin_write(register, operation, COLUMN_6); } \
while(0)
#define SET |=
#define CLEAR &=~
@ -90,66 +120,25 @@ 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")
DDRB |= 0b11100000; // set B(7,6,5) as output
_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
KB_LED1_SET_PERCENT(0.5); KB_LED1_OFF;
KB_LED2_SET_PERCENT(0.5); KB_LED2_OFF;
KB_LED3_SET_PERCENT(0.5); KB_LED3_OFF;
// I2C (TWI)
twi_init(); // on pins D(1,0)
// unused pins
// --- set as input
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_0);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_1);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_2);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_3);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_4);
TEENSYPIN_WRITE(DDR, CLEAR, UNUSED_5);
// --- set internal pull-up enabled
TEENSYPIN_WRITE(PORT, SET, UNUSED_0);
TEENSYPIN_WRITE(PORT, SET, UNUSED_1);
TEENSYPIN_WRITE(PORT, SET, UNUSED_2);
TEENSYPIN_WRITE(PORT, SET, UNUSED_3);
TEENSYPIN_WRITE(PORT, SET, UNUSED_4);
TEENSYPIN_WRITE(PORT, SET, UNUSED_5);
teensypin_write_all_unused(DDR, CLEAR); // set as input
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
// rows
// --- set as input (hi-Z)
TEENSYPIN_WRITE(DDR, CLEAR, ROW_0);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_1);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_2);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_3);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_4);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_5);
// --- set internal pull-up disabled
TEENSYPIN_WRITE(PORT, CLEAR, ROW_0);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_1);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_2);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_3);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_4);
TEENSYPIN_WRITE(PORT, CLEAR, ROW_5);
teensypin_write_all_row(DDR, CLEAR); // set as input
teensypin_write_all_row(PORT, SET); // set internal pull-up enabled
// columns
// --- set as input
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_0);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_1);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_2);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_3);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_4);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_5);
TEENSYPIN_WRITE(DDR, CLEAR, COLUMN_6);
// --- set internal pull-up enabled
TEENSYPIN_WRITE(PORT, SET, COLUMN_0);
TEENSYPIN_WRITE(PORT, SET, COLUMN_1);
TEENSYPIN_WRITE(PORT, SET, COLUMN_2);
TEENSYPIN_WRITE(PORT, SET, COLUMN_3);
TEENSYPIN_WRITE(PORT, SET, COLUMN_4);
TEENSYPIN_WRITE(PORT, SET, COLUMN_5);
TEENSYPIN_WRITE(PORT, SET, COLUMN_6);
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
teensypin_write_all_column(PORT, CLEAR); // set internal pull-up
// disabled
return 0; // success
}
@ -160,40 +149,43 @@ uint8_t teensy_init(void) {
#if KB_ROWS != 12 || KB_COLUMNS != 7
#error "Expecting different keyboard dimensions"
#endif
static inline void _update_columns(
bool matrix[KB_ROWS][KB_COLUMNS], uint8_t row ) {
matrix[row][0] = ! TEENSYPIN_READ(COLUMN_0);
matrix[row][1] = ! TEENSYPIN_READ(COLUMN_1);
matrix[row][2] = ! TEENSYPIN_READ(COLUMN_2);
matrix[row][3] = ! TEENSYPIN_READ(COLUMN_3);
matrix[row][4] = ! TEENSYPIN_READ(COLUMN_4);
matrix[row][5] = ! TEENSYPIN_READ(COLUMN_5);
matrix[row][6] = ! TEENSYPIN_READ(COLUMN_6);
static inline void _update_rows(
bool matrix[KB_ROWS][KB_COLUMNS], uint8_t column ) {
matrix[0][column] = ! teensypin_read(ROW_0);
matrix[1][column] = ! teensypin_read(ROW_1);
matrix[2][column] = ! teensypin_read(ROW_2);
matrix[3][column] = ! teensypin_read(ROW_3);
matrix[4][column] = ! teensypin_read(ROW_4);
matrix[5][column] = ! teensypin_read(ROW_5);
}
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
TEENSYPIN_WRITE(DDR, SET, ROW_0); // set row low (set as output)
_update_columns(matrix, 0); // read col 0..6 and update matrix
TEENSYPIN_WRITE(DDR, CLEAR, ROW_0); // set row hi-Z (set as input)
teensypin_write(DDR, SET, COLUMN_0); // set col low (set as output)
_update_rows(matrix, 0); // read row 0..5 & update matrix
teensypin_write(DDR, CLEAR, COLUMN_0); // set col hi-Z (set as input)
TEENSYPIN_WRITE(DDR, SET, ROW_1);
_update_columns(matrix, 1);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_1);
teensypin_write(DDR, SET, COLUMN_1);
_update_rows(matrix, 1);
teensypin_write(DDR, CLEAR, COLUMN_1);
TEENSYPIN_WRITE(DDR, SET, ROW_2);
_update_columns(matrix, 2);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_2);
teensypin_write(DDR, SET, COLUMN_2);
_update_rows(matrix, 2);
teensypin_write(DDR, CLEAR, COLUMN_2);
TEENSYPIN_WRITE(DDR, SET, ROW_3);
_update_columns(matrix, 3);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_3);
teensypin_write(DDR, SET, COLUMN_3);
_update_rows(matrix, 3);
teensypin_write(DDR, CLEAR, COLUMN_3);
TEENSYPIN_WRITE(DDR, SET, ROW_4);
_update_columns(matrix, 4);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_4);
teensypin_write(DDR, SET, COLUMN_4);
_update_rows(matrix, 4);
teensypin_write(DDR, CLEAR, COLUMN_4);
TEENSYPIN_WRITE(DDR, SET, ROW_5);
_update_columns(matrix, 5);
TEENSYPIN_WRITE(DDR, CLEAR, ROW_5);
teensypin_write(DDR, SET, COLUMN_5);
_update_rows(matrix, 5);
teensypin_write(DDR, CLEAR, COLUMN_5);
teensypin_write(DDR, SET, COLUMN_6);
_update_rows(matrix, 6);
teensypin_write(DDR, CLEAR, COLUMN_6);
return 0; // success
}

View File

@ -11,24 +11,47 @@
#define TEENSY_2_0_h
#include <avr/io.h> // for the register macros
#include "lib/data-types.h"
#include "matrix.h"
// LED control
#define KB_LED1_ON (DDRB |= (1<<5))
#define KB_LED1_OFF (DDRB &= ~(1<<5))
#define KB_LED1_SET(n) (OCR1A = (uint8_t)(n))
#define KB_LED1_SET_PERCENT(n) (OCR1A = (uint8_t)((n) * 0xFF))
#define KB_LED2_ON (DDRB |= (1<<6))
#define KB_LED2_OFF (DDRB &= ~(1<<6))
#define KB_LED2_SET(n) (OCR1B = (uint8_t)(n))
#define KB_LED2_SET_PERCENT(n) (OCR1B = (uint8_t)((n) * 0xFF))
#define KB_LED3_ON (DDRB |= (1<<7))
#define KB_LED3_OFF (DDRB &= ~(1<<7))
#define KB_LED3_SET(n) (OCR1C = (uint8_t)(n))
#define KB_LED3_SET_PERCENT(n) (OCR1C = (uint8_t)((n) * 0xFF))
#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 _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 _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 _led_all_on() do { \
_led_1_on(); \
_led_2_on(); \
_led_3_on(); \
} while(0)
#define _led_all_off() do { \
_led_1_off(); \
_led_2_off(); \
_led_3_off(); \
} while(0)
#define _led_all_set(n) do { \
_led_1_set(n); \
_led_2_set(n); \
_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); \
} while(0)
#ifdef KEYBOARD_INCLUDE_PRIVATE

View File

@ -34,8 +34,8 @@
PB3 o o o + PF5 row3
(OC1C) LED3 PB7 + PE6 AREF + PF6 row4
(SCL) I2C PD0 + + PF7 row5
(SDA) I2C PD1 + + PB6 LED2 (OC1B)
column3 PD2 + + PB5 LED1 (OC1A)
(SDA) I2C PD1 + + PB6 LED1 (OC1B)
column3 PD2 + + PB5 LED2 (OC1A)
column4 PD3 + + PB4 column0
column1 PC6 + + PD7 column5
column2 PC7 +-o-o-o-o-o-+ PD6 onboardLED
@ -44,10 +44,10 @@
GND-------/
* notes:
* 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 for
400kHz I&sup2;C seems to be 2.2kΩ.
* 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
for 400kHz I&sup2;C seems to be 2.2kΩ.
## Notes about Registers
@ -65,51 +65,52 @@
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.
* We want the row pins 'hi-Z' initially (set as input with pull-up disabled),
and the column pins set as input with internal pull-up enabled. We'll
cycle through driving the row pins low (setting them as output) and
checking the column pins in the update function.
* Switching the row 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 the row's not active.
* 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.
* We want the columns to be hi-Z when that column's not being scanned,
drive low when it is, and the rows to be input with pull-up enabled.
We'll cycle through driving the columns low and scanning all rows.
* To set a pin hi-Z on this board, set it as input with pull-up
disabled.
* Switching the row 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 the row's not active.
### 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)
* 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.
* 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
* OCR = Output Compare Register
* TCCR = Timer/Counter Control Register
-------------------------------------------------------------------------------

View File

@ -0,0 +1,19 @@
# src/lib/pjrc
## links to original files
* [pjrc] (http://pjrc.com/teensy/)
* [usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip)
<!--
* [usb_mouse] (http://pjrc.com/teensy/usb_mouse.zip)
* [usb_serial] (http://pjrc.com/teensy/usb_serial.zip)
* Directions for host setup [here]
(http://pjrc.com/teensy/usb_serial.html)
-->
-------------------------------------------------------------------------------
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

@ -1,614 +0,0 @@
# Hey Emacs, this is a -*- makefile -*-
#----------------------------------------------------------------------------
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
#
# Released to the Public Domain
#
# Additional material for this makefile was written by:
# Peter Fleury
# Tim Henigan
# Colin O'Flynn
# Reiner Patommel
# Markus Pfaff
# Sander Pool
# Frederik Rouleau
# Carlos Lamas
#
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device, using avrdude.
# Please customize the avrdude settings below first!
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------
# Target file name (without extension).
TARGET = example
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
usb_keyboard.c
# MCU name, you MUST set this to match the board you are using
# type "make clean" after changing this, so all files will be rebuilt
#
#MCU = at90usb162 # Teensy 1.0
MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb646 # Teensy++ 1.0
#MCU = at90usb1286 # Teensy++ 2.0
# Processor frequency.
# Normally the first thing your program should do is set the clock prescaler,
# so your program will run at the correct speed. You should also set this
# variable to same clock speed. The _delay_ms() macro uses this, and many
# examples use this variable to calculate timings. Do not add a "UL" here.
F_CPU = 16000000
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
# Object files directory
# To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro!
OBJDIR = .
# List C++ source files here. (C dependencies are automatically generated.)
CPPSRC =
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
# Debugging format.
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
# AVR Studio 4.10 requires dwarf-2.
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
DEBUG = dwarf-2
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS =
# Compiler flag to set the C Standard level.
# c89 = "ANSI" C
# gnu89 = c89 plus GCC extensions
# c99 = ISO C99 standard (not yet fully implemented)
# gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
CDEFS = -DF_CPU=$(F_CPU)UL
# Place -D or -U options here for ASM sources
ADEFS = -DF_CPU=$(F_CPU)
# Place -D or -U options here for C++ sources
CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
#---------------- Compiler Options C ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char
CFLAGS += -funsigned-bitfields
CFLAGS += -ffunction-sections
CFLAGS += -fpack-struct
CFLAGS += -fshort-enums
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes
#CFLAGS += -mshort-calls
#CFLAGS += -fno-unit-at-a-time
#CFLAGS += -Wundef
#CFLAGS += -Wunreachable-code
#CFLAGS += -Wsign-compare
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
#---------------- Compiler Options C++ ----------------
# -g*: generate debugging information
# -O*: optimization level
# -f...: tuning, see GCC manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
CPPFLAGS = -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
CPPFLAGS += -funsigned-char
CPPFLAGS += -funsigned-bitfields
CPPFLAGS += -fpack-struct
CPPFLAGS += -fshort-enums
CPPFLAGS += -fno-exceptions
CPPFLAGS += -Wall
CPPFLAGS += -Wundef
#CPPFLAGS += -mshort-calls
#CPPFLAGS += -fno-unit-at-a-time
#CPPFLAGS += -Wstrict-prototypes
#CPPFLAGS += -Wunreachable-code
#CPPFLAGS += -Wsign-compare
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
#CPPFLAGS += $(CSTANDARD)
#---------------- Assembler Options ----------------
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
#---------------- Library Options ----------------
# Minimalistic printf version
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
# Floating point printf version (requires MATH_LIB = -lm below)
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
# If this is left blank, then it will use the Standard printf version.
PRINTF_LIB =
#PRINTF_LIB = $(PRINTF_LIB_MIN)
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
# Minimalistic scanf version
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
# If this is left blank, then it will use the Standard scanf version.
SCANF_LIB =
#SCANF_LIB = $(SCANF_LIB_MIN)
#SCANF_LIB = $(SCANF_LIB_FLOAT)
MATH_LIB = -lm
# List any extra directories to look for libraries here.
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
EXTRALIBDIRS =
#---------------- External Memory Options ----------------
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# used for variables (.data/.bss) and heap (malloc()).
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
# only used for heap (malloc()).
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
EXTMEMOPTS =
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
LDFLAGS += -Wl,--relax
LDFLAGS += -Wl,--gc-sections
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
#LDFLAGS += -T linker_script.x
#---------------- Programming Options (avrdude) ----------------
# Programming hardware
# Type: avrdude -c ?
# to get a full listing.
#
AVRDUDE_PROGRAMMER = stk500v2
# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = com1 # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE_COUNTER = -y
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_NO_VERIFY = -V
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_VERBOSE = -v -v
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
#---------------- Debugging Options ----------------
# For simulavr only - target MCU frequency.
DEBUG_MFREQ = $(F_CPU)
# Set the DEBUG_UI to either gdb or insight.
# DEBUG_UI = gdb
DEBUG_UI = insight
# Set the debugging back-end to either avarice, simulavr.
DEBUG_BACKEND = avarice
#DEBUG_BACKEND = simulavr
# GDB Init Filename.
GDBINIT_FILE = __avr_gdbinit
# When using avarice settings for the JTAG
JTAG_DEV = /dev/com1
# Debugging port used to communicate between GDB / avarice / simulavr.
DEBUG_PORT = 4242
# Debugging host used to communicate between GDB / avarice / simulavr, normally
# just set to localhost unless doing some sort of crazy debugging when
# avarice is running on a different computer.
DEBUG_HOST = localhost
#============================================================================
# Define programs and commands.
SHELL = sh
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
AR = avr-ar rcs
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
REMOVEDIR = rm -rf
COPY = cp
WINSHELL = cmd
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling C:
MSG_COMPILING_CPP = Compiling C++:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:
# Define all object files.
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
# Define all listing files.
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
# Compiler flags to generate dependency files.
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: begin gccversion sizebefore build sizeafter end
# Change the build target to build a HEX file or a library.
build: elf hex eep lss sym
#build: lib
elf: $(TARGET).elf
hex: $(TARGET).hex
eep: $(TARGET).eep
lss: $(TARGET).lss
sym: $(TARGET).sym
LIBNAME=lib$(TARGET).a
lib: $(LIBNAME)
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
end:
@echo $(MSG_END)
@echo
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
ELFSIZE = $(SIZE) $(TARGET).elf
sizebefore:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
2>/dev/null; echo; fi
sizeafter:
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
2>/dev/null; echo; fi
# Display compiler version information.
gccversion :
@$(CC) --version
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
# Generate avr-gdb config/init file which does the following:
# define the reset signal, load the target file, connect to target, and set
# a breakpoint at main().
gdb-config:
@$(REMOVE) $(GDBINIT_FILE)
@echo define reset >> $(GDBINIT_FILE)
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
@echo end >> $(GDBINIT_FILE)
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
ifeq ($(DEBUG_BACKEND),simulavr)
@echo load >> $(GDBINIT_FILE)
endif
@echo break main >> $(GDBINIT_FILE)
debug: gdb-config $(TARGET).elf
ifeq ($(DEBUG_BACKEND), avarice)
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
@$(WINSHELL) /c pause
else
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
endif
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT = $(OBJCOPY) --debugging
COFFCONVERT += --change-section-address .data-0x800000
COFFCONVERT += --change-section-address .bss-0x800000
COFFCONVERT += --change-section-address .noinit-0x800000
COFFCONVERT += --change-section-address .eeprom-0x810000
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S -z $< > $@
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
$(NM) -n $< > $@
# Create library from object files.
.SECONDARY : $(TARGET).a
.PRECIOUS : $(OBJ)
%.a: $(OBJ)
@echo
@echo $(MSG_CREATING_LIBRARY) $@
$(AR) $@ $(OBJ)
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create object files from C++ source files.
$(OBJDIR)/%.o : %.cpp
@echo
@echo $(MSG_COMPILING_CPP) $<
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C++ source files.
%.s : %.cpp
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
$(OBJDIR)/%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Create preprocessed source for use in sending a bug report.
%.i : %.c
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
# Target: clean project.
clean: begin clean_list end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lss
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
$(REMOVE) $(SRC:.c=.i)
$(REMOVEDIR) .dep
# Create object files directory
$(shell mkdir $(OBJDIR) 2>/dev/null)
# Include the dependency files.
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion \
build elf hex eep lss sym coff extcoff \
clean clean_list program debug gdb-config

View File

@ -1,124 +0,0 @@
/* Keyboard example for Teensy USB Development Board
* http://www.pjrc.com/teensy/usb_keyboard.html
* Copyright (c) 2008 PJRC.COM, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usb_keyboard.h"
#define LED_CONFIG (DDRD |= (1<<6))
#define LED_ON (PORTD &= ~(1<<6))
#define LED_OFF (PORTD |= (1<<6))
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
uint8_t number_keys[10]=
{KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9};
uint16_t idle_count=0;
int main(void)
{
uint8_t b, d, mask, i, reset_idle;
uint8_t b_prev=0xFF, d_prev=0xFF;
// set for 16 MHz clock
CPU_PRESCALE(0);
// Configure all port B and port D pins as inputs with pullup resistors.
// See the "Using I/O Pins" page for details.
// http://www.pjrc.com/teensy/pins.html
DDRD = 0x00;
DDRB = 0x00;
PORTB = 0xFF;
PORTD = 0xFF;
// Initialize the USB, and then wait for the host to set configuration.
// If the Teensy is powered without a PC connected to the USB port,
// this will wait forever.
usb_init();
while (!usb_configured()) /* wait */ ;
// Wait an extra second for the PC's operating system to load drivers
// and do whatever it does to actually be ready for input
_delay_ms(1000);
// Configure timer 0 to generate a timer overflow interrupt every
// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
// This demonstrates how to use interrupts to implement a simple
// inactivity timeout.
TCCR0A = 0x00;
TCCR0B = 0x05;
TIMSK0 = (1<<TOIE0);
while (1) {
// read all port B and port D pins
b = PINB;
d = PIND;
// check if any pins are low, but were high previously
mask = 1;
reset_idle = 0;
for (i=0; i<8; i++) {
if (((b & mask) == 0) && (b_prev & mask) != 0) {
usb_keyboard_press(KEY_B, KEY_SHIFT);
usb_keyboard_press(number_keys[i], 0);
reset_idle = 1;
}
if (((d & mask) == 0) && (d_prev & mask) != 0) {
usb_keyboard_press(KEY_D, KEY_SHIFT);
usb_keyboard_press(number_keys[i], 0);
reset_idle = 1;
}
mask = mask << 1;
}
// if any keypresses were detected, reset the idle counter
if (reset_idle) {
// variables shared with interrupt routines must be
// accessed carefully so the interrupt routine doesn't
// try to use the variable in the middle of our access
cli();
idle_count = 0;
sei();
}
// now the current pins will be the previous, and
// wait a short delay so we're not highly sensitive
// to mechanical "bounce".
b_prev = b;
d_prev = d;
_delay_ms(2);
}
}
// This interrupt routine is run approx 61 times per second.
// A very simple inactivity timeout is implemented, where we
// will send a space character.
ISR(TIMER0_OVF_vect)
{
idle_count++;
if (idle_count > 61 * 8) {
idle_count = 0;
usb_keyboard_press(KEY_SPACE, 0);
}
}

View File

@ -349,8 +349,8 @@ int8_t usb_keyboard_send(void)
//
ISR(USB_GEN_vect)
{
uint8_t intbits, i; // used to declare `t` as well, but it wasn't used
// ::Blazak, 2012::
uint8_t intbits, i; // used to declare a variable `t` as well, but it
// wasn't used ::Ben Blazak, 2012::
static uint8_t div4=0;
intbits = UDINT;

View File

@ -19,7 +19,7 @@ extern volatile uint8_t keyboard_leds;
#define usb_debug_flush_output()
#if 0 // removed in favor of equilivent code elsewhere ::Ben Blazak, 2012::
#if 0 // removed in favor of equivalent code elsewhere ::Ben Blazak, 2012::
#define KEY_CTRL 0x01
#define KEY_SHIFT 0x02

118
src/lib/key-functions.c Normal file
View File

@ -0,0 +1,118 @@
/* ----------------------------------------------------------------------------
* key functions: code
*
* These functions may do.. pretty much anything rational that thay like. If
* they want keycodes to be sent to the host in an aggrate report, they're
* responsible for modifying the appropriate report variables.
* ----------------------------------------------------------------------------
* 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 "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"
// ----------------------------------------------------------------------------
#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
return 0; // success
}
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
}
#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;
}
}

View File

@ -12,20 +12,16 @@
#include "lib/data-types.h"
typedef void (*kbfun_funptr_t)(uint8_t*, uint8_t*, uint8_t*, uint8_t*);
typedef void (*kbfun_funptr_t)(
uint8_t, uint8_t *,
uint8_t *, uint8_t * );
void kbfun_press(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
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 );
void kbfun_mod_press(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
void kbfun_mod_release(
uint8_t * keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
uint8_t keycode, uint8_t * current_layer,
uint8_t * row, uint8_t * col );
#endif

View File

@ -1,10 +1,5 @@
# src/lib-other
Files taken from other projects
## links to original files
* [pjrc] (http://pjrc.com/teensy/)
* [usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip)
# src/lib
Stuff that's generally useful
-------------------------------------------------------------------------------

23
src/lib/twi.h Normal file
View File

@ -0,0 +1,23 @@
/* ----------------------------------------------------------------------------
* TWI (I2C) : exports
*
* Code specific to different development boards is used by modifying a
* variable in the makefile.
* ----------------------------------------------------------------------------
* 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>
* ------------------------------------------------------------------------- */
#undef _str
#undef _expstr
#undef _inc
#define _str(s) #s // stringify
#define _expstr(s) _str(s) // expand -> stringify
#define _inc _expstr(twi/MAKEFILE_BOARD.h) // inc(lude)
#include _inc
#undef _str
#undef _expstr
#undef _inc

View File

@ -3,13 +3,15 @@
*
* - This is mostly straight from the datasheet, section 20.6.6, figure 20-11
* (the code example in C), and section 20.8.1, figure 20-12
* - Also see the documentation for `<util/twi.h>` at <http://www.nongnu.org/avr-libc/user-manual/group__util__twi.html#ga8d3aca0acc182f459a51797321728168>
* - Also see the documentation for `<util/twi.h>` at
* <http://www.nongnu.org/avr-libc/user-manual/group__util__twi.html#ga8d3aca0acc182f459a51797321728168>
*
* Some other (more complete) TWI libraries for the Teensy 2.0 (and other Amtel
* Some other (more complete) TWI libraries for the Teensy 2.0 (and other Atmel
* processors):
* - [i2cmaster] (http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
* - written by [peter-fleury] (http://homepage.hispeed.ch/peterfleury/)
* - [the arduino twi library] (https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
* - [the arduino twi library]
* (https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
* - look for an older version if you need one that doesn't depend on all the
* other Arduino stuff
* ----------------------------------------------------------------------------
@ -19,10 +21,8 @@
* ------------------------------------------------------------------------- */
#include <util/delay.h> //dbg
#include <util/twi.h>
#include "twi.h"
#include "lib/twi.h"
void twi_init(void) {

View File

@ -1,4 +1,4 @@
# Documentation : Teensy 2.0 I&sup2;C
# Documentation : I&sup2;C : Teensy 2.0
## I&sup2;C Status Codes (for Master modes)

43
src/lib/usb/TODO.c Normal file
View File

@ -0,0 +1,43 @@
/* ----------------------------------------------------------------------------
* TODO: not sure where this stuff should be yet. a lot of it (depending on
* what ends up here) will likely be device and application specific.
*
* - The following document versions were used, unless otherwise noted:
* - USB Specification: revision 2.0
* - HID Usage Tables: version 1.12
* - Device Class Definition for Human Interface Devices (HID): version 1.11
* ----------------------------------------------------------------------------
* 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>
* ------------------------------------------------------------------------- */
// TODO: does stuff from spec sec 9.4.* belong directly in an interrupt vector?
// - spec sec 9.4.1 (Standard Device Requests / Clear Feature) (pg 252)
// - spec sec 9.4.2 (Standard Device Requests / Get Configuration) (pg 253)
// - spec sec 9.4.3 (Standard Device Requests / Get Descriptor) (pg 253)
// - spec sec 9.4.4 (Standard Device Requests / Get Interface) (pg 254)
// - spec sec 9.4.5 (Standard Device Requests / Get Status) (pg 254)
// - spec sec 9.4.6 (Standard Device Requests / Set Address) (pg 256)
// - spec sec 9.4.7 (Standard Device Requests / Set Configuration) (pg 257)
// - spec sec 9.4.8 (Standard Device Requests / Set Descriptor) (pg 257)
// - spec sec 9.4.9 (Standard Device Requests / Set Feature) (pg 258)
// - spec sec 9.4.10 (Standard Device Requests / Set Interface) (pg 259)
// - 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

52
src/lib/usb/common.h Normal file
View File

@ -0,0 +1,52 @@
/* ----------------------------------------------------------------------------
* USB 2.0 common macros and definitions
*
* See "notes from usb 2.0 spec sec 9 (usb device framework).h".
* ----------------------------------------------------------------------------
* 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 USB_COMMON_h
#define USB_COMMON_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// - spec table 9-4 (Standard Request Codes)
#define USB_GET_STATUS 0
#define USB_CLEAR_FEATURE 1
// (reserved for future use): 2
#define USB_SET_FEATURE 3
// (reserved for future use): 4
#define USB_SET_ADDRESS 5
#define USB_GET_DESCRIPTOR 6
#define USB_SET_DESCRIPTOR 7
#define USB_GET_CONFIGURATION 8
#define USB_SET_CONFIGURATION 9
#define USB_GET_INTERFACE 10
#define USB_SET_INTERFACE 11
#define USB_SYNCH_FRAME 12
// - spec table 9-5 (Descriptor Types)
#define USB_DEVICE 1
#define USB_CONFIGURATION 2
#define USB_STRING 3
#define USB_INTERFACE 4
#define USB_ENDPOINT 5
#define USB_DEVICE_QUALIFIER 6
#define USB_OTHER_SPEED_CONFIGURATION 7
#define USB_INTERFACE_POWER 8
// - spec table 9-6 (Standard Feature Selectors)
#define USB_DEVICE_REMOTE_WAKEUP 1 // recipient: device
#define USB_ENDPOINT_HALT 0 // recipient: endpoint
#define USB_TEST_MODE 2 // recipient: device
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -0,0 +1,27 @@
# Notes from the HID Device Class Definition, version 1.11
* sec 4.1 (The HID Class)
* The `bInterfaceClass` member of an Interface descriptor is always 3 for
HID class devices.
* sec 4.2 (Subclass)
* The `bInterfaceSubClass` member declares whether a device supports a boot interface.
* 0 => no subclass
* 1 => boot interface subclass
* 2..255 => reserved
* sec 4.3 (Protocols)
* The `bInterfaceProtocol` member of an Interface descriptor only has meaning if the `bInterfaceSubClass` member declares that the device supports a boot interface, otherwise it is 0.
* 0 => none
* 1 => keyboard
* 2 => mouse
* 3..255 => reserved
-------------------------------------------------------------------------------
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,858 @@
/* ----------------------------------------------------------------------------
* Notes from the USB 2.0 specification
*
* Written as a header file because I was going to actually use it. Changed my
* mind because it's simpler to use uint8_t arrays for things than to use
* structs. it's also easier i think to keep the least and most significant
* bits of uint16_t values separate initially instead of separating them later.
* Kept it as a header because it looks cleaner this way than i could make it
* look as an .md file.
*
* - conventions from the spec
* - variable prefixes
* - 'b' : bits or bytes; dependent on context
* - 'bcd' : binary-coded decimal
* - 'bm' : bitmap
* - 'd' : descriptor
* - 'i' : index
* - 'w' : word
*
* - conventions used in this file
* - everything prefixed with or `USB_` (for non-function-like macros) or
* `usb_` (for everything else)
*
* ----------------------------------------------------------------------------
* 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 USB_DATA_STRUCTURES_h
#define USB_DATA_STRUCTURES_h
#pragma pack(push)
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include "lib/data-types.h"
// ----------------------------------------------------------------------------
/* - spec sec 9.3 (USB Device Requests)
* - table 9-2 (Format of Setup Data)
*/
struct usb_setup_data {
uint8_t bmRequestType;
/* value: bitmap
* - data transfer direction, type, recipient
* (see macros below)
*/
uint8_t bRequest;
/* value: value
* - type of request (depending on bmRequestType)
* (see spec table 9-3 (Standard Device Requests))
*/
uint16_t wValue;
/* value: value
* - varies according to request; used to pass a request specific
* parameter to the device
*/
uint16_t wIndex;
/* value: index or offset
* - varies according to request; often used to specify an endpoint or
* an interface
* (see spec figure 9-2 and 9-3, copied below)
*/
uint16_t wLength;
/* value: count
* - number of bytes to transfer if there is a data stage
*/
};
/* - spec sec 9.3 (USB Device Requests)
* - table 9-2 (Format of Setup Data)
* - bmRequestType
*
* .-------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |-------------------------------------------------------|
* | direction | type | recipient |
* '-------------------------------------------------------'
*
* - direction: 0 => host to device
* 1 => device to host
*
* - type: 0 => standard
* 1 => class
* 2 = vendor
* 3 = reserved
*
* - recipient: 0 => device
* 1 => interface
* 2 => endpoint
* 3 => other
* 4..31 => reserved
*/
// --- data transfer direction
#define usb_bmRequestType_hostToDevice(val) (((val) & (0b1<<7)) == (0<<7))
#define usb_bmRequestType_deviceToHost(val) (((val) & (0b1<<7)) == (1<<7))
// --- type
#define usb_bmRequestType_standard(val) (((val) & (0b11<<5)) == (0<<5))
#define usb_bmRequestType_class(val) (((val) & (0b11<<5)) == (1<<5))
#define usb_bmRequestType_vendor(val) (((val) & (0b11<<5)) == (2<<5))
#define usb_bmRequestType_reserved(val) (((val) & (0b11<<5)) == (3<<5))
// --- recipient
#define usb_bmRequestType_device(val) (((val) & (0b11111<<0)) == (0<<0))
#define usb_bmRequestType_interface(val) (((val) & (0b11111<<0)) == (1<<0))
#define usb_bmRequestType_endpoint(val) (((val) & (0b11111<<0)) == (2<<0))
#define usb_bmRequestType_other(val) (((val) & (0b11111<<0)) == (3<<0))
#define usb_bmRequestType_reserved(val) (((val) & (0b11100<<0)) != (0<<0))
/* - spec sec 9.3.4 (wIndex)
* - figure 9-2 (format when specifying an endpoint)
*
* .-------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |-------------------------------------------------------|
* | direction | reserved (reset to 0) | endpoint number |
* >-----------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |-------------------------------------------------------|
* | reserved (reset to 0) |
* '-------------------------------------------------------'
*
* - direction: 0 => out (to device), 1 => in (to host)
*/
#define usb_wIndex_endpoint(direction, endpoint_number) \
( (uint16_t) (((direction)<<7) | (endpoint_number)) )
/* - spec sec 9.3.4 (wIndex)
* - figure 9-3 (format when specifying an interface)
*
* .-------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |-------------------------------------------------------|
* | interface number |
* >-----------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |-------------------------------------------------------|
* | reserved (reset to 0) |
* '-------------------------------------------------------'
*/
#define usb_wIndex_interface(interface_number) \
( (uint16_t) (interface_number) )
// ----------------------------------------------------------------------------
/* - spec table 9-4 (Standard Request Codes)
*/
#define USB_GET_STATUS 0
#define USB_CLEAR_FEATURE 1
// (reserved for future use): 2
#define USB_SET_FEATURE 3
// (reserved for future use): 4
#define USB_SET_ADDRESS 5
#define USB_GET_DESCRIPTOR 6
#define USB_SET_DESCRIPTOR 7
#define USB_GET_CONFIGURATION 8
#define USB_SET_CONFIGURATION 9
#define USB_GET_INTERFACE 10
#define USB_SET_INTERFACE 11
#define USB_SYNCH_FRAME 12
/* - spec table 9-5 (Descriptor Types)
*/
#define USB_DEVICE 1
#define USB_CONFIGURATION 2
#define USB_STRING 3
#define USB_INTERFACE 4
#define USB_ENDPOINT 5
#define USB_DEVICE_QUALIFIER 6
#define USB_OTHER_SPEED_CONFIGURATION 7
#define USB_INTERFACE_POWER 8
/* - spec table 9-6 (Standard Feature Selectors)
*/
#define USB_DEVICE_REMOTE_WAKEUP 1 // recipient: device
#define USB_ENDPOINT_HALT 0 // recipient: endpoint
#define USB_TEST_MODE 2 // recipient: device
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
* - figure 9-4 (information returned by a GetStatus() request to a device)
*
* .------------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |------------------------------------------------------------|
* | reserved (reset to 0) | remote wakeup | self powered |
* >----------------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |------------------------------------------------------------|
* | reserved (reset to 0) |
* '------------------------------------------------------------'
*
* - remote wakeup: 0 => ability of device to signal remote wakeup disabled
* (default)
* 1 => ability ................................. enabled
*
* - self powered: 0 => device is bus powered
* 1 => device is self powered
*/
#define usb_getStatus_device(remote_wakeup, self_powered) \
( (uint16_t) (((remote_wakeup)<<1) | (self_powered)) )
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
* - figure 9-5 (information returned by a GetStatus() request to an
* interface)
*
* .------------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |------------------------------------------------------------|
* | reserved (reset to 0) |
* >----------------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |------------------------------------------------------------|
* | reserved (reset to 0) |
* '------------------------------------------------------------'
*/
#define usb_getStatus_interface() ( (uint16_t) 0 )
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
* - figure 9-6 (information returned by a GetStatus() request to an
* endpoint)
*
* .------------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |------------------------------------------------------------|
* | reserved (reset to 0) | halt |
* >----------------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |------------------------------------------------------------|
* | reserved (reset to 0) |
* '------------------------------------------------------------'
*
* - halt: 0 => endpoint not currently halted
* 1 => endpoint currently halted
*/
#define usb_getStatus_endpoint(halt) ( (uint16_t) (halt) )
/* - spec sec 9.4.9 (Set Feature)
* - table 9-7 (Test Mode Selectors)
*
* - in the case of a SetFeature(TEST_MODE...):
* - the most significant byte of wIndex is used to specify the test mode
* - the lower byte of wIndex must be zero, because the recipient must be the
* device
*/
// (reserved): (0x0000)
#define USB_TEST_MODE_wIndex_Test_J ( (uint16_t) (0x0100) )
#define USB_TEST_MODE_wIndex_Test_K ( (uint16_t) (0x0200) )
#define USB_TEST_MODE_wIndex_Test_SE0_NAK ( (uint16_t) (0x0300) )
#define USB_TEST_MODE_wIndex_Test_Packet ( (uint16_t) (0x0400) )
#define USB_TEST_MODE_wIndex_Test_Force_Enable ( (uint16_t) (0x0500) )
// (reserved for standard test selectors): (0x0600)..(0x3F00)
// (reserved): (0x3F00)..(0xBF00)
// (reserved for vendor-specific test modes): (0xC000)..(0xFF00)
// ----------------------------------------------------------------------------
/* - spec sec 9.6.1 (Standard USB Descriptor Definitions / Device)
* - table 9-8 (Standard Device Descriptor)
*/
struct usb_device_descriptor {
uint8_t bLength;
/* value: number
* - size of this descriptor in bytes
*/
uint8_t bDescriptorType;
/* value: constant
* - DEVICE Descriptor Type
* - a high speed capable device will set this to 2.0 (0x0200). if the
* device is full-speed or low-speed only, this version number only
* means that it'll send a request error when asked for the
* device_qualifier descriptor
*/
uint16_t bcdUSB;
/* value: binary coded decimal
* - usb spec release number
* - format: 0xJJMN, where JJ = major version, M = minor version,
* N = sub-minor version; e.g. version 2.1.3 => 0x0213
*/
uint8_t bDeviceClass;
/* value: class
* - class code (assigned by the USB-IF)
* - 0x00 => each interface within a configuration specifies its own
* class information and the various interfaces operate independently
* - 0x01..0xFE => the device supports different class specifications
* on different interfaces and the interfaces may not operate
* independently. this value identifies the class definition used
* for the aggregate interfaces
* - 0xFF => the device class is vendor-specific
*/
uint8_t bDeviceSubClass;
/* value: subclass
* - subclass code (assigned by the USB-IF)
* - qualified by bDeviceClass
* - if bDeviceClass is reset to 0, this field must be also
* - if bDeviceClass != 0xFF , all values are reserved for assignment
* by the USB-IF
*/
uint8_t bDeviceProtocol;
/* value: protocol
* - protocol code (assigned by the USB-IF)
* - qualified by bDeviceClass and bDeviceSubClass
* - if a device supports class-specific protocols on a device basis as
* opposed to an interface basis, this code identifies the protocols
* that the device uses as defined by the specification of the device
* class
* - 0x00 => the device does not use class-specific protocols on a
* device basis. however, it may use class-specific protocols on an
* interface basis
* - 0xFF => the device uses a vendor-specific protocol on a device
* basis
*/
uint8_t bMaxPacketSize0;
/* value: number
* - max packet size for endpoint 0
* - only 8, 16, 32, or 64 are valid
* - if operating at high-speed, the value must be 64
*/
uint16_t idVendor;
/* value: id
* - vendor ID (assigned by the USB-IF)
*/
uint16_t idProduct;
/* value: id
* - product ID (assigned by the manufacturer)
*/
uint16_t bcdDevice;
/* value: binary coded decimal
* - device release number
*/
uint8_t iManufacturer;
/* value: index
* - index of string descriptor describing manufacturer
*/
uint8_t iProduct;
/* value: index
* - index of string descriptor describing product
*/
uint8_t iSerialNumber;
/* value: index
* - index of string descriptor describing the device's serial number
*/
uint8_t bNumConfigurations;
/* value: number
* - number of possible configurations (at the current operating speed)
*/
};
// ----------------------------------------------------------------------------
/* - spec sec 9.6.2 (Standard USB Descriptor Definitions / Device_Qualifier)
* - table 9-9 (Device_Qualifier Descriptor)
*
* - required if the device has different device information for full-speed and
* high-speed
*
* - not valid for a full-speed only device (with a device descriptor version
* number equal to 0x0200); if requested, the device must respond with a
* request error
*/
struct usb_device_qualifier_descriptor {
uint8_t bLength;
/* value: number
* - size of descriptor
*/
uint8_t bDescriptorType;
/* value: constant
* - device qualifier type
*/
uint16_t bcdUSB;
/* value: binary coded decimal
* - usb spec release number
* - format: (see note for usb_device_descriptor.bcdUSB)
* - must be at least 2.0 (0x0200) for this descriptor
*/
uint8_t bDeviceClass;
/* value: class
*/
uint8_t bDeviceSubClass;
/* value: subclass
*/
uint8_t bDeviceProtocol;
/* value: protocol
*/
uint8_t bMaxPacketSize0;
/* value: number
* - max packet size for other speed
*/
uint8_t bNumConfigurations;
/* value: number
* - number of other-speed configurations
*/
uint8_t bReserved;
/* value: 0
* - reserved for future use
*/
};
// ----------------------------------------------------------------------------
/* - spec sec 9.6.3 (Standard USB Descriptor Definitions / Configuration)
* - table 9-10 (Standard Configuration Descriptor)
*
* - spec sec 9.6.4 (Standard USB Descriptor Definitions /
* Other_Speed_Configuration)
* - table 9-11 (Other_Speed_Configuration Descriptor)
*
* - both descriptors have the same structure. the only specified difference
* is the value of the bDescriptorType constant.
*/
struct usb_configuration_descriptor {
uint8_t bLength;
/* value: number
* - size of this descriptor in bytes
uint8_t bDescriptorType;
* value: constant
* - CONFIGURATION Descriptor Type
* (for Standard Configuration Descriptor)
* - OTHER_SPEED_CONFIGURATION Type
* (for Other Speed Configuration Descriptor)
*/
uint16_t wTotalLength;
/* value: number
* - total length of data returned for this configuration. includes
* the combined length of all descriptors (configuration, interface,
* endpoint, and class- or vendor-specific) returned for this
* configuration.
*/
uint8_t bNumInterfaces;
/* value: number
* - number of interfaces supported by this configuration
*/
uint8_t bConfigurationValue;
/* value: number
* - value to use as an argument to the SetConfiguration() request to
* select this configuration
*/
uint8_t iConfiguration;
/* value: index
* - index of string descriptor describing this configuration
*/
uint8_t bmAttributes;
/* value: bitmap
* - self-powered, remote wakeup
* (see macro below)
*/
uint8_t bMaxPower;
/* value: mA
* - max power consumption of the USB device from the bus
* (configuration specific) (when device is fully operational)
* - format: expressed in 2 mA units (i.e. value=50 => 100mA)
* - note: a device configuration reports whether the configuration is
* bus-powered or self-powered. device status reports whether the
* device is currently self-powered. if a device is disconnected
* from its external power source, it updates device status to
* indicate that. it may not increase its power draw from the bus
* beyond the amount reported by its configuration. if it can
* continue to operate, it does so. if not, it fails operations it
* can no longer support, and the host software can determine the
* cause of failure by checking the status and noting the loss of the
* device's external power.
*/
};
/* - spec sec 9.6.3 (Standard USB Descriptor Definitions / Configuration)
* - table 9-10 (Standard Configuration Descriptor)
* - bmAttributes
*
* .--------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |--------------------------------------------------------|
* | reserved | self | remote | reserved |
* | (set to 1) | powered | wakeup | (reset to 0) |
* '--------------------------------------------------------'
*
* - D7: must be set to 1 for historical reasons
*
* - self powered: 0 => false
* 1 => true
* - a device configuration that uses both bus and local power must report a
* non-zero value in bMaxPower (to indicate the amount of bus power
* required) and set D6 = 1
*
* - remote wakeup: 0 => not supported by configuration
* 1 => supported by configuration
*/
#define usb_configuration_bmAttributes(self_powered, remote_wakeup) \
( (uint8_t) ((1<<7) | ((self_powered)<<6) | ((remote_wakeup)<<5)) )
// ----------------------------------------------------------------------------
/* - spec sec 9.6.5 (Standard USB Descriptor Definitions / Interface)
* - table 9-12 (Standard Interface Descriptor)
*/
struct usb_interface_descriptor {
uint8_t bLength;
/* value: number
* - size of this descriptor in bytes
*/
uint8_t bDescriptorType;
/* value: constant
* - INTERFACE Descriptor Type
*/
uint8_t bInterfaceNumber;
/* value: number
* - number of this interface
* - zero-based value identifying the index in the array of concurrent
* interfaces supported by this configuration
*/
uint8_t bAlternateSetting;
/* value: number
* - value used to select this alternate setting for the interface
* identified in the prior field
*/
uint8_t bNumEndpoints;
/* value: number
* - number of endpoints used by this interface (excluding endpoint
* zero)
* - if this value is zero, this interface only uses the Default
* Control Pipe
*/
uint8_t bInterfaceClass;
/* value: class
* - class code (assigned by the USB-IF)
* - 0x00 => reserved for future standardization
* - 0xFF => interface class is vendor specific
* - [others] => reserved for assignment by the USB-IF
*/
uint8_t bInterfaceSubClass;
/* value: subclass
* - subclass code (assigned by the USB-IF)
* - qualified by the value of the bInterfaceClass field
* - if the bInterfaceClass field is reset to zero, this field must be
* also
* - if the bInterfaceClass field is not set to 0xFF, all values are
* reserved for assignment by the USB-IF
*/
uint8_t bInterfaceProtocol;
/* value: protocol
* - protocol code (assigned by the USB)
* - qualified by the values of the bInterfaceClass and
* bInterfaceSubClass fields
* - if an interface supports class-specific requests, this code
* identifies the protocols that the device uses as defined by the
* specification of the device class.
* - 0x00 => the device does not use a class-specific protocol on this
* interface
* - 0xFF => the device uses a vendor-specific protocol for this
* interface
*/
uint8_t iInterface;
/* value: index
* - index of string descriptor describing this interface
*/
};
// ----------------------------------------------------------------------------
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
* - table 9-13 (Standard Endpoint Descriptor)
*
* - a feedback endpoint (explicit or implicit) needs to be associated with one
* (or more) isochronous data endpoints to which it provides feedback
* service. the association is based on endpoint number matching. a
* feedback endpoint always has the opposite direction from the data
* endpoint(s) it services. if multiple data endpoints are to be serviced by
* the same feedback endpoint, the data endpoints must have ascending ordered
* (but not necessarily consecutive) endpoint numbers. the first data
* endpoint and the feedback endpoint must have the same endpoint number (and
* opposite direction). this ensures that a data endpoint can uniquely
* identify its feedback endpoint by searching for the first feedback
* endpoint that has an endpoint number equal or less than its own endpoint
* number.
* - see spec figures 9-7 and 9-8
*/
struct usb_endpoint_descriptor {
uint8_t bLength;
/* value: number
* - size of this descriptor in bytes
*/
uint8_t bDescriptorType;
/* value: constant
* - ENDPOINT Descriptor Type
*/
uint8_t bEndpointAddress;
/* value: endpoint
* - the address and direction of the endpoint described
* (see macro below)
*/
uint8_t bmAttributes;
/* value: bitmap
* - endpoint's attributes when it is configured using the
* bConfigurationValue
* - includes: transfer type
* - if transfer type == isochronous, also includes:
* synchronization type, usage type
* - (see spec chapter 5 for more information)
* - (see macros below)
*/
uint16_t wMaxPacketSize;
/* value: number
* - max packet size this endpoint is capable of sending or receiving
* when this configuration is selected
* - for isochronous endpoints, this value is used to reserve the bus
* time in the schedule, required for the per-(micro)frame data
* payloads. the pipe may, on an ongoing basis, actually use less
* bandwidth than reserved. the device reports, if necessary, the
* actual bandwidth used via its normal, non-USB defined mechanisms
* - (see spec chapter 5 for more information)
* - (see macro below)
*/
uint8_t bInterval;
/* value: number
* - interval for polling endpoint for data transfers
* - expressed in frames or microframes, depending on the device
* operating speed (i.e. either 1 ms or 125 μs units)
* - for (full|high)-speed isochronous endpoints and high-speed
* interrupt endpoints, this value must be between 1..16 . this
* value is used as the exponent for a 2^(bInterval-1) value (e.g. a
* bInterval of 4 => a period of 8 == 2^(4-1))
* - for (full|low)-speed interrupt endpoints, this value may be
* between 1..255
* - for high-speed bulk/control OUT endpoints, this value must specify
* the max NAK rate of the endpoint. a value of 0 => the endpoint
* never NAKs. other values indicate at most 1 NAK each bInterval
* number of microframes. this value must be between 0..255
* - for high-speed bulk and control OUT endpoints, this field is only
* used for compliance purposes (the host controller is not required
* to change its behavior based on the value in this field)
* - (see spec chapter 5 description of periods for more detail)
*/
};
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
* - table 9-13 (Standard Endpoint Descriptor)
* - bEndpointAddress
*
* .-------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |-------------------------------------------------------|
* | direction | reserved (reset to 0) | endpoint number |
* '-------------------------------------------------------'
*
* - D7: 0 => OUT endpoint
* 1 => IN endpoint
* - ignored for control endpoints
*/
#define usb_endpoint_bEndpointAddress(direction, endpoint_number) \
( (uint8_t) ((direction)<<7) | (endpoint_number) )
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
* - table 9-13 (Standard Endpoint Descriptor)
* - bmAttributes
*
* .------------------------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |------------------------------------------------------------------------|
* | reserved | usage type | synchronization type | transfer type |
* | (reset to 0) | (if isochronous) | (if isochronous) | |
* | |(else reset to 0) | (else reset to 0) | |
* '------------------------------------------------------------------------'
*
* - transfer type: 0b00 => control
* 0b01 => isochronous
* 0b10 => bulk
* 0b11 => interrupt
*
* - synchronization type: 0b00 => no synchronization
* 0b01 => asynchronous
* 0b10 => adaptive
* 0b11 => synchronous
* - if transfer type != isochronous, field is reset to 0
*
* - usage type: 0b00 => data endpoint
* 0b01 => feedback endpoint
* 0b10 => implicit feedback data endpoint
* 0b11 => reserved
* - if transfer type != isochronous, field is reset to 0
*
* - if usage type == feedback endpoint, then transfer type must be isochronous
* and synchronization type must be no synchronization
*/
#define usb_endpoint_bmAttributes(transfer_type) \
( (uint8_t) (transfer_type) )
#define usb_endpoint_bmAttributes_isochronous( \
synchronization_type, usage_type ) \
( (uint8_t) (0b01 | ((synchronization_type)<<2) | ((usage_type)<<4)) )
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
* - table 9-13 (Standard Endpoint Descriptor)
* - wMaxPacketSize
*
* .-----------------------------------------------------------------.
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
* |-----------------------------------------------------------------|
* | max packet size |
* | (D10..D0) |
* | |
* >---------------------------------------------------------------<
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
* |-----------------------------------------------------------------|
* | reserved | number of additional | max packet size |
* | (reset to 0) | transaction opportunities | (D10..D0) |
* | | per microframe | (continued) |
* | | (for high-speed isochronous | |
* | | and interrupt endpoints) | |
* '-----------------------------------------------------------------'
*
* - D12..D11 (additional transaction opportunities for each microframe
* specified by bInterval):
* 0b00 => none (1 transaction per microframe)
* => max packet size: 1..1024
* 0b01 => 1 additional (2 per microframe)
* => max packet size: 513..1024
* 0b10 => 2 additional (3 per microframe)
* => max packet size: 683..1024
* 0b11 => reserved
* - for high-speed isochronous and interrupt endpoints only. else reset to
* 0, and max packet size can be any allowed value (as defined in spec
* chapter 5)
*/
#define usb_endpoint_wMaxPacketSize(adtl_trans_ops, max_packet_size) \
( (uint16_t) (((adtl_trans_ops)<<11) | max_packet_size) )
// ----------------------------------------------------------------------------
/* - spec sec 9.6.7 (Standard USB Descriptor Definitions / String)
* - table 9-15 (String Descriptor Zero, Specifying Languages Supported by
* the Device)
*
* - string descriptors are optional. if a device does not support them, all
* references to them within all descriptors must be reset to 0 .
*
* - string descriptors use unicode encodings (as defined in version 3.0 of the
* unicode standard)
*
* - the strings may support multiple languages. when requesting a string
* descriptor, the requester specifies the desired language using a 16 bit
* language ID (LANGID) (defined by the USB-IF; see
* <http://www.usb.org/developers/docs.html>).
*
* - string index 0 for all languages returns a string descriptor that contains
* an array of two-byte LANGID codes supported by the device. USB devices
* that omit all string descriptors must not return an array of LANGID codes.
*/
struct usb_string_descriptor_zero {
uint8_t bLength;
/* value: N+2
* - the size of this descriptor in bytes (which equals the size of the
* array of LANGIDs (in bytes) plus two)
*/
uint8_t bDescriptorType;
/* value: constant
* - STRING Descriptor Type
*/
uint16_t (* wLANGID_ptr)[];
/* value: a pointer to the array of supported LANGID codes
* - note: these must be transmitted as part of the descriptor; a
* pointer is used here to avoid using variable length struct members
* + malloc()
*/
};
/* - spec sec 9.6.7 (Standard USB Descriptor Definitions / String)
* - table 9-16 (UNICODE String Descriptor)
*/
struct usb_string_descriptor {
uint8_t bLength;
/* value: number
* - the size of this descriptor in bytes (which equals the size of the
* string (in bytes) plus two)
*/
uint8_t bDescriptorType;
/* value: constant
* - STRING Descriptor Type
*/
uint8_t bString;
/* value: number
* - UNICODE encoded string
*/
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#pragma pack(pop)
#endif

View File

@ -0,0 +1,311 @@
/* ----------------------------------------------------------------------------
* USB Keyboard Key Codes : short names
*
* These are for convenience (and to help with formatting, keeping stuff from
* getting too long). See "keyboard-usage-page.h" for definitions and
* everything.
* ----------------------------------------------------------------------------
* 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 USB_USAGE_PAGE_KEYBOARD_SHORT_NAMES_h
#define USB_USAGE_PAGE_KEYBOARD_SHORT_NAMES_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include "keyboard.h"
// ----------------------------------------------------------------------------
// protocol
// ----------------------------------------------------------------------------
// error
#define _ErrRollover KEY_ErrorRollOver
#define _PostFail KEY_POSTFail
#define _ErrUndef KEY_ErrorUndefined
// ----------------------------------------------------------------------------
// main keyboard
// ----------------------------------------------------------------------------
// letters
#define _A KEY_a_A
#define _B KEY_b_B
#define _C KEY_c_C
#define _D KEY_d_D
#define _E KEY_e_E
#define _F KEY_f_F
#define _G KEY_g_G
#define _H KEY_h_H
#define _I KEY_i_I
#define _J KEY_j_J
#define _K KEY_k_K
#define _L KEY_l_L
#define _M KEY_m_M
#define _N KEY_n_N
#define _O KEY_o_O
#define _P KEY_p_P
#define _Q KEY_q_Q
#define _R KEY_r_R
#define _S KEY_s_S
#define _T KEY_t_T
#define _U KEY_u_U
#define _V KEY_v_V
#define _W KEY_w_W
#define _X KEY_x_X
#define _Y KEY_y_Y
#define _Z KEY_z_Z
// numbers
#define _0 KEY_0_RightParenthesis
#define _1 KEY_1_Exclamation
#define _2 KEY_2_At
#define _3 KEY_3_Pound
#define _4 KEY_4_Dollar
#define _5 KEY_5_Percent
#define _6 KEY_6_Caret
#define _7 KEY_7_Ampersand
#define _8 KEY_8_Asterisk
#define _9 KEY_9_LeftParenthesis
// function
#define _F1 KEY_F1
#define _F2 KEY_F2
#define _F3 KEY_F3
#define _F4 KEY_F4
#define _F5 KEY_F5
#define _F6 KEY_F6
#define _F7 KEY_F7
#define _F8 KEY_F8
#define _F9 KEY_F9
#define _F10 KEY_F10
#define _F11 KEY_F11
#define _F12 KEY_F12
#define _F13 KEY_F13
#define _F14 KEY_F14
#define _F15 KEY_F15
#define _F16 KEY_F16
#define _F17 KEY_F17
#define _F18 KEY_F18
#define _F19 KEY_F19
#define _F20 KEY_F20
#define _F21 KEY_F21
#define _F22 KEY_F22
#define _F23 KEY_F23
#define _F24 KEY_F24
// whitespace and symbols
#define _enter KEY_ReturnEnter
#define _space KEY_Spacebar
#define _tab KEY_Tab
// ---
#define _backslash KEY_Backslash_Pipe
#define _bracketL KEY_LeftBracket_LeftBrace
#define _bracketR KEY_RightBracket_RightBrace
#define _comma KEY_Comma_LessThan
#define _dash KEY_Dash_Underscore
#define _equal KEY_Equal_Plus
#define _grave KEY_GraveAccent_Tilde
#define _period KEY_Period_GreaterThan
#define _quote KEY_SingleQuote_DoubleQuote
#define _semicolon KEY_Semicolon_Colon
#define _slash KEY_Slash_Question
// ---
#define _sep_dec KEY_DecimalSeparator
#define _sep_thousands KEY_ThousandsSeparator
#define _currencyUnit KEY_CurrencyUnit
#define _currencySubunit KEY_CurrencySubunit
// international and language
#define _int1 KEY_International1
#define _int2 KEY_International2
#define _int3 KEY_International3
#define _int4 KEY_International4
#define _int5 KEY_International5
#define _int6 KEY_International6
#define _int7 KEY_International7
#define _int8 KEY_International8
#define _int9 KEY_International9
// ---
#define _lang1 KEY_LANG1
#define _lang2 KEY_LANG2
#define _lang3 KEY_LANG3
#define _lang4 KEY_LANG4
#define _lang5 KEY_LANG5
#define _lang6 KEY_LANG6
#define _lang7 KEY_LANG7
#define _lang8 KEY_LANG8
#define _lang9 KEY_LANG9
// ---
#define _backslash_nonUS KEY_NonUS_Backslash_Pipe
#define _pound_nonUS KEY_NonUS_Pound_Tilde
// text control
#define _bs KEY_DeleteBackspace
#define _del KEY_DeleteForward
#define _home KEY_Home
#define _end KEY_End
#define _pageU KEY_PageUp
#define _pageD KEY_PageDown
#define _arrowU KEY_UpArrow
#define _arrowD KEY_DownArrow
#define _arrowL KEY_LeftArrow
#define _arrowR KEY_RightArrow
#define _esc KEY_Escape
#define _insert KEY_Insert
// modifier
#define _altL KEY_LeftAlt
#define _altR KEY_RightAlt
#define _ctrlL KEY_LeftControl
#define _ctrlR KEY_RightControl
#define _guiL KEY_LeftGUI
#define _guiR KEY_RightGUI
#define _shiftL KEY_LeftShift
#define _shiftR KEY_RightShift
// lock
#define _capsLock KEY_CapsLock
#define _scrollLock KEY_ScrollLock
// (numlock is under keypad)
// --- not generally used
#define _capsLock_locking KEY_LockingCapsLock
#define _numLock_locking KEY_LockingNumLock
#define _scrollLock_locking KEY_LockingScrollLock
// special function
#define _pause KEY_Pause
#define _print KEY_PrintScreen
// ---
#define _application KEY_Application
#define _execute KEY_Execute
#define _power KEY_Power
// ---
#define _help KEY_Help
#define _menu KEY_Menu
// ---
#define _cut KEY_Cut
#define _copy KEY_Copy
#define _paste KEY_Paste
#define _find KEY_Find
#define _select KEY_Select
#define _stop KEY_Stop
#define _undo KEY_Undo
// ---
#define _mute KEY_Mute
#define _volumeU KEY_VolumeUp
#define _volumeD KEY_VolumeDown
// ---
#define _altErase KEY_AlternateErase
// ---
#define _again KEY_Again
#define _cancel KEY_Cancel
#define _clear_again KEY_Clear_Again
#define _clear KEY_Clear
#define _oper KEY_Oper
#define _out KEY_Out
#define _prior KEY_Prior
#define _return KEY_Return
#define _separator KEY_Separator
// ---
#define _crSel KEY_CrSel_Props
#define _exSel KEY_ExSel
#define _sysReq KEY_SysReq_Attention
// ----------------------------------------------------------------------------
// keypad
// ----------------------------------------------------------------------------
// numbers and hex letters
#define _1_kp KEYPAD_1_End
#define _2_kp KEYPAD_2_DownArrow
#define _3_kp KEYPAD_3_PageDown
#define _4_kp KEYPAD_4_LeftArrow
#define _5_kp KEYPAD_5
#define _6_kp KEYPAD_6_RightArrow
#define _7_kp KEYPAD_7_Home
#define _8_kp KEYPAD_8_UpArrow
#define _9_kp KEYPAD_9_PageUp
#define _0_kp KEYPAD_0_Insert
#define _A_kp KEYPAD_A
#define _B_kp KEYPAD_B
#define _C_kp KEYPAD_C
#define _D_kp KEYPAD_D
#define _E_kp KEYPAD_E
#define _F_kp KEYPAD_F
// ---
#define _00_kp KEYPAD_00
#define _000_kp KEYPAD_000
// whitespace and symbols
#define _tab_kp KEYPAD_Tab
#define _space_kp KEYPAD_Space
#define _enter_kp KEYPAD_ENTER
// ---
#define _dec_del_kp KEYPAD_Period_Delete
#define _comma_kp KEYPAD_Comma
#define _equal_kp KEYPAD_Equal
#define _equalSign_kp KEYPAD_EqualSign
#define _parenL_kp KEYPAD_LeftParenthesis
#define _parenR_kp KEYPAD_RightParenthesis
#define _braceL_kp KEYPAD_LeftBrace
#define _braceR_kp KEYPAD_RightBrace
// operations
// --- basic
#define _add_kp KEYPAD_Plus
#define _sub_kp KEYPAD_Minus
#define _mul_kp KEYPAD_Asterisk
#define _div_kp KEYPAD_Slash
#define _plusMinus_kp KEYPAD_PlusMinus
// --- logical
#define _lt_kp KEYPAD_LessThan
#define _gt_kp KEYPAD_GreaterThan
#define _xor_kp KEYPAD_XOR
#define _and_kp KEYPAD_Ampersand
#define _andand_kp KEYPAD_AmpersandAmpersand
#define _pipe_kp KEYPAD_Pipe
#define _pipepipe_kp KEYPAD_PipePipe
#define _caret_kp KEYPAD_Caret
#define _exclamation_kp KEYPAD_Exclamation
// --- other
#define _at_kp KEYPAD_At
#define _colon_kp KEYPAD_Colon
#define _percent_kp KEYPAD_Percent
#define _pound_kp KEYPAD_Pound
// radix
#define _bin_kp KEYPAD_Binary
#define _oct_kp KEYPAD_Octal
#define _dec_kp KEYPAD_Decimal
#define _hex_kp KEYPAD_Hexadecimal
// text control
#define _bs_kp KEYPAD_Backspace
#define _clear_kp KEYPAD_Clear
#define _clearEntry_kp KEYPAD_ClearEntry
// lock
#define _numLock_kp KEYPAD_NumLock_Clear
// memory control
#define _memStore_kp KEYPAD_MemoryStore
#define _memRecall_kp KEYPAD_MemoryRecall
#define _memClear_kp KEYPAD_MemoryClear
#define _memAdd_kp KEYPAD_MemoryAdd
#define _memSub_kp KEYPAD_MemorySubtract
#define _memMul_kp KEYPAD_MemoryMultiply
#define _memDiv_kp KEYPAD_MemoryDivide
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -21,6 +21,12 @@
* ------------------------------------------------------------------------- */
#ifndef USB_USAGE_PAGE_KEYBOARD_h
#define USB_USAGE_PAGE_KEYBOARD_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Name ID // PC Mac Unix Boot Keyboard Req.
// --------------------------- ---- -- --- ---- ---------------------
@ -241,7 +247,7 @@
#define KEYPAD_MemorySubtract 0xD4 // - - - -
#define KEYPAD_MemoryMultiply 0xD5 // - - - -
#define KEYPAD_MemoryDivide 0xD6 // - - - -
#define KEYPAD_PlusMinux 0xD7 // - - - -
#define KEYPAD_PlusMinus 0xD7 // - - - -
#define KEYPAD_Clear 0xD8 // - - - -
#define KEYPAD_ClearEntry 0xD9 // - - - -
#define KEYPAD_Binary 0xDA // - - - -
@ -262,3 +268,8 @@
// (Reserved) 0xE8..0xFFFF // - - - -
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -20,6 +20,12 @@
* ------------------------------------------------------------------------- */
#ifndef USB_USAGE_PAGE_LED_h
#define USB_USAGE_PAGE_LED_h
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Name ID Usage Type Section of HID Tables
// --------------------------- ---- ---------- ----------------------
@ -104,3 +110,9 @@
#define LED_ExternalPowerConnected 0x4D // OOC 11.6
// (Reserved) 0x4E..0xFFFF // - -
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#endif

View File

@ -9,37 +9,22 @@
#include <util/delay.h>
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
#include "lib/data-types.h"
#include "keyboard.h"
// note:
// - see your keyswitch specification for the necessary value. for cherry mx
// switches, bounce time should be <= 5ms. it looks like most switches are
// speced between 5 and 8ms.
// - if timing is important, balance this value with the main() loop run time
// (~5ms, last i checked, nearly all of it in the i2c update() function)
#define DEBOUNCE_TIME 5 // in ms
int main(void) {
kb_init(); // does controller initialization too
KB_LED1_ON;
KB_LED2_ON;
KB_LED3_ON;
kb_led_state_power_on();
usb_init();
while (!usb_configured());
_delay_ms(1000); // make sure the OS has had time to load drivers, etc.
kb_led_delay_usb_init(); // give the OS time to load drivers, etc.
KB_LED1_OFF;
KB_LED2_OFF;
KB_LED3_OFF;
kb_led_state_ready();
for (;;) {
static uint8_t current_layer = 0;
@ -51,12 +36,12 @@ int main(void) {
kb_update_matrix(*kb_is_pressed);
// call the appropriate function for each key, then send the report if
// necessary
// 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 "key-functions.c" for
// their definitions
// keyboard layout file ("keyboard/ergodox/layout/*.c") for which key
// is assigned which function (per layer), and "lib/key-functions.c"
// for their definitions
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];
@ -64,36 +49,39 @@ int main(void) {
if (is_pressed != was_pressed) {
if (is_pressed) {
kbfun_funptr_t press_function =
kb_layout_press[current_layer][row][col];
kb_layout_press_get(current_layer, row, col);
if (press_function) {
(*press_function)(
&kb_layout[current_layer][row][col],
kb_layout_get(current_layer, row, col),
&current_layer, &row, &col );
}
} else {
kbfun_funptr_t release_function =
kb_layout_release[current_layer][row][col];
kb_layout_release_get(current_layer, row, col);
if (release_function) {
(*release_function)(
&kb_layout[current_layer][row][col],
kb_layout_get(current_layer, row, col),
&current_layer, &row, &col );
}
}
usb_keyboard_send();
_delay_ms(DEBOUNCE_TIME);
_delay_ms(KB_DEBOUNCE_TIME);
}
}
}
// update LEDs
(keyboard_leds & (1<<0)) ? KB_LED1_ON : KB_LED1_OFF; // num lock
(keyboard_leds & (1<<1)) ? KB_LED2_ON : KB_LED2_OFF; // caps lock
(keyboard_leds & (1<<2)) ? KB_LED3_ON : KB_LED3_OFF; // scroll lock
#if 0 // not implemented right now
(keyboard_leds & (1<<3)) ? KB_LED4_ON : KB_LED4_OFF; // compose
(keyboard_leds & (1<<4)) ? KB_LED5_ON : KB_LED5_OFF; // kana
#endif
if (keyboard_leds & (1<<0)) { kb_led_num_on(); }
else { kb_led_num_off(); }
if (keyboard_leds & (1<<1)) { kb_led_caps_on(); }
else { kb_led_caps_off(); }
if (keyboard_leds & (1<<2)) { kb_led_scroll_on(); }
else { kb_led_scroll_off(); }
if (keyboard_leds & (1<<3)) { kb_led_compose_on(); }
else { kb_led_compose_off(); }
if (keyboard_leds & (1<<4)) { kb_led_kana_on(); }
else { kb_led_kana_off(); }
}
return 0;

View File

@ -1,6 +1,11 @@
# -----------------------------------------------------------------------------
# This is mostly a stub at the moment, but I'm keeping it separate so I can
# mess with it later without changing the original
# makefile for the ergoDOX project
#
# - .h file dependencies are automatically generated
#
# - This makefile was originally (extensively) modified from the WinAVR
# makefile template, mostly by removing stuff. The copy I used was from
# [pjrc : usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip).
# -----------------------------------------------------------------------------
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (MIT) (see "license.md")
@ -8,33 +13,149 @@
# -----------------------------------------------------------------------------
TARGET = firmware
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
SRC = $(wildcard *.c) \
$(wildcard keyboard/*.c) \
$(wildcard keyboard/*/*.c) \
$(wildcard lib/*.c) \
$(wildcard lib/*/*.c) \
'./lib-other/pjrc/usb_keyboard/usb_keyboard.c'
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)
# keyboard and layout stuff
# --- remove whitespace from vars
KEYBOARD := $(strip $(KEYBOARD))
LAYOUT := $(strip $(LAYOUT))
# --- include stuff
SRC += $(wildcard keyboard/$(KEYBOARD)*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/*.c)
SRC += $(wildcard keyboard/$(KEYBOARD)/layout/$(LAYOUT)*.c)
# library stuff
# - add more "*/*/..."s as necessary to compile everything.
# - parts of the stuff under "lib" may not be necessary, depending on other
# options, but it's all included here. hopefully any unnecessary stuff gets
# compiled out. else, the makefile will have to become more complicated.
SRC += $(wildcard lib/*.c)
SRC += $(wildcard lib/*/*.c)
SRC += $(wildcard lib/*/*/*.c)
SRC += $(wildcard lib-other/*.c)
SRC += $(wildcard lib-other/*/*.c)
SRC += $(wildcard lib-other/*/*/*.c)
OBJ = $(SRC:%.c=%.o)
EXTRAINCDIRS = .
TEENSY_MAKE = $(MAKE) -f 'lib-other/pjrc/usb_keyboard/Makefile' \
TARGET='$(TARGET)' \
SRC='$(SRC)' \
EXTRAINCDIRS='$(EXTRAINCDIRS)'
CFLAGS = -mmcu=$(MCU) # processor type (teensy 2.0); must match real
# life
CFLAGS += -DF_CPU=$(F_CPU) # processor frequency; must match initialization
# in source
CFLAGS += -I. # search for includes in the current directory
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -DMAKEFILE_BOARD='$(strip $(BOARD))'
CFLAGS += -DMAKEFILE_KEYBOARD='$(strip $(KEYBOARD))'
CFLAGS += -DMAKEFILE_KEYBOARD_LAYOUT='$(strip $(LAYOUT))'
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -std=gnu99 # use C99 plus GCC extensions
CFLAGS += -Os # optimize for size
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -Wall # enable lots of common warnings
CFLAGS += -Wstrict-prototypes # "warn if a function is declared or defined
# without specifying the argument types"
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -fpack-struct # "pack all structure members together without holes"
CFLAGS += -fshort-enums # "allocate to an 'enum' type only as many bytes as it
# needs for the declared range of possible values"
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
CFLAGS += -ffunction-sections # \ "place each function or data into its own
CFLAGS += -fdata-sections # / section in the output file if the
# target supports arbitrary sections." for
# linker optimizations, and discarding
# unused code.
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
LDFLAGS = -Wl,--relax # for some linker optimizations
LDFLAGS += -Wl,--gc-sections # discard unused functions and data
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
GENDEPFLAGS += -MMD -MP -MF $@.dep # generate dependency files
.PHONY: all clean debug
CC = avr-gcc
OBJCOPY = avr-objcopy
SIZE = avr-size
all:
$(TEENSY_MAKE) all
# remove whitespace from some of the variables
TARGET := $(strip $(TARGET))
FORMAT := $(strip $(FORMAT))
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
.PHONY: all clean
all: $(TARGET).hex $(TARGET).eep
@echo
@echo '---------------------------------------------------------------'
@echo '------- done --------------------------------------------------'
@echo
$(SIZE) --target=$(FORMAT) $(TARGET).hex
@echo
$(SIZE) --target=$(FORMAT) $(TARGET).eep
@echo
@echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
@echo
$(SIZE) -C --mcu=atmega32u4 $(TARGET).elf
@echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
@echo
@echo 'you can load "$(TARGET).hex" and "$(TARGET).eep" onto the'
@echo 'Teensy using the Teensy loader'
@echo
@echo '---------------------------------------------------------------'
@echo
clean:
$(TEENSY_MAKE) clean
git clean -X
@echo
@echo --- cleaning ---
cd .. ; git clean -dX # remove ignored files and directories
debug:
$(TEENSY_MAKE) debug
# -----------------------------------------------------------------------------
.SECONDARY:
%.hex: %.elf
@echo
@echo --- making $@ ---
# from the WinAVR makefile template (modified)
$(OBJCOPY) -O $(FORMAT) \
-R .eeprom -R .fuse -R .lock -R .signature \
$< $@
%.eep: %.elf
@echo
@echo --- making $@ ---
# from the WinAVR makefile template (modified)
-$(OBJCOPY) -O $(FORMAT) \
-j .eeprom \
--set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 \
--no-change-warnings \
$< $@ || exit 0
%.elf: $(OBJ)
@echo
@echo --- making $@ ---
$(CC) $(strip $(CFLAGS)) $(strip $(LDFLAGS)) $^ --output $@
%.o: %.c
@echo
@echo --- making $@ ---
$(CC) -c $(strip $(CFLAGS)) $(strip $(GENDEPFLAGS)) $< -o $@
# -----------------------------------------------------------------------------
-include $(OBJ:%=%.dep)

View File

@ -1,38 +0,0 @@
# -----------------------------------------------------------------------------
# This is mostly a stub at the moment, but I'm keeping it separate so I can
# mess with it later without changing the original
# -----------------------------------------------------------------------------
# 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>
# -----------------------------------------------------------------------------
TARGET = test
EXTRAINCDIRS = ..
TEENSY_MAKE = $(MAKE) -f '../lib-other/pjrc/blinky/Makefile' \
TARGET='$(TARGET)' \
EXTRAINCDIRS='$(EXTRAINCDIRS)'
.PHONY: test_pwm test_twi test_twi_2
test_pwm:
$(TEENSY_MAKE) all \
SRC='test_pwm.c'
test_twi:
$(TEENSY_MAKE) all \
SRC='test_twi.c'
test_twi_2:
$(TEENSY_MAKE) all \
SRC='test_twi_2.c'
.PHONY: clean
clean:
$(TEENSY_MAKE) clean \
SRC='$(shell find -name '*.c')'

View File

@ -1,12 +0,0 @@
# src/test
Files used for testing (at some point)
I'm keeping these around for reference; they probably won't be maintained, and
are quite likely to become broken at some point in the future.
-------------------------------------------------------------------------------
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

@ -1,85 +0,0 @@
/* ----------------------------------------------------------------------------
* Test the Teensy 2.0 PWM code (see `#include`s)
* ----------------------------------------------------------------------------
* 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 <util/delay.h>
#include <avr/io.h>
#define bool _Bool
#define true 1
#define false 0
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
// LED control
#define KB_LED1_ON (DDRB |= (1<<5))
#define KB_LED1_OFF (DDRB &= ~(1<<5))
#define KB_LED1_SET(n) (OCR1A = (uint8_t)(n))
#define KB_LED1_SET_PERCENT(n) (OCR1A = (uint8_t)((n) * 0xFF))
#define KB_LED2_ON (DDRB |= (1<<6))
#define KB_LED2_OFF (DDRB &= ~(1<<6))
#define KB_LED2_SET(n) (OCR1B = (uint8_t)(n))
#define KB_LED2_SET_PERCENT(n) (OCR1B = (uint8_t)((n) * 0xFF))
#define KB_LED3_ON (DDRB |= (1<<7))
#define KB_LED3_OFF (DDRB &= ~(1<<7))
#define KB_LED3_SET(n) (OCR1C = (uint8_t)(n))
#define KB_LED3_SET_PERCENT(n) (OCR1C = (uint8_t)((n) * 0xFF))
int main(void) {
CPU_PRESCALE(0); // set for 16MHz
// pwm init for keyboard LEDs
// (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
DDRB |= 0b11100000; // set B(7,6,5) as output
TCCR1A = 0b10101001; // set and configure fast PWM
TCCR1B = 0b00001001; // set and configure fast PWM
for (uint8_t i=0; i<3; i++) {
KB_LED1_SET(0x10);
KB_LED2_SET(0x20);
KB_LED3_SET(0xFF);
_delay_ms(500);
KB_LED1_SET(0x20);
KB_LED2_SET(0xFF);
KB_LED3_SET(0x10);
_delay_ms(500);
KB_LED1_SET(0xFF);
KB_LED2_SET(0x10);
KB_LED3_SET(0x20);
_delay_ms(500);
}
for (uint8_t i=0; i<2; i++) {
KB_LED1_OFF;
KB_LED2_OFF;
KB_LED3_OFF;
_delay_ms(500);
KB_LED1_ON;
KB_LED2_ON;
KB_LED3_ON;
_delay_ms(500);
}
bool counting_up = true;
for (uint8_t i=0;;) {
(counting_up) ? i++ : i--;
if (i == 0xFF)
counting_up = false;
else if (i == 0)
counting_up = true;
KB_LED1_SET(i/2);
KB_LED2_SET(i/2);
KB_LED3_SET(i/2);
_delay_ms(10);
}
}

View File

@ -1,105 +0,0 @@
/* ----------------------------------------------------------------------------
* Test for ACK on address write (with a Teensy 2.0 and I/O expander)
* ----------------------------------------------------------------------------
* 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 <avr/io.h>
#include <util/twi.h>
#include <util/delay.h>
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
#define CPU_16MHz 0x00
#define CPU_8MHz 0x01
#define CPU_4MHz 0x02
#define CPU_2MHz 0x03
#define CPU_1MHz 0x04
#define CPU_500kHz 0x05
#define CPU_250kHz 0x06
#define CPU_125kHz 0x07
#define CPU_62kHz 0x08
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
#define blink_led(time1, time2) { \
/* Teensy 2.0 onboard LED on PD6
on high, off low */ \
PORTD |= (1<<6); \
_delay_ms(time1); \
PORTD &= ~(1<<6); \
_delay_ms(time2); \
}
// ---------------------------------------------------------------------------- // TWI
// ----------------------------------------------------------------------------
void twi_init(void) {
TWSR &= ~( (1<<TWPS1)|(1<<TWPS0) );
TWBR = ((F_CPU / 100000) - 16) / 2;
// TWSR |= (1<<TWPS1)|(1<<TWPS0); //dbg
// TWBR = 0xFF; //dbg
}
uint8_t twi_start(void) {
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_START)
return TWSR & 0xF8; // error
}
void twi_stop(void) {
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
while (TWCR & (1<<TWSTO));
}
uint8_t twi_send(uint8_t data) {
TWDR = data;
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
return TWSR & 0xF8; // error
}
// ----------------------------------------------------------------------------
// main
// ----------------------------------------------------------------------------
void main(void) {
CPU_PRESCALE(CPU_16MHz);
uint8_t ret;
twi_init();
for (uint8_t i=0;; i+=2) { // try all even (write) addresses
twi_start();
ret = twi_send(i); // i = address
twi_stop();
if (ret == 0x18) // SLA+W sent; ACK received
break;
if (i == 0xFE) // all done
break;
}
// blink the return value
// --- initial blink (get ready)
blink_led(700, 200);
// --- 1st hex number
for (uint8_t i=0; i<(ret/0x10); i++) {
blink_led(200, 100);
}
_delay_ms(400);
// --- 2nd hex number
for (uint8_t i=0; i<(ret%0x10); i++) {
blink_led(200, 100);
}
}

View File

@ -1,92 +0,0 @@
/* ----------------------------------------------------------------------------
* Test TWI write (with a Teensy 2.0 and I/O expander)
* ----------------------------------------------------------------------------
* 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 <avr/io.h>
#include <util/twi.h>
#include <util/delay.h>
#define TWI_FREQ 400000
#include "../lib/teensy-2-0/twi.c"
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
#define CPU_16MHz 0x00
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
#define blink_led(time1, time2) { \
/* Teensy 2.0 onboard LED on PD6
on high, off low */ \
PORTD |= (1<<6); \
_delay_ms(time1); \
PORTD &= ~(1<<6); \
_delay_ms(time2); \
}
// ---------------------------------------------------------------------------- // TWI
// ----------------------------------------------------------------------------
#define IODIRA 0x00
#define IODIRB 0x01
#define GPPUA 0x0C
#define GPPUB 0x0D
#define GPIOA 0x12
#define GPIOB 0x13
#define OLATA 0x14
#define OLATB 0x15
#define TWI_ADDR_WRITE (0b0100000<<1)|TW_WRITE
#define TWI_ADDR_READ (0b0100000<<1)|TW_READ
// ----------------------------------------------------------------------------
// main
// ----------------------------------------------------------------------------
/* notes:
* - won't work without the `twi_stop()`s after each block
*/
int main(void) {
CPU_PRESCALE(CPU_16MHz);
twi_init();
// set all gpio pins as:
// output
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(IODIRA);
twi_send(0);
twi_send(0);
twi_stop();
// with pull-up
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(GPPUA);
twi_send(0xff);
twi_send(0xff);
twi_stop();
// logical 1
twi_start();
twi_send(TWI_ADDR_WRITE);
twi_send(OLATA);
twi_send(0xff);
twi_send(0xff);
twi_stop();
return 0;
}