#include "tslib.h"
#include <QThread>

//tslib::tslib()
//{


//}


/*
uint16_t tslib::uchar2uint(uint8_t Highbyte, uint8_t Lowbyte)
{
    uint16_t uitmp;
    uitmp=0;
    uitmp |= uint8_t(Highbyte);
    uitmp<<=8;
    uitmp |= uint8_t(Lowbyte);
    return uitmp;
}

uint8_t tslib::uint2uchar(uint16_t uival, bool getHighB)
{
    // getHighB: low=GetLowByte
    uint16_t uitmp=uival;
    if (getHighB==0)
        return uint8_t(uitmp);
    uitmp>>=8;
    return uint8_t(uitmp);

}*/

uint16_t uchar2uint(char Highbyte, char Lowbyte)
{
    uint16_t uitmp;
    uitmp=0;
    uitmp |= uint8_t(Highbyte);
    uitmp<<=8;
    uitmp |= uint8_t(Lowbyte);
    return uitmp;
}

uint16_t uchar2uint(uint8_t Highbyte, uint8_t Lowbyte)
{
    uint16_t uitmp;
    uitmp=0;
    uitmp |= uint8_t(Highbyte);
    uitmp<<=8;
    uitmp |= uint8_t(Lowbyte);
    return uitmp;
}

uint32_t uchar2ulong(uint8_t Highbyte, uint8_t MHbyte, uint8_t MLbyte, uint8_t Lowbyte)
{
    uint32_t ultmp=0;

    ultmp |= uint8_t(Highbyte);
    ultmp<<=8;
    ultmp |= uint8_t(MHbyte);
    ultmp<<=8;
    ultmp |= uint8_t(MLbyte);
    ultmp<<=8;
    ultmp |= uint8_t(Lowbyte);
    return ultmp;
}

uint8_t uint2uchar(uint16_t uival, bool getHighB)
{
    // getHighB: low=GetLowByte
    uint16_t uitmp=uival;
    if (getHighB==0)
        return uint8_t(uitmp);
    uitmp>>=8;
    return uint8_t(uitmp);

}


uint8_t ulong2uchar(uint32_t ulval, uint8_t getBytNr)
{
    // getBytNr: 0=LSB  3=MSB
    uint32_t ultmp=ulval;
    if (getBytNr==0)
        return uint8_t(ultmp);
    ultmp>>=8;
    if (getBytNr==1)
        return uint8_t(ultmp);
    ultmp>>=8;
    if (getBytNr==2)
        return uint8_t(ultmp);
    ultmp>>=8;
    return uint8_t(ultmp);

}

void delay(uint16_t MilliSec)
{
    QThread::msleep(uint32_t(MilliSec));
}


void GetTimeString(uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t System12h, uint8_t ShowSec, uint8_t *buf)
{
	// Zahlenwerte in String wandeln, 12/24h-Format     // 12byte für buf!
	uint8_t usa;
	uint16_t  jj;
	uint8_t hh, mm, ss, with_sec;

        // buf[0]= ganz linkes Zeichen
    hh=hours;
    mm=minutes;
    ss=seconds;

    // 15.10.12, Plausibilitätsprüfung --------------------------------------------------
    if (hh>23) hh=0;
    if (mm>59) mm=0;
    if (ss>59) ss=0;

    with_sec=ShowSec;
        for (jj=0; jj<12; jj++) buf[jj]=0;
        usa = System12h; 		// 1:12h   0:24h

    // Stunden:
        if (usa)
    {
        // 12h System
        if (hh==0 || hh==12)
        {
            // 12AM (Mitternacht) oder 12PM (Mittag)
                buf[0]=0x31;
                buf[1]=0x32;
        } else
        if (hh<12)
        {
            // 1..11AM
                buf[0]=hh/10+0x30;
                buf[1]=hh%10+0x30;
        } else
        {
            //13:00 bis 23Uhr
                buf[0]=(hh-12)/10+0x30;
                buf[1]=(hh-12)%10+0x30;
        }
    } else
    {
        // 24h System
        buf[0]=hh/10+0x30;
        buf[1]=hh%10+0x30;
    }

    // Minuten:
    buf[2]=':';
    buf[3]=mm/10+0x30;
    buf[4]=mm%10+0x30;

    jj=5;
    if (with_sec)
    {
        buf[jj++]=':';
        buf[jj++]=ss/10+0x30;
        buf[jj++]=ss%10+0x30;
    }
    if (usa)
    {
        buf[jj++]=' ';
        if (hh<12)
            buf[jj++]='A';
        else
            buf[jj++]='P';
        buf[jj++]='M';
    }

}

// -------------------    ********************************************************************************

void GetDateString(uint8_t day, uint8_t month, uint8_t yearhigh, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf)
{
	// generate date as ascii string from integers day/month/year
	// yearhigh: 10..29, in europe always 20 (not in arabia!) comes as hex number, e.g. 0x20
	// format=  0: dd.mm.yyyy   (deutsch)
	//          1: mm.dd.yyyy   (amerika)
    //          2: yyyy.mm.dd   (Iran, Dubai)
    //          3: dd.yyyy.mm
    //          4: mm.yyyy.dd
    //          5: yyyy.dd.mm
        // sep: 0: use . as seperator   1: use / as seperator
    // return String in *buf      // 11byte für buf!


	uint8_t tag, mon, jahr, d10, d1, m10, m1, y1000, y100, y10, y1;
	uint8_t slash;


    y100= (yearhigh & 0x0F)+0x30;
    y1000=((yearhigh & 0xF0)>>4)+0x30;
//    if (yearhigh>=20)
//    {
//    	y1000='2';
//        y100=28+yearhigh;   // '0' + (yearhigh-20)
//    } else
//    if (yearhigh<20)
//    {
//        y1000='1';
//        y100=38-yearhigh;   // '9' - (19-yearhigh)
//    }

    tag=day;
    mon=month;
    jahr=yearlow;

    if (mon>12 || mon==0) mon=1;           // 23.10.12
    if (tag>31 || tag==0) tag=1;
    if (jahr>50 || jahr<11) jahr=1;

    if (sep==0)
        slash='.';          // slash==0
    else if (sep==1)
        slash='/';
    else
    if  (sep>=0x20)
        slash=sep;
    else
        slash='.';

    d10 =tag/10;
    d1  =tag%10;
    m10 =mon/10;
    m1  =mon%10;
    y10 =jahr/10;
    y1  =jahr%10;

	d10 +=0x30;    // in Asccii wandeln
	d1  +=0x30;
	m10 +=0x30;
	m1  +=0x30;
	y10 +=0x30;
    y1  +=0x30;

	switch (format)
	{
		    // 0: dd.mm.yyyy
	    case 0: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=m10; buf[4]=m1; buf[5]=slash;
		    buf[6]=y1000; buf[7]=y100; buf[8]=y10; buf[9]=y1; break;

		    // 1: mm.dd.yyyy
	    case 1: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=d10; buf[4]=d1; buf[5]=slash;
		    buf[6]=y1000; buf[7]=y100; buf[8]=y10; buf[9]=y1; break;

		// 2: yyyy.mm.dd
	    case 2: buf[0]=y1000; buf[1]=y100; buf[2]=y10; buf[3]=y1; buf[4]=slash; buf[5]=m10;
		    buf[6]=m1; buf[7]=slash; buf[8]=d10; buf[9]=d1; break;

		// 3: dd.yyyy.mm
	    case 3: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=y1000; buf[4]=y100;
		    buf[5]=y10; buf[6]=y1; buf[7]=slash; buf[8]=m10; buf[9]=m1; break;

		// 4: mm.yyyy.dd
	    case 4: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=y1000; buf[4]=y100;
		    buf[5]=y10; buf[6]=y1; buf[7]=slash; buf[8]=d10; buf[9]=d1; break;

		// 5: yyyy.dd.mm
	    case 5: buf[0]=y1000; buf[1]=y100; buf[2]=y10; buf[3]=y1; buf[4]=slash; buf[5]=d10;
		    buf[6]=d1; buf[7]=slash; buf[8]=m10; buf[9]=m1; break;

	}
	buf[10]=0;


}

// -------------------    ********************************************************************************

void GetShortDateString(uint8_t day, uint8_t month, uint8_t yearlow, uint8_t format, uint8_t sep, uint8_t *buf)
{
	// generate date as ascii string from integers day/month/year
	// format=  0: dd.mm.yy   (deutsch)
	//          1: mm.dd.yy   (amerika)
    //          2: yy.mm.dd   (Iran, Dubai)
    //          3: dd.yy.mm
    //          4: mm.yy.dd
    //          5: yy.dd.mm
        // sep: 0: use . as seperator   1: use / as seperator
    // return String in *buf      // 11byte für buf!


	uint8_t tag, mon, jahr, d10, d1, m10, m1, y10, y1;
	uint8_t slash;


    tag=day;
    mon=month;
    jahr=yearlow;

    if (mon>12 || mon==0) mon=1;           // 23.10.12
    if (tag>31 || tag==0) tag=1;
    if (jahr>50 || jahr<11) jahr=1;

    if (sep==0)
        slash='.';          // slash==0
    else if (sep==1)
        slash='/';
    else if  (sep>=0x20)
        slash=sep;
    else
        slash='.';

    d10 =tag/10;
    d1  =tag%10;
    m10 =mon/10;
    m1  =mon%10;
    y10 =jahr/10;
    y1  =jahr%10;

	d10 +=0x30;    // in Asccii wandeln
	d1  +=0x30;
	m10 +=0x30;
	m1  +=0x30;
	y10 +=0x30;
    y1  +=0x30;

	switch (format)
	{
		    // 0: dd.mm.yyyy
	    case 0: buf[0]=d10; buf[1]=d1; buf[2]=slash; buf[3]=m10; buf[4]=m1; buf[5]=slash;
		    buf[6]=y10; buf[7]=y1; break;

		    // 1: mm.dd.yyyy
	    case 1: buf[0]=m10; buf[1]=m1; buf[2]=slash; buf[3]=d10; buf[4]=d1; buf[5]=slash;
		    buf[6]=y10; buf[7]=y1; break;

		// 2: yyyy.mm.dd
	    case 2: buf[0]=y10; buf[1]=y1; buf[2]=slash; buf[3]=m10;
		    buf[4]=m1; buf[5]=slash; buf[6]=d10; buf[7]=d1; break;

		// 3: dd.yyyy.mm
	    case 3: buf[0]=d10; buf[1]=d1; buf[2]=slash;
		    buf[3]=y10; buf[4]=y1; buf[5]=slash; buf[6]=m10; buf[7]=m1; break;

		// 4: mm.yyyy.dd
	    case 4: buf[0]=m10; buf[1]=m1; buf[2]=slash;
		    buf[3]=y10; buf[4]=y1; buf[5]=slash; buf[6]=d10; buf[7]=d1; break;

		// 5: yyyy.dd.mm
	    case 5: buf[0]=y10; buf[1]=y1; buf[2]=slash; buf[3]=d10;
		    buf[4]=d1; buf[5]=slash; buf[6]=m10; buf[7]=m1; break;

	}
	buf[8]=0;


}

uint16_t tslib_strlen(char *buf)
{
    uint16_t nn;

    for (nn=0; nn<0xFFF0; nn++)
        if (buf[nn]==0)
            return nn;
    return 0;
}

uint16_t tslib_strlen(uint8_t *buf)
{
    uint16_t nn;

    for (nn=0; nn<0xFFF0; nn++)
        if (buf[nn]==0)
            return nn;
    return 0;
}

void tslib_strclr(char *buf, char clrsign, uint16_t len)
{
    uint16_t nn;

    for (nn=0; nn<len; nn++)
        buf[nn]=clrsign;

}

void tslib_strclr(uint8_t *buf, char clrsign, uint16_t len)
{
    uint16_t nn;

    for (nn=0; nn<len; nn++)
        buf[nn]=uint8_t (clrsign);

}


void tslib_strcpy(char *srcbuf, char *destbuf, uint16_t len)
{
    uint16_t nn;

    for (nn=0; nn<len; nn++)
        destbuf[nn]=srcbuf[nn];

}

void tslib_strcpy(char *srcbuf, uint8_t *destbuf, uint16_t len)
{
    uint16_t nn;

    for (nn=0; nn<len; nn++)
        destbuf[nn]=uint8_t(srcbuf[nn]);

}

void tslib_strcpy(uint8_t *srcbuf, uint8_t *destbuf, uint16_t len)
{
    uint16_t nn;

    for (nn=0; nn<len; nn++)
        destbuf[nn]=srcbuf[nn];

}

bool tslib_isDecAsciiNumber(char sign)
{
    if (sign>=0x30 && sign<=0x39)
        return true;
    return false;
}

bool tslib_isHexAsciiNumber(char sign)
{
    if (sign>=0x30 && sign<=0x39)
        return true;
    if (sign>=0x61 && sign<=0x66)   // a...f
        return true;
    if (sign>=0x41 && sign<=0x46)   // A...F
        return true;
    return false;
}

int tslib_getMinimum(int val1, int val2)
{
    if (val1<val2)
        return val1;
    return val2;
}



void tslib_text2array(QByteArray text, char *aray, uint16_t maxArayLen)
{
    QByteArray  sloc;
    int ii, LL=text.length();

    if (LL>maxArayLen) LL=maxArayLen;
    for (ii=0; ii<LL; ii++)
    {
        aray[ii]=text.at(ii);
    }
    if (LL==maxArayLen)
        aray[LL-1]=0;
    else
        aray[LL]=0;
}


// -----------------------------------------------------------------------------------------------
// functions for DeviceController's Bootloader ---------------------------------------------------
// -----------------------------------------------------------------------------------------------
/*
uint16_t tslib_calcCrcCcitt(uint16_t BufLength, uint8_t *buf)
{
    uint8_t  nn, B15H, element;
    uint16_t crc = 0x84cf;

    while (BufLength--)
    {
        element = *buf++;
        for (nn = 0; nn < 8; nn++)
        {
            B15H = 0;
            if(crc & 0x8000)
                B15H = 1;
            crc = (crc << 1) | ((element >> (7 - nn)) & 0x01);
            if (B15H)
            {
                crc ^= 0x1021;
            }
        }
    }

    for (nn = 0; nn < 16; nn++)
    {
        B15H = 0;
        if(crc & 0x8000)
        B15H = 1;
        crc = (crc << 1) | 0x00;
        if (B15H)
        {
            crc ^= 0x1021;
        }
    }
    return crc;

}

static uint8_t LastBLcmd;   // stored the last sent cmd in order to analys response
                            // cmd echo'ed: error       cmd or'ed with 0x80: OK

uint8_t tslib_prepareDC_BLcmd(uint8_t Cmd, uint8_t SendDataLength, uint8_t *sendData, uint8_t *outBuf)
{
    // make BL protocol, retval = outbuf length (5...133)
    // bring data in correct form: start always with 0x02   finish with 0x03 and append checksum
    // 0x02 Cmd < ...sendData ..>  CRC  CRC 0x03
    // Data length = 0...64
    // special conversion: if data contain 2 or 3 (STX, ETX) then write two bytes:  0x1B (=ESC) and data|0x80
    // so maxlength = 5 + 2 x 64 (if all data are 2 or 3)  without 2,3: maxlength = 5 + 64

    uint8_t  myBuf[140], pp=0, nn, uctmp, currLen=0;
    uint16_t calcCrc;

    tslib_strclr(myBuf, 0, 140);

    myBuf[pp++]=2;    // STX
    myBuf[pp++]=Cmd;
    LastBLcmd=Cmd;

    // append data:
    for (nn=0; nn<SendDataLength; nn++)
    {
        uctmp=sendData[nn];
        if (uctmp==2 || uctmp==3)       // STX or ETX in normal data!
        {
            myBuf[pp++]=0x1B;       // ESC
            myBuf[pp++]=uctmp | 0x80;
        } else
            myBuf[pp++]=uctmp;
    }
    currLen=pp;

    // calc crc: (over cmd and data, without STX)
    calcCrc=tslib_calcCrcCcitt(uint16_t(currLen), myBuf);
    myBuf[pp++]=uint8_t(calcCrc & 0x00FF);
    myBuf[pp++]=uint8_t((calcCrc>>8) & 0x00FF);
    myBuf[pp++]=3;
    currLen=pp;

    return currLen;
}

// some special commands (right out of bootloader manual)
uint8_t tslib_readBLversion(uint8_t *sendData)
{
    // minimum size of sendData-buffer: 5byte  retval: length
    uint8_t myBuf[2];
    tslib_strclr(myBuf, 0, 2);
    return tslib_prepareDC_BLcmd(0x11, 0, myBuf, sendData);
}

uint8_t tslib_readFWversion(uint8_t *sendData)
{
    // minimum size of sendData-buffer: 5byte  retval: length
    uint8_t myBuf[2];
    tslib_strclr(myBuf, 0, 2);
    return tslib_prepareDC_BLcmd(0x12, 0, myBuf, sendData);
}

uint8_t tslib_exitBL(uint8_t *sendData)
{
    // minimum size of sendData-buffer: 5byte  retval: length
    uint8_t myBuf[2];
    tslib_strclr(myBuf, 0, 2);
    return tslib_prepareDC_BLcmd(0x18, 0, myBuf, sendData);
}

uint8_t tslib_sendFlashStartAddr2BL(uint32_t startAddr, uint8_t *sendData)
{
    // minimum size of sendData-buffer: 13byte    retval: length (9...13)
    uint8_t myBuf[2];
    tslib_strclr(myBuf, 0, 2);
    return tslib_prepareDC_BLcmd(0x11, 0, myBuf, sendData);
}
*/

// -----------------------------------------------------------------------------------------------


void biox_CopyBlock(uint8_t *src, uint16_t srcPos, uint8_t *dest, uint16_t destPos, uint16_t len)
{
    // both buffers starting from pos 0
    uint16_t xx,yy,zz,ii;

    xx = srcPos;
    yy = destPos;
    zz = len;

    for (ii = 0; ii < zz; ++ii)
    {
        dest[yy + ii] = src[xx + ii];
    }
}


bool tslib_strComp(uint8_t *buf, char *compStr)
{
    uint16_t strLen=tslib_strlen(compStr), pp;

    for (pp=0; pp<strLen; pp++)
    {
        if (buf[pp] != compStr[pp])
            return false;
    }
    return true;
}