Index: trunk/psModules/src/camera/pmFPARead.c
===================================================================
--- trunk/psModules/src/camera/pmFPARead.c	(revision 18210)
+++ trunk/psModules/src/camera/pmFPARead.c	(revision 18830)
@@ -45,18 +45,40 @@
 
 // Return pointer to appropriate value for tracking scans
-static int *readoutScansByType(pmReadout *readout, // Readout of interest
-                               fpaReadType type // Type of image
+static int readoutGetThisScan(pmReadout *readout, // Readout of interest
+			      fpaReadType type // Type of image
     )
 {
     switch (type) {
       case FPA_READ_TYPE_IMAGE:
-        return &readout->imageScan;
+        return readout->thisImageScan;
       case FPA_READ_TYPE_MASK:
-        return &readout->maskScan;
+        return readout->thisMaskScan;
       case FPA_READ_TYPE_WEIGHT:
-        return &readout->weightScan;
+        return readout->thisWeightScan;
       default:
         psAbort("Unknown read type: %x\n", type);
     }
+}
+
+// Return pointer to appropriate value for tracking scans
+static int readoutSetLastScan(pmReadout *readout, // Readout of interest
+			      fpaReadType type,	  // Type of image
+			      int numScans	  // requested number of scans
+    )
+{
+    switch (type) {
+      case FPA_READ_TYPE_IMAGE:
+        readout->lastImageScan = readout->thisImageScan + numScans;
+	return readout->lastImageScan;
+      case FPA_READ_TYPE_MASK:
+        readout->lastMaskScan = readout->thisMaskScan + numScans;
+	return readout->lastMaskScan;
+      case FPA_READ_TYPE_WEIGHT:
+        readout->lastWeightScan = readout->thisWeightScan + numScans;
+	return readout->lastWeightScan;
+      default:
+        psAbort("Unknown read type: %x\n", type);
+    }
+    return false;
 }
 
@@ -134,21 +156,18 @@
 }
 
-
-// Determine readout scan properties: the next and last scans
-// Requires that cellNumReadouts() has been called before (for header and concepts to have been read)
-// In the process, adjusts the TRIMSEC
-static bool readoutScanProperties(int *next, // Index of next scan
-                                  int *last, // Index of last scan
-                                  pmReadout *readout, // Readout of interest
-                                  int numScans, // Number of scans to read at a time
-                                  fpaReadType type, // Type of image
-                                  pmConfig *config // Configuration
+// Does the current readout, with scans set for a new read, represent any real data, or is it
+// beyond the end?  Requires that cellNumReadouts() has been called before (for header and
+// concepts to have been read) In the process, adjusts the TRIMSEC
+static bool readoutHaveMoreScans(bool *result,	 // true : more data to read 
+			     pmReadout *readout, // Readout of interest
+			     int numScans, // Number of scans to read at a time
+			     fpaReadType type, // Type of image
+			     pmConfig *config // Configuration
     )
 {
-    assert(next);
-    assert(last);
+    assert(result);
     assert(readout);
 
-    psImage *image = *readoutImageByType(readout, type); // Appropriate image from readout
+    *result = false;
 
     if (!pmConceptsReadCell(readout->parent, PM_CONCEPT_SOURCE_DEFAULTS | PM_CONCEPT_SOURCE_DATABASE,
@@ -163,4 +182,5 @@
     PS_ASSERT_PTR_NON_NULL(cell, false);
     pmHDU *hdu = pmHDUFromCell(cell);   // HDU for data
+
     bool mdok = true;                   // Status of MD lookup
     psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim sections
@@ -195,11 +215,22 @@
     // Calculate the segment offset and upper limit
     if (numScans == 0) {
-        *next = (readdir == 1) ? trimsec->y0 : trimsec->x0;
-    } else {
-        *next = image ? *readoutScansByType(readout, type) + numScans : 0;
-    }
-    *last = (readdir == 1) ? trimsec->y1 : trimsec->x1;
-
+	// in the case of numScans == 0, we never call this funtion unless the data has not yet 
+	// been read.  thus, only if the delta is  should we return false (ie, trimsec defines an empty region)
+        int thisScan = (readdir == 1) ? trimsec->y0 : trimsec->x0;
+	int lastScan = (readdir == 1) ? trimsec->y1 : trimsec->x1;
+	*result = (lastScan > thisScan);
+	return true;
+    } 
+
+    // allow multiple threads to read different segments into different readouts
+    // this thread may not have read a segment yet; but others have.  trust readout->imageScan
+
+    // is the start scan of the read less than the last possible scan?
+    int thisScan = readoutGetThisScan(readout, type);
+    int lastScan = (readdir == 1) ? trimsec->y1 : trimsec->x1;
+
+    *result = (lastScan > thisScan);
     return true;
+    // XXX fold this and the above case together
 }
 
@@ -217,8 +248,13 @@
     psImage *image = *readoutImageByType(readout, type);
 
+    // XXX this may not be the valid test in a multithread environment. consider a fileGroup of
+    // N readouts, but numScans set to 0.  only the first should report that it requires data, 
+    // even if all readouts lack the image pointer.
     if (!image) {
         return true;
-    } else if (numScans == 0) {
-        // Can only read the entire image once
+    } 
+
+    // If we have already read an image, this result implies we are done (no more to read)
+    if (numScans == 0) {
         return false;
     }
@@ -235,12 +271,11 @@
     }
 
-    int next;                           // Next position
-    int last;                           // Last position
-    if (!readoutScanProperties(&next, &last, readout, numScans, type, config)) {
+    bool haveData;
+    if (!readoutHaveMoreScans(&haveData, readout, numScans, type, config)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to determine readout properties.");
         return false;
     }
 
-    return (next < last);
+    return haveData;
 }
 
@@ -423,14 +458,14 @@
     }
 
-    int next;                           // Next position
-    int last;                           // Last position
-    if (!readoutScanProperties(&next, &last, readout, numScans, type, config)) {
+    bool haveData;
+    if (!readoutHaveMoreScans (&haveData, readout, type, numScans, config)) {
         psError(PS_ERR_UNKNOWN, false, "Unable to determine readout properties.");
         return false;
     }
-    if (next >= last) {
+    if (!haveData) {
         psError(PS_ERR_IO, true, "No more of the readout to read.");
         return false;
     }
+
 
     pmHDU *hdu = pmHDUFromCell(cell);   // The HDU
@@ -459,6 +494,4 @@
     }
 
-
-
     // Check the third dimension
     int naxis = psMetadataLookupS32(&mdok, hdu->header, "NAXIS"); // The number of axes
@@ -478,11 +511,11 @@
     }
 
-    // Update number of scans read
-    int *scansTracker = readoutScansByType(readout, type); // Tracker for how many scans have been read
-    *scansTracker = next;
-    if (next == 0) {
+    // Determine the numbe of scans to read
+    int thisScan = readoutGetThisScan(readout, type);
+    int lastScan = readoutSetLastScan (readout, type, numScans);
+    if (thisScan == 0) {
         overlap = 0;
     }
-    next -= overlap;
+    thisScan -= overlap;
 
     // Calculate limits, adjust readout->row0,col0
@@ -491,5 +524,5 @@
     if (readdir == 1) {
         // Reading rows
-        readout->row0 = next;
+        readout->row0 = thisScan;
         readout->col0 = trimsec->x0;
         if (numScans == 0) {
@@ -498,5 +531,5 @@
     } else {
         // Reading cols
-        readout->col0 = next;
+        readout->col0 = thisScan;
         readout->row0 = trimsec->y0;
         if (numScans == 0) {
@@ -504,5 +537,4 @@
         }
     }
-    int upper = next + numScans + overlap;        // Upper limit to next section
 
     // Blow away existing data.
@@ -510,5 +542,5 @@
     psFree(*image);
     *image = NULL;
-    *image = readoutReadComponent(*image, fits, trimsec, readdir, next, upper, z, bad, pixelTypes[type]);
+    *image = readoutReadComponent(*image, fits, trimsec, readdir, thisScan, lastScan, z, bad, pixelTypes[type]);
 
     // Read overscans only for "image" type --- weights and masks shouldn't record overscans
@@ -528,6 +560,5 @@
         psRegion *biassec = NULL;           // Bias section from iteration
         while ((biassec = psListGetAndIncrement(biassecsIter))) {
-            psImage *bias = readoutReadComponent(NULL, fits, biassec, readdir, next, upper, z,
-                                                 bad, pixelTypes[type]); // The bias
+            psImage *bias = readoutReadComponent(NULL, fits, biassec, readdir, thisScan, lastScan, z, bad, pixelTypes[type]); // The bias
             psListAdd(readout->bias, PS_LIST_TAIL, bias);
             psFree(bias);                   // Drop reference
