i2cdevice.bmx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. ' Copyright (c) .NET Foundation and Contributors
  2. ' Copyright (c) 2019 Bruce A Henderson
  3. '
  4. ' All rights reserved.
  5. '
  6. ' Permission is hereby granted, free of charge, to any person obtaining a copy
  7. ' of this software and associated documentation files (the "Software"), to deal
  8. ' in the Software without restriction, including without limitation the rights
  9. ' to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. ' copies of the Software, and to permit persons to whom the Software is
  11. ' furnished to do so, subject to the following conditions:
  12. '
  13. ' The above copyright notice and this permission notice shall be included in all
  14. ' copies or substantial portions of the Software.
  15. '
  16. ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. ' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. ' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. ' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. ' OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. ' SOFTWARE.
  23. '
  24. SuperStrict
  25. Import brl.threads
  26. Import brl.stringbuilder
  27. Import brl.standardio
  28. Import "../../common.bmx"
  29. Const DEBUG_WRITE:Int = False
  30. Rem
  31. bbdoc: The communications channel to a device on an I2C bus.
  32. End Rem
  33. Type TI2cDevice Implements IDisposable
  34. Const DEFAULT_DEVICE_PATH:String = "/dev/i2c"
  35. Field ReadOnly settings:TI2cConnectionSettings
  36. Field deviceFileDescriptor:Int = -1
  37. Field functionalities:EI2cFunctionalityFlags
  38. Field devicePath:String
  39. Field initializationLock:TMutex = TMutex.Create()
  40. Method New(settings:TI2cConnectionSettings)
  41. Self.settings = settings
  42. devicePath = DEFAULT_DEVICE_PATH
  43. End Method
  44. Private
  45. Method Initialize()
  46. If deviceFileDescriptor >= 0 Then
  47. Return
  48. End If
  49. Local deviceFileName:String = devicePath + "-" + settings.GetBusId()
  50. Try
  51. initializationLock.Lock()
  52. deviceFileDescriptor = open_(deviceFileName, O_RDWR)
  53. If deviceFileDescriptor < 0 Then
  54. Throw New TIOException("Cannot open I2C device file '" + deviceFileName + "'.")
  55. End If
  56. Local tempFlags:EI2cFunctionalityFlags
  57. Local result:Int = ioctli2_(deviceFileDescriptor, EI2cSettings.I2C_FUNCS.Ordinal(), tempFlags)
  58. If result < 0 Then
  59. functionalities = EI2cFunctionalityFlags.None
  60. Else
  61. functionalities = tempFlags
  62. End If
  63. Finally
  64. initializationLock.Unlock()
  65. End Try
  66. End Method
  67. Method Transfer(writeBuffer:Byte Ptr, writeLength:Size_T, readBuffer:Byte Ptr, readLength:Size_T)
  68. If functionalities & EI2cFunctionalityFlags.I2C_FUNC_I2C Then
  69. ReadWriteInterfaceTransfer(writeBuffer, writeLength, readBuffer, readLength)
  70. Else
  71. FileInterfaceTransfer(writeBuffer, writeLength, readBuffer, readLength)
  72. End If
  73. End Method
  74. Method ReadWriteInterfaceTransfer(writeBuffer:Byte Ptr, writeLength:Size_T, readBuffer:Byte Ptr, readLength:Size_T)
  75. Local messages:i2c_msg[2]
  76. Local messageCount:UInt
  77. If writeBuffer Then
  78. If DEBUG_WRITE Then
  79. Local sb:TStringBuilder = New TStringBuilder()
  80. sb.Format("0x%x:", settings.GetDeviceAddress()).Format("0x%x:", writeBuffer[0])
  81. If writeLength = 2 Then
  82. sb.Format("0x%x", writeBuffer[1])
  83. Else If writelength > 2 Then
  84. For Local i:Int = 0 Until writelength - 1
  85. sb.Format("%02x", writeBuffer[1 + i])
  86. Next
  87. End If
  88. Print sb.ToString()
  89. End If
  90. messages[messageCount] = New i2c_msg(Short(settings.GetDeviceAddress()), Short(EI2cMessageFlags.I2C_M_WR), Short(writeLength), writeBuffer)
  91. messageCount :+ 1
  92. End If
  93. If readBuffer Then
  94. messages[messageCount] = New i2c_msg(Short(settings.GetDeviceAddress()), Short(EI2cMessageFlags.I2C_M_RD), Short(readLength), readBuffer)
  95. messageCount :+ 1
  96. End If
  97. Local msgset:i2c_rdwr_ioctl_data = New i2c_rdwr_ioctl_data(messages, messageCount)
  98. Local result:Int = ioctl_(deviceFileDescriptor, EI2cSettings.I2C_RDWR.Ordinal(), msgset)
  99. If result < 0 Then
  100. Throw New TIOException("Error performing I2C data transfer.")
  101. End If
  102. End Method
  103. Method FileInterfaceTransfer(writeBuffer:Byte Ptr, writeLength:Size_T, readBuffer:Byte Ptr, readLength:Size_T)
  104. Local result:Int = ioctli_(deviceFileDescriptor, EI2cSettings.I2C_SLAVE_FORCE.Ordinal(), settings.DeviceAddress)
  105. If result < 0 Then
  106. Throw New TIOException("Error performing I2C data transfer.")
  107. End If
  108. If writeBuffer Then
  109. result = write_(deviceFileDescriptor, writeBuffer, writeLength)
  110. If result < 0 Then
  111. Throw New TIOException("Error performing I2C data transfer.")
  112. End If
  113. End If
  114. If readBuffer Then
  115. result = read_(deviceFileDescriptor, readBuffer, readLength)
  116. If result < 0 Then
  117. Throw New TIOException("Error performing I2C data transfer.")
  118. End If
  119. End If
  120. End Method
  121. Public
  122. Rem
  123. bbdoc: Reads a byte from the I2C device.
  124. End Rem
  125. Method ReadByte:Byte()
  126. Initialize()
  127. Local result:Byte
  128. Transfer(Null, 0, Varptr result, 1)
  129. Return result
  130. End Method
  131. Rem
  132. bbdoc: Reads data from the I2C device.
  133. End Rem
  134. Method Read(buffer:Byte Ptr, length:Size_T)
  135. Initialize()
  136. Transfer(Null, 0, buffer, length)
  137. End Method
  138. Rem
  139. bbdoc: Writes a byte to the I2C device.
  140. End Rem
  141. Method WriteByte(value:Byte)
  142. Initialize()
  143. Transfer(Varptr value, 1, Null, 0)
  144. End Method
  145. Rem
  146. bbdoc: Writes data to the I2C device.
  147. End Rem
  148. Method Write(buffer:Byte Ptr, length:Size_T)
  149. Initialize()
  150. Transfer(buffer, length, Null, 0)
  151. End Method
  152. Rem
  153. bbdoc: Performs an atomic operation to write data to and then read data from the I2C bus on which the device is connected, and sends a restart condition between the write and read operations.
  154. End Rem
  155. Method WriteRead(writeBuffer:Byte Ptr, writeLength:Size_T, readBuffer:Byte Ptr, readLength:Size_T)
  156. Initialize()
  157. Transfer(writeBuffer, writeLength, readBuffer, readLength)
  158. End Method
  159. Rem
  160. bbdoc: Returns the path to I2C resources located on the system.
  161. End Rem
  162. Method GetDevicePath:String()
  163. Return devicePath
  164. End Method
  165. Rem
  166. bbdoc: Sets the path to I2C resources located on the system.
  167. End Rem
  168. Method SetDevicePath(devicePath:String)
  169. Self.devicePath = devicePath
  170. End Method
  171. Rem
  172. bbdoc: Returns the connection settings of a device on an I2C bus.
  173. End Rem
  174. Method GetConnectionSettings:TI2cConnectionSettings()
  175. Return settings
  176. End Method
  177. Method Dispose() Override
  178. If deviceFileDescriptor >= 0 Then
  179. close_(deviceFileDescriptor)
  180. deviceFileDescriptor = -1
  181. End If
  182. End Method
  183. End Type
  184. Rem
  185. bbdoc: The connection settings of a device on an I2C bus.
  186. End Rem
  187. Type TI2cConnectionSettings
  188. Field ReadOnly busId:Int
  189. Field ReadOnly deviceAddress:Int
  190. Rem
  191. bbdoc: Creates a new instance of #TI2cConnectionSettings.
  192. End Rem
  193. Method New(busId:Int, deviceAddress:Int)
  194. Self.busId = busId
  195. Self.deviceAddress = deviceAddress
  196. End Method
  197. Rem
  198. bbdoc: Creates a copy of a #TI2cConnectionSettings.
  199. End Rem
  200. Method New(other:TI2cConnectionSettings)
  201. busId = other.busId
  202. deviceAddress = other.deviceAddress
  203. End Method
  204. Rem
  205. bbdoc: Returns the bus id that the I2C device is connected to.
  206. End Rem
  207. Method GetBusId:Int()
  208. Return busId
  209. End Method
  210. Rem
  211. bbdoc: Returns the bus address of the I2C device.
  212. End Rem
  213. Method GetDeviceAddress:Int()
  214. Return deviceAddress
  215. End Method
  216. End Type