MK4ADC.TXT 2 SEP 1999 by Alan McCallum (almac@iconnect.net.au) MARK 4 ADC / ELECTRONICS TEST UTILITY NOTES +++++++++++++++++++++++++++++++++++++++++++ (Use F3 to search for a topic.) TOPICS +++++++++++++++++++++++++++++++++++++++++++ HISTORY WHY BASIC? OVERVIEW OUTPUT DISPLAY FITS HEADER READING BIT COUNTING CODE +++++++++++++++++++++++++++++++++++++++++++ HISTORY +++++++ On the 20th Aug 1999, Tom made a request to the list for a utility to check for stuck/open bits in MkIV camera output files. Tom requested that:- 1) The utility reads in a standard FITS image. 2) It studies it on a byte basis to check that all the 8 data lines have both high and low states. It looks for stuck bits. 3) It also studies it on a 16 bit basis to look for problems in the ADC. I had a quick go at the task using MS QuickBasic 4, and emailed the code to Tom. It was slow and _was not Windows_, but may have had some use at a pinch. With some encouragement from Tom, I decided to do a bit more work on the utility. The utility _still NOT Windows_ will now process several files from a menu, and scan user selectable rows, using random or sequential reading of rows. By changing the read method, it is now a bit faster. WHY BASIC? ++++++++++ One answer is that when the only tool you have is a hammer, everything looks like a nail. I cannot afford the constant software upgrade cycles, so I only keep up-to-date in programs that could make money for me. (ie Microsoft Office.) The program has been written in Microsoft Quick Basic Ver 4.0, (because it is there! ) and also uses some tools (menus, viewfile, picklist) from Crescent Software. (Quickpak ver. 3.1) The Crescent stuff, as old as it is, is still copyright and has been . All other Crescent functions could be replaced with standard BASIC functions and still work. Sorry about the presence of "tools", but I don't do menus any more; life is too short. The code is heavily commented and has (hopefully) meaningful variable names, so it should be easy enough to follow. Gosubs are used rather than SUBs or Functions (which of course are better and safer) BUT are also _slower_ believe it or not. There are a few gotos, but these are only used for :- local exits to redo incorrect user inputs to restart the menu code. The menu Gosub is placed last because of some nasty little MS editor syntax checking problem that only allows REDIMS in a certain order. (I think??? Perhaps it is me!) OVERVIEW ++++++++ The approach I used in this utility, is to initially set up an array of masking values where each successive base 2 power is set ON. (&H1, &H2, &H4 ... &H8000, in array BitMask() ). Then each ADC word is read as an integer, masked against the 16 BitMask() values in turn, and then recorded if the masked ADC bit is the same as the BitMask value. (A particular bit is SET.) This bit checking continues for a whole CCD row, to the value of the FITS keyword NAXIS1. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< NOTE: I _think_ the Dreaded Big-Endian problem is properly handled, but this point needs to be verified by an expert eye. When an integer is read, I have assumed I get HiByte, LoByte, and that masking in the order &H1 to &H8000 is the correct order to assign each bit a corresponding position from 0 to 15. This is assumption is critical to the correct operation of the utility. Please consider carefully! If my assumptions are incorrect, it is probably easy to swap the BitCtr1() and BitCtr2() arrays to get the correct results. I would appreciate it if someone else looked at this aspect of the code. Thanks. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Somehow the info obtained must be compactly displayed/recorded, without generating a debug file as large as the original file. I came up with a number of ways of doing this. Here are two ideas: 1) Use a sort of "rolling logical AND", by sliding a "search window" over the byte stream looking for, say, ten ADC words of not-toggled bits, recording the ADC word positions on the fly. This would be quick, but may have been difficult to analyse. 2) Scan a whole row for stuck/open bits, using the FITS value for NAXIS1 as the row length, then store two bytes for every scanned row in a log file. For display purposes, after every four words, the results are written to a temporary log file. This file will be automatically deleted unless the user requests a save. I used "1" for a bit set/ON for the entire row, "0" for a bit reset/OFF for an entire row, and "." for a bit toggled in the row. As the two result bytes for each line summarise the upper & lower bytes of each ADC word in the row, it is possible to align these output bytes in succesive lines in a log file, and thus easily see if bit 7, say, is ON in both bytes of the word. In other words just one possible check on the health of an 8 bit tri-state bus driver that is "acting up" for a few rows. The log file could be viewed on screen during program operation and then discarded or saved as required. OUTPUT DISPLAY ++++++++++++++ Here is a mock-up of the log file format. 1234U and 1234L refers to the upper & lower result bytes for CCD row 1234. Bit four is set in both bytes, for the whole of row 1234. (Possibly a driver problem.) Row# 76543210 Row# 76543210 Row# 76543210 Row# 76543210 |---------------------------------------------------------------------| File abcdefgh.123 Date Scanned 11/11/99 %ON 100 1234U ...1.... 1235U ...1.... 1236U ...1.... 1237U ...1.... 1234L ...1.... 1235L ...1.... 1236L ........ 1237L ........ 1238U ........ 1239U ........ 1240U ........ 1241U ........ 1238L ........ 1239L ......0. 1240L ......0. 1241L ......0. 1242U ......0. 1243U ........ 1244U ........ 1245U ........ 1242L ......0. 1243L ........ 1244L ........ 1245L ........ etc to 200 lines or as set by user. Next File etc |---------------------------------------------------------------------| I am assuming that bits "stick" in electronic gear for a number of cycles. Of course the hard-ON bits are the easiest to detect, (no pun intended) but intermittent latching is far harder to catch. Ditto open bits. This program can only "see" bits that are stuck for at least a whole row. However, I have also added a "feature" that may or may not have some practical use. The ability to look for a percentage of bits ON in the row. This is user settable from 10-100%. (A refinement to this, _not done_, is to have user selectable start / end columns, which then allows analysis of a single byte, a single column, a single row, or in fact any size "box" in the image file.) FITS HEADER READING +++++++++++++++++++ I had some trouble with this initially. I used some old code which was only ever used on files generated by software that put CRs in the end of the line. This makes it easy for the BASIC function GetLine() to grab lines. Without CRs at card intervals, (80 cols.) GetLine() grabs very l o o o ng lines. So I devised a new reading method of loading 2880 bytes, (36 FITS cards) into a string, then searching for each required keyword. I only did enough header reading for the purposes of this utility. BIT COUNTING CODE Extracted from source code '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CountBits: '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ LOCATE ScrnLinePosn, 7 PRINT "Mark IV ADC Bit Checker : Processing " ' Exactly one row of data to deal with. The # of ADC words ' scanned has been set by the value of NAXIS1 from the FITS ' header read for each file. ' always scan to end of line as defined by NAXIS1 FOR xcol = 1 TO NAXIS1 ' the bitmask() vals have been previously set to ' (&H1, &H2, &H4 ... &H8000, in array BitMask(0 to 15) ' get 2 bytes (as an integer) from the ADC words for ' an entire CCD row, previously loaded into array ' yFileVals%(). See GOSUB ScanRows: for the array ' loading method. ' get each int. in turn InBuf = yFileVals%(xcol) ' do bit banging for lower byte FOR j = 0 TO 7 ' mask each bit in lower byte BitBuf = InBuf AND BitMask(j) ' compare the bit result to the current bitmask IF BitBuf = BitMask(j) THEN ' the bit is the same as the mask ' and is therefore SET. ' so count the SET bit BitCtr1(j) = BitCtr1(j) + 1 END IF NEXT j ' do bit banging for upper byte FOR j = 8 TO 15 ' mask each bit in upper byte ' bitmask(8 to 15) BitBuf = InBuf AND BitMask(j) ' compare the bit result to the current bitmask IF BitBuf = BitMask(j) THEN ' the bit is the same as the mask ' so count the SET bit. ' (The upper byte o/p array is offset ' down by eight for output display ' convenience) BitCtr2(j - 8) = BitCtr2(j - 8) + 1 END IF NEXT j NEXT xcol RETURN Alan McCallum for TASS 2 Sep 1999