Skip to content

Commit

Permalink
Implement get_fattime (#160)
Browse files Browse the repository at this point in the history
* rtc_settime, rtc_gettime functions added

* wrapper funcs, bcd_to_data conversion

* update example using rtc_gettime

Signed-off-by: Hrushi20 <[email protected]>
  • Loading branch information
Hrushi20 authored Dec 5, 2023
1 parent d6f594a commit 80f021d
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Makefile

*.dump
.vscode/*
.idea/*

*~*
\#*\#
Expand Down
2 changes: 1 addition & 1 deletion src/commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
94 changes: 81 additions & 13 deletions src/helpers/rtc.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdint.h>
#include <time.h>

#include "../bus/i2c/i2c.h"
#include "../bus/uart/uart.h"
Expand All @@ -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(&timestamp);
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];
Expand All @@ -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];
Expand Down
36 changes: 32 additions & 4 deletions src/helpers/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define RTC_H

#include <xc.h>
#include "../commands.h"

#define DS1307_I2C_DEVICE_ADDRESS 0x68

Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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
*
Expand Down
30 changes: 17 additions & 13 deletions src/sdcard/fatfs/ff_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,27 @@
*/

#include "ff.h"
#include <time.h>
#include <stdint.h>
#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(&timestamp);

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);
}

0 comments on commit 80f021d

Please sign in to comment.