13#include "MB85RS64V.hpp"
15#ifdef TOUCH_CALIBRATION_ENABLE
27static bool touchMatrixValid =
false;
61 tft =
new (std::nothrow)
Adafruit_RA8875(halSPI, RA8875_CS_GPIO_Port, RA8875_CS_Pin,
62 LCD_RESET_GPIO_Port, LCD_RESET_Pin);
64 printf(
"RA8875 object could not be allocated (out of heap)\r\n");
70 printf(
"RA8875 Found\r\n");
72 printf(
"RA8875 not found (expected chip ID 0x75)\r\n");
105 if (tft ==
nullptr) {
106 printf(
"ERROR: testLCD() called before initTest()\r\n");
111 printf(
"================ Graphics Mode =============\r\n");
123 printf(
"FillSreen White\r\n");
129 printf(
"Start: Play with PWM\r\n");
131 for (uint8_t i=255; i!=0; i-=5 )
136 for (uint8_t i=0; i!=255; i+=5 )
143 printf(
"END: Play with PWM\r\n");
146 printf(
"FillSreen Red\r\n");
149 printf(
"FillSreen Yellow\r\n");
152 printf(
"FillSreen Green\r\n");
155 printf(
"FillSreen Cyan\r\n");
158 printf(
"FillSreen Magenta\r\n");
161 printf(
"FillSreen Black\r\n");
166 printf(
"drawCircle\r\n");
168 printf(
"fillCircle\r\n");
173 printf(
"fillRect\r\n");
176 printf(
"drawRect\r\n");
179 printf(
"fillRoundRect\r\n");
182 printf(
"drawPixel\r\n");
185 printf(
"drawPixel\r\n");
188 printf(
"drawLine\r\n");
191 printf(
"drawTriangle\r\n");
194 printf(
"fillTriangle\r\n");
197 printf(
"drawEllipse\r\n");
200 printf(
"fillEllipse\r\n");
204 printf(
"drawCurve\r\n");
207 printf(
"fillCurve\r\n");
210 printf(
"================ Text Mode =============\r\n");
215 printf(
"fillScreen\r\n");
232 printf(
"Render lots of Texts\r\n");
233 char string[80] =
"Hello, World! ";
302 fram =
new (std::nothrow)
MB85RS64V(halSPI, MB85RS64_CS_GPIO_Port, MB85RS64_CS_Pin);
303 if (fram ==
nullptr) {
304 printf(
"MB85RS64V object could not be allocated (out of heap)\r\n");
314 const int ID_READ_ATTEMPTS = 3;
317 for (
int attempt = 1; attempt <= ID_READ_ATTEMPTS; attempt++) {
319 printf(
"MB85RS64V ID read failed after begin() (HAL status %d), attempt %d of %d\r\n",
320 (
int) fram->
lastStatus(), attempt, ID_READ_ATTEMPTS);
321 }
else if (memcmp(
id, expectedId,
sizeof(expectedId)) != 0) {
322 printf(
"MB85RS64V ID read gave %02X %02X %02X %02X (expected 04 7F 03 02), attempt %d of %d\r\n",
323 id[0],
id[1],
id[2],
id[3], attempt, ID_READ_ATTEMPTS);
325 printf(
"MB85RS64V Found, ID: %02X %02X %02X %02X\r\n",
id[0],
id[1],
id[2],
id[3]);
330 printf(
"MB85RS64V ID could not be read correctly after %d attempts\r\n", ID_READ_ATTEMPTS);
334 printf(
"MB85RS64V not found (expected ID 04 7F 03 02): check HOLD/WP, CS (PB10) and power\r\n");
339 const bool idRead = fram->
readId(
id);
340 printf(
" ID read %s, bytes: %02X %02X %02X %02X, last HAL status %d\r\n", idRead ?
"OK" :
"FAILED",
341 id[0],
id[1],
id[2],
id[3], (int) fram->
lastStatus());
342 printf(
" SPI1: mode %s, polarity %s, phase %s, data size %s, NSS %s, prescaler 0x%02lX\r\n",
343 halSPI->Init.Mode == SPI_MODE_MASTER ?
"master" :
"NOT master",
344 halSPI->Init.CLKPolarity == SPI_POLARITY_LOW ?
"low" :
"high",
345 halSPI->Init.CLKPhase == SPI_PHASE_1EDGE ?
"1 edge" :
"2 edge",
346 halSPI->Init.DataSize == SPI_DATASIZE_8BIT ?
"8-bit" :
"NOT 8-bit",
347 halSPI->Init.NSS == SPI_NSS_SOFT ?
"soft" :
"NOT soft",
348 (
unsigned long) halSPI->Init.BaudRatePrescaler);
352 uint8_t status = 0xFF;
353 const bool statusRead = fram->
readStatus(&status);
354 printf(
" Status register read %s: %02X (FF = no answer, 00..8C = chip is answering)\r\n",
355 statusRead ?
"OK" :
"FAILED", status);
378 if (fram ==
nullptr) {
379 printf(
"ERROR: testFRAM() called before a successful initFRAM()\r\n");
385 if (!fram->
read(0x0000, before,
sizeof(before))) {
386 printf(
"FRAM read failed (HAL status %d)\r\n", (
int) fram->
lastStatus());
390 printf(
"FRAM at 0x0000 before this boot:");
391 for (
size_t i = 0; i <
sizeof(before); i++) {
392 printf(
" %02X", before[i]);
397 uint8_t out[16] = { (uint8_t) (before[0] + 1), 0xA5, 0x5A, 0xFF, 0x00,
'M',
'C',
'T',
'F',
'R',
'A',
'M', 1, 2, 3, 4 };
398 if (!fram->
write(0x0000, out,
sizeof(out))) {
399 printf(
"FRAM write failed (HAL status %d)\r\n", (
int) fram->
lastStatus());
404 uint8_t in[16] = { 0 };
405 if (!fram->
read(0x0000, in,
sizeof(in))) {
406 printf(
"FRAM read-back failed (HAL status %d)\r\n", (
int) fram->
lastStatus());
410 printf(
"FRAM read back: ");
411 for (
size_t i = 0; i <
sizeof(in); i++) {
412 printf(
" %02X", in[i]);
416 for (
size_t i = 0; i <
sizeof(out); i++) {
417 if (in[i] != out[i]) {
418 printf(
"FRAM read-back MISMATCH at byte %u\r\n", (
unsigned) i);
423 printf(
"FRAM write/read-back OK, boot count %u\r\n", (
unsigned) out[0]);
443 touchMatrixValid =
false;
445 if (tft ==
nullptr || fram ==
nullptr) {
446 printf(
"ERROR: initTouchCalibration() needs initTest() and initFRAM() to have run first\r\n");
451 printf(
"Reading the stored touch calibration from the FRAM\r\n");
456 printf(
"No usable touch calibration in the FRAM: define TOUCH_CALIBRATION_ENABLE in main.h and calibrate\r\n");
460 touchMatrixValid =
true;
461 printf(
"Touch calibration read from the FRAM: An=%ld Bn=%ld Cn=%ld Dn=%ld En=%ld Fn=%ld Divider=%ld\r\n",
462 (
long) touchMatrix.
An, (
long) touchMatrix.
Bn, (
long) touchMatrix.
Cn, (
long) touchMatrix.
Dn,
463 (
long) touchMatrix.
En, (
long) touchMatrix.
Fn, (
long) touchMatrix.
Divider);
467#ifdef TOUCH_CALIBRATION_ENABLE
469 const uint32_t DEMO_MS = 15000;
471 if (tft ==
nullptr) {
472 printf(
"ERROR: testTouch() called before initTest()\r\n");
486 if (huart ==
nullptr) {
487 printf(
"ERROR: testTouch() needs the terminal UART handle\r\n");
492 if (fram ==
nullptr) {
493 printf(
"ERROR: testTouch() needs the FRAM: initFRAM() has not run\r\n");
503 printf(
"Touch calibration failed after repeated attempts\r\n");
508 printf(
"Touch calibration could not be stored: the data read back from the FRAM differs\r\n");
512 printf(
"Touch calibration stored in the FRAM\r\n");
513 printf(
"Touch calibration done: An=%ld Bn=%ld Cn=%ld Dn=%ld En=%ld Fn=%ld Divider=%ld\r\n",
514 (
long) matrix.
An, (
long) matrix.
Bn, (
long) matrix.
Cn, (
long) matrix.
Dn, (
long) matrix.
En,
515 (
long) matrix.
Fn, (
long) matrix.
Divider);
517 printf(
"Touch the screen: red dots follow your finger for %lu seconds\r\n", (
unsigned long) (DEMO_MS / 1000));
520 const uint32_t start = HAL_GetTick();
521 while ((HAL_GetTick() - start) < DEMO_MS) {
527 tsPoint_t raw = { (int32_t) rx, (int32_t) ry };
530 printf(
"Touch conversion failed (divider is zero)\r\n");
535 printf(
"raw %u,%u -> screen %ld,%ld\r\n", (
unsigned) rx, (
unsigned) ry, (
long) pos.
x, (
long) pos.
y);
536 if (pos.
x >= 0 && pos.
x < tft->
width() && pos.
y >= 0 && pos.
y < tft->
height()) {
#define RA8875_GREEN
Green Color.
#define RA8875_YELLOW
Yellow Color.
#define RA8875_MAGENTA
Magenta Color.
#define RA8875_CYAN
Cyan Color.
#define RA8875_PWM_CLK_DIV1024
See datasheet.
#define RA8875_BLACK
Black Color.
#define RA8875_WHITE
White Color.
#define RA8875_RED
Red Color.
#define RA8875_BLUE
Blue Color.
Class that stores state and functions for interacting with the RA8875 display controller.
void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, uint16_t color)
boolean touchRead(uint16_t *x, uint16_t *y)
void drawPixel(int16_t x, int16_t y, uint16_t color)
void touchEnable(boolean on)
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color)
void fillCircle(int16_t x, int16_t y, int16_t r, uint16_t color)
void fillScreen(uint16_t color)
void fillCurve(int16_t xCenter, int16_t yCenter, int16_t longAxis, int16_t shortAxis, uint8_t curvePart, uint16_t color)
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
void fillEllipse(int16_t xCenter, int16_t yCenter, int16_t longAxis, int16_t shortAxis, uint16_t color)
void cursorBlink(uint8_t rate)
boolean begin(enum RA8875sizes s)
void drawCircle(int16_t x, int16_t y, int16_t r, uint16_t color)
void textEnlarge(uint8_t scale)
void textSetCursor(uint16_t x, uint16_t y)
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
void drawCurve(int16_t xCenter, int16_t yCenter, int16_t longAxis, int16_t shortAxis, uint8_t curvePart, uint16_t color)
void textColor(uint16_t foreColor, uint16_t bgColor)
void displayOn(boolean on)
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color)
void textTransparent(uint16_t foreColor)
void PWM1config(boolean on, uint8_t clock)
void textWrite(const char *buffer, uint16_t len=0)
void drawEllipse(int16_t xCenter, int16_t yCenter, int16_t longAxis, int16_t shortAxis, uint16_t color)
Driver for one MB85RS64V SPI FRAM (8192 bytes) on an STM32 HAL SPI bus.
bool read(uint16_t address, uint8_t *buffer, size_t length)
Reads bytes from the FRAM array (READ, 03h).
static constexpr size_t ID_LENGTH
Number of bytes returned by readId().
bool readStatus(uint8_t *status)
Reads the status register (RDSR, 05h).
HAL_StatusTypeDef lastStatus() const
HAL status of the most recent failed SPI call (HAL_OK if none has failed). Because a failed command i...
bool write(uint16_t address, const uint8_t *data, size_t length)
Writes bytes to the FRAM array (WREN, then WRITE, 02h); a retry repeats both steps.
bool begin()
Checks the SPI setup and the chip's identity, and leaves writes disabled.
bool readId(uint8_t *id)
Reads the four-byte device ID (RDID, 9Fh).
C-callable entry points into the C++ RA8875 display code.
bool initTouchCalibration(void)
Reads the touch calibration stored in the FRAM and reports it on the redirected USART.
void testFRAM(void)
Shows that the FRAM keeps its data, then does a write and read-back test.
void testLCD(bool buildTest)
Runs one of the two display demonstrations.
void initTest(SPI_HandleTypeDef *halSPI)
Creates the display object and starts the RA8875 controller.
void initFRAM(SPI_HandleTypeDef *halSPI)
Creates the FRAM driver object and checks that the chip answers.
void testTouch(UART_HandleTypeDef *huart)
Enables touch, runs the three-point calibration and shows the result.
Stores the touch calibration matrix in the MB85RS64V FRAM and checks it when loading.
bool touchCalibrationSave(Adafruit_RA8875 *display, MB85RS64V *fram, tsMatrix_t *matrix)
Saves the calibration matrix to the FRAM and checks it by reading it back.
bool touchCalibrationLoad(Adafruit_RA8875 *display, MB85RS64V *fram, tsMatrix_t *matrix)
Loads the calibration matrix from the FRAM if a valid one is stored.
void touchCalibrationAttachStorage(Adafruit_RA8875 *display, MB85RS64V *fram)
Registers the FRAM read and write callbacks with the display library.
Three-point touch-screen calibration for the RA8875's resistive panel.
bool touchCalibrationRun(Adafruit_RA8875 *display, UART_HandleTypeDef *uart, tsMatrix_t *matrix)
Runs the interactive calibration: draws three targets one at a time, waits for the user to touch each...
bool touchCalibrationApply(const tsMatrix_t *matrix, const tsPoint_t *raw, tsPoint_t *display)
Converts one raw touch reading into a display pixel position.