Big Mouth Billy Bass automation library
Revision 3:6c91a6232c4a, committed 2013-06-18
- Comitter:
- bikeNomad
- Date:
- Tue Jun 18 13:11:07 2013 +0000
- Parent:
- 2:eaba75af0f0d
- Child:
- 4:f009306756b3
- Commit message:
- changed debug messages; added inversion of BB outputs
Changed in this revision
--- a/billybass.hpp Tue Jun 18 06:12:48 2013 +0000
+++ b/billybass.hpp Tue Jun 18 13:11:07 2013 +0000
@@ -6,29 +6,42 @@
#include <list>
#include <vector>
#include <cmath>
-
-extern AnalogOut speaker;
-extern Serial pc;
+#include "mbed_debug.h"
class BillyBass
{
public:
- BillyBass(PinName tailPin, PinName mouthPin, PinName bodyPin) :
- tail(tailPin), mouth(mouthPin), body(bodyPin)
- {
- tail.write(0);
- mouth.write(0);
- body.write(0);
+ BillyBass(PinName tailPin, PinName mouthPin, PinName bodyPin, bool _inverted=false) :
+ tail(tailPin), mouth(mouthPin), body(bodyPin), inverted(!!_inverted) {
+ relax();
if (numFish < MAX_FISH) fish[numFish++] = this;
- // else error
+ else fprintf(stderr, "Too many fish!\r\n");
}
// if *_pName, it will get the string name of the output
DigitalOut *outputNamed(char const *_outputName, char const **_pName = 0);
- static BillyBass *bassNumber(unsigned which) { return (which >= numFish) ? 0 : fish[which]; }
- static unsigned getNumFish() { return numFish; }
+ static BillyBass *bassNumber(unsigned which) {
+ return (which >= numFish) ? 0 : fish[which];
+ }
+
+ static unsigned getNumFish() {
+ return numFish;
+ }
+
+ int onState() const {
+ return !inverted;
+ }
+ int offState() const {
+ return inverted;
+ }
+
+ void relax() {
+ tail.write(offState());
+ mouth.write(offState());
+ body.write(offState());
+ }
protected:
static BillyBass* fish[ MAX_FISH ];
@@ -40,6 +53,7 @@
DigitalOut tail;
DigitalOut mouth;
DigitalOut body;
+ int inverted;
};
#endif
--- a/player.hpp Tue Jun 18 06:12:48 2013 +0000
+++ b/player.hpp Tue Jun 18 13:11:07 2013 +0000
@@ -3,6 +3,8 @@
#include "billybass.hpp"
+extern AnalogOut speaker;
+
class SongPlayer;
struct SampleBuffer {
@@ -54,8 +56,7 @@
, nChunks(0)
, chunksRemaining(0)
, song(0)
- , actionsDone(0)
- {
+ , actionsDone(0) {
}
// interrupt handler
@@ -63,7 +64,7 @@
if (playing->samplesRemaining == 0)
swapBuffers();
// NOTE bias of 0xC000 requires normalizing to 75% of full scale
- speaker.write_u16(static_cast<uint16_t>(playing->getNextSample() + 0x8000) / 2);
+ speaker.write_u16(static_cast<uint16_t>(playing->getNextSample() + ANALOG_OUTPUT_BIAS));
}
bool startSong(Song *_song) {
@@ -73,29 +74,30 @@
timeInSong = 0.0;
actionsDone = 0;
- pc.printf("starting %s: ", song->getSampleFileName());
+ fprintf(stderr, "starting %s: ", song->getSampleFileName());
if (fp) fclose(fp);
fp = fopen(song->getSampleFileName(), "rb");
- pc.printf("opened, ");
+ fprintf(stderr, "opened, ");
if (!fp) return false;
- pc.printf("seekend, ");
+ fprintf(stderr, "seekend, ");
if (fseek(fp, 0, SEEK_END)) return false;
long fileSize = ftell(fp);
- pc.printf("size=%d, ", fileSize);
+ fprintf(stderr, "size=%d, ", fileSize);
if (fileSize < 0) return false;
if (fseek(fp, 0, SEEK_SET)) return false;
- pc.printf("rewound, ");
+ fprintf(stderr, "rewound, ");
chunksRemaining = nChunks = fileSize / BUFFER_SIZE;
loading = &buffer[0];
playing = &buffer[1];
- pc.printf("chunks=%d expected=%f seconds\r\n", nChunks, nChunks * SECONDS_PER_CHUNK);
- if (!loadNextChunk())
+ fprintf(stderr, "chunks=%d expected=%f seconds\r\n", nChunks, nChunks * SECONDS_PER_CHUNK);
+ if (!loadNextChunk()) {
+ fprintf(stderr, "first chunk empty!\r\n");
return false;
-
+ }
sampleTicker.attach_us(this, &SongPlayer::playNextSample, SAMPLE_PERIOD_USEC);
return true;
@@ -118,8 +120,8 @@
// to prepare for eventual swap.
// returns true if more samples remain
bool loadNextChunk() {
- if (!chunksRemaining) return false;
-
+ if (isDone())
+ return false;
bool notDone = loading->loadFrom(fp);
return notDone;
}
@@ -131,6 +133,7 @@
// look at loading buffer; load only if necessary.
bool loadIfNecessary() {
if (loading->isDone()) {
+ fprintf(stderr, "*");
timeInSong += SECONDS_PER_CHUNK;
return loadNextChunk();
} else {
@@ -143,12 +146,14 @@
while (!isDone()) {
while (nextAction != song->getActions().end() && nextAction->actIfPast(timeInSong)) {
+ fprintf(stderr, ".");
actionsDone++;
nextAction++;
}
loadIfNecessary();
}
sampleTicker.detach();
+ song->myFish()->relax();
}
};
--- a/song.cpp Tue Jun 18 06:12:48 2013 +0000
+++ b/song.cpp Tue Jun 18 13:11:07 2013 +0000
@@ -22,16 +22,16 @@
{
Song *s = new Song;
if (!s) {
- pc.printf("new Song == 0\r\n");
+ fprintf(stderr, "new Song == 0\r\n");
return 0;
}
if (! s->parseFilename(_name)) {
- pc.printf("parseFilename(%s) failed\r\n", _name);
+ fprintf(stderr, "parseFilename(%s) failed\r\n", _name);
goto on_error;
}
- pc.printf("parsed filename OK\r\n");
+ fprintf(stderr, "parsed filename OK\r\n");
if (! s->readActions()) {
- pc.printf("readActions(%s) failed\r\n", _name);
+ fprintf(stderr, "readActions(%s) failed\r\n", _name);
goto on_error;
}
@@ -85,19 +85,19 @@
bool Song::readActions()
{
- pc.printf("reading actions of %s\r\n", getTextFileName());
+ fprintf(stderr, "reading actions of %s\r\n", getTextFileName());
FILE *txtfile = fopen(getTextFileName(), "r");
if (!txtfile) {
- pc.printf("can't open %s\r\n", getTextFileName());
+ fprintf(stderr, "can't open %s\r\n", getTextFileName());
return false;
} else
- pc.printf("opened %s OK\r\n", getTextFileName());
+ fprintf(stderr, "opened %s OK\r\n", getTextFileName());
bool retval = false;
BillyBass *bass = BillyBass::bassNumber(whichFish);
if (!bass) {
- pc.printf("No bass!\r\n");
+ fprintf(stderr, "No bass!\r\n");
goto done;
}
@@ -105,7 +105,7 @@
static char textFileBuffer[ 2048 ];
memset(textFileBuffer, 0, sizeof(textFileBuffer));
int nread = fread(textFileBuffer, 1, sizeof(textFileBuffer), txtfile);
- pc.printf("Read %d\r\n", nread);
+ // fprintf(stderr, "Read %d bytes\r\n", nread);
if (nread <= 0 || nread == sizeof(textFileBuffer)) {
goto done;
}
@@ -126,15 +126,15 @@
char const *outName;
DigitalOut *out = bass->outputNamed(++q, &outName);
if (!out) {
- pc.printf("%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q);
+ fprintf(stderr, "%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q);
goto done;
}
- pc.printf("%d add %f %f %s\r\n", line, startTime, endTime, outName);
+ // fprintf(stderr, "%d add %f %f %s\r\n", line, startTime, endTime, outName);
- // actions.push_back(Action(startTime, true, out, outName));
- // actions.push_back(Action(endTime, false, out, outName));
+ actions.push_back(Action(startTime, bass->onState(), out, outName));
+ actions.push_back(Action(endTime, bass->offState(), out, outName));
}
-
+ fprintf(stderr, "Added %d actions\r\n", actions.size());
std::sort(actions.begin(), actions.end()); // sort actions by time
retval = true;
--- a/song.hpp Tue Jun 18 06:12:48 2013 +0000
+++ b/song.hpp Tue Jun 18 13:11:07 2013 +0000
@@ -21,7 +21,11 @@
fullname[0] = 0;
actions.reserve(MAX_ACTIONS_PER_SONG);
}
-
+ ~Song() {
+ actions.clear();
+ }
+
+ BillyBass * myFish() { return BillyBass::bassNumber(whichFish); }
bool isValid() const {
return basename != 0 && whichFish != NO_FISH;
}
@@ -48,11 +52,11 @@
return actions;
}
- void print(Serial &pc) {
- pc.printf("%s fish=%u seq=%u\r\n", getSampleFileName(), whichFish, sequenceNumber);
+ void print(FILE *f) {
+ fprintf(f, "%s fish=%u seq=%u\r\n", getSampleFileName(), whichFish, sequenceNumber);
for (actions_t::const_iterator action_it = actions.begin(); action_it != actions.end(); action_it++) {
Action const &action = *action_it;
- pc.printf("%0.02f %s %d\r\n", action.actionTime, action.outputName, action.desiredState ? 1 : 0);
+ fprintf(f, "%0.02f %s %d\r\n", action.actionTime, action.outputName, action.desiredState ? 1 : 0);
}
}
Ned Konz