Shop OBEX P1 Docs P2 Docs Learn Events
DS1307 SD-MMC FAT Engine with propGCC? — Parallax Forums

DS1307 SD-MMC FAT Engine with propGCC?

AkkarinAkkarin Posts: 43
edited 2014-02-26 14:36 in Propeller 1
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.
#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

  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-02-11 07:42
    Have you looked at either libpropeller or PropWare?

    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.
  • jazzedjazzed Posts: 11,803
    edited 2014-02-11 09:08
    Hi.

    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;
    }
    
    Implementation of these functions is left as an exercise for the reader.
    int GbI2C_rtc_getReg(int maddr)
    {
    }
    
    void GbI2C_rtc_writeReg(int maddr, unsigned char mdata)
    {
    }
    
  • AkkarinAkkarin Posts: 43
    edited 2014-02-11 22:20
    @SwimDude0614: No and no ;) I will have a look later. Thanks.

    @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.
  • jazzedjazzed Posts: 11,803
    edited 2014-02-11 22:46
    Akkarin wrote: »
    @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.
    Propeller GCC has file-system C library support, and date-time C library support built-in. Devices and drivers always need connections though. I've demonstrated the API. Someone like SwimDude0614 and SRLM may benefit from that in their driver library.

    It's likely best if you stick with SPIN if that code throws you a curve-ball.
  • AkkarinAkkarin Posts: 43
    edited 2014-02-11 23:37
    Hi jazzed,

    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.
  • jazzedjazzed Posts: 11,803
    edited 2014-02-12 13:35
    Akkarin wrote: »
    Hi jazzed,

    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.
    My .sig has pointers to documentation. Libraries use device drivers. Follow these links.

    https://sites.google.com/site/propellergcc/documentation/libraries

    http://propgcc.googlecode.com/hg/doc/Library.html
  • AkkarinAkkarin Posts: 43
    edited 2014-02-21 02:22
    Hi,

    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);
    }
    
    //RTC.h
    #ifndef __RTC_H
    #define __RTC_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
    
    time_t RTC_getTime(void);
    
    #endif
    

    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.
  • AkkarinAkkarin Posts: 43
    edited 2014-02-25 08:12
    Hi,

    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);
    }
    ...
    
  • jazzedjazzed Posts: 11,803
    edited 2014-02-26 14:36
    Akkarin wrote: »
    Hi,

    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:

    Great. I never noticed that function before.

    Sounds like progress.
Sign In or Register to comment.