summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2019-04-19 20:15:23 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2019-04-19 20:15:23 +1000
commit7447b39cd524bfb2709a7f8b49a1ea798e9be61f (patch)
treee3a52f73a448343bbeea80f91cbc51672b61506c
parent6d3eddd8196dd6256c1ed6872f8507d021de41d5 (diff)
aim65: added printer display
-rw-r--r--src/mame/drivers/aim65.cpp26
-rw-r--r--src/mame/includes/aim65.h24
-rw-r--r--src/mame/layout/aim65.lay21
-rw-r--r--src/mame/machine/aim65.cpp218
4 files changed, 133 insertions, 156 deletions
diff --git a/src/mame/drivers/aim65.cpp b/src/mame/drivers/aim65.cpp
index 930a254ea84..619c8c4fe99 100644
--- a/src/mame/drivers/aim65.cpp
+++ b/src/mame/drivers/aim65.cpp
@@ -7,9 +7,7 @@ Rewrite in progress, Dirk Best, 2007-07-31
Updated by Robbbert 2019-04-14
ToDo:
- - Printer. Tried to implement this but it was not working, currently disabled.
- Implement punchtape reader/writer
- - Front panel Reset switch (switch S1)
- Front panel Run/Step switch (switch S2)
@@ -161,6 +159,12 @@ INPUT_CHANGED_MEMBER(aim65_state::reset_button)
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
}
+void aim65_state::aim65_palette(palette_device &palette) const
+{
+ palette.set_pen_color(0, rgb_t(0x20, 0x02, 0x05));
+ palette.set_pen_color(1, rgb_t(0xc0, 0x00, 0x00));
+}
+
/***************************************************************************
MACHINE DRIVERS
@@ -220,6 +224,17 @@ MACHINE_CONFIG_START(aim65_state::aim65)
DL1416T(config, m_ds[4], u32(0));
m_ds[4]->update().set(FUNC(aim65_state::update_ds<5>));
+ // pseudo-"screen" for the thermal printer. Index 0.
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_refresh_hz(60);
+ screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
+ screen.set_screen_update(FUNC(aim65_state::screen_update));
+ screen.set_size(160, 200);
+ screen.set_visarea_full();
+ screen.set_palette("palette");
+
+ PALETTE(config, m_palette, FUNC(aim65_state::aim65_palette), 2);
+
/* Sound - wave sound only */
SPEAKER(config, "mono").front_center();
WAVE(config, "wave", m_cassette1).add_route(ALL_OUTPUTS, "mono", 0.1);
@@ -233,6 +248,7 @@ MACHINE_CONFIG_START(aim65_state::aim65)
VIA6522(config, m_via0, AIM65_CLOCK);
m_via0->readpb_handler().set([this] () { return aim65_state::z32_pb_r(); });
+ m_via0->writepa_handler().set([this] (u8 data) { aim65_state::z32_pa_w(data); });
m_via0->writepb_handler().set([this] (u8 data) { aim65_state::z32_pb_w(data); });
// in CA1 printer ready?
// out CA2 cass control (H=in)
@@ -240,7 +256,7 @@ MACHINE_CONFIG_START(aim65_state::aim65)
// out CB1 printer start
//m_via0->cb1_handler().set(FUNC(aim65_state::z32_cb1_w));
// out CB2 turn printer on
- //m_via0->cb2_handler().set(FUNC(aim65_state::z32_cb2_w));
+ m_via0->cb2_handler().set([this] (bool state) { aim65_state::z32_cb2_w(state); });
m_via0->irq_handler().set_inputline(m_maincpu, M6502_IRQ_LINE);
VIA6522(config, m_via1, AIM65_CLOCK);
@@ -255,8 +271,8 @@ MACHINE_CONFIG_START(aim65_state::aim65)
CASSETTE(config, m_cassette2);
m_cassette2->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED);
- /* TTY interface */
- RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ // Screen for TTY interface. Index 1.
+ RS232_PORT(config, m_rs232, default_rs232_devices, "terminal");
//m_rs232->rxd_handler().set(m_via0, FUNC(via6522_device::write_pb6)); // function disabled in 6522via.cpp
m_rs232->set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(serial_term));
diff --git a/src/mame/includes/aim65.h b/src/mame/includes/aim65.h
index c689c5f1529..be2b9370fbd 100644
--- a/src/mame/includes/aim65.h
+++ b/src/mame/includes/aim65.h
@@ -23,6 +23,8 @@
#include "machine/ram.h"
#include "sound/wave.h"
#include "video/dl1416.h"
+#include "emupal.h"
+#include "screen.h"
class aim65_state : public driver_device
@@ -30,10 +32,16 @@ class aim65_state : public driver_device
public:
aim65_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
+ , m_palette(*this, "palette")
, m_riot_port_a(0)
, m_pb_save(0)
, m_kb_en(true)
, m_ca2(true)
+ , m_cb2(true)
+ , m_printer_x(0)
+ , m_printer_y(0)
+ , m_printer_flag(0)
+ , m_printer_level(0)
, m_maincpu(*this, "maincpu")
, m_cassette1(*this, "cassette")
, m_cassette2(*this, "cassette2")
@@ -60,13 +68,16 @@ public:
DECLARE_INPUT_CHANGED_MEMBER(reset_button);
-protected:
+private:
virtual void machine_start() override;
+ void aim65_palette(palette_device &palette) const;
void u1_pa_w(u8 data);
void u1_pb_w(u8 data);
u8 z33_pb_r();
+ void z32_pa_w(u8 data);
void z32_pb_w(u8 data);
+ void z32_cb2_w(bool state);
u8 z32_pb_r();
template <unsigned D> DECLARE_WRITE16_MEMBER(update_ds);
@@ -78,16 +89,25 @@ protected:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(z13_load) { return load_cart(image, m_z13, "z13"); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(z14_load) { return load_cart(image, m_z14, "z14"); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(z15_load) { return load_cart(image, m_z15, "z15"); }
+ emu_timer *m_print_timer;
+ TIMER_CALLBACK_MEMBER(printer_timer);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
image_init_result load_cart(device_image_interface &image, generic_slot_device *slot, const char *slot_tag);
void mem_map(address_map &map);
-private:
+ optional_device<palette_device> m_palette;
uint8_t m_riot_port_a;
uint8_t m_pb_save;
bool m_kb_en;
bool m_ca2;
+ bool m_cb2;
+ u8 m_printer_x;
+ u8 m_printer_y;
+ u8 m_printer_flag;
+ bool m_printer_level;
+ std::unique_ptr<uint16_t[]> m_printerRAM;
required_device<cpu_device> m_maincpu;
required_device<cassette_image_device> m_cassette1;
diff --git a/src/mame/layout/aim65.lay b/src/mame/layout/aim65.lay
index a660628b976..6041a786bbd 100644
--- a/src/mame/layout/aim65.lay
+++ b/src/mame/layout/aim65.lay
@@ -64,13 +64,34 @@
</group>
</view>
+ <view name="Printer Below">
+ <group ref="displays">
+ <bounds x="0" y="0" width="241" height="16" />
+ </group>
+ <screen index="0">
+ <bounds x="0" y="16" width="241" height="180.75" />
+ </screen>
+ </view>
+
<view name="Terminal Below">
<group ref="displays">
<bounds x="0" y="0" width="241" height="16" />
</group>
+ <screen index="1">
+ <bounds x="0" y="16" width="241" height="180.75" />
+ </screen>
+ </view>
+
+ <view name="Printer and Terminal">
+ <group ref="displays">
+ <bounds x="0" y="0" width="241" height="16" />
+ </group>
<screen index="0">
<bounds x="0" y="16" width="241" height="180.75" />
</screen>
+ <screen index="1">
+ <bounds x="250" y="0" width="241" height="196.75" />
+ </screen>
</view>
</mamelayout>
diff --git a/src/mame/machine/aim65.cpp b/src/mame/machine/aim65.cpp
index 7b09e752c7c..e39e192d682 100644
--- a/src/mame/machine/aim65.cpp
+++ b/src/mame/machine/aim65.cpp
@@ -137,6 +137,14 @@ void aim65_state::machine_start()
save_item(NAME(m_pb_save));
save_item(NAME(m_kb_en));
save_item(NAME(m_ca2));
+ save_item(NAME(m_cb2));
+ save_item(NAME(m_printer_x));
+ save_item(NAME(m_printer_y));
+ save_item(NAME(m_printer_flag));
+ save_item(NAME(m_printer_level));
+ m_print_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(aim65_state::printer_timer),this));
+ m_printerRAM = make_unique_clear<uint16_t[]>(64*100);
+ save_pointer(NAME(m_printerRAM), 64*100);
}
@@ -163,7 +171,7 @@ void aim65_state::z32_pb_w( u8 data )
d5 = cass2 motor
d4 = cass1 motor
d2 = tty out
- d0/1 = printer data (not emulated)
+ d0/1 = printer data
There seems to be a mistake in the code. When the cassettes should both be stopped, it turns them on instead.
*/
@@ -190,6 +198,11 @@ void aim65_state::z32_pb_w( u8 data )
if (!m_kb_en)
m_rs232->write_txd(BIT(data, 2));
+
+ // 4 left-most characters for the thermal printer
+ data &= 0x03;
+ if ((m_printer_flag == 1) && (!m_cb2))
+ m_printerRAM[(m_printer_y * 100) + m_printer_x ] |= (data << 8);
}
@@ -227,193 +240,100 @@ u8 aim65_state::z32_pb_r ()
Printer
******************************************************************************/
-#ifdef UNUSED_FUNCTION
/*
-
-2012-01-24 Printer code removed [Robbbert]
-
-From here to the end is not compiled. It is the remnants of the old printer
-code. Have a look at version 0.114 or 0.115 for the original working code.
-
-I've left it here for the idly curious.
-
The system sends out the pattern of dots to the 'dot-matrix' print-head.
-This is why we can't simply replace it with a Centronics-like 'Printer'
-device - the output will be gibberish.
-*/
-
-
-
-/*
aim65 thermal printer (20 characters)
10 heat elements (place on 1 line, space between 2 characters(about 14dots))
(pa0..pa7,pb0,pb1 1 heat element on)
- cb2 0 motor, heat elements on
- cb1 output start!?
- ca1 input
+ cb2 0 motor, heat elements on. Enables printer. Also indicates that a new line is coming.
+ cb1 0 input - printer is requesting data, driven by "start" line
+ ca1 ^ input - changes polarity on each line, driven by s1 and s2
normally printer 5x7 characters
(horizontal movement limits not known, normally 2 dots between characters)
- 3 dots space between lines?
-*/
-
-
-/* Part of aim65_pb_w
-
- data &= 0x03;
-
- if (m_flag_b == 0)
- {
- printerRAM[(m_printer_y * 20) + m_printer_x ] |= (data << 8);
- m_flag_b = 1;
- }
-*/
-
-
-/* Items for driver state
-
- emu_timer *m_print_timer;
- int m_printer_x;
- int m_printer_y;
- bool m_printer_dir;
- bool m_flag_a;
- bool m_flag_b;
- bool m_printer_level;
- uint16_t *m_printerRAM;
-*/
-
-
-/* Other items from H file
-
-VIDEO_UPDATE( aim65 );
-*/
-
-
-/* From 6522 config
-DRIVER_MEMBER(aim65_state, aim65_pa_w), // out port A
-DRIVER_MEMBER(aim65_state, aim65_printer_on), // out CB2
-*/
-
-
-/* From Machine Config
- MCFG_VIDEO_START_OVERRIDE(aim65_state,aim65)
- MCFG_VIDEO_UPDATE(aim65)
+ 3 dots space between lines
*/
-
-TIMER_CALLBACK_MEMBER(aim65_state::aim65_printer_timer)
+// to get printer to pass the test at start.
+TIMER_CALLBACK_MEMBER(aim65_state::printer_timer)
{
- via6522_device *via_0 = machine().device<via6522_device>("via6522_0");
-
- via_0->write_cb1(m_printer_level);
- via_0->write_cb1(!m_printer_level);
- m_printer_level ^= 1;
-
- if (m_printer_dir)
- {
- if (m_printer_x > 0)
- m_printer_x--;
- else
- {
- m_printer_dir = 0;
- m_printer_x++;
- m_printer_y++;
- }
- }
- else
- {
- if (m_printer_x < 9)
- m_printer_x++;
- else
- {
- m_printer_dir = 1;
- m_printer_x--;
- m_printer_y++;
- }
- }
-
- if (m_printer_y > 500) m_printer_y = 0;
-
- m_flag_a=0;
- m_flag_b=0;
+ m_via0->write_cb1(m_printer_level);
+ m_via0->write_ca1(m_printer_level);
+ m_printer_level ^= 1;
}
-
-WRITE8_MEMBER( aim65_state::aim65_printer_on )
+// CB2 - enable, & new-line
+void aim65_state::z32_cb2_w( bool state )
{
- via6522_device *via_0 = machine().device<via6522_device>("via6522_0");
- if (!data)
+ m_cb2 = state;
+ if (!state)
{
- m_printer_x=0;
+ m_printer_x = 0;
m_printer_y++;
- if (m_printer_y > 500) m_printer_y = 0;
- m_flag_a = m_flag_b=0;
- via_0->write_cb1(0);
- m_print_timer->adjust(attotime::zero, 0, attotime::from_usec(10));
+ m_printer_y &= 63;
+ for (u8 i = 0; i < 100; i++)
+ m_printerRAM[m_printer_y*100+i] = 0;
+ m_printer_flag = 0;
+ m_via0->write_cb1(1);
+ m_print_timer->adjust(attotime::zero, 0, attotime::from_msec(1));
m_printer_level = 1;
}
else
m_print_timer->reset();
}
-
-WRITE8_MEMBER( aim65_state::aim65_pa_w )
+// new pixels spread among multiple thermal heads
+void aim65_state::z32_pa_w( u8 data )
{
-// All bits are for printer data (not emulated)
- if (m_flag_a == 0)
+ if (m_printer_flag == 1)
+ m_printerRAM[m_printer_y * 100 + m_printer_x] |= data;
+
+ m_printer_flag++;
+ if (m_printer_flag > 2)
+ {
+ m_printer_flag = 0;
+ m_printer_x++;
+ }
+ // toggle ca1 each 10 bytes
+ if ((m_printer_x % 10) == 0)
+ {
+ m_via0->write_ca1(m_printer_level);
+ m_printer_level ^= 1;
+ }
+ // take cb1 low after a complete line of characters
+ if (m_printer_x == 100)
{
- m_printerRAM[(m_printer_y * 20) + m_printer_x] |= data;
- m_flag_a = 1;
+ m_printer_x = 0;
+ m_via0->write_cb1(0);
}
}
-VIDEO_START_MEMBER(aim65_state,aim65)
-{
- m_print_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(aim65_state::aim65_printer_timer),this));
- m_printerRAM = std::make_unique<uint16_t[]>((600 * 10 * 2) / 2);
- memset(m_printerRAM, 0, videoram_size);
- VIDEO_START_CALL_MEMBER(generic);
- m_printer_x = 0;
- m_printer_y = 0;
- m_printer_dir = 0;
- m_flag_a = 0;
- m_flag_b = 0;
- m_printer_level = 0;
-}
-SCREEN_UPDATE( aim65 )
+// Display printer output
+uint32_t aim65_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- aim65_state *state = screen.machine().driver_data<aim65_state>();
- /* Display printer output */
- bool dir = 1;
- uint8_t b,x,pen;
- uint16_t y;
+ uint16_t data;
- for (y = 0; y<500; y++)
+ for (u8 y = 0; y<cliprect.max_y; y++)
{
- for(x = 0; x< 10; x++)
+ u16 sy = m_printer_y*10 - cliprect.max_y + 10 + y;
+ if (sy > 0xfe80) // wrap-around correctly
+ sy += 0x280;
+ for(u8 x = 0; x < 10; x++)
{
- if (dir == 1)
- data = state->m_printerRAM[y * 10 + x];
+ if (!BIT(sy, 0))
+ data = m_printerRAM[sy * 10 + x];
else
- data = state->m_printerRAM[(y * 10) + (9 - x)];
-
+ data = m_printerRAM[sy * 10 + (9 - x)];
- for (b = 0; b<10; b++)
- {
- pen = screen.m_palette->pen(BIT(data, 0) ? 2 : 0);
- plot_pixel(bitmap,700 - ((b * 10) + x), y, pen);
- data >>= 1;
- }
+ for (u8 b = 0; b < 10; b++)
+ bitmap.pix16(y, 120 - (b * 12) - ((x > 4) ? x+1 : x)) = BIT(data, b);
}
-
- dir ^= 1;
}
+
return 0;
}
-
-#endif