-
Notifications
You must be signed in to change notification settings - Fork 6
Home
The unpi is the packet builder and parser for Texas Instruments Unified Network Processor Interface (UNPI) used in RF4CE, BluetoothSmart, and ZigBee wireless SoCs. As stated in TI's wiki page:
TI's Unified Network Processor Interface (NPI) is used for establishing a serial data link between a TI SoC and external MCUs or PCs. This is mainly used by TI's network processor solutions.
The UNPI packet consists of sof, length, cmd0, cmd1, payload, and fcs fields. The description of each field can be found in Unified Network Processor Interface.
It is noted that UNPI defines the length field with 2 bytes wide, but some SoCs use NPI in their real transmission (physical layer), the length field just occupies a single byte. (The length field will be normalized to 2 bytes in the transportation layer of NPI stack.)
$ npm install unpi --save
To use unpi, just new an instance from the Unpi class. The Unpi constructor accepts an optional parameter config
object. If config
is not given, a default value of { lenBytes: 2 }
will be used internally. The property lenBytes
indicates the width of the length field.
Since the transmission should be accomplished upon an UART or a SPI physical interface, you can pass the physical transceiver to your unpi by attach it to config.phy
property, i.e., { phy: sp }
where sp
is a serialport instance. The phy
instance should be a Stream.
Here is an quick example and the parsed data format can be found in the 'data' event section.
var Unpi = require('unpi'),
SerialPort = require("serialport").SerialPort;
var sp = new SerialPort("/dev/ttyUSB0", {
baudrate: 57600
}),
unpi = new Unpi({
lenBytes: 1
phy: sp
});
unpi.on('data', function (data) {
console.log(data); // The parsed data receiving from the serial port
});
Exposed by require('unpi')
Unpi class also exports its dependencies DChunks and Concentrate for your convenient.
Examples:
var Unpi = require('unpi');
var DChunks = Unpi.DChunks;
var Concentrate = Unpi.Concentrate;
var myBuffer = Concentrate().uint8(1).uint8(20).uint16(100).result();
Create a new instance of the Unpi
class.
Arguments:
-
config
(Object, optional): Configuration of the unpi instance. Accepted properties ofconfig
are listed in the following table.
Property | Type | Description |
---|---|---|
lenBytes | Number | 1 or 2 to indicate the width of length field. Default is 2. |
phy | Stream | The transceiver instance, i.e. serial port, spi. It should be a duplex stream. |
Returns:
- (Object): unpi, an instance of Unpi
Examples:
- Create an unpi instance without physical transceiver
var Unpi = require('unpi');
var unpi = new Unpi({
lenBytes: 1
});
unpi.on('data', function (data) {
console.log(data); // The parsed data
});
// You can use .receive(buffer) to test it
unpi.receive(new Buffer([
0xFE, 0x01, 0x41, 0x00, 0x00, 0x40
]));
- Create an unpi instance with a serialport transceiver. The unpi will internally pipe from and to it.
var SerialPort = require("serialport").SerialPort
var sp = new SerialPort("/dev/ttyUSB0", {
baudrate: 57600
});
var Unpi = require('unpi');
var unpi = new Unpi({
lenBytes: 1
phy: sp
});
unpi.on('data', function (data) {
console.log(data); // The parsed data receiving from the serial port
});
Feeds the unpi with some binary raw data. You can take the unpi as a generic parser if you don't have any physical transceiver.
Arguments:
-
buf
(Buffer): An UNPI raw packet.
Returns:
- (Object): this (unpi instance itself)
Examples:
unpi.receive(new Buffer([
0xFE, 0x01, 0x41, 0x00, 0x00, 0x40
]));
Send the binaries out through the physical transmitter if there is a phy
transceiver. The API will return a raw buffer of the packet, you can take it as a generic packet builder. If the phy
exists, unpi will fire an 'flushed'
event after each command packet flushed to the phy
transceiver.
Arguments:
-
type
(Number | String): The command type. For exmaple, settype
to1
or'SREQ'
to send a synchronous command. -
subsys
(Number | String): The subsystem. For example, send a command of subsystem 'RPC_SYS_UTIL', you can setsubsys
to7
,'RPC_SYS_UTIL'
, or simply'UTIL'
(the prefix'RPC_SYS_'
can be ignored). -
cmdId
(Number): The command id which is a number according to which subsystem you are using. -
payload
(Buffer): The data payload.
Returns:
- (Buffer): Buffer of the built command packet.
Examples:
// The following calls do the same thing
unpi.send('AREQ', 'SYS', 0, new Buffer([ 0 ]));
unpi.send('AREQ', 1, 0, new Buffer([ 0 ]));
unpi.send(2, 'SYS', 0, new Buffer([ 0 ]));
unpi.send(2, 1, 0, new Buffer([ 0 ]));
## 5. Events
The 'data' event will be fired along with the parsed result. Here is an example of the parsed data to show you the format. The csum
is the checksum calculated from the received binaries. You can use it to check that if the received packet is corrupted.
{
sof: 254,
len: 6,
type: 2,
subsys: 1,
cmd: 128,
payload: <Buffer 02 02 00 02 06 02>,
fcs: 193, // this is the checksum originated from the sender
csum: 193 // this is the checksum calculated from the received binaries
}
Examples:
unpi.on('data', function (data) {
console.log(data); // The parsed data
});
After each command packet is sending out to phy
transceiver, a 'flushed' event will be fired along with the data of command information. The cmdInfo
object has three properties of type
, subsys
, and cmdId
to indicate which command was send.
Examples:
unpi.on('flushed', function (cmdInfo) {
console.log(cmdInfo); // { type: 1 , subsys: 2, cmdId: 10 }
});
Fired when any error occurs. Each time unpi finds that there is a corrupted packet with a bad checksum, both an data
event and an error
event will be fired along with the parsed result.
Examples:
unpi.on('error', function (err, parsedData) {
console.log(err); // for example: [Error: Invalid checksum.]
});
## 6. Appendix
- Command Type
{
"POLL": 0,
"SREQ": 1,
"AREQ": 2,
"SRSP": 3,
"RES0": 4,
"RES1": 5,
"RES2": 6,
"RES3": 7
}
- Subsystem
{
"RPC_SYS_RES0": 0,
"RPC_SYS_SYS": 1,
"RPC_SYS_MAC": 2,
"RPC_SYS_NWK": 3,
"RPC_SYS_AF": 4,
"RPC_SYS_ZDO": 5,
"RPC_SYS_SAPI": 6,
"RPC_SYS_UTIL": 7,
"RPC_SYS_DBG": 8,
"RPC_SYS_APP": 9,
"RPC_SYS_RCAF": 10,
"RPC_SYS_RCN": 11,
"RPC_SYS_RCN_CLIENT": 12,
"RPC_SYS_BOOT": 13,
"RPC_SYS_ZIPTEST": 14,
"RPC_SYS_DEBUG": 15,
"RPC_SYS_PERIPHERALS": 16,
"RPC_SYS_NFC": 17,
"RPC_SYS_PB_NWK_MGR": 18,
"RPC_SYS_PB_GW": 19,
"RPC_SYS_PB_OTA_MGR": 20,
"RPC_SYS_BLE_SPNP": 21,
"RPC_SYS_BLE_HCI": 22,
"RPC_SYS_RESV01": 23,
"RPC_SYS_RESV02": 24,
"RPC_SYS_RESV03": 25,
"RPC_SYS_RESV04": 26,
"RPC_SYS_RESV05": 27,
"RPC_SYS_RESV06": 28,
"RPC_SYS_RESV07": 29,
"RPC_SYS_RESV08": 30,
"RPC_SYS_SRV_CTR": 31
}