forked from Lephenixnoir/PythonExtra
pe: cap shell refresh rate at 30 FPS
This commit is contained in:
parent
d0654fc5e7
commit
8809f3eee4
|
@ -15,7 +15,6 @@ Most of the code is in `ports/sh` and is shared between the platforms.
|
|||
**TODO list**
|
||||
|
||||
Bugs to fix:
|
||||
- Don't refresh screen at every low-level console print
|
||||
- Fix not world switching during filesystem accesses (very unstable)
|
||||
|
||||
Python features:
|
||||
|
@ -25,6 +24,8 @@ Python features:
|
|||
- Interrupt with AC/ON
|
||||
|
||||
UI:
|
||||
- Shell escapes: move cursor, history
|
||||
- Better input system in the shell
|
||||
- Use [JustUI](/Lephenixnoir/JustUI) to get a file browser (already available)
|
||||
- Add an option for fixed-width font which also sets $COLUMNS properly so that
|
||||
MicroPython paginates (requires better getenv/setenv support in fxlib)
|
||||
|
|
|
@ -15,6 +15,7 @@ SRC_C = \
|
|||
ports/sh/keymap.c \
|
||||
ports/sh/modgint.c \
|
||||
ports/sh/mphalport.c \
|
||||
ports/sh/shell.c \
|
||||
shared/readline/readline.c \
|
||||
shared/runtime/gchelper_generic.c \
|
||||
shared/runtime/pyexec.c \
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "console.h"
|
||||
#include "shell.h"
|
||||
|
||||
//=== Console-based standard streams ===//
|
||||
|
||||
|
@ -33,33 +35,15 @@ fs_descriptor_type_t stdouterr_type = {
|
|||
|
||||
//=== Main function ===//
|
||||
|
||||
static console_t *cons = NULL;
|
||||
|
||||
void pe_draw(void)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
#ifdef FX9860G
|
||||
int rows = 8;
|
||||
console_render(1, 1, cons, DWIDTH-2, rows);
|
||||
#else
|
||||
dprint(3, 3, C_BLACK, "PythonExtra, very much WIP :)");
|
||||
dline(2, 16, DWIDTH-3, 16, C_BLACK);
|
||||
int rows = 12;
|
||||
console_render(3, 20, cons, DWIDTH-6, rows);
|
||||
int y = 20 + PE_CONSOLE_LINE_SPACING * rows;
|
||||
dline(2, y, DWIDTH-3, y, C_BLACK);
|
||||
#endif
|
||||
dupdate();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pe_shell_init();
|
||||
|
||||
/* Set up standard streams */
|
||||
cons = console_create(8192);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
open_generic(&stdouterr_type, cons, STDOUT_FILENO);
|
||||
open_generic(&stdouterr_type, cons, STDERR_FILENO);
|
||||
open_generic(&stdouterr_type, pe_shell_console, STDOUT_FILENO);
|
||||
open_generic(&stdouterr_type, pe_shell_console, STDERR_FILENO);
|
||||
|
||||
/* Initialize MicroPython */
|
||||
#define HEAP_SIZE 32768
|
||||
|
@ -86,11 +70,10 @@ int main(int argc, char **argv)
|
|||
// Start a normal REPL; will exit when ctrl-D is entered on a blank line.
|
||||
pyexec_friendly_repl();
|
||||
|
||||
console_destroy(cons);
|
||||
|
||||
// Deinitialise the runtime.
|
||||
gc_sweep_all();
|
||||
mp_deinit();
|
||||
pe_shell_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "py/objtuple.h"
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include "shell.h"
|
||||
|
||||
#define FUN_0(NAME) \
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(modgint_ ## NAME ## _obj, modgint_ ## NAME)
|
||||
|
@ -121,6 +122,7 @@ STATIC mp_obj_t modgint_dclear(mp_obj_t arg1)
|
|||
|
||||
STATIC mp_obj_t modgint_dupdate(void)
|
||||
{
|
||||
pe_shell_graphics_mode();
|
||||
dupdate();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#include "../../shared/readline/readline.h"
|
||||
|
||||
#include "keymap.h"
|
||||
#include "shell.h"
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
|
||||
// Receive single character, blocking until one is available.
|
||||
int mp_hal_stdin_rx_chr(void) {
|
||||
int mp_hal_stdin_rx_chr(void)
|
||||
{
|
||||
while(1) {
|
||||
key_event_t ev = getkey();
|
||||
int key = ev.key;
|
||||
|
@ -44,10 +46,10 @@ int mp_hal_stdin_rx_chr(void) {
|
|||
}
|
||||
|
||||
// Send the string of given length.
|
||||
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
|
||||
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len)
|
||||
{
|
||||
int r = write(STDOUT_FILENO, str, len);
|
||||
(void)r;
|
||||
|
||||
extern void pe_draw(void);
|
||||
pe_draw();
|
||||
pe_shell_schedule_update();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#include "shell.h"
|
||||
#include <gint/timer.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
/* The global terminal. */
|
||||
console_t *pe_shell_console;
|
||||
/* Timer handle for the refresh clock. */
|
||||
static int pe_shell_timer = -1;
|
||||
/* Whether there is new shell data to be shown on the next frame. */
|
||||
static bool pe_shell_update = true;
|
||||
|
||||
static void pe_shell_draw(void)
|
||||
{
|
||||
dclear(C_WHITE);
|
||||
|
||||
#ifdef FX9860G
|
||||
int rows = 8;
|
||||
console_render(1, 1, pe_shell_console, DWIDTH-2, rows);
|
||||
#else
|
||||
dprint(3, 3, C_BLACK, "PythonExtra, very much WIP :)");
|
||||
dline(2, 16, DWIDTH-3, 16, C_BLACK);
|
||||
int rows = 12;
|
||||
console_render(3, 20, pe_shell_console, DWIDTH-6, rows);
|
||||
int y = 20 + PE_CONSOLE_LINE_SPACING * rows;
|
||||
dline(2, y, DWIDTH-3, y, C_BLACK);
|
||||
#endif
|
||||
|
||||
dupdate();
|
||||
}
|
||||
|
||||
static int pe_shell_timer_handler(void)
|
||||
{
|
||||
if(pe_shell_update) {
|
||||
pe_shell_draw();
|
||||
pe_shell_update = false;
|
||||
}
|
||||
return TIMER_CONTINUE;
|
||||
}
|
||||
|
||||
void pe_shell_schedule_update(void)
|
||||
{
|
||||
pe_shell_update = true;
|
||||
}
|
||||
|
||||
void pe_shell_graphics_mode(void)
|
||||
{
|
||||
pe_shell_update = false;
|
||||
}
|
||||
|
||||
void pe_shell_init(void)
|
||||
{
|
||||
pe_shell_console = console_create(8192);
|
||||
|
||||
pe_shell_timer = timer_configure(TIMER_ANY, 1000000 / PE_SHELL_FPS,
|
||||
GINT_CALL(pe_shell_timer_handler));
|
||||
timer_start(pe_shell_timer);
|
||||
}
|
||||
|
||||
void pe_shell_deinit(void)
|
||||
{
|
||||
timer_stop(pe_shell_timer);
|
||||
console_destroy(pe_shell_console);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// pe.shell: Shell integration
|
||||
//
|
||||
// This header covers application-integration aspects of the shell. For the
|
||||
// implementation of the console itself (input, escape sequences, etc). see
|
||||
// <console.h> instead.
|
||||
//
|
||||
// The shell consists of a terminal-emulating `console_t` along with some input
|
||||
// UI. During execution, the shell is redrawn only (1) when new data is printed
|
||||
// or requested, and (2) a fixed refresh timer hits. Condition 1 avoids
|
||||
// needless updates for non-printing programs, while condition 2 prevents
|
||||
// performance issues for sequences that print one character at a time (which
|
||||
// is quite common even within MicroPython builtins).
|
||||
//
|
||||
// If the built-in function gint.dupdate() is used, the shell also hands over
|
||||
// display updates to "graphics mode", where only manual dupdate() calls push
|
||||
// the VRAM. Switching to graphics mode cancels any scheduled shell updates.
|
||||
// Graphics mode is exited once a new shell update is explicity scheduled,
|
||||
// typically by a call to print() or input().
|
||||
//---
|
||||
|
||||
#ifndef __PYTHONEXTRA_SHELL_H
|
||||
#define __PYTHONEXTRA_SHELL_H
|
||||
|
||||
#include "console.h"
|
||||
|
||||
/* Shell frame frequency, ie. cap on the number of shell redraws per second. */
|
||||
#define PE_SHELL_FPS 30
|
||||
|
||||
/* The terminal. */
|
||||
extern console_t *pe_shell_console;
|
||||
|
||||
/* Schedule a redraw of the shell interface at the next shell frame. This is
|
||||
called whenever data is printed into the shell or input() is used. The
|
||||
scheduled redraw might be canceled by switching to graphics mode before the
|
||||
frame timer fires. */
|
||||
void pe_shell_schedule_update(void);
|
||||
|
||||
/* Switch to graphics mode. This cancels pending shell updates. */
|
||||
void pe_shell_graphics_mode(void);
|
||||
|
||||
//=== Internal functions ===//
|
||||
|
||||
void pe_shell_init(void);
|
||||
void pe_shell_deinit(void);
|
||||
|
||||
#endif /* __PYTHONEXTRA_SHELL_H */
|
Loading…
Reference in New Issue