// Strobe lines are detected at startup, extra strobes cause anomalies like phantom keypresses
#define MAX_STROBES 18
+// Number of consecutive samples required to pass debounce
+#define DEBOUNCE_THRESHOLD 5
+
#define MUXES_COUNT 8
#define MUXES_COUNT_XSHIFT 3
uint16_t keys_averages_acc[KEY_COUNT];
uint16_t keys_averages [KEY_COUNT];
+uint8_t keys_debounce [KEY_COUNT];
uint8_t full_samples[KEY_COUNT];
int sampleColumn( uint8_t column );
+void capsense_scan( void );
+
void setup_ADC( void );
void strobe_w( uint8_t strobe_num );
// Strobes start at 0 and go to 17 (18), not all Model Fs use all of the available strobes
// The single row ribbon connector Model Fs only have a max of 16 strobes
#define KISHSAVER_STROBE
+//#define TERMINAL_6110668_STROBE
+//#define UNSAVER_STROBE
#ifdef KISHSAVER_STROBE
- total_strobes = 10;
-
- strobe_map[0] = 1; // Kishsaver doesn't use strobe 0
- strobe_map[1] = 2;
- strobe_map[2] = 3;
- strobe_map[3] = 4;
- strobe_map[4] = 5;
- strobe_map[5] = 6;
- strobe_map[6] = 7;
- strobe_map[7] = 8;
- strobe_map[8] = 9;
- strobe_map[9] = 15; // Test point strobe (3 test points, sense 1, 4, 5)
+ total_strobes = 8;
+ //total_strobes = 9;
+
+ strobe_map[0] = 2; // Kishsaver doesn't use strobe 0 and 1
+ strobe_map[1] = 3;
+ strobe_map[2] = 4;
+ strobe_map[3] = 5;
+ strobe_map[4] = 6;
+ strobe_map[5] = 7;
+ strobe_map[6] = 8;
+ strobe_map[7] = 9;
+ // XXX - Disabling for now, not sure how to deal with test points yet (without spamming the debug)
+ //strobe_map[9] = 15; // Test point strobe (3 test points, sense 1, 4, 5)
+#elif defined(TERMINAL_6110668_STROBE)
+ total_strobes = 16;
+
+ strobe_map[0] = 0;
+ strobe_map[1] = 1;
+ strobe_map[2] = 2;
+ strobe_map[3] = 3;
+ strobe_map[4] = 4;
+ strobe_map[5] = 5;
+ strobe_map[6] = 6;
+ strobe_map[7] = 7;
+ strobe_map[8] = 8;
+ strobe_map[9] = 9;
+ strobe_map[10] = 10;
+ strobe_map[11] = 11;
+ strobe_map[12] = 12;
+ strobe_map[13] = 13;
+ strobe_map[14] = 14;
+ strobe_map[15] = 15;
+#elif defined(UNSAVER_STROBE)
+ total_strobes = 14;
+
+ strobe_map[0] = 0;
+ strobe_map[1] = 1;
+ strobe_map[2] = 2;
+ strobe_map[3] = 3;
+ strobe_map[4] = 4;
+ strobe_map[5] = 5;
+ strobe_map[6] = 6;
+ strobe_map[7] = 7;
+ strobe_map[8] = 8;
+ strobe_map[9] = 9;
+ strobe_map[10] = 10;
+ strobe_map[11] = 11;
+ strobe_map[12] = 12;
+ strobe_map[13] = 13;
#else
// Strobe detection
// TODO
{
keys_averages[i] = DEFAULT_KEY_BASE;
keys_averages_acc[i] = (DEFAULT_KEY_BASE);
+
+ // Reset debounce table
+ keys_debounce[i] = 0;
}
/** warm things up a bit before we start collecting data, taking real samples. */
// Main Detection Loop
// This is where the important stuff happens
inline uint8_t scan_loop()
+{
+ capsense_scan();
+
+ // Error case, should not occur in normal operation
+ if ( error )
+ {
+ erro_msg("Problem detected... ");
+
+ // Keymap scan debug
+ for ( uint8_t i = 0; i < total_strobes; ++i )
+ {
+ printHex(cur_keymap[strobe_map[i]]);
+ print(" ");
+ }
+
+ print(" : ");
+ printHex(error);
+ error = 0;
+ print(" : ");
+ printHex(error_data);
+ error_data = 0;
+
+ // Display keymaps and other debug information if warmup completede
+ if ( boot_count >= WARMUP_LOOPS )
+ {
+ dump();
+ }
+ }
+
+
+ // Return non-zero if macro and USB processing should be delayed
+ // Macro processing will always run if returning 0
+ // USB processing only happens once the USB send timer expires, if it has not, scan_loop will be called
+ // after the macro processing has been completed
+ return 0;
+}
+
+
+// Reset Keyboard
+void scan_resetKeyboard( void )
+{
+ // Empty buffer, now that keyboard has been reset
+ KeyIndex_BufferUsed = 0;
+}
+
+
+// Send data to keyboard
+// NOTE: Only used for converters, since the scan module shouldn't handle sending data in a controller
+uint8_t scan_sendData( uint8_t dataPayload )
+{
+ return 0;
+}
+
+
+// Reset/Hold keyboard
+// NOTE: Only used for converters, not needed for full controllers
+void scan_lockKeyboard( void )
+{
+}
+
+// NOTE: Only used for converters, not needed for full controllers
+void scan_unlockKeyboard( void )
+{
+}
+
+
+// Signal KeyIndex_Buffer that it has been properly read
+// NOTE: Only really required for implementing "tricks" in converters for odd protocols
+void scan_finishedWithBuffer( uint8_t sentKeys )
+{
+ // Convenient place to clear the KeyIndex_Buffer
+ KeyIndex_BufferUsed = 0;
+ return;
+}
+
+
+// Signal KeyIndex_Buffer that it has been properly read and sent out by the USB module
+// NOTE: Only really required for implementing "tricks" in converters for odd protocols
+void scan_finishedWithUSBBuffer( uint8_t sentKeys )
+{
+ return;
+}
+
+
+inline void capsense_scan()
{
// TODO dfj code...needs commenting + cleanup...
- uint8_t strober = 0;
uint32_t full_av_acc = 0;
- for (strober = 0; strober < total_strobes; ++strober)
+ for ( uint8_t strober = 0; strober < total_strobes; ++strober )
{
+ uint8_t map_strobe = strobe_map[strober];
uint8_t tries = 1;
- while ( tries++ && sampleColumn( strobe_map[strober] ) ) { tries &= 0x7; } // don't waste this one just because the last one was poop.
- column = testColumn(strober);
+ while ( tries++ && sampleColumn( map_strobe ) ) { tries &= 0x7; } // don't waste this one just because the last one was poop.
+ column = testColumn( map_strobe );
idle |= column; // if column has any pressed keys, then we are not idle.
// TODO Is this needed anymore? Really only helps debug -HaaTa
- if( column != cur_keymap[strober] && ( boot_count >= WARMUP_LOOPS ) )
+ if( column != cur_keymap[map_strobe] && ( boot_count >= WARMUP_LOOPS ) )
{
- cur_keymap[strober] = column;
+ cur_keymap[map_strobe] = column;
keymap_change = 1;
}
if ( error == 0x50 )
{
- error_data |= (((uint16_t)strober) << 12);
+ error_data |= (((uint16_t)map_strobe) << 12);
}
- uint8_t strobe_line = strober << MUXES_COUNT_XSHIFT;
+ uint8_t strobe_line = map_strobe << MUXES_COUNT_XSHIFT;
for ( int i = 0; i < MUXES_COUNT; ++i )
{
// discard sketchy low bit, and meaningless high bits.
}
}
-
- // Error case, should not occur in normal operation
- if ( error )
- {
- erro_msg("Problem detected... ");
-
- // Keymap scan debug
- for ( uint8_t i = 0; i < total_strobes; ++i )
- {
- printHex(cur_keymap[i]);
- print(" ");
- }
-
- print(" : ");
- printHex(error);
- error = 0;
- print(" : ");
- printHex(error_data);
- error_data = 0;
-
- // Display keymaps and other debug information if warmup completede
- if ( boot_count >= WARMUP_LOOPS )
- {
- dump();
- }
- }
-
-
- // Return non-zero if macro and USB processing should be delayed
- // Macro processing will always run if returning 0
- // USB processing only happens once the USB send timer expires, if it has not, scan_loop will be called
- // after the macro processing has been completed
- return 0;
-}
-
-
-// Reset Keyboard
-void scan_resetKeyboard( void )
-{
- // Empty buffer, now that keyboard has been reset
- KeyIndex_BufferUsed = 0;
-}
-
-
-// Send data to keyboard
-// NOTE: Only used for converters, since the scan module shouldn't handle sending data in a controller
-uint8_t scan_sendData( uint8_t dataPayload )
-{
- return 0;
-}
-
-
-// Reset/Hold keyboard
-// NOTE: Only used for converters, not needed for full controllers
-void scan_lockKeyboard( void )
-{
-}
-
-// NOTE: Only used for converters, not needed for full controllers
-void scan_unlockKeyboard( void )
-{
-}
-
-
-// Signal KeyIndex_Buffer that it has been properly read
-// NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void scan_finishedWithBuffer( uint8_t sentKeys )
-{
- // Convenient place to clear the KeyIndex_Buffer
- KeyIndex_BufferUsed = 0;
- return;
-}
-
-
-// Signal KeyIndex_Buffer that it has been properly read and sent out by the USB module
-// NOTE: Only really required for implementing "tricks" in converters for odd protocols
-void scan_finishedWithUSBBuffer( uint8_t sentKeys )
-{
- return;
}
{
uint16_t delta = keys_averages[(strobe << MUXES_COUNT_XSHIFT) + mux];
+ uint8_t key = (strobe << MUXES_COUNT_XSHIFT) + mux;
+
// Keypress detected
if ( (db_sample = samples[SAMPLE_OFFSET + mux] >> 1) > (db_threshold = threshold) + (db_delta = delta) )
{
column |= bit;
- // Only register keypresses once the warmup is complete
- if ( boot_count >= WARMUP_LOOPS )
+ // Only register keypresses once the warmup is complete, or not enough debounce info
+ if ( boot_count >= WARMUP_LOOPS && keys_debounce[key] <= DEBOUNCE_THRESHOLD )
{
- uint8_t key = (strobe << MUXES_COUNT_XSHIFT) + mux;
-
- // TODO Add debounce first
- // Add to the Macro processing buffer
+ // Add to the Macro processing buffer if debounce criteria met
// Automatically handles converting to a USB code and sending off to the PC
- //bufferAdd( key );
+ if ( keys_debounce[key] == DEBOUNCE_THRESHOLD )
+ {
+#define KEYSCAN_DEBOUNCE_DEBUG
+#ifdef KEYSCAN_DEBOUNCE_DEBUG
+ // Debug message
+ print("0x");
+ printHex_op( key, 2 );
+ print(" ");
+#endif
-#define KEYSCAN_THRESHOLD_DEBUG
+ // Only add the key to the buffer once
+ // NOTE: Buffer can easily handle multiple adds, just more efficient
+ // and nicer debug messages :P
+ //bufferAdd( key );
+ }
+
+ keys_debounce[key]++;
+
+//#define KEYSCAN_THRESHOLD_DEBUG
#ifdef KEYSCAN_THRESHOLD_DEBUG
// Debug message
// <key> [<strobe>:<mux>] : <sense val> : <delta + threshold> : <margin>
#endif
}
}
+ // Clear debounce entry if no keypress detected
+ else
+ {
+ // If the key was previously pressed, remove from the buffer
+ for ( uint8_t c = 0; c < KeyIndex_BufferUsed; c++ )
+ {
+ // Key to release found
+ if ( KeyIndex_Buffer[c] == key )
+ {
+ // Shift keys from c position
+ for ( uint8_t k = c; k < KeyIndex_BufferUsed - 1; k++ )
+ KeyIndex_Buffer[k] = KeyIndex_Buffer[k + 1];
+
+ // Decrement Buffer
+ KeyIndex_BufferUsed--;
+
+ break;
+ }
+ }
+
+
+ // Clear debounce entry
+ keys_debounce[key] = 0;
+ }
bit <<= 1;
}