Log in Page Discussion History Go to the site toolbox

RPI Haptics:Vibrobyte Firmware

From BluWiki

Contents

Firmware, r3

Implemented

  • Addressing
  • Mode recognition
  • Multiple outputs
  • Amplitude, Sustain and Frequency (with smooth switching)
  • Reprogramming
  • LED display
  • Grouping
  • Ask modes: blinkinput, blinkoutput, batterylife

Unimplemented

  • Ask mode: quality

Source

helper.h

#define packetSize 3

#define modeMask B11000000
#define modeShift 6

#define outputMode B00
#define ledMode B01
#define askMode B10
#define reprogramMode B11

#define waveMask B00110000
#define waveShift 4
#define amplitudeMask B00001100
#define amplitudeShift 2
#define sustainMask B00000011
#define sustainShift 0
#define frequencyMask B11111000
#define frequencyShift 3
#define outputsMask B00000111
#define outputsShift 0

#define frequencyRange 31.
#define lowFrequency 1.
#define highFrequency 32.
#define amplitudeRange 3.
#define lowAmplitude .05
#define highAmplitude 1.
#define sustainRange 3.
#define lowSustain .1
#define highSustain 1

#define irMask B00110000
#define irShift 4
#define redMask B00001111
#define redShift 0
#define greenMask B11110000
#define greenShift 4
#define blueMask B00001111
#define blueShift 0

#define irMax 3.
#define rgbMax 15.

#define allLeds 4
#define rgbLeds 3

#define askBatteryLife 0
#define askSignalQuality 1
#define askPacketEcho 2
#define askOutputEcho 3

#define keyMask B00111111
#define keyShift 0

#define reOutputMode 0
#define reAddGroup 1
#define reRemoveGroup 2
#define reResetGroup 3

#define outputRepeat 0
#define outputSingle 1
#define outputOff 2

#define oneThird 1./3.

#define qualityWindow 100

int nullPacket[packetSize] = {191, 186, 154};
int ledPins[4] = {7, 5, 6, 9};
int outputPins[3] = {3, 10, 11};

int packet[packetSize];
int packetPosition = 0;

int address = 1;
long groups = 0;

float ledIntensity[allLeds] = {255., 230., 200., 255.};
float leds[allLeds];

int outputModeState = outputRepeat;
int waves[rgbLeds];
float amplitudes[rgbLeds], frequencies[rgbLeds], sustains[rgbLeds],counters[rgbLeds];

int qualityPosition = 0;
int quality = 0;
boolean qualityNote[qualityWindow];

int askState = askBatteryLife;

Pauline.pde

#include "helper.h"

void setup() {
  Serial.begin(28800);

  for(int i = 0; i < 3; i++)
    pinMode(outputPins[i], OUTPUT);
  for(int i = 0; i < 4; i++)
    pinMode(ledPins[i], OUTPUT);

  if(askState == askBatteryLife)
    displayBatteryLife();
}

void loop() {
  if(askState == askPacketEcho) {
    zeroLeds();
    setLed(1, Serial.available() > 0 ? 1 : 0); // red when receiving data
  }
  while(Serial.available() > 0) {    
    packet[packetPosition] = Serial.read();
    packetPosition = (packetPosition + 1) % packetSize;
    sync();
    if(packetPosition == 0)
      processPacket();
  }
  updateOutputs();
}

void sync() {
  if(
  packet[0] == nullPacket[2] &&
    packet[1] == nullPacket[0] &&
    packet[2] == nullPacket[1]) {
    resetPacket();
    packetPosition = (packetPosition + 2) % packetSize;
    noteSync(false);
    if(askState == askPacketEcho)
      setLed(3, 1);
  } 
  else if(
  packet[0] == nullPacket[1] &&
    packet[1] == nullPacket[2] &&
    packet[2] == nullPacket[0]) {
    resetPacket();
    packetPosition = (packetPosition + 1) % packetSize;
    noteSync(false);
    if(askState == askPacketEcho)
      setLed(3, 1);
  } 
  else if(isNullPacket()) {
    noteSync(true);
    if(askState == askPacketEcho)
      setLed(3, 0);
  }
}

void noteSync(boolean inSync) {
  if(qualityNote[qualityPosition])
    quality--;
  qualityNote[qualityPosition] = inSync;
  if(inSync)
    quality++;
  qualityPosition = (qualityPosition + 1) % qualityWindow;
}

void resetPacket() {
  packet[0] = nullPacket[0];
  packet[1] = nullPacket[1];
  packet[2] = nullPacket[2];
}

boolean isNullPacket() {
  return
    packet[0] == nullPacket[0] &&
    packet[1] == nullPacket[1] &&
    packet[2] == nullPacket[2];
}

void processPacket() {
  if(askState == askSignalQuality)
    displayLedBar(quality == 0 ? 0 : (float) quality / (float) qualityWindow);
  if(!isNullPacket() && (packet[0] == 255 || packet[0] == address || inGroup(254 - packet[0]))) {
    if(askState == askPacketEcho)
      setLed(2, 1); // green when a packet is received for this vibrobyte
    int mode = (packet[1] & modeMask) >> modeShift;
    switch(mode) {
    case outputMode: 
      {
        int wave = (packet[1] & waveMask) >> waveShift;
        float amplitude = grab(packet[1], amplitudeMask, amplitudeShift, amplitudeRange, lowAmplitude, highAmplitude);
        float sustain = grab(packet[1], sustainMask, sustainShift, sustainRange, lowSustain, highSustain);
        float frequency = grab(packet[2], frequencyMask, frequencyShift, frequencyRange, lowFrequency, highFrequency);
        int outputs = select(packet[2], outputsMask, outputsShift);
        for(int i = 0; i < 3; i++) {
          if(outputs & (B100 >> i)) {
            waves[i] = wave;
            amplitudes[i] = amplitude;
            frequencies[i] = frequency;
            sustains[i] = sustain;
            if(outputModeState == outputSingle)
              counters[i] = 0;
          }
        }
      }
      break;

    case ledMode: 
      {
        leds[0] = grab(packet[1], irMask, irShift, irMax);
        leds[1] = grab(packet[1], redMask, redShift, rgbMax);
        leds[2] = grab(packet[2], greenMask, greenShift, rgbMax);
        leds[3] = grab(packet[2], blueMask, blueShift, rgbMax);
        updateLeds();
      }
      break;

    case askMode: 
      {
        switch(packet[2]) {
        case askBatteryLife:  
          {
            askState = askBatteryLife;
            displayBatteryLife();
          }
          break;

        case askSignalQuality:  
          {
            askState = askSignalQuality;
          }
          break;

        case askPacketEcho: 
          {
            askState = askPacketEcho;
          }
          break;

        case askOutputEcho: 
          {
            askState = askOutputEcho;
          }
          break;
        }
      }
      break;

    case reprogramMode: 
      {
        int key = select(packet[1], keyMask, keyShift);
        int value = packet[2];
        switch(key) {
        case reOutputMode: 
          {
            outputModeState = value;
          }
          break;

        case reAddGroup:
          groups = groups | (1 << value);
          break;

        case reRemoveGroup:
          groups = groups & ~(1 << value);
          break;

        case reResetGroup:
          groups = 0;
          break;
        }
      }
      break;
    }
  } 
  else {
    if(askState == askPacketEcho)
      setLed(2, 0);
  }
}

boolean inGroup(int group) {
  return groups & (1 << group);
}

void displayBatteryLife() {
  displayLedBar((float) analogRead(1) / 1024.);
}

// output functions

float lastTime = 0;
void updateOutputs() {
  float time = (float) millis() / 1000.;
  float timeDiff = time - lastTime;
  float wave;
  for(int i = 0; i < 3; i++) {
    if(outputModeState == outputOff) {
      digitalWrite(outputPins[i], LOW);
    } 
    else {
      counters[i] += timeDiff * frequencies[i];
      if(outputModeState == outputRepeat)
        counters[i] = mod(counters[i], 1.);
      float value = amplitudes[i] * getWave(waves[i], counters[i], sustains[i]);
      analogWrite(outputPins[i], 255. * value);
      if(askState == askOutputEcho)
        setLed(i + 1, value);
    }
  }
  lastTime = time;
}

float getWave(int wave, float c, float s) {
  if(c < s) {
    switch(wave) {
    case 0: 
      return 1; // square
    case 1: 
      return c / s; // saw ascending
    case 2: 
      return 1 - (c / s); // saw descending
    default: 
      return sin(PI * (c / s)); // absolute sine
    }
  } 
  else {
    return 0;
  }
}

// led functions

/*
  takes a float from 0-1 and displays it on the LEDs
 1/3 will light red
 5/6 will light red and green and half-light blue
 */
void displayLedBar(float value) {
  zeroLeds();
  for(int i = 0; i < 3; i++) {
    if(value > oneThird) {
      leds[i + 1] = 1;
      value -= oneThird;
    } 
    else {
      leds[i + 1] = value * 3;
      break;
    }
  }
  updateLeds();
}

void zeroLeds() {
  for(int i = 0; i < allLeds; i++)
    leds[i] = 0;
}

void updateLeds() {
  digitalWrite(ledPins[0], leds[0]);
  for(int i = 1; i < allLeds; i++)
    setLed(i, leds[i]);
}

void setLed(int led, float pwm) {
  if(pwm == 0)
    digitalWrite(ledPins[led], LOW);
  else
    analogWrite(ledPins[led], pwm * ledIntensity[led]);
}

// aux

float mod(float x, float y) {
  return x - ((int) (x / y) * y);
}

float grab(int packet, int mask, int shift, float max) {
  return ((float) select(packet, mask, shift)) / max;
}

float grab(int packet, int mask, int shift, float range, float low, float high) {
  return map((float) select(packet, mask, shift) / range, low, high);
}

int select(int packet, int mask, int shift) {
  return (packet & mask) >> shift;
}

float map(float input, float low, float high) {
  return input * (high - low) + low;
}

Site Toolbox:

TOOLBOX
LANGUAGES
GNU Free Documentation License 1.2
This page was last modified on 12 July 2008, at 19:52.
Disclaimers - About BluWiki