148730Siwasaki/*
248730Siwasaki * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
348730Siwasaki *
448730Siwasaki * SPDX-License-Identifier: BSD-2-Clause
548730Siwasaki */
648730Siwasaki
748730Siwasaki/* CAmkES provides a generated header that prototypes all the relevant
848730Siwasaki * generated symbols.
948730Siwasaki */
1048730Siwasaki#include <camkes.h>
1148730Siwasaki
1248730Siwasaki#include <stdbool.h>
1348730Siwasaki#include <stdlib.h>
1448730Siwasaki#include <string.h>
1548730Siwasaki
1648730Siwasaki/* Hardware text mode color constants. */
1748730Siwasakienum vga_color {
1848730Siwasaki	VGA_COLOR_BLACK = 0,
1948730Siwasaki	VGA_COLOR_BLUE = 1,
2048730Siwasaki	VGA_COLOR_GREEN = 2,
2148730Siwasaki	VGA_COLOR_CYAN = 3,
2248730Siwasaki	VGA_COLOR_RED = 4,
2348730Siwasaki	VGA_COLOR_MAGENTA = 5,
2448730Siwasaki	VGA_COLOR_BROWN = 6,
2548730Siwasaki	VGA_COLOR_LIGHT_GREY = 7,
2648730Siwasaki	VGA_COLOR_DARK_GREY = 8,
2748730Siwasaki	VGA_COLOR_LIGHT_BLUE = 9,
2848730Siwasaki	VGA_COLOR_LIGHT_GREEN = 10,
2948730Siwasaki	VGA_COLOR_LIGHT_CYAN = 11,
3050479Speter	VGA_COLOR_LIGHT_RED = 12,
3148730Siwasaki	VGA_COLOR_LIGHT_MAGENTA = 13,
3248730Siwasaki	VGA_COLOR_LIGHT_BROWN = 14,
3348730Siwasaki	VGA_COLOR_WHITE = 15,
3448730Siwasaki};
3576611Snsayer
36116074Simpstatic inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) {
3748730Siwasaki	return fg | bg << 4;
3848730Siwasaki}
3948730Siwasaki
4048730Siwasakistatic inline uint16_t vga_entry(unsigned char uc, uint8_t color) {
4148730Siwasaki	return (uint16_t) uc | (uint16_t) color << 8;
4248730Siwasaki}
4348730Siwasaki
4448730Siwasakisize_t strlen(const char* str) {
4548730Siwasaki	size_t len = 0;
4648730Siwasaki	while (str[len])
4748730Siwasaki		len++;
4848730Siwasaki	return len;
4948730Siwasaki}
5048730Siwasaki
5148730Siwasakistatic const size_t VGA_WIDTH = 80;
5276611Snsayerstatic const size_t VGA_HEIGHT = 25;
5348730Siwasaki
5448730Siwasakisize_t terminal_row;
5548730Siwasakisize_t terminal_column;
5648730Siwasakiuint8_t terminal_color;
5748730Siwasakiuint16_t* terminal_buffer;
5876611Snsayer
5976611Snsayervoid terminal_initialize(void) {
60116442Smaxim	terminal_row = 0;
6148730Siwasaki	terminal_column = 0;
6248730Siwasaki	terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
6348730Siwasaki	printf("Casting a buffer pointer\n");
6448730Siwasaki	terminal_buffer = (uint16_t*) &mem[0];
6576611Snsayer	printf("Writing to buffer\n");
6676611Snsayer	for (size_t y = 0; y < VGA_HEIGHT; y++) {
6748730Siwasaki		for (size_t x = 0; x < VGA_WIDTH; x++) {
6848730Siwasaki			const size_t index = y * VGA_WIDTH + x;
6948730Siwasaki			terminal_buffer[index] = vga_entry(' ', terminal_color);
7048730Siwasaki		}
7148730Siwasaki	}
7248730Siwasaki	printf("Terminal initialized\n");
7348730Siwasaki}
7448730Siwasaki
7548730Siwasakivoid terminal_setcolor(uint8_t color) {
7648730Siwasaki	terminal_color = color;
7748730Siwasaki}
7848730Siwasaki
7948730Siwasakivoid terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
8048730Siwasaki	const size_t index = y * VGA_WIDTH + x;
8148730Siwasaki	terminal_buffer[index] = vga_entry(c, color);
8248730Siwasaki}
8348730Siwasaki
8448730Siwasakivoid terminal_putchar(char c) {
8548730Siwasaki	terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
8648730Siwasaki	if (++terminal_column == VGA_WIDTH) {
8776611Snsayer		terminal_column = 0;
8848730Siwasaki		if (++terminal_row == VGA_HEIGHT)
8948730Siwasaki			terminal_row = 0;
9048730Siwasaki	}
9148730Siwasaki}
9248730Siwasaki
9348730Siwasakivoid terminal_write(const char* data, size_t size) {
9448730Siwasaki	for (size_t i = 0; i < size; i++)
9548730Siwasaki		terminal_putchar(data[i]);
9648730Siwasaki}
9748730Siwasaki
9848730Siwasakivoid terminal_writestring(const char* data) {
9976611Snsayer	terminal_write(data, strlen(data));
10076611Snsayer}
10176611Snsayer
10276611Snsayer/* This function is invoked by the main CAmkES thread in this component. */
10376611Snsayerint run(void) {
10476611Snsayer  	/* Initialize terminal interface */
10576611Snsayer	  terminal_initialize();
10676611Snsayer
10776611Snsayer  	/* Display welcome message. */
10876611Snsayer    terminal_writestring("Hello, I am a CamKes component!\n");
10976611Snsayer    return 0;
11076611Snsayer}
11176611Snsayer