61 lines
2.0 KiB
C
61 lines
2.0 KiB
C
#ifndef SET_LOGIC_SCOPE_H
|
|
#define SET_LOGIC_SCOPE_H
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#define LOGIC_SCOPE_MAX 65536u
|
|
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;
|
|
double origin_s;
|
|
char status[96];
|
|
} LogicScope;
|
|
|
|
static inline unsigned logic_scope_channels(const LogicScope *s)
|
|
{
|
|
unsigned n=0;
|
|
for (unsigned i=0;i<8;++i) n+=s->mode[i]!=0;
|
|
return n;
|
|
}
|
|
|
|
/* Capture the requested interval with the finest representable sample period. */
|
|
static inline int logic_scope_plan(double span, unsigned clock, unsigned depth,
|
|
unsigned *count, unsigned *divider)
|
|
{
|
|
if (!isfinite(span) || span<=0 || !clock || depth<2 || depth>LOGIC_SCOPE_MAX) return 0;
|
|
double ticks=ceil(span*clock/depth);
|
|
ticks=fmax(1,fmin(65536,ticks));
|
|
*divider=(unsigned)ticks-1;
|
|
*count=(unsigned)fmax(2,fmin(depth,ceil(span*clock/ticks)));
|
|
return 1;
|
|
}
|
|
|
|
typedef void (*LogicScopePoint)(void *context, double time, double value);
|
|
/* Ignore clipped first/last cycles. A constant level has no measurable period. */
|
|
static inline unsigned logic_scope_pwm(const LogicScope *s, unsigned ch,
|
|
LogicScopePoint point, void *context)
|
|
{
|
|
if (ch>=8 || !s->clock || s->count<2) return 0;
|
|
unsigned rise=0,fall=0,have_rise=0,have_fall=0,n=0;
|
|
unsigned previous=(s->samples[0]>>ch)&1u;
|
|
double dt=(s->divider+1.0)/s->clock;
|
|
for (unsigned i=1;i<s->count;++i) {
|
|
unsigned level=(s->samples[i]>>ch)&1u;
|
|
if (level!=previous) {
|
|
if (level) {
|
|
if (have_rise && have_fall) {
|
|
point(context,s->origin_s+(rise+(i-rise)*0.5)*dt,
|
|
2.0*(fall-rise)/(i-rise)-1.0);
|
|
++n;
|
|
}
|
|
rise=i; have_rise=1; have_fall=0;
|
|
} else if (have_rise) { fall=i; have_fall=1; }
|
|
}
|
|
previous=level;
|
|
}
|
|
return n;
|
|
}
|
|
#endif
|