//=============================================================================
/*
 * Project name;
	MIDI_Bash2.c      v2.0
	(set TABS to 4)

 * Description;
	PIC16F876 based MIDI drum controller with 10 digital pads.
	This v2 saves drum setup to flash memory and has a
	volume pot that controls total drum velocity and can set
	individual drum pad velocities.

	When any button is pressed it sends a MIDI note-on signal
	to MIDI-out plug, which makes a MIDI device play a drum sound.
	v1.0 has no velocity info, all drum sounds are the same
	velocity (volume). v1.0 has 10 drum hit buttons.
	There are 2 other buttons; up/down
	If a drum is hit while either button is pressed the drum
	sound changes up/down to the next note (next drum sound).
	All notes are limited to MIDI channel 10 (standard for drums).

 * Test configuration;
    MCU:             PIC16F876 (NOT A)
    Dev.Board:       EasyPIC4
    Oscillator:      HS, 08.0000 MHz (2pin short-can xtal)
    SW:              mikroC v7.0.0.3

 * Version;
	v2.0	started 12/02/2009

	Specific for v2.0;
	On bootup it loads the previous settings (notes) for all 10 drums
	from non-volatile internal EEPROM. This keeps the same notes (sounds)
	on the 10 pads as when it was last used. When any drum sound is
	changed for a pad the new note data for that pad is now saved
	to internal EEPROM.

	Also for v2.0 is a "volume" pot that sets global velocity for all
	10 drums. This is a 0v-5v linear pot reading into PIC ADC input AN0,
	the PIC reads this voltage about 20 times per second and then
	sets the global MIDI "velocity" value that is used for all
	10 drums. So the pot can be adjusted in real time to add
	expression to the drums or just simply set global drum volume.
	Also, if BOTH up/down buttons are held down and a drum pad is
	hit, the current velocity (pot setting) is permanently set for
	that drum pad only. This allows each pad to have its own fixed
	velocity (if desired). These velocity settings are saved to
	EEPROM, to restore ANY ONE drum pad back to global velocity
	turn the pot to zero then hit that drum pad while pressing
	both the up/down buttons.

 * PIC pins (same as v1.0);
	RC6	out		serial MIDI out, manual bit banging (no usart needed)
	RC5 out		drum led, flashes at power up and when any pad is hit

	RC0 in      Note down button, pullup resistor, low=pressed
	RC1 in      Note up button, pullup resistor, low=pressed

	RB0-RB7 in  8 "drum" buttons (0-7), pullup resistor, low=pressed
	RC2 in      drum button (8), "
	RC3 in      drum button (9), "  (total 0-9 =10 drums)

	(v2.0 pin changes below)
	RA0 in		AN0 0v-5v analog ADC voltage in from "volume" pot

*/
//=============================================================================

// global vars

char sdata;				// disposable 2 bytes used for serial bit-banging;
char sbit;				// (must be first, need low place in ram for asm use)

//char i;               	// used for anything

char the_pad;			// the pad that was just hit

char the_note;			// the note to send to MIDI for this drum hit
char the_vel;			// the velocity to send to MIDI for this drum hit

char flash_address;		// (V2.0) to store drum note setup to PIC internal flash
char flash_data;		// "

char timer;             // (v2.0) inc on TMR0 overflow; used for ADC timing
char velocity;          // for global velocity (loudness) of the 10 drums

char note0;           	// MIDI note value for each of the 10 drum buttons
char note1;           	//  (which can be changed when device is operating)
char note2;           	//
char note3;           	//
char note4;           	//
char note5;           	//
char note6;           	//
char note7;           	//
char note8;           	//
char note9;           	//

char vel0;				// MIDI velocity used for each drum pad, only used
char vel1;				//  if it was specially set for that pad.
char vel2;				//
char vel3;				//
char vel4;				//
char vel5;				//
char vel6;				//
char vel7;				//
char vel8;				//
char vel9;				//

char wait_n0;			// used for debounce and afterpause for each drum note
char wait_n1;			//
char wait_n2;			//
char wait_n3;			//
char wait_n4;			//
char wait_n5;			//
char wait_n6;			//
char wait_n7;			//
char wait_n8;			//
char wait_n9;			//


// Constants used in my MIDI transmit funcions;
#define MIDI_CHANNEL 	10		// MIDI output channel (1-16) to drum machine
#define MIDI_NOTE_ON	(0b10010000 + (MIDI_CHANNEL-1)) // byte used to send MIDI note-on command
//#define MIDI_NOTE_ON	0b10011001 // byte used to send MIDI note-on command

#define NOTE_MIN        23      // lowest MIDI note that can be selected
#define NOTE_MAX        98		// highest " (Zoom MRS1608 range is 31-70) 40 sounds
								// (Roland D-20 drum range is 35-97) 63 sounds
								// (Tested; D-20 has 23/24 are metornome sounds
								// they work but at fixed max velocity only)

#define DEB_COUNT		21	// debounce wait count for debounce timer;
							// PIC 8Mhz prescale 32:1, so 21 TMR0 overflows = 84mS
#define DEB_COUNTSAFE	5	// safe period for after debounce special situations


#define PORT_MIDI		PORTC		// used for bit-banged serial out to MIDI
#define PIN_MIDI		6    		// "
#define PIN_LED_DRUM	PORTC.F5    // flashes a led when any drum button is pressed

#define PIN_DOWNBUT		PORTC.F0
#define PIN_UPBUT		PORTC.F1

// drums 0-7 input pins is PORTB.F0 - PORTB.F7
#define PIN_DRUM8		PORTC.F2    // with these 2 is 10 drums total
#define PIN_DRUM9		PORTC.F3

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//void  interrupt(void)
//{
   // is (TMR1) CCP2 capture int, so just clear TMR1 ??
//}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



//=============================================================================
//  WRITE_FLASH
//=============================================================================
void write_flash(void)
{
	//----------------------------------------------------
	// This writes one byte to the PIC internal EEPROM.
	// The byte written is the current drum "note" (sound)
	// for the selected pad;
	//
	// flash_address = the pad (0-9), is also the EEPROM address
	// flash_data = the note value to save for that pad
	//----------------------------------------------------

	// first check if a write is already in progress!! if so;
	// wait until it completes before this write starts.
	// this is a real issue for MIDI_Bash v2.0 as we can have
	// 2 or more drum pads adjusted at the same time...

	wf_wait:
	if(EECON1.WR == 1) goto wf_wait;

	// now is safe, so perform this write

	EEADR = flash_address;		// point to location to write
	EEDATA = flash_data;        // the byte to write

	EECON1.WREN = 1;            // set bit to allow writing operations

	// PIC safety feature requires these instructions exactly
	// for EEPROM write to commence... (as stated in PIC datasheet);
	asm {
		BSF STATUS, RP1			; set PIC to register Bank 3
		BSF STATUS, RP0			;

		MOVLW 0x55				; Write 55h to
		MOVWF EECON2			; EECON2
		MOVLW 0xAA				; Write AAh to
		MOVWF EECON2			; EECON2
		BSF EECON1, WR			; Start write operation

		BCF EECON1, WREN 		; clr bit to disable further writes (default)
	}

	// now the EEPROM write is happening...
	// we can return and do other stuff
}
//-----------------------------------------------------------------------------




//=============================================================================
//  READ_FLASH
//=============================================================================
void read_flash(void)
{
	//----------------------------------------------------
	// This reads one byte from the PIC internal non-volatile
	// EEPROM memory. This allows MIDI_Bash v2.0 to save the
	// drum pad setup so it will restore when next turned on.
	//
	// I have used simple global vars; flash_address, flash_data
	// so this can be converted to PIC assembler or other
	// language easily.
	//----------------------------------------------------

	EEADR = flash_address;		// point to location to read
	EECON1.RD = 1;				// set bit to start read operation
	flash_data = EEDATA;        // save the byte to my var
}
//-----------------------------------------------------------------------------



//=============================================================================
//  SEND_MIDI_BYTE
//=============================================================================
void send_midi_byte(void)
{
	//----------------------------------------------------
	// This version uses TMR0 for bit-banging, no usart needed.
	// I wrote this function in PIC assembler to speed it up as the
	// MikroC compiler SUCKS when it comes to fast bit manipulation.
	//-------------------------------------------------
	// NOTE! MIDI data is electrically inverted! ie MIDI bit=1 is PIC pin=O
	//
	// start bit, 8 data bits (LSBit first), then stop bit
	//
	// PIC 8MHz = 2MHz ticks, so MIDI at 31250 baud = 64 timer ticks
	// using TMR0 prescaled at 32:1 so 31250 baud  = 2 timer ticks
	// therefore whenever TMR0 bit1 changes = a baud
	//
	// This is a zero cumulative error system, even though there
	// is a variable 0-6 instruction delay for each bit
	// it still always re-syncs to TMR0,bit1 for the next bit.
	// Given that there is 64 insts between bits and that
	// the receiving device samples the bit right in the middle
	// (which is standard) this should give reliable serial
	// transmission. It will probably still work with an
	// internal RC osc at 4MHz too.. test later.
	//----------------------------------------------------
	sbit = 0;   // this is needed to make MikroC compiler recognise
	            // variables in the asm block below...
				// weird, but it is covered in MikroC help file.

	asm {
		;----------------------------
		; PIC 31250 baud MIDI bit-banging serial code - RomanBlack 2009
		; sends one byte out to MIDI port. byte is in sdata variable.
		; PIC 8 MHz, TMR0 is free-running and prescaled at 32:1
		; it is easily adapted to 4 Mhz or 16 Mhz, just change the prescale.
		; This assembler cource code is public domain, use it as you wish.
		;----------------------------
		; pre-delay, to sync to a "baud", then send start bit

		predelay:
        	BTFSC	TMR0, 1     	; pre-delay to sync baud with TMR0
			GOTO    predelay		;

		wbStart:
        	BTFSS	TMR0, 1			; again wait to ensure sync with baud
			GOTO    wbStart			;
			BCF     PORT_MIDI,PIN_MIDI ; send start bit (inverted remember)

		;----------------------------
		; now send the 8 serial bits, as 4 pairs of 2 bits (even then odd).
		; each bit tested first, then sync to baud using TMR0, then send bit.
		; 8 MHz PIC, each baud is 64 insts. jitter per baud is 0 to 2 insts.
		; system is zero-cumulative error, ie; it re syncs with every baud.
		; this gives very solid performance without needing a usart.

			MOVLW   4				; 4 bit pairs to send
			MOVWF   sbit			;

		serial_even:
			BTFSC   sdata,0			; test serial even bit
			GOTO	even1			;

		even0:
        	BTFSC	TMR0, 1			; wait for baud
			GOTO	even0			;
			BCF		PORT_MIDI,PIN_MIDI	; send bit (inverted remember)
			GOTO	serial_odd		;

		even1:
        	BTFSC	TMR0, 1			; wait for baud
			GOTO	even1			;
			BSF		PORT_MIDI,PIN_MIDI	; send bit (inverted remember)

		serial_odd:
			RRF		sdata,f         ; load next serial bit into sdata,0
			BTFSC   sdata,0			; test serial odd bit
			GOTO	odd1            ;

		odd0:
        	BTFSS	TMR0, 1			; wait for baud
			GOTO	odd0			;
			BCF		PORT_MIDI,PIN_MIDI	; send bit (inverted remember)
			GOTO	pair_done		;

		odd1:
        	BTFSS	TMR0, 1			; wait for baud
			GOTO	odd1			;
			BSF		PORT_MIDI,PIN_MIDI	; send bit (inverted remember)

		pair_done:
			RRF		sdata,f			; load next serial bit into sdata,0
			DECFSZ	sbit,f			; another bit pair was done, so test
			GOTO	serial_even		; bits left! so send another pair

		;----------------------------
		; send the stop bit

		wbStop:
        	BTFSC	TMR0, 1			; wait to sync with baud
			GOTO    wbStop			;
			BSF     PORT_MIDI,PIN_MIDI ; send stop bit (inverted remember)
	}
}
//-----------------------------------------------------------------------------



//=============================================================================
//  SEND_NOTE_ON
//=============================================================================
void send_note_on(void)
{
	//-------------------------------------------------
	// Sends 3 serial bytes out to MIDI port at 31250 baud;
	//   byte0	MIDI note on = 1001cccc (cccc = MIDI channel(1-16) -1)
	//   byte1	note 0-127 (the specific drum sound)
	//   byte2	velocity 0-127 (volume) i'm using fixed value of 100?
	//
	// This system just ties up the PIC while it sends
	// all 3 bytes. At standard MIDI 31250 baud that is less
	// than 1mS to send all 3 bytes so it shouldn't matter.
	// That is the fastest that MIDI can send drum messages anyway.
	//----------------------------------------------------

	// byte0 = MIDI specific note-on command
	sdata = MIDI_NOTE_ON;   	// data byte to send
	send_midi_byte();

	// byte1 = the note (which drum sound to play) MIDI range 0-127
	if(the_note > 127) the_note = 127;	// protect against illegal notes
	sdata = the_note;   		// data byte to send
	send_midi_byte();

	// byte2 = velocity (note volume) MIDI range 0-127
	// MIDI_Bash v2.0; gets value based on the specific velocity setting
	// for that pad, if that value is set to zero it uses global
	// velocity pot position
	if(the_vel > 127) the_vel = 127;	// protect against illegal velocity
	sdata = the_vel;			// data byte to send
	send_midi_byte();

	//----------------------------------------------------
}
//-----------------------------------------------------------------------------

//=============================================================================
//  DRUM_WAS_HIT
//=============================================================================
void drum_was_hit(void)
{
	//-------------------------------------------------
	// a drum pad was hit, so;
	//  if both up/down pressed; save new velocity to EEPROM
	//  if note down was pressed; save new note to EEPROM
	//  if note up was pressed; save new note to EEPROM
	//  then always play the drum sound
	//-------------------------------------------------

	if(PIN_DOWNBUT==0 && PIN_UPBUT==0)      // if BOTH up/down are pressed
	{
		// make global velocity the new set velocity for that pad only
		if(the_pad == 0) vel0 = velocity;
		if(the_pad == 1) vel1 = velocity;
		if(the_pad == 2) vel2 = velocity;
		if(the_pad == 3) vel3 = velocity;
		if(the_pad == 4) vel4 = velocity;
		if(the_pad == 5) vel5 = velocity;
		if(the_pad == 6) vel6 = velocity;
		if(the_pad == 7) vel7 = velocity;
		if(the_pad == 8) vel8 = velocity;
		if(the_pad == 9) vel9 = velocity;

		// save the new pad set velocity to EEPROM
		the_vel = velocity;
		flash_address = (32 + the_pad);
		flash_data = the_vel;
		write_flash();
	}

	else   // else NOT both buttons
	{
		if(PIN_DOWNBUT == 0)		// if DOWN was pressed
		{
			// change note
			the_note--;
			if(the_note < NOTE_MIN) the_note=NOTE_MIN;  // and limit at min/max
			flash_address = the_pad;
			flash_data = the_note;
			write_flash();			// write new note setting to EEPROM

			// and fix the pad setting in ram
			if(the_pad == 0) note0 = the_note;
			if(the_pad == 1) note1 = the_note;
			if(the_pad == 2) note2 = the_note;
			if(the_pad == 3) note3 = the_note;
			if(the_pad == 4) note4 = the_note;
			if(the_pad == 5) note5 = the_note;
			if(the_pad == 6) note6 = the_note;
			if(the_pad == 7) note7 = the_note;
			if(the_pad == 8) note8 = the_note;
			if(the_pad == 9) note9 = the_note;
		}

		else if(PIN_UPBUT == 0)		// else if UP was pressed
		{
			// change note
			the_note++;
			if(the_note > NOTE_MAX) the_note=NOTE_MAX;
			flash_address = the_pad;
			flash_data = the_note;
			write_flash();			// write new note setting to EEPROM

			// and fix the pad setting in ram
			if(the_pad == 0) note0 = the_note;
			if(the_pad == 1) note1 = the_note;
			if(the_pad == 2) note2 = the_note;
			if(the_pad == 3) note3 = the_note;
			if(the_pad == 4) note4 = the_note;
			if(the_pad == 5) note5 = the_note;
			if(the_pad == 6) note6 = the_note;
			if(the_pad == 7) note7 = the_note;
			if(the_pad == 8) note8 = the_note;
			if(the_pad == 9) note9 = the_note;
		}
	}

	// if no specific velocity is set for that pad (ie set to 0),
	// then use the global velocity to play this pad sound.
	if(the_vel == 0) the_vel = velocity;

	// now play the drum sound!
	send_note_on();         // send it to MIDI
}
//-----------------------------------------------------------------------------


//=============================================================================
//  MAIN
//=============================================================================
void main()
{
    //-------------------------------------------------
	// Setup PIC registers etc
	// Setup for 16F876;
    //-------------------------------------------------
	// setup ADC for MIDI_Bash v2.0;
	// we use only one ADC input; AN0 on PORTA.F0
	// which is used for a 0v-5v linear pot ("volume" pot)
	// we use left justified result, which means we only have to
	// read the hi byte; ADRESH (0v-5v = range 0-255)

	/*
	movlw b'10000001'
		  ; 7         AD clock (2 bits);
          ;  6         (using 10 = 32Tosc; slowest for best conversion)
          ;   5       ADC channel select (3 bits);
          ;    4       using AN0 = 000
          ;     3      "
          ;      2    conversion status bit
          ;       1   -not used
          ;        0  1=ADC on                       */
	ADCON0 = 0b10000001;

	/*
	movlw b'00001110'
		  ; 7         result right/left justified (0 = left just)
          ;  6        -not used
          ;   5       -not used
          ;    4      -not used
          ;     3     4bits, select ADC inputs/dig inputs setup
          ;      2     note! see datasheet, there are limited options...
          ;       1
          ;        0   (using 1110 = AN0 plus 4 digital inputs)   */
	ADCON1 = 0b00001110;


    //-------------------------------------------------
	// port pin directions;
	
	PORTA  = 0;
	TRISA  = 0b00000001;  	// PORTA; AN0=ADC in, other 4 are dig out
	PORTB  = 0;
	TRISB  = 0b11111111;   	// PORTB all in (drum0-drum7)
	PORTC  = 0;
	TRISC  = 0b00001111;	// PORTC; RC6 = serial out to MIDI)
	                        // RC0=down button in, RC1=up button in
							// RC2=drum8 in, RC3=drum9 in
	INTCON = 0;          // clear INTCON

	//-------------------------------------------------
 	// TMR0 setup
  	/*                  ; OPTION_REG setup 16F876
	movlw b'00000100'
         ; 7         portb pullups, 1=disabled, 0=enabled
         ;  6        RBO/INT pin edge select, 1= rising, 0=falling edge
         ;   5       TMR0 clock source, 1=ext RA4, 0=int clock
         ;    4      TMR0 source ext RA4 edge, 0=rising edge
         ;     3     PSA prescaler assign, 1=WDT, 0=TMR0
         ;      2    these three are the 3 bit prescaler rate;
         ;       1   000-111 = 2-256 for TMR0, 1-128 for WDT
         ;        0   (using 100 = 32:1 prescale)      */
	OPTION_REG = 0b00000100;

	// PIC 8MHz = 2MHz ticks, so MIDI at 31250 baud = 64 timer ticks
	// using TMR0 prescaled at 32:1 so 31250 baud  = 2 timer ticks
	// therefore whenever TMR0 bit1 changes = a baud

	// I think for different PIC clock speeds you can just
	// change the prescale value and leave the rest of the code as is.
	// PIC 4MHz use 16:1
	// PIC 8MHz use 32:1     (this code)
	// PIC 16MHz use 64:1

   	//-------------------------------------------------
	// EECON1 (used for my v2.0 to use EEPROM flash)

	EECON1 = 0;

   	//-------------------------------------------------

   	// TMR1 setup
   	/*                   ; timer1 control
   	movlw b'00000000'
         ; 7-------  na
         ; -6------  na
         ; --5-----  TIMER1 prescaler... two bits (5,4)
         ; ---4----   00=1, 01=2, 10=4, 11=8 prescale (using 00= 1:1)
         ; ----3---  T1OSCEN - timer1 osc enable, 1=en
         ; -----2--  T1SYNC - ext sync
         ; ------1-  TMR1CS - ext/inter, 0=internal clock
         ; -------0  TMR1ON - 1=timer1 enabled        */

	T1CON = 0b00000000;    // TMR1 not used


   	//-------------------------------------------------
	// Initialise vars
   	//-------------------------------------------------

	// set the MIDI output to off (HI)
	PORTC = 0;					// safe; drum led off etc
	PORT_MIDI.F6 = 1;			// MIDI output pin off (HI)

	// starting velocity (loudness) for drums, range 0-127
	velocity = 100;

	// load the starting (default) note values for the 10 drums;
	// for MIDI_Bash v2 we load these drum values from internal
	// EEPROM to restore the same drum sounds to the pads as
	// when it was last used. It also restores the same velocity
	// data for each pad.
	// MIDI drum note 0-9 = EEPROM location 0 - 9
	// MIDI velocity 0-9  = EEPROM location 32+0 - 32+9

	flash_address = 0;
	read_flash();			// get the MIDI note for that pad
	note0 = flash_data;
	flash_address += 32;
	read_flash();			// get the MIDI velocity for that pad
	vel0 = flash_data;

	flash_address = 1;
	read_flash();
	note1 = flash_data;
	flash_address += 32;
	read_flash();
	vel1 = flash_data;

	flash_address = 2;
	read_flash();
	note2 = flash_data;
	flash_address += 32;
	read_flash();
	vel2 = flash_data;

	flash_address = 3;
	read_flash();
	note3 = flash_data;
	flash_address += 32;
	read_flash();
	vel3 = flash_data;

	flash_address = 4;
	read_flash();
	note4 = flash_data;
	flash_address += 32;
	read_flash();
	vel4 = flash_data;

	flash_address = 5;
	read_flash();
	note5 = flash_data;
	flash_address += 32;
	read_flash();
	vel5 = flash_data;

	flash_address = 6;
	read_flash();
	note6 = flash_data;
	flash_address += 32;
	read_flash();
	vel6 = flash_data;

	flash_address = 7;
	read_flash();
	note7 = flash_data;
	flash_address += 32;
	read_flash();
	vel7 = flash_data;

	flash_address = 8;
	read_flash();
	note8 = flash_data;
	flash_address += 32;
	read_flash();
	vel8 = flash_data;

	flash_address = 9;
	read_flash();
	note9 = flash_data;
	flash_address += 32;
	read_flash();
	vel9 = flash_data;

	// load the wait timers for each drum;
	// this gives a bootup delay before any drums can be
	// triggered, 200 gives about 0.8 seconds.
	// the drum led will also be on for this 0.8 secs,
	// so it acts like a "power on" led.
	
	wait_n0 = 200;
	wait_n1 = 200;
	wait_n2 = 200;
	wait_n3 = 200;
	wait_n4 = 200;
	wait_n5 = 200;
	wait_n6 = 200;
	wait_n7 = 200;
	wait_n8 = 200;
	wait_n9 = 200;


   	//-------------------------------------------------
   	// MAIN RUN MODE AFTER HERE
   	//-------------------------------------------------
	// Operation;
	// * the 10 inputs are checked to see if button pressed (LO)
	// * if pressed, send 3 bytes to MIDI (make one drum sound)
	// * debounce inputs with a wait timer to stop retriggering drums!
	//
	// Details;
	// * test all inputs; only test an input if its wait timer==0
	// * if a button is pressed;
	//		* set its wait timer to a "debounce" value
	//		* send 3 MIDI bytes, do nothing else until all 3 sent ok.
	// * every TMR0 overflow;
	//		* if wait timer >1; dec wait timer
	//      * if wait timer==1, dec only if button is released (see below)
	//
	// This is about the simplest system to sense 8 buttons then fire drum
	// sounds off to MIDI, then ensure a simple delay with a countdown timer
	// to stop a drum being retriggered too soon. The simplest debounce
	// is used so it just counts a time period after the button was first
	// pressed, after a set time it is tested to make sure it is released,
	// then resets ready to be retriggered again. So if a button is held
	// down it will only make the drum sound once. This gives a faster
	// max drumroll speed then a long delay which would be needed for
	// other debounce systems.
   	//-------------------------------------------------

	TMR0 = 0;           // reset timer0
	INTCON.T0IF = 0;    // clear TMR0 overflow flag

	// main run loop
	while(1)
	{
		//---------------------------------------
		// this loop mainly just checks the 10 drum buttons.
		//---------------------------------------
		// if any button has JUST been pressed; send drum note
		if(wait_n0==0 && PORTB.F0==0)	// if debounce is reset && button pressed
		{
			// start debounce timer
			wait_n0 = DEB_COUNT;

			the_pad = 0;		// which pad was just hit
			the_note = note0;
			the_vel = vel0;

			drum_was_hit();		// process that pad and make drum sound
		}

		if(wait_n1==0 && PORTB.F1==0)
		{
			wait_n1 = DEB_COUNT;
			the_pad = 1;
			the_note = note1;
			the_vel = vel1;
			drum_was_hit();
		}

		if(wait_n2==0 && PORTB.F2==0)
		{
			wait_n2 = DEB_COUNT;
			the_pad = 2;
			the_note = note2;
			the_vel = vel2;
			drum_was_hit();
		}

		if(wait_n3==0 && PORTB.F3==0)
		{
			wait_n3 = DEB_COUNT;
			the_pad = 3;
			the_note = note3;
			the_vel = vel3;
			drum_was_hit();
		}

		if(wait_n4==0 && PORTB.F4==0)
		{
			wait_n4 = DEB_COUNT;
			the_pad = 4;
			the_note = note4;
			the_vel = vel4;
			drum_was_hit();
		}

		if(wait_n5==0 && PORTB.F5==0)
		{
			wait_n5 = DEB_COUNT;
			the_pad = 5;
			the_note = note5;
			the_vel = vel5;
			drum_was_hit();
		}

		if(wait_n6==0 && PORTB.F6==0)
		{
			wait_n6 = DEB_COUNT;
			the_pad = 6;
			the_note = note6;
			the_vel = vel6;
			drum_was_hit();
		}

		if(wait_n7==0 && PORTB.F7==0)
		{
			wait_n7 = DEB_COUNT;
			the_pad = 7;
			the_note = note7;
			the_vel = vel7;
			drum_was_hit();
		}

		if(wait_n8==0 && PIN_DRUM8==0)
		{
			wait_n8 = DEB_COUNT;
			the_pad = 8;
			the_note = note8;
			the_vel = vel8;
			drum_was_hit();
		}

		if(wait_n9==0 && PIN_DRUM9==0)
		{
			wait_n9 = DEB_COUNT;
			the_pad = 9;
			the_note = note9;
			the_vel = vel9;
			drum_was_hit();
		}


		//---------------------------------------
		// Now check for TMR0 event! if so, dec the 8 wait timers
		// to produce debounce of the pad contacts.
		// v2.0; also process the ADC input here for the volume pot.
		//
		// PIC 8MHz needs TMR0 prescaled at 32:1
		// so each overflow occurs at 2Mhz / 32 / 256 = 244Hz
		// 1/244 = 0.004096 so time between each overflow is 4mS
		//
		// To get good drum speed for drumroll etc we need to be able
		// to get about 12 drum hits per second. However to stop
		// double triggering with one hit (that's bad!) the debounce
		// needs to be as long as possible. So we use the max debounce;
		// ie use; 1 second /12 = 83mS.
		// as each overflow is 4mS, we use 21 overflows = 84mS
		//
		// That value 21 is set in the DEB_COUNT constant.
		// if using other PIC clock speeds just change TMR0
		// prescale value - see timer0 setup.
		//---------------------------------------
		// * every TMR0 overflow;
		//		* if wait timer >1; dec wait timer
		//      * if wait timer==1, dec only if button is released (see below)
		//---------------------------------------

		// check for TMR0 event! if so, dec the 8 wait timers.
		if(INTCON.T0IF == 1)    	// if TMR0 overflowed
		{
			// first clear overflow flag
			INTCON.T0IF = 0;

			// set the drum led to off (LO) by default
			PIN_LED_DRUM = 0;

			// then process all 8 drum button timers
			if(wait_n0 > 0)
			{
				wait_n0--;          // subtract another overflow period

			    // if button is still pressed (LO), thats bad!
			    // so add some more debounce time to allow for
			    // any button release bounce to be past.
				if(wait_n0==0 && PORTB.F0==0) wait_n0=DEB_COUNTSAFE;

				// if any wait timer is >0 then set the drum led to on!
				// this makes the drum led give a quick flash
				// every time a drum button is hit.
				PIN_LED_DRUM = 1;     // led on = HI
			}

			if(wait_n1 > 0)
			{
				wait_n1--;
				if(wait_n1==0 && PORTB.F1==0) wait_n1=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n2 > 0)
			{
				wait_n2--;
				if(wait_n2==0 && PORTB.F2==0) wait_n2=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n3 > 0)
			{
				wait_n3--;
				if(wait_n3==0 && PORTB.F3==0) wait_n3=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n4 > 0)
			{
				wait_n4--;
				if(wait_n4==0 && PORTB.F4==0) wait_n4=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n5 > 0)
			{
				wait_n5--;
				if(wait_n5==0 && PORTB.F5==0) wait_n5=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n6 > 0)
			{
				wait_n6--;
				if(wait_n6==0 && PORTB.F6==0) wait_n6=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n7 > 0)
			{
				wait_n7--;
				if(wait_n7==0 && PORTB.F7==0) wait_n7=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n8 > 0)
			{
				wait_n8--;
				if(wait_n8==0 && PIN_DRUM8==0) wait_n8=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			if(wait_n9 > 0)
			{
				wait_n9--;
				if(wait_n9==0 && PIN_DRUM9==0) wait_n9=DEB_COUNTSAFE;
				PIN_LED_DRUM = 1;
			}

			// now process the ADC input conversion...
			// MIDI_Bash v2.0 only using AN0 input (velocity "volume" pot)
			// 8MHz PIC we get here at 244 Hz (see above)
			// so do an ADC conversion about 25 times per second
			// (fast enough for good response, but slow enough
			// to save battery power) so we do a conversion
			// every 12 overflows; 244Hz /10 = 24.4Hz

			timer++;
			if(timer == 9)
			{
			    // start ADC conversion
			    ADCON0.GO = 1;
			}
			if(timer >= 10)
			{
				// get ADC result (must now be 4mS since starting conversion
				//  so no need to check if conversion is done)
				velocity = ADRESH;			// get pot position 0-255
				velocity = (velocity / 2);  // convert to MIDI 0-127 range
				if(velocity < 5) velocity = 0;  // safe; make very quiet = silent
				timer = 0;
			}

		}
		//---------------------------------------
	}
}
//-----------------------------------------------------------------------------






//=============================================================================
//  BLANK
//=============================================================================
void blank(void)
{
   //-------------------------------------------------



   //------------------------------------------------
}
//-----------------------------------------------------------------------------


















