ocoge/local_modules/@ocogeclub/lgpio/lgpio.cpp

573 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/** lgpio を Node.js から利用するモジュール ** */
/** 関数名・書式は lgpio Python に準拠 ******************* */
#include <napi.h>
#include <lgpio.h>
#include <unistd.h>
#include <string>
using namespace Napi;
// gpiochipデバイスを開く
Value gpiochipOpen(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 1)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int gpioDev = info[0].As<Number>().Int32Value();
return Number::New(env, lgGpiochipOpen(gpioDev));
}
// gpiochipデバイスを閉じる
Value gpiochipClose(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 1)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
return Number::New(env, lgGpiochipClose(handle));
}
// GPIO のモードを出力にする(ことを要求?)
Value gpioClaimOutput(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
return Number::New(env,
lgGpioClaimOutput(handle, 0, gpio, 0));
}
// GPIO のモードを入力にする(ことを要求?)
Value gpioClaimInput(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 3)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
int lflag = info[2].As<Number>().Int32Value();
return Number::New(env,
lgGpioClaimInput(handle, lflag, gpio));
}
// GPIOの電圧を読む
Value gpioRead(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
return Number::New(env,
lgGpioRead(handle, gpio));
}
// GPIO の電圧をセットする
Value gpioWrite(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 3)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
int level = info[2].As<Number>().Int32Value();
return Number::New(env,
lgGpioWrite(handle, gpio, level));
}
// サーボパルス幅をセットする
Value txServo(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 3)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
int pulseWidth = info[2].As<Number>().Int32Value();
return Number::New(env,
lgTxServo(handle, gpio, pulseWidth, 50, 0, 0));
}
// PWMを設定して出力
Value txPwm(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 4)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber() || !info[3].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int gpio = info[1].As<Number>().Int32Value();
float pwmFrequency = info[2].As<Number>().FloatValue();
float pwmDutyCycle = info[3].As<Number>().FloatValue();
return Number::New(env,
lgTxPwm(handle, gpio, pwmFrequency, pwmDutyCycle, 0, 0));
}
// シリアルポートを開く
Value serialOpen(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsString() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
std::string tty = info[0].As<String>().Utf8Value();
// char *c = new char[tty.size()+1];
// std::strcpy(c, tty.c_str());
// &ser_tty[0] で参照できるらしいけど危険?
int baud = info[1].As<Number>().Int32Value();
return Number::New(env,
lgSerialOpen(tty.c_str(), baud, 0));
}
// シリアルポートを閉じる
Value serialClose(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 1)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
return Number::New(env,
lgSerialClose(handle));
}
// シリアルデバイスからデータを受け取る
Value SerialRead(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int count = info[1].As<Number>().Int32Value();
// char rxBuf[count + 1];
// int32_t resultCount = lgSerialRead(handle, rxBuf, count);
// Buffer<char> resultBuf = Buffer<char>::Copy(env, rxBuf, count);
auto rxBuf = Buffer<char>::New(env, count);
int rxCount = lgSerialRead(handle, rxBuf.Data(), count);
Array returnArr = Array::New(env);
int i = 0;
returnArr[i] = Number::New(env, rxCount);
returnArr[++i] = rxBuf;
return returnArr;
}
// シリアルデバイスにバイト列を送る(data: buffer)
Value serialWrite(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsBuffer())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
auto txBuf = info[1].As<Buffer<char>>();
int count = txBuf.Length();
return Number::New(env,
lgSerialWrite(handle, txBuf.Data(), count));
}
// I2Cバスアドレスのデバイスのハンドルを返す
Value i2cOpen(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int i2cDev = info[0].As<Number>().Int32Value();
int i2cAddr = info[1].As<Number>().Int32Value();
return Number::New(env,
lgI2cOpen(i2cDev, i2cAddr, 0));
}
// オープン済みI2Cハンドルを閉じる
Value i2cClose(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 1)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
return Number::New(env,
lgI2cClose(handle));
}
// デバイスに1バイトを送る
Value i2cWriteByte(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int byteVal = info[1].As<Number>().Int32Value();
return Number::New(env,
lgI2cWriteByte(handle, byteVal));
}
// デバイスから1バイトを受け取る
Value i2cReadByte(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 1)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
return Number::New(env,
lgI2cReadByte(handle));
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタに1バイトを書き込む
Value i2cWriteByteData(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 3)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int i2cReg = info[1].As<Number>().Int32Value();
int byteVal = info[2].As<Number>().Int32Value();
return Number::New(env,
lgI2cWriteByteData(handle, i2cReg, byteVal));
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタから1バイトを読み込む
Value i2cReadByteData(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int i2cReg = info[1].As<Number>().Int32Value();
return Number::New(env,
lgI2cReadByteData(handle, i2cReg));
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタからcountバイトを読み込む。countは132。
Value i2cReadI2cBlockData(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 3)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber() || !info[2].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int i2cReg = info[1].As<Number>().Int32Value();
int count = info[2].As<Number>().Int32Value();
auto rxBuf = Buffer<char>::New(env, count);
int rxCount = lgI2cReadI2CBlockData(handle, i2cReg, rxBuf.Data(), count);
Array returnArr = Array::New(env);
int i = 0;
returnArr[i] = Number::New(env, rxCount);
returnArr[++i] = rxBuf;
return returnArr;
}
// I2Cハンドルに関連付けられているデバイスの指定されたレジスタから単一の16ビットワードを読み取る
Value I2cReadWordData(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int i2cReg = info[1].As<Number>().Int32Value();
return Number::New(env,
lgI2cReadWordData(handle, i2cReg));
}
// i2c デバイスからデータを受け取る
Value I2cReadDevice(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsNumber())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
int count = info[1].As<Number>().Int32Value();
auto rxBuf = Buffer<char>::New(env, count);
int rxCount = lgI2cReadDevice(handle, rxBuf.Data(), count);
auto returnArr = Array::New(env);
int i = 0;
returnArr[i] = Number::New(env, rxCount);
returnArr[++i] = rxBuf;
return returnArr;
}
// i2c デバイスにバイト列を送る(data: buffer)
Value I2cWriteDevice(const CallbackInfo &info)
{
Env env = info.Env();
if (info.Length() < 2)
{
TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
return env.Null();
}
if (!info[0].IsNumber() || !info[1].IsBuffer())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
int handle = info[0].As<Number>().Int32Value();
auto txBuf = info[1].As<Buffer<char>>();
int count = txBuf.Length();
return Number::New(env,
lgI2cWriteDevice(handle, txBuf.Data(), count));
}
Object
Init(Env env, Object exports)
{
exports.Set(String::New(env, "gpiochip_open"), Function::New(env, gpiochipOpen));
exports.Set(String::New(env, "gpiochip_close"), Function::New(env, gpiochipClose));
exports.Set(String::New(env, "gpio_claim_input"), Function::New(env, gpioClaimInput));
exports.Set(String::New(env, "gpio_claim_output"), Function::New(env, gpioClaimOutput));
exports.Set(String::New(env, "gpio_read"), Function::New(env, gpioRead));
exports.Set(String::New(env, "gpio_write"), Function::New(env, gpioWrite));
exports.Set(String::New(env, "tx_servo"), Function::New(env, txServo));
exports.Set(String::New(env, "tx_pwm"), Function::New(env, txPwm));
exports.Set(String::New(env, "serial_open"), Function::New(env, serialOpen));
exports.Set(String::New(env, "serial_close"), Function::New(env, serialClose));
exports.Set(String::New(env, "serial_read"), Function::New(env, SerialRead));
exports.Set(String::New(env, "serial_write"), Function::New(env, serialWrite));
exports.Set(String::New(env, "i2c_open"), Function::New(env, i2cOpen));
exports.Set(String::New(env, "i2c_close"), Function::New(env, i2cClose));
exports.Set(String::New(env, "i2c_write_byte"), Function::New(env, i2cWriteByte));
exports.Set(String::New(env, "i2c_read_byte"), Function::New(env, i2cReadByte));
exports.Set(String::New(env, "i2c_write_byte_data"), Function::New(env, i2cWriteByteData));
exports.Set(String::New(env, "i2c_read_byte_data"), Function::New(env, i2cReadByteData));
exports.Set(String::New(env, "i2c_read_i2c_block_data"), Function::New(env, i2cReadI2cBlockData));
exports.Set(String::New(env, "i2c_read_word_data"), Function::New(env, I2cReadWordData));
exports.Set(String::New(env, "i2c_read_device"), Function::New(env, I2cReadDevice));
exports.Set(String::New(env, "i2c_write_device"), Function::New(env, I2cWriteDevice));
return exports;
}
NODE_API_MODULE(lgpio, Init)