Добавить непрерывные окна и цифровой триггер Scope

This commit is contained in:
2026-11-09 02:51:28 +03:00
parent f0edb70dbe
commit a640f98f74
3 changed files with 42 additions and 0 deletions
+2
View File
@@ -19,3 +19,5 @@ Its `tests/test_logic_scope.c` checks the capture plan, phase-shifted PWM,
constant inputs, menu selection, retained snapshots, and renderer bounds.
`include/scope_decoders.h` contains the portable DSView catalogue/configuration/annotation model; the isolated ARM adapter is in `tools/scope-decoders`. The framebuffer UI and UIO acquisition live in the Zynq board project.
`include/logic_stream.h` assembles contiguous stream blocks into bounded windows, checks block sequence, preserves trigger edges across block boundaries, and stops after one window in SINGLE. FREE/RISE/FALL/HIGH/LOW use an explicitly selected D0-D7 input. Frame publication is independent of how many windows the display renders. The board integration owns DMA acknowledgement, overflow handling and exclusive UIO access.
+3
View File
@@ -9,6 +9,9 @@ typedef struct {
uint8_t samples[LOGIC_SCOPE_MAX];
unsigned mode[8]; /* 0 off, 1 logic, 2 PWM envelope */
unsigned count, clock, divider, running, single, generation;
unsigned trigger_mode, trigger_channel; /* FREE, RISE, FALL, HIGH, LOW */
unsigned stream, stream_rate; /* Separate acquisition mode; rate 0 follows timebase. */
uint64_t stream_samples;
double origin_s;
char status[96];
} LogicScope;
+37
View File
@@ -0,0 +1,37 @@
#ifndef SET_LOGIC_STREAM_H
#define SET_LOGIC_STREAM_H
#include "logic_scope.h"
typedef struct { uint8_t pending[LOGIC_SCOPE_MAX]; unsigned filled,target,previous,have_previous,triggered,sequence; } LogicStream;
static inline unsigned logic_stream_divider(double span,unsigned rate) {
static const unsigned fixed[]={0,1000,100,20,10};
if(rate>0&&rate<5)return fixed[rate];
double value=ceil(span*100000000.0/LOGIC_SCOPE_MAX);
return !isfinite(value)||value<10?10:value>65535?65535:(unsigned)value;
}
static inline void logic_stream_reset(LogicStream *state,unsigned target) {
memset(state,0,sizeof(*state));state->target=target<1?1:target>LOGIC_SCOPE_MAX?LOGIC_SCOPE_MAX:target;
}
static inline int logic_stream_match(unsigned mode,unsigned previous,unsigned current,unsigned valid,unsigned channel) {
unsigned mask=1u<<(channel&7),a=previous&mask,b=current&mask;
return !mode || (mode==1&&valid&&!a&&b)||(mode==2&&valid&&a&&!b)||(mode==3&&b)||(mode==4&&!b);
}
/* Sequence continuity is checked before touching the displayed frame. */
static inline int logic_stream_feed(LogicStream *state,LogicScope *scope,unsigned sequence,const uint8_t *bytes,unsigned count) {
if(sequence!=state->sequence)return -1;
++state->sequence;scope->stream_samples+=count;int updated=0;
unsigned i=0;
while(i<count){
while(!state->triggered&&i<count){unsigned current=bytes[i];
state->triggered=logic_stream_match(scope->trigger_mode,state->previous,current,state->have_previous,scope->trigger_channel);
if(!state->triggered){state->previous=current;state->have_previous=1;++i;}
}
if(i==count)break;
unsigned take=state->target-state->filled;if(take>count-i)take=count-i;
memcpy(state->pending+state->filled,bytes+i,take);state->filled+=take;i+=take;
state->previous=bytes[i-1];state->have_previous=1;
if(state->filled==state->target){memcpy(scope->samples,state->pending,state->target);scope->count=state->target;scope->origin_s=0;++scope->generation;updated=1;state->filled=0;state->triggered=0;
if(scope->single){scope->single=scope->running=0;break;}
}
}return updated;
}
#endif