Извлечение фрагментов из байтов в цикле for

У меня возникли проблемы с обработчиком прерывания DMA, который я адаптировал для ЖК-дисплея встроенного чипа MicroChip PIC32.

У меня ограниченная внутренняя память, и мне нужен буфер кадров для моего цветного ЖК-дисплея. Решили использовать 16 цветов и использовать откусывание на пиксель. Я создал массив, который выглядит так:

unsigned char GraphicsFrame[FRAME_HEIGHT][LINE_LENGTH/2]; 

В моем обработчике прерываний я конвертирую 4-битный полубайт в 16-битное значение для отправки на ЖК-дисплей через параллельный порт и передачу DMA. Для этого я использую справочную таблицу в обработчике прерываний, но при отладке я захожу в General_Exception_Handler, и он указывает на проблему в том, как я извлекаю 4-битный полубайт и преобразовываю его в 16-битное значение:

for( i=0,j=0; i<30; i++, lineX++ )
{
    // not particularly elegant, perhaps look at a better way
    if     ((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x0) lineBuffer[j++] = (unsigned short int)RGBBlack;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x1) lineBuffer[j++] = (unsigned short int)RGBBlue;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x2) lineBuffer[j++] = (unsigned short int)RGBRed;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x3) lineBuffer[j++] = (unsigned short int)RGBGreen;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x4) lineBuffer[j++] = (unsigned short int)RGBCyan;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x6) lineBuffer[j++] = (unsigned short int)RGBYellow;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0x7) lineBuffer[j++] = (unsigned short int)RGBKaneGreen;
    else if((((GraphicsFrame[line][i]) >> 4) & 0x0F) == 0xF) lineBuffer[j++] = (unsigned short int)RGBWhite;

    if     ((GraphicsFrame[line][i] & 0x0F) == 0x0) lineBuffer[j++] = (unsigned short int)RGBBlack;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x1) lineBuffer[j++] = (unsigned short int)RGBBlue;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x2) lineBuffer[j++] = (unsigned short int)RGBRed;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x3) lineBuffer[j++] = (unsigned short int)RGBGreen;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x4) lineBuffer[j++] = (unsigned short int)RGBCyan;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x5) lineBuffer[j++] = (unsigned short int)RGBMagenta;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x6) lineBuffer[j++] = (unsigned short int)RGBYellow;
    else if((GraphicsFrame[line][i] & 0x0F) == 0x7) lineBuffer[j++] = (unsigned short int)RGBKaneGreen;
    else if((GraphicsFrame[line][i] & 0x0F) == 0xF) lineBuffer[j++] = (unsigned short int)RGBWhite;
}

Я пытаюсь настроить DMA для передачи 60 пикселей за раз (60 x 16 бит), используя другой массив, содержащий 60 пикселей:

unsigned short int lineBuffer[60];

Может ли кто-нибудь обнаружить проблему с тем, как я извлекаю кусок и конвертирую его? Предупреждений и ошибок нет, так что ничего не выскакивает!

Любая помощь приветствуется, спасибо


person mr_Alex_Nok_    schedule 17.04.2014    source источник


Ответы (1)


Насколько я могу судить из того, что вы написали, все в порядке. Единственное, что подозрительно, это переменные line и lineX. Кажется, они не используются. Кроме того, если вы хотите выполнить итерацию по первому измерению двумерного массива, вам, вероятно, придется использовать вложенные циклы for.

Остальная часть поста представляет собой обзор кода, а не ответ:

Размещенный код не является таблицей поиска. Попробуйте сделать это так:

const uint16_t COLOR_TABLE [COLORS_N] = 
{
  RGBBlack,      // 0x0
  RGBBlue,       // 0x1
  RGBRed,        // 0x2
  RGBGreen,      // 0x3
  RGBCyan,       // 0x4
  undefined,     // 0x5
  RGBYellow,     // 0x6
  RGBKaneGreen,  // 0x7
  undefined,     // 0x8
  undefined,     // 0x9
  undefined,     // 0xA
  undefined,     // 0xB
  undefined,     // 0xC
  undefined,     // 0xD
  undefined,     // 0xE
  RGBWhite,      // 0xF
};

...

uint8_t line_iterator=0;

for(uint8_t i=0; i<LINE_LENGTH/2; i++)
{
  uint8_t nibble;

  nibble = (uint8_t) ((GraphicsFrame[line][i]) >> 4) & 0x0F);
  lineBuffer[line_iterator] =  COLOR_TABLE[nibble];

  nibble = (uint8_t) (GraphicsFrame[line][i] & 0x0F);
  lineBuffer[line_iterator + 1] =  COLOR_TABLE[nibble];

  line_iterator += 2;
}

Комментарии к вышеизложенному:

  • Эта таблица поиска значительно улучшит как удобочитаемость, так и скорость работы программы. Если это для ISR, вы обязательно должны использовать подобную таблицу.
  • Поскольку это встроенная система, вы должны использовать целочисленные типы из stdint.h.
  • Остерегайтесь неявных целочисленных рекламных акций.
  • Держите циклы for простыми и избегайте их запутывания. Используйте самоочевидные имена переменных для итераторов, если вам нужно более одного.
  • Не используйте «магические числа», такие как 30.
person Lundin    schedule 17.04.2014
comment
Большое спасибо за ваши комментарии. Да, на самом деле я не реализовал справочную таблицу! Это была небольшая «работа в процессе», но мне нравится ваше решение, и я реализовал большую его часть. У меня все еще возникают проблемы, так что думаю, что я выхожу за пределы где-то в ISR - person mr_Alex_Nok_; 17.04.2014