Smart-Home am Beispiel der Präsenzerkennung im Raum Projektarbeit Lennart Heimbs, Johannes Krug, Sebastian Dohle und Kevin Holzschuh bei Prof. Oliver Hofmann SS2019
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MLX90640_API.cpp 31KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /**
  2. * @copyright (C) 2017 Melexis N.V.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. #include "MLX90640_I2C_Driver.h"
  18. #include "MLX90640_API.h"
  19. #include <math.h>
  20. void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  21. void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  22. void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  23. void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  24. void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  25. void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  26. void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  27. void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  28. void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  29. void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  30. void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  31. void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  32. void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
  33. int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640);
  34. int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2);
  35. int CheckEEPROMValid(uint16_t *eeData);
  36. int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData)
  37. {
  38. return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData);
  39. }
  40. int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData)
  41. {
  42. uint16_t dataReady = 1;
  43. uint16_t controlRegister1;
  44. uint16_t statusRegister;
  45. int error = 1;
  46. uint8_t cnt = 0;
  47. dataReady = 0;
  48. while(dataReady == 0)
  49. {
  50. error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
  51. if(error != 0)
  52. {
  53. return error;
  54. }
  55. dataReady = statusRegister & 0x0008;
  56. }
  57. while(dataReady != 0 && cnt < 5)
  58. {
  59. error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
  60. if(error == -1)
  61. {
  62. return error;
  63. }
  64. error = MLX90640_I2CRead(slaveAddr, 0x0400, 832, frameData);
  65. if(error != 0)
  66. {
  67. return error;
  68. }
  69. error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
  70. if(error != 0)
  71. {
  72. return error;
  73. }
  74. dataReady = statusRegister & 0x0008;
  75. cnt = cnt + 1;
  76. }
  77. if(cnt > 4)
  78. {
  79. return -8;
  80. }
  81. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  82. frameData[832] = controlRegister1;
  83. frameData[833] = statusRegister & 0x0001;
  84. if(error != 0)
  85. {
  86. return error;
  87. }
  88. return frameData[833];
  89. }
  90. int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  91. {
  92. int error = CheckEEPROMValid(eeData);
  93. if(error == 0)
  94. {
  95. ExtractVDDParameters(eeData, mlx90640);
  96. ExtractPTATParameters(eeData, mlx90640);
  97. ExtractGainParameters(eeData, mlx90640);
  98. ExtractTgcParameters(eeData, mlx90640);
  99. ExtractResolutionParameters(eeData, mlx90640);
  100. ExtractKsTaParameters(eeData, mlx90640);
  101. ExtractKsToParameters(eeData, mlx90640);
  102. ExtractAlphaParameters(eeData, mlx90640);
  103. ExtractOffsetParameters(eeData, mlx90640);
  104. ExtractKtaPixelParameters(eeData, mlx90640);
  105. ExtractKvPixelParameters(eeData, mlx90640);
  106. ExtractCPParameters(eeData, mlx90640);
  107. ExtractCILCParameters(eeData, mlx90640);
  108. error = ExtractDeviatingPixels(eeData, mlx90640);
  109. }
  110. return error;
  111. }
  112. //------------------------------------------------------------------------------
  113. int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution)
  114. {
  115. uint16_t controlRegister1;
  116. int value;
  117. int error;
  118. value = (resolution & 0x03) << 10;
  119. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  120. if(error == 0)
  121. {
  122. value = (controlRegister1 & 0xF3FF) | value;
  123. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  124. }
  125. return error;
  126. }
  127. //------------------------------------------------------------------------------
  128. int MLX90640_GetCurResolution(uint8_t slaveAddr)
  129. {
  130. uint16_t controlRegister1;
  131. int resolutionRAM;
  132. int error;
  133. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  134. if(error != 0)
  135. {
  136. return error;
  137. }
  138. resolutionRAM = (controlRegister1 & 0x0C00) >> 10;
  139. return resolutionRAM;
  140. }
  141. //------------------------------------------------------------------------------
  142. int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate)
  143. {
  144. uint16_t controlRegister1;
  145. int value;
  146. int error;
  147. value = (refreshRate & 0x07)<<7;
  148. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  149. if(error == 0)
  150. {
  151. value = (controlRegister1 & 0xFC7F) | value;
  152. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  153. }
  154. return error;
  155. }
  156. //------------------------------------------------------------------------------
  157. int MLX90640_GetRefreshRate(uint8_t slaveAddr)
  158. {
  159. uint16_t controlRegister1;
  160. int refreshRate;
  161. int error;
  162. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  163. if(error != 0)
  164. {
  165. return error;
  166. }
  167. refreshRate = (controlRegister1 & 0x0380) >> 7;
  168. return refreshRate;
  169. }
  170. //------------------------------------------------------------------------------
  171. int MLX90640_SetInterleavedMode(uint8_t slaveAddr)
  172. {
  173. uint16_t controlRegister1;
  174. int value;
  175. int error;
  176. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  177. if(error == 0)
  178. {
  179. value = (controlRegister1 & 0xEFFF);
  180. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  181. }
  182. return error;
  183. }
  184. //------------------------------------------------------------------------------
  185. int MLX90640_SetChessMode(uint8_t slaveAddr)
  186. {
  187. uint16_t controlRegister1;
  188. int value;
  189. int error;
  190. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  191. if(error == 0)
  192. {
  193. value = (controlRegister1 | 0x1000);
  194. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  195. }
  196. return error;
  197. }
  198. //------------------------------------------------------------------------------
  199. int MLX90640_GetCurMode(uint8_t slaveAddr)
  200. {
  201. uint16_t controlRegister1;
  202. int modeRAM;
  203. int error;
  204. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  205. if(error != 0)
  206. {
  207. return error;
  208. }
  209. modeRAM = (controlRegister1 & 0x1000) >> 12;
  210. return modeRAM;
  211. }
  212. //------------------------------------------------------------------------------
  213. void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result)
  214. {
  215. float vdd;
  216. float ta;
  217. float ta4;
  218. float tr4;
  219. float taTr;
  220. float gain;
  221. float irDataCP[2];
  222. float irData;
  223. float alphaCompensated;
  224. uint8_t mode;
  225. int8_t ilPattern;
  226. int8_t chessPattern;
  227. int8_t pattern;
  228. int8_t conversionPattern;
  229. float Sx;
  230. float To;
  231. float alphaCorrR[4];
  232. int8_t range;
  233. uint16_t subPage;
  234. subPage = frameData[833];
  235. vdd = MLX90640_GetVdd(frameData, params);
  236. ta = MLX90640_GetTa(frameData, params);
  237. ta4 = pow((ta + 273.15), (double)4);
  238. tr4 = pow((tr + 273.15), (double)4);
  239. taTr = tr4 - (tr4-ta4)/emissivity;
  240. alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40);
  241. alphaCorrR[1] = 1 ;
  242. alphaCorrR[2] = (1 + params->ksTo[2] * params->ct[2]);
  243. alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[3] * (params->ct[3] - params->ct[2]));
  244. //------------------------- Gain calculation -----------------------------------
  245. gain = frameData[778];
  246. if(gain > 32767)
  247. {
  248. gain = gain - 65536;
  249. }
  250. gain = params->gainEE / gain;
  251. //------------------------- To calculation -------------------------------------
  252. mode = (frameData[832] & 0x1000) >> 5;
  253. irDataCP[0] = frameData[776];
  254. irDataCP[1] = frameData[808];
  255. for( int i = 0; i < 2; i++)
  256. {
  257. if(irDataCP[i] > 32767)
  258. {
  259. irDataCP[i] = irDataCP[i] - 65536;
  260. }
  261. irDataCP[i] = irDataCP[i] * gain;
  262. }
  263. irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  264. if( mode == params->calibrationModeEE)
  265. {
  266. irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  267. }
  268. else
  269. {
  270. irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  271. }
  272. for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
  273. {
  274. ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
  275. chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
  276. conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
  277. if(mode == 0)
  278. {
  279. pattern = ilPattern;
  280. }
  281. else
  282. {
  283. pattern = chessPattern;
  284. }
  285. if(pattern == frameData[833])
  286. {
  287. irData = frameData[pixelNumber];
  288. if(irData > 32767)
  289. {
  290. irData = irData - 65536;
  291. }
  292. irData = irData * gain;
  293. irData = irData - params->offset[pixelNumber]*(1 + params->kta[pixelNumber]*(ta - 25))*(1 + params->kv[pixelNumber]*(vdd - 3.3));
  294. if(mode != params->calibrationModeEE)
  295. {
  296. irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
  297. }
  298. irData = irData / emissivity;
  299. irData = irData - params->tgc * irDataCP[subPage];
  300. alphaCompensated = (params->alpha[pixelNumber] - params->tgc * params->cpAlpha[subPage])*(1 + params->KsTa * (ta - 25));
  301. Sx = pow((double)alphaCompensated, (double)3) * (irData + alphaCompensated * taTr);
  302. Sx = sqrt(sqrt(Sx)) * params->ksTo[1];
  303. To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15;
  304. if(To < params->ct[1])
  305. {
  306. range = 0;
  307. }
  308. else if(To < params->ct[2])
  309. {
  310. range = 1;
  311. }
  312. else if(To < params->ct[3])
  313. {
  314. range = 2;
  315. }
  316. else
  317. {
  318. range = 3;
  319. }
  320. To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15;
  321. result[pixelNumber] = To;
  322. }
  323. }
  324. }
  325. //------------------------------------------------------------------------------
  326. void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result)
  327. {
  328. float vdd;
  329. float ta;
  330. float gain;
  331. float irDataCP[2];
  332. float irData;
  333. float alphaCompensated;
  334. uint8_t mode;
  335. int8_t ilPattern;
  336. int8_t chessPattern;
  337. int8_t pattern;
  338. int8_t conversionPattern;
  339. float image;
  340. uint16_t subPage;
  341. subPage = frameData[833];
  342. vdd = MLX90640_GetVdd(frameData, params);
  343. ta = MLX90640_GetTa(frameData, params);
  344. //------------------------- Gain calculation -----------------------------------
  345. gain = frameData[778];
  346. if(gain > 32767)
  347. {
  348. gain = gain - 65536;
  349. }
  350. gain = params->gainEE / gain;
  351. //------------------------- Image calculation -------------------------------------
  352. mode = (frameData[832] & 0x1000) >> 5;
  353. irDataCP[0] = frameData[776];
  354. irDataCP[1] = frameData[808];
  355. for( int i = 0; i < 2; i++)
  356. {
  357. if(irDataCP[i] > 32767)
  358. {
  359. irDataCP[i] = irDataCP[i] - 65536;
  360. }
  361. irDataCP[i] = irDataCP[i] * gain;
  362. }
  363. irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  364. if( mode == params->calibrationModeEE)
  365. {
  366. irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  367. }
  368. else
  369. {
  370. irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  371. }
  372. for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
  373. {
  374. ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
  375. chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
  376. conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
  377. if(mode == 0)
  378. {
  379. pattern = ilPattern;
  380. }
  381. else
  382. {
  383. pattern = chessPattern;
  384. }
  385. if(pattern == frameData[833])
  386. {
  387. irData = frameData[pixelNumber];
  388. if(irData > 32767)
  389. {
  390. irData = irData - 65536;
  391. }
  392. irData = irData * gain;
  393. irData = irData - params->offset[pixelNumber]*(1 + params->kta[pixelNumber]*(ta - 25))*(1 + params->kv[pixelNumber]*(vdd - 3.3));
  394. if(mode != params->calibrationModeEE)
  395. {
  396. irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
  397. }
  398. irData = irData - params->tgc * irDataCP[subPage];
  399. alphaCompensated = (params->alpha[pixelNumber] - params->tgc * params->cpAlpha[subPage])*(1 + params->KsTa * (ta - 25));
  400. image = irData/alphaCompensated;
  401. result[pixelNumber] = image;
  402. }
  403. }
  404. }
  405. //------------------------------------------------------------------------------
  406. float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params)
  407. {
  408. float vdd;
  409. float resolutionCorrection;
  410. int resolutionRAM;
  411. vdd = frameData[810];
  412. if(vdd > 32767)
  413. {
  414. vdd = vdd - 65536;
  415. }
  416. resolutionRAM = (frameData[832] & 0x0C00) >> 10;
  417. resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM);
  418. vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3;
  419. return vdd;
  420. }
  421. //------------------------------------------------------------------------------
  422. float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params)
  423. {
  424. float ptat;
  425. float ptatArt;
  426. float vdd;
  427. float ta;
  428. vdd = MLX90640_GetVdd(frameData, params);
  429. ptat = frameData[800];
  430. if(ptat > 32767)
  431. {
  432. ptat = ptat - 65536;
  433. }
  434. ptatArt = frameData[768];
  435. if(ptatArt > 32767)
  436. {
  437. ptatArt = ptatArt - 65536;
  438. }
  439. ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18);
  440. ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25);
  441. ta = ta / params->KtPTAT + 25;
  442. return ta;
  443. }
  444. //------------------------------------------------------------------------------
  445. int MLX90640_GetSubPageNumber(uint16_t *frameData)
  446. {
  447. return frameData[833];
  448. }
  449. //------------------------------------------------------------------------------
  450. void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  451. {
  452. int16_t kVdd;
  453. int16_t vdd25;
  454. kVdd = eeData[51];
  455. kVdd = (eeData[51] & 0xFF00) >> 8;
  456. if(kVdd > 127)
  457. {
  458. kVdd = kVdd - 256;
  459. }
  460. kVdd = 32 * kVdd;
  461. vdd25 = eeData[51] & 0x00FF;
  462. vdd25 = ((vdd25 - 256) << 5) - 8192;
  463. mlx90640->kVdd = kVdd;
  464. mlx90640->vdd25 = vdd25;
  465. }
  466. //------------------------------------------------------------------------------
  467. void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  468. {
  469. float KvPTAT;
  470. float KtPTAT;
  471. int16_t vPTAT25;
  472. float alphaPTAT;
  473. KvPTAT = (eeData[50] & 0xFC00) >> 10;
  474. if(KvPTAT > 31)
  475. {
  476. KvPTAT = KvPTAT - 64;
  477. }
  478. KvPTAT = KvPTAT/4096;
  479. KtPTAT = eeData[50] & 0x03FF;
  480. if(KtPTAT > 511)
  481. {
  482. KtPTAT = KtPTAT - 1024;
  483. }
  484. KtPTAT = KtPTAT/8;
  485. vPTAT25 = eeData[49];
  486. alphaPTAT = (eeData[16] & 0xF000) / pow(2, (double)14) + 8.0f;
  487. mlx90640->KvPTAT = KvPTAT;
  488. mlx90640->KtPTAT = KtPTAT;
  489. mlx90640->vPTAT25 = vPTAT25;
  490. mlx90640->alphaPTAT = alphaPTAT;
  491. }
  492. //------------------------------------------------------------------------------
  493. void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  494. {
  495. int16_t gainEE;
  496. gainEE = eeData[48];
  497. if(gainEE > 32767)
  498. {
  499. gainEE = gainEE -65536;
  500. }
  501. mlx90640->gainEE = gainEE;
  502. }
  503. //------------------------------------------------------------------------------
  504. void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  505. {
  506. float tgc;
  507. tgc = eeData[60] & 0x00FF;
  508. if(tgc > 127)
  509. {
  510. tgc = tgc - 256;
  511. }
  512. tgc = tgc / 32.0f;
  513. mlx90640->tgc = tgc;
  514. }
  515. //------------------------------------------------------------------------------
  516. void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  517. {
  518. uint8_t resolutionEE;
  519. resolutionEE = (eeData[56] & 0x3000) >> 12;
  520. mlx90640->resolutionEE = resolutionEE;
  521. }
  522. //------------------------------------------------------------------------------
  523. void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  524. {
  525. float KsTa;
  526. KsTa = (eeData[60] & 0xFF00) >> 8;
  527. if(KsTa > 127)
  528. {
  529. KsTa = KsTa -256;
  530. }
  531. KsTa = KsTa / 8192.0f;
  532. mlx90640->KsTa = KsTa;
  533. }
  534. //------------------------------------------------------------------------------
  535. void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  536. {
  537. int KsToScale;
  538. int8_t step;
  539. step = ((eeData[63] & 0x3000) >> 12) * 10;
  540. mlx90640->ct[0] = -40;
  541. mlx90640->ct[1] = 0;
  542. mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4;
  543. mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8;
  544. mlx90640->ct[2] = mlx90640->ct[2]*step;
  545. mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step;
  546. KsToScale = (eeData[63] & 0x000F) + 8;
  547. KsToScale = 1 << KsToScale;
  548. mlx90640->ksTo[0] = eeData[61] & 0x00FF;
  549. mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8;
  550. mlx90640->ksTo[2] = eeData[62] & 0x00FF;
  551. mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8;
  552. for(int i = 0; i < 4; i++)
  553. {
  554. if(mlx90640->ksTo[i] > 127)
  555. {
  556. mlx90640->ksTo[i] = mlx90640->ksTo[i] -256;
  557. }
  558. mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale;
  559. }
  560. }
  561. //------------------------------------------------------------------------------
  562. void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  563. {
  564. int accRow[24];
  565. int accColumn[32];
  566. int p = 0;
  567. int alphaRef;
  568. uint8_t alphaScale;
  569. uint8_t accRowScale;
  570. uint8_t accColumnScale;
  571. uint8_t accRemScale;
  572. accRemScale = eeData[32] & 0x000F;
  573. accColumnScale = (eeData[32] & 0x00F0) >> 4;
  574. accRowScale = (eeData[32] & 0x0F00) >> 8;
  575. alphaScale = ((eeData[32] & 0xF000) >> 12) + 30;
  576. alphaRef = eeData[33];
  577. for(int i = 0; i < 6; i++)
  578. {
  579. p = i * 4;
  580. accRow[p + 0] = (eeData[34 + i] & 0x000F);
  581. accRow[p + 1] = (eeData[34 + i] & 0x00F0) >> 4;
  582. accRow[p + 2] = (eeData[34 + i] & 0x0F00) >> 8;
  583. accRow[p + 3] = (eeData[34 + i] & 0xF000) >> 12;
  584. }
  585. for(int i = 0; i < 24; i++)
  586. {
  587. if (accRow[i] > 7)
  588. {
  589. accRow[i] = accRow[i] - 16;
  590. }
  591. }
  592. for(int i = 0; i < 8; i++)
  593. {
  594. p = i * 4;
  595. accColumn[p + 0] = (eeData[40 + i] & 0x000F);
  596. accColumn[p + 1] = (eeData[40 + i] & 0x00F0) >> 4;
  597. accColumn[p + 2] = (eeData[40 + i] & 0x0F00) >> 8;
  598. accColumn[p + 3] = (eeData[40 + i] & 0xF000) >> 12;
  599. }
  600. for(int i = 0; i < 32; i ++)
  601. {
  602. if (accColumn[i] > 7)
  603. {
  604. accColumn[i] = accColumn[i] - 16;
  605. }
  606. }
  607. for(int i = 0; i < 24; i++)
  608. {
  609. for(int j = 0; j < 32; j ++)
  610. {
  611. p = 32 * i +j;
  612. mlx90640->alpha[p] = (eeData[64 + p] & 0x03F0) >> 4;
  613. if (mlx90640->alpha[p] > 31)
  614. {
  615. mlx90640->alpha[p] = mlx90640->alpha[p] - 64;
  616. }
  617. mlx90640->alpha[p] = mlx90640->alpha[p]*(1 << accRemScale);
  618. mlx90640->alpha[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + mlx90640->alpha[p]);
  619. mlx90640->alpha[p] = mlx90640->alpha[p] / pow(2,(double)alphaScale);
  620. }
  621. }
  622. }
  623. //------------------------------------------------------------------------------
  624. void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  625. {
  626. int occRow[24];
  627. int occColumn[32];
  628. int p = 0;
  629. int16_t offsetRef;
  630. uint8_t occRowScale;
  631. uint8_t occColumnScale;
  632. uint8_t occRemScale;
  633. occRemScale = (eeData[16] & 0x000F);
  634. occColumnScale = (eeData[16] & 0x00F0) >> 4;
  635. occRowScale = (eeData[16] & 0x0F00) >> 8;
  636. offsetRef = eeData[17];
  637. if (offsetRef > 32767)
  638. {
  639. offsetRef = offsetRef - 65536;
  640. }
  641. for(int i = 0; i < 6; i++)
  642. {
  643. p = i * 4;
  644. occRow[p + 0] = (eeData[18 + i] & 0x000F);
  645. occRow[p + 1] = (eeData[18 + i] & 0x00F0) >> 4;
  646. occRow[p + 2] = (eeData[18 + i] & 0x0F00) >> 8;
  647. occRow[p + 3] = (eeData[18 + i] & 0xF000) >> 12;
  648. }
  649. for(int i = 0; i < 24; i++)
  650. {
  651. if (occRow[i] > 7)
  652. {
  653. occRow[i] = occRow[i] - 16;
  654. }
  655. }
  656. for(int i = 0; i < 8; i++)
  657. {
  658. p = i * 4;
  659. occColumn[p + 0] = (eeData[24 + i] & 0x000F);
  660. occColumn[p + 1] = (eeData[24 + i] & 0x00F0) >> 4;
  661. occColumn[p + 2] = (eeData[24 + i] & 0x0F00) >> 8;
  662. occColumn[p + 3] = (eeData[24 + i] & 0xF000) >> 12;
  663. }
  664. for(int i = 0; i < 32; i ++)
  665. {
  666. if (occColumn[i] > 7)
  667. {
  668. occColumn[i] = occColumn[i] - 16;
  669. }
  670. }
  671. for(int i = 0; i < 24; i++)
  672. {
  673. for(int j = 0; j < 32; j ++)
  674. {
  675. p = 32 * i +j;
  676. mlx90640->offset[p] = (eeData[64 + p] & 0xFC00) >> 10;
  677. if (mlx90640->offset[p] > 31)
  678. {
  679. mlx90640->offset[p] = mlx90640->offset[p] - 64;
  680. }
  681. mlx90640->offset[p] = mlx90640->offset[p]*(1 << occRemScale);
  682. mlx90640->offset[p] = (offsetRef + (occRow[i] << occRowScale) + (occColumn[j] << occColumnScale) + mlx90640->offset[p]);
  683. }
  684. }
  685. }
  686. //------------------------------------------------------------------------------
  687. void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  688. {
  689. int p = 0;
  690. int8_t KtaRC[4];
  691. int8_t KtaRoCo;
  692. int8_t KtaRoCe;
  693. int8_t KtaReCo;
  694. int8_t KtaReCe;
  695. uint8_t ktaScale1;
  696. uint8_t ktaScale2;
  697. uint8_t split;
  698. KtaRoCo = (eeData[54] & 0xFF00) >> 8;
  699. if (KtaRoCo > 127)
  700. {
  701. KtaRoCo = KtaRoCo - 256;
  702. }
  703. KtaRC[0] = KtaRoCo;
  704. KtaReCo = (eeData[54] & 0x00FF);
  705. if (KtaReCo > 127)
  706. {
  707. KtaReCo = KtaReCo - 256;
  708. }
  709. KtaRC[2] = KtaReCo;
  710. KtaRoCe = (eeData[55] & 0xFF00) >> 8;
  711. if (KtaRoCe > 127)
  712. {
  713. KtaRoCe = KtaRoCe - 256;
  714. }
  715. KtaRC[1] = KtaRoCe;
  716. KtaReCe = (eeData[55] & 0x00FF);
  717. if (KtaReCe > 127)
  718. {
  719. KtaReCe = KtaReCe - 256;
  720. }
  721. KtaRC[3] = KtaReCe;
  722. ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8;
  723. ktaScale2 = (eeData[56] & 0x000F);
  724. for(int i = 0; i < 24; i++)
  725. {
  726. for(int j = 0; j < 32; j ++)
  727. {
  728. p = 32 * i +j;
  729. split = 2*(p/32 - (p/64)*2) + p%2;
  730. mlx90640->kta[p] = (eeData[64 + p] & 0x000E) >> 1;
  731. if (mlx90640->kta[p] > 3)
  732. {
  733. mlx90640->kta[p] = mlx90640->kta[p] - 8;
  734. }
  735. mlx90640->kta[p] = mlx90640->kta[p] * (1 << ktaScale2);
  736. mlx90640->kta[p] = KtaRC[split] + mlx90640->kta[p];
  737. mlx90640->kta[p] = mlx90640->kta[p] / pow(2,(double)ktaScale1);
  738. }
  739. }
  740. }
  741. //------------------------------------------------------------------------------
  742. void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  743. {
  744. int p = 0;
  745. int8_t KvT[4];
  746. int8_t KvRoCo;
  747. int8_t KvRoCe;
  748. int8_t KvReCo;
  749. int8_t KvReCe;
  750. uint8_t kvScale;
  751. uint8_t split;
  752. KvRoCo = (eeData[52] & 0xF000) >> 12;
  753. if (KvRoCo > 7)
  754. {
  755. KvRoCo = KvRoCo - 16;
  756. }
  757. KvT[0] = KvRoCo;
  758. KvReCo = (eeData[52] & 0x0F00) >> 8;
  759. if (KvReCo > 7)
  760. {
  761. KvReCo = KvReCo - 16;
  762. }
  763. KvT[2] = KvReCo;
  764. KvRoCe = (eeData[52] & 0x00F0) >> 4;
  765. if (KvRoCe > 7)
  766. {
  767. KvRoCe = KvRoCe - 16;
  768. }
  769. KvT[1] = KvRoCe;
  770. KvReCe = (eeData[52] & 0x000F);
  771. if (KvReCe > 7)
  772. {
  773. KvReCe = KvReCe - 16;
  774. }
  775. KvT[3] = KvReCe;
  776. kvScale = (eeData[56] & 0x0F00) >> 8;
  777. for(int i = 0; i < 24; i++)
  778. {
  779. for(int j = 0; j < 32; j ++)
  780. {
  781. p = 32 * i +j;
  782. split = 2*(p/32 - (p/64)*2) + p%2;
  783. mlx90640->kv[p] = KvT[split];
  784. mlx90640->kv[p] = mlx90640->kv[p] / pow(2,(double)kvScale);
  785. }
  786. }
  787. }
  788. //------------------------------------------------------------------------------
  789. void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  790. {
  791. float alphaSP[2];
  792. int16_t offsetSP[2];
  793. float cpKv;
  794. float cpKta;
  795. uint8_t alphaScale;
  796. uint8_t ktaScale1;
  797. uint8_t kvScale;
  798. alphaScale = ((eeData[32] & 0xF000) >> 12) + 27;
  799. offsetSP[0] = (eeData[58] & 0x03FF);
  800. if (offsetSP[0] > 511)
  801. {
  802. offsetSP[0] = offsetSP[0] - 1024;
  803. }
  804. offsetSP[1] = (eeData[58] & 0xFC00) >> 10;
  805. if (offsetSP[1] > 31)
  806. {
  807. offsetSP[1] = offsetSP[1] - 64;
  808. }
  809. offsetSP[1] = offsetSP[1] + offsetSP[0];
  810. alphaSP[0] = (eeData[57] & 0x03FF);
  811. if (alphaSP[0] > 511)
  812. {
  813. alphaSP[0] = alphaSP[0] - 1024;
  814. }
  815. alphaSP[0] = alphaSP[0] / pow(2,(double)alphaScale);
  816. alphaSP[1] = (eeData[57] & 0xFC00) >> 10;
  817. if (alphaSP[1] > 31)
  818. {
  819. alphaSP[1] = alphaSP[1] - 64;
  820. }
  821. alphaSP[1] = (1 + alphaSP[1]/128) * alphaSP[0];
  822. cpKta = (eeData[59] & 0x00FF);
  823. if (cpKta > 127)
  824. {
  825. cpKta = cpKta - 256;
  826. }
  827. ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8;
  828. mlx90640->cpKta = cpKta / pow(2,(double)ktaScale1);
  829. cpKv = (eeData[59] & 0xFF00) >> 8;
  830. if (cpKv > 127)
  831. {
  832. cpKv = cpKv - 256;
  833. }
  834. kvScale = (eeData[56] & 0x0F00) >> 8;
  835. mlx90640->cpKv = cpKv / pow(2,(double)kvScale);
  836. mlx90640->cpAlpha[0] = alphaSP[0];
  837. mlx90640->cpAlpha[1] = alphaSP[1];
  838. mlx90640->cpOffset[0] = offsetSP[0];
  839. mlx90640->cpOffset[1] = offsetSP[1];
  840. }
  841. //------------------------------------------------------------------------------
  842. void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  843. {
  844. float ilChessC[3];
  845. uint8_t calibrationModeEE;
  846. calibrationModeEE = (eeData[10] & 0x0800) >> 4;
  847. calibrationModeEE = calibrationModeEE ^ 0x80;
  848. ilChessC[0] = (eeData[53] & 0x003F);
  849. if (ilChessC[0] > 31)
  850. {
  851. ilChessC[0] = ilChessC[0] - 64;
  852. }
  853. ilChessC[0] = ilChessC[0] / 16.0f;
  854. ilChessC[1] = (eeData[53] & 0x07C0) >> 6;
  855. if (ilChessC[1] > 15)
  856. {
  857. ilChessC[1] = ilChessC[1] - 32;
  858. }
  859. ilChessC[1] = ilChessC[1] / 2.0f;
  860. ilChessC[2] = (eeData[53] & 0xF800) >> 11;
  861. if (ilChessC[2] > 15)
  862. {
  863. ilChessC[2] = ilChessC[2] - 32;
  864. }
  865. ilChessC[2] = ilChessC[2] / 8.0f;
  866. mlx90640->calibrationModeEE = calibrationModeEE;
  867. mlx90640->ilChessC[0] = ilChessC[0];
  868. mlx90640->ilChessC[1] = ilChessC[1];
  869. mlx90640->ilChessC[2] = ilChessC[2];
  870. }
  871. //------------------------------------------------------------------------------
  872. int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640)
  873. {
  874. uint16_t pixCnt = 0;
  875. uint16_t brokenPixCnt = 0;
  876. uint16_t outlierPixCnt = 0;
  877. int warn = 0;
  878. int i;
  879. for(pixCnt = 0; pixCnt<5; pixCnt++)
  880. {
  881. mlx90640->brokenPixels[pixCnt] = 0xFFFF;
  882. mlx90640->outlierPixels[pixCnt] = 0xFFFF;
  883. }
  884. pixCnt = 0;
  885. while (pixCnt < 768 && brokenPixCnt < 5 && outlierPixCnt < 5)
  886. {
  887. if(eeData[pixCnt+64] == 0)
  888. {
  889. mlx90640->brokenPixels[brokenPixCnt] = pixCnt;
  890. brokenPixCnt = brokenPixCnt + 1;
  891. }
  892. else if((eeData[pixCnt+64] & 0x0001) != 0)
  893. {
  894. mlx90640->outlierPixels[outlierPixCnt] = pixCnt;
  895. outlierPixCnt = outlierPixCnt + 1;
  896. }
  897. pixCnt = pixCnt + 1;
  898. }
  899. if(brokenPixCnt > 4)
  900. {
  901. warn = -3;
  902. }
  903. else if(outlierPixCnt > 4)
  904. {
  905. warn = -4;
  906. }
  907. else if((brokenPixCnt + outlierPixCnt) > 4)
  908. {
  909. warn = -5;
  910. }
  911. else
  912. {
  913. for(pixCnt=0; pixCnt<brokenPixCnt; pixCnt++)
  914. {
  915. for(i=pixCnt+1; i<brokenPixCnt; i++)
  916. {
  917. warn = CheckAdjacentPixels(mlx90640->brokenPixels[pixCnt],mlx90640->brokenPixels[i]);
  918. if(warn != 0)
  919. {
  920. return warn;
  921. }
  922. }
  923. }
  924. for(pixCnt=0; pixCnt<outlierPixCnt; pixCnt++)
  925. {
  926. for(i=pixCnt+1; i<outlierPixCnt; i++)
  927. {
  928. warn = CheckAdjacentPixels(mlx90640->outlierPixels[pixCnt],mlx90640->outlierPixels[i]);
  929. if(warn != 0)
  930. {
  931. return warn;
  932. }
  933. }
  934. }
  935. for(pixCnt=0; pixCnt<brokenPixCnt; pixCnt++)
  936. {
  937. for(i=0; i<outlierPixCnt; i++)
  938. {
  939. warn = CheckAdjacentPixels(mlx90640->brokenPixels[pixCnt],mlx90640->outlierPixels[i]);
  940. if(warn != 0)
  941. {
  942. return warn;
  943. }
  944. }
  945. }
  946. }
  947. return warn;
  948. }
  949. //------------------------------------------------------------------------------
  950. int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2)
  951. {
  952. int pixPosDif;
  953. pixPosDif = pix1 - pix2;
  954. if(pixPosDif > -34 && pixPosDif < -30)
  955. {
  956. return -6;
  957. }
  958. if(pixPosDif > -2 && pixPosDif < 2)
  959. {
  960. return -6;
  961. }
  962. if(pixPosDif > 30 && pixPosDif < 34)
  963. {
  964. return -6;
  965. }
  966. return 0;
  967. }
  968. //------------------------------------------------------------------------------
  969. int CheckEEPROMValid(uint16_t *eeData)
  970. {
  971. int deviceSelect;
  972. deviceSelect = eeData[10] & 0x0040;
  973. if(deviceSelect == 0)
  974. {
  975. return 0;
  976. }
  977. return -7;
  978. }