Problem With Division, Types, and Casting

Hi I'm writing some lower level code for an Attiny85 and have a CPP file that does the heavy lifting for the arduino. I'm using the Tiny Cores found on google code.

Anyway, I have simplified down my expression to the following to showcase where the problem is:

static volatile float timerPeriodMicros;
static volatile uint32_t Period;
static volatile uint16_t PrescalerVal;
#define FCPU 8000000
...

function GetPeriod(void)
{
TimerPeriodMicros = (PrescalerValue/FCPU) * 1000000; //returns zero always. It should return something like 512 or Timer1 Tick period
//Re-arranging the math to PrescalerValue*(1000000/FCPU) also fails
//Re-arranging the math to PrescalerValue*.125 works!
Period = TimerPeriodMicros * PeriodTicks;
return Period;
}

Any suggestions would be helpful!

Thanks!

PrescalerValue/FCPU

Unless PrescalerValue is greater then FCPU (unlikely), the result is 0.

Why? And what's the remedy?

Well, to start with, you are attempting 32 bit math with 16 bit integers.

static volatile float timerPeriodMicros;
...
static volatile uint16_t PrescalerVal;
#define FCPU 8000000
...

function GetPeriod(void)
{
TimerPeriodMicros = (PrescalerValue/FCPU) * 1000000; //returns zero always. It should return something like 512 or Timer1 Tick period

You showed us a snippet, not your entire code. :disappointed_relieved: However, without knowing what value PrescalerValue holds, I am going to guess that the division results in 0. Remember that when it comes to integers, smaller_number/larger_number will result in zero. The reult of the division is truncated; even 0.9 becomes 0.
Furthermore, 8000000 and 1000000 are too large for 16 bit integers. Follow them with an 'L' to turn them into 32 bit integers, e.g. 8000000L and 1000000L.

There is probably more, but that may help for a start.

Prescaler Holds an integer value between 1 and 16384

Yes, I understand about Integer Division, but I have defined TimerPeriodMicros as a float. That allows decimals, to my understanding... Does implicit casting not work that way? Do I need to cast as float on the right hand side of the equation?

I guess I'm just thrown off. Also, I'd like to accomplish my math in one line versus two lines like above.

This seems to work:

#define FCPU 8000000L

timerPeriodMicros = ((float)PrescalerVal/(float)FCPU)*(float)1000000L;//.125*PrescalerVal;
period = timerPeriodMicros * periodTicks;//period in microseconds//implicitly cast
return period;

But is there a cleaner or better solution? What's the best way to approach this?

you are attempting 32 bit math with 16 bit integers.

Nah. Using a constant longer than 16bits will automatically invoke 32bit math.

TimerPeriodMicros = (PrescalerValue/FCPU) * 1000000;

While TimerPeriodMicros is float, in C that does not cause any calculations on the right hand side to be done with floating point math, unless it's required for some other reason. So "PrecalerValue/FCPU" is treated as integers, and will result in zero since FCPU is always bigger than PrescalerValue. Multiplying that by 1000000 is still integer math, but is also still zero. The final result will be converted to a float before being assigned to TimerPeriodMicros, since THAT variable is a float. But it's STILL zero!

You should try:

TimerPeriodMicros = (PrescalerValue*1000000)/FCPU;

You might not even need the result to be a float (the timer periods aren't going to be floats, after all.)
If you want to do the calculations in floating point, that will work too, and you only need to cast ONE of your RHS numbers to be a float to get it done. (The first calculation, prefereably):

timerPeriodMicros = ((float)PrescalerVal/FCPU)*1.0e6;