xref: /openbmc/phosphor-logging/extensions/openpower-pels/bcd_time.hpp (revision 075c79237505ea3b810a461f5f514e4d520a0c44)
1df797f2bSMatt Spinler #pragma once
2df797f2bSMatt Spinler #include "stream.hpp"
3df797f2bSMatt Spinler 
4df797f2bSMatt Spinler #include <chrono>
5df797f2bSMatt Spinler 
6df797f2bSMatt Spinler namespace openpower
7df797f2bSMatt Spinler {
8df797f2bSMatt Spinler namespace pels
9df797f2bSMatt Spinler {
10df797f2bSMatt Spinler 
11df797f2bSMatt Spinler /**
12df797f2bSMatt Spinler  * @brief A structure that contains a PEL timestamp in BCD.
13df797f2bSMatt Spinler  */
14df797f2bSMatt Spinler struct BCDTime
15df797f2bSMatt Spinler {
16df797f2bSMatt Spinler     uint8_t yearMSB;
17df797f2bSMatt Spinler     uint8_t yearLSB;
18df797f2bSMatt Spinler     uint8_t month;
19df797f2bSMatt Spinler     uint8_t day;
20df797f2bSMatt Spinler     uint8_t hour;
21df797f2bSMatt Spinler     uint8_t minutes;
22df797f2bSMatt Spinler     uint8_t seconds;
23df797f2bSMatt Spinler     uint8_t hundredths;
24df797f2bSMatt Spinler 
BCDTimeopenpower::pels::BCDTime2586c70362SMatt Spinler     BCDTime() :
2686c70362SMatt Spinler         yearMSB(0), yearLSB(0), month(0), day(0), hour(0), minutes(0),
2786c70362SMatt Spinler         seconds(0), hundredths(0)
282544b419SPatrick Williams     {}
2986c70362SMatt Spinler 
BCDTimeopenpower::pels::BCDTime3086c70362SMatt Spinler     BCDTime(uint8_t yearMSB, uint8_t yearLSB, uint8_t month, uint8_t day,
3186c70362SMatt Spinler             uint8_t hour, uint8_t minutes, uint8_t seconds,
3286c70362SMatt Spinler             uint8_t hundredths) :
33*075c7923SPatrick Williams         yearMSB(yearMSB), yearLSB(yearLSB), month(month), day(day), hour(hour),
34*075c7923SPatrick Williams         minutes(minutes), seconds(seconds), hundredths(hundredths)
352544b419SPatrick Williams     {}
3686c70362SMatt Spinler 
37df797f2bSMatt Spinler     bool operator==(const BCDTime& right) const;
38df797f2bSMatt Spinler     bool operator!=(const BCDTime& right) const;
39df797f2bSMatt Spinler 
40df797f2bSMatt Spinler } __attribute__((packed));
41df797f2bSMatt Spinler 
42df797f2bSMatt Spinler /**
43df797f2bSMatt Spinler  * @brief Converts a time_point into a BCD time
44df797f2bSMatt Spinler  *
45df797f2bSMatt Spinler  * @param[in] time - the time_point to convert
46df797f2bSMatt Spinler  * @return BCDTime - the BCD time
47df797f2bSMatt Spinler  */
48df797f2bSMatt Spinler BCDTime getBCDTime(std::chrono::time_point<std::chrono::system_clock>& time);
49df797f2bSMatt Spinler 
50df797f2bSMatt Spinler /**
515fa87f08SMatt Spinler  * @brief Converts the number of milliseconds since the epoch into BCD time
525fa87f08SMatt Spinler  *
535fa87f08SMatt Spinler  * @param[in] milliseconds - Number of milliseconds since the epoch
545fa87f08SMatt Spinler  * @return BCDTime - the BCD time
555fa87f08SMatt Spinler  */
565fa87f08SMatt Spinler BCDTime getBCDTime(uint64_t milliseconds);
575fa87f08SMatt Spinler 
585fa87f08SMatt Spinler /**
590bf04b5dSMatt Spinler  * @brief Convert a BCDTime value into the number of
600bf04b5dSMatt Spinler  *        milliseconds since the epoch (1/1/1970).
610bf04b5dSMatt Spinler  *
620bf04b5dSMatt Spinler  * @param[in] bcdTime - The BCD time value
630bf04b5dSMatt Spinler  * @return uint64_t - The milliseconds value
640bf04b5dSMatt Spinler  */
650bf04b5dSMatt Spinler uint64_t getMillisecondsSinceEpoch(const BCDTime& bcdTime);
660bf04b5dSMatt Spinler 
670bf04b5dSMatt Spinler /**
68df797f2bSMatt Spinler  * @brief Converts a number to a BCD.
69df797f2bSMatt Spinler  *
70df797f2bSMatt Spinler  * For example 32 -> 0x32.
71df797f2bSMatt Spinler  *
72df797f2bSMatt Spinler  * Source: PLDM repository
73df797f2bSMatt Spinler  *
74df797f2bSMatt Spinler  * @param[in] value - the value to convert.
75df797f2bSMatt Spinler  *
76df797f2bSMatt Spinler  * @return T - the BCD value
77df797f2bSMatt Spinler  */
78df797f2bSMatt Spinler template <typename T>
toBCD(T decimal)79df797f2bSMatt Spinler T toBCD(T decimal)
80df797f2bSMatt Spinler {
81df797f2bSMatt Spinler     T bcd = 0;
82df797f2bSMatt Spinler     T remainder = 0;
83df797f2bSMatt Spinler     auto count = 0;
84df797f2bSMatt Spinler 
85df797f2bSMatt Spinler     while (decimal)
86df797f2bSMatt Spinler     {
87df797f2bSMatt Spinler         remainder = decimal % 10;
88df797f2bSMatt Spinler         bcd = bcd + (remainder << count);
89df797f2bSMatt Spinler         decimal = decimal / 10;
90df797f2bSMatt Spinler         count += 4;
91df797f2bSMatt Spinler     }
92df797f2bSMatt Spinler 
93df797f2bSMatt Spinler     return bcd;
94df797f2bSMatt Spinler }
95df797f2bSMatt Spinler 
96df797f2bSMatt Spinler /**
970bf04b5dSMatt Spinler  * @brief Converts a BCD byte to a decimal number.
980bf04b5dSMatt Spinler  *
990bf04b5dSMatt Spinler  * For example 0x22 -> 22.
1000bf04b5dSMatt Spinler  *
1010bf04b5dSMatt Spinler  * @param[in] bcd - The value in BCD
1020bf04b5dSMatt Spinler  * @return int - The number in decimal
1030bf04b5dSMatt Spinler  */
fromBCD(uint8_t bcd)1040bf04b5dSMatt Spinler inline int fromBCD(uint8_t bcd)
1050bf04b5dSMatt Spinler {
1060bf04b5dSMatt Spinler     return (((bcd & 0xF0) >> 4) * 10) + (bcd & 0xF);
1070bf04b5dSMatt Spinler }
1080bf04b5dSMatt Spinler 
1090bf04b5dSMatt Spinler /**
110df797f2bSMatt Spinler  * @brief Stream extraction operator for BCDTime
111df797f2bSMatt Spinler  *
112df797f2bSMatt Spinler  * @param[in] s - the Stream
113df797f2bSMatt Spinler  * @param[out] time - the BCD time
114df797f2bSMatt Spinler  *
115df797f2bSMatt Spinler  * @return Stream&
116df797f2bSMatt Spinler  */
117df797f2bSMatt Spinler Stream& operator>>(Stream& s, BCDTime& time);
118df797f2bSMatt Spinler 
119df797f2bSMatt Spinler /**
120df797f2bSMatt Spinler  * @brief Stream insertion operator for BCDTime
121df797f2bSMatt Spinler  *
122df797f2bSMatt Spinler  * @param[in/out] s - the Stream
123df797f2bSMatt Spinler  * @param[in] time - the BCD time
124df797f2bSMatt Spinler  *
125df797f2bSMatt Spinler  * @return Stream&
126df797f2bSMatt Spinler  */
127d7b004bfSMatt Spinler Stream& operator<<(Stream& s, const BCDTime& time);
128df797f2bSMatt Spinler 
129df797f2bSMatt Spinler } // namespace pels
130df797f2bSMatt Spinler } // namespace openpower
131