summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/machine/aim65.cpp
blob: c66eee067648e619441160563b26eeb75b98fe16 (plain) (tree)
1
2

                                                                  










































                                                                               
                                                                 
 



                                                                        

 
                             
 




                                





                                           
                    





                                           
                    


 
                                              
 
                                                         

 
                                              
 
                                                         

 
                                              
 
                                                         

 
                                              
 
                                                          

 
                                              
 
                                                          
















                                                                               
                                 






















                                                                            
                                 
 
                                
                                                            
 
                           
                            
                                                                                                                                            
                            
                                                                                                                                            
                            
                                                                                                                                            
 
                   
                                                                   
 
                      




























                                                                               
                                        



                         

                                                                




                                 
                                                                                               
                    
                                                                                              




                                 
                                                                                               
                    
                                                                                              











                                       
                                                  
                                                          
































































                                                                               
                           



                          
 










                                                        
                                                



                            
                                                       
 
                                                                              
 


                                           
 
                          
         

                                      

                    


                                          



                 

                                      

                    


                                          


                 
                                               
 

                   






























                                                                                  
                                     
 
                                                                                                                               
                                                                        







                                               






                                                                         

                        












                                                                               
                                                                                  











                                                                                
// license:GPL-2.0+
// copyright-holders:Peter Trauner, Dan Boris, Dirk Best, Robbbert
/******************************************************************************

 AIM65

******************************************************************************/


#include "includes/aim65.h"


/******************************************************************************
 Interrupt handling
******************************************************************************/

/* STEP/RUN
 *
 * Switch S2 (STEP/RUN) causes AIM 65 to operate either in the RUN mode or the
 * single STEP mode. In the STEP mode, the NMI interrupt line is driven low
 * when SYNC and O2 go high during instruction execution if the address lines
 * are outside the A000-FFFF range. The NMI interrupt occurs on the high to
 * low transition of the NMI line. The Monitor software will trace instructions
 * and register, outside the Monitor instruction address range if the trace
 * modes are selected and the NMI Interrupt Routine is not bypassed.
 */



/******************************************************************************
 6821 PIA
******************************************************************************/

/* PA0: A0 (Address)
 * PA1: A1 (Address)
 * PA2: CE1 (Chip enable)
 * PA3: CE2 (Chip enable)
 * PA4: CE3 (Chip enable)
 * PA5: CE4 (Chip enable)
 * PA6: CE5 (Chip enable)
 * PA7: W (Write enable)
 * PB0-6: D0-D6 (Data)
 * PB7: CU (Cursor)
 */

void aim65_state::dl1416_update(dl1416_device *device, int index)
{
	device->ce_w(m_pia_a & (0x04 << index));
	device->wr_w(BIT(m_pia_a, 7));
	device->cu_w(BIT(m_pia_b, 7));
	device->data_w(generic_space(), m_pia_a & 0x03, m_pia_b & 0x7f);
}

void aim65_state::aim65_pia()
{
	dl1416_update(m_ds1, 0);
	dl1416_update(m_ds2, 1);
	dl1416_update(m_ds3, 2);
	dl1416_update(m_ds4, 3);
	dl1416_update(m_ds5, 4);
}


WRITE8_MEMBER( aim65_state::aim65_pia_a_w )
{
	m_pia_a = data;
	aim65_pia();
}


WRITE8_MEMBER( aim65_state::aim65_pia_b_w )
{
	m_pia_b = data;
	aim65_pia();
}


WRITE16_MEMBER( aim65_state::aim65_update_ds1)
{
	output().set_digit_value(0 + (offset ^ 3), data);
}

WRITE16_MEMBER( aim65_state::aim65_update_ds2)
{
	output().set_digit_value(4 + (offset ^ 3), data);
}

WRITE16_MEMBER( aim65_state::aim65_update_ds3)
{
	output().set_digit_value(8 + (offset ^ 3), data);
}

WRITE16_MEMBER( aim65_state::aim65_update_ds4)
{
	output().set_digit_value(12 + (offset ^ 3), data);
}

WRITE16_MEMBER( aim65_state::aim65_update_ds5)
{
	output().set_digit_value(16 + (offset ^ 3), data);
}



/******************************************************************************
 6532 RIOT
******************************************************************************/


READ8_MEMBER( aim65_state::aim65_riot_b_r )
{
	static const char *const keynames[] =
	{
		"keyboard_0", "keyboard_1", "keyboard_2", "keyboard_3",
		"keyboard_4", "keyboard_5", "keyboard_6", "keyboard_7"
	};

	uint8_t row, data = 0xff;

	/* scan keyboard rows */
	for (row = 0; row < 8; row++)
	{
		if (!BIT(m_riot_port_a, row))
			data &= ioport(keynames[row])->read();
	}

	return data;
}


WRITE8_MEMBER( aim65_state::aim65_riot_a_w )
{
	m_riot_port_a = data;
}



/***************************************************************************
    DRIVER INIT
***************************************************************************/

void aim65_state::machine_start()
{
	ram_device *ram = m_ram;
	address_space &space = m_maincpu->space(AS_PROGRAM);

	// Init ROM sockets
	if (m_z24->exists())
		space.install_read_handler(0xd000, 0xdfff, read8_delegate(FUNC(generic_slot_device::read_rom),(generic_slot_device*)m_z24));
	if (m_z25->exists())
		space.install_read_handler(0xc000, 0xcfff, read8_delegate(FUNC(generic_slot_device::read_rom),(generic_slot_device*)m_z25));
	if (m_z26->exists())
		space.install_read_handler(0xb000, 0xbfff, read8_delegate(FUNC(generic_slot_device::read_rom),(generic_slot_device*)m_z26));

	// Init RAM
	space.install_ram(0x0000, ram->size() - 1, ram->pointer());

	m_pb_save = 0;
}


/* RESET
 *
 * Pushbutton switch S1 initiates RESET of the AIM65 hardware and software.
 * Timer Z4 holds the RES low for at least 15 ms from the time the pushbutton
 * is released. RES is routed to the R6502 CPU, the Monitor R6522 (Z32), the
 * Monitor R6532 RIOT (Z33), the user R6522 VIA (Z1), and the display R6520 PIA
 * (U1). To initiate the device RESET function is also routed to the expansion
 * connector for off-board RESET functions. The Monitor performs a software
 * reset when the RES line goes high.
 */


/******************************************************************************
 Cassette
******************************************************************************/

WRITE8_MEMBER( aim65_state::aim65_pb_w )
{
/*
    d7 = cass out (both decks)
    d5 = cass2 motor
    d4 = cass1 motor
    d2 = tty out (not emulated)
    d0/1 = printer data (not emulated)
*/

	uint8_t bits = data ^ m_pb_save;
	m_pb_save = data;

	if (BIT(bits, 7))
	{
		m_cassette1->output(BIT(data, 7) ? -1.0 : +1.0);
		m_cassette2->output(BIT(data, 7) ? -1.0 : +1.0);
	}

	if (BIT(bits, 5))
	{
		if (BIT(data, 5))
			m_cassette2->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
		else
			m_cassette2->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
	}

	if (BIT(bits, 4))
	{
		if (BIT(data, 4))
			m_cassette1->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
		else
			m_cassette1->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
	}
}


READ8_MEMBER( aim65_state::aim65_pb_r )
{
/*
    d7 = cassette in (deck 1)
    d6 = tty in (not emulated)
    d3 = kb/tty switch
*/

	uint8_t data = ioport("switches")->read();
	data |= (m_cassette1->input() > +0.03) ? 0x80 : 0;
	data |= 0x40; // TTY must be H if not used.
	data |= m_pb_save & 0x37;
	return data;
}


/******************************************************************************
 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

  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)
*/


TIMER_CALLBACK_MEMBER(aim65_state::aim65_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;
}


WRITE8_MEMBER( aim65_state::aim65_printer_on )
{
	via6522_device *via_0 = machine().device<via6522_device>("via6522_0");
	if (!data)
	{
		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_level = 1;
	}
	else
		m_print_timer->reset();
}


WRITE8_MEMBER( aim65_state::aim65_pa_w )
{
// All bits are for printer data (not emulated)
	if (m_flag_a == 0)
	{
		m_printerRAM[(m_printer_y * 20) + m_printer_x] |= data;
		m_flag_a = 1;
	}
}

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 )
{
	aim65_state *state = screen.machine().driver_data<aim65_state>();
	/* Display printer output */
	bool dir = 1;
	uint8_t b,x,pen;
	uint16_t y;

	for (y = 0; y<500; y++)
	{
		for(x = 0; x< 10; x++)
		{
			if (dir == 1)
				data = state->m_printerRAM[y * 10  + x];
			else
				data = state->m_printerRAM[(y * 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;
			}
		}

		dir ^= 1;
	}
	return 0;
}


#endif