News:

Welcome to the Bridgetek Community!

Please read our Welcome Note

Technical Support enquires
please contact the team
@ Bridgetek Support

Please refer to our website for detailed information on all our products - Bridgetek - Bridging Technology

Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - kumaichi

#1
Hello,

I've just ran into the strangest issue and I'm not exactly sure where to even start.  I have two projects, they both use QSPI to write to the BT817, not sure that matters but want to give as much information as possible.  One project uses FreeRTOS and the other one doesn't.  When the FreeRTOS version runs through the initialization,  I try to set the REG_PWM_DUTY to 25 and it crashes everything, the QSPI command returns successfully but then it crashes the debugger.  I've never ran into anything like this.  Has anyone experienced this before?  It's only on the setting of, REG_PWM_DUTY which calls TFT_qspi_write8(...), other commands call the same method with no issues.  Below is my initialization code as well as my write 8 method.

The non-freeRTOS project runs fine all day long using the exact same code.  Only difference is it uses a timer to update the display running off the main thread.

Any insight would be greatly appreciated.

Kindest regards.

Initialization:
void TFT_qspi_init()
{
tft_active = 0;

HAL_GPIO_WritePin(MCU_DISP_RST_GPIO_Port, MCU_DISP_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(40); /* minimum time for power-down is 5ms */
HAL_GPIO_WritePin(MCU_DISP_RST_GPIO_Port, MCU_DISP_RST_Pin, GPIO_PIN_SET);
HAL_Delay(40); /* minimum time to allow from rising PD_N to first access is 20ms */

//Explicitly put SPI in single mode
TFT_write8(REG_SPI_WIDTH, 0x00);
//External Crystal
TFT_sendCmd(CMD_CLKEXT, 0x00);
HAL_Delay(100);
/* set clock to 72 MHz */
TFT_sendCmd(CMD_CLKSEL, 0x46);
//Reset the device
TFT_sendCmd(EVE_RST_PULSE, 0x00);
/* give EVE time to power up */
HAL_Delay(40);
/* start EVE */
TFT_sendCmd(CMD_ACTIVE, 0x00);
HAL_Delay(300);
/* tell EVE that we changed the frequency to 72MHz */
TFT_write32(REG_FREQUENCY, 72000000);
/* read the frequency to verify */
if (TFT_read32(REG_FREQUENCY) != 72000000)
Error_Handler();

TFT_write8(REG_TRIM, 25);

/* read the ID */
while (TFT_readId(REG_ID) != 0x7c)
{
};

/* read REG_CPURESET to confirm 0 is returned */
uint8_t engine_status;

/* Read REG_CPURESET to check if engines are ready.
Bit 0 for coprocessor engine,
Bit 1 for touch engine,
Bit 2 for audio engine.
*/
engine_status = TFT_read8(REG_CPURESET);
while (engine_status != 0x00)
{
engine_status = TFT_read8(REG_CPURESET);
HAL_Delay(100);
}

TFT_write16(REG_PWM_HZ, 4000);
TFT_write8(REG_PWM_DUTY, 0);

/* switch to QSPI */
TFT_write8(REG_SPI_WIDTH, 0x02);
while (TFT_qspi_read8(REG_SPI_WIDTH) != 0x02)
{
TFT_write8(REG_SPI_WIDTH, 0x02);
};

/* Check if everything is okay */
if (TFT_qspi_read16(REG_CMD_READ) == 0xFFF)
{
uint8_t Offset = 0;
uint8_t ErrChar;
uint8_t result[128 + 1]; // Buffer to hold the full string (including null terminator)
int result_index = 0;
do
{
// Get the error character and display it
ErrChar = TFT_qspi_read8(EVE_RAM_ERR_REPORT + Offset);
// Only append valid characters (non-null)
if (ErrChar != 0 && result_index < 128)
{
result[result_index++] = ErrChar;
}

Offset++;
}
while ((ErrChar != 0) && (Offset < 128)); // when the last stuffed character was null, we are done

// Null-terminate the string
result[result_index] = '\0';

// Now the full string is in 'result', which you can use or print
printf("Captured string: %s\n", result);
sprintf((char*) message, "Captured string: %s\r\n", result);
CDC_Transmit_FS((uint8_t*) message, strlen((char*) message));
}

TFT_qspi_write16(REG_HSIZE, DispWidth); /*   800 */
TFT_qspi_write16(REG_VSIZE, DispHeight); /*   480 */
TFT_qspi_write16(REG_HCYCLE, DispHCycle); /*   816 */
TFT_qspi_write16(REG_HOFFSET, DispHOffset); /*     8 */
TFT_qspi_write16(REG_HSYNC0, DispHSync0); /*     0 */
TFT_qspi_write16(REG_HSYNC1, DispHSync1); /*     4 */
TFT_qspi_write16(REG_VCYCLE, DispVCycle); /*   496 */
TFT_qspi_write16(REG_VOFFSET, DispVOffset); /*     8 */
TFT_qspi_write16(REG_VSYNC0, DispVSync0); /*     0 */
TFT_qspi_write16(REG_VSYNC1, DispVSync1); /*     4 */
TFT_qspi_write8(REG_SWIZZLE, DispSwizzle); /*     0 */
TFT_qspi_write8(REG_PCLK_POL, DispPCLKPol); /*     1 */
TFT_qspi_write16(REG_CSPREAD, DispCSpread); /*     0 */
TFT_qspi_write16(REG_DITHER, DispDither); /*     0 */
TFT_qspi_write16(REG_PCLK_FREQ, DispPLCLKFREQ); /* 0xD14 */
TFT_qspi_write8(REG_PCLK_2X, DispPCLK2x); /*     0 */

/* disable Audio for now */
TFT_qspi_write8(REG_VOL_PB, 0U); /* turn recorded audio volume down, reset-default is 0xff */
TFT_qspi_write8(REG_VOL_SOUND, 0U); /* turn synthesizer volume down, reset-default is 0xff */
TFT_qspi_write16(REG_SOUND, EVE_MUTE); /* set synthesizer to mute */

uint32_t initCommands[] =
{
CMD_DLSTART,
DL_CLEAR_COLOR_RGB | WHITE,
DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG, /* clear the screen - this and the previous prevent artifacts between lists, Attributes are the color, stencil and tag buffers */
DL_DISPLAY,
CMD_SWAP // display, in this case nothing
};

TFT_qspi_cmd_burst(initCommands,
sizeof(initCommands) / sizeof(initCommands[0]));

//while (TFT_busy() != E_OK){};
TFT_qspi_WaitCmdfifo_empty();

if (TFT_qspi_read16(REG_CMD_READ) == 0xFFF)
{
uint8_t Offset = 0;
uint8_t ErrChar;
uint8_t result[128 + 1]; // Buffer to hold the full string (including null terminator)
int result_index = 0;
do
{
// Get the error character and display it
ErrChar = TFT_qspi_read8(EVE_RAM_ERR_REPORT + Offset);
// Only append valid characters (non-null)
if (ErrChar != 0 && result_index < 128)
{
result[result_index++] = ErrChar;
}

Offset++;
}
while ((ErrChar != 0) && (Offset < 128)); // when the last stuffed character was null, we are done

// Null-terminate the string
result[result_index] = '\0';

// Now the full string is in 'result', which you can use or print
printf("Captured string: %s\n", result);
sprintf((char*) message, "Captured string: %s\r\n", result);
CDC_Transmit_FS((uint8_t*) message, strlen((char*) message));
}

TFT_qspi_cmd_setrotate(0);

TFT_qspi_write16(REG_GPIOX_DIR, 0xFFFF);
TFT_qspi_write16(REG_GPIOX, 0xFFFF);

/* after this display is visible on the LCD */
TFT_qspi_write8(REG_PCLK, DispPCLK);

//while (TFT_busy() != E_OK){};
TFT_qspi_WaitCmdfifo_empty();

/* If the status of the flash is 0 (INIT) Attach it */
while (EVE_FLASH_STATUS_DETACHED == TFT_qspi_read8(REG_FLASH_STATUS))
{
TFT_qspi_dl_cmd(CMD_FLASHATTACH);
}

/* Initialize the onboard flash and put in FAST mode
* Need to check the return value and not proceed if
* there is an error so we can read in the Fonts
*/
if (TFT_init_flash() == E_OK)
{
/* Read the image from the flash */
uint32_t flashCommands[] =
{
CMD_FLASHREAD, (uint32_t) MEM_FONT34, (uint32_t) 198592, (uint32_t) 280 + 40,
CMD_FLASHREAD, (uint32_t) CAR_IMAGE_HORIZONTAL, (uint32_t) 198912, (uint32_t) 92000 + 32
};

TFT_qspi_cmd_burst(flashCommands, sizeof(flashCommands) / sizeof(flashCommands[0]));

while (TFT_busy() != E_OK)
{
};

TFT_qspi_WaitCmdfifo_empty();
}

TFT_qspi_dl_cmd(CMD_DLSTART);
TFT_qspi_dl_cmd(DL_CLEAR_COLOR_RGB | WHITE);
TFT_qspi_dl_cmd(DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG);
TFT_qspi_dl_cmd(DL_BEGIN);

TFT_qspi_dl_cmd(COLOR_RGB(120, 6, 6));

TFT_qspi_cmd_setfont2(13, MEM_FONT34, 0); /* assign bitmap handle to a custom font */
TFT_qspi_cmd_text((DispWidth / 2), (DispHeight / 5) - 15, 13, EVE_OPT_CENTERX, "Please wait...");

TFT_qspi_dl_cmd(COLOR_RGB(20, 20, 130));

TFT_qspi_cmd_spinner(DispWidth / 2, DispHeight / 2, 0, 0);

//TFT_qspi_write8(REG_PWM_DUTY, 25);

HAL_Delay(2000);

TFT_qspi_cmd_stop();

TFT_qspi_WaitCmdfifo_empty();

/* set the precision of VERTEX2F coordinates */
#if defined (IPS_70) || (IPS_101)
      /* VERTEX2F range: -2048 to 2047 */
      //TFT_qspi_dl_cmd(VERTEX_FORMAT(3));
      pixel_precision = 8;
#else
/* use default VERTEX_FORMAT(3) with VERTEX2F range: -1024 to 1023 */
pixel_precision = 16;
#endif

tft_active = 1;
}

Write 8 Method:
void TFT_qspi_write8(uint32_t const address, uint32_t const data)
{
QSPI_CommandTypeDef sCommand = {0};

// Set up the command structure
sCommand.InstructionMode   = QSPI_INSTRUCTION_4_LINES;    // Instruction sent over 1 line
sCommand.Instruction       = (uint8_t) (address >> 16U) | 0X80; //Get the first byte, should look like 0x30
sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;        // Address sent over 1 line
sCommand.AddressSize       = QSPI_ADDRESS_16_BITS;        // 16-bit address
sCommand.Address           = address & 0xFFFF;            // Mask off the first byte and keep the last two bytes
sCommand.DataMode          = QSPI_DATA_4_LINES;            // Data mode for receiving ID
sCommand.NbData            = 2;                          // Sending 2 bytes
sCommand.DummyCycles       = 0;                          // No dummy cycles
sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;      // Disable DDR mode
sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;    // Send instruction every command

// Send the command (instruction and address)
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
Error_Handler();

// Now write the data
uint8_t localData[2] = {(uint8_t) data & 0xFF,
(uint8_t) (data >> 8) & 0xFF};
if (HAL_QSPI_Transmit(&hqspi, localData, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
Error_Handler();

return;
}

FreeRTOS Task:
void StartDisplayTask(void *argument)
{
  /* USER CODE BEGIN StartDisplayTask */
  /* Infinite loop */
(void)argument;
const TickType_t period = pdMS_TO_TICKS(16); // ~60 Hz
TickType_t last = xTaskGetTickCount();
bool initialized = false;

for (;;)
{
if(!initialized)
{
initialized = true;

TFT_qspi_init();
}

//TFT_touch(); - Called from another task
TFT_display();

vTaskDelayUntil(&last, period);
}
  /* USER CODE END StartDisplayTask */
}
#2
Discussion - EVE / Not able to display font degree
August 26, 2025, 02:48:40 PM
Hello,

I modified a font, Reglo-Bold, adding a "degree" symbol but I'm unable to actually display it.  For some reason, depending on how I try to display it, it'll show up as a '0'.  I'm confident the symbol is there and in the correct position.  I viewed the images created by EVE Asset Builder v2.10.2 and it's there.

FontFolio Screenshot
You cannot view this attachment.

EVE Asset Builder Preview Last Screenshot
You cannot view this attachment.

EVE Asset Builder Font Index HTML Screenshot
You cannot view this attachment.

I've tried a bunch of different ways to display it:

snprintf(buf, sizeof buf, "%d " "\u00B0" "   F", temperature);
TFT_qspi_cmd_text(75, 120, 31, EVE_OPT_CENTERY, buf);

I'm not really sure what I'm doing wrong or maybe something like this isn't possible?

Any insight would be greatly appreciated.

Kindest regards.

#3
Hello,

I have my QSPI working perfect for my Riverdi 5" display, using the IPS-50 settings.  I switched over to my Riverdi 7" display, using the IPS-70 settings and I only get the DL-size text multiple times down the display.  I've attached photos of the 5" display and the 7" display.  I have flashed the same .bin file to both displays.

Is there anything special to consider when using the same code for both displays besides switching the IPS-X0 settings?

The DL sizes are different because after a few seconds my display connects to the Bluetooth module and updates the data on the screen, so the size isn't the issue.

Kindest regards.
#4
I'm stuck in an extremely painful situation where sometimes everything displays correctly when my device powers up and other times, actually most of the time, only the backlight seems to work.  I'm using Rudolph's library as well as the EVE library as a reference and can't seem to figure out what I'm missing.  I'm using qspi which I don't think is an issue because sometimes it works fine.

I have attached my init method, can anyone possibly see what could cause it to display intermittently?

Kindest regards.


void TFT_qspi_init()
{
    HAL_GPIO_WritePin(MCU_DISP_RST_GPIO_Port, MCU_DISP_RST_Pin, GPIO_PIN_RESET);
    HAL_Delay(21); /* minimum time for power-down is 5ms */
    HAL_GPIO_WritePin(MCU_DISP_RST_GPIO_Port, MCU_DISP_RST_Pin, GPIO_PIN_SET);
    HAL_Delay(21); /* minimum time to allow from rising PD_N to first access is 20ms */

    //Reset the device
    TFT_sendCmd(EVE_RST_PULSE, 0x00);
    HAL_Delay(21);

    //External Crystal
    TFT_sendCmd(CMD_CLKEXT, 0x00);
    HAL_Delay(100);
    /* set clock to 72 MHz */
    TFT_sendCmd(CMD_CLKSEL, 0x46);
    /* start EVE */
    TFT_sendCmd(CMD_ACTIVE, 0x00);
    /* give EVE time to power up */
    HAL_Delay(40);

    /* read the ID */
    uint8_t regId = TFT_readId(REG_ID);
    while(regId != 0x7c)
    regId = TFT_readId(REG_ID);

    /* ensure CPUreset register reads 0 signaling it's ready */
    uint8_t cpuState = TFT_read8(REG_CPURESET);
    while ( cpuState != 0x00)
cpuState = TFT_read8(REG_CPURESET);

    /* switch to QSPI */
    TFT_write8(REG_SPI_WIDTH, 0x02);
    if(TFT_qspi_read8(REG_SPI_WIDTH) != 0x02)
        Error_Handler();

    /* tell EVE that we changed the frequency to 72MHz */
    TFT_qspi_write32(REG_FREQUENCY, 72000000);
    /* read the frequency to verify */
    if(TFT_qspi_read32(REG_FREQUENCY) != 72000000)
    Error_Handler();

    TFT_qspi_write8(REG_TRIM, 25);
    TFT_qspi_write16(REG_HSIZE, DispWidth); /*   800 */
    TFT_qspi_write16(REG_VSIZE, DispHeight); /*   480 */
    TFT_qspi_write16(REG_HCYCLE, DispHCycle); /*   816 */
    TFT_qspi_write16(REG_HOFFSET, DispHOffset); /*     8 */
    TFT_qspi_write16(REG_HSYNC0, DispHSync0); /*     0 */
    TFT_qspi_write16(REG_HSYNC1, DispHSync1); /*     4 */
    TFT_qspi_write16(REG_VCYCLE, DispVCycle); /*   496 */
    TFT_qspi_write16(REG_VOFFSET, DispVOffset); /*     8 */
    TFT_qspi_write16(REG_VSYNC0, DispVSync0); /*     0 */
    TFT_qspi_write16(REG_VSYNC1, DispVSync1); /*     4 */
    TFT_qspi_write8(REG_PCLK, DispPCLK); /*     1 */
    TFT_qspi_write8(REG_SWIZZLE, DispSwizzle); /*     0 */
    TFT_qspi_write8(REG_PCLK_POL, DispPCLKPol); /*     1 */
    TFT_qspi_write16(REG_CSPREAD, DispCSpread); /*     0 */
    TFT_qspi_write16(REG_DITHER, DispDither); /*     0 */
    TFT_qspi_write16(REG_PCLK_FREQ, DispPLCLKFREQ); /* 0xD14 */
    TFT_qspi_write8(REG_PCLK_2X, DispPCLK2x); /*     0 */

    TFT_qspi_write16(REG_PWM_HZ, 4000);
    TFT_qspi_write8(REG_PWM_DUTY, 128);

    TFT_qspi_write16(REG_GPIOX_DIR, 0xFFFF);
    TFT_qspi_write16(REG_GPIOX, 0xFFFF);

    /* turn off back light */
    TFT_qspi_write8(REG_PWM_DUTY, 0);

    while(TFT_busy()){};

    TFT_qspi_cmd(REG_CMDB_WRITE, CMD_SETROTATE, 1);

    /* If the status of the flash is 0 (INIT) Attach it */
    if (TFT_qspi_read8(REG_FLASH_STATUS) == 0x00) {
        uint32_t flashAttachCommand[] = {CMD_FLASHATTACH};

TFT_qspi_display(flashAttachCommand, 1);
    }

    /* Initialize the onboard flash and put in FAST mode
* Need to check the return value and not proceed if
* there is an error.
    */
    if(TFT_init_flash() != E_OK)
Error_Handler();

    /* turn on backlight pwm to 25% for any other module */
    TFT_qspi_write8(REG_PWM_DUTY, 0x25);
    uint32_t commands[] = {
CMD_DLSTART, /* start the display list */
DL_CLEAR_COLOR_RGB | 0x00000000, /* set the default clear color to white */
DL_CLEAR | CLR_COL | CLR_STN | CLR_TAG, /* clear the screen - this and the previous prevent artifacts between lists, Attributes are the color, stencil and tag buffers */
DL_BEGIN | EVE_BITMAPS,
COLOR_RGB(255, 255, 255),
VERTEX2II(DispWidth / 2 , (DispHeight / 2) - 31, 31, 'T'), // ASCII T in font 31
VERTEX2II((DispWidth / 2 ) + 26, (DispHeight / 2) - 31, 31, 'E'), // ASCII E in font 31
VERTEX2II((DispWidth / 2 ) + 50, (DispHeight / 2) - 31, 31, 'X'), // ASCII X in font 31
VERTEX2II((DispWidth / 2 ) + 76, (DispHeight / 2) - 31, 31, 'T'),
DL_END,
COLOR_RGB(160, 22, 22), // change color to red
POINT_SIZE(520), // set point size to 20 pixels in radius
DL_BEGIN | EVE_POINTS, // start drawing points
VERTEX2II((DispWidth / 2 ) - 40, (DispHeight / 2) - 10, 0, 0), // red point
DL_END,
DL_DISPLAY,
CMD_SWAP// display the image
};

TFT_qspi_display(commands, sizeof(commands) / sizeof(commands[0]));

/* turn on backlight pwm to 25% for any other module */
TFT_qspi_write8(REG_PWM_DUTY, 0x25);

HAL_Delay(2000);
}
#5
Discussion - EVE / Using QUAD SPI (qspi)
September 04, 2024, 04:46:18 PM
Hello,

I currently have Rudolphs library and the Riverdi_EVE library running via SPI.  All that is working just fine.  I'm using custom hardware with an STM32WB55REV6 on it and the QUADSPI bus is what's connected to the Riverdi display.  I tried using the QUADSPI in single mode but have failed miserably so thought I'd try using QUAD SPI instead.

Looking at the datasheet, 4.1 Quad SPI Host Interface, I believe I need to write 0x04 to the REG_SPI_WIDTH.  At which point in the initialization process, documented in the BRT_AN_033_BT81X-Series-Programming-Guide, section 2.4 Initialization Sequence during Boot Up?  Should REG_SPI_WIDTH be set after setting everything up or is it the first thing that should be set after the RST/PD sequence?

Any other things that might be helpful getting it up and running via QUAD SPI?

Any insight would be greatly appreciated.

#6
Hello All,

New here, I've been writing Windows based software for longer than I'd like to admit and I'm having the hardest time trying to integrate any of the EVE libraries out on GitHub into an STM32CubeIDE project.  I've tried Riverdi (that's the display I'm trying to get working), Rudolph Riedel's and MatrixOrbital's libraries without much luck.  The steps I've tried:

1. Create a new project in Stm32CubeIDE using the STM32Wb55RG Nucleo board (I'm creating a custom board based off the MCU so bought the Nucleo for prototyping).
2. Dragged the cooresponding .c & .h files from the perspective library into the STM32CubeIDE file tree, .c to Src folder and .h to Inc folder.  Trying to keep it simple instead of creating specific folders like in the libraries for now to try and get something to compile.
3. Copied the contents of the host_layer/Stm32/platform.h and platform.c and copied into my main.h and main.c files.

Then I spend a few hours trying to get it to build.  Fail miserably and moved onto the next library trying the same steps (I am the definition of insanity, lol).  Can anyone provide some guidance to getting one of the libraries to build in an STM32CubeIDE project?

I am very new to hardware and STM32CubeIDE, which is why I think I'm having so much difficulty.

Kindest regards