|
|
View previous topic :: View next topic |
Author |
Message |
Hawk Guest
|
Keyboard, keypad debouncing and more |
Posted: Sun Jan 11, 2009 7:53 am |
|
|
Hello.
I've removed some parts from Mark's source code so it can fit my needs.
There is just single click check and hold down part.
I want to learn on this example but some help is welcome.
My end goal is to do keyboard (3x4, 4x4 debouncing on this way:
A B C a b c 1, A B C a b c 1, A B C a b c 1 and so on.
One button should be able to switch between this 7 possibilities and if you hold this button for 3 seconds, last char should be remembered.
The same as on mobile phones keypad.
--------------------------------------------------
Before i implement the keyboard i want to understand how to make this with the buttons on the picdem board , so i started with Mark's code.
1.) How to switch this possibilities thru some IF loop ?
2.) The clockspeed is 4 MHZ not 10 ( as in example ) so timer should be reconfigured.
Thank you.
Quote: | case 0:
if (Switch_State[1] == SWITCH_HELD) // hold for 3 secounds
printf(lcd_putc,"\fSW1 Click\nWhile SW2 Held");
else
if ( )
{
printf(lcd_putc,"\fSW1 Click");
//-------------------------------
printf("A\n\r");
//-------------------------------
}
break; |
Code: |
// Note to check timer2 setup if you change this to make sure it ints every ms
#define clockspeed 4000000
#use delay(clock=clockspeed)
#define CLICK_TIME 200 // Maximum time to consider a press/release a click
#define SWITCH_READ_TIME 30 // Interval to read the switches in ms
#define NUM_SWITCHES 2 // Good for up to 8 switches without having to modify the variable types
// Different types of click events
enum SWITCH_STATES
{
SWITCH_IDLE,
SWITCH_DOWN,
SWITCH_HELD, // last char confirmation
SINGLE_CLICK,
};
int8 Miliseconds; // Our system timer
int8 Read_Switch_Timer = 0; // How often we read the switch inputs
int1 Read_Switch_Flag = FALSE; // Signal to read the switches
int16 Click_Timer[NUM_SWITCHES]; // Timeout value or in this case the double click time
enum SWITCH_STATES Switch_State[NUM_SWITCHES];
// Timer 2 is our system tick
#int_timer2
void timer2_isr(void)
{
if (Miliseconds < 0xFF)
Miliseconds++;
}
// Handles what happens when we release a switch
void Switch_Released(int8 number)
{
if (number < NUM_SWITCHES) // Make sure this is a valid switch
{
switch (Switch_State[number])
{
case SWITCH_DOWN: // Set the timer to the maximum time between a press and release to consider this a single click
Click_Timer[number] = CLICK_TIME;
Switch_State[number] = SINGLE_CLICK;
break;
case SWITCH_HELD: // Just set the timer to a small number so that it will fire as soon as we release the switch
Click_Timer[number] = 1; // Don't change the state here, the timers will take care of it
break;
case SINGLE_CLICK: // Set the timer for the maximum time we will wait for a double click
break;
default:
Click_Timer[number] = 0;
Switch_State[number] = SWITCH_IDLE;
break;
}
}
}
//---------------------------------
void Switch_Pressed(int8 number) // Handles what happens when we press a switch
{
if (number < NUM_SWITCHES) // Make sure this is a valid switch
{
if (Switch_State[number] == SWITCH_IDLE) // Set the state to down only if we haven't just processed a click
Switch_State[number] = SWITCH_DOWN;
}
}
void Switch_Read_Value(void) // Handles debouncing of the switches
{
static int8 last_read = 0xFF;
static int8 last_state = 0xFF;
static int8 debounce_count;
int8 result = 0xFF;
int8 i;
int8 changed;
if (!input(PIN_A4)) // Read the current result
bit_clear(result,0);
if (!input(PIN_B0))
bit_clear(result,1);
if (result != last_read) // See if it changed
{
// It did so debounce it
debounce_count = 5;
last_read = result;
}
else if (debounce_count) // We are debouncing
{
debounce_count--;
if (debounce_count == 0) // Done debouncing
{
changed = (result ^ last_state); // See if the state of the switch has changed
for(i=0;i<8;i++) // Determine what type of event occurred
{
if (bit_test(changed,i))
{
if (bit_test(result,i))
Switch_Released(i);
else
Switch_Pressed(i);
}
last_state = result; // Save the current state
}
}
}
}
//***************************************************************
void Single_Click_Event(int8 number) // ***** ONE CLICK *****
{
switch(number) // TO ADD MORE SWITCHES you need to add the cases
{
case 0:
if (Switch_State[1] == SWITCH_HELD) // hold for 3 secounds
printf(lcd_putc,"\fSW1 Click\nWhile SW2 Held");
else
if ( )
{
printf(lcd_putc,"\fSW1 Click");
//-------------------------------
printf("A\n\r");
//-------------------------------
}
break;
case 1:
if (Switch_State[0] == SWITCH_HELD)
printf(lcd_putc,"\fSW2 Click\nWhile SW1 Held");
else
printf(lcd_putc,"\fSW2 Click");
printf("D\n\r");
break;
default:
break;
}
}
void Switch_Timers(void) // ***** Handles all our switch timers *****
{
int8 i;
if (Read_Switch_Timer == 0)
Read_Switch_Timer--;
else
Read_Switch_Flag = TRUE;
for(i=0;i<NUM_SWITCHES;i++)
{
if (Click_Timer[i])
{
Click_Timer[i]--;
if (Click_Timer[i] == 0)
{
switch (Switch_State[i])
{
case SWITCH_DOWN:
Switch_State[i] = SWITCH_HELD;
break;
case SWITCH_HELD:
Switch_State[i] = SWITCH_IDLE;
break;
case SINGLE_CLICK:
Single_Click_Event(i);
Switch_State[i] = SWITCH_IDLE;
break;
default:
Switch_State[i] = SWITCH_IDLE;
break;
}
}
}
}
}
void Switch_Tasks(void) //***** Handles all our switch tasks *****
{
if (Read_Switch_Flag)
{
Switch_Read_Value();
Read_Switch_Timer = SWITCH_READ_TIME;
Read_Switch_Flag = FALSE;
}
}
//**** System counter *****
void System_Tick(void)
{
while (Miliseconds)
{
Switch_Timers();
Miliseconds--;
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 12, 2009 12:07 am |
|
|
Mark's code does not work with a 3x4 keypad. It's intended for individual
switches, where each switch is connected to a separate PIC pin.
You will need a different driver for a 3x4 keypad.
Here is a data sheet for Grayhill 3x4 keypads. They have switches
wired in a matrix and have a 7-pin header on the back:
http://embrace.grayhill.com/embrace/IMAGES/PDF/c-06-09.pdf |
|
|
Hawk Guest
|
|
Posted: Mon Jan 12, 2009 12:50 pm |
|
|
Hi PCM Programmer,
and thank you for reply.
Yes i am aware that Mark's code is for individual switches only, but i was thinking that maybe it would be interesting to implement this kind of logic into keypad.
How would you make this what i described in first post ?
A B C a b c 1, A B C a b c 1, A B C a b c 1 and so on.
I now i have to use timers but i am not quite sure how will all this affect performance of the program, speed etc.
Anyway, where would you start ? |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Mon Jan 12, 2009 5:06 pm |
|
|
Call me clueless, but what does "A B C a b c 1, A B C a b c 1, A B C a b c " mean? |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Mon Jan 12, 2009 5:09 pm |
|
|
He wants it to cycle through the selections each time you push the button. First short push it displays A. the second short push it displays B etc. If you push and hold the button for three seconds it accepts that as the selection of the user. |
|
|
Hawk Guest
|
|
Posted: Sun Feb 01, 2009 6:05 am |
|
|
What is better way to connect the keypad, regarding to functionality described in previous posts ?
This
ht://i44.tinypic*com/1szblz.jpg
or
ht://i40.tinypic*com/rbxyrp.jpg
I will try to use modified ccs keypad example and mark's state machine idea, to get what i need. Suggestions, examples ?
Thanx! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|