home *** CD-ROM | disk | FTP | other *** search
- /* interrupt.c */
-
- /* set up a CIA interrupt to play the music
- */
-
- /* $Author: Espie $
- * $Date: 91/05/20 22:44:37 $
- * $Revision: 1.32 $
- * $Log: interrupt.c,v $
- * Revision 1.32 91/05/20 22:44:37 Espie
- * *** empty log message ***
- *
- * Revision 1.31 91/05/16 15:05:08 Espie
- * Modified far stuff.
- *
- * Revision 1.30 91/05/12 19:55:31 Espie
- * correct handling of resume.
- *
- * Revision 1.29 91/05/12 15:59:08 Espie
- * Suppressed some unnecessary assignments... More cleanup in order.
- *
- * Revision 1.28 91/05/09 17:36:26 Espie
- * Support for non standard speed modes.
- *
- * Revision 1.27 91/05/08 15:51:18 Espie
- * Added set_volume command for slider.
- *
- * Revision 1.26 91/05/07 12:13:06 Espie
- * *** empty log message ***
- *
- * Revision 1.25 91/05/06 23:38:32 Espie
- * Changed some includes ???
- *
- * Revision 1.24 91/05/06 15:14:46 Espie
- * Speed is now entirely the responsibility of the player itself.
- *
- * Revision 1.23 91/05/05 19:05:38 Espie
- * Moved most of the player stuff which should be private
- * to the player itself.
- *
- * Revision 1.22 91/05/05 15:38:21 Espie
- * Play is now private/public...
- *
- * Revision 1.21 91/05/02 23:26:38 Espie
- * Almost tested, reliable. Needs some cleanup.
- *
- * Revision 1.20 91/05/02 11:19:22 Espie
- * Added some more tests... Not incredibly reliable.
- *
- * Revision 1.19 91/05/02 01:29:22 Espie
- * Completely new interface, much safer.
- * The hardware part is now completely isolated from the software part.
- *
- * Revision 1.18 91/04/30 00:35:35 Espie
- * Stable version III.
- *
- * Revision 1.17 91/04/30 00:24:28 Espie
- * Modified launch_play() slightly: now resets the speed.
- *
- * Revision 1.16 91/04/29 15:07:26 Espie
- * Cleaned-up, now allocates cia timer on the fly.
- * Important: always ask for audio first, because the system
- * avoids deadlock in that case.
- *
- * Revision 1.15 91/04/29 02:21:39 Espie
- * Suppressed ``critical sections''.
- *
- * Revision 1.14 91/04/28 20:34:43 Espie
- * Added fine speed control, definitely needs some cleanup now.
- *
- * Revision 1.13 91/04/27 20:48:26 Espie
- * New dual speed tempo.
- *
- * Revision 1.12 91/04/27 16:44:17 Espie
- * Slight changes.
- *
- * Revision 1.11 91/04/27 04:00:39 Espie
- * Little as changed.
- *
- * Revision 1.10 91/04/26 16:30:36 Espie
- * Now the interrupt routines times itself, so there
- * are new fields to set up correctly.
- *
- * Revision 1.9 91/04/24 15:25:35 Espie
- * Minor changes ??
- *
- * Revision 1.8 91/04/23 21:28:33 Espie
- * New interrupt settings: since the player knows when not to play anything,
- * it is no longer necessary to give a valid song to establish the interrupt.
- * Also, the memory for interrupt and play structure is now dynamically allocated
- * as public memory, which seems more reasonable.
- *
- * Revision 1.7 91/04/21 20:05:16 Espie
- * Oversampling.
- *
- * Revision 1.6 91/04/21 12:11:40 Espie
- * Stable version, known as bunch II.
- * Also features ``right'' log description.
- *
- * Revision 1.5 91/04/20 18:14:04 Espie
- * Added symbolic constants everywhere.
- *
- * Revision 1.4 91/04/19 13:21:27 Espie
- * New interrupt setup, still needs to dynamically allocate
- * interrupt structure, plus some symbolic constants.
- *
- * Revision 1.3 91/04/19 02:19:17 Espie
- * Still many things to do. Concept of a ``play'' structure working.
- * Timing ok.
- *
- * Revision 1.2 91/04/18 20:24:09 Espie
- * Complete interrupt driver, speed is correct (small bug in play.c),
- * setup is correct. Take care that you can't change is_Data after
- * you've added the server.
- *
- * Revision 1.1 91/04/18 16:38:05 Espie
- * Initial revision
- *
- */
-
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <hardware/cia.h>
- #include <custom/cleanup.h>
- #include <proto/exec.h>
- #include <proto/cia.h>
- #include <stdio.h>
- #include <dos/dos.h>
- #include <proto/exec.h>
- #include "song.h"
- #include "proto.h"
- #include "player.h"
- #include "public_play.h"
- #include "int_play.h"
-
- extern struct ExecBase *SysBase;
-
- #ifdef LATTICE
- #define FAR_SUPPORT __far
- #else
- #error
- #endif
- extern volatile struct CIA FAR_SUPPORT ciab;
-
- struct BattMemBase *BattMemBase;
- LOCAL CLEAN int_clean;
-
- /* this is the logical interface structure with the interrupt
- * you send things to the interrupt through its data structure (play).
- * If you specify it, the interrupt will signal you when something
- * interesting happens (specifiy a task/signal mask...)
- *
- * In that case, you can check the play oflags to know what triggered
- * the signal. Don't forget to reset it yourself if you want to know
- * what's going on next time. Also, don't forget that the interrupt
- * won't stop for you, i.e., while you're processing that signal,
- * the interrupt might send other signals to you.
- * As a general rule, unless you disable/enable, don't expect any
- * field in the play structure to stay constant. That's generally not
- * a problem.
- */
- LOCAL struct play *play;
- LOCAL struct pub_play *public;
- LOCAL struct priv_play *private;
- LOCAL struct Interrupt *timerinterrupt;
-
- LOCAL ULONG timerbase;
- LOCAL ULONG current_tempo = 256, current_effect = 256;
- LOCAL BOOL available = FALSE, running = FALSE;
-
-
- LOCAL void latch_tempo(void)
- {
- Disable();
- public->timebase = timerbase*current_tempo/128;
- public->effectbase = timerbase*current_effect/128;
- private->tempo_change = TRUE;
- Enable();
- }
-
-
- /* country dependency: the frequency of the timers is different
- * when you change countries. The precise values are listed
- * in the hardware manual.
- */
- LOCAL void set_timerbase(void)
- {
- switch(SysBase->PowerSupplyFrequency)
- {
- case 50:
- timerbase = 709379;
- break;
- case 60:
- timerbase = 715909;
- break;
- default:
- break;
- }
- }
-
-
- LOCAL void timer_on(void)
- {
- *private->control |= CIACRAF_START;
- }
-
-
- LOCAL void timer_off(void)
- {
- *private->control &= ~CIACRAF_START;
- }
-
-
- /* if you want to modify play yourself, don't forget to Disable()/Enable()
- * all the changes, so that the interrupt routine will always see something
- * coherent. Don't forget to make it fast
- */
-
- /* sine table for vibrato command */
-
- BYTE sine_table[32] =
- {0,25,49,71,90,106,117,125,127,125,117,106,90,
- 71,49,25,0,-25,-49,-71,-90,-106,-117,-125,-127,
- -125,-117,-106,-90,-71,-49,-25};
-
-
-
- LOCAL void init_structures()
- {
- int i;
- play = AllocMem(sizeof(struct play), MEMF_PUBLIC | MEMF_CLEAR);
- if (play)
- ToClean2(FreeMem, play, sizeof(struct play));
- else
- mayPanic("Could not allocate data structure for replay");
-
- public = &(play->public);
- private = &(play->private);
-
- for (i = 0; i < 32; i++)
- play->sine_table[i] = sine_table[i];
- private->sine_table = play->sine_table;
- for (i = 0; i < NUMBER_TUNING; i++)
- {
- play->period_table[i] = play->periods + NUMBER_NOTES * i;
- }
-
- init_periods(play->period_table);
- private->period_table = play->period_table;
- for (i = 0; i < NUMBER_TRACKS; i++)
- private->track[i] = play->tracks + i;
-
- private->channel_mask = play->channel_mask;
- private->setup = play->setup;
- private->state = init_player;
-
-
- /* don't need that */
- /* public->volume = 256;
- */
- public->command = STOP;
- /* done by the MEMF_CLEAR, but keep as comments that this is a good idea.
- public->resume = FALSE;
- public->info = NULL;
- */
-
-
- timerinterrupt = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR);
- if (timerinterrupt)
- ToClean2(FreeMem, timerinterrupt, sizeof(struct Interrupt));
- else
- mayPanic("Could not allocate interrupt structure");
-
- timerinterrupt->is_Node.ln_Type = NT_INTERRUPT;
- /* timerinterrupt->is_Node.ln_Pri = 0;
- */
- timerinterrupt->is_Node.ln_Name = "player";
- timerinterrupt->is_Data = play;
- timerinterrupt->is_Code = &do_play;
- }
-
- LOCAL void open_cia(void)
- {
- BattMemBase = OpenResource("ciab.resource");
- if (!BattMemBase)
- mayPanic("Could not open ciab resource");
- }
-
- LOCAL void init_interrupt(void)
- {
- int signal;
- set_timerbase();
- init_structures();
- open_cia();
- signal = AllocSignal(-1);
- if (signal == -1)
- mayPanic("No signals available");
- else
- ToClean(FreeSignal, signal);
- public->signal = 1<<signal;
- public->task = FindTask(0L);
- }
-
-
- /* the install timer now puts everything back in the
- * state it should be
- */
- LOCAL void install_timer(void)
- {
- int old;
- int_clean = AllocClean(NIL);
- old = AddICRVector(BattMemBase, CIAICRB_TB, timerinterrupt);
- if (!old)
- {
- ToClean3L(int_clean, RemICRVector, BattMemBase, CIAICRB_TB,
- timerinterrupt);
- private->control = &(ciab.ciacrb);
- private->latchlo = &(ciab.ciatblo);
- private->latchhi = &(ciab.ciatbhi);
- }
- else
- {
- old = AddICRVector(BattMemBase, CIAICRB_TA, timerinterrupt);
- if (!old)
- {
- ToClean3L(int_clean, RemICRVector, BattMemBase, CIAICRB_TA,
- timerinterrupt);
- private->control = &(ciab.ciacra);
- private->latchlo = &(ciab.ciatalo);
- private->latchhi = &(ciab.ciatahi);
- }
- else
- mayPanic("Sorry, no timer available");
- }
- ToClean0L(int_clean, timer_off);
- /* keep the alarm running */
- *private->control &= CIACRBF_ALARM;
- latch_tempo();
- }
-
-
- struct pub_play *obtain_player()
- {
- init_interrupt();
- return public;
- }
-
- void start_timer(void)
- {
- if (!available)
- {
- install_timer();
- timer_on();
- available = TRUE;
- }
- }
-
- void stop_timer(void)
- {
- if (available)
- {
- timer_off();
- CleanUp(int_clean);
- public->resume = TRUE;
- available = FALSE;
- }
- }
-
- /* ``standard'' frequency is 50Hz.
- * tempo is in 256th.
- */
- void set_tempo(int tempo, int effect)
- {
- current_tempo = tempo;
- current_effect = effect;
- if (available)
- latch_tempo();
- }
-
- void set_volume(int new_value)
- {
- public->volume = new_value;
- }
-
- void set_mode(int mode)
- {
- public->mode = mode;
- }
-
- void setup_song(struct song *s)
- {
- Disable();
- public->command = STOP;
- public->pattern = 0;
- public->position = 0;
- public->info = s->info;
- public->sample = s->samples;
- public->resume = FALSE;
- Enable();
- }
-
- void launch_play(int patt)
- {
- if (public->info)
- {
- Disable();
- public->command = NEWPOS;
- public->pattern = patt;
- public->position = 0;
- Enable();
- }
- }
-