Jump to content
Sign in to follow this  
SvendW

How Is The #if Directive Supposed To Work?

Recommended Posts

I'am not sure of the #if syntax, so I tried this:

 

 

#include <system.h>

 

#define PortOUT porta

 

void main()

{

while (1)

{

#if PortOUT == portb

portb = 0;

#else

#if PortOUT == porta

porta = 0;

#endif

#endif

}

 

}

 

hoping that the resulting code would set porta = 0, but it actually assigns portb.

 

Is this a compiler bug, or is #if not suited for this purpose?

 

Regards

SvendW

Share this post


Link to post
Share on other sites

Hey SvendW,

 

porta isn't assigned a value in the headers, it's only assigned an address. It could very well be possible that porta has the same value at its' location as portb when the compiler parses that code.

 

It is my understanding that the #if, #ifdef, #define stuff is only parsed by the pre-compiler anyway... by the time it comes to compiling the asm all of those statements would already be resolved.

 

I think what you're looking to do is something like:

 

char *PortOUT;

PortOUT = &porta;

 

void main()

{

while (true)

{

/* this really assignes 0 to porta */

*PortOUT = 0;

}

}

 

 

I'am not sure of the #if syntax, so I tried this:

 

 

#include <system.h>

 

#define PortOUT porta

 

void main()

{

while (1)

{

#if PortOUT == portb

  portb = 0;

#else

#if PortOUT == porta

  porta = 0;

#endif

#endif

}

 

}

 

hoping that the resulting code would set porta = 0, but it actually assigns portb.

 

Is this a compiler bug, or is #if not suited for this purpose?

 

Regards

SvendW

Share this post


Link to post
Share on other sites

Thanks SnakeByte,

I have overlooked, that the definition of ports are NOT #defines but actually variable declarations like 'char porta@0x0005;'

 

Yes, I aggree that preprocessor commands should be handled solely by the preprocessor!

 

BUT:

If I add defines like:

 

#define PORTA porta

#define PORTB portb

 

and

 

#define PortOUT PORTB

 

I would expect that:

 

#if PortOUT == PORTA

...

#else

... (This code included)

#endif

 

Using pointers like char *PortOUT = *porta would cost valuable variable space, so I would like to try and twist the preprocessor to do the job!

 

By the way: My intend is to use 'almost' the same code for single port PIC devices and multiple port PIC devices only controlled by the "Target" selection in the GUI!

 

 

Regards

SvendW

Share this post


Link to post
Share on other sites

Another way to save data and code space and make code flexible is to use function templates. This feature was borrowed from C++. It's not fully supported in BoostC yet but the part that is supported can already help.

 

For example have a function that works with a port, want to have the port selectable at compile time and don't need it to be selectable at run time. Than code like this will help you ans save a lot of code and data space:

 

template <char A>
void foo( void )
{
   char port@A;
   ... //some code that operates with port
}

void main( void )
{
   foo<5>(); //function 'foo' will deal with port A
   ...
}

 

 

Note though that because function overloading doesn't work yet it won't be possible to use same template with different template arguments:

 

    ...
   foo<5>();
   foo<6>(); //this won't link
   ...

 

Regards,

Pavel

Share this post


Link to post
Share on other sites

Hey SvendW,

 

I'm curious.. for the targets where there is only one port, does "portb" even exist in the header for that target?

Edited by SnakeByte

Share this post


Link to post
Share on other sites
Thanks SnakeByte,

I have overlooked, that the definition of ports are NOT #defines but actually variable declarations like 'char porta@0x0005;'

 

Yes, I aggree that preprocessor commands should be handled solely by the preprocessor!

 

BUT:

If I add defines like:

 

#define PORTA porta

#define PORTB portb

 

and

 

#define PortOUT PORTB

 

I would expect that:

 

#if PortOUT == PORTA

...

#else

... (This code included)

#endif

 

Using pointers like char *PortOUT = *porta would cost valuable variable space, so I would like to try and twist the preprocessor to do the job!

 

By the way: My intend is to use 'almost' the same code for single port PIC devices and multiple port PIC devices only controlled by the "Target" selection in the GUI!

 

   

Regards

SvendW

 

try adding a "-D portb" to your compiler line and see what happens.

 

Understand that the preprocessor only does text substitution... if porta or portb aren't previously defined through either a compiler directive, or through the source/headers using #define, then your code will look like this:

 

#define PORTA porta

(since porta isn't defined, neither will PORTA)

 

#define PORTB portb

(since portb isn't defined, neither will PORTB)

 

#define PortOUT PORTB

(since PORTB wasn't defined, neither will PortOUT)

 

#if PortOUT == PORTA

(this translates to if NOTHING == NOTHING) which means that it will always be true.

 

by adding that "-D portb" for the compiler, you've defined portb (it doesn't matter WHAT it's defined to). Since portb is defined,

#define PORTB portb will work, and so the rest of your code should follow as expected. At least it should if I understand this stuff correctly.... :)

 

Oops.... I just tried the -D option and the compiler gave back the error:

"warning: unrecognized command line agrument '-D', skipped"

 

My advice was after seeing this:

Useage: boostc.pic16.exe [options] files

 

Options:

-t name target processor (default name=PIC16F628)

-On optimization level (default n=1)

n=0 - optimization turned off

n=1 - optimization turned on

-Wn warning level (default n=1)

n=0 - no warnings

n=1 - some warnings

n=2 - all warnings

-di debug inline code (default off)

-D name define 'name'

-v verbose mode turned on (default off)

 

So I guess the -D hasn't been implimented yet.

Edited by SnakeByte

Share this post


Link to post
Share on other sites

Guys,

 

It looks to me like this thread is getting a bit lost.

 

I'll try to explain.

 

#ifdef, #else and #endif are used by the pre-processor.

 

This means they do there stuff prior to the actual code compilation, you use then to add or leave out code or #defines.

So they can't change things at run time.

 

here what I would do

 

#include <system.h>

// note _PIC18 is define by compiler for PIC18 targets

#ifdef _PIC18
   #define port portd
   #define tris trisd
#else
   #define port portb
   #define tris trisb
#endif


void main()
{
   tris = 0x00; // make all bits output
   port = 0x01; // turn bit 0 of port 
}

 

Hope this makes sense.

 

Oh BTW: try -d on the command line for define, looks like the case is wrong!

 

You could put -d xxxx on the compiler command line (from in IDE used Settings->Options->Compile Options->Extra compiler options and put "-d xxxx" in the box you find there)

 

Regards

Dave

Share this post


Link to post
Share on other sites
Guys,

 

It looks to me like this thread is getting a bit lost.

 

I'll try to explain.

 

#ifdef, #else and #endif are used by the pre-processor.

 

This means they do there stuff prior to the actual code compilation, you use then to add or leave out code or #defines.

So they can't change things at run time.

 

here what I would do

 

#include <system.h>

// note _PIC18 is define by compiler for PIC18 targets

#ifdef _PIC18
   #define port portd
   #define tris trisd
#else
   #define port portb
   #define tris trisb
#endif


void main()
{
   tris = 0x00; // make all bits output
   port = 0x01; // turn bit 0 of port 
}

 

Hope this makes sense.

 

Oh BTW: try -d on the command line for define, looks like the case is wrong!

 

You could put -d xxxx on the compiler command line (from in IDE used Settings->Options->Compile Options->Extra compiler options and put "-d xxxx" in the box you find there)

 

Regards

Dave

 

 

Dave,

 

Your answer looks to me to be the best solution to his problem, but my previous explanation was trying to answer why his code didn't work.

 

In the headers, things like "portb" and "trisb" only show up in the headers as:

char portb@0x0006;

char trisb@0x0086;

 

Since the preprocessor doesn't know about chars, those lines in the headers are skipped over, and the preprocessor is left with names with no associated values. Normally this is just fine.. simply leave the replaced names and let the compiler complain if that name isn't declared. The problem that SvendW ran into was how #IF works:

 

While he thought:

#if portb == porta

was really comparing the strings:

if "portb" == "porta"

it was really comparing the values that those strings were defined as. Since neither was actually defined as anything the code translated to:

nothing == nothing

 

which would always equate to true.

 

This was what I was trying to convey.

Share this post


Link to post
Share on other sites

Hi, thanks for all the explanations!

 

To Pavel:

NO porta, portb,... ARE not defined in the header file for eg. PIC12F675,

BUT gpio (the only 5 port) IS defined: This is something that eg. the LED array plugin should know (only PortA,.. are selectable)

 

 

I have learned 2 things:

 

1) To be more carefull with the preprocessor directives!

and that:

2) The BoostC IDE has an option for setting "global" defines:

Settings | Options | In the edit box named: Extra compiler options: Type in "-d[space]<your symbol to be defined>" eg. -d ExtraStuff (This would have been my next question :( )

 

Regards,

SvendW

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...