1/*
2 * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7/* CAmkES provides a generated header that prototypes all the relevant
8 * generated symbols.
9 */
10#include <camkes.h>
11
12#include <stdbool.h>
13#include <stdlib.h>
14#include <string.h>
15
16/* Hardware text mode color constants. */
17enum vga_color {
18	VGA_COLOR_BLACK = 0,
19	VGA_COLOR_BLUE = 1,
20	VGA_COLOR_GREEN = 2,
21	VGA_COLOR_CYAN = 3,
22	VGA_COLOR_RED = 4,
23	VGA_COLOR_MAGENTA = 5,
24	VGA_COLOR_BROWN = 6,
25	VGA_COLOR_LIGHT_GREY = 7,
26	VGA_COLOR_DARK_GREY = 8,
27	VGA_COLOR_LIGHT_BLUE = 9,
28	VGA_COLOR_LIGHT_GREEN = 10,
29	VGA_COLOR_LIGHT_CYAN = 11,
30	VGA_COLOR_LIGHT_RED = 12,
31	VGA_COLOR_LIGHT_MAGENTA = 13,
32	VGA_COLOR_LIGHT_BROWN = 14,
33	VGA_COLOR_WHITE = 15,
34};
35
36static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
37	return fg | bg << 4;
38}
39
40static inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
41	return (uint16_t) uc | (uint16_t) color << 8;
42}
43
44size_t strlen(const char* str) {
45	size_t len = 0;
46	while (str[len])
47		len++;
48	return len;
49}
50
51static const size_t VGA_WIDTH = 80;
52static const size_t VGA_HEIGHT = 25;
53
54size_t terminal_row;
55size_t terminal_column;
56uint8_t terminal_color;
57uint16_t* terminal_buffer;
58
59void terminal_initialize(void) {
60	terminal_row = 0;
61	terminal_column = 0;
62	terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
63	printf("Casting a buffer pointer\n");
64	terminal_buffer = (uint16_t*) &mem[0];
65	printf("Writing to buffer\n");
66	for (size_t y = 0; y < VGA_HEIGHT; y++) {
67		for (size_t x = 0; x < VGA_WIDTH; x++) {
68			const size_t index = y * VGA_WIDTH + x;
69			terminal_buffer[index] = vga_entry(' ', terminal_color);
70		}
71	}
72	printf("Terminal initialized\n");
73}
74
75void terminal_setcolor(uint8_t color) {
76	terminal_color = color;
77}
78
79void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
80	const size_t index = y * VGA_WIDTH + x;
81	terminal_buffer[index] = vga_entry(c, color);
82}
83
84void terminal_putchar(char c) {
85	terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
86	if (++terminal_column == VGA_WIDTH) {
87		terminal_column = 0;
88		if (++terminal_row == VGA_HEIGHT)
89			terminal_row = 0;
90	}
91}
92
93void terminal_write(const char* data, size_t size) {
94	for (size_t i = 0; i < size; i++)
95		terminal_putchar(data[i]);
96}
97
98void terminal_writestring(const char* data) {
99	terminal_write(data, strlen(data));
100}
101
102/* This function is invoked by the main CAmkES thread in this component. */
103int run(void) {
104  	/* Initialize terminal interface */
105	  terminal_initialize();
106
107  	/* Display welcome message. */
108    terminal_writestring("Hello, I am a CamKes component!\n");
109    return 0;
110}
111