Big Mouth Billy Bass automation library

Dependents:   BillyBass_with_SD

Files at this revision

API Documentation at this revision

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

billybass.hpp Show annotated file Show diff for this revision Revisions of this file
player.hpp Show annotated file Show diff for this revision Revisions of this file
song.cpp Show annotated file Show diff for this revision Revisions of this file
song.hpp Show annotated file Show diff for this revision Revisions of this file
--- 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);
         }
     }