4 x 4 Magic Square solutions

I had to change the sense of some of the commented if statements, but that seems to work to filter out the reflections to produce 880 solutions:

/*
  Magische Quadrate 4x4, rekursiv
  Serial only version
*/

struct cell {
  int left;
  int top;
};

int w, h;
const byte cols = 4;
const byte maxi = cols * cols;
const byte sum = (maxi + 1) * maxi / 2 / cols;
byte p[maxi];
int colour[maxi + 1];

// Reihenfolge, in der die Werte gesetzt werden:
const byte seq[] = {
  0,  1,  2,  3,
  4,  5,  6,  7,
  8, 10, 12, 13,
  9, 11, 14, 15
};

/* die Positionen:
  _0 _1 _2  3    alle Postionen ohne "_"
  _4 _5 _6  7    koennen berechnet werden!
  _8 _9 10 11
  12 13 14 15
*/

cell disp[maxi];
char str[2 * maxi + 2];
int count = 0;
const byte charW = 13;
const byte charH = 13;
const byte left = 39;
const byte top =  59;
const byte p0 = 2;
const byte p1 = 102;
byte solution[maxi + 1] = {0};

void setup() {
  Serial.begin(115200);
  Serial.println(F(__FILE__));
  // calculate the positions of the 16 cells
  for (int i = 0; i < maxi; i++) {
    int j = seq[i];
    disp[j].left =  left + 1 + (i & 3) * charW;
    disp[j].top  = top + 2 + (i / 4) * charH;
  }
  // Generate the strings to display the numbers faster
  str[0] = 0xDB;
  str[1] = 0xDB;
  for (int i = 1; i <= maxi; i++) {
    //    colour[i] = hue(i);
    str[i * 2] = i < 10 ? ' ' : '1';
    str[i * 2 + 1] = '0' + i % 10;
    dispNumAtpos(0, i);
  }

  // start the recursion:
  place(0, 0xFFFF);
  // finished and ready.
  Serial.print(F("Complete ["));
  Serial.print(millis() / 1000);
  Serial.println(F(" sec]"));
}

void loop() {}

void place(byte pos, int avail) {
  byte i;
  switch (pos) {
    case  0: case 1: case 2: case 4: case 5: case 6: case 8:
      for (i = 1; i <= maxi; i++) Try(pos, i, avail); break;
    case  3: i = rem3(0,  1,  2);  if (p[0] < i)
        Try(pos, i, avail); break;
    // Row 1, mirrored on the vertical axis
    case  7: i = rem3(4,  5,  6); Try(pos, i, avail); break;   // Zeile 2
    case  9: i = rem3(0,  4,  8);  if ((p[0] < i) && (p[3] > i))
        //if(p[3] > i)
        Try(pos, i, avail); break;   // Spalte 1
    case 10: i = rem3(9,  6, 3); Try(pos, i, avail); break;   // /-diagonal
    case 11: i = rem3(1,  5, 10); Try(pos, i, avail); break;   // Spalte 2
    case 12: i = rem3(5,  6, 10); Try(pos, i, avail); break;   // mittlerer Block
    case 13: i = rem3(8, 10, 12); Try(pos, i, avail); break;   // Zeile 3
    case 14: i = rem3(2,  6, 12); Try(pos, i, avail); break;   // Spalte 3
    case 15: i = rem3(3,  7, 13);  if (p[0] < i)
        Try(pos, i, avail); break;
    // Column 4, mirrored on the main diagonal
    case 16: if (rem3(0, 5, 12) == p[15]) {
        // signal the current solution
        Serial.print(F("Solution #"));
        Serial.print(++count);
        Serial.print(F(" ["));
        Serial.print(millis() / 1000);
        Serial.println(F(" sec]:"));
        for (size_t pr = 0; pr < maxi; pr++) {
          Serial.print(str[solution[seq[pr]] * 2]);
          Serial.print(str[solution[seq[pr]] * 2 + 1]);
          Serial.print(' ');
          if (((pr + 1) % cols) == 0) {
            Serial.println();
          }
        }
        Serial.println();
      }
  }
}

void Try(byte pos, byte value, int avail) {
  if ((value < 1) || (value > maxi)) return;  // ungueltige Zahl
  int mask = 1 << (value - 1);
  if (avail & mask) {
    p[pos] = value;
    dispNumAtpos(value, pos);
    place(pos + 1, avail & ~mask);
    dispNumAtpos(0, pos); // loesche Zelle
    p[pos] = 0;
  }
}

byte rem3(byte a, byte b, byte c) {  // gib den Rest zurueck
  return sum - p[a] - p[b] - p[c];
}

void dispNumAtpos(byte number, byte position) {
  solution[position] = number;
}

On an Uno R3:

...
Solution #879 [115 sec]:
 7 16  1 10 
 4 13 12  5 
14  3  6 11 
 9  2 15  8 

Solution #880 [115 sec]:
 7 16  1 10 
12  5  4 13 
 6 11 14  3 
 9  2 15  8 

Complete [150 sec]:

It feels a bit wrong to filter out the exhaustive search and then plan to reflect/rotate the 880 that pass.