BabyGnusbuino code examples

From SGMK-SSAM-WIKI
Revision as of 23:07, 21 September 2013 by Dusjagr (talk | contribs) (→‎Babynusbuino V-2 codes)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Babynusbuino V-2 codes

ThereMIDI code, in progress

#include "MIDI.h"            // you have to include the Gnusbuino MIDI library
 
MIDIMessage message;
int MIDI_delay = 20;

int pinInt = 0;
int pinOSC = 4;
int pinPWM = 1;

uint8_t input = 0;
uint8_t inputNext = 0;

uint16_t count = 0;
uint16_t countTMP = 0;

uint8_t countHB = 0;         
uint8_t countLB = 0; 
uint16_t countSQ = 0; 

int averaging = 1;

void setup() {  
  
  //TCCR0B = TCCR0B & 0b11111001; //timer pre-scaler divided by 8
  //TCCR0A = (TCCR0A & 0b00111100) | 0b01000010; //sets to CTC and toggle Mode
  //OCR0A = 12;
  
  GTCCR = (GTCCR & 0b11000000) | 0b00010100; //general Timer1
  TCCR1 = (TCCR1 & 0b01000000) | 0b10010100; //Timer1: enable pwm, set toggle,  prescaler 8

  OCR1C = 93; // testing the other timer1 now
  
  pinMode(pinInt, INPUT);
  pinMode(pinOSC, OUTPUT);
  pinMode(pinPWM, OUTPUT);
  analogWrite(pinPWM, 200);
}

void loop() {
  
  countTMP = 0;
  count = 0;
  
  for(int c = 0 ; c < averaging; c +=1) { 
  
    countTMP = 0; 
    
    input = digitalRead(pinInt);
  
    for (int16_t i = 0; i < 10130; i++){
  
      inputNext = digitalRead(pinInt);
  
      if(input != inputNext){
        countTMP = countTMP + 1;
        input=inputNext;
      }
    }
  
    count = count + countTMP;

  }

  count = count / averaging;
  
  countHB = (count >> 7) & 0x7F;
  countLB = count & 0x7F;
  countSQ = sqrt(count);
  
  MIDI.write(MIDI_CONTROLCHANGE,1,countHB);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);
  MIDI.write(MIDI_CONTROLCHANGE,2,countLB);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);              // give some ti
  MIDI.write(MIDI_CONTROLCHANGE,3,countSQ);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);              // give some ti
        
}

Testing Frequency output on Timer1

the following code makes nice chriping sounds...

#include "MIDI.h"            // you have to include the Gnusbuino MIDI library

int ledPin = 4;    // LED connected to digital pin 4

int wait = 300;

void setup()  { 

  //TCCR0B = TCCR0B & 0b11111001; //timer pre-scaler divided by 8
  //TCCR0A = (TCCR0A & 0b00111100) | 0b01000010; //sets to CTC and toggle Mode
  
  GTCCR = (GTCCR & 0b11000000) | 0b00010100; //general Timer1
  //TCCR1 = (TCCR1 & 0b01000000) | 0b10010100; //Timer1 set toggle, prescaler 8
  TCCR1 = (TCCR1 & 0b01000000) | 0b10010100; //playing with Timer1
  
  pinMode(ledPin, OUTPUT);
  
  //OCR1C = 93; // testing the other timer1 now
  

} 

void loop()  { 
  
  // fade in from min to max in increments of 1 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=1) { 
    // sets the value (range from 0 to 255):
    OCR1C = fadeValue;         
    // wait for 30 milliseconds to see the dimming effect    
    delay(3);                            
  } 
  
}

Frequency Counter to MIDI

#include "MIDI.h"            // you have to include the Gnusbuino MIDI library
 
MIDIMessage message;
int MIDI_delay = 10;

int pinInt = 0;

uint8_t input = 0;
uint8_t inputNext = 0;

uint16_t count = 0;
uint16_t countTMP = 0;

uint8_t countHB = 0;         
uint8_t countLB = 0; 
uint16_t countSQ = 0; 

int averaging = 4;

void setup() {  

  pinMode(pinInt, INPUT);
    
}

void loop() {
  
  countTMP = 0;
  count = 0;
  
  for(int c = 0 ; c < averaging; c +=1) { 
  
    countTMP = 0; 
    
    input = digitalRead(pinInt);
  
    for (int16_t i = 0; i < 10130; i++){
  
      inputNext = digitalRead(pinInt);
  
      if(input != inputNext){
        countTMP = countTMP + 1;
        input=inputNext;
      }
    }
  
    count = count + countTMP;

  }

  count = count / averaging;
  
  countHB = (count >> 7) & 0x7F;
  countLB = count & 0x7F;
  countSQ = sqrt(count);
  
  MIDI.write(MIDI_CONTROLCHANGE,1,countHB);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);
  MIDI.write(MIDI_CONTROLCHANGE,2,countLB);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);              // give some ti
  MIDI.write(MIDI_CONTROLCHANGE,3,countSQ);     // put new control change message into MIDI sending queue
  delay(MIDI_delay);              // give some ti
        
}

2 10bit sensors to MIDI

/*---------------------------------------------------------------------------------------------
 
  Gnusbuino MIDI Library 2012 by Michael Egger
 
  SEND CONTROL CHANGE EXAMPLE combined with RECEIVE NOTE
  Read a potentiometer and send its value as a continuous controller message
  Control an LED  
 
  This example code is in the public domain.
 
--------------------------------------------------------------------------------------------- */
/* The circuit:
 * Potentiometer attached to analog input on pin 3, center pin of the potentiometer to the analog pin
 * one side pin (either one) to ground,  the other side pin to +5V
 * Put an LED on pin 4 to turn it on and off.
 */
 

//#include "GnusbuinoMIDI.h"

#include "MIDI.h"            // you have to include the Gnusbuino MIDI library
 
MIDIMessage message;
 
int LED = 0;
int LED2 = 1;

int sensorPin = 2; 
int sensorValue = 0;         // variable to store the value coming from the sensor
int sentValue = -1;          // we only want to send data when there's something changing
                             // so we have to keep track of the last value that was sent to the host
uint8_t sensorValueHB = 0;         // High byte
uint8_t sensorValueLB = 0;         // Low byte
 
int sensorPin2 = 4; 
int sensorValue2 = 0;         
int sentValue2 = -1; 

uint8_t sensorValue2HB = 0;         
uint8_t sensorValue2LB = 0;        

int MIDI_delay = 10;
 

void setup() {               // nothing to do in setup, pins are inputs by default
 
  pinMode(LED, OUTPUT);     
  pinMode(LED2, OUTPUT); 
  digitalWrite (LED2,HIGH); 

 
}
 
 
void loop() {
  
  //delay (200);
  
  sensorValue = analogRead(sensorPin);
  sensorValue2 = analogRead(sensorPin2);    // analogRead returns 0-1023, we need 0-127
  
  if (sensorValue != sentValue) {                         // compare actual readout to last sent value    
 
      //MIDI.write(MIDI_CONTROLCHANGE, controller number , controller value )
      
      sensorValueHB = sensorValue >> 3;
      sensorValueLB = sensorValue & 0x7;
      
        MIDI.write(MIDI_CONTROLCHANGE,1,sensorValueHB);     // put new control change message into MIDI sending queue
        sentValue = sensorValue;                          // store last sent value
        delay(MIDI_delay);              // give some time for sending, otherwhise the MIDI queue could fill up
        MIDI.write(MIDI_CONTROLCHANGE,2,sensorValueLB);     // put new control change message into MIDI sending queue
        delay(MIDI_delay);              // give some ti
        sentValue = sensorValue;
  }
 
   
  

  if (sensorValue2 != sentValue2) {                         // compare actual readout to last sent value    
 
      sensorValue2HB = sensorValue2 >> 3;
      sensorValue2LB = sensorValue2 & 0x7;
       
        MIDI.write(MIDI_CONTROLCHANGE,3,sensorValue2HB);     // put new control change message into MIDI sending queue
        sentValue = sensorValue;                          // store last sent value
        delay(MIDI_delay);              // give some time for sending, otherwhise the MIDI queue could fill up
        MIDI.write(MIDI_CONTROLCHANGE,4,sensorValue2LB);     // put new control change message into MIDI sending queue
        delay(MIDI_delay);              // give some ti
        sentValue2 = sensorValue2;             
  }
 
    
 
  if (MIDI.read(&message)) {
 
        if(message.command == MIDI_CONTROLCHANGE) {
              analogWrite(LED,(message.value*2));        // MaxMSP actually sends "noteon x 0" instead of "noteoff"
 
        }
       delay(10);              // give some time for sending, otherwhise the MIDI queue could fill up 
    }
  
}

Old Baby-Codes

setup()

best to set the pins used for programming via USB again as outputs and low, before starting your program

void setup()
{ // Set pins
 
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);
  digitalWrite(2, LOW);
 

}

PWM Heartbeat

/*
babygnusbuino: Fading


 */


int PWM_Pin = 0;    // LED connected to digital pin 0
int PWM_value = 0;

int wait = 30;

volatile unsigned char e = 0;
 
void setup()
{  
  // Timer Init
  TCCR0A = (0 << WGM02) | (0 << WGM01) | (0<< WGM00);    // Normal Mode 000
  TCCR0B = (0 << CS02) | (0 << CS01) | (1<< CS00);       // Clock Select no prescaling 001
  TIMSK = (1 << TOIE1);                                  // Overflow interrupt is enabled
  sei();                                                 // set Global Interrupt Enable

 
  // Set pins
  pinMode(PWM_Pin, OUTPUT);
  digitalWrite(0, LOW);

}
 
void loop()
{
 
  for (int c = 0; c < 255; c++) {
    PWM_value = c; 
    delay (wait);
  }
  
  for (int c = 255; c > 0; c--) {
    PWM_value = c; 
    delay (wait);
  }
  
}
 
 
//Overflow routine for Timer 1
ISR(TIM1_OVF_vect) {
 
  if(e==255) {
     e=0;
     digitalWrite(PWM_Pin, HIGH);
  }
 
  if (PWM_value == e) {  
     digitalWrite(PWM_Pin, LOW);
  }

  e++;
}

3 Channels PWM

/*
babygnusbuino: PWM 3 Channels


 */


int PWM_Pin0 = 0;    // LED connected to digital pin 0
int PWM_Pin1 = 1;    // LED connected to digital pin 0
int PWM_Pin2 = 2;    // LED connected to digital pin 0

int PWM_Pin0_value = 0;
int PWM_Pin1_value = 0;
int PWM_Pin2_value = 0;

int wait = 300;

volatile unsigned char e = 0;
 
void setup()
{  
  // Timer Init
  TCCR0A = (0 << WGM02) | (0 << WGM01) | (0<< WGM00);    // Normal Mode 000
  TCCR0B = (0 << CS02) | (0 << CS01) | (1<< CS00);       // Clock Select no prescaling 001
  TIMSK = (1 << TOIE1);                                  // Overflow interrupt is enabled
  sei();                                                 // set Global Interrupt Enable

  // Set pins
  pinMode(PWM_Pin0, OUTPUT);
  pinMode(PWM_Pin1, OUTPUT);
  pinMode(PWM_Pin2, OUTPUT);
 
}
 
void loop()
{
 
  for (int c = 0; c < 255; c++) {
    PWM_Pin2_value = c; 
    delay (wait);
  }
  
  for (int c = 255; c > 0; c--) {
    PWM_Pin2_value = c; 
    delay (wait);
  }
 
}
 
//Overflow routine for Timer 1
ISR(TIM1_OVF_vect) {
 
  if(e==255) {
     e=0;
     digitalWrite(PWM_Pin0, HIGH);
     digitalWrite(PWM_Pin1, HIGH);
     digitalWrite(PWM_Pin2, HIGH);

    }
 
  if (PWM_Pin0_value == e) {  
     digitalWrite(PWM_Pin0, LOW);
  }
  
  if (PWM_Pin1_value == e) {  
     digitalWrite(PWM_Pin1, LOW);
  }
  
  if (PWM_Pin2_value == e) {  
     digitalWrite(PWM_Pin2, LOW);
  }

  e++;
}

RGB Led

// based largely on Atmel's AVR138: Low-Jitter Multi-Channel Software PWM Application Note:
// http://www.atmel.com/dyn/resources/prod_documents/doc8020.pdf
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
#define CHMAX 3 // maximum number of PWM channels
#define PWMDEFAULT 0x00 // default PWM value at start up for all channels
 
#define RED_CLEAR (pinlevelB &= ~(1 << RED)) // map RED to PB4
#define GREEN_CLEAR (pinlevelB &= ~(1 << GREEN)) // map GREEN to PB3
#define BLUE_CLEAR (pinlevelB &= ~(1 << BLUE)) // map BLUE to PB0
 
//! Set bits corresponding to pin usage above
#define PORTB_MASK  (1 << PB4 | 1 << PB3| 1 << PB0)
 
#define set(x) |= (1<<x) 
#define clr(x) &=~(1<<x) 
#define inv(x) ^=(1<<x)
 
#define RED 		PB4
#define GREEN 		PB3
#define BLUE 		PB0
#define LED_PORT 	PORTB
#define LED_DDR 	DDRB

// function prototypes
void delay_ms(uint16_t ms);
void init();
void blend(int r, int g, int b, int da); 
 
// global variables
unsigned char compare[CHMAX];
volatile unsigned char compbuff[CHMAX];
unsigned long lfsr = 1;
unsigned char temp;

int main() {
	
	init();
	
	for (;;) { // forever
			
		lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1
		temp = (unsigned char) lfsr; // take lowest eight bits
		temp = (unsigned char) (lfsr >> 24);
		int r = temp & 0xff;
		
		lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1
		temp = (unsigned char) lfsr; // take lowest eight bits
		temp = (unsigned char) (lfsr >> 24);
		int g = temp & 0xff;
		
		lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1
		temp = (unsigned char) lfsr; // take lowest eight bits
		temp = (unsigned char) (lfsr >> 24);
		int b = temp & 0xff;
		
		for (int a = 0; a < 64; a++) { 
			_delay_ms(20);
			blend(r,g,b,a); // r g b alpha    
		}
		
	}
}
 
 
void delay_ms(uint16_t ms) {
  while (ms) {
    _delay_ms(1);
    ms--;
  }
}
 
void init(void) {
  // set the direction of the ports
  LED_DDR set(RED);
  LED_DDR set(GREEN);
  LED_DDR set(BLUE);
  
  unsigned char i, pwm;
 
  CLKPR = (1 << CLKPCE);        // enable clock prescaler update
  CLKPR = 0;                    // set clock to maximum (= crystal)
 
  pwm = PWMDEFAULT;
 
  // initialise all channels
  for(i=0 ; i<CHMAX ; i++) {
    compare[i] = pwm;           // set default PWM values
    compbuff[i] = pwm;          // set default PWM values
  }
 
  TIFR = (1 << TOV0);           // clear interrupt flag
  TIMSK = (1 << TOIE0);         // enable overflow interrupt
  TCCR0B = (1 << CS00);         // start timer, no prescale
 
  sei();
}
 
 
ISR (TIM0_OVF_vect) {
  static unsigned char pinlevelB=PORTB_MASK;
  static unsigned char softcount=0xFF;
 
  PORTB = pinlevelB;            // update outputs
  
  if(++softcount == 0){         // increment modulo 256 counter and update
                                // the compare values only when counter = 0.
    compare[0] = compbuff[0];   // verbose code for speed
    compare[1] = compbuff[1];
    compare[2] = compbuff[2];
 
    pinlevelB = PORTB_MASK;     // set all port pins high
  }
  // clear port pin on compare match (executed on next interrupt)
  if(compare[0] == softcount) RED_CLEAR;
  if(compare[1] == softcount) GREEN_CLEAR;
  if(compare[2] == softcount) BLUE_CLEAR;
}


/*
blend color
@param r Red
@param g Green
@param b Blue
@param da Alpha: the factor how much the new color will be blended with the existing color. da = 0: no change, da = 255: new color will be set (no blending).
*/
void blend(int r, int g, int b, int da) {
  
  // source alpha
  int sa = 255 - da;
  
  int tr = (sa * compbuff[0] + da * r) + 128;
  int tg = (sa * compbuff[1] + da * g) + 128;
  int tb = (sa * compbuff[2] + da * b) + 128;
  
  compbuff[0] = ((tr>>8)+tr)>>8;
  compbuff[1] = ((tg>>8)+tg)>>8;
  compbuff[2] = ((tb>>8)+tb)>>8;
  
}

Flickering RGB Led

/*
flickering RGB LED! 
*/
#include <avr/io.h>
#include <util/delay.h>

unsigned long lfsr = 1;
unsigned char temp;

/**
 * delay
 * @param ms duration in milliseconds
 */
void delay_ms(uint16_t ms)
{
  for (uint16_t i = 0 ; i < ms ; i++) {
    _delay_ms (1); // Loop delay
  }
}
 
void setup()
{
  DDRB = 0xff;
}

void loop() {  
  lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); /* taps 32 31 29 1 */
  temp = (unsigned char) lfsr; // take lowest eight bits
  DDRB = ~temp; // declare those pins as output where temp is zero
  PORTB = temp << 2; // give the value of 0 to the output pins
  temp = (unsigned char) (lfsr >> 24);
  _delay_loop_2(temp<<7);
  delay_ms(100);
}

8-bit Noise

/* Pseudo-Random Bit Sequence Generator                     2009-11-25 */
/* Copyright (c) 2009 John Honniball, Dorkbot Bristol                  */
 
/*
 * For a discussion of PRBS generators, see The Art Of Electronics, by
 * Horowitz and Hill, Second Edition, pages 655 to 660. For more info
 * on Linear Feedback Shift Registers, see Wikipedia:
 *   http://en.wikipedia.org/wiki/Linear_feedback_shift_register
 * For the actual shift register taps, refer to this article on noise
 * generation for synthesisers:
 *   http://www.electricdruid.net/index.php?page=techniques.practicalLFSRs
 */
 
// Choose the same pin as the "Melody" example sketch
int speakerPin = 0;
 
int potiPin = A3;
 
unsigned int analogValue;
 
int samplingDelay;
 
unsigned long int reg;
 
void setup ()
{
  // Serial setup for debugging only; slows down the program far too much
  // for audible white noise
  //Serial.begin (9600);
 
  // Connect a piezo sounder between Ground and this pin
  pinMode (speakerPin, OUTPUT);
 
 
  // Arbitrary inital value; must not be zero
  reg = 0x551155aaL;
}
 
 
void loop ()
{
  unsigned long int newr;
  unsigned char lobit;
  unsigned char b31, b29, b25, b24;
 
  // Extract four chosen bits from the 32-bit register
  b31 = (reg & (1L << 31)) >> 31;
  b29 = (reg & (1L << 29)) >> 29;
  b25 = (reg & (1L << 25)) >> 25;
  b24 = (reg & (1L << 24)) >> 24;
 
  // EXOR the four bits together
  lobit = b31 ^ b29 ^ b25 ^ b24;
 
  // Shift and incorporate new bit at bit position 0
  newr = (reg << 1) | lobit;
 
  // Replace register with new value
  reg = newr;
 
  // Drive speaker pin from bit 0 of 'reg'
  digitalWrite (speakerPin, reg & 1);
 
  // Display 'reg' in the serial console for debugging only 
//  Serial.println (reg, HEX);
  samplingDelay = 1 + (2*(analogRead(potiPin)>>0));
  // Delay corresponds to 20kHz, but the actual frequency of updates
  // will be lower, due to computation time and loop overhead
  delayMicroseconds (samplingDelay);
 
  // If the above delay is increased to a few tens of milliseconds,
  // and the piezo sounder is replaced by an LED and a suitable series
  // resistor, a randomly flashing light will result. Several LEDs
  // could be driven from various bits of the shift register.
}


Crazy shit 8-bit symphony generator

/* Crazy shit 8-bit symphony generator                   */
/*     */
 
/*
 * inspired by:
 *  http://countercomplex.blogspot.com/2011/10/algorithmic-symphonies-from-one-line-of.html
 */
 
int speakerPin = 0;
 
int potiPin = A3;
 
long t = 0; 
int v = 0; 
int c = 0;

unsigned int analogValue;
 
void setup ()
{
  // Connect a piezo sounder between Ground and this pin
  pinMode (speakerPin, OUTPUT);

 
}
 
 
void loop ()
{
  /*
  for(t=0;;t++){
    c = (analogRead(potiPin)>>3); 
    v=t*((t>>14|t>>(8))&c&t>>c);
    analogWrite (speakerPin, v);
  }
  */
  
  for(t=0;;t++){
    c = (analogRead(potiPin)>>4); 
    v=t*((t>>5|t>>11)&c&t>>c);
    analogWrite (speakerPin, v);
  }
  
  /*
    for(t=0;;t++){
    c = (analogRead(potiPin)>>4); 
    v=t*((t>>7|t>>(c+4))&(c)&t>>(c*3));
    analogWrite (speakerPin, v);
  }
  */
  
}

test MIDI send receive

/*---------------------------------------------------------------------------------------------
 
  Gnusbuino MIDI Library 2012 by Michael Egger
 
  SEND CONTROL CHANGE EXAMPLE combined with RECEIVE NOTE
  Read a potentiometer and send its value as a continuous controller message
  Control an LED  
 
  This example code is in the public domain.
 
--------------------------------------------------------------------------------------------- */
/* The circuit:
 * Potentiometer attached to analog input on pin 3, center pin of the potentiometer to the analog pin
 * one side pin (either one) to ground,  the other side pin to +5V
 * Put an LED on pin 4 to turn it on and off.
 */
 

//#include "GnusbuinoMIDI.h"
#include "MIDI.h"            // you have to include the Gnusbuino MIDI library
 
MIDIMessage message;
 
int LED = 0;
int sensorPin = 2; 
int sensorValue = 0;         // variable to store the value coming from the sensor
int sentValue = -1;          // we only want to send data when there's something changing
                             // so we have to keep track of the last value that was sent to the host
int sensorValueLB = 0;
 
int sensorPin2 = 4; 
int sensorValue2 = 0;         // variable to store the value coming from the sensor
int sentValue2 = -1; 
 
void setup() {               // nothing to do in setup, pins are inputs by default
 
 //digitalWrite(LED,1);
 pinMode(LED, OUTPUT);     

 
}
 
 
void loop() {
 
  sensorValue = analogRead(sensorPin) / 8;
  sensorValue2 = analogRead(sensorPin2) / 8;    // analogRead returns 0-1023, we need 0-127
  
  if (sensorValue != sentValue) {                         // compare actual readout to last sent value    
 
      //MIDI.write(MIDI_CONTROLCHANGE, controller number , controller value )
 
        MIDI.write(MIDI_CONTROLCHANGE,1,sensorValue);     // put new control change message into MIDI sending queue
        sentValue = sensorValue;                          // store last sent value
        delay(10);              // give some time for sending, otherwhise the MIDI queue could fill up
  }
 
   
  

  if (sensorValue2 != sentValue2) {                         // compare actual readout to last sent value    
 
       
        MIDI.write(MIDI_CONTROLCHANGE,2,sensorValue2);     // put new control change message into MIDI sending queue
        sentValue2 = sensorValue2;                          // store last sent value
        delay(10);              // give some time for sending, otherwhise the MIDI queue could fill up
  }
 
    
 
  if (MIDI.read(&message)) {
 
        if(message.command == MIDI_CONTROLCHANGE) {
              digitalWrite(LED,message.value);        // MaxMSP actually sends "noteon x 0" instead of "noteoff"
         
         
 
        }
       delay(10);              // give some time for sending, otherwhise the MIDI queue could fill up 
    }
  
}

BabyMidiTurbidoGnusbuino Code (SendReceive Midi on PB3 and PB4)

/*---------------------------------------------------------------------------------------------

  Gnusbuino MIDI Library 2012 by Michael Egger
 
  SEND CONTROL CHANGE EXAMPLE
  Read a potentiometer and send its value as a continuous controller message  
  
  This example code is in the public domain.

--------------------------------------------------------------------------------------------- */
/* The circuit:
 * Potentiometer attached to analog input 1 (pin2 aka PB3), center pin of the potentiometer to the analog pin
 * one side pin (either one) to ground,  the other side pin to +5V
 */

 
#include "MIDI.h"            // you have to include the Gnusbuino MIDI library

MIDIMessage message;

int averaging = 10;
int sensorPin = 3;
int MIDI_delay = 30;
int LED = 4;
long sensorValue = 0;         // variable to store the value coming from the sensor
int sensorValueTMP = 0;
uint8_t sensorValueHB = 0;         // variable to store the value coming from the sensor
uint8_t sensorValueLB = 0;         // variable to store the value coming from the sensor
int sentValue = -1;          // we only want to send data when there's something changing
                             // so we have to keep track of the last value that was sent to the host

void setup() {               // nothing to do in setup, pins are inputs by default

pinMode (LED, OUTPUT);
pinMode (LED, OUTPUT);
digitalWrite(LED,1);
delay (100);
digitalWrite(LED,0);
delay (100);
digitalWrite(LED,1);
delay (100);
digitalWrite(LED,0);
delay (100);
digitalWrite(LED,1);

}


void loop() {
  for(int c = 0 ; c < (averaging - 1); c +=1) { 
    sensorValueTMP = analogRead(sensorPin);                       // analogRead returns 0-1023, we need 0-127
    sensorValue = sensorValue + sensorValueTMP;
    delay (20);
  }
  
  sensorValue = sensorValue / (averaging);
  
  sensorValueHB = sensorValue / 8;
  sensorValueLB = sensorValue << 5;
  sensorValueLB = sensorValueLB >> 5;

 // if (sensorValue != sentValue) {                         // compare actual readout to last sent value    
       
      //MIDI.write(MIDI_CONTROLCHANGE, controller number , controller value )

        MIDI.write(MIDI_CONTROLCHANGE,1,sensorValueHB);     // put new control change message into MIDI sending queue
        delay(MIDI_delay);
        MIDI.write(MIDI_CONTROLCHANGE,2,sensorValueLB);     // put new control change message into MIDI sending queue
        delay(MIDI_delay);              // give some time for sending, otherwhise the MIDI queue could fill up
        sentValue = sensorValue;                          // store last sent value
  //}
  
    

  if (MIDI.read(&message)) {
      
        switch(message.command) {
            case MIDI_NOTEON:
              digitalWrite(LED,message.value);        // MaxMSP actually sends "noteon x 0" instead of "noteoff"
              delay(MIDI_delay);
              break;

            case MIDI_NOTEOFF:
              digitalWrite(LED,0);        
              delay(MIDI_delay);
        }
    }

  if (MIDI.read(&message)) {                            // see if we have received a new MIDI message and store it in our variable
                                                          // don't forget the ampersand (&) before the variable name !
        if(message.command == MIDI_CONTROLCHANGE) {
                analogWrite(LED,message.value);              
        }
    }  

}


/*---------------------------------------------------------------------------------------------
Some exercises:

  - how small can the delay be without stalling the transmission ? 
  - use two control channels to augment the resolution
  - add more potentiometers  (using an array for the values?)
  
*/