#ifndef MAINETHREAD_H
#define MAINETHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
class mainEthread : public QThread
{
    Q_OBJECT
public:
    mainEthread();
    ~mainEthread();
    void run();
    void transaction(const QString &request);
    void reaseive1(const QString &baudrate, const QString &checkCode,const QString &checklen);
    void openserial();
    void check(const QString &s);
    bool CRC(const QString &s1,const QString &s2);
    unsigned char crc8(unsigned char *ptr,unsigned int len, unsigned char check_code);
    unsigned int  crc16(unsigned char *ptr,unsigned int len, unsigned int check_code);
    unsigned long int crc32(unsigned char *ptr,unsigned int len, unsigned long int check_code);
    bool ASCIItoCHAR(QByteArray GET_DATA1,unsigned  int GET_DATA_len);
    unsigned char ASCIItoCHAR8(QByteArray GET_DATA1, unsigned int GET_DATA_len);
    unsigned int  ASCIItoCHAR16(QByteArray GET_DATA1, unsigned int GET_DATA_len);
    unsigned long int ASCIItoCHAR32(QByteArray GET_DATA1, unsigned int GET_DATA_len);
    void CHECK_SET();
signals:
    void response();
    void responsedata(const QString &s1, const QString &s2);
    void responserror();
private slots:
    void stopserial();
private:
    QString request;
    QString baudrate;
    QString checkCode;
    QString checklen;
    int DATA_LEN;
    QMutex mutex;
    QWaitCondition cond;
    bool quit;
    bool ok;
    int long1;
    QString response2;
    unsigned char char_8;
    unsigned int int_16;
    unsigned long int long_32;
};

#endif // MAINETHREAD_H



#ifndef MAINWINDOWS_H
#define MAINWINDOWS_H
#include <QtWidgets/QWidget>
#include <QtWidgets/QTextBrowser>
#include <QtWidgets/QLCDNumber>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGridLayout>
#include <mainethread.h>
#include <QTimer>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QRadioButton>

class MainWindows : public QWidget
{
    Q_OBJECT
public:
    MainWindows();
    ~MainWindows();
    void setbaudrate();
    void Edit_SET();
    void CHECKCODE_CHOSE();
private:
    QLabel *label1;
    QLabel *label2;
    QLabel *label4;
    QLabel *label5;
    QLabel *label6;
    QLabel *label7;
    QLabel *label8;
    QLabel *label9;
    QLabel *label10;
    QLabel *label11;
    QLabel *CHECK_8;
    QLabel *CHECK_16;
    QLabel *CHECK_32;
    QLabel *DATA_LENGTH;
    QLineEdit *edit1;
    QLineEdit *edit_8;
    QLineEdit *edit_16;
    QLineEdit *edit_32;
    QLineEdit *edit_length;
    QTextBrowser *browser1;
    QTextBrowser *browser4;
    QTextBrowser *browser2;
    QTextBrowser *browser3;
    QLCDNumber *lcd1;
    QPushButton *button1;
    QPushButton *button2;
    QPushButton *button3;
    QPushButton *button4;
    QRadioButton *CHECK8;
    QRadioButton *CHECK16;
    QRadioButton *CHECK32;
    mainEthread *thread;
    QComboBox *baudrateCombox;
    QGridLayout *layout1;
    long int num1;
    long int num2;
private slots:
    void transaction();
    void send1();
    void showResponse();
    void showdata(const QString &s1, const QString &s2);
    void clearwindows();
    void showerror();
};

#endif // MAINWINDOWS_H



#include <mainwindows.h>
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc,argv);
    MainWindows w;
    w.show();
    return a.exec();
}



#include "mainethread.h"
#include <QtSerialPort/QSerialPort>

mainEthread::mainEthread()
{
    long1 = 0;
    quit=false;
}
void mainEthread::transaction(const QString &request)
{
    quit=false;
    QMutexLocker locker(&mutex);
    this->request = request;
    if (!isRunning())
        start();
    else
        cond.wakeOne();
}

//接收波特率和校验码
void mainEthread::reaseive1(const QString &baudrate, const QString &checkCode,const QString &checklen)
{
    QMutexLocker locker(&mutex);
    this->baudrate = baudrate;
    this->checkCode = checkCode;
    this->checklen = checklen;
    DATA_LEN = this->checklen.toInt(&ok,10);
    qDebug()<<DATA_LEN;
    if (!isRunning())
        start();
    else
        cond.wakeOne();
}

void mainEthread::stopserial()
{
    quit = true;
}

//打开串口并接受数据
void mainEthread::openserial()
{
    QSerialPort serial;
    serial.setPortName("/dev/ttyS1");
    while(!quit){
      serial.open(QIODevice::ReadWrite);
      qint32 baudrate_set = (qint32)115200;
      serial.setBaudRate(baudrate_set);
      serial.setDataBits(QSerialPort::Data8);
      serial.setParity(QSerialPort::NoParity);
      serial.setStopBits(QSerialPort::OneStop);
      serial.setFlowControl(QSerialPort::NoFlowControl);
      while(long1<DATA_LEN){
        if(serial.waitForReadyRead(10)){
           QByteArray responseData = serial.readAll();
           QByteArray ss =responseData.toHex();
           QString response1(ss);
           response2.append(response1);
           long1 = response2.size();
        }
      }
      CHECK_SET();
      while(long1>=DATA_LEN)
      {
          if(response2.startsWith("5a")&&long1>=DATA_LEN)
          {
              response2.remove(0,2);
              QString cstring;
              int CUTLEN = DATA_LEN-2;
              cstring = response2.mid(0,CUTLEN);
              QByteArray ASCII_BYTE;
              ASCII_BYTE = cstring.toLatin1();
            if(ASCIItoCHAR(ASCII_BYTE,CUTLEN)==true)
             {
                emit this->response();
                //QString moni_data = cstring.mid(2,2);
                //QString zhen_data = cstring.mid(4,4);
                //int moni=moni_data.toInt(&ok,16);
                //QString mo=QString::number(moni,10);
                //int zhen=zhen_data.toInt(&ok,16);
                //QString zh=QString::number(zhen,10);
                //emit this->responsedata(mo,zh);
                response2.remove(0,CUTLEN);
                long1 = response2.size();
              }
            else
              {
                emit responserror();
                long1 =  response2.size();
              }
          }
          else if(long1<DATA_LEN)
          {
              long1=response2.size();
          }
          else
          {
              response2.remove(0,2);
              long1=response2.size();
              emit responserror();
          }
      }
      QByteArray requestData = request.toLocal8Bit();
      serial.write(requestData);
      if (serial.waitForBytesWritten(1)) {
      }
    }

}

//将需要校验的数据转化为char型并CRC校验
bool mainEthread::ASCIItoCHAR(QByteArray GET_DATA1, unsigned int GET_DATA_len)
{
    unsigned char CHAR_GET[GET_DATA_len];
    unsigned char CHAR_8[GET_DATA_len];
    char GET_DATA;
    for(unsigned int i1=0;i1<GET_DATA_len;i1++)
    {
        GET_DATA=GET_DATA1.at(i1);
        if(GET_DATA>='0' && GET_DATA<='9')
            CHAR_GET[i1]=GET_DATA-'0'+0x00;
        else if(GET_DATA>='a' && GET_DATA<='z')
            CHAR_GET[i1]=GET_DATA-'a'+0x0A;
        else if(GET_DATA>='A' && GET_DATA<='Z')
            CHAR_GET[i1]=GET_DATA-'A'+0x0A;
    }
    unsigned int GET_DATA_len1=GET_DATA_len/2;
    for(unsigned int j1=0;j1<GET_DATA_len1;j1++)
    {
        CHAR_8[j1]=(CHAR_GET[2*j1]<<4)^CHAR_GET[(2*j1)+1];
    }
    unsigned int LEN = this->checkCode.size();

    if(LEN==8)
    {
        unsigned char dd[4];
        for(int i=0;i<4;i++)
        {
            dd[i]=CHAR_8[GET_DATA_len1-i-1];
        }
        for(int i=0;i<4;i++)
        {
            CHAR_8[GET_DATA_len1+i-4]=dd[i];
        }
    }
    unsigned char *CHECKED_DATA ;
    CHECKED_DATA = CHAR_8;

    if(LEN==2)
    {
        if(crc8(CHECKED_DATA,GET_DATA_len1,char_8)!=0)
        {
            return false;
        }
        else
            return true;
    }
    else if(LEN==4)
    {
        if(crc16(CHECKED_DATA,GET_DATA_len1,int_16)!=0)
        {
            return false;
        }
        else
            return true;
    }
    else if(LEN==8)
    {
        if(crc32(CHECKED_DATA,GET_DATA_len1,long_32)!=0)
        {
            return false;
        }
        else
            return true;
    }
}

/****
 *生成多项式X^8+X^5+X^4+1
 *crc常数0x8c
 *8位校验
 ****/
unsigned char mainEthread::crc8(unsigned char *ptr,unsigned int len, unsigned char check_code)
{
    unsigned char crc;
    unsigned char CHECK_CODE = check_code;
    unsigned char i;
    crc = 0;
    while(len--)
    {
        crc ^= *ptr++;
        for(i = 0;i < 8;i++)
        {
            if(crc & 0x01)
            {
                crc = (crc>>1) ^ CHECK_CODE;
            }
            else
                crc >>= 1;
        }
    }
    return crc;
}

//16位校验
unsigned int mainEthread::crc16(unsigned char *ptr, unsigned int len, unsigned int check_code)
{
    unsigned int crc;
    unsigned int CHECK_CODE = check_code;
    unsigned int i;
    crc = 0;
    while(len--)
    {
        crc ^= *ptr++;
        for(i = 0;i < 8;i++)
        {
            if(crc & 0x01)
            {
                crc = (crc>>1) ^ CHECK_CODE;
            }
            else
                crc >>= 1;
        }
    }
    return crc;
}

//32位校验
unsigned long int mainEthread::crc32(unsigned char *ptr,unsigned int len, unsigned long int check_code)
{
    unsigned long int crc = 0;
    unsigned long int CHECK_CODE = check_code;
    unsigned long int i;
    while(len--)
    {
        crc ^= *ptr++;
        for(i = 0;i < 8;i++)
        {
            if(crc & 0x1)
            {
                crc = (crc>>1) ^ CHECK_CODE;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    return crc;
}

//将8位校验码转化为CHAR型
unsigned char mainEthread::ASCIItoCHAR8(QByteArray GET_DATA1, unsigned int GET_DATA_len)
{
    unsigned char CHAR_GET[GET_DATA_len];
    unsigned char CHAR_8;
    char GET_DATA;
    for(unsigned int i1=0;i1<GET_DATA_len;i1++)
    {
        GET_DATA=GET_DATA1.at(i1);
        if(GET_DATA>='0' && GET_DATA<='9')
            CHAR_GET[i1]=GET_DATA-'0'+0x00;
        else if(GET_DATA>='a' && GET_DATA<='z')
            CHAR_GET[i1]=GET_DATA-'a'+0x0A;
        else if(GET_DATA>='A' && GET_DATA<='Z')
            CHAR_GET[i1]=GET_DATA-'A'+0x0A;
    }
    unsigned int GET_DATA_len1=GET_DATA_len/2;
    for(unsigned int j1=0;j1<GET_DATA_len1;j1++)
    {
        CHAR_8=(CHAR_GET[2*j1]<<4)^CHAR_GET[(2*j1)+1];
    }
    return CHAR_8;
}

//将16位校验码转化为CHAR型
unsigned int mainEthread::ASCIItoCHAR16(QByteArray GET_DATA1, unsigned int GET_DATA_len)
{
    unsigned char CHAR_GET[GET_DATA_len];
    unsigned int CHAR_16=0;
    char GET_DATA;
    for(unsigned int i1=0;i1<GET_DATA_len;i1++)
    {
        GET_DATA=GET_DATA1.at(i1);
        if(GET_DATA>='0' && GET_DATA<='9')
            CHAR_GET[i1]=GET_DATA-'0'+0x00;
        else if(GET_DATA>='a' && GET_DATA<='z')
            CHAR_GET[i1]=GET_DATA-'a'+0x0A;
        else if(GET_DATA>='A' && GET_DATA<='Z')
            CHAR_GET[i1]=GET_DATA-'A'+0x0A;
    }
    for(unsigned int j1=0;j1<GET_DATA_len;j1++)
    {
        CHAR_16=(CHAR_16<<4)^(unsigned int)CHAR_GET[j1];
    }
    return CHAR_16;
}

//将32位校验码转化为CHAR型
unsigned long int mainEthread::ASCIItoCHAR32(QByteArray GET_DATA1, unsigned int GET_DATA_len)
{
    unsigned char CHAR_GET[GET_DATA_len];
    unsigned long CHAR_32=0;
    char GET_DATA;
    for(unsigned int i1=0;i1<GET_DATA_len;i1++)
    {
        GET_DATA=GET_DATA1.at(i1);
        if(GET_DATA>='0' && GET_DATA<='9')
            CHAR_GET[i1]=GET_DATA-'0'+0x00;
        else if(GET_DATA>='a' && GET_DATA<='z')
            CHAR_GET[i1]=GET_DATA-'a'+0x0A;
        else if(GET_DATA>='A' && GET_DATA<='Z')
            CHAR_GET[i1]=GET_DATA-'A'+0x0A;
    }
    for(unsigned int j1=0;j1<GET_DATA_len;j1++)
    {
        CHAR_32=(CHAR_32<<4)^(unsigned int)CHAR_GET[j1];
    }
    return CHAR_32;
}

void mainEthread::run()
{
    openserial();
}

//校验码设置
void mainEthread::CHECK_SET()
{
    QByteArray CheckCode = this->checkCode.toLatin1();
    unsigned int LEN = strlen(CheckCode);
    if(LEN==2)
    {
        char_8 = ASCIItoCHAR8(CheckCode,LEN);
    }
    else if(LEN==4)
    {
        int_16 = ASCIItoCHAR16(CheckCode,LEN);
    }
    else if(LEN==8)
    {
        long_32 = ASCIItoCHAR32(CheckCode,LEN);
    }
}

mainEthread::~mainEthread()
{
}



#include "mainwindows.h"

MainWindows::MainWindows()
{
    num1 =0;
    num2 =0;
    setWindowTitle("串口调试工具");
    label1 = new QLabel("串口工具");
    label1->setFont(QFont("宋体",20,QFont::Bold,false));
    label2 = new QLabel("输入");
    label4 = new QLabel("接收正确数据包的个数");
    label5 = new QLabel("接收模拟数据");
    label6 = new QLabel("接收真实数据");
    label7 = new QLabel("接收错误字节个数");
    label8 = new QLabel("设置");
    label9 = new QLabel("波特率");
    label10 = new QLabel("请输入多项式");
    label11 = new QLabel("差错率");
    DATA_LENGTH = new QLabel("发送数据包长度");
    CHECK_8 = new QLabel("8位多项式");
    CHECK_16 = new QLabel("16位多项式");
    CHECK_32 = new QLabel("32位多项式");
    browser1 = new QTextBrowser;
    browser4 = new QTextBrowser;
    browser2 = new QTextBrowser;
    browser3 = new QTextBrowser;
    lcd1 = new QLCDNumber;
    edit1 = new QLineEdit;
    edit_8 = new QLineEdit;
    edit_16 = new QLineEdit;
    edit_32 = new QLineEdit;
    edit_length = new QLineEdit;
    baudrateCombox = new QComboBox;
    button1 = new QPushButton("运行");
    button2 = new QPushButton("暂停");
    button3 = new QPushButton("清除窗口");
    button4 = new QPushButton("确定");
    CHECK8 = new QRadioButton;
    CHECK16 = new QRadioButton;
    CHECK32 = new QRadioButton;
    layout1 = new QGridLayout;
    layout1->addWidget(label4,1,0,1,5);
    layout1->addWidget(browser1,2,0,5,5);
    layout1->addWidget(label7,1,5,1,5);
    layout1->addWidget(browser4,2,5,5,5);
    layout1->addWidget(label5,7,0,1,5);
    layout1->addWidget(browser2,8,0,5,5);
    layout1->addWidget(label6,7,5,1,5);
    layout1->addWidget(browser3,8,5,5,5);
    layout1->addWidget(label1,0,4,1,2);
    layout1->addWidget(label2,13,0,1,1);
    layout1->addWidget(edit1,13,1,1,9);
    layout1->addWidget(button1,15,6,1,2);
    layout1->addWidget(button2,15,8,1,2);
    layout1->addWidget(button3,15,1,1,5);
    layout1->addWidget(label8,1,11,1,1);
    layout1->addWidget(label9,6,10,1,1);
    layout1->addWidget(baudrateCombox,6,11,1,2);
    layout1->addWidget(label10,2,10,1,2);
    layout1->addWidget(CHECK_8,3,10,1,1);
    layout1->addWidget(CHECK_16,4,10,1,1);
    layout1->addWidget(CHECK_32,5,10,1,1);
    layout1->addWidget(edit_8,3,11,1,2);
    layout1->addWidget(edit_16,4,11,1,2);
    layout1->addWidget(edit_32,5,11,1,2);
    layout1->addWidget(CHECK8,3,13,1,1);
    layout1->addWidget(CHECK16,4,13,1,1);
    layout1->addWidget(CHECK32,5,13,1,1);
    layout1->addWidget(label11,7,10,1,1);
    layout1->addWidget(lcd1,7,11,1,2);
    layout1->addWidget(DATA_LENGTH,8,10,1,1);
    layout1->addWidget(edit_length,8,11,1,2);
    layout1->addWidget(button4,17,9,1,1);
    setLayout(layout1);
    setbaudrate();
    Edit_SET();
    //CHECKCODE_CHOSE();
    thread = new mainEthread;
    thread->start();
    connect(button1,SIGNAL(clicked()),this,SLOT(transaction()));
    connect(thread,SIGNAL(responsedata(QString,QString)),this,SLOT(showdata(QString,QString)));
    connect(thread,SIGNAL(response()),this,SLOT(showResponse()));
    connect(thread,SIGNAL(responserror()),this,SLOT(showerror()));
    connect(button2,SIGNAL(clicked()),thread,SLOT(stopserial()));
    connect(button3,SIGNAL(clicked()),this,SLOT(clearwindows()));
    connect(button4,SIGNAL(clicked()),this,SLOT(send1()));



}

void MainWindows::setbaudrate()
{
    baudrateCombox->addItem("50");
    baudrateCombox->addItem("75");
    baudrateCombox->addItem("110");
    baudrateCombox->addItem("134");
    baudrateCombox->addItem("150");
    baudrateCombox->addItem("200");
    baudrateCombox->addItem("300");
    baudrateCombox->addItem("600");
    baudrateCombox->addItem("1200");
    baudrateCombox->addItem("1800");
    baudrateCombox->addItem("2400");
    baudrateCombox->addItem("4800");
    baudrateCombox->addItem("9600");
    baudrateCombox->addItem("14400");
    baudrateCombox->addItem("19200");
    baudrateCombox->addItem("38400");
    baudrateCombox->addItem("56000");
    baudrateCombox->addItem("57600");
    baudrateCombox->addItem("76800");
    baudrateCombox->addItem("115200");
    baudrateCombox->addItem("128000");
    baudrateCombox->addItem("256000");
}

void MainWindows::clearwindows()
{
    browser1->clear();
    edit1->clear();
}

MainWindows::~MainWindows()
{

}

void MainWindows::transaction()
{
    thread->transaction(this->edit1->text());
}

void MainWindows::send1()
{
    if(CHECK8->isChecked()&&edit_8->text()!=NULL&&edit_length->text()!=NULL)
    {
        thread->reaseive1(this->baudrateCombox->currentText(), this->edit_8->text(),this->edit_length->text());
        label8->setText("8");
        label10->setText("已经输入多项式8位");
        edit_16->clear();
        edit_32->clear();
    }
    else if(CHECK16->isChecked()&&edit_16->text()!=NULL&&edit_length->text()!=NULL)
    {
        thread->reaseive1(this->baudrateCombox->currentText(), this->edit_16->text(),this->edit_length->text());
        label8->setText("16");
        label10->setText("已经输入多项式16位");
        edit_8->clear();
        edit_32->clear();
    }
    else if(CHECK32->isChecked()&&edit_32->text()!=NULL&&edit_length->text()!=NULL)
    {
        thread->reaseive1(this->baudrateCombox->currentText(), this->edit_32->text(),this->edit_length->text());
        label8->setText("32");
        label10->setText("已经输入多项式32位");
        edit_8->clear();
        edit_16->clear();
    }
    else
    {
        label10->setText("请输入多项式");
    }

}

void MainWindows::showdata(const QString &s1, const QString &s2)
{
    browser2->setText(s1);
    browser3->setText(s2);
}

void MainWindows::showResponse()
{
    ++num1;
    QString datanum=QString::number(num1,10);
    browser1->setText(datanum);
    if(num1!=0)
    {
        float numv = (float)num2/num1;
        QString NUM_BER = QString("'f'format,precision 3,give %1").arg(numv,0,'F',3);
        lcd1->display(NUM_BER);
    }
}

void  MainWindows::showerror()
{
    ++num2;
    QString errornum=QString::number(num2,10);
    browser4->setText(errornum);
    browser2->clear();
    browser3->clear();
}

void MainWindows::Edit_SET()
{
    edit_8->setMaxLength(2);
    edit_16->setMaxLength(4);
    edit_32->setMaxLength(8);
    edit_length->setMaxLength(4);
    QRegExp regx("[a-fA-F0-9]+$");
    QRegExp rx("^[0-9]*[1-9][0-9]*$");
    QValidator *validator_8 = new QRegExpValidator(regx,edit_8);
    QValidator *validator_16 = new QRegExpValidator(regx,edit_16);
    QValidator *validator_32 = new QRegExpValidator(regx,edit_32);
    QValidator *validator_len = new QRegExpValidator(rx,edit_length);
    edit_8->setValidator(validator_8);
    edit_16->setValidator(validator_16);
    edit_32->setValidator(validator_32);
    edit_length->setValidator(validator_len);
}

void MainWindows::CHECKCODE_CHOSE()
{

}