summaryrefslogtreecommitdiff
path: root/EagleNamePositions/change_positions_noms.py
blob: 51581d41e1e9af61e4f7da8084f62e01f33f3587 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/python
#
# Ce programme Python extrait les noms ayant des differences entre les fichiers
# cible.pn et positions.pn, et genere un script Eagle donnant aux noms du board
# courant (qui doit correspondre avant execution du script a cible.pn) les
# positions de positions.pn.
#
# L'ULP PositionName.ulp permet de creer les fichiers .pn en question.
#
# Pour resumer un cycle complet de positionnement :
#
# - Une version est fournie a Steven Naheulbeuk.
# - Steven Naheulbeuk place les noms et lance l'ULP qui produit un truc.pn
# - Steven Naheulbeuk renomme truc.pn en positions.pn et envoie positions.pn
#   a Dieu
# - Pour integrer les positions, Dieu lance l'ULP et renomme truc.pn en
#   cible.pn puis IMMEDIATEMENT SANS TOUCHER A LA BOARD lance ce script
#   python qui genere regle_positions.scr puis TOUJOURS IMMEDIATEMENT
#   SANS TOUCHER A LA BOARD execute le script sous Eagle.
# - Comme Dieu veut eviter de se tromper, il detruit alors positions.pn,
#   cible.pn et regle_positions.scr pour eviter d'utiliser des versions
#   erronees de ces fichiers dans le futur. (Si Dieu est de plus parano,
#   il peut a la place de les detruire les archiver/versionner a un autre
#   endroit.)
#
# ATTENTION : le script genere change l'etat de la board sur les points
# suivants en plus de la position des noms :
#   - passage de la grille en microns
#   - passage de la grille alternative en microns
#   - passage de la grille alternative en "finest" (0.1 mic)
#   - a la fin de l'execution du script, seul le layer bNames est affiche

path = "/home/huytin/Stage/misc/EagleNamePositions/"

target_filename = path + "cible.pn"
positions_filename = path + "positions.pn"

script_filename = path + "regle_positions.scr"



from collections import namedtuple
import re

NDesc = namedtuple('NDesc', 'layer name value x y angle size mirror ratio')

TOP_LAYER_NAME = 'tnames'
BOTTOM_LAYER_NAME = 'bnames'
layers = {'25': TOP_LAYER_NAME, '26': BOTTOM_LAYER_NAME}

def load_pn(pn_filename):
    r = {}
    f = open(pn_filename)
    first_line = f.readline()
    if not first_line.startswith("T.layer"):
        raise ValueError("invalid file format -- "
                         + "first line does not start with 'T.layer': %s"
                           % first_line)
    for line in f:
        line = line.strip()
        if not line:
            continue
        elems = re.split("[ ]{1,8}", line)
        if elems[0] not in layers:
            print "warning: unknown layer, ignoring line:", line
            continue
        layer = layers[elems[0]]
        name = elems[1]
        value = elems[2]
        if name in r:
            print "warning: %s already loaded, ignoring line: %s" % (name, line)
        nd = NDesc(layer, name, value, *[int(x) for x in elems[3:]])
        r[name] = nd
    f.close()
    return r

print "loading %s" % target_filename
target = load_pn(target_filename)

print "loading %s" % positions_filename
positions = load_pn(positions_filename)

def deci(i):
    return "%d.%d" % (i / 10, i % 10)

def deci_mic_pos(desc):
    # AC means: DIE EAGLE, DIE! For real it means Ctrl+Alt;
    #  Ctrl: select the object origin
    #  Alt: use the alternate grid, which has been configured
    #       to FINEST (0.1 mic)                                   xref1
    return '(AC %s %s)' % (deci(desc.x), deci(desc.y))

def gen_script(pos, tgt, scr_fn):
    script = open(scr_fn, "w")
    try:
        pos_top = [v for v in pos.itervalues()
                   if v.layer == TOP_LAYER_NAME]
        pos_bot = [v for v in pos.itervalues()
                   if v.layer == BOTTOM_LAYER_NAME]
        script.write("set undo off;\n")
        script.write("grid mic;\n")
        script.write("grid alt mic;\n")
        script.write("grid alt finest;\n\n\n")                   # xref1
        def one_layer(pos_list, layer_name):
            mirror_char = 'M' if layer_name == BOTTOM_LAYER_NAME else ''
            script.write("display none;\n")
            script.write("display %s;\n\n\n" % layer_name)
            for dest in pos_list:
                if dest.name not in tgt:
                    print "warning: name %s not in target" % dest.name
                    continue
                tgt_desc = tgt[dest.name]
                if dest != tgt_desc:
                    script.write("move %s %s;\n"
                                 % (deci_mic_pos(tgt_desc), deci_mic_pos(dest)))
                    script.write("rotate =%sR%d %s;\n"
                                 % (mirror_char,
                                    dest.angle,
                                    deci_mic_pos(dest)))
                    script.write("change size %s %s;\n"
                                 % (deci(dest.size), deci_mic_pos(dest)))
                    script.write("change ratio %d %s;\n"
                                 % (dest.ratio, deci_mic_pos(dest)))
                    script.write("\n")
            script.write("\n\n\n")
        one_layer(pos_top, TOP_LAYER_NAME)
        one_layer(pos_bot, BOTTOM_LAYER_NAME)
        script.write("\n\n\nset undo on;\n")
    finally:
        script.close()

print "writing %s" % script_filename
gen_script(positions, target, script_filename)