Hi. Yeah, that looks like the kind of thing. Also see:

https://ece.uwaterloo.ca/~dwharder/Mapl ... Curves.ppt
Essentially what your PDF is showing is a 24-element LUT, but instead of having discrete values or linearly interpolated steps it uses a series of Bezier curves (a spline) to smooth out the curve.

You would want to implement this using 32-bit signed integers with 8-bit fixed point. It simplifies things to use floats but it will also be slower, so best to avoid this.

A cubic bezier curve is a curve with two fixed end points (anchors) and two control points that define the curve. A variable that is in the range 0-1 (usually called t) defines how far along the curve you are from the start point when t=0 to the end point when t=1. The formula for a Bezier curve is (where ^ is 'to the power of'):

Code: Select all

```
v = P0 * (1 - t)^3
+ P1 * 3 * (1 - t)^2 * (t)
+ P2 * 3 * (1 - t) * (t)^2
+ P3 * (t)^3
```

For the first curve the control points are at: 0, (2*sqrt(2) - 1) / 7, 2 * (2*sqrt(2) - 1) / 7, sqrt(2) / 2.

In 8-bit fixed point this means:

To calculate t (in 8-bit FP), we know the range of the segment of the line for this 1/8th of the curve is PI/4, so t = 256 * angle / (PI/4)

Code: Select all

```
t = 256 * angle / 0.78539816
i = 256 - t
tsq = (t * t) >> 1 // 15-bit fixed point t^2
tcu = tsq * t // 23-bit fixed point t^3
isq = (i * i) >> 1 // 15-bit fixed point (1-t)^2
icu = isq * i // 23-bit fixed point (1-t)^3
// Now calculate the point on the curve
y = (0 * icu)
y = y + (67 * (3 * isq * t))
y = y + (133 * (3 * i * tsq))
y = y + (181 * (tcu))
// y is now a 31-bit fixed point value representing sin(angle) where 0 <= angle <= PI/4
```

Of course, all this work only calculates the first 1/8th of the curve.

You have two choices now. The first is to look at the first PI/2 of the sine curve and produce an if statement for the two curves, then tweak the values depending on the angle sector, and the second is to create a look up table of all the points, get the curve segment, multiply by 4 and use the Bezier points starting at that index (LUT[ix], LUT[ix+1], LUT[ix+2], LUT[ix+3]).

This is an example of the first possibility, because not requiring look-ups saves memory overhead, which would need to be 16-bit entries, so 48 bytes of LUT (and also an ugly global variable).

Code: Select all

```
angle = angle / 0.78539816 // Divide by sin(PI/4): Integer part is the sector, decimal part is the range 0-1
sector = floor(angle)
t = 256 * (angle - sector)
if (sector & 2) // Then between PI/2 and 3*PI/2
sector = sector ^ 1
t = 256 - t
i = 256 - t
....... tsq, tcu, .....
if ((sector & 1) == 0)
// Bezier curve part 1 (use values above)
else
// Bezier curve part 2
if (sector & 4) // Then between PI and 2*PI
y = -y
result = y / 2147483648.0 // Convert 31-bit FP to a float, 0-1
```

This completely avoids floating point and should get the result required. I haven't tested this though, and have worked solely from your PDF.

What I would suggest is to use simulation in Flowcode to test any routine like this, and draw on the GLCD component to display the results.

I hope this is enough to go on. Cheers,

Jonny