diff --git a/.gitignore b/.gitignore index 217d05d..6e21dd1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ Makefile *.dump .vscode/* +.idea/* *~* \#*\# diff --git a/src/commands.c b/src/commands.c index b8016cf..a97993e 100644 --- a/src/commands.c +++ b/src/commands.c @@ -281,7 +281,7 @@ command_func_t* const cmd_table[NUM_PRIMARY_CMDS + 1][NUM_SECONDARY_CMDS_MAX + 1 }, { // 13 SENSORS // 0 1 RTC_SETTIME 2 RTC_SETDIGIT 3 RTC_GETTIME - Undefined, RTC_SetTime, RTC_SetDigit, RTC_GetTime, + Undefined, RTC_CmdSetTime, RTC_SetDigit, RTC_CmdGetTime, // 4 RTC_GETDIGIT 5 HCSR04 6 AM2302 7 BMP180 RTC_GetDigit, Unimplemented, Unimplemented, Unimplemented, // 8 TSL2591 9 TCD1304 10 11 diff --git a/src/helpers/rtc.c b/src/helpers/rtc.c index ecacc32..8c7f969 100644 --- a/src/helpers/rtc.c +++ b/src/helpers/rtc.c @@ -1,4 +1,5 @@ #include +#include #include "../bus/i2c/i2c.h" #include "../bus/uart/uart.h" @@ -8,24 +9,69 @@ #include "light.h" #include "rtc.h" -response_t RTC_SetTime(void) { - +// This bit is used to enable the oscillator. When negated, the oscillator is disabled. +static uint8_t const oscillator_enable = 0x7F; + +static uint8_t data_to_bcd(uint8_t data){ + uint8_t bcd = data; + + if(data >= 10){ + uint8_t left = data / 10; + uint8_t right = data % 10; + bcd = (left << 4) | right; + } + return bcd; +} + +static uint8_t bcd_to_data(uint8_t bcd){ + uint8_t right = (0xF & bcd); + uint8_t left = (bcd >> 4) & 0xF; + + left *= 10; + return left + right; +} + +response_t RTC_SetTime(uint32_t const * const unix_timestamp) { + + time_t timestamp = (time_t) *unix_timestamp; + struct tm *tm_info; + + tm_info = gmtime(×tamp); + uint8_t sec = tm_info->tm_sec; + uint8_t min = tm_info->tm_min; + uint8_t hours = tm_info->tm_hour; + uint8_t day = tm_info->tm_wday + 1; + uint8_t date = tm_info->tm_mday; + uint8_t month = tm_info->tm_mon + 1; + uint8_t year = tm_info->tm_year % 100; // Tm_year starts from 00 which means(1900). + // ds1307 only stores the last 2 digits. + if(sec == 60) + sec = 0; + + // Default 24 hrs format. uint8_t buffer[9]; buffer[0] = DS1307_DATA_REG_SECONDS; - buffer[1] = UART1_Read() & 0x7F; // seconds - buffer[2] = UART1_Read(); // minutes - buffer[3] = UART1_Read(); // hours - buffer[4] = UART1_Read(); // day - buffer[5] = UART1_Read(); // date - buffer[6] = UART1_Read(); // month - buffer[7] = UART1_Read(); // year - buffer[8] = UART1_Read(); // control + buffer[1] = data_to_bcd(sec) & oscillator_enable; // seconds + buffer[2] = data_to_bcd(min); // minutes + buffer[3] = data_to_bcd(hours); // hours (hrs format) + buffer[4] = data_to_bcd(day); // day + buffer[5] = data_to_bcd(date); // date + buffer[6] = data_to_bcd(month); // month + buffer[7] = data_to_bcd(year); // year + buffer[8] = 0; // control I2C_InitializeIfNot(I2C_BAUD_RATE_100KHZ, I2C_ENABLE_INTERRUPTS); return I2C_BulkWrite(buffer, 9, DS1307_I2C_DEVICE_ADDRESS); } +response_t RTC_CmdSetTime(void) { + uint32_t unix_timestamp = UART1_read_u32(); + + response_t res = RTC_SetTime(&unix_timestamp); + return res; +} + response_t RTC_SetDigit(void) { uint8_t buffer[2]; @@ -37,20 +83,42 @@ response_t RTC_SetDigit(void) { return I2C_BulkWrite(buffer, 2, DS1307_I2C_DEVICE_ADDRESS); } -response_t RTC_GetTime(void) { +response_t RTC_GetTime(uint32_t* unix_timestamp) { uint8_t buffer[7]; + struct tm tm_info; I2C_InitializeIfNot(I2C_BAUD_RATE_100KHZ, I2C_ENABLE_INTERRUPTS); if(I2C_BulkRead(DS1307_DATA_REG_SECONDS, DS1307_I2C_DEVICE_ADDRESS, buffer, 7) == SUCCESS) { - uint8_t i; - for (i = 0; i < sizeof(buffer); i++) UART1_Write(buffer[i]); + + // Need to convert from bcd to int. + tm_info.tm_sec = bcd_to_data(buffer[0]); + tm_info.tm_min = bcd_to_data(buffer[1]); + tm_info.tm_hour = bcd_to_data(buffer[2]); + tm_info.tm_wday = bcd_to_data(buffer[3]) - 1; + tm_info.tm_mday = bcd_to_data(buffer[4]); + tm_info.tm_mon = bcd_to_data(buffer[5]) - 1; + tm_info.tm_year = 100 + bcd_to_data(buffer[6]); // 100 means for year 2000 (2000 - 1900) + + tm_info.tm_sec = tm_info.tm_sec & oscillator_enable; + + uint32_t timestamp = (uint32_t) mktime(&tm_info); + *unix_timestamp = timestamp; } else return FAILED; return SUCCESS; } +response_t RTC_CmdGetTime(void){ + uint32_t unix_timestamp; + response_t res = RTC_GetTime(&unix_timestamp); + + // What if error occurs here, Returns fail. + UART1_write_u32(unix_timestamp); + return res; +} + response_t RTC_GetDigit(void) { uint8_t buffer[1]; diff --git a/src/helpers/rtc.h b/src/helpers/rtc.h index 1002a27..2918f40 100644 --- a/src/helpers/rtc.h +++ b/src/helpers/rtc.h @@ -2,6 +2,7 @@ #define RTC_H #include +#include "../commands.h" #define DS1307_I2C_DEVICE_ADDRESS 0x68 @@ -60,11 +61,26 @@ extern "C" { * | OUT (1) | XX (2) | SQWE (1) | XX (2) | RS1:0 (2) | * * This method does not pass any messages over the serial back to host. + * This method decodes the unix_timestamp passed as param, converts it into RTC format and + * stores the value in RTC hardware. + * + * @Param + * const* const unix_timestamp: Time to be stored in 32 bit unix timestamp format. * * @return SUCCESS, FAILED */ - response_t RTC_SetTime(void); - + response_t RTC_SetTime(uint32_t const* const unix_timestamp); + + /** + * @brief Stores time in RTC Hardware. + * + * @description This method reads 32 bit unix timestamp unsigned integer from the host and + * stores the value in RTC Hardware by calling RTC_SetTime function. + * + * @return SUCCESS, FAILED + */ + response_t RTC_CmdSetTime(void); + /** * @brief Updates a single time parameter in DS1307 real-time clock * @@ -94,11 +110,23 @@ extern "C" { * * This method will pass 8 unsigned bytes to the host over serial and host * will need to read all 7 bytes to complete the transaction. + * + * @param + * *unix_timestamp - Time in RTC hardware is converted to unix_timestamp and stored in the parameter * * @return SUCCESS, FAILED */ - response_t RTC_GetTime(void); - + response_t RTC_GetTime(uint32_t* unix_timestamp); + + /** + * @Brief Fetches time from RTC Hardware in unix_timestamp format. + * + * @Description This method reads time from RTC Hardware and returns the value in unix_timestamp + * format by calling the RTC_GetTime function. + * + * @return SUCCESS, FAILED + */ + response_t RTC_CmdGetTime(void); /** * @brief Fetch a single time parameter from DS1307 real-time clock * diff --git a/src/sdcard/fatfs/ff_time.c b/src/sdcard/fatfs/ff_time.c index a8f0999..cc01ef8 100644 --- a/src/sdcard/fatfs/ff_time.c +++ b/src/sdcard/fatfs/ff_time.c @@ -59,23 +59,27 @@ */ #include "ff.h" +#include #include +#include "../../helpers/rtc.h" + +DWORD get_fattime (void){ + + uint32_t unix_timestamp = 0; + RTC_GetTime(&unix_timestamp); + struct tm *tm_info; + + time_t timestamp = (time_t) (unix_timestamp); + tm_info = gmtime(×tamp); -static DWORD decimalToFatTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t seconds) -{ DWORD fatTime; - fatTime = (seconds >> 1); - fatTime |= ( ((DWORD)minute) << 5 ); - fatTime |= ( ((DWORD)hour) << 11 ); - fatTime |= ( ((DWORD)day) << 16 ); - fatTime |= ( ((DWORD)month) << 21 ); - fatTime |= ( ((DWORD)(year - 1980)) << 25 ); + fatTime = (tm_info->tm_sec >> 1); + fatTime |= ( ((DWORD)tm_info->tm_min) << 5 ); + fatTime |= ( ((DWORD)tm_info->tm_hour) << 11 ); + fatTime |= ( ((DWORD)tm_info->tm_mday) << 16 ); + fatTime |= ( ((DWORD)tm_info->tm_mon + 1) << 21 ); + fatTime |= ( ((DWORD)(tm_info->tm_year - 80)) << 25 ); return fatTime; } - -DWORD get_fattime (void) -{ - return decimalToFatTime(2018, 6, 31, 5, 10, 30); -} \ No newline at end of file