diff --git a/Marlin/pins.h b/Marlin/pins.h
index 9cad2557af..0d1a2380d7 100644
--- a/Marlin/pins.h
+++ b/Marlin/pins.h
@@ -52,217 +52,218 @@
//
#if MB(RAMPS_OLD)
- #include "pins_RAMPS_OLD.h"
+ #include "pins_RAMPS_OLD.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_13_EFB)
- #include "pins_RAMPS_13.h"
+ #include "pins_RAMPS_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_13_EEB)
- #include "pins_RAMPS_13.h"
+ #include "pins_RAMPS_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_13_EFF)
- #include "pins_RAMPS_13.h"
+ #include "pins_RAMPS_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_13_EEF)
- #include "pins_RAMPS_13.h"
+ #include "pins_RAMPS_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_13_SF)
- #include "pins_RAMPS_13.h"
+ #include "pins_RAMPS_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_14_EFB)
- #include "pins_RAMPS.h"
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_14_EEB)
- #include "pins_RAMPS.h"
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_14_EFF)
- #include "pins_RAMPS.h"
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_14_EEF)
- #include "pins_RAMPS.h"
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_14_SF)
- #include "pins_RAMPS.h"
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_PLUS_EFB)
- #include "pins_RAMPS_PLUS.h"
+ #include "pins_RAMPS_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_PLUS_EEB)
- #include "pins_RAMPS_PLUS.h"
+ #include "pins_RAMPS_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_PLUS_EFF)
- #include "pins_RAMPS_PLUS.h"
+ #include "pins_RAMPS_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_PLUS_EEF)
- #include "pins_RAMPS_PLUS.h"
+ #include "pins_RAMPS_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RAMPS_PLUS_SF)
- #include "pins_RAMPS_PLUS.h"
+ #include "pins_RAMPS_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
//
// RAMPS Derivatives - ATmega1280, ATmega2560
//
#elif MB(3DRAG)
- #include "pins_3DRAG.h" // ATmega1280, ATmega2560
+ #include "pins_3DRAG.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(K8200)
- #include "pins_K8200.h" // ATmega1280, ATmega2560 (3DRAG)
+ #include "pins_K8200.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560 (3DRAG)
#elif MB(K8400)
- #include "pins_K8400.h" // ATmega1280, ATmega2560 (3DRAG)
+ #include "pins_K8400.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560 (3DRAG)
#elif MB(BAM_DICE)
- #include "pins_RAMPS.h" // ATmega1280, ATmega2560
+ #include "pins_RAMPS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(BAM_DICE_DUE)
- #include "pins_BAM_DICE_DUE.h" // ATmega1280, ATmega2560
+ #include "pins_BAM_DICE_DUE.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MKS_BASE)
- #include "pins_MKS_BASE.h" // ATmega1280, ATmega2560
+ #include "pins_MKS_BASE.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MKS_BASE_15)
- #include "pins_MKS_BASE_15.h" // ATmega1280, ATmega2560
+ #include "pins_MKS_BASE_15.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MKS_BASE_HEROIC)
- #include "pins_MKS_BASE_HEROIC.h" // ATmega1280, ATmega2560
+ #include "pins_MKS_BASE_HEROIC.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MKS_GEN_13)
- #include "pins_MKS_GEN_13.h" // ATmega1280, ATmega2560
+ #include "pins_MKS_GEN_13.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MKS_GEN_L)
- #include "pins_MKS_GEN_L.h" // ATmega1280, ATmega2560
+ #include "pins_MKS_GEN_L.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(ZRIB_V20)
- #include "pins_ZRIB_V20.h" // ATmega1280, ATmega2560 (MKS_GEN_13)
+ #include "pins_ZRIB_V20.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560 (MKS_GEN_13)
#elif MB(FELIX2)
- #include "pins_FELIX2.h" // ATmega1280, ATmega2560
+ #include "pins_FELIX2.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RIGIDBOARD)
- #include "pins_RIGIDBOARD.h" // ATmega1280, ATmega2560
+ #include "pins_RIGIDBOARD.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(RIGIDBOARD_V2)
- #include "pins_RIGIDBOARD_V2.h" // ATmega1280, ATmega2560
+ #include "pins_RIGIDBOARD_V2.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(SAINSMART_2IN1)
- #include "pins_SAINSMART_2IN1.h" // ATmega1280, ATmega2560
+ #include "pins_SAINSMART_2IN1.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(ULTIMAKER)
- #include "pins_ULTIMAKER.h" // ATmega1280, ATmega2560
+ #include "pins_ULTIMAKER.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(ULTIMAKER_OLD)
- #include "pins_ULTIMAKER_OLD.h" // ATmega1280, ATmega2560
+ #include "pins_ULTIMAKER_OLD.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(AZTEEG_X3)
- #include "pins_AZTEEG_X3.h" // ATmega2560
+ #include "pins_AZTEEG_X3.h" // ATmega2560 env:megaatmega2560
#elif MB(AZTEEG_X3_PRO)
- #include "pins_AZTEEG_X3_PRO.h" // ATmega2560
+ #include "pins_AZTEEG_X3_PRO.h" // ATmega2560 env:megaatmega2560
#elif MB(ULTIMAIN_2)
- #include "pins_ULTIMAIN_2.h" // ATmega2560
+ #include "pins_ULTIMAIN_2.h" // ATmega2560 env:megaatmega2560
#elif MB(RUMBA)
- #include "pins_RUMBA.h" // ATmega2560
+ #include "pins_RUMBA.h" // ATmega2560 env:megaatmega2560
#elif MB(BQ_ZUM_MEGA_3D)
- #include "pins_BQ_ZUM_MEGA_3D.h" // ATmega2560
+ #include "pins_BQ_ZUM_MEGA_3D.h" // ATmega2560 env:megaatmega2560
#elif MB(MAKEBOARD_MINI)
- #include "pins_MAKEBOARD_MINI.h" // ATmega2560
+ #include "pins_MAKEBOARD_MINI.h" // ATmega2560 env:megaatmega2560
#elif MB(TRIGORILLA_13)
- #include "pins_TRIGORILLA_13.h" // ATmega2560
+ #include "pins_TRIGORILLA_13.h" // ATmega2560 env:megaatmega2560
#elif MB(TRIGORILLA_14)
- #include "pins_TRIGORILLA_14.h" // ATmega2560
+ #include "pins_TRIGORILLA_14.h" // ATmega2560 env:megaatmega2560
#elif MB(RAMPS_ENDER_4)
- #include "pins_RAMPS_ENDER_4.h" // ATmega2560
+ #include "pins_RAMPS_ENDER_4.h" // ATmega2560 env:megaatmega2560
//
// Other ATmega1280, ATmega2560
//
#elif MB(CNCONTROLS_11)
- #include "pins_CNCONTROLS_11.h" // ATmega1280, ATmega2560
+ #include "pins_CNCONTROLS_11.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(CNCONTROLS_12)
- #include "pins_CNCONTROLS_12.h" // ATmega1280, ATmega2560
+ #include "pins_CNCONTROLS_12.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MIGHTYBOARD_REVE)
- #include "pins_MIGHTYBOARD_REVE.h" // ATmega1280, ATmega2560
+ #include "pins_MIGHTYBOARD_REVE.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(CHEAPTRONIC)
- #include "pins_CHEAPTRONIC.h" // ATmega2560
+ #include "pins_CHEAPTRONIC.h" // ATmega2560 env:megaatmega2560
#elif MB(CHEAPTRONIC_V2)
- #include "pins_CHEAPTRONICv2.h" // ATmega2560
+ #include "pins_CHEAPTRONICv2.h" // ATmega2560 env:megaatmega2560
#elif MB(MEGATRONICS)
- #include "pins_MEGATRONICS.h" // ATmega2560
+ #include "pins_MEGATRONICS.h" // ATmega2560 env:megaatmega2560
#elif MB(MEGATRONICS_2)
- #include "pins_MEGATRONICS_2.h" // ATmega2560
+ #include "pins_MEGATRONICS_2.h" // ATmega2560 env:megaatmega2560
#elif MB(MEGATRONICS_3) || MB(MEGATRONICS_31)
- #include "pins_MEGATRONICS_3.h" // ATmega2560
+ #include "pins_MEGATRONICS_3.h" // ATmega2560 env:megaatmega2560
#elif MB(RAMBO)
- #include "pins_RAMBO.h" // ATmega2560
+ #include "pins_RAMBO.h" // ATmega2560 env:rambo
#elif MB(MINIRAMBO) || MB(MINIRAMBO_10A)
- #include "pins_MINIRAMBO.h" // ATmega2560
+ #include "pins_MINIRAMBO.h" // ATmega2560 env:rambo
#elif MB(EINSY_RAMBO)
- #include "pins_EINSY_RAMBO.h" // ATmega2560
+ #include "pins_EINSY_RAMBO.h" // ATmega2560 env:rambo
#elif MB(EINSY_RETRO)
- #include "pins_EINSY_RETRO.h" // ATmega2560
+ #include "pins_EINSY_RETRO.h" // ATmega2560 env:rambo
#elif MB(ELEFU_3)
- #include "pins_ELEFU_3.h" // ATmega2560
+ #include "pins_ELEFU_3.h" // ATmega2560 env:megaatmega2560
#elif MB(LEAPFROG)
- #include "pins_LEAPFROG.h" // ATmega1280, ATmega2560
+ #include "pins_LEAPFROG.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(MEGACONTROLLER)
- #include "pins_MEGACONTROLLER.h" // ATmega2560
+ #include "pins_MEGACONTROLLER.h" // ATmega2560 env:megaatmega2560
#elif MB(SCOOVO_X9H)
- #include "pins_SCOOVO_X9H.h" // ATmega2560
+ #include "pins_SCOOVO_X9H.h" // ATmega2560 env:rambo
#elif MB(GT2560_REV_A)
- #include "pins_GT2560_REV_A.h" // ATmega1280, ATmega2560
+ #include "pins_GT2560_REV_A.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
#elif MB(GT2560_REV_A_PLUS)
- #include "pins_GT2560_REV_A_PLUS.h" // ATmega1280, ATmega2560
+ #include "pins_GT2560_REV_A_PLUS.h" // ATmega1280, ATmega2560 env:megaatmega1280 env:megaatmega2560
//
// ATmega1281, ATmega2561
//
#elif MB(MINITRONICS)
- #include "pins_MINITRONICS.h" // ATmega1281
+ #include "pins_MINITRONICS.h" // ATmega1281 env:megaatmega1280
#elif MB(SILVER_GATE)
- #include "pins_SILVER_GATE.h" // ATmega2561
+ #include "pins_SILVER_GATE.h" // ATmega2561 env:megaatmega2560
//
// Sanguinololu and Derivatives - ATmega644P, ATmega1284P
//
#elif MB(SANGUINOLOLU_11)
- #include "pins_SANGUINOLOLU_11.h" // ATmega644P, ATmega1284P
+ #include "pins_SANGUINOLOLU_11.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(SANGUINOLOLU_12)
- #include "pins_SANGUINOLOLU_12.h" // ATmega644P, ATmega1284P
+ #include "pins_SANGUINOLOLU_12.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(MELZI)
- #include "pins_MELZI.h" // ATmega644P, ATmega1284P
+ #include "pins_MELZI.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(MELZI_MAKR3D)
- #include "pins_MELZI_MAKR3D.h" // ATmega644P, ATmega1284P
+ #include "pins_MELZI_MAKR3D.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(MELZI_CREALITY)
- #include "pins_MELZI_CREALITY.h" // ATmega644P, ATmega1284P
+ #include "pins_MELZI_CREALITY.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(MELZI_MALYAN)
- #include "pins_MELZI_MALYAN.h" // ATmega644P, ATmega1284P
+ #include "pins_MELZI_MALYAN.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(MELZI_TRONXY)
- #include "pins_MELZI_TRONXY.h" // ATmega644P, ATmega1284P
+ #include "pins_MELZI_TRONXY.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(STB_11)
- #include "pins_STB_11.h" // ATmega644P, ATmega1284P
+ #include "pins_STB_11.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(AZTEEG_X1)
- #include "pins_AZTEEG_X1.h" // ATmega644P, ATmega1284P
+ #include "pins_AZTEEG_X1.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
//
// Other ATmega644P, ATmega644, ATmega1284P
//
#elif MB(GEN3_MONOLITHIC)
- #include "pins_GEN3_MONOLITHIC.h" // ATmega644P
+ #include "pins_GEN3_MONOLITHIC.h" // ATmega644P env:sanguino_atmega644p
#elif MB(GEN3_PLUS)
- #include "pins_GEN3_PLUS.h" // ATmega644P, ATmega1284P
+ #include "pins_GEN3_PLUS.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN6)
- #include "pins_GEN6.h" // ATmega644P, ATmega1284P
+ #include "pins_GEN6.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN6_DELUXE)
- #include "pins_GEN6_DELUXE.h" // ATmega644P, ATmega1284P
+ #include "pins_GEN6_DELUXE.h" // ATmega644P, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN7_CUSTOM)
- #include "pins_GEN7_CUSTOM.h" // ATmega644P, ATmega644, ATmega1284P
+ #include "pins_GEN7_CUSTOM.h" // ATmega644P, ATmega644, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN7_12)
- #include "pins_GEN7_12.h" // ATmega644P, ATmega644, ATmega1284P
+ #include "pins_GEN7_12.h" // ATmega644P, ATmega644, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN7_13)
- #include "pins_GEN7_13.h" // ATmega644P, ATmega644, ATmega1284P
+ #include "pins_GEN7_13.h" // ATmega644P, ATmega644, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(GEN7_14)
- #include "pins_GEN7_14.h" // ATmega644P, ATmega644, ATmega1284P
+ #include "pins_GEN7_14.h" // ATmega644P, ATmega644, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
#elif MB(OMCA_A)
- #include "pins_OMCA_A.h" // ATmega644
+ #include "pins_OMCA_A.h" // ATmega644 env:sanguino_atmega644p
#elif MB(OMCA)
- #include "pins_OMCA.h" // ATmega644P, ATmega644
+ #include "pins_OMCA.h" // ATmega644P, ATmega644 env:sanguino_atmega644p
#elif MB(ANET_10)
- #include "pins_ANET_10.h" // ATmega1284P
+ #include "pins_ANET_10.h" // ATmega1284P env:sanguino_atmega1284p
#elif MB(SETHI)
- #include "pins_SETHI.h" // ATmega644P, ATmega644, ATmega1284P
+ #include "pins_SETHI.h" // ATmega644P, ATmega644, ATmega1284P env:sanguino_atmega644p env:sanguino_atmega1284p
//
// Teensyduino - AT90USB1286, AT90USB1286P
//
#elif MB(TEENSYLU)
- #include "pins_TEENSYLU.h" // AT90USB1286, AT90USB1286P
+ #include "pins_TEENSYLU.h" // AT90USB1286, AT90USB1286P env:teensy20
#elif MB(PRINTRBOARD)
- #include "pins_PRINTRBOARD.h" // AT90USB1286
+ #include "pins_PRINTRBOARD.h" // AT90USB1286 env:teensy20
#elif MB(PRINTRBOARD_REVF)
- #include "pins_PRINTRBOARD_REVF.h" // AT90USB1286
+ #include "pins_PRINTRBOARD_REVF.h" // AT90USB1286 env:teensy20
#elif MB(BRAINWAVE)
- #include "pins_BRAINWAVE.h" // AT90USB646
+ #include "pins_BRAINWAVE.h" // AT90USB646 env:teensy20
#elif MB(BRAINWAVE_PRO)
- #include "pins_BRAINWAVE_PRO.h" // AT90USB1286
+ #include "pins_BRAINWAVE_PRO.h" // AT90USB1286 env:teensy20
#elif MB(SAV_MKI)
- #include "pins_SAV_MKI.h" // AT90USB1286
+ #include "pins_SAV_MKI.h" // AT90USB1286 env:teensy20
#elif MB(TEENSY2)
- #include "pins_TEENSY2.h" // AT90USB1286
+ #include "pins_TEENSY2.h" // AT90USB1286 env:teensy20
#elif MB(5DPRINT)
- #include "pins_5DPRINT.h" // AT90USB1286
+ #include "pins_5DPRINT.h" // AT90USB1286 env:teensy20
+
#else
#error "Unknown MOTHERBOARD value set in Configuration.h"
diff --git a/buildroot/share/atom/auto_build.py b/buildroot/share/atom/auto_build.py
new file mode 100644
index 0000000000..765ebb5e1e
--- /dev/null
+++ b/buildroot/share/atom/auto_build.py
@@ -0,0 +1,935 @@
+#######################################
+#
+# Marlin 3D Printer Firmware
+# Copyright (C) 2018 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+#
+# Based on Sprinter and grbl.
+# Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+#######################################
+
+#######################################
+#
+# Description: script to automate PlatformIO builds
+# CLI: python auto_build.py build_option
+# build_option (required)
+# build executes -> platformio run -e target_env
+# clean executes -> platformio run --target clean -e target_env
+# upload executes -> platformio run --target upload -e target_env
+# traceback executes -> platformio run --target upload -e target_env
+# program executes -> platformio run --target program -e target_env
+# test executes -> platformio test upload -e target_env
+# remote executes -> platformio remote run --target upload -e target_env
+# debug executes -> platformio debug -e target_env
+#
+# 'traceback' just uses the debug variant of the target environment if one exists
+#
+#######################################
+
+#######################################
+#
+# General program flow
+#
+# 1. Scans Configuration.h for the motherboard name and Marlin version.
+# 2. Scans pins.h for the motherboard.
+# returns the CPU(s) and platformio environment(s) used by the motherboard
+# 3. If further info is needed then a popup gets it from the user.
+# 4. The OUTPUT_WINDOW class creates a window to display the output of the PlatformIO program.
+# 5. A thread is created by the OUTPUT_WINDOW class in order to execute the RUN_PIO function.
+# 6. The RUN_PIO function uses a subprocess to run the CLI version of PlatformIO.
+# 7. The "iter(pio_subprocess.stdout.readline, '')" function is used to stream the output of
+# PlatformIO back to the RUN_PIO function.
+# 8. Each line returned from PlatformIO is formatted to match the color coding seen in the
+# PlatformIO GUI.
+# 9. If there is a color change within a line then the line is broken at each color change
+# and sent separately.
+# 10. Each formatted segment (could be a full line or a split line) is put into the queue
+# IO_queue as it arrives from the platformio subprocess.
+# 11. The OUTPUT_WINDOW class periodically samples IO_queue. If data is available then it
+# is written to the window.
+# 12. The window stays open until the user closes it.
+# 13. The OUTPUT_WINDOW class continues to execute as long as the window is open. This allows
+# copying, saving, scrolling of the window. A right click popup is available.
+#
+#######################################
+
+import sys
+import os
+
+num_args = len(sys.argv)
+if num_args > 1:
+ build_type = str(sys.argv[1])
+else:
+ print 'Please specify build type'
+ exit()
+
+print'build_type: ', build_type
+
+print '\nWorking\n'
+
+python_ver = sys.version_info[0] # major version - 2 or 3
+
+if python_ver == 2:
+ print "python version " + str(sys.version_info[0]) + "." + str(sys.version_info[1]) + "." + str(sys.version_info[2])
+else:
+ print "python version " + str(sys.version_info[0])
+ print "This script only runs under python 2"
+ exit()
+
+#########
+# Python 2 error messages:
+# Can't find a usable init.tcl in the following directories ...
+# error "invalid command name "tcl_findLibrary""
+#
+# Fix for the above errors on my Win10 system:
+# search all init.tcl files for the line "package require -exact Tcl" that has the highest 8.5.x number
+# copy it into the first directory listed in the error messages
+# set the environmental variables TCLLIBPATH and TCL_LIBRARY to the directory where you found the init.tcl file
+# reboot
+#########
+
+#globals
+target_env = ''
+board_name = ''
+
+
+
+##########################################################################################
+#
+# popup to get input from user
+#
+##########################################################################################
+
+def get_answer(board_name, cpu_label_txt, cpu_a_txt, cpu_b_txt):
+
+
+ if python_ver == 2:
+ import Tkinter as tk
+ else:
+ import tkinter as tk
+
+ def CPU_exit_3(): # forward declare functions
+
+ CPU_exit_3_()
+ def CPU_exit_4():
+
+ CPU_exit_4_()
+ def kill_session():
+ kill_session_()
+
+ root_get_answer = tk.Tk()
+
+ root_get_answer.chk_state_1 = 1 # declare variables used by TK and enable
+
+ chk_state_1 = 0 # set initial state of check boxes
+
+
+ global get_answer_val
+ get_answer_val = 2 # return get_answer_val, set default to match chk_state_1 default
+
+
+ l1 = tk.Label(text=board_name,
+ fg = "light green",
+ bg = "dark green",
+ font = "Helvetica 12 bold").grid(row=1)
+
+ l2 = tk.Label(text=cpu_label_txt,
+ fg = "light green",
+ bg = "dark green",
+ font = "Helvetica 16 bold italic").grid(row=2)
+
+ b4 = tk.Checkbutton(text=cpu_a_txt,
+ fg = "black",
+ font = "Times 20 bold ",
+ variable=chk_state_1, onvalue=1, offvalue=0,
+
+ command = CPU_exit_3).grid(row=3)
+
+ b5 = tk.Checkbutton(text=cpu_b_txt,
+ fg = "black",
+ font = "Times 20 bold ",
+ variable=chk_state_1, onvalue=0, offvalue=1,
+
+ command = CPU_exit_4).grid(row=4) # use same variable but inverted so they will track
+ b6 = tk.Button(text="CONFIRM",
+ fg = "blue",
+ font = "Times 20 bold ",
+ command = root_get_answer.destroy).grid(row=5, pady=4)
+
+ b7 = tk.Button(text="CANCEL",
+ fg = "red",
+ font = "Times 12 bold ",
+ command = kill_session).grid(row=6, pady=4)
+
+
+ def CPU_exit_3_():
+ global get_answer_val
+ get_answer_val = 1
+
+ def CPU_exit_4_():
+ global get_answer_val
+ get_answer_val = 2
+
+ def kill_session_():
+ raise SystemExit(0) # kill everything
+
+ root_get_answer.mainloop()
+
+# end - get answer
+
+
+
+def env_name_check(argument):
+ name_check = {
+ 'teensy35' : True,
+ 'teensy20' : True,
+ 'STM32F4' : True,
+ 'STM32F1' : True,
+ 'sanguino_atmega644p' : True,
+ 'sanguino_atmega1284p' : True,
+ 'rambo' : True,
+ 'melzi_optiboot' : True,
+ 'melzi' : True,
+ 'megaatmega2560' : True,
+ 'megaatmega1280' : True,
+ 'malyanm200' : True,
+ 'LPC1768' : True,
+ 'DUE_debug' : True,
+ 'DUE_USB' : True,
+ 'DUE' : True
+ }
+
+ return name_check.get(argument, False)
+
+
+# gets the last build environment
+def get_build_last():
+ env_last = ''
+ DIR_PWD = os.listdir('.')
+ if '.pioenvs' in DIR_PWD:
+ date_last = 0.0
+ DIR__pioenvs = os.listdir('.pioenvs')
+ for name in DIR__pioenvs:
+ if env_name_check(name):
+ DIR_temp = os.listdir('.pioenvs/' + name)
+ for names_temp in DIR_temp:
+ if 0 == names_temp.find('firmware.'):
+ date_temp = os.path.getmtime('.pioenvs/' + name + '/' + names_temp)
+ if date_temp > date_last:
+ date_last = date_temp
+ env_last = name
+ return env_last
+
+
+# gets the board being built from the Configuration.h file
+# returns: board name, major version of Marlin being used (1 or 2)
+def get_board_name():
+ board_name = ''
+ # get board name
+
+ with open('Marlin/Configuration.h', 'r') as myfile:
+ Configuration_h = myfile.read()
+
+ Configuration_h = Configuration_h.split('\n')
+ Marlin_ver = 0 # set version to invalid number
+ for lines in Configuration_h:
+ if 0 == lines.find('#define CONFIGURATION_H_VERSION 01'):
+ Marlin_ver = 1
+ if 0 == lines.find('#define CONFIGURATION_H_VERSION 02'):
+ Marlin_ver = 2
+ board = lines.find(' BOARD_') + 1
+ motherboard = lines.find(' MOTHERBOARD ') + 1
+ define = lines.find('#define ')
+ comment = lines.find('//')
+ if (comment == -1 or comment > board) and \
+ board > motherboard and \
+ motherboard > define and \
+ define >= 0 :
+ spaces = lines.find(' ', board) # find the end of the board substring
+ if spaces == -1:
+ board_name = lines[board : ]
+ else:
+ board_name = lines[board : spaces]
+ break
+
+
+ return board_name, Marlin_ver
+
+
+# extract first environment name it finds after the start position
+# returns: environment name and position to start the next search from
+def get_env_from_line(line, start_position):
+ env = ''
+ next_position = -1
+ env_position = line.find('env:', start_position)
+ if 0 < env_position:
+ next_position = line.find(' ', env_position + 4)
+ if 0 < next_position:
+ env = line[env_position + 4 : next_position]
+ else:
+ env = line[env_position + 4 : ] # at the end of the line
+ return env, next_position
+
+
+
+#scans pins.h for board name and returns the environment(s) it finds
+def get_starting_env(board_name_full, version):
+ # get environment starting point
+
+ if version == 1:
+ path = 'Marlin/pins.h'
+ if version == 2:
+ path = 'Marlin/src/pins/pins.h'
+ with open(path, 'r') as myfile:
+ pins_h = myfile.read()
+
+ board_name = board_name_full[ 6 : ] # only use the part after "BOARD_" since we're searching the pins.h file
+ pins_h = pins_h.split('\n')
+ environment = ''
+ board_line = ''
+ cpu_A = ''
+ cpu_B = ''
+ i = 0
+ list_start_found = False
+ for lines in pins_h:
+ i = i + 1 # i is always one ahead of the index into pins_h
+ if 0 < lines.find("Unknown MOTHERBOARD value set in Configuration.h"):
+ break # no more
+ if 0 < lines.find('1280'):
+ list_start_found = True
+ if list_start_found == False: # skip lines until find start of CPU list
+ continue
+ board = lines.find(board_name)
+ comment_start = lines.find('// ')
+ cpu_A_loc = comment_start
+ cpu_B_loc = 0
+ if board > 0: # need to look at the next line for environment info
+ cpu_line = pins_h[i]
+ comment_start = cpu_line.find('// ')
+ env_A, next_position = get_env_from_line(cpu_line, comment_start) # get name of environment & start of search for next
+ env_B, next_position = get_env_from_line(cpu_line, next_position) # get next environment, if it exists
+ env_C, next_position = get_env_from_line(cpu_line, next_position) # get next environment, if it exists
+ break
+ return env_A, env_B, env_C
+
+
+# scans input string for CPUs that the users may need to select from
+# returns: CPU name
+def get_CPU_name(environment):
+ CPU_list = ('1280', '2560','644', '1284', 'LPC1768', 'DUE')
+ CPU_name = ''
+ for CPU in CPU_list:
+ if 0 < environment.find(CPU):
+ return CPU
+
+
+# get environment to be used for the build
+# returns: environment
+def get_env(board_name, ver_Marlin):
+ def no_environment():
+ print 'ERROR - no environment for this board'
+ print board_name
+ raise SystemExit(0) # no environment so quit
+
+ def invalid_board():
+ print 'ERROR - invalid board'
+ print board_name
+ raise SystemExit(0) # quit if unable to find board
+
+
+ CPU_question = ( ('1280', '2560', "1280 or 2560 CPU?"), ('644', '1284', "644 or 1284 CPU?") )
+
+ if 0 < board_name.find('MELZI') :
+ get_answer(board_name, "Which flavor of Melzi?", "Melzi (Optiboot bootloader)", "Melzi ")
+ if 1 == get_answer_val:
+ target_env = 'melzi_optiboot'
+ else:
+ target_env = 'melzi'
+ else:
+ env_A, env_B, env_C = get_starting_env(board_name, ver_Marlin)
+
+ if env_A == '':
+ no_environment()
+ if env_B == '':
+ return env_A # only one environment so finished
+
+ CPU_A = get_CPU_name(env_A)
+ CPU_B = get_CPU_name(env_B)
+
+ for item in CPU_question:
+ if CPU_A == item[0]:
+ get_answer(board_name, item[2], item[0], item[1])
+ if 2 == get_answer_val:
+ target_env = env_B
+ else:
+ target_env = env_A
+ return target_env
+
+ if env_A == 'LPC1768':
+ if build_type == 'traceback' or (build_type == 'clean' and get_build_last() == 'LPC1768_debug_and_upload'):
+ target_env = 'LPC1768_debug_and_upload'
+ else:
+ target_env = 'LPC1768'
+ elif env_A == 'DUE':
+ target_env = 'DUE'
+ if build_type == 'traceback' or (build_type == 'clean' and get_build_last() == 'DUE_debug'):
+ target_env = 'DUE_debug'
+ elif env_B == 'DUE_USB':
+ get_answer(board_name, "DUE: need download port", "USB (native USB) port", "Programming port ")
+ if 1 == get_answer_val:
+ target_env = 'DUE_USB'
+ else:
+ target_env = 'DUE'
+ else:
+ invalid_board()
+
+ if build_type == 'traceback' and not(target_env == 'LPC1768_debug_and_upload' or target_env == 'DUE_debug') and Marlin_ver == 2:
+ print "ERROR - this board isn't setup for traceback"
+ print 'board_name: ', board_name
+ print 'target_env: ', target_env
+ raise SystemExit(0)
+
+ return target_env
+# end - get_env
+
+# puts screen text into queue so that the parent thread can fetch the data from this thread
+import Queue
+IO_queue = Queue.Queue()
+def write_to_screen_queue(text, format_tag = 'normal'):
+ double_in = [text, format_tag]
+ IO_queue.put(double_in, block = False)
+
+
+#
+# send one line to the terminal screen with syntax highlighting
+#
+# input: unformatted text, flags from previous run
+# returns: formatted text ready to go to the terminal, flags from this run
+#
+# This routine remembers the status from call to call because previous
+# lines can affect how the current line is highlighted
+#
+
+# 'static' variables - init here and then keep updating them from within print_line
+warning = False
+warning_FROM = False
+error = False
+standard = True
+prev_line_COM = False
+next_line_warning = False
+warning_continue = False
+
+def line_print(line_input):
+
+ global warning
+ global warning_FROM
+ global error
+ global standard
+ global prev_line_COM
+ global next_line_warning
+ global warning_continue
+
+
+
+
+ # all '0' elements must precede all '1' elements or they'll be skipped
+ platformio_highlights = [
+ ['Environment', 0, 'highlight_blue'],
+ ['[SKIP]', 1, 'warning'],
+ ['[ERROR]', 1, 'error'],
+ ['[SUCCESS]', 1, 'highlight_green']
+ ]
+
+ def write_to_screen_with_replace(text, highlights): # search for highlights & split line accordingly
+ did_something = False
+ for highlight in highlights:
+ found = text.find(highlight[0])
+ if did_something == True:
+ break
+ if found >= 0 :
+ did_something = True
+ if 0 == highlight[1]:
+ found_1 = text.find(' ')
+ found_tab = text.find('\t')
+ if found_1 < 0 or found_1 > found_tab:
+ found_1 = found_tab
+ write_to_screen_queue(text[ : found_1 + 1 ])
+ for highlight_2 in highlights:
+ if highlight[0] == highlight_2[0] :
+ continue
+ found = text.find(highlight_2[0])
+ if found >= 0 :
+ found_space = text.find(' ', found_1 + 1)
+ found_tab = text.find('\t', found_1 + 1)
+ if found_space < 0 or found_space > found_tab:
+ found_space = found_tab
+ found_right = text.find(']', found + 1)
+ write_to_screen_queue(text[found_1 + 1 : found_space + 1 ], highlight[2])
+ write_to_screen_queue(text[found_space + 1 : found + 1 ])
+ write_to_screen_queue(text[found + 1 : found_right], highlight_2[2])
+ write_to_screen_queue(text[found_right : ] + '\n')
+ break
+ break
+ if 1 == highlight[1]:
+ found_right = text.find(']', found + 1)
+ write_to_screen_queue(text[ : found + 1 ])
+ write_to_screen_queue(text[found + 1 : found_right ], highlight[2])
+ write_to_screen_queue(text[found_right : ] + '\n')
+ break
+ if did_something == False:
+ write_to_screen_queue(text + '\n')
+ # end - write_to_screen_with_replace
+
+
+
+ # scan the line
+ max_search = len(line_input)
+ if max_search > 3 :
+ max_search = 3
+ beginning = line_input[:max_search]
+
+ # set flags
+ if 0 < line_input.find(': warning: '): # start of warning block
+ warning = True
+ warning_FROM = False
+ error = False
+ standard = False
+ prev_line_COM = False
+ prev_line_COM = False
+ warning_continue = True
+ if beginning == 'War' or \
+ beginning == '#er' or \
+ beginning == 'In ' or \
+ (beginning != 'Com' and prev_line_COM == True and not(beginning == 'Arc' or beginning == 'Lin' or beginning == 'Ind') or \
+ next_line_warning == True):
+ warning = True #warning found
+ warning_FROM = False
+ error = False
+ standard = False
+ prev_line_COM = False
+ elif beginning == 'Com' or \
+ beginning == 'Ver' or \
+ beginning == ' [E' or \
+ beginning == 'Rem' or \
+ beginning == 'Bui' or \
+ beginning == 'Ind' or \
+ beginning == 'PLA':
+ warning = False #standard line found
+ warning_FROM = False
+ error = False
+ standard = True
+ prev_line_COM = False
+ warning_continue = False
+ elif beginning == '***':
+ warning = False # error found
+ warning_FROM = False
+ error = True
+ standard = False
+ prev_line_COM = False
+
+ elif beginning == 'fro' and warning == True : # start of warning /error block
+ warning_FROM = True
+ prev_line_COM = False
+ warning_continue = True
+ elif 0 < line_input.find(': error:') or \
+ 0 < line_input.find(': fatal error:'): # start of warning /error block
+ warning = False # error found
+ warning_FROM = False
+ error = True
+ standard = False
+ prev_line_COM = False
+ warning_continue = True
+ elif warning_continue == True:
+ warning = True
+ warning_FROM = False # keep the warning status going until find a standard line
+ error = False
+ standard = False
+ prev_line_COM = False
+ warning_continue = True
+
+ else:
+ warning = False # unknown so assume standard line
+ warning_FROM = False
+ error = False
+ standard = True
+ prev_line_COM = False
+ warning_continue = False
+
+ if beginning == 'Com':
+ prev_line_COM = True
+
+ # print based on flags
+ if standard == True:
+ write_to_screen_with_replace(line_input, platformio_highlights) #print white on black with substitutions
+ if warning == True:
+ write_to_screen_queue(line_input + '\n', 'warning')
+ if error == True:
+ write_to_screen_queue(line_input + '\n', 'error')
+# end - line_print
+
+
+
+def run_PIO(dummy):
+
+ ##########################################################################
+ # #
+ # run Platformio #
+ # #
+ ##########################################################################
+
+
+ # build platformio run -e target_env
+ # clean platformio run --target clean -e target_env
+ # upload platformio run --target upload -e target_env
+ # traceback platformio run --target upload -e target_env
+ # program platformio run --target program -e target_env
+ # test platformio test upload -e target_env
+ # remote platformio remote run --target upload -e target_env
+ # debug platformio debug -e target_env
+
+
+ global build_type
+ global target_env
+ global board_name
+ print 'build_type: ', build_type
+
+ import subprocess
+ import sys
+ print 'starting platformio'
+
+ if build_type == 'build':
+ # platformio run -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'run', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'clean':
+ # platformio run --target clean -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'run', '--target', 'clean', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'upload':
+ # platformio run --target upload -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'run', '--target', 'upload', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'traceback':
+ # platformio run --target upload -e target_env - select the debug environment if there is one
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'run', '--target', 'upload', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'program':
+ # platformio run --target program -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'run', '--target', 'program', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'test':
+ #platformio test upload -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'test', 'upload', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'remote':
+ # platformio remote run --target upload -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'remote', 'run', '--target', 'program', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ elif build_type == 'debug':
+ # platformio debug -e target_env
+ # combine stdout & stderr so all compile messages are included
+ pio_subprocess = subprocess.Popen(['platformio', 'debug', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+ else:
+ print 'ERROR - unknown build type: ', build_type
+ raise SystemExit(0) # kill everything
+
+ # stream output from subprocess and split it into lines
+ for line in iter(pio_subprocess.stdout.readline, ''):
+ line_print(line.replace('\n', ''))
+
+
+ # append info used to run PlatformIO
+ write_to_screen_queue('\nBoard name: ' + board_name + '\n') # put build info at the bottom of the screen
+ write_to_screen_queue('Build type: ' + build_type + '\n')
+ write_to_screen_queue('Environment used: ' + target_env + '\n')
+# end - run_PIO
+
+
+########################################################################
+
+import time
+import threading
+import Tkinter as tk
+import ttk
+import Queue
+import subprocess
+import sys
+que = Queue.Queue()
+#IO_queue = Queue.Queue()
+
+from Tkinter import Tk, Frame, Text, Scrollbar, Menu
+from tkMessageBox import askokcancel
+
+import tkFileDialog
+from tkMessageBox import askokcancel
+import tkFileDialog
+
+
+
+class output_window(Text):
+
+ global continue_updates
+ continue_updates = True
+
+
+ def __init__(self):
+
+
+ self.root = tk.Tk()
+ self.frame = tk.Frame(self.root)
+ self.frame.pack(fill='both', expand=True)
+
+ # text widget
+ #self.text = tk.Text(self.frame, borderwidth=3, relief="sunken")
+ Text.__init__(self, self.frame, borderwidth=3, relief="sunken")
+ self.config(tabs=(400,)) # configure Text widget tab stops
+ self.config(background = 'black', foreground = 'white', font= ("consolas", 12), wrap = 'word', undo = 'True')
+ self.config(height = 24, width = 120)
+ self.pack(side='left', fill='both', expand=True)
+
+ self.tag_config('normal', foreground = 'white')
+ self.tag_config('warning', foreground = 'yellow' )
+ self.tag_config('error', foreground = 'red')
+ self.tag_config('highlight_green', foreground = 'green')
+ self.tag_config('highlight_blue', foreground = 'cyan')
+
+# self.bind('', self.select_all) # the event happens but the action doesn't
+
+ # scrollbar
+
+ scrb = tk.Scrollbar(self.frame, orient='vertical', command=self.yview)
+ self.config(yscrollcommand=scrb.set)
+ scrb.pack(side='right', fill='y')
+
+
+ # pop-up menu
+ self.popup = tk.Menu(self, tearoff=0)
+ self.popup.add_command(label='Cut', command=self._cut)
+ self.popup.add_command(label='Copy', command=self._copy)
+ self.popup.add_command(label='Paste', command=self._paste)
+ self.popup.add_separator()
+ self.popup.add_command(label='Select All', command=self._select_all)
+ self.popup.add_command(label='Clear All', command=self._clear_all)
+ self.popup.add_separator()
+ self.popup.add_command(label='Save As', command=self._file_save_as)
+ self.bind('', self._show_popup)
+
+
+ # threading & subprocess section
+
+ def start_thread(self, ):
+ global continue_updates
+ # create then start a secondary thread to run an arbitrary function
+ # must have at least one argument
+ self.secondary_thread = threading.Thread(target = lambda q, arg1: q.put(run_PIO(arg1)), args=(que, ''))
+ self.secondary_thread.start()
+ continue_updates = True
+ # check the Queue in 50ms
+ self.root.after(50, self.check_thread)
+ self.root.after(50, self.update)
+
+
+ def check_thread(self): # wait for user to kill the window
+ global continue_updates
+ if continue_updates == True:
+ self.root.after(20, self.check_thread)
+
+
+ def update(self):
+ global continue_updates
+ if continue_updates == True:
+ self.root.after(20, self.update)#method is called every 50ms
+ temp_text = ['0','0']
+ if IO_queue.empty():
+ if not(self.secondary_thread.is_alive()):
+ continue_updates = False # queue is exhausted and thread is dead so no need for further updates
+ self.tag_add('sel', '1.0', 'end')
+ else:
+ try:
+ temp_text = IO_queue.get(block = False)
+ except Queue.Empty:
+ continue_updates = False # queue is exhausted so no need for further updates
+ else:
+ self.insert('end', temp_text[0], temp_text[1])
+ self.see("end") # make the last line visible (scroll text off the top)
+
+
+ # text editing section
+
+ def _file_save_as(self):
+ self.filename = tkFileDialog.asksaveasfilename(defaultextension = '.txt')
+ f = open(self.filename, 'w')
+ f.write(self.get('1.0', 'end'))
+ f.close()
+
+
+
+ def copy(self, event):
+ try:
+ selection = self.get(*self.tag_ranges('sel'))
+ self.clipboard_clear()
+ self.clipboard_append(selection)
+ except TypeError:
+ pass
+
+ def cut(self, event):
+
+ try:
+ selection = self.get(*self.tag_ranges('sel'))
+ self.clipboard_clear()
+ self.clipboard_append(selection)
+ self.delete(*self.tag_ranges('sel'))
+ except TypeError:
+ pass
+
+ def _show_popup(self, event):
+ '''right-click popup menu'''
+
+ if self.root.focus_get() != self:
+ self.root.focus_set()
+
+ try:
+ self.popup.tk_popup(event.x_root, event.y_root, 0)
+ finally:
+ self.popup.grab_release()
+
+ def _cut(self):
+
+ try:
+ selection = self.get(*self.tag_ranges('sel'))
+ self.clipboard_clear()
+ self.clipboard_append(selection)
+ self.delete(*self.tag_ranges('sel'))
+ except TypeError:
+ pass
+
+ def cut(self, event):
+ _cut(self)
+
+ def _copy(self):
+
+ try:
+ selection = self.get(*self.tag_ranges('sel'))
+ self.clipboard_clear()
+ self.clipboard_append(selection)
+ except TypeError:
+ pass
+
+ def copy(self, event):
+ _copy(self)
+
+ def _paste(self):
+
+ self.insert('insert', self.selection_get(selection='CLIPBOARD'))
+
+ def _select_all(self):
+ self.tag_add('sel', '1.0', 'end')
+
+
+ def select_all(self, event):
+ self.tag_add('sel', '1.0', 'end')
+
+
+ def _clear_all(self):
+ '''erases all text'''
+
+ isok = askokcancel('Clear All', 'Erase all text?', frame=self,
+ default='ok')
+ if isok:
+ self.delete('1.0', 'end')
+
+ def _place_cursor(self): # theme: terminal
+ '''check the position of the cursor against the last known position
+ every 15ms and update the cursorblock tag as needed'''
+
+ current_index = self.index('insert')
+
+ if self.cursor != current_index:
+ self.cursor = current_index
+ self.tag_delete('cursorblock')
+
+ start = self.index('insert')
+ end = self.index('insert+1c')
+
+ if start[0] != end[0]:
+ self.insert(start, ' ')
+ end = self.index('insert')
+
+ self.tag_add('cursorblock', start, end)
+ self.mark_set('insert', self.cursor)
+
+ self.after(15, self._place_cursor)
+
+ def _blink_cursor(self): # theme: terminal
+ '''alternate the background color of the cursorblock tagged text
+ every 600 milliseconds'''
+
+ if self.switch == self.fg:
+ self.switch = self.bg
+ else:
+ self.switch = self.fg
+
+ self.tag_config('cursorblock', background=self.switch)
+
+ self.after(600, self._blink_cursor)
+# end - output_window
+
+
+
+def main():
+
+
+ ##########################################################################
+ # #
+ # main program #
+ # #
+ ##########################################################################
+
+ global build_type
+ global target_env
+ global board_name
+
+ board_name, Marlin_ver = get_board_name()
+
+ target_env = get_env(board_name, Marlin_ver)
+
+ auto_build = output_window()
+ auto_build.start_thread() # executes the "run_PIO" function
+
+ auto_build.root.mainloop()
+
+
+
+
+if __name__ == '__main__':
+
+ main()
diff --git a/platformio.ini b/platformio.ini
index 89f31afc62..c21325d9cb 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -52,15 +52,6 @@ build_flags = ${common.build_flags}
board_f_cpu = 16000000L
lib_deps = ${common.lib_deps}
-#
-# Brainwave Pro (Teensy 2.0)
-#
-[env:brainwavepro]
-platform = teensy
-framework = arduino
-board = teensy20pp
-build_flags = ${common.build_flags} -D MOTHERBOARD=BOARD_BRAINWAVE_PRO
-lib_deps = ${common.lib_deps}
#
# Melzi and clones (ATmega1284p)
@@ -85,28 +76,6 @@ build_flags = ${common.build_flags}
upload_speed = 115200
lib_deps = ${common.lib_deps}
-#
-# Printrboard (Teensy 2.0)
-#
-[env:printrboard]
-platform = teensy
-framework = arduino
-board = teensy20pp
-build_flags = ${common.build_flags} -D MOTHERBOARD=BOARD_PRINTRBOARD
-# Bug in arduino framework does not allow boards running at 20Mhz
-#board_f_cpu = 20000000L
-lib_deps = ${common.lib_deps}
-
-#
-# Printrboard Rev.F (Teensy 2.0)
-#
-[env:printrboard_revf]
-platform = teensy
-framework = arduino
-board = teensy20pp
-build_flags = ${common.build_flags} -D MOTHERBOARD=BOARD_PRINTRBOARD_REVF
-lib_deps = ${common.lib_deps}
-
#
# RAMBo
#
@@ -138,3 +107,17 @@ board = sanguino_atmega1284p
build_flags = ${common.build_flags}
lib_deps = ${common.lib_deps}
+
+#
+# Teensy++ 2.0
+#
+# - PrintrBoard
+# - PrintrBoard Rev.F
+# - Brainwave Pro
+#
+[env:teensy20]
+platform = teensy
+framework = arduino
+board = teensy20pp
+build_flags = ${common.build_flags}
+lib_deps = ${common.lib_deps}
\ No newline at end of file
diff --git a/process-palette.json b/process-palette.json
new file mode 100644
index 0000000000..8b68981584
--- /dev/null
+++ b/process-palette.json
@@ -0,0 +1,357 @@
+{
+ "patterns": {
+ "P1": {
+ "expression": "(path):(line)"
+ },
+ "P2": {
+ "expression": "(path)\\s+(line)",
+ "path": "(?:\\/[\\w\\.\\-]+)+"
+ }
+ },
+ "commands": [
+ {
+ "namespace": "process-palette",
+ "action": "PIO Build",
+ "command": "python buildroot/share/atom/auto_build.py build",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": true,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": "",
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Clean",
+ "command": "python buildroot/share/atom/auto_build.py clean",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Upload",
+ "command": "python buildroot/share/atom/auto_build.py upload",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Upload (traceback)",
+ "command": "python buildroot/share/atom/auto_build.py traceback",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Upload using Programmer",
+ "command": "python buildroot/share/atom/auto_build.py program",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Test",
+ "command": "python buildroot/share/atom/auto_build.py test",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Debug",
+ "command": "python buildroot/share/atom/auto_build.py debug",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ },
+ {
+ "namespace": "process-palette",
+ "action": "PIO Remote",
+ "command": "python buildroot/share/atom/auto_build.py remote",
+ "arguments": [],
+ "cwd": "{projectPath}",
+ "inputDialogs": [],
+ "env": {},
+ "keystroke": null,
+ "stream": true,
+ "outputTarget": "panel",
+ "outputBufferSize": 80000,
+ "maxCompleted": 3,
+ "autoShowOutput": true,
+ "autoHideOutput": false,
+ "scrollLockEnabled": false,
+ "singular": false,
+ "promptToSave": true,
+ "saveOption": "none",
+ "patterns": [
+ "default"
+ ],
+ "successOutput": "{stdout}",
+ "errorOutput": "{stdout}\n{stderr}",
+ "fatalOutput": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "startMessage": null,
+ "successMessage": "Executed : {fullCommand}",
+ "errorMessage": "Executed : {fullCommand}\nReturned with code {exitStatus}\n{stderr}",
+ "fatalMessage": "Failed to execute : {fullCommand}\n{stdout}\n{stderr}",
+ "menus": [
+ "Auto Build"
+ ],
+ "startScript": null,
+ "successScript": null,
+ "errorScript": null,
+ "scriptOnStart": false,
+ "scriptOnSuccess": false,
+ "scriptOnError": false,
+ "notifyOnStart": false,
+ "notifyOnSuccess": true,
+ "notifyOnError": true,
+ "input": null
+ }
+ ]
+}