/**
 * grab_pipe.c
 *
 * Written by Evan Raskob 2002-2003
 * :: devices [at] lowfrequency [dot] org ::
 *
 * pipe-based dj/saxophone audio/video controller
 *
 * Platform: PIC18F442
 * Uses 4 momentary switches on (top to bottom) RB7,RB6,RB5,RB4
 * Uses 2 ADC channels for a crossfader potentiometer RA,RA1
 * Uses 2 ADC channels for an accelerometer (y,x) RA2,RA3
 * Uses 1 ADC channel for rotary pot RA4
 *
 *
 * Not for use without permission of the author.
 */


/* Standard Include for 16F876 Chip */
#include <18F452.h>
/* library of midi functions (expanded in midi.c) */
#include "midi.h"

#device PIC18F452    ADC=10

//this is the ADC control register
#byte ADCON0   =     0x1F

#define  HIGH     0x1
#define  LOW      0x0



#FUSES HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP

/* Delay for 20 mhz crystal */
#use delay (clock=20000000)

/* Setup buit-in RS232 serial ports to work work at MIDI speeds */
#use rs232(baud=MIDI_BAUD_RATE, xmit=PIN_C6,rcv=PIN_C7)

int sendByte (byte byteToSend) {
        if (byteToSend < 0) output_bit(PIN_B1, HIGH);

        putc(byteToSend);
        return 0;
}

/** DEBUG **
//Setup buit-in RS232 serial ports to work work at serial port speeds
#use rs232(baud=9600, xmit=PIN_C4,rcv=PIN_C5)
** END DEBUG **/

#use standard_io(B)


// send a midi NOTE ON message from the uart of the form [0x9n, note, vel]
// where n is the midi channel from 0-F, note and vel are 7-bit numbers
int midiNoteOn(byte channel, byte note, byte vel) {
        sendByte(MIDI_NOTE_ON | (channel & MIDI_CHANNEL_MASK));
        sendByte(MIDI_DATA_MASK & note);
        sendByte(MIDI_DATA_MASK & vel);
        return 0;
}

// send a midi NOTE ON message from the uart of the form [0x9n, note, velocity]
// where n is the midi channel from 0-F, note is a 7-bit number and velocity is 0
int midiNoteOFF(byte channel, byte note) {
        sendByte(MIDI_NOTE_ON | (channel & MIDI_CHANNEL_MASK));
        sendByte(MIDI_DATA_MASK & note);
        sendByte(MIDI_DATA_MASK & 0);
        return 0;
        return 0;
}


// send a midi PITCH BEND message from the uart of the form [0xEn, bendLSB, bendMSB ]
// where n is the midi channel from 0-F, and bendLSB and bendMSB are 7-bit numbers
// note that MIDI devices normally pack together bendLSB and bendMSB to make a 14-bit number
int midiPitchBend(byte channel, byte bendLSB, byte bendMSB) {
        sendByte(MIDI_PITCH_BEND | (channel & MIDI_CHANNEL_MASK));
        sendByte(MIDI_DATA_MASK & bendLSB);
        sendByte(MIDI_DATA_MASK & bendMSB);
        return 0;
}

/** NOT NEEDED
void setStatusLED(int state) {
   output_bit(PIN_B0, state);
}
**/

main()
{


   int8 switch1   = 0;
   int8 note1 = 67;
   // hooked up to pins B6
   int8 switch2   = 0;
   int8 note2 = 68;
   // hooked up to pins B5
   int8 switch3   = 0;
   int8 note3 = 69;
   // hooked up to pins B4
   int8 switch4   = 0;
   int8 note4 = 70;

   int8 tempSwitch= 0;

   int8 ySwitch1  = 0;
   int8 note5     = 50; 
   int8 ySwitch2  = 0;
   int8 note6     = 51;
   
   int lastSlide1 = 0;
   int lastSlide2 = 0;
   int16 slideADC = 0;


   bit_set(ADCON0,7);

   // Flash what yo momma gave ya
   //setStatusLED(HIGH);
   //output_high(PIN_B0);
   //delay_ms(650);
   //setStatusLED(LOW);
   //output_low(PIN_B0);
   //output_high(PIN_B1);
   delay_ms(650);
   //output_low(PIN_B1);

   //setStatusLED(LOW);
   //output_low(PIN_B0);
   //delay_ms(150);
   //setStatusLED(HIGH);
   //output_high(PIN_B0);
   //delay_ms(150);
   //setStatusLED(LOW);
   //output_low(PIN_B0);
   //delay_ms(10);

   setup_adc_ports( ALL_ANALOG );
   setup_adc(ADC_CLOCK_INTERNAL );


   while (TRUE)
   {

      //switches
      tempSwitch = input(PIN_B7);
      if (tempSwitch != switch1) {
        switch1 = tempSwitch;
        midiNoteOn(0, note1, switch1*64);
      }

      tempSwitch = input(PIN_B6);
      if (tempSwitch != switch2) {
        switch2 = tempSwitch;
        midiNoteOn(1, note2, switch2*64);
      }

      tempSwitch = input(PIN_B5);
      if (tempSwitch != switch3) {
        switch3 = tempSwitch;
        midiNoteOn(2, note3, switch3*64);
      }

      tempSwitch = input(PIN_B4);
      if (tempSwitch != switch4) {
        switch4 = tempSwitch;
        midiNoteOn(3, note4, switch4*64);
      }

      tempSwitch = input(PIN_B2);
      if (tempSwitch != ySwitch1) {
        ySwitch1 = tempSwitch;
        midiNoteOn(4, note5, ySwitch1*64);
      }

      tempSwitch = input(PIN_B1);
      if (tempSwitch != ySwitch2) {
        ySwitch2 = tempSwitch;
        midiNoteOn(5, note6, ySwitch2*64);
      }

      //crossfade up
      /**
      set_adc_channel(0);
      delay_ms(4);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(0, lastSlide1, lastSlide2);
      **/
      
      // crossfade down
      set_adc_channel(1);
      delay_ms(3);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(1, lastSlide1, lastSlide2);

      // neck rotation
      set_adc_channel(2);
      delay_ms(3);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(2, lastSlide1, lastSlide2);

      set_adc_channel(3);
      delay_ms(3);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(3, lastSlide1, lastSlide2);

      // tilt
      set_adc_channel(4);
      delay_ms(3);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(4, lastSlide1, lastSlide2);

      // slider2
      set_adc_channel(5);
      delay_ms(3);
      slideADC = read_adc();
      lastSlide1 = (slideADC & 0x00FF) >> 1;
      lastSlide2 = (slideADC & 0xFF00) >> 7;
      midiPitchBend(5, lastSlide1, lastSlide2);

   }
 }
