void dss_lfsr_step(struct node_description *node) { const struct discrete_lfsr_desc *lfsr_desc = node->custom; struct dss_lfsr_context *context = node->context; PRECISION shiftAmount; int fb0,fb1,fbresult,i; /* Reset everything if necessary */ if((node->input[1] ? 1 : 0) == ((lfsr_desc->flags & DISC_LFSR_FLAG_RESET_TYPE_H) ? 1 : 0)) { dss_lfsr_reset(node); } i=0; /* Calculate the number of full shift register cycles since last machine sample. */ shiftAmount = ((context->sampleStep + context->t) / context->shiftStep); context->t = (shiftAmount - (int)shiftAmount) * context->shiftStep; /* left over amount of time */ while(i<(int)shiftAmount) { i++; /* Now clock the LFSR by 1 cycle and output */ /* Fetch the last feedback result */ fbresult=((context->lfsr_reg)>>(lfsr_desc->bitlength))&0x01; /* Stage 2 feedback combine fbresultNew with infeed bit */ fbresult=dss_lfsr_function(lfsr_desc->feedback_function1,fbresult,((node->input[4])?0x01:0x00),0x01); /* Stage 3 first we setup where the bit is going to be shifted into */ fbresult=fbresult*lfsr_desc->feedback_function2_mask; /* Then we left shift the register, */ context->lfsr_reg=(context->lfsr_reg)<<1; /* Now move the fbresult into the shift register and mask it to the bitlength */ context->lfsr_reg=dss_lfsr_function(lfsr_desc->feedback_function2,fbresult, (context->lfsr_reg), ((1<<(lfsr_desc->bitlength))-1)); /* Now get and store the new feedback result */ /* Fetch the feedback bits */ fb0=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel0))&0x01; fb1=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel1))&0x01; /* Now do the combo on them */ fbresult=dss_lfsr_function(lfsr_desc->feedback_function0,fb0,fb1,0x01); context->lfsr_reg=dss_lfsr_function(DISC_LFSR_REPLACE,(context->lfsr_reg), fbresult<<(lfsr_desc->bitlength), ((2<<(lfsr_desc->bitlength))-1)); /* Now select the output bit */ node->output=((context->lfsr_reg)>>(lfsr_desc->output_bit))&0x01; /* Final inversion if required */ if(lfsr_desc->flags & DISC_LFSR_FLAG_OUT_INVERT) node->output=(node->output)?0.0:1.0; /* Gain stage */ node->output=(node->output)?(node->input[3])/2:-(node->input[3])/2; /* Bias input as required */ node->output=node->output+node->input[5]; } if(!node->input[0]) { node->output=0; } }
int dss_lfsr_init(struct node_description *node) { struct dss_lfsr_context *context; discrete_log("dss_lfsr_init() - Creating node %d.",node->node-NODE_00); /* Allocate memory for the context array and the node execution order array */ if((node->context=malloc(sizeof(struct dss_lfsr_context)))==NULL) { discrete_log("dss_lfsr_init() - Failed to allocate local context memory."); return 1; } else { /* Initialise memory */ memset(node->context,0,sizeof(struct dss_lfsr_context)); } /* Initialise the object */ context=(struct dss_lfsr_context*)node->context; context->sampleStep = 1.0 / Machine->sample_rate; context->shiftStep = 1.0 / node->input[2]; context->t = 0; dss_lfsr_reset(node); return 0; }
void dss_lfsr_step(struct node_description *node) { const struct discrete_lfsr_desc *lfsr_desc = node->custom; struct dss_lfsr_context *context = node->context; double cycles; int clock, inc = 0; int fb0,fb1,fbresult; if (lfsr_desc->clock_type == DISC_CLK_IS_FREQ) { /* We need to keep clocking the internal clock even if disabled. */ cycles = (context->t_left + discrete_current_context->sample_time) / context->t_clock; inc = (int)cycles; context->t_left = (cycles - inc) * context->t_clock; } /* Reset everything if necessary */ if((DSS_LFSR_NOISE__RESET ? 1 : 0) == ((lfsr_desc->flags & DISC_LFSR_FLAG_RESET_TYPE_H) ? 1 : 0)) { dss_lfsr_reset(node); return; } switch (lfsr_desc->clock_type) { case DISC_CLK_ON_F_EDGE: case DISC_CLK_ON_R_EDGE: /* See if the clock has toggled to the proper edge */ clock = (DSS_LFSR_NOISE__CLOCK != 0); if (context->last != clock) { context->last = clock; if (lfsr_desc->clock_type == clock) { /* Toggled */ inc = 1; } } break; case DISC_CLK_BY_COUNT: /* Clock number of times specified. */ inc = (int)DSS_LFSR_NOISE__CLOCK; break; } for (clock = 0; clock < inc; clock++) { /* Fetch the last feedback result */ fbresult=((context->lfsr_reg)>>(lfsr_desc->bitlength))&0x01; /* Stage 2 feedback combine fbresultNew with infeed bit */ fbresult=dss_lfsr_function(lfsr_desc->feedback_function1,fbresult,((DSS_LFSR_NOISE__FEED)?0x01:0x00),0x01); /* Stage 3 first we setup where the bit is going to be shifted into */ fbresult=fbresult*lfsr_desc->feedback_function2_mask; /* Then we left shift the register, */ context->lfsr_reg=(context->lfsr_reg)<<1; /* Now move the fbresult into the shift register and mask it to the bitlength */ context->lfsr_reg=dss_lfsr_function(lfsr_desc->feedback_function2,fbresult, (context->lfsr_reg), ((1<<(lfsr_desc->bitlength))-1)); /* Now get and store the new feedback result */ /* Fetch the feedback bits */ fb0=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel0))&0x01; fb1=((context->lfsr_reg)>>(lfsr_desc->feedback_bitsel1))&0x01; /* Now do the combo on them */ fbresult=dss_lfsr_function(lfsr_desc->feedback_function0,fb0,fb1,0x01); context->lfsr_reg=dss_lfsr_function(DISC_LFSR_REPLACE,(context->lfsr_reg), fbresult<<(lfsr_desc->bitlength), ((2<<(lfsr_desc->bitlength))-1)); /* Now select the output bit */ node->output=((context->lfsr_reg)>>(lfsr_desc->output_bit))&0x01; /* Final inversion if required */ if(lfsr_desc->flags & DISC_LFSR_FLAG_OUT_INVERT) node->output=(node->output)?0.0:1.0; /* Gain stage */ node->output=(node->output)?(DSS_LFSR_NOISE__AMP)/2:-(DSS_LFSR_NOISE__AMP)/2; /* Bias input as required */ node->output=node->output+DSS_LFSR_NOISE__BIAS; } if(!DSS_LFSR_NOISE__ENABLE) { node->output=0; } }