Last active
October 18, 2024 19:38
-
-
Save uwezi/d5a565400b7e2f4af624de1a06c4b554 to your computer and use it in GitHub Desktop.
[Computer] Animated sequence of a computer adding two numbers. #manim #svg #animate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os, sys | |
from manim import * | |
myTexTemplate = TexTemplate() | |
myTexTemplate.add_to_preamble(r"\usepackage{siunitx}") | |
MathTex.set_default(tex_template=myTexTemplate) | |
Tex.set_default(tex_template=myTexTemplate) | |
config.max_files_cached = 10000 | |
def mkVGroup(mainVMobject, indices): | |
grp = VGroup() | |
for i in indices: | |
grp.add(mainVMobject[i].copy()) | |
return grp | |
def mkPath(points): | |
path = VMobject() | |
path.set_points_as_corners(points) | |
return path | |
class computer_en(Scene): | |
def construct(self): | |
copyleft = Text(r"© 2023 Uwe Zimmermann",font_size=22).move_to(6.9*LEFT+3.9*DOWN,DL).set_color(WHITE) | |
self.add(copyleft) | |
max_t = 15 | |
charge_t = 2 | |
def UCfunc(t): | |
return (1-np.exp(-t/0.4)) if t < charge_t else np.exp(-(t-charge_t)/2) | |
self.t = 0 | |
self.run = False | |
self.UC = 1 | |
self.I1 = 1 | |
self.I2 = 1 | |
def backgroundTimer(dt): | |
if self.run: | |
self.t += dt | |
self.t %= max_t | |
self.UC = UCfunc(self.t) | |
self.I1 = 1 - UCfunc(self.t) if self.t < charge_t else 0 | |
self.I2 = UCfunc(self.t) | |
self.add_updater(backgroundTimer) | |
circuit = SVGMobject(r"bilder\20231006_computer_02.svg", | |
stroke_color=WHITE, stroke_width=2, fill_color=WHITE, width=8) | |
comp = {} | |
arrow = {} | |
comp['memory'] = mkVGroup(circuit, [4]).set_color(WHITE) | |
comp['memory']+= Tex(r"Memory", font_size=24).next_to(comp["memory"],UP,aligned_edge=RIGHT,buff=0.05) | |
comp['pcnt'] = mkVGroup(circuit, [3]).set_color(WHITE) | |
comp['pcnt']+= Tex(r"address counter", font_size=24).next_to(comp["pcnt"],DOWN,aligned_edge=LEFT,buff=0.05) | |
comp['regA'] = mkVGroup(circuit, [0]).set_color(WHITE) | |
comp['regA']+= Tex(r"register A", font_size=24).next_to(comp["regA"],UP,aligned_edge=RIGHT,buff=0.05) | |
comp['regB'] = mkVGroup(circuit, [1]).set_color(WHITE) | |
comp['regB']+= Tex(r"register B", font_size=24).next_to(comp["regB"],UP,aligned_edge=RIGHT,buff=0.05) | |
comp['ALU'] = mkVGroup(circuit, [5]).set_color(WHITE) | |
comp['ALU']+= Tex(r"ALU", font_size=24).next_to(comp["ALU"],UP,aligned_edge=LEFT,buff=0.05) | |
comp['control'] = mkVGroup(circuit, [20]).set_color(WHITE) | |
comp['control']+= Tex(r"control unit", font_size=24).next_to(comp["control"],UP,aligned_edge=LEFT,buff=0.05) | |
comp['instruction'] = mkVGroup(circuit, [2]).set_color(WHITE) | |
comp['instruction']+= Tex(r"instruction", font_size=24).next_to(comp["instruction"],UP, aligned_edge=RIGHT,buff=0.05) | |
comp['databus'] = mkVGroup(circuit, [11]).set_color(WHITE).set_stroke(width=8) | |
comp['adrbus'] = mkVGroup(circuit, [40,41]).set_color(WHITE) | |
comp['result-data'] = mkVGroup(circuit, [53,54,55,19]).set_color(WHITE) | |
comp['data-A'] = mkVGroup(circuit, [8,14]).set_color(WHITE) | |
comp['data-B'] = mkVGroup(circuit, [9,13]).set_color(WHITE) | |
comp['data-instr'] = mkVGroup(circuit, [10,12]).set_color(WHITE) | |
comp['instr-ctrl'] = mkVGroup(circuit, [49,50]).set_color(WHITE) | |
comp['ctrl-instr'] = mkVGroup(circuit, [51,52]).set_color(WHITE) | |
comp['ctrl-regA'] = mkVGroup(circuit, [42,43,44]).set_color(WHITE) | |
comp['ctrl-regB'] = mkVGroup(circuit, [45,46]).set_color(WHITE) | |
comp['ctrl-pcnt'] = mkVGroup(circuit, [21]).set_color(WHITE) | |
comp['instr-ALU'] = mkVGroup(circuit, [47,48]).set_color(WHITE) | |
comp['data-mem'] = mkVGroup(circuit, [6,16]).set_color(WHITE) | |
circuit[7].reverse_direction() | |
comp['data-pcnt'] = mkVGroup(circuit, [7,15]).set_color(WHITE) | |
comp['regA-ALU'] = mkVGroup(circuit, [17]).set_color(WHITE) | |
comp['regB-ALU'] = mkVGroup(circuit, [18]).set_color(WHITE) | |
arrow['result-data_out'] = mkVGroup(circuit, [33]).set_color(WHITE) | |
arrow['adr-mem_in'] = mkVGroup(circuit, [22]).set_color(WHITE) | |
arrow['data-A_in'] = mkVGroup(circuit, [24]).set_color(WHITE) | |
arrow['data-A_out'] = mkVGroup(circuit, [30]).set_color(WHITE) | |
arrow['data-B_in'] = mkVGroup(circuit, [25]).set_color(WHITE) | |
arrow['data-B_out'] = mkVGroup(circuit, [29]).set_color(WHITE) | |
arrow['data-instr_in'] = mkVGroup(circuit, [26]).set_color(WHITE) | |
arrow['instr-ctrl_in'] = mkVGroup(circuit, [39]).set_color(WHITE) | |
arrow['ctrl-instr_in'] = mkVGroup(circuit, [36]).set_color(WHITE) | |
arrow['ctrl-regA_in'] = mkVGroup(circuit, [34]).set_color(WHITE) | |
arrow['ctrl-regB_in'] = mkVGroup(circuit, [35]).set_color(WHITE) | |
arrow['ctrl-pcnt_in'] = mkVGroup(circuit, [37]).set_color(WHITE) | |
arrow['instr-ALU_in'] = mkVGroup(circuit, [38]).set_color(WHITE) | |
arrow['data-mem_in'] = mkVGroup(circuit, [23]).set_color(WHITE) | |
arrow['data-mem_out'] = mkVGroup(circuit, [31]).set_color(WHITE) | |
arrow['data-pcnt_in'] = mkVGroup(circuit, [32]).set_color(WHITE) | |
arrow['regA-ALU_in'] = mkVGroup(circuit, [28]).set_color(WHITE) | |
arrow['regB-ALU_in'] = mkVGroup(circuit, [27]).set_color(WHITE) | |
tmpl = TexTemplate() | |
tmpl.add_to_preamble(r"\usepackage{array}") | |
code = Tex(r""" | |
1 & LOAD A & \$100\\ | |
3 & LOAD B & \$101\\ | |
5 & ADD & A,B\\ | |
6 & STORE & \$102\\ | |
&\dots &\\ | |
100 & 155 &\\ | |
101 & 42 &\\ | |
102 & 0 &\\ | |
""", | |
tex_environment=r"{tabular}{>{\ttfamily}r>{\ttfamily}l>{\ttfamily}l}", | |
tex_template=tmpl, | |
).scale_to_fit_width(0.65*comp['memory'].width).move_to(comp['memory'][0]) | |
codelines = VGroup( | |
VGroup( # load A | |
code[0][0], | |
code[0][1:6], | |
), | |
VGroup( # load A | |
code[0][0], | |
code[0][6:10], | |
), | |
VGroup( # load B | |
code[0][10], | |
code[0][11:16], | |
), | |
VGroup( # load B | |
code[0][10], | |
code[0][16:20], | |
), #******************* | |
VGroup( # add a,b | |
code[0][20], | |
code[0][21:27], | |
), | |
VGroup( # store | |
code[0][27], | |
code[0][28:33], | |
), | |
VGroup( | |
code[0][27], | |
code[0][33:37], | |
), | |
VGroup( | |
code[0][40:43], | |
code[0][43:46], | |
), | |
VGroup( | |
code[0][46:49], | |
code[0][49:51], | |
), | |
VGroup( | |
code[0][51:54], | |
code[0][54], | |
), | |
) | |
for c in comp: | |
self.add(comp[c]) | |
self.add(code) | |
pcnt = Integer(1, font_size=22).move_to(comp['pcnt'][0]) | |
self.add(pcnt) | |
# =================================================== | |
def signal_pcnt(): | |
self.play( | |
Indicate(comp['ctrl-pcnt'],scale_factor=1), | |
Indicate(arrow['ctrl-pcnt_in'],scale_factor=1) | |
) | |
self.remove(arrow['ctrl-pcnt_in']) | |
def signal_to_instr(): | |
self.play( | |
Indicate(comp['ctrl-instr'],scale_factor=1), | |
Indicate(arrow['ctrl-instr_in'],scale_factor=1) | |
) | |
self.remove(arrow['ctrl-instr_in']) | |
def signal_to_regA(): | |
self.play( | |
Indicate(comp['ctrl-regA'],scale_factor=1), | |
Indicate(arrow['ctrl-regA_in'],scale_factor=1) | |
) | |
self.remove(arrow['ctrl-regA_in']) | |
def signal_to_regB(): | |
self.play( | |
Indicate(comp['ctrl-regB'],scale_factor=1), | |
Indicate(arrow['ctrl-regB_in'],scale_factor=1) | |
) | |
self.remove(arrow['ctrl-regB_in']) | |
def act_regA(): | |
self.add(arrow['ctrl-regA_in']) | |
self.play( | |
comp['ctrl-regA'].animate.set_color(YELLOW), | |
arrow['ctrl-regA_in'].animate.set_color(YELLOW) | |
) | |
def deact_regA(): | |
self.play( | |
comp['ctrl-regA'].animate.set_color(WHITE), | |
arrow['ctrl-regA_in'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['ctrl-regA_in']) | |
def act_regB(): | |
self.add(arrow['ctrl-regB_in']) | |
self.play( | |
comp['ctrl-regB'].animate.set_color(YELLOW), | |
arrow['ctrl-regB_in'].animate.set_color(YELLOW) | |
) | |
def deact_regB(): | |
self.play( | |
comp['ctrl-regB'].animate.set_color(WHITE), | |
arrow['ctrl-regB_in'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['ctrl-regB_in']) | |
def act_ctrl_instr(): | |
self.add(arrow['ctrl-instr_in']) | |
self.play( | |
comp['ctrl-instr'].animate.set_color(YELLOW), | |
arrow['ctrl-instr_in'].animate.set_color(YELLOW) | |
) | |
def deact_ctrl_instr(): | |
self.play( | |
comp['ctrl-instr'].animate.set_color(WHITE), | |
arrow['ctrl-instr_in'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['ctrl-instr_in']) | |
def act_instr_ctrl(): | |
self.add(arrow['instr-ctrl_in']) | |
self.play( | |
comp['instr-ctrl'].animate.set_color(YELLOW), | |
arrow['instr-ctrl_in'].animate.set_color(YELLOW) | |
) | |
def deact_instr_ctrl(): | |
self.play( | |
comp['instr-ctrl'].animate.set_color(WHITE), | |
arrow['instr-ctrl_in'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['instr-ctrl_in']) | |
def act_instr_ALU(): | |
self.add(arrow['instr-ALU_in']) | |
self.play( | |
comp['instr-ALU'].animate.set_color(YELLOW), | |
arrow['instr-ALU_in'].animate.set_color(YELLOW) | |
) | |
def deact_instr_ALU(): | |
self.play( | |
comp['instr-ALU'].animate.set_color(WHITE), | |
arrow['instr-ALU_in'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['instr-ALU_in']) | |
def act_result_data(): | |
self.add(arrow['result-data_in']) | |
self.play( | |
comp['result-data'].animate.set_color(YELLOW), | |
arrow['result-data_out'].animate.set_color(YELLOW) | |
) | |
def deact_result_data(): | |
self.play( | |
comp['result-data'].animate.set_color(WHITE), | |
arrow['result-data_out'].animate.set_color(WHITE) | |
) | |
self.remove(arrow['rsult-data_out']) | |
p_adr = mkPath([ | |
comp['adrbus'][0].get_start()+.2*LEFT, | |
comp['adrbus'][0].get_end()+.2*UL, | |
comp['adrbus'][1].get_end()+.2*UL, | |
]) | |
def act_adrbus(obj): | |
self.add(arrow['adr-mem_in']) | |
comp['adrbus'].set_color(YELLOW) | |
arrow['adr-mem_in'].set_color(YELLOW) | |
self.play(MoveAlongPath(obj, p_adr), run_time=2) | |
def clear_adrbus(obj): | |
comp['adrbus'].set_color(WHITE) | |
arrow['adr-mem_in'].set_color(WHITE) | |
self.remove(obj, arrow['adr-mem_in']) | |
# =================================================== | |
# LADDA A -> instr | |
signal_pcnt() | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[0].animate.set_color(YELLOW).scale(1.1)) | |
d2 = codelines[0][1].copy() | |
p_mem_inst = mkPath([ | |
d2.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-instr'][0].get_end(), | |
comp['data-instr'][0].get_start(), | |
comp['instruction'][0].get_center(), | |
] | |
) | |
act_ctrl_instr() | |
self.add(arrow['data-mem_out'],arrow['data-instr_in']) | |
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-instr_in']) | |
deact_ctrl_instr() | |
act_instr_ctrl() | |
clear_adrbus(d1) | |
self.play(codelines[0].animate.set_color(WHITE).scale(1/1.1)) | |
# read argument -> pcnt | |
signal_pcnt() | |
self.play(pcnt.animate.set_value(2)) | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[1].animate.set_color(YELLOW).scale(1.1)) | |
d3 = codelines[1][1][1:].copy() | |
p_mem_pcnt = mkPath([ | |
d3.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-pcnt'][0].get_start(), | |
comp['data-pcnt'][0].get_end(), | |
comp['pcnt'][0].get_center()+RIGHT, | |
] | |
) | |
self.add(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
clear_adrbus(d1) | |
# read from address | |
signal_pcnt() | |
self.play(VGroup(d3,pcnt).animate.shift(LEFT)) | |
act_adrbus(d3) | |
self.play(codelines[1].animate.set_color(WHITE).scale(1/1.1)) | |
self.play(codelines[7].animate.set_color(YELLOW).scale(1.1)) | |
d4 = codelines[7][1].copy() | |
p_mem_A = mkPath([ | |
d4.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-A'][0].get_end(), | |
comp['data-A'][0].get_start(), | |
comp['regA'][0].get_center(), | |
] | |
) | |
act_regA() | |
self.add(arrow['data-mem_out'],arrow['data-A_in']) | |
self.play(MoveAlongPath(d4, p_mem_A), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-A_in']) | |
deact_regA() | |
deact_instr_ctrl() | |
self.play(FadeOut(d2)) | |
clear_adrbus(d3) | |
self.play(codelines[7].animate.set_color(WHITE).scale(1/1.1)) | |
self.play(pcnt.animate.shift(RIGHT)) | |
# step pcnt | |
signal_pcnt() | |
self.play(pcnt.animate.set_value(3)) | |
# LADDA B -> instr | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[2].animate.set_color(YELLOW).scale(1.1)) | |
d2 = codelines[2][1].copy() | |
p_mem_inst = mkPath([ | |
d2.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-instr'][0].get_end(), | |
comp['data-instr'][0].get_start(), | |
comp['instruction'][0].get_center(), | |
] | |
) | |
act_ctrl_instr() | |
self.add(arrow['data-mem_out'],arrow['data-instr_in']) | |
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-instr_in']) | |
deact_ctrl_instr() | |
act_instr_ctrl() | |
clear_adrbus(d1) | |
self.play(codelines[2].animate.set_color(WHITE).scale(1/1.1)) | |
# read argument -> pcnt | |
signal_pcnt() | |
self.play(pcnt.animate.set_value(4)) | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[3].animate.set_color(YELLOW).scale(1.1)) | |
d3 = codelines[3][1][1:].copy() | |
p_mem_pcnt = mkPath([ | |
d3.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-pcnt'][0].get_start(), | |
comp['data-pcnt'][0].get_end(), | |
comp['pcnt'][0].get_center()+RIGHT, | |
] | |
) | |
self.add(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
clear_adrbus(d1) | |
self.play(codelines[3].animate.set_color(WHITE).scale(1/1.1)) | |
# read from address | |
signal_pcnt() | |
self.play(VGroup(d3,pcnt).animate.shift(LEFT)) | |
act_adrbus(d3) | |
self.play(codelines[8].animate.set_color(YELLOW).scale(1.1)) | |
d5 = codelines[8][1].copy() | |
p_mem_B = mkPath([ | |
d5.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-B'][0].get_end(), | |
comp['data-B'][0].get_start(), | |
comp['regB'][0].get_center(), | |
] | |
) | |
act_regB() | |
self.add(arrow['data-mem_out'],arrow['data-B_in']) | |
self.play(MoveAlongPath(d5, p_mem_B), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-B_in']) | |
deact_regB() | |
deact_instr_ctrl() | |
self.play(FadeOut(d2)) | |
clear_adrbus(d3) | |
self.play(codelines[8].animate.set_color(WHITE).scale(1/1.1)) | |
# step pcnt | |
signal_pcnt() | |
self.play(pcnt.animate.shift(RIGHT)) | |
self.play(pcnt.animate.set_value(5)) | |
# ADD A,B -> instr | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[4].animate.set_color(YELLOW).scale(1.1)) | |
d2 = codelines[4][1].copy() | |
p_mem_inst = mkPath([ | |
d2.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-instr'][0].get_end(), | |
comp['data-instr'][0].get_start(), | |
comp['instruction'][0].get_center(), | |
] | |
) | |
act_ctrl_instr() | |
self.add(arrow['data-mem_out'],arrow['data-instr_in']) | |
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-instr_in']) | |
deact_ctrl_instr() | |
act_instr_ALU() | |
act_instr_ctrl() | |
self.add(arrow['regA-ALU_in'],arrow['regB-ALU_in']) | |
result = Integer(197, font_size=22).next_to(comp['result-data'],UP,aligned_edge=RIGHT,buff=0.1) | |
self.play(Create(result)) | |
self.remove(arrow['regA-ALU_in'],arrow['regB-ALU_in']) | |
deact_instr_ALU() | |
deact_instr_ctrl() | |
self.play(FadeOut(d2)) | |
clear_adrbus(d1) | |
self.play(codelines[4].animate.set_color(WHITE).scale(1/1.1)) | |
# SKRIV | |
self.play(pcnt.animate.set_value(6)) | |
# SKRIV -> instr | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[5].animate.set_color(YELLOW).scale(1.1)) | |
d2 = codelines[5][1].copy() | |
p_mem_inst = mkPath([ | |
d2.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-instr'][0].get_end(), | |
comp['data-instr'][0].get_start(), | |
comp['instruction'][0].get_center(), | |
] | |
) | |
act_ctrl_instr() | |
self.add(arrow['data-mem_out'],arrow['data-instr_in']) | |
self.play(MoveAlongPath(d2, p_mem_inst), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-instr_in']) | |
deact_ctrl_instr() | |
act_instr_ctrl() | |
clear_adrbus(d1) | |
self.play(codelines[5].animate.set_color(WHITE).scale(1/1.1)) | |
# read argument -> pcnt | |
signal_pcnt() | |
self.play(pcnt.animate.set_value(7)) | |
d1 = pcnt.copy() | |
act_adrbus(d1) | |
self.play(codelines[6].animate.set_color(YELLOW).scale(1.1)) | |
d3 = codelines[6][1][1:].copy() | |
p_mem_pcnt = mkPath([ | |
d3.get_center(), | |
comp['data-mem'][0].get_start(), | |
comp['data-mem'][0].get_end(), | |
comp['data-pcnt'][0].get_start(), | |
comp['data-pcnt'][0].get_end(), | |
comp['pcnt'][0].get_center()+RIGHT, | |
] | |
) | |
self.add(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
self.play(MoveAlongPath(d3, p_mem_pcnt), run_time=2) | |
self.remove(arrow['data-mem_out'],arrow['data-pcnt_in']) | |
clear_adrbus(d1) | |
self.play(codelines[6].animate.set_color(WHITE).scale(1/1.1)) | |
#-- | |
signal_pcnt() | |
self.play(VGroup(d3,pcnt).animate.shift(LEFT)) | |
act_adrbus(d3) | |
self.play(codelines[9].animate.set_color(YELLOW).scale(1.1)) | |
#-- | |
p_ALU_mem = mkPath([ | |
result.get_center(), | |
comp['result-data'][0].get_end()+0.1*UR, | |
comp['result-data'][1].get_end()+0.1*UR, | |
comp['result-data'][2].get_end()+0.1*UP, | |
comp['data-mem'][0].get_end(), | |
comp['data-mem'][0].get_start(), | |
codelines[9][1].get_right(), | |
] | |
) | |
self.add(arrow['data-mem_in'],arrow['result-data_out']) | |
self.play( | |
codelines[9][1].animate(run_time=1).set_opacity(0), | |
MoveAlongPath(result, p_ALU_mem), run_time=2 | |
) | |
self.remove(arrow['data-mem_in'],arrow['result-data_out']) | |
self.play(codelines[9].animate.set_color(WHITE).scale(1/1.1)) | |
clear_adrbus(d3) | |
self.play(FadeOut(d2)) | |
deact_instr_ctrl() | |
# -------------------------------------------------- | |
self.wait(3) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment