[chronojump] Add firmware recorder to the build system



commit 2d94e54e2d105fe8ac742f9acf24ad88362866e1
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Tue Jun 15 22:03:19 2010 +0200

    Add firmware recorder to the build system

 Makefile.am                                        |    4 +-
 chronopic-firmware/Makefile.am                     |    5 +
 .../chronopic-firmwarecord/Makefile.am             |    5 +
 .../chronopic-firmwarecord.in                      |  456 ++++++++++++++++++++
 .../chronopic-firmwarecord/libIris/Makefile.am     |   14 +
 configure.ac                                       |    6 +
 6 files changed, 488 insertions(+), 2 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 150158f..979c6e7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,10 +3,10 @@ EXTRA_DIST = m4 expansions.m4
 ACLOCAL_AMFLAGS = -I m4
 
 if ENABLE_DEBUG
- SUBDIRS =  chronojump_server chronopic-tests   src po manual 
+ SUBDIRS = chronopic-firmware chronojump_server chronopic-tests   src po manual chronopic-firmware
 endif
 if ENABLE_RELEASE
- SUBDIRS = chronojump_server chronopic-tests   src po manual 
+ SUBDIRS = chronopic-firmware chronojump_server chronopic-tests   src po manual
 endif
 
 # Build ChangeLog from GIT history
diff --git a/chronopic-firmware/Makefile.am b/chronopic-firmware/Makefile.am
new file mode 100644
index 0000000..ae89cca
--- /dev/null
+++ b/chronopic-firmware/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+## Created by Anjuta
+
+SUBDIRS = chronopic-firmwarecord
+
diff --git a/chronopic-firmware/chronopic-firmwarecord/Makefile.am b/chronopic-firmware/chronopic-firmwarecord/Makefile.am
new file mode 100644
index 0000000..863e18c
--- /dev/null
+++ b/chronopic-firmware/chronopic-firmwarecord/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = libIris
+
+bin_SCRIPTS = chronopic-firmwarecord
+
+CLEANFILES = $(bin_SCRIPTS)
diff --git a/chronopic-firmware/chronopic-firmwarecord/chronopic-firmwarecord.in b/chronopic-firmware/chronopic-firmwarecord/chronopic-firmwarecord.in
new file mode 100755
index 0000000..c4d34d5
--- /dev/null
+++ b/chronopic-firmware/chronopic-firmwarecord/chronopic-firmwarecord.in
@@ -0,0 +1,456 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+# Description: Example of use of libIris
+# Copyright (C) 2007 by Rafael Treviño Menéndez
+# Author: Rafael Treviño Menéndez <skasi 7 gmail com>
+#         Juan Gonzalez <juan iearobotics com>
+#	  Xavier de Blas <xaviblas gmail com> (2010 adapted to Chronopic)
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 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
+# Library 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+
+import wx
+import sys
+import os
+import platform
+
+if platform.version() == 'Windows':
+    sys.path = ['..'] + sys.path
+else:
+    LIBDIR = '@expanded_libdir@'
+    root = os.path.join(LIBDIR, 'chronojump', 'python')
+    sys.path.insert(0, root)
+
+
+#---------------------------
+#-- Modulos de LibIris
+#---------------------------
+
+import libIris.Pic16_Bootloader
+import libIris.IntelHex
+import libIris.Pic16_Firmware
+
+#-- Timeout para la deteccion del bootloader (en segundos)
+#-- Si el programa previamente grabado utiliza el puerto serie
+#-- (por ejemplo el servidor de eco esta cargado) este tiempo ya
+#-- no es en segundos. 
+
+#-- con este timeout esta unos 25 segundos esperando cuando el servidor
+#-- de eco esta cargado (400 si no se usa el puerto serie)
+TIMEOUT = 800
+
+#----------------------------------------------
+#- Clase para realizar el Drag and Drop
+#----------------------------------------------
+class myDragDrog(wx.FileDropTarget):
+
+  #-- En el constructor se le pasa el frame principal
+  #-- Se usa para invocar el metodo download
+  def __init__(self,obj):
+    wx.FileDropTarget.__init__(self)
+    self.frame = obj
+
+  #-- Se invoca cada vez que se recibe la lista de ficheros arrastrados
+  #-- Solo se descarga el primer fichero de la lista recibida
+  def OnDropFiles(self,x,y, filenames):
+  
+    #-- Obtener el nombre del fichero (el primero de la lista)
+    file = filenames[0]
+   
+    #-- Meter el fichero en el entry "fichero .hex"
+    self.frame.text_ctrl_2.SetValue(file)
+    
+    #-- Activar la grabacion....
+    self.frame.update()
+    self.frame.download()
+    
+    return True
+
+#-------------------------------------------------------------------
+#--                  CLASE PRINCIPAL
+#-------------------------------------------------------------------
+class MyFrame(wx.Frame):
+    def __init__(self, app, *args, **kwds):
+    
+    
+        #----------------------------------------------------------------
+        #--- Esta parte del codigo se ha generado automaticamente con la
+        #-- herramienta wxglade. NO modificar.
+        #---------------------------------------------------------------
+        # begin wxGlade: MyFrame.__init__
+        kwds["style"] = wx.DEFAULT_FRAME_STYLE
+        wx.Frame.__init__(self, *args, **kwds)
+        self.panel_1 = wx.Panel(self, -1)
+        self.sizer_4_copy_staticbox = wx.StaticBox(self.panel_1, -1, "Port / Puerto")
+        self.sizer_2_staticbox = wx.StaticBox(self.panel_1, -1, "Process / Proceso")
+        self.sizer_4_staticbox = wx.StaticBox(self.panel_1, -1, "Firmware Chronopic")
+        self.frame_1_statusbar = self.CreateStatusBar(1, 0)
+        self.text_ctrl_2 = wx.TextCtrl(self.panel_1, -1, "")
+        self.button_2 = wx.Button(self.panel_1, -1, "Search / Buscar", style=wx.BU_EXACTFIT)
+        self.button_7 = wx.Button(self.panel_1, -1, "Record / Grabar", style=wx.BU_EXACTFIT)
+        self.combo_box_1 = wx.ComboBox(self.panel_1, -1, choices=[], style=wx.CB_DROPDOWN)
+        self.gauge_1 = wx.Gauge(self.panel_1, -1, 100)
+        self.button_6 = wx.Button(self.panel_1, -1, "Cancel / Cancelar")
+        self.button_8 = wx.Button(self.panel_1, -1, "Help / Ayuda")
+
+        self.__set_properties()
+        self.__do_layout()
+
+        self.Bind(wx.EVT_BUTTON, self.boton_abrir, self.button_2)
+        self.Bind(wx.EVT_BUTTON, self.boton_grabar, self.button_7)
+        self.Bind(wx.EVT_BUTTON, self.boton_cancelar, self.button_6)
+        self.Bind(wx.EVT_BUTTON, self.boton_ayuda, self.button_8)
+        # end wxGlade
+        #--------------------------------------------
+        # Fin del codigo generado automaticamente
+        #--------------------------------------------
+        
+        
+        #-- Guardar la aplicacion
+        self.app=app;
+        
+        #-- Para configurar para el drag-and-drop
+        test = myDragDrog(self)
+        self.SetDropTarget(test)
+        self.text_ctrl_2.SetDropTarget(myDragDrog(self))
+        self.combo_box_1.SetDropTarget(myDragDrog(self))
+        
+        #-- Establecer la habilitacion de los widgets
+        #-- Todos menos el boton de cancelar estan activos inicialmente
+        self.button_6.Disable()
+        
+    #----------------------------------------------------------------
+    #--- Esta parte del codigo se ha generado automaticamente con la
+    #-- herramienta wxglade. NO modificar.
+    #---------------------------------------------------------------
+
+    def __set_properties(self):
+        # begin wxGlade: MyFrame.__set_properties
+        self.SetTitle("Chronopic Firmware Updater")
+        self.frame_1_statusbar.SetStatusWidths([-1])
+        # statusbar fields
+        frame_1_statusbar_fields = ["Change / Cambiar Chronopic firmware"]
+        for i in range(len(frame_1_statusbar_fields)):
+            self.frame_1_statusbar.SetStatusText(frame_1_statusbar_fields[i], i)
+        self.text_ctrl_2.SetMinSize((250, 27))
+        self.combo_box_1.SetMinSize((250,30))
+        # end wxGlade
+
+    def __do_layout(self):
+        # begin wxGlade: MyFrame.__do_layout
+        sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_3 = wx.BoxSizer(wx.VERTICAL)
+        sizer_2 = wx.StaticBoxSizer(self.sizer_2_staticbox, wx.VERTICAL)
+        sizer_3.Add(self.button_8, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
+        sizer_4_copy = wx.StaticBoxSizer(self.sizer_4_copy_staticbox, wx.HORIZONTAL)
+        sizer_4 = wx.StaticBoxSizer(self.sizer_4_staticbox, wx.HORIZONTAL)
+        sizer_4.Add(self.text_ctrl_2, 0, wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5)
+        sizer_4.Add(self.button_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
+        sizer_3.Add(sizer_4, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
+        sizer_4_copy.Add(self.combo_box_1, 0, wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 5)
+        sizer_4_copy.Add(self.button_7, 0, wx.ALIGN_CENTER_VERTICAL, 0)
+        sizer_3.Add(sizer_4_copy, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
+        sizer_2.Add(self.gauge_1, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.EXPAND|wx.ADJUST_MINSIZE, 4)
+        sizer_2.Add((20, 10), 0, wx.ADJUST_MINSIZE, 0)
+        sizer_2.Add(self.button_6, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        sizer_3.Add(sizer_2, 1, wx.ALL|wx.EXPAND, 5)
+        self.panel_1.SetAutoLayout(True)
+        self.panel_1.SetSizer(sizer_3)
+        sizer_3.Fit(self.panel_1)
+        sizer_3.SetSizeHints(self.panel_1)
+        sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0)
+        self.SetAutoLayout(True)
+        self.SetSizer(sizer_1)
+        sizer_1.Fit(self)
+        sizer_1.SetSizeHints(self)
+        self.Layout()
+        # end wxGlade
+        #--------------------------------------------
+        # Fin del codigo generado automaticamente
+        #--------------------------------------------
+        
+
+    #------------------------------------------------------------------
+    #-- Funcion de retrollamada del boton de exploracion de ficheros  
+    #------------------------------------------------------------------
+    def boton_abrir(self, event): # wxGlade: MyFrame.<event_handler>
+       
+        #-- Abrir un dialogo de busqueda de ficheros
+        filechooser = wx.FileDialog(self,wildcard = "*.hex;*.HEX")
+        
+        #-- Esperar a que el usuario seleccione el fichero
+        opcion = filechooser.ShowModal()
+        
+        #-- Segun la opcion...
+        if opcion == wx.ID_OK:
+        
+          #-- Se ha pulsado ok. Obtener el nombre del fichero
+          fichero = filechooser.GetPath()
+         
+          #-- Meter el fichero en el entry "fichero .hex"
+          self.text_ctrl_2.SetValue(fichero)
+          
+        else: #-- No se ha seleccionado ninguno
+          print "Cancel..."
+        
+        
+    #-----------------------------------------------------------------
+    #-- Funciones de retrollamada de los diferentes botones 
+    #-----------------------------------------------------------------
+    def boton_grabar(self, event): # wxGlade: MyFrame.<event_handler>
+        self.download()
+        
+        
+    def boton_cancelar(self, event): # wxGlade: MyFrame.<event_handler>
+        self.cancelar = True  
+       
+    def boton_ayuda(self, event): # wxGlade: MyFrame.<event_handler>
+        dlg = wx.MessageDialog(self, "ENGLISH\n\nWith this tool you can change Chronopic Firmware whenever you want. It's recommended 50ms for jumps and 10ms for runs.\nTesting: 'ledp.hex' can be recorded and then green led will blink.\nIf you need more help please check forum:\nhttp://forum.chronojump.org\n\n\nESPA�OL\n\nCon esta herramienta puede cambiar el Firmware de Chronopic tantas veces como quiera. Se recomienda 50ms para saltos, 10 ms para carreras.\nSi desea testear la herramienta, puede grabar el archivo 'ledp.hex' y verá como la luz verde parpadea.\nSi necesita más ayuda, por favor use el foro:\nhttp://foro.chronojump.org";, "PyDownloader Help", wx.OK)
+	dlg.ShowModal()
+
+    def boton_eco(self, event): # wxGlade: MyFrame.<event_handler>
+        self.download_program(libIris.Pic16_Firmware.echo)
+       
+        
+    
+    #-------------------------------------
+    #-- Actualizar el interfaz
+    #-------------------------------------    
+    def update(self):
+      while (self.app.Pending()):
+          self.app.Dispatch();  
+    
+    #------------------------------------------------------------
+    #-- Activar todos los botones relacionados con la descarga
+    #-- El boton de cancel se desactiva
+    #------------------------------------------------------------    
+    def botones_modo_descarga(self):
+      #-- Cancelar: Deshabilitado
+      self.button_6.Disable()
+      #-- Resto: Habilitados
+      self.button_7.Enable()
+          
+    #-----------------------------------------------------------------------
+    #-- Desactivar todos los botones de descarga. El de cancelar se activa  
+    #-----------------------------------------------------------------------
+    def botones_modo_cancelar(self):
+      #-- Cancelar Activado, resto desactivados
+      self.button_6.Enable()
+      self.button_7.Disable()
+
+    #---------------------------------------------------------
+    #-- Metodo para descargar un fichero .hex en la skypic
+    #-- Se lee el nombre del fichero de la interfaz grafica
+    #---------------------------------------------------------
+    def download(self):
+      
+      #----------------------------------------
+      #-- Abrir y parsear el fichero .hex
+      #----------------------------------------
+      #-- Obtener el nombre
+      file = str(self.text_ctrl_2.GetLineText(0))
+      
+      #-- Si no hay ningun fichero especificado: Error
+      if file=="":
+        self.frame_1_statusbar.SetStatusText("Fichero .hex no especificado", 0)
+        return
+      
+      #-- Realizar el parseo
+      try:
+        hr = libIris.IntelHex.HexReader (file)
+      except libIris.IntelHex.ReaderError,msg:
+        #-- Convertir el mensaje a una cadena
+        msg = "%s" % msg
+        self.frame_1_statusbar.SetStatusText(msg, 0)
+        return      
+      
+      #----------------------------------
+      #-- Realizar la descarga!!
+      #----------------------------------
+      
+      #-- Obtener el programa en el formato correcto
+      program = hr.dataBlocks16()
+      
+      self.download_program(program)
+
+    #------------------------------------------------------------------------
+    #-- Funcion de retrollamada de libIris. Segun el estado de la descarga
+    #-- Se hace una cosa u otra
+    #------------------------------------------------------------------------
+    def state(self,op,inc,total):
+      #-----------------------------
+      #-- Comienzo de descarga
+      #-----------------------------
+      if op==libIris.Pic16_Bootloader.WRITING_START:
+  
+        #-- Barra de progreso a cero
+        self.gauge_1.SetValue(0)
+       
+        #-- Actualizar barra de status
+        self.frame_1_statusbar.SetStatusText("Recording / Grabando", 0)
+        self.update()
+        
+        return True
+        
+      
+      #------------------------------
+      #-- Incremento en la descarga  
+      #------------------------------    
+      elif op==libIris.Pic16_Bootloader.WRITING_INC:
+        self.gauge_1.SetValue(100*inc/total)
+        self.update()
+        
+        #-- Comprobar si se ha apretado boton de Cancelar
+        if self.cancelar:
+          return False
+          
+        return True  
+      
+      #-------------------------------
+      #-- Fin de la descarga
+      #-------------------------------
+      elif op==libIris.Pic16_Bootloader.WRITING_END: 
+        self.gauge_1.SetValue(100)
+        self.frame_1_statusbar.SetStatusText("Complete / Completado", 0)
+        self.update()
+        return True
+     
+      #---------------------------------------------------
+      #-- Comienzo de la identificacion del bootloader    
+      #---------------------------------------------------    
+      elif op==libIris.Pic16_Bootloader.IDENT_START:
+        #-- Hay que esperar a que detecte el Bootloader
+        self.frame_1_statusbar.SetStatusText("Press Reset on Chronopic / Pulse Reset en el Chronopic", 0)
+        self.update()
+        return True
+        
+        
+      #-----------------------------------------------------------------
+      #-- Respuesta no recibida del bootloader tras un mini-timeout    
+      #-----------------------------------------------------------------
+      elif op==libIris.Pic16_Bootloader.IDENT_NACK:
+      
+        #-- Mientras que el tiempo total acumulado sea menor que el 
+        #-- TIMEOUT indicado, continuar esperando
+        self.update()
+        
+        #-- Si apretado boton de cancelar abortar...
+        if self.cancelar:
+          return False
+        
+        if total<=TIMEOUT:
+         return True
+        else :
+          return False    
+
+
+    #----------------------------------------
+    #- Descargar un programa 
+    #----------------------------------------
+    def download_program(self,prog):
+    
+      #-- Poner la barra de progreso a 0
+      self.gauge_1.SetValue(0)
+      self.update()
+    
+      #-- Desactivar flag de cancelacion
+      self.cancelar=False
+      
+      #-- Si ya se habia abierto un puerto serie, cerrarlo
+      #-- Esto ha sido necesario ponerlo para que funcione
+      #-- bien en WINDOWS
+      if self.app.iris!=None:
+        self.app.iris.close()
+      
+      #------------------------------------
+      #-- Abrir puerto serie
+      #------------------------------------
+      #-- Primero obtener el nombre del dispositivo serie
+      serialName=self.combo_box_1.GetValue()
+      
+      try:
+        self.app.iris = libIris.Pic16_Bootloader.Iris(serialName,
+                                                      logCallback=None)
+      except libIris.Pic16_Bootloader.IrisError,msg:
+      
+        #-- Si hay error indicarlo en la barra de estado y abortar
+        msg = "%s" % msg
+        self.frame_1_statusbar.SetStatusText(msg, 0)
+        return
+      
+      #-- Actualizar la sensibilidad de los botones
+      self.botones_modo_cancelar()
+      self.update()
+      
+      try:
+        self.app.iris.download(prog,stateCallback=self.state)
+      except libIris.Pic16_Bootloader.IrisError,msg:
+        msg= "%s" % msg
+        self.frame_1_statusbar.SetStatusText(msg, 0)
+        
+        #-- Poner botones en su estado inicial:
+        self.botones_modo_descarga()
+        return
+        
+      #-- Poner botones en su estado inicial:
+      self.botones_modo_descarga()
+
+# end of class MyFrame
+
+
+#---------------------------------------------------------
+#-- Funcion para obtener  la lista de puerto serie
+#-- Esto depende de la plataforma en la que se ejecute
+#---------------------------------------------------------
+def getSerialPorts():
+
+  #-- Windows
+  if os.name == 'nt':
+    
+    #-- Se usan los nueve primeros puertos serie
+    return ["COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9"]
+    
+  #-- Linux  
+  elif os.name == 'posix':
+    return ["/dev/ttyUSB0","/dev/ttyUSB1"]
+
+  else:
+    return []
+
+
+class MyApp(wx.App):
+      
+    def OnInit(self):
+        self.iris=None
+        frame = MyFrame(self,None, -1, "")
+        frame.Show(True)
+        self.SetTopWindow(frame)
+        
+        #-- Anadir los nombres de los puertos serie al combobox
+        serialports = getSerialPorts()
+        for disp in serialports:
+          frame.combo_box_1.Append(disp) 
+            
+        return True
+
+
+def main():
+    app = MyApp(0)
+    app.MainLoop()
+
+
+if __name__ == "__main__":
+    main()
diff --git a/chronopic-firmware/chronopic-firmwarecord/libIris/Makefile.am b/chronopic-firmware/chronopic-firmwarecord/libIris/Makefile.am
new file mode 100644
index 0000000..c8a7c06
--- /dev/null
+++ b/chronopic-firmware/chronopic-firmwarecord/libIris/Makefile.am
@@ -0,0 +1,14 @@
+chronojumpdir = $(libdir)/chronojump/python/libIris
+
+chronojump_PYTHON =          \
+        __init__.py          \
+	IntelHex.py          \
+	Pic16_Bootloader.py  \
+	Pic16_Firmware.py
+
+TAGS_FILES = $(chronojump_PYTHON)
+
+clean-local:
+	rm -rf *.pyc *.pyo
+
+EXTRA_DIST = $(chronojump_PYTHON)
diff --git a/configure.ac b/configure.ac
index be551c6..de57124 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,6 +8,8 @@ AC_CONFIG_MACRO_DIR([m4])
 
 AM_PROG_LIBTOOL
 
+AM_PATH_PYTHON
+
 dnl Check for pkg-config
 AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
 if test "x$PKG_CONFIG" = "xno"; then
@@ -90,6 +92,10 @@ done
 
 AC_CONFIG_FILES([
 Makefile
+chronopic-firmware/Makefile
+chronopic-firmware/chronopic-firmwarecord/Makefile
+chronopic-firmware/chronopic-firmwarecord/libIris/Makefile
+chronopic-firmware/chronopic-firmwarecord/chronopic-firmwarecord
 chronopic-tests/Makefile
 src/Makefile
 po/Makefile



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]