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:
Sun Mar 09 12:27:20 2014 +0000
Revision:
5:3ede9991d8e0
Parent:
2:20a89dc286d5
Update to match Library update

Who changed what in which revision?

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