Society of Robots - Robot Forum

Software => Software => Topic started by: Ro-Bot-X on December 30, 2009, 06:41:39 PM

Title: C version of digitalRead(pin)?
Post by: Ro-Bot-X on December 30, 2009, 06:41:39 PM
Hi guys, I'm trying to do something that needs to read fast an input pin and then write that to an output pin, but it seems that it is not going fast enough in Arduino, can someone help me write it using directly registers or what ever works as fast as possible?

Here is the code in Arduino:
Code: [Select]
void loop(){
      boolean a = digitalRead(0);
      digitalWrite(2, a);   
      boolean b = digitalRead(3);
      digitalWrite(1, b);

Title: Re: C version of digitalRead(pin)?
Post by: madsci1016 on December 30, 2009, 06:50:39 PM
I had to do something similar when i built my Arduino powered smart motor controller.

This helped me write the code for direct access of i/o register:

http://arduino.cc/en/Reference/PortManipulation (http://arduino.cc/en/Reference/PortManipulation)

Hope this helps.

Edit:

here's a sample of my code. This reads the state of pin 7:

Code: [Select]
if (PIND & 0b10000000)
The if statement is true if pin 7 is high.
Title: Re: C version of digitalRead(pin)?
Post by: Razor Concepts on December 30, 2009, 07:04:24 PM
I use bit_is_clear and bit_is_set.

clear returns true if the pin is grounded, set returns true if the pin is high.

Code: [Select]
if(bit_is_cleaar(PIND,0))   //if pin D0 is grounded...
{
//pin D0 is grounded!
}
Title: Re: C version of digitalRead(pin)?
Post by: madsci1016 on December 30, 2009, 07:09:24 PM
I use bit_is_clear and bit_is_set.

clear returns true if the pin is grounded, set returns true if the pin is high.

Code: [Select]
if(bit_is_cleaar(PIND,0))   //if pin D0 is grounded...
{
//pin D0 is grounded!
}

If cycles really counted, would bit_is_clear still be a waste of extra cycles to process that function? (or do i not understand what that is?)

My method is the lowest level direct port access( ie least number of cycles required), at least from what i understand.
Title: Re: C version of digitalRead(pin)?
Post by: Ro-Bot-X on December 30, 2009, 07:17:14 PM
OK, so if I write:

Code: [Select]
      if (PIND&0){
        PORTD&2;
      else{
        PORTD||2;
      }

will write 1 on port D2 if pin D0 is 1 and will write 0 on port D2 if pin D0 is 0?
Title: Re: C version of digitalRead(pin)?
Post by: madsci1016 on December 30, 2009, 07:26:25 PM
When setting ports, do it like this:

PORTD |= b00000010

this leaves ever other pins where they are and sets the second pin high.

You are confused about the D2 thing. Stick to using binary numbers when doing this, because each binary digit is one pin in the port.

I am still trying to find the right bitwise operator to clear only one bit (pin) in the port and leave the rest, i will get back to you when i find it.
Title: Re: C version of digitalRead(pin)?
Post by: Ro-Bot-X on December 30, 2009, 07:35:07 PM
Is this better?

Code: [Select]
      if (PIND&0){
        PORTD|=B00000100;
      else{
        PORTD|=B00000000;
      }

Thanks for your help!
Title: Re: C version of digitalRead(pin)?
Post by: GearMotion on December 30, 2009, 07:40:59 PM
I am still trying to find the right bitwise operator to clear only one bit (pin) in the port and leave the rest, i will get back to you when i find it.

Another way is to define these macros:

Code: [Select]

#define BIT_SET(REG, bit)                    ( REG |= (1UL << (bit) ) )

#define BIT_CLR(REG, bit)                    ( REG &= ~(1UL << (bit) ) )

#define BIT_TST(REG, bit, val)              ( ( (REG & (1UL << (bit) ) ) == ( (val) << (bit) ) ) )


And then write your code like this:

Code: [Select]


    if ( BIT_TST( PIND, 0, 1 ) )
        {
        BIT_SET( PORTD, 2);
        }
    else
        {
        BIT_CLR( PORTD, 2);
        }
    

Title: Re: C version of digitalRead(pin)?
Post by: rgcustodio on December 30, 2009, 07:47:18 PM
bit_is_clear IMHO is part of AVR libc ... http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html (http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html)


FWIW, the actual number of cycles used up will only be evident in the assembly code generated. Most optimizing C compilers (including gcc) will generate almost the same code for bit_is_clear() macro and the method being used by madsci1016.

Here are the other bitwise operations for everyone's reference.
http://en.wikipedia.org/wiki/Bit_manipulation (http://en.wikipedia.org/wiki/Bit_manipulation)
Title: Re: C version of digitalRead(pin)?
Post by: Ro-Bot-X on December 30, 2009, 08:00:49 PM

Another way is to define these macros:

Code: [Select]

#define BIT_SET(REG, bit)                    ( REG |= (1UL << (bit) ) )

#define BIT_CLR(REG, bit)                    ( REG &= ~(1UL << (bit) ) )

#define BIT_TST(REG, bit, val)              ( ( (REG & (1UL << (bit) ) ) == ( (val) << (bit) ) ) )


And then write your code like this:

Code: [Select]


    if ( BIT_TST( PIND, 0, 1 ) )
        {
        BIT_SET( PORTD, 2);
        }
    else
        {
        BIT_CLR( PORTD, 2);
        }
    



IT WORKS! Thank you very much! You made my day!

I mean not only that replaces perfectly the Arduino syntax, but it actually makes the serial bridge between the PC to the VRbot card that is plugged into Arduino, so I don't have to remove it and connect it to a Basic FTDI adapter to set up the new commands. Kudos to GearMotion and madsci1016!
Title: Re: C version of digitalRead(pin)?
Post by: GearMotion on December 30, 2009, 08:33:15 PM
I'm glad that worked for you. I might have nabbed those exact macros from here or somewhere. I use similar ones in my code.

I keep a notebook in my PIM and so such things are only a cut/paste away.
Title: Re: C version of digitalRead(pin)?
Post by: Razor Concepts on December 30, 2009, 08:34:12 PM
Gearmotion, could you post what little macros you had? Just recently I had to manipulate some ports and it took me quite a bit to dig through my old code and relearn what I used  :P
Title: Re: C version of digitalRead(pin)?
Post by: GearMotion on December 30, 2009, 08:44:36 PM
Gearmotion, could you post what little macros you had? Just recently I had to manipulate some ports and it took me quite a bit to dig through my old code and relearn what I used  :P

Well, those above for bit test and setting. Some macros for determining if a character is hex, numeric, etc. Lots of that done instead of linking in a library. Those?