Ejemplo n.º 1
0
class ValueWidget(QWidget, Ui_Widget):

    def __init__(self, iface):

        self.hasqwt=hasqwt
        self.hasmpl=hasmpl
        self.layerMap=dict()
        self.statsChecked=False
        self.ymin=0
        self.ymax=250

        self.iface=iface
        self.canvas=self.iface.mapCanvas()
        self.legend=self.iface.legendInterface()
        self.logger = logging.getLogger('.'.join((__name__, 
                                        self.__class__.__name__)))

        QWidget.__init__(self)
        self.setupUi(self)
        self.setupUi_extra()

        QObject.connect(self.cbxActive,SIGNAL("stateChanged(int)"),self.changeActive)
        QObject.connect(self.cbxGraph,SIGNAL("stateChanged(int)"),self.changePage)
        QObject.connect(self.canvas, SIGNAL( "keyPressed( QKeyEvent * )" ), self.pauseDisplay )
        QObject.connect(self.plotSelector, SIGNAL( "currentIndexChanged ( int )" ), self.changePlot )

    def setupUi_extra(self):

        # checkboxes
        #self.changeActive(Qt.Checked)
        #set inactive by default - should save last state in user config
        self.cbxActive.setCheckState(Qt.Unchecked)

        # plot
        self.plotSelector.setVisible( False )
        self.cbxStats.setVisible( False )
        self.graphControls.setVisible( False )
        if self.hasqwt:
            self.plotSelector.addItem( 'Qwt' )
        if self.hasmpl:
            self.plotSelector.addItem( 'mpl' )
        self.plotSelector.setCurrentIndex( 0 );
        if (not self.hasqwt or not self.hasmpl):
            #self.plotSelector.setVisible(False)
            self.plotSelector.setEnabled(False)

        # Page 2 - qwt
        if self.hasqwt:
            self.qwtPlot = QwtPlot(self.stackedWidget)
            self.qwtPlot.setAutoFillBackground(False)
            self.qwtPlot.setObjectName("qwtPlot")
            self.curve = QwtPlotCurve()
            self.curve.setSymbol(
                QwtSymbol(QwtSymbol.Ellipse,
                          QBrush(Qt.white),
                          QPen(Qt.red, 2),
                          QSize(9, 9)))
            self.curve.attach(self.qwtPlot)
            self.qwtPlot.setVisible(False)
        else:
            self.qwtPlot = QtGui.QLabel("Need Qwt >= 5.0 or matplotlib >= 1.0 !")

        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.qwtPlot.sizePolicy().hasHeightForWidth())
        self.qwtPlot.setSizePolicy(sizePolicy)
        self.qwtPlot.setObjectName("qwtPlot")
        self.qwtPlot.updateGeometry()
        self.stackedWidget.addWidget(self.qwtPlot)

        #Page 3 - matplotlib
        self.mplLine = None #make sure to invalidate when layers change
        if self.hasmpl:
            # mpl stuff
            # should make figure light gray
            self.mplBackground = None #http://www.scipy.org/Cookbook/Matplotlib/Animations
            self.mplFig = plt.Figure(facecolor='w', edgecolor='w')
            self.mplFig.subplots_adjust(left=0.1, right=0.975, bottom=0.13, top=0.95)
            self.mplPlt = self.mplFig.add_subplot(111)   
            self.mplPlt.tick_params(axis='both', which='major', labelsize=12)
            self.mplPlt.tick_params(axis='both', which='minor', labelsize=10)                           
            # qt stuff
            self.pltCanvas = FigureCanvasQTAgg(self.mplFig)
            self.pltCanvas.setParent(self.stackedWidget)
            self.pltCanvas.setAutoFillBackground(False)
            self.pltCanvas.setObjectName("mplPlot")
            self.mplPlot = self.pltCanvas
            self.mplPlot.setVisible(False)
        else:
            self.mplPlot = QtGui.QLabel("Need Qwt >= 5.0 or matplotlib >= 1.0 !")

        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.mplPlot.sizePolicy().hasHeightForWidth())
        self.mplPlot.setSizePolicy(sizePolicy)
        self.qwtPlot.setObjectName("qwtPlot")
        self.mplPlot.updateGeometry()
        self.stackedWidget.addWidget(self.mplPlot)

        self.stackedWidget.setCurrentIndex(0)


    def disconnect(self):
        self.changeActive(False)
        QObject.disconnect(self.canvas, SIGNAL( "keyPressed( QKeyEvent * )" ), self.pauseDisplay )
    
    def pauseDisplay(self,e):
      if ( e.modifiers() == Qt.ShiftModifier or e.modifiers() == Qt.MetaModifier ) and e.key() == Qt.Key_A:

        self.cbxActive.toggle()
        return True
      return False


    def keyPressEvent( self, e ):
      if ( e.modifiers() == Qt.ControlModifier or e.modifiers() == Qt.MetaModifier ) and e.key() == Qt.Key_C:
        items = QString()
        for rec in range( self.tableWidget.rowCount() ):
          items.append( '"' + self.tableWidget.item( rec, 0 ).text() + '",' + self.tableWidget.item( rec, 1 ).text() + "\n" )
        if not items.isEmpty():
          clipboard = QApplication.clipboard()
          clipboard.setText( items )
      elif (self.pauseDisplay(e)):
        pass
      else:
        QWidget.keyPressEvent( self, e )


    def changePage(self,state):
        if (state==Qt.Checked):
            self.plotSelector.setVisible( True )
            self.cbxStats.setVisible( True )
            self.graphControls.setVisible( True )
            if (self.plotSelector.currentText()=='mpl'):
                self.stackedWidget.setCurrentIndex(2)
            else:
                self.stackedWidget.setCurrentIndex(1)
        else:
            self.plotSelector.setVisible( False )
            self.cbxStats.setVisible( False )
            self.graphControls.setVisible( False )
            self.stackedWidget.setCurrentIndex(0)

    def changePlot(self):
        self.changePage(self.cbxActive.checkState())

    def changeActive(self,state):
        if (state==Qt.Checked):
            #QObject.connect(self.legend, SIGNAL( "itemAdded ( QModelIndex )" ), self.statsNeedChecked )
            #QObject.connect(self.legend, SIGNAL( "itemRemoved ()" ), self.invalidatePlot )
            QObject.connect(self.canvas, SIGNAL( "layersChanged ()" ), self.invalidatePlot )
            if int(QGis.QGIS_VERSION[2]) > 2: # for QGIS >= 1.3
                QObject.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint &)"), self.printValue)
            else:
                QObject.connect(self.canvas, SIGNAL("xyCoordinates(QgsPoint &)"), self.printValue)
        else:
            QObject.disconnect(self.canvas, SIGNAL( "layersChanged ()" ), self.invalidatePlot )
            if int(QGis.QGIS_VERSION[2]) > 2: # for QGIS >= 1.3
                QObject.disconnect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint &)"), self.printValue)
            else:
                QObject.disconnect(self.canvas, SIGNAL("xyCoordinates(QgsPoint &)"), self.printValue)


    def printValue(self,position):

        if self.canvas.layerCount() == 0:
            self.values=[]         
            self.showValues()
            return
        
        needextremum = self.cbxGraph.isChecked() # if plot is checked

        # count the number of requires rows and remember the raster layers
        nrow=0
        rasterlayers=[]
        layersWOStatistics=[]

        for i in range(self.canvas.layerCount()):
            layer = self.canvas.layer(i)
            if (layer!=None and layer.isValid() and layer.type()==QgsMapLayer.RasterLayer):
              if QGis.QGIS_VERSION_INT >= 10900: # for QGIS >= 1.9
                if not layer.dataProvider():
                  continue

                if not layer.dataProvider().capabilities() & QgsRasterDataProvider.IdentifyValue:
                  continue

                nrow+=layer.bandCount()
                rasterlayers.append(layer)

              else: # < 1.9
                if layer.providerKey()=="wms":
                  continue

                if layer.providerKey()=="grassraster":
                  nrow+=1
                  rasterlayers.append(layer)
                else: # normal raster layer
                  nrow+=layer.bandCount()
                  rasterlayers.append(layer)
                
              # check statistics for each band
              if needextremum:
                for i in range( 1,layer.bandCount()+1 ):
                  if int(QGis.QGIS_VERSION[2]) > 8: # for QGIS > 1.8
                    has_stats=layer.dataProvider().hasStatistics(i)
                  else:
                    has_stats=layer.hasStatistics(i)
                  if not layer.id() in self.layerMap and not has_stats\
                          and not layer in layersWOStatistics:
                    layersWOStatistics.append(layer)

        if layersWOStatistics and not self.statsChecked:
          self.calculateStatistics(layersWOStatistics)
                  
        # create the row if necessary
        self.tableWidget.setRowCount(nrow)

        irow=0
        self.values=[]
        self.ymin=1e38
        self.ymax=-1e38

        mapCanvasSrs = self.iface.mapCanvas().mapRenderer().destinationSrs()

        # TODO - calculate the min/max values only once, instead of every time!!!
        # keep them in a dict() with key=layer.id()
                
        for layer in rasterlayers:
            layername=unicode(layer.name())
            layerSrs = layer.srs()
            pos = position         

            # if given no position, get dummy values
            if position is None:
                pos = QgsPoint(0,0)
            # transform points if needed
            elif not mapCanvasSrs == layerSrs and self.iface.mapCanvas().hasCrsTransformEnabled():
              srsTransform = QgsCoordinateTransform(mapCanvasSrs, layerSrs)
              try:
                pos = srsTransform.transform(position)
              except QgsCsException, err:
                # ignore transformation errors
                continue

            if QGis.QGIS_VERSION_INT >= 10900: # for QGIS >= 1.9
              if not layer.dataProvider():
                continue

              ident = None
              if position is not None:
                canvas = self.iface.mapCanvas()

                # we can only use context if layer is not projected
                if canvas.hasCrsTransformEnabled() and layer.dataProvider().crs() != canvas.mapRenderer().destinationCrs():
                  ident = layer.dataProvider().identify(pos, QgsRasterDataProvider.IdentifyFormatValue )
                else:
                  extent = canvas.extent()
                  width = round(extent.width() / canvas.mapUnitsPerPixel());
                  height = round(extent.height() / canvas.mapUnitsPerPixel());

                  extent = canvas.mapRenderer().mapToLayerCoordinates( layer, extent );

                  ident = layer.dataProvider().identify(pos, QgsRasterDataProvider.IdentifyFormatValue, canvas.extent(), width, height )
                if not len( ident ) > 0:
                    continue

              # if given no position, set values to 0
              if position is None:
                  for key in ident.iterkeys():
                      ident[key] = layer.dataProvider().noDataValue(key)

              for iband in range(1,layer.bandCount()+1): # loop over the bands
                layernamewithband=layername
                if len(ident)>1:
                    layernamewithband+=' '+layer.bandName(iband)

                if not ident or not ident.has_key( iband ): # should not happen
                  bandvalue = "?"
                else: 
                  doubleValue =  ident[iband].toDouble()[0]
                  if layer.dataProvider().isNoDataValue ( iband, doubleValue ):  
                    bandvalue = "no data"
                  else:
                    bandvalue = QgsRasterBlock.printValue( doubleValue )

                self.values.append((layernamewithband,bandvalue))

                if needextremum:
                    has_stats=layer.hasStatistics(i)
                    if has_stats:
                        cstr=layer.bandStatistics(iband)
                    if has_stats:
                        self.ymin=min(self.ymin,cstr.minimumValue)
                        self.ymax=max(self.ymax,cstr.maximumValue)
                    else:
                        self.ymin=min(self.ymin,layer.minimumValue(i))
                        self.ymax=max(self.ymax,layer.maximumValue(i))

            else: # QGIS < 1.9
              isok,ident = layer.identify(pos)
              if not isok:
                  continue

              # if given no position, set values to 0
              if position is None:
                  for key in ident.iterkeys():
                      ident[key] = 0

              if layer.providerKey()=="grassraster":
                if not ident.has_key(QString("value")):
                  continue
                cstr = ident[QString("value")]
                if cstr.isNull():
                  continue
                value = cstr.toDouble()
                if not value[1]:
                  # if this is not a double, it is probably a (GRASS string like
                  # 'out of extent' or 'null (no data)'. Let's just show that:
                  self.values.append((layername, cstr))
                  continue
                self.values.append((layername,cstr))
                if needextremum:
                  self.ymin = min(self.ymin,value[0])
                  self.ymax = max(self.ymax,value[0])

              else:
                for iband in range(1,layer.bandCount()+1): # loop over the bands
                  bandvalue=ident[layer.bandName(iband)]
                  layernamewithband=layername
                  if len(ident)>1:
                      layernamewithband+=' '+layer.bandName(iband)

                  self.values.append((layernamewithband,bandvalue))

                  if needextremum:
                      if int(QGis.QGIS_VERSION[2]) > 8: # for QGIS > 1.8
                          has_stats=layer.dataProvider().hasStatistics(i)
                          if has_stats:
                              cstr=layer.dataProvider().bandStatistics(iband)
                      else:
                          has_stats=layer.hasStatistics(i)
                          if has_stats:
                              cstr=layer.bandStatistics(iband)
                      if has_stats:
                          self.ymin=min(self.ymin,cstr.minimumValue)
                          self.ymax=max(self.ymax,cstr.maximumValue)
                      else:
                          self.ymin=min(self.ymin,layer.minimumValue(i))
                          self.ymax=max(self.ymax,layer.maximumValue(i))

        self.showValues()
Ejemplo n.º 2
0
class RTTView(QtGui.QWidget, Ui_RTTView):
    def __init__(self, parent=None):
        super(RTTView, self).__init__(parent)

        self.setupUi(self)

        self.initSetting()

        self.initQwtPlot()

        self.daplink = None

        self.tmrDAP = QtCore.QTimer()
        self.tmrDAP.setInterval(10)
        self.tmrDAP.timeout.connect(self.on_tmrDAP_timeout)
        self.tmrDAP.start()

        self.tmrCntr = 0  # tmrDAP超时一次,tmrCntr加一

    def initSetting(self):
        if not os.path.exists('setting.ini'):
            open('setting.ini', 'w')

        self.conf = ConfigParser.ConfigParser()
        self.conf.read('setting.ini')

        if not self.conf.has_section('globals'):
            self.conf.add_section('globals')
            self.conf.set('globals', 'mappath', '[]')
        for path in eval(self.conf.get('globals', 'mappath')):
            self.cmbMap.insertItem(10, path)

    def initQwtPlot(self):
        self.PlotBuff = ''
        self.PlotData = [0] * 1000

        self.qwtPlot = QwtPlot(self)
        self.vLayout0.insertWidget(0, self.qwtPlot)

        self.PlotCurve = QwtPlotCurve()
        self.PlotCurve.attach(self.qwtPlot)
        self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData)

        self.on_cmbMode_currentIndexChanged(u'文本')

    def parseRTTAddr(self):
        with open(self.cmbMap.currentText(), 'r') as f:
            for line in f:
                match = re.match(
                    '\s+_SEGGER_RTT\s+(0x[0-9a-fA-F]{8})\s+Data.+', line)
                if match: return int(match.group(1), 16)
            else:
                raise Exception('Can not found _SEGGER_RTT')

    @QtCore.pyqtSlot()
    def on_btnOpen_clicked(self):
        if self.btnOpen.text() == u'打开连接':
            try:
                self.daplink.open()

                self.dp = coresight.dap.DebugPort(self.daplink)
                self.dp.init()
                self.dp.power_up_debug()

                self.ap = coresight.ap.AHB_AP(self.dp, 0)
                self.ap.init()

                self.RTTAddr = self.parseRTTAddr()
            except Exception as e:
                print e
            else:
                self.btnOpen.setText(u'关闭连接')
                self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inopening.png"))
        else:
            try:
                self.daplink.close()
            except Exception as e:
                print e
            finally:
                self.btnOpen.setText(u'打开连接')
                self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inclosing.png"))

    def aUpEmpty(self):
        LEN = (16 + 4 * 2) + (4 * 6) * 4

        buf = self.ap.readBlockMemoryUnaligned8(self.RTTAddr, LEN)

        arr = struct.unpack('16sLLLLLLLL24xLLLLLL24x',
                            ''.join([chr(x) for x in buf]))

        self.aUp = RingBuffer(arr[3:9])

        print 'WrOff=%d, RdOff=%d' % (self.aUp.WrOff, self.aUp.RdOff)

        self.aDown = RingBuffer(arr[9:15])

        return (self.aUp.RdOff == self.aUp.WrOff)

    def aUpRead(self):
        if self.aUp.RdOff < self.aUp.WrOff:
            len_ = self.aUp.WrOff - self.aUp.RdOff

            arr = self.ap.readBlockMemoryUnaligned8(
                self.aUp.pBuffer + self.aUp.RdOff, len_)

            self.aUp.RdOff += len_

            self.ap.write32(self.RTTAddr + (16 + 4 * 2) + 4 * 4,
                            self.aUp.RdOff)
        else:
            len_ = self.aUp.SizeOfBuffer - self.aUp.RdOff + 1

            arr = self.ap.readBlockMemoryUnaligned8(
                self.aUp.pBuffer + self.aUp.RdOff, len_)

            self.aUp.RdOff = 0  #这样下次再读就会进入执行上个条件

            self.ap.write32(self.RTTAddr + (16 + 4 * 2) + 4 * 4,
                            self.aUp.RdOff)

        return ''.join([chr(x) for x in arr])

    def on_tmrDAP_timeout(self):
        if self.btnOpen.text() == u'关闭连接':
            ss = ''
            try:
                if not self.aUpEmpty():
                    ss = self.aUpRead()
            except Exception as e:
                pass

            if ss:
                if self.mode == u'文本':
                    if len(self.txtMain.toPlainText()) > 50000:
                        self.txtMain.clear()
                    self.txtMain.moveCursor(QtGui.QTextCursor.End)
                    self.txtMain.insertPlainText(ss)

                elif self.mode == u'波形':
                    self.PlotBuff += ss
                    if self.PlotBuff.rfind(',') == -1: return
                    try:
                        d = [
                            int(x) for x in self.
                            PlotBuff[0:self.PlotBuff.rfind(',')].split(',')
                        ]
                        for x in d:
                            self.PlotData.pop(0)
                            self.PlotData.append(x)
                    except:
                        self.PlotBuff = ''
                    else:
                        self.PlotBuff = self.PlotBuff[self.PlotBuff.
                                                      rfind(',') + 1:]

                    self.PlotCurve.setData(range(1,
                                                 len(self.PlotData) + 1),
                                           self.PlotData)
                    self.qwtPlot.replot()

        self.detect_daplink()  # 自动检测 DAPLink 的热插拔

    def detect_daplink(self):
        daplinks = pyDAPAccess.DAPAccess.get_connected_devices()

        if self.daplink and (daplinks == []):  # daplink被拔下
            try:
                self.daplink.close()
            except Exception as e:
                print e
            finally:
                self.daplink = None
                self.linDAP.clear()

                self.btnOpen.setText(u'打开连接')
                self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inclosing.png"))

        if not self.daplink and daplinks != []:
            self.daplink = daplinks[0]

            self.linDAP.clear()
            self.linDAP.setText(self.daplink._product_name)

    @QtCore.pyqtSlot()
    def on_btnMap_clicked(self):
        path = QtGui.QFileDialog.getOpenFileName(
            caption=u'项目.map文件路径',
            filter=u'MDK .map file (*.map)',
            directory=self.cmbMap.currentText())
        if path != '':
            self.cmbMap.insertItem(0, path)
            self.cmbMap.setCurrentIndex(0)

    @QtCore.pyqtSlot(str)
    def on_cmbMode_currentIndexChanged(self, str):
        self.mode = str
        self.txtMain.setVisible(self.mode == u'文本')
        self.qwtPlot.setVisible(self.mode == u'波形')

    @QtCore.pyqtSlot()
    def on_btnClear_clicked(self):
        self.txtMain.clear()

    def closeEvent(self, evt):
        paths = []
        for i in range(min(10, self.cmbMap.count())):
            paths.append(self.cmbMap.itemText(i))
        self.conf.set('globals', 'mappath', repr(paths))
        self.conf.write(open('setting.ini', 'w'))
Ejemplo n.º 3
0
class RTTView(QtGui.QWidget):
    def __init__(self, parent=None):
        super(RTTView, self).__init__(parent)
        
        uic.loadUi('RTTView.ui', self)

        self.initSetting()

        self.initQwtPlot()

        self.rcvbuff = b''
        
        self.tmrRTT = QtCore.QTimer()
        self.tmrRTT.setInterval(10)
        self.tmrRTT.timeout.connect(self.on_tmrRTT_timeout)
        self.tmrRTT.start()
    
    def initSetting(self):
        if not os.path.exists('setting.ini'):
            open('setting.ini', 'w')
        
        self.conf = ConfigParser.ConfigParser()
        self.conf.read('setting.ini')
        
        if not self.conf.has_section('J-Link'):
            self.conf.add_section('J-Link')
            self.conf.set('J-Link', 'dllpath', '')
            self.conf.add_section('Memory')
            self.conf.set('Memory', 'StartAddr', '0x20000000')

        self.linDLL.setText(self.conf.get('J-Link', 'dllpath').decode('gbk'))

    def initQwtPlot(self):
        self.PlotData = [0]*1000
        
        self.qwtPlot = QwtPlot(self)
        self.qwtPlot.setVisible(False)
        self.vLayout.insertWidget(0, self.qwtPlot)
        
        self.PlotCurve = QwtPlotCurve()
        self.PlotCurve.attach(self.qwtPlot)
        self.PlotCurve.setData(range(1, len(self.PlotData)+1), self.PlotData)
    
    @QtCore.pyqtSlot()
    def on_btnOpen_clicked(self):
        if self.btnOpen.text() == u'打开连接':
            try:
                self.jlink = ctypes.cdll.LoadLibrary(self.linDLL.text())

                err_buf = (ctypes.c_char * 64)()
                self.jlink.JLINKARM_ExecCommand('Device = Cortex-M0', err_buf, 64)

                self.jlink.JLINKARM_TIF_Select(1)
                self.jlink.JLINKARM_SetSpeed(8000)
                
                buff = ctypes.create_string_buffer(1024)
                Addr = int(self.conf.get('Memory', 'StartAddr'), 16)
                for i in range(256):
                    self.jlink.JLINKARM_ReadMem(Addr + 1024*i, 1024, buff)
                    index = buff.raw.find('SEGGER RTT')
                    if index != -1:
                        self.RTTAddr = Addr + 1024*i + index

                        buff = ctypes.create_string_buffer(ctypes.sizeof(SEGGER_RTT_CB))
                        self.jlink.JLINKARM_ReadMem(self.RTTAddr, ctypes.sizeof(SEGGER_RTT_CB), buff)

                        rtt_cb = SEGGER_RTT_CB.from_buffer(buff)
                        self.aUpAddr = self.RTTAddr + 16 + 4 + 4
                        self.aDownAddr = self.aUpAddr + ctypes.sizeof(RingBuffer) * rtt_cb.MaxNumUpBuffers

                        self.txtMain.append('\n_SEGGER_RTT @ 0x%08X with %d aUp and %d aDown\n' %(self.RTTAddr, rtt_cb.MaxNumUpBuffers, rtt_cb.MaxNumDownBuffers))
                        break
                else:
                    raise Exception('Can not find _SEGGER_RTT')
            except Exception as e:
                self.txtMain.append('\n%s\n' %str(e))
            else:
                self.linDLL.setEnabled(False)
                self.btnDLL.setEnabled(False)
                self.btnOpen.setText(u'关闭连接')
        else:
            self.linDLL.setEnabled(True)
            self.btnDLL.setEnabled(True)
            self.btnOpen.setText(u'打开连接')
    
    def aUpRead(self):
        buf = ctypes.create_string_buffer(ctypes.sizeof(RingBuffer))
        self.jlink.JLINKARM_ReadMem(self.aUpAddr, ctypes.sizeof(RingBuffer), buf)

        aUp = RingBuffer.from_buffer(buf)
        
        if aUp.RdOff == aUp.WrOff:
            str = ctypes.create_string_buffer(0)

        elif aUp.RdOff < aUp.WrOff:
            cnt = aUp.WrOff - aUp.RdOff
            str = ctypes.create_string_buffer(cnt)
            self.jlink.JLINKARM_ReadMem(ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt, str)
            
            aUp.RdOff += cnt
            
            self.jlink.JLINKARM_WriteU32(self.aUpAddr + 4*4, aUp.RdOff)

        else:
            cnt = aUp.SizeOfBuffer - aUp.RdOff
            str = ctypes.create_string_buffer(cnt)
            self.jlink.JLINKARM_ReadMem(ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt, str)
            
            aUp.RdOff = 0  #这样下次再读就会进入执行上个条件
            
            self.jlink.JLINKARM_WriteU32(self.aUpAddr + 4*4, aUp.RdOff)
        
        return str.raw
    
    def on_tmrRTT_timeout(self):
        if self.btnOpen.text() == u'关闭连接':
            try:
                self.rcvbuff += self.aUpRead()

                if self.txtMain.isVisible():
                    if self.chkHEXShow.isChecked():
                        text = ''.join('%02X ' %ord(c) for c in self.rcvbuff)

                    else:
                        text = self.rcvbuff

                    if len(self.txtMain.toPlainText()) > 25000: self.txtMain.clear()
                    self.txtMain.moveCursor(QtGui.QTextCursor.End)
                    self.txtMain.insertPlainText(text)

                    self.rcvbuff = b''

                else:
                    if self.rcvbuff.rfind(',') == -1: return
                    
                    d = [int(x) for x in self.rcvbuff[0:self.rcvbuff.rfind(',')].split(',')]
                    for x in d:
                        self.PlotData.pop(0)
                        self.PlotData.append(x)
                    self.PlotCurve.setData(range(1, len(self.PlotData)+1), self.PlotData)
                    self.qwtPlot.replot()

                    self.rcvbuff = self.rcvbuff[self.rcvbuff.rfind(',')+1:]

            except Exception as e:
                self.rcvbuff = b''
                self.txtMain.append('\n%s\n' %str(e))
    
    def aDownWrite(self, bytes):
        buf = ctypes.create_string_buffer(ctypes.sizeof(RingBuffer))
        self.jlink.JLINKARM_ReadMem(self.aDownAddr, ctypes.sizeof(RingBuffer), buf)

        aDown = RingBuffer.from_buffer(buf)
        
        if aDown.WrOff >= aDown.RdOff:
            if aDown.RdOff != 0: cnt = min(aDown.SizeOfBuffer - aDown.WrOff, len(bytes))
            else:                cnt = min(aDown.SizeOfBuffer - 1 - aDown.WrOff, len(bytes))    # 写入操作不能使得 aDown.WrOff == aDown.RdOff,以区分满和空
            str = ctypes.create_string_buffer(bytes[:cnt])
            self.jlink.JLINKARM_WriteMem(ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, cnt, str)
            
            aDown.WrOff += cnt
            if aDown.WrOff == aDown.SizeOfBuffer: aDown.WrOff = 0

            bytes = bytes[cnt:]

        if bytes and aDown.RdOff != 0 and aDown.RdOff != 1:     # != 0 确保 aDown.WrOff 折返回 0,!= 1 确保有空间可写入
            cnt = min(aDown.RdOff - 1 - aDown.WrOff, len(bytes))    # - 1 确保写入操作不导致WrOff与RdOff指向同一位置
            str = ctypes.create_string_buffer(bytes[:cnt])
            self.jlink.JLINKARM_WriteMem(ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, cnt, str)

            aDown.WrOff += cnt

        self.jlink.JLINKARM_WriteU32(self.aDownAddr + 4*3, aDown.WrOff)

    @QtCore.pyqtSlot()
    def on_btnSend_clicked(self):
        if self.btnOpen.text() == u'关闭连接':
            text = self.txtSend.toPlainText()

            try:
                if self.chkHEXSend.isChecked():
                    bytes = ''.join([chr(int(x, 16)) for x in text.split()])

                else:
                    bytes = text

                self.aDownWrite(bytes)

            except Exception as e:
                self.txtMain.append('\n%s\n' %str(e))

    @QtCore.pyqtSlot()
    def on_btnDLL_clicked(self):
        path = QtGui.QFileDialog.getOpenFileName(caption=u'JLinkARM.dll路径', filter=u'动态链接库文件 (*.dll)', directory=self.linDLL.text())
        if path != '':
            self.linDLL.setText(path)

    @QtCore.pyqtSlot(int)
    def on_chkWavShow_stateChanged(self, state):
        self.qwtPlot.setVisible(state == QtCore.Qt.Checked)
        self.txtMain.setVisible(state == QtCore.Qt.Unchecked)

    @QtCore.pyqtSlot()
    def on_btnClear_clicked(self):
        self.txtMain.clear()
    
    def closeEvent(self, evt):
        self.conf.set('J-Link', 'dllpath', self.linDLL.text().encode('gbk'))
        self.conf.write(open('setting.ini', 'w'))
Ejemplo n.º 4
0
class RTTView(QtGui.QWidget):
    def __init__(self, parent=None):
        super(RTTView, self).__init__(parent)

        uic.loadUi('RTTView.ui', self)

        self.initSetting()

        self.initQwtPlot()

        self.rcvbuff = b''

        self.daplink = None

        self.tmrRTT = QtCore.QTimer()
        self.tmrRTT.setInterval(10)
        self.tmrRTT.timeout.connect(self.on_tmrRTT_timeout)
        self.tmrRTT.start()

        self.tmrRTT_Cnt = 0

    def initSetting(self):
        if not os.path.exists('setting.ini'):
            open('setting.ini', 'w')

        self.conf = ConfigParser.ConfigParser()
        self.conf.read('setting.ini')

        if not self.conf.has_section('Memory'):
            self.conf.add_section('Memory')
            self.conf.set('Memory', 'StartAddr', '0x20000000')

    def initQwtPlot(self):
        self.PlotData = [0] * 1000

        self.qwtPlot = QwtPlot(self)
        self.qwtPlot.setVisible(False)
        self.vLayout.insertWidget(0, self.qwtPlot)

        self.PlotCurve = QwtPlotCurve()
        self.PlotCurve.attach(self.qwtPlot)
        self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData)

    @QtCore.pyqtSlot()
    def on_btnOpen_clicked(self):
        if self.btnOpen.text() == u'打开连接':
            try:
                self.daplink = self.daplinks[self.cmbDAP.currentText()]
                self.daplink.open()

                dp = coresight.dap.DebugPort(self.daplink, None)
                dp.init()
                dp.power_up_debug()

                ap = coresight.ap.AHB_AP(dp, 0)
                ap.init()

                self.dap = coresight.cortex_m.CortexM(None, ap)

                Addr = int(self.conf.get('Memory', 'StartAddr'), 16)
                for i in range(256):
                    buff = self.dap.read_memory_block8(Addr + 1024 * i, 1024)
                    buff = ''.join([chr(x) for x in buff])
                    index = buff.find('SEGGER RTT')
                    if index != -1:
                        self.RTTAddr = Addr + 1024 * i + index

                        buff = self.dap.read_memory_block8(
                            self.RTTAddr, ctypes.sizeof(SEGGER_RTT_CB))

                        rtt_cb = SEGGER_RTT_CB.from_buffer(bytearray(buff))
                        self.aUpAddr = self.RTTAddr + 16 + 4 + 4
                        self.aDownAddr = self.aUpAddr + ctypes.sizeof(
                            RingBuffer) * rtt_cb.MaxNumUpBuffers

                        self.txtMain.append(
                            '\n_SEGGER_RTT @ 0x%08X with %d aUp and %d aDown\n'
                            % (self.RTTAddr, rtt_cb.MaxNumUpBuffers,
                               rtt_cb.MaxNumDownBuffers))
                        break
                else:
                    raise Exception('Can not find _SEGGER_RTT')
            except Exception as e:
                self.txtMain.append('\n%s\n' % str(e))
            else:
                self.cmbDAP.setEnabled(False)
                self.btnOpen.setText(u'关闭连接')
        else:
            self.daplink.close()
            self.cmbDAP.setEnabled(True)
            self.btnOpen.setText(u'打开连接')

    def aUpRead(self):
        buf = self.dap.read_memory_block8(self.aUpAddr,
                                          ctypes.sizeof(RingBuffer))
        aUp = RingBuffer.from_buffer(bytearray(buf))

        if aUp.RdOff == aUp.WrOff:
            buf = []

        elif aUp.RdOff < aUp.WrOff:
            cnt = aUp.WrOff - aUp.RdOff
            buf = self.dap.read_memory_block8(
                ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff,
                cnt)

            aUp.RdOff += cnt

            self.dap.write32(self.aUpAddr + 4 * 4, aUp.RdOff)

        else:
            cnt = aUp.SizeOfBuffer - aUp.RdOff
            buf = self.dap.read_memory_block8(
                ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff,
                cnt)

            aUp.RdOff = 0  #这样下次再读就会进入执行上个条件

            self.dap.write32(self.aUpAddr + 4 * 4, aUp.RdOff)

        return ''.join([chr(x) for x in buf])

    def on_tmrRTT_timeout(self):
        if self.btnOpen.text() == u'关闭连接':
            try:
                self.rcvbuff += self.aUpRead()

                if self.txtMain.isVisible():
                    if self.chkHEXShow.isChecked():
                        text = ''.join('%02X ' % ord(c) for c in self.rcvbuff)
                    else:
                        text = self.rcvbuff

                    if len(self.txtMain.toPlainText()) > 25000:
                        self.txtMain.clear()
                    self.txtMain.moveCursor(QtGui.QTextCursor.End)
                    self.txtMain.insertPlainText(text)

                    self.rcvbuff = b''

                else:
                    if self.rcvbuff.rfind(',') == -1: return

                    d = [
                        int(x) for x in
                        self.rcvbuff[0:self.rcvbuff.rfind(',')].split(',')
                    ]
                    for x in d:
                        self.PlotData.pop(0)
                        self.PlotData.append(x)
                    self.PlotCurve.setData(range(1,
                                                 len(self.PlotData) + 1),
                                           self.PlotData)
                    self.qwtPlot.replot()

                    self.rcvbuff = self.rcvbuff[self.rcvbuff.rfind(',') + 1:]

            except Exception as e:
                self.rcvbuff = b''
                self.txtMain.append('\n%s\n' % str(e))

        else:
            self.tmrRTT_Cnt += 1
            if self.tmrRTT_Cnt % 20 == 0:
                self.detect_daplink()  # 自动检测 DAPLink 的热插拔

    def aDownWrite(self, bytes):
        buf = self.dap.read_memory_block8(self.aDownAddr,
                                          ctypes.sizeof(RingBuffer))
        aDown = RingBuffer.from_buffer(bytearray(buf))

        if aDown.WrOff >= aDown.RdOff:
            if aDown.RdOff != 0:
                cnt = min(aDown.SizeOfBuffer - aDown.WrOff, len(bytes))
            else:
                cnt = min(
                    aDown.SizeOfBuffer - 1 - aDown.WrOff,
                    len(bytes))  # 写入操作不能使得 aDown.WrOff == aDown.RdOff,以区分满和空
            self.dap.write_memory_block8(
                ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value +
                aDown.WrOff, [ord(x) for x in bytes[:cnt]])

            aDown.WrOff += cnt
            if aDown.WrOff == aDown.SizeOfBuffer: aDown.WrOff = 0

            bytes = bytes[cnt:]

        if bytes and aDown.RdOff != 0 and aDown.RdOff != 1:  # != 0 确保 aDown.WrOff 折返回 0,!= 1 确保有空间可写入
            cnt = min(aDown.RdOff - 1 - aDown.WrOff,
                      len(bytes))  # - 1 确保写入操作不导致WrOff与RdOff指向同一位置
            self.dap.write_memory_block8(
                ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value +
                aDown.WrOff, [ord(x) for x in bytes[:cnt]])

            aDown.WrOff += cnt

        self.dap.write32(self.aDownAddr + 4 * 3, aDown.WrOff)

    @QtCore.pyqtSlot()
    def on_btnSend_clicked(self):
        if self.btnOpen.text() == u'关闭连接':
            text = self.txtSend.toPlainText()

            try:
                if self.chkHEXSend.isChecked():
                    bytes = ''.join([chr(int(x, 16)) for x in text.split()])

                else:
                    bytes = text

                self.aDownWrite(bytes)

            except Exception as e:
                self.txtMain.append('\n%s\n' % str(e))

    def detect_daplink(self):
        daplinks = aggregator.DebugProbeAggregator.get_all_connected_probes()

        if len(daplinks) != self.cmbDAP.count():
            self.cmbDAP.clear()
            for daplink in daplinks:
                self.cmbDAP.addItem(daplink.product_name)

            self.daplinks = collections.OrderedDict([
                (daplink.product_name, daplink) for daplink in daplinks
            ])

            if self.daplink and self.daplink.product_name in self.daplinks:
                self.cmbDAP.setCurrentIndex(self.daplinks.keys().index(
                    self.daplink.product_name))
            else:  # daplink被拔掉
                self.btnOpen.setText(u'打开连接')

    @QtCore.pyqtSlot(int)
    def on_chkWavShow_stateChanged(self, state):
        self.qwtPlot.setVisible(state == QtCore.Qt.Checked)
        self.txtMain.setVisible(state == QtCore.Qt.Unchecked)

    @QtCore.pyqtSlot()
    def on_btnClear_clicked(self):
        self.txtMain.clear()

    def closeEvent(self, evt):
        self.conf.write(open('setting.ini', 'w'))