/elekIOcalib/licor.c

http://github.com/Yniold/liftsrc · C · 270 lines · 172 code · 33 blank · 65 comment · 23 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. //#define DEBUG_MUTEX
  45. //#define DEBUG
  46. //#define DEBUG_SETPOS
  47. #undef DEBUG
  48. #undef DEBUG_SETPOS
  49. #undef DEBUG_MUTEX
  50. #include "licor.h"
  51. #include "serial.h"
  52. #include <stdint.h>
  53. #include <pthread.h>
  54. long lLicorBaudrate = 9600;
  55. int iLicorFile;
  56. unsigned char ucLicorDeviceName[256] = "/dev/ttyS0";
  57. unsigned char ucLicorDeviceOpened = false;
  58. unsigned char aLicorRxBuffer[1024];
  59. unsigned char aLicorTxBuffer[1024];
  60. // the thread works on this structure
  61. //
  62. struct sLicorType sLicorThread =
  63. {
  64. .iFD = -1,
  65. .iCommand = -1,
  66. .LicorTemperature = 0, /* Unit: degree kelvin * 100 e.g. 20 degree celsius -> 273,15 + 20,0 => 29315 */
  67. .AmbientPressure = 0, /* Unit: kPA * 100 e.g. 1002.7 mBar => 10027 */
  68. .CO2A = 0, /* CO2 concentration cell A in mymol/mol, coding scheme T.B.D. */
  69. .CO2B = 0, /* CO2 concentration cell B in mymol/mol, coding scheme T.B.D. */
  70. .CO2D = 0, /* CO2 differential concentration in mymol/mol, coding scheme T.B.D. */
  71. .H2OA = 0, /* H2O concentration cell A in mmol/mol, coding scheme T.B.D. */
  72. .H2OB = 0, /* H2O concentration cell B in mmol/mol, coding scheme T.B.D. */
  73. .H2OD = 0 /* H2O differential concentration in mmol/mol, coding scheme T.B.D. */
  74. };
  75. pthread_mutex_t mLicorMutex;
  76. // open tty and create the thread
  77. //
  78. int LicorInit(void)
  79. {
  80. int iRetCode;
  81. pthread_t ptLicorThread;
  82. iLicorFile = serial_open((char*)ucLicorDeviceName, lLicorBaudrate); // will stop with exit()
  83. sLicorThread.iFD = iLicorFile;
  84. #ifdef DEBUG
  85. printf("In LicorInit(): FD is %d\n\r", iLicorFile);
  86. #endif
  87. iRetCode = pthread_create(&ptLicorThread, NULL, (void*)&LicorThreadFunc,(void*) &sLicorThread);
  88. if(iRetCode > 0)
  89. {
  90. printf("In LicorInit: pthread_create failed!\n\r");
  91. return (1);
  92. };
  93. return(0);
  94. };
  95. // thread code
  96. //
  97. void LicorThreadFunc(void* pArgument)
  98. {
  99. #define MAX_PARSE_BUFLEN 1024
  100. struct sLicorType *sStructure = (struct sLicorType *) pArgument;
  101. int iBytesRead;
  102. int iBytesToWrite;
  103. // used for parsing
  104. enum LicorDecodeStateEnum DecodeState = LIC_STATE_WAIT_FOR_CR;
  105. int iBytesInBuffer = 0;
  106. char cTheChar = 0;
  107. // init mutex before creating thread
  108. pthread_mutex_init(&mLicorMutex,NULL);
  109. iBytesToWrite = snprintf(aLicorTxBuffer,sizeof(aLicorTxBuffer),\
  110. "(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");
  111. write(sStructure->iFD,aLicorTxBuffer,iBytesToWrite);
  112. // thread will run endless till exit();
  113. while(true)
  114. {
  115. iBytesRead = read(sStructure->iFD, &cTheChar, 1); // read non blocking
  116. if(iBytesRead > 0)
  117. {
  118. // check if we have not seen a LINEFEED right now
  119. if(DecodeState == LIC_STATE_WAIT_FOR_CR)
  120. {
  121. if(cTheChar == '\n')
  122. {
  123. DecodeState = LIC_STATE_PARSE_LINE;
  124. aLicorRxBuffer[iBytesInBuffer] = 0;
  125. };
  126. }
  127. if(DecodeState == LIC_STATE_PARSE_LINE)
  128. {
  129. if((cTheChar == '\n') && (iBytesInBuffer > 0))
  130. {
  131. aLicorRxBuffer[iBytesInBuffer++] = cTheChar;
  132. aLicorRxBuffer[iBytesInBuffer] = 0;
  133. LicorParseLine(aLicorRxBuffer,iBytesInBuffer,(struct sLicorType*)pArgument);
  134. iBytesInBuffer = 0;
  135. }
  136. else
  137. {
  138. if(iBytesInBuffer > (MAX_PARSE_BUFLEN-1))
  139. {
  140. printf("Buffer overflow in licor parse thread\n");
  141. iBytesInBuffer = 0; // throw away string
  142. }
  143. else
  144. {
  145. aLicorRxBuffer[iBytesInBuffer++] = cTheChar;
  146. };
  147. };
  148. };
  149. };
  150. };
  151. }
  152. // parse the input line
  153. //
  154. void LicorParseLine(unsigned char* aBuffer, int iLength, struct sLicorType* sTheStructure)
  155. {
  156. #ifdef DEBUG
  157. printf("Buffer consistes of %d chars\n\r",iLength);
  158. printf("Buffer contains: %s\n\r",aBuffer);
  159. #endif
  160. char cTempChar;
  161. char aTempBuffer[256];
  162. char aTempBuffer2[256];
  163. double dFloatArg[9];
  164. #ifdef DEBUG
  165. HexDump(aBuffer,iLength);
  166. #endif
  167. if(iLength > 6)
  168. {
  169. if(strncmp("DATAD",aBuffer,5) == 0)
  170. {
  171. // Data Block detected
  172. // so parse the line and fill it into structure
  173. sscanf((char*)aBuffer, "DATAD\t%s %s %lf %lf %lf %lf %lf %lf %lf %lf %lf",
  174. &aTempBuffer,
  175. &aTempBuffer2,
  176. &dFloatArg[0],
  177. &dFloatArg[1],
  178. &dFloatArg[2],
  179. &dFloatArg[3],
  180. &dFloatArg[4],
  181. &dFloatArg[5],
  182. &dFloatArg[6],
  183. &dFloatArg[7],
  184. &dFloatArg[8]
  185. );
  186. // copy data into shared structure, so make shure the main thread
  187. // is not reading meanwhile
  188. //
  189. pthread_mutex_lock(&mLicorMutex);
  190. sTheStructure->LicorTemperature = (uint16_t)((273.15f + dFloatArg[7])*100.0f); /* Unit: degree kelvin * 100 e.g. 20 degree celsius -> 273,15 + 20,0 => 29315 */
  191. sTheStructure->AmbientPressure = (uint16_t)(100.0f * dFloatArg[6]); /* Unit: kPA * 100 e.g. 1002.7 mBar => 10027 */
  192. sTheStructure->CO2A = (int16_t) (dFloatArg[3]); /* CO2 concentration cell A in mymol/mol, coding scheme T.B.D. */
  193. sTheStructure->CO2B = (int16_t) (dFloatArg[4]); /* CO2 concentration cell B in mymol/mol, coding scheme T.B.D. */
  194. sTheStructure->CO2D = (int16_t) (dFloatArg[5]); /* CO2 differential concentration in mymol/mol, coding scheme T.B.D. */
  195. sTheStructure->H2OA = (int16_t) (1000.0f * dFloatArg[0]); /* H2O concentration cell A in mmol/mol, coding scheme T.B.D. */
  196. sTheStructure->H2OB = (int16_t) (1000.0f * dFloatArg[1]); /* H2O concentration cell B in mmol/mol, coding scheme T.B.D. */
  197. sTheStructure->H2OD = (int16_t) (1000.0f * dFloatArg[2]); /* H2O differential concentration in mmol/mol, coding scheme T.B.D. */
  198. pthread_mutex_unlock(&mLicorMutex);
  199. }
  200. if(strncmp("DATAH",aBuffer,5) == 0)
  201. {
  202. // Header Block detected
  203. //
  204. }
  205. }
  206. #ifdef DEBUG
  207. printf("String1: %s\n\r", aTempBuffer);
  208. printf("String2: %s\n\r", aTempBuffer2);
  209. int iLoopCount;
  210. for(iLoopCount=0; iLoopCount < 9; iLoopCount++)
  211. {
  212. printf("value number#%d:%05.4f\n\r",iLoopCount,dFloatArg[iLoopCount]);
  213. };
  214. #endif
  215. };
  216. void HexDump(unsigned char *aBuffer, int iBytes)
  217. {
  218. int iLoop;
  219. for(iLoop = 0; iLoop < iBytes; iLoop++)
  220. {
  221. if((iLoop % 8)== 0)
  222. {
  223. printf("0x%04x:",iLoop);
  224. printf("%02x ",aBuffer[iLoop]);
  225. }
  226. else
  227. if((iLoop % 8) == 7)
  228. {
  229. printf("%02x\n\r",aBuffer[iLoop]);
  230. }
  231. else
  232. {
  233. printf("%02x ",aBuffer[iLoop]);
  234. };
  235. };
  236. printf("\n\r");
  237. };