-
Notifications
You must be signed in to change notification settings - Fork 0
/
rf.lua
156 lines (114 loc) · 3.46 KB
/
rf.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
-- file: rf.lua
local module = {}
-- ON/OFF states (inverted)
module.ON = 0
module.OFF = 1
-- unit/switch addressing
module.SWITCH_1 = 1
module.SWITCH_2 = 2
module.SWITCH_3 = 3
module.SWITCH_4 = 4
module.SWITCH_GROUP = 0
-- timing definitions in microseconds (Telldus and Nexa self-learning protocol)
local PULSE_HIGH_T = 250 -- 1T
local ONE_LOW_T = 250 -- 1T
local ZERO_LOW_T = 1250 -- 5T
local SYNC_LOW_T = 2500 -- 10T
local PAUSE_LOW_T = 10000 -- 40T
-- pulse definitions
local SYNC = {PULSE_HIGH_T, SYNC_LOW_T}
local PAUSE = {PULSE_HIGH_T, PAUSE_LOW_T}
local ZERO = {PULSE_HIGH_T, ZERO_LOW_T, PULSE_HIGH_T, ONE_LOW_T}
local ONE = {PULSE_HIGH_T, ONE_LOW_T, PULSE_HIGH_T, ZERO_LOW_T}
local tx_addr = nil
local unit_addr = {}
-- definition of Telldus units (Nexa is inverted e.g. {1, 1} for unit one)
unit_addr[1] = {0, 0} -- one
unit_addr[2] = {0, 1} -- two
unit_addr[3] = {1, 0} -- three
unit_addr[4] = {1, 1} -- four (not official, works for self-learing Telldus and Nexa)
unit_addr[0] = {0, 0} -- unit address when group bit set to zero
local tx_pin = nil
local repeats = nil
local queue = nil
local tx_is_ready = true
function module.start(rf_cfg)
tx_addr = rf_cfg.addr
tx_pin = rf_cfg.tx_pin
repeats = rf_cfg.repeats
queue = {}
gpio.mode(tx_pin, gpio.OUTPUT)
gpio.write(tx_pin, gpio.LOW)
tx_is_ready = true
end
function module.is_ready()
return tx_is_ready
end
function module.switch_on(addr, unit)
module.switch(addr, unit, module.ON)
end
function module.switch_off(addr, unit)
module.switch(addr, unit, module.OFF)
end
function module.switch(addr, unit, onoff)
-- push switch command on the queue
table.insert(queue, {addr, unit, onoff})
-- trigger transmission
dequeue()
end
function dequeue()
-- if transmission already in progress
if tx_is_ready == false then return end
-- if queue contains elements awaiting transmission
if table.getn(queue) > 0 then send(unpack(table.remove(queue))) else queue = {} end
end
function merge(a, b)
for n=1, table.getn(b) do table.insert(a, b[n]) end
end
function send(addr, unit, onoff)
-- clear ready flag
tx_is_ready = false
-- assert tx pin is low
gpio.write(tx_pin, gpio.LOW)
local bit_buffer = {}
local raw_buffer = {}
-- channel bits for Telldus (Nexa is inverted i.e. {1, 1} but seems to work with the Telldus definition)
local channel = {0, 0}
if unit == module.SWITCH_GROUP then group = module.ON else group = module.OFF end
-- build bit sequence
--
-- HHHH HHHH HHHH HHHH HHHH HHHH HHGO CCEE
--
-- H = The first 26 bits are transmitter unique codes, and it is this code that the reciever "learns" to recognize.
-- G = Group code. Set to 0 for ON, 1 for OFF.
-- O = ON/OFF bit. Set to 0 for ON, 1 for OFF.
-- C = Channel bits.
-- E = Unit bits. Device to be turned ON or OFF.
--
merge(bit_buffer, tx_addr[addr])
merge(bit_buffer, {group})
merge(bit_buffer, {onoff})
merge(bit_buffer, channel)
merge(bit_buffer, unit_addr[unit])
-- build raw pulse buffer
--
-- start with SYNC pulse
merge(raw_buffer, SYNC)
--
-- add pulses in accordance with the bit sequence i.e. the message
for n=1, table.getn(bit_buffer) do
if bit_buffer[n] == 0 then merge(raw_buffer, ZERO) else merge(raw_buffer, ONE) end
end
--
-- stop with PAUSE pulse
merge(raw_buffer, PAUSE)
-- push raw pulse buffer to the tx
gpio.serout(tx_pin, gpio.HIGH, raw_buffer, repeats,
function()
-- set ready flag
tx_is_ready = true
-- continue to dequeue commands awaiting transmission
dequeue()
end)
end
return module