From: Robby on
Hello,

Igor, I hope you are still around, I would really like to persue what we
were talking about in the previous thread. I know this seems like we are
going backwards here, but the trouble I am having has more to do on structure
than coding... and ofcourse my lack of experience in C ! :-)

I hope all this will lead up to what I am looking for. Sometimes I have a
hard time putting this stuff into words.

Okay, I like your proposition of the two functions. So let me start with
that. There is a first problem that I am running into. I did the two
functions. The first one called set_curr_sys_osc() and the second one called
get_curr_sys_osc(). Here is what I did so far, I will try to keep it short:

=============================test.h
#ifndef TEST_H
#define TEST_H

#define COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv) \
(((float)(extCrys/fpllidiv)*(float)(fpllmul/fpllodiv))*1000000)

extern static float the_sys_osc; //< store the SYS_CURR_OSC value here!
#endif // TEST_H //

=================================test.c
#include <stdio.h>
#include "test.h"

// In exactly one .c file.
static float the_sys_osc=0;

void set_curr_sys_osc(float extCrys, float fpllidiv, float fpllmul, float
fpllodiv)
{
the_sys_osc = COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv);
}

int get_curr_sys_osc()
{
return (int) the_sys_osc;
}

int main()
{
set_curr_sys_osc(8.0, 2.0, 21.0, 8.0);

// >>> SYSTEMConfig() is not one of my functions!
//SYSTEMConfig((int)get_curr_sys_osc(), SYS_CFG_ALL);

return 0;
}
=======================================

The above code generates the following error:

1>c:\_dts_programming\pic\_microchip_issues\simulated in
vc++\define_macros\define_macros\define_macros\test.h(13) : error C2159: more
than one storage class specified

It seems to point to the extern value I created. I did this extern variable
like all the others.... meaning:

- declaring it in the header file
- innitializing it in exactly one .c file
- using it in a function of test.c

Why the error?

Please get back!

--
Sincere regards
Roberto
From: Igor Tandetnik on
Robby <Robby(a)discussions.microsoft.com> wrote:
> Okay, I like your proposition of the two functions. So let me start
> with that. There is a first problem that I am running into. I did the
> two functions. The first one called set_curr_sys_osc() and the second
> one called get_curr_sys_osc(). Here is what I did so far, I will try
> to keep it short:
>
> =============================test.h
> #ifndef TEST_H
> #define TEST_H
>
> #define COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv) \
> (((float)(extCrys/fpllidiv)*(float)(fpllmul/fpllodiv))*1000000)

Why do you want this macro in the header file? Are users of this module expected to use it? In fact, it's not clear to me why you need this macro in the first place.

On the other hand, you are talking about the two functions - but you didn't place _their_ declarations into the header. How are clients supposed to call them?

> extern static float the_sys_osc; //< store the SYS_CURR_OSC value
> here! #endif // TEST_H //

There ain't no such thing as "extern static". The two qualifiers have precisely opposite meaning are cannot be combined.

The variable is an internal implementation detail, it shouldn't be in the header.

> =================================test.c
> #include <stdio.h>
> #include "test.h"
>
> // In exactly one .c file.
> static float the_sys_osc=0;
>
> void set_curr_sys_osc(float extCrys, float fpllidiv, float fpllmul,
> float fpllodiv)
> {
> the_sys_osc = COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv);
> }
>
> int get_curr_sys_osc()
> {
> return (int) the_sys_osc;

Why do you store the value as float when you always cast it to int anyway?

> }
>
> int main()
> {
> set_curr_sys_osc(8.0, 2.0, 21.0, 8.0);
>
> // >>> SYSTEMConfig() is not one of my functions!
> //SYSTEMConfig((int)get_curr_sys_osc(), SYS_CFG_ALL);

get_curr_sys_osc already returns int, no need to cast.

> The above code generates the following error:
>
> 1>c:\_dts_programming\pic\_microchip_issues\simulated in
> vc++\define_macros\define_macros\define_macros\test.h(13) : error
> C2159: more than one storage class specified

Like I said, no such thing as "extern static".
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925

From: Robby on
> The above code generates the following error:
>
> 1>c:\_dts_programming\pic\_microchip_issues\simulated in
> vc++\define_macros\define_macros\define_macros\test.h(13) : error C2159: more
> than one storage class specified
>
> It seems to point to the extern value I created. I did this extern variable
> like all the others.... meaning:
>
> - declaring it in the header file
> - innitializing it in exactly one .c file
> - using it in a function of test.c
>
> Why the error?

I got it to work, I had to change:

extern static float the_sys_osc;

to

extern float the_sys_osc;

I will continue with the two functions resolution and post back if there is
problems.
Please watch this thread. Thanks!

Rob
From: Robby on
Igor, you have done it again,

You have inspired me to persist on a resolution you provided and I finally
got it to work. I really, really want to thank you very much.

>Why do you want this macro in the header file? Are users of this module expected >to use it?

Hum, these the questions I am not too clear about yet. But I don't know yet
if users of this module will need to use it... I mean now that we have done
the three functions... its not clear to me either. Perhaps, one might need to
re-compute the current system oscilation value from the macro _again_ !!!

>In fact, it's not clear to me why you need this macro in the first place.

Yeah your right, but I use it in one of the functions, and I need practice
with these macros. I know, its a cheap excuse. :-)

>There ain't no such thing as "extern static". The two qualifiers have precisely >opposite meaning are cannot be combined.

Understood. I fixed it.

In any case Igor, I don't know if what I have done can be improved... by
your or this forum's standars, I suppose so, but I am quite happy with what
I have done. It all runs perfectly in MPLAB, so I haven't tried it in VC but
it does compile without error. So all I did was copy and paste from MPLAB IDE
to VC IDE. Here you can see why sometimes things are hard for me to explain
because I am thinking of everything else that goes on at the same time.
Please view what I have done, and if there is any other recomendations (I am
sure you will have!!!) let me know. But as I say, you have very much helped
me a great deal and I am happy with this so far.

The idea was to store the system frequency clock in a variable and then use
that variable to calculate a precise delay time in milli-seconds or
micro-seconds by simply calling a delay function on the fly. Even though
there are better ways to do delays, when bit banging at very short delays,
calling a delay function on the fly is very convinient. I have created 2 of
these delay functions, one for milli-seconds and another for micro-seconds.
Now, even if I decide to speed up the processor, these delay functions will
take into account all the overhead instructions and still carry out the
correct delays.

Here is the code:

========================KERNEL.h
#ifndef KERNEL_H
#define KERNEL_H

#define COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv) \
(((float)(extCrys/fpllidiv)*(float)(fpllmul/fpllodiv))*1000000)

extern float curr_sys_osc;

void set_curr_sys_osc(float extCrys, float fpllidiv, float fpllmul, float
fpllodiv);
int get_curr_sys_osc();
float get_osc_period();

#endif // KERNEL_H //

=========================KERNEL.c
#include <stdio.h>
#include "KERNEL.h"
#include "MYLIB.h"

// In exactly one .c file.
static float curr_sys_osc=0;

void set_curr_sys_osc(float extCrys, float fpllidiv, float fpllmul, float
fpllodiv)
{curr_sys_osc = COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv);}

int get_curr_sys_osc()
{return (int) curr_sys_osc;}

float get_osc_period()
{return (1/curr_sys_osc);}

int main()
{
set_curr_sys_osc(8.0, 2.0, 21.0, 8.0);
SYSTEMConfig(get_curr_sys_osc(), SYS_CFG_ALL); // Config wait states

// do something...

// Now I can call a delay routine on the fly
// no matter what I set my system frequency to.
delay_us(100);

// other code....
return 0;
}

=========================MYLIB.h
#ifndef MYLIB_H
#define MYLIB_H

#include "KERNEL.h"

// MILLI-SECOND DELAY FUNCTION @ optimization :0:
#define MILLI_SEC 0.001

// MICRO-SECOND DELAY FUNCTION @ optimization :0:
#define MICRO_SEC 0.000001

// INSTRUCTION CYCLES REQUIRED FOR DELAY FUNCTIONS @ optimization :0:
#define OVERHEAD_IC 67 // 67 overhead instructions
#define DELAY_LOOP_IC 8.0 // Instructions in the delay loop + ext # brch
in loop
#define LOOPS_REMOVE(a,b) (a/b) // Calculates dleay loops to remove
#define RATIO(a,b,c) (a/(b*c)) // Figures out ratio to apply to scale freq

void delay_ms(unsigned int ms_delay);
void delay_us(unsigned int us_delay);

#endif //MYLIB_H

===============================MYLIB.c
#include "MYLIB.h"

void delay_us(unsigned int us_delay)
{
unsigned int t;
float x,y;

x = ((float)RATIO((float)MICRO_SEC, get_osc_period(), (float)DELAY_LOOP_IC))
* (float)us_delay; //Ratio constant @ x-MHZ!

// Test if < shortest time possible !
if(x < (LOOPS_REMOVE((float)OVERHEAD_IC, (float)DELAY_LOOP_IC)))
t = 1; // Sys Osc is too slow... apply minimum delay!
else
{
// Get number of while loops to remove
y = (float) LOOPS_REMOVE((float)OVERHEAD_IC, (float)DELAY_LOOP_IC);

// Remove amount of while loops to compensate by time lost by overhead
//instructions
t = (int)(x-y);
}

while(--t) // do the delay!
{}
}


void delay_ms(unsigned int ms_delay)
{
unsigned int t;
float x,y;

x = ((float)RATIO((float)MILLI_SEC, get_osc_period(), (float)DELAY_LOOP_IC))
* (float)ms_delay;

// Test if < shortest time possible !
if(x < (LOOPS_REMOVE((float)OVERHEAD_IC, (float)DELAY_LOOP_IC)))
t = 1; // Sys Osc is too slow... apply minimum delay!
else
{
// Get number of while loops to remove
y = (float) LOOPS_REMOVE((float)OVERHEAD_IC, (float)DELAY_LOOP_IC);

// Remove amount of while loops to compensate by time lost by overhead
// instructions
t = (int)(x-y);
}

while(--t) // do the delay!
{}
}

=========================================

I am sure that more can be done to improve the MYLIB.c/.h module. But for
now, I will leave it like this.

Igor, I thank you for your insight, advice and most imporatant, your
constant assistance you give me time after time.

Sincere regards
Roberto

From: Ulrich Eckhardt on
Robby wrote:
> #define COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv) \
> (((float)(extCrys/fpllidiv)*(float)(fpllmul/fpllodiv))*1000000)

Why? Why isn't this a function?

> extern float curr_sys_osc;

This says: There is a global variable for anyone to access. However, zero
documentation on how to use it...

> void set_curr_sys_osc(float extCrys, float fpllidiv,
> float fpllmul, float fpllodiv);
> int get_curr_sys_osc();
> float get_osc_period();

All these seem to have something to do with the above global variable.

> // In exactly one .c file.
> static float curr_sys_osc=0;

This says: Create a variable accessible _only_ in this file. This conflicts
with the declaration in the header.

> void set_curr_sys_osc(float extCrys, float fpllidiv, float fpllmul, float
> fpllodiv)
> {curr_sys_osc = COMPUTE_SYS_OSC(extCrys, fpllidiv, fpllmul, fpllodiv);}

The macro is used here, where else? I guess nowhere, so move it into this
source file. Further, since even here it seems to only be used once, so you
don't need it at all. Macro are a simple text substitution mechanism
without any type checking. Adding all the casts you have in there, you get
zero checking. This is a recipe for disaster and bad programming.

> int get_curr_sys_osc()
> {return (int) curr_sys_osc;}
>
> float get_osc_period()
> {return (1/curr_sys_osc);}

Why not get_curr_sys_osc_period()? Why not get_curr_sys_osc_frequency()?
Also, these in combination with set_curr_sys_osc() show that curr_sys_osc
should not be global and visible everywhere.

Mylib.c/h are the same, too many global macros, too much type casting.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932