thermferm/delay.c

changeset 652
16d3d4b58b5b
--- /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 <mbroek at mbse dot eu>
+ *
+ * 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) ;
+    }
+}
+
+

mercurial