Xyris  0.5
console.cpp
Go to the documentation of this file.
1 /**
2  * @file console.cpp
3  * @author Keeton Feavel ([email protected])
4  * @brief Framebuffer console
5  * @version 0.3
6  * @date 2020-07-09
7  *
8  * @copyright Copyright Keeton Feavel et al (c) 2020
9  *
10  */
15 #include <Library/stdio.hpp>
16 #include <Locking/Mutex.hpp>
17 #include <Logger.hpp>
18 #include <stddef.h>
19 
20 namespace Console {
21 
22 #define PUSH_VAL(VAL) ansiValues[ansiValuesIdx++] = (VAL)
23 #define POP_VAL() ansiValues[--ansiValuesIdx]
24 #define CLEAR_VALS() ansiValuesIdx = 0
25 #define ESC ('\033')
26 #define TAB_WIDTH 4u
27 
28 enum vgaColor : uint32_t {
29  VGA_Black = 0x000000,
30  VGA_Blue = 0x0000AA,
31  VGA_Green = 0x00AA00,
32  VGA_Cyan = 0x00AAAA,
33  VGA_Red = 0xAA0000,
34  VGA_Magenta = 0xAA00AA,
35  VGA_Brown = 0xAA5500,
36  VGA_LightGrey = 0xAAAAAA,
37  VGA_DarkGrey = 0x555555,
38  VGA_LightBlue = 0x5555FF,
39  VGA_LightGreen = 0x55FF55,
40  VGA_LightCyan = 0x55FFFF,
41  VGA_LightRed = 0xFF5555,
42  VGA_LightMagenta = 0xFF55FF,
43  VGA_Yellow = 0xFFFF55,
44  VGA_White = 0xFFFFFF,
45 };
46 
47 enum ansiColor : uint16_t {
48  Background = 10,
49  Black = 30,
50  Red = 31,
51  Green = 32,
52  Yellow = 33,
53  Blue = 34,
54  Magenta = 35,
55  Cyan = 36,
56  White = 37,
58  BrightRed = 91,
61  BrightBlue = 94,
63  BrightCyan = 96,
65 };
66 
67 // Coorinate trackers
68 static uint8_t cursorX = 0;
69 static uint8_t cursorY = 0;
70 static uint32_t colorBack = VGA_Black;
71 static uint32_t colorFore = VGA_White;
72 static uint32_t resetBack = VGA_Black;
73 static uint32_t resetFore = VGA_White;
74 
75 // ANSI State and value storage
78  Esc,
81 };
82 
83 static uint16_t ansiVal = 0;
84 static size_t ansiValuesIdx = 0;
85 static uint16_t ansiValues[8] = { 0 };
86 static ansiStateType ansiState = Normal;
87 static uint32_t ansiCursorX = 0;
88 static uint32_t ansiCursorY = 0;
89 static uint32_t ansiVGATable[16] = {
94 };
95 
96 static Mutex ttyLock;
97 
98 static void Lock()
99 {
100  ttyLock.lock();
101 }
102 
103 static void Unlock()
104 {
105  ttyLock.unlock();
106 }
107 
108 static int putchar(unsigned c, void** ptr)
109 {
110  (void)ptr;
111  // Check the ANSI state
112  switch (ansiState) {
113  case Normal: // print the character out normally unless it's an ESC
114  if (c != ESC)
115  break;
116  ansiState = Esc;
117  goto end;
118  case Esc: // we got an ESC, now we need a left square bracket
119  if (c != '[')
120  break;
121  ansiState = Bracket;
122  goto end;
123  case Bracket: // we're looking for a value/command char now
124  if (c >= '0' && c <= '9') {
125  ansiVal = (uint16_t)(c - '0');
126  ansiState = Value;
127  goto end;
128  } else if (c == 's') { // Save cursor position attribute
129  ansiCursorX = cursorX;
130  ansiCursorY = cursorY;
131  goto normal;
132  } else if (c == 'u') { // Restore cursor position attribute
133  cursorX = ansiCursorX;
134  cursorY = ansiCursorY;
135  goto normal;
136  }
137  break;
138  case Value:
139  if (c == ';') { // the semicolon is a value separator
140  // enqueue the value here
141  PUSH_VAL(ansiVal);
142  ansiState = Bracket;
143  ansiVal = 0;
144  } else if (c == 'm') { // Set color/text attributes command
145  PUSH_VAL(ansiVal);
146  // take action here
147  // iterate through all values
148  while (ansiValuesIdx > 0) {
149  ansiVal = (uint16_t)POP_VAL();
150  if (ansiVal == 0) {
151  // Reset code will just reset to whatever was specified in tty_clear().
152  colorFore = resetFore;
153  colorBack = resetBack;
154  } else if (ansiVal >= Black && ansiVal <= White) {
155  colorFore = (vgaColor)ansiVGATable[ansiVal - Black];
156  } else if (ansiVal >= (Black + Background) && ansiVal <= (White + Background)) {
157  colorBack = (vgaColor)ansiVGATable[ansiVal - (Black + Background)];
158  } else if (ansiVal >= BrightBlack && ansiVal <= BrightWhite) {
159  colorFore = (vgaColor)ansiVGATable[ansiVal - BrightBlack + 8];
160  } else if (ansiVal >= (BrightBlack + Background) && ansiVal <= (BrightWhite + Background)) {
161  colorBack = (vgaColor)ansiVGATable[ansiVal - (BrightBlack + Background) + 8];
162  } // else it was an unknown code
163  }
164  goto normal;
165  } else if (c == 'H' || c == 'f') { // Set cursor position attribute
166  PUSH_VAL(ansiVal);
167  // the proper order is 'line (y);column (x)'
168  if (ansiValuesIdx > 2) {
169  goto error;
170  }
171  cursorX = (uint8_t)POP_VAL();
172  cursorY = (uint8_t)POP_VAL();
173  goto normal;
174  } else if (c == 'J') { // Clear screen attribute
175  // The proper code is ESC[2J
176  if (ansiVal != 2) {
177  goto error;
178  }
179  // Clear by resetting the double buffer and swapping.
180  // TODO: Find a better way to do this?
181  Logger::Debug(__func__, "Clearing screen");
183  Graphics::swap();
184  } else if (c >= '0' && c <= '9') { // just another digit of a value
185  ansiVal = (uint16_t)(ansiVal * 10 + (uint16_t)(c - '0'));
186  } else
187  break; // invald code, so just return to normal
188  // we hit one of the cases so return
189  goto end;
190  }
191  // we fell through some way or another so just reset to Normal no matter what
192  ansiState = Normal;
193  switch (c) {
194  // Backspace
195  case 0x08:
196  if (cursorX > 0) {
197  cursorX--;
198  }
199  break;
200  // Newline
201  case '\n':
202  cursorX = 0;
203  cursorY++;
204  break;
205  case '\t':
206  while (++cursorX % TAB_WIDTH)
207  ;
208  break;
209  // Carriage return
210  case '\r':
211  cursorX = 0;
212  break;
213  // Anything else (visible characters)
214  default:
215  Graphics::Font::Draw(c, cursorX++, cursorY, colorFore, colorBack);
216  }
217 
218  // Move to the next line
219  // TODO: Get width of "screen" (replace 80 with width) (#275)
220  if (cursorX >= 80) {
221  Logger::Debug(__func__, "Move to the next line");
222  cursorX = 0;
223  cursorY++;
224  }
225  // Clear the screen
226  // TODO: Get height of "screen" (replace 25 with height) (#275)
227  if (cursorY >= 25) {
228  Logger::Debug(__func__, "Shift up the screen");
229  //TODO: Shift text up and reset the bottom line
230  cursorX = 0;
231  cursorY = 25 - 1;
232  }
233  goto end;
234 error:
235  // Reset stack index
236  CLEAR_VALS();
237  // Return to normal
238  ansiState = Normal;
239  ansiVal = 0;
240  return -1;
241 normal:
242  ansiState = Normal;
243  ansiVal = 0;
244 end:
245  return 0;
246 }
247 
248 int vprintf(const char* fmt, va_list args)
249 {
250  int retval;
251  Lock();
252  retval = printf_helper(fmt, args, putchar, NULL);
253  Unlock();
254  return retval;
255 }
256 
257 void write(const char c)
258 {
259  Lock();
260  putchar(c, NULL);
261  Unlock();
262 }
263 
264 void write(const char* str)
265 {
266  size_t i = 0;
267  Lock();
268  while (str[i])
269  putchar(str[i++], NULL);
270  Unlock();
271 }
272 
273 int printf(const char* fmt, ...)
274 {
275  va_list args;
276  int ret_val;
277 
278  va_start(args, fmt);
279  ret_val = vprintf(fmt, args);
280  va_end(args);
281  // Swap out the buffer in draw
282  Graphics::swap();
283 
284  return ret_val;
285 }
286 
287 void reset(uint32_t fore, uint32_t back)
288 {
289  cursorX = cursorY = 0;
290  colorBack = resetBack = back;
291  colorFore = resetFore = fore;
292 }
293 
294 void reset()
295 {
296  cursorX = cursorY = 0;
297  colorBack = resetBack;
298  colorFore = resetFore;
299 }
300 
301 } // !console
Console::VGA_LightBlue
@ VGA_LightBlue
Definition: console.cpp:38
Mutex::unlock
bool unlock()
Release the mutex.
Definition: Mutex.cpp:38
stdio.hpp
Console::Yellow
@ Yellow
Definition: console.cpp:52
Console::VGA_Cyan
@ VGA_Cyan
Definition: console.cpp:32
Console::White
@ White
Definition: console.cpp:56
Console::VGA_LightMagenta
@ VGA_LightMagenta
Definition: console.cpp:42
Console::write
void write(const char c)
Definition: console.cpp:257
Console::BrightBlue
@ BrightBlue
Definition: console.cpp:61
Console::VGA_LightGreen
@ VGA_LightGreen
Definition: console.cpp:39
graphics.hpp
Console::VGA_LightRed
@ VGA_LightRed
Definition: console.cpp:41
Console::VGA_Magenta
@ VGA_Magenta
Definition: console.cpp:34
font.hpp
CLEAR_VALS
#define CLEAR_VALS()
Definition: console.cpp:24
console.hpp
Framebuffer console.
Console::Blue
@ Blue
Definition: console.cpp:53
ESC
#define ESC
Definition: console.cpp:25
Console::VGA_White
@ VGA_White
Definition: console.cpp:44
framebuffer.hpp
Console::ansiColor
ansiColor
Definition: console.cpp:47
Graphics::swap
void swap()
Swap the data on backbuffer to memory video buffer and show in the screen.
Definition: graphics.cpp:93
Graphics::resetDoubleBuffer
void resetDoubleBuffer()
Fill the backbuffer with '0'.
Definition: graphics.cpp:86
Console::BrightMagenta
@ BrightMagenta
Definition: console.cpp:62
Console::Green
@ Green
Definition: console.cpp:51
Console::VGA_Blue
@ VGA_Blue
Definition: console.cpp:30
Mutex
Definition: Mutex.hpp:16
Console::VGA_Yellow
@ VGA_Yellow
Definition: console.cpp:43
Console::BrightWhite
@ BrightWhite
Definition: console.cpp:64
Mutex::lock
bool lock()
Aquire the mutex.
Definition: Mutex.cpp:20
Console::Bracket
@ Bracket
Definition: console.cpp:79
Console::vgaColor
vgaColor
Definition: console.cpp:28
Console::vprintf
int vprintf(const char *fmt, va_list args)
Definition: console.cpp:248
Console::BrightYellow
@ BrightYellow
Definition: console.cpp:60
Console::Magenta
@ Magenta
Definition: console.cpp:54
Console::VGA_Red
@ VGA_Red
Definition: console.cpp:33
Console::printf
int printf(const char *fmt,...)
Definition: console.cpp:273
Console::VGA_LightGrey
@ VGA_LightGrey
Definition: console.cpp:36
Console::VGA_DarkGrey
@ VGA_DarkGrey
Definition: console.cpp:37
Console::Esc
@ Esc
Definition: console.cpp:78
Console::VGA_Brown
@ VGA_Brown
Definition: console.cpp:35
Graphics::Font::Draw
void Draw(char c, uint32_t x, uint32_t y, uint32_t fore)
Draw the character at the given coordinates in the given color.
Definition: font.cpp:157
Console::ansiStateType
ansiStateType
Definition: console.cpp:76
Console::VGA_Black
@ VGA_Black
Definition: console.cpp:29
Console::Normal
@ Normal
Definition: console.cpp:77
Console::VGA_LightCyan
@ VGA_LightCyan
Definition: console.cpp:40
TAB_WIDTH
#define TAB_WIDTH
Definition: console.cpp:26
POP_VAL
#define POP_VAL()
Definition: console.cpp:23
Logger::Debug
static void Debug(const char *tag, const char *fmt,...)
Definition: Logger.cpp:71
Console::Background
@ Background
Definition: console.cpp:48
Console::BrightGreen
@ BrightGreen
Definition: console.cpp:59
Console::reset
void reset(uint32_t fore, uint32_t back)
Definition: console.cpp:287
Console::VGA_Green
@ VGA_Green
Definition: console.cpp:31
Console::BrightCyan
@ BrightCyan
Definition: console.cpp:63
Console::Cyan
@ Cyan
Definition: console.cpp:55
Console::Red
@ Red
Definition: console.cpp:50
printf_helper
int printf_helper(const char *fmt, va_list args, printf_cb_fnptr_t fn, void *ptr)
Perform all printf operations on the format string using the provided argument list and uses the call...
Definition: printf.cpp:105
Console::Value
@ Value
Definition: console.cpp:80
Console::BrightRed
@ BrightRed
Definition: console.cpp:58
Console
Definition: console.cpp:20
Mutex.hpp
Console::BrightBlack
@ BrightBlack
Definition: console.cpp:57
PUSH_VAL
#define PUSH_VAL(VAL)
Definition: console.cpp:22
Console::Black
@ Black
Definition: console.cpp:49
Logger.hpp