Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
clawson
PostPosted: Jan 08, 2009 - 03:36 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71696
Location: (using avr-gcc in) Finchingfield, Essex, England

If you want to both clear some bits and then set some bits you need to do TWO read/modify/write operations. One to clear the bits and then another to set any bits that need setting. Something like
Code:
# define Sensor0 PORTC &= 0xFC
# define Sensor1 PORTC &= 0xFC; PORTC |= (1<<PORTC0)
# define Sensor2 PORTC &= 0xFC; PORTC |= (1<<PORTC1)
# define Sensor3 PORTC &= 0xFC; PORTC |= ((1<<PORTC0) | (1<<PORTC1))

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
ArnoldB
PostPosted: Jan 08, 2009 - 04:04 PM
Raving lunatic


Joined: Nov 29, 2007
Posts: 3219


Code:
PORTC &= ~((1<<PORTC0) | (1<<PORTC1));        // 00
PORTC = (PORTC & ~(1<<PORTC1)) | (1<<PORTC0); // 01
PORTC = (PORTC & ~(1<<PORTC0)) | (1<<PORTC1); // 10
PORTC |= (1<<PORTC0) | (1<<PORTC1);           // 11

_________________
Stealing Proteus doesn't make you an engineer.
 
 View user's profile Send private message  
Reply with quote Back to top
Maximilian
PostPosted: Jan 08, 2009 - 04:32 PM
Wannabe


Joined: Apr 01, 2006
Posts: 84


Ok, thats what i thought but didn't know how to do Smile

Will the compiler produce the same code from both your examples?

Thanks!! Very Happy
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jan 08, 2009 - 04:37 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71696
Location: (using avr-gcc in) Finchingfield, Essex, England

Unlikely - I think Arnold's may be more efficient though personally I think mine maybe makes it a little more obvious what's going on at the cost of a bit of inefficiency (I'm a great fan of "obvious" code for the person who comes back to read this in 3 months)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
ArnoldB
PostPosted: Jan 08, 2009 - 05:29 PM
Raving lunatic


Joined: Nov 29, 2007
Posts: 3219


clawson wrote:
I think mine maybe makes it a little more obvious what's going on
Hey, I even added comments. What more can you ask for? Razz

_________________
Stealing Proteus doesn't make you an engineer.
 
 View user's profile Send private message  
Reply with quote Back to top
Maximilian
PostPosted: Jan 08, 2009 - 06:05 PM
Wannabe


Joined: Apr 01, 2006
Posts: 84


ArnoldB wrote:
Hey, I even added comments. What more can you ask for? Razz


No fighting please, LOL

As speed is needed i will go with ArnoldB his version.

Points go to the both of you,
 
 View user's profile Send private message  
Reply with quote Back to top
damian_
PostPosted: Jan 09, 2009 - 07:04 PM
Newbie


Joined: Dec 12, 2008
Posts: 9


Hello again
First of all thanks very much, because of all of you I can continue working in my project.
I think I understand your explanations. But I'm still confuse with one point.
Here it is my code
Code:


   //PORT INITIALITATION.(1)OUTPUT,(0) INPUT
   DDRB  = 0b00001100;//LEDS AS OUTPUT   
   PORTB = 0b11111111;//PULL-UP ACTIVE
   
   DDRD  = 0b11101011;//DDC112 COMUNICATION
   PORTD = 0b11111111;//PULL-UP ACTIVE


//   PORTD &= ~(1 << 6);//DCLK "LOW"->INITIALITATION
   dclksemiperiod=0;
   
   
   
   PORTB ^= (1 << 3); //Toggle the LED PB3
   PORTD ^= (1 << 6); //Toggle PD6
   
   if((PIND & (1<<PD6)) && (dclksemiperiod == 0) && (PIND & (1<<PD4)))
   

The problem is that when I uncomment the line
Code:
PORTD &= ~(1 << 6);
The condition in the if its not true, and I don't not why.
I suposse that, at the beggining PD6=1, after
Code:
PORTD ^= (1 << 6);
PD6 shoud be 0, but its not. Why?
(I know the problem is PD6, because I allready checked all the other things and are ok, of course PD4 its allways on by hardware)
THANKS
 
 View user's profile Send private message  
Reply with quote Back to top
devilsandy
PostPosted: Jul 08, 2009 - 04:12 AM
Newbie


Joined: Jun 23, 2005
Posts: 3


tigrezno wrote:
those are my definitions, i find them more user-friendly, tell me what you think.

Code:
#define LOW 0
#define HIGH 1

#define INPUT(port,pin) DDR ## port &= ~(1<<pin)
#define OUTPUT(port,pin) DDR ## port |= (1<<pin)
#define CLEAR(port,pin) PORT ## port &= ~(1<<pin)
#define SET(port,pin) PORT ## port |= (1<<pin)
#define TOGGLE(port,pin) PORT ## port ^= (1<<pin)
#define READ(port,pin) (PIN ## port & (1<<pin))


usage:
Code:
OUTPUT(D, 3); // port D, pin 3 as output
SET(D, 3); // set port D pin 3 to HIGH
CLEAR(D, 3); // set it to LOW

INPUT(B, 5);
if (READ(B, 5) == HIGH)
...


feel free to add them to the tutorial Smile
[updated]



Hello All, I have extended this code one more step. I wanted to keep all the pin definition in one place or one file.
Code:

#define LED A, 0
#define SWITCH B, 1


SET(LED) // turn on

if(READ(SWITCH)== 0){ // switch active
}


The sequence of pre-processor substitution was causing compile problems. I found solution for this as variable arguments macro. http://en.wikipedia.org/wiki/Variadic_macro
The extended version is as follows
Code:

// ##############

// GPIO.h file
#define G_INPUT(port,pin) DDR ## port &= ~(1<<pin)
#define G_OUTPUT(port,pin) DDR ## port |= (1<<pin)
#define G_CLEAR(port,pin) PORT ## port &= ~(1<<pin)
#define G_SET(port,pin) PORT ## port |= (1<<pin)
#define G_TOGGLE(port,pin) PORT ## port ^= (1<<pin)
//#define G_READ(port,pin) (PIN ## port & (1<<pin))
#define G_READ(port,pin) ((PIN ## port & (1<<pin)) >> pin)


#define GPIO_INPUT(...)    G_INPUT(__VA_ARGS__)
#define GPIO_OUTPUT(...)   G_OUTPUT(__VA_ARGS__)
#define GPIO_CLEAR(...)    G_CLEAR(__VA_ARGS__)
#define GPIO_SET(...)      G_SET(__VA_ARGS__)
#define GPIO_TOGGLE(...)   G_TOGGLE(__VA_ARGS__)
#define GPIO_READ(...)     G_READ(__VA_ARGS__)
#define GPIO_READ_N(...)   G_READ_N(__VA_ARGS__)

// ########

// project.h file : keep all the definitions here

#define LED A, 0
#define SWITCH B, 1

// ###########

// Project.c file
// This can be used as follows

#include "include/GPIO.h"
#include "include/project.h"



GPIO_SET(LED) // Turn on the LED

if ( GPIO_READ(SWITCH)==0){ // Switch on
}



Please note my version of READ is different. I prefer return values as either 1 or 0.

Just my 2 cents. Thank you.
 
 View user's profile Send private message  
Reply with quote Back to top
milos.soucek
PostPosted: Oct 09, 2009 - 11:53 PM
Newbie


Joined: Oct 09, 2009
Posts: 2


Hi all,

I have one question about the bit's names definitions of AVR registers, as they are done in avrlib.

In avrlib are these defined like this :

#define PA0 0
#define PA1 1
#define PA2 2

and so on.

Is there any good reason why to not have them defined directly like this :

#define PA0 1
#define PA1 2
#define PA2 4
#define PA3 8

So You do not need to shift or use any _BV() macro everytime.

Who and when needs bits defined by their number, and not directly by their mask ?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Oct 10, 2009 - 12:13 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15086
Location: Vancouver, BC

Quote:
Is there any good reason why to not have them defined directly like this :

This is the way that Atmel defined them in assembler. Avrlibc (not avrlib, that is a separate product) gets the definitions from Atmel's definitions.

Quote:
Who and when needs bits defined by their number, and not directly by their mask ?

Assembler uses them directly in opcodes such a SBI, CBI, SBIC, SBIS.

You can always define your own versions of them that are bit masks instead of bit numbers.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
milos.soucek
PostPosted: Oct 10, 2009 - 04:04 PM
Newbie


Joined: Oct 09, 2009
Posts: 2


Thanks for reply.
Now it is clear.
Of course I was talking about avr-libc, sorry for that.
 
 View user's profile Send private message  
Reply with quote Back to top
Baldrian
PostPosted: Oct 13, 2009 - 08:47 AM
Hangaround


Joined: Jul 10, 2008
Posts: 195
Location: Ruhrpott, Germany

Bit Manipulation is clear for me, until it gets to negative values.
I have a function which returns an int16 value with following values:
-1 // OK
-2 // Failure
-3 // something
...
-75 // do something special
-128 // special detail

And of course some combinations with the special detail (-128)
-129 // OK and special detail
-130 // Not OK and special detail

But no combnination with the -75
And I don't have to use the special detail.

I have a working solution on how to check this, but in my opinion it is not a nice solution.
Code:

if (ret == -75){  // do something
   SendEvent(DO_SOMETHING);
}
else if (~(ret) & 128)   //special detail
{
   ret +=128;   //we don't need to check the special detail
   SendEvent(ret);   
}
else
   Send_Event(ret);


So, how can I easily handle negative return values?

_________________
http://xkcd.com/221/
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Oct 13, 2009 - 09:31 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71696
Location: (using avr-gcc in) Finchingfield, Essex, England

I don't wholly see the relevance of your question to this tutorial but to try and drag it slowly back on topic how about using negative binary return codes:
Code:
#define ERROR_CONDITION_1 -1
#define ERROR_CONDITION_2 -2
#define ERROR_CONDITION_3 -4
#define ERROR_CONDITION_4 -8
...

In a 16 bit signed int you could hold 15 such conditions with multiple error conditions combined with & and individual conditions tested on the return with bit testing instructions.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Baldrian
PostPosted: Oct 13, 2009 - 09:50 AM
Hangaround


Joined: Jul 10, 2008
Posts: 195
Location: Ruhrpott, Germany

OK, maybe you're right. It's not really bit manipulation what I need.
I cannot change the return value, because the function is in a Lib. I have to live with the strange return values, but I'm searching for a nice solution to handle this life Smile

Edit:
Ok. Found an easy solution:
Code:

ret *= -1; // and now I have nice positive values
...
else if (ret & 0x80)   // 128 special detail
{
   ret = ret & ~0x80;   //we don't need to check the special detail
   SendEvent(ret);   
}
else
   Send_Event(ret);

Then I changed the events to positive values. And after that delete the magic numbers by #defines
i.e. #define SPECIAL_DETAIL 0x80

Now I'm happy Smile

_________________
http://xkcd.com/221/
 
 View user's profile Send private message  
Reply with quote Back to top
LDEVRIES
PostPosted: Oct 18, 2009 - 04:39 AM
Raving lunatic


Joined: May 04, 2007
Posts: 3745
Location: Geelong Australia, Home of the "Cats"

I have gone through this tutorial with the view of putting all the "good stuff" in one document. The aim was to pick out the eyes out of it to keep it on track. Ie. Programming 101 - Bit manipulation, Is anyone interested in doing a proof read. Please PM me.
Lee

_________________
Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
EW
PostPosted: Oct 20, 2009 - 02:16 AM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

This was already put into one document: an article in Circuit Cellar magazine, July 2005 issue:

Bit Flipping Tutorial
An Uncomplicated Guide to Controlling MCU Functional
Eric Weddington
http://www.circuitcellar.com/magazine/180toc.htm

Unfortunately it's not a free article. However, the "Programming 101" post at the top of this thread is free. The magazine article is essentially the same information (but with grammar/spelling corrections).
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
fever2tel
PostPosted: Oct 25, 2009 - 05:35 PM
Hangaround


Joined: Jan 15, 2009
Posts: 167
Location: South Africa

I am busy learning C, and busy writing my first GCC program, and I read in the GCC FAQ:
Quote:
Why does the compiler compile an 8-bit operation that uses bitwise operators into a 16-bit operation in assembly?
Bitwise operations in Standard C will automatically promote their operands to an int, which is (by default) 16 bits in avr-gcc.

To work around this use typecasts on the operands, including literals, to declare that the values are to be 8 bit operands.

This may be especially important when clearing a bit:

Code:
var &= ~mask;  /* wrong way! */


The bitwise "not" operator (~) will also promote the value in mask to an int. To keep it an 8-bit value, typecast before the "not" operator:

Code:
var &= (unsigned char)~mask;

This made me cringe!! As all my variables are 1 byte, and I figured my code is probably 4x as long as it needs to be because of this casting to 2 bytes (since AVR is an 8-bit processor). So I added (unsigned char) in front of all my operations. Re-compiled and my code was the exact same size??
.... "Program: 1138 bytes (13.9% Full)"

I see this topic has been posted multiple times, in the forum the general consensus is you just accept it, in the FAQ it says use casting?

_________________
Just a noob in this crazy world trying to get some electrons to obey me.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Oct 25, 2009 - 06:57 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15086
Location: Vancouver, BC

In many cases the explicite cast is unnecessary. Before using casts, I would look at the assembly output to see if it is really needed.

Quote:
and I figured my code is probably 4x as long as it needs to be

Why 4 times? Surely the casting only occurs occasionally, not for every single operation.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Oct 26, 2009 - 09:02 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71696
Location: (using avr-gcc in) Finchingfield, Essex, England

Just to note that a common culprit for "bloated" code is if any of the math library function is used (this can even be */-+) and the code is not set to link against libm.a but links with inferior code in libgcc.a instead. This can "cost" up to about 3K. Another culprit is over-sized versions of printf.a being used.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Internetwarrior
PostPosted: Dec 07, 2009 - 10:37 AM
Newbie


Joined: May 06, 2009
Posts: 12
Location: Stockholm, Sweden

abcminiuser wrote:
A recent thread had a very nice solution which extends on the basic bit-manipulation macros. IIRC it went something along the lines of:

Defines:
Code:
#ifndef _AVR035_H_
#define _AVR035_H_

// from AVR035: Efficient C Coding for AVR

#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

#define SETBITMASK(x,y) (x |= (y))
#define CLEARBITMASK(x,y) (x &= (~y))
#define FLIPBITMASK(x,y) (x ^= (y))
#define CHECKBITMASK(x,y) (x & (y))

#define VARFROMCOMB(x, y) x
#define BITFROMCOMB(x, y) y

#define C_SETBIT(comb) SETBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CLEARBIT(comb) CLEARBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_FLIPBIT(comb) FLIPBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))
#define C_CHECKBIT(comb) CHECKBIT(VARFROMCOMB(comb), BITFROMCOMB(comb))

#endif


Use:
Code:
#define Status_LED  PORTA, 3

C_SETBIT(Status_LED);
C_CLEARBIT(Status_LED);


- Dean Twisted Evil
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits