view pads2gpcb/decals.c @ 49:b3b7013d9228

pads2gpcb.c/decals.c: allow underscores in written decal file names
author Mychaela Falconia <falcon@ivan.Harhan.ORG>
date Sat, 30 Jan 2016 17:38:47 +0000
parents c977d637f038
children 727d4e56d5c8
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	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 void
one_drawing_piece()
{
	int ncoord, i;

	/* just skip it for now */
	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);
	}
	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;

	/* 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 */
		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();
	}
}