Files
templates/c/logic-scope/include/logic_stream.h
T

38 lines
2.0 KiB
C

#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