MLX90640_API.c 39 KB

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