diff -r da166cb8470f -r 16d3d4b58b5b thermferm/delay.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermferm/delay.c Wed Mar 27 17:19:46 2024 +0100 @@ -0,0 +1,117 @@ +/** + * @file delay.c + * #brief Thread friendly delay functions. + * + * Copyright (C) 2024 + * + * Michiel Broek + * + * This file is part of the mbsePi-apps + * + * This 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, or (at your option) any + * later version. + * + * mbsePi-apps 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 ThermFerm; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "delay.h" +#include "thermferm.h" + + +void delay (unsigned int howLong) +{ + struct timespec sleeper, dummy ; + + sleeper.tv_sec = (time_t)(howLong / 1000) ; + sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; + + nanosleep (&sleeper, &dummy) ; +} + + + + +/** + * @brief mDelay Delay number of milliseconds. + * @param howLong The number of milliseconds. + */ +void mDelay(unsigned int howLong) +{ + struct timespec sleeper ; + unsigned int mSecs = howLong % 1000 ; + unsigned int wSecs = howLong / 1000 ; + + /**/ if (howLong == 0) + return ; + else { + sleeper.tv_sec = wSecs ; + sleeper.tv_nsec = (long)(mSecs * 1000000L) ; + nanosleep (&sleeper, NULL) ; + } +} + + +/* + * Code from wiringPi, Gordon. + * + * delayMicroseconds: + * This is somewhat intersting. It seems that on the Pi, a single call + * to nanosleep takes some 80 to 130 microseconds anyway, so while + * obeying the standards (may take longer), it's not always what we + * want! + * + * So what I'll do now is if the delay is less than 100uS we'll do it + * in a hard loop, watching a built-in counter on the ARM chip. This is + * somewhat sub-optimal in that it uses 100% CPU, something not an issue + * in a microcontroller, but under a multi-tasking, multi-user OS, it's + * wastefull, however we've no real choice )-: + * + * Plan B: It seems all might not be well with that plan, so changing it + * to use gettimeofday () and poll on that instead... + ********************************************************************************* + */ +void delayMicrosecondsHard (unsigned int howLong) +{ + struct timeval tNow, tLong, tEnd ; + + gettimeofday (&tNow, NULL) ; + tLong.tv_sec = howLong / 1000000 ; + tLong.tv_usec = howLong % 1000000 ; + timeradd (&tNow, &tLong, &tEnd) ; + + while (timercmp (&tNow, &tEnd, <)) + gettimeofday (&tNow, NULL) ; +} + + +/** + * @brief uDelay Delays a number of microseconds. Also used to replace usleep(). + * @param howLong The number is microseconds. + */ +void uDelay(unsigned int howLong) +{ + struct timespec sleeper ; + unsigned int uSecs = howLong % 1000000 ; + unsigned int wSecs = howLong / 1000000 ; + + /**/ if (howLong == 0) + return ; + else if (howLong < 100) + delayMicrosecondsHard(howLong) ; + else { + sleeper.tv_sec = wSecs ; + sleeper.tv_nsec = (long)(uSecs * 1000L) ; + nanosleep (&sleeper, NULL) ; + } +} + +