summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/steppers.c
blob: c73b1f77bc2547ad4ffcacdbbbd03268e8d100b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
///////////////////////////////////////////////////////////////////////////
//                                                                       //
// steppers.c steppermotor emulation                                     //
//                                                                       //
// Emulates : 48 step motors driven with full step or half step          //
//            also emulates the index optic                              //
//                                                                       //
// 26-01-2007: J. Wallace - Rewritten to make it more flexible           //
//                          and to allow indices to be set in drivers    //
// 29-12-2006: J. Wallace - Added state save support                     //
// 05-03-2004: Re-Animator                                               //
//                                                                       //
// TODO:  add different types of stepper motors if needed                //
//        Convert the tables to something more like the real thing       //
//        someone who understands the device system may want to convert  //
//        this                                                           //
///////////////////////////////////////////////////////////////////////////

#include "emu.h"
#include "steppers.h"

/* local prototypes */

static void update_optic(int which);

/* local vars */

typedef struct _stepper
{
	const stepper_interface *intf;
	UINT8	 pattern,	/* coil pattern */
		 old_pattern,	/* old coil pattern */
		       phase,	/* motor phase */
				type;	/* reel type */
	INT16	step_pos,	/* step position 0 - max_steps */
			max_steps;	/* maximum step position */

	INT16 index_start,	/* start position of index (in half steps) */
			index_end,	/* end position of index (in half steps) */
			index_patt;	/* pattern needed on coils (0=don't care) */

	UINT8 optic;
} stepper;

static stepper step[MAX_STEPPERS];
/* step table, use active coils as row, phase as column */
static const int StarpointStepTab[8][16] =
{//   0000  0001  0010  0011  0100  0101  0110  0111  1000  1001  1010  1011  1100  1101  1110  1111    Phase
	{ 0,    0,    4,    0,    2,    1,    3,    0,   -2,   -1,   -3,   0,    0,    0,    0,    0   },// 0
	{ 0,   -1,    3,    0,    1,    0,    2,    0,   -3,   -2,    4,   0,    0,    0,    0,    0   },// 1
	{ 0,   -2,    2,    0,    0,   -1,    1,    0,    4,   -3,    3,   0,    0,    0,    0,    0   },// 2
	{ 0,   -3,    1,    0,   -1,   -2,    0,    0,    3,    4,    2,   0,    0,    0,    0,    0   },// 3
	{ 0,    4,    0,    0,   -2,   -3,   -1,    0,    2,    3,    1,   0,    0,    0,    0,    0   },// 4
	{ 0,    3,   -1,    0,   -3,   -4,   -2,    0,    1,    2,    0,   0,    0,    0,    0,    0   },// 5
	{ 0,    2,   -2,    0,    4,    3,   -3,    0,    0,    1,   -1,   0,    0,    0,    0,    0   },// 6
	{ 0,    1,   -3,    0,    3,    2,   -4,    0,   -1,    0,   -2,   0,    0,    0,    0,    0   },// 7
};

static const int MPU3StepTab[8][4] =
{//   00  01  10  11  Phase
	{ 2,  0,  0, -2, },// 0
	{ 0,  0,  0,  0, },// 1
	{ 0, -2, -2,  0, },// 2
	{ 0,  0,  0,  0, },// 3
	{-2,  0,  0,  2, },// 4
	{ 0,  0,  0,  0, },// 5
	{ 0,  2, -2,  0, },// 6
	{ 0,  0,  0,  0, },// 7
};

static const int BarcrestStepTab[8][16] =
{//   0000  0001  0010  0011  0100  0101  0110  0111  1000  1001  1010 1011  1100  1101  1110  1111     Phase
	{ 0,    1,    3,    2,   -3,    0,    0,    0,   -1,    0,    0,   0,   -2,    0,    0,    0   },// 0
	{ 0,    0,    2,    1,    0,    0,    3,    0,   -2,   -1,    0,   0,   -3,    0,    0,    0   },// 1
	{ 0,   -1,    1,    0,    3,    0,    2,    0,   -3,   -2,    0,   0,    0,    0,    0,    0   },// 2
	{ 0,   -2,    0,   -1,    2,    0,    1,    0,    0,   -3,    0,   0,    3,    0,    0,    0   },// 3
	{ 0,   -3,   -1,   -2,    1,    0,    0,    0,    3,    0,    0,   0,    2,    0,    0,    0   },// 4
	{ 0,    0,   -2,   -3,    0,    0,   -1,    0,    2,    3,    0,   0,    1,    0,    0,    0   },// 5
	{ 0,    3,   -3,    0,   -1,    0,   -2,    0,    0,    2,    0,   0,    0,    0,    0,    0   },// 6
	{ 0,    2,    0,    3,   -2,    0,   -3,    0,    0,    1,    0,   0,   -1,    0,    0,    0   },// 7
};

/* useful interfaces */

const stepper_interface starpoint_interface_48step =
{
	STARPOINT_48STEP_REEL,
	16,
	24,
	0x09
};

///////////////////////////////////////////////////////////////////////////
void stepper_config(running_machine *machine, int which, const stepper_interface *intf)
{
	assert_always(machine->phase() == MACHINE_PHASE_INIT, "Can only call stepper_config at init time!");
	assert_always((which >= 0) && (which < MAX_STEPPERS), "stepper_config called on an invalid stepper motor!");
	assert_always(intf, "stepper_config called with an invalid interface!");

	step[which].intf = intf;

	step[which].type = intf->type;
	step[which].index_start = intf->index_start;/* location of first index value in half steps */
	step[which].index_end	= intf->index_end;	/* location of last index value in half steps */
	step[which].index_patt	= intf->index_patt; /* hex value of coil pattern (0 if not needed)*/
	step[which].phase       = 0;
	step[which].pattern     = 0;
	step[which].old_pattern = 0;
	step[which].step_pos    = 0;

	switch ( step[which].type )
	{	default:
		case STARPOINT_48STEP_REEL:  /* STARPOINT RMxxx */
		case BARCREST_48STEP_REEL :  /* Barcrest Reel unit */
		case MPU3_48STEP_REEL :
		step[which].max_steps = (48*2);
		break;
		case STARPOINT_144STEPS_DICE :/* STARPOINT 1DCU DICE mechanism */
		step[which].max_steps = (144*2);
		break;
	}

	state_save_register_item(machine, "stepper", NULL, which, step[which].index_start);
	state_save_register_item(machine, "stepper", NULL, which, step[which].index_end);
	state_save_register_item(machine, "stepper", NULL, which, step[which].index_patt);
	state_save_register_item(machine, "stepper", NULL, which, step[which].phase);
	state_save_register_item(machine, "stepper", NULL, which, step[which].pattern);
	state_save_register_item(machine, "stepper", NULL, which, step[which].old_pattern);
	state_save_register_item(machine, "stepper", NULL, which, step[which].step_pos);
	state_save_register_item(machine, "stepper", NULL, which, step[which].max_steps);
	state_save_register_item(machine, "stepper", NULL, which, step[which].type);
}

///////////////////////////////////////////////////////////////////////////
int stepper_get_position(int which)
{
	return step[which].step_pos;
}

///////////////////////////////////////////////////////////////////////////

int stepper_get_max(int which)
{
	return step[which].max_steps;
}

///////////////////////////////////////////////////////////////////////////

static void update_optic(int which)
{
	int pos   = step[which].step_pos,
		start = step[which].index_start,
		end = step[which].index_end;

	if (start > end) // cope with index patterns that wrap around
	{
		if ( (( pos > start ) || ( pos < end )) &&
		( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
		( step[which].pattern == 0 &&
		(step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
		) ) )
		{
			step[which].optic = 1;
		}
		else step[which].optic = 0;
		}
	else
	{
		if ( (( pos > start ) && ( pos < end )) &&
		( ( step[which].pattern == step[which].index_patt || step[which].index_patt==0) ||
		( step[which].pattern == 0 &&
		(step[which].old_pattern == step[which].index_patt || step[which].index_patt==0)
		) ) )
		{
		step[which].optic = 1;
		}
		else step[which].optic = 0;
	}
}
///////////////////////////////////////////////////////////////////////////

void stepper_reset_position(int which)
{
	step[which].step_pos    = 0;
	step[which].pattern     = 0x00;
	step[which].old_pattern = 0x00;

	update_optic(which);
}

///////////////////////////////////////////////////////////////////////////

int stepper_optic_state(int which)
{
	int result = 0;

	if ( which < MAX_STEPPERS )
	{
		result = step[which].optic;
	}

	return result;
}

///////////////////////////////////////////////////////////////////////////

int stepper_update(int which, UINT8 pattern)
{
	int changed = 0;

	if ( step[which].pattern != pattern )
	{ /* pattern changed */
		int steps,
			pos;
		if ( step[which].pattern )
		{
			step[which].old_pattern = step[which].pattern;
		}
		step[which].phase =	(step[which].step_pos % 8);
		step[which].pattern = pattern;

//		index = (step[which].old_pattern << 4) | pattern;
		switch ( step[which].type )
		{
			default:
			case STARPOINT_48STEP_REEL :	/* STARPOINT RMxxx */
			case STARPOINT_144STEPS_DICE :  /* STARPOINT 1DCU DICE mechanism */
			steps = StarpointStepTab[step[which].phase][pattern];
			break;
			case BARCREST_48STEP_REEL :	    /* Barcrest reel units have different windings */
			steps = BarcrestStepTab[step[which].phase][pattern];
			break;
			case MPU3_48STEP_REEL :	    /* Same unit as above, but different interface (2 active lines, not 4)*/
			steps = MPU3StepTab[step[which].phase][pattern];
		}
		#if 0 /* Assists with new index generation */
		if ( which ==3 )logerror("which %d Index %d Steps %d Phase %d Pattern Old %02X New %02X\n",which,index,steps,(step[which].step_pos % 8),step[which].old_pattern,step[which].pattern);
		#endif

		if ( steps )
		{
			pos = step[which].step_pos + steps;
			if ( pos > step[which].max_steps ) pos -= step[which].max_steps;
			if ( pos < 0 )                 pos += step[which].max_steps;

			step[which].step_pos = pos;
			update_optic(which);

			changed++;
		}
	}
	return changed;
}