Skip to content
Merged
54 changes: 54 additions & 0 deletions doc/contents/datetime.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
\documentclass{article}
\usepackage{listings}
\usepackage{geometry}
\geometry{margin=1in}
\title{Timekeeping API}
\date{}
\begin{document}

\maketitle

\section*{Structure Descriptions}

\begin{lstlisting}[language=C]

typedef struct
{
uint32_t hrs;
uint32_t mins;
uint32_t secs;
} timeval;

typedef struct
{
uint32_t day;
uint32_t month;
uint32_t year;

} dateval;

\end{lstlisting}

\section*{Implementation Note}

The number of seconds since epoch is retrieved from 926EJ-S's Real Time Clock Data Register(\textbf{RTCDR}). This is a 32 bit register, and therefore \underline{subject to the Year 2038 Problem}

\section*{uint32_t getdate(dateval *date)}

Fetch current date in days, months and years into \texttt{date}. Returns number of seconds since epoch.

\section*{uint32_t gettime(timeval *time)}

Fetch current time in hours, minutes and seconds into \texttt{time}. Returns number of seconds since epoch.

\section*{Examples}

\begin{lstlisting}[language=C,showstringspaces=false]
gettime(&time_struct);
puts("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);

getdate(&date_struct);
puts("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
\end{lstlisting}

\end{document}
33 changes: 33 additions & 0 deletions include/datetime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef DATETIME_H
#define DATETIME_H

#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

typedef struct
{
uint32_t hrs;
uint32_t mins;
uint32_t secs;
} timeval;

typedef struct
{
uint32_t day;
uint32_t month;
uint32_t year;

} dateval;

uint32_t getdate(dateval *date);
uint32_t gettime(timeval *time);

#ifdef __cplusplus
}
#endif

#endif // DATETIME_H
8 changes: 8 additions & 0 deletions include/printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ extern "C"
{
#endif

typedef struct Format_State
{
unsigned long long num;
bool valid_format;
bool in_format; // Used to handle multi-character format specifiers
bool long_format; // %l. type specifier
} Format_State;

void puts(const char *s);
void printf(char *s, ...);
void getlines(char *restrict buffer, size_t length);
Expand Down
15 changes: 11 additions & 4 deletions kernel/kernel.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdbool.h>
#include <stddef.h>

#include "datetime.h"
#include "printf.h"
#include "clear.h"

Expand Down Expand Up @@ -38,6 +39,9 @@ void kernel_main(void)

char input_buffer[100];

dateval date_struct;
timeval time_struct;

bool is_running = true;
while (is_running)
{
Expand Down Expand Up @@ -68,11 +72,14 @@ void kernel_main(void)
case 'c': // Check for clear screen command
clear();
break;
case 't': // Check for time command
printf("Current time: 12:00 PM\r\n"); // TO-DO: Implement real time check

case 't': // Check for time command
gettime(&time_struct);
printf("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
break;
case 'd': // Check for date command
printf("Current date: 2023-10-01\r\n"); // TO-DO: Implement real date check
case 'd': // Check for date command
getdate(&date_struct);
printf("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
break;
default:
printf("Unknown command. Type 'h' for help.\r\n");
Expand Down
64 changes: 64 additions & 0 deletions user/datetime.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <stddef.h>
#include <stdint.h>
#include "datetime.h"

_Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");

#define RTCDR (*(volatile uint32_t *)0x101e8000) // RTC Register

#define SECONDS_IN_YEAR 31556926
#define SECONDS_IN_MONTH 2629743
#define SECONDS_IN_DAY 86400
#define LEAP_YEARS_BEFORE_1970 477

uint32_t getdate(dateval *date_struct)
{
static uint32_t day_arr[12] = {31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Initialize only once

if (date_struct != NULL)
{
uint32_t since_epoch = RTCDR;

date_struct->year = 1970 + since_epoch / SECONDS_IN_YEAR;
date_struct->month = 1 + (since_epoch / SECONDS_IN_MONTH) % 12;

uint32_t days_since_epoch = since_epoch / SECONDS_IN_DAY;
uint32_t leap_years_since_epoch = (date_struct->year / 4) - (date_struct->year / 100) + (date_struct->year / 400) - LEAP_YEARS_BEFORE_1970;
uint32_t not_leap_years = date_struct->year - 1970 - leap_years_since_epoch;

date_struct->day = days_since_epoch - (leap_years_since_epoch * 366) - (not_leap_years * 365);

uint32_t is_leap_year = ((date_struct->year % 4 == 0) && (date_struct->year % 100 != 0)) || (date_struct->year % 400 == 0);
day_arr[1] += is_leap_year; // Extra day if leap year

for (uint32_t i = 0; i < 12; i++)
{
if (date_struct->day > day_arr[i])
{
date_struct->day -= day_arr[i];
}
}

day_arr[1] -= is_leap_year; // Undo the leap year effect, if any
}

return RTCDR;
}

uint32_t gettime(timeval *time_struct)
{
if (time_struct != NULL)
{
uint32_t since_epoch = RTCDR;

time_struct->secs = since_epoch % 60;
since_epoch /= 60;

time_struct->mins = since_epoch % 60;
since_epoch /= 60;

time_struct->hrs = since_epoch % 24;
}

return RTCDR;
}
135 changes: 120 additions & 15 deletions user/printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@

// TODO: Check working of printf, all cases

typedef struct Format_State
{
unsigned long long num;
bool valid_format;
bool in_format; // Used to handle multi-character format specifiers
bool long_format; // %l. type specifier
} Format_State;

_Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");

// Memory-mapped I/O registers for UART0 on QEMU versatilepb
Expand Down Expand Up @@ -259,26 +251,139 @@ static inline char getc(void)
// Function to getline from user input
void getlines(char *restrict buffer, size_t length)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this getlines function could be simplified by adding modularity. This would help with improving readability. This is okay for now, but I will probably refactor it in the future.

{
size_t index = 0;
long long index = 0;
long long cursor_position = 0;

char character;

uint8_t escape = 0;
uint8_t arrow_keys = 0;

while (index < length - 1)
{
character = getc();

if (character == '\033') // Handle Escape sequences
{
escape = 1;
continue;
}

if (escape)
{
if (escape == 1)
{
arrow_keys = (character == 91);
}
else
{
if (arrow_keys)
{
switch (character)
{
case 'A': // Up
{
break;
}
case 'B': // Down
{
break;
}
case 'C': // Right
{
if (cursor_position < index)
{
puts("\033[C");
cursor_position++;
}
break;
}
case 'D': // Left
{
if (cursor_position - 1 >= 0)
{
puts("\033[D");
cursor_position--;
}
}
default:
{
break;
}
}

arrow_keys = 0;
}
}

escape++;

if (escape == 3) // Escape sequence is 3 characters long
{
escape = 0;
}

continue;
}

if (character == '\r') // Check for carriage return
{
break;
}
if ((character == '\b' || character == 0x7F) && index > 0) // Check for backspace
{
index--;
putc('\b'); // Move cursor back
putc(' '); // Clear the character
putc('\b'); // Move cursor back again
if (cursor_position > 0)
{
long long initial_pos = cursor_position;

for (long long cur = cursor_position - 1; cur < index; cur++) // Shift characters to the left
{
buffer[cur] = buffer[cur + 1];
}

bool cond = (index != initial_pos);

index--;
buffer[index] = '\0';

cursor_position--;

if (cond)
printf("\033[%ldC", (index - cursor_position));

putc('\b'); // Move cursor back
putc(' '); // Clear the character
putc('\b'); // Move cursor back again

if (cond)
{
printf("\033[%ldD", index - cursor_position); // Analogous to the above putc sequence, but for multiple characters
printf("%s", buffer + cursor_position);
printf("\033[%ldD", index - cursor_position);
}
}
}
else
{
buffer[index++] = character; // Store the character in the buffer
putc(character); // Echo the character back
putc(character); // Echo the character back

long long initial_pos = cursor_position;

for (long long cur = index; cur >= cursor_position; cur--) // Shift characters to the right
{
buffer[cur + 1] = buffer[cur];
}

buffer[cursor_position] = character; // Store the character in the buffer

if (index != initial_pos)
{
puts(buffer + cursor_position + 1);
printf("\033[%ldD", index - initial_pos);
}

cursor_position++;
index++;
}
}
buffer[index] = '\0'; // Null-terminate the string
Expand Down