PageRenderTime 23ms CodeModel.GetById 8ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/elekIOcalib/licor.c

http://github.com/Yniold/liftsrc
C | 270 lines | 172 code | 33 blank | 65 comment | 22 complexity | cbf2b4eb29ffd47b1de3a15fd3afc029 MD5 | raw file
  1// ============================================
  2// licor.c
  3// Licor Control Thread
  4// ============================================
  5//
  6// $RCSfile: licor.c,v $ last changed on $Date: 2007/07/12 17:38:37 $ by $Author: rudolf $
  7//
  8// History:
  9//
 10// $Log: licor.c,v $
 11// Revision 1.10  2007/07/12 17:38:37  rudolf
 12// LICOR channels can also be negative, changed uint16 to int16
 13//
 14// Revision 1.9  2007-02-21 17:24:56  harder
 15// disabled debug output
 16//
 17// Revision 1.8  2007-02-21 17:12:13  rudolf
 18// removed test assigment
 19//
 20// Revision 1.7  2007-02-21 17:03:37  rudolf
 21// fixed using wrong pointer to struct
 22//
 23// Revision 1.6  2007-02-21 16:06:30  rudolf
 24// licor struct now read from parsing thread and copied to status struct
 25//
 26// Revision 1.5  2007-02-21 13:44:45  rudolf
 27// transfer LICOR data into inter-thread structure
 28//
 29// Revision 1.4  2007-02-21 13:17:28  rudolf
 30// more work on structure for licor
 31//
 32// Revision 1.3  2007-02-20 19:59:09  rudolf
 33// removed debug
 34//
 35// Revision 1.2  2007-02-20 13:10:05  rudolf
 36// fixed warning
 37//
 38// Revision 1.1  2007-02-12 18:32:18  rudolf
 39// added missing files for calibrator
 40//
 41//
 42//
 43//
 44
 45//#define DEBUG_MUTEX
 46//#define DEBUG
 47//#define DEBUG_SETPOS
 48
 49#undef DEBUG
 50#undef DEBUG_SETPOS
 51#undef DEBUG_MUTEX
 52
 53#include "licor.h"
 54#include "serial.h"
 55#include <stdint.h>
 56#include <pthread.h>
 57
 58long lLicorBaudrate = 9600;
 59int iLicorFile;
 60unsigned char ucLicorDeviceName[256] = "/dev/ttyS0";
 61unsigned char ucLicorDeviceOpened = false;
 62unsigned char aLicorRxBuffer[1024];
 63unsigned char aLicorTxBuffer[1024];
 64
 65// the thread works on this structure
 66//
 67struct sLicorType sLicorThread =
 68{
 69   .iFD = -1,
 70     .iCommand = -1,
 71     .LicorTemperature = 0, /* Unit: degree kelvin * 100 e.g. 20 degree celsius -> 273,15 + 20,0 => 29315 */
 72     .AmbientPressure = 0,  /* Unit: kPA * 100 e.g. 1002.7 mBar => 10027 */
 73
 74     .CO2A = 0,             /* CO2 concentration cell A in mymol/mol, coding scheme T.B.D. */
 75     .CO2B = 0,             /* CO2 concentration cell B in mymol/mol, coding scheme T.B.D. */
 76     .CO2D = 0,             /* CO2 differential concentration in mymol/mol, coding scheme T.B.D. */
 77
 78     .H2OA = 0,             /* H2O concentration cell A in mmol/mol, coding scheme T.B.D. */
 79     .H2OB = 0,             /* H2O concentration cell B in mmol/mol, coding scheme T.B.D. */
 80     .H2OD = 0              /* H2O differential concentration in mmol/mol, coding scheme T.B.D. */
 81};
 82
 83pthread_mutex_t mLicorMutex;
 84
 85// open tty and create the thread
 86//
 87int LicorInit(void)
 88{
 89   int iRetCode;
 90   pthread_t ptLicorThread;
 91   iLicorFile = serial_open((char*)ucLicorDeviceName, lLicorBaudrate); // will stop with exit()
 92   sLicorThread.iFD = iLicorFile;
 93#ifdef DEBUG
 94   printf("In LicorInit(): FD is %d\n\r", iLicorFile);
 95#endif
 96
 97   iRetCode = pthread_create(&ptLicorThread, NULL, (void*)&LicorThreadFunc,(void*) &sLicorThread);
 98   if(iRetCode > 0)
 99     {
100	printf("In LicorInit: pthread_create failed!\n\r");
101	return (1);
102     };
103
104   return(0);
105};
106
107// thread code
108//
109void LicorThreadFunc(void* pArgument)
110{
111#define MAX_PARSE_BUFLEN 1024
112   struct sLicorType *sStructure = (struct sLicorType *) pArgument;
113   int iBytesRead;
114   int iBytesToWrite;
115
116   // used for parsing
117   enum LicorDecodeStateEnum DecodeState = LIC_STATE_WAIT_FOR_CR;
118   int iBytesInBuffer = 0;
119   char cTheChar = 0;
120
121   // init mutex before creating thread
122   pthread_mutex_init(&mLicorMutex,NULL);
123
124   iBytesToWrite = snprintf(aLicorTxBuffer,sizeof(aLicorTxBuffer),\
125"(RS232 (Rate 1s)(Sources (\"H2OA mm/m\" \"H2OB mm/m\" \"H2OD mm/m\" \"CO2A um/m\" \"CO2B um/m\" \"CO2D um/m\" \"P kPa\" \"T C\" \"Diag\"))(Timestamp Long))\n");
126   write(sStructure->iFD,aLicorTxBuffer,iBytesToWrite);
127
128   // thread will run endless till exit();
129   while(true)
130     {
131	iBytesRead = read(sStructure->iFD, &cTheChar, 1); // read non blocking
132
133	if(iBytesRead > 0)
134	  {
135	     // check if we have not seen a LINEFEED right now
136	     if(DecodeState == LIC_STATE_WAIT_FOR_CR)
137	       {
138		  if(cTheChar == '\n')
139		    {
140		       DecodeState = LIC_STATE_PARSE_LINE;
141		       aLicorRxBuffer[iBytesInBuffer] = 0;
142		    };
143	       }
144
145	     if(DecodeState == LIC_STATE_PARSE_LINE)
146	       {
147		  if((cTheChar == '\n') && (iBytesInBuffer > 0))
148		    {
149		       aLicorRxBuffer[iBytesInBuffer++] = cTheChar;
150		       aLicorRxBuffer[iBytesInBuffer] = 0;
151
152		       LicorParseLine(aLicorRxBuffer,iBytesInBuffer,(struct sLicorType*)pArgument);
153
154		       iBytesInBuffer = 0;
155		    }
156		  else
157		    {
158		       if(iBytesInBuffer > (MAX_PARSE_BUFLEN-1))
159			 {
160			    printf("Buffer overflow in licor parse thread\n");
161			    iBytesInBuffer = 0; // throw away string
162			 }
163		       else
164			 {
165			    aLicorRxBuffer[iBytesInBuffer++] = cTheChar;
166			 };
167		    };
168	       };
169	  };
170     };
171}
172
173// parse the input line
174//
175void LicorParseLine(unsigned char* aBuffer, int iLength, struct sLicorType* sTheStructure)
176{
177#ifdef DEBUG
178   printf("Buffer consistes of %d chars\n\r",iLength);
179   printf("Buffer contains: %s\n\r",aBuffer);
180#endif
181   char cTempChar;
182   char aTempBuffer[256];
183   char aTempBuffer2[256];
184   double dFloatArg[9];
185
186#ifdef DEBUG
187   HexDump(aBuffer,iLength);
188#endif
189
190   if(iLength > 6)
191     {
192	if(strncmp("DATAD",aBuffer,5) == 0)
193	  {
194	     // Data Block detected
195	     // so parse the line and fill it into structure
196	     sscanf((char*)aBuffer, "DATAD\t%s %s %lf %lf %lf %lf %lf %lf %lf %lf %lf",
197		    &aTempBuffer,
198		    &aTempBuffer2,
199		    &dFloatArg[0],
200		    &dFloatArg[1],
201		    &dFloatArg[2],
202		    &dFloatArg[3],
203		    &dFloatArg[4],
204		    &dFloatArg[5],
205		    &dFloatArg[6],
206		    &dFloatArg[7],
207		    &dFloatArg[8]
208		    );
209
210	     // copy data into shared structure, so make shure the main thread
211	     // is not reading meanwhile
212	     //
213	     pthread_mutex_lock(&mLicorMutex);
214	     sTheStructure->LicorTemperature = (uint16_t)((273.15f + dFloatArg[7])*100.0f); /* Unit: degree kelvin * 100 e.g. 20 degree celsius -> 273,15 + 20,0 => 29315 */
215	     sTheStructure->AmbientPressure = (uint16_t)(100.0f * dFloatArg[6]);            /* Unit: kPA * 100 e.g. 1002.7 mBar => 10027 */
216
217	     sTheStructure->CO2A = (int16_t) (dFloatArg[3]); /* CO2 concentration cell A in mymol/mol, coding scheme T.B.D. */
218	     sTheStructure->CO2B = (int16_t) (dFloatArg[4]); /* CO2 concentration cell B in mymol/mol, coding scheme T.B.D. */
219	     sTheStructure->CO2D = (int16_t) (dFloatArg[5]); /* CO2 differential concentration in mymol/mol, coding scheme T.B.D. */
220
221	     sTheStructure->H2OA = (int16_t) (1000.0f * dFloatArg[0]); /* H2O concentration cell A in mmol/mol, coding scheme T.B.D. */
222	     sTheStructure->H2OB = (int16_t) (1000.0f * dFloatArg[1]); /* H2O concentration cell B in mmol/mol, coding scheme T.B.D. */
223	     sTheStructure->H2OD = (int16_t) (1000.0f * dFloatArg[2]); /* H2O differential concentration in mmol/mol, coding scheme T.B.D. */
224	     pthread_mutex_unlock(&mLicorMutex);
225
226	  }
227	if(strncmp("DATAH",aBuffer,5) == 0)
228	  {
229	     // Header Block detected
230	     //
231	  }
232
233     }
234
235#ifdef DEBUG
236   printf("String1: %s\n\r", aTempBuffer);
237   printf("String2: %s\n\r", aTempBuffer2);
238   int iLoopCount;
239
240   for(iLoopCount=0; iLoopCount < 9; iLoopCount++)
241     {
242	printf("value number#%d:%05.4f\n\r",iLoopCount,dFloatArg[iLoopCount]);
243     };
244#endif
245};
246
247void HexDump(unsigned char *aBuffer, int iBytes)
248{
249   int iLoop;
250   for(iLoop = 0; iLoop < iBytes; iLoop++)
251     {
252	if((iLoop % 8)== 0)
253	  {
254
255	     printf("0x%04x:",iLoop);
256	     printf("%02x ",aBuffer[iLoop]);
257	  }
258	else
259	  if((iLoop % 8) == 7)
260	    {
261
262	       printf("%02x\n\r",aBuffer[iLoop]);
263	    }
264	else
265	  {
266	     printf("%02x ",aBuffer[iLoop]);
267	  };
268     };
269   printf("\n\r");
270};