Previous 199869 Revisions Next

r23881 Sunday 23rd June, 2013 at 15:10:35 UTC by Fabio Priuli
Modernized phoenix custom sound device. [Osso]
[src/mame/audio]phoenix.c
[src/mame/drivers]phoenix.c
[src/mame/includes]phoenix.h

trunk/src/mame/drivers/phoenix.c
r23880r23881
3131
3232#include "emu.h"
3333#include "cpu/z80/z80.h"
34#include "sound/tms36xx.h"
3534#include "cpu/i8085/i8085.h"
3635#include "sound/ay8910.h"
3736#include "audio/pleiads.h"
r23880r23881
4342   AM_RANGE(0x4000, 0x4fff) AM_READ_BANK("bank1") AM_WRITE(phoenix_videoram_w) /* 2 pages selected by bit 0 of the video register */
4443   AM_RANGE(0x5000, 0x53ff) AM_WRITE(phoenix_videoreg_w)
4544   AM_RANGE(0x5800, 0x5bff) AM_WRITE(phoenix_scroll_w)
46   AM_RANGE(0x6000, 0x63ff) AM_DEVWRITE_LEGACY("cust", phoenix_sound_control_a_w)
47   AM_RANGE(0x6800, 0x6bff) AM_DEVWRITE_LEGACY("cust", phoenix_sound_control_b_w)
45   AM_RANGE(0x6000, 0x63ff) AM_DEVWRITE("cust", phoenix_sound_device, control_a_w)
46   AM_RANGE(0x6800, 0x6bff) AM_DEVWRITE("cust", phoenix_sound_device, control_b_w)
4847   AM_RANGE(0x7000, 0x73ff) AM_READ_PORT("IN0")                            /* IN0 or IN1 */
4948   AM_RANGE(0x7800, 0x7bff) AM_READ_PORT("DSW0")                           /* DSW */
5049ADDRESS_MAP_END
trunk/src/mame/audio/phoenix.c
r23880r23881
99
1010
1111#include "emu.h"
12#include "sound/tms36xx.h"
1312#include "includes/phoenix.h"
1413
1514/****************************************************************************
r23880r23881
4544#define VMIN    0
4645#define VMAX    32767
4746
48struct c_state
49{
50   INT32 counter;
51   INT32 level;
52};
5347
54struct n_state
48
49const device_type PHOENIX = &device_creator<phoenix_sound_device>;
50
51phoenix_sound_device::phoenix_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
52   : device_t(mconfig, PHOENIX, "Phoenix Custom", tag, owner, clock, "phoenix_sound", __FILE__),
53      device_sound_interface(mconfig, *this)
5554{
56   INT32 counter;
57   INT32 polyoffs;
58   INT32 polybit;
59   INT32 lowpass_counter;
60   INT32 lowpass_polybit;
61};
55}
6256
63struct phoenix_sound_state
57//-------------------------------------------------
58//  device_config_complete - perform any
59//  operations now that the configuration is
60//  complete
61//-------------------------------------------------
62
63void phoenix_sound_device::device_config_complete()
6464{
65   struct c_state      m_c24_state;
66   struct c_state      m_c25_state;
67   struct n_state      m_noise_state;
68   UINT8               m_sound_latch_a;
69   sound_stream *      m_channel;
70   UINT32 *                m_poly18;
71   device_t *m_discrete;
72   tms36xx_device *m_tms;
73};
65}
7466
75INLINE phoenix_sound_state *get_safe_token( device_t *device )
67//-------------------------------------------------
68//  device_start - device-specific startup
69//-------------------------------------------------
70
71void phoenix_sound_device::device_start()
7672{
77   assert(device != NULL);
78   assert(device->type() == PHOENIX);
73   int i, j;
74   UINT32 shiftreg;
7975
80   return (phoenix_sound_state *)downcast<phoenix_sound_device *>(device)->token();
76   m_sound_latch_a = 0;
77   memset(&m_c24_state, 0, sizeof(m_c24_state));
78   memset(&m_c25_state, 0, sizeof(m_c25_state));
79   memset(&m_noise_state, 0, sizeof(m_noise_state));
80
81   m_discrete = machine().device("discrete");
82   m_tms = machine().device<tms36xx_device>("tms");
83
84   m_poly18 = auto_alloc_array(machine(), UINT32, 1ul << (18-5));
85
86   shiftreg = 0;
87   for( i = 0; i < (1ul << (18-5)); i++ )
88   {
89      UINT32 bits = 0;
90      for( j = 0; j < 32; j++ )
91      {
92         bits = (bits >> 1) | (shiftreg << 31);
93         if( ((shiftreg >> 16) & 1) == ((shiftreg >> 17) & 1) )
94            shiftreg = (shiftreg << 1) | 1;
95         else
96            shiftreg <<= 1;
97      }
98      m_poly18[i] = bits;
99   }
100
101   m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this);
102
103   save_item(NAME(m_sound_latch_a));
104   save_item(NAME(m_c24_state.counter));
105   save_item(NAME(m_c24_state.level));
106   save_item(NAME(m_c25_state.counter));
107   save_item(NAME(m_c25_state.level));
108   save_item(NAME(m_noise_state.counter));
109   save_item(NAME(m_noise_state.polybit));
110   save_item(NAME(m_noise_state.polyoffs));
111   save_item(NAME(m_noise_state.lowpass_counter));
112   save_item(NAME(m_noise_state.lowpass_polybit));
113   save_pointer(NAME(m_poly18), (1ul << (18-5)));
81114}
82115
83INLINE int update_c24(phoenix_sound_state *state, int samplerate)
116int phoenix_sound_device::update_c24(int samplerate)
84117{
85118   /*
86119    * Noise frequency control (Port B):
r23880r23881
93126   #define R51 330
94127   #define R52 20000
95128
96   c_state *c24_state = &state->m_c24_state;
97
98   if( state->m_sound_latch_a & 0x40 )
129   if( m_sound_latch_a & 0x40 )
99130   {
100      if (c24_state->level > VMIN)
131      if (m_c24_state.level > VMIN)
101132      {
102         c24_state->counter -= (int)((c24_state->level - VMIN) / (R52 * C24));
103         if( c24_state->counter <= 0 )
133         m_c24_state.counter -= (int)((m_c24_state.level - VMIN) / (R52 * C24));
134         if( m_c24_state.counter <= 0 )
104135         {
105            int n = -c24_state->counter / samplerate + 1;
106            c24_state->counter += n * samplerate;
107            if( (c24_state->level -= n) < VMIN)
108               c24_state->level = VMIN;
136            int n = -m_c24_state.counter / samplerate + 1;
137            m_c24_state.counter += n * samplerate;
138            if( (m_c24_state.level -= n) < VMIN)
139               m_c24_state.level = VMIN;
109140         }
110141      }
111142   }
112143   else
113144   {
114      if (c24_state->level < VMAX)
145      if (m_c24_state.level < VMAX)
115146      {
116         c24_state->counter -= (int)((VMAX - c24_state->level) / ((R51+R49) * C24));
117         if( c24_state->counter <= 0 )
147         m_c24_state.counter -= (int)((VMAX - m_c24_state.level) / ((R51+R49) * C24));
148         if( m_c24_state.counter <= 0 )
118149         {
119            int n = -c24_state->counter / samplerate + 1;
120            c24_state->counter += n * samplerate;
121            if( (c24_state->level += n) > VMAX)
122               c24_state->level = VMAX;
150            int n = -m_c24_state.counter / samplerate + 1;
151            m_c24_state.counter += n * samplerate;
152            if( (m_c24_state.level += n) > VMAX)
153               m_c24_state.level = VMAX;
123154         }
124155      }
125156   }
126   return VMAX - c24_state->level;
157   return VMAX - m_c24_state.level;
127158}
128159
129INLINE int update_c25(phoenix_sound_state *state, int samplerate)
160int phoenix_sound_device::update_c25(int samplerate)
130161{
131162   /*
132163    * Bit 7 hi charges C25 (6.8u) over a R50 (1k) and R53 (330) and when
r23880r23881
138169   #define R53 330
139170   #define R54 47000
140171
141   c_state *c25_state = &state->m_c25_state;
142
143   if( state->m_sound_latch_a & 0x80 )
172   if( m_sound_latch_a & 0x80 )
144173   {
145      if (c25_state->level < VMAX)
174      if (m_c25_state.level < VMAX)
146175      {
147         c25_state->counter -= (int)((VMAX - c25_state->level) / ((R50+R53) * C25));
148         if( c25_state->counter <= 0 )
176         m_c25_state.counter -= (int)((VMAX - m_c25_state.level) / ((R50+R53) * C25));
177         if( m_c25_state.counter <= 0 )
149178         {
150            int n = -c25_state->counter / samplerate + 1;
151            c25_state->counter += n * samplerate;
152            if( (c25_state->level += n) > VMAX )
153               c25_state->level = VMAX;
179            int n = -m_c25_state.counter / samplerate + 1;
180            m_c25_state.counter += n * samplerate;
181            if( (m_c25_state.level += n) > VMAX )
182               m_c25_state.level = VMAX;
154183         }
155184      }
156185   }
157186   else
158187   {
159      if (c25_state->level > VMIN)
188      if (m_c25_state.level > VMIN)
160189      {
161         c25_state->counter -= (int)((c25_state->level - VMIN) / (R54 * C25));
162         if( c25_state->counter <= 0 )
190         m_c25_state.counter -= (int)((m_c25_state.level - VMIN) / (R54 * C25));
191         if( m_c25_state.counter <= 0 )
163192         {
164            int n = -c25_state->counter / samplerate + 1;
165            c25_state->counter += n * samplerate;
166            if( (c25_state->level -= n) < VMIN )
167               c25_state->level = VMIN;
193            int n = -m_c25_state.counter / samplerate + 1;
194            m_c25_state.counter += n * samplerate;
195            if( (m_c25_state.level -= n) < VMIN )
196               m_c25_state.level = VMIN;
168197         }
169198      }
170199   }
171   return c25_state->level;
200   return m_c25_state.level;
172201}
173202
174203
175INLINE int noise(phoenix_sound_state *state, int samplerate)
204int phoenix_sound_device::noise(int samplerate)
176205{
177   int vc24 = update_c24(state, samplerate);
178   int vc25 = update_c25(state, samplerate);
206   int vc24 = update_c24(samplerate);
207   int vc25 = update_c25(samplerate);
179208   int sum = 0, level, frequency;
180   n_state *noise_state = &state->m_noise_state;
181
209   
182210   /*
183211    * The voltage levels are added and control I(CE) of transistor TR1
184212    * (NPN) which then controls the noise clock frequency (linearily?).
r23880r23881
197225    * R71 (2700 Ohms) parallel to R73 (47k Ohms) = approx. 2553 Ohms
198226    * maxfreq = 1.44 / ((2553+2*1000) * 0.05e-6) = approx. 6325 Hz
199227    */
200   noise_state->counter -= frequency;
201   if( noise_state->counter <= 0 )
228   m_noise_state.counter -= frequency;
229   if( m_noise_state.counter <= 0 )
202230   {
203      int n = (-noise_state->counter / samplerate) + 1;
204      noise_state->counter += n * samplerate;
205      noise_state->polyoffs = (noise_state->polyoffs + n) & 0x3ffff;
206      noise_state->polybit = (state->m_poly18[noise_state->polyoffs>>5] >> (noise_state->polyoffs & 31)) & 1;
231      int n = (-m_noise_state.counter / samplerate) + 1;
232      m_noise_state.counter += n * samplerate;
233      m_noise_state.polyoffs = (m_noise_state.polyoffs + n) & 0x3ffff;
234      m_noise_state.polybit = (m_poly18[m_noise_state.polyoffs>>5] >> (m_noise_state.polyoffs & 31)) & 1;
207235   }
208   if (!noise_state->polybit)
236   if (!m_noise_state.polybit)
209237      sum += vc24;
210238
211239   /* 400Hz crude low pass filter: this is only a guess!! */
212   noise_state->lowpass_counter -= 400;
213   if( noise_state->lowpass_counter <= 0 )
240   m_noise_state.lowpass_counter -= 400;
241   if( m_noise_state.lowpass_counter <= 0 )
214242   {
215      noise_state->lowpass_counter += samplerate;
216      noise_state->lowpass_polybit = noise_state->polybit;
243      m_noise_state.lowpass_counter += samplerate;
244      m_noise_state.lowpass_polybit = m_noise_state.polybit;
217245   }
218   if (!noise_state->lowpass_polybit)
246   if (!m_noise_state.lowpass_polybit)
219247      sum += vc25;
220248
221249   return sum;
222250}
223251
224static STREAM_UPDATE( phoenix_sound_update )
225{
226   phoenix_sound_state *state = get_safe_token(device);
227   int samplerate = device->machine().sample_rate();
228   stream_sample_t *buffer = outputs[0];
229252
230   while( samples-- > 0 )
231   {
232      int sum = 0;
233      sum = noise(state, samplerate) / 2;
234      *buffer++ = sum < 32768 ? sum > -32768 ? sum : -32768 : 32767;
235   }
236}
237
238
239253/************************************************************************/
240254/* phoenix Sound System Analog emulation                                */
241255/*                                                                      */
r23880r23881
490504   DISCRETE_OUTPUT(NODE_90, 1)
491505DISCRETE_SOUND_END
492506
493WRITE8_DEVICE_HANDLER( phoenix_sound_control_a_w )
507WRITE8_MEMBER( phoenix_sound_device::control_a_w )
494508{
495   phoenix_sound_state *state = get_safe_token(device);
496
497   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_2_DATA, data & 0x0f);
498   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_2_FREQ, (data & 0x30) >> 4);
509   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_2_DATA, data & 0x0f);
510   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_2_FREQ, (data & 0x30) >> 4);
499511#if 0
500512   /* future handling of noise sounds */
501   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_3_EN  , data & 0x40);
502   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_4_EN  , data & 0x80);
513   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_3_EN  , data & 0x40);
514   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_4_EN  , data & 0x80);
503515#endif
504   state->m_channel->update();
505   state->m_sound_latch_a = data;
516   m_channel->update();
517   m_sound_latch_a = data;
506518}
507519
508static void register_state(device_t *device)
520WRITE8_MEMBER( phoenix_sound_device::control_b_w )
509521{
510   phoenix_sound_state *state = get_safe_token(device);
522   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_1_DATA, data & 0x0f);
523   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_1_FILT, data & 0x20);
524   discrete_sound_w(m_discrete, space, PHOENIX_EFFECT_1_FREQ, data & 0x10);
511525
512   device->save_item(NAME(state->m_sound_latch_a));
513   device->save_item(NAME(state->m_c24_state.counter));
514   device->save_item(NAME(state->m_c24_state.level));
515   device->save_item(NAME(state->m_c25_state.counter));
516   device->save_item(NAME(state->m_c25_state.level));
517   device->save_item(NAME(state->m_noise_state.counter));
518   device->save_item(NAME(state->m_noise_state.polybit));
519   device->save_item(NAME(state->m_noise_state.polyoffs));
520   device->save_item(NAME(state->m_noise_state.lowpass_counter));
521   device->save_item(NAME(state->m_noise_state.lowpass_polybit));
522   device->save_pointer(NAME(state->m_poly18), (1ul << (18-5)));
523}
524
525WRITE8_DEVICE_HANDLER( phoenix_sound_control_b_w )
526{
527   phoenix_sound_state *state = get_safe_token(device);
528
529   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_1_DATA, data & 0x0f);
530   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_1_FILT, data & 0x20);
531   discrete_sound_w(state->m_discrete, space, PHOENIX_EFFECT_1_FREQ, data & 0x10);
532
533526   /* update the tune that the MM6221AA is playing */
534   state->m_tms->mm6221aa_tune_w(data >> 6);
527   m_tms->mm6221aa_tune_w(data >> 6);
535528}
536529
537static DEVICE_START( phoenix_sound )
538{
539   phoenix_sound_state *state = get_safe_token(device);
540   int i, j;
541   UINT32 shiftreg;
542530
543   state->m_sound_latch_a = 0;
544   memset(&state->m_c24_state, 0, sizeof(state->m_c24_state));
545   memset(&state->m_c25_state, 0, sizeof(state->m_c25_state));
546   memset(&state->m_noise_state, 0, sizeof(state->m_noise_state));
547
548   state->m_discrete = device->machine().device("discrete");
549   state->m_tms = device->machine().device<tms36xx_device>("tms");
550
551   state->m_poly18 = auto_alloc_array(device->machine(), UINT32, 1ul << (18-5));
552
553   shiftreg = 0;
554   for( i = 0; i < (1ul << (18-5)); i++ )
555   {
556      UINT32 bits = 0;
557      for( j = 0; j < 32; j++ )
558      {
559         bits = (bits >> 1) | (shiftreg << 31);
560         if( ((shiftreg >> 16) & 1) == ((shiftreg >> 17) & 1) )
561            shiftreg = (shiftreg << 1) | 1;
562         else
563            shiftreg <<= 1;
564      }
565      state->m_poly18[i] = bits;
566   }
567
568   state->m_channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), 0, phoenix_sound_update);
569
570   register_state(device);
571}
572
573const device_type PHOENIX = &device_creator<phoenix_sound_device>;
574
575phoenix_sound_device::phoenix_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
576   : device_t(mconfig, PHOENIX, "Phoenix Custom", tag, owner, clock, "phoenix_sound", __FILE__),
577      device_sound_interface(mconfig, *this)
578{
579   m_token = global_alloc_clear(phoenix_sound_state);
580}
581
582531//-------------------------------------------------
583//  device_config_complete - perform any
584//  operations now that the configuration is
585//  complete
586//-------------------------------------------------
587
588void phoenix_sound_device::device_config_complete()
589{
590}
591
592//-------------------------------------------------
593//  device_start - device-specific startup
594//-------------------------------------------------
595
596void phoenix_sound_device::device_start()
597{
598   DEVICE_START_NAME( phoenix_sound )(this);
599}
600
601//-------------------------------------------------
602532//  sound_stream_update - handle a stream update
603533//-------------------------------------------------
604534
605535void phoenix_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
606536{
607   // should never get here
608   fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
537   int samplerate = machine().sample_rate();
538   stream_sample_t *buffer = outputs[0];
539
540   while( samples-- > 0 )
541   {
542      int sum = 0;
543      sum = noise(samplerate) / 2;
544      *buffer++ = sum < 32768 ? sum > -32768 ? sum : -32768 : 32767;
545   }
609546}
trunk/src/mame/includes/phoenix.h
r23880r23881
1#include "devlegcy.h"
21#include "devcb.h"
32#include "sound/discrete.h"
3#include "sound/tms36xx.h"
44
5
65class phoenix_state : public driver_device
76{
87public:
r23880r23881
5857
5958/*----------- defined in audio/phoenix.c -----------*/
6059
61DISCRETE_SOUND_EXTERN( phoenix );
60struct c_state
61{
62   INT32 counter;
63   INT32 level;
64};
6265
63DECLARE_WRITE8_DEVICE_HANDLER( phoenix_sound_control_a_w );
64DECLARE_WRITE8_DEVICE_HANDLER( phoenix_sound_control_b_w );
66struct n_state
67{
68   INT32 counter;
69   INT32 polyoffs;
70   INT32 polybit;
71   INT32 lowpass_counter;
72   INT32 lowpass_polybit;
73};
6574
6675class phoenix_sound_device : public device_t,
6776                           public device_sound_interface
6877{
6978public:
7079   phoenix_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
71   ~phoenix_sound_device() { global_free(m_token); }
80   ~phoenix_sound_device() {}
7281
73   // access to legacy token
74   void *token() const { assert(m_token != NULL); return m_token; }
82   DECLARE_WRITE8_MEMBER( control_a_w );
83   DECLARE_WRITE8_MEMBER( control_b_w );
84
7585protected:
7686   // device-level overrides
7787   virtual void device_config_complete();
r23880r23881
8191   virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
8292private:
8393   // internal state
84   void *m_token;
94   struct c_state      m_c24_state;
95   struct c_state      m_c25_state;
96   struct n_state      m_noise_state;
97   UINT8               m_sound_latch_a;
98   sound_stream *      m_channel;
99   UINT32 *                m_poly18;
100   device_t *m_discrete;
101   tms36xx_device *m_tms;
102   
103   int update_c24(int samplerate);
104   int update_c25(int samplerate);
105   int noise(int samplerate);
85106};
86107
87108extern const device_type PHOENIX;
109
110DISCRETE_SOUND_EXTERN( phoenix );

Previous 199869 Revisions Next


© 1997-2024 The MAME Team