lilypad touch sound example

// XYZ textile pad
// (procedural abstraction)
void analogPullup(int pin, boolean activate)
{  
  pinMode(14+pin, INPUT); // magic to active pullups 14 is the numbering of the analog pins
  digitalWrite(14+pin, activate ? HIGH : LOW); 
  // if activate is true then HIGH else LOW  <--- pseudocode
} 
// establish a potential difference between two  analog pins
void analog_establish_potential(int pinhigh, int pinlow)
{
  pinMode(14+pinhigh,OUTPUT); // 
  digitalWrite(14+pinhigh, HIGH); //3.3v

  pinMode(14+pinlow,OUTPUT); // 
  digitalWrite(14+pinlow, LOW);  //0v
}
// data abstraction (reuse which allows for scaling this to a lot of sensors and cool stuff)
const int left_strip_pin=0;
const int right_strip_pin=1;
const int top_strip_pin=2;
const int bottom_strip_pin= 3;
const int led_pin = 13;

void setup() {
  pinMode(led_pin, OUTPUT); 
  Serial.begin(9600); // debugging
}

void loop() {
  delay(500);  // slow sensing down so we have time to read values on serial console
  analog_establish_potential(top_strip_pin, bottom_strip_pin);
  analogPullup(right_strip_pin, true);
  analogPullup(left_strip_pin, true);
// analogRead functions numbers from 0 (not 14)!
  int sensorValue = analogRead(right_strip_pin);
  Serial.print(sensorValue); Serial.print(' ');
  
  if(sensorValue < 900)
  {
    // disable pullup to get an accurate value
   analogPullup(right_strip_pin, false);
  analogPullup(left_strip_pin, false);
  int sensorValue = analogRead(right_strip_pin);
  Serial.print(sensorValue);Serial.print("v ");
  
  // now we do left and right
 analog_establish_potential(left_strip_pin, right_strip_pin);
  analogPullup(top_strip_pin, false);
  analogPullup(bottom_strip_pin, false);
// analogRead functions numbers from 0 (not 14)!
   sensorValue = analogRead(bottom_strip_pin);
  Serial.print(sensorValue); Serial.print("h ");
  //  int ledFadeValue = map(sensorValue, 300, 700, 0, 255);
//  analogWrite(led_pin, ledFadeValue);     
  }
  Serial.println();
 }

// Touch Synth
// Copyright 2009 Adrian Freed. All Rights Reserved.
// tested on the lilypad
// requires rework to deal with different port assignments on the mega
//

//shorthands to turn on the built-in pullup resistors for each pin

inline void digitalPullup(byte pin, boolean b) { pinMode(pin, INPUT); digitalWrite(pin, b?HIGH:LOW); }
#if defined(__AVR_ATmega1280__)
inline void analogPullup(byte pin, boolean b) { digitalPullup(pin+54,b); }

#else
inline void analogPullup(byte pin, boolean b) { digitalPullup(pin+14,b); }
#endif


const byte speakerPin = 0; 	//a0
const byte speakerPinbis = 1;	 // differential drive for extra loudness and lower power consumption
 const boolean debugging = false;
void setup()
{
  if(debugging)
  {	 
      Serial.begin(9600);
  }
         pinMode(speakerPin, OUTPUT);	// sets the speakerPin to be an output
         pinMode(speakerPinbis, OUTPUT);	// sets the other speakerPin to be an output
}

//touch sensing on the 14 digial pins on ports d and b
// http://www.arduino.cc/en/Reference/PortManipulation
typedef struct tr
{
   byte t[14+8]; // >1 when touched. The  number is larger the better your bodies path is to ground
} touchresult;

struct tr touchsense(int pins); // a bit field to set which pins you want to be touch active.


#define TRANGE 32
struct tr touchsense(unsigned long pins)
{
  byte portd = pins &0xff;
  byte portb = (pins>>8) &0x3f;
  byte portc = (pins>>13)&0xff;
  byte i,j;
  byte result[TRANGE];
  touchresult r= { 0,0,0,0, 0,0,0,0 ,0,0,0,0, 0,0};
  
  
  // concurrent sensing for portb
   portb &= ~DDRB; // don't mess with direction of existing output pins
                   // xxxhow do we know what input pins are in use?
                   // how do we not disturb state of existing output pins?
if(portb)
 {
  PORTB &= ~portb;         // low level
  DDRB |= portb;           // discharge
 for(i=0;i<TRANGE;++i)
    result[i] = 0;
   
  DDRB &= ~portb;
  PORTB |= portb;
  
   result[0] = PINB;
    result[1] = PINB;
    result[2] = PINB;
      result[3] = PINB;
        result[4] = PINB;
          result[5] = PINB;
            result[6] = PINB;
              result[7] = PINB;
                result[8] = PINB;
                  result[9] = PINB;
                    result[10] = PINB;
                      result[11] = PINB;
                        result[12] = PINB;
                          result[13] = PINB;
                            result[14] = PINB;

                           result[15] = PINB;
 result[16] = PINB;
    result[17] = PINB;
    result[18] = PINB;
      result[19] = PINB;
        result[20] = PINB;
          result[21] = PINB;
            result[22] = PINB;
              result[23] = PINB;
                result[24] = PINB;
                  result[25] = PINB;
                    result[26] = PINB;
                      result[27] = PINB;
                        result[28] = PINB;
                          result[29] = PINB;
                            result[30] = PINB;

                           result[31] = PINB; 
  for(i=2;i<TRANGE;++i)
  {
 //       Serial.println(result[i], HEX);
      for(j=0;j<6;++j)
      {   
         if(portb&(1<<j))
           r.t[j+8] += !(result[i] & (1<<j));
      }
  }
 }
 // concurrent sensing for portc
   portc &= ~DDRC; // don't mess with direction of existing output pins
                   // xxxhow do we know what input pins are in use?
                   // how do we not disturb state of existing output pins?
if(portc)
 {
  PORTC &= ~portc;         // low level
  DDRC |= portc;           // discharge
 for(i=0;i<TRANGE;++i)
    result[i] = 0;
   
  DDRC &= ~portc;
  PORTC |= portc;
  
   result[0] = PINC;
    result[1] = PINC;
    result[2] = PINC;
      result[3] = PINC;
        result[4] = PINC;
          result[5] = PINC;
            result[6] = PINC;
              result[7] = PINC;
                result[8] = PINC;
                  result[9] = PINC;
                    result[10] = PINC;
                      result[11] = PINC;
                        result[12] = PINC;
                          result[13] = PINC;
                            result[14] = PINC;

                           result[15] = PINC;
 result[16] = PINC;
    result[17] = PINC;
    result[18] = PINC;
      result[19] = PINC;
        result[20] = PINC;
          result[21] = PINC;
            result[22] = PINC;
              result[23] = PINC;
                result[24] = PINC;
                  result[25] = PINC;
                    result[26] = PINC;
                      result[27] = PINC;
                        result[28] = PINC;
                          result[29] = PINC;
                            result[30] = PINC;

                           result[31] = PINC; 
  for(i=2;i<TRANGE;++i)
  {
 //       Serial.println(result[i], HEX);
      for(j=0;j<8;++j)
      {   
         if(portc&(1<<j))
           r.t[j+14] += !(result[i] & (1<<j));
      }
  }
 }

 // concurrent sensing for port D
  portd &= ~DDRD; // don't mess with direction of existing output pins
                   // xxxhow do we know what input pins are in use?
                   // how do we not disturb state of existing output pins?

 
 if(portd)
 {
  PORTD &= ~portd;         // low level
  DDRD |= portd;           // discharge
 for(i=0;i<TRANGE;++i)
    result[i] = 0;
  DDRD &= ~portd;
  PORTD |= portd;
  
  result[0] = PIND;
    result[1] = PIND;
    result[2] = PIND;
      result[3] = PIND;
        result[4] = PIND;
          result[5] = PIND;
            result[6] = PIND;
              result[7] = PIND;
                result[8] = PIND;
                  result[9] = PIND;
                    result[10] = PIND;
                      result[11] = PIND;
                        result[12] = PIND;
                          result[13] = PIND;
                            result[14] = PIND;

                           result[15] = PIND;
 result[16] = PIND;
    result[17] = PIND;
    result[18] = PIND;
      result[19] = PIND;
        result[20] = PIND;
          result[21] = PIND;
            result[22] = PIND;
              result[23] = PIND;
                result[24] = PIND;
                  result[25] = PIND;
                    result[26] = PIND;
                      result[27] = PIND;
                        result[28] = PIND;
                          result[29] = PIND;
                            result[30] = PIND;

                           result[31] = PIND;
  
  for(i=2;i<TRANGE;++i)
  {
 //       Serial.println(result[i], HEX);
      for(j=0;j<8;++j)
      {   if(portd&(1<<j))
              r.t[j] += !(result[i]  & (1<<j));
      }
  }
 }

  return r;
}
static int pitches[] =
{
    523,
    554,
    587,
    622,
    659,
    698,
    740,
    784,
    831,
    880,
    932,
    988,
    2*523,
    2*554,
    2*587,
    2*622,
    2*659,
    2*698,
    2*740,
    2*784,
    2*831,
    2*880,
    2*932,
    2*988,
};



 	 
 // differential pulse trains. The marktospacepercentage controls timbre (and amplitude for small values).
//  The frequency determines pitch. Use a high impedence driver: 30-100Ohms or a piezo.
void beep (unsigned frequencyInHertz, unsigned timeInMilliseconds, unsigned marktospacepercentage)     // the sound producing function
{	 
          int x;	
         static int swap=0; 
          unsigned long delayAmount = 1000000L/frequencyInHertz;
          unsigned long markdelay = delayAmount*marktospacepercentage/1000l;
          unsigned        long spacedelay = (delayAmount*(1000l-marktospacepercentage))/1000l;
          int loopTime = (int)((timeInMilliseconds*500l)/(delayAmount));
      
          while(loopTime--)	 
          {	
                    pinMode(speakerPin, OUTPUT);	// sets the speakerPin to be an output
               pinMode(speakerPinbis, OUTPUT);	// sets the other speakerPin to be an output
 
              digitalWrite(speakerPin,swap);
               digitalWrite(speakerPinbis,!swap);
              delayMicroseconds(markdelay);
                       pinMode(speakerPin, INPUT);	// sets the speakerPin to be an output
                 pinMode(speakerPinbis, INPUT);	// sets the other speakerPin to be an output

               delayMicroseconds(spacedelay);
          }	
         swap = !swap; 
}	 
  
void loop ()
{
 // read the keys
struct tr r = touchsense(0xcffcUL);
 
    
 // sound a short pitch for each touch using the touch value to determine loudness/timbre 
  for(int i = 0; i < 21; i++)
  {
    int key =r.t[i];

    if(key>0 &&i!=13 && i!=speakerPin && i!=speakerPinbis)
     {
       if(debugging)
       {
          Serial.print(i); Serial.print(" ");
           Serial.println(key);
 
       }
         beep(pitches[i]/4,100,key);
     }
  }

 
}

#include <stdarg.h>
void touchsensepins(int l, ...)
{
  va_list argp;
  unsigned long res = 0;

  va_start(argp, l);
  int i = l;

  do
  {
      res |= 1UL <<i;
  }
  while((i = va_arg(argp, int))!=-1);
  
  touchsense(res);
  va_end(argp);
}