diff --git a/F1:F103/MLX90640/MLX90640.bin b/F1:F103/MLX90640/MLX90640.bin
index e1978e6..46051af 100755
Binary files a/F1:F103/MLX90640/MLX90640.bin and b/F1:F103/MLX90640/MLX90640.bin differ
diff --git a/F1:F103/MLX90640/Makefile b/F1:F103/MLX90640/Makefile
index 8143eab..07e1d20 100644
--- a/F1:F103/MLX90640/Makefile
+++ b/F1:F103/MLX90640/Makefile
@@ -74,7 +74,7 @@ LDFLAGS += -T$(LDSCRIPT)
###############################################################################
# Used libraries
-LDLIBS += -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LDLIBS += -lm -lc $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU) -DSTM32F10X_$(DENSITY)
diff --git a/F1:F103/MLX90640/hardware.c b/F1:F103/MLX90640/hardware.c
index b1ead54..9a39ef7 100644
--- a/F1:F103/MLX90640/hardware.c
+++ b/F1:F103/MLX90640/hardware.c
@@ -28,8 +28,9 @@ static inline void gpio_setup(){
GPIOC->CRH |= CRH(13, CNF_ODOUTPUT | MODE_SLOW);
// USB pullup (PA15) - pushpull output
GPIOA->CRH = CRH(15, CNF_PPOUTPUT | MODE_SLOW);
- // PB5 is powered MLX sensor (less than 23mA) - pushpull output
- GPIOB->CRL = CRL(5, CNF_PPOUTPUT | MODE_SLOW);
+ // PB5 is powered MLX sensor (less than 23mA) - OD output
+ MLXPOW_OFF();
+ GPIOB->CRL = CRL(5, CNF_ODOUTPUT | MODE_SLOW);
}
void hw_setup(){
diff --git a/F1:F103/MLX90640/hardware.h b/F1:F103/MLX90640/hardware.h
index 0a44612..5ee8bd2 100644
--- a/F1:F103/MLX90640/hardware.h
+++ b/F1:F103/MLX90640/hardware.h
@@ -33,9 +33,9 @@
#define MLXPOW_pin (1<<5)
#define USBPU_ON() pin_set(USBPU_port, USBPU_pin)
#define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin)
-#define MLXPOW_ON() pin_set(MLXPOW_port, MLXPOW_pin)
-#define MLXPOW_OFF() pin_clear(MLXPOW_port, MLXPOW_pin)
-#define MLXPOW_VAL() pin_read(MLXPOW_port, MLXPOW_pin)
+#define MLXPOW_ON() pin_clear(MLXPOW_port, MLXPOW_pin)
+#define MLXPOW_OFF() pin_set(MLXPOW_port, MLXPOW_pin)
+#define MLXPOW_VAL() ((MLXPOW_port->IDR & MLXPOW_pin)?0:1)
#define LED_blink(x) pin_toggle(x ## _port, x ## _pin)
#define LED_on(x) pin_clear(x ## _port, x ## _pin)
diff --git a/F1:F103/MLX90640/i2c.c b/F1:F103/MLX90640/i2c.c
index 7b8e4e2..fd94621 100644
--- a/F1:F103/MLX90640/i2c.c
+++ b/F1:F103/MLX90640/i2c.c
@@ -49,17 +49,22 @@ static void i2c_DMAr_setup(){
* @param withDMA == 1 to setup DMA receiver too
*/
void i2c_setup(uint8_t withDMA){
- I2C1->CR1 = 0;
- I2C1->SR1 = 0;
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
GPIOB->CRL = (GPIOB->CRL & ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7)) |
CRL(6, CNF_AFOD | MODE_NORMAL) | CRL(7, CNF_AFOD | MODE_NORMAL);
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
+ I2C1->CR1 = 0; // clear all previous settings
+ I2C1->SR1 = 0;
+ RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST; // reset peripherial
+ RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;
I2C1->CR2 = 8; // FREQR=8MHz, T=125ns
- I2C1->TRISE = 9; // (9-1)*125 = 1mks
+ //I2C1->CR2 = 10; // FREQR=10MHz, T=100ns
+ I2C1->TRISE = 9; // (9-1)*125 = 1us
+ //I2C1->TRISE = 4; // (4-1)*100 = 300ns
I2C1->CCR = 40; // normal mode, 8MHz/2/40 = 100kHz
- I2C1->CR1 |= I2C_CR1_PE; // enable periph
+ //I2C1->CCR = I2C_CCR_FS | 10; // fast mode, 10MHz/2/10 = 500kHz
if(withDMA) i2c_DMAr_setup();
+ I2C1->CR1 |= I2C_CR1_PE; // enable periph
}
void i2c_set_addr7(uint8_t addr){
@@ -162,6 +167,7 @@ i2c_status i2c_7bit_receive_twobytes(uint8_t *data){
DBG("2 ADDR");
if(I2C1->SR1 & I2C_SR1_AF){ // NACK
ret = I2C_NACK;
+ DBG("2 NACK");
goto eotr;
}
DBG("2 ACK");
diff --git a/F1:F103/MLX90640/mlx90640.c b/F1:F103/MLX90640/mlx90640.c
index 6d40ea9..af703c3 100644
--- a/F1:F103/MLX90640/mlx90640.c
+++ b/F1:F103/MLX90640/mlx90640.c
@@ -16,6 +16,7 @@
* along with this program. If not, see .
*/
+#include
#include "hardware.h"
#include "i2c.h"
#include "mlx90640.h"
@@ -70,14 +71,27 @@ int read_reg(uint16_t reg, uint16_t *val){
}
// blocking read N uint16_t values starting from `reg`
-// @return N of registers read
-int read_data(uint16_t reg, uint16_t *data, int N){
- if(N < 1 ) return 0;
- int i;
- for(i = 0; i < N; ++i){
- if(!read_reg(reg+i, data++)) break;
+// @param reg - register to read
+// @param N (io) - amount of bytes to read / bytes read
+// @return `dataarray` or NULL if failed
+uint16_t *read_data(uint16_t reg, uint16_t *N){
+ uint16_t n = *N;
+ if(n < 1 || n > MLX_DMA_MAXLEN) return NULL;
+ uint16_t i, *data = dataarray;
+#ifdef EBUG
+ SEND("Tms="); printu(Tms); newline();
+#endif
+ for(i = 0; i < n; ++i){
+ if(!read_reg(reg++, data++)){
+ DBG("can't read");
+ break;
+ }
}
- return i;
+#ifdef EBUG
+ SEND("Tms="); printu(Tms); newline();
+#endif
+ *N = i;
+ return dataarray;
}
// write register value
@@ -146,7 +160,7 @@ static int get_parameters(){
SEND("0 Tms="); printu(Tms); newline();
#endif
int8_t i8;
- int16_t i16, *pi16;
+ int16_t i16;
uint16_t *pu16;
uint16_t val = CREG_VAL(REG_VDD);
i8 = (int8_t) (val >> 8);
@@ -169,14 +183,14 @@ static int get_parameters(){
#ifdef EBUG
SEND("1 Tms="); printu(Tms); newline();
#endif
- int8_t occRow[24];
- int8_t occColumn[32];
- occacc(occRow, 24, &CREG_VAL(REG_OCCROW14));
- occacc(occColumn, 32, &CREG_VAL(REG_OCCCOL14));
- int8_t accRow[24];
- int8_t accColumn[32];
- occacc(accRow, 24, &CREG_VAL(REG_ACCROW14));
- occacc(accColumn, 32, &CREG_VAL(REG_ACCCOL14));
+ int8_t occRow[MLX_H];
+ int8_t occColumn[MLX_W];
+ occacc(occRow, MLX_H, &CREG_VAL(REG_OCCROW14));
+ occacc(occColumn, MLX_W, &CREG_VAL(REG_OCCCOL14));
+ int8_t accRow[MLX_H];
+ int8_t accColumn[MLX_W];
+ occacc(accRow, MLX_H, &CREG_VAL(REG_ACCROW14));
+ occacc(accColumn, MLX_W, &CREG_VAL(REG_ACCCOL14));
val = CREG_VAL(REG_APTATOCCS);
// need to do multiplication instead of bitshift, so:
float occRemScale = 1<<(val&0x0F),
@@ -205,31 +219,28 @@ static int get_parameters(){
float accRowScale = 1<<((val & 0x0f00)>>8),
accColumnScale = 1<<((val & 0x00f0)>>4),
accRemScale = 1<<(val & 0x0f);
- pi16 = params.offset;
pu16 = &CREG_VAL(REG_OFFAK1);
- float *fp = params.kta;
+ float *kta = params.kta, *offset = params.offset;
#ifdef EBUG
SEND("2 Tms="); printu(Tms); newline();
#endif
- for(int row = 0; row < 24; ++row){
+ for(int row = 0; row < MLX_H; ++row){
int idx = (row&1)<<1;
- for(int col = 0; col < 32; ++col){
+ for(int col = 0; col < MLX_W; ++col){
// offset
register uint16_t rv = *pu16++;
i16 = (rv & 0xFC00) >> 10;
if(i16 > 0x1F) i16 -= 0x40;
- register float oft = (float)offavg + occRow[row]*occRowScale + occColumn[col]*occColumnScale + i16*occRemScale;
- *pi16++ = (int16_t)oft;
+ *offset++ = (float)offavg + (float)occRow[row]*occRowScale + (float)occColumn[col]*occColumnScale + (float)i16*occRemScale;
// kta
i16 = (rv & 0xF) >> 1;
if(i16 > 0x03) i16 -= 0x08;
- *fp++ = (ktaavg[idx|(col&1)] + i16*mul) / div;
+ *kta++ = (ktaavg[idx|(col&1)] + i16*mul) / div;
// alpha
i16 = (rv & 0x3F0) >> 4;
if(i16 > 0x1F) i16 -= 0x40;
- oft = (float)a_r + accRow[row]*accRowScale + accColumn[col]*accColumnScale +i16*accRemScale;
+ float oft = (float)a_r + accRow[row]*accRowScale + accColumn[col]*accColumnScale +i16*accRemScale;
*a++ = oft / diva;
- //*a++ /= diva;
}
}
#ifdef EBUG
@@ -280,14 +291,14 @@ static int get_parameters(){
div = 1<<((CREG_VAL(REG_CT34) & 0x0F) + 8); // kstoscale
val = CREG_VAL(REG_KSTO12);
i8 = (int8_t)(val & 0xFF);
- params.ksTo[0] = (float)i8 / div;
+ params.ksTo[0] = 273.15f * i8 / div;
i8 = (int8_t)(val >> 8);
- params.ksTo[1] = (float)i8 / div;
+ params.ksTo[1] = 273.15f * i8 / div;
val = CREG_VAL(REG_KSTO34);
i8 = (int8_t)(val & 0xFF);
- params.ksTo[2] = (float)i8 / div;
+ params.ksTo[2] = 273.15f * i8 / div;
i8 = (int8_t)(val >> 8);
- params.ksTo[3] = (float)i8 / div;
+ params.ksTo[3] = 273.15f * i8 / div;
params.CT[0] = 0.f; // 0degr - between ranges 1 and 2
val = CREG_VAL(REG_CT34);
mul = ((val & 0x3000)>>12)*10.f; // step
@@ -305,57 +316,82 @@ static int get_parameters(){
return TRUE;
}
-
-// calculate Vsup, Tamb, gain, off, Vdd, Ta
-static void stage1(){
- int16_t i16a = (int16_t)IMD_VAL(REG_IVDDPIX);
- float dvdd = i16a - params.vdd25;
- dvdd = dvdd / params.kVdd;
- float vdd = dvdd + 3.3f;
- SEND("Vd="); float2str(vdd, 2); newline();
- i16a = (int16_t)IMD_VAL(REG_ITAPTAT);
- int16_t i16b = (int16_t)IMD_VAL(REG_ITAVBE);
- float Ta = (float)i16a / (i16a * params.alphaPTAT + i16b); // vptatart
- Ta *= (float)(1<<18);
- Ta = (Ta / (1 + params.KvPTAT*dvdd) - params.vPTAT25);
- Ta = Ta / params.KtPTAT + 25.;
- SEND("Ta="); float2str(Ta, 2); newline();
- i16a = (int16_t)IMD_VAL(REG_IGAIN);
- float Kgain = params.gainEE / (float)i16a;
- SEND("Kgain="); float2str(Kgain, 2); newline();
- ;
- //int idx = (row&1)<<1;
- //for(int col = 0; col < 32; ++col){
- // *fp++ = (ktaavg[idx|(col&1)]
- // pix_gain = pix*Kgain
- // pix_os = pix_gain - offset*(1+kta*(Ta-Ta0))*(1+kv*(vdd-vdd0))
-}
-
/**
* @brief process_subpage - calculate all parameters from `dataarray` into `mlx_image`
*/
static void process_subpage(){
DBG("process_subpage()");
+SEND("Tms="); printu(Tms); newline();
SEND("subpage="); printu(subpageno); newline();
(void)subpageno; (void)simpleimage;
-for(int i = 0; i < 32; ++i){
+for(int i = 0; i < MLX_W; ++i){
printi((int8_t)dataarray[i]); bufputchar(' ');
} newline();
- stage1();
- NL();
+SEND("072a="); printuhex(IMD_VAL(REG_IVDDPIX));
+SEND("\n0720="); printuhex(IMD_VAL(REG_ITAPTAT));
+SEND("\n0700="); printuhex(IMD_VAL(REG_ITAVBE));
+SEND("\n070a="); printuhex(IMD_VAL(REG_IGAIN)); newline();
+ int16_t i16a = (int16_t)IMD_VAL(REG_IVDDPIX);
+ float dvdd = i16a - params.vdd25;
+ dvdd = dvdd / params.kVdd;
+ SEND("Vd="); float2str(dvdd+3.3f, 2); newline();
+ i16a = (int16_t)IMD_VAL(REG_ITAPTAT);
+ int16_t i16b = (int16_t)IMD_VAL(REG_ITAVBE);
+ float dTa = (float)i16a / (i16a * params.alphaPTAT + i16b); // vptatart
+ dTa *= (float)(1<<18);
+ dTa = (dTa / (1 + params.KvPTAT*dvdd) - params.vPTAT25);
+ dTa = dTa / params.KtPTAT; // without 25degr - Ta0
+ SEND("Ta="); float2str(dTa+25., 2); newline();
+ i16a = (int16_t)IMD_VAL(REG_IGAIN);
+ float Kgain = params.gainEE / (float)i16a;
+ SEND("Kgain="); float2str(Kgain, 2); newline();
+ // now make first approximation to image
+ uint16_t pixno = 0; // current pixel number - for indexing in parameters etc
+ for(int row = 0; row < MLX_H; ++row){
+ int idx = (row&1)<<1; // index for params.kv
+ for(int col = 0; col < MLX_W; ++col, ++pixno){
+ uint8_t sp = (row&1)^(col&1); // subpage of current pixel
+ if(sp != subpageno) continue;
+ register float curval = (float)((int16_t)dataarray[pixno]) * Kgain; // gain compensation
+ curval -= params.offset[pixno] * (1.f + params.kta[pixno]*dTa) *
+ (1.f + params.kv[idx|(col&1)]*dvdd); // add offset
+ float IRcompens = curval; // IR_compensated
+ curval -= params.cpOffset[subpageno] * (1.f - params.cpKta * dTa) *
+ (1.f + params.cpKv * dvdd); // CP
+ if(!simpleimage){
+ curval = IRcompens - params.tgc * curval; // IR gradient compens
+ float alphaComp = params.alpha[pixno] - params.tgc * params.cpAlpha[subpageno];
+ alphaComp /= 1.f + params.KsTa * dTa;
+ // calculate To for basic range
+ float Tar = dTa + 273.15f + 25.f;
+ Tar = Tar*Tar*Tar*Tar;
+ float ac3 = alphaComp*alphaComp*alphaComp;
+ float Sx = ac3*IRcompens + alphaComp*ac3*Tar;
+ Sx = params.KsTa * sqrt(sqrt(Sx));
+ float To = IRcompens / (alphaComp * (1.f - params.ksTo[1]) + Sx) + Tar;
+ curval = sqrt(sqrt(To)) - 273.15; // To
+ // TODO: extended
+ }
+ mlx_image[pixno] = curval;
+ }
+ }
+SEND("Tms="); printu(Tms); newline();
+NL();
}
// start image acquiring for next subpage
static int startima(){
DBG("startima()");
+ // write `overwrite` flag twice
if(!write_reg(REG_CONTROL, reg_control_val[subpageno]) ||
+ !write_reg(REG_STATUS, REG_STATUS_OVWEN) ||
!write_reg(REG_STATUS, REG_STATUS_OVWEN)) return FALSE;
return TRUE;
}
/**
* @brief parse_buffer - swap bytes in `dataarray` (after receiving or before transmitting data)
- */
+ *
static void parse_buffer(){
uint16_t *ptr = dataarray;
DBG("parse_buffer()");
@@ -371,7 +407,7 @@ static void parse_buffer(){
#if 0
sendbuf();
#endif
-}
+}*/
/**
* @brief mlx90640_process - main finite-state machine
@@ -382,13 +418,14 @@ void mlx90640_process(){
#define chktmout() do{if(Tms - Tlast > MLX_TIMEOUT){chstate(M_ERROR); DBG("Timeout! -> M_ERROR"); }}while(0)
static int errctr = 0;
static uint32_t Tlast = 0;
+ uint16_t reg, N;
+ /*
uint8_t gotdata = 0;
- uint16_t reg;
if(i2cDMAr == I2C_DMA_READY){ // convert received data into little-endian
i2cDMAr = I2C_DMA_RELAX;
parse_buffer();
gotdata = 1;
- }
+ }*/
switch(mlx_state){
case M_FIRSTSTART: // init working mode by request
if(write_reg(REG_CONTROL, reg_control_val[0])
@@ -396,14 +433,30 @@ void mlx90640_process(){
SEND("REG_CTRL="); printuhex(reg); NL();
if(read_reg(REG_STATUS, ®)){
SEND("REG_STATUS="); printuhex(reg); NL();}
- if(read_data_dma(REG_CALIDATA, REG_CALIDATA_LEN)){
+/*
+#define PARTD 512
+ if(read_data_dma(REG_CALIDATA, PARTD)){
+ chstate(M_READCONF);
+ DBG("-> M_READCONF");
+ }else chkerr();
+*/
+ N = REG_CALIDATA_LEN;
+ if(read_data(REG_CALIDATA, &N)){
chstate(M_READCONF);
DBG("-> M_READCONF");
}else chkerr();
}else chkerr();
break;
case M_READCONF:
- if(gotdata){ // calculate calibration parameters
+ //if(gotdata){ // calculate calibration parameters
+ /* uint16_t *d = &dataarray[PARTD];
+ for(uint16_t r = REG_CALIDATA+PARTD; r < REG_CALIDATA + REG_CALIDATA_LEN; ++r){
+ if(!read_reg(r, d++)){
+ chstate(M_FIRSTSTART);
+ DBG("can't read all confdata -> M_FIRSTSTART");
+ return;
+ }
+ }*/
if(get_parameters()){
chstate(M_RELAX);
DBG("-> M_RELAX");
@@ -411,16 +464,15 @@ void mlx90640_process(){
chstate(M_FIRSTSTART);
DBG("-> M_FIRSTSTART");
}
- }else chktmout();
+ //}else chktmout();
break;
case M_STARTIMA:
- subpageno = 0;
if(startima()){
chstate(M_PROCESS);
DBG("-> M_PROCESS");
}else{
chstate(M_ERROR);
- DBG("can't start sp0 -> M_ERROR");
+ DBG("can't start subpage -> M_ERROR");
}
break;
case M_PROCESS:
@@ -430,7 +482,15 @@ void mlx90640_process(){
chstate(M_ERROR);
DBG("wrong subpage number -> M_ERROR");
}else{ // all OK, run image reading
- if(read_data_dma(REG_IMAGEDATA, MLX_PIXARRSZ)){
+ write_reg(REG_STATUS, 0); // clear rdy bit
+ /*
+ if(read_data_dma(REG_IMAGEDATA, PARTD)){
+ chstate(M_READOUT);
+ DBG("-> M_READOUT");
+ }else chkerr();
+ */
+ N = MLX_PIXARRSZ;
+ if(read_data(REG_IMAGEDATA, &N)){
chstate(M_READOUT);
DBG("-> M_READOUT");
}else chkerr();
@@ -439,21 +499,29 @@ void mlx90640_process(){
}else chkerr();
break;
case M_READOUT:
- if(gotdata){
+ //if(gotdata){
+ /* uint16_t *d = &dataarray[PARTD];
+ for(uint16_t r = REG_IMAGEDATA+PARTD; r < REG_IMAGEDATA+MLX_PIXARRSZ; ++r){
+ if(!read_reg(r, d++)){
+ chstate(M_ERROR);
+ DBG("can't read all confdata -> M_ERROR");
+ return;
+ }
+ }*/
process_subpage();
+ subpageno = !subpageno;
+ DBG("Subpage ready");
+ chstate(M_RELAX);
+ /*
if(++subpageno > 1){ // image ready
+ subpageno = 0;
chstate(M_RELAX);
DBG("Image READY!");
}else{
- if(startima()){
- chstate(M_PROCESS);
- DBG("-> M_PROCESS");
- }else{
- chstate(M_ERROR);
- DBG("can't start sp1 -> M_ERROR");
- }
- }
- }else chktmout();
+ chstate(M_STARTIMA);
+ DBG("-> M_STARTIMA");
+ }*/
+ //}else chktmout();
break;
case M_POWERON:
if(Tms - Tlast > MLX_POWON_WAIT){
@@ -494,12 +562,17 @@ void mlx90640_restart(){
// @param simple ==1 for simplest image processing (without T calibration)
int mlx90640_take_image(uint8_t simple){
simpleimage = simple;
- if(mlx_state != M_RELAX) return FALSE;
+ if(mlx_state == M_ERROR){
+ DBG("Restart I2C");
+ i2c_setup(i2cDMAr != I2C_DMA_NOTINIT);
+ } else if(mlx_state != M_RELAX) return FALSE;
if(params.kVdd == 0){ // no parameters -> make first run
mlx_state = M_FIRSTSTART;
DBG("no params -> M_FIRSTSTART");
return TRUE;
}
+ //subpageno = 0;
mlx_state = M_STARTIMA;
+ DBG("-> M_STARTIMA");
return TRUE;
}
diff --git a/F1:F103/MLX90640/mlx90640.h b/F1:F103/MLX90640/mlx90640.h
index 697dc5d..a277f36 100644
--- a/F1:F103/MLX90640/mlx90640.h
+++ b/F1:F103/MLX90640/mlx90640.h
@@ -31,7 +31,9 @@
#define MLX_POWON_WAIT 2000
// amount of pixels
-#define MLX_PIXNO (24*32)
+#define MLX_W (32)
+#define MLX_H (24)
+#define MLX_PIXNO (MLX_W*MLX_H)
// pixels + service data
#define MLX_PIXARRSZ (MLX_PIXNO + 64)
@@ -48,10 +50,10 @@ typedef struct{
float cpKta; // K_Ta_CP
float KsTa;
float CT[3]; // range borders (0, 160, 320 degrC?)
- float ksTo[4]; // K_S_To for each range
+ float ksTo[4]; // K_S_To for each range * 273.15
float alphacorr[4]; // Alpha_corr for each range
float alpha[MLX_PIXNO]; // full - with alpha_scale
- int16_t offset[MLX_PIXNO];
+ float offset[MLX_PIXNO];
float kta[MLX_PIXNO]; // full K_ta - with scale1&2
float kv[4]; // full - with scale; 0 - odd row, odd col; 1 - odd row even col; 2 - even row, odd col; 3 - even row, even col
float cpAlpha[2]; // alpha_CP_subpage 0 and 1
@@ -85,7 +87,7 @@ extern float mlx_image[MLX_PIXNO];
int read_reg(uint16_t reg, uint16_t *val);
int write_reg(uint16_t reg, uint16_t val);
-int read_data(uint16_t reg, uint16_t *data, int N);
+uint16_t *read_data(uint16_t reg, uint16_t *N);
int read_data_dma(uint16_t reg, int N);
void mlx90640_process();
int mlx90640_take_image(uint8_t simple);
diff --git a/F1:F103/MLX90640/proto.c b/F1:F103/MLX90640/proto.c
index 42c29bd..eb778e3 100644
--- a/F1:F103/MLX90640/proto.c
+++ b/F1:F103/MLX90640/proto.c
@@ -23,8 +23,6 @@
#include "usb.h"
#include "version.inc"
-#define D16LEN (256)
-
extern uint32_t Tms;
static const char* _states[M_STATES_AMOUNT] = {
@@ -51,7 +49,6 @@ static void dumpfarr(float *arr){
}
static void dumpparams(){
- int16_t *pi16;
SEND("\nkVdd="); printi(params.kVdd);
SEND("\nvdd25="); printi(params.vdd25);
SEND("\nKvPTAT="); float2str(params.KvPTAT, 4);
@@ -60,10 +57,10 @@ static void dumpparams(){
SEND("\nalphaPTAT="); float2str(params.alphaPTAT, 2);
SEND("\ngainEE="); printi(params.gainEE);
SEND("\nPixel offset parameters:\n");
- pi16 = params.offset;
+ float *offset = params.offset;
for(int row = 0; row < 24; ++row){
for(int col = 0; col < 32; ++col){
- printi(*pi16++); bufputchar(' ');
+ float2str(*offset++, 2); bufputchar(' ');
}
newline();
}
@@ -94,10 +91,21 @@ static void dumpparams(){
NL();
}
+static void dumpimage(){
+ float *idata = mlx_image;
+ for(int row = 0; row < MLX_H; ++row){
+ for(int col = 0; col < MLX_W; ++col, ++idata){
+ float2str(*idata,1); bufputchar(' ');
+ }
+ newline();
+ }
+ NL();
+}
+
const char *parse_cmd(char *buf){
int32_t Num = 0;
uint16_t r, d;
- uint16_t data[D16LEN];
+ uint16_t *data;
const float pi = 3.1415927f, e = 2.7182818f;
char *ptr, cmd = *buf++;
switch(cmd){
@@ -112,7 +120,7 @@ const char *parse_cmd(char *buf){
if(buf != (ptr = getnum(buf, &Num))){
r = Num;
if(ptr != getnum(ptr, &Num)){
- if(Num < 1) return "N>0";
+ if(Num < 1 || Num > MLX_DMA_MAXLEN) return "0 256) return "N from 0 to 256";
- d = read_data(r, data, Num);
- if(d < Num){
+ if(Num < 1 || Num > MLX_DMA_MAXLEN) return "N from 0 to 832";
+ uint16_t od = d = Num;
+ if(!(data = read_data(r, &d))){
+ SEND("Can't read\n");
+ return NULL;
+ }
+ if(d != od){
addtobuf("Got only ");
printu(d);
addtobuf(" values\n");
@@ -190,6 +202,10 @@ const char *parse_cmd(char *buf){
USB_sendstr("Soft reset\n");
NVIC_SystemReset();
break;
+ case 'S':
+ dumpimage();
+ return NULL;
+ break;
case 'T':
SEND("Tms="); printu(Tms); NL();
return NULL;
@@ -201,17 +217,6 @@ const char *parse_cmd(char *buf){
if(write_reg(r, Num)) return "OK";
else return "Failed";
break;
- case 'W':
- r = 0;
- while(r < D16LEN){
- if(buf == (ptr = getnum(buf, &Num))) break;
- data[r++] = ((Num & 0xff) << 8) | (Num >> 8);
- buf = ptr + 1;
- }
- if(r == 0) return "Need at least one uint8_t";
- if(I2C_OK == i2c_7bit_send((uint8_t*)data, r*2, 1)) return "Sent\n";
- else return "Error\n";
- break;
default: // help
addtobuf(
"MLX90640 build #" BUILD_NUMBER " @" BUILD_DATE "\n\n"
@@ -219,16 +224,16 @@ const char *parse_cmd(char *buf){
"'d reg N' - read registers starting from `reg` using DMA\n"
"'Ee' - expose image: E - full, e - simple\n"
"'f' - test float printf (0.00, 3.1, -2.72, -3.142, 2.7183, -INF, NAN)\n"
- "'g reg N' - read N (<256) registers starting from `reg`\n"
+ "'g reg N' - read N registers starting from `reg`\n"
"'I' - restart I2C\n"
"'M' - MLX state\n"
"'O' - turn On or restart MLX sensor\n"
"'P' - dump params\n"
"'r reg' - read `reg`\n"
"'R' - software reset\n"
+ "'S' - show image\n"
"'T' - get Tms\n"
"'w reg dword' - write `dword` to `reg`\n"
- "'W d0 d1 ...' - write N (<256) 16-bit words directly to I2C\n"
);
NL();
return NULL;
diff --git a/F1:F103/MLX90640/usb.c b/F1:F103/MLX90640/usb.c
index d7e2db2..8a3f90d 100644
--- a/F1:F103/MLX90640/usb.c
+++ b/F1:F103/MLX90640/usb.c
@@ -66,13 +66,15 @@ static int usbwr(const uint8_t *buf, uint16_t l){
while(--ctra && tx_succesfull == 0){
IWDG->KR = IWDG_REFRESH;
}
+ if(tx_succesfull == 0) return 1;
tx_succesfull = 0;
EP_Write(3, buf, l);
- ctra = 1000000;
+ /* ctra = 1000000;
while(--ctra && tx_succesfull == 0){
IWDG->KR = IWDG_REFRESH;
}
if(tx_succesfull == 0){usbON = 0; return 1;} // usb is OFF?
+ */
return 0;
}
diff --git a/F1:F103/MLX90640/version.inc b/F1:F103/MLX90640/version.inc
index 4396fae..0716cf2 100644
--- a/F1:F103/MLX90640/version.inc
+++ b/F1:F103/MLX90640/version.inc
@@ -1,2 +1,2 @@
-#define BUILD_NUMBER "141"
-#define BUILD_DATE "2022-05-19"
+#define BUILD_NUMBER "197"
+#define BUILD_DATE "2022-05-20"