How to switch between interrupt input and analog input on the same pin?

Hello Jan,

Can I change the pin configuration / functionality “on the fly”?

Try to create the InterruptIn and AnalogIn dynamically on the heap rather than as static variables. Keep global only the associated pointers. Then you’ll be able to delete and recreate them as needed. I tested your code with such modification on an mbed LPC1768 board. Since I didn’t have your special keyboard I connected one end of a push button to pin p15 and the other end over a 4k7 resistor to the +3.3V rail:

...
#define TRACE_GROUP "main"
#define KBD_IN      p15

InterruptIn  *kbd_int;    // Global pointer to an InterruptIn
AnalogIn     *ainn;       // Global pointer to an AnalogIn

DigitalOut led1(LED1);
DigitalOut led2(LED2);

EventQueue kbd_event_q(3 * EVENTS_EVENT_SIZE);     // Let kbd get its own EventQueue
Thread kbd_tread;                                  // Let kbd get its own Thread
...
int decode_kbd()
{
    // 	Her I want to change the pin mode to Analog In
    // 	But I find no way to do it correctly
    //  AnalogIn ainn(KBD_IN);      // When I do this, I get only one interrupt.
    ainn = new AnalogIn(KBD_IN);    // Create a new 'ainn' AnalogIn object on the heap connected to the 'KBD_IN' pin
    uint16_t adc_sample;

    thread_sleep_for(10);    // 10ms

    // 	Her I want to Read the Analog value from the same pin that gave the interrupt
    //     adc_sample = ainn.read_u16();
    adc_sample = ainn->read_u16();
    delete ainn;            // Delete the 'ainn' AnalogIn object from the heap

    thread_sleep_for(3);    // 3ms (this is probably not needed)

    // 	Her I want to change the pin mode to interrupt In and continue reciveing interrupts
    // 	But I find no way to do it correctly
    //     InterruptIn kbd_int(KBD_IN, PullDown);	// This is most likely Wrong, and have no effect
    //  The 'kbd_int' object could be re-created here.
    //  But I prerere to do it in the function where it was deleted (i.e. in 'kbd_int_handler')

    return(adc_sample);
}

void kbd_int_handler()
{
    kbd_event_q.break_dispatch();                       // Forces event queue's dispatch loop to terminate.
    delete kbd_int;                                     // Delete the kbd_int InterruptIn object from the heap
    led1 = !led1;
    printf("\n **** kbd_int() **** %d\n", decode_kbd()    /*, Thread::gettid()*/);
    thread_sleep_for(300);    // debounce the KBD_INT key (wait untill it stops bouncing) - may not be needed for your hadware/keyboard
    kbd_int = new InterruptIn(KBD_IN, PullDown);        // Create a new kbd_int InterruptIn object on the heap
    kbd_event_q.dispatch_forever();                     // Dispatch events without a timeout.
    kbd_int->rise(kbd_event_q.event(kbd_int_handler));  // Attach this function to handle the kbd_int's next 'rise' event
}

int main(void)
{
    ...
    kbd_int = new InterruptIn(KBD_IN, PullDown);        // Create a new 'kbd_int' InterruptIn object on the heap
    kbd_tread.start(callback(&kbd_event_q, &EventQueue::dispatch_forever));        // Let kbd få get its own Thread
    kbd_int->rise(kbd_event_q.event(kbd_int_handler));  // The 'rise' handler 'kbd_int_handler' will execute in the context of 'kbd_tread'
    ...
}

Below is the printout on Termite 3.4 serial terminal:


[1B][2J[1B][7hARM Ltd

[1B][2K/> [1B][1D
[1B][2J[1B][7hARM Ltd

[1B][2K/> [1B][1D
 ***** mbed_kbd_test *****

 **** kbd_int() **** 65535

 **** kbd_int() **** 65535

 **** kbd_int() **** 65535

What do I have to do with the serial line (in my example code) to enable Mbed to enter deep sleep mode?

Unfortunately, I have no answer to that question. Maybe this thread can help you a bit.