//#DOC Main, program entry and main loop
// Copied from Adafruit examples
#include "main.h"
#include <otTimer.h>
#include <otSerial.h>
#include <otPrintfLite.h>
#include <otILI9341.h>

otILI9341 tft;

const S16
  bits        = 20,   // Fractional resolution
  pixelWidth  = 320,  // TFT dimensions
  pixelHeight = 240,
  iterations  = 128;  // Fractal iteration limit or 'dwell'
float
  centerReal  = -0.6, // Image center point in complex plane
  centerImag  =  0.0,
  rangeReal   =  3.0, // Image coverage in complex plane
  rangeImag   =  3.0;
  
void setup()
{
    UartEnableSignals(UART0);
    UartSetBaud(UART0, 115200);
    TimerSetAsCounter(TIMER0);
    TimerEnable(TIMER0, true);
    setStdout(UART0); // printf output is now directed on UART0
    tft.init();
    tft.setRotation(otILI9341::IR_270);
    tft.clear();
    tft.setTextColor(RGB565_YELLOW, RGB565_BLACK);
    tft.setTextSize(3);
}

FAST_CODE_1 void loop()
{
    S64     n, a, b, a2, b2, posReal, posImag;
    U32     startTime, elapsedTime;
    
    S32
    startReal   = (S64)((centerReal - rangeReal * 0.5)   * (float)(1 << bits)),
    startImag   = (S64)((centerImag + rangeImag * 0.5)   * (float)(1 << bits)),
    incReal     = (S64)((rangeReal / (float)pixelWidth)  * (float)(1 << bits)),
    incImag     = (S64)((rangeImag / (float)pixelHeight) * (float)(1 << bits));
  
    startTime = TimerGetCounts(TIMER0);
    posImag = startImag;
    for(int y = 0; y < pixelHeight; y++)
    {
        posReal = startReal;
        for(int x = 0; x < pixelWidth; x++)
        {
            a = posReal;
            b = posImag;
            for(n = iterations; n > 0 ; n--)
            {
                a2 = (a * a) >> bits;
                b2 = (b * b) >> bits;
                if((a2 + b2) >= (4 << bits))
                    break;
                b  = posImag + ((a * b) >> (bits - 1));
                a  = posReal + a2 - b2;
        }
        #if defined(USE_BUFFER)
            buffer[y * pixelWidth + x] = (n * 29) << 8 | (n * 67);
        #else
            tft.setPixel(x, y, (n * 29) << 8 | (n * 67));
        #endif
        posReal += incReal;
        }
        posImag -= incImag;
    }
    #if defined(USE_BUFFER)
        tft.drawRGBBitmap(0, 0, buffer, pixelWidth, pixelHeight);
    #endif
    elapsedTime = TimerGetCounts(TIMER0);
    elapsedTime = ElapsedTimeUs(startTime, elapsedTime) / 1000;
    printf("Took %u ms\n", elapsedTime);

    rangeReal *= 0.95;
    rangeImag *= 0.95;
}