#!/usr/bin/perl use strict; use warnings; use GD; use Getopt::Long qw/:config auto_help gnu_getopt bundling/; use File::Slurp; use Pod::Usage; use List::Util qw/max min/; use Data::Dumper; use feature qw(switch); use GdUtil qw/:all/; use PTouchOut; use YAML; my $outfile; # tape width in mm my $pin_spacing = 2.54; # mm my $offset = 1.0; # mm my $all = 0; my @chip; my $tech; my $invert = 0; PTouchOut::defaults(width => 6); GetOptions( PTouchOut->opts, "o=s" => \$outfile, "c=s" => \@chip, "a" => \$all, "t" => \$tech, "i" => \$invert, ) or die "invalid options"; my %yaml; sub loadFile { my $yaml = YAML::LoadFile($_[0]) or die "$!: $_[0]"; my $family = $yaml->{family}; delete $yaml->{family}; for (keys %$yaml) { $yaml->{$_}{family} = $family if defined $family; $yaml->{$_}{key} = $_; } %yaml = (%yaml, %$yaml); } sub loadChipDbFile { print(STDERR "$!: $_[0]\n"),return unless -e $_[0]; my $data = read_file($_[0]); my $name = $_[0]; $name =~ s/^(.*\/)?(.*)\.yaml$/$2/; $data =~ s/^\.\.\.$//m; my $yaml = YAML::Load($data); my $count = $yaml->{pincount}; my @pins = ("N/C") x $count; for my $h (@{$yaml->{pins}}) { $pins[$h->{num} - 1] = $h->{sym}; } map { if (/\~/) { s/\~//g; s/^/\// } } @pins; my %n = ($name => { key => $name, name => undef, npins => $count, pins => \@pins, family => $yaml->{family}}); # print Dumper(\%n); %yaml = (%yaml, %n); } map { loadChipDbFile "chipdb-master/$_.yaml" } qw/4017 4013 7474 4093 4516/; map { loadFile "chips/$_.yaml" } qw/misc 4000 7400 power display chips mcu opamps/; my %family; for (values %yaml) { $family{$_->{family}}{$_->{key}} = $_ if exists $_->{family}; } my $height = PTouchOut->pixels; sub genchip { my ($ch) = @_; my @pins; my $name = $ch; if (!exists $yaml{$ch}) { # attempt to generate appropriate one. if ($ch =~ /^(([57]4[a-zA-Z]{1,3})|MC1|CD)(.*)$/) { my $p = $3; # printf "$ch $p $1\n"; if ($p =~ /^4[0-9]{3}$/) { if (exists $family{4000}{$p}) { @pins = @{$family{4000}{$p}{pins}}; map { s/^Vss$/GND/ } @pins unless $ch =~ /^MC/; map { s/^Vdd$/Vcc/ } @pins unless $ch =~ /^MC/; } } else { if (exists $yaml{"74$p"}) { $ch = "74$p"; @pins = @{$yaml{$ch}{pins}}; } } } } else { @pins = @{$yaml{$ch}{pins}}; $name = $ch; } if (defined($yaml{$ch}{npins}) and ($yaml{$ch}{npins} + 0) != scalar @pins) { print "pin mismatch."; print Dumper $yaml{$ch}; return; } my $lname = $name; my $type = $yaml{$ch}{type} // 'dil'; @pins = (@pins,@pins) if $type eq 'sil'; $lname = "$name $yaml{$ch}{name}" if defined $yaml{$ch}{name}; print join " ", $lname, @pins, "\n"; @pins or (print Dumper $yaml{$ch}) and die "no pins!"; return if defined $yaml{$ch}{status} && $yaml{$ch}{status} eq 'disable'; my $canvas = GD::Image->new(PTouchOut->mmtopix($offset*2 + $pin_spacing * (@pins/2 - 1)), $height); $canvas->useFontConfig(1); my $bg = $canvas->colorAllocate(255,255,255); my $fg = $canvas->colorAllocate(0,0,0); # pin 0 unless (defined $yaml{$ch}{name} and $yaml{$ch}{name} eq '_none_') { $canvas->filledRectangle(0,$height / 2 - 3, 3, $height / 2 + 3,$fg); my $inv = $invert ? -3 : 0; $canvas->filledRectangle(3,$height / 2 + -3*$invert, 6, $height / 2 + -3*$invert + 3,$fg); } my $cx = PTouchOut->mmtopix($offset); for my $pl (1 .. @pins / 2) { my $pr = @pins - $pl + 1; if ($invert) { ($pl, $pr) = ($pr, $pl); } sub dpin { my ($cx,$canvas,$pn,$lr,$yml) = @_; my $bar = $pn =~ s/^\///; my $t = drawtext2($pn, font => GD::Font->Tiny, overbar => $bar ); if (exists $yml->{rotation} and $yml->{rotation} == 90) { $t = $t->copyRotate90(); } else { $t = $t->copyRotate270(); } my $padding = $yml->{padding} // 0; my ($tw,$th) = $t->getBounds(); $canvas->copy($t,$cx - $tw / 2 ,$lr ? ($height - $th) -$padding : $padding,0,0,$tw,$th); } dpin $cx,$canvas,$pins[$pr - 1],1,$yaml{$ch}; dpin $cx,$canvas,$pins[$pl - 1],0,$yaml{$ch} unless ($yaml{$ch}{type} // '') eq 'sil'; $cx += PTouchOut->mmtopix($pin_spacing); } unless (defined $yaml{$ch}{name} and $yaml{$ch}{name} eq '_none_') { my $nc = drawtext2($lname, font => GD::Font->Tiny); my ($tw,$th) = $nc->getBounds(); $canvas->copy($nc,11,($height - $th) / 2,0,0,$tw,$th); } $name = "r_$name" if $invert; PTouchOut->output($canvas, lc "out/$name.png"); } genchip($_) for @chip; if ($all) { genchip($_) foreach keys %yaml; } __END__ =head1 SYNOPSIS Options: --help brief help message -w n specify tape width in mm -c chip chip name as specified in chips.yaml -a generate pngs for all chips in the file -t (hc,ttl,ac,cd) technology of 74 or 4000 series logic -i invert label, for dead bug soldering. output placed in out/ directory.