diff options
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 |
commit | 7447b39cd524bfb2709a7f8b49a1ea798e9be61f (patch) | |
tree | e3a52f73a448343bbeea80f91cbc51672b61506c | |
parent | 6d3eddd8196dd6256c1ed6872f8507d021de41d5 (diff) |
aim65: added printer display
-rw-r--r-- | src/mame/drivers/aim65.cpp | 26 | ||||
-rw-r--r-- | src/mame/includes/aim65.h | 24 | ||||
-rw-r--r-- | src/mame/layout/aim65.lay | 21 | ||||
-rw-r--r-- | src/mame/machine/aim65.cpp | 218 |
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 |