mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
hp9825: printer output on a screen added, cassette status added (#9230)
This commit is contained in:
parent
3637f4bc4d
commit
8da1c53966
@ -47,6 +47,7 @@
|
||||
#include "bus/hp9845_io/hp9845_io.h"
|
||||
#include "imagedev/bitbngr.h"
|
||||
#include "speaker.h"
|
||||
#include "screen.h"
|
||||
#include "sound/beep.h"
|
||||
#include "hp9825.lh"
|
||||
#include "softlist_dev.h"
|
||||
@ -54,6 +55,8 @@
|
||||
// Debugging
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
#define LOG_DBG_MASK (LOG_GENERAL << 1)
|
||||
#define LOG_DBG(...) LOGMASKED(LOG_DBG_MASK, __VA_ARGS__)
|
||||
|
||||
// CPU clock (generated by a trimmered RC oscillator)
|
||||
constexpr unsigned MAIN_CLOCK = 6000000;
|
||||
@ -71,6 +74,25 @@ constexpr uint8_t IO_SLOT_LAST_PA = 15;
|
||||
// This value is semi-guessed.
|
||||
constexpr unsigned KDP_CLOCKS_PER_LINE = 50000;
|
||||
|
||||
// Printer constants
|
||||
constexpr unsigned PRINT_MATRIX_H = 7;
|
||||
constexpr unsigned PRINT_EMPTY_TOP = 1;
|
||||
constexpr unsigned PRINT_EMPTY_BOT = 2;
|
||||
constexpr unsigned PRINT_CELL_H = PRINT_MATRIX_H + PRINT_EMPTY_TOP + PRINT_EMPTY_BOT;
|
||||
constexpr unsigned PRINT_MATRIX_W = 5;
|
||||
constexpr unsigned PRINT_EMPTY_R = 2;
|
||||
constexpr unsigned PRINT_CELL_W = PRINT_MATRIX_W + PRINT_EMPTY_R;
|
||||
constexpr unsigned PRINT_COLUMNS = 16;
|
||||
constexpr unsigned PRINT_PIXELS_ROW = PRINT_COLUMNS * PRINT_CELL_W - PRINT_EMPTY_R;
|
||||
constexpr unsigned PRINT_WIN_ROWS = 6;
|
||||
constexpr unsigned PRINT_WINDOWS = 4;
|
||||
constexpr unsigned PRINT_WIN_H = PRINT_WIN_ROWS * PRINT_CELL_H;
|
||||
constexpr unsigned PRINT_WIN_W = PRINT_PIXELS_ROW;
|
||||
constexpr unsigned PRINT_OUT_H = PRINT_WIN_H * PRINT_WINDOWS;
|
||||
constexpr unsigned PRINT_OUT_W = PRINT_PIXELS_ROW;
|
||||
constexpr uint32_t PRINT_BG = 0xffffff; // White
|
||||
constexpr uint32_t PRINT_FG = 0x2d1881; // Blue-violet
|
||||
|
||||
// Beeper constants
|
||||
// Values come from R/C values on schematics
|
||||
constexpr unsigned BEEPER_FREQ = 1400;
|
||||
@ -109,22 +131,29 @@ public:
|
||||
, m_tape(*this , "tape")
|
||||
, m_io_key(*this , "KEY%u" , 0)
|
||||
, m_shift_key(*this , "KEY_SHIFT")
|
||||
, m_scroll_key(*this , "KEY_SCROLL")
|
||||
, m_prt_alpha_out(*this , "prt_alpha")
|
||||
, m_prt_graph_out(*this , "prt_graph")
|
||||
, m_prt_timer(*this , "prt_timer")
|
||||
, m_beeper(*this , "beeper")
|
||||
, m_beep_timer(*this , "beep_timer")
|
||||
, m_io_slot(*this, "slot%u", 0U)
|
||||
, m_prt_out(*this, "printer")
|
||||
, m_display(*this , "char_%u_%u" , 0U , 0U)
|
||||
, m_run_light(*this , "run_light")
|
||||
, m_shift_lock(*this , "shift_lock")
|
||||
, m_tape_led(*this , "tape_led")
|
||||
, m_cassette(*this , "cassette")
|
||||
, m_printer_bitmap(PRINT_OUT_W , PRINT_OUT_H)
|
||||
{
|
||||
}
|
||||
|
||||
void hp9825_base(machine_config &config);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(kb_changed);
|
||||
DECLARE_INPUT_CHANGED_MEMBER(scroll_changed);
|
||||
|
||||
uint32_t printer_out_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
@ -140,16 +169,19 @@ private:
|
||||
required_device<hp9825_tape_device> m_tape;
|
||||
required_ioport_array<4> m_io_key;
|
||||
required_ioport m_shift_key;
|
||||
required_ioport m_scroll_key;
|
||||
required_device<bitbanger_device> m_prt_alpha_out;
|
||||
required_device<bitbanger_device> m_prt_graph_out;
|
||||
required_device<timer_device> m_prt_timer;
|
||||
required_device<beep_device> m_beeper;
|
||||
required_device<timer_device> m_beep_timer;
|
||||
required_device_array<hp9845_io_slot_device , 3> m_io_slot;
|
||||
required_device<screen_device> m_prt_out;
|
||||
output_finder<32 , 7> m_display;
|
||||
output_finder<> m_run_light;
|
||||
output_finder<> m_shift_lock;
|
||||
output_finder<> m_tape_led;
|
||||
output_finder<> m_cassette;
|
||||
|
||||
bool m_display_on;
|
||||
uint8_t m_display_mem[ 32 ];
|
||||
@ -162,9 +194,11 @@ private:
|
||||
bool m_autorepeating;
|
||||
unsigned m_autorepeat_cnt;
|
||||
// Printer
|
||||
uint8_t m_printer_mem[ 16 ];
|
||||
uint8_t m_printer_mem[ PRINT_COLUMNS ];
|
||||
uint8_t m_printer_idx;
|
||||
unsigned m_printer_line; // 0: printer idle, 1..10: line being printed
|
||||
bitmap_rgb32 m_printer_bitmap;
|
||||
unsigned m_printer_window; // 0 is bottom window (the one closer to printhead)
|
||||
// SC of slots
|
||||
int m_slot_sc[ 3 ];
|
||||
|
||||
@ -198,6 +232,10 @@ void hp9825_state::machine_start()
|
||||
m_run_light.resolve();
|
||||
m_shift_lock.resolve();
|
||||
m_tape_led.resolve();
|
||||
m_cassette.resolve();
|
||||
|
||||
m_printer_bitmap.fill(PRINT_BG);
|
||||
m_printer_window = 0;
|
||||
|
||||
save_item(NAME(m_display_on));
|
||||
save_item(NAME(m_display_mem));
|
||||
@ -345,7 +383,7 @@ void hp9825_state::kdp_control_w(uint16_t data)
|
||||
void hp9825_state::printer_w(uint16_t data)
|
||||
{
|
||||
m_printer_mem[ m_printer_idx ] = uint8_t(data);
|
||||
m_printer_idx = (m_printer_idx + 1) & 0xf;
|
||||
m_printer_idx = (m_printer_idx + 1) % PRINT_COLUMNS;
|
||||
}
|
||||
|
||||
// The character generator was reverse engineered from images of printer & display test patterns.
|
||||
@ -596,6 +634,26 @@ INPUT_CHANGED_MEMBER(hp9825_state::kb_changed)
|
||||
}
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(hp9825_state::scroll_changed)
|
||||
{
|
||||
LOG_DBG("scroll p=%d n=%d\n" , param , newval);
|
||||
switch (param) {
|
||||
case 0:
|
||||
// Scroll up
|
||||
if (newval && m_printer_window > 0) {
|
||||
m_printer_window--;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Scroll down
|
||||
if (newval && m_printer_window < (PRINT_WINDOWS - 1)) {
|
||||
m_printer_window++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hp9825_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx)
|
||||
{
|
||||
while (pressed) {
|
||||
@ -612,16 +670,31 @@ void hp9825_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , uns
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::prt_timer)
|
||||
{
|
||||
if (m_printer_line == 1 || m_printer_line == 9 || m_printer_line == 10) {
|
||||
// Shift printer bitmap one line up and clear bottom line
|
||||
{
|
||||
bitmap_rgb32 tmp{ m_printer_bitmap.width() , m_printer_bitmap.height() };
|
||||
s32 scroll = -1;
|
||||
rectangle cliprect{ 0 , m_printer_bitmap.width() - 1 , 0 , m_printer_bitmap.height() - 2 };
|
||||
copyscrollbitmap(tmp , m_printer_bitmap , 0 , nullptr , 1 , &scroll , cliprect);
|
||||
copybitmap(m_printer_bitmap , tmp , 0 , 0 , 0 , 0 , cliprect);
|
||||
m_printer_bitmap.plot_box(0 , m_printer_bitmap.height() - 1 , m_printer_bitmap.width() , 1 , PRINT_BG);
|
||||
}
|
||||
|
||||
if ((m_printer_line > 0 && m_printer_line <= PRINT_EMPTY_TOP) ||
|
||||
(m_printer_line > (PRINT_EMPTY_TOP + PRINT_MATRIX_H) && m_printer_line <= PRINT_CELL_H)) {
|
||||
// Empty lines
|
||||
for (unsigned i = 0; i < 110; i++) {
|
||||
for (unsigned i = 0; i < PRINT_PIXELS_ROW; i++) {
|
||||
m_prt_graph_out->output(' ');
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < 16; i++) {
|
||||
for (unsigned col = 0; col < 5; col++) {
|
||||
for (unsigned i = 0; i < PRINT_COLUMNS; i++) {
|
||||
for (unsigned col = 0; col < PRINT_MATRIX_W; col++) {
|
||||
uint8_t pixels = chargen[ m_printer_mem[ i ] & 0x7f ][ col ];
|
||||
m_prt_graph_out->output(BIT(pixels , m_printer_line - 2) ? '*' : ' ');
|
||||
bool pixel = BIT(pixels , m_printer_line - PRINT_EMPTY_TOP - 1);
|
||||
m_prt_graph_out->output(pixel ? '*' : ' ');
|
||||
if (pixel) {
|
||||
m_printer_bitmap.pix(m_printer_bitmap.height() - 1 , i * PRINT_CELL_W + col) = PRINT_FG;
|
||||
}
|
||||
}
|
||||
m_prt_graph_out->output(' ');
|
||||
m_prt_graph_out->output(' ');
|
||||
@ -629,13 +702,21 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::prt_timer)
|
||||
}
|
||||
m_prt_graph_out->output('\n');
|
||||
m_printer_line++;
|
||||
if (m_printer_line <= 10) {
|
||||
if (m_printer_line <= PRINT_CELL_H) {
|
||||
m_prt_timer->adjust(attotime::from_ticks(KDP_CLOCKS_PER_LINE , KDP_CLOCK));
|
||||
} else {
|
||||
m_printer_line = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t hp9825_state::printer_out_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
s32 scroll = -s32((PRINT_WINDOWS - m_printer_window - 1) * PRINT_WIN_H);
|
||||
copyscrollbitmap(bitmap , m_printer_bitmap , 0 , nullptr , 1 , &scroll , cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::beep_timer)
|
||||
{
|
||||
m_beeper->set_state(0);
|
||||
@ -700,11 +781,17 @@ void hp9825_state::hp9825_base(machine_config &config)
|
||||
m_tape->sts().set([this](int state) { m_io_sys->set_sts(TAPE_PA , state); });
|
||||
m_tape->dmar().set([this](int state) { m_io_sys->set_dmar(TAPE_PA , state); });
|
||||
m_tape->led().set([this](int state) { m_tape_led = state; });
|
||||
m_tape->cart_in().set([this](int state) { if (started()) m_cassette = state; });
|
||||
|
||||
// Printer
|
||||
BITBANGER(config , m_prt_alpha_out , 0);
|
||||
BITBANGER(config , m_prt_graph_out , 0);
|
||||
TIMER(config , m_prt_timer , 0).configure_generic(FUNC(hp9825_state::prt_timer));
|
||||
SCREEN(config , m_prt_out , SCREEN_TYPE_RASTER);
|
||||
m_prt_out->set_screen_update(FUNC(hp9825_state::printer_out_update));
|
||||
m_prt_out->set_refresh_hz(60);
|
||||
m_prt_out->set_size(PRINT_WIN_W, PRINT_WIN_H);
|
||||
m_prt_out->set_visarea_full();
|
||||
|
||||
// Beeper
|
||||
SPEAKER(config, "mono").front_center();
|
||||
@ -881,6 +968,10 @@ static INPUT_PORTS_START(hp9825)
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CHANGED_MEMBER(DEVICE_SELF, hp9825_state, kb_changed, 0) // Left and right Shift
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Shift lock") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9825_state, kb_changed, 1) // Shift lock
|
||||
PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9825_state, kb_changed, 2) // Reset
|
||||
|
||||
PORT_START("KEY_SCROLL")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Scroll up") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9825_state, scroll_changed, 0)
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Scroll down") PORT_CHANGED_MEMBER(DEVICE_SELF, hp9825_state, scroll_changed, 1)
|
||||
INPUT_PORTS_END
|
||||
|
||||
// +---------------+
|
||||
|
@ -20,7 +20,8 @@
|
||||
#define LOG_DBG(...) LOGMASKED(LOG_DBG_MASK, __VA_ARGS__)
|
||||
#undef VERBOSE
|
||||
//#define VERBOSE (LOG_GENERAL | LOG_REG_MASK | LOG_DBG_MASK)
|
||||
#define VERBOSE (LOG_GENERAL)
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
#define VERBOSE (LOG_GENERAL | LOG_DBG_MASK)
|
||||
|
||||
// Bit manipulation
|
||||
namespace {
|
||||
@ -80,6 +81,7 @@ hp9825_tape_device::hp9825_tape_device(const machine_config &mconfig, const char
|
||||
, m_sts_handler(*this)
|
||||
, m_dmar_handler(*this)
|
||||
, m_led_handler(*this)
|
||||
, m_cart_in_handler(*this)
|
||||
, m_tape(*this , "drive")
|
||||
, m_short_gap_timer(*this , "short_tmr")
|
||||
, m_long_gap_timer(*this , "long_tmr")
|
||||
@ -119,10 +121,12 @@ void hp9825_tape_device::device_add_mconfig(machine_config &config)
|
||||
|
||||
void hp9825_tape_device::device_start()
|
||||
{
|
||||
LOG_DBG("start\n");
|
||||
m_flg_handler.resolve_safe();
|
||||
m_sts_handler.resolve_safe();
|
||||
m_dmar_handler.resolve_safe();
|
||||
m_led_handler.resolve_safe();
|
||||
m_cart_in_handler.resolve_safe();
|
||||
|
||||
save_item(NAME(m_cmd_reg));
|
||||
save_item(NAME(m_stat_reg));
|
||||
@ -143,6 +147,7 @@ void hp9825_tape_device::device_start()
|
||||
|
||||
void hp9825_tape_device::device_reset()
|
||||
{
|
||||
LOG_DBG("reset\n");
|
||||
clear_state();
|
||||
}
|
||||
|
||||
@ -327,6 +332,8 @@ WRITE_LINE_MEMBER(hp9825_tape_device::cart_out_w)
|
||||
BIT_CLR(m_stat_reg, STAT_REG_WPR_BIT);
|
||||
}
|
||||
|
||||
m_cart_in_handler(!state);
|
||||
|
||||
update_sts();
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
auto sts() { return m_sts_handler.bind(); }
|
||||
auto dmar() { return m_dmar_handler.bind(); }
|
||||
auto led() { return m_led_handler.bind(); }
|
||||
auto cart_in() { return m_cart_in_handler.bind(); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(short_gap_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(long_gap_w);
|
||||
@ -52,6 +53,7 @@ private:
|
||||
devcb_write_line m_sts_handler;
|
||||
devcb_write_line m_dmar_handler;
|
||||
devcb_write_line m_led_handler;
|
||||
devcb_write_line m_cart_in_handler;
|
||||
|
||||
required_device<hp_dc100_tape_device> m_tape;
|
||||
required_device<ttl74123_device> m_short_gap_timer; // U43a
|
||||
|
Loading…
Reference in New Issue
Block a user