rpio-define
Version:
Modern style define GPIO for RaspberryPi.
204 lines (202 loc) • 8.21 kB
JavaScript
"use strict";
/** @license original source: https://github.com/ros2jsguy/mpu6050-motion-data/blob/081986/src/rpio-i2c-helper.ts */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.I2CDevice = void 0;
const rpio_1 = __importDefault(require("rpio"));
// TODO - repalce this constant with actual enum type returned from
// rpio.i2cWriteXXX() once the typescript definitions have been
// udpated, https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/rpio
const I2C_SUCCESS = 0; // I2cStatusCode.OK
/**
This class copy from @ros2jsguy mpu6050-motion-data: https://github.com/ros2jsguy/mpu6050-motion-data/blob/0819863463db455c88a37b94c9280dba9a5118b2/src/rpio-i2c-helper.ts
(* but not compatible.)
usage.
```typescript
enum Register1 {
INT_STATUS = 0x3A,
ACCEL_XOUT_H = 0x3B,
TEMP_OUT_H = 0x41,
GYRO_XOUT_H = 0x43,
}
const mpu6050 = new I2CDevice<Register1>({
deviceAddr: 0x68
})
mpu6050.readBit(Register1.ACCEL_XOUT_H, 1)
mpu6050.readBit(Register1.ACCEL_XOUT_H + 2, 1) // allow unknown address
```
or
```typescript
const Register2 = Object.freeze({
INT_STATUS : 0x3A,
ACCEL_XOUT_H : 0x3B,
TEMP_OUT_H : 0x41,
GYRO_XOUT_H : 0x43,
} as const)
type ValueOf<T extends Object> = T[keyof T]
const mpu9050 = new I2CDevice<ValueOf<typeof Register2>>({
deviceAddr: 0x68
})
mpu9050.readBit(Register2.ACCEL_XOUT_H, 1)
mpu9050.readBit(Register2.ACCEL_XOUT_H + 2, 1) // disallow unknown address
```
*/
class I2CDevice {
constructor({ deviceAddr, baudRate = 100000, regBufferSize = 4, dataBufferSize = 42 }) {
// configure RPIO
// TODO - i2c should be setup/shutdown externally as i2c may have multiple slave devices
rpio_1.default.i2cBegin();
rpio_1.default.i2cSetBaudRate(baudRate);
this.deviceAddr = deviceAddr;
this.baudRate = baudRate;
const regArrayBuffer = new ArrayBuffer(regBufferSize);
const dataArrayBuffer = new ArrayBuffer(dataBufferSize);
this.regView = new DataView(regArrayBuffer);
this.dataView = new DataView(dataArrayBuffer);
this.regBuffer = Buffer.from(regArrayBuffer);
this.dataBuffer = Buffer.from(dataArrayBuffer);
}
shutdown() {
// TODO revise - see note above
rpio_1.default.i2cEnd();
}
/** Read a single bit from an 8-bit device register.
* @param regAddr Register regAddr to read from
* @param bitNum Bit position to read (0-7)
* @returns Status bit value
*/
readBit(regAddr, bitNum) {
const b = this.readByte(regAddr);
return ((b & (1 << bitNum)) >> bitNum);
}
/** Read multiple bits from an 8-bit device register.
* @param regAddr Register regAddr to read from
* @param bitStart First bit position to read (0-7)
* @param length Number of bits to read (not more than 8)
* @returns The bits read
*/
readBits(regAddr, bitStart, length) {
let b = this.readByte(regAddr);
const mask = ((1 << length) - 1) << (bitStart - length + 1);
b &= mask;
b >>= (bitStart - length + 1);
return b;
}
/** Read single byte from an 8-bit device register.
* @param regAddr Register regAddr to read from
* @returns The byte read.
*/
readByte(regAddr) {
const status = this.readBytes(regAddr, 1);
return this.dataView.getUint8(0);
}
/** Read multiple bytes from an 8-bit device register.
* @param regAddr First register regAddr to read from
* @param length Number of bytes to read
* @returns Buffer containing the read bytes
*/
readBytes(regAddr, byteCnt) {
// set register to read
this.regView.setUint8(0, regAddr);
rpio_1.default.i2cSetSlaveAddress(this.deviceAddr);
rpio_1.default.i2cSetBaudRate(this.baudRate);
rpio_1.default.i2cWrite(this.regBuffer, 1);
// read register data
rpio_1.default.i2cRead(this.dataBuffer, byteCnt);
return this.dataBuffer.subarray(0, byteCnt);
}
/** Read single word from a 16-bit device register.
* @param regAddr Register regAddr to read from
* @return The 16-bit word read.
*/
readWord(regAddr) {
this.readBytes(regAddr, 2);
return this.dataView.getUint16(0, false);
}
/**
* Write a single bit in an 8-bit device register.
* @param regAddr Register regAddr to write to
* @param bitNum Bit position to write (0-7)
* @param data New bit value to write
* @returns Status of operation (0 = success)
*/
writeBit(regAddr, bitNum, data) {
let b = this.readByte(regAddr);
b = (data !== 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));
this.writeByte(regAddr, b);
return I2C_SUCCESS;
}
/** Write multiple bits in an 8-bit device register.
* @param regAddr Register regAddr to write to
* @param bitStart First bit position to write (0-7)
* @param length Number of bits to write (not more than 8)
* @param bits Right-aligned value to write
* @returns Status of operation (0 = success)
*/
writeBits(regAddr, bitStart, length, bits) {
// 010 value to write
// 76543210 bit numbers
// xxx args: bitStart=4, length=3
// 00011100 mask byte
// 10101111 original value (sample)
// 10100011 original & ~mask
// 10101011 masked | value
let b = this.readByte(regAddr);
const mask = ((1 << length) - 1) << (bitStart - length + 1);
let data = bits << (bitStart - length + 1); // bits data into correct position
data &= mask; // zero all non-important bits in data
b &= ~(mask); // zero all important bits in existing byte
b |= data; // combine data with existing byte
this.writeByte(regAddr, b);
return I2C_SUCCESS;
}
/** Write single byte to an 8-bit device register.
* @param regAddr Register address to write to
* @param data New byte value to write
* @returns Status of operation (0 = success)
*/
writeByte(regAddr, data) {
// identify register and data to write
this.dataView.setUint8(0, regAddr);
this.dataView.setUint8(1, data);
// write to register
rpio_1.default.i2cSetSlaveAddress(this.deviceAddr);
rpio_1.default.i2cSetBaudRate(this.baudRate);
rpio_1.default.i2cWrite(this.dataBuffer, 2);
return I2C_SUCCESS;
}
/** Write multiple bytes to an 8-bit device register.
* @param regAddr First register address to write to
* @param data Buffer to copy new data from
* @returns Status of operation (0 = success)
*/
writeBytes(regAddr, data) {
// identify register and data to write
this.dataView.setUint8(0, regAddr);
for (let i = 0; i < data.length; i++) {
this.dataView.setUint8(i + 1, data[i]);
}
rpio_1.default.i2cSetSlaveAddress(this.deviceAddr);
rpio_1.default.i2cSetBaudRate(this.baudRate);
rpio_1.default.i2cWrite(this.dataBuffer, data.length + 1);
return I2C_SUCCESS;
}
/** Write 2 byte number to a 16-bit device register.
* @param regAddr First register address to write to
* @param data Data to copy
* @returns Status of operation (0 = success)
*/
writeWord(regAddr, data) {
// identify register and data to write
this.dataView.setUint8(0, regAddr);
this.dataView.setUint16(1, data, false);
// write to register
rpio_1.default.i2cSetSlaveAddress(this.deviceAddr);
rpio_1.default.i2cSetBaudRate(this.baudRate);
rpio_1.default.i2cWrite(this.dataBuffer, 3);
return I2C_SUCCESS;
}
}
exports.I2CDevice = I2CDevice;