1 // license:LGPL-2.1+
2 // copyright-holders:Michael Zapf
3 /*******************************************************************************
4     FORTi Sound card
5 
6     4 x TMS9919 sound generators
7     4 sound outputs; may be coupled to two stereo outputs
8 
9     Mapping:
10 
11     1000 01xx xxxD CBA0
12 
13     8402: Sound chip 1 (A)
14     8404: Sound chip 2 (B)
15     8408: Sound chip 3 (C)
16     8410: Sound chip 4 (D)
17 
18     Sound chips may be addressed in parallel:
19     8406: Sound chips 1+2
20     841a: Sound chips 1+3+4
21 
22     All sound READY lines are combined by a wired-AND as the common
23     READY line to the CPU.
24 
25     Michael Zapf
26     March 2020
27 
28 *******************************************************************************/
29 
30 #include "emu.h"
31 #include "forti.h"
32 
33 #define LOG_READY       (1U<<1)
34 
35 #define VERBOSE ( LOG_GENERAL )
36 
37 #include "logmacro.h"
38 
39 #define FORTI_GEN1_TAG "soundchip1"
40 #define FORTI_GEN2_TAG "soundchip2"
41 #define FORTI_GEN3_TAG "soundchip3"
42 #define FORTI_GEN4_TAG "soundchip4"
43 
44 DEFINE_DEVICE_TYPE_NS(TI99_FORTI, bus::ti99::peb, forti_device, "ti99_forti", "FORTi Sound Card")
45 
46 namespace bus { namespace ti99 { namespace peb {
47 
forti_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)48 forti_device::forti_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
49 	  device_t(mconfig, TI99_FORTI, tag, owner, clock),
50 	  device_ti99_peribox_card_interface(mconfig, *this),
51 	  m_generator1(*this, FORTI_GEN1_TAG),
52 	  m_generator2(*this, FORTI_GEN2_TAG),
53 	  m_generator3(*this, FORTI_GEN3_TAG),
54 	  m_generator4(*this, FORTI_GEN4_TAG)
55 {
56 }
57 
58 /*
59     No read access. The FORTi card does not support any reading.
60 */
readz(offs_t offset,uint8_t * value)61 void forti_device::readz(offs_t offset, uint8_t *value)
62 {
63 	return;
64 }
65 
66 /*
67     READY callbacks from the sound chips.
68 */
WRITE_LINE_MEMBER(forti_device::ready_sound)69 WRITE_LINE_MEMBER( forti_device::ready_sound )
70 {
71 	LOGMASKED(LOG_READY, "READY (%d, %d, %d, %d)\n",  m_generator1->ready_r(),
72 		m_generator2->ready_r(), m_generator3->ready_r(), m_generator4->ready_r());
73 
74 	line_state ready = (m_generator1->ready_r() && m_generator2->ready_r()
75 		 && m_generator3->ready_r() && m_generator4->ready_r())? ASSERT_LINE : CLEAR_LINE;
76 
77 	m_slot->set_ready(ready);
78 }
79 
write(offs_t offset,uint8_t data)80 void forti_device::write(offs_t offset, uint8_t data)
81 {
82 	// Decode for 8400-87ff
83 	if ((offset & 0xfc01) == 0x8400)
84 	{
85 		// The generators can be accessed in parallel
86 		if ((offset & 0x2)!=0)
87 			m_generator1->write(data);
88 
89 		if ((offset & 0x4)!=0)
90 			m_generator2->write(data);
91 
92 		if ((offset & 0x8)!=0)
93 			m_generator3->write(data);
94 
95 		if ((offset & 0x10)!=0)
96 			m_generator4->write(data);
97 	}
98 }
99 
device_add_mconfig(machine_config & config)100 void forti_device::device_add_mconfig(machine_config& config)
101 {
102 	// 1 and 3 are mixed to left channel
103 	// 2 and 4 are moxed to right channel
104 
105 	SPEAKER(config, "forti_left").front_left();
106 	SPEAKER(config, "forti_right").front_right();
107 
108 	SN94624(config, m_generator1, XTAL(3'579'545)/8);
109 	m_generator1->ready_cb().set(FUNC(forti_device::ready_sound));
110 	m_generator1->add_route(ALL_OUTPUTS, "forti_left", 0.75);
111 
112 	SN94624(config, m_generator2, XTAL(3'579'545)/8);
113 	m_generator2->ready_cb().set(FUNC(forti_device::ready_sound));
114 	m_generator2->add_route(ALL_OUTPUTS, "forti_right", 0.75);
115 
116 	SN94624(config, m_generator3, XTAL(3'579'545)/8);
117 	m_generator3->ready_cb().set(FUNC(forti_device::ready_sound));
118 	m_generator3->add_route(ALL_OUTPUTS, "forti_left", 0.75);
119 
120 	SN94624(config, m_generator4, XTAL(3'579'545)/8);
121 	m_generator4->ready_cb().set(FUNC(forti_device::ready_sound));
122 	m_generator4->add_route(ALL_OUTPUTS, "forti_right", 0.75);
123 }
124 
device_start()125 void forti_device::device_start()
126 {
127 }
128 
device_reset()129 void forti_device::device_reset()
130 {
131 }
132 
133 } } } // end namespace bus::ti99::peb
134