//***************************************************************************** // //! @file am_devices_mspi_rm67162.c //! //! @brief Generic Raydium TFT display driver. // //***************************************************************************** //***************************************************************************** // // Copyright (c) 2020, Ambiq Micro // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // Third party software included in this distribution is subject to the // additional license terms as defined in the /docs/licenses directory. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // This is part of revision 2.4.2 of the AmbiqSuite Development Package. // //***************************************************************************** #include #include "am_mcu_apollo.h" #include "am_devices_mspi_rm67162.h" #include "am_bsp.h" #include "am_util_delay.h" #include "am_util.h" //***************************************************************************** // // Global variables. // //***************************************************************************** #define BYTE_NUM_PER_WRITE 65535 //#define BYTE_NUM_PER_WRITE AM_HAL_MSPI_MAX_TRANS_SIZE #define AM_DEVICES_MSPI_TIMEOUT 1000000 static struct { uint32_t row_start; uint32_t row_end; uint32_t col_start; uint32_t col_end; } gs_display_info; static am_devices_rm67162_graphic_conf_t g_sGraphic_conf = { .bus_mode = AM_DEVICES_RM67162_SPI_WRAM, .color_mode = AM_DEVICES_RM67162_COLOR_MODE_8BIT, .scan_mode = AM_DEVICES_RM67162_SCAN_MODE_0, .max_row = 400, //390, .max_col = 400, // 390, .row_offset = 0, .col_offset = 0 // 6 // .col_offset = 100 }; // Display MSPI configuration static am_hal_mspi_dev_config_t SerialDisplayMSPICfg = { .ui8TurnAround = 1, .eAddrCfg = AM_HAL_MSPI_ADDR_3_BYTE, .eInstrCfg = AM_HAL_MSPI_INSTR_1_BYTE, .ui8ReadInstr = AM_DEVICES_RM67162_MEMORY_READ, .ui8WriteInstr = AM_DEVICES_RM67162_MEMORY_WRITE_CONTINUE, // AM_DEVICES_RM67162_MEMORY_WRITE_CONTINUE, .eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0, .ui8WriteLatency = 0, .eSpiMode = AM_HAL_MSPI_SPI_MODE_0, .eClockFreq = AM_HAL_MSPI_CLK_48MHZ, .bEnWriteLatency = false, .bSendAddr = false, .bSendInstr = true, .bSeparateIO = false, .bTurnaround = false, .bEmulateDDR = false, .ui16DMATimeLimit = 0, .eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE, .ui32TCBSize = 0, .pTCB = 0, .scramblingStartAddr = 0, .scramblingEndAddr = 0, }; typedef struct { uint32_t ui32Module; void *pMspiHandle; bool bOccupied; } am_devices_mspi_rm67162_t; am_devices_mspi_rm67162_t gAmRm67162[AM_DEVICES_MSPI_RM67162_MAX_DEVICE_NUM]; void pfnMSPI_RM67162_Callback(void *pCallbackCtxt, uint32_t status) { // Set the DMA complete flag. *(volatile bool *)pCallbackCtxt = true; } //***************************************************************************** // // Generic Command Write function. // //***************************************************************************** uint32_t am_devices_rm67162_command_write(void *pHandle, uint32_t ui32Instr, uint8_t *pData, uint32_t ui32NumBytes) { am_hal_mspi_pio_transfer_t Transaction; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // Create the individual write transaction. Transaction.ui32NumBytes = ui32NumBytes; Transaction.bScrambling = false; Transaction.bDCX = true; Transaction.eDirection = AM_HAL_MSPI_TX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = true; Transaction.ui16DeviceInstr = ui32Instr; Transaction.bTurnaround = false; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = false; Transaction.pui32Buffer = (uint32_t *)pData; // // Execute the transction over MSPI. // if (am_hal_mspi_blocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_DEVICES_MSPI_TIMEOUT)) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } static uint32_t am_devices_rm67162_command_read(void *pHandle, uint32_t ui32Instr, uint32_t *pData, uint32_t ui32NumBytes, bool bTurnaround) { am_hal_mspi_pio_transfer_t Transaction; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // Create the individual write transaction. Transaction.ui32NumBytes = ui32NumBytes; Transaction.bScrambling = false; Transaction.bDCX = true; Transaction.eDirection = AM_HAL_MSPI_RX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = true; Transaction.ui16DeviceInstr = ui32Instr; Transaction.bTurnaround = bTurnaround; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = false; Transaction.pui32Buffer = (uint32_t *)pData; // // Execute the transction over MSPI. // if (am_hal_mspi_blocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_DEVICES_MSPI_TIMEOUT)) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Reads the current status of the external display //! //! @param ui32DeviceNumber - Device number of the external display //! //! This function reads the device ID register of the external display, and returns //! the result as an 32-bit unsigned integer value. //! //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_reset(void *pHandle) { // Hardware Reset #if 1 am_hal_gpio_state_write(AM_BSP_GPIO_DISPLAY_RESET, AM_HAL_GPIO_OUTPUT_SET); am_util_delay_ms(20); am_hal_gpio_state_write(AM_BSP_GPIO_DISPLAY_RESET, AM_HAL_GPIO_OUTPUT_CLEAR); am_util_delay_ms(20); am_hal_gpio_state_write(AM_BSP_GPIO_DISPLAY_RESET, AM_HAL_GPIO_OUTPUT_SET); am_util_delay_ms(20); #endif if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SWRESET, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } am_util_delay_ms(300); return AM_DEVICES_RM67162_STATUS_SUCCESS; } uint32_t am_devices_rm67162_display_off(void *pHandle) { if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_DISPLAY_OFF, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SLEEP_IN, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } uint32_t am_devices_rm67162_display_on(void *pHandle) { if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_DISPLAY_ON, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Programs the given range of flash addresses. //! //! @param pui8TxBuffer - Buffer to write the external flash data from //! @param ui32NumBytes - Number of bytes to write to the external flash //! //! This function uses the data in the provided pui8TxBuffer and copies it to //! the external flash at the address given by ui32WriteAddress. It will copy //! exactly ui32NumBytes of data from the original pui8TxBuffer pointer. The //! user is responsible for ensuring that they do not overflow the target flash //! memory or underflow the pui8TxBuffer array // //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_blocking_write(void *pHandle, uint8_t *pui8TxBuffer, uint32_t ui32NumBytes) { am_hal_mspi_pio_transfer_t Transaction; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // Create the individual write transaction. Transaction.ui32NumBytes = 0; Transaction.bScrambling = false; Transaction.bDCX = true; Transaction.eDirection = AM_HAL_MSPI_TX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = true; Transaction.ui16DeviceInstr = AM_DEVICES_RM67162_MEMORY_WRITE; Transaction.bTurnaround = false; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = true; Transaction.pui32Buffer = NULL; // // Execute the transction over MSPI. // if (am_hal_mspi_blocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_DEVICES_MSPI_TIMEOUT)) { return AM_DEVICES_RM67162_STATUS_ERROR; } while (ui32NumBytes) { // Create the individual write transaction. Transaction.ui32NumBytes = (ui32NumBytes > BYTE_NUM_PER_WRITE) ? BYTE_NUM_PER_WRITE : ui32NumBytes; Transaction.bScrambling = false; Transaction.bDCX = false; Transaction.eDirection = AM_HAL_MSPI_TX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = false; Transaction.ui16DeviceInstr = 0; Transaction.bTurnaround = false; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = (ui32NumBytes > BYTE_NUM_PER_WRITE) ? true : false; Transaction.pui32Buffer = (uint32_t *)pui8TxBuffer; // // Execute the transction over MSPI. // if (am_hal_mspi_blocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_DEVICES_MSPI_TIMEOUT)) { return AM_DEVICES_RM67162_STATUS_ERROR; } ui32NumBytes -= Transaction.ui32NumBytes; pui8TxBuffer += Transaction.ui32NumBytes; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Reads the contents of the fram into a buffer. //! //! @param pui8RxBuffer - Buffer to store the received data from the flash //! @param ui32ReadAddress - Address of desired data in external flash //! @param ui32NumBytes - Number of bytes to read from external flash //! //! This function reads the external flash at the provided address and stores //! the received data into the provided buffer location. This function will //! only store ui32NumBytes worth of data. // //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_blocking_read(void *pHandle, uint8_t *pui8RxBuffer, uint32_t ui32NumBytes) { am_hal_mspi_pio_transfer_t Transaction; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // Create the individual write transaction. Transaction.ui32NumBytes = 0; Transaction.bScrambling = false; Transaction.bDCX = true; Transaction.eDirection = AM_HAL_MSPI_RX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = true; Transaction.ui16DeviceInstr = AM_DEVICES_RM67162_MEMORY_READ; Transaction.bTurnaround = false; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = true; Transaction.pui32Buffer = NULL; while (ui32NumBytes) { // Create the individual write transaction. Transaction.ui32NumBytes = (ui32NumBytes > BYTE_NUM_PER_WRITE) ? BYTE_NUM_PER_WRITE : ui32NumBytes; Transaction.bScrambling = false; Transaction.bDCX = false; Transaction.eDirection = AM_HAL_MSPI_RX; Transaction.bSendAddr = false; Transaction.ui32DeviceAddr = 0; Transaction.bSendInstr = false; Transaction.ui16DeviceInstr = 0; Transaction.bTurnaround = false; Transaction.bEnWRLatency = false; Transaction.bQuadCmd = false; Transaction.bContinue = (ui32NumBytes > BYTE_NUM_PER_WRITE) ? true : false; Transaction.pui32Buffer = (uint32_t *)pui8RxBuffer; // // Execute the transction over MSPI. // if (am_hal_mspi_blocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_DEVICES_MSPI_TIMEOUT)) { return AM_DEVICES_RM67162_STATUS_ERROR; } ui32NumBytes -= Transaction.ui32NumBytes; pui8RxBuffer += Transaction.ui32NumBytes; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Programs the given range of display addresses. //! //! @param ui32Module - MSPI Instance //! @param pui8TxBuffer - Buffer to write the data from //! @param ui32NumBytes - Number of bytes to write to the display memory //! @param bWaitForCompletion - Waits for CQ/DMA to complete before return. //! //! This function uses the data in the provided pui8TxBuffer and copies it to //! the external flash at the address given by ui32WriteAddress. It will copy //! exactly ui32NumBytes of data from the original pui8TxBuffer pointer. The //! user is responsible for ensuring that they do not overflow the target flash //! memory or underflow the pui8TxBuffer array // //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_nonblocking_write(void *pHandle, uint8_t *pui8TxBuffer, uint32_t ui32NumBytes, bool bWaitForCompletion) { am_hal_mspi_dma_transfer_t Transaction; volatile bool bDMAComplete = false; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // // Enable DCX for DMA Transactions. // if (am_hal_mspi_control(pDisplay->pMspiHandle, AM_HAL_MSPI_REQ_DCX_EN, 0)) { return AM_DEVICES_RM67162_STATUS_ERROR; } // // Create the transaction. // Transaction.ui8Priority = 1; Transaction.eDirection = AM_HAL_MSPI_TX; Transaction.ui32TransferCount = ui32NumBytes; Transaction.ui32DeviceAddress = 0; Transaction.ui32SRAMAddress = (uint32_t)pui8TxBuffer; Transaction.ui32PauseCondition = 0; Transaction.ui32StatusSetClr = 0; // // Execute the transction over MSPI. // if (am_hal_mspi_nonblocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnMSPI_RM67162_Callback, (void *)&bDMAComplete)) { return AM_DEVICES_RM67162_STATUS_ERROR; } if (bWaitForCompletion) { // Wait for DMA Complete or Timeout for (uint32_t i = 0; i < AM_DEVICES_MSPI_TIMEOUT; i++) { if (bDMAComplete) { break; } // // Call the BOOTROM cycle function to delay for about 1 microsecond. // am_hal_flash_delay( FLASH_CYCLES_US(1) ); } // Check the status. if (!bDMAComplete) { return AM_DEVICES_RM67162_STATUS_ERROR; } } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Programs the given range of display addresses. //! //! @param ui32Module - MSPI Instance //! @param pui8TxBuffer - Buffer to write the data from //! @param ui32NumBytes - Number of bytes to write to the display memory //! @param ui32PauseCondition - CQ Pause condition before execution. //! @param ui32StatusSetClr - CQ Set/Clear condition after execution. //! @param pfnCallback - Callback function after execution. //! @param pCallbackCtxt - Callback context after execution. //! //! This function uses the data in the provided pui8TxBuffer and copies it to //! the external display the address given by ui32WriteAddress. It will copy //! exactly ui32NumBytes of data from the original pui8TxBuffer pointer. The //! user is responsible for ensuring that they do not overflow the target display //! memory or underflow the pui8TxBuffer array // //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_nonblocking_write_adv(void *pHandle, uint8_t *pui8TxBuffer, uint32_t ui32NumBytes, uint32_t ui32PauseCondition, uint32_t ui32StatusSetClr, am_hal_mspi_callback_t pfnCallback, void *pCallbackCtxt) { am_hal_mspi_dma_transfer_t Transaction; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // // Create the transaction. // Transaction.ui8Priority = 1; Transaction.eDirection = AM_HAL_MSPI_TX; Transaction.ui32TransferCount = ui32NumBytes; Transaction.ui32DeviceAddress = 0; Transaction.ui32SRAMAddress = (uint32_t)pui8TxBuffer; Transaction.ui32PauseCondition = ui32PauseCondition; Transaction.ui32StatusSetClr = ui32StatusSetClr; // am_hal_gpio_state_write(AM_BSP_GPIO_IOM0_DCX, AM_HAL_GPIO_OUTPUT_CLEAR); // // Execute the transction over IOM. // if (am_hal_mspi_nonblocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnCallback, pCallbackCtxt)) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Reads the contents of the display into a buffer. //! //! @param ui32Module - MSPI Instance //! @param pui8RxBuffer - Buffer to store the received data from the flash //! @param ui32NumBytes - Number of bytes to read from external flash //! @param bWaitForCompletion - Waits for CQ/DMA to complete before return. //! //! This function reads the external display at the provided address and stores //! the received data into the provided buffer location. This function will //! only store ui32NumBytes worth of data. // //! @return 32-bit status // //***************************************************************************** uint32_t am_devices_rm67162_nonblocking_read(void *pHandle, uint8_t *pui8RxBuffer, uint32_t ui32NumBytes, bool bWaitForCompletion) { am_hal_mspi_dma_transfer_t Transaction; volatile bool bDMAComplete = false; am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; // // Create the transaction. // Transaction.ui8Priority = 1; Transaction.eDirection = AM_HAL_MSPI_RX; Transaction.ui32TransferCount = ui32NumBytes; Transaction.ui32DeviceAddress = 0; Transaction.ui32SRAMAddress = (uint32_t)pui8RxBuffer; Transaction.ui32PauseCondition = 0; Transaction.ui32StatusSetClr = 0; // // Execute the transction over MSPI. // if (am_hal_mspi_nonblocking_transfer(pDisplay->pMspiHandle, &Transaction, AM_HAL_MSPI_TRANS_DMA, pfnMSPI_RM67162_Callback, (void *)&bDMAComplete)) { return AM_DEVICES_RM67162_STATUS_ERROR; } if (bWaitForCompletion) { // Wait for DMA Complete or Timeout for (uint32_t i = 0; i < AM_DEVICES_MSPI_TIMEOUT; i++) { if (bDMAComplete) { break; } // // Call the BOOTROM cycle function to delay for about 1 microsecond. // am_hal_flash_delay( FLASH_CYCLES_US(1) ); } // Check the status. if (!bDMAComplete) { return AM_DEVICES_RM67162_STATUS_ERROR; } } return AM_DEVICES_RM67162_STATUS_SUCCESS; } static uint32_t am_devices_set_row_col(void *pHandle, am_devices_rm67162_graphic_conf_t *psGraphic_conf) { uint8_t data[10] = {0}; gs_display_info.row_start = psGraphic_conf->row_offset; gs_display_info.row_end = psGraphic_conf->max_row + psGraphic_conf->row_offset - 1; gs_display_info.col_start = psGraphic_conf->col_offset; gs_display_info.col_end = psGraphic_conf->max_col + psGraphic_conf->col_offset - 1; /* set column start address */ data[0] = (gs_display_info.col_start / 256); data[1] = (gs_display_info.col_start % 256); data[2] = (gs_display_info.col_end / 256); data[3] = (gs_display_info.col_end % 256); if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_COLUMN_ADDR_SETTING, data, 4))//Column { return AM_DEVICES_RM67162_STATUS_ERROR; } /* set row start address */ data[0] = (gs_display_info.row_start / 256); data[1] = (gs_display_info.row_start % 256); data[2] = (gs_display_info.row_end / 256); data[3] = (gs_display_info.row_end % 256); if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_ROW_ADDR_SETTING, data, 4))//raw { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } static uint32_t am_devices_lcm_init(void *pHandle, am_devices_rm67162_graphic_conf_t *psGraphic_conf) { uint8_t data[10] = {0}; /* Tearing effect line ON */ data[0] = 0x0; if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_TEARING_EFFECT_LINE_ON, data, 1)) { return AM_DEVICES_RM67162_STATUS_ERROR; } data[0] = psGraphic_conf->bus_mode; if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SET_DSPI_MODE, data, 1)) { return AM_DEVICES_RM67162_STATUS_ERROR; } data[0] = psGraphic_conf->color_mode ; if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_DATA_FORMAT_SEL, data, 1)) { return AM_DEVICES_RM67162_STATUS_ERROR; } data[0] = psGraphic_conf->scan_mode; if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SCAN_MODE, data, 1)) { return AM_DEVICES_RM67162_STATUS_ERROR; } data[0] = 0x20; if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SET_WRITE_DISPLAY_CTRL, data, 1)) { return AM_DEVICES_RM67162_STATUS_ERROR; } // // Set row/col start/end addresses. // am_devices_set_row_col(pHandle, psGraphic_conf); /* set tear scan-line */ data[0] = 0x00; data[1] = 0x28; // 0xf0 if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SET_TEAR_SCANLINE, data, 2) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_SLEEP_OUT, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } am_util_delay_ms(130); if ( am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_DISPLAY_ON, NULL, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } am_util_delay_ms(200); // am_hal_gpio_state_write(AM_BSP_GPIO_DISPLAY_BL, AM_HAL_GPIO_OUTPUT_CLEAR); am_util_stdio_printf("AM_BSP_GPIO_DISPLAY_BL set on \n"); return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief Initialize the rm67162 driver. //! //! @param ui32Module - MSPI module ID. //! @param psMSPISettings - MSPI device structure describing the target spiflash. //! @param ppMspiHandle - MSPI handler. //! //! This function should be called before any other am_devices_rm67162 //! functions. It is used to set tell the other functions how to communicate //! with the TFT display hardware. //! //! @return Status. // //***************************************************************************** uint32_t am_devices_mspi_rm67162_init(uint32_t ui32Module, am_devices_mspi_rm67162_config_t *psMSPISettings, void **ppHandle, void **ppMspiHandle) { uint32_t ui32Status; uint32_t ui32DeviceID; uint32_t ui32Index = 0; am_hal_mspi_dev_config_t mspiDevCfg; void *pMspiHandle; if ((ui32Module > AM_REG_MSPI_NUM_MODULES) || (psMSPISettings == NULL)) { return AM_DEVICES_RM67162_STATUS_ERROR; } // Allocate a vacant device handle for ( ui32Index = 0; ui32Index < AM_DEVICES_MSPI_RM67162_MAX_DEVICE_NUM; ui32Index++ ) { if ( gAmRm67162[ui32Index].bOccupied == false ) { break; } } if ( ui32Index == AM_DEVICES_MSPI_RM67162_MAX_DEVICE_NUM ) { return AM_DEVICES_RM67162_STATUS_ERROR; } // // Re-Configure the MSPI for the requested operation mode. // mspiDevCfg = SerialDisplayMSPICfg; mspiDevCfg.eClockFreq = psMSPISettings->eClockFreq; //mspiDevCfg.eDeviceConfig = psMSPISettings->eDeviceConfig; mspiDevCfg.ui32TCBSize = psMSPISettings->ui32NBTxnBufLength; mspiDevCfg.pTCB = psMSPISettings->pNBTxnBuf; mspiDevCfg.scramblingStartAddr = psMSPISettings->ui32ScramblingStartAddr; mspiDevCfg.scramblingEndAddr = psMSPISettings->ui32ScramblingEndAddr; mspiDevCfg.eXipMixedMode = psMSPISettings->eMixedMode; // // Configure the MSPI pins. // am_bsp_mspi_pins_enable(ui32Module, mspiDevCfg.eDeviceConfig); // // Initialize the MSPI instance. // Enable power to the MSPI instance. // Configure the MSPI for Serial operation during initialization. // Enable the MSPI. // HAL Success return is 0 // if ( am_hal_mspi_initialize(ui32Module, &pMspiHandle) || am_hal_mspi_power_control(pMspiHandle, AM_HAL_SYSCTRL_WAKE, false) || am_hal_mspi_device_configure(pMspiHandle, &mspiDevCfg) || am_hal_mspi_enable(pMspiHandle) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } else { // // Enable DCX for DMA Transactions. // if ( am_hal_mspi_control(pMspiHandle, AM_HAL_MSPI_REQ_DCX_EN, 0) ) { return AM_DEVICES_RM67162_STATUS_ERROR; } // // Enable MSPI interrupts. // ui32Status = am_hal_mspi_interrupt_clear(pMspiHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR ); if (AM_HAL_STATUS_SUCCESS != ui32Status) { return AM_DEVICES_RM67162_STATUS_ERROR; } ui32Status = am_hal_mspi_interrupt_enable(pMspiHandle, AM_HAL_MSPI_INT_CQUPD | AM_HAL_MSPI_INT_ERR ); if (AM_HAL_STATUS_SUCCESS != ui32Status) { return AM_DEVICES_RM67162_STATUS_ERROR; } gAmRm67162[ui32Index].pMspiHandle = pMspiHandle; gAmRm67162[ui32Index].ui32Module = ui32Module; *ppMspiHandle = pMspiHandle; *ppHandle = (void *)&gAmRm67162[ui32Index]; // // Read the Device ID. // am_devices_rm67162_read_id((void*)&gAmRm67162[ui32Index], &ui32DeviceID); am_util_stdio_printf("RM67167 Device ID = %6X\n", (ui32DeviceID & 0x00FFFFFF)); // // Device specific TFT display initialization. // am_util_delay_ms(500); am_devices_rm67162_reset((void*)&gAmRm67162[ui32Index]); ui32Status = am_devices_lcm_init((void*)&gAmRm67162[ui32Index], &g_sGraphic_conf); if (AM_DEVICES_RM67162_STATUS_SUCCESS != ui32Status) { return AM_DEVICES_RM67162_STATUS_ERROR; } gAmRm67162[ui32Index].bOccupied = true; //am_hal_gpio_state_write(AM_BSP_GPIO_DISPLAY_BL, AM_HAL_GPIO_OUTPUT_SET); // // Return the status. // return AM_DEVICES_RM67162_STATUS_SUCCESS; } } uint32_t am_devices_mspi_rm67162_row_col_reset(void *pHandle) { uint32_t ui32Status = am_devices_set_row_col(pHandle, &g_sGraphic_conf); if (AM_DEVICES_RM67162_STATUS_SUCCESS != ui32Status) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } //***************************************************************************** // //! @brief De-Initialize the rm67162 driver. //! //! @param ui32Module - MSPI Module# //! //! This function reverses the initialization //! //! @return Status. // //***************************************************************************** uint32_t am_devices_rm67162_term(void *pHandle) { am_devices_mspi_rm67162_t *pDisplay = (am_devices_mspi_rm67162_t *)pHandle; if ( pDisplay->ui32Module > AM_REG_IOM_NUM_MODULES ) { return AM_DEVICES_RM67162_STATUS_ERROR; } // am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, AM_BSP_GPIO_DISPLAY_TE)); // am_hal_gpio_interrupt_disable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, AM_BSP_GPIO_DISPLAY_TE)); // NVIC_DisableIRQ(GPIO_IRQn); // Disable the pins // am_bsp_iom_display_pins_disable(AM_BSP_4_WIRES_SPI_MODE); // // Disable the MSPI. // am_hal_mspi_disable(pDisplay->pMspiHandle); // // Disable power to and uninitialize the MSPI instance. // am_hal_mspi_power_control(pDisplay->pMspiHandle, AM_HAL_SYSCTRL_DEEPSLEEP, false); am_hal_mspi_deinitialize(pDisplay->pMspiHandle); // Free this device handle pDisplay->bOccupied = false; // // Return the status. // return AM_DEVICES_RM67162_STATUS_SUCCESS; } uint32_t am_devices_rm67162_read_id(void *pHandle, uint32_t *pdata) { if (am_devices_rm67162_command_read(pHandle, AM_DEVICES_RM67162_READ_ID, pdata, 3, true)) { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; } uint32_t am_devices_mspi_rm67162_set_transfer_window(void *pHandle, uint32_t startRow, uint32_t startCol, uint32_t endRow, uint32_t endCol) { uint8_t data[4] = {0}; /* set column start address */ data[0] = (startCol / 256); data[1] = (startCol % 256); data[2] = (endCol / 256); data[3] = (endCol % 256); if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_COLUMN_ADDR_SETTING, data, 4))//Column { return AM_DEVICES_RM67162_STATUS_ERROR; } /* set row start address */ data[0] = (startRow / 256); data[1] = (startRow % 256); data[2] = (endRow / 256); data[3] = (endRow % 256); if (am_devices_rm67162_command_write(pHandle, AM_DEVICES_RM67162_ROW_ADDR_SETTING, data, 4))//raw { return AM_DEVICES_RM67162_STATUS_ERROR; } return AM_DEVICES_RM67162_STATUS_SUCCESS; }