MIDI Thru changes data on Atmega32U4
CorjanV opened this issue · 2 comments
Hi,
I have some trouble with the MIDI Thru function on a custom atmega32U4 based board. The board checks the keys of a keyboard and send a MIDI signal. Incoming messages are also send thru. This way it is possible to daisy-chain multiple boards.
The hardware is not the problem, I think. I've made some other custom boards based on the atmega32U4 and they work great. But I don't use serial communication on those boards.
What I use to debug:
I have 2 of the custom boards: daisy-chained. Those are connected by a MIDI-USB converter to my PC. I use MIDI-OX to debug.
So: [Board 1] -> [Board 2] -> [MIDI-USB converter] -> [PC] -> [MIDI-OX]
...............|..........................|
...[Keyboard 1] [Keyboard 2]
What does work:
When I press a key on [Keyboard 2], on the MIDI-OX monitor I see a proper Note-On message and when I release I see a proper Note-Off message.
What doesn't work:
When I press a key on [Keyboard 1], on the MIDI-OX monitor I see something totally different. Only when I press a key very fast or multiple at ones, some messages are Note-On/Off. The corresponding data (channel, pitch) are then correct.
I can reproduce the problem when I switches [Board 1] with [Board 2].
I use the Leonardo bootloader to set the fuses.
I hope that I provided enough information.
Thanks in advance!
Corjan
That's very odd indeed, can I have a look at the code ?
Yes, sure. Here it is:
#include <MIDI.h>
#include <digitalWriteFast.h>
#define KLAVIER_LED_ON PORTE |= 0b00000100;
#define KLAVIER_LED_OFF PORTE &= ~0b00000100;
#define CH_S1 5
#define CH_S2 13
#define CH_S4 A5
#define CH_S8 A4
#define T0 8
#define T1 9
#define T2 10
#define T3 11
#define T4 A3
#define T5 A2
#define T6 A1
#define T7 A0
#define BR0_STATUS (PIND & 0b00000001) >> 0
#define BR1_STATUS (PIND & 0b00000010) >> 1
#define BR2_STATUS (PINB & 0b00000001) >> 0
#define BR3_STATUS (PINE & 0b01000000) >> 6
#define BR4_STATUS (PIND & 0b00010000) >> 4
#define BR5_STATUS (PIND & 0b00100000) >> 5
#define BR6_STATUS (PIND & 0b01000000) >> 6
#define BR7_STATUS (PIND & 0b10000000) >> 7
MIDI_CREATE_DEFAULT_INSTANCE();
int inputNieuw[64] = {0};
int inputOud[64] = {0};
int i,j,k;
int counter = 0;
int offset = 36;
int kanaal = 0;
int toetsActief = 0;
void setup()
{
WDT_off();
WDT_Prescaler_Change();
// pinMode(KLAVIER_ACT, OUTPUT);
DDRE |= 0b00000100;
pinMode(CH_S1, INPUT_PULLUP);
pinMode(CH_S2, INPUT_PULLUP);
pinMode(CH_S4, INPUT_PULLUP);
pinMode(CH_S8, INPUT_PULLUP);
if(digitalRead(CH_S1) == LOW) kanaal |= 0b0001;
if(digitalRead(CH_S2) == LOW) kanaal |= 0b0010;
if(digitalRead(CH_S4) == LOW) kanaal |= 0b0100;
if(digitalRead(CH_S8) == LOW) kanaal |= 0b1000;
kanaal++;
pinMode(T0, OUTPUT);
pinMode(T1, OUTPUT);
pinMode(T2, OUTPUT);
pinMode(T3, OUTPUT);
pinMode(T4, OUTPUT);
pinMode(T5, OUTPUT);
pinMode(T6, OUTPUT);
pinMode(T7, OUTPUT);
DDRD &= ~0b11110011;
DDRB &= ~0b00000001;
DDRE &= ~0b01000000;
MIDI.begin(MIDI_CHANNEL_OMNI); // Luister op alle kanalen
MIDI.turnThruOn(); //Alle inkomende berichten doorsturen
}
void loop()
{
asm("wdr \n"); // reset
MIDI.read();
highMode(); // Lees klavier in met hoge aanslaggevoeligheid (lage aanslaggevoeligheid niet beschikbaar)
for(k=0; k<64; k++)
{
if(inputNieuw[k] != inputOud[k]) // alleen als de input is veranderd een MIDI transfer doen
{
if(inputNieuw[k] == HIGH) MIDI.sendNoteOn(offset+k,127,kanaal);
else MIDI.sendNoteOff(offset+k,0,kanaal);
}
}
MIDI.read();
copy(inputNieuw, inputOud, 64);
}
void copy(int* src, int* dst, int len) {
memcpy(dst, src, sizeof(src[0])*len);
}
void maakTPinHoog(int T) {
if(T==0) {digitalWriteFast(T0, HIGH); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==1) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, HIGH); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==2) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, HIGH); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==3) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, HIGH); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==4) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, HIGH); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==5) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, HIGH); digitalWriteFast(T6, LOW); digitalWriteFast(T7, LOW);}
else if(T==6) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, HIGH); digitalWriteFast(T7, LOW);}
else if(T==7) {digitalWriteFast(T0, LOW); digitalWriteFast(T1, LOW); digitalWriteFast(T2, LOW); digitalWriteFast(T3, LOW); digitalWriteFast(T4, LOW); digitalWriteFast(T5, LOW); digitalWriteFast(T6, LOW); digitalWriteFast(T7, HIGH);}
}
int leesIngangStatus(int BR) {
if(BR==0) return BR0_STATUS;
else if(BR==1) return BR1_STATUS;
else if(BR==2) return BR2_STATUS;
else if(BR==3) return BR3_STATUS;
else if(BR==4) return BR4_STATUS;
else if(BR==5) return BR5_STATUS;
else if(BR==6) return BR6_STATUS;
else if(BR==7) return BR7_STATUS;
else return 0;
}
void highMode(void) {
toetsActief = 0;
for(i=0; i<=7; i++)
{
MIDI.read();
maakTPinHoog(i);
for(j=0; j<=7; j++)
{
toetsActief |= leesIngangStatus(j);
inputNieuw[j*8+i] = leesIngangStatus(j);
}
}
if(toetsActief != 0) KLAVIER_LED_ON
else KLAVIER_LED_OFF
}
void WDT_off(void)
{
asm("cli \n"); // turn off global interrupt
asm("wdr \n"); // reset WDT
/* Clear WDRF in MCUSR */
MCUSR &= ~(1<<WDRF);
/* Write logical one to WDCE and WDE */
/* Keep old prescaler setting to prevent unintentional time-out
*/
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Turn off WDT */
WDTCSR = 0x00;
asm("sei \n"); // turn on global interrupt
}
void WDT_Prescaler_Change(void)
{
asm("cli \n"); // turn off global interrupt
asm("wdr \n"); // reset WDT
/* Start timed equence */
WDTCSR |= (1<<WDCE) | (1<<WDE);
/* Set new prescaler(time-out) value = 256K cycles (~2.0 s) */
WDTCSR = (1<<WDE) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
asm("sei \n"); // turn on global interrupt
}
Sorry for the dunglish language ;)