236 lines
6.0 KiB
C
236 lines
6.0 KiB
C
/*-
|
|
* Copyright (c) 2017-2018 Carsten Sonne Larsen <cs@innolan.net>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "time.h"
|
|
#include "mem.h"
|
|
|
|
#include <clib/alib_protos.h>
|
|
|
|
/*
|
|
* 2922 is the number of days between 1.1.1970 and 1.1.1978
|
|
* (2 leap years and 6 normal)
|
|
* 2922 * 24 * 60 * 60 = 252460800
|
|
*/
|
|
#define AMIGA_OFFSET 252460800
|
|
#define TIMER_ERROR 10
|
|
#define TIMER_OK 0
|
|
|
|
struct TimerInfo
|
|
{
|
|
bool TimerTrigged;
|
|
struct MsgPort *TimerPort;
|
|
struct timerequest *TimerIO;
|
|
};
|
|
|
|
struct Device *TimerBase = NULL;
|
|
static struct timerequest *TimerIO = NULL;
|
|
static long utcOffset = 0;
|
|
|
|
/*
|
|
* Set up pointer for timer functions.
|
|
*/
|
|
struct Device *OpenTimerBase(void)
|
|
{
|
|
LONG error;
|
|
|
|
TimerIO = (struct timerequest *)AllocMemSafe(sizeof(struct timerequest));
|
|
if (TimerIO == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
error = OpenDevice((STRPTR)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0);
|
|
if (error != 0)
|
|
{
|
|
FreeMemSafe(TimerIO);
|
|
TimerIO = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
TimerBase = TimerIO->tr_node.io_Device;
|
|
return TimerBase;
|
|
}
|
|
|
|
void CloseTimerBase(void)
|
|
{
|
|
if (TimerBase != NULL && TimerIO != NULL)
|
|
{
|
|
CloseDevice((struct IORequest *)TimerIO);
|
|
}
|
|
|
|
if (TimerIO != NULL)
|
|
{
|
|
FreeMemSafe(TimerIO);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Open a timer device with UNIT_VBLANK.
|
|
*/
|
|
struct TimerInfo *CreateTimer(bool setTimerBase)
|
|
{
|
|
LONG error;
|
|
static const char *name = APP_SHORT_NAME " Timer Message Port";
|
|
struct TimerInfo *info = (struct TimerInfo *)AllocMemSafe(sizeof(struct TimerInfo));
|
|
if (info == NULL)
|
|
return NULL;
|
|
|
|
info->TimerPort = CreateMsgPort();
|
|
if (info->TimerPort == NULL)
|
|
{
|
|
DeleteTimer(info);
|
|
return NULL;
|
|
}
|
|
|
|
info->TimerPort->mp_Node.ln_Name = (char *)name;
|
|
info->TimerPort->mp_Node.ln_Pri = 0;
|
|
|
|
info->TimerIO = (struct timerequest *)CreateExtIO(info->TimerPort, sizeof(struct timerequest));
|
|
if (info->TimerIO == NULL)
|
|
{
|
|
DeleteTimer(info);
|
|
return NULL;
|
|
}
|
|
|
|
error = OpenDevice(
|
|
(STRPTR)TIMERNAME, UNIT_MICROHZ,
|
|
(struct IORequest *)info->TimerIO, 0);
|
|
|
|
if (error != 0)
|
|
{
|
|
DeleteTimer(info);
|
|
return NULL;
|
|
}
|
|
|
|
return info;
|
|
}
|
|
|
|
void SetTimer(struct TimerInfo *info)
|
|
{
|
|
info->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
|
|
info->TimerIO->tr_time.tv_secs = Globals->Settings->Interval / 1000;
|
|
info->TimerIO->tr_time.tv_micro = Globals->Settings->Interval % 1000;
|
|
SendIO((struct IORequest *)info->TimerIO);
|
|
info->TimerTrigged = true;
|
|
}
|
|
|
|
ULONG GetTimerSigMask(struct TimerInfo *info)
|
|
{
|
|
return (1 << info->TimerPort->mp_SigBit);
|
|
}
|
|
|
|
void DeleteTimer(struct TimerInfo *info)
|
|
{
|
|
if (info->TimerIO != NULL)
|
|
{
|
|
AbortIO((struct IORequest *)info->TimerIO);
|
|
if (info->TimerTrigged)
|
|
{
|
|
WaitIO((struct IORequest *)info->TimerIO);
|
|
}
|
|
CloseDevice((struct IORequest *)info->TimerIO);
|
|
DeleteExtIO((struct IORequest *)info->TimerIO);
|
|
info->TimerIO = NULL;
|
|
}
|
|
|
|
if (info->TimerPort != NULL)
|
|
{
|
|
DeleteMsgPort(info->TimerPort);
|
|
}
|
|
|
|
FreeMemSafe(info);
|
|
}
|
|
|
|
void InitUtcOffset(void)
|
|
{
|
|
char timeZone[10];
|
|
int gmtoffset = Globals->Locale->loc_GMTOffset * 60;
|
|
utcOffset = gmtoffset + AMIGA_OFFSET;
|
|
GetTimeZoneText(timeZone);
|
|
LogWarning("Local time zone is %s", timeZone);
|
|
}
|
|
|
|
void GetTimeZoneText(char *text)
|
|
{
|
|
SNPrintf(text, 10, "UTC%s%ld:%02ld",
|
|
-Globals->Locale->loc_GMTOffset > 0 ? "+" : "",
|
|
(long)-Globals->Locale->loc_GMTOffset / 60,
|
|
(long)-Globals->Locale->loc_GMTOffset % 60);
|
|
}
|
|
|
|
void Unix2Amiga(struct timeval *unix, struct timeval *tv)
|
|
{
|
|
tv->tv_secs = unix->tv_secs + AMIGA_OFFSET;
|
|
tv->tv_micro = unix->tv_micro;
|
|
}
|
|
|
|
void Utc2Local(struct timeval *utc, struct timeval *tv)
|
|
{
|
|
int gmtoffset = Globals->Locale->loc_GMTOffset * 60;
|
|
tv->tv_secs = utc->tv_secs - gmtoffset;
|
|
tv->tv_micro = utc->tv_micro;
|
|
}
|
|
|
|
void GetTimeOfDay(struct timeval *tv)
|
|
{
|
|
GetSysTime(tv);
|
|
tv->tv_secs = tv->tv_secs + utcOffset;
|
|
}
|
|
|
|
void GetLocalTimeOfDay(struct timeval *tv)
|
|
{
|
|
GetSysTime(tv);
|
|
}
|
|
|
|
void SetTimeOfDay(const struct TimerInfo *info, const struct timeval *tv)
|
|
{
|
|
info->TimerIO->tr_node.io_Command = TR_SETSYSTIME;
|
|
info->TimerIO->tr_time.tv_secs = (long)tv->tv_secs - utcOffset;
|
|
info->TimerIO->tr_time.tv_micro = tv->tv_micro;
|
|
DoIO((struct IORequest *)info->TimerIO);
|
|
}
|
|
|
|
void SaveTimeOfDay(const struct timeval *tv)
|
|
{
|
|
WriteBattClock((long)tv->tv_secs - utcOffset);
|
|
}
|
|
|
|
void SystemTimeString(char *time, char *date, char *day)
|
|
{
|
|
struct DateTime dt;
|
|
|
|
DateStamp(&dt.dat_Stamp);
|
|
|
|
dt.dat_Format = FORMAT_DOS;
|
|
dt.dat_Flags = 0;
|
|
dt.dat_StrDay = (void *)day;
|
|
dt.dat_StrDate = (void *)date;
|
|
dt.dat_StrTime = (void *)time;
|
|
|
|
DateToStr(&dt);
|
|
}
|