[fluksod] skeleton implementation of message processing on spidev bus
This commit is contained in:
parent
221636f5cf
commit
f3516415bd
|
@ -3,7 +3,7 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=flukso
|
PKG_NAME:=flukso
|
||||||
PKG_VERSION:=2.0
|
PKG_VERSION:=2.0-alpha
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
|
@ -15,6 +15,8 @@ define Package/flukso
|
||||||
CATEGORY:=Utilities
|
CATEGORY:=Utilities
|
||||||
DEPENDS:=+libdaemon +ntpclient +liblua +luci-nixio +rrdtool1
|
DEPENDS:=+libdaemon +ntpclient +liblua +luci-nixio +rrdtool1
|
||||||
TITLE:=Flukso - community metering
|
TITLE:=Flukso - community metering
|
||||||
|
URL:=http://www.flukso.net
|
||||||
|
MAINTAINER:=Bart Van Der Meerssche <bart.vandermeerssche@flukso.net>
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/flukso/description
|
define Package/flukso/description
|
||||||
|
@ -32,10 +34,12 @@ define Package/flukso/install
|
||||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/dbg.lua $(1)/usr/lib/lua/
|
$(INSTALL_DATA) $(PKG_BUILD_DIR)/dbg.lua $(1)/usr/lib/lua/
|
||||||
$(INSTALL_DIR) $(1)/usr/lib/lua/rrd
|
$(INSTALL_DIR) $(1)/usr/lib/lua/rrd
|
||||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/rrd/*.lua $(1)/usr/lib/lua/rrd/
|
$(INSTALL_DATA) $(PKG_BUILD_DIR)/rrd/*.lua $(1)/usr/lib/lua/rrd/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib/lua/flukso
|
||||||
|
$(INSTALL_DATA) $(PKG_BUILD_DIR)/flukso/*.lua $(1)/usr/lib/lua/flukso/
|
||||||
$(INSTALL_DIR) $(1)/usr/sbin
|
$(INSTALL_DIR) $(1)/usr/sbin
|
||||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/luad $(1)/usr/sbin/
|
$(INSTALL_BIN) $(PKG_BUILD_DIR)/luad $(1)/usr/sbin/
|
||||||
$(LN) /usr/sbin/luad $(1)/usr/sbin/spid
|
$(LN) /usr/sbin/luad $(1)/usr/sbin/fluksod
|
||||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/spi/spid.lua $(1)/usr/sbin/
|
$(INSTALL_BIN) $(PKG_BUILD_DIR)/fluksod.lua $(1)/usr/sbin/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call BuildPackage,flukso))
|
$(eval $(call BuildPackage,flukso))
|
||||||
|
|
|
@ -0,0 +1,517 @@
|
||||||
|
--[[
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2007 Tim Kelly/Dialectronics
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
* persons to whom the Software is furnished to do so, subject to the
|
||||||
|
* following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||||
|
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||||
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
module(..., package.seeall);
|
||||||
|
|
||||||
|
local hex2bin = {
|
||||||
|
["0"] = "0000",
|
||||||
|
["1"] = "0001",
|
||||||
|
["2"] = "0010",
|
||||||
|
["3"] = "0011",
|
||||||
|
["4"] = "0100",
|
||||||
|
["5"] = "0101",
|
||||||
|
["6"] = "0110",
|
||||||
|
["7"] = "0111",
|
||||||
|
["8"] = "1000",
|
||||||
|
["9"] = "1001",
|
||||||
|
["a"] = "1010",
|
||||||
|
["b"] = "1011",
|
||||||
|
["c"] = "1100",
|
||||||
|
["d"] = "1101",
|
||||||
|
["e"] = "1110",
|
||||||
|
["f"] = "1111"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local bin2hex = {
|
||||||
|
["0000"] = "0",
|
||||||
|
["0001"] = "1",
|
||||||
|
["0010"] = "2",
|
||||||
|
["0011"] = "3",
|
||||||
|
["0100"] = "4",
|
||||||
|
["0101"] = "5",
|
||||||
|
["0110"] = "6",
|
||||||
|
["0111"] = "7",
|
||||||
|
["1000"] = "8",
|
||||||
|
["1001"] = "9",
|
||||||
|
["1010"] = "A",
|
||||||
|
["1011"] = "B",
|
||||||
|
["1100"] = "C",
|
||||||
|
["1101"] = "D",
|
||||||
|
["1110"] = "E",
|
||||||
|
["1111"] = "F"
|
||||||
|
}
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local dec2hex = {
|
||||||
|
["0"] = "0",
|
||||||
|
["1"] = "1",
|
||||||
|
["2"] = "2",
|
||||||
|
["3"] = "3",
|
||||||
|
["4"] = "4",
|
||||||
|
["5"] = "5",
|
||||||
|
["6"] = "6",
|
||||||
|
["7"] = "7",
|
||||||
|
["8"] = "8",
|
||||||
|
["9"] = "9",
|
||||||
|
["10"] = "A",
|
||||||
|
["11"] = "B",
|
||||||
|
["12"] = "C",
|
||||||
|
["13"] = "D",
|
||||||
|
["14"] = "E",
|
||||||
|
["15"] = "F"
|
||||||
|
}
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
-- These functions are big-endian and take up to 32 bits
|
||||||
|
|
||||||
|
-- Hex2Bin
|
||||||
|
-- Bin2Hex
|
||||||
|
-- Hex2Dec
|
||||||
|
-- Dec2Hex
|
||||||
|
-- Bin2Dec
|
||||||
|
-- Dec2Bin
|
||||||
|
|
||||||
|
|
||||||
|
function Hex2Bin(s)
|
||||||
|
|
||||||
|
-- s -> hexadecimal string
|
||||||
|
|
||||||
|
local ret = ""
|
||||||
|
local i = 0
|
||||||
|
|
||||||
|
|
||||||
|
for i in string.gfind(s, ".") do
|
||||||
|
i = string.lower(i)
|
||||||
|
|
||||||
|
ret = ret..hex2bin[i]
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bin2Hex(s)
|
||||||
|
|
||||||
|
-- s -> binary string
|
||||||
|
|
||||||
|
local l = 0
|
||||||
|
local h = ""
|
||||||
|
local b = ""
|
||||||
|
local rem
|
||||||
|
|
||||||
|
l = string.len(s)
|
||||||
|
rem = l % 4
|
||||||
|
l = l-1
|
||||||
|
h = ""
|
||||||
|
|
||||||
|
-- need to prepend zeros to eliminate mod 4
|
||||||
|
if (rem > 0) then
|
||||||
|
s = string.rep("0", 4 - rem)..s
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, l, 4 do
|
||||||
|
b = string.sub(s, i, i+3)
|
||||||
|
h = h..bin2hex[b]
|
||||||
|
end
|
||||||
|
|
||||||
|
return h
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bin2Dec(s)
|
||||||
|
|
||||||
|
-- s -> binary string
|
||||||
|
|
||||||
|
local num = 0
|
||||||
|
local ex = string.len(s) - 1
|
||||||
|
local l = 0
|
||||||
|
|
||||||
|
l = ex + 1
|
||||||
|
for i = 1, l do
|
||||||
|
b = string.sub(s, i, i)
|
||||||
|
if b == "1" then
|
||||||
|
num = num + 2^ex
|
||||||
|
end
|
||||||
|
ex = ex - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return string.format("%u", num)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Dec2Bin(s, num)
|
||||||
|
|
||||||
|
-- s -> Base10 string
|
||||||
|
-- num -> string length to extend to
|
||||||
|
|
||||||
|
local n
|
||||||
|
|
||||||
|
if (num == nil) then
|
||||||
|
n = 0
|
||||||
|
else
|
||||||
|
n = num
|
||||||
|
end
|
||||||
|
|
||||||
|
s = string.format("%x", s)
|
||||||
|
|
||||||
|
s = Hex2Bin(s)
|
||||||
|
|
||||||
|
while string.len(s) < n do
|
||||||
|
s = "0"..s
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Hex2Dec(s)
|
||||||
|
|
||||||
|
-- s -> hexadecimal string
|
||||||
|
|
||||||
|
local s = Hex2Bin(s)
|
||||||
|
|
||||||
|
return Bin2Dec(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Dec2Hex(s)
|
||||||
|
|
||||||
|
-- s -> Base10 string
|
||||||
|
|
||||||
|
s = string.format("%x", s)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- These functions are big-endian and will extend to 32 bits
|
||||||
|
|
||||||
|
-- BMAnd
|
||||||
|
-- BMNAnd
|
||||||
|
-- BMOr
|
||||||
|
-- BMXOr
|
||||||
|
-- BMNot
|
||||||
|
|
||||||
|
|
||||||
|
function BMAnd(v, m)
|
||||||
|
|
||||||
|
-- v -> hex string to be masked
|
||||||
|
-- m -> hex string mask
|
||||||
|
|
||||||
|
-- s -> hex string as masked
|
||||||
|
|
||||||
|
-- bv -> binary string of v
|
||||||
|
-- bm -> binary string mask
|
||||||
|
|
||||||
|
local bv = Hex2Bin(v)
|
||||||
|
local bm = Hex2Bin(m)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
while (string.len(bv) < 32) do
|
||||||
|
bv = "0000"..bv
|
||||||
|
end
|
||||||
|
|
||||||
|
while (string.len(bm) < 32) do
|
||||||
|
bm = "0000"..bm
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1, 32 do
|
||||||
|
cv = string.sub(bv, i, i)
|
||||||
|
cm = string.sub(bm, i, i)
|
||||||
|
if cv == cm then
|
||||||
|
if cv == "1" then
|
||||||
|
s = s.."1"
|
||||||
|
else
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s = s.."0"
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BMNAnd(v, m)
|
||||||
|
|
||||||
|
-- v -> hex string to be masked
|
||||||
|
-- m -> hex string mask
|
||||||
|
|
||||||
|
-- s -> hex string as masked
|
||||||
|
|
||||||
|
-- bv -> binary string of v
|
||||||
|
-- bm -> binary string mask
|
||||||
|
|
||||||
|
local bv = Hex2Bin(v)
|
||||||
|
local bm = Hex2Bin(m)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
while (string.len(bv) < 32) do
|
||||||
|
bv = "0000"..bv
|
||||||
|
end
|
||||||
|
|
||||||
|
while (string.len(bm) < 32) do
|
||||||
|
bm = "0000"..bm
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1, 32 do
|
||||||
|
cv = string.sub(bv, i, i)
|
||||||
|
cm = string.sub(bm, i, i)
|
||||||
|
if cv == cm then
|
||||||
|
if cv == "1" then
|
||||||
|
s = s.."0"
|
||||||
|
else
|
||||||
|
s = s.."1"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s = s.."1"
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function BMOr(v, m)
|
||||||
|
|
||||||
|
-- v -> hex string to be masked
|
||||||
|
-- m -> hex string mask
|
||||||
|
|
||||||
|
-- s -> hex string as masked
|
||||||
|
|
||||||
|
-- bv -> binary string of v
|
||||||
|
-- bm -> binary string mask
|
||||||
|
|
||||||
|
local bv = Hex2Bin(v)
|
||||||
|
local bm = Hex2Bin(m)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
while (string.len(bv) < 32) do
|
||||||
|
bv = "0000"..bv
|
||||||
|
end
|
||||||
|
|
||||||
|
while (string.len(bm) < 32) do
|
||||||
|
bm = "0000"..bm
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1, 32 do
|
||||||
|
cv = string.sub(bv, i, i)
|
||||||
|
cm = string.sub(bm, i, i)
|
||||||
|
if cv == "1" then
|
||||||
|
s = s.."1"
|
||||||
|
elseif cm == "1" then
|
||||||
|
s = s.."1"
|
||||||
|
else
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function BMXOr(v, m)
|
||||||
|
|
||||||
|
-- v -> hex string to be masked
|
||||||
|
-- m -> hex string mask
|
||||||
|
|
||||||
|
-- s -> hex string as masked
|
||||||
|
|
||||||
|
-- bv -> binary string of v
|
||||||
|
-- bm -> binary string mask
|
||||||
|
|
||||||
|
local bv = Hex2Bin(v)
|
||||||
|
local bm = Hex2Bin(m)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
while (string.len(bv) < 32) do
|
||||||
|
bv = "0000"..bv
|
||||||
|
end
|
||||||
|
|
||||||
|
while (string.len(bm) < 32) do
|
||||||
|
bm = "0000"..bm
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1, 32 do
|
||||||
|
cv = string.sub(bv, i, i)
|
||||||
|
cm = string.sub(bm, i, i)
|
||||||
|
if cv == "1" then
|
||||||
|
if cm == "0" then
|
||||||
|
s = s.."1"
|
||||||
|
else
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
elseif cm == "1" then
|
||||||
|
if cv == "0" then
|
||||||
|
s = s.."1"
|
||||||
|
else
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- cv and cm == "0"
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BMNot(v, m)
|
||||||
|
|
||||||
|
-- v -> hex string to be masked
|
||||||
|
-- m -> hex string mask
|
||||||
|
|
||||||
|
-- s -> hex string as masked
|
||||||
|
|
||||||
|
-- bv -> binary string of v
|
||||||
|
-- bm -> binary string mask
|
||||||
|
|
||||||
|
local bv = Hex2Bin(v)
|
||||||
|
local bm = Hex2Bin(m)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
while (string.len(bv) < 32) do
|
||||||
|
bv = "0000"..bv
|
||||||
|
end
|
||||||
|
|
||||||
|
while (string.len(bm) < 32) do
|
||||||
|
bm = "0000"..bm
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i = 1, 32 do
|
||||||
|
cv = string.sub(bv, i, i)
|
||||||
|
cm = string.sub(bm, i, i)
|
||||||
|
if cm == "1" then
|
||||||
|
if cv == "1" then
|
||||||
|
-- turn off
|
||||||
|
s = s.."0"
|
||||||
|
else
|
||||||
|
-- turn on
|
||||||
|
s = s.."1"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- leave untouched
|
||||||
|
s = s..cv
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- these functions shift right and left, adding zeros to lost or gained bits
|
||||||
|
-- returned values are 32 bits long
|
||||||
|
|
||||||
|
-- BShRight(v, nb)
|
||||||
|
-- BShLeft(v, nb)
|
||||||
|
|
||||||
|
|
||||||
|
function BShRight(v, nb)
|
||||||
|
|
||||||
|
-- v -> hexstring value to be shifted
|
||||||
|
-- nb -> number of bits to shift to the right
|
||||||
|
|
||||||
|
-- s -> binary string of v
|
||||||
|
|
||||||
|
local s = Hex2Bin(v)
|
||||||
|
|
||||||
|
while (string.len(s) < 32) do
|
||||||
|
s = "0000"..s
|
||||||
|
end
|
||||||
|
|
||||||
|
s = string.sub(s, 1, 32 - nb)
|
||||||
|
|
||||||
|
while (string.len(s) < 32) do
|
||||||
|
s = "0"..s
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function BShLeft(v, nb)
|
||||||
|
|
||||||
|
-- v -> hexstring value to be shifted
|
||||||
|
-- nb -> number of bits to shift to the right
|
||||||
|
|
||||||
|
-- s -> binary string of v
|
||||||
|
|
||||||
|
local s = Hex2Bin(v)
|
||||||
|
|
||||||
|
while (string.len(s) < 32) do
|
||||||
|
s = "0000"..s
|
||||||
|
end
|
||||||
|
|
||||||
|
s = string.sub(s, nb + 1, 32)
|
||||||
|
|
||||||
|
while (string.len(s) < 32) do
|
||||||
|
s = s.."0"
|
||||||
|
end
|
||||||
|
|
||||||
|
return Bin2Hex(s)
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,210 @@
|
||||||
|
--[[
|
||||||
|
|
||||||
|
spi.lua - Lua 5.1 flukso module for spidev message processing
|
||||||
|
|
||||||
|
Copyright (C) 2011 Bart Van Der Meerssche <bart.vandermeerssche@flukso.net>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
local nixio = require 'nixio'
|
||||||
|
local BinDecHex = require 'flukso.BinDecHex'
|
||||||
|
|
||||||
|
local os, table, string =
|
||||||
|
os, table, string
|
||||||
|
|
||||||
|
local getfenv, setmetatable, tonumber =
|
||||||
|
getfenv, setmetatable, tonumber
|
||||||
|
|
||||||
|
module (...)
|
||||||
|
local modenv = getfenv()
|
||||||
|
|
||||||
|
-- private
|
||||||
|
local function dow_crc(sequence, crc)
|
||||||
|
crc = crc or 0x00
|
||||||
|
|
||||||
|
local r1 = { 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
|
||||||
|
0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41 }
|
||||||
|
|
||||||
|
local r2 = { 0x00, 0x9d, 0x23, 0xbe, 0x46, 0xdb, 0x65, 0xf8,
|
||||||
|
0x8c, 0x11, 0xaf, 0x32, 0xca, 0x57, 0xe9, 0x74 }
|
||||||
|
|
||||||
|
local first_char = sequence:sub(1, 1)
|
||||||
|
|
||||||
|
if first_char ~= '' then
|
||||||
|
local i = nixio.bit.band(nixio.bit.bxor(first_char:byte(), crc), 0xff)
|
||||||
|
crc = nixio.bit.bxor(r1[nixio.bit.band(i, 0xf) + 1], r2[nixio.bit.rshift(i, 4) + 1])
|
||||||
|
return dow_crc(sequence:sub(2, -1), crc)
|
||||||
|
else
|
||||||
|
return nixio.bin.hexlify(string.char(crc))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new spi message object.
|
||||||
|
--
|
||||||
|
-- Attributes:
|
||||||
|
-- { to = ctrl | delta | uart
|
||||||
|
-- body = <string>
|
||||||
|
-- parsed = { <command>, <arg1>, <arg2>, ... }
|
||||||
|
-- encoded = <string>
|
||||||
|
-- received = { raw = <string>, l = <string>, crc = <string>, u = <string> }
|
||||||
|
-- decoded = { l = ..., u = ... }
|
||||||
|
-- reply = <string>
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
-- @param to The message destination: ctrl | delta | uart.
|
||||||
|
-- @param body The message body.
|
||||||
|
-- @return An spi message object.
|
||||||
|
function new_msg(to, body)
|
||||||
|
return setmetatable({ to = to, body = body }, { __index = modenv })
|
||||||
|
end
|
||||||
|
|
||||||
|
function parse(msg)
|
||||||
|
msg.parsed = {}
|
||||||
|
|
||||||
|
msg.parsed[1] = msg.body:match('^%l%l')
|
||||||
|
for arg in msg.body:gmatch('%d+') do
|
||||||
|
msg.parsed[#msg.parsed + 1] = arg
|
||||||
|
end
|
||||||
|
|
||||||
|
--> TODO: more detailed command syntax checking
|
||||||
|
end
|
||||||
|
|
||||||
|
function encode(msg)
|
||||||
|
if msg.to == 'uart' then
|
||||||
|
msg.encoded = nixio.bin.hexlify(msg.body)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if msg.parsed[1] == 'gd' then
|
||||||
|
msg.encoded = msg.parsed[1]
|
||||||
|
elseif msg.parsed[1] == 'gv' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gp' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gc' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gm' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gw' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gb' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sv' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sp' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sc' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sm' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sw' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sb' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'ct' then
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--> TODO msg.encoded = msg.encoded .. dow_crc(msg.encoded)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tx(msg, cdev)
|
||||||
|
if msg.to == 'ctrl' or msg.to == 'delta' then
|
||||||
|
cdev:write('l' .. msg.encoded .. '.\0\0')
|
||||||
|
elseif msg.to == 'uart' then
|
||||||
|
cdev:write('u' .. msg.encoded .. '\0\0')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function rx(msg, cdev)
|
||||||
|
local sequence = {}
|
||||||
|
|
||||||
|
for char in function() return cdev:read(1) end do
|
||||||
|
if char ~= '\0' then
|
||||||
|
table.insert(sequence, char)
|
||||||
|
else
|
||||||
|
-- one more read to let the AVR send a second 0x00
|
||||||
|
-- after which the AVR's state machine toggles to read mode
|
||||||
|
cdev:read(1)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
msg.received = {}
|
||||||
|
msg.received.raw = table.concat(sequence)
|
||||||
|
msg.received.l, msg.received.u = msg.received.raw:match('^l(%w*)%.?u(%w*)%.?$')
|
||||||
|
|
||||||
|
if msg.received.l ~= '' and msg.received.l:sub(1, 2) == msg.parsed[1] then
|
||||||
|
msg.received.crc = msg.received.l:sub(-2, -1)
|
||||||
|
msg.received.l = msg.received.l:sub(1, -3)
|
||||||
|
|
||||||
|
if dow_crc(msg.received.l) ~= msg.received.crc then
|
||||||
|
--> TODO implement crc error counter
|
||||||
|
msg.received.l = ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function decode(msg)
|
||||||
|
msg.decoded = {}
|
||||||
|
|
||||||
|
if msg.received.u ~= '' then
|
||||||
|
msg.decoded.u = nixio.bin.unhexlify(msg.received.u)
|
||||||
|
end
|
||||||
|
|
||||||
|
if msg.received.l ~= '' then
|
||||||
|
msg.decoded.largs = msg.received.l:sub(3, -1)
|
||||||
|
|
||||||
|
if msg.parsed[1] == 'gd' then
|
||||||
|
for i = 1, msg.decoded.largs:len() / 18 do
|
||||||
|
msg.decoded[(i-1)*3 + 1] =
|
||||||
|
tonumber(BinDecHex.Hex2Dec(msg.decoded.largs:sub((i-1)*18 + 1, (i-1)*18 + 2)))
|
||||||
|
msg.decoded[(i-1)*3 + 2] =
|
||||||
|
tonumber(BinDecHex.Hex2Dec(msg.decoded.largs:sub((i-1)*18 + 3, (i-1)*18 + 10)))
|
||||||
|
msg.decoded[(i-1)*3 + 3] =
|
||||||
|
tonumber(BinDecHex.Hex2Dec(msg.decoded.largs:sub((i-1)*18 + 11, (i-1)*18 + 18)))
|
||||||
|
end
|
||||||
|
elseif msg.parsed[1] == 'gv' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gp' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gc' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gm' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gw' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'gb' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sv' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sp' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sc' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sm' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sw' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'sb' then
|
||||||
|
|
||||||
|
elseif msg.parsed[1] == 'ct' then
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,78 @@
|
||||||
|
#! /usr/bin/env lua
|
||||||
|
|
||||||
|
--[[
|
||||||
|
|
||||||
|
fluksod.lua - Lua part of fluksod
|
||||||
|
|
||||||
|
Copyright (C) 2011 Bart Van Der Meerssche <bart.vandermeerssche@flukso.net>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
require 'dbg'
|
||||||
|
require 'nixio'
|
||||||
|
require 'nixio.fs'
|
||||||
|
local spi = require 'flukso.spi'
|
||||||
|
|
||||||
|
DAEMON = os.getenv('DAEMON') or 'fluksod'
|
||||||
|
DAEMON_PATH = os.getenv('DAEMON_PATH') or '/var/run/' .. DAEMON
|
||||||
|
|
||||||
|
O_RDWR_NONBLOCK = nixio.open_flags('rdwr', 'nonblock')
|
||||||
|
POLLIN = nixio.poll_flags('in')
|
||||||
|
|
||||||
|
function mkfifos(input)
|
||||||
|
local path = string.format('%s/%s/', DAEMON_PATH, input)
|
||||||
|
|
||||||
|
nixio.fs.mkdirr(path)
|
||||||
|
nixio.fs.unlink(path .. 'in') --> clean up mess from previous run
|
||||||
|
nixio.fs.unlink(path .. 'out') --> idem
|
||||||
|
nixio.fs.mkfifo(path .. 'in', '644')
|
||||||
|
nixio.fs.mkfifo(path .. 'out', '644')
|
||||||
|
|
||||||
|
local fdin = nixio.open(path .. 'in', O_RDWR_NONBLOCK)
|
||||||
|
local fdout = nixio.open(path .. 'out', O_RDWR_NONBLOCK)
|
||||||
|
|
||||||
|
return { fd = fdin, --> need this entry for nixio.poll
|
||||||
|
fdin = fdin,
|
||||||
|
fdout = fdout,
|
||||||
|
events = POLLIN,
|
||||||
|
revents = 0,
|
||||||
|
line = fdin:linesource() }
|
||||||
|
end
|
||||||
|
|
||||||
|
local uart = mkfifos('uart')
|
||||||
|
local ctrl = mkfifos('ctrl')
|
||||||
|
local delta = mkfifos('delta')
|
||||||
|
|
||||||
|
local fds = { uart, ctrl, delta }
|
||||||
|
|
||||||
|
local spidev = nixio.open('/dev/spidev0.0', O_RDWR_NONBLOCK)
|
||||||
|
|
||||||
|
while true do
|
||||||
|
if nixio.poll(fds, -1) then
|
||||||
|
if delta.revents == POLLIN then
|
||||||
|
--> TODO flush the delta fd after each POLLIN
|
||||||
|
local msg = spi.new_msg('delta', delta.line())
|
||||||
|
msg:parse()
|
||||||
|
msg:encode()
|
||||||
|
msg:tx(spidev)
|
||||||
|
nixio.nanosleep(0, 10e7) --> 10ms
|
||||||
|
msg:rx(spidev)
|
||||||
|
msg:decode()
|
||||||
|
--> dbg.vardump(msg)
|
||||||
|
delta.fdout:write(msg.parsed[1] .. ' ' .. table.concat(msg.decoded, ' ') .. '\n')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,60 +0,0 @@
|
||||||
#! /usr/bin/env lua
|
|
||||||
|
|
||||||
--[[
|
|
||||||
|
|
||||||
spid.lua - Lua part of the spi daemon
|
|
||||||
|
|
||||||
Copyright (C) 2011 Bart Van Der Meerssche <bart.vandermeerssche@flukso.net>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
]]--
|
|
||||||
|
|
||||||
|
|
||||||
require 'nixio.fs'
|
|
||||||
|
|
||||||
ctrl_path = os.getenv('DAEMON_PATH') .. '/ctrl/'
|
|
||||||
|
|
||||||
nixio.fs.mkdirr(ctrl_path)
|
|
||||||
nixio.fs.unlink(ctrl_path .. 'in')
|
|
||||||
nixio.fs.unlink(ctrl_path .. 'out')
|
|
||||||
|
|
||||||
nixio.fs.mkfifo(ctrl_path .. 'in', '644')
|
|
||||||
nixio.fs.mkfifo(ctrl_path .. 'out', '644')
|
|
||||||
|
|
||||||
rdwr_nonblock = nixio.open_flags('rdwr', 'nonblock')
|
|
||||||
|
|
||||||
ctrl_fd_in = nixio.open(ctrl_path .. 'in', rdwr_nonblock)
|
|
||||||
ctrl_fd_out = nixio.open(ctrl_path .. 'out', rdwr_nonblock)
|
|
||||||
|
|
||||||
pfin = nixio.poll_flags('in')
|
|
||||||
|
|
||||||
local fd = {fd = ctrl_fd_in,
|
|
||||||
events = pfin,
|
|
||||||
revents = 0}
|
|
||||||
|
|
||||||
local fds = {fd}
|
|
||||||
|
|
||||||
ctrl_line = ctrl_fd_in:linesource()
|
|
||||||
|
|
||||||
while true do
|
|
||||||
if nixio.poll(fds, 1000) then
|
|
||||||
ctrl_fd_out:write((ctrl_line() or 'nil!') .. '\n')
|
|
||||||
else
|
|
||||||
ctrl_fd_out:write('timeout\n')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
nixio.fs.unlink(ctrl_path .. 'in')
|
|
||||||
nixio.fs.unlink(ctrl_path .. 'out')
|
|
Loading…
Reference in New Issue