2015-08-11 03:28:43 -03:00
# include "AP_HAL.h"
2013-09-21 01:25:42 -03:00
# include "Util.h"
# include "utility/print_vprintf.h"
2016-04-12 01:39:29 -03:00
# include <time.h>
2016-06-21 07:50:01 -03:00
# if defined(__APPLE__) && defined(__MACH__)
# include <sys/time.h>
# endif
2013-09-21 01:25:42 -03:00
/* Helper class implements AP_HAL::Print so we can use utility/vprintf */
class BufferPrinter : public AP_HAL : : Print {
public :
BufferPrinter ( char * str , size_t size ) : _offs ( 0 ) , _str ( str ) , _size ( size ) { }
size_t write ( uint8_t c ) {
if ( _offs < _size ) {
_str [ _offs ] = c ;
_offs + + ;
return 1 ;
} else {
return 0 ;
}
}
2013-10-02 04:36:01 -03:00
size_t write ( const uint8_t * buffer , size_t size ) {
size_t n = 0 ;
while ( size - - ) {
n + = write ( * buffer + + ) ;
}
return n ;
}
2013-09-21 01:25:42 -03:00
size_t _offs ;
char * const _str ;
const size_t _size ;
} ;
int AP_HAL : : Util : : snprintf ( char * str , size_t size , const char * format , . . . )
{
va_list ap ;
va_start ( ap , format ) ;
2013-09-21 02:45:05 -03:00
int res = vsnprintf ( str , size , format , ap ) ;
2013-09-21 01:25:42 -03:00
va_end ( ap ) ;
return res ;
}
int AP_HAL : : Util : : vsnprintf ( char * str , size_t size , const char * format , va_list ap )
{
BufferPrinter buf ( str , size ) ;
2015-12-23 10:25:56 -04:00
print_vprintf ( & buf , format , ap ) ;
2013-09-21 01:25:42 -03:00
// null terminate if possible
2013-09-21 02:45:05 -03:00
int ret = buf . _offs ;
2013-09-21 01:25:42 -03:00
buf . write ( 0 ) ;
2013-09-21 02:45:05 -03:00
return ret ;
2013-09-21 01:25:42 -03:00
}
2016-04-12 01:39:29 -03:00
uint64_t AP_HAL : : Util : : get_system_clock_ms ( ) const
{
2016-06-21 07:50:01 -03:00
# if defined(__APPLE__) && defined(__MACH__)
struct timeval ts ;
2016-10-30 02:24:21 -03:00
gettimeofday ( & ts , nullptr ) ;
2016-06-21 07:50:01 -03:00
return ( ( long long ) ( ( ts . tv_sec * 1000 ) + ( ts . tv_usec / 1000 ) ) ) ;
# else
2016-04-12 01:39:29 -03:00
struct timespec ts ;
clock_gettime ( CLOCK_REALTIME , & ts ) ;
2016-10-14 03:29:31 -03:00
const uint64_t seconds = ts . tv_sec ;
const uint64_t nanoseconds = ts . tv_nsec ;
2017-06-26 07:39:28 -03:00
return ( seconds * 1000ULL + nanoseconds / 1000000ULL ) ;
2016-06-21 07:50:01 -03:00
# endif
2016-04-12 01:39:29 -03:00
}
void AP_HAL : : Util : : get_system_clock_utc ( int32_t & hour , int32_t & min , int32_t & sec , int32_t & ms ) const
{
// get time of day in ms
uint64_t time_ms = get_system_clock_ms ( ) ;
// separate time into ms, sec, min, hour and days but all expressed in milliseconds
ms = time_ms % 1000 ;
uint32_t sec_ms = ( time_ms % ( 60 * 1000 ) ) - ms ;
uint32_t min_ms = ( time_ms % ( 60 * 60 * 1000 ) ) - sec_ms - ms ;
uint32_t hour_ms = ( time_ms % ( 24 * 60 * 60 * 1000 ) ) - min_ms - sec_ms - ms ;
// convert times as milliseconds into appropriate units
sec = sec_ms / 1000 ;
min = min_ms / ( 60 * 1000 ) ;
hour = hour_ms / ( 60 * 60 * 1000 ) ;
}
// get milliseconds from now to a target time of day expressed as hour, min, sec, ms
2016-05-04 09:26:58 -03:00
// match starts from first value that is not -1. I.e. specifying hour=-1, minutes=10 will ignore the hour and return time until 10 minutes past 12am (utc)
2016-04-12 01:39:29 -03:00
uint32_t AP_HAL : : Util : : get_time_utc ( int32_t hour , int32_t min , int32_t sec , int32_t ms ) const
{
// determine highest value specified (0=none, 1=ms, 2=sec, 3=min, 4=hour)
int8_t largest_element = 0 ;
2016-10-14 10:12:31 -03:00
if ( hour ! = - 1 ) {
largest_element = 4 ;
} else if ( min ! = - 1 ) {
largest_element = 3 ;
} else if ( sec ! = - 1 ) {
largest_element = 2 ;
} else if ( ms ! = - 1 ) {
largest_element = 1 ;
} else {
// exit immediately if no time specified
2016-04-12 01:39:29 -03:00
return 0 ;
}
// get start_time_ms as h, m, s, ms
int32_t curr_hour , curr_min , curr_sec , curr_ms ;
get_system_clock_utc ( curr_hour , curr_min , curr_sec , curr_ms ) ;
int32_t total_delay_ms = 0 ;
// calculate ms to target
if ( largest_element > = 1 ) {
total_delay_ms + = ms - curr_ms ;
}
if ( largest_element = = 1 & & total_delay_ms < 0 ) {
2016-10-14 10:12:31 -03:00
return static_cast < uint32_t > ( total_delay_ms + = 1000 ) ;
2016-04-12 01:39:29 -03:00
}
// calculate sec to target
if ( largest_element > = 2 ) {
total_delay_ms + = ( sec - curr_sec ) * 1000 ;
}
if ( largest_element = = 2 & & total_delay_ms < 0 ) {
2016-10-14 10:12:31 -03:00
return static_cast < uint32_t > ( total_delay_ms + = ( 60 * 1000 ) ) ;
2016-04-12 01:39:29 -03:00
}
// calculate min to target
if ( largest_element > = 3 ) {
total_delay_ms + = ( min - curr_min ) * 60 * 1000 ;
}
if ( largest_element = = 3 & & total_delay_ms < 0 ) {
2016-10-14 10:12:31 -03:00
return static_cast < uint32_t > ( total_delay_ms + = ( 60 * 60 * 1000 ) ) ;
2016-04-12 01:39:29 -03:00
}
// calculate hours to target
if ( largest_element > = 4 ) {
total_delay_ms + = ( hour - curr_hour ) * 60 * 60 * 1000 ;
}
if ( largest_element = = 4 & & total_delay_ms < 0 ) {
2016-10-14 10:12:31 -03:00
return static_cast < uint32_t > ( total_delay_ms + = ( 24 * 60 * 60 * 1000 ) ) ;
2016-04-12 01:39:29 -03:00
}
// total delay in milliseconds
2016-10-14 10:12:31 -03:00
return static_cast < uint32_t > ( total_delay_ms ) ;
2016-04-12 01:39:29 -03:00
}