Exemplo n.º 1
0
def entertower(layer_hght):
    purgeheight = layer_hght - v.cur_tower_z_delta

    if v.current_position_z != purgeheight:
        v.max_tower_delta = max(v.cur_tower_z_delta, v.max_tower_delta)
        gcode.issue_code(";------------------------------", True)
        gcode.issue_code(";  P2PP DELTA ENTER", True)
        gcode.issue_code(
            ";  Current printing Z = {:.2f}".format(v.current_position_z),
            True)
        gcode.issue_code(";  Tower Z = {:.2f}".format(purgeheight), True)
        gcode.issue_code(
            ";  Delta = {:.2f} ".format(v.current_position_z - purgeheight),
            True)
        gcode.issue_code(";------------------------------", True)

        if v.retraction >= 0:
            purgetower.retract(v.current_tool)

        if v.manual_filament_swap:
            swap.swap_pause("M25")
            # unpause z-move is not required

        gcode.issue_code("G1 X{} Y{} F8640".format(v.current_position_x,
                                                   v.current_position_y))
        gcode.issue_code("G1 Z{:.2f} F10810".format(purgeheight))

        if purgeheight <= (v.first_layer_height +
                           0.02):  # FIRST LAYER PURGES SLOWER
            gcode.issue_code("G1 F{}".format(min(1200, v.wipe_feedrate)))
        else:
            gcode.issue_code("G1 F{}".format(v.wipe_feedrate))

        v.disable_z = True
Exemplo n.º 2
0
def create_sidewipe_bb3d(length):

    # purge blobs should all be same size
    if v.bigbrain3d_matrix_blobs and v.bigbrain3d_last_toolchange >= 0:
        filin = int(v.bigbrain3d_last_toolchange / 10)
        filout = v.bigbrain3d_last_toolchange % 10
        matidx = filin * v.colors + filout
        purgeblobs = int(v.wiping_info[matidx])
        correction = 0
        length = purgeblobs * v.mechpurge_blob_size
    else:
        purgeleft = length % v.mechpurge_blob_size
        purgeblobs = int(length / v.mechpurge_blob_size)

        if purgeleft > 1:
            purgeblobs += 1

        correction = v.mechpurge_blob_size * purgeblobs - length

    if v.single_blob:
        purgeblobs = 1
        correction = 0

    issue_code(";-------------------------------", True)
    issue_code("; P2PP BB3DBLOBS: {:.0f} BLOB(S)".format(purgeblobs), True)
    issue_code(";-------------------------------", True)

    issue_code("; Req={:.2f}mm  Act={:.2f}mm".format(length,
                                                     length + correction))
    issue_code("; Purge difference {:.2f}mm".format(correction))
    issue_code(";-------------------------------")

    if v.retraction == 0:
        purgetower.largeretract(v.mechpurge_retract)

    keep_xpos = v.current_position_x
    keep_ypos = v.current_position_y

    if v.retraction > -v.mechpurge_retract:
        diff = -v.mechpurge_retract - v.retraction
        issue_code("\nG1 E{:.3f}   ; retract to -{}mm".format(
            diff, v.mechpurge_retract))

    if v.bigbrain3d_y_position is not None:
        issue_code(
            "\nG1 Y{:.3f} F8640    ; change Y position to purge equipment".
            format(v.bigbrain3d_y_position))

    if v.current_position_z < v.mechpurge_minimalclearenceheight:
        issue_code(
            "\nG1 Z{:.3f} F8640    ; Increase Z to prevent collission with bed"
            .format(v.mechpurge_minimalclearenceheight))

    issue_code("G1 X{:.3f} F10800  ; go near edge of bed".format(
        v.mechpurge_x_position - 30))

    if v.manual_filament_swap:
        swap.swap_pause("M25")
        swap.swap_unpause()

    issue_code("{}               ; wait for the print buffer to clear".format(
        v.finish_moves))
    v.processed_gcode.append(
        "M907 X{}           ; increase motor power".format(
            v.bigbrain3d_motorpower_high))
    issue_code(
        "; -- P2PP -- Generating {} blobs for {}mm of purge".format(
            purgeblobs, length), True)

    if v.single_blob:
        generate_bb3d_blob(length, 0)
    else:
        for i in range(purgeblobs):
            generate_bb3d_blob(v.mechpurge_blob_size, i)

    if not v.retraction < 0:
        purgetower.retract(v.current_tool)

    if v.current_position_z < v.mechpurge_minimalclearenceheight:

        if keep_xpos > v.bed_max_x or keep_xpos < v.bed_origin_x:
            keep_xpos = (v.bed_max_x - v.bed_origin_x) / 2

        if keep_ypos > v.bed_max_y or keep_ypos < v.bed_origin_y:
            keep_ypos = (v.bed_max_y - v.bed_origin_y) / 2

        issue_code("\nG1 X{:.3f} Y{:.3f} F8640".format(keep_xpos, keep_ypos))
        if not v.sidewipe_delay_zreturn:
            issue_code(
                "\nG1 Z{:.4f} F8640    ; P2PP - ZHOP - return to oroginal height"
                .format(v.current_position_z))
        else:
            issue_code(
                "\n; G1 Z{:.4f} F8640  ; P2PP - Deferred return to Z_height".
                format(v.current_position_z))

    resetfanspeed()
    v.processed_gcode.append("\nM907 X{}           ; reset motor power".format(
        v.bigbrain3d_motorpower_normal))
    issue_code("\n;-------------------------------\n", True)
Exemplo n.º 3
0
def create_side_wipe(length=0):

    if length != 0:
        v.side_wipe_length = length

    if not v.side_wipe or v.side_wipe_length == 0:
        return

    if v.bigbrain3d_purge_enabled:
        create_sidewipe_bb3d(v.side_wipe_length)
        v.side_wipe_length = 0
    elif v.blobster_purge_enabled:
        create_sidewipe_blobster(v.side_wipe_length)
        v.side_wipe_length = 0
    else:

        issue_code(";---------------------------", True)
        issue_code(";  P2PP SIDE WIPE: {:7.3f}mm".format(v.side_wipe_length),
                   True)

        # check if the sidewipe has an additional z-hop defined, if so increase z-height with that amount
        if v.addzop > 0.0:
            issue_code(
                "G1 Z{} ;P2PP ZHOP SIDEWIPE".format(v.current_position_z +
                                                    1.0))

        for line in v.before_sidewipe_gcode:
            issue_code(line)

        if v.retraction == 0:
            purgetower.retract(v.current_tool)

        issue_code("G1 F8640")
        issue_code("G1 {} Y{}".format(v.side_wipe_loc, v.sidewipe_miny))

        if v.manual_filament_swap:
            swap.swap_pause("M25")
            swap.swap_unpause()

        delta_y = abs(v.sidewipe_maxy - v.sidewipe_miny)

        if v.sidewipe_maxy == v.sidewipe_miny:  # no Y movement, just purge
            purgetower.unretract(v.current_tool)
            while v.side_wipe_length > 0:
                sweep = min(v.side_wipe_length, 50)
                issue_code("G1 E{:.5f} F{}".format(sweep, v.wipe_feedrate))
                issue_code("G1 E-3.0000 F200")
                issue_code("G1 E3.0000 F200")
                v.side_wipe_length -= sweep

        else:

            sweep_base_speed = v.wipe_feedrate * 20 * delta_y / 150
            sweep_length = 20

            yrange = [v.sidewipe_maxy, v.sidewipe_miny]
            rangeidx = 0
            movefrom = v.sidewipe_miny
            moveto = yrange[rangeidx]
            numdiffs = 20
            purgetower.unretract(v.current_tool)

            while v.side_wipe_length > 0:
                sweep = min(v.side_wipe_length, sweep_length)
                v.side_wipe_length -= sweep_length
                wipe_speed = min(5000, int(sweep_base_speed / sweep))

                # split this move in very short moves to allow for faster planning buffer depletion
                diff = (moveto - movefrom) / numdiffs

                for i in range(numdiffs):
                    issue_code("G1 {} Y{:.3f} E{:.5f} F{}".format(
                        v.side_wipe_loc, movefrom + (i + 1) * diff,
                        sweep / numdiffs * v.sidewipe_correction, wipe_speed))

                # issue_code(
                #     "G1 {} Y{} E{:.5f} F{}\n".format(v.side_wipe_loc, moveto, sweep * v.sidewipe_correction, wipe_speed))

                rangeidx += 1
                movefrom = moveto
                moveto = yrange[rangeidx % 2]

        for line in v.after_sidewipe_gcode:
            issue_code(line)

        purgetower.retract(v.current_tool)

        issue_code("G1 F8640")
        issue_code(";---------------------------", True)

        v.side_wipe_length = 0
Exemplo n.º 4
0
def purge_generate_sequence():
    global last_posx, last_posy

    if last_posx is None:
        last_posx = v.purge_sequence_x
    if last_posy is None:
        last_posy = v.purge_sequence_y

    if not v.side_wipe_length > 0:
        return

    actual = 0

    gcode.issue_code("; --------------------------------------------------", True)
    gcode.issue_code("; --- P2PP WIPE SEQUENCE START  FOR {:5.2f}mm".format(v.side_wipe_length), True)
    gcode.issue_code(
        "; --- DELTA = {:.2f}".format(v.current_position_z - (v.purgelayer + 1) * v.layer_height), True)
    #
    # if v.previous_tool != -1:
    #     index = v.previous_tool * 4 + v.current_tool
    #     if v.side_wipe_length > v.wiping_info[index]:
    #         v.side_wipe_length = v.wiping_info[index]
    #         gcode.issue_code(
    #             "; --- CORRECTED PURGE TO TRANSITION LENGTH {:.2f}mm\n".format(v.wiping_info[index]))
    # gcode.issue_code("; --------------------------------------------------\n")

    v.max_tower_delta = max(v.max_tower_delta, v.current_position_z - (v.purgelayer + 1) * v.layer_height)
    v.min_tower_delta = min(v.min_tower_delta, v.current_position_z - (v.purgelayer + 1) * v.layer_height)

    if last_posx and last_posy:
        # gcode.issue_code(";retraction {}".format(v.retraction))
        if v.retraction == 0:
            retract(v.current_tool)
        gcode.issue_code("G1 X{} Y{} F8640".format(last_posx, last_posy))

        if v.manual_filament_swap:
            swap.swap_pause("M25")
            # no need to unpause as the reauired Z-move is part of the remaining sequence

    gcode.issue_code("G1 Z{:.2f} F10800".format((v.purgelayer + 1) * v.layer_height))
    unretract(v.current_tool)
    # p2pp_process_file wipe code
    while v.side_wipe_length > 0:
        next_command = _purge_get_nextcommand_in_sequence()

        last_posx = if_defined(next_command[gcode.X], last_posx)
        last_posy = if_defined(next_command[gcode.Y], last_posy)
        v.side_wipe_length -= if_defined(next_command[gcode.E], 0)
        actual += if_defined(next_command[gcode.E], 0)
        gcode.issue_command(next_command, getwipespeed())
        _purge_update_sequence_index()

    # return to print height
    retract(v.current_tool)
    if v.retraction == 0:
        v.expect_retract = True

    gcode.issue_code(
        "G1 Z{:.2f} F10800\n".format(max(v.current_position_z + 0.6, (v.purgelayer + 1) * v.layer_height) + 0.6))
    gcode.issue_code("; -------------------------------------", True)
    gcode.issue_code("; --- P2PP WIPE SEQUENCE END DONE", True)
    gcode.issue_code("; -------------------------------------", True)

    # if we extruded more we need to account for that in the total count

    v.side_wipe_length = 0
    v.retract_x = last_posx
    v.retract_y = last_posy
    v.expect_retract = True
Exemplo n.º 5
0
def parse_gcode_second_pass():
    idx = 0
    intower = False
    purge = False
    total_line_count = len(v.parsed_gcode)
    v.retraction = 0
    v.last_parsed_layer = -1
    v.previous_block_classification = v.parsed_gcode[0][gcode.CLASS]

    # include firmware purge length accounting
    v.total_material_extruded = v.firmwarepurge
    v.material_extruded_per_color[v.current_tool] = v.firmwarepurge

    for process_line_count in range(total_line_count):

        try:
            if process_line_count >= v.layer_end[0]:
                v.last_parsed_layer += 1
                v.layer_end.pop(0)
                v.current_layer_is_skippable = v.skippable_layer[
                    v.last_parsed_layer] and not v.last_parsed_layer == 0
                if v.current_layer_is_skippable:
                    if v.last_parsed_layer == 0:
                        v.cur_tower_z_delta += v.first_layer_height
                    else:
                        v.cur_tower_z_delta += v.layer_height
        except IndexError:
            pass

        g = v.parsed_gcode[idx]

        idx = idx + 1

        # ----- MEMORY MANAGEMENT - when 100K lines are processed, remove the top of the list

        if idx > 100000:
            v.parsed_gcode = v.parsed_gcode[idx:]
            idx = 0

        if process_line_count % 10000 == 0:
            gui.progress_string(50 +
                                50 * process_line_count // total_line_count)

        current_block_class = g[gcode.CLASS]

        # ---- FIRST SECTION HANDLES DELAYED TEMPERATURE COMMANDS ----

        if current_block_class not in [
                CLS_TOOL_PURGE, CLS_TOOL_START, CLS_TOOL_UNLOAD
        ] and v.current_temp != v.new_temp:
            gcode.issue_code(v.temp1_stored_command)
            v.temp1_stored_command = ""

        # BLOCK Added 27/11/2021 - PS2.4 - P3 - showinf lines between print and tower
        if current_block_class != v.previous_block_classification and not v.side_wipe and not v.full_purge_reduction:
            if v.previous_block_classification == CLS_TOOL_UNLOAD:
                if v.restore_move_point:
                    v.restore_move_point = False
                    gcode.issue_code(
                        "G1 X{:0.3f} Y{:0.3f} F8640 ; P2PP positional alignment"
                        .format(v.current_position_x, v.current_position_y))
        # BLOCK END

        # ---- SECOND SECTION HANDLES COMMENTS AND NONE-MOVEMENT COMMANDS ----

        if g[gcode.COMMAND] is None:
            if v.disable_z and g[gcode.COMMENT].endswith("END"):
                v.disable_z = False

            if v.needpurgetower and g[gcode.COMMENT].endswith("BRIM END"):
                v.needpurgetower = False
                purgetower.purge_create_layers(v.wipe_tower_info_minx,
                                               v.wipe_tower_info_miny,
                                               v.wipe_tower_xsize,
                                               v.wipe_tower_ysize)
                purgetower.purge_generate_brim()
                v.toolchange_processed = False
            gcode.issue_command(g)
            continue

        elif g[gcode.MOVEMENT] == 0:

            if g[gcode.COMMAND].startswith('T'):

                if v.manual_filament_swap and not (
                        v.side_wipe or v.full_purge_reduction
                        or v.tower_delta) and (v.current_tool != -1):
                    swap.swap_pause("M25")
                    swap.swap_unpause()

                gcode_process_toolchange(int(g[gcode.COMMAND][1:]))
                if not v.debug_leaveToolCommands:
                    gcode.move_to_comment(g, "--P2PP-- Color Change")

                v.toolchange_processed = (current_block_class != CLS_NORMAL)

            elif v.klipper and g[gcode.COMMAND] == "ACTIVATE_EXTRUDER":

                extruder = g[gcode.OTHER].strip()

                if extruder.startswith("EXTRUDER=extruder"):
                    if len(extruder) == 17:
                        extruder_num = 0
                    else:
                        try:
                            extruder_num = int(extruder[17:])
                        except (ValueError, IndexError):
                            extruder_num = None
                            gui.log_warning(
                                "KLIPPER - Named extruders are not supported ({})"
                                .format(extruder))

                    if extruder_num is not None:
                        gcode_process_toolchange(extruder_num)

                    if not v.debug_leaveToolCommands:
                        gcode.move_to_comment(g, "--P2PP-- Color Change")
                        v.toolchange_processed = True
                else:
                    gui.log_warning(
                        "KLIPPER - Named extruders are not supported ({})".
                        format(extruder))
            else:
                if current_block_class == CLS_TOOL_UNLOAD:
                    if g[gcode.COMMAND] in ["G4", "M900", "M400"]:
                        gcode.move_to_comment(g, "--P2PP-- tool unload")

                if g[gcode.COMMAND] is not None and g[
                        gcode.COMMAND].startswith('M'):
                    try:
                        command_num = int(g[gcode.COMMAND][1:])
                    except (ValueError, KeyError):
                        command_num = 0

                    if command_num in [104, 109]:
                        if v.process_temp:
                            if current_block_class not in [
                                    CLS_TOOL_PURGE, CLS_TOOL_START,
                                    CLS_TOOL_UNLOAD
                            ]:
                                g[gcode.COMMENT] += " Unprocessed temp "
                                v.new_temp = gcode.get_parameter(
                                    g, gcode.S, v.current_temp)
                                v.current_temp = v.new_temp
                            else:
                                v.new_temp = gcode.get_parameter(
                                    g, gcode.S, v.current_temp)
                                if v.new_temp >= v.current_temp:
                                    g[gcode.COMMAND] = "M109"
                                    v.temp2_stored_command = gcode.create_commandstring(
                                        g)
                                    gcode.move_to_comment(
                                        g,
                                        "--P2PP-- delayed temp rise until after purge {}-->{}"
                                        .format(v.current_temp, v.new_temp))
                                    v.current_temp = v.new_temp

                                else:
                                    v.temp1_stored_command = gcode.create_commandstring(
                                        g)
                                    gcode.move_to_comment(
                                        g,
                                        "--P2PP-- delayed temp drop until after purge {}-->{}"
                                        .format(v.current_temp, v.new_temp))
                    elif command_num == 107:
                        v.saved_fanspeed = 0

                    elif command_num == 106:
                        v.saved_fanspeed = gcode.get_parameter(
                            g, gcode.S, v.saved_fanspeed)

                    elif command_num == 221:
                        v.extrusion_multiplier = float(
                            gcode.get_parameter(
                                g, gcode.S,
                                v.extrusion_multiplier * 100.0)) / 100.0

                    elif command_num == 220:
                        gcode.move_to_comment(
                            g, "--P2PP-- Feed Rate Adjustments are removed")

                    elif command_num == 572:
                        for i in range(1, v.filament_count):
                            g[gcode.OTHER] = g[gcode.OTHER].replace(
                                "D{}".format(i), "D0")

                    elif not v.generate_M0 and g[gcode.COMMAND] == "M0":
                        gcode.move_to_comment(g, "--P2PP-- remove M0 command")

            gcode.issue_command(g)
            continue

        classupdate = not current_block_class == v.previous_block_classification
        v.previous_block_classification = current_block_class

        # ---- AS OF HERE ONLY MOVEMENT COMMANDS ----

        if g[gcode.MOVEMENT] & 1:
            v.previous_purge_keep_x = v.purge_keep_x
            v.purge_keep_x = g[gcode.X]
            v.current_position_x = g[gcode.X]

        if g[gcode.MOVEMENT] & 2:
            v.previous_purge_keep_y = v.purge_keep_y
            v.purge_keep_y = g[gcode.Y]
            v.current_position_y = g[gcode.Y]

        if g[gcode.MOVEMENT] & 4:
            if v.disable_z:
                gcode.move_to_comment(g,
                                      "-- P2PP - invalid move in delta tower")
                gcode.issue_command(g)
                continue
            else:
                v.current_position_z = g[gcode.Z]

        if g[gcode.MOVEMENT] & 16:
            v.keep_speed = g[gcode.F]

        # this goes for all situations: START and UNLOAD are not needed
        if current_block_class in [CLS_TOOL_START, CLS_TOOL_UNLOAD]:
            # BLOCK Added 27/11/2021 - PS2.4 - P3 - showinf lines between print and tower
            if not (v.side_wipe or v.full_purge_reduction):
                v.restore_move_point = True
            # BLOCK END
            gcode.move_to_comment(g, "--P2PP-- tool unload")
            gcode.issue_command(g)
            continue

        # --------------------- TOWER DELTA PROCESSING
        if v.tower_delta:

            if classupdate:

                if current_block_class == CLS_TOOL_PURGE:
                    gcode.issue_command(g)
                    entertower(v.last_parsed_layer * v.layer_height +
                               v.first_layer_height)
                    continue

                if current_block_class == CLS_EMPTY and not v.towerskipped:

                    v.towerskipped = (
                        g[gcode.MOVEMENT] & gcode.INTOWER
                    ) == gcode.INTOWER and v.current_layer_is_skippable

                    if not v.towerskipped:
                        gcode.issue_command(g)
                        entertower(v.last_parsed_layer * v.layer_height +
                                   v.first_layer_height)
                        continue

                if current_block_class == CLS_NORMAL:
                    if v.towerskipped:
                        gcode.issue_code("G1 Z{:.2f} F10810".format(
                            v.current_position_z))
                        v.towerskipped = False

            if current_block_class == CLS_TOOL_PURGE:
                speed_limiter(g)

            if current_block_class == CLS_TOOL_PURGE:
                if g[gcode.F] is not None and g[
                        gcode.F] > v.purgetopspeed and g[gcode.E]:
                    g[gcode.F] = v.purgetopspeed
                    g[gcode.COMMENT] += " prugespeed topped"

            if v.towerskipped:
                gcode.move_to_comment(g, "--P2PP-- tower skipped")
                gcode.issue_command(g)
                continue
        # --------------------- SIDE WIPE PROCESSING
        elif v.side_wipe:

            if classupdate:

                if current_block_class == CLS_BRIM:
                    v.towerskipped = True
                    v.side_wipe_state = 0

            if not v.towerskipped and (g[gcode.MOVEMENT] & 3) != 0:
                if (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER:
                    v.towerskipped = True
                    v.side_wipe_state = 1 if (current_block_class
                                              == CLS_TOOL_PURGE) else 0

            if v.towerskipped and current_block_class == CLS_NORMAL and (
                    g[gcode.MOVEMENT] & 3) == 3:
                if (v.bed_origin_x <= g[gcode.X] <= v.bed_max_x) and (
                        v.bed_origin_y <= g[gcode.Y] <= v.bed_max_y):
                    v.towerskipped = False
                    v.side_wipe_state = 0
                    if v.toolchange_processed and v.side_wipe_length:
                        create_side_wipe()
                        v.toolchange_processed = False

            if v.towerskipped:
                inc = "NO_E"
                if current_block_class in [
                        CLS_TOOL_PURGE, CLS_ENDPURGE
                ] or (current_block_class == CLS_EMPTY
                      and v.side_wipe_state == 1):
                    if g[gcode.EXTRUDE]:
                        v.side_wipe_length += g[gcode.E]
                        inc = "INC_E"

                gcode.move_to_comment(
                    g, "--P2PP-- side wipe skipped ({})".format(inc))
                gcode.issue_command(g)
                continue

            # for PS2.4
            # before first extrusion prime the nozzle
            if not v.mechpurge_hasprimed and g[gcode.EXTRUDE]:
                if v.bigbrain3d_purge_enabled or v.blobster_purge_enabled:
                    create_side_wipe(v.mechpurge_prime_blobs *
                                     v.mechpurge_blob_size)
                v.mechpurge_hasprimed = True

        # --------------------- FULL PURGE PROCESSING
        elif v.full_purge_reduction:

            if (g[gcode.MOVEMENT] & 3) > 0:  # if there is a movement
                intower = (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER

            if classupdate:

                if current_block_class == CLS_NORMAL:
                    v.towerskipped = False
                    purge = False

                if current_block_class == CLS_TOOL_PURGE:
                    purge = True

            if not v.towerskipped and current_block_class == CLS_EMPTY and v.current_layer_is_skippable:
                v.towerskipped = (g[gcode.MOVEMENT]
                                  & gcode.INTOWER) == gcode.INTOWER

            if v.towerskipped or current_block_class in [
                    CLS_BRIM, CLS_ENDGRID
            ]:
                gcode.move_to_comment(
                    g, "--P2PP-- full purge skipped [Excluded]")
                gcode.issue_command(g)
                continue

            if current_block_class in [
                    CLS_TOOL_PURGE, CLS_ENDPURGE, CLS_EMPTY
            ]:
                if purge and g[gcode.EXTRUDE]:
                    v.side_wipe_length += g[gcode.E]
                    gcode.move_to_comment(
                        g, "--P2PP-- full purge skipped [Included]")
                else:
                    gcode.move_to_comment(
                        g, "--P2PP-- full purge skipped [Excluded]")
                gcode.issue_command(g)
                continue

            if v.toolchange_processed and current_block_class == CLS_NORMAL:
                if v.side_wipe_length and (
                        g[gcode.MOVEMENT]
                        & 3) == 3 and not (g[gcode.MOVEMENT]
                                           & gcode.INTOWER) == gcode.INTOWER:
                    purgetower.purge_generate_sequence()
                    v.toolchange_processed = False
                    # do not issue code here as the next code might require further processing such as retractioncorrection
                else:
                    gcode.move_to_comment(g, "--P2PP-- full purge skipped")
                    gcode.issue_command(g)
                    continue

            if v.expect_retract and (g[gcode.MOVEMENT] & 3):
                v.expect_retract = False
                if v.retraction >= 0 and g[gcode.RETRACT]:
                    purgetower.retract(v.current_tool)

            if v.retract_move and g[gcode.RETRACT]:
                g[gcode.X] = v.retract_x
                g[gcode.Y] = v.retract_y
                g[gcode.MOVEMENT] |= 3
                v.retract_move = False

                if v.retraction <= -v.retract_length[v.current_tool]:
                    gcode.move_to_comment(g, "--P2PP-- Double Retract")
                else:
                    v.retraction += g[gcode.E]

            if intower:
                gcode.move_to_comment(
                    g, "--P2PP-- full purge skipped [Excluded]")
                gcode.issue_command(g)
                continue

        # --------------------- NO TOWER PROCESSING
        else:

            if current_block_class in [CLS_TOOL_PURGE, CLS_EMPTY
                                       ] and g[gcode.E]:
                if v.acc_ping_left <= 0:
                    pings.check_accessorymode_first()
                    v.enterpurge = True

            # TOEE - Added to limit the speed of the extrusions during purge to defined WIPEFEEDRATE
            if current_block_class == CLS_TOOL_PURGE:
                speed_limiter(g)

            if v.toolchange_processed:
                if v.temp2_stored_command != "":
                    wait_location = calculate_temp_wait_position()
                    gcode.issue_code(
                        "G1 X{:.3f} Y{:.3f} F8640; temp wait position\n".
                        format(wait_location[0], wait_location[0]))
                    gcode.issue_code(v.temp2_stored_command)
                    v.temp2_stored_command = ""

                gcode.issue_code("G1 F8640 ; correct speed")
                gcode.issue_command(g)
                if v.wipe_remove_sparse_layers:
                    gcode.issue_code(
                        "G1 X{}  Y{} F8640 ;P2PP Position XY to avoid tower crash"
                        .format(v.current_position_x, v.current_position_y))
                v.z_correction = "G1 Z{} F10800 ;P2PP correct z-moves".format(
                    v.current_position_z)

                v.toolchange_processed = False
                continue

            if current_block_class == CLS_TOOL_PURGE:
                if g[gcode.F] is not None and g[
                        gcode.F] > v.purgetopspeed and g[gcode.E]:
                    g[gcode.F] = v.purgetopspeed
                    g[gcode.COMMENT] += " prugespeed topped"

        # --------------------- GLOBAL PROCEDDING

        if g[gcode.UNRETRACT]:
            g[gcode.E] = min(-v.retraction, g[gcode.E])
            v.retraction += g[gcode.E]
        elif g[gcode.RETRACT]:
            v.retraction += g[gcode.E]
        elif (g[gcode.MOVEMENT] & 3) and g[gcode.EXTRUDE]:
            if v.z_correction is not None or v.retraction < -0.01:
                if current_block_class != CLS_TOOL_START:
                    gcode.issue_code(";P2PP START Z/E alignment processing")
                    if v.z_correction is not None:
                        gcode.issue_code(v.z_correction)
                        v.z_correction = None
                    if v.retraction < -0.01:
                        purgetower.unretract(v.retraction, -1,
                                             ";--- P2PP --- fixup retracts")
                    gcode.issue_code(";P2PP END Z/E alignment processing")
                else:
                    gcode.issue_command(g)
                    gcode.issue_code(";P2PP START Z/E alignment processing")
                    if v.z_correction is not None:
                        gcode.issue_code(v.z_correction)
                        v.z_correction = None
                    if v.retraction < -0.01:
                        purgetower.unretract(v.retraction, -1,
                                             ";--- P2PP --- fixup retracts")
                    g = gcode.create_command(
                        ";P2PP END Z/E alignment processing")

        # --------------------- PING PROCESSING

        if v.accessory_mode and g[gcode.EXTRUDE]:
            if not pings.check_accessorymode_second(g[gcode.E]):
                gcode.issue_command(g)
        else:
            gcode.issue_command(g)
            if g[gcode.EXTRUDE] and v.side_wipe_length == 0:
                pings.check_connected_ping()

        v.previous_position_x = v.current_position_x
        v.previous_position_y = v.current_position_y

    # LAST STEP IS ADDING AN EXTRA TOOL UNLOAD TO DETERMINE THE LENGTH OF THE LAST SPLICE
    gcode_process_toolchange(-1)