BabyGnusbuino code examples

From SGMK-SSAM-WIKI
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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?)
  
*/