Invaders game for the Gameduino

Dependencies:   Gameduino mbed

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