summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/drivers/a6809.cpp
blob: 5d242f43b42da5ad5afb9d8636bc5a1adc9ccff4 (plain) (tree)
1
2
3
4
5
6
7
8
                       
                                                



                                                                            

                                     



                                                                 








                                                                           

                       

                                     






















                                        
 





                                                                             
                          

                          

                              

                    




                                        
                                                                                     







                                                   


                                           
                              
                                         

                                                
                                          
                                     

                                              
 
                                         
 
        


                                                  
                               
                          
                       
                              
                                              
                                                      
                                              
                                              


  










                                                                                                                    
 




                                 
                                         
 







                            

 
                                       
 





                                                  

 
                                             
 






                                              

                                         
 

















                                                                      


                                        

 



                                                  





                                         









                                                                               
                                                            



                                         
                                                      



                                   
                                  
 
                                

                                                        






                                    



                            
                                        
                                    
                                                        
                                       
                                                       
 


                                         
                                                          

                                                                
                                                                           
                                      




                                                   
 
                     
                                                            
                                                                
                                                                      
 
                                                                        

                                           




                                                               
                                                        
                                                           
                                       

                                                                                                 








                                                                                                                                     



            
                                                                                                                
                                                                                                                   
// license:BSD-3-Clause
// copyright-holders:Robbbert and unknown others
/***************************************************************************

    Acorn 6809

    2009-05-12 Skeleton driver.
    2013-12-16 Fixed video [Robbbert]

    Acorn System 3 update?
    http://acorn.chriswhy.co.uk/8bit_Upgrades/Acorn_6809_CPU.html

    This is a few boards emulated together:
    - 6809 main board
    - 80x25 video board
    - FDC board (to come)

The video board has a mc6845, and the characters do not go to a character
generator, instead they go to a SAA5050, which has its own CG inbuilt, plus
many other features.

ToDo:
    - FDC (address A00)
    - Centronics Printer (VIA port A)

Commands:
C - Echo to printer ( C '+' turns it on)
D - boot from disk
G - Go
L - Load tape
P - Run from  pc reg
R - Display regs
S - Save tape
T - Trace
V - Set breakpoint

M - Modify memory
MV - Modify memory at breakpoint address
MG - Modify memory from Go address
MP - Modify memory from pc-reg address
MR - Modify regs

While modifying memory:
,  show next address
-  show previous address
enter  show next address
;  exit


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

#include "emu.h"
#include "cpu/m6809/m6809.h"
#include "machine/6522via.h"
#include "machine/keyboard.h"
#include "machine/timer.h"
#include "video/saa5050.h"
#include "video/mc6845.h"
#include "imagedev/cassette.h"
#include "sound/wave.h"
#include "screen.h"
#include "speaker.h"


class a6809_state : public driver_device
{
public:
	a6809_state(const machine_config &mconfig, device_type type, const char *tag)
		: driver_device(mconfig, type, tag)
		, m_p_videoram(*this, "videoram")
		, m_via(*this, "via")
		, m_cass(*this, "cassette")
		, m_maincpu(*this, "maincpu")
		, m_crtc(*this, "mc6845")
	{ }

	void a6809(machine_config &config);

protected:
	void kbd_put(u8 data);
	DECLARE_READ8_MEMBER(videoram_r);
	DECLARE_WRITE8_MEMBER(a6809_address_w);
	DECLARE_WRITE8_MEMBER(a6809_register_w);
	DECLARE_WRITE_LINE_MEMBER(cass_w);
	DECLARE_MACHINE_RESET(a6809);
	TIMER_DEVICE_CALLBACK_MEMBER(a6809_c);
	TIMER_DEVICE_CALLBACK_MEMBER(a6809_p);

	void a6809_mem(address_map &map);

private:
	required_shared_ptr<uint8_t> m_p_videoram;
	uint16_t m_start_address;
	uint16_t m_cursor_address;
	uint8_t m_cass_data[4];
	bool m_cass_state;
	bool m_cassold;
	uint8_t m_video_index;
	required_device<via6522_device> m_via;
	required_device<cassette_image_device> m_cass;
	required_device<cpu_device> m_maincpu;
	required_device<mc6845_device> m_crtc;
};


void a6809_state::a6809_mem(address_map &map)
{
	map.unmap_value_high();
	map(0x0000, 0x03ff).ram();
	map(0x0400, 0x07ff).ram().share("videoram");
	map(0x0800, 0x0800).r(m_crtc, FUNC(mc6845_device::status_r)).w(this, FUNC(a6809_state::a6809_address_w));
	map(0x0801, 0x0801).r(m_crtc, FUNC(mc6845_device::register_r)).w(this, FUNC(a6809_state::a6809_register_w));
	map(0x0900, 0x090f).mirror(0xf0).rw(m_via, FUNC(via6522_device::read), FUNC(via6522_device::write));
	map(0xf000, 0xf7ff); // optional ROM
	map(0xf800, 0xffff).rom().region("maincpu", 0);
}

/* Input ports */
static INPUT_PORTS_START( a6809 )
INPUT_PORTS_END


MACHINE_RESET_MEMBER( a6809_state, a6809)
{
	m_via->write_pb0(0);
	m_via->write_pb1(0);
	m_via->write_pb2(0);
	m_via->write_pb3(0);
	m_via->write_pb4(0);
	m_via->write_pb5(0);
	m_via->write_pb6(0);
	m_via->write_pb7(0);
}

READ8_MEMBER( a6809_state::videoram_r )
{
	offset += m_start_address;

	if (m_cursor_address == offset)
		return 0x7f; // cheap cursor
	else
		return m_p_videoram[offset&0x3ff];
}

WRITE8_MEMBER( a6809_state::a6809_address_w )
{
	m_crtc->address_w( space, 0, data );

	m_video_index = data & 0x1f;
}

WRITE8_MEMBER( a6809_state::a6809_register_w )
{
	uint16_t temp = m_start_address;
	uint16_t temq = m_cursor_address;

	m_crtc->register_w( space, 0, data );

	// Get start address
	if (m_video_index == 12)
		m_start_address = ((data & 7) << 8 ) | (temp & 0xff);
	else
	if (m_video_index == 13)
		m_start_address = data | (temp & 0x3f00);

	else
	// Get cursor address
	if (m_video_index == 14)
		m_cursor_address = ((data & 7) << 8 ) | (temq & 0xff);
	else
	if (m_video_index == 15)
		m_cursor_address = data | (temq & 0x3f00);
}

WRITE_LINE_MEMBER( a6809_state::cass_w )
{
	m_cass_state = state;
}

TIMER_DEVICE_CALLBACK_MEMBER(a6809_state::a6809_c)
{
	m_cass_data[3]++;

	if (m_cass_state != m_cassold)
	{
		m_cass_data[3] = 0;
		m_cassold = m_cass_state;
	}

	if (m_cass_state)
		m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz
	else
		m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz
}

TIMER_DEVICE_CALLBACK_MEMBER(a6809_state::a6809_p)
{
	/* cassette - turn 1200/2400Hz to a bit */
	m_cass_data[1]++;
	uint8_t cass_ws = (m_cass->input() > +0.03) ? 1 : 0;

	if (cass_ws != m_cass_data[0])
	{
		m_cass_data[0] = cass_ws;
		m_via->write_pb7(m_cass_data[1] < 12);
		m_cass_data[1] = 0;
	}
}

void a6809_state::kbd_put(u8 data)
{
	uint8_t d = data & 0x7f;
	if (d == 8) d = 0x7f; // allow backspace to work

	m_via->write_pb0(BIT(d, 0));
	m_via->write_pb1(BIT(d, 1));
	m_via->write_pb2(BIT(d, 2));
	m_via->write_pb3(BIT(d, 3));
	m_via->write_pb4(BIT(d, 4));
	m_via->write_pb5(BIT(d, 5));
	m_via->write_pb6(BIT(d, 6));
	m_via->write_cb1(1);
	m_via->write_cb1(0);
}

MACHINE_CONFIG_START(a6809_state::a6809)
	/* basic machine hardware */
	MCFG_CPU_ADD("maincpu", MC6809, XTAL(4'000'000))
	MCFG_CPU_PROGRAM_MAP(a6809_mem)
	MCFG_MACHINE_RESET_OVERRIDE(a6809_state, a6809)

	/* video hardware */
	MCFG_SCREEN_ADD("screen", RASTER)
	MCFG_SCREEN_REFRESH_RATE(50)
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500))
	MCFG_SCREEN_SIZE(40 * 12, 25 * 20)
	MCFG_SCREEN_VISIBLE_AREA(0, 40 * 12 - 1, 0, 25 * 20 - 1)
	MCFG_SCREEN_UPDATE_DEVICE("saa5050", saa5050_device, screen_update)
	MCFG_PALETTE_ADD("palette", 8)

	/* sound hardware */
	MCFG_SPEAKER_STANDARD_MONO("mono")
	MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette")
	MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)

	/* Devices */
	MCFG_DEVICE_ADD("via", VIA6522, XTAL(4'000'000) / 4)
	MCFG_VIA6522_CB2_HANDLER(WRITELINE(a6809_state, cass_w))
	MCFG_VIA6522_IRQ_HANDLER(INPUTLINE("maincpu", M6809_IRQ_LINE))

	MCFG_MC6845_ADD("mc6845", HD6845, "screen", XTAL(4'000'000) / 2)
	MCFG_MC6845_SHOW_BORDER_AREA(false)
	MCFG_MC6845_CHAR_WIDTH(12)

	MCFG_DEVICE_ADD("saa5050", SAA5050, 6000000)
	MCFG_SAA5050_D_CALLBACK(READ8(a6809_state, videoram_r))
	MCFG_SAA5050_SCREEN_SIZE(40, 25, 40)

	MCFG_DEVICE_ADD("keyboard", GENERIC_KEYBOARD, 0)
	MCFG_GENERIC_KEYBOARD_CB(PUT(a6809_state, kbd_put))
	MCFG_CASSETTE_ADD( "cassette" )
	MCFG_TIMER_DRIVER_ADD_PERIODIC("a6809_c", a6809_state, a6809_c, attotime::from_hz(4800))
	MCFG_TIMER_DRIVER_ADD_PERIODIC("a6809_p", a6809_state, a6809_p, attotime::from_hz(40000))
MACHINE_CONFIG_END

/* ROM definition */
ROM_START( a6809 )
	ROM_REGION( 0x800, "maincpu", 0 )
	ROM_LOAD( "acorn6809.bin", 0x000, 0x800, CRC(5fa5b632) SHA1(b14a884bf82a7a8c23bc03c2e112728dd1a74896) )

	ROM_REGION( 0x100, "proms", 0 )
	ROM_LOAD( "acorn6809.ic11", 0x0000, 0x0100, CRC(7908317d) SHA1(e0f1e5bd3a8598d3b62bc432dd1f3892ed7e66d8) ) // address decoder
ROM_END

/* Driver */

/*    YEAR   NAME   PARENT  COMPAT   MACHINE    INPUT  CLASS           INIT    COMPANY   FULLNAME       FLAGS */
COMP( 1980, a6809,  0,      0,       a6809,     a6809, a6809_state,     0,     "Acorn",  "System 3 (6809 CPU)", 0 )