#include <FastLED.h>

//
// Array of sine raised to the power of 4 and scaled to the range 0 to 255 in fixed point Q15 notation.
// Range: 0 to 90 degrees.
// Resolution: 1 degree per step.

// abs(sin(x))^3 * sin(x) has the same magnitude as sin(x)^4 which fits into a 23-bit range leaving
// 8 bits spare for the brightness of the LED if using int32_t.

// Here is demo that uses a look-up table for sine raised to the power of 4, scaled to 255 for the LED brightness,
//  and converted to Q15, with some bit shifting to obtain the brightness of the LED.
//
const int32_t sin4[] =
{
  0,
  1,
  12,
  63,
  198,
  482,
  998,
  1843,
  3135,
  5004,
  7598,
  11076,
  15614,
  21396,
  28621,
  37495,
  48233,
  61056,
  76194,
  93877,
  114340,
  137818,
  164548,
  194761,
  228688,
  266553,
  308573,
  354958,
  405908,
  461610,
  522240,
  587960,
  658914,
  735233,
  817028,
  904389,
  997390,
  1096080,
  1200489,
  1310622,
  1426462,
  1547967,
  1675073,
  1807688,
  1945697,
  2088960,
  2237312,
  2390562,
  2548496,
  2710875,
  2877438,
  3047898,
  3221949,
  3399262,
  3579486,
  3762255,
  3947180,
  4133860,
  4321873,
  4510789,
  4700160,
  4889530,
  5078434,
  5266398,
  5452942,
  5637583,
  5819836,
  5999215,
  6175236,
  6347418,
  6515284,
  6678368,
  6836210,
  6988362,
  7134387,
  7273865,
  7406390,
  7531576,
  7649053,
  7758476,
  7859519,
  7951880,
  8035284,
  8109479,
  8174242,
  8229378,
  8274719,
  8310129,
  8335498,
  8350751,
  8355840  // sin(0.5 * PI)^4 x 255 x 2^15
};

const int32_t Q15_HALF = 2 ^ 14;

void setup()
{
  Serial.begin(115200);
}

float fmap(float x, float a, float b, float c, float d)
{
      float f=x/(b-a)*(d-c)+c;
      return f;
}

// long lmap(long x, long a, long b, long c, long d)
// {
//       return x/(b-a)*(d-c)+c;
// }


int32_t ld_max = 4000;
int32_t ld_min = -4000;

void loop()
{
    float rotationSpeedFloat = 6.3;
    int lineWidth = 3;
    int32_t input = (int16_t)round(millis() * rotationSpeedFloat) ;
    int32_t factor = sin16(input); // = divide by 32, but no messy decimals
    int32_t twoFactor = sin16(input) >> 7; // = divide by 32, but no messy decimals
    int32_t absFactor = abs(round(pow(twoFactor,3))) >> 7;
    int32_t largeDelta = (absFactor) * twoFactor;
    int32_t mapped = fmap(largeDelta,ld_min,ld_max,-32767,32767) + 32767;
    Serial.print(factor);
    // Serial.print(",");
    // Serial.print(ld_min);
    // Serial.print(",");
    // Serial.print(largeDelta);
    Serial.print(",");
   Serial.print(mapped);
    Serial.println();

    if( largeDelta > ld_max ) {
      ld_max = largeDelta;
    }

    if( largeDelta < ld_min){
      ld_min = largeDelta;
    }

    // yMax = 294000

  // for (int x = 0; x <= 180; x++)
  // {
  //   int absX = abs(x);
  //   int32_t sin4AbsX = sin4[absX];
  //   int32_t brightness = (sin4AbsX + Q15_HALF) >> 15;
  //   Serial.println(sin4AbsX);
  //   analogWrite(3, brightness);
  //   delay(100);
  // }
}