diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..3e0f233 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +a.out + diff --git a/src/key.c b/src/key.c index 55c5192..f7b0013 100644 --- a/src/key.c +++ b/src/key.c @@ -4,12 +4,58 @@ * Created on: Mar 20, 2019 */ + #include +#include "utils.h" + +#ifndef DESKTOP #include "stc15.h" +#endif -static uint8_t keys[5]; +#define TOTAL_ROWS 5 +#define M_COLS 4 +static uint8_t keys[TOTAL_ROWS]; //only bottom nibbles get set +static uint32_t new_keys_pressed; //bottom 20 bits get set +static uint8_t last_state[TOTAL_ROWS]; //all used, 2 bits per key +static int8_t last_count[TOTAL_ROWS][M_COLS]; //all used +static uint8_t unexpected_count; //count of unexpected transitions + +static const int8_t COUNT_LIM_LOW = -30; +static const int8_t COUNT_LIM_HIGH = 30; +static const int8_t THRESH_STEADY = 2; +static const int8_t THRESH_TRANS = 2; + +//2-bit state: +#define STEADY_LOW 0 +#define TRANS_LOW_HIGH 1 +#define STEADY_HIGH 2 +#define TRANS_HIGH_LOW 3 + +#ifdef DESKTOP +//test functions +void KeyInit(void){} + +static void raw_scan(void){ + static uint8_t i = 0; + static const uint8_t data[] = { + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,0,2,0,2,0,2,0,2,0,2, + 2,2,0,2,2,0,2,2,0,2,2,0, + 2,2,2,2,2,2,2,2,2,2,2,2, + 0,2,0,2,0,2,0,2,0,2,0,2, + 0,0,2,0,0,2,0,0,2,0,0,2, + 0,0,0,0,0,0,0,0,0,0,0,0 + }; + + keys[1] = data[i]; + i++; + if (i >= (sizeof(data)/sizeof(data[0]))){ + i = 0; + } +} +#else void KeyInit(void){ //set column drivers bits 7:4 to quasi-bidirectional w/ pullup M[1:0]=b00 //and row inputs bits 3:0 to quasi-bidirectional w/ pullup M[1:0]=b00 @@ -29,11 +75,9 @@ void KeyInit(void){ P5 |= 0x30; //pull up } - -void KeyScan(void){ +static void raw_scan(void){ //top row not part of matrix static const uint8_t M_ROWS = 4; - static const uint8_t M_COLS = 4; uint8_t i, j; //scan top row @@ -62,8 +106,131 @@ void KeyScan(void){ } } } +#endif -uint8_t* GetKeys(void){ +//based on quick draw/integrator hybrid debounce algorithm from +//https://summivox.wordpress.com/2016/06/03/keyboard-matrix-scanning-and-debouncing/ +static void debounce(void){ + uint8_t i, j; + new_keys_pressed = 0; //initially + for (i = 0; i < TOTAL_ROWS; i++){ + for (j = 0; j < M_COLS; j++){ + int8_t new_count; + uint8_t new_state; + int8_t curr_count = last_count[i][j]; + uint8_t curr_state = last_state[i] & (0x3 << (j*2)); + curr_state >>= j*2; + new_count = curr_count; + new_state = curr_state; + //update count + if (keys[i] & (1 << j)){ + if (curr_count < COUNT_LIM_HIGH){ + new_count = curr_count + 1; + } + } else { + if (curr_count > COUNT_LIM_LOW){ + new_count = curr_count - 1; + } + } + //update state + switch(curr_state){ + //////// + case STEADY_LOW: { + if (new_count >= COUNT_LIM_LOW + THRESH_TRANS){ + new_count = 0; + new_state = TRANS_LOW_HIGH; + } + break; + } + //////// + case TRANS_LOW_HIGH: { + if (new_count >= THRESH_STEADY){ + new_state = STEADY_HIGH; + new_count = COUNT_LIM_HIGH; + } else if (new_count <= -THRESH_STEADY){ + new_state = STEADY_LOW; + new_count = COUNT_LIM_LOW; + unexpected_count++; + } + break; + } + //////// + case STEADY_HIGH: { + if (new_count <= COUNT_LIM_HIGH - THRESH_TRANS){ + new_count = 0; + new_state = TRANS_HIGH_LOW; + } + break; + } + //////// + case TRANS_HIGH_LOW: { + if (new_count <= -THRESH_STEADY){ + new_state = STEADY_LOW; + new_count = COUNT_LIM_LOW; + } else if (new_count >= THRESH_STEADY){ + new_state = STEADY_HIGH; + new_count = COUNT_LIM_HIGH; + unexpected_count++; + } + break; + } + //////// + default: + new_state = STEADY_LOW; + new_count = COUNT_LIM_LOW; + unexpected_count++; + } //switch(curr_state) + //track new keys down + if (curr_state != TRANS_LOW_HIGH && new_state == TRANS_LOW_HIGH){ + new_keys_pressed |= ((uint32_t) 1 << (i*M_COLS + j)); + } + //write back new count + last_count[i][j] = new_count; + //write back new state + last_state[i] = (last_state[i] & ~(0x3 << (j*2))) | (new_state << (j*2)); + } //for cols + } //for rows +} + + +void KeyScan(void){ + raw_scan(); + debounce(); +} + +const uint8_t* DebugGetKeys(void){ return keys; } +const uint32_t GetNewKeys(void){ + return new_keys_pressed; +} + + + +#ifdef DESKTOP +#include + +const char state_names[4][32] = { + "STEADY_LOW" , + "TRANS_LOW_HIGH", + "STEADY_HIGH" , + "TRANS_HIGH_LOW" +}; + +int main(void){ + for (int iii = 0; iii < 100; iii++){ + KeyScan(); + const uint8_t* keys = DebugGetKeys(); + static const uint8_t i = 1, j = 1; + uint8_t curr_count = last_count[i][j/2] & (0xf << ((j&1)*4)); + uint8_t curr_state = last_state[i] & (0x3 << (j*2)); + curr_count >>= (j&1)*4; + curr_state >>= j*2; + printf("%3d: %x, %14s, %2u, %2lx\n", + iii, keys[1], state_names[curr_state], curr_count, (unsigned long) GetNewKeys()); + } + + return 0; +} +#endif diff --git a/src/key.h b/src/key.h index 997ac3e..f487852 100644 --- a/src/key.h +++ b/src/key.h @@ -9,7 +9,8 @@ void KeyInit(void); void KeyScan(void); -uint8_t* GetKeys(void); +const uint8_t* DebugGetKeys(void); +const uint32_t GetNewKeys(void); #endif /* SRC_KEY_H_ */ diff --git a/src/main.c b/src/main.c index 60c3701..2948e83 100644 --- a/src/main.c +++ b/src/main.c @@ -10,11 +10,42 @@ #define FOSC 11059200 -// clear wdt -#define WDT_CLEAR() (WDT_CONTR |= 1 << 4) + +static const char KEY_MAP[20] = { + 'c', '<', 'r', 'm', + '/', '9', '8', '7', + '*', '6', '5', '4', + '-', '3', '2', '1', + '+', '=', '.', '0' +}; + + +uint32_t NewKeyBuf[4]; +volatile uint8_t new_key_write_i; +volatile uint8_t new_key_read_i; +volatile uint8_t new_key_empty; +#define INCR_NEW_KEY_I(i) i = (i + 1) & 3 + +volatile uint8_t SecCount; void timer0_isr() __interrupt 1 __using 1 { -// P3_1 ^= 1; + static uint8_t count = 0; + static uint8_t min_count = 0, hour_count = 0; + + uint32_t new_keys; + + //scan keyboard + KeyScan(); + new_keys = GetNewKeys(); + if (new_keys != 0){ + if (!new_key_empty && (new_key_write_i == new_key_read_i)){ + //do not overwrite keymap currently being processed + INCR_NEW_KEY_I(new_key_write_i); + } + NewKeyBuf[new_key_write_i] = new_keys; + INCR_NEW_KEY_I(new_key_write_i); + new_key_empty = 0; + } } @@ -41,34 +72,56 @@ char buf[17]; int main() { uint32_t i; - uint8_t* keys; + uint8_t j; + const uint8_t* keys; uint8_t key_i; Timer0Init(); // display refresh & switch read LCD_Open(); KeyInit(); P3_4 = 0; //turn on led backlight - LCD_OutString("Hello world !!!!"); - LCD_GoTo(1,0); - LCD_OutString("......."); i = 0; + j = 0; // LOOP while (1) { LCD_GoTo(0,0); - //scan keyboard - KeyScan(); - keys = GetKeys(); + //keyboard debug + keys = DebugGetKeys(); for (key_i = 0; key_i < 5; key_i++){ LCD_OutNibble(keys[key_i]); } + TERMIO_PutChar(','); //counter - LCD_GoTo(1,7); - LCD_OutString(u32str(i, buf, 10)); - i++; + if (SecCount == 0){ + LCD_OutString(" "); + } else if (SecCount < 10){ + TERMIO_PutChar(' '); + LCD_OutString(u32str(SecCount, buf, 10)); + } else { + LCD_OutString(u32str(SecCount, buf, 10)); + } - WDT_CLEAR(); + ///new keys + if (!new_key_empty){ + uint8_t i_key; + uint32_t new_keys = NewKeyBuf[new_key_read_i]; + INCR_NEW_KEY_I(new_key_read_i); + if (new_key_read_i == new_key_write_i){ + new_key_empty = 1; + } + + LCD_GoTo(1,j); + for (i_key = 0; i_key < 20; i_key++){ + if (new_keys & ((uint32_t) 1 << i_key)){ + TERMIO_PutChar(KEY_MAP[i_key]); + j++; + j &= 0x0f; + break; + } + } + } } } /* ------------------------------------------------------------------------- */ diff --git a/src/utils.h b/src/utils.h index 9e9edea..6264455 100644 --- a/src/utils.h +++ b/src/utils.h @@ -17,5 +17,13 @@ void _delay_ms(uint8_t ms); char* u32str(uint32_t x, char* buf, uint8_t base); +#ifdef __linux__ +#define DESKTOP +#elif _WIN32 +#define DESKTOP +#elif __APPLE__ +#define DESKTOP +#endif + #endif /* SRC_UTILS_H_ */