SWO+USB Serial+TouchScreen Demo

Dependencies:   BSP_DISCO_F429ZI LCD_DISCO_F429ZI SWO TS_DISCO_F429ZI USBDEVICE mbed storage_on_flash

Fork of DISCO-F429ZI_LCDTS_demo by ST

main.cpp

Committer:
pierrebizouard
Date:
2018-03-20
Revision:
9:62df0b9df08d
Parent:
7:9276134bb25e
Child:
10:1e21661f4e04

File content as of revision 9:62df0b9df08d:

//#define USB_STM_HAL
//#define DISCO
#define LANDSCAPE_MODE

#include "mbed.h"


#include "SOFBlock.h"


#include "stm32f429i_discovery_sdram.h"
#include "TS_DISCO_F429ZI.h"
#include "LCD_DISCO_F429ZI.h"
#include "USBSerial.h"
#include "SWO.h"
#include "logos.h"
#include "SOFBlock.h"
#include "ubuntu_font.h"

#include <cstdlib>

//PA3 PA5
AnalogOut temperature_out(PA_5);
//PC3

//AnalogIn #conflicts with something somewhere
//SPI PE6 PE5 PE2

LCD_DISCO_F429ZI lcd;
TS_DISCO_F429ZI ts;
uint8_t text[30];

SWO_Channel swo;
//USBSerial ser;

//AnalogOut temp_setpoint(PA_5);
//AnalogIn temp_read(PF_4);

//#define DEBUG

#define CODE_VERSION_STRING "1.0"
#define LINE(x) ((x) * (((sFONT *)BSP_LCD_GetFont())->Height))

#ifdef DEBUG
#define TEMP_SET_LINE 0
#define CLOSER 0
#define TEMP_SET_TEXT LINE(TEMP_SET_LINE)+CLOSER
#define TEMP_SET_DISP LINE(TEMP_SET_LINE+1)+CLOSER
#define TEMP_READ_TEXT LINE(TEMP_SET_LINE+3)-CLOSER
#define TEMP_READ_DISP LINE(TEMP_SET_LINE+4)-CLOSER
#define TEMP_TEXT_X 5
#define TEMP_DISP_X (TEMP_TEXT_X - 5)
#else
#define TEMP_SET_LINE 4
#define OFFSET 5
#define CLOSER 10
#define TEMP_SET_TEXT LINE(TEMP_SET_LINE)+CLOSER+OFFSET
#define TEMP_SET_DISP LINE(TEMP_SET_LINE+1)+CLOSER+OFFSET
#define TEMP_READ_TEXT LINE(TEMP_SET_LINE+3)+CLOSER/2+OFFSET
#define TEMP_READ_DISP LINE(TEMP_SET_LINE+4)+CLOSER/2+OFFSET
#define TEMP_TEXT_X 32
#define TEMP_DISP_X (TEMP_TEXT_X - 5)
#endif
    

#define min(x,y) (x>y?y:x)
#define max(x,y) (x>y?x:y)

#define DEFAULT_LAYER 0
#define MIN_TEMP -40.
#define MAX_TEMP 20.0
    
double temperature_setpoint = -10.0;
double last_read_temperature = temperature_setpoint;

#define MAX_TP_POINTS (320-2*10-2*10)
#define DELAY_ACQ 200
#define TS_READ_TIME 75
#define TEMPERATURE_SLOW_ACCUMULATE 40
//(5*10) //10s approx 5*10*200ms

double temperature_curve_fast[MAX_TP_POINTS]; 
double temperature_curve_slow[MAX_TP_POINTS];
int accumulated_slow_temp = 0;
double slow_temp_acc = 0.;
int temperature_curve_slow_count = 0;
int temperature_curve_fast_count = 0;
int temperature_curve_fast_index = 0;
int temperature_curve_slow_index = 0;

int last_update_index = -1;

double eeprom_temperature = 0.0;

double pcoefs[] = {-1.10014853, 10.40077476, -70.49071822,  86.20161024};
double rev_pcoefs[] = {-5.42057541e-08, 5.11915693e-05, -2.13855322e-02, 1.50390471e+00};

double polyval(double* coefs, int degree, double value)
{
    int power = 0;
    int degree_current = degree;
    double value_out = 0;
    do {
        value_out += pow(value, power)*coefs[degree_current];
        degree_current -= 1;
        power += 1;
    } while (power <= degree);
    return value_out;
}

double read_temperature() 
{
    //fixes a bug for repetitve readout failures
    AnalogIn temp_read(PA_3); //PF4 PF5 PF3 PF6 PF8
    double bridge_res = 100e3;
    double bridge_voltage = 3.3;
    int averaging = 16;
    double accumulator = 0.;
    for (int i=0; i<averaging; i++) {
        accumulator += temp_read.read();
    }
    double temp_averaging = accumulator/averaging;
    double midpoint_voltage = double(temp_averaging*bridge_voltage);
    double rx = (midpoint_voltage / bridge_voltage) * bridge_res / (1 - midpoint_voltage / bridge_voltage);
    #ifdef DEBUG
    sprintf((char*)text, "TR %lf V ", midpoint_voltage);
    lcd.DisplayStringAt(0, LINE(9), (uint8_t *)&text, LEFT_MODE);
    #endif
    return polyval(pcoefs, 3, log10(rx/1e3));
}

void write_temperature_setpoint(double temperature)
{
    double bridge_res = 100e3;
    double bridge_voltage = 3.3;
    double res = pow(10., polyval(rev_pcoefs, 3, temperature))*1e3;
    double voltage = (res/(res+bridge_res) * bridge_voltage);
    #ifdef DEBUG
    sprintf((char*)text, "SP %4.1lf V ", voltage);
    lcd.DisplayStringAt(0, LINE(8), (uint8_t *)&text, LEFT_MODE);
    #endif
    temperature_out.write(voltage/bridge_voltage);
}



#define LCD_REFRESH_RATE 40

void LCD_Reload_Safe(void)
{
    BSP_LCD_Reload(LTDC_RELOAD_VERTICAL_BLANKING);
    wait(1./LCD_REFRESH_RATE);
}


const uint8_t sector_index = 11;
SOFWriter writer;
SOFReader reader;

void check_temperature_storage(void)
{
    //here could check for data
    reader.open(sector_index);
    double temp_backup = *(double *)(reader.get_physical_data_addr()-sizeof(double));
    reader.close();
    writer.open(sector_index);
    if (writer.get_free_size() <= sizeof(double)*1024) { // check available byte
        SOFBlock::format(sector_index);
        writer.write_data((uint8_t*)(&temp_backup), sizeof(double));
    } else {
        #ifndef NO_WAIT
        wait(1);
        #endif
    }
    writer.close();
}

void load_temperature_storage(void)
{
    reader.open(sector_index);
    eeprom_temperature = *(double *)(reader.get_physical_data_addr()-sizeof(double));
    reader.close();
    
    if ((eeprom_temperature >= MIN_TEMP) && (eeprom_temperature <= MAX_TEMP))
    {
        temperature_setpoint = eeprom_temperature;
    }
    write_temperature_setpoint(temperature_setpoint);
    
}

void save_temperature_storage(void)
{
    /* write temperature set point */
    if ((temperature_setpoint != eeprom_temperature) && 
            (temperature_setpoint < MAX_TEMP) && (temperature_setpoint > MIN_TEMP)) {
        writer.open(sector_index);
        writer.write_data((uint8_t*)(&temperature_setpoint), sizeof(double));

        eeprom_temperature = temperature_setpoint;
        if (writer.get_free_size() <= sizeof(double)+1) { // check available byte
            SOFBlock::format(sector_index);
        }
        writer.close();
        eeprom_temperature = temperature_setpoint;
    }

}

void DrawRectCentered(uint16_t xcenter, uint16_t ycenter, uint16_t width, uint16_t height)
{
    //landscape mode only
    lcd.FillRect(xcenter+width/2,ycenter-height/2, height, width);
}

void print_layer(int layer)
{
    lcd.SelectLayer(layer);
    BSP_LCD_SetLayerVisible(layer, ENABLE);
    sprintf((char*)text, "LAYER %d", layer);
    lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text, LEFT_MODE);
    BSP_LCD_SetLayerVisible(layer, DISABLE);
}

void print_layers()
{
    for (int i=0;i<3;i++)
    {
        print_layer(i);
    }
    lcd.SelectLayer(0);
    BSP_LCD_SetLayerVisible(0, ENABLE);

}

void draw_startup_screen(int layer)
{
    lcd.SelectLayer(layer);
    BSP_LCD_SetLayerVisible_NoReload(layer, ENABLE);
    LCD_Reload_Safe();
    lcd.Clear(LCD_COLOR_BLUE);
    uint8_t* pBmp = (uint8_t*)big_fastlite_logo_68_302;
    lcd.DrawBitmap((lcd.GetYSize()-302)/2, (lcd.GetXSize()-68)/2, pBmp);
}

void draw_version_screen(int layer)
{
    lcd.SelectLayer(layer);
    lcd.SetBackColor(LCD_COLOR_BLUE);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.Clear(LCD_COLOR_BLUE);
    
    BSP_LCD_SetFont(&UbuntuFont23);
    
    lcd.Clear(LCD_COLOR_BLUE);
    uint8_t* pBmp = (uint8_t*)big_fastlite_logo_68_302;
    lcd.DrawBitmap((lcd.GetYSize()-302)/2, 0, pBmp);
    
    sprintf((char*)text, "TEC interface");
    lcd.DisplayStringAt(5, LINE(0)+70, (uint8_t *)&text, LEFT_MODE);
    sprintf((char*)text, "Version %s", CODE_VERSION_STRING);
    lcd.DisplayStringAt(5, LINE(1)+70, (uint8_t *)&text, LEFT_MODE);    
}

void fade_screen(int layer, int fade_count, uint32_t color, int dest_layer)
{
    lcd.SelectLayer(layer+1);
    BSP_LCD_SetTransparency_NoReload(layer+1, 0);
    BSP_LCD_SetColorKeying_NoReload(layer+1, LCD_COLOR_WHITE);
    lcd.Clear(color);
    LCD_Reload_Safe();
    BSP_LCD_SetLayerVisible_NoReload(layer+1, ENABLE);
    BSP_LCD_Reload(LTDC_RELOAD_VERTICAL_BLANKING);
    lcd.SetTextColor(color);
    
    for (int i=0; i<fade_count; i++)
    {
        BSP_LCD_SetTransparency_NoReload(layer+1,255/(fade_count-1)*i); //TRANSPARENCY == ALPHA so 255 is no transparent
        BSP_LCD_Reload(LTDC_RELOAD_VERTICAL_BLANKING);
        #ifndef NO_WAIT
        wait(1./fade_count);
        #endif
    }
    
    BSP_LCD_ResetColorKeying_NoReload(layer+1);
    BSP_LCD_SetLayerVisible_NoReload(layer+1, DISABLE);
    
    lcd.SelectLayer(layer);
    lcd.Clear(color);
    
    if (layer != dest_layer) {
        lcd.SelectLayer(dest_layer);
        lcd.Clear(color);
        BSP_LCD_SetLayerVisible_NoReload(dest_layer, ENABLE);
    }
    LCD_Reload_Safe();

}

int curve_y_min_temp = 0;
int curve_y_zero_temp = 0;
int curve_x_zero_time = 0;
int curve_height_x = 0;
int curve_width_y = 0;
double pixel_temp_f=1.;

void enable_curve_overlay(int layer, bool set_visible)
{
    if (set_visible) BSP_LCD_SetLayerVisible_NoReload(layer, ENABLE);
    lcd.SelectLayer(layer);
    lcd.Clear(LCD_COLOR_TRANSPARENT);
    BSP_LCD_SetColorKeying_NoReload(layer, LCD_COLOR_TRANSPARENT);
    if (set_visible) {
        LCD_Reload_Safe();
    }
}

void disable_curve_overlay(int layer)
{
    BSP_LCD_SetLayerVisible_NoReload(layer, DISABLE);
    lcd.SelectLayer(layer);
    lcd.Clear(LCD_COLOR_TRANSPARENT);
    BSP_LCD_SetColorKeying_NoReload(layer, LCD_COLOR_TRANSPARENT);
    LCD_Reload_Safe();

}

void clear_curve_overlay(int layer)
{
    lcd.SelectLayer(layer);
    lcd.Clear(LCD_COLOR_TRANSPARENT);
}

bool update_temperature_read_curve(int layer, int screen, bool clear, bool force_update)
{
    lcd.SelectLayer(layer);
    int temp_index = 0;
    int temp_count = 0;
    double* temp_curve = NULL;
    uint32_t curve_color = 0;
    
    if (screen == -1)
    {
        temp_index = temperature_curve_fast_index;
        temp_count = temperature_curve_fast_count;
        temp_curve = temperature_curve_fast;
        curve_color = LCD_COLOR_RED;
    } else {
        temp_index = temperature_curve_slow_index;
        temp_count = temperature_curve_slow_count;
        temp_curve = temperature_curve_slow;
        curve_color = LCD_COLOR_DARKGREEN;
    }
    
    if ((last_update_index == temp_index) && (force_update == false))
    {
        return false;
    } else {
        last_update_index = temp_index;   
    }

    int start_index = (temp_index-temp_count)%MAX_TP_POINTS;
    if (start_index < 0) {
        start_index += MAX_TP_POINTS;
    }
    int stop_index = temp_index;
    
    int prev_y = -1;
    int py = 0;
    int px = 0;
    
    if (temp_count == 0)
    {
        return false;
    }
    
    if (clear) {
        clear_curve_overlay(layer);
    }
    
    #define LINE_DRAW
    
    /*
    lcd.SetTextColor(LCD_COLOR_WHITE);
    sprintf((char*)text, "U%d %d %d", start_index, stop_index, start_index+MAX_TP_POINTS);
    lcd.DisplayStringAt(0, LINE(1), (uint8_t *)&text, LEFT_MODE);  
    */
    
    lcd.SetTextColor(curve_color);
    int begin = -1; 
    int stop = -1; 

    bool two_step = false;
    if (stop_index <= start_index) { 
        begin = start_index;
        stop = MAX_TP_POINTS;
        two_step = true;
    } else {
        begin = start_index;
        stop = stop_index;
    }
    

    bool draw_done = false;
    while (draw_done == false)
    {
        for (int i=begin; i<stop; i++)
        {
            py = curve_y_zero_temp - temp_curve[i]*pixel_temp_f;
            #ifdef LINE_DRAW
            if ((prev_y != -1) && (px<curve_width_y) && (py>curve_y_min_temp-curve_height_x) && (py<curve_y_min_temp))
            {
                lcd.DrawLine(px-1+curve_x_zero_time, prev_y, px+curve_x_zero_time, py);
            }
            prev_y = py;            
            #else
            if ((px<curve_width_y) && (py>curve_y_min_temp-curve_height_x) && (py<curve_y_min_temp))
            {
                lcd.DrawPixel(px+curve_x_zero_time, py, LCD_COLOR_BLACK);
            }
            #endif
            px ++;
        }
        if (two_step) {
            if (begin == 0)
            {
                draw_done = true;
            } else {
                begin = 0;
                stop = stop_index;
            }
        } else {
            draw_done = true;
        }
    }
    return true;
}

int plus_x = lcd.GetYSize()*3./4+30;
int plus_y = lcd.GetXSize()*1./4+20;
int minus_x = lcd.GetYSize()*3./4+30;
int minus_y = lcd.GetXSize()*3./4-20;
int radius = lcd.GetXSize()/8.;

char temp_formatting[] = "  %4.1lf xC  ";

void update_temperature_read_text()
{
    sprintf((char*)text, temp_formatting, last_read_temperature);
    lcd.DisplayStringAt(TEMP_DISP_X, TEMP_READ_DISP, (uint8_t *)&text, LEFT_MODE);
}

void draw_regulation_screen(int layer)
{
    temp_formatting[9] = 176; 
    
    lcd.SetBackColor(LCD_COLOR_BLUE);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.Clear(LCD_COLOR_BLUE);
    
    BSP_LCD_SetFont(&UbuntuFont23);
    
    lcd.DrawCircle(minus_x, minus_y, radius);
    DrawRectCentered(minus_x, minus_y, radius*1.6, 5);

    lcd.DrawCircle(plus_x, plus_y, radius);
    DrawRectCentered(plus_x, plus_y, radius*1.6, 5);
    DrawRectCentered(plus_x, plus_y, 5, radius*1.6);
    
    //FASTLITE LOGO + LINE
    DrawRectCentered(lcd.GetYSize()/2, lcd.GetXSize()-6, lcd.GetYSize(), 2);
    uint8_t* pBmp = (uint8_t*)fastlite_logo_landscape_90_20;
    lcd.DrawBitmap(lcd.GetYSize()-90, lcd.GetXSize()-20, pBmp);
    
    
    //FRINGEEZZ LOGO
    #ifdef DEBUG
        pBmp = (uint8_t*)fringeezz_logo_landscape_124_49;
        lcd.DrawBitmap(0, lcd.GetXSize()-20-49-40, pBmp);
    #else
        pBmp = (uint8_t*)big_fringezz_logo_91_233;
        lcd.DrawBitmap(5, 5, pBmp);    
    #endif
    
    sprintf((char*)text, "TEC set-up:");
    lcd.DisplayStringAt(TEMP_TEXT_X, TEMP_SET_TEXT, (uint8_t *)&text, LEFT_MODE);
    sprintf((char*)text, temp_formatting, temperature_setpoint);
    lcd.DisplayStringAt(TEMP_DISP_X, TEMP_SET_DISP, (uint8_t *)&text, LEFT_MODE);
    
    sprintf((char*)text, "TEC temp:");
    lcd.DisplayStringAt(TEMP_TEXT_X, TEMP_READ_TEXT, (uint8_t *)&text, LEFT_MODE);  
    
    update_temperature_read_text();    
}



void draw_curve_screen(int layer)
{
    lcd.SetBackColor(LCD_COLOR_BLUE);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.Clear(LCD_COLOR_BLUE);
    
    uint8_t* pBmp = (uint8_t*)fringeezz_logo_landscape_124_49;
    lcd.DrawBitmap(1, 1, pBmp);
   
    lcd.SetBackColor(LCD_COLOR_BLUE);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    BSP_LCD_SetFont(&Font16);
    sprintf((char*)text, "TEC temperature");
    lcd.DisplayStringAt(130, LINE(0)+10, (uint8_t *)&text, LEFT_MODE);  
    
    int margin_y = 10;
    int margin_x = 21;
    int offset_x = 15;
    int offset_y = 10;
    
    lcd.SetTextColor(LCD_COLOR_BLACK);
    
    int curve_center_y = lcd.GetYSize()/2+offset_y;
    int curve_center_x = lcd.GetXSize()/2+offset_x;
    curve_height_x = lcd.GetXSize()-offset_x*2-margin_x*2;
    curve_width_y = lcd.GetYSize()-offset_y*2-margin_y*2;
    
    DrawRectCentered(curve_center_y, curve_center_x, curve_width_y, curve_height_x);
    
    lcd.SetTextColor(LCD_COLOR_WHITE);
    DrawRectCentered(curve_center_y, curve_center_x, curve_width_y-2, curve_height_x-2);

    int min_temp = -20;
    int max_temp = 35;
    int tick_space = 10;

    int delta_temp = max_temp - min_temp;
    int vticks_pixels = int((curve_height_x-2)*tick_space/delta_temp);
    double max_temp_f = min_temp + (1.*tick_space*curve_height_x)/vticks_pixels;
    double delta_temp_f = max_temp - min_temp;
    pixel_temp_f = curve_height_x/delta_temp;
    curve_y_min_temp = curve_center_x+curve_height_x/2-1;
    curve_y_zero_temp = curve_y_min_temp+(1.*min_temp*vticks_pixels/tick_space);    
    curve_x_zero_time = curve_center_y-curve_width_y/2+1;
    
    BSP_LCD_SetFont(&Font12);
    for (int i=0; i<curve_height_x/vticks_pixels+1; i++)
    {
        lcd.SetTextColor(LCD_COLOR_BLACK);

        int vtick_pos = curve_center_x+curve_height_x/2-1-i*(vticks_pixels);       
        int vtick_pos_x = curve_center_y-curve_width_y/2-1;    
        lcd.DrawVLine(vtick_pos_x+5+1, vtick_pos, 5);

        lcd.SetTextColor(LCD_COLOR_WHITE);

        sprintf((char*)text, "%d", min_temp+10*i);
        lcd.DisplayStringAt(30,  vtick_pos-6, (uint8_t *)&text, RIGHT_MODE);  

        lcd.SetTextColor(LCD_COLOR_BLACK);

        vtick_pos = curve_center_x+curve_height_x/2-1-i*(vticks_pixels);       
        vtick_pos_x = curve_center_y+curve_width_y/2-1;    
        lcd.DrawVLine(vtick_pos_x+1, vtick_pos, 5);
        
    }
                
    lcd.SetTextColor(LCD_COLOR_WHITE);
    BSP_LCD_SetFont(&UbuntuFont23);

    
    //FASTLITE LOGO + LINE
    DrawRectCentered(lcd.GetYSize()/2, lcd.GetXSize()-6, lcd.GetYSize(), 2);
    pBmp = (uint8_t*)fastlite_logo_landscape_90_20;
    lcd.DrawBitmap(lcd.GetYSize()-90, lcd.GetXSize()-20, pBmp);
}

void draw_screens(int screen, int layer)
{
    lcd.SelectLayer(layer);
    lcd.Clear(LCD_COLOR_BLUE);
    if ((screen == -1) || (screen == -2))
    {
        draw_curve_screen(layer);
        
        lcd.SetBackColor(LCD_COLOR_BLUE);
        lcd.SetTextColor(LCD_COLOR_WHITE);
        BSP_LCD_SetFont(&Font16);
        if (screen == -1) { 
            sprintf((char*)text, "(%dms)", DELAY_ACQ+TS_READ_TIME);
        } else {
            sprintf((char*)text, "(%ds)", (DELAY_ACQ+TS_READ_TIME)*TEMPERATURE_SLOW_ACCUMULATE/1000);
        }
        lcd.DisplayStringAt(130, LINE(1)+10, (uint8_t *)&text, LEFT_MODE);  
    } else {
        if (screen == 0) {
            draw_regulation_screen(layer);
        } else if (screen == 1) {
            draw_version_screen(layer);
        }
    }
    
    #ifdef DEBUG
        lcd.SelectLayer(layer);
        lcd.SetBackColor(LCD_COLOR_BLUE);
        lcd.SetTextColor(LCD_COLOR_WHITE);
        BSP_LCD_SetFont(&UbuntuFont23);
        sprintf((char*)text, "screen(%d)", screen);
        lcd.DisplayStringAt(0, LINE(0), (uint8_t *)&text, LEFT_MODE);
    #endif
}


int main()
{
    TS_StateTypeDef TS_State;
    uint16_t x, y;
    uint8_t ts_status;

    load_temperature_storage();
 
    /*initialize lcd*/
    lcd.SelectLayer(2);
    BSP_LCD_SetTransparency_NoReload(2, 255);
    BSP_LCD_ResetColorKeying_NoReload(2);
    lcd.Clear(LCD_COLOR_BLUE);
    BSP_LCD_SetLayerVisible_NoReload(2, ENABLE);
    LCD_Reload_Safe();
    BSP_LCD_SetFont(&UbuntuFont23);
    
    lcd.SelectLayer(1);
    BSP_LCD_SetTransparency_NoReload(1, 255);
    BSP_LCD_ResetColorKeying_NoReload(1);
    lcd.Clear(LCD_COLOR_BLUE);
    BSP_LCD_SetLayerVisible_NoReload(2, DISABLE);
    BSP_LCD_SetLayerVisible_NoReload(1, ENABLE);
    LCD_Reload_Safe();
    lcd.SetTextColor(LCD_COLOR_BLUE);
    BSP_LCD_SetFont(&UbuntuFont23);

    lcd.SelectLayer(0);
    BSP_LCD_SetTransparency_NoReload(0, 255);
    BSP_LCD_ResetColorKeying_NoReload(0);
    lcd.Clear(LCD_COLOR_BLUE);
    BSP_LCD_SetLayerVisible_NoReload(1, DISABLE);
    BSP_LCD_SetLayerVisible_NoReload(0, ENABLE);
    LCD_Reload_Safe();
    lcd.SetTextColor(LCD_COLOR_BLUE);
    BSP_LCD_SetFont(&UbuntuFont23);
    
    ts_status = ts.Init(lcd.GetXSize(), lcd.GetYSize());
    
    
    int layer_startup = 0;    
    draw_startup_screen(layer_startup);
    wait(0.01);
    
    check_temperature_storage(); /*takes 1s */
    
    //FADE
    int fade_count = 30;
    fade_screen(layer_startup, fade_count, LCD_COLOR_BLUE, DEFAULT_LAYER);
    //FADE DONE
    
    #define TOUCH_COUNT 512
    int touch_history_x[TOUCH_COUNT];
    int touch_history_y[TOUCH_COUNT];
    int touch_history_count = 0; 
    bool touch_screen_idle = false;
    int previous_x = -1;
    int previous_y = -1;
    int swipe_pos_x_start = -1;
    
    int swipe_dir = 0;
    bool start_swipe = false;
    int swipe_pos = 0;
    int selected_screen = 0;
    
    enable_curve_overlay(DEFAULT_LAYER+1, false);
    draw_screens(selected_screen, DEFAULT_LAYER);
    
    int accel = 1;
    Timer t;
    t.start();
    Timer idle_time;
    t.start();
    
    while (ts_status != TS_OK) {
        lcd.SelectLayer(DEFAULT_LAYER);
        lcd.SetTextColor(LCD_COLOR_RED);
        lcd.DisplayStringAt(0, LINE(0), (uint8_t *)"TOUCH INIT FAIL", LEFT_MODE); /*center mode is broken in landscape for fixing right mode*/
        lcd.SetTextColor(LCD_COLOR_WHITE);
    }
    
    int dest_loc = 0;
    int swipe_layer = 1;
    uint32_t swipe_layer_address = LCD_FRAME_BUFFER+(lcd.GetXSize()*lcd.GetYSize()*4)*swipe_layer;
    int destination_screen = 0 ;

    /*
    int source_layer = 0;
    int dest_layer = 0;
    int backup_layer = 0;
    int backup_loc = 0;
    */
    int curve_update = 0;
    while(1)
    {
      ts.GetState(&TS_State);  
      //#ifdef TOUCHSCREEN_DEMO    
      if ((TS_State.TouchDetected) && (start_swipe == false))
      {
        idle_time.reset();

        x = TS_State.X;
        y = TS_State.Y;
        
        int portrait_x = lcd.GetYSize()-y;
        int portrait_y = x;
        
        x = portrait_x;
        y = portrait_y;
        

        
        //sprintf((char*)text, "%d %d %d", minus_dist, plus_dist, radius*radius);
        //lcd.DisplayStringAt(0, LINE(6), (uint8_t *)&text, LEFT_MODE);

        if (touch_screen_idle) { 
            touch_screen_idle = false;
            previous_y = -1;
            previous_x = -1;
        }
        
        bool button_pressed = false;
        
        /* handle buttons */
        if (selected_screen == 0) /* screen has buttons (regulation screen) */ {
            int minus_dist = (x-minus_x)*(x-minus_x) + (y-minus_y)*(y-minus_y);
            int plus_dist = (x-plus_x)*(x-plus_x) + (y-plus_y)*(y-plus_y);
            
            if  (minus_dist <= radius*radius) {
                button_pressed = true;
                lcd.SetTextColor(LCD_COLOR_RED);
                lcd.DrawCircle(minus_x, minus_y, radius);
                temperature_setpoint = temperature_setpoint - 0.1;
                sprintf((char*)text, temp_formatting, temperature_setpoint);
                lcd.DisplayStringAt(TEMP_DISP_X, TEMP_SET_DISP, (uint8_t *)&text, LEFT_MODE);
                write_temperature_setpoint(temperature_setpoint);
                wait(0.1/max(accel/10,1));
                lcd.SetTextColor(LCD_COLOR_WHITE);
                lcd.DrawCircle(minus_x, minus_y, radius);
                if (accel < 1000)
                {
                    accel += 1;
                }
            } else {
                if  (plus_dist <= radius*radius) {
                    button_pressed = true;
                    lcd.SetTextColor(LCD_COLOR_GREEN);
                    lcd.DrawCircle(plus_x, plus_y, radius);
                    temperature_setpoint = temperature_setpoint + 0.1;
                    sprintf((char*)text, temp_formatting, temperature_setpoint);
                    lcd.DisplayStringAt(TEMP_DISP_X, TEMP_SET_DISP, (uint8_t *)&text, LEFT_MODE);
                    write_temperature_setpoint(temperature_setpoint);
                    wait(0.1/max(accel/10,1));
                    lcd.SetTextColor(LCD_COLOR_WHITE);
                    lcd.DrawCircle(plus_x, plus_y, radius);
                    if (accel < 1000)
                    {
                        accel += 1;
                    }
                }
            }
        }
        
        /* handle swipe */
        if (not button_pressed) {
            accel = 0;
            if (start_swipe == false)
            {
                if (swipe_pos_x_start == -1)
                {
                    swipe_pos_x_start = x;
                } else {
                    if (abs(x - swipe_pos_x_start) > 15) {
                        start_swipe = true;
                        if ((x-swipe_pos_x_start) < 0)
                        {
                            swipe_dir = +1;
                        } else {
                            swipe_dir = -1;
                        }
                    }
                }
            } else {
             /*swipe started do nothing*/
            }
            //sprintf((char*)text, "x=%d, px=%d y=%d    ", x, swipe_pos_x_start, touch_screen_idle);
            //lcd.DisplayStringAt(0, LINE(0), (uint8_t *)&text, LEFT_MODE);
        }
        

        previous_x = x;
        previous_y = y;

        #ifdef TOUCH_TEST
        swo.puts((char*)text);
        ser.puts((char*)text);
        for (int l=0; l<10; l++) {
            sprintf((char*)text, "l=%d, x=%d y=%d    ", l, x, y);
            lcd.DisplayStringAt(0, LINE(l), (uint8_t *)&text, LEFT_MODE);
        }
        #endif
      } else {
        //no touch
        if (not touch_screen_idle)
        {
            idle_time.start();
        }
        if (idle_time.read_ms() >= 100)
        {
            touch_history_count = 0;
            //sprintf((char*)text, "px=%d i=%d    ", swipe_pos_x_start, touch_screen_idle);
            //lcd.DisplayStringAt(0, LINE(0), (uint8_t *)&text, LEFT_MODE);
            
            if (not touch_screen_idle) {
                touch_screen_idle = true;
                swipe_pos_x_start = -1;
            }

        } else {
            
        }
        accel = 0;   
      }
      
      if (start_swipe && ((selected_screen == 1) && (swipe_dir == +1)) || ((selected_screen == -2) && (swipe_dir == -1)))
      {
          start_swipe = false;
      } 
          
      if (start_swipe == true)
      {

          if (swipe_pos >= lcd.GetYSize())
          {
              start_swipe = false;
              
              wait(1./LCD_REFRESH_RATE);
              
              // swipe occurs to 
              
              // swipe to 0. changes the pointer
              BSP_LCD_SetLayerAddress_NoReload(swipe_layer, swipe_layer_address);
                
              //copy current displayed layer to 0
              if (dest_loc != DEFAULT_LAYER) {
                BSP_LCD_CopyLayer(dest_loc, DEFAULT_LAYER, 0); //overwrite layer 0 with data displayed        
              }
              
              if (DEFAULT_LAYER != swipe_layer) {
                    if (swipe_layer == DEFAULT_LAYER+1)
                    {
                        if (destination_screen < 0) /* destination screen has overlay */
                        {
                            /* clear the swipe layer for overlay */
                            /* 0 != 1 */
                            /* this means it goes DOWN */
                            /* swipe layer is 1 */
                            /* swipe layer is pointing to dest_loc */
                            /* dest_loc is copied to layer 0 */
                            
                            /* clear_curve_overlay(swipe_layer); this flickers because layer is allready visible */
                            BSP_LCD_SetLayerVisible_NoReload(swipe_layer, ENABLE);
                            curve_update = 0;
                        } else {
                            BSP_LCD_SetLayerVisible_NoReload(swipe_layer, DISABLE);
                        }
                    } else {
                        BSP_LCD_SetLayerVisible_NoReload(swipe_layer, DISABLE);
                    }
                    lcd.SelectLayer(DEFAULT_LAYER);
                    BSP_LCD_SetLayerVisible_NoReload(DEFAULT_LAYER, ENABLE);
              } else {
                    /* it swipes UP */
                    /* there is a not displayed overlay clear it before */
                    if (destination_screen < 0) /* destination screen has overlay */
                    {
                        /* clear the swipe layer for overlay */
                        /* clear_curve_overlay(DEFAULT_LAYER+1); */                   
                        BSP_LCD_SetLayerVisible_NoReload(DEFAULT_LAYER+1, ENABLE);
                        /* go from 1 to 0*/
                        
                        curve_update = 0;
                    } else {
                        /* should allready be disabled */
                        BSP_LCD_SetLayerVisible_NoReload(DEFAULT_LAYER+1, DISABLE);
                    }
              }
              lcd.SelectLayer(DEFAULT_LAYER);
              wait(1./LCD_REFRESH_RATE);
              LCD_Reload_Safe();

              //BSP_LCD_Reload(LTDC_RELOAD_IMMEDIATE);
              selected_screen = destination_screen;
              
              swipe_pos = 0;
              swipe_dir = 0;
          } else {
              if (swipe_pos == 0) {
                /* start swipe */
                
                wait(0.1);
                
                /* if (selected_screen < 0)
                {
                    // this would flicker
                    clear_curve_overlay(DEFAULT_LAYER+1); //hide the curve displayed
                    lcd.SelectLayer(DEFAULT_LAYER);
                   
                }
                */
                
                dest_loc = 1-swipe_dir;
                if (dest_loc == 0)
                {
                    swipe_layer = 1;
                } else {
                    if (dest_loc == 2)
                    {
                        swipe_layer = 0;
                        dest_loc = 1;
                    } else {
                        start_swipe = false;
                        swipe_pos = 0;
                        swipe_dir = 0;    
                    }
                }
                
                swipe_layer_address = LCD_FRAME_BUFFER+(lcd.GetXSize()*lcd.GetYSize()*4)*swipe_layer;

                if (swipe_layer == DEFAULT_LAYER) {
                    if (selected_screen < 0) /* selected screen has overlay */ {
                        /* hides overlay */
                        BSP_LCD_SetLayerVisible_NoReload(DEFAULT_LAYER+1, DISABLE);  
                        /* update destination display */
                        update_temperature_read_curve(DEFAULT_LAYER, selected_screen, false, true);
                        wait(1./LCD_REFRESH_RATE);
                        /* hides overlay */
                    } else {
                        /* no overlay do nothing */   
                    }
                } else {
                    /* copy visible layer to swipe layer */
                    BSP_LCD_CopyLayer(DEFAULT_LAYER, swipe_layer, 0); //reload backup of layer 0 or save it
                    if (selected_screen < 0) /* selected screen has overlay */ {
                        update_temperature_read_curve(swipe_layer, selected_screen, false, true);
                    }
                    BSP_LCD_SetLayerVisible_NoReload(DEFAULT_LAYER, DISABLE);  
                    BSP_LCD_SetLayerVisible_NoReload(swipe_layer, ENABLE);
                    wait(1./LCD_REFRESH_RATE);
                }
                LCD_Reload_Safe();
                                
                destination_screen = selected_screen + swipe_dir;
                //prepare destination screen (destination screen will be 2)
                //cannot be overwriten by previous command

                draw_screens(destination_screen, dest_loc);
                /*
                lcd.SelectLayer(swipe_layer);
                sprintf((char*)text, "screen(%d)", selected_screen);
                lcd.DisplayStringAt(0, LINE(0), (uint8_t *)&text, LEFT_MODE);
                */
              } else {
                BSP_LCD_SetLayerAddress(swipe_layer, swipe_layer_address-swipe_dir*lcd.GetXSize()*4*swipe_pos);
              }
              
              wait(0.);
              swipe_pos++;
          }

      }
      
      if (t.read_ms() >= DELAY_ACQ and (not start_swipe)) {
        //read temperature
        last_read_temperature = read_temperature();
        
        /* slow buffer */
        slow_temp_acc = slow_temp_acc + last_read_temperature;
        if (accumulated_slow_temp == TEMPERATURE_SLOW_ACCUMULATE-1)
        {
            temperature_curve_slow[temperature_curve_slow_index]= slow_temp_acc/TEMPERATURE_SLOW_ACCUMULATE;
            slow_temp_acc = 0.;
            accumulated_slow_temp = 0;
            if (temperature_curve_slow_count < MAX_TP_POINTS)
            {
                temperature_curve_slow_count++;
            }
            temperature_curve_slow_index = (temperature_curve_slow_index+1)%MAX_TP_POINTS;
        } else {
            accumulated_slow_temp++;
        }
        
        temperature_curve_fast[temperature_curve_fast_index] = last_read_temperature;
        if (temperature_curve_fast_count < MAX_TP_POINTS)
        {
            temperature_curve_fast_count++;
        }
        temperature_curve_fast_index = (temperature_curve_fast_index+1)%MAX_TP_POINTS;
        
        if (selected_screen < 0)
        {
            /* diminish flicker */
            bool updated = update_temperature_read_curve(DEFAULT_LAYER+2, selected_screen, true, false);
            if (updated)
            {
                BSP_LCD_CopyLayer(DEFAULT_LAYER+2, DEFAULT_LAYER+1, 0);
                //LCD_Reload_Safe();
                BSP_LCD_Reload(LTDC_RELOAD_IMMEDIATE);

            } else {
                lcd.SelectLayer(DEFAULT_LAYER);
            }
            curve_update = (curve_update+1)%2;
        } else {
            if (selected_screen == 0) { 
                update_temperature_read_text();
            }
        }
        save_temperature_storage();

        
        #ifdef DEBUG
        reader.open(sector_index);
        sprintf((char*)text, "SOF(%d.%p)", reader.get_data_size(), reader.get_physical_data_addr());
        lcd.DisplayStringAt(0, LINE(TEMP_SET_LINE+6), (uint8_t *)&text, LEFT_MODE);
        reader.close();
        #endif
        
        t.reset();
        
      }
      //#endif
      
      
    }
}