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.3
to
1.7.4
+189
-686
lib/array-gpio.js
/*!
* array-gpio
*
* Copyright(c) 2017 Ed Alegrid
* Copyright(c) 2017 Ed Alegrid <ealegrid@gmail.com>
* MIT Licensed

@@ -10,42 +10,38 @@ */

const EventEmitter = require('events');
class StateEmitter extends EventEmitter {}
const emitter = exports.emitter = new StateEmitter();
emitter.setMaxListeners(2);
const rpi = require('./rpi.js');
const I2C = require('./i2c.js');
const SPI = require('./spi.js');
const PWM = require('./pwm.js');
const i2c = require('./i2c.js');
const spi = require('./spi.js');
const pwm = require('./pwm.js');
const GpioInput = require('./gpio-input.js');
const GpioOutput = require('./gpio-output.js');
var pwr3 = [1,17];
var pwr5 = [2,4];
var uart = {txd:8,rxd:10};
var i2c = {sda:3,scl:5};
var pwm = {pwm0:[12,32],pwm1:[33,35]};
var spi = {mosi:19,miso:21,sclk:23,cs0:24,cs1:26};
var eprom = {sda:27,scl:28};
var ground = [6,9,14,20,25,30,34,39];
var gpio = [3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,27,28,29,31,32,33,35,36,37,38,40];
/* time variables */
var d1, d2;
var outputPin = [];
var inputPin = [], inputObject = [];
var activeGpioPins = [];
/* debug mode variables */
var debugState = false, debugStateAdvanced = false;
function startTime(){
d1 = new Date();
}
/* PWM variables */
var pwmObjectTotal = 0, pwmPin = {c1:[], c2:[]}, pwmObject = 0;
function endTime(m){
d2 = new Date();
let eT = Math.abs(d2-d1);
if(m === undefined){
console.log(eT + ' ms');
}
else if(m === 1){
return (eT + ' ms');
}
}
/* GPIO setup variables */
var eventPin = [], arrayPinCheck = [];
function findDuplicatePins(arr) {
let dup = arr.filter((item, index) => arr.indexOf(item) !== index);
if(dup[0]){
console.log('*** WARNING : duplicate pin detected', dup, '***' )
}
}
/* watch input object container */
//var watchData = [];
/* GPIO option input default values */
function setOption(options){
if(options.index === undefined){
function setInputDefaultOptions(options){
if(!options.index === undefined){
options.index = '0~n';

@@ -59,100 +55,122 @@ }

}
if(options.intR === undefined){
options.intR = 'none';
if(options.pud === undefined){
options.pud = null;
}
if(options.pinCheck === undefined || options.pinCheck === true){
options.pinCheck = true;
}
return options;
}
/* watch/monitor a gpio input pin */
function watchPin(edge, cb, pin, td){
rpi.gpio_watchPin(edge, cb, pin, td);
function createGpioSingleObject(arg, pinArray, type, options){
let pin = arg[0];
let gpioObject = {};
let config = '{ ' + pin + ' } ';
if(Number.isInteger(pin)){
pinArray.push(pin);
activeGpioPins.push(pin);
if(type === 0){ // input
inputPin.push(pin);
gpioObject = new GpioInput(pin, 0, options);
inputObject.push(gpioObject);
}
else if(type === 1){ // output
outputPin.push(pin);
gpioObject = new GpioOutput(pin, 0, options);
}
}
if(type === 0){
console.log('GPIO Input', config + endTime(1));
}
else if(type === 1){
console.log('GPIO Output', config + endTime(1));
}
return gpioObject;
}
/* unwatch a gpio input pin */
function unwatchPin(pin){
rpi.gpio_unwatchPin(pin);
function createGpioArrayObject(pinArray, type, options){
let pins = [];
let objectArray = [];
let config = '{ pin:[' + pinArray + '], index:0~n } ';
for (let i = 0; i < pinArray.length; i++) {
let index = i, pin = pinArray[i];
activeGpioPins.push(pin);
if(options.index === 'pin' || options.i === 1){
config = '{ pin:[' + pinArray + '], index:pin } ';
index = pinArray[i];
}
if(type === 0){ // input
inputPin.push(pin);
objectArray[index] = new GpioInput(pin, index, options);
inputObject.push(objectArray[index]);
}
else if(type === 1){ // output
outputPin.push(pin);
objectArray[index] = new GpioOutput(pin, index, options);
}
}
if(type === 0){
console.log('GPIO Input', config + endTime(1));
}
else if(type === 1){
console.log('GPIO Output', config + endTime(1));
}
return objectArray;
}
/* show warning msg for GPIO duplicate pin */
function duplicatePinError(pin) {
console.log('pin ' + pin + ' is already in used\n');
function setArrayObject1(args, pinArray, type, options){
let pins = args[0].pin;
for (let x = 0; x < pins.length; x++) {
if(Number.isInteger(pins[x]) ){
pinArray.push(pins[x]);
}
}
options.i = args[0].i;
options.index = args[0].index;
}
/* invalid pin error handler */
function invalidPinError(pin) {
console.log('invalid pin', pin);
throw new Error('invalid pin');
}
/* debug message function */
function dmsg(x, msg, cb){
if(x === undefined){
console.log(msg);
}
else if(x === 0){
if(debugState && !debugStateAdvanced){
//continue
function setArrayObject2(args, pinArray, type, options){
for (let x = 0; x < args.length; x++) {
let pin = args[x];
if(Number.isInteger(pin) ){
pinArray.push(pin);
}
else if(args[x] === 'pin'){
options.index = args[x];
}
}
else if (x === 1){
if(debugState && debugStateAdvanced){
if(msg){
console.log(msg);
}
}
}
}
/* process time functions */
function getTime(){
var d = new Date();
var t = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + ':' + d.getMilliseconds();
return t;
}
function createGpio(type, pins){
startTime();
function startTime(){
d1 = new Date();
}
let gpioObject = [], gpioPins = [], options = {};
function endTime(m){
d2 = new Date();
var eT = Math.abs(d2-d1);
if(m === undefined){
console.log(eT + ' ms');
pins = Array.from(pins);
rpi.validatePins(pins);
if(type == 0){
setInputDefaultOptions(options);
}
// single gpio object, e.g. r.setInput(11) or r.Output(33)
if(Number.isInteger(pins[0]) && pins.length === 1){
delete options.index;
gpioObject = createGpioSingleObject(pins, gpioPins, type, options);
}
else if(m === 1){
return (eT + ' ms');
// array object type 1, e.g. r.input({pin:[pin1, pin2, pin3, ... pinN], options})
else if(!Number.isInteger(pins[0]) && pins.length === 1) {
setArrayObject1(pins, gpioPins, type, options)
gpioObject = createGpioArrayObject(gpioPins, type, options);
}
}
// array object type 2, e.g. r.output(pin1, pin2, pin3, ... pinN, options)
else if(pins.length > 1) {
setArrayObject2(pins, gpioPins, type, options);
gpioObject = createGpioArrayObject(gpioPins, type, options);
}
findDuplicatePins(activeGpioPins);
/* Check GPIO duplicate pins */
function checkPinOnArray(arr1){
var pinCheck = '\n*** Warning ***\nDuplicate pin detected [';
for (var x = 0; x < arr1.length; x++) {
for (var i = 0; i < arr1.length; i++) {
if(x === i){
pinCheck += ' ' + arr1[i];
break;
}
else if (arr1[x] === arr1[i]) {
pinCheck += ' *' + arr1[i];
if(debugStateAdvanced){
dmsg(1, pinCheck + ' ] *** Fail ***');
return false
}
else{
console.log('** warning **');
duplicatePinError(arr1[x]);
}
}
}
}
dmsg(1, pinCheck + ' ] OK');
return true;
Object.preventExtensions(gpioObject);
return gpioObject;
}
/******************************

@@ -165,630 +183,115 @@ *

constructor (){
this.in = this.setInput;
this.input = this.setInput;
this.Input = this.setInput;
this.out = this.setOutput;
this.output = this.setOutput;
this.Output = this.setOutput;
}
constructor (){}
close()
{
rpi.lib_close();
close (){
rpi.rpi_close();
}
/* watchInput - shared GPIO input monitoring method */
watchInput (edge, cb, td){
if(typeof edge === 'function' && typeof cb === 'number'){
td = cb;
cb = edge;
edge = null;
for (let x = 0; x < inputObject.length; x++) {
inputObject[x].watchPin(edge, cb, td);
}
else if(typeof edge === 'function' && cb === undefined){
cb = edge;
edge = null;
}
else if(typeof edge !== 'string' && typeof edge !== 'number' && edge !== null){
throw new Error('invalid edge argument');
}
else if ((typeof edge === 'string' || typeof edge === 'number') && typeof cb !== 'function'){
throw new Error('invalid callback argument');
}
for (var x = 0; x < eventPin.length; x++) {
watchPin(edge, cb, eventPin[x], td);
}
}
/* unwatch() method (for watchInput) */
unwatchInput(){
for (var x = 0; x < eventPin.length; x++) {
unwatchPin(eventPin[x]);
}
for (let x = 0; x < inputObject.length; x++) {
inputObject[x].unwatchPin(edge, cb, td);
}
}
/********************************************
/***********
GPIO Methods
GPIO
********************************************/
/*
* GPIO setInput method
*/
***********/
setInput () {
startTime();
var input = [], options = {}, inputPin = [], pinCheck = true, config, arraySetup;
return createGpio(0, arguments);
}
if(arguments[0] === undefined || arguments[0] === null ){
console.log('\nsetInput() - empty argument!');
invalidPinError(arguments[0]);
}
in = this.setInput;
input = this.setInput;
Input = this.setInput;
if(typeof arguments[0] === 'string' || typeof arguments[0] === 'function' ){
console.log('\nsetInput() - invalid argument!');
invalidPinError(arguments[0]);
}
/* check for invalid pin arguments - empty {} or {pin:[]} */
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]);
}
/*
* barebone single input object
* r.setInput(11);
*/
if(Number.isInteger(arguments[0]) && arguments.length === 1) {
var pin = arguments[0];
try{
rpi.gpio_open(arguments[0], 0);
inputPin.push(arguments[0]);
eventPin.push(arguments[0]);
arrayPinCheck.push(arguments[0]);
config = '{ pin:' + inputPin + ' } ' + endTime(1);
console.log('GPIO Input', config);
return new GpioInput(0, pin, {});
}
catch(e){
return invalidPinError(arguments[0]);
}
}
/*
* array object
* r.input({pin:[pin1, pin2, pin3, ... pinN], options})
*/
if(!Number.isInteger(arguments[0]) && typeof arguments[0] === 'object' && arguments.length === 1) {
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];
}
/*
* array object
* r.input(pin1, pin2, pin3, ... pinN, options)
*/
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]);
}
// invalid pin number
else if(Number.isInteger(arguments[x]) && arguments[x] <= 0 || arguments[x] > 40){
invalidPinError(arguments[x]);
}
else if(arguments[x] === 're' || arguments[x] === 'fe'){
options.edge = arguments[x];
}
else if(arguments[x] === 'pu' || arguments[x] === 'pd'){
options.intR = arguments[x];
}
else if(arguments[x] === true || arguments[x] === false){
options.event = arguments[x];
}
else if(arguments[x] === 'PinAsIndex'){
options.index = arguments[x];
}
else if(arguments[x] === 'NoPinCheck'){
options.pinCheck = arguments[x];
pinCheck = false;
}
else if(arguments[x] instanceof Object ){
options = arguments[x];
}
else {
console.log('Invalid arguments', arguments[x]);
}
} // for
}
setOption(options);
/*
* function to create an input array object
*/
function createObject(inputPin, options, GpioInput){
for (var i = 0; i < inputPin.length; i++) {
var index = i, pin = inputPin[i];
if(options){
if(options.pinCheck === 'NoPinCheck' || options.pinCheck === false){
pinCheck = false;
}
if(options.index === 'PinAsIndex' || options.index === 'pin'){
index = inputPin[i];
}
eventPin.push(pin);
input[index] = new GpioInput(index, pin, options);
}
}
}
createObject(inputPin, options, GpioInput);
/* check for duplicate pins */
if(debugState || debugStateAdvanced){
arrayPinCheck = [];
}
else if(pinCheck){
checkPinOnArray(arrayPinCheck);
}
if(inputPin.length > 1) {
arraySetup = options.index;
config = '{ pin:[' + inputPin + ']' + ', index:' + options.index + ' } ' + endTime(1);
if(options.array){
config = '{ pin:[' + inputPin + ']' + ', array:true, index:' + options.index + ' } ' + endTime(1);
}
}
else if(inputPin.length < 2 && options.array === true && (options.index === 'PinAsIndex' || options.index === 'pin')){
config = '{ pin:[' + inputPin + '], array:true, index:pin } ' + endTime(1);
}
else if(inputPin.length < 2 && options.array === true ){
config = '{ pin:[' + inputPin + '], array:true, index:0~n } ' + endTime(1);
}
else{
config = '{ pin:' + inputPin + ' } ' + endTime(1);
}
/* INPUT GPIO config output */
console.log('GPIO input ', config);
Object.preventExtensions(input);
return input;
} // end of setInput
/*
* GPIO setOutput method property
*/
setOutput () {
return createGpio(1, arguments);
}
startTime();
out = this.setOutput;
output = this.setOutput;
Output = this.setOutput;
var output = [], outputPin = [], options = {}, pinCheck = true, config, arraySetup;
/*********
if(arguments[0] === undefined || arguments[0] === null ){
console.log('\nsetOutput() - empty argument!');
invalidPinError(arguments[0]);
}
PWM
if(typeof arguments[0] === 'string' || typeof arguments[0] === 'function' ){
console.log('\nsetOutput() - invalid argument!');
invalidPinError(arguments[0]);
}
*********/
// classic api
// e.g let pwm = new r.PWM(12)
PWM = pwm;
/* check for invalid arguments - empty {} or {pin:[]} */
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]);
}
/*
* barebone single output object
* r.setOutput(33);
*/
if(Number.isInteger(arguments[0]) && arguments.length === 1 && arguments[0] > 0 && arguments[0] < 41) {
var pin = arguments[0];
try{
rpi.gpio_open(arguments[0] , 1);
outputPin.push(arguments[0]);
arrayPinCheck.push(arguments[0]);
config = '{ pin:' + outputPin + ' } ' + endTime(1);
console.log('GPIO Output', config);
return new GpioOutput(0, pin, {});
}
catch(e){
return invalidPinError(arguments[0]);
}
}
/*
* array object
* r.output({pin:[pin1, pin2, pin3, ... pinN], options})
*/
if(!Number.isInteger(arguments[0]) && typeof arguments[0] === 'object' && arguments.length === 1) {
for (var x = 0; x < arguments[0].pin.length; x++) {
// 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){
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]);
}
// invalid pin number
else{
invalidPinError(arguments[0].pin[x]);
}
}
options = arguments[0];
}
/*
* array object
* r.output(pin1, pin2, pin3, ... pinN, options)
*/
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 output use
if(Number.isInteger(arguments[x]) && arguments[x] > 0 && arguments[x] < 41 ){
try{
rpi.gpio_open(arguments[x], 1);
}
catch(e){
outputPin.push(' *' + arguments[x]);
console.log('output pins [ ' + outputPin + ' ]');
invalidPinError(arguments[x]);
}
outputPin[x] = arguments[x]; /* direct */
//outputPin.push(arguments[x]); /* push method */
arrayPinCheck.push(arguments[x]);
}
// invalid pin number
else if(Number.isInteger(arguments[x]) && arguments[x] <= 0 || arguments[x] > 40){
invalidPinError(arguments[x]);
}
else if(arguments[x] === 'PinAsIndex'){
options = arguments[x];
}
else if(arguments[x] === 'NoPinCheck'){
options = arguments[x];
pinCheck = false;
}
else if(arguments[x] instanceof Object ){
if(arguments[x].pinCheck === false){
pinCheck = false;
}
if(arguments[x].pinCheck === true){
pinCheck = true;
}
options = arguments[x];
}
else{
console.log('Invalid arguments', arguments[x]);
}
}
}
/*
* function to create an output object
*/
function createObject(outputPin, options, GpioOutput){
for (var x = 0; x < outputPin.length; x++) { /* Dec. 27, 2017 */
var index = x;
if(options){
if(options === 'PinAsIndex' || options.index === 'pin'){
index = outputPin[x];
}
}
output[index] = new GpioOutput(index, outputPin[x]);
}
}
createObject(outputPin, options, GpioOutput);
/* check for duplicate pins */
if(debugState || debugStateAdvanced){
arrayPinCheck = [];
}
else if(pinCheck) {
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){
arraySetup = 'array:true, index:pin';
}
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);
}
else if(outputPin.length < 2 && options && options.array){
config = '{ pin:[' + outputPin + '], array:true, index:0~n } ' + endTime(1);
}
else{
config = '{ pin:' + outputPin + ' } ' + endTime(1);
}
/* OUTPUT GPIO config output */
console.log('GPIO output ' + config);
Object.preventExtensions(output);
return output;
} // end of setOutput
/* validPin helper method */
validPin (){
var validPin = [], invalidPin = [];
for(var x = 0; x < 41 ; x++){
try{
rpi.gpio_open(x, 0);
validPin.push(x);
}
catch(e){
invalidPin.push(x);
}
}
console.log('GPIO valid pins', validPin);
console.log('GPIO invalid pins', invalidPin);
// w/o new e.g let pwm = r.PWM(12)
PWM(pin, freq, T, pw) {
return new spi(pin, freq, T, pw);
}
/* debug mode setup method for test */
debug(x){
if(x === 1){
debugState = true;
debugStateAdvanced = true;
}
return debugState;
startPWM(pin, freq, T, pw){
return new pwm(pin, freq, T, pw);
}
/********************************************
/*********
PWM Methods
I2C
********************************************/
setPWM(pin, freq, T, pw){
if(arguments.length > 4 || arguments.length < 1){
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);
}
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');
}
}
}
else{
throw new Error('invalid setPulse() pin argument');
}
*********/
// classic api
// e.g let i2c = new r.I2C()
// i2c.begin()
I2C = i2c;
if(arguments[1] === 10 || arguments[1] === 100 || arguments[1] === 1000 ){
var validFreq = freq;
}
else if(arguments[1] === undefined){
var validFreq = 1;
}
else{
throw new Error('invalid setPulse() freq argument');
}
/* T or range */
if(arguments[2] > 0 || arguments[2] < 1000000 ){
var validT = T;
}
else if(arguments[2] === undefined){
var validT = 0;
}
else{
throw new Error('invalid setPulse() period T argument');
}
/* pw or data */
if(arguments[3] > 0 || arguments[3] < 1000000 ){
var validPW = pw;
}
else if( arguments[3] === undefined){
var validPW = 0;
}
else{
throw new Error('invalid setPulse() pw argument');
}
/* create pwm object using validated arguments */
var pwm = new PWM(validPin, validFreq, validT, validPW);
/* track Freq from pwm.js */
var Freq = require('./pwm.js').Freq;
/* PWM setup reference console output */
if(Freq === 10){
var res = '0.1 ms';
}
else if(Freq === 100){
var res = '0.01 ms';
}
else if(Freq === 1000){
var res = '0.001 ms';
}
if(validFreq === 1){
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);
}
/* get the pwmObject from pwm.js */
pwmObject = require('./pwm.js').pwmObject;
/* check for more than 1 peripheral and channel pairs */
setImmediate(function(){
pwmObjectTotal += 1;
if(pwmObject === pwmObjectTotal && pwmObject > 1){
console.log("\nArray-gpio has detected you are using more than 1 PWM peripheral."
+ "\nAll PWM peripherals are using 1 clock oscillator.\nClock frequency is set to " + Freq + " KHz for all.\n");
}
/* pwm pin channel check */
setImmediate(function(){
/* channel 1 */
if(pwmPin.c1.length > 1 && pwmObject > 1){
if(pwmPin.c1[1] === validPin){
console.log("Paired PWM peripherals (pin " + pwmPin.c1 + ") detected.");
console.log("Range and data will be same for both peripherals.\n");
}
}
/* channel 2 */
if(pwmPin.c2.length > 1 && pwmObject > 1){
if(pwmPin.c2[1] === validPin){
console.log("Paired PWM peripherals (pin " + pwmPin.c2 + ") detected.");
console.log("Range and data will be same for both peripherals.\n");
}
}
});
});
return pwm;
// w/o new e.g let i2c = r.I2C(pin_select)
I2C(pin_select) {
return new i2c(pin_select);
}
PWM(pin, freq, T, pw){
return this.setPWM(pin, freq, T, pw);
startI2C(pin_select) {
return new i2c(1);
}
startPWM(pin, freq, T, pw){
return this.setPWM(pin, freq, T, pw);
createI2C(pinSet) {
return new I2C(1);
}
/********************************************
/*********
I2C Methods
SPI
********************************************/
I2C(pin) {
return new I2C(pin);
}
*********/
// classic api
// e.g let spi = new r.SPI()
// spi.begin()
SPI = spi;
setI2C(pin) {
return new I2C(pin);
}
startI2C(pinSet) {
return new I2C(pinSet);
}
/********************************************
SPI Methods
********************************************/
// w/o new e.g let spi = r.I2C()
SPI() {
var spi = new SPI();
return spi;
return new spi();
}
setSPI() {
var spi = new SPI();
return spi;
return new spi();
}
startSPI() {
var spi = new SPI();
return spi;
return new spi(1);
}
/********************************************
Other Helper Methods
********************************************/
/* mswait (millisecond) method */
mswait (ms)
{
rpi.mswait(ms);
createSPI() {
return new spi(1);
}
/* uswait (microsecond) method */
uswait (us)
{
rpi.uswait(us);
}
pinout = rpi.pinout;
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('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');
}
} // end of ArrayGpio class
module.exports = new ArrayGpio();
module.exports = new ArrayGpio;

@@ -12,87 +12,160 @@ /*!

//var watchData = [];
const watchPinEvent = [];
/*
* Gpio input class module
*/
class GpioInput {
constructor(i, pin, o ){
this._index = i;
this.pin = pin;
#pin = 0;
#index = 0;
if(o.intR === 'pu' || o.intR === 'pd' || o.intR === 1 || o.intR === 0){
/* istanbul ignore next */
this.intR(o.intR);
}
else{
this.intR(null);
}
this.setR = this.intR;
#open(pin) {
rpi.gpio_open(pin, 0);
}
open () {
rpi.gpio_open(this.pin, 0);
constructor(pin, i, o){
this.#pin = pin;
this.#index = i;
this.#open(pin);
if(o.pud === 0 || o.pud === 1 || o.pud === 'pd' || o.pud === 'pu'){
this.setPud(o.pud);
}
}
close () {
rpi.gpio_close(this.pin);
close() {
rpi.gpio_close(this.#pin);
}
get pin(){
return this.#pin;
}
get state(){
let state = rpi.gpio_read(this.pin);
if(state === 1){
return true;
}
else{
return false;
}
let state = rpi.gpio_read(this.#pin);
if(state === 1){
return true;
}
else if(state === 0){
return false;
}
}
get isOn(){
return this.state;
return this.state;
}
get isOff(){
return !this.state;
return !this.state;
}
intR (x) {
if(x === null || x === undefined) {
return rpi.gpio_enable_pud(this.pin, 0);
}
else if(x === 'pu' || x == 1) {
return rpi.gpio_enable_pud(this.pin, 2);
}
else if(x === 'pd' || x === 0) {
return rpi.gpio_enable_pud(this.pin, 1);
}
read(cb){
let s = rpi.gpio_read(this.#pin);
if(cb){
return setImmediate(cb, s);
}
return s;
}
read(cb){
let s = rpi.gpio_read(this.pin);
// rpi 4 only
getPud(){
let pud = rpi.gpio_get_pud(this.#pin);
if(pud === 0){ // no pull resistor
return null;
}
else if(pud === 1){ // pull-up
return 1;
}
else if(pud === 2){ // pull-down
return 0;
}
else{
return 'n/a'; // not available
}
}
if(arguments.length === 0){
return s;
}
else if(arguments.length === 1 && typeof arguments[0] === 'function'){
return setImmediate(cb, s);
}
else {
throw new Error('invalid callback argument');
}
setPud(pud){
if(pud === null || pud === undefined ) {
rpi.gpio_set_pud(this.#pin, 0); // no pull resistor
}
else if(pud === 0 || pud === 'pd') {
rpi.gpio_set_pud(this.#pin, 1); // pull-down
}
else if(pud == 1 || pud === 'pu') {
rpi.gpio_set_pud(this.#pin, 2); // pull-up
}
else{
throw new Error('Invalid pull resistor select');
}
}
watch(edge, cb, td){
let pin = this.pin;
rpi.gpio_watchPin(edge, cb, pin, td);
watchPin(edge, cb, td){
const pin = this.#pin;
let on = false;
if(typeof edge === 'function' && typeof cb === 'number'){
td = cb;
cb = edge;
edge = null;
}
else if(typeof edge === 'function' && cb === undefined){
cb = edge;
edge = null;
}
else if(typeof edge !== 'string' && typeof edge !== 'number' && edge !== null ){
console.log('invalid input watch edge argument');
process.exit(1);
}
else if ((typeof edge === 'string' || typeof edge === 'number') && typeof cb !== 'function'){
console.log('invalid input watch callback argument');
process.exit(1);
}
const watch_pin_state = () => {
let pin_state = rpi.gpio_read(pin);
if(pin_state && !on){
on = true;
if(edge === 1 || edge === 're' || edge === 'both' || edge === null ){
setImmediate(cb, true, pin);
}
}
else if(!pin_state && on){
on = false;
if(edge === 0 || edge === 'fe' || edge == 'both' || edge === null){
setImmediate(cb, false, pin);
}
}
}
if(!td){
td = 100;
}
let monInt = setInterval(watch_pin_state, td);
watchPinEvent.push({monInt:monInt, pin:pin});
}
unwatch(){
let pin = this.pin;
rpi.gpio_unwatchPin(pin);
unwatchPin(){
const pin = this.#pin;
watchPinEvent.forEach((monData, x) => {
if(monData.pin === pin){
clearInterval(monData.monInt);
if(monData.monInt._destroyed){
try{
watchPinEvent.splice(x, 1);
}
catch(e){
console.log('gpio_unwatch error:', e);
}
}
}
});
}
} // end of GpioInput class
setR = this.setPud; // for compatibility with old versions 4/25/25
watch = this.watchPin;
unwatch = this.unwatchPin;
}
module.exports = GpioInput;

@@ -99,0 +172,0 @@

@@ -12,29 +12,12 @@ /*!

/* OnOff helper function */
function OnOff(pin, c, t, cb){
let state;
if(c === 1 || c === true){
rpi.gpio_write(pin, 1); // returns 1
state = true;
if(t === 'w'){
state = 1;
}
}
else{ // c === 0 || c === false
rpi.gpio_write(pin, 0); // returns 0
state = false;
if(t === 'w'){
state = 0;
}
}
function OnOff(pin, c, cb){
if(cb){
setImmediate(cb, state);
setImmediate(cb, c);
}
return state;
return rpi.gpio_write(pin, c);
}
/* pulse helper function */
function startPulse(pin, c, t, cb){
rpi.gpio_write(pin, 1);
setTimeout( function() {
setTimeout(() => {
rpi.gpio_write(pin, 0);

@@ -47,65 +30,50 @@ if(cb){

/* internal gpio control function */
function OutputPinControl(pin, c, t, cb) {
// pulse
if(c === null && t){
return startPulse(pin, c, t, cb);
}
// on/off control
else if(t){
return setTimeout( function() {
OnOff(pin, c, t, cb);
return setTimeout(() => {
OnOff(pin, c, cb);
}, t);
}
else{
return OnOff(pin, c, t, cb);
return OnOff(pin, c, cb);
}
}
/*
* Gpio output class module
*/
class GpioOutput {
constructor(i, pin, o ){
this._index = i;
this.pin = pin;
this.stop = 0;
this.start = 0;
this.pulseRef = null;
this.pulseStarted = false;
#pin = 0;
#index = 0;
this.loopStop = 0;
this.loopStart = 0;
this.loopRef = null;
this.loopStarted = false;
this.delayOn = this.on;
this.delayOff = this.off;
//this.pulse = this.startPulse;
//this.loop = this.processLoop;
#open(pin){
rpi.gpio_open(pin, 1);
}
open(){
rpi.gpio_open(this.pin, 1);
return this.state;
constructor(pin, i, o ){
this.#pin = pin;
this.#index = i;
this.#open(pin);
}
close(){
rpi.gpio_close(this.pin);
rpi.gpio_close(this.#pin);
return this.state;
}
get pin(){
return this.#pin;
}
get state(){
let state = rpi.gpio_read(this.pin);
let state = rpi.gpio_read(this.#pin);
if(state === 1){
return true;
return true;
}
else{
return false;
}
else if(state === 0){
return false;
}
}
get isOn(){

@@ -120,21 +88,16 @@ return this.state;

read(cb){
let s = rpi.gpio_read(this.pin);
if(arguments.length === 0){
return s;
}
else if(arguments.length === 1 && typeof arguments[0] === 'function'){
let s = rpi.gpio_read(this.#pin);
if(cb){
return setImmediate(cb, s);
}
else {
throw new Error('invalid callback argument');
}
return s
}
write (bit, cb){
write(bit, cb){
if(arguments.length === 0){
throw new Error('missing control bit argument');
}
throw new Error('missing control bit argument');
}
else if(arguments.length === 1){
if((typeof arguments[0] === 'number' && arguments[0] < 2 ) || typeof arguments[0] === 'boolean'){
return OutputPinControl(this.pin, bit, 'w', null);
return OutputPinControl(this.#pin, bit, null, null);
}

@@ -145,3 +108,3 @@ throw new Error('invalid control bit argument');

if((typeof arguments[0] === 'number' || typeof arguments[0] === 'boolean') && arguments[1] instanceof Function){
return OutputPinControl(this.pin, bit, 'w', cb);
return OutputPinControl(this.#pin, bit, null, cb);
}

@@ -154,10 +117,10 @@ throw new Error('invalid argument');

if(arguments.length === 0){
return OutputPinControl(this.pin, 1, 0, null);
return OutputPinControl(this.#pin, 1, 0, null);
}
else if(arguments.length === 1){
if(typeof arguments[0] === 'number' || arguments[0] === undefined){
return OutputPinControl(this.pin, 1, t, null);
return OutputPinControl(this.#pin, 1, t, null);
}
if(arguments[0] instanceof Function){
return OutputPinControl(this.pin, 1, t, arguments[0]);
return OutputPinControl(this.#pin, 1, t, arguments[0]);
}

@@ -168,3 +131,3 @@ throw new Error('invalid argument');

if(typeof arguments[0] === 'number' && arguments[1] instanceof Function){
return OutputPinControl(this.pin, 1, t, cb);
return OutputPinControl(this.#pin, 1, t, cb);
}

@@ -183,10 +146,10 @@ if(typeof arguments[0] !== 'number' && arguments[1] instanceof Function){

if(arguments.length === 0){
return OutputPinControl(this.pin, 0, 0, null);
}
else if(arguments.length === 1){
return OutputPinControl(this.#pin, 0, 0, null);
}
else if(arguments.length === 1){
if(typeof arguments[0] === 'number' || arguments[0] === undefined){
return OutputPinControl(this.pin, 0, t, null);
return OutputPinControl(this.#pin, 0, t, null);
}
if(arguments[0] instanceof Function){
return OutputPinControl(this.pin, 0, t, arguments[0]);
return OutputPinControl(this.#pin, 0, t, arguments[0]);
}

@@ -197,3 +160,3 @@ throw new Error('invalid argument');

if(typeof arguments[0] === 'number' && arguments[1] instanceof Function){
return OutputPinControl(this.pin, 0, t, cb);
return OutputPinControl(this.#pin, 0, t, cb);
}

@@ -212,24 +175,24 @@ if(typeof arguments[0] !== 'number' && arguments[1] instanceof Function){

pulse(t, cb){
let pwError = 'invalid pulse width time duration';
let error = 'pulse - invalid pulse width time duration';
this.on();
if(arguments.length === 0){
throw new Error(pwError);
throw new Error(error);
}
else if(arguments.length === 1){
if(typeof arguments[0] === 'number'){
return OutputPinControl(this.pin, null, t, null);
return OutputPinControl(this.#pin, null, t, null);
}
throw new Error(pwError);
throw new Error(error);
}
else {
if(typeof arguments[0] === 'number' && arguments[1] instanceof Function){
return OutputPinControl(this.pin, null, t, cb);
return OutputPinControl(this.#pin, null, t, cb);
}
if(typeof arguments[0] !== 'number' && arguments[1] instanceof Function){
throw new Error(pwError);
throw new Error(error);
}
if(typeof arguments[0] === 'number' && !(arguments[1] instanceof Function)){
throw new Error('invalid callback argument');
throw new Error('pulse - invalid callback argument');
}
throw new Error('invalid arguments');
throw new Error('pulse - invalid arguments');
}

@@ -239,3 +202,2 @@ }

}
// end of class GpioOutput

@@ -242,0 +204,0 @@ module.exports = GpioOutput;

@@ -12,64 +12,61 @@ /*!

var test = false;
// 0 - SDA0 (GPIO 00/pin 27) and SCL0 (GPIO 01/pin 28) (disabled)
// 1 - BSC1_BASE, using SDA1 (GPIO 02/pin 03) and SCL1 (GPIO 03/pin 05) (default)
/*
* i2c class
*/
class I2C {
/*constructor (){
this.begin();
}*/
constructor (pinSet){
/*if(!pinSet){
this.startI2C(1);
}*/
if(pinSet === undefined){
this.startI2C(1);
#init = 0;
#start(ps){
this.#init = 1;
if(ps === undefined){
rpi.i2c_start(1);
}
else{
this.startI2C(pinSet);
else if(ps === 0 || ps === 1){
rpi.i2c_start(ps);
}
else{
throw new Error('Invalid i2c pin select ' + ps);
}
}
begin(){
return rpi.i2cBegin();
constructor(ps){
if(ps == undefined){
// start manually using begin
this.#init = 0;
}
else{
this.#init = 1;
this.#start(ps)
}
}
startI2C(pinSet){
return rpi.i2cInit(pinSet);
}
test(){
test = true;
begin(){
this.#init = 1;
rpi.i2c_start(1);
}
setBaudRate(baud) {
if(test){
return;
}
rpi.i2cSetBaudRate(baud);
var Baud = baud/1000;
console.log('I2C data rate: ' + Baud + ' kHz');
if(this.#init){
rpi.i2c_set_baud_rate(baud);
let Baud = baud/1000;
console.log('I2C data rate: ' + Baud + ' kHz');
}
}
setTransferSpeed(baud) {
if(test){
return;
}
rpi.i2cSetBaudRate(baud);
var Baud = baud/1000;
console.log('I2C data rate: ' + Baud + ' kHz');
if(this.#init){
rpi.i2c_set_baud_rate(baud);
let Baud = baud/1000;
console.log('I2C data rate: ' + Baud + ' kHz');
}
}
setClockFreq(div) {
var freq = Math.round(250000000/div);
var Freq = Math.round(freq/1000);
console.log('I2C data rate: ' + Freq + ' kHz (div ' + div +')');
if(test){
return;
}
rpi.i2cSetClockDivider(div);
if(this.#init){
let freq = Math.round(250000000/div);
let Freq = Math.round(freq/1000);
console.log('I2C data rate: ' + Freq + ' kHz (div ' + div +')');
rpi.i2c_set_clock_divider(div);
}
}

@@ -79,6 +76,5 @@

setSlaveAddress(value){
if(test){
return;
}
return rpi.i2cSetSlaveAddress(value);
if(this.#init){
return rpi.i2c_set_slave_address(value);
}
}

@@ -88,6 +84,5 @@

selectSlave(value){
if(test){
return;
if(this.#init){
return rpi.i2c_set_slave_address(value);
}
return rpi.i2cSetSlaveAddress(value);
}

@@ -97,6 +92,5 @@

read(buf, len){
if(test){
return;
if(this.#init){
rpi.i2c_read(buf, len);
}
rpi.i2cRead(buf, len);
}

@@ -106,14 +100,23 @@

write(buf, len){
if(test){
return;
if(this.#init){
rpi.i2c_write(buf, len);
}
rpi.i2cWrite(buf, len);
}
end(){
rpi.i2cEnd();
if(this.#init){
rpi.i2c_stop();
this.#init = 0;
}
}
} // end of I2C class
stop(){
if(this.#init){
rpi.i2c_stop();
this.#init = 0;
}
}
}
module.exports = I2C;
+193
-84

@@ -12,55 +12,171 @@ /*!

var Freq = 1, pwmObject = 0;
var pwm_instance = 0;
var pwmPin = {c1:[], c2:[]};
var freqF = 1, validT = 0, validPW = 0, validPin = 0, validFreqF = 0;
class PWM {
constructor(pin, freq, T, pw){
/* track pwm object */
pwmObject += 1;
exports.pwmObject = pwmObject;
#T = 0;
#pw = 0;
#pin = 0;
#pwmStarted = false;
#pinOnlySetup = false;
this._T = T;
this._pw = pw;
this._pin = pin;
this._freq = freq;
this._pinOnlySetup = false;
#validate_pwm_params(pin, freq, T, pw){
++pwm_instance;
if(pin === 33 || pin === 35 || pin === 12 || pin === 32){
validPin = pin;
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');
}
}
}
else{
throw new Error('invalid pwm pin');
}
// Get frequecy factor (freq)
if(freq === undefined){
validFreqF = 1;
}
else if(freq === 10 || freq === 100 || freq === 1000 ){
validFreqF = freq;
}
else{
throw new Error('invalid pwm freq');
}
// T or range
if(T === undefined){
validT = 0;
}
else if(T > 0 || T < 1000000 ){
validT = T;
}
else{
throw new Error('invalid pwm period T');
}
// pw or data
if(pw === undefined){
validPW = 0;
}
else if(pw > 0 || pw < 1000000 ){
validPW = pw;
}
else{
throw new Error('invalid pwm data');
}
this.#T = validT;
this.#pw = validPW;
this.#pin = validPin;
if(freq === 1){
this._pinOnlySetup = true;
this.#pinOnlySetup = true;
}
/*
* initilize PWM
* servo control will use only mark/space (M/S) mode
*/
rpi.pwmInit();
/* Initilize PWM. Servo control will use only mark/space (M/S) mode. */
this.pwm_init();
this.enable(false);
this._pwmStarted = false;
this.#pwmStarted = false;
let div = null, res = null;
if( freq !== 1 && T !== 0 && pw !== 0){
if( pwmObject === 1){
/* 10kHz -> 0.1 ms */
if(freq === 10){
Freq = 10;
this.setClockFreq(1920);
}
/* 100KHz -> 0.01 ms */
else if(freq === 100){
Freq = 100;
this.setClockFreq(192);
}
/* 100KHz -> 0.001 ms */
else if(freq === 1000){
Freq = 1000;
this.setClockFreq(19);
}
// e.g. var pwm = r.startPWM(pin, freq, T, pw);
if(validFreqF > 1 && validT > 0 && validPW > 0){
// 10kHz -> 0.1 ms
if(freq === 10){
freqF = 10;
div = 1920
this.setClockFreq(div);
}
this.setRange(this._T);
this.setData(this._pw);
// 100KHz -> 0.01 ms
else if(freq === 100){
freqF = 100;
div = 192
this.setClockFreq(div);
}
// 100KHz -> 0.001 ms
else if(freq === 1000){
freqF = 1000;
div = 19
this.setClockFreq(div);
}
let freqC = (Math.round(19200000/div))/1000;
if(freqF === 10){
res = '0.1 ms';
}
else if(freqF === 100){
res = '0.01 ms';
}
else if(freqF === 1000){
res = '0.001 ms';
}
/* freqF is freq factor and not validFreqF, pwm is using one freq for all pins */
console.log('PWM config: pin ' + validPin + ', freq ' + freqC + ' KHz (' + res + '), T ' + validT + ', pw ' + validPW);
this.setRange(this.#T);
this.setData(this.#pw);
}
else if(validFreqF === 1){ // e.g var pwm = r.startPWM(12);
console.log('PWM config: (pin ' + validPin + ')');
this.#pinOnlySetup = true;
// Note: setClockFreq(), setRange() and setData() must be set manually
}
/* Check for more than 1 peripheral used and channel pairs */
if(pwm_instance > 1){
console.log("\nArray-gpio has detected you are using more than 1 PWM peripheral."
+ "\nClock frequency is set to " + freqF + " KHz for all.\n");
}
/* channel 1 */
if(pwmPin.c1.length > 1 && pwm_instance > 1){
if(pwmPin.c1[1] === validPin){
console.log("Paired PWM peripherals (pin " + pwmPin.c1 + ") detected.");
console.log("Range and data will be same for both peripherals.\n");
}
}
/* channel 2 */
if(pwmPin.c2.length > 1 && pwm_instance > 1){
if(pwmPin.c2[1] === validPin){
console.log("Paired PWM peripherals (pin " + pwmPin.c2 + ") detected.");
console.log("Range and data will be same for both peripherals.\n");
}
}
}
constructor(pin, freq, T, pw){
this.#validate_pwm_params(pin, freq, T, pw);
}
pwm_init(){
rpi.pwm_init();
}
/* initialize PWM object */
enable (start){
rpi.pwmSetup(this._pin, start);
rpi.pwm_setup(this.#pin, start);
}

@@ -71,46 +187,37 @@

if(div > 0 && div < 4095 ){
rpi.pwmSetClockDivider(div);
var freq = Math.round(19200000/div);
Freq = freq/1000;
if(pwmObject === 1){
setImmediate(function(){
console.log('Frequency calculation (div ' + div +'): ' + Freq + ' KHz');
});
rpi.pwm_set_clock_divider(div);
let freqC = (Math.round(19200000/div))/1000; // calculated freq
if(pwm_instance === 1){
console.log('Frequency calculated using (div ' + div +'): ' + freqC + ' KHz');
}
exports.Freq = Freq;
}
else{
throw new Error('setClock() error: invalid div value');
throw new Error('setClockFreq error: invalid div value ' + div);
}
}
/*
* set period T or space value from m/s mode
*/
/* set period T or space value from m/s mode */
setRange (range){
// console.log('this. _pin ' + this._pin + ' this._T ' + this._T + ' range ' + range + ' this._pw ' + this._pw );
this._T = range;
rpi.pwmSetRange(this._pin, range);
this.#T = range;
rpi.pwm_set_range(this.#pin, range);
}
/*
* set pw(pulse width) over period T or mark value over space
*/
/* set pw(pulse width) over period T or mark value over space */
setData (data){
this._pw = data;
this.#pw = data;
this.enable(true);
/* validate pw vs range */
if(Freq === 10 || Freq === 100 || Freq === 1000 || Freq === 1){
if(this._T === 0 ){
console.log('Alert! pin ' + this._pin + ' period T or range is zero.');
if(freqF === 1 || freqF === 10 || freqF === 100 || freqF === 1000){
if(this.#T === 0 ){
console.log('WARNING! pwm pin', this.#pin, 'period T or range is', 0);
console.log('Please set a range first using the setRange(range) method');
}
if(data > 0 && data <= this._T){
rpi.pwmSetData(this._pin, data);
else if(data > 0 && data <= this.#T){
rpi.pwm_set_data(this.#pin, data);
}
if(data > this._T){
console.log('Alert! pin ' + this._pin + ', pw ' + data + ' is higher than the period T ' + this._T );
rpi.pwmSetData(this._pin, data);
else if(data > this.#T){
console.log('WARNING! pwm pin', this.#pin, ' pw ' + data + ' is higher than the period T', this.#T );
rpi.pwm_set_data(this.#pin, data);
}

@@ -121,6 +228,6 @@ }

start (){
if(this._pw === 1){
this._pw = this._T;
if(this.#pw === 1){
this.#pw = this.#T;
}
rpi.pwmSetData(this._pin, this._pw);
rpi.pwm_set_data(this.#pin, this.#pw);
}

@@ -130,15 +237,17 @@

this.enable(false);
this._pwmStarted = false;
this.#pwmStarted = false;
}
pulse (pw){
if(!this._pwmStarted){
if(!this.#pwmStarted){
this.enable(true);
}
this._pwmStarted = true;
this.#pwmStarted = true;
if(pw === undefined){
this.setData(this._pw);
this.setData(this.#pw);
}
else {
rpi.pwmSetData(this._pin, pw);
rpi.pwm_set_data(this.#pin, pw);
}

@@ -149,19 +258,19 @@ }

this.enable(false);
this._pwmStarted = false;
this.#pwmStarted = false;
}
close (){
this._pwmStarted = false;
this.#pwmStarted = false;
/* reset to 19.2MHz */
//rpi.pwmSetClockDivider(1);
rpi.pwmSetup(this._pin, false);
rpi.pwmSetRange(this._pin, 0);
rpi.pwmSetData(this._pin, 0);
rpi.pwmReset();
//rpi.pwmResetPin(this._pin);
//rpi.pwm_set_clock_divider(1);
rpi.pwm_setup(this.#pin, false);
rpi.pwm_set_range(this.#pin, 0);
rpi.pwm_set_data(this.#pin, 0);
rpi.pwm_reset();
//rpi.pwm_reset_pin(this.#pin);
}
} // end of PWM class
}
module.exports = PWM;
+338
-383

@@ -10,124 +10,149 @@ /*!

const fs = require('fs');
const os = require('os');
const fs = require('node:fs');
const { arch } = require('node:process');
const cc = require('bindings')('node_rpi');
const EventEmitter = require('events');
class StateEmitter extends EventEmitter {}
const emitter = exports.emitter = new StateEmitter();
emitter.setMaxListeners(2);
var rpi_board_rev = null, rpi_model = null, eventStarted = null, BcmPin = [];
var rpiInit = { initialized:false, gpio:false, pwm:false , i2c:false , spi:false, gpiomem:false, devmem:false };
var match;
var BoardRev;
var BcmPin = {};
var inputPin = [];
var outputPin = [];
var watchData = [];
var eventStarted = null;
var rpiSetup = { initialized:false, gpiomem:false, initI2c:false , initSpi:false };
/*
* Verify if the board is a Raspberry Pi
*/
if(os.arch() === 'arm' || os.arch() === 'arm64'){
//continue
if(arch === 'arm' || arch === 'arm64'){
// continue
}
else{
console.log('Sorry, array-gpio has detected that your device is not a Raspberry Pi.\narray-gpio will only work in Raspberry Pi devices.\n');
throw new Error('device is not a raspberry pi');
throw new Error('Device is not a raspberry pi');
}
/*
* Check rpi board revision.
*/
/*fs.readFile('/proc/cpuinfo', function (err, info) {
if (err) throw err;
if (!info){
return false;
function get_rpi_model(){
let model = null, match = null;
try{
let info = fs.readFileSync('/proc/cpuinfo');
info.toString().split(/\n/).forEach((line) => {
model = line.match(/^Model.*(.{4})/);
if(model){
//rpi_model = model[0].slice(8, 30); // e.g. Raspberry Pi 4 Model
rpi_model = model[0].slice(18, 24).trim(); // e.g. Pi 4
}
match = line.match(/^Revision.*(.{4})/);
if(match) {
rpi_board_rev = parseInt(match[1], 16);
}
});
}
info.toString().split(/\n/).forEach(function (line) {
match = line.match(/^Revision.*(.{4})/);
if (match) {
return BoardRev = parseInt(match[1], 16);
}
});
//console.log('BoardRev', BoardRev.toString(16));
switch (BoardRev) {
case 0x10:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x32:
case 0x92:
case 0x93:
case 0xc1:
case 0x1041:
case 0x2042:
case 0x2082:
case 0x20d3:
case 0x20a0:
case 0x20e0:
break;
default:
console.log('\nSorry, your raspberry pi model is not currently supported at this time.\n');
throw new Error('unsupported rpi board');
return false;
catch(e){
console.log("fs.readFileSync('/proc/cpuinfo')", e.message);
}
return true;
});*/
}
get_rpi_model();
/*
* This module only supports 40-pin Raspberry Pi Models.
* 40-pin Physical Board Pinout Mapping with BCM GPIOxx Pin Numbering.
*
* Note: This module only supports 40-pin Raspberry Pi Models.
* Below is the BCM GPIOxx pin numbering to the physical board header (40-pins) pinout map.
* -1 indicates a power supply or a ground pin.
*/
var pinLayout = [
const rpi_pin_map = [
// BCM GPIOxx Physical Board Header (*ground or power supply)
-1,
-1, -1, /* P1 P2 */
2, -1, /* P3 P4 */
3, -1, /* P5 P6 */
4, 14, /* P7 P8 */
-1, 15, /* P9 P10 */
17, 18, /* P11 P12 */
27, -1, /* P13 P14 */
22, 23, /* P15 P16 */
-1, 24, /* P17 P18 */
10, -1, /* P19 P20 */
9, 25, /* P21 P22 */
11, 8, /* P23 P24 */
-1, 7, /* P25 P26 */
0, 1, /* P27 P28 */
5, -1, /* P29 P30 */
6, 12, /* P31 P32 */
13, -1, /* P33 P34 */
19, 16, /* P35 P36 */
26, 20, /* P37 P38 */
-1, 21 /* P39 P40 */
-1, -1, // *1 *2
2, -1, // 3 *4
3, -1, // 5 *6
4, 14, // 7 8
-1, 15, // *9 10
17, 18, // 11 12
27, -1, // 13 *14
22, 23, // 15 16
-1, 24, // *17 18
10, -1, // 19 *20
9, 25, // 21 22
11, 8, // 23 24
-1, 7, // *25 26
0, 1, // 27 28
5, -1, // 29 *30
6, 12, // 31 32
13, -1, // 33 *34
19, 16, // 35 36
26, 20, // 37 38
-1, 21 // *39 40
]
/* Convert physical board pinout number to BCM pin numbering */
function convertPin(pin)
// gound pins
const gnd = [6, 9, 14, 20, 25, 30, 34, 39];
// 3.3 V pins
const p3 = [1, 17];
// 5.0 V pins
const p5 = [2, 4];
function checkInvalidPin(pin){
if(gnd.includes(pin)) {
throw new Error('*Ground header pin ' + pin + '\n');
}
if(p3.includes(pin)) {
throw new Error('*3.3 power supply header pin ' + pin + '\n');
}
if(p5.includes(pin)) {
throw new Error('*5 power supply header pin ' + pin + '\n');
}
if(pin === 0 || pin < 0 || pin > 40){
throw new Error('*Out-of-range (1 ~ 40 only) header pin ' + pin + '\n');
}
}
/* Convert board header pin number to BCM (Broadcom) pin number */
function header_to_bcm(pin)
{
if (BcmPin[pin]) {
return BcmPin[pin];
}
if (pinLayout[pin] === -1 || pinLayout[pin] === null){
throw new Error(pin, 'is invalid!');
}
BcmPin[pin] = pinLayout[pin];
return BcmPin[pin];
try{
if(BcmPin[pin]) {
return BcmPin[pin];
}
checkInvalidPin(pin);
if (rpi_pin_map[pin] === -1){
throw new Error('Power supply or gound header pin ' + pin + '\n');
}
BcmPin[pin] = rpi_pin_map[pin];
return BcmPin[pin];
}
catch(e){
console.log('Invalid pin', pin);
console.log(e.message);
process.exit(1);
}
}
function validate_pins(pin){
let currentPin = null;
try{
if(pin[0] === undefined){
currentPin = pin[0];
throw new Error('*Cannot set input/output gpio w/o pecified pins\n');
}
if(typeof pin[0] === 'object'){
currentPin = pin[0];
if(!pin[0].pin || pin[0].pin[0] == undefined){
throw new Error('*createGpio - pin property is empty!\n')
}
pin = pin[0].pin;
}
pin.forEach((_pin, x) => {
currentPin = _pin;
checkInvalidPin(_pin);
});
}
catch(e){
console.log('\nInvalid pin', currentPin);
console.log(e.message);
process.exit(1);
}
}
/* Check if the pin is being used by another application using '/sys/class/gpio/gpio' */
function check_sys_gpio(gpioPin, pin)
function check_sys_gpio(bcm_pin, pin)
{
fs.stat('/sys/class/gpio/gpio' + gpioPin, (err, stats) => {
fs.stat('/sys/class/gpio/gpio' + bcm_pin, (err, stats) => {
if(err) {
if(err.code === 'ENOENT'){
// '/sys/class/gpio/gpio' + gpioPin file does not exist
// '/sys/class/gpio/gpio' + bcm_pin file does not exist
return;

@@ -146,7 +171,19 @@ }

/* error message for rpi mode conflict */
function rpiModeConflict(){
console.log('\n** Peripheral access conflict.');
console.log('** I2C, SPI and PWM object creation takes precedence over GPIO object creation.');
console.log('** Try creating I2C/SPI/PWM objects before creating GPIO input/output objects.\n');
function pinout(){
console.log('Common Board Header Physical Pinout Numbers');
let uart = {txd:8, rxd:10};
let i2c = {sda1:3, scl1:5, sda0:27, scl0:28};
let pwm = {pwm0:[12,32], pwm1:[33,35]};
let spi = {mosi:19, miso:21, sclk:23, cs0:24, cs1:26};
let eprom = {sda:27, scl:28};
let gpio = [3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,27,28,29,31,32,33,35,36,37,38,40];
console.log('3.3v', p3);
console.log('5v', p5);
console.log('ground', gnd);
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');
}

@@ -159,6 +196,13 @@

* Incorrect use of this functions may cause hang-up/file corruptions
*
* Note: gpio is using 'dev/gpiomem' and i2c, spi, pwm is using 'dev/mem'
* 1 - Start gpio only, then load all other peripherals together (i2c, spi, pwm) on demand
* 0 - Start gpio first, then load each peripheral individually on demand (default)
*/
var clock1 = 250000000;
var clock2 = 400000000;
class Rpi {
constructor (){
constructor (init){
this.LOW = 0x0;

@@ -177,23 +221,19 @@ this.HIGH = 0x1;

this.BOTH = 0x3;
if(init === 1){
this.rpi_init_access = 1;
}
else if(init == 0){
this.rpi_init_access = 0;
}
}
/*
* rpi lib access methods
*/
lib_init (access)
/* Explicit initialization of rpi lib */
rpi_init (access)
{
/* reset pin store */
BcmPin = {};
cc.rpi_init(access);
if(access === 0){
rpiSetup.gpiomem = true; // rpi in dev/gpiomem for GPIO
}
else{
rpiSetup.gpiomem = false; // rpi in dev/mem for i2c, spi, pwm
}
rpiSetup.initialized = true; // rpi must be initialized only once
cc.rpi_init(access);
this.rpi_init_access = 1;
}
lib_close ()
rpi_close ()
{

@@ -208,50 +248,45 @@ return cc.rpi_close();

{
var gpioPin = convertPin(pin);
if (!rpiSetup.initialized) {
this.lib_init(0);
}
//console.log('open', pin)
let bcm_pin = header_to_bcm(pin);
check_sys_gpio(gpioPin, pin);
check_sys_gpio(bcm_pin, pin);
/* pin initial state */
cc.gpio_config(gpioPin, this.INPUT);
cc.gpio_enable_pud(gpioPin, this.PULL_OFF);
/* set as INPUT */
if(this.rpi_init_access){
if(!rpiInit.gpiomem){
rpiInit.gpiomem = true;
cc.rpi_init(0);
}
}
else{
if(!rpiInit.gpio){
rpiInit.gpio = true;
cc.gpio_init();
}
}
if(mode === this.INPUT){
var result = cc.gpio_config(gpioPin, this.INPUT);
let result = cc.gpio_config(bcm_pin, this.INPUT);
if(init){
cc.gpio_enable_pud(gpioPin, init);
cc.gpio_set_pud(bcm_pin, this.PULL_OFF);
if(init){
cc.gpio_set_pud(bcm_pin, init);
}
else{
cc.gpio_enable_pud(gpioPin, this.PULL_OFF); /* initial PUD setup, none */
}
// track all input pins
inputPin.push(pin);
// remove duplicates
inputPin = inputPin.filter(function(c, index){return inputPin.indexOf(c) === index});
return result;
}
/* set as OUTPUT */
else if(mode === this.OUTPUT){
var result = cc.gpio_config(gpioPin, this.OUTPUT);
let result = cc.gpio_config(bcm_pin, this.OUTPUT);
cc.gpio_write(bcm_pin, this.LOW);
if (init){
cc.gpio_write(gpioPin, init);
cc.gpio_write(bcm_pin, init);
}
else{
cc.gpio_write(gpioPin, this.LOW); /* initial state is OFF */
}
// track all output pins
outputPin.push(pin);
// remove duplicates
outputPin = outputPin.filter(function(c, index){return outputPin.indexOf(c) === index});
return result;
}
else {
throw new Error('Unsupported mode ' + mode);
console.log('Unsupported GPIO mode:', mode);
process.exit(1);
}

@@ -262,19 +297,9 @@ }

{
var gpioPin = convertPin(pin);
let bcm_pin = header_to_bcm(pin);
cc.gpio_config(bcm_pin, this.INPUT);
cc.gpio_set_pud(bcm_pin, this.PULL_OFF);
}
if (!rpiSetup.gpiomem){
cc.gpio_enable_pud(gpioPin, this.PULL_OFF);
}
/* reset pin to input */
cc.gpio_config(gpioPin, this.INPUT);
cc.gpio_enable_pud(gpioPin, this.PULL_OFF);
inputPin = inputPin.filter(function(item) {
return item !== pin;
});
outputPin = outputPin.filter(function(item) {
return item !== pin;
});
gpio_get_bcm(){
return BcmPin;
}

@@ -284,3 +309,4 @@

{
cc.gpio_enable_async_rising_event(convertPin(pin), 1);
let bcm_pin = header_to_bcm(pin);
cc.gpio_enable_async_rising_event(bcm_pin, 1);
}

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

{
return cc.gpio_detect_input_event(convertPin(pin));
let bcm_pin = header_to_bcm(pin);
return cc.gpio_detect_input_event(bcm_pin);
}

@@ -296,3 +323,4 @@

{
cc.gpio_reset_all_events(convertPin(pin));
let bcm_pin = header_to_bcm(pin);
cc.gpio_reset_all_events(bcm_pin);
}

@@ -302,3 +330,4 @@

{
cc.gpio_reset_event(convertPin(pin));
let bcm_pin = header_to_bcm(pin);
cc.gpio_reset_event(bcm_pin);
}

@@ -308,3 +337,4 @@

{
return cc.gpio_write(convertPin(pin), value);
let bcm_pin = header_to_bcm(pin);
return cc.gpio_write(bcm_pin, value);
}

@@ -314,128 +344,45 @@

{
return cc.gpio_read(convertPin(pin));
let bcm_pin = header_to_bcm(pin);
return cc.gpio_read(bcm_pin);
}
gpio_enable_pud (pin, value)
gpio_set_pud (pin, pud)
{
return cc.gpio_enable_pud(convertPin(pin), value);
let bcm_pin = header_to_bcm(pin);
cc.gpio_set_pud(bcm_pin, pud);
}
gpio_watchPin(edge, cb, pin, td){
/* check pin if valid */
if(cb){
try{
this.gpio_read(pin);
}
catch(e){
throw new Error('invalid pin');
}
}
let on = false;
if(typeof edge === 'function' && typeof cb === 'number'){
td = cb;
cb = edge;
edge = null;
}
else if(typeof edge === 'function' && cb === undefined){
cb = edge;
edge = null;
}
else if(typeof edge !== 'string' && typeof edge !== 'number' && edge !== null ){
throw new Error('invalid edge argument');
}
else if ((typeof edge === 'string' || typeof edge === 'number') && typeof cb !== 'function'){
throw new Error('invalid callback argument');
}
/* set internal pull-down resistor */
// conflict with pull-up resistor from Paulo Castro 1/14/2022
// need to validate with new RPI boards as well as with new RPI OS's
//cc.gpio_enable_pud(convertPin(pin), this.PULL_DOWN);
if(!td){
td = 100;
}
function logic () {
if(cc.gpio_read(convertPin(pin)) && !on){
on = true;
if(edge === 1 || edge === 're' || edge === 'both' || edge === null ){
setImmediate(cb, true, pin);
}
}
else if(!cc.gpio_read(convertPin(pin)) && on){
on = false;
if(edge === 0 || edge === 'fe' || edge == 'both' || edge === null){
setImmediate(cb, false, pin);
}
}
}
/*cc.gpio_reset_all_events(convertPin(pin));
cc.gpio_enable_async_rising_event(convertPin(pin), 1);
function logic () {
if(cc.gpio_detect_input_event(convertPin(pin)) && !on){
on = true;
if(edge === 1 || edge === 're' || edge === 'both' || edge === null ){
setImmediate(cb, true, pin);
}
cc.gpio_reset_event(convertPin(pin))
}
else if(!cc.gpio_detect_input_event(convertPin(pin)) && on){
on = false;
if(edge === 0 || edge === 'fe' || edge == 'both' || edge === null){
setImmediate(cb, false, pin);
}
cc.gpio_reset_event(convertPin(pin))
}
}*/
let monitor = setInterval(logic, td);
let monData = {monitor:monitor, pin:pin};
watchData.push(monData);
gpio_get_pud (pin)
{
let bcm_pin = header_to_bcm(pin);
return cc.gpio_get_pud(bcm_pin);
}
gpio_unwatchPin(pin){
watchData.forEach((monData, index) => {
if(monData.pin === pin){
clearInterval(monData.monitor);
watchData.splice(index,1);
}
});
}
/*
* PWM
*/
pwmInit ()
pwm_init()
{
/* check if GPIO is already using the rpi library in gpiomem */
if (rpiSetup.initialized && rpiSetup.gpiomem){
rpiModeConflict();
rpiSetup.gpiomem = false;
this.pwmReset();
throw new Error('pwm peripheral access conflict');
}
/* PWM peripheral requires /dev/mem */
if (!rpiSetup.initialized) {
this.lib_init(1);
if(this.rpi_init_access){
if(!rpiInit.devmem){
rpiInit.devmem = true;
cc.rpi_init(1);
}
}
else{
if(!rpiInit.pwm){
rpiInit.gpio = true;
rpiInit.pwm = true;
cc.pwm_init();
}
}
}
pwmResetPin (pin)
pwm_reset_pin (pin)
{
var gpioPin = convertPin(pin);
var v = outputPin.indexOf(gpioPin);
if(v === -1){
cc.pwm_reset_pin(gpioPin);
this.gpio_close(gpioPin);
}
let bcm_pin = header_to_bcm(pin);
cc.pwm_reset_pin(bcm_pin);
}
pwmReset ()
pwm_reset ()
{

@@ -446,3 +393,3 @@ cc.pwm_reset_all_pins();

/*
* available pins for PWM - RPi 3 / RPi 4
* Available pins for PWM - RPi 3 / RPi 4
* PHY pin BCM GPIO pin

@@ -454,7 +401,7 @@ * 12 18

*/
pwmSetup (pin, start, mode)
pwm_setup (pin, start, mode)
{
var gpioPin = convertPin(pin);
let bcm_pin = header_to_bcm(pin);
check_sys_gpio(gpioPin);
check_sys_gpio(bcm_pin);

@@ -469,9 +416,10 @@ /* true - enable pwm, false - disable */

}
//console.log('pin', pin, 'start', Number(start), 'mode', Number(mode));
cc.pwm_set_pin(gpioPin);
cc.pwm_set_mode(gpioPin, Number(mode));
cc.pwm_enable(gpioPin, Number(start));
cc.pwm_set_pin(bcm_pin);
cc.pwm_set_mode(bcm_pin, Number(mode));
cc.pwm_enable(bcm_pin, Number(start));
}
pwmSetClockDivider (divider)
pwm_set_clock_divider (divider)
{

@@ -481,10 +429,12 @@ return cc.pwm_set_clock_freq(divider);

pwmSetRange (pin, range)
pwm_set_range (pin, range)
{
return cc.pwm_set_range(convertPin(pin), range);
let bcm_pin = header_to_bcm(pin);
return cc.pwm_set_range(bcm_pin, range);
}
pwmSetData (pin, data)
pwm_set_data (pin, data)
{
return cc.pwm_set_data(convertPin(pin), data);
let bcm_pin = header_to_bcm(pin);
return cc.pwm_set_data(bcm_pin, data);
}

@@ -494,34 +444,20 @@

* I2C
*
* pinSet 0, use SDA0 and SCL0 pins (disabled)
* pinSet 1, use SDA1 and SCL1 pins (default)
*/
i2cBegin ()
i2c_start(pinSet)
{
if(rpiSetup.initialized && rpiSetup.gpiomem){
rpiModeConflict();
rpiSetup.gpiomem = false;
throw new Error('i2c peripheral access conflict');
}
/* I2C requires /dev/mem */
if (!rpiSetup.initialized){
this.lib_init(1);
rpiSetup.initI2c = true;
return cc.i2c_start();
}
}
i2cInit (pinSet)
{
if(rpiSetup.initialized && rpiSetup.gpiomem){
rpiModeConflict();
rpiSetup.gpiomem = false;
throw new Error('i2c peripheral access conflict');
}
/* I2C requires /dev/mem */
if (!rpiSetup.initialized){
rpiSetup.initI2c = true;
rpiSetup.initialized = true;
if(pinSet === 0){
return cc.i2c_init(0); // use SDA0 and SCL0 pins
if(this.rpi_init_access){
if(!rpiInit.devmem){
rpiInit.devmem = true;
cc.rpi_init(1);
cc.spi_start();
}
else if(pinSet === 1){
return cc.i2c_init(1); // use SDA1 and SCL1 pins
}
else{
if (!rpiInit.i2c){
rpiInit.gpio = true;
rpiInit.i2c = true;
cc.i2c_start(pinSet);
}

@@ -531,3 +467,3 @@ }

i2cSetSlaveAddress (addr)
i2c_set_slave_address (addr)
{

@@ -537,3 +473,3 @@ return cc.i2c_select_slave(addr);

i2cSetClockDivider (divider)
i2c_set_clock_divider (divider)
{

@@ -543,3 +479,3 @@ cc.i2c_set_clock_freq(divider);

i2cSetBaudRate (baud)
i2c_set_baud_rate (baud)
{

@@ -549,11 +485,16 @@ return cc.i2c_data_transfer_speed(baud);

i2cRead (buf, len)
i2c_read (buf, len)
{
if (len === undefined){
len = buf.length;
try{
if (len === undefined){
len = buf.length;
}
if (len > buf.length){
throw new Error('Insufficient buffer size');
}
return cc.i2c_read(buf, len);
}
catch(e){
console.log(e);
}
if (len > buf.length){
throw new Error('Insufficient buffer size');
}
return cc.i2c_read(buf, len);
}

@@ -566,14 +507,19 @@

i2cWrite (buf, len)
i2c_write (buf, len)
{
if (len === undefined){
len = buf.length;
try{
if (len === undefined){
len = buf.length;
}
if (len > buf.length){
throw new Error('Insufficient buffer size');
}
return cc.i2c_write(buf, len);
}
if (len > buf.length){
throw new Error('Insufficient buffer size');
catch(e){
console.log(e);
}
return cc.i2c_write(buf, len);
}
i2cEnd ()
i2c_stop ()
{

@@ -586,25 +532,26 @@ cc.i2c_stop();

*/
spiGetBoardRev ()
spi_get_board_rev ()
{
return BoardRev;
return { model:rpi_model, rev:rpi_board_rev.toString(16) };
}
spiBegin ()
spi_start()
{
if (rpiSetup.initialized && rpiSetup.gpiomem){
rpiModeConflict();
rpiSetup.gpiomem = false;
throw new Error('spi peripheral access conflict');
if(this.rpi_init_access){
if(!rpiInit.devmem){
rpiInit.devmem = true;
cc.rpi_init(1);
cc.spi_start();
}
}
/* SPI requires /dev/mem */
if (!rpiSetup.initialized) {
this.lib_init(1);
rpiSetup.initSpi = true;
return cc.spi_start();
else{
if (!rpiInit.spi){
rpiInit.gpio = true;
rpiInit.spi = true;
cc.spi_start();
}
}
}
spiChipSelect (cs)
spi_chip_select (cs)
{

@@ -614,3 +561,3 @@ cc.spi_chip_select(cs);

spiSetCSPolarity (cs, active)
spi_set_cs_polarity (cs, active)
{

@@ -620,11 +567,29 @@ cc.spi_set_chip_select_polarity(cs, active);

spiSetClockDivider (divider)
spi_set_clock_freq (div)
{
if ((divider % 2) !== 0 || divider < 0 || divider > 65536){
throw new Error('Clock divider must be an even number between 0 and 65536');
let freq = null;
try{
if ((div % 2) !== 0 || div < 0 || div > 65536){
throw new Error('Clock divider must be an even number between 0 and 65536');
}
if( rpi_model === 'Pi 3' || rpi_model === 'Pi 4'){
freq = Math.round(clock2/div);
}
else{
freq = Math.round(clock1/div);
}
let Freq = freq/1000;
console.log('SPI clock freq: ' + Freq + ' kHz (div ' + div +')');
cc.spi_set_clock_freq(div);
}
cc.spi_set_clock_freq(divider);
catch(e){
console.log(e);
}
}
spiSetDataMode (mode)
spi_set_data_mode (mode)
{

@@ -634,3 +599,3 @@ cc.spi_set_data_mode(mode);

spiTransfer (wbuf, rbuf, len)
spi_data_transfer (wbuf, rbuf, len)
{

@@ -640,3 +605,3 @@ cc.spi_data_transfer(wbuf, rbuf, len);

spiWrite (wbuf, len)
spi_write (wbuf, len)
{

@@ -646,3 +611,3 @@ cc.spi_write(wbuf, len);

spiRead (rbuf, len)
spi_read (rbuf, len)
{

@@ -652,3 +617,3 @@ cc.spi_read(rbuf, len);

spiEnd ()
spi_end ()
{

@@ -658,21 +623,11 @@ cc.spi_stop();

/*
* time delay methods
*/
// delay in milliseconds
mswait (ms)
{
cc.mswait(ms);
validatePins = validate_pins;
pinout = pinout;
}
// delay in microseconds
uswait (us)
{
cc.uswait(us);
}
}// end of Rpi class
module.exports = new Rpi(0);
module.exports = new Rpi();
process.on('exit', function (code) {
process.on('exit', (code) => {
cc.rpi_close();

@@ -679,0 +634,0 @@ });

@@ -12,77 +12,55 @@ /*!

/*
* spi class
*/
class SPI {
var test = false;
#init = 0;
class SPI {
#start(){
this.#init = 1;
rpi.spi_start();
}
constructor (){
this.begin();
constructor(s){
if(s === 1){
this.#init = 1;
this.#start();
}
else{
this.#init = 0;
}
}
/* returns 1 if successful, otherwise returns 0*/
begin(){
return rpi.spiBegin();
this.#init = 1;
rpi.spi_start();
}
test(){
test = true;
}
setDataMode (mode) {
rpi.spiSetDataMode(mode);
if(this.#init){
rpi.spi_set_data_mode(mode);
}
}
/* 250MHz on RPi1 and RPi2, and 400MHz on RPi3 */
setClockFreq(div) {
var clock1 = 250000000;
var clock3 = 400000000;
var boardRev = rpi.spiGetBoardRev();
if( boardRev === 8322){
var freq = Math.round(clock3/div);
}else{
var freq = Math.round(clock1/div);
if(this.#init){
rpi.spi_set_clock_freq(div);
}
var Freq = freq/1000;
console.log('SPI clock freq: ' + Freq + ' kHz (div ' + div +')');
rpi.spiSetClockDivider(div);
}
/* 250MHz on RPi1 and RPi2, and 400MHz on RPi3 */
setClock(div) {
var clock1 = 250000000;
var clock3 = 400000000;
var boardRev = rpi.spiGetBoardRev();
if( boardRev === 8322){
var freq = Math.round(clock3/div);
}
else{
var freq = Math.round(clock1/div);
}
var Freq = freq/1000;
console.log('SPI clock freq: ' + Freq + ' kHz (div ' + div +')');
rpi.spiSetClockDivider(div);
}
setCSPolarity(cs, active){
rpi.spiSetCSPolarity(cs, active);
if(this.#init){
rpi.spi_set_cs_polarity(cs, active);
}
}
chipSelect(cs){
rpi.spiChipSelect(cs);
if(this.#init){
rpi.spi_chip_select(cs);
}
}
/* transfer data bytes to/from periphetal registers using node buffer objects */
transfer (wbuf, rbuf, len){
if(test){
return;
}
rpi.spiTransfer(wbuf, rbuf, len);
dataTransfer (wbuf, rbuf, len){
if(this.#init){
rpi.spi_data_transfer(wbuf, rbuf, len);
}
}

@@ -92,6 +70,5 @@

write(wbuf, len){
if(test){
return;
}
rpi.spiWrite(wbuf, len);
if(this.#init){
rpi.spi_write(wbuf, len);
}
}

@@ -101,14 +78,16 @@

read(rbuf, len){
if(test){
return;
}
rpi.spiRead(rbuf, len);
if(this.#init){
rpi.spi_read(rbuf, len);
}
}
end(){
rpi.spiEnd();
if(this.#init){
rpi.spi_end();
this.#init = 0;
}
}
} // end of SPI class
}
module.exports = SPI;
{
"name": "array-gpio",
"version": "1.7.3",
"version": "1.7.4",
"description": "array-gpio is low-level javascript library for Raspberry Pi using direct register access.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -8,9 +8,5 @@ /**

#include <nan.h>
#include <unistd.h>
#include <errno.h>
#include "rpi.h"
#define LIBNAME node_bcm
#define BCM_EVENT_LOW 0x1
#define BCM_EVENT_HIGH 0x2

@@ -34,3 +30,3 @@ using namespace Nan;

/*
* rpi closing
* rpi close
*/

@@ -47,3 +43,3 @@ NAN_METHOD(rpi_close)

/*
* time delays
* Timers
*/

@@ -86,2 +82,8 @@ NAN_METHOD(nswait)

*/
NAN_METHOD(gpio_init)
{
gpio_init();
}
NAN_METHOD(gpio_config)

@@ -201,3 +203,3 @@ {

NAN_METHOD(gpio_enable_pud)
NAN_METHOD(gpio_set_pud)
{

@@ -211,8 +213,27 @@ if((info.Length() != 2) || (!info[0]->IsNumber()) || (!info[1]->IsNumber())){

gpio_enable_pud(arg1, arg2);
gpio_set_pud(arg1, arg2);
}
NAN_METHOD(gpio_get_pud)
{
uint8_t ret;
if((info.Length() != 1) || (!info[0]->IsNumber())){
return ThrowTypeError("Incorrect arguments");
}
uint8_t arg1 = info[0]->IntegerValue(Nan::GetCurrentContext()).ToChecked();
ret = gpio_get_pud(arg1);
info.GetReturnValue().Set(ret);
}
/*
* PWM
*/
NAN_METHOD(pwm_init)
{
pwm_init();
}
NAN_METHOD(pwm_set_pin)

@@ -334,13 +355,2 @@ {

{
uint8_t rval;
rval = i2c_start();
info.GetReturnValue().Set(rval);
}
NAN_METHOD(i2c_init)
{
uint8_t rval;
if((info.Length() != 1) || (!info[0]->IsNumber() )){

@@ -352,5 +362,3 @@ return ThrowTypeError("Incorrect argument");

rval = i2c_init(arg);
info.GetReturnValue().Set(rval);
i2c_start(arg);
}

@@ -397,3 +405,3 @@

{
uint8_t rval;
uint8_t rval;

@@ -442,7 +450,3 @@ if((info.Length() != 2) || (!info[0]->IsObject()) || (!info[1]->IsNumber())){

{
uint8_t rval;
rval = spi_start();
info.GetReturnValue().Set(rval);
spi_start();
}

@@ -547,2 +551,3 @@

/* gpio */
NAN_EXPORT(target, gpio_init);
NAN_EXPORT(target, gpio_config);

@@ -557,5 +562,7 @@ NAN_EXPORT(target, gpio_input);

NAN_EXPORT(target, gpio_write);
NAN_EXPORT(target, gpio_enable_pud);
NAN_EXPORT(target, gpio_set_pud);
NAN_EXPORT(target, gpio_get_pud);
/* pwm */
NAN_EXPORT(target, pwm_init);
NAN_EXPORT(target, pwm_set_pin);

@@ -574,3 +581,2 @@ NAN_EXPORT(target, pwm_reset_pin);

NAN_EXPORT(target, i2c_start);
NAN_EXPORT(target, i2c_init);
NAN_EXPORT(target, i2c_stop);

@@ -577,0 +583,0 @@ NAN_EXPORT(target, i2c_select_slave);

+605
-526

@@ -21,3 +21,2 @@ /**

#include <time.h>
//#include <bcm_host.h>

@@ -30,25 +29,18 @@ #include "rpi.h"

//#define debug 0
/* Peripherals base addresses for different Rpi models */
#define PERI_BASE_RPI1 0x20000000 // Rpi 1
#define PERI_BASE_RPI23 0x3F000000 // Rpi 2 & 3
#define PERI_BASE_RPI4 0xFE000000 // Rpi 4
#define PERI_BASE_1 0x20000000 // Rpi 1 & Rpi Zero/Rpi Zero W
#define PERI_BASE_2 0x3F000000 // Rpi 2 & 3
#define PERI_BASE_3 0xFE000000 // Rpi 4
/* Common core clock frequency for all RPI models */
#define CORE_CLK_FREQ 250000000 // 250 MHz
//#define CORE_CLK_FREQ 250000000 // 250 MHz
/* Dynamic CORE_CLOCK_FREQ for different models
* that can affect UART, SPI and I2C performance
*/
#define CORE_CLOCK_FREQ_RPI1 250000000 // 250 MHz
#define CORE_CLOCK_FREQ_RPI23 400000000 // 400 MHz
#define CORE_CLOCK_FREQ_RPI4 400000000 // 400 MHz
/* Base address of each peripheral registers
* with a dynamic peri_base offset value
*/
/* Base address of each peripheral registers based on the Rpi model */
#define ST_BASE (peri_base + 0x003000) // 0x7E003000
#define GPIO_PADS (peri_base + 0x100000) // 0x7E100000 unused
#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 SPI0_BASE (peri_base + 0x204000) // 0x7E204000 SPI0
#define BSC0_BASE (peri_base + 0x205000) // 0x7E205000 BSC0 // GPIO 00 & 01/pin 27 & 28

@@ -64,14 +56,12 @@ #define PWM_BASE (peri_base + 0x20C000) // 0x7E20C000 PWM0

/* Size of base_add[] and *base_pointer[] arrays */
#define BASE_INDEX 6 // from the current total of 11 base addresses
/* System timer registers */
#define ST_PERI_BASE base_pointer[0] // ST_BASE
/* System timer registers */
#define ST_PERI_ BASE base_pointer[0] // ST_BASE
#define ST_CS (ST_PERI_BASE + 0x00/4)
#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)

@@ -90,8 +80,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)

@@ -112,21 +102,18 @@ #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)
#define GPIO_GPPUDCLK0 (GPIO_PERI_BASE + 0x98/4)
#define GPIO_GPPUDCLK1 (GPIO_PERI_BASE + 0x9C/4)
#define GPIO_GPPUDCLK1 (GPIO_PERI_BASE + 0x9C/4)
/* SPI registers */
#define SPI_PERI_BASE base_pointer[3] // SPI0_BASE
#define SPI_CS (SPI_PERI_BASE + 0x00/4)
#define SPI_FIFO (SPI_PERI_BASE + 0x04/4)
#define SPI_CLK (SPI_PERI_BASE + 0x08/4)
#define SPI_DLEN (SPI_PERI_BASE + 0x0C/4)
#define SPI_LTOH (SPI_PERI_BASE + 0x10/4)
#define SPI_DC (SPI_PERI_BASE + 0x14/4)
/* BCM2711 (rpi4) gpio pull-up/down registers */
#define GPIO_GPPUPPDN0 (GPIO_PERI_BASE + 0xe4/4) // for pins 0 ~ 15
#define GPIO_GPPUPPDN1 (GPIO_PERI_BASE + 0xe8/4) // for pins 16 ~ 31
#define GPIO_GPPUPPDN2 (GPIO_PERI_BASE + 0xec/4) // for pins 32 ~ 47
#define GPIO_GPPUPPDN3 (GPIO_PERI_BASE + 0xf0/4) // for pins 48 ~ 57
/* PWM control and status registers */
#define PWM_PERI_BASE base_pointer[4] // PWM_BASE
#define PWM_PERI_BASE base_pointer[3] // from 4 PWM_BASE
#define PWM_CTL (PWM_PERI_BASE + 0x00/4)

@@ -140,12 +127,21 @@ #define PWM_STA (PWM_PERI_BASE + 0x04/4)

/* SPI registers */
#define SPI_PERI_BASE base_pointer[4] // from 3 SPI0_BASE
#define SPI_CS (SPI_PERI_BASE + 0x00/4)
#define SPI_FIFO (SPI_PERI_BASE + 0x04/4)
#define SPI_CLK (SPI_PERI_BASE + 0x08/4)
#define SPI_DLEN (SPI_PERI_BASE + 0x0C/4)
#define SPI_LTOH (SPI_PERI_BASE + 0x10/4)
#define SPI_DC (SPI_PERI_BASE + 0x14/4)
/* I2C registers */
#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)
#define I2C_DIV (I2C_PERI_BASE + 0x14/4)
#define I2C_DEL (I2C_PERI_BASE + 0x18/4)
#define I2C_CLKT (I2C_PERI_BASE + 0x1C/4)
#define I2C_CLKT (I2C_PERI_BASE + 0x1C/4)

@@ -155,4 +151,12 @@ /* Size of info[] array */

/* Dynamic peripheral base address array */
volatile uint32_t base_add[10] = {}; // ininialize each element to 0
/* Dynamic peripheral base address array pointer
* This is the return mapped address of each peripheral base address
*/
volatile uint32_t *base_pointer[10] = {}; // ininialize each element to 0
/* page_size variable */
int page_size = 0; // (4*1024)
uint32_t page_size = 0;

@@ -164,11 +168,5 @@ /* Peripheral base address variable. The value of which will be determined

/* Dynamic peripheral base address container */
volatile uint32_t base_add[BASE_INDEX] = {0};
/* core_clock frequency for for all RPI models */
uint32_t core_clock_freq = 250000000; // 250 MHz
/* Dynamic base address pointer to be used during mmap() process */
volatile uint32_t *base_pointer[BASE_INDEX] = {0};
/* 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
/**********************************

@@ -179,4 +177,5 @@

***********************************/
/* Get device RPI model and set peripheral base address accordingly */
void set_peri_base_address(uint8_t pwm_option, uint8_t spi_option, uint8_t i2c_option){
uint8_t cpu_type = 0, init_devmem = 0, init_gpiomem = 0, rpi_init_access = 0;
void get_cpu_type(){
FILE *fp;

@@ -188,157 +187,236 @@ char info[INFO_SIZE];

if (fp == NULL) {
fputs ("reading file /proc/cpuinfo error", stderr);
exit (1);
fputs ("fopen /proc/cpuinfo error", stderr);
exit(1);
}
/* Get 'Model' info */
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Model", 5) == 0)
break;
break;
}
//printf("%s", info);
if(strstr(info, "Pi Zero")||strstr(info, "Pi 1")){
//puts("Pi zero/Pi 1");
peri_base = PERI_BASE_RPI1;
}
if(debug) printf("%s", info);
if(strstr(info, "Pi Zero")||strstr(info, "Pi 1")){
if(debug) puts("Pi zero/Pi 1");
peri_base = PERI_BASE_1;
cpu_type = 1;
}
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;
}
if(debug) puts("Pi Zero 2/Pi 3");
peri_base = PERI_BASE_2;
cpu_type = 2;
}
else if(strstr(info, "Pi Compute Module 3")){
//puts("Pi Compute Module 3 Model");
peri_base = PERI_BASE_RPI23;
core_clock_freq = CORE_CLOCK_FREQ_RPI23;
}
if(debug) puts("Pi Compute Module 3 Model");
peri_base = PERI_BASE_2;
cpu_type = 3;
}
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;
}
if(debug) puts("Pi 4 Model B/Pi Compute Module 4");
peri_base = PERI_BASE_3;
cpu_type = 4;
}
else if(strstr(info, "Pi 400")){
//puts("Pi 400 Model");
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
if(debug) puts("Pi 400 Model");
peri_base = PERI_BASE_3;
cpu_type = 4;
}
else{
//puts("Other Rpi Model");
peri_base = PERI_BASE_RPI4;
core_clock_freq = CORE_CLOCK_FREQ_RPI4;
}
/* Verify ST_BASE, its new value should be other than 0x3000
* otherwise its peripheral base address was not correctly initialized
* along with other peripherals during runtime
*/
if(debug) puts("Other Rpi Model");
cpu_type = 0;
}
if(ST_BASE == 0x3000){
puts("peri_base address setup error:");
puts("peri_base address initialization error:");
printf("Target ST_BASE: %X\n", peri_base);
printf("Actual ST_BASE: %X\n", ST_BASE);
exit(1);
}
/*
// Check other information
// Get 'Hardware' info
rewind (fp);
while (fgets (info, INFO_SIZE, fp) != NULL){
if (strncmp (info, "Hardware", 8) == 0)
}
if(debug){
// '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
}
printf("%s", info); // show Hardware line info
// Get 'Revision' info
// '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 ;
}
// show Revision line info
printf("%s", info);
}
/* Set each peripheral base address
* consecutively for each base array element
*/
base_add[0] = ST_BASE;
base_add[1] = CLK_BASE;
base_add[2] = GPIO_BASE;
fclose(fp);
}
if(spi_option == 0){
base_add[3] = SPI0_BASE;
/* Set each peripheral register on demand */
uint8_t set_each_peri_mmap(uint8_t peri_type){
int fd = 0;
char *mem = NULL, *type = NULL;
uint8_t i = 0, end_index = 0, start_index = 0;
if(peri_type == 0 && init_gpiomem == 0){
mem = "/dev/gpiomem", type = "gpio";
start_index = 0, end_index = 3;
base_add[0] = ST_BASE;
base_add[1] = CLK_BASE;
base_add[2] = GPIO_BASE;
}
else if(peri_type == 1){
mem = "/dev/mem", type = "pwm";
start_index = 3, end_index = 4;
base_add[3] = PWM_BASE;
}
else if(peri_type == 2){
mem = "/dev/mem", type = "spi";
start_index = 4, end_index = 5;
base_add[4] = SPI0_BASE;
}
else if(peri_type == 3){
mem = "/dev/mem", type = "i2c";
start_index = 5, end_index = 7;
base_add[5] = BSC1_BASE;
//base_add[6] = BSC0_BASE;
}
else{
return 1;
}
uswait(5);
if(pwm_option == 0){
base_add[4] = PWM_BASE;
}
if((fd = open(mem, O_RDWR|O_SYNC)) < 0) {
if(peri_type == 0){
if(debug) printf("open error: %s, %s, %u\n", mem, type, peri_type);
perror("Opening gpio in /dev/gpiomem");
printf("%s() error: ", __func__);
}
else {
if(debug) printf("open error: %s, %s, %u\n", mem, type, peri_type);
perror("Opening pwm, spi or i2c in /dev/mem requires root access");
puts("Try running your app in root or sudo\n");
}
exit(1);
}
if(i2c_option == 0){
base_add[5] = BSC0_BASE;
uswait(5);
for(i = start_index; i < end_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("set_each_peri_mmap error");
printf("%s() error: ", __func__);
if(close(fd) < 0){
perror("map failed - fd close");
exit(1);
}
}
if(debug){
printf("base_add[i]: %lu\n", (unsigned long)base_add[i]);
printf("base_pointer[i]: %lu\n", (unsigned long)base_pointer[i]);
}
// Note: Disable this for SocketCan operation
*base_pointer[i] = 0;
uswait(5);
}
else if(i2c_option == 1){
base_add[5] = BSC1_BASE;
if(peri_type == 0 && init_gpiomem == 0){
init_gpiomem = 1;
}
fclose(fp);
if(close(fd) < 0){
perror("set_each_peri_mmap - fd close");
}
if(debug) printf("set individual mmap success: %s, %s, %u\n", mem, type, peri_type);
return 0;
}
void start_mmap(int access){
int fd, i;
/* Set gpio peripheral register and other registers (pwm, i2c, spi) on demand */
uint8_t set_all_peri_mmap(uint8_t access){
int fd = 0;
char *mem = NULL, *type = NULL;
uint8_t i, end_index = 0, start_index = 0;
/*
page_size = (size_t)sysconf(_SC_PAGESIZE);
//printf("init page_size: %i\n", page_size);
base_add[0] = ST_BASE;
base_add[1] = CLK_BASE;
base_add[2] = GPIO_BASE;
base_add[3] = PWM_BASE;
base_add[4] = SPI0_BASE;
base_add[5] = BSC1_BASE;
//base_add[6] = BSC0_BASE;
if(page_size < 0){
perror("page_size");
exit(1);
// access = 0, non-root
if (access == 0 && init_gpiomem == 0){
mem = "/dev/gpiomem", type = "gpio";
start_index = 0, end_index = 3;
}
*/
// access = 1, root
else if(access == 1 && init_devmem == 0) {
mem = "/dev/mem", type = "pwm, i2c, spi";
start_index = 3, end_index = 7;
}
else{
return 1;
}
// access = 0, non-root
if (!access) {
if ((fd = open("/dev/gpiomem", O_RDWR|O_SYNC)) < 0) {
perror("Opening rpi in /dev/gpiomem");
if((fd = open(mem, O_RDWR|O_SYNC)) < 0) {
if(access == 0){
if(debug) printf("open error: %s, %s, %u\n", mem, type, access);
perror("Opening gpio in /dev/gpiomem");
printf("%s() error: ", __func__);
exit(1);
}
}
// access = 1, root
else if(access) {
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0) {
perror("Opening rpi in /dev/mem requires root access");
//printf("%s() error: ", __func__);
puts("Try running your application with sudo or in root!\n");
exit(1);
}
}
/* Start mmap() process for each peripheral base address
* and capture the corresponding peripheral memory base pointers
*/
for(i = 0; i < BASE_INDEX; i++){
}
else {
if(debug) printf("open error: %s, %s, %u\n", mem, type, access);
perror("Opening pwm, spi or i2c in /dev/mem requires root access");
puts("Try running your app in root or sudo\n");
}
exit(1);
}
base_pointer[i] = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base_add[i]);
for(i = start_index; i < end_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("set_all_peri_mmap error");
printf("%s() error: ", __func__);
puts("Invalid peripheral register base address.");
if(close(fd) < 0)
if(close(fd) < 0){
perror("fd close");
exit(1);
}
/* Reset peripheral base register pointers back to 0 */
exit(1);
}
}
uswait(5);
// Note: Disable this for SocketCan operation
*base_pointer[i] = 0;
*base_pointer[i] = 0;
}
/* Close fd after memory-mapped operation */
if(access == 0 && init_gpiomem == 0){
init_gpiomem = 1;
}
else if(access == 1 && init_devmem == 0){
init_devmem = 1;
}
if(close(fd) < 0)
perror("fd close");
perror("set_all_peri_mmap - fd close");
if(debug) printf("set all mmap success: %s, %s, %u\n", mem, type, access);
return 0;
}
/* Initialize Arm Peripheral Base Register Adressses
* using mmap() either using "/dev/gpiomem" or "/dev/mem"
/* Initialize GPIO, PWM, I2C and SPI Peripheral Base Register Adressses using mmap()
*

@@ -348,50 +426,36 @@ * access = 0 ("/dev/gpiomem") // GPIO

*/
void rpi_init(int access) {
set_peri_base_address(0, 0, 1);
start_mmap(access);
}
/* Initialize Arm peripheral base register w/ i2c pin options
*
* value = 0 (use SDA0 and SCL0 pins)
* value = 1 (use SDA1 and SCL1 pins)
*/
void rpi_init_i2c(uint8_t access, uint8_t value) {
if(value == 0){
set_peri_base_address(0, 0, 0); // use SDA0 and SCL0 pins
void rpi_init(uint8_t access) {
get_cpu_type();
if(access == 1){
set_all_peri_mmap(0);
}
else if(value == 1){
set_peri_base_address(0, 0, 1); // use SDA1 and SCL1 pins
}
start_mmap(access);
set_all_peri_mmap(access);
rpi_init_access = 1;
}
/*
* Close the library and reset all memory pointers to 0 or NULL
/* Close the library and reset all memory pointers to 0 or NULL
*/
uint8_t rpi_close()
{
int i;
//page_size = (size_t)sysconf(_SC_PAGESIZE);
//printf("close page_size: %i\n", page_size);
uint32_t i;
uint8_t end_index = 7;
for(i = 0; i < BASE_INDEX; i++){
rpi_init_access = 1;
for(i = 0; i < end_index; i++){
if (munmap((uint32_t *) base_pointer[i] , BLOCK_SIZE) < 0){
perror("munmap() error");
perror("munmap() error");
printf("%s() error: ", __func__);
puts("munmap() operation fail");
return -1;
}
}
}
/* munmap() success */
return 0;
return 0;
}
/**************************************
/*****************************************
Time Delay Functions
***************************************
1 ms = 1000 us or microsecond

@@ -404,3 +468,5 @@ 1 ms = 1000000 ns or nanosecond

1 sec = 1000000000 ns or nanosecond
***************************************/
******************************************/
/* Time delay function in nanoseconds */

@@ -411,7 +477,7 @@ void nswait(uint64_t ns) {

while ( nanosleep(&req,&rem) == -1 )
req.tv_nsec = rem.tv_nsec;
while ( nanosleep(&req,&rem) == -1 )
req.tv_nsec = rem.tv_nsec;
}
/* Time delay function in us or microseconds, valid only if us is below 1000 */
/* Time delay function in microseconds, valid only if us is below 1000 */
void uswait(uint32_t us) {

@@ -431,3 +497,3 @@ struct timespec req = { us / 1000, us % 1000 * 1000 };

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

@@ -440,2 +506,3 @@

**********************************************************/
/* Set register bit position to 1 (ON state) */

@@ -483,7 +550,26 @@ uint32_t setBit(volatile uint32_t* reg, uint8_t position)

/*******************************
/******************************
GPIO Control Functions
********************************/
*******************************/
/* Initialize only the gpio peripheral register */
void gpio_init(){
if(rpi_init_access == 0){
get_cpu_type();
set_each_peri_mmap(0);
}
mswait(5);
if(debug) printf("GPIO_PERI_BASE: %lu\n", (unsigned long)GPIO_PERI_BASE);
__sync_synchronize();
if (GPIO_PERI_BASE == 0){
printf("%s() error: ", __func__);
puts("Invalid memory-mapped GPIO peripheral base register");
exit(1);
}
}
/*

@@ -509,13 +595,13 @@ * Set a GPIO pin based on fsel hex value

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
__sync_synchronize();
*gpsel |= mask; // write new fsel value to gpselect pointer
__sync_synchronize();
// get the GPFSEL0 pointer (GPFSEL0 ~ GPFSEL5) based on the pin number selected
volatile uint32_t *gpsel = (uint32_t *)(GPIO_GPFSEL0 + (pin/10));
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
__sync_synchronize();
}
/*
* Set a GPIO pin as input
/* Set a GPIO pin as input
*/

@@ -526,7 +612,6 @@ void gpio_input(uint8_t pin){

/*
* Set a GPIO pin as output
/* Set a GPIO pin as output
*/
void gpio_output(uint8_t pin){
set_gpio(pin, 1);
set_gpio(pin, 1);
}

@@ -547,28 +632,28 @@

if(mode == 0){
set_gpio(pin, 0); // input
set_gpio(pin, 0); // input
}
else if(mode == 1){
set_gpio(pin, 1); // output
set_gpio(pin, 1); // output
}
else if(mode == 4){
set_gpio(pin, 4); // alt-func 0
set_gpio(pin, 4); // alt-func 0
}
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
}
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
set_gpio(pin, 3); // alt-func 4
}
else if(mode == 2){
set_gpio(pin, 2); // alt-func 5
}
else{
printf("%s() error: ", __func__);
puts("Invalid mode parameter.");
puts("Invalid mode parameter.");
}

@@ -582,3 +667,3 @@ }

*/
uint8_t gpio_write(uint8_t pin, uint8_t bit) {
uint8_t gpio_write(uint8_t pin, uint8_t bit) {
volatile uint32_t *p = NULL;

@@ -617,7 +702,7 @@ __sync_synchronize();

/* Create a simple sing-shot pulse
/* Create a single-shot pulse
*
* td as time duration or period of the pulse
*/
void gpio_pulse(uint8_t pin, int td){
void gpio_pulse(uint8_t pin, uint32_t td){
gpio_on(pin);

@@ -668,10 +753,10 @@ mswait(td);

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.");
}

@@ -687,10 +772,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.");
}

@@ -701,3 +786,3 @@ }

Edge Detection Event
Edge Detection Event

@@ -730,10 +815,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.");
}

@@ -749,10 +834,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.");
}

@@ -768,10 +853,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.");
}

@@ -784,3 +869,3 @@ }

*/
uint8_t gpio_detect_input_event(uint8_t pin) {
uint8_t gpio_detect_input_event(uint8_t pin) {
return isBitSet(GPIO_GPEDS0, pin);

@@ -794,38 +879,84 @@ }

void gpio_reset_event(uint8_t pin) {
setBit(GPIO_GPEDS0, pin);
setBit(GPIO_GPEDS0, pin);
}
/* Enable internal PULL-UP/PULL-DOWN resistor for input pin
/* Enable internal PULL-UP/PULL-DOWN resistor for gpio pins
*
* value = 0, 0x0 or 00b, Disable Pull-Up/Down, no PU/PD resistor will be used
* value = 1, 0x1 or 01b, Enable Pull-Down resistor
* value = 2, 0x2 or 10b, Enable Pull-Up resistor
* rpi 4
* BCM2711 GPIO_GPPUPPDN0, GPIO_GPPUPPDN1, GPIO_GPPUPPDN2, GPIO_GPPUPPDN3
*
* value = 0, 0x0 or 00b, // Disable pull-up/down
* value = 1, 0x1 or 01b, // Enable pull-up
* value = 2, 0x2 or 10b, // Enable pull-down
* pi zero, rpi3 and others
* BCM2835 GPIO_GPPUD
*
* value = 0, 0x0 or 00b, // Disable pull-up/down
* value = 1, 0x1 or 01b, // Enable pull-down
* value = 2, 0x2 or 10b, // Enable pull-up
*/
void gpio_enable_pud(uint8_t pin, uint8_t value) {
if(value == 0){
*GPIO_GPPUD = 0x0; // Disable PUD/Pull-UP/Down
}
else if(value == 1){
*GPIO_GPPUD = 0x1; // Enable PD/Pull-Down
void gpio_set_pud(uint8_t pin, uint8_t pud) {
if(cpu_type == 4){
uint32_t pull = 0x0;
uint32_t lsb = (pin & 0xf) << 1;
if(pud == 0){
pull = 0x0; // No pull-up/down resistor is selected
}
else if(pud == 1){
pull = 0x2; // Pull-down is selected
}
else if(pud == 2){
pull = 0x1; // Pull-up is selected
}
else{
printf("%s() error: ", __func__);
puts("Invalid pull select pud.");
}
*(GPIO_GPPUPPDN0 + (pin >> 4)) = (*(GPIO_GPPUPPDN0 + (pin >> 4)) & ~(3 << lsb)) | (pull << lsb);
}
else{
if(pud == 0){
*GPIO_GPPUD = 0x0; // No pull-up/down resistor is selected
}
else if(pud == 1){
*GPIO_GPPUD = 0x1; // Pull-down is selected
}
else if(pud == 2){
*GPIO_GPPUD = 0x2; // Pull-up is selected
}
else{
printf("%s() error: ", __func__);
puts("Invalid pull select pud.");
}
uswait(10);
setBit(GPIO_GPPUDCLK0, pin);
uswait(10);
*GPIO_GPPUD = 0x0;
uswait(10);
clearBit(GPIO_GPPUDCLK0, pin);
}
else if(value == 2){
*GPIO_GPPUD = 0x2; // Enable PU/Pull-Up
}
else{
printf("%s() error: ", __func__);
puts("Invalid pud value.");
}
}
uswait(150); /* required wait times based on bcm2835 manual */
setBit(GPIO_GPPUDCLK0, pin);
uswait(150); /* required wait times based on bcm2835 manual */
*GPIO_GPPUD = 0x0;
clearBit(GPIO_GPPUDCLK0, pin);
uint8_t gpio_get_pud(uint8_t pin) {
uint8_t pull_state = -1;
if(cpu_type == 4){
volatile uint32_t *addr = GPIO_GPPUPPDN0 + (pin >> 4);
pull_state = (*addr) >> ((pin & 0xf) << 1) & 0x3;
}
return pull_state;
}
/*********************************
/***************************
PWM Setup functions
*********************************/
****************************/
/* Reset all PWM pins to GPIO input */

@@ -844,14 +975,14 @@ void pwm_reset_all_pins(){

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.");
puts("Choose only from the board header pins 12, 32, 33 and 35.");
exit(1);
}
}
}

@@ -861,20 +992,21 @@

void pwm_reset_pin(uint8_t pin){
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__);
if(pin == 18 || pin == 12 || pin== 13 || pin== 19) {
gpio_input(pin); // GPIO18/PHY12, GPIO12/PHY32, GPIO13/PHY33, GPIO19/PHY35
gpio_set_pud(pin, 0);
}
else {
printf("%s() error: ", __func__);
puts("Invalid pin.");
exit(1);
}
exit(1);
}
}
/*****************************************
/*************************************
PWM Clock operation functions
******************************************/
/* define clock source constants */
**************************************/
/* clock source constants */
#define OSC 0x1
#define PLLD 0x6
#define PLLD 0x6

@@ -896,13 +1028,12 @@ /* A quick check which clock generator is running

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
}
}
/* Calculate clock freq based on divisor div value */
/* Calculate clock freq based on div (divisor) value */
void set_clock_div(uint32_t div){
// using 5A as clock manager password for PASSWD field
// on bit num 31-21
// using 5A as clock manager password for PASSWD field on bit num 31-21

@@ -922,2 +1053,3 @@ /* disable PWM while performing clk operations */

}
uswait(20);

@@ -930,10 +1062,10 @@

}
/*
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)){
*CM_PWMDIV = 0x5A000000 | ( div << 12 );
}
}
uswait(20);

@@ -944,3 +1076,4 @@ }

uint8_t pwm_set_clock_freq(uint32_t divider) {
if( 0 < divider && divider < 4096){
//if( 0 < divider && divider < 4096){
if(divider > 0 && divider < 4096){
set_clock_div(divider);

@@ -964,10 +1097,28 @@ }

return -1;
}
}
}
/***************************************
/*******************************
PWM Operation functions
***************************************/
********************************/
void pwm_init(){
if(rpi_init_access == 0){
gpio_init(); // map gpio for alt pin sel
set_each_peri_mmap(1); // map pwm peripheral register
}
mswait(5);
if(debug) printf("PWM_PERI_BASE: %lu\n", (unsigned long)PWM_PERI_BASE);
__sync_synchronize();
if (PWM_PERI_BASE == 0){
printf("%s() error: ", __func__);
puts("Invalid memory-mapped PWM peripheral base register");
exit(1);
}
}
/* Monitor PWM status register and reset accordingly

@@ -986,3 +1137,3 @@ * (Internal use only)

bool WERR1 = isBitSet(PWM_STA, 2);
uswait(10);
uswait(10);

@@ -999,9 +1150,9 @@ 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
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);
}

@@ -1014,11 +1165,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);
}

@@ -1033,4 +1184,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);
}

@@ -1055,3 +1206,3 @@ // Channel 2

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

@@ -1108,23 +1259,23 @@ // Channel 2

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.");
}
}
}
/**************************************************
/****************************************
Helper functions for I2C and SPI
**************************************************/
****************************************/
/* Clear FIFO buffer function for I2C and SPI operation */

@@ -1134,17 +1285,12 @@ void clear_fifo(volatile uint32_t* reg){

setBit(reg, 5); // Set bit 5 of CLEAR field
/* alternative code */
//uint32_t mask = (3 << 4); // create a mask to set bit 4 and 5 (CLEAR field) to 1 (covers both I2C & SPI FIFO)
//*reg |= mask; // using bitwise OR assignment to clear FIFO
//uint32_t mask = 0x00000010; // mask to clear bit 4 (CLEAR field) only
//*reg |= mask;
}
/****************************
/*******************
I2C Functons
*****************************/
********************/
// Write cycles place data into the 16-byte FIFO ready for BSC bus transmission (sends data to FIFO)
// Read cycles access data received from the BSC bus (read data from FIFO).
uint8_t i2c_pin_set = 1;

@@ -1158,34 +1304,3 @@

}
// Write cycles place data into the 16-byte FIFO ready for BSC bus transmission (sends data to FIFO)
// Read cycles access data received from the BSC bus (read data from FIFO).
/* Start I2C operation */
int i2c_start()
{
//rpi_init(1);
//mswait(25);
if ( I2C_C == 0 ){
printf("%s() error: ", __func__);
puts("Invalid I2C registers addresses.");
return 0;
}
/* BSC0_BASE */
//set_gpio(0, 4); // alt 100b, PHY 27, GPIO 00, alt 0 SDA0
//set_gpio(1, 4); // alt 100b, PHY 28, GPIO 01, alt 0 SCL0
/* BSC1_BASE */
set_gpio(2, 4); // alt 100b, PHY 03, GPIO 02, alt 0 SDA1
set_gpio(3, 4); // alt 100b, PHY 05, GPIO 03, alt 0 SCL1
mswait(10);
setBit(I2C_C, 15); // set I2CEN field, enable I2C operation (BSC controller is enabled)
return 1; // i2c initialization is successful
}
/* Start I2C operation immediately w/o calling 'rpi_init(1)'
/* Start I2C operation immediately w/o calling rpi_init(1)
* (Initialization process is integrated with the function)

@@ -1198,30 +1313,33 @@ *

*/
int i2c_init(uint8_t value)
{
if(value == 1){
rpi_init_i2c(1, 1);
i2c_pin_set = 1;
void i2c_start(uint8_t sel) {
if(rpi_init_access == 0){
gpio_init(); // init gpio for alt pin sel
set_each_peri_mmap(3); // init i2c
}
else if(value == 0){
rpi_init_i2c(1, 0);
i2c_pin_set = 0;
mswait(5);
if(debug){
printf("I2C_PERI_BASE: %lu\n", (unsigned long)I2C_PERI_BASE);
//printf("I2C_PERI_BASE2: %lu\n", (unsigned long)I2C_PERI_BASE2);
printf("base_pointer[6]: %lu\n", (unsigned long)base_pointer[6]);
}
mswait(25);
if (I2C_C == 0){
if (I2C_PERI_BASE == 0){
printf("%s() error: ", __func__);
puts("Invalid I2C register addresses.");
return 0;
puts("Invalid memory-mapped I2C peripheral base register");
exit(1);
}
mswait(10);
mswait(5);
// BSC0_BASE, using SDA0 (GPIO 00/pin 27) and SCL0 (GPIO 01/pin 28)
if(value == 0){
if(sel == 0){
i2c_pin_set = 0;
set_gpio(0, 4); // GPIO 00 alt 100b, alt 0 SDA0
set_gpio(1, 4); // GPIO 01 alt 100b, alt 0 SCL0
}
}
// BSC1_BASE, using SDA1 (GPIO 02/pin 03) and SCL1 (GPIO 03/pin 05)
else if(value == 1){
else if(sel == 1){
i2c_pin_set = 1;
set_gpio(2, 4); // GPIO 02 alt 100b, alt 0 SDA1

@@ -1231,9 +1349,7 @@ set_gpio(3, 4); // GPIO 03 alt 100b, alt 0 SCL1

mswait(10);
mswait(5);
setBit(I2C_C, 15); // set I2CEN field, enable I2C operation (BSC controller is enabled)
setBit(I2C_C, 15); // set I2CEN field, enable I2C operation (BSC controller is enabled)
// or
//*I2C_C |= 0x00008000;
return 1; // i2c initialization is successful
}

@@ -1262,3 +1378,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);

@@ -1268,5 +1384,2 @@

*I2C_DEL = value;
//printf("msb:%x\n", msb);
//printf("lsb:%x\n", lsb);
//printf("value:%x\n", value);
}

@@ -1278,14 +1391,2 @@ else{

/*
volatile uint32_t delay_reg = *I2C_DEL;
// Extract the msb and lsb values from a pointer
volatile uint32_t msb1 = delay_reg & 0xFFFF0000;
volatile uint32_t lsb1 = delay_reg & 0x0000FFFF;
printf("msb1:%x\n", msb1);
printf("lsb1:%x\n", lsb1);
printf("delay_reg:%x\n", delay_reg);
*/
return *I2C_DEL;

@@ -1301,23 +1402,11 @@ }

/*
printf("cdiv msb:%x\n", msb);
printf("cdiv lsb:%x\n", lsb);
printf("cdiv_reg:%x\n", div_reg);
*/
volatile uint32_t *div = I2C_DIV;
volatile uint32_t *div = I2C_DIV;
lsb = 0x05DC;
// reset
lsb = 0x05DC;
*div = (volatile uint32_t)(msb << 16 | lsb);
//or
//*div = lsb;
//printf("reset value I2C_DIV:%x\n", *I2C_DIV);
*div = divider;
//printf("new value I2C_DIV:%x\n", *I2C_DIV);
set_clock_delay(1, 1);
//printf("set_clock_delay: %i\n", set_clock_delay(11, 11));
}

@@ -1329,5 +1418,5 @@

/* 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_CLK_FREQ/baud);
uint32_t divider = (core_clock_freq/baud);
uint32_t divider = (CORE_CLK_FREQ/baud); // using a fixed core clock freq

@@ -1341,11 +1430,2 @@ i2c_set_clock_freq((uint16_t)divider);

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

@@ -1355,3 +1435,3 @@ {

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

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

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

@@ -1371,3 +1451,3 @@

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

@@ -1380,3 +1460,3 @@

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

@@ -1389,6 +1469,6 @@ /* write error

{
//puts("The i2c controller did not send all data to slave device.");
if(debug) puts("The i2c controller did not send all the data to slave device.");
result = 4;
printf("%s(): ", __func__);
puts("Not all data were sent to the slave device.");
if(debug) puts("Not all data were sent to the slave device.");
}

@@ -1401,6 +1481,6 @@ /* read error

{
//puts("The i2c controller did not receive all data from slave device.");
if(debug) puts("The i2c controller did not receive all the data from slave device.");
result = 4;
printf("%s(): ", __func__);
puts("Not all data were received from the slave device.");
if(debug) puts("Not all data were received from the slave device.");
}

@@ -1419,4 +1499,4 @@

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

@@ -1535,7 +1615,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++;
}

@@ -1592,6 +1671,5 @@ }

clearBit(I2C_C, 15); /* clear I2CEN field to disable I2C operation (BSC controller is disabled) */
clearBit(I2C_C, 15);
if(i2c_pin_set == 0){
//puts("reset SDA0/SCL0 pins to GPIO input");
set_gpio(0, 0); /* alt 00b, PHY 27, GPIO 00, alt 0 SDA */

@@ -1601,24 +1679,28 @@ set_gpio(1, 0); /* alt 00b, PHY 28, GPIO 01, alt 0 SCL */

else{
//puts("reset SDA1/SCL1 pins to GPIO input");
set_gpio(2, 0); /* alt 00b, PHY 3, GPIO 02, alt 0 SDA */
set_gpio(3, 0); /* alt 00b, PHY 5, GPIO 03, alt 0 SCL */
}
}
}
/****************************
/********************
SPI Functons
SPI Functons
*****************************/
*********************/
/* Start SPI operation */
int spi_start()
{
//rpi_init(1);
//mswait(25);
void spi_start() {
if(rpi_init_access == 0){
gpio_init(); // map gpio for alt pin sel
set_each_peri_mmap(2); // map spi peripheral register
}
mswait(5);
if(debug) printf("SPI_PERI_BASE: %lu\n", (unsigned long)SPI_PERI_BASE);
__sync_synchronize();
if (SPI_CS == 0){
if (SPI_PERI_BASE == 0){
printf("%s() error: ", __func__);
puts("Invalid SPI registers addresses.");
return 0;
puts("Invalid memory-mapped SPI peripheral base register");
exit(1);
}

@@ -1632,8 +1714,6 @@

mswait(10);
mswait(5);
clearBit(SPI_CS, 13); // set SPI to SPI Master (Standard SPI)
clear_fifo(SPI_CS); // Clear SPI TX and RX FIFO
return 1;
}

@@ -1671,11 +1751,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
}

@@ -1686,15 +1766,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
*/
}

@@ -1714,5 +1794,5 @@

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

@@ -1732,3 +1812,3 @@

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

@@ -1766,8 +1846,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++;
}
}

@@ -1778,8 +1858,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++;
}
}

@@ -1792,4 +1872,4 @@

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

@@ -1816,4 +1896,4 @@ }

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

@@ -1835,3 +1915,3 @@ }

/* continue data transfer from spi_write start transfer */
//setBit(SPI_CS, 7); // no need to start data transfer
//setBit(SPI_CS, 7); // currently no need to set to start data transfer

@@ -1845,4 +1925,4 @@ uint8_t i = 0;

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

@@ -1855,2 +1935,1 @@ }

+18
-13

@@ -15,2 +15,4 @@ /**

#define debug 0
#ifdef __cplusplus

@@ -20,17 +22,16 @@ extern "C" {

/* Initialize RPI library */
extern void rpi_init(int access);
void rpi_init(uint8_t access);
/* Close RPI library */
extern uint8_t rpi_close();
uint8_t rpi_close();
/**
* Time Delays
* Timers
*/
void nswait(uint64_t ns); //nanosecond time delay
void nswait(uint64_t ns); //nanosecond
void uswait(uint32_t us); //microsecond time delay
void uswait(uint32_t us); //microsecond
void mswait(uint32_t ms); //millisecond time delay
void mswait(uint32_t ms); //millisecond

@@ -40,2 +41,4 @@ /**

*/
void gpio_init();
void gpio_config(uint8_t pin, uint8_t mode);

@@ -55,3 +58,3 @@

void gpio_pulse(uint8_t pin, int td);
void gpio_pulse(uint8_t pin, uint32_t td);

@@ -76,7 +79,11 @@ void gpio_reset_all_events(uint8_t pin);

void gpio_enable_pud(uint8_t pin, uint8_t value);
void gpio_set_pud(uint8_t pin, uint8_t value);
uint8_t gpio_get_pud(uint8_t pin);
/**
* PWM
*/
void pwm_init();
void pwm_set_pin(uint8_t pin);

@@ -105,6 +112,4 @@

*/
int i2c_start();
void i2c_start(uint8_t sel);
int i2c_init(uint8_t value);
void i2c_stop();

@@ -127,3 +132,3 @@

*/
int spi_start();
void spi_start();

@@ -130,0 +135,0 @@ void spi_stop();