フレームバッファ設定
このセクションでは、以下のいずれかのフレームバッファ設定を使用するTouchGFX HALを生成するためのTouchGFX Generator の設定方法について説明します。
- シングル
- ダブル
- 部分
シングル・フレームバッファ
バッファの設定として[Single Buffer] を選択すると、コンパイラが内蔵RAMにフレームバッファ用メモリを割り当てることができますが、このバッファ用に特定の場所を選択することも可能です。
By Allocation
[By Allocation]n を選択すると、TouchGFX Generatorは、アプリケーションの寸法とビット深さに基づいた配列を割り当てます。
この配列をフレームバッファとして使用するようにHALを設定するコードが生成されます。
TouchGFXGeneratedHAL.cpp
namespace {
// Use the section "TouchGFX_Framebuffer" in the linker script
// to specify the placement of the buffer
LOCATION_PRAGMA("TouchGFX_Framebuffer")
uint32_t frameBuf[(480 * 272 * 2 + 3) / 4] LOCATION_ATTRIBUTE("TouchGFX_Framebuffer");
}
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();
setFrameBufferStartAddresses((void*)frameBuf, (void*)0, (void*)0);
}
By Address
フレームバッファの場所として[By Address] [By Address]</525>を選択すると、TouchGFX GeneratorはHAL初期化時に指定された開始アドレスを使用します。
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();
setFrameBufferStartAddresses((void*)0xC0000000, (void*)0, (void*)0);
}
ダブル・フレームバッファ
ダブル・フレームバッファ構成の場合、選択したフレームバッファ設定とディスプレイ・インタフェースに応じて、TouchGFX GeneratorによりフレームバッファをスワップするコードがHAL内に生成されます。 このフレームバッファ位置へのメモリ・インタフェースは、メイン・イベント・ループでTouchGFXエンジンによって使用されます。
By Address
[By Address] を選択すると、TouchGFX GeneratorはHAL初期化時に指定された2つの開始アドレスを使用します。
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();
setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC003FC00, (void*)0);
}
Tip
By Allocation
[By Allocation] を選択すると、TouchGFX Generatorは、シングル・フレームバッファの場合とまったく同様に、アプリケーションの寸法とビット深さに基づいた配列を、サイズだけ2倍にして割り当てます。
TouchGFXGeneratedHAL.cpp
namespace {
// Use the section "TouchGFX_Framebuffer" in the linker to specify the placement of the buffer
LOCATION_PRAGMA("TouchGFX_Framebuffer")
uint32_t frameBuf[(480 * 272 * 2 + 3) / 4 * 2] LOCATION_ATTRIBUTE("TouchGFX_Framebuffer");
}
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();
setFrameBufferStartAddresses((void*)frameBuf, (void*)(frameBuf + sizeof(frameBuf)/(sizeof(uint32_t)*2)), (void*)0);
}
パーシャル・フレームバッファ
[Partial Buffer] の設定を選択する場合、フレームバッファとして使用するブロックの数とそれぞれのサイズを開発者が選択できます。 この設定は、フレームバッファが配置される外部メモリへのポインタを提供したり、内蔵メモリに固定サイズの配列を割り当てたりする方法とは異なり、TouchGFXのレームバッファ・アロケータと呼ばれる機能を使用します。
フレームバッファの概念の概要については、「フレームバッファ」の記事を参照してください。
Tip
パーシャル・フレームバッファ設定が採用されるのは、通常、TFTコントローラを搭載せず、内蔵RAM容量が小さい低コストのマイクロコントローラの場合に限られるため、フレームバッファの内容をディスプレイに転送する機能は開発者が実装するものと想定されています。 TFTコントローラを搭載していないマイクロコントローラでシリアル・ディスプレイなどにピクセルを転送する方法については、FMC / SPIシナリオを参照してください。
パーシャル・フレームバッファ設定を使用する場合、TouchGFXと同期するには、次の2つの関数を実装する必要があります。 以下に示すコードは、CubeMXによってTouchGFX/target/generated/TouchGFXGeneratedHAL.cpp
内に生成されたもので、開発者からTouchGFXエンジンへのインタフェースを定義しています。
TouchGFXGeneratedHAL.cpp
/* ******************************************************
* Functions required by Partial Frame Buffer Strategy
* ******************************************************
*
* * uint8_t isTransmittingData() must return whether or not data is currently being transmitted, over e.g. SPI.
* * void transmitFrameBufferBlock(uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h) will be called
* when the framework wants to send a block. The user must then transfer
* the data represented by the arguments.
*
* A user must call touchgfx::startNewTransfer(); once transmitFrameBufferBlock() has succesfully sent a block.
* E.g. if using DMA to transfer the block, this could be called in the "Transfer Completed" interrupt handler.
*
*/
extern "C" void transmitFrameBufferBlock(uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
extern "C" uint8_t isTransmittingData();
以下の関数も、CubeMXによってTouchGFX/target/generated/TouchGFXGeneratedHAL.cpp
内の、読出し専用クラスTouchGFXGeneratedHAL
内に生成されます。
Note
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
HAL::flushFrameBuffer(rect);
// Once flushFrameBuffer() is called by the framework a block is ready for transfer
// Mark it ready for transfer and transmit it if user defined method
// isTransmittingData() does not return false
// If data is not being transmitted, transfer the data with user defined method
// transmitFrameBufferBlock().
frameBufferAllocator->markBlockReadyForTransfer();
if (!isTransmittingData())
{
touchgfx::Rect r;
const uint8_t* pixels = frameBufferAllocator->getBlockForTransfer(r);
transmitFrameBufferBlock((uint8_t*)pixels, r.x, r.y, r.width, r.height);
}
}