From: Thomas Pietrzak Date: Tue, 14 Jun 2011 19:15:23 +0000 (+0000) Subject: Arduino library X-Git-Url: https://git.thomaspietrzak.com/?a=commitdiff_plain;h=699fc09fe9f778ca413a76292ef7e78be0331741;p=tactonlibrary.git Arduino library git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@29 47cf9a05-e0a8-4ed5-9e9b-101a649bc004 --- diff --git a/Arduino/Tacton/Tacton.cpp b/Arduino/Tacton/Tacton.cpp new file mode 100644 index 0000000..11bf828 --- /dev/null +++ b/Arduino/Tacton/Tacton.cpp @@ -0,0 +1,79 @@ +#include "WProgram.h" +#include "Tacton.h" + + +/*Tacton::Tacton() +:_nbframes(0), _patterns(NULL), _durations(NULL), _frequencies(NULL), _amplitudes(NULL) +{ +}*/ + +Tacton::Tacton(unsigned int nbframes, byte *desc) +:_nbframes(nbframes), _patterns((byte *)malloc(nbframes * sizeof(byte))), _durations((unsigned int *)malloc(nbframes * sizeof(unsigned int))), _frequencies((unsigned int *)malloc(nbframes * sizeof(unsigned int))), _amplitudes((byte *)malloc(nbframes * sizeof(byte))) +{ + if (isValid()) + { + for(int i = 0 ; i < nbframes ; i++) + { + _patterns[i] = desc[6*i]; + _durations[i] = (((unsigned int)(desc[6*i+1])) << 8) | ((unsigned int)(desc[6*i+2])); + _frequencies[i] = (((unsigned int)(desc[6*i+3])) << 8) | ((unsigned int)(desc[6*i+4])); + _amplitudes[i] = desc[6*i+5]; + } + } +} + +/*Tacton::Tacton(const Tacton &tacton) +:_nbframes(tacton._nbframes), _patterns((byte *)malloc(tacton._nbframes * sizeof(byte))), _durations((unsigned int *)malloc(tacton._nbframes * sizeof(unsigned int))), _frequencies((unsigned int *)malloc(tacton._nbframes * sizeof(unsigned int))), _amplitudes((byte *)malloc(tacton._nbframes * sizeof(byte))) +{ + for(int i = 0 ; i < tacton._nbframes ; i++) + { + _patterns[i] = tacton._patterns[i]; + _durations[i] = tacton._durations[i]; + _frequencies[i] = tacton._frequencies[i]; + _amplitudes[i] = tacton._amplitudes[i]; + } +}*/ + +Tacton::~Tacton() +{ + free(_patterns); + free(_durations); + free(_frequencies); + free(_amplitudes); +} + +void Tacton::play(const TactonPlayer &player) const +{ + if (isValid()) + for (int i = 0 ; i < _nbframes ; i++) + player.beep(_patterns[i], _durations[i], _frequencies[i], _amplitudes[i]); +} + +/*Tacton& Tacton::operator=(const Tacton &t) +{ + if (this == &t) + return *this; + if (_patterns) + free(_patterns); + if (_durations) + free(_durations); + if (_frequencies) + free(_frequencies); + if (_amplitudes) + free(_amplitudes); + _nbframes = t._nbframes; + _patterns = (byte *)malloc(_nbframes * sizeof(byte)); + _durations = (unsigned int *)malloc(_nbframes * sizeof(unsigned int)); + _frequencies = (unsigned int *)malloc(_nbframes * sizeof(unsigned int)); + _amplitudes = (byte *)malloc(_nbframes * sizeof(byte)); + for(int i = 0 ; i < _nbframes ; i++) + { + _patterns[i] = t._patterns[i]; + _durations[i] = t._durations[i]; + _frequencies[i] = t._frequencies[i]; + _amplitudes[i] = t._amplitudes[i]; + } + + return *this; +}*/ + \ No newline at end of file diff --git a/Arduino/Tacton/Tacton.h b/Arduino/Tacton/Tacton.h new file mode 100644 index 0000000..8ef8ae1 --- /dev/null +++ b/Arduino/Tacton/Tacton.h @@ -0,0 +1,29 @@ +#ifndef _TACTON_ +#define _TACTON_ + +#include "WProgram.h" + +#include + +class Tacton +{ + public: +// Tacton(); + Tacton(unsigned int nbframes, byte *desc); +// Tacton(const Tacton &tacton); + ~Tacton(); + + void play(const TactonPlayer &player) const; + +// Tacton & operator=(const Tacton &t); + boolean isValid() const { return _patterns && _durations && _frequencies && _amplitudes; } + + private: + unsigned int _nbframes; + byte *_patterns; + unsigned int *_durations; + unsigned int *_frequencies; + byte *_amplitudes; +}; + +#endif diff --git a/Arduino/Tacton/keywords.txt b/Arduino/Tacton/keywords.txt new file mode 100644 index 0000000..4cc4b36 --- /dev/null +++ b/Arduino/Tacton/keywords.txt @@ -0,0 +1,3 @@ +Tacton KEYWORD1 +play KEYWORD2 +isValid KEYWORD2 \ No newline at end of file diff --git a/Arduino/TactonManager/TactonManager.cpp b/Arduino/TactonManager/TactonManager.cpp new file mode 100644 index 0000000..91e7093 --- /dev/null +++ b/Arduino/TactonManager/TactonManager.cpp @@ -0,0 +1,109 @@ +#include "WProgram.h" +#include "TactonManager.h" + +TactonManager::TactonManager(TactonPlayer *player) +: _nbplays(0), _nbtactons(0), _player(player) +{ +} + +void TactonManager::add(unsigned int nbframes, byte *desc) +{ + if (_nbtactons < MAXTACTONS) + { + _tactons[_nbtactons] = new Tacton(nbframes, desc); + if (_tactons[_nbtactons]) + { + Serial.println("Tacton added"); + _nbtactons++; + } + } +} + +const Tacton *TactonManager::get(byte numtacton) const +{ + if (numtacton < _nbtactons) + return _tactons[numtacton]; + else + return NULL; +} + +void TactonManager::clear() +{ + for (int i = 0 ; i < _nbtactons ; i++) + delete _tactons[i]; + _nbtactons = 0; + _nbplays = 0; +} + +void TactonManager::addPlay(byte index, unsigned long timestamp) +{ + if (index >= _nbtactons || _nbplays >= MAXPLAYBUFFER) + return; + _playindex[_nbplays] = index; + _playtimestamps[_nbplays] = timestamp; + _nbplays++; +} + +void TactonManager::play(byte index) +{ + if (index < _nbtactons) + _tactons[index]->play(*_player); +} + +void TactonManager::play(unsigned int nbframes, byte *desc) +{ + Tacton t(nbframes, desc); + t.play(*_player); +} + +void TactonManager::setOffset(unsigned long timestamp) +{ + _offset = timestamp; +} + +void TactonManager::checkPlay() +{ + unsigned long now = millis() - _offset; +/* if (_nbplays == 0 || _playtimestamps[0] > now) + return; + Serial.print("Play at "); + Serial.println(now, DEC); + play(_playindex[0]); + //shift other plays + for (int i = 0 ; i < _nbplays ; i++) + { + _playindex[i] = _playindex[i + i]; + _playtimestamps[i] = _playtimestamps[i + i]; + } + _nbplays--;*/ + + int i = 0, j = 0; + while (_nbplays > 0 && i < MAXPLAYBUFFER && _playtimestamps[i] < now) + { + //TEST + Serial.print("Play "); + Serial.println(_playtimestamps[i], DEC); + Serial.print(" at "); + Serial.println(now, DEC); + // + play(_playindex[i]); + i++; + _nbplays--; + } + if (i == 0) + return; + //shift not played tactons + for (j = 0 ; i + j < MAXPLAYBUFFER ; j++) + { + _playindex[j] = _playindex[j + i]; + _playtimestamps[j] = _playtimestamps[j + i]; + } + //erase shifted values +/* for (i = j ; i < MAXPLAYBUFFER ; i++) + { + _playindex[i] = 0xff; + _playtimestamps[i] = 0xffffffff; + }*/ +} + + \ No newline at end of file diff --git a/Arduino/TactonManager/TactonManager.h b/Arduino/TactonManager/TactonManager.h new file mode 100644 index 0000000..5d89970 --- /dev/null +++ b/Arduino/TactonManager/TactonManager.h @@ -0,0 +1,39 @@ +#ifndef _TACTONMANAGER_ +#define _TACTONMANAGER_ + +#include "WProgram.h" + +#include +#include + +#define MAXTACTONS 16 +#define MAXPLAYBUFFER 10 + +class TactonManager +{ + public: + TactonManager(TactonPlayer *player); + +// void add(const Tacton &t); + void add(unsigned int nbframes, byte *desc); + const Tacton *get(byte numtacton) const; + + void play(byte index); + void play(unsigned int nbframes, byte *desc); + void addPlay(byte index, unsigned long timestamp); + void checkPlay(); + void setOffset(unsigned long timestamp); + + void clear(); + + private: + byte _nbplays; + byte _nbtactons; + Tacton *_tactons[MAXTACTONS]; + byte _playindex[MAXPLAYBUFFER]; + unsigned long _playtimestamps[MAXPLAYBUFFER]; + TactonPlayer *_player; + unsigned long _offset; +}; + +#endif diff --git a/Arduino/TactonManager/keywords.txt b/Arduino/TactonManager/keywords.txt new file mode 100644 index 0000000..ca231bc --- /dev/null +++ b/Arduino/TactonManager/keywords.txt @@ -0,0 +1,7 @@ +TactonManager KEYWORD1 +get KEYWORD2 +add KEYWORD2 +clear KEYWORD2 +play KEYWORD2 +addPlay KEYWORD2 +checkPlay KEYWORD2 \ No newline at end of file diff --git a/Arduino/TactonPlayer/TactonPlayer.cpp b/Arduino/TactonPlayer/TactonPlayer.cpp new file mode 100644 index 0000000..b8a7a3f --- /dev/null +++ b/Arduino/TactonPlayer/TactonPlayer.cpp @@ -0,0 +1,27 @@ +#include "WProgram.h" +#include "TactonPlayer.h" + +TactonPlayer::TactonPlayer(byte nbtactors, byte *pins) +:_nbtactors(nbtactors), _pins(pins) +{ + for (int i = 0 ; i < nbtactors ; i++) + pinMode(pins[i], OUTPUT); +} + +void TactonPlayer::beep(byte pattern, unsigned int duration, unsigned int frequency, byte amplitude) const +{ + int i; + long del = (long)(1000000 / frequency); + long looptime = (long)((((long)duration) * 1000) / (del * 2)); + for (i = 0 ; i < looptime ; i++) + { + for (int j = 0 ; j < 8 ; j++) + if (j < _nbtactors && (pattern & (0x01 << j))) + analogWrite(_pins[j], amplitude); + delayMicroseconds(del); + for (int j = 0 ; j < 8 ; j++) + if (j < _nbtactors && (pattern & (0x01 << j))) + analogWrite(_pins[j], 0); + delayMicroseconds(del); + } +} diff --git a/Arduino/TactonPlayer/TactonPlayer.h b/Arduino/TactonPlayer/TactonPlayer.h new file mode 100644 index 0000000..775f9f6 --- /dev/null +++ b/Arduino/TactonPlayer/TactonPlayer.h @@ -0,0 +1,24 @@ +#ifndef _TACTONPLAYER_ +#define _TACTONPLAYER_ + +#include "WProgram.h" + +class TactonPlayer +{ + public: + TactonPlayer(byte nbtactors, byte *pins); + + //8bits pattern => max 8 tactors, change type if using more + void beep(byte pattern, unsigned int duration, unsigned int frequency, byte amplitude) const; + + void debug1() { analogWrite(_pins[0], 255); delay(200); analogWrite(_pins[0], 0); delay(100);} + void debug2() { analogWrite(_pins[1], 255); delay(200); analogWrite(_pins[1], 0); delay(100); } + void debug3() { analogWrite(_pins[2], 255); delay(200); analogWrite(_pins[2], 0); delay(100); } + void debug4() { analogWrite(_pins[3], 255); delay(200); analogWrite(_pins[3], 0); delay(100); } + + private: + byte _nbtactors; + byte *_pins; +}; + +#endif diff --git a/Arduino/TactonPlayer/keywords.txt b/Arduino/TactonPlayer/keywords.txt new file mode 100644 index 0000000..2e2fd22 --- /dev/null +++ b/Arduino/TactonPlayer/keywords.txt @@ -0,0 +1,6 @@ +TactonPlayer KEYWORD1 +beep KEYWORD2 +debug1 KEYWORD2 +debug2 KEYWORD2 +debug3 KEYWORD2 +debug4 KEYWORD2 \ No newline at end of file diff --git a/Arduino/wristbandTactons/wristbandTactons.pde b/Arduino/wristbandTactons/wristbandTactons.pde new file mode 100644 index 0000000..e512d44 --- /dev/null +++ b/Arduino/wristbandTactons/wristbandTactons.pde @@ -0,0 +1,141 @@ +#include +#include +#include +byte pins[] = { + 3, 11, 9, 5}; +TactonPlayer player(4, pins); +TactonManager manager(&player); + +void* operator new(size_t n, void * p) { + return p; +} +void* operator new(size_t n) { + return malloc(n); +} +void operator delete (void * p) { + free(p); +}; + +byte command = 0; +byte posbuf = 0; +unsigned int nbf = 0; +byte buffer[60]; +//unsigned long start = 0; +boolean active = false; + +void setup() +{ + Serial.begin(57600); + player.debug1(); + player.debug2(); + player.debug3(); + player.debug4(); +} + +void loop() +{ + byte index; + unsigned long timestamp; + + if (Serial.available() > 0) + { + if (command == 0) + command = Serial.read(); + switch(command) + { + //set the timestamp to 0, and watch for scheduled tactons + case 'S': +// start = millis(); + manager.setOffset(millis()); + command = 0; + active = true; + break; + //stop watching scheduled tactons, and erase registered tactons + case 'Q': + command = 0; + manager.clear(); + active = false; + break; + //register a tacton + case 'N': + if (nbf == 0 && Serial.available() >= 2) + nbf = (((unsigned int) Serial.read()) << 8) | ((unsigned int) Serial.read()); + if (nbf > 0) + { + //DO NOT OVERFLOW max(nbf): 10 + while (posbuf < nbf * 6 && Serial.available() > 0) + { + buffer[posbuf] = Serial.read(); + posbuf++; + } + if (posbuf >= nbf*6) + { + manager.add(nbf, buffer); + posbuf = 0; + command = 0; + nbf = 0; + } + } + break; + //play a specified tacton + case 'V': + if (nbf == 0 && Serial.available() >= 2) + nbf = (((unsigned int) Serial.read()) << 8) | ((unsigned int) Serial.read()); + if (nbf > 0) + { + //DO NOT OVERFLOW max(nbf): 10 + while (posbuf < nbf * 6 && Serial.available() > 0) + { + buffer[posbuf] = Serial.read(); + posbuf++; + } + if (posbuf >= nbf*6) + { + manager.play(nbf, buffer); + posbuf = 0; + command = 0; + nbf = 0; + } + } + break; + //play a registered tacton + case 'T': + if (Serial.available() >= 1) + { + index = Serial.read(); + manager.play(index); + command = 0; + Serial.print("Play"); + Serial.println(index, DEC); + } + break; + //schedule the play of a registered tacton + case 'P': + if (Serial.available() >= 5) + { + index = Serial.read(); + timestamp = (((unsigned long)Serial.read()) << 24) | \ + (((unsigned long)Serial.read()) << 16) | \ + (((unsigned long)Serial.read()) << 8) | \ + (((unsigned long)Serial.read())); + Serial.print("Plan "); + Serial.println(timestamp, DEC); +/* Serial.print(" played at "); + Serial.print(timestamp + start, DEC); + Serial.print(" shift="); + Serial.println(start, DEC);*/ + manager.addPlay(index, timestamp); + command = 0; + } + break; + //unknown command: do nothing + default: + command = 0; + break; + } + } + + if (active) + manager.checkPlay(); +} +