Compare commits

..

2 Commits

Author SHA1 Message Date
alivender 5103145d01 feat:为边界扫描添加自动重复扫描 2025-07-20 10:34:42 +08:00
alivender 27c8ceb1db fix:修复七段数码管的显示问题 2025-07-20 10:33:57 +08:00
2 changed files with 155 additions and 15 deletions

View File

@ -79,6 +79,7 @@ interface SevenSegmentDisplayProps {
size?: number;
color?: string;
AFTERGLOW_BUFFER_SIZE?: number; //
AFTERGLOW_DURATION?: number; //
pins?: {
pinId: string;
constraint: string;
@ -92,7 +93,7 @@ const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
size: 1,
color: "red",
AFTERGLOW_BUFFER_SIZE: 1, // 100
AFTERGLOW_UPDATE_INTERVAL: 5, // 2
AFTERGLOW_DURATION: 2000, // 500
cathodeType: "common", //
pins: () => [
{ pinId: "a", constraint: "", x: 10, y: 170 }, // a
@ -149,7 +150,7 @@ const afterglowBuffers = ref<Record<string, boolean[]>>({
});
// 10
const STABLE_THRESHOLD = 10;
const STABLE_THRESHOLD = 3;
//
const stableSegmentStates = ref({
@ -175,10 +176,54 @@ const segmentStableCounters = ref<Record<string, number>>({
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(
segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
): boolean {
// 使
if (isInAfterglowMode.value) {
return afterglowStates.value[segment];
}
// COM
if (!currentComActive.value) {
return false;
}
// 使
return stableSegmentStates.value[segment];
}
@ -186,21 +231,45 @@ function isSegmentActive(
function updateSegmentStates() {
// COM
const comPin = props.pins.find((p) => p.pinId === "COM");
let comActive = true;
let comActive = false; //
if (comPin && comPin.constraint) {
const comState = getConstraintState(comPin.constraint);
if (props.cathodeType === "anode") {
// anodeCOM
comActive = comState !== "high";
// COM
comActive = comState === "low";
} else {
// COM
comActive = comState === "low";
}
//
} else if (!comPin || !comPin.constraint) {
// COMCOM
comActive = true;
}
// COM
if (comActive) {
updateAfterglowBuffers();
// COM
const comStateChanged = currentComActive.value !== comActive;
currentComActive.value = comActive;
// COM
if (comStateChanged && !comActive) {
enterAfterglowMode();
return; //
}
// COM退
if (comStateChanged && comActive) {
exitAfterglowMode();
}
// COM
if (!comActive || isInAfterglowMode.value) {
return;
}
// COM
updateAfterglowBuffers();
// segmentStates
for (const pin of props.pins) {
if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
@ -215,7 +284,8 @@ function updateSegmentStates() {
} else {
newState = pinState === "low";
}
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState && comActive;
// COM
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState;
}
}
@ -255,6 +325,49 @@ 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) {
const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
@ -276,6 +389,15 @@ onMounted(() => {
onConstraintStateChange(onConstraintChange);
});
onUnmounted(() => {
//
for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
if (afterglowTimers.value[segmentId]) {
clearTimeout(afterglowTimers.value[segmentId]!);
}
}
});
//
defineExpose({
updateSegmentStates,
@ -307,6 +429,7 @@ export function getDefaultProps() {
size: 1,
color: "red",
cathodeType: "common",
AFTERGLOW_DURATION: 500, // 500
pins: [
{ pinId: "a", constraint: "", x: 10, y: 170 },
{ pinId: "b", constraint: "", x: 25 - 1, y: 170 },

View File

@ -22,6 +22,8 @@ export const useEquipments = defineStore("equipments", () => {
// Jtag
const jtagBitstream = ref<File>();
const jtagBoundaryScanFreq = ref(100);
const jtagBoundaryScanErrorCount = ref(0); // 边界扫描连续错误计数
const maxJtagBoundaryScanErrors = 5; // 最大允许连续错误次数
const jtagClientMutex = withTimeout(
new Mutex(),
1000,
@ -50,7 +52,11 @@ export const useEquipments = defineStore("equipments", () => {
// Watch
watchPostEffect(async () => {
if (true === enableJtagBoundaryScan.value) jtagBoundaryScan();
if (true === enableJtagBoundaryScan.value) {
// 重新启用时重置错误计数器
jtagBoundaryScanErrorCount.value = 0;
jtagBoundaryScan();
}
});
// Parse and Set
@ -109,10 +115,20 @@ export const useEquipments = defineStore("equipments", () => {
);
constrainsts.batchSetConstraintStates(portStates);
// 扫描成功,重置错误计数器
jtagBoundaryScanErrorCount.value = 0;
} catch (error) {
dialog.error("边界扫描发生错误");
console.error(error);
enableJtagBoundaryScan.value = false;
jtagBoundaryScanErrorCount.value++;
console.error(`边界扫描错误 (${jtagBoundaryScanErrorCount.value}/${maxJtagBoundaryScanErrors}):`, error);
// 如果错误次数超过最大允许次数,才停止扫描并显示错误
if (jtagBoundaryScanErrorCount.value >= maxJtagBoundaryScanErrors) {
dialog.error("边界扫描发生连续错误,已自动停止");
enableJtagBoundaryScan.value = false;
jtagBoundaryScanErrorCount.value = 0; // 重置错误计数器
}
} finally {
release();
@ -267,6 +283,7 @@ export const useEquipments = defineStore("equipments", () => {
enableJtagBoundaryScan,
jtagBitstream,
jtagBoundaryScanFreq,
jtagBoundaryScanErrorCount,
jtagClientMutex,
jtagUploadBitstream,
jtagDownloadBitstream,