bonescript
Version:
Physical computing library for embedded Linux
314 lines (291 loc) • 10.6 kB
JavaScript
var fs = require('fs');
var winston = require('winston');
var my = require('./my');
var parse = require('./parse');
var eeprom = require('./eeprom');
var debug = process.env.DEBUG ? true : false;
var gpioFile = {};
var pwmPrefix = {};
var ainPrefix = "";
var logfile = '/var/lib/cloud9/bonescript.log';
var readPWMFreqAndValue = function (pin, pwm) {
var mode = {};
try {
var period = fs.readFileSync(pwmPrefix[pin.pwm.name] + '/period_ns');
var duty = fs.readFileSync(pwmPrefix[pin.pwm.name] + '/duty_ns');
mode.freq = 1.0e9 / period;
mode.value = duty / period;
} catch (ex) {}
return (mode);
};
var readGPIODirection = function (n, gpio) {
var mode = {};
var directionFile = "/sys/class/gpio/gpio" + n + "/direction";
if (my.file_existsSync(directionFile)) {
mode.active = true;
var direction = fs.readFileSync(directionFile, 'utf-8');
direction = direction.replace(/^\s+|\s+$/g, '');
mode.direction = direction;
}
return (mode);
};
var readPinMux = function (pin, mode, callback) {
var pinctrlFile = '/sys/kernel/debug/pinctrl/44e10800.pinmux/pins';
var muxRegOffset = parseInt(pin.muxRegOffset, 16);
var readPinctrl = function (err, data) {
if (err) {
mode.err = 'readPinctrl error: ' + err;
if (debug) winston.debug(mode.err);
callback(mode);
}
mode = parse.modeFromPinctrl(data, muxRegOffset, 0x44e10800, mode);
callback(mode);
};
var tryPinctrl = function (exists) {
if (exists) {
fs.readFile(pinctrlFile, 'utf8', readPinctrl);
} else {
if (debug) winston.debug('getPinMode(' + pin.key + '): no valid mux data');
callback(mode);
}
};
if (callback) {
my.file_exists(pinctrlFile, tryPinctrl);
} else {
try {
var data2 = fs.readFileSync(pinctrlFile, 'utf8');
mode = parse.modeFromPinctrl(data2, muxRegOffset, 0x44e10800, mode);
} catch (ex) {
if (debug) winston.debug('getPinMode(' + pin.key + '): ' + ex);
}
}
return (mode);
};
var setPinMode = function (pin, pinData, template, resp, callback) {
if (debug) winston.debug('hw.setPinMode(' + [pin.key, pinData, template, JSON.stringify(resp)] + ');');
var p = pin.key + "_pinmux";
if (pin.universalName) p = pin.universalName + "_pinmux";
var pinmux = my.find_sysfsFile(p, my.is_ocp(), p + '.');
if (!pinmux) {
throw p + " was not found under " + my.is_ocp();
}
if ((pinData & 7) == 7) {
gpioFile[pin.key] = '/sys/class/gpio/gpio' + pin.gpio + '/value';
fs.writeFileSync(pinmux + "/state", 'gpio');
} else if (template == 'bspwm') {
fs.writeFileSync(pinmux + "/state", 'pwm');
pwmPrefix[pin.pwm.name] = '/sys/class/pwm/pwm' + pin.pwm.sysfs;
if (!my.file_existsSync(pwmPrefix[pin.pwm.name])) {
fs.appendFileSync('/sys/class/pwm/export', pin.pwm.sysfs);
}
fs.appendFileSync(pwmPrefix[pin.pwm.name] + '/run', 1);
} else {
resp.err = 'Unknown pin mode template';
}
if (callback) callback(resp);
return (resp);
};
var setLEDPinToGPIO = function (pin, resp) {
var path = "/sys/class/leds/beaglebone:green:" + pin.led + "/trigger";
if (my.file_existsSync(path)) {
fs.writeFileSync(path, "gpio");
} else {
resp.err = "Unable to find LED " + pin.led;
winston.error(resp.err);
resp.value = false;
}
return (resp);
};
var exportGPIOControls = function (pin, direction, resp, callback) {
if (debug) winston.debug('hw.exportGPIOControls(' + [pin.key, direction, resp] + ');');
var n = pin.gpio;
var exists = my.file_existsSync(gpioFile[pin.key]);
if (!exists) {
if (debug) winston.debug("exporting gpio: " + n);
fs.writeFileSync("/sys/class/gpio/export", "" + n, null);
}
var directionFile = "/sys/class/gpio/gpio" + n + "/direction";
if (debug) winston.debug('Writing GPIO direction(' + direction + ') to ' +
directionFile + ');');
fs.writeFileSync(directionFile, direction);
return (resp);
};
var writeGPIOValue = function (pin, value, callback) {
if (typeof gpioFile[pin.key] == 'undefined') {
gpioFile[pin.key] = '/sys/class/gpio/gpio' + pin.gpio + '/value';
if (pin.led) {
gpioFile[pin.key] = "/sys/class/leds/beaglebone:";
gpioFile[pin.key] += "green:" + pin.led + "/brightness";
}
if (!my.file_existsSync(gpioFile[pin.key])) {
winston.error("Unable to find gpio: " + gpioFile[pin.key]);
}
}
if (debug) winston.debug("gpioFile = " + gpioFile[pin.key]);
if (callback) {
fs.writeFile(gpioFile[pin.key], '' + value, null, callback);
} else {
try {
fs.writeFileSync(gpioFile[pin.key], '' + value, null);
} catch (ex) {
winston.error("Unable to write to " + gpioFile[pin.key]);
}
}
};
var readGPIOValue = function (pin, resp, callback) {
var gpioFile = '/sys/class/gpio/gpio' + pin.gpio + '/value';
if (callback) {
var readFile = function (err, data) {
if (err) {
resp.err = 'digitalRead error: ' + err;
winston.error(resp.err);
}
resp.value = parseInt(data, 2);
callback(resp);
};
fs.readFile(gpioFile, readFile);
return (true);
}
resp.value = parseInt(fs.readFileSync(gpioFile), 2);
return (resp);
};
var enableAIN = function (callback) {
var helper = "";
if (my.load_dt('cape-bone-iio')) {
var ocp = my.is_ocp();
if (ocp) {
helper = my.find_sysfsFile('helper', ocp, 'helper.');
if (helper) {
ainPrefix = helper + '/AIN';
}
}
} else {
if (debug) winston.debug('enableAIN: load of cape-bone-iio failed');
}
if (callback) {
callback({
'path': helper
})
}
return (helper.length > 1);
};
var readAIN = function (pin, resp, callback) {
var ainFile = ainPrefix + pin.ain.toString();
if (callback) {
var readFile = function (err, data) {
if (err) {
resp.err = 'analogRead error: ' + err;
winston.error(resp.err);
}
resp.value = parseInt(data, 10) / 1800;
callback(resp);
};
fs.readFile(ainFile, readFile);
return (resp);
}
resp.value = parseInt(fs.readFileSync(ainFile), 10);
if (isNaN(resp.value)) {
resp.err = 'analogRead(' + pin.key + ') returned ' + resp.value;
winston.error(resp.err);
}
resp.value = resp.value / 1800;
if (isNaN(resp.value)) {
resp.err = 'analogRead(' + pin.key + ') scaled to ' + resp.value;
winston.error(resp.err);
}
return (resp);
};
var writeGPIOEdge = function (pin, mode) {
fs.writeFileSync('/sys/class/gpio/gpio' + pin.gpio + '/edge', mode);
var resp = {};
resp.gpioFile = '/sys/class/gpio/gpio' + pin.gpio + '/value';
resp.valuefd = fs.openSync(resp.gpioFile, 'r');
resp.value = new Buffer(1);
return (resp);
};
var writePWMFreqAndValue = function (pin, pwm, freq, value, resp, callback) {
if (debug) winston.debug('hw.writePWMFreqAndValue(' + [pin.key, pwm, freq, value, resp] + ');');
var path = pwmPrefix[pin.pwm.name];
try {
var period = Math.round(1.0e9 / freq); // period in ns
if (pwm.freq != freq) {
if (debug) winston.debug('Stopping PWM');
fs.writeFileSync(path + '/run', "0\n");
if (debug) winston.debug('Setting duty to 0');
fs.writeFileSync(path + '/duty_ns', "0\n");
try {
if (debug) winston.debug('Updating PWM period: ' + period);
fs.writeFileSync(path + '/period_ns', period + "\n");
} catch (ex2) {
period = fs.readFileSync(path + '/period_ns');
winston.info('Unable to update PWM period, period is set to ' + period);
}
if (debug) winston.debug('Starting PWM');
fs.writeFileSync(path + '/run', "1\n");
}
var duty = Math.round(period * value);
if (debug) winston.debug('Updating PWM duty: ' + duty);
//if(duty == 0) winston.error('Updating PWM duty: ' + duty);
fs.writeFileSync(path + '/duty_ns', duty + "\n");
} catch (ex) {
resp.err = 'error updating PWM freq and value: ' + path + ', ' + ex;
winston.error(resp.err);
}
return (resp);
};
var readEeproms = function (eeproms) {
var EepromFiles = {
'/sys/bus/i2c/drivers/at24/0-0050/eeprom': {
type: 'bone'
},
'/sys/bus/i2c/drivers/at24/2-0054/eeprom': {
type: 'cape'
},
'/sys/bus/i2c/drivers/at24/2-0055/eeprom': {
type: 'cape'
},
'/sys/bus/i2c/drivers/at24/2-0056/eeprom': {
type: 'cape'
},
'/sys/bus/i2c/drivers/at24/2-0057/eeprom': {
type: 'cape'
}
};
eeproms = eeprom.readEeproms(EepromFiles);
return (eeproms);
};
var readPlatform = function (platform) {
var eeproms = eeprom.readEeproms({
'/sys/bus/i2c/drivers/at24/0-0050/eeprom': {
type: 'bone'
}
});
var x = eeproms['/sys/bus/i2c/drivers/at24/0-0050/eeprom'];
if (x.boardName == 'A335BONE') platform.name = 'BeagleBone';
if (x.boardName == 'A335BNLT') platform.name = 'BeagleBone Black';
platform.version = x.version;
if (!platform.version.match(/^[\040-\176]*$/)) delete platform.version;
platform.serialNumber = x.serialNumber;
if (!platform.serialNumber.match(/^[\040-\176]*$/)) delete platform.serialNumber;
try {
platform.dogtag = fs.readFileSync('/etc/dogtag', 'ascii');
} catch (ex) {}
return (platform);
};
module.exports = {
logfile: logfile,
readPWMFreqAndValue: readPWMFreqAndValue,
readGPIODirection: readGPIODirection,
readPinMux: readPinMux,
setPinMode: setPinMode,
setLEDPinToGPIO: setLEDPinToGPIO,
exportGPIOControls: exportGPIOControls,
writeGPIOValue: writeGPIOValue,
readGPIOValue: readGPIOValue,
enableAIN: enableAIN,
readAIN: readAIN,
writeGPIOEdge: writeGPIOEdge,
writePWMFreqAndValue: writePWMFreqAndValue,
readEeproms: readEeproms,
readPlatform: readPlatform
}