Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Here are the methods that a J5 IO-Plugin is expected to implement:
- * i2cWrite(address, inBytes)
- * i2cWrite(address, register, inBytes)
- * i2cWriteReg(address, register, value)
- * i2cRead(address, register, bytesToRead, handler)
- * i2cRead(address, bytesToRead, handler)
- * i2cReadOnce(address, register, bytesToRead, handler)
- * i2cReadOnce(address, bytesToRead, handler)
- Here are the functions available in WiringPi:
- * int wiringPiI2CSetup(int devId);
- * int wiringPiI2CRead(int fd);
- * int wiringPiI2CWrite(int fd, int data);
- * int wiringPiI2CWriteReg8(int fd, int reg, int data);
- * int wiringPiI2CWriteReg16(int fd, int reg, int data);
- * int wiringPiI2CReadReg8(int fd, int reg);
- * int wiringPiI2CReadReg16(int fd, int reg);
- WiringPi has functions to read or write a byte, read or write a byte register,
- and read or write a word register. Note that WiringPi doesn't have functions
- for reading or writing blocks of data, but most J5 methods are block methods.
- The following table shows the direct mapping from J5 methods to WiringPi
- functions:
- Johnny-Five | WiringPi
- :---: | :---:
- i2cWrite(address, inBytes) | no block write available
- i2cWrite(address, register, inBytes) | no block write to register available
- i2cWriteReg(address, register, value) | wiringPiI2CWriteReg8
- i2cRead(address, register, bytesToRead, handler) | no block read available
- i2cRead(address, bytesToRead, handler) | no block read available
- i2cReadOnce(address, register, bytesToRead, handler) | no block read available
- i2cReadOnce(address, bytesToRead, handler) | no block read available
- Perhaps it's possible to implement the J5 block methods by calling WiringPi
- byte/word functions multiple times. If not, new functions could be
- implemented to perform the task.
- The next question is "which thread does the code that reads and writes I2C data
- run in?" There are two possible answers here:
- * In the same thread as the JavaScript code
- * In one or more worker threads
- The worker thread option is available because Raspi-io uses C++ addons.
- In Galileo-IO the code that reads and writes I2C data runs in the JavaScript
- thread. This is because Galileo-IO uses mraa under the covers and mraa only
- has blocking synchronous calls on offer. AFAIK, this is something Rick isn't
- to happy about. On the other hand, this make things a lot more deterministic
- and a lot easier to reason about. For example, because only one thread is
- involved, only one piece of code can be accessing the I2C bus at any point
- in time.
- In BeagleBone-IO the code that reads I2C data runs in worker threads. The
- code that writes I2C data runs in the JavaScript thread. BeagleBone-IO uses
- the i2c-bus package under the covers and i2c-bus offers both blocking
- synchronous calls and non-blocking asynchronous calls. This means that
- multiple threads can be accessing the I2C bus at the same point in time.
- Even deeper under the covers, i2c-bus uses the Linux ioctl call. Multiple
- threads will end up calling this method at practically the same time. However,
- Linux has things organized so that these calls will not be stopped half way
- through. Each call will run to completion before the next call runs, perhaps
- in another thread.
- In an early version of the BeagleBone-IO implementation there was code
- similar to the following in the continuous i2cRead method:
- ```js
- BeagleBone.prototype.i2cRead = function(address, register, bytesToRead, handler) {
- ...
- setTimeout(function read() {
- ...
- this.i2cWrite(address, register);
- _i2c.i2cRead(address, bytesToRead, data, function(err) {
- ...
- setTimeout(read.bind(this), _i2cDelay);
- }.bind(this));
- }.bind(this), _i2cDelay);
- return this;
- };
- ```
- In a test program, this continuous read method was being called for two devices
- at the same time.
- The call to `this.i2cWrite` is a blocking synchronous call and runs in
- the JavaScript thread, the call to `_i2c.i2cRead` results in a non-blocking worker
- thread reading the data asynchronously.
- Between the call to `this.i2cWrite` and `_i2c.i2cRead`, there were sometimes
- context switches to worker threads and the I2C bus was accessed by the worker
- threads. This accesses to the bus messed up the prerequisites for the later call
- to `_i2c.i2cRead`.
- In the current BeagleBone-IO implementation the code in the continuous i2cRead
- is similar to this:
- ```js
- BeagleBone.prototype.i2cRead = function(address, register, bytesToRead, handler) {
- ...
- setTimeout(function read() {
- ...
- _i2c.readI2cBlock(address, register, bytesToRead, data, function(err) {
- ...
- setTimeout(read.bind(this), _i2cDelay);
- }.bind(this));
- }.bind(this), _i2cDelay);
- return this;
- };
- ```
- The two calls to `this.i2cWrite` and `_i2c.i2cRead` were replaced by a single
- call to `_i2c.readI2cBlock` and everything works as expected.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement