diff --git a/MLX90640_OrangePi/Makefile b/MLX90640_OrangePi/Makefile deleted file mode 100644 index 9ab7bd3..0000000 --- a/MLX90640_OrangePi/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# run `make DEF=...` to add extra defines -PROGRAM := mlx -LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -LDFLAGS += -lwiringPi -lusefull_macros -L/usr/local/lib -lm -lcrypt -SRCS := $(wildcard *.c) -DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 -OBJDIR := mk -CFLAGS += -O2 -Wall -Wextra -Wno-trampolines -std=gnu99 -OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) -DEPS := $(OBJS:.o=.d) -TARGFILE := $(OBJDIR)/TARGET -CC = gcc -#TARGET := RELEASE - -ifeq ($(shell test -e $(TARGFILE) && echo -n yes),yes) - TARGET := $(file < $(TARGFILE)) -else - TARGET := RELEASE -endif - -release: $(PROGRAM) - -debug: CFLAGS += -DEBUG -Werror -debug: TARGET := DEBUG -debug: $(PROGRAM) - -$(TARGFILE): $(OBJDIR) - @echo -e "\t\tTARGET: $(TARGET)" - @echo "$(TARGET)" > $(TARGFILE) - -$(PROGRAM) : $(TARGFILE) $(OBJS) - @echo -e "\t\tLD $(PROGRAM)" - $(CC) $(OBJS) $(LDFLAGS) -o $(PROGRAM) - -$(OBJDIR): - @mkdir $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPS) -endif - -$(OBJDIR)/%.o: %.c - @echo -e "\t\tCC $<" - $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< - -clean: - @echo -e "\t\tCLEAN" - @rm -rf $(OBJDIR) 2>/dev/null || true - -xclean: clean - @rm -f $(PROGRAM) - -.PHONY: clean xclean diff --git a/MLX90640_OrangePi/cmdlnopts.c b/MLX90640_OrangePi/cmdlnopts.c deleted file mode 100644 index 07b8baf..0000000 --- a/MLX90640_OrangePi/cmdlnopts.c +++ /dev/null @@ -1,86 +0,0 @@ -/* geany_encoding=koi8-r - * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters - * - * Copyright 2013 Edward V. Emelianoff - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#include -#include -#include -#include -#include -#include "cmdlnopts.h" -#include "usefull_macros.h" - -/* - * here are global parameters initialisation - */ -static int help; -static glob_pars G; - -// default PID filename: -#define DEFAULT_PIDFILE "/tmp/testcmdlnopts.pid" -#define DEFAULT_I2C "/dev/i2c-3" - -// DEFAULTS -// default global parameters -static glob_pars const Gdefault = { - .device = DEFAULT_I2C, - .pidfile = DEFAULT_PIDFILE, - .logfile = NULL // don't save logs -}; - -/* - * Define command line options by filling structure: - * name has_arg flag val type argptr help -*/ -static myoption cmdlnopts[] = { -// common options - {"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")}, - {"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs")}, - {"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")}, - {"device", NEED_ARG, NULL, 'd', arg_string, APTR(&G.device), _("I2C device path (default: " DEFAULT_I2C ")")}, - end_option -}; - -/** - * Parse command line options and return dynamically allocated structure - * to global parameters - * @param argc - copy of argc from main - * @param argv - copy of argv from main - * @return allocated structure with global parameters - */ -glob_pars *parse_args(int argc, char **argv){ - int i; - void *ptr; - ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); - size_t hlen = 1024; - char helpstring[1024], *hptr = helpstring; - snprintf(hptr, hlen, "Usage: %%s [args]\n\n\tWhere args are:\n"); - // format of help: "Usage: progname [args]\n" - change_helpstring(helpstring); - // parse arguments - parseargs(&argc, &argv, cmdlnopts); - if(help) showhelp(-1, cmdlnopts); - if(argc > 0){ - WARNX("Ignoring arguments:"); - for (i = 0; i < argc; i++) - printf("\t%s\n", argv[i]); - } - return &G; -} - diff --git a/MLX90640_OrangePi/cmdlnopts.h b/MLX90640_OrangePi/cmdlnopts.h deleted file mode 100644 index 3d37d41..0000000 --- a/MLX90640_OrangePi/cmdlnopts.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the mxl90640wPi 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 . - */ - -#pragma once - -/* - * here are some typedef's for global data - */ -typedef struct{ - char *device; // I2C device - char *pidfile; // name of PID file - char *logfile; // logging to this file -} glob_pars; - - -glob_pars *parse_args(int argc, char **argv); - diff --git a/MLX90640_OrangePi/main.c b/MLX90640_OrangePi/main.c deleted file mode 100644 index f4fc2bc..0000000 --- a/MLX90640_OrangePi/main.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of the mxl90640wPi 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 -#include -#include -#include - -#include "cmdlnopts.h" -#include "mlx90640.h" - -#define DEVICE_ID 0x33 - -static glob_pars *GP = NULL; - -void signals(int sig){ - if(sig){ - signal(sig, SIG_IGN); - DBG("Get signal %d, quit.\n", sig); - } - LOGERR("Exit with status %d", sig); - if(GP && GP->pidfile) // remove unnesessary PID file - unlink(GP->pidfile); - exit(sig); -} - -static double image[MLX_PIXNO]; -static double image2[MLX_PIXNO]; -static void pushima(const double *img){ - for(int i = 0; i < MLX_PIXNO; ++i){ - double val = *img++; - image[i] += val; - image2[i] += val*val; - } -} - -int main (int argc, char **argv){ - initial_setup(); - char *self = strdup(argv[0]); - GP = parse_args(argc, argv); - check4running(self, GP->pidfile); - FREE(self); - if(GP->logfile) OPENLOG(GP->logfile, LOGLEVEL_ANY, 1); - - if(!mlx90640_init(GP->device, DEVICE_ID)) ERR("Can't open device"); - //mlx90640_dump_parameters(); -#define N 9 - double T0 = dtime(); - uint8_t simple = 2; - //for(uint8_t simple = 0; simple < 3; ++simple){ - memset(image, 0, sizeof(image)); - memset(image2, 0, sizeof(image)); - for(int i = 0; i < N; ++i){ - double *ima = NULL; - if(!mlx90640_take_image(simple, &ima) || !ima) ERRX("Can't take image"); - pushima(ima); - printf("Got image %d, T=%g\n", i, dtime() - T0); - } - double *im = image, *im2 = image2; - green("\nImage (simple=%d):\n", simple); - for(int row = 0; row < MLX_H; ++row){ - for(int col = 0; col < MLX_W; ++col){ - double v = *im++, v2 = *im2; - v /= N; v2 /= N; - printf("%5.1f ", v); - *im2++ = v2 - v*v; - } - printf("\n"); - } - green("\nRMS:\n"); - im2 = image2; - for(int row = 0; row < MLX_H; ++row){ - for(int col = 0; col < MLX_W; ++col){ - printf("%5.1f ", *im2++); - } - printf("\n"); - } - //} - return 0; -} diff --git a/MLX90640_OrangePi/mlx b/MLX90640_OrangePi/mlx deleted file mode 100755 index 4d751ef..0000000 Binary files a/MLX90640_OrangePi/mlx and /dev/null differ diff --git a/MLX90640_OrangePi/mlx90640.c b/MLX90640_OrangePi/mlx90640.c deleted file mode 100644 index 6dfc8f7..0000000 --- a/MLX90640_OrangePi/mlx90640.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * This file is part of the mxl90640wPi 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mlx90640.h" -#include "mlx90640_regs.h" - - -static int I2Cfd = -1; -static uint8_t lastaddr = 0; -static MLX90640_params params; - -static uint16_t dataarray[MLX_DMA_MAXLEN]; // array for raw data from sensor -static double mlx_image[MLX_PIXNO]; // ready image - -#define CREG_VAL(reg) dataarray[CREG_IDX(reg)] -#define IMD_VAL(reg) dataarray[IMD_IDX(reg)] - -// reg_control values for subpage #0 and #1 -static const uint16_t reg_control_val[2] = { - REG_CONTROL_CHESS | REG_CONTROL_RES18 | REG_CONTROL_REFR_64HZ | REG_CONTROL_SUBPSEL | REG_CONTROL_DATAHOLD | REG_CONTROL_SUBPEN, - REG_CONTROL_CHESS | REG_CONTROL_RES18 | REG_CONTROL_REFR_64HZ | REG_CONTROL_SUBP1 | REG_CONTROL_SUBPSEL | REG_CONTROL_DATAHOLD | REG_CONTROL_SUBPEN -}; - - -static int errctr = 0; -static double Tlast = 0.; -#define chstate() do{errctr = 0; Tlast = dtime(); DBG("chstate()");}while(0) -#define chkerr() do{DBG("chkerr(), T=%g", dtime()-Tlast); if(++errctr > MLX_MAXERR_COUNT){ DBG("-> M_ERROR"); return FALSE;}else continue;}while(0) -#define chktmout() do{DBG("chktmout, T=%g", dtime()-Tlast); if(dtime() - Tlast > MLX_TIMEOUT){ DBG("Timeout! -> M_ERROR"); return FALSE;}else continue;}while(0) - - -// read register value -static int read_reg(uint16_t regaddr, uint16_t *data){ - if(I2Cfd < 1) return FALSE; - struct i2c_msg m[2]; - struct i2c_rdwr_ioctl_data x = {.msgs = m, .nmsgs = 2}; - m[0].addr = lastaddr; m[1].addr = lastaddr; - m[0].flags = 0; - m[1].flags = I2C_M_RD; - m[0].len = 2; m[1].len = 2; - uint8_t a[2], d[2] = {0}; - a[0] = regaddr >> 8; - a[1] = regaddr & 0xff; - m[0].buf = a; m[1].buf = d; - if(ioctl(I2Cfd, I2C_RDWR, &x) < 0) return FALSE; - if(data) *data = (uint16_t)((d[0] << 8) | (d[1])); - return TRUE; -} - - -//#if 0 - // Sometimes don't work :( -// read N values starting from regaddr -static int read_regN(uint16_t regaddr, uint16_t *data, uint16_t N){ - if(I2Cfd < 1 || N > 128 || N == 0) return FALSE; - struct i2c_msg m[2]; - struct i2c_rdwr_ioctl_data x = {.msgs = m, .nmsgs = 2}; - m[0].addr = lastaddr; m[1].addr = lastaddr; - m[0].flags = 0; - m[1].flags = I2C_M_RD; - m[0].len = 2; m[1].len = N * 2; - uint8_t a[2], d[256] = {0}; - a[0] = regaddr >> 8; - a[1] = regaddr & 0xff; - m[0].buf = a; m[1].buf = d; - if(ioctl(I2Cfd, I2C_RDWR, &x) < 0) return FALSE; - if(data) for(int i = 0; i < N; ++i){ - *data++ = (uint16_t)((d[2*i] << 8) | (d[2*i + 1])); - } - return TRUE; -} - -// blocking read N uint16_t values starting from `reg` -// @param reg - register to read -// @param N (io) - amount of bytes to read / bytes read -// @return `dataarray` or NULL if failed -static uint16_t *read_data(uint16_t reg, uint16_t *N){ - if(I2Cfd < 1 || !N || *N < 1) return NULL; - uint16_t n = *N; - if(n < 1 || n > MLX_DMA_MAXLEN) return NULL; - uint16_t *data = dataarray; - uint16_t got = 0, rest = *N; - do{ - uint8_t l = (rest > 128) ? 128 : (uint8_t)rest; - if(!read_regN(reg, data, l)){ - DBG("can't read"); - break; - } - rest -= l; - reg += l; - data += l; - got += l; - }while(rest); - *N = got; - return dataarray; -} -//#endif -#if 0 -// blocking read N uint16_t values starting from `reg` -// @param reg - register to read -// @param N (io) - amount of bytes to read / bytes read -// @return `dataarray` or NULL if failed -static uint16_t *read_data(uint16_t reg, uint16_t *N){ - if(I2Cfd < 1 || !N || *N < 1) return NULL; - uint16_t n = *N; - if(n < 1 || n > MLX_DMA_MAXLEN) return NULL; - uint16_t i, *data = dataarray; - for(i = 0; i < n; ++i){ - if(!read_reg(reg++, data++)){ - DBG("can't read"); - break; - } - } - *N = i; - return dataarray; -} -#endif - - -// write register value -static int write_reg(uint16_t regaddr, uint16_t data){ - if(I2Cfd < 1) return FALSE; - union i2c_smbus_data d; - d.block[0] = 3; - d.block[1] = regaddr & 0xff; - d.block[2] = data >> 8; - d.block[3] = data & 0xff; - struct i2c_smbus_ioctl_data args; - args.read_write = I2C_SMBUS_WRITE; - args.command = regaddr >> 8; - args.size = I2C_SMBUS_I2C_BLOCK_DATA; - args.data = &d; - if(ioctl(I2Cfd, I2C_SMBUS, &args) < 0) return FALSE; - return TRUE; -} - -int mlx90640_set_slave_address(uint8_t addr){ - if(I2Cfd < 1) return FALSE; - if(ioctl (I2Cfd, I2C_SLAVE, addr) < 0) return FALSE; - lastaddr = addr; - return TRUE; -} - -static void dumpIma(double *im){ - for(int row = 0; row < MLX_H; ++row){ - for(int col = 0; col < MLX_W; ++col){ - printf("%5.1f ", *im++); - } - printf("\n"); - } -} - -void mlx90640_dump_parameters(){ - printf("kVdd=%d\nvdd25=%d\nKvPTAT=%g\nKtPTAT=%g\nvPTAT25=%d\n", params.kVdd, params.vdd25, params.KvPTAT, params.KtPTAT, params.vPTAT25); - printf("alphaPTAT=%g\ngainEE=%d\ntgc=%g\ncpKv=%g\ncpKta=%g\n", params.alphaPTAT, params.gainEE, params.tgc, params.cpKta, params.cpKta); - printf("KsTa=%g\nCT[]={%g, %g, %g}\n", params.KsTa, params.CT[0], params.CT[1], params.CT[2]); - printf("ksTo[]={"); for(int i = 0; i < 4; ++i) printf("%s%g", (i) ? ", " : "", params.ksTo[i]); printf("}\n"); - printf("alphacorr[]={"); for(int i = 0; i < 4; ++i) printf("%s%g", (i) ? ", " : "", params.alphacorr[i]); printf("}\n"); - printf("alpha[]=\n"); dumpIma(params.alpha); - printf("offset[]=\n"); dumpIma(params.offset); - printf("kta[]=\n"); dumpIma(params.kta); - printf("kv[]={"); for(int i = 0; i < 4; ++i) printf("%s%g", (i) ? ", " : "", params.kv[i]); printf("}\n"); - printf("cpAlpha[]={%g, %g}\n", params.cpAlpha[0], params.cpAlpha[1]); - printf("cpOffset[]={%d, %d}\n", params.cpOffset[0], params.cpOffset[1]); - printf("outliers[]=\n"); - uint8_t *o = params.outliers; - for(int row = 0; row < MLX_H; ++row){ - for(int col = 0; col < MLX_W; ++col){ - printf("%d ", *o++); - } - printf("\n"); - } -} - -/***************************************************************************** - Calculate parameters & values - *****************************************************************************/ - -// fill OCC/ACC row/col arrays -static void occacc(int8_t *arr, int l, uint16_t *regstart){ - int n = l >> 2; // divide by 4 - int8_t *p = arr; - for(int i = 0; i < n; ++i){ - register uint16_t val = *regstart++; - *p++ = (val & 0x000F) >> 0; - *p++ = (val & 0x00F0) >> 4; - *p++ = (val & 0x0F00) >> 8; - *p++ = (val ) >> 12; - } - for(int i = 0; i < l; ++i, ++arr){ - if(*arr > 0x07) *arr -= 0x10; - } -} - -// get all parameters' values from `dataarray`, return FALSE if something failed -static int get_parameters(){ - int8_t i8; - int16_t i16; - uint16_t *pu16; - uint16_t val = CREG_VAL(REG_VDD); - i8 = (int8_t) (val >> 8); - params.kVdd = i8 * 32; // keep sign - if(params.kVdd == 0) return FALSE; - i16 = val & 0xFF; - params.vdd25 = ((i16 - 0x100) * 32) - (1<<13); - val = CREG_VAL(REG_KVTPTAT); - i16 = (val & 0xFC00) >> 10; - if(i16 > 0x1F) i16 -= 0x40; - params.KvPTAT = (double)i16 / (1<<12); - i16 = (val & 0x03FF); - if(i16 > 0x1FF) i16 -= 0x400; - params.KtPTAT = (double)i16 / 8.; - params.vPTAT25 = (int16_t) CREG_VAL(REG_PTAT); - val = CREG_VAL(REG_APTATOCCS) >> 12; - params.alphaPTAT = val / 4. + 8.; - params.gainEE = (int16_t)CREG_VAL(REG_GAIN); - if(params.gainEE == 0) return FALSE; - 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: - double occRemScale = 1<<(val&0x0F), - occColumnScale = 1<<((val>>4)&0x0F), - occRowScale = 1<<((val>>8)&0x0F); - int16_t offavg = (int16_t) CREG_VAL(REG_OSAVG); - // even/odd column/row numbers are for starting from 1, so for starting from 0 we chould swap them: - // even - for 1,3,5,...; odd - for 0,2,4,... etc - int8_t ktaavg[4]; - // 0 - odd row, odd col; 1 - odd row even col; 2 - even row, odd col; 3 - even row, even col - val = CREG_VAL(REG_KTAAVGODDCOL); - ktaavg[2] = (int8_t)(val & 0xFF); // odd col, even row -> col 0,2,..; row 1,3,.. - ktaavg[0] = (int8_t)(val >> 8); // odd col, odd row -> col 0,2,..; row 0,2,.. - val = CREG_VAL(REG_KTAAVGEVENCOL); - ktaavg[3] = (int8_t)(val & 0xFF); // even col, even row -> col 1,3,..; row 1,3,.. - ktaavg[1] = (int8_t)(val >> 8); // even col, odd row -> col 1,3,..; row 0,2,.. - // so index of ktaavg is 2*(row&1)+(col&1) - val = CREG_VAL(REG_KTAVSCALE); - uint8_t scale1 = ((val & 0xFF)>>4) + 8, scale2 = (val&0xF); - if(scale1 == 0 || scale2 == 0) return FALSE; - double mul = (double)(1<> 12); - diva *= (double)(1<<30); // alpha_scale - double accRowScale = 1<<((val & 0x0f00)>>8), - accColumnScale = 1<<((val & 0x00f0)>>4), - accRemScale = 1<<(val & 0x0f); - pu16 = &CREG_VAL(REG_OFFAK1); - double *kta = params.kta, *offset = params.offset; - uint8_t *ol = params.outliers; - for(int row = 0; row < MLX_H; ++row){ - int idx = (row&1)<<1; - for(int col = 0; col < MLX_W; ++col){ - // offset - register uint16_t rv = *pu16++; - i16 = (rv & 0xFC00) >> 10; - if(i16 > 0x1F) i16 -= 0x40; - *offset++ = (double)offavg + (double)occRow[row]*occRowScale + (double)occColumn[col]*occColumnScale + (double)i16*occRemScale; - // kta - i16 = (rv & 0xF) >> 1; - if(i16 > 0x03) i16 -= 0x08; - *kta++ = (ktaavg[idx|(col&1)] + i16*mul) / div; - // alpha - i16 = (rv & 0x3F0) >> 4; - if(i16 > 0x1F) i16 -= 0x40; - double oft = (double)a_r + accRow[row]*accRowScale + accColumn[col]*accColumnScale +i16*accRemScale; - *a++ = oft / diva; - *ol++ = (rv&1) ? 1 : 0; - } - } - scale1 = (CREG_VAL(REG_KTAVSCALE) >> 8) & 0xF; // kvscale - div = (double)(1<> 12; if(i16 > 0x07) i16 -= 0x10; - ktaavg[0] = (int8_t)i16; // odd col, odd row - i16 = (val & 0xF0) >> 4; if(i16 > 0x07) i16 -= 0x10; - ktaavg[1] = (int8_t)i16; // even col, odd row - i16 = (val & 0x0F00) >> 8; if(i16 > 0x07) i16 -= 0x10; - ktaavg[2] = (int8_t)i16; // odd col, even row - i16 = val & 0x0F; if(i16 > 0x07) i16 -= 0x10; - ktaavg[3] = (int8_t)i16; // even col, even row - for(int i = 0; i < 4; ++i) params.kv[i] = ktaavg[i] / div; - val = CREG_VAL(REG_CPOFF); - params.cpOffset[0] = (val & 0x03ff); - if(params.cpOffset[0] > 0x1ff) params.cpOffset[0] -= 0x400; - params.cpOffset[1] = val >> 10; - if(params.cpOffset[1] > 0x1f) params.cpOffset[1] -= 0x40; - params.cpOffset[1] += params.cpOffset[0]; - val = ((CREG_VAL(REG_KTAVSCALE) & 0xF0) >> 4) + 8; - i8 = (int8_t)(CREG_VAL(REG_KVTACP) & 0xFF); - params.cpKta = (double)i8 / (1<> 8; - i16 = CREG_VAL(REG_KVTACP) >> 8; - if(i16 > 0x7F) i16 -= 0x100; - params.cpKv = (double)i16 / (1< 0x7F) i16 -= 0x100; - params.tgc = (double)i16; - params.tgc /= 32.; - val = (CREG_VAL(REG_SCALEACC)>>12); // alpha_scale_CP - i16 = CREG_VAL(REG_ALPHA)>>10; // cp_P1_P0_ratio - if(i16 > 0x1F) i16 -= 0x40; - div = (double)(1<> 8); - params.KsTa = (double)i8/(1<<13); - div = 1<<((CREG_VAL(REG_CT34) & 0x0F) + 8); // kstoscale - DBG("kstoscale=%g (regct34=0x%04x)", div, CREG_VAL(REG_CT34)); - val = CREG_VAL(REG_KSTO12); - DBG("ksto12=0x%04x", val); - i8 = (int8_t)(val & 0xFF); - DBG("To1ee=%d", i8); - params.ksTo[0] = i8 / div; - i8 = (int8_t)(val >> 8); - DBG("To2ee=%d", i8); - params.ksTo[1] = i8 / div; - val = CREG_VAL(REG_KSTO34); - DBG("ksto34=0x%04x", val); - i8 = (int8_t)(val & 0xFF); - DBG("To3ee=%d", i8); - params.ksTo[2] = i8 / div; - i8 = (int8_t)(val >> 8); - DBG("To4ee=%d", i8); - params.ksTo[3] = i8 / div; - params.CT[0] = 0.; // 0degr - between ranges 1 and 2 - val = CREG_VAL(REG_CT34); - mul = ((val & 0x3000)>>12)*10.; // step - params.CT[1] = ((val & 0xF0)>>4)*mul; // CT3 - between ranges 2 and 3 - params.CT[2] = ((val & 0x0F00) >> 8)*mul + params.CT[1]; // CT4 - between ranges 3 and 4 - params.alphacorr[0] = 1./(1. + params.ksTo[0] * 40.); - params.alphacorr[1] = 1.; - params.alphacorr[2] = (1. + params.ksTo[2] * params.CT[1]); - params.alphacorr[3] = (1. + params.ksTo[3] * (params.CT[2] - params.CT[1])) * params.alphacorr[2]; - // Don't forget to check 'outlier' flags for wide purpose - return TRUE; -} - -/** - * @brief process_subpage - calculate all parameters from `dataarray` into `mlx_image` - * @param subpageno - number of subpage - * @param simpleimage == 0 - simplest, 1 - narrow range, 2 - extended range - */ -static void process_subpage(int subpageno, int simpleimage){ - DBG("\nprocess_subpage(%d)", subpageno); -#ifdef EBUG - chstate(); -#endif - int16_t i16a = (int16_t)IMD_VAL(REG_IVDDPIX); - double dvdd = i16a - params.vdd25; - dvdd = dvdd / params.kVdd; - DBG("Vd=%g", dvdd+3.3); - i16a = (int16_t)IMD_VAL(REG_ITAPTAT); - int16_t i16b = (int16_t)IMD_VAL(REG_ITAVBE); - double dTa = (double)i16a / (i16a * params.alphaPTAT + i16b); // vptatart - dTa *= (double)(1<<18); - dTa = (dTa / (1 + params.KvPTAT*dvdd) - params.vPTAT25); - dTa = dTa / params.KtPTAT; // without 25degr - Ta0 - DBG("Ta=%g", dTa+25.); - i16a = (int16_t)IMD_VAL(REG_IGAIN); - double Kgain = params.gainEE / (double)i16a; - DBG("Kgain=%g", Kgain); - // 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; - double curval = (double)((int16_t)dataarray[pixno]) * Kgain; // gain compensation - curval -= params.offset[pixno] * (1. + params.kta[pixno]*dTa) * - (1. + params.kv[idx|(col&1)]*dvdd); // add offset - double IRcompens = curval; // IR_compensated - if(simpleimage == 0){ - curval -= params.cpOffset[subpageno] * (1. - params.cpKta * dTa) * - (1. + params.cpKv * dvdd); // CP - curval = IRcompens - params.tgc * curval; // IR gradient compens - }else{ - double alphaComp = params.alpha[pixno] - params.tgc * params.cpAlpha[subpageno]; - alphaComp /= 1. + params.KsTa * dTa; - // calculate To for basic range - double Tar = dTa + 273.15 + 25.; - Tar = Tar*Tar*Tar*Tar; - double ac3 = alphaComp*alphaComp*alphaComp; - double Sx = ac3*IRcompens + alphaComp*ac3*Tar; - Sx = params.KsTa * sqrt(sqrt(Sx)); - double To = IRcompens / (alphaComp * (1. - 273.15*params.ksTo[1]) + Sx) + Tar; - curval = sqrt(sqrt(To)) - 273.15; // To - // extended range - if(simpleimage == 2){ - int idx = 0; // range 1 by default - double ctx = -40.; - if(curval > params.CT[0] && curval < params.CT[1]){ // range 2 - idx = 1; ctx = params.CT[0]; - }else if(curval < params.CT[2]){ // range 3 - idx = 2; ctx = params.CT[1]; - }else{ // range 4 - idx = 3; ctx = params.CT[2]; - } - To = IRcompens / (alphaComp * params.alphacorr[idx] * (1. + params.ksTo[idx]*(curval - ctx))) + Tar; - curval = sqrt(sqrt(To)) - 273.15; - } - } - mlx_image[pixno] = curval; - } - } - DBG("Time: %g", dtime()-Tlast); -} - -static int process_readconf(){ - chstate(); - while(1){ - if(get_parameters()) return TRUE; - else chkerr(); - } -} -static int process_firstrun(){ - uint16_t reg, N; - write_reg(REG_CONTROL, REG_CONTROL_DEFAULT); - usleep(50); - write_reg(REG_CONTROL, REG_CONTROL_DEFAULT); - usleep(50); - chstate(); - while(1){ - if(write_reg(REG_CONTROL, reg_control_val[0]) - && read_reg(REG_CONTROL, ®)){ - DBG("REG_CTRL=0x%04x, T=%g", reg, dtime()-Tlast); - if(read_reg(REG_STATUS, ®)) DBG("REG_STATUS=0x%04x", reg); - N = REG_CALIDATA_LEN; - if(read_data(REG_CALIDATA, &N)){ - DBG("-> M_READCONF, T=%g", dtime()-Tlast); - return process_readconf(); - }else chkerr(); - }else chkerr(); - } - return FALSE; -} -// start image acquiring for next subpage -static int process_startima(int subpageno){ - chstate(); - DBG("startima(%d)", subpageno); - uint16_t reg, N; - while(1){ - // 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)) chkerr(); - while(1){ - if(read_reg(REG_STATUS, ®)){ - if(reg & REG_STATUS_NEWDATA){ - DBG("got newdata: %g", dtime() - Tlast); - if(subpageno != (reg & REG_STATUS_SPNO)){ - DBG("wrong subpage number -> M_ERROR"); - return FALSE; - }else{ // all OK, run image reading - chstate(); - write_reg(REG_STATUS, 0); // clear rdy bit - N = MLX_PIXARRSZ; - if(read_data(REG_IMAGEDATA, &N) && N == MLX_PIXARRSZ){ - DBG("got readoutm N=%d: %g", N, dtime() - Tlast); - return TRUE; - }else chkerr(); - } - }else chktmout(); - }else chkerr(); - } - } - return FALSE; -} - -void mlx90640_restart(){ - memset(¶ms, 0, sizeof(params)); - process_firstrun(); -} - -// if state of MLX allows, make an image else return error -// @param simple ==1 for simplest image processing (without T calibration) -int mlx90640_take_image(uint8_t simple, double **image){ - if(I2Cfd < 1) return FALSE; - if(params.kVdd == 0){ // no parameters -> make first run - if(!process_firstrun()) return FALSE; - } - DBG("\n\n\n-> M_STARTIMA"); - for(int sp = 0; sp < 2; ++sp){ - if(!process_startima(sp)) return FALSE; // get first subpage - process_subpage(sp, simple); - } - if(image) *image = mlx_image; - return TRUE; -} - -int mlx90640_init(const char *dev, uint8_t ID){ - if(I2Cfd > 0) close(I2Cfd); - I2Cfd = open(dev, O_RDWR); - if(I2Cfd < 1) return FALSE; - if(!mlx90640_set_slave_address(ID)) return FALSE; - if(!read_reg(0, NULL)) return FALSE; - if(!process_firstrun()) return FALSE; - return TRUE; -} - diff --git a/MLX90640_OrangePi/mlx90640.h b/MLX90640_OrangePi/mlx90640.h deleted file mode 100644 index e906462..0000000 --- a/MLX90640_OrangePi/mlx90640.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of the mxl90640wPi 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 . - */ - -#pragma once - -#include - -// timeout for reading operations, s -#define MLX_TIMEOUT 5. -// counter of errors, when > max -> M_ERROR -#define MLX_MAXERR_COUNT 10 -// wait after power off, s -#define MLX_POWOFF_WAIT 0.5 -// wait after power on, s -#define MLX_POWON_WAIT 2. - -// amount of pixels -#define MLX_W (32) -#define MLX_H (24) -#define MLX_PIXNO (MLX_W*MLX_H) -// pixels + service data -#define MLX_PIXARRSZ (MLX_PIXNO + 64) - -typedef struct{ - int16_t kVdd; - int16_t vdd25; - double KvPTAT; - double KtPTAT; - int16_t vPTAT25; - double alphaPTAT; - int16_t gainEE; - double tgc; - double cpKv; // K_V_CP - double cpKta; // K_Ta_CP - double KsTa; - double CT[3]; // range borders (0, 160, 320 degrC?) - double ksTo[4]; // K_S_To for each range * 273.15 - double alphacorr[4]; // Alpha_corr for each range - double alpha[MLX_PIXNO]; // full - with alpha_scale - double offset[MLX_PIXNO]; - double kta[MLX_PIXNO]; // full K_ta - with scale1&2 - double 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 - double cpAlpha[2]; // alpha_CP_subpage 0 and 1 - int16_t cpOffset[2]; - uint8_t outliers[MLX_PIXNO]; // outliers - bad pixels (if == 1) -} MLX90640_params; - -// default I2C address -#define MLX_DEFAULT_ADDR (0x33) -// max datalength by one read (in 16-bit values) -#define MLX_DMA_MAXLEN (832) - -void mlx90640_dump_parameters(); -int mlx90640_init(const char *dev, uint8_t ID); -int mlx90640_set_slave_address(uint8_t addr); -int mlx90640_take_image(uint8_t simple, double **image); -void mlx90640_restart(); diff --git a/MLX90640_OrangePi/mlx90640_regs.h b/MLX90640_OrangePi/mlx90640_regs.h deleted file mode 100644 index d5b657c..0000000 --- a/MLX90640_OrangePi/mlx90640_regs.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the mxl90640wPi 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 . - */ - -#pragma once - -#define REG_STATUS 0x8000 -#define REG_STATUS_OVWEN (1<<4) -#define REG_STATUS_NEWDATA (1<<3) -#define REG_STATUS_SPNO (1<<0) -#define REG_STATUS_SPMASK (3<<0) -#define REG_CONTROL 0x800D -#define REG_CONTROL_CHESS (1<<12) -#define REG_CONTROL_RES18 (2<<10) -#define REG_CONTROL_RESMASK (3<<10) -#define REG_CONTROL_REFR_05HZ (0<<7) -#define REG_CONTROL_REFR_1HZ (1<<7) -#define REG_CONTROL_REFR_2HZ (2<<7) -#define REG_CONTROL_REFR_4HZ (3<<7) -#define REG_CONTROL_REFR_8HZ (4<<7) -#define REG_CONTROL_REFR_16HZ (5<<7) -#define REG_CONTROL_REFR_32HZ (6<<7) -#define REG_CONTROL_REFR_64HZ (7<<7) -#define REG_CONTROL_SUBP1 (1<<4) -#define REG_CONTROL_SUBPMASK (3<<4) -#define REG_CONTROL_SUBPSEL (1<<3) -#define REG_CONTROL_DATAHOLD (1<<2) -#define REG_CONTROL_SUBPEN (1<<0) - -// default value -#define REG_CONTROL_DEFAULT (REG_CONTROL_CHESS|REG_CONTROL_RES18|REG_CONTROL_REFR_2HZ|REG_CONTROL_SUBPEN) - -// calibration data start & len -#define REG_CALIDATA 0x2410 -#define REG_CALIDATA_LEN 816 - -#define REG_APTATOCCS 0x2410 -#define REG_OSAVG 0x2411 -#define REG_OCCROW14 0x2412 -#define REG_OCCCOL14 0x2418 -#define REG_SCALEACC 0x2420 -#define REG_SENSIVITY 0x2421 -#define REG_ACCROW14 0x2422 -#define REG_ACCCOL14 0x2428 -#define REG_GAIN 0x2430 -#define REG_PTAT 0x2431 -#define REG_KVTPTAT 0x2432 -#define REG_VDD 0x2433 -#define REG_KVAVG 0x2434 -#define REG_ILCHESS 0x2435 -#define REG_KTAAVGODDCOL 0x2436 -#define REG_KTAAVGEVENCOL 0x2437 -#define REG_KTAVSCALE 0x2438 -#define REG_ALPHA 0x2439 -#define REG_CPOFF 0x243A -#define REG_KVTACP 0x243B -#define REG_KSTATGC 0x243C -#define REG_KSTO12 0x243D -#define REG_KSTO34 0x243E -#define REG_CT34 0x243F -#define REG_OFFAK1 0x2440 -// index of register in array (from REG_CALIDATA) -#define CREG_IDX(addr) ((addr)-REG_CALIDATA) - -#define REG_IMAGEDATA 0x0400 -#define REG_ITAVBE 0x0700 -#define REG_ICPSP0 0x0708 -#define REG_IGAIN 0x070A -#define REG_ITAPTAT 0x0720 -#define REG_ICPSP1 0x0728 -#define REG_IVDDPIX 0x072A -// indeg of register in array (from REG_IMAGEDATA) -#define IMD_IDX(addr) ((addr)-REG_IMAGEDATA) diff --git a/MLX90640_OrangePi/mxl90640OPi.cflags b/MLX90640_OrangePi/mxl90640OPi.cflags deleted file mode 100644 index 68d5165..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.cflags +++ /dev/null @@ -1 +0,0 @@ --std=c17 \ No newline at end of file diff --git a/MLX90640_OrangePi/mxl90640OPi.config b/MLX90640_OrangePi/mxl90640OPi.config deleted file mode 100644 index e93f8a9..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.config +++ /dev/null @@ -1,4 +0,0 @@ -#define GNU_SOURCE 1 -#define _XOPEN_SOURCE 1111 -#define EBUG - diff --git a/MLX90640_OrangePi/mxl90640OPi.creator b/MLX90640_OrangePi/mxl90640OPi.creator deleted file mode 100644 index e94cbbd..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.creator +++ /dev/null @@ -1 +0,0 @@ -[General] diff --git a/MLX90640_OrangePi/mxl90640OPi.creator.user b/MLX90640_OrangePi/mxl90640OPi.creator.user deleted file mode 100644 index 88d3f4b..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.creator.user +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - EnvironmentId - {7bd84e39-ca37-46d3-be9d-99ebea85bc0d} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - KOI8-R - false - 4 - false - 80 - true - true - 1 - false - true - false - 0 - true - true - 0 - 8 - true - false - 1 - true - false - true - *.md, *.MD, Makefile - false - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - - 0 - true - - true - Builtin.BuildSystem - - true - true - Builtin.DefaultTidyAndClazy - 2 - - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - Desktop - {65a14f9e-e008-4c1b-89df-4eaa4774b6e3} - 0 - 0 - 0 - - /tmp/1/home/eddy/MLX90640_wiringPi - - - - all - - true - GenericProjectManager.GenericMakeStep - - 1 - Сборка - Сборка - ProjectExplorer.BuildSteps.Build - - - - - clean - - true - GenericProjectManager.GenericMakeStep - - 1 - Очистка - Очистка - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - По умолчанию - GenericProjectManager.GenericBuildConfiguration - - 1 - - - 0 - Развёртывание - Развёртывание - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - 2 - - ProjectExplorer.CustomExecutableRunConfiguration - - false - true - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - diff --git a/MLX90640_OrangePi/mxl90640OPi.cxxflags b/MLX90640_OrangePi/mxl90640OPi.cxxflags deleted file mode 100644 index 6435dfc..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.cxxflags +++ /dev/null @@ -1 +0,0 @@ --std=c++17 \ No newline at end of file diff --git a/MLX90640_OrangePi/mxl90640OPi.files b/MLX90640_OrangePi/mxl90640OPi.files deleted file mode 100644 index d70565e..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.files +++ /dev/null @@ -1,6 +0,0 @@ -cmdlnopts.c -cmdlnopts.h -main.c -mlx90640.c -mlx90640.h -mlx90640_regs.h diff --git a/MLX90640_OrangePi/mxl90640OPi.includes b/MLX90640_OrangePi/mxl90640OPi.includes deleted file mode 100644 index 774cf29..0000000 --- a/MLX90640_OrangePi/mxl90640OPi.includes +++ /dev/null @@ -1,2 +0,0 @@ -/usr/local/include -. diff --git a/stringHash4MCU_/Readme b/stringHash4MCU_/Readme index 4e7cf15..53cb74b 100644 --- a/stringHash4MCU_/Readme +++ b/stringHash4MCU_/Readme @@ -1,6 +1,7 @@ -hashtest.c allows to test different hash functions on your dictionary +hashtest.c allows to test different hash functions on your dictionary (test En_words for example) hashgen.c will generate two files by dictionary: source and header -use test.c to test generated files + +another files used for test: use script ./run for it Compile: gcc -lusefull_macro file.c -o file gcc -lusefull_macro test.c hash.c -o test diff --git a/stringHash4MCU_/hashgen.c b/stringHash4MCU_/hashgen.c index f922161..ac4ee7f 100644 --- a/stringHash4MCU_/hashgen.c +++ b/stringHash4MCU_/hashgen.c @@ -169,21 +169,39 @@ static char *fnname(const char *cmd){ } static const char *fhdr = -"int parsecmd(char *cmd, char *args){\n\ - if(!cmd || !args) return 0;\n\ - uint32_t h = hashf(cmd);\n\ - switch(h){\n" +"int parsecmd(const char *str){\n\ + char cmd[CMD_MAXLEN + 1];\n\ + if(!str || !*str) return RET_CMDNOTFOUND;\n\ + int i = 0;\n\ + while(*str > '@' && i < CMD_MAXLEN){ cmd[i++] = *str++; }\n\ + cmd[i] = 0;\n\ + if(*str){\n\ + while(*str <= ' ') ++str;\n\ + }\n\ + char *args = (char*) str;\n\ + uint32_t h = hashf(cmd);\n\ + switch(h){\n\n" ; static const char *ffooter = -" default: return 0;\n\ +" default: break;\n\ }\n\ - return 0;\n\ + return RET_CMDNOTFOUND;\n\ }\n\n" ; static const char *fns = "int fn_%s(_U_ uint32_t hash, _U_ char *args) WAL; // \"%s\" (%u)\n\n" ; -static const char *fproto = "int parsecmd(char *cmdwargs, char *args);\n\n"; +static const char *headercontent = "#ifndef _U_\n\ +#define _U_ __attribute__((__unused__))\n\ +#endif\n\n\ +#define CMD_MAXLEN (32)\n\n\ +enum{\n\ + RET_CMDNOTFOUND = -2,\n\ + RET_WRONGCMD = -1,\n\ + RET_BAD = 0,\n\ + RET_GOOD = 1\n\ +};\n\n\ +int parsecmd(const char *cmdwargs);\n\n"; static const char *sw = " case CMD_%s:\n\ return fn_%s(h, args);\n\ @@ -192,9 +210,6 @@ static const char *srchdr = "#include \n\ #include \n\ #include \"%s\"\n\n\ -#ifndef _U_\n\ -#define _U_ __attribute__((__unused__))\n\ -#endif\n\n\ #ifndef WAL\n\ #define WAL __attribute__ ((weak, alias (\"__f1\")))\n\ #endif\n\nstatic int __f1(_U_ uint32_t h, _U_ char *a){return 1;}\n\n" @@ -220,7 +235,7 @@ static void build(strhash *H, int hno, int hlen){ fprintf(source, fns, H[i].fname, H[i].str, H[i].hash); } } - fprintf(header, "%s", fproto); + fprintf(header, "%s", headercontent); fprintf(source, "%s\n", hashsources[hno]); fprintf(source, "%s", fhdr); for(int i = 0; i < hlen; ++i){ diff --git a/stringHash4MCU_/run b/stringHash4MCU_/run new file mode 100755 index 0000000..e79297c --- /dev/null +++ b/stringHash4MCU_/run @@ -0,0 +1,10 @@ +#!/bin/bash + +gcc hashgen.c -o hashgen -lusefull_macros +./hashgen -d testdic -H hdr.h -S hdr.c -F +gcc hdr.c test.c strfunc.c -o test +./test "time 54 = some" +./test "voltage12 more" +./test "esw45 = some text" +./test "goto 55 = " +./test "stop 3256" diff --git a/stringHash4MCU_/strfunc.c b/stringHash4MCU_/strfunc.c new file mode 100644 index 0000000..5b9e9f1 --- /dev/null +++ b/stringHash4MCU_/strfunc.c @@ -0,0 +1,256 @@ +#include "strfunc.h" + +/** + * @brief hexdump - dump hex array by 16 bytes in string + * @param sendfun - function to send data + * @param arr - array to dump + * @param len - length of `arr` + */ +void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){ + char buf[52], *bptr = buf; + for(uint16_t l = 0; l < len; ++l, ++arr){ + for(int16_t j = 1; j > -1; --j){ + register uint8_t half = (*arr >> (4*j)) & 0x0f; + if(half < 10) *bptr++ = half + '0'; + else *bptr++ = half - 10 + 'a'; + } + if(l % 16 == 15){ + *bptr++ = '\n'; + *bptr = 0; + sendfun(buf); + bptr = buf; + }else *bptr++ = ' '; + } + if(bptr != buf){ + *bptr++ = '\n'; + *bptr = 0; + sendfun(buf); + } +} + +/** + * @brief _2str - convert value into string buffer + * @param val - |value| + * @param minus - ==0 if value > 0 + * @return buffer with number + */ +static char *_2str(uint32_t val, uint8_t minus){ + static char strbuf[12]; + char *bufptr = &strbuf[11]; + *bufptr = 0; + if(!val){ + *(--bufptr) = '0'; + }else{ + while(val){ + uint32_t x = val / 10; + *(--bufptr) = (val - 10*x) + '0'; + val = x; + //*(--bufptr) = val % 10 + '0'; + //val /= 10; + } + } + if(minus) *(--bufptr) = '-'; + return bufptr; +} + +// return string with number `val` +char *u2str(uint32_t val){ + return _2str(val, 0); +} +char *i2str(int32_t i){ + uint8_t minus = 0; + uint32_t val; + if(i < 0){ + minus = 1; + val = -i; + }else val = i; + return _2str(val, minus); +} + +/** + * @brief uhex2str - print 32bit unsigned int as hex + * @param val - value + * @return string with number + */ +char *uhex2str(uint32_t val){ + static char buf[12] = "0x"; + int npos = 2; + uint8_t *ptr = (uint8_t*)&val + 3; + int8_t i, j, z=1; + for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; + for(j = 1; j > -1; --j){ + uint8_t half = (*ptr >> (4*j)) & 0x0f; + if(half < 10) buf[npos++] = half + '0'; + else buf[npos++] = half - 10 + 'a'; + } + } + buf[npos] = 0; + return buf; +} + +/** + * @brief omit_spaces - eliminate leading spaces and other trash in string + * @param buf - string + * @return - pointer to first character in `buf` > ' ' + */ +const char *omit_spaces(const char *buf){ + while(*buf){ + if(*buf > ' ') break; + ++buf; + } + return buf; +} + +/** + * @brief getdec - read decimal number & return pointer to next non-number symbol + * @param buf - string + * @param N - number read + * @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff + */ +static const char *getdec(const char *buf, uint32_t *N){ + char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '9'){ + break; + } + if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow + *N = 0xffffff; + return start; + } + num *= 10; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read hexadecimal number (without 0x prefix!) +static const char *gethex(const char *buf, uint32_t *N){ + const char *start = buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + uint8_t M = 0; + if(c >= '0' && c <= '9'){ + M = '0'; + }else if(c >= 'A' && c <= 'F'){ + M = 'A' - 10; + }else if(c >= 'a' && c <= 'f'){ + M = 'a' - 10; + } + if(M){ + if(num & 0xf0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 4; + num += c - M; + }else{ + break; + } + ++buf; + } + *N = num; + return buf; +} +// read octal number (without 0 prefix!) +static const char *getoct(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '7'){ + break; + } + if(num & 0xe0000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 3; + num += c - '0'; + ++buf; + } + *N = num; + return buf; +} +// read binary number (without b prefix!) +static const char *getbin(const char *buf, uint32_t *N){ + const char *start = (char*)buf; + uint32_t num = 0; + while(*buf){ + char c = *buf; + if(c < '0' || c > '1'){ + break; + } + if(num & 0x80000000){ // overflow + *N = 0xffffff; + return start; + } + num <<= 1; + if(c == '1') num |= 1; + ++buf; + } + *N = num; + return buf; +} + +/** + * @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111) + * @param buf - buffer with number and so on + * @param N - the number read + * @return pointer to first non-number symbol in buf + * (if it is == buf, there's no number or if *N==0xffffffff there was overflow) + */ +const char *getnum(const char *txt, uint32_t *N){ + const char *nxt = NULL; + const char *s = omit_spaces(txt); + if(*s == '0'){ // hex, oct or 0 + if(s[1] == 'x' || s[1] == 'X'){ // hex + nxt = gethex(s+2, N); + if(nxt == s+2) nxt = (char*)txt; + }else if(s[1] > '0'-1 && s[1] < '8'){ // oct + nxt = getoct(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ // 0 + nxt = s+1; + *N = 0; + } + }else if(*s == 'b' || *s == 'B'){ + nxt = getbin(s+1, N); + if(nxt == s+1) nxt = (char*)txt; + }else{ + nxt = getdec(s, N); + if(nxt == s) nxt = (char*)txt; + } + return nxt; +} + +// get signed integer +const char *getint(const char *txt, int32_t *I){ + const char *s = omit_spaces(txt); + int32_t sign = 1; + uint32_t U; + if(*s == '-'){ + sign = -1; + ++s; + } + const char *nxt = getnum(s, &U); + if(nxt == s) return txt; + if(U & 0x80000000) return txt; // overfull + *I = sign * (int32_t)U; + return nxt; +} + +/* +void mymemcpy(char *dest, const char *src, int len){ + if(len < 1) return; + while(len--) *dest++ = *src++; +} +*/ diff --git a/stringHash4MCU_/strfunc.h b/stringHash4MCU_/strfunc.h new file mode 100644 index 0000000..a067ff8 --- /dev/null +++ b/stringHash4MCU_/strfunc.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len); +char *u2str(uint32_t val); +char *i2str(int32_t i); +char *uhex2str(uint32_t val); +const char *getnum(const char *txt, uint32_t *N); +const char *omit_spaces(const char *buf); +const char *getint(const char *txt, int32_t *I); +//void mymemcpy(char *dest, const char *src, int len); diff --git a/stringHash4MCU_/test.c b/stringHash4MCU_/test.c index 0f6f881..3dc0dda 100644 --- a/stringHash4MCU_/test.c +++ b/stringHash4MCU_/test.c @@ -2,22 +2,61 @@ #include #include -#include "hash.h" +#include "hdr.h" +#include "strfunc.h" -int fn_hello(uint32_t hash, char *args){ - printf("HELLO! Hash=%u, param=%s\n", hash, args); +static int noargs(uint32_t hash){ + switch(hash){ + case CMD_REBOOT: printf("REBOOT\n"); break; + case CMD_TIME: printf("TIME!\n"); break; + case CMD_TEMP: printf("Temp\n"); break; + default: printf("Unknown hash 0x%x\n", hash); return 0; + } return 1; } -int fn_world(uint32_t hash, char *args){ - printf("WORLD: %u - %s\n", hash, args); - return 1; +static int withparno(uint32_t hash, char *args){ + uint32_t N; + //printf("args=%s\n", args); + const char *nxt = getnum((const char*)args, &N); + if(nxt == args){ printf("need arg\n"); return RET_WRONGCMD; } + args = (char*)omit_spaces(nxt); + if(*args){ + if(*args != '='){ printf("need nothing or '=' after par\n"); return RET_WRONGCMD; } + args = (char*)omit_spaces(args+1); + // we can check in next functions what if `args` will be an empty string + } + else args = NULL; + const char *fname = NULL; + switch(hash){ + case CMD_ESW: fname = "ESW"; break; + case CMD_GOTO: fname = "GOTO"; break; + case CMD_POS: fname = "POS"; break; + case CMD_STOP: fname = "STOP"; break; + default: fname = "unknown"; + } + if(!args) printf("We want a getter '%s' with par %u\n", fname, N); + else printf("We want a setter '%s' with par %u and arg '%s'\n", fname, N, args); + if(N > 255){ printf("N should be 0..255\n"); return RET_BAD;} + return RET_GOOD; } +// these functions should be global to substitute weak aliases +int fn_esw(uint32_t hash, char *args){return withparno(hash, args);} +int fn_goto(uint32_t hash, char *args){return withparno(hash, args);} +int fn_pos(uint32_t hash, char *args){return withparno(hash, args);} +int fn_stop(uint32_t hash, char *args){return withparno(hash, args);} +int fn_voltage(uint32_t hash, char *args){return withparno(hash, args);} +int fn_reboot(uint32_t hash, _U_ char *args){return noargs(hash);} +int fn_time(uint32_t hash, _U_ char *args){return noargs(hash);} +int fn_temp(uint32_t hash, _U_ char *args){return noargs(hash);} int main(int argc, char **argv){ - if(argc < 2) return 1; - char *args = ""; - if(argc > 2) args = argv[2]; - if(!parsecmd(argv[1], args)) printf("%s not found\n", argv[1]); - else printf("All OK\n"); + if(argc != 2) return 1; + int ret = parsecmd(argv[1]); + switch(ret){ + case RET_CMDNOTFOUND: printf("'%s' not found\n", argv[1]); break; + case RET_WRONGCMD: printf("Wrong sintax of '%s'\n", argv[1]); break; + case RET_GOOD: printf("'%s' - OK\n", argv[1]); break; + default: printf("'%s' - bad\n", argv[1]); + } return 0; } diff --git a/stringHash4MCU_/testdic b/stringHash4MCU_/testdic index 153cc32..bb2b5b1 100644 --- a/stringHash4MCU_/testdic +++ b/stringHash4MCU_/testdic @@ -1,13 +1,8 @@ -hello -world -what -put -sim key -change ip -change param -set - clear -reset - get -out -in +pos +temp +voltage +time +reboot +stop +goto +esw