Напишите повторно используемую низкоуровневую графическую библиотеку для встроенного устройства на языке ansi C.

Мне нужно написать низкоуровневый драйвер для управления tft-дисплеем встроенного устройства. Устройство питается от PIC24, 64 КБ оперативной памяти и около 128 КБ программной памяти.

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

Графическая библиотека использует драйвер для доступа к дисплею, но технология отображения может измениться, поэтому драйвер должен быть легко перереализуемым.

Как лучше всего написать повторно используемый код в таком сценарии?

 -----------------          ---------------       
|                 |        |               |
|                 |        |               |
|    GFX_LIB      | =====> |    DRIVER     | ====> DISPLAY
|                 |        |               |
|                 |        |               |
 -----------------          -----/----\----
                                /      \
                               /        \
                         ----------   ----------
                        |          | |          |
                        | TYPE A   | |  TYPE B  |
                        |          | |          |
                         ----------   ----------

Подробнее

Это фрагмент кода моей библиотеки gfx.

#include "Graphics.h"

void gfx_Init(uint16_t width, uint16_t height, uint8_t rotation){
    gfx_displayWidth=width;
    gfx_displayHeight=height;
    gfx_rotation=rotation;  
    displayDriverInit();
}

void gfx_setPixel(uint16_t x, uint16_t y, uint32_t color){
    displayDriverSendCommand(CHANGE_COORDINATE);
    displayDriverSendData(x);
    displayDriverSendData(y);
    displayDriverSendCommand(SET_COLOR);
    displayDriverSendData(color);
}

Это гипотетическая реализация моей графической библиотеки.

Теперь, если я сменю драйвер, я буду очень рад, если смогу повторно использовать свою библиотеку gfx и переписать только подпрограммы драйвера дисплея. Каков наилучший способ добиться этого?

Спасибо.


person blow    schedule 30.06.2012    source источник
comment
привет, это для встроенного устройства с picmicro   -  person blow    schedule 01.07.2012


Ответы (4)


Это немного зависит от того, какую функциональность будут предлагать ваши драйверы.

Минимальный API можно объявить следующим образом:

typedef void* gfx;
typedef struct init_options {
  int display_width, display_height;
  //..etc..
};

gfx* gfx_init( init_options* opts );
void gfx_free( gfx* gfx );

// blit something onto sceeen
void gfx_blit( gfx* gfx, void* buffer, int buf_w, int buf_h, int trg_x, int trg_y, int trg_w, int trg_h );

// if you have double buffering (probably a good idea)
void gfx_swap( gfx* gfx );

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

Выбор драйвера и реализация этого API могут быть выполнены путем простого связывания нужной библиотеки (где каждая библиотека содержит фактический драйвер, содержащий фактический код для передачи данных и т. д.).

ИЗМЕНИТЬ

Чтобы иметь некоторый динамически заменяемый код, ваш драйвер может быть структурой с указателями функций на фактическую реализацию кода, специфичного для драйвера:

// common driver struct, used by gfx api
typedef struct driver {
    void (*init)( driver *driver, init_options* );
    void (*setpixel)( driver *driver, int x, int y, color color );
    //...
};

// driver constructor
driver* create_foo_driver() {
    driver* d = malloc( sizeof(driver) );
    memset(d,0,sizeof(driver));
    d->init = foo_init;
    d->setpixel = foo_setpixel;
    return d;
}

// some driver-specific code ...
void foo_setpixel( driver *driver, int x, int y, color color ) {
    // actual implementation
}

// API code calling driver code
void gfx_setpixel( gfx* gfx, int x, int y, color color ) {
   driver* driver = ((gfx_impl)gfx)->driver; // .. just an example
   driver->setpixel( driver, x, y, color );
}
person Frunsi    schedule 30.06.2012
comment
Да! да, это очень похоже на мою библиотеку gfx, теперь возникает вопрос: как лучше всего внедрить мой tft-драйвер для отправки команды и данных для отображения и оставить открытой возможность того, что технология отображения может измениться, и я должен повторно реализовать драйвер? Мне не нужно (и я не хочу) переопределять всю библиотеку gfx для каждого дисплея, который я использую. - person blow; 01.07.2012
comment
@blow: предоставьте более подробную информацию, пожалуйста - person Frunsi; 01.07.2012

Зачем изобретать велосипед? Используйте графическую библиотеку GD, чтобы создать изображение в буфере изображений дисплея. Или создайте изображение за пределами буфера изображения дисплея, а затем скопируйте данные пикселей после завершения рендеринга.

Обратите внимание, что GD обычно используется для создания файлов изображений (которые затем загружаются браузером), но код рендеринга независим.

person Aaron Digulla    schedule 30.06.2012
comment
Мне нужно что-то вроде графического класса java, но для встроенного устройства с низкой производительностью. И я знаю, как написать свою примитивную функцию gfx, мне нужен только совет, как построить все для повторного использования... я новичок в C. - person blow; 01.07.2012
comment
Взгляните на исходный код GD; это решает все ваши проблемы. Возможно, вам придется извлечь несколько файлов и удалить остальные, но это будет быстрее, чем писать все с нуля. - person Aaron Digulla; 01.07.2012

В зависимости от того, сколько памяти вы можете выделить на своей платформе, вы можете использовать Cairo, структура которого точно такая же, как вы нарисовали в своем ASCII арт. Он также реализован на языке C.

person mensi    schedule 30.06.2012
comment
привет, у меня всего 64 КБ оперативной памяти и около 128 КБ программной памяти, поэтому я могу написать только простой драйвер для примитивной графической функции. - person blow; 01.07.2012
comment
вы должны добавить эту информацию к своему вопросу, низкая спецификация, графика низкого уровня - это другой котелок с рыбой - person IanNorton; 01.07.2012

Любой, кто погуглит здесь, должен посмотреть библиотеку Adafruit GFX, а затем посмотреть, как их библиотеки для конкретных графические драйверы реализуют это. Мой опыт связан с их драйвером ST7735 (который я портировал для работы с chipKIT's PIC32 и теперь получает помощь от опытных разработчиков chipKIT). Прекрасный пример графической среды C++/OOP, которую могут реализовать драйверы для определенного оборудования.

Я удивлен, что этот вопрос не был закрыт из-за того, что он не по теме, как и любой другой вопрос типа «как я могу это сделать» в последнее время.

person Chris K    schedule 06.09.2013