1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- #include "RowBase.h"
- /*
- process() scans the row and calls any newly pressed or released keys.
- */
- void RowBase::process()
- {
- //these variables are all bitwise, one bit per key
- uint8_t rowState; //1 means pressed, 0 means released
- uint16_t rowEnd; //1 bit marks positioned after last key of row
- uint8_t debouncedChanged; //1 means debounced changed
-
- wait();
- rowState = scan(rowEnd);
- debouncedChanged = debounce(rowState, debounced);
- pressRelease(rowEnd, debouncedChanged);
- }
-
- /* wait() delay's scan to give switches time to debounce.
- This version of wait() is very simple. More sophisticated versions can override this one.
-
- For fastest response time, wait() should be placed before scan() or after pressRelease()
- (waiting between strobe and send would unnecessarily delay send).
-
- A keyboard with a faster scan rate responds faster.
- Follow these step to tune DELAY_MICROSECONDS for maximum scan rate for a given SAMPLE_COUNT:
- Initialize DELAY_MICROSECONDS in your sketch:
- const unsigned int RowBase::DELAY_MICROSECONDS = 1000;
- Add this to the sketch's loop() function:
- debug.print_microseconds_per_scan();
- Compile and load the sketch into the microcontroller; microseconds_per_scan is printed every second.
- Adjust the value of DELAY_MICROSECONDS and repeat until:
- debug.print_microseconds_per_scan() <= DEBOUNCE_TIME / SAMPLE_COUNT
-
- DEBOUNCE_TIME can be obtained from the switch's datasheet. Some switch bounce times are:
- Cherry MX specifies 5msec bounce time http://www.cherrycorp.com/english/switches/key/mx.htm
- hasu measured Cherry MX bounce times .3ms to 1.4ms http://geekhack.org/index.php?topic=42385.0
- Tactile switch MJTP series bounce 10 ms http://www.apem.com/files/apem/brochures/MJTP_6MM.pdf
-
- Avoid sampling the switch input at a rate synchronous to events in the environment
- that might create periodic EMI. For instance, 50 and 60 Hz.
-
- The largest allowable DELAY_MICROSECONDS is 65535 (.065535 seconds).
-
- Polling I2C may slow the scan rate enough so that no additional delay is needed:
- const unsigned int RowBase::DELAY_MICROSECONDS = 0;
- */
- void RowBase::wait()
- {
- delayMicroseconds(DELAY_MICROSECONDS); //delay between Row scans to debounce switches
- }
-
- /*
- pressRelease() calls key's press() or release() function if it was pressed or released.
- Both parameters are bitwise.
- rowEnd bit marks positioned immediatly after last key of row.
- */
- void RowBase::pressRelease(const uint16_t rowEnd, const uint8_t debouncedChanged)
- {
- uint8_t isFallingEdge; //1 means falling edge
- uint8_t isRisingEdge; //1 means rising edge
- uint8_t rowMask; //bitwise, active col bit is 1
- uint8_t col; //index for ptrsKeys[col] array
-
- //bit=1 if last debounced changed from 1 to 0, else bit=0
- isFallingEdge = debouncedChanged & ~debounced;
-
- //bit=1 if last debounced changed from 0 to 1, else bit=0
- isRisingEdge = debouncedChanged & debounced;
-
- for (rowMask=1, col=0; rowMask<rowEnd; rowMask<<=1, col++) //for each key in row
- {
- //release before press avoids impossible key sequence
- if (rowMask & isFallingEdge) //if key was released
- {
- ptrsKeys[col]->release();
- }
-
- if (rowMask & isRisingEdge) //if key was pressed
- {
- ptrsKeys[col]->press();
- keyWasPressed();
- }
- }
- }
-
- void RowBase::keyWasPressed()
- {
- //empty in RowBase class. To unstick sticky keys, override keyWasPressed() in derived class.
- }
|