Commits

saar drimer committed 5d314a1

added the ability to automatically renumber refdets four different ways

Comments (0)

Files changed (2)

     argp = argparse.ArgumentParser(description=description, 
                       add_help=True, version=pcbmode_version, epilog=epilog)
      
-    #me_group = argp.add_mutually_exclusive_group()
-
     argp.add_argument('-b', '--board-name',
                       dest='boards', required=True, nargs=1,
                       help='Makes the specified board. The location of the files should be specified in the configuration file, otherwise defaults will be used')
                       action='store_true', dest='extract', default=False,
                       help="Extract routing and component placement from the design's SVG")
      
-    argp.add_argument('-fab', '--fab', nargs='?',
+    argp.add_argument('--fab', nargs='?',
                       dest='fab', default=False,
                       help='Generate manufacturing files (Gerbers, Excellon, etc.)')
 
                       action='store_true', dest='no_layer_index', default=False,
                       help='Do not add layer index to Gerbers')
 
+    argp.add_argument('--renumber-refdefs', nargs='?',
+                      dest='renumber', default=False,
+                      help="Renumber refdefs (valid options are 'top_to_bottom', 'bottom_to_top', 'left_to_right', 'right_to_left'")
+
 #    argp.add_argument('-z', '--zip',
 #                      action='store_true', dest='zip', default=False,
 #                      help='Zip manufacturing files')    
+
+    #me_group = argp.add_mutually_exclusive_group()
+
         
     return argp
 
 
 
 
+
 def create_board_configuration(board_name, version, cmdline_args):
     """
     Returns a dictionary of configuration data based on content
     cmdline_args = argp.parse_args()
 
     for board_name in cmdline_args.boards:
-        #pcbmode_cfg, board_cfg, layout_style = create_global_parameters(board_name)
         cfg = create_board_configuration(board_name, pcbmode_version, cmdline_args)
 
     # check if build directory exists; if not, create
     build_dir = os.path.join(cfg['base_dir'], cfg['pcbmode']['locations']['build'])
     utils.create_dir(build_dir)
 
+    # renumber refdefs and dump board config file
+    if cmdline_args.renumber is not False:
+        print "-- renumbering refdefs"
+        if cmdline_args.renumber is None:
+            order = 'top_to_bottom'
+        else:
+            order = cmdline_args.renumber.lower()    
+
+        utils.renumber_refdefs(cfg, order)
+
     # extract routing from input SVG file
-    if cmdline_args.extract is True:
+    elif cmdline_args.extract is True:
         print "-- extracting routing and placement"
         extract.extract_from_svg(cfg)
 
-    # make the board
-    if cmdline_args.make is True:
-        print "-- creating board"
-        board.create_board(cfg) 
-
-    
-    if cmdline_args.fab is not False:
-        if cmdline_args.fab is None:
-            manufacturer = 'default'
-        else:
-            manufacturer = cmdline_args.fab.lower()
-
-        print "-- creating Gerbers"
-        print "files:",
-        gerber_filenames = gerber.gerberise(cfg, manufacturer)
-        print
-        print "-- creating drill file(s)"
-        print "files:",
-        drill_filenames = excellon.make_excellon(cfg, manufacturer)
-        print
-
-        filenames = gerber_filenames + drill_filenames
-
-        # create a readme file
-        readme = open(os.path.join(cfg['base_dir'],
-                                    cfg['pcbmode']['locations']['build'], 
-                                    'production', 'README.txt'), 'w')
-
-        readme.write("The following files are included in this archive:\n")
-        for f in filenames:
-            readme.write("%s\n" % os.path.basename(f))
-        readme.write("\n")
-        readme.write("Please refer to the docoumentation Gerber file for manufacturing instructions.")
-        readme.write("\n")
-        readme.close()
-
-        
-#        if cmdline_args.zip is True:
-# 
-#            filenames = gerber_filenames + drill_filenames
-# 
-#            board_name = cfg['board_name']
-#            board_revision = cfg['board']['meta'].get('board_revision') or 'A'
-#            base_dir = os.path.join(cfg['base_dir'], 
-#                                    cfg['pcbmode']['locations']['build'], 
-#                                    'production')
-#            base_name = "%s_rev_%s" % (board_name, board_revision)
-# 
-#            zip_name = base_name + '.zip'
-# 
-#            print "-- creating zip of manufacturing files"
-#            utils.zip_files(base_dir, zip_name, filenames)
-
-
-
-    if cmdline_args.pngs is True:
-        print "-- creating PNGs"
-        utils.create_pngs(cfg)
+    else:
+        # make the board
+        if cmdline_args.make is True:
+            print "-- creating board"
+            board.create_board(cfg) 
      
-    
-    if cmdline_args.bom is True:
-        print "-- creating BOM (not implemented yet!)"
-        pass
+        # create files required for fab
+        if cmdline_args.fab is not False:
+            if cmdline_args.fab is None:
+                manufacturer = 'default'
+            else:
+                manufacturer = cmdline_args.fab.lower()
+     
+            print "-- creating Gerbers"
+            print "files:",
+            gerber_filenames = gerber.gerberise(cfg, manufacturer)
+            print
+            print "-- creating drill file(s)"
+            print "files:",
+            drill_filenames = excellon.make_excellon(cfg, manufacturer)
+            print
+     
+            filenames = gerber_filenames + drill_filenames
+     
+            # create a readme file
+            readme = open(os.path.join(cfg['base_dir'],
+                                        cfg['pcbmode']['locations']['build'], 
+                                        'production', 'README.txt'), 'w')
+     
+            readme.write("The following files are included in this archive:\n")
+            for f in filenames:
+                readme.write("%s\n" % os.path.basename(f))
+            readme.write("\n")
+            readme.write("Please refer to the docoumentation Gerber file for manufacturing instructions.")
+            readme.write("\n")
+            readme.close()
+     
+    #        if cmdline_args.zip is True:
+    # 
+    #            filenames = gerber_filenames + drill_filenames
+    # 
+    #            board_name = cfg['board_name']
+    #            board_revision = cfg['board']['meta'].get('board_revision') or 'A'
+    #            base_dir = os.path.join(cfg['base_dir'], 
+    #                                    cfg['pcbmode']['locations']['build'], 
+    #                                    'production')
+    #            base_name = "%s_rev_%s" % (board_name, board_revision)
+    # 
+    #            zip_name = base_name + '.zip'
+    # 
+    #            print "-- creating zip of manufacturing files"
+    #            utils.zip_files(base_dir, zip_name, filenames)
+     
+        if cmdline_args.pngs is True:
+            print "-- creating PNGs"
+            utils.create_pngs(cfg)
+         
+        
+        if cmdline_args.bom is True:
+            print "-- creating BOM (not implemented yet!)"
+            pass
      
     print "-- Done!"
 
 import zipfile
 import subprocess as subp # for shell commands
 import math
+from operator import itemgetter # for sorting lists by dict value
 
 # pcbmode modules
 from Point import Point
 
 
 
+
+
 def get_json_data_from_file(filename):
     """
     Open a json file and returns its content as a dict
     angle = -angle
 
     return coord, angle, scale
+
+
+
+
+
+def renumber_refdefs(cfg, order):
+    """
+    Renumber the refdefs in the specified order
+    """
+
+    regex = r'^(?P<t>[a-zA-z\D]+?)(?P<n>\d+)(?P<e>[\-\s].*)?'
+    components = cfg['board']['placement']['components']
+    record_start_values = {}
+
+    # put all components in a list
+    for layer in components:
+        new_dict = {}
+        comp_lists = {}
+        for refdef in components[layer]:
+
+            # split the refdef into components
+            parse = re.match(regex, refdef)
+
+            if comp_lists.get(parse.group('t')) is None:
+                comp_lists[parse.group('t')] = []
+
+            location = to_Point(components[layer][refdef].get('location') or [0, 0])
+            tmp = {}
+            tmp['record'] = components[layer][refdef]
+            tmp['type'] = parse.group('t')
+            tmp['number'] = parse.group('n')
+            tmp['extra'] = parse.group('e')
+            tmp['coord_x'] = location.x
+            tmp['coord_y'] = location.y
+            comp_lists[parse.group('t')].append(tmp)
+
+        # sort list according to desired 'order'
+        for comp_type in comp_lists:
+           if order == 'left_to_right':
+               reverse = False
+               itemget_param = 'coord_x'
+           elif order == 'right_to_left':
+               reverse = True
+               itemget_param = 'coord_x'
+           elif order == 'top_to_bottom':
+               reverse = True
+               itemget_param = 'coord_y'
+           elif order == 'bottom_to_top':
+               reverse = False
+               itemget_param = 'coord_y'
+           else:
+               print 'ERROR: unrecognised renumbering order %s' % (order) 
+
+           sorted_list = sorted(comp_lists[comp_type], 
+                                key=itemgetter(itemget_param), 
+                                reverse=reverse)
+
+           if record_start_values.get(comp_type) is None:
+               record_start_values[comp_type] = 1
+           for i, record in enumerate(sorted_list, start=record_start_values[comp_type]):
+               new_refdef = "%s%s" % (record['type'], i)
+               if record['extra'] is not None:
+                   new_refdef += "%s" % (record['extra'])
+               new_dict[new_refdef] = record['record']
+           record_start_values[comp_type] = i+1
+
+        components[layer] = new_dict
+
+    try:
+        f = open(cfg['board']['config_filename'], 'wb')
+    except IOError as e:
+        print "I/O error({0}): {1}".format(e.errno, e.strerror)
+
+    f.write(json.dumps(cfg['board'], sort_keys=True, indent=2))
+    f.close()       
+