FreeCalypso > hg > ueda-linux
view pads2gpcb/decals.c @ 72:fab9fc646044
pads2gpcb: single -f option to write loose footprint files
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Feb 2016 00:26:04 +0000 |
parents | a7f0e9bb3fb7 |
children | f673b6ad2a78 |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <strings.h> #include "globals.h" #include "struct.h" extern long convert_input_dim(); static struct part_decal *current_decal; static struct footprint_body fpbody; static struct footprint_pad *pins_array; #define MAX_SILK_LINES 64 static struct element_line silk_lines[MAX_SILK_LINES]; static struct element_arc silk_arcs[MAX_SILK_LINES]; static int num_silk_lines; static int num_silk_arcs; #define SOLDERMASK_DELTA (600 * 254) #define CLEARANCE_SETTING (2000 * 254) static void enter_decal() { struct part_decal *p, **pp; char *name = input_line_fields[0]; for (pp = &part_decal_list; p = *pp; pp = &p->next) if (!strcmp(p->name, name)) { fprintf(stderr, "%s line %d: decal name \"%s\" already defined\n", input_filename, input_lineno, name); exit(1); } p = malloc(sizeof(struct part_decal) + strlen(name) + 1); if (!p) { perror("malloc of struct part_decal"); exit(1); } p->name = (char *)(p + 1); strcpy(p->name, name); p->body = 0; p->next = 0; *pp = p; current_decal = p; } static void get_line_internal() { if (!get_input_line()) { fprintf(stderr, "error: EOF in the middle of a part decal definition\n"); exit(1); } } static drawpiece_silk_candidate() { int level; if (input_line_nfields != 5) return(0); level = atoi(input_line_fields[4]); return is_drawlevel_selected(level); } static try_silk_open_closed() { int ncoord, i, bad; struct coord_pair coord[MAX_SILK_LINES+1]; long thickness; if (strcmp(input_line_fields[0], "OPEN") && strcmp(input_line_fields[0], "CLOSED")) return(0); ncoord = atoi(input_line_fields[1]); if (ncoord < 2) { printf("line %d: silk %s piece ncoord < 2\n", input_lineno, input_line_fields[0]); return(0); } if (ncoord > MAX_SILK_LINES + 1) { printf("line %d: silk %s piece ncoord too big\n", input_lineno, input_line_fields[0]); return(0); } thickness = convert_input_dim(input_line_fields[2]); bad = 0; for (i = 0; i < ncoord; i++) { get_line_internal(); parse_input_line_fields(); if (input_line_nfields != 2) { printf("line %d: silk line coord not 2 numbers\n", input_lineno); bad = 1; continue; } coord[i].x = convert_input_dim(input_line_fields[0]); coord[i].y = convert_input_dim(input_line_fields[1]); } if (bad) return(1); for (i = 0; i < ncoord - 1; i++) { if (num_silk_lines >= MAX_SILK_LINES) { printf("Too many silk lines!\n"); return(1); } silk_lines[num_silk_lines].end1 = coord[i]; silk_lines[num_silk_lines].end2 = coord[i+1]; silk_lines[num_silk_lines].thickness = thickness; num_silk_lines++; } return(1); } static try_silk_circle() { int i, bad; struct coord_pair coord[2], centre; long diameter, thickness; if (strcmp(input_line_fields[0], "CIRCLE")) return(0); if (strcmp(input_line_fields[1], "2")) { printf("line %d: silk CIRCLE piece ncoord != 2\n", input_lineno); return(0); } thickness = convert_input_dim(input_line_fields[2]); bad = 0; for (i = 0; i < 2; i++) { get_line_internal(); parse_input_line_fields(); if (input_line_nfields != 2) { printf("line %d: silk CIRCLE coord not 2 numbers\n", input_lineno); bad = 1; continue; } coord[i].x = convert_input_dim(input_line_fields[0]); coord[i].y = convert_input_dim(input_line_fields[1]); } if (bad) return(1); /* find the centre and diameter */ if (coord[0].x == coord[1].x) { centre.x = coord[0].x; if (coord[0].y < coord[1].y) { diameter = coord[1].y - coord[0].y; centre.y = coord[0].y + diameter / 2; } else if (coord[1].y < coord[0].y) { diameter = coord[0].y - coord[1].y; centre.y = coord[1].y + diameter / 2; } else goto centre_diam_fail; } else if (coord[0].y == coord[1].y) { centre.y = coord[0].y; if (coord[0].x < coord[1].x) { diameter = coord[1].x - coord[0].x; centre.x = coord[0].x + diameter / 2; } else if (coord[1].x < coord[0].x) { diameter = coord[0].x - coord[1].x; centre.x = coord[1].x + diameter / 2; } else goto centre_diam_fail; } else { centre_diam_fail: printf("line %d: unable to find circle centre and diameter\n", input_lineno); return(1); } if (diameter % 2) printf("warning: line %d: circle diameter in nm is odd!\n", input_lineno); if (num_silk_arcs >= MAX_SILK_LINES) { printf("Too many silk arcs!\n"); return(1); } silk_arcs[num_silk_arcs].centre = centre; silk_arcs[num_silk_arcs].width = diameter / 2; silk_arcs[num_silk_arcs].height = diameter / 2; silk_arcs[num_silk_arcs].start_angle = 0; silk_arcs[num_silk_arcs].delta_angle = 360; silk_arcs[num_silk_arcs].thickness = thickness; num_silk_arcs++; return(1); } static void one_drawing_piece() { int ncoord, i; /* extract silk lines and arcs if enabled, otherwise skip */ get_line_internal(); parse_input_line_fields(); if (input_line_nfields < 2) { fprintf(stderr, "%s line %d: expected piece header line giving # of coords\n", input_filename, input_lineno); exit(1); } if (do_footprint_silk && drawpiece_silk_candidate()) { if (try_silk_open_closed()) return; if (try_silk_circle()) return; } ncoord = atoi(input_line_fields[1]); for (i = 0; i < ncoord; i++) get_line_internal(); } static void one_text_item() { /* just skip it for now */ get_line_internal(); get_line_internal(); get_line_internal(); } static void one_attr_label() { /* just skip it for now */ get_line_internal(); get_line_internal(); get_line_internal(); } static void read_pindef_line(idx) { get_line_internal(); if (input_line_buf[0] != 'T') { fprintf(stderr, "%s line %d: 'T' line expected\n", input_filename, input_lineno); exit(1); } parse_input_line_fields(); if (input_line_nfields != 5) { fprintf(stderr, "%s line %d: expected 5 fields in 'T' line\n", input_filename, input_lineno); exit(1); } input_line_fields[0]++; if (atoi(input_line_fields[4]) != idx + 1) { fprintf(stderr, "%s line %d: expected %d in the pin number field\n", input_filename, input_lineno); exit(1); } pins_array[idx].end1.x = convert_input_dim(input_line_fields[0]); pins_array[idx].end1.y = convert_input_dim(input_line_fields[1]); } static void process_pad_shape(padptr) struct pad_shape_info *padptr; { padptr->short_dim = convert_input_dim(input_line_fields[1]); if (padptr->short_dim <= 0) { printf("line %d: pad short dim <= 0\n", input_lineno); return; } if (!strcmp(input_line_fields[2], "R")) { padptr->rounded = 1; padptr->elongated = 0; } else if (!strcmp(input_line_fields[2], "S")) { padptr->rounded = 0; padptr->elongated = 0; } else if (!strcmp(input_line_fields[2], "OF")) { padptr->rounded = 1; padptr->elongated = 1; } else if (!strcmp(input_line_fields[2], "RF")) { padptr->rounded = 0; padptr->elongated = 1; } else { printf("line %d: unsupported pad shape %s\n", input_lineno, input_line_fields[2]); return; } if (padptr->elongated) { if (input_line_nfields < 6) { fprintf(stderr, "%s line %d: too few fields in OF/RF pad stack line\n", input_filename, input_lineno); exit(1); } padptr->angle = parse_input_angle_90s(input_line_fields[3]); if (padptr->angle != 0 && padptr->angle != 90) { printf("line %d: unsupported OF/RF angle\n", input_lineno); return; } padptr->long_dim = convert_input_dim(input_line_fields[4]); if (strcmp(input_line_fields[5], "0")) { printf("line %d: unsupported nonzero finoffset\n", input_lineno); return; } if (padptr->long_dim <= padptr->short_dim) { printf("line %d: OF/RF long dim <= short dim\n", input_lineno); return; } } padptr->valid = 1; } static void one_padstack_def() { int pinno, stacklines, i; struct pad_shape_info *padptr; get_line_internal(); parse_input_line_fields(); if (input_line_nfields != 3 || strcmp(input_line_fields[0], "PAD")) { fprintf(stderr, "%s line %d: expected PAD header line\n", input_filename, input_lineno); exit(1); } pinno = atoi(input_line_fields[1]); stacklines = atoi(input_line_fields[2]); if (pinno < 0 || pinno > fpbody.npins) { fprintf(stderr, "%s line %d: PAD pinno field invalid\n", input_filename, input_lineno); exit(1); } if (pinno) padptr = &pins_array[pinno-1].shape; else padptr = &fpbody.default_pad; padptr->defined = 1; for (i = 0; i < stacklines; i++) { get_line_internal(); parse_input_line_fields(); if (input_line_nfields < 3) { fprintf(stderr, "%s line %d: too few fields in pad stack line\n", input_filename, input_lineno); exit(1); } if (!strcmp(input_line_fields[0], "-2")) process_pad_shape(padptr); } } static void apply_default_padstack() { int i; if (!fpbody.default_pad.valid) return; for (i = 0; i < fpbody.npins; i++) if (!pins_array[i].shape.defined) pins_array[i].shape = fpbody.default_pad; } static convert_pad_to_gpcb(pinidx) { struct footprint_pad *pin = pins_array + pinidx; long long_minus_short, delta; if (!pin->shape.valid) { printf("error: no pad shape for pin #%d\n", pinidx + 1); return(-1); } pin->thickness = pin->shape.short_dim; pin->clearance = CLEARANCE_SETTING; pin->mask = pin->thickness + SOLDERMASK_DELTA; pin->end2 = pin->end1; if (!pin->shape.elongated) return(0); long_minus_short = pin->shape.long_dim - pin->shape.short_dim; delta = long_minus_short / 2; switch (pin->shape.angle) { case 0: pin->end1.x -= delta; pin->end2.x += delta; return(0); case 90: pin->end1.y -= delta; pin->end2.y += delta; return(0); } return(-1); } static void write_decal_as_element() { char *filename, *cp, *dp; int c; FILE *outf; filename = malloc(strlen(current_decal->name) * 3 + 8); if (!filename) { perror("malloc for output file name"); exit(1); } strcpy(filename, "decals/"); dp = filename + 7; for (cp = current_decal->name; *cp; ) { c = *cp++; if (isalnum(c) || c == '-' || c == '.' || c == '_') *dp++ = c; else { sprintf(dp, "%%%02X", c); dp += 3; } } *dp = '\0'; outf = fopen(filename, "w"); if (!outf) { perror(filename); exit(1); } write_gpcb_element(outf, current_decal->body, 0, "", "", "", 0); fclose(outf); printf("Written to %s\n", filename); free(filename); } static void process_one_decal() { int num_drawing_pieces, num_padstack_defs; int num_text_items, num_attr_labels; int i, valid; if (input_line_nfields < 7 || input_line_nfields > 9) { fprintf(stderr, "%s line %d: expected beginning of part decal definition, wrong # of fields\n", input_filename, input_lineno); exit(1); } enter_decal(); printf("Processing decal %s\n", current_decal->name); bzero(&fpbody, sizeof fpbody); if (input_line_fields[1][0] != 'I' && input_line_fields[1][0] != 'M' || input_line_fields[1][1]) { fprintf(stderr, "%s line %d: expected 'I' or 'M' in field 1\n", input_filename, input_lineno); exit(1); } fpbody.src_units = input_line_fields[1][0]; if (input_units_global == 'B') input_units_current = 'B'; else input_units_current = fpbody.src_units; fpbody.mark_x = convert_input_dim(input_line_fields[2]); fpbody.mark_y = convert_input_dim(input_line_fields[3]); num_drawing_pieces = atoi(input_line_fields[4]); fpbody.npins = atoi(input_line_fields[5]); num_padstack_defs = atoi(input_line_fields[6]); if (input_line_nfields > 7) num_text_items = atoi(input_line_fields[7]); else num_text_items = 0; if (input_line_nfields > 8) num_attr_labels = atoi(input_line_fields[8]); else num_attr_labels = 0; /* done parsing the header line, initialize some misc */ fpbody.refdes_scale = 100; num_silk_lines = 0; num_silk_arcs = 0; /* read and process the miscellany */ for (i = 0; i < num_drawing_pieces; i++) one_drawing_piece(); for (i = 0; i < num_text_items; i++) one_text_item(); for (i = 0; i < num_attr_labels; i++) one_attr_label(); /* deal with dummies */ if (fpbody.npins == 0 && num_padstack_defs == 0) { printf("Dummy decal with no pins, skipping\n"); return; } if (fpbody.npins < 1) { fprintf(stderr, "Error in decal %s: # of terminals %d < 1\n", current_decal->name, fpbody.npins); exit(1); } if (num_padstack_defs < 1) { fprintf(stderr, "Error in decal %s: # of pad stack defs %d < 1\n", current_decal->name, num_padstack_defs); exit(1); } /* the meat: allocate and fill the pins array */ pins_array = malloc(sizeof(struct footprint_pad) * fpbody.npins); if (!pins_array) { perror("malloc of the pins array"); exit(1); } fpbody.pins = pins_array; bzero(pins_array, sizeof(struct footprint_pad) * fpbody.npins); for (i = 0; i < fpbody.npins; i++) read_pindef_line(i); /* read and process the pad stack definitions */ for (i = 0; i < num_padstack_defs; i++) one_padstack_def(); /* post-processing */ apply_default_padstack(); valid = 1; for (i = 0; i < fpbody.npins; i++) if (convert_pad_to_gpcb(i) < 0) valid = 0; if (valid) { /* good, save it */ if (num_silk_lines) { fpbody.silk_lines = malloc(sizeof(struct element_line) * num_silk_lines); if (!fpbody.silk_lines) { perror("malloc to save silk lines"); exit(1); } bcopy(silk_lines, fpbody.silk_lines, sizeof(struct element_line) * num_silk_lines); fpbody.num_silk_lines = num_silk_lines; } if (num_silk_arcs) { fpbody.silk_arcs = malloc(sizeof(struct element_arc) * num_silk_arcs); if (!fpbody.silk_arcs) { perror("malloc to save silk arcs"); exit(1); } bcopy(silk_arcs, fpbody.silk_arcs, sizeof(struct element_arc) * num_silk_arcs); fpbody.num_silk_arcs = num_silk_arcs; } current_decal->body = malloc(sizeof(struct footprint_body)); if (!current_decal->body) { perror("malloc to save footprint body"); exit(1); } *current_decal->body = fpbody; if (write_footprint_files) write_decal_as_element(); } else { printf("decal to gpcb fp conversion FAILED\n"); free(pins_array); } } process_partdecal_section() { for (;;) { if (!get_input_line()) { fprintf(stderr, "error: EOF in PARTDECAL section\n"); exit(1); } if (input_line_buf[0] == '*') { parse_starline(); if (strcmp(input_line_starkw, "REMARK")) break; else continue; } parse_input_line_fields(); if (input_line_nfields) process_one_decal(); } } struct part_decal * find_decal_by_name(name) char *name; { struct part_decal *p; for (p = part_decal_list; p; p = p->next) if (!strcmp(p->name, name)) break; return(p); }