rev.1

Dependencies:   RA8875 SDFileSystem mbed

main.cpp

Committer:
vnemera
Date:
2017-02-17
Revision:
0:6ef3fd4921d7

File content as of revision 0:6ef3fd4921d7:

// MW771 Laser Press HMI.
// V.Nemera, 10/07/2016, ver.1.0, C++
// CPU: mbed NXP LPC1768 (ARM Cortex-M3, 32bit, 90MHz)
//#pragma once
#include "mbed.h"           
#include "RA8875.h"         
#include "MyFont18x32.h"
#include "BPG_Arial08x08.h"
#include "BPG_Arial10x10.h"
#include "BPG_Arial20x20.h"
#include "BPG_Arial31x32.h"
#include "BPG_Arial63x63.h"
#include "SDFileSystem.h"
#include "stdint.h"
#include <string>
using std::string;

#include "main.h"
#include "comm.h"

int a7, b7, c7, d7;

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

int iLed;

Serial pc(USBTX, USBRX);     // pc feedback

extern void main_cycle_add(void);
extern void initHMIio(void);
extern int SetLasComm(int icLC);
extern void flipRS(void);

// These two defines can be enabled, or commented out
#define BIG_SCREEN
//#define CAP_TOUCH
#define LCD_C 16         // color - bits per pixel

#ifdef CAP_TOUCH
RA8875 lcd(p5, p6, p7, p8, NC, p11,p12,p13, "tft"); // MOSI,MISO,SCK,/ChipSelect,/reset, SDA,SCL,/IRQ, name
#else
RA8875 lcd(p5, p6, p7, p8, NC, "tft");             //MOSI, MISO, SCK, /ChipSelect, /reset, name
//LocalFileSystem local ("sd");                     // access to calibration file for resistive touch.
#endif

#define PC_BAUD 115200  // I like the serial communications to be fast

#ifdef BIG_SCREEN
    #define LCD_W 800
    #define LCD_H 480
    #define DEF_RADIUS 50   // default radius of the fingerprint
    #define BL_NORM 25      // Backlight Normal setting (0 to 255)
#else
    #define LCD_W 480
    #define LCD_H 272
    #define DEF_RADIUS 20   // default radius of the fingerprint
    #define BL_NORM 25      // Backlight Normal setting (0 to 255)
#endif

#define Gray        (color_t)(RGB(187,187,187))

color_t fingerColor[5] = {Blue, Red, Green, Yellow, Magenta};
point_t last[5];        // space for tracking 5 touches
int layer = 0;


//SDFileSystem(mosi,miso,sclk,cs,name,cd, SwitchType, int hz);
SDFileSystem sd(p5, p6, p7, p29, "sd", p30, SDFileSystem::SWITCH_NEG_NO, 8000000);

int iPC;
char bufferNL[512];
//const char *rDr = "/";
char *rDr = "/";

Ticker tickRS;               //rs232 pc, io, laser 
timestamp_t tickTime = 2048;  // ticker interval in microSec

//Timer IOwait;                //timeout for IO controller RS232 connection
int usMeasure;

point_t lastTP;

const char *cPN[8];
const char *cWM[3];
//---------------------------------------------------------------------------------
TextBox txtBox[] = {
    { 290, 15, 348, 57, 310, 20, Gray, Black, "1"},
    { 350, 15, 408, 57, 370, 20, Gray, Black, "2"},
    { 410, 15, 468, 57, 430, 20, Gray, Black, "3"},
    { 470, 15, 528, 57, 490, 20, Gray, Black, "4"},
    { 530, 15, 588, 57, 550, 20, Gray, Black, "5"},
    { 590, 15, 648, 57, 610, 20, Gray, Black, "6"},
    { 650, 15, 708, 57, 670, 20, Gray, Black, "7"},
    { 710, 15, 768, 57, 730, 20, Gray, Black, "8"},
    { 290, 70, 408, 112, 300, 75, Gray, Black, "Circle"},
    { 410, 70, 528, 112, 420, 75, Gray, Black, "Eight"},
    { 530, 70, 648, 112, 540, 75, Gray, Black, "Infinity"}
};
int TextBoxSize = 11;
int progNumber = 0;     //program# 0..7
int wobbleMode = 0;     //wobble mode
int Lmode = 0;          //laser mode

ProgPar prPar[] = {     //default (init) parameters
    { 0, 10,  50, 0, 100, 100, 1, 4, 230,  500,  4},
    { 0, 20,  80, 0, 200,  50, 2, 5, 200, 1000,  7},
    { 0, 30,  90, 0, 400,  25, 3, 3, 100, 1500,  1},
    { 0, 40, 100, 0, 500,  10, 4, 5,  50, 1600,  3},
    { 1, 50,  70, 1, 100,   8, 1, 5, 250, 1100,  9},
    { 1, 60, 100, 1, 200,   5, 2, 5, 180,  800,  5},
    { 2, 70,  75, 1, 400,  10, 1, 3, 120,  600,  7},
    { 2, 80,  85, 1, 500,   9, 3, 5, 240,  750, 21}
};
char nCh[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
                             
TextBoxR txtBoxR[] = {
    { 290, 125, 380, 167, 10, 8, 320, 130, Gray, Black, "10"},          //LPbeg
    { 470, 125, 560, 167, 10, 8, 500, 130, Gray, Black, "100"},         //LPend
    { 650, 125, 768, 167, 10, 8, 660, 130, Gray, Black, "CW"},          //Lmode
    { 290, 180, 380, 222, 10, 8, 320, 185, Gray, Black, "500"},         //Lfreq
    { 470, 180, 560, 222, 10, 8, 500, 185, Gray, Black, "10"},          //Lpulse
    { 290, 235, 380, 277, 10, 8, 320, 240, Gray, Black, "20"},          //amplBeg
    { 470, 235, 560, 277, 10, 8, 500, 240, Gray, Black, "50"},          //amplEnd
    { 290, 290, 380, 332, 10, 8, 320, 295, Gray, Black, "250"},         //wobFreq
    { 290, 345, 380, 387, 10, 8, 310, 350, Gray, Black, "1500"},        //wobtime
    { 470, 345, 560, 387, 10, 8, 500, 350, Gray, Black, "4"},           //amplNum
    { 200, 410, 600, 452, 10, 8, 210, 415, Gray, Green, "R E A D Y"},   //status line
    { 625, 253, 775, 343,  5, 3, 635, 283, Yellow, Black, "  E D I T"},   //edit btn
    { 625, 365, 775, 455,  5, 3, 635, 395, Yellow, Black, "  M A I N"}    //main btn
};
int TextBoxRSize = 13;
int numTPstatus = 10;   // # txtBoxR[10] for status line    
int numTPeditBtn = 11;  // # txtBoxR[11] for edit btn
int numTPmainBtn = 12;  // # txtBoxR[12] for main btn
int numTPvalBtn = 11;   // # txtBoxR[11] for values btn
int numTPservBtn = 12;  // # txtBoxR[12] for service btn
int numPrPar = 10;      // # of integer programm parameters
int numLmode = 2;       // # of Lmode parameter

int flagParChanged = 0;
int flagLrsConnected = 0;
int flagLcomProcess = 0;
int flagWeld = 0;       //welding in progress    
int TPmode = 0;         //0-Operate mode, 1-Edit mode, 2-Service mode
int editBtnMode = 0;    //0-edit, 1-set
int TPstatus = 0;       //index Stat[]
char sTatus[32];

// Status reported by controller
TPstring Stat[] = {"R E A D Y",             //status 0
                   "IO NOT READY",          //status 1
                   "E-STOP ON",             //status 2
                   "LASER POWER OFF",       //status 3
                   "LASER NOT READY",       //status 4
                   "LASER RS232 NOT READY", //status 5
                   "SHORT IO COMMAND",      //status 6
                   "WRONG IO COMMAND",      //status 7
                   "",                      //status 8
                   "",                      //status 9
                   "",                      //status 10 (do not change it)
                   "LASER DOES NOT ANSWER", //error 11
                   "LASER COMMAND ERROR",   //error 12
                   "",                      //error 13
                   "",                      //status 14
                   "",                      //status 15
                   "READY FOR WELDING",     //status 16 
                   "WOBBLE HEAD INIT...",   //status 17 
                   "WOBBLE HEAD ERROR",     //status 18 
                   "IO CONTROLLER ERROR",   //status 19 
                   "WELDING IN PROGRESS..", //status 20 
                   "",                      //status 21 (auto reset e-stop) 
                   };
int indStat = 0;
                   
// Errors reported by controller    
TPstring fErr[] = {"Done!",
                   "Write error!",
                   "Failed to close file!",
                   "Failed to create file!",
                   "Failed to open file!",
                   "No card present!",
                   "Failed mount SD!"};
//Numpad screen label 
TPstring Labels[] = {"Laser power [%] beg",
                     "Laser power [%] end",
                     "Laser mode",
                     "Laser frequency [Hz]",
                     "Laser pulse length [%]",
                     "Amplitude [0.1mm] beg.",
                     "Amplitude [0.1mm] end",
                     "Wobble frequency [Hz]",
                     "Welding time [mS]",
                     "# of amplitude steps",
                     "File p#"};
int LabelsIndex = 0;                     

TextBox txtBoxNP[] = {
    { 656, 166, 776, 261, 706, 186, Gray, Black, "0"},
    { 290, 360, 410, 455, 340, 380, Gray, Black, "1"},
    { 412, 360, 532, 455, 462, 380, Gray, Black, "2"},
    { 534, 360, 654, 455, 584, 380, Gray, Black, "3"},
    { 290, 263, 410, 358, 340, 283, Gray, Black, "4"},
    { 412, 263, 532, 358, 462, 283, Gray, Black, "5"},
    { 534, 263, 654, 358, 584, 283, Gray, Black, "6"},
    { 290, 166, 410, 261, 340, 186, Gray, Black, "7"},
    { 412, 166, 532, 261, 462, 186, Gray, Black, "8"},
    { 534, 166, 654, 261, 584, 186, Gray, Black, "9"},
    { 656, 263, 776, 358, 706, 283, Gray, Black, "."},
    { 656, 360, 776, 455, 680, 380, Gray, Black, "BACK"},
    { 656, 69, 776, 164, 695, 89, Gray, Black, "OK"}
};
int TextBoxNPSize = 13;
int NPinp = 0;
bool flagNPinp = false;
                                             
int LPscreen = 0;    //0-values, 1-numpad, 2-sevice, 3-main screen

TextBoxR txtBNP = { 300, 120, 640, 162, 10, 8, 320, 130, Gray, Black, ""};

MinMax miMa[] = {
    { 0, 100},    //0-LPbeg
    { 0, 100},    //1-LPend
    { 0, 1},      //2
    { 1, 1000},   //3-Lfreq
    { 1, 100},    //4-Lpulse
    { 0, 90},     //5-amplBeg
    { 0, 90},     //6-amplEnd
    { 1, 100},    //7-wFreq
    { 1, 5000},   //8-wTime
    { 1, 100},    //9-amplNum
    { 0, 99}      //10-file p#
};
int miMaSize = 9;

IOPar ioPar;    //io controller parameters

//------service-------------------------
TextBoxR txtRServ[] = {
    { 625, 365, 775, 455, 10, 8, 650, 395, Yellow, Black, "M A I N"},     //btn main
    { 625, 276, 775, 346, 10, 8, 650, 296, Yellow, Black, "S A V E"},     //btn save
    { 625, 196, 775, 266, 10, 8, 650, 216, Yellow, Black, "L O A D"},     //btn load
    { 625, 116, 775, 186, 10, 8, 650, 136, Yellow, Black, " D I R"},      //btn dir
    { 715,  26, 775,  86, 10, 8, 725,  40, Gray,   Black,   "0"},         //file #
};
int txtRServSize = 5;
int fileNum = 0;

TextBox txtBoxDir[] = {
    { 20,  54, 400,  91, 25,  58, Gray, Black, " "},
    { 20,  93, 400, 130, 25,  97, Gray, Black, " "},
    { 20, 132, 400, 169, 25, 136, Gray, Black, " "},
    { 20, 171, 400, 208, 25, 175, Gray, Black, " "},
    { 20, 210, 400, 247, 25, 214, Gray, Black, " "},
    { 20, 249, 400, 286, 25, 253, Gray, Black, " "},
    { 20, 288, 400, 325, 25, 292, Gray, Black, " "},
    { 20, 327, 400, 364, 25, 331, Gray, Black, " "},
    { 20, 366, 400, 403, 25, 370, Gray, Black, " "}
};
int TextBoxDirSize = 9;

TextBoxR txtRdir[] = {
    { 410,  20, 560, 110, 10, 8, 425,  48, Yellow, Black, "SPLASH"},   //btn splash
    { 410, 210, 560, 300, 10, 8, 450, 238, Yellow, Black, "  UP"},     //btn up
    { 410, 310, 560, 400, 10, 8, 440, 338, Yellow, Black, " DOWN"},    //btn down
};
int txtRdirSize = 3;
//---------------------------------------------------------------------------------
void flipUS(void) {
    NVIC_DisableIRQ(TIMER3_IRQn);    //disable timer3 interrupt
    flipRS();    
    LPC_TIM3->IR |= 1 << 0;         // Clear MR0 interrupt flag
    NVIC_EnableIRQ(TIMER3_IRQn);    //enable timer3 interrupt
}   

 void writeTestFile(void)
 {
    //creating a 1MB test file <Test File.bin>
    iPC = pc.printf("Write <Test File.bin> from %iB buffer", sizeof(bufferNL));
    FileHandle* file = sd.open("Test File.bin", O_WRONLY | O_CREAT | O_TRUNC);
    if (file != NULL) {
        for (int i = 0; i < (1048576 / sizeof(bufferNL)); i++) {
            if (file->write(bufferNL, sizeof(bufferNL)) != sizeof(bufferNL)) {
                pc.printf("write error!\n");
                return;
            }
        }
        if (file->close())
            pc.printf("failed to close file!\n");
        else
            pc.printf("done!\n");
    } else {
        printf("failed to create file!\n");
    }
}

void readTestFile(void)
{
    //read buffer from the 1MB file created by writeTest()
    pc.printf("Read <Test File.bin> to %iB buffer.. ", sizeof(bufferNL));
    FileHandle* file = sd.open("Test File.bin", O_RDONLY);
    if (file != NULL) {
        file->read(bufferNL, sizeof(bufferNL));
        if (file->close())
           pc.printf("failed to close file!\n");
        else
           pc.printf("done!\n");
    }
    else {
        pc.printf("failed to open file!\n");
    }
}

void fillTestBuffer(void){
    for (int i = 0; i < 40; i++) {bufferNL[i] = (char)48;} 
    for (int i = 0; i < 440; i++) {bufferNL[i+40] = (char)49;}    
    for (int i = 0; i < 60; i++) {bufferNL[i+440] = (char)48;}
    
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 50; j++) {
            pc.printf("%c",bufferNL[i * 50 + j]);
        }
        pc.printf("\n");
    }
}

int connectSD(void){
    //Make sure a card is present
    if (!sd.card_present()) {
        pc.printf("\nNo card present!\n");
        return 1;
    }
    //Try to mount the SD card
    //pc.printf("\nMounting SD card...");  //%u", aaa);
    if (sd.mount() != 0) {
        pc.printf("failed mount SD!\n");
        return 2;
    }
    //pc.printf("success!\n");
    return 0;
}


void disconnectSD(void) {
    sd.unmount();    
}
    
void infoSD(void)
{
     //Display the card type
    pc.printf("\tCard type: ");
    SDFileSystem::CardType cardType = sd.card_type();
    if (cardType == SDFileSystem::CARD_NONE)
        pc.printf("None\n");
    else if (cardType == SDFileSystem::CARD_MMC)
        pc.printf("MMC\n");
    else if (cardType == SDFileSystem::CARD_SD)
        pc.printf("SD\n");
    else if (cardType == SDFileSystem::CARD_SDHC)
        pc.printf("SDHC\n");
    else
        pc.printf("Unknown\n");
    //Display the card capacity
    pc.printf("\tSectors: %u\n", sd.disk_sectors());
    pc.printf("\tCapacity: %.1fMB\n", sd.disk_sectors() / 2048.0);
}

bool readDirSD(char *pDr)
{
    bool result = true;
    DIR *dir;
    struct dirent *ent;
    //pc.printf("D- %i\n", pDr);    
    if ((dir = sd.opendir (pDr)) != NULL) {
        // print all the files and directories within directory
        while ((ent = readdir (dir)) != NULL) {
            pc.printf("%s\r\n", ent->d_name);
        }
        closedir (dir);
    } else {
        // could not open directory
        pc.printf("Could not open directory");
        result = false;
    }
    return !result;
}

char dirName[40][40];
int indName = 0;
string dirS;
 
bool readDirHmiSD(char *pDr)
{
    bool result = true;
    DIR *dir;
    struct dirent *ent;
    if ((dir = sd.opendir (pDr)) != NULL) {
        dirS.assign(pDr);
        // copy all the files and directories within directory
        indName = 0;
        while ((ent = readdir (dir)) != NULL) {
            strcpy(dirName[indName++], ent->d_name);
        }
        closedir (dir);
    } else {
        // could not open directory
        pc.printf("Could not open directory");
        result = false;
    }
    return !result;
} 
//ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
int bufferPar[128];

void saveBufferPar(void){
    //clean bufferPar[]
    for (int i = 0; i < 128; i++) {
        bufferPar[i] = 0;
    }
    //save parameters in bufferPar 
    for (int i = 0; i < 8; i++) {
        bufferPar[i*16] = prPar[i].wMode;
        bufferPar[i*16+1] = prPar[i].LPbeg;
        bufferPar[i*16+2] = prPar[i].LPend;
        bufferPar[i*16+3] = prPar[i].Lmode;
        bufferPar[i*16+4] = prPar[i].Lfreq;
        bufferPar[i*16+5] = prPar[i].Lpulse;
        bufferPar[i*16+6] = prPar[i].amplBeg;
        bufferPar[i*16+7] = prPar[i].amplEnd;
        bufferPar[i*16+8] = prPar[i].wFreq;
        bufferPar[i*16+9] = prPar[i].wTime;
        bufferPar[i*16+10] = prPar[i].amplNum;   
    }
    //print bufferPar
//    /*
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16]);}
    pc.printf("wMode\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+1]);}
    pc.printf("LPbeg\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+2]);}
    pc.printf("LPend\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+3]);}
    pc.printf("Lmode\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+4]);}
    pc.printf("Lfreq\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+5]);}
    pc.printf("Lpulse\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+6]);}
    pc.printf("amplBeg\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+7]);}
    pc.printf("amplEnd\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+8]);}
    pc.printf("wFreq\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+9]);}
    pc.printf("wTime\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+10]);}
    pc.printf("amplNum\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",bufferPar[j * 16+11]);}
    pc.printf("\n");
//    */
}

void readBufferPar(void){
    //save parameters in prPar
    for (int i = 0; i < 8; i++) {
        if(bufferPar[i*16] < 0) bufferPar[i*16] = 0;
        if(bufferPar[i*16] > 2) bufferPar[i*16] = 2;
        prPar[i].wMode = bufferPar[i*16];
        if(bufferPar[i*16+1] < miMa[0].min) bufferPar[i*16+1] = miMa[0].min;
        if(bufferPar[i*16+1] > miMa[0].max) bufferPar[i*16+1] = miMa[0].max;
        prPar[i].LPbeg = bufferPar[i*16+1];
        if(bufferPar[i*16+2] < miMa[1].min) bufferPar[i*16+2] = miMa[1].min;
        if(bufferPar[i*16+2] > miMa[1].max) bufferPar[i*16+2] = miMa[1].max;
        prPar[i].LPend = bufferPar[i*16+2];
        if(bufferPar[i*16+3] < miMa[2].min) bufferPar[i*16+3] = miMa[2].min;
        if(bufferPar[i*16+3] > miMa[2].max) bufferPar[i*16+3] = miMa[2].max;
        prPar[i].Lmode = bufferPar[i*16+3];
        if(bufferPar[i*16+4] < miMa[3].min) bufferPar[i*16+4] = miMa[3].min;
        if(bufferPar[i*16+4] > miMa[3].max) bufferPar[i*16+4] = miMa[3].max;
        prPar[i].Lfreq = bufferPar[i*16+4];
        if(bufferPar[i*16+5] < miMa[4].min) bufferPar[i*16+5] = miMa[4].min;
        if(bufferPar[i*16+5] > miMa[4].max) bufferPar[i*16+5] = miMa[4].max;
        prPar[i].Lpulse = bufferPar[i*16+5];
        if(bufferPar[i*16+6] < miMa[5].min) bufferPar[i*16+6] = miMa[5].min;
        if(bufferPar[i*16+6] > miMa[5].max) bufferPar[i*16+6] = miMa[5].max;
        prPar[i].amplBeg = bufferPar[i*16+6];
        if(bufferPar[i*16+7] < miMa[6].min) bufferPar[i*16+7] = miMa[6].min;
        if(bufferPar[i*16+7] > miMa[6].max) bufferPar[i*16+7] = miMa[6].max;
        prPar[i].amplEnd = bufferPar[i*16+7];
        if(bufferPar[i*16+8] < miMa[7].min) bufferPar[i*16+8] = miMa[7].min;
        if(bufferPar[i*16+8] > miMa[7].max) bufferPar[i*16+8] = miMa[7].max;
        prPar[i].wFreq = bufferPar[i*16+8];
        if(bufferPar[i*16+9] < miMa[8].min) bufferPar[i*16+9] = miMa[8].min;
        if(bufferPar[i*16+9] > miMa[8].max) bufferPar[i*16+9] = miMa[8].max;
        prPar[i].wTime = bufferPar[i*16+9];
        if(bufferPar[i*16+10] < miMa[9].min) bufferPar[i*16+10] = miMa[9].min;
        if(bufferPar[i*16+10] > miMa[9].max) bufferPar[i*16+10] = miMa[9].max;
        prPar[i].amplNum = bufferPar[i*16+10];   
    }
    //print prPar
//    /*
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].wMode);}
    pc.printf("wMode\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].LPbeg);}
    pc.printf("LPbeg\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].LPend);}
    pc.printf("LPend\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].Lmode);}
    pc.printf("Lmode\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].Lfreq);}
    pc.printf("Lfreq\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].Lpulse);}
    pc.printf("Lpulse\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].amplBeg);}
    pc.printf("amplBeg\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].amplEnd);}
    pc.printf("amplEnd\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].wFreq);}
    pc.printf("wFreq\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].wTime);}
    pc.printf("wTime\n");
    for (int j = 0; j < 8; j++) {pc.printf("%i ",prPar[j].amplNum);}
    pc.printf("amplNum\n");
//    */
}

char fileN[20];
int errOK;

int wrFile(char *fName)
{
    errOK = connectSD();
    if(errOK == 0) {
        FileHandle* file = sd.open(fName, O_WRONLY | O_CREAT | O_TRUNC);
        if (file != NULL) {
            if (file->write(bufferPar, sizeof(bufferPar)) != sizeof(bufferPar)) {
                pc.printf("write error!\n");
                errOK = 1;
            }
            if (file->close()) {
                pc.printf("failed to close file!\n");
                errOK = 2;
            }    
            else {
                pc.printf("done!\n");
                errOK = 0;
            }
        }        
        else {
            printf("failed to create file!\n");
            errOK = 3;
        }
        disconnectSD();
    }
    else {errOK = errOK + 4;}
    return errOK;
}

int writeIniFile(void)
{
    for (int i = 0; i < 128; i++) {bufferPar[i] = 0;}   //clean bufferPar[]
    bufferPar[0] = fileNum;
    bufferPar[1] = progNumber;
    
    sprintf(fileN, "p.ini");
    pc.printf("%s\n", fileN);
    
    int resp = wrFile(fileN);
    return resp;
}

int writeParFile(int numP)
{
    saveBufferPar();

    sprintf(fileN, "p%i.par", numP);
    pc.printf("%s\n", fileN);
    
    int resp = wrFile(fileN);
    if(resp == 0) {resp = writeIniFile();}
    return resp;
}

int rdFile(char *fName)
{
    errOK = connectSD();
    if(errOK == 0) {
        FileHandle* file = sd.open(fName, O_RDONLY);
        if (file != NULL) {
            file->read(bufferPar, sizeof(bufferPar));
            if (file->close()) {
               pc.printf("failed to close file!\n");
               errOK = 2;
            }   
            else {
               pc.printf("done!\n");
               errOK = 0;
            }   
        }
        else {
            pc.printf("failed to open file!\n");
            errOK = 4;
        }
        disconnectSD();
    }
    else {errOK = errOK + 4;}
    return errOK;
}

int readParFile(int numP)
{
    sprintf(fileN, "p%i.par", numP);
    pc.printf("%s\n", fileN);
    
    int resp = rdFile(fileN);
    if(resp == 0) {
        readBufferPar();
        resp = writeIniFile();
    }
    return resp;
}

void readIniFile(void)
{
    sprintf(fileN, "p.ini");
    pc.printf("%s\n", fileN);
    
    int resp = rdFile(fileN);
    if(resp == 0) {
        if(bufferPar[0] < miMa[10].min) bufferPar[0] = miMa[10].min;
        if(bufferPar[0] > miMa[10].max) bufferPar[0] = miMa[10].max;
        fileNum = bufferPar[0];    
        if(bufferPar[1] < 1) bufferPar[1] = 1;
        if(bufferPar[1] > 8) bufferPar[1] = 8;
        progNumber = bufferPar[1];    
        resp = readParFile(fileNum);
    }    
}
//ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

//---------------------------------------------
// When drawing a "fingerprint" under the touch point - the RA8875 
// cannot draw an object partially off-screen, so this shrinks the 
// fingerprint as the touch approaches the edge of the screen.
//
int ComputeRadius(point_t p)
{
    int radius = DEF_RADIUS;
    
    if (p.x < radius)
        radius = p.x;
    else if (LCD_W - p.x < radius)
        radius = LCD_W - p.x;
    if (p.y < radius)
        radius = p.y;
    else if (LCD_H - p.y < radius)
        radius = LCD_H - p.y;
    return radius;
}

// Calibrate the resistive touch screen, and store the data on the local file system.
void CalibrateTS(void)
{
    tpMatrix_t matrix;
    RetCode_t r;
    Timer testperiod;
 
    r = lcd.TouchPanelCalibrate("Calibrate the touch panel", &matrix);
    if (r == noerror) {
        if (connectSD() == 0) {
            FileHandle* fh = sd.open("tpcal.cfg", O_WRONLY | O_CREAT | O_TRUNC);
            if (fh) {
                if (fh->write(&matrix, sizeof(tpMatrix_t)) != sizeof(tpMatrix_t))
                {
                    pc.printf("write error!\n");
                }
                if (fh->close()) pc.printf("failed to close file!\n");
            }
            else printf("failed to create tpcal.cfg file!\n");
        }    
    } 
    else printf("error TP Calibrate: %d\r\n", r);
    disconnectSD();
    pc.printf("TS ok\n");
    lcd.cls();
}

// Try to load a previous resistive touch screen calibration from storage. If it
// doesn't exist, activate the touch screen calibration process.
void InitTS(void)
{
    tpMatrix_t matrix;
    if (connectSD() == 0) {
        FileHandle* fh = sd.open("tpcal.cfg", O_RDONLY);
        if (fh) {
            if (fh->read(&matrix, sizeof(tpMatrix_t)) != sizeof(tpMatrix_t))
            {
                pc.printf("read error!\n");
                //return;
                if (fh->close()) pc.printf("failed to close file!\n");
            }
            else
            {
                lcd.TouchPanelSetMatrix(&matrix);
                if (fh->close()) pc.printf("failed to close file!\n");
                disconnectSD();
                pc.printf("ok\n");
                return;
            }
        }
        else printf("failed to open tpcal.cfg file!\n");
    }
    disconnectSD();
    CalibrateTS();
}

//-------------------------------------------------------
void lcd800x480Init(void)
{
    lcd.init(LCD_W,LCD_H,LCD_C);
    //lcd.init();
    lcd.Backlight(0.5f);
    //lcd.Backlight_u8(BL_NORM);

    lcd.foreground(RGB(255,255,0));
    lcd.background(RGB(0,0,0));
    
    lcd.SelectUserFont(BPG_Arial08x08);
    lcd.puts(300, 0, "www.ipgphotonics.com\r\n");

    lcd.SelectUserFont(BPG_Arial31x32);
    
    lastTP.x = 0;
    lastTP.y = 0;
}

void showTPstatus(int k)
{
    int i = numTPstatus;
    lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
    lcd.foreground(txtBoxR[i].textColor);
    lcd.background(txtBoxR[i].color);
    
    lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "                               ");
    lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, Stat[k]);
    //pc.printf("q%i\n", k);
}

void showTPeditBtn(int k)
{
    int i = numTPeditBtn;
    lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
    lcd.foreground(txtBoxR[i].textColor);
    lcd.background(txtBoxR[i].color);
    
    if(k == 0) {lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "  E D I T");}
    else {lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "   S E T");}
}

void showTPmainBtn(void)
{
    int i = numTPmainBtn;
    lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
    lcd.foreground(txtBoxR[i].textColor);
    lcd.background(txtBoxR[i].color);
    
    lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "  M A I N");
}

void showTPvalBtn(void)
{
    int i = numTPvalBtn;
    lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
    lcd.foreground(txtBoxR[i].textColor);
    lcd.background(txtBoxR[i].color);
    
    lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, " VALUES");
}

void showTPservBtn(void)
{
    int i = numTPservBtn;
    lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
    lcd.foreground(txtBoxR[i].textColor);
    lcd.background(txtBoxR[i].color);
    
    lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "SERVICE");
}

void showProgNum(int i)
{
    //pc.printf("%i\n", i);
    if((i >= 0) && (i < 8)) { //&& (i != progNumber) ) {
        //pc.printf(":\n");
        lcd.fillrect(txtBox[progNumber].x1, txtBox[progNumber].y1, txtBox[progNumber].x2, txtBox[progNumber].y2, txtBox[progNumber].color);
        lcd.foreground(txtBox[progNumber].textColor);
        lcd.background(txtBox[progNumber].color);
        lcd.puts(txtBox[progNumber].textX, txtBox[progNumber].textY, txtBox[progNumber].text);
        
        lcd.fillrect(txtBox[i].x1, txtBox[i].y1, txtBox[i].x2, txtBox[i].y2, Green);
        lcd.foreground(txtBox[i].textColor);
        lcd.background(Green);
        lcd.puts(txtBox[i].textX, txtBox[i].textY, txtBox[i].text);
        progNumber = i; 
    }
}
 
void showWobMode(int i)
{
    if((i >= 0) && (i < 3)) {
        //pc.printf(";\n");
        int k;
        k = wobbleMode + 8;
        lcd.fillrect(txtBox[k].x1, txtBox[k].y1, txtBox[k].x2, txtBox[k].y2, txtBox[k].color);
        lcd.foreground(txtBox[k].textColor);
        lcd.background(txtBox[k].color);
        lcd.puts(txtBox[k].textX, txtBox[k].textY, txtBox[k].text);
        k = i + 8;
        lcd.fillrect(txtBox[k].x1, txtBox[k].y1, txtBox[k].x2, txtBox[k].y2, Green);
        lcd.foreground(txtBox[k].textColor);
        lcd.background(Green);
        lcd.puts(txtBox[k].textX, txtBox[k].textY, txtBox[k].text);
        wobbleMode = i;
    }
}
    
void showWobParam(int i)
{
    showWobMode(i);
    prPar[progNumber].wMode = i;
}

void showProgParam(int k)
{
    showProgNum(k);
    //fill round text boxes (TextBoxR)
    showWobMode(prPar[progNumber].wMode);
    for(int i = 0; i < numPrPar; i++) {
        lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
        lcd.foreground(txtBoxR[i].textColor);
        lcd.background(txtBoxR[i].color);
        if (i == 2) {
             if(prPar[progNumber].Lmode == 0) {
                 lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "CW");
                 if(Lmode == 1) { 
                     Lmode = 0;
                     if(SetLasComm(33) == 1) {TPstatus = 5;}      //DPM -disable pulse mode
                     else {
                        if(SetLasComm( 1) == 1) {TPstatus = 5;}   //STA -read laser status
                        else TPstatus = 0; 
                    }
                }               
             }    
             else if(prPar[progNumber].Lmode == 1) {
                 lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "PULSE");
                 if(Lmode == 0) {
                     Lmode = 1;
                     if(SetLasComm(32) == 1) {TPstatus = 5;}       //EPM -enable pulse mode
                     else {
                        if(SetLasComm( 1) == 1) {TPstatus = 5;}   //STA -read laser status
                        else TPstatus = 0; 
                    }
                }                    
            }    
        }
        else {
            switch (i) {
                case 0: {sprintf(txtBoxR[0].text, "%i", prPar[progNumber].LPbeg); break;}
                case 1: {sprintf(txtBoxR[1].text, "%i", prPar[progNumber].LPend); break;}
                case 3: {sprintf(txtBoxR[3].text, "%i", prPar[progNumber].Lfreq); break;}
                case 4: {sprintf(txtBoxR[4].text, "%i", prPar[progNumber].Lpulse); break;}
                case 5: {sprintf(txtBoxR[5].text, "%i", prPar[progNumber].amplBeg); break;}
                case 6: {sprintf(txtBoxR[6].text, "%i", prPar[progNumber].amplEnd); break;}
                case 7: {sprintf(txtBoxR[7].text, "%i", prPar[progNumber].wFreq); break;}
                case 8: {sprintf(txtBoxR[8].text, "%i", prPar[progNumber].wTime); break;}
                case 9: {sprintf(txtBoxR[9].text, "%i", prPar[progNumber].amplNum); break;}
            }
            lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, txtBoxR[i].text);
        }
    }
}

void lcd800x480main(int a)
{
    lcd.roundrect(    2,10, 798,478, 10,8,    Yellow);  //full screen
    lcd.fillroundrect(3,11, 797,477, 8,6,     Black);   //do full screen black
    lcd.roundrect(    620,360, 780,460, 10,8, Yellow);  //around btn edit
    lcd.roundrect(    620,248, 780,348, 10,8, Yellow);  //around btn service
    lcd.roundrect(    5,62, 615,405, 10,8,    Yellow);  //picture screen
    
    lcd.foreground(Yellow);
    lcd.background(Black);
    lcd.puts(100, 20, "Program #");
    lcd.puts(20, 415, "STATUS:");
   
    //fill text boxes (TextBox)
    for(int i = 0; i < 8; i++) {
        lcd.fillrect(txtBox[i].x1, txtBox[i].y1, txtBox[i].x2, txtBox[i].y2, txtBox[i].color);
        lcd.foreground(txtBox[i].textColor);
        lcd.background(txtBox[i].color);
        lcd.puts(txtBox[i].textX, txtBox[i].textY, txtBox[i].text);
    }
    showProgNum(a);
    //fill round text boxes (TextBoxR)

}

void lcd800x480val(int a)
{
    lcd.roundrect(    2,10, 798,478, 10,8,    Yellow);  //full screen
    lcd.fillroundrect(3,11, 797,477, 8,6,     Black);   //do full screen black
    lcd.roundrect(    620,360, 780,460, 10,8, Yellow);  //around btn edit
    lcd.roundrect(    620,248, 780,348, 10,8, Yellow);  //around btn service
    
    lcd.foreground(Yellow);
    lcd.background(Black);
    lcd.puts(10, 20, "Program #");
    lcd.puts(10, 75, "Wobble mode");
    lcd.puts(10, 130, "Laser power [%] beg");
    lcd.puts(390, 130, " end");
    lcd.puts(570, 130, "mode");
    lcd.puts(10, 185, "Laser freq.[Hz]");
    lcd.puts(390, 185, "Pulse");
    lcd.puts(575, 185, "[%]");
    lcd.puts(10, 240, "Size [0.1mm] beg.");
    lcd.puts(390, 240, " end");
    lcd.puts(10, 295, "Wobble freq.[Hz]");
    lcd.puts(10, 350, "Welding time [mS]");
    lcd.puts(390, 350, "Steps");
    lcd.puts(20, 415, "STATUS:");
   
    //fill text boxes (TextBox)
    for(int i = 0; i < TextBoxSize; i++) {
        lcd.fillrect(txtBox[i].x1, txtBox[i].y1, txtBox[i].x2, txtBox[i].y2, txtBox[i].color);
        lcd.foreground(txtBox[i].textColor);
        lcd.background(txtBox[i].color);
        lcd.puts(txtBox[i].textX, txtBox[i].textY, txtBox[i].text);
    }
    //fill round text boxes (TextBoxR)
    showProgParam(a);
}

void lcd800x480NP(int k)
{
    lcd.roundrect(    285,65, 781,460, 10,8,    Yellow);
    lcd.fillroundrect(288,68, 776,455, 5,3,    Black);
    
    lcd.foreground(Yellow);
    lcd.background(Black);
    lcd.puts(300, 75, Labels[k]);
   
    //fill text boxes (TextBox)
    for(int i = 0; i < TextBoxNPSize; i++) {
        lcd.fillrect(txtBoxNP[i].x1, txtBoxNP[i].y1, txtBoxNP[i].x2, txtBoxNP[i].y2, txtBoxNP[i].color);
        lcd.foreground(txtBoxNP[i].textColor);
        lcd.background(txtBoxNP[i].color);
        lcd.puts(txtBoxNP[i].textX, txtBoxNP[i].textY, txtBoxNP[i].text);
    }
    //fill round text box
    lcd.fillroundrect(txtBNP.x1, txtBNP.y1, txtBNP.x2, txtBNP.y2, txtBNP.r1, txtBNP.r2, txtBNP.color);
    lcd.foreground(txtBNP.textColor);
    lcd.background(txtBNP.color);
    *txtBNP.text = '\0';
    lcd.puts(txtBNP.textX, txtBNP.textY, txtBNP.text);
}

void lcd800x480Serv(void)
{
    lcd.roundrect(    2,10, 798,478, 10,8,    Yellow);  //full screen
    lcd.fillroundrect(3,11, 797,477, 8,6,     Black);   //do full screen black
    lcd.roundrect(    620,360, 780,460, 10,8, Yellow);  //around main btn 
    lcd.roundrect(    620,20, 780,348, 10,8, Yellow);   //around file btns
    lcd.roundrect(    20,418, 600,460, 10,8, Yellow);   //around status line
    
    lcd.foreground(Yellow);
    lcd.background(Black);
    lcd.puts(623, 40, "File p#");
   
    //fill round text box
    int i;
    i = txtRServSize-1;
    sprintf(txtRServ[i].text, "%i", fileNum);
    for(i = 0; i < txtRServSize; i++) {
        lcd.fillroundrect(txtRServ[i].x1, txtRServ[i].y1, txtRServ[i].x2, txtRServ[i].y2, txtRServ[i].r1, txtRServ[i].r2, txtRServ[i].color);
        lcd.foreground(txtRServ[i].textColor);
        lcd.background(txtRServ[i].color);
        lcd.puts(txtRServ[i].textX, txtRServ[i].textY, txtRServ[i].text);
    }
}

void lcd800x480dirB(void)
{
    lcd.fillrect(20, 15, 565, 405, Black);
}

void lcd800x480dir(char *pDr)
{
    int i;
    
    lcd.fillrect(20, 15, 565, 405, Black);            //clean area
    lcd.roundrect(20,15, 400,52, 10,8,    Yellow);    //around dir name
    lcd.roundrect(405,15, 565,405, 10,8,    Yellow);  //around buttons
    
    lcd.foreground(Yellow);
    lcd.background(Black);
    lcd.puts(25, 19, rDr);
   
    //fill round text box
    for(i = 0; i < txtRdirSize; i++) {
        lcd.fillroundrect(txtRdir[i].x1, txtRdir[i].y1, txtRdir[i].x2, txtRdir[i].y2, txtRdir[i].r1, txtRdir[i].r2, txtRdir[i].color);
        lcd.foreground(txtRdir[i].textColor);
        lcd.background(txtRdir[i].color);
        lcd.puts(txtRdir[i].textX, txtRdir[i].textY, txtRdir[i].text);
    }
    //fill text boxes (TextBox)
    for(i = 0; i < TextBoxDirSize; i++) {
        lcd.fillrect(txtBoxDir[i].x1, txtBoxDir[i].y1, txtBoxDir[i].x2, txtBoxDir[i].y2, txtBoxDir[i].color);
        lcd.foreground(txtBoxDir[i].textColor);
        lcd.background(txtBoxDir[i].color);
        //lcd.puts(txtBoxDir[i].textX, txtBoxDir[i].textY, txtBoxDir[i].text);
    }
}

void showMain(int i) {
    lcd800x480main(i);
    showTPvalBtn();
    showTPservBtn();
    showTPstatus(TPstatus);
    LPscreen = 3;
}

void showVal(int i) {
    lcd800x480val(i);
    showTPeditBtn(editBtnMode);
    showTPmainBtn();
    showTPstatus(TPstatus);
}

void showNP(int i) {
    lcd800x480NP(i);    
}

void showService(void) {
    lcd800x480Serv();    
}

void statServErr(int stS) {
    lcd.foreground(Gray);
    lcd.background(Black);
    lcd.puts(30, 423, "                               ");
    lcd.puts(30, 423, Stat[stS]);    
}

void statServ(int stS) {
    lcd.foreground(Gray);
    lcd.background(Black);
    lcd.puts(30, 423, "                               ");
    lcd.puts(30, 423, fErr[stS]);    
}

void dirOpenHmi(char *pDr) {
    if(connectSD() == 0) {
        readDirHmiSD(pDr);
    }    
    disconnectSD();
    
    lcd800x480dir(rDr);
    if(indName > 9) {
        for(int i=0; i<9; i++) {
            lcd.puts(txtBoxDir[i].textX, txtBoxDir[i].textY, dirName[i]);
        }    
    }
    else {
        for(int i=0; i<indName; i++) {
            lcd.puts(txtBoxDir[i].textX, txtBoxDir[i].textY, dirName[i]);
        }    
    }
    for(int i=0; i<indName; i++) {
        pc.printf("%s\n", dirName[i]);
    }    
    pc.printf(">>%i\n", indName);
}            

int flagDirOpen = 0;
    
void btnServ(int k) {
    int retSt;
    switch (k) {
    case 0:    //btn main
        showMain(progNumber);
        LPscreen = 3;   //main screen
        pc.printf("\n>");
        break;
    case 1:    //btn save
        retSt = writeParFile(fileNum);
        statServ(retSt);
        pc.printf("\ns>%i ", retSt);
        break;
    case 2:    //btn load
        retSt = readParFile(fileNum);
        statServ(retSt);
        pc.printf("\nl>%i ", retSt);
        flagParChanged = 0;
        break;
    case 3:    //btn dir
        if(flagDirOpen ==0) {
            flagDirOpen = 1;
            dirOpenHmi(rDr);
        }
        else {
            flagDirOpen = 0;
            lcd800x480dirB();
        }    
        break;
    case 4:    //txtBox file#
        showNP(10);
        LabelsIndex = 10;
        NPinp = 0;
        flagNPinp = false;
        LPscreen = 1;   //LP screen
    
        pc.printf("\nf ");
        break;
    }
}
/*
RetCode_t showBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image)
{
    BITMAPINFOHEADER BMP_Info;
    RGBQUAD * colorPalette = NULL;
    int colorCount;
    uint8_t * lineBuffer = NULL;
    color_t * pixelBuffer = NULL;
    uint16_t BPP_t;
    dim_t PixelWidth, PixelHeight;
    unsigned int    i, offset;
    int padd,j;

    // Now, Read the bitmap info header
    Image->read(&BMP_Info, sizeof(BMP_Info));
    HexDump0("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
    BPP_t = BMP_Info.biBitCount;
    pc.printf("biBitCount %04X", BPP_t);
    if (BPP_t != 1 && BPP_t != 4 && BPP_t != 8 && BPP_t != 16 && BPP_t != 24) { // Support 4, 8, 16, 24-bits per pixel
        Image->close();
        pc.printf("not_supported_format");
        return(not_supported_format);
    }
    if (BMP_Info.biCompression != 0) {  // Only the "no comporession" option is supported.
        Image->close();
        pc.printf("not_supported_format");
        return(not_supported_format);
    }
    PixelHeight = BMP_Info.biHeight;
    PixelWidth = BMP_Info.biWidth;
    pc.printf("(%d,%d) (%d,%d) (%d,%d)", x,y, PixelWidth,PixelHeight, width(), height());
    if (PixelHeight > 340 || PixelWidth > 608 {
        Image->close();
        pc.printf("image_too_big");
        return(image_too_big);
    }
    if (BMP_Info.biBitCount <= 8) {
        int paletteSize;
        // Read the color palette
        colorCount = 1 << BMP_Info.biBitCount;
        paletteSize = sizeof(RGBQUAD) * colorCount;
        colorPalette = (RGBQUAD *)malloc(paletteSize);
        if (colorPalette == NULL) {
        Image->close();
        pc.printf("not_enough_ram");
            return(not_enough_ram);
        }
        Image->read(colorPalette, paletteSize);
        HexDump0("Color Palette", (uint8_t *)colorPalette, paletteSize);
    }

    int lineBufSize = ((BPP_t * PixelWidth + 7)/8);
    pc.printf("BPP_t %d, PixelWidth %d, lineBufSize %d", BPP_t, PixelWidth, lineBufSize);
    lineBuffer = (uint8_t *)malloc(lineBufSize);
    if (lineBuffer == NULL) {
        free(colorPalette);
        fclose(Image);
        return(not_enough_ram);
    }
    pixelBuffer = (color_t *)malloc(PixelWidth * sizeof(color_t));
    if (pixelBuffer == NULL) {
        free(lineBuffer);
        if (colorPalette)
            free(colorPalette);
        Image->close();
        pc.printf("not_enough_ram");
        return(not_enough_ram);
    }

    padd = (lineBufSize % 4);
    if (padd)
        padd = 4 - padd;

    // Define window for top to bottom and left to right so writing auto-wraps
    rect_t restore = windowrect;
    window(x,y, PixelWidth,PixelHeight);
    SetGraphicsCursor(x, y);
    //StartGraphicsStream
    WriteCommand(0x40,0x00);    // Graphics write mode
    WriteCommand(0x02);         // Prepare for streaming data

    //start_data = BMP_Info.bfOffBits;
    //HexDump("Raw Data", (uint8_t *)&start_data, 32);
    pc.printf("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd);
    for (j = PixelHeight - 1; j >= 0; j--) {                //Lines bottom up
        offset = fileOffset + j * (lineBufSize + padd);     // start of line
        //fseek(Image, offset, SEEK_SET);
        Image->read(lineBuffer, lineBufSize);               // read a line - slow !
        //INFO("offset: %6X", offset);
        //HexDump("Line", lineBuffer, lineBufSize);
        for (i = 0; i < PixelWidth; i++) {                  // copy pixel data to TFT
            if (BPP_t == 1) {
                uint8_t dPix = lineBuffer[i/8];
                uint8_t bMask = 0x80 >> (i % 8);
                uint8_t bit = (bMask & dPix) ? 0 : 1;
                //INFO("%02X & %02X ? => %02X", dPix, bMask, bit);
                pixelBuffer[i] = RGBQuadToRGB16(colorPalette, bit);                
            } else if (BPP_t == 4) {
                uint8_t dPix = lineBuffer[i/2];
                if ((i & 1) == 0)
                    dPix >>= 4;
                dPix &= 0x0F;
                pixelBuffer[i] = RGBQuadToRGB16(colorPalette, dPix);
            } else if (BPP_t == 8) {
                pixelBuffer[i] = RGBQuadToRGB16(colorPalette, lineBuffer[i]);
            } else if (BPP_t == 16) {
                pixelBuffer[i] = lineBuffer[i];
            } else if (BPP_t == 24) {
                color_t color;
                color = RGB(lineBuffer[i*3+2], lineBuffer[i*3+1], lineBuffer[i*3+0]);
                pixelBuffer[i] = color;
            }
        }
        pixelStream(pixelBuffer, PixelWidth, x, y++);
    }
    window(restore);
    free(pixelBuffer);      // don't leak memory
    free(lineBuffer);
    if (colorPalette)
        free(colorPalette);
    return (noerror);
}

static void HexDump0(const char * title, const uint8_t * p, int count)
{
    int i;
    char buf[100] = "0000: ";
    
    if (*title)
    for (i=0; i<count; ) {
        sprintf(buf + strlen(buf), "%02X ", *(p+i));
        if ((++i & 0x0F) == 0x00) {
            if (i < count)
                sprintf(buf, "%04X: ", i);
            else
                buf[0] = '\0';
        }
    }
}

void showPic(void) {
    const char Name_BMP[] = "/local/48027224.bmp";
    
    if (connectSD() == 0) {
        FileHandle* fh = sd.open(Name_BMP, O_RDONLY);
        if (fh) {
             if (fh->read(&BMP_Header, sizeof(BMP_Header)) != sizeof(BMP_Header))
            {
                pc.printf("read error!\n");
                if (fh->close()) pc.printf("failed to close file!\n");
            }
            else
            {
                pc.printf("bfType %04X", BMP_Header.bfType);
                HexDump0("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));
                if (BMP_Header.bfType != BF_TYPE) {
                    fh->close();
                    pc.printf("not_bmp_format");
                }
                pc.printf("bfOffits %04X", BMP_Header.bfOffBits);
                RetCode_t rt = showBitmap(5, 62, BMP_Header.bfOffBits, fh);
                pc.printf("==%i\n", rt);
                if (fh->close()) pc.printf("failed to close file!\n");
            }                
        }
        else {
            pc.printf("file_not_found");    
        }    
    }       
    disconnectSD();
                
            
    char fqfn[50];
    int i = 0;

            if (fh->read(&matrix, sizeof(tpMatrix_t)) != sizeof(tpMatrix_t))
            {
                pc.printf("read error!\n");
                //return;
                if (fh->close()) pc.printf("failed to close file!\n");
            }
            else
            {
                lcd.TouchPanelSetMatrix(&matrix);
                if (fh->close()) pc.printf("failed to close file!\n");
                disconnectSD();
                pc.printf("ok\n");
                return;
            }
        }
        else printf("failed to open tpcal.cfg file!\n");
    }
    disconnectSD();


    INFO("Screen Capture... ");
    for (i=1; i< 100; i++) {
        snprintf(fqfn, sizeof(fqfn), "/local/Screen%02d.bmp", i);
        FILE * fh = fopen(fqfn, "rb");
        if (!fh) {
            lcd.PrintScreen(0,0,lcd.width(),lcd.height(),fqfn);
            INFO(" as /local/Screen%02d.bmp", i);
            return i;
        } else {
            fclose(fh);     // close this and try the next
        }
    }
    return 0;

        RetCode_t r = lcd.PrintScreen(5,62,615,405,"/sd/local/48027224.bmp");
}
*/
LocalFileSystem local("local"); 
void showPic(void) {
    RetCode_t r = lcd.RenderImageFile(8, 66, "/local/Rio24.bmp");    
}    

int indDirFirst = 0;
int indDirCheck = 0;

void btnDir(int k) {
    int nn = indName;
    switch (k) {
    case 0:   //btn splash
        showMain(progNumber);
        LPscreen = 3;   //main screen

        showPic();

        break;
    case 1:   //btn up
        if(nn > 9) {
            lcd800x480dir(rDr);
            if((indDirFirst) > 8) indDirFirst = indDirFirst - 8;
            else indDirFirst = 0;
            for(int i=0; i<9; i++) {
                lcd.puts(txtBoxDir[i].textX, txtBoxDir[i].textY, dirName[indDirFirst + i]);
            }    
        }
        break;
    case 2:   //btn down
        if(nn > 9) {
            lcd800x480dir(rDr);
            if((nn - indDirFirst) > 16) indDirFirst = indDirFirst + 8;
            else indDirFirst = nn - 9;
            for(int i=0; i<9; i++) {
                lcd.puts(txtBoxDir[i].textX, txtBoxDir[i].textY, dirName[indDirFirst + i]);
            }    
        }
        break;
    }
}

int indDirText = 0;
char ccD[40];

void btnDirText(int k) {
    int nn = indDirText - 1;
    
    if(indDirText != 0) {
        lcd.fillrect(txtBoxDir[nn].x1, txtBoxDir[nn].y1, txtBoxDir[nn].x2, txtBoxDir[nn].y2, txtBoxDir[nn].color);
        lcd.foreground(txtBoxDir[nn].textColor);
        lcd.background(txtBoxDir[nn].color);
        lcd.puts(txtBoxDir[nn].textX, txtBoxDir[nn].textY, dirName[indDirFirst + nn]);
    }
    indDirText = k + 1;
    nn = k;
    lcd.fillrect(txtBoxDir[k].x1, txtBoxDir[k].y1, txtBoxDir[k].x2, txtBoxDir[k].y2, Yellow);
    lcd.foreground(txtBoxDir[k].textColor);
    lcd.background(Yellow);
    lcd.puts(txtBoxDir[k].textX, txtBoxDir[k].textY, dirName[indDirFirst + k]);
    
    if (strchr(dirName[indDirFirst + k], '.') == NULL) {
        //pc.printf("<%s>", dirName[indDirFirst + k]);
        dirS.append(dirName[indDirFirst + k]);
        //pc.printf("<%s>", dirS.c_str());
        strcpy(&ccD[0], dirS.c_str());
        //pc.printf("<%s>", ccD);
        dirOpenHmi(ccD);
        // clean directory
        for(int i =indName; i<40; i++) {
           strcpy(&dirName[indName++][0], "  ");
        }
            
    }    
}

void txtBoxNPadd(int i) {
    if(i < 10) {
        NPinp =10 * NPinp + i;
        if(NPinp > miMa[LabelsIndex].max) {NPinp = miMa[LabelsIndex].max;}
        
        lcd.fillroundrect(txtBNP.x1, txtBNP.y1, txtBNP.x2, txtBNP.y2, txtBNP.r1, txtBNP.r2, txtBNP.color);
        lcd.foreground(txtBNP.textColor);
        lcd.background(txtBNP.color);
        sprintf(txtBNP.text, "%i", NPinp);
        lcd.puts(txtBNP.textX, txtBNP.textY, txtBNP.text);
        flagNPinp = true;
    }    
    if(i == 11) {
        lcd.fillroundrect(txtBNP.x1, txtBNP.y1, txtBNP.x2, txtBNP.y2, txtBNP.r1, txtBNP.r2, txtBNP.color);
        lcd.foreground(txtBNP.textColor);
        lcd.background(txtBNP.color);
        NPinp = NPinp / 10;
        if(NPinp == 0) {
            lcd.puts(txtBNP.textX, txtBNP.textY, "");
            flagNPinp = false;
        }
        else {
            sprintf(txtBNP.text, "%i", NPinp);
            lcd.puts(txtBNP.textX, txtBNP.textY, txtBNP.text);
        }
    }    
    if(i == 12) {
        if(TPmode == 1) {
            if(flagNPinp == true) {
                if(NPinp < miMa[LabelsIndex].min) {NPinp = miMa[LabelsIndex].min;}
                switch (LabelsIndex) {
                    case 0: {prPar[progNumber].LPbeg = NPinp; break;}
                    case 1: {prPar[progNumber].LPend = NPinp; break;}
                    case 3: {prPar[progNumber].Lfreq = NPinp; break;}
                    case 4: {prPar[progNumber].Lpulse = NPinp; break;}
                    case 5: {prPar[progNumber].amplBeg = NPinp; break;}
                    case 6: {prPar[progNumber].amplEnd = NPinp; break;}
                    case 7: {prPar[progNumber].wFreq = NPinp; break;}
                    case 8: {prPar[progNumber].wTime = NPinp; break;}
                    case 9: {prPar[progNumber].amplNum = NPinp; break;}
                }
                sprintf(txtBoxR[LabelsIndex].text, "%i", NPinp);
            }    
            showVal(progNumber);
            LPscreen = 0;   //value screen
            flagParChanged = 0;    
        }    
        else if(TPmode == 2) {
            if(flagNPinp == true) {
                if(NPinp < miMa[LabelsIndex].min) {NPinp = miMa[LabelsIndex].min;}
                switch (LabelsIndex) {
                    case 10: {fileNum = NPinp; break;}
                }
                sprintf(txtRServ[4].text, "%i", NPinp);
            }    
            showService();
            LPscreen = 2;   //service screen
            
        }    
    }    
}
    
void testTP(void) {
    TouchCode_t touch;
    
    touch = lcd.TouchPanelReadable();         // any touch to report?
    if (touch) {
        uint8_t id = lcd.TouchID();           // 'id' tracks the individual touches
        TouchCode_t ev = lcd.TouchCode();     // 'ev'ent 0-no_touch,1-touch,2-held,3-release,4-no_cal
        point_t xy = lcd.TouchCoordinates();  // and of course the (x,y) coordinates

        pc.printf("%2d,%d:(%4d,%4d)\n", id, ev, xy.x, xy.y);
        int lastRadius, newRadius;
        lastRadius = ComputeRadius(lastTP);           // To erase the last fingerprint
        newRadius = ComputeRadius(xy);                  // Shrink near edge of screen
        lcd.circle(xy, newRadius, Red); // draw new fingerprint
        lcd.circle(lastTP, lastRadius, Black);    // erase old fingerprint
        lastTP = xy;

        led2 = 1;
        wait_ms(100);
        led2 = 0;
    }
}

void checkTP(void) {
    TouchCode_t touch;
    
    touch = lcd.TouchPanelReadable();         // any touch to report?
    //pc.printf("TP\n");
    if (touch) {
        uint8_t id = lcd.TouchID();           // 'id' tracks the individual touches
        TouchCode_t ev = lcd.TouchCode();     // 'ev'ent 0-no_touch,1-touch,2-held,3-release,4-no_cal
        point_t xy = lcd.TouchCoordinates();  // and of course the (x,y) coordinates

        //printf("(%4d,%4d)\n", xy.x, xy.y);
        pc.printf("%d,%d:(%4d,%4d)\n", TPmode, LPscreen, xy.x, xy.y);

        if(LPscreen == 0) {     //value screen 
            //8 program#
            for(int i = 0; i < TextBoxSize; i++) {
                if((xy.x > txtBox[i].x1)&(xy.x < txtBox[i].x2)&(xy.y > txtBox[i].y1)&(xy.y < txtBox[i].y2)) {
                    pc.printf("%i\n", i);
                    if(i<8) {showProgParam(i); flagParChanged = 0; goto checkTPend;}
                    else {if(editBtnMode == 1) {showWobParam(i-8); flagParChanged = 0; goto checkTPend;}}  //edit mode, 3 wob.mode      
                }    
            }
            // text boxes
            if(editBtnMode == 1) {
                for(int i = 0; i < numPrPar; i++) {
                    if((xy.x > txtBoxR[i].x1)&(xy.x < txtBoxR[i].x2)&(xy.y > txtBoxR[i].y1)&(xy.y < txtBoxR[i].y2)) {
                        pc.printf("%i\n", i);
                        if(i == numLmode) {
                            lcd.fillroundrect(txtBoxR[i].x1, txtBoxR[i].y1, txtBoxR[i].x2, txtBoxR[i].y2, txtBoxR[i].r1, txtBoxR[i].r2, txtBoxR[i].color);
                            lcd.foreground(txtBoxR[i].textColor);
                            lcd.background(txtBoxR[i].color);
                            if(Lmode == 0) {
                                Lmode = 1;
                                prPar[progNumber].Lmode = 1;
                                lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "PULSE");
                                if(SetLasComm(32) == 1) {TPstatus = 5;}       //EPM -enable pulse mode
                                else {
                                    if(SetLasComm( 1) == 1) {TPstatus = 5;}   //STA -read laser status
                                    else TPstatus = 0; 
                                }
                            }
                            else {
                                Lmode = 0;
                                prPar[progNumber].Lmode = 0;
                                lcd.puts(txtBoxR[i].textX, txtBoxR[i].textY, "CW");
                                if(SetLasComm(33) == 1) {TPstatus = 5;}       //DPM -disable pulse mode
                                else {
                                    if(SetLasComm( 1) == 1) {TPstatus = 5;}   //STA -read laser status
                                    else TPstatus = 0; 
                                }
                            }
                            flagParChanged = 0;
                        }
                        else {    
                            showNP(i);
                            LabelsIndex = i;
                            NPinp = 0;
                            flagNPinp = false;
                            LPscreen = 1;   //LP screen
                        }
                        goto checkTPend;
                    }    
                }
            }
            //btn Edit
            if((xy.x > txtBoxR[numTPeditBtn].x1)&(xy.x < txtBoxR[numTPeditBtn].x2)&(xy.y > txtBoxR[numTPeditBtn].y1)&(xy.y < txtBoxR[numTPeditBtn].y2)) {
                if(TPmode == 1) {
                    showTPeditBtn(0);  //set operate mode
                    TPmode = 0; 
                    editBtnMode = 0;               
                }
                else {
                    showTPeditBtn(1);  //set edit mode
                    TPmode = 1;                
                    editBtnMode = 1;               
               }
                goto checkTPend;            
            }    
            //btn Main
            if((xy.x > txtBoxR[numTPmainBtn].x1)&(xy.x < txtBoxR[numTPmainBtn].x2)&(xy.y > txtBoxR[numTPmainBtn].y1)&(xy.y < txtBoxR[numTPmainBtn].y2)) {
                pc.printf("MainBtn");
                
                showMain(progNumber);
                TPmode = 0;
                LPscreen = 3;                
            }    
            //status line
            if((xy.x > txtBoxR[numTPstatus].x1)&(xy.x < txtBoxR[numTPstatus].x2)&(xy.y > txtBoxR[numTPstatus].y1)&(xy.y < txtBoxR[numTPstatus].y2)) {
                showTPstatus(10);   //clean status line
            }    
            goto checkTPend;            
        }
        else if(LPscreen == 1) {   //numpad screen
            if(xy.x < txtBoxNP[1].x1) { //touch left from form
                showVal(progNumber);
                LPscreen = 0;   //values screen
                pc.printf("<<");
                goto checkTPend;
            }    
            //btn 0..9, ok, back
            for(int i = 0; i < 13; i++) {
                if((xy.x > txtBoxNP[i].x1)&(xy.x < txtBoxNP[i].x2)&(xy.y > txtBoxNP[i].y1)&(xy.y < txtBoxNP[i].y2)) {
                    pc.printf("%i\n", i);
                    txtBoxNPadd(i);
                    goto checkTPend;
                }    
            }
        
        }
        else if(LPscreen == 2) {     //service screen 
            for(int i = 0; i < txtRServSize; i++) {
                if((xy.x > txtRServ[i].x1)&(xy.x < txtRServ[i].x2)&(xy.y > txtRServ[i].y1)&(xy.y < txtRServ[i].y2)) {
                    btnServ(i);
                    break;
                }    
            }
            if(flagDirOpen != 0) {
                for(int i = 0; i < txtRdirSize; i++) {
                    if((xy.x > txtRdir[i].x1)&&(xy.x < txtRdir[i].x2)&&(xy.y > txtRdir[i].y1)&&(xy.y < txtRdir[i].y2)) {
                        btnDir(i);
                        break;
                    }    
                }
                for(int i = 0; i < TextBoxDirSize; i++) {
                    if((xy.x > txtBoxDir[i].x1)&&(xy.x < txtBoxDir[i].x2)&&(xy.y > txtBoxDir[i].y1)&&(xy.y < txtBoxDir[i].y2)) {
                        btnDirText(i);
                        break;
                    }    
                }
            }
        }
        else if(LPscreen == 3) {     //main screen
            //8 program#
            for(int i = 0; i < TextBoxSize; i++) {
                if((xy.x > txtBox[i].x1)&(xy.x < txtBox[i].x2)&(xy.y > txtBox[i].y1)&(xy.y < txtBox[i].y2)) {
                    pc.printf("%i\n", i);
                    if(i<8) {showProgNum(i); flagParChanged = 0; goto checkTPend;}
                }    
            }
            //btn Values
            if((xy.x > txtBoxR[numTPvalBtn].x1)&(xy.x < txtBoxR[numTPvalBtn].x2)&(xy.y > txtBoxR[numTPvalBtn].y1)&(xy.y < txtBoxR[numTPvalBtn].y2)) {
                pc.printf("ValuesBtn");
                
                showVal(progNumber);
                TPmode = 0;
                LPscreen = 0;                
            }    
            //btn Service
            if((xy.x > txtBoxR[numTPservBtn].x1)&(xy.x < txtBoxR[numTPservBtn].x2)&(xy.y > txtBoxR[numTPservBtn].y1)&(xy.y < txtBoxR[numTPservBtn].y2)) {
                pc.printf("ServiceBtn");
                
                showService();
                TPmode = 2;
                LPscreen = 2;                
            }    
            //status line
            if((xy.x > txtBoxR[numTPstatus].x1)&(xy.x < txtBoxR[numTPstatus].x2)&(xy.y > txtBoxR[numTPstatus].y1)&(xy.y < txtBoxR[numTPstatus].y2)) {
                showTPstatus(10);   //clean status line
            }    
        }
 checkTPend:       
        led2 = 1;
        wait_ms(100);
        led2 = 0;
        
        while(touch) {
            touch = lcd.TouchPanelReadable();         // any touch to report?
            wait_ms(1);
        }
    }
}
//ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    
void LasCommInit(void) {
    if(LPscreen == 2) statServErr(10);    //service screen, status " "
    else showTPstatus(10);                // main screen, status " "
    
    if(SetLasComm(52) == 1) {c7=52; goto met1;}    //RERR -Resets any resettable errors 
    if(SetLasComm(54) == 1) {c7=54; goto met1;}    //EMOFF -Stop Emission
    if(SetLasComm(41) == 1) {c7=41; goto met1;}    //DMOD -disable external modulation input
    if(SetLasComm(47) == 1) {c7=47; goto met1;}    //DEABC -disable external aiming beam control input
    if(SetLasComm(34) == 1) {c7=34; goto met1;}    //ABN -aiming beam on
    //if(SetLasComm(35) == 1) {c7=35; goto met1;}    //ABF -aiming beam off
    //if(SetLasComm(46) == 1) {c7=46; goto met1;}    //EEABC -enable external aiming beam control input
    if(SetLasComm(39) == 1) {c7=39; goto met1;}    //DGM -disable gate mode
    if(SetLasComm(36) == 1) {c7=36; goto met1;}    //EEC -enable external analog power control input
    if(SetLasComm(40) == 1) {c7=40; goto met1;}    //EMOD -enable external modulation input
    if(SetLasComm(42) == 1) {c7=42; goto met1;}    //ELE -enable external emission input
    if(SetLasComm( 1) == 1) {c7=1; goto met1;}    //STA -read laser status 
    c7 = 99;   
    if(LPscreen == 2) statServErr(0);    //service screen, status READY
    else showTPstatus(0);                // main screen, status READY
    return;
    
met1:
    if(LPscreen == 2) statServErr(5);    //service screen
    else showTPstatus(5);                // main screen
}  

void initIOparam(void) {
    for(int i=0; i<4; i++) {
        ioPar.o3[i] = '\0';
        ioPar.o2[i] = '\0';
        ioPar.o1[i] = '\0';
        ioPar.i3[i] = '\0';
        ioPar.i2[i] = '\0';
        ioPar.i1[i] = '\0';
        ioPar.aiLPow[i] = '\0';
        ioPar.aiLCur[i] = '\0';
        ioPar.aiLTemp[i] = '\0';
        ioPar.aiLBR[i] = '\0';
    }
}

uint8_t bitOstate = 0x80; //d7=1 need set/reset, d6=1-set,0-reset, d5-d0 bit number
uint8_t ioReq = 0;        //0-no request, 1-inp.request, 2-out.request
     
//============================================================================== 
int main()
{
    a7=0;
    b7=0;
    c7=0;
    
    //Configure CRC, large frames, and write validation
    sd.crc(true);
    sd.large_frames(true);
    sd.write_validation(true);
    
    pc.baud(PC_BAUD);    //
    
    pc.printf("\nRA8875 Touch Screen. Date: " __DATE__ " " __TIME__ "\r\n");
    //wait_ms(5000);
    //pc.printf("\n>>\n");
    //wait_ms(5000);
    
    initHMIio();
    initIOparam();
    
    lcd800x480Init();
    //showMain(progNumber+1);
    tickRS.attach_us(&flipUS, tickTime); // the address of the function to be attached (flip) to ticker

    wait_ms(5000);
    LasCommInit();
    
    fillTestBuffer();
    if(connectSD() == 0) {
        infoSD();
        //writeTestFile();
        readTestFile();
        
        readDirSD(rDr);
        
        //RetCode_t r = lcd.RenderImageFile(0, 0, "/sd/local/48027208.bmp");
        //printf("returned %d\r\n", r);
        //wait(3);
        //r = lcd.RenderJpegFile(0, 0, "/sd/local/p480272.jpg");
        //printf("returned %d\r\n", r);
      
        disconnectSD();
    }
    pc.printf("a7=%i b7=%i c7=%i d7=%i\n", a7, b7, c7, d7);
    
    InitTS();
    readIniFile();       
    showMain(progNumber);
    //int x, y, z;
    
    while(true)
    {
        //testTP();
        if(flagWeld == 0) checkTP();
        
        main_cycle_add();
        
        iLed++;
        if(iLed > 500) {
            led1 = !led1;
            iLed = 0;
        }    
        wait_ms(1);
    }
}