aboutsummaryrefslogtreecommitdiffstats
path: root/boards/base/STM32F746-Discovery/gmouse_lld_FT5336_board.h
blob: bf523212e8d1b728130575925f4df3fc36834239 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */

#ifndef _GINPUT_LLD_MOUSE_BOARD_H
#define _GINPUT_LLD_MOUSE_BOARD_H

#include "stm32f7xx.h"

// Resolution and Accuracy Settings
#define GMOUSE_FT5336_PEN_CALIBRATE_ERROR		8
#define GMOUSE_FT5336_PEN_CLICK_ERROR			6
#define GMOUSE_FT5336_PEN_MOVE_ERROR			4
#define GMOUSE_FT5336_FINGER_CALIBRATE_ERROR	14
#define GMOUSE_FT5336_FINGER_CLICK_ERROR		18
#define GMOUSE_FT5336_FINGER_MOVE_ERROR			14

// How much extra data to allocate at the end of the GMouse structure for the board's use
#define GMOUSE_FT5336_BOARD_DATA_SIZE			0

// Set this to TRUE if you want self-calibration.
//	NOTE:	This is not as accurate as real calibration.
//			It requires the orientation of the touch panel to match the display.
//			It requires the active area of the touch panel to exactly match the display size.
#define GMOUSE_FT5336_SELF_CALIBRATE			FALSE

// The FT5336 slave address
#define FT5336_ADDR 0x70

static bool_t init_board(GMouse* m, unsigned instance)
{
	(void)m;
	(void)instance;

	// I2C3_SCL    GPIOH7, alternate, opendrain, highspeed
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;					// Enable clock for
	GPIOB->MODER |= GPIO_MODER_MODER7_1;					// Alternate function
	GPIOB->OTYPER |= GPIO_OTYPER_OT_7;						// OpenDrain
	GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;					// PullUp
	GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7;				// HighSpeed
	GPIOB->AFR[0] |= (0b0100 << 4*0);						// AF4

	// I2C3_SDA    GPIOH8, alternate, opendrain, highspeed
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;					// Enable clock
	GPIOB->MODER |= GPIO_MODER_MODER8_1;					// Alternate function
	GPIOB->OTYPER |= GPIO_OTYPER_OT_8;						// OpenDrain
	GPIOB->PUPDR |= GPIO_PUPDR_PUPDR8_0;					// PullUp
	GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8;				// HighSpeed
	GPIOB->AFR[1] |= (0b0100 << 4*0);						// AF4

	// Enable I2C3 peripheral clock
	RCC->APB1ENR |= RCC_APB1ENR_I2C3EN;

	// Reset I2C3 peripheral
	RCC->APB1RSTR |= RCC_APB1RSTR_I2C3RST;
	RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C3RST;

	// Set Fm mode
	I2C3->CCR |= I2C_CCR_FS;

	// Set Duty to 50:50
	I2C3->CCR &= ~I2C_CCR_DUTY;

	// Set peripheral clock frequency (APB1 frequency)
	// APB1CLK running at 42 MHz
	I2C3->CR2 |= 42;

	// Set I2C bus clock speed to 400 kHz
	// Period of 400 kHz is 2.5 us, half of that is 1.25 us. TPCLK1 is
    // 40 ns (see below). 1.25 us / 40 ns = 32.
	I2C3->CCR |= (I2C_CCR_CCR & 32);

	// Rise time
	// Period of 42 MHz is 24 ns. Rise time is 1000 ns. 1000/24 = 42.
	I2C3->TRISE |= (I2C_TRISE_TRISE & 42);

	// Disable POS
	I2C3->CR1 &=~ I2C_CR1_POS;

	// Enable I2C3
	I2C3->CR1 |= I2C_CR1_PE;

	return TRUE;
}

static void write_reg(GMouse* m, uint8_t reg, uint8_t val)
{
	(void)m;

	// Generate start condition
	I2C3->CR1 |= I2C_CR1_START;
	while (!(I2C3->SR2 & I2C_SR2_MSL));
	while (!(I2C3->SR1 & I2C_SR1_SB));

	// Send slave address (Write = last bit is 0)
	I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_ADDR));

	// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
	(void)I2C3->SR1;
	(void)I2C3->SR2;

	// Send register address
	while (!(I2C3->SR1 & I2C_SR1_TXE));
	I2C3->DR = (reg & I2C_DR_DR);

	// Send data
	while (!(I2C3->SR1 & I2C_SR1_TXE));
	I2C3->DR = (val & I2C_DR_DR);

	// Generate stop condition when we are done transmitting
	while (!(I2C3->SR1 & I2C_SR1_TXE));
	I2C3->CR1 |= I2C_CR1_STOP;
}

static uint8_t read_byte(GMouse* m, uint8_t reg)
{
	(void)m;

	uint8_t ret = 0x00;

	// Generate start condition
	I2C3->CR1 |= I2C_CR1_START;
	while (!(I2C3->SR2 & I2C_SR2_MSL));
	while (!(I2C3->SR1 & I2C_SR1_SB));

	// Send slave address (Write = last bit is 0)
	I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_ADDR));

	// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
	(void)I2C3->SR1;
	(void)I2C3->SR2;

	// Send register address that we want to read
	I2C3->DR = (reg & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_BTF));

	// Generate start condition (repeated start)
	I2C3->CR1 |= I2C_CR1_START;
	while (!(I2C3->SR2 & I2C_SR2_MSL));
	while (!(I2C3->SR1 & I2C_SR1_SB));

	// Send slave address (Read = last bit is 1)
	I2C3->DR = ((FT5336_ADDR | 1) & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_ADDR));

	// Set up for one byte receival
	I2C3->CR1 &= ~I2C_CR1_POS;
	//I2C3->CR1 |= I2C_CR1_ACK;

	// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
	(void)I2C3->SR1;
	(void)I2C3->SR2;

	// Clean SR1_ACK. This needs to be done on the last byte received from slave
	I2C3->CR1 &= ~I2C_CR1_ACK;

	// Generate stop condition
	I2C3->CR1 |= I2C_CR1_STOP;

	return ret;
}

static uint16_t read_word(GMouse* m, uint8_t reg)
{
	(void)m;

	uint16_t ret = 0x00;

	// Generate start condition
	I2C3->CR1 |= I2C_CR1_START;
	while (!(I2C3->SR2 & I2C_SR2_MSL));
	while (!(I2C3->SR1 & I2C_SR1_SB));

	// Send slave address (Write = last bit is 0)
	I2C3->DR = ((FT5336_ADDR | 0) & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_ADDR));

	// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
	(void)I2C3->SR1;
	(void)I2C3->SR2;

	// Send register address that we want to read
	I2C3->DR = (reg & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_BTF));

	// Generate start condition (repeated start)
	I2C3->CR1 |= I2C_CR1_START;
	while (!(I2C3->SR2 & I2C_SR2_MSL));
	while (!(I2C3->SR1 & I2C_SR1_SB));

	// Send slave address (Read = last bit is 1)
	I2C3->DR = ((FT5336_ADDR | 1) & I2C_DR_DR);
	while (!(I2C3->SR1 & I2C_SR1_ADDR));

	// Set up for two byte receival
	I2C3->CR1 |= I2C_CR1_POS;
	//I2C3->CR1 &= ~I2C_CR1_ACK;
	I2C3->SR1 &= ~I2C_SR1_ADDR;

	// Read SR1/SR2 register to clear the SB bit (see STM32F4xx RM)
	(void)I2C3->SR1;
	(void)I2C3->SR2;

	// The slave should now send a byte to us.
	while (!(I2C3->SR1 & I2C_SR1_RXNE));
	ret = (uint16_t)((I2C3->DR & 0x00FF) << 8);

	// Set STOP and clear ACK right after reading the second last byte
	I2C3->CR1 |= I2C_CR1_STOP;
	I2C3->CR1 &= ~I2C_CR1_ACK;

	// The second byte becomes available after sending the stop condition
	ret |= (I2C3->DR & 0x00FF);

	// Get back to original state
	I2C3->CR1 &= ~I2C_CR1_POS;

	return ret;
}

#endif /* _GINPUT_LLD_MOUSE_BOARD_H */