chore: save local history restorations from accidental git restore
This commit is contained in:
@@ -6,13 +6,19 @@
|
||||
<div class="mode-buttons">
|
||||
<button
|
||||
:class="['mode-btn', { active: mode === 'serial' }]"
|
||||
@click="mode = 'serial'; reset()"
|
||||
@click="
|
||||
mode = 'serial';
|
||||
reset()
|
||||
"
|
||||
>
|
||||
串行传输(现代)
|
||||
</button>
|
||||
<button
|
||||
:class="['mode-btn', { active: mode === 'parallel' }]"
|
||||
@click="mode = 'parallel'; reset()"
|
||||
@click="
|
||||
mode = 'parallel';
|
||||
reset()
|
||||
"
|
||||
>
|
||||
并行传输(旧时代)
|
||||
</button>
|
||||
@@ -31,7 +37,7 @@
|
||||
:key="i"
|
||||
class="bit"
|
||||
:class="{ sent: sentBits.includes(i) }"
|
||||
>{{ bit }}</span>
|
||||
>{{ bit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -45,7 +51,7 @@
|
||||
:key="'p' + i"
|
||||
class="particle"
|
||||
:style="{ left: p.progress + '%', top: '50%' }"
|
||||
>{{ p.bit }}</span>
|
||||
>{{ p.bit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="mode === 'parallel'" class="wire-group parallel-group">
|
||||
@@ -55,7 +61,7 @@
|
||||
v-if="parallelParticle && parallelParticle.lane === l - 1"
|
||||
class="particle"
|
||||
:style="{ left: parallelParticle.progress + '%', top: '50%' }"
|
||||
>{{ parallelBits[l - 1] || '·' }}</span>
|
||||
>{{ parallelBits[l - 1] || '·' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -69,9 +75,13 @@
|
||||
v-for="(bit, i) in receivedBits"
|
||||
:key="'r' + i"
|
||||
class="bit received"
|
||||
>{{ bit }}</span>
|
||||
>{{ bit }}</span>
|
||||
</div>
|
||||
<div v-if="checksumResult !== null" class="checksum-badge" :class="checksumResult ? 'ok' : 'fail'">
|
||||
<div
|
||||
v-if="checksumResult !== null"
|
||||
class="checksum-badge"
|
||||
:class="checksumResult ? 'ok' : 'fail'"
|
||||
>
|
||||
{{ checksumResult ? '✓ 校验通过' : '✕ 校验失败' }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,7 +95,9 @@
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="s-label">传输速率</span>
|
||||
<span class="s-val">{{ mode === 'serial' ? '1 位/次' : '8 位/次' }}</span>
|
||||
<span class="s-val">{{
|
||||
mode === 'serial' ? '1 位/次' : '8 位/次'
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<span class="s-label">状态</span>
|
||||
@@ -99,8 +111,10 @@
|
||||
</button>
|
||||
|
||||
<div class="note-box">
|
||||
<strong>提示:等等,串行不是更慢吗?</strong><br>
|
||||
表面上是的——但现代串行接口(USB 4、PCIe)传输频率高达每秒 <strong>数百亿次</strong>,而并行线路之间会产生 <em>信号串扰(Crosstalk)</em>,反而限制了速度。所以高速接口全面转向了串行。
|
||||
<strong>提示:等等,串行不是更慢吗?</strong><br />
|
||||
表面上是的——但现代串行接口(USB 4、PCIe)传输频率高达每秒
|
||||
<strong>数百亿次</strong>,而并行线路之间会产生
|
||||
<em>信号串扰(Crosstalk)</em>,反而限制了速度。所以高速接口全面转向了串行。
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -109,7 +123,7 @@
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
const mode = ref('serial')
|
||||
const dataBits = ref([1,0,1,1,0,0,1,0]) // "Hello" first byte 0b10110010
|
||||
const dataBits = ref([1, 0, 1, 1, 0, 0, 1, 0]) // "Hello" first byte 0b10110010
|
||||
const sentBits = ref([])
|
||||
const receivedBits = ref([])
|
||||
const particles = ref([])
|
||||
@@ -141,7 +155,9 @@ const statusColor = computed(() => {
|
||||
return ''
|
||||
})
|
||||
|
||||
function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }
|
||||
function sleep(ms) {
|
||||
return new Promise((r) => setTimeout(r, ms))
|
||||
}
|
||||
|
||||
async function send() {
|
||||
if (isSending.value) return
|
||||
@@ -156,7 +172,7 @@ async function send() {
|
||||
|
||||
// Checksum simulation
|
||||
await sleep(400)
|
||||
checksumResult.value = true // always pass in demo
|
||||
checksumResult.value = true // always pass in demo
|
||||
isSending.value = false
|
||||
}
|
||||
|
||||
@@ -171,7 +187,7 @@ async function sendSerial() {
|
||||
p.progress = prog
|
||||
await sleep(35)
|
||||
}
|
||||
particles.value = particles.value.filter(x => x !== p)
|
||||
particles.value = particles.value.filter((x) => x !== p)
|
||||
receivedBits.value.push(bit)
|
||||
await sleep(30)
|
||||
}
|
||||
@@ -181,7 +197,10 @@ async function sendParallel() {
|
||||
sentBits.value = dataBits.value.map((_, i) => i)
|
||||
parallelBits.value = [...dataBits.value]
|
||||
for (let prog = 0; prog <= 100; prog += 8) {
|
||||
parallelParticle.value = { progress: prog, lane: Math.floor(Math.random() * 8) }
|
||||
parallelParticle.value = {
|
||||
progress: prog,
|
||||
lane: Math.floor(Math.random() * 8)
|
||||
}
|
||||
await sleep(40)
|
||||
}
|
||||
parallelParticle.value = null
|
||||
@@ -249,10 +268,17 @@ async function sendParallel() {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.device-icon { font-size: 2rem; }
|
||||
.device-label { font-size: 0.8rem; font-weight: bold; color: var(--vp-c-text-2); }
|
||||
.device-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
.device-label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.data-bits, .received-bits {
|
||||
.data-bits,
|
||||
.received-bits {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 2px;
|
||||
@@ -273,8 +299,15 @@ async function sendParallel() {
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.bit.sent { background: var(--vp-c-brand-soft); border-color: var(--vp-c-brand); }
|
||||
.bit.received { background: #d1fae5; border-color: #059669; color: #065f46; }
|
||||
.bit.sent {
|
||||
background: var(--vp-c-brand-soft);
|
||||
border-color: var(--vp-c-brand);
|
||||
}
|
||||
.bit.received {
|
||||
background: #d1fae5;
|
||||
border-color: #059669;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
.checksum-badge {
|
||||
margin-top: 4px;
|
||||
@@ -283,8 +316,14 @@ async function sendParallel() {
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.checksum-badge.ok { background: #d1fae5; color: #065f46; }
|
||||
.checksum-badge.fail { background: #fee2e2; color: #991b1b; }
|
||||
.checksum-badge.ok {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
}
|
||||
.checksum-badge.fail {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
/* Wires */
|
||||
.wire-container {
|
||||
@@ -311,8 +350,14 @@ async function sendParallel() {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wire-group.serial .wire { height: 20px; }
|
||||
.parallel-group { display: flex; flex-direction: column; gap: 2px; }
|
||||
.wire-group.serial .wire {
|
||||
height: 20px;
|
||||
}
|
||||
.parallel-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.particle {
|
||||
position: absolute;
|
||||
@@ -337,11 +382,25 @@ async function sendParallel() {
|
||||
padding: 0.6rem 0.85rem;
|
||||
}
|
||||
|
||||
.status-item { display: flex; flex-direction: column; gap: 2px; }
|
||||
.s-label { font-size: 0.72rem; color: var(--vp-c-text-3); }
|
||||
.s-val { font-size: 0.88rem; font-weight: bold; }
|
||||
.s-val.green { color: #059669; }
|
||||
.s-val.yellow { color: #d97706; }
|
||||
.status-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
.s-label {
|
||||
font-size: 0.72rem;
|
||||
color: var(--vp-c-text-3);
|
||||
}
|
||||
.s-val {
|
||||
font-size: 0.88rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.s-val.green {
|
||||
color: #059669;
|
||||
}
|
||||
.s-val.yellow {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
padding: 0.5rem 1.2rem;
|
||||
@@ -356,7 +415,10 @@ async function sendParallel() {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.send-btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
||||
.send-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.note-box {
|
||||
background: var(--vp-c-bg-alt);
|
||||
|
||||
Reference in New Issue
Block a user