Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Merged to trunk for next blog post release. This has the nominally working email when startled script that can be configured to either email a plot of SPL or an MP3 of the room audio around the event. |
|---|---|
| Timelines: | family | ancestors | descendants | both | blog-splear09 | trunk |
| Files: | files | file ages | folders |
| SHA1: |
8d8ccc7f52b757d10112b15fed1d83e9 |
| User & Date: | rberteig 2015-06-16 22:18:12.993 |
Context
|
2015-06-25
| ||
| 21:36 | Change scared delta SPL threshold to 12dB from 6dB. check-in: dd66d0e331 user: rberteig tags: trunk | |
|
2015-06-16
| ||
| 22:18 | Merged to trunk for next blog post release. This has the nominally working email when startled script that can be configured to either email a plot of SPL or an MP3 of the room audio around the event. check-in: 8d8ccc7f52 user: rberteig tags: blog-splear09, trunk | |
| 22:11 | Fixed double noise gate stages in the SoX filter pipeline, restored the companding stage that should have been after a single noise gate. Tweaked levels on the noise gate. Also merged the recorder into the main scared.lua script, so that it can send email when scared based on the GPIO pin signalling. The email has a noise gated companded and MP3 encoded copy of the audio from just before the trigger to some time after the trigger. MP3 is used because both Android and iPhone appear to be able to play it directly from an email attachment. Leaf check-in: 8b86ec7568 user: rberteig tags: scared | |
|
2015-05-22
| ||
| 23:23 | Merge in the scared.lua scripts for the latest blog post. check-in: 26b540b327 user: rberteig tags: trunk | |
Changes
Added Scared/pinmmap.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 |
local GPIO=require"GPIO"
GPIO.setmode(GPIO.BOARD)
--[[
table.foreach(GPIO,function(k,v)
if type(v)=="string" or type(v)=="number" then print(k,v) end
end
)
--]]
i2c={sda=3,scl=5}
--GPIO.setup(i2c.sda,GPIO.I2C)
--GPIO.setup(i2c.scl,GPIO.I2C)
uart={tx=8,rx=10}
--GPIO.setup(uart.tx,GPIO.SERIAL)
--GPIO.setup(uart.rx,GPIO.SERIAL)
spi={mosi=19,miso=21,sclk=23}
--GIO.setup(spi.mosi, GPIO.SPI)
--GIO.setup(spi.miso, GPIO.SPI)
--GIO.setup(spi.sclk, GPIO.SPI)
--[[
pins={11,12,13,15,16,18,22,24,26}
for _,p in ipairs(pins) do
GPIO.setup(p,GPIO.IN)
end
for _,p in ipairs(pins) do
print(p, GPIO.input(p))
end
--]]
local b = false
--GPIO.setup(26,GPIO.IN,GPIO.PUD_UP)
GPIO.setup(26,GPIO.IN)
while(true) do
--GPIO.wait_for_edge(26, GPIO.BOTH)
local b0 = GPIO.input(26)
if b0 ~= b then
print(b0)
end
b = b0
end
local pinfuncs={}
pinfuncs[GPIO.IN] = "in"
pinfuncs[GPIO.OUT] = "out"
pinfuncs[GPIO.SPI] = "spi"
pinfuncs[GPIO.I2C] = "i2c"
pinfuncs[GPIO.PWM] = "pwm"
pinfuncs[GPIO.SERIAL] = "ser"
pinfuncs[GPIO.UNKNOWN] = "unk"
setmetatable(pinfuncs,{__index=function(k) return tostring(k) end})
pins={3,5,7,8,10}
for i=1,#pins do
print(i, pins[i], pinfuncs[GPIO.gpio_function(pins[i])])
end
GPIO.cleanup()
|
Added Scared/pinsysfs.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 |
local P = require "posix"
-- write str to the named file
function putfile(name,str)
local f = assert(io.open(name,"w"))
f:write(str)
f:close()
end
-- read the named file and return its content
function getfile(name)
local f = assert(io.open(name,"r"))
local str f:read"*a"
f:close()
return str
end
-- transform a list into a set for quick lookup
function SET(t)
local s = {}
for _,v in ipairs(t) do
s[v] = true
end
return s
end
-- container for GPIO functions
gpio={
pins1_1 = SET{ -- Original RPi A, B
0, 1, 4, 7,
8, 9, 10, 11, 14, 15,
17, 18, 21, 22, 23,
24, 25, },
pins1_2 = SET{ -- Rev 2 A, B
2, 3, 4, 7,
8, 9, 10, 11, 14, 15,
17, 18, 22, 23,
24, 25, 27},
pins2_0 = SET{ -- A+, B+, 2A, 2B
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},
}
-- default to RPi B+ board
-- TODO: Read /proc/cpuinfo and get this right
gpio.pins = gpio.pins2_0
-- export a sysfs pin to userland
function gpio.export(pin)
assert(gpio.pins[pin], "Can't use pin")
putfile("/sys/class/gpio/export",tostring(pin))
end
-- return a sysfs pin to the kernel
function gpio.unexport(pin)
assert(gpio.pins[pin], "Can't use pin")
putfile("/sys/class/gpio/unexport",tostring(pin))
end
-- userland path to a specific pin's atribute file
function gpio.pinpath(pin,attr)
return ("/sys/class/gpio/gpio%d/%s"):format(pin,attr)
end
-- set pin direction
function gpio.direction(pin,dir)
local path = gpio.pinpath(pin, "direction")
print("Setting "..path.." to "..dir)
putfile(path, dir)
end
-- set pin edge detector
function gpio.edge(pin,edge)
local path = gpio.pinpath(pin, "edge")
print("Setting "..path.." to "..edge)
putfile(path, edge)
end
-- blocking wait with timeout for an edge on a pin
function gpio.wait(pin)
assert(gpio.pins[pin], "Can't use pin")
local path = gpio.pinpath(pin, "value")
if not gpio.pinfd then
gpio.pinfd = P.open(path, P.O_RDONLY)
end
local p = gpio.pinfd
if not gpio.fds then gpio.fds = {} end
if not gpio.fds[p] then gpio.fds[p] = {events={}, revents={}} end
gpio.fds[p].events.PRI=true
local ret = P.poll(gpio.fds, 10000)
if ret == 0 then return 0 end
P.lseek(p,0,P.SEEK_SET)
ret = tonumber(P.read(p,8))
--P.close(p)
--gpio.pinfd = nil
return ret
end
-- Use pin P1-28 aka GPIO7 for SPLear alerts
gpio.export(7)
gpio.direction(7,"in")
gpio.edge(7,"rising")
while(true) do
local r = gpio.wait(7)
if r == 0 then
--print"timeout"
elseif r==1 then
local tim = P.gettimeofday()
print("eek "..tim.sec..'.'..tim.usec)
else
print("???", r)
end
end
if gpio.pinfd then P.close(gpio.pinfd) end
|
Added Scared/record.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 |
#! lua
local struct = require "struct"
-- today's date in (almost) ISO-8601 format
local function isodate()
return os.date"%Y%m%d-%H%M%S"
end
-- Implement a buffer of samples. For simplicity, let the
-- index increment without bound. Note that this will have
-- a problem after 2^53 samples, which is about 30 million
-- years at 10 samples per second.
local recent = {
depth=100,
n=1,
add=function(self,s)
local n = self.n
self[n] = s
self[n-self.depth] = nil
self.n = n + 1
end,
buffer=function(self)
local n1,n2 = self.n-self.depth, self.n-1
if n1 <= 0 or n2 <= 0 then return end
return table.concat(self,'',self.n-self.depth,self.n-1)
end
}
local function auheader(buf, rate)
local fmt = ">c4LLLLLL"
local hdr = struct.pack(fmt,
".snd", -- 0 magic number
struct.size(fmt), -- 1 data offset
#buf, -- 2 length or -1
1, -- 3 encoding uLaw
rate, -- 4 8152 Hz sample rate
1, -- 5 mono
0) -- 6 empty metadata string
return hdr
end
local function writeau(au, buf)
local f = assert(io.open(au,"wb"))
f:write(auheader(buf, 8152), buf)
f:close()
end
function writemp3(name, udata)
local soxgate = 'compand .1,.2 -inf,-55.1,-inf,-55,-55 0 -90 .1 '
local soxcompand = 'compand 0.3,1 6:-70,-60,-20 -5 -90 0.2 '
local soxcmd = 'sox -t au - -t wav -b 16 - '
.. soxgate
.. soxcompand
..'| lame - '..name
print(soxcmd)
local fp = assert(io.popen('sh -c "'..soxcmd..'"', 'w'))
fp:write(auheader(udata, 8152), udata)
fp:close()
end
-- Quick and dirty way to force the UART to have the
-- tty driver settings we need for clean raw access
-- to the port.
os.execute("stty -F /dev/ttyAMA0 115200"
.." pass8 raw -iexten"
.." -echo -echoe -echok -echoke -echoctl")
-- Open the UART for both reading and writing, and send
-- the SPLear command to go into uLaw recording mode. The
-- output must be unbuffered because the current SPLear
-- firmware would revert to 0.5 Hz summary mode if it
-- receives a newline.
local port = assert(io.open('/dev/ttyAMA0','r+'))
port:setvbuf"no" -- no output buffer at all
port:write"R" -- so this write is immediate
-- Loop reading the audio stream and watching for loud
-- noises, keeping a log of recent samples as we go.
-- When a loud noise is heard, keep logging for a bit
-- before sending email. Include the log in the email.
while true do
local buf = port:read(1000) -- sampled at 8153 Hz probably
recent:add(buf)
if recent.n % 8 == 0 then
io.write(tostring(recent.n),"\r")
io.flush()
end
if recent.n > recent.depth then
local eek = "rec-"..isodate()
--writeau(eek..".au", recent:buffer())
writemp3(eek..".mp3", recent:buffer())
return
end
end
|
Changes to Scared/scared.lua.
1 2 3 | #! lua local plot = require "plotspl" | > > > | > > > > > > > | | | < | | | | > > > > > > > > > > > > > > > > | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
#! lua
local lanes = require "lanes".configure()
local plot = require "plotspl"
local struct = require "struct"
local rc = dofile"scared.rc"
rc.address = rc.address or "user@example.com"
rc.mode = rc.mode or "SPL"
-- today's date in (almost) ISO-8601 format
local function isodate()
return os.date"%Y-%m-%d %H:%M:%S"
end
-- today's date for use in a file name
local function namedate()
return os.date"%Y%m%d-%H%M%S"
end
-- make its argument be a single double-quoted string
function flatten(s)
if type(s)=="string" then return '"'..s..'"' end
if type(s)~="table" then return nil end
return '"'..table.concat(s, '" "')..'"'
end
-- Send an email to addr with subject and body. If body
-- is nil then just repeat the subject. This assumes that
-- a "mail" command is available with the usual options.
local function email(addr, subj, body)
body = body or subj
local mail = ("mail -s '%q' %s"):format(subj,addr)
local b = assert(io.popen(mail, "w"))
b:write([[I heard a noise on ]], isodate(), "\r\n\r\n")
b:write(body, "\r\n\r\n")
b:write"(This an automated message.)\r\n"
b:close()
end
-- Send a MIME packed email containing a file related
-- to the event to a recipient with a subject
local function mpack(address, subject, file)
assert(address)
assert(subject)
assert(file)
local cmd = ("mpack -a -s %q %q %s"):format(subject, file, address)
print(cmd)
os.execute(cmd)
end
-- Implement a buffer of samples. For simplicity, let the
-- index increment without bound. Note that this will have
-- a problem after 2^53 samples, which is about 30 million
-- years at 10 samples per second or 300 thousand years at
-- about 1000 samples per second.
local recent = {
depth=200,
n=1,
-- clear the buffer and set a new depth
clear=function(self,newdepth)
newdepth = newdepth or 200
local offset = self.n-self.depth-1
for i=1,self.depth do
self[i+offset] = nil
end
self.n = 1
self.depth = newdepth
end,
-- add a sample to the buffer
add=function(self,spl)
local n = self.n
self[n] = spl
self[n-self.depth] = nil
self.n = n + 1
end,
-- return the entire buffer as a raw blob
raw=function(self)
return table.concat(self,'',self.n-self.depth,self.n-1)
end,
-- return a CSV formatted buffer assuming the samples
-- are SPL levels at 10 Hz
CSVtext=function(self, header)
local t = header and {"s, dB"} or {}
local offset = self.n-self.depth-1
for i=1,self.depth do
if self[i+offset] then
t[#t+1] = ("%0.1f, %s"):format(i/10,self[i+offset])
end
end
return table.concat(t,"\n")
end
}
local function auheader(buf, rate)
local fmt = ">c4LLLLLL"
local hdr = struct.pack(fmt,
".snd", -- 0 magic number
struct.size(fmt), -- 1 data offset
#buf, -- 2 length or -1
1, -- 3 encoding uLaw
rate, -- 4 8152 Hz sample rate
1, -- 5 mono
0) -- 6 empty metadata string
return hdr
end
local function writeau(au, buf)
local f = assert(io.open(au,"wb"))
f:write(auheader(buf, 8152), buf)
f:close()
end
function writemp3(name, udata)
local soxgate = 'compand .1,.2 -inf,-55.1,-inf,-55,-55 0 -90 .1 '
local soxcompand = 'compand 0.3,1 6:-70,-60,-20 -5 -90 0.2 '
local soxcmd = 'sox -t au - -t wav -b 16 - '
.. soxgate
.. soxcompand
..'| lame - '..name
print(soxcmd)
local fp = assert(io.popen('sh -c "'..soxcmd..'"', 'w'))
fp:write(auheader(udata, 8000), udata)
fp:close()
end
-- Quick and dirty way to force the UART to have the
-- tty driver settings we need for clean raw access
-- to the port.
os.execute("stty -F /dev/ttyAMA0 115200"
.." pass8 raw -iexten"
.." -echo -echoe -echok -echoke -echoctl")
-- Open the UART for both reading and writing, and send
-- the SPLear command to go into raw SPL sample mode. The
-- output must be unbuffered because the current SPLear
-- firmware would revert to 0.5 Hz summary mode if it
-- receives a newline.
local port = assert(io.open('/dev/ttyAMA0','r+'))
port:setvbuf"no" -- no output buffer at all
local addr = flatten(rc.address)
print("Notifying "..addr)
-- command the requested mode
if rc.mode == "record" then
port:write"R" -- so this write is immediate
local msgs = lanes.linda()
-- temporary simulation of noises by 10 second timer
lanes.timer(msgs, "tick", 10, 10)
-- Function running in a separate thread that watches for loud
-- noises signled via GPIO pin
pinwatcher = lanes.gen("*", function()
gpio = require "sysfsgpio"
gpio.export(7)
gpio.direction(7, "in")
gpio.edge(7, "rising")
print("Watching GPIO07 which is pin P1-26")
while true do
--local _, t = msgs:receive"tick" -- external simulation timer
local r = gpio.wait(7)
if r == 0 then
-- poll timed out
elseif r == 1 then
msgs:send("eek", isodate())
else
-- something unexpected happened
end
end
end
)()
-- main loop reads data as usual, keeping an eye out for
-- being scared, after which it saves and emails a recording.
local triggered = false
local eek
while true do
local sample = port:read(800) -- read 1/10 sec audio
if sample then
io.write("Rec "..(triggered and "TRG " or " "), recent.n, "\r")
io.flush()
recent:add(sample)
-- Notice GPIO pin
local s = pinwatcher.status
if not (s == "waiting" or s == "running" or s == "pending") then
print("Watcher status: "..s)
break
end
local eekflag, eekval = msgs:receive(0.0, "eek")
if eekflag then
if not triggered then
triggered = math.floor(recent.depth * 2. / 3.)
eek = "EEK! "..eekval
end
end
if triggered then
triggered = triggered - 1
if triggered == 0 then
triggered = false
local data = recent:raw(false)
local mp3file = "eek-"..namedate()..".mp3"
writemp3(mp3file, data)
print("email " .. addr, mp3file, isodate())
mpack(addr, eek, mp3file)
end
end
spl0 = spl
end
end
else -- mode == "SPL"
port:write"S" -- so this write is immediate
-- Loop reading the SPL samples and watching for loud
-- noises, keeping a log of recent samples as we go.
-- When a loud noise is heard, keep logging for a bit
-- before sending email. Include the log in the email.
local spl, spl0
local triggered = false
local eek = ""
while true do
local line = port:read"*l" -- read a single line
spl = tonumber(line)
if spl then
spl = 0.75 * spl
io.write("SPL "..(triggered and "TRG " or " "), spl, "\r")
recent:add(spl)
-- Watch for the trigger condition: 12 dB louder
if not triggered and spl0 and (spl - spl0 > 12.) then
triggered = math.floor(recent.depth * 2. / 3.)
eek = "EEK! "..spl.." dB"
end
if triggered then
triggered = triggered - 1
if triggered == 0 then
triggered = false
local data = recent:CSVtext(false)
local pngfile = "tmp-SPL.png"
plot.plot(data,
pngfile,
recent.depth/30., -- 1/3 trigger pos, 1/10 for time scale
"Startled at "..isodate())
local body = eek.."\n"..data
print("email " .. addr, eek, isodate())
mpack(addr, eek, pngfile)
end
end
spl0 = spl
end
end
end
|
Added Scared/sysfsgpio.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 |
-- Module to make GPIO via the sysfs gpio class interface easy
-- for simple Lua applications.
-- simplest minimal module framework, just return M
local M = {
_NAME=(...),
_VERSION="v0.001",
}
-- Utility functions private to the module
local P = require "posix"
-- write str to the named file
function putfile(name,str)
local f = assert(io.open(name,"w"))
f:write(str)
f:close()
end
-- read the named file and return its content
function getfile(name)
local f = assert(io.open(name,"r"))
local str f:read"*a"
f:close()
return str
end
-- transform a list into a set for quick lookup
function SET(t)
local s = {}
for _,v in ipairs(t) do
s[v] = true
end
return s
end
-- container for GPIO functions, alias to M
local gpio=M
gpio.pins1_1 = SET{ -- Original RPi A, B
0, 1, 4, 7,
8, 9, 10, 11, 14, 15,
17, 18, 21, 22, 23,
24, 25, }
gpio.pins1_2 = SET{ -- Rev 2 A, B
2, 3, 4, 7,
8, 9, 10, 11, 14, 15,
17, 18, 22, 23,
24, 25, 27}
gpio.pins2_0 = SET{ -- A+, B+, 2A, 2B
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}
-- default to RPi B+ board
-- TODO: Read /proc/cpuinfo and get this right based on the
-- Hardware and Revision fields. For now, just assume
-- what I have will work.
gpio.pins = gpio.pins2_0
-- export a sysfs pin to userland
function gpio.export(pin)
assert(gpio.pins[pin], "Can't use pin")
putfile("/sys/class/gpio/export",tostring(pin))
end
-- return a sysfs pin to the kernel
function gpio.unexport(pin)
assert(gpio.pins[pin], "Can't use pin")
putfile("/sys/class/gpio/unexport",tostring(pin))
end
-- userland path to a specific pin's atribute file
function gpio.pinpath(pin,attr)
return ("/sys/class/gpio/gpio%d/%s"):format(pin,attr)
end
-- set pin direction
function gpio.direction(pin,dir)
local path = gpio.pinpath(pin, "direction")
--print("Setting "..path.." to "..dir)
putfile(path, dir)
end
-- set pin edge detector
function gpio.edge(pin,edge)
local path = gpio.pinpath(pin, "edge")
--print("Setting "..path.." to "..edge)
putfile(path, edge)
end
-- blocking wait with timeout for an edge on a pin
function gpio.wait(pin)
assert(gpio.pins[pin], "Can't use pin")
local path = gpio.pinpath(pin, "value")
if not gpio.pinfd then
gpio.pinfd = P.open(path, P.O_RDONLY)
end
local p = gpio.pinfd
if not gpio.fds then gpio.fds = {} end
if not gpio.fds[p] then gpio.fds[p] = {events={}, revents={}} end
gpio.fds[p].events.PRI=true
local ret = P.poll(gpio.fds, 10000)
if ret == 0 then return 0 end
P.lseek(p,0,P.SEEK_SET)
ret = tonumber(P.read(p,8))
--P.close(p)
--gpio.pinfd = nil
return ret
end
--Example
--[===[
-- Use pin P1-28 aka GPIO7 for SPLear alerts
-- local gpio = require "sysfsgpio"
gpio.export(7)
gpio.direction(7,"in")
gpio.edge(7,"rising")
while(true) do
local r = gpio.wait(7)
if r == 0 then
--print"timeout"
elseif r==1 then
local tim = P.gettimeofday()
print("eek "..tim.sec..'.'..tim.usec)
else
print("???", r)
end
end
if gpio.pinfd then P.close(gpio.pinfd) end
--]===]
-- TODO: Do some minimal validation that there actually is
-- a sysfs and error out if not.
return M
|
Added Scared/volley.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 |
local lanes = require 'lanes'.configure()
local msg = lanes.linda()
local function volley(n,isa)
print("Starting "..(isa and "A" or "B"), n)
local rkey,skey = "a","b"
if isa then
skey,rkey = rkey,skey
end
msg:send("done",true)
for i=1,n do
local ball,value = msg:receive(rkey)
msg:send(skey, value+1)
end
msg:send("done",true)
end
print("starting threads")
local gen = lanes.gen("",volley)
local N = 1e5
local a = gen(N, true)
local b = gen(N)
local ok,_ = msg:receive(0.5, msg.batched, "done", 2)
if not ok then print "ouch" return end
local t0 = os.time()
msg:send("a", 0)
msg:receive(nil, msg.batched, "done", 2)
local t1 = os.time()
print((t1-t0).." sec")
print(((t1-t0)/N).." sec")
print((N/(t1-t0)).." per sec")
|