Calculate a variable in an array

Hello everyone.

I need to calculate the 21th byte (which is Checksum) in this array:

byte sA[22] = {0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};

The first 8 bytes (0-7) and the last byte (f7) are fix.

Bytes number 8-20 are variable and can be 0x40 or 0x0e.

The 21th bytes is Checksum and is calculated like this:

  • SUM = 8th + 7th + ... + 20th

  • (While summing, every time result becomes bigger than 127 (0x7f) , subtract it from 128 (0x80)

  • Remainder = SUM % 0x80

  • Checksum = 0x80 - Remainder

I tried this code but the calculated Checksum is incorrect!

one= sA[8] + sA[9];
  if (one> 0x7f)
  {
    one = one - 0x80;
  }

  two = one + sA[10];
  if (two > 0x7f)
  {
    two = two - 0x80;
  }

  three = two + sA[11];
  if (three > 0x7f)
  {
    three = three - 0x80;
  }

  four = three + sA[12];
  if (four > 0x7f)
  {
    four = four - 0x80;
  }

  five = four + sA[13];
  if (five > 0x7f)
  {
    five = five - 0x80;
  }

  six = five + sA[14];
  if (six > 0x7f)
  {
    six = six - 0x80;
  }
  seven = six + sA[15];
  if (seven > 0x7f)
  {
    seven = seven - 0x80;
  }

  eight = seven + sA[16];
  if (eight > 0x7f)
  {
    eight = eight - 0x80;
  }

  nine = eight + sA[17];
  if (nine > 0x7f)
  {
    nine = nine - 0x80;
  }

  ten = nine + sA[18];
  if (ten > 0x7f)
  {
    ten = ten - 0x80;
  }

  eleven = ten + sA[19];
  if (ten > 0x7f)
  {
    eleven = eleven - 0x80;
  }

  twelve = eleven + sA[20];
  if (ten > 0x7f)
  {
    twelve = twelve - 0x80;
  }

  Remainder = twelve % 0x80;

  sA[21] = 0x80 - Remainder;

Would you guys please let me know what is wrong with my calculation?
I have attached the .ino file to this topic. Everything works fine in it but the Checksum calculation!

jv-1010_tuner.ino (4.84 KB)

Please post the complete program here to make it easier to copy to an editor.

What data types are the variables that you are using ?
Have you tried printing the intermediate results to check that they are correct ?

By the way, you could use a for loop for much of the program rather than repeating the same code over and over again.

one= sA[8] + sA[9];

one is the sum of two numbers? That makes NO sense.

Handling rollover that way is unnecessary. The value that you are subtracting will automatically fall into the bit bucket. Just add the values in the array in a for loop, and let rollover happen.

Thank you guys for answering me.
So i'm really off the course!

Let me show you exactly what i'm going to do.

This is the System exclusive message array:

The code sends this array to my MIDI gear to do some stuff.

Notes (index 8-19) are the variables which can be 0X40 or 0x0e according to state of digital inputs.

Checksum (index 20) is an another variable which depends to the value of the 12 notes and is calculated with this formula:

C + C# + D + D# + E + F + F# + G + G# + A + A# + B

Calculating the SUM, every time the result becomes bigger than 127 (0x7f), it must be subtracted from 128 (0x80)

Then we calculate the Remainder:

SUM Result % 128

and finally calculate the Checksum like this : Checksum = 128 - Remainder.

Since i'm a skinny noob, this is quite challenging for me. I have no idea how to make a FOR loop that only rolls over the indexes number 8 through 19 and not the entire array.

So far I haven't come up with any idea how to write the code to calculate the correct Checksum. So I'll appreciate your help on this issue.

how to make a FOR loop that only rolls over the indexes number 8 through 19 and not the entire array

for (i=8; i<=19;i++)
{
// do stuff
}

kooroshi60:
Notes (index 8-19) are the variables which can be 0X40 or 0x0e according to state of digital inputs.

Then why are they all 0x00 in the picture you posted?

gfvalvo:
Then why are they all 0x00 in the picture you posted?

well; they are variables and they will change according to the state of digital inputs. they can be either 0x40 or 0x0e. In the array I just put 0x00 because this way it makes more sense when I look at it.

kooroshi60:
well; they are variables and they will change according to the state of digital inputs. they can be either 0x40 or 0x0e. In the array I just put 0x00 because this way it makes more sense when I look at it.

A mix of 0x40 and 0x0E would have made more sense for people trying to understand the picture. Given that's what you said would be in there…..

You add all the entries and truncate to 7 bits - no need to do any tests or % operators, just sum then
sum & 0x7F will return the low 7 bits of the sum.

UFFA.. This is so difficult. I tried my best but the codes I wrote were trash. no one worked.

I tried to regenerate the CRC (Checksum) of this array that is taken from a Roland MIDI Implementation chart.

byte S[22] = {0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x11, 0x40, 0x3a, 0x6d, 0x3e, 0x34, 0x0d, 0x38, 0x6b, 0x3c, 0x6f, 0x40, 0x36, 0x0f, 0X76, 0xf7};

As it is written in the array, index number 20 is 0x76 which is the correct Checksum of indexes number 8 through 19.

Is anyone out there who can write the correct Checksum calculator code please?
I appreciate your help, attention and the time you spend solving my problem.

And googling "MIDI checksum" doesn't show any results?

Putting together what @evanmars said:

for (i=8; i<=19;i++)
{
// do stuff
}

And what @MarkT said:

You add all the entries and truncate to 7 bits - no need to do any tests or % operators, just sum then
sum & 0x7F will return the low 7 bits of the sum.

You shoud come up with something like:

byte checksum();
  byte partialSum = 0;
  for (byte i = 8 ; i <= 19 ; i++)
  {
    partialSum += sA[i];
  }
  return 0x80 - (partialSum & 0x7F);
}

Jacques

Thank you "jbellavance" for helping me on this.

Now I have a second problem with this FOR loop! It prevents the following lines from running.
I loaded the code to the Arduino but the next part after the FOR loop which controls 3 switches does not work when the FOR loop is there at the beginning of the void loop ().
Is it possible to do this calculation outside the void loop?
It tried to take it outside but ended up with errors!

Here is my code:

//Roland Jv-1010 Scale Controller.
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
MIDI_CREATE_DEFAULT_INSTANCE();

//Scale ON/OFF Arrays
byte onArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x01, 0x78, 0xf7}; // ON array
byte offArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x79, 0xf7}; // OFF array


// Analog pin A0-ON
int switchPinON = 14;
// Analog pin A1-OFF
int switchPinOFF = 15;
// Analog pin A2-SEND
int scaleSend = 16;


int Do = 2;
int Dos = 3;
int Re = 4;
int Res = 5;
int Mi = 6;
int Fa = 7;
int Fas = 8;
int Sol = 9;
int Sols = 10;
int La = 11;
int Las = 12;
int Si = 13;


void setup() {
  MIDI.begin();                            //Midi channel = 1 , Baud = 31250
  pinMode (switchPinON, INPUT);           //Scale ON
  pinMode (switchPinOFF, INPUT);         //Sclae OFF
  pinMode (scaleSend, INPUT);           //Scale SEND
  pinMode (Do, INPUT);
  pinMode (Dos, INPUT);
  pinMode (Re, INPUT);
  pinMode (Res, INPUT);
  pinMode (Mi, INPUT);
  pinMode (Fa, INPUT);
  pinMode (Fas, INPUT);
  pinMode (Sol, INPUT);
  pinMode (Sols, INPUT);
  pinMode (La, INPUT);
  pinMode (Las, INPUT);
  pinMode (Si, INPUT);
}

void loop() {


  // Roland Checksum calculation
  byte checksum();
  byte partialSum = 0;
  byte SA[22] = {0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x11, 0x40, 0x3a, 0x6d, 0x3e, 0x34, 0x0d, 0x38, 0x6b, 0x3c, 0x6f, 0x40, 0x36, 0x0f, checksum, 0xf7};
  for (byte i = 8 ; i <= 19 ; i++)
  {
    partialSum += SA[i];
  }
  return 0x80 - (partialSum & 0x7F);


  // This part doesn't run when follows the checksum calculation!!!!

  // ON - OFF - SEND switches  

  if (digitalRead(scaleSend) == HIGH)
  {
    MIDI.sendSysEx(22, SA, true);
    delay(1000);
  }
  if (digitalRead(switchPinON) == HIGH)
  {
    MIDI.sendSysEx(12, onArray, true);
    delay(1000);
  }
  if (digitalRead(switchPinOFF) == HIGH)
  {
    MIDI.sendSysEx(12 , offArray, true);
    delay(1000);
  }

  // 12 ON/OFF Switches.
  // ***************************************  DO

  if (digitalRead(Do) == HIGH)
  {
    SA[8] = 0x0e;
  }
  else
  {
    SA[8] = 0x40;
  }
  // ***************************************  DO#
  if (digitalRead(Dos) == HIGH)
  {
    SA[9] = 0x0e;
  }
  else
  {
    SA[9] = 0x40;
  }
  // ***************************************  RE
  if (digitalRead(Re) == HIGH)
  {
    SA[10] = 0x0e;
  }
  else
  {
    SA[10] = 0x40;
  }
  // ***************************************  RE#
  if (digitalRead(Res) == HIGH)
  {
    SA[11] = 0x0e;
  }
  else
  {
    SA[11] = 0x40;
  }
  // ***************************************  MI
  if (digitalRead(Mi) == HIGH)
  {
    SA[12] = 0x0e;
  }
  else
  {
    SA[12] = 0x40;
  }
  // ***************************************  FA
  if (digitalRead(Fa) == HIGH)
  {
    SA[13] = 0x0e;
  }
  else
  {
    SA[13] = 0x40;
  }
  // ***************************************  FA#
  if (digitalRead(Fas) == HIGH)
  {
    SA[14] = 0x0e;
  }
  else
  {
    SA[14] = 0x40;
  }
  // ***************************************  SOL
  if (digitalRead(Sol) == HIGH)
  {
    SA[15] = 0x0e;
  }
  else
  {
    SA[15] = 0x40;
  }
  // ***************************************  SOL#
  if (digitalRead(Sols) == HIGH)
  {
    SA[16] = 0x0e;
  }
  else
  {
    SA[16] = 0x40;
  }
  // ***************************************  LA
  if (digitalRead(La) == HIGH)
  {
    SA[17] = 0x0e;
  }
  else
  {
    SA[17] = 0x40;
  }
  // ***************************************  LA#
  if (digitalRead(Las) == HIGH)
  {
    SA[18] = 0x0e;
  }
  else
  {
    SA[18] = 0x40;
  }
  // ***************************************  SI
  if (digitalRead(Si) == HIGH)
  {
    SA[19] = 0x0e;
  }
  else
  {
    SA[19] = 0x40;
  }
}

Because you executed a return statement that causes an exit from the loop() function.

byte SA[22] = {0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x11, 0x40, 0x3a, 0x6d, 0x3e, 0x34, 0x0d, 0x38, 0x6b, 0x3c, 0x6f, 0x40, 0x36, 0x0f, checksum, 0xf7};


byte checksum();
  byte partialSum = 0;
  for (byte i = 8 ; i <= 19 ; i++)
  {
    partialSum += SA[i];
  }
  return 0x80 - (partialSum & 0x7F);
}
void loop() {
  // Roland Checksum calculation
  SA[20] = checksum(); //Or maybe you want to compare your checksum with SA[20]??
  //The rest of your code that modifies SA[]

Jacques

YESSS! Problem SOLVED!
Thank you so much for your help.

I finally ended up with this code and it works flawlessly.

//Roland Jv-1010 Scale Controller.
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
MIDI_CREATE_DEFAULT_INSTANCE();

//Scale ON/OFF Arrays
byte onArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x01, 0x78, 0xf7}; // ON array
byte offArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x79, 0xf7}; // OFF array

byte SA[22] = {0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x11, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};

// Analog pin A0-ON
int switchPinON = 14;
// Analog pin A1-OFF
int switchPinOFF = 15;
// Analog pin A2-SEND
int scaleSend = 16;


int Do = 2;
int Dos = 3;
int Re = 4;
int Res = 5;
int Mi = 6;
int Fa = 7;
int Fas = 8;
int Sol = 9;
int Sols = 10;
int La = 11;
int Las = 12;
int Si = 13;


void setup() {
  MIDI.begin();                            //Midi channel = 1 , Baud = 31250
  pinMode (switchPinON, INPUT);           //Scale ON
  pinMode (switchPinOFF, INPUT);         //Sclae OFF
  pinMode (scaleSend, INPUT);           //Scale SEND
  pinMode (Do, INPUT);
  pinMode (Dos, INPUT);
  pinMode (Re, INPUT);
  pinMode (Res, INPUT);
  pinMode (Mi, INPUT);
  pinMode (Fa, INPUT);
  pinMode (Fas, INPUT);
  pinMode (Sol, INPUT);
  pinMode (Sols, INPUT);
  pinMode (La, INPUT);
  pinMode (Las, INPUT);
  pinMode (Si, INPUT);
}

void loop() {

  // ARRAY VALUES
  if (digitalRead(scaleSend) == HIGH)
  {
    MIDI.sendSysEx(22, SA, true);
    delay(1000);
  }
  if (digitalRead(switchPinON) == HIGH)
  {
    MIDI.sendSysEx(12, onArray, true);
    delay(1000);
  }
  if (digitalRead(switchPinOFF) == HIGH)
  {
    MIDI.sendSysEx(12 , offArray, true);
    delay(1000);
  }

  // 12 ON/OFF Switches.
  // ***************************************  DO

  if (digitalRead(Do) == HIGH)
  {
    SA[8] = 0x0e;
  }
  else
  {
    SA[8] = 0x40;
  }
  // ***************************************  DO#
  if (digitalRead(Dos) == HIGH)
  {
    SA[9] = 0x0e;
  }
  else
  {
    SA[9] = 0x40;
  }
  // ***************************************  RE
  if (digitalRead(Re) == HIGH)
  {
    SA[10] = 0x0e;
  }
  else
  {
    SA[10] = 0x40;
  }
  // ***************************************  RE#
  if (digitalRead(Res) == HIGH)
  {
    SA[11] = 0x0e;
  }
  else
  {
    SA[11] = 0x40;
  }
  // ***************************************  MI
  if (digitalRead(Mi) == HIGH)
  {
    SA[12] = 0x0e;
  }
  else
  {
    SA[12] = 0x40;
  }
  // ***************************************  FA
  if (digitalRead(Fa) == HIGH)
  {
    SA[13] = 0x0e;
  }
  else
  {
    SA[13] = 0x40;
  }
  // ***************************************  FA#
  if (digitalRead(Fas) == HIGH)
  {
    SA[14] = 0x0e;
  }
  else
  {
    SA[14] = 0x40;
  }
  // ***************************************  SOL
  if (digitalRead(Sol) == HIGH)
  {
    SA[15] = 0x0e;
  }
  else
  {
    SA[15] = 0x40;
  }
  // ***************************************  SOL#
  if (digitalRead(Sols) == HIGH)
  {
    SA[16] = 0x0e;
  }
  else
  {
    SA[16] = 0x40;
  }
  // ***************************************  LA
  if (digitalRead(La) == HIGH)
  {
    SA[17] = 0x0e;
  }
  else
  {
    SA[17] = 0x40;
  }
  // ***************************************  LA#
  if (digitalRead(Las) == HIGH)
  {
    SA[18] = 0x0e;
  }
  else
  {
    SA[18] = 0x40;
  }
  // ***************************************  SI
  if (digitalRead(Si) == HIGH)
  {
    SA[19] = 0x0e;
  }
  else
  {
    SA[19] = 0x40;
  }

// ROLAND CHECKSUM

byte partialSum = 0;
for (byte i = 8 ; i <= 19 ; i++)
{
  partialSum += SA[i];
}
{
SA[20] = 0x80 - (partialSum & 0x7F);
}
}