Sure. This would be a quick sketch and hopefully it will send you on the way:
//define pin connection here
#define INT_PIN 2 //int0 pin on pd2, active now (falling edge). do not change the number
//
volatile unsigned char key_pressed=0; //flag for key pressed. 1=key pressed; 0=key not pressed
//int0 isr
ISR(INT0_vect) {
if (key_pressed==0) { //now, key is pressed
key_pressed = 1; //set the flag
//now active isr on the rising edge, to detect the release of the key
EICRA = (EICRA & ~0x03) | //preserve eicra bit 7..2
(1<<ISC01) | (1<<ISC00) //interrupt on int0's rising edge
;
} else { //now, the key is released
key_pressed = 0; //reset the flag
EICRA = (EICRA & ~0x03) | //preserve eicra bit 7..2
(1<<ISC01) | (0<<ISC00) //interrupt on int0's falling edge
;
}
}
void int0_init(void) {
//set up direction register
pinMode(INT_PIN, INPUT_PULLUP); //int pin configure as input, pull-up activated
//set up the isr
EICRA = (EICRA & ~0x03) | //preserve eicra bit 7..2
(1<<ISC01) | (0<<ISC00) //interrupt on int0's falling edge
;
EIFR |= (1<<INTF0); //clera int0 interrupt flag
EIMSK |= (1<<INT0); //activate int0 interrupt
}
void setup(void) {
//initialize int0 isr
int0_init();
//active interrupts
interrupts();
}
void loop(void) {
if (key_pressed) {
//key is pressed
//do something with it
} else {
//key is not pressed
//do something else
}
}
It sets up int0 pin (digital 2) as external interrupt, active now. The code detects a falling edge, and sets key_pressed. After that, it detects a rising edge (key released) and clears key_pressed to signal that the key has been released.
In the main loop, you process key_pressed only.
The same function can be also coded with ioc and probably more cleanly.
You will need to rewrite your main loop function now so that it can process key_pressed.
Something like this will work:
#define LOOP_MAX 10 //how many times you want to run the loop before change servo position
#define LOOP_DLY 10 //delay in each loop.
...
void loop(void) {
static unsigned short loop_counter = 0;
if (key_pressed) {
loop_counter += 1; //increment loop counter
if (loop_counter == LOOP_MAX) { //time to advance the servo
loop_counter = 0; //reset loop counter
//advance the servo
}
} else {
loop_counter = 0; //reset loop counter
//stop the servo
}
delay(LOOP_DLY); //delay the loop a little bit
}
As long as the key is pressed, the code counts the number of times it has been executed, and if it has reached the maximum number of execution (defined by LOOP_MAX), it moves the servo.
LOOP_DLY is to add some time to the loop so that LOOP_MAX does not need to be huge.
Something like this will respond to a key pressed quickly (no longer than LOOP_DLY).
Hope it helps.
Warning: untested code.