F439_CPP_SPI_RA8875_TFT_LCD_04 1.0
STM32F439 SPI RA8875 7-inch TFT display with FRAM-backed touch calibration, built on the STM32_GFX, STM32_RA8875 and STM32_MB85RS64V libraries
Loading...
Searching...
No Matches
touchCalibrationStorage.cpp
Go to the documentation of this file.
1
9#include <stdio.h>
10#include <string.h>
11#include "main.h"
13
14namespace {
15
17const uint32_t BLOCK_BYTES = CFG_EEPROM_TOUCHSCREEN_CALIBRATED + 1;
18
20const uint32_t HEADER_BYTES = 12;
21
23const uint32_t HEADER_MAGIC = 0x314C4143;
24
26const uint16_t HEADER_VERSION = 1;
27
34uint32_t crc32(const uint8_t *data, uint32_t length) {
35 uint32_t crc = 0xFFFFFFFFu;
36 for (uint32_t i = 0; i < length; i++) {
37 crc ^= data[i];
38 for (int bit = 0; bit < 8; bit++) {
39 crc = (crc & 1u) ? ((crc >> 1) ^ 0xEDB88320u) : (crc >> 1);
40 }
41 }
42 return ~crc;
43}
44
53bool storageRead(void *ctx, uint32_t address, uint8_t *data, uint32_t length) {
54 MB85RS64V *fram = static_cast<MB85RS64V *>(ctx);
55 if (fram == nullptr || address >= MB85RS64V::SIZE_BYTES) {
56 return false;
57 }
58 return fram->read(static_cast<uint16_t>(address), data, length);
59}
60
71bool storageWrite(void *ctx, uint32_t address, const uint8_t *data, uint32_t length) {
72 MB85RS64V *fram = static_cast<MB85RS64V *>(ctx);
73 if (fram == nullptr || address >= MB85RS64V::SIZE_BYTES ||
74 !fram->write(static_cast<uint16_t>(address), data, length)) {
75 printf("Calibration storage write failed (address 0x%04lX, %lu bytes)\r\n", (unsigned long) address,
76 (unsigned long) length);
77 Error_Handler();
78 return false;
79 }
80 return true;
81}
82
83} // namespace
84
95 if (display == nullptr || fram == nullptr) {
96 printf("touchCalibrationAttachStorage: display or FRAM object is missing\r\n");
97 Error_Handler();
98 return;
99 }
100 display->setCalibrationStorage(storageRead, storageWrite, fram, MB85RS64V::SIZE_BYTES);
101}
102
115 if (display == nullptr || fram == nullptr || matrix == nullptr) {
116 printf("touchCalibrationLoad: missing argument\r\n");
117 Error_Handler();
118 return false;
119 }
120
121 uint8_t header[HEADER_BYTES];
122 if (!fram->read(TOUCH_CAL_HEADER_ADDRESS, header, HEADER_BYTES)) {
123 printf("Stored calibration: header could not be read\r\n");
124 Error_Handler();
125 return false;
126 }
127
128 const uint32_t magic = (uint32_t) header[0] | ((uint32_t) header[1] << 8) | ((uint32_t) header[2] << 16) |
129 ((uint32_t) header[3] << 24);
130 const uint16_t version = (uint16_t) (header[4] | (header[5] << 8));
131 const uint16_t length = (uint16_t) (header[6] | (header[7] << 8));
132 const uint32_t storedCrc = (uint32_t) header[8] | ((uint32_t) header[9] << 8) | ((uint32_t) header[10] << 16) |
133 ((uint32_t) header[11] << 24);
134
135 if (magic != HEADER_MAGIC) {
136 printf("Stored calibration: none (no marker in the FRAM)\r\n");
137 return false;
138 }
139 if (version != HEADER_VERSION || length != BLOCK_BYTES) {
140 printf("Stored calibration: unknown format (version %u, length %u)\r\n", (unsigned) version,
141 (unsigned) length);
142 return false;
143 }
144
145 uint8_t block[BLOCK_BYTES];
146 if (!fram->read(TOUCH_CAL_ADDRESS, block, BLOCK_BYTES)) {
147 printf("Stored calibration: matrix block could not be read\r\n");
148 Error_Handler();
149 return false;
150 }
151 if (crc32(block, BLOCK_BYTES) != storedCrc) {
152 printf("Stored calibration: checksum does not match, data is damaged\r\n");
153 return false;
154 }
155
156 if (!display->readCalibration(TOUCH_CAL_ADDRESS, matrix)) {
157 printf("Stored calibration: the library does not report it as calibrated\r\n");
158 return false;
159 }
160 if (matrix->Divider == 0) {
161 printf("Stored calibration: matrix divider is zero, not usable\r\n");
162 return false;
163 }
164 return true;
165}
166
176 if (display == nullptr || fram == nullptr || matrix == nullptr) {
177 printf("touchCalibrationSave: missing argument\r\n");
178 Error_Handler();
179 return false;
180 }
181
182 // Matrix first: the library writes the seven values and then its flag byte
183 display->writeCalibration(TOUCH_CAL_ADDRESS, matrix);
184
185 uint8_t block[BLOCK_BYTES];
186 if (!fram->read(TOUCH_CAL_ADDRESS, block, BLOCK_BYTES)) {
187 printf("Calibration save: matrix block could not be read back\r\n");
188 Error_Handler();
189 return false;
190 }
191 const uint32_t crc = crc32(block, BLOCK_BYTES);
192
193 // Header last: it is what marks the stored matrix as valid
194 uint8_t header[HEADER_BYTES];
195 header[0] = (uint8_t) (HEADER_MAGIC & 0xFF);
196 header[1] = (uint8_t) ((HEADER_MAGIC >> 8) & 0xFF);
197 header[2] = (uint8_t) ((HEADER_MAGIC >> 16) & 0xFF);
198 header[3] = (uint8_t) ((HEADER_MAGIC >> 24) & 0xFF);
199 header[4] = (uint8_t) (HEADER_VERSION & 0xFF);
200 header[5] = (uint8_t) (HEADER_VERSION >> 8);
201 header[6] = (uint8_t) (BLOCK_BYTES & 0xFF);
202 header[7] = (uint8_t) (BLOCK_BYTES >> 8);
203 header[8] = (uint8_t) (crc & 0xFF);
204 header[9] = (uint8_t) ((crc >> 8) & 0xFF);
205 header[10] = (uint8_t) ((crc >> 16) & 0xFF);
206 header[11] = (uint8_t) ((crc >> 24) & 0xFF);
207 if (!fram->write(TOUCH_CAL_HEADER_ADDRESS, header, HEADER_BYTES)) {
208 printf("Calibration save: header could not be written\r\n");
209 Error_Handler();
210 return false;
211 }
212
213 // Prove it: load it back and compare with what was saved
214 tsMatrix_t check;
215 if (!touchCalibrationLoad(display, fram, &check)) {
216 return false;
217 }
218 return memcmp(&check, matrix, sizeof(tsMatrix_t)) == 0;
219}
#define CFG_EEPROM_TOUCHSCREEN_CALIBRATED
EEPROM Storage Location.
Class that stores state and functions for interacting with the RA8875 display controller.
bool readCalibration(int location, tsMatrix_t *matrixPtr)
void writeCalibration(int location, tsMatrix_t *matrixPtr)
void setCalibrationStorage(StorageReadFn read, StorageWriteFn write, void *ctx, uint32_t sizeBytes)
Driver for one MB85RS64V SPI FRAM (8192 bytes) on an STM32 HAL SPI bus.
Definition MB85RS64V.hpp:78
bool read(uint16_t address, uint8_t *buffer, size_t length)
Reads bytes from the FRAM array (READ, 03h).
static constexpr uint16_t SIZE_BYTES
Capacity in bytes (8192; addresses 0x0000 to 0x1FFF).
Definition MB85RS64V.hpp:81
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.
: Header for main.c file. This file contains the common defines of the application.
int32_t Divider
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.
Stores the touch calibration matrix in the MB85RS64V FRAM and checks it when loading.
constexpr uint16_t TOUCH_CAL_ADDRESS
FRAM address of the calibration matrix block written by the RA8875 library.
constexpr uint16_t TOUCH_CAL_HEADER_ADDRESS
FRAM address of the 12-byte validity header.