DS1302 Module C code
Rsadeika
Posts: 3,837
in Propeller 1
The program below is something that Daniel Robert put together. I made a very slight adjustment, but it needs more improvements.
All of the code, for the DS1302, that is available, on the internet, is for other processors and not the Propeller. So, taking an exiting C program and just plugging into SimpleIDE does not work out very well.
The problem that I am having is trying to figure out how to write a time and date to the module. Not sure what format the module is expecting, and what the command would be for doing the write. If some of you C experts could show me some examples, it would be very helpful.
Of course I am using SimpleIDE and the FLiP module for the testing procedure.
Thanks
Ray
All of the code, for the DS1302, that is available, on the internet, is for other processors and not the Propeller. So, taking an exiting C program and just plugging into SimpleIDE does not work out very well.
The problem that I am having is trying to figure out how to write a time and date to the module. Not sure what format the module is expecting, and what the command would be for doing the write. If some of you C experts could show me some examples, it would be very helpful.
Of course I am using SimpleIDE and the FLiP module for the testing procedure.
Thanks
Ray
/* rtc_test.c September 15, 2018 Parallax DS1302 Real_Time Clock module. Original program by Daniel Robert. */ #include "simpletools.h" int *cog; /* Using pins 17,18,19 with the FLiP module.*/ #define ds1302cs 19 #define ds1302sclk 18 #define ds1302io 17 #define dsSec 0x80 #define dsMin 0x82 #define dsHour 0x84 #define dsDate 0x86 #define dsMon 0x88 #define dsDay 0x8A #define dsYear 0x8C #define dsWpa 0x8E #define dsTca 0x90 volatile int seconds,minutes,hours,date,month,day,year,prevSec; volatile long flagWord; void writeDs1302(int myreg, int value) { high(ds1302cs); shift_out(ds1302io, ds1302sclk, LSBFIRST, 8, myreg); shift_out(ds1302io, ds1302sclk, LSBFIRST, 8, value); low(ds1302cs); } int readDs1302(int myreg) { int readreg = myreg + 1; high(ds1302cs); shift_out(ds1302io, ds1302sclk, LSBFIRST, 8, readreg); int result = shift_in(ds1302io, ds1302sclk, LSBPRE, 8); low(ds1302cs); return result; } /* COG 1*/ void dsClock(); /* COG 0 */ int main() { // Add startup code here. flagWord = 0x80000000; cog = cog_run(dsClock, 128); while(flagWord != 0){} flagWord = 0x80000000 | (dsMin << 8) | 0x40; while (flagWord !=0){} while(1) { // Add main loop code here. putHexLen(hours, 2); putStr(":"); putHexLen(minutes,2); putStr(":"); putHexLen(seconds,2); putStr(" "); /* Display in month day year format. */ putHexLen(month,2); putStr("/"); putHexLen(date,2); putStr("/"); putHexLen(year,2); putChar(NL); // New line pause(500); } } /* COG 1*/ void dsClock() { low(ds1302cs); low(ds1302sclk); writeDs1302(dsWpa, 0); int started = readDs1302(dsSec); if((started & 0x80) !=0) { writeDs1302(dsSec, 0); } flagWord = 0; while(1) { if(prevSec != readDs1302(dsSec)) { seconds = readDs1302(dsSec); prevSec = seconds; hours = readDs1302(dsHour); minutes = readDs1302(dsMin); date = readDs1302(dsDate); month = readDs1302(dsMon); day = readDs1302(dsDay); year = readDs1302(dsYear); } if(flagWord != 0) { writeDs1302(((flagWord >> 8) & 0xFF), (flagWord & 0xFF)); flagWord = 0; } pause(100); } }
Comments
writeDs1302(int myreg, int value) is the "command" that is used for write.
Determining the values to be written (that is, current date and time) is a little messier. I always used a couple of buttons and a state machine.
Edit: There is something I don't understand about this program: writeDs1302 and readDs1302 are defined prior to int main(). Yet they are apparently accessible to void dsClock() in another cog. How does this work?
DS1302 Library
Mike
Doing a quick test, it looks like the time and date are correct when it is printed back. I guess this could be a stand alone program that you would run one time to set the time and date of the DS1302. I guess I need to write some code for accessing the time and date within a general program.
Anybody have any ideas for simplifying or condensing the program code below?
Ray
Ray
I'm not a C guru by any means, but you might be able to reduce the number of "print" statements quite a bit by putting the constants text (ie "Day: Month: etc) in a string that has space for the actual variables and then converting the variables to text and inserting them in the string. Not sure how well it would work with C, but it works like a charm in Spin.
But, before I proceed with that, I also purchased an ADC0831 chip. I will start another thread for some advise as to how to proceed with that. Of course it will be C code using SimpleIDE.
Ray
First, I took your code and copied it into one of my scratch projects which is built with PropWare. There are two important differences and I don't know which one is causing the result (or both?)
Building your code with SimpleIDE:
Code size: 6,420 b
Total size: 7,184 b
Building your code with PropWare:
Code size: 7,128 b
Total size: 7,480 b
Strange that they're different. Not only are they different, but the ratio of code size to total size is significantly different.
Anyway, then I got really curious how the PropWare classes compared in code size to what you were doing (since you were trying to get your code size down as small as possible). So, I took your code and converted it to PropWare and left all of the original code commented out so you can see line-for-line what everything does. Here's my code size results:
Code size: 6,212 b
Total size: 6,604 b
I don't have a DS1302 sitting around to test it out... no idea if it works... hopefully?
Overall, your code is pretty darned effecient. I think you did a good job. Use of the individual putChar, putHex, etc functions was a very smart way to start.
More so now though, I only read the RTC hardware itself at reset and once a day at midnight to update the date and to synchronize a 32-bit milliseconds time of day counter which is used directly for time stamps (I add in day of month into the the top 5 bits) and converted easily and quickly for whatever format I need to read the time in. This also means I can support multiple types of RTC chips (DS3231/PCF8563/MCP79410 etc) at runtime without hardly any complication and the bonus is that I don't suffer I2C bus conflicts or lengthy transactions. None of this really takes much code memory, I worked out that even with all the fancy formatting and soft and hard RTC code including my general 1ms cog timing task that maintains runtime, milliseconds of the day, linked 32-bit timeouts and alarms etc that this is around 1100 bytes.