Previous 15994 Revisions Next

r3249 Saturday 13th September, 2008 at 07:16:07 UTC by Fabio Priuli
[THOMSON] Updated drivers to use new cassette device implementation.
[src/mess/formats]thom_cas.c thom_cas.h
[src/mess/machine]thomson.c

src/mess/machine/thomson.c
r3248r3249
2121#include "devices/printer.h"
2222#include "includes/serial.h"
2323#include "devices/cassette.h"
24#include "formats/thom_cas.h"
2524#include "devices/thomflop.h"
2625#include "formats/thom_dsk.h"
2726
r3248r3249
3635#define PRINT(x) mame_printf_info x
3736
3837#define LOG(x)   do { if (VERBOSE) logerror x; } while (0)
38#define VLOG(x)   do { if (VERBOSE > 1) logerror x; } while (0)
3939#define LOG_IRQ(x) do { if (VERBOSE_IRQ) logerror x; } while (0)
4040#define LOG_KBD(x) do { if (VERBOSE_KBD) logerror x; } while (0)
4141#define LOG_BANK(x) do { if (VERBOSE_BANK) logerror x; } while (0)
r3248r3249
4343#define LOG_IO(x) do { if (VERBOSE_IO) logerror x; } while (0)
4444#define LOG_MIDI(x) do { if (VERBOSE_MIDI) logerror x; } while (0)
4545
46/* This set to 1 handle the .k7 files without passing through .wav */
47/* It must be set accordingly in formats/thom_cas.c */
48#define K7_SPEED_HACK 0
49
50/********************* common cassette code ***************************/
51
52INLINE const device_config* thom_cassette_img( running_machine *machine )
53{ return device_list_find_by_tag( machine->config->devicelist, CASSETTE, "cassette" ); }
54
55/*-------------- TO7 ------------*/
56
57
58/* On the TO7 & compatible (TO7/70,TO8,TO9, but not MO5,MO6), bits are coded
59   in FM format with a 1.1 ms period (900 bauds):
60   - 0 is 5 periods at 4.5 KHz
61   - 1 is 7 periods at 6.3 KHz
62
63   Moreover, a byte is represented using 11 bits:
64   - one 0 start bit
65   - eight data bits (low bit first)
66   - two 1 stop bits
67
68   There are also long (1 s) sequences of 1 bits to re-synchronize the
69   cassette at places the motor can be cut off and back on (e.g., between
70   files).
71
72   The computer outputs a modulated wave that is directly put on the cassette.
73   However, the input is demodulated by the cassette-reader before being
74   sent to the computer: we got 0 when the signal is around 4.5 KHz and
75   1 when the signal is around 6.3 KHz.
76*/
77
78#define TO7_BIT_LENGTH 0.001114
79
80/* buffer storing demodulated bits, only for k7 and with speed hack */
81static UINT32 to7_k7_bitsize;
82static UINT8* to7_k7_bits;
83
84
85/* 1-bit cassette input to the computer
86   inside the controller, two frequency filters (adjusted to 6.3 and 4.5 KHz)
87   and a comparator demodulate the raw signal into 0s and 1s.
88*/
89static int to7_get_cassette ( running_machine *machine )
90{
91   const device_config* img = thom_cassette_img(machine);
92
93   if ( image_exists( img ) )
94   {
95      cassette_image* cass = cassette_get_image( img );
96      cassette_state state = cassette_get_state( img );
97      double pos = cassette_get_position( img );
98      int bitpos = pos / TO7_BIT_LENGTH;
99
100      if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
101         return 1;
102
103      if ( K7_SPEED_HACK && to7_k7_bits )
104      {
105         /* hack, feed existing bits */
106         if ( bitpos >= to7_k7_bitsize )
107            bitpos = to7_k7_bitsize -1;
108         VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i\n",
109            activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos, bitpos,
110            to7_k7_bits[ bitpos ] ));
111         return to7_k7_bits[ bitpos ];
112      }
113      else
114      {
115         /* demodulate wave signal on-the-fly */
116         /* we simply count sign changes... */
117         int k, chg;
118         INT8 data[40];
119         cassette_get_samples( cass, 0, pos, TO7_BIT_LENGTH * 15. / 14., 40, 1, data, 0 );
120
121         for ( k = 1, chg = 0; k < 40; k++ )
122         {
123            if ( data[ k - 1 ] >= 0 && data[ k ] < 0 )
124               chg++;
125            if ( data[ k - 1 ] <= 0 && data[ k ] > 0 )
126               chg++;
127         }
128         k = ( chg >= 13 ) ? 1 : 0;
129         VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i (%i)\n",
130            activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos, bitpos,
131            k, chg ));
132         return k;
133      }
134
135   }
136   else
137      return 0;
138}
139
140
141
142/* 1-bit cassette output */
143static void to7_set_cassette ( running_machine *machine, int data )
144{
145   const device_config* img = thom_cassette_img(machine);
146   cassette_output( img, data ? 1. : -1. );
147}
148
149
150
151static WRITE8_HANDLER ( to7_set_cassette_motor )
152{
153   const device_config* img = thom_cassette_img(machine);
154   cassette_state state = cassette_get_state( img );
155   double pos = cassette_get_position(img);
156
157   LOG (( "$%04x %f to7_set_cassette_motor: cassette motor %s bitpos=%i\n",
158          activecpu_get_previouspc(), attotime_to_double(timer_get_time()), data ? "off" : "on",
159          (int) (pos / TO7_BIT_LENGTH) ));
160
161   if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED && !data && pos > 0.3 )
162   {
163      /* rewind a little before starting the motor */
164      cassette_seek( img, -0.3, SEEK_CUR );
165   }
166
167   cassette_change_state( img, data ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR );
168}
169
170
171
172/*-------------- MO5 ------------*/
173
174
175/* Each byte is represented as 8 bits without start or stop bit (unlike TO7).
176   Bits are coded in MFM, and the MFM signal is directly fed to the
177   computer which has to decode it in software (unlike TO7).
178   A 1 bit is one period at 1200 Hz; a 0 bit is one half-period at 600 Hz.
179   Bit-order is most significant bit first (unlike TO7).
180
181   Double-density MO6 cassettes follow the exact same mechanism, but with
182   at double frequency (perdiods at 2400 Hz, and half-perdios at 1200 Hz).
183*/
184
185
186#define MO5_BIT_LENGTH   0.000833
187#define MO5_HBIT_LENGTH (MO5_BIT_LENGTH / 2.)
188
189
190static int mo5_get_cassette ( running_machine *machine )
191{
192   const device_config* img = thom_cassette_img(machine);
193
194   if ( image_exists( img ) )
195   {
196      cassette_image* cass = cassette_get_image( img );
197      cassette_state state = cassette_get_state( img );
198      double pos = cassette_get_position( img );
199      INT32 hbit;
200
201      if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
202         return 1;
203
204      cassette_get_sample( cass, 0, pos, 0, &hbit );
205      hbit = hbit >= 0;
206
207      VLOG (( "$%04x %f mo5_get_cassette: state=$%X pos=%f hbitpos=%i hbit=%i\n",
208         activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos,
209         (int) (pos / MO5_HBIT_LENGTH), hbit ));
210      return hbit;
211   }
212   else
213      return 0;
214}
215
216
217
218static void mo5_set_cassette ( running_machine *machine, int data )
219{
220   const device_config* img = thom_cassette_img(machine);
221   cassette_output( img, data ? 1. : -1. );
222}
223
224
225
226static WRITE8_HANDLER ( mo5_set_cassette_motor )
227{
228   const device_config* img = thom_cassette_img(machine);
229   cassette_state state = cassette_get_state( img );
230   double pos = cassette_get_position(img);
231
232   LOG (( "$%04x %f mo5_set_cassette_motor: cassette motor %s hbitpos=%i\n",
233          activecpu_get_previouspc(), attotime_to_double(timer_get_time()), data ? "off" : "on",
234          (int) (pos / MO5_HBIT_LENGTH) ));
235
236   if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED &&  !data && pos > 0.3 )
237   {
238      /* rewind a little before starting the motor */
239      cassette_seek( img, -0.3, SEEK_CUR );
240   }
241
242   cassette_change_state( img, data ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR );
243}
244
245
246
247
46248/*************************** utilities ********************************/
47249
48250
r3248r3249
380582static READ8_HANDLER ( to7_timer_port_in )
381583{
382584   int lightpen = (input_port_read(machine, "lightpen_button") & 1) ? 2 : 0;
383   int cass = to7_get_cassette() ? 0x80 : 0;
585   int cass = to7_get_cassette(machine) ? 0x80 : 0;
384586   return lightpen | cass;
385587}
386588
r3248r3249
389591static WRITE8_HANDLER ( to7_timer_tco_out )
390592{
391593   /* 1-bit cassette output */
392   to7_set_cassette( data );
594   to7_set_cassette( machine, data );
393595}
394596
395597
r3248r3249
16421844
16431845static WRITE8_HANDLER ( mo5_sys_porta_out )
16441846{
1645   thom_set_mode_point( data & 1 );               /* bit 0: video bank switch */
1646   thom_set_border_color( (data >> 1) & 15 );     /* bit 1-4: border color */
1647   mo5_set_cassette( (data & 0x40) ? 1 : 0 );     /* bit 6: cassette output */
1847   thom_set_mode_point( data & 1 );                  /* bit 0: video bank switch */
1848   thom_set_border_color( (data >> 1) & 15 );            /* bit 1-4: border color */
1849   mo5_set_cassette( machine, (data & 0x40) ? 1 : 0 );      /* bit 6: cassette output */
16481850}
16491851
16501852
r3248r3249
16521854static READ8_HANDLER ( mo5_sys_porta_in )
16531855{
16541856   return
1655      (mo5_get_cassette() ? 0x80 : 0) |     /* bit 7: cassette input */
1857      (mo5_get_cassette(machine) ? 0x80 : 0) |     /* bit 7: cassette input */
16561858      ((input_port_read(machine, "lightpen_button") & 1) ? 0x20 : 0)
16571859      /* bit 5: lightpen button */;
16581860}
r3248r3249
37353937static READ8_HANDLER ( to8_timer_port_in )
37363938{
37373939   int lightpen = (input_port_read(machine, "lightpen_button") & 1) ? 2 : 0;
3738   int cass = to7_get_cassette() ? 0x80 : 0;
3940   int cass = to7_get_cassette(machine) ? 0x80 : 0;
37393941   int dtr = (centronics_read_handshake( 0 ) & CENTRONICS_NOT_BUSY) ? 0 : 0x40;
37403942   int lock = to8_kbd_caps ? 0 : 8; /* undocumented! */
37413943   return lightpen | cass | dtr | lock;
r3248r3249
39314133static READ8_HANDLER ( to9p_timer_port_in )
39324134{
39334135   int lightpen = (input_port_read(machine, "lightpen_button") & 1) ? 2 : 0;
3934   int cass = to7_get_cassette() ? 0x80 : 0;
4136   int cass = to7_get_cassette(machine) ? 0x80 : 0;
39354137   int dtr = (centronics_read_handshake( 0 ) & CENTRONICS_NOT_BUSY) ? 0 : 0x40;
39364138   return lightpen | cass | dtr;
39374139}
r3248r3249
43174519static READ8_HANDLER ( mo6_sys_porta_in )
43184520{
43194521   return
4320      (mo5_get_cassette() ? 0x80 : 0) |     /* bit 7: cassette input */
4522      (mo5_get_cassette(machine) ? 0x80 : 0) |     /* bit 7: cassette input */
43214523      8 |                                   /* bit 3: kbd-line float up to 1 */
43224524      ((input_port_read(machine, "lightpen_button") & 1) ? 2 : 0);
43234525   /* bit 1: lightpen button */;
r3248r3249
43474549
43484550static WRITE8_HANDLER ( mo6_sys_porta_out )
43494551{
4350   thom_set_mode_point( data & 1 );           /* bit 0: video bank switch */
4351   to7_game_mute = data & 4;                  /* bit 2: sound mute */
4352   thom_set_caps_led( (data & 16) ? 0 : 1 ) ; /* bit 4: keyboard led */
4353   mo5_set_cassette( (data & 0x40) ? 1 : 0 ); /* bit 6: cassette output */
4354   mo6_update_cart_bank(machine);                    /* bit 5: rom bank */
4552   thom_set_mode_point( data & 1 );                  /* bit 0: video bank switch */
4553   to7_game_mute = data & 4;                        /* bit 2: sound mute */
4554   thom_set_caps_led( (data & 16) ? 0 : 1 ) ;            /* bit 4: keyboard led */
4555   mo5_set_cassette( machine, (data & 0x40) ? 1 : 0 );      /* bit 6: cassette output */
4556   mo6_update_cart_bank(machine);                     /* bit 5: rom bank */
43554557   to7_game_sound_update();
43564558}
43574559
r3248r3249
47684970static WRITE8_HANDLER ( mo5nr_sys_porta_out )
47694971{
47704972   /* no keyboard LED */
4771   thom_set_mode_point( data & 1 );           /* bit 0: video bank switch */
4772   to7_game_mute = data & 4;                  /* bit 2: sound mute */
4773   mo5_set_cassette( (data & 0x40) ? 1 : 0 ); /* bit 6: cassette output */
4774   mo6_update_cart_bank(machine);                    /* bit 5: rom bank */
4973   thom_set_mode_point( data & 1 );                  /* bit 0: video bank switch */
4974   to7_game_mute = data & 4;                        /* bit 2: sound mute */
4975   mo5_set_cassette( machine, (data & 0x40) ? 1 : 0 );      /* bit 6: cassette output */
4976   mo6_update_cart_bank(machine);                     /* bit 5: rom bank */
47754977   to7_game_sound_update();
47764978}
47774979
src/mess/formats/thom_cas.h
r3248r3249
1414
1515/******************** TO7 ************************/
1616
17extern WRITE8_HANDLER ( to7_set_cassette_motor );
18
19/* 1-bit cassette input (demodulated) */
20extern int to7_get_cassette ( void );
21
22/* 1-bit cassette output (modulated) */
23extern void to7_set_cassette ( int i );
24
25CASSETTE_FORMATLIST_EXTERN( to7_cassette_formats );
26
2717extern const cassette_config to7_cassette_config;
2818
2919
3020/******************** MO5 ************************/
3121
32extern WRITE8_HANDLER ( mo5_set_cassette_motor );
33
34/* 1-bit cassette input  */
35extern int mo5_get_cassette ( void );
36
37/* 1-bit cassette output */
38extern void mo5_set_cassette ( int i );
39
40CASSETTE_FORMATLIST_EXTERN( mo5_cassette_formats );
41
4222extern const cassette_config mo5_cassette_config;
4323
4424#endif
src/mess/formats/thom_cas.c
r3248r3249
1717
1818/***************************** configuration **************************/
1919
20#define K7_SPEED_HACK 1
20#define K7_SPEED_HACK
2121/* When set to 1, bits extracted from k7 files are not transformed into a
2222   raw wave. It saves some time & memory but disables the ability to "hear" the
2323   cassette.
2424   This does not affect raw wave files.
2525   Also, we do not do this for k5 files because the the corresponding wave
26   files are more compact anyway.
27*/
26   files are more compact anyway. */
27/* It must be set accordingly in machine/thomson.c */
2828
2929#define VERBOSE 0 /* 0, 1 or 2 */
3030
3131
32
3332/***************************** utilities **************************/
3433
3534#define PRINT(x) mame_printf_info x
r3248r3249
3837#define VLOG(x)   do { if (VERBOSE > 1) logerror x; } while (0)
3938
4039
41
42/*************************** I / O **************************/
43
44
45INLINE const device_config* thom_cassette_img( void )
46{ return image_from_devtype_and_index(IO_CASSETTE, 0); }
47
48
49
50/*-------------- TO7 ------------*/
51
52
53/* On the TO7 & compatible (TO7/70,TO8,TO9, but not MO5,MO6), bits are coded
54   in FM format with a 1.1 ms period (900 bauds):
55   - 0 is 5 periods at 4.5 KHz
56   - 1 is 7 periods at 6.3 KHz
57
58   Moreover, a byte is represented using 11 bits:
59   - one 0 start bit
60   - eight data bits (low bit first)
61   - two 1 stop bits
62
63   There are also long (1 s) sequences of 1 bits to re-synchronize the
64   cassette at places the motor can be cut off and back on (e.g., between
65   files).
66
67   The computer outputs a modulated wave that is directly put on the cassette.
68   However, the input is demodulated by the cassette-reader before being
69   sent to the computer: we got 0 when the signal is around 4.5 KHz and
70   1 when the signal is around 6.3 KHz.
71*/
72
7340#define TO7_BIT_LENGTH 0.001114
7441
7542#define TO7_FREQ_CASS_0 4500.
r3248r3249
7845#define TO7_PERIOD_CASS_0 ( 1. / TO7_FREQ_CASS_0 )
7946#define TO7_PERIOD_CASS_1 ( 1. / TO7_FREQ_CASS_1 )
8047
81/* buffer storing demodulated bits, only for k7 and with speed hack */
8248static UINT32 to7_k7_bitsize;
8349static UINT8* to7_k7_bits;
8450
85
86/* 1-bit cassette input to the computer
87   inside the controller, two frequency filters (adjusted to 6.3 and 4.5 KHz)
88   and a comparator demodulate the raw signal into 0s and 1s.
89*/
90int to7_get_cassette ( void )
91{
92   const device_config* img = thom_cassette_img();
93
94   if ( image_exists( img ) )
95   {
96      cassette_image* cass = cassette_get_image( img );
97      cassette_state state = cassette_get_state( img );
98      double pos = cassette_get_position( img );
99      int bitpos = pos / TO7_BIT_LENGTH;
100
101      if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
102         return 1;
103
104      if ( K7_SPEED_HACK && to7_k7_bits )
105      {
106         /* hack, feed existing bits */
107         if ( bitpos >= to7_k7_bitsize )
108            bitpos = to7_k7_bitsize -1;
109         VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i\n",
110            activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos, bitpos,
111            to7_k7_bits[ bitpos ] ));
112         return to7_k7_bits[ bitpos ];
113      }
114      else
115      {
116         /* demodulate wave signal on-the-fly */
117         /* we simply count sign changes... */
118         int k, chg;
119         INT8 data[40];
120         cassette_get_samples( cass, 0, pos, TO7_BIT_LENGTH * 15. / 14., 40, 1, data, 0 );
121
122         for ( k = 1, chg = 0; k < 40; k++ )
123         {
124            if ( data[ k - 1 ] >= 0 && data[ k ] < 0 )
125               chg++;
126            if ( data[ k - 1 ] <= 0 && data[ k ] > 0 )
127               chg++;
128         }
129         k = ( chg >= 13 ) ? 1 : 0;
130         VLOG (( "$%04x %f to7_get_cassette: state=$%X pos=%f samppos=%i bit=%i (%i)\n",
131            activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos, bitpos,
132            k, chg ));
133         return k;
134      }
135
136   }
137   else
138      return 0;
139}
140
141
142
143/* 1-bit cassette output */
144void to7_set_cassette ( int data )
145{
146   const device_config* img = thom_cassette_img();
147   cassette_output( img, data ? 1. : -1. );
148}
149
150
151
152WRITE8_HANDLER ( to7_set_cassette_motor )
153{
154   const device_config* img = thom_cassette_img();
155   cassette_state state = cassette_get_state( img );
156   double pos = cassette_get_position(img);
157
158   LOG (( "$%04x %f to7_set_cassette_motor: cassette motor %s bitpos=%i\n",
159          activecpu_get_previouspc(), attotime_to_double(timer_get_time()), data ? "off" : "on",
160          (int) (pos / TO7_BIT_LENGTH) ));
161
162   if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED && !data && pos > 0.3 )
163   {
164      /* rewind a little before starting the motor */
165      cassette_seek( img, -0.3, SEEK_CUR );
166   }
167
168   cassette_change_state( img, data ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR );
169}
170
171
172
173/*-------------- MO5 ------------*/
174
175
176/* Each byte is represented as 8 bits without start or stop bit (unlike TO7).
177   Bits are coded in MFM, and the MFM signal is directly fed to the
178   computer which has to decode it in software (unlike TO7).
179   A 1 bit is one period at 1200 Hz; a 0 bit is one half-period at 600 Hz.
180   Bit-order is most significant bit first (unlike TO7).
181
182   Double-density MO6 cassettes follow the exact same mechanism, but with
183   at double frequency (perdiods at 2400 Hz, and half-perdios at 1200 Hz).
184*/
185
186
18751#define MO5_BIT_LENGTH   0.000833
18852#define MO5_HBIT_LENGTH (MO5_BIT_LENGTH / 2.)
18953
190
191int mo5_get_cassette ( void )
192{
193   const device_config* img = thom_cassette_img();
194
195   if ( image_exists( img ) )
196   {
197      cassette_image* cass = cassette_get_image( img );
198      cassette_state state = cassette_get_state( img );
199      double pos = cassette_get_position( img );
200      INT32 hbit;
201
202      if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED )
203         return 1;
204
205      cassette_get_sample( cass, 0, pos, 0, &hbit );
206      hbit = hbit >= 0;
207
208      VLOG (( "$%04x %f mo5_get_cassette: state=$%X pos=%f hbitpos=%i hbit=%i\n",
209         activecpu_get_previouspc(), attotime_to_double(timer_get_time()), state, pos,
210         (int) (pos / MO5_HBIT_LENGTH), hbit ));
211      return hbit;
212   }
213   else
214      return 0;
215}
216
217
218
219void mo5_set_cassette ( int data )
220{
221   const device_config* img = thom_cassette_img();
222   cassette_output( img, data ? 1. : -1. );
223}
224
225
226
227WRITE8_HANDLER ( mo5_set_cassette_motor )
228{
229   const device_config* img = thom_cassette_img();
230   cassette_state state = cassette_get_state( img );
231   double pos = cassette_get_position(img);
232
233   LOG (( "$%04x %f mo5_set_cassette_motor: cassette motor %s hbitpos=%i\n",
234          activecpu_get_previouspc(), attotime_to_double(timer_get_time()), data ? "off" : "on",
235          (int) (pos / MO5_HBIT_LENGTH) ));
236
237   if ( (state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_DISABLED &&  !data && pos > 0.3 )
238   {
239      /* rewind a little before starting the motor */
240      cassette_seek( img, -0.3, SEEK_CUR );
241   }
242
243   cassette_change_state( img, data ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR );
244}
245
246
247
24854/************************* k7 format *************************/
24955
25056/* The k7 format is widespread among existing Thomson emulators.

Previous 15994 Revisions Next


© 1998-2018 The MESS Team