summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--applications/clock/makefile12
-rw-r--r--applications/clock/source/main.cpp63
-rw-r--r--applications/init/source/main.cpp2
-rw-r--r--documentation/kernel-interfaces/syscalls.txt10
-rw-r--r--euler/include/ctime20
-rw-r--r--euler/include/euler/syscall.hpp5
-rw-r--r--euler/include/std/string.hpp10
-rw-r--r--euler/makefile2
-rw-r--r--euler/source/std/ctime.cpp58
-rw-r--r--euler/source/syscall.cpp23
-rw-r--r--kernel/include/hilbert/kernel/timer.hpp18
-rw-r--r--kernel/include/hilbert/kernel/utility.hpp19
-rw-r--r--kernel/makefile2
-rw-r--r--kernel/source/entry.cpp2
-rw-r--r--kernel/source/interrupts.asm26
-rw-r--r--kernel/source/syscall.cpp30
-rw-r--r--kernel/source/timer.asm162
-rw-r--r--kernel/source/timer.cpp117
-rw-r--r--libraries/pake/include/pake/widgets/fixed-text.hpp25
-rw-r--r--libraries/pake/include/pake/window.hpp21
-rw-r--r--libraries/pake/source/widgets/fixed-text.cpp12
-rw-r--r--makefile9
-rw-r--r--readme.txt10
23 files changed, 643 insertions, 15 deletions
diff --git a/applications/clock/makefile b/applications/clock/makefile
new file mode 100644
index 0000000..949e6ce
--- /dev/null
+++ b/applications/clock/makefile
@@ -0,0 +1,12 @@
+SOURCES = \
+ main.cpp
+
+build/%.cpp.o: source/%.cpp
+ @mkdir -p $(@D)
+ $(HILBERT_CC) -c $^ -o $@
+
+build/clock.elf: $(SOURCES:%=build/%.o)
+ $(HILBERT_CC) $^ -ldaguerre -lpake -o $@
+
+clean:
+ rm -rf build
diff --git a/applications/clock/source/main.cpp b/applications/clock/source/main.cpp
new file mode 100644
index 0000000..3a1270d
--- /dev/null
+++ b/applications/clock/source/main.cpp
@@ -0,0 +1,63 @@
+#include <pake/widgets/fixed-text.hpp>
+#include <daguerre/psf.hpp>
+#include <pake/window.hpp>
+#include <ctime>
+
+static daguerre::fixed_font<bool> *font;
+
+std::string the_time() {
+
+ time_t t = time(0);
+
+ //convert to edt - TODO: timezones in euler
+ t -= 4 * 3600 * 1024;
+
+ tm *gt = gmtime(&t);
+
+ int hour = (gt->tm_hour - 1) % 12 + 1;
+ int min = gt->tm_min;
+ int sec = gt->tm_sec;
+ bool pm = gt->tm_hour >= 12;
+
+ std::string s;
+ s.resize(8);
+
+ s[0] = hour / 10 + '0'; s[1] = hour % 10 + '0';
+ s[3] = min / 10 + '0'; s[4] = min % 10 + '0';
+
+ s[2] = sec % 2 == 0 ? ':' : ' ';
+
+ s[5] = ' ';
+ s[6] = pm ? 'p' : 'a';
+ s[7] = 'm';
+
+ if (s[0] == '0')
+ s.erase(0, 1);
+
+ return s;
+
+}
+
+int main(int, char **) {
+
+ font = new daguerre::fixed_font<bool>(
+ daguerre::try_load_psf("/assets/terminus/10x18-bold.psf").value());
+
+ pake::widgets::fixed_text *text =
+ new pake::widgets::fixed_text(the_time(), font,
+ euler::syscall::encode_color(0xaa, 0xaa, 0xaa),
+ euler::syscall::encode_color(0x00, 0x00, 0x00),
+ pake::halign::center, pake::valign::center);
+
+ pake::window w(90, 28, "Clock");
+ w.set_root(std::unique_ptr<pake::widget>(text));
+ w.render_and_send_to_compositor();
+ w.show();
+
+ while (1) {
+ euler::syscall::sleep(512);
+ text->set_text(the_time());
+ w.render_and_send_to_compositor();
+ }
+
+}
diff --git a/applications/init/source/main.cpp b/applications/init/source/main.cpp
index ca137a4..c281bc0 100644
--- a/applications/init/source/main.cpp
+++ b/applications/init/source/main.cpp
@@ -6,6 +6,6 @@
int main(int, char **) {
euler::syscall::process_handle dummy;
euler::syscall::start_process("/bin/compositor", {}, {}, dummy);
- euler::syscall::start_process("/bin/hello", {}, {}, dummy);
+ euler::syscall::start_process("/bin/clock", {}, {}, dummy);
return 0;
}
diff --git a/documentation/kernel-interfaces/syscalls.txt b/documentation/kernel-interfaces/syscalls.txt
index 933ad34..f7dddba 100644
--- a/documentation/kernel-interfaces/syscalls.txt
+++ b/documentation/kernel-interfaces/syscalls.txt
@@ -4,6 +4,8 @@ rcx, rflags, r8-r11 are clobbered.
interrupts (including the timer!) are disabled during system calls.
+a "mibisecond" is a 1024th of a second
+
stream result:
0 = success
1 = bad handle
@@ -203,3 +205,11 @@ set thread name:
rax in: 24
rdi in: pointer to thread name
rsi in: thread name length
+
+sleep:
+ rax in: 25
+ rdi in: "mibiseconds" to sleep for
+
+get time:
+ rax in: 26
+ rax out: "mibiseconds" since january 1st 2000
diff --git a/euler/include/ctime b/euler/include/ctime
new file mode 100644
index 0000000..9cf1b1f
--- /dev/null
+++ b/euler/include/ctime
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <cstdint>
+
+typedef uint64_t time_t;
+
+struct tm {
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+};
+
+time_t time(time_t *arg);
+tm *gmtime(const time_t *time);
diff --git a/euler/include/euler/syscall.hpp b/euler/include/euler/syscall.hpp
index 4a3daa4..043dcd4 100644
--- a/euler/include/euler/syscall.hpp
+++ b/euler/include/euler/syscall.hpp
@@ -159,6 +159,11 @@ namespace euler::syscall {
void set_thread_name(const std::string &name);
+ void sleep(uint64_t mibiseconds);
+
+ //out is mibiseconds since january 1st 2000
+ uint64_t get_time();
+
}
#include <string>
diff --git a/euler/include/std/string.hpp b/euler/include/std/string.hpp
index 505ee69..c5a3d99 100644
--- a/euler/include/std/string.hpp
+++ b/euler/include/std/string.hpp
@@ -12,6 +12,8 @@ namespace std {
std::vector<char> characters;
public:
+ static const size_t npos = (size_t)-1;
+
constexpr string() : characters({'\0'}) {}
constexpr string(const string &other)
@@ -74,6 +76,14 @@ namespace std {
return characters[pos];
}
+ constexpr string &erase(size_t index = 0, size_t count = npos) {
+ count = std::min(count, size() - index);
+ for (size_t i = index; i + count < size(); ++i)
+ characters[i] = characters[i + count];
+ resize(size() - count);
+ return *this;
+ }
+
};
}
diff --git a/euler/makefile b/euler/makefile
index 62716f6..7574dea 100644
--- a/euler/makefile
+++ b/euler/makefile
@@ -1,6 +1,6 @@
LIBC_SOURCES = \
entry.cpp std/string.cpp std/cstring.cpp syscall.cpp std/cstdlib.cpp \
- heap.cpp syscall.asm std/cctype.cpp std/cstdio.cpp stream.cpp
+ heap.cpp syscall.asm std/cctype.cpp std/cstdio.cpp stream.cpp std/ctime.cpp
clean:
rm -rf build
diff --git a/euler/source/std/ctime.cpp b/euler/source/std/ctime.cpp
new file mode 100644
index 0000000..d83817a
--- /dev/null
+++ b/euler/source/std/ctime.cpp
@@ -0,0 +1,58 @@
+#include <euler/syscall.hpp>
+#include <ctime>
+
+time_t time(time_t *arg) {
+ time_t t = euler::syscall::get_time();
+ if (arg) *arg = t;
+ return t;
+}
+
+static tm static_tm;
+
+static int days_per_month[] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+tm *gmtime(const time_t *time) {
+
+ time_t t = *time / 1024;
+
+ static_tm.tm_isdst = 0;
+
+ static_tm.tm_sec = t % 60; t /= 60;
+ static_tm.tm_min = t % 60; t /= 60;
+ static_tm.tm_hour = t % 24; t /= 24;
+ static_tm.tm_wday = (t + 5) % 7 + 1;
+ static_tm.tm_year = (t / 1461) * 4 + 100;
+
+ int days_into_quadyear = t % 1461;
+
+ static_tm.tm_yday = 0;
+ static_tm.tm_mon = 0;
+ static_tm.tm_mday = 1;
+
+ for (int i = 0; i < 48; ++i) {
+ if (days_into_quadyear >= days_per_month[i]) {
+ days_into_quadyear -= days_per_month[i];
+ if (static_tm.tm_mon == 11) {
+ static_tm.tm_mon = 0;
+ static_tm.tm_yday = 0;
+ }
+ else {
+ ++static_tm.tm_mon;
+ static_tm.tm_yday += days_per_month[i];
+ }
+ }
+ else {
+ static_tm.tm_yday += days_into_quadyear;
+ static_tm.tm_mday += days_into_quadyear;
+ break;
+ }
+ }
+
+ return &static_tm;
+
+}
diff --git a/euler/source/syscall.cpp b/euler/source/syscall.cpp
index 0d30c4a..7637b10 100644
--- a/euler/source/syscall.cpp
+++ b/euler/source/syscall.cpp
@@ -407,4 +407,27 @@ namespace euler::syscall {
}
+ void sleep(uint64_t mibiseconds) {
+
+ uint64_t rax = 25;
+ uint64_t rdi = mibiseconds;
+ uint64_t rsi;
+ uint64_t rdx;
+
+ __euler_do_syscall(rax, rdi, rsi, rdx);
+
+ }
+
+ uint64_t get_time() {
+
+ uint64_t rax = 26;
+ uint64_t rdi;
+ uint64_t rsi;
+ uint64_t rdx;
+
+ __euler_do_syscall(rax, rdi, rsi, rdx);
+ return rax;
+
+ }
+
}
diff --git a/kernel/include/hilbert/kernel/timer.hpp b/kernel/include/hilbert/kernel/timer.hpp
new file mode 100644
index 0000000..f4ce17e
--- /dev/null
+++ b/kernel/include/hilbert/kernel/timer.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <hilbert/kernel/application.hpp>
+
+namespace hilbert::kernel::timer {
+
+ void init_timer();
+
+ //"mibiseconds" (1 second / 1024) since january 1st 2000
+ extern uint64_t current_time;
+
+ //when current_time >= sleeping_until, puts thread into paused threads
+ void register_sleeping_thread(
+ uint64_t sleeping_until, application::thread *thread);
+
+ void on_timer_interrupt();
+
+}
diff --git a/kernel/include/hilbert/kernel/utility.hpp b/kernel/include/hilbert/kernel/utility.hpp
index a21d3fe..b0ced32 100644
--- a/kernel/include/hilbert/kernel/utility.hpp
+++ b/kernel/include/hilbert/kernel/utility.hpp
@@ -126,6 +126,25 @@ namespace hilbert::kernel::utility {
last = n;
}
+ //if other == 0, then insert at the end
+ void insert_before(value_t &&value, node *other) {
+ node *n = new node {};
+ n->value = value;
+ n->next = other;
+ if (other) {
+ n->prev = other->prev;
+ other->prev = n;
+ }
+ else {
+ n->prev = last;
+ last = n;
+ }
+ if (n->prev)
+ n->prev->next = n;
+ else
+ first = n;
+ }
+
void clear() {
if (first) {
for (node *n = first->next; n; n = n->next)
diff --git a/kernel/makefile b/kernel/makefile
index 6d32537..608e67e 100644
--- a/kernel/makefile
+++ b/kernel/makefile
@@ -2,7 +2,7 @@ SOURCES = \
storage/bd/memory.cpp storage/fs/tarfs.cpp application.asm application.cpp \
framebuffer.cpp interrupts.asm interrupts.cpp allocator.cpp storage.cpp \
syscall.cpp utility.cpp paging.asm paging.cpp entry.cpp input.cpp panic.cpp \
- vfile.cpp serial.asm app-memory.cpp load-app.cpp
+ vfile.cpp serial.asm app-memory.cpp load-app.cpp timer.cpp timer.asm
build/%.asm.o: source/%.asm
@mkdir -p $(@D)
diff --git a/kernel/source/entry.cpp b/kernel/source/entry.cpp
index efa70fd..73e79c7 100644
--- a/kernel/source/entry.cpp
+++ b/kernel/source/entry.cpp
@@ -7,6 +7,7 @@
#include <hilbert/kernel/serial.hpp>
#include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/panic.hpp>
+#include <hilbert/kernel/timer.hpp>
#include <hilbert/kernel/vfile.hpp>
#include <limine.h>
@@ -179,6 +180,7 @@ extern "C" [[noreturn]] void entry() {
if (!have_initfs)
panic(0x5f8860);
+ timer::init_timer();
input::init_input();
application::init_applications();
diff --git a/kernel/source/interrupts.asm b/kernel/source/interrupts.asm
index e4912ee..df8e7ce 100644
--- a/kernel/source/interrupts.asm
+++ b/kernel/source/interrupts.asm
@@ -267,6 +267,22 @@ isr_end:
ret
+extern on_rtc_interrupt
+
+rtc_isr:
+
+ call isr_start
+
+ call on_rtc_interrupt
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xa0, al
+
+ call isr_end
+
+ iretq
+
extern on_keyboard_interrupt
keyboard_isr:
@@ -343,7 +359,7 @@ load_gdt_and_idt:
out 0x21, al
mov al, 0x01
out 0x21, al
- mov al, 0xf9 ;mask all but irq 1 and 2
+ mov al, 0xf9 ;mask all but irqs 1 and 2
out 0x21, al
mov al, 0x11
@@ -354,9 +370,15 @@ load_gdt_and_idt:
out 0xa1, al
mov al, 0x01
out 0xa1, al
- mov al, 0xef ;mask all but irq 12
+ mov al, 0xee ;mask all but irqs 8 and 12
out 0xa1, al
+ ;register rtc interrupt
+
+ mov rdi, 0x28
+ mov rsi, rtc_isr
+ call set_isr
+
;register keyboard and mouse interrupts
mov rdi, 0x21
diff --git a/kernel/source/syscall.cpp b/kernel/source/syscall.cpp
index c631df1..803f7d2 100644
--- a/kernel/source/syscall.cpp
+++ b/kernel/source/syscall.cpp
@@ -4,6 +4,7 @@
#include <hilbert/kernel/paging.hpp>
#include <hilbert/kernel/input.hpp>
#include <hilbert/kernel/panic.hpp>
+#include <hilbert/kernel/timer.hpp>
#include <hilbert/kernel/vfile.hpp>
namespace hilbert::kernel::syscall {
@@ -800,6 +801,29 @@ namespace hilbert::kernel::syscall {
}
+ void sleep_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ uint64_t mis = rdi;
+ set_zero(rax, rdi, rsi, rdx);
+
+ auto *t = application::running_thread;
+
+ timer::register_sleeping_thread(
+ timer::current_time + mis, t);
+
+ application::yield(t->saved_state);
+
+ }
+
+ void get_time_syscall(
+ uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) {
+
+ set_zero(rax, rdi, rsi, rdx);
+ rax = timer::current_time;
+
+ }
+
void (*handlers[])(
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx) = {
@@ -827,11 +851,13 @@ namespace hilbert::kernel::syscall {
&clear_socket_read_queue_syscall,
&get_environment_variable_length_syscall,
&get_environment_variable_value_syscall,
- &set_thread_name_syscall
+ &set_thread_name_syscall,
+ &sleep_syscall,
+ &get_time_syscall
};
- static constexpr int max_syscall_number = 24;
+ static constexpr int max_syscall_number = 26;
}
diff --git a/kernel/source/timer.asm b/kernel/source/timer.asm
new file mode 100644
index 0000000..d5f6f73
--- /dev/null
+++ b/kernel/source/timer.asm
@@ -0,0 +1,162 @@
+bits 64
+
+section .rodata
+
+section .text
+
+read_cmos_byte:
+;dil in = register number
+;al out = value
+;rdx and rcx are not touched
+
+ mov al, dil
+ out 0x70, al
+ in al, 0x71
+ ret
+
+global enable_rtc_interrupts
+enable_rtc_interrupts:
+
+ ;secondary status register
+ mov dil, 11
+ call read_cmos_byte
+
+ ;enable interrupts
+ or al, 0x40
+ mov cl, al
+
+ ;do cmos write
+ mov al, 11
+ out 0x70, al
+ mov al, cl
+ out 0x71, al
+
+ ret
+
+global acknowledge_rtc_interrupt
+acknowledge_rtc_interrupt:
+ mov dil, 12
+ jmp read_cmos_byte
+
+convert_bcd:
+;al in = byte (possibly bcd)
+;al out = byte (not bcd)
+;sil 0x02 = bcd
+;does not touch rdx, rcx, sil
+ test sil, 0x02
+ jz .no_convert
+
+ mov dil, al
+ and dil, 0xf0
+ and al, 0x0f
+ shr dil, 3
+ add al, dil
+ shl dil, 2
+ add al, dil
+
+.no_convert:
+ ret
+
+convert_hours:
+;al in = byte (possibly bcd and 12 hour)
+;al out = byte (not bcd or 12 hour)
+;sil 0x02 = bcd, sil 0x01 = 12 hour
+;does not touch rdx, rcx, sil
+ test sil, 0x01
+ jz convert_bcd
+
+ test al, 0x80
+ jz .am
+
+ and al, 0x7f
+ call convert_bcd
+ cmp al, 12
+ je .noon
+
+ add al, 12
+ ret
+
+.noon:
+ ret
+
+.am:
+ call convert_bcd
+ cmp al, 12
+ je .midnight
+
+ ret
+
+.midnight:
+ xor al, al
+ ret
+
+global get_time_from_rtc
+get_time_from_rtc:
+;rax out = time (see timer.cpp for encoding)
+;we assume the year is 20xx (sorry)
+
+ mov dil, 11
+ call read_cmos_byte
+
+ shr al, 1
+ not al
+ and al, 3
+ mov sil, al
+
+ xor rdx, rdx
+
+.outer_loop:
+ mov rcx, rdx
+
+.wait_for_update_loop:
+ ;status register - 0x80 is update in progress
+ mov dil, 10
+ call read_cmos_byte
+ test al, 0x80
+ jnz .wait_for_update_loop
+
+ ;years
+ mov dil, 9
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;months
+ mov dil, 8
+ call read_cmos_byte
+ call convert_bcd
+ mov dl, al
+
+ shl edx, 16
+
+ ;days
+ mov dil, 7
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;hours
+ mov dil, 4
+ call read_cmos_byte
+ call convert_hours
+ mov dl, al
+
+ shl rdx, 16
+
+ ;minutes
+ mov dil, 2
+ call read_cmos_byte
+ call convert_bcd
+ mov dh, al
+
+ ;seconds
+ xor dil, dil
+ call read_cmos_byte
+ call convert_bcd
+ mov dl, al
+
+ cmp rdx, rcx
+ jne .outer_loop
+
+ mov rax, rdx
+ ret
diff --git a/kernel/source/timer.cpp b/kernel/source/timer.cpp
new file mode 100644
index 0000000..d6d37d7
--- /dev/null
+++ b/kernel/source/timer.cpp
@@ -0,0 +1,117 @@
+#include <hilbert/kernel/timer.hpp>
+
+namespace hilbert::kernel::timer {
+
+ struct sleeping_thread {
+ uint64_t sleeping_until;
+ application::thread *thread;
+ };
+
+ //sorted ascending by sleeping_until
+ static utility::list<sleeping_thread> *sleeping_threads;
+
+ uint64_t current_time;
+
+ //output is
+ // seconds | (minutes << 8) | (hours << 16) |
+ // (days << 24) | ( months << 32) | (years << 40)
+ extern "C" uint64_t get_time_from_rtc();
+
+ //index is (year % 4) * 12 + month - 1;
+ //output is days from january 1st 2000 to [month] 1st [year]
+ static uint16_t month_table[] {
+ 0, 31, 60, 91, 121, 152,
+ 182, 213, 244, 274, 305, 335,
+ 366, 397, 425, 456, 486, 517,
+ 547, 578, 609, 639, 670, 700,
+ 731, 762, 790, 821, 851, 882,
+ 912, 943, 974, 1004, 1035, 1065,
+ 1096, 1127, 1155, 1186, 1216, 1247,
+ 1277, 1308, 1339, 1369, 1400, 1430
+ };
+
+ //index is (year % 4) * 12 + month - 1;
+ //output is days in that month
+ static uint8_t month_table_2[] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+
+ void clamp(uint8_t &value, uint8_t min, uint8_t max) {
+ if (value < min)
+ value = min;
+ else if (value > max)
+ value = max;
+ }
+
+ extern "C" void enable_rtc_interrupts();
+
+ void init_timer() {
+
+ sleeping_threads = new utility::list<sleeping_thread>();
+
+ uint64_t rtc_time = get_time_from_rtc();
+
+ uint8_t years = rtc_time >> 40;
+ uint8_t months = (rtc_time >> 32) & 0xff;
+ uint8_t days = (rtc_time >> 24) & 0xff;
+ uint8_t hours = (rtc_time >> 16) & 0xff;
+ uint8_t minutes = (rtc_time >> 8) & 0xff;
+ uint8_t seconds = rtc_time & 0xff;
+
+ uint8_t month_table_index =
+ (years % 4) * 12 + months - 1;
+
+ clamp( years, 0, 99);
+ clamp( months, 1, 12);
+ clamp( days, 1, month_table_2[month_table_index]);
+ clamp( hours, 0, 23);
+ clamp(minutes, 0, 59);
+ clamp(seconds, 0, 59);
+
+ current_time = 1461 * (years / 4);
+ current_time += month_table[month_table_index];
+ current_time += days - 1;
+ current_time *= 86400;
+ current_time += hours * 3600;
+ current_time += minutes * 60;
+ current_time += seconds;
+ current_time *= 1024;
+
+ enable_rtc_interrupts();
+
+ }
+
+ void register_sleeping_thread(
+ uint64_t sleeping_until, application::thread *thread) {
+
+ auto *after = sleeping_threads->first;
+ while (after && after->value.sleeping_until < sleeping_until)
+ after = after->next;
+
+ sleeping_threads->insert_before(
+ { .sleeping_until = sleeping_until, .thread = thread }, after);
+
+ }
+
+ extern "C" void acknowledge_rtc_interrupt();
+
+ extern "C" void on_rtc_interrupt() {
+
+ ++current_time;
+
+ while (sleeping_threads->first &&
+ sleeping_threads->first->value.sleeping_until <=
+ current_time) {
+ application::paused_threads->insert(
+ sleeping_threads->first->value.thread);
+ sleeping_threads->remove(sleeping_threads->first);
+ }
+
+ acknowledge_rtc_interrupt();
+
+ }
+
+}
diff --git a/libraries/pake/include/pake/widgets/fixed-text.hpp b/libraries/pake/include/pake/widgets/fixed-text.hpp
index dc2e277..fb8a49e 100644
--- a/libraries/pake/include/pake/widgets/fixed-text.hpp
+++ b/libraries/pake/include/pake/widgets/fixed-text.hpp
@@ -5,18 +5,36 @@
namespace pake::widgets {
+ //a widget that draws text with a daguerre::fixed_font<bool>
class fixed_text : public widget {
+ //the font to use
const daguerre::fixed_font<bool> *font;
- daguerre::hilbert_color bg, fg;
+
+ //background color of the widget
+ daguerre::hilbert_color bg;
+
+ //color of the text
+ daguerre::hilbert_color fg;
+
+ //the text to draw
std::string text;
+ //has the text changed since the last draw to render
+ bool text_changed;
+
+ //the width and height of this widget, as set by notify_size
int width, height;
+
+ //the alignment of the text within the region
halign ha;
valign va;
public:
- //TODO: look up font in some kind of catalogue
+ //text: the text to draw. this can be changed later by set_text.
+ //font: the font to use. TODO: pass a string and look up the font with that name
+ //bg: the background color of the widget. fg: the color of the text.
+ //ha, va: the alignment of the text within the widget
fixed_text(
std::string &&text,
const daguerre::fixed_font<bool> *font,
@@ -24,6 +42,9 @@ namespace pake::widgets {
daguerre::hilbert_color fg,
halign ha, valign va);
+ //change the text to draw
+ void set_text(std::string &&text);
+
virtual void render(
dirtiable_image &onto, int x_off, int y_off, bool force) override;
diff --git a/libraries/pake/include/pake/window.hpp b/libraries/pake/include/pake/window.hpp
index bb63b9d..3f23d41 100644
--- a/libraries/pake/include/pake/window.hpp
+++ b/libraries/pake/include/pake/window.hpp
@@ -6,25 +6,46 @@
namespace pake {
+ //a window / a connection to the compositor.
class window {
+ //the socket that connects us to the compositor
euler::syscall::stream_handle socket;
+ //the size of the window
int width;
int height;
+ //the rendered contents of the window. pixels are dirty when
+ //the compositor has not been informed of them changing.
dirtiable_image contents;
+
+ //the root widget, or an unset pointer if there is no root widget set
std::unique_ptr<widget> root;
public:
+ //create a new window / connection to the compositor
window(int width, int height, const std::string &title);
+
+ //destroy the window / connection to the compositor
~window();
+ //tell the compositor to show this window. you probably want to call
+ //set_root and render_and_send_to_compositor before calling this.
void show();
+
+ //tell the compositor to hide this window
void hide();
+ //set the root widget. the widget is notified that its size is the
+ //size of the window, and then it is rendered with force = true.
void set_root(std::unique_ptr<widget> &&w);
+ //get the root widget (assumes there is one)
+ widget *get_root();
+
+ //renders the root widget with force = false and
+ //then sends the new contents to the compositor.
void render_and_send_to_compositor();
};
diff --git a/libraries/pake/source/widgets/fixed-text.cpp b/libraries/pake/source/widgets/fixed-text.cpp
index c3a9a10..69c4046 100644
--- a/libraries/pake/source/widgets/fixed-text.cpp
+++ b/libraries/pake/source/widgets/fixed-text.cpp
@@ -15,12 +15,18 @@ namespace pake::widgets {
daguerre::hilbert_color fg,
halign ha, valign va)
: font(font), bg(bg), fg(fg),
- text(std::move(text)), ha(ha), va(va) {}
+ text(std::move(text)),
+ ha(ha), va(va) {}
+
+ void fixed_text::set_text(std::string &&text) {
+ this->text = std::move(text);
+ text_changed = true;
+ }
void fixed_text::render(
dirtiable_image &onto, int x_off, int y_off, bool force) {
- if (force) {
+ if (force || text_changed) {
//TODO: check overflow
@@ -54,6 +60,8 @@ namespace pake::widgets {
*font, fg, x_off, y_off,
text.data(), draw_if_true);
+ text_changed = false;
+
}
}
diff --git a/makefile b/makefile
index c827422..3151d4d 100644
--- a/makefile
+++ b/makefile
@@ -44,6 +44,7 @@ clean:
make -C applications/init clean
make -C applications/goldman clean
make -C applications/hello clean
+ make -C applications/clock clean
make -C libraries/daguerre clean
make -C libraries/pake clean
@@ -136,15 +137,21 @@ applications/goldman/build/goldman.elf: ${APP_DEPS} ${DAGUERRE_DEP}
applications/hello/build/hello.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP}
+make -C applications/hello build/hello.elf
+.PHONY: applications/clock/build/clock.elf
+applications/clock/build/clock.elf: ${APP_DEPS} ${DAGUERRE_DEP} ${PAKE_DEP}
+ +make -C applications/clock build/clock.elf
+
build/initfs.tgz: applications/init/build/init.elf \
applications/goldman/build/goldman.elf \
- applications/hello/build/hello.elf
+ applications/hello/build/hello.elf \
+ applications/clock/build/clock.elf
@mkdir -p build
rm -rf build/initfs
cp -r skeleton build/initfs
cp applications/init/build/init.elf build/initfs/bin/init
cp applications/goldman/build/goldman.elf build/initfs/bin/goldman
cp applications/hello/build/hello.elf build/initfs/bin/hello
+ cp applications/clock/build/clock.elf build/initfs/bin/clock
cd build/initfs && tar czf ../initfs.tgz .
build/disk.iso: kernel/build/kernel.elf build/initfs.tgz ${LIMINE_DEP}
diff --git a/readme.txt b/readme.txt
index 0cbd9a8..425e51d 100644
--- a/readme.txt
+++ b/readme.txt
@@ -67,12 +67,16 @@ the following directories and files are released under the text in cc0.txt
project structure:
+ - applications/clock:
+ a simple application that displays the current time in EDT.
+
- applications/goldman:
- the default compositor, in a very early stage
+ the default compositor.
- applications/init:
- the initial program loaded by the kernel. currently it just
- (attempts to) start /bin/compositor and then /bin/hello.
+ the initial program loaded by the kernel. currently it just starts the
+ compositor and the clock, but in the future it will read some kind of
+ configuration file and decide what to do based on that.
- documentation:
documentation. currently this directory is a bit disorganized, and has