Настройка матричной клавиатуры 4х4

Нет ответов
sevmakc
Offline
Зарегистрирован: 19.05.2017
Собрал гирлянду, с применением матричной клавиатуры 4х4 (16 клавиш) для переключения режимов. 
Клавиатура такая
https://ru.aliexpress.com/item/Free-Shipping-New-16-Key-4-x-4-Membrane-Switch-Keypad-4x4-4-4-Matrix-Array/32562855426.html?spm=2114.13010608.0.0.Cx4srd

Должны переключатся 15 режимов + 1 демо (все режимы) на клавише D.
Работают только 4 клавиши верхнего ряда (1,2,3,А), соответственно переключаются только 4 режима, а остальные клавиши никак не реагируют на нажатия.
ПОМОГИТЕ ПОЖАЛУЙСТА, видимо в скетче для настройки клавиатуры где-то ошибка

Сам скетч

 

#define PSPEED        A0
#define PBRIGHTNESS   A1
#define PR            A2
#define PG            A4
#define PB            A6

#define PIXEL_PIN     13
#define PIXEL_COUNT   200

byte pixels[PIXEL_COUNT * 3];

int demoCounter = 0;
byte loopDelay = 5, delayValue = 0, lastRed, lastGreen, lastBlue, demoEffectCounter, mode = 1, speedValue = 11, brightness = 16;
bool nextStep = true, demoMode = false, hiSpeed = false;

void setup()
{
  randomSeed(analogRead(3));

  pinMode(PIXEL_PIN, OUTPUT);
  digitalWrite(PIXEL_PIN, LOW);

  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);  
  pinMode(5, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);  
  
  digitalWrite(9, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(6, HIGH);
}

// --- SendDataToLEDs --------------------------------------------------------------------------------------------
void show()
{
  noInterrupts();
  
  volatile uint16_t i = PIXEL_COUNT * 3;
  volatile uint8_t *ptr = pixels, b = *ptr++, hi, lo, bright = brightness, temp;
  const volatile uint8_t *port = portOutputRegister(digitalPinToPort(13));
  uint8_t pinMask = digitalPinToBitMask(13);
 
  volatile uint8_t next, bit;

  hi   = *port |  pinMask;
  lo   = *port & ~pinMask;
  next = lo;
  bit  = 8;
  b = ((int)b * bright) >> 8;

  asm volatile(
    "push R0"                  "\n\t"
    "push R1"                  "\n\t"
   "start:"                    "\n\t"
    "st   %a[port],  %[hi]"    "\n\t"
    "sbrc %[byte], 7"          "\n\t"
    "mov  %[next], %[hi]"      "\n\t"
    "dec  %[bit]"              "\n\t"
    "st   %a[port],  %[next]"  "\n\t"
    "mov  %[next] ,  %[lo]"    "\n\t"
    "breq nextbyte"            "\n\t"
    "rol  %[byte]"             "\n\t"
    "ld   %[temp],  %a[ptr]"   "\n\t"
    "nop"                      "\n\t"
    "st   %a[port],  %[lo]"    "\n\t"
    "nop"                      "\n\t"
    "mul  %[bright], %[temp]"  "\n\t"
    "rjmp start"               "\n\t"
   "nextbyte:"                 "\n\t"
    "ldi  %[bit], 8"           "\n\t"
    "adiw %[ptr], 1"           "\n\t"
    "st   %a[port], %[lo]"     "\n\t"
    "mov  %[byte], R1"         "\n\t"
    "sbiw %[count], 1"         "\n\t"
    "brne start"               "\n\t"
    "pop R1"                   "\n\t"
    "pop R0"                   "\n"
    : [port]  "+e" (port),
      [byte]  "+r" (b),
      [bit]   "+r" (bit),
      [next]  "+r" (next),
      [count] "+w" (i)
    : [ptr]    "e" (ptr),
      [hi]     "r" (hi),
      [lo]     "r" (lo),
      [bright] "d" (bright),
      [temp]   "r" (temp));
      
  interrupts();
}

// --- Keyboard --------------------------------------------------------------------------------------------------
byte ReadKeypad(void)
{
  byte keyState = 0, value;

  PORTB &= 0xfd;
  delayMicroseconds(1);
  value = PIND;
  if ((value & 0x3c) != 0x3c)
  {
    if ((value & 0x20) == 0) keyState = 1;
    else if ((value & 0x10) == 0) keyState = 2;
    else if ((value & 0x08) == 0) keyState = 3;
    else keyState = 4;
  }
  PORTB |= 0x02;

  PORTB &= 0xfe;
  delayMicroseconds(1);
  value = PIND;
  if ((value & 0x3c) != 0x3c)
  {
    if ((value & 0x20) == 0) keyState = 5;
    else if ((value & 0x10) == 0) keyState = 6;
    else if ((value & 0x08) == 0) keyState = 7;
    else keyState = 8;
  }
  PORTB |= 0x01;

  PORTD &= 0x7f;
  delayMicroseconds(1);
  value = PIND;
  if ((value & 0x3c) != 0x3c)
  {
    if ((value & 0x20) == 0) keyState = 9;
    else if ((value & 0x10) == 0) keyState = 10;
    else if ((value & 0x08) == 0) keyState = 11;
    else keyState = 12;
  }
  PORTD |= 0x80;

  PORTD &= 0xbf;
  delayMicroseconds(1);
  value = PIND;
  if ((value & 0x3c) != 0x3c)
  {
    if ((value & 0x20) == 0) keyState = 13;
    else if ((value & 0x10) == 0) keyState = 14;
    else if ((value & 0x08) == 0) keyState = 15;
    else keyState = 16;
  }
  PORTD |= 0x40;

  return keyState;
}

// --- Get color values ------------------------------------------------------------------------------------------
byte GetRed()
{
  int value = (analogRead(PR) >> 2);
  if (abs(value - lastRed) > 3 || value == 0 || value == 255)
    lastRed = value;
  return lastRed;
}

byte GetGreen()
{
  int value = (analogRead(PG) >> 2);
  if (abs(value - lastGreen) > 3 || value == 0 || value == 255)
    lastGreen = value;
  return lastGreen;
}

byte GetBlue()
{
  int value = (analogRead(PB) >> 2);
  if (abs(value - lastBlue) > 3 || value == 0 || value == 255)
    lastBlue = value;
  return lastBlue;
}

// --- Rainbow colors --------------------------------------------------------------------------------------------
void Rainbow(int index, byte pos)
{
  if(pos < 85)
  {
    pixels[index * 3 + 0] = 255 - pos * 3;
    pixels[index * 3 + 1] = 0;
    pixels[index * 3 + 2] = pos * 3;
  }
  else if(pos < 170)
  {
    pos -= 85;
    pixels[index * 3 + 0] = 0;
    pixels[index * 3 + 1] = pos * 3;
    pixels[index * 3 + 2] = 255 - pos * 3;
  }
  else
  {
    pos -= 170;
    pixels[index * 3 + 0] = pos * 3;
    pixels[index * 3 + 1] = 255 - pos * 3;
    pixels[index * 3 + 2] = 0;
  }
}

void Rainbow(byte pos, byte *r, byte *g, byte *b)
{
  if(pos < 85)
  {
    *r = 255 - pos * 3;
    *g = 0;
    *b = pos * 3;
  }
  else if(pos < 170)
  {
    pos -= 85;
    *r = 0;
    *g = pos * 3;
    *b = 255 - pos * 3;
  }
  else
  {
    pos -= 170;
    *r = pos * 3;
    *g = 255 - pos * 3;
    *b = 0;
  }
}

// --- Mode 1 ----------------------------------------------------------------------------------------------------
void Mode1(bool init)
{
  static byte phase;
  
  if (init)
    phase = 0;

  if (nextStep)
  {
    for(int i = PIXEL_COUNT - 1; i >= 0; i--)
      Rainbow(i, (phase + i) & 255);
    
    phase++;
  }
}

// --- Mode 2 ----------------------------------------------------------------------------------------------------
void Mode2(bool init)
{
  static byte delayLoop;

  byte r = GetRed() >> 3;
  byte g = GetGreen() >> 3;
  byte b = GetBlue() >> 3;
  
  if (init)
  {
    delayLoop = 0;
    
    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = r;
      pixels[i * 3 + 1] = g;
      pixels[i * 3 + 2] = b;
    }
  }
  
  for(int i = 0; i < PIXEL_COUNT; i++)
  {
    if (pixels[i * 3 + 0] < r)
    {
      if (pixels[i * 3 + 0] < r - 4)
        pixels[i * 3 + 0] += 4;
      else
        pixels[i * 3 + 0] = r;
    }
    else if (pixels[i * 3 + 0] > r)
    {
      if (pixels[i * 3 + 0] > r + 4)
        pixels[i * 3 + 0] -= 4;
      else
        pixels[i * 3 + 0] = r;
    }

    if (pixels[i * 3 + 1] < g)
    {
      if (pixels[i * 3 + 1] < g - 4)
        pixels[i * 3 + 1] += 4;
      else
        pixels[i * 3 + 1] = g;
    }
    else if (pixels[i * 3 + 1] > g)
    {
      if (pixels[i * 3 + 1] > g + 4)
        pixels[i * 3 + 1] -= 4;
      else
        pixels[i * 3 + 1] = g;
    }

    if (pixels[i * 3 + 2] < b)
    {
      if (pixels[i * 3 + 2] < b - 4)
        pixels[i * 3 + 2] += 4;
      else
        pixels[i * 3 + 2] = b;
    }
    else if (pixels[i * 3 + 2] > b)
    {
      if (pixels[i * 3 + 2] > b + 4)
        pixels[i * 3 + 2] -= 4;
      else
        pixels[i * 3 + 2] = b;
    }
  }
  
  if (nextStep && ++delayLoop == 5)
  {
    delayLoop = 0;
    
    int index = random(PIXEL_COUNT);
    pixels[index * 3 + 0] = 255;
    pixels[index * 3 + 1] = 255;
    pixels[index * 3 + 2] = 255;
  }
}

// --- Mode 3 ----------------------------------------------------------------------------------------------------
void Mode3(bool init)
{
  byte r = GetRed();
  byte g = GetGreen();
  byte b = GetBlue();

  for(int i = 0; i < PIXEL_COUNT; i++)
  {
    pixels[i * 3 + 0] = r;
    pixels[i * 3 + 1] = g;
    pixels[i * 3 + 2] = b;
  }
}

// --- Mode 4 ----------------------------------------------------------------------------------------------------
void Mode4(bool init)
{
  static byte colorIndex1, colorIndex2, colorIndex3;  //color
  static byte colorPhase1, colorPhase2, colorPhase3;  //colorPhase
  static byte d1, d2, d3;                             //delay
  static int v1, v2, v3, p1, p2, p3;                  //velocity, position
  
  if (init)
  {
    colorIndex1 = random(256);
    
    do 
    {
      colorIndex2 = random(256);
    } while (abs((int)colorIndex2 - colorIndex1) < 64);
    
    do
    {
      colorIndex3 = random(256);
    } while (abs((int)colorIndex3 - colorIndex2) < 64 || abs((int)colorIndex3 - colorIndex1) < 64);
    
    colorPhase1 = colorPhase2 = colorPhase3 = 0;
    
    d1 = 0;
    d2 = 0;
    d3 = 0;
    
    v1 = random(4) + 1;
    do 
    {
      v2 = random(4) + 1;
    } while (v2 == v1);
    do
    {
      v3 = random(4) + 1;
    } while (v3 == v1 || v3 == v2);
    
    if (random(2) == 0)
      p1 = 0;
    else
    {
      p1 = PIXEL_COUNT - 1;
      v1 = -v1;
    }
    
    if (random(2) == 0)
      p2 = 0;
    else
    {
      p2 = PIXEL_COUNT - 1;
      v2 = -v2;
    }
  
    if (random(2) == 0)
      p3 = 0;
    else
    {
      p3 = PIXEL_COUNT - 1;
      v3 = -v3;
    }
    
    for(int i = 0; i < PIXEL_COUNT * 3; i++)
      pixels[i] = 0;
    
    demoEffectCounter = 0;
    hiSpeed = true;
  }

  int maxColorPhase1, maxColorPhase2, maxColorPhase3, pos;
  byte r1, g1, b1, r2, g2, b2, r3, g3, b3, v;
  long factor1, factor2, factor3, factor;

  maxColorPhase1 = loopDelay * abs(v1);
  if (colorPhase1 > maxColorPhase1)
    colorPhase1 = maxColorPhase1;

  maxColorPhase2 = loopDelay * abs(v2);
  if (colorPhase2 > maxColorPhase2)
    colorPhase2 = maxColorPhase2;

  maxColorPhase3 = loopDelay * abs(v3);
  if (colorPhase3 > maxColorPhase3)
    colorPhase3 = maxColorPhase3;

  Rainbow(colorIndex1, &r1, &g1, &b1);
  Rainbow(colorIndex2, &r2, &g2, &b2);
  Rainbow(colorIndex3, &r3, &g3, &b3);

  for(int l = 0; l < PIXEL_COUNT; l++)
  {
    factor1 = factor2 = factor3 = 0;
    
    pos = (v1 > 0) ? p1 - l : l - p1;
    if (pos >= 0 && pos < 40)
    {
      if (pos < 8)
        factor1 = ((long)colorPhase1 << 5) / maxColorPhase1 + ((long)pos << 5);
      else if (pos == 39)
        factor1 = 0;
      else if (pos > 31)
        factor1 = ((39L - pos) << 5) - ((long)colorPhase1 << 5) / maxColorPhase1;
      else
        factor1 = 256;
    }
    
    pos = (v2 > 0) ? p2 - l : l - p2;
    if (pos >= 0 && pos < 40)
    {
      if (pos < 8)
        factor2 = ((long)colorPhase2 << 5) / maxColorPhase2 + ((long)pos << 5);
      else if (pos == 39)
        factor2 = 0;
      else if (pos > 31)
        factor2 = ((39L - pos) << 5) - ((long)colorPhase2 << 5) / maxColorPhase2;
      else
        factor2 = 256;
    }

    pos = (v3 > 0) ? p3 - l : l - p3;
    if (pos >= 0 && pos < 40)
    {
      if (pos < 8)
        factor3 = ((long)colorPhase3 << 5) / maxColorPhase3 + ((long)pos << 5);
      else if (pos == 39)
        factor3 = 0;
      else if (pos > 31)
        factor3 = ((39L - pos) << 5) - ((long)colorPhase3 << 5) / maxColorPhase3;
      else
        factor3 = 256;
    }
    
    factor = factor1 + factor2 + factor3;
    if (factor > 0)
    {
      pixels[l * 3 + 0] = ((r1 * factor1 * factor1 + r2 * factor2 * factor2 + r3 * factor3 * factor3) / factor) >> 8;
      pixels[l * 3 + 1] = ((g1 * factor1 * factor1 + g2 * factor2 * factor2 + g3 * factor3 * factor3) / factor) >> 8;
      pixels[l * 3 + 2] = ((b1 * factor1 * factor1 + b2 * factor2 * factor2 + b3 * factor3 * factor3) / factor) >> 8;
    }
    else
    {
      pixels[l * 3 + 0] = 0;
      pixels[l * 3 + 1] = 0;
      pixels[l * 3 + 2] = 0;
    }
  }

  colorPhase1++;
  colorPhase2++;
  colorPhase3++;
  
  if (nextStep)
  {
    d1++;
    if (d1 >= abs(v1))
    {
      d1 = 0;
      colorPhase1 = 0;
      p1 += (v1 > 0) ? 1 : -1;
      
      if (p1 < -40 || p1 > PIXEL_COUNT + 40)
      {
        do
        {
          colorIndex1 = random(256);
        } while (abs((int)colorIndex1 - colorIndex2) < 64 || abs((int)colorIndex1 - colorIndex3) < 64);
       
        do
        {
          v = random(4) + 1;
        } while (v == abs(v2) || v == abs(v3));
        
        if (v1 > 0)
        {
          v1 = -v;
          p1 = PIXEL_COUNT - 1;
        }
        else
        {
          v1 = v;
          p1 = 0;
        }
        
        demoEffectCounter++;
      }
    }
      
    d2++;
    if (d2 >= abs(v2))
    {
      d2 = 0;
      colorPhase2 = 0;
      p2 += (v2 > 0) ? 1 : -1;
      
      if (p2 < -40 || p2 > PIXEL_COUNT + 40)
      {
        do
        {
          colorIndex2 = random(256);
        } while (abs((int)colorIndex2 - colorIndex1) < 64 || abs((int)colorIndex2 - colorIndex3) < 64);
       
        do
        {
          v = random(4) + 1;
        } while (v == abs(v1) || v == abs(v3));
        
        if (v2 > 0)
        {
          v2 = -v;
          p2 = PIXEL_COUNT - 1;
        }
        else
        {
          v2 = v;
          p2 = 0;
        }
        
        demoEffectCounter++;
      }
    }
    
    d3++;
    if (d3 >= abs(v3))
    {
      d3 = 0;
      colorPhase3 = 0;
      p3 += (v3 > 0) ? 1 : -1;
      
      if (p3 < -40 || p3 > PIXEL_COUNT + 40)
      {
        do
        {
          colorIndex3 = random(256);
        } while (abs((int)colorIndex3 - colorIndex1) < 64 || abs((int)colorIndex3 - colorIndex2) < 64);
       
        do
        {
          v = random(4) + 1;
        } while (v == abs(v1) || v == abs(v2));
        
        if (v3 > 0)
        {
          v3 = -v;
          p3 = PIXEL_COUNT - 1;
        }
        else
        {
          v3 = v;
          p3 = 0;
        }
        
        demoEffectCounter++;
      }
    }
   
    demoCounter = (demoEffectCounter < 4) ? 0 : 10000;
  }
}

// --- Mode 5 ----------------------------------------------------------------------------------------------------
void Mode5(bool init)
{
  static byte delayLoop;
  
  byte r = GetRed();
  byte g = GetGreen();
  byte b = GetBlue();

  if ((r | g | b) == 0)
    r = g = b = 1;
  
  if (init)
  {
    delayLoop = 0;
    
    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = r;
      pixels[i * 3 + 1] = g;
      pixels[i * 3 + 2] = b;      
    }
    
    for(int i = 0; i < PIXEL_COUNT / 4; i++)
    {
      int index;

      do 
      {
        index = random(PIXEL_COUNT);
      } while ((pixels[index * 3 + 0] | pixels[index * 3 + 1] | pixels[index * 3 + 2]) == 0);

      pixels[index * 3 + 0] = 0;
      pixels[index * 3 + 1] = 0;
      pixels[index * 3 + 2] = 0;
    }
  }

  if (nextStep && ++delayLoop == 3)
  {
    delayLoop = 0;
    
    byte numberOfDiodes = (18 - loopDelay) >> 1;
  
    while(numberOfDiodes > 0)
    {
      int index1, index2;
     
      do 
      {
        index1 = random(PIXEL_COUNT);
      } while ((pixels[index1 * 3 + 0] | pixels[index1 * 3 + 1] | pixels[index1 * 3 + 2]) == 0);
      
      do
      {
        index2 = random(PIXEL_COUNT);
      } while ((pixels[index2 * 3 + 0] | pixels[index2 * 3 + 1] | pixels[index2 * 3 + 2]) > 0);
      
      pixels[index1 * 3 + 0] = 0;
      pixels[index1 * 3 + 1] = 0;
      pixels[index1 * 3 + 2] = 0;
      
      pixels[index2 * 3 + 0] = r;
      pixels[index2 * 3 + 1] = g;
      pixels[index2 * 3 + 2] = b;
  
      numberOfDiodes--;
    }
  }
}

// --- Mode 6 ----------------------------------------------------------------------------------------------------
void Mode6(bool init)
{
  static byte phase, colorPhase, delayLoop;
  
  if (init)
    delayLoop = phase = colorPhase = 0;

  byte r = GetRed();
  byte g = GetGreen();
  byte b = GetBlue();
  
  int maxColorPhase = loopDelay * 2;
  if (colorPhase > maxColorPhase)
    colorPhase = maxColorPhase;
  
  for(int i = 0; i < PIXEL_COUNT; i++)
  {
    int index = (i + phase) % 14;
    word factor;
    
    if (index < 4)
      factor = ((word)colorPhase << 6) / maxColorPhase + ((word)index << 6);
    else if (index < 8)
      factor = ((word)(8 - index) << 6) - ((word)colorPhase << 6) / maxColorPhase;
    else factor = 0;
    
    pixels[i * 3 + 0] = (r * factor) >> 8;
    pixels[i * 3 + 1] = (g * factor) >> 8;
    pixels[i * 3 + 2] = (b * factor) >> 8;
  }

  colorPhase++;

  if (nextStep && ++delayLoop == 2)
  {
    delayLoop = 0;
    colorPhase = 0;
    
    if (++phase == 14)
      phase = 0;
  }
}

// --- Mode 7 ----------------------------------------------------------------------------------------------------
void Mode7(bool init)
{
  static byte phase;
  
  if (init)
    phase = 0;

  if (nextStep)
  {
    for(int i = 0; i < PIXEL_COUNT; i++)
      Rainbow(i, phase);
    
    phase++;
  }
}

// --- Mode 8 ----------------------------------------------------------------------------------------------------
void Mode8(bool init)
{
  static byte phase, colorIndex, delayLoop, colorPhase;
  
  if (init)
    delayLoop = phase = colorIndex = colorPhase = 0;

  int maxColorPhase = loopDelay * 8;
  if (colorPhase > maxColorPhase)
    colorPhase = maxColorPhase;

  byte r, g, b;
  
  byte pr = GetRed() >> 3;
  byte pg = GetGreen() >> 3;
  byte pb = GetBlue() >> 3;
  
  for(int i = 0; i < PIXEL_COUNT; i++)
  {
    pixels[i * 3 + 0] = pr;
    pixels[i * 3 + 1] = pg;
    pixels[i * 3 + 2] = pb;
  }

  long factor = ((long)colorPhase << 8) / maxColorPhase;
  
  for(int i = 0; i < PIXEL_COUNT; i += 15)
  {
    Rainbow((i - colorIndex) % 255, &r, &g, &b);
    
    int pos = i + phase;
    if (pos < PIXEL_COUNT)
    {
      pixels[pos * 3 + 0] = (factor * r + (256 - factor) * pr) >> 8;
      pixels[pos * 3 + 1] = (factor * g + (256 - factor) * pg) >> 8;
      pixels[pos * 3 + 2] = (factor * b + (256 - factor) * pb) >> 8;
    }
    pos--;
    if (pos >= 0 && pos < PIXEL_COUNT)
    {
      pixels[pos * 3 + 0] = ((256 - factor) * r + factor * pr) >> 8;
      pixels[pos * 3 + 1] = ((256 - factor) * g + factor * pg) >> 8;
      pixels[pos * 3 + 2] = ((256 - factor) * b + factor * pb) >> 8;
    }
  }
  
  colorPhase++;
  
  if (nextStep && ++delayLoop == 8)
  {
    delayLoop = 0;
    colorPhase = 0;
  
    if (++phase == 15)
    {
      phase = 0;
      colorIndex += 15;
    }
  }
}

// --- Mode 9 ----------------------------------------------------------------------------------------------------
void Mode9(bool init)
{
  static byte phase, colorIndex, previousColorIndex, colorPhase;
  byte r, g, b, pr, pg, pb;
  
  if (init)
  {
    colorPhase = phase = 0;
    colorIndex = random(256);
    previousColorIndex = colorIndex ^ 0x80;
    
    Rainbow(previousColorIndex, &r, &g, &b);
    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = r;
      pixels[i * 3 + 1] = g;
      pixels[i * 3 + 2] = b;
    }
  }
  
  int maxColorPhase = loopDelay;
  if (colorPhase > maxColorPhase)
    colorPhase = maxColorPhase;
  
  Rainbow(colorIndex, &r, &g, &b);
  Rainbow(previousColorIndex, &pr, &pg, &pb);
  
  for(int i = 0; i < 15; i++)
    for(int k = 0; k < PIXEL_COUNT; k += 15)
    {
      int pos = k + i;
      if (pos >= PIXEL_COUNT)
        break;
        
      int actualPhase = phase - i;
      if (actualPhase < 0)
        continue;
        
      long factor = (actualPhase >= 8) ? 256 : ((long)actualPhase << 5) + ((long)colorPhase << 5) / maxColorPhase;
      
      pixels[pos * 3 + 0] = (factor * r + (256 - factor) * pr) >> 8;
      pixels[pos * 3 + 1] = (factor * g + (256 - factor) * pg) >> 8;
      pixels[pos * 3 + 2] = (factor * b + (256 - factor) * pb) >> 8;
    }
 
  colorPhase++;
 
  if (nextStep)
  {
    colorPhase = 0;
    
    if (++phase == 25)
    {
      phase = 0;
      previousColorIndex = colorIndex;
      do
      {
        colorIndex = random(256);
      } while (abs((int)previousColorIndex - colorIndex) < 64);
    }
  }
}
    
// --- Mode 10 ---------------------------------------------------------------------------------------------------
void Mode10(bool init)
{
  static int index;
  static byte colorIndex, previousColorIndex;
  byte r, g, b, pr, pg, pb;
    
  if (init)
  {
    index = 0;
    colorIndex = random(256);
    previousColorIndex = colorIndex ^ 0x80;
    
    Rainbow(previousColorIndex, &r, &g, &b);
    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = r;
      pixels[i * 3 + 1] = g;
      pixels[i * 3 + 2] = b;
    }
    demoEffectCounter = 0;
  }
  
  if (nextStep)
  {
    Rainbow(previousColorIndex, &pr, &pg, &pb);
    Rainbow(colorIndex, &r, &g, &b);
    
    for(int i = 0; i < PIXEL_COUNT + 16; i++)
    {
      int pos = index - i;
      if (pos < 0 || pos >= PIXEL_COUNT)
        continue;
       
       if (i < 16)
       {
         pixels[pos * 3 + 0] = (i * r + pr * (16 - i)) >> 4;
         pixels[pos * 3 + 1] = (i * g + pg * (16 - i)) >> 4;
         pixels[pos * 3 + 2] = (i * b + pb * (16 - i)) >> 4;
       }
       else
       {
         pixels[pos * 3 + 0] = r;
         pixels[pos * 3 + 1] = g;
         pixels[pos * 3 + 2] = b;
       }
    }
    
    if (++index > PIXEL_COUNT + 16)
    {
      index = 0;
      previousColorIndex = colorIndex;
      do
      {
        colorIndex = random(256);
      } while (abs((int)previousColorIndex - colorIndex) < 64);
      
      demoCounter = (++demoEffectCounter < 2) ? 0 : 10000;
    }
  }
}

// --- Mode 11 ---------------------------------------------------------------------------------------------------
void Mode11(bool init)
{
  static int startPosition;
  static byte colorIndex;
  
  if (init)
  {
    startPosition = 0;
    colorIndex = random(256);
    demoEffectCounter = 0;
  }

  if (nextStep)
  {
    byte pr = GetRed() >> 2;
    byte pg = GetGreen() >> 2;
    byte pb = GetBlue() >> 2;

    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = pr;
      pixels[i * 3 + 1] = pg;
      pixels[i * 3 + 2] = pb;
    }
    
    int pos;
    byte nr, ng, nb, r, g, b;
    
    Rainbow(colorIndex, &r, &g, &b);
    
    for(int i = 0; i < 90; i++)
    {
      pos = startPosition - i;
      if (pos < 0 || pos >= PIXEL_COUNT)
        continue;
       
       if (i < 20)
       {
         nr = i * r / 20;
         ng = i * g / 20;
         nb = i * b / 20;
       }
       else if (i > 70)
       {
         nr = (89 - i) * r / 20;
         ng = (89 - i) * g / 20;
         nb = (89 - i) * b / 20;
       }
       else
       {
         nr = r;
         ng = g;
         nb = b;
       }
       
       if (nr > pr)
         pixels[pos * 3 + 0] = nr;
       if (ng > pg)
         pixels[pos * 3 + 1] = ng;
       if (nb > pb)
         pixels[pos * 3 + 2] = nb;
    }
    
    startPosition++;
    if (startPosition - 90 > PIXEL_COUNT)
    {
      startPosition = 0;
      colorIndex = random(256);
      demoCounter = (++demoEffectCounter < 3) ? 0 : 10000;
    }
  }
}

// --- Mode 12 ---------------------------------------------------------------------------------------------------
void Mode12(bool init)
{
  static int startPosition;
  
  if (init)
    demoEffectCounter = startPosition = 0;

  if (nextStep)
  {
    byte r = GetRed();
    byte g = GetGreen();
    byte b = GetBlue();

    byte pr = r >> 3;
    byte pg = g >> 3;
    byte pb = b >> 3;

    for(int i = 0; i < PIXEL_COUNT; i++)
    {
      pixels[i * 3 + 0] = pr;
      pixels[i * 3 + 1] = pg;
      pixels[i * 3 + 2] = pb;
    }
    
    int pos;
    byte nr, ng, nb;
    
    for(int i = 0; i < 60; i++)
    {
      pos = startPosition - i;
      if (pos < 0 || pos >= PIXEL_COUNT)
        continue;
       
       if (i < 20)
       {
         nr = i * r / 20;
         ng = i * g / 20;
         nb = i * b / 20;
       }
       else if (i > 40)
       {
         nr = (59 - i) * r / 20;
         ng = (59 - i) * g / 20;
         nb = (59 - i) * b / 20;
       }
       else
       {
         nr = r;
         ng = g;
         nb = b;
       }
       
       if (nr > pr)
         pixels[pos * 3 + 0] = nr;
       if (ng > pg)
         pixels[pos * 3 + 1] = ng;
       if (nb > pb)
         pixels[pos * 3 + 2] = nb;
    }
    
    startPosition++;
    if (startPosition - 90 > PIXEL_COUNT)
    {
      startPosition = 0;
      demoCounter = (++demoEffectCounter < 2) ? 0 : 10000;
    }
  }
}

// --- Mode 13 ---------------------------------------------------------------------------------------------------
void Mode13(bool init)
{
  static byte delayLoop;
  
  if (init)
  {
    for(int i = 0; i < PIXEL_COUNT; i++)
      Rainbow(i, random(256));
    
    for(int i = 0; i < PIXEL_COUNT / 5; i++)
    {
      int index;

      do 
      {
        index = random(PIXEL_COUNT);
      } while ((pixels[index * 3 + 0] | pixels[index * 3 + 1] | pixels[index * 3 + 2]) == 0);
      
      pixels[index * 3 + 0] = 0;
      pixels[index * 3 + 1] = 0;
      pixels[index * 3 + 2] = 0;
    }
    
    delayLoop = 0;
  }
  
  if (nextStep && ++delayLoop == 3)
  {
    delayLoop = 0;
    
    byte numberOfDiodes = (18 - loopDelay) >> 1;
  
    while(numberOfDiodes > 0)
    {
      int index1, index2;
     
      do 
      {
        index1 = random(PIXEL_COUNT);
      } while ((pixels[index1 * 3 + 0] | pixels[index1 * 3 + 1] | pixels[index1 * 3 + 2]) == 0);
      
      do
      {
        index2 = random(PIXEL_COUNT);
      } while ((pixels[index2 * 3 + 0] | pixels[index2 * 3 + 1] | pixels[index2 * 3 + 2]) > 0);
      
      pixels[index1 * 3 + 0] = 0;
      pixels[index1 * 3 + 1] = 0;
      pixels[index1 * 3 + 2] = 0;
      
      Rainbow(index2, random(256));
  
      numberOfDiodes--;
    }
  }
}

// --- Mode 14 ---------------------------------------------------------------------------------------------------
void Mode14(bool init)
{
  static byte phase, r, g, b, nr, ng, nb;
  static int pos;
  
  if (init)
  {
    for(int i = 0; i < PIXEL_COUNT; i++)
      Rainbow(i, random(256));
    
    phase = 0;
    pos = random(PIXEL_COUNT);
    r = pixels[pos * 3 + 0];
    g = pixels[pos * 3 + 1];
    b = pixels[pos * 3 + 2];
    
    do
    {
      Rainbow(random(256), &nr, &ng, &nb);
    } while (abs((int)nr - r) < 64 && abs((int)ng - g) < 64 && abs((int)nb - b) < 64);
  }
  
  if (nextStep)
  {
    byte ar, ag, ab;
  
    pixels[pos * 3 + 0] = r + ((((int)nr - r) * phase) >> 4);
    pixels[pos * 3 + 1] = g + ((((int)ng - g) * phase) >> 4);
    pixels[pos * 3 + 2] = b + ((((int)nb - b) * phase) >> 4);
    
    if (++phase > 16)
    {
      phase = 0;
      pos = random(PIXEL_COUNT);
      
      r = pixels[pos * 3 + 0];
      g = pixels[pos * 3 + 1];
      b = pixels[pos * 3 + 2];
      
      do
      {
        Rainbow(random(256), &nr, &ng, &nb);
      } while (abs((int)nr - r) < 64 && abs((int)ng - g) < 64 && abs((int)nb - b) < 64);
    }
  }
}

// --- Mode 15 ---------------------------------------------------------------------------------------------------
void Mode15(bool init)
{
  static int startPosition, lastPosition;
  static byte colorIndex, lastColorIndex, firstColorIndex;
  static bool entering;
  
  if (init)
  {
    startPosition = 0;
    lastPosition = PIXEL_COUNT;
    
    entering = true;
    
    colorIndex = random(256);
    lastColorIndex = colorIndex;
    firstColorIndex = colorIndex;
    
    for(int i = 0; i < PIXEL_COUNT * 3; i++)
      pixels[i] = 0;
      
    demoEffectCounter = 0;
  }
  
  if (nextStep)
  {
    int pos;
    byte nr, ng, nb, r, g, b;
    
    if (entering)
    {
      Rainbow(colorIndex, &r, &g, &b);
      
      for(int i = 0; i < 34; i++)
      {
        pos = startPosition - i;
        if (pos < 0 || pos >= PIXEL_COUNT)
          continue;
         
         if (pos >= lastPosition)
         {
           nr = (i * r + ((10 - i) * pixels[(lastPosition + 12) * 3 + 0])) / 10;
           ng = (i * g + ((10 - i) * pixels[(lastPosition + 12) * 3 + 1])) / 10;
           nb = (i * b + ((10 - i) * pixels[(lastPosition + 12) * 3 + 2])) / 10;
         }
         else
         {
           if (i < 9)
           {
             nr = ((i + 1) * r) / 10;
             ng = ((i + 1) * g) / 10;
             nb = ((i + 1) * b) / 10;
           }
           else if (i > 24)
           {
             int value = (startPosition > lastPosition) ? 34 - i - startPosition + lastPosition : 33 - i;
             if (value < 0)
               value = 0;
             nr = (value * r) / 10;
             ng = (value * g) / 10;
             nb = (value * b) / 10;
           }
           else
           {
             nr = r;
             ng = g;
             nb = b;
           }
         }
         
         pixels[pos * 3 + 0] = nr;
         pixels[pos * 3 + 1] = ng;
         pixels[pos * 3 + 2] = nb;
      }
      
      startPosition++;
      if (startPosition == lastPosition + 10)
      {
        startPosition = 0;
        demoCounter = 0;

        do
        {
          colorIndex = random(256);
        } while (abs((int)colorIndex - lastColorIndex) < 64);

        lastColorIndex = colorIndex;

        lastPosition -= 15;
        
        if (lastPosition < 0)
        {
          entering = false;
          lastPosition = PIXEL_COUNT;
        }
      }
    }
    else
    {
      startPosition++;
      
      for(int i = 0; i < PIXEL_COUNT - startPosition; i++)
      {
        pixels[i * 3 + 0] = pixels[(i + 1) * 3 + 0];
        pixels[i * 3 + 1] = pixels[(i + 1) * 3 + 1];
        pixels[i * 3 + 2] = pixels[(i + 1) * 3 + 2];
      }
      
      Rainbow(firstColorIndex, &r, &g, &b);
      for(int i = 0; i <= 10; i++)
      {
        pos = PIXEL_COUNT - startPosition + i;
        if (pos < PIXEL_COUNT && pos >= 0)
        {
          pixels[pos * 3 + 0] = (10 - i) * r / 10;
          pixels[pos * 3 + 1] = (10 - i) * g / 10;
          pixels[pos * 3 + 2] = (10 - i) * b / 10;
        }
      }
      
      if (startPosition == PIXEL_COUNT + 10)
      {
        entering = true;
        firstColorIndex = lastColorIndex;
        lastPosition = PIXEL_COUNT;
        startPosition = 0;
        demoCounter = 10000;
      }
    }
  }
}

// --- Moin loop -------------------------------------------------------------------------------------------------
void loop()
{
  byte oldMode = 0;
  bool init;
  
  while (true)
  {
    if (mode != oldMode)
    {
      oldMode = mode;
      init = true;
      
      delayValue = 0;
      nextStep = true;
      hiSpeed = false;
    }
    else
      init = false;
    
    switch(mode)
    {
      case 1: Mode1(init); break;
      case 2: Mode2(init); break;
      case 3: Mode3(init); break;
      case 4: Mode4(init); break;
      case 5: Mode5(init); break;
      case 6: Mode6(init); break;
      case 7: Mode7(init); break;
      case 8: Mode8(init); break;
      case 9: Mode9(init); break;
      case 10: Mode10(init); break;
      case 11: Mode11(init); break;
      case 12: Mode12(init); break;
      case 13: Mode13(init); break;
      case 14: Mode14(init); break;
      case 15: Mode15(init); break;
    }
    
    show();

    byte key = ReadKeypad();
    if (key == 16)
    {
      if (!demoMode)
      {
        demoMode = true;
        demoCounter = 0;
        mode = 1;
      }
      key = 0;
    }
    else if (key > 0)
    {
      mode = key;
      demoMode = false;
    }
    
    int value = (analogRead(PBRIGHTNESS) >> 2) + 1;
    if (abs(value - brightness) > 3 || value == 1 || value == 256)
      brightness = value;

    value = analogRead(PSPEED) >> 6;
    loopDelay = (hiSpeed) ? 4 - (value >> 2) : 16 - value;

    delayValue++;
    if (delayValue >= loopDelay)
    {
      delayValue = 0;
      nextStep = true;
    }
    else
      nextStep = false;

    if (demoMode && nextStep)
    {
      if (++demoCounter >= PIXEL_COUNT * 2)
      {
        demoCounter = 0;
        if (++mode == 16)
          mode = 1;
      }
    }
  }
}