Configtool: add the ability to build and upload.
This commit is contained in:
parent
d6b2a2293e
commit
b9f524d256
247
config.py
247
config.py
|
|
@ -7,8 +7,10 @@ import inspect
|
|||
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(
|
||||
inspect.currentframe()))[0]))
|
||||
|
||||
from configtool.settings import Settings
|
||||
from configtool.printerpanel import PrinterPanel
|
||||
from configtool.boardpanel import BoardPanel
|
||||
from configtool.build import Build, Upload
|
||||
from configtool.data import VERSION, reInclude
|
||||
|
||||
ID_LOAD_PRINTER = 1000
|
||||
|
|
@ -20,6 +22,8 @@ ID_SAVE_BOARD_AS = 1012
|
|||
ID_LOAD_CONFIG = 1020
|
||||
ID_LOAD_DEFAULT = 1021
|
||||
ID_SAVE_CONFIG = 1022
|
||||
ID_BUILD = 1030
|
||||
ID_UPLOAD = 1031
|
||||
|
||||
|
||||
class ConfigFrame(wx.Frame):
|
||||
|
|
@ -29,11 +33,13 @@ class ConfigFrame(wx.Frame):
|
|||
size = (880, 550))
|
||||
self.Bind(wx.EVT_CLOSE, self.onClose)
|
||||
|
||||
self.font = wx.Font(8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
|
||||
wx.FONTWEIGHT_BOLD)
|
||||
|
||||
panel = wx.Panel(self, -1)
|
||||
|
||||
self.settings = Settings(self, cmd_folder)
|
||||
self.settings.font = wx.Font(8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
|
||||
wx.FONTWEIGHT_BOLD)
|
||||
self.settings.folder = cmd_folder
|
||||
|
||||
self.heaters = []
|
||||
self.savePrtEna = False
|
||||
self.saveBrdEna = False
|
||||
|
|
@ -42,13 +48,19 @@ class ConfigFrame(wx.Frame):
|
|||
|
||||
self.nb = wx.Notebook(panel, wx.ID_ANY, size = (880, 550),
|
||||
style = wx.BK_DEFAULT)
|
||||
self.nb.SetFont(self.font)
|
||||
self.nb.SetFont(self.settings.font)
|
||||
|
||||
self.pgPrinter = PrinterPanel(self, self.nb, self.font, cmd_folder)
|
||||
self.nb.AddPage(self.pgPrinter, "Printer")
|
||||
self.printerFileName = None
|
||||
self.printerTabDecor = ""
|
||||
self.printerBaseText = "Printer"
|
||||
self.pgPrinter = PrinterPanel(self, self.nb, self.settings)
|
||||
self.nb.AddPage(self.pgPrinter, self.printerBaseText)
|
||||
|
||||
self.pgBoard = BoardPanel(self, self.nb, self.font, cmd_folder)
|
||||
self.nb.AddPage(self.pgBoard, "Board")
|
||||
self.boardFileName = None
|
||||
self.boardTabDecor = ""
|
||||
self.boardBaseText = "Board"
|
||||
self.pgBoard = BoardPanel(self, self.nb, self.settings)
|
||||
self.nb.AddPage(self.pgBoard, self.boardBaseText)
|
||||
|
||||
panel.Fit()
|
||||
|
||||
|
|
@ -65,10 +77,32 @@ class ConfigFrame(wx.Frame):
|
|||
|
||||
self.Destroy()
|
||||
|
||||
def setPrinterTabText(self, txt):
|
||||
def setPrinterTabFile(self, fn):
|
||||
self.printerFileName = fn
|
||||
self.updatePrinterTab()
|
||||
|
||||
def setPrinterTabDecor(self, prefix):
|
||||
self.printerTabDecor = prefix
|
||||
self.updatePrinterTab()
|
||||
|
||||
def updatePrinterTab(self):
|
||||
txt = self.printerTabDecor + self.printerBaseText
|
||||
if self.printerFileName:
|
||||
txt += " <%s>" % self.printerFileName
|
||||
self.nb.SetPageText(0, txt)
|
||||
|
||||
def setBoardTabText(self, txt):
|
||||
def setBoardTabFile(self, fn):
|
||||
self.boardFileName = fn
|
||||
self.updateBoardTab()
|
||||
|
||||
def setBoardTabDecor(self, prefix):
|
||||
self.boardTabDecor = prefix
|
||||
self.updateBoardTab()
|
||||
|
||||
def updateBoardTab(self):
|
||||
txt = self.boardTabDecor + self.boardBaseText
|
||||
if self.boardFileName:
|
||||
txt += " <%s>" % self.boardFileName
|
||||
self.nb.SetPageText(1, txt)
|
||||
|
||||
def setHeaters(self, ht):
|
||||
|
|
@ -81,10 +115,12 @@ class ConfigFrame(wx.Frame):
|
|||
file_menu.Append(ID_LOAD_CONFIG, "Load config.h",
|
||||
"Load config.h and its named printer and board files.")
|
||||
self.Bind(wx.EVT_MENU, self.onLoadConfig, id = ID_LOAD_CONFIG)
|
||||
file_menu.Enable(ID_LOAD_CONFIG, False)
|
||||
|
||||
file_menu.Append(ID_LOAD_DEFAULT, "Load default",
|
||||
"Load default config.h and its named printer and board files.")
|
||||
self.Bind(wx.EVT_MENU, self.onLoadDefault, id = ID_LOAD_DEFAULT)
|
||||
file_menu.Enable(ID_LOAD_DEFAULT, False)
|
||||
|
||||
file_menu.Append(ID_SAVE_CONFIG, "Save config.h", "Save config.h file.")
|
||||
self.Bind(wx.EVT_MENU, self.onSaveConfig, id = ID_SAVE_CONFIG)
|
||||
|
|
@ -98,13 +134,12 @@ class ConfigFrame(wx.Frame):
|
|||
|
||||
file_menu.Append(ID_SAVE_PRINTER, "Save printer",
|
||||
"Save printer configuration.")
|
||||
self.Bind(wx.EVT_MENU, self.pgPrinter.onSaveConfig, id = ID_SAVE_PRINTER)
|
||||
self.Bind(wx.EVT_MENU, self.onSavePrinterConfig, id = ID_SAVE_PRINTER)
|
||||
file_menu.Enable(ID_SAVE_PRINTER, False)
|
||||
|
||||
file_menu.Append(ID_SAVE_PRINTER_AS, "Save printer as...",
|
||||
"Save printer configuration to a new file.")
|
||||
self.Bind(wx.EVT_MENU, self.pgPrinter.onSaveConfigAs,
|
||||
id = ID_SAVE_PRINTER_AS)
|
||||
self.Bind(wx.EVT_MENU, self.onSavePrinterConfigAs, id = ID_SAVE_PRINTER_AS)
|
||||
file_menu.Enable(ID_SAVE_PRINTER_AS, False)
|
||||
|
||||
file_menu.AppendSeparator()
|
||||
|
|
@ -114,12 +149,12 @@ class ConfigFrame(wx.Frame):
|
|||
self.Bind(wx.EVT_MENU, self.pgBoard.onLoadConfig, id = ID_LOAD_BOARD)
|
||||
|
||||
file_menu.Append(ID_SAVE_BOARD, "Save board", "Save board configuration.")
|
||||
self.Bind(wx.EVT_MENU, self.pgBoard.onSaveConfig, id = ID_SAVE_BOARD)
|
||||
self.Bind(wx.EVT_MENU, self.onSaveBoardConfig, id = ID_SAVE_BOARD)
|
||||
file_menu.Enable(ID_SAVE_BOARD, False)
|
||||
|
||||
file_menu.Append(ID_SAVE_BOARD_AS, "Save board as...",
|
||||
"Save board configuration to a new file.")
|
||||
self.Bind(wx.EVT_MENU, self.pgBoard.onSaveConfigAs, id = ID_SAVE_BOARD_AS)
|
||||
self.Bind(wx.EVT_MENU, self.onSaveBoardConfigAs, id = ID_SAVE_BOARD_AS)
|
||||
file_menu.Enable(ID_SAVE_BOARD_AS, False)
|
||||
|
||||
file_menu.AppendSeparator()
|
||||
|
|
@ -133,7 +168,59 @@ class ConfigFrame(wx.Frame):
|
|||
|
||||
menu_bar.Append(file_menu, "&File")
|
||||
|
||||
build_menu = wx.Menu()
|
||||
|
||||
build_menu.Append(ID_BUILD, "Build", "Build the executable.")
|
||||
self.Bind(wx.EVT_MENU, self.onBuild, id = ID_BUILD)
|
||||
|
||||
build_menu.Append(ID_UPLOAD, "Upload", "Upload the executable.")
|
||||
self.Bind(wx.EVT_MENU, self.onUpload, id = ID_UPLOAD)
|
||||
|
||||
self.buildMenu = build_menu
|
||||
|
||||
menu_bar.Append(build_menu, "&Build")
|
||||
|
||||
self.SetMenuBar(menu_bar)
|
||||
self.checkEnableLoadConfig()
|
||||
self.checkEnableUpload()
|
||||
|
||||
def onSaveBoardConfig(self, evt):
|
||||
self.pgBoard.onSaveConfig(evt)
|
||||
self.checkEnableLoadConfig()
|
||||
|
||||
def onSaveBoardConfigAs(self, evt):
|
||||
self.pgBoard.onSaveConfigAs(evt)
|
||||
self.checkEnableLoadConfig()
|
||||
|
||||
def onSavePrinterConfig(self, evt):
|
||||
self.pgPrinter.onSaveConfig(evt)
|
||||
self.checkEnableLoadConfig()
|
||||
|
||||
def onSavePrinterConfigAs(self, evt):
|
||||
self.pgPrinter.onSaveConfigAs(evt)
|
||||
self.checkEnableLoadConfig()
|
||||
|
||||
def checkEnableLoadConfig(self):
|
||||
fn = os.path.join(cmd_folder, "config.h")
|
||||
if os.path.isfile(fn):
|
||||
self.fileMenu.Enable(ID_LOAD_CONFIG, True)
|
||||
self.buildMenu.Enable(ID_BUILD, True)
|
||||
else:
|
||||
self.fileMenu.Enable(ID_LOAD_CONFIG, False)
|
||||
self.buildMenu.Enable(ID_BUILD, False)
|
||||
|
||||
fn = os.path.join(cmd_folder, "config.default.h")
|
||||
if os.path.isfile(fn):
|
||||
self.fileMenu.Enable(ID_LOAD_DEFAULT, True)
|
||||
else:
|
||||
self.fileMenu.Enable(ID_LOAD_DEFAULT, False)
|
||||
|
||||
def checkEnableUpload(self):
|
||||
fn = os.path.join(cmd_folder, "teacup.hex")
|
||||
if os.path.isfile(fn):
|
||||
self.buildMenu.Enable(ID_UPLOAD, True)
|
||||
else:
|
||||
self.buildMenu.Enable(ID_UPLOAD, False)
|
||||
|
||||
def enableSavePrinter(self, flag):
|
||||
self.fileMenu.Enable(ID_SAVE_PRINTER, flag)
|
||||
|
|
@ -168,6 +255,23 @@ class ConfigFrame(wx.Frame):
|
|||
if not self.pgBoard.confirmLoseChanges("load config"):
|
||||
return
|
||||
|
||||
pfile, bfile = self.getConfigFileNames(fn)
|
||||
|
||||
if not pfile:
|
||||
self.message("Config file did not contain a printer file "
|
||||
"include statement.", "Config error")
|
||||
return
|
||||
|
||||
if not bfile:
|
||||
self.message("Config file did not contain a board file "
|
||||
"include statement.", "Config error")
|
||||
return
|
||||
|
||||
self.pgPrinter.loadConfigFile(pfile)
|
||||
|
||||
self.pgBoard.loadConfigFile(bfile)
|
||||
|
||||
def getConfigFileNames(self, fn):
|
||||
pfile = None
|
||||
bfile = None
|
||||
path = os.path.join(cmd_folder, fn)
|
||||
|
|
@ -203,19 +307,7 @@ class ConfigFrame(wx.Frame):
|
|||
self.message("Unable to parse include statement:\n%s" % ln,
|
||||
"Config error")
|
||||
|
||||
if not pfile:
|
||||
self.message("Config file did not contain a printer file include "
|
||||
"statement.", "Config error")
|
||||
return
|
||||
|
||||
if not bfile:
|
||||
self.message("Config file did not contain a board file include "
|
||||
"statement.", "Config error")
|
||||
return
|
||||
|
||||
self.pgPrinter.loadConfigFile(pfile)
|
||||
|
||||
self.pgBoard.loadConfigFile(bfile)
|
||||
return pfile, bfile
|
||||
|
||||
def onSaveConfig(self, evt):
|
||||
fn = os.path.join(cmd_folder, "config.h")
|
||||
|
|
@ -263,6 +355,105 @@ class ConfigFrame(wx.Frame):
|
|||
"%s successfully saved.\nconfig.h successfully saved.") % (rbfn, rpfn)
|
||||
self.message(m, "Save configuration success", wx.OK + wx.ICON_INFORMATION)
|
||||
|
||||
self.checkEnableLoadConfig()
|
||||
|
||||
def onBuild(self, evt):
|
||||
self.onBuildorUpload(True)
|
||||
|
||||
def onUpload(self, evt):
|
||||
self.onBuildorUpload(False)
|
||||
|
||||
def onBuildorUpload(self, buildFlag):
|
||||
if not (self.pgPrinter.hasData() or self.pgBoard.hasData()):
|
||||
dlg = wx.MessageDialog(self, "Data needs to be loaded. "
|
||||
"Click Yes to load config.h.",
|
||||
"Data missing",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if rc != wx.ID_YES:
|
||||
return
|
||||
|
||||
self.loadConfigFile("config.h")
|
||||
else:
|
||||
if self.pgPrinter.isModified():
|
||||
dlg = wx.MessageDialog(self, "Printer data needs to be saved. Click "
|
||||
"Yes to save printer configuration.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if rc != wx.ID_YES:
|
||||
return
|
||||
self.onSavePrinterConfig(None)
|
||||
|
||||
if self.pgBoard.isModified():
|
||||
dlg = wx.MessageDialog(self, "Board data needs to be saved. Click "
|
||||
"Yes to save board configuration.",
|
||||
"Changes pending",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if rc != wx.ID_YES:
|
||||
return
|
||||
self.onSaveBoardConfig(None)
|
||||
|
||||
if not self.verifyConfigLoaded():
|
||||
dlg = wx.MessageDialog(self, "Loaded configuration does not match what "
|
||||
"the config.h file. Click Yes to load "
|
||||
"config.h.",
|
||||
"Incorrect data loaded",
|
||||
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION)
|
||||
rc = dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
if rc != wx.ID_YES:
|
||||
return
|
||||
|
||||
self.loadConfigFile("config.h")
|
||||
|
||||
f_cpu, cpu, baud = self.pgBoard.getCPUInfo()
|
||||
if not cpu:
|
||||
dlg = wx.MessageDialog(self, "Unable to determine CPU type.",
|
||||
"CPU type error", wx.OK | wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
if not f_cpu:
|
||||
dlg = wx.MessageDialog(self, "Unable to determine CPU clock rate.",
|
||||
"CPU clock rate error", wx.OK | wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
if not baud:
|
||||
# TODO: It looks like serial port baud rate is confused with bootloader
|
||||
# baud rate here. These two can be the same, but don't have to.
|
||||
# Bootloader baud rate isn't user selectable, it's a property of
|
||||
# the bootloader and can be changed only by overwriting the
|
||||
# bootloader.
|
||||
dlg = wx.MessageDialog(self, "Unable to determine CPU baud rate.",
|
||||
"CPU baud rate error", wx.OK | wx.ICON_ERROR)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
return
|
||||
|
||||
if buildFlag:
|
||||
# TODO: building the executable needs no baud rate.
|
||||
dlg = Build(self, self.settings, f_cpu, cpu, baud)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
self.checkEnableUpload()
|
||||
else:
|
||||
dlg = Upload(self, self.settings, f_cpu, cpu, baud)
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
|
||||
def verifyConfigLoaded(self):
|
||||
pfile, bfile = self.getConfigFileNames("config.h")
|
||||
lpfile = self.pgPrinter.getFileName()
|
||||
lbfile = self.pgBoard.getFileName()
|
||||
|
||||
return ((pfile == lpfile) and (bfile == lbfile))
|
||||
|
||||
def message(self, text, title, style = wx.OK + wx.ICON_ERROR):
|
||||
dlg = wx.MessageDialog(self, text, title, style)
|
||||
dlg.ShowModal()
|
||||
|
|
|
|||
|
|
@ -5,20 +5,29 @@
|
|||
* *
|
||||
\***************************************************************************/
|
||||
|
||||
//PROCESSORS_START
|
||||
#ifndef __AVR_ATmega644__
|
||||
#ifndef __AVR_ATmega644P__
|
||||
#ifndef __AVR_ATmega1284__
|
||||
#ifndef __AVR_ATmega1284P__
|
||||
#error Wrong CPU type.
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
//PROCESSORS_END
|
||||
/** \def CPU_TYPE
|
||||
CPU types a user should be able to choose from in configtool. All
|
||||
commented out.
|
||||
*/
|
||||
//#define CPU_TYPE atmega644
|
||||
//#define CPU_TYPE atmega644p
|
||||
//#define CPU_TYPE atmega1284
|
||||
//#define CPU_TYPE atmega1284p
|
||||
|
||||
/** \def CPU
|
||||
CPU actually present on the board.
|
||||
*/
|
||||
#define CPU atmega1284p
|
||||
|
||||
/** \def F_CPU_OPT
|
||||
CPU clock frequencies a user should be able to choose from in configtool.
|
||||
All commented out.
|
||||
*/
|
||||
//#define F_CPU_OPT 16000000UL
|
||||
//#define F_CPU_OPT 20000000UL
|
||||
|
||||
/** \def F_CPU
|
||||
CPU clock rate. #ifndef required for Arduino compatibility.
|
||||
Actual CPU clock rate. #ifndef required for Arduino compatibility.
|
||||
*/
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 20000000UL
|
||||
|
|
|
|||
|
|
@ -5,16 +5,26 @@
|
|||
* *
|
||||
\***************************************************************************/
|
||||
|
||||
//PROCESSORS_START
|
||||
#ifndef __AVR_ATmega1280__
|
||||
#ifndef __AVR_ATmega2560__
|
||||
#error Wrong CPU type.
|
||||
#endif
|
||||
#endif
|
||||
//PROCESSORS_END
|
||||
/** \def CPU_TYPE
|
||||
CPU types a user should be able to choose from in configtool. All
|
||||
commented out.
|
||||
*/
|
||||
//#define CPU_TYPE atmega1280
|
||||
//#define CPU_TYPE atmega2560
|
||||
|
||||
/** \def CPU
|
||||
CPU actually present on the board.
|
||||
*/
|
||||
#define CPU atmega2560
|
||||
|
||||
/** \def F_CPU_OPT
|
||||
CPU clock frequencies a user should be able to choose from in configtool.
|
||||
All commented out.
|
||||
*/
|
||||
//#define F_CPU_OPT 16000000UL
|
||||
|
||||
/** \def F_CPU
|
||||
CPU clock rate. #ifndef required for Arduino compatibility.
|
||||
Actual CPU clock rate. #ifndef required for Arduino compatibility.
|
||||
*/
|
||||
#ifndef F_CPU
|
||||
#define F_CPU 16000000UL
|
||||
|
|
|
|||
|
|
@ -67,35 +67,32 @@ The start of a help text block is as follows:
|
|||
All subsequent lines are copied exactly as entered into the help text until
|
||||
the end delimiter is reached. The end delimiter is a line that starts with '*/'.
|
||||
|
||||
Note that it is possible to specify multiple names on the start line. This
|
||||
allows identical help text for similar or related fields.
|
||||
The names are the actual #define variable names and are used to associate the
|
||||
help text with a specific field. Note that it is possible to specify multiple
|
||||
names on the start line. This allows identical help text for similar or related
|
||||
fields.
|
||||
|
||||
|
||||
Processor Preamble - Board file
|
||||
-------------------------------
|
||||
|
||||
The utility parses out the processor types from the config file when it loads
|
||||
it, and it provides an interface where processors may be added or removed.
|
||||
When a file is saved, the utility needs to know 1) where to insert the new
|
||||
processor preamble, and 2) what to remove from the old file. To achieve this,
|
||||
there is a sequence that identifies the start of the processor preamble, and
|
||||
a sequence that indicates the end. As follows:
|
||||
The various CPU_TYPE lines define the options that the user can select from
|
||||
for CPU type. These must be legal values acceptable to avr-gcc for the -MMCU
|
||||
parameter. The CPU line is the currently chosen value from these options.
|
||||
|
||||
//PROCESSORS_START
|
||||
#ifndef __AVR_ATmega1280__
|
||||
#ifndef __AVR_ATmega2560__
|
||||
#error Wrong CPU type.
|
||||
#endif
|
||||
#endif
|
||||
//PROCESSORS_END
|
||||
Example:
|
||||
|
||||
when a file is saved, all of the lines between these two delimiters are removed
|
||||
and a new preamble is generated based on the values from the screen. The
|
||||
supported processor types are defined in a python list in the data.py file. As
|
||||
additional processors are supported, then can be added to this list.
|
||||
//#define CPU_TYPE atmega1280
|
||||
//#define CPU_TYPE atmega2560
|
||||
#define CPU atmega2560
|
||||
|
||||
If the START/END delimiters are not present, then the processor preamble will
|
||||
not be generated and the content from the original file will be retained.
|
||||
There can be multiple F_CPU_OPT lines specifying the various CPU clock values.
|
||||
The final F_CPU line shows the currently chose value from the options.
|
||||
|
||||
Example:
|
||||
|
||||
//#define F_CPU_OPT 16000000UL
|
||||
#define F_CPU 16000000UL
|
||||
|
||||
|
||||
Temperature Sensor Considerations - Board file
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
[configtool]
|
||||
|
||||
# Where to find the arduino tools (avr-gcc, avrdude, etc). This is only used
|
||||
# for windows. For linux it is assumed that the tools are available through
|
||||
# the normal PATH.
|
||||
arduinodir = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin
|
||||
|
||||
# Flags passed into the avr-gcc compiler. These flags can have 3 different
|
||||
# variabled embedded within them:
|
||||
#
|
||||
# %F_CPU% will be replaced by the value of the CPU Clock Rate entered
|
||||
# through the GUI.
|
||||
#
|
||||
# %CPU% will be replaced by the value of the CPU entered through the GUI.
|
||||
#
|
||||
# %ALNAME% is the name of the source file being compiled with the .c
|
||||
# extension replaced by .al.
|
||||
#
|
||||
# Note: the flag -save-temps=obj does not appear to be a valid flag for win32.
|
||||
# Omit the "=obj", or omit it entirely.
|
||||
cflags = -DF_CPU=%F_CPU% -mmcu=%CPU% -Wall -Wstrict-prototypes -std=gnu99
|
||||
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
-Winline -fno-move-loop-invariants -fno-tree-scev-cprop -Os
|
||||
-ffunction-sections -finline-functions-called-once -mcall-prologues
|
||||
-Wa,-adhlns=build/%ALNAME%
|
||||
|
||||
# Flags passed to avr-gcc to be passed on to the linker.
|
||||
ldflags = -Wl,--as-needed -Wl,--gc-sections
|
||||
|
||||
# Flags passed to avr-objcopy.
|
||||
objcopyflags = -j .text -j .data -O ihex -R .eeprom -R .fuse -R .lock
|
||||
|
||||
# The programmer type - passed to avrdude.
|
||||
programmer = stk500v2
|
||||
|
||||
# The port through which the firmware will be uploaded - passed to avrdude.
|
||||
port = /dev/ttyACM0
|
||||
|
|
@ -3,13 +3,13 @@ import os
|
|||
import wx
|
||||
import re
|
||||
|
||||
from configtool.data import (supportedCPUs, defineValueFormat,
|
||||
from configtool.data import (defineValueFormat,
|
||||
defineBoolFormat, defineHeaterFormat, reCommDefBL,
|
||||
reCommDefBoolBL, reHelpTextStart, reHelpTextEnd,
|
||||
reStartSensors, reEndSensors, reStartHeaters,
|
||||
reEndHeaters, reStartProcessors, reEndProcessors,
|
||||
reCandHeatPins, reCandThermPins, reFloatAttr,
|
||||
reAVR, reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reEndHeaters, reCandHeatPins, reCandThermPins,
|
||||
reCandProcessors, reCandCPUClocks, reFloatAttr,
|
||||
reDefine, reDefineBL, reDefQS, reDefQSm,
|
||||
reDefQSm2, reDefBool, reDefBoolBL, reDefHT,
|
||||
reDefTS, reHeater, reSensor3, reSensor4)
|
||||
from configtool.pinoutspage import PinoutsPage
|
||||
|
|
@ -20,32 +20,32 @@ from configtool.cpupage import CpuPage
|
|||
|
||||
|
||||
class BoardPanel(wx.Panel):
|
||||
def __init__(self, parent, nb, font, folder):
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
self.settings = settings
|
||||
|
||||
self.configFile = None
|
||||
|
||||
self.cfgValues = {}
|
||||
self.heaters = []
|
||||
self.sensors = []
|
||||
self.processors = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
self.dir = os.path.join(folder, "config")
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21),
|
||||
style = wx.BK_DEFAULT)
|
||||
self.nb.SetFont(font)
|
||||
self.nb.SetFont(self.settings.font)
|
||||
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
|
||||
self.pgCpu = CpuPage(self, self.nb, len(self.pages), font)
|
||||
self.pgCpu = CpuPage(self, self.nb, len(self.pages), self.settings.font)
|
||||
text = "CPU"
|
||||
self.nb.AddPage(self.pgCpu, text)
|
||||
self.pages.append(self.pgCpu)
|
||||
|
|
@ -53,7 +53,8 @@ class BoardPanel(wx.Panel):
|
|||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
|
||||
self.pgPins = PinoutsPage(self, self.nb, len(self.pages), font)
|
||||
self.pgPins = PinoutsPage(self, self.nb, len(self.pages),
|
||||
self.settings.font)
|
||||
text = "Pinouts"
|
||||
self.nb.AddPage(self.pgPins, text)
|
||||
self.pages.append(self.pgPins)
|
||||
|
|
@ -61,7 +62,8 @@ class BoardPanel(wx.Panel):
|
|||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
|
||||
self.pgSensors = SensorsPage(self, self.nb, len(self.pages), font)
|
||||
self.pgSensors = SensorsPage(self, self.nb, len(self.pages),
|
||||
self.settings.font)
|
||||
text = "Temperature Sensors"
|
||||
self.nb.AddPage(self.pgSensors, text)
|
||||
self.pages.append(self.pgSensors)
|
||||
|
|
@ -69,7 +71,8 @@ class BoardPanel(wx.Panel):
|
|||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
|
||||
self.pgHeaters = HeatersPage(self, self.nb, len(self.pages), font)
|
||||
self.pgHeaters = HeatersPage(self, self.nb, len(self.pages),
|
||||
self.settings.font)
|
||||
text = "Heaters"
|
||||
self.nb.AddPage(self.pgHeaters, text)
|
||||
self.pages.append(self.pgHeaters)
|
||||
|
|
@ -78,7 +81,7 @@ class BoardPanel(wx.Panel):
|
|||
self.pageValid.append(True)
|
||||
|
||||
self.pgCommunications = CommunicationsPage(self, self.nb, len(self.pages),
|
||||
font)
|
||||
self.settings.font)
|
||||
text = "Communications"
|
||||
self.nb.AddPage(self.pgCommunications, text)
|
||||
self.pages.append(self.pgCommunications)
|
||||
|
|
@ -91,6 +94,23 @@ class BoardPanel(wx.Panel):
|
|||
self.SetSizer(sz)
|
||||
self.Fit()
|
||||
|
||||
def getCPUInfo(self):
|
||||
vF_CPU = None
|
||||
if 'F_CPU' in self.cfgValues.keys():
|
||||
vF_CPU = self.cfgValues['F_CPU']
|
||||
|
||||
vCPU = None
|
||||
if 'CPU' in self.cfgValues.keys():
|
||||
vCPU = self.cfgValues['CPU']
|
||||
|
||||
# TODO: this is probably obsolete, because the build process doesn't need
|
||||
# the firmware baud rate, but the bootloader baud rate.
|
||||
vBaud = None
|
||||
if 'BAUD' in self.cfgValues.keys():
|
||||
vBaud = self.cfgValues['BAUD']
|
||||
|
||||
return vF_CPU, vCPU, vBaud
|
||||
|
||||
def assertModified(self, pg, flag = True):
|
||||
self.pageModified[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
|
@ -98,6 +118,9 @@ class BoardPanel(wx.Panel):
|
|||
def isModified(self):
|
||||
return (True in self.pageModified)
|
||||
|
||||
def hasData(self):
|
||||
return (self.configFile != None)
|
||||
|
||||
def getFileName(self):
|
||||
return self.configFile
|
||||
|
||||
|
|
@ -121,6 +144,15 @@ class BoardPanel(wx.Panel):
|
|||
pfx = ""
|
||||
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setBoardTabDecor(pfx)
|
||||
|
||||
def setHeaters(self, ht):
|
||||
self.parent.setHeaters(ht)
|
||||
|
|
@ -190,6 +222,8 @@ class BoardPanel(wx.Panel):
|
|||
self.heaters = []
|
||||
self.candHeatPins = []
|
||||
self.candThermPins = []
|
||||
self.candProcessors = []
|
||||
self.candClocks = []
|
||||
gatheringHelpText = False
|
||||
helpTextString = ""
|
||||
helpKey = None
|
||||
|
|
@ -242,33 +276,20 @@ class BoardPanel(wx.Panel):
|
|||
self.candHeatPins.append(t[0])
|
||||
continue
|
||||
|
||||
continue
|
||||
m = reCandProcessors.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candProcessors.append(t[0])
|
||||
continue
|
||||
|
||||
if ln.lstrip().startswith("#if"):
|
||||
m = re.findall(reAVR, ln)
|
||||
inv = []
|
||||
for p in m:
|
||||
if p in supportedCPUs:
|
||||
self.processors.append(p)
|
||||
else:
|
||||
inv.append(p)
|
||||
if len(inv) > 0:
|
||||
if len(inv) == 1:
|
||||
a = " is"
|
||||
b = "it"
|
||||
else:
|
||||
a = "s are"
|
||||
b = "them"
|
||||
dlg = wx.MessageDialog(self,
|
||||
("The following processor type%s not "
|
||||
"supported:\n %s\nPlease add %s to "
|
||||
"\"supportedCPUs\".") %
|
||||
(a, ", ".join(inv), b),
|
||||
"Unsupported processor type",
|
||||
wx.OK + wx.ICON_INFORMATION)
|
||||
m = reCandCPUClocks.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
if len(t) == 1:
|
||||
self.candClocks.append(t[0])
|
||||
continue
|
||||
|
||||
dlg.ShowModal()
|
||||
dlg.Destroy()
|
||||
continue
|
||||
|
||||
if ln.lstrip().startswith("#define"):
|
||||
|
|
@ -322,9 +343,11 @@ class BoardPanel(wx.Panel):
|
|||
continue
|
||||
|
||||
self.parent.enableSaveBoard(True)
|
||||
self.parent.setBoardTabText("Board <%s>" % os.path.basename(fn))
|
||||
self.parent.setBoardTabFile(os.path.basename(fn))
|
||||
self.pgHeaters.setCandidatePins(self.candHeatPins)
|
||||
self.pgSensors.setCandidatePins(self.candThermPins)
|
||||
self.pgCpu.setCandidateProcessors(self.candProcessors)
|
||||
self.pgCpu.setCandidateClocks(self.candClocks)
|
||||
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.cfgValues)
|
||||
|
|
@ -332,7 +355,6 @@ class BoardPanel(wx.Panel):
|
|||
|
||||
self.pgSensors.setSensors(self.sensors)
|
||||
self.pgHeaters.setHeaters(self.heaters)
|
||||
self.pgCpu.setProcessors(self.processors)
|
||||
|
||||
return True
|
||||
|
||||
|
|
@ -415,11 +437,8 @@ class BoardPanel(wx.Panel):
|
|||
for k in v1.keys():
|
||||
values[k] = v1[k]
|
||||
|
||||
self.processors = self.pgCpu.getProcessors()
|
||||
|
||||
skipToSensorEnd = False
|
||||
skipToHeaterEnd = False
|
||||
skipToProcessorEnd = False
|
||||
for ln in self.cfgBuffer:
|
||||
m = reStartSensors.match(ln)
|
||||
if m:
|
||||
|
|
@ -457,26 +476,6 @@ class BoardPanel(wx.Panel):
|
|||
skipToHeaterEnd = False
|
||||
continue
|
||||
|
||||
m = reStartProcessors.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
for i in range(len(self.processors)):
|
||||
fp.write("%s#ifndef __AVR_%s__\n" % (i * " ", self.processors[i]))
|
||||
fp.write("%s#error Wrong CPU type.\n" % ((i + 1) * " "))
|
||||
for s in self.processors:
|
||||
fp.write("%s#endif\n" % (i * " "))
|
||||
i -= 1
|
||||
|
||||
skipToProcessorEnd = True
|
||||
continue
|
||||
|
||||
if skipToProcessorEnd:
|
||||
m = reEndProcessors.match(ln)
|
||||
if m:
|
||||
fp.write(ln)
|
||||
skipToProcessorEnd = False
|
||||
continue
|
||||
|
||||
m = reDefineBL.match(ln)
|
||||
if m:
|
||||
t = m.groups()
|
||||
|
|
@ -525,6 +524,6 @@ class BoardPanel(wx.Panel):
|
|||
|
||||
fp.close()
|
||||
|
||||
self.parent.setBoardTabText("Board <%s>" % os.path.basename(path))
|
||||
self.parent.setBoardTabFile(os.path.basename(path))
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -0,0 +1,309 @@
|
|||
|
||||
import wx
|
||||
import wx.lib.newevent
|
||||
import thread, shlex, subprocess
|
||||
import os
|
||||
from os.path import isfile, join
|
||||
from sys import platform
|
||||
|
||||
if platform == "win32":
|
||||
from _subprocess import STARTF_USESHOWWINDOW
|
||||
|
||||
(scriptEvent, EVT_SCRIPT_UPDATE) = wx.lib.newevent.NewEvent()
|
||||
SCRIPT_RUNNING = 1
|
||||
SCRIPT_FINISHED = 2
|
||||
SCRIPT_CANCELLED = 3
|
||||
|
||||
|
||||
class ScriptThread:
|
||||
def __init__(self, win, script):
|
||||
self.win = win
|
||||
self.running = False
|
||||
self.cancelled = False
|
||||
self.script = script
|
||||
|
||||
def Start(self):
|
||||
self.running = True
|
||||
self.cancelled = False
|
||||
thread.start_new_thread(self.Run, ())
|
||||
|
||||
def Stop(self):
|
||||
self.cancelled = True
|
||||
|
||||
def IsRunning(self):
|
||||
return self.running
|
||||
|
||||
def Run(self):
|
||||
if platform == "win32":
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
||||
|
||||
for cmd in self.script:
|
||||
evt = scriptEvent(msg = cmd, state = SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
args = shlex.split(str(cmd))
|
||||
try:
|
||||
if platform == "win32":
|
||||
p = subprocess.Popen(args, stderr = subprocess.STDOUT,
|
||||
stdout = subprocess.PIPE,
|
||||
startupinfo = startupinfo)
|
||||
else:
|
||||
p = subprocess.Popen(args, stderr = subprocess.STDOUT,
|
||||
stdout = subprocess.PIPE)
|
||||
except:
|
||||
evt = scriptEvent(msg = "Exception occurred trying to run\n\n%s" % cmd,
|
||||
state = SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
obuf = ''
|
||||
while not self.cancelled:
|
||||
o = p.stdout.read(1)
|
||||
if o == '': break
|
||||
if o == '\r' or o == '\n':
|
||||
if obuf.strip() != "":
|
||||
evt = scriptEvent(msg = obuf, state = SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
obuf = ''
|
||||
elif ord(o) < 32:
|
||||
pass
|
||||
else:
|
||||
obuf += o
|
||||
|
||||
if self.cancelled:
|
||||
evt = scriptEvent(msg = None, state = SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
p.kill()
|
||||
self.running = False
|
||||
return
|
||||
|
||||
rc = p.wait()
|
||||
if rc != 0:
|
||||
msg = "RC = " + str(rc) + " - Build terminated"
|
||||
evt = scriptEvent(msg = msg, state = SCRIPT_CANCELLED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
self.running = False
|
||||
return
|
||||
|
||||
evt = scriptEvent(msg = "", state = SCRIPT_RUNNING)
|
||||
wx.PostEvent(self.win, evt)
|
||||
|
||||
evt = scriptEvent(msg = None, state = SCRIPT_FINISHED)
|
||||
wx.PostEvent(self.win, evt)
|
||||
|
||||
self.running = False
|
||||
|
||||
|
||||
class Build(wx.Dialog):
|
||||
def __init__(self, parent, settings, f_cpu, cpu, baud):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Build teacup",
|
||||
style = wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.baud = baud
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.AddSpacer((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.AddSpacer((10, 10))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
|
||||
style = wx.TE_READONLY + wx.TE_MULTILINE)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
self.log = tc
|
||||
|
||||
sz.AddSpacer((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.AddSpacer((10, 10))
|
||||
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
builddir = join(self.root, "build")
|
||||
if not os.path.exists(builddir):
|
||||
os.makedirs(builddir)
|
||||
self.log.AppendText("Directory (%s) created.\n\n" % builddir)
|
||||
|
||||
self.compile()
|
||||
|
||||
def compile(self):
|
||||
self.generateCompileScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to compile!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.compileUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
def link(self):
|
||||
self.generateLinkScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to link!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.linkUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
def generateCompileScript(self):
|
||||
self.script = []
|
||||
if platform == "win32":
|
||||
cmdpath = "\"" + join(self.settings.arduinodir, "avr-gcc") + "\""
|
||||
else:
|
||||
cmdpath = "avr-gcc"
|
||||
|
||||
cfiles = [f for f in os.listdir(self.root)
|
||||
if isfile(join(self.root,f)) and f.endswith(".c")]
|
||||
for f in cfiles:
|
||||
basename = f[:-2]
|
||||
ofile = basename + ".o"
|
||||
alfile = basename + ".al"
|
||||
opath = "\"" + join(self.root, "build", ofile) + "\""
|
||||
cpath = "\"" + join(self.root, f) + "\""
|
||||
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", alfile)
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
|
||||
cmd = cmdpath + " -c " + opts + " -o " + opath + " " + cpath
|
||||
self.script.append(cmd)
|
||||
|
||||
def generateLinkScript(self):
|
||||
self.script = []
|
||||
if platform == "win32":
|
||||
cmdpath = "\"" + join(self.settings.arduinodir, "avr-gcc") + "\""
|
||||
else:
|
||||
cmdpath = "avr-gcc"
|
||||
|
||||
ofiles = ["\"" + join(self.root, "build", f) + "\""
|
||||
for f in os.listdir(join(self.root, "build"))
|
||||
if isfile(join(self.root, "build", f)) and f.endswith(".o")]
|
||||
opath = " ".join(ofiles)
|
||||
elfpath = "\"" + join(self.root, "build", "teacup.elf") + "\""
|
||||
opts = self.settings.cflags
|
||||
opts = opts.replace("%ALNAME%", "teacup.elf")
|
||||
opts = opts.replace("%F_CPU%", self.f_cpu)
|
||||
opts = opts.replace("%CPU%", self.cpu)
|
||||
cmd = cmdpath + " " + self.settings.ldflags + " " + opts + " -o " + \
|
||||
elfpath + " " + opath + " -lm"
|
||||
self.script.append(cmd)
|
||||
|
||||
if platform == "win32":
|
||||
cmdpath = "\"" + join(self.settings.arduinodir, "avr-objcopy") + "\""
|
||||
else:
|
||||
cmdpath = "avr-objcopy"
|
||||
cmd = cmdpath + " " + self.settings.objcopyflags + " " + elfpath + \
|
||||
" teacup.hex"
|
||||
self.script.append(cmd)
|
||||
|
||||
def compileUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText("Compile terminated abnormally.\n\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Compile completed normally.\n\n")
|
||||
self.link()
|
||||
|
||||
def linkUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText("Link terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Link completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
return
|
||||
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
|
||||
class Upload(wx.Dialog):
|
||||
def __init__(self, parent, settings, f_cpu, cpu, baud):
|
||||
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Upload teacup",
|
||||
style = wx.RESIZE_BORDER + wx.DEFAULT_DIALOG_STYLE)
|
||||
self.settings = settings
|
||||
self.SetFont(self.settings.font)
|
||||
self.root = self.settings.folder
|
||||
self.f_cpu = f_cpu
|
||||
self.cpu = cpu
|
||||
self.baud = baud
|
||||
self.Bind(wx.EVT_CLOSE, self.onExit)
|
||||
|
||||
hsz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
hsz.AddSpacer((10, 10))
|
||||
|
||||
sz = wx.BoxSizer(wx.VERTICAL)
|
||||
sz.AddSpacer((10, 10))
|
||||
|
||||
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
|
||||
style = wx.TE_READONLY + wx.TE_MULTILINE)
|
||||
sz.Add(tc, 1, wx.EXPAND)
|
||||
self.log = tc
|
||||
|
||||
sz.AddSpacer((10, 10))
|
||||
hsz.Add(sz, 1, wx.EXPAND)
|
||||
hsz.AddSpacer((10, 10))
|
||||
|
||||
self.SetSizer(hsz)
|
||||
|
||||
self.Fit()
|
||||
self.generateUploadScript()
|
||||
if len(self.script) == 0:
|
||||
self.log.AppendText("Nothing to upload!\n")
|
||||
self.active = False
|
||||
else:
|
||||
self.Bind(EVT_SCRIPT_UPDATE, self.uploadUpdate)
|
||||
t = ScriptThread(self, self.script)
|
||||
self.active = True
|
||||
t.Start()
|
||||
|
||||
def generateUploadScript(self):
|
||||
self.script = []
|
||||
if platform == "win32":
|
||||
cmdpath = "\"" + join(self.settings.arduinodir, "avrdude") + "\""
|
||||
else:
|
||||
cmdpath = "avrdude"
|
||||
|
||||
cmd = cmdpath + " -c %s -b %s -p %s -P %s -U flash:w:teacup.hex" % \
|
||||
(self.settings.programmer, self.baud, self.cpu, self.settings.port)
|
||||
self.script.append(cmd)
|
||||
|
||||
def uploadUpdate(self, evt):
|
||||
if evt.msg is not None:
|
||||
self.log.AppendText(evt.msg + "\n")
|
||||
|
||||
if evt.state == SCRIPT_RUNNING:
|
||||
pass
|
||||
if evt.state == SCRIPT_CANCELLED:
|
||||
self.log.AppendText("Upload terminated abnormally.\n")
|
||||
self.active = False
|
||||
if evt.state == SCRIPT_FINISHED:
|
||||
self.log.AppendText("Upload completed normally.\n")
|
||||
self.active = False
|
||||
|
||||
def onExit(self, evt):
|
||||
if self.active:
|
||||
return
|
||||
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
import wx
|
||||
from configtool.page import Page
|
||||
from configtool.data import supportedCPUs
|
||||
|
||||
|
||||
class CpuPage(wx.Panel, Page):
|
||||
|
|
@ -11,64 +10,49 @@ class CpuPage(wx.Panel, Page):
|
|||
self.parent = parent
|
||||
self.id = idPg
|
||||
|
||||
self.labels = {'F_CPU': "CPU Clock Rate:"}
|
||||
self.defaultClock = '16000000UL'
|
||||
self.clocks = ['8000000UL', self.defaultClock, '20000000UL']
|
||||
self.labels = {'F_CPU': "CPU Clock Rate:", 'CPU': "Processor Type:"}
|
||||
self.clocks = []
|
||||
self.processors = []
|
||||
|
||||
sz = wx.GridBagSizer()
|
||||
sz.AddSpacer((20, 40), pos = (0, 0))
|
||||
|
||||
k = 'F_CPU'
|
||||
ch = self.addChoice(k, self.clocks, self.clocks.index(self.defaultClock),
|
||||
100, self.onChoice)
|
||||
ch = self.addChoice(k, self.clocks, 0, 100, self.onChoice)
|
||||
sz.Add(ch, pos = (1, 1))
|
||||
sz.AddSpacer((100, 10), pos = (1, 2))
|
||||
|
||||
b = wx.StaticBox(self, wx.ID_ANY, "Processor Type(s)")
|
||||
sbox = wx.StaticBoxSizer(b, wx.VERTICAL)
|
||||
|
||||
ht = "Choose the processor(s) this configuration will work with."
|
||||
for k in supportedCPUs:
|
||||
cb = self.addCheckBox(k, self.onCheckBox)
|
||||
cb.SetToolTipString(ht)
|
||||
sbox.Add(cb)
|
||||
sbox.AddSpacer((120, 5))
|
||||
|
||||
sbox.AddSpacer((5, 5))
|
||||
sz.Add(sbox, pos = (1, 3), span = (3, 1))
|
||||
k = 'CPU'
|
||||
ch = self.addChoice(k, self.processors, 0, 100, self.onChoice)
|
||||
sz.Add(ch, pos = (1, 3))
|
||||
|
||||
self.SetSizer(sz)
|
||||
self.enableAll(False)
|
||||
|
||||
def setProcessors(self, plist):
|
||||
def setCandidateProcessors(self, plist):
|
||||
k = 'CPU'
|
||||
self.choices[k].Clear()
|
||||
for p in plist:
|
||||
self.choices[k].Append(p)
|
||||
self.processors = plist
|
||||
for p in supportedCPUs:
|
||||
if p in self.processors:
|
||||
self.checkBoxes[p].SetValue(True)
|
||||
else:
|
||||
self.checkBoxes[p].SetValue(False)
|
||||
|
||||
def getProcessors(self):
|
||||
plist = []
|
||||
for p in supportedCPUs:
|
||||
if self.checkBoxes[p].IsChecked():
|
||||
plist.append(p)
|
||||
|
||||
return plist
|
||||
def setCandidateClocks(self, clist):
|
||||
k = 'F_CPU'
|
||||
self.choices[k].Clear()
|
||||
for c in clist:
|
||||
self.choices[k].Append(c)
|
||||
self.clocks = clist
|
||||
|
||||
def insertValues(self, cfgValues):
|
||||
self.assertValid(True)
|
||||
self.enableAll(True)
|
||||
|
||||
for k in self.fieldValid.keys():
|
||||
self.fieldValid[k] = True
|
||||
|
||||
for k in self.checkBoxes.keys():
|
||||
if k in cfgValues.keys() and cfgValues[k]:
|
||||
self.checkBoxes[k].SetValue(True)
|
||||
else:
|
||||
self.checkBoxes[k].SetValue(False)
|
||||
|
||||
self.setChoice('F_CPU', cfgValues, self.defaultClock)
|
||||
if len(self.clocks) > 0:
|
||||
self.setChoice('F_CPU', cfgValues, self.clocks[0])
|
||||
if len(self.processors) > 0:
|
||||
self.setChoice('CPU', cfgValues, self.processors[0])
|
||||
|
||||
self.assertModified(False)
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@ reStartSensors = re.compile("^\s*//\s*DEFINE_TEMP_SENSORS_START")
|
|||
reEndSensors = re.compile("^\s*//\s*DEFINE_TEMP_SENSORS_END")
|
||||
reStartHeaters = re.compile("^\s*//\s*DEFINE_HEATERS_START")
|
||||
reEndHeaters = re.compile("^\s*//\s*DEFINE_HEATERS_END")
|
||||
reStartProcessors = re.compile("^\s*//\s*PROCESSORS_START")
|
||||
reEndProcessors = re.compile("^\s*//\s*PROCESSORS_END")
|
||||
reCandHeatPins = re.compile("^\s*//\s*#define\s+HEATER_PIN\s+(\w+)")
|
||||
reCandThermPins = re.compile("^\s*//\s*#define\s+TEMP_SENSOR_PIN\s+(\w+)")
|
||||
reCandProcessors = re.compile("^\s*//\s*#define\s+CPU_TYPE\s+(\w+)")
|
||||
reCandCPUClocks = re.compile("^\s*//\s*#define\s+F_CPU_OPT\s+(\w+)")
|
||||
|
||||
reHelpTextStart = re.compile("^\s*/\*\*\s+\\\\def\s+(.*)")
|
||||
reHelpTextEnd = re.compile("^\s*\*/")
|
||||
|
|
@ -55,8 +55,6 @@ reHeater = re.compile(".*\\(\s*(\w+)\s*,\s*(\w+)\s*,\s*(\w+)\s*\\)")
|
|||
reInteger = re.compile("^\d+U?L?$")
|
||||
reFloat = re.compile("^\d+(\.\d*)?$")
|
||||
|
||||
reAVR = re.compile("__AVR_(\w+)__")
|
||||
|
||||
defineValueFormat = "#define %-24s %s\n"
|
||||
defineBoolFormat = "#define %s\n"
|
||||
defineHeaterFormat = "#define HEATER_%s HEATER_%s\n"
|
||||
|
|
|
|||
|
|
@ -14,28 +14,31 @@ from configtool.miscellaneouspage import MiscellaneousPage
|
|||
|
||||
|
||||
class PrinterPanel(wx.Panel):
|
||||
def __init__(self, parent, nb, font, folder):
|
||||
def __init__(self, parent, nb, settings):
|
||||
wx.Panel.__init__(self, nb, wx.ID_ANY)
|
||||
self.parent = parent
|
||||
|
||||
self.configFile = None
|
||||
|
||||
self.settings = settings
|
||||
|
||||
self.cfgValues = {}
|
||||
self.heaters = []
|
||||
self.dir = os.path.join(folder, "config")
|
||||
self.dir = os.path.join(self.settings.folder, "config")
|
||||
|
||||
sz = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21),
|
||||
style = wx.BK_DEFAULT)
|
||||
self.nb.SetFont(font)
|
||||
self.nb.SetFont(self.settings.font)
|
||||
|
||||
self.pages = []
|
||||
self.titles = []
|
||||
self.pageModified = []
|
||||
self.pageValid = []
|
||||
|
||||
self.pgMech = MechanicalPage(self, self.nb, len(self.pages), font)
|
||||
self.pgMech = MechanicalPage(self, self.nb, len(self.pages),
|
||||
self.settings.font)
|
||||
text = "Mechanical"
|
||||
self.nb.AddPage(self.pgMech, text)
|
||||
self.pages.append(self.pgMech)
|
||||
|
|
@ -43,7 +46,8 @@ class PrinterPanel(wx.Panel):
|
|||
self.pageModified.append(False)
|
||||
self.pageValid.append(True)
|
||||
|
||||
self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), font)
|
||||
self.pgAcc = AccelerationPage(self, self.nb, len(self.pages),
|
||||
self.settings.font)
|
||||
text = "Acceleration"
|
||||
self.nb.AddPage(self.pgAcc, text)
|
||||
self.pages.append(self.pgAcc)
|
||||
|
|
@ -52,7 +56,7 @@ class PrinterPanel(wx.Panel):
|
|||
self.pageValid.append(True)
|
||||
|
||||
self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages),
|
||||
font)
|
||||
self.settings.font)
|
||||
text = "Miscellaneous"
|
||||
self.nb.AddPage(self.pgMiscellaneous, text)
|
||||
self.pages.append(self.pgMiscellaneous)
|
||||
|
|
@ -75,6 +79,9 @@ class PrinterPanel(wx.Panel):
|
|||
def isModified(self):
|
||||
return (True in self.pageModified)
|
||||
|
||||
def hasData(self):
|
||||
return (self.configFile != None)
|
||||
|
||||
def assertValid(self, pg, flag = True):
|
||||
self.pageValid[pg] = flag
|
||||
self.modifyTab(pg)
|
||||
|
|
@ -95,6 +102,15 @@ class PrinterPanel(wx.Panel):
|
|||
pfx = ""
|
||||
|
||||
self.nb.SetPageText(pg, pfx + self.titles[pg])
|
||||
if True in self.pageModified and False in self.pageValid:
|
||||
pfx = "?* "
|
||||
elif True in self.pageModified:
|
||||
pfx = "* "
|
||||
elif False in self.pageValid:
|
||||
pfx = "? "
|
||||
else:
|
||||
pfx = ""
|
||||
self.parent.setPrinterTabDecor(pfx)
|
||||
|
||||
def setHeaters(self, ht):
|
||||
return self.pgMiscellaneous.setHeaters(ht)
|
||||
|
|
@ -229,7 +245,7 @@ class PrinterPanel(wx.Panel):
|
|||
self.cfgValues[t[0]] = True
|
||||
|
||||
self.parent.enableSavePrinter(True)
|
||||
self.parent.setPrinterTabText("Printer <%s>" % os.path.basename(fn))
|
||||
self.parent.setPrinterTabFile(os.path.basename(fn))
|
||||
|
||||
for pg in self.pages:
|
||||
pg.insertValues(self.cfgValues)
|
||||
|
|
@ -274,7 +290,7 @@ class PrinterPanel(wx.Panel):
|
|||
if self.saveConfigFile(path):
|
||||
dlg = wx.MessageDialog(self, "File %s successfully written." % path,
|
||||
"Save successful", wx.OK + wx.ICON_INFORMATION)
|
||||
self.parent.setPrinterTabText("Printer <%s>" % os.path.basename(path))
|
||||
self.parent.setPrinterTabFile(os.path.basename(path))
|
||||
|
||||
else:
|
||||
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
import ConfigParser
|
||||
import os
|
||||
|
||||
INIFILE = "configtool.default.ini"
|
||||
|
||||
|
||||
class Settings:
|
||||
def __init__(self, app, folder):
|
||||
self.app = app
|
||||
self.cmdfolder = folder
|
||||
self.inifile = os.path.join(folder, INIFILE)
|
||||
self.section = "configtool"
|
||||
|
||||
self.arduinodir = ""
|
||||
self.cflags = ""
|
||||
self.ldflags = ""
|
||||
self.objcopyflags = ""
|
||||
self.programmer = "wiring"
|
||||
self.port = "/dev/ttyACM0"
|
||||
|
||||
self.cfg = ConfigParser.ConfigParser()
|
||||
self.cfg.optionxform = str
|
||||
if not self.cfg.read(self.inifile):
|
||||
print "Settings file %s does not exist. Using default values." % INIFILE
|
||||
|
||||
return
|
||||
|
||||
if self.cfg.has_section(self.section):
|
||||
for opt, value in self.cfg.items(self.section):
|
||||
value = value.replace('\n', ' ')
|
||||
if opt == "arduinodir":
|
||||
self.arduinodir = value
|
||||
elif opt == "cflags":
|
||||
self.cflags = value
|
||||
elif opt == "ldflags":
|
||||
self.ldflags = value
|
||||
elif opt == "programmer":
|
||||
self.programmer = value
|
||||
elif opt == "port":
|
||||
self.port = value
|
||||
elif opt == "objcopyflags":
|
||||
self.objcopyflags = value
|
||||
else:
|
||||
print "Unknown %s option: %s - ignoring." % (self.section, opt)
|
||||
else:
|
||||
print "Missing %s section - assuming defaults." % self.section
|
||||
Loading…
Reference in New Issue