Compare commits
No commits in common. "5103145d01a63db02c3786b8947db5af6d883ad4" and "d30712d0f6e9c3cd00dc29efa38d2f48f3cf7278" have entirely different histories.
5103145d01
...
d30712d0f6
|
@ -79,7 +79,6 @@ interface SevenSegmentDisplayProps {
|
||||||
size?: number;
|
size?: number;
|
||||||
color?: string;
|
color?: string;
|
||||||
AFTERGLOW_BUFFER_SIZE?: number; // 余晖存储槽大小
|
AFTERGLOW_BUFFER_SIZE?: number; // 余晖存储槽大小
|
||||||
AFTERGLOW_DURATION?: number; // 余晖持续时间(毫秒)
|
|
||||||
pins?: {
|
pins?: {
|
||||||
pinId: string;
|
pinId: string;
|
||||||
constraint: string;
|
constraint: string;
|
||||||
|
@ -93,7 +92,7 @@ const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "red",
|
||||||
AFTERGLOW_BUFFER_SIZE: 1, // 默认存储槽大小为100
|
AFTERGLOW_BUFFER_SIZE: 1, // 默认存储槽大小为100
|
||||||
AFTERGLOW_DURATION: 2000, // 默认余晖持续时间500毫秒
|
AFTERGLOW_UPDATE_INTERVAL: 5, // 默认更新间隔为2毫秒
|
||||||
cathodeType: "common", // 默认为共阴极
|
cathodeType: "common", // 默认为共阴极
|
||||||
pins: () => [
|
pins: () => [
|
||||||
{ pinId: "a", constraint: "", x: 10, y: 170 }, // a段
|
{ pinId: "a", constraint: "", x: 10, y: 170 }, // a段
|
||||||
|
@ -150,7 +149,7 @@ const afterglowBuffers = ref<Record<string, boolean[]>>({
|
||||||
});
|
});
|
||||||
|
|
||||||
// 余晖判定阈值(比如持续10帧才算稳定,可根据刷新间隔和人眼余晖调节)
|
// 余晖判定阈值(比如持续10帧才算稳定,可根据刷新间隔和人眼余晖调节)
|
||||||
const STABLE_THRESHOLD = 3;
|
const STABLE_THRESHOLD = 10;
|
||||||
|
|
||||||
// 实际显示的段状态(只有稳定后才改变)
|
// 实际显示的段状态(只有稳定后才改变)
|
||||||
const stableSegmentStates = ref({
|
const stableSegmentStates = ref({
|
||||||
|
@ -176,54 +175,10 @@ const segmentStableCounters = ref<Record<string, number>>({
|
||||||
dp: 0,
|
dp: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 段选关闭时的余晖状态保持
|
// 判断段是否激活(用稳定状态)
|
||||||
const afterglowStates = ref({
|
|
||||||
a: false,
|
|
||||||
b: false,
|
|
||||||
c: false,
|
|
||||||
d: false,
|
|
||||||
e: false,
|
|
||||||
f: false,
|
|
||||||
g: false,
|
|
||||||
dp: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 余晖计时器
|
|
||||||
const afterglowTimers = ref<Record<string, number | null>>({
|
|
||||||
a: null,
|
|
||||||
b: null,
|
|
||||||
c: null,
|
|
||||||
d: null,
|
|
||||||
e: null,
|
|
||||||
f: null,
|
|
||||||
g: null,
|
|
||||||
dp: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 余晖持续时间(毫秒)
|
|
||||||
const AFTERGLOW_DURATION = computed(() => props.AFTERGLOW_DURATION || 500);
|
|
||||||
|
|
||||||
// 当前COM口状态
|
|
||||||
const currentComActive = ref(false); // 初始化为false,等待第一次状态检查
|
|
||||||
|
|
||||||
// 是否处于余晖模式
|
|
||||||
const isInAfterglowMode = ref(false);
|
|
||||||
|
|
||||||
// 判断段是否激活(用稳定状态或余晖状态)
|
|
||||||
function isSegmentActive(
|
function isSegmentActive(
|
||||||
segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
|
segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
|
||||||
): boolean {
|
): boolean {
|
||||||
// 如果处于余晖模式,使用余晖状态
|
|
||||||
if (isInAfterglowMode.value) {
|
|
||||||
return afterglowStates.value[segment];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果COM口未激活,所有段都不显示
|
|
||||||
if (!currentComActive.value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 否则使用稳定状态
|
|
||||||
return stableSegmentStates.value[segment];
|
return stableSegmentStates.value[segment];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,45 +186,21 @@ function isSegmentActive(
|
||||||
function updateSegmentStates() {
|
function updateSegmentStates() {
|
||||||
// 先获取COM口状态
|
// 先获取COM口状态
|
||||||
const comPin = props.pins.find((p) => p.pinId === "COM");
|
const comPin = props.pins.find((p) => p.pinId === "COM");
|
||||||
let comActive = false; // 默认未激活
|
let comActive = true;
|
||||||
|
|
||||||
if (comPin && comPin.constraint) {
|
if (comPin && comPin.constraint) {
|
||||||
const comState = getConstraintState(comPin.constraint);
|
const comState = getConstraintState(comPin.constraint);
|
||||||
if (props.cathodeType === "anode") {
|
if (props.cathodeType === "anode") {
|
||||||
// 共阳极模式下,COM为低电平才激活
|
// anode模式下,COM为高电平则所有段都熄灭
|
||||||
comActive = comState === "low";
|
comActive = comState !== "high";
|
||||||
} else {
|
|
||||||
// 共阴极模式下,COM为低电平才激活
|
|
||||||
comActive = comState === "low";
|
|
||||||
}
|
}
|
||||||
} else if (!comPin || !comPin.constraint) {
|
// 可扩展其他模式
|
||||||
// 如果没有COM引脚或者COM引脚没有约束,则认为始终激活
|
|
||||||
comActive = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查COM口状态是否发生变化
|
// 如果COM口激活,更新所有段的状态到存储槽
|
||||||
const comStateChanged = currentComActive.value !== comActive;
|
if (comActive) {
|
||||||
currentComActive.value = comActive;
|
updateAfterglowBuffers();
|
||||||
|
|
||||||
// 如果COM从激活变为非激活,进入余晖模式
|
|
||||||
if (comStateChanged && !comActive) {
|
|
||||||
enterAfterglowMode();
|
|
||||||
return; // 在余晖模式下,不处理其他引脚变化
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果COM从非激活变为激活,退出余晖模式
|
|
||||||
if (comStateChanged && comActive) {
|
|
||||||
exitAfterglowMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关键修复:如果COM口未激活或处于余晖模式,不处理任何引脚状态变化
|
|
||||||
if (!comActive || isInAfterglowMode.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只有当COM口激活时,才更新段的状态
|
|
||||||
updateAfterglowBuffers();
|
|
||||||
|
|
||||||
// 先更新 segmentStates
|
// 先更新 segmentStates
|
||||||
for (const pin of props.pins) {
|
for (const pin of props.pins) {
|
||||||
if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
|
if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
|
||||||
|
@ -284,8 +215,7 @@ function updateSegmentStates() {
|
||||||
} else {
|
} else {
|
||||||
newState = pinState === "low";
|
newState = pinState === "low";
|
||||||
}
|
}
|
||||||
// 段状态只有在COM激活时才有效
|
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState && comActive;
|
||||||
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,49 +255,6 @@ function updateAfterglowBuffers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进入余晖模式
|
|
||||||
function enterAfterglowMode() {
|
|
||||||
isInAfterglowMode.value = true;
|
|
||||||
|
|
||||||
// 保存当前稳定状态作为余晖状态
|
|
||||||
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
|
|
||||||
const typedSegmentId = segmentId as keyof typeof stableSegmentStates.value;
|
|
||||||
afterglowStates.value[typedSegmentId] = stableSegmentStates.value[typedSegmentId];
|
|
||||||
|
|
||||||
// 设置定时器,在余晖持续时间后退出余晖模式
|
|
||||||
if (afterglowTimers.value[segmentId]) {
|
|
||||||
clearTimeout(afterglowTimers.value[segmentId]!);
|
|
||||||
}
|
|
||||||
|
|
||||||
afterglowTimers.value[segmentId] = setTimeout(() => {
|
|
||||||
afterglowStates.value[typedSegmentId] = false;
|
|
||||||
|
|
||||||
// 检查是否所有段都已经关闭
|
|
||||||
const allSegmentsOff = Object.values(afterglowStates.value).every(state => !state);
|
|
||||||
if (allSegmentsOff) {
|
|
||||||
exitAfterglowMode();
|
|
||||||
}
|
|
||||||
}, AFTERGLOW_DURATION.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退出余晖模式
|
|
||||||
function exitAfterglowMode() {
|
|
||||||
isInAfterglowMode.value = false;
|
|
||||||
|
|
||||||
// 清除所有定时器
|
|
||||||
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
|
|
||||||
if (afterglowTimers.value[segmentId]) {
|
|
||||||
clearTimeout(afterglowTimers.value[segmentId]!);
|
|
||||||
afterglowTimers.value[segmentId] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置余晖状态
|
|
||||||
const typedSegmentId = segmentId as keyof typeof afterglowStates.value;
|
|
||||||
afterglowStates.value[typedSegmentId] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听约束状态变化
|
// 监听约束状态变化
|
||||||
function onConstraintChange(constraint: string, level: string) {
|
function onConstraintChange(constraint: string, level: string) {
|
||||||
const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
|
const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
|
||||||
|
@ -389,15 +276,6 @@ onMounted(() => {
|
||||||
onConstraintStateChange(onConstraintChange);
|
onConstraintStateChange(onConstraintChange);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
// 清理所有余晖定时器
|
|
||||||
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
|
|
||||||
if (afterglowTimers.value[segmentId]) {
|
|
||||||
clearTimeout(afterglowTimers.value[segmentId]!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 暴露属性和方法
|
// 暴露属性和方法
|
||||||
defineExpose({
|
defineExpose({
|
||||||
updateSegmentStates,
|
updateSegmentStates,
|
||||||
|
@ -429,7 +307,6 @@ export function getDefaultProps() {
|
||||||
size: 1,
|
size: 1,
|
||||||
color: "red",
|
color: "red",
|
||||||
cathodeType: "common",
|
cathodeType: "common",
|
||||||
AFTERGLOW_DURATION: 500, // 默认余晖持续时间500毫秒
|
|
||||||
pins: [
|
pins: [
|
||||||
{ pinId: "a", constraint: "", x: 10, y: 170 },
|
{ pinId: "a", constraint: "", x: 10, y: 170 },
|
||||||
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 },
|
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 },
|
||||||
|
|
|
@ -22,8 +22,6 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
// Jtag
|
// Jtag
|
||||||
const jtagBitstream = ref<File>();
|
const jtagBitstream = ref<File>();
|
||||||
const jtagBoundaryScanFreq = ref(100);
|
const jtagBoundaryScanFreq = ref(100);
|
||||||
const jtagBoundaryScanErrorCount = ref(0); // 边界扫描连续错误计数
|
|
||||||
const maxJtagBoundaryScanErrors = 5; // 最大允许连续错误次数
|
|
||||||
const jtagClientMutex = withTimeout(
|
const jtagClientMutex = withTimeout(
|
||||||
new Mutex(),
|
new Mutex(),
|
||||||
1000,
|
1000,
|
||||||
|
@ -52,11 +50,7 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
|
|
||||||
// Watch
|
// Watch
|
||||||
watchPostEffect(async () => {
|
watchPostEffect(async () => {
|
||||||
if (true === enableJtagBoundaryScan.value) {
|
if (true === enableJtagBoundaryScan.value) jtagBoundaryScan();
|
||||||
// 重新启用时重置错误计数器
|
|
||||||
jtagBoundaryScanErrorCount.value = 0;
|
|
||||||
jtagBoundaryScan();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Parse and Set
|
// Parse and Set
|
||||||
|
@ -115,20 +109,10 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
constrainsts.batchSetConstraintStates(portStates);
|
constrainsts.batchSetConstraintStates(portStates);
|
||||||
|
|
||||||
// 扫描成功,重置错误计数器
|
|
||||||
jtagBoundaryScanErrorCount.value = 0;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
jtagBoundaryScanErrorCount.value++;
|
dialog.error("边界扫描发生错误");
|
||||||
|
console.error(error);
|
||||||
console.error(`边界扫描错误 (${jtagBoundaryScanErrorCount.value}/${maxJtagBoundaryScanErrors}):`, error);
|
enableJtagBoundaryScan.value = false;
|
||||||
|
|
||||||
// 如果错误次数超过最大允许次数,才停止扫描并显示错误
|
|
||||||
if (jtagBoundaryScanErrorCount.value >= maxJtagBoundaryScanErrors) {
|
|
||||||
dialog.error("边界扫描发生连续错误,已自动停止");
|
|
||||||
enableJtagBoundaryScan.value = false;
|
|
||||||
jtagBoundaryScanErrorCount.value = 0; // 重置错误计数器
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
release();
|
release();
|
||||||
|
|
||||||
|
@ -283,7 +267,6 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
enableJtagBoundaryScan,
|
enableJtagBoundaryScan,
|
||||||
jtagBitstream,
|
jtagBitstream,
|
||||||
jtagBoundaryScanFreq,
|
jtagBoundaryScanFreq,
|
||||||
jtagBoundaryScanErrorCount,
|
|
||||||
jtagClientMutex,
|
jtagClientMutex,
|
||||||
jtagUploadBitstream,
|
jtagUploadBitstream,
|
||||||
jtagDownloadBitstream,
|
jtagDownloadBitstream,
|
||||||
|
|
Loading…
Reference in New Issue