using Unosquare.Swan; using Unosquare.Swan.Abstractions; using System; namespace Unosquare.RaspberryIO.Native { /// <summary> /// Provides access to timing and threading properties and methods /// </summary> public class Timing : SingletonBase<Timing> { /// <summary> /// Prevents a default instance of the <see cref="Timing"/> class from being created. /// </summary> /// <exception cref="NotSupportedException">Could not initialize the GPIO controller</exception> private Timing() { // placeholder } /// <summary> /// This returns a number representing the number of milliseconds since your program /// initialized the GPIO controller. /// It returns an unsigned 32-bit number which wraps after 49 days. /// </summary> /// <value> /// The milliseconds since setup. /// </value> public UInt32 MillisecondsSinceSetup => WiringPi.Millis(); /// <summary> /// This returns a number representing the number of microseconds since your /// program initialized the GPIO controller /// It returns an unsigned 32-bit number which wraps after approximately 71 minutes. /// </summary> /// <value> /// The microseconds since setup. /// </value> public UInt32 MicrosecondsSinceSetup => WiringPi.Micros(); /// <summary> /// This causes program execution to pause for at least howLong milliseconds. /// Due to the multi-tasking nature of Linux it could be longer. /// Note that the maximum delay is an unsigned 32-bit integer or approximately 49 days. /// </summary> /// <param name="value">The value.</param> public static void SleepMilliseconds(UInt32 value) => WiringPi.Delay(value); /// <summary> /// This causes program execution to pause for at least howLong microseconds. /// Due to the multi-tasking nature of Linux it could be longer. /// Note that the maximum delay is an unsigned 32-bit integer microseconds or approximately 71 minutes. /// Delays under 100 microseconds are timed using a hard-coded loop continually polling the system time, /// Delays over 100 microseconds are done using the system nanosleep() function – /// You may need to consider the implications of very short delays on the overall performance of the system, /// especially if using threads. /// </summary> /// <param name="value">The value.</param> public void SleepMicroseconds(UInt32 value) => WiringPi.DelayMicroseconds(value); /// <summary> /// This attempts to shift your program (or thread in a multi-threaded program) to a higher priority and /// enables a real-time scheduling. The priority parameter should be from 0 (the default) to 99 (the maximum). /// This won’t make your program go any faster, but it will give it a bigger slice of time when other programs /// are running. The priority parameter works relative to others – so you can make one program priority 1 and /// another priority 2 and it will have the same effect as setting one to 10 and the other to 90 /// (as long as no other programs are running with elevated priorities) /// </summary> /// <param name="priority">The priority.</param> public void SetThreadPriority(Int32 priority) { priority = priority.Clamp(0, 99); Int32 result = WiringPi.PiHiPri(priority); if(result < 0) { HardwareException.Throw(nameof(Timing), nameof(SetThreadPriority)); } } /// <summary> /// This is really nothing more than a simplified interface to the Posix threads mechanism that Linux supports. /// See the manual pages on Posix threads (man pthread) if you need more control over them. /// </summary> /// <param name="worker">The worker.</param> /// <exception cref="ArgumentNullException">worker</exception> public void CreateThread(ThreadWorker worker) { if(worker == null) { throw new ArgumentNullException(nameof(worker)); } Int32 result = WiringPi.PiThreadCreate(worker); if(result != 0) { HardwareException.Throw(nameof(Timing), nameof(CreateThread)); } } /// <summary> /// These allow you to synchronize variable updates from your main program to any threads running in your program. /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key, /// it will be stalled until the first process has unlocked the same key. /// </summary> /// <param name="key">The key.</param> public void Lock(ThreadLockKey key) => WiringPi.PiLock((Int32)key); /// <summary> /// These allow you to synchronize variable updates from your main program to any threads running in your program. /// keyNum is a number from 0 to 3 and represents a “key”. When another process tries to lock the same key, /// it will be stalled until the first process has unlocked the same key. /// </summary> /// <param name="key">The key.</param> public void Unlock(ThreadLockKey key) => WiringPi.PiUnlock((Int32)key); } }