Generate patch.h for Dan's Chromcord Arduino

The first block is just setup, don't modify it (execute it once):


In [14]:
# Setup, don't modify this
import re
import collections
from pprint import pprint

stencils = collections.OrderedDict()
Patches_Per_Show = 16 # so 1st knob is shows/stencil, 2nd is patch

def make():

    marker = "Generated by ipython patchGenerate"
    output = []
    output.append("// %s:\n" % marker)

    patch_names = []
    for a_stencil in stencils.values():
        output.extend( a_stencil.patch_code_lines() )
    
    # patches[]
    patch_decl = []
    for a_stencil in stencils.values():
        the_patch_names = a_stencil.patch_names()
        # fill out the 16/patch
        for i in range(len(the_patch_names),16):
            the_patch_names.append("empty_patch")

        patch_decl.extend(["patch_%s" % x for x in the_patch_names])

    output.append(
        "const byte** patches[] = {"
        + ", ".join(patch_decl)
        + "};"
        )
    output.append("")

    i=0
    name_list = []
    output.append('const char empty_patch_name[] PROGMEM = "-";')
    for a_stencil in stencils.values():
        the_patch_names = a_stencil.patch_names()
        
        for n in the_patch_names :
            output.append("const char patch_name_%s[] PROGMEM = \"%s\";" % (i,n))
            name_list.append("patch_name_%s" % i)
            i += 1
        
        for empty_i in range(len(the_patch_names),16):
            name_list.append("empty_patch_name")
        
    output.append(
        "PROGMEM char* const patch_names[] = {"
        + ", ".join(name_list)
        + "};"
        )
    
    output.append("const byte Patch_Count = count_of(patches);")
    output.append("// Generated by ipython patchGenerate")
    print "\n".join(output)

the dsl support (execute once)


In [15]:
# for use by "with"
class new_stencil(object):
        current = None
        
        def __init__(self,name):
            self.name = name
            self.patches = collections.OrderedDict()
            new_stencil.current = self
        
        def __enter__(self):
            pass
            
        def __exit__(self,err_type,err_value,traceback):
            # print "exited %s w/%s" % (self,len(self.patches))
            stencils[self.name] = self

        def patch_names(self):
            x=[]
            for a_patch in self.patches.values():
                x.append(a_patch.token_name())
            return x
        
        def patch_code_lines(self):
            lines = []
            for a_patch in self.patches.values():
                lines.extend( a_patch.code_lines())
                lines.append("")
            return lines   
        
class new_patch(object):
        current = None

        def __init__(self,name):
            self.name = name
            self.zones = []
            new_patch.current = self
            self.stencil = new_stencil.current


        def __enter__(self):
            pass
            
        def __exit__(self,err_type,err_value,traceback):
            self.stencil.patches[self.name] = self
            # print "exited %s w/%s" % (self,len(self.zones))

        def token_name(self):
            n = "%s_%s" % (self.stencil.name,self.name)
            n = re.sub('[^a-z0-9_]', '', n, flags=re.IGNORECASE)
            return n
        
        def code_lines(self):
            lines = [ "// Patch '%s' : '%s'" % (self.stencil.name, self.name) ]
            
            zone_maps = []
            for i,zone in enumerate(self.zones):
                if (zone and len(zone)>0):
                    zone_maps.append("patch_%s_z%s" % (self.token_name(),i))
                    array_lit = "{%s,-1}" % ",".join(("%s" % lunit) for lunit in zone)
                    lines.append( 
                        "    const byte patch_%s_z%s[] = %s;"
                        % (
                            self.token_name(), 
                            i,
                            array_lit
                            )
                        )
                else:
                    zone_maps.append('empty_zone')
                    

            zone_lit = ''
            if len(zone_maps) > 0:
                zone_lit = "{%s}" % ", ".join(zone_maps)
            else:
                zone_lit = 'empty_zones'
                
            lines.append(
                "const byte* patch_%s[Zone_Count] = %s;"
                % (
                    self.token_name(), 
                    zone_lit
                    )
                )

            return lines
                
def assign_zone(*lunit_list):
    # print "make zone %s for %s of %s" % (lunit_list, new_patch.current, new_stencil.current)
    if len(lunit_list) and isinstance(lunit_list[0],list):
        new_patch.current.zones.append(lunit_list[0])
    else:
        new_patch.current.zones.append(lunit_list)

Patches Patches are structured as:

  1. Group Name, like "Show 1
  2. Patch name, Like "Squarish #2
  3. A list of the Zones (rgb controllers), 1..4
  4. Each lunit that belongs to the zone

E.g.:

with new_stencil('Show 1'):
    with new_patch('squarish'):
        assign_zone(0,1,2,3,4,5)
        assign_zone(6,7,8)
        assign_zone(range(9,16))
        assign_zone()
    with new_patch('center'):
        assign_zone(0,1,2,3,5,8,9,11,12,13,14,15)
        assign_zone(4,7,10)
        assign_zone()
        assign_zone()  
    with new_patch('squarish #2'):
        assign_zone(0,1,2,3,4,5)
        assign_zone(6,7,8)
        assign_zone(range(9,16))
        assign_zone([])

with new_stencil('Show 2'):
    with new_patch('cross'):
        assign_zone(0,1,2,3,5,8,9,11,12,13,14,15)
        assign_zone([])
        assign_zone([])
        assign_zone(4,7,10)

Keeps the order you specify.


In [16]:
# Edit, and Run to check

Run this to make the C++ code:


In [17]:
# Run this and paste result into patches.h
#------------------------------------------------
# 2016-10-26_RiverBend
with new_stencil('Test'):
    with new_patch('Test-00'):
        assign_zone(0,5,10)
        assign_zone(1,6,11) 
        assign_zone(2,7,12)
        assign_zone(3,8,13)       
    with new_patch('Test-01'):
        assign_zone(0,1,2,3,4)
        assign_zone(5,6,8,9) 
        assign_zone(10,11,13,14)
        assign_zone(7,12)     
    with new_patch('Test-02'):
        assign_zone(4,9,14)
        assign_zone(11,12,13) 
        assign_zone(4,9,14) 
        assign_zone(1,2,5,8,10)
    with new_patch('Test-03'):
        assign_zone(4,9,14) 
        assign_zone(11,12,13) 
        assign_zone(1,2,3,6,7,8) 
        assign_zone(0,5,10)
        
with new_stencil('Tester'):        
    with new_patch('Tester-01'):
        assign_zone(1,3,8,13,14) 
        assign_zone(4,5,9,10,11) 
        assign_zone(0,6) 
        assign_zone(2,7,12)
    with new_patch('Tester-02'):
        assign_zone(3,8,13,14)
        assign_zone(5,7,10,11,12)
        assign_zone(6,2,9)
        assign_zone(0,1,4)
    with new_patch('Tester-03'):
        assign_zone(1,3,5,8,13)
        assign_zone(0,2,7,10,11,12)
        assign_zone(6,14)
        assign_zone(4,9)   
    with new_patch('Tester-04'):
        assign_zone(1,5,8,13)
        assign_zone(0,3,4,7,9,12)
        assign_zone(6)
        assign_zone(2,10,11,14)
        
with new_stencil('Tester2'):           
        
    with new_patch('Tester2-01'):
        assign_zone(1,3,5,8,13,14)
        assign_zone(0,4,7,9,10,11,12) 
        assign_zone(6)
        assign_zone(2)
    with new_patch('Tester2-02'):
        assign_zone(1,5,8,13)
        assign_zone(0,3,7,12)
        assign_zone(4,6,10,14)
        assign_zone(2,9,11)
    with new_patch('Tester2-03'):
        assign_zone(1,3,5,8,13)
        assign_zone(0,7,12)
        assign_zone(4,6,10,14)
        assign_zone(2,9,11)
    with new_patch('Tester2-04'):
        assign_zone(1,3,8,13)
        assign_zone(0,4,7,9,11,12)
        assign_zone(6,14)
        assign_zone(2,5,10)  



#-----------------------------------------

make()


// Generated by ipython patchGenerate:

// Patch 'Test' : 'Test-00'
    const byte patch_Test_Test00_z0[] = {0,5,10,-1};
    const byte patch_Test_Test00_z1[] = {1,6,11,-1};
    const byte patch_Test_Test00_z2[] = {2,7,12,-1};
    const byte patch_Test_Test00_z3[] = {3,8,13,-1};
const byte* patch_Test_Test00[Zone_Count] = {patch_Test_Test00_z0, patch_Test_Test00_z1, patch_Test_Test00_z2, patch_Test_Test00_z3};

// Patch 'Test' : 'Test-01'
    const byte patch_Test_Test01_z0[] = {0,1,2,3,4,-1};
    const byte patch_Test_Test01_z1[] = {5,6,8,9,-1};
    const byte patch_Test_Test01_z2[] = {10,11,13,14,-1};
    const byte patch_Test_Test01_z3[] = {7,12,-1};
const byte* patch_Test_Test01[Zone_Count] = {patch_Test_Test01_z0, patch_Test_Test01_z1, patch_Test_Test01_z2, patch_Test_Test01_z3};

// Patch 'Test' : 'Test-02'
    const byte patch_Test_Test02_z0[] = {4,9,14,-1};
    const byte patch_Test_Test02_z1[] = {11,12,13,-1};
    const byte patch_Test_Test02_z2[] = {4,9,14,-1};
    const byte patch_Test_Test02_z3[] = {1,2,5,8,10,-1};
const byte* patch_Test_Test02[Zone_Count] = {patch_Test_Test02_z0, patch_Test_Test02_z1, patch_Test_Test02_z2, patch_Test_Test02_z3};

// Patch 'Test' : 'Test-03'
    const byte patch_Test_Test03_z0[] = {4,9,14,-1};
    const byte patch_Test_Test03_z1[] = {11,12,13,-1};
    const byte patch_Test_Test03_z2[] = {1,2,3,6,7,8,-1};
    const byte patch_Test_Test03_z3[] = {0,5,10,-1};
const byte* patch_Test_Test03[Zone_Count] = {patch_Test_Test03_z0, patch_Test_Test03_z1, patch_Test_Test03_z2, patch_Test_Test03_z3};

// Patch 'Tester' : 'Tester-01'
    const byte patch_Tester_Tester01_z0[] = {1,3,8,13,14,-1};
    const byte patch_Tester_Tester01_z1[] = {4,5,9,10,11,-1};
    const byte patch_Tester_Tester01_z2[] = {0,6,-1};
    const byte patch_Tester_Tester01_z3[] = {2,7,12,-1};
const byte* patch_Tester_Tester01[Zone_Count] = {patch_Tester_Tester01_z0, patch_Tester_Tester01_z1, patch_Tester_Tester01_z2, patch_Tester_Tester01_z3};

// Patch 'Tester' : 'Tester-02'
    const byte patch_Tester_Tester02_z0[] = {3,8,13,14,-1};
    const byte patch_Tester_Tester02_z1[] = {5,7,10,11,12,-1};
    const byte patch_Tester_Tester02_z2[] = {6,2,9,-1};
    const byte patch_Tester_Tester02_z3[] = {0,1,4,-1};
const byte* patch_Tester_Tester02[Zone_Count] = {patch_Tester_Tester02_z0, patch_Tester_Tester02_z1, patch_Tester_Tester02_z2, patch_Tester_Tester02_z3};

// Patch 'Tester' : 'Tester-03'
    const byte patch_Tester_Tester03_z0[] = {1,3,5,8,13,-1};
    const byte patch_Tester_Tester03_z1[] = {0,2,7,10,11,12,-1};
    const byte patch_Tester_Tester03_z2[] = {6,14,-1};
    const byte patch_Tester_Tester03_z3[] = {4,9,-1};
const byte* patch_Tester_Tester03[Zone_Count] = {patch_Tester_Tester03_z0, patch_Tester_Tester03_z1, patch_Tester_Tester03_z2, patch_Tester_Tester03_z3};

// Patch 'Tester' : 'Tester-04'
    const byte patch_Tester_Tester04_z0[] = {1,5,8,13,-1};
    const byte patch_Tester_Tester04_z1[] = {0,3,4,7,9,12,-1};
    const byte patch_Tester_Tester04_z2[] = {6,-1};
    const byte patch_Tester_Tester04_z3[] = {2,10,11,14,-1};
const byte* patch_Tester_Tester04[Zone_Count] = {patch_Tester_Tester04_z0, patch_Tester_Tester04_z1, patch_Tester_Tester04_z2, patch_Tester_Tester04_z3};

// Patch 'Tester2' : 'Tester2-01'
    const byte patch_Tester2_Tester201_z0[] = {1,3,5,8,13,14,-1};
    const byte patch_Tester2_Tester201_z1[] = {0,4,7,9,10,11,12,-1};
    const byte patch_Tester2_Tester201_z2[] = {6,-1};
    const byte patch_Tester2_Tester201_z3[] = {2,-1};
const byte* patch_Tester2_Tester201[Zone_Count] = {patch_Tester2_Tester201_z0, patch_Tester2_Tester201_z1, patch_Tester2_Tester201_z2, patch_Tester2_Tester201_z3};

// Patch 'Tester2' : 'Tester2-02'
    const byte patch_Tester2_Tester202_z0[] = {1,5,8,13,-1};
    const byte patch_Tester2_Tester202_z1[] = {0,3,7,12,-1};
    const byte patch_Tester2_Tester202_z2[] = {4,6,10,14,-1};
    const byte patch_Tester2_Tester202_z3[] = {2,9,11,-1};
const byte* patch_Tester2_Tester202[Zone_Count] = {patch_Tester2_Tester202_z0, patch_Tester2_Tester202_z1, patch_Tester2_Tester202_z2, patch_Tester2_Tester202_z3};

// Patch 'Tester2' : 'Tester2-03'
    const byte patch_Tester2_Tester203_z0[] = {1,3,5,8,13,-1};
    const byte patch_Tester2_Tester203_z1[] = {0,7,12,-1};
    const byte patch_Tester2_Tester203_z2[] = {4,6,10,14,-1};
    const byte patch_Tester2_Tester203_z3[] = {2,9,11,-1};
const byte* patch_Tester2_Tester203[Zone_Count] = {patch_Tester2_Tester203_z0, patch_Tester2_Tester203_z1, patch_Tester2_Tester203_z2, patch_Tester2_Tester203_z3};

// Patch 'Tester2' : 'Tester2-04'
    const byte patch_Tester2_Tester204_z0[] = {1,3,8,13,-1};
    const byte patch_Tester2_Tester204_z1[] = {0,4,7,9,11,12,-1};
    const byte patch_Tester2_Tester204_z2[] = {6,14,-1};
    const byte patch_Tester2_Tester204_z3[] = {2,5,10,-1};
const byte* patch_Tester2_Tester204[Zone_Count] = {patch_Tester2_Tester204_z0, patch_Tester2_Tester204_z1, patch_Tester2_Tester204_z2, patch_Tester2_Tester204_z3};

const byte** patches[] = {patch_Test_Test00, patch_Test_Test01, patch_Test_Test02, patch_Test_Test03, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_Tester_Tester01, patch_Tester_Tester02, patch_Tester_Tester03, patch_Tester_Tester04, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_Tester2_Tester201, patch_Tester2_Tester202, patch_Tester2_Tester203, patch_Tester2_Tester204, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch, patch_empty_patch};

const char empty_patch_name[] PROGMEM = "-";
const char patch_name_0[] PROGMEM = "Test_Test00";
const char patch_name_1[] PROGMEM = "Test_Test01";
const char patch_name_2[] PROGMEM = "Test_Test02";
const char patch_name_3[] PROGMEM = "Test_Test03";
const char patch_name_4[] PROGMEM = "Tester_Tester01";
const char patch_name_5[] PROGMEM = "Tester_Tester02";
const char patch_name_6[] PROGMEM = "Tester_Tester03";
const char patch_name_7[] PROGMEM = "Tester_Tester04";
const char patch_name_8[] PROGMEM = "Tester2_Tester201";
const char patch_name_9[] PROGMEM = "Tester2_Tester202";
const char patch_name_10[] PROGMEM = "Tester2_Tester203";
const char patch_name_11[] PROGMEM = "Tester2_Tester204";
PROGMEM const char *patch_names[] = {patch_name_0, patch_name_1, patch_name_2, patch_name_3, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, patch_name_4, patch_name_5, patch_name_6, patch_name_7, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, patch_name_8, patch_name_9, patch_name_10, patch_name_11, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name, empty_patch_name};
const byte Patch_Count = count_of(patches);
// Generated by ipython patchGenerate

And Paste

the above result into patches.h, replacing the section:

// Generated by ....
...
// End Generatted by ...

In [ ]: