Last active
August 26, 2016 09:55
-
-
Save jsopenrb/f97f85f9d010c70cd61856c6766aae6a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local luadmx = require('luadmx') | |
module('DMX', package.seeall) | |
local DMX = {} | |
-- default params | |
local defaults = { | |
-- storage key | |
skey = 'dmx_line_1', | |
-- RS-485 port | |
port = '/dev/RS485', | |
-- number of calls per second | |
resolution = 20, | |
-- total number of channels to use | |
channels = 3, | |
-- transition time in seconds, does not include DMX transfer time | |
transition = 2, | |
} | |
-- value setter | |
function set(chan, val, key) | |
key = key or defaults.skey | |
chan = tonumber(chan) or 0 | |
val = tonumber(val) or -1 | |
-- validate channel number and value | |
if chan >= 1 and chan <= 512 and val >= 0 and val <= 255 then | |
storage.exec('lset', key, chan - 1, val) | |
end | |
end | |
-- value getter | |
function get(chan, key) | |
local res, val | |
key = key or defaults.skey | |
chan = tonumber(chan) or 0 | |
-- validate channel number and value | |
if chan >= 1 and chan <= 512 then | |
res = storage.exec('lrange', key, chan - 1, chan - 1) | |
if type(res) == 'table' then | |
val = tonumber(res[ 1 ]) | |
end | |
end | |
return val | |
end | |
-- DMX init, returns new DMX object | |
function init(params) | |
local n, k, v, _ | |
-- create metatable and set user parameters | |
n = setmetatable({}, { __index = DMX }) | |
n.params = params or {} | |
_, n.conn = pcall(require('redis').connect) | |
-- merge parameters that are set by user | |
for k, v in pairs(defaults) do | |
if n.params[ k ] == nil then | |
n.params[ k ] = v | |
end | |
end | |
n:reset() | |
return n | |
end | |
function DMX:reset() | |
local err, chan, params | |
params = self.params | |
self.dm, err = luadmx.open(params.port) | |
-- error while opening | |
if err then | |
os.sleep(1) | |
error(err) | |
end | |
-- set channel count | |
self.dm:setcount(params.channels) | |
-- number of transaction ticks | |
self.ticks = math.max(1, params.transition * params.resolution) | |
-- calculate sleep time | |
self.sleep = 1 / params.resolution | |
-- reset channel map | |
self.channels = {} | |
-- empty channel value map | |
self.conn:ltrim(params.skey, 1, 0) | |
-- fill channel map | |
for chan = 1, params.channels do | |
self.channels[ chan ] = { current = 0, target = 0, ticks = 0 } | |
-- turn off by default | |
self.conn:lpush(params.skey, 0) | |
self.dm:setchannel(chan, 0) | |
end | |
end | |
-- get new values | |
function DMX:getvalues() | |
local max, channels, ticks, values, val | |
max = self.params.channels | |
channels = self.channels | |
ticks = self.ticks | |
values = self.conn:lrange(self.params.skey, 0, max - 1) or {} | |
-- check for new values for each channel | |
for chan = 1, max do | |
val = tonumber(values[ chan ]) or 0 | |
-- target value differs, set transcation | |
if val ~= channels[ chan ].target then | |
channels[ chan ].target = val | |
channels[ chan ].delta = (channels[ chan ].target - channels[ chan ].current) / ticks | |
channels[ chan ].ticks = ticks | |
end | |
end | |
end | |
-- main loop handler | |
function DMX:run() | |
self:getvalues() | |
-- transition loop | |
for i = 1, self.params.resolution do | |
self:step() | |
self.dm:send() | |
os.sleep(self.sleep) | |
end | |
end | |
-- single transition step | |
function DMX:step() | |
local chan, channels, t | |
channels = self.channels | |
-- transition for each channel | |
for chan = 1, self.params.channels do | |
t = channels[ chan ].ticks | |
-- transition is active | |
if t > 0 then | |
t = t - 1 | |
channels[ chan ].current = channels[ chan ].target - channels[ chan ].delta * t | |
channels[ chan ].ticks = t | |
self.dm:setchannel(chan, channels[ chan ].current) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment