1
0
mirror of https://github.com/jscrane/r65emu.git synced 2025-01-02 13:30:53 +00:00

38 simpletimer (#39)

* SimpleTimer

* handlers

* use std::function for handlers

* ...

* add optional USE_OWN_DISPLAY
This commit is contained in:
Stephen Crane 2024-11-23 12:28:18 +00:00 committed by GitHub
parent 70d63487bc
commit 7625e1613a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 111 additions and 115 deletions

View File

@ -4,6 +4,8 @@
#include "memory.h"
#include "display.h"
#if !defined(USE_OWN_DISPLAY)
#if defined(USE_UTFT)
#pragma message "UTFT configured"
#include <UTFT.h>
@ -373,3 +375,4 @@ void Display::drawString(const char *s, unsigned x, unsigned y, colour_t c) {
dvi.print(s);
#endif
}
#endif

View File

@ -1,4 +1,5 @@
#include <Arduino.h>
#include <SimpleTimer.h>
#include <stdint.h>
#include <stddef.h>
#include "memory.h"
@ -26,6 +27,7 @@ spiram sram(SPIRAM_SIZE);
#endif
static CPU *_cpu;
static SimpleTimer timers;
bool hardware_reset() {
bool success = false;
@ -105,6 +107,8 @@ bool hardware_debug_cpu() {
bool hardware_run(unsigned instructions) {
timers.run();
#if defined(CPU_DEBUG)
if (cpu_debug) {
char buf[256];
@ -119,6 +123,14 @@ bool hardware_run(unsigned instructions) {
return !_cpu->halted();
}
int hardware_interval_timer(uint32_t interval, std::function<void(void)> cb) {
return timers.setInterval(interval, cb);
}
int hardware_oneshot_timer(uint32_t interval, std::function<void(void)> cb) {
return timers.setTimeout(interval, cb);
}
#if !defined(NO_CHECKPOINT)
void hardware_checkpoint(Stream &s) {
unsigned ds = 0;

View File

@ -11,7 +11,7 @@
#endif
#if !defined(CPU_INSTRUCTIONS)
#define CPU_INSTRUCTIONS 1000
#define CPU_INSTRUCTIONS 500
#endif
#if !defined(TERMINAL_SPEED)
@ -24,6 +24,8 @@ void hardware_checkpoint(class Stream &);
void hardware_restore(class Stream &);
bool hardware_run(unsigned instructions = CPU_INSTRUCTIONS);
bool hardware_debug_cpu();
int hardware_interval_timer(uint32_t ms, std::function<void(void)> cb);
int hardware_oneshot_timer(uint32_t ms, std::function<void(void)> cb);
#if defined(__SPIRAM_H__) && defined(USE_SPIRAM)
extern class spiram sram;

View File

@ -26,6 +26,7 @@
// Display
// https://cdn-learn.adafruit.com/downloads/pdf/picodvi-arduino-library-video-out-for-rp2040-boards.pdf
#if !defined(USE_OWN_DISPLAY)
#define USE_DVI
#define DVI_CONFIG adafruit_feather_dvi_cfg
@ -52,6 +53,7 @@
#if !defined(DVI_DEFAULT_FONT)
#define DVI_DEFAULT_FONT 0
#endif
#endif
// 64kB RAM
#define RAM_SIZE 0x10000u

View File

@ -1,6 +1,7 @@
#define RAM_SIZE 0x10000u
// TFT display...
#if !defined(USE_OWN_DISPLAY)
#define USE_ESPI
// must be configured in uC-Makefile, or platformio, or TFT_eSPI's User_Setup.h
//#define USER_SETUP_LOADED
@ -26,6 +27,7 @@
//#define TFT_WR 33
//#define TFT_CS 27
//#define TFT_RST 26
#endif
// PS/2 keyboard
#if !defined(USE_OWN_KBD)

View File

@ -4,6 +4,7 @@
#define RAM_SIZE 0x8000u
// TFT display...
#if !defined(USE_OWN_DISPLAY)
#define USE_ESPI
//must define these in Makefile (or platformio)
//#define USER_SETUP_LOADED
@ -19,6 +20,7 @@
#if !defined(ESPI_DEFAULT_FONT)
#define ESPI_DEFAULT_FONT 0
#endif
#endif
// PS/2 keyboard
#if !defined(USE_OWN_KBD)

View File

@ -30,6 +30,7 @@
// TFT display...
// NOTE: edit memorysaver.h to select the correct chip for your display!
// Daniel Rebollo's boosterpack
#if !defined(USE_OWN_DISPLAY)
#define USE_UTFT
#define TFT_BACKLIGHT PD_6
#define TFT_MODEL SSD1289
@ -37,4 +38,4 @@
#define TFT_WR PC_5
#define TFT_CS PC_7
#define TFT_RST PC_4
#endif

View File

@ -2,6 +2,7 @@
// https://www.tinytronics.nl/shop/en/development-boards/microcontroller-boards/with-wi-fi/lilygo-ttgo-vga32-esp32
// Display
#if !defined(USE_OWN_DISPLAY)
#define USE_VGA
#if !defined(VGA_RESOLUTION)
#define VGA_RESOLUTION VGA_480x300_75Hz
@ -10,6 +11,7 @@
#if !defined(VGA_DEFAULT_FONT)
#define VGA_DEFAULT_FONT &fabgl::FONT_6x10
#endif
#endif
// PS/2 Keyboard
#if !defined(USE_OWN_KBD)

View File

@ -100,6 +100,22 @@ void PIA::restore(Stream &s) {
ca2 = s.read();
}
void PIA::write_porta(uint8_t b) {
outa = b;
if (porta_write_handler)
porta_write_handler(b);
}
void PIA::write_portb(uint8_t b) {
outb = b;
if (portb_write_handler)
portb_write_handler(b);
}
void PIA::write_ca1(bool state) {
if (ca1 == state)
@ -169,11 +185,19 @@ uint8_t PIA::read_crb() {
}
uint8_t PIA::read_porta() {
if (porta_read_handler)
ina = porta_read_handler();
irq_a1 = irq_a2 = false;
return (ina & ~ddra) | (outa & ddra);
}
uint8_t PIA::read_portb() {
if (portb_read_handler)
inb = portb_read_handler();
irq_b1 = irq_b2 = false;
return (inb & ~ddrb) | (outb & ddrb);
}

View File

@ -1,5 +1,4 @@
#ifndef __PIA_H__
#define __PIA_H__
#pragma once
// Motorola 6820 / 6821 PIA
// https://en.wikipedia.org/wiki/Peripheral_Interface_Adapter
@ -34,26 +33,49 @@ public:
static const uint8_t IRQ1 = 0x80;
static const uint8_t IRQ2 = 0x40;
protected:
// overrideable device memory interface
virtual uint8_t read_ddra() { return ddra; }
virtual uint8_t read_porta();
virtual uint8_t read_cra();
virtual uint8_t read_ddrb() { return ddrb; }
virtual uint8_t read_portb();
virtual uint8_t read_crb();
void register_porta_write_handler(std::function<void(uint8_t)> fn) {
porta_write_handler = fn;
}
virtual void write_ddra(uint8_t b) { ddra = b; }
virtual void write_porta(uint8_t b) { outa = b; }
virtual void write_cra(uint8_t b) { cra = (b & 0x3f); }
virtual void write_ddrb(uint8_t b) { ddrb = b; }
virtual void write_portb(uint8_t b) { outb = b; }
virtual void write_crb(uint8_t b) { crb = (b & 0x3f); }
void register_portb_write_handler(std::function<void(uint8_t)> fn) {
portb_write_handler = fn;
}
void register_porta_read_handler(std::function<uint8_t(void)> fn) {
porta_read_handler = fn;
}
void register_portb_read_handler(std::function<uint8_t(void)> fn) {
portb_read_handler = fn;
}
protected:
// FIXME: overrideable device memory interface
// should be non-virtual and private
virtual uint8_t read_porta();
virtual uint8_t read_portb();
virtual void write_portb(uint8_t b);
private:
void write_ddra(uint8_t b) { ddra = b; }
void write_ddrb(uint8_t b) { ddrb = b; }
uint8_t read_ddra() { return ddra; }
uint8_t read_ddrb() { return ddrb; }
void write_cra(uint8_t b) { cra = (b & 0x3f); }
void write_crb(uint8_t b) { crb = (b & 0x3f); }
uint8_t read_cra();
uint8_t read_crb();
void write_porta(uint8_t b);
std::function<void(uint8_t)> porta_write_handler;
std::function<void(uint8_t)> portb_write_handler;
std::function<uint8_t(void)> porta_read_handler;
std::function<uint8_t(void)> portb_read_handler;
uint8_t cra, ina, outa, ddra;
uint8_t crb, inb, outb, ddrb;
bool ca1, ca2, irq_a1, irq_a2;
bool cb1, cb2, irq_b1, irq_b2;
};
#endif

View File

@ -1,4 +1,4 @@
#include <stdint.h>
#include <Arduino.h>
#include "hardware.h"
#if defined(USE_PS2_KBD)

View File

@ -1,5 +1,4 @@
#if !defined(__PS2_KBD_H__)
#define __PS2_KBD_H__
#pragma once
class matrix_keyboard {
public:
@ -12,13 +11,11 @@ inline bool is_ps2_shift(uint16_t scan) { return scan == 0x12 || scan == 0x59; }
inline bool is_ps2_ctrl(uint16_t scan) { return scan == 0x14; }
typedef void (*fnkey_handler)(uint8_t);
class ps2_raw_kbd {
public:
ps2_raw_kbd(matrix_keyboard &m): _m(m) {}
void register_fnkey_handler(fnkey_handler f) { _f = f; }
void register_fnkey_handler(std::function<void(uint8_t)> f) { _f = f; }
void poll();
void reset();
@ -29,8 +26,6 @@ private:
uint16_t read();
bool available();
fnkey_handler _f;
std::function<void(uint8_t)> _f;
matrix_keyboard &_m;
};
#endif

View File

@ -12,7 +12,6 @@
#include "flash_filer.h"
#include "serial_filer.h"
#include "socket_filer.h"
#include "timed.h"
#include "hardware.h"
#include "sound_dac.h"
#include "ps2_raw_kbd.h"

View File

@ -1,20 +1,15 @@
#if !defined(__SERIAL_KBD_H__)
#define __SERIAL_KBD_H__
typedef void (*fnkey_handler)(uint8_t);
#pragma once
class serial_kbd {
public:
virtual int read() = 0;
virtual bool available() = 0;
virtual void reset() {}
virtual void register_fnkey_handler(fnkey_handler f) { _f = f; }
virtual void register_fnkey_handler(std::function<void(uint8_t)> f) { _f = f; }
protected:
void fnkey(uint8_t k) { if (_f) _f(k); }
private:
fnkey_handler _f;
std::function<void(uint8_t)> _f;
};
#endif

View File

@ -1,6 +1,8 @@
// FIXME: does this really belong in the core library?
// it only works on esp32 and is only used by invaders
#include <Arduino.h>
#include <hardware.h>
#include "timed.h"
#include "sound_dac.h"
#if defined(DAC_SOUND) && defined(ESP_PLATFORM)
@ -15,6 +17,15 @@ void IRAM_ATTR timer_callback() {
s->on_tick();
}
typedef void (*handler_t)(void);
static void timer_create(unsigned freq, handler_t handler) {
hw_timer_t *timer = timerBegin(3, 80, true); // prescaler of 80
timerAttachInterrupt(timer, handler, true);
timerAlarmWrite(timer, 1000000 / freq, true);
timerAlarmEnable(timer);
}
void IRAM_ATTR DAC::on_tick() {
portENTER_CRITICAL_ISR(&mux);

View File

@ -1,3 +1,4 @@
#include <Arduino.h>
#include "hardware.h"
#if defined(USE_SPIRAM)

View File

@ -1,65 +0,0 @@
#include <Arduino.h>
#if defined(__LM4F120H5QR__)
#include <inc/hw_ints.h>
#include <driverlib/interrupt.h>
#include <driverlib/sysctl.h>
#include <driverlib/timer.h>
#elif defined(ESP8266)
#include <ets_sys.h>
#include <osapi.h>
#include <os_type.h>
#endif
#include "timed.h"
#if defined(__LM4F120H5QR__)
static handler_t client_handler;
static void timer0isr(void) {
ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
client_handler();
}
void timer_create(unsigned freq, handler_t handler) {
client_handler = handler;
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
TimerIntRegister(TIMER0_BASE, TIMER_A, timer0isr);
ROM_TimerEnable(TIMER0_BASE, TIMER_A);
ROM_IntEnable(INT_TIMER0A);
ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
ROM_TimerLoadSet(TIMER0_BASE, TIMER_A, ROM_SysCtlClockGet() / freq);
}
#elif defined(ESP_PLATFORM)
void timer_create(unsigned freq, handler_t handler) {
hw_timer_t *timer = timerBegin(3, 80, true); // prescaler of 80
timerAttachInterrupt(timer, handler, true);
timerAlarmWrite(timer, 1000000 / freq, true);
timerAlarmEnable(timer);
}
#elif defined(ESP8266)
void timer_create(unsigned freq, handler_t handler) {
static os_timer_t t;
os_timer_setfn(&t, (os_timer_func_t *)handler, 0);
os_timer_arm(&t, 1000 / freq, true);
}
#elif defined(ARDUINO_ARCH_rp2040)
static handler_t client_handler;
static int64_t period;
int64_t alarm_callback(alarm_id_t, void *) {
client_handler();
return -period;
}
void timer_create(unsigned freq, handler_t handler) {
period = 1000000 / freq;
client_handler = handler;
add_alarm_in_us(period, alarm_callback, 0, false);
}
#endif

View File

@ -1,12 +0,0 @@
#ifndef __TIMED_H__
#define __TIMED_H__
typedef void (*handler_t)(void);
void timer_create(unsigned freq, handler_t handler);
#if !defined(ESP32) && !defined(ESP8266)
#define IRAM_ATTR
#endif
#endif