20 #include <registryFunction.h> 22 #include <menuFtype.h> 23 #include <aSubRecord.h> 26 #define NINPUTS (aSubRecordU - aSubRecordA) 31 menuFtype seq_repeat_ft[] = {
32 menuFtypeULONG, menuFtypeULONG, menuFtypeULONG, menuFtypeDOUBLE, menuFtypeUCHAR
36 menuFtype seq_repeat_ftv[] = {
37 menuFtypeDOUBLE, menuFtypeDOUBLE, menuFtypeUCHAR
69 epicsUInt32 num_cycles, per_mask, len_in, len_out, num_out;
71 double *cycle_D = prec->d;
72 epicsUInt8 *cycle_C = prec->e;
75 double *period_D = prec->valb;
76 epicsUInt8 *period_C = prec->valc;
78 if(prec->nsev>=INVALID_ALARM)
83 for(i=0; i<NELEMENTS(seq_repeat_ft); i++) {
84 if((&prec->fta)[i]!=seq_repeat_ft[i]) {
85 epicsPrintf(
"%s: Invalid type for FT%c\n", prec->name,
'A'+i);
88 if((&prec->nea)[i]==0) {
89 epicsPrintf(
"%s.NE%c empty\n", prec->name,
'A'+i);
94 for(i=0; i<NELEMENTS(seq_repeat_ftv); i++) {
95 if((&prec->ftva)[i]!=seq_repeat_ftv[i]) {
96 epicsPrintf(
"%s: Invalid type for FTV%c\n", prec->name,
'A'+i);
99 if((&prec->nova)[i]==0) {
100 epicsPrintf(
"%s.NOV%c empty\n", prec->name,
'A'+i);
105 period = *(epicsUInt32*)prec->a;
106 num_cycles = *(epicsUInt32*)prec->b;
107 per_mask = *(epicsUInt32*)prec->c;
110 if(len_in > prec->nee)
113 len_out = prec->novb;
114 if(len_out > prec->novc)
115 len_out = prec->novc;
119 }
else if(num_cycles>32) {
120 epicsPrintf(
"%s: Num cycles is out of range", prec->name);
125 add = period/num_cycles;
127 if(len_in * num_cycles > len_out) {
128 epicsPrintf(
"%s: Not enough elements for result. Have %u, need %u\n",
129 prec->name, len_out, len_in * num_cycles);
133 if( period%num_cycles ) {
134 epicsPrintf(
"%s: %u cycles does not evenly divide period %u", prec->name, num_cycles, period);
138 *(
double*)prec->vala = add;
141 for(N=0; per_mask && N<num_cycles; N++, per_mask>>=1) {
144 for(i=0; i<len_in; i++) {
145 if(cycle_D[i]>=add) {
149 *period_D++ = cycle_D[i] + add*
N;
150 *period_C++ = cycle_C[i];
155 if(num_out==0 || len_in==0) {
159 prec->nevb = prec->nevc = 1;
161 prec->nevb = prec->nevc = num_out * len_in;
167 recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
194 unsigned int ninputs;
196 epicsUInt32 maxout = prec->nova;
197 double *out_T = prec->vala;
198 epicsUInt8 *out_C = prec->valb;
200 if(prec->nsev>=INVALID_ALARM)
203 memset(in_pos, 0,
sizeof(in_pos));
205 if(maxout > prec->novb)
209 if(prec->ftva!=menuFtypeDOUBLE || prec->ftvb!=menuFtypeUCHAR ||
210 prec->nova==0 || prec->novb==0)
212 epicsPrintf(
"%s: Invalid types for lengths for VALA and/or VALB\n", prec->name);
219 if((&prec->fta)[2*N]!=menuFtypeDOUBLE)
221 if((&prec->fta)[2*N+1]!=menuFtypeUCHAR)
225 if((&prec->nea)[2*N]!=(&prec->nea)[2*N+1]) {
226 epicsPrintf(
"%s: NE%c (%d) != NE%c (%d)\n",
228 (
char)(
'A'+2*N), (&prec->nea)[2*N],
229 (
char)(
'A'+2*N+1), (&prec->nea)[2*N+1]);
238 epicsPrintf(
"%s: No inputs configured!\n", prec->name);
243 printf(
"%s Merge\n", prec->name);
246 for(i=0; i<maxout; i++) {
248 int found_element = -1;
249 double last_time = -1.0;
251 for(N=0; N<ninputs; N++) {
255 T = (
double*)(&prec->a)[2*
N];
256 C = (epicsUInt8*)(&prec->a)[2*N+1];
258 while(in_pos[N]<(&prec->nea)[2*
N] && C[in_pos[
N]]==0)
261 if(in_pos[N]==(&prec->nea)[2*
N])
264 if(found_element==-1 || T[in_pos[N]]<last_time) {
266 out_T[i] = T[in_pos[
N]];
267 out_C[i] = C[in_pos[
N]];
268 last_time = out_T[i];
270 }
else if(T[in_pos[N]]==last_time && found_element!=-1) {
272 printf(
"%s: Dup timestamp. %c[%u] and %c[%u]\n",
274 'A'+(2*found_element), in_pos[found_element]-1,
275 'A'+(2*N), in_pos[N]);
276 printf(
" Found element: %d\n", found_element);
277 printf(
" i=%u, N=%u, ninputs=%u\n", i, N, ninputs);
278 printf(
" Out %u C=%u T=%f [", i, out_C[i], out_T[i]);
279 for(N=0; N<ninputs; N++)
280 printf(
"%u, ", in_pos[N/2]);
286 if(found_element==-1) {
289 }
else if(i>0 && out_T[i] < out_T[i-1]) {
290 epicsPrintf(
"%s: input %c times not sorted!\n", prec->name,
'A'+(2*found_element));
293 in_pos[found_element]++;
297 printf(
"Out %u C=%u T=%f [", i, out_C[i], out_T[i]);
298 for(N=0; N<ninputs; N++)
299 printf(
"%u, ", in_pos[N/2]);
305 epicsPrintf(
"%s: merge result has %u element\n", prec->name, i);
310 unsigned int nogood = 0;
311 for(N=0; N<ninputs; N++) {
312 if(in_pos[N]!=(&prec->nea)[2*N]) {
313 epicsPrintf(
"%s.%c: Not completely consumed! %u of %u\n",
314 prec->name,
'A'+(2*N), in_pos[N], (&prec->nea)[2*N]);
325 epicsPrintf(
"%s: merged yields empty sequence\n", prec->name);
345 recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
365 const double *input=(
const double*)prec->b;
366 double *output=(
double*)prec->vala;
369 if(prec->fta!=menuFtypeDOUBLE
370 || prec->ftb!=menuFtypeDOUBLE
371 || prec->ftva!=menuFtypeDOUBLE)
373 epicsPrintf(
"%s: invalid types\n", prec->name);
375 }
else if(prec->nea==0 || prec->neb > prec->nova) {
376 epicsPrintf(
"%s: incorrect sizes\n", prec->name);
380 delay = *(
double*)prec->a;
382 for(i=0; i<prec->neb; i++)
383 output[i] = input[i]+
delay;
385 prec->neva = prec->neb;
390 recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM);
409 const epicsUInt8 *inp = (
const epicsUInt8*)prec->a;
410 const epicsUInt32 *mask = (
const epicsUInt32*)prec->b;
411 epicsUInt8 *out = (epicsUInt8*)prec->vala;
412 epicsUInt32 i, num = prec->neb*32;
419 for(i=0; i<num; i++) {
420 epicsUInt8 M = (mask[i/32]>>(i%32))&0x1;
421 out[i] = M ? inp[i] : 0;
429 static registryFunctionRef asub_seq[] = {
430 {
"Seq Repeat", (REGISTRYFUNCTION)
seq_repeat},
431 {
"Seq Merge", (REGISTRYFUNCTION)
seq_merge},
432 {
"Seq Shift", (REGISTRYFUNCTION)
seq_shift},
433 {
"Seq Mask", (REGISTRYFUNCTION)
seq_mask},
437 void asub_evg(
void) {
438 registryFunctionRefAdd(asub_seq, NELEMENTS(asub_seq));
441 #include <epicsExport.h> long seq_merge(aSubRecord *prec)
Merge several sorted sequences.
long seq_repeat(aSubRecord *prec)
Periodically repeat a given set of event codes and time delays. A bit mask selects if each possible r...
epicsExportRegistrar(asub_evg)
long seq_mask(aSubRecord *prec)
Sequence masker.
epicsExportAddress(int, seqConstDebug)
long seq_shift(aSubRecord *prec)
Sequence shifter.