diff --git a/src/dsp/cmDspFx.c b/src/dsp/cmDspFx.c index 67252a5..bbb1c68 100644 --- a/src/dsp/cmDspFx.c +++ b/src/dsp/cmDspFx.c @@ -2909,6 +2909,7 @@ typedef struct cmDspScalar_str cmDspInst_t inst; _cmDspScalarOpFunc_t func; unsigned inPortCnt; + bool allActiveFl; } cmDspScalarOp_t; cmDspRC_t _cmDspScalarOpFuncMult(cmDspCtx_t* ctx, cmDspInst_t* inst ) @@ -2966,6 +2967,7 @@ cmDspInst_t* _cmDspScalarOpAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig double dfltVal[ inPortCnt ]; unsigned i; _cmDspScalarOpFunc_t fp = NULL; + bool allActiveFl = false; // validate the count of input ports if( inPortCnt == 0 ) @@ -2974,12 +2976,26 @@ cmDspInst_t* _cmDspScalarOpAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig goto errLabel; } - // locate the operation function - if( strcmp(opIdStr,"*") == 0 ) - fp = _cmDspScalarOpFuncMult; - else - if( strcmp(opIdStr,"+") == 0 ) - fp = _cmDspScalarOpFuncAdd; + if( opIdStr != NULL ) + { + switch( opIdStr[0] ) + { + case '*': + fp = _cmDspScalarOpFuncMult; + break; + case '+': + fp = _cmDspScalarOpFuncAdd; + break; + } + + // if the second character of the operator string is '$' then all input ports trigger an output + if( strlen( opIdStr ) > 0 && opIdStr[1]=='$' ) + allActiveFl = true; + + + } + + // validate the operation function if( fp == NULL ) @@ -3012,7 +3028,7 @@ cmDspInst_t* _cmDspScalarOpAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsig p->inPortCnt = inPortCnt; p->func = fp; - + p->allActiveFl = allActiveFl; va_end(vl1); return &p->inst; @@ -3039,7 +3055,7 @@ cmDspRC_t _cmDspScalarOpRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_ if((rc = cmDspSetEvent(ctx,inst,evt)) == kOkDspRC ) { - if( evt->dstVarId == kBaseOpdSoId ) + if( evt->dstVarId == kBaseOpdSoId || p->allActiveFl ) p->func(ctx,inst); } diff --git a/src/dsp/cmDspPgm.c b/src/dsp/cmDspPgm.c index 6725238..fb347bb 100644 --- a/src/dsp/cmDspPgm.c +++ b/src/dsp/cmDspPgm.c @@ -898,7 +898,7 @@ cmDspRC_t _cmDspSysPgm_UiTest(cmDspSysH_t h, void** userPtrPtr ) cmDspInst_t* prp = cmDspSysAllocInst(h,"Printer", NULL, 1, ">" ); cmDspInst_t* mtp = cmDspSysAllocInst(h,"Meter", "meter", 3, 0.0, 0.0, 4.0); cmDspInst_t* ctp = cmDspSysAllocInst(h,"Counter", NULL, 3, 0.0, 10.0, 1.0 ); - cmDspSysAllocInst(h,"Label", "label1", 1, "label2"); + cmDspInst_t* lbl = cmDspSysAllocInst(h,"Label", "label1", 1, "label2"); if((rc = cmDspSysLastRC(h)) != kOkDspRC ) return rc; @@ -924,6 +924,8 @@ cmDspRC_t _cmDspSysPgm_UiTest(cmDspSysH_t h, void** userPtrPtr ) cmDspSysInstallCb(h, chb, "out", prp, "in", NULL ); cmDspSysInstallCb(h, chb, "sym", prp, "in", NULL ); + cmDspSysInstallCb(h, mdp, "val", lbl, "in", NULL ); + return rc; } @@ -2055,8 +2057,8 @@ cmDspRC_t _cmDspSysPgm_ScalarOp( cmDspSysH_t h, void** userPtrPtr ) { cmDspRC_t rc; - cmDspInst_t* add = cmDspSysAllocInst( h, "ScalarOp", NULL, 6, 2, "+", "in-0", 0.0, "in-1", 0.0 ); - cmDspInst_t* mul0 = cmDspSysAllocInst( h, "ScalarOp", NULL, 6, 2, "*", "in-0", 0.0, "in-1", 0.0 ); + cmDspInst_t* add = cmDspSysAllocInst( h, "ScalarOp", NULL, 6, 2, "+", "in-0", 0.0, "in-1", 0.0 ); + cmDspInst_t* mul0 = cmDspSysAllocInst( h, "ScalarOp", NULL, 6, 2, "*$", "in-0", 0.0, "in-1", 0.0 ); cmDspInst_t* mul1 = cmDspSysAllocInst( h, "ScalarOp", NULL, 6, 2, "*", "in-0", 0.0, "in-1", 0.0 ); cmDspInst_t* in = cmDspSysAllocScalar( h, "Input", 0.0, 10.0, 0.001, 0.0); cmDspInst_t* in_m = cmDspSysAllocScalar( h, "Input_M", 0.0, 10.0, 0.001, 0.0); @@ -2068,6 +2070,18 @@ cmDspRC_t _cmDspSysPgm_ScalarOp( cmDspSysH_t h, void** userPtrPtr ) if((rc = cmDspSysLastRC(h)) != kOkDspRC ) goto errLabel; + // Notice that changing 'in' or 'in_m' causes 'out' to be recomputed, but other + // changes are cached prior to 'add'. This prevents the program from going into + // an infinite loop. + // + // in -> mult0 + // in_m -> mult0--+ + // +-->fb -> mult1 +----> add + // | fb_m -> mult1-------> add --------+------> out + // | | + // +-------------------------------------+ + // + cmDspSysInstallCb( h, in, "val", mul0, "in-0", NULL ); cmDspSysInstallCb( h, in_m, "val", mul0, "in-1", NULL ); cmDspSysInstallCb( h, fb, "val", mul1, "in-0", NULL );