MLX90640_API.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572
  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. float GetMedian(float *values, int n);
  36. int IsPixelBad(uint16_t pixel,paramsMLX90640 *params);
  37. int ValidateFrameData(uint16_t *frameData);
  38. int ValidateAuxData(uint16_t *auxData);
  39. int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData)
  40. {
  41. return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData);
  42. }
  43. int MLX90640_SynchFrame(uint8_t slaveAddr)
  44. {
  45. uint16_t dataReady = 0;
  46. uint16_t statusRegister;
  47. int error = 1;
  48. error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
  49. if(error == -1)
  50. {
  51. return error;
  52. }
  53. while(dataReady == 0)
  54. {
  55. error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
  56. if(error != 0)
  57. {
  58. return error;
  59. }
  60. dataReady = statusRegister & 0x0008;
  61. }
  62. return 0;
  63. }
  64. int MLX90640_TriggerMeasurement(uint8_t slaveAddr)
  65. {
  66. int error = 1;
  67. uint16_t ctrlReg;
  68. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg);
  69. if ( error != 0)
  70. {
  71. return error;
  72. }
  73. ctrlReg |= 0x8000;
  74. error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg);
  75. if ( error != 0)
  76. {
  77. return error;
  78. }
  79. error = MLX90640_I2CGeneralReset();
  80. if ( error != 0)
  81. {
  82. return error;
  83. }
  84. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg);
  85. if ( error != 0)
  86. {
  87. return error;
  88. }
  89. if ((ctrlReg & 0x8000) != 0)
  90. {
  91. return -9;
  92. }
  93. return 0;
  94. }
  95. int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData)
  96. {
  97. uint16_t dataReady = 0;
  98. uint16_t controlRegister1;
  99. uint16_t statusRegister;
  100. int error = 1;
  101. uint16_t data[64];
  102. uint8_t cnt = 0;
  103. while(dataReady == 0)
  104. {
  105. error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
  106. if(error != 0)
  107. {
  108. return error;
  109. }
  110. dataReady = statusRegister & 0x0008;
  111. }
  112. error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
  113. if(error == -1)
  114. {
  115. return error;
  116. }
  117. error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData);
  118. if(error != 0)
  119. {
  120. return error;
  121. }
  122. error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data);
  123. if(error != 0)
  124. {
  125. return error;
  126. }
  127. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  128. frameData[832] = controlRegister1;
  129. frameData[833] = statusRegister & 0x0001;
  130. if(error != 0)
  131. {
  132. return error;
  133. }
  134. error = ValidateAuxData(data);
  135. if(error == 0)
  136. {
  137. for(cnt=0; cnt<64; cnt++)
  138. {
  139. frameData[cnt+768] = data[cnt];
  140. }
  141. }
  142. error = ValidateFrameData(frameData);
  143. if (error != 0)
  144. {
  145. return error;
  146. }
  147. return frameData[833];
  148. }
  149. int ValidateFrameData(uint16_t *frameData)
  150. {
  151. uint8_t line = 0;
  152. for(int i=0; i<768; i+=32)
  153. {
  154. if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8;
  155. line = line + 1;
  156. }
  157. return 0;
  158. }
  159. int ValidateAuxData(uint16_t *auxData)
  160. {
  161. if(auxData[0] == 0x7FFF) return -8;
  162. for(int i=8; i<19; i++)
  163. {
  164. if(auxData[i] == 0x7FFF) return -8;
  165. }
  166. for(int i=20; i<23; i++)
  167. {
  168. if(auxData[i] == 0x7FFF) return -8;
  169. }
  170. for(int i=24; i<33; i++)
  171. {
  172. if(auxData[i] == 0x7FFF) return -8;
  173. }
  174. for(int i=40; i<51; i++)
  175. {
  176. if(auxData[i] == 0x7FFF) return -8;
  177. }
  178. for(int i=52; i<55; i++)
  179. {
  180. if(auxData[i] == 0x7FFF) return -8;
  181. }
  182. for(int i=56; i<64; i++)
  183. {
  184. if(auxData[i] == 0x7FFF) return -8;
  185. }
  186. return 0;
  187. }
  188. int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  189. {
  190. int error = 0;
  191. ExtractVDDParameters(eeData, mlx90640);
  192. ExtractPTATParameters(eeData, mlx90640);
  193. ExtractGainParameters(eeData, mlx90640);
  194. ExtractTgcParameters(eeData, mlx90640);
  195. ExtractResolutionParameters(eeData, mlx90640);
  196. ExtractKsTaParameters(eeData, mlx90640);
  197. ExtractKsToParameters(eeData, mlx90640);
  198. ExtractCPParameters(eeData, mlx90640);
  199. ExtractAlphaParameters(eeData, mlx90640);
  200. ExtractOffsetParameters(eeData, mlx90640);
  201. ExtractKtaPixelParameters(eeData, mlx90640);
  202. ExtractKvPixelParameters(eeData, mlx90640);
  203. ExtractCILCParameters(eeData, mlx90640);
  204. error = ExtractDeviatingPixels(eeData, mlx90640);
  205. return error;
  206. }
  207. //------------------------------------------------------------------------------
  208. int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution)
  209. {
  210. uint16_t controlRegister1;
  211. int value;
  212. int error;
  213. value = (resolution & 0x03) << 10;
  214. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  215. if(error == 0)
  216. {
  217. value = (controlRegister1 & 0xF3FF) | value;
  218. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  219. }
  220. return error;
  221. }
  222. //------------------------------------------------------------------------------
  223. int MLX90640_GetCurResolution(uint8_t slaveAddr)
  224. {
  225. uint16_t controlRegister1;
  226. int resolutionRAM;
  227. int error;
  228. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  229. if(error != 0)
  230. {
  231. return error;
  232. }
  233. resolutionRAM = (controlRegister1 & 0x0C00) >> 10;
  234. return resolutionRAM;
  235. }
  236. //------------------------------------------------------------------------------
  237. int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate)
  238. {
  239. uint16_t controlRegister1;
  240. int value;
  241. int error;
  242. value = (refreshRate & 0x07)<<7;
  243. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  244. if(error == 0)
  245. {
  246. value = (controlRegister1 & 0xFC7F) | value;
  247. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  248. }
  249. return error;
  250. }
  251. //------------------------------------------------------------------------------
  252. int MLX90640_GetRefreshRate(uint8_t slaveAddr)
  253. {
  254. uint16_t controlRegister1;
  255. int refreshRate;
  256. int error;
  257. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  258. if(error != 0)
  259. {
  260. return error;
  261. }
  262. refreshRate = (controlRegister1 & 0x0380) >> 7;
  263. return refreshRate;
  264. }
  265. //------------------------------------------------------------------------------
  266. int MLX90640_SetInterleavedMode(uint8_t slaveAddr)
  267. {
  268. uint16_t controlRegister1;
  269. int value;
  270. int error;
  271. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  272. if(error == 0)
  273. {
  274. value = (controlRegister1 & 0xEFFF);
  275. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  276. }
  277. return error;
  278. }
  279. //------------------------------------------------------------------------------
  280. int MLX90640_SetChessMode(uint8_t slaveAddr)
  281. {
  282. uint16_t controlRegister1;
  283. int value;
  284. int error;
  285. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  286. if(error == 0)
  287. {
  288. value = (controlRegister1 | 0x1000);
  289. error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
  290. }
  291. return error;
  292. }
  293. //------------------------------------------------------------------------------
  294. int MLX90640_GetCurMode(uint8_t slaveAddr)
  295. {
  296. uint16_t controlRegister1;
  297. int modeRAM;
  298. int error;
  299. error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
  300. if(error != 0)
  301. {
  302. return error;
  303. }
  304. modeRAM = (controlRegister1 & 0x1000) >> 12;
  305. return modeRAM;
  306. }
  307. //------------------------------------------------------------------------------
  308. void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result)
  309. {
  310. float vdd;
  311. float ta;
  312. float ta4;
  313. float tr4;
  314. float taTr;
  315. float gain;
  316. float irDataCP[2];
  317. float irData;
  318. float alphaCompensated;
  319. uint8_t mode;
  320. int8_t ilPattern;
  321. int8_t chessPattern;
  322. int8_t pattern;
  323. int8_t conversionPattern;
  324. float Sx;
  325. float To;
  326. float alphaCorrR[4];
  327. int8_t range;
  328. uint16_t subPage;
  329. float ktaScale;
  330. float kvScale;
  331. float alphaScale;
  332. float kta;
  333. float kv;
  334. subPage = frameData[833];
  335. vdd = MLX90640_GetVdd(frameData, params);
  336. ta = MLX90640_GetTa(frameData, params);
  337. ta4 = (ta + 273.15);
  338. ta4 = ta4 * ta4;
  339. ta4 = ta4 * ta4;
  340. tr4 = (tr + 273.15);
  341. tr4 = tr4 * tr4;
  342. tr4 = tr4 * tr4;
  343. taTr = tr4 - (tr4-ta4)/emissivity;
  344. ktaScale = pow(2,(double)params->ktaScale);
  345. kvScale = pow(2,(double)params->kvScale);
  346. alphaScale = pow(2,(double)params->alphaScale);
  347. alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40);
  348. alphaCorrR[1] = 1 ;
  349. alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]);
  350. alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2]));
  351. //------------------------- Gain calculation -----------------------------------
  352. gain = frameData[778];
  353. if(gain > 32767)
  354. {
  355. gain = gain - 65536;
  356. }
  357. gain = params->gainEE / gain;
  358. //------------------------- To calculation -------------------------------------
  359. mode = (frameData[832] & 0x1000) >> 5;
  360. irDataCP[0] = frameData[776];
  361. irDataCP[1] = frameData[808];
  362. for( int i = 0; i < 2; i++)
  363. {
  364. if(irDataCP[i] > 32767)
  365. {
  366. irDataCP[i] = irDataCP[i] - 65536;
  367. }
  368. irDataCP[i] = irDataCP[i] * gain;
  369. }
  370. irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  371. if( mode == params->calibrationModeEE)
  372. {
  373. irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  374. }
  375. else
  376. {
  377. irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  378. }
  379. for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
  380. {
  381. ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
  382. chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
  383. conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
  384. if(mode == 0)
  385. {
  386. pattern = ilPattern;
  387. }
  388. else
  389. {
  390. pattern = chessPattern;
  391. }
  392. if(pattern == frameData[833])
  393. {
  394. irData = frameData[pixelNumber];
  395. if(irData > 32767)
  396. {
  397. irData = irData - 65536;
  398. }
  399. irData = irData * gain;
  400. kta = params->kta[pixelNumber]/ktaScale;
  401. kv = params->kv[pixelNumber]/kvScale;
  402. irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3));
  403. if(mode != params->calibrationModeEE)
  404. {
  405. irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
  406. }
  407. irData = irData - params->tgc * irDataCP[subPage];
  408. irData = irData / emissivity;
  409. alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber];
  410. alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25));
  411. Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr);
  412. Sx = sqrt(sqrt(Sx)) * params->ksTo[1];
  413. To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15;
  414. if(To < params->ct[1])
  415. {
  416. range = 0;
  417. }
  418. else if(To < params->ct[2])
  419. {
  420. range = 1;
  421. }
  422. else if(To < params->ct[3])
  423. {
  424. range = 2;
  425. }
  426. else
  427. {
  428. range = 3;
  429. }
  430. To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15;
  431. result[pixelNumber] = To;
  432. }
  433. }
  434. }
  435. //------------------------------------------------------------------------------
  436. void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result)
  437. {
  438. float vdd;
  439. float ta;
  440. float gain;
  441. float irDataCP[2];
  442. float irData;
  443. float alphaCompensated;
  444. uint8_t mode;
  445. int8_t ilPattern;
  446. int8_t chessPattern;
  447. int8_t pattern;
  448. int8_t conversionPattern;
  449. float image;
  450. uint16_t subPage;
  451. float ktaScale;
  452. float kvScale;
  453. float kta;
  454. float kv;
  455. subPage = frameData[833];
  456. vdd = MLX90640_GetVdd(frameData, params);
  457. ta = MLX90640_GetTa(frameData, params);
  458. ktaScale = pow(2,(double)params->ktaScale);
  459. kvScale = pow(2,(double)params->kvScale);
  460. //------------------------- Gain calculation -----------------------------------
  461. gain = frameData[778];
  462. if(gain > 32767)
  463. {
  464. gain = gain - 65536;
  465. }
  466. gain = params->gainEE / gain;
  467. //------------------------- Image calculation -------------------------------------
  468. mode = (frameData[832] & 0x1000) >> 5;
  469. irDataCP[0] = frameData[776];
  470. irDataCP[1] = frameData[808];
  471. for( int i = 0; i < 2; i++)
  472. {
  473. if(irDataCP[i] > 32767)
  474. {
  475. irDataCP[i] = irDataCP[i] - 65536;
  476. }
  477. irDataCP[i] = irDataCP[i] * gain;
  478. }
  479. irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  480. if( mode == params->calibrationModeEE)
  481. {
  482. irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  483. }
  484. else
  485. {
  486. irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
  487. }
  488. for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
  489. {
  490. ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
  491. chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
  492. conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
  493. if(mode == 0)
  494. {
  495. pattern = ilPattern;
  496. }
  497. else
  498. {
  499. pattern = chessPattern;
  500. }
  501. if(pattern == frameData[833])
  502. {
  503. irData = frameData[pixelNumber];
  504. if(irData > 32767)
  505. {
  506. irData = irData - 65536;
  507. }
  508. irData = irData * gain;
  509. kta = params->kta[pixelNumber]/ktaScale;
  510. kv = params->kv[pixelNumber]/kvScale;
  511. irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3));
  512. if(mode != params->calibrationModeEE)
  513. {
  514. irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
  515. }
  516. irData = irData - params->tgc * irDataCP[subPage];
  517. alphaCompensated = params->alpha[pixelNumber];
  518. image = irData*alphaCompensated;
  519. result[pixelNumber] = image;
  520. }
  521. }
  522. }
  523. //------------------------------------------------------------------------------
  524. float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params)
  525. {
  526. float vdd;
  527. float resolutionCorrection;
  528. int resolutionRAM;
  529. vdd = frameData[810];
  530. if(vdd > 32767)
  531. {
  532. vdd = vdd - 65536;
  533. }
  534. resolutionRAM = (frameData[832] & 0x0C00) >> 10;
  535. resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM);
  536. vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3;
  537. return vdd;
  538. }
  539. //------------------------------------------------------------------------------
  540. float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params)
  541. {
  542. float ptat;
  543. float ptatArt;
  544. float vdd;
  545. float ta;
  546. vdd = MLX90640_GetVdd(frameData, params);
  547. ptat = frameData[800];
  548. if(ptat > 32767)
  549. {
  550. ptat = ptat - 65536;
  551. }
  552. ptatArt = frameData[768];
  553. if(ptatArt > 32767)
  554. {
  555. ptatArt = ptatArt - 65536;
  556. }
  557. ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18);
  558. ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25);
  559. ta = ta / params->KtPTAT + 25;
  560. return ta;
  561. }
  562. //------------------------------------------------------------------------------
  563. int MLX90640_GetSubPageNumber(uint16_t *frameData)
  564. {
  565. return frameData[833];
  566. }
  567. //------------------------------------------------------------------------------
  568. void MLX90640_BadPixelsCorrection(uint16_t *pixels, float *to, int mode, paramsMLX90640 *params)
  569. {
  570. float ap[4];
  571. uint8_t pix;
  572. uint8_t line;
  573. uint8_t column;
  574. pix = 0;
  575. while(pixels[pix] != 0xFFFF)
  576. {
  577. line = pixels[pix]>>5;
  578. column = pixels[pix] - (line<<5);
  579. if(mode == 1)
  580. {
  581. if(line == 0)
  582. {
  583. if(column == 0)
  584. {
  585. to[pixels[pix]] = to[33];
  586. }
  587. else if(column == 31)
  588. {
  589. to[pixels[pix]] = to[62];
  590. }
  591. else
  592. {
  593. to[pixels[pix]] = (to[pixels[pix]+31] + to[pixels[pix]+33])/2.0;
  594. }
  595. }
  596. else if(line == 23)
  597. {
  598. if(column == 0)
  599. {
  600. to[pixels[pix]] = to[705];
  601. }
  602. else if(column == 31)
  603. {
  604. to[pixels[pix]] = to[734];
  605. }
  606. else
  607. {
  608. to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]-31])/2.0;
  609. }
  610. }
  611. else if(column == 0)
  612. {
  613. to[pixels[pix]] = (to[pixels[pix]-31] + to[pixels[pix]+33])/2.0;
  614. }
  615. else if(column == 31)
  616. {
  617. to[pixels[pix]] = (to[pixels[pix]-33] + to[pixels[pix]+31])/2.0;
  618. }
  619. else
  620. {
  621. ap[0] = to[pixels[pix]-33];
  622. ap[1] = to[pixels[pix]-31];
  623. ap[2] = to[pixels[pix]+31];
  624. ap[3] = to[pixels[pix]+33];
  625. to[pixels[pix]] = GetMedian(ap,4);
  626. }
  627. }
  628. else
  629. {
  630. if(column == 0)
  631. {
  632. to[pixels[pix]] = to[pixels[pix]+1];
  633. }
  634. else if(column == 1 || column == 30)
  635. {
  636. to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0;
  637. }
  638. else if(column == 31)
  639. {
  640. to[pixels[pix]] = to[pixels[pix]-1];
  641. }
  642. else
  643. {
  644. if(IsPixelBad(pixels[pix]-2,params) == 0 && IsPixelBad(pixels[pix]+2,params) == 0)
  645. {
  646. ap[0] = to[pixels[pix]+1] - to[pixels[pix]+2];
  647. ap[1] = to[pixels[pix]-1] - to[pixels[pix]-2];
  648. if(fabs(ap[0]) > fabs(ap[1]))
  649. {
  650. to[pixels[pix]] = to[pixels[pix]-1] + ap[1];
  651. }
  652. else
  653. {
  654. to[pixels[pix]] = to[pixels[pix]+1] + ap[0];
  655. }
  656. }
  657. else
  658. {
  659. to[pixels[pix]] = (to[pixels[pix]-1]+to[pixels[pix]+1])/2.0;
  660. }
  661. }
  662. }
  663. pix = pix + 1;
  664. }
  665. }
  666. //------------------------------------------------------------------------------
  667. void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  668. {
  669. int16_t kVdd;
  670. int16_t vdd25;
  671. kVdd = eeData[51];
  672. kVdd = (eeData[51] & 0xFF00) >> 8;
  673. if(kVdd > 127)
  674. {
  675. kVdd = kVdd - 256;
  676. }
  677. kVdd = 32 * kVdd;
  678. vdd25 = eeData[51] & 0x00FF;
  679. vdd25 = ((vdd25 - 256) << 5) - 8192;
  680. mlx90640->kVdd = kVdd;
  681. mlx90640->vdd25 = vdd25;
  682. }
  683. //------------------------------------------------------------------------------
  684. void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  685. {
  686. float KvPTAT;
  687. float KtPTAT;
  688. int16_t vPTAT25;
  689. float alphaPTAT;
  690. KvPTAT = (eeData[50] & 0xFC00) >> 10;
  691. if(KvPTAT > 31)
  692. {
  693. KvPTAT = KvPTAT - 64;
  694. }
  695. KvPTAT = KvPTAT/4096;
  696. KtPTAT = eeData[50] & 0x03FF;
  697. if(KtPTAT > 511)
  698. {
  699. KtPTAT = KtPTAT - 1024;
  700. }
  701. KtPTAT = KtPTAT/8;
  702. vPTAT25 = eeData[49];
  703. alphaPTAT = (eeData[16] & 0xF000) / pow(2, (double)14) + 8.0f;
  704. mlx90640->KvPTAT = KvPTAT;
  705. mlx90640->KtPTAT = KtPTAT;
  706. mlx90640->vPTAT25 = vPTAT25;
  707. mlx90640->alphaPTAT = alphaPTAT;
  708. }
  709. //------------------------------------------------------------------------------
  710. void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  711. {
  712. int16_t gainEE;
  713. gainEE = eeData[48];
  714. if(gainEE > 32767)
  715. {
  716. gainEE = gainEE -65536;
  717. }
  718. mlx90640->gainEE = gainEE;
  719. }
  720. //------------------------------------------------------------------------------
  721. void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  722. {
  723. float tgc;
  724. tgc = eeData[60] & 0x00FF;
  725. if(tgc > 127)
  726. {
  727. tgc = tgc - 256;
  728. }
  729. tgc = tgc / 32.0f;
  730. mlx90640->tgc = tgc;
  731. }
  732. //------------------------------------------------------------------------------
  733. void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  734. {
  735. uint8_t resolutionEE;
  736. resolutionEE = (eeData[56] & 0x3000) >> 12;
  737. mlx90640->resolutionEE = resolutionEE;
  738. }
  739. //------------------------------------------------------------------------------
  740. void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  741. {
  742. float KsTa;
  743. KsTa = (eeData[60] & 0xFF00) >> 8;
  744. if(KsTa > 127)
  745. {
  746. KsTa = KsTa -256;
  747. }
  748. KsTa = KsTa / 8192.0f;
  749. mlx90640->KsTa = KsTa;
  750. }
  751. //------------------------------------------------------------------------------
  752. void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  753. {
  754. int32_t KsToScale;
  755. int8_t step;
  756. step = ((eeData[63] & 0x3000) >> 12) * 10;
  757. mlx90640->ct[0] = -40;
  758. mlx90640->ct[1] = 0;
  759. mlx90640->ct[2] = (eeData[63] & 0x00F0) >> 4;
  760. mlx90640->ct[3] = (eeData[63] & 0x0F00) >> 8;
  761. mlx90640->ct[2] = mlx90640->ct[2]*step;
  762. mlx90640->ct[3] = mlx90640->ct[2] + mlx90640->ct[3]*step;
  763. mlx90640->ct[4] = 400;
  764. KsToScale = (eeData[63] & 0x000F) + 8;
  765. KsToScale = 1UL << KsToScale;
  766. mlx90640->ksTo[0] = eeData[61] & 0x00FF;
  767. mlx90640->ksTo[1] = (eeData[61] & 0xFF00) >> 8;
  768. mlx90640->ksTo[2] = eeData[62] & 0x00FF;
  769. mlx90640->ksTo[3] = (eeData[62] & 0xFF00) >> 8;
  770. for(int i = 0; i < 4; i++)
  771. {
  772. if(mlx90640->ksTo[i] > 127)
  773. {
  774. mlx90640->ksTo[i] = mlx90640->ksTo[i] - 256;
  775. }
  776. mlx90640->ksTo[i] = mlx90640->ksTo[i] / KsToScale;
  777. }
  778. mlx90640->ksTo[4] = -0.0002;
  779. }
  780. //------------------------------------------------------------------------------
  781. void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  782. {
  783. int accRow[24];
  784. int accColumn[32];
  785. int p = 0;
  786. int alphaRef;
  787. uint8_t alphaScale;
  788. uint8_t accRowScale;
  789. uint8_t accColumnScale;
  790. uint8_t accRemScale;
  791. float alphaTemp[768];
  792. float temp;
  793. accRemScale = eeData[32] & 0x000F;
  794. accColumnScale = (eeData[32] & 0x00F0) >> 4;
  795. accRowScale = (eeData[32] & 0x0F00) >> 8;
  796. alphaScale = ((eeData[32] & 0xF000) >> 12) + 30;
  797. alphaRef = eeData[33];
  798. for(int i = 0; i < 6; i++)
  799. {
  800. p = i * 4;
  801. accRow[p + 0] = (eeData[34 + i] & 0x000F);
  802. accRow[p + 1] = (eeData[34 + i] & 0x00F0) >> 4;
  803. accRow[p + 2] = (eeData[34 + i] & 0x0F00) >> 8;
  804. accRow[p + 3] = (eeData[34 + i] & 0xF000) >> 12;
  805. }
  806. for(int i = 0; i < 24; i++)
  807. {
  808. if (accRow[i] > 7)
  809. {
  810. accRow[i] = accRow[i] - 16;
  811. }
  812. }
  813. for(int i = 0; i < 8; i++)
  814. {
  815. p = i * 4;
  816. accColumn[p + 0] = (eeData[40 + i] & 0x000F);
  817. accColumn[p + 1] = (eeData[40 + i] & 0x00F0) >> 4;
  818. accColumn[p + 2] = (eeData[40 + i] & 0x0F00) >> 8;
  819. accColumn[p + 3] = (eeData[40 + i] & 0xF000) >> 12;
  820. }
  821. for(int i = 0; i < 32; i ++)
  822. {
  823. if (accColumn[i] > 7)
  824. {
  825. accColumn[i] = accColumn[i] - 16;
  826. }
  827. }
  828. for(int i = 0; i < 24; i++)
  829. {
  830. for(int j = 0; j < 32; j ++)
  831. {
  832. p = 32 * i +j;
  833. alphaTemp[p] = (eeData[64 + p] & 0x03F0) >> 4;
  834. if (alphaTemp[p] > 31)
  835. {
  836. alphaTemp[p] = alphaTemp[p] - 64;
  837. }
  838. alphaTemp[p] = alphaTemp[p]*(1 << accRemScale);
  839. alphaTemp[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + alphaTemp[p]);
  840. alphaTemp[p] = alphaTemp[p] / pow(2,(double)alphaScale);
  841. alphaTemp[p] = alphaTemp[p] - mlx90640->tgc * (mlx90640->cpAlpha[0] + mlx90640->cpAlpha[1])/2;
  842. alphaTemp[p] = SCALEALPHA/alphaTemp[p];
  843. }
  844. }
  845. temp = alphaTemp[0];
  846. for(int i = 1; i < 768; i++)
  847. {
  848. if (alphaTemp[i] > temp)
  849. {
  850. temp = alphaTemp[i];
  851. }
  852. }
  853. alphaScale = 0;
  854. while(temp < 32767.4)
  855. {
  856. temp = temp*2;
  857. alphaScale = alphaScale + 1;
  858. }
  859. for(int i = 0; i < 768; i++)
  860. {
  861. temp = alphaTemp[i] * pow(2,(double)alphaScale);
  862. mlx90640->alpha[i] = (temp + 0.5);
  863. }
  864. mlx90640->alphaScale = alphaScale;
  865. }
  866. //------------------------------------------------------------------------------
  867. void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  868. {
  869. int occRow[24];
  870. int occColumn[32];
  871. int p = 0;
  872. int16_t offsetRef;
  873. uint8_t occRowScale;
  874. uint8_t occColumnScale;
  875. uint8_t occRemScale;
  876. occRemScale = (eeData[16] & 0x000F);
  877. occColumnScale = (eeData[16] & 0x00F0) >> 4;
  878. occRowScale = (eeData[16] & 0x0F00) >> 8;
  879. offsetRef = eeData[17];
  880. if (offsetRef > 32767)
  881. {
  882. offsetRef = offsetRef - 65536;
  883. }
  884. for(int i = 0; i < 6; i++)
  885. {
  886. p = i * 4;
  887. occRow[p + 0] = (eeData[18 + i] & 0x000F);
  888. occRow[p + 1] = (eeData[18 + i] & 0x00F0) >> 4;
  889. occRow[p + 2] = (eeData[18 + i] & 0x0F00) >> 8;
  890. occRow[p + 3] = (eeData[18 + i] & 0xF000) >> 12;
  891. }
  892. for(int i = 0; i < 24; i++)
  893. {
  894. if (occRow[i] > 7)
  895. {
  896. occRow[i] = occRow[i] - 16;
  897. }
  898. }
  899. for(int i = 0; i < 8; i++)
  900. {
  901. p = i * 4;
  902. occColumn[p + 0] = (eeData[24 + i] & 0x000F);
  903. occColumn[p + 1] = (eeData[24 + i] & 0x00F0) >> 4;
  904. occColumn[p + 2] = (eeData[24 + i] & 0x0F00) >> 8;
  905. occColumn[p + 3] = (eeData[24 + i] & 0xF000) >> 12;
  906. }
  907. for(int i = 0; i < 32; i ++)
  908. {
  909. if (occColumn[i] > 7)
  910. {
  911. occColumn[i] = occColumn[i] - 16;
  912. }
  913. }
  914. for(int i = 0; i < 24; i++)
  915. {
  916. for(int j = 0; j < 32; j ++)
  917. {
  918. p = 32 * i +j;
  919. mlx90640->offset[p] = (eeData[64 + p] & 0xFC00) >> 10;
  920. if (mlx90640->offset[p] > 31)
  921. {
  922. mlx90640->offset[p] = mlx90640->offset[p] - 64;
  923. }
  924. mlx90640->offset[p] = mlx90640->offset[p]*(1 << occRemScale);
  925. mlx90640->offset[p] = (offsetRef + (occRow[i] << occRowScale) + (occColumn[j] << occColumnScale) + mlx90640->offset[p]);
  926. }
  927. }
  928. }
  929. //------------------------------------------------------------------------------
  930. void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  931. {
  932. int p = 0;
  933. int8_t KtaRC[4];
  934. int8_t KtaRoCo;
  935. int8_t KtaRoCe;
  936. int8_t KtaReCo;
  937. int8_t KtaReCe;
  938. uint8_t ktaScale1;
  939. uint8_t ktaScale2;
  940. uint8_t split;
  941. float ktaTemp[768];
  942. float temp;
  943. KtaRoCo = (eeData[54] & 0xFF00) >> 8;
  944. if (KtaRoCo > 127)
  945. {
  946. KtaRoCo = KtaRoCo - 256;
  947. }
  948. KtaRC[0] = KtaRoCo;
  949. KtaReCo = (eeData[54] & 0x00FF);
  950. if (KtaReCo > 127)
  951. {
  952. KtaReCo = KtaReCo - 256;
  953. }
  954. KtaRC[2] = KtaReCo;
  955. KtaRoCe = (eeData[55] & 0xFF00) >> 8;
  956. if (KtaRoCe > 127)
  957. {
  958. KtaRoCe = KtaRoCe - 256;
  959. }
  960. KtaRC[1] = KtaRoCe;
  961. KtaReCe = (eeData[55] & 0x00FF);
  962. if (KtaReCe > 127)
  963. {
  964. KtaReCe = KtaReCe - 256;
  965. }
  966. KtaRC[3] = KtaReCe;
  967. ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8;
  968. ktaScale2 = (eeData[56] & 0x000F);
  969. for(int i = 0; i < 24; i++)
  970. {
  971. for(int j = 0; j < 32; j ++)
  972. {
  973. p = 32 * i +j;
  974. split = 2*(p/32 - (p/64)*2) + p%2;
  975. ktaTemp[p] = (eeData[64 + p] & 0x000E) >> 1;
  976. if (ktaTemp[p] > 3)
  977. {
  978. ktaTemp[p] = ktaTemp[p] - 8;
  979. }
  980. ktaTemp[p] = ktaTemp[p] * (1 << ktaScale2);
  981. ktaTemp[p] = KtaRC[split] + ktaTemp[p];
  982. ktaTemp[p] = ktaTemp[p] / pow(2,(double)ktaScale1);
  983. //ktaTemp[p] = ktaTemp[p] * mlx90640->offset[p];
  984. }
  985. }
  986. temp = fabs(ktaTemp[0]);
  987. for(int i = 1; i < 768; i++)
  988. {
  989. if (fabs(ktaTemp[i]) > temp)
  990. {
  991. temp = fabs(ktaTemp[i]);
  992. }
  993. }
  994. ktaScale1 = 0;
  995. while(temp < 63.4)
  996. {
  997. temp = temp*2;
  998. ktaScale1 = ktaScale1 + 1;
  999. }
  1000. for(int i = 0; i < 768; i++)
  1001. {
  1002. temp = ktaTemp[i] * pow(2,(double)ktaScale1);
  1003. if (temp < 0)
  1004. {
  1005. mlx90640->kta[i] = (temp - 0.5);
  1006. }
  1007. else
  1008. {
  1009. mlx90640->kta[i] = (temp + 0.5);
  1010. }
  1011. }
  1012. mlx90640->ktaScale = ktaScale1;
  1013. }
  1014. //------------------------------------------------------------------------------
  1015. void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  1016. {
  1017. int p = 0;
  1018. int8_t KvT[4];
  1019. int8_t KvRoCo;
  1020. int8_t KvRoCe;
  1021. int8_t KvReCo;
  1022. int8_t KvReCe;
  1023. uint8_t kvScale;
  1024. uint8_t split;
  1025. float kvTemp[768];
  1026. float temp;
  1027. KvRoCo = (eeData[52] & 0xF000) >> 12;
  1028. if (KvRoCo > 7)
  1029. {
  1030. KvRoCo = KvRoCo - 16;
  1031. }
  1032. KvT[0] = KvRoCo;
  1033. KvReCo = (eeData[52] & 0x0F00) >> 8;
  1034. if (KvReCo > 7)
  1035. {
  1036. KvReCo = KvReCo - 16;
  1037. }
  1038. KvT[2] = KvReCo;
  1039. KvRoCe = (eeData[52] & 0x00F0) >> 4;
  1040. if (KvRoCe > 7)
  1041. {
  1042. KvRoCe = KvRoCe - 16;
  1043. }
  1044. KvT[1] = KvRoCe;
  1045. KvReCe = (eeData[52] & 0x000F);
  1046. if (KvReCe > 7)
  1047. {
  1048. KvReCe = KvReCe - 16;
  1049. }
  1050. KvT[3] = KvReCe;
  1051. kvScale = (eeData[56] & 0x0F00) >> 8;
  1052. for(int i = 0; i < 24; i++)
  1053. {
  1054. for(int j = 0; j < 32; j ++)
  1055. {
  1056. p = 32 * i +j;
  1057. split = 2*(p/32 - (p/64)*2) + p%2;
  1058. kvTemp[p] = KvT[split];
  1059. kvTemp[p] = kvTemp[p] / pow(2,(double)kvScale);
  1060. //kvTemp[p] = kvTemp[p] * mlx90640->offset[p];
  1061. }
  1062. }
  1063. temp = fabs(kvTemp[0]);
  1064. for(int i = 1; i < 768; i++)
  1065. {
  1066. if (fabs(kvTemp[i]) > temp)
  1067. {
  1068. temp = fabs(kvTemp[i]);
  1069. }
  1070. }
  1071. kvScale = 0;
  1072. while(temp < 63.4)
  1073. {
  1074. temp = temp*2;
  1075. kvScale = kvScale + 1;
  1076. }
  1077. for(int i = 0; i < 768; i++)
  1078. {
  1079. temp = kvTemp[i] * pow(2,(double)kvScale);
  1080. if (temp < 0)
  1081. {
  1082. mlx90640->kv[i] = (temp - 0.5);
  1083. }
  1084. else
  1085. {
  1086. mlx90640->kv[i] = (temp + 0.5);
  1087. }
  1088. }
  1089. mlx90640->kvScale = kvScale;
  1090. }
  1091. //------------------------------------------------------------------------------
  1092. void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  1093. {
  1094. float alphaSP[2];
  1095. int16_t offsetSP[2];
  1096. float cpKv;
  1097. float cpKta;
  1098. uint8_t alphaScale;
  1099. uint8_t ktaScale1;
  1100. uint8_t kvScale;
  1101. alphaScale = ((eeData[32] & 0xF000) >> 12) + 27;
  1102. offsetSP[0] = (eeData[58] & 0x03FF);
  1103. if (offsetSP[0] > 511)
  1104. {
  1105. offsetSP[0] = offsetSP[0] - 1024;
  1106. }
  1107. offsetSP[1] = (eeData[58] & 0xFC00) >> 10;
  1108. if (offsetSP[1] > 31)
  1109. {
  1110. offsetSP[1] = offsetSP[1] - 64;
  1111. }
  1112. offsetSP[1] = offsetSP[1] + offsetSP[0];
  1113. alphaSP[0] = (eeData[57] & 0x03FF);
  1114. if (alphaSP[0] > 511)
  1115. {
  1116. alphaSP[0] = alphaSP[0] - 1024;
  1117. }
  1118. alphaSP[0] = alphaSP[0] / pow(2,(double)alphaScale);
  1119. alphaSP[1] = (eeData[57] & 0xFC00) >> 10;
  1120. if (alphaSP[1] > 31)
  1121. {
  1122. alphaSP[1] = alphaSP[1] - 64;
  1123. }
  1124. alphaSP[1] = (1 + alphaSP[1]/128) * alphaSP[0];
  1125. cpKta = (eeData[59] & 0x00FF);
  1126. if (cpKta > 127)
  1127. {
  1128. cpKta = cpKta - 256;
  1129. }
  1130. ktaScale1 = ((eeData[56] & 0x00F0) >> 4) + 8;
  1131. mlx90640->cpKta = cpKta / pow(2,(double)ktaScale1);
  1132. cpKv = (eeData[59] & 0xFF00) >> 8;
  1133. if (cpKv > 127)
  1134. {
  1135. cpKv = cpKv - 256;
  1136. }
  1137. kvScale = (eeData[56] & 0x0F00) >> 8;
  1138. mlx90640->cpKv = cpKv / pow(2,(double)kvScale);
  1139. mlx90640->cpAlpha[0] = alphaSP[0];
  1140. mlx90640->cpAlpha[1] = alphaSP[1];
  1141. mlx90640->cpOffset[0] = offsetSP[0];
  1142. mlx90640->cpOffset[1] = offsetSP[1];
  1143. }
  1144. //------------------------------------------------------------------------------
  1145. void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
  1146. {
  1147. float ilChessC[3];
  1148. uint8_t calibrationModeEE;
  1149. calibrationModeEE = (eeData[10] & 0x0800) >> 4;
  1150. calibrationModeEE = calibrationModeEE ^ 0x80;
  1151. ilChessC[0] = (eeData[53] & 0x003F);
  1152. if (ilChessC[0] > 31)
  1153. {
  1154. ilChessC[0] = ilChessC[0] - 64;
  1155. }
  1156. ilChessC[0] = ilChessC[0] / 16.0f;
  1157. ilChessC[1] = (eeData[53] & 0x07C0) >> 6;
  1158. if (ilChessC[1] > 15)
  1159. {
  1160. ilChessC[1] = ilChessC[1] - 32;
  1161. }
  1162. ilChessC[1] = ilChessC[1] / 2.0f;
  1163. ilChessC[2] = (eeData[53] & 0xF800) >> 11;
  1164. if (ilChessC[2] > 15)
  1165. {
  1166. ilChessC[2] = ilChessC[2] - 32;
  1167. }
  1168. ilChessC[2] = ilChessC[2] / 8.0f;
  1169. mlx90640->calibrationModeEE = calibrationModeEE;
  1170. mlx90640->ilChessC[0] = ilChessC[0];
  1171. mlx90640->ilChessC[1] = ilChessC[1];
  1172. mlx90640->ilChessC[2] = ilChessC[2];
  1173. }
  1174. //------------------------------------------------------------------------------
  1175. int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640)
  1176. {
  1177. uint16_t pixCnt = 0;
  1178. uint16_t brokenPixCnt = 0;
  1179. uint16_t outlierPixCnt = 0;
  1180. int warn = 0;
  1181. int i;
  1182. for(pixCnt = 0; pixCnt<5; pixCnt++)
  1183. {
  1184. mlx90640->brokenPixels[pixCnt] = 0xFFFF;
  1185. mlx90640->outlierPixels[pixCnt] = 0xFFFF;
  1186. }
  1187. pixCnt = 0;
  1188. while (pixCnt < 768 && brokenPixCnt < 5 && outlierPixCnt < 5)
  1189. {
  1190. if(eeData[pixCnt+64] == 0)
  1191. {
  1192. mlx90640->brokenPixels[brokenPixCnt] = pixCnt;
  1193. brokenPixCnt = brokenPixCnt + 1;
  1194. }
  1195. else if((eeData[pixCnt+64] & 0x0001) != 0)
  1196. {
  1197. mlx90640->outlierPixels[outlierPixCnt] = pixCnt;
  1198. outlierPixCnt = outlierPixCnt + 1;
  1199. }
  1200. pixCnt = pixCnt + 1;
  1201. }
  1202. if(brokenPixCnt > 4)
  1203. {
  1204. warn = -3;
  1205. }
  1206. else if(outlierPixCnt > 4)
  1207. {
  1208. warn = -4;
  1209. }
  1210. else if((brokenPixCnt + outlierPixCnt) > 4)
  1211. {
  1212. warn = -5;
  1213. }
  1214. else
  1215. {
  1216. for(pixCnt=0; pixCnt<brokenPixCnt; pixCnt++)
  1217. {
  1218. for(i=pixCnt+1; i<brokenPixCnt; i++)
  1219. {
  1220. warn = CheckAdjacentPixels(mlx90640->brokenPixels[pixCnt],mlx90640->brokenPixels[i]);
  1221. if(warn != 0)
  1222. {
  1223. return warn;
  1224. }
  1225. }
  1226. }
  1227. for(pixCnt=0; pixCnt<outlierPixCnt; pixCnt++)
  1228. {
  1229. for(i=pixCnt+1; i<outlierPixCnt; i++)
  1230. {
  1231. warn = CheckAdjacentPixels(mlx90640->outlierPixels[pixCnt],mlx90640->outlierPixels[i]);
  1232. if(warn != 0)
  1233. {
  1234. return warn;
  1235. }
  1236. }
  1237. }
  1238. for(pixCnt=0; pixCnt<brokenPixCnt; pixCnt++)
  1239. {
  1240. for(i=0; i<outlierPixCnt; i++)
  1241. {
  1242. warn = CheckAdjacentPixels(mlx90640->brokenPixels[pixCnt],mlx90640->outlierPixels[i]);
  1243. if(warn != 0)
  1244. {
  1245. return warn;
  1246. }
  1247. }
  1248. }
  1249. }
  1250. return warn;
  1251. }
  1252. //------------------------------------------------------------------------------
  1253. int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2)
  1254. {
  1255. int pixPosDif;
  1256. pixPosDif = pix1 - pix2;
  1257. if(pixPosDif > -34 && pixPosDif < -30)
  1258. {
  1259. return -6;
  1260. }
  1261. if(pixPosDif > -2 && pixPosDif < 2)
  1262. {
  1263. return -6;
  1264. }
  1265. if(pixPosDif > 30 && pixPosDif < 34)
  1266. {
  1267. return -6;
  1268. }
  1269. return 0;
  1270. }
  1271. //------------------------------------------------------------------------------
  1272. float GetMedian(float *values, int n)
  1273. {
  1274. float temp;
  1275. for(int i=0; i<n-1; i++)
  1276. {
  1277. for(int j=i+1; j<n; j++)
  1278. {
  1279. if(values[j] < values[i])
  1280. {
  1281. temp = values[i];
  1282. values[i] = values[j];
  1283. values[j] = temp;
  1284. }
  1285. }
  1286. }
  1287. if(n%2==0)
  1288. {
  1289. return ((values[n/2] + values[n/2 - 1]) / 2.0);
  1290. }
  1291. else
  1292. {
  1293. return values[n/2];
  1294. }
  1295. }
  1296. //------------------------------------------------------------------------------
  1297. int IsPixelBad(uint16_t pixel,paramsMLX90640 *params)
  1298. {
  1299. for(int i=0; i<5; i++)
  1300. {
  1301. if(pixel == params->outlierPixels[i] || pixel == params->brokenPixels[i])
  1302. {
  1303. return 1;
  1304. }
  1305. }
  1306. return 0;
  1307. }
  1308. //------------------------------------------------------------------------------