2018-08-31 18:04:44 +02:00
|
|
|
#include <sys/console.h>
|
2018-09-07 14:00:06 +02:00
|
|
|
#include <sys/keybios.h>
|
2018-08-31 18:04:44 +02:00
|
|
|
#include <sys/casio_syscalls.h>
|
|
|
|
|
2018-09-07 14:00:06 +02:00
|
|
|
|
2018-08-31 18:04:44 +02:00
|
|
|
/*
|
|
|
|
* Console instance for printf etc.
|
|
|
|
*/
|
|
|
|
_console _console_ctx = {
|
|
|
|
.cursor_x = 0,
|
|
|
|
.cursor_y = 0,
|
|
|
|
.buf_strlen = 0,
|
|
|
|
.buf = {0},
|
|
|
|
};
|
|
|
|
|
2018-09-07 14:00:06 +02:00
|
|
|
/*
|
|
|
|
* GetKeyWait provides a row from 2 (bottom) to 10 (top).
|
|
|
|
* The only exception is the AC key with a row of 1.
|
|
|
|
* This macro maps the row to 0 (top) to 8 (bottom)
|
|
|
|
* and 0 (AC)
|
|
|
|
*/
|
|
|
|
#define _CONSOLE_CONV_ROW(row) (!!(row - _CASIO_ROW_AC) * (_CASIO_ROW_MAX - row))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GetKeyWait provides a column from 2 (right) to 10 (left).
|
|
|
|
* The only exception is the AC key with a column of 1.
|
|
|
|
* This macro maps the column to 0 (left) to 8 (right)
|
|
|
|
* and 0 (AC)
|
|
|
|
*/
|
|
|
|
#define _CONSOLE_CONV_COL(col) (!!(col - _CASIO_COL_AC) * (_CASIO_COL_MAX - col))
|
|
|
|
|
|
|
|
#define _CONSOLE_MAX_ROW (_CASIO_ROW_MAX - _CASIO_ROW_MIN + 1)
|
|
|
|
#define _CONSOLE_MAX_COL (_CASIO_COL_MAX - _CASIO_COL_MIN + 1)
|
|
|
|
|
|
|
|
#define _CONSOLE_MODES 3
|
|
|
|
#define _CONSOLE_MODE_NORMAL 0
|
|
|
|
#define _CONSOLE_MODE_SHIFT 1
|
|
|
|
#define _CONSOLE_MODE_ALPHA 2
|
|
|
|
|
|
|
|
static const char row_col_to_ascii[_CONSOLE_MODES][_CONSOLE_MAX_ROW][_CONSOLE_MAX_COL] =
|
|
|
|
{
|
|
|
|
//row_col_to_ascii[_CONSOLE_MAX_MODE_NORMAL]
|
|
|
|
{
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, '(', ')', ',', 0},
|
|
|
|
{'7', '8', '9', '\b', 0, 0},
|
|
|
|
{'4', '5', '6', '\x9E', '\xF6', 0},
|
|
|
|
{'1', '2', '3', '+', '-', 0},
|
|
|
|
{'0', '.', 0, ' ', '\n', 0}
|
|
|
|
},
|
|
|
|
|
|
|
|
//row_col_to_ascii[_CONSOLE_MAX_MODE_SHIFT]
|
|
|
|
{
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 'e', 0, 0, 0},
|
|
|
|
{0, 0, 0, 'x', 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, '{', '}', 0},
|
|
|
|
{0, 0, 0, '[', ']', 0},
|
|
|
|
{'i', '=', 0, 0, '\n', 0},
|
|
|
|
},
|
|
|
|
//row_col_to_ascii[_CONSOLE_MAX_MODE_ALPHA]
|
|
|
|
{
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0, 0, 0},
|
|
|
|
{0, 0, 'r', 0, 0, 0},
|
|
|
|
{'A', 'B', 'C', 'D', 'E', 'F'},
|
|
|
|
{'G', 'H', 'I', 'J', 'K', 'L'},
|
|
|
|
{'M', 'N', 'O', '\b', 0, 0},
|
|
|
|
{'P', 'Q', 'R', 'S', 'T', 0},
|
|
|
|
{'U', 'V', 'W', 'X', 'Y', 0},
|
|
|
|
{'Z', ' ', '"', 0, 0, 0},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
int _console_read(_console *ctx, int file, char *ptr, int len) {
|
|
|
|
char mode = _CONSOLE_MODE_NORMAL;
|
|
|
|
int col, row;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
while (i < len) {
|
|
|
|
GetKeyWait(&col, &row, 0, 0, 0, 0);
|
|
|
|
|
|
|
|
if (col == _CASIO_COL_SHIFT && row == _CASIO_ROW_SHIFT) {
|
|
|
|
mode = _CONSOLE_MODE_SHIFT;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (col == _CASIO_COL_ALPHA && row == _CASIO_ROW_ALPHA) {
|
|
|
|
mode = _CONSOLE_MODE_ALPHA;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// append char to string
|
|
|
|
ptr[i] = row_col_to_ascii[mode][_CONSOLE_CONV_ROW(row)][_CONSOLE_CONV_COL(col)];
|
|
|
|
|
|
|
|
// if the read character was a LF, stop
|
|
|
|
if (ptr[i] == '\n') {
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// print character to stdout
|
|
|
|
_console_write(&_console_ctx, 1, ptr+i, 1);
|
|
|
|
_console_flush(&_console_ctx);
|
|
|
|
Bdisp_PutDisp_DD();
|
|
|
|
|
|
|
|
// reset mode
|
|
|
|
mode = _CONSOLE_MODE_NORMAL;
|
|
|
|
|
|
|
|
// increment i if the current char was not '\0' only
|
|
|
|
i += !!ptr[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
2018-08-31 18:04:44 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Sets the internal cursor position on the console.
|
|
|
|
* Note that the Casio cursor position will not be set until
|
|
|
|
* the console is flushed (automatically or manually).
|
|
|
|
*/
|
|
|
|
void _console_set_cursor(_console *ctx, unsigned char x, unsigned char y) {
|
|
|
|
/*
|
|
|
|
* No need to flush here, because the buffer already was flushed
|
|
|
|
* at the end of the _console_write() function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (x < _CONSOLE_WIDTH && y < _CONSOLE_HEIGHT) {
|
|
|
|
ctx->cursor_x = x;
|
|
|
|
ctx->cursor_y = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Writes the (potentially but not necessarily null-terminated)
|
|
|
|
* string *ptr to the internal buffer. May flush and invoke
|
|
|
|
* the Casio "locate" and "Print" syscalls.
|
|
|
|
*/
|
|
|
|
int _console_write (_console *ctx, int file, char *ptr, int len)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Start parsing
|
|
|
|
*/
|
|
|
|
while (len-- && *ptr) {
|
|
|
|
/*
|
|
|
|
* Filter out all control characters
|
|
|
|
*/
|
|
|
|
switch (*ptr) {
|
|
|
|
case '\a':
|
|
|
|
// ignore
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
case '\b':
|
|
|
|
// undo last char (if not first char in line)
|
|
|
|
// no wrapping
|
|
|
|
ctx->cursor_x -= !!ctx->cursor_x;
|
|
|
|
ctx->buf_strlen -= !!ctx->buf_strlen;
|
|
|
|
ctx->buf[ctx->buf_strlen] = '\0';
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
case '\f':
|
|
|
|
case '\v':
|
|
|
|
_console_flush(ctx);
|
|
|
|
ctx->cursor_y = (ctx->cursor_y + 1) % _CONSOLE_HEIGHT;
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
case '\n':
|
|
|
|
_console_flush(ctx);
|
|
|
|
ctx->cursor_x = 0;
|
|
|
|
ctx->cursor_y = (ctx->cursor_y + (ctx->cursor_x < _CONSOLE_WIDTH)) % _CONSOLE_HEIGHT;
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
case '\r':
|
|
|
|
_console_flush(ctx);
|
|
|
|
ctx->cursor_x = 0;
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
case '\t':
|
|
|
|
;
|
|
|
|
/*
|
|
|
|
* Go to next tab stop (or to the end of the line).
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Somehow the following statement (see int s) cannot be written directly inside
|
|
|
|
* the condition of the for loop (or the program will act strangely).
|
|
|
|
* Possibly due to signedness? TODO
|
|
|
|
*/
|
|
|
|
int s = _CONSOLE_TAB_LEN - (ctx->cursor_x % _CONSOLE_TAB_LEN);
|
|
|
|
for (int i = 0; i < s; i++) {
|
|
|
|
_console_write(ctx, file, " ", 1);
|
|
|
|
}
|
|
|
|
ptr++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add char to the buffer (flushes before it overflows)
|
|
|
|
_console_putc(ctx, *ptr);
|
|
|
|
|
|
|
|
// Flush buffer if there is a line wrap
|
|
|
|
if (ctx->cursor_x == _CONSOLE_WIDTH - 1) {
|
|
|
|
/*
|
|
|
|
* Temporarily increment cursor_x (without wrapping)
|
|
|
|
* because _console_flush expects the cursor to point
|
|
|
|
* to the position of the next char.
|
|
|
|
*/
|
|
|
|
ctx->cursor_x++;
|
|
|
|
_console_flush(ctx);
|
|
|
|
ctx->cursor_x--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move curser to the left (wrap if bounds are exceeded)
|
|
|
|
ctx->cursor_x = (ctx->cursor_x + 1) % _CONSOLE_WIDTH;
|
|
|
|
|
|
|
|
// Move curser down if (ctx->cursor_x == 0) (wrap if bounds are exceeded)
|
|
|
|
ctx->cursor_y = (ctx->cursor_y + !ctx->cursor_x) % _CONSOLE_HEIGHT;
|
|
|
|
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Always flush in the end
|
|
|
|
_console_flush(ctx);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adds a character to the internal buffer.
|
|
|
|
* Does not take care of the cursor position.
|
|
|
|
* May invoke _console_flush() to print the contents of the internal buffer.
|
|
|
|
* Use _console_flush() to manually flush the contents to the console output.
|
|
|
|
* Does not change the position of the internal cursor.
|
|
|
|
*/
|
|
|
|
void _console_putc(_console *ctx, char c) {
|
|
|
|
if (ctx->buf_strlen == _CONSOLE_BUF_WIDTH - 1) {
|
|
|
|
_console_flush(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->buf[ctx->buf_strlen++] = c;
|
|
|
|
ctx->buf[ctx->buf_strlen] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prints the buffer out to the console and invokes
|
|
|
|
* the Casio "locate" and "Print" syscalls.
|
|
|
|
* Resets the internal buffer to "".
|
|
|
|
* Does not change the position of the internal cursor.
|
|
|
|
*/
|
|
|
|
void _console_flush(_console *ctx) {
|
|
|
|
/*
|
|
|
|
* Local syscall to Casio's locate
|
|
|
|
* because Casio's syscall is overwritten by _casio_set_cursor()
|
|
|
|
*/
|
|
|
|
typedef void (*console_locate_type)(int, int);
|
|
|
|
static const unsigned int console_locate_address[] = { _CASIO_SYSCALLS_SCA, _CASIO_SYSCALLS_SCB,_CASIO_SYSCALLS_SCE, 0x807 };
|
|
|
|
static const console_locate_type console_locate_ptr = (console_locate_type) console_locate_address;
|
|
|
|
|
|
|
|
if (!ctx->buf_strlen) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// +1 because the CASIO cursor position is 1-based
|
|
|
|
console_locate_ptr(ctx->cursor_x - ctx->buf_strlen + 1, ctx->cursor_y + 1);
|
|
|
|
Print((unsigned char*) ctx->buf);
|
|
|
|
|
|
|
|
ctx->buf[0] = '\0';
|
|
|
|
ctx->buf_strlen = 0;
|
2018-09-07 14:00:06 +02:00
|
|
|
}
|