Манипуляции с массивами. Помогите найти ошибку

ustas
Offline
Зарегистрирован: 12.03.2012

Помогите найти ошибку - уже второй день бьюсь над тремя строчками.

Чтобы был чуть понятнее контекст:

Делается систма управления светодиодной биколорной матрицы с результирующим разрешением 8х32. Матрица состоит из физических матриц 8х8.

Изображение кодируется 8 наборами (8 строк) по 8 байт (4 "красных" и 4 "зеленых" байта, байты цветов - чередуются). Изменить это нельзя - управление идет с помощью цепочки сдвиговых регистров (схема уже есть и работает).

Сейчас делаю "бегущую строку" (и именно с ней и проблема). Логика работы проста:

1. Есть массив array[8][8] - его отображаем

2. Есть массив shadow[8][8] - это то, что должно "выползти"

3. Прогоняем в цикле "сдвиг" обоих массивов влево и по необходимости дополняем массив array данными из массива shadow 

Таким образом, после завершения "прогона" результирующий массив arrow должен сравняться с исходным массивом shadow.

Выкинул из скетча все лишнее - оставил только "сдвиг":

#define RED    0
#define GREEN  1
#define YELLOW 2

byte array[8][8] = { // Массив из 64 байт
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B10000000, B00000001},  // строка 7
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B01000000, B00000010},  // строка 6
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00100000, B00000100},  // строка 5
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00010000, B00001000},  // строка 4
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00001000, B00010000},  // строка 3
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000100, B00100000},  // строка 2
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000010, B01000000},  // строка 1
  {B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000001, B10000000}   // строка 0
  // red3      green3      red2      green2      red1      green1       red0      green0
  //  b0          b1         b2        b3          b4        b5          b6          b7
};

byte shadow[8][8] = { // Массив из 64 байт
  {B10000000, B00000001, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 7
  {B01000000, B00000010, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 6
  {B00100000, B00000100, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 5
  {B00010000, B00001000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 4
  {B00001000, B00010000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 3
  {B00000100, B00100000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 2
  {B00000010, B01000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000},  // строка 1
  {B00000001, B10000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000}   // строка 0
  // red3      green3      red2      green2      red1      green1       red0      green0
};


void setup(){
  int i, j, k;
  Serial.begin(9600);
  printArray();
  printShadow();
  for(k=0; k<32; k++){	// проходим 32 шага - чтобы самый крайний правый пиксель уехал влево до конца
    for(j=0; j<8; j++){		// перебираем столбцы (начинаем с самого левого)
      for(i=0; i<8; i++){	// строки (с нулевой)
        array[i][j]=array[i][j]<<1;	// сдвигаем байты основного массива на 1 (старший бит - теряется, младший - 0)
					
        // заполняем младший бит текущего байта
        if(j<6){	// если требуемый байт в рамках основного массива
                        // берем старший бит из предыдущего байта нужного цвета
          bitWrite(array[i][j],0,bitRead(array[i][j+2],7));
        }
        else {		// если в текущем массиве нет нужного байта (за границей массива)
                        // берем из начала теневого массива (подтягиваем теневой массив)
          if(j==6){	// "красный" байт
            bitWrite(array[i][6],0,bitRead(shadow[i][0],7));
          }
          else {		// "зеленый" байт
            bitWrite(array[i][7],0,bitRead(shadow[i][1],7));
          }
        }
					
        // теневой массив тоже сдвигаем
        shadow[i][j]=shadow[i][j]<<1;
        if(j<6){
           bitWrite(shadow[i][j],0,bitRead(shadow[i][j+2],7));
        }			
      }
    }
    Serial.println("-----------------------------------------------");
    Serial.print("k=");
    Serial.println(k);
    printArray();
    printShadow();
  }

}

void loop(){
}


// печатем основной массив
void printArray() {
  Serial.println("----- array -----");
  for(byte color=RED; color<YELLOW; color++){
    Serial.println((color)?"GREEN":"RED");
    for(int i=0; i<8; i++){
      for(int j=color; j<8; j=j+2) {
        for(int k=7; k>=0; k--){
          Serial.print(bitRead(array[i][j], k), DEC);
        }
        Serial.print(" ");
      }
      Serial.println();
    }
    Serial.println();
  }
}

// печатем теневой массив
void printShadow() {
  Serial.println("----- shadow ------");
  for(byte color=RED; color<YELLOW; color++){
    Serial.println((color)?"GREEN":"RED");
    for(int i=0; i<8; i++){
      for(int j=color; j<8; j=j+2) {
        for(int k=7; k>=0; k--){
          Serial.print(bitRead(shadow[i][j], k), DEC);
        }
        Serial.print(" ");
      }
      Serial.println();
    }
    Serial.println();
  }
}

В коде специально оставил пару отладочных функций для печати массива - чтобы наглядно можно было отследить.

Сам сдвиг работает, но есть ошибка, которую я никак не могу отловить (находится скорее всего в выделенных строках или в условии чуть выше).

В массиве специально завел "единички" по диагонали - чтобы при сдвиге было просто увидеть, как работает скетч.

Проблема в том, что при k=0 - из теневого массива вытягиваются неправильные данные:

----- array -----
RED
00000000 00000000 00000001 00000000 
00000000 00000000 00000000 10000001 
00000000 00000000 00000000 01000000 
00000000 00000000 00000000 00100000 
00000000 00000000 00000000 00010000 
00000000 00000000 00000000 00001000 
00000000 00000000 00000000 00000100 
00000000 00000000 00000000 00000010 

GREEN
00000000 00000000 00000000 00000010 
00000000 00000000 00000000 00000100 
00000000 00000000 00000000 00001000 
00000000 00000000 00000000 00010000 
00000000 00000000 00000000 00100000 
00000000 00000000 00000000 01000000 
00000000 00000000 00000000 10000001 
00000000 00000000 00000001 00000000 

Видно, что исходные "\" и "/" в массиве сдвинулись на 1 позицию влево, но из теневого массива почему-то подтянулись неправильные данные (в "красном" массиве самая правая единичка должна быть сверху, а не во второй строке, в "зеленом" - соответственно в самом нижнем должна быть).

Помогите найти ошибку, пожалуйста.

tsostik
Offline
Зарегистрирован: 28.02.2013

Проблема не в выделенных строках, а в логике цикла.

Если внимательно всмотреться в код станет понятно, что первый столбец теневого массива сдвигается раньше, чем последний столбец исходного. Таким образом, к моменту сдвига последнего столбца исходного массива, в первом столбце теневого (откуда должны браться данные), данные уже сдвинуты. В итоге из теневого массива берется бит, который изначально был вторым. Что неверно.

Сдвиг теневого массива нужно вынести из цикла по j в самостоятельный цикл. Оставив его, при этом, внутри цикла по k.

 

ustas
Offline
Зарегистрирован: 12.03.2012

Спасибо! Тоже уже до этого дошел. Правда, сдвиг теневого массива оставил, где он есть, но обернул его условием, чтобы выполнялся при k>0

        // теневой массив тоже сдвигаем
        if(k>0){
          shadow[i][j]=shadow[i][j]<<1;
          if(j<6){
           bitWrite(shadow[i][j],0,bitRead(shadow[i][j+2],7));
          }	
        }

Судя по выводу в сериал.монитор - работает правильно, но, может, я чего-то не замечаю?

tsostik
Offline
Зарегистрирован: 28.02.2013

Так тоже должно работать.

Но в итоге shadow окажется недосдвинутым на 1 пиксель. Если эта особенность не смущает, то и проблем нет, хотя ясности программе это не добавит -)

ustas
Offline
Зарегистрирован: 12.03.2012

особенность не смущает - во всех последующих вызовах shadow предварительно "зачищается".

Попробовал вынести из цикла и запутался еще больше (не получилось), подскажите, как это в коде должно выглядеть?

tsostik
Offline
Зарегистрирован: 28.02.2013

Сорри, пишу на бегу, подробно не  получиться, но примерно должно выглядеть так:

for(step=0;step<32; step++) //в итоге сделаем 32 сдвига
{
    for(row = 0; row < 8; row++) //цикл по строкам
    {
        for(matrix = 0; matrix < 8; matrix ++ ) //по матрицам основного массива
        {
            //сдвигаем данные. Если матрица номер 6 или 7 добавляем пиксели из 
            //теневого массива иначе из следующей матрицы основного
        }
        for(matrix = 0; matrix < 8; matrix ++ ) //по матрицам теневого массива
        {
            //сдвигаем данные теневого массива
        }
    }
}