FortySevenEffects / arduino_midi_library

MIDI for Arduino
MIT License
1.56k stars 253 forks source link

MIDI Thru changes data on Atmega32U4 #174

Open CorjanV opened 3 years ago

CorjanV commented 3 years ago

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. image

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

franky47 commented 3 years ago

That's very odd indeed, can I have a look at the code ?

CorjanV commented 3 years ago

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 ;)