Atmega1284 using same pin both for analogRead and pin change interrupt

Hello,

I've got a programming question -

can one and the same analog pin on the Atmega1284P be used both for a pin change interrupt and an analogRead?

I've read conflicting info on the web about that.

As part of my CarDuino project, I want to be able to navigate between different menu screens of my display, using three buttons which will act as "forward", "back" and "set" buttons.

To achieve this, I have made a triple voltage divider. Meaning, one pull down resistor on the analog A4 pin on the 1284 goes to ground, and each of the three buttons is connected to a different value resistor, so that when you press either of the buttons, it produces a different analog reading on the pin.

The way I have chosen my resistors, they result in values on the A4 pin from some 4 volts to around 2.9 volts.

If I put in different resistors so that all of them are above 3.3 volts, could I then also do a pin change interrupt on the same A4 pin?

The idea would be to use that interrupt to increase or decrease a number between 1 and about 10, and have that number indicate which menu page is to be shown.

Pseudo (!!) code:

ISR(Pin A4) {


analogValue = analogRead(A4);
  

if(analogValue is button "back") menuScreen -=1;

if(analogValue is button "forward") menuScreen +=1;

if'(analogValue is button "set") enter set mode;

}

I know that that's a bunch to put inside an interrupt service routine... any suggestions how that ISR could be slimmed down to run a bit faster?

Anyway, in the loop() code, I would then call a function which would create the desired menu page on the screen based on the value of menuScreen.

So, long story short, can I use the same pin both as an analog and a pin change input in the same code?

I believe that the digital pin logic is disconnected from the pin when the pin is in analog mode. Otherwise the digital logic could be biased to intermediate voltages that would cause excessive current consumption.

Probably quicker to actually try it than try to analyze the datasheet "functional" diagrams...

Hmm. If you have all the voltages above the threshold, you could probably leave the pin in digital mode EXCEPT when you actually want to read the value. But note that reconfiguring the pin for analog and waiting for an A2D conversion in a pin change ISR would be ... more code than you should put in an ISR.

ok I've now got it so that it's working pretty well.

Here's my code:

// defining navigation button pin

#define allInOnePin A4

// Menu navigation variables

byte showMenu = 1;
boolean setButton = false;

boolean backButtonSet = false;
boolean setButtonSet = false;
boolean forwardButtonSet = false;


void buttonNavi() {


  /* The screeens are navigated with back, forward and set buttons.
      They act as part of a triple voltage divider with a 5K1 pulldown
      resistor on analog pin A4, and one resistor each between the
      buttons and Vcc (1K, 4K7 and 10K). This produces distinct
      analog readings on the pin A4 for each button, which
      are used to count a global-variable byte number up or down,
      which is used elsewhere in the code to determine which menu
      page is to be shown.
  */

  int buttonState = analogRead(allInOnePin);

  //Back button
  if (buttonState > 250 && buttonState < 400 && !backButtonSet) {

    showMenu -= 1;
    backButtonSet = true;
  }

  // Set button
  if (buttonState > 450 && buttonState < 600) {

    setButton = true;
    setButtonSet = true;

  //Forward button
  if (buttonState > 750 && buttonState < 950 && !forwardButtonSet) {

    showMenu += 1;
    forwardButtonSet = true;
  }

  /* Altogether, twelve different menu screens (hey, it's a 1.44'' display...
    you can only provide so many bits of information at any one time for the driver
    to notice at a glance). 

    Per page, two readings are displayed. Of these twelve pages, three are "settings" pages, 
    so we're left with nine pages of actual information, again, with two readings per page
    at a time.  */

  if (showMenu <= 0) showMenu = 12;
  if (showMenu > 12) showMenu = 1;

  if (!buttonState) {

    backButtonSet = false;
    setButtonSet = false;
    forwardButtonSet = false;
  }


  return showMenu;
}


void setup(){

 pinMode(allInOnePin, INPUT);

}


void loop(){

buttonNavi();

}

Suggestions are still welcome...