From 171942349fc73edd835a555520503ba29f76835b Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 26 Feb 2025 13:23:37 +1000 Subject: [PATCH 01/46] Testing ki-ntree fix --- .scripts/ki-ntree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scripts/ki-ntree b/.scripts/ki-ntree index c66d40d..f1e2306 160000 --- a/.scripts/ki-ntree +++ b/.scripts/ki-ntree @@ -1 +1 @@ -Subproject commit c66d40daf798f7d876e2213f15f004e8f253672b +Subproject commit f1e2306633a3c4a0a7e60f8c08ed9bcca06d7e16 From f0d9ad3fd6d0d7523d63edb118cfb90c3ce72828 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 18 Mar 2025 18:20:00 +1000 Subject: [PATCH 02/46] Fixed up foot gen script --- .scripts/foot_gen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index 0eed083..4aaf4e8 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -95,7 +95,7 @@ for d in brd_drawings: # Keep only required foots saved = [] -while len(pcb.Footprints()) > 1: +while len(pcb.Footprints()) > 0: foot = pcb.Footprints().pop() if foot.GetReference() in new_foots.keys(): saved.append(foot) @@ -323,7 +323,7 @@ for [foot, pad_map] in sorted_foots: elif shape_type == pcbnew.PAD_SHAPE_CUSTOM: pad_shape = Pad.SHAPE_CUSTOM for d in foot.GraphicalItems(): - if type(d) is pcbnew.FP_TEXT and "User.Drawings" in d.GetLayerName(): + if type(d) is pcbnew.PCB_TEXT and "User.Drawings" in d.GetLayerName(): txt_sp = d.GetText().split(':',1) if pad_number != txt_sp[0]: continue From cf480237f5fe510105f7f16aea98150a927b407a Mon Sep 17 00:00:00 2001 From: ac Date: Fri, 28 Mar 2025 09:05:14 +1000 Subject: [PATCH 03/46] Added step file creation to panel job --- default.kibot.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/default.kibot.yaml b/default.kibot.yaml index 74623da..b71eb39 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -260,6 +260,7 @@ groups: - JLCPCB_compress - neo_position - print_pcb + - step - interactive_bom - name: sch From ebee7ef48e8f07a5a98ae5ccfd1acbed6c3ca0e6 Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 29 Apr 2025 21:29:05 +1000 Subject: [PATCH 04/46] Neo: fixed up script to point to the 'Fabrication' folder properly Variants: able to use kibot variants, separate variants for: mech, sch, and pcb outputs. This because a BOM variant does not affect the PCB, but it might affect the step file. --- .scripts/neo.py | 4 +- blank.kibot.yaml | 2 + default.kibot.yaml | 80 ++++++++++++++-------------- kibot-ci.yml | 125 +++++++++++++++++++++++--------------------- mech.kibot.yaml | 13 +++++ panel.kibot.yaml | 17 ++++++ pcb_dev.kibot.yaml | 13 +++++ pcb_main.kibot.yaml | 18 +++++++ pos.kibot.yaml | 13 +++++ sch.kibot.yaml | 15 ++++++ 10 files changed, 201 insertions(+), 99 deletions(-) create mode 100644 blank.kibot.yaml create mode 100644 mech.kibot.yaml create mode 100644 panel.kibot.yaml create mode 100644 pcb_dev.kibot.yaml create mode 100644 pcb_main.kibot.yaml create mode 100644 pos.kibot.yaml create mode 100644 sch.kibot.yaml diff --git a/.scripts/neo.py b/.scripts/neo.py index 6084630..b9f8fd6 100644 --- a/.scripts/neo.py +++ b/.scripts/neo.py @@ -1,4 +1,5 @@ import csv +import os import sys from copy import deepcopy from glob import glob @@ -31,8 +32,9 @@ print("bottom Orig: ", bottomOrig) output_dir = deepcopy(pcb_dir) csv_files = glob(output_dir + "/*.csv") +print("CSV Files: ", csv_files) if len(csv_files) < 1: - output_dir = "Fabrication/" + output_dir + output_dir = os.path.join(os.environ.get('CI_PROJECT_DIR', ''), '') + "Fabrication/" + output_dir csv_files = glob(output_dir + "/*.csv") input = next(filter(lambda f: KI_POS_SUFFIX in f, csv_files)) diff --git a/blank.kibot.yaml b/blank.kibot.yaml new file mode 100644 index 0000000..352c8c8 --- /dev/null +++ b/blank.kibot.yaml @@ -0,0 +1,2 @@ +kibot: + version: 1 diff --git a/default.kibot.yaml b/default.kibot.yaml index b71eb39..55b21b3 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -2,10 +2,13 @@ kibot: version: 1 +import: + - file: '../kibot.yaml' + preflight: - erc: true - update_xml: true - drc: true + # erc: true + # update_xml: true + # drc: true set_text_variables: - name: 'rev' command: 'if [ $(git describe --tags | wc -w) -gt 0 ]; then git describe --tags | sed -e "s/\([r,R][0-9]\+\)*$//g"; else echo $CI_COMMIT_SHORT_SHA; fi' @@ -31,14 +34,14 @@ outputs: type: pdf_sch_print dir: . options: - output: "%f_%r_%i.%x" + output: "%f%v_%r_%i.%x" - name: 'print_pcb' comment: "Print Top and Bottom Copper+Silk" type: pcb_print dir: . options: - output: "%f_%r_PCB.%x" + output: "%f%v_%r_PCB.%x" pages: - layers: - layer: F.Cu @@ -51,7 +54,7 @@ outputs: - name: '_bom' type: bom - dir: . + dir: /tmp options: columns: - field: Value @@ -70,14 +73,14 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f_%r_%i.%x" + output: "%f%v_%r_%i.%x" expand_text_vars: true - disable_run_by_default: true - name: 'bom_csv' type: bom dir: . extends: "_bom" + disable_run_by_default: _bom options: csv: separator: ';' @@ -89,6 +92,7 @@ outputs: type: bom dir: . extends: '_bom' + disable_run_by_default: _bom options: xlsx: # this is a relative path unfortunately @@ -108,7 +112,7 @@ outputs: type: step dir: . options: - output: '%f_%r.%x' + output: '%f%v_%r.%x' download: false subst_models: true @@ -124,7 +128,7 @@ outputs: download: false download_lcsc: false orthographic: true - output: 'PCB_%f_%r.%x' + output: 'PCB_%f%v_%r.%x' show_components: 'none' - name: 'pcba_render' @@ -139,14 +143,14 @@ outputs: zoom: -1 download_lcsc: false orthographic: true - output: 'PCBA_%f_%r.%x' + output: 'PCBA_%f%v_%r.%x' show_components: 'all' - name: 'neo_position' comment: "Pick and place" type: position options: - output: '%f_%r_cpl.%x' + output: '%f%v_%r_cpl.%x' format: CSV units: millimeters separate_files_for_front_and_back: false @@ -157,7 +161,7 @@ outputs: type: stencil_3d dir: '3D_Stencil' options: - output: '%f_%r_%i.%x' + output: '%f%v_%r_%i.%x' - name: 'diff_pcb' comment: "Diff for visual comparison" @@ -181,7 +185,7 @@ outputs: type: ibom dir: . options: - output: '%f_%r_%i.%x' + output: '%f%v_%r_%i.%x' dark_mode: true - name: JLCPCB_gerbers @@ -234,7 +238,7 @@ outputs: metric_units: true map: gerber route_mode_for_oval_holes: false - output: "%f%i.%x" + output: "%f%v%i.%x" - name: 'JLCPCB_compress' comment: ZIP file for JLCPCB @@ -245,29 +249,29 @@ outputs: dest: / - from_output: JLCPCB_drill dest: / - output: '%f_%r_JLC.%x' -groups: - - name: pcb - outputs: - - JLCPCB_compress - - neo_position - - print_pcb - - stencil - - interactive_bom - - - name: pcb_panel - outputs: - - JLCPCB_compress - - neo_position - - print_pcb - - step - - interactive_bom - - - name: sch - outputs: - - bom_csv - - bom_xlsx - - print_sch + output: '%f%v_%r_JLC.%x' +# groups: +# - name: pcb +# outputs: +# - JLCPCB_compress +# - neo_position +# - print_pcb +# - stencil +# - interactive_bom +# +# - name: pcb_panel +# outputs: +# - JLCPCB_compress +# - neo_position +# - print_pcb +# - step +# - interactive_bom +# +# - name: sch +# outputs: +# - bom_csv +# - bom_xlsx +# - print_sch ... definitions: _KIBOT_POS_ENABLED: false diff --git a/kibot-ci.yml b/kibot-ci.yml index 30b3155..5f41f43 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -20,7 +20,7 @@ stages: - release image: - name: ghcr.io/inti-cmnb/kicad8_auto:1.8.2 + name: ghcr.io/inti-cmnb/kicad8_auto:1.8.4 .main_rules: rules: @@ -82,27 +82,33 @@ image: fi echo ${dir_arr[i-1]} echo ${sch_arr[i-1]} + USER_FILE="$CI_PROJECT_DIR/.gitlab/blank.kibot.yaml" + if [ -f "${dir_arr[i-1]}/kibot.yaml" ]; then + USER_FILE="${dir_arr[i-1]}/kibot.yaml" + fi + cp $USER_FILE $CI_PROJECT_DIR/kibot.yaml python3 $CI_PROJECT_DIR/.gitlab/.scripts/orig.py ${dir_arr[i-1]} - kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/default.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} -s $SUFFIX + for CONF in $KIBOT_CONF + do + kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS + done mv $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]}/*.zip Fabrication/ 2> /dev/null || true done - cd $CI_PROJECT_DIR - panel: + pre_panel: + - cd $CI_PROJECT_DIR + - mkdir panels - 'SEARCH="_panel.json"' - !reference [.commands, get_dirs] - | - mkdir panels - cd $CI_PROJECT_DIR for d in $DIRS do - echo "found panel" - echo $d + echo "found panel: $d" JSON=$(find $d/*_panel.json) FILE=$(basename "${JSON}") NAME=$(echo "${FILE%.json}") PCB=$(find $d/*.kicad_pcb) - echo "mkdring" mkdir -p panels/$NAME echo "panelising" kikit panelize -p $JSON $PCB panels/$NAME/$NAME.kicad_pcb @@ -110,10 +116,10 @@ image: cp $d/fp-lib-table panels/$NAME/ python3 .gitlab/.scripts/post_panel.py panels/$NAME/$NAME.kicad_pro $PCB done - - cd panels || true - - !reference [.commands, kibot] + - cd panels + + post_panel: - mv panels/* . || true - - rm -rf panels/ || true neo: - 'SEARCH=".kicad_pro"' @@ -231,87 +237,86 @@ image: strip_tag: - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) -output_mech: +outputs_mech: stage: gen_mech + when: always artifacts: when: always paths: - Fabrication/**/* - variables: - SUFF_MECH: erc,drc step pcb_render pcba_render - script: - - !reference [.commands, git_tag] - - SUFFIX=$SUFF_MECH - - !reference [.commands, kibot] - -outputs_dev: - rules: - - !reference [.dev_rules, rules] - stage: gen_fab - artifacts: - when: always - name: "$CI_PROJECT_TITLE-$CI_COMMIT_SHORT_SHA" - paths: - - Fabrication/**/* expire_in: 1 week - variables: - SUFF_SCH: drc sch - SUFF_PCB: erc,update_xml,set_text_variables print_pcb - script: + before_script: - !reference [.commands, git_tag] - - SUFFIX=$SUFF_SCH - - !reference [.commands, kibot] - - SUFFIX=$SUFF_PCB + script: + - VARIANTS="$VARIANTS_MECH" + - KIBOT_CONF="mech" - !reference [.commands, kibot] -outputs_all: - extends: outputs_dev - rules: - - !reference [.main_rules, rules] - variables: - SUFF_SCH: drc sch - SUFF_PCB: erc,update_xml,set_text_variables pcb - SUFF_PANEL: erc,update_xml,set_text_variables pcb_panel + +outputs_dev: + extends: outputs_mech + stage: gen_fab script: - - !reference [.commands, git_tag] - - SUFFIX=$SUFF_SCH + # SCH + - VARIANTS="$VARIANTS_SCH" + - KIBOT_CONF="sch" - !reference [.commands, kibot] - - SUFFIX=$SUFF_PCB + # PCB + - VARIANTS="$VARIANTS_PCB" + - KIBOT_CONF="pcb_dev" + - !reference [.commands, kibot] + +outputs_main: + extends: outputs_dev + script: + # SCH + - VARIANTS="$VARIANTS_SCH" + - KIBOT_CONF="sch" + - !reference [.commands, kibot] + # PCB + - VARIANTS="$VARIANTS_PCB" + - KIBOT_CONF="pcb_main" + - !reference [.commands, kibot] + # Panels + - !reference [.commands, pre_panel] + - KIBOT_CONF="panel" + - !reference [.commands, kibot] + - !reference [.commands, post_panel] + # Pos + - VARIANTS="$VARIANTS_SCH" + - KIBOT_CONF="pos" - !reference [.commands, kibot] - - SUFFIX=$SUFF_PANEL - - !reference [.commands, panel] - !reference [.commands, neo] - - ls Fabrication/ inventree_job_dev: stage: inventree + rules: + - !reference [.dev_rules, rules] needs: - - job: output_mech + - job: outputs_mech artifacts: true - job: outputs_dev artifacts: true - rules: - - !reference [.dev_rules, rules] script: - !reference [.commands, boms] -inventree_job: +inventree_job_main: stage: inventree - needs: - - job: output_mech - artifacts: true - - job: outputs_all - artifacts: true rules: - !reference [.main_rules, rules] + needs: + - job: outputs_mech + artifacts: true + - job: outputs_main + artifacts: true script: - !reference [.commands, boms] upload_job: stage: upload needs: - - job: inventree_job - - job: outputs_all + - job: inventree_job_main + - job: outputs_main artifacts: true rules: - if: $CI_COMMIT_TAG diff --git a/mech.kibot.yaml b/mech.kibot.yaml new file mode 100644 index 0000000..d700e8a --- /dev/null +++ b/mech.kibot.yaml @@ -0,0 +1,13 @@ +# Example KiPlot config file +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - step + +preflight: + erc: false + update_xml: false + drc: false diff --git a/panel.kibot.yaml b/panel.kibot.yaml new file mode 100644 index 0000000..6a0c242 --- /dev/null +++ b/panel.kibot.yaml @@ -0,0 +1,17 @@ +# Example KiPlot config file +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - JLCPCB_compress + - neo_position + - print_pcb + - step + - interactive_bom + +preflight: + erc: false + update_xml: false + drc: true diff --git a/pcb_dev.kibot.yaml b/pcb_dev.kibot.yaml new file mode 100644 index 0000000..23ef335 --- /dev/null +++ b/pcb_dev.kibot.yaml @@ -0,0 +1,13 @@ +# Example KiPlot config file +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - print_pcb + +preflight: + erc: false + update_xml: false + drc: true diff --git a/pcb_main.kibot.yaml b/pcb_main.kibot.yaml new file mode 100644 index 0000000..36bf3f4 --- /dev/null +++ b/pcb_main.kibot.yaml @@ -0,0 +1,18 @@ +# Example KiPlot config file +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - JLCPCB_gerbers + - JLCPCB_drill + - JLCPCB_compress + - print_pcb + - stencil + - interactive_bom + +preflight: + erc: false + update_xml: false + drc: true diff --git a/pos.kibot.yaml b/pos.kibot.yaml new file mode 100644 index 0000000..bd2829c --- /dev/null +++ b/pos.kibot.yaml @@ -0,0 +1,13 @@ +# Example KiPlot config file +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - neo_position + +preflight: + erc: false + update_xml: false + drc: true diff --git a/sch.kibot.yaml b/sch.kibot.yaml new file mode 100644 index 0000000..6f754a5 --- /dev/null +++ b/sch.kibot.yaml @@ -0,0 +1,15 @@ +kibot: + version: 1 + +import: + - file: default.kibot.yaml + outputs: + - print_sch + - _bom + - bom_csv + - bom_xlsx + +preflight: + erc: true + update_xml: true + drc: false From 7a2452cc8e0264d6ac8f582aeec5ed27cacab4c9 Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 13 May 2025 16:13:35 +1000 Subject: [PATCH 05/46] Changed footprint script to export vrml instead of step --- .scripts/foot_gen.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index 4aaf4e8..179bfdb 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -153,6 +153,7 @@ for foot in saved: pad_map[pad.GetNumber()] = match_num sorted_foots.append([load_foot, pad_map]) + print("Added: ", load_foot) pcb.Add(load_foot) @@ -160,13 +161,13 @@ for foot in saved: # sorted_foots.sort(key=lambda foot: foot[0].GetY()) # Export the step file -os.system("kicad-cli pcb export step -f --no-dnp --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.step " + sys.argv[1]) +os.system("kicad-cli pcb export vrml --units 'tenths' -f --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.wrl " + sys.argv[1]) # Import the 3d model of the actual PCB dummy = FOOTPRINT(pcb) dummy.SetPosition(brd_cent) dummy_model = FP_3DMODEL() -dummy_model.m_Filename = "/tmp/dummy.step" +dummy_model.m_Filename = "/tmp/dummy.wrl" dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset) dummy.Add3DModel(dummy_model) pcb.Add(dummy) @@ -177,8 +178,8 @@ pcb.Add(dummy) # Save and export step of board + mating connectors SaveBoard("test/test.kicad_pcb", pcb) -final_model_path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".step" -os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + final_model_path + " test/test.kicad_pcb") +final_model_path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" +os.system("kicad-cli pcb export vrml -f --units 'mm' --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + final_model_path + " test/test.kicad_pcb") # Generate footprint @@ -249,6 +250,7 @@ for [foot, pad_map] in sorted_foots: # start = [cent_mm[0] - size_mm[0], cent_mm[1] - size_mm[1]] # end = [cent_mm[0] + size_mm[0], cent_mm[1] + size_mm[1]] # kicad_mod.append(RectLine(start=start, end=end, layer='F.Silkscreen', width=0.05, offset=0.2)) + # elif shape_type == pcbnew.SHAPE_T_CIRCLE: # start = [cent_mm[0], cent_mm[1] + size_mm[1]/2] # end = [start[0], start[1]] @@ -410,7 +412,7 @@ for i in range(len(corners)): # kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.SilkS', width=0.15)) -final_model_path = "${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".step" +final_model_path = "${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" kicad_mod.append(Model(filename=final_model_path ,at=[0,0,-1.6] ,scale=[1,1,1] From 51f029af3aae6d538df7ae64c1f91498d622714d Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 13 May 2025 19:22:59 +1000 Subject: [PATCH 06/46] Added support for generating a second 'base' footprint --- .scripts/foot_gen.py | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index 179bfdb..282f9f2 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -42,7 +42,11 @@ for item in pcb.GetDrawings(): foot_path = lines[2].split(":")[-1].strip() if not lines[3].startswith("Z:"): continue - z_offset = float(lines[3].split(":")[-1].strip()) + z_str = lines[3].split(":")[-1].strip() + z_offset = eval(z_str) + if type(z_offset) is not tuple: + z_offset = (z_offset) + for line in lines[4:]: sp = line.split(':', 1) if len(sp) != 2: @@ -163,12 +167,17 @@ for foot in saved: # Export the step file os.system("kicad-cli pcb export vrml --units 'tenths' -f --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.wrl " + sys.argv[1]) +# Export step file of board with no additional components +if len(z_offset) > 1: + path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + "_base" + ".wrl" + os.system("kicad-cli pcb export vrml --units 'tenths' -f --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + path + " " + sys.argv[1]) + # Import the 3d model of the actual PCB dummy = FOOTPRINT(pcb) dummy.SetPosition(brd_cent) dummy_model = FP_3DMODEL() dummy_model.m_Filename = "/tmp/dummy.wrl" -dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset) +dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset[0]) dummy.Add3DModel(dummy_model) pcb.Add(dummy) @@ -178,8 +187,8 @@ pcb.Add(dummy) # Save and export step of board + mating connectors SaveBoard("test/test.kicad_pcb", pcb) -final_model_path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" -os.system("kicad-cli pcb export vrml -f --units 'mm' --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + final_model_path + " test/test.kicad_pcb") +path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" +os.system("kicad-cli pcb export vrml -f --units 'mm' --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + path + " test/test.kicad_pcb") # Generate footprint @@ -412,17 +421,21 @@ for i in range(len(corners)): # kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.SilkS', width=0.15)) -final_model_path = "${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" -kicad_mod.append(Model(filename=final_model_path - ,at=[0,0,-1.6] - ,scale=[1,1,1] - ,rotate=[0,0,0])) +output_list = [(foot_name, -1.6)] +# Output another footprint if a second offset is specified +if len(z_offset) > 1: + output_list.append((foot_name+"_base", z_offset[1])) -# write file -file_handler = KicadFileHandler(kicad_mod) -final_foot_path = sys.path[0] + "/../../libs/melonlib/" + foot_path + ".pretty/" + foot_name + ".kicad_mod" -file_handler.writeFile(final_foot_path) +for [local_name, z] in output_list: + local_mod = deepcopy(kicad_mod) + local_mod.append(Model(filename="${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + local_name + ".wrl" + ,at=[0,0,z] + ,scale=[1,1,1] + ,rotate=[0,0,0])) + + # write file + file_handler = KicadFileHandler(local_mod) + file_handler.writeFile(sys.path[0] + "/../../libs/melonlib/" + foot_path + ".pretty/" + local_name + ".kicad_mod" ) import shutil - shutil.rmtree("test") From 8b4ef0e0c4463afd622d47127e3ed5515f21c87f Mon Sep 17 00:00:00 2001 From: andrewc Date: Fri, 16 May 2025 16:33:31 +1000 Subject: [PATCH 07/46] Added Dockerfile so ki-ntree does not need to be installed every run --- .gitlab-ci.yml | 36 ++++++++++++++++++++++++++++++++++++ Dockerfile-poetry | 3 +++ 2 files changed, 39 insertions(+) create mode 100644 .gitlab-ci.yml create mode 100644 Dockerfile-poetry diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..e6146d7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,36 @@ +workflow: + rules: + - if: $CI_COMMIT_TAG + when: never + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS + when: never + # - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch +default: + image: docker:28.0.4 + services: + - docker:28.0.4-dind + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY +variables: + # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + CONTAINER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_BRANCH + CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest + IMAGES: ('poetry') +stages: + - build +.commands: + strip_tag: + - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) +build: + stage: build + script: + - docker context create my-builder + - docker buildx create my-builder --driver docker-container --use + - | + for image in $IMAGES + do + CONTAINER_IMAGE="$CI_REGISTRY_IMAGE/$image" + docker buildx build --push -t $CONTAINER_IMAGE --cache-to type=registry,ref=$CONTAINER_IMAGE,mode=max --cache-from type=registry,ref=$CONTAINER_IMAGE -f Dockerfile-$image . + done diff --git a/Dockerfile-poetry b/Dockerfile-poetry new file mode 100644 index 0000000..6f555d3 --- /dev/null +++ b/Dockerfile-poetry @@ -0,0 +1,3 @@ +FROM thehale/python-poetry:2.1.3-py3.12-slim + +RUN apt update && apt install -y curl wget From 0f9ab507dd3e7f6eac15d5bff9ff0228c9383d5a Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 20 May 2025 13:13:36 +1000 Subject: [PATCH 08/46] Fixed up a few kibot options --- default.kibot.yaml | 4 ++-- kibot-ci.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 55b21b3..7ebbd24 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -21,12 +21,12 @@ preflight: - name: 'title' expand_kibot_patterns: true command: 'echo $KIBOT_PCB_NAME | rev | cut -d"/" -f1 | rev | cut -d"." -f1 ' - fill_zones: true + check_zone_fills: true global: environment: user_templates: "${CI_PROJECT_DIR}/.gitlab" - + restore_project: true outputs: - name: 'print_sch' diff --git a/kibot-ci.yml b/kibot-ci.yml index 5f41f43..d98dee9 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -139,9 +139,6 @@ image: - proj=$(echo $CI_PROJECT_NAME | tr -d '0123456789' | tr '-' ' ' | sed -r 's/\<./\U&/g') - desc_suffix=$(echo $client $proj) - cd $CI_PROJECT_DIR/.gitlab/.scripts/ki-ntree/ - - apt remove libcurl4 -y - - apt update && apt install curl pip -y && pip install --break-system-packages poetry - - poetry install - url="https://gitlab.com/api/v4/projects/${DIGI_API_PRJ_ID}/packages/generic/digikey_api/0/token_storage.json" - | if [[ -z "$KINTREE_DIGI_TOKEN" ]]; then @@ -172,7 +169,7 @@ image: if [[ $CI_COMMIT_BRANCH == "main" ]]; then DRY="" fi - poetry run python -m kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '$TAG', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 + python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '$TAG', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 done # - cp token_storage.json /tmp - | @@ -289,6 +286,9 @@ outputs_main: - !reference [.commands, neo] inventree_job_dev: + image: + name: ghcr.io/andrew-collins/ki-ntree:cli + entrypoint: [""] stage: inventree rules: - !reference [.dev_rules, rules] From 2663e63353d3968fe7606ad849aab307a3a763a0 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 20 May 2025 14:48:10 +1000 Subject: [PATCH 09/46] Fixed up where variant sits in output names, testing CI --- default.kibot.yaml | 22 +++++++++++----------- kibot-ci.yml | 3 +++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 7ebbd24..845f0ad 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -34,14 +34,14 @@ outputs: type: pdf_sch_print dir: . options: - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" - name: 'print_pcb' comment: "Print Top and Bottom Copper+Silk" type: pcb_print dir: . options: - output: "%f%v_%r_PCB.%x" + output: "%f_%r%v_PCB.%x" pages: - layers: - layer: F.Cu @@ -73,7 +73,7 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" expand_text_vars: true - name: 'bom_csv' @@ -112,7 +112,7 @@ outputs: type: step dir: . options: - output: '%f%v_%r.%x' + output: '%f_%r%v.%x' download: false subst_models: true @@ -128,7 +128,7 @@ outputs: download: false download_lcsc: false orthographic: true - output: 'PCB_%f%v_%r.%x' + output: 'PCB_%f_%r%v.%x' show_components: 'none' - name: 'pcba_render' @@ -143,14 +143,14 @@ outputs: zoom: -1 download_lcsc: false orthographic: true - output: 'PCBA_%f%v_%r.%x' + output: 'PCBA_%f_%r%v.%x' show_components: 'all' - name: 'neo_position' comment: "Pick and place" type: position options: - output: '%f%v_%r_cpl.%x' + output: '%f_%r%v_cpl.%x' format: CSV units: millimeters separate_files_for_front_and_back: false @@ -161,7 +161,7 @@ outputs: type: stencil_3d dir: '3D_Stencil' options: - output: '%f%v_%r_%i.%x' + output: '%f_%r%v_%i.%x' - name: 'diff_pcb' comment: "Diff for visual comparison" @@ -185,7 +185,7 @@ outputs: type: ibom dir: . options: - output: '%f%v_%r_%i.%x' + output: '%f_%r%v_%i.%x' dark_mode: true - name: JLCPCB_gerbers @@ -238,7 +238,7 @@ outputs: metric_units: true map: gerber route_mode_for_oval_holes: false - output: "%f%v%i.%x" + output: "%f_%r%v_%i.%x" - name: 'JLCPCB_compress' comment: ZIP file for JLCPCB @@ -249,7 +249,7 @@ outputs: dest: / - from_output: JLCPCB_drill dest: / - output: '%f%v_%r_JLC.%x' + output: '%f_%r%v_JLC.%x' # groups: # - name: pcb # outputs: diff --git a/kibot-ci.yml b/kibot-ci.yml index d98dee9..60fd565 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -160,6 +160,7 @@ image: name=$(echo $f | cut -c3- | cut -d'-' -f1)A fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-) name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) + echo "name: $name_n_rev" pcb_im=$fab_path/PCB_$name_n_rev.png pcba_im=$fab_path/PCBA_$name_n_rev.png pcb_attach=$(echo "['$fab_path/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']") @@ -265,6 +266,8 @@ outputs_dev: outputs_main: extends: outputs_dev + rules: + - !reference [.main_rules, rules] script: # SCH - VARIANTS="$VARIANTS_SCH" From e1c997756c7d5548c66c2a177693d941224528eb Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 20 May 2025 16:18:41 +1000 Subject: [PATCH 10/46] Fix up paths during `boms` --- kibot-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 60fd565..50ab55f 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -138,7 +138,6 @@ image: - client=$(echo $CI_PROJECT_PATH | cut -d'/' -f3 | sed -r 's/\<./\U&/g') - proj=$(echo $CI_PROJECT_NAME | tr -d '0123456789' | tr '-' ' ' | sed -r 's/\<./\U&/g') - desc_suffix=$(echo $client $proj) - - cd $CI_PROJECT_DIR/.gitlab/.scripts/ki-ntree/ - url="https://gitlab.com/api/v4/projects/${DIGI_API_PRJ_ID}/packages/generic/digikey_api/0/token_storage.json" - | if [[ -z "$KINTREE_DIGI_TOKEN" ]]; then @@ -151,7 +150,7 @@ image: - 'SEARCH="bom.csv"' - !reference [.commands, strip_tag] - !reference [.commands, get_files] - - cd $CI_PROJECT_DIR/.gitlab/.scripts/ki-ntree/ + - cd $CI_PROJECT_DIR - FAIL=0 - | for f in $FILES From 5a909ac0f0265b2ad0a29b2d46f71cb45be72c8e Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 20 May 2025 17:02:42 +1000 Subject: [PATCH 11/46] Allow `inventree_job_dev` to create BOM parts, but not the assembly --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 50ab55f..2ada0ae 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -165,7 +165,7 @@ image: pcb_attach=$(echo "['$fab_path/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']") pcba_attach=$(echo "['$fab_path/${name_n_rev}_schematic.pdf', '$fab_path/${name_n_rev}_bom.csv', '$fab_path/${name_n_rev}-neo-pos_top.csv', '$fab_path/${name_n_rev}-neo-pos_bot.csv', '$fab_path/${name_n_rev}_ibom.html']") - DRY="--dry" + DRY="--dry assemblies" if [[ $CI_COMMIT_BRANCH == "main" ]]; then DRY="" fi From 387a8d9b68debd0875c1f70382f3f34acd4d868d Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 21 May 2025 11:45:33 +1000 Subject: [PATCH 12/46] Testing having a truncated (major.minor only) revision for the PCB --- default.kibot.yaml | 2 ++ kibot-ci.yml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 845f0ad..5d81110 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -12,6 +12,8 @@ preflight: set_text_variables: - name: 'rev' command: 'if [ $(git describe --tags | wc -w) -gt 0 ]; then git describe --tags | sed -e "s/\([r,R][0-9]\+\)*$//g"; else echo $CI_COMMIT_SHORT_SHA; fi' + - name: 'rev_pcb' + command: if [ $(git describe --tags | wc -w) -gt 0 ]; then git describe --tags | awk -F- 'BEGIN {ORS=""} {split($1,a,"."); print a[1]"."a[2]; if ($2) print "-"$2}' ; else echo $CI_COMMIT_SHORT_SHA; fi - name: 'date' expand_kibot_patterns: true text: '%D' diff --git a/kibot-ci.yml b/kibot-ci.yml index 2ada0ae..55e4019 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -160,6 +160,8 @@ image: fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-) name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) echo "name: $name_n_rev" + assembly_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) + pcb_rev=$(echo $assembly_rev | cut -d'_' -f1,2 | cut -d'.' -f1,2) pcb_im=$fab_path/PCB_$name_n_rev.png pcba_im=$fab_path/PCBA_$name_n_rev.png pcb_attach=$(echo "['$fab_path/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']") @@ -169,7 +171,7 @@ image: if [[ $CI_COMMIT_BRANCH == "main" ]]; then DRY="" fi - python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '$TAG', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 + python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '($pcb_rev, $assembly_rev)', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 done # - cp token_storage.json /tmp - | From 57ef513fe5380efe6125d50550dbb9417cb3d3a4 Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 21 May 2025 13:01:42 +1000 Subject: [PATCH 13/46] Checking the rev parsing --- kibot-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 55e4019..382c9d3 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -171,12 +171,14 @@ image: if [[ $CI_COMMIT_BRANCH == "main" ]]; then DRY="" fi + echo "Revs: $pcb_rev, $assembly_rev" python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '($pcb_rev, $assembly_rev)', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 done # - cp token_storage.json /tmp - | - cat /tmp/token_storage.json - curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file /tmp/token_storage.json $url + cd $CI_PROJECT_DIR + cat token_storage.json + curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file token_storage.json $url - exit $FAIL # USE PRIVATE-TOKEN to upload from gitlab-ci From 1828df591fcb8f9852d603b19c516e7ab9f7a026 Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 21 May 2025 15:24:28 +1000 Subject: [PATCH 14/46] Added `pcb_rev` variable to kicad templates --- micromelon_default/micromelon_default.kicad_pro | 1 + tcs_default/tcs_default.kicad_pro | 1 + 2 files changed, 2 insertions(+) diff --git a/micromelon_default/micromelon_default.kicad_pro b/micromelon_default/micromelon_default.kicad_pro index fd03554..fa5adcf 100644 --- a/micromelon_default/micromelon_default.kicad_pro +++ b/micromelon_default/micromelon_default.kicad_pro @@ -476,6 +476,7 @@ "text_variables": { "date": "", "rev": "", + "pcb_rev": "", "title": "", "client": "", "partner": "", diff --git a/tcs_default/tcs_default.kicad_pro b/tcs_default/tcs_default.kicad_pro index 91f31ac..eb81261 100644 --- a/tcs_default/tcs_default.kicad_pro +++ b/tcs_default/tcs_default.kicad_pro @@ -476,6 +476,7 @@ "text_variables": { "date": "", "rev": "", + "pcb_rev": "", "title": "", "client": "TCS JOHN HUXLEY", "name": "" From a1564dece5408505a2f3605910d4a6e7c53972c7 Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 27 May 2025 17:04:02 +1000 Subject: [PATCH 15/46] Added 3rd field for footprint gen, allowing you to disable the 3d model of the added footprint --- .scripts/foot_gen.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index 4aaf4e8..8fc2992 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -53,14 +53,17 @@ for item in pcb.GetDrawings(): foot = foot_sp[0].strip() offset = (0,0) # Optional offset tuple - if len(foot_sp) == 2: + if len(foot_sp) > 1: print("Foot sp: ", foot_sp) offset = foot_sp[1].strip(" ()").split(',') print("Offset: ", offset) offset[0] = FromMM(float(offset[0])) offset[1] = FromMM(float(offset[1])) + disable_model = False + if len(foot_sp) > 2: + disable_model = eval(foot_sp[2]) - new_foots[ref] = [foot, offset] + new_foots[ref] = [foot, offset, disable_model] # pins = sp[1] # pin_refs = [] # for pin in pins.split(','): @@ -126,6 +129,9 @@ for foot in saved: cent_diff = orig_cent - new_cent load_foot.SetX(load_foot.GetX() + cent_diff.x + vals[1][0]) load_foot.SetY(load_foot.GetY() + cent_diff.y + vals[1][1]) + # Disable model if applicable + if vals[2]: + load_foot.Models().clear() # Flip the net assignments of the pads pad_map = {} for pad in load_foot.Pads(): From a05af9436aff0f43fbeed56b671fd682be89d941 Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 2 Jun 2025 12:18:59 +1000 Subject: [PATCH 16/46] Switch variant field back to being in the part number --- default.kibot.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 5d81110..9b31ff5 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -36,14 +36,14 @@ outputs: type: pdf_sch_print dir: . options: - output: "%f_%r%v_%i.%x" + output: "%f%v_%r_%i.%x" - name: 'print_pcb' comment: "Print Top and Bottom Copper+Silk" type: pcb_print dir: . options: - output: "%f_%r%v_PCB.%x" + output: "%f%v_%r_PCB.%x" pages: - layers: - layer: F.Cu @@ -75,7 +75,7 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f_%r%v_%i.%x" + output: "%f%v_%r_%i.%x" expand_text_vars: true - name: 'bom_csv' @@ -114,7 +114,7 @@ outputs: type: step dir: . options: - output: '%f_%r%v.%x' + output: '%f%v_%r.%x' download: false subst_models: true @@ -130,7 +130,7 @@ outputs: download: false download_lcsc: false orthographic: true - output: 'PCB_%f_%r%v.%x' + output: 'PCB_%f%v_%r.%x' show_components: 'none' - name: 'pcba_render' @@ -145,14 +145,14 @@ outputs: zoom: -1 download_lcsc: false orthographic: true - output: 'PCBA_%f_%r%v.%x' + output: 'PCBA_%f%v_%r.%x' show_components: 'all' - name: 'neo_position' comment: "Pick and place" type: position options: - output: '%f_%r%v_cpl.%x' + output: '%f%v_%r_cpl.%x' format: CSV units: millimeters separate_files_for_front_and_back: false @@ -163,7 +163,7 @@ outputs: type: stencil_3d dir: '3D_Stencil' options: - output: '%f_%r%v_%i.%x' + output: '%f%v_%r_%i.%x' - name: 'diff_pcb' comment: "Diff for visual comparison" @@ -187,7 +187,7 @@ outputs: type: ibom dir: . options: - output: '%f_%r%v_%i.%x' + output: '%f%v_%r_%i.%x' dark_mode: true - name: JLCPCB_gerbers @@ -240,7 +240,7 @@ outputs: metric_units: true map: gerber route_mode_for_oval_holes: false - output: "%f_%r%v_%i.%x" + output: "%f%v_%r_%i.%x" - name: 'JLCPCB_compress' comment: ZIP file for JLCPCB @@ -251,7 +251,7 @@ outputs: dest: / - from_output: JLCPCB_drill dest: / - output: '%f_%r%v_JLC.%x' + output: '%f%v_%r_JLC.%x' # groups: # - name: pcb # outputs: From 003b7401311f42db72195846e451c76e8c1ce03d Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 3 Jun 2025 07:49:31 +1000 Subject: [PATCH 17/46] WIP: pre-panel script to parse and impl panel info --- .scripts/post_panel.py | 4 +- .scripts/pre_panel.py | 98 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .scripts/pre_panel.py diff --git a/.scripts/post_panel.py b/.scripts/post_panel.py index 812700d..ae457c5 100644 --- a/.scripts/post_panel.py +++ b/.scripts/post_panel.py @@ -33,8 +33,8 @@ dest["board"]["design_settings"]["rule_severities"]["hole_near_hole"] = "ignore" dest["board"]["design_settings"]["rule_severities"]["silk_overlap"] = "ignore" dest["board"]["design_settings"]["rule_severities"]["silk_over_copper"] = "ignore" dest["board"]["design_settings"]["rule_severities"]["drill_out_of_range"] = "ignore" -# This one is just until kibot image is updated to 7.0.5 -dest["board"]["design_settings"]["rule_severities"]["copper_sliver"] = "ignore" +# # This one is just until kibot image is updated to 7.0.5 +# dest["board"]["design_settings"]["rule_severities"]["copper_sliver"] = "ignore" dest["net_settings"]["classes"] = src["net_settings"]["classes"] dest["net_settings"]["netclass_patterns"] = src["net_settings"]["netclass_patterns"] diff --git a/.scripts/pre_panel.py b/.scripts/pre_panel.py new file mode 100644 index 0000000..dbebfd6 --- /dev/null +++ b/.scripts/pre_panel.py @@ -0,0 +1,98 @@ +import json +import sys +import shutil + +proj_file = sys.argv[1] +pcb_file = sys.argv[2] +panel_file = sys.argv[3] + +def num_to_mm(input: str) -> float: + input = input.lower() + # Panic, should all be in mm for sanity's sake + if "mm" not in input: + print(input, "not in mm") + exit(1) + return float(input.replace("mm", "")) + + +class Text: + def __init__(self, text: str, anchor: str, offset: (float, float), rot: float, size: (float, float, float), just: (str, str)): + self.text = text + self.anchor = anchor + self.hoff = offset[0] + self.voff = offset[1] + self.rot = str(rot)+"deg" + self.width = size[0] + self.height = size[1] + self.thickness = size[2] + self.hjust = just[0] + self.vjust = just[1] + + # def to_json(self) -> + + +class Frame: + def __init__(self, ftype: str, width: str, spacing: str): + self.ftype = ftype.lower() + self.width = num_to_mm(width) + self.spacing = num_to_mm(spacing) + +class Panel: + def __init__(self, spacing: str, frame: Frame): + self.spacing = num_to_mm(spacing) + self.frame = frame + + self.text = "{boardTitle}-{boardRevision}" + if "frame" in self.frame.ftype or "tb" in self.frame.ftype: + if "frame" in self.frame.ftype: + else: + self.text2 = None + self.text3 = None + +print("Starting post_panel script") + +dest_folder = '/'.join(proj_file.split('/')[:-1]) +dest_name = proj_file.split('/')[-1].removesuffix(".kicad_pro") + +src_name = pcb_file.removesuffix(".kicad_pcb") +src_proj = src_name + ".kicad_pro" + +try: + shutil.copy(src_name + ".kicad_dru", dest_folder + "/" + dest_name + ".kicad_dru") +except Exception: + pass + +json_file = open(panel_file) +json_str = json_file.read() +panel_json = json.loads(json_str) + +frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["spacing"]) +panel = Panel(panel_json["layout"]["space"], frame) + + + +json_file = open(src_proj) +json_str = json_file.read() +src = json.loads(json_str) + +json_file = open(proj_file) +json_str = json_file.read() +dest = json.loads(json_str) + +# dest["board"]["design_settings"]["rule_severities"]["duplicate_footprints"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["extra_footprint"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["lib_footprint_issues"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["lib_footprint_mismatch"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["hole_near_hole"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["silk_overlap"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["silk_over_copper"] = "ignore" +# dest["board"]["design_settings"]["rule_severities"]["drill_out_of_range"] = "ignore" +# # # This one is just until kibot image is updated to 7.0.5 +# # dest["board"]["design_settings"]["rule_severities"]["copper_sliver"] = "ignore" +# dest["net_settings"]["classes"] = src["net_settings"]["classes"] +# dest["net_settings"]["netclass_patterns"] = src["net_settings"]["netclass_patterns"] + +with open(proj_file, mode="w") as json_file: + json.dump(dest, json_file, indent=2) + +print("Finished post_panel script") From 538c109b25fc86264b3e99ae885bd7ba2f54305e Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 3 Jun 2025 13:58:58 +1000 Subject: [PATCH 18/46] Panel info generation operational, need to integrate into CI --- .scripts/pre_panel.py | 173 ++++++++++++++++++++++++++++++++---------- 1 file changed, 131 insertions(+), 42 deletions(-) diff --git a/.scripts/pre_panel.py b/.scripts/pre_panel.py index dbebfd6..7ee3f67 100644 --- a/.scripts/pre_panel.py +++ b/.scripts/pre_panel.py @@ -2,11 +2,17 @@ import json import sys import shutil +from kikit.panelize import Origin,getOriginCoord +from kikit.common import findBoardBoundingBox +from pcbnewTransition.pcbnew import LoadBoard + +PCB_DIV_MM = 1000000 + proj_file = sys.argv[1] pcb_file = sys.argv[2] panel_file = sys.argv[3] -def num_to_mm(input: str) -> float: +def str_mm_to_float(input: str) -> float: input = input.lower() # Panic, should all be in mm for sanity's sake if "mm" not in input: @@ -14,42 +20,129 @@ def num_to_mm(input: str) -> float: exit(1) return float(input.replace("mm", "")) +def float_to_str_mm(input: float, n: int=0) -> str: + return "{:.2f}".format(input).zfill(n+3)+"mm" + +def float_to_deg(input: float, n: int=0) -> str: + return "{:.2f}".format(input).zfill(n+3)+"deg" + class Text: - def __init__(self, text: str, anchor: str, offset: (float, float), rot: float, size: (float, float, float), just: (str, str)): + def __init__(self, text: str, anchor: str, offset: tuple[float, float], rot: float, size: tuple[float, float, float] = (1.0, 1.0, 0.16), just: tuple[str, str] = ('center', 'center')): self.text = text self.anchor = anchor - self.hoff = offset[0] - self.voff = offset[1] + self.hoff = float_to_str_mm(offset[0]) + self.voff = float_to_str_mm(offset[1]) self.rot = str(rot)+"deg" - self.width = size[0] - self.height = size[1] - self.thickness = size[2] + self.width = float_to_str_mm(size[0]) + self.height = float_to_str_mm(size[1]) + self.thickness = float_to_str_mm(size[2]) self.hjust = just[0] self.vjust = just[1] - # def to_json(self) -> + def to_dict(self, n: int) -> dict: + if n == 0: + str_n = '' + else: + str_n = str(n + 1) + + return { + "text" + str_n: + { + "type": "simple", + "text": self.text, + "anchor": self.anchor, + "hoffset": self.hoff, + "voffset": self.voff, + "orientation": self.rot, + "width": self.width, + "height": self.height, + "hjustify": self.hjust, + "vjustify": self.vjust, + "thickness": self.thickness, + } + } class Frame: def __init__(self, ftype: str, width: str, spacing: str): self.ftype = ftype.lower() - self.width = num_to_mm(width) - self.spacing = num_to_mm(spacing) + self.width = str_mm_to_float(width) + self.spacing = str_mm_to_float(spacing) + if "frame" in self.ftype: + self.extra_d = [(self.width + self.spacing)*2, (self.width + self.spacing)*2] + elif "tb" in self.ftype: + self.extra_d = [0, (self.width + self.spacing)*2] + else: + self.extra_d = [(self.width + self.spacing)*2, 0] + +class Board: + def __init__(self, fids: list[tuple[float, float]], rot: float, dims: tuple[float, float]): + fid_list = [] + for f in fids: + fid_list.append("(" + float_to_str_mm(f[0]) + ", " + float_to_str_mm(f[1]) + ")") + self.fids = ",".join(fid_list) + self.rot = rot + self.dims = dims + class Panel: - def __init__(self, spacing: str, frame: Frame): - self.spacing = num_to_mm(spacing) + def __init__(self, spacing: str, grid: (int, int), frame: Frame, board: Board): + self.spacing = str_mm_to_float(spacing) + self.grid = grid + self.gaps = (grid[0] - 1, grid[1] - 1) self.frame = frame + self.text = None + self.text2 = None + self.text3 = None + self.text4 = None - self.text = "{boardTitle}-{boardRevision}" - if "frame" in self.frame.ftype or "tb" in self.frame.ftype: - if "frame" in self.frame.ftype: + self.dims = [self.gaps[i]*self.spacing + self.grid[i]*board.dims[i] + frame.extra_d[i] for i in range(0,2)] + + arrow_off = [frame.spacing + frame.width, frame.width] + text_off = [arrow_off[0] + 2, frame.width/2] + + if "frame" in frame.ftype or "tb" in frame.ftype: + txt_loc = ('mt', 'bl') + txt_off = ((0, text_off[1]), (text_off[0], -text_off[1])) + txt_just = (('center', 'center'), ('left', 'center')) + txt_rot = 0 else: - self.text2 = None - self.text3 = None + txt_loc = ('ml', 'br') + txt_off = ((text_off[1], 0), (text_off[1], text_off[0])) + txt_just = (('center', 'center'), ('center', 'center')) + txt_rot = 90 -print("Starting post_panel script") + self.text = Text("{boardTitle}-{boardRevision}", txt_loc[0], txt_off[0], txt_rot, just=txt_just[0]).to_dict(0) + + spacer = " " + txt =\ + "PNL (x,y) : (" + "x: " +float_to_str_mm(self.dims[0],4) + ", " + float_to_str_mm(self.dims[1],4) + ")\n" +\ + "BRD (x,y),r: (" + float_to_str_mm(board.dims[0],4) + ", " + float_to_str_mm(board.dims[1],4) + "), " +\ + float_to_deg(board.rot, 3) + "\n" +\ + "FIDS (x,y) : " + board.fids + + + self.text2 = Text(txt, txt_loc[1], txt_off[1], txt_rot, just=txt_just[1]).to_dict(1) + if "frame" in self.frame.ftype: + self.text3 = Text("ORIGY ->", "bl", (arrow_off[1], -arrow_off[0]), 0, just=("right", "center")).to_dict(2) + self.text4 = Text("ORIGX ->", "bl", (arrow_off[0], -arrow_off[1]), 90, just=("right", "center")).to_dict(3) + +print("Starting pre_panel script") + +board = LoadBoard(pcb_file) +sourceArea = findBoardBoundingBox(board) +# bottomOrig = [(a - b)/10**6 for a,b in zip(*[list(getOriginCoord(o, sourceArea)) for o in [Origin.BottomRight, Origin.BottomLeft]])] +# print("bottom Orig: ", bottomOrig) + + +fids = [] +for foot in board.Footprints(): + if "FID" in foot.GetReference(): + cent = foot.GetBoundingBox().GetCenter() + fids.append(tuple([cent[i]/PCB_DIV_MM for i in range(0,2)])) + +print("Fids:", fids) dest_folder = '/'.join(proj_file.split('/')[:-1]) dest_name = proj_file.split('/')[-1].removesuffix(".kicad_pro") @@ -66,33 +159,29 @@ json_file = open(panel_file) json_str = json_file.read() panel_json = json.loads(json_str) -frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["spacing"]) -panel = Panel(panel_json["layout"]["space"], frame) +print(panel_json) + +frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["space"]) +board = Board(fids, panel_json["layout"].get("rotation", "0deg"), (sourceArea.GetWidth()/PCB_DIV_MM, sourceArea.GetHeight()/PCB_DIV_MM)) +panel = Panel(panel_json["layout"]["space"], (int(panel_json["layout"]["rows"]), int(panel_json["layout"]["rows"])) ,frame, board) -json_file = open(src_proj) -json_str = json_file.read() -src = json.loads(json_str) -json_file = open(proj_file) -json_str = json_file.read() -dest = json.loads(json_str) +for t in [panel.text, panel.text2, panel.text3, panel.text4]: + if t is not None: + panel_json.update(t) +# panel_json.update(panel.text3) -# dest["board"]["design_settings"]["rule_severities"]["duplicate_footprints"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["extra_footprint"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["lib_footprint_issues"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["lib_footprint_mismatch"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["hole_near_hole"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["silk_overlap"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["silk_over_copper"] = "ignore" -# dest["board"]["design_settings"]["rule_severities"]["drill_out_of_range"] = "ignore" -# # # This one is just until kibot image is updated to 7.0.5 -# # dest["board"]["design_settings"]["rule_severities"]["copper_sliver"] = "ignore" -# dest["net_settings"]["classes"] = src["net_settings"]["classes"] -# dest["net_settings"]["netclass_patterns"] = src["net_settings"]["netclass_patterns"] +# json_file = open(src_proj) +# json_str = json_file.read() +# src = json.loads(json_str) +# +# json_file = open(proj_file) +# json_str = json_file.read() +# dest = json.loads(json_str) +# +json_file = open(panel_file, mode="w") +json.dump(panel_json, json_file, indent=4) -with open(proj_file, mode="w") as json_file: - json.dump(dest, json_file, indent=2) - -print("Finished post_panel script") +print("Finished pre_panel script") From f73d59d2e308f6be3f4a9cff9377ab92e6c8cb5b Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 3 Jun 2025 14:50:54 +1000 Subject: [PATCH 19/46] Cleaned up script, integrated into CI --- .scripts/pre_panel.py | 51 ++++++------------------------------------- kibot-ci.yml | 1 + 2 files changed, 8 insertions(+), 44 deletions(-) diff --git a/.scripts/pre_panel.py b/.scripts/pre_panel.py index 7ee3f67..7072905 100644 --- a/.scripts/pre_panel.py +++ b/.scripts/pre_panel.py @@ -1,16 +1,13 @@ import json import sys -import shutil -from kikit.panelize import Origin,getOriginCoord from kikit.common import findBoardBoundingBox from pcbnewTransition.pcbnew import LoadBoard PCB_DIV_MM = 1000000 -proj_file = sys.argv[1] -pcb_file = sys.argv[2] -panel_file = sys.argv[3] +pcb_file = sys.argv[1] +panel_file = sys.argv[2] def str_mm_to_float(input: str) -> float: input = input.lower() @@ -45,7 +42,6 @@ class Text: str_n = '' else: str_n = str(n + 1) - return { "text" + str_n: { @@ -87,7 +83,7 @@ class Board: class Panel: - def __init__(self, spacing: str, grid: (int, int), frame: Frame, board: Board): + def __init__(self, spacing: str, grid: tuple[int, int], frame: Frame, board: Board): self.spacing = str_mm_to_float(spacing) self.grid = grid self.gaps = (grid[0] - 1, grid[1] - 1) @@ -96,7 +92,6 @@ class Panel: self.text2 = None self.text3 = None self.text4 = None - self.dims = [self.gaps[i]*self.spacing + self.grid[i]*board.dims[i] + frame.extra_d[i] for i in range(0,2)] arrow_off = [frame.spacing + frame.width, frame.width] @@ -109,21 +104,20 @@ class Panel: txt_rot = 0 else: txt_loc = ('ml', 'br') - txt_off = ((text_off[1], 0), (text_off[1], text_off[0])) - txt_just = (('center', 'center'), ('center', 'center')) + txt_off = ((text_off[1], 0), (-text_off[1], -text_off[0])) + txt_just = (('center', 'center'), ('left', 'center')) txt_rot = 90 self.text = Text("{boardTitle}-{boardRevision}", txt_loc[0], txt_off[0], txt_rot, just=txt_just[0]).to_dict(0) spacer = " " txt =\ - "PNL (x,y) : (" + "x: " +float_to_str_mm(self.dims[0],4) + ", " + float_to_str_mm(self.dims[1],4) + ")\n" +\ + "PNL (x,y) : (" + float_to_str_mm(self.dims[0],4) + ", " + float_to_str_mm(self.dims[1],4) + ")\n" +\ "BRD (x,y),r: (" + float_to_str_mm(board.dims[0],4) + ", " + float_to_str_mm(board.dims[1],4) + "), " +\ float_to_deg(board.rot, 3) + "\n" +\ "FIDS (x,y) : " + board.fids - - self.text2 = Text(txt, txt_loc[1], txt_off[1], txt_rot, just=txt_just[1]).to_dict(1) + if "frame" in self.frame.ftype: self.text3 = Text("ORIGY ->", "bl", (arrow_off[1], -arrow_off[0]), 0, just=("right", "center")).to_dict(2) self.text4 = Text("ORIGX ->", "bl", (arrow_off[0], -arrow_off[1]), 90, just=("right", "center")).to_dict(3) @@ -132,55 +126,24 @@ print("Starting pre_panel script") board = LoadBoard(pcb_file) sourceArea = findBoardBoundingBox(board) -# bottomOrig = [(a - b)/10**6 for a,b in zip(*[list(getOriginCoord(o, sourceArea)) for o in [Origin.BottomRight, Origin.BottomLeft]])] -# print("bottom Orig: ", bottomOrig) - - fids = [] for foot in board.Footprints(): if "FID" in foot.GetReference(): cent = foot.GetBoundingBox().GetCenter() fids.append(tuple([cent[i]/PCB_DIV_MM for i in range(0,2)])) -print("Fids:", fids) - -dest_folder = '/'.join(proj_file.split('/')[:-1]) -dest_name = proj_file.split('/')[-1].removesuffix(".kicad_pro") - -src_name = pcb_file.removesuffix(".kicad_pcb") -src_proj = src_name + ".kicad_pro" - -try: - shutil.copy(src_name + ".kicad_dru", dest_folder + "/" + dest_name + ".kicad_dru") -except Exception: - pass - json_file = open(panel_file) json_str = json_file.read() panel_json = json.loads(json_str) -print(panel_json) - frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["space"]) - - board = Board(fids, panel_json["layout"].get("rotation", "0deg"), (sourceArea.GetWidth()/PCB_DIV_MM, sourceArea.GetHeight()/PCB_DIV_MM)) panel = Panel(panel_json["layout"]["space"], (int(panel_json["layout"]["rows"]), int(panel_json["layout"]["rows"])) ,frame, board) - for t in [panel.text, panel.text2, panel.text3, panel.text4]: if t is not None: panel_json.update(t) -# panel_json.update(panel.text3) -# json_file = open(src_proj) -# json_str = json_file.read() -# src = json.loads(json_str) -# -# json_file = open(proj_file) -# json_str = json_file.read() -# dest = json.loads(json_str) -# json_file = open(panel_file, mode="w") json.dump(panel_json, json_file, indent=4) diff --git a/kibot-ci.yml b/kibot-ci.yml index 30b3155..1a4f235 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -105,6 +105,7 @@ image: echo "mkdring" mkdir -p panels/$NAME echo "panelising" + python3 .gitlab/.scripts/pre_panel.py $PCB $JSON kikit panelize -p $JSON $PCB panels/$NAME/$NAME.kicad_pcb cp .gitlab/micromelon_default/micromelon_default.kicad_sch panels/$NAME/$NAME.kicad_sch cp $d/fp-lib-table panels/$NAME/ From 6d7b4336dc88a21f22a9a9ad39e4ce7881aa91ea Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 9 Jun 2025 13:18:49 +1000 Subject: [PATCH 20/46] Use the ki-ntree docker image in inventree_job_main --- kibot-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kibot-ci.yml b/kibot-ci.yml index 382c9d3..aca1cc4 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -307,6 +307,9 @@ inventree_job_dev: - !reference [.commands, boms] inventree_job_main: + image: + name: ghcr.io/andrew-collins/ki-ntree:cli + entrypoint: [""] stage: inventree rules: - !reference [.main_rules, rules] From c2310a0d963a766dba069b8728ffb102827c2db9 Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 9 Jun 2025 13:35:17 +1000 Subject: [PATCH 21/46] Fixed rules on outputs_dev --- kibot-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kibot-ci.yml b/kibot-ci.yml index aca1cc4..2c9b772 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -256,6 +256,8 @@ outputs_mech: outputs_dev: extends: outputs_mech + rules: + - !reference [.dev_rules, rules] stage: gen_fab script: # SCH From 15650e1e71357a6f174cf6c59e4c2207bc97b0b0 Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 9 Jun 2025 14:40:01 +1000 Subject: [PATCH 22/46] Fixed up quotes around name of JLC ouputs --- default.kibot.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 9b31ff5..769d550 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -190,7 +190,7 @@ outputs: output: '%f%v_%r_%i.%x' dark_mode: true - - name: JLCPCB_gerbers + - name: 'JLCPCB_gerbers' comment: Gerbers compatible with JLCPCB type: gerber dir: JLCPCB @@ -229,7 +229,7 @@ outputs: - Edge.Cuts - user - - name: JLCPCB_drill + - name: 'JLCPCB_drill' comment: Drill files compatible with JLCPCB type: excellon dir: JLCPCB From 0ed550e61351cf173695c724216829fd477baf9f Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 9 Jun 2025 15:06:33 +1000 Subject: [PATCH 23/46] Changed to using groups again, separate configs for each group currently --- default.kibot.yaml | 56 +++++++++++++++++++++++++++------------------ kibot-ci.yml | 2 +- mech.kibot.yaml | 2 -- panel.kibot.yaml | 6 ----- pcb_dev.kibot.yaml | 2 -- pcb_main.kibot.yaml | 7 ------ pos.kibot.yaml | 2 -- sch.kibot.yaml | 5 ---- 8 files changed, 35 insertions(+), 47 deletions(-) diff --git a/default.kibot.yaml b/default.kibot.yaml index 769d550..cc7a800 100644 --- a/default.kibot.yaml +++ b/default.kibot.yaml @@ -252,28 +252,40 @@ outputs: - from_output: JLCPCB_drill dest: / output: '%f%v_%r_JLC.%x' -# groups: -# - name: pcb -# outputs: -# - JLCPCB_compress -# - neo_position -# - print_pcb -# - stencil -# - interactive_bom -# -# - name: pcb_panel -# outputs: -# - JLCPCB_compress -# - neo_position -# - print_pcb -# - step -# - interactive_bom -# -# - name: sch -# outputs: -# - bom_csv -# - bom_xlsx -# - print_sch +groups: + - name: mech + outputs: + - step + + - name: pos + outputs: + - neo_position + + - name: pcb_dev + outputs: + - print_pcb + + - name: pcb_main + outputs: + - JLCPCB_compress + - neo_position + - print_pcb + - stencil + - interactive_bom + + - name: panel + outputs: + - JLCPCB_compress + - neo_position + - print_pcb + - step + - interactive_bom + + - name: sch + outputs: + - bom_csv + - bom_xlsx + - print_sch ... definitions: _KIBOT_POS_ENABLED: false diff --git a/kibot-ci.yml b/kibot-ci.yml index 2c9b772..eeed13a 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -90,7 +90,7 @@ image: python3 $CI_PROJECT_DIR/.gitlab/.scripts/orig.py ${dir_arr[i-1]} for CONF in $KIBOT_CONF do - kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS + kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS $CONF done mv $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]}/*.zip Fabrication/ 2> /dev/null || true done diff --git a/mech.kibot.yaml b/mech.kibot.yaml index d700e8a..d3e8086 100644 --- a/mech.kibot.yaml +++ b/mech.kibot.yaml @@ -4,8 +4,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - step preflight: erc: false diff --git a/panel.kibot.yaml b/panel.kibot.yaml index 6a0c242..d107b67 100644 --- a/panel.kibot.yaml +++ b/panel.kibot.yaml @@ -4,12 +4,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - JLCPCB_compress - - neo_position - - print_pcb - - step - - interactive_bom preflight: erc: false diff --git a/pcb_dev.kibot.yaml b/pcb_dev.kibot.yaml index 23ef335..d107b67 100644 --- a/pcb_dev.kibot.yaml +++ b/pcb_dev.kibot.yaml @@ -4,8 +4,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - print_pcb preflight: erc: false diff --git a/pcb_main.kibot.yaml b/pcb_main.kibot.yaml index 36bf3f4..d107b67 100644 --- a/pcb_main.kibot.yaml +++ b/pcb_main.kibot.yaml @@ -4,13 +4,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - JLCPCB_gerbers - - JLCPCB_drill - - JLCPCB_compress - - print_pcb - - stencil - - interactive_bom preflight: erc: false diff --git a/pos.kibot.yaml b/pos.kibot.yaml index bd2829c..d107b67 100644 --- a/pos.kibot.yaml +++ b/pos.kibot.yaml @@ -4,8 +4,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - neo_position preflight: erc: false diff --git a/sch.kibot.yaml b/sch.kibot.yaml index 6f754a5..955573f 100644 --- a/sch.kibot.yaml +++ b/sch.kibot.yaml @@ -3,11 +3,6 @@ kibot: import: - file: default.kibot.yaml - outputs: - - print_sch - - _bom - - bom_csv - - bom_xlsx preflight: erc: true From 88d02915a4a6982a5bc4e3fd2fcaf2a805615042 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 24 Jun 2025 09:40:00 +1000 Subject: [PATCH 24/46] Moved kibot configs around to maybe fix pipeline --- blank.kibot.yaml => configs/blank.kibot.yaml | 0 default.kibot.yaml => configs/default.kibot.yaml | 2 +- mech.kibot.yaml => configs/mech.kibot.yaml | 0 panel.kibot.yaml => configs/panel.kibot.yaml | 0 pcb_dev.kibot.yaml => configs/pcb_dev.kibot.yaml | 0 pcb_main.kibot.yaml => configs/pcb_main.kibot.yaml | 0 pos.kibot.yaml => configs/pos.kibot.yaml | 0 sch.kibot.yaml => configs/sch.kibot.yaml | 0 kibot-ci.yml | 6 +++--- 9 files changed, 4 insertions(+), 4 deletions(-) rename blank.kibot.yaml => configs/blank.kibot.yaml (100%) rename default.kibot.yaml => configs/default.kibot.yaml (99%) rename mech.kibot.yaml => configs/mech.kibot.yaml (100%) rename panel.kibot.yaml => configs/panel.kibot.yaml (100%) rename pcb_dev.kibot.yaml => configs/pcb_dev.kibot.yaml (100%) rename pcb_main.kibot.yaml => configs/pcb_main.kibot.yaml (100%) rename pos.kibot.yaml => configs/pos.kibot.yaml (100%) rename sch.kibot.yaml => configs/sch.kibot.yaml (100%) diff --git a/blank.kibot.yaml b/configs/blank.kibot.yaml similarity index 100% rename from blank.kibot.yaml rename to configs/blank.kibot.yaml diff --git a/default.kibot.yaml b/configs/default.kibot.yaml similarity index 99% rename from default.kibot.yaml rename to configs/default.kibot.yaml index cc7a800..6ef36bd 100644 --- a/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -3,7 +3,7 @@ kibot: version: 1 import: - - file: '../kibot.yaml' + - file: 'user.kibot.yaml' preflight: # erc: true diff --git a/mech.kibot.yaml b/configs/mech.kibot.yaml similarity index 100% rename from mech.kibot.yaml rename to configs/mech.kibot.yaml diff --git a/panel.kibot.yaml b/configs/panel.kibot.yaml similarity index 100% rename from panel.kibot.yaml rename to configs/panel.kibot.yaml diff --git a/pcb_dev.kibot.yaml b/configs/pcb_dev.kibot.yaml similarity index 100% rename from pcb_dev.kibot.yaml rename to configs/pcb_dev.kibot.yaml diff --git a/pcb_main.kibot.yaml b/configs/pcb_main.kibot.yaml similarity index 100% rename from pcb_main.kibot.yaml rename to configs/pcb_main.kibot.yaml diff --git a/pos.kibot.yaml b/configs/pos.kibot.yaml similarity index 100% rename from pos.kibot.yaml rename to configs/pos.kibot.yaml diff --git a/sch.kibot.yaml b/configs/sch.kibot.yaml similarity index 100% rename from sch.kibot.yaml rename to configs/sch.kibot.yaml diff --git a/kibot-ci.yml b/kibot-ci.yml index eeed13a..4349384 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -82,15 +82,15 @@ image: fi echo ${dir_arr[i-1]} echo ${sch_arr[i-1]} - USER_FILE="$CI_PROJECT_DIR/.gitlab/blank.kibot.yaml" + USER_FILE="$CI_PROJECT_DIR/.gitlab/configs/blank.kibot.yaml" if [ -f "${dir_arr[i-1]}/kibot.yaml" ]; then USER_FILE="${dir_arr[i-1]}/kibot.yaml" fi - cp $USER_FILE $CI_PROJECT_DIR/kibot.yaml + cp $USER_FILE $CI_PROJECT_DIR/.gitlab/configs/user.kibot.yaml python3 $CI_PROJECT_DIR/.gitlab/.scripts/orig.py ${dir_arr[i-1]} for CONF in $KIBOT_CONF do - kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS $CONF + kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/configs/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS $CONF done mv $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]}/*.zip Fabrication/ 2> /dev/null || true done From a69e5a291e1b0e507a7c119cb256fc92d2317698 Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 24 Jun 2025 11:42:48 +1000 Subject: [PATCH 25/46] Fixed up inventree rev --- .gitmodules | 4 ---- .scripts/ki-ntree | 1 - kibot-ci.yml | 5 +++-- 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 160000 .scripts/ki-ntree diff --git a/.gitmodules b/.gitmodules index a2d914a..02916e8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,7 +2,3 @@ path = kicad-footprint-generator url = git@gitlab.com:acmelon/kicad-footprint-generator.git branch = offset_fix -[submodule ".scripts/ki-ntree"] - path = .scripts/ki-ntree - url = https://github.com/Andrew-Collins/Ki-nTree - branch = cli diff --git a/.scripts/ki-ntree b/.scripts/ki-ntree deleted file mode 160000 index f1e2306..0000000 --- a/.scripts/ki-ntree +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f1e2306633a3c4a0a7e60f8c08ed9bcca06d7e16 diff --git a/kibot-ci.yml b/kibot-ci.yml index 4349384..d0507a8 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -157,10 +157,11 @@ image: do echo $f name=$(echo $f | cut -c3- | cut -d'-' -f1)A + rev=$(echo $f | cut -c3- | cut -d'-' -f1)A fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-) name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) echo "name: $name_n_rev" - assembly_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) + assembly_rev=$(echo $name_n_rev | cut -d'_' -f2) pcb_rev=$(echo $assembly_rev | cut -d'_' -f1,2 | cut -d'.' -f1,2) pcb_im=$fab_path/PCB_$name_n_rev.png pcba_im=$fab_path/PCBA_$name_n_rev.png @@ -172,7 +173,7 @@ image: DRY="" fi echo "Revs: $pcb_rev, $assembly_rev" - python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': '($pcb_rev, $assembly_rev)', 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 + python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': ['$pcb_rev', '$assembly_rev'], 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 done # - cp token_storage.json /tmp - | From 090bfacd2c22477cb4d5c4e2e3a73b51623cafd4 Mon Sep 17 00:00:00 2001 From: ac Date: Thu, 26 Jun 2025 13:47:52 +1000 Subject: [PATCH 26/46] Updated templates and worksheets to include drawn, check, and approve --- melon.kicad_wks | 30 +++++++++++++++++++ .../micromelon_default.kicad_pro | 3 ++ tcs.kicad_wks | 30 +++++++++++++++++++ tcs_default/tcs_default.kicad_pro | 3 ++ 4 files changed, 66 insertions(+) diff --git a/melon.kicad_wks b/melon.kicad_wks index 96a189f..bc9774d 100644 --- a/melon.kicad_wks +++ b/melon.kicad_wks @@ -420,4 +420,34 @@ "EIQK+P9lgpN4WCgLHAAAAABJRU5ErkJggg==" ) ) + (rect + (name "") + (start 47.739 18.5022) + (end 32.489 12.5022) + ) + (tbtext "DWN: ${DWN}" + (name "") + (pos 39.989 15.5022) + (justify center) + ) + (rect + (name "") + (start 32.489 18.5022) + (end 17.239 12.5022) + ) + (tbtext "CHK: ${CHK}" + (name "") + (pos 24.739 15.5022) + (justify center) + ) + (rect + (name "") + (start 17.239 18.5022) + (end 1.989 12.5022) + ) + (tbtext "APP: ${APP}" + (name "") + (pos 9.489 15.5022) + (justify center) + ) ) diff --git a/micromelon_default/micromelon_default.kicad_pro b/micromelon_default/micromelon_default.kicad_pro index fa5adcf..bd315f1 100644 --- a/micromelon_default/micromelon_default.kicad_pro +++ b/micromelon_default/micromelon_default.kicad_pro @@ -480,6 +480,9 @@ "title": "", "client": "", "partner": "", + "DWN": "", + "CHK": "", + "APP": "", "name": "" } } diff --git a/tcs.kicad_wks b/tcs.kicad_wks index 28e0c33..e314bde 100644 --- a/tcs.kicad_wks +++ b/tcs.kicad_wks @@ -450,4 +450,34 @@ (data "41 10 04 41 10 84 0A F8 FF 65 82 93 78 58 28 0B 1C 00 00 00 00 49 45 4E 44 AE 42 60 82 ") ) ) + (rect + (name "") + (start 47.739 18.5022) + (end 32.489 12.5022) + ) + (tbtext "DWN: ${DWN}" + (name "") + (pos 39.989 15.5022) + (justify center) + ) + (rect + (name "") + (start 32.489 18.5022) + (end 17.239 12.5022) + ) + (tbtext "CHK: ${CHK}" + (name "") + (pos 24.739 15.5022) + (justify center) + ) + (rect + (name "") + (start 17.239 18.5022) + (end 1.989 12.5022) + ) + (tbtext "APP: ${APP}" + (name "") + (pos 9.489 15.5022) + (justify center) + ) ) diff --git a/tcs_default/tcs_default.kicad_pro b/tcs_default/tcs_default.kicad_pro index eb81261..ab342c8 100644 --- a/tcs_default/tcs_default.kicad_pro +++ b/tcs_default/tcs_default.kicad_pro @@ -479,6 +479,9 @@ "pcb_rev": "", "title": "", "client": "TCS JOHN HUXLEY", + "DWN": "", + "CHK": "", + "APP": "", "name": "" } } From 4729aa8b86f58cfeebef3a9cb2554430d517bbd0 Mon Sep 17 00:00:00 2001 From: ac Date: Thu, 26 Jun 2025 15:46:35 +1000 Subject: [PATCH 27/46] Implemented parsing of commit message to find DWN, CHK, APP --- configs/default.kibot.yaml | 6 ++++++ kibot-ci.yml | 29 ++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/configs/default.kibot.yaml b/configs/default.kibot.yaml index 6ef36bd..9df96bb 100644 --- a/configs/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -23,6 +23,12 @@ preflight: - name: 'title' expand_kibot_patterns: true command: 'echo $KIBOT_PCB_NAME | rev | cut -d"/" -f1 | rev | cut -d"." -f1 ' + - name: 'DWN' + command: 'echo $DWN' + - name: 'CHK' + command: 'echo $CHK' + - name: 'APP' + command: 'echo $APP' check_zone_fills: true global: diff --git a/kibot-ci.yml b/kibot-ci.yml index d0507a8..0d2213b 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -148,7 +148,7 @@ image: - cat token_storage.json - cd $CI_PROJECT_DIR/Fabrication - 'SEARCH="bom.csv"' - - !reference [.commands, strip_tag] + - !reference [.commands, parse_commit] - !reference [.commands, get_files] - cd $CI_PROJECT_DIR - FAIL=0 @@ -184,7 +184,7 @@ image: # USE PRIVATE-TOKEN to upload from gitlab-ci git_tag: - - !reference [.commands, strip_tag] + - !reference [.commands, parse_commit] - | if [[ $GITLAB_CI == 'true' && $CI_COMMIT_BRANCH == "main" ]]; then echo "running git tag" @@ -236,7 +236,26 @@ image: done fi - strip_tag: + parse_commit: + - | + initials () { + echo "$(echo $1 | cut -d' ' -f1 | cut -c1-1)$(echo $1 | cut -d' ' -f2 | cut -c1-1)" + } + + str=$CI_COMMIT_MESSAGE + REV=$(echo "$str" | sed -n '1 p') + DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f1,2)") + CHK='' + APP='' + + while IFS= read -r line; do + if [[ $line == Rev* ]]; then + CHK=$(initials "$(echo $line | cut -d' ' -f2,3)") + fi + if [[ $line == App* ]]; then + APP=$(initials "$(echo $line | cut -d' ' -f2,3)") + fi + done <<<"$str" - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) outputs_mech: @@ -335,7 +354,7 @@ upload_job: when: never # Do not run this job when a tag is created manually - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch script: - - !reference [.commands, strip_tag] + - !reference [.commands, parse_commit] - apt remove libcurl4 -y - apt-get update && apt-get -y install zip curl - | @@ -370,7 +389,7 @@ release_job: when: never # Do not run this job when a tag is created manually - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch script: - - !reference [.commands, strip_tag] + - !reference [.commands, parse_commit] - apk add jq curl - | echo "running release_job for $TAG" From 00b6518d84b499cadf2c32df7634ec410400c63e Mon Sep 17 00:00:00 2001 From: ac Date: Thu, 26 Jun 2025 16:52:54 +1000 Subject: [PATCH 28/46] Export DWN CHK APP so that kibot can use them --- kibot-ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 0d2213b..9ab0517 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -244,7 +244,7 @@ image: str=$CI_COMMIT_MESSAGE REV=$(echo "$str" | sed -n '1 p') - DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f1,2)") + DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f2,3)") CHK='' APP='' @@ -256,6 +256,9 @@ image: APP=$(initials "$(echo $line | cut -d' ' -f2,3)") fi done <<<"$str" + export DWN + export CHK + export APP - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) outputs_mech: From 4af1df25788d98447e86e843c32312f930e73a48 Mon Sep 17 00:00:00 2001 From: andrewc Date: Fri, 27 Jun 2025 15:49:24 +1000 Subject: [PATCH 29/46] Move templates to their own folder, create a hfs template. --- configs/default.kibot.yaml | 2 +- tcs.kicad_wks | 483 ----------------- tcs_default/meta/icon.png | Bin 2908 -> 0 bytes templates/hfs.kicad_wks | 493 ++++++++++++++++++ .../hfs_default/hfs_default.kicad_pcb | 0 templates/hfs_default/hfs_default.kicad_pro | 488 +++++++++++++++++ .../hfs_default/hfs_default.kicad_sch | 0 .../hfs_default/hfs_default_panel.json | 0 templates/hfs_default/meta/icon.png | Bin 0 -> 840 bytes templates/hfs_default/meta/info.html | 11 + melon.kicad_wks => templates/melon.kicad_wks | 0 .../micromelon_default}/meta/icon.png | Bin .../micromelon_default}/meta/info.html | 0 .../micromelon_default.kicad_pcb | 90 ++++ .../micromelon_default.kicad_pro | 4 +- .../micromelon_default.kicad_sch | 21 + .../micromelon_default_panel.json | 0 templates/tcs.kicad_wks | 453 ++++++++++++++++ templates/tcs_default/meta/icon.png | Bin 0 -> 10960 bytes .../tcs_default}/meta/info.html | 0 .../tcs_default}/tcs_default.kicad_pcb | 0 .../tcs_default}/tcs_default.kicad_pro | 4 +- .../tcs_default}/tcs_default.kicad_sch | 0 templates/tcs_default/tcs_default_panel.json | 38 ++ 24 files changed, 1599 insertions(+), 488 deletions(-) delete mode 100644 tcs.kicad_wks delete mode 100644 tcs_default/meta/icon.png create mode 100644 templates/hfs.kicad_wks rename micromelon_default/micromelon_default.kicad_pcb => templates/hfs_default/hfs_default.kicad_pcb (100%) create mode 100644 templates/hfs_default/hfs_default.kicad_pro rename micromelon_default/micromelon_default.kicad_sch => templates/hfs_default/hfs_default.kicad_sch (100%) rename micromelon_default/micromelon_default_panel.json => templates/hfs_default/hfs_default_panel.json (100%) create mode 100644 templates/hfs_default/meta/icon.png create mode 100644 templates/hfs_default/meta/info.html rename melon.kicad_wks => templates/melon.kicad_wks (100%) rename {micromelon_default => templates/micromelon_default}/meta/icon.png (100%) rename {micromelon_default => templates/micromelon_default}/meta/info.html (100%) create mode 100644 templates/micromelon_default/micromelon_default.kicad_pcb rename {micromelon_default => templates/micromelon_default}/micromelon_default.kicad_pro (98%) create mode 100644 templates/micromelon_default/micromelon_default.kicad_sch rename tcs_default/tcs_default_panel.json => templates/micromelon_default/micromelon_default_panel.json (100%) create mode 100644 templates/tcs.kicad_wks create mode 100644 templates/tcs_default/meta/icon.png rename {tcs_default => templates/tcs_default}/meta/info.html (100%) rename {tcs_default => templates/tcs_default}/tcs_default.kicad_pcb (100%) rename {tcs_default => templates/tcs_default}/tcs_default.kicad_pro (98%) rename {tcs_default => templates/tcs_default}/tcs_default.kicad_sch (100%) create mode 100644 templates/tcs_default/tcs_default_panel.json diff --git a/configs/default.kibot.yaml b/configs/default.kibot.yaml index 9df96bb..8e4e607 100644 --- a/configs/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -33,7 +33,7 @@ preflight: global: environment: - user_templates: "${CI_PROJECT_DIR}/.gitlab" + user_templates: "${CI_PROJECT_DIR}/.gitlab/templates" restore_project: true outputs: diff --git a/tcs.kicad_wks b/tcs.kicad_wks deleted file mode 100644 index e314bde..0000000 --- a/tcs.kicad_wks +++ /dev/null @@ -1,483 +0,0 @@ -(kicad_wks (version 20220228) (generator pl_editor) - (setup (textsize 1.5 1.5)(linewidth 0.15)(textlinewidth 0.15) - (left_margin 10)(right_margin 10)(top_margin 10)(bottom_margin 10)) - (rect (name "") (start 110 34) (end 2 2) (comment "rect around the title block") -) - (rect (name "") (start 0 0 ltcorner) (end 0 0) (repeat 2) (incrx 2) (incry 2)) - (line (name "") (start 50 2 ltcorner) (end 50 0 ltcorner) (repeat 30) (incrx 50)) - (tbtext "1" (name "") (pos 25 1 ltcorner) (font (size 1.3 1.3)) (repeat 100) (incrx 50)) - (line (name "") (start 50 2 lbcorner) (end 50 0 lbcorner) (repeat 30) (incrx 50)) - (tbtext "1" (name "") (pos 25 1 lbcorner) (font (size 1.3 1.3)) (repeat 100) (incrx 50)) - (line (name "") (start 0 50 ltcorner) (end 2 50 ltcorner) (repeat 30) (incry 50)) - (tbtext "A" (name "") (pos 1 25 ltcorner) (font (size 1.3 1.3)) (justify center) (repeat 100) (incry 50)) - (line (name "") (start 0 50 rtcorner) (end 2 50 rtcorner) (repeat 30) (incry 50)) - (tbtext "A" (name "") (pos 1 25 rtcorner) (font (size 1.3 1.3)) (justify center) (repeat 100) (incry 50)) - (tbtext "Date: ${ISSUE_DATE}" (name "") (pos 87 6.9)) - (line (name "") (start 110 5.5) (end 2 5.5)) - (tbtext "${KICAD_VERSION}" (name "") (pos 109 4.1) (comment "Kicad version") -) - (line (name "") (start 110 8.5) (end 2 8.5)) - (tbtext "Rev: ${REVISION}" (name "") (pos 24 6.9) (font bold)) - (tbtext "Size: ${PAPER}" (name "") (pos 109 6.9) (comment "Paper format name") -) - (tbtext "Id: ${#}/${##}" (name "") (pos 24 4.1) (comment "Sheet id") -) - (line (name "") (start 110 12.5) (end 2 12.5)) - (tbtext "Title: ${TITLE}" (name "") (pos 109 10.7) (font (size 2 2) bold italic)) - (tbtext "File: ${FILENAME}" (name "") (pos 109 14.3)) - (line (name "") (start 110 18.5) (end 2 18.5)) - (tbtext "Sheet: ${SHEETPATH}" (name "") (pos 109 17)) - (tbtext "Micromelon Robotics" (name "") (pos 109 20) (font bold) (comment "Company name") -) - (tbtext "In association with: Designworks" (name "") (pos 109 23) (comment "Comment 0") -) - (tbtext "Client: ${client}" (name "") (pos 109 26) (comment "Comment 1") -) - (tbtext "${COMMENT3}" (name "") (pos 109 29) (comment "Comment 2") -) - (tbtext "${COMMENT4}" (name "") (pos 109 32) (comment "Comment 3") -) - (line (name "") (start 90 8.5) (end 90 5.5)) - (line (name "") (start 26 8.5) (end 26 2)) - (bitmap (name "") (pos 28.989 25.3822) (scale 1) - (pngdata - (data "89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 02 38 00 00 00 A1 08 06 00 00 00 CA 83 C5 ") - (data "54 00 00 00 04 73 42 49 54 08 08 08 08 7C 08 64 88 00 00 00 09 70 48 59 73 00 00 2E 18 00 00 2E ") - (data "18 01 2A AA 27 20 00 00 20 00 49 44 41 54 78 9C ED 9D 5D 92 DA D6 F6 F6 9F 25 3E F2 DE B5 4E 55 ") - (data "4B E6 CE 9C 11 98 73 97 6A 27 65 65 04 86 11 98 8C 20 9D 11 18 8F 20 ED 11 04 8F 00 3C 82 D0 75 ") - (data "62 57 EE 42 8F E0 D0 77 0E 72 D5 9F BE 3B 07 90 D6 7B 21 D1 08 1A 49 7B EB 0B BA B3 7E 55 A9 8A ") - (data "1B 21 6D 84 D8 FB D9 EB 13 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 ") - (data "41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 ") - (data "04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 ") - (data "10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 84 ") - (data "53 84 8E 3D 80 C7 02 8F BE 6D AF 51 6F 03 70 00 80 0C DF D9 BE 48 AF 0E BC E5 0E C4 53 00 80 4F ") - (data "0B 06 4D 0D F0 C2 07 4D EB A8 4F A9 37 59 94 3E 68 41 10 04 41 F8 9B 22 02 27 86 E5 E8 A2 43 30 ") - (data "BA 64 F8 0E 98 3A 00 CE 0A BE C4 2D 33 8F 1B BD CF 97 05 9F 57 10 04 41 10 FE F6 88 C0 89 B0 1E ") - (data "7D DF 05 FC 2E 08 5D 14 2F 68 0E E2 33 FF AB D9 FB 3C AD E2 5A 82 20 08 82 F0 77 A1 7E EC 01 1C ") - (data "9B D5 E8 3B 87 C0 FD 40 D4 F8 95 88 9A 28 0D F8 E2 AA 12 04 41 10 84 82 F9 5B 0A 1C 1E 39 A6 87 ") - (data "65 17 44 03 80 9F 1F 71 28 B7 D4 FB 63 76 C4 EB 0B 82 20 08 C2 93 E4 6F 25 70 78 E4 98 6B AC 2F ") - (data "3D 5A 5D 02 54 B9 B5 E6 E1 80 30 39 F6 10 04 41 10 04 E1 29 F2 B7 10 38 51 61 43 F9 63 6B 6E 41 ") - (data "3C 63 DF 98 00 00 C1 9F 31 8C D9 FE 41 04 32 19 DC 31 0C EE 32 E3 45 CC C8 26 39 C7 22 08 82 20 ") - (data "08 C2 01 9E BC C0 59 8F 2E FA 1E AD 06 04 64 73 45 11 5F 87 62 66 D2 E8 FD 3E D1 7C F7 D8 1B BD ") - (data "5C 80 F0 CB A1 17 6B F0 75 CF 27 08 82 20 08 82 02 4F 56 E0 2C 47 17 1D C3 C0 55 4C 8D 9A 24 EE ") - (data "C0 18 03 C6 B8 86 DA 84 BA F9 EA D5 30 D0 89 79 49 E2 6F 04 41 10 04 A1 24 9E A4 C0 59 8D BE 1B ") - (data "10 F1 5B B0 C6 9B 88 AF E1 63 58 EF 7D 1E 16 3A 18 0A 0A 03 3E 40 E2 6F 04 41 10 04 A1 34 9E 94 ") - (data "C0 E1 D1 B7 6D DF A8 8D 99 39 26 E6 E5 01 77 60 8C 6B F0 06 D4 2D DE 9A C2 A3 6F DB 5E AC 6B 4C ") - (data "E2 6F 04 41 10 04 A1 2C 9E 8C C0 09 62 6D E8 0A AC 14 44 7C C7 4C 57 75 D4 AF CA 6C 99 E0 C1 70 ") - (data "E2 5E 93 F8 1B 41 10 04 41 28 8F 27 21 70 56 A3 8B 2B 10 FD A4 74 30 E3 43 0D 8D CB 6A 7A 41 91 ") - (data "13 F3 82 C4 DF 08 82 20 08 42 89 3C 6A 81 C3 23 C7 F4 8C E5 58 29 90 98 F8 DA F7 71 59 69 5B 04 ") - (data "89 BF 11 04 41 10 84 A3 F0 68 05 4E 10 6F B3 1A 83 29 2D DE E6 8E 18 83 5A F7 F3 55 25 03 0B 09 ") - (data "AA 25 AF 24 FE 46 10 04 41 10 8E C0 A3 14 38 CB D1 45 C7 23 9A A4 C5 DB 10 E1 C6 F0 BD EE 31 DC ") - (data "41 1E 96 DD B8 5E A6 12 7F 23 08 82 20 08 E5 F2 E8 04 CE 72 74 D1 31 88 26 48 A9 48 CC CC EF EB ") - (data "DD CF 97 D5 8C EA C0 F5 81 4E 4C AB 76 89 BF 11 04 41 10 84 92 79 54 02 47 51 DC DC 81 8D 7E A3 ") - (data "F7 EF 71 45 C3 3A 88 61 90 C3 87 EA F0 48 FC 8D 20 08 82 20 94 CE A3 11 38 8A E2 E6 D6 67 EE 36 ") - (data "7B FF AE 2E 90 F8 00 3C 72 4C 8F 57 D2 7F 4A 10 04 41 10 8E C4 A3 10 38 2A E2 26 88 B7 69 38 F5 ") - (data "4A D2 BF 93 F1 E0 39 71 AF 49 FC 8D 20 08 82 20 94 8F 71 EC 01 A4 C1 23 C7 AC 19 34 84 82 B8 A9 ") - (data "A6 B6 4D 3A 1C 2F 70 24 FE 46 10 04 41 10 2A E0 E4 05 8E 6F AC 26 CC 88 4D 05 3F 35 71 03 04 F1 ") - (data "37 07 5F 90 F8 1B 41 10 04 41 A8 84 93 16 38 EB D1 CB E1 63 13 37 3C 72 CC F8 31 4B FC 8D 20 08 ") - (data "82 20 54 C1 C9 0A 1C 6F F4 F2 12 84 37 71 AF 9F A2 B8 01 24 FE 46 10 04 41 10 4E 81 93 14 38 CB ") - (data "D1 45 87 09 BF C4 BD 7E AA E2 06 90 F8 1B 41 10 04 41 38 05 4E 4E E0 F0 C8 31 0D A2 A4 1A 36 77 ") - (data "9E CF FD BC E2 86 47 DF B6 BD D1 CB C2 0B 01 4A FC 8D 20 08 82 20 1C 9F 93 13 38 1E 56 43 00 31 ") - (data "3D 9C 00 66 EA E6 6D 98 19 B4 7A A8 FD 87 09 BF 78 1F 5F 4E 79 E4 98 79 CE 77 3F 36 89 BF 11 04 ") - (data "41 10 84 93 E0 A4 04 CE 7A F4 7D 17 84 D7 71 AF 13 E3 E7 46 EF F7 49 DE EB 34 D0 9C 6D FE 9F 19 ") - (data "2F 7C 63 35 29 42 E4 48 FC 8D 20 08 82 20 9C 06 27 23 70 78 E4 98 20 7F 18 7F 00 3E D6 7A 9F 0A ") - (data "E9 08 4E BD C9 02 C4 D7 F7 A7 0E 45 4E DE F3 4A FC 8D 20 08 82 20 9C 06 27 23 70 3C AC AE 10 5F ") - (data "CC EF AE 86 46 BF C8 EB B1 6F 0C 76 FE CD 78 B1 1A 5D E4 12 50 12 7F 23 08 82 20 08 A7 41 4C C3 ") - (data "EB 6A 59 8D BE 73 88 F8 B7 B8 D7 99 E9 87 22 5C 53 FB AC 3F 5E 4C C0 F4 6A F7 62 46 AF 9E A1 51 ") - (data "27 8F 1C D3 A3 D5 FF 1D 7E 91 7F AC F7 3E 0F 33 0D 52 38 2A 96 65 75 98 6B 26 C0 1D C3 E0 07 6E ") - (data "4C DF 37 26 00 B0 5E FF 77 BA 58 2C 4E 2E AB EF 94 D9 DC 5B C3 F0 9D B8 63 98 79 C6 5C 9B 7D FD ") - (data "FA 65 52 DD C8 04 21 1B 96 65 75 88 A8 0D A0 03 00 CC BB 9B 5E 66 5E 18 06 A6 BE 4F 0B 80 A6 32 ") - (data "6F 94 CB 49 08 1C EF E3 CB 69 5C 70 2E 33 BF 6F F4 3E 17 9E ED 04 C4 0A AB DB 1A 37 3A BA 59 5A ") - (data "41 FC 90 3F 3A F4 5A 8D BD 7F AA B8 A8 2C CB EA 87 3F 0E 65 0C C3 18 7E F9 F2 25 F5 DC 0A D7 EE ") - (data "10 51 57 F5 78 DF 47 87 88 4C D7 FD CB 49 3A CE B6 ED 2E 33 95 F2 FD 45 46 33 75 5D B7 90 6B 6C ") - (data "EE 43 30 31 F1 AB D4 37 EC 72 07 D0 94 88 27 BE 6F 4C B2 2C CA E7 E7 CF 2E 89 A0 FC 3D 24 C3 33 ") - (data "22 CC C2 7F 4C 99 79 E6 BA EE D1 1A D1 B6 5A AD F6 7A CD DD E0 F3 69 DF 5B 00 B8 21 C2 B8 A8 67 ") - (data "7E 9F 2C F7 9E 88 AF E6 F3 B9 F6 86 68 9F 56 AB D5 F6 3C 1E EA BE AF 56 A3 BE CA BD A8 E6 77 78 ") - (data "18 66 8C BF 7E FD 2B D1 3A 6E DB F6 60 5F 0C C4 41 C4 93 F9 7C 3E 28 62 6C 79 31 4D D3 6C 34 1A ") - (data "5D 66 EA 12 C1 41 72 33 E8 38 6E 98 69 58 AF D3 B8 8C E7 DA B2 9E 4D F4 DE 91 6F 3E B5 2C AB 0F ") - (data "18 FD F4 23 79 E6 BA 73 85 E3 B2 73 F4 66 9B EB D1 45 3F A1 5A F1 5D 1D CD 41 59 D7 6E F4 7E 9F ") - (data "AC 46 17 EF 89 E8 A7 C8 9F 9F AF B1 BE 04 A0 75 5D 86 E7 D0 61 BD A8 11 7F 43 57 CC 7A 3F 10 CF ") - (data "F3 66 00 86 3A EF 89 B9 76 62 D5 E8 07 47 13 00 F0 4D DA 71 CC EC 00 C8 B2 98 29 43 41 23 D6 CC ") - (data "98 A6 69 36 9B CD 4B DF 47 1F C0 73 66 00 E0 2C A7 3A 03 F8 15 33 5E 11 F9 6F 2D CB BE 03 30 06 ") - (data "F8 4A 55 58 10 71 1F 50 FF 1E 52 78 C5 3B 1F 83 60 59 F6 1D 33 26 44 3C 76 5D 77 58 D0 75 12 D9 ") - (data "4C 78 9E E7 BF A2 7C 5B AA 17 CC 78 E1 79 FE 5B CB 7A 76 CD 4C 83 22 2D 3B 59 84 17 33 4F 01 E4 ") - (data "16 38 81 B8 D1 17 D4 5F BE FC 35 53 39 90 39 B3 A8 CC 0D 51 BA 70 0B C7 A7 F4 DC FB 7E 62 19 91 ") - (data "4A 38 3F 6F 39 44 7E 1F 08 8A D1 E6 7D AE 89 F8 17 CF E3 5F 2C CB FE 50 AB 19 83 A2 84 CE F9 79 ") - (data "CB 01 7C CD EF 9D 5E B5 5A AD AB EC 63 30 FA 8A CF 5A C6 F3 AB 73 FC 18 1C A2 41 EC 6B CC 97 65 ") - (data "17 F3 AB A3 39 20 C2 CE 42 4D C4 97 BA 59 55 79 E3 6F 5A AD 56 1B 99 D4 BF DA AE 27 09 DB B6 07 ") - (data "C8 B6 A8 2A 2C DA F9 C7 97 C6 C6 4D A4 4B AB D5 6A 5B 96 3D 6C 34 9A FF C7 8C B7 44 F1 E5 09 32 ") - (data "72 06 E0 0D 40 7F 5A D6 B3 49 30 D9 C4 63 9A A6 89 E2 C4 4D EC 98 88 F0 1A A0 5F 2D CB 5E D8 B6 ") - (data "3D 08 AF 5B 38 96 65 F5 CF CF ED 19 40 BF 16 BF B8 F2 2B 22 FF 37 CB B2 AE 8A 1B 7F 96 31 1A 9D ") - (data "BC 57 3D 3F 7F 76 99 ED DA A4 63 8D CB 3D CE 1C 24 8E 53 FF B9 D7 FA DC 85 62 59 56 C7 B2 9E 4D ") - (data "88 FC DF 80 F8 4A FB 39 78 E3 79 FE 34 78 26 F2 93 E4 FE 4D C2 F3 BC 1C D7 57 7B 96 99 CB FF 1E ") - (data "8F 2A 70 D6 A3 8B 3E E2 6A DE 10 5F 57 11 B7 42 BD C9 C2 F0 BD 2E 80 BB C8 9F CF 7C AC FA AA E7 ") - (data "28 A2 FE 8D E7 C5 A7 98 A7 90 6B E2 0A E2 20 F0 36 DB BB 93 3F 5B 45 0B 36 D6 EB FF 6A FF 50 6C ") - (data "DB 1E 78 9E 3F 45 39 93 D4 01 F8 15 90 90 25 08 A0 5E FF 7F 55 2F 42 67 CC 78 5B AF 37 A7 96 65 ") - (data "15 76 ED 60 11 B0 A7 00 FD 5A 82 68 DC 83 7E 6A 34 9A 93 BC E3 4F 13 9F F1 E4 13 6E 81 4B 94 63 ") - (data "AB B6 27 41 A4 36 B7 54 F5 3B 8C E1 2E CD 7A D9 6C 36 1D 9D 13 1E 23 1E CB 34 4D D3 B2 AC 2B 80 ") - (data "FE AC C0 12 76 46 C4 BF 58 96 3D CC 7B 22 DF CF BA 3E 50 3F CB C6 41 E7 77 48 54 7E E9 94 E3 5A ") - (data "70 12 AC 37 FB 59 4E A5 0E A3 F7 C7 CC 0F 5C 29 F7 22 87 0D 56 F6 C5 17 54 FF 26 EB 04 FD 22 EB ") - (data "0E 36 78 1F 0D 33 5E 17 B5 5A 6D 92 F4 7A 45 0B F6 8D 4E 90 5E 68 B5 99 86 A2 2E 8B BF 3C 33 44 ") - (data "C9 D6 BC AC BB AD BC 04 22 84 72 8B 04 60 63 0D A4 3F 51 ED 82 FA 22 EF F8 F3 DC FB EC E2 08 C8 ") - (data "F3 FB 53 B5 5C EA 0A 88 22 61 35 0B B6 C6 F7 46 D7 E9 C7 14 8B 65 59 9D 7A BD 39 05 76 42 19 AA ") - (data "E0 4D 5E 91 13 C6 05 65 E1 AC 5E FF A6 AF FB 26 66 43 F5 7A A9 C2 B7 08 8E 26 70 12 AD 37 8C 0F ") - (data "65 64 4D 25 D1 EC 7D 9E 86 22 E7 36 18 03 29 FF E8 8A A9 7F 93 DD 95 93 55 48 34 1A 8D 01 B2 2F ") - (data "44 77 69 3E DA 6A 16 6C F5 0A D1 B6 6D 77 43 AB CD 91 76 B3 C9 63 55 0D B2 2C 89 33 66 1A E7 11 ") - (data "CB E7 E7 F6 38 BB 35 30 37 B9 C6 9F 7D A7 0B 00 9C E9 BD 39 5C C3 00 B4 2C 19 47 73 4F 19 46 BA ") - (data "1B 5B E7 B9 57 B5 5A 15 45 10 3F 46 7F 96 6F 89 8C 25 B3 C8 09 05 7F 8E 4D 1C 67 70 53 B1 A3 76 ") - (data "5C 35 6E C6 E3 59 70 12 AC 37 35 78 B1 AF 95 49 B3 F7 79 5A E3 46 87 99 DF 87 62 47 89 BC F1 37 ") - (data "79 4D C8 59 84 44 B0 EB CC BE 23 51 D9 99 55 B4 60 2B FD 50 2C CB EA 33 63 84 8A AD 36 51 D2 2C ") - (data "5E C7 0A 02 DD 40 84 E7 CD 66 53 7B 52 0B 32 49 9A 13 4A A8 42 5E 05 44 78 5E AF 37 87 19 DF EB ") - (data "64 BF B2 FA 5C B1 21 9F 6B 18 00 90 1A E0 BF E1 98 C2 59 CD CA A4 F5 DC 57 16 7F 13 8A 9B 5F AB ") - (data "BA 5E 02 6F 6C DB CE 92 59 99 4B D8 12 E1 79 86 EB 2A 5D B3 2A A1 7A 94 2C AA F5 E8 FB 2E E0 C7 ") - (data "5A 6F 8E 59 F5 37 0C 6A 56 9E E4 79 E4 98 1E AF 72 C5 DF 04 16 18 5F F5 92 0F D0 DD 7D 06 82 2A ") - (data "39 1E 24 1D 95 CC A5 6C 3B 5B 1D D2 45 C3 C9 4C 54 89 16 AF 22 63 60 F2 C0 0C AD 0C C2 8D B8 41 ") - (data "46 81 CE 8C 5B 00 D3 E8 4E 3F 63 8A 3E 00 80 08 AF 6D DB EE EA A4 6E E7 DF E9 66 59 48 B2 BB A6 ") - (data "02 74 16 88 E3 09 E7 34 2B 53 98 E5 A3 7C BE E5 72 99 78 BE A2 C8 39 67 DC 31 63 B2 AD 77 03 18 ") - (data "06 9B 41 69 8D 6C 9B 00 DF C7 95 69 9A 13 BD 9A 39 F9 85 6D 58 5A 40 E9 B7 14 94 3A 88 59 D7 F7 ") - (data "C8 9A 18 A2 CB 91 D2 C4 FD 7E DC 2B C7 B2 DE 64 A5 88 F8 1B C3 F0 9D DD 74 5E 3D 74 77 9F A1 6B ") - (data "2A A7 C9 35 DD C4 C8 6C 74 89 BC C5 BE AF 35 4C B1 8C 2D EC B8 8F EB CE 33 27 61 86 13 68 A6 89 ") - (data "8A 19 B7 44 3C 66 AE 8D 0F 4D D4 C1 B9 B9 A3 92 DA 9D 66 F1 62 36 1C 22 B5 87 80 19 B7 86 11 5F ") - (data "1A 80 99 CD B0 2E 47 96 EF F8 EC FC BC E5 A8 BA 3F 1A 8D 6F C6 AA E9 BD 7B 7C 00 F8 EA EB D7 C3 ") - (data "7E F8 4D EA 7E 28 B8 B4 C4 87 EF E3 0A 7A A9 DB B9 77 BA AD 56 AB AD 9A 56 1B D4 7C C9 E7 26 55 ") - (data "2D 8D A0 2B 20 88 F0 2E E3 90 1E C0 CC 33 85 A3 74 EE BD 56 BC 5D 56 B2 CE 19 E1 7C 31 48 2A BF ") - (data "10 8A 80 01 34 93 1B 02 EB E4 37 7D 00 CA D5 F6 99 E1 E4 4C 5F 07 C0 AF 54 9F ED 20 51 46 ED 82 ") - (data "59 12 43 B2 50 B9 C0 E1 D1 B7 6D 2F 4E C5 12 5F 53 37 BF F5 66 35 FA 6E 40 86 EF B0 8F 29 60 8C ") - (data "CB 8C E7 29 A2 FE 4D B8 63 CD 33 8C 33 D5 87 30 FC F1 E6 0E 96 53 59 00 E3 8E D1 13 74 D9 83 0A ") - (data "C3 C9 44 BF 2A 75 38 51 7D FD 9A 5C 27 26 FC 7C 13 00 57 A1 68 BB 42 AC D0 49 5B 90 D4 DD 1C 44 ") - (data "3C 9E CF DD 41 CA 61 97 E1 98 C6 D0 B6 4E 70 07 48 77 41 06 59 25 BA 75 63 70 0B 18 FD B4 E7 27 ") - (data "5C C8 06 96 65 8D C3 7B A7 FC 19 88 F0 5C 47 A4 15 B1 D3 F5 7D BF 03 85 BA 1E 05 B8 A6 00 00 86 ") - (data "61 28 2E 10 7A 02 A2 FA 02 7A 5A EE BD D2 17 C5 AC 73 06 11 DE B9 6E FA BD 0B E7 E8 BE 65 59 13 ") - (data "7D 0B 11 5F 42 51 E0 98 A6 69 16 15 37 14 0A B2 BE C2 A1 AA CF 5A 25 42 15 38 42 0C CE 1A F5 7E ") - (data "DC 6B 45 65 4E 11 F1 5B 30 BD 22 A2 9F 88 F8 B7 F5 F8 E5 6C 35 FA 6E C0 A3 6F DB 45 9C 3F 4A 31 ") - (data "FD A7 F2 9B 90 55 D2 CC 8B 71 4D 01 79 33 19 AA 0A 2A 0C 27 2A 5D D7 C3 87 F5 7A D9 D1 2D 82 F7 ") - (data "F5 EB 97 89 EB CE 3B 71 3B 60 85 94 48 9D 85 48 69 A2 0F 16 78 FD F8 90 43 2D 29 F6 C9 18 C3 75 ") - (data "B3 5E 2F 3B 3A 69 BE 81 F5 4F FF 33 10 79 CA B1 03 CC 79 E2 6F EE 51 FC FE F2 BA A6 02 91 A8 5E ") - (data "84 4D E7 DE 55 1B C0 0B E8 5A 9F CB 1F 5F 58 4D 5A 67 CE B8 63 36 7E D0 15 86 C1 FC C2 EF 75 DE ") - (data "43 84 E7 AA AE EC 82 33 E7 DE A8 05 EF AB CE EB D5 3D 67 95 0B 9C D0 9C 7F 88 DB A2 2C 2D CC 0F ") - (data "1E 9C E7 44 FC D6 A3 DA 7F 02 A1 A3 57 C4 2F F6 3A 05 D4 BF 29 30 F6 22 F5 3C 8D 46 63 50 84 AA ") - (data "CF 1F 20 56 7E 50 61 96 0C 15 66 FA D9 75 E7 FD 3C BB 8B F9 7C 3E 60 36 7E C0 6E 5D A5 C4 94 C8 ") - (data "56 AB D5 D6 F9 5E 54 E2 8E 36 04 D7 2D 23 B5 56 5B 28 DF B8 EE BC 93 E5 DE 86 F7 EE 83 CE 7B 98 ") - (data "D5 DA 8E 14 B5 D3 55 11 ED 81 C5 2B 7F 06 5F 5A B9 81 BD 63 1D F5 63 F3 55 04 D7 45 B7 B8 A9 CE ") - (data "73 9F 85 6C 05 17 59 C3 52 B8 CB 6A B5 1A 60 77 9E 48 BF 9A 62 1A 36 6B 24 C9 A8 A0 98 7C A0 FA ") - (data "6C 57 16 28 5E A9 C0 59 8E 2E 3A 88 89 FD 20 56 F7 2D A6 D1 E8 7D BE 04 1F 9E 10 03 A1 B3 9A 05 ") - (data "81 CE F9 28 22 FE 46 A3 6E 40 0A C9 13 6C DE AC A9 3D 32 3F A0 BA 82 2E 4B 50 61 AB D5 6A 87 B1 ") - (data "1B CA 10 E1 5D 5A BF 1C 55 22 96 93 3B 20 3D FE 46 A7 C8 A3 DE EE 3D A0 E8 8C 05 DB B6 75 85 F2 ") - (data "CD 6A B5 74 F2 5C B3 56 D3 B3 EE AA 8E AF B8 9D 6E F2 C2 58 E4 EF 4F B5 02 AC AE 80 50 77 7B 15 ") - (data "83 66 71 D3 D4 B2 14 79 08 84 2E 0F F4 DE C5 3F E6 A9 E5 12 88 7D BD FE 63 44 AA 2E C7 FC 15 B6 ") - (data "A3 84 6D 6C 62 D1 A9 05 55 B6 50 8D 52 A9 C0 A1 04 3F 9E 81 C6 B0 C8 6B D5 7B 9F FA 60 FE 11 87 ") - (data "15 F2 19 C8 1F AD 46 17 B9 16 B4 62 EA DF 14 A6 B4 63 D5 73 71 AE A9 80 3C 99 0C 9A 82 2E 93 AF ") - (data "36 F4 19 2B 4F EC CC F8 58 74 EC C1 C6 B5 12 B8 AC 8C B4 E7 AC 70 F7 54 1E 92 32 1C 4C D3 34 75 ") - (data "C5 23 C0 B9 AC 62 C0 7D EC 82 72 6A 34 A0 36 E9 16 B9 D3 8D 13 EF 45 FF FE 54 2B C0 96 2D 9C 0B ") - (data "40 BD D6 98 96 CB 5F 9F D0 42 A1 35 67 14 D1 CB 8D B9 A6 19 EF 43 6D C5 33 17 9A 39 17 BA C7 FA ") - (data "71 AF AB 96 2A A9 FA 39 AB 56 E0 C4 75 AB 66 7C 2C A3 E7 54 BD F7 79 58 63 AF 03 E2 83 26 7A 22 ") - (data "FA 69 3D 7A 39 CC 7A FE 62 E2 6F 8A 2B C2 15 37 A1 D7 EB CD 61 81 85 AA 72 06 88 95 1B 54 18 EE ") - (data "5A 75 32 14 EE D6 EB 65 5F F7 3A 2A B8 AE 3B 9D CF E7 0A 0D 21 75 82 5C F5 DD 08 BA 75 50 EA F5 ") - (data "F8 60 59 DD 85 20 08 BE 2C AC 62 69 09 E2 4E 6D A7 1B A6 B3 A7 1C 63 38 87 FE 5E 94 6B 38 44 A7 ") - (data "02 AC F2 DC A2 E3 F6 2A 8E 72 9F 7B 55 32 88 F6 C2 E6 0C 7D F7 96 6A 7C 9C 1A 7A 59 73 F1 1D C2 ") - (data "35 E6 98 4A AD 84 95 65 51 25 B9 A7 00 D6 8E 5A 57 25 B4 A4 38 AB D1 77 0E 19 FE 00 4C BB CA 96 ") - (data "F0 66 35 BA 58 34 7A 9F B5 76 A5 45 D4 BF D1 A9 1B 80 20 06 21 65 E1 7E 98 FD 62 DB 76 97 B9 D0 ") - (data "02 6C 79 1F 50 0D 41 A7 EF 5A F1 FD F8 12 04 07 AF C0 34 A8 2A A2 3F 01 8D 2E EE 7A FD 5B C2 67 ") - (data "4C 79 37 97 B6 C3 F2 7D F4 35 52 4F EF 96 CB 65 61 AE 67 22 CC F2 94 53 38 8C F2 4E 77 0A C0 44 ") - (data "82 B8 3B E4 3E 28 2A 6B 31 72 15 8D DF 9F 9E B0 CD D7 72 22 A0 5E C7 4C 65 87 7E 4A 0D 36 1B 8D ") - (data "46 17 7A A2 FD AA E0 39 E3 4E E3 FA A9 F7 4C 23 4B F5 6E B9 5C 5E 35 1A AA 9B 16 7E 15 9F 9D A8 ") - (data "EA 3A AB 36 CE AB 32 81 53 03 39 71 F7 BC 86 66 69 02 67 43 18 C0 1C 08 1D F0 25 22 A9 EA A1 65 ") - (data "49 4B E0 14 11 7F A3 53 37 80 08 63 66 A4 FC 10 D9 41 24 8D 30 DC 99 0C 93 CE BB D9 99 AA EF 30 ") - (data "B3 C7 73 68 0A BA 4C BE 5A 9D 9D 18 33 6E 8B 8A BB C9 8A 6E 9D 12 5D 6B C8 7A ED 5F E9 D5 C2 A0 ") - (data "D8 FB 11 8A 65 E5 EF AF 84 85 A0 50 F4 EE 3D 4D 00 98 49 82 68 3F 1B 4B D1 35 75 87 20 BD 5C 69 ") - (data "B1 2F B1 C1 E6 1B 22 3F 77 E3 59 DF C7 3B 28 14 8A D4 2D 6E 5A 6E 83 4D D2 9A FB 8B 14 ED E1 F5 ") - (data "A7 45 BA 94 C2 82 82 A9 30 63 B2 58 2C 16 96 65 0D 55 E3 C3 88 FC 3E F6 36 D1 3A 85 32 AB 68 B0 ") - (data "19 A5 32 17 55 6C F3 CA 92 DC 53 71 34 7A BF 4F EA BD 4F DD 7A F7 13 31 D3 0F 60 FE B1 C6 FA 9D ") - (data "BC 8B 89 BF 51 B7 66 04 71 2F A9 BB 98 9D F3 85 65 EB 13 1F 3C C3 C0 65 59 19 3C FB 94 1D 54 18 ") - (data "96 15 D7 48 F1 8C 5F CC AB 42 AF CD 86 7A 36 54 D0 FD D8 1E 6A 56 4E BD 5B AF FF 37 8C 7B 31 14 ") - (data "D8 CA 18 86 11 7B AE 53 40 E7 DE 13 F9 93 34 71 41 84 E7 D1 74 5A 15 D7 14 11 FA 00 DA AA E3 50 ") - (data "AD 00 7B 84 CE F4 00 D4 C7 57 D6 73 AF 4B E8 D2 D6 11 82 1F 8E 2C DA 53 B3 AE D4 33 E7 02 6B 4A ") - (data "AD 56 D3 99 07 DF 84 F7 EC 1E 9D B8 CA 2A 1A 6C 46 A9 2E 06 67 DF 35 14 42 0A 05 C5 CA 22 10 3B ") - (data "9F 87 59 5A 43 14 13 7F A3 66 42 66 C6 ED 62 B1 58 A8 4C B0 9B 87 CF B6 ED 6E DA E2 C6 8C 8F 8A ") - (data "03 DD 90 37 93 A1 D4 A0 42 DD 05 B8 5E A7 D2 2D 87 69 14 5D 13 28 10 36 56 3F E8 7E AC 5D 2D 35 ") - (data "2D 18 58 E7 FE DE 1C 21 68 55 0B 9D 16 27 E1 C4 9C 3A 39 6F 84 85 4A D6 14 33 3E 86 D5 7E 95 45 ") - (data "B9 6A 05 D8 63 75 A6 57 B5 B4 9C 4A 83 CD F5 3A 66 E3 1D 03 91 56 85 6C 45 D2 E3 6A 22 23 48 FC ") - (data "FE F5 DA 8E 04 E7 FA F2 E5 CB 4C 67 2D D8 0F 03 50 CF EC AA BE 13 7C 25 2E AA D5 E8 3B 27 AE 52 ") - (data "AF 77 84 E2 52 79 29 22 FE 46 C7 84 1C 09 00 4C 9D DC 7C DF EF 98 A6 B9 48 73 4D 21 0C 94 D3 69 ") - (data "AE 98 3F 93 A1 EC 60 5A AD D2 E4 27 B2 00 AB 57 9A 65 46 3B AC EF 73 F0 B5 20 C3 22 30 75 67 28 ") - (data "D1 FE 21 A9 7F 93 6E BF 26 E6 FC 05 ED CA 46 63 A7 7B 0D 6C 5A 0F 24 DF 58 C3 F0 1D D3 34 A7 2A ") - (data "AE A9 7A DD B8 5C AF B9 AB DA A2 03 1A 01 FE 05 54 47 CF 82 46 96 DB A9 34 D8 D4 CB A2 D3 E9 71 ") - (data "A6 41 EE DA 48 11 94 E7 93 A8 18 35 0C 0C 55 63 35 F7 FB D5 A9 CE BB 55 77 82 07 AA 8B C1 71 62 ") - (data "FE 7E DB EC 7D AE D4 64 55 04 45 C4 DF E8 F9 A0 83 07 C3 30 8C A9 E7 25 BF 87 99 9D 7A BD D9 47 ") - (data "CA 62 B4 D9 AD 5B D6 33 47 7D 22 CC 1E 20 56 76 50 A1 7E C1 B6 E3 0B EB 0C 4D 1E DF 24 07 0F 66 ") - (data "5E D0 3E B8 EE BC 9F 78 66 8D 5E 59 01 C5 07 85 32 B3 A9 1A B3 06 24 5B 13 F4 E2 06 82 67 C5 75 ") - (data "DD A9 65 D9 29 63 24 A7 5E 6F 76 D2 9E 45 66 1A 7C F9 F2 65 66 59 76 49 41 F7 C7 68 B0 59 4E 71 ") - (data "D3 32 1B 6C EA 55 52 AE DE 02 F1 10 3F E5 77 A5 BA 89 DC FD 2C F3 F9 7C 7C 7E 6E DF 2A CE A1 67 ") - (data "96 65 F5 5D D7 1D 9E 62 83 CD 28 95 B8 A8 28 CE 5C CA D5 A6 8C 15 45 42 FC CD 9D AA BB 4B D3 84 ") - (data "7C 6F 4A 44 AA 0F 96 FA 2A AE A9 ED 4E 44 67 22 CC BE 68 E9 C6 04 E8 06 15 EA 9E BF EA AA AD 87 ") - (data "28 AE C8 63 1E F8 7D 9A B8 01 74 CC D0 01 E5 04 85 6A 15 2F 4B 8B 55 50 3E D7 EE C4 9C B6 C8 B1 ") - (data "42 C7 68 BA DE 04 B7 6B B6 89 50 FA FD 1D AB 33 BD EA 6F AA 8A 5A 58 2A 84 9B 2E 8D 0D 46 9A B8 ") - (data "D0 47 37 73 8D 88 D2 EE 85 D2 77 7F D8 9A A2 1E 93 C8 4C 03 E0 BE 07 9B 12 55 35 D8 8C 52 4D 0C ") - (data "0E D3 C1 9B 70 CC F8 9B 3C 14 11 7F A3 E1 83 DE AB 7B 91 2A 32 D2 7E B0 F7 35 1C 74 7F 5C 79 16 ") - (data "AD B2 83 0A 75 63 0E 7C DF 38 7A 76 8F AE 68 28 98 3B 22 F4 5C D7 55 74 51 52 5B F5 C4 2A 35 63 ") - (data "B2 A1 73 BF D2 7E 27 EA EE D2 DD 89 39 75 91 4B FD FD D5 6A D4 07 CA 6B D1 71 2C E1 AC D1 00 D4 ") - (data "D1 38 6D 69 8B 62 86 4D 51 E1 73 06 91 D7 D6 39 3E AD 08 27 72 B4 4B 08 13 0C 94 5A 47 6C 1A DA ") - (data "6A 14 CA AC AC C1 66 94 D2 5D 54 3C FA B6 ED C5 FC E8 FD 02 CC D8 3C 72 CC 35 D6 1D 03 DC 61 18 ") - (data "33 06 2F EA 58 CF B2 04 0E AB 5E 2F 2E FE 46 4F B0 A9 59 4E F6 E3 5E 88 78 C2 8C CC E6 E7 DD 40 ") - (data "52 AD 05 A3 80 06 9B 6A 2E 8E 2A 7C B5 E5 A6 9D AA A1 19 33 54 14 77 44 B8 5A 2E 97 9A 29 DC EA ") - (data "CF 0A 11 CD 32 8C 2B 91 D0 14 AE 51 AB 24 F5 19 52 FD 3C FB 13 73 AE 39 6B E3 9A 02 F4 76 BF E5 ") - (data "35 D8 2C 06 CD 0A B5 25 B9 E5 F4 30 0C DF D4 A9 AB 54 8E 8B 45 AF 56 51 D2 BC D5 6C 36 55 EB DF ") - (data "1C 74 FB 05 21 0B F6 18 CA C9 09 FE 25 60 98 6A F3 FA 71 42 02 4A 17 38 6B D4 DB 14 73 03 8A 68 ") - (data "AE E9 63 D5 27 C2 2F 1C FE 8B 00 78 A8 61 3D 7E 09 10 5F B3 8F 29 60 8C 8B 6A E4 99 14 7F 63 C0 ") - (data "53 0A 40 D3 31 21 1B C6 83 09 35 C7 04 4B D7 F3 F9 5F 91 31 AA 4F 84 A7 DE 60 53 B5 F6 C3 A9 A0 ") - (data "5B 13 A8 00 6E 98 69 B8 5E FF 6F 98 71 27 A5 DB 95 BD 50 82 60 5C F5 E3 99 E3 8B 87 EA ED 74 1F ") - (data "3C F7 B9 7E 7F D1 BA 4B C1 EE 57 F9 43 E9 5C 57 43 8C A2 57 52 E0 EC 41 AA A8 85 A5 C1 31 2D A8 ") - (data "00 74 37 39 A9 9B CC AC A2 FD 9E 5A CD 18 78 9E 5A 3D A4 C0 15 AB AC 10 8F 12 8E 52 85 8B CA 89 ") - (data "F9 7B 21 66 6C 86 31 43 9C 59 8D E9 15 11 FD 44 C4 BF AD C7 2F 17 EB D1 CB 61 90 D1 95 E7 7A F9 ") - (data "E3 6F 74 4C C8 FB BB 86 1C 0D F1 EE 4D E3 1B F4 02 EC 4E BB C1 26 11 69 A4 5A 1E 1F 9D DD 7B 31 ") - (data "F0 D5 D7 AF 7F 9D 74 E1 BD 24 88 B8 AF 71 78 62 3B 03 CD 06 9B 3B E7 C9 53 C7 63 FF F7 A7 17 53 ") - (data "A4 16 DF A2 EB F6 FA 3B 37 D8 3C 36 61 29 0F E5 EF 8A 39 39 45 BD 88 76 09 C1 FD 2E 3E 98 BA CA ") - (data "06 9B 51 2A 10 38 FE E1 85 87 78 56 C4 D9 EB BD 7F 8F 6B EC 75 E2 BA 87 47 38 03 E1 4D 28 76 66 ") - (data "59 85 0E 19 31 2A 59 2B 85 5A DD 72 B2 6F 92 54 0B 34 3E 70 C5 88 69 1C D0 EF 34 7C EA 0D 36 1F ") - (data "1B 45 36 79 54 BB 5E 10 14 F8 18 09 05 B2 4E 2A 6D 9A 45 42 59 58 1C 9E 98 F5 17 00 22 BC 7B B8 ") - (data "58 AB 5B 35 A5 C1 E6 D3 A3 F8 BA 5D AA CF 53 5A 3D 35 56 0E 36 56 BA DA 71 9E 33 00 15 08 9C 38 ") - (data "41 C0 05 FA 33 A9 F7 C7 AC DE FB D4 AF 71 E3 1F C4 F8 39 AE B9 66 84 E7 44 FC DB 7A F4 BD D6 03 ") - (data "06 A0 A8 82 85 39 0B 23 E9 C6 2E ED 9A C6 01 FD 89 F0 94 1B 6C 3E 4E D4 7D EF CC F8 48 84 77 FB ") - (data "FF E9 2C B4 44 78 1E 57 43 E7 F4 D1 2B A5 0F 24 4F D0 AA 3B DD F8 89 59 3B 9B E6 66 BF 5B BD 6E ") - (data "80 BF 34 D8 7C 5A E8 37 05 A6 EB 24 91 A0 F3 3C A5 59 53 E6 F3 F9 B8 E0 44 81 A3 CD E9 95 F5 A2 ") - (data "AA 82 B0 E5 C3 15 80 2B 1E 39 A6 07 CF 61 70 87 0C DF 01 53 1B 7B CD 3E 7D 78 33 9D F3 17 51 B0 ") - (data "50 CF 07 7D 78 22 D5 0C 34 7E E0 9A 0A CF E2 28 BE BF 88 89 F0 24 82 0A A3 C4 37 8D AB 0C 8D 06 ") - (data "9B 3C 98 CF 1F 2E 70 C1 B3 C4 FF 51 3D 0F 33 2E 4D D3 AC C0 4D A5 53 99 35 99 D0 7A A3 53 91 F9 ") - (data "26 5D 0C 68 35 D8 D4 F9 7B DC F5 FA FB 7F D1 68 88 08 3D 8B 91 8E 70 2E AF 81 E5 21 4E A9 C1 66 ") - (data "16 C2 4C CD 49 11 E7 D2 EF 11 97 56 38 52 39 09 40 C9 ED 17 16 FE 7B AB 78 CE 14 8E 27 54 CB 17 ") - (data "38 31 16 0F 94 9C 22 1E 8A 9D 31 F6 CC D5 9B AC AB 8C 41 C7 4E CC DF EF 54 0B 16 EA 35 D8 8C 7D ") - (data "30 94 7F F8 FB AE A9 08 95 88 8E 13 0B 2A BC 47 37 3D 53 15 CB B2 3A CC 35 33 49 3C 15 D5 60 33 ") - (data "28 14 67 BD 57 6D 94 07 E0 AC D1 68 0C A0 D9 58 36 03 2F 4C D3 34 8B 11 52 BA 15 91 93 AD 37 19 ") - (data "1A 6C 1E 42 F9 F7 47 84 77 87 C4 A9 4E 50 7C 59 0D 36 AB 6E 7C 78 5A 0D 36 01 68 0A D5 A0 5A 78 ") - (data "7E C2 A6 B5 CA 3D E2 82 A6 C0 EE 30 E5 28 47 F1 5C 13 95 E3 C2 2E E3 85 08 9C AA 9F B3 28 D5 F5 ") - (data "A2 3A 11 A8 37 59 64 CD A8 4A 28 58 A8 73 3E 65 61 11 17 F7 A2 1E 18 F8 D0 35 05 64 EA 34 9C 79 ") - (data "27 55 55 50 A1 6E 96 17 33 E9 BB 27 53 08 5C 40 F4 27 91 9F B8 C8 16 59 13 68 B5 5A 0D A0 15 93 ") - (data "45 3F ED 37 CB 2B 62 1C FB 34 1A 8D DC F7 37 74 A9 29 3F A7 CC B8 75 DD D4 85 40 C3 85 73 78 62 ") - (data "D6 70 17 3D 70 4D 6D CF AD 1E E0 5F 52 83 CD C4 40 EC 32 38 95 06 9B 1B 32 D4 C2 CA FD 4C B7 5A ") - (data "AD B6 42 1B 9D 1D 88 78 90 7E 8C 5E 83 CD 34 C2 CD 49 5A 5C AB 12 55 3F 67 51 8E 26 70 18 FE E3 ") - (data "0B 24 2D 24 FE 46 AF C1 E6 A1 D7 D4 45 80 7F 70 A7 AE 99 45 92 77 22 AC 24 A8 D0 F7 F5 8A 70 11 ") - (data "E1 75 B6 85 FE 21 AD 56 AB 6D 59 CF 26 5B 93 6E B2 D8 2A B2 D1 60 D0 84 15 5A 41 81 9E E7 0F 74 ") - (data "8E 0F D0 4D 0A 30 FA FA D7 D8 62 59 56 5F DF 44 AE 72 4D F5 78 B0 E4 E7 5E 65 01 3E 9C F9 A5 DB ") - (data "A2 A3 9C 06 9B D5 BB 7F 74 9E FB 32 AA 06 EF 93 C1 42 74 66 59 56 3F EB F5 4C D3 34 3D CF 1F 43 ") - (data "AB E4 02 5D A7 89 76 BD 84 11 9D EF BD 88 60 E3 E3 B6 B7 28 55 E0 F0 C8 89 F5 C5 3F B6 1E 54 49 ") - (data "59 57 9A 0D 43 75 1B 6C C6 1D 91 F8 E0 10 E1 5D C2 04 5D 61 26 43 35 41 85 59 CC A0 9E C7 C3 AC ") - (data "D7 03 82 09 CB B6 ED 81 E7 F9 FF 89 C6 75 A4 97 AC 57 B7 22 A8 EC DE 97 CB E5 15 F4 32 EB DE E8 ") - (data "06 B9 EA BB 29 F9 95 6D DB 99 76 BC C1 22 42 BF 6A 5D 8D F1 51 65 C1 D2 6D B0 19 4F DA 02 CC EF ") - (data "8B F8 FD 41 BB C1 A6 1A C7 68 7C A8 97 35 56 55 DC 86 EE 02 4C 57 A1 05 5C 0B D3 34 CD 46 A3 39 ") - (data "81 76 63 CD C3 9B D4 28 3A 56 72 1D 51 17 3C BF F9 04 CA 71 9E B3 2D A5 C6 E0 AC B1 EE 3C A2 DA ") - (data "6B 69 38 31 7F 57 8E BF D1 F3 FF 27 3F 18 AE FB 57 DC 78 D2 CF AC 51 55 F8 40 A1 41 65 AA 0C 2A ") - (data "74 5D 77 AA D1 2C 2E 84 5F 9D 9F DB E3 F5 7A D9 D7 89 17 31 4D D3 6C 36 9B 97 CC B8 64 7E B8 73 ") - (data "4A 4A A9 2F 63 F7 BE 58 2C 16 B6 6D 5F E9 58 3C 42 B3 B7 A3 7A FC 6A B5 1A 37 1A 4D 5D D1 31 B4 ") - (data "2C CB D1 B1 00 5A 96 75 A5 11 53 B4 B9 CE ED A6 FD 48 12 3A D5 90 D3 26 E6 B0 C5 45 C6 58 26 1D ") - (data "D1 5F 4E 83 CD AA 1B 1F 9E 52 83 CD 5D FC 21 10 1B 27 7A 88 B3 46 A3 39 31 4D D3 51 9D 33 CE CF ") - (data "5B 0E 91 AE E5 06 60 A6 9F BF 7E 9D 2B FC 76 B2 35 D8 54 43 FB FE EC BE FB 08 0D 36 A3 3C A9 2C ") - (data "AA 32 09 33 B1 1E BE A0 61 E1 D0 CB 9C 28 33 B5 AE 9A 89 B0 EA A0 42 22 1E EB 2E 8E 44 78 DD 68 ") - (data "34 67 E7 E7 CF 06 F5 3A 8D E3 DC 7F A1 A8 71 C2 DA 15 DD 43 C2 26 24 71 C7 AD D9 95 5B 79 F7 1E ") - (data "06 05 5E 42 79 12 E5 57 3A 99 64 61 19 F7 0F D0 CB 68 3A 03 E8 4F DB B6 DF C5 C5 A2 6C 08 5C 52 ") - (data "34 00 74 04 2A 00 E0 8E 88 BB 2A F7 49 27 C0 1F 25 FE FE 34 5B 74 28 8D 43 57 40 18 86 EF D8 B6 ") - (data "ED E8 BC 27 0E 66 9E A5 B9 51 74 BB D1 37 1A DF 8C 2D EB 59 DE A1 01 08 EA BA C4 55 6B 0E 85 FB ") - (data "15 F4 C4 C7 8B 7A BD 39 B5 2C 6B 90 F4 B9 03 61 C3 03 C0 CF 22 10 3E 1C 8A 9F 8C 41 E9 BB CF 62 ") - (data "4D 71 5D 77 78 7E 6E 0F F4 36 8E 5B 8E D1 60 33 8A 08 1C 55 0A 88 BF D1 B0 9C 94 16 00 A8 9B C1 ") - (data "93 B6 00 06 EE 84 C3 B1 0F CC 7E 5B 7D 64 B8 B3 AC 67 07 AF 45 C4 93 B4 05 12 00 6A B5 DA 95 E7 ") - (data "F9 5A 02 27 E4 8C 88 7F F1 3C FE 25 B0 02 ED F6 52 62 E6 36 11 9E AB 89 D3 D4 22 5A A5 64 AF 65 ") - (data "B1 E2 84 A9 A7 6D D5 A3 75 CA B8 47 61 C6 5B CB B2 2F 01 8C 89 30 DB 88 E6 50 F0 B7 11 04 6F 9E ") - (data "65 6B B5 C1 97 EA BF 15 75 CB 49 59 16 04 D3 34 CD B2 1A 6C EA 08 88 E2 52 80 01 22 7A A7 70 45 ") - (data "47 EF AC 5A AD 5D 12 F1 7D 63 10 F7 5A B6 DF 4D 50 57 0A A0 5F C3 C5 7F 42 84 D9 E6 35 66 B4 03 ") - (data "11 9B B9 15 CB 8D EB CE FB 2A 07 E6 6D B0 A9 42 8E 94 F1 A3 17 6D 15 81 A3 40 11 F5 6F 02 D4 16 ") - (data "B7 72 2B 78 16 DB 60 93 99 BA 44 87 27 23 CD 05 EB 2C 6E 52 F3 FD B4 0A 9E 01 19 D2 A6 1F 10 4C ") - (data "5C FC 7C EF 6F 1A EF 4F 8E 1D 28 63 F7 BE 41 D7 8A 43 84 E7 96 65 F5 D3 33 8F 02 BE 7C F9 32 B3 ") - (data "6D FB 5D C6 C9 EE 0C C0 1B 66 80 C8 7F 0B 00 3A 8D 0E 0F C3 3F AA 8E 3D 44 F5 D9 2F 6D 62 D6 69 ") - (data "88 78 EA 0D 36 23 A8 3C A7 5A 16 A6 22 49 DB A4 2D 97 CB AB 7A BD D9 CF 62 A5 08 DF F3 66 FF 3B ") - (data "CD D1 17 EF 66 B5 5A 3A AA 07 E7 6D B0 A9 F8 BE AC 29 E3 47 8F B3 7D F4 02 67 35 FA CE 31 C0 1D ") - (data "1F 64 12 B8 0D 83 DB F7 2F FA B4 60 D0 D4 00 2F 3C F0 24 47 60 B3 13 F3 77 E5 F8 1B 9D D8 8B 3C ") - (data "71 2F E9 E8 4C 84 4A 99 0C A5 4F 5C 3A 01 C4 AB D5 6A 50 AF 37 B5 7A BC 14 49 D2 24 52 76 4D A0 ") - (data "6C BB 51 BA 32 4D 73 AC BA A0 CF E7 F3 81 65 D9 5D 68 07 4B 16 CA 5D 68 B9 19 AA BE A1 8A 9D AE ") - (data "0A A7 D0 60 B3 68 D2 16 CE 23 34 96 8D 90 BE 49 0B DC AF 56 37 4C 72 38 66 53 D9 0F AB D5 F2 52 ") - (data "53 5C 97 2E DA 33 BA A7 71 AC 0E E2 51 1E AD C0 59 8D BE 1B 10 F1 25 C0 67 0C E0 BE 63 79 34 4E ") - (data "86 00 02 BF 66 00 06 08 EB D1 CB 0F 35 34 2E C3 22 80 CA 14 11 7F A3 63 42 2E 39 30 4B A3 0E 48 ") - (data "B2 35 A2 AA 89 4B C7 5D 77 CC C9 2A AD A5 85 4E 83 CD AC FD 5B 32 EC 46 CF 9A CD E6 25 80 81 EA ") - (data "35 56 AB A5 93 2D 23 24 3F CC B8 25 E2 AE AE 0B 57 67 A7 5B EE C4 6C 74 D4 3B 30 AB 37 D8 3C 9E ") - (data "80 48 5F 38 35 63 9F 0A 45 35 EE C4 75 DD A9 65 59 97 BA D9 7B 45 11 14 84 4C 77 C3 EF A3 11 F6 ") - (data "90 4B B4 33 1B 43 22 3D F7 F4 B1 1A 6C 46 29 35 4D BC 8E F5 AC AC 73 13 F1 5B E8 2E 60 84 37 5E ") - (data "7C 37 F0 78 0A 88 BF D1 89 BD 28 AB 82 A7 58 EE 4E 58 00 00 12 73 49 44 41 54 6E A7 E1 B4 9D 59 ") - (data "35 1D B1 F5 23 FF 83 C5 8F 1D 64 68 4A 9A 87 B4 D4 7E CD 06 9B 99 26 A4 A0 2E 4E 7A 61 B0 28 61 ") - (data "0B 07 E5 D4 D7 C5 62 B1 08 CD E8 37 9A C3 CB 09 BF 5F AF 97 9D 8C F1 69 CA CF 6A B9 13 F3 71 1B ") - (data "6C 96 C0 49 58 79 13 50 7E 56 5C D7 1D 12 A1 87 0A E7 0D 66 DC 32 1B 3F 64 11 37 E1 19 0A 69 B0 ") - (data "99 46 B8 26 E9 FC DE 4F A2 13 7C A9 02 87 7A 7F CC E2 5E 5B 8E 2E 72 3D F4 CC FC 1E 1A 0F 22 11 ") - (data "6E 98 E9 87 7A EF DF 4A F1 1C 1B 8A AA 7F C3 5C 54 FD 8D EC 14 DD 60 B3 8A 8E D8 59 EB 28 B8 AE ") - (data "3B AD D5 8C 4E 15 85 A6 02 AB 02 DE D5 6A F1 C1 8C 01 D5 D4 04 72 5D 77 A8 D9 2C EF 2C CC 24 51 ") - (data "66 2B 72 F8 BD DE E8 B2 40 D7 CC C6 0F AE EB EA 9A EF EF D1 A8 11 53 DA C4 7C 0A 0D 36 8B 47 E5 ") - (data "F7 A9 F3 DC 17 8B 6E DC C9 7C 3E 1F 57 34 6F DC 11 E1 DD D7 AF F3 76 D6 0D AD E6 F3 54 80 DB 55 ") - (data "BD F0 DF A9 74 82 3F 9A 8B 8A 60 68 17 4B 8A D2 E8 7D BE 04 70 B9 1A 7D E7 10 FC 36 C3 68 3F BC ") - (data "86 3F 63 18 B3 3A EA 53 EA EA B9 A5 22 38 31 7F 57 8E BF 29 A2 C1 66 41 68 B8 A7 54 1E D0 F2 27 ") - (data "AE 3C EE BA 70 A1 72 36 29 C8 C5 C7 E5 D0 35 E0 0F D3 FB C4 DC 53 59 9F A0 C0 8A A3 65 6E 7F D3 ") - (data "6A B5 E2 FA 96 1D 24 14 1B 97 E7 E7 AD 71 70 BD E2 32 5F 02 E8 3A 48 F1 FD 4B 6B 53 72 18 B5 B1 ") - (data "95 39 31 9F 42 83 CD 12 50 99 AF 8E 15 AF 95 29 EE A4 CC 79 83 19 B7 86 81 E1 72 B9 2C A0 E9 AD ") - (data "7A 83 CD 22 B2 72 5D D7 1D 5A 96 AD 98 52 7F 1A 9D E0 1F 6D 0C CE 86 AC 7D A5 54 29 22 FE 46 C7 ") - (data "95 53 6E 05 4F 1D FF BF 92 E5 A4 F4 89 AB 88 3A 0A 61 30 EA D0 B6 ED AE EF A3 1F 56 B3 CD 14 9F ") - (data "C3 8C 8F 00 4D 92 6A E6 1C A2 A8 06 9B 1A EF D7 AE 5F 11 B6 70 E8 EB 5E 2B DC 81 3A 61 20 7D 3F ") - (data "C8 AC CB BC 28 DC 30 D3 50 F7 FE 26 11 8C 4B 4D 30 84 05 D9 4A 44 55 B8 A4 75 8F DE 39 E7 02 C0 ") - (data "51 4A E2 BB 6E 72 21 3A 9D 7B 5F 34 79 AB E8 6E E6 8D B0 50 5F 3F CC 80 CC F2 5C DF 84 F3 E9 F0 ") - (data "EB D7 E2 CA 7F 18 06 9B CC 2A F7 B6 B8 4D 73 28 F8 BA 69 C7 1D B3 C1 66 94 D2 23 BF BC 8F 2F A7 ") - (data "CC 0F 17 42 62 FC 5C EB 7D D2 32 8B 1F 83 F5 F8 E5 41 45 F0 58 C6 2F 1C 26 10 1C DC 31 0C 36 83 ") - (data "CE CE F4 C0 A2 C8 CC 0B C3 C0 34 E8 73 45 D3 0A BA 1B 3F 19 5A AD 56 3B 14 F6 9D A0 D6 0D B5 F7 ") - (data "8F 91 FB 2B 3C 36 5A AD 56 7B BD 46 7B D3 F7 8B 99 CD 60 E3 08 00 3C DB D4 C3 61 E6 19 73 6D 26 ") - (data "CF F4 71 29 DD 82 C3 E0 C5 21 1D E5 E3 E1 82 72 6A 14 57 FF 46 38 35 C2 89 67 72 E4 61 3C 59 42 ") - (data "EB CB 0C 40 C9 16 11 41 A8 8E C8 73 3D 39 EA 40 04 25 CA EF 26 EE EF 56 85 DD 40 5A 05 E7 8E 86 ") - (data "13 F3 77 E5 F8 1B 41 10 04 41 10 AA A7 74 81 C3 88 11 38 86 7A 89 F8 63 41 A1 19 F2 01 27 12 21 ") - (data "2E 08 82 20 08 C2 61 4A 17 38 14 D3 21 FA 50 5C CE C9 51 40 FD 1B 41 10 04 41 10 AA A7 74 81 53 ") - (data "C3 2A D6 95 93 54 63 E6 D8 14 55 FF 46 10 04 41 10 84 EA 29 DF 82 13 14 FB 3B 58 90 CF 38 ED 38 ") - (data "1C 27 E6 EF 12 7F 23 08 82 20 08 27 4E 35 75 70 88 A7 87 DC 3D 1C 88 88 D2 52 AD 43 2B 8C 43 E0 ") - (data "0E 0C 36 01 80 7D 63 D2 E8 FD 3E 48 7B 6F 11 F5 6F 4E 05 D3 34 CD 7A FD FF ED 88 C9 7A 1D B3 53 ") - (data "28 A5 AD CA E6 33 10 79 6D 22 6A FB BE 31 21 F2 16 45 14 B0 7A 0C 1C FA 0E 81 FC 6D 3D 2C CB EA ") - (data "30 D7 CC 6D CA 7C 50 58 71 BD FE EF B4 AC 8E DA 82 20 08 55 50 49 07 B4 B0 31 E6 A1 0E C7 77 F5 ") - (data "EE A7 42 D3 C5 D7 A3 EF BB 80 DF 45 50 8C E8 60 31 B7 1A 37 FE 91 D6 70 B3 CC FA 37 E7 E7 F6 2C ") - (data "AE 60 54 58 62 7F 6A 18 18 CE E7 F3 5C 29 B6 61 71 B9 4B 22 BC 8E BB 16 11 0F 74 BA 32 6F B0 2C ") - (data "EB 0A A0 9F 92 8F A2 6B 66 8C D7 EB FF 0D B3 2E 96 69 9F 01 41 C9 F3 2B D5 5E 2E A6 69 9A 8D 46 ") - (data "F3 FF B2 8C 65 0B FF 18 77 CF 2C CB 5E 20 BE 88 E0 9D EB CE 95 9F F7 40 D4 7C D3 27 E2 3E 92 8B ") - (data "2A 7E 60 36 86 AA 62 C7 34 4D B3 D9 6C 5E 86 45 0F 93 0A 97 DD 30 D3 30 CF F7 27 08 82 70 2C AA ") - (data "12 38 0E 11 FF 76 E8 35 9F F9 5F 45 B8 7C D6 A3 8B 3E 88 06 40 72 A5 49 15 81 52 E6 78 C3 B6 0D ") - (data "FF 51 3B 9A AE 5D F7 2F 47 F7 1A C1 22 FE CD 58 A3 74 FE 07 D7 9D F7 75 AE 61 59 F6 14 EA 95 8C ") - (data "6F 56 AB A5 A3 B3 48 06 8B 7B 73 98 20 6C 32 5D 23 AC 4A 7A F0 BB 55 87 FF 75 C8 72 94 FE DD AA ") - (data "7F 9F 61 D5 E5 2B 9D CA A9 CC F4 F3 D7 AF 7F 25 3E DB 81 C5 86 C6 7A 15 59 F9 BD EB BA 97 EA C7 ") - (data "0B 82 20 1C 9F 4A 5C 54 8D DE EF 93 F5 F8 E5 C1 D7 08 46 17 39 1A 81 85 62 64 88 14 61 03 E0 96 ") - (data "99 FA 75 B5 D6 0E 4E CC DF 73 C7 DF EC B6 6D A0 EB FD 72 E2 BB BB 6A 7E 65 DB F6 40 A7 D3 6C 58 ") - (data "1A 7D 02 F0 19 B0 B1 08 D1 55 B4 F4 7D B8 C8 0D 22 E2 E1 8D 65 59 0B CD 45 EC C5 F6 FC 46 7F F3 ") - (data "C7 6D 85 4F 74 B1 15 40 2F EA F5 6F FA 50 74 47 1E 58 84 EF 98 69 B0 FF 19 00 BA 04 F0 66 73 8D ") - (data "46 A3 31 00 90 FA 19 88 F0 EE D0 DF F7 EE FD 7B 22 3A 28 96 E6 F3 C3 6E B1 70 6C 04 EC 5A E9 5C ") - (data "77 AE B5 91 08 7A E0 E0 57 BA 7F 57 D0 93 69 B9 5C 4E 36 02 EE FC BC E5 18 86 EF 44 C7 4C E4 27 ") - (data "8A BB CD B3 41 84 CD B3 F1 71 DF 52 18 88 34 CF 09 BE D3 7B 81 FC B7 70 03 0A 82 F0 B4 A8 C4 82 ") - (data "03 00 EB 8F 17 93 43 71 38 44 B8 A9 BD FE 94 29 D8 38 B4 DA 24 37 14 24 BE 86 8F 61 BD F7 79 A8 ") - (data "7C DE 98 B1 82 F1 B1 DE FB 94 DA 87 23 89 A8 6B 87 08 BD 43 6E 28 CB B2 87 B8 5F B8 D5 77 FD A1 ") - (data "D5 63 1A 11 06 89 56 0D DB B6 07 CC B8 77 1D AE 56 CB 7F A8 58 59 F6 AC 20 B1 D6 9F E8 E7 60 C6 ") - (data "C7 AF 5F E7 A9 F7 2E 74 21 4D B0 15 47 37 B5 9A D1 8D 8B 17 B2 2C AB 1F 6D 2A 59 AB 19 FF CC 1A ") - (data "5B 14 71 2F 69 B9 92 F6 D9 B5 E4 E8 59 E1 F6 3F 8F 8A F5 64 FB 3D 1E B6 2C 6D CF FD 6C B2 11 2D ") - (data "2A D6 9E F0 7B BE 02 B8 FF 77 89 75 12 04 E1 E9 50 7E 25 E3 10 F2 E9 60 3C 09 33 5E F0 E8 DB 76 ") - (data "96 73 72 4C 77 6C 22 DC 30 F3 7B 9F F9 5F F5 D7 9F 1D 1D 71 13 9C B8 CC FA 37 DB CE BF CB E5 32 ") - (data "E6 7C D1 B6 F4 EA 1D 9A 43 97 8E 92 B8 01 80 F9 7C 3E 08 63 7E 00 00 8D 46 43 49 BC 19 3B 05 10 ") - (data "E3 53 E6 37 7D 59 82 F7 A8 59 01 EA F5 E6 10 11 71 B3 5A 2D 9D 24 C1 12 C4 C2 6C 1B CE AD D7 9C ") - (data "49 80 86 8D 22 37 96 8D 49 96 73 6C 88 5A E9 74 1A FE 85 16 96 A8 B8 F9 51 C5 AA 36 9F CF 07 44 ") - (data "E8 25 89 90 56 AB D5 8E 3C 4B 37 69 E2 06 08 02 98 5D 77 DE 11 71 23 08 C2 63 A4 B2 6E E2 06 BC ") - (data "B1 87 DA 2F 87 5E F3 51 EB 22 43 36 55 1D FE D5 9A EB D1 05 7C 52 47 7D 4A DD E4 00 E2 24 2A E8 ") - (data "3F 75 BF 78 C7 89 0F E6 9A 49 74 DF 79 FA 46 E5 A4 E1 6E FB 75 F0 7E DC AE D7 6A 31 2F 86 81 E1 ") - (data "C6 8A 43 44 6D 95 6B 05 CD 29 EF FF 19 BB F8 A9 1E B7 21 EB 67 60 C6 98 08 E1 E2 CD 0E B2 65 E6 ") - (data "DD 8B 12 55 31 16 3F 1E 76 22 C6 51 8D 73 19 57 9B 67 2F B0 B0 CC 87 AA EF 4C 0B 48 5F AF D1 8E ") - (data "B8 BC 24 60 58 10 84 27 4F 65 02 87 7A 7F CC BC 8F 2F 6F 0E 56 30 36 D0 47 86 45 29 AC B1 33 C8 ") - (data "3B B6 3D 9C B8 17 F2 C6 DF 84 19 41 9B 7F C6 9E CB 30 7C 87 B7 1A 4B E9 9A 44 3C D8 BE 1F 97 AA ") - (data "01 BD 41 BA B5 FF 36 F8 FF C3 16 B1 87 D7 BA BF 47 77 71 BB FB C0 D5 B2 89 F1 A1 EB F9 FC 2F 85 ") - (data "8C 30 FF DE 5A 41 C4 03 F5 A0 64 9A 6E 84 C1 A1 AE E0 8A E7 70 EE 47 11 A6 4A 67 47 C5 4A B7 4B ") - (data "60 BD D9 B8 8F 70 AB 62 61 C9 0E BF 32 4D D3 94 CC 28 41 10 9E 32 95 09 1C 00 80 8F 21 08 0F AC ") - (data "38 CC 78 B1 1C 5D 74 4E A1 80 5E 6C FD 1B E2 EB 87 7F D4 63 57 B8 1C B6 06 05 01 B6 DB 40 59 66 ") - (data "63 98 76 DE 30 E6 E3 7E 71 74 DD 7C E9 E5 49 44 5D 39 00 66 81 68 8B C2 9D D0 8A 72 2F 6E 56 AB ") - (data "FF 29 C5 DE 44 82 9E EF B2 A4 AE E7 81 19 CE C6 C2 91 B7 B6 0C 14 AC 74 0F A1 88 2B 8A 0A 17 37 ") - (data "F5 3A 66 9E B7 FD 77 A3 D1 9C D9 B6 7D 65 18 C6 F0 31 D5 43 12 04 41 50 A5 52 81 93 E4 A6 32 82 ") - (data "09 BE 5F E5 78 0E 12 13 7F C3 B9 77 F5 00 33 39 1B 4B 43 AD 56 7B 70 BE D0 C2 73 85 7B 01 C1 EF ") - (data "55 16 DB F5 9A BB 9B C5 99 88 B5 C4 8D 61 F8 E6 46 74 29 BA 66 A2 56 9E 17 49 29 D7 CC B8 AD D7 ") - (data "A9 EF BA E9 8B FC 5E FC 4F 66 81 C6 CC DA 56 89 50 5C 85 B1 4B 94 4B C8 AA 5A E9 F6 89 0A AC 7A ") - (data "FD 70 BC 5A 1E BE 7C F9 32 B3 2C EB 7D A4 76 D1 19 33 DE 7A 9E FF F6 FC DC BE 0D C6 4A 13 22 7F ") - (data "22 31 37 82 20 3C 05 2A 0B 32 06 42 97 52 9C 25 84 D0 E5 91 53 68 D1 3F 5D 52 7A 63 4D F2 5F 61 ") - (data "DB 9A C2 F7 FD BE 6D DB 03 DB B6 07 E7 E7 F6 D8 B2 EC 69 28 16 C2 DD BF 7A ED 11 A2 ED 79 89 48 ") - (data "77 9C 9A 19 6C 5B F7 4B EA 91 84 E7 9E E7 4F 6D DB 56 09 FC 8D 8C 43 37 D6 69 FB F9 B3 C4 CF 34 ") - (data "9B 4D 67 FB 2F 3F D7 E2 AE 1A 80 1D 25 2A B0 98 71 5B 96 45 C5 75 DD CB 30 45 7E A7 75 0A 11 9E ") - (data "13 E1 35 11 FF 02 D0 9F E7 E7 F6 4C F1 3B 13 04 41 38 59 2A 15 38 00 02 37 D5 61 CE D6 58 1F B5 ") - (data "98 58 52 6F AC 86 5A FD 9C 58 F6 5C 3B 60 C6 DB CD 7F A1 6B 26 14 36 74 CD 6C FC A0 57 93 86 DA ") - (data "DB F3 F2 4C 67 5C D1 B8 1B 95 D8 13 E6 6D 8C 92 EB CE E9 D0 7F 44 E8 61 1B 1C 7D C6 4C 0A 9F C5 ") - (data "B8 1F 07 73 6D A6 FC 01 B0 2B F0 90 A1 66 4B 10 14 BC 39 97 B6 40 DC 3B D7 56 00 1E B2 D2 1D 22 ") - (data "DA 82 81 88 66 79 AE 9F C6 7C 3E 1F AC 56 CB 36 C0 3F 02 FC FE 90 C5 8A 08 CF 99 31 7A E8 7E 14 ") - (data "04 41 78 3C 54 2E 70 C2 94 ED 83 CD 37 89 F8 F2 98 56 1C 8E 0B 30 2E 20 FE 06 11 0B 45 58 7C EF ") - (data "7A FB DF F6 EF AB D5 FF BA FA 31 20 7C 7F CF 74 DD 0B 91 80 E1 D4 D8 13 55 57 CE 7C 3E 1F AF 56 ") - (data "4B 67 9B 82 CE AF 82 34 65 35 EA F5 6D 7A B9 0A 51 D1 A5 1A D4 BB CB 56 5C 65 7B FF CE 68 36 E7 ") - (data "BA 3B D5 D8 96 C5 62 B1 70 5D 77 E8 BA EE A5 EB FE E5 B8 EE 9C 98 8D 1F 00 7C 88 1E 47 E4 F7 8F ") - (data "33 42 41 10 84 FC 54 6F C1 01 C0 1C 1B 44 79 5C 2B 0E 1D 16 38 45 C4 DF EC BA 76 8C 7E B0 B0 04 ") - (data "FF 6D C4 02 11 9E 87 D5 78 75 51 6D 99 B0 43 98 E9 B4 B1 2A 7D 48 38 14 80 9E 2B 67 B1 58 2C A2 ") - (data "D6 88 F5 1A 6D FD 11 A6 63 DB 76 37 E2 DE F9 98 2D 33 68 9B BD 94 27 B3 A8 C8 5A 3A 55 13 D6 BC ") - (data "E9 07 96 9D 7B C4 4D 25 08 C2 A3 E5 28 02 A7 8E FA 15 4E CC 8A B3 1C 5D EC B8 90 F6 98 E4 3D 7F ") - (data "D4 CA B0 6F 29 A9 D5 A8 8F FB FB 41 3F E9 BB 06 B6 D6 94 70 91 55 1C 13 0D B6 FF 9F 9E AD A5 EF ") - (data "CA 89 C6 06 79 CA C2 41 47 0C 31 47 CB 04 18 DA D9 47 D1 7B 4D 94 EF 7B 66 36 9C ED BF B2 B9 BA ") - (data "98 B9 9D 67 0C 79 A9 3A 7B 4D 10 04 A1 2C 8E 22 70 A8 37 59 9C 9A 15 A7 96 10 3C 9B 37 FE 26 CD ") - (data "B5 F3 E5 CB 97 59 54 6C 00 FE D0 34 CD 4C 22 6F 77 91 8D C7 B2 EC 61 D4 F2 A1 E6 16 53 77 E5 84 ") - (data "C2 E1 BE 1F 56 BA EB 6C 1B 3B 44 E4 29 59 0E C2 56 10 F7 B1 4B 59 D2 BB B3 04 05 C7 B1 1B 0B 44 ") - (data "CA AE C2 F5 FA BF F7 C7 12 E1 B9 8E 3B 2F 4D D0 9A 21 AA E7 8B 5E FB B1 59 A1 04 41 10 A2 1C 45 ") - (data "E0 00 A9 56 9C B7 59 DB 37 64 A5 CC F8 1B 15 D7 4E 50 D8 2D 9B AB 8A 39 9A 56 CD 97 49 0B 9A 69 ") - (data "9A E6 F9 B9 3D C6 B6 49 E5 DD 7A BD EC 2B 5E 49 C9 95 63 59 56 87 C8 BF 1F 53 B4 08 61 C2 B9 27 ") - (data "DB FF A7 7E D2 22 6F 9A A6 B9 DB AF 0B 77 A1 15 4C 9B BD E2 86 39 2B 18 AB C7 33 45 09 EE E5 56 ") - (data "F8 7A 1E 0F D3 DE 63 9A A6 69 DB F6 00 A0 3F 93 8E 6B 36 9B 4E A3 D1 9C A8 5A F6 D6 6B FF 7E E3 ") - (data "61 18 B1 09 01 82 20 08 27 CF D1 04 4E 8A 15 07 9E 91 EE 32 29 94 12 E3 6F 54 5D 3B 59 5D 55 EB ") - (data "F5 FF 86 9B F7 05 E2 A8 39 39 24 10 5A AD 56 BB D1 68 4E A2 05 F5 00 56 6A 87 A0 E2 CA 39 3F 6F ") - (data "39 61 33 D1 09 22 B5 7C 54 DC 1E AE EB 0E 23 7D B1 CE 3C CF 1F 1F FA FC 9B CF 80 88 B8 01 38 B1 ") - (data "5F 55 12 2A 55 99 55 68 B5 5A ED 3C B5 74 76 2D 78 FC CA B2 9E C5 7E 87 96 65 5D 35 1A CD 59 D0 ") - (data "62 23 F5 5A 1D 00 2F 00 FA D3 B2 EC 61 5C FA B7 65 59 1D CB 7A 16 7D 36 3E A4 B5 7F 10 04 41 38 ") - (data "65 2A EB 26 7E 08 1E 39 A6 47 AB 19 62 62 5F 88 F1 73 AD F7 A9 C4 92 F5 01 CB D1 45 C7 A0 C3 3B ") - (data "61 66 FA 21 7F 8A F8 B6 8B 73 5A C7 EE F3 F3 67 97 41 3D 92 FB 7E 4C 1D 15 01 62 DB 76 97 19 A3 ") - (data "BD 3F DF 60 6B 95 08 17 BA 00 66 DC 12 71 57 75 51 8F 8E 4B 83 D8 4E E3 87 08 9B 4D 4E B0 FB 3C ") - (data "DC 6C 7B 27 B1 89 DD 80 EA 3B 80 9D AC C2 24 BC DE 9F 80 7A B7 F3 87 E7 B0 87 41 9A FE 76 6C C1 ") - (data "BD 0D 02 AC F3 75 12 DF 3D D7 E1 C6 AB C9 F5 92 A2 CF DE 2E 51 61 C4 7B F1 67 7A 1D D0 05 41 10 ") - (data "4E 91 A3 59 70 80 C0 8A 03 E6 D8 C9 99 09 83 2A 5C 55 65 C6 DF 04 A8 67 E9 64 75 55 CD E7 F3 31 ") - (data "11 7A D1 EE E0 08 16 DC 37 E1 7F 1B 61 70 07 F0 FB F5 7A A9 D9 25 7A 6B 85 52 E0 43 AD 66 FC 53 ") - (data "47 DC 00 9B 14 77 76 1E 7E 06 7E 15 DE C3 9D CF B0 5A 2D DB 39 AB EE E6 2A 10 18 BA 02 DF EC 8D ") - (data "0D 81 25 87 5F 45 D3 F7 55 70 5D 77 B8 FF 1D 46 CE B5 23 52 98 F1 31 EC 20 9E 18 AF 16 5A 05 3F ") - (data "E0 81 3B 78 73 4E 7E 85 48 AC 54 D0 C1 5C C4 8D 20 08 8F 9F A3 5A 70 36 AC 3F 5E 4C E2 5A 24 10 ") - (data "E1 A6 F6 FA 93 66 B5 5D CD EB 8F 5E 8E B1 35 CD 47 2E CE D7 F5 D7 9F 9D 3C E7 36 4D D3 DC 14 72 ") - (data "23 F2 16 2A 0B 72 F4 3D 80 7E 6F A4 C0 9A C3 4E 34 28 38 8C FD 99 AE 56 AB 71 96 54 E8 A0 47 56 ") - (data "2D 75 C1 2E A0 8F 13 80 E0 33 00 E8 44 0B E7 11 F1 84 99 67 59 3F C3 3E AD 56 AB BD C9 D8 5A AF ") - (data "FF 3B D5 3D E7 FE F7 B4 8F EA F7 7D 88 20 8E 89 0E 59 94 A6 CB E5 72 92 E5 F3 07 2E 3F EE 18 C6 ") - (data "AE F0 F2 7D 5A 48 8B 06 41 10 9E 1A 27 21 70 92 5C 44 00 C0 CC EF 1B BD CF A5 65 56 AD C7 2F 17 ") - (data "38 E0 26 63 A6 77 8D DE EF 83 B2 AE 2B 08 82 20 08 42 39 1C D5 45 B5 A1 D9 FB 3C 65 A6 77 71 AF ") - (data "13 D1 4F EB D1 45 BF 8C 6B 97 5D FF 46 10 04 41 10 84 EA 39 09 81 03 00 8D DE EF 03 A2 FB FE 45 ") - (data "0F 21 BA 0A C5 48 A1 94 1F 7F 23 08 82 20 08 42 D5 9C 8C C0 01 00 C3 F7 BA 88 A9 8D 03 E0 CC 20 ") - (data "9A 14 2D 72 4A EE 3F 25 08 82 20 08 C2 11 38 29 81 43 BD 3F 66 60 A3 9F 70 C8 99 41 34 2E B4 95 ") - (data "43 A9 FD A7 04 41 10 04 41 38 06 27 25 70 00 A0 DE FB F7 38 29 1E 07 C0 73 DF 58 4D 8A 10 39 12 ") - (data "7F 23 08 82 20 08 4F 93 93 13 38 40 10 8F 03 8E EF 6E CD 8C 17 BE B1 CA ED AE 92 F8 1B 41 10 04 ") - (data "41 78 9A 9C A4 C0 01 80 1A 1A 97 49 41 C7 CC 78 91 37 26 47 E2 6F 04 41 10 04 E1 69 72 B2 02 87 ") - (data "7A 93 85 E1 37 9C C4 CC AA 30 F0 78 3D FA 5E BB C4 7E 70 11 89 BF 11 04 41 10 84 A7 C8 C9 0A 1C ") - (data "40 5D E4 80 FC D1 6A F4 DD 40 E7 DC 12 7F 23 08 82 20 08 4F 97 93 16 38 80 B2 C8 01 11 BF 5D 7F ") - (data "BC 98 A8 F6 AE 92 F8 1B 41 10 04 41 78 BA 9C BC C0 01 D4 45 0E 98 5E 79 54 9B 7A A3 97 A9 6D 1D ") - (data "24 FE 46 10 04 41 10 9E 2E 8F 42 E0 00 5B 91 03 C6 C7 94 43 CF 98 F0 CB FA E3 C5 64 35 FA CE 89 ") - (data "3F A1 C4 DF 08 82 20 08 C2 53 E5 24 9A 6D EA B2 1A 5D 5C 11 D1 4F 4A 07 33 3E D4 E0 0D A8 F7 C7 ") - (data "6C F3 A7 A4 E6 9E CC F4 83 B8 A8 04 41 10 04 E1 71 F3 68 2C 38 51 1A BD CF 97 60 A3 87 F8 B6 0E ") - (data "5B 08 6F 3C AA FD 67 3D 7A 39 DC A4 94 13 8C D8 AC 2B 11 37 82 20 08 82 F0 F8 79 94 16 9C 0D 3C ") - (data "FA B6 ED 1B B5 31 33 5E 68 BC ED 16 C0 F3 83 AF 10 5F D7 5F 7F 76 8A 18 9B 20 08 82 20 08 C7 E3 ") - (data "51 5A 70 36 50 EF 8F 59 ED F5 A7 4E 4A 6B 87 7D 0E 8B 1B 48 FC 8D 20 08 82 20 3C 15 1E B5 C0 D9 ") - (data "D0 E8 FD 3E A8 B1 F7 CF 02 32 A0 26 45 8C 47 10 04 41 10 84 E3 F2 A8 5D 54 87 58 8F BE EF 82 FC ") - (data "2B 24 58 6A E2 A8 77 3F 3D B9 FB 21 08 82 20 08 7F 47 9E 84 05 27 4A BD F7 EF 71 BD FB A9 0D E6 ") - (data "1F 11 C4 DB 28 91 5A 63 47 10 04 41 10 84 47 C3 93 13 38 1B EA BD CF C3 7B A1 A3 E0 BA F2 7D 9E ") - (data "54 30 2C 41 10 04 41 10 2A E0 C9 0A 9C 0D F5 DE E7 61 FD F5 67 C7 67 FE 17 18 1F 10 93 5A 4E A8 ") - (data "4D AA 1D 99 20 08 82 20 08 65 F1 B7 8C 39 09 BA 8F FB DD B0 9A F1 73 00 A8 71 E3 1F D4 9B 2C 8E ") - (data "3B 32 41 10 04 41 10 84 02 58 8E 2E 3A BA 9D C8 05 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 ") - (data "41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 ") - (data "04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 ") - (data "10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 41 10 04 ") - (data "41 10 04 41 10 84 0A F8 FF 65 82 93 78 58 28 0B 1C 00 00 00 00 49 45 4E 44 AE 42 60 82 ") - ) - ) - (rect - (name "") - (start 47.739 18.5022) - (end 32.489 12.5022) - ) - (tbtext "DWN: ${DWN}" - (name "") - (pos 39.989 15.5022) - (justify center) - ) - (rect - (name "") - (start 32.489 18.5022) - (end 17.239 12.5022) - ) - (tbtext "CHK: ${CHK}" - (name "") - (pos 24.739 15.5022) - (justify center) - ) - (rect - (name "") - (start 17.239 18.5022) - (end 1.989 12.5022) - ) - (tbtext "APP: ${APP}" - (name "") - (pos 9.489 15.5022) - (justify center) - ) -) diff --git a/tcs_default/meta/icon.png b/tcs_default/meta/icon.png deleted file mode 100644 index ba7cda492682479e49ef2eaf32e11594b3fe0e76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2908 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 + + + +HFS Default + + +HFS default project. + + diff --git a/melon.kicad_wks b/templates/melon.kicad_wks similarity index 100% rename from melon.kicad_wks rename to templates/melon.kicad_wks diff --git a/micromelon_default/meta/icon.png b/templates/micromelon_default/meta/icon.png similarity index 100% rename from micromelon_default/meta/icon.png rename to templates/micromelon_default/meta/icon.png diff --git a/micromelon_default/meta/info.html b/templates/micromelon_default/meta/info.html similarity index 100% rename from micromelon_default/meta/info.html rename to templates/micromelon_default/meta/info.html diff --git a/templates/micromelon_default/micromelon_default.kicad_pcb b/templates/micromelon_default/micromelon_default.kicad_pcb new file mode 100644 index 0000000..208c1d4 --- /dev/null +++ b/templates/micromelon_default/micromelon_default.kicad_pcb @@ -0,0 +1,90 @@ +(kicad_pcb (version 20221018) (generator pcbnew) + + (general + (thickness 1.6) + ) + + (paper "A4") + (title_block + (title "${title}") + (date "${date}") + (rev "${rev}") + (company "Micromelon Robotics") + ) + + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + (50 "User.1" user) + (51 "User.2" user) + (52 "User.3" user) + (53 "User.4" user) + (54 "User.5" user) + (55 "User.6" user) + (56 "User.7" user) + (57 "User.8" user) + (58 "User.9" user) + ) + + (setup + (pad_to_mask_clearance 0) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (plot_on_all_layers_selection 0x0000000_00000000) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (dashed_line_dash_ratio 12.000000) + (dashed_line_gap_ratio 3.000000) + (svgprecision 4) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (dxfpolygonmode true) + (dxfimperialunits true) + (dxfusepcbnewfont true) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (sketchpadsonfab false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + + (property "rev" "") + (property "title" "") + + (net 0 "") + +) diff --git a/micromelon_default/micromelon_default.kicad_pro b/templates/micromelon_default/micromelon_default.kicad_pro similarity index 98% rename from micromelon_default/micromelon_default.kicad_pro rename to templates/micromelon_default/micromelon_default.kicad_pro index bd315f1..6cae8e3 100644 --- a/micromelon_default/micromelon_default.kicad_pro +++ b/templates/micromelon_default/micromelon_default.kicad_pro @@ -431,7 +431,7 @@ "step": "", "vrml": "" }, - "page_layout_descr_file": "${KICAD_USER_TEMPLATE_DIR}/melon.kicad_wks" + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks" }, "schematic": { "annotate_start_num": 0, @@ -457,7 +457,7 @@ "version": 1 }, "net_format_name": "", - "page_layout_descr_file": "${KICAD_USER_TEMPLATE_DIR}/melon.kicad_wks", + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks", "plot_directory": "", "spice_current_sheet_as_root": false, "spice_external_command": "spice \"%I\"", diff --git a/templates/micromelon_default/micromelon_default.kicad_sch b/templates/micromelon_default/micromelon_default.kicad_sch new file mode 100644 index 0000000..cb424c5 --- /dev/null +++ b/templates/micromelon_default/micromelon_default.kicad_sch @@ -0,0 +1,21 @@ +(kicad_sch (version 20230121) (generator eeschema) + + (uuid 2a512e6e-fb04-4deb-bd23-d310e8f9b83d) + + (paper "A4") + + (title_block + (title "${title}") + (date "${date}") + (rev "${rev}") + (company "Micromelon Robotics") + ) + + (lib_symbols + ) + + + (sheet_instances + (path "/" (page "1")) + ) +) diff --git a/tcs_default/tcs_default_panel.json b/templates/micromelon_default/micromelon_default_panel.json similarity index 100% rename from tcs_default/tcs_default_panel.json rename to templates/micromelon_default/micromelon_default_panel.json diff --git a/templates/tcs.kicad_wks b/templates/tcs.kicad_wks new file mode 100644 index 0000000..cae275b --- /dev/null +++ b/templates/tcs.kicad_wks @@ -0,0 +1,453 @@ +(kicad_wks + (version 20231118) + (generator "pl_editor") + (generator_version "8.0") + (setup + (textsize 1.5 1.5) + (linewidth 0.15) + (textlinewidth 0.15) + (left_margin 10) + (right_margin 10) + (top_margin 10) + (bottom_margin 10) + ) + (rect + (name "") + (start 110 34) + (end 2 2) + (comment "rect around the title block") + ) + (rect + (name "") + (start 0 0 ltcorner) + (end 0 0) + (repeat 2) + (incrx 2) + (incry 2) + ) + (line + (name "") + (start 50 2 ltcorner) + (end 50 0 ltcorner) + (repeat 30) + (incrx 50) + ) + (tbtext "1" + (name "") + (pos 25 1 ltcorner) + (font + (size 1.3 1.3) + ) + (repeat 100) + (incrx 50) + ) + (line + (name "") + (start 50 2 lbcorner) + (end 50 0 lbcorner) + (repeat 30) + (incrx 50) + ) + (tbtext "1" + (name "") + (pos 25 1 lbcorner) + (font + (size 1.3 1.3) + ) + (repeat 100) + (incrx 50) + ) + (line + (name "") + (start 0 50 ltcorner) + (end 2 50 ltcorner) + (repeat 30) + (incry 50) + ) + (tbtext "A" + (name "") + (pos 1 25 ltcorner) + (font + (size 1.3 1.3) + ) + (justify center) + (repeat 100) + (incry 50) + ) + (line + (name "") + (start 0 50 rtcorner) + (end 2 50 rtcorner) + (repeat 30) + (incry 50) + ) + (tbtext "A" + (name "") + (pos 1 25 rtcorner) + (font + (size 1.3 1.3) + ) + (justify center) + (repeat 100) + (incry 50) + ) + (tbtext "Date: ${ISSUE_DATE}" + (name "") + (pos 87 6.9) + ) + (line + (name "") + (start 110 5.5) + (end 2 5.5) + ) + (tbtext "${KICAD_VERSION}" + (name "") + (pos 109 4.1) + (comment "Kicad version") + ) + (line + (name "") + (start 110 8.5) + (end 2 8.5) + ) + (tbtext "Rev: ${REVISION}" + (name "") + (pos 24 6.9) + (font bold) + ) + (tbtext "Size: ${PAPER}" + (name "") + (pos 109 6.9) + (comment "Paper format name") + ) + (tbtext "Id: ${#}/${##}" + (name "") + (pos 24 4.1) + (comment "Sheet id") + ) + (line + (name "") + (start 110 12.5) + (end 2 12.5) + ) + (tbtext "Title: ${TITLE}" + (name "") + (pos 109 10.7) + (font + (size 2 2) bold italic) + ) + (tbtext "File: ${FILENAME}" + (name "") + (pos 109 14.3) + ) + (line + (name "") + (start 110 18.5) + (end 2 18.5) + ) + (tbtext "Sheet: ${SHEETPATH}" + (name "") + (pos 109 17) + ) + (tbtext "Micromelon Robotics" + (name "") + (pos 109 20) + (font bold) + (comment "Company name") + ) + (tbtext "In association with: Designworks" + (name "") + (pos 109 23) + (comment "Comment 0") + ) + (tbtext "Client: ${client}" + (name "") + (pos 109 26) + (comment "Comment 1") + ) + (tbtext "${COMMENT3}" + (name "") + (pos 109 29) + (comment "Comment 2") + ) + (tbtext "${COMMENT4}" + (name "") + (pos 109 32) + (comment "Comment 3") + ) + (line + (name "") + (start 90 8.5) + (end 90 5.5) + ) + (line + (name "") + (start 26 8.5) + (end 26 2) + ) + (bitmap + (name "") + (pos 28.989 25.3822) + (scale 1) + (data "iVBORw0KGgoAAAANSUhEUgAAAjgAAAChCAYAAADKg8VUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz" + "AAAuGAAALhgBKqonIAAAIABJREFUeJztnV2S2tb29p8lPvLetU5VS+bOnBGYc5dqJ2VlBIYRmIwg" + "nREYjyDtEQSPADyC0HViV+5Cj+DQdw5y1Z++OweQ1nsh0QgaSXvrC7qzflWpihshbYTY+9nrExAE" + "QRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAE" + "QRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAEQRAE" + "QRCEU4SOPYDHAo++ba9RbwNwAIAM39m+SK8OvOUOxFMAgE8LBk0N8MIHTeuoT6k3WZQ+aEEQBEH4" + "myICJ4bl6KJDMLpk+A6YOgDOCr7ELTOPG73PlwWfVxAEQRD+9ojAibAefd8F/C4IXRQvaA7iM/+r" + "2fs8reJagiAIgvB3oX7sARyb1eg7h8D9QNT4lYiaKA344qoSBEEQhIL5WwocHjmmh2UXRAOAnx9x" + "KLfU+2N2xOsLgiAIwpPkbyVweOSYa6wvPVpdAlS5tebhgDA59hAEQRAE4SnytxA4UWFD+WNrbkE8" + "Y9+YAADBnzGM2f5BBDIZ3DEM7jLjRczIJjnHIgiCIAjCAZ68wFmPLvoerQYEZHNFEV+HYmbS6P0+" + "0Xz32Bu9XIDwy6EXa/B1zycIgiAIggJPVuAsRxcdw8BVTI2aJO7AGAPGuIbahLr56tUw0Il5SeJv" + "BEEQBKEknqTAWY2+GxDxW7DGm4iv4WNY730eFjoYCgoDPkDibwRBEAShNJ6UwOHRt23fqI2ZOSbm" + "5QF3YIxr8AbULd6awqNv216sa0zibwRBEAShLJ6MwAlibegKrBREfMdMV3XUr8psmeDBcOJek/gb" + "QRAEQSiPJyFwVqOLKxD9pHQw40MNjctqekGRE/OCxN8IgiAIQok8aoHDI8f0jOVYKZCY+Nr3cVlp" + "WwSJvxEEQRCEo/BoBU4Qb7Magykt3uaOGINa9/NVJQMLCaolryT+RhAEQRCOwKMUOMvRRccjmqTF" + "2xDhxvC97jHcQR6W3bhephJ/IwiCIAjl8ugEznJ00TGIJkipSMzM7+vdz5fVjOrA9YFOTKt2ib8R" + "BEEQhJJ5VAJHUdzcgY1+o/fvcUXDOohhkMOH6vBI/I0gCIIglM6jETiK4ubWZ+42e/+uLpD4ADxy" + "TI9X0n9KEARBEI7EoxA4KuImiLdpOPVK0r+T8eA5ca9J/I0gCIIglI9x7AGkwSPHrBk0hIK4qaa2" + "TTocL3Ak/kYQBEEQKuDkBY5vrCbMiE0FPzVxAwTxNwdfkPgbQRAEQaiEkxY469HL4WMTNzxyzPgx" + "S/yNIAiCIFTByQocb/TyEoQ3ca+forgBJP5GEARBEE6BkxQ4y9FFhwm/xL1+quIGkPgbQRAEQTgF" + "Tk7g8MgxDaKkGjZ3ns/9vOKGR9+2vdHLwgsBSvyNIAiCIByfkxM4HlZDADE9nABm6uZtmBm0eqj9" + "hwm/eB9fTnnkmHnOdz82ib8RBEEQhJPgpATOevR9F4TXca8T4+dG7/dJ3us00Jxt/p8ZL3xjNSlC" + "5Ej8jSAIgiCcBicjcHjkmCB/GH8APtZ6nwrpCE69yQLE1/enDkVO3vNK/I0gCIIgnAYnI3A8rK4Q" + "X8zvroZGv8jrsW8Mdv7NeLEaXeQSUBJ/IwiCIAinQUzD62pZjb5ziPi3uNeZ6YciXFP7rD9eTMD0" + "avdiRq+eoVEnjxzTo9X/HX6Rf6z3Pg8zDVI4KpZldZhrJsAdw+AHbkzfNyYAsF7/d7pYLE4uq++U" + "2dxbw/CduGOYecZcm339+mVS3cgEIRuWZXWIqA2gAwDMu5teZl4YBqa+TwuApjJvlMtJCBzv48tp" + "XHAuM79v9D4Xnu0ExAqr2xo3OrpZWkH8kD869FqNvX+quKgsy+qHPw5lDMMYfvnyJfXcCtfuEFFX" + "9XjfR4eITNf9y0k6zrbtLjOV8v1FRjN1XbeQa2zuQzAx8avUN+xyB9CUiCe+b0yyLMrn588uiaD8" + "PSTDMyLMwn9MmXnmuu7RGtG2Wq32es3d4PNp31sAuCHCuKhnfp8s956Ir+bzufaGaJ9Wq9X2PB7q" + "vq9Wo77Kvajmd3gYZoy/fv0r0Tpu2/ZgXwzEQcST+Xw+KGJseTFN02w0Gl1m6hLBQXIz6DhumGlY" + "r9O4jOfasp5N9N6Rbz61LKsPGP30I3nmunOF47Jz9Gab69FFP6Fa8V0dzUFZ1270fp+sRhfviein" + "yJ+fr7G+BKB1XYbn0GG9qBF/Q1fMej8Qz/NmAIY674m5dmLV6AdHEwDwTdpxzOwAyLKYKUNBI9bM" + "mKZpNpvNS99HH8BzZgDgLKc6A/gVM14R+W8ty74DMAb4SlVYEHEfUP8eUnjFOx+DYFn2HTMmRDx2" + "XXdY0HUS2Ux4nue/onxbqhfMeOF5/lvLenbNTIMiLTtZhBczTwHkFjiBuNEX1F++/DVTOZA5s6jM" + "DVG6cAvHp/Tc+35iGZFKOD9vOUR+HwiK0eZ9ron4F8/jXyzL/lCrGYOihM75ecsBfM3vnV61Wq2r" + "7GMw+orPWsbzq3P8GByiQexrzJdlF/Orozkgws5CTcSXullVeeNvWq1WG5nUv9quJwnbtgfItqgq" + "LNr5x5fGxk2kS6vValuWPWw0mv/HjLdE8eUJMnIG4A1Af1rWs0kw2cRjmqaJ4sRN7JiI8BqgXy3L" + "Xti2PQivWziWZfXPz+0ZQL8Wv7jyKyL/N8uyroobf5YxGp28Vz0/f3aZ7dqkY43LPc4cJI5T/7nX" + "+tyFYllWx7KeTYj834D4Svs5eON5/jR4JvKT5P5NwvO8HNdXe5aZy/8ejypw1qOLPuJq3hBfVxG3" + "Qr3JwvC9LoC7yJ/PfKz6qucoov6N58WnmKeQa+IK4iDwNtu7kz9bRQs21uv/av9QbNseeJ4/RTmT" + "1AH4FZCQJQigXv9/VS9CZ8x4W683p5ZlFXbtYBGwpwD9WoJo3IN+ajSak7zjTxOf8eQTboFLlGOr" + "tidBpDa3VPU7jOEuzXrZbDYdnRMeIx7LNE3TsqwrgP6swBJ2RsS/WJY9zHsi38+6PlA/y8ZB53dI" + "VH7plONacBKsN/tZTqUOo/fHzA9cKfcihw1W9sUXVP8m6wT9IusONngfDTNeF7VabZL0ekUL9o1O" + "kF5otZmGoi6LvzwzRMnWvKy7rbwEIoRyiwRgYw2kP1Htgvoi7/jz3Pvs4gjI8/tTtVzqCogiYTUL" + "tsb3RtfpxxSLZVmder05BXZCGargTV6RE8YFZeGsXv+mr/smZkP1eqnCtwiOJnASrTeMD2VkTSXR" + "7H2ehiLnNhgDKf/oiql/k92Vk1VINBqNAbIvRHdpPtpqFmz1CtG2bXdDq82RdrPJY1UNsiyJM2Ya" + "5xHL5+f2OLs1MDe5xp99pwsAnOm9OVzDALQsGUdzTxlGuhtb57lXtVoVRRA/Rn+Wb4mMJbPICQV/" + "jk0cZ3BTsaN2XDVuxuNZcBKsNzV4sa+VSbP3eVrjRoeZ34diR4m88Td5TchZhESw68y+I1HZmVW0" + "YCv9UCzL6jNjhIqtNlHSLF7HCgLdQITnzWZTe1ILMkmaE0qoQl4FRHherzeHGd/rZL+y+lyxIZ9r" + "GACQGuC/4ZjCWc3KpPXcVxZ/E4qbX6u6XgJvbNvOklmZS9gS4XmG6ypdsyqhepQsqvXo+y7gx1pv" + "jln1NwxqVp7keeSYHq9yxd8EFhhf9ZIP0N19BoIqOR4kHZXMpWw7Wx3SRcPJTFSJFq8iY2DywAyt" + "DMKNuEFGgc6MWwDT6E4/Y4o+AIAIr23b7uqkbuff6WZZSLK7pgJ0FojjCec0K1OY5aN8vuVymXi+" + "osg5Z9wxY7KtdwMYBptBaY1smwDfx5VpmhO9mjn5hW1YWkDptxSUOohZ1/fImhiiy5HSxP1+3CvH" + "st5kpYj4G8Pwnd10Xj10d5+hayqnyTXdxMhsdIm8xb6vNUyxjC3suI/rzjMnYYYTaKaJihm3RDxm" + "ro0PTdTBubmjktqdZvFiNhwitYeAGbeGEV8agJnNsC5Hlu/47Py85ai6PxqNb8aq6b17fAD46uvX" + "w374Tep+KLi0xIfv4wp6qdu5d7qtVqutmlYb1HzJ5yZVLY2gKyCI8C7jkB7AzDOFo3TuvVa8XVay" + "zhnhfDFIKr8QioABNJMbAuvkN30AytX2meHkTF8HwK9Un+0gUUbtglkSQ7JQucDh0bdtL07FEl9T" + "N7/1ZjX6bkCG77CPKWCMy4znKaL+TbhjzTOMM9WHMPzx5g6WU1kA447RE3TZgwrDyUS/KnU4UX39" + "mlwnJvx8EwBXoWi7QqzQSVuQ1N0cRDyez91BymGX4ZjG0LZOcAdId0EGWSW6dWNwCxj9tOcnXMgG" + "lmWNw3un/BmI8FxHpBWx0/V9vwOFuh4FuKYAAIZhKC4QegKi+gJ6Wu690hfFrHMGEd65bvq9C+fo" + "vmVZE30LEV9CUeCYpmkWFTcUCrK+wqGqz1olQhU4QgzOGvV+3GtFZU4R8VswvSKin4j4t/X45Ww1" + "+m7Ao2/bRZw/SjH9p/KbkFXSzItxTQF5MxmqCioMJypd18OH9XrZ0S2C9/Xrl4nrzjtxO2CFlEid" + "hUhpog8WeP34kEMtKfbJGMN1s14vOzppvoH1T/8zEHnKsQPMeeJv7lH8/vK6pgKRqF6ETefeVRvA" + "C+han8sfX1hNWmfOuGM2ftAVhsH8wu913kOE56qu7IIz596oBe+rzuvVPWeVC5zQnH+I26IsLcwP" + "HpznRPzWo9p/AqGjV8Qv9joF1L8pMPYi9TyNRmNQhKrPHyBWflBhlgwVZvrZdef9PLuL+Xw+YDZ+" + "wG5dpcSUyFar1db5XlTijjYE1y0jtVZbKN+47ryT5d6G9+6DznuY1dqOFLXTVRHtgcUrfwZfWrmB" + "vWMd9WPzVQTXRbe4qc5zn4VsBRdZw1K4y2q1GmB3nki/mmIaNmskyaigmHyg+mxXFiheqcBZji46" + "iIn9IFb3LabR6H2+BB+eEAOhs5oFgc75KCL+RqNuQArJE2zerKk9Mj+guoIuS1Bhq9Vqh7EbyhDh" + "XVq/HFUilpM7ID3+RqfIo97uPaDojAXbtnWF8s1qtXTyXLNW07Puqo6vuJ1u8sJY5O9PtQKsroBQ" + "d3sVg2Zx09SyFHkIhC4P9N7FP+ap5RKIfb3+Y0SqLsf8FbajhG1sYtGpBVW2UI1SqcChBD+egcaw" + "yGvVe5/6YP4RhxXyGcgfrUYXuRa0YurfFKa0Y9Vzca6pgDyZDJqCLpOvNvQZK0/szPhYdOzBxrUS" + "uKyMtOescPdUHpIyHEzTNHXFI8C5rGLAfeyCcmo0oDbpFrnTjRPvRf/+VCvAli2cC0C91piWy1+f" + "0EKhNWcU0cuNuaYZ70NtxTMXmjkXusf6ca+rliqp+jmrVuDEdatmfCyj51S993lYY68D4oMmeiL6" + "aT16Ocx6/mLib4orwhU3odfrzWGBhapyBoiVG1QY7lp1MhTu1utlX/c6KriuO53P5woNIXWCXPXd" + "CLp1UOr1+GBZ3YUgCL4srGJpCeJObacbprOnHGM4h/5elGs4RKcCrPLcouP2Ko5yn3tVMoj2wuYM" + "ffeWanycGnpZc/EdwjXmmEqthJVlUSW5pwDWjlpXJbSkOKvRdw4Z/gBMu8qW8GY1ulg0ep+1dqVF" + "1L/RqRuAIAYhZeF+mP1i23aXudACbHkfUA1Bp+9a8f34EgQHr8A0qCqiPwGNLu56/VvCZ0x5N5e2" + "w/J99DVST++Wy2VhrmcizPKUUziM8k53CsBEgrg75D4oKmsxchWN35+esM3XciKgXsdMZYd+Sg02" + "G41GF3qi/argOeNO4/qp90wjS/VuuVxeNRqqmxZ+FZ+dqOo6qzbOqzKBUwM5cfe8hmZpAmdDGMAc" + "CB3wJSKp6qFlSUvgFBF/o1M3gAhjZqT8ENlBJI0w3JkMk8672Zmq7zCzx3NoCrpMvlqdnRgzbouK" + "u8mKbp0SXWvIeu1f6dXCoNj7EYpl5e+vhIWgUPTuPU0AmEmCaD8bS9E1dYcgvVxpsS+xweYbIj93" + "41nfxzsoFIrULW5aboNN0pr7ixTt4fWnRbqUwoKCqTBjslgsFpZlDVXjw4j8PvY20TqFMqtosBml" + "MhdVbPPKktxTcTR6v0/qvU/devcTMdMPYP6xxvqdvIuJv1G3ZgRxL6m7mJ3zhWXrEx88w8BlWRk8" + "+5QdVBiWFddI8YxfzKtCr82GejZU0P3YHmpWTr1br/83jHsxFNjKGIYRe65TQOfeE/mTNHFBhOfR" + "dFoV1xQR+gDaquNQrQB7hM70ANTHV9Zzr0vo0tYRgh+OLNpTs67UM+cCa0qtVtOZB9+E9+wenbjK" + "KhpsRqkuBmffNRRCCgXFyiIQO5+HWVpDFBN/o2ZCZsbtYrFYqEywm4fPtu1u2uLGjI+KA92QN5Oh" + "1KBC3QW4XqfSLYdpFF0TKBA2Vj/ofqxdLTUtGFjn/t4cIWhVC50WJ+HEnDo5b4SFStYUMz6G1X6V" + "RblqBdhjdaZXtbScSoPN9Tpm4x0DkVaFbEXS42oiI0j8/vXajgTn+vLly0xnLdgPA1DP7Kq+E3wl" + "LqrV6DsnrlKvd4TiUnkpIv5Gx4QcCQBMndx83++YprlIc00hDJTTaa6YP5Oh7GBardLkJ7IAq1ea" + "ZUY7rO9z8LUgwyIwdWco0f4hqX+Tbr8m5vwF7cpGY6d7DWxaDyTfWMPwHdM0pyquqXrduFyvuava" + "ogMaAf4FVEfPgkaW26k02NTLotPpcaZB7tpIEZTnk6gYNQwMVWM19/vVqc67VXeCB6qLwXFi/n7b" + "7H2u1GRVBEXE3+j5oIMHwzCMqeclv4eZnXq92UfKYrTZrVvWM0d9IsweIFZ2UKF+wbbjC+sMTR7f" + "JAcPZl7QPrjuvJ94Zo1eWQHFB4Uys6kaswYkWxP04gaCZ8V13all2SljJKdeb3bSnkVmGnz58mVm" + "WXZJQffHaLBZTnHTMhts6lVSrt4C8RA/5Xeluonc/Szz+Xx8fm7fKs6hZ5Zl9V3XHZ5ig80olbio" + "KM5cytWmjBVFQvzNnaq7S9OEfG9KRKoPlvoqrqntTkRnIsy+aOnGBOgGFeqev+qqrYcorshjHvh9" + "mrgBdMzQAeUEhWoVL0uLVVA+1+7EnLbIsULHaLreBLdrtolQ+v0dqzO96m+qilpYKoSbLo0NRpq4" + "0Ec3c42I0u6F0nd/2JqiHpPITAPgvgebElU12IxSTQwO08GbcMz4mzwUEX+j4YPeq3uRKjLSfrD3" + "NRx0f1x5Fq2ygwp1Yw583zh6do+uaCiYOyL0XNdVdFFSW/XEKjVjsqFzv9J+J+ru0t2JOXWRS/39" + "1WrUB8pr0XEs4azRANTROG1pi2KGTVHhcwaR19Y5Pq0IJ3K0SwgTDJRaR2wa2moUyqyswWaU0l1U" + "PPq27cX86P0CzNg8csw11h0D3GEYMwYv6ljPsgQOq14vLv5GT7CpWU72416IeMKMzObn3UBSrQWj" + "gAabai6OKny15aadqqEZM1QUd0S4Wi6Xminc6s8KEc0yjCuR0BSuUask9RlS/Tz7E3OuOWvjmgL0" + "dr/lNdgsBs0KtSW55fQwDN/UqatUjotFr1ZR0rzVbDZV698cdPsFIQv2GMrJCf4lYJhq8/pxQgJK" + "Fzhr1NsUcwOKaK7pY9Unwi8c/osAeKhhPX4JEF+zjylgjItq5JkUf2PAUwpA0zEhG8aDCTXHBEvX" + "8/lfkTGqT4Sn3mBTtfbDqaBbE6gAbphpuF7/b5hxJ6Xblb1QgmBc9eOZ44uH6u10Hzz3uX5/0bpL" + "we5X+UPpXFdDjKJXUuDsQaqohaXBMS2oAHQ3OambzKyi/Z5azRh4nlo9pMAVq6wQjxKOUoWLyon5" + "eyFmbIYxQ5xZjekVEf1ExL+txy8X69HLYZDRled6+eNvdEzI+7uGHA3x7k3jG/QC7E67wSYRaaRa" + "Hh+d3Xsx8NXXr3+ddOG9JIi4r3F4YjsDzQabO+fJU8dj//enF1OkFt+i6/b6OzfYPDZhKQ/l74o5" + "OUW9iHYJwf0uPpi6ygabUSoQOP7hhYd4VsTZ671/j2vsdeK6h0c4A+FNKHZmWYUOGTEqWSuFWt1y" + "sm+SVAs0PnDFiGkc0O80fOoNNh8bRTZ5VLteEBT4GAkFsk4qbZpFQllYHJ6Y9RcAIrx7uFirWzWl" + "webTo/i6XarPU1o9NVYONla62nGeMwAVCJw4QcAF+jOp98es3vvUr3HjH8T4Oa65ZoTnRPzbevS9" + "1gMGoKiChTkLI+nGLu2axgH9ifCUG2w+TtR978z4SIR3+//pLLREeB5XQ+f00SulDyRP0Ko73fiJ" + "WTub5ma/W71ugL802Hxa6DcFpuskkaDzPKVZU+bz+bjgRIGjzemV9aKqgrDlwxWAKx45pgfPYXCH" + "DN8BUxt7zT59eDOd8xdRsFDPB314ItUMNH7gmgrP4ii+v4iJ8CSCCqPEN42rDI0GmzyYzx8ucMGz" + "xP9RPQ8zLk3TrMBNpVOZNZnQeqNTkfkmXQxoNdjU+Xvc9fr7f9FoiAg9i5GOcC6vgeUhTqnBZhbC" + "TM1JEefS7xGXVjhSOQlAye0XFv57q3jOFI4nVMsXODEWD5ScIh6KnTH2zNWbrKuMQcdOzN/vVAsW" + "6jXYjH0wlH/4+66pCJWIjhMLKrxHNz1TFcuyOsw1M0k8FdVgMygUZ71XbZQH4KzRaAyg2Vg2Ay9M" + "0zSLEVK6FZGTrTcZGmweQvn3R4R3h8SpTlB8WQ02q258eFoNNgFoCtWgWnh+wqa1yj3igqbA7jDl" + "KEfxXBOV48Iu44UInKqfsyjV9aI6Eag3WWTNqEooWKhzPmVhERf3oh4Y+NA1BWTqNJx5J1VVUKFu" + "lhcz6bsnUwhcQPQnkZ+4yBZZE2i1Wg2gFZNFP+03yytiHPs0Go3c9zd0qSk/p8y4dd3UhUDDhXN4" + "YtZwFz1wTW3PrR7gX1KDzcRA7DI4lQabGzLUwsr9TLdarbZCG50diHiQfoxeg800ws1JWlyrElU/" + "Z1GOJnAY/uMLJC0k/kavweah19RFgH9wp66ZRZJ3IqwkqND39YpwEeF1toX+Ia1Wq21ZzyZbk26y" + "2Cqy0WDQhBVaQYGe5w90jg/QTQow+vrX2GJZVl/fRK5yTfV4sOTnXmUBPpz5pduio5wGm9W7f3Se" + "+zKqBu+TwUJ0ZllWP+v1TNM0Pc8fQ6vkAl2niXa9hBGd772IYOPjtrcoVeDwyIn1xT+2HlRJWVea" + "DUN1G2zGHZH44BDhXcIEXWEmQzVBhVnMoJ7Hw6zXA4IJy7btgef5/4nGdaSXrFe3Iqjs3pfL5RX0" + "Muve6Aa56rsp+ZVt25l2vMEiQr9qXY3xUWXB0m2wGU/aAszvi/j9QbvBphrHaHyolzVWVdyG7gJM" + "V6EFXAvTNM1GozmBdmPNw5vUKDpWch1RFzy/+QTKcZ6zLaXG4Kyx7jyi2mtpODF/V46/0fP/Jz8Y" + "rvtX3HjSz6xRVfhAoUFlqgwqdF13qtEsLoRfnZ/b4/V62deJFzFN02w2m5fMuGR+uHNKSqkvY/e+" + "WCwWtm1f6Vg8QrO3o3r8arUaNxpNXdExtCzL0bEAWpZ1pRFTtLnO7ab9SBI61ZDTJuawxUXGWCYd" + "0V9Og82qGx+eUoPNXfwhEBsneoizRqM5MU3TUZ0zzs9bDpGu5QZgpp+/fp0r/HayNdhUQ/v+7L77" + "CA02ozypLKoyCTOxHr6gYeHQy5woM7Wumomw6qBCIh7rLo5EeN1oNGfn588G9TqN49x/oahxwtoV" + "3UPCJiRxx63ZlVt59x4GBV5CeRLlVzqZZGEZ9w/Qy2g6A+hP27bfxcWibAhcUjQAdAQqAOCOiLsq" + "90knwB8l/v40W3QojUNXQBiG79i27ei8Jw5mnqW5UXS70Tca34wt61neoQEI6rrEVWsOhfsV9MTH" + "i3q9ObUsa5D0uQNhwwPAzyIQPhyKn4xB6bvPYk1xXXd4fm4P9DaOW47RYDOKCBxVCoi/0bCclBYA" + "qJvBk7YABu6Ew7EPzH5bfWS4s6xnB69FxJO0BRIAarXalef5WgIn5IyIf/E8/iWwAu32UmLmNhGe" + "q4nT1CJapWSvZbHihKmnbdWjdcq4R2HGW8uyLwGMiTDbiOZQ8LcRBG+eZWu1wZfqvxV1y0lZFgTT" + "NM2yGmzqCIjiUoABInqncEVH76xarV0S8X1jEPdatt9NUFcKoF/DxX9ChNnmNWa0AxGbuRXLjevO" + "+yoH5m2wqUKOlPGjF20VgaNAEfVvAtQWt3IreBbbYJOZukSHJyPNBessblLz/bQKngEZ0qYfEExc" + "/HzvbxrvT44dKGP3vkHXikOE55Zl9dMzjwK+fPkys237XcbJ7gzAG2aAyH8LADqNDg/DP6qOPUT1" + "2S9tYtZpiHjqDTYjqDynWhamIknbpC2Xy6t6vdnPYqUI3/Nm/zvN0RfvZrVaOqoH522wqfi+rCnj" + "R4+zffQCZzX6zjHAHR9kErgNg9v3L/q0YNDUAC888CRHYLMT83fl+Bud2Is8cS/p6EyESpkMpU9c" + "OgHEq9VqUK83tXq8FEnSJFJ2TaBsu1G6Mk1zrLqgz+fzgWXZXWgHSxbKXWi5Gaq+oYqdrgqn0GCz" + "aNIWziM0lo2QvkkL3K9WN0xyOGZT2Q+r1fJSU1yXLtozuqdxrA7iUR6twFmNvhsQ8SXAZwzgvmN5" + "NE6GAAK/ZgAGCOvRyw81NC7DIoDKFBF/o2NCLjkwS6MOSLI1oqqJS8ddd8zJKq2lhU6Dzaz9WzLs" + "Rs+azeYlgIHqNVarpZMtIyQ/zLgl4q6uC1dnp1vuxGx01DswqzfYPJ6ASF84NWOfCkU17sR13all" + "WZe62XtFERSETHfD76MR9pBLtDMbQyI99/SxGmxGKTVNvI71rKxzE/Fb6C5ghDdefDfweAqIv9GJ" + "vSirgqdY7k5YAAASc0lEQVRup+G0nVk1HbH1I/+DxY8dZGhKmoe01H7NBpuZJqSgLk56YbAoYQsH" + "5dTXxWKxCM3oN5rDywm/X6+XnYzxacrParkT83EbbJbASVh5E1B+VlzXHRKhhwrnDWbcMhs/ZBE3" + "4RkKabCZRrgm6fzeT6ITfKkCh3p/zOJeW44ucj30zPweGg8iEW6Y6Yd6799K8Rwbiqp/w1xU/Y3s" + "FN1gs4qO2FnrKLiuO63VjE4VhaYCqwLe1WrxwYwB1dQEcl13qNks7yzMJFFmK3L4vd7oskDXzMYP" + "ruvqmu/v0agRU9rEfAoNNotH5fep89wXi27cyXw+H1c0b9wR4d3Xr/N21g2t5vNUgNtVvfDfqXSC" + "P5qLimBoF0uK0uh9vgRwuRp95xD8NsNoP7yGP2MYszrqU+rquaUiODF/V46/KaLBZkFouKdUHtDy" + "J6487rpwoXI2KcjFx+XQNeAP0/vE3FNZn6DAiqNlbn/TarXi+pYdJBQbl+fnrXFwveIyXwLoOkjx" + "/UtrU3IYtbGVOTGfQoPNElCZr44Vr5Up7qTMeYMZt4aB4XK5LKDprXqDzSKycl3XHVqWrZhSfxqd" + "4B9tDM6GrH2lVCki/kbHlVNuBU8d/7+S5aT0iauIOgphMOrQtu2u76MfVrPNFJ/DjI8ATZJq5hyi" + "qAabGu/Xrl8RtnDo614r3IE6YSB9P8isy7wo3DDTUPf+JhGMS00whAXZSkRVuKR1j9455wLAUUri" + "u25yITqde180eavobuaNsFBfP8yAzPJc34Tz6fDr1+LKfxgGm8wq97a4TXMo+Lppxx2zwWaU0iO/" + "vI8vp8wPF0Ji/FzrfdIyix+D9fjlQUXwWMYvHCYQHNwxDDaDzs70wKLIzAvDwDToc0XTCrobPxla" + "rVY7FPadoNYNtfePkfsrPDZarVZ7vUZ70/eLmc1g4wgAPNvUw2HmGXNtJs/0cSndgsPgxSEd5ePh" + "gnJqFFf/Rjg1wolncuRhPFlC68sMQMkWEUGojshzPTnqQAQlyu8m7u9Whd1AWgXnjoYT83fl+BtB" + "EARBEKqndIHDiBE4hnqJ+GNBoRnyAScSIS4IgiAIwmFKFzgU0yH6UFzOyVFA/RtBEARBEKqndIFT" + "wyrWlZNUY+bYFFX/RhAEQRCE6infghMU+ztYkM847TgcJ+bvEn8jCIIgCCdONXVwiKeH3D0ciIjS" + "Uq1DK4xD4A4MNgGAfWPS6P0+SHtvEfVvTgXTNM16/f/tiMl6HbNTKKWtyuYzEHltImr7vjEh8hZF" + "FLB6DBz6DoH8bT0sy+ow18xtynxQWHG9/u+0rI7agiAIVVBJB7SwMeahDsd39e6nQtPF16Pvu4Df" + "RVCM6GAxtxo3/pHWcLPM+jfn5/YsrmBUWGJ/ahgYzufzXCm2YXG5SyK8jrsWEQ90ujJvsCzrCqCf" + "ko+ia2aM1+v/DbMulmmfAUHJ8yvVXi6maZqNRvP/soxlC/8Yd88sy14gvojgnevOlZ/3QNR80yfi" + "PpKLKn5gNoaqYsc0TbPZbF6GRQ+TCpfdMNMwz/cnCIJwLKoSOA4R/3boNZ/5X0W4fNajiz6IBkBy" + "pUkVgVLmeMO2Df9RO5quXfcvR/cawSL+zVijdP4H1533da5hWfYU6pWMb1arpaOzSAaLe3OYIGwy" + "XSOsSnrwu1WH/3XIcpT+3ap/n2HV5SudyqnM9PPXr38lPtuBxYbGehVZ+b3rupfqxwuCIByfSlxU" + "jd7vk/X45cHXCEYXORqBhWJkiBRhA+CWmfp1tdYOTszfc8ff7LZtoOv9cuK7u2p+Zdv2QKfTbFga" + "fQLwGbCxCNFVtPR9uMgNIuLhjWVZC81F7MX2/EZ/88dthU90sRVAL+r1b/pQdEceWITvmGmw/xkA" + "ugTwZnONRqMxAJD6GYjw7tDf9+79eyI6KJbm88NusXBsBOxa6Vx3rrWRCHrg4Fe6f1fQk2m5XE42" + "Au78vOUYhu9Ex0zkJ4q7zbNBhM2z8XHfUhiINM8JvtN7gfy3cAMKgvC0qMSCAwDrjxeTQ3E4RLip" + "vf6UKdg4tNokNxQkvoaPYb33eah83pixgvGx3vuU2ocjiahrhwi9Q24oy7KHuF+41Xf9odVjGhEG" + "iVYN27YHzLh3Ha5Wy3+oWFn2rCCx1p/o52DGx69f56n3LnQhTbAVRze1mtGNixeyLKsfbSpZqxn/" + "zBpbFHEvabmS9tm15OhZ4fY/j4r1ZPs9HrYsbc/9bLIRLSrWnvB7vgK4/3eJdRIE4elQfiXjEPLp" + "YDwJM17w6Nt2lnNyTHdsItww83uf+V/1158dHXETnLjM+jfbzr/L5TLmfNG29OodmkOXjpK4AYD5" + "fD4IY34AAI1GQ0m8GTsFEONT5jd9WYL3qFkB6vXmEBFxs1otnSTBEsTCbBvOrdecSYCGjSI3lo1J" + "lnNsiFrpdBr+hRaWqLj5UcWqNp/PB0ToJYmQVqvVjjxLN2niBggCmF133hFxIwjCY6SybuIGvLGH" + "2i+HXvNR6yJDNlUd/tWa69EFfFJHfUrd5ADiJCroP3W/eMeJD+aaSXTfefpG5aThbvt18H7crtdq" + "MS+GgeHGikNEbZVrBc0p7/8Zu/ipHrch62dgxpgI4eLNDrJl5t2LElUxFj8ediLGUY1zGVebZy+w" + "sMyHqu9MC0hfr9GOuLwkYFgQhCdPZQKHen/MvI8vbw5WMDbQR4ZFKayxM8g7tj2cuBfyxt+EGUGb" + "f8aeyzB8h7caS+maRDzYvh+XqgG9Qbq1/zb4/8MWsYfXur9Hd3G7+8DVsonxoev5/C+FjDD/3lpB" + "xAP1oGSaboTBoa7giudw7kcRpkpnR8VKt0tgvdm4j3CrYmHJDr8yTdOUzChBEJ4ylQkcAICPIQgP" + "rDjMeLEcXXROoYBebP0b4uuHf9RjV7gctgYFAbbbQFlmY5h23jDm435xdN186eVJRF05AGaBaIvC" + "ndCKci9uVqv/KcXeRIKe77KkrueBGc7GwpG3tgwUrHQPoYgrigoXN/U6Zp63/Xej0ZzZtn1lGMbw" + "MdVDEgRBUKVSgZPkpjKCCb5f5XgOEhN/w7l39QAzORtLQ61We3C+0MJzhXsBwe9VFtv1mrubxZmI" + "tcSNYfjmRnQpumaiVp4XSSnXzLit16nvuumL/F78T2aBxszaVolQXIWxS5RLyKpa6faJCqx6/XC8" + "Wh6+fPkysyzrfaR20Rkz3nqe//b83L4NxkoTIn8iMTeCIDwFKgsyBkKXUpwlhNDlkVNo0T9dUnpj" + "TfJfYduawvf9vm3bA9u2B+fn9tiy7GkoFsLdv3rtEaLteYlId5yaGWxb90vqkYTnnudPbdtWCfyN" + "jEM31mn7+bPEzzSbTWf7Lz/X4q4agB0lKrCYcVuWRcV13cswRX6ndQoRnhPhNRH/AtCf5+f2TPE7" + "EwRBOFkqFTgAAjfVYc7WWB+1mFhSb6yGWv2cWPZcO2DG281/oWsmFDZ0zWz8oFeThtrb8/JMZ1zR" + "uBuV2BPmbYyS687p0H9E6GEbHH3GTAqfxbgfB3NtpvwBsCvwkKFmSxAUvDmXtkDcO9dWAB6y0h0i" + "2oKBiGZ5rp/GfD4frFbLNsA/Avz+kMWKCM+ZMXrofhQEQXg8VC5wwpTtg803ifjymFYcjgswLiD+" + "BhELRVh873r73/bvq9X/uvoxIHx/z3TdC5GA4dTYE1VXznw+H69WS2ebgs6vgjRlNer1bXq5ClHR" + "pRrUu8tWXGV7/85oNue6O9XYlsVisXBdd+i67qXr/uW47pyYjR8AfIgeR+T3jzNCQRCE/FRvwQHA" + "HBtEeVwrDh0WOEXE3+y6dox+sLAE/23EAhGeh9V4dVFtmbBDmOm0sSp9SDgUgJ4rZ7FYLKLWiPUa" + "bf0RpmPbdjfi3vmYLTNom72UJ7OoyFo6VRPWvOkHlp17xE0lCMKj5SgCp476FU7MirMcXey4kPaY" + "5D1/1Mqwbymp1aiP+/tBP+m7BrbWlHCRVRwTDbb/n56tpe/KicYGecrCQUcMMUfLBBja2UfRe02U" + "73tmNpztv7K5upi5nWcMeak6e00QBKEsjiJwqDdZnJoVp5YQPJs3/ibNtfPly5dZVGwA/tA0zUwi" + "b3eRjcey7GHU8qHmFlN35YTC4b4fVrrrbBs7ROQpWQ7CVhD3sUtZ0ruzBAXHsRsLRMquwvX6v/fH" + "EuG5jjsvTdCaIarni177sVmhBEEQohxF4ACpVpy3Wds3ZKXM+BsV105Q2C2bq4o5mlbNl0kLmmma" + "5vm5Pca2SeXder3sK15JyZVjWVaHyL8fU7QIYcK5J9v/p37SIm+aprnbrwt3oRVMm73ihjkrGKvH" + "M0UJ7uVW+HoeD9PeY5qmadv2AKA/k45rNptOo9GcqFr21mv/fuNhGLEJAYIgCCfP0QROihUHnpHu" + "MimUEuNvVF07WV1V6/X/hpv3BeKoOTkkEFqtVrvRaE6iBfUAVmqHoOLKOT9vOWEz0QkitXxU3B6u" + "6w4jfbHOPM8fH/r8m8+AiLgBOLFfVRIqVZlVaLVa7Ty1dHYtePzKsp7FfoeWZV01Gs1Z0GIj9Vod" + "AC8A+tOy7GFc+rdlWR3LehZ9Nj6ktX8QBEE4ZSrrJn4IHjmmR6sZYmJfiPFzrfepxJL1AcvRRceg" + "wzthZvohf4r4totzWsfu8/Nnl0E9kvt+TB0VAWLbdpcZo70/32BrlQgXugBm3BJxV3VRj45Lg9hO" + "44cIm01OsPs83Gx7J7GJ3YDqO4CdrMIkvN6fgHq384fnsIdBmv52bMG9DQKs83US3z3X4caryfWS" + "os/eLlFhxHvxZ3od0AVBEE6Ro1lwgMCKA+bYyZkJgypcVWXG3wSoZ+lkdVXN5/MxEXrR7uAIFtw3" + "4X8bYXAH8Pv1eqnZJXprhVLgQ61m/FNH3ACbFHd2Hn4GfhXew53PsFot2zmr7uYqEBi6At/sjQ2B" + "JYdfRdP3VXBdd7j/HUbOtSNSmPEx7CCeGK8WWgU/4IE7eHNOfoVIrFTQwVzEjSAIj5+jWnA2rD9e" + "TOJaJBDhpvb6k2a1Xc3rj16OsTXNRy7O1/XXn5085zZN09wUciPyFioLcvQ9gH5vpMCaw040KDiM" + "/ZmuVqtxllTooEdWLXXBLqCPE4DgMwDoRAvnEfGEmWdZP8M+rVarvcnYWq//O9U95/73tI/q932I" + "II6JDlmUpsvlcpLl8wcuP+4Yxq7w8n1aSIsGQRCeGichcJJcRADAzO8bvc+lZVatxy8XOOAmY6Z3" + "jd7vg7KuKwiCIAhCORzVRbWh2fs8ZaZ3ca8T0U/r0UW/jGuXXf9GEARBEITqOQmBAwCN3u8Dovv+" + "RQ8hugrFSKGUH38jCIIgCELVnIzAAQDD97qIqY0D4MwgmhQtckruPyUIgiAIwhE4KYFDvT9mYKOf" + "cMiZQTQutJVDqf2nBEEQBEE4BiclcACg3vv3OCkeB8Bz31hNihA5En8jCIIgCE+TkxM4QBCPA47v" + "bs2MF76xyu2ukvgbQRAEQXianKTAAYAaGpdJQcfMeJE3JkfibwRBEAThaXKyAod6k4XhN5zEzKow" + "8Hg9+l67xH5wEYm/EQRBEISnyMkKHEBd5ID80Wr03UDn3BJ/IwiCIAhPl5MWOICyyAERv11/vJio" + "9q6S+BtBEARBeLqcvMAB1EUOmF55VJt6o5epbR0k/kYQBEEQni6PQuAAW5EDxseUQ8+Y8Mv648Vk" + "NfrOiT+hxN8IgiAIwlPlJJpt6rIaXVwR0U9KBzM+1OANqPfHbPOnpOaezPSDuKgEQRAE4XHzaCw4" + "URq9z5dgo4f4tg5bCG88qv1nPXo53KSUE4zYrCsRN4IgCILw+HmUFpwNPPq27Ru1MTNeaLztFsDz" + "g68QX9dff3aKGJsgCIIgCMfjUVpwNlDvj1nt9adOSmuHfQ6LG0j8jSAIgiA8FR61wNnQ6P0+qLH3" + "zwIyoCZFjEcQBEEQhOPyqF1Uh1iPvu+C/CskWGriqHc/Pbn7IQiCIAh/R56EBSdKvffvcb37qQ3m" + "HxHE2yiRWmNHEARBEIRHw5MTOBvqvc/De6Gj4LryfZ5UMCxBEARBECrgyQqcDfXe52H99WfHZ/4X" + "GB8Qk1pOqE2qHZkgCIIgCGXxt4w5CbqP+92wmvFzAKhx4x/UmyyOOzJBEARBEIQCWI4uOrqdyAVB" + "EARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARB" + "EARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARBEARB" + "EIQK+P9lgpN4WCgLHAAAAABJRU5ErkJggg==" + ) + ) + (rect + (name "") + (start 47.739 18.5022) + (end 32.489 12.5022) + ) + (tbtext "DWN: ${DWN}" + (name "") + (pos 39.989 15.5022) + (justify center) + ) + (rect + (name "") + (start 32.489 18.5022) + (end 17.239 12.5022) + ) + (tbtext "CHK: ${CHK}" + (name "") + (pos 24.739 15.5022) + (justify center) + ) + (rect + (name "") + (start 17.239 18.5022) + (end 1.989 12.5022) + ) + (tbtext "APP: ${APP}" + (name "") + (pos 9.489 15.5022) + (justify center) + ) +) diff --git a/templates/tcs_default/meta/icon.png b/templates/tcs_default/meta/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..980536556bb7c64a244975ec98471928d8b98143 GIT binary patch literal 10960 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 gO Date: Sat, 28 Jun 2025 13:04:20 +1000 Subject: [PATCH 30/46] Fixed up page links in template proj files --- templates/hfs_default/hfs_default.kicad_pro | 4 ++-- templates/tcs_default/tcs_default.kicad_pro | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/hfs_default/hfs_default.kicad_pro b/templates/hfs_default/hfs_default.kicad_pro index 6cae8e3..6eb1d72 100644 --- a/templates/hfs_default/hfs_default.kicad_pro +++ b/templates/hfs_default/hfs_default.kicad_pro @@ -431,7 +431,7 @@ "step": "", "vrml": "" }, - "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks" + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/hfs.kicad_wks" }, "schematic": { "annotate_start_num": 0, @@ -457,7 +457,7 @@ "version": 1 }, "net_format_name": "", - "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks", + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/hfs.kicad_wks", "plot_directory": "", "spice_current_sheet_as_root": false, "spice_external_command": "spice \"%I\"", diff --git a/templates/tcs_default/tcs_default.kicad_pro b/templates/tcs_default/tcs_default.kicad_pro index 92ef1cf..e2e8a38 100644 --- a/templates/tcs_default/tcs_default.kicad_pro +++ b/templates/tcs_default/tcs_default.kicad_pro @@ -431,7 +431,7 @@ "step": "", "vrml": "" }, - "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks" + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/tcs.kicad_wks" }, "schematic": { "annotate_start_num": 0, @@ -457,7 +457,7 @@ "version": 1 }, "net_format_name": "", - "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/melon.kicad_wks", + "page_layout_descr_file": "${KIPRJMOD}/../.gitlab/templates/tcs.kicad_wks", "plot_directory": "", "spice_current_sheet_as_root": false, "spice_external_command": "spice \"%I\"", From 191ef7db663240f9cd0194b5ae41ee451a24ed38 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 1 Jul 2025 09:39:17 +1000 Subject: [PATCH 31/46] Merge main into dev --- .scripts/foot_gen.py | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index c5de24b..bae74b0 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -44,9 +44,6 @@ for item in pcb.GetDrawings(): continue z_str = lines[3].split(":")[-1].strip() z_offset = eval(z_str) - if type(z_offset) is not tuple: - z_offset = (z_offset) - for line in lines[4:]: sp = line.split(':', 1) if len(sp) != 2: @@ -171,19 +168,15 @@ for foot in saved: # sorted_foots.sort(key=lambda foot: foot[0].GetY()) # Export the step file -os.system("kicad-cli pcb export vrml --units 'tenths' -f --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.wrl " + sys.argv[1]) - # Export step file of board with no additional components -if len(z_offset) > 1: - path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + "_base" + ".wrl" - os.system("kicad-cli pcb export vrml --units 'tenths' -f --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + path + " " + sys.argv[1]) +os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.stp " + sys.argv[1]) # Import the 3d model of the actual PCB dummy = FOOTPRINT(pcb) dummy.SetPosition(brd_cent) dummy_model = FP_3DMODEL() dummy_model.m_Filename = "/tmp/dummy.wrl" -dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset[0]) +dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset) dummy.Add3DModel(dummy_model) pcb.Add(dummy) @@ -193,8 +186,8 @@ pcb.Add(dummy) # Save and export step of board + mating connectors SaveBoard("test/test.kicad_pcb", pcb) -path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".wrl" -os.system("kicad-cli pcb export vrml -f --units 'mm' --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + path + " test/test.kicad_pcb") +final_model_path_stp = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".stp" +os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + final_model_path_stp + " test/test.kicad_pcb") # Generate footprint @@ -265,7 +258,6 @@ for [foot, pad_map] in sorted_foots: # start = [cent_mm[0] - size_mm[0], cent_mm[1] - size_mm[1]] # end = [cent_mm[0] + size_mm[0], cent_mm[1] + size_mm[1]] # kicad_mod.append(RectLine(start=start, end=end, layer='F.Silkscreen', width=0.05, offset=0.2)) - # elif shape_type == pcbnew.SHAPE_T_CIRCLE: # start = [cent_mm[0], cent_mm[1] + size_mm[1]/2] # end = [start[0], start[1]] @@ -427,21 +419,17 @@ for i in range(len(corners)): # kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.SilkS', width=0.15)) -output_list = [(foot_name, -1.6)] -# Output another footprint if a second offset is specified -if len(z_offset) > 1: - output_list.append((foot_name+"_base", z_offset[1])) +final_model_path = "${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".stp" +kicad_mod.append(Model(filename=final_model_path + ,at=[0,0,-1.6] + ,scale=[1,1,1] + ,rotate=[0,0,0])) -for [local_name, z] in output_list: - local_mod = deepcopy(kicad_mod) - local_mod.append(Model(filename="${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + local_name + ".wrl" - ,at=[0,0,z] - ,scale=[1,1,1] - ,rotate=[0,0,0])) - - # write file - file_handler = KicadFileHandler(local_mod) - file_handler.writeFile(sys.path[0] + "/../../libs/melonlib/" + foot_path + ".pretty/" + local_name + ".kicad_mod" ) +# write file +file_handler = KicadFileHandler(kicad_mod) +final_foot_path = sys.path[0] + "/../../libs/melonlib/" + foot_path + ".pretty/" + foot_name + ".kicad_mod" +file_handler.writeFile(final_foot_path) import shutil + shutil.rmtree("test") From e39c3af4f902bb6cd324cedab25234139e6999b4 Mon Sep 17 00:00:00 2001 From: ac Date: Tue, 1 Jul 2025 17:26:01 +1000 Subject: [PATCH 32/46] Remove logo from xlsx bom --- .scripts/foot_gen.py | 1 + configs/default.kibot.yaml | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index bae74b0..cf9ff2e 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -258,6 +258,7 @@ for [foot, pad_map] in sorted_foots: # start = [cent_mm[0] - size_mm[0], cent_mm[1] - size_mm[1]] # end = [cent_mm[0] + size_mm[0], cent_mm[1] + size_mm[1]] # kicad_mod.append(RectLine(start=start, end=end, layer='F.Silkscreen', width=0.05, offset=0.2)) + # elif shape_type == pcbnew.SHAPE_T_CIRCLE: # start = [cent_mm[0], cent_mm[1] + size_mm[1]/2] # end = [start[0], start[1]] diff --git a/configs/default.kibot.yaml b/configs/default.kibot.yaml index 8e4e607..80b02cc 100644 --- a/configs/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -103,8 +103,6 @@ outputs: disable_run_by_default: _bom options: xlsx: - # this is a relative path unfortunately - logo: ".gitlab/micromelon_default/meta/icon.png" hide_pcb_info: true hide_stats_info: true format: "XLSX" From 03225edd05f51a901d6f2f26bb09773469ab37e0 Mon Sep 17 00:00:00 2001 From: ac Date: Wed, 2 Jul 2025 08:57:46 +1000 Subject: [PATCH 33/46] Added spacing text and aligned text better --- .scripts/pre_panel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.scripts/pre_panel.py b/.scripts/pre_panel.py index 7072905..578eb90 100644 --- a/.scripts/pre_panel.py +++ b/.scripts/pre_panel.py @@ -93,6 +93,7 @@ class Panel: self.text3 = None self.text4 = None self.dims = [self.gaps[i]*self.spacing + self.grid[i]*board.dims[i] + frame.extra_d[i] for i in range(0,2)] + self.spacing = [self.spacing + board.dims[i] for i in range(0,2)] arrow_off = [frame.spacing + frame.width, frame.width] text_off = [arrow_off[0] + 2, frame.width/2] @@ -112,7 +113,8 @@ class Panel: spacer = " " txt =\ - "PNL (x,y) : (" + float_to_str_mm(self.dims[0],4) + ", " + float_to_str_mm(self.dims[1],4) + ")\n" +\ + "PNL (x,y): (" + float_to_str_mm(self.dims[0],4) + ", " + float_to_str_mm(self.dims[1],4) + ")\n" +\ + "SPA (x,y): (" + float_to_str_mm(self.spacing[0],2) + ", " + float_to_str_mm(self.spacing[1],2) +")\n" +\ "BRD (x,y),r: (" + float_to_str_mm(board.dims[0],4) + ", " + float_to_str_mm(board.dims[1],4) + "), " +\ float_to_deg(board.rot, 3) + "\n" +\ "FIDS (x,y) : " + board.fids From 284f4a075aab563e0fcfc54d9c7c4612915fb1fc Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 2 Jul 2025 13:57:49 +1000 Subject: [PATCH 34/46] Panel text addition now has to be done using the post panel script process, as too many text fields required --- .scripts/pre_panel.py | 88 +++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/.scripts/pre_panel.py b/.scripts/pre_panel.py index 578eb90..d761e18 100644 --- a/.scripts/pre_panel.py +++ b/.scripts/pre_panel.py @@ -2,6 +2,9 @@ import json import sys from kikit.common import findBoardBoundingBox +from kikit.panelize_ui_impl import buildText +from kikit.panelize_ui_sections import ppText +from kikit.defs import * from pcbnewTransition.pcbnew import LoadBoard PCB_DIV_MM = 1000000 @@ -26,6 +29,7 @@ def float_to_deg(input: float, n: int=0) -> str: class Text: def __init__(self, text: str, anchor: str, offset: tuple[float, float], rot: float, size: tuple[float, float, float] = (1.0, 1.0, 0.16), just: tuple[str, str] = ('center', 'center')): + self.layer=Layer.F_SilkS self.text = text self.anchor = anchor self.hoff = float_to_str_mm(offset[0]) @@ -37,6 +41,13 @@ class Text: self.hjust = just[0] self.vjust = just[1] + def flip(self): + self.layer=Layer.B_SilkS + rot = float(self.rot.replace("deg", "")) + rot += 180.0 + self.rot = str(rot)+"deg" + return self + def to_dict(self, n: int) -> dict: if n == 0: str_n = '' @@ -56,6 +67,7 @@ class Text: "hjustify": self.hjust, "vjustify": self.vjust, "thickness": self.thickness, + "layer": int(self.layer), } } @@ -88,10 +100,7 @@ class Panel: self.grid = grid self.gaps = (grid[0] - 1, grid[1] - 1) self.frame = frame - self.text = None - self.text2 = None - self.text3 = None - self.text4 = None + self.text = {} self.dims = [self.gaps[i]*self.spacing + self.grid[i]*board.dims[i] + frame.extra_d[i] for i in range(0,2)] self.spacing = [self.spacing + board.dims[i] for i in range(0,2)] @@ -109,7 +118,7 @@ class Panel: txt_just = (('center', 'center'), ('left', 'center')) txt_rot = 90 - self.text = Text("{boardTitle}-{boardRevision}", txt_loc[0], txt_off[0], txt_rot, just=txt_just[0]).to_dict(0) + self.text.update(Text("{boardTitle}-{boardRevision}", txt_loc[0], txt_off[0], txt_rot, just=txt_just[0]).to_dict(len(self.text))) spacer = " " txt =\ @@ -118,35 +127,58 @@ class Panel: "BRD (x,y),r: (" + float_to_str_mm(board.dims[0],4) + ", " + float_to_str_mm(board.dims[1],4) + "), " +\ float_to_deg(board.rot, 3) + "\n" +\ "FIDS (x,y) : " + board.fids - self.text2 = Text(txt, txt_loc[1], txt_off[1], txt_rot, just=txt_just[1]).to_dict(1) + self.text.update(Text(txt, txt_loc[1], txt_off[1], txt_rot, just=txt_just[1]).to_dict(1)) if "frame" in self.frame.ftype: - self.text3 = Text("ORIGY ->", "bl", (arrow_off[1], -arrow_off[0]), 0, just=("right", "center")).to_dict(2) - self.text4 = Text("ORIGX ->", "bl", (arrow_off[0], -arrow_off[1]), 90, just=("right", "center")).to_dict(3) + txt_orig = [ +Text("ORIGX ->", "bl", (arrow_off[0], -arrow_off[1]), 90, just=("right", "center")), +Text("ORIGY ->", "bl", (arrow_off[1], -arrow_off[0]), 0, just=("right", "center")) + ] + for txt in txt_orig: + self.text.update(txt.to_dict(len(self.text))) + self.text.update(txt.flip().to_dict(len(self.text))) -print("Starting pre_panel script") +def kikitPostprocess(panel, arg): + print("arg:", arg) + text_dict = eval(arg) + for t in text_dict.values(): + ppText(t) + print(t["thickness"]) + t["plugin"] = None + buildText(t,panel) + # panel.addText(t.text, position=, orientation=t.rot, + # width=t.width, height=t.height, thickness=t.thickness, + # hJustify=t.hjustify, + # vJustify=t.vjustify, + # layer=t.layer): -board = LoadBoard(pcb_file) -sourceArea = findBoardBoundingBox(board) -fids = [] -for foot in board.Footprints(): - if "FID" in foot.GetReference(): - cent = foot.GetBoundingBox().GetCenter() - fids.append(tuple([cent[i]/PCB_DIV_MM for i in range(0,2)])) + print("Finished post panel script") -json_file = open(panel_file) -json_str = json_file.read() -panel_json = json.loads(json_str) +if __name__ == '__main__': + print("Starting pre_panel script") -frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["space"]) -board = Board(fids, panel_json["layout"].get("rotation", "0deg"), (sourceArea.GetWidth()/PCB_DIV_MM, sourceArea.GetHeight()/PCB_DIV_MM)) -panel = Panel(panel_json["layout"]["space"], (int(panel_json["layout"]["rows"]), int(panel_json["layout"]["rows"])) ,frame, board) + board = LoadBoard(pcb_file) + sourceArea = findBoardBoundingBox(board) + fids = [] + for foot in board.Footprints(): + if "FID" in foot.GetReference(): + cent = foot.GetBoundingBox().GetCenter() + fids.append(tuple([cent[i]/PCB_DIV_MM for i in range(0,2)])) -for t in [panel.text, panel.text2, panel.text3, panel.text4]: - if t is not None: - panel_json.update(t) + json_file = open(panel_file) + json_str = json_file.read() + panel_json = json.loads(json_str) -json_file = open(panel_file, mode="w") -json.dump(panel_json, json_file, indent=4) + frame = Frame(panel_json["framing"]["type"], panel_json["framing"]["width"], panel_json["framing"]["space"]) + board = Board(fids, panel_json["layout"].get("rotation", "0deg"), (sourceArea.GetWidth()/PCB_DIV_MM, sourceArea.GetHeight()/PCB_DIV_MM)) + panel = Panel(panel_json["layout"]["space"], (int(panel_json["layout"]["rows"]), int(panel_json["layout"]["rows"])) ,frame, board) -print("Finished pre_panel script") + import pathlib + + panel_json["post"]["script"] = str(pathlib.Path(__file__).resolve()) + panel_json["post"]["scriptarg"] = str(panel.text) + + json_file = open(panel_file, mode="w") + json.dump(panel_json, json_file, indent=4) + + print("Finished pre_panel script") From afa1ed40a536d92ed5bd9780151619568f36df39 Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 2 Jul 2025 13:59:59 +1000 Subject: [PATCH 35/46] Fix incorrect file reference in `foot_gen` script --- .scripts/foot_gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scripts/foot_gen.py b/.scripts/foot_gen.py index cf9ff2e..e643c35 100644 --- a/.scripts/foot_gen.py +++ b/.scripts/foot_gen.py @@ -175,7 +175,7 @@ os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToM dummy = FOOTPRINT(pcb) dummy.SetPosition(brd_cent) dummy_model = FP_3DMODEL() -dummy_model.m_Filename = "/tmp/dummy.wrl" +dummy_model.m_Filename = "/tmp/dummy.stp" dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset) dummy.Add3DModel(dummy_model) pcb.Add(dummy) From e803315a12a66dcce70c9cdbbb21634a5ab2de5f Mon Sep 17 00:00:00 2001 From: andrewc Date: Wed, 16 Jul 2025 12:14:58 +1000 Subject: [PATCH 36/46] FIX: cut down bash function in release job so it doesn't complain about syntax errors. --- kibot-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 727e218..4e13199 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -260,6 +260,8 @@ image: export DWN export CHK export APP + - !reference [.commands, parse_tag] + parse_tag: - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) outputs_mech: @@ -393,7 +395,7 @@ release_job: when: never # Do not run this job when a tag is created manually - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch script: - - !reference [.commands, parse_commit] + - !reference [.commands, parse_tag] - apk add jq curl - | echo "running release_job for $TAG" From a9abc89dcfc8ebc00b4cd4413fd929024ec2b7f2 Mon Sep 17 00:00:00 2001 From: andrewc Date: Thu, 17 Jul 2025 11:45:19 +1000 Subject: [PATCH 37/46] FIX: update gitignore to ignore kicad locks --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a8098cd..2d2948c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.kicad_prl *.sch-bak *~ +*.lck _autosave-* **/#auto_saved_files# *.tmp From 27cc645aed4d407fad25bbbf900f10b235b24663 Mon Sep 17 00:00:00 2001 From: ac Date: Mon, 21 Jul 2025 16:01:33 +1000 Subject: [PATCH 38/46] FIX: tag parsing --- kibot-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 4e13199..ac4e96d 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -262,7 +262,8 @@ image: export APP - !reference [.commands, parse_tag] parse_tag: - - TAG=$(echo ${CI_COMMIT_MESSAGE} | tr -d \\n) + - TAG=$REV + - echo $TAG outputs_mech: stage: gen_mech From f139e49ff7f84393f760784587f62568a126df8c Mon Sep 17 00:00:00 2001 From: ac Date: Mon, 21 Jul 2025 16:17:36 +1000 Subject: [PATCH 39/46] FIX: tag parsing in release job --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index ac4e96d..f238408 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -262,7 +262,7 @@ image: export APP - !reference [.commands, parse_tag] parse_tag: - - TAG=$REV + - TAG=$(echo "$CI_COMMIT_MESSAGE" | sed -n '1 p') - echo $TAG outputs_mech: From 908120fc75c7a10b97540322184151c3380e17a9 Mon Sep 17 00:00:00 2001 From: ac Date: Mon, 21 Jul 2025 16:44:59 +1000 Subject: [PATCH 40/46] FIX: Author initials parsing --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index f238408..d798c1d 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -245,7 +245,7 @@ image: str=$CI_COMMIT_MESSAGE REV=$(echo "$str" | sed -n '1 p') - DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f2,3)") + DWN=$(initials "$(echo "$str" | sed -n '3 p' | cut -d' ' -f1,2)") CHK='' APP='' From c18b69520dd1c42a03de1da52a5545e42884c963 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 22 Jul 2025 14:25:02 +1000 Subject: [PATCH 41/46] FIX: fix path to template schematic for post panel scripting --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index d798c1d..132e05c 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -113,7 +113,7 @@ image: echo "panelising" python3 .gitlab/.scripts/pre_panel.py $PCB $JSON kikit panelize -p $JSON $PCB panels/$NAME/$NAME.kicad_pcb - cp .gitlab/micromelon_default/micromelon_default.kicad_sch panels/$NAME/$NAME.kicad_sch + cp .gitlab/templates/micromelon_default/micromelon_default.kicad_sch panels/$NAME/$NAME.kicad_sch cp $d/fp-lib-table panels/$NAME/ python3 .gitlab/.scripts/post_panel.py panels/$NAME/$NAME.kicad_pro $PCB done From e9f401a2040b528d78815816b6974d258a510157 Mon Sep 17 00:00:00 2001 From: andrewc Date: Fri, 25 Jul 2025 10:33:17 +1000 Subject: [PATCH 42/46] Kibot variants were not working with groups as expected, so config structure has been changed to not use groups --- configs/default.kibot.yaml | 44 ++++++++++++++++++++++++++++++++----- configs/mech.kibot.yaml | 1 + configs/panel.kibot.yaml | 1 + configs/pcb_dev.kibot.yaml | 1 + configs/pcb_main.kibot.yaml | 1 + configs/pos.kibot.yaml | 3 ++- configs/sch.kibot.yaml | 1 + kibot-ci.yml | 2 +- 8 files changed, 46 insertions(+), 8 deletions(-) diff --git a/configs/default.kibot.yaml b/configs/default.kibot.yaml index 80b02cc..11630b4 100644 --- a/configs/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -87,9 +87,26 @@ outputs: - name: 'bom_csv' type: bom dir: . - extends: "_bom" - disable_run_by_default: _bom options: + columns: + - field: Value + name: value + - field: Quantity Per PCB + name: qty + - field: Footprint + name: footprint + - field: Datasheet + name: datasheet + - mpn + - manf + - rev + - conn_manf + - conn_mpn + - field: References + name: refs + exclude_filter: "" + output: "%f%v_%r_%i.%x" + expand_text_vars: true csv: separator: ';' hide_pcb_info: true @@ -99,9 +116,26 @@ outputs: - name: 'bom_xlsx' type: bom dir: . - extends: '_bom' - disable_run_by_default: _bom options: + columns: + - field: Value + name: value + - field: Quantity Per PCB + name: qty + - field: Footprint + name: footprint + - field: Datasheet + name: datasheet + - mpn + - manf + - rev + - conn_manf + - conn_mpn + - field: References + name: refs + exclude_filter: "" + output: "%f%v_%r_%i.%x" + expand_text_vars: true xlsx: hide_pcb_info: true hide_stats_info: true @@ -272,7 +306,6 @@ groups: - name: pcb_main outputs: - JLCPCB_compress - - neo_position - print_pcb - stencil - interactive_bom @@ -280,7 +313,6 @@ groups: - name: panel outputs: - JLCPCB_compress - - neo_position - print_pcb - step - interactive_bom diff --git a/configs/mech.kibot.yaml b/configs/mech.kibot.yaml index d3e8086..18c0caf 100644 --- a/configs/mech.kibot.yaml +++ b/configs/mech.kibot.yaml @@ -4,6 +4,7 @@ kibot: import: - file: default.kibot.yaml + outputs: ['step'] preflight: erc: false diff --git a/configs/panel.kibot.yaml b/configs/panel.kibot.yaml index d107b67..291ba94 100644 --- a/configs/panel.kibot.yaml +++ b/configs/panel.kibot.yaml @@ -4,6 +4,7 @@ kibot: import: - file: default.kibot.yaml + outputs: [JLCPCB_compress, neo_position, print_pcb, step, interactive_bom] preflight: erc: false diff --git a/configs/pcb_dev.kibot.yaml b/configs/pcb_dev.kibot.yaml index d107b67..5a6b3ff 100644 --- a/configs/pcb_dev.kibot.yaml +++ b/configs/pcb_dev.kibot.yaml @@ -4,6 +4,7 @@ kibot: import: - file: default.kibot.yaml + outputs: [print_pcb] preflight: erc: false diff --git a/configs/pcb_main.kibot.yaml b/configs/pcb_main.kibot.yaml index d107b67..3d6e619 100644 --- a/configs/pcb_main.kibot.yaml +++ b/configs/pcb_main.kibot.yaml @@ -4,6 +4,7 @@ kibot: import: - file: default.kibot.yaml + outputs: [JLCPCB_gerbers, JLCPCB_drill, JLCPCB_compress, print_pcb, stencil] preflight: erc: false diff --git a/configs/pos.kibot.yaml b/configs/pos.kibot.yaml index d107b67..47168d4 100644 --- a/configs/pos.kibot.yaml +++ b/configs/pos.kibot.yaml @@ -4,8 +4,9 @@ kibot: import: - file: default.kibot.yaml + outputs: ['neo_position'] preflight: erc: false update_xml: false - drc: true + drc: false diff --git a/configs/sch.kibot.yaml b/configs/sch.kibot.yaml index 955573f..799fe67 100644 --- a/configs/sch.kibot.yaml +++ b/configs/sch.kibot.yaml @@ -3,6 +3,7 @@ kibot: import: - file: default.kibot.yaml + outputs: ['bom_csv','bom_xlsx', 'print_sch', 'interactive_bom'] preflight: erc: true diff --git a/kibot-ci.yml b/kibot-ci.yml index 132e05c..be6bbd9 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -90,7 +90,7 @@ image: python3 $CI_PROJECT_DIR/.gitlab/.scripts/orig.py ${dir_arr[i-1]} for CONF in $KIBOT_CONF do - kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/configs/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS $CONF + kibot -e ${dir_arr[i-1]}/${sch_arr[i-1]} -c $CI_PROJECT_DIR/.gitlab/configs/$CONF.kibot.yaml -d $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]} $VARIANTS done mv $CI_PROJECT_DIR/Fabrication/${dir_arr[i-1]}/*.zip Fabrication/ 2> /dev/null || true done From 6b1e4b44c4a5a287dae8670a512099ce5c784707 Mon Sep 17 00:00:00 2001 From: andrewc Date: Fri, 25 Jul 2025 15:36:42 +1000 Subject: [PATCH 43/46] Fix up naming and parsing of files with variants --- configs/default.kibot.yaml | 26 +++++++++++++------------- configs/mech.kibot.yaml | 2 +- kibot-ci.yml | 3 +-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/configs/default.kibot.yaml b/configs/default.kibot.yaml index 11630b4..7880bc7 100644 --- a/configs/default.kibot.yaml +++ b/configs/default.kibot.yaml @@ -42,14 +42,14 @@ outputs: type: pdf_sch_print dir: . options: - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" - name: 'print_pcb' comment: "Print Top and Bottom Copper+Silk" type: pcb_print dir: . options: - output: "%f%v_%r_PCB.%x" + output: "%f_%r%v_PCB.%x" pages: - layers: - layer: F.Cu @@ -81,7 +81,7 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" expand_text_vars: true - name: 'bom_csv' @@ -105,7 +105,7 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" expand_text_vars: true csv: separator: ';' @@ -134,7 +134,7 @@ outputs: - field: References name: refs exclude_filter: "" - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" expand_text_vars: true xlsx: hide_pcb_info: true @@ -152,7 +152,7 @@ outputs: type: step dir: . options: - output: '%f%v_%r.%x' + output: '%f_%r%v.%x' download: false subst_models: true @@ -168,7 +168,7 @@ outputs: download: false download_lcsc: false orthographic: true - output: 'PCB_%f%v_%r.%x' + output: 'PCB_%f_%r%v.%x' show_components: 'none' - name: 'pcba_render' @@ -183,14 +183,14 @@ outputs: zoom: -1 download_lcsc: false orthographic: true - output: 'PCBA_%f%v_%r.%x' + output: 'PCBA_%f_%r%v.%x' show_components: 'all' - name: 'neo_position' comment: "Pick and place" type: position options: - output: '%f%v_%r_cpl.%x' + output: '%f_%r%v_cpl.%x' format: CSV units: millimeters separate_files_for_front_and_back: false @@ -201,7 +201,7 @@ outputs: type: stencil_3d dir: '3D_Stencil' options: - output: '%f%v_%r_%i.%x' + output: '%f_%r%v_%i.%x' - name: 'diff_pcb' comment: "Diff for visual comparison" @@ -225,7 +225,7 @@ outputs: type: ibom dir: . options: - output: '%f%v_%r_%i.%x' + output: '%f_%r%v_%i.%x' dark_mode: true - name: 'JLCPCB_gerbers' @@ -278,7 +278,7 @@ outputs: metric_units: true map: gerber route_mode_for_oval_holes: false - output: "%f%v_%r_%i.%x" + output: "%f_%r%v_%i.%x" - name: 'JLCPCB_compress' comment: ZIP file for JLCPCB @@ -289,7 +289,7 @@ outputs: dest: / - from_output: JLCPCB_drill dest: / - output: '%f%v_%r_JLC.%x' + output: '%f_%r%v_JLC.%x' groups: - name: mech outputs: diff --git a/configs/mech.kibot.yaml b/configs/mech.kibot.yaml index 18c0caf..3fec3f5 100644 --- a/configs/mech.kibot.yaml +++ b/configs/mech.kibot.yaml @@ -4,7 +4,7 @@ kibot: import: - file: default.kibot.yaml - outputs: ['step'] + outputs: ['step', 'pcb_render'] preflight: erc: false diff --git a/kibot-ci.yml b/kibot-ci.yml index be6bbd9..f858486 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -157,12 +157,11 @@ image: for f in $FILES do echo $f - name=$(echo $f | cut -c3- | cut -d'-' -f1)A - rev=$(echo $f | cut -c3- | cut -d'-' -f1)A fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-) name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) echo "name: $name_n_rev" assembly_rev=$(echo $name_n_rev | cut -d'_' -f2) + name=$(echo $name_n_rev | cut -d'_' -f1)A$(echo ${name_n_rev//$assembly_rev/.} | cut -d'.' -f2) pcb_rev=$(echo $assembly_rev | cut -d'_' -f1,2 | cut -d'.' -f1,2) pcb_im=$fab_path/PCB_$name_n_rev.png pcba_im=$fab_path/PCBA_$name_n_rev.png From 5e5b4560726f1760883d6564c208de730c6c5c2a Mon Sep 17 00:00:00 2001 From: andrewc Date: Mon, 28 Jul 2025 10:08:24 +1000 Subject: [PATCH 44/46] Change kintree_cli flags to match new syntax --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index f858486..6e0ec8d 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -173,7 +173,7 @@ image: DRY="" fi echo "Revs: $pcb_rev, $assembly_rev" - python -m kintree.kintree_cli $DRY -p $CI_PROJECT_DIR/Fabrication/$f --assembly "{'ipn': '$name', 'rev': ['$pcb_rev', '$assembly_rev'], 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 + python -m kintree.kintree_cli $DRY -b $CI_PROJECT_DIR/Fabrication/$f -a "{'ipn': '$name', 'rev': ['$pcb_rev', '$assembly_rev'], 'image': ['$pcb_im', '$pcba_im'], 'desc': '$desc_suffix', 'attachments': [$pcb_attach, $pcba_attach]}" --settings $KINTREE_SETT --digi_token token_storage.json || FAIL=1 done # - cp token_storage.json /tmp - | From 218ec0f190abb5164298907381ecb9e22bc6a454 Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 29 Jul 2025 10:04:16 +1000 Subject: [PATCH 45/46] Parse the pcb name properly for use as the IPN --- kibot-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot-ci.yml b/kibot-ci.yml index 6e0ec8d..edacb6a 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -161,7 +161,7 @@ image: name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) echo "name: $name_n_rev" assembly_rev=$(echo $name_n_rev | cut -d'_' -f2) - name=$(echo $name_n_rev | cut -d'_' -f1)A$(echo ${name_n_rev//$assembly_rev/.} | cut -d'.' -f2) + name=$(echo $name_n_rev | cut -d'-' -f1)A$(echo ${name_n_rev//$assembly_rev/.} | cut -d'.' -f2) pcb_rev=$(echo $assembly_rev | cut -d'_' -f1,2 | cut -d'.' -f1,2) pcb_im=$fab_path/PCB_$name_n_rev.png pcba_im=$fab_path/PCBA_$name_n_rev.png From f916bbead6487fe6224fbfe1beae54d81fa9428f Mon Sep 17 00:00:00 2001 From: andrewc Date: Tue, 29 Jul 2025 10:42:57 +1000 Subject: [PATCH 46/46] Generate PCBA image, and fixup uploads of images to inventree --- configs/mech.kibot.yaml | 2 +- kibot-ci.yml | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/configs/mech.kibot.yaml b/configs/mech.kibot.yaml index 3fec3f5..0ab63cc 100644 --- a/configs/mech.kibot.yaml +++ b/configs/mech.kibot.yaml @@ -4,7 +4,7 @@ kibot: import: - file: default.kibot.yaml - outputs: ['step', 'pcb_render'] + outputs: ['step', 'pcb_render', 'pcba_render'] preflight: erc: false diff --git a/kibot-ci.yml b/kibot-ci.yml index edacb6a..30f66ac 100644 --- a/kibot-ci.yml +++ b/kibot-ci.yml @@ -158,15 +158,16 @@ image: do echo $f fab_path=$CI_PROJECT_DIR/Fabrication/$(dirname $f | cut -c3-) - name_n_rev=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) - echo "name: $name_n_rev" - assembly_rev=$(echo $name_n_rev | cut -d'_' -f2) - name=$(echo $name_n_rev | cut -d'-' -f1)A$(echo ${name_n_rev//$assembly_rev/.} | cut -d'.' -f2) - pcb_rev=$(echo $assembly_rev | cut -d'_' -f1,2 | cut -d'.' -f1,2) - pcb_im=$fab_path/PCB_$name_n_rev.png - pcba_im=$fab_path/PCBA_$name_n_rev.png - pcb_attach=$(echo "['$fab_path/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']") - pcba_attach=$(echo "['$fab_path/${name_n_rev}_schematic.pdf', '$fab_path/${name_n_rev}_bom.csv', '$fab_path/${name_n_rev}-neo-pos_top.csv', '$fab_path/${name_n_rev}-neo-pos_bot.csv', '$fab_path/${name_n_rev}_ibom.html']") + full_name=$(echo $f | cut -c3- | rev | cut -d'/' -f1 | cut -c9- | rev) + echo "name: $full_name" + name_n_rev=$(echo $full_name | cut -d'_' -f1,2) + assembly_rev=$(echo $full_name | cut -d'_' -f2) + name=$(echo $full_name | cut -d'-' -f1)A$(echo ${full_name//$assembly_rev/.} | cut -d'.' -f2) + pcb_rev=$(echo ${assembly_rev} | cut -d'_' -f1,2 | cut -d'.' -f1,2) + pcb_im=${fab_path}/PCB_${name_n_rev}.png + pcba_im=${fab_path}/PCBA_${name_n_rev}.png + pcb_attach=$(echo "['${fab_path}/${name_n_rev}_PCB.pdf', '$CI_PROJECT_DIR/Fabrication/${name_n_rev}_JLC.zip']") + pcba_attach=$(echo "['${fab_path}/${full_name}_schematic.pdf', '${fab_path}/${full_name}_bom.csv', '${fab_path}/${full_name}-neo-pos_top.csv', '${fab_path}/${full_name}-neo-pos_bot.csv', '${fab_path}/${full_name}_ibom.html']") DRY="--dry assemblies" if [[ $CI_COMMIT_BRANCH == "main" ]]; then