/* * 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 "adc.h" #include "hardware.h" #include "proto.h" #include "shutter.h" #include "usb.h" static const char *states[SHUTTER_STATE_AMOUNT] = { [SHUTTER_ERROR] = "error", [SHUTTER_RELAX] = "relax", [SHUTTER_PROCESS] = "process", [SHUTTER_WAIT] = "wait", [SHUTTER_EXPOSE] = "exposing", }; static const char *regstates[4] = { [REG_OPEN] = "open", [REG_CLOSE] = "close", [REG_OFF] = "off", [REG_HIZ] = "hiZ" }; static const char *opcl[2] = {"closed", "opened"}; shutter_state shutterstate = SHUTTER_RELAX; static shutter_state nextstate = SHUTTER_RELAX; static uint32_t Tstart = 0, Texp = 0, Topened = 0; /** * @brief changestate - open/close shutter and set next state to nxt * @return TRUE if success */ static int changestate(int open, shutter_state nxt){ if(shutterstate != SHUTTER_RELAX && shutterstate != SHUTTER_EXPOSE) return FALSE; // don't ready if(open == CHKHALL()){ //shutterstate = SHUTTER_RELAX; return TRUE; // already opened or closed } if(getShutterVoltage() < the_conf.workvoltage) return FALSE; //if(shutterstate == SHUTTER_ERROR) return FALSE; if(open) SHTROPEN(); else SHTRCLOSE(); shutterstate = SHUTTER_PROCESS; nextstate = nxt; Tstart = Tms; return TRUE; } /** * @brief open_shutter, close shutter - change shutter state * @return false if can't work due to error (no shutter) or insufficient voltage */ int open_shutter(){ return changestate(1, SHUTTER_RELAX); } int close_shutter(){ return changestate(0, SHUTTER_RELAX); } int expose_shutter(uint32_t exptime){ if(!changestate(1, SHUTTER_EXPOSE)) return FALSE; Texp = exptime; return TRUE; } void process_shutter(){ static uint32_t T = 0; uint32_t V = getShutterVoltage(); switch(shutterstate){ case SHUTTER_ERROR: // error state: no shutter? - switch HIZ/OFF each 10ms if(SHTRSTATE() == REG_HIZ){ // check in HiZ state: if the error still occurs? if(!CHKFB()){ shutterstate = SHUTTER_RELAX; nextstate = SHUTTER_RELAX; }else if(Tms - T > 10){ T = Tms; SHTROFF(); // turn off for 10ms } }else{ if(Tms - T > 10){ T = Tms; SHTRHIZ(); // and check error again } } break; case SHUTTER_PROCESS: // process opening or closing #ifdef EBUG if(T != Tms){ T = Tms; USB_sendstr(u2str(V)); USB_putbyte('\n'); } #endif if(Tms - Tstart > the_conf.shutterrime || V < the_conf.minvoltage){ SHTROFF(); shutterstate = SHUTTER_WAIT; Tstart = Tms; } break; case SHUTTER_WAIT: // wait for mechanical work done if(Tms - Tstart >= the_conf.waitingtime){ SHTRHIZ(); shutterstate = nextstate; int h = CHKHALL(); if(h) Topened = Tms; else{ USB_sendstr("exptime="); USB_sendstr(u2str(Tms - Topened - the_conf.shutterrime)); USB_putbyte('\n'); } USB_sendstr("shutter="); USB_sendstr(opcl[h]); USB_putbyte('\n'); } break; case SHUTTER_EXPOSE: // wait for exposition ends to close shutter // now Tstart is time when shutter was opened; wait until Tms - Tstart >= Texp if(Tms - Tstart < Texp || T == Tms) break; // once per 1ms T = Tms; if(!close_shutter()){ if(Tms - Tstart > Texp + the_conf.waitingtime){ // try to close not more than `waitingtime` ms USB_sendstr("exp=cantclose\n"); shutterstate = SHUTTER_ERROR; } } break; default: if(CHKFB()){ shutterstate = SHUTTER_ERROR; T = Tms; } break; } static uint8_t oldbtnstate = 0; 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 >= 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;} }else{ // released if(CHKHALL()){ if(close_shutter()){oldbtnstate = s; /*USB_sendstr(" close, old->0\n");*/}} else{/*USB_sendstr("released when !CHKHALL(), old->0\n");*/ oldbtnstate = s;} } } } void print_shutter_state(){ add2buf("shutter="); if(shutterstate != SHUTTER_RELAX) add2buf(states[shutterstate]); else add2buf(opcl[CHKHALL()]); if(CHKHALL()){ if(shutterstate == SHUTTER_EXPOSE){ add2buf("\nexpfor="); add2buf(u2str(Texp)); } add2buf("\nexptime="); add2buf(u2str(Tms - Topened)); } add2buf("\nregstate="); add2buf(regstates[SHTRSTATE()]); add2buf("\nfbstate="); bufputchar('0' + CHKFB()); bufputchar('\n'); }