hal.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. /*
  2. * hal.cpp
  3. *
  4. * Created on: Aug 3, 2016
  5. * Author: Philipp Hinz, Sebastian Vendt
  6. */
  7. #include <wiringPi.h>
  8. #include <stdlib.h>
  9. #include <stdint.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <signal.h>
  13. #include <ctime>
  14. #include <time.h>
  15. #include <unistd.h>
  16. #include "hal.h"
  17. #include "global.h"
  18. #include "logger.h"
  19. #include "timer.h"
  20. #include "database.h"
  21. const char* SigName[] = {
  22. "NULL",
  23. "SigInt0Psh",
  24. "SigInt0Rls",
  25. "SigInt0RlsLong",
  26. "SigInt1Psh",
  27. "SigInt1Rls",
  28. "SigInt1RlsLong",
  29. "SigPressCls",
  30. "SigPressOpn",
  31. "SigProxOpn",
  32. "SigProxCvrd",
  33. "SigBrewOn",
  34. "SigBrewOff",
  35. "SigPowerUp",
  36. "SigPowerDown",
  37. "SigRotCW",
  38. "SigRotCCW"};
  39. typedef struct timespec timespec;
  40. volatile int flowcnt = 0;
  41. int lastFlowcnt = 0;
  42. int flowResetValue = -1;
  43. bool brewmanual = false;
  44. //local copies of the corresponding database entries
  45. time_t heatingCycleStart = 0;
  46. uint64_t totalHeatingTime = 0; //total heating time in seconds
  47. uint16_t flowResetTime = 0; //see TIME_FLOWRESET for details
  48. int Int0Time, Int1Time;
  49. int idleCounter;
  50. bool idle;
  51. bool flagIgnoreRlsInt0, flagIgnoreRlsInt1;
  52. //storage for the last state of the buttons, the proximity sensor and the pressure sensor
  53. int pinState[4] = {1, 1, 0, 0};
  54. //state of the rotary encoder
  55. //0: rotary1 state at t-1
  56. //1: rotary2 state at t-1
  57. //2: rotary1 state at t
  58. //3: rotary2 state at t
  59. int rotaryState[4] = {1, 0, 0, 1};
  60. timer Int0Timer(&halInt0TimerHandler);
  61. timer Int1Timer(&halInt1TimerHandler);
  62. timer idleTimer(&halIdleTimerHandler);
  63. timer flowResetTimer (&flowResetTimerHandler);
  64. timer flowTimer(&halFlowTimerHandler);
  65. timespec flowTimestep[] = {{0,0},{0,0}};
  66. uint8_t flowIndex = 0;
  67. int16_t tickCounter = 0; //rotary encoder
  68. uint16_t flowtime = 0;
  69. uint16_t lastFlowTime = 0;
  70. bool brewSigFired = false;
  71. //delay of the debounce in milliseconds
  72. #define DELAY_DEBOUNCE 50
  73. #define DELAY_MICRODEB 2
  74. //display turn off after idle time in min
  75. //minimal time is 2min
  76. #define IDLE_TIME 10
  77. /**
  78. * Initializes HAL
  79. */
  80. void halInit(void) {
  81. pinMode(RELAIS_HEAT, OUTPUT);
  82. pinMode(RELAIS_PUMP, OUTPUT);
  83. pinMode(RELAIS_POWER, OUTPUT);
  84. pinMode(PIN_PRESSURE_CTRL, INPUT);
  85. pinMode(PIN_PROXIMITY_SENSOR, INPUT);
  86. pinMode(PIN_INT0, INPUT);
  87. pinMode(PIN_INT1, INPUT);
  88. pinMode(PIN_FLOW, INPUT);
  89. pinMode(PIN_DISP, OUTPUT);
  90. pinMode(PIN_ROTARY1, INPUT);
  91. pinMode(PIN_ROTARY2, INPUT);
  92. idleTimer.setDivider(ms2Divider(60000));
  93. idleCounter = 0;
  94. idle = false;
  95. clock_gettime(CLOCK_REALTIME, &flowTimestep[0]);
  96. clock_gettime(CLOCK_REALTIME, &flowTimestep[1]);
  97. halDisplayOn();
  98. if (!(totalHeatingTime = sqlGetConf(CFGHeatingTime))) {
  99. logger_error("hal.cpp: Couldn't read the total heating time from the database\n");
  100. //pthread_exit(EXIT_SUCCESS);
  101. exit(EXIT_FAILURE);
  102. }
  103. if (!(flowResetTime = sqlGetConf(CFGFlowResetTime))) {
  104. flowResetTime = TIME_FLOWRESET;
  105. logger_error("hal.cpp: Couldn't read the flow reset time from the database\nFalling back to defaults.\n");
  106. }
  107. if (optPower) {
  108. halMachineOn();
  109. } else {
  110. halMachineOff();
  111. }
  112. sleep(1); //wait till the machine eventually turned on when optPower
  113. //Determine the inital state of the pins for the pressure control and the graywater tank sensor
  114. //TODO do a proper averaging here
  115. pinState[3] = halGetPressureSensorPin();
  116. if (halIsHeating()) logger(V_HAL, "hal.cpp: pressure sensor state set initially to: HEATING\n");
  117. else logger(V_HAL, "hal.cpp: pressure sensor state set initially to: OPEN\n");
  118. pinState[2] = halGetProxSensorPin();
  119. if (halProxSensorCovered()) logger(V_HAL, "hal.cpp: proximity sensor state set initially to: COVERED\n");
  120. else logger(V_HAL, "hal.cpp: proximity sensor state set initially to: OPEN\n");
  121. Int0Timer.setDivider(ms2Divider(200));
  122. Int1Timer.setDivider(ms2Divider(200));
  123. Int0Time = 0;
  124. Int1Time = 0;
  125. flowResetTimer.setDivider(ms2Divider(TIME_FLOWRESET));
  126. flowTimer.setDivider(ms2Divider(200));
  127. flagIgnoreRlsInt0 = false;
  128. flagIgnoreRlsInt1 = false;
  129. event_subscribe("terminate", &halTerminate, "hal.cpp");
  130. if (wiringPiISR(PIN_INT0, INT_EDGE_BOTH, &halInt0) < 0) {
  131. logger_error("Unable to setup ISR0: %s\n", strerror(errno));
  132. return;
  133. }
  134. if (wiringPiISR(PIN_INT1, INT_EDGE_BOTH, &halInt1) < 0) {
  135. logger_error("Unable to setup ISR1: %s\n", strerror(errno));
  136. return;
  137. }
  138. if (wiringPiISR(PIN_FLOW, INT_EDGE_FALLING, &halIntFlow) < 0) {
  139. logger_error("Unable to setup ISRFLOW: %s\n", strerror(errno));
  140. return;
  141. }
  142. if (wiringPiISR(PIN_PRESSURE_CTRL, INT_EDGE_BOTH, &halIntPressure) < 0) {
  143. logger_error("Unable to setup ISRPressure: %s\n", strerror(errno));
  144. return;
  145. }
  146. if (wiringPiISR(PIN_PROXIMITY_SENSOR, INT_EDGE_BOTH, &halIntProximity) < 0) {
  147. logger_error("Unable to setup ISRProximity: %s\n", strerror(errno));
  148. return;
  149. }
  150. if (wiringPiISR(PIN_ROTARY1, INT_EDGE_BOTH, &halIntRotary) < 0) {
  151. logger_error("Unable to setup ISRRotary2: %s\n", strerror(errno));
  152. return;
  153. }
  154. logger(V_BASIC, "hal.cpp: Initialized\n");
  155. }
  156. /**
  157. * Switches relais on
  158. * @param relais Relais ID
  159. */
  160. void halRelaisOn(int relais) {
  161. halRelaisSet(relais, LOW);
  162. }
  163. /**
  164. * Turn the display off
  165. */
  166. void halDisplayOff(){
  167. digitalWrite(PIN_DISP, LOW);
  168. }
  169. /**
  170. * Turn the display on
  171. */
  172. void halDisplayOn(){
  173. digitalWrite(PIN_DISP, HIGH);
  174. }
  175. /**
  176. * Switches relais off
  177. * @param relais Relais ID
  178. */
  179. void halRelaisOff(int relais) {
  180. halRelaisSet(relais, HIGH);
  181. }
  182. /**
  183. * Switches relais to state
  184. * @param relais Relais ID
  185. * @param state LOW(0) or HIGH(1)
  186. */
  187. void halRelaisSet(int relais, int state) {
  188. if (state != HIGH && state != LOW)
  189. return;
  190. switch (relais) {
  191. case RELAIS_POWER:
  192. case RELAIS_HEAT:
  193. case RELAIS_PUMP:
  194. digitalWrite(relais, state);
  195. break;
  196. }
  197. }
  198. /**
  199. * Returns the state of the relais relais
  200. * Returns HIGH when Relais is ON
  201. * @param relais Relais ID
  202. */
  203. int halGetRelaisState(int relais) {
  204. switch (relais) {
  205. case RELAIS_POWER:
  206. case RELAIS_HEAT:
  207. case RELAIS_PUMP:
  208. return !digitalRead(relais);
  209. break;
  210. }
  211. return -1;
  212. }
  213. /**
  214. *
  215. */
  216. void halIntRotary(void) {
  217. //delay(DELAY_MICRODEB);
  218. rotaryState[2] = digitalRead(PIN_ROTARY1);
  219. rotaryState[3] = digitalRead(PIN_ROTARY2);
  220. if (rotaryState[0] != rotaryState[2]) {
  221. //check for the status of the other pin
  222. if (rotaryState[1] != rotaryState[3]) {
  223. if ((rotaryState[2] == HIGH && rotaryState[3] == LOW) || (rotaryState[2] == LOW && rotaryState[3] == HIGH)) {
  224. //clockwise rotation
  225. tickCounter++;
  226. if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
  227. //logger(V_HAL, "rotary encoder CW \n");
  228. halSendSignal(SigRotCW);
  229. tickCounter = 0;
  230. }
  231. } else if ((rotaryState[2] == HIGH && rotaryState[3] == HIGH) || (rotaryState[2] == LOW && rotaryState[3] == LOW)) {
  232. //counterclockwise rotation
  233. tickCounter--;
  234. if (!(abs(tickCounter) % ROTARY_STEPSIZE)) {
  235. //logger(V_HAL, "rotary encoder CCW \n");
  236. halSendSignal(SigRotCCW);
  237. tickCounter = 0;
  238. }
  239. }
  240. rotaryState[1] = rotaryState[3];
  241. }
  242. rotaryState[0] = rotaryState[2];
  243. }
  244. }
  245. /**
  246. * Interrupt routine for Int0 (Top button)
  247. */
  248. void halInt0(void) {
  249. //wait for a debounce
  250. delay(DELAY_DEBOUNCE);
  251. if (halGetInt0() && !pinState[0]) { //released
  252. logger(V_HAL, "Int0 released\n");
  253. pinState[0] = 1;
  254. if (flagIgnoreRlsInt0) {
  255. flagIgnoreRlsInt0 = false;
  256. } else {
  257. Int0Time = 0;
  258. Int0Timer.stop();
  259. halSendSignal(SigInt0Rls);
  260. }
  261. } else if(!halGetInt0() && pinState[0]) { //pressed
  262. logger(V_HAL, "Int0 pushed\n");
  263. pinState[0] = 0;
  264. halSendSignal(SigInt0Psh);
  265. Int0Time = 0;
  266. Int0Timer.start();
  267. }
  268. }
  269. /**
  270. *
  271. */
  272. void halInt0TimerHandler(void) {
  273. Int0Time += 200;
  274. if (Int0Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  275. halSendSignal(SigInt0RlsLong);
  276. flagIgnoreRlsInt0 = true;
  277. Int0Time = 0;
  278. Int0Timer.stop();
  279. }
  280. }
  281. /**
  282. *
  283. */
  284. void halIdleTimerHandler(void) {
  285. if(++idleCounter == IDLE_TIME){
  286. halEnterIdle();
  287. }
  288. }
  289. /**
  290. * Interrupt routine for Int1 (Bottom button)
  291. */
  292. void halInt1(void) {
  293. delay(DELAY_DEBOUNCE);
  294. if (halGetInt1() && !pinState[1]) {
  295. logger(V_HAL, "Int1 released\n");
  296. pinState[1] = 1;
  297. if (flagIgnoreRlsInt1) {
  298. flagIgnoreRlsInt1 = false;
  299. } else {
  300. Int1Time = 0;
  301. Int1Timer.stop();
  302. halSendSignal(SigInt1Rls);
  303. }
  304. } else if(!halGetInt1() && pinState[1]) {
  305. logger(V_HAL, "Int1 pushed\n");
  306. pinState[1] = 0;
  307. halSendSignal(SigInt1Psh);
  308. Int1Time = 0;
  309. Int1Timer.start();
  310. }
  311. }
  312. /*
  313. *
  314. */
  315. void halInt1TimerHandler(void) {
  316. Int1Time += 200;
  317. if (Int1Time >= (TIME_BUTTONLONGPRESS * 1000)) {
  318. halSendSignal(SigInt1RlsLong);
  319. flagIgnoreRlsInt1 = true;
  320. Int1Time = 0;
  321. Int1Timer.stop();
  322. }
  323. }
  324. /**
  325. * Timer handler to auto-reset the flow counter.
  326. * The timer is started when the flow interrupt is triggered.
  327. * It compares the last value (flowResetValue) with the current flow value
  328. * If they match (e.g no flow within 1000ms) the flow counter is reseted.
  329. * Setting the last value to -1 ensures that when the timer gets called immediately after it is started the comparison will fail.
  330. * This implementation is read-only and so it doesn't need semaphores.
  331. */
  332. void flowResetTimerHandler() {
  333. if(flowResetValue == flowcnt) {
  334. halResetFlow();
  335. return;
  336. }
  337. flowResetValue = flowcnt;
  338. }
  339. /**
  340. *
  341. */
  342. void halFlowTimerHandler() {
  343. flowtime += 200;
  344. }
  345. /**
  346. * Interrupt routine for the flow sensor
  347. * It counts the edges and stores the value in flowcnt
  348. */
  349. void halIntFlow(void) {
  350. //halRelaisOff(RELAIS_POWER);
  351. if(!flowResetTimer.isActive()) flowResetTimer.start();
  352. flowcnt++;
  353. logger(V_HAL, "IntFlow triggered #%d total: %.2fml\n", flowcnt, halGetFlow());
  354. //tracking of flowtime
  355. if(!flowTimer.isActive()) flowTimer.start();
  356. //trigger the brewing signal using the total flow time
  357. if (halGetFlowTime() >= BREW_MANUAL_TRIGGER && !brewSigFired) {
  358. halSendSignal(SigBrewOn);
  359. brewSigFired = true;
  360. }
  361. //subroutine to log the flow to the database
  362. /*timespec deltaT;
  363. clock_gettime(CLOCK_REALTIME, &flowTimestep[flowIndex]);
  364. timespec_diff(&flowTimestep[((flowIndex + 1) % 2)], &flowTimestep[flowIndex], &deltaT);
  365. if (sqlLogFlow(logcycle, halGetFlow()*1000, deltaT.tv_sec * 1000 + deltaT.tv_nsec/1000000)) {
  366. logger_error("hal.cpp: could not log flow to database!");
  367. return;
  368. }
  369. flowIndex = (flowIndex + 1) % 2;*/
  370. }
  371. /**
  372. * Interrupt routine for the pressure control
  373. * It captures the time at closing point and opening point
  374. * Reading heating time via the getHeatingTime function
  375. */
  376. void halIntPressure(void) {
  377. delay(DELAY_DEBOUNCE);
  378. if (!halGetPressureSensorPin() && pinState[3]) {
  379. logger(V_HAL, "hal.cpp: Pressure Control closed\n");
  380. pinState[3] = 0;
  381. halStartHeatingTime();
  382. halSendSignal(SigPressCls);
  383. } else if(halGetPressureSensorPin() && !pinState[3]) {
  384. logger(V_HAL, "hal.cpp: Pressure Control opened\n");
  385. pinState[3] = 1;
  386. halStopHeatingTime();
  387. halSendSignal(SigPressOpn);
  388. }
  389. }
  390. /**
  391. *
  392. */
  393. void halStartHeatingTime(void) {
  394. time(&heatingCycleStart);
  395. }
  396. /**
  397. *
  398. */
  399. void halStopHeatingTime(void) {
  400. if (heatingCycleStart != 0) { //only track time if stopwatch was started!
  401. uint64_t timediff = (uint64_t) difftime(time(0), heatingCycleStart);
  402. logger(V_HAL, "hal.cpp: Heating time: %f\n", timediff);
  403. totalHeatingTime += timediff;
  404. heatingCycleStart = 0;
  405. }
  406. }
  407. /**
  408. * Method to handle toggle of the proximity sensor
  409. */
  410. void halIntProximity(void) {
  411. delay(DELAY_DEBOUNCE);
  412. if (halGetProxSensorPin() && !pinState[2]) {
  413. logger(V_HAL, "hal.cpp: Proximity switch closed\n");
  414. pinState[2] = 1;
  415. } else if(!halGetProxSensorPin() && pinState[2]){
  416. logger(V_HAL, "hal.cpp: Proximity switch opened\n");
  417. pinState[2] = 0;
  418. }
  419. }
  420. /**
  421. * Returns total flow through sensor in ml
  422. */
  423. float halGetFlow(void) {
  424. return flowcnt * FLOW_ML_PULSE;
  425. }
  426. /**
  427. * Returns the total flow time in ms
  428. */
  429. uint16_t halGetFlowTime(void){
  430. return flowtime;
  431. }
  432. /*
  433. * Returns the last total flow through the sensor in ml after reset
  434. */
  435. float halGetLastFlow(void) {
  436. return lastFlowcnt * FLOW_ML_PULSE;
  437. }
  438. /**
  439. * Returns the total flow time in ms before the last reset.
  440. */
  441. uint16_t halGetLastFlowTime(void){
  442. return lastFlowTime;
  443. }
  444. /**
  445. * Returns the time interval in ms between the last received flow signal and the reset of the flow counter
  446. */
  447. uint16_t halGetFlowResetTime(void) {
  448. return flowResetTime;
  449. }
  450. /**
  451. * Set the value of the Flow reset time. Its the responsibility of the caller to also call halWriteBackCache()!
  452. */
  453. void halSetFlowResetTime(uint16_t val) {
  454. flowResetTime = val;
  455. }
  456. /**
  457. * Resets the Flow counter. Do not call this function manually. It will be automatically triggered
  458. * from the flow reset timer routine!
  459. */
  460. void halResetFlow(void) {
  461. logger(V_HAL, "Flow counter reset, amount so far: %.2f ml\n", halGetFlow());
  462. lastFlowcnt = flowcnt;
  463. flowcnt = 0;
  464. lastFlowTime = flowtime;
  465. flowtime = 0;
  466. flowResetTimer.stop();
  467. flowTimer.stop();
  468. flowResetValue = -1;
  469. if(brewSigFired) {
  470. brewSigFired = false;
  471. halSendSignal(SigBrewOff);
  472. }
  473. }
  474. /**
  475. * Reads the status of the Pressure Control
  476. * @return 1 (true) for closed Pressure Control (heating) and 0 (false) for open
  477. */
  478. bool halIsHeating(void) {
  479. return !pinState[3];
  480. }
  481. /**
  482. * Get the total elapsed heating time in seconds since the last reset
  483. */
  484. uint64_t halGetTotalHeatingTime() {
  485. return totalHeatingTime;
  486. }
  487. /**
  488. * Set/Reset the total heating time in seconds
  489. */
  490. void halSetTotalHeatingTime(uint64_t newTime) {
  491. totalHeatingTime = newTime;
  492. }
  493. /**
  494. * Returns filtered status of the proximity switch
  495. * @return 1 if the proximity switch is covered and 0 if uncovered
  496. */
  497. bool halProxSensorCovered(void) {
  498. return pinState[2];
  499. }
  500. /**
  501. *
  502. */
  503. int halGetPressureSensorPin(void) {
  504. return digitalRead(PIN_PRESSURE_CTRL);
  505. }
  506. /**
  507. * Returns the pin status of the proximity sensor
  508. */
  509. int halGetProxSensorPin(void) {
  510. return digitalRead(PIN_PROXIMITY_SENSOR);
  511. }
  512. /**
  513. * Returns the value of the top button Int0 (low active)
  514. * @return LOW or HIGH
  515. */
  516. int halGetInt0(void) {
  517. return digitalRead(PIN_INT0);
  518. }
  519. /**
  520. * Returns the value of the bottom button Int1 (low active)
  521. * @return LOW or HIGH
  522. */
  523. int halGetInt1(void) {
  524. return digitalRead(PIN_INT1);
  525. }
  526. /**
  527. * send Signal to coffee thread
  528. * @param val Integer value assigned to signal
  529. */
  530. void halSendSignal(HalSig val) {
  531. //restart software when lower button is pressed long
  532. if (val == SigInt1RlsLong) {
  533. event_trigger("terminate");
  534. sleep(4);
  535. exit(EXIT_SUCCESS);
  536. return;
  537. }
  538. if (halIdle(val)) return;
  539. sigval value = { 0 };
  540. value.sival_int = (int) val;
  541. try {
  542. if (pthread_sigqueue(thread[THREAD_COFFEE], SIGUSR2, value)) {
  543. logger_error("hal.cpp: Failed to queue signal %d %s\n", val, strerror(errno));
  544. //No Signals reach the state machine anymore...
  545. exit(EXIT_FAILURE);
  546. }
  547. } catch (int e) {
  548. logger_error("Whoops.. %d\n", e);
  549. }
  550. }
  551. /**
  552. * Turn machine on
  553. */
  554. void halMachineOn(void) {
  555. halRelaisOn(RELAIS_HEAT);
  556. halRelaisOff(RELAIS_PUMP);
  557. halRelaisOn(RELAIS_POWER);
  558. idleTimer.stop();
  559. if(halIsHeating()) halStartHeatingTime();
  560. logger(V_HAL, "hal.cpp: Turning machine on\n");
  561. }
  562. /**
  563. * Turn machine off
  564. */
  565. void halMachineOff(void) {
  566. halRelaisOff(RELAIS_HEAT);
  567. halRelaisOff(RELAIS_PUMP);
  568. halRelaisOff(RELAIS_POWER);
  569. idleCounter = 0;
  570. idleTimer.start();
  571. halStopHeatingTime();
  572. halWriteBackCache();
  573. logger(V_HAL, "hal.cpp: Turning machine off\n");
  574. }
  575. /**
  576. *
  577. */
  578. void halEnterIdle(void){
  579. logger(V_HAL, "hal.cpp: Entering Idle Mode\n");
  580. idleTimer.stop();
  581. halDisplayOff();
  582. idle = true;
  583. }
  584. /**
  585. *
  586. */
  587. void halLeaveIdle(void) {
  588. idleCounter = 0;
  589. logger(V_HAL, "hal.cpp: Leaving Idle Mode\n");
  590. halDisplayOn();
  591. idleTimer.start();
  592. idle = false;
  593. }
  594. /**
  595. * processes the signal value with respect to the idle state
  596. * returns true, if the current signal should be dropped
  597. */
  598. bool halIdle(HalSig val){
  599. //idle processing filter for signals
  600. if (idle) {
  601. switch (val) {
  602. case SigInt0Psh:
  603. case SigInt1Psh:
  604. return true;
  605. break;
  606. case SigInt0Rls:
  607. case SigInt0RlsLong:
  608. case SigInt1Rls:
  609. case SigRotCCW:
  610. case SigRotCW:
  611. halLeaveIdle();
  612. return true;
  613. break;
  614. case SigPowerUp:
  615. halLeaveIdle();
  616. return false;
  617. break;
  618. default:
  619. return false;
  620. }
  621. } else {
  622. //reset the idle time on every input
  623. halResetIdleTimer();
  624. return false;
  625. }
  626. }
  627. /**
  628. *
  629. */
  630. void halResetIdleTimer(void) {
  631. idleCounter = 0;
  632. }
  633. /**
  634. * Wrapper function to turn the pump on.
  635. */
  636. void halPumpOn(){
  637. halRelaisOn(RELAIS_PUMP);
  638. }
  639. /**
  640. * Wrapper function to turn the pump off
  641. * and to measure how long the pump is running
  642. */
  643. void halPumpOff(void){
  644. halRelaisOff(RELAIS_PUMP);
  645. }
  646. /**
  647. * Function to calculate the difference between two timespecs
  648. */
  649. void timespec_diff(timespec *start, timespec *stop, timespec *result) {
  650. long int secDiff = stop->tv_sec - start->tv_sec;
  651. long int nsecDiff = stop->tv_nsec - start->tv_nsec;
  652. if (secDiff > 0) {
  653. if (nsecDiff >= 0) {
  654. result->tv_sec = secDiff;
  655. result->tv_nsec = nsecDiff;
  656. } else if (nsecDiff < 0) {
  657. result->tv_sec = --secDiff;
  658. result->tv_nsec = 1000000000 + nsecDiff;
  659. }
  660. } else if (secDiff < 0) {
  661. if (nsecDiff >= 0) {
  662. result->tv_sec = ++secDiff;
  663. result->tv_nsec = -(1000000000 - nsecDiff);
  664. } else if (nsecDiff < 0) {
  665. result->tv_sec = secDiff;
  666. result->tv_nsec = nsecDiff;
  667. }
  668. } else if (secDiff == 0){
  669. result->tv_sec = secDiff;
  670. result->tv_nsec = nsecDiff;
  671. }
  672. return;
  673. }
  674. /*
  675. * Handler for Termination of the hal
  676. */
  677. void halTerminate(event_t *event){
  678. halStopHeatingTime();
  679. halWriteBackCache();
  680. }
  681. /*
  682. * writing back non volatile variables of the hal to the database: totalHeatingTime, flowResetTime
  683. */
  684. void halWriteBackCache(){
  685. if (sqlSetConf(CFGHeatingTime, totalHeatingTime)) {
  686. logger_error("hal.cpp: Couldn't write heating time to database\n");
  687. return;
  688. }
  689. logger(V_BREW, "Writing back heating time: %lld sec\n", totalHeatingTime);
  690. if (sqlSetConf(CFGFlowResetTime, flowResetTime)) {
  691. logger_error("hal.cpp: Couldn't write the flow reset time to database\n");
  692. return;
  693. }
  694. logger(V_BREW, "Writing back flow reset time: %d ms\n", flowResetTime);
  695. }