1 /***************************************************************************
2 
3   machine.c
4 
5   Functions to emulate a prototypical ticket dispenser hardware.
6 
7   Right now, this is an *extremely* basic ticket dispenser.
8   TODO:	Active Bit may not be Bit 7 in all applications.
9   	    Add a ticket dispenser interface instead of passing a bunch
10 		of arguments to ticket_dispenser_init.
11 		Add sound, graphical output?
12 ***************************************************************************/
13 
14 #include "driver.h"
15 #include "machine/ticket.h"
16 
17 /*#define DEBUG_TICKET*/
18 
19 #define MAX_DISPENSERS	2
20 
21 extern unsigned int dispensed_tickets;
22 
23 struct ticket_state
24 {
25 	int status;
26 	int power;
27 	void *timer;
28 };
29 
30 static int active_bit = 0x80;
31 static int time_msec;
32 static int motoron;
33 static int ticketdispensed;
34 static int ticketnotdispensed;
35 
36 static struct ticket_state dispenser[MAX_DISPENSERS];
37 
38 /* Callback routine used during ticket dispensing */
39 static void ticket_dispenser_toggle(int parm);
40 
41 
42 /***************************************************************************
43   ticket_dispenser_init
44 
45 ***************************************************************************/
ticket_dispenser_init(int msec,int motoronhigh,int statusactivehigh)46 void ticket_dispenser_init(int msec, int motoronhigh, int statusactivehigh)
47 {
48 	int i;
49 
50 	time_msec			= msec;
51 	motoron				= motoronhigh  ? active_bit : 0;
52 	ticketdispensed		= statusactivehigh ? active_bit : 0;
53 	ticketnotdispensed	= ticketdispensed ^ active_bit;
54 	dispensed_tickets	= 0;
55 
56 	for (i = 0; i < MAX_DISPENSERS; i++)
57 	{
58 		dispenser[i].status	= ticketnotdispensed;
59 		dispenser[i].power 	= 0x00;
60 		dispenser[i].timer 	= timer_alloc(ticket_dispenser_toggle);
61 	}
62 }
63 
64 /***************************************************************************
65   ticket_dispenser_r
66 ***************************************************************************/
READ_HANDLER(ticket_dispenser_r)67 READ_HANDLER( ticket_dispenser_r )
68 {
69 	return ticket_dispenser_0_r(offset);
70 }
71 
READ_HANDLER(ticket_dispenser_0_r)72 READ_HANDLER( ticket_dispenser_0_r )
73 {
74 #ifdef DEBUG_TICKET
75 	logerror("PC: %04X  Ticket Status Read = %02X\n", activecpu_get_pc(), status);
76 #endif
77 	return dispenser[0].status;
78 }
79 
READ_HANDLER(ticket_dispenser_1_r)80 READ_HANDLER( ticket_dispenser_1_r )
81 {
82 #ifdef DEBUG_TICKET
83 	logerror("PC: %04X  Ticket Status Read = %02X\n", activecpu_get_pc(), status);
84 #endif
85 	return dispenser[1].status;
86 }
87 
88 /***************************************************************************
89   ticket_dispenser_w
90 ***************************************************************************/
WRITE_HANDLER(ticket_dispenser_w)91 WRITE_HANDLER( ticket_dispenser_w )
92 {
93 	ticket_dispenser_0_w(offset, data);
94 }
95 
WRITE_HANDLER(ticket_dispenser_0_w)96 WRITE_HANDLER( ticket_dispenser_0_w )
97 {
98 	/* On an activate signal, start dispensing! */
99 	if ((data & active_bit) == motoron)
100 	{
101 		if (!dispenser[0].power)
102 		{
103 #ifdef DEBUG_TICKET
104 			logerror("PC: %04X  Ticket Power On\n", activecpu_get_pc());
105 #endif
106 			timer_adjust(dispenser[0].timer, TIME_IN_MSEC(time_msec), 0, 0);
107 			dispenser[0].power = 1;
108 
109 			dispenser[0].status = ticketnotdispensed;
110 		}
111 	}
112 	else
113 	{
114 		if (dispenser[0].power)
115 		{
116 #ifdef DEBUG_TICKET
117 			logerror("PC: %04X  Ticket Power Off\n", activecpu_get_pc());
118 #endif
119 			timer_adjust(dispenser[0].timer, TIME_NEVER, 0, 0);
120 			set_led_status(2,0);
121 			dispenser[0].power = 0;
122 		}
123 	}
124 }
125 
WRITE_HANDLER(ticket_dispenser_1_w)126 WRITE_HANDLER( ticket_dispenser_1_w )
127 {
128 	/* On an activate signal, start dispensing! */
129 	if ((data & active_bit) == motoron)
130 	{
131 		if (!dispenser[1].power)
132 		{
133 #ifdef DEBUG_TICKET
134 			logerror("PC: %04X  Ticket Power On\n", activecpu_get_pc());
135 #endif
136 			timer_adjust(dispenser[1].timer, TIME_IN_MSEC(time_msec), 1, 0);
137 			dispenser[1].power = 1;
138 
139 			dispenser[1].status = ticketnotdispensed;
140 		}
141 	}
142 	else
143 	{
144 		if (dispenser[1].power)
145 		{
146 #ifdef DEBUG_TICKET
147 			logerror("PC: %04X  Ticket Power Off\n", activecpu_get_pc());
148 #endif
149 			timer_adjust(dispenser[1].timer, TIME_NEVER, 1, 0);
150 			set_led_status(2,0);
151 			dispenser[1].power = 0;
152 		}
153 	}
154 }
155 
156 
157 /***************************************************************************
158   ticket_dispenser_toggle
159 
160   How I think this works:
161   When a ticket dispenses, there is N milliseconds of status = high,
162   and N milliseconds of status = low (a wait cycle?).
163 ***************************************************************************/
ticket_dispenser_toggle(int which)164 static void ticket_dispenser_toggle(int which)
165 {
166 	/* If we still have power, keep toggling ticket states. */
167 	if (dispenser[which].power)
168 	{
169 		dispenser[which].status ^= active_bit;
170 #ifdef DEBUG_TICKET
171 		logerror("Ticket Status Changed to %02X\n", status);
172 #endif
173 		timer_adjust(dispenser[which].timer, TIME_IN_MSEC(time_msec), which, 0);
174 	}
175 
176 	if (dispenser[which].status == ticketdispensed)
177 	{
178 		set_led_status(2,1);
179 		dispensed_tickets++;
180 
181 #ifdef DEBUG_TICKET
182 		logerror("Ticket Dispensed\n");
183 #endif
184 	}
185 	else
186 	{
187 		set_led_status(2,0);
188 	}
189 }
190