FreeCalypso > hg > ueda-linux
view pads2gpcb/decals.c @ 60:0444db01fa4a
pads2gpcb: recognize drawing on levels 0 and 1 in decals as silk
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Sun, 31 Jan 2016 03:29:33 +0000 |
parents | aeef205f7580 |
children | ff1d565d233c |
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 16 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 try_silk_open_closed() { int ncoord, i, bad; long x[MAX_SILK_LINES+1], y[MAX_SILK_LINES+1]; long thickness; if (strcmp(input_line_fields[0], "OPEN") && strcmp(input_line_fields[0], "CLOSED")) return(0); if (input_line_nfields != 5) return(0); if (strcmp(input_line_fields[4], "0") && strcmp(input_line_fields[4], "1")) 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; } x[i] = convert_input_dim(input_line_fields[0]); y[i] = -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].x1 = x[i]; silk_lines[num_silk_lines].y1 = y[i]; silk_lines[num_silk_lines].x2 = x[i+1]; silk_lines[num_silk_lines].y2 = y[i+1]; silk_lines[num_silk_lines].thickness = thickness; num_silk_lines++; } return(1); } static try_silk_circle() { int i, bad; long x[2], y[2]; long centre_x, centre_y, diameter, thickness; if (strcmp(input_line_fields[0], "CIRCLE")) return(0); if (input_line_nfields != 5) return(0); if (strcmp(input_line_fields[4], "0") && strcmp(input_line_fields[4], "1")) 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; } x[i] = convert_input_dim(input_line_fields[0]); y[i] = -convert_input_dim(input_line_fields[1]); } if (bad) return(1); /* find the centre and diameter */ if (x[0] == x[1]) { centre_x = x[0]; if (y[0] < y[1]) { diameter = y[1] - y[0]; centre_y = y[0] + diameter / 2; } else if (y[1] < y[0]) { diameter = y[0] - y[1]; centre_y = y[1] + diameter / 2; } else goto centre_diam_fail; } else if (y[0] == y[1]) { centre_y = y[0]; if (x[0] < x[1]) { diameter = x[1] - x[0]; centre_x = x[0] + diameter / 2; } else if (x[1] < x[0]) { diameter = x[0] - x[1]; centre_x = x[1] + 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_x = centre_x; silk_arcs[num_silk_arcs].centre_y = centre_y; 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) { 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].x1 = convert_input_dim(input_line_fields[0]); pins_array[idx].y1 = -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->x2 = pin->x1; pin->y2 = pin->y1; 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->x1 -= delta; pin->x2 += delta; return(0); case 90: pin->y1 -= delta; pin->y2 += 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; /* sanity checks */ if (fpbody.npins < 1) { fprintf(stderr, "%s line %d: # of terminals %d < 1\n", input_filename, input_lineno, fpbody.npins); exit(1); } if (num_padstack_defs < 1) { fprintf(stderr, "%s line %d: # of pad stack defs %d < 1\n", input_filename, input_lineno, num_padstack_defs); exit(1); } /* 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(); /* 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_decal_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(); } }