PCINT question

Where are these variable names defined?

PCMSK2 = _BV (PCINT4) | _BV (PCINT5); // want pins 20, 21 >> PCMSK2 is port D

PCIFR = _BV (PCIF2) ; // Clear any existing interrupts

PCICR |= _BV (PCIE2) ; // enable pin change interrupts for PCINT20,21 on port D

and how do I explain what they do?

Are they coming from this somehow?

#include <avr/interrupt.h>

Thanks!

hardware/tools/avr/lib/avr/include/avr/iom328p.h

If you are using the standard Arduino. Other if you are using other variants.

grep is your friend.

Thanks TanHadron. So I suppose buried somewhere is the callout for iom328p.h as my sketch certainly didn't call it out.

Hi,

I had a stab at explaining it here, its not any easy topic -

http://rcarduino.blogspot.ae/2013/06/rc-arduino-traction-control-traction.html

Duane B

rcarduino.blogspot.com

Are they coming from this somehow?

Close...

CrossRoads: So I suppose buried somewhere is the callout for iom328p.h as my sketch certainly didn't call it out.

Correct. A processor specific header file (iom328p.h for the at[u]M[/u]ega [u]328[/u] [u]P[/u]) is included when you, the software developer, include the avr/io.h file. In the Arduino world this is done through the Arduino.h file... https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/Arduino.h#L9

CrossRoads: Where are these variable names defined?

They are not actually variables but macros that expand to a memory address (e.g. PCMSK2) or a constant integer (e.g. PCINT4).

and how do I explain what they do?

Who is the audience?

and how do I explain what they do?

You read the data sheet for the chip that's on your board. They are all detailed in there, with what each bit means, and how you configure them to do different things.

Audience is teens being introduced to INTs and PCINTs.

I had found some things in the datasheet last night:

(0x68) PCICR – – – – – PCIE2 PCIE1 PCIE0
0x1B (0x3B) PCIFR – – – – – PCIF2 PCIF1 PCIF0

What I missed was this, even tho it was in the same area:
(0x6D) PCMSK2 PCINT23 PCINT22 PCINT21 PCINT20 PCINT19 PCINT18 PCINT17 PCINT16
on page 520

The use of _BV in the code was not at all clear, google searching found lots of explanations involving things like (name<<1), and which was ‘better’ due to writing fewer characters, vs how much shifting was needed to get a bit into position.

Now that I know what its doing, I’d just as soon write it this way, which I find clearer, and I would think would perform quicker, but haven’t looked at compiled code to actually confirm:

PCMSK2 = _BV (PCINT4) | _BV (PCINT5);
becomes
PCMSK2 = PCMSK2 | B00110000; // set bits for PCINT21, 20 in PinChangeMask2 (PCINTs 23 to 16)

PCIFR = _BV (PCIF2) ;
becomes
PCIFR = PCIFR | B00000100; // write 1 to clear any interrupts for PCMSK2 in Pin Change Interrupt Flag Register

PCICR |= _BV (PCIE2) ;
becomes
PCICR = PCICR | B00000100; // enable PCINTs for PCMSK2 in Pin Change Interrupt Configuration(?) Register

But that’s just me, coming at this as hardware engineer and not a software engineer.

I prefer bitSet(), bitClear() if I can use them. The compiler converts them to sbi and cbi instructions if it can, so they’re as efficient as possible.

But I’m with you, if I can do more than one bit at a time, I like to specify them in binary or hex.

From what I’ve seen, the compiler is very good at optimizing _BV() and (1 << name) as well, so it’s not a super big efficiency issue. I just don’t like how they look in my code.

CrossRoads:
Now that I know what its doing, I’d just as soon write it this way, which I find clearer, and I would think would perform quicker, but haven’t looked at compiled code to actually confirm:

Speed won’t be an issue, the compiler will optimize all those methods into the same thing (for one bit anyway).

My problem with bitSet is that it is written like a function, so you can’t combine them.

ie.

#define bitSet(value, bit) ((value) |= (1UL << (bit)))

So you can’t write:

 PCMSK2 = _BV (PCINT4) | _BV (PCINT5);

as:

 PCMSK2 = bitSet (PCINT4) | bitSet (PCINT5);

Instead you have to write:

bitSet (PCMSK2, PCINT4);
bitSet (PCMSK2, PCINT5);

And that hides the fact (a bit) that you are setting two bits in the same thing, and might conceivably not be optimized as much.