1 // 2 // Copyright (c) 2010-2020 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Peripherals.I2C; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Utilities; 13 using System.Linq; 14 using System.Collections.Generic; 15 16 namespace Antmicro.Renode.Peripherals.Input 17 { 18 public class AR1021 : II2CPeripheral, IAbsolutePositionPointerInput 19 { AR1021()20 public AR1021() 21 { 22 IRQ = new GPIO(); 23 } 24 Write(byte[] data)25 public void Write(byte[] data) 26 { 27 this.DebugLog("Writing {0}.", data.Select(x => x.ToString()).Stringify()); 28 } 29 Read(int count)30 public byte[] Read(int count) 31 { 32 var returnValue = currentRetValue ?? new byte[5]; 33 this.DebugLog("Read returning {0}.", returnValue.Select(x => x.ToString()).Stringify()); 34 readItAlready = true; 35 return returnValue; 36 } 37 FinishTransmission()38 public void FinishTransmission() 39 { 40 } 41 Reset()42 public void Reset() 43 { 44 readQueue.Clear(); 45 readItAlready = false; 46 pressed = false; 47 currentRetValue = null; 48 } 49 MoveTo(int x, int y)50 public void MoveTo(int x, int y) 51 { 52 points[0].X = (ushort)(y); 53 points[0].Y = (ushort)(x); 54 if(points[0].Type == PointType.Down) 55 { 56 this.DebugLog("Moving the pointer to {0}x{1}", x, y); 57 EnqueueNewPoint(); 58 IRQ.Set(); 59 } 60 } 61 Press(MouseButton button = MouseButton.Left)62 public void Press(MouseButton button = MouseButton.Left) 63 { 64 pressed = true; 65 points[0].Type = PointType.Down; 66 this.DebugLog("Button pressed, sending press signal at {0}x{1}.", points[0].X, points[0].Y); 67 EnqueueNewPoint(); 68 IRQ.Set(); 69 } 70 Release(MouseButton button = MouseButton.Left)71 public void Release(MouseButton button = MouseButton.Left) 72 { 73 this.Log(LogLevel.Noisy, "Sending release signal"); 74 points[0].Type = PointType.Up; 75 pressed = false; 76 EnqueueNewPoint(); 77 IRQ.Set(); 78 this.DebugLog("Button released at {0}x{1}.", points[0].X, points[0].Y); 79 } 80 81 public GPIO IRQ 82 { 83 get; 84 private set; 85 } 86 87 public int MaxY 88 { 89 get{ return 4095; } 90 } 91 92 public int MaxX 93 { 94 get{ return 4095; } 95 } 96 97 public int MinX 98 { 99 get { return 0; } 100 } 101 102 public int MinY 103 { 104 get { return 0; } 105 } 106 PressAgainIfNeeded()107 private void PressAgainIfNeeded() 108 { 109 var newPacket = false; 110 if(readQueue.Any()) 111 { 112 this.Log(LogLevel.Noisy, "Another packet to send."); 113 newPacket = true; 114 currentRetValue = readQueue.Dequeue(); 115 readItAlready = false; 116 } 117 if(pressed || newPacket || !readItAlready) 118 { 119 this.Log(LogLevel.Noisy, "Sending signal again at {0}x{1}, state is {2}.", points[0].X, points[0].Y, points[0].Type); 120 IRQ.Set(); 121 } 122 else 123 { 124 this.Log(LogLevel.Noisy, "No more packets."); 125 currentRetValue = null; 126 } 127 } 128 EnqueueNewPoint()129 private void EnqueueNewPoint() 130 { 131 var data = PrepareTouchData(); 132 if(currentRetValue == null) 133 { 134 this.Log(LogLevel.Noisy, "Setting currentRetValue"); 135 currentRetValue = data; 136 readItAlready = false; 137 } 138 else 139 { 140 this.Log(LogLevel.Noisy, "Enqueueing packet"); 141 readQueue.Enqueue(data); 142 if(IRQ.IsSet) 143 { 144 this.Log(LogLevel.Noisy, "Forcing IRQ"); 145 IRQ.Unset(); 146 IRQ.Set(); 147 } 148 } 149 } 150 PrepareTouchData()151 private byte[] PrepareTouchData() 152 { 153 var data = new byte[5]; 154 data[0] = (byte)(0x80 | ((points[0].Type == PointType.Down) ? 0x1 : 0)); 155 data[2] = (byte)((points[0].X >> 7) & 0x1f); 156 data[1] = (byte)(points[0].X & 0x7f); 157 data[4] = (byte)((points[0].Y >> 7) & 0x1f); 158 data[3] = (byte)(points[0].Y & 0x7f); 159 return data; 160 } 161 162 private Queue<byte[]> readQueue = new Queue<byte[]>(); 163 private readonly TouchedPoint[] points = new TouchedPoint[1]; 164 private byte[] currentRetValue; 165 private bool pressed; 166 private bool readItAlready; 167 168 private enum Command : byte 169 { 170 Reset = 0x10, 171 ScanComplete = 0x11 172 } 173 174 private struct TouchedPoint 175 { 176 public UInt16 X; 177 public UInt16 Y; 178 public PointType Type; 179 } 180 181 private enum PointType 182 { 183 Up = 0, 184 Down = 1 185 } 186 } 187 } 188