Big Mouth Billy Bass automation library

Dependents:   BillyBass_with_SD

Committer:
bikeNomad
Date:
Thu Jun 20 04:10:22 2013 +0000
Revision:
7:dba9221acf48
Parent:
6:ea8136eb6976
Child:
8:ad0c038ebfc1
try to shift times and enforce minimum times

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bikeNomad 0:84aaade0de8f 1 #include <stdlib.h>
bikeNomad 0:84aaade0de8f 2 #include <string.h>
bikeNomad 0:84aaade0de8f 3 #include <stdio.h>
bikeNomad 0:84aaade0de8f 4 #include <ctype.h>
bikeNomad 0:84aaade0de8f 5 #include <algorithm>
bikeNomad 7:dba9221acf48 6 #include <math.h>
bikeNomad 0:84aaade0de8f 7
bikeNomad 0:84aaade0de8f 8 #include "billybass.hpp"
bikeNomad 0:84aaade0de8f 9 #include "song.hpp"
bikeNomad 0:84aaade0de8f 10
bikeNomad 0:84aaade0de8f 11 // class static
bikeNomad 0:84aaade0de8f 12 char const Song::directoryName[ BASS_DIRECTORY_LENGTH + 1 ] = BASS_DIRECTORY;
bikeNomad 0:84aaade0de8f 13 // class static
bikeNomad 0:84aaade0de8f 14 char const *Song::textExtension = "txt";
bikeNomad 0:84aaade0de8f 15 // class static
bikeNomad 0:84aaade0de8f 16 char const *Song::sampleExtension = "raw";
bikeNomad 0:84aaade0de8f 17 // class static
bikeNomad 0:84aaade0de8f 18 unsigned const Song::NO_FISH = MAX_FISH + 1;
bikeNomad 4:f009306756b3 19 // one song, re-used
bikeNomad 4:f009306756b3 20 Song Song::theSong;
bikeNomad 0:84aaade0de8f 21
bikeNomad 0:84aaade0de8f 22 // _name is relative to BASS_DIRECTORY
bikeNomad 0:84aaade0de8f 23 // class static
bikeNomad 0:84aaade0de8f 24 Song *Song::newSong(char const *_name)
bikeNomad 0:84aaade0de8f 25 {
bikeNomad 4:f009306756b3 26 Song *s = &theSong;
bikeNomad 4:f009306756b3 27 s->reset();
bikeNomad 0:84aaade0de8f 28 if (! s->parseFilename(_name)) {
bikeNomad 3:6c91a6232c4a 29 fprintf(stderr, "parseFilename(%s) failed\r\n", _name);
bikeNomad 0:84aaade0de8f 30 goto on_error;
bikeNomad 0:84aaade0de8f 31 }
bikeNomad 3:6c91a6232c4a 32 fprintf(stderr, "parsed filename OK\r\n");
bikeNomad 0:84aaade0de8f 33 if (! s->readActions()) {
bikeNomad 3:6c91a6232c4a 34 fprintf(stderr, "readActions(%s) failed\r\n", _name);
bikeNomad 0:84aaade0de8f 35 goto on_error;
bikeNomad 0:84aaade0de8f 36 }
bikeNomad 0:84aaade0de8f 37
bikeNomad 0:84aaade0de8f 38 return s;
bikeNomad 0:84aaade0de8f 39
bikeNomad 0:84aaade0de8f 40 on_error:
bikeNomad 0:84aaade0de8f 41 return 0;
bikeNomad 0:84aaade0de8f 42 }
bikeNomad 0:84aaade0de8f 43
bikeNomad 0:84aaade0de8f 44 bool Song::parseFilename(char const *_name)
bikeNomad 0:84aaade0de8f 45 {
bikeNomad 0:84aaade0de8f 46 if (strlen(_name) > MAX_BASENAME_LENGTH)
bikeNomad 0:84aaade0de8f 47 goto on_error;
bikeNomad 0:84aaade0de8f 48
bikeNomad 0:84aaade0de8f 49 strcpy(fullname, directoryName);
bikeNomad 0:84aaade0de8f 50 basename = fullname + BASS_DIRECTORY_LENGTH;
bikeNomad 0:84aaade0de8f 51 *basename++ = '/';
bikeNomad 0:84aaade0de8f 52 strcpy(basename, _name);
bikeNomad 0:84aaade0de8f 53
bikeNomad 0:84aaade0de8f 54 char *p;
bikeNomad 0:84aaade0de8f 55 long n = strtol(_name, &p, 10);
bikeNomad 0:84aaade0de8f 56 if (*p != '_' || n <= 0)
bikeNomad 0:84aaade0de8f 57 goto on_error;
bikeNomad 0:84aaade0de8f 58
bikeNomad 0:84aaade0de8f 59 sequenceNumber = (unsigned)(n - 1);
bikeNomad 0:84aaade0de8f 60
bikeNomad 0:84aaade0de8f 61 p++; // skip underscore
bikeNomad 0:84aaade0de8f 62 n = strtol(p, &p, 10);
bikeNomad 0:84aaade0de8f 63 if (*p != '_' || n <= 0 || n > MAX_FISH)
bikeNomad 0:84aaade0de8f 64 goto on_error;
bikeNomad 0:84aaade0de8f 65
bikeNomad 0:84aaade0de8f 66 whichFish = (unsigned)(n - 1);
bikeNomad 0:84aaade0de8f 67
bikeNomad 0:84aaade0de8f 68 p = strrchr(basename, '.');
bikeNomad 0:84aaade0de8f 69 if (!p)
bikeNomad 0:84aaade0de8f 70 goto on_error;
bikeNomad 0:84aaade0de8f 71
bikeNomad 0:84aaade0de8f 72 extension = p+1;
bikeNomad 0:84aaade0de8f 73
bikeNomad 0:84aaade0de8f 74 if (strcasecmp(extension, sampleExtension))
bikeNomad 0:84aaade0de8f 75 goto on_error;
bikeNomad 0:84aaade0de8f 76
bikeNomad 0:84aaade0de8f 77 return true;
bikeNomad 0:84aaade0de8f 78
bikeNomad 0:84aaade0de8f 79 on_error:
bikeNomad 0:84aaade0de8f 80 whichFish = NO_FISH;
bikeNomad 0:84aaade0de8f 81 basename = 0;
bikeNomad 0:84aaade0de8f 82 return false;
bikeNomad 0:84aaade0de8f 83 }
bikeNomad 0:84aaade0de8f 84
bikeNomad 7:dba9221acf48 85 bool Song::addAction(float _time, int _state, DigitalOut* _out, char _code)
bikeNomad 7:dba9221acf48 86 {
bikeNomad 7:dba9221acf48 87 Action *priorAction = (numActions > 0) ? actions + numActions - 1 : 0;
bikeNomad 7:dba9221acf48 88 if (priorAction ) {
bikeNomad 7:dba9221acf48 89 if (priorAction->output == _out) {
bikeNomad 7:dba9221acf48 90 if (priorAction->actionTime >= _time && priorAction->desiredState != _state)
bikeNomad 7:dba9221acf48 91 return true;
bikeNomad 7:dba9221acf48 92 if (priorAction->actionTime < _time && priorAction->desiredState == _state) {
bikeNomad 7:dba9221acf48 93 priorAction->actionTime = _time;
bikeNomad 7:dba9221acf48 94 return true;
bikeNomad 7:dba9221acf48 95 }
bikeNomad 7:dba9221acf48 96 }
bikeNomad 7:dba9221acf48 97 }
bikeNomad 7:dba9221acf48 98 if (numActions >= MAX_ACTIONS_PER_SONG) return false;
bikeNomad 7:dba9221acf48 99 actions[numActions++].set(_time, _state, _out, _code);
bikeNomad 7:dba9221acf48 100 return true;
bikeNomad 7:dba9221acf48 101 }
bikeNomad 7:dba9221acf48 102
bikeNomad 0:84aaade0de8f 103 bool Song::readActions()
bikeNomad 0:84aaade0de8f 104 {
bikeNomad 3:6c91a6232c4a 105 fprintf(stderr, "reading actions of %s\r\n", getTextFileName());
bikeNomad 1:9b1f3eb204ac 106
bikeNomad 0:84aaade0de8f 107 FILE *txtfile = fopen(getTextFileName(), "r");
bikeNomad 0:84aaade0de8f 108 if (!txtfile) {
bikeNomad 3:6c91a6232c4a 109 fprintf(stderr, "can't open %s\r\n", getTextFileName());
bikeNomad 0:84aaade0de8f 110 return false;
bikeNomad 1:9b1f3eb204ac 111 } else
bikeNomad 3:6c91a6232c4a 112 fprintf(stderr, "opened %s OK\r\n", getTextFileName());
bikeNomad 0:84aaade0de8f 113 bool retval = false;
bikeNomad 0:84aaade0de8f 114
bikeNomad 0:84aaade0de8f 115 BillyBass *bass = BillyBass::bassNumber(whichFish);
bikeNomad 0:84aaade0de8f 116 if (!bass) {
bikeNomad 3:6c91a6232c4a 117 fprintf(stderr, "No bass!\r\n");
bikeNomad 0:84aaade0de8f 118 goto done;
bikeNomad 0:84aaade0de8f 119 }
bikeNomad 0:84aaade0de8f 120
bikeNomad 0:84aaade0de8f 121 // read actions from file
bikeNomad 5:869b3711bdb3 122 static char textFileBuffer[ MAX_TEXT_FILE_LENGTH ];
bikeNomad 1:9b1f3eb204ac 123 memset(textFileBuffer, 0, sizeof(textFileBuffer));
bikeNomad 1:9b1f3eb204ac 124 int nread = fread(textFileBuffer, 1, sizeof(textFileBuffer), txtfile);
bikeNomad 3:6c91a6232c4a 125 // fprintf(stderr, "Read %d bytes\r\n", nread);
bikeNomad 1:9b1f3eb204ac 126 if (nread <= 0 || nread == sizeof(textFileBuffer)) {
bikeNomad 1:9b1f3eb204ac 127 goto done;
bikeNomad 1:9b1f3eb204ac 128 }
bikeNomad 0:84aaade0de8f 129 unsigned line = 1;
bikeNomad 1:9b1f3eb204ac 130 for (char *actionLine = strtok(textFileBuffer, "\r\n");
bikeNomad 1:9b1f3eb204ac 131 actionLine;
bikeNomad 1:9b1f3eb204ac 132 actionLine = strtok(0, "\r\n"), line++) {
bikeNomad 1:9b1f3eb204ac 133 char *p;
bikeNomad 0:84aaade0de8f 134 float startTime = strtof(actionLine, &p);
bikeNomad 0:84aaade0de8f 135 if (p == actionLine)
bikeNomad 0:84aaade0de8f 136 goto done;
bikeNomad 0:84aaade0de8f 137
bikeNomad 0:84aaade0de8f 138 char *q;
bikeNomad 0:84aaade0de8f 139 float endTime = strtof(p, &q);
bikeNomad 0:84aaade0de8f 140 if (q == p)
bikeNomad 0:84aaade0de8f 141 goto done;
bikeNomad 0:84aaade0de8f 142
bikeNomad 0:84aaade0de8f 143 char const *outName;
bikeNomad 7:dba9221acf48 144 float onDelay, offDelay, minOnTime;
bikeNomad 7:dba9221acf48 145 DigitalOut *out = bass->outputNamed(++q, &outName, &onDelay, &offDelay, &minOnTime);
bikeNomad 0:84aaade0de8f 146 if (!out) {
bikeNomad 3:6c91a6232c4a 147 fprintf(stderr, "%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q);
bikeNomad 0:84aaade0de8f 148 goto done;
bikeNomad 0:84aaade0de8f 149 }
bikeNomad 7:dba9221acf48 150
bikeNomad 7:dba9221acf48 151 startTime -= onDelay;
bikeNomad 7:dba9221acf48 152 startTime -= remainder(startTime, SECONDS_PER_CHUNK);
bikeNomad 7:dba9221acf48 153 if (startTime < 0.0) startTime = 0.0;
bikeNomad 7:dba9221acf48 154
bikeNomad 7:dba9221acf48 155 endTime -= offDelay;
bikeNomad 7:dba9221acf48 156 endTime += remainder(endTime, SECONDS_PER_CHUNK);
bikeNomad 7:dba9221acf48 157 if (endTime < startTime + minOnTime)
bikeNomad 7:dba9221acf48 158 endTime = startTime + minOnTime;
bikeNomad 7:dba9221acf48 159
bikeNomad 7:dba9221acf48 160 fprintf(stderr, "%d %f %f %s\r\n", line, startTime, endTime, outName);
bikeNomad 0:84aaade0de8f 161
bikeNomad 6:ea8136eb6976 162 addAction(startTime, bass->onState(), out, toupper(outName[0]));
bikeNomad 6:ea8136eb6976 163 addAction(endTime, bass->offState(), out, outName[0]);
bikeNomad 0:84aaade0de8f 164 }
bikeNomad 4:f009306756b3 165 fprintf(stderr, "Added %d actions\r\n", numActions);
bikeNomad 4:f009306756b3 166 qsort(actions, numActions, sizeof(Action), &Action::compare);
bikeNomad 7:dba9221acf48 167 for (int i = 0; i < numActions; i++ ) {
bikeNomad 7:dba9221acf48 168 fprintf(stderr, "%f %c\r\n", actions[i].actionTime, actions[i].code);
bikeNomad 7:dba9221acf48 169 }
bikeNomad 0:84aaade0de8f 170 retval = true;
bikeNomad 0:84aaade0de8f 171
bikeNomad 0:84aaade0de8f 172 done:
bikeNomad 1:9b1f3eb204ac 173
bikeNomad 0:84aaade0de8f 174 fclose(txtfile);
bikeNomad 0:84aaade0de8f 175 return retval;
bikeNomad 0:84aaade0de8f 176 }
bikeNomad 4:f009306756b3 177