MIDI and clock prescaler problems

Hi there,

I am using a clock prescaler in my arduino synth project. This one line of code, which sets the prescaler:

TCCR2B = _BV(CS20);

Stops the standard midi library from working. Has anyone encountered this before and does anybody know of a work-around?

Thanks, Matt

WHat is the standard MIDI library ? do you have a link to the sources?

might be that the lib uses the same timer .... for timing of the bits going in and out ...

By standard midi library I mean the following midi.h file that comes with arduino:

#ifndef LIB_MIDI_H_
#define LIB_MIDI_H_

#include <inttypes.h> 


#define COMPILE_MIDI_IN         1           // Set this setting to 1 to use the MIDI input.
#define COMPILE_MIDI_OUT        0           // Set this setting to 1 to use the MIDI output. 
#define COMPILE_MIDI_THRU       0           // Set this setting to 1 to use the MIDI Soft Thru feature
                                            // Please note that the Thru will work only when both COMPILE_MIDI_IN and COMPILE_MIDI_OUT set to 1.


#define USE_SERIAL_PORT         Serial      // Change the number (to Serial1 for example) if you want
                                            // to use a different serial port for MIDI I/O.


#define USE_RUNNING_STATUS		1			// Running status enables short messages when sending multiple values
                                            // of the same type and channel.
                                            // Set to 0 if you have troubles with controlling you hardware.


#define USE_CALLBACKS           1           // Set this to 1 if you want to use callback handlers (to bind your functions to the library).
                                            // To use the callbacks, you need to have COMPILE_MIDI_IN set to 1


// END OF CONFIGURATION AREA 
// (do not modify anything under this line unless you know what you are doing)


#define MIDI_BAUDRATE			31250


#define MIDI_CHANNEL_OMNI		0
#define MIDI_CHANNEL_OFF		17 // and over

#define MIDI_SYSEX_ARRAY_SIZE	255

/*! Type definition for practical use (because "unsigned char" is a bit long to write.. )*/
typedef uint8_t byte;
typedef uint16_t word;

/*! Enumeration of MIDI types */
enum kMIDIType {
	NoteOff	              = 0x80,	///< Note Off
	NoteOn                = 0x90,	///< Note On
	AfterTouchPoly        = 0xA0,	///< Polyphonic AfterTouch
	ControlChange         = 0xB0,	///< Control Change / Channel Mode
	ProgramChange         = 0xC0,	///< Program Change
	AfterTouchChannel     = 0xD0,	///< Channel (monophonic) AfterTouch
	PitchBend             = 0xE0,	///< Pitch Bend
	SystemExclusive       = 0xF0,	///< System Exclusive
	TimeCodeQuarterFrame  = 0xF1,	///< System Common - MIDI Time Code Quarter Frame
	SongPosition          = 0xF2,	///< System Common - Song Position Pointer
	SongSelect            = 0xF3,	///< System Common - Song Select
	TuneRequest           = 0xF6,	///< System Common - Tune Request
	Clock                 = 0xF8,	///< System Real Time - Timing Clock
	Start                 = 0xFA,	///< System Real Time - Start
	Continue              = 0xFB,	///< System Real Time - Continue
	Stop                  = 0xFC,	///< System Real Time - Stop
	ActiveSensing         = 0xFE,	///< System Real Time - Active Sensing
	SystemReset           = 0xFF,	///< System Real Time - System Reset
	InvalidType           = 0x00    ///< For notifying errors
};

/*! Enumeration of Thru filter modes */
enum kThruFilterMode {
	Off                   = 0,  ///< Thru disabled (nothing passes through).
	Full                  = 1,  ///< Fully enabled Thru (every incoming message is sent back).
	SameChannel           = 2,  ///< Only the messages on the Input Channel will be sent back.
	DifferentChannel      = 3   ///< All the messages but the ones on the Input Channel will be sent back.
};


/*! The midimsg structure contains decoded data of a MIDI message read from the serial port with read() or thru(). \n */
struct midimsg {
	/*! The MIDI channel on which the message was recieved. \n Value goes from 1 to 16. */
	byte channel; 
	/*! The type of the message (see the define section for types reference) */
	kMIDIType type;
	/*! The first data byte.\n Value goes from 0 to 127.\n If the message is SysEx, this byte contains the array length. */
	byte data1;
	/*! The second data byte. If the message is only 2 bytes long, this one is null.\n Value goes from 0 to 127. */
	byte data2;
	/*! System Exclusive dedicated byte array. \n Array length is stocked in data1. */
	byte sysex_array[MIDI_SYSEX_ARRAY_SIZE];
	/*! This boolean indicates if the message is valid or not. There is no channel consideration here, validity means the message respects the MIDI norm. */
	bool valid;
};




/*! \brief The main class for MIDI handling.\n
	See member descriptions to know how to use it,
	or check out the examples supplied with the library.
 */
class MIDI_Class {
	
	
public:
	// Constructor and Destructor
	MIDI_Class();
	~MIDI_Class();
	
	
	void begin(const byte inChannel = 1);
	
	
	
	


	
/* ####### INPUT COMPILATION BLOCK ####### */
#if COMPILE_MIDI_IN	
	
public:
	
	bool read();
	bool read(const byte Channel);
	
	// Getters
	kMIDIType getType();
	byte getChannel();
	byte getData1();
	byte getData2();
	byte * getSysExArray();
	bool check();
	
	byte getInputChannel() { return mInputChannel; }
	
	// Setters
	void setInputChannel(const byte Channel);
	
	/*! \brief Extract an enumerated MIDI type from a status byte.
	 
	 This is a utility static method, used internally, made public so you can handle kMIDITypes more easily.
	 */
	static inline const kMIDIType getTypeFromStatusByte(const byte inStatus) {
		if ((inStatus < 0x80) 
			|| (inStatus == 0xF4) 
			|| (inStatus == 0xF5) 
			|| (inStatus == 0xF9) 
			|| (inStatus == 0xFD)) return InvalidType; // data bytes and undefined.
		if (inStatus < 0xF0) return (kMIDIType)(inStatus & 0xF0);	// Channel message, remove channel nibble.
		else return (kMIDIType)inStatus;
	}
	
	
#if USE_CALLBACKS
	
	void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
	void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
	void setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure));
	void setHandleControlChange(void (*fptr)(byte channel, byte number, byte value));
	void setHandleProgramChange(void (*fptr)(byte channel, byte number));
	void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
	void setHandlePitchBend(void (*fptr)(byte channel, int bend));
	void setHandleSystemExclusive(void (*fptr)(byte * array, byte size));
	void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
	void setHandleSongPosition(void (*fptr)(unsigned int beats));
	void setHandleSongSelect(void (*fptr)(byte songnumber));
	void setHandleTuneRequest(void (*fptr)(void));
	void setHandleClock(void (*fptr)(void));
	void setHandleStart(void (*fptr)(void));
	void setHandleContinue(void (*fptr)(void));
	void setHandleStop(void (*fptr)(void));
	void setHandleActiveSensing(void (*fptr)(void));
	void setHandleSystemReset(void (*fptr)(void));
	
	void disconnectCallbackFromType(kMIDIType Type);
	
#endif // USE_CALLBACKS
	
	
private:
	
	bool input_filter(byte inChannel);
	bool parse(byte inChannel);
	void reset_input_attributes();
	
	// Attributes
	byte			mRunningStatus_RX;
	byte			mInputChannel;
	
	byte			mPendingMessage[MIDI_SYSEX_ARRAY_SIZE];
	byte			mPendingMessageExpectedLenght;
	byte			mPendingMessageIndex;
	
	midimsg			mMessage;
	
#if USE_CALLBACKS
	
	void launchCallback();
	
	void (*mNoteOffCallback)(byte channel, byte note, byte velocity);
	void (*mNoteOnCallback)(byte channel, byte note, byte velocity);
	void (*mAfterTouchPolyCallback)(byte channel, byte note, byte velocity);
	void (*mControlChangeCallback)(byte channel, byte, byte);
	void (*mProgramChangeCallback)(byte channel, byte);
	void (*mAfterTouchChannelCallback)(byte channel, byte);
	void (*mPitchBendCallback)(byte channel, int);
	void (*mSystemExclusiveCallback)(byte * array, byte size);
	void (*mTimeCodeQuarterFrameCallback)(byte data);
	void (*mSongPositionCallback)(unsigned int beats);
	void (*mSongSelectCallback)(byte songnumber);
	void (*mTuneRequestCallback)(void);
	void (*mClockCallback)(void);
	void (*mStartCallback)(void);
	void (*mContinueCallback)(void);
	void (*mStopCallback)(void);
	void (*mActiveSensingCallback)(void);
	void (*mSystemResetCallback)(void);
	
#endif // USE_CALLBACKS
	
	
#endif // COMPILE_MIDI_IN
	



extern MIDI_Class MIDI;

#endif // LIB_MIDI_H_

(I've had to remove some irrelevant parts of this code to fit it in this post)

As for my code, I'm using a similar method to the one of this page:

http://adrianfreed.com/content/arduino-sketch-high-frequency-precision-sine-wave-tone-sound-synthesis

By standard midi library I mean the following midi.h file that comes with arduino:

not with mine IDE22 for windows.

the .h file does not give me a clue for the original question , sorry. Do you have the cpp file?

My bad, I must have downloaded it and forgotten!

Here's a link to the arduino midi library page, with a link to download. Sorry I would have pasted the .cpp up here but it's too large.

Thanks

Why do you need to adjust prescaler?

Also, I don't get why MIDI needs a timer, all my MIDI stuff uses the regular Serial Output (TX UART) no timers.

I'm a bit confused by all this, sorry... :blush:

Wk

I adjust the clock prescale to slow the clock down in order to do more processing in the timer interrupt.

I don't think midi needs a timer either, which is why I was confused that it didn't work.. Perhaps it affects the baudrate?

Maybe I should try not using the midi library, but I couldn't work out how to process the serial data properly.

UPDATE:

It seems to be having both of these lines in there stop me being able to read any midi data through the serial..

TCCR2B = _BV(CS20);
TIMSK2 = _BV(TOIE2);

I guess that means there's not enough time in the loop() to read the serial data because the interrupts are too frequent? Could that be it?

Here's a simple example of my problem:

byte incomingByte;

void setup() {
TCCR2B = _BV(CS20);
TIMSK2 = _BV(TOIE2);
  Serial.begin(31250);        
  digitalWrite(13,LOW);  
}


void loop () {
  if (Serial.available() > 0) {

    incomingByte = Serial.read();
    if(incomingByte==144){digitalWrite(13,HIGH); }

  }
}

If you run this sketch, no note on message will be found, but if you remove the two lines of code mentioned above, it works.

Any ideas?