Support 512K "RCT6" in BTT SKR Mini (#15890)

This commit is contained in:
thisiskeithb 2019-11-15 00:51:26 -08:00 committed by Scott Lahteine
parent aa93e1f21a
commit 0f57818f2d
13 changed files with 1002 additions and 954 deletions

View file

@ -27,7 +27,7 @@ env:
# Extended STM32 Environments # Extended STM32 Environments
- TEST_PLATFORM="STM32F103RC_bigtree" - TEST_PLATFORM="STM32F103RC_bigtree"
- TEST_PLATFORM="STM32F103RC_bigtree_USB" - TEST_PLATFORM="STM32F103RC_bigtree_NOUSB"
- TEST_PLATFORM="STM32F103RC_fysetc" - TEST_PLATFORM="STM32F103RC_fysetc"
- TEST_PLATFORM="jgaurora_a5s_a1" - TEST_PLATFORM="jgaurora_a5s_a1"
- TEST_PLATFORM="STM32F103VE_longer" - TEST_PLATFORM="STM32F103VE_longer"

View file

@ -51,6 +51,14 @@
// Defines // Defines
// ------------------------ // ------------------------
#ifndef STM32_FLASH_SIZE
#ifdef MCU_STM32F103RE
#define STM32_FLASH_SIZE 512
#else
#define STM32_FLASH_SIZE 256
#endif
#endif
#ifdef SERIAL_USB #ifdef SERIAL_USB
#ifndef USE_USB_COMPOSITE #ifndef USE_USB_COMPOSITE
#define UsbSerial Serial #define UsbSerial Serial

View file

@ -470,13 +470,13 @@
#elif MB(MKS_ROBIN_LITE) #elif MB(MKS_ROBIN_LITE)
#include "stm32/pins_MKS_ROBIN_LITE.h" // STM32F1 env:mks_robin_lite #include "stm32/pins_MKS_ROBIN_LITE.h" // STM32F1 env:mks_robin_lite
#elif MB(BIGTREE_SKR_MINI_V1_1) #elif MB(BIGTREE_SKR_MINI_V1_1)
#include "stm32/pins_BIGTREE_SKR_MINI_V1_1.h" // STM32F1 env:STM32F103RC_bigtree #include "stm32/pins_BIGTREE_SKR_MINI_V1_1.h" // STM32F1 env:STM32F103RC_bigtree env:STM32F103RC_bigtree_512K env:STM32F103RC_bigtree_NOUSB env:STM32F103RC_bigtree_512K_NOUSB
#elif MB(BTT_SKR_MINI_E3_V1_2) #elif MB(BTT_SKR_MINI_E3_V1_2)
#include "stm32/pins_BTT_SKR_MINI_E3_V1_2.h" // STM32F1 env:STM32F103RC_bigtree #include "stm32/pins_BTT_SKR_MINI_E3_V1_2.h" // STM32F1 env:STM32F103RC_bigtree env:STM32F103RC_bigtree_512K env:STM32F103RC_bigtree_NOUSB env:STM32F103RC_bigtree_512K_NOUSB
#elif MB(BIGTREE_SKR_MINI_E3) #elif MB(BIGTREE_SKR_MINI_E3)
#include "stm32/pins_BIGTREE_SKR_MINI_E3.h" // STM32F1 env:STM32F103RC_bigtree #include "stm32/pins_BIGTREE_SKR_MINI_E3.h" // STM32F1 env:STM32F103RC_bigtree env:STM32F103RC_bigtree_512K env:STM32F103RC_bigtree_NOUSB env:STM32F103RC_bigtree_512K_NOUSB
#elif MB(BIGTREE_SKR_E3_DIP) #elif MB(BIGTREE_SKR_E3_DIP)
#include "stm32/pins_BIGTREE_SKR_E3_DIP.h" // STM32F1 env:STM32F103RC_bigtree #include "stm32/pins_BIGTREE_SKR_E3_DIP.h" // STM32F1 env:STM32F103RC_bigtree env:STM32F103RC_bigtree_512K env:STM32F103RC_bigtree_NOUSB env:STM32F103RC_bigtree_512K_NOUSB
#elif MB(JGAURORA_A5S_A1) #elif MB(JGAURORA_A5S_A1)
#include "stm32/pins_JGAURORA_A5S_A1.h" // STM32F1 env:jgaurora_a5s_a1 #include "stm32/pins_JGAURORA_A5S_A1.h" // STM32F1 env:jgaurora_a5s_a1
#elif MB(FYSETC_AIO_II) #elif MB(FYSETC_AIO_II)

View file

@ -33,15 +33,9 @@
// Ignore temp readings during development. // Ignore temp readings during development.
//#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000
#ifdef MCU_STM32F103RE
#define STM32_FLASH_SIZE (512 * 1024)
#else
#define STM32_FLASH_SIZE (256 * 1024)
#endif
#define FLASH_EEPROM_EMULATION #define FLASH_EEPROM_EMULATION
#define EEPROM_PAGE_SIZE uint16(0x800) // 2KB #define EEPROM_PAGE_SIZE uint16(0x800) // 2KB
#define EEPROM_START_ADDRESS uint32(0x8000000 + STM32_FLASH_SIZE - 2 * EEPROM_PAGE_SIZE) #define EEPROM_START_ADDRESS uint32(0x8000000 + (STM32_FLASH_SIZE) * 1024 - 2 * EEPROM_PAGE_SIZE)
#undef E2END #undef E2END
#define E2END (EEPROM_PAGE_SIZE - 1) // 2KB #define E2END (EEPROM_PAGE_SIZE - 1) // 2KB

View file

@ -33,15 +33,9 @@
// Ignore temp readings during development. // Ignore temp readings during development.
//#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000
#ifdef MCU_STM32F103RE
#define STM32_FLASH_SIZE (512 * 1024)
#else
#define STM32_FLASH_SIZE (256 * 1024)
#endif
#define FLASH_EEPROM_EMULATION #define FLASH_EEPROM_EMULATION
#define EEPROM_PAGE_SIZE uint16(0x800) // 2KB #define EEPROM_PAGE_SIZE uint16(0x800) // 2KB
#define EEPROM_START_ADDRESS uint32(0x8000000 + STM32_FLASH_SIZE - 2 * EEPROM_PAGE_SIZE) #define EEPROM_START_ADDRESS uint32(0x8000000 + (STM32_FLASH_SIZE) * 1024 - 2 * EEPROM_PAGE_SIZE)
#undef E2END #undef E2END
#define E2END (EEPROM_PAGE_SIZE - 1) // 2KB #define E2END (EEPROM_PAGE_SIZE - 1) // 2KB

View file

@ -33,15 +33,9 @@
// Ignore temp readings during development. // Ignore temp readings during development.
//#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000
#ifdef MCU_STM32F103RE
#define STM32_FLASH_SIZE (512 * 1024)
#else
#define STM32_FLASH_SIZE (256 * 1024)
#endif
#define FLASH_EEPROM_EMULATION #define FLASH_EEPROM_EMULATION
#define EEPROM_PAGE_SIZE (0x800) // 2KB #define EEPROM_PAGE_SIZE (0x800) // 2KB
#define EEPROM_START_ADDRESS (0x8000000 + STM32_FLASH_SIZE - 2 * EEPROM_PAGE_SIZE) #define EEPROM_START_ADDRESS uint32(0x8000000 + (STM32_FLASH_SIZE) * 1024 - 2 * EEPROM_PAGE_SIZE)
#define E2END (EEPROM_PAGE_SIZE - 1) #define E2END (EEPROM_PAGE_SIZE - 1)
// //

View file

@ -35,7 +35,7 @@
#define FLASH_EEPROM_EMULATION #define FLASH_EEPROM_EMULATION
#define EEPROM_PAGE_SIZE uint16(0x800) // 2KB #define EEPROM_PAGE_SIZE uint16(0x800) // 2KB
#define EEPROM_START_ADDRESS uint32(0x8000000 + 256 * 1024 - 2 * EEPROM_PAGE_SIZE) #define EEPROM_START_ADDRESS uint32(0x8000000 + (STM32_FLASH_SIZE) * 1024 - 2 * EEPROM_PAGE_SIZE)
#undef E2END #undef E2END
#define E2END (EEPROM_PAGE_SIZE - 1) // 2KB #define E2END (EEPROM_PAGE_SIZE - 1) // 2KB

View file

@ -0,0 +1,14 @@
MEMORY
{
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K - 40
rom (rx) : ORIGIN = 0x08007000, LENGTH = 512K - 28K
}
/* Provide memory region aliases for common.inc */
REGION_ALIAS("REGION_TEXT", rom);
REGION_ALIAS("REGION_DATA", ram);
REGION_ALIAS("REGION_BSS", ram);
REGION_ALIAS("REGION_RODATA", rom);
/* Let common.inc handle the real work. */
INCLUDE common.inc

View file

@ -1,13 +1,18 @@
import os import os
Import("env") Import("env")
# Relocate firmware from 0x08000000 to 0x08007000 STM32_FLASH_SIZE = 256
for define in env['CPPDEFINES']: for define in env['CPPDEFINES']:
if define[0] == "VECT_TAB_ADDR": if define[0] == "VECT_TAB_ADDR":
env['CPPDEFINES'].remove(define) env['CPPDEFINES'].remove(define)
if define[0] == "STM32_FLASH_SIZE":
STM32_FLASH_SIZE = define[1]
# Relocate firmware from 0x08000000 to 0x08007000
env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000")) env['CPPDEFINES'].append(("VECT_TAB_ADDR", "0x08007000"))
custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103RC_SKR_MINI.ld") custom_ld_script = os.path.abspath("buildroot/share/PlatformIO/ldscripts/STM32F103RC_SKR_MINI_" + str(STM32_FLASH_SIZE) + "K.ld")
for i, flag in enumerate(env["LINKFLAGS"]): for i, flag in enumerate(env["LINKFLAGS"]):
if "-Wl,-T" in flag: if "-Wl,-T" in flag:
env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script env["LINKFLAGS"][i] = "-Wl,-T" + custom_ld_script

View file

@ -75,10 +75,10 @@ from __future__ import division
import sys import sys
import os import os
pwd = os.getcwd() # make sure we're executing from the correct directory level pwd = os.getcwd() # make sure we're executing from the correct directory level
pwd = pwd.replace('\\', '/') pwd = pwd.replace('\\', '/')
if 0 <= pwd.find('buildroot/share/atom'): if 0 <= pwd.find('buildroot/share/atom'):
pwd = pwd[ : pwd.find('buildroot/share/atom')] pwd = pwd[:pwd.find('buildroot/share/atom')]
os.chdir(pwd) os.chdir(pwd)
print('pwd: ', pwd) print('pwd: ', pwd)
@ -93,7 +93,7 @@ print('build_type: ', build_type)
print('\nWorking\n') print('\nWorking\n')
python_ver = sys.version_info[0] # major version - 2 or 3 python_ver = sys.version_info[0] # major version - 2 or 3
print("python version " + str(sys.version_info[0]) + "." + str(sys.version_info[1]) + "." + str(sys.version_info[2])) print("python version " + str(sys.version_info[0]) + "." + str(sys.version_info[1]) + "." + str(sys.version_info[2]))
@ -118,8 +118,6 @@ from datetime import datetime, date, time
# reboot # reboot
######### #########
########################################################################################## ##########################################################################################
# #
# popup to get input from user # popup to get input from user
@ -128,79 +126,83 @@ from datetime import datetime, date, time
def get_answer(board_name, cpu_label_txt, cpu_a_txt, cpu_b_txt): 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
if python_ver == 2: def CPU_exit_3(): # forward declare functions
import Tkinter as tk CPU_exit_3_()
else:
import tkinter as tk
def CPU_exit_3(): # forward declare functions def got_answer():
got_answer_()
CPU_exit_3_() def kill_session():
def CPU_exit_4(): kill_session_()
CPU_exit_4_() root_get_answer = tk.Tk()
def kill_session(): root_get_answer.title('')
kill_session_() root_get_answer.withdraw()
root_get_answer.deiconify()
root_get_answer = tk.Tk() def disable_event():
root_get_answer.attributes("-topmost", True) pass
root_get_answer.chk_state_1 = 1 # declare variables used by TK and enable root_get_answer.protocol("WM_DELETE_WINDOW", disable_event)
root_get_answer.resizable(False, False)
chk_state_1 = 0 # set initial state of check boxes root_get_answer.radio_state = 1 # declare variables used by TK and enable
global get_answer_val
get_answer_val = 2 # return get_answer_val, set default to match radio_state default
global get_answer_val radio_state = tk.IntVar()
get_answer_val = 2 # return get_answer_val, set default to match chk_state_1 default radio_state.set(get_answer_val)
l1 = tk.Label(text=board_name, fg="light green", bg="dark green",
font="default 14 bold").grid(row=0, columnspan=2, sticky='EW', ipadx=2, ipady=2)
l1 = tk.Label(text=board_name, l2 = tk.Label(text=cpu_label_txt).grid(row=1, pady=4, columnspan=2, sticky='EW')
fg = "light green",
bg = "dark green",
font = "Helvetica 12 bold").grid(row=1)
l2 = tk.Label(text=cpu_label_txt, b4 = tk.Radiobutton(
fg = "light green", text=cpu_a_txt,
bg = "dark green", fg="black",
font = "Helvetica 16 bold italic").grid(row=2) bg="lightgray",
relief=tk.SUNKEN,
selectcolor="green",
variable=radio_state,
value=1,
indicatoron=0,
command=CPU_exit_3
).grid(row=2, pady=1, ipady=2, ipadx=10, columnspan=2)
b4 = tk.Checkbutton(text=cpu_a_txt, b5 = tk.Radiobutton(
fg = "black", text=cpu_b_txt,
font = "Times 20 bold ", fg="black",
variable=chk_state_1, onvalue=1, offvalue=0, bg="lightgray",
relief=tk.SUNKEN,
selectcolor="green",
variable=radio_state,
value=2,
indicatoron=0,
command=CPU_exit_3
).grid(row=3, pady=1, ipady=2, ipadx=10, columnspan=2) # use same variable but inverted so they will track
command = CPU_exit_3).grid(row=3) b6 = tk.Button(text="Cancel", fg="red", command=kill_session).grid(row=4, column=0, padx=4, pady=4, ipadx=2, ipady=2)
b5 = tk.Checkbutton(text=cpu_b_txt, b7 = tk.Button(text="Continue", fg="green", command=got_answer).grid(row=4, column=1, padx=4, pady=4, ipadx=2, ipady=2)
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 def got_answer_():
b6 = tk.Button(text="CONFIRM", root_get_answer.destroy()
fg = "blue",
font = "Times 20 bold ",
command = root_get_answer.destroy).grid(row=5, pady=4)
b7 = tk.Button(text="CANCEL", def CPU_exit_3_():
fg = "red", global get_answer_val
font = "Times 12 bold ", get_answer_val = radio_state.get()
command = kill_session).grid(row=6, pady=4)
def kill_session_():
raise SystemExit(0) # kill everything
def CPU_exit_3_(): root_get_answer.mainloop()
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 # end - get answer
@ -209,102 +211,101 @@ def get_answer(board_name, cpu_label_txt, cpu_a_txt, cpu_b_txt):
# move custom board definitions from project folder to PlatformIO # move custom board definitions from project folder to PlatformIO
# #
def resolve_path(path): def resolve_path(path):
import os import os
# turn the selection into a partial path # turn the selection into a partial path
if 0 <= path.find('"'): if 0 <= path.find('"'):
path = path[ path.find('"') : ] path = path[path.find('"'):]
if 0 <= path.find(', line '): if 0 <= path.find(', line '):
path = path.replace(', line ', ':') path = path.replace(', line ', ':')
path = path.replace('"', '') path = path.replace('"', '')
#get line and column numbers # get line and column numbers
line_num = 1 line_num = 1
column_num = 1 column_num = 1
line_start = path.find(':', 2) # use 2 here so don't eat Windows full path line_start = path.find(':', 2) # use 2 here so don't eat Windows full path
column_start = path.find(':', line_start + 1) column_start = path.find(':', line_start + 1)
if column_start == -1: if column_start == -1:
column_start = len(path) column_start = len(path)
column_end = path.find(':', column_start + 1) column_end = path.find(':', column_start + 1)
if column_end == -1: if column_end == -1:
column_end = len(path) column_end = len(path)
if 0 <= line_start: if 0 <= line_start:
line_num = path[ line_start + 1 : column_start] line_num = path[line_start + 1:column_start]
if line_num == '': if line_num == '':
line_num = 1 line_num = 1
if column_start != column_end: if column_start != column_end:
column_num = path[ column_start + 1 : column_end] column_num = path[column_start + 1:column_end]
if column_num == '': if column_num == '':
column_num = 0 column_num = 0
index_end = path.find(',') index_end = path.find(',')
if 0 <= index_end: if 0 <= index_end:
path = path[ : index_end] # delete comma and anything after path = path[:index_end] # delete comma and anything after
index_end = path.find(':', 2) index_end = path.find(':', 2)
if 0 <= index_end: if 0 <= index_end:
path = path[ : path.find(':', 2)] # delete the line number and anything after path = path[:path.find(':', 2)] # delete the line number and anything after
path = path.replace('\\','/') path = path.replace('\\', '/')
if 1 == path.find(':') and current_OS == 'Windows': if 1 == path.find(':') and current_OS == 'Windows':
return path, line_num, column_num # found a full path - no need for further processing return path, line_num, column_num # found a full path - no need for further processing
elif 0 == path.find('/') and (current_OS == 'Linux' or current_OS == 'Darwin'): elif 0 == path.find('/') and (current_OS == 'Linux' or current_OS == 'Darwin'):
return path, line_num, column_num # found a full path - no need for further processing return path, line_num, column_num # found a full path - no need for further processing
else: else:
# resolve as many '../' as we can # resolve as many '../' as we can
while 0 <= path.find('../'): while 0 <= path.find('../'):
end = path.find('../') - 1 end = path.find('../') - 1
start = path.find('/') start = path.find('/')
while 0 <= path.find('/',start) and end > path.find('/',start): while 0 <= path.find('/', start) and end > path.find('/', start):
start = path.find('/',start) + 1 start = path.find('/', start) + 1
path = path[0:start] + path[end + 4: ] path = path[0:start] + path[end + 4:]
# this is an alternative to the above - it just deletes the '../' section # this is an alternative to the above - it just deletes the '../' section
# start_temp = path.find('../') # start_temp = path.find('../')
# while 0 <= path.find('../',start_temp): # while 0 <= path.find('../',start_temp):
# start = path.find('../',start_temp) # start = path.find('../',start_temp)
# start_temp = start + 1 # start_temp = start + 1
# if 0 <= start: # if 0 <= start:
# path = path[start + 2 : ] # path = path[start + 2 : ]
start = path.find('/')
if start != 0: # make sure path starts with '/'
while 0 == path.find(' '): # eat any spaces at the beginning
path = path[1:]
path = '/' + path
start = path.find('/') if current_OS == 'Windows':
if start != 0: # make sure path starts with '/' search_path = path.replace('/', '\\') # os.walk uses '\' in Windows
while 0 == path.find(' '): # eat any spaces at the beginning else:
path = path[ 1 : ] search_path = path
path = '/' + path
if current_OS == 'Windows': start_path = os.path.abspath('')
search_path = path.replace('/', '\\') # os.walk uses '\' in Windows
else:
search_path = path
start_path = os.path.abspath('') # search project directory for the selection
found = False
full_path = ''
for root, directories, filenames in os.walk(start_path):
for filename in filenames:
if 0 <= root.find('.git'): # don't bother looking in this directory
break
full_path = os.path.join(root, filename)
if 0 <= full_path.find(search_path):
found = True
break
if found:
break
# search project directory for the selection return full_path, line_num, column_num
found = False
full_path = ''
for root, directories, filenames in os.walk(start_path):
for filename in filenames:
if 0 <= root.find('.git'): # don't bother looking in this directory
break
full_path = os.path.join(root,filename)
if 0 <= full_path.find(search_path):
found = True
break
if found:
break
return full_path, line_num, column_num
# end - resolve_path # end - resolve_path
# #
# Opens the file in the preferred editor at the line & column number # Open the file in the preferred editor at the line & column number
# If the preferred editor isn't already running then it tries the next. # If the preferred editor isn't already running then it tries the next.
# If none are open then the system default is used. # If none are open then the system default is used.
# #
@ -315,317 +316,331 @@ def resolve_path(path):
# 4. System default (opens at line 1, column 1 only) # 4. System default (opens at line 1, column 1 only)
# #
def open_file(path): def open_file(path):
import subprocess import subprocess
file_path, line_num, column_num = resolve_path(path) file_path, line_num, column_num = resolve_path(path)
if file_path == '' : if file_path == '':
return return
if current_OS == 'Windows': if current_OS == 'Windows':
editor_note = subprocess.check_output('wmic process where "name=' + "'notepad++.exe'" + '" get ExecutablePath') editor_note = subprocess.check_output('wmic process where "name=' + "'notepad++.exe'" + '" get ExecutablePath')
editor_sublime = subprocess.check_output('wmic process where "name=' + "'sublime_text.exe'" + '" get ExecutablePath') editor_sublime = subprocess.check_output('wmic process where "name=' + "'sublime_text.exe'" + '" get ExecutablePath')
editor_atom = subprocess.check_output('wmic process where "name=' + "'atom.exe'" + '" get ExecutablePath') editor_atom = subprocess.check_output('wmic process where "name=' + "'atom.exe'" + '" get ExecutablePath')
if 0 <= editor_note.find('notepad++.exe'): if 0 <= editor_note.find('notepad++.exe'):
start = editor_note.find('\n') + 1 start = editor_note.find('\n') + 1
end = editor_note.find('\n',start + 5) -4 end = editor_note.find('\n', start + 5) - 4
editor_note = editor_note[ start : end] editor_note = editor_note[start:end]
command = file_path , ' -n' + str(line_num) , ' -c' + str(column_num) command = file_path, ' -n' + str(line_num), ' -c' + str(column_num)
subprocess.Popen([editor_note, command]) subprocess.Popen([editor_note, command])
elif 0 <= editor_sublime.find('sublime_text.exe'): elif 0 <= editor_sublime.find('sublime_text.exe'):
start = editor_sublime.find('\n') + 1 start = editor_sublime.find('\n') + 1
end = editor_sublime.find('\n',start + 5) -4 end = editor_sublime.find('\n', start + 5) - 4
editor_sublime = editor_sublime[ start : end] editor_sublime = editor_sublime[start:end]
command = file_path + ':' + line_num + ':' + column_num command = file_path + ':' + line_num + ':' + column_num
subprocess.Popen([editor_sublime, command]) subprocess.Popen([editor_sublime, command])
elif 0 <= editor_atom.find('atom.exe'): elif 0 <= editor_atom.find('atom.exe'):
start = editor_atom.find('\n') + 1 start = editor_atom.find('\n') + 1
end = editor_atom.find('\n',start + 5) -4 end = editor_atom.find('\n', start + 5) - 4
editor_atom = editor_atom[ start : end] editor_atom = editor_atom[start:end]
command = file_path + ':' + str(line_num) + ':' + str(column_num) command = file_path + ':' + str(line_num) + ':' + str(column_num)
subprocess.Popen([editor_atom, command]) subprocess.Popen([editor_atom, command])
else: else:
os.startfile(resolve_path(path)) # open file with default app os.startfile(resolve_path(path)) # open file with default app
elif current_OS == 'Linux': elif current_OS == 'Linux':
command = file_path + ':' + str(line_num) + ':' + str(column_num) command = file_path + ':' + str(line_num) + ':' + str(column_num)
index_end = command.find(',') index_end = command.find(',')
if 0 <= index_end: if 0 <= index_end:
command = command[ : index_end] # sometimes a comma magically appears, don't want it command = command[:index_end] # sometimes a comma magically appears, don't want it
running_apps = subprocess.Popen('ps ax -o cmd', stdout=subprocess.PIPE, shell=True) running_apps = subprocess.Popen('ps ax -o cmd', stdout=subprocess.PIPE, shell=True)
(output, err) = running_apps.communicate() (output, err) = running_apps.communicate()
temp = output.split('\n') temp = output.split('\n')
def find_editor_linux(name, search_obj): def find_editor_linux(name, search_obj):
for line in search_obj: for line in search_obj:
if 0 <= line.find(name): if 0 <= line.find(name):
path = line path = line
return True, path return True, path
return False , '' return False, ''
(success_sublime, editor_path_sublime) = find_editor_linux('sublime_text',temp) (success_sublime, editor_path_sublime) = find_editor_linux('sublime_text', temp)
(success_atom, editor_path_atom) = find_editor_linux('atom',temp) (success_atom, editor_path_atom) = find_editor_linux('atom', temp)
if success_sublime: if success_sublime:
subprocess.Popen([editor_path_sublime, command]) subprocess.Popen([editor_path_sublime, command])
elif success_atom: elif success_atom:
subprocess.Popen([editor_path_atom, command]) subprocess.Popen([editor_path_atom, command])
else: else:
os.system('xdg-open ' + file_path ) os.system('xdg-open ' + file_path)
elif current_OS == 'Darwin': # MAC elif current_OS == 'Darwin': # MAC
command = file_path + ':' + str(line_num) + ':' + str(column_num) command = file_path + ':' + str(line_num) + ':' + str(column_num)
index_end = command.find(',') index_end = command.find(',')
if 0 <= index_end: if 0 <= index_end:
command = command[ : index_end] # sometimes a comma magically appears, don't want it command = command[:index_end] # sometimes a comma magically appears, don't want it
running_apps = subprocess.Popen('ps axwww -o command', stdout=subprocess.PIPE, shell=True) running_apps = subprocess.Popen('ps axwww -o command', stdout=subprocess.PIPE, shell=True)
(output, err) = running_apps.communicate() (output, err) = running_apps.communicate()
temp = output.split('\n') temp = output.split('\n')
def find_editor_mac(name, search_obj): def find_editor_mac(name, search_obj):
for line in search_obj: for line in search_obj:
if 0 <= line.find(name): if 0 <= line.find(name):
path = line path = line
if 0 <= path.find('-psn'): if 0 <= path.find('-psn'):
path = path[ : path.find('-psn') - 1 ] path = path[:path.find('-psn') - 1]
return True, path return True, path
return False , '' return False, ''
(success_sublime, editor_path_sublime) = find_editor_mac('Sublime',temp) (success_sublime, editor_path_sublime) = find_editor_mac('Sublime', temp)
(success_atom, editor_path_atom) = find_editor_mac('Atom',temp) (success_atom, editor_path_atom) = find_editor_mac('Atom', temp)
if success_sublime: if success_sublime:
subprocess.Popen([editor_path_sublime, command]) subprocess.Popen([editor_path_sublime, command])
elif success_atom: elif success_atom:
subprocess.Popen([editor_path_atom, command]) subprocess.Popen([editor_path_atom, command])
else:
os.system('open ' + file_path)
else:
os.system('open ' + file_path )
# end - open_file # end - open_file
# gets the last build environment # Get the last build environment
def get_build_last(): def get_build_last():
env_last = '' env_last = ''
DIR_PWD = os.listdir('.') DIR_PWD = os.listdir('.')
if '.pio' in DIR_PWD: if '.pio' in DIR_PWD:
date_last = 0.0 date_last = 0.0
DIR__pioenvs = os.listdir('.pio') DIR__pioenvs = os.listdir('.pio')
for name in DIR__pioenvs: for name in DIR__pioenvs:
if 0 <= name.find('.') or 0 <= name.find('-'): # skip files in listing if 0 <= name.find('.') or 0 <= name.find('-'): # skip files in listing
continue continue
DIR_temp = os.listdir('.pio/build/' + name) DIR_temp = os.listdir('.pio/build/' + name)
for names_temp in DIR_temp: for names_temp in DIR_temp:
if 0 == names_temp.find('firmware.'): if 0 == names_temp.find('firmware.'):
date_temp = os.path.getmtime('.pio/build/' + name + '/' + names_temp) date_temp = os.path.getmtime('.pio/build/' + name + '/' + names_temp)
if date_temp > date_last: if date_temp > date_last:
date_last = date_temp date_last = date_temp
env_last = name env_last = name
return env_last return env_last
# gets the board being built from the Configuration.h file # Get the board being built from the Configuration.h file
# returns: board name, major version of Marlin being used (1 or 2) # return: board name, major version of Marlin being used (1 or 2)
def get_board_name(): def get_board_name():
board_name = '' board_name = ''
# get board name # get board name
with open('Marlin/Configuration.h', 'r') as myfile: with open('Marlin/Configuration.h', 'r') as myfile:
Configuration_h = myfile.read() Configuration_h = myfile.read()
Configuration_h = Configuration_h.split('\n') Configuration_h = Configuration_h.split('\n')
Marlin_ver = 0 # set version to invalid number Marlin_ver = 0 # set version to invalid number
for lines in Configuration_h: for lines in Configuration_h:
if 0 == lines.find('#define CONFIGURATION_H_VERSION 01'): if 0 == lines.find('#define CONFIGURATION_H_VERSION 01'):
Marlin_ver = 1 Marlin_ver = 1
if 0 == lines.find('#define CONFIGURATION_H_VERSION 02'): if 0 == lines.find('#define CONFIGURATION_H_VERSION 02'):
Marlin_ver = 2 Marlin_ver = 2
board = lines.find(' BOARD_') + 1 board = lines.find(' BOARD_') + 1
motherboard = lines.find(' MOTHERBOARD ') + 1 motherboard = lines.find(' MOTHERBOARD ') + 1
define = lines.find('#define ') define = lines.find('#define ')
comment = lines.find('//') comment = lines.find('//')
if (comment == -1 or comment > board) and \ if (comment == -1 or comment > board) and \
board > motherboard and \ board > motherboard and \
motherboard > define and \ motherboard > define and \
define >= 0 : define >= 0 :
spaces = lines.find(' ', board) # find the end of the board substring spaces = lines.find(' ', board) # find the end of the board substring
if spaces == -1: if spaces == -1:
board_name = lines[board : ] board_name = lines[board:]
else: else:
board_name = lines[board : spaces] board_name = lines[board:spaces]
break break
return board_name, Marlin_ver
return board_name, Marlin_ver # extract first environment name found after the start position
# return: environment name and position to start the next search from
# 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): def get_env_from_line(line, start_position):
env = '' env = ''
next_position = -1 next_position = -1
env_position = line.find('env:', start_position) env_position = line.find('env:', start_position)
if 0 < env_position: if 0 < env_position:
next_position = line.find(' ', env_position + 4) next_position = line.find(' ', env_position + 4)
if 0 < next_position: if 0 < next_position:
env = line[env_position + 4 : next_position] env = line[env_position + 4:next_position]
else: else:
env = line[env_position + 4 : ] # at the end of the line env = line[env_position + 4:] # at the end of the line
return env, next_position return env, next_position
# scan pins.h for board name and return the environment(s) found
#scans pins.h for board name and returns the environment(s) it finds
def get_starting_env(board_name_full, version): def get_starting_env(board_name_full, version):
# get environment starting point # get environment starting point
if version == 1: if version == 1:
path = 'Marlin/pins.h' path = 'Marlin/pins.h'
if version == 2: if version == 2:
path = 'Marlin/src/pins/pins.h' path = 'Marlin/src/pins/pins.h'
with open(path, 'r') as myfile: with open(path, 'r') as myfile:
pins_h = myfile.read() pins_h = myfile.read()
env_A = '' env_A = ''
env_B = '' env_B = ''
env_C = '' env_C = ''
board_name = board_name_full[ 6 : ] # only use the part after "BOARD_" since we're searching the pins.h file 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') pins_h = pins_h.split('\n')
environment = '' environment = ''
board_line = '' board_line = ''
cpu_A = '' cpu_A = ''
cpu_B = '' cpu_B = ''
i = 0 i = 0
list_start_found = False list_start_found = False
for lines in pins_h: for lines in pins_h:
i = i + 1 # i is always one ahead of the index into 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"): if 0 < lines.find("Unknown MOTHERBOARD value set in Configuration.h"):
break # no more break # no more
if 0 < lines.find('1280'): if 0 < lines.find('1280'):
list_start_found = True list_start_found = True
if list_start_found == False: # skip lines until find start of CPU list if list_start_found == False: # skip lines until find start of CPU list
continue continue
board = lines.find(board_name) board = lines.find(board_name)
comment_start = lines.find('// ') comment_start = lines.find('// ')
cpu_A_loc = comment_start cpu_A_loc = comment_start
cpu_B_loc = 0 cpu_B_loc = 0
if board > 0: # need to look at the next line for environment info if board > 0: # need to look at the next line for environment info
cpu_line = pins_h[i] cpu_line = pins_h[i]
comment_start = cpu_line.find('// ') 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_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_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 env_C, next_position = get_env_from_line(cpu_line, next_position) # get next environment, if it exists
break break
return env_A, env_B, env_C return env_A, env_B, env_C
# scans input string for CPUs that the users may need to select from # Scan input string for CPUs that users may need to select from
# returns: CPU name # return: CPU name
def get_CPU_name(environment): def get_CPU_name(environment):
CPU_list = ('1280', '2560','644', '1284', 'LPC1768', 'DUE') CPU_list = ('1280', '2560', '644', '1284', 'LPC1768', 'DUE')
CPU_name = '' CPU_name = ''
for CPU in CPU_list: for CPU in CPU_list:
if 0 < environment.find(CPU): if 0 < environment.find(CPU):
return CPU return CPU
# get environment to be used for the build # get environment to be used for the build
# returns: environment # return: environment
def get_env(board_name, ver_Marlin): 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(): def no_environment():
print('ERROR - invalid board') print('ERROR - no environment for this board')
print(board_name) print(board_name)
raise SystemExit(0) # quit if unable to find board 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? ") ) CPU_question = (('1280', '2560', '1280 or 2560 CPU?'), ('644', '1284', '644 or 1284 CPU?'))
if 0 < board_name.find('MELZI') : if 0 < board_name.find('MELZI'):
get_answer(' ' + board_name + ' ', " Which flavor of Melzi? ", "Melzi (Optiboot bootloader)", "Melzi ") get_answer(
if 1 == get_answer_val: board_name, " Which flavor of Melzi? ", "Melzi (Optiboot bootloader)", "Melzi "
target_env = 'melzi_optiboot' )
else: if 1 == get_answer_val:
target_env = 'melzi' 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: else:
env_A, env_B, env_C = get_starting_env(board_name, ver_Marlin) 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 Download Port?', '(Native) USB port', 'Programming port')
if 1 == get_answer_val:
target_env = 'DUE_USB'
else:
target_env = 'DUE'
elif env_A == 'STM32F103RC_bigtree':
get_answer(board_name, 'RCT6 Flash Size?', '512K', '256K')
if 1 == get_answer_val:
target_env = 'STM32F103RC_bigtree_512K'
else:
target_env = 'STM32F103RC_bigtree'
get_answer(board_name, 'USB Support?', 'No USB', 'USB')
if 1 == get_answer_val:
target_env += '_NOUSB'
else:
invalid_board()
if env_A == '': if build_type == 'traceback' and target_env != 'LPC1768_debug_and_upload' and target_env != 'DUE_debug' and Marlin_ver == 2:
no_environment() print("ERROR - this board isn't setup for traceback")
if env_B == '': print('board_name: ', board_name)
return env_A # only one environment so finished print('target_env: ', target_env)
raise SystemExit(0)
CPU_A = get_CPU_name(env_A) return target_env
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 target_env != 'LPC1768_debug_and_upload' and 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 # end - get_env
# puts screen text into queue so that the parent thread can fetch the data from this thread # puts screen text into queue so that the parent thread can fetch the data from this thread
if python_ver == 2: if python_ver == 2:
import Queue as queue import Queue as queue
else: else:
import queue as queue import queue as queue
IO_queue = queue.Queue() IO_queue = queue.Queue()
#PIO_queue = queue.Queue() not used! #PIO_queue = queue.Queue() not used!
def write_to_screen_queue(text, format_tag = 'normal'): def write_to_screen_queue(text, format_tag='normal'):
double_in = [text, format_tag] double_in = [text, format_tag]
IO_queue.put(double_in, block = False) IO_queue.put(double_in, block=False)
# #
# send one line to the terminal screen with syntax highlighting # send one line to the terminal screen with syntax highlighting
# #
# input: unformatted text, flags from previous run # input: unformatted text, flags from previous run
# returns: formatted text ready to go to the terminal, flags from this run # return: formatted text ready to go to the terminal, flags from this run
# #
# This routine remembers the status from call to call because previous # This routine remembers the status from call to call because previous
# lines can affect how the current line is highlighted # lines can affect how the current line is highlighted
@ -641,166 +656,164 @@ next_line_warning = False
warning_continue = False warning_continue = False
line_counter = 0 line_counter = 0
def line_print(line_input): def line_print(line_input):
global warning global warning
global warning_FROM global warning_FROM
global error global error
global standard global standard
global prev_line_COM global prev_line_COM
global next_line_warning global next_line_warning
global warning_continue global warning_continue
global line_counter global line_counter
# all '0' elements must precede all '1' elements or they'll be skipped # all '0' elements must precede all '1' elements or they'll be skipped
platformio_highlights = [ platformio_highlights = [
['Environment', 0, 'highlight_blue'], ['Environment', 0, 'highlight_blue'], ['[SKIP]', 1, 'warning'], ['[IGNORED]', 1, 'warning'], ['[ERROR]', 1, 'error'],
['[SKIP]', 1, 'warning'], ['[FAILED]', 1, 'error'], ['[SUCCESS]', 1, 'highlight_green']
['[IGNORED]', 1, 'warning'], ]
['[ERROR]', 1, 'error'],
['[FAILED]', 1, 'error'],
['[SUCCESS]', 1, 'highlight_green']
]
def write_to_screen_with_replace(text, highlights): # search for highlights & split line accordingly def write_to_screen_with_replace(text, highlights): # search for highlights & split line accordingly
did_something = False did_something = False
for highlight in highlights: for highlight in highlights:
found = text.find(highlight[0]) found = text.find(highlight[0])
if did_something == True: if did_something == True:
break break
if found >= 0 : if found >= 0:
did_something = True did_something = True
if 0 == highlight[1]: if 0 == highlight[1]:
found_1 = text.find(' ') found_1 = text.find(' ')
found_tab = text.find('\t') found_tab = text.find('\t')
if found_1 < 0 or found_1 > found_tab: if found_1 < 0 or found_1 > found_tab:
found_1 = found_tab found_1 = found_tab
write_to_screen_queue(text[ : found_1 + 1 ]) write_to_screen_queue(text[:found_1 + 1])
for highlight_2 in highlights: for highlight_2 in highlights:
if highlight[0] == highlight_2[0] : if highlight[0] == highlight_2[0]:
continue continue
found = text.find(highlight_2[0]) found = text.find(highlight_2[0])
if found >= 0 : if found >= 0:
found_space = text.find(' ', found_1 + 1) found_space = text.find(' ', found_1 + 1)
found_tab = text.find('\t', found_1 + 1) found_tab = text.find('\t', found_1 + 1)
if found_space < 0 or found_space > found_tab: if found_space < 0 or found_space > found_tab:
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) found_right = text.find(']', found + 1)
write_to_screen_queue(text[ : found + 1 ]) write_to_screen_queue(text[found_1 + 1:found_space + 1], highlight[2])
write_to_screen_queue(text[found + 1 : found_right ], highlight[2]) write_to_screen_queue(text[found_space + 1:found + 1])
write_to_screen_queue(text[found_right : ] + '\n' + '\n') write_to_screen_queue(text[found + 1:found_right], highlight_2[2])
break write_to_screen_queue(text[found_right:] + '\n')
if did_something == False: break
r_loc = text.find('\r') + 1 break
if r_loc > 0 and r_loc < len(text): # need to split this line if 1 == highlight[1]:
text = text.split('\r') found_right = text.find(']', found + 1)
for line in text: write_to_screen_queue(text[:found + 1])
if line != '': write_to_screen_queue(text[found + 1:found_right], highlight[2])
write_to_screen_queue(line + '\n') write_to_screen_queue(text[found_right:] + '\n' + '\n')
else: break
write_to_screen_queue(text + '\n') if did_something == False:
# end - write_to_screen_with_replace r_loc = text.find('\r') + 1
if r_loc > 0 and r_loc < len(text): # need to split this line
text = text.split('\r')
# scan the line for line in text:
line_counter = line_counter + 1 if line != '':
max_search = len(line_input) write_to_screen_queue(line + '\n')
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 0 < line_input.find('Thank you') or 0 < line_input.find('SUMMARY') :
warning = False #standard line found
warning_FROM = False
error = False
standard = True
prev_line_COM = False
warning_continue = False
elif 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 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 beginning == 'fro' and warning == True or \
beginning == '.pi' : # start of warning /error block
warning_FROM = True
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 or an error
error = False
standard = False
prev_line_COM = False
warning_continue = True
else: else:
warning = False # unknown so assume standard line write_to_screen_queue(text + '\n')
warning_FROM = False
error = False
standard = True
prev_line_COM = False
warning_continue = False
if beginning == 'Com': # end - write_to_screen_with_replace
prev_line_COM = True
# scan the line
line_counter = line_counter + 1
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 0 < line_input.find('Thank you') or 0 < line_input.find('SUMMARY'):
warning = False #standard line found
warning_FROM = False
error = False
standard = True
prev_line_COM = False
warning_continue = False
elif 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 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 beginning == 'fro' and warning == True or \
beginning == '.pi' : # start of warning /error block
warning_FROM = True
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 or an error
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')
# 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 # end - line_print
@ -810,7 +823,6 @@ def line_print(line_input):
# # # #
########################################################################## ##########################################################################
# build platformio run -e target_env # build platformio run -e target_env
# clean platformio run --target clean -e target_env # clean platformio run --target clean -e target_env
# upload platformio run --target upload -e target_env # upload platformio run --target upload -e target_env
@ -823,478 +835,467 @@ def line_print(line_input):
def sys_PIO(): def sys_PIO():
########################################################################## ##########################################################################
# # # #
# run Platformio inside the same shell as this Python script # # run Platformio inside the same shell as this Python script #
# # # #
########################################################################## ##########################################################################
global build_type global build_type
global target_env global target_env
import os import os
print('build_type: ', build_type) print('build_type: ', build_type)
print('starting platformio') print('starting platformio')
if build_type == 'build': if build_type == 'build':
# pio_result = os.system("echo -en '\033c'") # pio_result = os.system("echo -en '\033c'")
pio_result = os.system('platformio run -e ' + target_env) pio_result = os.system('platformio run -e ' + target_env)
elif build_type == 'clean': elif build_type == 'clean':
pio_result = os.system('platformio run --target clean -e ' + target_env) pio_result = os.system('platformio run --target clean -e ' + target_env)
elif build_type == 'upload': elif build_type == 'upload':
pio_result = os.system('platformio run --target upload -e ' + target_env) pio_result = os.system('platformio run --target upload -e ' + target_env)
elif build_type == 'traceback': elif build_type == 'traceback':
pio_result = os.system('platformio run --target upload -e ' + target_env) pio_result = os.system('platformio run --target upload -e ' + target_env)
elif build_type == 'program': elif build_type == 'program':
pio_result = os.system('platformio run --target program -e ' + target_env) pio_result = os.system('platformio run --target program -e ' + target_env)
elif build_type == 'test': elif build_type == 'test':
pio_result = os.system('platformio test upload -e ' + target_env) pio_result = os.system('platformio test upload -e ' + target_env)
elif build_type == 'remote': elif build_type == 'remote':
pio_result = os.system('platformio remote run --target program -e ' + target_env) pio_result = os.system('platformio remote run --target program -e ' + target_env)
elif build_type == 'debug': elif build_type == 'debug':
pio_result = os.system('platformio debug -e ' + target_env) pio_result = os.system('platformio debug -e ' + target_env)
else: else:
print('ERROR - unknown build type: ', build_type) print('ERROR - unknown build type: ', build_type)
raise SystemExit(0) # kill everything raise SystemExit(0) # kill everything
# stream output from subprocess and split it into lines # stream output from subprocess and split it into lines
#for line in iter(pio_subprocess.stdout.readline, ''): #for line in iter(pio_subprocess.stdout.readline, ''):
# line_print(line.replace('\n', '')) # line_print(line.replace('\n', ''))
# append info used to run PlatformIO
# 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('\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('Build type: ' + build_type + '\n') # write_to_screen_queue('Environment used: ' + target_env + '\n')
# write_to_screen_queue('Environment used: ' + target_env + '\n') # write_to_screen_queue(str(datetime.now()) + '\n')
# write_to_screen_queue(str(datetime.now()) + '\n')
# end - sys_PIO # end - sys_PIO
def run_PIO(dummy): def run_PIO(dummy):
global build_type global build_type
global target_env global target_env
global board_name global board_name
print('build_type: ', build_type) print('build_type: ', build_type)
import subprocess import subprocess
import sys import sys
print('starting platformio') print('starting platformio')
if build_type == 'build': if build_type == 'build':
# platformio run -e target_env # platformio run -e target_env
# combine stdout & stderr so all compile messages are included # combine stdout & stderr so all compile messages are included
pio_subprocess = subprocess.Popen(['platformio', 'run', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 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 == 'clean': elif build_type == 'upload':
# platformio run --target clean -e target_env # platformio run --target upload -e target_env
# combine stdout & stderr so all compile messages are included # 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) 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 == 'upload': elif build_type == 'program':
# platformio run --target upload -e target_env # platformio run --target program -e target_env
# combine stdout & stderr so all compile messages are included # 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) 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 == 'traceback': elif build_type == 'remote':
# platformio run --target upload -e target_env - select the debug environment if there is one # platformio remote run --target upload -e target_env
# combine stdout & stderr so all compile messages are included # 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) 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
)
elif build_type == 'program': else:
# platformio run --target program -e target_env print('ERROR - unknown build type: ', build_type)
# combine stdout & stderr so all compile messages are included raise SystemExit(0) # kill everything
pio_subprocess = subprocess.Popen(['platformio', 'run', '--target', 'program', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# stream output from subprocess and split it into lines
if python_ver == 2:
for line in iter(pio_subprocess.stdout.readline, ''):
line_print(line.replace('\n', ''))
else:
for line in iter(pio_subprocess.stdout.readline, b''):
line = line.decode('utf-8')
line_print(line.replace('\n', ''))
elif build_type == 'test': # append info used to run PlatformIO
#platformio test upload -e target_env write_to_screen_queue('\nBoard name: ' + board_name + '\n') # put build info at the bottom of the screen
# combine stdout & stderr so all compile messages are included write_to_screen_queue('Build type: ' + build_type + '\n')
pio_subprocess = subprocess.Popen(['platformio', 'test', 'upload', '-e', target_env], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) write_to_screen_queue('Environment used: ' + target_env + '\n')
write_to_screen_queue(str(datetime.now()) + '\n')
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
if python_ver == 2:
for line in iter(pio_subprocess.stdout.readline, ''):
line_print(line.replace('\n', ''))
else:
for line in iter(pio_subprocess.stdout.readline, b''):
line = line.decode('utf-8')
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')
write_to_screen_queue(str(datetime.now()) + '\n')
# end - run_PIO # end - run_PIO
######################################################################## ########################################################################
import time import time
import threading import threading
if python_ver == 2: if python_ver == 2:
import Tkinter as tk import Tkinter as tk
import Queue as queue import Queue as queue
import ttk import ttk
from Tkinter import Tk, Frame, Text, Scrollbar, Menu from Tkinter import Tk, Frame, Text, Scrollbar, Menu
#from tkMessageBox import askokcancel this is not used: removed #from tkMessageBox import askokcancel this is not used: removed
import tkFileDialog as fileDialog import tkFileDialog as fileDialog
else: else:
import tkinter as tk import tkinter as tk
import queue as queue import queue as queue
from tkinter import ttk, Tk, Frame, Text, Scrollbar, Menu from tkinter import ttk, Tk, Frame, Text, Menu
from tkinter import filedialog
import subprocess import subprocess
import sys import sys
que = queue.Queue() que = queue.Queue()
#IO_queue = queue.Queue() #IO_queue = queue.Queue()
class output_window(Text): class output_window(Text):
# based on Super Text # based on Super Text
global continue_updates
continue_updates = True
global search_position
search_position = '' # start with invalid search position
global error_found
error_found = False # are there any errors?
def __init__(self):
self.root = tk.Tk()
self.root.attributes("-topmost", True)
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(background = 'black', foreground = 'white', font= ("consolas", 12), wrap = 'none', undo = 'True')
self.config(height=24, width=100)
self.config(insertbackground='pale green') # keyboard insertion point
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.tag_config('error_highlight_inactive', background='dim gray')
self.tag_config('error_highlight_active', background='light grey')
self.bind_class("Text", "<Control-a>", self.select_all) # required in windows, works in others
self.bind_all("<Control-Shift-E>", self.scroll_errors)
self.bind_class("<Control-Shift-R>", self.rebuild)
# scrollbar
scrb = tk.Scrollbar(self.frame, orient='vertical', command=self.yview)
self.config(yscrollcommand=scrb.set)
scrb.pack(side='right', fill='y')
#self.scrb_Y = tk.Scrollbar(self.frame, orient='vertical', command=self.yview)
#self.scrb_Y.config(yscrollcommand=self.scrb_Y.set)
#self.scrb_Y.pack(side='right', fill='y')
#self.scrb_X = tk.Scrollbar(self.frame, orient='horizontal', command=self.xview)
#self.scrb_X.config(xscrollcommand=self.scrb_X.set)
#self.scrb_X.pack(side='bottom', fill='x')
#scrb_X = tk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.xview) # tk.HORIZONTAL now have a horizsontal scroll bar BUT... shrinks it to a postage stamp and hides far right behind the vertical scroll bar
#self.config(xscrollcommand=scrb_X.set)
#scrb_X.pack(side='bottom', fill='x')
#scrb= tk.Scrollbar(self, orient='vertical', command=self.yview)
#self.config(yscrollcommand=scrb.set)
#scrb.pack(side='right', fill='y')
#self.config(height = 240, width = 1000) # didn't get the size baCK TO NORMAL
#self.pack(side='left', fill='both', expand=True) # didn't get the size baCK TO NORMAL
# pop-up menu
self.popup = tk.Menu(self, tearoff=0)
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='Cut', command=self._cut)
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.popup.add_separator()
#self.popup.add_command(label='Repeat Build(CTL-shift-r)', command=self._rebuild)
self.popup.add_command(label='Repeat Build', command=self._rebuild)
self.popup.add_separator()
self.popup.add_command(label='Scroll Errors (CTL-shift-e)', command=self._scroll_errors)
self.popup.add_separator()
self.popup.add_command(label='Open File at Cursor', command=self._open_selected_file)
if current_OS == 'Darwin': # MAC
self.bind('<Button-2>', self._show_popup) # macOS only
else:
self.bind('<Button-3>', self._show_popup) # Windows & Linux
# threading & subprocess section
def start_thread(self, ):
global continue_updates 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 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(10, self.check_thread)
def update(self):
global continue_updates
if continue_updates == True:
self.root.after(10, 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
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 _scroll_errors(self):
global search_position global search_position
search_position = '' # start with invalid search position
global error_found global error_found
error_found = False # are there any errors? if search_position == '': # first time so highlight all errors
countVar = tk.IntVar()
search_position = '1.0'
def __init__(self): search_count = 0
while search_position != '' and search_count < 100:
search_position = self.search("error", search_position, stopindex="end", count=countVar, nocase=1)
self.root = tk.Tk() search_count = search_count + 1
self.root.attributes("-topmost", True) if search_position != '':
self.frame = tk.Frame(self.root) error_found = True
self.frame.pack(fill='both', expand=True) end_pos = '{}+{}c'.format(search_position, 5)
self.tag_add("error_highlight_inactive", search_position, end_pos)
# text widget search_position = '{}+{}c'.format(search_position, 1) # point to the next character for new search
#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(background = 'black', foreground = 'white', font= ("consolas", 12), wrap = 'none', undo = 'True')
self.config(height = 24, width = 100)
self.config(insertbackground = 'pale green') # keyboard insertion point
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.tag_config('error_highlight_inactive', background = 'dim gray')
self.tag_config('error_highlight_active', background = 'light grey')
self.bind_class("Text","<Control-a>", self.select_all) # required in windows, works in others
self.bind_all("<Control-Shift-E>", self.scroll_errors)
self.bind_class("<Control-Shift-R>", self.rebuild)
# scrollbar
scrb = tk.Scrollbar(self.frame, orient='vertical', command=self.yview)
self.config(yscrollcommand=scrb.set)
scrb.pack(side='right', fill='y')
#self.scrb_Y = tk.Scrollbar(self.frame, orient='vertical', command=self.yview)
#self.scrb_Y.config(yscrollcommand=self.scrb_Y.set)
#self.scrb_Y.pack(side='right', fill='y')
#self.scrb_X = tk.Scrollbar(self.frame, orient='horizontal', command=self.xview)
#self.scrb_X.config(xscrollcommand=self.scrb_X.set)
#self.scrb_X.pack(side='bottom', fill='x')
#scrb_X = tk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.xview) # tk.HORIZONTAL now have a horizsontal scroll bar BUT... shrinks it to a postage stamp and hides far right behind the vertical scroll bar
#self.config(xscrollcommand=scrb_X.set)
#scrb_X.pack(side='bottom', fill='x')
#scrb= tk.Scrollbar(self, orient='vertical', command=self.yview)
#self.config(yscrollcommand=scrb.set)
#scrb.pack(side='right', fill='y')
#self.config(height = 240, width = 1000) # didn't get the size baCK TO NORMAL
#self.pack(side='left', fill='both', expand=True) # didn't get the size baCK TO NORMAL
# pop-up menu
self.popup = tk.Menu(self, tearoff=0)
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='Cut', command=self._cut)
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.popup.add_separator()
#self.popup.add_command(label='Repeat Build(CTL-shift-r)', command=self._rebuild)
self.popup.add_command(label='Repeat Build', command=self._rebuild)
self.popup.add_separator()
self.popup.add_command(label='Scroll Errors (CTL-shift-e)', command=self._scroll_errors)
self.popup.add_separator()
self.popup.add_command(label='Open File at Cursor', command=self._open_selected_file)
if current_OS == 'Darwin': # MAC
self.bind('<Button-2>', self._show_popup) # macOS only
else: else:
self.bind('<Button-3>', self._show_popup) # Windows & Linux break
if error_found:
if search_position == '':
search_position = self.search("error", '1.0', stopindex="end", nocase=1) # new search
else: # remove active highlight
end_pos = '{}+{}c'.format(search_position, 5)
start_pos = '{}+{}c'.format(search_position, -1)
self.tag_remove("error_highlight_active", start_pos, end_pos)
search_position = self.search(
"error", search_position, stopindex="end", nocase=1
) # finds first occurrence AGAIN on the first time through
if search_position == "": # wrap around
search_position = self.search("error", '1.0', stopindex="end", nocase=1)
end_pos = '{}+{}c'.format(search_position, 5)
self.tag_add("error_highlight_active", search_position, end_pos) # add active highlight
self.see(search_position)
search_position = '{}+{}c'.format(search_position, 1) # point to the next character for new search
# threading & subprocess section def scroll_errors(self, event):
self._scroll_errors()
def start_thread(self, ): def _rebuild(self):
global continue_updates #global board_name
# create then start a secondary thread to run an arbitrary function #global Marlin_ver
# must have at least one argument #global target_env
self.secondary_thread = threading.Thread(target = lambda q, arg1: q.put(run_PIO(arg1)), args=(que, '')) #board_name, Marlin_ver = get_board_name()
self.secondary_thread.start() #target_env = get_env(board_name, Marlin_ver)
continue_updates = True self.start_thread()
# check the Queue in 50ms
self.root.after(50, self.check_thread)
self.root.after(50, self.update)
def rebuild(self, event):
print("event happened")
self._rebuild()
def check_thread(self): # wait for user to kill the window def _open_selected_file(self):
global continue_updates current_line = self.index('insert')
if continue_updates == True: line_start = current_line[:current_line.find('.')] + '.0'
self.root.after(10, self.check_thread) line_end = current_line[:current_line.find('.')] + '.200'
self.mark_set("path_start", line_start)
self.mark_set("path_end", line_end)
path = self.get("path_start", "path_end")
from_loc = path.find('from ')
colon_loc = path.find(': ')
if 0 <= from_loc and ((colon_loc == -1) or (from_loc < colon_loc)):
path = path[from_loc + 5:]
if 0 <= colon_loc:
path = path[:colon_loc]
if 0 <= path.find('\\') or 0 <= path.find('/'): # make sure it really contains a path
open_file(path)
def _file_save_as(self):
self.filename = fileDialog.asksaveasfilename(defaultextension='.txt')
f = open(self.filename, 'w')
f.write(self.get('1.0', 'end'))
f.close()
def update(self): def copy(self, event):
global continue_updates try:
if continue_updates == True: selection = self.get(*self.tag_ranges('sel'))
self.root.after(10, self.update)#method is called every 50ms self.clipboard_clear()
temp_text = ['0','0'] self.clipboard_append(selection)
if IO_queue.empty(): except TypeError:
if not(self.secondary_thread.is_alive()): pass
continue_updates = False # queue is exhausted and thread is dead so no need for further updates
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)
def cut(self, event):
# text editing section 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'''
def _scroll_errors(self): if self.root.focus_get() != self:
global search_position self.root.focus_set()
global error_found
if search_position == '': # first time so highlight all errors
countVar = tk.IntVar()
search_position = '1.0'
search_count = 0
while search_position != '' and search_count < 100:
search_position = self.search("error", search_position, stopindex="end", count=countVar, nocase=1)
search_count = search_count + 1
if search_position != '':
error_found = True
end_pos = '{}+{}c'.format(search_position, 5)
self.tag_add("error_highlight_inactive", search_position, end_pos)
search_position = '{}+{}c'.format(search_position, 1) # point to the next character for new search
else:
break
if error_found: try:
if search_position == '': self.popup.tk_popup(event.x_root, event.y_root, 0)
search_position = self.search("error", '1.0', stopindex="end", nocase=1) # new search finally:
else: # remove active highlight self.popup.grab_release()
end_pos = '{}+{}c'.format(search_position, 5)
start_pos = '{}+{}c'.format(search_position, -1)
self.tag_remove("error_highlight_active", start_pos, end_pos)
search_position = self.search("error", search_position, stopindex="end", nocase=1) # finds first occurrence AGAIN on the first time through
if search_position == "": # wrap around
search_position = self.search("error", '1.0', stopindex="end", nocase=1)
end_pos = '{}+{}c'.format(search_position, 5)
self.tag_add("error_highlight_active", search_position, end_pos) # add active highlight
self.see(search_position)
search_position = '{}+{}c'.format(search_position, 1) # point to the next character for new search
def scroll_errors(self, event): def _cut(self):
self._scroll_errors()
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 _rebuild(self): def cut(self, event):
#global board_name self._cut()
#global Marlin_ver
#global target_env
#board_name, Marlin_ver = get_board_name()
#target_env = get_env(board_name, Marlin_ver)
self.start_thread()
def rebuild(self, event): def _copy(self):
print("event happened")
self._rebuild()
try:
selection = self.get(*self.tag_ranges('sel'))
self.clipboard_clear()
self.clipboard_append(selection)
except TypeError:
pass
def _open_selected_file(self): def copy(self, event):
current_line = self.index('insert') self._copy()
line_start = current_line[ : current_line.find('.')] + '.0'
line_end = current_line[ : current_line.find('.')] + '.200'
self.mark_set("path_start", line_start)
self.mark_set("path_end", line_end)
path = self.get("path_start", "path_end")
from_loc = path.find('from ')
colon_loc = path.find(': ')
if 0 <= from_loc and ((colon_loc == -1) or (from_loc < colon_loc)) :
path = path [ from_loc + 5 : ]
if 0 <= colon_loc:
path = path [ : colon_loc ]
if 0 <= path.find('\\') or 0 <= path.find('/'): # make sure it really contains a path
open_file(path)
def _paste(self):
def _file_save_as(self): self.insert('insert', self.selection_get(selection='CLIPBOARD'))
self.filename = fileDialog.asksaveasfilename(defaultextension = '.txt')
f = open(self.filename, 'w')
f.write(self.get('1.0', 'end'))
f.close()
def _select_all(self):
self.tag_add('sel', '1.0', 'end')
def select_all(self, event):
self.tag_add('sel', '1.0', 'end')
def copy(self, event): def _clear_all(self):
try: #'''erases all text'''
selection = self.get(*self.tag_ranges('sel')) #
self.clipboard_clear() #isok = askokcancel('Clear All', 'Erase all text?', frame=self,
self.clipboard_append(selection) # default='ok')
except TypeError: #if isok:
pass # self.delete('1.0', 'end')
self.delete('1.0', 'end')
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):
self._cut()
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):
self._copy()
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')
self.delete('1.0', 'end')
# end - output_window # end - output_window
def main(): def main():
##########################################################################
# #
# main program #
# #
##########################################################################
########################################################################## global build_type
# # global target_env
# main program # global board_name
# #
##########################################################################
global build_type board_name, Marlin_ver = get_board_name()
global target_env
global board_name
board_name, Marlin_ver = get_board_name() target_env = get_env(board_name, Marlin_ver)
target_env = get_env(board_name, Marlin_ver) # Re-use the VSCode terminal, if possible
if os.environ.get('PLATFORMIO_CALLER', '') == 'vscode':
# Re-use the VSCode terminal, if possible sys_PIO()
if os.environ.get('PLATFORMIO_CALLER', '') == 'vscode': else:
sys_PIO() auto_build = output_window()
else: auto_build.start_thread() # executes the "run_PIO" function
auto_build = output_window()
auto_build.start_thread() # executes the "run_PIO" function
auto_build.root.mainloop()
auto_build.root.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View file

@ -294,12 +294,33 @@ upload_protocol = serial
# #
# BigTree SKR Mini V1.1 / SKR mini E3 / SKR E3 DIP (STM32F103RCT6 ARM Cortex-M3) # BigTree SKR Mini V1.1 / SKR mini E3 / SKR E3 DIP (STM32F103RCT6 ARM Cortex-M3)
# #
# STM32F103RC_bigtree .............. RCT6 with 256K
# STM32F103RC_bigtree_NOUSB ........ RCT6 with 256K (no USB)
# STM32F103RC_bigtree_512K.......... RCT6 with 512K
# STM32F103RC_bigtree_512K_NOUSB ... RCT6 with 512K (no USB)
#
[env:STM32F103RC_bigtree] [env:STM32F103RC_bigtree]
platform = ststm32 platform = ststm32
framework = arduino framework = arduino
board = genericSTM32F103RC board = genericSTM32F103RC
platform_packages = tool-stm32duino platform_packages = tool-stm32duino
extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py
build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py
${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DUSE_USB_COMPOSITE -DHAVE_SW_SERIAL -DSS_TIMER=4 -DSTM32_FLASH_SIZE=256
build_unflags = -std=gnu++11
lib_deps = ${common.lib_deps}
SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip
lib_ignore = Adafruit NeoPixel, SPI
src_filter = ${common.default_src_filter} +<src/HAL/HAL_STM32F1>
monitor_speed = 115200
[env:STM32F103RC_bigtree_NOUSB]
platform = ststm32
framework = arduino
board = genericSTM32F103RC
platform_packages = tool-stm32duino
extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py
build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py
${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DHAVE_SW_SERIAL -DSS_TIMER=4 ${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DHAVE_SW_SERIAL -DSS_TIMER=4
build_unflags = -std=gnu++11 build_unflags = -std=gnu++11
@ -309,14 +330,31 @@ lib_ignore = Adafruit NeoPixel, SPI
src_filter = ${common.default_src_filter} +<src/HAL/HAL_STM32F1> src_filter = ${common.default_src_filter} +<src/HAL/HAL_STM32F1>
monitor_speed = 115200 monitor_speed = 115200
[env:STM32F103RC_bigtree_USB] [env:STM32F103RC_bigtree_512K]
platform = ststm32 platform = ststm32
framework = arduino framework = arduino
board = genericSTM32F103RC board = genericSTM32F103RC
board_upload.maximum_size=524288
platform_packages = tool-stm32duino platform_packages = tool-stm32duino
extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py
build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py
${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DUSE_USB_COMPOSITE -DHAVE_SW_SERIAL -DSS_TIMER=4 ${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DUSE_USB_COMPOSITE -DHAVE_SW_SERIAL -DSS_TIMER=4 -DSTM32_FLASH_SIZE=512
build_unflags = -std=gnu++11
lib_deps = ${common.lib_deps}
SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip
lib_ignore = Adafruit NeoPixel, SPI
src_filter = ${common.default_src_filter} +<src/HAL/HAL_STM32F1>
monitor_speed = 115200
[env:STM32F103RC_bigtree_512K_NOUSB]
platform = ststm32
framework = arduino
board = genericSTM32F103RC
board_upload.maximum_size=524288
platform_packages = tool-stm32duino
extra_scripts = buildroot/share/PlatformIO/scripts/STM32F103RC_SKR_MINI.py
build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py
${common.build_flags} -DDEBUG_LEVEL=0 -std=gnu++14 -DHAVE_SW_SERIAL -DSS_TIMER=4 -DSTM32_FLASH_SIZE=512
build_unflags = -std=gnu++11 build_unflags = -std=gnu++11
lib_deps = ${common.lib_deps} lib_deps = ${common.lib_deps}
SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip SoftwareSerialM=https://github.com/FYSETC/SoftwareSerialM/archive/master.zip