diff --git a/.gitignore b/.gitignore index 378eac2..e2a5649 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ build +npm-debug.log +install.log \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..56bee6c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,142 @@ +# CHANGELOG + +## v2.1.0 *[not released yes]* + * **Update:** libWiringPi to [custom][nekuz0r-libWiringPi] v2.21 `nekuz0r` + * **Add:** raspberry pi A+ support `nekuz0r` + +## v2.0.0 *[Jan 1 2015]* + * **Update:** libWiringPi to [custom][nekuz0r-libWiringPi] v2.20 `nekuz0r` + * **Update:** split source code (based on libWiringPi hierarchy) `nekuz0r` + * **Update:** better types check `nekuz0r` + * **Update:** better allowed values check `nekuz0r` + * **Update:** better error messages `nekuz0r` + * **Update:** documentation `nekuz0r` + * **Update:** constants are exported from c++ (ReadOnly | DontDelete) `nekuz0r` + * **Update:** setup() is exported from c++ `nekuz0r` + * NOTE: it no longer accepts empty parameter 'mode' (breaks backward compatibility) + * **Update:** wiringPiSPIDataRW now takes a buffer as second parameter (no third anymore) `nekuz0r` + * **Update:** piBoardId `nekuz0r` + * **Remove:** backward compatibility constants `nekuz0r` + * **Remove:** export of piComputeModuleRevisionNames `nekuz0r` + * **Add:** export of PI_MODEL_* constants `nekuz0r` + * **Add:** export of PI_VERSION_* constants `nekuz0r` + * **Add:** export of PI_MAKER_* constants `nekuz0r` + * **Add:** export of piMakerNames string table `nekuz0r` + * **Add:** wiringPiISR `nekuz0r` + * **Add:** pwmToneWrite `nekuz0r` + * **Add:** CHANGELOG.md `nekuz0r` + * **Add:** wiringPiI2C support `nekuz0r` + * **Add:** wiring-pi install gpio utilty (required for interrupts) `nekuz0r` + * **Add:** ds1302 support `nekuz0r` + * **Add:** gertboard support `nekuz0r` + * **Add:** lcd support `nekuz0r` + * **Add:** lcd128x64 support `nekuz0r` + * **Add:** maxdetect support `nekuz0r` + * **Add:** piFace support `nekuz0r` + * **Add:** piGlow support `nekuz0r` + * **Add:** piNes support `nekuz0r` + * **Add:** tcs34725 support `nekuz0r` + * **Add:** dac7678 support `nekuz0r` + * **Fictitious:** this release eats Pi(e)s :) + +## v1.1.1 *[Jul 4 2014]* + * **Fix:** missing constant in pinModeCheck `nekuz0r` + * **Fix:** missing constant PI_MODEL_CM `nekuz0r` + * **Add:** serialPrintf (alias to serialPuts) `nekuz0r` + +## v1.1.0 *[Jun 30 2014]* + * **Update:** libWiringPi to [custom][nekuz0r-libWiringPi] v2.15 `nekuz0r` + * **Fix:** mcp3422 constants again `nekuz0r` + * **Remove:** precompiled dependencies `nekuz0r` + * **Add:** install script + * **Add:** pca9685 support `nekuz0r` + * **Add:** pulseIn `nekuz0r` + * **Add:** piBoardId `nekuz0r` + * **Add:** softPwmStop `nekuz0r` + * **Add:** softToneStop `nekuz0r` + * **Add:** SOFT_PWM_OUTPUT, SOFT_TONE_OUTPUT `nekuz0r` + * **Add:** PI_MODEL_A, PI_MODEL_B, PI_MODEL_CM `nekuz0r` + * **Add:** PI_MODEL_NAMES, PI_REVISION_NAMES, PI_COMPUTE_REVISION_NAMES `nekuz0r` + * **Add:** delay `nekuz0r` + * **Add:** delayMicroseconds `nekuz0r` + * **Add:** millis `nekuz0r` + * **Add:** micros `nekuz0r` + +## v1.0.2 *[Mar 18 2014]* + * Releasing as Open Open Source `eugeneware` + +## v1.0.1 *[Mar 18 2014]* + * **Fix:** mcp3422 constants `nekuz0r` + +## v1.0.0 *[Nov 29 2013]* + * **Update:** libWiringPi to v2.13 `nekuz0r` + * **Update:** examples (blink, pwm) `nekuz0r` + * **Update:** documentation `nekuz0r` + * **Add:** physical numbering scheme support (setup) `nekuz0r` + * **Add:** drcSerial support `nekuz0r` + * **Add:** max5322 support `nekuz0r` + * **Add:** mcp23s08 support `nekuz0r` + * **Add:** mcp3002 support `nekuz0r` + * **Add:** mcp3004 support `nekuz0r` + * **Add:** mcp3422 support `nekuz0r` + * **Add:** mcp4802 support `nekuz0r` + * **Add:** mcp23008 support `nekuz0r` + * **Add:** mcp23016 support `nekuz0r` + * **Add:** mcp23017 support `nekuz0r` + * **Add:** pcf8574 support `nekuz0r` + * **Add:** pcf8591 support `nekuz0r` + * **Add:** softPWM support `nekuz0r` + * **Add:** softServo support `nekuz0r` + * **Add:** softTone support `nekuz0r` + * **Add:** sr595 support `nekuz0r` + * **Add:** wiringPiSPI support `nekuz0r` + * **Add:** wiringPiSerial support (serialPrintf not implemented yet) `nekuz0r` + * **Add:** wiringPiShift support `nekuz0r` + * **Add:** pinModeAlt `nekuz0r` + * **Add:** analogRead `nekuz0r` + * **Add:** analogWrite `nekuz0r` + * **Add:** wpiPinToGpio `nekuz0r` + * **Add:** physPinToGpio `nekuz0r` + * **Add:** setPadDrive `nekuz0r` + * **Add:** getAlt `nekuz0r` + * **Add:** digitalWriteByte `nekuz0r` + * **Add:** pwmSetMode `nekuz0r` + * **Add:** gpioClockSet `nekuz0r` + * **Add:** LSBFIRST, MSBFIRST `nekuz0r` + * **Add:** MCP3422_SR_3_75, MCP3422_SR_15, MCP3422_SR_60, MCP3422_SR_240 `nekuz0r` + * **Add:** MCP3422_GAIN_1, MCP3422_GAIN_2, MCP3422_GAIN_4, MCP3422_GAIN_8 `nekuz0r` + * **Add:** WPI_MODE_PINS, WPI_MODE_GPIO, WPI_MODE_GPIO_SYS, WPI_MODE_GPIO_PHYS, WPI_MODE_PIFACE, WPI_MODE_UNINITIALIZED `nekuz0r` + * **Add:** INPUT, OUTPUT, PWM_OUTPUT, GPIO_CLOCK `nekuz0r` + * **Add:** PUD_OFF, PUD_UP, PUD_DOWN `nekuz0r` + * **Add:** PWM_MODE_MS, PWM_MODE, BAL `nekuz0r` + * **Add:** INT_EDGE_SETUP, INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH `nekuz0r` + +## v0.2.0 *[Nov 5 2013]* + * **Add:** pullUpDnControl `nekuz0r` + * **Add:** pull.PUD_OFF, pull.PUD_UP, pull.PUD_DOWN `nekuz0r` + +## v0.1.2 *[Aug 2 2013]* + * **Add:** HIGH, LOW `csquared` + * **Fix:** typo in exports.js `csquared` + * **Update:** README.md `csquared` + +## v0.1.1 *[Jun 11 2013]* + * **Add:** PWM example `eugeneware` + * **Fix:** pwmWrite export `eugeneware` + +## v0.1.0 *[Dec 20 2013]* + * Initial version `soarez` + * wiringPiSetup + * wiringPiSetupGpio + * wiringPiSetupSys + * piBoardRev + * pinMode + * digitalWrite + * digitalRead + * pwmSetRange + * pwmSetClock + * pwmWrite + * setup + * blink example + +[nekuz0r-libWiringPi]: https://github.com/nekuz0r/wiringpi/ \ No newline at end of file diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md new file mode 100644 index 0000000..b1548c6 --- /dev/null +++ b/DOCUMENTATION.md @@ -0,0 +1,1150 @@ +# Table of Contents + +* [Install](#install) +* [Usage](#usage) +* [APIs](#apis) + * [Setup](#setup) + * [Core functions](#core) + * [Interrupts](#interrupts) + * [Raspberry Pi specific](#raspberry-pi-hardware-specific-functions) + * [I2C](#i2c) + * [SPI](#spi) + * [Serial](#serial) + * [Shift](#shift) + * [Soft PWM](#soft-pwm) + * [Soft Servo](#soft-servo) + * [Soft Tone](#soft-tone) + * [Extensions](#extensions) + * [dac7678](#dac7678) + * [drcSerial](#drcserial) + * [max31855](#max31855) + * [max5322](#max5322) + * [mcp23008](#mcp23008) + * [mcp23016](#mcp23016) + * [mcp23017](#mcp23017) + * [mcp23s08](#mcp23s08) + * [mcp23s17](#mcp23s17) + * [mcp3002](#mcp3002) + * [mcp3004/8](#mcp30048) + * [mcp3422/3/4](#mcp342234) + * [mcp4802/12/22](#mcp48021222) + * [pca9685](#pca9685) + * [pcf8574](#pcf8574) + * [pcf8591](#pcf8591) + * [sn3218](#sn3218) + * [sr595](#sr595) + * [DevLib](#devlib) + * [ds1302](#ds1302) + * [GetBoard](#getboard) + * [LCD](#lcd) + * [LCD 128x64](#lcd-128x64) + * [piFace](#piface) + * [piGlow](#piglow) + * [piNew](#pinew) + * [tcs34725](#tcs34725) + +--- + +# Install + +``` +npm install wiring-pi +``` + +--- + +# Usage + +```javascript +var wpi = require('wiring-pi'); +``` + +--- + +# APIs + +## Setup + +### wiringPiSetup() + >= 0.1.0 + +Initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme. + +This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. + +see the [pins](http://wiringpi.com/pins/) page for a table which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector. + +This function needs to be called with root privileges. + +### wiringPiSetupGpio() + >= 0.1.1 + +This is indential to above, however it allows the calling programs to use the Broadcom GPIO pin numbers directly with no re-mapping. + +As above, this function needs to be called with root privileges, and note that some pins are different from revision 1 to revision 2 boards. + +### wiringPiSetupPhys() + >= 1.0.0 + +Identical to above, however it allows the calling programs to use the physical pin numbers on the P1 connector only. + +As above, this function needs to be called with root priviliges. + +### wiringPiSetupSys() + >= 0.1.1 + +This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly. + +This can be called as a non-root user provided the GPIO pins have been exported before-hand using gpio program. + +Pin numbering in this mode is the native Broadcom GPIO numbers - the same as wiringPiSetGpio above, so be aware of the differences between Rev 1 and Rev 2 boards. + +**NOTE: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface before you run your program.** + +**You can do this in a seperate shell script, or by using the system() function from inside your program to call the gpio program.** + +**Also note that some functions have no effect when using this mode as they're not currently possible to action unless called with root privileges. (although you can use system() to call gpio to set/change modes if needed).** + +### setup(mode) + >= 0.1.1 + +An handy function to setup wiringPi + +`mode` can be one of the following values: + +* `wpi`: sets up pin numbering with wiringPiSetup + >= 0.1.1 +* `gpio`: sets up pin numbering with wiringPiSetupGpio + >= 0.1.1 +* `sys`: sets up pin numbering with wiringPiSetupSys + >= 0.1.1 +* `phys`: sets up pin numbering with wiringPiSetupPhys + >= 1.0.0 + +More info about pin numbering systems at [wiringpi.com/pins/](http://wiringpi.com/pins/) + +**NOTE: `>= 2.0.0` no longer accept calling setup without mode specified. (defaulting to `wpi` in `< 2.0.0`)** + +--- + +## Core functions + +### pinModeAlt(pin, mode) + >= 1.0.0 + +This is an un-documented special to let you set any pin to any mode. + +`mode` can be one of the following values: + +* `WPI_MODE_PINS` + >= 1.0.0 +* `WPI_MODE_PHYS` + >= 1.0.0 +* `WPI_MODE_GPIO` + >= 1.0.0 + +### pinMode(pin, mode) + >= 0.1.0 + +This sets the mode of a pin. + +Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes. + +This function has no effect when in Sys mode. + +If you need to change the pin mode, the you can do it with the gpio program in a script before you start your program. + +`mode` can be one of the following values: + +* `modes.INPUT` + >= 0.1.1 < 2.0.0 removed +* `modes.OUTPUT` + >= 0.1.1 < 2.0.0 removed +* `modes.PWM_OUTPUT` + >= 0.1.1 < 2.0.0 removed +* `modes.GPIO_CLOCK` + >= 0.1.1 < 2.0.0 removed +* `INPUT` + >= 1.0.0 +* `OUTPUT` + >= 1.0.0 +* `PWM_OUTPUT` + >= 1.0.0 +* `GPIO_CLOCK` + >= 1.0.0 +* `SOFT_PWM_OUTPUT` + >= 1.1.0 +* `SOFT_TONE_OUTPUT` + >= 1.1.0 + +### pullUpDnControl(pin, pud) + >= 0.2.0 + +This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. + +Unlike Arduino, the BCM2835 has both pull-up and down internal resistors. + +The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi. + +`pud` can be one of the following values: + +* `PUD_OFF` *no pull up/down* + >= 0.2.0 +* `PUD_DOWN` *pull to ground* + >= 0.2.0 +* `PUD_UP` *pull to 3.3v* + >= 0.2.0 + +### digitalRead(pin) + >= 0.1.1 + +This function returns the value read at the given pin. + +It will be `HIGH` (1) or `LOW` (0) depending on the logic level at the pin. + +### digitalWrite(pin, state) + >= 0.1.0 + +Write the value `HIGH` (1) or `LOW` (0) to the given pin which must have been previously set as an output. + +WiringPi treats any non-zero number as `HIGH`, however 0 is the only representation of `LOW`. + +`state` can be one of the following value: + +* `HIGH` + >= 0.1.2 +* `LOW` + >= 0.1.2 + +### pwmWrite(pin, value) + >= 0.1.1 + +Writes the value to the PWM register for the given pin. + +The Raspberry Pi has one on-board PWM pin, pin 1 (BCM_GPIO 18, Phys 12) and the range is [0, 1024]. + +Other PWM devices may have other PWM ranges. + +This function is not able to control the Pi's on-board PWM when in Sys mode. + +### analogRead(pin) + >= 1.0.0 + +This returns the value read on the supplied analog input pin. + +You will need to register additional analog modules to enable this function for device such as the Gertboard, quick2Wire analog board, etc. + +### analogWrite(pin, value) + >= 1.0.0 + +This writes the given value to the supplied analog pin. + +You will need to register additional analog modules to enable this function for devices such as the Gertboard. + +### pulseIn(pin, state) + >= 1.1.0 + +Reads a pulse (either HIGH or LOW) on a pin. + +For example, if `state` is HIGH, pulseIn waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. + +Returns the length of the pulse in microseconds. + +Gives up and returns 0 if no pulse starts within a specified time out. + +`state` can be one of the following values: + +* `HIGH` + >= 0.1.2 +* `LOW` + >= 0.1.2 + +### delay(milliseconds) + >= 1.1.0 + +Pauses the program for the amount of time (in miliseconds) specified as parameter. + +There are 1000 milliseconds in a second. + +### delayMicroseconds(microseconds) + >= 1.1.0 + +Pauses the program for the amount of time (in microseconds) specified as parameter. + +There are a thousand microseconds in a millisecond, and a million microseconds in a second. + +For delays longer than a few thousand microseconds, you should use delay() instead. + +### millis() + >= 1.1.0 + +Returns the number of milliseconds since the beginning running of the current program + +### micros() + >= 1.1.0 + +Returns the number of microseconds since the beginning running of the current program + +--- + +## Interrupts + +### wiringPiISR(pin, edgeType, callback) + >= 2.0.0 + +This function registers a function to received interrupts on the specified pin. + +The edgeType parameter is either `INT_EDGE_FALLING`, `INT_EDGE_RISING`, `INT_EDGE_BOTH` or `INT_EDGE_SETUP`. + +If it is `INT_EDGE_SETUP` then no initialisation of the pin will happen – it’s assumed that you have already setup the pin elsewhere (e.g. with the gpio program), but if you specify one of the other types, then the pin will be exported and initialised as specified. + +This is accomplished via a suitable call to the gpio utility program, so it need to be available. + +The pin number is supplied in the current mode – native wiringPi, BCM_GPIO, physical or Sys modes. + +This function will work in any mode, and does not need root privileges to work. + +The callback will be called when the interrupt triggers. + +When it is triggered, it’s cleared in the dispatcher before calling your function, so if a subsequent interrupt fires before you finish your handler, then it won’t be missed. + +However it can only track one more interrupt, if more than one interrupt fires while one is being handled then they will be ignored. + +```javascript +wpi.setup('wpi'); +wpi.pinMode(7, wpi.INPUT); +wpi.pullUpDnControl(7, wpi.PUD_UP); +wpi.wiringPiISR(7, wpi.INT_EDGE_FALLING, function(delta) { + console.log('Pin 7 changed to LOW (', delta, ')'); +}); +``` + +--- + +## Raspberry Pi hardware specific functions + +### piBoardRev() + >= 0.1.1 + +This returns the board revision of the Raspberry Pi. + +It will be either 1 or 2. + +Some of the BCM_GPIO pins changed number and function when moving from board revision 1 to 2, so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences. + +### piBoardId() + >= 1.1.0 + +Do more digging into the board revision string as above, but return as much details as we can. + +Returns an object with the following keys: + +* `model`: indexes to `PI_MODEL_NAMES` string table +* `rev`: indexes to `PI_REVISION_NAMES` string table +* `mem`: 256 or 512 +* `maker`: indexes to `PI_MAKER_NAMES` string table +* `overvolted`: 0 or 1 + >= 2.0.0 + +**NOTE: `maker` was a string in versions >= 1.1.0 and < 2.0.0** + +Indexes of each string table have corresponding constants + +* `PI_MODEL_NAME` + * `PI_MODEL_UNKNOWN` + >= 2.0.0 + * `PI_MODEL_A` + >= 1.1.0 + * `PI_MODEL_B` + >= 1.1.0 + * `PI_MODEL_BP` + >= 2.0.0 + * `PI_MODEL_CM` + >= 1.1.1 + + +* `PI_REVISION_NAMES` + * `PI_VERSION_UNKNOWN` + >= 2.0.0 + * `PI_VERSION_1` + >= 2.0.0 + * `PI_VERSION_1_1` + >= 2.0.0 + * `PI_VERSION_1_2` + >= 2.0.0 + * `PI_VERSION_2` + >= 2.0.0 + +* `PI_MAKER_NAMES` + * `PI_MAKER_UNKNOWN` + >= 2.0.0 + * `PI_MAKER_EGOMAN` + >= 2.0.0 + * `PI_MAKER_SONY` + >= 2.0.0 + * `PI_MAKER_QISDA` + >= 2.0.0 + +### wpiPinToGpio(pin) + >= 1.0.0 + +This returns the BCM_GPIO pin number of the supplied wiringPi pin. + +It takes the board revision into account. + +### physPinToGpio(pin) + >= 1.0.0 + +This returns the BCM_GPIO pin number of the suppled physical pin on the P1 connector. + +### setPadDrive(group, value) + >= 1.0.0 + +This sets the "strength" of the pad drivers for a particular group of pins. + +There are 3 groups of pins and the drive strength is from 0 to 7. + +**NOTE: Do not use the unless you know what you are doing.** + +### getAlt(pin) + >= 1.0.0 + +Returns the ALT bits for a given port. + +### digitalWriteByte(byte) + >= 1.0.0 + +This writes the 8-bit byte supplied to the first 8 GPIO pins. + +It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware. + +### pwmSetMode(mode) + >= 1.0.0 + +The PWM generator can run in 2 modes – “balanced” and “mark:space”. + +The mark:space mode is traditional, however the default mode in the Pi is “balanced”. + +`mode` can be one of the following values: + +* `PWM_MODE_BAL` *balanced* +* `PWM_MODE_MS` *mark:space* + +### pwmSetRange(range) + >= 0.1.1 + +This sets the range register in the PWM generator. + +The default is 1024. + +**NOTE: The PWM control functions can not be used when in Sys mode. To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.** + +### pwmSetClock(divisor) + >= 0.1.1 + +This sets the divisor for the PWM clock. + +**NOTE: The PWM control functions can not be used when in Sys mode. To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.** + +### pwmToneWrite(pin, frequency) + >= 2.0.0 + +Output the given frequency on the Pi's PWM pin + +### gpioClockSet(pin, frequency) + >= 1.0.0 + +Set the frequency on a GPIO clock pin + +--- + +## I2C + +### wiringPiI2CSetup(devId) + >= 2.0.0 + +This initialises the I2C system with your given device identifier. + +The ID is the I2C number of the device and you can use the i2cdetect program to find this out. + +wiringPiI2CSetup() will work out which revision Raspberry Pi you have and open the appropriate device in /dev. + +The return value is the standard Linux filehandle, or -1 if any error – in which case, you can consult errno as usual. + +### wiringPiI2CSetupInterface(device, devId) + >= 2.0.0 + +Undocumented access to set the interface explicitly - might be used for the Pi's 2nd I2C interface... + +### wiringPiI2CRead(fd) + >= 2.0.0 + +Simple device read. + +Some devices present data when you read them without having to do any register transactions. + +### wiringPiI2CReadReg8(fd, reg) + >= 2.0.0 + +This read an 8-bit value from the device register indicated. + +### wiringPiI2CReadReg16(fd, red) + >= 2.0.0 + +This read an 16-bit value from the device register indicated. + +### wiringPiI2CWrite(fd, data) + >= 2.0.0 + +Simple device write. + +Some devices accept data this way without needing to access any internal registers. + +### wiringPiI2CWriteReg8(fd, reg, data) + >= 2.0.0 + +This write an 8-bit data value into the device register indicated. + +### wiringPiI2CWriteReg16(fd, reg, data) + >= 2.0.0 + +This write an 16-bit data value into the device register indicated. + +--- + +## SPI + +### wiringPiSPIGetFd(channel) + >= 1.0.0 + +Returns the file-descriptor for the given channel + +### wiringPiSPIDataRW(channel, data) + >= 1.0.0 + +This performs a simultaneous write/read transaction over the selected SPI bus. + +Data that was in your buffer is overwritten by data returned from the SPI bus. + +It is possible to do simple read and writes over the SPI bus using the standard read() and write() system calls though – write() may be better to use for sending data to chains of shift registers, or those LED strings where you send RGB triplets of data. + +Devices such as A/D and D/A converters usually need to perform a concurrent write/read transaction to work. + +### wiringPiSPISetup(channel, speed) + >= 1.0.0 + +This is the way to initialise a channel (The Pi has 2 channels; 0 and 1). + +The speed parameter is an integer in the range 500,000 through 32,000,000 and represents the SPI clock speed in Hz. + +The returned value is the Linux file-descriptor for the device, or -1 on error. + +If an error has happened, you may use the standard errno global variable to see why. + +--- + +## Serial + +### serialOpen(device, baudrate) + >= 1.0.0 + +This opens and initialises the serial device and sets the baud rate. + +It sets the port into “raw” mode (character at a time and no translations), and sets the read timeout to 10 seconds. + +The return value is the file descriptor or -1 for any error, in which case errno will be set as appropriate. + +**NOTE: The file descriptor (fd) returned is a standard Linux file descriptor.** + +**You can use the standard read(), write(), etc. system calls on this file descriptor as required.** + +**E.g. you may wish to write a larger block of binary data where the serialPutchar() or serialPuts() function may not be the most appropriate function to use, in which case, you can use write() to send the data.** + +### serialClose(fd) + >= 1.0.0 + +Closes the device identified by the file descriptor given. + +### serialFlush(fd) + >= 1.0.0 + +This discards all data received, or waiting to be send down the given device. + +### serialPutchar(fd, character) + >= 1.0.0 + +Sends the single byte to the serial device identified by the given file descriptor. + +### serialPuts(fd, string) + >= 1.0.0 + +Sends the nul-terminated string to the serial device identified by the given file descriptor. + +### serialPrintf(fd, string) + + Alias: serialPuts + >= 2.0.0 + + +### serialDataAvail(fd) + >= 1.0.0 + +Returns the number of characters available for reading, or -1 for any error condition, in which case errno will be set appropriately. + +### serialGetchar(fd) + >= 1.0.0 + +Returns the next character available on the serial device. + +This call will block for up to 10 seconds if no data is available (when it will return -1) + +--- + +## Shift + +### shiftIn(dPin, cPin, order) + >= 1.0.0 + +This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin. + +Order is either `LSBFIRST` or `MSBFIRST`. + +The data is sampled after the cPin goes high. (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function. + +### shiftOut(dPin, cPin, order, value) + >= 1.0.0 + +The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin. + +Order is as above. + +Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low – repeated for the 8 bits. + +--- + +## Soft PWM + +### softPwmCreate(pin, value, range) + >= 1.0.0 + +This creates a software controlled PWM pin. + +You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. + +Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin. + +The return value is 0 for success. + +Anything else and you should check the global errno variable to see what went wrong. + +**NOTE: Each “cycle” of PWM output takes 10mS with the default range value of 100, so trying to change the PWM value more than 100 times a second will be futile.** + +**NOTE: Each pin activated in softPWM mode uses approximately 0.5% of the CPU.** + +**NOTE: You need to keep your program running to maintain the PWM output!** + +### softPwmWrite(pin, value) + >= 1.0.0 + +This updates the PWM value on the given pin. + +The value is checked to be in-range and pins that haven’t previously been initialised via softPwmCreate will be silently ignored. + +### softPwmStop(pin) + >= 1.1.0 + +--- + +## Soft Servo + +### softServoWrite(pin, value) + >= 1.0.0 + +### softServoSetup(p0, p1, p2, p3, p4, p5, p6, p7) + >= 1.0.0 + +--- + +## Soft Tone + +### softToneCreate(pin); + >= 1.0.0 + +This creates a software controlled tone pin. + +You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. + +The return value is 0 for success. + +Anything else and you should check the global errno variable to see what went wrong. + +**NOTE: Each pin activated in softTone mode uses approximately 0.5% of the CPU.** + +**NOTE: You need to keep your program running to maintain the sound output!** + +### softToneWrite(pin, frequency); + >= 1.0.0 + +This updates the tone frequency value on the given pin. + +The tone will be played until you set the frequency to 0. + +### softToneStop(pin); + >= 1.1.0 + +--- + +## Extensions + +### dac7678 + +12-Bit octal-channel DAC with 2.5V internal reference (I2C) + +*Datasheet*: http://www.ti.com/lit/ds/sbas493c/sbas493c.pdf + +#### dac7678Setup(pinBase, i2cAddress, vrefMode) + >= 2.0.0 + +`state` can be one of the following value: + +* `DAC7678_VREF_MODE_STATIC_ON` + >= 2.0.0 +* `DAC7678_VREF_MODE_STATIC_OFF` + >= 2.0.0 +* `DAC7678_VREF_MODE_FLEXIBLE_ON` + >= 2.0.0 +* `DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_ON` + >= 2.0.0 +* `DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_OFF` + >= 2.0.0 + +### drcSerial + +#### drcSetupSerial(pinBase, numPins, device, baudrate) + >= 1.0.0 + +### max31855 + +Cold-junction compensated thermocouple-to-digital converter (SPI) + +*Datasheet*: http://datasheets.maximintegrated.com/en/ds/MAX31855.pdf + +#### max31855Setup(pinBase, spiChannel) + >= 1.0.0 + +### max5322 + +12-Bit DAC (SPI) + +*Datasheet*: http://datasheets.maximintegrated.com/en/ds/MAX5322.pdf + +#### max5322Setup(pinBase, spiChannel) + >= 1.0.0 + +### mcp23008 + +8-Bit I/O expander (I2C) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21919e.pdf + +#### mcp23008Setup(pinBase, i2cAddress) + >= 1.0.0 + +### mcp23016 + +16-Bit I/O expander (I2C) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/20090C.pdf + +#### mcp23016Setup(pinBase, i2cAddress) + >= 1.0.0 + +### mpc23017 + +16-Bit I/O expander (I2C) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf + +#### mcp23017Setup(pinBase, i2cAddress) + >= 1.0.0 + +### mcp23s08 + +8-Bit I/O expander (SPI) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21919e.pdf + +#### mcp23s08Setup(pinBase, spiChannel, devId) + >= 1.0.0 + +### mcp23s17 + +16-Bit I/O expander (SPI) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf + +#### mcp23s17Setup(pinBase, spiChannel, devId) + >= 1.0.0 + +### mcp3002 + +2-Channel 10-Bit ADC (SPI) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf + +#### mcp3002Setup(pinBase, spiChannel) + >= 1.0.0 + +### mcp3004/8 + +4/8-Channel 10-Bit ADC (SPI) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf + +#### mcp3004Setup(pinBase, spiChannel) + >= 1.0.0 + +### mcp3422/3/4 + +2/4-Channel 18-Bit ADC (I2C) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/22088b.pdf + +#### mcp3422Setup(pinBase, i2cAddress, sampleRate, gain) + >= 1.0.0 + +### mcp4802/12/22 + +2-Channel 8/10/12-Bit DAC (SPI) + +*Datasheet*: http://ww1.microchip.com/downloads/en/DeviceDoc/22249A.pdf + +#### mcp4802Setup(pinBase, spiChannel) + >= 1.0.0 + +### pca9685 + +16-Channel 12-Bit PWM led/servo driver (I2C) + +*Datasheet*: http://www.adafruit.com/datasheets/PCA9685.pdf + +#### pca9685Setup(pinBase, i2cAddress, frequency) + >= 1.1.0 + +### pcf8574 + +8-Bit I/O expander (I2C) + +*Datasheet*: http://www.nxp.com/documents/data_sheet/PCF8574.pdf + +#### pcf8574Setup(pinBase, i2cAddress) + >= 1.0.0 + +### pcf8591 + +8-Bit ADC and DAC (I2C) + +*Datasheet*: http://www.nxp.com/documents/data_sheet/PCF8591.pdf + +#### pcf8591Setup(pinBase, i2cAddress) + >= 1.0.0 + +### sn3218 + +18-Channel PWM led driver (I2C) + +*Datasheet*: http://www.si-en.com/uploadpdf/s2011517171720.pdf + +#### sn3218Setup(pinBase) + >= 1.0.0 + +### sr595 + +74x595 shift register + +*Datasheet*: http://www.nxp.com/documents/data_sheet/74HC_HCT595.pdf + +#### sr595Setup(pinBase, numPins, dataPin, clockPin, latchPin) + >= 1.0.0 + +--- + +## DevLib + +### ds1302 + +Trickle-charge timekeeping chip + +*Datasheet*: http://datasheets.maximintegrated.com/en/ds/DS1302.pdf + +#### ds1302setup(clockPin, dataPin, csPin) + >= 2.0.0 + +#### ds1302rtcRead(reg) + >= 2.0.0 + +#### ds1302rtcWrite(reg, data) + >= 2.0.0 + +#### ds1302ramRead(address) + >= 2.0.0 + +#### ds1302ramWrite(address, data) + >= 2.0.0 + +#### ds1302clockRead() + >= 2.0.0 + +#### ds1302clockWrite(clockData[8]) + >= 2.0.0 + +#### ds1302trickleCharge(diodes, resistors) + >= 2.0.0 + +### GertBoard + +#### getboardAnalogSetup(pinBase) + >= 2.0.0 + +pinBase is the base pin that you want the analog ports to appear as. + +The setup routine allocates 2 pins and overlays the analog to digital input pins with the digital to analog output pins. + +So reading channel pinBase + 0 reads the first analog input channel (pin DA0 on the Gertboard), and writing pinBase + 0 outputs to the first analog output channel. (Pin AD0). + +**NOTE: The analog interface chips on the Gertboard are connected to the SPI bus. You need to load the SPI kernel modules with gpio load spi and make sure that the 5 SPI jumpers are in-place on the Gertboard – pins SCLK, MOSI, MISO, CSnA and CSnB.** + +**NOTE: The analog to digital convertor is a 10-bit device. Values returned will be in the range 0-1023 representing an input voltage of 0 to 3.3 volts.** + +**NOTE: Input Voltage calculation: volts = analogIn * 3.3 / 1023** + +**NOTE: The digital to analog converter is an 8-bit device. Values sent to it should be in the range 0-255 representing an output voltage on 0 to 2.047 volts.** + +**NOTE: Output voltage calculation: volts = analogOut / 255 * 2.047** + +**NOTE: The gpio program has commands to directly read and write the analog ports on the Gertboard: gpio gbr 0 will read input channel 0, gpio gbw 1 55 will write the value 55 output channel 1.** + +### LCD + +#### lcdInit(rows, cols, bits, rs, strb, d0, d1, d2, d3, d4, d5, d6, d7) + >= 2.0.0 + +This is the main initialisation function and must be called before you use any other LCD functions. + +Rows and cols are the rows and columns on the display (e.g. 2, 16 or 4,20). + +Bits is the number of bits wide on the interface (4 or 8). + +The rs and strb represent the pin numbers of the displays RS pin and Strobe (E) pin. + +The parameters d0 through d7 are the pin numbers of the 8 data pins connected from the Pi to the display. + +Only the first 4 are used if you are running the display in 4-bit mode. + +The return value is the ‘handle’ to be used for all subsequent calls to the lcd library when dealing with that LCD, or -1 to indicate a fault. (Usually incorrect parameters) + +#### lcdHome(fd) + >= 2.0.0 + +This home the cursor + +#### lcdClear(fd) + >= 2.0.0 + +This clear the screen + +#### lcdDisplay(fd, state) + >= 2.0.0 + +This turns the display on or off + +#### lcdCursor(fd, state) + >= 2.0.0 + +This turns the cursor on or off + +#### lcdCursorBlink(fd, state) + >= 2.0.0 + +This turns blinking cursor on or off + +#### lcdSendCommand(fd, command) + >= 2.0.0 + +#### lcdPosition(fd, x, y) + >= 2.0.0 + +Set the position of the cursor for subsequent text entry. + +x is the column and 0 is the left-most edge. + +y is the line and 0 is the top line. + +#### lcdCharDef(fd, index, data[8]) + >= 2.0.0 + +This allows you to re-define one of the 8 user-definable chanracters in the display. + +The data array is 8 bytes which represent the character from the top-line to the bottom line. + +Note that the characters are actually 5×8, so only the lower 5 bits are used. + +The index is from 0 to 7 and you can subsequently print the character defined using the lcdPutchar() call. + +#### lcdPutchar(fd, character) + >= 2.0.0 + +#### lcdPuts(fd, string) + >= 2.0.0 + +#### lcdPrintf(fd, string) + >= 2.0.0 + +### LCD 128x64 + +### MaxDetect + +#### maxDetectRead(pin) + >= 2.0.0 + +#### readRHT03(pin) + >= 2.0.0 + +### piFace + +#### piFaceSetup(pinBase) + >= 2.0.0 + +pinBase is the base pin that you want your PiFace to appear as – the examples provided use 200 as the base pin. + +The setup assigns 32 pins, although the way it works is to overlay the 8 input pins with the 8 output pins. + +So you read from pin base + 0 to read the first input pin, and write to base + 0 to write to the first output pin. + +To read the state of the output latch, read from pin + 8 + outputPin. + +The remaining 16 pins are used by the underlying MCP23S17 driver and should not be used directly. + +**NOTE: The PiFace uses the MCP23S17 SPI GPIO expansion chip so you need to load the SPI kernel driver first. Use the gpio command: gpio load spi** + +**NOTE: If you want to use the input pins as outputs, then you need to use the mcp23s17 expansion module for wiringPI instead of the piFace expansion. Then setting up is relatively straighforward – pins 0 through 7 are the output pins, and 8 through 15 are the normal input pins which you can use pinMode() on to change to outputs, if required.** + +**NOTE: The gpio command supports the PiFace board directly using the -p flag, but assumes the pin-base is 200. So gpio -p write 200 1 will set the first output pin high – that’s the first relay.** + +### piGlow + +#### piGlowSetup(clear) + >= 2.0.0 + +This initialises the PiGlow devLib software. + +You need to make sure the I2C kernel module is pre-loaded and if you have not used the gpio program to load it, then you may have to run your program as root (ie. with sudo) + +The clear parameter is TRUE or FALSE. + +If TRUE, then all the LEDs will be turned off to start with. + +**NOTE: You need to load the I2C kernel modules before you can use I2C devices. Use the gpio command: gpio load i2c** + +**NOTE: If this is the only I2C device on your Pi (and it almost certianly will be unless you’re using some sort of break-out connector!), then it will run at 400KHz, so try: gpio load i2c 400** + +**NOTE: Use the i2cdetect program to scan your I2C bus to make sure the Pi can see the SN3218 which will show up as 0×54.** + +**NOTE: If you have a Rev 1 Pi, then the i2cdetect command is: i2cdetect -q -y 0 if you have a Rev. 2 Pi, then use i2cdetect -q -y 1** + +**NOTE: The gpio command supports the i2cdetect command and automatically caters for board revision. Simply type: gpio i2cd** + +**NOTE: The wiringPi SN3218 driver knows which revision Pi you have, so you know need to take any special precautions – your code will work on either a Revision 1 or 2 Pi.** + +**NOTE: Internally the PiGlow devLib extension adds 18 more pins to wiringPi’s pin map. These pin are normally at location 577. This should not be an issue as the PiGlow is designed to be the only peripheral on the Pi, but if you have used a breakout board to add other devices to it, then you should pick a pinBase that’s outside the range 577 through 595.** + +#### piGlow1(leg, ring, intensity) + >= 2.0.0 + +This lights up an individual LED to the intensity given. + +The leg and ring parameters specify the LED to set. + +#### piGlowLeg(leg, intensity) + >= 2.0.0 + +This will light up all 6 LEDs on the given led (0, 1 or 2) to the supplied intensity. + +The leg number will depend on which way up you have the Pi, but leg 0 is normally the one that points to the same edge the composite video connector in on, 1 is to the right (clockwise) and 2 is to the left (anticlockwise) + +#### piGlowRing(ring, intensity) + >= 2.0.0 + +This will light up all 3 LEDs on the given ring at the given intensity – 0 (off) to 255 (really bright!) The ring number is 0 from the outside to 5 for the inside. + +You can use the constants: + +* `PIGLOW_RED` +* `PIGLOW_YELLOW` +* `PIGLOW_ORANGE` +* `PIGLOW_GREEN` +* `PIGLOW_BLUE` +* `PIGLOW_WHITE` + +### piNes + +#### setupNesJoystick(dPin, cPin, lPin) + >= 2.0.0 + +#### readNesJoystick(joystick) + >= 2.0.0 + +### tcs34725 + +Color light-to-digital converter with IR filter + +*Datasheet*: http://www.adafruit.com/datasheets/TCS34725.pdf + +#### tcs34725Setup(i2cAddress, integrationTime, gain) + >= 2.0.0 + +Initialize the device and returns the assigned id. +Don't forget to call `tcs34725Enable`, the device is in power sleep mode after initialization. + +#### tcs34725ReadRGBC(id) + >= 2.0.0 + +Read the raw red, green, blue and clear channel values (0 - 255) + +#### tcs34725ReadHSV(id) + >= 2.0.0 + +Returns the cylindrical-coordinate representation of the sensor red, green and blue channels. + +#### tcs34725GetCorrelatedColorTemperature(r, g, b) + >= 2.0.0 + +Convert the raw R/G/B values to color temperature in degrees Kelvin + +#### tcs34725GetIlluminance(r, g, b) + >= 2.0.0 + +Convert the raw R/G/B values to illuminance in Lux + +#### tcs34725SetInterrupt(id, aien) + >= 2.0.0 + +Enable/Disable interrupt + +#### tcs34725ClearInterrupt(id) + >= 2.0.0 + +Clear interrupt + +#### tcs34725SetInterruptLimits(id, low, high) + >= 2.0.0 + +#### tcs34725Enable(id) + >= 2.0.0 + +Enable the device + +#### tcs34725Disable(id) + >= 2.0.0 + +Disable the device (putting it in lower power sleep mode) diff --git a/README.md b/README.md index 2572085..0b563e9 100644 --- a/README.md +++ b/README.md @@ -1,258 +1,21 @@ -Node.js bindings to [wiringPi](https://projects.drogon.net/raspberry-pi/wiringpi/) +Node.js bindings to [wiringPi](http://www.wiringpi.com) Based on the awesome work of [Soarez](https://github.com/Soarez/node-wiring-pi) ## Install - > npm install wiring-pi - -## Use - -```javascript -var wpi = require('wiring-pi'); -``` -## Setup - -### `wpi.setup([mode])` - -An handy function to setup wiringPi - -```javascript -wpi.setup(); -``` - -```javascript -wpi.setup('gpio'); -``` - -Valid Modes: - -- `wpi`: sets up pin numbering with `wiringPiSetup` -- `gpio`: sets up pin numbers with `wiringPiSetupGpio` -- `sys`: sets up pin numbers with `wiringPiSetupSys` -- `phys`: sets up pin numbers with `wiringPiSetupPhys` - -See [wiringPi Pins](http://wiringpi.com/pins/) for the differences in Pin numbering; - -### `wpi.wiringPiSetup()` - -Initialises wiringPi and assumes that the calling program is going to be using the wiringPi pin numbering scheme. -This is a simplified numbering scheme which provides a mapping from virtual pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. -see the pins page (https://projects.drogon.net/raspberry-pi/wiringpi/pins/) for a table which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location on the edge connector. -This function needs to be called with root privileges. - -```javascript -wpi.wiringPisetup(); -``` - -### `wpi.wiringPiSetupGpio()` - -This is indential to above, however it allows the calling programs to use the Broadcom GPIO pin numbers directly with no re-mapping. -As above, this function needs to be called with root privileges, and note that some pins are different from revision 1 to revision 2 boards. - -```javascript -wpi.wiringPisetupGpio(); -``` - -### `wpi.wiringPiSetupPhys()` - -Identical to above, however it allows the calling programs to use the physical pin numbers on the P1 connector only. -As above, this function needs to be called with root priviliges. - -```javascript -wpi.wiringPisetupPhys(); ``` - -### `wpi.wiringPiSetupSys()` - -This initialises wiringPi but uses the /sys/class/gpio interface rather than accessing the hardware directly. This can be called as a non-root user provided the GPIO pins have been exported before-hand using gpio program. Pin numbering in this mode is the native Broadcom GPIO numbers - the same as wiringPiSetGpio above, so be aware of the differences between Rev 1 and Rev 2 boards. -Note: In this mode you can only use the pins which have been exported via the /sys/class/gpio interface before you run your program. -You can do this in a seperate shell script, or by using the system() function from inside your program to call the gpio program. -Also note that some functions have no effect when using this mode as they're not currently possible to action unless called with root privileges. (although you can use system() to call gpio to set/change modes if needed). - -```javascript -wpi.wiringPisetupSys(); -``` - -## Core functions - -### `wpi.pinModeAlt(pin, mode)` - -This is an un-documented special to let you set any pin to any mode. - -- `pin`: pin number -- `mode`: `wpi.WPI_MODE_PINS`, `wpi.WPI_MODE_PHYS` or `wpi.WPI_MODE_GPIO` - -### `wpi.pinMode(pin, mode)` - -This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. -Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK output modes. -This function has no effect when in Sys mode. If you need to change the pin mode, the you can do it with the gpio program in a script before you start your program. - -```javascript -wpi.pinMode(0, wpi.modes.OUTPUT); -``` - -- `pin`: pin number -- `mode`: `wpi.modes.INPUT`, `wpi.modes.OUTPUT`, `wpi.modes.PWM_OUTPUT` or `wpi.modes.GPIO_CLOCK` - -### `wpi.pullUpDnControl(pin, pud)` - -This sets the pull-up or pull-down resistor mode on the given pin, which should be set as an input. Unlike Arduino, the BCM2835 has both pull-up and down internal resistors. -The parameter pud should be; PUD_OFF (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v). -The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi. - -```javascript -wpi.pullUpDnControl(0, wpi.PUD_DOWN); +npm install wiring-pi ``` -- `pin`: pin number -- `pud`: `wpi.PUD_OFF`, `wpi.PUD_DOWN`, `wpi.PUD_UP` - -### `wpi.digitalRead(pin)` - -This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) depending on the logic level at the pin. - -```javascript -wpi.digitalRead(0); -//=> 1 -``` - -- `pin`: pin number - -### `wpi.digitalWrite(pin, value)` - -Write the value HIGH or LOW (1 or 0) to the given pin which must have been previously set as an output. -WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW. - -```javascript -wpi.digitalWrite(0, wpi.HIGH); -``` +## Usage ```javascript -wpi.digitalWrite(0, wpi.LOW); -``` - -- `pin`: pin number -- `value`: 0 (`wpi.LOW`) or 1 (`wpi.HIGH`) - -### `wpi.pwmWrite(pin, value)` - -Writes the value to the PWM register for the given pin. The Raspberry Pi has one on-board PWM pin, pin 1 (BCM_GPIO 18, Phys 12) and the range is 0-1024. -Other PWM devices may have other PWM ranges. -This function is not able to control the Pi's on-board PWM when in Sys mode. - -```javascript -wpi.pwmWrite(0, 512); -``` - -- `pin`: pin number -- `value`: value in PWM ranges - -### `wpi.analogRead(pin)` - -This returns the value read on the supplied analog input pin. You will need to register additional analog modules to enable this function for device such as the Gertboard, quick2Wire analog board, etc. - -```javascript -wpi.analogRead(0); -//=> 512 -``` - -- `pin`: pin number - -### `wpi.analogWrite(pin, value)` - -This writes the given value to the supplied analog pin. You will need to register additional analog modules to enable this function for devices such as the Gertboard. - -```javascript -wpi.analogWrite(0, 512); -``` - -- `pin`: pin number -- `value`: value - -## Raspberry Pi specifics - -### `wpi.piBoardRev()` - -This returns the board revision of the Raspberry Pi. It will be either 1 or 2. -Some of the BCM_GPIO pins changed number and function when moving from board revision 1 to 2, so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences. - -```javascript -wpi.piBoardRev(); -//=>2 -``` - -### `wpi.wpiPinToGpio(pin)` - -This returns the BCM_GPIO pin number of the supplied wiringPi pin. -It takes the board revision into account. - -```javascript -wpi.wpiPinToGpio(7); -//=>4 -``` - -- `pin`: pin number in WiringPi scheme - -### `wpi.physPinToGpio(pin)` - -This returns the BCM_GPIO pin number of the suppled physical pin on the P1 connector. - -```javascript -wpi.wpiPinToGpio(23); -//=>11 -``` - -- `pin`: pin number in physical scheme - -### `wpi.setPadDrive(group, value)` - -This sets the "strength" of the pad drivers for a particular group of pins. -There are 3 groups of pins and the drive strength is from 0 to 7. Do not use the unless you know what you are doing. - -### `wpi.getAlt(pin)` - -Returns the ALT bits for a given port. Only really of-use for the gpio readall command (I think). - -### `wpi.digitalWriteByte(value)` - -This writes the 8-bit byte supplied to the first 8 GPIO pins. -It’s the fastest way to set all 8 bits at once to a particular value, although it still takes two write operations to the Pi’s GPIO hardware. - -```javascript -wpi.digitalWriteByte(0xFF); //set the first 8 GPIO pins to HIGH -``` - -- `value`: the byte to write to the first 8 GPIO pins - -### `wpi.pwmSetMode(mode)` - -The PWM generator can run in 2 modes – “balanced” and “mark:space”. -The mark:space mode is traditional, however the default mode in the Pi is “balanced”. -You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS. - -```javascript -wpi.pwmSetMode(wpi.PWM_MODE_BAL); +var wpi = require('wiring-pi'); ``` +## Documentation -- `mode`: `wpi.PWM_MODE_BAL` or `wpi.PWM_MODE_MS` - -### `wpi.pwmSetRange(range)` - -This sets the range register in the PWM generator. The default is 1024. -Note: The PWM control functions can not be used when in Sys mode. -To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual. - -### `wpi.pwmSetClock(divisor)` - -This sets the divisor for the PWM clock. -Note: The PWM control functions can not be used when in Sys mode. -To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual. - -### `wpi.gpioClockSet(pin, freq)` - -Set the frequency on a GPIO clock pin +See the [DOCUMENTATION.md](https://github.com/eugeneware/wiring-pi/blob/master/DOCUMENTATION.md) file for more detailed documentation. ## Contributing @@ -266,8 +29,8 @@ See the [CONTRIBUTING.md](https://github.com/eugeneware/wiring-pi/blob/master/CO wiring-pi is only possible due to the excellent work of the following contributors: - - - - -
Igor Soarez (Creator)GitHub/SoarezTwitter/@igorsoarez
Gohy LeandreGitHub/nekuz0rTwitter/@LeandreGohy
Eugene WareGitHub/eugenewareTwitter/@eugeneware
+Contributor | GitHub profile | Twitter profile | +--- | --- | --- +Igor Soarez (Creator) | [Soarez](https://github.com/Soarez) | [@igorsoarez](https://twitter.com/igorsoarez) +Leandre Gohy | [nekuz0r](https://github.com/nekuz0r) | [@LeandreGohy](http://twitter.com/LeandreGohy) +Eugene Ware | [eugeneware](https://github.com/eugeneware) | [@eugeneware](http://twitter.com/eugeneware) diff --git a/binding.gyp b/binding.gyp index 8b110d9..682c95e 100644 --- a/binding.gyp +++ b/binding.gyp @@ -3,13 +3,57 @@ { 'target_name': 'wiringPi', 'sources': [ - 'src/bindings.cc' + 'src/addon.cc', + + 'src/wiringPi.cc', + 'src/softPwm.cc', + 'src/softServo.cc', + 'src/softTone.cc', + 'src/wiringPiI2C.cc', + 'src/wiringPiSPI.cc', + 'src/wiringSerial.cc', + 'src/wiringShift.cc', + 'src/wiringPiISR.cc', + 'src/wpi.cc', + + 'src/extensions/extensions.cc', + 'src/extensions/drcSerial.cc', + 'src/extensions/max5322.cc', + 'src/extensions/max31855.cc', + 'src/extensions/mcp23s08.cc', + 'src/extensions/mcp23s17.cc', + 'src/extensions/mcp3002.cc', + 'src/extensions/mcp3004.cc', + 'src/extensions/mcp3422.cc', + 'src/extensions/mcp4802.cc', + 'src/extensions/mcp23008.cc', + 'src/extensions/mcp23016.cc', + 'src/extensions/mcp23017.cc', + 'src/extensions/pcf8574.cc', + 'src/extensions/pcf8591.cc', + 'src/extensions/sn3218.cc', + 'src/extensions/sr595.cc', + 'src/extensions/pca9685.cc', + 'src/extensions/dac7678.cc', + + 'src/devlib/devlib.cc', + 'src/devlib/ds1302.cc', + 'src/devlib/gertboard.cc', + 'src/devlib/lcd.cc', + 'src/devlib/lcd128x64.cc', + 'src/devlib/maxdetect.cc', + 'src/devlib/piFace.cc', + 'src/devlib/piGlow.cc', + 'src/devlib/piNes.cc', + 'src/devlib/tcs34725.cc' ], 'include_dirs': [ - 'wiringpi/wiringPi' + 'wiringpi/wiringPi', + 'wiringpi/devLib' ], 'libraries': [ - '/dev/null 1>&2 + +echo -n "Cloning libWiringPi ... " +rm -Rf ./wiringpi 2>/dev/null 1>&2 +git clone https://github.com/nekuz0r/wiringpi.git > ./install.log 2>&1 +check_git_clone +#git submodule init +#check_git_clone +#git submodule update +#check_git_clone +echo "done." + +patch ./wiringpi/devLib/Makefile < ./patchs/devLib_Makefile.patch +patch ./wiringpi/gpio/Makefile < ./patchs/gpio_Makefile.patch + +echo -n "Making libWiringPi ... " cd ./wiringpi/wiringPi/ -make static +make clean >> ../../install.log 2>&1 +make static >> ../../install.log 2>&1 +check_make_ok "libWiringPi" 1 +cd ../../ +echo "done." + +cd ./wiringpi/devLib/ +echo -n "Making devLib ..." +make clean >> ../../install.log 2>&1 +make static >> ../../install.log 2>&1 +check_make_ok "devLib" 0 cd ../../ -node-gyp rebuild \ No newline at end of file +echo "done." + +cd ./wiringpi/gpio/ +echo -n "Unistalling gpio utility ... " +sudo make uninstall >> ../../install.log 2>&1 +echo "done." + +echo -n "Making gpio utility ... " +make clean >> ../../install.log 2>&1 +make >> ../../install.log 2>&1 +check_make_ok "gpio utility" 0 +echo "done." + +echo -n "Installing gpio utility ... " +sudo make install >> ../../install.log 2>&1 +check_make_ok "gpio utility" 0 +cd ../../ +echo "done." + +echo -n "Making wiring-pi ... " +node-gyp rebuild 2>&1 | tee -a ./install.log +check_make_ok "wiring-pi" 1 +echo "done." + +echo "Enjoy !" diff --git a/lib/exports.js b/lib/exports.js index f993c90..7e6aa8b 100644 --- a/lib/exports.js +++ b/lib/exports.js @@ -1,137 +1,2 @@ -var c = require('../build/Release/wiringPi'); - -function noop() {} - -function extend(source, destination) { - var property; - for (property in source) { - destination[property] = source[property]; - } - return destination; -} - -exports = { - VERSION: require('../package').version, - - // Handy defines - NUM_PINS: 17, //Deprecated - WPI_MODE_PINS: 0, - WPI_MODE_GPIO: 1, - WPI_MODE_GPIO_SYS: 2, - WPI_MODE_PHYS: 3, - WPI_MODE_PIFACE: 4, - WPI_MODE_UNINITIALISED: -1, - - // Pin modes - INPUT: 0, - OUTPUT: 1, - PWM_OUTPUT: 2, - GPIO_CLOCK: 3, - SOFT_PWM_OUTPUT: 4, - SOFT_TONE_OUTPUT: 5, - LOW: 0, - HIGH: 1, - - // Pull up/down/none - PUD_OFF: 0, - PUD_DOWN: 1, - PUD_UP: 2, - - // PWM - PWM_MODE_MS: 0, - PWM_MODE_BAL: 1, - - // Interrupt levels - INT_EDGE_SETUP: 0, - INT_EDGE_FALLING: 1, - INT_EDGE_RISING: 2, - INT_EDGE_BOTH: 3, - - // Backward compatibility - modes: { - INPUT: 0, - OUTPUT: 1, - PWM_OUTPUT: 2 - }, - pull: { - OFF: 0, - DOWN: 1, - UP: 2 - }, - - // Extensions - - // WiringPiShift - LSBFIRST: 0, - MSBFIRST: 1, - - // PI Model type - PI_MODEL_A: 0, - PI_MODEL_B: 1, - PI_MODEL_CM: 2, - - // PI Model names - PI_MODEL_NAMES: [ - "Model A", - "Model B", - "Compute Module" - ], - - // PI Revision names - PI_REVISION_NAMES: [ - "1", - "1.1", - "2" - ], - - // PI Compute revision names - PI_COMPUTE_REVISION_NAMES: [ - - ], - - //MCP3422 - MCP3422_SR_3_75: 3, - MCP3422_SR_15: 2, - MCP3422_SR_60: 1, - MCP3422_SR_240: 0, - - MCP3422_GAIN_1: 0, - MCP3422_GAIN_2: 1, - MCP3422_GAIN_4: 2, - MCP3422_GAIN_8: 3, -}; - -// Extends exports with properties of 'c' -extend(c, exports); - -// Handy function to setup wiringPi -exports.setup = function setup(mode) { - - if (mode === undefined) - mode = 'wpi'; - - if (typeof mode == 'string') - mode = mode.toLowerCase(); - - var setup; - if (mode === 'wpi') - setup = 'wiringPiSetup'; - else if (mode === 'gpio') - setup = 'wiringPiSetupGpio'; - else if (mode === 'sys') - setup = 'wiringPiSetupSys'; - else if (mode === 'phys') - setup = 'wiringPiSetupPhys'; - else throw new Error('Invalid argument'); - - // libWiringPi v2 setup functions always returns 0, so this check is kind of useless, unless v1 behaviour is restored - // NOTE: If you want to restore the v1 behaviour, then you need to set the - // environment variable: WIRINGPI_CODES (to any value, it just needs to exist) - if (c[setup]() == -1) { - throw new Error('wiringPiSetup failed'); - } - - exports.setup = noop; -}; - -module.exports = exports; +module.exports = require('../build/Release/wiringPi'); +module.exports.VERSION = require('../package').version; \ No newline at end of file diff --git a/package.json b/package.json index a5be35d..88eed48 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wiring-pi", - "version": "1.1.2", + "version": "2.0.0", "description": "Bindings to wiringPi", "main": "lib/exports.js", "scripts": { @@ -21,7 +21,8 @@ ], "author": "Igor Soarez ", "contributors": [ - "Leandre Gohy " + "Leandre Gohy ", + "Eugene Ware " ], "license": "BSD" } diff --git a/patchs/devLib_Makefile.patch b/patchs/devLib_Makefile.patch new file mode 100644 index 0000000..8ae4125 --- /dev/null +++ b/patchs/devLib_Makefile.patch @@ -0,0 +1,19 @@ +--- Makefile_org 2014-07-04 09:48:18.000000000 +0200 ++++ Makefile 2014-07-04 10:12:15.000000000 +0200 +@@ -26,6 +26,7 @@ + VERSION=$(DYN_VERS_MAJ).$(DYN_VERS_MIN) + DESTDIR=/usr + PREFIX=/local ++PWD=`pwd` + + STATIC=libwiringPiDev.a + DYNAMIC=libwiringPiDev.so.$(VERSION) +@@ -33,7 +34,7 @@ + #DEBUG = -g -O0 + DEBUG = -O2 + CC = gcc +-INCLUDE = -I. ++INCLUDE = -I. -I$(PWD)/../wiringPi + CFLAGS = $(DEBUG) -Wformat=2 -Wall $(INCLUDE) -Winline -pipe -fPIC + + LIBS = diff --git a/patchs/gpio_Makefile.patch b/patchs/gpio_Makefile.patch new file mode 100644 index 0000000..e50bfe0 --- /dev/null +++ b/patchs/gpio_Makefile.patch @@ -0,0 +1,20 @@ +--- Makefile_org 2014-07-04 09:58:05.000000000 +0200 ++++ Makefile 2014-07-04 10:13:01.000000000 +0200 +@@ -25,14 +25,15 @@ + + DESTDIR=/usr + PREFIX=/local ++PWD=`pwd` + + #DEBUG = -g -O0 + DEBUG = -O2 + CC = gcc +-INCLUDE = -I$(DESTDIR)$(PREFIX)/include ++INCLUDE = -I$(PWD)/../wiringPi -I$(PWD)/../devLib + CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe + +-LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib ++LDFLAGS = -L$(PWD)/../wiringPi -L$(PWD)/../devLib + LIBS = -lwiringPi -lwiringPiDev -lpthread -lm + + # May not need to alter anything below this line diff --git a/src/addon.cc b/src/addon.cc new file mode 100644 index 0000000..ab1dec3 --- /dev/null +++ b/src/addon.cc @@ -0,0 +1,31 @@ +#include "addon.h" +#include +#include + +bool find_string(const char* string, const char* array[], size_t s) { + for (size_t i = 0; i < s; i++) { + if (!strcasecmp(string, array[i])) { + return true; + } + } + return false; +} + +bool find_int(const int value, const int array[], size_t s) { + for (size_t i = 0; i < s; i++) { + if (value == array[i]) { + return true; + } + } + return false; +} + +void throw_error(const char* format, ...) { + char buffer[256]; + va_list args; + va_start(args, format); + vsnprintf(buffer, 156, format, args); + va_end(args); + + v8::ThrowException(v8::Exception::Error(v8::String::New(buffer))); +} \ No newline at end of file diff --git a/src/addon.h b/src/addon.h new file mode 100644 index 0000000..666f552 --- /dev/null +++ b/src/addon.h @@ -0,0 +1,149 @@ +#ifndef _ADDON_H_ +#define _ADDON_H_ + + #include + + using namespace v8; + + // We don't want to include the whole node headers :) + namespace node { + namespace Buffer { + bool HasInstance(v8::Handle val); + bool HasInstance(v8::Handle val); + char* Data(v8::Handle val); + char* Data(v8::Handle val); + size_t Length(v8::Handle val); + size_t Length(v8::Handle val); + } + } + + bool find_string(const char* string, const char* array[], size_t s); + bool find_int(const int value, const int array[], size_t s); + void throw_error(const char* fmt, ...); + + #define DECLARE(name) \ + namespace nodemodule { \ + static v8::Handle name(const v8::Arguments& args); \ + } + + #define IMPLEMENT(name) \ + v8::Handle nodemodule::name(const v8::Arguments& args) + + #define EXPORT_FUNCTION(name) \ + target->Set(v8::String::NewSymbol(#name), \ + v8::FunctionTemplate::New(nodemodule::name)->GetFunction()) + + #define EXPORT_CONSTANT_INT(name) \ + target->Set(v8::String::NewSymbol(#name), \ + v8::Int32::New(name), static_cast(v8::ReadOnly | v8::DontDelete)); + + #define EXPORT_CONSTANT_STRING(name) \ + target->Set(v8::String::NewSymbol(#name), \ + v8::String::New(name), static_cast(v8::ReadOnly | v8::DontDelete)); + + #define EXPORT_CONSTANT_INT_ARRAY(name, array, length) \ + { \ + v8::Local arr = v8::Array::New(); \ + for (int i = 0; i < length; i++) { \ + arr->Set(i, v8::Int32::New(array[i])); \ + } \ + target->Set(v8::String::NewSymbol(#name), arr, static_cast(v8::ReadOnly | v8::DontDelete)); \ + } + + #define EXPORT_CONSTANT_STRING_ARRAY(name, array, length) \ + { \ + v8::Local arr = v8::Array::New(); \ + for (int i = 0; i < length; i++) { \ + arr->Set(i, v8::String::New(array[i])); \ + } \ + target->Set(v8::String::NewSymbol(#name), arr, static_cast(v8::ReadOnly | v8::DontDelete)); \ + } + + #define NODE_MODULE_INIT() \ + namespace nodemodule { \ + void init(v8::Handle target); \ + } \ + void nodemodule::init(v8::Handle target) + #define NODE_MODULE_DECLARE(name) NODE_MODULE(name, nodemodule::init) + #define IMPLEMENT_EXPORT_INIT(name) void nodemodule::init##name(v8::Handle target) + #define DECLARE_EXPORT_INIT(name) \ + namespace nodemodule { \ + void init##name(v8::Handle target); \ + } + + #define INIT(name) nodemodule::init##name(target); + + #define SCOPE_OPEN() v8::HandleScope scope + #define SCOPE_CLOSE(obj) return scope.Close(obj) + + #define UNDEFINED() v8::Undefined() + #define INT32(v) v8::Int32::New(v) + #define UINT32(v) v8::Uint32::New(v) + #define STRING(v) v8::String::New(v) + + #define THROW_ERROR(fmt, ...) \ + throw_error(fmt, __VA_ARGS__); \ + SCOPE_CLOSE(UNDEFINED()) + + #define SET_ARGUMENT_NAME(id, name) static const char* arg##id = #name + #define GET_ARGUMENT_NAME(id) arg##id + + #define CHECK_ARGUMENTS_LENGTH_EQUAL(length) \ + if (args.Length() != length) { \ + THROW_ERROR("%s: arguments.length => (%i === %i) === false", __func__, args.Length(), length); \ + } + + #define CHECK_ARGUMENT_TYPE(id, istype) \ + if (!args[id]->istype()) { \ + THROW_ERROR("%s: %s(arguments['%s']) === false", __func__, #istype, GET_ARGUMENT_NAME(id)); \ + } + + #define CHECK_ARGUMENT_TYPE_ARRAY(id) CHECK_ARGUMENT_TYPE(id, IsArray) + #define CHECK_ARGUMENT_TYPE_INT32(id) CHECK_ARGUMENT_TYPE(id, IsInt32) + #define CHECK_ARGUMENT_TYPE_UINT32(id) CHECK_ARGUMENT_TYPE(id, IsUint32) + #define CHECK_ARGUMENT_TYPE_NUMBER(id) CHECK_ARGUMENT_TYPE(id, IsNumber) + #define CHECK_ARGUMENT_TYPE_STRING(id) CHECK_ARGUMENT_TYPE(id, IsString) + #define CHECK_ARGUMENT_TYPE_FUNCTION(id) CHECK_ARGUMENT_TYPE(id, IsFunction) + #define CHECK_ARGUMENT_TYPE_OBJECT(id) CHECK_ARGUMENT_TYPE(id, IsObject) + #define CHECK_ARGUMENT_TYPE_NODE_BUFFER(id) \ + if (!(args[id]->IsObject() && node::Buffer::HasInstance(args[id]))) { \ + THROW_ERROR("%s: %s(arguments['%s']) === false", __func__, "isBuffer", GET_ARGUMENT_NAME(id)); \ + } + + #define CHECK_ARGUMENT_ARRAY_LENGTH(id, length) \ + if (!(v8::Local::Cast(args[id])->Length() == length)) { \ + THROW_ERROR("%s: (arguments['%s'].length === %i) === false", __func__, GET_ARGUMENT_NAME(id), length); \ + } + + #define GET_ARGUMENT_AS_TYPE(id, type) args[id]->type() + + #define GET_ARGUMENT_AS_INT32(id) GET_ARGUMENT_AS_TYPE(id, Int32Value) + #define GET_ARGUMENT_AS_UINT32(id) GET_ARGUMENT_AS_TYPE(id, Uint32Value) + #define GET_ARGUMENT_AS_NUMBER(id) GET_ARGUMENT_AS_TYPE(id, NumberValue) + #define GET_ARGUMENT_AS_STRING(id) GET_ARGUMENT_AS_TYPE(id, ToString) + #define GET_ARGUMENT_AS_LOCAL_FUNCTION(id) v8::Local::Cast(args[id]) + #define GET_ARGUMENT_AS_PERSISTENT_FUNCTION(id) v8::Persistent::New(GET_ARGUMENT_AS_LOCAL_FUNCTION(id)) + + #define LIST(...) { __VA_ARGS__ } + #define CHECK_ARGUMENT_IN_STRINGS(id, value, T) \ + { \ + static const char* strings[] = LIST T; \ + if (!find_string(*value, strings, sizeof(strings) / sizeof(char*))) { \ + THROW_ERROR("%s: arguments['%s'] => (\"%s\" in %s) === false", __func__, GET_ARGUMENT_NAME(id), *value, #T); \ + } \ + } + + #define CHECK_ARGUMENT_IN_INTS(id, value, T) \ + { \ + static const int ints[] = LIST T; \ + if (!find_int(value, ints, sizeof(ints) / sizeof(int))) { \ + THROW_ERROR("%s: arguments['%s'] => (%i in %s) === false", __func__, GET_ARGUMENT_NAME(id), value, #T); \ + } \ + } + + #define CHECK_ARGUMENT_IN_RANGE(id, value, min, max) \ + if (value < min || value > max) { \ + THROW_ERROR("%s: arguments['%s'] => inRange(%i, [%i, %i]) === false", __func__, GET_ARGUMENT_NAME(id), value, min, max); \ + } + +#endif diff --git a/src/bindings.cc b/src/bindings.cc deleted file mode 100644 index c372009..0000000 --- a/src/bindings.cc +++ /dev/null @@ -1,2498 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace v8; - -#define DECLARE(name) \ - static Handle name(const Arguments& args) -#define IMPLEMENT(name) \ - Handle wpi::name(const Arguments& args) -#define EXPORT(name) \ - target->Set(String::NewSymbol(#name), \ - FunctionTemplate::New(wpi::name)->GetFunction()) - -namespace wpi { - // Setup - DECLARE(wiringPiSetup); - DECLARE(wiringPiSetupGpio); - DECLARE(wiringPiSetupSys); - DECLARE(wiringPiSetupPhys); - - // Core wiringPi functions - DECLARE(pinModeAlt); - DECLARE(pinMode); - DECLARE(pullUpDnControl); - DECLARE(digitalRead); - DECLARE(digitalWrite); - DECLARE(pwmWrite); - DECLARE(analogRead); - DECLARE(analogWrite); - DECLARE(pulseIn); - - DECLARE(delay); - DECLARE(delayMicroseconds); - DECLARE(millis); - DECLARE(micros); - - // PiFace specifics (Deprecated) - //DECLARE(wiringPiSetupPiFace); - //DECLARE(wiringPiSetupPiFaceForGpioProg); // Don't use this - for gpio program only - - // On-Board Rasberry Pi hardware specific stuff - DECLARE(piBoardRev); - DECLARE(piBoardId); - DECLARE(wpiPinToGpio); - DECLARE(physPinToGpio); - DECLARE(setPadDrive); - DECLARE(getAlt); - DECLARE(digitalWriteByte); - DECLARE(pwmSetMode); - DECLARE(pwmSetRange); - DECLARE(pwmSetClock); - DECLARE(gpioClockSet); - - // Extensions - DECLARE(drcSetupSerial); - DECLARE(max5322Setup); - DECLARE(max31855Setup); - DECLARE(mcp23s08Setup); - DECLARE(mcp23s17Setup); - DECLARE(mcp3002Setup); - DECLARE(mcp3004Setup); - DECLARE(mcp3422Setup); - DECLARE(mcp4802Setup); - DECLARE(mcp23008Setup); - DECLARE(mcp23016Setup); - DECLARE(mcp23017Setup); - DECLARE(pcf8574Setup); - DECLARE(pcf8591Setup); - DECLARE(sn3218Setup); - DECLARE(sr595Setup); - DECLARE(pca9685Setup); - - // Soft PWM - DECLARE(softPwmCreate); - DECLARE(softPwmWrite); - DECLARE(softPwmStop); - - // Soft Servo - DECLARE(softServoWrite); - DECLARE(softServoSetup); - - // Soft Tone - DECLARE(softToneCreate); - DECLARE(softToneWrite); - DECLARE(softToneStop); - - // WiringPI I2C - DECLARE(wiringPiI2CRead); - DECLARE(wiringPiI2CReadReg8); - DECLARE(wiringPiI2CReadReg16); - DECLARE(wiringPiI2CWrite); - DECLARE(wiringPiI2CWriteReg8); - DECLARE(wiringPiI2CWriteReg16); - DECLARE(wiringPiI2CSetupInterface); - DECLARE(wiringPiI2CSetup); - - // WiringPI SPI - DECLARE(wiringPiSPIGetFd); - DECLARE(wiringPiSPIDataRW); - DECLARE(wiringPiSPISetup); - - // WiringPi Serial - DECLARE(serialOpen); - DECLARE(serialClose); - DECLARE(serialFlush); - DECLARE(serialPutchar); - DECLARE(serialPuts); - DECLARE(serialPrintf); - DECLARE(serialDataAvail); - DECLARE(serialGetchar); - - // WiringPi Shift - DECLARE(shiftIn); - DECLARE(shiftOut); -} - -// === Setup === - -// Func : int wiringPiSetup(void) -// Returns : error code if v1 mode otherwise always returns 0 -// Description : Initialises wiringPi and assumes that the calling program is going -// to be using the wiringPi pin numbering scheme. -// This is a simplified numbering scheme which provides a mapping from virtual -// pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. -// see the pins page (https://projects.drogon.net/raspberry-pi/wiringpi/pins/) for a table -// which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location -// on the edge connector. -// This function needs to be called with root privileges. - -IMPLEMENT(wiringPiSetup) { - HandleScope scope; - int res; - - // CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSetup(); - - return scope.Close(Int32::New(res)); -} - -// Func : int wiringPiSetupGpio(void) -// Returns : error code if v1 mode otherwise always returns 0 -// Description : This is indential to above, however it allows the calling programs to use -// the Broadcom GPIO pin numbers directly with no re-mapping. -// As above, this function needs to be called with root privileges, and note that some pins -// are different from revision 1 to revision 2 boards. - -IMPLEMENT(wiringPiSetupGpio) { - HandleScope scope; - int res; - - // CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSetupGpio(); - - return scope.Close(Int32::New(res)); -} - -// Func : int wiringPiSetupPhys(void) -// Returns : error code if v1 mode otherwise always returns 0 -// Description : Identical to above, however it allows the calling programs to use -// the physical pin numbers on the P1 connector only. -// As above, this function needs to be called with root priviliges. - -IMPLEMENT(wiringPiSetupPhys) { - HandleScope scope; - int res; - - // CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSetupPhys(); - - return scope.Close(Int32::New(res)); -} - -// Func : int wiringPiSetupSys(void) -// Returns : error code if v1 mode otherwise always returns 0 -// Description : This initialises wiringPi but uses the /sys/class/gpio interface rather than -// accessing the hardware directly. This can be called as a non-root user provided the GPIO pins -// have been exported before-hand using gpio program. Pin numbering in this mode is the native -// Broadcom GPIO numbers - the same as wiringPiSetGpio above, so be aware of the differences -// between Rev 1 and Rev 2 boards. -// Note: In this mode you can only use the pins which have been exported via the -// /sys/class/gpio interface before you run your program. You can do this in a seperate -// shell script, or by using the system() function from inside your program to call the gpio program. -// Also note that some functions have no effect when using this mode as they're not currently -// possible to action unless called with root privileges. (although you can use system() to call -// gpio to set/change modes if needed). - -IMPLEMENT(wiringPiSetupSys) { - HandleScope scope; - int res; - - // CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSetupSys(); - - return scope.Close(Int32::New(res)); -} - -// === Core functions === - -// Func : void pinModeAlt(int pin, int mode) -// Description : This is an un-documented special to let you set any pin to any mode. -// Modes are WPI_MODE_PINS, WPI_MODE_PHYS, WPI_MODE_GPIO. - -IMPLEMENT(pinModeAlt) { - HandleScope scope; - int pin; - int mode; - - // CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument types. Numbers expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - mode = args[1]->NumberValue(); - - // CHECK: Allowed values - if (mode != WPI_MODE_PINS && mode != WPI_MODE_PHYS && mode != WPI_MODE_GPIO) { - ThrowException(Exception::TypeError( - String::New("Incorrect mode value. WPI_MODE_PINS, WPI_MODE_PHYS or WPI_MODE_GPIO expected."))); - return scope.Close(Undefined()); - } - - ::pinModeAlt(pin, mode); - - return scope.Close(Undefined()); -} - -// Func : void pinMode(int pin, int mode) -// Description : This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. -// Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) -// supports CLOCK output modes. -// This function has no effect when in Sys mode. If you need to change the pin mode, the you can -// do it with the gpio program in a script before you start your program. - -IMPLEMENT(pinMode) { - HandleScope scope; - int mode; - int pin; - - // CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument types. Numbers expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - mode = args[1]->NumberValue(); - - // CHECK: Allowed values - if (mode != INPUT && mode != OUTPUT && mode != PWM_OUTPUT && mode != GPIO_CLOCK && mode != SOFT_PWM_OUTPUT && mode != SOFT_TONE_OUTPUT) { - ThrowException(Exception::TypeError( - String::New("Incorrect mode value. INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK expected."))); - return scope.Close(Undefined()); - } - - ::pinMode(pin, mode); - - return scope.Close(Undefined()); -} - -// Func : void pullUpDnControl(int pin, int pud) -// Description : This sets the pull-up or pull-down resistor mode on the given pin, which should be set -// as an input. Unlike Arduino, the BCM2835 has both pull-up and down internal resistors. -// The parameter pud should be; PUD_OFF (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v). -// The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi. - -IMPLEMENT(pullUpDnControl) { - HandleScope scope; - int pin; - int pud; - - // CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument types. Numbers expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - pud = args[1]->NumberValue(); - - // CHECK: Allowed values - if (pud != PUD_OFF && pud != PUD_DOWN && pud != PUD_UP) { - ThrowException(Exception::TypeError( - String::New("Incorrect mode value. PUD_OFF, PUD_DOWN or PUD_UP expected."))); - return scope.Close(Undefined()); - } - - ::pullUpDnControl(pin, pud); - - return scope.Close(Undefined()); -} - -// Func : int digitalRead(int pin) -// Description : This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) -// depending on the logic level at the pin. - -IMPLEMENT(digitalRead) { - HandleScope scope; - int pin; - int res; - - // CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - res = ::digitalRead(pin); - - // Make sure the function returns strictly 1 or 0 - // §4.7/4 from the C++ Standard says (Integral Conversion) - // If the source type is bool, the value false is converted to zero and the value true is converted to one. - res = (res != 0); - - return scope.Close(Int32::New(res)); -} - -// Func : void digitalWrite(int pin, int value) -// Description : Write the value HIGH or LOW (1 or 0) to the given pin which must have been -// previously set as an output. -// WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW. - -IMPLEMENT(digitalWrite) { - HandleScope scope; - int pin; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument types. Numbers expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - value = args[1]->NumberValue(); - - // Make sure value is strictly 1 or 0 - // §4.7/4 from the C++ Standard says (Integral Conversion) - // If the source type is bool, the value false is converted to zero and the value true is converted to one. - value = (value != 0); - - ::digitalWrite(pin, value); - - return scope.Close(Undefined()); -} - -// Func : void pwmWrite(int pin, int value) -// Description : Writes the value to the PWM register for the given pin. The Raspberry Pi has -// one on-board PWM pin, pin 1 (BCM_GPIO 18, Phys 12) and the range is 0-1024. Other PWM -// devices may have other PWM ranges. -// This function is not able to control the Pi's on-board PWM when in Sys mode. - -IMPLEMENT(pwmWrite) { - HandleScope scope; - int pin; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument types. Numbers expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - value = args[1]->NumberValue(); - - ::pwmWrite(pin, value); - - return scope.Close(Undefined()); -} - -// Func : int analogRead(int pin) -// Description : This returns the value read on the supplied analog input pin. You will need to -// register additional analog modules to enable this function for device such as the Gertboard, -// quick2Wire analog board, etc. - -IMPLEMENT(analogRead) { - HandleScope scope; - int pin; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - res = ::analogRead(pin); - - return scope.Close(Int32::New(res)); -} - -// Func : void analogWrite(int pin, int value) -// Description : This writes the given value to the supplied analog pin. You will need to register -// additional analog modules to enable this function for devices such as the Gertboard. - -IMPLEMENT(analogWrite) { - HandleScope scope; - int pin; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - value = args[1]->NumberValue(); - - ::analogWrite(pin, value); - - return scope.Close(Undefined()); -} - -IMPLEMENT(pulseIn) { - HandleScope scope; - int pin; - int state; - int microseconds; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - state = args[1]->NumberValue(); - - microseconds = ::pulseIn(pin, state); - - return scope.Close(Int32::New(microseconds)); -} - -IMPLEMENT(delay) { - HandleScope scope; - unsigned int howLong; - - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - howLong = args[0]->Uint32Value(); - - ::delay(howLong); - - return scope.Close(Undefined()); -} - -IMPLEMENT(delayMicroseconds) { - HandleScope scope; - unsigned int howLong; - - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - howLong = args[0]->Uint32Value(); - - ::delayMicroseconds(howLong); - - return scope.Close(Undefined()); -} - -IMPLEMENT(millis) { - HandleScope scope; - - unsigned int ms = ::millis(); - - return scope.Close(Uint32::New(ms)); -} - -IMPLEMENT(micros) { - HandleScope scope; - - unsigned int us = ::micros(); - - return scope.Close(Uint32::New(us)); -} - -// === Raspberry Pi specific === - -// Func : int piBoardRev(void) -// Description : This returns the board revision of the Raspberry Pi. It will be either 1 or 2. -// Some of the BCM_GPIO pins changed number and function when moving from board revision 1 to 2, -// so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences. - -IMPLEMENT(piBoardRev) { - HandleScope scope; - int res; - - //CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - res = ::piBoardRev(); - - return scope.Close(Int32::New(res)); -} - -IMPLEMENT(piBoardId) { - HandleScope scope; - int model; - int rev; - int mem; - char* marker; - - //CHECK: Number of argument - if (args.Length() != 0) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - ::piBoardId(&model, &rev, &mem, &marker); - - Local obj = Object::New(); - obj->Set(String::NewSymbol("model"), Int32::New(model)); - obj->Set(String::NewSymbol("rev"), Int32::New(rev)); - obj->Set(String::NewSymbol("mem"), Int32::New(mem)); - obj->Set(String::NewSymbol("marker"), String::New(marker)); - - return scope.Close(obj); -} - -// Func : int wpiPinToGpio(int wpiPin) -// Description : This returns the BCM_GPIO pin number of the supplied wiringPi pin. -// It takes the board revision into account. - -IMPLEMENT(wpiPinToGpio) { - HandleScope scope; - int wpiPin; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - wpiPin = args[0]->NumberValue(); - res = ::wpiPinToGpio(wpiPin); - - return scope.Close(Int32::New(res)); -} - -// Func : int physPinToGpio (int physPin) -// Description : This returns the BCM_GPIO pin number of the suppled physical pin on the P1 connector. - -IMPLEMENT(physPinToGpio) { - HandleScope scope; - int physPin; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - physPin = args[0]->NumberValue(); - res = ::physPinToGpio(physPin); - - return scope.Close(Int32::New(res)); -} - -// Func : void setPadDrive(int group, int value) -// Description : This sets the "strength" of the pad drivers for a particular group of pins. -// There are 3 groups of pins and the drive strength is from 0 to 7. Do not use the unless you -// know what you are doing. - -IMPLEMENT(setPadDrive) { - HandleScope scope; - int group; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - group = args[0]->NumberValue(); - value = args[1]->NumberValue(); - ::setPadDrive(group, value); - - return scope.Close(Undefined()); -} - -// Func : int getAlt(int pin) -// Description : Returns the ALT bits for a given port. Only really of-use -// for the gpio readall command (I think). - -IMPLEMENT(getAlt) { - HandleScope scope; - int pin; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - res = ::getAlt(pin); - - return scope.Close(Int32::New(res)); -} - -// Func : void digitalWriteByte(int value) -// Description : This writes the 8-bit byte supplied to the first 8 GPIO pins. -// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes -// two write operations to the Pi’s GPIO hardware. - -IMPLEMENT(digitalWriteByte) { - HandleScope scope; - int value; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - value = args[0]->NumberValue(); - ::digitalWriteByte(value); - - return scope.Close(Undefined()); -} - -// Func : void pwmSetMode(int mode) -// Description : The PWM generator can run in 2 modes – “balanced” and “mark:space”. -// The mark:space mode is traditional, however the default mode in the Pi is “balanced”. -// You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS. - -IMPLEMENT(pwmSetMode) { - HandleScope scope; - int mode; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - mode = args[0]->NumberValue(); - - //CHECK: Allowed values - if (mode != PWM_MODE_BAL && mode != PWM_MODE_MS) { - ThrowException(Exception::TypeError( - String::New("Incorrect mode value. PWM_MODE_BAL or PWM_MODE_MS expected."))); - return scope.Close(Undefined()); - } - - ::pwmSetMode(mode); - - return scope.Close(Undefined()); -} - -// Func : void pwmSetRange(unsigned int range) -// Description : This sets the range register in the PWM generator. The default is 1024. -// Note: The PWM control functions can not be used when in Sys mode. To understand more about -// the PWM system, you’ll need to read the Broadcom ARM peripherals manual. - -IMPLEMENT(pwmSetRange) { - HandleScope scope; - unsigned int range; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - range = args[0]->Uint32Value(); - ::pwmSetRange(range); - - return scope.Close(Undefined()); -} - -// Func : void pwmSetClock(int divisor) -// Description : This sets the divisor for the PWM clock. -// Note: The PWM control functions can not be used when in Sys mode. To understand more about -// the PWM system, you’ll need to read the Broadcom ARM peripherals manual. - -IMPLEMENT(pwmSetClock) { - HandleScope scope; - int divisor; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - divisor = args[0]->NumberValue(); - ::pwmSetClock(divisor); - - return scope.Close(Undefined()); -} - -// Func : void gpioClockSet(int pin, int freq) -// Description : Set the frequency on a GPIO clock pin - -IMPLEMENT(gpioClockSet) { - HandleScope scope; - int pin; - int freq; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->NumberValue(); - freq = args[1]->NumberValue(); - ::gpioClockSet(pin, freq); - - return scope.Close(Undefined()); -} - -// === Extensions === - -// Func : int drcSetupSerial(const int pinBase, const int numPins, const char* device, const int baud) -// Description : https://projects.drogon.net/drogon-remote-control/drc-protocol-arduino/ - -IMPLEMENT(drcSetupSerial) { - HandleScope scope; - int pinBase; - int numPins; - const char* device; - int baud; - int res; - - //CHECK: Number of argument - if (args.Length() != 4) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsString() || !args[3]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - numPins = args[1]->Int32Value(); - v8::String::AsciiValue deviceString(args[2]->ToString()); - device = *deviceString; - baud = args[3]->Int32Value(); - - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::drcSetupSerial(pinBase, numPins, device, baud); - - return scope.Close(Int32::New(res)); -} - -// Func : int max5233Setup(int pinBase, int spiChannel) - -IMPLEMENT(max5322Setup) { - HandleScope scope; - int pinBase; - int spiChannel; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - spiChannel = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiChannel != 0 && spiChannel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiChannel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::max5322Setup(pinBase, spiChannel); - - return scope.Close(Int32::New(res)); -} - -// Func : int max31855Setup(int pinBase, int spiChannel) - -IMPLEMENT(max31855Setup) { - HandleScope scope; - int pinBase; - int spiChannel; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - spiChannel = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiChannel != 0 && spiChannel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiChannel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::max31855Setup(pinBase, spiChannel); - - return scope.Close(Int32::New(res)); -} - -// Func int mcp23s08Setup(const int pinBase, const int spiPort, const int devId) - -IMPLEMENT(mcp23s08Setup) { - HandleScope scope; - int pinBase; - int spiPort; - int devId; - int res; - - //CHECK: Number of argument - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->NumberValue(); - spiPort = args[1]->NumberValue(); - devId = args[2]->NumberValue(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiPort != 0 && spiPort != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiPort value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - //MCP23S08 3bits addressing - if (devId < 0 || devId > 7) { - ThrowException(Exception::TypeError( - String::New("Incorrect devId value. Value from 0 to 7 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp23s08Setup(pinBase, spiPort, devId); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp23s17Setup(int pinBase, int spiPort, int devId) -// Description : Initialise libWiringPi to be used with MCP23S17 -// pinBase is any number above 64 that doesn’t clash with any other wiringPi expansion module, -// spiPort is 0 or 1 for one of the two SPI ports on the Pi and devId is the ID of that MCP23s17 on the SPI port. - -IMPLEMENT(mcp23s17Setup) { - HandleScope scope; - int pinBase; - int spiPort; - int devId; - int res; - - //CHECK: Number of argument - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->NumberValue(); - spiPort = args[1]->NumberValue(); - devId = args[2]->NumberValue(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiPort != 0 && spiPort != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiPort value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - //MCP23S17 3bits addressing - if (devId < 0 || devId > 7) { - ThrowException(Exception::TypeError( - String::New("Incorrect devId value. Value from 0 to 7 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp23s17Setup(pinBase, spiPort, devId); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp3002Setup(int pinBase, int spiChannel) - -IMPLEMENT(mcp3002Setup) { - HandleScope scope; - int pinBase; - int spiChannel; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - spiChannel = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiChannel != 0 && spiChannel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiChannel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp3002Setup(pinBase, spiChannel); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp3004Setup(int pinBase, int spiChannel) - -IMPLEMENT(mcp3004Setup) { - HandleScope scope; - int pinBase; - int spiChannel; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - spiChannel = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiChannel != 0 && spiChannel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiChannel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp3004Setup(pinBase, spiChannel); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp3422Setup(int pinBase, int i2cAddress, int sampleRate, int gain) - -IMPLEMENT(mcp3422Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int sampleRate; - int gain; - int res; - - //CHECK: Number of argument - if (args.Length() != 4) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - sampleRate = args[2]->Int32Value(); - gain = args[3]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (sampleRate < 0 || sampleRate > 3) { - ThrowException(Exception::TypeError( - String::New("Incorrect sampleRate value. MCP3422_SR_3_75, MCP3422_SR_15, MCP3422_SR_60 or MCP3422_SR_240 expected."))); - return scope.Close(Undefined()); - } - - if (gain < 0 || gain > 3) { - ThrowException(Exception::TypeError( - String::New("Incorrect gain value. MCP3422_GAIN_1, MCP3422_GAIN_2, MCP3422_GAIN_3 or MCP3422_GAIN_4 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp3422Setup(pinBase, i2cAddress, sampleRate, gain); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp4802Setup(int pinBase, int spiChannel) - -IMPLEMENT(mcp4802Setup) { - HandleScope scope; - int pinBase; - int spiChannel; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - spiChannel = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - if (spiChannel != 0 && spiChannel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect spiChannel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp4802Setup(pinBase, spiChannel); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp23008Setup(int pinBase, int i2cAddress) - -IMPLEMENT(mcp23008Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp23008Setup(pinBase, i2cAddress); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp23016Setup(const int pinBase, const int i2cAddress) - -IMPLEMENT(mcp23016Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp23016Setup(pinBase, i2cAddress); - - return scope.Close(Int32::New(res)); -} - -// Func : int mcp23017Setup(const int pinBase, const int i2cAddress) - -IMPLEMENT(mcp23017Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::mcp23017Setup(pinBase, i2cAddress); - - return scope.Close(Int32::New(res)); -} - -// Func : int pcf8574Setup(const int pinBase, const int i2cAddress) - -IMPLEMENT(pcf8574Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::pcf8574Setup(pinBase, i2cAddress); - - return scope.Close(Int32::New(res)); -} - -// Func : int pcf8591Setup(const int pinBase, const int i2cAddress) - -IMPLEMENT(pcf8591Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::pcf8591Setup(pinBase, i2cAddress); - - return scope.Close(Int32::New(res)); -} - -// Func : int sn3128Setup(int pinBase) - -IMPLEMENT(sn3218Setup) { - HandleScope scope; - int pinBase; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::sn3218Setup(pinBase); - - return scope.Close(Int32::New(res)); -} - -// Func : int sr595Setup(const int pinBase, const int numPins, const int dataPin, const int clockPin, const int latchPin) - -IMPLEMENT(sr595Setup) { - HandleScope scope; - int pinBase; - int numPins; - int dataPin; - int clockPin; - int latchPin; - int res; - - //CHECK: Number of argument - if (args.Length() != 5) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber() || !args[4]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - numPins = args[1]->Int32Value(); - dataPin = args[2]->Int32Value(); - clockPin = args[3]->Int32Value(); - latchPin = args[4]->Int32Value(); - - //CHECK: Allowed values - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected."))); - return scope.Close(Undefined()); - } - - res = ::sr595Setup(pinBase, numPins, dataPin, clockPin, latchPin); - - return scope.Close(Int32::New(res)); -} - -IMPLEMENT(pca9685Setup) { - HandleScope scope; - int pinBase; - int i2cAddress; - int freq; - int res; - - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect arguments type. Number expected."))); - return scope.Close(Undefined()); - } - - pinBase = args[0]->Int32Value(); - i2cAddress = args[1]->Int32Value(); - freq = args[2]->Int32Value(); - - if (pinBase <= 64) { - ThrowException(Exception::TypeError( - String::New("Incorrect pinBase value. >64 expected"))); - return scope.Close(Undefined()); - } - - res = ::pca9685Setup(pinBase, i2cAddress, freq); - - return scope.Close(Int32::New(res)); -} - -// === Soft PWM === - -// Func : int softPwmCreate(int pin, int value, int range) -// Description : This creates a software controlled PWM pin. -// You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. -// Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin. -// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong. -// NOTE : You must initialise wiringPi with one of wiringPiSetup(), wiringPiSetupGpio() or wiringPiSetupPhys() functions. -// wiringPiSetupSys() is not fast enough, so you must run your programs with sudo. -// NOTE2 : Each “cycle” of PWM output takes 10mS with the default range value of 100, -// so trying to change the PWM value more than 100 times a second will be futile. -// NOTE3 : Each pin activated in softPWM mode uses approximately 0.5% of the CPU. -// NOTE4 : There is currently no way to disable softPWM on a pin while the program in running. -// NOTE5 : You need to keep your program running to maintain the PWM output! - -IMPLEMENT(softPwmCreate) { - HandleScope scope; - int pin; - int value; - int range; - int res; - - //CHECK: Number of argument - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - value = args[1]->Int32Value(); - range = args[2]->Int32Value(); - - res = ::softPwmCreate(pin, value, range); - - return scope.Close(Int32::New(res)); -} - -// Func void softPwmWrite(int pin, int value) -// Description : This updates the PWM value on the given pin. -// The value is checked to be in-range and pins that haven’t previously been initialised via softPwmCreate will be silently ignored. - -IMPLEMENT(softPwmWrite) { - HandleScope scope; - int pin; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - value = args[1]->Int32Value(); - - ::softPwmWrite(pin, value); - - return scope.Close(Undefined()); -} - -IMPLEMENT(softPwmStop) { - HandleScope scope; - int pin; - - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - - ::softPwmStop(pin); - - return scope.Close(Undefined()); -} - -// === Soft Servo === - -// Func : void softServoWrite(int pin, int value) -// Description : Write a Servo value to the given pin - -IMPLEMENT(softServoWrite) { - HandleScope scope; - int pin; - int value; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - value = args[1]->Int32Value(); - - ::softServoWrite(pin, value); - - return scope.Close(Undefined()); -} - -// Func : int softServoSetup(int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7) -// Description : Setup the software servo system - -IMPLEMENT(softServoSetup) { - HandleScope scope; - int p0; - int p1; - int p2; - int p3; - int p4; - int p5; - int p6; - int p7; - int res; - - //CHECK: Number of argument - if (args.Length() != 8) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber() - || !args[4]->IsNumber() || !args[5]->IsNumber() || !args[6]->IsNumber() || !args[7]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - p0 = args[0]->Int32Value(); - p1 = args[1]->Int32Value(); - p2 = args[2]->Int32Value(); - p3 = args[3]->Int32Value(); - p4 = args[4]->Int32Value(); - p5 = args[5]->Int32Value(); - p6 = args[6]->Int32Value(); - p7 = args[7]->Int32Value(); - - res = ::softServoSetup(p0, p1, p2, p3, p4, p5, p6, p7); - - return scope.Close(Int32::New(res)); -} - -// === Soft Tone === - -// Func : int softToneCreate(int pin); -// Description : This creates a software controlled tone pin. -// You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. -// The return value is 0 for success. -// Anything else and you should check the global errno variable to see what went wrong. -// NOTE : You must initialise wiringPi with one of wiringPiSetup(), wiringPiSetupGpio() or wiringPiSetupPhys() functions. -// wiringPiSetupSys() is not fast enough, so you must run your programs with sudo. -// NOTE2 : Each pin activated in softTone mode uses approximately 0.5% of the CPU. -// NOTE3 : You need to keep your program running to maintain the sound output! - -IMPLEMENT(softToneCreate) { - HandleScope scope; - int pin; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - - res = ::softToneCreate(pin); - - return scope.Close(Int32::New(res)); -} - -// Func : void softToneWrite(int pin, int freq); -// Description : This updates the tone frequency value on the given pin. The tone will be played until you set the frequency to 0. - -IMPLEMENT(softToneWrite) { - HandleScope scope; - int pin; - int freq; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - freq = args[1]->Int32Value(); - - ::softToneWrite(pin, freq); - - return scope.Close(Undefined()); -} - -IMPLEMENT(softToneStop) { - HandleScope scope; - int pin; - - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - pin = args[0]->Int32Value(); - - ::softToneStop(pin); - - return scope.Close(Undefined()); -} - -// === WiringPI I2C === - -IMPLEMENT(wiringPiI2CRead) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CReadReg8) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CReadReg16) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CWrite) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CWriteReg8) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CWriteReg16) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CSetupInterface) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -IMPLEMENT(wiringPiI2CSetup) { - HandleScope scope; - ThrowException(Exception::TypeError( - String::New("Not implemented"))); - return scope.Close(Undefined()); -} - -// === WiringPI SPI === - -// Func : int wiringPiSPIGetFd(int channel) - -IMPLEMENT(wiringPiSPIGetFd) { - HandleScope scope; - int channel; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - channel = args[0]->Int32Value(); - - // CHECK: Allowed values - if (channel != 0 || channel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect channel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSPIGetFd(channel); - - return scope.Close(Int32::New(res)); -} - -// Func : wiringPiSPIDataRW(int channel, unsigned char* data, int len) - -IMPLEMENT(wiringPiSPIDataRW) { - HandleScope scope; - int channel; - unsigned char* data; - int len; - int res; - - //CHECK: Number of argument - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsString() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type."))); - return scope.Close(Undefined()); - } - - channel = args[0]->Int32Value(); - v8::String::AsciiValue dataString(args[1]->ToString()); - data = (unsigned char*)*dataString; - len = args[2]->Int32Value(); - - // CHECK: Allowed values - if (channel != 0 || channel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect channel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSPIDataRW(channel, data, len); - - return scope.Close(Int32::New(res)); -} - -// Func : int wiringPiSPISetup(int channel, int speed) - -IMPLEMENT(wiringPiSPISetup) { - HandleScope scope; - int channel; - int speed; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - channel = args[0]->Int32Value(); - speed = args[1]->Int32Value(); - - // CHECK: Allowed values - if (channel != 0 || channel != 1) { - ThrowException(Exception::TypeError( - String::New("Incorrect channel value. 0 or 1 expected."))); - return scope.Close(Undefined()); - } - - res = ::wiringPiSPISetup(channel, speed); - - return scope.Close(Int32::New(res)); -} - -// === WiringPi Serial === - -// Func : int serialOpen(const char* device, const int baud) - -IMPLEMENT(serialOpen) { - HandleScope scope; - const char* device; - int baud; - int res; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsString()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type."))); - return scope.Close(Undefined()); - } - - v8::String::AsciiValue deviceString(args[0]->ToString()); - device = *deviceString; - baud = args[1]->Int32Value(); - - res = ::serialOpen(device, baud); - - return scope.Close(Int32::New(res)); -} - -// Func : void serialClose(const int fd) - -IMPLEMENT(serialClose) { - HandleScope scope; - int fd; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - - ::serialClose(fd); - - return scope.Close(Undefined()); -} - -// Func : void serialFlush(const int fd); - -IMPLEMENT(serialFlush) { - HandleScope scope; - int fd; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - - ::serialFlush(fd); - - return scope.Close(Undefined()); -} - -// Func : void serialPutchar(const int fd, const unsigned char c) - -IMPLEMENT(serialPutchar) { - HandleScope scope; - int fd; - unsigned char c; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - c = (args[0]->Uint32Value() & 0xFF); - - ::serialPutchar(fd, c); - - return scope.Close(Undefined()); -} - -// Func : void serialPuts(const int fd, const char* s) - -IMPLEMENT(serialPuts) { - HandleScope scope; - int fd; - const char* s; - - //CHECK: Number of argument - if (args.Length() != 2) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsString()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - v8::String::AsciiValue sString(args[0]->ToString()); - s = *sString; - - ::serialPuts(fd, s); - - return scope.Close(Undefined()); -} - -// Func : void serialPrintf(const int fd, const char* message, ...) - -IMPLEMENT(serialPrintf) { - return serialPuts(args); -} - -// Func : int serialDataAvail(const int fd) - -IMPLEMENT(serialDataAvail) { - HandleScope scope; - int fd; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - - res = ::serialDataAvail(fd); - - return scope.Close(Int32::New(res)); -} - -// Func : int serialGetchar(const int fd) -// NOTE TO MYSELF : I don't understand why serialPutchar takes a unsigned char and on the other side -// serialGetchar returns a int ... serialGetchar should returns a unsigned char too. - -IMPLEMENT(serialGetchar) { - HandleScope scope; - int fd; - int res; - - //CHECK: Number of argument - if (args.Length() != 1) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - //CHECK: Argument types - if (!args[0]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - fd = args[0]->Int32Value(); - - res = ::serialGetchar(fd); - - return scope.Close(Int32::New(res)); -} - -// === WiringPi Shift === - -// Func : uint8_t shiftIn(uint8_t dPin, uint8_t cPin, uint8_t order) -// Description : This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin. -// Order is either LSBFIRST or MSBFIRST. -// The data is sampled after the cPin goes high. -// (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function. - -IMPLEMENT(shiftIn) { - HandleScope scope; - uint8_t dPin; - uint8_t cPin; - uint8_t order; - uint8_t res; - - // CHECK: Number of argument - if (args.Length() != 3) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - dPin = args[0]->Uint32Value(); - cPin = args[1]->Uint32Value(); - order = args[2]->Uint32Value(); - - // CHECK : Allowed values - if (order != LSBFIRST || order != MSBFIRST) { - ThrowException(Exception::TypeError( - String::New("Incorrect order value. LSBFIRT or MSBFIRST expected."))); - return scope.Close(Undefined()); - } - - res = ::shiftIn(dPin, cPin, order); - - return scope.Close(Uint32::New(res)); -} - -// Func : void shiftOut(uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) ; -// Description : The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin. -// order is as above. -// Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low – repeated for the 8 bits. - -IMPLEMENT(shiftOut) { - HandleScope scope; - uint8_t dPin; - uint8_t cPin; - uint8_t order; - uint8_t val; - - // CHECK: Number of argument - if (args.Length() != 4) { - ThrowException(Exception::TypeError( - String::New("Wrong number of arguments."))); - return scope.Close(Undefined()); - } - - // CHECK: Argument types - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsNumber() || !args[3]->IsNumber()) { - ThrowException(Exception::TypeError( - String::New("Incorrect argument type. Number expected."))); - return scope.Close(Undefined()); - } - - dPin = args[0]->Uint32Value(); - cPin = args[1]->Uint32Value(); - order = args[2]->Uint32Value(); - val = args[3]->Uint32Value(); - - // CHECK : Allowed values - if (order != LSBFIRST || order != MSBFIRST) { - ThrowException(Exception::TypeError( - String::New("Incorrect order value. LSBFIRT or MSBFIRST expected."))); - return scope.Close(Undefined()); - } - - ::shiftOut(dPin, cPin, order, val); - - return scope.Close(Undefined()); -} - -void init(Handle target) { - // Setup - EXPORT(wiringPiSetup); - EXPORT(wiringPiSetupGpio); - EXPORT(wiringPiSetupSys); - EXPORT(wiringPiSetupPhys); - - // Core wiringPi functions - EXPORT(pinModeAlt); - EXPORT(pinMode); - EXPORT(pullUpDnControl); - EXPORT(digitalRead); - EXPORT(digitalWrite); - EXPORT(pwmWrite); - EXPORT(analogRead); - EXPORT(analogWrite); - EXPORT(pulseIn); - - EXPORT(delay); - EXPORT(delayMicroseconds); - EXPORT(millis); - EXPORT(micros); - - // PiFace specifics (Deprecated) - //EXPORT(wiringPiSetupPiFace); - //EXPORT(wiringPiSetupPiFaceForGpioProg); // Don't use this - for gpio program only - - // On-Board Rasberry Pi hardware specific stuff - EXPORT(piBoardRev); - EXPORT(piBoardId); - EXPORT(wpiPinToGpio); - EXPORT(physPinToGpio); - EXPORT(setPadDrive); - EXPORT(getAlt); - EXPORT(digitalWriteByte); - EXPORT(pwmSetMode); - EXPORT(pwmSetRange); - EXPORT(pwmSetClock); - EXPORT(gpioClockSet); - - // Extensions - EXPORT(drcSetupSerial); - EXPORT(max5322Setup); - EXPORT(max31855Setup); - EXPORT(mcp23s08Setup); - EXPORT(mcp23s17Setup); - EXPORT(mcp3002Setup); - EXPORT(mcp3004Setup); - EXPORT(mcp3422Setup); - EXPORT(mcp4802Setup); - EXPORT(mcp23008Setup); - EXPORT(mcp23016Setup); - EXPORT(mcp23017Setup); - EXPORT(pcf8574Setup); - EXPORT(pcf8591Setup); - EXPORT(sn3218Setup); - EXPORT(sr595Setup); - EXPORT(pca9685Setup); - - // Soft PWM - EXPORT(softPwmCreate); - EXPORT(softPwmWrite); - EXPORT(softPwmStop); - - // Soft Servo - EXPORT(softServoWrite); - EXPORT(softServoSetup); - - // Soft Tone - EXPORT(softToneCreate); - EXPORT(softToneWrite); - EXPORT(softToneStop); - - // WiringPI I2C - EXPORT(wiringPiI2CRead); - EXPORT(wiringPiI2CReadReg8); - EXPORT(wiringPiI2CReadReg16); - EXPORT(wiringPiI2CWrite); - EXPORT(wiringPiI2CWriteReg8); - EXPORT(wiringPiI2CWriteReg16); - EXPORT(wiringPiI2CSetupInterface); - EXPORT(wiringPiI2CSetup); - - // WiringPI SPI - EXPORT(wiringPiSPIGetFd); - EXPORT(wiringPiSPIDataRW); - EXPORT(wiringPiSPISetup); - - // WiringPi Serial - EXPORT(serialOpen); - EXPORT(serialClose); - EXPORT(serialFlush); - EXPORT(serialPutchar); - EXPORT(serialPuts); - EXPORT(serialPrintf); - EXPORT(serialDataAvail); - EXPORT(serialGetchar); - - // WiringPi Shift - EXPORT(shiftIn); - EXPORT(shiftOut); -} - -NODE_MODULE(wiringPi, init) diff --git a/src/devlib/devlib.cc b/src/devlib/devlib.cc new file mode 100644 index 0000000..ae4ec04 --- /dev/null +++ b/src/devlib/devlib.cc @@ -0,0 +1,23 @@ +#include "devlib.h" + +#include "ds1302.h" +#include "gertboard.h" +#include "lcd.h" +#include "lcd128x64.h" +#include "maxdetect.h" +#include "piFace.h" +#include "piGlow.h" +#include "piNes.h" +#include "tcs34725.h" + +IMPLEMENT_EXPORT_INIT(devlib) { + INIT(ds1302); + INIT(gertboard); + INIT(lcd); + INIT(lcd128x64); + INIT(maxdetect); + INIT(piFace); + INIT(piGlow); + INIT(piNes); + INIT(tcs34725); +} \ No newline at end of file diff --git a/src/devlib/devlib.h b/src/devlib/devlib.h new file mode 100644 index 0000000..2c6c5f7 --- /dev/null +++ b/src/devlib/devlib.h @@ -0,0 +1,8 @@ +#ifndef _WPI_DEV_LIB_H_ +#define _WPI_DEV_LIB_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(devlib); + +#endif \ No newline at end of file diff --git a/src/devlib/ds1302.cc b/src/devlib/ds1302.cc new file mode 100644 index 0000000..fe6e127 --- /dev/null +++ b/src/devlib/ds1302.cc @@ -0,0 +1,177 @@ +#include "ds1302.h" +#include + +DECLARE(ds1302rtcRead); +DECLARE(ds1302rtcWrite); +DECLARE(ds1302ramRead); +DECLARE(ds1302ramWrite); +DECLARE(ds1302clockRead); +DECLARE(ds1302clockWrite); +DECLARE(ds1302trickleCharge); +DECLARE(ds1302setup); + +// Func: unsigned int ds1302rtcRead (const int reg) +// Description: Reads the data to/from the RTC register + +IMPLEMENT(ds1302rtcRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, reg); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int reg = GET_ARGUMENT_AS_INT32(0); + + unsigned int res = ::ds1302rtcRead(reg); + + SCOPE_CLOSE(UINT32(res)); +} + +// Func: void ds1302rtcWrite (int reg, unsigned int data) +// Description: Writes the data to/from the RTC register + +IMPLEMENT(ds1302rtcWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, reg); + SET_ARGUMENT_NAME(1, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int reg = GET_ARGUMENT_AS_INT32(0); + unsigned int data = GET_ARGUMENT_AS_UINT32(1); + + ::ds1302rtcWrite(reg, data); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(ds1302ramRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, address); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int address = GET_ARGUMENT_AS_INT32(0); + + unsigned int res = ::ds1302ramRead(address); + + SCOPE_CLOSE(UINT32(res)); +} + +IMPLEMENT(ds1302ramWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, address); + SET_ARGUMENT_NAME(1, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + + int address = GET_ARGUMENT_AS_INT32(0); + unsigned int data = GET_ARGUMENT_AS_UINT32(1); + + ::ds1302ramWrite(address, data); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(ds1302clockRead) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int clockData[8]; + ::ds1302clockRead(clockData); + + v8::Local res = v8::Array::New(8); + for (int i = 0; i < 8; i++) { + res->Set(i, v8::Int32::New(clockData[i])); + } + + SCOPE_CLOSE(res); +} + +IMPLEMENT(ds1302clockWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, clockData); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_ARRAY(0); + CHECK_ARGUMENT_ARRAY_LENGTH(0, 8); + + v8::Local clockData = v8::Local::Cast(args[0]); + + int ar[8]; + for (int i = 0; i < 8; i++) { + ar[i] = clockData->Get(i)->Int32Value(); + } + + ::ds1302clockWrite(ar); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(ds1302trickleCharge) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, diodes); + SET_ARGUMENT_NAME(1, resistors); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int diodes = GET_ARGUMENT_AS_INT32(0); + int resistors = GET_ARGUMENT_AS_INT32(1); + + ::ds1302trickleCharge(diodes, resistors); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(ds1302setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, clockPin); + SET_ARGUMENT_NAME(1, dataPin); + SET_ARGUMENT_NAME(2, csPin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int clockPin = GET_ARGUMENT_AS_INT32(0); + int dataPin = GET_ARGUMENT_AS_INT32(1); + int csPin = GET_ARGUMENT_AS_INT32(2); + + ::ds1302setup(clockPin, dataPin, csPin); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(ds1302) { + EXPORT_FUNCTION(ds1302rtcRead); + EXPORT_FUNCTION(ds1302rtcWrite); + EXPORT_FUNCTION(ds1302ramRead); + EXPORT_FUNCTION(ds1302ramWrite); + EXPORT_FUNCTION(ds1302clockRead); + EXPORT_FUNCTION(ds1302clockWrite); + EXPORT_FUNCTION(ds1302trickleCharge); + EXPORT_FUNCTION(ds1302setup); +} \ No newline at end of file diff --git a/src/devlib/ds1302.h b/src/devlib/ds1302.h new file mode 100644 index 0000000..349d2e5 --- /dev/null +++ b/src/devlib/ds1302.h @@ -0,0 +1,8 @@ +#ifndef _WPI_DS1302_H_ +#define _WPI_DS1302_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(ds1302); + +#endif \ No newline at end of file diff --git a/src/devlib/gertboard.cc b/src/devlib/gertboard.cc new file mode 100644 index 0000000..8cc9b37 --- /dev/null +++ b/src/devlib/gertboard.cc @@ -0,0 +1,24 @@ +#include "gertboard.h" +#include + +DECLARE(gertboardAnalogSetup); + +IMPLEMENT(gertboardAnalogSetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + + int res = ::gertboardAnalogSetup(pinBase); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(gertboard) { + EXPORT_FUNCTION(gertboardAnalogSetup); +} \ No newline at end of file diff --git a/src/devlib/gertboard.h b/src/devlib/gertboard.h new file mode 100644 index 0000000..f9d1ea1 --- /dev/null +++ b/src/devlib/gertboard.h @@ -0,0 +1,8 @@ +#ifndef _WPI_GERTBOARD_H_ +#define _WPI_GERTBOARD_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(gertboard); + +#endif \ No newline at end of file diff --git a/src/devlib/lcd.cc b/src/devlib/lcd.cc new file mode 100644 index 0000000..6fbd787 --- /dev/null +++ b/src/devlib/lcd.cc @@ -0,0 +1,284 @@ +#include "lcd.h" +#include + +DECLARE(lcdHome); +DECLARE(lcdClear); +DECLARE(lcdDisplay); +DECLARE(lcdCursor); +DECLARE(lcdCursorBlink); +DECLARE(lcdSendCommand); +DECLARE(lcdPosition); +DECLARE(lcdCharDef); +DECLARE(lcdPutchar); +DECLARE(lcdPuts); +DECLARE(lcdPrintf); +DECLARE(lcdInit); + +IMPLEMENT(lcdHome) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + ::lcdHome(fd); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdClear) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + ::lcdClear(fd); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdDisplay) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, state); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int state = GET_ARGUMENT_AS_INT32(1); + + ::lcdDisplay(fd, state); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdCursor) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, state); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int state = GET_ARGUMENT_AS_INT32(1); + + ::lcdCursor(fd, state); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdCursorBlink) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, state); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int state = GET_ARGUMENT_AS_INT32(1); + + ::lcdCursorBlink(fd, state); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdSendCommand) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, command); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int command = GET_ARGUMENT_AS_UINT32(1); + + ::lcdSendCommand(fd, command); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdPosition) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, x); + SET_ARGUMENT_NAME(2, y); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int fd = GET_ARGUMENT_AS_INT32(0); + int x = GET_ARGUMENT_AS_INT32(1); + int y = GET_ARGUMENT_AS_INT32(2); + + ::lcdPosition(fd, x, y); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdCharDef) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, index); + SET_ARGUMENT_NAME(2, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_ARRAY(2); + CHECK_ARGUMENT_ARRAY_LENGTH(2, 8); + + int fd = GET_ARGUMENT_AS_INT32(0); + int index = GET_ARGUMENT_AS_INT32(1); + v8::Local data = v8::Local::Cast(args[2]); + + unsigned char ar[8]; + for (int i = 0; i < 8; i++) { + ar[i] = data->Get(i)->Uint32Value() & 0xFF; + } + + ::lcdCharDef(fd, index, ar); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdPutchar) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + unsigned int data = GET_ARGUMENT_AS_UINT32(1); + + ::lcdPutchar(fd, data); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdPuts) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, string); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_STRING(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + v8::String::AsciiValue data(GET_ARGUMENT_AS_STRING(1)); + + ::lcdPuts(fd, *data); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcdPrintf) { + return lcdPuts(args); +} + +IMPLEMENT(lcdInit) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, rows); + SET_ARGUMENT_NAME(1, cols); + SET_ARGUMENT_NAME(2, bits); + SET_ARGUMENT_NAME(3, rs); + SET_ARGUMENT_NAME(4, strb); + SET_ARGUMENT_NAME(5, d0); + SET_ARGUMENT_NAME(6, d1); + SET_ARGUMENT_NAME(7, d2); + SET_ARGUMENT_NAME(8, d3); + SET_ARGUMENT_NAME(9, d4); + SET_ARGUMENT_NAME(10, d5); + SET_ARGUMENT_NAME(11, d6); + SET_ARGUMENT_NAME(12, d7); + + CHECK_ARGUMENTS_LENGTH_EQUAL(13); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + CHECK_ARGUMENT_TYPE_INT32(5); + CHECK_ARGUMENT_TYPE_INT32(6); + CHECK_ARGUMENT_TYPE_INT32(7); + CHECK_ARGUMENT_TYPE_INT32(8); + CHECK_ARGUMENT_TYPE_INT32(9); + CHECK_ARGUMENT_TYPE_INT32(10); + CHECK_ARGUMENT_TYPE_INT32(11); + CHECK_ARGUMENT_TYPE_INT32(12); + + int rows = GET_ARGUMENT_AS_INT32(0); + int cols = GET_ARGUMENT_AS_INT32(1); + int bits = GET_ARGUMENT_AS_INT32(2); + int rs = GET_ARGUMENT_AS_INT32(3); + int strb = GET_ARGUMENT_AS_INT32(4); + int d0 = GET_ARGUMENT_AS_INT32(5); + int d1 = GET_ARGUMENT_AS_INT32(6); + int d2 = GET_ARGUMENT_AS_INT32(7); + int d3 = GET_ARGUMENT_AS_INT32(8); + int d4 = GET_ARGUMENT_AS_INT32(9); + int d5 = GET_ARGUMENT_AS_INT32(10); + int d6 = GET_ARGUMENT_AS_INT32(11); + int d7 = GET_ARGUMENT_AS_INT32(12); + + int res = ::lcdInit(rows, cols, bits, rs, strb, d0, d1, d2, d3, d4, d5, d6, d7); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(lcd) { + EXPORT_FUNCTION(lcdHome); + EXPORT_FUNCTION(lcdClear); + EXPORT_FUNCTION(lcdDisplay); + EXPORT_FUNCTION(lcdCursor); + EXPORT_FUNCTION(lcdCursorBlink); + EXPORT_FUNCTION(lcdSendCommand); + EXPORT_FUNCTION(lcdPosition); + EXPORT_FUNCTION(lcdCharDef); + EXPORT_FUNCTION(lcdPutchar); + EXPORT_FUNCTION(lcdPuts); + EXPORT_FUNCTION(lcdPrintf); + EXPORT_FUNCTION(lcdInit); + + EXPORT_CONSTANT_INT(MAX_LCDS); +} \ No newline at end of file diff --git a/src/devlib/lcd.h b/src/devlib/lcd.h new file mode 100644 index 0000000..1b66119 --- /dev/null +++ b/src/devlib/lcd.h @@ -0,0 +1,8 @@ +#ifndef _WPI_LCD_H_ +#define _WPI_LCD_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(lcd); + +#endif \ No newline at end of file diff --git a/src/devlib/lcd128x64.cc b/src/devlib/lcd128x64.cc new file mode 100644 index 0000000..2e4c2bb --- /dev/null +++ b/src/devlib/lcd128x64.cc @@ -0,0 +1,355 @@ +#include "lcd128x64.h" +#include + +DECLARE(lcd128x64setOrigin); +DECLARE(lcd128x64setOrientation); +DECLARE(lcd128x64orientCoordinates); +DECLARE(lcd128x64getScreenSize); +DECLARE(lcd128x64point); +DECLARE(lcd128x64line); +DECLARE(lcd128x64lineTo); +DECLARE(lcd128x64rectangle); +DECLARE(lcd128x64circle); +DECLARE(lcd128x64ellipse); +DECLARE(lcd128x64putchar); +DECLARE(lcd128x64puts); +DECLARE(lcd128x64update); +DECLARE(lcd128x64clear); +DECLARE(lcd128x64setup); + +IMPLEMENT(lcd128x64setOrigin) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + + ::lcd128x64setOrigin(x, y); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64setOrientation) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, orientation); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int orientation = GET_ARGUMENT_AS_INT32(0); + + ::lcd128x64setOrientation(orientation); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64orientCoordinates) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int x, y; + ::lcd128x64orientCoordinates(&x, &y); + + v8::Local res = v8::Array::New(2); + res->Set(0, v8::Int32::New(x)); + res->Set(1, v8::Int32::New(y)); + + SCOPE_CLOSE(res); +} + +IMPLEMENT(lcd128x64getScreenSize) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int x, y; + ::lcd128x64getScreenSize(&x, &y); + + v8::Local res = v8::Array::New(2); + res->Set(0, v8::Int32::New(x)); + res->Set(1, v8::Int32::New(y)); + + SCOPE_CLOSE(res); +} + +IMPLEMENT(lcd128x64point) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + SET_ARGUMENT_NAME(2, color); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + int color = GET_ARGUMENT_AS_INT32(2); + + ::lcd128x64point(x, y, color); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64line) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x0); + SET_ARGUMENT_NAME(1, y0); + SET_ARGUMENT_NAME(2, x1); + SET_ARGUMENT_NAME(3, y1); + SET_ARGUMENT_NAME(4, color); + + CHECK_ARGUMENTS_LENGTH_EQUAL(5); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + + int x0 = GET_ARGUMENT_AS_INT32(0); + int y0 = GET_ARGUMENT_AS_INT32(1); + int x1 = GET_ARGUMENT_AS_INT32(2); + int y1 = GET_ARGUMENT_AS_INT32(3); + int color = GET_ARGUMENT_AS_INT32(4); + + ::lcd128x64line(x0, y0, x1, y1, color); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64lineTo) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + SET_ARGUMENT_NAME(2, color); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + int color = GET_ARGUMENT_AS_INT32(2); + + ::lcd128x64lineTo(x, y, color); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64rectangle) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x1); + SET_ARGUMENT_NAME(1, y1); + SET_ARGUMENT_NAME(2, x2); + SET_ARGUMENT_NAME(3, y2); + SET_ARGUMENT_NAME(4, color); + SET_ARGUMENT_NAME(5, filled); + + CHECK_ARGUMENTS_LENGTH_EQUAL(6); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + CHECK_ARGUMENT_TYPE_INT32(5); + + int x1 = GET_ARGUMENT_AS_INT32(0); + int y1 = GET_ARGUMENT_AS_INT32(1); + int x2 = GET_ARGUMENT_AS_INT32(2); + int y2 = GET_ARGUMENT_AS_INT32(3); + int color = GET_ARGUMENT_AS_INT32(4); + int filled = GET_ARGUMENT_AS_INT32(5); + + ::lcd128x64rectangle(x1, y1, x2, y2, color, filled); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64circle) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + SET_ARGUMENT_NAME(2, r); + SET_ARGUMENT_NAME(3, color); + SET_ARGUMENT_NAME(4, filled); + + CHECK_ARGUMENTS_LENGTH_EQUAL(5); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + int r = GET_ARGUMENT_AS_INT32(2); + int color = GET_ARGUMENT_AS_INT32(3); + int filled = GET_ARGUMENT_AS_INT32(4); + + ::lcd128x64circle(x, y, r, color, filled); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64ellipse) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, cx); + SET_ARGUMENT_NAME(1, cy); + SET_ARGUMENT_NAME(2, xRadius); + SET_ARGUMENT_NAME(3, yRadius); + SET_ARGUMENT_NAME(4, color); + SET_ARGUMENT_NAME(5, filled); + + CHECK_ARGUMENTS_LENGTH_EQUAL(6); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + CHECK_ARGUMENT_TYPE_INT32(5); + + int cx = GET_ARGUMENT_AS_INT32(0); + int cy = GET_ARGUMENT_AS_INT32(1); + int xRadius = GET_ARGUMENT_AS_INT32(2); + int yRadius = GET_ARGUMENT_AS_INT32(3); + int color = GET_ARGUMENT_AS_INT32(4); + int filled = GET_ARGUMENT_AS_INT32(5); + + ::lcd128x64ellipse(cx, cy, xRadius, yRadius, color, filled); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64putchar) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + SET_ARGUMENT_NAME(2, c); + SET_ARGUMENT_NAME(3, bgColor); + SET_ARGUMENT_NAME(4, fgColor); + + CHECK_ARGUMENTS_LENGTH_EQUAL(5); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + int c = GET_ARGUMENT_AS_INT32(2); + int bgColor = GET_ARGUMENT_AS_INT32(3); + int fgColor = GET_ARGUMENT_AS_INT32(4); + + ::lcd128x64putchar(x, y, c, bgColor, fgColor); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64puts) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, x); + SET_ARGUMENT_NAME(1, y); + SET_ARGUMENT_NAME(2, string); + SET_ARGUMENT_NAME(3, bgColor); + SET_ARGUMENT_NAME(4, fgColor); + + CHECK_ARGUMENTS_LENGTH_EQUAL(5); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_STRING(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + + int x = GET_ARGUMENT_AS_INT32(0); + int y = GET_ARGUMENT_AS_INT32(1); + v8::String::AsciiValue string(GET_ARGUMENT_AS_STRING(2)); + int bgColor = GET_ARGUMENT_AS_INT32(3); + int fgColor = GET_ARGUMENT_AS_INT32(4); + + ::lcd128x64puts(x, y, *string, bgColor, fgColor); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64update) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + ::lcd128x64update(); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64clear) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, color); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int color = GET_ARGUMENT_AS_INT32(0); + + ::lcd128x64clear(color); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(lcd128x64setup) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::lcd128x64setup(); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(lcd128x64) { + EXPORT_FUNCTION(lcd128x64setOrigin); + EXPORT_FUNCTION(lcd128x64setOrientation); + EXPORT_FUNCTION(lcd128x64orientCoordinates); + EXPORT_FUNCTION(lcd128x64getScreenSize); + EXPORT_FUNCTION(lcd128x64point); + EXPORT_FUNCTION(lcd128x64line); + EXPORT_FUNCTION(lcd128x64lineTo); + EXPORT_FUNCTION(lcd128x64rectangle); + EXPORT_FUNCTION(lcd128x64circle); + EXPORT_FUNCTION(lcd128x64ellipse); + EXPORT_FUNCTION(lcd128x64putchar); + EXPORT_FUNCTION(lcd128x64puts); + EXPORT_FUNCTION(lcd128x64update); + EXPORT_FUNCTION(lcd128x64clear); + EXPORT_FUNCTION(lcd128x64setup); +} \ No newline at end of file diff --git a/src/devlib/lcd128x64.h b/src/devlib/lcd128x64.h new file mode 100644 index 0000000..5a7cb32 --- /dev/null +++ b/src/devlib/lcd128x64.h @@ -0,0 +1,8 @@ +#ifndef _WPI_LCD128X64_H_ +#define _WPI_LCD128X64_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(lcd128x64); + +#endif \ No newline at end of file diff --git a/src/devlib/maxdetect.cc b/src/devlib/maxdetect.cc new file mode 100644 index 0000000..75b674c --- /dev/null +++ b/src/devlib/maxdetect.cc @@ -0,0 +1,58 @@ +#include "maxdetect.h" +#include + +DECLARE(maxDetectRead); +DECLARE(readRHT03); + +IMPLEMENT(maxDetectRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + + unsigned char buffer[4]; + int res = ::maxDetectRead(pin, buffer); + + v8::Local data = v8::Array::New(4); + for (int i = 0; i < 4; i++) { + data->Set(i, Int32::New(buffer[i])); + } + + v8::Local ret = v8::Array::New(2); + ret->Set(0, Int32::New(res)); + ret->Set(1, data); + + SCOPE_CLOSE(ret); +} + +IMPLEMENT(readRHT03) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + + int temp, rh; + int res = ::readRHT03(pin, &temp, &rh); + + v8::Local ret = v8::Array::New(3); + ret->Set(0, v8::Int32::New(res)); + ret->Set(1, v8::Int32::New(temp)); + ret->Set(2, v8::Int32::New(rh)); + + SCOPE_CLOSE(ret); +} + +IMPLEMENT_EXPORT_INIT(maxdetect) { + EXPORT_FUNCTION(maxDetectRead); + EXPORT_FUNCTION(readRHT03); +} \ No newline at end of file diff --git a/src/devlib/maxdetect.h b/src/devlib/maxdetect.h new file mode 100644 index 0000000..d9e7d38 --- /dev/null +++ b/src/devlib/maxdetect.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MAXDETECT_H_ +#define _WPI_MAXDETECT_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(maxdetect); + +#endif \ No newline at end of file diff --git a/src/devlib/piFace.cc b/src/devlib/piFace.cc new file mode 100644 index 0000000..1efba8b --- /dev/null +++ b/src/devlib/piFace.cc @@ -0,0 +1,24 @@ +#include "piFace.h" +#include + +DECLARE(piFaceSetup); + +IMPLEMENT(piFaceSetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + + int res = ::piFaceSetup(pinBase); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(piFace) { + EXPORT_FUNCTION(piFaceSetup); +} \ No newline at end of file diff --git a/src/devlib/piFace.h b/src/devlib/piFace.h new file mode 100644 index 0000000..63bf848 --- /dev/null +++ b/src/devlib/piFace.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PI_FACE_H_ +#define _WPI_PI_FACE_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(piFace); + +#endif \ No newline at end of file diff --git a/src/devlib/piGlow.cc b/src/devlib/piGlow.cc new file mode 100644 index 0000000..ef89e11 --- /dev/null +++ b/src/devlib/piGlow.cc @@ -0,0 +1,97 @@ +#include "piGlow.h" +#include + +DECLARE(piGlow1); +DECLARE(piGlowLeg); +DECLARE(piGlowRing); +DECLARE(piGlowSetup); + +IMPLEMENT(piGlow1) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, leg); + SET_ARGUMENT_NAME(1, ring); + SET_ARGUMENT_NAME(2, intensity); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int leg = GET_ARGUMENT_AS_INT32(0); + int ring = GET_ARGUMENT_AS_INT32(1); + int intensity = GET_ARGUMENT_AS_INT32(2); + + ::piGlow1(leg, ring, intensity); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(piGlowLeg) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, leg); + SET_ARGUMENT_NAME(1, intensity); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int leg = GET_ARGUMENT_AS_INT32(0); + int intensity = GET_ARGUMENT_AS_INT32(1); + + ::piGlowLeg(leg, intensity); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(piGlowRing) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, ring); + SET_ARGUMENT_NAME(1, intensity); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int ring = GET_ARGUMENT_AS_INT32(0); + int intensity = GET_ARGUMENT_AS_INT32(1); + + ::piGlowRing(ring, intensity); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(piGlowSetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, clear); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int clear = GET_ARGUMENT_AS_INT32(0); + + ::piGlowSetup(clear); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(piGlow) { + EXPORT_FUNCTION(piGlow1); + EXPORT_FUNCTION(piGlowLeg); + EXPORT_FUNCTION(piGlowRing); + EXPORT_FUNCTION(piGlowSetup); + + EXPORT_CONSTANT_INT(PIGLOW_RED); + EXPORT_CONSTANT_INT(PIGLOW_YELLOW); + EXPORT_CONSTANT_INT(PIGLOW_ORANGE); + EXPORT_CONSTANT_INT(PIGLOW_GREEN); + EXPORT_CONSTANT_INT(PIGLOW_BLUE); + EXPORT_CONSTANT_INT(PIGLOW_WHITE); +} \ No newline at end of file diff --git a/src/devlib/piGlow.h b/src/devlib/piGlow.h new file mode 100644 index 0000000..b1dd98c --- /dev/null +++ b/src/devlib/piGlow.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PI_GLOW_H_ +#define _WPI_PI_GLOW_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(piGlow); + +#endif \ No newline at end of file diff --git a/src/devlib/piNes.cc b/src/devlib/piNes.cc new file mode 100644 index 0000000..f94d988 --- /dev/null +++ b/src/devlib/piNes.cc @@ -0,0 +1,58 @@ +#include "piNes.h" +#include + +DECLARE(setupNesJoystick); +DECLARE(readNesJoystick); + +IMPLEMENT(setupNesJoystick) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, dPin); + SET_ARGUMENT_NAME(1, cPin); + SET_ARGUMENT_NAME(2, lPin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int dPin = GET_ARGUMENT_AS_INT32(0); + int cPin = GET_ARGUMENT_AS_INT32(1); + int lPin = GET_ARGUMENT_AS_INT32(2); + + int res = ::setupNesJoystick(dPin, cPin, lPin); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT(readNesJoystick) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, joystick); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int joystick = GET_ARGUMENT_AS_INT32(0); + + unsigned int res = ::readNesJoystick(joystick); + + SCOPE_CLOSE(UINT32(res)); +} + +IMPLEMENT_EXPORT_INIT(piNes) { + EXPORT_FUNCTION(setupNesJoystick); + EXPORT_FUNCTION(readNesJoystick); + + EXPORT_CONSTANT_INT(MAX_NES_JOYSTICKS); + EXPORT_CONSTANT_INT(NES_RIGHT); + EXPORT_CONSTANT_INT(NES_LEFT); + EXPORT_CONSTANT_INT(NES_DOWN); + EXPORT_CONSTANT_INT(NES_UP); + EXPORT_CONSTANT_INT(NES_START); + EXPORT_CONSTANT_INT(NES_SELECT); + EXPORT_CONSTANT_INT(NES_A); + EXPORT_CONSTANT_INT(NES_B); +} \ No newline at end of file diff --git a/src/devlib/piNes.h b/src/devlib/piNes.h new file mode 100644 index 0000000..f7125a8 --- /dev/null +++ b/src/devlib/piNes.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PI_NES_H_ +#define _WPI_PI_NES_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(piNes); + +#endif \ No newline at end of file diff --git a/src/devlib/tcs34725.cc b/src/devlib/tcs34725.cc new file mode 100644 index 0000000..d25026d --- /dev/null +++ b/src/devlib/tcs34725.cc @@ -0,0 +1,244 @@ +#include +#include "tcs34725.h" + +DECLARE(tcs34725ReadRGBC); +DECLARE(tcs34725ReadHSV); +DECLARE(tcs34725GetCorrelatedColorTemperature); +DECLARE(tcs34725GetIlluminance); +DECLARE(tcs34725SetInterrupt); +DECLARE(tcs34725ClearInterrupt); +DECLARE(tcs34725SetInterruptLimits); +DECLARE(tcs34725Enable); +DECLARE(tcs34725Disable); +DECLARE(tcs34725Setup); + +IMPLEMENT(tcs34725ReadRGBC) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int id = GET_ARGUMENT_AS_INT32(0); + unsigned char r, g, b, c; + + ::tcs34725ReadRGBC(id, &r, &g, &b, &c); + + Local obj = Object::New(); + obj->Set(String::NewSymbol("r"), UINT32(r)); + obj->Set(String::NewSymbol("g"), UINT32(g)); + obj->Set(String::NewSymbol("b"), UINT32(b)); + obj->Set(String::NewSymbol("c"), UINT32(c)); + + SCOPE_CLOSE(obj); +} + +IMPLEMENT(tcs34725ReadHSV) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int id = GET_ARGUMENT_AS_INT32(0); + unsigned short h; + unsigned char s, v; + + ::tcs34725ReadHSV(id, &h, &s, &v); + + Local obj = Object::New(); + obj->Set(String::NewSymbol("h"), UINT32(h)); + obj->Set(String::NewSymbol("s"), UINT32(s)); + obj->Set(String::NewSymbol("v"), UINT32(v)); + + SCOPE_CLOSE(obj); +} + +IMPLEMENT(tcs34725GetCorrelatedColorTemperature) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, r); + SET_ARGUMENT_NAME(1, g); + SET_ARGUMENT_NAME(2, b); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_UINT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + + unsigned short r = GET_ARGUMENT_AS_UINT32(0); + unsigned short g = GET_ARGUMENT_AS_UINT32(1); + unsigned short b = GET_ARGUMENT_AS_UINT32(2); + + unsigned short k = ::tcs34725GetCorrelatedColorTemperature(r, g, b); + + SCOPE_CLOSE(UINT32(k)); +} + +IMPLEMENT(tcs34725GetIlluminance) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, r); + SET_ARGUMENT_NAME(1, g); + SET_ARGUMENT_NAME(2, b); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_UINT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + + unsigned short r = GET_ARGUMENT_AS_UINT32(0); + unsigned short g = GET_ARGUMENT_AS_UINT32(1); + unsigned short b = GET_ARGUMENT_AS_UINT32(2); + + unsigned short i = ::tcs34725GetIlluminance(r, g, b); + + SCOPE_CLOSE(UINT32(i)); +} + +IMPLEMENT(tcs34725SetInterrupt) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + SET_ARGUMENT_NAME(1, aien); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int id = GET_ARGUMENT_AS_INT32(0); + int aien = GET_ARGUMENT_AS_INT32(1); + + ::tcs34725SetInterrupt(id, aien); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(tcs34725ClearInterrupt) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int id = GET_ARGUMENT_AS_INT32(0); + + ::tcs34725ClearInterrupt(id); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(tcs34725SetInterruptLimits) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + SET_ARGUMENT_NAME(1, low); + SET_ARGUMENT_NAME(2, high); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + + int id = GET_ARGUMENT_AS_INT32(0); + int low = GET_ARGUMENT_AS_UINT32(1) & 0xFFFF; + int high = GET_ARGUMENT_AS_UINT32(2) & 0xFFFF; + + ::tcs34725SetInterruptLimits(id, low, high); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(tcs34725Enable) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int id = GET_ARGUMENT_AS_INT32(0); + + ::tcs34725Enable(id); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(tcs34725Disable) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, id); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int id = GET_ARGUMENT_AS_INT32(0); + + ::tcs34725Disable(id); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(tcs34725Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, i2cAddress); + SET_ARGUMENT_NAME(1, integrationTime); + SET_ARGUMENT_NAME(2, gain); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int i2cAddress = GET_ARGUMENT_AS_INT32(0); + int integrationTime = GET_ARGUMENT_AS_INT32(1); + int gain = GET_ARGUMENT_AS_INT32(2); + + CHECK_ARGUMENT_IN_INTS(1, integrationTime, (TCS34725_ATIME_2_4MS, TCS34725_ATIME_24MS, TCS34725_ATIME_50MS, TCS34725_ATIME_101MS, TCS34725_ATIME_154MS, TCS34725_ATIME_700MS)); + CHECK_ARGUMENT_IN_INTS(2, gain, (TCS34725_GAIN_1, TCS34725_GAIN_4, TCS34725_GAIN_16, TCS34725_GAIN_60)); + + int id = ::tcs34725Setup(i2cAddress, integrationTime, gain); + + SCOPE_CLOSE(INT32(id)); +} + +IMPLEMENT_EXPORT_INIT(tcs34725) { + EXPORT_FUNCTION(tcs34725ReadRGBC); + EXPORT_FUNCTION(tcs34725ReadHSV); + EXPORT_FUNCTION(tcs34725GetCorrelatedColorTemperature); + EXPORT_FUNCTION(tcs34725GetIlluminance); + EXPORT_FUNCTION(tcs34725SetInterrupt); + EXPORT_FUNCTION(tcs34725ClearInterrupt); + EXPORT_FUNCTION(tcs34725SetInterruptLimits); + EXPORT_FUNCTION(tcs34725Enable); + EXPORT_FUNCTION(tcs34725Disable); + EXPORT_FUNCTION(tcs34725Setup); + + EXPORT_CONSTANT_INT(TCS34725_ATIME_2_4MS); + EXPORT_CONSTANT_INT(TCS34725_ATIME_24MS); + EXPORT_CONSTANT_INT(TCS34725_ATIME_50MS); + EXPORT_CONSTANT_INT(TCS34725_ATIME_101MS); + EXPORT_CONSTANT_INT(TCS34725_ATIME_154MS); + EXPORT_CONSTANT_INT(TCS34725_ATIME_700MS); + + EXPORT_CONSTANT_INT(TCS34725_GAIN_1); + EXPORT_CONSTANT_INT(TCS34725_GAIN_4); + EXPORT_CONSTANT_INT(TCS34725_GAIN_16); + EXPORT_CONSTANT_INT(TCS34725_GAIN_60); + + EXPORT_CONSTANT_INT(TCS34725_MAX_TCS34725); +} \ No newline at end of file diff --git a/src/devlib/tcs34725.h b/src/devlib/tcs34725.h new file mode 100644 index 0000000..7655481 --- /dev/null +++ b/src/devlib/tcs34725.h @@ -0,0 +1,8 @@ +#ifndef _WPI_TCS34725_H_ +#define _WPI_TCS34725_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(tcs34725); + +#endif \ No newline at end of file diff --git a/src/extensions/dac7678.cc b/src/extensions/dac7678.cc new file mode 100644 index 0000000..ca1ded0 --- /dev/null +++ b/src/extensions/dac7678.cc @@ -0,0 +1,43 @@ +#include "dac7678.h" +#include +#include + +DECLARE(dac7678Setup); + +IMPLEMENT(dac7678Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + SET_ARGUMENT_NAME(2, vrefMode); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + unsigned short vrefMode = GET_ARGUMENT_AS_UINT32(2); + + CHECK_ARGUMENT_IN_INTS(2, vrefMode, (DAC7678_VREF_MODE_STATIC_ON, + DAC7678_VREF_MODE_STATIC_OFF, + DAC7678_VREF_MODE_FLEXIBLE_ON, + DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_ON, + DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_OFF)); + + int res = ::dac7678Setup(pinBase, i2cAddress, vrefMode); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(dac7678) { + EXPORT_FUNCTION(dac7678Setup); + + EXPORT_CONSTANT_INT(DAC7678_VREF_MODE_STATIC_ON); + EXPORT_CONSTANT_INT(DAC7678_VREF_MODE_STATIC_OFF); + EXPORT_CONSTANT_INT(DAC7678_VREF_MODE_FLEXIBLE_ON); + EXPORT_CONSTANT_INT(DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_ON); + EXPORT_CONSTANT_INT(DAC7678_VREF_MODE_FLEXIBLE_ALWAYS_OFF); +} \ No newline at end of file diff --git a/src/extensions/dac7678.h b/src/extensions/dac7678.h new file mode 100644 index 0000000..d0e8a6c --- /dev/null +++ b/src/extensions/dac7678.h @@ -0,0 +1,8 @@ +#ifndef _WPI_DAC7678_H_ +#define _WPI_DAC7678_H_ + +#include "../addon.h" + +DECLARE_EXPORT_INIT(dac7678); + +#endif \ No newline at end of file diff --git a/src/extensions/drcSerial.cc b/src/extensions/drcSerial.cc new file mode 100644 index 0000000..1a7bf1a --- /dev/null +++ b/src/extensions/drcSerial.cc @@ -0,0 +1,37 @@ +#include "drcSerial.h" +#include +#include + +DECLARE(drcSetupSerial); + +// Func : int drcSetupSerial(const int pinBase, const int numPins, const char* device, const int baud) +// Description : https://projects.drogon.net/drogon-remote-control/drc-protocol-arduino/ + +IMPLEMENT(drcSetupSerial) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, numPins); + SET_ARGUMENT_NAME(2, device); + SET_ARGUMENT_NAME(3, baudrate); + + CHECK_ARGUMENTS_LENGTH_EQUAL(4); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_STRING(2); + CHECK_ARGUMENT_TYPE_INT32(3); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int numPins = GET_ARGUMENT_AS_INT32(1); + String::AsciiValue device(GET_ARGUMENT_AS_STRING(2)); + int baudrate = GET_ARGUMENT_AS_INT32(3); + + int res = ::drcSetupSerial(pinBase, numPins, *device, baudrate); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(drcSerial) { + EXPORT_FUNCTION(drcSetupSerial); +} \ No newline at end of file diff --git a/src/extensions/drcSerial.h b/src/extensions/drcSerial.h new file mode 100644 index 0000000..76e3417 --- /dev/null +++ b/src/extensions/drcSerial.h @@ -0,0 +1,8 @@ +#ifndef _WPI_DRC_SERIAL_H_ +#define _WPI_DRC_SERIAL_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(drcSerial); + +#endif \ No newline at end of file diff --git a/src/extensions/extensions.cc b/src/extensions/extensions.cc new file mode 100644 index 0000000..2f3002e --- /dev/null +++ b/src/extensions/extensions.cc @@ -0,0 +1,38 @@ +#include "extensions.h" + +#include "drcSerial.h" +#include "max5322.h" +#include "max31855.h" +#include "mcp23s08.h" +#include "mcp23s17.h" +#include "mcp3002.h" +#include "mcp3004.h" +#include "mcp3422.h" +#include "mcp4802.h" +#include "mcp23008.h" +#include "mcp23016.h" +#include "mcp23017.h" +#include "pcf8574.h" +#include "pcf8591.h" +#include "sn3218.h" +#include "sr595.h" +#include "pca9685.h" + +IMPLEMENT_EXPORT_INIT(extensions) { + INIT(drcSerial); + INIT(max5322); + INIT(max31855); + INIT(mcp23s08); + INIT(mcp23s17); + INIT(mcp3002); + INIT(mcp3004); + INIT(mcp3422); + INIT(mcp4802); + INIT(mcp23008); + INIT(mcp23016); + INIT(mcp23017); + INIT(pcf8574); + INIT(pcf8591); + INIT(sr595); + INIT(pca9685); +} \ No newline at end of file diff --git a/src/extensions/extensions.h b/src/extensions/extensions.h new file mode 100644 index 0000000..c2a90a4 --- /dev/null +++ b/src/extensions/extensions.h @@ -0,0 +1,8 @@ +#ifndef _WPI_EXTENSIONS_H_ +#define _WPI_EXTENSIONS_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(extensions); + +#endif \ No newline at end of file diff --git a/src/extensions/max31855.cc b/src/extensions/max31855.cc new file mode 100644 index 0000000..65a3f8c --- /dev/null +++ b/src/extensions/max31855.cc @@ -0,0 +1,31 @@ +#include "max31855.h" +#include + +DECLARE(max31855Setup); + +// Func : int max31855Setup(int pinBase, int spiChannel) + +IMPLEMENT(max31855Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + int res = ::max31855Setup(pinBase, spiChannel); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(max31855) { + EXPORT_FUNCTION(max31855Setup); +} \ No newline at end of file diff --git a/src/extensions/max31855.h b/src/extensions/max31855.h new file mode 100644 index 0000000..caebaeb --- /dev/null +++ b/src/extensions/max31855.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MAX31855_H_ +#define _WPI_MAX31855_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(max31855); + +#endif \ No newline at end of file diff --git a/src/extensions/max5322.cc b/src/extensions/max5322.cc new file mode 100644 index 0000000..9b945b4 --- /dev/null +++ b/src/extensions/max5322.cc @@ -0,0 +1,32 @@ +#include "max5322.h" +#include + +DECLARE(max5322Setup); + +// Func : int max5233Setup(int pinBase, int spiChannel) + +IMPLEMENT(max5322Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + int res = ::max5322Setup(pinBase, spiChannel); + + SCOPE_CLOSE(INT32(res)); +} + + +IMPLEMENT_EXPORT_INIT(max5322) { + EXPORT_FUNCTION(max5322Setup); +} \ No newline at end of file diff --git a/src/extensions/max5322.h b/src/extensions/max5322.h new file mode 100644 index 0000000..912d267 --- /dev/null +++ b/src/extensions/max5322.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MAX5322_H_ +#define _WPI_MAX5322_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(max5322); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp23008.cc b/src/extensions/mcp23008.cc new file mode 100644 index 0000000..f254d34 --- /dev/null +++ b/src/extensions/mcp23008.cc @@ -0,0 +1,29 @@ +#include "mcp23008.h" +#include + +DECLARE(mcp23008Setup); + +// Func : int mcp23008Setup(int pinBase, int i2cAddress) + +IMPLEMENT(mcp23008Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + + int res = ::mcp23008Setup(pinBase, i2cAddress); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp23008) { + EXPORT_FUNCTION(mcp23008Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp23008.h b/src/extensions/mcp23008.h new file mode 100644 index 0000000..5297854 --- /dev/null +++ b/src/extensions/mcp23008.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP23008_H_ +#define _WPI_MCP23008_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp23008); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp23016.cc b/src/extensions/mcp23016.cc new file mode 100644 index 0000000..46f2751 --- /dev/null +++ b/src/extensions/mcp23016.cc @@ -0,0 +1,29 @@ +#include "mcp23016.h" +#include + +DECLARE(mcp23016Setup); + +// Func : int mcp23016Setup(int pinBase, int i2cAddress) + +IMPLEMENT(mcp23016Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + + int res = ::mcp23016Setup(pinBase, i2cAddress); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp23016) { + EXPORT_FUNCTION(mcp23016Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp23016.h b/src/extensions/mcp23016.h new file mode 100644 index 0000000..64a6761 --- /dev/null +++ b/src/extensions/mcp23016.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP23016_H_ +#define _WPI_MCP23016_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp23016); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp23017.cc b/src/extensions/mcp23017.cc new file mode 100644 index 0000000..aebdc8b --- /dev/null +++ b/src/extensions/mcp23017.cc @@ -0,0 +1,29 @@ +#include "mcp23017.h" +#include + +DECLARE(mcp23017Setup); + +// Func : int mcp23017Setup(int pinBase, int i2cAddress) + +IMPLEMENT(mcp23017Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + + int res = ::mcp23017Setup(pinBase, i2cAddress); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp23017) { + EXPORT_FUNCTION(mcp23017Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp23017.h b/src/extensions/mcp23017.h new file mode 100644 index 0000000..4ca67ff --- /dev/null +++ b/src/extensions/mcp23017.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP23017_H_ +#define _WPI_MCP23017_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp23017); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp23s08.cc b/src/extensions/mcp23s08.cc new file mode 100644 index 0000000..94bd38f --- /dev/null +++ b/src/extensions/mcp23s08.cc @@ -0,0 +1,37 @@ +#include "mcp23s08.h" +#include + +DECLARE(mcp23s08Setup); + +// Func int mcp23s08Setup(const int pinBase, const int spiChannel, const int devId) + +IMPLEMENT(mcp23s08Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + SET_ARGUMENT_NAME(2, devId); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + int devId = GET_ARGUMENT_AS_INT32(2); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + //MCP23S08 3bits addressing + CHECK_ARGUMENT_IN_RANGE(2, devId, 0, 7); + + int res = ::mcp23s08Setup(pinBase, spiChannel, devId); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp23s08) { + EXPORT_FUNCTION(mcp23s08Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp23s08.h b/src/extensions/mcp23s08.h new file mode 100644 index 0000000..2eabae4 --- /dev/null +++ b/src/extensions/mcp23s08.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP23S08_H_ +#define _WPI_MCP23S08_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp23s08); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp23s17.cc b/src/extensions/mcp23s17.cc new file mode 100644 index 0000000..3352812 --- /dev/null +++ b/src/extensions/mcp23s17.cc @@ -0,0 +1,40 @@ +#include "mcp23s17.h" +#include + +DECLARE(mcp23s17Setup); + +// Func : int mcp23s17Setup(int pinBase, int spiPort, int devId) +// Description : Initialise libWiringPi to be used with MCP23S17 +// pinBase is any number above 64 that doesn’t clash with any other wiringPi expansion module, +// spiPort is 0 or 1 for one of the two SPI ports on the Pi and devId is the ID of that MCP23s17 on the SPI port. + +IMPLEMENT(mcp23s17Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + SET_ARGUMENT_NAME(2, devId); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + int devId = GET_ARGUMENT_AS_INT32(2); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + //MCP23S17 3bits addressing + CHECK_ARGUMENT_IN_RANGE(2, devId, 0, 7); + + int res = ::mcp23s17Setup(pinBase, spiChannel, devId); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp23s17) { + EXPORT_FUNCTION(mcp23s17Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp23s17.h b/src/extensions/mcp23s17.h new file mode 100644 index 0000000..9e71198 --- /dev/null +++ b/src/extensions/mcp23s17.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP23S17_H_ +#define _WPI_MCP23S17_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp23s17); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp3002.cc b/src/extensions/mcp3002.cc new file mode 100644 index 0000000..1332690 --- /dev/null +++ b/src/extensions/mcp3002.cc @@ -0,0 +1,31 @@ +#include "mcp3002.h" +#include + +DECLARE(mcp3002Setup); + +// Func : int mcp3002Setup(int pinBase, int spiChannel) + +IMPLEMENT(mcp3002Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + int res = ::mcp3002Setup(pinBase, spiChannel); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp3002) { + EXPORT_FUNCTION(mcp3002Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp3002.h b/src/extensions/mcp3002.h new file mode 100644 index 0000000..242c3b7 --- /dev/null +++ b/src/extensions/mcp3002.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP3002_H_ +#define _WPI_MCP3002_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp3002); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp3004.cc b/src/extensions/mcp3004.cc new file mode 100644 index 0000000..78bbc60 --- /dev/null +++ b/src/extensions/mcp3004.cc @@ -0,0 +1,31 @@ +#include "mcp3004.h" +#include + +DECLARE(mcp3004Setup); + +// Func : int mcp3004Setup(int pinBase, int spiChannel) + +IMPLEMENT(mcp3004Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + int res = ::mcp3004Setup(pinBase, spiChannel); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp3004) { + EXPORT_FUNCTION(mcp3004Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp3004.h b/src/extensions/mcp3004.h new file mode 100644 index 0000000..176ca0b --- /dev/null +++ b/src/extensions/mcp3004.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP3004_H_ +#define _WPI_MCP3004_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp3004); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp3422.cc b/src/extensions/mcp3422.cc new file mode 100644 index 0000000..30211a0 --- /dev/null +++ b/src/extensions/mcp3422.cc @@ -0,0 +1,48 @@ +#include "mcp3422.h" +#include + +DECLARE(mcp3422Setup); + +// Func : int mcp3422Setup(int pinBase, int i2cAddress, int sampleRate, int gain) + +IMPLEMENT(mcp3422Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + SET_ARGUMENT_NAME(2, sampleRate); + SET_ARGUMENT_NAME(3, gain); + + CHECK_ARGUMENTS_LENGTH_EQUAL(4); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + int sampleRate = GET_ARGUMENT_AS_INT32(2); + int gain = GET_ARGUMENT_AS_INT32(3); + + CHECK_ARGUMENT_IN_INTS(2, sampleRate, (MCP3422_SR_3_75, MCP3422_SR_15, MCP3422_SR_60, MCP3422_SR_240)); + CHECK_ARGUMENT_IN_INTS(3, gain, (MCP3422_GAIN_1, MCP3422_GAIN_2, MCP3422_GAIN_4, MCP3422_GAIN_8)); + + int res = ::mcp3422Setup(pinBase, i2cAddress, sampleRate, gain); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp3422) { + EXPORT_FUNCTION(mcp3422Setup); + + EXPORT_CONSTANT_INT(MCP3422_SR_3_75); + EXPORT_CONSTANT_INT(MCP3422_SR_15); + EXPORT_CONSTANT_INT(MCP3422_SR_60); + EXPORT_CONSTANT_INT(MCP3422_SR_240); + + EXPORT_CONSTANT_INT(MCP3422_GAIN_1); + EXPORT_CONSTANT_INT(MCP3422_GAIN_2); + EXPORT_CONSTANT_INT(MCP3422_GAIN_4); + EXPORT_CONSTANT_INT(MCP3422_GAIN_8); +} \ No newline at end of file diff --git a/src/extensions/mcp3422.h b/src/extensions/mcp3422.h new file mode 100644 index 0000000..57bfe74 --- /dev/null +++ b/src/extensions/mcp3422.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP3422_H_ +#define _WPI_MCP3422_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp3422); + +#endif \ No newline at end of file diff --git a/src/extensions/mcp4802.cc b/src/extensions/mcp4802.cc new file mode 100644 index 0000000..f12732e --- /dev/null +++ b/src/extensions/mcp4802.cc @@ -0,0 +1,31 @@ +#include "mcp4802.h" +#include + +DECLARE(mcp4802Setup); + +// Func : int mcp4802Setup(int pinBase, int spiChannel) + +IMPLEMENT(mcp4802Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, spiChannel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int spiChannel = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, spiChannel, (0, 1)); + + int res = ::mcp4802Setup(pinBase, spiChannel); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(mcp4802) { + EXPORT_FUNCTION(mcp4802Setup); +} \ No newline at end of file diff --git a/src/extensions/mcp4802.h b/src/extensions/mcp4802.h new file mode 100644 index 0000000..a8d887f --- /dev/null +++ b/src/extensions/mcp4802.h @@ -0,0 +1,8 @@ +#ifndef _WPI_MCP4802_H_ +#define _WPI_MCP4802_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(mcp4802); + +#endif \ No newline at end of file diff --git a/src/extensions/pca9685.cc b/src/extensions/pca9685.cc new file mode 100644 index 0000000..309347c --- /dev/null +++ b/src/extensions/pca9685.cc @@ -0,0 +1,30 @@ +#include "pca9685.h" +#include + +DECLARE(pca9685Setup); + +IMPLEMENT(pca9685Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + SET_ARGUMENT_NAME(2, frequency); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + int freq = GET_ARGUMENT_AS_INT32(2); + + int res = ::pca9685Setup(pinBase, i2cAddress, freq); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(pca9685) { + EXPORT_FUNCTION(pca9685Setup); +} \ No newline at end of file diff --git a/src/extensions/pca9685.h b/src/extensions/pca9685.h new file mode 100644 index 0000000..bbf4dc3 --- /dev/null +++ b/src/extensions/pca9685.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PCA9685_H_ +#define _WPI_PCA9685_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(pca9685); + +#endif \ No newline at end of file diff --git a/src/extensions/pcf8574.cc b/src/extensions/pcf8574.cc new file mode 100644 index 0000000..7e10b5b --- /dev/null +++ b/src/extensions/pcf8574.cc @@ -0,0 +1,29 @@ +#include "pcf8574.h" +#include + +DECLARE(pcf8574Setup); + +// Func : int pcf8574Setup(const int pinBase, const int i2cAddress) + +IMPLEMENT(pcf8574Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + + int res = ::pcf8574Setup(pinBase, i2cAddress); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(pcf8574) { + EXPORT_FUNCTION(pcf8574Setup); +} \ No newline at end of file diff --git a/src/extensions/pcf8574.h b/src/extensions/pcf8574.h new file mode 100644 index 0000000..53d42a2 --- /dev/null +++ b/src/extensions/pcf8574.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PCF8574_H_ +#define _WPI_PCF8574_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(pcf8574); + +#endif \ No newline at end of file diff --git a/src/extensions/pcf8591.cc b/src/extensions/pcf8591.cc new file mode 100644 index 0000000..fd9744a --- /dev/null +++ b/src/extensions/pcf8591.cc @@ -0,0 +1,29 @@ +#include "pcf8591.h" +#include + +DECLARE(pcf8591Setup); + +// Func : int pcf8591Setup(const int pinBase, const int i2cAddress) + +IMPLEMENT(pcf8591Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, i2cAddress); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int i2cAddress = GET_ARGUMENT_AS_INT32(1); + + int res = ::pcf8591Setup(pinBase, i2cAddress); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(pcf8591) { + EXPORT_FUNCTION(pcf8591Setup); +} \ No newline at end of file diff --git a/src/extensions/pcf8591.h b/src/extensions/pcf8591.h new file mode 100644 index 0000000..2cfa1d9 --- /dev/null +++ b/src/extensions/pcf8591.h @@ -0,0 +1,8 @@ +#ifndef _WPI_PCF8591_H_ +#define _WPI_PCF8591_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(pcf8591); + +#endif \ No newline at end of file diff --git a/src/extensions/sn3218.cc b/src/extensions/sn3218.cc new file mode 100644 index 0000000..d125cc4 --- /dev/null +++ b/src/extensions/sn3218.cc @@ -0,0 +1,26 @@ +#include "sn3218.h" +#include + +DECLARE(sn3218Setup); + +// Func : int sn3128Setup(int pinBase) + +IMPLEMENT(sn3218Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + + int res = ::sn3218Setup(pinBase); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(sn3218) { + EXPORT_FUNCTION(sn3218Setup); +} \ No newline at end of file diff --git a/src/extensions/sn3218.h b/src/extensions/sn3218.h new file mode 100644 index 0000000..a1ce2f4 --- /dev/null +++ b/src/extensions/sn3218.h @@ -0,0 +1,8 @@ +#ifndef _WPI_SN3218_H_ +#define _WPI_SN3218_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(sn3218); + +#endif \ No newline at end of file diff --git a/src/extensions/sr595.cc b/src/extensions/sr595.cc new file mode 100644 index 0000000..0db70fd --- /dev/null +++ b/src/extensions/sr595.cc @@ -0,0 +1,38 @@ +#include "sr595.h" +#include + +DECLARE(sr595Setup); + +// Func : int sr595Setup(const int pinBase, const int numPins, const int dataPin, const int clockPin, const int latchPin) + +IMPLEMENT(sr595Setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pinBase); + SET_ARGUMENT_NAME(1, numPins); + SET_ARGUMENT_NAME(2, dataPin); + SET_ARGUMENT_NAME(3, clockPin); + SET_ARGUMENT_NAME(4, latchPin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(5); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + + int pinBase = GET_ARGUMENT_AS_INT32(0); + int numPins = GET_ARGUMENT_AS_INT32(1); + int dataPin = GET_ARGUMENT_AS_INT32(2); + int clockPin = GET_ARGUMENT_AS_INT32(3); + int latchPin = GET_ARGUMENT_AS_INT32(4); + + int res = ::sr595Setup(pinBase, numPins, dataPin, clockPin, latchPin); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(sr595) { + EXPORT_FUNCTION(sr595Setup); +} \ No newline at end of file diff --git a/src/extensions/sr595.h b/src/extensions/sr595.h new file mode 100644 index 0000000..e25bfb6 --- /dev/null +++ b/src/extensions/sr595.h @@ -0,0 +1,8 @@ +#ifndef _WPI_SR595_H_ +#define _WPI_SR595_H_ + + #include "../addon.h" + + DECLARE_EXPORT_INIT(sr595); + +#endif \ No newline at end of file diff --git a/src/softPwm.cc b/src/softPwm.cc new file mode 100644 index 0000000..a9cdd04 --- /dev/null +++ b/src/softPwm.cc @@ -0,0 +1,86 @@ +#include "softPwm.h" +#include + +DECLARE(softPwmCreate); +DECLARE(softPwmWrite); +DECLARE(softPwmStop); + +// Func : int softPwmCreate(int pin, int value, int range) +// Description : This creates a software controlled PWM pin. +// You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. +// Use 100 for the pwmRange, then the value can be anything from 0 (off) to 100 (fully on) for the given pin. +// The return value is 0 for success. Anything else and you should check the global errno variable to see what went wrong. +// NOTE : You must initialise wiringPi with one of wiringPiSetup(), wiringPiSetupGpio() or wiringPiSetupPhys() functions. +// wiringPiSetupSys() is not fast enough, so you must run your programs with sudo. +// NOTE2 : Each “cycle” of PWM output takes 10mS with the default range value of 100, +// so trying to change the PWM value more than 100 times a second will be futile. +// NOTE3 : Each pin activated in softPWM mode uses approximately 0.5% of the CPU. +// NOTE4 : There is currently no way to disable softPWM on a pin while the program in running. +// NOTE5 : You need to keep your program running to maintain the PWM output! + +IMPLEMENT(softPwmCreate) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, value); + SET_ARGUMENT_NAME(2, range); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int pin = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + int range = GET_ARGUMENT_AS_INT32(2); + + int res = ::softPwmCreate(pin, value, range); + + SCOPE_CLOSE(INT32(res)); +} + +// Func void softPwmWrite(int pin, int value) +// Description : This updates the PWM value on the given pin. +// The value is checked to be in-range and pins that haven’t previously been initialised via softPwmCreate will be silently ignored. + +IMPLEMENT(softPwmWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + + ::softPwmWrite(pin, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(softPwmStop) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + + ::softPwmStop(pin); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(softPwm) { + EXPORT_FUNCTION(softPwmCreate); + EXPORT_FUNCTION(softPwmWrite); + EXPORT_FUNCTION(softPwmStop); +} \ No newline at end of file diff --git a/src/softPwm.h b/src/softPwm.h new file mode 100644 index 0000000..33db755 --- /dev/null +++ b/src/softPwm.h @@ -0,0 +1,8 @@ +#ifndef _WPI_SOFT_PWM_H_ +#define _WPI_SOFT_PWM_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(softPwm); + +#endif \ No newline at end of file diff --git a/src/softServo.cc b/src/softServo.cc new file mode 100644 index 0000000..f082efb --- /dev/null +++ b/src/softServo.cc @@ -0,0 +1,72 @@ +#include "softServo.h" +#include + +DECLARE(softServoWrite); +DECLARE(softServoSetup); + +// Func : void softServoWrite(int pin, int value) +// Description : Write a Servo value to the given pin + +IMPLEMENT(softServoWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + + ::softServoWrite(pin, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : int softServoSetup(int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7) +// Description : Setup the software servo system + +IMPLEMENT(softServoSetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, p0); + SET_ARGUMENT_NAME(1, p1); + SET_ARGUMENT_NAME(2, p2); + SET_ARGUMENT_NAME(3, p3); + SET_ARGUMENT_NAME(4, p4); + SET_ARGUMENT_NAME(5, p5); + SET_ARGUMENT_NAME(6, p6); + SET_ARGUMENT_NAME(7, p7); + + CHECK_ARGUMENTS_LENGTH_EQUAL(8); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + CHECK_ARGUMENT_TYPE_INT32(3); + CHECK_ARGUMENT_TYPE_INT32(4); + CHECK_ARGUMENT_TYPE_INT32(5); + CHECK_ARGUMENT_TYPE_INT32(6); + CHECK_ARGUMENT_TYPE_INT32(7); + + int p0 = GET_ARGUMENT_AS_INT32(0); + int p1 = GET_ARGUMENT_AS_INT32(1); + int p2 = GET_ARGUMENT_AS_INT32(2); + int p3 = GET_ARGUMENT_AS_INT32(3); + int p4 = GET_ARGUMENT_AS_INT32(4); + int p5 = GET_ARGUMENT_AS_INT32(5); + int p6 = GET_ARGUMENT_AS_INT32(6); + int p7 = GET_ARGUMENT_AS_INT32(7); + + int res = ::softServoSetup(p0, p1, p2, p3, p4, p5, p6, p7); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(softServo) { + EXPORT_FUNCTION(softServoWrite); + EXPORT_FUNCTION(softServoSetup); +} \ No newline at end of file diff --git a/src/softServo.h b/src/softServo.h new file mode 100644 index 0000000..f079730 --- /dev/null +++ b/src/softServo.h @@ -0,0 +1,8 @@ +#ifndef _WPI_SOFT_SERVO_H_ +#define _WPI_SOFT_SERVO_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(softServo); + +#endif \ No newline at end of file diff --git a/src/softTone.cc b/src/softTone.cc new file mode 100644 index 0000000..61999e3 --- /dev/null +++ b/src/softTone.cc @@ -0,0 +1,76 @@ +#include "softTone.h" +#include + +DECLARE(softToneCreate); +DECLARE(softToneWrite); +DECLARE(softToneStop); + +// Func : int softToneCreate(int pin); +// Description : This creates a software controlled tone pin. +// You can use any GPIO pin and the pin numbering will be that of the wiringPiSetup() function you used. +// The return value is 0 for success. +// Anything else and you should check the global errno variable to see what went wrong. +// NOTE : You must initialise wiringPi with one of wiringPiSetup(), wiringPiSetupGpio() or wiringPiSetupPhys() functions. +// wiringPiSetupSys() is not fast enough, so you must run your programs with sudo. +// NOTE2 : Each pin activated in softTone mode uses approximately 0.5% of the CPU. +// NOTE3 : You need to keep your program running to maintain the sound output! + +IMPLEMENT(softToneCreate) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + + int res = ::softToneCreate(pin); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void softToneWrite(int pin, int freq); +// Description : This updates the tone frequency value on the given pin. The tone will be played until you set the frequency to 0. + +IMPLEMENT(softToneWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, frequency); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int frequency = GET_ARGUMENT_AS_INT32(1); + + ::softToneWrite(pin, frequency); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(softToneStop) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + + ::softToneStop(pin); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(softTone) { + EXPORT_FUNCTION(softToneCreate); + EXPORT_FUNCTION(softToneWrite); + EXPORT_FUNCTION(softToneStop); +} \ No newline at end of file diff --git a/src/softTone.h b/src/softTone.h new file mode 100644 index 0000000..a96682f --- /dev/null +++ b/src/softTone.h @@ -0,0 +1,8 @@ +#ifndef _WPI_SOFT_TONE_H_ +#define _WPI_SOFT_TONE_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(softTone); + +#endif \ No newline at end of file diff --git a/src/wiringPi.cc b/src/wiringPi.cc new file mode 100644 index 0000000..6f862f5 --- /dev/null +++ b/src/wiringPi.cc @@ -0,0 +1,747 @@ +#include "wiringPi.h" +#include +#include + +// Setup +DECLARE(setup); +DECLARE(wiringPiSetup); +DECLARE(wiringPiSetupGpio); +DECLARE(wiringPiSetupSys); +DECLARE(wiringPiSetupPhys); + +// Core functions +DECLARE(pinModeAlt); +DECLARE(pinMode); +DECLARE(pullUpDnControl); +DECLARE(digitalRead); +DECLARE(digitalWrite); +DECLARE(pwmWrite); +DECLARE(analogRead); +DECLARE(analogWrite); +DECLARE(pulseIn); + +DECLARE(delay); +DECLARE(delayMicroseconds); +DECLARE(millis); +DECLARE(micros); + +// On-Board Rasberry Pi hardware specific stuff +DECLARE(piBoardRev); +DECLARE(piBoardId); +DECLARE(wpiPinToGpio); +DECLARE(physPinToGpio); +DECLARE(setPadDrive); +DECLARE(getAlt); +DECLARE(pwmToneWrite); +DECLARE(digitalWriteByte); +DECLARE(pwmSetMode); +DECLARE(pwmSetRange); +DECLARE(pwmSetClock); +DECLARE(gpioClockSet); + +IMPLEMENT(setup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, mode); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_STRING(0); + + String::AsciiValue mode(GET_ARGUMENT_AS_STRING(0)); + + CHECK_ARGUMENT_IN_STRINGS(0, mode, ("wpi", "gpio", "sys", "phys")); + + int res = 0; + if (!strcasecmp(*mode, "wpi")) { + res = ::wiringPiSetup(); + } + else if (!strcasecmp(*mode, "gpio")) { + res = ::wiringPiSetupGpio(); + } + else if (!strcasecmp(*mode, "sys")) { + res = ::wiringPiSetupSys(); + } + else if (!strcasecmp(*mode, "phys")) { + res = ::wiringPiSetupPhys(); + } + + // libWiringPi v2 setup functions always returns 0, so this check is kind of useless, unless v1 behaviour is restored + // NOTE: If you want to restore the v1 behaviour, then you need to set the + // environment variable: WIRINGPI_CODES (to any value, it just needs to exist) + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiSetup(void) +// Returns : error code if v1 mode otherwise always returns 0 +// Description : Initialises wiringPi and assumes that the calling program is going +// to be using the wiringPi pin numbering scheme. +// This is a simplified numbering scheme which provides a mapping from virtual +// pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. +// see the pins page (https://projects.drogon.net/raspberry-pi/wiringpi/pins/) for a table +// which maps the wiringPi pin number to the Broadcom GPIO pin number to the physical location +// on the edge connector. +// This function needs to be called with root privileges. + +IMPLEMENT(wiringPiSetup) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::wiringPiSetup(); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiSetupGpio(void) +// Returns : error code if v1 mode otherwise always returns 0 +// Description : This is indential to above, however it allows the calling programs to use +// the Broadcom GPIO pin numbers directly with no re-mapping. +// As above, this function needs to be called with root privileges, and note that some pins +// are different from revision 1 to revision 2 boards. + +IMPLEMENT(wiringPiSetupGpio) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::wiringPiSetupGpio(); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiSetupSys(void) +// Returns : error code if v1 mode otherwise always returns 0 +// Description : This initialises wiringPi but uses the /sys/class/gpio interface rather than +// accessing the hardware directly. This can be called as a non-root user provided the GPIO pins +// have been exported before-hand using gpio program. Pin numbering in this mode is the native +// Broadcom GPIO numbers - the same as wiringPiSetGpio above, so be aware of the differences +// between Rev 1 and Rev 2 boards. +// Note: In this mode you can only use the pins which have been exported via the +// /sys/class/gpio interface before you run your program. You can do this in a seperate +// shell script, or by using the system() function from inside your program to call the gpio program. +// Also note that some functions have no effect when using this mode as they're not currently +// possible to action unless called with root privileges. (although you can use system() to call +// gpio to set/change modes if needed). + +IMPLEMENT(wiringPiSetupSys) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::wiringPiSetupSys(); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiSetupPhys(void) +// Returns : error code if v1 mode otherwise always returns 0 +// Description : Identical to above, however it allows the calling programs to use +// the physical pin numbers on the P1 connector only. +// As above, this function needs to be called with root priviliges. + +IMPLEMENT(wiringPiSetupPhys) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::wiringPiSetupPhys(); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void pinModeAlt(int pin, int mode) +// Description : This is an un-documented special to let you set any pin to any mode. +// Modes are WPI_MODE_PINS, WPI_MODE_PHYS, WPI_MODE_GPIO. + +IMPLEMENT(pinModeAlt) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, mode); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int mode = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, mode, (WPI_MODE_PINS, WPI_MODE_PHYS, WPI_MODE_GPIO)); + + ::pinModeAlt(pin, mode); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pinMode(int pin, int mode) +// Description : This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. +// Note that only wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) +// supports CLOCK output modes. +// This function has no effect when in Sys mode. If you need to change the pin mode, the you can +// do it with the gpio program in a script before you start your program. + +IMPLEMENT(pinMode) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, mode); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int mode = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, mode, (INPUT, OUTPUT, PWM_OUTPUT, GPIO_CLOCK, SOFT_PWM_OUTPUT, SOFT_TONE_OUTPUT)); + + ::pinMode(pin, mode); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pullUpDnControl(int pin, int pud) +// Description : This sets the pull-up or pull-down resistor mode on the given pin, which should be set +// as an input. Unlike Arduino, the BCM2835 has both pull-up and down internal resistors. +// The parameter pud should be; PUD_OFF (no pull up/down), PUD_DOWN (pull to ground) or PUD_UP (pull to 3.3v). +// The internal pull up/down resistors have a value of approximately 50KΩ on the Raspberry Pi. + +IMPLEMENT(pullUpDnControl) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, pud); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int pud = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, pud, (PUD_OFF, PUD_DOWN, PUD_UP)); + + ::pullUpDnControl(pin, pud); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : int digitalRead(int pin) +// Description : This function returns the value read at the given pin. It will be HIGH or LOW (1 or 0) +// depending on the logic level at the pin. + +IMPLEMENT(digitalRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + int res = ::digitalRead(pin); + + // Make sure the function returns strictly 1 or 0 + // §4.7/4 from the C++ Standard says (Integral Conversion) + // If the source type is bool, the value false is converted to zero and the value true is converted to one. + res = (res != 0); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void digitalWrite(int pin, int value) +// Description : Write the value HIGH or LOW (1 or 0) to the given pin which must have been +// previously set as an output. +// WiringPi treats any non-zero number as HIGH, however 0 is the only representation of LOW. + +IMPLEMENT(digitalWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, state); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int state = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, state, (HIGH, LOW)); + + ::digitalWrite(pin, state); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pwmWrite(int pin, int value) +// Description : Writes the value to the PWM register for the given pin. The Raspberry Pi has +// one on-board PWM pin, pin 1 (BCM_GPIO 18, Phys 12) and the range is 0-1024. Other PWM +// devices may have other PWM ranges. +// This function is not able to control the Pi's on-board PWM when in Sys mode. + +IMPLEMENT(pwmWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + + ::pwmWrite(pin, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(analogRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + int res = ::analogRead(pin); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void analogWrite(int pin, int value) +// Description : This writes the given value to the supplied analog pin. You will need to register +// additional analog modules to enable this function for devices such as the Gertboard. + +IMPLEMENT(analogWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + + ::analogWrite(pin, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(pulseIn) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, state); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int state = GET_ARGUMENT_AS_INT32(1); + + CHECK_ARGUMENT_IN_INTS(1, state, (HIGH, LOW)); + + int us = ::pulseIn(pin, state); + + SCOPE_CLOSE(INT32(us)); +} + +IMPLEMENT(delay) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, ms); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int ms = GET_ARGUMENT_AS_INT32(0); + + ::delay(ms); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(delayMicroseconds) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, us); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int us = GET_ARGUMENT_AS_INT32(0); + + ::delayMicroseconds(us); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT(millis) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + unsigned int ms = ::millis(); + + SCOPE_CLOSE(UINT32(ms)); +} + +IMPLEMENT(micros) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + unsigned int us = ::micros(); + + SCOPE_CLOSE(UINT32(us)); +} + +// === Raspberry Pi specific === + +// Func : int piBoardRev(void) +// Description : This returns the board revision of the Raspberry Pi. It will be either 1 or 2. +// Some of the BCM_GPIO pins changed number and function when moving from board revision 1 to 2, +// so if you are using BCM_GPIO pin numbers, then you need to be aware of the differences. + +IMPLEMENT(piBoardRev) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + int res = ::piBoardRev(); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT(piBoardId) { + SCOPE_OPEN(); + + CHECK_ARGUMENTS_LENGTH_EQUAL(0); + + // libWiringPi 2.20 changes: + // maker is now a int indexing makerNames string tables + // a fifth arguments was added named overvolted + int model, rev, mem, marker, overvolted; + + ::piBoardId(&model, &rev, &mem, &marker, &overvolted); + + Local obj = Object::New(); + obj->Set(String::NewSymbol("model"), INT32(model)); + obj->Set(String::NewSymbol("rev"), INT32(rev)); + obj->Set(String::NewSymbol("mem"), INT32(mem)); + obj->Set(String::NewSymbol("marker"), INT32(marker)); + obj->Set(String::NewSymbol("overvolted"), INT32(overvolted)); + + SCOPE_CLOSE(obj); +} + +// Func : int wpiPinToGpio(int wpiPin) +// Description : This returns the BCM_GPIO pin number of the supplied wiringPi pin. +// It takes the board revision into account. + +IMPLEMENT(wpiPinToGpio) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + int res = ::wpiPinToGpio(pin); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int physPinToGpio (int physPin) +// Description : This returns the BCM_GPIO pin number of the suppled physical pin on the P1 connector. + +IMPLEMENT(physPinToGpio) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + int res = ::physPinToGpio(pin); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void setPadDrive(int group, int value) +// Description : This sets the "strength" of the pad drivers for a particular group of pins. +// There are 3 groups of pins and the drive strength is from 0 to 7. Do not use the unless you +// know what you are doing. + +IMPLEMENT(setPadDrive) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, group); + SET_ARGUMENT_NAME(1, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int group = GET_ARGUMENT_AS_INT32(0); + int value = GET_ARGUMENT_AS_INT32(1); + + ::setPadDrive(group, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : int getAlt(int pin) +// Description : Returns the ALT bits for a given port. Only really of-use +// for the gpio readall command (I think). + +IMPLEMENT(getAlt) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int pin = GET_ARGUMENT_AS_INT32(0); + int res = ::getAlt(pin); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT(pwmToneWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, frequency); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int frequency = GET_ARGUMENT_AS_INT32(1); + + ::pwmToneWrite(pin, frequency); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void digitalWriteByte(int value) +// Description : This writes the 8-bit byte supplied to the first 8 GPIO pins. +// It’s the fastest way to set all 8 bits at once to a particular value, although it still takes +// two write operations to the Pi’s GPIO hardware. + +IMPLEMENT(digitalWriteByte) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, byte); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int byte = GET_ARGUMENT_AS_INT32(0); + ::digitalWriteByte(byte); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pwmSetMode(int mode) +// Description : The PWM generator can run in 2 modes – “balanced” and “mark:space”. +// The mark:space mode is traditional, however the default mode in the Pi is “balanced”. +// You can switch modes by supplying the parameter: PWM_MODE_BAL or PWM_MODE_MS. + +IMPLEMENT(pwmSetMode) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, mode); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int mode = GET_ARGUMENT_AS_INT32(0); + + CHECK_ARGUMENT_IN_INTS(0, mode, (PWM_MODE_BAL, PWM_MODE_MS)); + + ::pwmSetMode(mode); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pwmSetRange(unsigned int range) +// Description : This sets the range register in the PWM generator. The default is 1024. +// Note: The PWM control functions can not be used when in Sys mode. To understand more about +// the PWM system, you’ll need to read the Broadcom ARM peripherals manual. + +IMPLEMENT(pwmSetRange) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, range); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_UINT32(0); + + unsigned int range = GET_ARGUMENT_AS_UINT32(0); + ::pwmSetRange(range); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void pwmSetClock(int divisor) +// Description : This sets the divisor for the PWM clock. +// Note: The PWM control functions can not be used when in Sys mode. To understand more about +// the PWM system, you’ll need to read the Broadcom ARM peripherals manual. + +IMPLEMENT(pwmSetClock) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, divisor); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int divisor = GET_ARGUMENT_AS_INT32(0); + ::pwmSetClock(divisor); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void gpioClockSet(int pin, int freq) +// Description : Set the frequency on a GPIO clock pin + +IMPLEMENT(gpioClockSet) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, frequency); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int pin = GET_ARGUMENT_AS_INT32(0); + int frequency = GET_ARGUMENT_AS_INT32(1); + + ::gpioClockSet(pin, frequency); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(wiringPi) { + // Setup + EXPORT_FUNCTION(setup); + EXPORT_FUNCTION(wiringPiSetup); + EXPORT_FUNCTION(wiringPiSetupGpio); + EXPORT_FUNCTION(wiringPiSetupSys); + EXPORT_FUNCTION(wiringPiSetupPhys); + + // Core functions + EXPORT_FUNCTION(pinModeAlt); + EXPORT_FUNCTION(pinMode); + EXPORT_FUNCTION(pullUpDnControl); + EXPORT_FUNCTION(digitalRead); + EXPORT_FUNCTION(digitalWrite); + EXPORT_FUNCTION(pwmWrite); + EXPORT_FUNCTION(analogRead); + EXPORT_FUNCTION(analogWrite); + EXPORT_FUNCTION(pulseIn); + + EXPORT_FUNCTION(delay); + EXPORT_FUNCTION(delayMicroseconds); + EXPORT_FUNCTION(millis); + EXPORT_FUNCTION(micros); + + // On-Board Rasberry Pi hardware specific stuff + EXPORT_FUNCTION(piBoardRev); + EXPORT_FUNCTION(piBoardId); + EXPORT_FUNCTION(wpiPinToGpio); + EXPORT_FUNCTION(physPinToGpio); + EXPORT_FUNCTION(setPadDrive); + EXPORT_FUNCTION(getAlt); + EXPORT_FUNCTION(pwmToneWrite); + EXPORT_FUNCTION(digitalWriteByte); + EXPORT_FUNCTION(pwmSetMode); + EXPORT_FUNCTION(pwmSetRange); + EXPORT_FUNCTION(pwmSetClock); + EXPORT_FUNCTION(gpioClockSet); + + // pinModeAlt + EXPORT_CONSTANT_INT(WPI_MODE_PINS); + EXPORT_CONSTANT_INT(WPI_MODE_PHYS); + EXPORT_CONSTANT_INT(WPI_MODE_GPIO); + + // pinMode + EXPORT_CONSTANT_INT(INPUT); + EXPORT_CONSTANT_INT(OUTPUT); + EXPORT_CONSTANT_INT(PWM_OUTPUT); + EXPORT_CONSTANT_INT(GPIO_CLOCK); + EXPORT_CONSTANT_INT(SOFT_PWM_OUTPUT); + EXPORT_CONSTANT_INT(SOFT_TONE_OUTPUT); + + // pullUpDnControl + EXPORT_CONSTANT_INT(PUD_OFF); + EXPORT_CONSTANT_INT(PUD_DOWN); + EXPORT_CONSTANT_INT(PUD_UP); + + // digitalRead/Write + EXPORT_CONSTANT_INT(HIGH); + EXPORT_CONSTANT_INT(LOW); + + // pwmSetMode + EXPORT_CONSTANT_INT(PWM_MODE_BAL); + EXPORT_CONSTANT_INT(PWM_MODE_MS); + + EXPORT_CONSTANT_INT(PI_MODEL_UNKNOWN); + EXPORT_CONSTANT_INT(PI_MODEL_A); + EXPORT_CONSTANT_INT(PI_MODEL_B); + EXPORT_CONSTANT_INT(PI_MODEL_BP); + EXPORT_CONSTANT_INT(PI_MODEL_CM); + + EXPORT_CONSTANT_INT(PI_VERSION_UNKNOWN); + EXPORT_CONSTANT_INT(PI_VERSION_1); + EXPORT_CONSTANT_INT(PI_VERSION_1_1); + EXPORT_CONSTANT_INT(PI_VERSION_1_2); + EXPORT_CONSTANT_INT(PI_VERSION_2); + + EXPORT_CONSTANT_INT(PI_MAKER_UNKNOWN); + EXPORT_CONSTANT_INT(PI_MAKER_EGOMAN); + EXPORT_CONSTANT_INT(PI_MAKER_SONY); + EXPORT_CONSTANT_INT(PI_MAKER_QISDA); + + EXPORT_CONSTANT_STRING_ARRAY(PI_MODEL_NAMES, piModelNames, 5); + EXPORT_CONSTANT_STRING_ARRAY(PI_REVISION_NAMES, piRevisionNames, 5); + EXPORT_CONSTANT_STRING_ARRAY(PI_MAKER_NAMES, piMakerNames, 4); +} + diff --git a/src/wiringPi.h b/src/wiringPi.h new file mode 100644 index 0000000..f6cde55 --- /dev/null +++ b/src/wiringPi.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_PI_H_ +#define _WPI_WIRING_PI_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringPi); + +#endif \ No newline at end of file diff --git a/src/wiringPiI2C.cc b/src/wiringPiI2C.cc new file mode 100644 index 0000000..38203be --- /dev/null +++ b/src/wiringPiI2C.cc @@ -0,0 +1,196 @@ +#include "wiringPiI2C.h" +#include + +DECLARE(wiringPiI2CRead); +DECLARE(wiringPiI2CReadReg8); +DECLARE(wiringPiI2CReadReg16); +DECLARE(wiringPiI2CWrite); +DECLARE(wiringPiI2CWriteReg8); +DECLARE(wiringPiI2CWriteReg16); +DECLARE(wiringPiI2CSetupInterface); +DECLARE(wiringPiI2CSetup); + +// Func : int wiringPiI2CRead (int fd); +// Simple device read. Some devices present data when you read them without having to do any register transactions. + +IMPLEMENT(wiringPiI2CRead) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + int res = ::wiringPiI2CRead(fd); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiI2CRead (int fd, int reg); +// read an 8-bits value from the device register indicated. + +IMPLEMENT(wiringPiI2CReadReg8) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, reg); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int reg = GET_ARGUMENT_AS_INT32(1); + + int res = ::wiringPiI2CReadReg8(fd, reg); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiI2CRead (int fd, int reg) +// read a 16-bits value from the device register indicated. + +IMPLEMENT(wiringPiI2CReadReg16) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, reg); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int reg = GET_ARGUMENT_AS_INT32(1); + + int res = ::wiringPiI2CReadReg16(fd, reg); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiI2CWrite (int fd, int data) +// Simple device write. Some devices accept data this way without needing to access any internal registers. + +IMPLEMENT(wiringPiI2CWrite) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + int data = GET_ARGUMENT_AS_INT32(1); + data = data & 0xFF; + + int res = ::wiringPiI2CWrite(fd, data); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiI2CWriteReg8 (int fd, int reg, int data) +// write an 8-bit data value into the device register indicated. + +IMPLEMENT(wiringPiI2CWriteReg8) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, reg); + SET_ARGUMENT_NAME(2, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int fd = GET_ARGUMENT_AS_INT32(0); + int reg = GET_ARGUMENT_AS_INT32(1); + int data = GET_ARGUMENT_AS_INT32(2); + data = data & 0xFF; + + int res = ::wiringPiI2CWriteReg8(fd, reg, data); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT(wiringPiI2CWriteReg16) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, reg); + SET_ARGUMENT_NAME(2, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_INT32(2); + + int fd = GET_ARGUMENT_AS_INT32(0); + int reg = GET_ARGUMENT_AS_INT32(1); + int data = GET_ARGUMENT_AS_INT32(2); + data = data & 0xFFFF; + + int res = ::wiringPiI2CWriteReg16(fd, reg, data); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiI2CSetupInterface (const char *device, int devId) + +IMPLEMENT(wiringPiI2CSetupInterface) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, device); + SET_ARGUMENT_NAME(1, devId); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_STRING(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + String::AsciiValue device(GET_ARGUMENT_AS_STRING(0)); + int devId = GET_ARGUMENT_AS_INT32(1); + + int res = ::wiringPiI2CSetupInterface(*device, devId); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wirintPiI2CSetup (int devId) + +IMPLEMENT(wiringPiI2CSetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, devId); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int devId = GET_ARGUMENT_AS_INT32(0); + + int res = ::wiringPiI2CSetup(devId); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(wiringPiI2C) { + EXPORT_FUNCTION(wiringPiI2CRead); + EXPORT_FUNCTION(wiringPiI2CReadReg8); + EXPORT_FUNCTION(wiringPiI2CReadReg16); + EXPORT_FUNCTION(wiringPiI2CWrite); + EXPORT_FUNCTION(wiringPiI2CWriteReg8); + EXPORT_FUNCTION(wiringPiI2CWriteReg16); + EXPORT_FUNCTION(wiringPiI2CSetupInterface); + EXPORT_FUNCTION(wiringPiI2CSetup); +} diff --git a/src/wiringPiI2C.h b/src/wiringPiI2C.h new file mode 100644 index 0000000..27fbe9d --- /dev/null +++ b/src/wiringPiI2C.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_PI_I2C_H_ +#define _WPI_WIRING_PI_I2C_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringPiI2C); + +#endif \ No newline at end of file diff --git a/src/wiringPiISR.cc b/src/wiringPiISR.cc new file mode 100644 index 0000000..710bee2 --- /dev/null +++ b/src/wiringPiISR.cc @@ -0,0 +1,227 @@ +#include "wiringPiISR.h" +#include +#include +#include +#include + +using namespace v8; + +typedef struct js_work_t { + uv_work_t req; + int pin; + unsigned int delta; +} js_work_t; + +typedef void (*NATIVE_INTERRUPT_HANDLER_T)(void); + +static NATIVE_INTERRUPT_HANDLER_T nativeInterruptHandlers[64]; +static unsigned long int lastInterruptMicroseconds[64]; +static std::map > interruptCallbackMapping; + +#define DEFINE_NATIVE_INTERRUPT_HANDLER(pin) \ + static void nativeInterruptHandler##pin(void) { \ + processNativeInterrupt(pin); \ + } + +#define REGISTER_NATIVE_INTERRUPT_HANDLER(pin) nativeInterruptHandlers[pin] = &nativeInterruptHandler##pin + +#define GET_NATIVE_INTERRUPT_HANDLER(pin) nativeInterruptHandlers[pin] + +static void processInterrupt(uv_work_t* req, int status) { + js_work_t* work = static_cast(req->data); + + Persistent callback = interruptCallbackMapping[work->pin]; + + Local argv[] = { + Local::New(Uint32::New(work->delta)) + }; + + callback->Call(Context::GetCurrent()->Global(), 1, argv); + + delete work; +} + +static void UV_NOP(uv_work_t*) {} + +void processNativeInterrupt(int pin) { + unsigned int now = ::micros(); + + js_work_t* work = new js_work_t; + work->req.data = work; + work->pin = pin; + work->delta = now - lastInterruptMicroseconds[pin]; + + int r = uv_queue_work(uv_default_loop(), &work->req, &UV_NOP, &processInterrupt); + if (r != 0) { + delete work; + } + + lastInterruptMicroseconds[pin] = now; +} + +DEFINE_NATIVE_INTERRUPT_HANDLER(0); +DEFINE_NATIVE_INTERRUPT_HANDLER(1); +DEFINE_NATIVE_INTERRUPT_HANDLER(2); +DEFINE_NATIVE_INTERRUPT_HANDLER(3); +DEFINE_NATIVE_INTERRUPT_HANDLER(4); +DEFINE_NATIVE_INTERRUPT_HANDLER(5); +DEFINE_NATIVE_INTERRUPT_HANDLER(6); +DEFINE_NATIVE_INTERRUPT_HANDLER(7); +DEFINE_NATIVE_INTERRUPT_HANDLER(8); +DEFINE_NATIVE_INTERRUPT_HANDLER(9); +DEFINE_NATIVE_INTERRUPT_HANDLER(10); +DEFINE_NATIVE_INTERRUPT_HANDLER(11); +DEFINE_NATIVE_INTERRUPT_HANDLER(12); +DEFINE_NATIVE_INTERRUPT_HANDLER(13); +DEFINE_NATIVE_INTERRUPT_HANDLER(14); +DEFINE_NATIVE_INTERRUPT_HANDLER(15); +DEFINE_NATIVE_INTERRUPT_HANDLER(16); +DEFINE_NATIVE_INTERRUPT_HANDLER(17); +DEFINE_NATIVE_INTERRUPT_HANDLER(18); +DEFINE_NATIVE_INTERRUPT_HANDLER(19); +DEFINE_NATIVE_INTERRUPT_HANDLER(20); +DEFINE_NATIVE_INTERRUPT_HANDLER(21); +DEFINE_NATIVE_INTERRUPT_HANDLER(22); +DEFINE_NATIVE_INTERRUPT_HANDLER(23); +DEFINE_NATIVE_INTERRUPT_HANDLER(24); +DEFINE_NATIVE_INTERRUPT_HANDLER(25); +DEFINE_NATIVE_INTERRUPT_HANDLER(26); +DEFINE_NATIVE_INTERRUPT_HANDLER(27); +DEFINE_NATIVE_INTERRUPT_HANDLER(28); +DEFINE_NATIVE_INTERRUPT_HANDLER(29); +DEFINE_NATIVE_INTERRUPT_HANDLER(30); +DEFINE_NATIVE_INTERRUPT_HANDLER(31); +DEFINE_NATIVE_INTERRUPT_HANDLER(32); +DEFINE_NATIVE_INTERRUPT_HANDLER(33); +DEFINE_NATIVE_INTERRUPT_HANDLER(34); +DEFINE_NATIVE_INTERRUPT_HANDLER(35); +DEFINE_NATIVE_INTERRUPT_HANDLER(36); +DEFINE_NATIVE_INTERRUPT_HANDLER(37); +DEFINE_NATIVE_INTERRUPT_HANDLER(38); +DEFINE_NATIVE_INTERRUPT_HANDLER(39); +DEFINE_NATIVE_INTERRUPT_HANDLER(40); +DEFINE_NATIVE_INTERRUPT_HANDLER(41); +DEFINE_NATIVE_INTERRUPT_HANDLER(42); +DEFINE_NATIVE_INTERRUPT_HANDLER(43); +DEFINE_NATIVE_INTERRUPT_HANDLER(44); +DEFINE_NATIVE_INTERRUPT_HANDLER(45); +DEFINE_NATIVE_INTERRUPT_HANDLER(46); +DEFINE_NATIVE_INTERRUPT_HANDLER(47); +DEFINE_NATIVE_INTERRUPT_HANDLER(48); +DEFINE_NATIVE_INTERRUPT_HANDLER(49); +DEFINE_NATIVE_INTERRUPT_HANDLER(50); +DEFINE_NATIVE_INTERRUPT_HANDLER(51); +DEFINE_NATIVE_INTERRUPT_HANDLER(52); +DEFINE_NATIVE_INTERRUPT_HANDLER(53); +DEFINE_NATIVE_INTERRUPT_HANDLER(54); +DEFINE_NATIVE_INTERRUPT_HANDLER(55); +DEFINE_NATIVE_INTERRUPT_HANDLER(56); +DEFINE_NATIVE_INTERRUPT_HANDLER(57); +DEFINE_NATIVE_INTERRUPT_HANDLER(58); +DEFINE_NATIVE_INTERRUPT_HANDLER(59); +DEFINE_NATIVE_INTERRUPT_HANDLER(60); +DEFINE_NATIVE_INTERRUPT_HANDLER(61); +DEFINE_NATIVE_INTERRUPT_HANDLER(62); +DEFINE_NATIVE_INTERRUPT_HANDLER(63); + +DECLARE(wiringPiISR); +IMPLEMENT(wiringPiISR) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, pin); + SET_ARGUMENT_NAME(1, edgeType); + SET_ARGUMENT_NAME(2, callback); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + CHECK_ARGUMENT_TYPE_FUNCTION(2); + + int pin = GET_ARGUMENT_AS_INT32(0); + int edgeType = GET_ARGUMENT_AS_INT32(1); + Persistent callback = GET_ARGUMENT_AS_PERSISTENT_FUNCTION(2); + + CHECK_ARGUMENT_IN_INTS(1, edgeType, (INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH, INT_EDGE_SETUP)); + + interruptCallbackMapping.insert(std::pair >(pin, callback)); + lastInterruptMicroseconds[pin] = ::micros(); + + ::wiringPiISR(pin, edgeType, GET_NATIVE_INTERRUPT_HANDLER(pin)); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(wiringPiISR) { + REGISTER_NATIVE_INTERRUPT_HANDLER(0); + REGISTER_NATIVE_INTERRUPT_HANDLER(1); + REGISTER_NATIVE_INTERRUPT_HANDLER(2); + REGISTER_NATIVE_INTERRUPT_HANDLER(3); + REGISTER_NATIVE_INTERRUPT_HANDLER(4); + REGISTER_NATIVE_INTERRUPT_HANDLER(5); + REGISTER_NATIVE_INTERRUPT_HANDLER(6); + REGISTER_NATIVE_INTERRUPT_HANDLER(7); + REGISTER_NATIVE_INTERRUPT_HANDLER(8); + REGISTER_NATIVE_INTERRUPT_HANDLER(9); + REGISTER_NATIVE_INTERRUPT_HANDLER(10); + REGISTER_NATIVE_INTERRUPT_HANDLER(11); + REGISTER_NATIVE_INTERRUPT_HANDLER(12); + REGISTER_NATIVE_INTERRUPT_HANDLER(13); + REGISTER_NATIVE_INTERRUPT_HANDLER(14); + REGISTER_NATIVE_INTERRUPT_HANDLER(15); + REGISTER_NATIVE_INTERRUPT_HANDLER(16); + REGISTER_NATIVE_INTERRUPT_HANDLER(17); + REGISTER_NATIVE_INTERRUPT_HANDLER(18); + REGISTER_NATIVE_INTERRUPT_HANDLER(19); + REGISTER_NATIVE_INTERRUPT_HANDLER(20); + REGISTER_NATIVE_INTERRUPT_HANDLER(21); + REGISTER_NATIVE_INTERRUPT_HANDLER(22); + REGISTER_NATIVE_INTERRUPT_HANDLER(23); + REGISTER_NATIVE_INTERRUPT_HANDLER(24); + REGISTER_NATIVE_INTERRUPT_HANDLER(25); + REGISTER_NATIVE_INTERRUPT_HANDLER(26); + REGISTER_NATIVE_INTERRUPT_HANDLER(27); + REGISTER_NATIVE_INTERRUPT_HANDLER(28); + REGISTER_NATIVE_INTERRUPT_HANDLER(29); + REGISTER_NATIVE_INTERRUPT_HANDLER(30); + REGISTER_NATIVE_INTERRUPT_HANDLER(31); + REGISTER_NATIVE_INTERRUPT_HANDLER(32); + REGISTER_NATIVE_INTERRUPT_HANDLER(33); + REGISTER_NATIVE_INTERRUPT_HANDLER(34); + REGISTER_NATIVE_INTERRUPT_HANDLER(35); + REGISTER_NATIVE_INTERRUPT_HANDLER(36); + REGISTER_NATIVE_INTERRUPT_HANDLER(37); + REGISTER_NATIVE_INTERRUPT_HANDLER(38); + REGISTER_NATIVE_INTERRUPT_HANDLER(39); + REGISTER_NATIVE_INTERRUPT_HANDLER(40); + REGISTER_NATIVE_INTERRUPT_HANDLER(41); + REGISTER_NATIVE_INTERRUPT_HANDLER(42); + REGISTER_NATIVE_INTERRUPT_HANDLER(43); + REGISTER_NATIVE_INTERRUPT_HANDLER(44); + REGISTER_NATIVE_INTERRUPT_HANDLER(45); + REGISTER_NATIVE_INTERRUPT_HANDLER(46); + REGISTER_NATIVE_INTERRUPT_HANDLER(47); + REGISTER_NATIVE_INTERRUPT_HANDLER(48); + REGISTER_NATIVE_INTERRUPT_HANDLER(49); + REGISTER_NATIVE_INTERRUPT_HANDLER(50); + REGISTER_NATIVE_INTERRUPT_HANDLER(51); + REGISTER_NATIVE_INTERRUPT_HANDLER(52); + REGISTER_NATIVE_INTERRUPT_HANDLER(53); + REGISTER_NATIVE_INTERRUPT_HANDLER(54); + REGISTER_NATIVE_INTERRUPT_HANDLER(55); + REGISTER_NATIVE_INTERRUPT_HANDLER(56); + REGISTER_NATIVE_INTERRUPT_HANDLER(57); + REGISTER_NATIVE_INTERRUPT_HANDLER(58); + REGISTER_NATIVE_INTERRUPT_HANDLER(59); + REGISTER_NATIVE_INTERRUPT_HANDLER(60); + REGISTER_NATIVE_INTERRUPT_HANDLER(61); + REGISTER_NATIVE_INTERRUPT_HANDLER(62); + REGISTER_NATIVE_INTERRUPT_HANDLER(63); + + EXPORT_FUNCTION(wiringPiISR); + + EXPORT_CONSTANT_INT(INT_EDGE_FALLING); + EXPORT_CONSTANT_INT(INT_EDGE_RISING); + EXPORT_CONSTANT_INT(INT_EDGE_BOTH); + EXPORT_CONSTANT_INT(INT_EDGE_SETUP); +} \ No newline at end of file diff --git a/src/wiringPiISR.h b/src/wiringPiISR.h new file mode 100644 index 0000000..c08ff1e --- /dev/null +++ b/src/wiringPiISR.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_PI_ISR_H_ +#define _WPI_WIRING_PI_ISR_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringPiISR); + +#endif \ No newline at end of file diff --git a/src/wiringPiSPI.cc b/src/wiringPiSPI.cc new file mode 100644 index 0000000..a8210f6 --- /dev/null +++ b/src/wiringPiSPI.cc @@ -0,0 +1,79 @@ +#include "wiringPiSPI.h" +#include + +DECLARE(wiringPiSPIGetFd); +DECLARE(wiringPiSPIDataRW); +DECLARE(wiringPiSPISetup); + +// Func : int wiringPiSPIGetFd(int channel) + +IMPLEMENT(wiringPiSPIGetFd) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, channel); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int channel = GET_ARGUMENT_AS_INT32(0); + + CHECK_ARGUMENT_IN_INTS(0, channel, (0, 1)); + + int res = ::wiringPiSPIGetFd(channel); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : wiringPiSPIDataRW(int channel, unsigned char* data, int len) + +IMPLEMENT(wiringPiSPIDataRW) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, channel); + SET_ARGUMENT_NAME(1, data); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_NODE_BUFFER(1); + + int channel = GET_ARGUMENT_AS_INT32(0); + char* data = node::Buffer::Data(args[1]->ToObject()); + int length = node::Buffer::Length(args[1]->ToObject()); + + CHECK_ARGUMENT_IN_INTS(0, channel, (0, 1)); + + int res = ::wiringPiSPIDataRW(channel, reinterpret_cast(data), length); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int wiringPiSPISetup(int channel, int speed) + +IMPLEMENT(wiringPiSPISetup) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, channel); + SET_ARGUMENT_NAME(1, speed); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + int channel = GET_ARGUMENT_AS_INT32(0); + int speed = GET_ARGUMENT_AS_INT32(0); + + CHECK_ARGUMENT_IN_INTS(0, channel, (0, 1)); + + int res = ::wiringPiSPISetup(channel, speed); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(wiringPiSPI) { + EXPORT_FUNCTION(wiringPiSPIGetFd); + EXPORT_FUNCTION(wiringPiSPIDataRW); + EXPORT_FUNCTION(wiringPiSPISetup); +} \ No newline at end of file diff --git a/src/wiringPiSPI.h b/src/wiringPiSPI.h new file mode 100644 index 0000000..4ff13a5 --- /dev/null +++ b/src/wiringPiSPI.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_PI_SPI_H_ +#define _WPI_WIRING_PI_SPI_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringPiSPI); + +#endif \ No newline at end of file diff --git a/src/wiringSerial.cc b/src/wiringSerial.cc new file mode 100644 index 0000000..55360f6 --- /dev/null +++ b/src/wiringSerial.cc @@ -0,0 +1,166 @@ +#include "wiringSerial.h" +#include + +DECLARE(serialOpen); +DECLARE(serialClose); +DECLARE(serialFlush); +DECLARE(serialPutchar); +DECLARE(serialPuts); +DECLARE(serialPrintf); +DECLARE(serialDataAvail); +DECLARE(serialGetchar); + +// Func : int serialOpen(const char* device, const int baud) + +IMPLEMENT(serialOpen) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, device); + SET_ARGUMENT_NAME(1, baudrate); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_STRING(0); + CHECK_ARGUMENT_TYPE_INT32(1); + + String::AsciiValue device(GET_ARGUMENT_AS_STRING(0)); + int baudrate = GET_ARGUMENT_AS_INT32(1); + + int res = ::serialOpen(*device, baudrate); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : void serialClose(const int fd) + +IMPLEMENT(serialClose) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + ::serialClose(fd); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void serialFlush(const int fd); + +IMPLEMENT(serialFlush) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + ::serialFlush(fd); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void serialPutchar(const int fd, const unsigned char c) + +IMPLEMENT(serialPutchar) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, character); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + unsigned char character = GET_ARGUMENT_AS_UINT32(1); + + ::serialPutchar(fd, character); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void serialPuts(const int fd, const char* s) + +IMPLEMENT(serialPuts) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + SET_ARGUMENT_NAME(1, string); + + CHECK_ARGUMENTS_LENGTH_EQUAL(2); + + CHECK_ARGUMENT_TYPE_INT32(0); + CHECK_ARGUMENT_TYPE_STRING(1); + + int fd = GET_ARGUMENT_AS_INT32(0); + String::AsciiValue string(GET_ARGUMENT_AS_STRING(1)); + + ::serialPuts(fd, *string); + + SCOPE_CLOSE(UNDEFINED()); +} + +// Func : void serialPrintf(const int fd, const char* message, ...) + +IMPLEMENT(serialPrintf) { + // Make serialPrintf a alias to serialPuts + return serialPuts(args); +} + +// Func : int serialDataAvail(const int fd) + +IMPLEMENT(serialDataAvail) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + int res = ::serialDataAvail(fd); + + SCOPE_CLOSE(INT32(res)); +} + +// Func : int serialGetchar(const int fd) +// NOTE TO MYSELF : I don't understand why serialPutchar takes a unsigned char and on the other side +// serialGetchar returns a int ... serialGetchar should returns a unsigned char too. + +IMPLEMENT(serialGetchar) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, fd); + + CHECK_ARGUMENTS_LENGTH_EQUAL(1); + + CHECK_ARGUMENT_TYPE_INT32(0); + + int fd = GET_ARGUMENT_AS_INT32(0); + + int res = ::serialGetchar(fd); + + SCOPE_CLOSE(INT32(res)); +} + +IMPLEMENT_EXPORT_INIT(wiringSerial) { + EXPORT_FUNCTION(serialOpen); + EXPORT_FUNCTION(serialClose); + EXPORT_FUNCTION(serialFlush); + EXPORT_FUNCTION(serialPutchar); + EXPORT_FUNCTION(serialPuts); + EXPORT_FUNCTION(serialPrintf); + EXPORT_FUNCTION(serialDataAvail); + EXPORT_FUNCTION(serialGetchar); +} \ No newline at end of file diff --git a/src/wiringSerial.h b/src/wiringSerial.h new file mode 100644 index 0000000..2da6c1f --- /dev/null +++ b/src/wiringSerial.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_SERIAL_H_ +#define _WPI_WIRING_SERIAL_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringSerial); + +#endif \ No newline at end of file diff --git a/src/wiringShift.cc b/src/wiringShift.cc new file mode 100644 index 0000000..4e34978 --- /dev/null +++ b/src/wiringShift.cc @@ -0,0 +1,75 @@ +#include "wiringShift.h" +#include + +DECLARE(shiftIn); +DECLARE(shiftOut); + +// Func : uint8_t shiftIn(uint8_t dPin, uint8_t cPin, uint8_t order) +// Description : This shifts an 8-bit data value in with the data appearing on the dPin and the clock being sent out on the cPin. +// Order is either LSBFIRST or MSBFIRST. +// The data is sampled after the cPin goes high. +// (So cPin high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function. + +IMPLEMENT(shiftIn) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, dPin); + SET_ARGUMENT_NAME(1, cPin); + SET_ARGUMENT_NAME(2, order); + + CHECK_ARGUMENTS_LENGTH_EQUAL(3); + + CHECK_ARGUMENT_TYPE_UINT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + + uint8_t dPin = GET_ARGUMENT_AS_UINT32(0); + uint8_t cPin = GET_ARGUMENT_AS_UINT32(1); + uint8_t order = GET_ARGUMENT_AS_UINT32(2); + + CHECK_ARGUMENT_IN_INTS(2, order, (LSBFIRST, MSBFIRST)); + + uint8_t res = ::shiftIn(dPin, cPin, order); + + SCOPE_CLOSE(UINT32(res)); +} + +// Func : void shiftOut(uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) ; +// Description : The shifts an 8-bit data value val out with the data being sent out on dPin and the clock being sent out on the cPin. +// order is as above. +// Data is clocked out on the rising or falling edge – ie. dPin is set, then cPin is taken high then low – repeated for the 8 bits. + +IMPLEMENT(shiftOut) { + SCOPE_OPEN(); + + SET_ARGUMENT_NAME(0, dPin); + SET_ARGUMENT_NAME(1, cPin); + SET_ARGUMENT_NAME(2, order); + SET_ARGUMENT_NAME(3, value); + + CHECK_ARGUMENTS_LENGTH_EQUAL(4); + + CHECK_ARGUMENT_TYPE_UINT32(0); + CHECK_ARGUMENT_TYPE_UINT32(1); + CHECK_ARGUMENT_TYPE_UINT32(2); + CHECK_ARGUMENT_TYPE_UINT32(3); + + uint8_t dPin = GET_ARGUMENT_AS_UINT32(0); + uint8_t cPin = GET_ARGUMENT_AS_UINT32(1); + uint8_t order = GET_ARGUMENT_AS_UINT32(2); + uint8_t value = GET_ARGUMENT_AS_UINT32(3); + + CHECK_ARGUMENT_IN_INTS(2, order, (LSBFIRST, MSBFIRST)); + + ::shiftOut(dPin, cPin, order, value); + + SCOPE_CLOSE(UNDEFINED()); +} + +IMPLEMENT_EXPORT_INIT(wiringShift) { + EXPORT_FUNCTION(shiftIn); + EXPORT_FUNCTION(shiftOut); + + EXPORT_CONSTANT_INT(LSBFIRST); + EXPORT_CONSTANT_INT(MSBFIRST); +} \ No newline at end of file diff --git a/src/wiringShift.h b/src/wiringShift.h new file mode 100644 index 0000000..98ca11b --- /dev/null +++ b/src/wiringShift.h @@ -0,0 +1,8 @@ +#ifndef _WPI_WIRING_SHIFT_H_ +#define _WPI_WIRING_SHIFT_H_ + + #include "addon.h" + + DECLARE_EXPORT_INIT(wiringShift); + +#endif \ No newline at end of file diff --git a/src/wpi.cc b/src/wpi.cc new file mode 100644 index 0000000..f04c705 --- /dev/null +++ b/src/wpi.cc @@ -0,0 +1,19 @@ +#include "wpi.h" +#include + +NODE_MODULE_INIT() { + INIT(wiringPi); + INIT(softPwm); + INIT(softServo); + INIT(softTone); + INIT(wiringPiI2C); + INIT(wiringPiSPI); + INIT(wiringSerial); + INIT(wiringShift); + INIT(wiringPiISR); + + INIT(extensions); + INIT(devlib); +} + +NODE_MODULE_DECLARE(wiringPi); \ No newline at end of file diff --git a/src/wpi.h b/src/wpi.h new file mode 100644 index 0000000..a9c60df --- /dev/null +++ b/src/wpi.h @@ -0,0 +1,17 @@ +#ifndef _WPI_H_ +#define _WPI_H_ + + #include "wiringPi.h" + #include "softPwm.h" + #include "softServo.h" + #include "softTone.h" + #include "wiringPiI2C.h" + #include "wiringPiSPI.h" + #include "wiringSerial.h" + #include "wiringShift.h" + #include "wiringPiISR.h" + + #include "extensions/extensions.h" + #include "devlib/devlib.h" + +#endif \ No newline at end of file