> I'm working on an Atmel AT89C51RD2 based circuit that will need to slide
> between two arbitrary DAC values at a constant time. I have a 1msec timer
> that decrements (or increments) the DAC counters in a particular direction.
> Mathematically I know how to do it -
>
> abs(DACStart - DACEnd) / # of milliseconds = Amount to step each 1ms
>
> However I'm on an 18Mhz 6 cycle Atmel AT89C51RD2 , and worst case for a 32
> bit divide is somewhere in the 500usec range. I need it to be under 300usec
> in order to keep up with an incoming data stream. So I'm trying to avoid
> doing a divide and instead somehow use a multiply. The DAC Start and DAC End
> values are completely arbitrary - they can be any value, so doing table
> lookups is not a possibility. ;-(
What are the DAC resolutions - 8 bits in the PCA, or more external ? I can see the above eqn would have rounding errors, but if you tuned both the step size, and the 1ms time, a better slope-fit would result.
Work out your numeric limits, and what the tolerances are, and you get a handle on the number of bits of precision needed.
The 8051 gives 16 bit results in both MUL and DIV[REM], so you might get enough from that with some carefull scaling.
Try as I may, I haven't been able to come up with an algorithm that works.
> Everything either scales wrong or my remainder gets truncated. I have a 16
> bit integer part and an 8 bit decimal (16.8 fixed point) for step values,
> and need something similar.
>
> Is there any trick I'm missing? Or, does anyone know of a 24x8 divide
> routine for the 8051 style of CPU that takes under 300usec worst case? Or a
> 16x8 divide that gives me a remainder?
Divide routines will give a remainder, but it is not always preserved. I recall we changed our Mod51 libraries to keep the remainder intact, usefull for formatted writes - allowed N MOD 10 and N DIV 10 in a single call.
-jg