New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

array-gpio

Package Overview
Dependencies
Maintainers
1
Versions
96
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

array-gpio - npm Package Compare versions

Comparing version
1.7.2
to
1.7.3
+165
-168
lib/array-gpio.js

@@ -115,3 +115,3 @@ /*!

function startTime(){
d1 = new Date();
d1 = new Date();
}

@@ -142,8 +142,8 @@

if(debugStateAdvanced){
dmsg(1, pinCheck + ' ] *** Fail ***');
return false
dmsg(1, pinCheck + ' ] *** Fail ***');
return false
}
else{
console.log('** warning **');
duplicatePinError(arr1[x]);
console.log('** warning **');
duplicatePinError(arr1[x]);
}

@@ -158,7 +158,7 @@ }

/****************************************
* * *
* array-gpio class module *
* * *
****************************************/
/******************************
*
* array-gpio class module
*
******************************/
class ArrayGpio {

@@ -178,3 +178,3 @@

{
rpi.lib_close();
rpi.lib_close();
}

@@ -184,11 +184,10 @@

watchInput (edge, cb, td){
if(typeof edge === 'function' && typeof cb === 'number'){
td = cb;
cb = edge;
edge = null;
td = cb;
cb = edge;
edge = null;
}
else if(typeof edge === 'function' && cb === undefined){
cb = edge;
edge = null;
cb = edge;
edge = null;
}

@@ -199,9 +198,8 @@ else if(typeof edge !== 'string' && typeof edge !== 'number' && edge !== null){

else if ((typeof edge === 'string' || typeof edge === 'number') && typeof cb !== 'function'){
throw new Error('invalid callback argument');
throw new Error('invalid callback argument');
}
for (var x = 0; x < eventPin.length; x++) {
watchPin(edge, cb, eventPin[x], td);
watchPin(edge, cb, eventPin[x], td);
}
}

@@ -225,3 +223,2 @@

setInput () {
startTime();

@@ -231,9 +228,9 @@ var input = [], options = {}, inputPin = [], pinCheck = true, config, arraySetup;

if(arguments[0] === undefined || arguments[0] === null ){
console.log('\nsetInput() - empty argument!');
invalidPinError(arguments[0]);
console.log('\nsetInput() - empty argument!');
invalidPinError(arguments[0]);
}
if(typeof arguments[0] === 'string' || typeof arguments[0] === 'function' ){
console.log('\nsetInput() - invalid argument!');
invalidPinError(arguments[0]);
console.log('\nsetInput() - invalid argument!');
invalidPinError(arguments[0]);
}

@@ -243,4 +240,4 @@

if(typeof arguments[0] === 'object' && (arguments[0].pin === undefined || arguments[0].pin[0] == undefined)){
console.log('\nsetInput({pin:[]}) - array pin property is empty!');
invalidPinError(arguments[0]);
console.log('\nsetInput({pin:[]}) - array pin property is empty!');
invalidPinError(arguments[0]);
}

@@ -274,21 +271,21 @@

for (var x = 0; x < arguments[0].pin.length; x++) {
// check if pins are from numbers 1 ~ 40 and validate for input use
if(Number.isInteger(arguments[0].pin[x]) && arguments[0].pin[x] > 0 && arguments[0].pin[x] < 41){
try{
rpi.gpio_open(arguments[0].pin[x], 0);
}
catch(e){
inputPin.push(' *' + arguments[0].pin[x]);
console.log('input pins [ ' + inputPin + ' ]');
invalidPinError(arguments[0].pin[x]);
}
inputPin.push(arguments[0].pin[x]);
arrayPinCheck.push(arguments[0].pin[x]);
}
// invalid pin number
else{
invalidPinError(arguments[0].pin[x]);
}
}
options = arguments[0];
// check if pins are from numbers 1 ~ 40 and validate for input use
if(Number.isInteger(arguments[0].pin[x]) && arguments[0].pin[x] > 0 && arguments[0].pin[x] < 41){
try{
rpi.gpio_open(arguments[0].pin[x], 0);
}
catch(e){
inputPin.push(' *' + arguments[0].pin[x]);
console.log('input pins [ ' + inputPin + ' ]');
invalidPinError(arguments[0].pin[x]);
}
inputPin.push(arguments[0].pin[x]);
arrayPinCheck.push(arguments[0].pin[x]);
}
// invalid pin number
else{
invalidPinError(arguments[0].pin[x]);
}
}
options = arguments[0];
}

@@ -300,17 +297,17 @@

*/
if (Number.isInteger(arguments[0]) && arguments.length >= 1) {
if(Number.isInteger(arguments[0]) && arguments.length >= 1) {
for (var x = 0; x < arguments.length; x++) {
// check if pins are from numbers 1 ~ 40 and validate for input use
if(Number.isInteger(arguments[x]) && arguments[x] > 0 && arguments[x] < 41){
try{
rpi.gpio_open(arguments[x], 0);
}
catch(e){
inputPin.push(' *' + arguments[x]);
console.log('input pins [ ' + inputPin + ' ]');
invalidPinError(arguments[x]);
}
inputPin.push(arguments[x]);
arrayPinCheck.push(inputPin[x]);
}
// check if pins are from numbers 1 ~ 40 and validate for input use
if(Number.isInteger(arguments[x]) && arguments[x] > 0 && arguments[x] < 41){
try{
rpi.gpio_open(arguments[x], 0);
}
catch(e){
inputPin.push(' *' + arguments[x]);
console.log('input pins [ ' + inputPin + ' ]');
invalidPinError(arguments[x]);
}
inputPin.push(arguments[x]);
arrayPinCheck.push(inputPin[x]);
}
// invalid pin number

@@ -337,8 +334,8 @@ else if(Number.isInteger(arguments[x]) && arguments[x] <= 0 || arguments[x] > 40){

else if(arguments[x] instanceof Object ){
options = arguments[x];
}
else {
console.log('Invalid arguments', arguments[x]);
}
} // for
options = arguments[x];
}
else {
console.log('Invalid arguments', arguments[x]);
}
} // for
}

@@ -353,14 +350,14 @@

for (var i = 0; i < inputPin.length; i++) {
var index = i, pin = inputPin[i];
if(options){
if(options.pinCheck === 'NoPinCheck' || options.pinCheck === false){
var index = i, pin = inputPin[i];
if(options){
if(options.pinCheck === 'NoPinCheck' || options.pinCheck === false){
pinCheck = false;
}
if(options.index === 'PinAsIndex' || options.index === 'pin'){
}
if(options.index === 'PinAsIndex' || options.index === 'pin'){
index = inputPin[i];
}
eventPin.push(pin);
input[index] = new GpioInput(index, pin, options);
}
}
}
eventPin.push(pin);
input[index] = new GpioInput(index, pin, options);
}
}
}

@@ -379,6 +376,6 @@ createObject(inputPin, options, GpioInput);

arraySetup = options.index;
config = '{ pin:[' + inputPin + ']' + ', index:' + options.index + ' } ' + endTime(1);
if(options.array){
config = '{ pin:[' + inputPin + ']' + ', array:true, index:' + options.index + ' } ' + endTime(1);
}
config = '{ pin:[' + inputPin + ']' + ', index:' + options.index + ' } ' + endTime(1);
if(options.array){
config = '{ pin:[' + inputPin + ']' + ', array:true, index:' + options.index + ' } ' + endTime(1);
}
}

@@ -415,8 +412,8 @@ else if(inputPin.length < 2 && options.array === true && (options.index === 'PinAsIndex' || options.index === 'pin')){

console.log('\nsetOutput() - empty argument!');
invalidPinError(arguments[0]);
invalidPinError(arguments[0]);
}
if(typeof arguments[0] === 'string' || typeof arguments[0] === 'function' ){
console.log('\nsetOutput() - invalid argument!');
invalidPinError(arguments[0]);
console.log('\nsetOutput() - invalid argument!');
invalidPinError(arguments[0]);
}

@@ -426,4 +423,4 @@

if(typeof arguments[0] === 'object' && (arguments[0].pin === undefined || arguments[0].pin[0] == undefined)){
console.log('\nsetOutput({pin:[]}) - array pin property is empty!');
invalidPinError(arguments[0]);
console.log('\nsetOutput({pin:[]}) - array pin property is empty!');
invalidPinError(arguments[0]);
}

@@ -457,20 +454,20 @@

// check if pins are from numbers 1 ~ 40 and validate for output use
if(Number.isInteger(arguments[0].pin[x]) && arguments[0].pin[x] > 0 && arguments[0].pin[x] < 41){
try{
rpi.gpio_open(arguments[0].pin[x] , 1);
}
catch(e){
if(Number.isInteger(arguments[0].pin[x]) && arguments[0].pin[x] > 0 && arguments[0].pin[x] < 41){
try{
rpi.gpio_open(arguments[0].pin[x], 1);
}
catch(e){
outputPin.push(' *' + arguments[0].pin[x]);
console.log('output pins [ ' + outputPin + ' ]');
invalidPinError(arguments[0].pin[x]);
}
outputPin.push(arguments[0].pin[x]);
arrayPinCheck.push(arguments[0].pin[x]);
}
}
outputPin.push(arguments[0].pin[x]);
arrayPinCheck.push(arguments[0].pin[x]);
}
// invalid pin number
else{
invalidPinError(arguments[0].pin[x]);
}
}
options = arguments[0];
else{
invalidPinError(arguments[0].pin[x]);
}
}
options = arguments[0];
}

@@ -521,3 +518,3 @@

}
}
}
}

@@ -543,28 +540,28 @@

if(debugState || debugStateAdvanced){
arrayPinCheck = [];
arrayPinCheck = [];
}
else if(pinCheck) {
checkPinOnArray(arrayPinCheck);
checkPinOnArray(arrayPinCheck);
}
if(outputPin.length > 1) {
if(options === undefined || !options.index){
arraySetup = 'index:0~n';
}
else if(options.index && !options.array) {
arraySetup = 'index:pin';
}
else if(options.array && !options.index) {
arraySetup = 'array:true, index:0~n';
}
else if(options.array && options.index){
if(options === undefined || !options.index){
arraySetup = 'index:0~n';
}
else if(options.index && !options.array) {
arraySetup = 'index:pin';
}
else if(options.array && !options.index) {
arraySetup = 'array:true, index:0~n';
}
else if(options.array && options.index){
arraySetup = 'array:true, index:pin';
}
config = '{ pin:[' + outputPin + '], ' + arraySetup + ' } ' + endTime(1);
}
config = '{ pin:[' + outputPin + '], ' + arraySetup + ' } ' + endTime(1);
}
else if(outputPin.length < 2 && options && options.array == true && (options.index === 'pin' || options === 'PinAsIndex')){
config = '{ pin:[' + outputPin + '], array:true, index:pin } ' + endTime(1);
config = '{ pin:[' + outputPin + '], array:true, index:pin } ' + endTime(1);
}
else if(outputPin.length < 2 && options && options.array){
config = '{ pin:[' + outputPin + '], array:true, index:0~n } ' + endTime(1);
config = '{ pin:[' + outputPin + '], array:true, index:0~n } ' + endTime(1);
}

@@ -603,6 +600,6 @@ else{

if(x === 1){
debugState = true;
debugStateAdvanced = true;
}
return debugState;
debugState = true;
debugStateAdvanced = true;
}
return debugState;
}

@@ -617,25 +614,25 @@

if(arguments.length > 4 || arguments.length < 1){
throw new Error('invalid PWM(pin, freq, T, pw) arguments');
throw new Error('invalid PWM(pin, freq, T, pw) arguments');
}
/* arguments validation */
if(arguments[0] === 33 || arguments[0] === 35 || arguments[0] === 12 || arguments[0] === 32){
var validPin = pin;
/* store validated pin in array */
if(validPin === 12 || validPin === 32){
pwmPin.c1.push(validPin);
}
var validPin = pin;
/* store validated pin in array */
if(validPin === 12 || validPin === 32){
pwmPin.c1.push(validPin);
}
else{
pwmPin.c2.push(validPin);
}
/* check duplicate pins */
if(pwmPin.c1.length > 1 ){
if(validPin === pwmPin.c1[0]){
throw new Error('\nsetPWM() error: pin ' + validPin + ' is already in use.\n');
}
}
if(pwmPin.c2.length > 1){
if(validPin === pwmPin.c2[0]){
throw new Error('\nsetPWM() error: pin ' + validPin + ' is already in use.\n');
}
}
pwmPin.c2.push(validPin);
}
/* check duplicate pins */
if(pwmPin.c1.length > 1 ){
if(validPin === pwmPin.c1[0]){
throw new Error('\nsetPWM() error: pin ' + validPin + ' is already in use.\n');
}
}
if(pwmPin.c2.length > 1){
if(validPin === pwmPin.c2[0]){
throw new Error('\nsetPWM() error: pin ' + validPin + ' is already in use.\n');
}
}
}

@@ -647,9 +644,9 @@ else{

if(arguments[1] === 10 || arguments[1] === 100 || arguments[1] === 1000 ){
var validFreq = freq;
var validFreq = freq;
}
else if(arguments[1] === undefined){
var validFreq = 1;
var validFreq = 1;
}
else{
throw new Error('invalid setPulse() freq argument');
throw new Error('invalid setPulse() freq argument');
}

@@ -659,19 +656,19 @@

if(arguments[2] > 0 || arguments[2] < 1000000 ){
var validT = T;
var validT = T;
}
else if(arguments[2] === undefined){
var validT = 0;
var validT = 0;
}
else{
throw new Error('invalid setPulse() period T argument');
throw new Error('invalid setPulse() period T argument');
}
/* pw or data */
if(arguments[3] > 0 || arguments[3] < 1000000 ){
var validPW = pw;
var validPW = pw;
}
else if( arguments[3] === undefined){
var validPW = 0;
var validPW = 0;
}
else{
throw new Error('invalid setPulse() pw argument');
throw new Error('invalid setPulse() pw argument');
}

@@ -687,17 +684,17 @@

if(Freq === 10){
var res = '0.1 ms';
var res = '0.1 ms';
}
else if(Freq === 100){
var res = '0.01 ms';
var res = '0.01 ms';
}
else if(Freq === 1000){
var res = '0.001 ms';
var res = '0.001 ms';
}
if(validFreq === 1){
console.log('PWM setup: (pin ' + validPin + ')');
console.log('PWM setup: (pin ' + validPin + ')');
}
else{
/* Freq is global, not validFreq - one freq only for all */
console.log('PWM setup: pin ' + validPin + ', Freq ' + Freq + ' KHz (' + res + '), T ' + validT + ', pw ' + validPW);
/* Freq is global, not validFreq - one freq only for all */
console.log('PWM setup: pin ' + validPin + ', Freq ' + Freq + ' KHz (' + res + '), T ' + validT + ', pw ' + validPW);
}

@@ -709,3 +706,3 @@

setImmediate(function(){
pwmObjectTotal += 1;
pwmObjectTotal += 1;
if(pwmObject === pwmObjectTotal && pwmObject > 1){

@@ -716,3 +713,3 @@ console.log("\nArray-gpio has detected you are using more than 1 PWM peripheral."

/* pwm pin channel check */
setImmediate(function(){
setImmediate(function(){
/* channel 1 */

@@ -732,3 +729,3 @@ if(pwmPin.c1.length > 1 && pwmObject > 1){

}
});
});
});

@@ -752,3 +749,3 @@ return pwm;

I2C(pin) {
return new I2C(pin);
return new I2C(pin);
}

@@ -761,3 +758,3 @@

startI2C(pinSet) {
return new I2C(pinSet);
return new I2C(pinSet);
}

@@ -801,17 +798,17 @@

{
rpi.uswait(us);
rpi.uswait(us);
}
pinout(){
console.log('** common pins for rpi zero, rpi3 and rpi4 **');
console.log('(based on the physical pinout numbering from the board header)\n');
console.log('** common pins for rpi zero, rpi3 and rpi4 **');
console.log('(based on the physical pinout numbering from the board header)\n');
console.log('5v', pwr5);
console.log('3.3v', pwr3);
console.log('ground', ground);
console.log('eeprom id',eprom);
console.log('uart', uart);
console.log('i2c', i2c);
console.log('spi', spi);
console.log('pwm', pwm);
console.log('gpio (ALT0)', gpio, '\n');
console.log('eeprom id',eprom);
console.log('uart', uart);
console.log('i2c', i2c);
console.log('spi', spi);
console.log('pwm', pwm);
console.log('gpio (ALT0)', gpio, '\n');
}

@@ -818,0 +815,0 @@

{
"name": "array-gpio",
"version": "1.7.2",
"description": "array-gpio is low-level javascript library for Raspberry Pi using direct register control.",
"version": "1.7.3",
"description": "array-gpio is low-level javascript library for Raspberry Pi using direct register access.",
"main": "index.js",

@@ -32,6 +32,3 @@ "cpu" : ["arm","arm64"],

"pi",
"raspberry",
"raspberrypi",
"raspberry pi",
"raspberry pi 3",
"rpi",

@@ -38,0 +35,0 @@ "rpio",

+4
-1402

@@ -6,3 +6,3 @@ [![Version npm](https://img.shields.io/npm/v/array-gpio.svg?logo=npm)](https://www.npmjs.com/package/array-gpio)

**array-gpio** is a low-level javascript library for Raspberry Pi using a direct register control.
**array-gpio** is a low-level javascript library for Raspberry Pi using direct register access.

@@ -23,7 +23,7 @@ It maps the ARM peripheral registers in memory using */dev/mem* for PWM, I2C, SPI

### GPIO pin numbers
All pin numbering used on this module are based on the RPI board's pinout diagram *numbers 1~40*.
All pin numbering used on this module are based on the RPI's board pinout diagram *numbers 1~40*.
<br>
For IoT or machine-to-machine applications, please check [m2m](https://www.npmjs.com/package/m2m) using array-gpio.
<!--For IoT or machine-to-machine applications, please check [m2m](https://www.npmjs.com/package/m2m) using array-gpio.-->

@@ -53,3 +53,3 @@ # Table of contents

### Supported Raspberry Pi Devices
* Model: Pi Zero & Zero W, Pi 3 Model B+, Pi 4 Model B, Compute Module 3 & 4 (Generally most of the 40-pin models)
* Model: Pi Zero & Zero W, Pi 3 Model B+, Pi 4, Compute Module 3 & 4 (Generally most of the 40-pin models)

@@ -75,1399 +75,1 @@ <br>

# Quick Tour
## Example 1
### Create a GPIO input and output object
Connect a momentary *switch button* on pin **11** and an *led* on pin **33**.
![](https://raw.githubusercontent.com/EdoLabs/src3/master/array-gpio-quick-example1.svg?sanitize=true)
Using **in** and **out** method from *array-gpio* object module
```js
// create a raspberry pi (r) object
const r = require('array-gpio');
// set pin 11 as input
let input = r.in(11);
// set pin 33 as output
let output = r.out(33);
```
Alternatively using the object destructuring assignment pattern, you can use the **setInput** and **setOutput** methods to create your input/output objects
```js
const {setInput, setOutput} = require('array-gpio');
// set pin 11 as input
let sw = setInput(11);
// set pin 33 as output
let led = setOutput(33);
```
## Example 2
### Monitor the state of an input object
```js
const r = require('array-gpio');
let sw = r.in(11);
let led = r.out(33);
// Pressing the switch sw button, the led will turn on
// Releasing the switch sw button, the led will turn off
sw.watch((state) => {
if(state){
led.on();
}
else{
led.off();
}
});
```
## Example 3
### Using *isOn* and *isOff* properties to get the current state of an input/output object
The **isOn** and **isOff** properties are built-in own properties of input/output objects when they are created.
![](https://raw.githubusercontent.com/EdoLabs/src3/master/quick-example2.svg?sanitize=true)
```js
const r = require('array-gpio');
let sw = r.in(11);
let led = r.out(33);
// Check the current state of sw and led object
console.log(sw1.isOn); // false
console.log(led.isOn); // false
console.log(sw1.isOff); // true
console.log(led.isOff); // true
```
## Example 4
### Monitor multiple input objects
To monitor multiple input objects, you can use the **watchInput()** method.
Connect a momentary *switch button* on pin **11, 13, 15** and **19** and an *led* on pin **33** and **35**.
```js
const r = require('array-gpio');
let sw1 = r.in(11), sw2 = r.in(13), sw3 = r.in(15), sw4 = r.in(19);
let led1 = r.out(33), led2 = r.out(35);
// Press sw1 to turn on led1, press sw2 to turn off led1
// Press sw3 to turn on led2, press sw4 to turn off led2
// The callback argument will be invoked
// if you press any of the input switches
r.watchInput(() => {
if(sw1.isOn){
led1.on();
}
else if(sw2.isOn){
led1.off();
}
else if(sw3.isOn){
led2.on();
}
else if(sw4.isOn){
led2.off();
}
});
```
## Example 5
### Turning *on* and *off* a GPIO output with a *delay*
Connect a momentary *switch button* on pin **11** and **13** and an *led* on pin **33**.
```js
const {setInput, setOutput, watchInput} = require('array-gpio');
let sw1 = setInput(11);
let sw2 = setInput(13);
let led = setOutput(33);
watchInput(() => {
if(sw1.isOn){
// pressing sw1, the led will turn on after 1000 ms or 1 sec delay
led.on(1000);
}
else if(sw2.isOn){
// pressing sw2, the led will turn off after 500 ms or 0.5 sec delay
led.off(500);
}
});
```
## Example 6
### Create an input/output array object
Connect a momentary *switch button* for each input pin and an *led* for each output pin.
![](https://raw.githubusercontent.com/EdoLabs/src3/master/quick-example4.svg?sanitize=true)
```js
const r = require('array-gpio');
const sw = r.in({pin:[11, 13], index:'pin'});
const led = r.out({pin:[33, 35, 37, 36, 38, 40], index:'pin'});
// turn on all led outputs sequentially
let LedOn = () => {
let t = 0; // initial on time delay in ms
for(let x in led){
t += 50;
led[x].on(t);
}
}
// turn off all led outputs sequentially
let LedOff = () => {
let t = 0; // initial off time delay in ms
for(let x in led){
t += 50;
led[x].off(t);
}
}
r.watchInput(() => {
if(sw[11].isOn){
LedOn();
}
else if(sw[13].isOn){
LedOff();
}
});
```
### Using forEach to iterate over the array objects
```js
const {setInput, setOutput, watchInput} = require('array-gpio');
const sw = setInput({pin:[11, 13], index:'pin'});
const led = setOutput({pin:[33, 35, 37, 36, 38, 40], index:'pin'});
let LedOn = () => {
let t = 0;
led.forEach((output) => {
t += 50;
output.on(t);
})
}
let LedOff = () => {
let t = 0;
led.forEach((output) => {
t += 50;
output.off(t);
})
}
watchInput(() => {
sw.forEach((input) => {
if(input.pin === 11 && input.isOn){
ledOn();
}
else if(input.pin === 13 && input.isOn){
ledOff();
}
})
});
```
## Example 7
### Create a simple GPIO single one-shot pulse
Connect a momentary *switch button* on pin **11, 13, 15** and an *led* on pin **33**.
```js
const {setInput, setOutput, watchInput} = require('array-gpio');
let sw1 = setInput(11);
let sw2 = setInput(13);
let sw3 = setInput(15);
let led = setOutput(33);
watchInput(() => {
// press sw1 to create a pulse with a duration of 50 ms
if(sw1.isOn){
led.pulse(50);
}
// press sw2 to create a pulse with a duration of 200 ms
else if(sw2.isOn){
led.pulse(200);
}
// press sw3 to create a pulse with a duration of 1000 ms or 1 sec
else if(sw3.isOn){
led.pulse(1000);
}
});
```
# API
All pin numbering used on this module are based on the RPI board's pinout diagram *numbers 1~40*.
If you are using a *Raspberry Pi OS*, you can check your board's pinout by entering *pinout* from a terminal.
```console
$ pinout
```
All numbers in parenthesis are the pin numbers used on this module.
<br>
## GPIO
### state
`input/output property`
Shows the current digital logical state of an input/output object during runtime. It is a getter only property.
Returns *true* if the object logical state is *high* or *ON*.
Returns *false* if the object logical state is *low* or *OFF*.
##### Example 1
```js
const r = require('array-gpio');
let sensor = r.in(11);
// returns the current state of the sensor
console.log(sensor.state); // false
```
##### Example 2
```js
const r = require('array-gpio');
let sw = r.in(11);
let led = r.out(33);
sw.watch(function(){
if(sw.state && !led.state){
console.log(sw.state); // true
console.log(led.state); // false
led.on();
console.log(sw.state); // true
console.log(led.state); // true
}
});
```
### isOn and isOff
`input/output property`
Similar with the *state* property, it will return the current digital logical state of an input/output object with explicit context.
**isOn** - returns *true* if the object logical state is *high* or *ON*, otherwise it returns *false*.
**isOff** - returns *true* if the object logical state is *low* or *OFF*, otherwise it returns *false*.
##### Example
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let sw2 = r.in(13);
let led = r.out(33);
r.watchInput(() => {
// turns on led if sw1 is on and if led is off
if(sw1.isOn && led.isOff){
led.on();
}
// turns off led if sw2 is on and if led is on
else if(sw2.isOn && led.isOn){
led.off();
}
});
```
### pin
`input/output property`
Returns the GPIO pin used from any input/output objects.
##### Example
```js
const r = require('array-gpio');
let sw = r.setInput(11);
let led = r.setOutput(33);
console.log(sw.pin); // 11
console.log(led.pin); // 33
```
### close()
`input/output method`
Closes an input/output object. Removes any events (pin watching) from the object and resets the pin to GPIO input.
##### Example 1
```js
const r = require('array-gpio');
let sw = r.setInput(11);
let led = r.setOutput(33);
sw.close();
led.close();
```
##### Example 2
```js
const r = require('array-gpio');
let input = r.setInput({pin:[11, 13]});
let output = r.setOutput({pin:[33, 35]});
function appExitProcess(){
console.log('closing all I/O objects');
for(let x in input){
input[x].close();
}
for(let x in output){
output[x].close();
}
}
// using Ctrl-C for app exit
process.on('SIGINT', function (){
appExitProcess();
process.exit(0);
});
```
### read([callback])
`input/output method`
The conventional way of getting the current logical state condition of an input/output object.
Returns logical **1** value if the object state is in *high* or *ON* state condition and **0** for *low* or *OFF* state condition.
The optional **callback** parameter will be invoked asynchronously after returning the object state condition.
This method is similar to **state** property but as a method property, you can use a
callback argument to execute any additional application logic based on the object state condition.
##### Example
```js
const r = require('array-gpio');
let sw = r.setInput(11);
let solenoid = r.setOutput(35);
sw.read((state) => {
if(state === 1)
solenoid.on();
else
solenoid.off();
});
```
## Input Properties
### in(arg)
or
### setInput(arg)
Sets a GPIO pin or group of GPIO pins as input object.
**arg**
Any valid GPIO pin number or an input option argument.
#### Single Object
```js
const r = require('array-gpio');
let input = r.setInput(11);
// or
let input = r.in(11);
```
#### Array Object
```js
const r = require('array-gpio');
let inputOption = {pin: [11, 13, 15]};
const input = r.setInput(inputOption);
// or
const input = r.in(inputOption);
// By default, the array object created is indexed using zero-based indexing
// (indexed from 0 to n-1, where n is the array.length).
/* Get the current logical state of each input element */
console.log(input[0].state);
console.log(input[1].state);
console.log(input[2].state);
```
To use the pin as index, add an *index* property to the object argument and set the value to `'pin'`.
```js
let inputOption = {pin:[11, 13, 15], index: 'pin'};
const input = r.setInput(inputOption);
/* Get the current logical state of each input element using pin as index */
console.log(input[11].state);
console.log(input[13].state);
console.log(input[15].state);
/* Iterate over the array object in both cases to access each input element */
for(let x in input){
console.log(input[x].isOn);
}
// or
input.forEach(function(inputObject){
console.log(inputObject.isOn);
});
```
### watch (edge, callback, [s])
`input method`
Watches the logical state of an input object for changes or state transitions.
**edge**
`1` - watch state changes from *low* to *high* (*false* to *true*) or rising edge transition
`0` - watch state changes from *high* to *low* (*true* to *false*) or falling edge transition
`'both'` - watches both state transitions
If edge argument is not provided, it will watch both transitions same as `'both'`.
**callback**
The callback argument will be called asynchronously everytime a state transition is detected based on the above conditions.
You can passed an optional parameters *state* and *pin* respectively to the callback argument for any fine-grained application logic execution.
**s**
This is an an optional scan rate argument in ms (milliseconds). If not provided, scan rate will default to *100* ms, minimum is *1* ms.
A lower value will make your input more responsive but contact bounce will increase. A higher value will make it less responsive but with a lower contact bounce.
##### Example1
```js
const r = require('array-gpio');
let sw = r.in(11);
function pinEvent(){
console.log('pinEvent invoked');
}
// pinEvent will be invoked if sw state changes from false to true
sw.watch(1, pinEvent);
// pinEvent will be invoked if sw state changes from true to false
sw.watch(0, pinEvent);
// edge argument is not provided,
// pinEvent will be invoked if sw state changes from true to false and vice versa
sw.watch(pinEvent);
// using a scan rate of 10 ms
sw.watch(pinEvent, 10);
```
##### Example 2
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let led = r.out(33);
// pressing the sw1 button will turn on the led then turns off after 1000 ms delay
// releasing the sw1 button will do nothing
sw1.watch(1, (state) => {
if(state){
led.on();
led.off(1000);
}
});
```
### unwatch()
`input method`
Stops monitoring an input object from the .watch() method.
### setR(value)
`input method`
Sets the internal resistor of an input pin using either *pull up* or *pull down* resistor.
**value**
`'pu'` or `1` - Enable internal *pull up* resistor.
`'pd'` or `0` - Enable internal *pull down* resistor.
If argument is not provided, no internal resistor will be used.
##### Example
```js
const r = require('array-gpio');
let sw = r.setInput({pin:[11,13,15]});
// using pull up resistor
sw[0].setR('pu');
// using pull down resistor
sw[1].setR(0);
// no internal resistor is used
sw[2].setR();
```
### watchInput(callback, [s])
`main module method`
Monitor multiple input objects all at once from the main module using **.watchInput()** method.
It will watch both state transistions from *low* to *high* and vice versa for all inputs.
The **callback** argument is shared by all input objects. It will be invoked asynchronously if any of the input objects changes state.
You can passed an optional parameters - *state* and *pin* respectively to the callback argument for any fine-grained application logic execution.
**s** is an optional scan rate argument in ms (milliseconds). If not provided, scan rate will default to *100* ms, minimum is *1* ms. A lower value will make your input more responsive but contact bounce will increase. A higher value will make it less responsive but with a lower contact bounce.
To capture which input object state has changed, you can use each object's **state** or **isOn** property. Or use the *pin* argument from the callback when it is invoked for any state transitions.
##### Example 1
```js
const r = require('array-gpio');
let sw = r.in({pin:[11, 13, 15], index:'pin'});
let led = r.out({pin:[33, 35], index:'pin'});
r.watchInput(() => {
// if sw[11] is on, led[33] will turn on
if(sw[11].isOn){
led[33].on();
}
// if sw[13] is on, led[35] will turn on
else if(sw[13].isOn){
led[35].on();
}
// if sw[15] is on, both led[33] and led[35] will turn off
else if(sw[15].isOn){
led[33].off();
led[35].off();
}
});
```
##### Example 2
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let sw2 = r.in(13);
let led = r.out(35);
r.watchInput((state, pin) => {
if(state && sw1.pin === pin){
led.on();
}
else if(state && sw2.pin === pin){
led.off();
}
});
```
### unwatchInput()
`main module method`
Stop monitoring all the input objects from **.watchInput()** method.
It will stop invoking the shared callback argument for any input state changes.
##### Example
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let sw2 = r.in(13);
let sw3 = r.in(15);
let led1 = r.out(33);
let led2 = r.out(35);
r.watchInput(() => {
if(sw1.state){
return led1.on();
}
if(sw2.state){
return led2.on();
}
if(sw3.state){
led1.off();
led2.off();
}
});
// stops all input pin monitoring after 15 secs
setTimeout(() => r.unwatchInput(), 15000);
```
### Output Properties
### setOutput(arg)
or
### out(arg)
`main module method`
Sets a GPIO pin or group of GPIO pins as output object.
**arg**
Any valid GPIO pin number or an output option argument.
#### Single Object
```js
const r = require('array-gpio');
/* creates a single output object */
let led = r.setOutput(33);
// or
let led = r.out(33);
/* turn on the led */
led.on();
```
#### Array Object
```js
const r = require('array-gpio');
/* creates an array output object */
let outputOption = {pin:[33, 35, 36]};
const output = r.setOutput(outputOption);
// or
const output = r.out(outputOption);
// Similar with input, the array object created is indexed using zero-based indexing
// (indexed from 0 to n-1, where n is the array.length).
/* Get the current logical state of each output element */
console.log(output[0].state);
console.log(output[1].state);
console.log(output[2].state);
```
To use the pin as index, add an *index* property to the object argument and set the value to `'pin'`.
```js
let outputOption = {pin:[33, 35, 36], index:'pin'};
const output = r.setOutput(outputOption);
/* Get the current logical state of each output element using pin as index */
console.log(output[33].state);
console.log(output[35].state);
console.log(output[36].state);
// iterate over the array object in both cases to access each output element
for(let x in output){
output[x].on();
}
// or
output.forEach(function(outputObject){
outputObject.on();
});
```
### on([t],[callback]) and off([t],[callback])
`output method`
Sets the state of an output object to logical *high* state condition (*true*) or *low* state condition (*false*).
**t** is an optional time delay in milliseconds.
The state will change after the duration of time delay *t*.
**callback**
The optional callback argument will be invoked asynchronously after the output state has changed.
You can passed an optional parameter *state* for any fine-grained application logic execution.
##### Example
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let sw2 = r.in(13);
let actuator1 = r.out(33);
let actuator2 = r.out(35);
r.watchInput(() => {
if(sw1.isOn && actuator1.isOff){
actuator1.on(200); // turns on after 200 ms delay
actuator2.on((state) => {
if(state){
console.log('actuator2 is on');
}
});
}
else if(sw2.isOn && actuator2.isOn){
actuator1.off(50); // turns off after 50 ms delay
actuator2.off((state) => {
if(!state){
console.log('actuator2 is off');
}
});
}
});
```
### write(bit [,callback])
`output method`
This is the conventional way of setting the ouput state to *high* or *low* state condition.
**bit** - control bit value.
`1` or `true` - high or ON state
`0` or `false` - low or OFF state
**callback**
The optional callback argument will be invoked asynchronously after the output state has changed.
You can passed an optional parameter *state* for any fine-grained application logic execution.
##### Example
```js
const {setInput, setOutput, watchInput} = require('array-gpio');
const sw = setInput(11,13);
const motor = setOutput(33,35);
let sw1 = sw[0];
let sw2 = sw[1];
let motorA = motor[0];
let motorB = motor[1];
watchInput((state) => {
if(sw1.read()){
motorA.write(state, () => motorB.write(!state));
}
if(sw2.read()){
motorB.write(state, () => motorA.write(!state));
}
});
```
### pulse(pw [,callback])
`output method`
Generates a single square wave pulse with a duration of *pw*.
**pw**
This is the pulse width in milliseconds or the time duration of the pulse.
**callback**
The optional callback argument will be invoked asynchronously when *pw* time duration expires.
##### Example
```js
const r = require('array-gpio');
let sw1 = r.in(11);
let sw2 = r.in(13);
let actuator = r.out({pin:[33, 35]});
r.watchInput(() => {
// starts a single pulse w/ a duration of 1 sec
if(sw1.isOn && actuator[0].isOff){
actuator[0].pulse(1000);
}
// starts a single pulse w/ a duration of 2 secs
else if(sw2.isOn && actuator[1].isOff){
console.log('start of actuator[1] pulse');
actuator[1].pulse(3000, () => {
console.log('end of actuator[1] pulse');
});
}
});
```
***
## PWM
### startPWM(pin)
Creates a pwm object from the provided GPIO pin and starts the PWM operations.
Sets GPIO pins *12* and *33* to alternate function 0 (ALT0) and sets pins *12* and *35* to alternate function 5 (ALT5).
This operation requires root access.
**pin**
Channel 1 - pins *12* and *32*.
Channel 2 - pins *33* and *35*.
You can only control 2 peripherals independently, one from channel 1 and one from channel 2. If both peripherals are from the same channel, you can control both channels using only
the control values (setRange and setData) from one of the peripherals.
### setClockFreq(div)
**div**
The divisor value to calculate the desired clock frequency from a fixed oscillator freq of 19.2 MHz.
(0 to 4095)
freq = 19200000/div
### setRange(range)
Sets the period **T** of the pwm pulse.
**range** The period T of the pulse
### setData(data)
Sets the **pw** (pulse width) of the pwm pulse.
**data** The pulse width of the pulse
### stop()
Stops temporarily the pulse generation from the system 19.2 MHz clock oscillator.
You can restart the pulse generation at anytime by calling the **.pulse()** or **.setData()** method.
### close()
Stops PWM operations on the GPIO pin. Resets the pin to GPIO input.
##### Example 1
![](https://raw.githubusercontent.com/EdoLabs/src3/master/pwm-example1.svg?sanitize=true)
```js
/* Connect an led to pin 12. */
/* r for raspberry pi */
const r = require('array-gpio');
/* create a pwm object using pin 12 */
var pwm = r.startPWM(12);
/* set the pwm clock frequency using a div value of 1920 */
pwm.setClockFreq(1920); // sets clock freq to 10kHz or 0.1 ms time resolution for T and pw
/* set period (T) of the pulse */
pwm.setRange(1000); // 1000 x 0.1 ms = 100 ms (actual period T)
/*
* set pw (pulse width) of the pulse and start the pulse generation for 2 seconds
*
* The led attached to pin 12 should blink for 2 seconds
*/
pwm.setData(100); // 100 x 0.1 ms = 10 ms (actual pw)
/* stop the pwm operation and reset pin 12 to GPIO input after 2 secs */
setTimeout(function(){
pwm.stop();
pwm.close();
}, 2000);
```
### startPWM(pin, freq, T, pw)
Creates a pwm object from a predefined clock frequencies of `10`, `100`, or `1000` kHz that will provide different time resolutions
for the **T** (period) and **pw** (pulse width) of your desired pwm pulse.
**pin**
Choose from channel 1 (12, 32) or channel 2 (33, 35).
**freq** (kHz)
Choose a predefined clock oscillator frequency of `10`, `100`, or `1000` kHz
`10` kHz provides *0.1* ms resolution
`100` kHz provides *0.01* ms resolution
`1000` kHz provides *0.001* ms or *1* uS (microsecond) resolution
**T** (ms)
The initial cycle period of the pulse.
**pw** (ms)
The initial pulse width of the pulse.
The ratio of **pw** over **T** is the pulse **duty cycle** (pw/T) x 100%.
### pulse([pw])
Start the pulse generation or generates a new pulse using the **pw** argument provided.
If **pw** argument is not provided, it will use the initial *pw* argument used in **.setPWM()** constructor and start the pulse generation.
**pw** (ms) is the pulse width that will be used to generate a new pulse.
You can change the period *T* of the pulse using the **.setRange()** and the pulse width *pw* using **.setData()** or **.pulse()** method at anytime in your application.
However in servo motor applications, the period *T* is usually fixed while changes in pulse width *pw* controls the rotational position of your servo motors.
##### Example 2
![](https://raw.githubusercontent.com/EdoLabs/src3/master/pwm-example2.svg?sanitize=true)
```js
/* Using a generic micro servo motor (~4.8 to 6.0 V)
*
* T = 20 ms (pulse period)
*
* pw (pulse width) needed for various servo positions
*
* pw 1.0 ms - pos 1, home position
* pw 1.5 ms - pos 2, rotates 40 degrees cw (clockwise) from pos 1
* pw 2.0 ms - pos 3, rotates 80 degress cw from pos 1
* pw 2.5 ms - pos 4, rotates 120 degress cw from pos 1
*
*/
const r = require('array-gpio');
var pin = 33; /* pin from channel 2 */
var freq = 10; /* using 10 kHz clock frequency that will provide a 0.1 ms time resolution */
var T = 200; /* Use 200 to get the 20 ms period (200 x 0.1 ms = 20 ms) */
var pw = 10; /* Use 10 to get an initial pulse width of 1.0 ms (10 x 0.1 ms = 1.0 ms), home position */
/* initialize PWM using with above pin, freq, T and pw details */
var pwm = r.startPWM(pin, freq, T, pw);
/* create four push buttons sw[0], sw[1], sw[2] and sw[4] */
const sw = r.setInput({pin:[11, 13, 15, 19]});
r.watchInput(() => {
/* Press sw[0] button to rotate the servo motor to pos 1 or home position */
if(sw[0].isOn){
pwm.pulse(10); // 1.0 ms pw
}
/* Press sw[1] button to rotate to pos 2 */
else if(sw[1].isOn){
pwm.pulse(15); // 1.5 ms pw
}
/* Press sw[2] button to rotate to pos 3 */
else if(sw[2].isOn){
pwm.pulse(20); // 2.0 ms pw
}
/* Press sw[3] button to rotate to pos 4 */
else if(sw[3].isOn){
pwm.pulse(25); // 2.5 ms pw
}
});
const appExitProcess = () => {
console.log('closing all sw and pwm objects');
for(let x in sw){
sw[x].close();
}
pwm.close();
process.exit(0);
}
process.on('SIGINT', () => {
console.log('\napp terminated using Ctrl-C');
appExitProcess();
});
```
***
## I2C
### startI2C()
Sets i2c pins 03 (SDA) and 05 (SCL) to its alternate function (ALT0) for i2c operation.
Returns an i2c object with properties to configure the I2C interface to start the i2c data transfer operation.
This operation requires root access.
### begin()
Starts i2c operation in your application.
This operation is integrated in setI2C() method, so there is no need to call it explicitly to start the i2c operation.
### end()
Stops i2c operation and resets i2c pins 03 (SDA) and 05 (SCL) to GPIO input pins.
### setClockFreq(div)
Sets the i2c clock speed based on the **div** divisor value. Check the various *div* values below and the possible clock speeds that will be generated.
```code
div 2500 => 10us => 100 kHz
div 626 => 2.504us => 399.3610 kHz
div 150 => 60ns => 1.666 MHz (default at reset)
div 148 => 59ns => 1.689 MHz
```
### setTransferSpeed(baud)
Directly set the the i2c clock speed using a baud argument instead of using a div value. Either use the setClockFreq above or this method.
Sets the i2c clock frequency by converting the **baud** argument to the equivalent i2c clock divider value.
### selectSlave(addr)
Sets the i2c address of the slave device.
**addr**
The i2c address of the slave device.
### write(wbuf, n)
Write a number of bytes to the currently selected i2c slave device.
**wbuf** The buffer containing the actual data bytes to send/write to the selected i2c slave device.
**n** The number of bytes to send/write to the selected i2c slave device.
### read(rbuf, n)
Read a number of bytes from the currently selected i2c slave device.
**rbuf** The buffer containing the actual data bytes to read/receive from the selected i2c slave device.
**n** The number of bytes to read/receive from the selected i2c slave device.
##### Example
![](https://raw.githubusercontent.com/EdoLabs/src3/master/i2c-example.svg?sanitize=true)
```js
/* Using MCP9808 Temperature Sensor
*
* Please read the MCP9808 datasheet on how to configure the chip for more details.
*/
const r = require('array-gpio');
let i2c = r.startI2C(); // using SDA1 and SCL1 (pin 3 & 5) pins
/* Set data transfer speed to 200 kHz */
i2c.setTransferSpeed(200000);
/* MCP9808 hardware device address */
let addr = 0x18;
/* Select the MCP9808 device for data trasfer */
i2c.selectSlave(addr);
/* Setup the application read and write data buffer */
const wbuf = Buffer.alloc(16); // write buffer
const rbuf = Buffer.alloc(16); // read buffer
/* Accessing the internal 16-bit manufacturer ID register within MCP9808 */
wbuf[0] = 0x06; // from the MCP9808 datasheet, set the address of the manufacturer ID register to the write buffer
i2c.write(wbuf, 1); // writes 1 data byte to the slave device selecting the MCP9808 manufacturer ID register for data access
/* Master (rpi) device will now read the content of the 16-bit manufacturer ID register (should be 0x54 as per datasheet) */
/* Reading 2 data bytes - the upper byte (rbuf[0]) and lower byte (rbuf[1]) from the manufacturer ID register, ID value is on the lower byte from the datasheet */
i2c.read(rbuf, 2);
console.log('MCP9808 ID: ', rbuf[1].toString(16)); // convert the ID value to hex value
/* Based on MCP9808 datasheet, compute the temperature data as follows */
function getTemp(){
let Temp = null;
let UpperByte = rbuf[0]; // MSB
let LowerByte = rbuf[1]; // LSB
UpperByte = UpperByte & 0x1F; // Clear flag bits
/* Temp < 0 C */
if ((UpperByte & 0x10) == 0x10){
UpperByte = UpperByte & 0x0F; // Clear SIGN
Temp = 256 - ((UpperByte * 16) + (LowerByte / 16));
/* Temp > 0 C */
}
else {
Temp = ((UpperByte * 16) + (LowerByte / 16));
}
/* Print out temperature data */
console.log('Temp: ', Temp);
return Temp;
}
/* Get temperature readings every 2 seconds */
setInterval( function(){
/* Accessing the internal 16-bit configuration register within MCP9808.
You can skip accessing this register using default settings */
wbuf[0] = 0x01; // address of the configuration register
/* Change content of configuration register */
wbuf[1] = 0x02; // register upper byte, THYST set with +1.5 C
wbuf[2] = 0x00; // register lower byte (power up defaults)
i2c.write(wbuf, 3);
/* Accessing the internal 16-bit ambient temp register within MCP9808 */
wbuf[0] = 0x05; // address of ambient temperature register
i2c.write(wbuf, 1);
/* Read the content of ambient temp register */
i2c.read(rbuf, 2); // read the UpperByte and LowerByte data
/* Get temperature data and print out the results */
getTemp();
}, 2000);
process.on('SIGINT', function (){
console.log('\napp terminated using Ctrl-C');
i2c.end();
process.exit(0);
});
```
***
## SPI
### startSPI()
Sets SPI0 bus pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CE0) and 26 (CE1) to its alternate function (ALT0) for spi operation.
Returns an spi object with properties to configure the SPI interface.
This operation requires root access.
### begin()
Initializes the SPI0 bus pins for spi operation.
This process is integrated in setSPI() method, so there is no need to call it explicitly to start the spi operation.
### setClockFreq(div)
Sets the SPI clock frequency using a divisor value.
Clock is based on the nominal core clock rate of 250MHz on RPi1 and RPi2, and 400MHz on RPi3.
**div**
The SPI divisor to generate the SPI clock frequency.
The information below shows the various *div* value and the *clock frequency* in kHz that will be generated.
```code
SPI div 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3
SPI div 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3
SPI div 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3
SPI div 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3
SPI div 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 (default)
SPI div 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3
SPI div 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3
SPI div 16 = 15.625MHz on Rpi2, 25MHz on RPI3
SPI div 8 = 31.25MHz on Rpi2, 50MHz on RPI3
```
### chipSelect(cs)
Sets the chip select pin(s).
When data transfer starts, the selected pin(s) will be asserted or held in active state (usually active **low**) during data transfer.
**cs**
Choose from one of cs values below.
```code
cs = 0, Chip Select 0
cs = 1, Chip Select 1
cs = 2, Chip Select 2
cs = 3, No Chip Select
```
### setCSPolarity(cs, active)
Change the active state of the chip select pin.
**cs**
The chip select pin you want to change the active state.
**active**
Select `0` for active low or `1` for active high state.
### setDataMode(mode)
Sets the SPI data mode, the clock polariy (CPOL) and phase (CPHA).
**mode**
Choose from one of SPI mode below.
```code
mode = 0, CPOL = 0, CPHA = 0
mode = 1, CPOL = 0, CPHA = 1
mode = 2, CPOL = 1, CPHA = 0
mode = 3, CPOL = 1, CPHA = 1
```
### transfer(wbuf, rbuf, n)
Transfers any number of bytes to and from the currently selected spi slave device.
This method makes it possible to perform simultaneous write and read operations for date transfer.
Selected CS pins (as previously set by chipSelect) will be held in active state during the data transfer.
**wbuf** The buffer containing the actual data bytes to send/write to the selected spi slave device.
**rbuf** The buffer containing the actual data bytes to read/receive from the selected spi slave device.
**n** The number of bytes to send/receive from/to the selected spi device.
### write(wbuf, n)
Write a number of bytes to the currently selected spi slave chip.
Asserts the currently selected CS pins (as previously set by chipSelect) during the data transfer operations.
**wbuf** The buffer containing the actual data bytes to write/send to the selected spi slave device.
**n** The number of bytes to write/send to the selected spi slave device.
### read(rbuf, n)
Read a number of bytes from the currently selected spi slave device.
**rbuf** The buffer containing the actual data bytes to read/receive from the selected spi slave device.
**n** The number of bytes to read/receive from the spi slave device.
### end()
Stops the SPI data transfer operations. SPI0 pins 19 (MOSI), 21 (MISO), 23 (CLK), 24 (CE0) and 26 (CE1) are reset to GPIO input pins.
##### Example
![](https://raw.githubusercontent.com/EdoLabs/src3/master/spi-example.svg?sanitize=true)
```js
/* Using MCP3008 10-bit A/D Converter Chip
*
* In this example, we will connect the Vdd and Vref pins to the Raspberry Pi's 3.3 V.
* Channel 0 (pin 1) will be used for analog input voltage using single-ended mode.
*
* Please read the MCP3008 datasheet on how to configure the chip for more details.
*/
const r = require('array-gpio');
var spi = r.startSPI();
spi.setDataMode(0);
spi.setClockFreq(128);
spi.setCSPolarity(0, 0);
spi.chipSelect(0);
/* Setup write and read data buffer */
const wbuf = Buffer.alloc(16); // write buffer
const rbuf = Buffer.alloc(16); // read buffer
/* Configure the chip to use CH0 in single-ended mode.
* The device will begin to sample the analog input on the fourth rising edge of the clock after
* the start bit has been received */
wbuf[0] = 0x01; // start bit
wbuf[1] = 0x80; // using channel 0, single ended
wbuf[2] = 0x00; // don't care data byte as per datasheet
spi.write(wbuf, 3);
/* Alternative way to write and read to a slave at the same time */
//spi.transfer(wbuf, rbuf, 3); // write 3 bytes and receive 3 bytes afterwards
/* Read the conversion result */
spi.read(rbuf, 3);
/* Read A/D conversion result
* The 1st byte received through rbuf[0] will be discarded as per datasheet */
var data1 = rbuf[1] << 8; // MSB, using only 2 bits data
var data2 = rbuf[2]; // LSB, 8 bits data
var adc = data1 + data2; // combine both data to create a 10-bit digital output code
console.log("* A/D digital output code: ", adc);
/* Compute the output voltage */
var vout = (adc/1023) * 3.3;
console.log("* A/D voltage output: ", vout);
spi.end();
```

@@ -1,2 +0,4 @@

/*
/**
* node_rpi.cc
*
* Copyright (c) 2017 Ed Alegrid <ealegrid@gmail.com>

@@ -12,3 +14,3 @@ */

#define BCM_EVENT_LOW 0x1
#define BCM_EVENT_HIGH 0x2
#define BCM_EVENT_HIGH 0x2

@@ -26,3 +28,3 @@ using namespace Nan;

uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -41,3 +43,3 @@ rpi_init(arg);

info.GetReturnValue().Set(rval);
info.GetReturnValue().Set(rval);
}

@@ -51,6 +53,6 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint64_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint64_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -63,6 +65,6 @@ nswait(arg);

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -75,8 +77,8 @@ uswait(arg);

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
mswait(arg);
mswait(arg);
}

@@ -90,9 +92,9 @@

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_config(arg1, arg2);
gpio_config(arg1, arg2);
}

@@ -103,8 +105,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_input(arg);
gpio_input(arg);
}

@@ -115,8 +117,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_output(arg);
gpio_output(arg);
}

@@ -129,8 +131,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
rval = gpio_read(arg);
rval = gpio_read(arg);

@@ -143,9 +145,9 @@ info.GetReturnValue().Set(rval);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_enable_async_rising_event(arg1, arg2);
gpio_enable_async_rising_event(arg1, arg2);
}

@@ -158,8 +160,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
rval = gpio_detect_input_event(arg);
rval = gpio_detect_input_event(arg);

@@ -172,8 +174,8 @@ info.GetReturnValue().Set(rval);

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_reset_all_events(arg);
gpio_reset_all_events(arg);
}

@@ -184,8 +186,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_reset_event(arg);
gpio_reset_event(arg);
}

@@ -198,9 +200,9 @@

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
rval = gpio_write(arg1, arg2);
rval = gpio_write(arg1, arg2);

@@ -213,9 +215,9 @@ info.GetReturnValue().Set(rval);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
gpio_enable_pud(arg1, arg2);
gpio_enable_pud(arg1, arg2);
}

@@ -229,4 +231,4 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -241,4 +243,4 @@ uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -260,6 +262,6 @@ uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -283,7 +285,7 @@ rval = pwm_set_clock_freq(arg);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -296,7 +298,7 @@ pwm_enable(arg1, arg2);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -309,9 +311,9 @@ pwm_set_mode(arg1, arg2);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
pwm_set_pola(arg1, arg2);
pwm_set_pola(arg1, arg2);
}

@@ -322,7 +324,7 @@

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -335,9 +337,9 @@ pwm_set_data(arg1, arg2);

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint32_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
pwm_set_range(arg1, arg2);
pwm_set_range(arg1, arg2);
}

@@ -362,8 +364,8 @@

if((info.Length() != 1) || (!info[0]->IsNumber() )){
return ThrowTypeError("Incorrect argument");
}
return ThrowTypeError("Incorrect argument");
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
rval = i2c_init(arg);
rval = i2c_init(arg);

@@ -382,7 +384,7 @@ info.GetReturnValue().Set(rval);

return ThrowTypeError("Incorrect arguments");
}
}
uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
i2c_select_slave(arg);
i2c_select_slave(arg);
}

@@ -394,3 +396,3 @@

return ThrowTypeError("Incorrect arguments");
}
}
uint16_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -404,4 +406,4 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -418,4 +420,4 @@ uint32_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 2) || (!info[0]->IsObject()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -425,3 +427,3 @@ v8::Local<v8::Object> wbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());

rval = i2c_write(node::Buffer::Data(wbuf), arg);
rval = i2c_write(node::Buffer::Data(wbuf), arg);

@@ -433,9 +435,9 @@ info.GetReturnValue().Set(rval);

{
uint8_t rval;
uint8_t rval;
if((info.Length() != 2) || (!info[0]->IsObject()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
v8::Local<v8::Object> rbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());
v8::Local<v8::Object> rbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());
uint8_t arg = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -477,4 +479,4 @@

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -489,4 +491,4 @@ uint16_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -501,7 +503,7 @@ uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
uint8_t arg2 = info[1]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

@@ -514,4 +516,4 @@ spi_set_chip_select_polarity(arg1, arg2);

if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -526,4 +528,4 @@ uint8_t arg = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();

if((info.Length() != 3) || (!info[0]->IsObject()) || (!info[1]->IsObject()) || (!info[2]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -541,4 +543,4 @@ v8::Local<v8::Object> wbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());

if((info.Length() != 2) || (!info[0]->IsObject()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -554,4 +556,4 @@ v8::Local<v8::Object> wbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());

if((info.Length() != 2) || (!info[0]->IsObject()) || (!info[1]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
return ThrowTypeError("Incorrect arguments");
}

@@ -572,7 +574,7 @@ v8::Local<v8::Object> rbuf = info[0]->ToObject(Nan::GetCurrentContext()).FromMaybe(v8::Local<v8::Object>());

/* gpio */
/* gpio */
NAN_EXPORT(target, gpio_config);
NAN_EXPORT(target, gpio_input);
NAN_EXPORT(target, gpio_output);
NAN_EXPORT(target, gpio_read);
NAN_EXPORT(target, gpio_read);
NAN_EXPORT(target, gpio_enable_async_rising_event);

@@ -586,3 +588,3 @@ NAN_EXPORT(target, gpio_detect_input_event);

/* pwm */
NAN_EXPORT(target, pwm_set_pin);
NAN_EXPORT(target, pwm_set_pin);
NAN_EXPORT(target, pwm_reset_pin);

@@ -592,3 +594,3 @@ NAN_EXPORT(target, pwm_reset_all_pins);

NAN_EXPORT(target, pwm_clk_status);
NAN_EXPORT(target, pwm_enable);
NAN_EXPORT(target, pwm_enable);
NAN_EXPORT(target, pwm_set_mode);

@@ -599,4 +601,4 @@ NAN_EXPORT(target, pwm_set_pola);

/* i2c */
NAN_EXPORT(target, i2c_start);
/* i2c */
NAN_EXPORT(target, i2c_start);
NAN_EXPORT(target, i2c_init);

@@ -608,3 +610,3 @@ NAN_EXPORT(target, i2c_stop);

NAN_EXPORT(target, i2c_write);
NAN_EXPORT(target, i2c_read);
NAN_EXPORT(target, i2c_read);
NAN_EXPORT(target, i2c_byte_read);

@@ -615,7 +617,7 @@

NAN_EXPORT(target, spi_stop);
NAN_EXPORT(target, spi_set_clock_freq);
NAN_EXPORT(target, spi_set_clock_freq);
NAN_EXPORT(target, spi_set_data_mode);
NAN_EXPORT(target, spi_set_chip_select_polarity);
NAN_EXPORT(target, spi_set_chip_select_polarity);
NAN_EXPORT(target, spi_chip_select);
NAN_EXPORT(target, spi_data_transfer);
NAN_EXPORT(target, spi_data_transfer);
NAN_EXPORT(target, spi_write);

@@ -622,0 +624,0 @@ NAN_EXPORT(target, spi_read);

+285
-253

@@ -48,12 +48,12 @@ /**

#define ST_BASE (peri_base + 0x003000) // 0x7E003000
#define GPIO_PADS (peri_base + 0x100000) // 0x7E100000 unused
#define CLK_BASE (peri_base + 0x101000) // 0x7E101000
#define GPIO_BASE (peri_base + 0x200000) // 0x7E200000
#define GPIO_PADS (peri_base + 0x100000) // 0x7E100000 unused
#define CLK_BASE (peri_base + 0x101000) // 0x7E101000
#define GPIO_BASE (peri_base + 0x200000) // 0x7E200000
#define SPI0_BASE (peri_base + 0x204000) // 0x7E204000 SPI0
#define BSC0_BASE (peri_base + 0x205000) // 0x7E205000 BSC0 // GPIO 00 & 01/pin 27 & 28
#define PWM_BASE (peri_base + 0x20C000) // 0x7E20C000 PWM0
#define PWM_BASE (peri_base + 0x20C000) // 0x7E20C000 PWM0
#define AUX_BASE (peri_base + 0x215000) // 0x7E215000 unused
#define SPI1_BASE (peri_base + 0x215080) // 0x7E215080 unused
#define SPI2_BASE (peri_base + 0x2150C0) // 0x7E2150C0 unused
#define BSC1_BASE (peri_base + 0x804000) // 0x7E804000 BSC1 // GPIO 02 & 03/pin 03 & 05
#define BSC1_BASE (peri_base + 0x804000) // 0x7E804000 BSC1 // GPIO 02 & 03/pin 03 & 05

@@ -67,10 +67,10 @@ /* Size of memory block or length of bytes to be used during mmap() */

/* System timer registers */
#define ST_PERI_BASE base_pointer[0] // ST_BASE
#define ST_CS (ST_PERI_BASE + 0x00/4)
#define ST_CLO (ST_PERI_BASE + 0x04/4)
#define ST_PERI_ BASE base_pointer[0] // ST_BASE
#define ST_CS (ST_PERI_BASE + 0x00/4)
#define ST_CLO (ST_PERI_BASE + 0x04/4)
#define ST_CHI_CLO (ST_PERI_BASE + 0x08/4)
#define ST_C0 (ST_PERI_BASE + 0x0C/4)
#define ST_C1 (ST_PERI_BASE + 0x10/4)
#define ST_C2 (ST_PERI_BASE + 0x14/4)
#define ST_C3 (ST_PERI_BASE + 0x18/4)
#define ST_C0 (ST_PERI_BASE + 0x0C/4)
#define ST_C1 (ST_PERI_BASE + 0x10/4)
#define ST_C2 (ST_PERI_BASE + 0x14/4)
#define ST_C3 (ST_PERI_BASE + 0x18/4)

@@ -89,8 +89,8 @@ /* PWM control manager clocks control registers

#define GPIO_PERI_BASE base_pointer[2] // GPIO_BASE
#define GPIO_GPFSEL0 (GPIO_PERI_BASE + 0x00/4)
#define GPIO_GPFSEL1 (GPIO_PERI_BASE + 0x04/4)
#define GPIO_GPFSEL2 (GPIO_PERI_BASE + 0x08/4)
#define GPIO_GPFSEL3 (GPIO_PERI_BASE + 0x0C/4)
#define GPIO_GPFSEL4 (GPIO_PERI_BASE + 0x10/4)
#define GPIO_GPFSEL5 (GPIO_PERI_BASE + 0x14/4)
#define GPIO_GPFSEL0 (GPIO_PERI_BASE + 0x00/4)
#define GPIO_GPFSEL1 (GPIO_PERI_BASE + 0x04/4)
#define GPIO_GPFSEL2 (GPIO_PERI_BASE + 0x08/4)
#define GPIO_GPFSEL3 (GPIO_PERI_BASE + 0x0C/4)
#define GPIO_GPFSEL4 (GPIO_PERI_BASE + 0x10/4)
#define GPIO_GPFSEL5 (GPIO_PERI_BASE + 0x14/4)
#define GPIO_GPSET0 (GPIO_PERI_BASE + 0x1C/4)

@@ -111,6 +111,6 @@ #define GPIO_GPSET1 (GPIO_PERI_BASE + 0x20/4)

#define GPIO_GPLEN0 (GPIO_PERI_BASE + 0x70/4)
#define GPIO_GPAREN0 (GPIO_PERI_BASE + 0x7C/4)
#define GPIO_GPAREN1 (GPIO_PERI_BASE + 0x80/4)
#define GPIO_GPAFEN0 (GPIO_PERI_BASE + 0x88/4)
#define GPIO_GPAFEN1 (GPIO_PERI_BASE + 0x8C/4)
#define GPIO_GPAREN0 (GPIO_PERI_BASE + 0x7C/4)
#define GPIO_GPAREN1 (GPIO_PERI_BASE + 0x80/4)
#define GPIO_GPAFEN0 (GPIO_PERI_BASE + 0x88/4)
#define GPIO_GPAFEN1 (GPIO_PERI_BASE + 0x8C/4)
#define GPIO_GPPUD (GPIO_PERI_BASE + 0x94/4)

@@ -136,3 +136,3 @@ #define GPIO_GPPUDCLK0 (GPIO_PERI_BASE + 0x98/4)

#define PWM_FIF1 (PWM_PERI_BASE + 0x18/4)
#define PWM_RNG2 (PWM_PERI_BASE + 0x20/4)
#define PWM_RNG2 (PWM_PERI_BASE + 0x20/4)
#define PWM_DAT2 (PWM_PERI_BASE + 0x24/4)

@@ -142,6 +142,6 @@

#define I2C_PERI_BASE base_pointer[5] // BSC1_BASE
#define I2C_C (I2C_PERI_BASE + 0x00/4)
#define I2C_S (I2C_PERI_BASE + 0x04/4)
#define I2C_C (I2C_PERI_BASE + 0x00/4)
#define I2C_S (I2C_PERI_BASE + 0x04/4)
#define I2C_DLEN (I2C_PERI_BASE + 0x08/4)
#define I2C_A (I2C_PERI_BASE + 0x0C/4)
#define I2C_A (I2C_PERI_BASE + 0x0C/4)
#define I2C_FIFO (I2C_PERI_BASE + 0x10/4)

@@ -170,3 +170,3 @@ #define I2C_DIV (I2C_PERI_BASE + 0x14/4)

/* Temporary dynamic core_clock frequency container (RPi 1 & 2 = 250 MHz, RPi 3 & 4 = 400 MHz) */
uint32_t core_clock_freq = 250000000; // initial value is 250 MHz
uint32_t core_clock_freq = 250000000; // Initial value is 250 MHz

@@ -193,35 +193,35 @@ /**********************************

if (strncmp (info, "Model", 5) == 0)
break;
break;
}
//printf("%s", info);
if(strstr(info, "Pi Zero")||strstr(info, "Pi 1")){
if(strstr(info, "Pi Zero")||strstr(info, "Pi 1")){
//puts("Pi zero/Pi 1");
peri_base = PERI_BASE_RPI1;
}
peri_base = PERI_BASE_RPI1;
}
else if(strstr(info, "Pi Zero 2")||strstr(info, "Pi 3")){
//puts("Pi Zero 2/Pi 3");
peri_base = PERI_BASE_RPI23;
core_clock_freq = CORE_CLOCK_FREQ_RPI23;
}
peri_base = PERI_BASE_RPI23;
core_clock_freq = CORE_CLOCK_FREQ_RPI23;
}
else if(strstr(info, "Pi Compute Module 3")){
//puts("Pi Compute Module 3 Model");
peri_base = PERI_BASE_RPI23;
peri_base = PERI_BASE_RPI23;
core_clock_freq = CORE_CLOCK_FREQ_RPI23;
}
}
else if(strstr(info, "Pi 4")||strstr(info, "Pi Compute Module 4")){
//puts("Pi 4 Model B/Pi Compute Module 4");
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
else if(strstr(info, "Pi 400")){
//puts("Pi 400 Model");
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
else{
//puts("Other Rpi Model");
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}

@@ -237,3 +237,3 @@ /* Verify ST_BASE, its new value should be other than 0x3000

exit(1);
}
}

@@ -243,20 +243,20 @@ /*

// Get 'Hardware' info
rewind (fp);
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Hardware", 8) == 0)
break ;
}
printf("%s", info); // show Hardware line info
rewind (fp);
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Hardware", 8) == 0)
break ;
}
printf("%s", info); // show Hardware line info
/ Get 'Revision' info
// Get 'Revision' info
rewind (fp);
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Revision", 8) == 0)
break ;
}
printf("%s", info); // show Revision line info
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Revision", 8) == 0)
break ;
}
printf("%s", info); // show Revision line info
*/
/* Set each peripheral base address
* consecutively for each base array element
* consecutively for each base array element
*/

@@ -273,3 +273,3 @@ base_add[0] = ST_BASE;

base_add[4] = PWM_BASE;
}
}

@@ -283,3 +283,3 @@ if(i2c_option == 0){

fclose(fp);
fclose(fp);
}

@@ -290,3 +290,4 @@

/*page_size = (size_t)sysconf(_SC_PAGESIZE);
/*
page_size = (size_t)sysconf(_SC_PAGESIZE);
//printf("init page_size: %i\n", page_size);

@@ -297,3 +298,4 @@

exit(1);
}*/
}
*/

@@ -306,4 +308,4 @@ // access = 0, non-root

exit(1);
}
}
}
}
// access = 1, root

@@ -316,30 +318,29 @@ else if(access) {

exit(1);
}
}
}
}
/* Start mmap() process for each peripheral base address
/* Start mmap() process for each peripheral base address
* and capture the corresponding peripheral memory base pointers
*/
for(i = 0; i < BASE_INDEX; i++){
base_pointer[i] = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base_add[i]);
for(i = 0; i < BASE_INDEX; i++){
base_pointer[i] = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base_add[i]);
if (base_pointer[i] == MAP_FAILED) {
perror("mmap() error");
perror("mmap() error");
printf("%s() error: ", __func__);
puts("Invalid peripheral register base address.");
if(close(fd) < 0){
perror("fd close");
}
if(close(fd) < 0)
perror("fd close");
exit(1);
}
}
/* Reset peripheral base register pointers back to 0 */
// Note: Disable this for SocketCan operation
*base_pointer[i] = 0;
*base_pointer[i] = 0;
}
/* Close fd after memory-mapped operation */
if(close(fd) < 0){
/* Close fd after memory-mapped operation */
if(close(fd) < 0)
perror("fd close");
}
}

@@ -354,3 +355,4 @@

void rpi_init(int access) {
set_peri_base_address(0, 0, 1);
set_peri_base_address(0, 0, 1);
start_mmap(access);

@@ -379,3 +381,3 @@ }

{
int i;
int i;
//page_size = (size_t)sysconf(_SC_PAGESIZE);

@@ -385,12 +387,12 @@ //printf("close page_size: %i\n", page_size);

for(i = 0; i < BASE_INDEX; i++){
if (munmap((uint32_t *) base_pointer[i] , BLOCK_SIZE) < 0){
perror("munmap() error");
if (munmap((uint32_t *) base_pointer[i] , BLOCK_SIZE) < 0){
perror("munmap() error");
printf("%s() error: ", __func__);
puts("munmap() operation fail");
return -1;
}
}
}
/* munmap() success */
return 0;
return 0;
}

@@ -413,7 +415,7 @@

void nswait(uint64_t ns) {
struct timespec req = { ns / 1000000, ns % 1000000 };
struct timespec rem;
struct timespec req = { ns / 1000000, ns % 1000000 };
struct timespec rem;
while ( nanosleep(&req,&rem) == -1 )
req.tv_nsec = rem.tv_nsec;
while ( nanosleep(&req,&rem) == -1 )
req.tv_nsec = rem.tv_nsec;
}

@@ -427,3 +429,3 @@

while ( nanosleep(&req,&rem) == -1 )
req.tv_nsec = rem.tv_nsec;
req.tv_nsec = rem.tv_nsec;
}

@@ -437,3 +439,3 @@

while ( nanosleep(&req, &rem) == -1 )
req.tv_nsec = rem.tv_nsec;
req.tv_nsec = rem.tv_nsec;
}

@@ -514,7 +516,7 @@

volatile uint32_t *gpsel = (uint32_t *)(GPIO_GPFSEL0 + (pin/10)); // get the GPFSEL0 pointer (GPFSEL0 ~ GPFSEL5) based on the pin number selected
uint32_t mask = ~ (7 << (pin % 10)*3); // mask to reset fsel to 0 first
*gpsel &= mask; // reset gpsel value to 0
mask = (fsel << ((pin) % 10)*3); // mask for new fsel value
uint32_t mask = ~ (7 << (pin % 10)*3); // mask to reset fsel to 0 first
*gpsel &= mask; // reset gpsel value to 0
mask = (fsel << ((pin) % 10)*3); // mask for new fsel value
__sync_synchronize();
*gpsel |= mask; // write new fsel value to gpselect pointer
*gpsel |= mask; // write new fsel value to gpselect pointer
__sync_synchronize();

@@ -534,3 +536,3 @@ }

void gpio_output(uint8_t pin){
set_gpio(pin, 1);
set_gpio(pin, 1);
}

@@ -560,19 +562,19 @@

else if(mode == 5){
set_gpio(pin, 5); // alt-func 1
}
set_gpio(pin, 5); // alt-func 1
}
else if(mode == 6){
set_gpio(pin, 6); // alt-func 2
}
}
else if(mode == 7){
set_gpio(pin, 7); // alt-func 3
}
set_gpio(pin, 7); // alt-func 3
}
else if(mode == 3){
set_gpio(pin, 3); // alt-func 4
}
else if(mode == 2){
set_gpio(pin, 2); // alt-func 5
}
else if(mode == 2){
set_gpio(pin, 2); // alt-func 5
}
else{
printf("%s() error: ", __func__);
puts("Invalid mode parameter.");
puts("Invalid mode parameter.");
}

@@ -608,2 +610,24 @@ }

/* Turn ON a GPIO pin
*/
void gpio_on(uint8_t pin){
gpio_write(pin, 1);
}
/* Turn OFF a GPIO pin
*/
void gpio_off(uint8_t pin){
gpio_write(pin, 0);
}
/* Create a simple sing-shot pulse
*
* td as time duration or period of the pulse
*/
void gpio_pulse(uint8_t pin, int td){
gpio_on(pin);
mswait(td);
gpio_off(pin);
}
/* Read the current state of a GPIO pin (input/output)

@@ -649,10 +673,10 @@ *

if(bit == 1){
setBit(GPIO_GPHEN0, pin);
setBit(GPIO_GPHEN0, pin);
}
else if(bit == 0){
clearBit(GPIO_GPHEN0, pin);
clearBit(GPIO_GPHEN0, pin);
}
else {
printf("%s() error: ", __func__);
puts("Invalid bit parameter.");
puts("Invalid bit parameter.");
}

@@ -668,10 +692,10 @@ }

if(bit == 1){
setBit(GPIO_GPLEN0, pin);
setBit(GPIO_GPLEN0, pin);
}
else if(bit == 0){
clearBit(GPIO_GPLEN0, pin);
clearBit(GPIO_GPLEN0, pin);
}
else {
printf("%s() error: ", __func__);
puts("Invalid bit parameter.");
puts("Invalid bit parameter.");
}

@@ -710,10 +734,10 @@ }

if(bit == 1){
setBit(GPIO_GPFEN0, pin);
setBit(GPIO_GPFEN0, pin);
}
else if(bit == 0){
clearBit(GPIO_GPFEN0, pin);
clearBit(GPIO_GPFEN0, pin);
}
else {
printf("%s() error: ", __func__);
puts("Invalid bit parameter.");
puts("Invalid bit parameter.");
}

@@ -729,10 +753,10 @@ }

if(bit == 1){
setBit(GPIO_GPAREN0, pin);
setBit(GPIO_GPAREN0, pin);
}
else if(bit == 0){
clearBit(GPIO_GPAREN0, pin);
clearBit(GPIO_GPAREN0, pin);
}
else {
printf("%s() error: ", __func__);
puts("Invalid bit parameter.");
puts("Invalid bit parameter.");
}

@@ -748,10 +772,10 @@ }

if(bit == 1){
setBit(GPIO_GPAFEN0, pin);
setBit(GPIO_GPAFEN0, pin);
}
else if(bit == 0){
clearBit(GPIO_GPAFEN0, pin);
clearBit(GPIO_GPAFEN0, pin);
}
else {
printf("%s() error: ", __func__);
puts("Invalid bit parameter.");
puts("Invalid bit parameter.");
}

@@ -773,3 +797,3 @@ }

void gpio_reset_event(uint8_t pin) {
setBit(GPIO_GPEDS0, pin);
setBit(GPIO_GPEDS0, pin);
}

@@ -785,14 +809,14 @@

if(value == 0){
*GPIO_GPPUD = 0x0; // Disable PUD/Pull-UP/Down
}
*GPIO_GPPUD = 0x0; // Disable PUD/Pull-UP/Down
}
else if(value == 1){
*GPIO_GPPUD = 0x1; // Enable PD/Pull-Down
*GPIO_GPPUD = 0x1; // Enable PD/Pull-Down
}
else if(value == 2){
*GPIO_GPPUD = 0x2; // Enable PU/Pull-Up
*GPIO_GPPUD = 0x2; // Enable PU/Pull-Up
}
else{
printf("%s() error: ", __func__);
else{
printf("%s() error: ", __func__);
puts("Invalid pud value.");
}
}

@@ -824,14 +848,14 @@ uswait(150); /* required wait times based on bcm2835 manual */

void pwm_set_pin(uint8_t pin){
if(pin == 12||pin ==13) { // alt 100b, PHY pin 33, GPIO 13, alt 0
set_gpio(pin, 4); // alt 100b, PHY pin 32, GPIO 12, alt 0
}
else if(pin == 18||pin == 19) { // alt 10b, PHY pin 35, GPIO 19, alt 5
set_gpio(pin, 2); // alt 10b, PHY pin 12, GPIO 18, alt 5
if(pin == 12||pin ==13) { // alt 100b, PHY pin 33, GPIO 13, alt 0
set_gpio(pin, 4); // alt 100b, PHY pin 32, GPIO 12, alt 0
}
else if(pin == 18||pin == 19) { // alt 10b, PHY pin 35, GPIO 19, alt 5
set_gpio(pin, 2); // alt 10b, PHY pin 12, GPIO 18, alt 5
}
else {
printf("%s() error: ", __func__);
else {
printf("%s() error: ", __func__);
puts("Invalid pin number for PWM.");
puts("Choose only from board header layout pins 12, 32, 33 and 35.");
exit(1);
}
}
}

@@ -842,9 +866,9 @@

if(pin == 18||pin ==12||pin==13||pin==19) {
gpio_input(pin); // GPIO18/PHY12, GPIO12/PHY32, GPIO13/PHY33, GPIO19/PHY35
}
else {
printf("%s() error: ", __func__);
gpio_input(pin); // GPIO18/PHY12, GPIO12/PHY32, GPIO13/PHY33, GPIO19/PHY35
}
else {
printf("%s() error: ", __func__);
puts("Invalid pin.");
exit(1);
}
exit(1);
}
}

@@ -876,7 +900,7 @@

if(isBitSet(CM_PWMCTL, 7)){
return 1; // clk is running
}
return 1; // clk is running
}
else{
return 0; // clk is not running
}
return 0; // clk is not running
}
}

@@ -910,4 +934,6 @@

/* set DIVF (bit num 11-0) divisor from clock manager
general purpose register (CM_GP2DIV) while clk is not running */
/*
set DIVF (bit num 11-0) divisor from clock manager
general purpose register (CM_GP2DIV) while clk is not running
*/
if(!isBitSet(CM_PWMCTL, 7)){

@@ -939,4 +965,4 @@ *CM_PWMDIV = 0x5A000000 | ( div << 12 );

else{
return -1;
}
return -1;
}
}

@@ -962,21 +988,21 @@

bool WERR1 = isBitSet(PWM_STA, 2);
uswait(10);
uswait(10);
if (!STA1) {
if (RERR1)
setBit(PWM_STA, 3); // reset RERR1
if (WERR1)
if(!STA1) {
if(RERR1)
setBit(PWM_STA, 3); // reset RERR1
if(WERR1)
setBit(PWM_STA, 2); // reset WERR1
if (BERR)
setBit(PWM_STA, 8); // reset BERR
if(BERR)
setBit(PWM_STA, 8); // reset BERR
}
if(!STA2){
if (RERR1)
setBit(PWM_STA, 3); // reset RERR1
if (WERR1)
setBit(PWM_STA, 2); // reset WERR1
if (BERR)
setBit(PWM_STA, 8); // reset BERR
if(RERR1)
setBit(PWM_STA, 3); // reset RERR1
if(WERR1)
setBit(PWM_STA, 2); // reset WERR1
if(BERR)
setBit(PWM_STA, 8); // reset BERR
}
uswait(10);
uswait(10);
}

@@ -989,11 +1015,11 @@

if(n == 1){
setBit(PWM_CTL, position);
}
else if(n == 0) {
clearBit(PWM_CTL, position);
}
else{
puts("Invalid n control parameter. Choose 1 or 0 only.");
}
uswait(10);
setBit(PWM_CTL, position);
}
else if(n == 0) {
clearBit(PWM_CTL, position);
}
else{
puts("Invalid n control parameter. Choose 1 or 0 only.");
}
uswait(10);
}

@@ -1008,4 +1034,4 @@

// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
pwm_reg_ctrl(n, 0);
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
pwm_reg_ctrl(n, 0);
}

@@ -1029,4 +1055,4 @@ // Channel 2

// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
pwm_reg_ctrl(n, 7);
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
pwm_reg_ctrl(n, 7);
}

@@ -1050,3 +1076,3 @@ // Channel 2

// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
pwm_reg_ctrl(n, 4);

@@ -1067,3 +1093,3 @@ }

// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
*PWM_RNG1 = range;

@@ -1085,16 +1111,16 @@ reset_status_reg();

void pwm_set_data(uint8_t pin, uint32_t data){
// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
*PWM_DAT1 = data;
// Channel 1
if( pin == 18 || pin == 12) { // GPIO 18/12, PHY 12/32
*PWM_DAT1 = data;
reset_status_reg();
}
// Channel 2
else if(pin == 13 || pin == 19) { // GPIO 13/19, PHY 33/35
*PWM_DAT2 = data;
reset_status_reg();
}
else{
// Channel 2
else if(pin == 13 || pin == 19) { // GPIO 13/19, PHY 33/35
*PWM_DAT2 = data;
reset_status_reg();
}
else{
printf("%s() error: ", __func__);
puts("Invalid pin.");
}
}
}

@@ -1211,3 +1237,3 @@

return 1; // i2c initialization success is successful
return 1; // i2c initialization is successful
}

@@ -1236,3 +1262,3 @@

// set a new msb and lsb values to data delay register
// set a new msb and lsb values to data delay register
volatile uint32_t value = (volatile uint32_t)(msb << 16 | lsb);

@@ -1251,3 +1277,4 @@

/*volatile uint32_t delay_reg = *I2C_DEL;
/*
volatile uint32_t delay_reg = *I2C_DEL;

@@ -1260,3 +1287,4 @@ // Extract the msb and lsb values from a pointer

printf("lsb1:%x\n", lsb1);
printf("delay_reg:%x\n", delay_reg);*/
printf("delay_reg:%x\n", delay_reg);
*/

@@ -1273,8 +1301,10 @@ return *I2C_DEL;

/*printf("cdiv msb:%x\n", msb);
/*
printf("cdiv msb:%x\n", msb);
printf("cdiv lsb:%x\n", lsb);
printf("cdiv_reg:%x\n", div_reg);*/
printf("cdiv_reg:%x\n", div_reg);
*/
volatile uint32_t *div = I2C_DIV;
lsb = 0x05DC;
lsb = 0x05DC;
// reset

@@ -1299,3 +1329,3 @@ *div = (volatile uint32_t)(msb << 16 | lsb);

/* get the divisor value from the 250 MHz system clock source */
//uint32_t divider = (core_clock_freq / baud); // using a dynamic core clock freq
//uint32_t divider = (core_clock_freq / baud); // using a dynamic core clock freq

@@ -1311,8 +1341,10 @@ uint32_t divider = (CORE_CLK_FREQ/baud); // using a fixed core clock freq

/*volatile uint32_t *clkt = I2C_CLKT;
printf("clkt:%i\n", *clkt);
/*
volatile uint32_t *clkt = I2C_CLKT;
printf("clkt:%i\n", *clkt);
if(i == buf_len){
puts("Data tansfer is complete.");
}*/
}
*/

@@ -1323,3 +1355,3 @@ if(i < buf_len)

printf("%s(): ", __func__);
puts("Data tansfer is incomplete.");
puts("Data tansfer is incomplete.");
}

@@ -1330,3 +1362,3 @@ else if(i > buf_len)

printf("%s(): ", __func__);
puts("Data tansfer error.");
puts("Data tansfer error.");
}

@@ -1339,3 +1371,3 @@

printf("%s(): ", __func__);
puts("Slave address is not acknowledged.");
puts("Slave address is not acknowledged.");
}

@@ -1348,3 +1380,3 @@

printf("%s(): ", __func__);
puts("Clock stretch timeout.");
puts("Clock stretch timeout.");
}

@@ -1361,3 +1393,2 @@ /* write error

puts("Not all data were sent to the slave device.");
}

@@ -1373,3 +1404,3 @@ /* read error

printf("%s(): ", __func__);
puts("Not all data were received from the slave device.");
puts("Not all data were received from the slave device.");
}

@@ -1388,4 +1419,4 @@

result = 4;
printf("%s(): ", __func__);
puts("Data transfer is incomplete.");
printf("%s(): ", __func__);
puts("Data transfer is incomplete.");
}

@@ -1505,6 +1536,6 @@

//while(isBitSet(I2C_S, 5) && (i <= rbuf_len))
while(isBitSet(I2C_S, 5) && (rbuf_len >= i )) // check RXD field (RXD = 0 FIFO is empty, RXD = 1 FIFO contains at least 1 byte of data)
while(isBitSet(I2C_S, 5) && (rbuf_len >= i )) // check RXD field (RXD = 0 FIFO is empty, RXD = 1 FIFO contains at least 1 byte of data)
{
rbuf[i] = *fifo;
i++;
rbuf[i] = *fifo;
i++;
}

@@ -1564,3 +1595,3 @@ }

if(i2c_pin_set == 0){
//puts("reset SDA0/SCL0 pins to GPIO input");
//puts("reset SDA0/SCL0 pins to GPIO input");
set_gpio(0, 0); /* alt 00b, PHY 27, GPIO 00, alt 0 SDA */

@@ -1573,3 +1604,3 @@ set_gpio(1, 0); /* alt 00b, PHY 28, GPIO 01, alt 0 SCL */

set_gpio(3, 0); /* alt 00b, PHY 5, GPIO 03, alt 0 SCL */
}
}
}

@@ -1585,3 +1616,3 @@

{
//rpi_init(1);
//rpi_init(1);
//mswait(25);

@@ -1592,4 +1623,4 @@

printf("%s() error: ", __func__);
puts("Invalid SPI registers addresses.");
return 0;
puts("Invalid SPI registers addresses.");
return 0;
}

@@ -1606,3 +1637,3 @@

clearBit(SPI_CS, 13); // set SPI to SPI Master (Standard SPI)
clear_fifo(SPI_CS); // Clear SPI TX and RX FIFO
clear_fifo(SPI_CS); // Clear SPI TX and RX FIFO

@@ -1628,3 +1659,3 @@ return 1;

volatile uint32_t *div = SPI_CLK;
*div = divider;
*div = divider;
}

@@ -1643,11 +1674,11 @@

clearBit(SPI_CS, 2); //CPHA 0
clearBit(SPI_CS, 3); //CPOL 0
clearBit(SPI_CS, 3); //CPOL 0
}
else if(mode == 1){
setBit(SPI_CS, 2); //CPHA 1
clearBit(SPI_CS, 3); //CPOL 0
setBit(SPI_CS, 2); //CPHA 1
clearBit(SPI_CS, 3); //CPOL 0
}
else if(mode == 2){
clearBit(SPI_CS, 2); //CPHA 0
setBit(SPI_CS, 3); //CPOL 1
setBit(SPI_CS, 3); //CPOL 1
}

@@ -1658,15 +1689,15 @@ else if(mode == 3){

}
else{
printf("%s() error: ", __func__);
puts("invalid mode");
}
else{
printf("%s() error: ", __func__);
puts("invalid mode");
}
// alternate code
/*
volatile uint32_t *cs = SPI_CS;
uint32_t mask = ~ (3 << 2); // clear bit position 2 and 3 first
*cs &= mask; // set mask to 0
mask = (mode << 2); // write mode value to set SPI data mode
*cs |= mask; // set data mode
*/
// alternate code
/*
volatile uint32_t *cs = SPI_CS;
uint32_t mask = ~ (3 << 2); // clear bit position 2 and 3 first
*cs &= mask; // set mask to 0
mask = (mode << 2); // write mode value to set SPI data mode
*cs |= mask; // set data mode
*/
}

@@ -1686,3 +1717,3 @@

uint32_t mask = ~ (3 << 0); // clear bit 0 and 1 first
*cs_addr &= mask; // set mask to value 0
*cs_addr &= mask; // set mask to value 0
mask = (cs << 0); // write cs value to set SPI data mode

@@ -1704,3 +1735,3 @@ *cs_addr |= mask; // set cs value

else if(cs == 0 && active == 1){
setBit(SPI_CS, 21);
setBit(SPI_CS, 21);
}

@@ -1738,8 +1769,8 @@ else if(cs == 1 && active == 0){

{
// TX fifo is not full, add/write more bytes
while(isBitSet(SPI_CS, 18) && (w < len))
{
*fifo = wbuf[w];
w++;
}
// TX fifo is not full, add/write more bytes
while(isBitSet(SPI_CS, 18) && (w < len))
{
*fifo = wbuf[w];
w++;
}
}

@@ -1750,8 +1781,8 @@

{
// RX fifo is not empty, read more received bytes
// RX fifo is not empty, read more received bytes
while(isBitSet(SPI_CS, 17) && (r < len ))
{
rbuf[r] = *fifo;
r++;
}
{
rbuf[r] = *fifo;
r++;
}
}

@@ -1764,4 +1795,4 @@

if(isBitSet(SPI_CS, 16)){
printf("%s() error: ", __func__);
puts("data transfer error");
printf("%s() error: ", __func__);
puts("data transfer error");
}

@@ -1788,4 +1819,4 @@ }

{
*fifo = wbuf[i];
i++;
*fifo = wbuf[i];
i++;
}

@@ -1816,4 +1847,4 @@ }

{
rbuf[i] = *fifo;
i++;
rbuf[i] = *fifo;
i++;
}

@@ -1826,1 +1857,2 @@ }

@@ -48,2 +48,8 @@ /**

void gpio_on(uint8_t pin);
void gpio_off(uint8_t pin);
void gpio_pulse(uint8_t pin, int td);
void gpio_reset_all_events(uint8_t pin);

@@ -134,3 +140,2 @@

#ifdef __cplusplus

@@ -137,0 +142,0 @@ }