/* * This file is part of the MLX90640 project. * Copyright 2022 Edward V. Emelianov . * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "i2c.h" #include "mlx90640.h" #include "proto.h" #include "strfunct.h" #include "usb.h" #include "version.inc" extern uint32_t Tms; static const char* _states[M_STATES_AMOUNT] = { [M_ERROR] = "error", [M_RELAX] = "do nothing", [M_FIRSTSTART] = "first start", [M_READCONF] = "read config", [M_STARTIMA] = "start image", [M_PROCESS] = "process subframe", [M_READOUT] = "read subpage data", [M_POWERON] = "wait after power on", [M_POWEROFF1] = "turn power off", [M_POWEROFF] = "wait without power", }; // dump floating point array 24x32 static void dumpfarr(float *arr){ for(int row = 0; row < 24; ++row){ for(int col = 0; col < 32; ++col){ float2str(*arr++, 2); bufputchar(' '); } newline(); } } static void dumpparams(){ SEND("\nkVdd="); printi(params.kVdd); SEND("\nvdd25="); printi(params.vdd25); SEND("\nKvPTAT="); float2str(params.KvPTAT, 4); SEND("\nKtPTAT="); float2str(params.KtPTAT, 4); SEND("\nvPTAT25="); printi(params.vPTAT25); SEND("\nalphaPTAT="); float2str(params.alphaPTAT, 2); SEND("\ngainEE="); printi(params.gainEE); SEND("\nPixel offset parameters:\n"); float *offset = params.offset; for(int row = 0; row < 24; ++row){ for(int col = 0; col < 32; ++col){ float2str(*offset++, 2); bufputchar(' '); } newline(); } SEND("K_talpha:\n"); dumpfarr(params.kta); SEND("Kv: "); for(int i = 0; i < 4; ++i){ float2str(params.kv[i], 2); bufputchar(' '); } SEND("\ncpOffset="); printi(params.cpOffset[0]); SEND(", "); printi(params.cpOffset[1]); SEND("\ncpKta="); float2str(params.cpKta, 2); SEND("\ncpKv="); float2str(params.cpKv, 2); SEND("\ntgc="); float2str(params.tgc, 2); SEND("\ncpALpha="); float2str(params.cpAlpha[0], 2); SEND(", "); float2str(params.cpAlpha[1], 2); SEND("\nKsTa="); float2str(params.KsTa, 2); SEND("\nAlpha:\n"); dumpfarr(params.alpha); SEND("\nCT3="); float2str(params.CT[1], 2); SEND("\nCT4="); float2str(params.CT[2], 2); for(int i = 0; i < 4; ++i){ SEND("\nKsTo"); bufputchar('0'+i); bufputchar('='); float2str(params.ksTo[i], 2); SEND("\nalphacorr"); bufputchar('0'+i); bufputchar('='); float2str(params.alphacorr[i], 2); } 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; const float pi = 3.1415927f, e = 2.7182818f; char *ptr, cmd = *buf++; switch(cmd){ case 'a': if(buf != getnum(buf, &Num)){ if(Num & 0x80) return "Enter 7bit address"; i2c_set_addr7(Num); return "Changed"; }else return "Wrong address"; break; case 'd': if(buf != (ptr = getnum(buf, &Num))){ r = Num; if(ptr != getnum(ptr, &Num)){ if(Num < 1 || Num > MLX_DMA_MAXLEN) return "0 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"); } for(uint16_t i = 0; i < d; ++i){ printuhex(r + i); addtobuf(" "); printuhex(data[i]); newline(); } sendbuf(); return NULL; }else return "Need amount"; }else return "Need reg"; break; case 'I': i2c_setup(TRUE); return "I2C restarted"; break; case 'M': SEND("MLX state: "); SEND(_states[mlx_state]); SEND("\npower="); printu(MLXPOW_VAL()); NL(); return NULL; break; case 'O': mlx90640_restart(); return "Power off/on"; break; case 'P': dumpparams(); return NULL; break; case 'r': if(buf != (ptr = getnum(buf, &Num))){ if(read_reg(Num, &d)){ printuhex(d); NL(); return NULL; }else return "Can't read"; }else return "Need register address"; break; case 'R': USB_sendstr("Soft reset\n"); NVIC_SystemReset(); break; case 'S': dumpimage(); return NULL; break; case 'T': SEND("Tms="); printu(Tms); NL(); return NULL; break; case 'w': if(buf == (ptr = getnum(buf, &Num))) return "Need register"; r = Num; if(ptr == getnum(ptr, &Num)) return "Need data"; if(write_reg(r, Num)) return "OK"; else return "Failed"; break; default: // help addtobuf( "MLX90640 build #" BUILD_NUMBER " @" BUILD_DATE "\n\n" "'a addr' - change MLX I2C address to `addr`\n" "'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 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" ); NL(); return NULL; break; } return NULL; }