Nuvoton
/
NuMaker-mbed-emWin-example
NuMaker emWin HMI
tslib/ts_calibrate.c@10:c8165817d92a, 6 months ago (annotated)
- Committer:
- csyang2
- Date:
- Mon Mar 04 15:47:41 2024 +0800
- Revision:
- 10:c8165817d92a
- Parent:
- 9:1286ec7f3230
Support NuMaker-IoT-M467
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
csyang2 |
1:c0f972361605 | 1 | /* |
csyang2 |
9:1286ec7f3230 | 2 | * ts_calibrate.c |
csyang2 |
1:c0f972361605 | 3 | * |
csyang2 |
9:1286ec7f3230 | 4 | * Copyright (C) 2022 Nuvoton Technology |
csyang2 |
1:c0f972361605 | 5 | * |
csyang2 |
1:c0f972361605 | 6 | * |
csyang2 |
1:c0f972361605 | 7 | */ |
csyang2 |
1:c0f972361605 | 8 | #include <stdio.h> |
csyang2 |
1:c0f972361605 | 9 | #include <stdlib.h> |
csyang2 |
9:1286ec7f3230 | 10 | #include <string.h> |
csyang2 |
6:d15151941247 | 11 | #include "NuMicro.h" |
csyang2 |
1:c0f972361605 | 12 | #include "GUI.h" |
csyang2 |
6:d15151941247 | 13 | #include "TouchPanel.h" |
csyang2 |
1:c0f972361605 | 14 | |
csyang2 |
9:1286ec7f3230 | 15 | #define POINT_NUM 5 //7 |
csyang2 |
9:1286ec7f3230 | 16 | #define MAX_NUM 200 |
csyang2 |
9:1286ec7f3230 | 17 | |
csyang2 |
9:1286ec7f3230 | 18 | #define DIFF 5 |
csyang2 |
1:c0f972361605 | 19 | |
csyang2 |
1:c0f972361605 | 20 | typedef struct |
csyang2 |
1:c0f972361605 | 21 | { |
csyang2 |
9:1286ec7f3230 | 22 | int x; |
csyang2 |
9:1286ec7f3230 | 23 | int y; |
csyang2 |
9:1286ec7f3230 | 24 | } coordiante; |
csyang2 |
9:1286ec7f3230 | 25 | |
csyang2 |
9:1286ec7f3230 | 26 | // physical.x, y is the coordinate of H/W for LCD. |
csyang2 |
9:1286ec7f3230 | 27 | // logical x,y is the coordinate of GUI. |
csyang2 |
9:1286ec7f3230 | 28 | coordiante physical[POINT_NUM], logical[POINT_NUM]; |
csyang2 |
9:1286ec7f3230 | 29 | |
csyang2 |
9:1286ec7f3230 | 30 | // samples x, y for calibration. maximum number is adjustable MAX_NUM |
csyang2 |
9:1286ec7f3230 | 31 | // the duration is at least 2 seconds for clicking down, and then release |
csyang2 |
1:c0f972361605 | 32 | |
csyang2 |
9:1286ec7f3230 | 33 | int sampleX[MAX_NUM], sampleY[MAX_NUM]; |
csyang2 |
9:1286ec7f3230 | 34 | /* |
csyang2 |
9:1286ec7f3230 | 35 | // Binary linear equations are as follows, it is the key of solution. |
csyang2 |
9:1286ec7f3230 | 36 | // logical.x = physical.x X A + physical.y X B + C |
csyang2 |
9:1286ec7f3230 | 37 | // logical.y = physical.x X D + physical.y X E + F |
csyang2 |
9:1286ec7f3230 | 38 | // Xl = A x Xp + B x Yp + C |
csyang2 |
9:1286ec7f3230 | 39 | // Yl = D x Xp + E x Yp + F |
csyang2 |
9:1286ec7f3230 | 40 | // We use Xp and Yp to be the multiple of the above equations, and obtain the following equations. |
csyang2 |
9:1286ec7f3230 | 41 | // Xl = A x Xp + B x Yp + C |
csyang2 |
9:1286ec7f3230 | 42 | // Xl x Xp = A x Xp x Xp + B x Yp x Xp + C x Xp |
csyang2 |
9:1286ec7f3230 | 43 | // Xl x Yp = A x Xp x Yp + B x Yp x Yp + C x Yp |
csyang2 |
9:1286ec7f3230 | 44 | // we obtain A, B, C from the above 3 equations, by accumulating the coordinates of 5 points. |
csyang2 |
9:1286ec7f3230 | 45 | // Yl = D x Xp + E x Yp + F |
csyang2 |
9:1286ec7f3230 | 46 | // Yl x Xp = D x Xp x Xp + E x Yp x Xp + F x Xp |
csyang2 |
9:1286ec7f3230 | 47 | // Yl x Yp = D x Xp x Yp + E x Yp x Yp + F x Yp |
csyang2 |
9:1286ec7f3230 | 48 | // we obtain D, E, F from the above 3 equations, by accumulating the coordinates of 5 points. |
csyang2 |
9:1286ec7f3230 | 49 | // the value of calibration : A B C D E F (65536), 7 integers used, 1 integer reserved |
csyang2 |
9:1286ec7f3230 | 50 | */ |
csyang2 |
9:1286ec7f3230 | 51 | int cal_values[8]; |
csyang2 |
1:c0f972361605 | 52 | |
csyang2 |
1:c0f972361605 | 53 | |
csyang2 |
1:c0f972361605 | 54 | int ts_writefile(void); |
csyang2 |
1:c0f972361605 | 55 | int ts_readfile(void); |
csyang2 |
9:1286ec7f3230 | 56 | int ts_calibrate(int xsize, int ysize); |
csyang2 |
9:1286ec7f3230 | 57 | int ts_phy2log(int *logx, int *logy); |
csyang2 |
1:c0f972361605 | 58 | |
csyang2 |
9:1286ec7f3230 | 59 | int DisplayFailStatus(int xsize, int ysize) |
csyang2 |
9:1286ec7f3230 | 60 | { |
csyang2 |
9:1286ec7f3230 | 61 | int i; |
csyang2 |
9:1286ec7f3230 | 62 | |
csyang2 |
9:1286ec7f3230 | 63 | GUI_SetFont(&GUI_Font32_ASCII); |
csyang2 |
9:1286ec7f3230 | 64 | GUI_SetTextMode(GUI_TM_XOR); |
csyang2 |
1:c0f972361605 | 65 | |
csyang2 |
9:1286ec7f3230 | 66 | for (i=0; i<3; i++) |
csyang2 |
9:1286ec7f3230 | 67 | { |
csyang2 |
9:1286ec7f3230 | 68 | GUI_DispStringHCenterAt("Fail to calibrate", xsize / 2, ysize / 4 + 30); |
csyang2 |
9:1286ec7f3230 | 69 | GUI_X_Delay(500); |
csyang2 |
9:1286ec7f3230 | 70 | GUI_DispStringHCenterAt("Fail to calibrate", xsize / 2, ysize / 4 + 30); |
csyang2 |
9:1286ec7f3230 | 71 | GUI_X_Delay(500); |
csyang2 |
9:1286ec7f3230 | 72 | } |
csyang2 |
9:1286ec7f3230 | 73 | |
csyang2 |
9:1286ec7f3230 | 74 | return -1; |
csyang2 |
9:1286ec7f3230 | 75 | } |
csyang2 |
9:1286ec7f3230 | 76 | |
csyang2 |
9:1286ec7f3230 | 77 | void write_cross(int x, int y) |
csyang2 |
1:c0f972361605 | 78 | { |
csyang2 |
9:1286ec7f3230 | 79 | GUI_DrawLine(x - 12, y, x - 2, y); |
csyang2 |
9:1286ec7f3230 | 80 | GUI_DrawLine(x + 2, y, x + 12, y); |
csyang2 |
9:1286ec7f3230 | 81 | GUI_DrawLine(x, y - 12, x, y - 2); |
csyang2 |
9:1286ec7f3230 | 82 | GUI_DrawLine(x, y + 2, x, y + 12); |
csyang2 |
9:1286ec7f3230 | 83 | GUI_DrawLine(x - 6, y - 12, x - 12, y - 12); |
csyang2 |
9:1286ec7f3230 | 84 | GUI_DrawLine(x - 12, y - 12, x - 12, y - 6); |
csyang2 |
9:1286ec7f3230 | 85 | GUI_DrawLine(x - 12, y + 6, x - 12, y + 12); |
csyang2 |
9:1286ec7f3230 | 86 | GUI_DrawLine(x - 12, y + 12, x - 6, y + 12); |
csyang2 |
9:1286ec7f3230 | 87 | GUI_DrawLine(x + 6, y + 12, x + 12, y + 12); |
csyang2 |
9:1286ec7f3230 | 88 | GUI_DrawLine(x + 12, y + 12, x + 12, y + 6); |
csyang2 |
9:1286ec7f3230 | 89 | GUI_DrawLine(x + 12, y - 6, x + 12, y - 12); |
csyang2 |
9:1286ec7f3230 | 90 | GUI_DrawLine(x + 12, y - 12, x + 6, y - 12); |
csyang2 |
9:1286ec7f3230 | 91 | } |
csyang2 |
1:c0f972361605 | 92 | |
csyang2 |
9:1286ec7f3230 | 93 | static int compare_x(const void* arg1, const void *arg2) |
csyang2 |
9:1286ec7f3230 | 94 | { |
csyang2 |
9:1286ec7f3230 | 95 | int ret; |
csyang2 |
9:1286ec7f3230 | 96 | ret = *(int *)arg1 -*(int *)arg2; |
csyang2 |
9:1286ec7f3230 | 97 | if ( ret > 0 ) |
csyang2 |
9:1286ec7f3230 | 98 | return 1; |
csyang2 |
9:1286ec7f3230 | 99 | else if ( ret < 0 ) |
csyang2 |
9:1286ec7f3230 | 100 | return -1; |
csyang2 |
9:1286ec7f3230 | 101 | return 0; |
csyang2 |
9:1286ec7f3230 | 102 | } |
csyang2 |
9:1286ec7f3230 | 103 | |
csyang2 |
9:1286ec7f3230 | 104 | static int compare_y(const void* arg1, const void *arg2) |
csyang2 |
9:1286ec7f3230 | 105 | { |
csyang2 |
9:1286ec7f3230 | 106 | int ret; |
csyang2 |
9:1286ec7f3230 | 107 | ret = *(int *)arg1 -*(int *)arg2; |
csyang2 |
9:1286ec7f3230 | 108 | if ( ret > 0 ) |
csyang2 |
9:1286ec7f3230 | 109 | return 1; |
csyang2 |
9:1286ec7f3230 | 110 | else if ( ret < 0 ) |
csyang2 |
9:1286ec7f3230 | 111 | return -1; |
csyang2 |
9:1286ec7f3230 | 112 | return 0; |
csyang2 |
9:1286ec7f3230 | 113 | } |
csyang2 |
9:1286ec7f3230 | 114 | |
csyang2 |
9:1286ec7f3230 | 115 | int read_phy_xy(int *x, int *y) |
csyang2 |
9:1286ec7f3230 | 116 | { |
csyang2 |
9:1286ec7f3230 | 117 | |
csyang2 |
9:1286ec7f3230 | 118 | int number, middle; |
csyang2 |
9:1286ec7f3230 | 119 | int phyx, phyy; |
csyang2 |
9:1286ec7f3230 | 120 | |
csyang2 |
9:1286ec7f3230 | 121 | printf("read physical x, y\n"); |
csyang2 |
9:1286ec7f3230 | 122 | again: |
csyang2 |
9:1286ec7f3230 | 123 | while (1) |
csyang2 |
1:c0f972361605 | 124 | { |
csyang2 |
9:1286ec7f3230 | 125 | if ( Read_TouchPanel(&phyx, &phyy) > 0 ) |
csyang2 |
9:1286ec7f3230 | 126 | { |
csyang2 |
9:1286ec7f3230 | 127 | if ( (phyx < 0) || ( phyy < 0 ) ) |
csyang2 |
9:1286ec7f3230 | 128 | continue; |
csyang2 |
9:1286ec7f3230 | 129 | break; |
csyang2 |
9:1286ec7f3230 | 130 | } |
csyang2 |
9:1286ec7f3230 | 131 | } |
csyang2 |
9:1286ec7f3230 | 132 | |
csyang2 |
9:1286ec7f3230 | 133 | // Delay 50 ms to wait HW ADC to be ready |
csyang2 |
9:1286ec7f3230 | 134 | GUI_X_Delay(50); |
csyang2 |
9:1286ec7f3230 | 135 | number = 0; |
csyang2 |
9:1286ec7f3230 | 136 | while (1) |
csyang2 |
9:1286ec7f3230 | 137 | { |
csyang2 |
9:1286ec7f3230 | 138 | if ( Read_TouchPanel(&phyx, &phyy) > 0) |
csyang2 |
9:1286ec7f3230 | 139 | { |
csyang2 |
9:1286ec7f3230 | 140 | sampleX[number] = phyx; |
csyang2 |
9:1286ec7f3230 | 141 | sampleY[number] = phyy; |
csyang2 |
9:1286ec7f3230 | 142 | } |
csyang2 |
9:1286ec7f3230 | 143 | else |
csyang2 |
9:1286ec7f3230 | 144 | { |
csyang2 |
9:1286ec7f3230 | 145 | break; |
csyang2 |
9:1286ec7f3230 | 146 | } |
csyang2 |
9:1286ec7f3230 | 147 | if ( number < MAX_NUM-1) |
csyang2 |
9:1286ec7f3230 | 148 | number++; |
csyang2 |
1:c0f972361605 | 149 | } |
csyang2 |
9:1286ec7f3230 | 150 | |
csyang2 |
9:1286ec7f3230 | 151 | printf("Capture %d samples\n",number); |
csyang2 |
9:1286ec7f3230 | 152 | |
csyang2 |
9:1286ec7f3230 | 153 | // pick the average value of the middle for the coordinate x, y |
csyang2 |
9:1286ec7f3230 | 154 | middle = number/2; |
csyang2 |
9:1286ec7f3230 | 155 | qsort(sampleX, number, sizeof(int), compare_x); |
csyang2 |
9:1286ec7f3230 | 156 | *x = (sampleX[middle-1] + sampleX[middle]) / 2; |
csyang2 |
9:1286ec7f3230 | 157 | |
csyang2 |
9:1286ec7f3230 | 158 | qsort(sampleY, number, sizeof(int), compare_y); |
csyang2 |
9:1286ec7f3230 | 159 | *y = (sampleY[middle-1] + sampleY[middle]) / 2; |
csyang2 |
9:1286ec7f3230 | 160 | |
csyang2 |
9:1286ec7f3230 | 161 | if ( number <= 10) |
csyang2 |
9:1286ec7f3230 | 162 | goto again; |
csyang2 |
9:1286ec7f3230 | 163 | |
csyang2 |
9:1286ec7f3230 | 164 | // >= DIFF, it means touch screen is not stable. stop the calibration |
csyang2 |
9:1286ec7f3230 | 165 | if ( abs(sampleY[middle-1] - sampleY[middle]) >= DIFF ) |
csyang2 |
9:1286ec7f3230 | 166 | return 0; |
csyang2 |
9:1286ec7f3230 | 167 | if ( abs(sampleX[middle-1] - sampleX[middle]) >= DIFF ) |
csyang2 |
9:1286ec7f3230 | 168 | return 0; |
csyang2 |
9:1286ec7f3230 | 169 | return 1; |
csyang2 |
9:1286ec7f3230 | 170 | } |
csyang2 |
9:1286ec7f3230 | 171 | |
csyang2 |
9:1286ec7f3230 | 172 | int run_calibration(void) |
csyang2 |
9:1286ec7f3230 | 173 | { |
csyang2 |
9:1286ec7f3230 | 174 | int i, no; |
csyang2 |
9:1286ec7f3230 | 175 | int sum_px, sum_py, sum_pxy, sum_square_px, sum_square_py, sum_lx, sum_lpx, sum_lpy, sum_ly; |
csyang2 |
9:1286ec7f3230 | 176 | float deter, im11, im12, im13, im21, im22, im23, im31, im32, im33; |
csyang2 |
9:1286ec7f3230 | 177 | |
csyang2 |
9:1286ec7f3230 | 178 | // logical.x = physical.x X A + physical.y X B + C |
csyang2 |
9:1286ec7f3230 | 179 | // logical.y = physical.x X D + physical.y X E + F |
csyang2 |
9:1286ec7f3230 | 180 | |
csyang2 |
9:1286ec7f3230 | 181 | // multiple physic.y and physic.y as follows |
csyang2 |
9:1286ec7f3230 | 182 | // logical.x X physical.x = physical.x X A X physical.x+ physical.y X B X physical.x + C X physical.x |
csyang2 |
9:1286ec7f3230 | 183 | // logical.x X physical.y = physical.x X A X physical.y+ physical.y X B X physical.y + C X physical.y |
csyang2 |
9:1286ec7f3230 | 184 | // we can obtain the paramters A, B, C from 3 x 3 matrix |
csyang2 |
9:1286ec7f3230 | 185 | // In the similiar method, we could also obtain the parameters D, E, F |
csyang2 |
9:1286ec7f3230 | 186 | // logical.y X physical.x = physical.x X D X physical.x+ physical.y X E X physical.x + F X physical.x |
csyang2 |
9:1286ec7f3230 | 187 | // logical.y X physical.y = physical.x X D X physical.y+ physical.y X E X physical.y + F X physical.y |
csyang2 |
9:1286ec7f3230 | 188 | |
csyang2 |
9:1286ec7f3230 | 189 | cal_values[6] = 65536; |
csyang2 |
9:1286ec7f3230 | 190 | sum_px = sum_py = sum_square_px = sum_square_py = sum_pxy = 0; |
csyang2 |
9:1286ec7f3230 | 191 | |
csyang2 |
9:1286ec7f3230 | 192 | // Get sums of physical x, y for matrix |
csyang2 |
9:1286ec7f3230 | 193 | |
csyang2 |
9:1286ec7f3230 | 194 | no = POINT_NUM; |
csyang2 |
9:1286ec7f3230 | 195 | for(i=0; i<POINT_NUM; i++) |
csyang2 |
1:c0f972361605 | 196 | { |
csyang2 |
9:1286ec7f3230 | 197 | sum_px += physical[i].x; |
csyang2 |
9:1286ec7f3230 | 198 | sum_py += physical[i].y; |
csyang2 |
9:1286ec7f3230 | 199 | sum_square_px += (physical[i].x * physical[i].x); |
csyang2 |
9:1286ec7f3230 | 200 | sum_square_py += (physical[i].y * physical[i].y); |
csyang2 |
9:1286ec7f3230 | 201 | sum_pxy += (physical[i].x * physical[i].y); |
csyang2 |
9:1286ec7f3230 | 202 | } |
csyang2 |
9:1286ec7f3230 | 203 | // From 3x3 matix Z, ZX= Y, X, Y is a 3 x 1 matrix |
csyang2 |
9:1286ec7f3230 | 204 | // deter is the determinant for 3 x 3 matix |
csyang2 |
9:1286ec7f3230 | 205 | |
csyang2 |
9:1286ec7f3230 | 206 | im11 = (float)sum_pxy*sum_py - (float)sum_px*sum_square_py; |
csyang2 |
9:1286ec7f3230 | 207 | im21 = (float)sum_px*sum_pxy - (float)sum_py*sum_square_px; |
csyang2 |
9:1286ec7f3230 | 208 | im31= (float)sum_square_px*sum_square_py - (float)sum_pxy*sum_pxy; |
csyang2 |
9:1286ec7f3230 | 209 | deter = im11*sum_px+im21*sum_py+im31*no; |
csyang2 |
9:1286ec7f3230 | 210 | |
csyang2 |
9:1286ec7f3230 | 211 | if(deter < 0.01 && deter > -0.01) |
csyang2 |
9:1286ec7f3230 | 212 | { |
csyang2 |
9:1286ec7f3230 | 213 | printf("ts_calibrate: No inverse matrix \n"); |
csyang2 |
1:c0f972361605 | 214 | return 0; |
csyang2 |
1:c0f972361605 | 215 | } |
csyang2 |
1:c0f972361605 | 216 | |
csyang2 |
9:1286ec7f3230 | 217 | // Get elements of inverse matrix as follows |
csyang2 |
9:1286ec7f3230 | 218 | // im11 im12 im13 |
csyang2 |
9:1286ec7f3230 | 219 | // im21 im22 im23 |
csyang2 |
9:1286ec7f3230 | 220 | // im31 im32 im33 |
csyang2 |
9:1286ec7f3230 | 221 | im32 = im11 = im11/deter; |
csyang2 |
9:1286ec7f3230 | 222 | im12 = (float)(no*sum_square_py - sum_py*sum_py)/deter; |
csyang2 |
9:1286ec7f3230 | 223 | im22 = im13 = (float)(sum_px*sum_py - no*sum_pxy)/deter; |
csyang2 |
9:1286ec7f3230 | 224 | im33 = im21 = im21/deter; |
csyang2 |
9:1286ec7f3230 | 225 | im23 = (float)(no*sum_square_px - sum_px*sum_px)/deter; |
csyang2 |
9:1286ec7f3230 | 226 | im31= im31/deter; |
csyang2 |
1:c0f972361605 | 227 | |
csyang2 |
9:1286ec7f3230 | 228 | // Get sums of logical and physical for x calibration |
csyang2 |
9:1286ec7f3230 | 229 | sum_lx = sum_lpx = sum_lpy = 0; |
csyang2 |
9:1286ec7f3230 | 230 | for(i=0; i<POINT_NUM; i++) |
csyang2 |
1:c0f972361605 | 231 | { |
csyang2 |
9:1286ec7f3230 | 232 | sum_lx += logical[i].x; |
csyang2 |
9:1286ec7f3230 | 233 | sum_lpx += (logical[i].x*physical[i].x); |
csyang2 |
9:1286ec7f3230 | 234 | sum_lpy += (logical[i].x*physical[i].y); |
csyang2 |
1:c0f972361605 | 235 | } |
csyang2 |
1:c0f972361605 | 236 | |
csyang2 |
9:1286ec7f3230 | 237 | // get the calibration for A, B, C mapping cal_values[0], cal_values[1], cal_values[2] |
csyang2 |
9:1286ec7f3230 | 238 | cal_values[0] = (int)((im11*sum_lx + im12*sum_lpx + im13*sum_lpy)* cal_values[6]); |
csyang2 |
9:1286ec7f3230 | 239 | cal_values[1] = (int)((im21*sum_lx + im22*sum_lpx + im23*sum_lpy)* cal_values[6]); |
csyang2 |
9:1286ec7f3230 | 240 | cal_values[2] = (int)((im31*sum_lx + im32*sum_lpx + im33*sum_lpy)* cal_values[6]); |
csyang2 |
1:c0f972361605 | 241 | |
csyang2 |
9:1286ec7f3230 | 242 | // Get sums of logical and physical for y calibration |
csyang2 |
9:1286ec7f3230 | 243 | sum_ly = sum_lpx = sum_lpy = 0; |
csyang2 |
9:1286ec7f3230 | 244 | for(i=0; i<POINT_NUM; i++) |
csyang2 |
1:c0f972361605 | 245 | { |
csyang2 |
9:1286ec7f3230 | 246 | sum_ly += logical[i].y; |
csyang2 |
9:1286ec7f3230 | 247 | sum_lpx += (logical[i].y*physical[i].x); |
csyang2 |
9:1286ec7f3230 | 248 | sum_lpy += (logical[i].y*physical[i].y); |
csyang2 |
1:c0f972361605 | 249 | } |
csyang2 |
1:c0f972361605 | 250 | |
csyang2 |
9:1286ec7f3230 | 251 | // get the calibration for D, E, F mapping cal_values[3], cal_values[4], cal_values[5] |
csyang2 |
9:1286ec7f3230 | 252 | cal_values[3] = (int)((im11*sum_ly + im12*sum_lpx + im13*sum_lpy)* cal_values[6]); |
csyang2 |
9:1286ec7f3230 | 253 | cal_values[4] = (int)((im21*sum_ly + im22*sum_lpx + im23*sum_lpy)* cal_values[6]); |
csyang2 |
9:1286ec7f3230 | 254 | cal_values[5] = (int)((im31*sum_ly + im32*sum_lpx + im33*sum_lpy)* cal_values[6]); |
csyang2 |
1:c0f972361605 | 255 | |
csyang2 |
1:c0f972361605 | 256 | return 1; |
csyang2 |
1:c0f972361605 | 257 | } |
csyang2 |
1:c0f972361605 | 258 | |
csyang2 |
1:c0f972361605 | 259 | |
csyang2 |
9:1286ec7f3230 | 260 | int read_calib_sample(char *rect_name, int index, int logx, int logy) |
csyang2 |
9:1286ec7f3230 | 261 | { |
csyang2 |
9:1286ec7f3230 | 262 | int result; |
csyang2 |
9:1286ec7f3230 | 263 | GUI_SetColor(GUI_WHITE); |
csyang2 |
9:1286ec7f3230 | 264 | write_cross(logx, logy); |
csyang2 |
9:1286ec7f3230 | 265 | result = read_phy_xy (&physical[index].x, &physical[index].y); |
csyang2 |
9:1286ec7f3230 | 266 | GUI_SetColor(GUI_BLACK); |
csyang2 |
9:1286ec7f3230 | 267 | write_cross(logx, logy); |
csyang2 |
1:c0f972361605 | 268 | |
csyang2 |
9:1286ec7f3230 | 269 | logical[index].x = logx; |
csyang2 |
9:1286ec7f3230 | 270 | logical[index].y = logy; |
csyang2 |
1:c0f972361605 | 271 | |
csyang2 |
9:1286ec7f3230 | 272 | printf("%s : X = %4d Y = %4d\n", rect_name, physical[index].x, physical[index].y); |
csyang2 |
9:1286ec7f3230 | 273 | return result; |
csyang2 |
1:c0f972361605 | 274 | } |
csyang2 |
1:c0f972361605 | 275 | |
csyang2 |
1:c0f972361605 | 276 | int ts_calibrate(int xsize, int ysize) |
csyang2 |
1:c0f972361605 | 277 | { |
csyang2 |
9:1286ec7f3230 | 278 | int result,d1, d2, d3; |
csyang2 |
9:1286ec7f3230 | 279 | GUI_SetBkColor(GUI_BLACK); |
csyang2 |
9:1286ec7f3230 | 280 | GUI_Clear(); |
csyang2 |
1:c0f972361605 | 281 | |
csyang2 |
9:1286ec7f3230 | 282 | if ( xsize >= 800 ) // 800x480 |
csyang2 |
9:1286ec7f3230 | 283 | { |
csyang2 |
9:1286ec7f3230 | 284 | GUI_SetFont(&GUI_Font24B_ASCII); |
csyang2 |
9:1286ec7f3230 | 285 | d1 = -50; |
csyang2 |
9:1286ec7f3230 | 286 | d2 = -20; |
csyang2 |
9:1286ec7f3230 | 287 | d3 = 10; |
csyang2 |
9:1286ec7f3230 | 288 | } |
csyang2 |
9:1286ec7f3230 | 289 | else if ( xsize >= 480 ) // 480 x272 |
csyang2 |
9:1286ec7f3230 | 290 | { |
csyang2 |
9:1286ec7f3230 | 291 | GUI_SetFont(&GUI_Font13B_ASCII); |
csyang2 |
9:1286ec7f3230 | 292 | d1 = -50; |
csyang2 |
9:1286ec7f3230 | 293 | d2 = -30; |
csyang2 |
9:1286ec7f3230 | 294 | d3 = -10; |
csyang2 |
9:1286ec7f3230 | 295 | } |
csyang2 |
9:1286ec7f3230 | 296 | else |
csyang2 |
9:1286ec7f3230 | 297 | { |
csyang2 |
9:1286ec7f3230 | 298 | GUI_SetFont(&GUI_Font8_ASCII); |
csyang2 |
9:1286ec7f3230 | 299 | d1 = -20; |
csyang2 |
9:1286ec7f3230 | 300 | d2 = -10; |
csyang2 |
9:1286ec7f3230 | 301 | d3 = 0; |
csyang2 |
9:1286ec7f3230 | 302 | } |
csyang2 |
1:c0f972361605 | 303 | |
csyang2 |
9:1286ec7f3230 | 304 | GUI_SetColor(GUI_RED); |
csyang2 |
9:1286ec7f3230 | 305 | GUI_DispStringHCenterAt("Nuvoton's TS calibration utility", xsize / 2, ysize / 4 +d1); |
csyang2 |
9:1286ec7f3230 | 306 | |
csyang2 |
9:1286ec7f3230 | 307 | GUI_SetColor(GUI_BLUE); |
csyang2 |
9:1286ec7f3230 | 308 | GUI_DispStringHCenterAt("Touch crosshair to calibrate", xsize / 2, ysize / 4 +d2 ); |
csyang2 |
1:c0f972361605 | 309 | |
csyang2 |
9:1286ec7f3230 | 310 | GUI_SetColor(GUI_GREEN); |
csyang2 |
9:1286ec7f3230 | 311 | GUI_DispStringHCenterAt("Click down 2 seconds and release", xsize / 2, ysize / 4 + d3); |
csyang2 |
9:1286ec7f3230 | 312 | |
csyang2 |
9:1286ec7f3230 | 313 | printf("xsize = %d, ysize = %d\n", xsize, ysize); |
csyang2 |
9:1286ec7f3230 | 314 | |
csyang2 |
9:1286ec7f3230 | 315 | //GUI_SetColor(GUI_WHITE); |
csyang2 |
9:1286ec7f3230 | 316 | //GUI_SetDrawMode(GUI_DRAWMODE_XOR); |
csyang2 |
9:1286ec7f3230 | 317 | GUI_SetPenSize(1); |
csyang2 |
1:c0f972361605 | 318 | |
csyang2 |
9:1286ec7f3230 | 319 | //Top left |
csyang2 |
9:1286ec7f3230 | 320 | result = read_calib_sample ("Top left", 0, 40, 40); |
csyang2 |
9:1286ec7f3230 | 321 | GUI_X_Delay(300); |
csyang2 |
9:1286ec7f3230 | 322 | if ( result == 0 ) |
csyang2 |
9:1286ec7f3230 | 323 | { |
csyang2 |
9:1286ec7f3230 | 324 | return(DisplayFailStatus(xsize, ysize)); |
csyang2 |
9:1286ec7f3230 | 325 | } |
csyang2 |
1:c0f972361605 | 326 | |
csyang2 |
9:1286ec7f3230 | 327 | //Top right |
csyang2 |
9:1286ec7f3230 | 328 | result = read_calib_sample ("Top right", 1, xsize - 40, 40); |
csyang2 |
9:1286ec7f3230 | 329 | GUI_X_Delay(300); |
csyang2 |
9:1286ec7f3230 | 330 | if ( result == 0 ) |
csyang2 |
9:1286ec7f3230 | 331 | { |
csyang2 |
9:1286ec7f3230 | 332 | return(DisplayFailStatus(xsize, ysize)); |
csyang2 |
9:1286ec7f3230 | 333 | } |
csyang2 |
1:c0f972361605 | 334 | |
csyang2 |
9:1286ec7f3230 | 335 | //Bottom right |
csyang2 |
9:1286ec7f3230 | 336 | result = read_calib_sample ("Bottom right", 2, xsize - 40, ysize - 40); |
csyang2 |
9:1286ec7f3230 | 337 | GUI_X_Delay(300); |
csyang2 |
9:1286ec7f3230 | 338 | if ( result == 0 ) |
csyang2 |
9:1286ec7f3230 | 339 | { |
csyang2 |
9:1286ec7f3230 | 340 | return(DisplayFailStatus(xsize, ysize)); |
csyang2 |
9:1286ec7f3230 | 341 | } |
csyang2 |
9:1286ec7f3230 | 342 | |
csyang2 |
9:1286ec7f3230 | 343 | //Bottom left |
csyang2 |
9:1286ec7f3230 | 344 | result = read_calib_sample ("Bottom left", 3, 40, ysize - 40); |
csyang2 |
9:1286ec7f3230 | 345 | GUI_X_Delay(300); |
csyang2 |
9:1286ec7f3230 | 346 | if ( result == 0 ) |
csyang2 |
1:c0f972361605 | 347 | { |
csyang2 |
9:1286ec7f3230 | 348 | return(DisplayFailStatus(xsize, ysize)); |
csyang2 |
9:1286ec7f3230 | 349 | } |
csyang2 |
9:1286ec7f3230 | 350 | |
csyang2 |
9:1286ec7f3230 | 351 | // Center |
csyang2 |
9:1286ec7f3230 | 352 | result = read_calib_sample ("Center", 4, xsize / 2, ysize / 2); |
csyang2 |
9:1286ec7f3230 | 353 | GUI_X_Delay(300); |
csyang2 |
9:1286ec7f3230 | 354 | if ( result == 0 ) |
csyang2 |
9:1286ec7f3230 | 355 | { |
csyang2 |
9:1286ec7f3230 | 356 | return(DisplayFailStatus(xsize, ysize)); |
csyang2 |
9:1286ec7f3230 | 357 | } |
csyang2 |
9:1286ec7f3230 | 358 | |
csyang2 |
9:1286ec7f3230 | 359 | // After running API run_calibration, global variable cal_values is exported. |
csyang2 |
9:1286ec7f3230 | 360 | if (run_calibration()) |
csyang2 |
9:1286ec7f3230 | 361 | { |
csyang2 |
9:1286ec7f3230 | 362 | printf("Calibration OK.\n"); |
csyang2 |
9:1286ec7f3230 | 363 | result = 1; |
csyang2 |
1:c0f972361605 | 364 | } |
csyang2 |
1:c0f972361605 | 365 | else |
csyang2 |
1:c0f972361605 | 366 | { |
csyang2 |
1:c0f972361605 | 367 | printf("Calibration failed.\n"); |
csyang2 |
9:1286ec7f3230 | 368 | result = -1; |
csyang2 |
1:c0f972361605 | 369 | } |
csyang2 |
9:1286ec7f3230 | 370 | #if 0 |
csyang2 |
9:1286ec7f3230 | 371 | printf("cal_values[0][0x%08X]\n", (unsigned int)cal_values[0]); |
csyang2 |
9:1286ec7f3230 | 372 | printf("cal_values[1][0x%08X]\n", (unsigned int)cal_values[1]); |
csyang2 |
9:1286ec7f3230 | 373 | printf("cal_values[2][0x%08X]\n", (unsigned int)cal_values[2]); |
csyang2 |
9:1286ec7f3230 | 374 | printf("cal_values[3][0x%08X]\n", (unsigned int)cal_values[3]); |
csyang2 |
9:1286ec7f3230 | 375 | printf("cal_values[4][0x%08X]\n", (unsigned int)cal_values[4]); |
csyang2 |
9:1286ec7f3230 | 376 | printf("cal_values[5][0x%08X]\n", (unsigned int)cal_values[5]); |
csyang2 |
9:1286ec7f3230 | 377 | printf("cal_values[6][0x%08X]\n", (unsigned int)cal_values[6]); |
csyang2 |
9:1286ec7f3230 | 378 | #endif |
csyang2 |
9:1286ec7f3230 | 379 | return result; |
csyang2 |
1:c0f972361605 | 380 | } |
csyang2 |
1:c0f972361605 | 381 | |
csyang2 |
9:1286ec7f3230 | 382 | // logical.x = physical.x X A + physical.y X B + C |
csyang2 |
9:1286ec7f3230 | 383 | // logical.y = physical.x X D + physical.y X E + F |
csyang2 |
9:1286ec7f3230 | 384 | int ts_phy2log(int *logx, int *logy) |
csyang2 |
1:c0f972361605 | 385 | { |
csyang2 |
9:1286ec7f3230 | 386 | int phyx,phyy; |
csyang2 |
1:c0f972361605 | 387 | |
csyang2 |
9:1286ec7f3230 | 388 | phyx = *logx; |
csyang2 |
9:1286ec7f3230 | 389 | phyy = *logy; |
csyang2 |
9:1286ec7f3230 | 390 | *logx = ( phyx*cal_values[0] + phyy*cal_values[1] + cal_values[2] ) / cal_values[6]; |
csyang2 |
9:1286ec7f3230 | 391 | *logy = ( phyx*cal_values[3]+ phyy*cal_values[4] + cal_values[5] ) / cal_values[6]; |
csyang2 |
1:c0f972361605 | 392 | return 1; |
csyang2 |
1:c0f972361605 | 393 | } |
csyang2 |
1:c0f972361605 | 394 | |
csyang2 |
9:1286ec7f3230 | 395 | // write the calibration parameters into one file |
csyang2 |
1:c0f972361605 | 396 | int ts_writefile(void) |
csyang2 |
1:c0f972361605 | 397 | { |
csyang2 |
9:1286ec7f3230 | 398 | #if 0 |
csyang2 |
9:1286ec7f3230 | 399 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x00, cal_values[0]); |
csyang2 |
9:1286ec7f3230 | 400 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x04, cal_values[1]); |
csyang2 |
9:1286ec7f3230 | 401 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x08, cal_values[2]); |
csyang2 |
9:1286ec7f3230 | 402 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x0C, cal_values[3]); |
csyang2 |
9:1286ec7f3230 | 403 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x10, cal_values[4]); |
csyang2 |
9:1286ec7f3230 | 404 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x14, cal_values[5]); |
csyang2 |
9:1286ec7f3230 | 405 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x18, cal_values[6]); |
csyang2 |
1:c0f972361605 | 406 | FMC_Write(__DEMO_TSFILE_ADDR__ + 0x1C, 0x55AAA55A); |
csyang2 |
1:c0f972361605 | 407 | #endif |
csyang2 |
1:c0f972361605 | 408 | return 0; |
csyang2 |
1:c0f972361605 | 409 | } |
csyang2 |
1:c0f972361605 | 410 | |
csyang2 |
1:c0f972361605 | 411 | int ts_readfile(void) |
csyang2 |
1:c0f972361605 | 412 | { |
csyang2 |
9:1286ec7f3230 | 413 | #if 0 |
csyang2 |
9:1286ec7f3230 | 414 | cal_values[0] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x00); |
csyang2 |
9:1286ec7f3230 | 415 | cal_values[1] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x04); |
csyang2 |
9:1286ec7f3230 | 416 | cal_values[2] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x08); |
csyang2 |
9:1286ec7f3230 | 417 | cal_values[3] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x0C); |
csyang2 |
9:1286ec7f3230 | 418 | cal_values[4] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x10); |
csyang2 |
9:1286ec7f3230 | 419 | cal_values[5] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x14); |
csyang2 |
9:1286ec7f3230 | 420 | cal_values[6] = FMC_Read(__DEMO_TSFILE_ADDR__ + 0x18); |
csyang2 |
1:c0f972361605 | 421 | #endif |
csyang2 |
1:c0f972361605 | 422 | return 0; |
csyang2 |
1:c0f972361605 | 423 | } |
csyang2 |
9:1286ec7f3230 | 424 | |
csyang2 |
9:1286ec7f3230 | 425 | void ts_init(void) |
csyang2 |
9:1286ec7f3230 | 426 | { |
csyang2 |
9:1286ec7f3230 | 427 | #if 0 |
csyang2 |
9:1286ec7f3230 | 428 | #ifdef __DEMO_160x128__ |
csyang2 |
9:1286ec7f3230 | 429 | cal_values[0] = 0xFFFFFFEB; |
csyang2 |
9:1286ec7f3230 | 430 | cal_values[1] = 0x00000D1D; |
csyang2 |
9:1286ec7f3230 | 431 | cal_values[2] = 0xFFEE9924; |
csyang2 |
9:1286ec7f3230 | 432 | cal_values[3] = 0x00000BF3; |
csyang2 |
9:1286ec7f3230 | 433 | cal_values[4] = 0x00000004; |
csyang2 |
9:1286ec7f3230 | 434 | cal_values[5] = 0xFFE8E0E6; |
csyang2 |
9:1286ec7f3230 | 435 | cal_values[6] = 0x00010000; |
csyang2 |
9:1286ec7f3230 | 436 | #else |
csyang2 |
9:1286ec7f3230 | 437 | cal_values[0] = 0x00000050; |
csyang2 |
9:1286ec7f3230 | 438 | cal_values[1] = 0x00001896; |
csyang2 |
9:1286ec7f3230 | 439 | cal_values[2] = 0xFFC6AEB4; |
csyang2 |
9:1286ec7f3230 | 440 | cal_values[3] = 0x00001404; |
csyang2 |
9:1286ec7f3230 | 441 | cal_values[4] = 0xFFFFFFF5; |
csyang2 |
9:1286ec7f3230 | 442 | cal_values[5] = 0xFFD1601B; |
csyang2 |
9:1286ec7f3230 | 443 | cal_values[6] = 0x00010000; |
csyang2 |
9:1286ec7f3230 | 444 | #endif |
csyang2 |
9:1286ec7f3230 | 445 | #endif |
csyang2 |
9:1286ec7f3230 | 446 | } |