hal.cpp 16 KB

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