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 //#include <SPI.h>
TheChrisyd 2:20a89dc286d5 2
TheChrisyd 2:20a89dc286d5 3 #include "utils.h"
TheChrisyd 2:20a89dc286d5 4 #include "shield.h"
TheChrisyd 2:20a89dc286d5 5 extern GDClass GD;
TheChrisyd 2:20a89dc286d5 6 SPI spiutils(ARD_MOSI, ARD_MISO, ARD_SCK); // mosi, miso, sclk
TheChrisyd 2:20a89dc286d5 7 Serial pcu(USBTX, USBRX);
TheChrisyd 2:20a89dc286d5 8 /*---------------------------------------------
TheChrisyd 2:20a89dc286d5 9 Coprocessor controller
TheChrisyd 2:20a89dc286d5 10 ---------------------------------------------*/
TheChrisyd 2:20a89dc286d5 11 enum {
TheChrisyd 2:20a89dc286d5 12 COPPERCTRL = COMM,
TheChrisyd 2:20a89dc286d5 13 COPPERLISTSTART = COPPERCTRL,
TheChrisyd 2:20a89dc286d5 14 SAMPLEREADPOS = COPPERCTRL+2,
TheChrisyd 2:20a89dc286d5 15 SAMPLEREADPAGE = COPPERCTRL+4,
TheChrisyd 2:20a89dc286d5 16 COPPERLISTPTR = COPPERCTRL+6,
TheChrisyd 2:20a89dc286d5 17 YLINEECHO = COPPERCTRL+8,
TheChrisyd 2:20a89dc286d5 18 DUMMYCOPPERLIST = COPPERCTRL+10
TheChrisyd 2:20a89dc286d5 19 };
TheChrisyd 2:20a89dc286d5 20
TheChrisyd 2:20a89dc286d5 21 // Available commands
TheChrisyd 2:20a89dc286d5 22 enum copper_commands {
TheChrisyd 2:20a89dc286d5 23 cp_halt='@',
TheChrisyd 2:20a89dc286d5 24 cp_wait,
TheChrisyd 2:20a89dc286d5 25 cp_write8,
TheChrisyd 2:20a89dc286d5 26 cp_write16,
TheChrisyd 2:20a89dc286d5 27 cp_copy
TheChrisyd 2:20a89dc286d5 28 };
TheChrisyd 2:20a89dc286d5 29
TheChrisyd 2:20a89dc286d5 30 #include "j1.h"
TheChrisyd 2:20a89dc286d5 31 void crash()
TheChrisyd 2:20a89dc286d5 32 {
TheChrisyd 2:20a89dc286d5 33 unsigned int p;
TheChrisyd 2:20a89dc286d5 34 while (1) {
TheChrisyd 2:20a89dc286d5 35 GD.wr(0,p++);
TheChrisyd 2:20a89dc286d5 36 }
TheChrisyd 2:20a89dc286d5 37 }
TheChrisyd 2:20a89dc286d5 38 static unsigned int samplePage_, listStart_;
TheChrisyd 2:20a89dc286d5 39 void Coprocessor::reset(unsigned int spg)
TheChrisyd 2:20a89dc286d5 40 {
TheChrisyd 2:20a89dc286d5 41 samplePage_ = spg;
TheChrisyd 2:20a89dc286d5 42 GD.wr(J1_RESET, 1); // Halt the coprocessor
TheChrisyd 2:20a89dc286d5 43 GD.copy(J1_CODE, copper_code, sizeof(copper_code));
TheChrisyd 2:20a89dc286d5 44 for (unsigned int i=J1_CODE; i<J1_CODE+256; i+=2) {
TheChrisyd 2:20a89dc286d5 45 unsigned int w = GD.rd16(i);
TheChrisyd 2:20a89dc286d5 46 if (w == 0xbf00) { GD.wr16(i,spg+0x8000); }
TheChrisyd 2:20a89dc286d5 47 else if (w == COMM+0x8000) { listStart_ = i; }
TheChrisyd 2:20a89dc286d5 48 }
TheChrisyd 2:20a89dc286d5 49 CopperlistBuilder d; // Set up a fake copperlist
TheChrisyd 2:20a89dc286d5 50 GD.wr(DUMMYCOPPERLIST,cp_halt);
TheChrisyd 2:20a89dc286d5 51 GD.wr16(listStart_,DUMMYCOPPERLIST+0x8000);
TheChrisyd 2:20a89dc286d5 52 GD.wr16(SAMPLEREADPAGE,samplePage_);
TheChrisyd 2:20a89dc286d5 53 SoundController::reset();
TheChrisyd 2:20a89dc286d5 54 GD.wr(J1_RESET, 0); // Go!
TheChrisyd 2:20a89dc286d5 55 delay(10);
TheChrisyd 2:20a89dc286d5 56 SoundController::update();
TheChrisyd 2:20a89dc286d5 57 }
TheChrisyd 2:20a89dc286d5 58
TheChrisyd 2:20a89dc286d5 59 void Coprocessor::setCopperlist(unsigned int addr)
TheChrisyd 2:20a89dc286d5 60 {
TheChrisyd 2:20a89dc286d5 61 GD.wr(J1_RESET, 1); // Halt the coprocessor
TheChrisyd 2:20a89dc286d5 62 GD.wr16(listStart_,addr+0x8000);
TheChrisyd 2:20a89dc286d5 63 GD.wr(J1_RESET, 0); // Go!
TheChrisyd 2:20a89dc286d5 64 }
TheChrisyd 2:20a89dc286d5 65
TheChrisyd 2:20a89dc286d5 66 int Coprocessor::yline()
TheChrisyd 2:20a89dc286d5 67 {
TheChrisyd 2:20a89dc286d5 68 return GD.rd16(YLINEECHO);
TheChrisyd 2:20a89dc286d5 69 }
TheChrisyd 2:20a89dc286d5 70 unsigned int Coprocessor::samplePage()
TheChrisyd 2:20a89dc286d5 71 {
TheChrisyd 2:20a89dc286d5 72 return samplePage_;
TheChrisyd 2:20a89dc286d5 73 }
TheChrisyd 2:20a89dc286d5 74 byte Coprocessor::sampleReadPos()
TheChrisyd 2:20a89dc286d5 75 {
TheChrisyd 2:20a89dc286d5 76 return GD.rd(SAMPLEREADPOS);
TheChrisyd 2:20a89dc286d5 77 }
TheChrisyd 2:20a89dc286d5 78
TheChrisyd 2:20a89dc286d5 79 // CopperlistBuilder
TheChrisyd 2:20a89dc286d5 80 void CopperlistBuilder::put(byte b)
TheChrisyd 2:20a89dc286d5 81 {
TheChrisyd 2:20a89dc286d5 82 GD.wr(out++,b);
TheChrisyd 2:20a89dc286d5 83 }
TheChrisyd 2:20a89dc286d5 84 void CopperlistBuilder::put16(unsigned int v)
TheChrisyd 2:20a89dc286d5 85 {
TheChrisyd 2:20a89dc286d5 86 put(lowByte(v));
TheChrisyd 2:20a89dc286d5 87 put(highByte(v));
TheChrisyd 2:20a89dc286d5 88 }
TheChrisyd 2:20a89dc286d5 89
TheChrisyd 2:20a89dc286d5 90 void CopperlistBuilder::begin(unsigned int dest)
TheChrisyd 2:20a89dc286d5 91 {
TheChrisyd 2:20a89dc286d5 92 out = start = dest;
TheChrisyd 2:20a89dc286d5 93 #if 0
TheChrisyd 2:20a89dc286d5 94 // Debugging...
TheChrisyd 2:20a89dc286d5 95 write(0,65);
TheChrisyd 2:20a89dc286d5 96 write(1,66);
TheChrisyd 2:20a89dc286d5 97 write(2,67);
TheChrisyd 2:20a89dc286d5 98 write(3,68);
TheChrisyd 2:20a89dc286d5 99 write(4,69);
TheChrisyd 2:20a89dc286d5 100 copy(0,64,4);
TheChrisyd 2:20a89dc286d5 101 copy(64,128,3);
TheChrisyd 2:20a89dc286d5 102 copy(128,131,5);
TheChrisyd 2:20a89dc286d5 103 #endif
TheChrisyd 2:20a89dc286d5 104 }
TheChrisyd 2:20a89dc286d5 105 void CopperlistBuilder::wait(int line)
TheChrisyd 2:20a89dc286d5 106 {
TheChrisyd 2:20a89dc286d5 107 if (line > 0) {
TheChrisyd 2:20a89dc286d5 108 put(cp_wait);
TheChrisyd 2:20a89dc286d5 109 put16(line);
TheChrisyd 2:20a89dc286d5 110 }
TheChrisyd 2:20a89dc286d5 111 }
TheChrisyd 2:20a89dc286d5 112 void CopperlistBuilder::write(unsigned int addr, byte val)
TheChrisyd 2:20a89dc286d5 113 {
TheChrisyd 2:20a89dc286d5 114 put(cp_write8);
TheChrisyd 2:20a89dc286d5 115 put(val);
TheChrisyd 2:20a89dc286d5 116 put16(addr);
TheChrisyd 2:20a89dc286d5 117 }
TheChrisyd 2:20a89dc286d5 118 void CopperlistBuilder::write16(unsigned int addr, unsigned int val)
TheChrisyd 2:20a89dc286d5 119 {
TheChrisyd 2:20a89dc286d5 120 put(cp_write16);
TheChrisyd 2:20a89dc286d5 121 put16(val);
TheChrisyd 2:20a89dc286d5 122 put16(addr);
TheChrisyd 2:20a89dc286d5 123 }
TheChrisyd 2:20a89dc286d5 124 void CopperlistBuilder::copy(unsigned int src, unsigned int dst, unsigned int numBytes)
TheChrisyd 2:20a89dc286d5 125 {
TheChrisyd 2:20a89dc286d5 126 if (numBytes > 0) {
TheChrisyd 2:20a89dc286d5 127 put(cp_copy);
TheChrisyd 2:20a89dc286d5 128 put16(src);
TheChrisyd 2:20a89dc286d5 129 put16(dst);
TheChrisyd 2:20a89dc286d5 130 put16(numBytes);
TheChrisyd 2:20a89dc286d5 131 }
TheChrisyd 2:20a89dc286d5 132 }
TheChrisyd 2:20a89dc286d5 133 void CopperlistBuilder::end(bool executeNow)
TheChrisyd 2:20a89dc286d5 134 {
TheChrisyd 2:20a89dc286d5 135 put(cp_halt); // Nice end to the list
TheChrisyd 2:20a89dc286d5 136 if (executeNow) {
TheChrisyd 2:20a89dc286d5 137 Coprocessor::setCopperlist(start);
TheChrisyd 2:20a89dc286d5 138 }
TheChrisyd 2:20a89dc286d5 139 }
TheChrisyd 2:20a89dc286d5 140
TheChrisyd 2:20a89dc286d5 141 unsigned int CopperlistBuilder::position()
TheChrisyd 2:20a89dc286d5 142 {
TheChrisyd 2:20a89dc286d5 143 return out;
TheChrisyd 2:20a89dc286d5 144 }
TheChrisyd 2:20a89dc286d5 145
TheChrisyd 2:20a89dc286d5 146 /*---------------------------------------------
TheChrisyd 2:20a89dc286d5 147 Sound
TheChrisyd 2:20a89dc286d5 148 ---------------------------------------------*/
TheChrisyd 2:20a89dc286d5 149 // The amount of space to leave in the buffer
TheChrisyd 2:20a89dc286d5 150 #define BUFFERGAP 8
TheChrisyd 2:20a89dc286d5 151
TheChrisyd 2:20a89dc286d5 152 /*---------------------------------------------
TheChrisyd 2:20a89dc286d5 153 Sample playback
TheChrisyd 2:20a89dc286d5 154 ---------------------------------------------*/
TheChrisyd 2:20a89dc286d5 155 static byte sampleWritePos;
TheChrisyd 2:20a89dc286d5 156 static prog_char *sampleStart0, *samplePos0, *sampleEnd0;
TheChrisyd 2:20a89dc286d5 157 static prog_char *sampleStart1, *samplePos1, *sampleEnd1;
TheChrisyd 2:20a89dc286d5 158 static prog_char *sampleStart2, *samplePos2, *sampleEnd2;
TheChrisyd 2:20a89dc286d5 159 static prog_char *sampleStart3, *samplePos3, *sampleEnd3;
TheChrisyd 2:20a89dc286d5 160 static bool repeatSample0, repeatSample1, repeatSample2, repeatSample3;
TheChrisyd 2:20a89dc286d5 161
TheChrisyd 2:20a89dc286d5 162 static void writeSamples(byte num)
TheChrisyd 2:20a89dc286d5 163 {
TheChrisyd 2:20a89dc286d5 164 if (num > 0) {
TheChrisyd 2:20a89dc286d5 165 GD.__wstart(Coprocessor::samplePage()+sampleWritePos);
TheChrisyd 2:20a89dc286d5 166 prog_char *s0=samplePos0, *se0=sampleEnd0;
TheChrisyd 2:20a89dc286d5 167 prog_char *s1=samplePos1, *se1=sampleEnd1;
TheChrisyd 2:20a89dc286d5 168 prog_char *s2=samplePos2, *se2=sampleEnd2;
TheChrisyd 2:20a89dc286d5 169 prog_char *s3=samplePos3, *se3=sampleEnd3;
TheChrisyd 2:20a89dc286d5 170 for (byte i=0; i<num; ++i) {
TheChrisyd 2:20a89dc286d5 171 int val = 0;
TheChrisyd 2:20a89dc286d5 172 if (s0) {
TheChrisyd 2:20a89dc286d5 173 val += (char)pgm_read_byte(s0++);
TheChrisyd 2:20a89dc286d5 174 if (s0 == se0) {
TheChrisyd 2:20a89dc286d5 175 s0 = (repeatSample0)? sampleStart0: 0;
TheChrisyd 2:20a89dc286d5 176 }
TheChrisyd 2:20a89dc286d5 177 }
TheChrisyd 2:20a89dc286d5 178 if (s1) {
TheChrisyd 2:20a89dc286d5 179 val += (char)pgm_read_byte(s1++);
TheChrisyd 2:20a89dc286d5 180 if (s1 == se1) {
TheChrisyd 2:20a89dc286d5 181 s1 = (repeatSample1)? sampleStart1: 0;
TheChrisyd 2:20a89dc286d5 182 }
TheChrisyd 2:20a89dc286d5 183 }
TheChrisyd 2:20a89dc286d5 184 if (s2) {
TheChrisyd 2:20a89dc286d5 185 val += (char)pgm_read_byte(s2++);
TheChrisyd 2:20a89dc286d5 186 if (s2 == se2) {
TheChrisyd 2:20a89dc286d5 187 s2 = (repeatSample2)? sampleStart2: 0;
TheChrisyd 2:20a89dc286d5 188 }
TheChrisyd 2:20a89dc286d5 189 }
TheChrisyd 2:20a89dc286d5 190 if (s3) {
TheChrisyd 2:20a89dc286d5 191 val += (char)pgm_read_byte(s3++);
TheChrisyd 2:20a89dc286d5 192 if (s3 == se3) {
TheChrisyd 2:20a89dc286d5 193 s3 = (repeatSample3)? sampleStart3: 0;
TheChrisyd 2:20a89dc286d5 194 }
TheChrisyd 2:20a89dc286d5 195 }
TheChrisyd 2:20a89dc286d5 196 spiutils.write(val>>2);
TheChrisyd 2:20a89dc286d5 197 }
TheChrisyd 2:20a89dc286d5 198 GD.__end();
TheChrisyd 2:20a89dc286d5 199 samplePos0 = s0;
TheChrisyd 2:20a89dc286d5 200 samplePos1 = s1;
TheChrisyd 2:20a89dc286d5 201 samplePos2 = s2;
TheChrisyd 2:20a89dc286d5 202 samplePos3 = s3;
TheChrisyd 2:20a89dc286d5 203 sampleWritePos += num;
TheChrisyd 2:20a89dc286d5 204 }
TheChrisyd 2:20a89dc286d5 205 }
TheChrisyd 2:20a89dc286d5 206
TheChrisyd 2:20a89dc286d5 207 void SoundController::playSample(prog_char *s, int n, byte ch)
TheChrisyd 2:20a89dc286d5 208 {
TheChrisyd 2:20a89dc286d5 209 bool repeat = (n < 0);
TheChrisyd 2:20a89dc286d5 210 if (repeat) {
TheChrisyd 2:20a89dc286d5 211 n = -n;
TheChrisyd 2:20a89dc286d5 212 }
TheChrisyd 2:20a89dc286d5 213 switch (ch) {
TheChrisyd 2:20a89dc286d5 214 case 0: sampleStart0 = s;
TheChrisyd 2:20a89dc286d5 215 samplePos0 = s;
TheChrisyd 2:20a89dc286d5 216 sampleEnd0 = s+n;
TheChrisyd 2:20a89dc286d5 217 repeatSample0 = repeat;
TheChrisyd 2:20a89dc286d5 218 break;
TheChrisyd 2:20a89dc286d5 219 case 1: sampleStart1 = s;
TheChrisyd 2:20a89dc286d5 220 samplePos1 = s;
TheChrisyd 2:20a89dc286d5 221 sampleEnd1 = s+n;
TheChrisyd 2:20a89dc286d5 222 repeatSample1 = repeat;
TheChrisyd 2:20a89dc286d5 223 break;
TheChrisyd 2:20a89dc286d5 224 case 2: sampleStart2 = s;
TheChrisyd 2:20a89dc286d5 225 samplePos2 = s;
TheChrisyd 2:20a89dc286d5 226 sampleEnd2 = s+n;
TheChrisyd 2:20a89dc286d5 227 repeatSample2 = repeat;
TheChrisyd 2:20a89dc286d5 228 break;
TheChrisyd 2:20a89dc286d5 229 case 3: sampleStart3 = s;
TheChrisyd 2:20a89dc286d5 230 samplePos3 = s;
TheChrisyd 2:20a89dc286d5 231 sampleEnd3 = s+n;
TheChrisyd 2:20a89dc286d5 232 repeatSample3 = repeat;
TheChrisyd 2:20a89dc286d5 233 break;
TheChrisyd 2:20a89dc286d5 234 }
TheChrisyd 2:20a89dc286d5 235 }
TheChrisyd 2:20a89dc286d5 236
TheChrisyd 2:20a89dc286d5 237 #if SYNTHSOUNDS
TheChrisyd 2:20a89dc286d5 238 /*---------------------------------------------
TheChrisyd 2:20a89dc286d5 239 Synthesized sounds
TheChrisyd 2:20a89dc286d5 240 ---------------------------------------------*/
TheChrisyd 2:20a89dc286d5 241 static SoundPlayer *soundPlayerList=0;
TheChrisyd 2:20a89dc286d5 242 ADSR::ADSR(byte a, byte d, byte s, byte r) : attack(a), decay(d), sustain(s), release(r)
TheChrisyd 2:20a89dc286d5 243 {
TheChrisyd 2:20a89dc286d5 244 }
TheChrisyd 2:20a89dc286d5 245 byte ADSR::evaluate(unsigned int t, unsigned int r)
TheChrisyd 2:20a89dc286d5 246 {
TheChrisyd 2:20a89dc286d5 247 if (t > r) {
TheChrisyd 2:20a89dc286d5 248 // In release phase...
TheChrisyd 2:20a89dc286d5 249 t -= r;
TheChrisyd 2:20a89dc286d5 250 if (t > release) {
TheChrisyd 2:20a89dc286d5 251 return 0;
TheChrisyd 2:20a89dc286d5 252 }
TheChrisyd 2:20a89dc286d5 253 t = sustain*(release-t);
TheChrisyd 2:20a89dc286d5 254 return t/release;
TheChrisyd 2:20a89dc286d5 255 }
TheChrisyd 2:20a89dc286d5 256 else if (t >= (attack+decay)) {
TheChrisyd 2:20a89dc286d5 257 // In sustain phase
TheChrisyd 2:20a89dc286d5 258 return sustain;
TheChrisyd 2:20a89dc286d5 259 }
TheChrisyd 2:20a89dc286d5 260 else if (t > attack) {
TheChrisyd 2:20a89dc286d5 261 // In decay phase
TheChrisyd 2:20a89dc286d5 262 t -= attack;
TheChrisyd 2:20a89dc286d5 263 t = (255-sustain)*t;
TheChrisyd 2:20a89dc286d5 264 return 255-(t/decay);
TheChrisyd 2:20a89dc286d5 265 }
TheChrisyd 2:20a89dc286d5 266 else if (t > 0) {
TheChrisyd 2:20a89dc286d5 267 // In attack phase
TheChrisyd 2:20a89dc286d5 268 return (t*255)/attack;
TheChrisyd 2:20a89dc286d5 269 }
TheChrisyd 2:20a89dc286d5 270 return 0;
TheChrisyd 2:20a89dc286d5 271 }
TheChrisyd 2:20a89dc286d5 272
TheChrisyd 2:20a89dc286d5 273 SoundPlayer::SoundPlayer()
TheChrisyd 2:20a89dc286d5 274 {
TheChrisyd 2:20a89dc286d5 275 volume = 255;
TheChrisyd 2:20a89dc286d5 276 active = false;
TheChrisyd 2:20a89dc286d5 277 isLinked = false;
TheChrisyd 2:20a89dc286d5 278 }
TheChrisyd 2:20a89dc286d5 279 SoundPlayer& SoundPlayer::setVolume(byte v)
TheChrisyd 2:20a89dc286d5 280 {
TheChrisyd 2:20a89dc286d5 281 volume = v;
TheChrisyd 2:20a89dc286d5 282 return *this;
TheChrisyd 2:20a89dc286d5 283 }
TheChrisyd 2:20a89dc286d5 284 SoundPlayer& SoundPlayer::setSound(const Sound& s)
TheChrisyd 2:20a89dc286d5 285 {
TheChrisyd 2:20a89dc286d5 286 sound = s;
TheChrisyd 2:20a89dc286d5 287 return *this;
TheChrisyd 2:20a89dc286d5 288 }
TheChrisyd 2:20a89dc286d5 289 void SoundPlayer::play(unsigned int p, unsigned int d)
TheChrisyd 2:20a89dc286d5 290 {
TheChrisyd 2:20a89dc286d5 291 if (!isLinked) {
TheChrisyd 2:20a89dc286d5 292 // Add me to the list of sounds to be updated
TheChrisyd 2:20a89dc286d5 293 isLinked = true;
TheChrisyd 2:20a89dc286d5 294 link = soundPlayerList;
TheChrisyd 2:20a89dc286d5 295 soundPlayerList = this;
TheChrisyd 2:20a89dc286d5 296 }
TheChrisyd 2:20a89dc286d5 297 ticks = 0;
TheChrisyd 2:20a89dc286d5 298 pitch = p;
TheChrisyd 2:20a89dc286d5 299 duration = d;
TheChrisyd 2:20a89dc286d5 300 releasing = false;
TheChrisyd 2:20a89dc286d5 301 active = true;
TheChrisyd 2:20a89dc286d5 302 }
TheChrisyd 2:20a89dc286d5 303 void SoundPlayer::release()
TheChrisyd 2:20a89dc286d5 304 {
TheChrisyd 2:20a89dc286d5 305 releasing = true;
TheChrisyd 2:20a89dc286d5 306 duration = ticks;
TheChrisyd 2:20a89dc286d5 307 }
TheChrisyd 2:20a89dc286d5 308 void SoundPlayer::update()
TheChrisyd 2:20a89dc286d5 309 {
TheChrisyd 2:20a89dc286d5 310 if (active) {
TheChrisyd 2:20a89dc286d5 311 if (releasing) {
TheChrisyd 2:20a89dc286d5 312 if (++ticks > (duration+sound.adsr.release)) {
TheChrisyd 2:20a89dc286d5 313 stop();
TheChrisyd 2:20a89dc286d5 314 }
TheChrisyd 2:20a89dc286d5 315 }
TheChrisyd 2:20a89dc286d5 316 else {
TheChrisyd 2:20a89dc286d5 317 if (ticks!=infinite) {
TheChrisyd 2:20a89dc286d5 318 ++ticks;
TheChrisyd 2:20a89dc286d5 319 }
TheChrisyd 2:20a89dc286d5 320 if ((ticks==duration) and (duration!=infinite)) {
TheChrisyd 2:20a89dc286d5 321 release();
TheChrisyd 2:20a89dc286d5 322 }
TheChrisyd 2:20a89dc286d5 323 }
TheChrisyd 2:20a89dc286d5 324 if (active) {
TheChrisyd 2:20a89dc286d5 325 GD.__wstart(VOICES);
TheChrisyd 2:20a89dc286d5 326 spimain.write(lowByte(pitch));
TheChrisyd 2:20a89dc286d5 327 spimain.write(highByte(pitch));
TheChrisyd 2:20a89dc286d5 328 unsigned int b = sound.adsr.evaluate(ticks,duration);
TheChrisyd 2:20a89dc286d5 329 b = highByte(b*volume);
TheChrisyd 2:20a89dc286d5 330 //spimain.write(b);
TheChrisyd 2:20a89dc286d5 331 //spimain.write(b);
TheChrisyd 2:20a89dc286d5 332 GD.__end();
TheChrisyd 2:20a89dc286d5 333 }
TheChrisyd 2:20a89dc286d5 334 }
TheChrisyd 2:20a89dc286d5 335 }
TheChrisyd 2:20a89dc286d5 336 void SoundPlayer::stop()
TheChrisyd 2:20a89dc286d5 337 {
TheChrisyd 2:20a89dc286d5 338 if (active) {
TheChrisyd 2:20a89dc286d5 339 active = false;
TheChrisyd 2:20a89dc286d5 340 GD.__wstart(VOICES+2);
TheChrisyd 2:20a89dc286d5 341 spimain.write(0);
TheChrisyd 2:20a89dc286d5 342 spimain.write(0);
TheChrisyd 2:20a89dc286d5 343 GD.__end();
TheChrisyd 2:20a89dc286d5 344 }
TheChrisyd 2:20a89dc286d5 345 }
TheChrisyd 2:20a89dc286d5 346 #endif
TheChrisyd 2:20a89dc286d5 347 /*---------------------------------------------
TheChrisyd 2:20a89dc286d5 348 SoundController object
TheChrisyd 2:20a89dc286d5 349 ---------------------------------------------*/
TheChrisyd 2:20a89dc286d5 350 void SoundController::reset()
TheChrisyd 2:20a89dc286d5 351 {
TheChrisyd 2:20a89dc286d5 352 samplePos0 = 0;
TheChrisyd 2:20a89dc286d5 353 samplePos1 = 0;
TheChrisyd 2:20a89dc286d5 354 samplePos2 = 0;
TheChrisyd 2:20a89dc286d5 355 samplePos3 = 0;
TheChrisyd 2:20a89dc286d5 356 GD.__wstart(Coprocessor::samplePage());
TheChrisyd 2:20a89dc286d5 357 for (int i=0; i<256; ++i) {
TheChrisyd 2:20a89dc286d5 358 spiutils.write(0);
TheChrisyd 2:20a89dc286d5 359 }
TheChrisyd 2:20a89dc286d5 360 GD.__end();
TheChrisyd 2:20a89dc286d5 361 #if SYNTHSOUNDS
TheChrisyd 2:20a89dc286d5 362 SoundPlayer *p = soundPlayerList;
TheChrisyd 2:20a89dc286d5 363 while (p) {
TheChrisyd 2:20a89dc286d5 364 p->stop();
TheChrisyd 2:20a89dc286d5 365 p->isLinked = false;
TheChrisyd 2:20a89dc286d5 366 p = p->link;
TheChrisyd 2:20a89dc286d5 367 }
TheChrisyd 2:20a89dc286d5 368 #endif
TheChrisyd 2:20a89dc286d5 369 }
TheChrisyd 2:20a89dc286d5 370
TheChrisyd 2:20a89dc286d5 371 void SoundController::update()
TheChrisyd 2:20a89dc286d5 372 {
TheChrisyd 2:20a89dc286d5 373 #if SYNTHSOUNDS
TheChrisyd 2:20a89dc286d5 374 { // Synthesized sounds
TheChrisyd 2:20a89dc286d5 375 byte b = '0';
TheChrisyd 2:20a89dc286d5 376 SoundPlayer *p = soundPlayerList;
TheChrisyd 2:20a89dc286d5 377 while (p) {
TheChrisyd 2:20a89dc286d5 378 ++b;
TheChrisyd 2:20a89dc286d5 379 p->update();
TheChrisyd 2:20a89dc286d5 380 p = p->link;
TheChrisyd 2:20a89dc286d5 381 }
TheChrisyd 2:20a89dc286d5 382 GD.wr(0,b);
TheChrisyd 2:20a89dc286d5 383 }
TheChrisyd 2:20a89dc286d5 384 #endif
TheChrisyd 2:20a89dc286d5 385 { // Sampled sounds
TheChrisyd 2:20a89dc286d5 386 unsigned int rp = Coprocessor::sampleReadPos();
TheChrisyd 2:20a89dc286d5 387 unsigned int wp = sampleWritePos;
TheChrisyd 2:20a89dc286d5 388 unsigned int emptySpace = (rp-wp)&255;
TheChrisyd 2:20a89dc286d5 389 if (emptySpace > BUFFERGAP) {
TheChrisyd 2:20a89dc286d5 390 emptySpace -= BUFFERGAP;
TheChrisyd 2:20a89dc286d5 391 if ((wp+emptySpace) > 256) {
TheChrisyd 2:20a89dc286d5 392 // Write would overflow the buffer - need to split it into two
TheChrisyd 2:20a89dc286d5 393 unsigned int b = 256-wp;
TheChrisyd 2:20a89dc286d5 394 writeSamples(b);
TheChrisyd 2:20a89dc286d5 395 writeSamples(emptySpace-b);
TheChrisyd 2:20a89dc286d5 396 }
TheChrisyd 2:20a89dc286d5 397 else {
TheChrisyd 2:20a89dc286d5 398 // Can write a single block
TheChrisyd 2:20a89dc286d5 399 writeSamples(emptySpace);
TheChrisyd 2:20a89dc286d5 400 }
TheChrisyd 2:20a89dc286d5 401 }
TheChrisyd 2:20a89dc286d5 402 }
TheChrisyd 2:20a89dc286d5 403 }
TheChrisyd 2:20a89dc286d5 404
TheChrisyd 2:20a89dc286d5 405
TheChrisyd 2:20a89dc286d5 406 /*------------------------------------------------------------
TheChrisyd 2:20a89dc286d5 407 Useful little functions
TheChrisyd 2:20a89dc286d5 408 ------------------------------------------------------------*/
TheChrisyd 2:20a89dc286d5 409 void showNumber(int n, byte x, byte y)
TheChrisyd 2:20a89dc286d5 410 {
TheChrisyd 2:20a89dc286d5 411 char temp[8];
TheChrisyd 2:20a89dc286d5 412 boolean neg = (n<0);
TheChrisyd 2:20a89dc286d5 413 if (neg) {
TheChrisyd 2:20a89dc286d5 414 n = -n;
TheChrisyd 2:20a89dc286d5 415 }
TheChrisyd 2:20a89dc286d5 416 char *o = temp;
TheChrisyd 2:20a89dc286d5 417 int m = 10000;
TheChrisyd 2:20a89dc286d5 418 while (m != 0) {
TheChrisyd 2:20a89dc286d5 419 int d = n/m;
TheChrisyd 2:20a89dc286d5 420 *o++ = d+'0';
TheChrisyd 2:20a89dc286d5 421 n -= d*m;
TheChrisyd 2:20a89dc286d5 422 m /= 10;
TheChrisyd 2:20a89dc286d5 423 }
TheChrisyd 2:20a89dc286d5 424 *o-- = 0;
TheChrisyd 2:20a89dc286d5 425 // Remove leading zeros
TheChrisyd 2:20a89dc286d5 426 char *s = temp;
TheChrisyd 2:20a89dc286d5 427 while ((s<o) and (*s=='0')) {
TheChrisyd 2:20a89dc286d5 428 *s++ = ' ';
TheChrisyd 2:20a89dc286d5 429 }
TheChrisyd 2:20a89dc286d5 430 if (neg) {
TheChrisyd 2:20a89dc286d5 431 *--s = '-';
TheChrisyd 2:20a89dc286d5 432 }
TheChrisyd 2:20a89dc286d5 433 GD.__wstart((64*y)+x);
TheChrisyd 2:20a89dc286d5 434 while (*s) {
TheChrisyd 2:20a89dc286d5 435 spiutils.write(*s++);
TheChrisyd 2:20a89dc286d5 436 }
TheChrisyd 2:20a89dc286d5 437 GD.__end();
TheChrisyd 2:20a89dc286d5 438 }
TheChrisyd 2:20a89dc286d5 439
TheChrisyd 2:20a89dc286d5 440 static void hexDigit(byte b)
TheChrisyd 2:20a89dc286d5 441 {
TheChrisyd 2:20a89dc286d5 442 b = (b&0x0f)+'0';
TheChrisyd 2:20a89dc286d5 443 if (b > '9') {
TheChrisyd 2:20a89dc286d5 444 b += 'a'-('9'+1);
TheChrisyd 2:20a89dc286d5 445 }
TheChrisyd 2:20a89dc286d5 446 spiutils.write(b);
TheChrisyd 2:20a89dc286d5 447 }
TheChrisyd 2:20a89dc286d5 448 static void hexPair(byte b)
TheChrisyd 2:20a89dc286d5 449 {
TheChrisyd 2:20a89dc286d5 450 hexDigit(b>>4);
TheChrisyd 2:20a89dc286d5 451 hexDigit(b);
TheChrisyd 2:20a89dc286d5 452 }
TheChrisyd 2:20a89dc286d5 453 void showHexNumber(unsigned int n, byte x, byte y)
TheChrisyd 2:20a89dc286d5 454 {
TheChrisyd 2:20a89dc286d5 455 GD.__wstart((64*y)+x);
TheChrisyd 2:20a89dc286d5 456 hexPair(highByte(n));
TheChrisyd 2:20a89dc286d5 457 hexPair(lowByte(n));
TheChrisyd 2:20a89dc286d5 458 GD.__end();
TheChrisyd 2:20a89dc286d5 459 }
TheChrisyd 2:20a89dc286d5 460 void writeColor(int c)
TheChrisyd 2:20a89dc286d5 461 {
TheChrisyd 2:20a89dc286d5 462 // Colors are five bits - encode in base 32
TheChrisyd 2:20a89dc286d5 463 c = (c&31)+'0';
TheChrisyd 2:20a89dc286d5 464 if (c > '9') {
TheChrisyd 2:20a89dc286d5 465 c += 'A'-('9'+1);
TheChrisyd 2:20a89dc286d5 466 }
TheChrisyd 2:20a89dc286d5 467 pcu.printf("%d", c);
TheChrisyd 2:20a89dc286d5 468 }
TheChrisyd 2:20a89dc286d5 469 void sendScreenshot()
TheChrisyd 2:20a89dc286d5 470 {
TheChrisyd 2:20a89dc286d5 471 pcu.baud(115200);
TheChrisyd 2:20a89dc286d5 472 for (int i=0; i<300; ++i) {
TheChrisyd 2:20a89dc286d5 473 // Ask for the line...
TheChrisyd 2:20a89dc286d5 474 GD.wr16(SCREENSHOT_Y, 0x8000|i);
TheChrisyd 2:20a89dc286d5 475 // Wait for it to appear
TheChrisyd 2:20a89dc286d5 476 while ((GD.rd(SCREENSHOT_Y+1)&0x80)==0) {
TheChrisyd 2:20a89dc286d5 477 delay(1);
TheChrisyd 2:20a89dc286d5 478 }
TheChrisyd 2:20a89dc286d5 479 // Send the line of pixels to the serial port
TheChrisyd 2:20a89dc286d5 480 for (int x=0; x<400; ++x) {
TheChrisyd 2:20a89dc286d5 481 uint16_t pixel = GD.rd16(SCREENSHOT+(x*2));
TheChrisyd 2:20a89dc286d5 482 writeColor(pixel>>10); // Red
TheChrisyd 2:20a89dc286d5 483 writeColor(pixel>>5); // Green
TheChrisyd 2:20a89dc286d5 484 writeColor(pixel); // Blue
TheChrisyd 2:20a89dc286d5 485 }
TheChrisyd 2:20a89dc286d5 486 pcu.printf("\n");
TheChrisyd 2:20a89dc286d5 487 }
TheChrisyd 2:20a89dc286d5 488 // Restore sanity
TheChrisyd 2:20a89dc286d5 489 GD.wr16(SCREENSHOT_Y, 0);
TheChrisyd 2:20a89dc286d5 490 }