Advertisement
Guest User

Untitled

a guest
Jan 31st, 2015
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.70 KB | None | 0 0
  1. Here are the methods that a J5 IO-Plugin is expected to implement:
  2.  
  3. * i2cWrite(address, inBytes)
  4. * i2cWrite(address, register, inBytes)
  5. * i2cWriteReg(address, register, value)
  6. * i2cRead(address, register, bytesToRead, handler)
  7. * i2cRead(address, bytesToRead, handler)
  8. * i2cReadOnce(address, register, bytesToRead, handler)
  9. * i2cReadOnce(address, bytesToRead, handler)
  10.  
  11.  
  12. Here are the functions available in WiringPi:
  13.  
  14. * int wiringPiI2CSetup(int devId);
  15. * int wiringPiI2CRead(int fd);
  16. * int wiringPiI2CWrite(int fd, int data);
  17. * int wiringPiI2CWriteReg8(int fd, int reg, int data);
  18. * int wiringPiI2CWriteReg16(int fd, int reg, int data);
  19. * int wiringPiI2CReadReg8(int fd, int reg);
  20. * int wiringPiI2CReadReg16(int fd, int reg);
  21.  
  22. WiringPi has functions to read or write a byte, read or write a byte register,
  23. and read or write a word register. Note that WiringPi doesn't have functions
  24. for reading or writing blocks of data, but most J5 methods are block methods.
  25.  
  26. The following table shows the direct mapping from J5 methods to WiringPi
  27. functions:
  28.  
  29. Johnny-Five | WiringPi
  30. :---: | :---:
  31. i2cWrite(address, inBytes) | no block write available
  32. i2cWrite(address, register, inBytes) | no block write to register available
  33. i2cWriteReg(address, register, value) | wiringPiI2CWriteReg8
  34. i2cRead(address, register, bytesToRead, handler) | no block read available
  35. i2cRead(address, bytesToRead, handler) | no block read available
  36. i2cReadOnce(address, register, bytesToRead, handler) | no block read available
  37. i2cReadOnce(address, bytesToRead, handler) | no block read available
  38.  
  39. Perhaps it's possible to implement the J5 block methods by calling WiringPi
  40. byte/word functions multiple times. If not, new functions could be
  41. implemented to perform the task.
  42.  
  43. The next question is "which thread does the code that reads and writes I2C data
  44. run in?" There are two possible answers here:
  45.  
  46. * In the same thread as the JavaScript code
  47. * In one or more worker threads
  48.  
  49. The worker thread option is available because Raspi-io uses C++ addons.
  50.  
  51. In Galileo-IO the code that reads and writes I2C data runs in the JavaScript
  52. thread. This is because Galileo-IO uses mraa under the covers and mraa only
  53. has blocking synchronous calls on offer. AFAIK, this is something Rick isn't
  54. to happy about. On the other hand, this make things a lot more deterministic
  55. and a lot easier to reason about. For example, because only one thread is
  56. involved, only one piece of code can be accessing the I2C bus at any point
  57. in time.
  58.  
  59. In BeagleBone-IO the code that reads I2C data runs in worker threads. The
  60. code that writes I2C data runs in the JavaScript thread. BeagleBone-IO uses
  61. the i2c-bus package under the covers and i2c-bus offers both blocking
  62. synchronous calls and non-blocking asynchronous calls. This means that
  63. multiple threads can be accessing the I2C bus at the same point in time.
  64. Even deeper under the covers, i2c-bus uses the Linux ioctl call. Multiple
  65. threads will end up calling this method at practically the same time. However,
  66. Linux has things organized so that these calls will not be stopped half way
  67. through. Each call will run to completion before the next call runs, perhaps
  68. in another thread.
  69.  
  70. In an early version of the BeagleBone-IO implementation there was code
  71. similar to the following in the continuous i2cRead method:
  72.  
  73. ```js
  74. BeagleBone.prototype.i2cRead = function(address, register, bytesToRead, handler) {
  75. ...
  76. setTimeout(function read() {
  77. ...
  78. this.i2cWrite(address, register);
  79. _i2c.i2cRead(address, bytesToRead, data, function(err) {
  80. ...
  81. setTimeout(read.bind(this), _i2cDelay);
  82. }.bind(this));
  83. }.bind(this), _i2cDelay);
  84.  
  85. return this;
  86. };
  87. ```
  88.  
  89. In a test program, this continuous read method was being called for two devices
  90. at the same time.
  91.  
  92. The call to `this.i2cWrite` is a blocking synchronous call and runs in
  93. the JavaScript thread, the call to `_i2c.i2cRead` results in a non-blocking worker
  94. thread reading the data asynchronously.
  95.  
  96. Between the call to `this.i2cWrite` and `_i2c.i2cRead`, there were sometimes
  97. context switches to worker threads and the I2C bus was accessed by the worker
  98. threads. This accesses to the bus messed up the prerequisites for the later call
  99. to `_i2c.i2cRead`.
  100.  
  101. In the current BeagleBone-IO implementation the code in the continuous i2cRead
  102. is similar to this:
  103.  
  104.  
  105. ```js
  106. BeagleBone.prototype.i2cRead = function(address, register, bytesToRead, handler) {
  107. ...
  108. setTimeout(function read() {
  109. ...
  110. _i2c.readI2cBlock(address, register, bytesToRead, data, function(err) {
  111. ...
  112. setTimeout(read.bind(this), _i2cDelay);
  113. }.bind(this));
  114. }.bind(this), _i2cDelay);
  115.  
  116. return this;
  117. };
  118.  
  119. ```
  120.  
  121. The two calls to `this.i2cWrite` and `_i2c.i2cRead` were replaced by a single
  122. call to `_i2c.readI2cBlock` and everything works as expected.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement