Skip to content

Commit 4337b96

Browse files
Merge branch 'develop' of https://github.com/OpenAstroTech/OpenAstroTracker-Firmware into develop
2 parents 2d60381 + fe5e685 commit 4337b96

21 files changed

+1655
-242
lines changed

Changelog.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
**V1.13.15 - Updates**
2+
- Check `INFO_DISPLAY_TYPE` builds in CI
3+
- Fix `INFO_DISPLAY_TYPE_I2C_SSD1306_128x64` for esp32 builds
4+
5+
**V1.13.14 - Updates**
6+
- Improved Serial command handling (made it less 'blocking'), which should improve general performance
7+
- Guide pulses are ignored when tracking is disabled (for example, when at the limits)
8+
9+
**V1.13.13 - Updates**
10+
- Improved Meade command documentation
11+
- Fixed a bug that was not correctly showing the stepper direction in the :GX# command reply./
12+
13+
**V1.13.12 - Updates**
14+
- Parallelize matrix_build.py for faster CI builds
15+
- Added basic test mode that can be run via terminal connection.
16+
17+
**V1.13.11 - Updates**
18+
- Fixed DEBUG macro usage.
19+
- Clarified some Meade documentation.
20+
21+
**V1.13.10 - Updates**
22+
- Fixed dependency specification for git tags
23+
124
**V1.13.9 - Updates**
225
- Added guide logging support.
326
- Fixed some Meade documentation errors.
@@ -29,7 +52,6 @@ NOTE: Make sure to do a Factory Reset when using this version.
2952
- Lowered ESP32 second core priority
3053
- Added support for informational display
3154
- You must upgrade to OATControl V1.1.2.0 to use with this version (at least if you want to use teh DEC park/unpark feature)
32-
3355
**V1.13.2 - Updates**
3456
- Fix for RA steps being incorrectly set on every boot.
3557

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,14 @@ When using `avr-stub` as a debug interface, it requires 2 things:
5757
Debugging is still a bit flakey, so you may need to try multiple times in order to get a solid debugging session.
5858

5959
More information is available in the [avr-stub documentation](https://github.com/jdolinay/avr_debug/tree/master/doc)
60+
61+
### Meade Command Documentation
62+
The Meade commands page on the Wiki is generated by running:
63+
```shell
64+
python .\scripts\MeadeCommandParser.py
65+
```
66+
from the main directory. The page is generated in the scripts folder and needs to be copy pasted into the Wiki manually. Please add the version manually (for now) by pasting something like this:
67+
```
68+
> This documentation is current as of Firmware **V1.13.9**
69+
{.is-warning}
70+
```

Version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
// Also, numbers are interpreted as simple numbers. _ __ _
44
// So 1.8 is actually 1.08, meaning that 1.12 is a later version than 1.8. \_(..)_/
55

6-
#define VERSION "V1.13.9"
6+
#define VERSION "V1.13.15"

matrix_build.py

Lines changed: 120 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,30 @@
44
import os
55
import shutil
66
import signal
7-
import subprocess
87
import click
8+
import sys
9+
from pathlib import Path
10+
from typing import List
911

1012
import tabulate
1113
from constraint import *
1214

15+
from matrix_build_parallel import Executor, execute, get_available_executor_idx, get_finished_executor_idx, \
16+
cleanup_tempdirs, create_executors, get_source_files_to_link, wait_for_executor_to_finish, copy_caches_to_executors
17+
1318
CONTINUE_ON_ERROR = False
1419

15-
BOARDS = [
20+
MKS_GENL_BOARDS = [
1621
"mksgenlv21",
1722
"mksgenlv2",
1823
"mksgenlv1",
19-
"esp32",
24+
]
25+
AVR_BOARDS = MKS_GENL_BOARDS + [
2026
"ramps",
2127
]
28+
BOARDS = AVR_BOARDS + [
29+
"esp32",
30+
]
2231

2332
STEPPER_TYPES = [
2433
"STEPPER_TYPE_NONE",
@@ -42,6 +51,11 @@
4251
"DISPLAY_TYPE_LCD_JOY_I2C_SSD1306",
4352
]
4453

54+
INFO_DISPLAY_TYPES = [
55+
"INFO_DISPLAY_TYPE_NONE",
56+
"INFO_DISPLAY_TYPE_I2C_SSD1306_128x64",
57+
]
58+
4559
BUILD_FLAGS = {
4660
"CONFIG_VERSION": "1",
4761
"RA_STEPPER_TYPE": [x for x in STEPPER_TYPES if x != "STEPPER_TYPE_NONE"],
@@ -57,6 +71,8 @@
5771
"FOCUS_STEPPER_TYPE": STEPPER_TYPES,
5872
"FOCUS_DRIVER_TYPE": DRIVER_TYPES,
5973
"DISPLAY_TYPE": DISPLAY_TYPES,
74+
"INFO_DISPLAY_TYPE": INFO_DISPLAY_TYPES,
75+
"TEST_VERIFY_MODE": BOOLEAN_VALUES,
6076
"DEBUG_LEVEL": ["DEBUG_NONE", "DEBUG_ANY"],
6177
"RA_MOTOR_CURRENT_RATING": "1",
6278
"RA_OPERATING_CURRENT_SETTING": "1",
@@ -230,6 +246,25 @@ def driver_supports_stepper(d, s):
230246
problem.addConstraint(driver_supports_stepper, ["AZ_DRIVER_TYPE", "AZ_STEPPER_TYPE"])
231247
problem.addConstraint(driver_supports_stepper, ["FOCUS_DRIVER_TYPE", "FOCUS_STEPPER_TYPE"])
232248

249+
# AVR boards can't have both DISPLAY_TYPE and INFO_DISPLAY_TYPE enabled
250+
def avr_display_exclusivity(board, display, info_display):
251+
if board not in AVR_BOARDS:
252+
return True
253+
return (
254+
display == "DISPLAY_TYPE_NONE" or
255+
info_display == "INFO_DISPLAY_TYPE_NONE"
256+
)
257+
problem.addConstraint(avr_display_exclusivity, ["BOARD", "DISPLAY_TYPE", "INFO_DISPLAY_TYPE"])
258+
259+
# MKS GenL boards must not have a focus stepper when info display is enabled
260+
def mksgenl_focus_exclusivity(board, info_display, focus_stepper):
261+
if board not in MKS_GENL_BOARDS:
262+
return True
263+
if info_display != "INFO_DISPLAY_TYPE_NONE":
264+
return focus_stepper == "STEPPER_TYPE_NONE"
265+
return True
266+
problem.addConstraint(mksgenl_focus_exclusivity, ["BOARD", "INFO_DISPLAY_TYPE", "FOCUS_STEPPER_TYPE"])
267+
233268

234269
# Define constraints for excluded tests
235270
def set_test_constraints(problem):
@@ -261,6 +296,14 @@ def set_ci_constraints(problem):
261296
problem.addConstraint(InSetConstraint({"DISPLAY_TYPE_NONE", "DISPLAY_TYPE_LCD_KEYPAD"}), ["DISPLAY_TYPE"])
262297
# problem.addConstraint(InSetConstraint({"DRIVER_TYPE_ULN2003"}), ["ALT_DRIVER_TYPE"])
263298

299+
# Restrict INFO_DISPLAY_TYPE_I2C_SSD1306_128x64 to mksgenlv21 and esp32 only
300+
# (just to reduce compile times)
301+
def info_display_constraint(board, info_display):
302+
if info_display == "INFO_DISPLAY_TYPE_I2C_SSD1306_128x64":
303+
return board in ["mksgenlv21", "esp32"]
304+
return True
305+
problem.addConstraint(info_display_constraint, ["BOARD", "INFO_DISPLAY_TYPE"])
306+
264307

265308
def print_solutions_matrix(solutions, short_strings=False):
266309
def get_value(vb, vk):
@@ -279,43 +322,28 @@ def get_value(vb, vk):
279322
print(tabulate.tabulate(rows, tablefmt="grid", showindex=map(shorten, keys), colalign=("right",)))
280323

281324

282-
def generate_config_file(flag_values):
283-
content = "#pragma once\n\n"
284-
for key, value in flag_values.items():
285-
content += "#define {} {}\n".format(key, value)
286-
287-
with open("Configuration_local_matrix.hpp", 'w') as f:
288-
f.write(content)
289-
print("Generated local config")
290-
print("Path: {}".format(os.path.abspath(f.name)))
291-
print("Content:")
292-
print(content)
293-
294-
295-
def create_run_environment(flag_values):
296-
build_env = dict(os.environ)
297-
build_flags = " ".join(["-D{}={}".format(key, value) for key, value in flag_values.items()])
298-
build_env["PLATFORMIO_BUILD_FLAGS"] = build_flags
299-
return build_env
325+
def print_failed_executor(executor: Executor):
326+
print(f'Error for the following configuration ({executor.proj_dir}):', file=sys.stderr)
327+
print_solutions_matrix([executor.solution])
328+
configuration_path = Path(executor.proj_dir, 'Configuration_local_matrix.hpp')
329+
print(f'{configuration_path}:')
330+
with open(configuration_path, 'r') as fp:
331+
print(fp.read())
332+
out_bytes, err_bytes = executor.proc.communicate()
333+
if out_bytes:
334+
print(out_bytes.decode())
335+
if err_bytes:
336+
print(err_bytes.decode(), file=sys.stderr)
300337

301338

302-
def execute(board, flag_values, use_config_file=True):
303-
if use_config_file:
304-
build_env = dict(os.environ)
305-
build_env["PLATFORMIO_BUILD_FLAGS"] = "-DMATRIX_LOCAL_CONFIG=1"
306-
generate_config_file(flag_values)
307-
else:
308-
build_env = create_run_environment(flag_values)
309-
310-
proc = subprocess.Popen(
311-
"pio run -e {}".format(board),
312-
# stdout=subprocess.PIPE,
313-
# stderr=subprocess.PIPE,
314-
shell=True,
315-
env=build_env,
316-
)
317-
(stdout, stderr) = proc.communicate()
318-
return stdout, stdout, proc.returncode
339+
def run_solution_blocking(executor: Executor, solution: dict) -> int:
340+
executor.solution = copy.deepcopy(solution)
341+
board = solution.pop("BOARD")
342+
executor.proc = execute(executor.proj_dir, board, solution, jobs=os.cpu_count(), out_pipe=False)
343+
executor.proc.wait()
344+
if executor.proc.returncode != 0:
345+
print_failed_executor(executor)
346+
return executor.proc.returncode
319347

320348

321349
class GracefulKiller:
@@ -353,17 +381,60 @@ def solve(board):
353381
solutions = problem.getSolutions()
354382
print_solutions_matrix(solutions, short_strings=False)
355383

356-
print("Testing {} combinations".format(len(solutions)))
357-
358-
for num, solution in enumerate(solutions, start=1):
359-
print("[{}/{}] Building ...".format(num, len(solutions)), flush=True)
360-
print_solutions_matrix([solution])
361-
362-
board = solution.pop("BOARD")
363-
(o, e, c) = execute(board, solution)
364-
if c and not CONTINUE_ON_ERROR:
365-
exit(c)
366-
print(flush=True)
384+
total_solutions = len(solutions)
385+
print(f'Testing {total_solutions} combinations')
386+
387+
nproc = min(os.cpu_count(), len(solutions))
388+
389+
local_paths_to_link = get_source_files_to_link()
390+
executor_list: List[Executor] = create_executors(nproc, local_paths_to_link)
391+
392+
print('First run to fill cache')
393+
solution = solutions.pop()
394+
retcode = run_solution_blocking(executor_list[0], solution)
395+
if retcode != 0 and not CONTINUE_ON_ERROR:
396+
exit(retcode)
397+
398+
copy_caches_to_executors(executor_list[0].proj_dir, executor_list[1:])
399+
400+
solutions_built = 2 # We've already built one solution, and we're 1-indexing
401+
exit_early = False # Exit trigger
402+
while solutions:
403+
# First fill any open execution slots
404+
while get_available_executor_idx(executor_list) is not None:
405+
available_executor_idx = get_available_executor_idx(executor_list)
406+
executor = executor_list[available_executor_idx]
407+
try:
408+
solution = solutions.pop()
409+
except IndexError:
410+
# No more solutions to try!
411+
break
412+
print(f'[{solutions_built}/{total_solutions}] Building ...')
413+
executor.solution = copy.deepcopy(solution)
414+
board = solution.pop("BOARD")
415+
executor.proc = execute(executor.proj_dir, board, solution)
416+
solutions_built += 1
417+
418+
# Next wait for any processes to finish
419+
wait_for_executor_to_finish(executor_list)
420+
421+
# Go through all the finished processes and check their status
422+
while get_finished_executor_idx(executor_list) is not None:
423+
finished_executor_idx = get_finished_executor_idx(executor_list)
424+
executor = executor_list[finished_executor_idx]
425+
if executor.proc.returncode != 0:
426+
print_failed_executor(executor)
427+
if not CONTINUE_ON_ERROR:
428+
exit_early = True
429+
del executor.proc
430+
executor.proc = None
431+
432+
if exit_early:
433+
break
434+
if exit_early:
435+
exit(1)
436+
print('Done!')
437+
cleanup_tempdirs(executor_list)
367438

368439

369440
if __name__ == '__main__':

0 commit comments

Comments
 (0)