thermferm/delay.c

Wed, 27 Mar 2024 17:19:46 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 27 Mar 2024 17:19:46 +0100
changeset 652
16d3d4b58b5b
permissions
-rw-r--r--

Moved all delay functions into a new general file.

/**
 * @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