def xy_sequencer(start_x, start_y, stroke_height, stroke_spacing, n_strokes,
            both_directions=True):
    """
    xy_sequencer generates a list of tuples specifying the x,y coordinates of
    the path that the LU20 sampler must follow. 

    This path has two forms. The first form, where both_directions=True is a
    sideways "S" shape in which the sample moves in vertical strokes and at the
    end of each stroke, increments in the horizontal axes. 

    The second form, where both_directions=False looks like a comb. In this
    form, the sample moves vertically (following the magnitude and direction of
    stroke height) first. It then reverses this motion, returning to the
    original height BEFORE incrementing horizontally and beginning the next
    stroke.

    The last coordinate in the sequence guarantees that the sample returns to
    its original y axis position, with its x axis prepped for the next vertical
    stroke.

    Parameters
    ----------
    start_x : float
        Initial X coordinate of the motion. The first stroke will begin
        immediately from this point.

    start_y : float
        Initial Y coordinate of the motion. The first stroke will begin
        immediately from this point.

    stroke_height : float
        Set the distance of the total y-axis stroke.

    stroke_spacing : float
        Set the horicontal (x-axis) distance between vertical strokes.

    n_strokes : float
        Number of vertical strokes to complete.

    both_directions : bool, optional
        Defaults to True. If this is True, follow the "S" shaped motion path.
        Otherwise follow the comb shaped motion path. 
    
    Returns
    -------
    list of tuples
        This is the list of (x,y) coordinates defining the path for the sample.
        The 0th indexed coordinate is the initial position.

    """
    coord_list = []
    coord_list.append((start_x,start_y))

    direction = 1
    for x in range(n_strokes):
        # vertical stroke
        new_x = coord_list[-1][0]
        new_y = coord_list[-1][1] + (direction * stroke_height)
        coord_list.append((new_x,new_y))
        # flip direction for the next stroke if both directions are used
        if both_directions:
            direction *= -1

        # second vertical stroke if only one direction is allowed
        if not both_directions:
            new_x = coord_list[-1][0]
            new_y = coord_list[-1][1] - (direction * stroke_height)
            coord_list.append((new_x,new_y))

        # horizontal stroke
        new_x = coord_list[-1][0] + stroke_spacing
        new_y = coord_list[-1][1]
        coord_list.append((new_x,new_y))
        
    # reset move for next set 
    new_x = coord_list[0][0] + n_strokes * stroke_spacing
    new_y = coord_list[0][1]
    coord_list.append((new_x,new_y))
    
    return coord_list