View previous topic :: View next topic |
Author |
Message |
pilar
Joined: 30 Jan 2008 Posts: 197
|
Working with bits |
Posted: Sat Sep 05, 2020 6:39 pm |
|
|
Hi, I need to represent the date and the time in only 3 bytes without including the minutes and the seconds. Assuming that a byte has 8 bits, then the hours I can represent it with 5 bits, the days also with 5 bits, the months with 4 bits which leaves me 10 bits to represent the year, how would my code be to represent today: 20/09/05 19 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Sep 05, 2020 9:59 pm |
|
|
Start counting the years at 0x00.
2020 = 0
2021 = 1
2022 = 2
.
.
.
2062 = 62
2063 = 63
That gives you a product life of 64 years, and it takes 6 bits.
That leaves 4 bits for something else. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sat Sep 05, 2020 11:53 pm |
|
|
Worth possibly also saying, you could just use the top 3 bytes of the
standard Unix time.
This (simply!...), codes time, as the number of seconds past it's epoch.
The epoch is either 1900, or 2010 (if the option TIME_T_USES_2010 is
enabled).
Now standard functions are supplied (in time.h/time.t), to convert
a time in year, month, day, hours, mins, secs etc., into this format, and
back. These are the standard Unix functions for this. The time is stored
in and int32, and though obviously involves adding this code, would save
having to write the conversions yourself. The functions understand about
things like leap years etc..
So if you then just store the upper three bytes of this value, and for
retrieval add a dummy '0' byte to the end, you can store 'time', to the
nearest 4.26 minutes, with all the work done for you. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sun Sep 06, 2020 4:53 am |
|
|
For decades I've stored date and time into 2 bytes.
Time( hrs-mns) is encoded into 7 bits, where each bit is a 15 minute 'slice of the day'. So 0=midnight, 1=00:15, 2=00:30,3=00:45. This leaves one free bit of the 1st byte.
You combine that free bit with the 2nd byte to store the Day of the year( 1-365).
The 3rd byte easily stores the year ( 20, 21,22) with lots of bits leftover.
The 'time in a byte' trick is from the reality(30+ years ago) that alarm 'opening and closings' and energy controls times(heat on/off) don't need to be ultra precise. Slicing 24 hrs into 128 'segments' gives nice 1/4 hr times. Back then it was critical to save bits of memory wherever you could as chips cost big $$$ !
You do have to encode/decode the bits of data, fairly simple but I don't know how it compares to using the UNIX time method. I know my 'hrsmns' is fast and creates compact code. Less of an issue today with fast PICs and lots of memory but... the OP did want 'compact' time.
This might be another option, or at least something to think about.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Sep 06, 2020 7:59 am |
|
|
That'll undoubtedly be quicker than the Unix version. But (of course), leaves
you having to do the calculations for maximum number of days in each
month etc.. |
|
|
pilar
Joined: 30 Jan 2008 Posts: 197
|
|
Posted: Sun Sep 06, 2020 10:53 am |
|
|
Hi, Based on your comments I want to convert the data read from a DS3231 to epoch seconds, for this I am using the time.h and time.c, here is my code, but I have errors, can someone tell me how to correct this?
Code: | #include <18F4520.h>
#fuses HS,NOWDT,WDT32768,PROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar
#include <time.h>
#include <time.c>
int32 timeSecond;
struct {
int8 myyear;
int8 mymonth;
int8 myday;
int8 myhour;
int8 mymin;
int8 mysec;
}timeDatos;
void main(){
timeDatos.myyear = 2020;
timeDatos.mymonth = 9;
timeDatos.myday = 6;
timeDatos.myhour = 12;
timeDatos.mymin = 30;
timeDatos.mysec = 59;
timeSecond = time_t mktime ( &timeDatos);
while (TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Sep 06, 2020 11:20 am |
|
|
Your time needs to be a struct_tm.
This is typedefed in time.h, and is what the mktime uses.
You don't want 'time_t' in front of mktime.
Code: |
#include <18F4520.h>
#fuses HS,NOWDT,WDT32768,PROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar
#ignore_warnings 242
#include <time.h>
#include <time.c>
#ignore_warnings none
signed int32 timeSecond;
struct_tm timeDatos;
void main(){
timeDatos.tm_year = 2020-1900; //year needs to be since 1900
timeDatos.tm_mon = 9;
timeDatos.tm_mday = 6;
timeDatos.tm_hour = 12;
timeDatos.tm_min = 30;
timeDatos.tm_sec = 59;
timeSecond = mktime ( &timeDatos);
while (TRUE);
}
|
I've added an ignore_warnings, since the driver will give warnings about
missing breaks. It is however correct.
The 'time' is a signed value. This allows you to do things like handle
dates before the 1900 epoch. |
|
|
pilar
Joined: 30 Jan 2008 Posts: 197
|
|
Posted: Sun Sep 06, 2020 11:51 am |
|
|
Hi Ttelmah, the result is:
Code: | timeSecond = 1602073859 |
but this is different from the value obtained using the https://www.epochconverter.com/
Code: | Epoch timestamp: 1599395459 |
How can I correct it? |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun Sep 06, 2020 11:55 am |
|
|
pilar wrote: | Hi Ttelmah, the result is:
Code: | timeSecond = 1602073859 |
but this is different from the value obtained using the https://www.epochconverter.com/
Code: | Epoch timestamp: 1599395459 |
How can I correct it? |
I thought it's supposed to be the time since 1970? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Sep 06, 2020 12:18 pm |
|
|
There are a number of different bases actually used for 'Unix time', as
well as a number of different formats. Unless you need to send the time
to a Unix system and then process it there, why care?. If you are
sending the time, send it as a time in ASCII.
I think you will find the difference is using 31st Jan or 1st Jan. |
|
|
pilar
Joined: 30 Jan 2008 Posts: 197
|
|
Posted: Sun Sep 06, 2020 1:45 pm |
|
|
Quote: | why care?. If you are
sending the time, send it as a time in ASCII |
Unfortunately, I only have 4 bytes to send this date and time data, and these 4 bytes is precisely the size of the epoch seconds expressed in hex, that's why my interest in that the epoch seconds is exact. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun Sep 06, 2020 2:04 pm |
|
|
If you are sending it to a pre-built system, don't they tell you what it is expecting?
Otherwise, if you are sending it to something you are designing yourself, you can define it however you need. In this case, I'm wondering what is the reason for the 4-byte restriction? If it's a memory restriction I highly recommend updating your hardware...
Do you change from your local time zone to UTC before doing the conversion?
I have some code that converted from the RTC struct rtc_time_t provided by CCS to work with PIC RTCs to unixtime:
Code: | struct_tm rtc_time_t_to_struct_tm(rtc_time_t realtime)
{
struct_tm tm;
tm.tm_sec = realtime.tm_sec;
tm.tm_min = realtime.tm_min;
tm.tm_hour = realtime.tm_hour;
tm.tm_mday = realtime.tm_mday;
tm.tm_mon = realtime.tm_mon - 1;
tm.tm_year = realtime.tm_year + 100;
return tm;
}
void func()
{
rtc_time_t realtime_utc;
// assign a time to realtime_utc here
struct_tm timestruct = rtc_time_t_to_struct_tm(realtime_utc);
time_t unixtime = mktime(×truct);
}
|
|
|
|
pilar
Joined: 30 Jan 2008 Posts: 197
|
|
Posted: Sun Sep 06, 2020 2:21 pm |
|
|
Quote: | I'm wondering what is the reason for the 4-byte restriction? If it's a memory restriction I highly recommend updating your hardware... |
I have hardware restriction. This is a very specific modem that only allows sending a specific number of data in this case only 16 bytes and only in hexadecimal. I am using 12 bytes for reading sensors and I only have 4 bytes for the date and time. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sun Sep 06, 2020 2:47 pm |
|
|
hmm...in your original post you had 3 bytes....and you only wanted yr/mt/dy/hr.
Having 4 bytes does open up for more coding options....and more data to be sent |
|
|
pilar
Joined: 30 Jan 2008 Posts: 197
|
|
Posted: Sun Sep 06, 2020 3:23 pm |
|
|
Quote: | hmm...in your original post you had 3 bytes....and you only wanted yr/mt/dy/hr. |
Yes it is true at the beginning it was my query on how to send yr/mt/dy/hr. in only 3 byts, but along the way I got curious about epoch seconds and since there are not many examples using CCS, keep asking; now I have two doubts, how to correct the epoch seconds and how can I send this data in only 3 bytes
Quote: | For decades I've stored date and time into 2 bytes. |
Please could you share your code with us on how you have managed to do this? |
|
|
|