180 #define __compare_timespec(CMP, t1, t2) ((t1.tv_sec == t2.tv_sec)? t1.tv_nsec CMP t2.tv_nsec : t1.tv_sec CMP t2.tv_sec) |
180 #define __compare_timespec(CMP, t1, t2) ((t1.tv_sec == t2.tv_sec)? t1.tv_nsec CMP t2.tv_nsec : t1.tv_sec CMP t2.tv_sec) |
181 |
181 |
182 |
182 |
183 |
183 |
184 /* Some necessary forward declarations... */ |
184 /* Some necessary forward declarations... */ |
|
185 /* |
185 class TIME; |
186 class TIME; |
186 class TOD; |
187 class TOD; |
187 class DT; |
188 class DT; |
188 class DATE; |
189 class DATE; |
189 |
190 |
190 typedef struct timespec __timebase_t; |
191 typedef struct timespec __timebase_t; |
191 |
192 */ |
192 |
193 |
193 |
194 typedef struct TIME timespec; |
|
195 typedef struct TOD timespec; |
|
196 typedef struct DT timespec; |
|
197 typedef struct DATE timespec; |
|
198 |
|
199 static inline struct timespec __time_to_timespec(int sign, double mseconds, double seconds, double minutes, double hours, double days) { |
|
200 struct timespec ts; |
|
201 |
|
202 /* sign is 1 for positive values, -1 for negative time... */ |
|
203 long double total_sec = ((days*24 + hours)*60 + minutes)*60 + seconds + mseconds/1e3; |
|
204 if (sign >= 0) sign = 1; else sign = -1; |
|
205 ts.tv_sec = sign * (long int)total_sec; |
|
206 ts.tv_nsec = sign * (long int)((total_sec - ts.tv_sec)*1e9); |
|
207 |
|
208 return ts; |
|
209 } |
|
210 |
|
211 |
|
212 static inline struct timespec __tod_to_timespec(double seconds, double minutes, double hours) { |
|
213 struct timespec ts; |
|
214 |
|
215 long double total_sec = (hours*60 + minutes)*60 + seconds; |
|
216 ts.tv_sec = (long int)total_sec; |
|
217 ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9); |
|
218 |
|
219 return ts; |
|
220 } |
|
221 |
|
222 static inline struct timespec __date_to_timespec(int day, int month, int year) { |
|
223 struct timespec ts; |
|
224 struct tm broken_down_time; |
|
225 |
|
226 broken_down_time.tm_sec = 0; |
|
227 broken_down_time.tm_min = 0; |
|
228 broken_down_time.tm_hour = 0; |
|
229 broken_down_time.tm_mday = day; /* day of month, from 1 to 31 */ |
|
230 broken_down_time.tm_mon = month - 1; /* month since January, in the range 0 to 11 */ |
|
231 broken_down_time.tm_year = year - 1900; /* number of years since 1900 */ |
|
232 |
|
233 time_t epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */ |
|
234 |
|
235 if ((time_t)(-1) == epoch_seconds) |
|
236 IEC_error(); |
|
237 |
|
238 ts.tv_sec = epoch_seconds; |
|
239 ts.tv_nsec = 0; |
|
240 |
|
241 return ts; |
|
242 } |
|
243 |
|
244 static inline struct timespec __dt_to_timespec(double seconds, double minutes, double hours, int day, int month, int year) { |
|
245 struct timespec ts; |
|
246 |
|
247 long double total_sec = (hours*60 + minutes)*60 + seconds; |
|
248 ts.tv_sec = (long int)total_sec; |
|
249 ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9); |
|
250 |
|
251 struct tm broken_down_time; |
|
252 broken_down_time.tm_sec = 0; |
|
253 broken_down_time.tm_min = 0; |
|
254 broken_down_time.tm_hour = 0; |
|
255 broken_down_time.tm_mday = day; /* day of month, from 1 to 31 */ |
|
256 broken_down_time.tm_mon = month - 1; /* month since January, in the range 0 to 11 */ |
|
257 broken_down_time.tm_year = year - 1900; /* number of years since 1900 */ |
|
258 |
|
259 time_t epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */ |
|
260 if ((time_t)(-1) == epoch_seconds) |
|
261 IEC_error(); |
|
262 |
|
263 ts.tv_sec += epoch_seconds; |
|
264 if (ts.tv_sec < epoch_seconds) |
|
265 /* since the TOD is always positive, if the above happens then we had an overflow */ |
|
266 IEC_error(); |
|
267 |
|
268 return ts; |
|
269 } |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 #ifdef 0 |
194 class TIME{ |
279 class TIME{ |
195 private: |
280 private: |
196 /* private variable that contains the value of time. */ |
281 /* private variable that contains the value of time. */ |
197 /* NOTE: The stored value is _always_ (time.tv_sec + time.tv_nsec), |
282 /* NOTE: The stored value is _always_ (time.tv_sec + time.tv_nsec), |
198 no matter whether tv_sec is positive or negative, or tv_nsec is positive or negative. |
283 no matter whether tv_sec is positive or negative, or tv_nsec is positive or negative. |
449 * but will ease the implementation of the default function CONCAT_DATE_TOD |
534 * but will ease the implementation of the default function CONCAT_DATE_TOD |
450 */ |
535 */ |
451 DT operator+ (const DATE &date, const TOD &tod) {return DT(__add_timespec(date.time, tod.time));}; |
536 DT operator+ (const DATE &date, const TOD &tod) {return DT(__add_timespec(date.time, tod.time));}; |
452 DT operator+ (const TOD &tod, const DATE &date) {return DT(__add_timespec(date.time, tod.time));}; |
537 DT operator+ (const TOD &tod, const DATE &date) {return DT(__add_timespec(date.time, tod.time));}; |
453 |
538 |
|
539 #endif |
454 |
540 |
455 /* global variable that will be used to implement the timers TON, TOFF and TP */ |
541 /* global variable that will be used to implement the timers TON, TOFF and TP */ |
456 extern TIME __CURRENT_TIME; |
542 extern TIME __CURRENT_TIME; |
457 |
543 |
458 |
544 |
488 * The workaround is to use a base data type (in this case __timebase_t) that |
574 * The workaround is to use a base data type (in this case __timebase_t) that |
489 * contains all the internal data these classes require, and then add an operator |
575 * contains all the internal data these classes require, and then add an operator |
490 * member function to each class that allows it to be converted to that same base data type, |
576 * member function to each class that allows it to be converted to that same base data type, |
491 * acompanied by a constructor using that data type. |
577 * acompanied by a constructor using that data type. |
492 */ |
578 */ |
493 /* |
579 |
494 TIME TIMEvar; |
580 TIME TIMEvar; |
495 TOD TODvar; |
581 TOD TODvar; |
496 DT DTvar; |
582 DT DTvar; |
497 DATE DATEvar; |
583 DATE DATEvar; |
498 */ |
584 |
|
585 /* |
499 __timebase_t TIMEvar; |
586 __timebase_t TIMEvar; |
500 __timebase_t TODvar; |
587 __timebase_t TODvar; |
501 __timebase_t DTvar; |
588 __timebase_t DTvar; |
502 __timebase_t DATEvar; |
589 __timebase_t DATEvar; |
|
590 */ |
503 } __IL_DEFVAR_T; |
591 } __IL_DEFVAR_T; |
504 /*TODO TODO TODO TODO TODO TODO TODO TODO TODO |
592 /*TODO TODO TODO TODO TODO TODO TODO TODO TODO |
505 * How do we add support for the possibility of storing |
593 * How do we add support for the possibility of storing |
506 * data values of derived data types into the default register, |
594 * data values of derived data types into the default register, |
507 * to be later used for calling functions, stroing in another |
595 * to be later used for calling functions, stroing in another |