/************************************************************************** ** ** ir.c - support for IR Arrays . ** *************************************************************************** */ #define EXTERN extern /*-------------------------- ** include files **-------------------------- */ #if LINUX #include #include #include #include #include #else #include // uboot general include file #include // uboot general include file #endif #include "ce.h" #include "ir.h" #ifdef LINUX unsigned int upper_digout = 0; unsigned int lower_digout = 0; #endif /*---------------------------------------------------------------------------------------- ** ir_seq_open () - allocates memory for the ir_seq_out_t structure. ** **--------------------------------------------------------------------------------------- */ void ir_seq_open ( struct ir_seq_t * s, /* O: allocate buffer for this structure */ int n, /* I: number of CE words to allocate for ck */ int clear_opt /* I: True to do memset(0) on ck (for stack variables) */ ) { /* set buffer to all zeros - caller option */ if( clear_opt ) memset( s, 0, sizeof(struct ir_seq_t)); /* frees previously allocated memory */ ir_seq_close( s ); s->seq = malloc( sizeof(char)*n ); s->n = 0; } /*---------------------------------------------------------------------------------------- ** ir_seq_close () - IR Seq Close. ** Frees memory allocated by al_seq_open() **--------------------------------------------------------------------------------------- */ void ir_seq_close ( struct ir_seq_t * s /* O: free buffers in seq struct */ ) { if( s->seq != NULL ) { free( s->seq ); s->seq = NULL; } } /*---------------------------------------------------------------------------------------- ** ir_seq_generate_seq () - Generate a sequence ** returns PASS or FAIL. **--------------------------------------------------------------------------------------- */ int ir_seq_generate_ce_data ( struct ir_seq_t * s, /* O: sequence data returned here. */ struct ir_seq_in_t * in, /* I: input to generate sequence data */ FILE * fp /* O: for debug output */ ) { int c, n, rc; int64_t total_usec; /* copy all the inputs to s-> */ s->cbmode = in->cbmode; s->itime_usec = in->itime_msec*1000; s->coadd = in->coadd; s->ndr = in->ndr; s->rsample = in->rsample; s->frame_usec = in->frame_usec; s->reset_usec = in->reset_usec; s->glr_enable = in->glr_enable; s->wait_usec = 0; /* caculated below */ s->total_msec = 0; /* caculated below */ s->n = 0; /* initialize to 0 */ /* ** calculate wait_usec, and possibly adjust itime, ndr, rsamples. */ rc = ir_seq_cal_wait_usec ( &s->wait_usec, &s->itime_usec, /* could be adjusted */ &s->ndr, /* could be adjusted */ &s->rsample, /* could be adjusted */ s->cbmode, s->itime_usec, s->ndr, s->rsample, s->frame_usec, s->glr_enable); if( rc ) return rc; total_usec = 0; if( s->cbmode == CBMODE_FS ) { /* GPS timestamp at begining of sequence */ s->seq[s->n++] = IR_SEQ_GPS_HIGH; total_usec += 30; /* shutter ON or OFF take 30 ns */ for( c=0; c < s->coadd; c++ ) { /* reset the array */ s->seq[s->n++] = IR_SEQ_RESET_ARRAY; total_usec += s->reset_usec; /* bring the GPS low */ if( c==0 ) { s->seq[s->n++] = IR_SEQ_GPS_LOW; total_usec += 30; /* shutter ON or OFF take 30 ns */ } /* wait */ s->seq[s->n++] = IR_SEQ_WAIT_USEC; total_usec += s->wait_usec; /* SAMPLE * ndr */ for( n=0; n < s->ndr; n++ ) { s->seq[s->n++] = IR_SEQ_SAMPLE_ARRAY; total_usec += s->frame_usec; } } s->total_msec = total_usec/1000LL; } else if( s->cbmode == CBMODE_FD ) { /* GPS timestamp at begining of sequence */ s->seq[s->n++] = IR_SEQ_GPS_HIGH; total_usec += 30; /* shutter ON or OFF take 30 ns */ for( c=0; c < s->coadd; c++ ) { /* reset the array */ s->seq[s->n++] = IR_SEQ_RESET_ARRAY; total_usec += s->reset_usec; /* bring the GPS low */ if( c==0 ) { s->seq[s->n++] = IR_SEQ_GPS_LOW; total_usec += 30; /* shutter ON or OFF take 30 ns */ } /* Pedestal * ndr */ for( n=0; n < s->ndr; n++ ) { s->seq[s->n++] = IR_SEQ_SAMPLE_ARRAY; total_usec += s->frame_usec; } /* wait */ s->seq[s->n++] = IR_SEQ_WAIT_USEC; total_usec += s->wait_usec; /* Samples * ndr */ for( n=0; n < s->ndr; n++ ) { s->seq[s->n++] = IR_SEQ_SAMPLE_ARRAY; total_usec += s->frame_usec; } } s->total_msec = total_usec/1000LL; } else if( s->cbmode == CBMODE_RAMP ) { /* GPS timestamp at begining of sequence */ s->seq[s->n++] = IR_SEQ_GPS_HIGH; total_usec += 30; /* shutter ON or OFF take 30 ns */ for( c=0; c < s->coadd; c++ ) { /* reset the array */ s->seq[s->n++] = IR_SEQ_RESET_ARRAY; total_usec += s->reset_usec; /* bring the GPS low */ if( c==0 ) { s->seq[s->n++] = IR_SEQ_GPS_LOW; total_usec += 30; /* shutter ON or OFF take 30 ns */ } /* clock 1st samples imediately after reset */ s->seq[s->n++] = IR_SEQ_SAMPLE_ARRAY; total_usec += s->frame_usec; for( n=1; n < s->rsample; n++ ) { /* wait between samples */ s->seq[s->n++] = IR_SEQ_WAIT_USEC; total_usec += s->wait_usec; /* up the ramp samples */ s->seq[s->n++] = IR_SEQ_SAMPLE_ARRAY; total_usec += s->frame_usec; } } s->total_msec = total_usec/1000LL; } #if LINUX /* ** Display verbose output */ if( fp ) { int i; ir_printf( fp, "# ir_seq_generate_ce_data() begin ---------------------\n"); if( in->ndr != s->ndr) ir_printf( fp, "ndr reduced from %d to %d \n", in->ndr, s->ndr); if( in->rsample != s->rsample) ir_printf( fp, "rsample reduced from %d to %d \n", in->rsample, s->rsample); if( (in->itime_msec*1000) != s->itime_usec ) ir_printf( fp, "itime changed from %d to %d \n\n", in->itime_msec*1000, s->itime_usec); ir_printf( fp, " cbmode %d \n", s->cbmode); ir_printf( fp, " itime %d usec\n", s->itime_usec); ir_printf( fp, " coadd %d \n", s->coadd); ir_printf( fp, " ndr %d \n", s->ndr); ir_printf( fp, " rsample %d \n", s->rsample); ir_printf( fp, " frame_usec %d \n", s->frame_usec); ir_printf( fp, " reset_usec %d \n", s->reset_usec); ir_printf( fp, " glr_enable %d \n", s->glr_enable); ir_printf( fp, " wait_usec %d \n", s->wait_usec); ir_printf( fp, " total_msec %d \n", s->total_msec); ir_printf( fp, " n %d \n", s->n); for( i=0; in; i++ ) { if (s->seq[i] == IR_SEQ_GPS_HIGH ) { ir_printf( fp, "%3d [IR_SEQ_GPS_HIGH] \n", i ); } else if (s->seq[i] == IR_SEQ_GPS_LOW ) { ir_printf( fp, "%3d [IR_SEQ_GPS_LOW] \n", i ); } else if (s->seq[i] == IR_SEQ_RESET_ARRAY ) { ir_printf( fp, "%3d [IR_SEQ_RESET_ARRAY] glr_enable=%d reset_usec=%d\n", i, s->glr_enable, s->reset_usec ); } else if (s->seq[i] == IR_SEQ_SAMPLE_ARRAY ) { ir_printf( fp, "%3d [IR_SEQ_SAMPLE_ARRAY] frame_usec=%8d \n", i, s->frame_usec); } else if (s->seq[i] == IR_SEQ_WAIT_USEC ) { ir_printf( fp, "%3d [IR_SEQ_WAIT_USEC] wait_usec=%8d \n", i, s->wait_usec); } else { ir_printf( fp, "[IR_SEQ_UNKNOWN] ....bad data \n"); } } ir_printf( fp, "# ir_seq_generate_ce_data() ends ---------------------\n"); } #endif /* linux */ return PASS; } /*-------------------------------------------------------------------------------- ** ir_seq_cal_wait_usec() - calculated some timing varirbles given ** the cbmode, itime_usec, frame_usec, etc. ** return PASS or FAIL. **-------------------------------------------------------------------------------- */ int ir_seq_cal_wait_usec ( int * wait_usec_out, /* O: wait or sleep time in usec */ int * itime_usec_out, /* O: actual itime in usec (could be adjusted) */ int * ndr_out, /* O: ndrs (could be adjusted ) */ int * rsample_out, /* O: rsample_out( could be adjusted ) */ int cbmode, /* I: clock/buffer mode */ int itime_usec, /* I: requested integration time, microseconds */ int ndr, /* I: arc_s/arc_d: Requested number of ndr */ int rsample, /* I: ramp: Requested number of ramp samples */ int frame_usec, /* I: time to clock out array, microseconds */ int glr_enable /* I: global reset enable: T=global or F=clocking resets */ ) { int total_usec; int wait_usec; int reset_usec; /* reset_usec: - time a reset operation adds to the intergration time. ** For glr_enable == T, the reset time is 0. This function doesn't care how long ** the global reset pulse is, as integration time starts when the pulse is released. ** For glr_enable == F, reset time should be equal to frame_usec. Since reset is pixel ** by pixel, after the reset a pixels starts integrating. ** */ if( glr_enable ) reset_usec = 0; else reset_usec = frame_usec; if ( cbmode == CBMODE_FS ) { /* Input: itime_usec, frame_usec, ndr, reset_usec ** Output: wait_usec_out, itime_usec_out, ndr_out */ /* reduce NDR to fit inside the requested itime */ /* itime_usec = waitusec + (frame_usec*ndr)/2 */ total_usec = reset_usec + ((frame_usec * ndr) / 2); while ( (total_usec > itime_usec) && (ndr > 1)) { ndr--; total_usec = reset_usec + ((frame_usec * ndr) / 2); } total_usec = reset_usec + ((frame_usec * ndr) / 2); /* this is the mininum itime */ if ( total_usec > itime_usec ) /* itime need to be adjusted. */ itime_usec = total_usec; wait_usec = itime_usec - total_usec; /* return data to caller */ *wait_usec_out = wait_usec; *itime_usec_out = itime_usec; /* could have been adjusted */ *ndr_out = ndr; /* could have been adjusted */ *rsample_out = rsample; /* unused for this CBMODE */ return PASS; } else if ( cbmode==CBMODE_FD ) { /* Input: itime_usec, frame_usec, ndr ** Output: wait_usec_out, itime_usec_out, ndr_out */ /* reduce NDR to fit inside the requested itime */ total_usec = frame_usec * ndr; while ( (total_usec > itime_usec) && (ndr > 1)) { ndr--; total_usec = frame_usec * ndr; } if ( (frame_usec*ndr) > itime_usec ) // min. itime_usec is equal to (frame_usec*ndr) itime_usec = (frame_usec*ndr); wait_usec = itime_usec - (frame_usec*ndr); /* return data to caller */ *wait_usec_out = wait_usec; *itime_usec_out = itime_usec; /* could have been adjusted */ *ndr_out = ndr; /* could have been adjusted */ *rsample_out = rsample; /* unused for this CBMODE */ return PASS; } else if ( cbmode == CBMODE_RAMP ) { /* Input: itime_usec, frame_usec, rsample, reset_usec ** Output: wait_usec_out, itime_usec_out, rsample_out */ /* min. itime is 3 rsamples */ if( (reset_usec+(frame_usec*3)) > itime_usec ) itime_usec = reset_usec+(frame_usec*3); /* reduce the number of rsamples to obtain the desired itime */ total_usec = reset_usec + (frame_usec * (rsample-1)); while ( (total_usec > itime_usec) && (rsample > 4)) { rsample--; total_usec = reset_usec + (frame_usec * (rsample-1)); printf(" %d > %d , rsample=%d \n", total_usec, itime_usec, rsample); } /* calculate wait_usec - time between the RAMPs */ wait_usec = (itime_usec - total_usec ) / (rsample-1); /* return data to caller */ *wait_usec_out = wait_usec; *itime_usec_out = itime_usec; /* could have been adjusted */ *ndr_out = ndr; /* unused for this CBMODE */ *rsample_out = rsample; /* could have been adjusted */ return PASS; } /* invalid cbmode FAIL */ return FAIL; } /******************************************************************************/ /* IR CE functions */ /******************************************************************************/ /*---------------------------------------------------------------------------------------- ** ir_ce_open () - allocates memory for the ir_ce_buf_t structure. ** **--------------------------------------------------------------------------------------- */ void ir_ce_open ( struct ir_ce_buf_t * ceb, /* O: allocate buffer for ce data */ int n, /* I: number of CE words to allocate for ceb */ int clear_opt /* I: True to do memset(0) on ceb (for stack variables) */ ) { /* set buffer to all zeros - caller option */ if( clear_opt ) memset( ceb, 0, sizeof(struct ir_ce_buf_t)); /* frees previously allocated memory */ ir_ce_close( ceb ); ceb->cmd = malloc( sizeof(int)*n ); ir_ce_clear( ceb ); } /*---------------------------------------------------------------------------------------- ** ir_ce_close () - Frees memory allocated by ir_ce_open() **--------------------------------------------------------------------------------------- */ void ir_ce_close ( struct ir_ce_buf_t * ceb /* O: free buffers in ceb data */ ) { if( ceb->cmd != NULL ) { free( ceb->cmd ); ceb->cmd = NULL; } } /*---------------------------------------------------------------------------------------- ** ir_ce_clear () - clear out and CE data. ** Do this before adding new data **--------------------------------------------------------------------------------------- */ void ir_ce_clear ( struct ir_ce_buf_t * ceb /* O: free buffers in ceb data */ ) { ceb->n = 0; ceb->nsec = 0; } /*---------------------------------------------------------------------------------------- ** ir_ce_parseq_param () - Write CE commands that defines PSEQ (PARAM_PARSEQ_0 to 7) **--------------------------------------------------------------------------------------- */ void ir_ce_parseq_param( struct ir_ce_pseq_t *pseq, /* I/O: PSEQ wave form definition; pseq.nsec is updated. */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { int i, nsec; /* need to caculate the time it takes to execute 1 PSEQ iter */ pseq->nsec = 50; /* 50 nsec state time for each iter */ nsec = (10 << pseq->scale); /* unit for duration in nsec */ for( i=0; i<9; i++ ) { pseq->nsec += (pseq->dur[i] * nsec ) + 10; /* time slice + 10ns to skip table entries */ } /* debug output */ if( fp ) { ir_printf( fp, "#pseq_param:\n# dur:"); for(i=0; idur[i]); ir_printf( fp, " scale=%d\n", pseq->scale); ir_printf( fp, "# bit0: "); for(i=0; ibits[i]&0x01?1:0)); ir_printf( fp, "\n# bit1: "); for(i=0; ibits[i]&0x02?1:0)); ir_printf( fp, "\n# bit2: "); for(i=0; ibits[i]&0x04?1:0)); ir_printf( fp, "\n# bit3: "); for(i=0; ibits[i]&0x08?1:0)); ir_printf( fp, "\n"); } /* write data to CE. PARSEQ has 8 timeslices. */ nsec = IR_CE_PARAM_PARSEQ_NS; /* time to write PARSEQ_x data to CE */ ir_ce_put( CE_PARAM_PARSEQ_0 | ((pseq->dur[1] & 0x003f)<<10) | (pseq->dur[0]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_1 | ((pseq->dur[3]&0x03)<<14) | (pseq->dur[2]<<4) | ((pseq->dur[1]>>6)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_2 | ((pseq->dur[4]&0x00ff)<<8) | (pseq->dur[3]>>2) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_3 | ((pseq->dur[6]&0x0f)<<12) | (pseq->dur[5]<<2) | ((pseq->dur[4]>>8)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_4 | (pseq->dur[7]<<6) | (pseq->dur[6]>>4) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_5 | (pseq->bits[0]<<12) | (pseq->scale<<10) | (pseq->dur[8]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_6 | (pseq->bits[4]<<12) | (pseq->bits[3]<<8) | (pseq->bits[2]<<4) | (pseq->bits[1]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_PARSEQ_7 | (pseq->bits[8]<<12) | (pseq->bits[7]<<8) | (pseq->bits[6]<<4) | (pseq->bits[5]) , nsec, ceb, fp ); } /*---------------------------------------------------------------------------------------- ** ir_ce_parseq_exe () - Write CE_CMD_PARSEQ to execute the PSEQ **--------------------------------------------------------------------------------------- */ void ir_ce_parseq_exe( int iter, /* I: iteration value for pseq command. 1 to 32768 */ struct ir_ce_pseq_t *pseq, /* I: PSEQ data structure define the wave form */ struct ir_ce_buf_t * ceb, /* O: ce cmd written to this memory buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { /* Time to execute command is 20 ns startup + time for each iter */ ir_ce_put( CE_CMD_PARSEQ|CE_ITER(iter), 20 + (iter*pseq->nsec), ceb, fp ); } /*---------------------------------------------------------------------------------------- ** ir_ce_vidseq_param () - Write CE commands that defines ** VSEQ (PARAM_VIDSEQ_PG3_0/7 and PARAM_VIDSEQ_PG4_0/7 ) **--------------------------------------------------------------------------------------- */ void ir_ce_vidseq_param( struct ir_ce_vseq_t *vseq, /* I/O: PSEQ wave form definition; vseq.nsec is updated. */ struct ir_ce_buf_t * ceb, /* O: ce cmd written to this memory buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { int i, nsec; /*--------------------------- VIDSEQ_PG3 ---------------------------*/ /* calculate the time it for 1 PG3 */ vseq->pg3_nsec = 50; /* 50 ns for each iter */ for( i=0; i<9; i++ ) { vseq->pg3_nsec += (vseq->pg3_dur[i] * 10 ) + 10; /* duration + 10ns to skip table entries */ } /* debug output */ if( fp ) { ir_printf( fp, "#vseq_param PG3:\n# dur:"); for(i=0; ipg3_dur[i]); ir_printf( fp, "\n"); ir_printf( fp, "# PG3 bit0: "); for(i=0; ipg3_bits[i]&0x01?1:0)); ir_printf( fp, "\n# PG3 bit1: "); for(i=0; ipg3_bits[i]&0x02?1:0)); ir_printf( fp, "\n# PG3 bit2: "); for(i=0; ipg3_bits[i]&0x04?1:0)); ir_printf( fp, "\n"); } /* write data to CE. CE_PARAM_VIDSEQ_PG3_x has 8 timeslices. */ nsec = IR_CE_PARAM_VIDSEQ_NS; /* time to write CE_PARAM_VIDSEQ_PG3_x data to CE */ ir_ce_put( CE_PARAM_VIDSEQ_PG3_0 | ((vseq->pg3_dur[1] & 0x003f)<<10) | (vseq->pg3_dur[0]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_1 | ((vseq->pg3_dur[3]&0x03)<<14) | (vseq->pg3_dur[2]<<4) | ((vseq->pg3_dur[1]>>6)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_2 | ((vseq->pg3_dur[4]&0x00ff)<<8) | (vseq->pg3_dur[3]>>2) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_3 | ((vseq->pg3_dur[6]&0x0f)<<12) | (vseq->pg3_dur[5]<<2) | ((vseq->pg3_dur[4]>>8)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_4 | (vseq->pg3_dur[7]<<6) | (vseq->pg3_dur[6]>>4) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_5 | (vseq->reps<<10) | (vseq->pg3_dur[8]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_6 | ((vseq->pg3_bits[5]&0x01)<<15) | (vseq->pg3_bits[4]<<12) | (vseq->pg3_bits[3]<<9) | (vseq->pg3_bits[2]<<6) | (vseq->pg3_bits[1]<<3) | (vseq->pg3_bits[0]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG3_7 | (vseq->pg3_bits[8]<<8) | (vseq->pg3_bits[7]<<5) | (vseq->pg3_bits[6]<<2) | (vseq->pg3_bits[5]>>1) , nsec, ceb, fp ); /*--------------------------- VIDSEQ_PG4 ---------------------------*/ /* calculate the time for 1 PG4 ITER */ vseq->pg4_nsec = 70; /* 70 ns startup for each ITER */ for( i=0; i<9; i++ ) { vseq->pg4_nsec += (vseq->pg4_dur[i] * 10 ) + 10; /* duration + 10ns to skip table entries */ } /* debug output */ if( fp ) { ir_printf( fp, "#vseq_param PG4:\n# dur:"); for(i=0; ipg4_dur[i]); ir_printf( fp, "\n"); ir_printf( fp, "# PG4 bit0: "); for(i=0; ipg4_bits[i]&0x01?1:0)); ir_printf( fp, "\n# PG4 bit1: "); for(i=0; ipg4_bits[i]&0x02?1:0)); ir_printf( fp, "\n# PG4 bit2: "); for(i=0; ipg4_bits[i]&0x04?1:0)); ir_printf( fp, "\n# PG4 bit3: "); for(i=0; ipg4_bits[i]&0x08?1:0)); ir_printf( fp, "\n"); } /* write data to CE. CE_PARAM_VIDSEQ_PG4_x has 8 timeslices. */ nsec = IR_CE_PARAM_VIDSEQ_NS; /* time to write CE_PARAM_VIDSEQ_PG4_x data to CE */ ir_ce_put( CE_PARAM_VIDSEQ_PG4_0 | ((vseq->pg4_dur[1] & 0x003f)<<10) | (vseq->pg4_dur[0]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_1 | ((vseq->pg4_dur[3]&0x03)<<14) | (vseq->pg4_dur[2]<<4) | ((vseq->pg4_dur[1]>>6)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_2 | ((vseq->pg4_dur[4]&0x00ff)<<8) | (vseq->pg4_dur[3]>>2) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_3 | ((vseq->pg4_dur[6]&0x0f)<<12) | (vseq->pg4_dur[5]<<2) | ((vseq->pg4_dur[4]>>8)) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_4 | (vseq->pg4_dur[7]<<6) | (vseq->pg4_dur[6]>>4) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_5 | (vseq->pg4_bits[0]<<12) | (vseq->pg4_dur[8]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_6 | (vseq->pg4_bits[4]<<12) | (vseq->pg4_bits[3]<<8) | (vseq->pg4_bits[2]<<4) | (vseq->pg4_bits[1]) , nsec, ceb, fp ); ir_ce_put( CE_PARAM_VIDSEQ_PG4_7 | (vseq->pg4_bits[8]<<12) | (vseq->pg4_bits[7]<<8) | (vseq->pg4_bits[6]<<4) | (vseq->pg4_bits[5]) , nsec, ceb, fp ); } /*---------------------------------------------------------------------------------------- ** ir_ce_vidseq_exe () - Write CE_CMD_VIDSEQ to execute the PSEQ **--------------------------------------------------------------------------------------- */ void ir_ce_vidseq_exe( int iter, /* I: iteration value for pseq command. 1 to 32768 */ struct ir_ce_vseq_t *vseq, /* I: PSEQ data structure define the wave form */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { /* time to execute table is based on pg4's total time */ /* 20 ns startup + time per iteration */ ir_ce_put( CE_CMD_VIDSEQ|CE_ITER(iter), 20 + (iter*vseq->pg4_nsec), ceb, fp ); } /*---------------------------------------------------------------------------------------- ** ir_ce_adc_param () - Write CE commands to setup ADC paramters: CE_PARAM_ADC. **--------------------------------------------------------------------------------------- */ void ir_ce_adc_param( struct ir_ce_adc_t *adc, /* I: ADC options */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { /* CE_PARAM_ADC command takes 30 ns */ unsigned short adc_param = (adc->numsample<<10) | (adc->numchannels<<8) | adc->multisample_gap; ir_ce_put( CE_PARAM_ADC| adc_param, 30, ceb, fp ); } /*---------------------------------------------------------------------------------------- ** ir_ce_digout_lo () - CE Digitial Output Low Word. ** generates CE command to change the DigOut Low Word (a 16bit register) ** You need to enable the UPDWR using digout_hi for this to work. **--------------------------------------------------------------------------------------- */ void ir_ce_digout_lo( unsigned short *bits, /* I/O: current values of the bits...to be changed */ unsigned short clrbits, /* I: bits to clear (done 1st ) */ unsigned short setbits, /* I: bits to set (done 2nd ) */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { unsigned short c;; c = (*bits) & ~clrbits; /* clear the bits */ c |= setbits; /* set the bits */ *bits = c; /* update caller's bits */ ir_ce_put( CE_PARAM_UPDWR_LO | c , IR_CE_PARAM_UPDWR_LO_NS, ceb, fp ); /* load data */ #ifdef LINUX lower_digout = c; #endif ir_ce_put( CE_CMD_UPDWR, IR_CE_CMD_UPDWR_NS, ceb, fp ); /* output data */ } /*---------------------------------------------------------------------------------------- ** ir_ce_digout_hi () - CE Digitial Output HI Word. ** generates CE command to change the DigOut HI Word (a 16bit register) ** Or in the enable flag. **--------------------------------------------------------------------------------------- */ void ir_ce_digout_hi( unsigned short *bits, /* I/O: current values of the bits...to be changed */ unsigned short clrbits, /* I: bits to clear (done 1st ) */ unsigned short setbits, /* I: bits to set (done 2nd ) */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { unsigned short c;; c = (*bits) & ~clrbits; /* clear the bits */ c |= setbits; /* set the bits */ *bits = c; /* update caller's bits */ /* loads data. note: 0x8000 is the enable bit for digout interface */ ir_ce_put( CE_PARAM_UPDWR_HI | 0x8000 | c, IR_CE_PARAM_UPDWR_LO_NS, ceb, fp ); #ifdef LINUX upper_digout = c; #endif ir_ce_put( CE_CMD_UPDWR, IR_CE_CMD_UPDWR_NS, ceb, fp ); /* output data */ } /*---------------------------------------------------------------------------------------- ** ir_ce_gps() - uses CE_CMD_SHUTTERCLOS/CE_CMD_SHUTTEROPEN to drive an external ** gps timestamp signal. **--------------------------------------------------------------------------------------- */ void ir_ce_gps( int value, /* I: 0=low; 1=high */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp /* O: Debug file supported on LINUX only */ ) { /* the CE_CMD_SHUTTEROPEN takes 30 ns to execute */ if( value ) ir_ce_put( CE_CMD_SHUTTEROPEN, IR_CE_CMD_SHUTTER_NS, ceb, fp ); /* open (high) */ else ir_ce_put( CE_CMD_SHUTTERCLOS, IR_CE_CMD_SHUTTER_NS, ceb, fp ); /* close (low) */ } /*---------------------------------------------------------------------------------------- ** ir_ce_cmd_delay_usec () - Generates a delay using ir_ce_cmd_delay(). ** but unit are in microseconds. **--------------------------------------------------------------------------------------- */ void ir_ce_cmd_delay_usec( struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ int64_t delay_usec, /* I: 0 to 2^63ns/1000 (a very long time, > 7000 years ) */ FILE * fp /* O: Debug file supported on LINUX only */ ) { ir_printf( fp, "#ir_ce_cmd_delay_usec()\n"); ir_ce_cmd_delay ( ceb, delay_usec * 1000LL, fp); } /*---------------------------------------------------------------------------------------- ** ir_ce_cmd_delay () - Generates CE_CMD_DELAY, CMD_NOP to wait in the CE. ** Breaks up the total waits into a series of 2 second (or smaller) DELAY commands. **--------------------------------------------------------------------------------------- */ void ir_ce_cmd_delay( struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ int64_t delay_ns, /* I: 0 to 2^63ns (a very long time, > 7000 years ) */ FILE * fp /* O: Debug file supported on LINUX only */ ) { int i; if (delay_ns < 20 ) /* can generate under 20 ns delays */ return; /* 1 CMD_DELAY is 100 usec, or 100,000 ns. */ /* max ITER is 32768, which can yeild a 3.2 sec wait, but (32000 * 10000) is more that 32bits */ /* So this loop does 2 seconds CE_DELAY wait so we can use normal int (not int64_t) */ while( delay_ns > 2000000000 ) { ir_ce_put( CE_CMD_DELAY | CE_ITER(20000), 2000000000, ceb, fp ); /* output CE data */ delay_ns -= 2000000000; } /* Use CMD_DELAY for 100000 ns to 3276000000 ns. It should loop just once. */ while( delay_ns > 100000 ) { i = delay_ns / 100000; ir_ce_put( CE_CMD_DELAY | CE_ITER(i), i*100000, ceb, fp ); /* output CE data */ delay_ns -= i*100000; } /* Use CMD_NOP for the remainder. */ /* CMD_NOP is 10ns + 10 per iter */ if( delay_ns >= 20 ) { i = (delay_ns - 10) / 10; /* at least 1 */ ir_ce_put( CE_CMD_NOP | CE_ITER(i), 10+(i*10), ceb, fp ); /* output CE data */ } } /*-------------------------------------------------------------------------- ** ir_ce_put - IR CE Put - write a CE work into ce buffer structure. **-------------------------------------------------------------------------- */ void ir_ce_put( unsigned int ce, /* I: CE command to add to the buffer */ int nsec, /* I: nsec to execute this command */ struct ir_ce_buf_t * ceb, /* I/O: ce command buffer */ FILE * fp ) { ceb->cmd[ceb->n] = ce; ceb->n++; ceb->nsec += nsec; #if LINUX if( fp ) { char buf[128]; ir_btosl ( buf, ce ); fprintf( fp, "ce: %9d %10lld %04d 0x%08x %s [0x%04x] [0x%04x] \n", ceb->n, ceb->nsec, nsec, ce, buf, upper_digout, lower_digout); } #endif } /*---------------------------------------------------------- ** ir_ce_slowcnt_to_ns( ) - slowcount to nsec conversion **---------------------------------------------------------- */ int ir_ce_slowcnt_to_ns ( int slowcnt ) { return 40+ (slowcnt*20); } /*---------------------------------------------------------------------------- ** ir_ce_slowcnt_to_pseqdir( ) - return the PARSEQ duration value given slowcnt. ** Assumes the PARSEQ scale is set to 0 (10ns). **---------------------------------------------------------------------------- */ int ir_ce_slowcnt_to_pseqdur ( int slowcnt ) { int nsec = ir_ce_slowcnt_to_ns ( slowcnt ); return (nsec - 10) / 10; /* -10 to skip; /10 for IR_CE_PSEQ_SCALE_10 */ } /*---------------------------------------------------------------------------- ** ir_ce_slowcnt_to_vseqdir( ) - return the VIDSEQ duration value given slowcnt. **---------------------------------------------------------------------------- */ int ir_ce_slowcnt_to_vseqdur ( int slowcnt ) { int nsec = ir_ce_slowcnt_to_ns ( slowcnt ); return (nsec - 10) / 10; /* -10 to skip; /10 for 1_period is 10ns */ } /*---------------------------------------------------------------------------- ** ir_adc_to_ns( ) - determine time (ns) need to an ADC. ** Tells you how long the the ADC period is. **---------------------------------------------------------------------------- */ int ir_adc_to_ns ( int sam, /* num samples - Number of SAMPCLK per edge of ADCTRIG */ int ch, /* numcahnnels - 1=R, 2=RG, 3=RGB */ int mgap /* multigaps - a 10 ns time added between SAMPLECLK pulses */ ) { int nsec; /* note: the falling ADC trigger startup is 30 ns (vs 20 on the rising edge) ** This function just uses 20 ns, as getting the rising edge is critial, ** and we can ignore the extra 10 ns on the falling edge in the clocking */ nsec = 40; /* 20 startup + 20 until 1st SAMCLK */ nsec += (90 * ch)* sam; /* 90 ns per channel x numsamples */ nsec += 10 * mgap; /* add multgap time */ return nsec; } /*---------------------------------------------------------- ** ir_btosl( s ) - Create a string of 0's and 1's based on the ** bit pattern in l. ** Note: s should be at least char[40]; ** returns s. **---------------------------------------------------------- */ char * ir_btosl ( char * s, unsigned long l ) { int i; unsigned long mask; char * cptr; mask = 0x80000000; cptr = s; for( i=0; i<32; i++) { *cptr++ = ( l & mask ? '1' : '0' ); if( (i % 4)==3 ) *cptr++ = ' '; mask >>= 1; } *cptr = 0; return s; } /*-------------------------------------------------------------------------- ** ir_printf - puts a common in the debug file ** OR only prints on the linux hosts. **-------------------------------------------------------------------------- */ void ir_printf( FILE * fp, char * fmt, ... ) { #if LINUX va_list argptr; char buf[256]; if( fp==NULL ) return; /* expand format string */ va_start( argptr, fmt ); vsprintf( buf, fmt, argptr ); va_end( argptr ); fprintf( fp, buf ); #endif } /********************************************************************** ** ir_cep - Functions that write directly to the FIFO. ********************************************************************** */ /*---------------------------------------------------------------------------------------- ** ir_cep_delay_usec () - Generates a delay using ir_ce_cmd_delay(). ** but unit are in microseconds. **--------------------------------------------------------------------------------------- */ void ir_cep_delay_usec( ce_t * ce, /* O: ce */ int64_t delay_usec /* I: 0 to 2^63ns/1000 (a very long time, > 7000 years ) */ ) { ir_cep_delay_ns( ce, delay_usec * 1000LL ); } /*---------------------------------------------------------------------------------------- ** ir_cep_delay_ns () - Generates CE_CMD_DELAY, CMD_NOP to wait in the CE. ** Breaks up the total waits into a series of 2 second (or smaller) DELAY commands. ** Number of CE command generate are: (delay_ns / 2000000000LL ) + 2 **--------------------------------------------------------------------------------------- */ void ir_cep_delay_ns( ce_t * ce, /* O: ce */ int64_t delay_ns /* I: 0 to 2^63ns (a very long time, > 7000 years ) */ ) { int i; if (delay_ns < 20 ) /* can't generate under 20 ns delays */ return; /* 1 CMD_DELAY is 100 usec, or 100,000 ns. */ /* max ITER is 32768, which can yeild a 3.2 sec wait, but (32000 * 10000) is more that 32bits */ /* So this loop does 2 seconds CE_DELAY wait so we can use normal int (not int64_t) */ while( delay_ns > 2000000000 ) { ce_put( ce, CE_CMD_DELAY | CE_ITER(20000)); /* output CE data */ delay_ns -= 2000000000; } /* Use CMD_DELAY for 100000 ns to 3276000000 ns. It should loop just once. */ while( delay_ns > 100000 ) { i = delay_ns / 100000; ce_put( ce, CE_CMD_DELAY | CE_ITER(i) ); /* output CE data */ delay_ns -= i*100000; } /* Use CMD_NOP for the remainder. */ /* CMD_NOP is 10ns + 10 per iter */ if( delay_ns >= 20 ) { i = (delay_ns - 10) / 10; /* at least 1 */ ce_put( ce, CE_CMD_NOP | CE_ITER(i) ); /* output CE data */ } } /****************************** EOF ****************************************/