How to bring values in as options

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

How to bring values in as options

Post by SHughes_Fusion » Mon Jul 21, 2014 3:33 pm

I'm writing a library for the RFM73 2.4GHz transceiver and I'm struggling with how to bring options in.

For example, you can set the address width to either 3, 4 or 5 bytes.

I tried setting up consts as AW3bytes = 1, AW4Bytes = 2 and AW5Bytes = 3 - the values are what you write to the register to set those address widths.

The intention is to allow the user to set #option RFM_AddressWidth = AW4Bytes (or whatever).

I set #option RFM_AddressWidth = AW5Bytes in the module as a default.

However, when I try and access this value I can't work out what I need to do. I've tried using const R_AddrW = RFM_AddressWidth but it won't let me use this as a parameter in the routine I call to set the address width.

I've ended up using a series of #if / #elseif / #endif statements but I'm wondering if there is a better way to do this?

The hardware SPI modules seem to do something similar for spiOscDivxx but I can't fathom how to do it in my application. Is the preprocessor documented in detail anywhere? The in-built help files seem to assume a high level of prior knowledge.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: How to bring values in as options

Post by Jerry Messina » Mon Jul 21, 2014 8:37 pm

It's a little confusing at first, but to put it simply:

The preprocessor doesn't have visibility of the language elements/syntax... just other preprocessor statements.
If you mix this up it may APPEAR to work in that you don't get any compiler errors, but things won't evaluate the way you'd expect.


With that in mind, try some of these out and see what happens

Code: Select all

// does NOT work
const EA = $100			' try $101, 0, and $100
#define _EA = EA        ' ** can't assign a CONST to a #define (or #option) **

#if (_EA > $100)        ' this doesn't evaluate as expected...
  #warning "_EA > $100"
#elseif (_EA = 0)
  #warning "_EA = 0"
#else                   ' this condition is always true no matter what the value of EA is
  #warning "_EA <= $100"
#endif
and likewise

Code: Select all

// does NOT work either... 
const EA = 0

#if (EA > $100)        ' this doesn't evaluate as expected... preprocessor can't see language element
  #warning "EA > $100"
#elseif (EA = 0)
  #warning "EA = 0"
#else                    ' this condition is always true no matter what the value of EA is
  #warning "EA <= $100"
#endif

But, if you turn it the other way around the compiler CAN see preprocessor statements...

Code: Select all

// this works
#define _EA = $0        ' try $101, 0, and $100
const EA = _EA          ' "bring in" the value... the compiler can see preprocessor

#if (_EA > $100)
  #warning "_EA > $100"
#elseif (_EA = 0)
  #warning "_EA = 0"
#else
  #warning "_EA <= $100"
#endif
Perhaps you could show an example of what you're trying to do (even if it doesn't work)

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: How to bring values in as options

Post by SHughes_Fusion » Tue Jul 22, 2014 7:40 am

Hi Jerry,

Maybe that is what I'm doing wrong. I've used Const to define the values I want to pass:

Code: Select all

Public Const    AW3Bytes = 1,                   // Options for address width
                AW4Bytes = 2,
                AW5Bytes = 3

#option RFM_AddressWidth = AW5Bytes             // Default to 5 byte address width
Const R_AddressWidth = RFM_AddressWidth
When I try and use R_AddressWidth I get an error and looking at the code explorer it shows R_AddressWidth = AW5Bytes rather than showing 3 as I'd expect.

What I'm trying to do is to allow the user of the library to over-ride the RFM_AddressWidth option but as the numeric values don't tie up with the values you need to write to the register to set a particular address width I was hoping to use named constants.

At the moment I'm getting around it by using conditional compilation, having:

Code: Select all

  #if RFM_AddressWidth = 3 
    RFM70_Write_Reg( SETUP_AW, AW3Bytes)  //B0_SETUP_AW )
  #elseif RFM_AddressWidth = 4 
    RFM70_Write_Reg( SETUP_AW, AW4Bytes)
  #elseif RFM_AddressWidth = 5  
    RFM70_Write_Reg( SETUP_AW, AW5Bytes)
  #else
    #error "RFM_AddressWidth must be 3, 4 or 5 only"
  #endif
Which isn't that elegant and as there are several options to be configured there are going to be a few of these code blocks. I'd prefer to just call the Write_Reg command with a value set in the option in the first place.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: How to bring values in as options

Post by Jerry Messina » Tue Jul 22, 2014 10:23 am

That's what it sounded like you were doing.

The # preprocessor settings don't have to be pre-defined... they ARE the definition. They're like some sort of variant data type
that can be set to just about anything.

How about something like this? It still uses #if/#else, but just to define the const value to use

Code: Select all

// if desired, set option selection (this will override default)
// this is usually in the main project module, before the include
'#option RFM_AddressWidth = AW3Bytes


// check to see if user has set the option, and if so that it's valid
// note: this step is optional, but it'll do a sanity check on any "#option = ' setting right off the bat
#if (isoption(RFM_AddressWidth) and not (RFM_AddressWidth in (AW3Bytes, AW4Bytes, AW5Bytes)))
  #error "invalid RFM_AddressWidth option"
#endif  
// set default option value
#option RFM_AddressWidth = AW5Bytes             // Default to 5 byte address width

// define addr width const based on option setting
#if (RFM_AddressWidth = AW3Bytes)
  const R_AddressWidth = 1
  #warning "selection 1"                // these warning msgs can be removed... just here for display
#elseif (RFM_AddressWidth = AW4Bytes)
  const R_AddressWidth = 2
  #warning "selection 2"
#elseif (RFM_AddressWidth = AW5Bytes)
  const R_AddressWidth = 3
  #warning "selection 3 (default)"
#else                                   // not a valid choice... generate an error
  #error "invalid selection"            // good idea to have this if there's no 'isoption' value check                
#endif


// use addr width in code
dim b as byte

b = R_AddressWidth

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: How to bring values in as options

Post by SHughes_Fusion » Tue Jul 22, 2014 11:00 am

Thanks, Jerry, I'll consider if that option is better than what I'm doing. Doesn't look like I can do what I'd like so it is a case of working how to best implement it with #if commands.

I've realised that the SPI module doesn't use the spiOscDiv as an option but it is used to call a sub. That is the difference between what I am trying to do and what it does.

I'm now trying to get my head around whether the way I set the oscillator divisor in this module via an option actually works or not....

Post Reply