Overview
用于延迟时钟序列, 可以让每Tick的信号延迟指定时间后输出
基本说明
这是一个典型的4-bit 60-ticks模块
灵感来源于 这 [tieba.baidu.com] 和这 [tieba.baidu.com]
主旨是通过信号本身去存储时序信息
原理为将信号用二进制方式分割为几个区块
并通过移位的方式将数据从区块中转移, 用以保存时序信息
以4位为一个区块为例:
移位使一个2^4-1以内的信号延迟了7-ticks后输出
- 模块操作数全部是黄色星号(同时输入多个信号)
- 需要增加延迟时间的, 可以通过模块串联到需要的倍数
- 需要增加信号数值上限的, 模块并联到需要的倍数; 输出直接并联, 输入做除法和取模运算
- 需注意的是, 模块不支持负数输入, 请将输入信号进行标准化
推荐使用的调试模组:
- TimeTools[mods.factorio.com]
- controllinator[mods.factorio.com]
- pushbutton[mods.factorio.com]
一些示例
1bit 60-ticks 延迟模块
4-bit 60-ticks 延迟模块
7-bit 120-ticks 延迟模块X2 右侧的模块使用更多的运算器但更酷
原理解说
简化流程图
简化模块图
T = 延迟总时长
M = 幂值 (每次移动多少位 | 区块位数)
D = 总移位次数 | 区块数量
S = 信号的数值上限
CON = 延时运算器数量 | 额外延迟时间(ticks)
另外:
取高位输出模块 与 取低位模块 必须有相同的延迟时间!
CON = T / D – 2 中的 2 是一个可变值, 为 移位模块 的 1tick + 取低位模块 的 ?tick
S = 2^31-1 (游戏内表示为 2147483647, hex为 0x7FFFFFFF)
S = 2^32-1 (游戏内表示为 -1, hex为 0xFFFFFFFF) *可以通过windows计算器计算
由于带符号位的值左移, 填充高位的是1而不是0, 所以输出前还需要进行一次对低位的与运算
而经过下面的计算 实际只有M值为1,2,4,8时才有可能使用同样数量的运算器并提升延迟时间
为了确保移位的过程中不溢出, 必须确保 2^(M*D)*(2^M-1) <= S
变换公式为 S/(2^M-1)-2^(M*D) >= 0
以下是一个lua示例程序, 用于列出可用的D值, 其值越高, 相同延迟时间下所需的运算器数量就越少
*文章末提供用于计算的xlsx表, 可以自行根据需求进行计算
Let’s do it
*注: 一个模块的运算器数量为Out+Loop+CON
Out = 用于输出的 取高位运算器 数量
Loop = 移位运算器 和 取低位运算器 数量
T_Uni = 将模块延迟总时长统一 方便计算CP值
EffX = 自定义CON 和 T-Uni 得到所需的 模块数量
EffC = 自定义CON 和 T-Uni 得到所需的 运算器数量
这里提供一个简单的用于计算CON和EffX和EffC的示例:
*其中math.tointeger函数需要较高的lua版本才能运行
以最高数字为100, 延迟 120-ticks (2s) 为例:
根据前表, 选择 M=7 也就是 128, D值 则选择 3
设定 T_Uni=120, D=3, Out=1, Loop=2 得出结果
本着使用最少运算器的原则, 我们选择使用 CON=38
汇总一下重要参数 M=7, D=3, Out=1, Loop=2, CON=38, EffX=1
根据以下原理图进行构建
设定好M值
按CON值设定延迟, 这里以38个1-tick运算器为例
根据计算公式 2^(M*D)-1 得出值 2097151
根据计算公式 M*D 得出值 21
一些基础模块[drive.google.com]
*文章末提供用于计算的xlsx表, 可以自行根据需求进行计算
增加延迟时长&提升信号容量
这很简单, 只需要选择信号容量相同的模块, 将其首尾串联到需要的时间
例如 4-bit 60-ticks + 4-bit 40-ticks = 4-bit 100ticks
这里以上一章的模块为例:
模块首尾串联, 总时长360-ticks
通过并联时长相同的模块, 将其并联到需要的容量
例如 60-ticks 15C + 60-ticks 63C = 60ticks 78C
这里以上一章的模块为例:
最高信号容量为127*4=508, 可以继续增加额外的并联模块来提升容量
除法与取模运算
左上方1个加法运算器用于补偿原始信号的延迟
除法运算得到的值将决定启动几个延迟模块
取模得到的值会用于一个单独的延迟模块
开关门
最左侧两对加法运算器分别用于补偿 取模结果 和 原始信号 的延迟
右侧每对运算器分别为 >0启动; >1启动; >2启动; …, 并将信号以127的值输出
模块可以参考[drive.google.com]
嵌套模块
嵌套模块不会节省运算器的数量, 但可以拥有美观的结构
基本原理为将上层模块中已处理的信号还原到原始信号(对信号的每个区块进行还原), 进行延迟后原样返回
以之前的7-bit 120-ticks为例, 嵌套的模块:
- 由于D值为3, 需单独的3个模块分别处理各个区块的信号
- 右侧2×3的Split模块用来 取各区的值
- 值分别为 (2^M-1)*2^M; (2^M-1)*2^2M; (2^M-1)*2^3M — 1-ticks
- 下方分别移位 M; 2M; 3M 位来还原信号 — 1-ticks
- 将信号输出到各自对应区块的延迟模块中 — 33-ticks
- 原进原出, Merge模块将信号分别移位 M; 2M; 3M 位来还原信号 — 1-ticks
- 用于补足延迟时间的运算器 — 2-ticks
由于过于繁琐, 更详细的内容这里不做阐述了, 有需要可以使用文末提供的xlsx表格
这里提供一个lua示例程序, 用于计算这些
模块可以参考[drive.google.com]
表格与详细内容可以参考[drive.google.com]