Big Mouth Billy Bass automation library

Dependents:   BillyBass_with_SD

Committer:
bikeNomad
Date:
Thu Jun 20 15:03:49 2013 +0000
Revision:
8:ad0c038ebfc1
Parent:
7:dba9221acf48
Made main loop repeat forever; eliminated time shifting

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 if (numActions >= MAX_ACTIONS_PER_SONG) return false;
bikeNomad 7:dba9221acf48 88 actions[numActions++].set(_time, _state, _out, _code);
bikeNomad 7:dba9221acf48 89 return true;
bikeNomad 7:dba9221acf48 90 }
bikeNomad 7:dba9221acf48 91
bikeNomad 0:84aaade0de8f 92 bool Song::readActions()
bikeNomad 0:84aaade0de8f 93 {
bikeNomad 3:6c91a6232c4a 94 fprintf(stderr, "reading actions of %s\r\n", getTextFileName());
bikeNomad 1:9b1f3eb204ac 95
bikeNomad 0:84aaade0de8f 96 FILE *txtfile = fopen(getTextFileName(), "r");
bikeNomad 0:84aaade0de8f 97 if (!txtfile) {
bikeNomad 3:6c91a6232c4a 98 fprintf(stderr, "can't open %s\r\n", getTextFileName());
bikeNomad 0:84aaade0de8f 99 return false;
bikeNomad 1:9b1f3eb204ac 100 } else
bikeNomad 3:6c91a6232c4a 101 fprintf(stderr, "opened %s OK\r\n", getTextFileName());
bikeNomad 0:84aaade0de8f 102 bool retval = false;
bikeNomad 0:84aaade0de8f 103
bikeNomad 0:84aaade0de8f 104 BillyBass *bass = BillyBass::bassNumber(whichFish);
bikeNomad 0:84aaade0de8f 105 if (!bass) {
bikeNomad 3:6c91a6232c4a 106 fprintf(stderr, "No bass!\r\n");
bikeNomad 0:84aaade0de8f 107 goto done;
bikeNomad 0:84aaade0de8f 108 }
bikeNomad 0:84aaade0de8f 109
bikeNomad 0:84aaade0de8f 110 // read actions from file
bikeNomad 5:869b3711bdb3 111 static char textFileBuffer[ MAX_TEXT_FILE_LENGTH ];
bikeNomad 1:9b1f3eb204ac 112 memset(textFileBuffer, 0, sizeof(textFileBuffer));
bikeNomad 1:9b1f3eb204ac 113 int nread = fread(textFileBuffer, 1, sizeof(textFileBuffer), txtfile);
bikeNomad 3:6c91a6232c4a 114 // fprintf(stderr, "Read %d bytes\r\n", nread);
bikeNomad 1:9b1f3eb204ac 115 if (nread <= 0 || nread == sizeof(textFileBuffer)) {
bikeNomad 1:9b1f3eb204ac 116 goto done;
bikeNomad 1:9b1f3eb204ac 117 }
bikeNomad 0:84aaade0de8f 118 unsigned line = 1;
bikeNomad 1:9b1f3eb204ac 119 for (char *actionLine = strtok(textFileBuffer, "\r\n");
bikeNomad 1:9b1f3eb204ac 120 actionLine;
bikeNomad 1:9b1f3eb204ac 121 actionLine = strtok(0, "\r\n"), line++) {
bikeNomad 1:9b1f3eb204ac 122 char *p;
bikeNomad 0:84aaade0de8f 123 float startTime = strtof(actionLine, &p);
bikeNomad 0:84aaade0de8f 124 if (p == actionLine)
bikeNomad 0:84aaade0de8f 125 goto done;
bikeNomad 0:84aaade0de8f 126
bikeNomad 0:84aaade0de8f 127 char *q;
bikeNomad 0:84aaade0de8f 128 float endTime = strtof(p, &q);
bikeNomad 0:84aaade0de8f 129 if (q == p)
bikeNomad 0:84aaade0de8f 130 goto done;
bikeNomad 0:84aaade0de8f 131
bikeNomad 0:84aaade0de8f 132 char const *outName;
bikeNomad 7:dba9221acf48 133 float onDelay, offDelay, minOnTime;
bikeNomad 7:dba9221acf48 134 DigitalOut *out = bass->outputNamed(++q, &outName, &onDelay, &offDelay, &minOnTime);
bikeNomad 0:84aaade0de8f 135 if (!out) {
bikeNomad 3:6c91a6232c4a 136 fprintf(stderr, "%s line %d: bad outname \"%s\"\r\n", getTextFileName(), line, q);
bikeNomad 0:84aaade0de8f 137 goto done;
bikeNomad 0:84aaade0de8f 138 }
bikeNomad 7:dba9221acf48 139
bikeNomad 8:ad0c038ebfc1 140 #if FIX_TIMES
bikeNomad 7:dba9221acf48 141 startTime -= onDelay;
bikeNomad 7:dba9221acf48 142 if (startTime < 0.0) startTime = 0.0;
bikeNomad 7:dba9221acf48 143
bikeNomad 7:dba9221acf48 144 if (endTime < startTime + minOnTime)
bikeNomad 7:dba9221acf48 145 endTime = startTime + minOnTime;
bikeNomad 8:ad0c038ebfc1 146 #endif
bikeNomad 8:ad0c038ebfc1 147
bikeNomad 8:ad0c038ebfc1 148 startTime -= remainder(startTime, SECONDS_PER_CHUNK);
bikeNomad 8:ad0c038ebfc1 149 endTime += remainder(endTime, SECONDS_PER_CHUNK);
bikeNomad 7:dba9221acf48 150
bikeNomad 7:dba9221acf48 151 fprintf(stderr, "%d %f %f %s\r\n", line, startTime, endTime, outName);
bikeNomad 0:84aaade0de8f 152
bikeNomad 6:ea8136eb6976 153 addAction(startTime, bass->onState(), out, toupper(outName[0]));
bikeNomad 6:ea8136eb6976 154 addAction(endTime, bass->offState(), out, outName[0]);
bikeNomad 0:84aaade0de8f 155 }
bikeNomad 4:f009306756b3 156 fprintf(stderr, "Added %d actions\r\n", numActions);
bikeNomad 4:f009306756b3 157 qsort(actions, numActions, sizeof(Action), &Action::compare);
bikeNomad 8:ad0c038ebfc1 158 #if 0
bikeNomad 7:dba9221acf48 159 for (int i = 0; i < numActions; i++ ) {
bikeNomad 7:dba9221acf48 160 fprintf(stderr, "%f %c\r\n", actions[i].actionTime, actions[i].code);
bikeNomad 7:dba9221acf48 161 }
bikeNomad 8:ad0c038ebfc1 162 #endif
bikeNomad 0:84aaade0de8f 163 retval = true;
bikeNomad 0:84aaade0de8f 164
bikeNomad 0:84aaade0de8f 165 done:
bikeNomad 1:9b1f3eb204ac 166
bikeNomad 0:84aaade0de8f 167 fclose(txtfile);
bikeNomad 0:84aaade0de8f 168 return retval;
bikeNomad 0:84aaade0de8f 169 }
bikeNomad 4:f009306756b3 170