1 //
2 // Copyright (c) 2010-2020 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using Antmicro.Renode.Core;
9 using Antmicro.Renode.Logging;
10 using Antmicro.Renode.Peripherals.I2C;
11 using System.Linq;
12 using Antmicro.Renode.Utilities;
13 using System.Collections.Generic;
14 
15 namespace Antmicro.Renode.Peripherals.Input
16 {
17     /// <summary>
18     /// This class differs from FT5x06. Although it was based on FT5x06 datasheet, it is inconsistent
19     /// with the Linux driver we used to create FT5x06.cs.
20     /// This name is used because of STM32F7 Cube, providing such a driver.
21     /// </summary>
22     public sealed class FT5336 : II2CPeripheral, IAbsolutePositionPointerInput
23     {
FT5336(bool isRotated = false)24         public FT5336(bool isRotated = false)
25         {
26             this.isRotated = isRotated;
27             IRQ = new GPIO();
28             Reset();
29         }
30 
Reset()31         public void Reset()
32         {
33             IRQ.Unset();
34             currentReturnValue = null;
35             lastWriteRegister = 0;
36             for(ushort i = 0; i < touchedPoints.Length; ++i)
37             {
38                 touchedPoints[i] = new TouchedPoint
39                 {
40                     Type = PointType.Reserved,
41                     X = 0,
42                     Y = 0,
43                     Id = i
44                 };
45             }
46         }
47 
Write(byte[] data)48         public void Write(byte[] data)
49         {
50             lastWriteRegister = (Registers)data[0];
51             if(lastWriteRegister < Registers.TouchEndRegister && lastWriteRegister >= Registers.TouchBeginRegister)
52             {
53                 PrepareTouchData((byte)((lastWriteRegister - Registers.TouchBeginRegister) % TouchInfoSize), (lastWriteRegister - Registers.TouchBeginRegister) / TouchInfoSize);
54                 return;
55             }
56             switch(lastWriteRegister)
57             {
58             case Registers.TouchDataStatus:
59                 SetReturnValue((byte)touchedPoints.Count(x => x.Type == PointType.Contact || x.Type == PointType.Down));
60                 break;
61             case Registers.InterruptStatus:
62                 break;
63             case Registers.ChipVendorId:
64                 SetReturnValue(ChipVendorId);
65                 break;
66             default:
67                 this.Log(LogLevel.Warning, "Unhandled write to offset 0x{0:X}{1:X}.", lastWriteRegister,
68                     data.Length == 1 ? String.Empty : ", values {0}".FormatWith(data.Skip(1).Select(x => "0x" + x.ToString("X")).Stringify(", ")));
69                 break;
70             }
71         }
72 
Read(int count)73         public byte[] Read(int count)
74         {
75             return currentReturnValue.Take(count).ToArray();
76         }
77 
FinishTransmission()78         public void FinishTransmission()
79         {
80         }
81 
MoveTo(int x, int y)82         public void MoveTo(int x, int y)
83         {
84             if(!isRotated)
85             {
86                 touchedPoints[0].X = (ushort)x;
87                 touchedPoints[0].Y = (ushort)y;
88             }
89             else
90             {
91                 touchedPoints[0].X = (ushort)y;
92                 touchedPoints[0].Y = (ushort)x;
93             }
94             if(touchedPoints[0].Type == PointType.Down || touchedPoints[0].Type == PointType.Contact)
95             {
96                 this.NoisyLog("Moving the pointer at {0}x{1}", touchedPoints[0].X, touchedPoints[0].Y);
97                 touchedPoints[0].Type = PointType.Contact;
98             }
99             if(touchedPoints.Any(b => b.Type == PointType.Down || b.Type == PointType.Contact))
100             {
101                 IRQ.Blink();
102             }
103         }
104 
Press(MouseButton button = MouseButton.Left)105         public void Press(MouseButton button = MouseButton.Left)
106         {
107             this.NoisyLog("Pressing the pointer at {0}x{1}", touchedPoints[0].X, touchedPoints[0].Y);
108             touchedPoints[0].Type = PointType.Contact;
109             IRQ.Blink();
110         }
111 
Release(MouseButton button = MouseButton.Left)112         public void Release(MouseButton button = MouseButton.Left)
113         {
114             this.NoisyLog("Releasing the pointer at {0}x{1}", touchedPoints[0].X, touchedPoints[0].Y);
115             touchedPoints[0].Type = PointType.Up;
116             IRQ.Blink();
117         }
118 
119         public int MaxX { get; set; }
120 
121         public int MaxY { get; set; }
122 
123         public int MinX
124         {
125             get
126             {
127                 return 0;
128             }
129         }
130 
131         public int MinY
132         {
133             get
134             {
135                 return 0;
136             }
137         }
138 
139         public GPIO IRQ { get; private set; }
140 
PrepareTouchData(byte offset, int pointNumber)141         private void PrepareTouchData(byte offset, int pointNumber)
142         {
143             var queue = new Queue<byte>();
144 
145             switch((TouchDataRegisters)offset)
146             {
147             case TouchDataRegisters.TouchXHigh:
148                 queue.Enqueue((byte)(((int)touchedPoints[pointNumber].Type << 6) | (touchedPoints[pointNumber].X.HiByte() & 0xF)));
149                 goto case TouchDataRegisters.TouchXLow;
150             case TouchDataRegisters.TouchXLow:
151                 queue.Enqueue(touchedPoints[pointNumber].X.LoByte());
152                 goto case TouchDataRegisters.TouchYHigh;
153             case TouchDataRegisters.TouchYHigh:
154                 queue.Enqueue((byte)((touchedPoints[pointNumber].Id << 4) | (touchedPoints[pointNumber].Y.HiByte() & 0xF)));
155                 goto case TouchDataRegisters.TouchYLow;
156             case TouchDataRegisters.TouchYLow:
157                 queue.Enqueue(touchedPoints[pointNumber].Y.LoByte());
158                 goto case TouchDataRegisters.TouchWeight;
159             case TouchDataRegisters.TouchWeight:
160                 queue.Enqueue(0);
161                 goto case TouchDataRegisters.TouchMisc;
162             case TouchDataRegisters.TouchMisc:
163                 queue.Enqueue(0);
164                 break;
165             default:
166                 throw new Exception("Should not reach here.");
167             }
168             SetReturnValue(queue.ToArray());
169         }
170 
SetReturnValue(params byte[] bytes)171         private void SetReturnValue(params byte[] bytes)
172         {
173             currentReturnValue = bytes;
174         }
175 
176         private byte[] currentReturnValue;
177         private Registers lastWriteRegister;
178         private readonly bool isRotated;
179 
180         private readonly TouchedPoint[] touchedPoints = new TouchedPoint[5];
181 
182         private const byte ChipVendorId = 0x51;
183 
184         private const int TouchInfoSize = TouchDataRegisters.TouchMisc - TouchDataRegisters.TouchXHigh + 1;
185 
186         private struct TouchedPoint
187         {
188             public UInt16 X;
189             public UInt16 Y;
190             public UInt16 Id;
191             public PointType Type;
192         }
193 
194         private enum PointType
195         {
196             Down = 0,
197             Up = 1,
198             Contact = 2,
199             Reserved = 3
200         }
201 
202         private enum TouchDataRegisters
203         {
204             TouchXHigh = 0x0,
205             TouchXLow = 0x1,
206             TouchYHigh = 0x2,
207             TouchYLow = 0x3,
208             TouchWeight = 0x4,
209             TouchMisc = 0x5,
210         }
211 
212         private enum Registers
213         {
214             GestureId = 0x1,
215             TouchDataStatus = 0x2,
216             TouchBeginRegister = 0x3,
217             TouchEndRegister = 0x21,
218             InterruptStatus = 0xA4,
219             ChipVendorId = 0xA8
220         }
221     }
222 }
223 
224