Skip to content

Commit 7925e6f

Browse files
committed
2 parents c381038 + 08c3781 commit 7925e6f

File tree

6 files changed

+290
-19
lines changed

6 files changed

+290
-19
lines changed

doc/contents/datetime.tex

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
\documentclass{article}
2+
\usepackage{listings}
3+
\usepackage{geometry}
4+
\geometry{margin=1in}
5+
\title{Timekeeping API}
6+
\date{}
7+
\begin{document}
8+
9+
\maketitle
10+
11+
\section*{Structure Descriptions}
12+
13+
\begin{lstlisting}[language=C]
14+
15+
typedef struct
16+
{
17+
uint32_t hrs;
18+
uint32_t mins;
19+
uint32_t secs;
20+
} timeval;
21+
22+
typedef struct
23+
{
24+
uint32_t day;
25+
uint32_t month;
26+
uint32_t year;
27+
28+
} dateval;
29+
30+
\end{lstlisting}
31+
32+
\section*{Implementation Note}
33+
34+
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}
35+
36+
\section*{uint32_t getdate(dateval *date)}
37+
38+
Fetch current date in days, months and years into \texttt{date}. Returns number of seconds since epoch.
39+
40+
\section*{uint32_t gettime(timeval *time)}
41+
42+
Fetch current time in hours, minutes and seconds into \texttt{time}. Returns number of seconds since epoch.
43+
44+
\section*{Examples}
45+
46+
\begin{lstlisting}[language=C,showstringspaces=false]
47+
gettime(&time_struct);
48+
puts("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
49+
50+
getdate(&date_struct);
51+
puts("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
52+
\end{lstlisting}
53+
54+
\end{document}

include/datetime.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef DATETIME_H
2+
#define DATETIME_H
3+
4+
#include <stdint.h>
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
typedef struct
12+
{
13+
uint32_t hrs;
14+
uint32_t mins;
15+
uint32_t secs;
16+
} timeval;
17+
18+
typedef struct
19+
{
20+
uint32_t day;
21+
uint32_t month;
22+
uint32_t year;
23+
24+
} dateval;
25+
26+
uint32_t getdate(dateval *date);
27+
uint32_t gettime(timeval *time);
28+
29+
#ifdef __cplusplus
30+
}
31+
#endif
32+
33+
#endif // DATETIME_H

include/printf.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ extern "C"
1010
{
1111
#endif
1212

13+
typedef struct Format_State
14+
{
15+
unsigned long long num;
16+
bool valid_format;
17+
bool in_format; // Used to handle multi-character format specifiers
18+
bool long_format; // %l. type specifier
19+
} Format_State;
20+
1321
void puts(const char *s);
1422
void printf(char *s, ...);
1523
void getlines(char *restrict buffer, size_t length);

kernel/kernel.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <stdbool.h>
22
#include <stddef.h>
33

4+
#include "datetime.h"
45
#include "printf.h"
56
#include "clear.h"
67

@@ -38,6 +39,9 @@ void kernel_main(void)
3839

3940
char input_buffer[100];
4041

42+
dateval date_struct;
43+
timeval time_struct;
44+
4145
bool is_running = true;
4246
while (is_running)
4347
{
@@ -68,11 +72,14 @@ void kernel_main(void)
6872
case 'c': // Check for clear screen command
6973
clear();
7074
break;
71-
case 't': // Check for time command
72-
printf("Current time: 12:00 PM\r\n"); // TO-DO: Implement real time check
75+
76+
case 't': // Check for time command
77+
gettime(&time_struct);
78+
printf("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
7379
break;
74-
case 'd': // Check for date command
75-
printf("Current date: 2023-10-01\r\n"); // TO-DO: Implement real date check
80+
case 'd': // Check for date command
81+
getdate(&date_struct);
82+
printf("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
7683
break;
7784
default:
7885
printf("Unknown command. Type 'h' for help.\r\n");

user/datetime.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <stddef.h>
2+
#include <stdint.h>
3+
#include "datetime.h"
4+
5+
_Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
6+
7+
#define RTCDR (*(volatile uint32_t *)0x101e8000) // RTC Register
8+
9+
#define SECONDS_IN_YEAR 31556926
10+
#define SECONDS_IN_MONTH 2629743
11+
#define SECONDS_IN_DAY 86400
12+
#define LEAP_YEARS_BEFORE_1970 477
13+
14+
uint32_t getdate(dateval *date_struct)
15+
{
16+
static uint32_t day_arr[12] = {31, 27, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Initialize only once
17+
18+
if (date_struct != NULL)
19+
{
20+
uint32_t since_epoch = RTCDR;
21+
22+
date_struct->year = 1970 + since_epoch / SECONDS_IN_YEAR;
23+
date_struct->month = 1 + (since_epoch / SECONDS_IN_MONTH) % 12;
24+
25+
uint32_t days_since_epoch = since_epoch / SECONDS_IN_DAY;
26+
uint32_t leap_years_since_epoch = (date_struct->year / 4) - (date_struct->year / 100) + (date_struct->year / 400) - LEAP_YEARS_BEFORE_1970;
27+
uint32_t not_leap_years = date_struct->year - 1970 - leap_years_since_epoch;
28+
29+
date_struct->day = days_since_epoch - (leap_years_since_epoch * 366) - (not_leap_years * 365);
30+
31+
uint32_t is_leap_year = ((date_struct->year % 4 == 0) && (date_struct->year % 100 != 0)) || (date_struct->year % 400 == 0);
32+
day_arr[1] += is_leap_year; // Extra day if leap year
33+
34+
for (uint32_t i = 0; i < 12; i++)
35+
{
36+
if (date_struct->day > day_arr[i])
37+
{
38+
date_struct->day -= day_arr[i];
39+
}
40+
}
41+
42+
day_arr[1] -= is_leap_year; // Undo the leap year effect, if any
43+
}
44+
45+
return RTCDR;
46+
}
47+
48+
uint32_t gettime(timeval *time_struct)
49+
{
50+
if (time_struct != NULL)
51+
{
52+
uint32_t since_epoch = RTCDR;
53+
54+
time_struct->secs = since_epoch % 60;
55+
since_epoch /= 60;
56+
57+
time_struct->mins = since_epoch % 60;
58+
since_epoch /= 60;
59+
60+
time_struct->hrs = since_epoch % 24;
61+
}
62+
63+
return RTCDR;
64+
}

user/printf.c

Lines changed: 120 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@
66

77
// TODO: Check working of printf, all cases
88

9-
typedef struct Format_State
10-
{
11-
unsigned long long num;
12-
bool valid_format;
13-
bool in_format; // Used to handle multi-character format specifiers
14-
bool long_format; // %l. type specifier
15-
} Format_State;
16-
179
_Static_assert(sizeof(uint32_t) == 4, "uint32_t must be 4 bytes");
1810

1911
// Memory-mapped I/O registers for UART0 on QEMU versatilepb
@@ -259,26 +251,139 @@ static inline char getc(void)
259251
// Function to getline from user input
260252
void getlines(char *restrict buffer, size_t length)
261253
{
262-
size_t index = 0;
254+
long long index = 0;
255+
long long cursor_position = 0;
256+
263257
char character;
258+
259+
uint8_t escape = 0;
260+
uint8_t arrow_keys = 0;
261+
264262
while (index < length - 1)
265263
{
266264
character = getc();
265+
266+
if (character == '\033') // Handle Escape sequences
267+
{
268+
escape = 1;
269+
continue;
270+
}
271+
272+
if (escape)
273+
{
274+
if (escape == 1)
275+
{
276+
arrow_keys = (character == 91);
277+
}
278+
else
279+
{
280+
if (arrow_keys)
281+
{
282+
switch (character)
283+
{
284+
case 'A': // Up
285+
{
286+
break;
287+
}
288+
case 'B': // Down
289+
{
290+
break;
291+
}
292+
case 'C': // Right
293+
{
294+
if (cursor_position < index)
295+
{
296+
puts("\033[C");
297+
cursor_position++;
298+
}
299+
break;
300+
}
301+
case 'D': // Left
302+
{
303+
if (cursor_position - 1 >= 0)
304+
{
305+
puts("\033[D");
306+
cursor_position--;
307+
}
308+
}
309+
default:
310+
{
311+
break;
312+
}
313+
}
314+
315+
arrow_keys = 0;
316+
}
317+
}
318+
319+
escape++;
320+
321+
if (escape == 3) // Escape sequence is 3 characters long
322+
{
323+
escape = 0;
324+
}
325+
326+
continue;
327+
}
328+
267329
if (character == '\r') // Check for carriage return
268330
{
269331
break;
270332
}
271333
if ((character == '\b' || character == 0x7F) && index > 0) // Check for backspace
272334
{
273-
index--;
274-
putc('\b'); // Move cursor back
275-
putc(' '); // Clear the character
276-
putc('\b'); // Move cursor back again
335+
if (cursor_position > 0)
336+
{
337+
long long initial_pos = cursor_position;
338+
339+
for (long long cur = cursor_position - 1; cur < index; cur++) // Shift characters to the left
340+
{
341+
buffer[cur] = buffer[cur + 1];
342+
}
343+
344+
bool cond = (index != initial_pos);
345+
346+
index--;
347+
buffer[index] = '\0';
348+
349+
cursor_position--;
350+
351+
if (cond)
352+
printf("\033[%ldC", (index - cursor_position));
353+
354+
putc('\b'); // Move cursor back
355+
putc(' '); // Clear the character
356+
putc('\b'); // Move cursor back again
357+
358+
if (cond)
359+
{
360+
printf("\033[%ldD", index - cursor_position); // Analogous to the above putc sequence, but for multiple characters
361+
printf("%s", buffer + cursor_position);
362+
printf("\033[%ldD", index - cursor_position);
363+
}
364+
}
277365
}
278366
else
279367
{
280-
buffer[index++] = character; // Store the character in the buffer
281-
putc(character); // Echo the character back
368+
putc(character); // Echo the character back
369+
370+
long long initial_pos = cursor_position;
371+
372+
for (long long cur = index; cur >= cursor_position; cur--) // Shift characters to the right
373+
{
374+
buffer[cur + 1] = buffer[cur];
375+
}
376+
377+
buffer[cursor_position] = character; // Store the character in the buffer
378+
379+
if (index != initial_pos)
380+
{
381+
puts(buffer + cursor_position + 1);
382+
printf("\033[%ldD", index - initial_pos);
383+
}
384+
385+
cursor_position++;
386+
index++;
282387
}
283388
}
284389
buffer[index] = '\0'; // Null-terminate the string

0 commit comments

Comments
 (0)