C to Spin Conversion issue
Greg LaPolla
Posts: 323
P is a pointer to a variable of type long (int32_t in c)
Sensor reading at idle puts out readings between 2_300 - 2_500
after a few iterations this routine is returning values above 100_000
I have tried using x.long and x.word but that doesn't seem to help at all.
In the C version they typecast x as long but in this case its already a long in the spin2 version
Here is the original C Code
// Average DC Estimator static int16_t averageDCEstimator(int32_t *p, uint16_t x) { *p += ((((long) x << 15) - *p) >> 4); return (*p >> 15); }
Here is the spin2 code
PUB averageDCEstimator(p, x): result long[p] += (((x << 15) - long[p]) >> 4) result := (long[p] >> 15) return result
Comments
Maybe that right shift of 4 needs to be an arithmetic shift in Spin?
I don't know what C does with pointers as I program mainly in Pascal - Pascal does pointer arithmetic such as if you add 1 to the pointer, it points to the next long.
In Spin you have to add 4 to the "pointer" to point to the next long
I would assume that would equate to a divide by 16 ?
Kindof, but arithmetic right shift and signed division have different rounding behavior for negative numbers.
In Spin 1 the arithmetic right shift operator is "~>". Hopefully Spin 2 has the same operator.
No, that would be too easy
The operator is now: SAR
Andy
Wonder if it would be better to have the default shift in Spin2 be arithmetic...
Being as the usual variables are signed...
Looks like C automatically decides for you which shift to use.
Right shifts in C depends on the sign attribute of the value that is being shifted. A signed value uses a signed shift, and an unsigned value uses an unsigned shift. In Spin, the type of shift is based entirely on the operator that is used. I suppose the ">>" operator could have been defined as a signed shift, but Chips chose to make it unsigned.
So divide by 16 works as well as SAR 4.
Thanks for the input
They both do similar things, but you will get slightly different results for negative numbers. (-1 SAR 4) will be -1, and (-1/16) will be zero. Also, a divide requires more cycles than a shift.
It would be more accurate to round by adding half of the shift amount before shifting down, but then you'll get different results than the Spin code produces. So for a shift of 4 you would first add 2^3 = 8, and for a shift of 15 you would add 2^14 = 16384. However, if the Spin code works fine without rounding I wouldn't bother with rounding in the C code.
No, divide by 16 is the same as SAR 4 only for positive numbers. For negative numbers they are different. Use SAR 4, it's much faster than divide anyway.