PB2, LCD, графика

Увидел такую вещь и захотел тоже порисовать:



В общем, игрушку мне было делать лень, но вот сам вывод графики я реализовал так:

Вывод графики на HD44780

Поскольку пользовательских символов всего 8 штук, то мы имеем размер экранчика 20x16 пикселов. Хранение в буфере я реализовал вот так:

uint8_t Buffer[48] = {

    // Это наш экран 20x16

    BIN8(11111111), BIN8(11111111), BIN8(11110000), // 11111 11111 11111 11111
    BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    BIN8(10001100), BIN8(00000000), BIN8(00010000), // 10001 10000 00000 00001
    BIN8(10010010), BIN8(00000000), BIN8(00010000), // 10010 01000 00000 00001
    BIN8(10100001), BIN8(00000000), BIN8(00010000), // 10100 00100 00000 00001
    BIN8(10100001), BIN8(00000000), BIN8(00010000), // 10100 00100 00000 00001
    BIN8(11000000), BIN8(10000000), BIN8(00010000), // 11000 00010 00000 00001
    BIN8(11000000), BIN8(01000000), BIN8(00010000), // 11000 00001 00000 00001
                                                                         
    BIN8(10000000), BIN8(00100000), BIN8(00010000), // 10000 00000 10000 00001
    BIN8(10000000), BIN8(00010000), BIN8(00110000), // 10000 00000 01000 00011
    BIN8(10000000), BIN8(00010000), BIN8(01010000), // 10000 00000 01000 00101
    BIN8(10000000), BIN8(00001000), BIN8(10010000), // 10000 00000 00100 01001
    BIN8(10000000), BIN8(00000100), BIN8(10010000), // 10000 00000 00010 01001
    BIN8(10000000), BIN8(00000011), BIN8(00010000), // 10000 00000 00001 10001
    BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    BIN8(11111111), BIN8(11111111), BIN8(11110000), // 11111 11111 11111 11111

};

А вот сама хитромудрая функция по выводу буфера на экран:
/**
 * Отобразить экранный буфер
 */
void CLCD::Draw( uint8_t Buffer[], uint8_t Row, uint8_t Col ){
    
    // Заглушка, если драйвер не выбран
    if ( Driver == LCD_DRIVER_NONE ) return;
    
    // Шаг 1. Загружаем буфер в пользовательские символы
    
    //   Buffer[0]       Buffer[1]       Buffer[2]
    //BIN8(11111111), BIN8(11111111), BIN8(11110000), // 11111 11111 11111 11111 

    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001  _ _
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001 |   |
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001 
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001 
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001 
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001

    //  Buffer[24]      Buffer[25]      Buffer[26]
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001

    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001 |_ _|
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(10000000), BIN8(00000000), BIN8(00010000), // 10000 00000 00000 00001
    //BIN8(11111111), BIN8(11111111), BIN8(11110000), // 11111 11111 11111 11111
    
    uint8_t Data = 0, CharNum;
    
    // Сохраняем текущую позицию курсора
    uint8_t saveDDRAMAddr = ReadAddress();
    
    for ( uint8_t j = 0; j < 8; j++ ) {
    
        // multiply the character index by 8
        // each character occupies 8 bytes
        CharNum = ( j << 3 );

        // copy the 8 bytes into CG (character generator) RAM
        for ( uint8_t i = 0; i < 8; i++ ) {

            // set CG RAM address
            WriteData( TYPE_COMMAND, ( 1 << LCD_HD44780_CMD_CGRAM ) | ( CharNum + i ) );
            
            switch (j) {
            
                case 0: {
                    Data = Buffer[ 3 * i ] >> 3;
                    break;
                }

                case 4: {
                    Data = Buffer[ 24 + 3 * i ] >> 3;
                    break;
                }
                                
                case 2: {
                    Data = ( Buffer[ 1 + 3 * i ] & BIN8(00111110) ) >> 1;
                    break;
                }
                
                case 6: {
                    Data = ( Buffer[ 25 + 3 * i ] & BIN8(00111110) ) >> 1;
                    break;
                }
                
                case 1: {
                    Data = ( Buffer[ 3 * i ] & BIN8(00000111) ) << 2;
                    Data += Buffer[ 3 * i + 1 ] >> 6;
                    
                    break;
                }

                case 5: {
                    Data = ( Buffer[ 24 + 3 * i ] & BIN8(00000111) ) << 2;
                    Data += Buffer[ 24 + 3 * i + 1 ] >> 6;

                    break;
                }

                case 3: {
                    Data = ( Buffer[ 3 * i + 1 ] & BIN8(00000001) ) << 4;
                    Data += Buffer[ 3 * i + 2 ] >> 4;

                    break;
                }
                
                case 7: {
                    Data = ( Buffer[ 24 + 3 * i + 1 ] & BIN8(00000001) ) << 4;
                    Data += Buffer[ 24 + 3 * i + 2 ] >> 4;

                    break;
                }

            }
            
            WriteData( TYPE_DATA, Data );                
            
        }
        
    }
    
    // Шаг 2. Отображаем их на экране
    for ( uint8_t i = 0; i < 4; i++ ) { 
        
        PutChar( i, Row, Col + i );
        PutChar( i + 4, Row + 1, Col + i );
    }    
    
    // Восстанавливаем позицию курсора
    WriteData( TYPE_COMMAND, ( 1 << LCD_HD44780_CMD_DDRAM ) | saveDDRAMAddr );
    
}

Все исходники к проекту в одном месте: mysvn.ru/schoolbell/pbiidemo/
Ревизия для этой демонстрации: 15.

Чтобы что-то нарисовать, нужно выделить буфер в ОЗУ размером 48 байт и вызвать метод CLCD::Draw(). Например, так:
void TFormDisplay::FormPaint(){

    CLCD::Draw( Buffer, 0, 12 );
};

Исходник функции вывода тут: LCD.cpp
Как ей пользоваться тут: FormDisplay.cpp
  • +2
  • 11 марта 2012, 08:30
  • uni

Комментарии (11)

RSS свернуть / развернуть
а у тебя повреждения мозгов не произошло? а то я тут в 6 утра смотрю и как бы уже
0
Не спится. Вчера вечером продумал в уме идею и реализацию, но спать хотел жуть. Пришлось уснуть, а утром как проснулся — сразу написал.

Я хочу эту идею использовать как небольшую часть в будущём генераторе на основе Pinboard II. Есть одна такая очень хорошая статья, которую я решил повторить на PB2. Всё есть, только жаль, что DI нас ограничил 16 уровнями, а мне лень доделывать до 256 (8 выводов). Но софт-то будет всё равно как в статье: DDS V2.0 signal generator

Так вот, я приделаю на дисплей вывод маленького графического экранчика, где будет показан сэмпл (период) генерируемого сигнала. Там код не сложный, только я хочу как всегда, чтобы компилировалось одновременно в IAR C++ и AVG GCC, а там асм-вставки. Вот я и думаю как лучше поступить: асм вставку для двух вариантов или два асм-файла под каждый компилятор? Второй вариант мне почему-то нравится больше.
0
Очень интересно! утащил. )
0
странно что то с ссылкой что ты дал в комменте, появляется на секунду сайт и сразу белый экран… антивирусы что ли у меня чудят…
0
Не, там реклама пытается отправить на другую страницу:)
0
а так как прочесть то… обратно то не переходит…
0
У меня adblock вполне справляется.
0
у меня тоже аддблок и как видишь не справился )_)))
0
Нужно только добавить в черный список еще и api.clickcha.com
0
спасибо, добавление в черный список помогло.
0
Да, я заметил, раньше такого не было. Там уже есть кое-что про DDS v. 3.0. Автор разводит аналоговую часть и показывает её симуляцию:
Suggest features to DDS V3.0 signal generator
Modeling of analog part for DDS3 signal generator

Можно упеть нажать Стоп при загрузке страницы и перехода не произойдёт. У меня получалось. Вторую версию этой штуковины вполне можно реализовать на PBII, там всё есть, только сигнал на выходе будет из 16 уровней, т.к. матрица из резисторов на плате только для 4-х выходов разведена. В остальном там ничего особо сложного. Полезная бы вещь была, не просто лампочками помигать, а цифровой синтез не помню уже от скольки, но до 65 кГц примерно. Разные вшитые виды периодических сигналов.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.