Invaders game for the Gameduino

Dependencies:   Gameduino mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers utils.h Source File

utils.h

00001 #ifndef COM_ARTLUM_GDUTILS_INCLUDED
00002 #define COM_ARTLUM_GDUTILS_INCLUDED
00003 #include "arduino.h"
00004 #include "GD.h"
00005 //#include "WProgram.h"
00006 
00007 /*---------------------------------------------------
00008   Coprocessor controller - makes it easy to do
00009   raster effects (eg. split screens) without
00010   writing any FORTH.
00011   
00012   The way this works is that you build a list of
00013   instructions in memory (a "copperlist") and
00014   the coprocessor will execute the list on every
00015   video frame.
00016   
00017   Code samples:
00018   
00019   void setup() {
00020     ...
00021     // Make a copperlist to change a palette color on line 100
00022     // The copperlist is stored on the Gameduino at address 0x3f80
00023     Coprocessor::reset();
00024     CopperlistBuilder cp;
00025     cp.begin(0x3f80);
00026     cp.wait(100);
00027     cp.write16(PALETTE4A, 0x7fff);
00028     cp.end();  // And start using the new copperlist
00029   }
00030  
00031   Modifying an existing copperlist:
00032   
00033   // Make a copperlist to set the horizontal scroll register
00034   // on line 220 and modify the copperlist.
00035   // a) Build the list
00036   unsigned int XscrollInst;
00037   void setup() {
00038     ...
00039     CopperlistBuilder cp;
00040     cp.begin(0x3f80);
00041     cp.wait(220);
00042     XscrollInst = cp.position();    // Get current output location
00043     cp.write16(SCROLL_X, 0);
00044     cp.end();
00045   }
00046   // b) Modify the list with current 'xscroll'
00047   void loop() {
00048     CopperlistBuilder cp;
00049     cp.begin(XscrollInst)           // Where the 'write16()' instruction is
00050     cp.write16(SCROLL_X, xscroll);  // Overwrite the previous instruction
00051   }
00052 
00053   Notes: 
00054   The Coprocessor object uses the "COMM" block
00055   of memory at 0x2980 so don't mess with it.
00056 
00057   The coprocessor also provides support for the
00058   sound functions below.
00059 ---------------------------------------------------*/
00060 class Coprocessor {
00061 public:
00062   // This initializes everything and load the coprocessor code.
00063   // You should call this in your setup() function after "GD.begin();"
00064   //
00065   // The sample page is the page of Gameduino memory to
00066   // use as a buffer for sample playback. It *must* be
00067   // on a page boundry (ie. bottom 8 bits are 0) and
00068   // the whole page will be used so you can't use it
00069   // for anything else.
00070   static void reset(unsigned int samplePage=0x3f00);  // Default: Use memory from 0x3f00 to 0x3fff
00071   
00072   // Select a copperlist. The list will start running on the next video frame.
00073   // nb. The "CopperlistBuilder::end()" function normally calls this automatically
00074   // (unless you tell it not to...)
00075   static void setCopperlist(unsigned int addr);
00076   
00077   // Where the sample playback page is located
00078   static unsigned int samplePage();
00079 
00080   // Where the coprocessor is currently reading samples
00081   // from in the sample page. Use this info to keep the
00082   // page full of fresh sample data for playback
00083   static byte sampleReadPos();
00084 
00085   // A copy of the coprocessor YLINE register
00086   static int yline();
00087 };
00088 
00089 // This object helps you make a copperlist in memory
00090 class CopperlistBuilder {
00091   unsigned int out,start;
00092   void put(byte);
00093   void put16(unsigned int);
00094 public:
00095   // Available commands are:
00096   // * Wait for a raster line
00097   // * Write a byte to a memory location
00098   // * Write a 16-bit word to a memory location
00099   // * Copy a block of memory from one place to another
00100   void begin(unsigned int dest);
00101     void wait(int line);
00102     void write(unsigned int addr, byte val);
00103     void write16(unsigned int addr, unsigned int val);
00104     void copy(unsigned int src, unsigned int dst, unsigned int numBytes);
00105   void end(bool executeNow=true);
00106 
00107   // Where I'm currently outputting
00108   unsigned int position();
00109 };
00110 
00111 
00112 /*------------------------------------------------------------------
00113   Sound functions - play synthesized sounds and sound samples
00114   
00115   These functions require support from the Coprocessor object
00116   above. If you load different microcode they'll stop working...
00117 ------------------------------------------------------------------*/
00118 
00119 /*------------------------------------------------------------------
00120   Synthesized sounds
00121 ------------------------------------------------------------------*/
00122 #define SYNTHSOUNDS 0
00123 #if SYNTHSOUNDS
00124 // ADSR volume envelope
00125 struct ADSR {
00126   byte attack;      // Attack time (in clock ticks)
00127   byte decay;       // Decay time (in clock ticks)
00128   byte sustain;     // Sustain level [0..255]
00129   byte release;     // Release time (in clock ticks)
00130   ADSR(byte a=4, byte d=4, byte s=90, byte r=30);
00131   byte evaluate(unsigned int elapsedTime, unsigned int releaseTime);
00132 };
00133 
00134 // Change pitch of a sound as it plays
00135 struct PitchModulator {
00136   // Vibrato
00137   byte vibratoDelay;   // Delay before vibrato starts (in clock ticks)
00138   byte vibrato;        // Amount of vibrato (percentage of note pitch)
00139   char vibratoDelta;   // Added to 'vibrato' every clock tick 
00140   // Pitch Sweep
00141   byte sweepDelay;     // Delay before sweep starts (in clock ticks)
00142   byte sweep;
00143   char sweepDelta;
00144   PitchModulator() {
00145     vibratoDelay = 0;
00146     vibrato = 0;
00147     vibratoDelta = 0;
00148   }
00149   int evaluate(int startpitch, unsigned int time);
00150 };
00151 
00152 // All the parameters for a sound
00153 struct Sound {
00154   ADSR adsr;
00155   PitchModulator pm;
00156 };
00157 
00158 class SoundPlayer {
00159   // Playback parameters
00160   Sound sound;
00161   byte volume;
00162   unsigned int pitch;
00163   unsigned int duration;
00164   // Internal vars
00165   unsigned int ticks;
00166   bool active, releasing;
00167   // Sound players form a linked list
00168   bool isLinked;
00169   SoundPlayer *link;
00170   // The SoundPlayer is updated from SoundController
00171   void update();
00172   friend class SoundController;
00173   // You can't copy me...
00174   SoundPlayer(const SoundPlayer&);
00175   void operator=(const SoundPlayer&);
00176 public:
00177   SoundPlayer();
00178   
00179   // Set the sound parameters
00180   SoundPlayer& setSound(const Sound&);
00181 
00182   // Set playback volume in range [0..255], default = 255
00183   SoundPlayer& setVolume(byte);
00184  
00185   // Play a sound, pitch in Hz, duration in clock ticks.
00186   // If duration is 'infinite' then the sound plays until you call 'release()'
00187   // One "clock tick" is equivalent to one call to "SoundController::update()"
00188   enum { infinite=0x7fff };
00189   void play(unsigned int pitchHz, unsigned int duration=infinite);
00190   
00191   // Make the current sound enter the 'release' phase
00192   void release();
00193   
00194   // Stop sound playback immediately
00195   void stop();
00196 };
00197 #endif
00198 
00199 /*------------------------------------------------------------------
00200   Main sound controller object
00201 ------------------------------------------------------------------*/
00202 struct SoundController {
00203   // Reset all sounds, return to silence
00204   static void reset();
00205 
00206   // Update all sound - call this at least once every video frame.
00207   // The frequency at which you call this function is one "clock tick" for synthesised sounds
00208   static void update();
00209 
00210   // Play a sound sample from program memory
00211   // Samples are eight bits and will be played at
00212   // the system sample rate (see "Coprocessor").
00213   // if "numBytes" is negative, the sample will repeat until you play
00214   // another sample on the channel (eg. pass a null pointer to "playSample()"...)
00215   static void playSample(prog_char*, int numBytes, byte channel);
00216 };
00217 
00218 
00219 
00220 /*------------------------------------------------------------
00221   Useful little functions
00222 ------------------------------------------------------------*/
00223 // Show a number on screen
00224 void showNumber(int n, byte x, byte y);
00225 void showHexNumber(unsigned int n, byte x, byte y);
00226 
00227 // Send screenshot to serial port
00228 
00229 void sendScreenshot();
00230 
00231 // COM_ARTLUM_GDUTILS_INCLUDED
00232 #endif