Несколько дисплеев P6 на Mega
- Войдите на сайт для отправки комментариев
Пт, 09/12/2016 - 03:55
Здравствуйте форумчане, попались мне в руки светодиодные модули p6 (64х32). Подключил к одному модулю мегу, все заработало (через Adafruit библиотеку). Однако хотелось бы связать их в квадрат. Информации как это сделать я не нашел (там все предлагают через Raspberry). Всё же путем нехитрых манипуляций мне удалось подключить два модуля строкой, но памяти больше чем на два модуля нехватает.
По расчетам если на одну точку записывать не 8 бит, а 2 бита, то я думаю можно подключить до 12 модулей. (Идея просто раскрашивать строки в три цвета). Кто нибудь заморачивался как можно модифицировать библиотеку adafruit чтобы она выделяла меньше памяти?
А как Вы собираетесь "раскрашивать строки в три цвета" при 2 битах на пиксель?
А как Вы собираетесь "раскрашивать строки в три цвета" при 2 битах на пиксель?
Не знаю, как ТС сможет закрасить , но если для картинки достаточно только 4 цвета , причем любых, то это достаточно легко организовать. Выделяется еще 12 байт: по 3 байта цветности RGB для 00,01,10,11 комбинаций.
хочется именно выделять память под пиксель два бита (т.е. 4 значения всего). не получается модифицировать библиотеку adafruit чтобы она использовала только два бита
не получается модифицировать библиотеку adafruit чтобы она использовала только два бита
Раз "не получается", значит пробовали? КОд в студию и конкретные вопросы - что именно не получается.
Вот код обновления панели, вызывается по таймеру. Данные записаны в массиве matrixbuff как он их вытаскивает ума не приложу Сама библиотека https://github.com/adafruit/RGB-matrix-Panel
void RGBmatrixPanel::updateDisplay(void) { uint8_t i, tick, tock, *ptr; uint16_t t, duration; *oeport |= oepin; // Disable LED output during row/plane switchover *latport |= latpin; // Latch data loaded during *prior* interrupt // Calculate time to next interrupt BEFORE incrementing plane #. // This is because duration is the display time for the data loaded // on the PRIOR interrupt. CALLOVERHEAD is subtracted from the // result because that time is implicit between the timer overflow // (interrupt triggered) and the initial LEDs-off line at the start // of this method. t = (nRows > 8) ? LOOPTIME : (LOOPTIME * 2); duration = ((t + CALLOVERHEAD * 2) << plane) - CALLOVERHEAD; // Borrowing a technique here from Ray's Logic: // www.rayslogic.com/propeller/Programming/AdafruitRGB/AdafruitRGB.htm // This code cycles through all four planes for each scanline before // advancing to the next line. While it might seem beneficial to // advance lines every time and interleave the planes to reduce // vertical scanning artifacts, in practice with this panel it causes // a green 'ghosting' effect on black pixels, a much worse artifact. if(++plane >= nPlanes) { // Advance plane counter. Maxed out? plane = 0; // Yes, reset to plane 0, and if(++row >= nRows) { // advance row counter. Maxed out? row = 0; // Yes, reset row counter, then... if(swapflag == true) { // Swap front/back buffers if requested backindex = 1 - backindex; swapflag = false; } buffptr = matrixbuff[1-backindex]; // Reset into front buffer } } else if(plane == 1) { // Plane 0 was loaded on prior interrupt invocation and is about to // latch now, so update the row address lines before we do that: if(row & 0x1) *addraport |= addrapin; else *addraport &= ~addrapin; if(row & 0x2) *addrbport |= addrbpin; else *addrbport &= ~addrbpin; if(row & 0x4) *addrcport |= addrcpin; else *addrcport &= ~addrcpin; if(nRows > 8) { if(row & 0x8) *addrdport |= addrdpin; else *addrdport &= ~addrdpin; } } // buffptr, being 'volatile' type, doesn't take well to optimization. // A local register copy can speed some things up: ptr = (uint8_t *)buffptr; ICR1 = duration; // Set interval for next interrupt TCNT1 = 0; // Restart interrupt timer *oeport &= ~oepin; // Re-enable output *latport &= ~latpin; // Latch down // Record current state of SCLKPORT register, as well as a second // copy with the clock bit set. This makes the innnermost data- // pushing loops faster, as they can just set the PORT state and // not have to load/modify/store bits every single time. It's a // somewhat rude trick that ONLY works because the interrupt // handler is set ISR_BLOCK, halting any other interrupts that // might otherwise also be twiddling the port at the same time // (else this would clobber them). tock = SCLKPORT; tick = tock | sclkpin; if(plane > 0) { // 188 ticks from TCNT1=0 (above) to end of function // Planes 1-3 copy bytes directly from RAM to PORT without unpacking. // The least 2 bits (used for plane 0 data) are presumed masked out // by the port direction bits. // A tiny bit of inline assembly is used; compiler doesn't pick // up on opportunity for post-increment addressing mode. // 5 instruction ticks per 'pew' = 160 ticks total #define pew asm volatile( \ "ld __tmp_reg__, %a[ptr]+" "\n\t" \ "out %[data] , __tmp_reg__" "\n\t" \ "out %[clk] , %[tick]" "\n\t" \ "out %[clk] , %[tock]" "\n" \ :: [ptr] "e" (ptr), \ [data] "I" (_SFR_IO_ADDR(DATAPORT)), \ [clk] "I" (_SFR_IO_ADDR(SCLKPORT)), \ [tick] "r" (tick), \ [tock] "r" (tock)); // Loop is unrolled for speed: pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew if (WIDTH == 64) { pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew pew } buffptr = ptr; //+= 32; } else { // 920 ticks from TCNT1=0 (above) to end of function // Planes 1-3 (handled above) formatted their data "in place," // their layout matching that out the output PORT register (where // 6 bits correspond to output data lines), maximizing throughput // as no conversion or unpacking is needed. Plane 0 then takes up // the slack, with all its data packed into the 2 least bits not // used by the other planes. This works because the unpacking and // output for plane 0 is handled while plane 3 is being displayed... // because binary coded modulation is used (not PWM), that plane // has the longest display interval, so the extra work fits. for(i=0; i<WIDTH; i++) { DATAPORT = ( ptr[i] << 6) | ((ptr[i+WIDTH] << 4) & 0x30) | ((ptr[i+WIDTH*2] << 2) & 0x0C); SCLKPORT = tick; // Clock lo SCLKPORT = tock; // Clock hi } } }Нет, ну это же просто кусок библиотеки. А где Ваши попытки переделать на 2 бита, про которые Вы говорите "не получается"? Или Вы и не пробовали?
А как Вы собираетесь "раскрашивать строки в три цвета" при 2 битах на пиксель?
00 - один цвет
01 - второй
10 - третий
и о ужас
11 - четвёртый
Да в том то и дело я не могу понять как оно все работает. Закоментировал 117 строку, а она все равно продолжает отображать, думаю дело в асемблерной вставке, но я в ней не разбираюсь что она делает. Может кто поможет, общяснит мне
Сейчас библиотека использует 12 бит на пиксель, причем старшие биты для нижней части экрана, а младшие для верхней
Понятно, значит "не пытались".
А как Вы собираетесь "раскрашивать строки в три цвета" при 2 битах на пиксель?
00 - один цвет
01 - второй
10 - третий
и о ужас
11 - четвёртый
Понял.
Я почему-то невнимательно прочитал как "три компоненты цвета".
Тогда, судя по всему у ТС именно 3 цвета (комбинации 01, 10 и 11) и отсутствие цвета (00).
mgm_arduino, я бы Вам посоветовал начать не с адаптации чужой библиотеки, а с написантя своей, пусть даже с гораздо меньшим числом возможностей. Вам нужно понять, как устроен экран и как должна быть устроена Ваша структура для управления экраном. Когда Вы это поймете (посредством написания своей библиотеки), можно будет подумать и о том, чтобы адаптировать чужую. Пока Вы к этому не готовы.
я бы Вам посоветовал начать не с адаптации чужой библиотеки, а с написантя своей, пусть даже с гораздо меньшим числом возможностей.
Тем более, что данная библиотека (которую Вы хотите менять) достаточно сложна и писалась явно не чайником.
К томуже это не самостоятельная библиотека а надстройка на GFX, изменять безсмысленно нехватит рам памяти у AVR, под DUE есть эта же библиотека вот на ней можно наращивать матрицы. в поиске набери типа RGB MATRIX DUE и найдёш эту библиотеку.