SOLVED: Old datalogger with new RTC

Dear community,
I found a cheap, low power, accurate and oscillator-free RTC chip, the RV3029 by MicroCrystal.com. The good people there sent me readily a breakout board and a couple of chips. A month later, I found the fitting example code in elektor (thanks to Danny Winkler).
I put together the good old AnalogLogger example from the SdFat library and substituted the DS1307 with the fitting code for the RV3029.

// A simple data logger for the Arduino analog pins with optional RV3029

#include <SdFat.h>
#include <SdFatUtil.h>  // define FreeRam()

#define SD_CHIP_SELECT  SS  // SD chip select pin
#define LOG_INTERVAL  100  // mills between entries
#define SENSOR_COUNT     6  // number of analog pins to log
#define ECHO_TO_SERIAL   1  // echo data to serial port if nonzero
#define WAIT_TO_START    1  // Wait for serial input in setup()
#define ADC_DELAY       10  // ADC delay for high impedence sensors

// file system object
SdFat sd;

// text file for logging
ofstream logfile;

// Serial print stream
ArduinoOutStream cout(Serial);

// buffer to format data - makes it eaiser to echo to Serial
char buf[80];
//------------------------------------------------------------------------------
#if SENSOR_COUNT > 6
#error SENSOR_COUNT too large
#endif  // SENSOR_COUNT
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
#include <Wire.h>

int second, minute, hour, day, dom, month, year;

//------------------------------------------------------------------------------
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
  get_clock;

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(year, month, dom);

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(hour, minute, second);
}

void getFilename(char *filename) {
  get_clock;
  filename[0] = (year - 2000) / 10 + '0';
  filename[1] = year % 10 + '0';
  filename[2] = month / 10 + '0';
  filename[3] = month % 10 + '0';
  filename[4] = dom / 10 + '0';
  filename[5] = dom % 10 + '0';
  /*filename[6] = '.';
    filename[7] = 'C';
    filename[8] = 'S';
    filename[9] = 'V';*/
  return;
}

//------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial) {} // wait for Leonardo

  // pstr stores strings in flash to save RAM
  cout << endl << pstr("FreeRam: ") << FreeRam() << endl;

#if WAIT_TO_START
  cout << pstr("Type any character to start\n");
  while (Serial.read() <= 0) {}
  delay(400);  // catch Due reset problem
#endif  // WAIT_TO_START

  Wire.begin();
  init_clock;
  get_clock;

  // set date time callback function
  SdFile::dateTimeCallback(dateTime);
  get_clock();

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  if (!sd.begin(SD_CHIP_SELECT, SPI_HALF_SPEED)) sd.initErrorHalt();

  char filename[] = "000000.CSV";

  getFilename(filename);
  logfile.open(filename);
  /*
    // create a new file in root, the current working directory
    //char name[] = "LOGGER00.CSV";

    for (uint8_t i = 0; i < 100; i++) {
    name[6] = i / 10 + '0';
    name[7] = i % 10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
    }
    if (!logfile.is_open()) error("file.open");
  */

  cout << pstr("Logging to: ") << filename << endl;
  cout << pstr("Type any character to stop\n\n");

  // format header in buffer
  obufstream bout(buf, sizeof(buf));

  bout << pstr("millis");

  bout << pstr(",date,time");

  for (uint8_t i = 0; i < SENSOR_COUNT; i++) {
    bout << pstr(",sens") << int(i);
  }
  logfile << buf << endl;

#if ECHO_TO_SERIAL
  cout << buf << endl;
#endif  // ECHO_TO_SERIAL
}
//------------------------------------------------------------------------------
void loop() {
  uint32_t m;

  // wait for time to be a multiple of interval
  do {
    m = millis();
  } while (m % LOG_INTERVAL);

  // use buffer stream to format line
  obufstream bout(buf, sizeof(buf));

  // start with time in millis
  bout << m;
  get_clock();
  bout << ',' << dom << '/' << month << '/' << year << ',' << hour << ':' << minute << ':' << second;


  // read analog pins and format data
  for (uint8_t ia = 0; ia < SENSOR_COUNT; ia++) {
#if ADC_DELAY
    analogRead(ia);
    delay(ADC_DELAY);
#endif  // ADC_DELAY
    bout << ',' << analogRead(ia);
  }
  bout << endl;

  // log data and flush to SD
  logfile << buf << flush;

  // check for error
  if (!logfile) error("write data failed");

#if ECHO_TO_SERIAL
  cout << buf;
#endif  // ECHO_TO_SERIAL

  // don't log two points in the same millis
  if (m == millis()) delay(1);

  if (!Serial.available()) return;
  logfile.close();
  cout << pstr("Done!");
  while (1);
}

and

// initialize clock
void init_clock()
{
  Wire.beginTransmission(0x56);
  Wire.write(0x00);  // CONTROL_1 address.
  Wire.write(0x01);  // CONTROL_1: Enable 1 Hz clock source for watch.
  Wire.write(0x00);  // CONTROL_INT: Disable all interrupts.
  Wire.write(0x00);  // CONTROL_INT FLAG: Clear all.
  Wire.write(0x00);  // CONTROL_STATUS: Clear all, including PON.
  Wire.endTransmission();
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ((val / 10 * 16) + (val % 10));
}

//Set clock
void set_clock()
{
  Wire.beginTransmission(0x56);
  Wire.write(0x08);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dom));//day of month
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

//Read clock
void get_clock()
{
  // send request to receive data starting at register 8
  Wire.beginTransmission(0x56); // 208 is DS3231 device address
  Wire.write(0x08); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(0x56, 7); // request seven bytes

  if (Wire.available())
  {
    second = Wire.read(); // get seconds
    minute = Wire.read(); // get minutes
    hour = Wire.read();   // get hours
    dom = Wire.read();  //get dayofmonth
    day = Wire.read();  //get dayofweek
    month = Wire.read(); //get month
    year = Wire.read();  //get year

    second = (((second & B11110000) >> 4) * 10 + (second & B00001111)); // convert BCD to decimal
    minute = (((minute & B11110000) >> 4) * 10 + (minute & B00001111)); // convert BCD to decimal
    hour = (((hour & B00110000) >> 4) * 10 + (hour & B00001111)); // convert BCD to decimal (assume 24 hour mode)
    day = (day & B00000111); // 1-7
    dom = (((dom & B00110000) >> 4) * 10 + (dom & B00001111)); // 1-31
    month = (((month & B00010000) >> 4) * 10 + (month & B00001111)); //
    year = (((year & B11110000) >> 4) * 10 + (year & B00001111) + 2000);
  }
  else {

  }
}

I modified the code further to build filenames corresponding to the date. Works like a charm. Buuuuuut… the problem is here:

// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
  get_clock;

  // return date using FAT_DATE macro to format fields
  *date = FAT_DATE(year, month, dom);

  // return time using FAT_TIME macro to format fields
  *time = FAT_TIME(hour, minute, second);
}

I know it is a luxury problem, but I either get 2064 (with year like that) or 2064 (with uint16_t year) as year in the fat date, but in the filename it is always correct. Sure, it is a minor thing, but it bothers me greatly not to understand what is going on.
Any suggestion is appreciated, thanks in advance.

Yeah, sure, after one week of trying I had to post it to find the solution by myself :-\
Here's the fix: in get_clock, it has to be

    year = (((year & B11110000) >> 4) * 10 + (year & B00001111) + 2000);

I found it looking closely into the RTClib.cpp.
So I hope someone finds the code with the RV3029 useful, at least. It is a little more difficult to solder, as the C2-package is considerably smaller than a usual DIP-8, but not impossible. Good luck!

Thanks for posting godo it looks interesting and attractive with very low power consumption.

Found another little bug. Corrected the originally posted code.