/************************************************************************** ** ** al.c - support for Aladdin IR Arrays. ** *************************************************************************** */ /*-------------------------- ** 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" #include "al.h" /*---------------------------------------------------------------------------------------- ** al_ck_generate_ce_sample () - Generate ce sample clocking based on input **--------------------------------------------------------------------------------------- */ int al_ck_generate_ce_sample ( struct ir_ce_buf_t *ce_s, /* O: Creates CE commands to readout the array */ struct alst_table_t *st, /* I: Scan Table */ struct al_ck_in_t *in, /* I: input variables for created CE clocking commands */ FILE * fp /* I: file descriptor for debug output */ ) { unsigned short digout; int digout_ns, ts_ns, ts_adc, y, i; struct ir_ce_adc_t adc_in; if ( fp ) { ir_printf( fp, "#-------al_ck_generate_ce_sample() ---------------------\n"); ir_printf( fp, "# in.slowcnt = %d \n", in->slowcnt); ir_printf( fp, "# in.numdarray = %d \n", in->num_darray); for ( i=0; inum_darray; i++ ) { ir_printf( fp, "#in.darray[%d] = %d %d %d %d \n", i, in->darray[i].x, in->darray[i].y, in->darray[i].wid, in->darray[i].hgt); } ir_printf( fp, "# cd_adc = %d sam, %d chan, %d mgap \n", in->numsample, in->numchannels, in->multisample_gap); } digout_ns = IR_CE_PARAM_UPDWR_LO_NS+IR_CE_CMD_UPDWR_NS; /* time to do a digout = 50+30 ns */ ts_ns = ir_ce_slowcnt_to_ns(in->slowcnt); /* one TS in nano seconds */ ir_printf( fp, "# ts_ns=%d ns \n", ts_ns); /* start clocking with FRAME signal */ ir_ce_clear( ce_s ); digout = 0; /* start with all bit cleared */ ir_ce_digout_lo( &digout, 0, AL_FRAME, ce_s, fp); ir_ce_cmd_delay( ce_s, (1*ts_ns)-digout_ns, fp ); /* ** calculate ts_adc, the number of time slices need after an ADCTRIG edge. ** AND setup ADC parameters */ i = ir_adc_to_ns( in->numsample, in->numchannels, in->multisample_gap ); ts_adc = i / ts_ns; if ( (i % ts_ns) > 0 ) ts_adc++; ir_printf( fp, "# Setup ADC opt: ts_adc=%d %d ns \n", ts_adc, i); adc_in.numsample = in->numsample; adc_in.numchannels = in->numchannels; adc_in.multisample_gap = in->multisample_gap; ir_ce_adc_param( &adc_in, ce_s, fp); /* Setup ADC options */ /* ** Initialize slow mux register */ ir_printf( fp, "# Init Slow Mux:\n" ); ir_ce_digout_lo( &digout, 0, AL_PSS, ce_s, fp); ir_ce_cmd_delay( ce_s, (4*ts_ns)-digout_ns, fp ); ir_ce_digout_lo( &digout, AL_PSS, 0, ce_s, fp); ir_ce_cmd_delay( ce_s, (4*ts_ns)-digout_ns, fp ); ir_ce_digout_lo( &digout, 0, AL_PS1, ce_s, fp); ir_ce_cmd_delay( ce_s, (4*ts_ns)-digout_ns, fp ); ir_ce_digout_lo( &digout, AL_PS1, 0, ce_s, fp); ir_ce_cmd_delay( ce_s, (4*ts_ns)-digout_ns, fp ); /* ** each loop does 4 row {ABCD} .. */ for ( y=0; y <= st->max_row; ) /* y incremented in loop */ { /* Row A */ ir_printf( fp, "# Row %3d A\n", y); ir_ce_digout_lo( &digout, AL_PS1|AL_PSOE, 0, ce_s, fp); // clear PS1, PSOE ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); ir_ce_digout_lo( &digout, 0, AL_PS2, ce_s, fp); // raise PS2 ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); al_ck_sample_column( ce_s, st, in, &digout, y, ts_adc, fp); y++; /* Row B */ ir_printf( fp, "# Row %3d B\n", y); ir_ce_digout_lo( &digout, 0, AL_PSOE, ce_s, fp); // raise PSOE ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); al_ck_sample_column( ce_s, st, in, &digout, y, ts_adc, fp); y++; /* Row C */ ir_printf( fp, "# Row %3d C\n", y); ir_ce_digout_lo( &digout, AL_PS2|AL_PSOE, 0, ce_s, fp); // clear PS2, PSOE ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); ir_ce_digout_lo( &digout, 0, AL_PS1, ce_s, fp); // raise PS1 ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); al_ck_sample_column( ce_s, st, in, &digout, y, ts_adc, fp); y++; /* Row D */ ir_printf( fp, "# Row %3d D\n", y); ir_ce_digout_lo( &digout, 0, AL_PSOE, ce_s, fp); // raise PSOE ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); al_ck_sample_column( ce_s, st, in, &digout, y, ts_adc, fp); y++; } /* ** End of Array, clear ALL */ ir_ce_digout_lo( &digout, 0xffff, 0, ce_s, fp); // clear all ir_ce_cmd_delay( ce_s, (3*ts_ns)-digout_ns, fp ); if ( fp ) { ir_printf( fp, "# ce_buf.n = %d \n", ce_s->n); ir_printf( fp, "# ce_buf.msec = %d.%06d\n", (int)(ce_s->nsec/1000000LL), (int)(ce_s->nsec%1000000LL)); ir_printf( fp, "# al_ck_generate_ce_sample() ends \n"); } return 0; } /*---------------------------------------------------------------------------------------- ** al_ck_sample_column () - Generate CE commands to clock a column. **--------------------------------------------------------------------------------------- */ int al_ck_sample_column( struct ir_ce_buf_t *ce_s, /* O: Creates CE commands to reset the array */ struct alst_table_t *st, /* I: Scan Table */ struct al_ck_in_t *in, /* I: input variables for created CE clocking commands */ unsigned short *digout, /* I/O: value of the digout bits */ int y, /* I: the row being clocked */ int ts_adc, /* I: Time Slice need for ADC Edge */ FILE * fp /* I: file descriptor for debug output */ ) { struct ir_ce_vseq_t vseq; int dur, ts_ns, c, type; /* when clock a row, we need to get how may converts vs. skip column. with 3 subarray ** we could swap between converts and skip 7 times. c_ variable below help with this: */ #define C_SKIP 0 #define C_CNVT 1 int c_n; int c_cnt[8]; int c_type[8]; ts_ns = ir_ce_slowcnt_to_ns(in->slowcnt); /* Timeslice in nanoseconds */ /*--------------------------------------------------- ** initalize the row mux register using pg3/pg4 */ vseq.reps = 1; /* pg3 reps .. always 1 */ dur = ir_ce_slowcnt_to_vseqdur( in->slowcnt ); // ---- duration for pg3 & pg4 -----------|----- pg3 bits------------|----- pg4 bits ------- vseq.pg3_dur[0] = vseq.pg4_dur[0] = 4*dur; vseq.pg3_bits[0] = 0; vseq.pg4_bits[0] = 0; vseq.pg3_dur[1] = vseq.pg4_dur[1] = 4*dur; vseq.pg3_bits[1] = AL_PFS; vseq.pg4_bits[1] = 0; vseq.pg3_dur[2] = vseq.pg4_dur[2] = 4*dur; vseq.pg3_bits[2] = 0; vseq.pg4_bits[2] = 0; vseq.pg3_dur[3] = vseq.pg4_dur[3] = 4*dur; vseq.pg3_bits[3] = 0; vseq.pg4_bits[3] = AL_PF1; vseq.pg3_dur[4] = vseq.pg4_dur[4] = dur; vseq.pg3_bits[4] = 0; vseq.pg4_bits[4] = 0; vseq.pg3_dur[5] = vseq.pg4_dur[5] = dur; vseq.pg3_bits[5] = 0; vseq.pg4_bits[5] = 0; vseq.pg3_dur[6] = vseq.pg4_dur[6] = dur; vseq.pg3_bits[6] = 0; vseq.pg4_bits[6] = 0; vseq.pg3_dur[7] = vseq.pg4_dur[7] = dur; vseq.pg3_bits[7] = 0; vseq.pg4_bits[7] = 0; vseq.pg3_dur[8] = vseq.pg4_dur[8] = dur; vseq.pg3_bits[8] = 0; vseq.pg4_bits[8] = 0; ir_printf( fp, "# Init FastMux:\n"); ir_ce_vidseq_param( &vseq, ce_s, fp ); /* write vseq parameter */ ir_ce_vidseq_exe( 1, &vseq, ce_s, fp ); /* execute vseq */ /* some quite time after column sync */ ir_ce_cmd_delay( ce_s, (20*ts_ns), fp ); /*--------------------------------------------------- ** figure out the c_n, c_cnt[], and c_type[] for this column: */ /* init var using 1st column */ c_n = 0; c_type[c_n] = (alst_getColRow( st, 0, y ) ? C_CNVT : C_SKIP); c_cnt[c_n] = 1; /* do the remaining columns */ for ( c=1; cslowcnt ); if ( c_type[c] == C_SKIP ) { ir_printf( fp, "# c=%d. SKIPx%d\n", c, c_cnt[c]); /* SKIP */ /* ---- duration for pg3 & pg4 ------|----- pg3 bits-----|----- pg4 bits -------*/ vseq.pg3_dur[0]=vseq.pg4_dur[0]=4*dur; vseq.pg3_bits[0]=0; vseq.pg4_bits[0]=0; vseq.pg3_dur[1]=vseq.pg4_dur[1]=2*dur; vseq.pg3_bits[1]=0; vseq.pg4_bits[1]=AL_PF2; vseq.pg3_dur[2]=vseq.pg4_dur[2]=1*dur; vseq.pg3_bits[2]=0; vseq.pg4_bits[2]=AL_PF2; vseq.pg3_dur[3]=vseq.pg4_dur[3]=1*dur; vseq.pg3_bits[3]=0; vseq.pg4_bits[3]=AL_PF2; vseq.pg3_dur[4]=vseq.pg4_dur[4]=4*dur; vseq.pg3_bits[4]=0; vseq.pg4_bits[4]=0; vseq.pg3_dur[5]=vseq.pg4_dur[5]=2*dur; vseq.pg3_bits[5]=0; vseq.pg4_bits[5]=AL_PF1; vseq.pg3_dur[6]=vseq.pg4_dur[6]=1*dur; vseq.pg3_bits[6]=0; vseq.pg4_bits[6]=AL_PF1; vseq.pg3_dur[7]=vseq.pg4_dur[7]=1*dur; vseq.pg3_bits[7]=0; vseq.pg4_bits[7]=AL_PF1; vseq.pg3_dur[8]=vseq.pg4_dur[8]=1*dur; vseq.pg3_bits[8]=0; vseq.pg4_bits[8]=0; } else { ir_printf( fp, "# c=%d. CNVTx%d\n", c, c_cnt[c]); /* ADC Sample */ /* ---- duration for pg3 & pg4 ------|----- pg3 bits-----|----- pg4 bits -------*/ vseq.pg3_dur[0]=vseq.pg4_dur[0]=3*dur; vseq.pg3_bits[0]=0; vseq.pg4_bits[0]=0; vseq.pg3_dur[1]=vseq.pg4_dur[1]=9*dur; vseq.pg3_bits[1]=0; vseq.pg4_bits[1]=AL_PF2; vseq.pg3_dur[2]=vseq.pg4_dur[2]=ts_adc*dur; vseq.pg3_bits[2]=0; vseq.pg4_bits[2]=AL_PF2|AL_ADC; vseq.pg3_dur[3]=vseq.pg4_dur[3]=ts_adc*dur; vseq.pg3_bits[3]=0; vseq.pg4_bits[3]=AL_PF2; vseq.pg3_dur[4]=vseq.pg4_dur[4]=3*dur; vseq.pg3_bits[4]=0; vseq.pg4_bits[4]=0; vseq.pg3_dur[5]=vseq.pg4_dur[5]=9*dur; vseq.pg3_bits[5]=0; vseq.pg4_bits[5]=AL_PF1; vseq.pg3_dur[6]=vseq.pg4_dur[6]=ts_adc*dur; vseq.pg3_bits[6]=0; vseq.pg4_bits[6]=AL_PF1|AL_ADC; vseq.pg3_dur[7]=vseq.pg4_dur[7]=ts_adc*dur; vseq.pg3_bits[7]=0; vseq.pg4_bits[7]=AL_PF1; vseq.pg3_dur[8]=vseq.pg4_dur[8]=1*dur; vseq.pg3_bits[8]=0; vseq.pg4_bits[8]=0; } ir_ce_vidseq_param( &vseq, ce_s, fp ); /* write vseq parameter */ ir_ce_vidseq_exe( c_cnt[c], &vseq, ce_s, fp ); /* execute vseq, iter is c_cnt */ } return PASS; } /*---------------------------------------------------------------------------------------- ** al_ck_generate_ce_reset () - Generate ce reset clocking based on input **--------------------------------------------------------------------------------------- */ int al_ck_generate_ce_reset ( struct ir_ce_buf_t *ce_r, /* O: Creates CE commands to reset the array */ struct al_ck_in_t *in, /* I: input variables for created CE clocking commands */ FILE * fp /* I: file descriptor for debug output */ ) { unsigned short digout; int digout_ns, ts_ns, reset_ns; ir_ce_clear( ce_r ); digout = 0; /* start with all bit cleared */ digout_ns = IR_CE_PARAM_UPDWR_LO_NS+IR_CE_CMD_UPDWR_NS; /* time to do a digout = 50+30 ns */ ts_ns = ir_ce_slowcnt_to_ns(in->slowcnt); /* one TS in nano seconds */ reset_ns = in->glr_period_usec*1000; if ( fp ) { ir_printf( fp, "#-------al_ck_generate_ce_reset() ---------------------\n"); ir_printf( fp, "# glr_period_usec = %d \n", in->glr_period_usec); } /* 1 time slices */ ir_ce_digout_lo( &digout, 0, 0, ce_r, fp); ir_ce_cmd_delay( ce_r, ts_ns-digout_ns, fp ); /* reset for glr_perid */ ir_ce_digout_lo( &digout, 0, AL_VRSTG|AL_VDDCL|AL_VGGCL, ce_r, fp); ir_ce_cmd_delay( ce_r, reset_ns-digout_ns, fp ); /* 1 time slices */ ir_ce_digout_lo( &digout, AL_VRSTG|AL_VDDCL|AL_VGGCL, 0, ce_r, fp); ir_ce_cmd_delay( ce_r, ts_ns-digout_ns, fp ); if ( fp ) { ir_printf( fp, "# ce_buf.n = %d \n", ce_r->n); ir_printf( fp, "# ce_buf.msec = %d.%06d\n", (int)(ce_r->nsec/1000000LL), (int)(ce_r->nsec%1000000LL)); ir_printf( fp, "# al_ck_generate_ce_reset() ends \n"); } return 0; } /*-------------------------------------------------------------------------------- ** al_check_subarray() - check subarray parameters for insb device **-------------------------------------------------------------------------------- */ int al_check_subarray( int num_darray, /* I: number of data arrays */ struct ir_array_t *da /* I: data array definition */ ) { int i; for ( i=0; i < num_darray; i++ ) { /*--------------------------------------------- ** x: 16 pixel boundraries, & check range ** wid: 16 pixel boundraries, & min value = 16 */ if ( da[i].x % 16 ) return FAIL; if ( !INRANGE( 0, da[i].x, AL_NAXIS1-16)) return FAIL; if ( da[i].wid % 16 ) return FAIL; if ( !INRANGE( 16, da[i].wid, AL_NAXIS1-da[i].x)) return FAIL; /*---------------------------------------- ** y must start on row A (of ABCD) (mod 4) ** hgt should be mod 4. (at least a row-pair). */ if ( da[i].y % 4 ) return FAIL; if ( !INRANGE( 0, da[i].y, AL_NAXIS1-4)) return FAIL; if ( da[i].hgt % 4 ) return FAIL; if ( !INRANGE( 0, da[i].hgt, AL_NAXIS1-da[i].y)) return FAIL; } return PASS; } /**************************************************************************************/ /* alst_ are ALaddin Scan Table function */ /**************************************************************************************/ /*---------------------------------------------------------------------------------------- ** alst_clear() - initialize, or zeroes, the variables in scan table. **--------------------------------------------------------------------------------------- */ int alst_clear( struct alst_table_t * st ) { memset( st, 0, sizeof(struct alst_table_t) ); return PASS; } /*----------------------------------------------------------------------------------------- ** alst_setColRow() - Turn on bits represting a row/col location **----------------------------------------------------------------------------------------- */ int alst_setColRow( struct alst_table_t * st, /* scan table */ int col, /* x index (0...ncol-1) in scan coordinates */ int row /* y index (0...nrow-1) in scan coordinates */ ) { unsigned long mask; if ( !INRANGE( 0, row, ALST_NUM_ROW-1)) return FAIL; if ( !INRANGE( 0, col, ALST_NUM_COL-1)) return FAIL; /* keep track of min & max rows */ if ( st->min_row > row ) st->min_row = row; if ( st->max_row < row ) st->max_row = row; /* keep track of min & max column used in the row */ if ( st->row[row].min_col > col ) st->row[row].min_col = col; if ( st->row[row].max_col < col ) st->row[row].max_col = col; /* if bit not set, increment scans. */ mask = ( 0x80000000 >> col ); if ( !(st->row[row].col & mask) ) { st->row[row].converts++; /* total for row */ st->converts++; /* total for entire array */ st->row[row].col |= mask; /* turn on bit */ } return PASS; } /*----------------------------------------------------------------------------------------- ** alst_getColRow() - Return T/F indicated if the Col,Row is sampled(T) or not(F). **----------------------------------------------------------------------------------------- */ int alst_getColRow( struct alst_table_t * st, /* scan table */ int col, /* x index (0...ncol-1) in scan coordinates */ int row /* y index (0...nrow-1) in scan coordinates */ ) { if ( !INRANGE( 0, row, ALST_NUM_ROW-1)) return 0; if ( !INRANGE( 0, col, ALST_NUM_COL-1)) return 0; return(st->row[row].col & ( 0x80000000 >> col ) ? 1 : 0); } /*----------------------------------------------------------------------------------------- ** alst_setTable() - turns on bits representing the subarray location. **----------------------------------------------------------------------------------------- */ int alst_setTable( struct alst_table_t * st, int num_darray, /* I: number of data arrays */ struct ir_array_t *da /* I: data array definition */ ) { int a, xinx, yinx, x, y, wid, hgt; if ( al_check_subarray( num_darray, da ) == FAIL ) return FAIL; for ( a=0; a < num_darray; a++ ) { /*------------------------------------------------------ ** convert x,y,wid,hgt from pixel to scan coordinates */ x = da[a].x / 16; wid = da[a].wid / 16; y = da[a].y; hgt = da[a].hgt; for ( yinx=y; yinxconverts); for ( r=0; r < ALST_NUM_ROW; r++ ) { ir_btosl( buf, st->row[r].col); fprintf( fp, "%04d. %8d 0x%08lx %s \n", r, st->row[r].converts, st->row[r].col, buf); } #endif return PASS; }