finished timer code; now using in main()
untested, but it should work. i'll test before pushing to github, and update if i messed anything uppartial-rewrite
parent
5e1877cb82
commit
a7d11e0af2
|
@ -103,7 +103,7 @@
|
|||
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=606865&viewfull=1#post606865).
|
||||
Before adding a delay we were having [strange problems with ghosting]
|
||||
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=605857&viewfull=1#post605857).
|
||||
|
||||
|
||||
|
||||
### PWM on ports OC1(A|B|C) (see datasheet section 14.10)
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* Timer interface
|
||||
*
|
||||
* Prefix: `timer__`
|
||||
*
|
||||
* `timer__init()` is meant to be called once, on startup, by `main()`
|
||||
*/
|
||||
|
||||
|
||||
|
@ -17,7 +19,29 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// TODO
|
||||
void timer__init(void);
|
||||
/** functions/timer__init/description
|
||||
* Initialize the timer
|
||||
*/
|
||||
|
||||
uint32_t timer__get_milliseconds(void);
|
||||
/** functions/timer__get_milliseconds/description
|
||||
* Return the number of milliseconds since the timer was initialized (mod 2^32)
|
||||
*
|
||||
* Usage notes:
|
||||
*
|
||||
* - It's unnecessary to keep 32-bit (or even 16-bit) resolution when storing
|
||||
* the value returned by `timer__get_milliseconds()` if you don't need it.
|
||||
* Casting to a smaller unsigned value should be safe (as long as you cast
|
||||
* *all* the values you plan to compare with each other to the same type!).
|
||||
*
|
||||
* - Use `end_time - start_time` for determining time difference. Since the
|
||||
* returned values are unsigned (and you should be storing them in unsigned
|
||||
* variables as well) this will work across overflows, for up to the maximum
|
||||
* amount of milliseconds representable by the type you're using. (See [this
|
||||
* answer] (http://stackoverflow.com/a/50632) on <http://stackoverflow.com/>
|
||||
* if you're curious as to why.)
|
||||
*/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -5,28 +5,11 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/** description
|
||||
* Implements the time defined in "../timer.h" for the ATMega32U4
|
||||
* Implements the timer functions defined in "../timer.h" for the ATMega32U4
|
||||
*
|
||||
* Prefix: `timer__`
|
||||
*
|
||||
* `timer__init()` is meant to be called once, on startup, by `main()`
|
||||
*
|
||||
* See the accompanying '.md' file for more documentation.
|
||||
*
|
||||
*
|
||||
* Usage Notes:
|
||||
*
|
||||
* - It's unnecessary to keep 32-bit (or even 16-bit) resolution when storing
|
||||
* the value returned by `timer__get_milliseconds()` if you don't need it.
|
||||
* Casting to a smaller unsigned value should be safe (as long as you cast
|
||||
* *all* the values you plan to compare with each other to the same type!).
|
||||
*
|
||||
* - Use `end_time - start_time` for determining time difference. Since the
|
||||
* returned values are unsigned (and you should be storing them in unsigned
|
||||
* variables as well) this will work across overflows, for up to the maximum
|
||||
* amount of milliseconds representable by the type you're using. (See [this
|
||||
* answer] (http://stackoverflow.com/a/50632) on <http://stackoverflow.com/>
|
||||
* if you're curious as to why.)
|
||||
* See the accompanying '.md' file for documentation.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -52,7 +35,6 @@ uint32_t timer__get_milliseconds(void) {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: document this in the '.md' file too
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
_milliseconds++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
## 8-bit Timer/Counter Register Description (see datasheet section 13.8)
|
||||
|
||||
TCCR0A : Timer/Counter Control Register A
|
||||
.---------------------------------------------------------------.
|
||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
|---------------------------------------------------------------|
|
||||
| COM0A | COM0A | COM0B | COM0B | Reserved | WGM1 | WGM0 |
|
||||
'---------------------------------------------------------------'
|
||||
|
||||
TCCR0B : Timer/Counter Control Register B
|
||||
.---------------------------------------------------------------.
|
||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
|---------------------------------------------------------------|
|
||||
| FOC0A | FOC0B | Reserved | WGM02 | CS02 | CS01 | CS00 |
|
||||
'---------------------------------------------------------------'
|
||||
|
||||
* We want:
|
||||
* `COM0A` = `0b10` : Clear `OC0A` on Compare Match
|
||||
* `COM0B` = `0b00` : Normal port operation, `OC0B` disconnected
|
||||
* `WGM` = `0b010` : CTC (see section 13.6.2 "Clear Timer on Compare
|
||||
Match (CTC) Mode")
|
||||
* `CS` = `0b011` : clk_i/o / 64 (from prescaler)
|
||||
|
||||
|
||||
TIMSK0 : Timer/Counter Interrupt Mask Register
|
||||
.-----------------------------------------------------------------.
|
||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
|-----------------------------------------------------------------|
|
||||
| Reserved | OCIE0B | OCIE0A | TOIE0 |
|
||||
'-----------------------------------------------------------------'
|
||||
|
||||
* We want:
|
||||
* `OCIE0A` = `0b1` : enable the Timer/Counter0 Compare Match A
|
||||
interrupt
|
||||
|
||||
|
||||
* We also want to set `OCR0A` (Output Compare Register A) to `250`
|
||||
|
||||
* Since we're using CTC mode with `OCIE0A` enabled, we will be using the
|
||||
`TIMER0_COMPA_vect` interrupt vector (see
|
||||
[the avr-libc documentation on interrupts]
|
||||
(http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html)).
|
||||
|
||||
|
||||
## Other Notes
|
||||
|
||||
* References:
|
||||
|
||||
* [Newbie's Guide to AVR Timers]
|
||||
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106)
|
||||
: tutorial lby Deana Camera
|
||||
|
||||
|
||||
* For a CPU frequency of 16 MHz:
|
||||
|
||||
--------------------------------------------
|
||||
prescale value ticks per millisecond
|
||||
---------------- -----------------------
|
||||
1 16000
|
||||
8 2000
|
||||
64 250
|
||||
256 62.5
|
||||
1024 15.625
|
||||
--------------------------------------------
|
||||
|
||||
* So if we set the prescaler to 64, we can just barely get to a millisecond
|
||||
within the range of an 8-bit counter (2^8-1 = 255, and we need 250
|
||||
ticks).
|
||||
|
||||
|
||||
* Abbreviations:
|
||||
* `COM`: Compare
|
||||
* `CS`: Clock Select
|
||||
* `FOC`: Force Output Compare
|
||||
* `TCCR: Timer/Counter Control Register
|
||||
* `TIMSK`: Timer/Counter Interrupt Mask Register
|
||||
* `WGM`: Waveform Generation Module
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2013 Ben Blazak <benblazak.dev@gmail.com>
|
||||
Released under The MIT License (see "doc/licenses/MIT.md")
|
||||
Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
#include "../firmware/keyboard.h"
|
||||
#include "../firmware/lib/timer.h"
|
||||
#include "../firmware/lib/usb.h"
|
||||
#include "./main.h"
|
||||
|
||||
|
@ -65,7 +66,9 @@ int main(void) {
|
|||
static bool key_is_pressed;
|
||||
static bool key_was_pressed;
|
||||
|
||||
kb__init(); // initialize hardware (besides USB)
|
||||
static uint8_t time_scan_started;
|
||||
|
||||
kb__init(); // initialize hardware (besides USB and timer)
|
||||
|
||||
kb__led__state__power_on();
|
||||
|
||||
|
@ -73,13 +76,24 @@ int main(void) {
|
|||
while (!usb__is_configured());
|
||||
kb__led__delay__usb_init(); // give the OS time to load drivers, etc.
|
||||
|
||||
timer__init();
|
||||
|
||||
kb__led__state__ready();
|
||||
|
||||
time_scan_started // first iteration, scan immediately
|
||||
= (uint8_t)timer__get_milliseconds() - OPT__DEBOUNCE_TIME;
|
||||
|
||||
for(;;) {
|
||||
temp = is_pressed;
|
||||
is_pressed = was_pressed;
|
||||
was_pressed = temp;
|
||||
|
||||
// delay if necessary, then rescan
|
||||
// - add 1 to `OPT__DEBOUNCE_TIME` in case `time_scan_started` caught
|
||||
// the tail end of the millisecond it recorded
|
||||
while( (uint8_t)timer__get_milliseconds() - time_scan_started
|
||||
< OPT__DEBOUNCE_TIME + 1 );
|
||||
time_scan_started = timer__get_milliseconds();
|
||||
kb__update_matrix(*is_pressed);
|
||||
|
||||
// "execute" keys that have changed state
|
||||
|
@ -94,7 +108,6 @@ int main(void) {
|
|||
}
|
||||
|
||||
usb__kb__send_report(); // (even if nothing's changed)
|
||||
_delay_ms(OPT__DEBOUNCE_TIME);
|
||||
|
||||
// note: only use the `kb__led__logical...` functions here, since the
|
||||
// meaning of the physical LEDs should be controlled by the layout
|
||||
|
|
Loading…
Reference in New Issue