From 75dc072d17e8be75198418da0906a4c299cc7e99 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Wed, 29 Nov 2023 09:35:17 +0300 Subject: [PATCH] add USB settings for parameters --- F1:F103/shutter/flash.c | 184 ++++++++++++++++++++++++++++++++++ F1:F103/shutter/flash.h | 42 ++++++++ F1:F103/shutter/hardware.h | 11 +- F1:F103/shutter/main.c | 1 + F1:F103/shutter/proto.c | 62 ++++++++++-- F1:F103/shutter/shutter.bin | Bin 8104 -> 10016 bytes F1:F103/shutter/shutter.c | 6 +- F1:F103/shutter/shutter.files | 2 + F1:F103/shutter/version.inc | 4 +- 9 files changed, 291 insertions(+), 21 deletions(-) create mode 100644 F1:F103/shutter/flash.c create mode 100644 F1:F103/shutter/flash.h diff --git a/F1:F103/shutter/flash.c b/F1:F103/shutter/flash.c new file mode 100644 index 0000000..68972cb --- /dev/null +++ b/F1:F103/shutter/flash.c @@ -0,0 +1,184 @@ +/* + * This file is part of the shutter project. + * Copyright 2023 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 "stm32f1.h" + +#include "flash.h" +#include "proto.h" +#include "usb.h" // printout +#include // memcpy + +extern const uint32_t __varsstart, _BLOCKSIZE; +static const uint32_t FLASH_blocksize = (uint32_t)&_BLOCKSIZE; +static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here + +#define USERCONF_INITIALIZER { \ + .userconf_sz = sizeof(user_conf) \ + ,.hallactive = 0 \ + ,.ccdactive = 1 \ + ,.minvoltage = 500 \ + ,.workvoltage = 1300 \ + } + +static int write2flash(const void*, const void*, uint32_t); +const user_conf *Flash_Data = (const user_conf *)(&__varsstart); +user_conf the_conf = USERCONF_INITIALIZER; + +static int currentconfidx = -1; // index of current configuration + +/** + * @brief binarySearch - binary search in flash for last non-empty cell + * any struct searched should have its sizeof() @ the first field!!! + * @param l - left index + * @param r - right index (should be @1 less than last index!) + * @param start - starting address + * @param stor_size - size of structure to search + * @return index of non-empty cell or -1 + */ +static int binarySearch(int r, const uint8_t *start, int stor_size){ + int l = 0; + while(r >= l){ + int mid = l + (r - l) / 2; + const uint8_t *s = start + mid * stor_size; + if(*((const uint16_t*)s) == stor_size){ + if(*((const uint16_t*)(s + stor_size)) == 0xffff){ // next is free + return mid; + }else{ // element is to the right + l = mid + 1; + } + }else{ // element is to the left + r = mid - 1; + } + } + return -1; // not found +} + +/** + * @brief flashstorage_init - initialization of user conf storage + * run in once @ start + */ +void flashstorage_init(){ + if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ + uint32_t flsz = FLASH_SIZE * 1024; // size in bytes + flsz -= (uint32_t)(&__varsstart) - FLASH_BASE; + maxCnum = flsz / sizeof(user_conf); + } + // -1 if there's no data at all & flash is clear; maxnum-1 if flash is full + currentconfidx = binarySearch((int)maxCnum-2, (const uint8_t*)Flash_Data, sizeof(user_conf)); + if(currentconfidx > -1){ + memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf)); + } +} + +// store new configuration +// @return 0 if all OK +int store_userconf(){ + // maxnum - 3 means that there always should be at least one empty record after last data + // for binarySearch() checking that there's nothing more after it! + if(currentconfidx > (int)maxCnum - 3){ // there's no more place + currentconfidx = 0; + if(erase_storage(-1)) return 1; + }else ++currentconfidx; // take next data position (0 - within first run after firmware flashing) + return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf)); +} + +static int write2flash(const void *start, const void *wrdata, uint32_t stor_size){ + int ret = 0; + if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } + while (FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags + FLASH->CR |= FLASH_CR_PG; + const uint16_t *data = (const uint16_t*) wrdata; + volatile uint16_t *address = (volatile uint16_t*) start; + uint32_t i, count = (stor_size + 1) / 2; + for(i = 0; i < count; ++i){ + *(volatile uint16_t*)(address + i) = data[i]; + while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + if(*(volatile uint16_t*)(address + i) != data[i]){ + USB_sendstr("Error: flash is corrupted\n"); + ret = 1; + break; + } + if(FLASH->SR & FLASH_SR_PGERR){ + USB_sendstr("Error: FLASH_SR_PGERR\n"); + ret = 1; // program error - meet not 0xffff + break; + } + FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; + } + FLASH->CR &= ~(FLASH_CR_PG); + return ret; +} + +// erase Nth page of flash storage (flash should be prepared!) +static int erase_pageN(int N){ + int ret = 0; + FLASH->AR = (uint32_t)Flash_Data + N*FLASH_blocksize; + FLASH->CR |= FLASH_CR_STRT; + while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + FLASH->SR = FLASH_SR_EOP; + if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */ + ret = 1; + FLASH->SR = FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/ + } + return ret; +} + +// erase full storage (npage < 0) or its nth page; @return 0 if all OK +int erase_storage(int npage){ + int ret = 0; + uint32_t end = 1, start = 0, flsz = 0; + if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ + flsz = FLASH_SIZE * 1024; // size in bytes + flsz -= (uint32_t)Flash_Data - FLASH_BASE; + } + end = flsz / FLASH_blocksize; + if(end == 0 || end >= FLASH_SIZE) return 1; + if(npage > -1){ // erase only one page + if((uint32_t)npage >= end) return 1; + start = npage; + end = start + 1; + } + if((FLASH->CR & FLASH_CR_LOCK) != 0){ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } + while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; + FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; + FLASH->CR |= FLASH_CR_PER; + for(uint32_t i = start; i < end; ++i){ + if(erase_pageN(i)){ + ret = 1; + break; + } + } + FLASH->CR &= ~FLASH_CR_PER; + return ret; +} + +void dump_userconf(){ + USB_sendstr("userconf_sz="); USB_sendstr(u2str(the_conf.userconf_sz)); + USB_sendstr("\nccdactive="); USB_putbyte('0' + the_conf.ccdactive); + USB_sendstr("\nhallactive="); USB_putbyte('0' + the_conf.hallactive); + USB_sendstr("\nminvoltage="); USB_sendstr(u2str(the_conf.minvoltage)); + USB_sendstr("\nworkvoltage="); USB_sendstr(u2str(the_conf.workvoltage)); + newline(); +} diff --git a/F1:F103/shutter/flash.h b/F1:F103/shutter/flash.h new file mode 100644 index 0000000..e24fce7 --- /dev/null +++ b/F1:F103/shutter/flash.h @@ -0,0 +1,42 @@ +/* + * This file is part of the shutter project. + * Copyright 2023 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 + +#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0) +#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG) + +/* + * struct to save user configurations + */ +typedef struct __attribute__((packed, aligned(4))){ + uint16_t userconf_sz; // "magick number" + uint8_t ccdactive : 1; // ccd active (open shutter at): 0 - low, 1 - high + uint8_t hallactive : 1; // hall sensor active (shutter is opened when): 0 - low, 1 - high + uint16_t minvoltage; // minimal voltage on C (*100) + uint16_t workvoltage; // working voltage (*100) +} user_conf; + +extern user_conf the_conf; + +void flashstorage_init(); +int store_userconf(); +int erase_storage(int npage); +void dump_userconf(); diff --git a/F1:F103/shutter/hardware.h b/F1:F103/shutter/hardware.h index 79d00f7..bc5fb4e 100644 --- a/F1:F103/shutter/hardware.h +++ b/F1:F103/shutter/hardware.h @@ -20,6 +20,8 @@ #include +#include "flash.h" + // PA7 - SHTR_FB #define FBPORT GPIOA #define FBPIN (1<<7) @@ -52,17 +54,12 @@ typedef enum{ #define BTNPORT GPIOB #define HALLPIN (1<<0) #define CCDPIN (1<<11) -#define CHKHALL() (BTNPORT->IDR & HALLPIN ? 0 : 1) -#define CHKCCD() (BTNPORT->IDR & CCDPIN ? 0 : 1) +#define CHKHALL() ((HALLPIN == (BTNPORT->IDR & HALLPIN)) == the_conf.hallactive) +#define CHKCCD() ((CCDPIN == (BTNPORT->IDR & CCDPIN)) == the_conf.ccdactive) // multiplyer of shutter voltage (due to R divider) #define SHTRVMUL (13) -// minimal voltage on capacitor for shutter can work -#define SHTR_WORK_VOLTAGE (1300) -// minimal voltage on capacitor due to discharging -#define SHTR_MIN_VOLTAGE (100) - extern volatile uint32_t Tms; void hw_setup(); diff --git a/F1:F103/shutter/main.c b/F1:F103/shutter/main.c index 9fb59cb..04d102d 100644 --- a/F1:F103/shutter/main.c +++ b/F1:F103/shutter/main.c @@ -39,6 +39,7 @@ int main(void){ SysTick_Config(72000); USBPU_OFF(); hw_setup(); + flashstorage_init(); USB_setup(); USBPU_ON(); diff --git a/F1:F103/shutter/proto.c b/F1:F103/shutter/proto.c index f441fc9..0dee2de 100644 --- a/F1:F103/shutter/proto.c +++ b/F1:F103/shutter/proto.c @@ -17,6 +17,7 @@ */ #include "adc.h" +#include "flash.h" #include "hardware.h" #include "proto.h" #include "shutter.h" @@ -158,6 +159,13 @@ const char* helpmsg = "'0' - shutter CLO\n" "'1' - shutter OPE\n" "'2' - shutter HIZ\n" + "'< n' - voltage on discharged capacitor (*100)\n" + "'> n' - voltage on fully charged capacitor (*100)\n" + "'c n' - open shutter when CCD ext level is n (0/1)\n" + "'d' - dump current config\n" + "'e' - erase flash storage\n" + "'h n' - shutter is opened when hall level is n (0/1)\n" + "'s' - save configuration into flash\n" "'A' - get raw ADC values\n" "'C' - close shutter / abort exposition\n" "'E n' - expose for n milliseconds\n" @@ -206,6 +214,17 @@ const char *parse_cmd(const char *buf){ SHTRHIZ(); add2buf("regstate=hiz"); break; + case 'd': // dump config + dump_userconf(); return NULL; + break; + case 'e': // erase flash + if(erase_storage(-1)) add2buf(ERR); + else add2buf(OK); + break; + case 's': // save configuration + if(store_userconf()) add2buf(ERR); + else add2buf(OK); + break; case 'A': for(int i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i){ add2buf("\nadc"); @@ -262,15 +281,38 @@ const char *parse_cmd(const char *buf){ } }else{ // long messages uint32_t Num = 0; - char *nxt; - switch(*buf){ + char c = *buf++; + char *nxt = getnum(buf, &Num); + int errnum = 0, overflow = 0; + if(buf == nxt){ + if(Num) overflow = 1; + errnum = 1; + } + switch(c){ + case '<': // min voltage + if(errnum) break; + if(Num < 100 || Num > 1000) return "ERRVAL\n"; + the_conf.minvoltage = Num; + add2buf("minvoltage="); add2buf(u2str(the_conf.minvoltage)); + break; + case '>': // max voltage + if(errnum) break; + if(Num < 500 || Num > 10000) return "ERRVAL\n"; + the_conf.workvoltage = Num; + add2buf("workvoltage="); add2buf(u2str(the_conf.workvoltage)); + break; + case 'c': // CCD active @ + if(errnum) break; + the_conf.ccdactive = Num; + add2buf("ccdactive="); bufputchar('0' + the_conf.ccdactive); + break; + case 'h': // HALL active @ + if(errnum) break; + the_conf.hallactive = Num; + add2buf("hallactive="); bufputchar('0' + the_conf.hallactive); + break; case 'E': - ++buf; - nxt = getnum(buf, &Num); - if(buf == nxt){ - if(Num == 0) return "ERRNUM\n"; - return "I32OVERFLOW\n"; - } + if(errnum) break; if(shutterstate != SHUTTER_RELAX){ add2buf(ERR); break; @@ -279,8 +321,10 @@ const char *parse_cmd(const char *buf){ else add2buf(ERR); break; default: - return buf; + return buf-1; } + if(overflow) return "I32OVERFLOW\n"; + if(errnum) return "ERRNUM\n"; } bufputchar('\n'); return stbuf; diff --git a/F1:F103/shutter/shutter.bin b/F1:F103/shutter/shutter.bin index 2b2301669c2ef52a712176829eb22f315caf3488..78419b01098f447a0f2eb6459905988d753d5bb0 100755 GIT binary patch delta 6264 zcmb_gdstIfw%_NR03k#Hv6eDZ2X6NP*6(INe&lG@bi2?TNq%DHPNV9|EI`QzSv z-#X{)z1QAr?X}nXt+lf+e{TVUvJn0Ja3nlTBH{jf2;K9;JeY7deru9`KIh&w{zIGj znb0rd|Ids5Y|VeK#N+?p!rTRfno%J{BQsK=Wk@xrC&Q9slvFLu*mLwHHF24s9donv z?6ET;WX+sU1uNtS)%AVdJu@!7sh)OmtWjbg5l^+sb#lXE^HMWyxMaJU5Z`L(IY86% zX!9jodqQ8!6uHEJ#$GZ*?}Rihota{9=L-EQmP9F*B^Jrkb~URaC6+5TZ-Sup0*5?T zY!?%HTiVTSwiGr6iM%N?g1%x-G^E+(EJ>wV*wX|JH02|8_MCsTbq4$q{vq%TArin* z)1*pHtkxX-!w=_?!d*>FB~xxD~X0(4#wqoR2Ct~j-9 z&>XNBT?c+MUxHM#AqOcK5_}h@x!3^0L6)5if()6BGUk&zlLCGq3f1 z&J{o5I8A8z$ba|U44_5?jCg{sC%Kd~_-sk4OXdsiUnkBbg6{If`!n9<(S+}PJ%PbR z6~|JHl}Fs%H;R|J1mtFg=?^vcqpWT(K~qN*r~OVovV~^@6w4#rMvW@>dx^gqdxAjp z`E%#aAz7TUlG`jrbzcP(GOF{rluGV7sbel)-tAA!!rF?A_u(dGxX5i)5_zA&(=ito zs<(^Q5X4z`Yf=QB=f!!VF2Nqui+*VBoWYT7H%4u_4l z@W(i%Vx-~yK1zNh=uRGSX@t?uH4wJCL&sAMsrpn4DJAGj+*au}Zi=~*Ye;S4JW|JL zM1!H^35IlS1=pZ-oHm6$M4Tbj5(pqM0UDxI+Vp*M0oD}>2^9@~>Mk3m(Blq290`7p zOn^bz#2YT%C&t6w3C|05No?xQWQRKJ%6&j9F_V75o=SCGn_v%-CvYd(-llq54;m%5 zU6iKvfcxe!4I_9x4tR*X`tHq)z)fDHZ0{01tw_4dxYU-em9Z4L)V$QDW=VJpUK`3Q zxH#KJv0_S?6ZWwW^N}03(O6U1Wl5m78Mhg>7c4hdaPr5=kVj2+w=HfG~+e($ZHEFM9@k-%H=uYgH1>{ zxyzUEhb3eFtY&>ECumK$N}Vk+R(?w%(r;qE2kbl5i2c#EQ?2THue_DvQaoEVs;=YZH*B*rcFYln_?by_&V&dd z=`YnF_Hel{ND*lq@n5GxqU3HL%Jy_#aFwe+ZOpL~A%c8Ah{#VHFQy;uMhxoOU7n|l z+s{X?_5mueCtR~LQ0UF_*SRby$?^mmuVVMOaBEm-q*%;RDQG;SVyj&!2eBWzco~w9 z)oN0Yxh5O2^S7%yFKx4CtJoj5@iMCv!Wp%5AAV-*LWp_CxDA>qT4HL3mg0!f z2n3Abh=)*i*awU>`RHd|h(zqg1|<8f<$wj74~@?cud2mX3%QVdE0?A8h6sx3URL{( zj*tAYkB{uWje;s63RVdPljgOxe;dyx8uzaM4dNp&-8Qkqgu*_=QR7_3a>lR~Tqw zF+&TgC>sJ;l@`vE+QOZcJuPvok6nuOoRd|nYrRpAmLj^DJD1BxX57Y(CIuI3u)H@o zQ@TeoJ*WDzS!U21j3P@6Ki>fC8^q9RwYbs55+d-9$3=MmOMJ2YH|OSq0r}p1BNcp6 zbcJ((!MI)#%}28PoI{o$nUmjRsXfL`R_xX^!ci;@P+GUTv1d;04R>AYeavIE;#ky7 z7LD)mt>_rsyQ*e<0Li}&07f|F(MXxqt5RD#kbI5hAU;|p%E=Fps*N3LYG5>IbEG%A zW%rnlbZG65wpzGma^$ph2_Ly14*T7xhTh)Y0c`gjE@iP+0eNBHEo_?#7Z`sfw$IJ$ z*pXQ|Ms6BK9UXA~?ATax#g6WWvBi*RRY2-aLYLJ`awXphh3PCIWWtZuKqMYH7*bH$ z93A*n8v7@57rEa3#EARdsuA&VA!;sq2De6xg0H#g)wsWq8el_`UaZ@u4y6`>nKN&t)Zxv0b8+w5>ln?j{ut4YbkqYs*?Xm9r&g0K z@S@K0%IOeP4{fW_)fhhwp=4oWy0$fN$aomQyb0AarwGeILv6k+HqAGfu$b3BF|ii4b-g zLWmcNA6Oym!=ecv;!E3t1Qc>s7z}4Pv8O^!g-Gga zpGlTy*Xrc}C3%(^M!>|JlVBq%p7N$f@gI_q42*4+IOYZVBj4V#)oEnY^m#)#|8T@&+=u{>oDjazNR>2}YZG;l!fOcpmPX$9RMxy_5<*~_a|4y zsGXa0=BN5%qIV3OKa>~UKAqtK$3;%)!77MZLX0!`N)0R~Q^?3i$;aT_;w6qHjxl~h zDujfx{6~~E!@ESQG)%-c8yySF{P46I0Iz7l@<<2FkwM=PC7Z>-Mg_Kh2&$hj`h1e~YuD54-|!lGuZ$l~i7*?s!qcOBU6!-HoYx&D*z z)Is5vnb-RxI-b&g(J^Hps*W=_oS=cj2&cg@@W$aJ2EwPe>H$D6}xQsqJ}q7Em^2uILi|~w)B$z$Q(W) z(4b@bBOmqW!Ic^#oJMw1fAX#!y>VwpuU`KIMD6T97QKKIZ~+el>h({UiBOgD3G>wJ zNFKEIM~ZtXEy~IdPdwZfux96nnL{>sZaEaUZ_zh6x$)z!Xxq6R6=>2juSou(UcqRI znQE;NlFtGRlu;}obCW^}VtWS8PgNYDr~-_~84H2W?kJxjtKvw75a1cc=-t}Sfp3ci zc$JH_{Sglj(fwZfNrn6ss3xCNeo_Zw#j~_|aMp2tVj5&jF~Jc@qrA9sMp;a^?-b-E z%3Gz)(88H1lR`w&$qt^TGzvc8|xUJYbutD@uo3ILZ4jl<)g2Q=BwdmU}l zv)6cMX1|Qnw~+Er&t49#?LKwqn1%bgd!5zlWo^9dS!p|WOQPn^>AQv_^a?l>M` zH5Ayq-A>fgZU2sbnE(}(Q8$yY2OPD8SQ0D=cS3|Z1eUD__xLm?A5XbotB zs`CTaOz7Es(wZIT#j1^|#k;Hx;3pqBaU8!fm^8UGvI)9qFvfBuL3vY#=EyXOgY@I5 zkN^;Gfm`Frle;&OOdiTw=Z)z*%HI%*OWqr@h(}*O1z-6+zuRwOpAx6D4%6PCSbW5X z_aY7o)3J-K-H&fPr(hp@L$ii|-DYAHVo0&zHz4WKqgcG<2<0Z-g@f+Twa;J(+T;WHMPnt ztd6iz2SpfG=-~l{h~(g9K*i(LY9^ck7tkM1xB#$vPVlm|-~-n@3h;r+gFXQGH#$GO zp?2_^1vwl}lYC5(3#N)+;*dD(ftg_Tm2gwJc0vvzc=1+$DUTXZ(Muz<> z(`NtOjC=Y6JGH;>P-q2G;OnQf`|6OCm#6DS8k)JY6>uDD{!tf=0fL0@9$)hfW<@TN z;nGmzcqG8fl68rC%(lFam(fPxt z&?-7tk()PBshpVmYxnNak1^Bfb(!=;dSgj(nPqhmU9yfYw3k|K7U$}sLfUF^SgiK4 z5+|KCUa3%Ii!x{ajD6LH;^OD%e?P+-n^EE@T1S`KHk6eWIq7F@(3m}Y4qe1-Dx-^w zHWn4r_ELHsou!zp1Sy4BrNRws9kg|W(^<5xjJB4nTV-D@$}GYoMNUg;5xuI|Qfi}1 zK|4@flxd5}859A_VUe(js4$zQxcCE;>Ox+1H!&|)pKZ!DUDL|DLJ1COn>uN$ywjQ80R=b9lMaAL@0 zL`dUwmN=&l>;-hTmN=ao9A!m?aDD@0+Ih1U>Q*dVkh0?OxiAd|M3zD;$Z-Ge!6)ZF zWwDphtKfv3MJr26%A&_URQ5e`(GZ={5S`sWJb2o04gTQU2ebvq0b~Xe#itM;ONAeA zgUfvgbO`8Upi@9+fxJLlfp!4B4zwHov(0#A%E&lKxg^XR_>H9QZVM3+CV&Yq?E>QA F_rKSi#qj_D delta 4344 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 SHUTTER_TIME || V < SHTR_MIN_VOLTAGE){ + if(Tms - Tstart > SHUTTER_TIME || V < the_conf.minvoltage){ SHTROFF(); shutterstate = SHUTTER_WAIT; Tstart = Tms; @@ -125,7 +125,7 @@ void process_shutter(){ uint8_t s = CHKCCD(); if(oldbtnstate == s) return; // button's state not changed // check button only when can open/close & shutter operations done - if(V >= SHTR_WORK_VOLTAGE && shutterstate == SHUTTER_RELAX){ // shutter state allows to open/close + if(V >= the_conf.workvoltage && shutterstate == SHUTTER_RELAX){ // shutter state allows to open/close if(s){ // pressed if(!CHKHALL()){ if(open_shutter()){oldbtnstate = s; /*USB_sendstr(" open, old->1\n");*/}} else{/*USB_sendstr("pressed when CHKHALL(), old->1\n");*/ oldbtnstate = s;} diff --git a/F1:F103/shutter/shutter.files b/F1:F103/shutter/shutter.files index bff2394..1274a33 100644 --- a/F1:F103/shutter/shutter.files +++ b/F1:F103/shutter/shutter.files @@ -1,5 +1,7 @@ adc.c adc.h +flash.c +flash.h hardware.c hardware.h main.c diff --git a/F1:F103/shutter/version.inc b/F1:F103/shutter/version.inc index 65002d8..4ae7bc7 100644 --- a/F1:F103/shutter/version.inc +++ b/F1:F103/shutter/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "80" -#define BUILD_DATE "2023-09-22" +#define BUILD_NUMBER "84" +#define BUILD_DATE "2023-11-29"