/*------------------------------------------------------------------------------ -- This file is a part of the SocExplorer Software -- Copyright (C) 2011, Plasma Physics Laboratory - CNRS -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -------------------------------------------------------------------------------*/ /*-- Author : Alexis Jeandet -- Mail : alexis.jeandet@lpp.polytechnique.fr ----------------------------------------------------------------------------*/ #include #include "ahbuartplugin.h" #include #include #include #include #include #include #include #include #include #include ahbuartplugin::ahbuartplugin(QWidget *parent):socexplorerplugin(parent,false) { this->port =(rs232port_t)NULL; this->portMutex = new QMutex(QMutex::Recursive); this->UI = new ahbUartPluginUI(); this->setWidget((QWidget*)this->UI); QObject::connect(this,SIGNAL(activateSig(bool)),this->UI,SLOT(setConnected(bool))); QObject::connect(this->UI,SIGNAL(connectPortsig(QString,int)),this,SLOT(togglePort(QString,int))); // this->pyObject = new ahbuartPywrapper(this); // QObject::connect(((ahbuartPywrapper*)this->pyObject),SIGNAL(open(QString,int)),this,SLOT(open(QString,int))); // QObject::connect(((ahbuartPywrapper*)this->pyObject),SIGNAL(close()),this,SLOT(close())); // QObject::connect(((ahbuartPywrapper*)this->pyObject),SIGNAL(ReadBytes(uint,uint)),this,SLOT(ReadBytes(uint,uint))); // QObject::connect(((ahbuartPywrapper*)this->pyObject),SIGNAL(WriteBytes(uint,QList)),this,SLOT(WriteBytes(uint,QList))); QObject::connect(this->UI,SIGNAL(rescanPorts()),this,SLOT(updatePortList())); QObject::connect(this,SIGNAL(addReadBytes(int)),this->UI,SLOT(addReadBytes(int))); QObject::connect(this,SIGNAL(addWritenBytes(int)),this->UI,SLOT(addWritenBytes(int))); this->portListcompleter = NULL; this->scanDone = false; updatePortList(); } ahbuartplugin::~ahbuartplugin() { if(this->port!=(rs232port_t)NULL) { rs232close(this->port); this->port = (rs232port_t)NULL; } this->UI->close(); this->UI->~ahbUartPluginUI(); } void ahbuartplugin::closeMe() { if(this->port!=(rs232port_t)NULL) { rs232close(this->port); this->port = (rs232port_t)NULL; } emit this->closePlugin(this); } int ahbuartplugin::registermenu(QMainWindow *menuHolder) { this->menu = menuHolder->menuBar()->addMenu(tr("&AHB UART")); this->closeAction = this->menu->addAction(tr("Close plugin")); QObject::connect(this->closeAction,SIGNAL(triggered()),this,SLOT(closeMe())); return 1; } bool ahbuartplugin::checkConnection() { QTime timeout; char test[5] ={(char)0x80,(char)0x80,(char)0,(char)0,(char)0}; char test2[1024]; int writen =0; int read = 0; timeout.start(); SocExplorerEngine::message(this,"Check connection",2); QMutexLocker lock(portMutex); while(writen!=5) { writen+=rs232write(this->port,test+writen,5-writen); if(timeout.elapsed()>1000) { SocExplorerEngine::message(this,"Can't write any data on serial port",2); return false; } } #ifdef WIN32 usleep(1000); #endif timeout.restart(); int avail = 0; do { avail = rs232availablebytes(this->port); if(timeout.elapsed()>1000) { if(avail) rs232read(this->port,test2,avail); SocExplorerEngine::message(this,"Connection Error",2); return false; } }while(avail<4); read = rs232read(this->port,test2,avail); if(read>0) { SocExplorerEngine::message(this,"Connection Ok",2); return true; } else { SocExplorerEngine::message(this,"Connection Error",2); return false; } } void ahbuartplugin::connectPort(QString PortName, int baudrate) { QTime timeout; SocExplorerEngine::message(this,"Try to connect to port "+PortName,2); timeout.start(); QMutexLocker lock(portMutex); if(this->port==(rs232port_t)NULL) { SocExplorerEngine::message(this,"Open port "+PortName,2); this->port=rs232open((char*)PortName.toStdString().c_str()); } if(this->port!=badPortValue) { SocExplorerEngine::message(this,"Port opened "+PortName,2); SocExplorerEngine::message(this,"Configure port "+PortName,2); rs232setup(this->port,8,baudrate,rs232parityNo,rs232OneStop); char test[7] ={(char)0x55,(char)0x51,(char)0x80,(char)0x80,(char)0x0,(char)0x0,(char)0x14}; char test2[1024]; SAFEWRITE(test,1,timeout,2000,return); SAFEWRITE((test+1),1,timeout,2000,return); rs232read(this->port,test2,512); int read = 0; for(int i=0;i<10;i++) { SocExplorerEngine::message(this,"Send test patern :0x55,0x55,0x80,0x80,0x0,0x0,0x14",2); SAFEWRITE(test+2,5,timeout,2000,return); SocExplorerEngine::message(this,"Read Result",2); read=rs232read(this->port,test2+read,16); SocExplorerEngine::message(this,QString("Get ") + QString::number(read) + " bytes",2); if(read>0) { SocExplorerEngine::message(this,"Flush port ",2); while(rs232read(this->port,test2,1)>0); this->Connected = true; SocExplorerEngine::message(this,QString("Connection success on ")+PortName,2); emit this->activate(true); if(this->scanDone==false) { socexplorerproxy::loadChildSysDriver(this,"AMBA_PLUGIN"); this->scanDone=true; } this->UI->setSystemSpeed(this->detectSpeed()); break; } } } else { SocExplorerEngine::message(this,QString("Port not opened ")+PortName,2); this->port = (rs232port_t)NULL; this->Connected = false; emit this->activateSig(false); return; } if(this->Connected == false) { SocExplorerEngine::message(this,QString("Port not opened ")+PortName,2); rs232close(this->port); this->port = (rs232port_t)NULL; emit this->activateSig(false); } } bool ahbuartplugin::open(QString PortName,int baudrate) { if(this->port!=(rs232port_t)NULL) this->close(); this->UI->setconfig(PortName,baudrate); this->connectPort(PortName,baudrate); return (this->port!=(rs232port_t)NULL); } void ahbuartplugin::close() { if(this->port!=(rs232port_t)NULL) { rs232close(this->port); this->port = (rs232port_t)NULL; this->Connected = false; emit this->activateSig(false); } } void ahbuartplugin::togglePort(QString PortName,int baudrate) { if(this->port!=(rs232port_t)NULL) { this->close(); } else { this->connectPort(PortName,baudrate); } } unsigned int ahbuartplugin::Read(unsigned int *Value,unsigned int count,unsigned int address) { QTime timeout; timeout.start(); unsigned int read=0; unsigned int cnt=count; unsigned int nextUpdateTrig=0,updateStep=1024; SocExplorerEngine::message(this,QString("Read ")+ QString::number(count) + QString(" words @0x")+ QString::number(address,16),2); if((this->port!= badPortValue)||(this->port!=(rs232port_t)NULL)) { QMutexLocker lock(portMutex); if(!this->checkConnection()) { this->Connected = false; emit this->activateSig(false); this->portMutex->unlock(); return 0; } QProgressBar* progress=NULL; if(cnt>128) progress= SocExplorerEngine::getProgressBar("Reading on uart @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); char CMD[5]; char* result = (char*)malloc(count*4); while(count>32) { CMD[0] = 0x80 | (32-1); CMD[1] = (char)((address>>24)&0xFF); CMD[2] = (char)((address>>16)&0xFF); CMD[3] = (char)((address>>8)&0xFF); CMD[4] = (char)((address)&0xFF); SAFEWRITE(CMD,5,timeout,1000,return 0); timeout.restart(); int avail=0; do{ avail=rs232availablebytes(this->port); if(timeout.elapsed()>1000) { rs232close(this->port); this->port = (rs232port_t)NULL; this->Connected = false; emit this->activateSig(false); return 0; } }while(avail<(32*4)); rs232read(this->port,result+((cnt-count)*4),32*4); count-=32; address+=32*4; if(cnt>128) { if((cnt-count)>=nextUpdateTrig) { progress->setValue(cnt-count); qApp->processEvents(); nextUpdateTrig+=updateStep; } } } if(count>0) { CMD[0] = 0x80 | (count-1); CMD[1] = (char)((address>>24)&0xFF); CMD[2] = (char)((address>>16)&0xFF); CMD[3] = (char)((address>>8)&0xFF); CMD[4] = (char)((address)&0xFF); SAFEWRITE(CMD,5,timeout,1000,return 0); timeout.restart(); int avail=0; do{ avail=rs232availablebytes(this->port); if(timeout.elapsed()>1000) { rs232close(this->port); this->port = (rs232port_t)NULL; this->Connected = false; emit this->activateSig(false); return 0; } }while(avail<(count*4)); rs232read(this->port,result+((cnt-count)*4),count*4); } if(cnt>128) { progress->setValue(cnt-count); qApp->processEvents(); } for(int i=0;(unsigned int)i128) SocExplorerEngine::deleteProgressBar(progress); free(result); } emit this->addReadBytes(read); return read/4; } unsigned int ahbuartplugin::Write(unsigned int *Value,unsigned int count, unsigned int address) { QTime timeout; timeout.start(); unsigned int writen=0; unsigned int nextUpdateTrig=0,updateStep=1024; SocExplorerEngine::message(this,QString("Write ")+ QString::number(count) + QString(" words @0x")+ QString::number(address,16),2); if((this->port!= badPortValue)||(this->port!=(rs232port_t)NULL)) { QMutexLocker lock(portMutex); if(!this->checkConnection()) { emit this->activateSig(false); this->Connected = false; this->portMutex->unlock(); return 0; } QProgressBar* progress = NULL; if(count>128) progress = SocExplorerEngine::getProgressBar("Writing on uart @0x"+QString::number(address,16)+" %v of "+QString::number(count)+" words ",count); int offset = 0; char* CMD= (char*)malloc((32*4)+5); writen=0; while(count>32) { CMD[0] = 0xC0 | (32-1); CMD[1] = (char)(((unsigned int)address>>24)&0xFF); CMD[2] = (char)(((unsigned int)address>>16)&0xFF); CMD[3] = (char)(((unsigned int)address>>8)&0xFF); CMD[4] = (char)(((unsigned int)address)&0xFF); for(int i=0;i<32;i++) { #if __BYTE_ORDER == __LITTLE_ENDIAN CMD[(i*4)+5] = (char)(((unsigned int)Value[i+offset]>>24)&0xFF); CMD[(i*4)+6] = (char)(((unsigned int)Value[i+offset]>>16)&0xFF); CMD[(i*4)+7] = (char)(((unsigned int)Value[i+offset]>>8)&0xFF); CMD[(i*4)+8] = (char)(((unsigned int)Value[i+offset])&0xFF); #elif __BYTE_ORDER == __BIG_ENDIAN CMD[(i*4)+5] = (char)(((unsigned int)Value[i+offset])&0xFF); CMD[(i*4)+6] = (char)(((unsigned int)Value[i+offset]>>8)&0xFF); CMD[(i*4)+7] = (char)(((unsigned int)Value[i+offset]>>16)&0xFF); CMD[(i*4)+8] = (char)(((unsigned int)Value[i+offset]>>24)&0xFF); #endif } SAFEWRITE(CMD,((32*4)+5),timeout,1000,return 0); writen+=32; count-=32; offset+=32; address+=32*4; if(offset>=nextUpdateTrig && progress!=NULL) { progress->setValue(offset); qApp->processEvents(); nextUpdateTrig +=updateStep; } } if(count>0) { CMD[0] = 0xC0 | (count-1); CMD[1] = (char)(((unsigned int)address>>24)&0xFF); CMD[2] = (char)(((unsigned int)address>>16)&0xFF); CMD[3] = (char)(((unsigned int)address>>8)&0xFF); CMD[4] = (char)(((unsigned int)address)&0xFF); for(int i=0;(unsigned int) i<(count);i++) { #if __BYTE_ORDER == __LITTLE_ENDIAN CMD[(i*4)+5] = (char)(((unsigned int)Value[i+offset]>>24)&0xFF); CMD[(i*4)+6] = (char)(((unsigned int)Value[i+offset]>>16)&0xFF); CMD[(i*4)+7] = (char)(((unsigned int)Value[i+offset]>>8)&0xFF); CMD[(i*4)+8] = (char)(((unsigned int)Value[i+offset])&0xFF); #elif __BYTE_ORDER == __BIG_ENDIAN CMD[(i*4)+5] = (char)(((unsigned int)Value[i+offset])&0xFF); CMD[(i*4)+6] = (char)(((unsigned int)Value[i+offset]>>8)&0xFF); CMD[(i*4)+7] = (char)(((unsigned int)Value[i+offset]>>16)&0xFF); CMD[(i*4)+8] = (char)(((unsigned int)Value[i+offset]>>24)&0xFF); #endif } SAFEWRITE(CMD,((count*4)+5),timeout,1000,return 0); writen+=count; } if(progress!=NULL) { progress->setValue(writen); qApp->processEvents(); SocExplorerEngine::deleteProgressBar(progress); } free(CMD); emit this->addWritenBytes(writen*4); return writen; } return 0; } void ahbuartplugin::updatePortList() { if(this->portListcompleter==(QCompleter*)NULL) { this->portListcompleter=new QCompleter(this); this->portListcompleter->setCaseSensitivity(Qt::CaseInsensitive); this->portListcompleterModel = new QStringListModel(this); this->portListcompleter->setModel(this->portListcompleterModel); this->UI->setCompleter(this->portListcompleter); } rs232portslist_t* portlist = rs232getportlist(); rs232portslist_t* portlistenum = portlist; QStringList wordList; while(portlistenum!=NULL) { wordList << portlistenum->name; portlistenum = portlistenum->next; } rs232deleteportlist(portlist); this->portListcompleterModel->setStringList(wordList); } QVariantList ahbuartplugin::ReadBytes(unsigned int address, unsigned int count) { unsigned int data[(count/4)+1]; QVariantList result; this->Read(data,(count/4)+1,address); for(unsigned int i = 0;i>24)))); result.append(QVariant((int)(0x0FF&(data[i]>>16)))); result.append(QVariant((int)(0x0FF&(data[i]>>8)))); result.append(QVariant((int)(0x0FF&(data[i])))); } for(int i=0;i<(count%4);i++) { result.append(QVariant((int)(0x0FF&(data[count/4]>>((3-i)*8))))); } return result; } void ahbuartplugin::WriteBytes(unsigned int address, QList dataList) { unsigned int data[dataList.count()/4]; for(int i = 0;i<(dataList.count()/4);i++) { data[i] = 0x0FF & ((unsigned int)dataList.at(4*i).toUInt()); data[i] = (data[i]<<8) + (0x0FF & ((unsigned int)dataList.at((4*i)+1).toUInt())); data[i] = (data[i]<<8) + (0x0FF & ((unsigned int)dataList.at((4*i)+2).toUInt())); data[i] = (data[i]<<8) + (0x0FF & ((unsigned int)dataList.at((4*i)+3).toUInt())); } this->Write(data,dataList.count()/4,address); } int ahbuartplugin::detectSpeed() { //scaler = (((system_clk*10)/(baudrate*8))-5)/10 unsigned int ahbUartBaseAddress = SocExplorerEngine::self()->getEnumDeviceBaseAddress(this,0x01,0x007,0); // unsigned int dsuBaseAddress = SocExplorerEngine::self()->getEnumDeviceBaseAddress(this,0x01,0x0017,0); unsigned int dsuBaseAddress = 0x90000000; unsigned int scaler = 0,dsuVal1=0,dsuVal2=0; int speed=0; QElapsedTimer time; if(dsuBaseAddress!=-1) { time.start(); if( this->Read(&dsuVal1,1,dsuBaseAddress+0x08)==1) { usleep(1000*1000); qint64 el = time.elapsed(); this->Read(&dsuVal2,1,dsuBaseAddress+0x08); if(dsuVal1!=dsuVal2) return ((dsuVal2-dsuVal1)/el)*1000; } } if(ahbUartBaseAddress!=-1) { if( this->Read(&scaler,1,ahbUartBaseAddress+0x0C)==1) { scaler&=0x3FFFF; speed = (int)(((double)scaler*10.0)+5.0)*((double)this->UI->baudRate()/10.0)*8.0; // speed = (int)((double)(scaler+1)*8.0*(double)this->UI->baudRate()); } } return speed; } void ahbuartplugin::postInstantiationTrigger() { if(this->scanDone && this->Connected) { this->UI->setSystemSpeed(this->detectSpeed()); } }