PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/Main/Modules/GHIElectronics/RotaryH1/Software/RotaryH1/RotaryH1_42/RotaryH1_42.cs

#
C# | 296 lines | 217 code | 53 blank | 26 comment | 13 complexity | b2e096f628529e7e4f61ba9c40633f0b MD5 | raw file
  1. #define USE_SOFTWARE_SPI
  2. using System.Threading;
  3. using GT = Gadgeteer;
  4. using GTI = Gadgeteer.Interfaces;
  5. using GTM = Gadgeteer.Modules;
  6. namespace Gadgeteer.Modules.GHIElectronics
  7. {
  8. /// <summary>
  9. /// A RotaryH1 module for Microsoft .NET Gadgeteer
  10. /// </summary>
  11. public class RotaryH1 : GTM.Module
  12. {
  13. private byte[] write1 = new byte[1];
  14. private byte[] write2 = new byte[2];
  15. private byte[] read2 = new byte[2];
  16. private byte[] read4 = new byte[4];
  17. private GTI.DigitalOutput Enable;
  18. #if USE_SOFTWARE_SPI
  19. private GTI.DigitalInput MISO;
  20. private GTI.DigitalOutput MOSI;
  21. private GTI.DigitalOutput CLOCK;
  22. private GTI.DigitalOutput CS;
  23. #else
  24. private readonly GTI.SPI.Configuration config;
  25. private readonly GTI.SPI spi;
  26. #endif
  27. /// <summary>Constructs a new instance of the RotaryH1 module.</summary>
  28. /// <param name="socketNumber">The socket that this module is plugged in to.</param>
  29. public RotaryH1(int socketNumber)
  30. {
  31. Socket socket = Socket.GetSocket(socketNumber, true, this, null);
  32. #if USE_SOFTWARE_SPI
  33. socket.EnsureTypeIsSupported('Y', this);
  34. this.CS = new GTI.DigitalOutput(socket, Socket.Pin.Six, true, this);
  35. this.MISO = new GTI.DigitalInput(socket, Socket.Pin.Eight, GTI.GlitchFilterMode.Off, GTI.ResistorMode.Disabled, this);
  36. this.MOSI = new GTI.DigitalOutput(socket, Socket.Pin.Seven, false, this);
  37. this.CLOCK = new GTI.DigitalOutput(socket, Socket.Pin.Nine, false, this);
  38. #else
  39. socket.EnsureTypeIsSupported('S', this);
  40. this.config = new GTI.SPI.Configuration(false, 0, 0, false, true, 1000);
  41. this.spi = new GTI.SPI(socket, this.config, GTI.SPI.Sharing.Shared, socket, GT.Socket.Pin.Six, this);
  42. #endif
  43. this.Enable = new GTI.DigitalOutput(socket, Socket.Pin.Five, true, this);
  44. this.Initialize();
  45. }
  46. /// <summary>
  47. /// Gets the current count of the encoder.
  48. /// </summary>
  49. /// <returns>An integer representing the count.</returns>
  50. public int GetCount()
  51. {
  52. int count = this.Read2((byte)Commands.LS7366_READ | (byte)Registers.LS7366_CNTR);
  53. if ((this.ReadStatusReg() & 0x1) > 0) // native number
  54. {
  55. count = ~count;
  56. count &= 0x7FFF;
  57. count *= (-1);
  58. }
  59. return count;
  60. }
  61. /// <summary>
  62. /// Gets the current direction that the encoder count is going.
  63. /// </summary>
  64. /// <returns>The direction the encoder count is going.</returns>
  65. public Direction GetDirection()
  66. {
  67. return ((this.ReadStatusReg() & 0x2) >> 1) > 0 ? Direction.CounterClockwise : Direction.Clockwise;
  68. }
  69. private void Initialize()
  70. {
  71. this.Write((byte)Commands.LS7366_CLEAR | (byte)Registers.LS7366_MDR0);
  72. this.Write((byte)Commands.LS7366_CLEAR | (byte)Registers.LS7366_MDR1);
  73. this.Write((byte)Commands.LS7366_CLEAR | (byte)Registers.LS7366_STR);
  74. this.Write((byte)Commands.LS7366_CLEAR | (byte)Registers.LS7366_CNTR);
  75. this.Write((byte)Commands.LS7366_LOAD | (byte)Registers.LS7366_OTR);
  76. this.Write((byte)Commands.LS7366_WRITE | (byte)Registers.LS7366_MDR0,
  77. (byte)MDR0Mode.LS7366_MDR0_QUAD1 // none quadrature mode
  78. | (byte)MDR0Mode.LS7366_MDR0_FREER // modulo-n counting
  79. | (byte)MDR0Mode.LS7366_MDR0_DIDX
  80. | (byte)MDR0Mode.LS7366_MDR0_FFAC2);
  81. this.Write((byte)Commands.LS7366_WRITE | (byte)Registers.LS7366_MDR1,
  82. (byte)MDR1Mode.LS7366_MDR1_2BYTE // 2 byte counter mode
  83. | (byte)MDR1Mode.LS7366_MDR1_ENCNT); // enable counting
  84. }
  85. private byte ReadStatusReg()
  86. {
  87. return this.Read1((byte)((byte)Commands.LS7366_READ | (byte)Registers.LS7366_STR));
  88. }
  89. private byte Read1(byte register)
  90. {
  91. write1[0] = register;
  92. #if USE_SOFTWARE_SPI
  93. this.SoftwareSPI_WriteRead(write1, read2);
  94. #else
  95. this.spi.WriteRead(write1, read2);
  96. #endif
  97. return read2[1];
  98. }
  99. private short Read2(byte register)
  100. {
  101. write1[0] = register;
  102. #if USE_SOFTWARE_SPI
  103. this.SoftwareSPI_WriteRead(write1, read4);
  104. #else
  105. this.spi.WriteRead(write1, read4);
  106. #endif
  107. return (short)((read4[1] << 8) + read4[2]);
  108. }
  109. private void Write(byte register)
  110. {
  111. write1[0] = register;
  112. #if USE_SOFTWARE_SPI
  113. this.SoftwareSPI_WriteRead(write1, null);
  114. #else
  115. this.spi.Write(write1);
  116. #endif
  117. }
  118. private void Write(byte register, byte command)
  119. {
  120. write2[0] = register;
  121. write2[1] = command;
  122. #if USE_SOFTWARE_SPI
  123. this.SoftwareSPI_WriteRead(write2, null);
  124. #else
  125. this.spi.Write(write2);
  126. #endif
  127. }
  128. #if USE_SOFTWARE_SPI
  129. private void SoftwareSPI_WriteRead(byte[] write, byte[] read)
  130. {
  131. int writeLen = write.Length;
  132. int readLen = 0;
  133. if (read != null)
  134. {
  135. readLen = read.Length;
  136. for (int i = 0; i < readLen; i++)
  137. {
  138. read[i] = 0;
  139. }
  140. }
  141. int loopLen = (writeLen < readLen ? readLen : writeLen);
  142. byte w = 0;
  143. CS.Write(false);
  144. // per byte
  145. for (int len = 0; len < loopLen; len++)
  146. {
  147. if (len < writeLen)
  148. w = write[len];
  149. byte mask = 0x80;
  150. // per bit
  151. for (int i = 0; i < 8; i++)
  152. {
  153. CLOCK.Write(false);
  154. if ((w & mask) == mask)
  155. MOSI.Write(true);
  156. else
  157. MOSI.Write(false);
  158. CLOCK.Write(true);
  159. if (true == MISO.Read())
  160. if (read != null)
  161. read[len] |= mask;
  162. mask >>= 1;
  163. }
  164. MOSI.Write(false);
  165. CLOCK.Write(false);
  166. }
  167. Thread.Sleep(20);
  168. CS.Write(true);
  169. }
  170. #endif
  171. /// <summary>
  172. /// The direction the encoder is being turned.
  173. /// </summary>
  174. public enum Direction : byte
  175. {
  176. /// <summary>
  177. /// The encoder is moving in a counter-clockwise direction.
  178. /// </summary>
  179. CounterClockwise,
  180. /// <summary>
  181. /// The encoder is moving in a clockwise direction.
  182. /// </summary>
  183. Clockwise
  184. }
  185. private enum Commands : byte
  186. {
  187. LS7366_CLEAR = 0x00, // clear register
  188. LS7366_READ = 0x40, // read register
  189. LS7366_WRITE = 0x80, // write register
  190. LS7366_LOAD = 0xC0, // load register
  191. }
  192. private enum Registers : byte
  193. {
  194. LS7366_MDR0 = 0x08, // select MDR0
  195. LS7366_MDR1 = 0x10, // select MDR1
  196. LS7366_DTR = 0x18, // select DTR
  197. LS7366_CNTR = 0x20, // select CNTR
  198. LS7366_OTR = 0x28, // select OTR
  199. LS7366_STR = 0x30, // select STR
  200. }
  201. private enum MDR0Mode : byte
  202. {
  203. LS7366_MDR0_QUAD0 = 0x00, // none quadrature mode
  204. LS7366_MDR0_QUAD1 = 0x01, // quadrature x1 mode
  205. LS7366_MDR0_QUAD2 = 0x02, // quadrature x2 mode
  206. LS7366_MDR0_QUAD4 = 0x03, // quadrature x4 mode
  207. LS7366_MDR0_FREER = 0x00, // free run mode
  208. LS7366_MDR0_SICYC = 0x04, // single cycle count mode
  209. LS7366_MDR0_RANGE = 0x08, // range limit count mode (0-DTR-0)
  210. // counting freezes at limits but
  211. // resumes on direction reverse
  212. LS7366_MDR0_MODTR = 0x0C, // modulo-n count (n=DTR both dirs)
  213. LS7366_MDR0_DIDX = 0x00, // disable index
  214. LS7366_MDR0_LDCNT = 0x10, // config IDX as load DTR to CNTR
  215. LS7366_MDR0_RECNT = 0x20, // config IDX as reset CNTR (=0)
  216. LS7366_MDR0_LDOTR = 0x30, // config IDX as load CNTR to OTR
  217. LS7366_MDR0_ASIDX = 0x00, // asynchronous index
  218. LS7366_MDR0_SYINX = 0x40, // synchronous IDX (if !NQUAD)
  219. LS7366_MDR0_FFAC1 = 0x00, // filter clock division factor=1
  220. LS7366_MDR0_FFAC2 = 0x80, // filter clock division factor=2
  221. LS7366_MDR0_NOFLA = 0x00, // no flags
  222. }
  223. private enum CountMode : byte
  224. {
  225. NoneQuad = 0x00, // none quadrature mode
  226. Quad1 = 0x01, // quadrature x1 mode
  227. Quad2 = 0x02, // quadrature x2 mode
  228. Quad4 = 0x03, // quadrature x4 mode
  229. }
  230. private enum MDR1Mode : byte
  231. {
  232. LS7366_MDR1_4BYTE = 0x00, // 4 byte counter mode
  233. LS7366_MDR1_3BYTE = 0x01, // 3 byte counter mode
  234. LS7366_MDR1_2BYTE = 0x02, // 2 byte counter mode
  235. LS7366_MDR1_1BYTE = 0x03, // 1 byte counter mode
  236. LS7366_MDR1_ENCNT = 0x00, // enable counting
  237. LS7366_MDR1_DICNT = 0x04, // disable counting
  238. LS7366_MDR1_FLIDX = 0x20, // FLAG on IDX (index)
  239. LS7366_MDR1_FLCMP = 0x40, // FLAG on CMP (compare)
  240. LS7366_MDR1_FLCY = 0x80, // FLAG on CY (carry)
  241. }
  242. }
  243. }