Exact match. Not showing close matches.
PICList
Thread
'[PIC]: Need help with 24F/30F/33F PICs extended pr'
2008\07\13@050918
by
Electron

[ resending: I forgot the tag, sorry :( ]
Hi,
although my knowledge of the dsPIC (without DSP) is getting better, I am now
faced with a problem I must do absolutely bug free, because otherwise precious
data would be corrupted, so I'm seeking help here.
In short I have 24bits coming from an ADC, and I have to make them 16bits, but
inside a certain range of these 24bits.
So, to say it in pseudo C:
unsigned long int adc;
unsigned long int min;
unsigned long int max;
unsigned short int out;
if (adc<=min) {
out=0;
} else if (adc>=max) {
out=65535;
} else {
out=(adcmin)*65536/(maxmin); /* needs 64bit intermediary precision */
}
pretty simple problem, if it wasn't for my knowledge of the MUL instruction
and also because of the necessary extended precision intermediary results,
but MUL and DIV are 16bit/32but instructions only. So the best I've done so
far is (given that adc, min and max are "only" 24bit values after all):
out=((adcmin)*255)/(((maxmin)*255+32768)/65536);
which doesn't need more than the normal usage of the MUL and DIV instructions.
But this is not ideal, how could I perform it in multiprecision, to implement
the "real" formula?
Could anybody help please?
With kind regards,
Mario
2008\07\13@080614
by
Tomás Ó hÉilidhe

Electron wrote:
> So, to say it in pseudo C:
>
> unsigned long int adc;
> unsigned long int min;
> unsigned long int max;
> unsigned short int out;
>
> if (adc<=min) {
> out=0;
> } else if (adc>=max) {
> out=65535;
> } else {
> out=(adcmin)*65536/(maxmin); /* needs 64bit intermediary precision */
> }
>
To scale a 24Bit value to a 16Bit value I'd shift 8 places to the right:
long unsigned Scale24to16(long unsigned original_val)
{
return original_val >> 8;
}
Then to make it more generic:
long unsigned ScaleYtoX(long unsigned const original_val, unsigned
const y, unsigned const x)
{
if (y >= x) return original_val >> yx;
else return original_val << xy;
}
Now, to complicate it, let's do it within a certain range of the 24Bit
value. Here's our 24Bit value:
111111111111111111111111
Now let's say our 16Bit value should be crafted from the following
range in the 24Bit value:
min = 2048
max = 4194304
Take the minimum value, and assign the most appropriate high bit, so
2048 becomes bit 11 (where bit 0 is the LSB).
Take the maximum value, and assign the most appropriate high bit, so
4194304 becomes bit 22.
(Yes, they're conveniently chosen)
So that means out 16Bit value should be taken from the following bits
marked with an x:
1xxxxxxxxxxxx11111111111
(That's 12 bits)
If the highest bit is set, we know that the number is out of range. If
the lower eleven are set, well they would just give us extra precision
if we wanted it. In the case of turning a 12Bit figure into a 16Bit
figure, we can use this extra precision, so that would be:
1xxxxxxxxxxxxYYYY1111111
So we shift this 7 places to the right to give:
00000001xxxxxxxxxxxxYYYY
Since we're going to discard values that are too big, we know that that
highest 1 won't be set:
00000000xxxxxxxxxxxxYYYY
I'm getting sloppy here, but altogether it might be something like:
long unsigned ScaleRangeToX(long unsigned val, unsigned const high_bit,
unsigned low_bit, unsigned const x)
{
unsigned const initial_bit_range = high_bit  low_bit;
/* First of all, let's see if the value is outside the range */
long unsigned const max_value_for_original_value = (1uL << high_bit)
 1,
min_value_for_original_value = (1uL <<
low_bit)  1,
max_value_for_return_value = (1uL <<
x)  1;
if ( original_value < min_value_for_original_value ) return 0;
if ( original_value > max_value_for_original_value ) return
max_value_for_final_value;
/* Now let's see if we can use those extra precision bits */
unsigned const amount_precision_bits_wasted = 0;
if (initial_bit_range < x)
{
unsigned const amount_extra_precision_bits = x  initial_bit_range;
if (low_bit > amount_extra_precision_bits)
{
low_bit = amount_extra_precision_bits;
amount_precision_bits_wasted = 0;
}
else
{
low_bit = 0;
amount_precision_bits_wasted = amount_extra_precision_bits 
low_bit;
}
}
/* Now clean the value up */
original_value >>= low_bit  amount_precision_bits_wasted;
return original_value;
}
The code above was thrown together in 10 minutes while I was eating my
morning porridge so it contains bugs, errors and oversights. One
particular thing I haven't paid attention to is making sure that the
number of places I shift by is less than the number of bits in the type;
for instance, if I want the highest value for 4 bits, I can do:
(1u << 4)  1
However, if I do this for 16 bits:
(1u << 16) 1
then the C Standard says the behaviour is undefined if int is 16Bit.
If you work with a range that doesn't nicely fit as a power of two, then
I think you'll have to resort to using floatingpoint arithmetic.
2008\07\13@084443
by
olin piclist
Electron wrote:
> In short I have 24bits coming from an ADC, and I have to make them
> 16bits, but inside a certain range of these 24bits.
>
> ...
>
> if (adc<=min) {
> out=0;
> } else if (adc>=max) {
> out=65535;
> } else {
> out=(adcmin)*65536/(maxmin); /* needs 64bit intermediary
> precision */ }
Take your input value and subtract off MIN. Now the rest is a scale factor
problem. If this remaining value is still wider than 16 bits, then left
justify it in a 32 bit number and divide to get the 16 bit result. If
ADCMIN always fits in 16 bits, then multiply it by a scale factor such that
the result you want ends up in 16 bits near the high end of the 32 bit
product.
********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 7429014. Gold level PIC consultants since 2000.
2008\07\14@010114
by
Vitaliy
Electron wrote:
> although my knowledge of the dsPIC (without DSP) is getting better, I am
> now
> faced with a problem I must do absolutely bug free, because otherwise
> precious
> data would be corrupted, so I'm seeking help here.
>
> In short I have 24bits coming from an ADC, and I have to make them 16bits,
> but
> inside a certain range of these 24bits.
Mario, perhaps I don't fully understand the problem  can you explain why
you can't simply drop the lower order bits? AFAIK, few applications require
more than 8bit precision.
Vitaliy
More... (looser matching)
 Last day of these posts
 In 2008
, 2009 only
 Today
 New search...