]> git.gag.com Git - hw/altusmetrum/commitdiff
Add jlcpcb BOM generation
authorKeith Packard <keithp@keithp.com>
Wed, 12 Feb 2025 05:29:18 +0000 (21:29 -0800)
committerKeith Packard <keithp@keithp.com>
Wed, 12 Feb 2025 05:29:18 +0000 (21:29 -0800)
Signed-off-by: Keith Packard <keithp@keithp.com>
bin/partslist-vendor
pcb-rnd.mk
pcb.mk

index 6ac421747526497dc0e8ce024e91cdcad6f3b7d1..19f4d55b9284c26b94208458c5cc4158f9c5247b 100755 (executable)
@@ -13,8 +13,10 @@ string               not_vendor_list;
 string input_name;
 string output_name;
 string         program;
+file   output = stdout;
 int    argi;
 int    lineno = 0;
+bool   saw_error = false;
 
 void fatal(string format, poly args ...)
 {
@@ -22,6 +24,12 @@ void fatal(string format, poly args ...)
        exit(1);
 }
 
+void error(string format, poly args ...)
+{
+       File::fprintf(stderr, format, args...);
+       saw_error = true;
+}
+
 string[*] read_line(file f) {
        lineno++;
        string  line = fgets(f);
@@ -126,21 +134,21 @@ void process_seeed(string[string] entry)
 
        static bool start = true;
        if (start) {
-               printf("Part/Designator,Manufacturer Part Number/Seeed SKU, Quantity\n");
+               File::fprintf (output, "Part/Designator,Manufacturer Part Number/Seeed SKU, Quantity\n");
                start = false;
        }
 
        string[*] refdes = String::wordsplit(entry["refdes"], " \t");
        if (dim(refdes) > 1)
-               printf ("\"");
+               File::fprintf (output, "\"");
        for (int i = 0; i < dim(refdes); i++) {
-               printf("%s", refdes[i]);
+               File::fprintf (output, "%s", refdes[i]);
                if (i < dim(refdes) - 1)
-                       printf (",");
+                       File::fprintf (output, ",");
        }
        if (dim(refdes) > 1)
-               printf ("\"");
-       printf(",%s,%s\n", quoted(part_number), entry["quantity"]);
+               File::fprintf (output, "\"");
+       File::fprintf (output, ",%s,%s\n", quoted(part_number), entry["quantity"]);
 }
 
 void process_goldphoenix(string[string] entry)
@@ -153,31 +161,31 @@ void process_goldphoenix(string[string] entry)
        static int item = 1;
        static bool start = true;
        if (start) {
-               printf("#Item,Description,Designator,Package,Manufacturer,Manufacturer Part Number#,Supplier,Supplier Part #,QTY/BOARD,Order QTY,Unit Price, Subtotal \n");
+               File::fprintf (output, "#Item,Description,Designator,Package,Manufacturer,Manufacturer Part Number#,Supplier,Supplier Part #,QTY/BOARD,Order QTY,Unit Price, Subtotal \n");
                start = false;
        }
 
        string[*] refdes = String::wordsplit(entry["refdes"], " \t");
-       printf("%d,", item);
+       File::fprintf (output, "%d,", item);
 
        /* description */
-       printf("%s %s,",
+       File::fprintf (output, "%s %s,",
               quoted(entry["device"]),
               quoted(entry["value"]));
 
        /* designators */
        if (dim(refdes) > 1)
-               printf ("\"");
+               File::fprintf (output, "\"");
        for (int i = 0; i < dim(refdes); i++) {
-               printf("%s", refdes[i]);
+               File::fprintf (output, "%s", refdes[i]);
                if (i < dim(refdes) - 1)
-                       printf (",");
+                       File::fprintf (output, ",");
        }
        if (dim(refdes) > 1)
-               printf ("\"");
+               File::fprintf (output, "\"");
 
        /* rest */
-       printf(",%s,%s,%s,%s,%s,%s,%d\n",
+       File::fprintf (output, ",%s,%s,%s,%s,%s,%s,%d\n",
               quoted(entry["footprint"]),
               quoted(entry["mfg"]),
               quoted(entry["mfg_part_number"]),
@@ -188,11 +196,42 @@ void process_goldphoenix(string[string] entry)
        item++;
 }
 
+void process_jlcpcb(string[string] entry)
+{
+       if (entry["loadstatus"] == "noload") {
+               File::fprintf(stderr, "skipping part %v\n", entry);
+               return;
+       }
+       string part_number;
+       if (hash_test(entry, "jlcpcb_part_number")) {
+               part_number = entry["jlcpcb_part_number"];
+       } else {
+               error("Component (%s, %s, %s) has no JLCPCB Part #\n",
+                     entry["device"], entry["value"], entry["footprint"]);
+               part_number = "unknown";
+       }
+
+       static bool start = true;
+       if (start) {
+               File::fprintf (output, "Comment,Designator,Footprint,JLCPCB Part #\n");
+               start = false;
+       }
+
+       File::fprintf (output, "%s,", quoted(entry["value"]));
+       string[*] refdes = String::wordsplit(entry["refdes"], " \t");
+       for (int i = 0; i < dim(refdes); i++) {
+               File::fprintf (output, "%s", quoted(refdes[i]));
+               if (i < dim(refdes) - 1)
+                       File::fprintf (output, " ");
+       }
+       File::fprintf (output, "%s,%s\n", quoted(entry["footprint"]), quoted(part_number));
+}
+
 void process_digikey(string[string] entry)
 {
        if (entry["loadstatus"] == "noload")
                return;
-       printf("%s,%s,%s %s\n",
+       File::fprintf (output, "%s,%s,%s %s\n",
               entry["quantity"],
               quoted(part_number(entry)),
               quoted(entry["device"]),
@@ -203,16 +242,16 @@ void process_mouser(string[string] entry)
 {
        if (entry["loadstatus"] == "noload")
                return;
-/*     printf("%s|%s\n", part_number(entry), entry["quantity"]); */
+/*     File::fprintf (output, "%s|%s\n", part_number(entry), entry["quantity"]); */
 
        static bool start = true;
 
        if (start) {
-               printf("Mouser Part Number,Manufacturer Part Number,Quantity\n");
+               File::fprintf (output, "Mouser Part Number,Manufacturer Part Number,Quantity\n");
                start = false;
        }
 
-       printf("%s,%s,%s\n",
+       File::fprintf (output, "%s,%s,%s\n",
               quoted(entry["vendor_part_number"]),
               quoted(entry["mfg_part_number"]),
               entry["quantity"]);
@@ -221,7 +260,7 @@ void process_mouser(string[string] entry)
 void process_other(string[string] entry) {
        if (entry["loadstatus"] == "noload")
                return;
-       printf("%s,%s,%s,%s %s\n",
+       File::fprintf (output, "%s,%s,%s,%s %s\n",
               entry["vendor"],
               entry["quantity"],
               quoted(part_number(entry)),
@@ -238,6 +277,8 @@ void process_file(file f) {
                        process_seeed(entry);
                } else if (!is_uninit(&vendors) && has_vendor(vendors, "goldphoenix")) {
                        process_goldphoenix(entry);
+               } else if (!is_uninit(&vendors) && has_vendor(vendors, "jlcpcb")) {
+                       process_jlcpcb(entry);
                } else if ((!is_uninit(&vendors) && has_vendor(vendors, vendor)) ||
                           (!is_uninit(&not_vendors) && !has_vendor(not_vendors, vendor))) {
                        switch (entry["vendor"]) {
@@ -271,11 +312,22 @@ ParseArgs::argdesc argd = {
                  .name = "not-vendor",
                  .expr_name = "not-vendor",
                  .desc = "Vendors to exclude"},
+               { .var = { .arg_string = &output_name },
+                 .abbr = 'o',
+                 .name = "output",
+                 .expr_name = "output",
+                 .desc = "Output file name"},
        },
        .unknown = &argi,
 };
 
+void cleanup(int status) {
+       if (status != 0 && !is_uninit(&output_name))
+               File::unlink(output_name);
+}
+
 void main() {
+       int status = 1;
        ParseArgs::parseargs(&argd, &argv);
        if (!is_uninit(&vendor_list))
                vendors = String::parse_csv(vendor_list);
@@ -283,12 +335,20 @@ void main() {
        if (!is_uninit(&not_vendor_list))
                not_vendors = String::parse_csv(not_vendor_list);
 
-       if (!is_uninit(&argi)) {
-               for (int i = argi; i < dim(argv); i++)
-                       twixt(file f = File::open(argv[i], "r"); File::close(f))
-                               process_file(f);
-       } else
-               process_file(stdin);
+       if (!is_uninit(&output_name))
+               output = File::open(output_name, "w");
+
+       twixt(; cleanup(status)) {
+               if (!is_uninit(&argi)) {
+                       for (int i = argi; i < dim(argv); i++)
+                               twixt(file f = File::open(argv[i], "r"); File::close(f))
+                                       process_file(f);
+               } else
+                       process_file(stdin);
+               if (!saw_error)
+                       status = 0;
+       }
+       exit(status);
 }
 
 main();
index 2de9604c5784b8a916c7c6bd7ae2fd7c7972d7f3..e61aa46f27a58080a68fc699433ede94f48909cc 100644 (file)
@@ -31,22 +31,25 @@ partslist.csv:      $(PROJECT)-parts.csv preferred-parts.csv $(CONFIG)
        $(AM)/bin/fillpartscsv.py $(PROJECT)-parts.csv --output $@ --preferred preferred-parts.csv
 
 partslist-dk.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor digikey partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor digikey -o $@ partslist.csv
 
 partslist-check.dk: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor digikey --mfg partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor digikey -o $@ --mfg partslist.csv
 
 partslist-mouser.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor mouser partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor mouser -o $@ partslist.csv
 
 partslist-other.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --not-vendor digikey,mouser partslist.csv > $@
+       $(AM)/bin/partslist-vendor --not-vendor digikey,mouser -o $@ partslist.csv
 
 $(PROJECT)-seeed.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor seeed partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor seeed -o $@ partslist.csv
 
 $(PROJECT)-goldphoenix.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor goldphoenix partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor goldphoenix -o $@ partslist.csv
+
+$(PROJECT)-jlcpcb.csv: partslist.csv
+       $(AM)/bin/partslist-vendor --vendor jlcpcb -o $@ partslist.csv
 
 $(PROJECT)-parts.tab: $(SCHEMATICS) Makefile
        lepton-netlist -g bom -o $@ $(SCHEMATICS)
@@ -95,10 +98,10 @@ $(PROJECT)-seeed.zip:       $(PROJECT).lht $(CONFIG) $(PROJECT)-sch.pdf $(SEEED_EXTRA)
 
 jlcpcb: $(PROJECT)-jlcpcb.zip 
 
-$(PROJECT)-jlcpcb.zip: $(PROJECT).lht $(CONFIG)
+$(PROJECT)-jlcpcb.zip: $(PROJECT).lht $(CONFIG) $(PROJECT)-jlcpcb.csv
        pcb-rnd -x cam gerber:JLC_PCB --outfile out/$(PROJECT) $(PROJECT).lht
        $(call emit_xyrs)
-       rm -f $@ && zip -j $@ out/* $(PROJECT).xy
+       rm -f $@ && zip -j $@ out/* $(PROJECT).xy $(PROJECT)-jlcpcb.csv
 
 stencilsunlimited:     $(BOTTOMCOPPER) $(PROJECT).toppaste.gbr $(OUTLINE)
        rm -f $(PROJECT)-stencil.zip && zip $(PROJECT)-stencil.zip $(PROJECT).toppaste.gbr $(OUTLINE)
@@ -123,7 +126,7 @@ clean:
        rm -f $(PROJECT).txt $(PROJECT).gl2 $(PROJECT).gl3
        rm -f $(PROJECT).drd $(PROJECT).g2l $(PROJECT).g3l $(PROJECT).gko 
        rm -f $(PROJECT)-seeed.zip $(PROJECT)-seeed.csv
-       rm -f $(PROJECT)-goldphoenix.zip $(PROJECT)-goldphoenix.csv
+       rm -f $(PROJECT)-goldphoenix.zip $(PROJECT)-goldphoenix.csv $(PROJECT)-jlcpcb.csv
        rm -f $(PROJECT)*.ps $(PROJECT)*.pdf $(PROJECT)-bom.csv
        rm -f $(PROJECT)-parts.csv $(PROJECT)-parts.tab preferred-parts.csv
        rm -f *.scad
diff --git a/pcb.mk b/pcb.mk
index b6fe2eac8feca23c05a862c646b368f181f7aca8..ecddd7fa8fe2c0d693f7ac2ba5d5a9c7da0dd118 100644 (file)
--- a/pcb.mk
+++ b/pcb.mk
@@ -31,22 +31,25 @@ partslist.csv:      $(PROJECT)-parts.csv preferred-parts.csv
        $(AM)/bin/fillpartscsv.py $(PROJECT)-parts.csv --output $@ --preferred preferred-parts.csv
 
 partslist-dk.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor digikey partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor digikey -o $@ partslist.csv
 
 partslist-check.dk: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor digikey --mfg partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor digikey -o $@ --mfg partslist.csv
 
 partslist-mouser.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor mouser partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor mouser -o $@ partslist.csv
 
 partslist-other.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --not-vendor digikey,mouser partslist.csv > $@
+       $(AM)/bin/partslist-vendor --not-vendor digikey,mouser -o $@ partslist.csv
 
 $(PROJECT)-seeed.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor seeed partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor seeed -o $@ partslist.csv
 
 $(PROJECT)-goldphoenix.csv: partslist.csv
-       $(AM)/bin/partslist-vendor --vendor goldphoenix partslist.csv > $@
+       $(AM)/bin/partslist-vendor --vendor goldphoenix -o $@ partslist.csv
+
+$(PROJECT)-jlcpcb.csv: partslist.csv
+       $(AM)/bin/partslist-vendor --vendor jlcpcb -o $@ partslist.csv
 
 pcb:   $(SCHEMATICS) Makefile $(CONFIG)
        lepton-sch2pcb project