I am writing code to talk to a Seiko S-35390A Real Time Clock (RTC) chip for the new Battery Management system I am designing for REVOLT Custom Electric Vehicles. The chip communicates with my microcontroller via I2C, a reasonably well defined standard. I2C,conveniently defines the bit order for data transmitted over the bus. The RTC chip, for some reason, requires all of it's data to be sent as BCD encoded data with the bits reversed from the bus standard, (LSB becomes MSB.) Reversing bits should be a textbook problem, but I found only a few clean ways to do it. There is probably an simpler way using 16bit shifts but here is a solution using a lookup table.
//Seiko RTC chip uses an annoying packing system where the LSB
// of the BCD represented data is in the MSB of the value
// that has to be written to the register. This function
// does the bitwise flip of each nybble using a lookup, and
// swaps the two nybbles.
unsigned char RTC_ConvertRBCD( unsigned char value ) {
const unsigned char tobcd[] = { 0x0, 0x8, 0x4, 0xC,
0x2, 0xA, 0x6, 0xE, 0x1, 0x9, 0x5, 0xD, 0x3, 0xB,
0x7, 0xF };
return (tobcd[value & 0x0F] << 4 ) + tobcd[value >> 4];
}
//Input is a 8bit number, returns the BCD encoded, bit reversed
// value needed by the Seiko RTC chip registers
unsigned char RTC_ToRTCBCD( unsigned char value ) {
return RTC_ConvertRBCD( ( ( value / 10) << 4) + ( value % 10 ) );
//return RTC_ConvertRBCD( ( ( value / 10) << 4) + ( value & 0x0F) );
}
//Input is a bit reversed packed BCD register value from
// the Seiko RTC chip, return is a normal 8bit value
unsigned char RTC_FromRTCBCD( unsigned char bcdvalue ) {
unsigned char unpacked = RTC_ConvertRBCD( bcdvalue );
return ( ( unpacked >> 4 ) * 10) + ( unpacked & 0x0F );
}

Leave a comment