On Tue, Oct 23, 2012 at 2:21 PM, Yama Ploskonka <yamap...@gmail.com> wrote:
> What I want to achieve is a two-whisker robot, the kind that bounces off
> the wall in either direction oposite from the whisker closing a switch.
> Couldn't be simpler.

Great, that makes this easy. If I understand correctly, the thing you
care about only happens when the switch closes (ie. the robot hits a
wall). If you don't care when the switch opens, you can simplify your
ISR a lot.

Just do something like this:

#include <msp430x20x3.h>
#define BUTTON BIT4

void __attribute__((interrupt(PORT1_VECTOR))) p1_isr()
{
  if (P1IFG & BUTTON) {
    P1IFG &= ~BUTTON; /* Clear the flag */
    /* Do stuff here ... */
  }
  /* Duplicate the above code for each pin you want to handle. */
}

Since you don't need to deal with the opposite edge, you never need to
toggle the IES flag or anything fancy like that. You probably don't
need to deal with debounce either in a case like this.

Things get trickier if you want to trigger on both the rising and the
falling edges. If you don't do it exactly right, it is possible for
the IO pin to get out of sync with the interrupt edge selector bit. I
use the following macro to deal with that:

/**
 * Reads an IO pin and adjusts the interrupt edge selector.
 */
#define gpio_sample(port, bit, sample) \
  do { \
    sample = port##IN & bit; \
    if (sample) \
      port##IES |= bit; \
    else \
      port##IES &= ~bit; \
    if (port##IFG & bit) \
      return; \
  } while ((sample ^ port##IN) & bit)

This macro deals with every possible race condition, and guarantees
that the IES flag will match the pin. Otherwise, the macro will return
with the IFG flag set, causing the ISR to just run again. You would
use the macro like this:

void __attribute__((interrupt(PORT1_VECTOR))) p1_isr()
{
  if (P1IFG & BUTTON) {
    char sample;
    P1IFG &= ~BUTTON; /* Clear the flag */
    gpio_sample(P1, BUTTON, sample);
    if (sample) {
      /* The pin went high... */
    } else {
      /* The pin went low... */
    }
  }
  /* Duplicate the above code for each pin you want to handle. */
}

Ok, so that handles level-following. Debounce is a whole different
issue, and my personal strategy involves a timer and a few flags. If
you just want to do it the easy way, I suppose you could put a delay
loop after the gpio_sample call, and then check to see if the IFG flag
is set. If it became set while the loop was running, the pin is still
bouncing so you should just return without doing anything:

void __attribute__((interrupt(PORT1_VECTOR))) p1_isr()
{
  if (P1IFG & BUTTON) {
    char sample;
    P1IFG &= ~BUTTON; /* Clear the flag */
    gpio_sample(P1, BUTTON, sample);
    __delay_cycles(30000);
    if (P1IFG & BUTTON)
      return; /* Still bouncing */
    if (sample) {
      /* The pin went high... */
    } else {
      /* The pin went low... */
    }
  }
  /* Duplicate the above code for each pin you want to handle. */
}

This isn't ideal, since debounce doesn't allow any action until
*after* the pin has settled, which adds latency. It also ties up the
CPU for a long time in that delay loop. It's probably fine for your
robot, though, so I will leave it at that.

Hope this helps.

-William

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to