Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "rs485v2.h"
- RS485v2::RS485v2()
- {
- this->config = new Config(this);
- this->foundDunaHeader = false;
- serialPortName = config->getGlobal("module_rs485v2","serialPortName").toString();
- slowDataSend = config->getGlobal("module_rs485v2","SlowDataSend").toBool();
- allow7Seg = config->getGlobal("module_rs485v2","Allow7Seg").toBool();
- allowLCD = config->getGlobal("module_rs485v2","AllowLCD").toBool();
- enableClock = config->getGlobal("module_rs485v2","EnableClock").toBool();
- this->serialPort = new QSerialPort(serialPortName,this);
- serialPort->setBaudRate(QSerialPort::Baud19200);
- serialPort->setFlowControl(QSerialPort::NoFlowControl);
- serialPort->setParity(QSerialPort::NoParity);
- serialPort->setDataBits(QSerialPort::Data8);
- serialPort->setStopBits(QSerialPort::OneStop);
- rs485Busy = false;
- if (serialPort->open(QIODevice::ReadWrite | QIODevice::Unbuffered) == true) {
- qDebug() << "ready to send data on" << serialPort->portName();
- connect(serialPort, SIGNAL(readyRead()), this, SLOT(onSerialDataAvailable()));
- } else {
- qDebug() << "device failed to open:" << serialPort->errorString();
- }
- }
- RS485v2::~RS485v2()
- {
- this->serialPort->close();
- }
- void RS485v2::sendDataTo7Seg(ZegarStatus zegarStatus, QString location)
- {
- if(!allow7Seg)
- return;
- // wysłanie danych do wyświetlaczy
- QByteArray bufor;
- bufor.resize(13);
- bufor.fill(0);
- // PRZYGOTOWANIE DANYCH DO WYSYŁKI
- bufor[0] = 0x02; // adres wyświetlacza - broadcast
- if(zegarStatus.kierunek == GORA || zegarStatus.przekroczony){
- bufor[1] = (quint8)(zegarStatus.czas_up / 60); // minuty
- bufor[2] = (quint8)(zegarStatus.czas_up % 60); // sekundy
- } else {
- bufor[1] = (quint8)(zegarStatus.czas_down / 60); // minuty
- bufor[2] = (quint8)(zegarStatus.czas_down % 60); // sekundy
- }
- if(bufor.at(1) > 99)
- bufor[1] = 99;
- if(zegarStatus.warning)
- bufor[5] = 1;
- if(zegarStatus.przekroczony){
- //mrugać szybko
- //zapalić diodę informującą o przekroczeniu czasu
- bufor[6] = 1;
- }
- if(zegarStatus.stan_zegara == STAN_ZEGARA_STOPPED){
- bufor[4] = 1; // reset wyświetlacza
- if(this->enableClock){
- QDate data;
- QTime czas;
- data = QDate::currentDate();
- czas = QTime::currentTime();
- bufor[8] = (quint8)czas.hour();
- bufor[9] = (quint8)czas.minute();
- bufor[10] = (quint8)czas.second();
- bufor[11] = (quint8)data.month();
- bufor[12] = (quint8)data.day();
- } else {
- // nie ma opcji zegara - wszystko na zero
- bufor[8] = 0;
- bufor[9] = 0;
- bufor[10] = 0;
- bufor[11] = 0;
- bufor[12] = 0;
- }
- }
- if(zegarStatus.wygaszaj_wiodace){
- bufor[3] = 1;
- }
- if(zegarStatus.buzzer){
- if(zegarStatus.przekroczony){
- if(zegarStatus.czas_up == 1)
- bufor[7] = 1;
- if(zegarStatus.czas_up == 10)
- bufor[7] = 2;
- if(zegarStatus.czas_up == 20)
- bufor[7] = 20;
- bufor[6] = 1;
- }
- }
- if(location.toUpper() == "A"){
- // display obsługuje tylko lokalizację w sali A
- this->sendData(bufor, 0x01);
- }
- }
- void RS485v2::sendDataToLCD(LCD_Command lcd_command)
- {
- if(!allowLCD)
- return;
- //wysyłanie do wyświetlaczy LCD
- quint8 i, poz, dl_linia;
- QByteArray bufor;
- bufor.resize(165);
- bufor.fill(' ');
- QByteArray tmp;
- //linie wpisywane do bufora w kolejności 1-3-2-4
- //naturalna kolejność wyświetlacza LCD
- lcd_command.linia1 = lcd_command.linia1.replace("_"," ");
- lcd_command.linia2 = lcd_command.linia2.replace("_"," ");
- lcd_command.linia3 = lcd_command.linia3.replace("_"," ");
- lcd_command.linia4 = lcd_command.linia4.replace("_"," ");
- lcd_command.linia1 = lcd_command.linia1.replace("ń","n");
- lcd_command.linia2 = lcd_command.linia2.replace("ń","n");
- lcd_command.linia3 = lcd_command.linia3.replace("ń","n");
- lcd_command.linia4 = lcd_command.linia4.replace("ń","n");
- lcd_command.linia1 = lcd_command.linia1.replace("ą","_a");
- lcd_command.linia2 = lcd_command.linia2.replace("ą","_a");
- lcd_command.linia3 = lcd_command.linia3.replace("ą","_a");
- lcd_command.linia4 = lcd_command.linia4.replace("ą","_a");
- lcd_command.linia1 = lcd_command.linia1.replace("ć","_c");
- lcd_command.linia2 = lcd_command.linia2.replace("ć","_c");
- lcd_command.linia3 = lcd_command.linia3.replace("ć","_c");
- lcd_command.linia4 = lcd_command.linia4.replace("ć","_c");
- lcd_command.linia1 = lcd_command.linia1.replace("ę","_e");
- lcd_command.linia2 = lcd_command.linia2.replace("ę","_e");
- lcd_command.linia3 = lcd_command.linia3.replace("ę","_e");
- lcd_command.linia4 = lcd_command.linia4.replace("ę","_e");
- lcd_command.linia1 = lcd_command.linia1.replace("ł","_l");
- lcd_command.linia2 = lcd_command.linia2.replace("ł","_l");
- lcd_command.linia3 = lcd_command.linia3.replace("ł","_l");
- lcd_command.linia4 = lcd_command.linia4.replace("ł","_l");
- lcd_command.linia1 = lcd_command.linia1.replace("ó","_o");
- lcd_command.linia2 = lcd_command.linia2.replace("ó","_o");
- lcd_command.linia3 = lcd_command.linia3.replace("ó","_o");
- lcd_command.linia4 = lcd_command.linia4.replace("ó","_o");
- lcd_command.linia1 = lcd_command.linia1.replace("ś","_s");
- lcd_command.linia2 = lcd_command.linia2.replace("ś","_s");
- lcd_command.linia3 = lcd_command.linia3.replace("ś","_s");
- lcd_command.linia4 = lcd_command.linia4.replace("ś","_s");
- lcd_command.linia1 = lcd_command.linia1.replace("ż","_z");
- lcd_command.linia2 = lcd_command.linia2.replace("ż","_z");
- lcd_command.linia3 = lcd_command.linia3.replace("ż","_z");
- lcd_command.linia4 = lcd_command.linia4.replace("ż","_z");
- lcd_command.linia1 = lcd_command.linia1.replace("ź","_x");
- lcd_command.linia2 = lcd_command.linia2.replace("ź","_x");
- lcd_command.linia3 = lcd_command.linia3.replace("ź","_x");
- lcd_command.linia4 = lcd_command.linia4.replace("ź","_x");
- // duże polskie na duże nie polskie
- lcd_command.linia1 = lcd_command.linia1.replace("Ń","N");
- lcd_command.linia2 = lcd_command.linia2.replace("Ń","N");
- lcd_command.linia3 = lcd_command.linia3.replace("Ń","N");
- lcd_command.linia4 = lcd_command.linia4.replace("Ń","N");
- lcd_command.linia1 = lcd_command.linia1.replace("Ą","A");
- lcd_command.linia2 = lcd_command.linia2.replace("Ą","A");
- lcd_command.linia3 = lcd_command.linia3.replace("Ą","A");
- lcd_command.linia4 = lcd_command.linia4.replace("Ą","A");
- lcd_command.linia1 = lcd_command.linia1.replace("Ć","C");
- lcd_command.linia2 = lcd_command.linia2.replace("Ć","C");
- lcd_command.linia3 = lcd_command.linia3.replace("Ć","C");
- lcd_command.linia4 = lcd_command.linia4.replace("Ć","C");
- lcd_command.linia1 = lcd_command.linia1.replace("Ę","E");
- lcd_command.linia2 = lcd_command.linia2.replace("Ę","E");
- lcd_command.linia3 = lcd_command.linia3.replace("Ę","E");
- lcd_command.linia4 = lcd_command.linia4.replace("Ę","E");
- lcd_command.linia1 = lcd_command.linia1.replace("Ł","L");
- lcd_command.linia2 = lcd_command.linia2.replace("Ł","L");
- lcd_command.linia3 = lcd_command.linia3.replace("Ł","L");
- lcd_command.linia4 = lcd_command.linia4.replace("Ł","L");
- lcd_command.linia1 = lcd_command.linia1.replace("Ó","O");
- lcd_command.linia2 = lcd_command.linia2.replace("Ó","O");
- lcd_command.linia3 = lcd_command.linia3.replace("Ó","O");
- lcd_command.linia4 = lcd_command.linia4.replace("Ó","O");
- lcd_command.linia1 = lcd_command.linia1.replace("Ś","S");
- lcd_command.linia2 = lcd_command.linia2.replace("Ś","S");
- lcd_command.linia3 = lcd_command.linia3.replace("Ś","S");
- lcd_command.linia4 = lcd_command.linia4.replace("Ś","S");
- lcd_command.linia1 = lcd_command.linia1.replace("Ż","Z");
- lcd_command.linia2 = lcd_command.linia2.replace("Ż","Z");
- lcd_command.linia3 = lcd_command.linia3.replace("Ż","Z");
- lcd_command.linia4 = lcd_command.linia4.replace("Ż","Z");
- lcd_command.linia1 = lcd_command.linia1.replace("Ź","Z");
- lcd_command.linia2 = lcd_command.linia2.replace("Ź","Z");
- lcd_command.linia3 = lcd_command.linia3.replace("Ź","Z");
- lcd_command.linia4 = lcd_command.linia4.replace("Ź","Z");
- poz = 5; // pozycja, od której zacząć wpisywać do
- // bufora dane tekstowe
- if(lcd_command.opcje == OPT_LCD_SEKUNDY || lcd_command.opcje == OPT_LCD_MINUTY){
- dl_linia = 0;
- tmp = lcd_command.linia1.toLatin1();
- for(i = 0; i < tmp.size(); i++){
- bufor[poz] = tmp.at(i);
- if(bufor.at(poz) != 95)
- dl_linia++;
- poz++;
- }
- poz += (20 - dl_linia);
- dl_linia = 0;
- tmp.clear();
- tmp = lcd_command.linia3.toLatin1();
- for(i = 0; i < tmp.size(); i++){
- bufor[poz] = tmp.at(i);
- if(bufor.at(poz) != 95)
- dl_linia++;
- poz++;
- }
- poz += (20 - dl_linia);
- dl_linia = 0;
- tmp.clear();
- tmp = lcd_command.linia2.toLatin1();
- for(i = 0; i < tmp.size(); i++){
- bufor[poz] = tmp.at(i);
- if(bufor.at(poz) != 95)
- dl_linia++;
- poz++;
- }
- poz += (20 - dl_linia);
- dl_linia = 0;
- tmp.clear();
- tmp = lcd_command.linia4.toLatin1();
- for(i = 0; i < tmp.size(); i++){
- bufor[poz] = tmp.at(i);
- if(bufor.at(poz) != 95)
- dl_linia++;
- poz++;
- }
- poz += (20 - dl_linia);
- }
- if(lcd_command.opcje == OPT_LCD_TIMER_START){
- dl_linia = 0;
- tmp = lcd_command.linia1.toLatin1();
- for(i = 0; i < tmp.size(); i++){
- bufor[poz] = tmp.at(i);
- if(bufor.at(poz) != 95)
- dl_linia++;
- poz++;
- }
- }
- bufor[0] = 0x0B; //adres rozgłoszeniowy dla wyświetlacza LCD
- bufor[1] = LCD_TEXT;//zwykły text
- if(lcd_command.opcje == OPT_LCD_TIMER_START ||
- lcd_command.opcje == OPT_LCD_TIMER_STOP ||
- lcd_command.opcje == OPT_LCD_CLEAR){
- bufor[1] = LCD_TIMER1;
- }
- bufor[2] = poz - 5; //aktualizacja długości tekstu
- bufor[3] = lcd_command.czas;
- bufor[4] = lcd_command.opcje;
- quint8 copySize = bufor.at(2)+5;
- QByteArray tmpBuff;
- tmpBuff = bufor.left(copySize);
- this->sendData(tmpBuff, 0x02);
- }
- quint16 RS485v2::crc16_update(quint16 crc, quint8 a)
- {
- quint8 i;
- crc ^= a;
- for (i = 0; i < 8; ++i) {
- if (crc & 1)
- crc = (crc >> 1) ^ 0xA001;
- else
- crc = (crc >> 1);
- }
- return crc;
- }
- bool RS485v2::isOK_CRC(QByteArray buffer, quint16 crc)
- {
- quint16 newCrc;
- quint8 i;
- newCrc = 0xFFFF;
- for(i = 2; i < buffer.size(); i++){
- newCrc = this->crc16_update(newCrc, (quint8)buffer.at(i));
- }
- return newCrc == crc;
- }
- quint16 RS485v2::calculateCRC16(QByteArray buffer)
- {
- quint16 newCrc;
- quint8 i;
- newCrc = 0xFFFF;
- for(i = 0; i < buffer.size(); i++){
- newCrc = this->crc16_update(newCrc, (quint8)buffer.at(i));
- }
- return newCrc;
- }
- void RS485v2::sendData(QByteArray bufor, quint16 addres)
- {
- // UTWORZENIE BUFORA DO WYSYŁKI
- // Header protokołu Duna
- QByteArray crcBuf, buffer;
- QDataStream ds1(&crcBuf, QIODevice::WriteOnly);
- ds1 << (quint8)DATA_TYPE_TIMER_DATA; // dataType
- ds1 << (quint16)bufor.size(); // dataSize
- ds1 << (quint16)0x00; // srcAddr
- ds1 << (quint16)addres; // dstAddr dla 7SEG zawsze 0x01; dla LCD zawsze 0x02
- ds1 << (quint32)0x0D42; // serial number
- ds1 << (quint16)((0x01 << 8) | 0x00); // firmware ver
- ds1.unsetDevice();
- crcBuf.append(bufor); // dne zegara
- QDataStream ds2(&buffer, QIODevice::WriteOnly);
- ds2 << (quint32) 0x44756E61; // magic header 'Duna'
- ds2 << (quint16)this->calculateCRC16(crcBuf);// CRC16
- ds2.unsetDevice();
- buffer.append(crcBuf); // data
- crcBuf.clear();
- while(this->rs485Busy){
- QCoreApplication::processEvents();
- }
- rs485Busy = true;
- if(this->slowDataSend){
- Sleeper::msleep(1);
- char byte;
- for(quint8 i = 0; i < buffer.size(); i++){
- byte = buffer[i];
- this->serialPort->write(&byte,1);
- Sleeper::usleep(500); // WARTOŚĆ KRYTYCZNA - 500us
- }
- Sleeper::msleep(1);
- } else {
- this->serialPort->write(buffer,buffer.size());
- this->serialPort->flush();
- QTimer::singleShot(buffer.size() * 2,this,SLOT(rs485SwitchToRead()));
- }
- }
- void RS485v2::onSerialDataAvailable()
- {
- datagramHeader header;
- if (serialPort->bytesAvailable()) {
- Sleeper::msleep(10);
- globalBuffer.append(serialPort->readAll());
- }
- // jeśli globalBuffer jest większy niż 100 i foundDunaHeader == true
- // coś poszło nie tak
- if(globalBuffer.size() > 100 && this->foundDunaHeader){
- this->foundDunaHeader = false;
- }
- // wykrywamy początek transmisji (magic header == 'Duna')
- if(!this->foundDunaHeader){
- while ( globalBuffer.size() > 3 && globalBuffer.at(0) != 'D' && globalBuffer.at(0) != 'u' && globalBuffer.at(0) != 'n' && globalBuffer.at(0) != 'a') {
- if(globalBuffer.size() > 3){
- globalBuffer.remove(0,1);
- }
- }
- }
- if(globalBuffer.size() > 3){
- // znaleziony header
- if(!this->foundDunaHeader){
- globalBuffer.remove(0,4);
- }
- this->foundDunaHeader = true;
- } else {
- // wycieliśmy początkową sieczkę, ale nie znaleziono nagłowka
- return;
- }
- if( globalBuffer.size() >= DATAGRAM_HEADER_SIZE) {
- QByteArray buffer;
- buffer = globalBuffer.left(DATAGRAM_HEADER_SIZE);
- QDataStream stream(buffer);
- stream.setByteOrder(QDataStream::LittleEndian);
- stream >> header.crc16;
- stream >> header.dataType;
- stream >> header.dataSize;
- stream >> header.srcAddr;
- stream >> header.dstAddr;
- stream >> header.serialNumber;
- stream >> header.firmwareVer;
- stream.unsetDevice();
- buffer.clear();
- if((quint32)globalBuffer.size() < (header.dataSize + (quint32)(DATAGRAM_HEADER_SIZE))){
- // nie dotarły wszystkie dane, czekamy dalej
- return;
- }
- // jeśli program dotarł do tego miejsca, znaczy że dane dotarły wszystkie
- globalBuffer.remove(0,DATAGRAM_HEADER_SIZE); // obcięcie headera z bufora
- this->foundDunaHeader = false; // znacznik headera już nie potrzebny
- if(header.dstAddr == 0x00){
- // pakiet dla nas (jeśli nie, ignorujemy dane)
- // TUTAJ SPRAWDZIĆ CRC16!!!!
- QByteArray crcBuf;
- QDataStream ds(&crcBuf, QIODevice::WriteOnly);
- ds.setByteOrder(QDataStream::LittleEndian);
- ds << (quint16) header.crc16;
- ds << (quint8) header.dataType;
- ds << (quint16) header.dataSize;
- ds << (quint16) header.srcAddr;
- ds << (quint16) header.dstAddr;
- ds << (quint32) header.serialNumber;
- ds << (quint16) header.firmwareVer;
- ds.unsetDevice();
- crcBuf.append(globalBuffer.left(header.dataSize));
- if(!this->isOK_CRC(crcBuf, header.crc16)){
- // PROBLEM!!!!!
- // przekłamanie danych
- qDebug() << "CRC ERROR!!!!\nModule hwID: "<< header.srcAddr << " SN: "<< header.serialNumber << " FV: "<< header.firmwareVer;
- this->foundDunaHeader = false;
- globalBuffer.clear();
- return;
- }
- // #####################################################################
- // ##### DANE DOTARŁY ##################################################
- // ##### CO TO JEST ZA PAKIET? #########################################
- // #####################################################################
- if(header.dataType == DATA_TYPE_ACK){
- // potwierdzenie odebrania danych
- QByteArray datagram;
- datagram = globalBuffer.left(header.dataSize);
- globalBuffer.remove(0, header.dataSize);
- if(header.srcAddr == 0x02){
- // potwierdzenie od LCD
- emit this->sigLCDAck(datagram);
- }
- return;
- } // header.dataType == DATA_TYPE_ACK
- // #####################################################################
- // ##### DANE DOTARŁY ##################################################
- // ##### CO TO JEST ZA PAKIET? #########################################
- // #####################################################################
- if(header.dataType == DATA_TYPE_TIMER_DATA){
- // potwierdzenie odebrania danych
- QByteArray datagram;
- datagram = globalBuffer.left(header.dataSize);
- globalBuffer.remove(0, header.dataSize);
- if(header.srcAddr == 0x02){
- // klawisz od LCD
- emit this->sigLCDKey(datagram);
- }
- return;
- } // header.dataType == DATA_TYPE_TIMER_DATA
- } else { // header.dstAddr == 0x00
- globalBuffer.remove(0,header.dataSize);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment