From 05f50a18fd08c867c9896341e82495ed66ac6ff3 Mon Sep 17 00:00:00 2001 From: Stephen Crane Date: Thu, 29 Aug 2024 07:03:46 +0100 Subject: [PATCH] Serial display (#11) * extract disp from io * extract screen_disp * working * ... * working * refactor * config --- Apple1.ino | 28 +++++++------ Makefile | 4 +- config.h | 4 ++ disp.h | 12 ++++++ io.cpp | 91 +++-------------------------------------- io.h | 20 +++------ screen_disp.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ screen_disp.h | 29 +++++++++++++ 8 files changed, 181 insertions(+), 113 deletions(-) create mode 100644 disp.h create mode 100644 screen_disp.cpp create mode 100644 screen_disp.h diff --git a/Apple1.ino b/Apple1.ino index d83a72b..489915f 100644 --- a/Apple1.ino +++ b/Apple1.ino @@ -7,6 +7,9 @@ #include #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) diff --git a/Makefile b/Makefile index 1b3b1c2..b480bd2 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/config.h b/config.h index 2c57b7b..bbc00b4 100644 --- a/config.h +++ b/config.h @@ -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 diff --git a/disp.h b/disp.h new file mode 100644 index 0000000..f02a8b2 --- /dev/null +++ b/disp.h @@ -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 diff --git a/io.cpp b/io.cpp index 4122677..95e81aa 100644 --- a/io.cpp +++ b/io.cpp @@ -4,51 +4,28 @@ #include #include #include +#include #include #include #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); } diff --git a/io.h b/io.h index 2a7ffaf..3b82852 100644 --- a/io.h +++ b/io.h @@ -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 diff --git a/screen_disp.cpp b/screen_disp.cpp new file mode 100644 index 0000000..aff16a0 --- /dev/null +++ b/screen_disp.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/screen_disp.h b/screen_disp.h new file mode 100644 index 0000000..2a5181a --- /dev/null +++ b/screen_disp.h @@ -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