DS1307 SD-MMC FAT Engine with propGCC?
Akkarin
Posts: 43
Hi all,
I'm quite new to C. I had a C course at university some years ago, but haven't touched it since nor have I ever done complex projects like in Spin lately. I'm in the process of evaluating if C could be an alternative way of programming the Prop for me.
I like the idea, that C programs would be faster than Spin or to have large programs with XMM (though I haven't understood that completely yet).
So, one requirement would be to write to an SD card. I managed to do so in a simple test program.
But I really like Kye's FAT Engine with RTC support, error handling and file system. Is there a way to use this driver in simple IDE so that it is compiled in C and not running in a Spin COG?
Thanks,
Akk4rin
I'm quite new to C. I had a C course at university some years ago, but haven't touched it since nor have I ever done complex projects like in Spin lately. I'm in the process of evaluating if C could be an alternative way of programming the Prop for me.
I like the idea, that C programs would be faster than Spin or to have large programs with XMM (though I haven't understood that completely yet).
So, one requirement would be to write to an SD card. I managed to do so in a simple test program.
#include "simpletools.h"
#include "simpletext.h"
#include "simplei2c.h"
char name[20];FILE *fp1;
int main(void)
{
sd_mount(8,7,6,5);
sprintf(name,"Test.txt"); // test file name
printf("Opening file '%s'.\n", name);
if((fp1=fopen(name,"w+"))==0) {
printf("Can't open file %s.\n",name);
}
else {
printf("File was opened.\n");
fprintf(fp1,"Test\r\n");
fprintf(fp1,"123\r\n");
fclose(fp1);
high(11);
}
return 0;
But I really like Kye's FAT Engine with RTC support, error handling and file system. Is there a way to use this driver in simple IDE so that it is compiled in C and not running in a Spin COG?
Thanks,
Akk4rin

Comments
I know PropWare doesn't have RTC support (I don't think libpropeller does either) but they are informative about errors. PropWare does support traversing directories as well.
Example code for file-system is here: https://sites.google.com/site/propellergcc/documentation/libraries#TOC-Console-and-File-system-driver-initialization
Adding RTC is relatively trivial as long as you have an i2c driver.
/** * @file RTC1338.c generic DS1307 interface. */ #include <stdio.h> #include <sys/rtc.h> #include <sys/time.h> #include <time.h> /* ================================================================= RTC REGISTERS ================================================================= */ #define GbI2C_RTC_SECOND 0 #define GbI2C_RTC_MINUTE 1 #define GbI2C_RTC_HOUR 2 #define GbI2C_RTC_DAY 3 #define GbI2C_RTC_DATE 4 #define GbI2C_RTC_MONTH 5 #define GbI2C_RTC_YEAR 6 #define GbI2C_RTC_CONTROL 7 /* separate functions */ extern int GbI2C_rtc_getReg(int maddr); extern void GbI2C_rtc_writeReg(int maddr, unsigned char mdata); // RTC year is only 0-99. Unix computing epoc is Jan 1, 1970 #define YEARADJUST 70 static time_t mytime; int RTC_setTime(const struct timeval *tv) { unsigned char ones, tens; struct tm *t = localtime(&tv->tv_sec); mytime = tv->tv_sec; /* printf("%02d:%02d:%02d ",t->tm_hour, t->tm_min, t->tm_sec); printf("%02d-%02d-%04d %d %d\n",t->tm_mon, t->tm_mday, t->tm_year, t->tm_wday, tv->tv_sec); printf("RTC_setTime Seconds = %10d TimeStamp %s\n", mytime, asctime(t)); */ /* * write rtc register fields. */ /* make sure seconds are encoded as BCD */ ones = t->tm_sec & 0xf; tens = (t->tm_sec/10) & 0x7; t->tm_sec = (tens << 4) + ones; /* CH bit is 0 by now. Should be to keep timer going */ GbI2C_rtc_writeReg(GbI2C_RTC_SECOND, t->tm_sec); /* make sure minutes are encoded as BCD */ ones = t->tm_min & 0xf; tens = (t->tm_min/10) & 0x7; t->tm_min = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_MINUTE, t->tm_min); /* make sure hours are encoded as BCD 24 hour time */ ones = t->tm_hour & 0xf; tens = (t->tm_hour/10) & 0x3; t->tm_hour = (tens << 4) + ones; /* 24 hour bit is 0 by now */ GbI2C_rtc_writeReg(GbI2C_RTC_HOUR, t->tm_hour); /* make sure week days are encoded as BCD */ t->tm_wday &= 0xf; GbI2C_rtc_writeReg(GbI2C_RTC_DAY, t->tm_wday); /* make sure month days are encoded as BCD */ ones = t->tm_mday & 0xf; tens = (t->tm_mday/10) & 0x3; t->tm_mday = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_DATE, t->tm_mday); /* make sure months are encoded as BCD */ ones = t->tm_mon & 0xf; tens = (t->tm_mon/10) & 0x1; t->tm_mon = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_MONTH, t->tm_mon+1); /* make sure years are encoded as BCD */ ones = (t->tm_year-YEARADJUST) & 0xf; tens = ((t->tm_year-YEARADJUST)/10); t->tm_year = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_YEAR, t->tm_year); return 0; } int RTC_getTime(struct timeval *tv) { struct tm t; /* read all rtc registers */ GbI2C_rtc_readRegs(); /* get rtc register fields */ t.tm_sec = GbI2C_rtc_getReg(GbI2C_RTC_SECOND); t.tm_min = GbI2C_rtc_getReg(GbI2C_RTC_MINUTE); t.tm_hour = GbI2C_rtc_getReg(GbI2C_RTC_HOUR); t.tm_wday = GbI2C_rtc_getReg(GbI2C_RTC_DAY); t.tm_mday = GbI2C_rtc_getReg(GbI2C_RTC_DATE); t.tm_mon = GbI2C_rtc_getReg(GbI2C_RTC_MONTH)-1; t.tm_year = GbI2C_rtc_getReg(GbI2C_RTC_YEAR); t.tm_sec = ((t.tm_sec >> 4) & 7)*10 + (t.tm_sec & 0xF); // bcd conversion t.tm_min = ((t.tm_min >> 4) & 7)*10 + (t.tm_min & 0xF); // bcd conversion t.tm_hour = ((t.tm_hour >> 4) & 1)*10 + (t.tm_hour & 0xF); // bcd conversion t.tm_wday = t.tm_wday & 0x7; t.tm_mday = ((t.tm_mday >> 4) & 3)*10 + (t.tm_mday & 0xF); // bcd conversion t.tm_mon = ((t.tm_mon >> 4) & 3)*10 + (t.tm_mon & 0xF); // bcd conversion t.tm_year = (t.tm_year >> 4)*10 + (t.tm_year & 0xF); // bcd conversion t.tm_year = t.tm_year + YEARADJUST; mytime = mktime(&t); tv->tv_sec = mytime; tv->tv_usec = 0; /* printf("%02d:%02d:%02d ",t.tm_hour, t.tm_min, t.tm_sec); printf("%02d-%02d-%04d %d %d\n",t.tm_mon, t.tm_mday, t.tm_year, t.tm_wday, tv->tv_sec); printf("RTC_getTime Seconds = %10d TimeStamp %s\n", mytime, asctime(&t)); */ return 0; } void RTC_init() { int t; /* make sure clock is enabled */ t = GbI2C_rtc_getReg(GbI2C_RTC_SECOND) & ~(0x80); GbI2C_rtc_writeReg(GbI2C_RTC_SECOND, t); /* make sure we are using 24 hour time */ t = GbI2C_rtc_getReg(GbI2C_RTC_HOUR) & ~(0x40); GbI2C_rtc_writeReg(GbI2C_RTC_HOUR, t); /* set generic driver interface to our functions */ _rtc_gettime = RTC_getTime; _rtc_settime = RTC_setTime; }int GbI2C_rtc_getReg(int maddr) { } void GbI2C_rtc_writeReg(int maddr, unsigned char mdata) { }@jazzed: Oh my, I will need some time to get my head around that code you posted. Thanks.
So, in the end it does not seem possible to use Kye's DS1307 FAT Engine with propGCC and simple IDE. At least not without a lot of effort.
It's likely best if you stick with SPIN if that code throws you a curve-ball.
that's what I thought, too. I will have to get deeper into C programming first. Thanks anyway. Is there a good document, especially for that devices and drivers link part? I don't think I need the "hello world" part, though. Just a little more documentation in written words and not only code snippets.
https://sites.google.com/site/propellergcc/documentation/libraries
http://propgcc.googlecode.com/hg/doc/Library.html
I managed to get the clock value from my RTC. Here is the code I produced, though I think this is not the way it is supposed to be used, but I don't understand the generic driver concept, yet.
/** * This is the main SD Test program file. */ #include "simpletools.h" #include "simpletext.h" #include "simplei2c.h" #include "RTC.h" char name[20]; FILE *fp1; int main(void) { time_t mytime; sd_mount(8,7,6,5); sprintf(name,"Test.txt"); // test file name printf("Opening file '%s'.\n", name); if((fp1=fopen(name,"w+"))==0) { printf("Can't open file %s.\n",name); } else { printf("File was opened.\n"); fprintf(fp1,"Test\r\n"); fprintf(fp1,"123\r\n"); fclose(fp1); mytime = RTC_getTime(); printf("RTC_getTime Seconds = %10d TimeStamp %s\n", mytime, ctime(&mytime)); high(11); } return 0; }//RTC.c #include "simplei2c.h" #include "stdio.h" #include "time.h" #include "RTC.h" /* separate functions */ int GbI2C_rtc_getReg(int maddr); // RTC year is only 0-99. Unix computing epoch is Jan 1, 1970 #define YEARADJUST 100 static time_t mytime; //Whenever you declare static data, it will get stored in the hub by default. i2c bus; // = i2c_newbus(28,29,0); /* int RTC_setTime(const struct timeval *tv) { unsigned char ones, tens; struct tm *t = localtime(&tv->tv_sec); mytime = tv->tv_sec; */ /* printf("%02d:%02d:%02d ",t->tm_hour, t->tm_min, t->tm_sec); printf("%02d-%02d-%04d %d %d\n",t->tm_mon, t->tm_mday, t->tm_year, t->tm_wday, tv->tv_sec); printf("RTC_setTime Seconds = %10d TimeStamp %s\n", mytime, asctime(t)); */ /* * write rtc register fields. */ /* make sure seconds are encoded as BCD */ /* ones = t->tm_sec & 0xf; tens = (t->tm_sec/10) & 0x7; t->tm_sec = (tens << 4) + ones; */ /* CH bit is 0 by now. Should be to keep timer going */ //GbI2C_rtc_writeReg(GbI2C_RTC_SECOND, t->tm_sec); /* make sure minutes are encoded as BCD */ /* ones = t->tm_min & 0xf; tens = (t->tm_min/10) & 0x7; t->tm_min = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_MINUTE, t->tm_min); */ /* make sure hours are encoded as BCD 24 hour time */ /* ones = t->tm_hour & 0xf; tens = (t->tm_hour/10) & 0x3; t->tm_hour = (tens << 4) + ones; */ /* 24 hour bit is 0 by now */ //GbI2C_rtc_writeReg(GbI2C_RTC_HOUR, t->tm_hour); /* make sure week days are encoded as BCD */ /* t->tm_wday &= 0xf; GbI2C_rtc_writeReg(GbI2C_RTC_DAY, t->tm_wday); */ /* make sure month days are encoded as BCD */ /* ones = t->tm_mday & 0xf; tens = (t->tm_mday/10) & 0x3; t->tm_mday = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_DATE, t->tm_mday); */ /* make sure months are encoded as BCD */ /* ones = t->tm_mon & 0xf; tens = (t->tm_mon/10) & 0x1; t->tm_mon = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_MONTH, t->tm_mon+1); */ /* make sure years are encoded as BCD */ /* ones = (t->tm_year-YEARADJUST) & 0xf; tens = ((t->tm_year-YEARADJUST)/10); t->tm_year = (tens << 4) + ones; GbI2C_rtc_writeReg(GbI2C_RTC_YEAR, t->tm_year); return 0; } */ time_t RTC_getTime(void) { struct tm t; /* get rtc register fields */ t.tm_sec = GbI2C_rtc_getReg(GbI2C_RTC_SECOND); t.tm_min = GbI2C_rtc_getReg(GbI2C_RTC_MINUTE); t.tm_hour = GbI2C_rtc_getReg(GbI2C_RTC_HOUR); t.tm_wday = GbI2C_rtc_getReg(GbI2C_RTC_DAY)-1; //1 = sunday, 2 = monday,...,7 = saturday t.tm_mday = GbI2C_rtc_getReg(GbI2C_RTC_DATE); t.tm_mon = GbI2C_rtc_getReg(GbI2C_RTC_MONTH)-1; t.tm_year = GbI2C_rtc_getReg(GbI2C_RTC_YEAR); t.tm_sec = ((t.tm_sec >> 4) & 7)*10 + (t.tm_sec & 0xF); // bcd conversion t.tm_min = ((t.tm_min >> 4) & 7)*10 + (t.tm_min & 0xF); // bcd conversion t.tm_hour = ((t.tm_hour >> 4) & 1)*10 + (t.tm_hour & 0xF); // bcd conversion t.tm_wday = t.tm_wday & 0x7; t.tm_mday = ((t.tm_mday >> 4) & 3)*10 + (t.tm_mday & 0xF); // bcd conversion t.tm_mon = ((t.tm_mon >> 4) & 3)*10 + (t.tm_mon & 0xF); // bcd conversion t.tm_year = (t.tm_year >> 4)*10 + (t.tm_year & 0xF); // bcd conversion t.tm_year = t.tm_year + YEARADJUST; mytime = mktime(&t); //Convert tm structure to time_t //printf("%02d:%02d:%02d\n",t.tm_hour, t.tm_min, t.tm_sec); //printf("RTC_getTime Seconds = %10d TimeStamp %s\n", mytime, asctime(&t)); return mytime; } int GbI2C_rtc_getReg(int maddr) { int data; i2c_open(&bus,28,29,1); i2c_start(&bus); i2c_writeByte(&bus,0xD0); // = 0xD0 + 0 = 1101000 (slave address) + 0 (write) i2c_writeByte(&bus,maddr); //register the RTC should send i2c_start(&bus); //repeated start i2c_writeByte(&bus,0xD1); // = 0xD0+1 = 1101000 (slave address) + 1 (read) data = i2c_readByte(&bus,1); //printf("%x \n",data); return data; i2c_stop(&bus); }Up to now I only have implemented the read methods.
How can I write the creation time attribute or modification time attribute of a file on SD card? I could put the time in the file name but this is limited by the 8.3 file name format.
in sys/sd.h I found a function "void dfs_setDefaultFileDateTime(struct tm* tm);".
So when I call this right before creating a file on SD card, the new file will have the correct creation and modification time attributes:
... mytime = RTC_getTime(); //mytime is of type time_t dfs_setDefaultFileDateTime(localtime(&mytime)); if((fp1=fopen(name,"w+"))==0) { printf("Can't open file %s.\n",name); } ...Great. I never noticed that function before.
Sounds like progress.