Create FAT Date/time from DS1307 output

BCJKiwi

Senior Member
Looking to create the Fat file system Dword value from the current date & time returned from a DS1307 Clock.

Why you may well ask.

Am testing a uAlfat-TF device. This is GHI Electronics' competition to the VDrive2.
After a few initial hiccups it is currently writing continuously to a file on a microSD (or TransFlash) card using Hi2c. Found issues with hSPI.

Filename is being created from the date&time which is straightforward.

However the uAlFat system has a built in clock to create file date/timestamps used by the FAT file system. So the clock has to be set in that system as well - real friendly!

The information given is as follows;
Time and Date structure is a DWORD Standard structure in FAT system
Bits(s) Field Description
31..25 Year Years since 1980
24..21 Month 1..12
20..16 Day 1..31
15..11 Hour 0..23
10..5 Minute 0..59
4..0 Second Seconds divided by 2
The set Date Time data has to be sent in the form ddddtttt.
The example given is the date time value of 1/1/2006 00:00:00 is written as 34210000.

The DS1307 returns the time data in BCD which is currently converted with the bcdtoascii function
However to get the DWORD format the YMD data has to be converted into one word and the HMS data into another.
My research on FAT file systems indicates that the individual values can be converted to hex then added together to get the word values.
I have not found a way to do this in PICAXE Integer math and am hoping some of you math gurus might help.

Thanks
 

lbenson

Senior Member
Try this in the simulator. I think it will work, giving you yymmdd in w5 and hhmmss in w6.

b0=2006 - 1980 ' year
b1 = 1 ' month
b2 = 1 ' day
b3 = 13 ' hour
b4 = 25 ' minutes
b5 = 15 ' seconds
w5 = b0 * 512 ' shift year to bits 9-15
w6 = b1 * 32 ' shift month to bits 5-8
w5 = w5 + w6 + b1 ' result of $3421
w6 = b3 * 2048 ' shift hour to bits 11-15
w0 = b4 * 128 ' shift minutes to bits 5-10
b5 = b5 /2 ' seconds divided by 2
w6 = w6 + w0 + b5
 
Last edited:

BCJKiwi

Senior Member
Thanks very much for your input. Have worked with your code but it did not seem to produce the expected results.

For testing purposes the simulator was used to calculate the hex w5 and w6 values from your code, and then in the working program, the ascii string of the hex digits was sent to the device.

One issue is that the device wants the calculated hex value (i.e. the $3421 etc ) to be entered as an ascii string "3421 etc". I have no idea how to get the ascii representation of the same digits from the hex.
The other thing was that when I input the data as an ascii string some of the values were not returned correctly.

After much study of the sample a couple of things became apparent.
this line
w5 = w5 + w6 + b1 ' result of $3421
should be
w5 = w5 + w6 + b2 ' result of $3421 - has an effect if b1 and b2 are not both 1!

the other was that this line
w0 = b4 * 128 ' shift minutes to bits 5-10
should be
w0 = b4 * 32 ' shift minutes to bits 5-10 - same shift as for months

Since I'm using a 28X1, I realised this is the same as the << function so have written the last part up as;
w5 = b0 << 9 'shift year to bits 9-15
w6 = b1 << 5 'shift month to bits 5-8
w5 = w5 + w6 + b2 ' result of $3421 'YMD
w6 = b3 << 11 ' shift hour to bits 11-15
w4 = b4 << 5 ' shift minutes to bits 5-10
b5 = b5 /2 ' seconds divided by 2
w6 = w6 + w4 + b5 'HMS

So the remaining issue is how to translate the w5 and w6 values into ascii containing the same digits as for hex.

Using your example values of 06/1/1 13:25:15 (yy/mm/dd hh:mm:ss)
the revised code gives hex values of $3421 and $6B27
If these are sent to the device as an ascii string of "34216B27"
then everything works.
the actual code line is;
hi2cout ("S 34216B27",$0D)

Thanks very much for you assistance on this and I'm wondering if you have some magic for this last puzzle?
 
Last edited:

lbenson

Senior Member
Oops. Thanks for cleaning up the code. The b1 instead of b2 error was masked because, as you point out, the values were the same, and on the 128 instead of 32, I confused myself after getting it right the first time I tried it. Your shifts make it look clearer (for those with X1 parts).

Your problem with getting the hex results into ascii is that you need to represent each "nibble" (half a byte) as an ascii character. So if b11 = $34, then you get the first nibble into b0 and the second into b1 by saying
b0 = b11 >> 4 + "0" ' ASCII "3"
b1 = b11 & $0F + "0" ' ASCII "4"
and so on for the remaining 3 bytes. But you also have to compare each result and if it is greater than "9", add another 7 so that it shifts this hex value up into the range "A","B", etc. of the ASCII table.
if b0 > "9" then
b0 = b0 + 7
endif
 
Last edited:

BCJKiwi

Senior Member
Thanks again for your input.
After some fiddling around I got the 'nibble' code working and output being accepted.

Once I had it working in the simulator with manual input, I found the data returned from the DS1307 , being in ascii, needed conversion to decimal. The input routine for the DS1307 uses BCDTOASCII to get ascii and store it in the scratchpad.

I also utilised the routines you provided here;
http://www.picaxeforum.co.uk/showthread.php?t=8451
for PFM - modified the *16 to *10 - as Decimal was needed not BCD.

Also figured a mod was required to the code snippet;
b0 = "5"
b1 = "9"
b0 = b0 - $30 * 16 + b1 - $30
The last '- $30' comes off the whole value of the calculation up to there, not just the b1?
I felt it should be;
b0 = "5"
b1 = "9"
b0 = b0 - $30
b1 = b1 - $30
b0 = b0 * 16 + b1 (or in my case *10 for decimal)

So my code now looks like this;
Code:
 'sertxd ("< Set Clock >")
 ptr = 192 'set scatchpad pointer to beginning of clock data
gosub uAget_clk
 b0 =w11+2000-1980 'YY - convert to number of years since 1980
gosub uAget_clk
 b1=w11
gosub uAget_clk
 b2=w11
gosub uAget_clk
 b3=w11
gosub uAget_clk
 b4=w11
gosub uAget_clk
 b5=w11
w5 = b0 << 9   '* 512 ' shift year to bits 9-15
w6 = b1 << 5   '* 32 ' shift month to bits 5-8
w5 = w5 + w6 + b2  'YMD
w6 = b3 << 11   '* 2048 ' shift hour to bits 11-15
w4 = b4 << 5   '* 128 ' shift minutes to bits 5-10
b5 = b5 /2    ' seconds divided by 2
w6 = w6 + w4 + b5  'HMS
gosub uAget_nibbles
'set time
 hi2cout ("S ",b0,b1,b2,b3,b4,b5,b6,b7,$0D) 'set time in clock
 
#########################################################################
#  SUBROUTINES         #
#########################################################################
'
uAget_clk:
 b20 = @ptr  'Get ascii clock data from scatchpad
 b20 = b20-$30 'change ascii to hex
 inc ptr  'next data
 b21 = @ptr  'Get ascii clock data from scatchpad
 b21 = b21-$30 'change ascii to hex
 w11 = b20 * 10 'shift high byte 
 w11 = w11 + b21 'add low byte
 inc ptr
return
uAGet_nibbles:
' Create 8 nibbles from 2 words and convert to ascii representation of Hex Data
' to send to uAlfat in required ascii format ( a DWORD of int32 in 'C' )
b0 = b11 >> 4   'shift high nibble to low nibble
if b0 > 9 then  'test to see if hex over numerical value
 b0=b0+7+"0"  'if so, convert to alpha value - convert to ascii
else b0=b0+"0"  ' else leave as numerical - convert to ascii
endif
b1 = b11 & $0F
if b1 > 9 then
 b1=b1+7+"0"
else b1=b1+"0"
endif
b2 = b10 >> 4
if b2 > 9 then
 b2=b2+7+"0"
else b2=b2+"0"
endif
b3 = b10 & $0F
if b3 > 9 then
 b3=b3+7+"0"
else b3=b3+"0"
endif
b4 = b13 >> 4
if b4 > 9 then
 b4=b4+7+"0"
else b4=b4+"0"
endif
b5 = b13 & $0F
if b5 > 9 then
 b5=b5+7+"0"
else b5=b5+"0"
endif
b6 = b12 >> 4
if b6 > 9 then
 b6=b6+7+"0"
else b6=b6+"0"
endif
b7 = b12 & $0F
if b7 > 9 then
 b7=b7+7+"0"
else b7=b7+"0"
endif
Return
So again, many thanks for your assistance which is greatly appreciated.
 
Last edited:

hippy

Ex-Staff (retired)
I felt it should be;
b0 = "5"
b1 = "9"
b0 = b0 - $30
b1 = b1 - $30
b0 = b0 * 16 + b1 (or in my case *10 for decimal)
or, for bcd ...

b0 = "5"
b1 = "9"
b0 = b0 * 16 + b1 - $330 ' $330 = $30 * 16 + $30

and, for decimal ...

b0 = b0 * 10 + b1 - $210 ' $210 = $30 * 10 + $30
 
Top