Subversion Repositories f9daq

Rev

Blame | Last modification | View Log | RSS feed

  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5.  
  6.  
  7. // Izberi ustrezni interface v meniju projektnega okna
  8. //  Options->CompilerDefines (dodaj /DSISVME ali /DWIENVME)
  9. #ifdef USE_DAQ
  10. #  ifdef SISVME
  11. #    include "sisvme_dll.h"
  12. #  endif
  13. #  ifdef WIENVME
  14. #    include "wienvme_dll.h"
  15. #  endif
  16. #  ifdef WUSBVME
  17. #    include "wusbvme_dll.h"
  18. #  endif
  19.  
  20. #endif
  21.  
  22. #include "wusbvme_dll.h"    
  23. #include <formatio.h>
  24.  
  25. #include "daq_cvi.h"
  26. #include "CAENV965_DEF.h"
  27. #define USBVME_NAME "VM0120"
  28.  
  29. #define VERSION 1.0
  30. #define TIMEOUT 3
  31.  
  32.  
  33. /* VME modules */
  34.  
  35. #define CAEN_V792      0x340000  // IJS V792
  36. #define CAEN_V792_1    0x530000  // FMF1 V792
  37. #define CAEN_V792_2    0x630000  // FMF2 V792
  38. #define CAEN_V965      0x350000  // IJS  V965
  39. int addr[3]={CAEN_V792,CAEN_V792_1,CAEN_V965  };
  40. int nadc=2;
  41. #define BUFF_L 2048
  42. static  int stackwrite[10000];
  43. static  int stackdata[10000],stackdump[27000];
  44.  
  45.  
  46. /************************************************/
  47. int weight_while(int num)
  48. {
  49.   int i, tmp;
  50.  
  51.   for ( i =0; i <num; i++ ) tmp = 0;
  52.   return 0;
  53. }
  54. #define WWHILE weight_while(0)
  55.  
  56. #define TRUE 1
  57. #define FALSE 0
  58.  
  59. int timer_out;
  60. //struct sigaction oact;
  61. void timerast (int signumber)
  62. {
  63.  timer_out = TRUE;
  64.  fprintf(stderr,"TIMEOUT !!!\n");
  65. }
  66.  
  67. void tmlnk (int tout)
  68. {
  69.         /*
  70.  timer_out = FALSE;
  71.  struct sigaction act;
  72.  struct itimerval tdelay;
  73.  
  74.  act.sa_handler = timerast;
  75.  sigemptyset (&act.sa_mask);
  76.  act.sa_flags = 0;
  77.  
  78.  tdelay.it_value.tv_sec = tout / 100;
  79.  tdelay.it_value.tv_usec = 10000 * (tout % 100);
  80.  tdelay.it_interval.tv_sec = 0;
  81.  tdelay.it_interval.tv_usec = 0;
  82.  
  83.  if (sigaction (SIGALRM, &act, &oact) < 0)
  84.  {
  85.    perror ("sigaction(tmlnk)");
  86.    exit (EXIT_FAILURE);
  87.  }
  88.  if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
  89.  {
  90.    perror ("setitimer(tmlnk)");
  91.    exit (EXIT_FAILURE);
  92.  }
  93.         */
  94. }
  95.  
  96. void tmulk ()
  97. {
  98.        
  99.         /*
  100.  struct itimerval tdelay;
  101.  
  102.  tdelay.it_value.tv_sec = 0;
  103.  tdelay.it_value.tv_usec = 0;
  104.  tdelay.it_interval.tv_sec = 0;
  105.  tdelay.it_interval.tv_usec = 0;
  106.  
  107.  if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
  108.  {
  109.    perror ("setitimer(tmulk)");
  110.    exit (EXIT_FAILURE);
  111.  }
  112.  if (sigaction (SIGALRM, &oact, NULL) < 0)
  113.  {
  114.    perror ("sigaction(tmulk)");
  115.    exit (EXIT_FAILURE);
  116.  }
  117.         */
  118. }
  119.  
  120. int fexist( char * path){
  121.    int size=0;
  122.    return GetFileInfo(path,&size);      
  123.    
  124. }
  125.  
  126.  
  127.  
  128. uint32_t fInit[MAXSTACKSIZE];
  129. uint32_t fRun[MAXSTACKSIZE];
  130. int init(){
  131.   if (WUSB_udev == NULL) return -1;
  132.   int retval = xxusb_register_write(WUSB_udev,1,0x0); // Stop DAQ mode
  133.   if (retval<0) return retval;
  134.   while (xxusb_usbfifo_read(WUSB_udev,(int *) stackdump,BUFF_L,100)>0);
  135.  
  136.  
  137.   int rate=1000;
  138.   int ii=80000000/rate-40; // 80 MHz
  139.   if (ii<72) ii=72;
  140.         // Set DGG channel A as a pulser, output on O1,
  141.         //     with delay =500 x 12.5ns,
  142.         //     and width =  500 x 12.5ns,
  143.         //     not latching or inverting
  144.   //  VME_DGG(udev,0,6,0,24000,6000,0,0);
  145.   VME_DGG(WUSB_udev,0,6,0,ii,40,0,0);
  146.         // Set DGG channel B to trigger on NIM1, output on O2,
  147.         //     with delay =200 x 12.5ns,
  148.         //     and width =  200 x 12.5ns,
  149.         //     not latching or inverting
  150.         VME_DGG(WUSB_udev,1,1,1,0,10,0,1);
  151.   printf("CAEN V965 Pedestal set to %d\n", fPedestal);
  152.  
  153. // INIT stackdata
  154.         int fPedestal=255;
  155.         WIENER_VMUSB_StackInit();
  156.  
  157.  
  158.         for (int i=0;i<nadc;i++){
  159.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_CRN , 0x0);
  160.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_GEO , i);
  161.                 WIENER_VMUSB_StackReadA24D16(addr[i] + CAENV965_GEO);
  162.     for (int j=0;j<32;j++){
  163.                    WIENER_VMUSB_StackWriteA24D16(addr[i] + CAENV965_THM + 0x02*j, fThreshold[j+i*32]); // threshold/kill for 32 channels
  164.     }
  165.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_BS1, 0x80 ); // soft reset
  166.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_BC1, 0x80 ); // soft reset
  167.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_PED, fPedestal ); // pedestal
  168.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_BS2,0x5000);
  169.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_BS2,0x4);  // clear module
  170.                 WIENER_VMUSB_StackWriteA24D16( addr[i] + CAENV965_BC2,0x4);
  171.         }
  172.         WIENER_VMUSB_StackMarker(0xFAFC);
  173.  
  174.         WIENER_VMUSB_StackGetUInt32(MAXSTACKSIZE, fInit);
  175.  
  176. //      fInit->Print();
  177.        
  178.        
  179.         // READOUT stackdata
  180.         WIENER_VMUSB_StackInit();  
  181.   WIENER_VMUSB_StackMarker(0xFFAB);
  182.        
  183.         //fStack->ConditionalRead(addr[i] + CAENV965_SR1,0x1);        // TRG wait : loop until bit 0 is on
  184.         // fStack->RepeatRead( CMD_A24, CMD_D32, addr[i] + CAENV965_OB,34,0);  // repead read
  185.         //fStack->ConditionalRead(addr[i] + CAENV965_OB ,0x4000000) ; // loop until bit 26 is on, read data
  186.   for (int j=0;j<36;j++) WIENER_VMUSB_StackReadA24D32(addr[0] + CAENV965_OB);
  187.   //for (int j=0;j<36;j++) fStack->ReadA24D32(addr[1] + CAENV965_OB);
  188.   //for (int j=0;j<8;j++) fStack->ReadA24D32(addr[2] + CAENV965_OB);// 4 channels connected
  189.         WIENER_VMUSB_StackMarker(0xFAFB);  
  190.  
  191.         for (int k=0;k<nadc;k++){
  192.                 WIENER_VMUSB_StackWriteA24D16(addr[k] + CAENV965_BS2,0x4);  // clear module
  193.                 WIENER_VMUSB_StackWriteA24D16(addr[k] + CAENV965_BC2,0x4);  
  194.         }
  195.  
  196.         //fStack->Print();
  197.  
  198.  VME_LED_settings(WUSB_udev, 0,0,0,0); // Set Yellow LED to light with with USB out buffer not empty
  199.  VME_LED_settings(WUSB_udev, 1,1,0,0); // Set Red LED to light with NIM1
  200.  VME_LED_settings(WUSB_udev,2,0,0,0); // Set Green LED to light when stack is not empty
  201.  
  202.  uint32_t  vmereg;
  203.  VME_register_read(WUSB_udev,0x00,&vmereg);
  204.  printf("VMUSB Firmware ID -> 0x%08X\n",vmereg);
  205.  
  206.  VME_register_read(WUSB_udev,0x04,&vmereg);
  207.  printf("VMUSB Global Mode -> 0x%08X\n",vmereg);
  208.  
  209.  vmereg=(vmereg&0xF000)|0x0004;
  210.  VME_register_write(WUSB_udev,0x04,vmereg);
  211.  VME_register_write(WUSB_udev,0x08,0x00000080);
  212.  VME_register_write(WUSB_udev,0x28,0x0);
  213.  VME_register_write(WUSB_udev,0x2C,0x0);
  214.  VME_register_write(WUSB_udev,0x30,0x0);
  215.  VME_register_write(WUSB_udev,0x34,0x0);
  216.  VME_register_write(WUSB_udev,0x3C,0x000);
  217.  
  218.  int nb = 0;
  219.  int ret= xxusb_stack_execute(WUSB_udev,(uint32_t *)fInit);
  220.  printf("Init::%d ret=%d\n",nb,ret);
  221.  if (ret>0) for (int ki=0;ki<ret/2;ki++) printf ("stackdata=0x%08X\n",stackdata[ki]);
  222.  
  223.  int nb0= 0; //fStack->Get(10000,&stackwrite[0]);
  224.  if (nb0>768) {
  225.    fprintf(stderr,"nb0=%d > 768 error xxusb_stack_write\n", nb0);
  226.    exit(-1);
  227.  }
  228.  nb =xxusb_stack_write(WUSB_udev,0x2,(uint32_t *) fRun);
  229.  nb0=xxusb_stack_read(WUSB_udev,0x2,(uint32_t *) stackdata);
  230.  for (int li=0;li<fRun[0]+1;li++){
  231.    if (stackdata[li]!=fRun[li]) printf("%d %d init err %x %x\n",nb,nb0,fRun[li], stackdata[li]);
  232.  }
  233.  
  234.  if (fMode==2) xxusb_register_write(WUSB_udev,1,0x1); // Start DAQ mode
  235.  
  236.  printf("daq::init() \n");
  237.  return 0;
  238. }
  239.  
  240. int connect(){
  241.     WIENER_VMUSB_VME_START(USBVME_NAME);
  242.     if (WUSB_udev == NULL) printf("daq::connect() not initialized");
  243.     printf("daq::connect()\n");
  244.     return 0;
  245. }
  246.  
  247. int disconnect(){
  248.   /* zakljuci */
  249.   WIENER_VMUSB_VME_STOP();
  250.   printf("daq::disconnect()\n");
  251.   return 0;
  252. }
  253.  
  254. int clear(){    
  255.    return 0;
  256. }
  257.  
  258. int module_header(int recid,uint32_t *data,int len){
  259.    data[0] = recid;
  260.    data[1] = (len >0)? len : 0 ;
  261.    return data[1]+2;
  262. }
  263.  
  264.  
  265. int event(unsigned int *data, int maxn, int *ctr, int print){
  266.    int tout=200; /* 1/100 of a second */
  267.    const int lsize=sizeof(uint32_t);  
  268.  
  269.    if (WUSB_udev==NULL) return -222;
  270.    ctr[0]++;
  271.    ctr[1]++;
  272.    
  273.    int count=0;
  274.          switch (fMode){
  275.          case 0:// normal calls
  276.                  {
  277.                          unsigned short clr= 0x4;
  278.                          unsigned int status=0;
  279.        int32_t mdata;
  280.                          
  281.                          for (int i=0;i<nadc;i++){
  282.                                  // wait for trg
  283.                                  tmlnk (tout);
  284.                                  do WIENER_VMUSB_VME_A24D16_R( addr[i] + CAENV965_SR1, &status); while ( (status&0x1)==0 && timer_out==0 );
  285.                                  tmulk();
  286.                                  // readout data
  287.                                  if (timer_out) return 0;
  288.                                  int len=0;
  289.                                  
  290.                                  do {
  291.                                          WIENER_VMUSB_VME_A24D32_R(addr[i]  + CAENV965_OB, &mdata);
  292.                                          mdata=data[count++];
  293.                                          len++;
  294.                                  } while  ( (mdata & 0x4000000)==0 && timer_out==0) ; // bit 26 EOB or not valid datum
  295.                                  // clear
  296.                                  WIENER_VMUSB_VME_A24D16_W( addr[i] + CAENV965_BS2, &clr);
  297.                                  WIENER_VMUSB_VME_A24D16_W( addr[i] + CAENV965_BC2, &clr);
  298.                                  
  299.                                  if (count+2<maxn) {
  300.                                          if (print)  printf("V965 %3d\n",len);
  301.                                          count+=module_header(0x130+i,&data[count],len);
  302.                                          ctr[2]++;
  303.                                          ctr[3]+=len;
  304.                                  }
  305.                          
  306.                                  timer_out=0;
  307.                          }
  308.                  }
  309.                  break;
  310.          case 1:// stack execute
  311.                  {
  312.                          for (int k=0;k<10000;k++) data[k]=fRun[k];
  313.                          int ret=xxusb_stack_execute(WUSB_udev,(uint32_t *) data); //The first element of the array is the number of bytes.
  314.        if (ret< 0 ) {
  315.                                  printf ("xxusb_stack_execute error err=%d\n",ret);     \
  316.                                  count = 0;
  317.                          } else count= ret/lsize;
  318.  
  319.                  }
  320.                  break;
  321.          case 2:// stack load
  322.                  {
  323.                          int ret=xxusb_usbfifo_read(WUSB_udev,(int *) data,BUFF_L,100);
  324.                          if (ret< 0 ) {
  325.                                  if (ret!=-110) {
  326.                                     printf ("xxusb_usbfifo_read error err=%d\n",ret);
  327.                                     end();
  328.                                     init();
  329.                                  }     
  330.                                  count = 0;
  331.                          } else {
  332.                                  if (0 && print && ret>0) {
  333.                                          for (int i=0;i<100;i++) {
  334.                                                  printf ("%4d fifodata=0x%08X\n",i, data[i]);
  335.              if (data[i]==0xFAFB) break;
  336.                                          }
  337.                                          /*
  338.    
  339.    0 fifodata=0x0000000D
  340.    1 fifodata=0x00000049
  341.    2 fifodata=0x0000FFAB
  342.    3 fifodata=0x00002000
  343.    4 fifodata=0x00000200
  344.    5 fifodata=0x00004141
  345.    6 fifodata=0x00000000
  346.    7 fifodata=0x00004057
  347.    8 fifodata=0x00000010
  348.    9 fifodata=0x00004052
  349.   10 fifodata=0x00000001
  350.   11 fifodata=0x0000405C
  351.   12 fifodata=0x00000011
  352.   13 fifodata=0x0000405D
  353.   14 fifodata=0x00000002
  354.   15 fifodata=0x0000405E
  355.   16 fifodata=0x00000012
  356.   17 fifodata=0x0000401C
  357.   18 fifodata=0x00000003
  358.   19 fifodata=0x0000402F
  359.   20 fifodata=0x00000013
  360.   21 fifodata=0x00004024
  361.   22 fifodata=0x00000004
  362.   23 fifodata=0x00004076
  363.   24 fifodata=0x00000014
  364.   25 fifodata=0x0000412F
  365.   26 fifodata=0x00000005
  366.   27 fifodata=0x0000404C
  367.   28 fifodata=0x00000015
  368.   29 fifodata=0x00004132
  369.   30 fifodata=0x00000006
  370.   31 fifodata=0x00004044
  371.   32 fifodata=0x00000016
  372.   33 fifodata=0x0000404A
  373.   34 fifodata=0x00000007
  374.   35 fifodata=0x0000409B
  375.   36 fifodata=0x00000017
  376.   37 fifodata=0x000040F1
  377.   38 fifodata=0x00000008
  378.   39 fifodata=0x00004087
  379.   40 fifodata=0x00000018
  380.   41 fifodata=0x00004173
  381.   42 fifodata=0x00000009
  382.   43 fifodata=0x0000404C
  383.   44 fifodata=0x00000019
  384.   45 fifodata=0x0000406C
  385.   46 fifodata=0x0000000A
  386.   47 fifodata=0x00004070
  387.   48 fifodata=0x0000001A
  388.   49 fifodata=0x0000406E
  389.   50 fifodata=0x0000000B
  390.   51 fifodata=0x00004014
  391.   52 fifodata=0x0000001B
  392.   53 fifodata=0x000040B7
  393.   54 fifodata=0x0000000C
  394.   55 fifodata=0x000040A9
  395.   56 fifodata=0x0000001C
  396.   57 fifodata=0x00004048
  397.   58 fifodata=0x0000000D
  398.   59 fifodata=0x00004118
  399.   60 fifodata=0x0000001D
  400.   61 fifodata=0x0000409D
  401.   62 fifodata=0x0000000E
  402.   63 fifodata=0x0000405B
  403.   64 fifodata=0x0000001E
  404.   65 fifodata=0x00004285
  405.   66 fifodata=0x0000000F
  406.   67 fifodata=0x00004159
  407.   68 fifodata=0x0000001F
  408.   69 fifodata=0x00000035
  409.   70 fifodata=0x00000400
  410.   71 fifodata=0x00000035
  411.   72 fifodata=0x00000600
  412.   73 fifodata=0x00000035
  413.   74 fifodata=0x0000FAFB
  414.  
  415.  
  416.                                          */
  417.                                  }
  418.                                  if (print) printf("------------------ret=%d data[0]=%d\n",ret,(int)data[0]);
  419.                                  count= ret/lsize;
  420.                                  ctr[2]+=data[0];
  421.                                  ctr[3]+=count;
  422.                          }
  423.                  }
  424.                  break;
  425.          }
  426.    return count*lsize;
  427. }
  428.  
  429. int end(){
  430.    if (WUSB_udev!=NULL) {
  431.            xxusb_register_write(WUSB_udev,1,0x0); // Stop DAQ mode
  432.            while (xxusb_usbfifo_read(WUSB_udev,(int *) stackdata,BUFF_L,30)>0);  
  433.    }
  434.    printf("daq::end()\n");
  435.   return 0;
  436. }
  437.  
  438. int daq_init(){
  439.   fMode = 2;
  440.   fPedestal=255;
  441.   for (int i=0;i<128;i++){
  442.      if (i<72) fThreshold[i]= 0;      
  443.      else      fThreshold[i]= 0x1<<8; // samo 4 kanali na zadnjem modulu so enablani
  444.   }
  445.   fThresholdEnable=0;
  446.   fStop=0;
  447.   //fInit=NULL;
  448.   //fStack=NULL;
  449.   connect();
  450.   return 0;
  451. }
  452.  
  453.  
  454. /* ------------------- CatchSig ----------------- */
  455. int ctrlcflag=0;
  456.  
  457. void SigInt (int sig)
  458. {
  459.     ctrlcflag = 1;
  460.     timer_out=1;
  461. }
  462.  
  463.  
  464. int read_pedestals(char *fpedname) {
  465.   FILE *fped=fopen(fpedname,"r");
  466.   if(fped==NULL) return -1;
  467.   int j=0;
  468.   int ndim=400;
  469.   char line[ndim];
  470.   int val=0;
  471.   while (fgets(line,ndim,fped)!=NULL) {
  472.     sscanf(line,"%d",&val);
  473.     fThreshold[j++]=val;
  474.   }
  475.   fThresholdEnable=1;
  476.   //fclose(fped);
  477.   fclose(fped);
  478.   return 0;
  479. }
  480.      
  481. int main (int argc, char **argv){
  482.    // intercept routine
  483.    if (signal (SIGINT, SigInt) == SIG_ERR) {
  484.         perror ("sigignore");
  485.    }
  486.  
  487.    // print welcome message
  488.   time_t t,told=0, tstart, tstop;
  489.   time(&t);
  490.   fprintf(stdout,"#############################################\n");
  491.   fprintf(stdout,"Program %s version %2.1f\n",argv[0], VERSION);
  492.   fprintf(stdout,"Compiled on %s %s\n",__DATE__, __TIME__);
  493.   fprintf(stdout,"Runtime  %s \n",ctime(&t));
  494.   fprintf(stdout,"#############################################\n");
  495.  
  496.  
  497.   int neve=-1;
  498.   char cfname[100]="test.dat";
  499.   char *fname=cfname;
  500.   char *fpedname=NULL;
  501.  
  502. #define BSIZE 10000
  503.   uint32_t data[10000];
  504.   daq_init();
  505.  
  506.   if (argc>3) {
  507.  
  508.       fpedname = argv[3];
  509.       read_pedestals(fpedname);
  510.      
  511.   }
  512.  
  513.   if (argc>2) neve  = atoi(argv[2]); // negative argument time ( in s )limited event loop
  514.   if (argc>1) {
  515.     fname = argv[1];
  516.  
  517.     if (fexist(fname)==1){
  518.        fprintf(stdout,"Error !\n");
  519.        fprintf(stdout,"File %s already exist. Appending ....\n",fname);
  520.        //fprintf(stdout,"Remove the file and restart !!!\n");
  521.        //exit(0);
  522.     }
  523.   }
  524.  
  525.   FILE *fp=fopen(fname,"a");
  526.   //gzFile fp=gzopen(fname,"a");
  527.  
  528.   init();
  529.   clear();
  530.  
  531.   int hdr[4]={2}; // recid od run 11 naprej
  532.   int i=0;
  533.   int ntotal=0;
  534.   int counters[30]={0,0,0,0,0, 0,0,0,0,0,0,0};
  535.   char names[10][20]={"TRG","CAEN V965"};
  536.   time(&t);
  537.   tstart=t;
  538.   tstop=tstart+360000;
  539.   if (neve<-1) {
  540.     tstop=tstart-neve;
  541.     neve=-1;
  542.   }
  543.   for (i=0;i!=neve && !ctrlcflag && t<tstop;i++){
  544.      time(&t);
  545.      if (t!=told ) printf("%d in %2.2f min daq::event() %s\n",i, (double)(t-tstart)/60., ctime(&t));
  546.      int nb=event(data,BSIZE, counters,t!=told);
  547.      if (nb>0){
  548.       // zapis v datoteko  
  549.       hdr[1]=nb+4*sizeof(int);
  550.       hdr[2]=time(NULL);
  551.       hdr[3]=i;
  552.    
  553.       fwrite(hdr,   sizeof(int),4 , fp);
  554.       //gzwrite(fp, hdr,   sizeof(int)*4); //gzip
  555.      // recid=1 do runa 10.  ntotal += fwrite(data,   sizeof(int),nb, fp);
  556.       ntotal += fwrite(data, 1,nb, fp);
  557.       //ntotal += gzwrite(fp, data, nb);
  558.       told=t;
  559.      } else i--;
  560.   }
  561.  
  562.   end();
  563.  
  564.   printf("Number of Events: %d\n",i);
  565.   if (ctrlcflag) printf("User Program termination CTRL-C\n");
  566.   if (t>tstop  ) printf("Timeout termination tstart# t>tstop: %d# %d >%d\n",(int)t, (int)tstart, (int) tstop);
  567.  
  568.  
  569.   fclose(fp);  
  570.   //gzclose(fp);  
  571.   fprintf(stdout,"%d bytes written to %s\nCounts:\n", (int) (ntotal*sizeof(int)),fname);
  572.   for (i=0;i<2;i++) fprintf(stdout,"%s\t%d\t%d\n",names[i],counters[2*i],counters[2*i+1]) ;
  573.  
  574.  
  575.   if (argc==1) {
  576.     fprintf(stdout,"Usage: %s [filename] [number of events] [thresholdfile]\n negative number of events = acq time in seconds\n",argv[0]);
  577.   }
  578.   disconnect();
  579.   return 0;
  580. }
  581.  
  582.