| 1 | C -+-+-+-+-+ \ e H A E A D C . F T \ e -+-+-+-+-+\r |
| 2 | C\r |
| 3 | C * UP 6-OCT-82\r |
| 4 | C * UP 25-OCT-82\r |
| 5 | C * UP 11-MAY-83\r |
| 6 | C * UP 15-JUL-83 IMPROVED FILE OVERFLOW PROTECTION\r |
| 7 | C * UP 22-NOV-83 IMPROVED FILE OVERFLOW MESSAGE\r |
| 8 | C * UP 1-JUL-85 SCHMITT TRIGGER INPUT\r |
| 9 | C\r |
| 10 | C ANALOG --> DIGITAL CONVERSION AND DATA ACQUISITION\r |
| 11 | SUBROUTINE ADCON\r |
| 12 | INCLUDE HAEBUF.FI\r |
| 13 | INCLUDE HAEHAS.FI\r |
| 14 | INCLUDE HAEPTI.FI\r |
| 15 | INCLUDE HABRK.FI\r |
| 16 | INCLUDE HAETTY.FI\r |
| 17 | INTEGER TOASCI,NCOND,LOG2\r |
| 18 | LOGICAL BETW\r |
| 19 | EXTERNAL TOASCI,NCOND,LOG2,BETW\r |
| 20 | C\r |
| 21 | \fC\r |
| 22 | INTEGER PARMS(4),CSTART @ THRUPT PARAMETER VECTOR, STARTCHANNEL\r |
| 23 | EQUIVALENCE (PARMS(1),CSTART)\r |
| 24 | INTEGER BUFF1(85),BUFF2(85), @ THRUPT BUFFERS\r |
| 25 | * I,TEMP1,TEMP2,TEMP3,C,CH,SS, @ TEMPORARY STORAGE\r |
| 26 | * STARTR @ BLOCK NUMBER OF THE HEADER FOR THE ACTUAL DATA SET (UNIT 6)\r |
| 27 | * ,CLKPRM(4) @ FIRST PARAMETER TO CLOCK4 (STRIGG CHANNEL BIT PATTERN),\r |
| 28 | REAL STAT1,STAT2 @ THRUPT STATUS WORDS\r |
| 29 | EXTERNAL STAT1,STAT2 @ SET BY ADBUFF SAMPLING PROCEDURE\r |
| 30 | DATA CSTART /0/, CLKPRM /0,1,3,7/\r |
| 31 | C\r |
| 32 | C PREPARE THE DEFAULT VALUES FOR SAMRAT,SAMCNT,CSTART\r |
| 33 | C AND READ THE NEW VALUES\r |
| 34 | C\r |
| 35 | IF (XSAML.EQ.0) RETURN @ NO OUTPUT FILE SPACE, SKIP ADCON\r |
| 36 | PARMS(2)=CHNLS @ INSERT THE NUMBER OF INPUT CHANNELS INTO THRUPT PARAMETER VECTOR\r |
| 37 | TEMP2=0 @ WE USE IF WE DO A JUMP TO 40\r |
| 38 | TEMP3=2H00 @ "" "" "" "" ""\r |
| 39 | LABCNT=0 @ FORCE IDENTIFICATION TO SPACES\r |
| 40 | SAMCNT=NCOND(SAMCNT,SAMCNT,32*SAMRAT) @ 32 SEC IS THE DEFAULT SAMPLING TIME\r |
| 41 | C\r |
| 42 | IF (OPTION.EQ.12) GOTO 22 @ IF 'AD*' THEN WE ASSUME THE DEFAULT PARAMETERS\r |
| 43 | IF (.NOT.(OPTION.GE.2 .AND. OPTION.LE.10)) GOTO 10\r |
| 44 | SAMCNT=(OPTION-1)*60*SAMRAT @ AD1 ... AD9 FROM 1 TO 9 MINUTES TIME\r |
| 45 | GOTO 20 @ READ THE DATA SET IDENTIFICATION ONLY\r |
| 46 | C\r |
| 47 | 10 CONTINUE @ COMPUTE THE DEFAULT SAMPLE TIME\r |
| 48 | I=SAMCNT/SAMRAT @ SAMPLE TIME IN SECONDS --> I\r |
| 49 | CH=NCOND(I.GE.3600,1HH,1HM) @ COMPUTE THE CORRECT SUFFIX: HOURS OR MINUTES\r |
| 50 | I=I/NCOND(I.GE.3600,60,1) @ IF THE SAMPLING TIME EXCEEDS ONE HOUR THEN WE CONVERT INTO MINUTES\r |
| 51 | MM=TOASCI(I/60) @ AND CONVERT INTO ASCII CHARACTERS\r |
| 52 | SS=TOASCI(MOD(I,60)) @ FOR MINUTES AND SECONDS OR HOURS AND MINUTES\r |
| 53 | WRITE (TTO,101) MM,CH,SS\r |
| 54 | READ (TTI,102) MM,C,SS @ GET THE SAMPLING TIME\r |
| 55 | IF (BREAK(11)) RETURN @ USER GET'S RID OF PROGRAM\r |
| 56 | SS=NCOND(MM+SS,MM*60+SS,I)*\r |
| 57 | * NCOND(C.EQ.1HH,60,C.EQ.1HM,1,CH.EQ.1HH,60,1)\r |
| 58 | WRITE (TTO,103) SAMRAT @ AND ASK FOR THE SAMPLING FREQUENCY\r |
| 59 | READ (TTI,104) TEMP1\r |
| 60 | SAMRAT=NCOND(TEMP1,TEMP1,SAMRAT)\r |
| 61 | WRITE (TTO,107) SPEED @ AND ASK FOR THE TAPE SPEED FACTOR\r |
| 62 | READ (TTI,1) TEMP1\r |
| 63 | SPEED=NCOND(TEMP1,TEMP1,SPEED.GT.0,SPEED,1)\r |
| 64 | CSTART=0\r |
| 65 | CX WRITE (TTO,105) @ ASK FOR START CHANNEL WHERE TO SAMPLE\r |
| 66 | CX READ (TTI,104) CSTART\r |
| 67 | WRITE (TTO,106) CHNLS\r |
| 68 | READ (TTI,1) I\r |
| 69 | CHNLS=NCOND(I,I,CHNLS)\r |
| 70 | PARMS(2)=CHNLS @ THE NUMBER OF CHANNELS TO SAMPLE\r |
| 71 | C\r |
| 72 | DO 35 I=1,CHNLS\r |
| 73 | TEMP1=SAMRAT/PACK(I) @ HERE WE ASK FOR THE SAMPLE RATE OF EACH CHANNEL\r |
| 74 | 36 WRITE (TTO,108) I,TEMP1 @ TYPE CHANNEL NUMBER AND DEFAULT SAMPLE RATE\r |
| 75 | READ (TTI,104) TEMP2 @ READ THE SAMPLE FREQUENCY\r |
| 76 | TEMP1=NCOND(TEMP2,TEMP2,TEMP1) @ IF NO INPUT, THEN WE INSERT THE DEFAULT VALUE\r |
| 77 | PACK(I)=SAMRAT/TEMP1 @ RATIO (MAX SAMPLE RATE)/(CHANNEL SAMPLE RATE) --> PACK\r |
| 78 | IF (PACK(I).LT.1) GOTO 36\r |
| 79 | IF (LOG2(PACK(I)).GE.0) GOTO 35 @ THE RATIO MUST BE A POWER OF TWO, IF SO ASK FOR NEXT CHANNEL \r |
| 80 | WRITE (TTO,109) @ ELSE WE PRINT A MESSAGE AND \r |
| 81 | TEMP1=SAMRAT @ MAKE A NEW DEFAULT VALUE END THEN\r |
| 82 | GOTO 36 @ WE ASK AGAIN\r |
| 83 | 35 CONTINUE\r |
| 84 | C\r |
| 85 | 42 WRITE (TTO,2) STRIGS @ ASK FOR NUMBER OF SCHMITT TRIGGER INPUTS\r |
| 86 | READ (TTI,202) I\r |
| 87 | I=NCOND(I.EQ.1H0,0,I.EQ.1H1,1,I.EQ.1H2,2,I.EQ.1H3,3,STRIGS)\r |
| 88 | IF (BREAK(11)) RETURN @ SWITCH 11: RETURN\r |
| 89 | IF (BETW(0,I,4).AND.CHNLS+I.LE.7) @ WE ALLOW 0 TO 3 BUT NOT MORE THAN 7 CHANNELS AT ALL!\r |
| 90 | * GOTO 41\r |
| 91 | I=MIN0(7-CHNLS,3) @ COMPUTE CHANNELS LEFT FOR S"TRIGG\r |
| 92 | WRITE (TTO,201) I\r |
| 93 | GOTO 42 @ AND ASK AGAIN\r |
| 94 | 41 STRIGS=I @ NUMBER OF STRIG INPUTS --> STRIGS\r |
| 95 | CALL MOVE (-STRIGS,1,PACK(CHNLS+1)) @ HIGHEST SAMPLE RATE FOR TRIGGERED EVENTS!\r |
| 96 | SAMCNT=SAMRAT*SS @ NUMBER OF SAMPLES TO TAKE FOR THE 'SAMRAT' FREQUENCY CHANNEL\r |
| 97 | \fC\r |
| 98 | 22 CONTINUE @ HERE WE COME IF AD* SWITCHED ON\r |
| 99 | PCKMAX=0\r |
| 100 | DO 38 C=1,CHNLS+STRIGS @ FETCH DIVIDER FOR SLOWEST FREQUENCY\r |
| 101 | 38 PCKMAX=MAX0(PCKMAX,PACK(C))\r |
| 102 | C\r |
| 103 | HSHDON=.FALSE. @ DESTROY HASH CODE TABLE (USED BY ESAM)\r |
| 104 | CALL MKHASH @ MAKE A HASH TABLE TO SEE IF POSSIBLE\r |
| 105 | IF (.NOT.HSHDON) GOTO 10 @ HASH TABLE TOO LONG, SO WE ASK AGAIN FOR NEW PARAMETERS\r |
| 106 | HSHDON=.FALSE. @ AND NOW WE DESTROY THE HASH CODE TABLE SINCE WE\r |
| 107 | J=0 @ WE BUILD THE "SAMPLE VALID" TABLE FOR ADBUFF ROUTINE\r |
| 108 | DO 39 I=1,PCKMAX @ INTO THE HASH CODE TABLE IN ORDER TO SAVE CORE\r |
| 109 | DO 39 C=1,CHNLS+STRIGS\r |
| 110 | J=J+1\r |
| 111 | 39 HASHV(J)=NCOND(MOD(I,PACK(C)),0,1)\r |
| 112 | C\r |
| 113 | TOTSAM=SAMCNT*HSHSIG/PCKMAX @ TOTAL NUMBER OF SAMPLES (PACKED AND FOR ALL CHANNELS) --> TOTSAM\r |
| 114 | IF (XSAML.GT.TOTSAM) GOTO 20 @ TEST: SAMCNT MAY NOT EXCEED THE REMAINING FILE SPACE ON UNIT 6\r |
| 115 | 25 CONTINUE @ THE BUFFER IS TOO SMALL FOR THIS SAMPLE COUNT, ASK FOR A NEW ONE\r |
| 116 | TEMP1=XSAML/(HSHSIG*SAMRAT/PCKMAX)/60 @ MINUTES STILL FITTING INTO THE BUFFER --> TEMP1\r |
| 117 | WRITE (TTO,3) XSAML,TOTSAM,TEMP1,REC6,LASREC @ NUMBER TOO LARGE, BUFFER WILL OVERFLOW\r |
| 118 | SAMCNT=XSAML/HSHSIG*PCKMAX @ INSERT THE MAXIMUM SAMPLE COUNT --> SAMCNT\r |
| 119 | IF (BREAK(11)) RETURN @ USER GET'S RID OF PROGRAM\r |
| 120 | GOTO 10 @ AND ASK AGAIN \r |
| 121 | C\r |
| 122 | 20 CONTINUE\r |
| 123 | C READ THE DATA SET IDENTIFICATION \r |
| 124 | C\r |
| 125 | 17 CONTINUE\r |
| 126 | IF (BREAK(11)) RETURN @ USER GET'S RID OF PROGRAM\r |
| 127 | WRITE (TTO,5) SIXCNT @ DATASET IDENTIFICATION? \r |
| 128 | READ (TTI,6) LABEL\r |
| 129 | IF (BREAK(11)) RETURN @ USER GET'S RID OF PROGRAM\r |
| 130 | DO 15 I=1,10 @ STRIP OFF THE TRAILING SPACES\r |
| 131 | IF (LABEL(11-I).NE. 1H ) GOTO 16\r |
| 132 | 15 CONTINUE\r |
| 133 | GOTO 17 @ SPACES ARE NO VALID INPUT AT ALL\r |
| 134 | 16 LABCNT=11-I\r |
| 135 | C\r |
| 136 | C PREPARE THE SAMPLING\r |
| 137 | C\r |
| 138 | 50 CONTINUE\r |
| 139 | COMP=.FALSE. @ WE GET A NEW DATA SET SO THERE ARE NO COMPUTATIONS DONE SO FAR\r |
| 140 | IF (SAMCNT.EQ.0) GOTO 40 @ NOTHING TO DO, SKIP THE SAMPLING\r |
| 141 | WRITE (TTO,9) @ SKIP A LINE (USED BY ETIME OUTPUT)\r |
| 142 | COMP=.FALSE. @ RESET COMPUT FLAG\r |
| 143 | PARMS(3)=SAMCNT*(CHNLS+STRIGS) @ TOTAL NUMBER OF SAMPLES INCLUDING INVALID ONES\r |
| 144 | PARMS(4)=PCKMAX*(CHNLS+STRIGS) @ LENGTH OF VALID VECTOR\r |
| 145 | CALL THRUPT (BUFF1,BUFF2,PARMS,HASH,STRIGS\r |
| 146 | * ,1.E5/FLOAT(SAMRAT)/FLOAT(SPEED)/12.) @ SET UP BUFFERED A/D CONVERSION AND TRIGGERED EVENTS\r |
| 147 | C LAST PARAMTER:\r |
| 148 | C TRIGGER FREQUENCY/(AD FREQUENCY)/(# OF SLOTS)\r |
| 149 | C 1.E5 REQUIRES CLOCK4 WITH RATE OF 30 HZ\r |
| 150 | C THIS IS THE RATIO BETWEEN TRIGGER CLOCK AND A/D CLOCK.\r |
| 151 | C AT CLOCK1 INTERRUPT FOR A/D SAMPLING WE CLEAR THE CLOCK4 COUNTER.\r |
| 152 | C THE TIME OF THE TRIGGER INPUT - TOKEN WITH CLOCK4 - IS DIVIDED BY THE \r |
| 153 | C LAST PARAMETER TO THRUPT. THE RESULT IS BETWEEN 0 AND THE # OF SLOTS-1.\r |
| 154 | C WITH 12 SLOTS (ONE 8-WORD) WE GET AN ACCURACY OF 1/SAMRAT/12 HZ FOR\r |
| 155 | C THE TIME OF THE EVENT. (FOR 64 HZ APPROX 1.3 MILLI SEC \r |
| 156 | C FOR 256 HZ 0.3 MILLI SEC.\r |
| 157 | C MAX SAMRAT IS 512 HZ I THINK.\r |
| 158 | C\r |
| 159 | C\r |
| 160 | C OPEN THE OUTPUT FILE, WRITE THE DATA SET HEADER BLOCK\r |
| 161 | C\r |
| 162 | STARTR=REC6 @ ADR. OF HEADER BLOCK --> STARTR\r |
| 163 | REDVAL=6HDLWPD2 @ SET THE READ VALID FLAG\r |
| 164 | LASREC=(SAMCNT*HSHSIG/PCKMAX+254)/255+REC6+1 @ COMPUTE THE NUMBER OF BLOCKS FOR THIS SAMPLE\r |
| 165 | WRITE (6'REC6) (RCRD0(I),I=1,85)@ WRITE THE NEW HEADER BLOCK\r |
| 166 | REDVAL=0 @ RESET THE READ VALID FLAG\r |
| 167 | OFFSET=REC6 @ START ADR. OF THE DATA BUFFER SPACE --> OFFSET\r |
| 168 | \fC\r |
| 169 | C START THE SAMPLING \r |
| 170 | C\r |
| 171 | CALL CLOCK1 (8,SAMRAT*SPEED) @ A/D CONVERSION ENABLED FROM SECOND DK8-EP CLOCK!\r |
| 172 | CALL CLOCK4 (CLKPRM(STRIGS+1),30.) @ ENABLE TRIGGERED INPUT VIA FIRST CLOCK-100K HZ FREQUENCY\r |
| 173 | IF BREAK(11) GOTO 60 @ USER DOES NOT KNOW WHAT HE WANTS\r |
| 174 | 100 CALL MARK (SPEED) @ TYPE OUT THE TIME ELAPSED \r |
| 175 | 111 IF(STAT1-0.5) 100,110,120\r |
| 176 | 110 WRITE (6'REC6) BUFF1 @ TRANSFER 255 SAMPLES ONTO MASS STORAGE\r |
| 177 | CALL RELEAS (1)\r |
| 178 | IF (REC6 .EQ. LASREC) GOTO 30 @ LOOK IF THE WORK IS DONE\r |
| 179 | CX IF (REC6.LT.LASREC-1 .AND.BREAK(11)) GOTO 60 @ USER ABORT ONLY IF THERE ARE AT LEAST 256 SAMPLES LEFT\r |
| 180 | GOTO 211\r |
| 181 | 200 CALL MARK (SPEED) @ TYPE OUT THE TIME ELAPSED \r |
| 182 | 211 IF (STAT2-0.5) 200,210,220\r |
| 183 | 210 WRITE (6'REC6) BUFF2 @ TRANSFER 255 SAMPLES ONTO MASS STORAGE\r |
| 184 | CALL RELEAS (2)\r |
| 185 | IF (REC6 .EQ. LASREC) GOTO 30 @ LOOK IF THE WORK IS DONE\r |
| 186 | IF (REC6.LT.LASREC-1 .AND.BREAK(11)) GOTO 60 @ USER ABORT ONLY IF THERE ARE AT LEAST 256 SAMPLES LEFT\r |
| 187 | GOTO 111 @ GO AND WAIT FOR BUFFER # 1\r |
| 188 | 120 TEMP1=1 @ BUFFER 1 OVERFLOW\r |
| 189 | GOTO 125\r |
| 190 | 220 TEMP1=2 @ BUFFER TWO OVERFLOW\r |
| 191 | 125 WRITE (TTO,7) I,TEMP1 @ SAMPLING TOO FAST\r |
| 192 | GOTO 10 @ TRY ONCE MORE\r |
| 193 | C\r |
| 194 | C SAMPLING FINISHED\r |
| 195 | C\r |
| 196 | 60 CONTINUE @ USER SWITCHED SW 11\r |
| 197 | TEMP2=MAX1(0,TIME(TEMP2)+0.5)*SPEED @ GET SAMPLING TIME PRIOR TO ANY OUTPUT\r |
| 198 | SAMCNT=(REC6-STARTR-1)*255*PCKMAX/HSHSIG @ COMPUTE NUMBER OF SAMPLES TOKEN\r |
| 199 | LASREC=REC6-1 @ INSERT THE NEW SAMCNT AND LASREC INTO THE HEADER BLOCK\r |
| 200 | REC6=STARTR @ ADR. OF HEADER BLOCK --> REC6\r |
| 201 | REDVAL=6HDLWPD2 @ SET THE READ VALID FLAG\r |
| 202 | WRITE (6'REC6) (RCRD0(I),I=1,85) @ AND WRITE THE NEW HEADER BLOCK\r |
| 203 | REDVAL=0 @ RESET THE READ VALID FLAG\r |
| 204 | WRITE (TTO,8) @ PRINT A MESSAGE\r |
| 205 | 61 IF (STAT1.LE.0.6 .AND. STAT2.LE.0.6) GOTO 61 @ BUFF1 & BUFF2 MAY BE OVERLAYS, SO WE HAVE TO WAIT UNTIL THRUPT ABORTS\r |
| 206 | GOTO 62 @ SAMPLING TIME ALREADY TOKEN\r |
| 207 | 30 CONTINUE @ WE COME HERE IF ALL SAMPLES TOKEN, SO THE WORK IS DONE\r |
| 208 | TEMP2=INT(MAX0(0,TIME(TEMP2))+0.5)*SPEED @ COMPUTE THE TIME ELAPSED\r |
| 209 | 62 CONTINUE @ ABORT COMES HERE\r |
| 210 | TEMP3=TOASCI(MOD(TEMP2,60)) @ ASCII SECONDS\r |
| 211 | TEMP2=TEMP2/60 @ MINUTES\r |
| 212 | 40 CONTINUE\r |
| 213 | TEMP1=PARMS(2)+CSTART-1 @ TO FORM A PRETTY LIST: LAST CHANNEL WE SAMPLED --> TEMP1\r |
| 214 | C=2H & \r |
| 215 | WRITE (TTO,4) SAMCNT,TEMP2,TEMP3,(I,C,I=CSTART,TEMP1)\r |
| 216 | IF (STRIGS.EQ.0) RETURN @ NO SCHMITT TRIGGER INPUT - NO MSG\r |
| 217 | WRITE (TTO,203) (I,C,I=1,STRIGS) @ MAKE A PRETTY LIST\r |
| 218 | RETURN\r |
| 219 | 101 FORMAT (' MESSDAUER (',A2,A1,A2,')? ',$)\r |
| 220 | 102 FORMAT (I2,A1,I2)\r |
| 221 | 103 FORMAT (' MESSRATE-MAXIMAL (',I3,' HZ)? ',$)\r |
| 222 | 104 FORMAT (I3)\r |
| 223 | 105 FORMAT (' STARTKANAL (0) ? ',$)\r |
| 224 | 106 FORMAT (' ANZAHL KANAELE (',I1,') ? ',$)\r |
| 225 | 107 FORMAT (' VERVIELFACHER (',I1,') ? ',$)\r |
| 226 | 108 FORMAT (' MESSRATE KANAL',I2,' (',I3,' HZ)?',$)\r |
| 227 | 109 FORMAT (' (MESSRATE MAXIMAL)/(KANALMESS RATE) MUSS EINE ZWEIER'\r |
| 228 | 201 FORMAT (' FALSCHE EINGABE - NUR 0 BIS',I2,', ZULAESSIG.')\r |
| 229 | * ,'-POTENZ SEIN!')\r |
| 230 | 202 FORMAT (A1)\r |
| 231 | 203 FORMAT (3X,'UND VON DEN SCHMITT TRIGGER EINGAENGEN :',3(I2,A2))\r |
| 232 | 1 FORMAT (I1)\r |
| 233 | 2 FORMAT (' ANZAHL SCHMITT TRIGGER EINGAENGE? (',I1,') ',$)\r |
| 234 | 3 FORMAT (' MEHR ALS',2P,E9.1,' MESSWERTE:',E9.1,\r |
| 235 | * ' NUR NOCH FUER',I4,' MINUTEN PLATZ.'/1X,E10.2,'/',E10.2)\r |
| 236 | 4 FORMAT (I8,' PUNKTE IN',I4,':',A2,' MINUTEN VON KANAL',\r |
| 237 | * 7(I2,A2))\r |
| 238 | 5 FORMAT (' DATENSATZ',I3,' BEZEICHNUNG ? ',$)\r |
| 239 | 6 FORMAT (10A6)\r |
| 240 | 7 FORMAT (' WORT',I5,' PUFFER',I2,' MESSFREQUENZ ZU HOCH:',\r |
| 241 | * /' MESSRATE VERKLEINERN.')\r |
| 242 | 8 FORMAT (' MESSUNG ABGEBROCHEN.')\r |
| 243 | 9 FORMAT (1X)\r |
| 244 | END\r |
| 245 | \1a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 |