Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nickshl/DevCore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornickshl <nicolai.shlapunov@gmail.com>2019-05-01 05:59:41 +0300
committernickshl <nicolai.shlapunov@gmail.com>2019-05-01 05:59:41 +0300
commit8976577292f0322349caccc088e11a0da47994b3 (patch)
tree305f224e386b4364f8b921a867048dd4da38a6ac /Display
parentf560c684baebe9d7d5bdc4ee01149e8c29cf060f (diff)
Major redesign: Interfaces for Display and Touchscreen, both uses interface to SPI.
Diffstat (limited to 'Display')
-rw-r--r--Display/DisplayDrv.cpp299
-rw-r--r--Display/DisplayDrv.h49
-rw-r--r--Display/ILI9341.cpp362
-rw-r--r--Display/ILI9341.h177
-rw-r--r--Display/Strings.cpp17
-rw-r--r--Display/Strings.h5
-rw-r--r--Display/XPT2046.cpp115
-rw-r--r--Display/XPT2046.h46
8 files changed, 576 insertions, 494 deletions
diff --git a/Display/DisplayDrv.cpp b/Display/DisplayDrv.cpp
index ac75415..2d23fc5 100644
--- a/Display/DisplayDrv.cpp
+++ b/Display/DisplayDrv.cpp
@@ -34,40 +34,37 @@ DisplayDrv& DisplayDrv::GetInstance(void)
// *****************************************************************************
Result DisplayDrv::Setup()
{
- // Init display driver
- tft.Init();
- // Set mode - mode can be set earlier than Display initialization
- SetUpdateMode(update_mode);
+ // Task can't be initialized without display driver
+ Result result = Result::ERR_NULL_PTR;
- // If deisplay and touchscreen share same SPI
- if(tft_hspi == touch_hspi)
+ // If pointer to display present
+ if(display != nullptr)
{
- // Read original SPI prescaler
- uint32_t prescaler = READ_REG(tft_hspi->Instance->CR1) & SPI_CR1_BR_Msk;
- // Set prescaler for SPI
- MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_64);
- // Init touchscreen driver
- touch.Init();
- // Restore prescaler for SPI
- MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, prescaler);
- }
- else
- {
- // Init touchscreen driver
- touch.Init();
- }
+ // Init display driver
+ display->Init();
+ // Set mode - mode can be set earlier than Display initialization
+ SetUpdateMode(update_mode);
- // Set string parameters
- fps_str.SetParams(str, width/3, height - 6, COLOR_MAGENTA, String::FONT_4x6);
- // Show string if flag is set
- if(DISPLAY_DEBUG_INFO)
- {
- // Max Z
- fps_str.Show(0xFFFFFFFFU);
+ // If pointer to touchscreen present
+ if(touch != nullptr)
+ {
+ // Init touchscreen driver
+ touch->Init();
+ }
+
+ // Set string parameters
+ fps_str.SetParams(str, width/3, height - 6, COLOR_MAGENTA, String::FONT_4x6);
+ // Show string if flag is set
+ if(DISPLAY_DEBUG_INFO)
+ {
+ // Max Z
+ fps_str.Show(0xFFFFFFFFU);
+ }
+ result = Result::RESULT_OK;
}
- // Always ok
- return Result::RESULT_OK;
+ // Return result
+ return result;
}
// *****************************************************************************
@@ -87,7 +84,7 @@ Result DisplayDrv::Loop()
if(LockDisplay() == Result::RESULT_OK)
{
// Set address window for all screen
- tft.SetAddrWindow(0, 0, width-1, height-1);
+ display->SetAddrWindow(0, 0, width-1, height-1);
// For each line/row
for(int32_t i=0; i < height; i++)
{
@@ -101,25 +98,25 @@ Result DisplayDrv::Loop()
while(p_obj != nullptr)
{
// Draw object to buf
- if(update_mode) p_obj->DrawInBufH(scr_buf[i%2], width, i);
- else p_obj->DrawInBufW(scr_buf[i%2], width, i);
+ if(update_mode == UPDATE_LEFT_RIGHT) p_obj->DrawInBufH(scr_buf[i%2], width, i);
+ else p_obj->DrawInBufW(scr_buf[i%2], width, i);
// Set pointer to next object in list
p_obj = p_obj->p_next;
}
// Give semaphore after changes
line_mutex.Release();
// Wait until previous transfer complete
- while(tft.IsTransferComplete() == false) taskYIELD();
+ while(display->IsTransferComplete() == false) taskYIELD();
// Write stream to LCD
- tft.SpiWriteStream((uint8_t*)scr_buf[i%2], width*tft.GetBytesPerPixel());
+ display->WriteDataStream((uint8_t*)scr_buf[i%2], width * display->GetBytesPerPixel());
// DO NOT TRY "OPTIMIZE" CODE !!!
// Two "while" cycles used for generate next line when previous line
// transfer via SPI to display.
}
// Wait until last transfer complete
- while(tft.IsTransferComplete() == false) taskYIELD();
+ while(display->IsTransferComplete() == false) taskYIELD();
// Pull up CS
- tft.StopTransfer();
+ display->StopTransfer();
// Give semaphore after draw frame
UnlockDisplay();
// Calculate FPS if debug info is ON
@@ -137,18 +134,11 @@ Result DisplayDrv::Loop()
// Try to take mutex. 1 ms should be enough.
if(touchscreen_mutex.Lock(1U) == Result::RESULT_OK)
{
- // Set prescaler for SPI it display share save SPI with touchscreen
- if(tft_hspi == touch_hspi)
- {
- MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_64);
- }
- // Get touch coordinates
- tmp_is_touch = touch.GetXY(tmp_tx, tmp_ty);
- // Reset prescaler for SPI it display share save SPI with touchscreen
- if(tft_hspi == touch_hspi)
+ // If pointer to touchscreen present
+ if(touch != nullptr)
{
- // Restore prescaler for SPI
- MODIFY_REG(tft_hspi->Instance->CR1, (uint32_t)SPI_CR1_BR_Msk, SPI_BAUDRATEPRESCALER_2);
+ // Get touch coordinates
+ tmp_is_touch = touch->GetXY(tmp_tx, tmp_ty);
}
// Give semaphore for drawing frame - we can enter in this "if" statement
// only if mutex taken
@@ -259,6 +249,33 @@ Result DisplayDrv::Loop()
}
// *****************************************************************************
+// *** Set display driver(or clear if nullptr used as argument) ************
+// *****************************************************************************
+Result DisplayDrv::SetDisplayDrv(IDisplay* in_display)
+{
+ Result result = Result::ERR_INVALID_ITEM;
+ // Display driver should be set before scheduler started
+ if(Rtos::IsSchedulerNotRunning())
+ {
+ // If pointer to display present
+ if(in_display != nullptr)
+ {
+ // Save display driver pointer
+ display = in_display;
+ // Set result
+ result = Result::RESULT_OK;
+ }
+ else
+ {
+ // Task can't be initialized without display driver
+ Result result = Result::ERR_NULL_PTR;
+ }
+ }
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
// *** Add Visual Object to object list ************************************
// *****************************************************************************
Result DisplayDrv::AddVisObjectToList(VisObject* obj, uint32_t z)
@@ -434,31 +451,49 @@ Result DisplayDrv::UpdateDisplay(void)
// *****************************************************************************
// *** Set Update Mode *****************************************************
// *****************************************************************************
-void DisplayDrv::SetUpdateMode(bool is_vertical)
+void DisplayDrv::SetUpdateMode(UpdateMode mode)
{
// Lock display
LockDisplay();
// Wait while transfer complete before change settings
- while(tft.IsTransferComplete() == false);
+ while(display->IsTransferComplete() == false);
// Change Update mode
- if(is_vertical)
+ if(mode == UPDATE_LEFT_RIGHT)
{
- tft.SetRotation(2U);
+ display->SetRotation(IDisplay::ROTATION_LEFT);
}
else
{
- tft.SetRotation(3U);
+ display->SetRotation(IDisplay::ROTATION_TOP);
}
// Set width and height variables for selected screen update mode
- width = tft.GetWidth();
- height = tft.GetHeight();
+ width = display->GetWidth();
+ height = display->GetHeight();
// Save Update mode
- update_mode = is_vertical;
+ update_mode = mode;
// Unlock display
UnlockDisplay();
}
// *****************************************************************************
+// *** Set touchscreen driver(or clear if nullptr used as argument) ********
+// *****************************************************************************
+Result DisplayDrv::SetTouchDrv(ITouchscreen* in_touch)
+{
+ Result result = Result::ERR_INVALID_ITEM;
+ // Touchscreen driver should be set before scheduler started
+ if(Rtos::IsSchedulerNotRunning())
+ {
+ // Store new touch pointer
+ touch = in_touch;
+ // Set good result
+ result = Result::RESULT_OK;
+ }
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
// *** Get Touch X and Y coordinate ****************************************
// *****************************************************************************
bool DisplayDrv::GetTouchXY(int32_t& x, int32_t& y)
@@ -470,7 +505,7 @@ bool DisplayDrv::GetTouchXY(int32_t& x, int32_t& y)
if(touchscreen_mutex.Lock(1U) == Result::RESULT_OK)
{
// If display driver gets touch coordinates and touch still present
- if(is_touch && touch.IsTouch())
+ if((touch != nullptr) && is_touch && touch->IsTouched())
{
// Return last values
x = tx;
@@ -495,9 +530,25 @@ bool DisplayDrv::GetTouchXY(int32_t& x, int32_t& y)
// *************************************************************************
// *** Check touch *****************************************************
// *************************************************************************
-bool DisplayDrv::IsTouch()
+bool DisplayDrv::IsTouched()
{
- return touch.IsTouch();
+ // Not touched by default
+ bool touched = false;
+ // Try to take mutex. 1 ms should be enough.
+ if(touchscreen_mutex.Lock(1U) == Result::RESULT_OK)
+ {
+ // If pointer to touchscreen present
+ if(touch != nullptr)
+ {
+ // Get status
+ touched = touch->IsTouched();
+ }
+ // Give semaphore for drawing frame - we can enter in this "if" statement
+ // only if mutex taken
+ touchscreen_mutex.Release();
+ }
+ // Return status
+ return touched;
}
// *****************************************************************************
@@ -505,73 +556,77 @@ bool DisplayDrv::IsTouch()
// *****************************************************************************
void DisplayDrv::TouchCalibrate()
{
- // Box for calibration
- Box background(0, 0, width, height, COLOR_BLACK, true);
- Box box(0, 0, 2, 2, COLOR_WHITE, true);
- int32_t tx;
- int32_t ty;
- int32_t x1, x2;
- int32_t y1, y2;
-
- // Reset calibration
- touch.SetCalibrationConsts(XPT2046::COEF, XPT2046::COEF, 0, 0);
-
- // Show background box
- background.Show(0xFFFFFFFFU-1U);
- // Show box
- box.Show(0xFFFFFFFFU);
-
- // Move box to position
- box.Move(10-1, 10-1);
- // Wait press for get initial coordinates
- while(!GetTouchXY(x1, y1))
- {
- // Update Display
- UpdateDisplay();
- // Delay
- RtosTick::DelayMs(100U);
- }
- // Wait unpress and measure coordinates continuously for averaging
- while(GetTouchXY(tx, ty))
+ // If pointer to touchscreen present
+ if(touch != nullptr)
{
- x1 = (x1 + tx) / 2;
- y1 = (y1 + ty) / 2;
- // Update Display - for update touch coordinates
- UpdateDisplay();
- // Delay
- RtosTick::DelayMs(100U);
- }
+ // Box for calibration
+ Box background(0, 0, width, height, COLOR_BLACK, true);
+ Box box(0, 0, 2, 2, COLOR_WHITE, true);
+ int32_t tx;
+ int32_t ty;
+ int32_t x1, x2;
+ int32_t y1, y2;
+
+ // Reset calibration
+ touch->SetCalibrationConsts(ITouchscreen::COEF, ITouchscreen::COEF, 0, 0);
+
+ // Show background box
+ background.Show(0xFFFFFFFFU-1U);
+ // Show box
+ box.Show(0xFFFFFFFFU);
+
+ // Move box to position
+ box.Move(10-1, 10-1);
+ // Wait press for get initial coordinates
+ while(!GetTouchXY(x1, y1))
+ {
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+ // Wait unpress and measure coordinates continuously for averaging
+ while(GetTouchXY(tx, ty))
+ {
+ x1 = (x1 + tx) / 2;
+ y1 = (y1 + ty) / 2;
+ // Update Display - for update touch coordinates
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
- // Move box to position
- box.Move(width - 10 - 1, height - 10 - 1);
- // Wait press for get initial coordinates
- while(!GetTouchXY(x2, y2))
- {
- // Update Display
- UpdateDisplay();
- // Delay
- RtosTick::DelayMs(100U);
- }
- // Wait unpress and measure coordinates continuously for averaging
- while(GetTouchXY(tx, ty))
- {
- x2 = (x2 + tx) / 2;
- y2 = (y2 + ty) / 2;
- // Update Display
- UpdateDisplay();
- // Delay
- RtosTick::DelayMs(100U);
- }
+ // Move box to position
+ box.Move(width - 10 - 1, height - 10 - 1);
+ // Wait press for get initial coordinates
+ while(!GetTouchXY(x2, y2))
+ {
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
+ // Wait unpress and measure coordinates continuously for averaging
+ while(GetTouchXY(tx, ty))
+ {
+ x2 = (x2 + tx) / 2;
+ y2 = (y2 + ty) / 2;
+ // Update Display
+ UpdateDisplay();
+ // Delay
+ RtosTick::DelayMs(100U);
+ }
- // Calc coefs
- int32_t kx = ((x2 - x1) * XPT2046::COEF) / (width - 2*10);
- int32_t ky = ((y2 - y1) * XPT2046::COEF) / (height - 2*10);
- int32_t bx = 10 - (x1 * XPT2046::COEF) / kx;
- int32_t by = 10 - (y1 * XPT2046::COEF) / ky;
+ // Calc coefs
+ int32_t kx = ((x2 - x1) * ITouchscreen::COEF) / (width - 2*10);
+ int32_t ky = ((y2 - y1) * ITouchscreen::COEF) / (height - 2*10);
+ int32_t bx = 10 - (x1 * ITouchscreen::COEF) / kx;
+ int32_t by = 10 - (y1 * ITouchscreen::COEF) / ky;
- // Save calibration
- touch.SetCalibrationConsts(kx, ky, bx, by);
+ // Save calibration
+ touch->SetCalibrationConsts(kx, ky, bx, by);
- // Hide box
- box.Hide();
+ // Hide box
+ box.Hide();
+ }
}
diff --git a/Display/DisplayDrv.h b/Display/DisplayDrv.h
index aafa814..d62ef4b 100644
--- a/Display/DisplayDrv.h
+++ b/Display/DisplayDrv.h
@@ -50,8 +50,8 @@
#include "RtosMutex.h"
#include "RtosSemaphore.h"
-#include "ILI9341.h"
-#include "XPT2046.h"
+#include "IDisplay.h"
+#include "ITouchscreen.h"
#include "VisObject.h"
#include "Primitives.h"
#include "Strings.h"
@@ -65,6 +65,15 @@ class DisplayDrv : public AppTask
{
public:
// *************************************************************************
+ // *** Update Mode *****************************************************
+ // *************************************************************************
+ enum UpdateMode
+ {
+ UPDATE_TOP_BOTTOM,
+ UPDATE_LEFT_RIGHT
+ };
+
+ // *************************************************************************
// *** Get Instance ****************************************************
// *************************************************************************
static DisplayDrv& GetInstance(void);
@@ -80,6 +89,16 @@ class DisplayDrv : public AppTask
virtual Result Loop();
// *************************************************************************
+ // *** Set display driver **********************************************
+ // *************************************************************************
+ Result SetDisplayDrv(IDisplay* in_display);
+
+ // *************************************************************************
+ // *** Get display driver **********************************************
+ // *************************************************************************
+ IDisplay* GetDisplayDrv(void) {return display;}
+
+ // *************************************************************************
// *** Add Visual Object to object list ********************************
// *************************************************************************
Result AddVisObjectToList(VisObject* obj, uint32_t z);
@@ -117,7 +136,7 @@ class DisplayDrv : public AppTask
// *************************************************************************
// *** Set Update Mode *************************************************
// *************************************************************************
- void SetUpdateMode(bool is_vertical = false);
+ void SetUpdateMode(UpdateMode mode);
// *************************************************************************
// *** GetScreenW ******************************************************
@@ -130,6 +149,16 @@ class DisplayDrv : public AppTask
inline int32_t GetScreenH(void) {return height;}
// *************************************************************************
+ // *** Set touchscreen driver(or clear if nullptr used as argument) ****
+ // *************************************************************************
+ Result SetTouchDrv(ITouchscreen* in_touch);
+
+ // *************************************************************************
+ // *** Get touchscreen driver ******************************************
+ // *************************************************************************
+ ITouchscreen* GetTouchDrv(void) {return touch;}
+
+ // *************************************************************************
// *** Get Touch X and Y coordinate ************************************
// *************************************************************************
bool GetTouchXY(int32_t& x, int32_t& y);
@@ -137,7 +166,7 @@ class DisplayDrv : public AppTask
// *************************************************************************
// *** Check touch *****************************************************
// *************************************************************************
- bool IsTouch();
+ bool IsTouched();
// *************************************************************************
// *** Calibrate Touchscreen *******************************************
@@ -149,14 +178,10 @@ class DisplayDrv : public AppTask
static const bool DISPLAY_DEBUG_INFO = true;
// Display driver object
- ILI9341 tft = TFT_HSPI;
- // Display SPI handle
- SPI_HandleTypeDef* tft_hspi = TFT_HSPI;
+ IDisplay* display = nullptr;
// Touchscreen driver object
- XPT2046 touch = TOUCH_HSPI;
- // Touchscreen SPI handle
- SPI_HandleTypeDef* touch_hspi = TOUCH_HSPI;
+ ITouchscreen* touch = nullptr;
// Pointer to first object in list
VisObject* object_list = nullptr;
@@ -164,12 +189,12 @@ class DisplayDrv : public AppTask
VisObject* object_list_last = nullptr;
// Update mode: true - vertical, false = horizontal
- bool update_mode = false;
+ UpdateMode update_mode = UPDATE_TOP_BOTTOM;
// Variables for update screen mode
int32_t width = 0;
int32_t height = 0;
// Double Screen Line buffer
- uint16_t scr_buf[2][ILI9341::GetMaxLine()];
+ uint16_t scr_buf[2][IDisplay::GetMaxLine()];
// Touch coordinates and state
bool is_touch = false;
diff --git a/Display/ILI9341.cpp b/Display/ILI9341.cpp
index f680a33..dfbe078 100644
--- a/Display/ILI9341.cpp
+++ b/Display/ILI9341.cpp
@@ -112,90 +112,20 @@
#define MADCTL_MH 0x04 // Horizontal Refresh ORDER
// *****************************************************************************
-// *** Constructor *********************************************************
+// *** Public: Init screen *************************************************
// *****************************************************************************
-ILI9341::ILI9341(SPI_HandleTypeDef* in_hspi) : hspi(in_hspi) {};
-
-// *****************************************************************************
-// *** Write byte to SPI ***************************************************
-// *****************************************************************************
-inline void ILI9341::SpiWrite(uint8_t c)
-{
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
- HAL_SPI_Transmit(hspi, &c, sizeof(c), 1U);
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); // Pull up CS
-}
-
-// *****************************************************************************
-// *** Write byte stream to SPI ********************************************
-// *****************************************************************************
-void ILI9341::SpiWriteStream(uint8_t* data, uint32_t n)
-{
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
- HAL_SPI_Transmit_DMA(hspi, data, n);
-}
-
-// *****************************************************************************
-// *** Write command to SPI ************************************************
-// *****************************************************************************
-inline void ILI9341::WriteCommand(uint8_t c)
+Result ILI9341::Init(void)
{
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // Command
- SpiWrite(c);
-}
-
-// *****************************************************************************
-// *** Write data to SPI ***************************************************
-// *****************************************************************************
-inline void ILI9341::WriteData(uint8_t c)
-{
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
- SpiWrite(c);
-}
-
-// *****************************************************************************
-// *** Write data steram to SPI ********************************************
-// *****************************************************************************
-void ILI9341::WriteDataStream(uint8_t* data, uint32_t n)
-{
- // Data
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);
- // Pull down CS
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
- // Send data to screen
- HAL_SPI_Transmit_DMA(hspi, data, n);
-}
-
-// *****************************************************************************
-// *** Check SPI transfer status *******************************************
-// *****************************************************************************
-bool ILI9341::IsTransferComplete(void)
-{
- return (hspi->State != HAL_SPI_STATE_BUSY_TX);
-// return (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == SET);
-}
-
-// *****************************************************************************
-// *** Pull up CS line for LCD **********************************************
-// *****************************************************************************
-void ILI9341::StopTransfer(void)
-{
- // Pull up CS
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
-}
-
-// *****************************************************************************
-// *** Init screen *********************************************************
-// *****************************************************************************
-void ILI9341::Init(void)
-{
-// // Reset sequence. Used only if GPIO pin used as LCD reset.
-// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
-// HAL_Delay(5);
-// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
-// HAL_Delay(20);
-// HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
-// HAL_Delay(150);
+ if(display_rst != nullptr)
+ {
+ // Reset sequence. Used only if GPIO pin used as LCD reset.
+ display_rst->SetHigh();
+ HAL_Delay(5);
+ display_rst->SetLow();
+ HAL_Delay(20);
+ display_rst->SetHigh();
+ HAL_Delay(150);
+ }
// Exit Sleep
WriteCommand(CMD_SWRESET);
@@ -215,7 +145,7 @@ void ILI9341::Init(void)
WriteData(0x2B);
WriteData(0x2B);
- // VCM control 2
+ // VCM control 2
WriteCommand(CMD_VMCTR2);
WriteData(0xC0);
@@ -268,13 +198,13 @@ void ILI9341::Init(void)
WriteCommand(CMD_MADCTL);
WriteData(0x48);
- // Display Function Control
+ // Display Function Control
WriteCommand(CMD_DFUNCTR);
WriteData(0x08);
WriteData(0x82);
WriteData(0x27);
- // Enable 3 gamma control - Disable 3 Gamma Function
+ // Enable 3 gamma control - Disable 3 Gamma Function
WriteCommand(CMD_EN3G);
WriteData(0x00);
@@ -330,12 +260,54 @@ void ILI9341::Init(void)
HAL_Delay(120U);
// Display on
WriteCommand(CMD_DISPON);
+
+ // Always Ok
+ return Result::RESULT_OK;
+}
+
+// *****************************************************************************
+// *** Public: Write data steram to SPI ************************************
+// *****************************************************************************
+Result ILI9341::WriteDataStream(uint8_t* data, uint32_t n)
+{
+ // Data
+ display_dc.SetHigh();
+ // Pull down CS
+ display_cs.SetLow();
+ // Send data to screen
+ Result result = spi.WriteAsync(data, n);
+ // Return result
+ return result;
+}
+
+// *****************************************************************************
+// *** Public: Check SPI transfer status **********************************
+// *****************************************************************************
+bool ILI9341::IsTransferComplete(void)
+{
+ return spi.IsTransferComplete();
+}
+
+// *****************************************************************************
+// *** Pull up CS line for LCD **********************************************
+// *****************************************************************************
+Result ILI9341::StopTransfer(void)
+{
+ // In case if transfer isn't finished - abort it.
+ if(spi.IsTransferComplete() == false)
+ {
+ spi.Abort();
+ }
+ // Pull up CS
+ display_cs.SetHigh();
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Set output window ***************************************************
// *****************************************************************************
-void ILI9341::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
+Result ILI9341::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
WriteCommand(CMD_CASET); // Column address set
WriteData(x0 >> 8);
@@ -352,169 +324,168 @@ void ILI9341::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
WriteCommand(CMD_RAMWR); // write to RAM
// Prepare for write data
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
-}
-
-// *****************************************************************************
-// *** Pass 8-bit (each) R,G,B, get back 16-bit packed color ***************
-// *****************************************************************************
-uint16_t ILI9341::GetColor565(uint8_t r, uint8_t g, uint8_t b)
-{
- return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
+ display_dc.SetHigh(); // Data
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Set screen orientation **********************************************
// *****************************************************************************
-void ILI9341::SetRotation(uint8_t m)
+Result ILI9341::SetRotation(IDisplay::Rotation r)
{
+ rotation = r;
WriteCommand(CMD_MADCTL);
- rotation = m % 4; // can't be higher than 3
switch (rotation)
{
- case 0:
+ case IDisplay::ROTATION_BOTTOM:
WriteData(MADCTL_BGR);
- width = TFT_HEIGHT;
- height = TFT_WIDTH;
+ width = init_height;
+ height = init_width;
break;
- case 1:
+ case IDisplay::ROTATION_RIGHT:
WriteData(MADCTL_MV | MADCTL_BGR);
- width = TFT_WIDTH;
- height = TFT_HEIGHT;
+ width = init_width;
+ height = init_height;
break;
- case 2: // Y: up -> down
+ case IDisplay::ROTATION_LEFT: // Y: up -> down
WriteData(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
- width = TFT_HEIGHT;
- height = TFT_WIDTH;
+ width = init_height;
+ height = init_width;
break;
- case 3: // X: left -> right
+ case IDisplay::ROTATION_TOP: // X: left -> right
WriteData(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
- width = TFT_WIDTH;
- height = TFT_HEIGHT;
+ width = init_width;
+ height = init_height;
break;
default:
break;
}
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Write color to screen ***********************************************
// *****************************************************************************
-void ILI9341::PushColor(uint16_t color)
+Result ILI9341::PushColor(uint16_t color)
{
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
-
+ display_dc.SetHigh(); // Data
+ // Write color
SpiWrite(color >> 8);
SpiWrite(color);
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Draw one pixel on screen *******************************************
// *****************************************************************************
-void ILI9341::DrawPixel(int16_t x, int16_t y, uint16_t color)
+Result ILI9341::DrawPixel(int16_t x, int16_t y, uint16_t color)
{
- if((x < 0) ||(x >= width) || (y < 0) || (y >= height)) return;
-
- SetAddrWindow(x,y,x+1,y+1);
-
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
-
- SpiWrite(color >> 8);
- SpiWrite(color);
+ if((x >= 0) && (x < width) && (y >= 0) && (y < height))
+ {
+ SetAddrWindow(x,y,x+1,y+1);
+ // Write color
+ SpiWrite(color >> 8);
+ SpiWrite(color);
+ }
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Draw vertical line **************************************************
// *****************************************************************************
-void ILI9341::DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
+Result ILI9341::DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
// Rudimentary clipping
- if((x >= width) || (y >= height)) return;
-
- if((y+h-1) >= height) h = height-y;
-
- SetAddrWindow(x, y, x, y+h-1);
+ if((x < width) && (y < height))
+ {
+ if((y+h-1) >= height) h = height-y;
- uint8_t hi = color >> 8, lo = color;
+ SetAddrWindow(x, y, x, y+h-1);
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ // Swap bytes
+ uint8_t color = ((color >> 8) & 0x00FF) | ((color << 8) & 0xFF00);
- while (h--)
- {
- SpiWrite(hi);
- SpiWrite(lo);
+ display_cs.SetLow(); // Pull down CS
+ while(h--)
+ {
+ spi.Write(&color, sizeof(color));
+ }
+ display_cs.SetHigh(); // Pull up CS
}
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Draw horizontal line ************************************************
// *****************************************************************************
-void ILI9341::DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
+Result ILI9341::DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
- if((x >= width) || (y >= height)) return;
- if((x+w-1) >= width) w = width-x;
-
- SetAddrWindow(x, y, x+w-1, y);
+ if((x < width) && (y < height))
+ {
+ if((x+w-1) >= width) w = width-x;
- uint8_t hi = color >> 8, lo = color;
+ SetAddrWindow(x, y, x+w-1, y);
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ // Swap bytes
+ uint8_t color = ((color >> 8) & 0x00FF) | ((color << 8) & 0xFF00);
- while (w--)
- {
- SpiWrite(hi);
- SpiWrite(lo);
+ display_cs.SetLow(); // Pull down CS
+ while(w--)
+ {
+ spi.Write(&color, sizeof(color));
+ }
+ display_cs.SetHigh(); // Pull up CS
}
-}
-
-// *****************************************************************************
-// *** Fill full screen ****************************************************
-// *****************************************************************************
-void ILI9341::FillScreen(uint16_t color)
-{
- FillRect(0, 0, width, height, color);
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Fill rectangle on screen ********************************************
// *****************************************************************************
-void ILI9341::FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
+Result ILI9341::FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
- if((x >= width) || (y >= height)) return;
- if((x + w - 1) >= width) w = width - x;
- if((y + h - 1) >= height) h = height - y;
-
- SetAddrWindow(x, y, x+w-1, y+h-1);
+ if((x < width) && (y < height))
+ {
+ if((x + w - 1) >= width) w = width - x;
+ if((y + h - 1) >= height) h = height - y;
- uint8_t hi = color >> 8, lo = color;
+ SetAddrWindow(x, y, x+w-1, y+h-1);
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ // Swap bytes
+ uint8_t color = ((color >> 8) & 0x00FF) | ((color << 8) & 0xFF00);
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); // Pull down CS
- for(y=h; y>0; y--)
- {
- for(x=w; x>0; x--)
+ display_cs.SetLow(); // Pull down CS
+ for(y=h; y>0; y--)
{
- // Wait until TXE flag is set to send data
- while(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == RESET);
- hspi->Instance->DR = hi;
- while(__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == RESET);
- hspi->Instance->DR = lo;
+ for(x=w; x>0; x--)
+ {
+ spi.Write(&color, sizeof(color));
+ }
}
+ display_cs.SetHigh(); // Pull up CS
}
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET); // Pull up CS
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
// *** Invert display ******************************************************
// *****************************************************************************
-void ILI9341::InvertDisplay(bool invert)
+Result ILI9341::InvertDisplay(bool invert)
{
WriteCommand(invert ? CMD_INVON : CMD_INVOFF);
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
@@ -525,11 +496,11 @@ inline uint8_t ILI9341::SpiRead(void)
// Result variable
uint8_t r = 0;
// Pull down CS
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
+ display_cs.SetLow();
// Receive data
- HAL_SPI_Receive(hspi, &r, sizeof(r), 100U);
+ spi.Read(&r, sizeof(r));
// Pull up CS
- HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
+ display_cs.SetHigh();
// Return result
return r;
}
@@ -540,7 +511,7 @@ inline uint8_t ILI9341::SpiRead(void)
inline uint8_t ILI9341::ReadData(void)
{
// Data
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ display_dc.SetHigh(); // Data
// Receive data
uint8_t r = SpiRead();
// Return result
@@ -553,14 +524,51 @@ inline uint8_t ILI9341::ReadData(void)
uint8_t ILI9341::ReadCommand(uint8_t c)
{
// Set command mode
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // Command
+ display_dc.SetLow(); // Command
SpiWrite(c);
// Set data mode
- HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // Data
+ display_dc.SetHigh(); // Data
// Receive data
uint8_t r = SpiRead();
// Return result
return r;
}
+
+// *****************************************************************************
+// *** Write byte to SPI ***************************************************
+// *****************************************************************************
+inline void ILI9341::SpiWrite(uint8_t c)
+{
+ display_cs.SetLow(); // Pull down CS
+ spi.Write(&c, sizeof(c));
+ display_cs.SetHigh(); // Pull up CS
+}
+
+//// *****************************************************************************
+//// *** Write byte stream to SPI ********************************************
+//// *****************************************************************************
+//void ILI9341::SpiWriteStream(uint8_t* data, uint32_t n)
+//{
+// display_cs.SetLow(); // Pull down CS
+// HAL_SPI_Transmit_DMA(hspi, data, n);
+//}
+
+// *****************************************************************************
+// *** Write command to SPI ************************************************
+// *****************************************************************************
+inline void ILI9341::WriteCommand(uint8_t c)
+{
+ display_dc.SetLow(); // Command
+ SpiWrite(c);
+}
+
+// *****************************************************************************
+// *** Write data to SPI ***************************************************
+// *****************************************************************************
+inline void ILI9341::WriteData(uint8_t c)
+{
+ display_dc.SetHigh(); // Data
+ SpiWrite(c);
+}
diff --git a/Display/ILI9341.h b/Display/ILI9341.h
index 15712c1..d8d800a 100644
--- a/Display/ILI9341.h
+++ b/Display/ILI9341.h
@@ -42,217 +42,120 @@
// *** Includes ************************************************************
// *****************************************************************************
#include <DevCfg.h>
+#include "IDisplay.h"
+#include "ISpi.h"
+#include "IGpio.h"
// *****************************************************************************
-// *** Enums ***************************************************************
+// *** ILI9341 *************************************************************
// *****************************************************************************
-
-// Color definitions
-enum Color
-{
- COLOR_BLACK = 0x0000, // 0, 0, 0
- COLOR_VERYDARKGREY = 0xEF7B, // 32, 32, 32
- COLOR_DARKGREY = 0xEF7B, // 64, 64, 64
- COLOR_GREY = 0xEF7B, // 128, 128, 128
- COLOR_LIGHTGREY = 0x18C6, // 192, 192, 192
- COLOR_WHITE = 0xFFFF, // 255, 255, 255
-
- COLOR_VERYDARKRED = 0x0018, // 32, 0, 0
- COLOR_DARKRED = 0x0038, // 64, 0, 0
- COLOR_MEDIUMRED = 0x0078, // 128, 0, 0
- COLOR_LIGHTRED = 0x00B8, // 192, 0, 0
- COLOR_RED = 0x00F8, // 255, 0, 0
-
- COLOR_VERYDARKGREEN = 0xE000, // 0, 32, 0
- COLOR_DARKGREEN = 0xE001, // 0, 64, 0
- COLOR_MEDIUMGREEN = 0xE003, // 0, 128, 0
- COLOR_LIGHTGREEN = 0xE005, // 0, 192, 0
- COLOR_GREEN = 0xE007, // 0, 255, 0
-
- COLOR_VERYDARKBLUE = 0x0300, // 0, 0, 32
- COLOR_DARKBLUE = 0x0700, // 0, 0, 64
- COLOR_MEDIUMBLUE = 0x0F00, // 0, 0, 128
- COLOR_LIGHTBLUE = 0x1700, // 0, 0, 192
- COLOR_BLUE = 0x1F00, // 0, 0, 255
-
- COLOR_VERYDARKYELLOW = 0xE018, // 32, 32, 0
- COLOR_DARKYELLOW = 0xE039, // 64, 64, 0
- COLOR_MEDIUMYELLOW = 0xE07B, // 128, 128, 0
- COLOR_LIGHTYELLOW = 0xE0BD, // 192, 192, 0
- COLOR_YELLOW = 0xE0FF, // 255, 255, 0
-
- COLOR_VERYDARKCYAN = 0xE300, // 0, 32, 32
- COLOR_DARKCYAN = 0xE701, // 0, 64, 64
- COLOR_MEDIUMCYAN = 0xEF03, // 0, 128, 128
- COLOR_LIGHTCYAN = 0xF705, // 0, 192, 192
- COLOR_CYAN = 0xFF07, // 0, 255, 255
-
- COLOR_VERYDARKMAGENTA = 0x0318, // 32, 0, 32
- COLOR_DARKMAGENTA = 0x0738, // 64, 0, 64
- COLOR_MEDIUMMAGENTA = 0x0F78, // 128, 0, 128
- COLOR_LIGHTMAGENTA = 0x17B8, // 192, 0, 192
- COLOR_MAGENTA = 0x1FF8, // 255, 0, 255
-};
-
-class ILI9341
+class ILI9341 : public IDisplay
{
public:
// *************************************************************************
// *** Constructor *****************************************************
// *************************************************************************
- ILI9341(SPI_HandleTypeDef* in_hspi);
-
- // *************************************************************************
- // *** Write byte to SPI ***********************************************
- // *************************************************************************
- inline void SpiWrite(uint8_t c);
+ explicit ILI9341(int32_t in_width, int32_t in_height, ISpi& in_spi, IGpio& disp_cs, IGpio& disp_dc, IGpio* disp_rst = nullptr) :
+ IDisplay(in_width, in_height), spi(in_spi), display_cs(disp_cs), display_dc(disp_dc), display_rst(disp_rst) {};
// *************************************************************************
- // *** Write byte stream to SPI ****************************************
- // *************************************************************************
- void SpiWriteStream(uint8_t* data, uint32_t n);
-
- // *************************************************************************
- // *** Write command to SPI ********************************************
- // *************************************************************************
- inline void WriteCommand(uint8_t c);
-
- // *************************************************************************
- // *** Write data to SPI ***********************************************
+ // *** Init screen *****************************************************
// *************************************************************************
- inline void WriteData(uint8_t c);
+ virtual Result Init(void);
// *************************************************************************
// *** Write data steram to SPI ****************************************
// *************************************************************************
- void WriteDataStream(uint8_t* data, uint32_t n);
+ virtual Result WriteDataStream(uint8_t* data, uint32_t n);
// *************************************************************************
// *** Check SPI transfer status ****************************************
// *************************************************************************
- bool IsTransferComplete(void);
+ virtual bool IsTransferComplete(void);
// *************************************************************************
// *** Pull up CS line for LCD ******************************************
// *************************************************************************
- void StopTransfer(void);
-
- // *************************************************************************
- // *** Init screen *****************************************************
- // *************************************************************************
- void Init(void);
+ virtual Result StopTransfer(void);
// *************************************************************************
// *** Set output window ***********************************************
// *************************************************************************
- void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
-
- // *************************************************************************
- // *** Pass 8-bit (each) R,G,B, get back 16-bit packed color ***********
- // *************************************************************************
- uint16_t GetColor565(uint8_t r, uint8_t g, uint8_t b);
+ virtual Result SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
// *************************************************************************
// *** Set screen orientation ******************************************
// *************************************************************************
- void SetRotation(uint8_t r);
+ virtual Result SetRotation(IDisplay::Rotation r);
// *************************************************************************
// *** Write color to screen *******************************************
// *************************************************************************
- void PushColor(uint16_t color);
+ virtual Result PushColor(uint16_t color);
// *************************************************************************
// *** Draw one pixel on screen ***************************************
// *************************************************************************
- void DrawPixel(int16_t x, int16_t y, uint16_t color);
+ virtual Result DrawPixel(int16_t x, int16_t y, uint16_t color);
// *************************************************************************
// *** Draw vertical line **********************************************
// *************************************************************************
- void DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
+ virtual Result DrawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
// *************************************************************************
// *** Draw horizontal line ********************************************
// *************************************************************************
- void DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
-
- // *************************************************************************
- // *** Fill full screen ************************************************
- // *************************************************************************
- void FillScreen(uint16_t color);
+ virtual Result DrawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
// *************************************************************************
// *** Fill rectangle on screen ****************************************
// *************************************************************************
- void FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
+ virtual Result FillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
// *************************************************************************
// *** Invert display **************************************************
// *************************************************************************
- void InvertDisplay(bool invert);
-
- // *************************************************************************
- // *** Read data from SPI **********************************************
- // *************************************************************************
- inline uint8_t SpiRead(void);
+ virtual Result InvertDisplay(bool invert);
- // *************************************************************************
- // *** Read data from display ******************************************
- // *************************************************************************
- inline uint8_t ReadData(void);
+ private:
+ // Handle to SPI used for display
+ ISpi& spi;
+ // Reference to CS and DC - mandatory
+ IGpio& display_cs;
+ IGpio& display_dc;
+ // Pointer to Reset - optional
+ IGpio* display_rst = nullptr;
// *************************************************************************
- // *** Send read command ad read result ********************************
+ // *** Private: Write data to SPI **************************************
// *************************************************************************
- uint8_t ReadCommand(uint8_t c);
+ inline void WriteData(uint8_t c);
// *************************************************************************
- // *** Return screen width *********************************************
+ // *** Private: Write command to SPI ***********************************
// *************************************************************************
- inline int32_t GetWidth(void) {return width;}
+ inline void WriteCommand(uint8_t c);
// *************************************************************************
- // *** Return screen height ********************************************
+ // *** Private: Write byte to SPI **************************************
// *************************************************************************
- inline int32_t GetHeight(void) {return height;}
+ inline void SpiWrite(uint8_t c);
// *************************************************************************
- // *** Return byte(s) per pixel ****************************************
+ // *** Private: Read data from SPI *************************************
// *************************************************************************
- inline int32_t GetBytesPerPixel(void) {return byte_per_pixel;}
+ inline uint8_t SpiRead(void);
// *************************************************************************
- // *** Return max line *************************************************
+ // *** Private: Read data from display *********************************
// *************************************************************************
- static constexpr int32_t GetMaxLine(void) {return TFT_WIDTH > TFT_HEIGHT ? TFT_WIDTH : TFT_HEIGHT;}
+ inline uint8_t ReadData(void);
// *************************************************************************
- // *** Return max line *************************************************
+ // *** Private: Send read command ad read result ***********************
// *************************************************************************
- static constexpr int32_t GetMaxBpp(void) {return TFT_BPP;}
-
- private:
-
- // Display width
- static const int32_t TFT_WIDTH = 320;
- // Display height
- static const int32_t TFT_HEIGHT = 240;
- // Display byte per pixel
- static const int32_t TFT_BPP = 2;
-
- // Handle to screen SPI
- SPI_HandleTypeDef* hspi = nullptr;
-
- // Width
- int32_t width = TFT_WIDTH;
- // Height
- int32_t height = TFT_HEIGHT;
- // Byte(s) per pixel
- int32_t byte_per_pixel = TFT_BPP;
-
- // Rotation
- uint32_t rotation = 0U;
+ uint8_t ReadCommand(uint8_t c);
};
#endif
diff --git a/Display/Strings.cpp b/Display/Strings.cpp
index e600867..d7fc910 100644
--- a/Display/Strings.cpp
+++ b/Display/Strings.cpp
@@ -22,6 +22,8 @@
#include "Fonts.h"
#include <cstring> // for strlen()
+#include <cstring>
+#include <stdarg.h>
// *****************************************************************************
// *****************************************************************************
@@ -116,6 +118,21 @@ void String::SetString(const char* str)
}
// *****************************************************************************
+// *** SetString ***********************************************************
+// *****************************************************************************
+void String::SetString(char* buf, uint32_t len, const char* format, ...)
+{
+ // Argument list
+ va_list arglist;
+ // Create string
+ va_start(arglist, format);
+ vsnprintf(buf, len, format, arglist);
+ va_end(arglist);
+ // Update string
+ SetString(buf);
+}
+
+// *****************************************************************************
// *** Put line in buffer **************************************************
// *****************************************************************************
void String::DrawInBufW(uint16_t* buf, int32_t n, int32_t line, int32_t start_x)
diff --git a/Display/Strings.h b/Display/Strings.h
index 4dd5633..1fea746 100644
--- a/Display/Strings.h
+++ b/Display/Strings.h
@@ -94,6 +94,11 @@ class String : public VisObject
void SetString(const char* str);
// *************************************************************************
+ // *** SetString *******************************************************
+ // *************************************************************************
+ void SetString(char* buffer, uint32_t n, const char* format, ...);
+
+ // *************************************************************************
// *** SetColor ********************************************************
// *************************************************************************
void SetColor(uint32_t tc, uint32_t bgc = 0U, bool is_trnsp = true);
diff --git a/Display/XPT2046.cpp b/Display/XPT2046.cpp
index 0e7f396..f013f3d 100644
--- a/Display/XPT2046.cpp
+++ b/Display/XPT2046.cpp
@@ -21,12 +21,33 @@
#include <XPT2046.h>
// *****************************************************************************
-// *** Init touchscreen ****************************************************
+// *** Public: Init touchscreen ********************************************
// *****************************************************************************
-void XPT2046::Init(void)
+Result XPT2046::Init(void)
{
+ // Variable for original SPI clock
+ ISpi::Mode spi_mode = ISpi::MODE_0;
+ // Get original SPI clock
+ Result mode_result = spi.GetMode(spi_mode);
+ // If we successfully received speed
+ if(mode_result.IsGood())
+ {
+ // Set MODE_0 for SPI
+ mode_result = spi.SetMode(ISpi::MODE_0);
+ }
+ // Variable for original SPI clock
+ uint32_t spi_clock = 0U;
+ // Get original SPI clock
+ Result speed_result = spi.GetSpeed(spi_clock);
+ // If we successfully received speed
+ if(speed_result.IsGood())
+ {
+ // Set SPI speed - max 2 MHz
+ speed_result = spi.SetSpeed(2000000U);
+ }
+
// Pull down CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ touch_cs.SetLow();
// Send ON command
SpiWrite(TON);
// Send empty byte for skip answer
@@ -34,30 +55,65 @@ void XPT2046::Init(void)
// Send empty byte for skip answer
SpiWrite(EMP);
// Pull up CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+ touch_cs.SetHigh();
+
+ // Restore original SPI clock
+ if(speed_result.IsGood())
+ {
+ spi.SetSpeed(spi_clock);
+ }
+ // Restore original SPI mode
+ if(mode_result.IsGood())
+ {
+ spi.SetMode(spi_mode);
+ }
+
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
-// *** If touched - return true. *******************************************
+// *** Public: If touched - return true. ***********************************
// *****************************************************************************
-bool XPT2046::IsTouch(void)
+bool XPT2046::IsTouched(void)
{
- // Check T_IRQ input and return state
- return(HAL_GPIO_ReadPin(T_IRQ_GPIO_Port, T_IRQ_Pin) == GPIO_PIN_RESET);
+ // Check T_IRQ input
+ return touch_irq.IsLow();
}
// *****************************************************************************
-// *** Get X and Y coordinates. If touched - return true. ******************
+// *** Public: Get X and Y coordinates. If touched - return true. **********
// *****************************************************************************
bool XPT2046::GetRawXY(int32_t& x, int32_t& y)
{
// Return value
bool ret = false;
- // If touch present
- if(HAL_GPIO_ReadPin(T_IRQ_GPIO_Port, T_IRQ_Pin) == GPIO_PIN_RESET)
+ // If touch properly initialized and actual touch present
+ if(IsTouched())
{
+ // Variable for original SPI clock
+ uint32_t spi_clock = 0U;
+ // Get original SPI clock
+ Result speed_result = spi.GetSpeed(spi_clock);
+ // If we successfully received speed
+ if(speed_result.IsGood())
+ {
+ // Set SPI speed - max 2 MHz
+ speed_result = spi.SetSpeed(2000000U);
+ }
+ // Variable for original SPI clock
+ ISpi::Mode spi_mode = ISpi::MODE_0;
+ // Get original SPI clock
+ Result mode_result = spi.GetMode(spi_mode);
+ // If we successfully received speed
+ if(mode_result.IsGood())
+ {
+ // Set MODE_0 for SPI
+ mode_result = spi.SetMode(ISpi::MODE_0);
+ }
+
// Pull down CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ touch_cs.SetLow();
// Request X coordinate
SpiWrite(CHX);
// Receive High byte for X
@@ -68,10 +124,10 @@ bool XPT2046::GetRawXY(int32_t& x, int32_t& y)
// second rise edge
x >>= 3;
// Pull up CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+ touch_cs.SetHigh();
// Pull down CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_RESET);
+ touch_cs.SetLow();
// Request Y coordinate
SpiWrite(CHY);
// Receive High byte for Y
@@ -82,7 +138,18 @@ bool XPT2046::GetRawXY(int32_t& x, int32_t& y)
// second rise edge
y >>= 3;
// Pull up CS
- HAL_GPIO_WritePin(TOUCH_CS_GPIO_Port, TOUCH_CS_Pin, GPIO_PIN_SET);
+ touch_cs.SetHigh();
+
+ // Restore original SPI clock
+ if(speed_result.IsGood())
+ {
+ spi.SetSpeed(spi_clock);
+ }
+ // Restore original SPI mode
+ if(mode_result.IsGood())
+ {
+ spi.SetMode(spi_mode);
+ }
// Touch present
ret = true;
@@ -92,7 +159,7 @@ bool XPT2046::GetRawXY(int32_t& x, int32_t& y)
}
// *****************************************************************************
-// *** Get X and Y coordinates. If touched - return true. ******************
+// *** Public: Get X and Y coordinates. If touched - return true. **********
// *****************************************************************************
bool XPT2046::GetXY(int32_t& x, int32_t& y)
{
@@ -111,35 +178,37 @@ bool XPT2046::GetXY(int32_t& x, int32_t& y)
}
// *****************************************************************************
-// *** SetCalibrationConsts ************************************************
+// *** Public: SetCalibrationConsts ****************************************
// *****************************************************************************
-void XPT2046::SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby)
+Result XPT2046::SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby)
{
// Save calibration constants
kx = nkx;
ky = nky;
bx = nbx;
by = nby;
+ // Always Ok
+ return Result::RESULT_OK;
}
// *****************************************************************************
-// *** Write byte to SPI ***************************************************
+// *** Private: Write byte to SPI ******************************************
// *****************************************************************************
inline void XPT2046::SpiWrite(uint8_t c)
{
// Call HAL function for send byte by SPI
- (void) HAL_SPI_Transmit(hspi, &c, sizeof(c), 1U);
+ spi.Write(&c, sizeof(c));
}
// *****************************************************************************
-// *** Write and read byte to/from SPI *************************************
+// *** Private: Write and read byte to/from SPI ****************************
// *****************************************************************************
inline uint8_t XPT2046::SpiWriteRead(uint8_t c)
{
// Temporary variable for receive byte
- uint8_t rcv;
+ uint8_t rcv = 0U;
// Call HAL function for send/receive byte by SPI
- (void) HAL_SPI_TransmitReceive(hspi, &c, &rcv, sizeof(uint8_t), 1U);
+ spi.Transfer(&c, &rcv, sizeof(uint8_t));
// Return received byte
return rcv;
}
diff --git a/Display/XPT2046.h b/Display/XPT2046.h
index 51b35a5..3a5014f 100644
--- a/Display/XPT2046.h
+++ b/Display/XPT2046.h
@@ -42,6 +42,9 @@
// *** Includes ************************************************************
// *****************************************************************************
#include "DevCfg.h"
+#include "ITouchscreen.h"
+#include "ISpi.h"
+#include "IGpio.h"
// *****************************************************************************
// *** Defines *************************************************************
@@ -49,51 +52,45 @@
// *****************************************************************************
// * XPT2046 class. Implements work with XPT2046 resistive touchscreen.
-class XPT2046
+class XPT2046 : public ITouchscreen
{
public:
- // Coefficient for calibration
- const static int32_t COEF = 100;
-
// *************************************************************************
- // *** Constructor *****************************************************
+ // *** Public: Constructor *********************************************
// *************************************************************************
- // * This class hasn't task inside. For use this class user must provide
- // * handle to SPI. Previously I think shape SPI between TFT and Touch.
- // * But now it is two different SPI. Anyway main idea it is use this class
- // * in DisplayDrv class for find pressed VisObjects.
- XPT2046(SPI_HandleTypeDef* in_hspi) : hspi(in_hspi) {};
+ explicit XPT2046(ISpi& in_spi, IGpio& in_touch_cs, IGpio& in_touch_irq) :
+ spi(in_spi), touch_cs(in_touch_cs), touch_irq(in_touch_irq) {};
// *************************************************************************
- // *** Init ************************************************************
+ // *** Public: Init ****************************************************
// *************************************************************************
// * Init function. Send init sequence to touchscreen controller.
- void Init(void);
+ virtual Result Init(void);
// *************************************************************************
- // *** IsTouch *********************************************************
+ // *** Public: IsTouch *************************************************
// *************************************************************************
// * Check touched or not by T_IRQ pin. Return true if touched.
- bool IsTouch(void);
+ virtual bool IsTouched(void);
// *************************************************************************
- // *** GetRawXY ********************************************************
+ // *** Public: GetRawXY ************************************************
// *************************************************************************
// * Return raw X and Y coordinates. If touched - return true.
- bool GetRawXY(int32_t& x, int32_t& y);
+ virtual bool GetRawXY(int32_t& x, int32_t& y);
// *************************************************************************
- // *** GetXY ***********************************************************
+ // *** Public: GetXY ***************************************************
// *************************************************************************
// * Return recalculated using calibration constants X and Y coordinates.
// * If touched - return true. Can be used for second calibration.
- bool GetXY(int32_t& x, int32_t& y);
+ virtual bool GetXY(int32_t& x, int32_t& y);
// *************************************************************************
- // *** SetCalibrationConsts ********************************************
+ // *** Public: SetCalibrationConsts ************************************
// *************************************************************************
// * Set calibration constants. Must be call for calibration touchscreen.
- void SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby);
+ virtual Result SetCalibrationConsts(int32_t nkx, int32_t nky, int32_t nbx, int32_t nby);
private:
// Turn touchscreen ON
@@ -106,7 +103,10 @@ class XPT2046
const static uint8_t CHY = 0xD0;
// Handle to SPI used for touchscreen
- SPI_HandleTypeDef* hspi = nullptr;
+ ISpi& spi;
+ // Reference to CS and IRQ - mandatory
+ IGpio& touch_cs;
+ IGpio& touch_irq;
// Display width and height offset
int32_t kx = -1097, ky = -1499;
@@ -114,13 +114,13 @@ class XPT2046
int32_t bx = 334, by = 259;
// *************************************************************************
- // *** SpiWrite ********************************************************
+ // *** Private: SpiWrite ***********************************************
// *************************************************************************
// * Write byte to SPI
inline void SpiWrite(uint8_t c);
// *************************************************************************
- // *** SpiWriteRead ****************************************************
+ // *** Private: SpiWriteRead *******************************************
// *************************************************************************
// * Write/read byte from/to SPI
inline uint8_t SpiWriteRead(uint8_t c);