Пример #1
0
void ProcessRunner::updateError()
{
  QByteArray data = process->readAllStandardError();
  QString errorOutput(data);
  output += errorOutput;
  if(context)
    context->error(toString(errorOutput));
}
Пример #2
0
int fitsCheck(char *keyword, char *value)
{
   char  *end;
   int    ival;
   double dval;

   char   msg[1024];

   if(CHdebug)
   {
      printf("fitsCheck() [%s] = [%s]\n", keyword, value);
      fflush(stdout);
   }

   if(strcmp(keyword, "SIMPLE") == 0)
   {
      haveSIMPLE = 1;

      if(strcmp(value, "T") != 0
      && strcmp(value, "F") != 0)
         errorOutput("SIMPLE keyword must be T or F");
   }

   else if(strcmp(keyword, "BITPIX") == 0)
   {
      haveBITPIX = 1;

      ival = strtol(value, &end, 0);

      if(end < value + (int)strlen(value))
         errorOutput("BITPIX keyword in FITS header not an integer");

      if(ival != 8
      && ival != 16
      && ival != 32
      && ival != 64
      && ival != -32
      && ival != -64)
         errorOutput("Invalid BITPIX in FITS header (must be 8,16,32,64,-32 or -64)");
   }

   else if(strcmp(keyword, "NAXIS") == 0)
   {
      haveNAXIS = 1;

      ival = strtol(value, &end, 0);

      if(end < value + (int)strlen(value))
         errorOutput("NAXIS keyword in FITS header not an integer");

      if(ival < 2)
         errorOutput("NAXIS keyword in FITS header must be >= 2");
   }

   else if(strcmp(keyword, "NAXIS1") == 0)
   {
      haveNAXIS1 = 1;

      ival = strtol(value, &end, 0);

      if(end < value + (int)strlen(value))
         errorOutput("NAXIS1 keyword in FITS header not an integer");

      if(ival < 0)
         errorOutput("NAXIS1 keyword in FITS header must be > 0");
   }

   else if(strcmp(keyword, "NAXIS2") == 0)
   {
      haveNAXIS2 = 1;

      ival = strtol(value, &end, 0);

      if(end < value + (int)strlen(value))
         errorOutput("NAXIS2 keyword in FITS header not an integer");

      if(ival < 0)
         errorOutput("NAXIS2 keyword in FITS header must be > 0");
   }

   else if(strcmp(keyword, "PLTRAH") == 0)
      havePLTRAH = 1;

   else if(strcmp(keyword, "CTYPE1") == 0)
   {
      haveCTYPE1 = 1;
      strcpy(ctype1, value);
   }

   else if(strcmp(keyword, "CTYPE2") == 0)
   {
      haveCTYPE2 = 1;
      strcpy(ctype2, value);
   }

   else if(strcmp(keyword, "CRPIX1") == 0)
   {
      haveCRPIX1 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CRPIX1 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CRPIX2") == 0)
   {
      haveCRPIX2 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CRPIX2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CRVAL1") == 0)
   {
      haveCRVAL1 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CRVAL1 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CRVAL2") == 0)
   {
      haveCRVAL2 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CRVAL2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CDELT1") == 0)
   {
      haveCDELT1 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CDELT1 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CDELT2") == 0)
   {
      haveCDELT2 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CDELT2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CROTA2") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CROTA2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CD1_1") == 0)
   {
      haveCD1_1 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CD1_1 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CD1_2") == 0)
   {
      haveCD1_2 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CD1_2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CD2_1") == 0)
   {
      haveCD2_1 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CD1_2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "CD2_2") == 0)
   {
      haveCD2_2 = 1;

      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("CD2_2 keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "BSCALE") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("BSCALE keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "BZERO") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("BZERO keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "BLANK") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("BLANK keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "EPOCH") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
         errorOutput("EPOCH keyword in FITS header not a real number");
   }

   else if(strcmp(keyword, "EQUINOX") == 0)
   {
      dval = strtod(value, &end);

      if(end < value + (int)strlen(value))
      {
         if(dval < 1900. || dval > 2050.)
            errorOutput("EQUINOX keyword in FITS header not a real number");
      }
   }
   
   return 0;
}
Пример #3
0
int checkHdr(char *infile, int hdrflag, int hdu)
{
   int       i, len, ncard, morekeys;

   int       status = 0;

   char     *keyword;
   char     *value;

   char      fitskeyword[80];
   char      fitsvalue  [80];
   char      fitscomment[80];
   char      tmpstr     [80];

   char     *end;

   char      line  [1024];
   char      pline [1024];

   char     *ptr1;
   char     *ptr2;

   FILE     *fp;
   fitsfile *infptr;

   static int maxhdr;

   if(!mHeader)
   {
      mHeader = malloc(MAXHDR);
      maxhdr = MAXHDR;
   }

   havePLTRAH  = 0;

   haveSIMPLE  = 0;
   haveBITPIX  = 0;
   haveNAXIS   = 0;
   haveNAXIS1  = 0;
   haveNAXIS2  = 0;
   haveCTYPE1  = 0;
   haveCTYPE2  = 0;
   haveCRPIX1  = 0;
   haveCRPIX2  = 0;
   haveCDELT1  = 0;
   haveCDELT2  = 0;
   haveCD1_1   = 0;
   haveCD1_2   = 0;
   haveCD2_1   = 0;
   haveCD2_2   = 0;
   haveCRVAL1  = 0;
   haveCRVAL2  = 0;
   haveBSCALE  = 0;
   haveBZERO   = 0;
   haveBLANK   = 0;
   haveEPOCH   = 0;
   haveEQUINOX = 0;


   /****************************************/
   /* Initialize the WCS transform library */
   /* and find the pixel location of the   */
   /* sky coordinate specified             */
   /****************************************/

   errorCount = 0;

   if(hdrCheck_outfile)
   {
      fout = fopen(hdrCheck_outfile, "w+");

      if(fout == (FILE *)NULL)
      {
         fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"Cannot open output file %s.\"]\n", hdrCheck_outfile);
         fflush(fstatus);
         exit(1);
      }
   }

   strcpy(mHeader, "");

   if(fits_open_file(&infptr, infile, READONLY, &status) == 0)
   {
      if(CHdebug)
      {
         printf("\nFITS file\n");
         fflush(stdout);
      }

      if(hdrflag == HDR)
      {
       fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"FITS file (%s) cannot be used as a header template\"]\n",
                infile);
         fflush(fstatus);
         exit(1);
      }

      if(hdu > 0)
      {
         if(fits_movabs_hdu(infptr, hdu+1, NULL, &status))
            FITSerror(status);
      }

      if(fits_get_hdrspace (infptr, &ncard, &morekeys, &status))
         FITSerror(status);
      
      if(ncard > 1000)
         mHeader = realloc(mHeader, ncard * 80 + 1024);

      if(CHdebug)
      {
         printf("ncard = %d\n", ncard);
         fflush(stdout);
      }

      for (i=1; i<=ncard; i++)
      {
         if(fits_read_keyn (infptr, i, fitskeyword, fitsvalue, fitscomment, &status))
            FITSerror(status);

         if(fitsvalue[0] == '\'')
         {
            strcpy(tmpstr, fitsvalue+1);

            if(tmpstr[strlen(tmpstr)-1] == '\'')
               tmpstr[strlen(tmpstr)-1] =  '\0';
         }
         else
            strcpy(tmpstr, fitsvalue);

         fitsCheck(fitskeyword, tmpstr);

         sprintf(line, "%-8s= %20s", fitskeyword, fitsvalue);

         if(strncmp(line, "COMMENT", 7) != 0)
            strAdd(mHeader, line);
      }

      strAdd(mHeader, "END");

      if(fits_close_file(infptr, &status))
         FITSerror(status);
   }
   else
   {
      if(CHdebug)
      {
         printf("\nTemplate file\n");
         fflush(stdout);
      }

      if(hdrflag == FITS)
      {
         fp = fopen(infile, "r");

         if(fp == (FILE *)NULL)
         {
            fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File %s not found.\"]\n", infile);
            fflush(fstatus);
            exit(1);
         }

         fclose(fp);

         fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File (%s) is not a FITS image\"]\n",
                infile);
         fflush(fstatus);
         exit(1);
      }

      fp = fopen(infile, "r");

      if(fp == (FILE *)NULL)
      {
         fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"File %s not found.\"]\n", infile);
         fflush(fstatus);
         exit(1);
      }

      while(1)
      {
         if(fgets(line, 1024, fp) == (char *)NULL)
            break;

         if(line[(int)strlen(line)-1] == '\n')
            line[(int)strlen(line)-1]  = '\0';
         
         if(line[(int)strlen(line)-1] == '\r')
            line[(int)strlen(line)-1]  = '\0';
         
         strcpy(pline, line);

         if((int)strlen(line) > 80)
         {
            fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"FITS header lines cannot be greater than 80 characters.\"]\n");
            fflush(fstatus);
            exit(1);
         }

         len = (int)strlen(pline);

         keyword = pline;

         while(*keyword == ' ' && keyword < pline+len)
            ++keyword;

         end = keyword;

         while(*end != ' ' && *end != '=' && end < pline+len)
            ++end;

         value = end;

         while((*value == '=' || *value == ' ' || *value == '\'')
               && value < pline+len)
            ++value;

         *end = '\0';
         end = value;

         if(*end == '\'')
            ++end;

         while(*end != ' ' && *end != '\'' && end < pline+len)
            ++end;

         *end = '\0';

         fitsCheck(keyword, value);

         strAdd(mHeader, line);
         
         if((int)strlen(mHeader) + 160 > maxhdr)
         {
            maxhdr += MAXHDR;
            mHeader = realloc(mHeader, maxhdr);
         }
      }

      fclose(fp);
   }


   /********************************************************/
   /*                                                      */
   /* Check to see if we have the minimum FITS header info */
   /*                                                      */
   /********************************************************/

   if(!haveBITPIX)
      errorOutput("No BITPIX keyword in FITS header");

   if(!haveNAXIS)
      errorOutput("No NAXIS keyword in FITS header");

   if(!haveNAXIS1)
      errorOutput("No NAXIS1 keyword in FITS header");

   if(!haveNAXIS2)
      errorOutput("No NAXIS2 keyword in FITS header");

   if(havePLTRAH)
   {
      /* If we have this parameter, we'll assume this is a DSS header  */
      /* the WCS checking routine should be able to verify if it isn't */

      free(mHeader);

      maxhdr = 0;
      
      mHeader = (char *)NULL;

      return(0);
   }

   if(!haveCTYPE1)
      errorOutput("No CTYPE1 keyword in FITS header");

   if(!haveCTYPE2)
      errorOutput("No CTYPE2 keyword in FITS header");

   if(!haveCRPIX1)
      errorOutput("No CRPIX1 keyword in FITS header");

   if(!haveCRPIX2)
      errorOutput("No CRPIX2 keyword in FITS header");

   if(!haveCRVAL1)
      errorOutput("No CRVAL1 keyword in FITS header");

   if(!haveCRVAL2)
      errorOutput("No CRVAL2 keyword in FITS header");

   if(!haveCD1_1 
   && !haveCD1_2 
   && !haveCD2_1 
   && !haveCD2_2)
   {
      if(!haveCDELT1)
         errorOutput("No CDELT1 keyword (or incomplete CD matrix) in FITS header");
      else if(!haveCDELT2)
         errorOutput("No CDELT2 keyword (or incomplete CD matrix) in FITS header");
   }

   if(strlen(ctype1) < 8)
      errorOutput("CTYPE1 must be at least 8 characters");

   if(strlen(ctype2) < 8)
      errorOutput("CTYPE2 must be at least 8 characters");

   ptr1 = ctype1;

   while(*ptr1 != '-' && *ptr1 != '\0') ++ptr1;
   while(*ptr1 == '-' && *ptr1 != '\0') ++ptr1;

   ptr2 = ctype2;

   while(*ptr2 != '-' && *ptr2 != '\0') ++ptr2;
   while(*ptr2 == '-' && *ptr2 != '\0') ++ptr2;

   if(strlen(ptr1) == 0
   || strlen(ptr2) == 0)
      errorOutput("Invalid CTYPE1 or CTYPE2 projection information");

   if(strcmp(ptr1, ptr2) != 0)
      errorOutput("CTYPE1, CTYPE2 projection information mismatch");

   if(hdrStringent)
   {
      if(strlen(ptr1) != 3)
         errorOutput("Invalid CTYPE1 projection information");

      if(strlen(ptr2) != 3)
         errorOutput("Invalid CTYPE2 projection information");
   }


   /****************************************/
   /* Initialize the WCS transform library */
   /* and find the pixel location of the   */
   /* sky coordinate specified             */
   /****************************************/

   /*
   if(CHdebug)
   {
      printf("header = \n%s\n", mHeader);
      fflush(stdout);
   }
   */

   hdrCheck_wcs = wcsinit(mHeader);

   checkWCS(hdrCheck_wcs, 0);

   if(errorCount > 0)
   {
      fprintf(fstatus, "[struct stat=\"ERROR\", msg=\"%d Errors\"]\n", 
         errorCount);
      fflush(fstatus);
      exit(1);
   }

   return(0);
}
Пример #4
0
T* StreamlineTexture<T>::fastLIC(const Flow2D& flow, const SimpleTexture<float>& inputTexture,
                                 const size_t textureScaling, const size_t sampling,
                                 const int maxKernelSize, const tgt::vec2& thresholds,
                                 const bool useAdaptiveKernelSize)
{
    const tgt::ivec2 inputTexSize(inputTexture.getDimensions().xy());
    if (flow.dimensions_ != inputTexSize)
        return 0;

    StreamlineTexture<T> outputTexture(inputTexSize * static_cast<int>(textureScaling));
    const tgt::ivec2& outputTexSize = outputTexture.getDimensions().xy();
    const int delta = static_cast<int>(sampling);
    const float stepSize = (0.5f / textureScaling);
    const float length = static_cast<float>(tgt::max(flow.dimensions_)) * 1.10f;

    size_t numStreamlines = 0;
    for (int y = 0; y < outputTexSize.y; y += delta) {
        for (int x = 0; x < outputTexSize.x; x += delta) {
            tgt::ivec2 ir0(x, y);
            if (outputTexture[ir0].counter_ > 0)
                continue;

            // get the coordinates of the pixel in the input texture which corresponds
            // to this position in the output texture and calculate its position within
            // the flow.
            //
            tgt::ivec2 r0Input(ir0 / static_cast<int>(textureScaling));
            tgt::ivec2 errorInput(0, 0);
            tgt::vec2 r0 = flow.slicePosToFlowPos(r0Input, inputTexSize, &errorInput);
            const tgt::vec2 v = flow.lookupFlow(r0);

            if (v == tgt::vec2::zero)
                continue;

            // start streamline computation
            //
            int indexR0 = 0;
            std::deque<tgt::vec2> streamlineD =
                FlowMath::computeStreamlineRungeKutta(flow, r0, length, stepSize, &indexR0, thresholds);
            if (streamlineD.size() <= 1)
                continue;

            // also determine the round-off error which occurs if the flow positions was
            // converted back directly to the coordinates of the output textures.
            //
            tgt::ivec2 errorOutput(0, 0);
            flow.slicePosToFlowPos(ir0, outputTexSize, &errorOutput);

            ++numStreamlines;
            std::vector<tgt::vec2> streamline = FlowMath::dequeToVector(streamlineD);

            // copy the streamline for second coordinate conversion
            //
            std::vector<tgt::vec2> streamlineCopy(streamline);

            // convert the streamline into dimensions of the input texture
            //
            std::vector<tgt::ivec2> streamlineInput =
                flow.flowPosToSlicePos(streamline, inputTexSize, errorInput);

            // also convert the streamline into dimensions of the output texture
            //
            std::vector<tgt::ivec2> streamlineOutput =
                flow.flowPosToSlicePos(streamlineCopy, outputTexSize, errorOutput);

            // calculate initial intensity for the starting pixel
            //
            int L = maxKernelSize;
            if (useAdaptiveKernelSize == true)
                L = static_cast<int>(tgt::round(maxKernelSize * (tgt::length(v) / thresholds.y)));
            const float k = 1.0f / (((2 * L) + 1));
            float intensity0 = k * fastLICIntensity(inputTexture, indexR0, L, streamlineInput);

            // determine the affected pixel in the output texture and add the
            // initial intensity
            //
            tgt::ivec2& outputTexCoord = streamlineOutput[indexR0];
            outputTexture[outputTexCoord].elem_ += T(intensity0);
            ++(outputTexture[outputTexCoord].counter_);

            // trace streamline in forward direction and update intensity
            //
            float intensity = intensity0;
            int left = indexR0 + L + 1;
            int right = indexR0 - L;
            const int numPoints = static_cast<int>(streamlineInput.size());

            for (int i = (indexR0 + 1); i < numPoints; ++i, ++left, ++right) {
                int l = (left >= numPoints) ? (numPoints - 1) : left;
                int r = (right <= 0) ? 0 : right;

                intensity += (inputTexture[streamlineInput[l]] - inputTexture[streamlineInput[r]]) * k;

                outputTexCoord = streamlineOutput[i];
                outputTexture[outputTexCoord].elem_ += T(intensity);
                ++(outputTexture[outputTexCoord].counter_);
            }   // for (i

            // trace streamline in backward direction and update intensity
            //
            intensity = intensity0;
            left = indexR0 - L - 1;
            right = indexR0 + L;
            for (int i = (indexR0 - 1); i >= 0; --i, --left, --right) {
                int l = (left <= 0) ? 0 : left;
                int r = (right >= numPoints) ? (numPoints - 1) : right;

                intensity += (inputTexture[streamlineInput[l]] - inputTexture[streamlineInput[r]]) * k;

                outputTexCoord = streamlineOutput[i];
                outputTexture[outputTexCoord].elem_ += T(intensity);
                ++(outputTexture[outputTexCoord].counter_);
            }   // for (i
        }   // for (x
    }   // for (y

    size_t unhitPixels = 0;
    const size_t numPixels = outputTexture.getNumElements();
    for (size_t i = 0; i < numPixels; ++i) {
        if (outputTexture[i].counter_ > 1)
            outputTexture[i].elem_ /= static_cast<unsigned char>(outputTexture[i].counter_);
        else
            if (outputTexture[i].counter_ <= 0)
                ++unhitPixels;
    }
    std::cout << "# streamlines = " << numStreamlines << ", # unhit pixels = " << unhitPixels
        << " (" << static_cast<float>(100 * unhitPixels) / static_cast<float>(numPixels) << " %)\n";

    T* result = new T[numPixels];
    memcpy(result, outputTexture.getData(), sizeof(T) * numPixels);
    return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
	//Initialize stucts and stuff
	DCB dcbUSB = { 0 }; //for USB COM port configuration
	DCB dcbBT = { 0 }; //for Bluetooth COM port configuration
	dcbUSB.DCBlength = sizeof(DCB);
	dcbBT.DCBlength = sizeof(DCB);
	


	//Initialize events
	USBIncoming.hEvent = CreateEvent(0, true, 0, 0);
	if (USBIncoming.hEvent == NULL) {
		errorOutput();
		return 1;
	}

	BTIncoming.hEvent = CreateEvent(0, true, 0, 0);
	if (BTIncoming.hEvent == NULL) {
		errorOutput();
		return 1;
	}

	USBOutgoing.hEvent = CreateEvent(0, true, 0, 0);
	if (USBOutgoing.hEvent == NULL) {
		errorOutput();
		return 1;
	}

	BTOutgoing.hEvent = CreateEvent(0, true, 0, 0);
	if (BTOutgoing.hEvent == NULL) {
		errorOutput();
		return 1;
	}

	for (int i = 0; i < 2; i++) {
		processingReady[i] = CreateEvent(0, true, 0, 0);
		if (processingReady[i] == NULL) {
			errorOutput();
			return 1;
		}
	}

	//Initialize COM ports
	comPortUSB = CreateFile("COM4", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
	if (comPortUSB == INVALID_HANDLE_VALUE) {
		errorOutput();
		return 1;
	}

	comPortBT = CreateFile("COM5", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
	if (comPortBT == INVALID_HANDLE_VALUE) {
		errorOutput();
		return 1;
	}

	//Setup COM ports
	if (!GetCommState(comPortUSB, &dcbUSB)) {
		errorOutput();
		return 1;
	}
	dcbUSB.BaudRate = CBR_9600; //normall 1200
	dcbUSB.fParity = false; //normally false
	dcbUSB.Parity = NOPARITY; //normally no parity
	dcbUSB.StopBits = ONESTOPBIT; //normally no stop bits
	dcbUSB.fRtsControl = RTS_CONTROL_DISABLE; //normally 1
	dcbUSB.fDtrControl = false; //normally 1
	dcbUSB.ByteSize = 8; //normally 7

	if (!SetCommState(comPortUSB, &dcbUSB)) {
		errorOutput();
		return 1;
	}
	if (!SetCommState(comPortBT, &dcbUSB)) {
		errorOutput();
		return 1;
	}

	//Set timeouts
	COMMTIMEOUTS timeouts;
	timeouts.ReadIntervalTimeout = MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier = 0;
	timeouts.ReadTotalTimeoutConstant = 0;
	timeouts.WriteTotalTimeoutMultiplier = 0;
	timeouts.WriteTotalTimeoutConstant = 0;

	if (!SetCommTimeouts(comPortUSB, &timeouts)) {
		errorOutput();
		return 1;
	}

	if (!SetCommTimeouts(comPortBT, &timeouts)) {
		errorOutput();
		return 1;
	}



	//Set masks
	DWORD mask = 0;
	BOOL retVal = false;
	if (!SetCommMask(comPortUSB, /*EV_TXEMPTY |*/ EV_RXCHAR)) {
		errorOutput();
		return 1;
	}

	retVal = WaitCommEvent(comPortUSB, &mask, &USBIncoming);
	if (retVal == 0 && GetLastError() != ERROR_IO_PENDING){
		errorOutput();
		return 1;
	}

	if (!SetCommMask(comPortBT, /*EV_TXEMPTY |*/ EV_RXCHAR)) {
		errorOutput();
		return 1;
	}

	retVal = WaitCommEvent(comPortBT, &mask, &BTIncoming);
	if (retVal == 0 && GetLastError() != ERROR_IO_PENDING){
		errorOutput();
		return 1;
	}

	printf("Starting threads...\n");

	//create threads
	comPort port[2];
	for (int i = 0; i < 2; i++) {
		port[i] = (comPort)i; //cheap way of creating different threads for different coms
		threads[i] = CreateThread(NULL, 0, ThreadProc, &port[i], 0, NULL);
	}

	//Spawn threads to wait
	while (true) {
		//Wait for a thread to process incoming data, then process it, then spawn a new thread and clear the appropriate buffer

		
		
		/////////////Goals for this section: spawn threads, wait until one terminates, process the data, then respawn the terminated thread.

		if (WaitForSingleObject(processingReady[0], 2) == WAIT_OBJECT_0) {
			ResetEvent(processingReady[0]);
			if (bufferUSB[0] == '|') {
				printf(bufferUSB);
				WriteFile(comPortBT, bufferUSB, strlen(bufferUSB), NULL, &BTOutgoing);
			}
			else if (bufferUSB[0] == '!') {
				printf(bufferUSB);
			}

			memset(bufferUSB, '\0', sizeof(bufferUSB));

			retVal = WaitCommEvent(comPortUSB, &mask, &USBIncoming);
			if (retVal == 0 && GetLastError() != ERROR_IO_PENDING){
				errorOutput();
				return 1;
			}

			comPort port = usb;
			threads[0] = CreateThread(NULL, 0, ThreadProc, &port, 0, NULL);
		}

		if (WaitForSingleObject(processingReady[1], 2) == WAIT_OBJECT_0) {
			ResetEvent(processingReady[1]);
			if (bufferBT[0] == '|') {
				printf(bufferBT);
				WriteFile(comPortUSB, bufferBT, strlen(bufferBT), NULL, &USBOutgoing);
			}
			else if (bufferBT[0] == '!') {
				printf(bufferBT);
			}

			memset(bufferBT, '\0', sizeof(bufferBT));

			retVal = WaitCommEvent(comPortBT, &mask, &BTIncoming);
			if (retVal == 0 && GetLastError() != ERROR_IO_PENDING){
				errorOutput();
				return 1;
			}

			comPort port = bt;
			threads[1] = CreateThread(NULL, 0, ThreadProc, &port, 0, NULL);
		}

		if (WaitForSingleObject(USBOutgoing.hEvent, 2) == WAIT_OBJECT_0) {
			ResetEvent(USBOutgoing.hEvent);
		}

		if (WaitForSingleObject(BTOutgoing.hEvent, 2) == WAIT_OBJECT_0) {
			ResetEvent(BTOutgoing.hEvent);
		}
	}

	

	CloseHandle(USBIncoming.hEvent);
	CloseHandle(BTIncoming.hEvent);
	CloseHandle(USBOutgoing.hEvent);
	CloseHandle(BTOutgoing.hEvent);
	for (int i = 0; i < 2; i++)	CloseHandle(processingReady[i]);

	//Threads will exit on their own

	system("pause");
	return 0;
}
DWORD WINAPI ThreadProc(LPVOID parameter) {
	comPort *typeTemp = (comPort *) parameter; //convert parameter into the right type
	comPort type = *typeTemp;

	DWORD waitResult;
	HANDLE *theEvent;
	HANDLE *port;
	HANDLE *processing;
	OVERLAPPED *overlap;
	char *buffer;

	//Setup variables
	if (type == usb) {
		theEvent = &USBIncoming.hEvent;
		port = &comPortUSB;
		overlap = &USBIncoming;
		buffer = bufferUSB;
		processing = &processingReady[0];
	}
	else {
		theEvent = &BTIncoming.hEvent;
		port = &comPortBT;
		overlap = &BTIncoming;
		buffer = bufferBT;
		processing = &processingReady[1];
	}


	//Stop the thread until a character has entered the buffer
		waitResult = WaitForSingleObject(*theEvent, INFINITE);

	if (waitResult == WAIT_OBJECT_0) {
		DWORD bytesRead = 0;
		char delim = '\0';
		unsigned int counter = 0;
		char internalBuffer[BUFFER_SIZE] = { '\0' };

		do {
			ReadFile(*port, internalBuffer, 1, NULL, overlap);
			GetOverlappedResult(*port, overlap, &bytesRead, true);
			if (internalBuffer[0] == '|') {
				delim = '|';
				break;
			}
			else if (internalBuffer[0] == '!') {
				delim = '\n';
				break;
			}
		} while (true);


		//Reads in the data from the port... I feel like there's going to be a problem here if there's multiple reads, or the ReadFile returns false due to asychronous processing. Also, message grouping... this needs to gather an entire message field
		do {
			counter++;
			ReadFile(*port, internalBuffer + counter, 1, NULL, overlap);
			GetOverlappedResult(*port, overlap, &bytesRead, true);
			if (bytesRead == 0) {
				counter--;
			}

		} while (counter < sizeof(internalBuffer) && (counter == 0 || internalBuffer[counter] != delim));

		memcpy_s(buffer, BUFFER_SIZE, internalBuffer, BUFFER_SIZE); //copy contents of internal buffer back to global buffer

		SetEvent(*processing);
		ResetEvent(*theEvent);
	}
	else {
		errorOutput();
		return 1;
	}

	return 0;
}