mirror of
https://github.com/jscrane/Apple1.git
synced 2024-12-22 03:30:09 +00:00
Serial display (#11)
* extract disp from io * extract screen_disp * working * ... * working * refactor * config
This commit is contained in:
parent
c7db5b18b4
commit
05f50a18fd
28
Apple1.ino
28
Apple1.ino
@ -7,6 +7,9 @@
|
|||||||
#include <sd_filer.h>
|
#include <sd_filer.h>
|
||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "disp.h"
|
||||||
|
#include "screen_disp.h"
|
||||||
|
#include "terminal_disp.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#if defined(KRUSADER)
|
#if defined(KRUSADER)
|
||||||
@ -29,15 +32,16 @@ flash_filer files(PROGRAMS);
|
|||||||
|
|
||||||
#if defined(PS2_SERIAL_KBD)
|
#if defined(PS2_SERIAL_KBD)
|
||||||
ps2_serial_kbd kbd;
|
ps2_serial_kbd kbd;
|
||||||
|
|
||||||
#elif defined(HW_SERIAL_KBD)
|
|
||||||
hw_serial_kbd kbd(Serial);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "No keyboard defined!"
|
hw_serial_kbd kbd(Serial);
|
||||||
#endif
|
#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);
|
r6502 cpu(memory);
|
||||||
|
|
||||||
@ -46,14 +50,14 @@ void reset() {
|
|||||||
|
|
||||||
io.reset();
|
io.reset();
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
io.status("Reset failed");
|
dsp.status("Reset failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
io.start();
|
io.start();
|
||||||
#if defined(KRUSADER)
|
#if defined(KRUSADER)
|
||||||
io.status("Krusader: F000R / Basic: E000R");
|
dsp.status("Krusader: F000R / Basic: E000R");
|
||||||
#else
|
#else
|
||||||
io.status("Basic: E000R");
|
dsp.status("Basic: E000R");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,17 +70,17 @@ void function_key(uint8_t fn) {
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
filename = io.files.advance();
|
filename = io.files.advance();
|
||||||
io.status(filename);
|
dsp.status(filename);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
filename = io.files.rewind();
|
filename = io.files.rewind();
|
||||||
io.status(filename);
|
dsp.status(filename);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
io.load();
|
io.load();
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
io.status(io.files.checkpoint());
|
dsp.status(io.files.checkpoint());
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (filename)
|
if (filename)
|
||||||
|
4
Makefile
4
Makefile
@ -1,8 +1,8 @@
|
|||||||
t ?= esp32
|
t ?= esp32
|
||||||
|
|
||||||
TERMINAL_SPEED := 115200
|
TERMINAL_SPEED := 115200
|
||||||
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 -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 -DUSE_SERIAL
|
||||||
LIBRARIES = PS2KeyAdvanced PS2KeyMap
|
LIBRARIES = PS2KeyAdvanced PS2KeyMap
|
||||||
|
|
||||||
ifeq ($t, esp8266)
|
ifeq ($t, esp8266)
|
||||||
|
4
config.h
4
config.h
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// uncomment to use TFT / VGA display
|
||||||
|
// otherwise serial terminal is used
|
||||||
|
//#define SCREEN_SERIAL_DSP
|
||||||
|
|
||||||
#define FG_COLOUR GREEN
|
#define FG_COLOUR GREEN
|
||||||
#define BG_COLOUR BLACK
|
#define BG_COLOUR BLACK
|
||||||
|
|
||||||
|
12
disp.h
Normal file
12
disp.h
Normal 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
91
io.cpp
@ -4,51 +4,28 @@
|
|||||||
#include <serialio.h>
|
#include <serialio.h>
|
||||||
#include <filer.h>
|
#include <filer.h>
|
||||||
#include <serial_kbd.h>
|
#include <serial_kbd.h>
|
||||||
|
#include <serial_dsp.h>
|
||||||
#include <pia.h>
|
#include <pia.h>
|
||||||
#include <timed.h>
|
#include <timed.h>
|
||||||
|
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "disp.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
void io::reset() {
|
void io::reset() {
|
||||||
Display::begin(BG_COLOUR, FG_COLOUR, ORIENT);
|
_dsp.reset();
|
||||||
clear();
|
|
||||||
_cy += 2;
|
|
||||||
|
|
||||||
r = c = 0;
|
|
||||||
for (int j = 0; j < ROWS; j++)
|
|
||||||
for (int i = 0; i < COLS; i++)
|
|
||||||
screen[j][i] = ' ';
|
|
||||||
|
|
||||||
_kbd.reset();
|
_kbd.reset();
|
||||||
|
|
||||||
_loading = false;
|
_loading = false;
|
||||||
PIA::reset();
|
PIA::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static io *i;
|
|
||||||
|
|
||||||
const int TICK_FREQ = 2;
|
|
||||||
|
|
||||||
bool io::start() {
|
bool io::start() {
|
||||||
|
|
||||||
i = this;
|
|
||||||
timer_create(TICK_FREQ, io::on_tick);
|
|
||||||
return files.start();
|
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() {
|
void io::load() {
|
||||||
if (files.more()) {
|
if (files.more()) {
|
||||||
_loading = true;
|
_loading = true;
|
||||||
@ -62,53 +39,9 @@ void io::enter(uint8_t key) {
|
|||||||
PIA::write_ca1(true);
|
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) {
|
void io::write_portb(uint8_t b) {
|
||||||
b &= 0x7f;
|
b &= 0x7f;
|
||||||
display(b);
|
_dsp.write(b);
|
||||||
PIA::write_portb(b);
|
PIA::write_portb(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,22 +62,10 @@ uint8_t io::read_cra() {
|
|||||||
|
|
||||||
void io::checkpoint(Stream &s) {
|
void io::checkpoint(Stream &s) {
|
||||||
PIA::checkpoint(s);
|
PIA::checkpoint(s);
|
||||||
s.write(r);
|
_dsp.checkpoint(s);
|
||||||
s.write(c);
|
|
||||||
for (int j = 0; j < ROWS; j++)
|
|
||||||
for (int i = 0; i < COLS; i++)
|
|
||||||
s.write(screen[j][i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void io::restore(Stream &s) {
|
void io::restore(Stream &s) {
|
||||||
PIA::restore(s);
|
PIA::restore(s);
|
||||||
r = s.read();
|
_dsp.restore(s);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
20
io.h
20
io.h
@ -2,16 +2,16 @@
|
|||||||
#define _IO_H
|
#define _IO_H
|
||||||
|
|
||||||
class serial_kbd;
|
class serial_kbd;
|
||||||
|
class disp;
|
||||||
|
|
||||||
class io: public Memory::Device, public Display, public PIA {
|
class io: public Memory::Device, public PIA {
|
||||||
public:
|
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();
|
void reset();
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
static void on_tick();
|
|
||||||
|
|
||||||
void operator=(uint8_t b) { PIA::write(_acc, b); }
|
void operator=(uint8_t b) { PIA::write(_acc, b); }
|
||||||
operator uint8_t() { return PIA::read(_acc); }
|
operator uint8_t() { return PIA::read(_acc); }
|
||||||
|
|
||||||
@ -24,20 +24,12 @@ public:
|
|||||||
void load();
|
void load();
|
||||||
filer &files;
|
filer &files;
|
||||||
|
|
||||||
static const uint8_t ROWS = 24;
|
|
||||||
static const uint8_t COLS = 40;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
serial_kbd &_kbd;
|
serial_kbd &_kbd;
|
||||||
|
disp &_dsp;
|
||||||
|
|
||||||
void cursor(bool on);
|
|
||||||
void display(uint8_t);
|
|
||||||
void draw(char, int, int);
|
|
||||||
void enter(uint8_t);
|
void enter(uint8_t);
|
||||||
|
bool _loading;
|
||||||
bool _shift, _loading;
|
|
||||||
uint8_t r, c;
|
|
||||||
char screen[ROWS][COLS];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
106
screen_disp.cpp
Normal file
106
screen_disp.cpp
Normal 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
29
screen_disp.h
Normal 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
|
Loading…
Reference in New Issue
Block a user