A_I Пока не умрёт Всё же асм больше подходит для низкого уровня - драйверов, например (я не сторонник разных теоретико-академических задач типа факторизации сверхбольших, хотя и понимаю, что такого плана исследования тоже нужны, хотя не ясно кому ) Поэтому вот реальный пример - часть драйвера, а именно - слой апи взаимодействия с одной тепловизионной матрицей от мелексис, и да - на плюсах. (Заказали матрицу для своих поделок, пока не пришла - теоретически готовимся..) По объему - ничего примечательного, средний такой драйверок. Причем особо извращенной логики там нет, - достаточно всё просто, но сомнительно, как это всё в асме писать да ещё потом поддерживать.. Приведу меньше половины, т.к. местный редактор ругается на превышение макс. кол-ва знаков. Однако только в инклудах, к примеру, один матн хедер чего стоит.. Во что это выльется на асме? Я уж не говорю о том, что никакого прироста быстродействия не будет в принципе - инертность ик- пикселов сводит на нет все попытки снимать данные чаще чем 16 Гц (хотя в даташите указывается до 64-х - но, пишут шумы возрастают непропорционально сильно, так что без толку). За это время всё прекрасно обработается. (Оффтоп)
Код: #include <MLX90640_I2C_Driver.h> #include <MLX90640_API.h> #include <math.h>
void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640); int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640); int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2); float GetMedian(float *values, int n); int IsPixelBad(uint16_t pixel,paramsMLX90640 *params); int ValidateFrameData(uint16_t *frameData); int ValidateAuxData(uint16_t *auxData); int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData) { return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData); }
int MLX90640_SynchFrame(uint8_t slaveAddr) { uint16_t dataReady = 0; uint16_t statusRegister; int error = 1; error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); if(error == -1) { return error; } while(dataReady == 0) { error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); if(error != 0) { return error; } dataReady = statusRegister & 0x0008; } return 0; }
int MLX90640_TriggerMeasurement(uint8_t slaveAddr) { int error = 1; uint16_t ctrlReg; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); if ( error != 0) { return error; } ctrlReg |= 0x8000; error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg); if ( error != 0) { return error; } error = MLX90640_I2CGeneralReset(); if ( error != 0) { return error; } error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg); if ( error != 0) { return error; } if ((ctrlReg & 0x8000) != 0) { return -9; } return 0; } int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData) { uint16_t dataReady = 0; uint16_t controlRegister1; uint16_t statusRegister; int error = 1; uint16_t data[64]; uint8_t cnt = 0; while(dataReady == 0) { error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister); if(error != 0) { return error; } dataReady = statusRegister & 0x0008; } error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030); if(error == -1) { return error; } error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData); if(error != 0) { return error; } error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data); if(error != 0) { return error; } error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); frameData[832] = controlRegister1; frameData[833] = statusRegister & 0x0001; if(error != 0) { return error; } error = ValidateAuxData(data); if(error == 0) { for(cnt=0; cnt<64; cnt++) { frameData[cnt+768] = data[cnt]; } } error = ValidateFrameData(frameData); if (error != 0) { return error; } return frameData[833]; }
int ValidateFrameData(uint16_t *frameData) { uint8_t line = 0; for(int i=0; i<768; i+=32) { if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8; line = line + 1; } return 0; }
int ValidateAuxData(uint16_t *auxData) { if(auxData[0] == 0x7FFF) return -8; for(int i=8; i<19; i++) { if(auxData[i] == 0x7FFF) return -8; } for(int i=20; i<23; i++) { if(auxData[i] == 0x7FFF) return -8; } for(int i=24; i<33; i++) { if(auxData[i] == 0x7FFF) return -8; } for(int i=40; i<51; i++) { if(auxData[i] == 0x7FFF) return -8; } for(int i=52; i<55; i++) { if(auxData[i] == 0x7FFF) return -8; } for(int i=56; i<64; i++) { if(auxData[i] == 0x7FFF) return -8; } return 0; } int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640) { int error = 0; ExtractVDDParameters(eeData, mlx90640); ExtractPTATParameters(eeData, mlx90640); ExtractGainParameters(eeData, mlx90640); ExtractTgcParameters(eeData, mlx90640); ExtractResolutionParameters(eeData, mlx90640); ExtractKsTaParameters(eeData, mlx90640); ExtractKsToParameters(eeData, mlx90640); ExtractCPParameters(eeData, mlx90640); ExtractAlphaParameters(eeData, mlx90640); ExtractOffsetParameters(eeData, mlx90640); ExtractKtaPixelParameters(eeData, mlx90640); ExtractKvPixelParameters(eeData, mlx90640); ExtractCILCParameters(eeData, mlx90640); error = ExtractDeviatingPixels(eeData, mlx90640); return error;
}
//------------------------------------------------------------------------------
int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution) { uint16_t controlRegister1; int value; int error; value = (resolution & 0x03) << 10; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); if(error == 0) { value = (controlRegister1 & 0xF3FF) | value; error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); } return error; }
//------------------------------------------------------------------------------
int MLX90640_GetCurResolution(uint8_t slaveAddr) { uint16_t controlRegister1; int resolutionRAM; int error; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); if(error != 0) { return error; } resolutionRAM = (controlRegister1 & 0x0C00) >> 10; return resolutionRAM; }
//------------------------------------------------------------------------------
int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate) { uint16_t controlRegister1; int value; int error; value = (refreshRate & 0x07)<<7; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); if(error == 0) { value = (controlRegister1 & 0xFC7F) | value; error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); } return error; }
//------------------------------------------------------------------------------
int MLX90640_GetRefreshRate(uint8_t slaveAddr) { uint16_t controlRegister1; int refreshRate; int error; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); if(error != 0) { return error; } refreshRate = (controlRegister1 & 0x0380) >> 7; return refreshRate; }
//------------------------------------------------------------------------------
int MLX90640_SetInterleavedMode(uint8_t slaveAddr) { uint16_t controlRegister1; int value; int error; error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1); if(error == 0) { value = (controlRegister1 & 0xEFFF); error = MLX90640_I2CWrite(slaveAddr, 0x800D, value); } return error; }
//------------------------------------------------------------------------------
...
... //------------------------------------------------------------------------------
void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result) { float vdd; float ta; float ta4; float tr4; float taTr; float gain; float irDataCP[2]; float irData; float alphaCompensated; uint8_t mode; int8_t ilPattern; int8_t chessPattern; int8_t pattern; int8_t conversionPattern; float Sx; float To; float alphaCorrR[4]; int8_t range; uint16_t subPage; float ktaScale; float kvScale; float alphaScale; float kta; float kv; subPage = frameData[833]; vdd = MLX90640_GetVdd(frameData, params); ta = MLX90640_GetTa(frameData, params); ta4 = (ta + 273.15); ta4 = ta4 * ta4; ta4 = ta4 * ta4; tr4 = (tr + 273.15); tr4 = tr4 * tr4; tr4 = tr4 * tr4; taTr = tr4 - (tr4-ta4)/emissivity; ktaScale = pow(2,(double)params->ktaScale); kvScale = pow(2,(double)params->kvScale); alphaScale = pow(2,(double)params->alphaScale); alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40); alphaCorrR[1] = 1 ; alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]); alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2])); //------------------------- Gain calculation ----------------------------------- gain = frameData[778]; if(gain > 32767) { gain = gain - 65536; } gain = params->gainEE / gain; //------------------------- To calculation ------------------------------------- mode = (frameData[832] & 0x1000) >> 5; irDataCP[0] = frameData[776]; irDataCP[1] = frameData[808]; for( int i = 0; i < 2; i++) { if(irDataCP[i] > 32767) { irDataCP[i] = irDataCP[i] - 65536; } irDataCP[i] = irDataCP[i] * gain; } irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); if( mode == params->calibrationModeEE) { irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); } else { irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); }
for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++) { ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); if(mode == 0) { pattern = ilPattern; } else { pattern = chessPattern; } if(pattern == frameData[833]) { irData = frameData[pixelNumber]; if(irData > 32767) { irData = irData - 65536; } irData = irData * gain; kta = params->kta[pixelNumber]/ktaScale; kv = params->kv[pixelNumber]/kvScale; irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3)); if(mode != params->calibrationModeEE) { irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; } irData = irData - params->tgc * irDataCP[subPage]; irData = irData / emissivity; alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber]; alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25)); Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr); Sx = sqrt(sqrt(Sx)) * params->ksTo[1]; To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15; if(To < params->ct[1]) { range = 0; } else if(To < params->ct[2]) { range = 1; } else if(To < params->ct[3]) { range = 2; } else { range = 3; } To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15; result[pixelNumber] = To; } } }
//------------------------------------------------------------------------------
void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result) { float vdd; float ta; float gain; float irDataCP[2]; float irData; float alphaCompensated; uint8_t mode; int8_t ilPattern; int8_t chessPattern; int8_t pattern; int8_t conversionPattern; float image; uint16_t subPage; float ktaScale; float kvScale; float kta; float kv; subPage = frameData[833]; vdd = MLX90640_GetVdd(frameData, params); ta = MLX90640_GetTa(frameData, params); ktaScale = pow(2,(double)params->ktaScale); kvScale = pow(2,(double)params->kvScale); //------------------------- Gain calculation ----------------------------------- gain = frameData[778]; if(gain > 32767) { gain = gain - 65536; } gain = params->gainEE / gain; //------------------------- Image calculation ------------------------------------- mode = (frameData[832] & 0x1000) >> 5; irDataCP[0] = frameData[776]; irDataCP[1] = frameData[808]; for( int i = 0; i < 2; i++) { if(irDataCP[i] > 32767) { irDataCP[i] = irDataCP[i] - 65536; } irDataCP[i] = irDataCP[i] * gain; } irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); if( mode == params->calibrationModeEE) { irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); } else { irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3)); }
for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++) { ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2; chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2); conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern); if(mode == 0) { pattern = ilPattern; } else { pattern = chessPattern; } if(pattern == frameData[833]) { irData = frameData[pixelNumber]; if(irData > 32767) { irData = irData - 65536; } irData = irData * gain; kta = params->kta[pixelNumber]/ktaScale; kv = params->kv[pixelNumber]/kvScale; irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3));
if(mode != params->calibrationModeEE) { irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern; } irData = irData - params->tgc * irDataCP[subPage]; alphaCompensated = params->alpha[pixelNumber]; image = irData*alphaCompensated; result[pixelNumber] = image; } } }
//------------------------------------------------------------------------------
float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params) { float vdd; float resolutionCorrection;
int resolutionRAM; vdd = frameData[810]; if(vdd > 32767) { vdd = vdd - 65536; } resolutionRAM = (frameData[832] & 0x0C00) >> 10; resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM); vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3; return vdd; }
//------------------------------------------------------------------------------
float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params) { float ptat; float ptatArt; float vdd; float ta; vdd = MLX90640_GetVdd(frameData, params); ptat = frameData[800]; if(ptat > 32767) { ptat = ptat - 65536; } ptatArt = frameData[768]; if(ptatArt > 32767) { ptatArt = ptatArt - 65536; } ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18); ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25); ta = ta / params->KtPTAT + 25; return ta; }
//------------------------------------------------------------------------------
int MLX90640_GetSubPageNumber(uint16_t *frameData) { return frameData[833];
}
//------------------------------------------------------------------------------ ...
...
... }
//------------------------------------------------------------------------------
|