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
cinderblock
PostPosted: Jan 20, 2009 - 10:30 PM
Rookie


Joined: Dec 23, 2008
Posts: 25


My first tutorial:

A philosophy of mine for programming is eliminating repeated code as much as possible. Because of this I've always been "annoyed" at code like this for use in generalized functions:
Code:
// Defines like this
#define LED_PORT PORTB
#define LED_DDR  DDRB
#define LED_PIN  PINB
#define LED_BIT  1

// To make this code more general
LED_DDR  |= 1<<LED_BIT; // Set output
LED_PORT |= 1<<LED_BIT; // Turn on
LED_PIN  |= 1<<LED_BIT; // Toggle

This may not look repetitive, but I wanted to make it look like this using a macro:
Code:
#define LED_PORT B
#define LED_PIN  1

DDR(LED_PORT)  |= 1<<LED_PIN;
PORT(LED_PORT) |= 1<<LED_PIN;
PIN(LED_PORT)  |= 1<<LED_PIN;

This simplifies the defines that need to be adjusted for different boards but makes the actual code a little different.

If anyone else has tried to do this, the knee-jerk is to use these macros:
Code:
#define PORT(port) PORT ## port
#define DDR(port)  DDR  ## port
#define PIN(port)  PIN  ## port

Unfortunately, this does not work. You get errors saying something to the effect of PORTLED_PORT undefined that will force most to give up and use the standard of a separate define for PORT, DDR, and PIN. What happens is the compiler actually appends the literal LED_PORT to PORT instead of taking the value we defined LED_PORT to be.

Fortunately, there is a workaround for this. You just need an extra macro step:
Code:
#define PORT_(port) PORT ## port
#define DDR_(port)  DDR  ## port
#define PIN_(port)  PIN  ## port

#define PORT(port) PORT_(port)
#define DDR(port)  DDR_(port)
#define PIN(port)  PIN_(port)

I hope someone likes & uses this!
 
 View user's profile Send private message  
Reply with quote Back to top
dikhet
PostPosted: Jan 22, 2009 - 10:21 AM
Newbie


Joined: Sep 24, 2007
Posts: 5


hi, i got a nice code to define i/o port. The author is Tomasz Ostrowski so all credit belong to this man.

Code:

// define electric connections according to your circuit, DATA line
#define DATA_PORT      PORTB
#define DATA_DDR      DDRB
#define DATA_PINPORT   PINB
#define DATA_PIN      0
#define SWITCH_DATA_IN  DATA_DDR &= ~_BV(DATA_PIN)
#define SWITCH_DATA_OUT DATA_DDR |= _BV(DATA_PIN); NOP   ///< \todo is NOP needed?
#define CLEAR_DATA      DATA_PORT &= ~_BV(DATA_PIN)
#define SET_DATA        DATA_PORT |= _BV(DATA_PIN)
#define DATA            (DATA_PINPORT & _BV(DATA_PIN))


and i add 'toggle' function to the code
Code:

#define TOGGLE_DATA        DATA_PORT ^= _BV(DATA_PIN)



i usually write this in ionames.h then i included this file to my main program.

hope you like it.
 
 View user's profile Send private message  
Reply with quote Back to top
robwasab
PostPosted: Dec 20, 2011 - 12:56 AM
Newbie


Joined: Aug 01, 2011
Posts: 13


hey cinderblock,

very very clean code, I only wish I knew what your macros are actually doing, your code makes the most sense... once you get to use it in your code.

Thanks for your help.
 
 View user's profile Send private message  
Reply with quote Back to top
westfw
PostPosted: Dec 20, 2011 - 02:11 AM
Resident


Joined: Jun 19, 2002
Posts: 983
Location: SF Bay area

Quote:
You just need an extra macro step

Warning: there are a bunch of things in the area of macro expansion and stringification and concatenation and the performance order thereof that are NOT DEFINED in the C standard, and therefore subject to change when you switch compilers or versions of a compiler...

In fact, we had a grand old time when the behavior changed between gcc 3.4.5 and 4.1 (or something like that.)
 
 View user's profile Send private message  
Reply with quote Back to top
Torby
PostPosted: Dec 20, 2011 - 02:56 PM
Raving lunatic


Joined: Nov 11, 2003
Posts: 4040
Location: Chicago Illinois USA

Now I've always wondered why we don't define our bits this way:

Code:

#define BLUE_LED 1
#define RED_LED  2
#define GREEN_LED 4

So we could just set:

DDRB = BLUE_LED | RED_LED | GREEN_LED


_________________
Discursive design,

Torby

Some days, it's just not worth chewing through the restraints.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
david.prentice
PostPosted: Dec 20, 2011 - 03:17 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 16544
Location: Wormshill, England

Code:

#define BLUE_LED_bm 1
#define RED_LED_bm  2
#define GREEN_LED_bm 4

So we could just set:

DDRB = BLUE_LED_bm | RED_LED_bm | GREEN_LED_bm


It would be far more natural to use bit_masks instead of bit_positions. However the Atmel data sheets chose bit_positions.

I have always assumed that this was because some ASM ops use bit_positions e.g.
Code:
    SBRS   r16,3


There are many different schemes for describing special_bits in special function registers. Personally, I like the bitfield_structure used by PIC (and others).

It is a historic thing. I suspect that the early compilers were not clever enough. Hence we are stuck with the bit_position scheme.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
clawson
PostPosted: Dec 20, 2011 - 03:18 PM
10k+ Postman


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

Quote:

Now I've always wondered why we don't define our bits this way:

Funny I gave the answer to this very question yesterday.

http://www.avrfreaks.net/index.php?name ... 923#903923

Nothing stops you defining bit masks rather than bit numbers if you prefer. In fact if you are willing to live without io.h (or whatever it's called in your compiler) you can redefine the entire set of SFRs and bit names if you like except that it would hugely confuse anyone else trying to use the code if they assumed registers/bits defined the "normal" way. One possibility is to use a case change to avoid name pollution such as:
Code:
#define Txen 0x08
#define Rxen 0x10

UCSRB = Txen | Rxen;

Another alternative is:
Code:
typedef struct {
 uint8_t Txb8:1;
 uint8_t Rxb8:1;
 uint8_t Ucsz2:1;
 uint8_t Txen:1;
 uint8_t Rxen:1;
 uint8_t Udrie:1;
 uint8_t Txcie:1;
 uint8_t Rxcie:1;
} UB_t;

#define Ucsrb (*(volatile UB_t *)0x2A)

Ucsrb.Txen = 1;

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
blarkavr
PostPosted: Jun 27, 2012 - 05:02 PM
Rookie


Joined: Oct 26, 2011
Posts: 29


Hey guys,

I'm a bit of a C noob, but this seems like the correct thread. Any chance you could help me out here a bit? Currently I'm doing this in my code:

Code:
#define LED0 PA0 // assign LED names to output ports on the attiny84
#define LED1 PA1
#define LED2 PA2
#define LED3 PA3
#define LED4 PA4
#define LED5 PA5
#define LED6 PA6
 
#define LED0_CLEAR (pin_level &= ~(1 << LED0))
#define LED1_CLEAR (pin_level &= ~(1 << LED1))
#define LED2_CLEAR (pin_level &= ~(1 << LED2))
#define LED3_CLEAR (pin_level &= ~(1 << LED3))
#define LED4_CLEAR (pin_level &= ~(1 << LED4))
#define LED5_CLEAR (pin_level &= ~(1 << LED5))
#define LED6_CLEAR (pin_level &= ~(1 << LED6))
 
// Set bits corresponding to pin usage above
#define PORT_MASK  (1 << PA0)|(1 << PA1)|(1 << PA2)|(1 << PA3)|(1 << PA4)|(1 << PA5)|(1 << PA6)


It seems silly to me, can you guys recommend a way to condense this? Note: This is for a led fader project, and the amount of LEDs is variable (based on chip selection and well, how many LEDs you want to hook up) so I would like to write code that based on a CHMAX variable will automatically set things up correctly.

Thanks in advance for your advice and help!
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jun 27, 2012 - 05:11 PM
Moderator


Joined: Jan 23, 2004
Posts: 9878
Location: Trondheim, Norway

Note that the XMEGA and UC3 device headers *do* contain bit masks as well as (in some cases) bit positions. They also contain group masks, so code for them usually looks quite clean.

- Dean Twisted Evil

_________________
Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Jun 27, 2012 - 07:03 PM
10k+ Postman


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

Quote:

Any chance you could help me out here a bit?

What is "pin_level" in the code you show?

(BTW not entirely sure a tutorial thread is the right place for this - usually the following thread is just to suggest improvements to the tutorial).

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
blarkavr
PostPosted: Jun 28, 2012 - 12:24 AM
Rookie


Joined: Oct 26, 2011
Posts: 29


Hmm. OK I will re post to another thread. Sorry folks!
 
 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