Serial display (#11)

* extract disp from io

* extract screen_disp

* working

* ...

* working

* refactor

* config
This commit is contained in:
Stephen Crane 2024-08-29 07:03:46 +01:00 committed by GitHub
parent c7db5b18b4
commit 05f50a18fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 181 additions and 113 deletions

View File

@ -7,6 +7,9 @@
#include <sd_filer.h>
#include "io.h"
#include "disp.h"
#include "screen_disp.h"
#include "terminal_disp.h"
#include "config.h"
#if defined(KRUSADER)
@ -29,15 +32,16 @@ flash_filer files(PROGRAMS);
#if defined(PS2_SERIAL_KBD)
ps2_serial_kbd kbd;
#elif defined(HW_SERIAL_KBD)
hw_serial_kbd kbd(Serial);
#else
#error "No keyboard defined!"
hw_serial_kbd kbd(Serial);
#endif
io io(files, kbd);
#if defined(SCREEN_SERIAL_DSP)
screen_disp dsp;
#else
terminal_disp dsp(Serial);
#endif
io io(files, kbd, dsp);
r6502 cpu(memory);
@ -46,14 +50,14 @@ void reset() {
io.reset();
if (!ok) {
io.status("Reset failed");
dsp.status("Reset failed");
return;
}
io.start();
#if defined(KRUSADER)
io.status("Krusader: F000R / Basic: E000R");
dsp.status("Krusader: F000R / Basic: E000R");
#else
io.status("Basic: E000R");
dsp.status("Basic: E000R");
#endif
}
@ -66,17 +70,17 @@ void function_key(uint8_t fn) {
break;
case 2:
filename = io.files.advance();
io.status(filename);
dsp.status(filename);
break;
case 3:
filename = io.files.rewind();
io.status(filename);
dsp.status(filename);
break;
case 4:
io.load();
break;
case 6:
io.status(io.files.checkpoint());
dsp.status(io.files.checkpoint());
break;
case 7:
if (filename)

View File

@ -1,8 +1,8 @@
t ?= esp32
TERMINAL_SPEED := 115200
CPPFLAGS = -DDEBUGGING -DCPU_DEBUG=false -DTERMINAL_SPEED=$(TERMINAL_SPEED) -DUSE_OWN_KBD -DPS2_SERIAL_KBD=\"UK\"
#CPPFLAGS = -DDEBUGGING -DCPU_DEBUG -DTERMINAL_SPEED=$(TERMINAL_SPEED) -DUSE_OWN_KBD -DHW_SERIAL_KBD
#CPPFLAGS = -DDEBUGGING -DCPU_DEBUG=false -DTERMINAL_SPEED=$(TERMINAL_SPEED) -DUSE_OWN_KBD -DPS2_SERIAL_KBD=\"UK\"
CPPFLAGS = -DDEBUGGING -DCPU_DEBUG=false -DTERMINAL_SPEED=$(TERMINAL_SPEED) -DUSE_OWN_KBD -DUSE_SERIAL
LIBRARIES = PS2KeyAdvanced PS2KeyMap
ifeq ($t, esp8266)

View File

@ -16,6 +16,10 @@
#endif
// uncomment to use TFT / VGA display
// otherwise serial terminal is used
//#define SCREEN_SERIAL_DSP
#define FG_COLOUR GREEN
#define BG_COLOUR BLACK

12
disp.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _DISP_H
#define _DISP_H
class disp: public serial_dsp {
public:
virtual void checkpoint(Stream &) =0;
virtual void restore(Stream &) =0;
virtual void status(const char *) =0;
};
#endif

91
io.cpp
View File

@ -4,51 +4,28 @@
#include <serialio.h>
#include <filer.h>
#include <serial_kbd.h>
#include <serial_dsp.h>
#include <pia.h>
#include <timed.h>
#include "io.h"
#include "disp.h"
#include "hardware.h"
#include "config.h"
void io::reset() {
Display::begin(BG_COLOUR, FG_COLOUR, ORIENT);
clear();
_cy += 2;
r = c = 0;
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++)
screen[j][i] = ' ';
_dsp.reset();
_kbd.reset();
_loading = false;
PIA::reset();
}
static io *i;
const int TICK_FREQ = 2;
bool io::start() {
i = this;
timer_create(TICK_FREQ, io::on_tick);
return files.start();
}
void IRAM_ATTR io::on_tick() {
static int tick = 0;
tick = ++tick % 3;
i->cursor(tick < 2);
}
void io::cursor(bool on) {
draw(on? '_': ' ', c, r);
}
void io::load() {
if (files.more()) {
_loading = true;
@ -62,53 +39,9 @@ void io::enter(uint8_t key) {
PIA::write_ca1(true);
}
void io::draw(char ch, int i, int j) {
if (screen[j][i] != ch) {
screen[j][i] = ch;
char c[2] = { ch, 0 };
drawString(c, i*_cx, j*_cy);
}
}
void io::display(uint8_t b) {
char ch = (char)b;
switch(ch) {
case 0x5f:
draw(' ', c, r);
if (c-- == 0) {
r--;
c = COLS-1;
}
break;
case 0x0d:
draw(' ', c, r);
c = 0;
r++;
break;
default:
if (ch >= 0x20 && ch < 0x7f) {
draw(ch, c, r);
if (++c == COLS) {
c = 0;
r++;
}
}
}
if (r == ROWS) {
// scroll
r--;
for (int j = 0; j < (ROWS-1); j++)
for (int i = 0; i < COLS; i++)
draw(screen[j+1][i], i, j);
for (int i = 0; i < COLS; i++)
draw(' ', i, ROWS-1);
}
draw('_', c, r);
}
void io::write_portb(uint8_t b) {
b &= 0x7f;
display(b);
_dsp.write(b);
PIA::write_portb(b);
}
@ -129,22 +62,10 @@ uint8_t io::read_cra() {
void io::checkpoint(Stream &s) {
PIA::checkpoint(s);
s.write(r);
s.write(c);
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++)
s.write(screen[j][i]);
_dsp.checkpoint(s);
}
void io::restore(Stream &s) {
PIA::restore(s);
r = s.read();
c = s.read();
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++) {
char c = s.read();
screen[j][i] = c;
draw(c, i, j);
}
draw('_', c, r);
_dsp.restore(s);
}

20
io.h
View File

@ -2,16 +2,16 @@
#define _IO_H
class serial_kbd;
class disp;
class io: public Memory::Device, public Display, public PIA {
class io: public Memory::Device, public PIA {
public:
io(filer &files, serial_kbd &kbd): Memory::Device(Memory::page_size), files(files), _kbd(kbd) {}
io(filer &files, serial_kbd &kbd, disp &dsp):
Memory::Device(Memory::page_size), files(files), _kbd(kbd), _dsp(dsp) {}
void reset();
bool start();
static void on_tick();
void operator=(uint8_t b) { PIA::write(_acc, b); }
operator uint8_t() { return PIA::read(_acc); }
@ -24,20 +24,12 @@ public:
void load();
filer &files;
static const uint8_t ROWS = 24;
static const uint8_t COLS = 40;
private:
serial_kbd &_kbd;
disp &_dsp;
void cursor(bool on);
void display(uint8_t);
void draw(char, int, int);
void enter(uint8_t);
bool _shift, _loading;
uint8_t r, c;
char screen[ROWS][COLS];
bool _loading;
};
#endif

106
screen_disp.cpp Normal file
View File

@ -0,0 +1,106 @@
#include <Arduino.h>
#include <memory.h>
#include <display.h>
#include <serial_dsp.h>
#include <timed.h>
#include <hardware.h>
#include "disp.h"
#include "screen_disp.h"
#include "config.h"
static screen_disp *i;
const int TICK_FREQ = 2;
void IRAM_ATTR screen_disp::on_tick() {
static int tick = 0;
tick = ++tick % 3;
i->cursor(tick < 2);
}
void screen_disp::reset() {
if (!i) {
i = this;
timer_create(TICK_FREQ, on_tick);
}
Display::begin(BG_COLOUR, FG_COLOUR, ORIENT);
Display::clear();
_cy += 2;
r = c = 0;
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++)
screen[j][i] = ' ';
}
void screen_disp::cursor(bool on) {
draw(on? '_': ' ', c, r);
}
void screen_disp::draw(char ch, int i, int j) {
if (screen[j][i] != ch) {
screen[j][i] = ch;
char c[2] = { ch, 0 };
drawString(c, i*_cx, j*_cy);
}
}
void screen_disp::write(uint8_t b) {
char ch = (char)b;
switch(ch) {
case '_':
draw(' ', c, r);
if (c-- == 0) {
r--;
c = COLS-1;
}
break;
case 0x0d:
draw(' ', c, r);
c = 0;
r++;
break;
default:
if (ch >= 0x20 && ch < 0x7f) {
draw(ch, c, r);
if (++c == COLS) {
c = 0;
r++;
}
}
}
if (r == ROWS) {
// scroll
r--;
for (int j = 0; j < (ROWS-1); j++)
for (int i = 0; i < COLS; i++)
draw(screen[j+1][i], i, j);
for (int i = 0; i < COLS; i++)
draw(' ', i, ROWS-1);
}
draw('_', c, r);
}
void screen_disp::checkpoint(Stream &s) {
s.write(r);
s.write(c);
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++)
s.write(screen[j][i]);
}
void screen_disp::restore(Stream &s) {
r = s.read();
c = s.read();
for (int j = 0; j < ROWS; j++)
for (int i = 0; i < COLS; i++) {
char c = s.read();
screen[j][i] = c;
draw(c, i, j);
}
draw('_', c, r);
}

29
screen_disp.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __SCREEN_DISP_H__
#define __SCREEN_DISP_H__
class screen_disp: public Display, public disp {
public:
void reset();
void checkpoint(Stream &);
void restore(Stream &);
void write(uint8_t);
void status(const char *s) { Display::status(s); }
protected:
static void on_tick();
void cursor(bool on);
private:
void draw(char, int, int);
static const uint8_t ROWS = 24;
static const uint8_t COLS = 40;
uint8_t r, c;
char screen[ROWS][COLS];
};
#endif