Space invaders with a nRF2401A wireless joypad

Dependencies:   Gameduino mbed nRF2401A

Fork of Gameduino_Invaders_game by Chris Dick

Gameduino and an nRF2401A hooked up to an mbed on an mbeduino:

/media/uploads/TheChrisyd/2014-03-08_22.53.54.jpg

Committer:
TheChrisyd
Date:
Thu Jun 21 19:13:34 2012 +0000
Revision:
0:8a7c58553b44
Child:
1:f44175dd69fd
backup before adding more features

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TheChrisyd 0:8a7c58553b44 1 #ifndef COM_ARTLUM_GDUTILS_INCLUDED
TheChrisyd 0:8a7c58553b44 2 #define COM_ARTLUM_GDUTILS_INCLUDED
TheChrisyd 0:8a7c58553b44 3 #include "arduino.h"
TheChrisyd 0:8a7c58553b44 4 #include "GD.h"
TheChrisyd 0:8a7c58553b44 5 //#include "WProgram.h"
TheChrisyd 0:8a7c58553b44 6
TheChrisyd 0:8a7c58553b44 7 /*---------------------------------------------------
TheChrisyd 0:8a7c58553b44 8 Coprocessor controller - makes it easy to do
TheChrisyd 0:8a7c58553b44 9 raster effects (eg. split screens) without
TheChrisyd 0:8a7c58553b44 10 writing any FORTH.
TheChrisyd 0:8a7c58553b44 11
TheChrisyd 0:8a7c58553b44 12 The way this works is that you build a list of
TheChrisyd 0:8a7c58553b44 13 instructions in memory (a "copperlist") and
TheChrisyd 0:8a7c58553b44 14 the coprocessor will execute the list on every
TheChrisyd 0:8a7c58553b44 15 video frame.
TheChrisyd 0:8a7c58553b44 16
TheChrisyd 0:8a7c58553b44 17 Code samples:
TheChrisyd 0:8a7c58553b44 18
TheChrisyd 0:8a7c58553b44 19 void setup() {
TheChrisyd 0:8a7c58553b44 20 ...
TheChrisyd 0:8a7c58553b44 21 // Make a copperlist to change a palette color on line 100
TheChrisyd 0:8a7c58553b44 22 // The copperlist is stored on the Gameduino at address 0x3f80
TheChrisyd 0:8a7c58553b44 23 Coprocessor::reset();
TheChrisyd 0:8a7c58553b44 24 CopperlistBuilder cp;
TheChrisyd 0:8a7c58553b44 25 cp.begin(0x3f80);
TheChrisyd 0:8a7c58553b44 26 cp.wait(100);
TheChrisyd 0:8a7c58553b44 27 cp.write16(PALETTE4A, 0x7fff);
TheChrisyd 0:8a7c58553b44 28 cp.end(); // And start using the new copperlist
TheChrisyd 0:8a7c58553b44 29 }
TheChrisyd 0:8a7c58553b44 30
TheChrisyd 0:8a7c58553b44 31 Modifying an existing copperlist:
TheChrisyd 0:8a7c58553b44 32
TheChrisyd 0:8a7c58553b44 33 // Make a copperlist to set the horizontal scroll register
TheChrisyd 0:8a7c58553b44 34 // on line 220 and modify the copperlist.
TheChrisyd 0:8a7c58553b44 35 // a) Build the list
TheChrisyd 0:8a7c58553b44 36 unsigned int XscrollInst;
TheChrisyd 0:8a7c58553b44 37 void setup() {
TheChrisyd 0:8a7c58553b44 38 ...
TheChrisyd 0:8a7c58553b44 39 CopperlistBuilder cp;
TheChrisyd 0:8a7c58553b44 40 cp.begin(0x3f80);
TheChrisyd 0:8a7c58553b44 41 cp.wait(220);
TheChrisyd 0:8a7c58553b44 42 XscrollInst = cp.position(); // Get current output location
TheChrisyd 0:8a7c58553b44 43 cp.write16(SCROLL_X, 0);
TheChrisyd 0:8a7c58553b44 44 cp.end();
TheChrisyd 0:8a7c58553b44 45 }
TheChrisyd 0:8a7c58553b44 46 // b) Modify the list with current 'xscroll'
TheChrisyd 0:8a7c58553b44 47 void loop() {
TheChrisyd 0:8a7c58553b44 48 CopperlistBuilder cp;
TheChrisyd 0:8a7c58553b44 49 cp.begin(XscrollInst) // Where the 'write16()' instruction is
TheChrisyd 0:8a7c58553b44 50 cp.write16(SCROLL_X, xscroll); // Overwrite the previous instruction
TheChrisyd 0:8a7c58553b44 51 }
TheChrisyd 0:8a7c58553b44 52
TheChrisyd 0:8a7c58553b44 53 Notes:
TheChrisyd 0:8a7c58553b44 54 The Coprocessor object uses the "COMM" block
TheChrisyd 0:8a7c58553b44 55 of memory at 0x2980 so don't mess with it.
TheChrisyd 0:8a7c58553b44 56
TheChrisyd 0:8a7c58553b44 57 The coprocessor also provides support for the
TheChrisyd 0:8a7c58553b44 58 sound functions below.
TheChrisyd 0:8a7c58553b44 59 ---------------------------------------------------*/
TheChrisyd 0:8a7c58553b44 60 class Coprocessor {
TheChrisyd 0:8a7c58553b44 61 public:
TheChrisyd 0:8a7c58553b44 62 // This initializes everything and load the coprocessor code.
TheChrisyd 0:8a7c58553b44 63 // You should call this in your setup() function after "GD.begin();"
TheChrisyd 0:8a7c58553b44 64 //
TheChrisyd 0:8a7c58553b44 65 // The sample page is the page of Gameduino memory to
TheChrisyd 0:8a7c58553b44 66 // use as a buffer for sample playback. It *must* be
TheChrisyd 0:8a7c58553b44 67 // on a page boundry (ie. bottom 8 bits are 0) and
TheChrisyd 0:8a7c58553b44 68 // the whole page will be used so you can't use it
TheChrisyd 0:8a7c58553b44 69 // for anything else.
TheChrisyd 0:8a7c58553b44 70 static void reset(unsigned int samplePage=0x3f00); // Default: Use memory from 0x3f00 to 0x3fff
TheChrisyd 0:8a7c58553b44 71
TheChrisyd 0:8a7c58553b44 72 // Select a copperlist. The list will start running on the next video frame.
TheChrisyd 0:8a7c58553b44 73 // nb. The "CopperlistBuilder::end()" function normally calls this automatically
TheChrisyd 0:8a7c58553b44 74 // (unless you tell it not to...)
TheChrisyd 0:8a7c58553b44 75 static void setCopperlist(unsigned int addr);
TheChrisyd 0:8a7c58553b44 76
TheChrisyd 0:8a7c58553b44 77 // Where the sample playback page is located
TheChrisyd 0:8a7c58553b44 78 static unsigned int samplePage();
TheChrisyd 0:8a7c58553b44 79
TheChrisyd 0:8a7c58553b44 80 // Where the coprocessor is currently reading samples
TheChrisyd 0:8a7c58553b44 81 // from in the sample page. Use this info to keep the
TheChrisyd 0:8a7c58553b44 82 // page full of fresh sample data for playback
TheChrisyd 0:8a7c58553b44 83 static byte sampleReadPos();
TheChrisyd 0:8a7c58553b44 84
TheChrisyd 0:8a7c58553b44 85 // A copy of the coprocessor YLINE register
TheChrisyd 0:8a7c58553b44 86 static int yline();
TheChrisyd 0:8a7c58553b44 87 };
TheChrisyd 0:8a7c58553b44 88
TheChrisyd 0:8a7c58553b44 89 // This object helps you make a copperlist in memory
TheChrisyd 0:8a7c58553b44 90 class CopperlistBuilder {
TheChrisyd 0:8a7c58553b44 91 unsigned int out,start;
TheChrisyd 0:8a7c58553b44 92 void put(byte);
TheChrisyd 0:8a7c58553b44 93 void put16(unsigned int);
TheChrisyd 0:8a7c58553b44 94 public:
TheChrisyd 0:8a7c58553b44 95 // Available commands are:
TheChrisyd 0:8a7c58553b44 96 // * Wait for a raster line
TheChrisyd 0:8a7c58553b44 97 // * Write a byte to a memory location
TheChrisyd 0:8a7c58553b44 98 // * Write a 16-bit word to a memory location
TheChrisyd 0:8a7c58553b44 99 // * Copy a block of memory from one place to another
TheChrisyd 0:8a7c58553b44 100 void begin(unsigned int dest);
TheChrisyd 0:8a7c58553b44 101 void wait(int line);
TheChrisyd 0:8a7c58553b44 102 void write(unsigned int addr, byte val);
TheChrisyd 0:8a7c58553b44 103 void write16(unsigned int addr, unsigned int val);
TheChrisyd 0:8a7c58553b44 104 void copy(unsigned int src, unsigned int dst, unsigned int numBytes);
TheChrisyd 0:8a7c58553b44 105 void end(bool executeNow=true);
TheChrisyd 0:8a7c58553b44 106
TheChrisyd 0:8a7c58553b44 107 // Where I'm currently outputting
TheChrisyd 0:8a7c58553b44 108 unsigned int position();
TheChrisyd 0:8a7c58553b44 109 };
TheChrisyd 0:8a7c58553b44 110
TheChrisyd 0:8a7c58553b44 111
TheChrisyd 0:8a7c58553b44 112 /*------------------------------------------------------------------
TheChrisyd 0:8a7c58553b44 113 Sound functions - play synthesized sounds and sound samples
TheChrisyd 0:8a7c58553b44 114
TheChrisyd 0:8a7c58553b44 115 These functions require support from the Coprocessor object
TheChrisyd 0:8a7c58553b44 116 above. If you load different microcode they'll stop working...
TheChrisyd 0:8a7c58553b44 117 ------------------------------------------------------------------*/
TheChrisyd 0:8a7c58553b44 118
TheChrisyd 0:8a7c58553b44 119 /*------------------------------------------------------------------
TheChrisyd 0:8a7c58553b44 120 Synthesized sounds
TheChrisyd 0:8a7c58553b44 121 ------------------------------------------------------------------*/
TheChrisyd 0:8a7c58553b44 122 #define SYNTHSOUNDS 0
TheChrisyd 0:8a7c58553b44 123 #if SYNTHSOUNDS
TheChrisyd 0:8a7c58553b44 124 // ADSR volume envelope
TheChrisyd 0:8a7c58553b44 125 struct ADSR {
TheChrisyd 0:8a7c58553b44 126 byte attack; // Attack time (in clock ticks)
TheChrisyd 0:8a7c58553b44 127 byte decay; // Decay time (in clock ticks)
TheChrisyd 0:8a7c58553b44 128 byte sustain; // Sustain level [0..255]
TheChrisyd 0:8a7c58553b44 129 byte release; // Release time (in clock ticks)
TheChrisyd 0:8a7c58553b44 130 ADSR(byte a=4, byte d=4, byte s=90, byte r=30);
TheChrisyd 0:8a7c58553b44 131 byte evaluate(unsigned int elapsedTime, unsigned int releaseTime);
TheChrisyd 0:8a7c58553b44 132 };
TheChrisyd 0:8a7c58553b44 133
TheChrisyd 0:8a7c58553b44 134 // Change pitch of a sound as it plays
TheChrisyd 0:8a7c58553b44 135 struct PitchModulator {
TheChrisyd 0:8a7c58553b44 136 // Vibrato
TheChrisyd 0:8a7c58553b44 137 byte vibratoDelay; // Delay before vibrato starts (in clock ticks)
TheChrisyd 0:8a7c58553b44 138 byte vibrato; // Amount of vibrato (percentage of note pitch)
TheChrisyd 0:8a7c58553b44 139 char vibratoDelta; // Added to 'vibrato' every clock tick
TheChrisyd 0:8a7c58553b44 140 // Pitch Sweep
TheChrisyd 0:8a7c58553b44 141 byte sweepDelay; // Delay before sweep starts (in clock ticks)
TheChrisyd 0:8a7c58553b44 142 byte sweep;
TheChrisyd 0:8a7c58553b44 143 char sweepDelta;
TheChrisyd 0:8a7c58553b44 144 PitchModulator() {
TheChrisyd 0:8a7c58553b44 145 vibratoDelay = 0;
TheChrisyd 0:8a7c58553b44 146 vibrato = 0;
TheChrisyd 0:8a7c58553b44 147 vibratoDelta = 0;
TheChrisyd 0:8a7c58553b44 148 }
TheChrisyd 0:8a7c58553b44 149 int evaluate(int startpitch, unsigned int time);
TheChrisyd 0:8a7c58553b44 150 };
TheChrisyd 0:8a7c58553b44 151
TheChrisyd 0:8a7c58553b44 152 // All the parameters for a sound
TheChrisyd 0:8a7c58553b44 153 struct Sound {
TheChrisyd 0:8a7c58553b44 154 ADSR adsr;
TheChrisyd 0:8a7c58553b44 155 PitchModulator pm;
TheChrisyd 0:8a7c58553b44 156 };
TheChrisyd 0:8a7c58553b44 157
TheChrisyd 0:8a7c58553b44 158 class SoundPlayer {
TheChrisyd 0:8a7c58553b44 159 // Playback parameters
TheChrisyd 0:8a7c58553b44 160 Sound sound;
TheChrisyd 0:8a7c58553b44 161 byte volume;
TheChrisyd 0:8a7c58553b44 162 unsigned int pitch;
TheChrisyd 0:8a7c58553b44 163 unsigned int duration;
TheChrisyd 0:8a7c58553b44 164 // Internal vars
TheChrisyd 0:8a7c58553b44 165 unsigned int ticks;
TheChrisyd 0:8a7c58553b44 166 bool active, releasing;
TheChrisyd 0:8a7c58553b44 167 // Sound players form a linked list
TheChrisyd 0:8a7c58553b44 168 bool isLinked;
TheChrisyd 0:8a7c58553b44 169 SoundPlayer *link;
TheChrisyd 0:8a7c58553b44 170 // The SoundPlayer is updated from SoundController
TheChrisyd 0:8a7c58553b44 171 void update();
TheChrisyd 0:8a7c58553b44 172 friend class SoundController;
TheChrisyd 0:8a7c58553b44 173 // You can't copy me...
TheChrisyd 0:8a7c58553b44 174 SoundPlayer(const SoundPlayer&);
TheChrisyd 0:8a7c58553b44 175 void operator=(const SoundPlayer&);
TheChrisyd 0:8a7c58553b44 176 public:
TheChrisyd 0:8a7c58553b44 177 SoundPlayer();
TheChrisyd 0:8a7c58553b44 178
TheChrisyd 0:8a7c58553b44 179 // Set the sound parameters
TheChrisyd 0:8a7c58553b44 180 SoundPlayer& setSound(const Sound&);
TheChrisyd 0:8a7c58553b44 181
TheChrisyd 0:8a7c58553b44 182 // Set playback volume in range [0..255], default = 255
TheChrisyd 0:8a7c58553b44 183 SoundPlayer& setVolume(byte);
TheChrisyd 0:8a7c58553b44 184
TheChrisyd 0:8a7c58553b44 185 // Play a sound, pitch in Hz, duration in clock ticks.
TheChrisyd 0:8a7c58553b44 186 // If duration is 'infinite' then the sound plays until you call 'release()'
TheChrisyd 0:8a7c58553b44 187 // One "clock tick" is equivalent to one call to "SoundController::update()"
TheChrisyd 0:8a7c58553b44 188 enum { infinite=0x7fff };
TheChrisyd 0:8a7c58553b44 189 void play(unsigned int pitchHz, unsigned int duration=infinite);
TheChrisyd 0:8a7c58553b44 190
TheChrisyd 0:8a7c58553b44 191 // Make the current sound enter the 'release' phase
TheChrisyd 0:8a7c58553b44 192 void release();
TheChrisyd 0:8a7c58553b44 193
TheChrisyd 0:8a7c58553b44 194 // Stop sound playback immediately
TheChrisyd 0:8a7c58553b44 195 void stop();
TheChrisyd 0:8a7c58553b44 196 };
TheChrisyd 0:8a7c58553b44 197 #endif
TheChrisyd 0:8a7c58553b44 198
TheChrisyd 0:8a7c58553b44 199 /*------------------------------------------------------------------
TheChrisyd 0:8a7c58553b44 200 Main sound controller object
TheChrisyd 0:8a7c58553b44 201 ------------------------------------------------------------------*/
TheChrisyd 0:8a7c58553b44 202 struct SoundController {
TheChrisyd 0:8a7c58553b44 203 // Reset all sounds, return to silence
TheChrisyd 0:8a7c58553b44 204 static void reset();
TheChrisyd 0:8a7c58553b44 205
TheChrisyd 0:8a7c58553b44 206 // Update all sound - call this at least once every video frame.
TheChrisyd 0:8a7c58553b44 207 // The frequency at which you call this function is one "clock tick" for synthesised sounds
TheChrisyd 0:8a7c58553b44 208 static void update();
TheChrisyd 0:8a7c58553b44 209
TheChrisyd 0:8a7c58553b44 210 // Play a sound sample from program memory
TheChrisyd 0:8a7c58553b44 211 // Samples are eight bits and will be played at
TheChrisyd 0:8a7c58553b44 212 // the system sample rate (see "Coprocessor").
TheChrisyd 0:8a7c58553b44 213 // if "numBytes" is negative, the sample will repeat until you play
TheChrisyd 0:8a7c58553b44 214 // another sample on the channel (eg. pass a null pointer to "playSample()"...)
TheChrisyd 0:8a7c58553b44 215 static void playSample(prog_char*, int numBytes, byte channel);
TheChrisyd 0:8a7c58553b44 216 };
TheChrisyd 0:8a7c58553b44 217
TheChrisyd 0:8a7c58553b44 218
TheChrisyd 0:8a7c58553b44 219
TheChrisyd 0:8a7c58553b44 220 /*------------------------------------------------------------
TheChrisyd 0:8a7c58553b44 221 Useful little functions
TheChrisyd 0:8a7c58553b44 222 ------------------------------------------------------------*/
TheChrisyd 0:8a7c58553b44 223 // Show a number on screen
TheChrisyd 0:8a7c58553b44 224 void showNumber(int n, byte x, byte y);
TheChrisyd 0:8a7c58553b44 225 void showHexNumber(unsigned int n, byte x, byte y);
TheChrisyd 0:8a7c58553b44 226
TheChrisyd 0:8a7c58553b44 227 // Send screenshot to serial port
TheChrisyd 0:8a7c58553b44 228
TheChrisyd 0:8a7c58553b44 229 void sendScreenshot();
TheChrisyd 0:8a7c58553b44 230
TheChrisyd 0:8a7c58553b44 231 // COM_ARTLUM_GDUTILS_INCLUDED
TheChrisyd 0:8a7c58553b44 232 #endif