Добавить непрерывные окна и цифровой триггер Scope
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user