/*----------------------------------------------------------------------------*/ /* cadc.c: version for the multiplexed serial readout of the custom ADC */ /* boards. Running on VME cpu */ /* */ /* June, 1998, YG.KIM */ /* copied to custom_adc.c, nov20 98 HvH, and slightly modified: */ /* swapped sclk and din lines */ /* 16 chips instead of 12 */ /* differential instead of single-ended */ /* */ /* It seems that VME cpu doesn't like 'pow' function. So I simply */ /* substitute it with a 'For' loop. */ /* Modified for use with GreenSpring I/O modules June 2000 HvH */ /* */ /* compile command -------> */ /* cc68k -c -O -DCPU=MC68020 -I$VX_VW_BASE/h cadc.c */ /* load with: ld < /usr1/mvdonl/vme/cadc.o */ /*-----------------------------------------------------------*/ #include #include #include #include #include "taskLib.h" STATUS cadc(){ int loop; int i, j, k, m, n, ichan, index, idout; int iomodule = 1; int iabcd = 3; int ipin = 17; int idebug = 0; int port[4]; int q, ibit, go_on, power, data; int ival[16][8] = { 0*128 }; int icon, jpin, iconn[4][16]; int icontrol[8] = { 1,0,0,0,1,0,1,0 }; /* switch to differential */ int jcontrol[4][3] = { {0,0,0}, {0,0,1},{0,1,0}, {0,1,1} } ; char c,command[50]; /* address */ /* vvvv */ int sclk_on = 16; /* 0001 0000 bit 5 */ int din_on = 32; /* 0010 0000 bit 6 */ int output_on = 192; /* 1100 0000 <-- passive, enable */ int all_off = 192; /* 1100 0000 don't touch the output */ int both_off = 207; /* 1100 1111 '' */ int sclk_off = 239; /* 1110 1111 '' */ /* ^^ */ /* data, sstrb out */ /*---------------------------------------------------------------------------*/ data = output_on; /* enable ouput lines: */ io_write(iomodule,iabcd,ipin,data,idebug); go_on =1; /* command loop: */ while(go_on) { printf("\n Custom ADC >> "); gets(command); if ( strstr(command, "read") | strstr(command,"r") ) { for ( i = 0 ; i <16 ; i++ ) for ( j = 0 ; j < 8 ; j++ ) ival[i][j] = 0; data = all_off; io_write(iomodule,iabcd,ipin,data,idebug); for ( i = 0; i < 16 ; i++ ){ /* loop over 16 ADCs (0-16)*/ data = data | i ; io_write(iomodule,iabcd,ipin,data,idebug); /* for ( ichan = 0; ichan < 8 ; ichan++ ){ loop over channels */ for ( ichan = 0; ichan < 4 ; ichan++ ){ /* now only 0-3 */ for ( j = 0 ; j < 3 ; j++ ) icontrol[j+1] = jcontrol[ichan][j]; for ( k = 0 ; k < 8 ; k++ ){ /* clock out control bits */ if ( icontrol[k] == 0 ) { data = data & both_off; io_write(iomodule,iabcd,ipin,data,idebug); } if ( icontrol[k] == 1 ) { data = data | din_on; data = data & sclk_off; io_write(iomodule,iabcd,ipin,data,idebug); } data = data | sclk_on; io_write(iomodule,iabcd,ipin,data,idebug); } data = data & both_off; /* din; off, sclk; off */ io_write(iomodule,iabcd,ipin,data,idebug); data = data | sclk_on; io_write(iomodule,iabcd,ipin,data,idebug); for ( j = 0 ; j < 16 ; j++) { data = data & sclk_off; io_write(iomodule,iabcd,ipin,data,idebug); data = data | sclk_on; io_write(iomodule,iabcd,ipin,data,idebug); idout = 24; io_read(iomodule,iabcd,idout,&ibit,idebug); index = 11 - j; k = 0; power = 1; while ( k < index ) { power = power << 1; k = k + 1; } ival[i][ichan] = ival[i][ichan] + ibit*power; icon = 3 - (2*(i/8) + ichan%2); jpin = (i*2 + ichan/2)%16; iconn[icon][jpin] = ival[i][ichan]; } /* end loop for 12 bits clocked out*/ printf("icon %d jpin %d \n", icon, jpin); for ( j = 0 ; j < 4 ; j++ ) { data = data | sclk_on; io_write(iomodule,iabcd,ipin,data,idebug); data = data & sclk_off; io_write(iomodule,iabcd,ipin,data,idebug); } /* printf("chip#,chan#,ival : %d %d %d\n",i+1,ichan,ival[i][ichan]); */ } /* loop over channels */ data = all_off; } /* loop over ADCs */ /* printf("\n--------------------------------\n"); printf("chip# | CH3 CH2\n"); printf(" CH1 CH0\n"); printf("--------------------------------\n"); for ( i = 15 ; i >=0 ; i-- ) { printf(" U%2d | %4d %4d\n",i+5,ival[i][3],ival[i][2]); printf(" | %4d %4d\n",ival[i][1],ival[i][0]); if (i==8) printf("--------------------------------\n"); } printf("--------------------------------\n"); */ printf( "\n pin A B | C D \n -----------------+-----------\n"); for (jpin=15; jpin >=0; jpin--) { printf(" %2d %4d %4d | %4d %4d \n", jpin+1, iconn[0][jpin], iconn[1][jpin], iconn[2][jpin], iconn[3][jpin] ); } printf(" -----------------+-----------\n"); } /* if(..."read") closed */ else if ( strstr(command, "exit") | strstr(command,"quit") | strstr(command,"x") | strstr(command,"q") ){ go_on = 0; puts("\n bye. \n"); } else if ( strstr(command, "int") ) { puts("\n Set Internal clock mode. \n"); icontrol[7] = 0; } else if ( strstr(command, "ext") ) { puts("\n Set External clock mode. \n"); icontrol[7] = 1; } else { puts("\n Try read, int, ext, exit.\n"); } } /* while loop closed */ return(OK); } /*=======================================================================*/ int io_write(int iomodule,int iabcd,int ipin,int data, int idebug) { /*--------------------------------------------------------------------------*/ /* This one does the write-part of the ADC protocol. 8 bits are written, */ /* - 4 bits to address a particular chip */ /* - a serial clock */ /* - serial data */ /* two additional bits return SSTRB and DOUT, and are safeguarded in */ /* the calling program by being set high, and also in this routine. */ /*-------------------------------------------------------------------*/ #define BASE 0xffff6000 int eightbits, readback, index, ibit, itemp; unsigned int *address; char c; /* see http://p25ext.lanl.gov/phenix/mvd/ancillary/logic/logic.html: */ int dout_mask[2][4] = { {0xc000c0, 0x00c000, 0xc000c0, 0xa0} , {0xb0, 0xc0, 0xd0, 0xe0} }; /*-- end declarations --------------------------------------------------------*/ address = (unsigned int *)(BASE + (iomodule-1)*0x1000 + (iabcd -1)*0x100 ); readback = *address; /* read what's there now, and */ itemp = readback; /* unshuffle bytes cdab->abcd */ readback = readback >> 16; /* shift 16 bits to the front */ readback = readback & 0x0000ffff; /* mask off the rest */ itemp = itemp << 16; /* shift first 8 bits to the */ itemp = itemp & 0xff0000; /* back, and mask off the rest*/ readback = readback | itemp; /* combine halves again */ readback = readback | dout_mask[iomodule-1][iabcd-1]; /* safeguard output lines */ eightbits = 0x000000ff; /* 8-bit mask where data goes */ eightbits = eightbits << (ipin-1); /* shift mask into place */ readback = readback & ~eightbits; /* clear 8-bit space */ data = data & 0x00000000ff; /* only 8 bits, mask rest */ data = data << (ipin-1); /* shift to ipin */ data = data | readback; /* combine old and new */ /* itemp = data; printf(" on C: (1-24) "); for (ibit=1; ibit<=24; ibit++){ index = data & 0x1; printf("%d",index); data = data >> 1; } data = itemp; */ itemp = data; /* reshuffle bytes abcd->cdab */ data = data << 16; /* shift 16 bits to the back */ data = data & 0xffff0000; /* mask off the rest */ itemp = itemp >> 16; /* shift 8 bits to the front, */ itemp = itemp & 0x000000ff; /* and mask off the rest */ data = data | itemp; /* combine them again */ *address = data; /* load the bits */ /* printf(" (end of write) ready? "); while ((c = getchar()) != '\n') { } */ } /* end io_write */ /*============================================================================*/ int io_read(int iomodule,int iabcd,int ipin, int *ibit, int idebug) { /*----------------------------------------------------------------------------*/ /* Do a 'direct read' of one bit from a given connector. This is done from */ /* a word in memory 1 higher than where you do a 'write'. Also, for this */ /* work, the bit in the 'write' register must be kept high (=passive). */ /* June 2000 Hubert van Hecke LANL */ /*-----------------------------------------------------------------------*/ #define BASE 0xffff6000 int readback, itemp; unsigned int *address; /*-- end declarations --------------------------------------------------------*/ address = (unsigned int *)(BASE + (iomodule-1)*0x1000 + (iabcd -1)*0x100 ); address = address + 1; /* 'direct read' see pgs 3,15 */ readback = *address; /* read what's there now */ itemp = readback; /* make a copy */ readback = readback >> 16; /* shift 16 bits to the front */ readback = readback & 0xffff; /* mask off the rest */ itemp = itemp << 16; /* shift first 8 bits to the */ itemp = itemp & 0xff0000; /* back, and mask off the rest*/ readback = readback | itemp; /* combine them again */ readback = readback >> (ipin-1); /* shift bit to position 1 */ readback = readback & 0x1; /* mask off the rest */ *ibit = readback; /* copy to output argument */ } /* end of io_read */ /*============================================================================*/