--LTC-4000 Firmware - 1.0 --A product of Advanced Mesecons Devices, a Cheapie Systems company --This is free and unencumbered software released into the public domain. --See http://unlicense.org/ for more information --Lookup tables for human-readable strings and such lttypes = {"Permissive","Protected","Yellow Arrow Prot/Perm","Circular Green Prot/Perm"} pedtypes = {"Unsignalized","Signalized"} signaltypes = {"Streets 1","Roads","Streets 2"} pedbuttontypes = {"Normal","TrafficNeXt Compatibility"} shortphases = {"O","G","R","Y","FR","FY","FG","RY"} -- Green/red switched for, uh, reasons phases = {O = "Off",R = "Red",Y = "Yellow",G = "Green",RY = "RedYellow",FR = "FlashRed",FY = "FlashYellow",FG = "FlashGreen"} monitortypes = {"Straight","Left Turn","Pedestrian"} --Used for reverse lookups function pivot(table) local out = {} for k,v in pairs(table) do out[v] = k end return(out) end --Phase setter thing function setlight(light,phase) mem.currentphase[light] = phase end --Fault logger function logfault(desc,fatal) if fatal then mem.phaselocked = true end print(string.format("[LTC-4000] %s FAULT: ",(fatal and "FATAL" or "Non-fatal"))..desc) local date = os.datetable() local time = string.format(" - %04u-%02u-%02u %02u:%02u:%02u",date.year,date.month,date.day,date.hour,date.min,date.sec) table.insert(mem.faultlog,1,desc..time) end --Default parameters if event.type == "program" then mem.version = "1.0" mem.menu = "run" mem.monitor = 1 mem.monflash = false if not mem.ltatype then mem.ltatype = 1 end if not mem.ltbtype then mem.ltbtype = 1 end if not mem.ltctype then mem.ltctype = 1 end if not mem.ltdtype then mem.ltdtype = 1 end if not mem.pedatype then mem.pedatype = 1 end if not mem.pedbtype then mem.pedbtype = 1 end if not mem.pedctype then mem.pedctype = 1 end if not mem.peddtype then mem.peddtype = 1 end if not mem.signaltype then mem.signaltype = 2 end if not mem.pedbuttontype then mem.pedbuttontype = 1 end if not mem.allreda then mem.allreda = 2 end if not mem.allredb then mem.allredb = 2 end if not mem.yellowa then mem.yellowa = 3 end if not mem.yellowb then mem.yellowb = 3 end if not mem.mindwell then mem.mindwell = 10 end if not mem.sidegreen then mem.sidegreen = 7 end if not mem.pedwarn then mem.pedwarn = 7 end if not mem.sideped then mem.sideped = 5 end if not mem.llturn then mem.llturn = 4 end if not mem.name then mem.name = "Test" end mem.det = {} mem.busy = false mem.currentphase = {a = "G",b = "R",c = "G",d = "R",at = "R",bt = "R",ct = "R",dt = "R",ap = "R",bp = "R",cp = "R",dp = "R"} if not mem.phaselock then mem.phaselock = {a = "FR",b = "FR",c = "FR",d = "FR",at = "FR",bt = "FR",ct = "FR",dt = "FR",ap = "O",bp = "O",cp = "O",dp = "O"} end mem.phaselocked = false mem.faultlog = {} print("[LTC-4000] Chip programmed") end --Detector signal handling if event.type == "digiline" and string.sub(event.channel,1,9) == "detector_" then local detname = string.sub(event.channel,10) if detname == "a" or detname == "c" then print("[LTC-4000] Ignoring unused detector "..detname) elseif (detname == "at" and mem.ltatype == 1) then logfault("AT disabled but detector present",false) elseif (detname == "bt" and mem.ltbtype == 1) then logfault("BT disabled but detector present",false) elseif (detname == "ct" and mem.ltctype == 1) then logfault("CT disabled but detector present",false) elseif (detname == "dt" and mem.ltdtype == 1) then logfault("DT disabled but detector present",false) elseif (detname == "ap" and mem.pedatype == 1) then logfault("AP disabled but detector present",false) elseif (detname == "bp" and mem.pedbtype == 1) then logfault("BP disabled but detector present",false) elseif (detname == "cp" and mem.pedctype == 1) then logfault("CP disabled but detector present",false) elseif (detname == "dp" and mem.peddtype == 1) then logfault("DP disabled but detector present",false) else print("[LTC-4000] Detector "..detname.." activated") mem.det[detname] = true end print("[LTC-4000] Active detectors:") print(mem.det) end if event.type == "digiline" and mem.pedbuttontype == 2 and event.channel == "pedbutton" then if event.msg == "main" then print("[LTC-4000] Emulating detector_ap/cp for TrafficNeXt compatibility") mem.det.ap = true mem.det.cp = true elseif event.msg == "side" then print("[LTC-4000] Emulating detector_bp/dp for TrafficNeXt compatibility") mem.det.bp = true mem.det.dp = true else logfault("Unrecognized pedbutton type "..event.msg,false) end print("[LTC-4000] Active detectors:") print(mem.det) end --Phase logic for already-running cycles if mem.busy and event.type == "interrupt" and event.iid == "tick" and not mem.phaselocked then print("[LTC-4000] Continuing existing cycle at phase "..mem.cycle) if mem.cycle == "straight1" then mem.cycle = "straight2" setlight("a","R") setlight("c","R") setlight("at","R") setlight("ct","R") --Branch over to B/D leading left turn if necessary if (mem.det.bt and mem.det.dt and mem.ltbtype ~= 1 and mem.ltdtype ~= 1) or (((mem.det.bt and mem.ltbtype ~= 1) or (mem.det.dt and mem.ltdtype ~= 1)) and ((mem.det.ap and mem.pedatype ~= 1) or (mem.det.cp and mem.pedctype ~= 1))) then mem.cycle = "bdlead1" elseif mem.det.bt and mem.ltbtype ~= 1 then mem.cycle = "blead1" elseif mem.det.dt and mem.ltdtype ~= 1 then mem.cycle = "dlead1" end --If nobody wants to go straight or turn on B/D, but there are cars an AT and CT, serve them instead if mem.det.at and mem.ltatype ~= 1 and mem.det.ct and mem.ltctype ~= 1 then if not mem.det.b and not mem.det.d and not mem.det.bt and not mem.det.dt and not mem.det.ap and not mem.det.cp then mem.cycle = "aclead1" end end interrupt(mem.allreda,"tick") elseif mem.cycle == "straight2" then mem.cycle = "straight3" setlight("b","G") setlight("d","G") if mem.ltbtype == 3 then setlight("bt","FY") end if mem.ltdtype == 3 then setlight("dt","FY") end if (mem.det.ap and mem.pedatype ~= 1) or (mem.det.cp and mem.pedctype ~= 1) then mem.cycle = "straight2.5" if mem.pedatype ~= 1 then setlight("ap","G") end if mem.pedctype ~= 1 then setlight("cp","G") end end interrupt(mem.sidegreen,"tick") elseif mem.cycle == "straight2.5" then mem.cycle = "straight3" mem.det.ap = nil mem.det.cp = nil if mem.pedatype ~= 1 then setlight("ap","FR") end if mem.pedctype ~= 1 then setlight("cp","FR") end interrupt(mem.pedwarn,"tick") elseif mem.cycle == "straight3" then mem.cycle = "straight4" setlight("b","Y") setlight("d","Y") if mem.pedatype ~= 1 then setlight("ap","R") end if mem.pedctype ~= 1 then setlight("cp","R") end if mem.ltbtype == 3 then setlight("bt","Y") end if mem.ltdtype == 3 then setlight("dt","Y") end mem.det.b = nil mem.det.d = nil interrupt(mem.yellowb,"tick") elseif mem.cycle == "straight4" then mem.cycle = "mindwell" setlight("b","R") setlight("d","R") setlight("bt","R") setlight("dt","R") --Branch over to A/C leading left turn if necessary if mem.det.at and mem.det.ct and mem.ltatype ~= 1 and mem.ltbtype ~= 1 then mem.cycle = "aclead1" elseif mem.det.at and mem.ltatype ~= 1 then mem.cycle = "alead1" elseif mem.det.ct and mem.ltctype ~= 1 then mem.cycle = "clead1" end interrupt(mem.allredb,"tick") elseif mem.cycle == "mindwell" then mem.cycle = "reset" setlight("a","G") setlight("c","G") if mem.ltatype == 3 then setlight("at","FY") end if mem.ltctype == 3 then setlight("ct","FY") end if (mem.det.bp and mem.pedbtype ~= 1) or (mem.det.dp and mem.peddtype ~= 1) then mem.cycle = "sideped1" if mem.ltatype == 3 and mem.pedbtype ~= 1 then setlight("at","R") end if mem.ltctype == 3 and mem.peddtype ~= 1 then setlight("ct","R") end if mem.ltatype == 3 or mem.ltctype == 3 then interrupt(mem.yellowa,"tick") else interrupt(0,"tick") end else interrupt(mem.mindwell,"tick") end elseif mem.cycle == "bdlead1" then mem.cycle = "bdlead2" setlight("bt","G") setlight("dt","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "bdlead2" then mem.cycle = "bdlead3" mem.det.bt = nil mem.det.dt = nil setlight("bt","Y") setlight("dt","Y") interrupt(mem.yellowb,"tick") elseif mem.cycle == "bdlead3" then mem.cycle = "straight2" setlight("bt","R") setlight("dt","R") interrupt(mem.allredb,"tick") elseif mem.cycle == "blead1" then mem.cycle = "blead2" setlight("bt","G") setlight("b","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "blead2" then mem.cycle = "blead3" mem.det.bt = nil setlight("bt","Y") interrupt(mem.yellowb,"tick") elseif mem.cycle == "blead3" then mem.cycle = "straight2" setlight("bt","R") interrupt(mem.allredb,"tick") elseif mem.cycle == "dlead1" then mem.cycle = "dlead2" setlight("dt","G") setlight("d","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "dlead2" then mem.cycle = "dlead3" mem.det.dt = nil setlight("dt","Y") interrupt(mem.yellowb,"tick") elseif mem.cycle == "dlead3" then mem.cycle = "straight2" setlight("dt","R") interrupt(mem.allredb,"tick") elseif mem.cycle == "aclead1" then mem.cycle = "aclead2" setlight("at","G") setlight("ct","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "aclead2" then mem.cycle = "aclead3" setlight("at","Y") setlight("ct","Y") mem.det.at = nil mem.det.ct = nil interrupt(mem.yellowa,"tick") elseif mem.cycle == "aclead3" then mem.cycle = "mindwell" setlight("at","R") setlight("ct","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "alead1" then mem.cycle = "alead2" setlight("at","G") setlight("a","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "alead2" then mem.cycle = "alead3" setlight("at","Y") mem.det.at = nil interrupt(mem.yellowa,"tick") elseif mem.cycle == "alead3" then mem.cycle = "mindwell" setlight("at","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "clead1" then mem.cycle = "clead2" setlight("ct","G") setlight("c","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "clead2" then mem.cycle = "clead3" setlight("ct","Y") mem.det.ct = nil interrupt(mem.yellowa,"tick") elseif mem.cycle == "clead3" then mem.cycle = "mindwell" setlight("ct","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "yta1" then mem.cycle = "yta2" setlight("c","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "yta2" then mem.cycle = "yta3" setlight("at","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "yta3" then mem.cycle = "yta4" setlight("at","Y") mem.det.at = nil interrupt(mem.yellowa,"tick") elseif mem.cycle == "yta4" then mem.cycle = "mindwell" setlight("at","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "ytc1" then mem.cycle = "ytc2" setlight("a","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "ytc2" then mem.cycle = "ytc3" setlight("ct","G") interrupt(mem.llturn,"tick") elseif mem.cycle == "ytc3" then mem.cycle = "ytc4" setlight("ct","Y") mem.det.ct = nil interrupt(mem.yellowa,"tick") elseif mem.cycle == "ytc4" then mem.cycle = "mindwell" setlight("ct","R") interrupt(mem.allreda,"tick") elseif mem.cycle == "sideped1" then mem.cycle = "sideped2" if mem.ltatype == 3 and mem.pedbtype ~= 1 then setlight("at","R") end if mem.ltctype == 3 and mem.peddtype ~= 1 then setlight("ct","R") end interrupt(mem.allreda,"tick") elseif mem.cycle == "sideped2" then mem.cycle = "sideped3" if mem.pedbtype ~= 1 then setlight("bp","G") end if mem.peddtype ~= 1 then setlight("dp","G") end interrupt(mem.sideped,"tick") elseif mem.cycle == "sideped3" then mem.cycle = "sideped4" mem.det.bp = nil mem.det.dp = nil if mem.pedbtype ~= 1 then setlight("bp","FR") end if mem.peddtype ~= 1 then setlight("dp","FR") end interrupt(mem.pedwarn,"tick") elseif mem.cycle == "sideped4" then mem.cycle = "mindwell" setlight("bp","R") setlight("dp","R") interrupt(0,"tick") elseif mem.cycle == "reset" then mem.cycle = nil mem.busy = false --If someone shows up on AT/CT and turns immediately, --we shouldn't change for them unless we're completely idle or protected only if mem.ltatype ~= 2 then mem.det.at = nil end if mem.ltctype ~= 2 then mem.det.ct = nil end else logfault("Unrecognized phase "..mem.cycle,true) end end --Phase logic for starting new cycles detactive = false for _,_ in pairs(mem.det) do detactive = true end if (not mem.busy) and detactive then if mem.phaselocked then print("[LTC-4000] Not starting cycle due to phase lock") else print("[LTC-4000] Starting new cycle") if mem.det.at and mem.ltatype ~= 1 and mem.ltctype == 2 and not (mem.det.b or mem.det.d or mem.det.bt or mem.det.ct or mem.det.dt) then mem.cycle = "yta1" mem.busy = true setlight("c","Y") interrupt(mem.yellowa,"tick") elseif mem.det.ct and mem.ltctype ~=1 and mem.ltatype == 2 and not (mem.det.b or mem.det.d or mem.det.at or mem.det.bt or mem.det.dt) then mem.cycle = "ytc1" mem.busy = true setlight("a","Y") interrupt(mem.yellowa,"tick") elseif mem.det.b or mem.det.d or mem.det.bt or mem.det.dt or (mem.det.at and mem.ltatype ~= 1) or (mem.det.ct and mem.ltctype ~= 1) then mem.cycle = "straight1" mem.busy = true setlight("a","Y") setlight("c","Y") if mem.ltatype == 3 then setlight("at","Y") end if mem.ltctype == 3 then setlight("ct","Y") end interrupt(mem.yellowa,"tick") elseif (mem.det.ap and mem.pedatype ~= 1) or (mem.det.cp and mem.pedctype ~= 1) then mem.cycle = "straight1" mem.busy = true setlight("a","Y") setlight("c","Y") if mem.ltatype == 3 then setlight("at","Y") end if mem.ltctype == 3 then setlight("ct","Y") end interrupt(mem.yellowa,"tick") elseif (mem.det.bp and mem.pedbtype ~= 1) or (mem.det.dp and mem.peddtype ~= 1) then mem.cycle = "sideped1" mem.busy = true if mem.ltatype == 3 and mem.pedbtype ~= 1 then setlight("at","Y") end if mem.ltctype == 3 and mem.peddtype ~= 1 then setlight("ct","Y") end if mem.ltatype == 3 or mem.ltctype == 3 then interrupt(mem.yellowa,"tick") else interrupt(0,"tick") end else logfault("Detectors active but no cycle found",true) end end end --Touch event handling if event.type == "digiline" and event.channel == "touchscreen" then local fields = event.msg if mem.menu == "main" then if fields.exit then mem.menu = "run" elseif fields.hwsetup then mem.menu = "hwsetup" elseif fields.timing then mem.menu = "timing" elseif fields.options then mem.menu = "options" elseif fields.phaselock then mem.menu = "phaselock" elseif fields.about then mem.menu = "about" elseif fields.log then mem.menu = "log" elseif fields.monitoring then mem.menu = "monitoring" elseif fields.mancyc then mem.menu = "mancyc" end elseif mem.menu == "run" then if fields.menu then mem.menu = "main" end elseif mem.menu == "hwsetup" then if fields.cancel then mem.menu = "main" elseif fields.save then mem.menu = "main" mem.ltatype = pivot(lttypes)[fields.ltatype] mem.ltbtype = pivot(lttypes)[fields.ltbtype] mem.ltctype = pivot(lttypes)[fields.ltctype] mem.ltdtype = pivot(lttypes)[fields.ltdtype] mem.pedatype = pivot(pedtypes)[fields.pedatype] mem.pedbtype = pivot(pedtypes)[fields.pedbtype] mem.pedctype = pivot(pedtypes)[fields.pedctype] mem.peddtype = pivot(pedtypes)[fields.peddtype] mem.signaltype = pivot(signaltypes)[fields.signaltype] mem.pedbuttontype = pivot(pedbuttontypes)[fields.pedbuttontype] end elseif mem.menu == "timing" then if fields.cancel then mem.menu = "main" elseif fields.save then mem.menu = "main" mem.allreda = tonumber(fields.allreda) or mem.allreda mem.allredb = tonumber(fields.allredb) or mem.allredb mem.yellowa = tonumber(fields.yellowa) or mem.yellowa mem.yellowb = tonumber(fields.yellowb) or mem.yellowb mem.mindwell = tonumber(fields.mindwell) or mem.mindwell mem.sidegreen = tonumber(fields.sidegreen) or mem.sidegreen mem.pedwarn = tonumber(fields.pedwarn) or mem.pedwarn mem.sideped = tonumber(fields.sideped) or mem.sideped mem.llturn = tonumber(fields.llturn) or mem.llturn end elseif mem.menu == "options" then if fields.cancel then mem.menu = "main" elseif fields.save then mem.menu = "main" mem.name = fields.name end elseif mem.menu == "mancyc" then if fields.cancel then mem.menu = "main" else for _,v in pairs({"a","b","c","d","at","bt","ct","dt","ap","bp","cp","dp"}) do if fields[v] then mem.det[v] = true interrupt(0) --Forces the program to be re-run since the cycle logic is up there ^^ end end end elseif mem.menu == "log" then if fields.cancel then mem.menu = "main" elseif fields.clear then mem.faultlog = {} end elseif mem.menu == "monitoring" then if fields.cancel then mem.menu = "main" elseif fields.straight then mem.monitor = 1 elseif fields.leftturn then mem.monitor = 2 elseif fields.pedestrian then mem.monitor = 3 end elseif mem.menu == "phaselock" then if fields.cancel then mem.menu = "main" elseif fields.save then mem.menu = "main" local phases_reverse = pivot(phases) mem.phaselock.a = phases_reverse[fields.a] mem.phaselock.b = phases_reverse[fields.b] mem.phaselock.c = phases_reverse[fields.c] mem.phaselock.d = phases_reverse[fields.d] mem.phaselock.at = phases_reverse[fields.at] mem.phaselock.bt = phases_reverse[fields.bt] mem.phaselock.ct = phases_reverse[fields.ct] mem.phaselock.dt = phases_reverse[fields.dt] mem.phaselock.ap = phases_reverse[fields.ap] mem.phaselock.bp = phases_reverse[fields.bp] mem.phaselock.cp = phases_reverse[fields.cp] mem.phaselock.dp = phases_reverse[fields.dp] if mem.phaselock and fields.enable == "Disabled" then mem.currentphase = {a = "G",b = "R",c = "G",d = "R",at = "R",bt = "R",ct = "R",dt = "R",ap = "R",bp = "R",cp = "R",dp = "R"} end mem.phaselocked = fields.enable == "Enabled" end elseif mem.menu == "about" then if fields.cancel then mem.menu = "main" end else logfault("Unrecognized menu "..mem.menu,false) mem.menu = "run" end end --Light control signal sending if mem.phaselocked then mem.busy = false mem.cycle = nil mem.currentphase = mem.phaselock for k,v in pairs(mem.phaselock) do digiline_send(k,string.upper(phases[v])) end else for k,v in pairs(mem.currentphase) do digiline_send(k,string.upper(phases[v])) end end --Display drawing if event.type == "interrupt" and event.iid == "monflash" then mem.monflash = not mem.monflash end local disp = {{command="clear"}} table.insert(disp,{command="lock"}) if mem.menu == "main" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Main Menu"}) table.insert(disp,{command="addbutton",X=1,Y=1,W=2,H=1,name="exit",label="Exit"}) table.insert(disp,{command="addbutton",X=1,Y=3,W=2,H=1,name="hwsetup",label="Hardware Setup"}) table.insert(disp,{command="addbutton",X=1,Y=5,W=2,H=1,name="timing",label="Timing"}) table.insert(disp,{command="addbutton",X=4,Y=1,W=2,H=1,name="options",label="Set Name"}) table.insert(disp,{command="addbutton",X=4,Y=3,W=2,H=1,name="phaselock",label="Phase Lock"}) table.insert(disp,{command="addbutton",X=4,Y=5,W=2,H=1,name="about",label="About"}) table.insert(disp,{command="addbutton",X=7,Y=1,W=2,H=1,name="log",label="Log"}) table.insert(disp,{command="addbutton",X=7,Y=3,W=2,H=1,name="monitoring",label="Monitoring"}) table.insert(disp,{command="addbutton",X=7,Y=5,W=2,H=1,name="mancyc",label="Manual Call Entry"}) elseif mem.menu == "run" then table.insert(disp,{command="addlabel",X=0,Y=0,label=mem.name}) table.insert(disp,{command="addlabel",X=0,Y=1,label="Advanced Mesecons Devices LTC-4000"}) table.insert(disp,{command="addlabel",X=0,Y=1.5,label="FW Version: "..mem.version}) if #mem.faultlog > 0 then table.insert(disp,{command="addlabel",X=0,Y=2,label="FAULT DETECTED! Use Menu->Log to view"}) else table.insert(disp,{command="addlabel",X=0,Y=2,label="No Current Faults"}) end table.insert(disp,{command="addbutton",X=0,Y=7,W=2,H=1,name="menu",label="Menu"}) elseif mem.menu == "hwsetup" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Hardware Setup"}) table.insert(disp,{command="addlabel",X=0,Y=1,label="Left Turn A Type"}) table.insert(disp,{command="adddropdown",X=0.1,Y=1.5,W=2.25,H=1,name="ltatype",selected_id=mem.ltatype,choices=lttypes}) table.insert(disp,{command="addlabel",X=0,Y=2.5,label="Left Turn B Type"}) table.insert(disp,{command="adddropdown",X=0.1,Y=3,W=2.25,H=1,name="ltbtype",selected_id=mem.ltbtype,choices=lttypes}) table.insert(disp,{command="addlabel",X=0,Y=4,label="Left Turn C Type"}) table.insert(disp,{command="adddropdown",X=0.1,Y=4.5,W=2.25,H=1,name="ltctype",selected_id=mem.ltctype,choices=lttypes}) table.insert(disp,{command="addlabel",X=0,Y=5.5,label="Left Turn D Type"}) table.insert(disp,{command="adddropdown",X=0.1,Y=6,W=2.25,H=1,name="ltdtype",selected_id=mem.ltdtype,choices=lttypes}) table.insert(disp,{command="addlabel",X=3,Y=1,label="Pedestrian A Type"}) table.insert(disp,{command="adddropdown",X=3.1,Y=1.5,W=2.25,H=1,name="pedatype",selected_id=mem.pedatype,choices=pedtypes}) table.insert(disp,{command="addlabel",X=3,Y=2.5,label="Pedestrian B Type"}) table.insert(disp,{command="adddropdown",X=3.1,Y=3,W=2.25,H=1,name="pedbtype",selected_id=mem.pedbtype,choices=pedtypes}) table.insert(disp,{command="addlabel",X=3,Y=4,label="Pedestrian C Type"}) table.insert(disp,{command="adddropdown",X=3.1,Y=4.5,W=2.25,H=1,name="pedctype",selected_id=mem.pedctype,choices=pedtypes}) table.insert(disp,{command="addlabel",X=3,Y=5.5,label="Pedestrian D Type"}) table.insert(disp,{command="adddropdown",X=3.1,Y=6,W=2.25,H=1,name="peddtype",selected_id=mem.peddtype,choices=pedtypes}) table.insert(disp,{command="addlabel",X=6,Y=1,label="Signal Type"}) table.insert(disp,{command="adddropdown",X=6.1,Y=1.5,W=2.25,H=1,name="signaltype",selected_id=mem.signaltype,choices=signaltypes}) table.insert(disp,{command="addlabel",X=6,Y=2.5,label="Pedestrian Button Type"}) table.insert(disp,{command="adddropdown",X=6.1,Y=3,W=2.25,H=1,name="pedbuttontype",selected_id=mem.pedbuttontype,choices=pedbuttontypes}) table.insert(disp,{command="addbutton",X=6,Y=4.5,W=2,H=1,name="save",label="Save"}) table.insert(disp,{command="addbutton",X=6,Y=6,W=2,H=1,name="cancel",label="Cancel"}) elseif mem.menu == "timing" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Timing"}) table.insert(disp,{command="addfield",X=0.25,Y=1,W=2.25,H=1,name="allreda",label="All Red A/C->B/D",default=tostring(mem.allreda)}) table.insert(disp,{command="addfield",X=0.25,Y=2.5,W=2.25,H=1,name="allredb",label="All Red B/D->A/C",default=tostring(mem.allredb)}) table.insert(disp,{command="addfield",X=0.25,Y=4,W=2.25,H=1,name="yellowa",label="Yellow A/C->B/D",default=tostring(mem.yellowa)}) table.insert(disp,{command="addfield",X=0.25,Y=5.5,W=2.25,H=1,name="yellowb",label="Yellow B/D->A/C",default=tostring(mem.yellowb)}) table.insert(disp,{command="addfield",X=3.25,Y=1,W=2.25,H=1,name="mindwell",label="Minimum Dwell",default=tostring(mem.mindwell)}) table.insert(disp,{command="addfield",X=3.25,Y=2.5,W=2.25,H=1,name="sidegreen",label="B/D Green",default=tostring(mem.sidegreen)}) table.insert(disp,{command="addfield",X=3.25,Y=4,W=2.25,H=1,name="pedwarn",label="Pedestrian Warn",default=tostring(mem.pedwarn)}) table.insert(disp,{command="addfield",X=3.25,Y=5.5,W=2.25,H=1,name="sideped",label="B/D Pedestrian Walk",default=tostring(mem.sideped)}) table.insert(disp,{command="addfield",X=6.25,Y=1,W=2.25,H=1,name="llturn",label="Lead/Lag Turn",default=tostring(mem.llturn)}) table.insert(disp,{command="addbutton",X=6,Y=3.75,W=2,H=1,name="save",label="Save"}) table.insert(disp,{command="addbutton",X=6,Y=5,W=2,H=1,name="cancel",label="Cancel"}) elseif mem.menu == "options" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Set Name"}) table.insert(disp,{command="addfield",X=0.25,Y=1,W=5,H=1,name="name",label="Intersection Name",default=mem.name}) table.insert(disp,{command="addbutton",X=0.25,Y=2.5,W=2,H=1,name="save",label="Save"}) table.insert(disp,{command="addbutton",X=0.25,Y=3.5,W=2,H=1,name="cancel",label="Cancel"}) elseif mem.menu == "mancyc" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Manual Call Entry"}) table.insert(disp,{command="addbutton",X=1,Y=2,W=2,H=1,name="b",label="Straight B"}) table.insert(disp,{command="addbutton",X=1,Y=4,W=2,H=1,name="d",label="Straight D"}) if mem.ltatype ~= 1 then table.insert(disp,{command="addbutton",X=4,Y=1,W=2,H=1,name="at",label="Left Turn A"}) end if mem.ltbtype ~= 1 then table.insert(disp,{command="addbutton",X=4,Y=2,W=2,H=1,name="bt",label="Left Turn B"}) end if mem.ltctype ~= 1 then table.insert(disp,{command="addbutton",X=4,Y=3,W=2,H=1,name="ct",label="Left Turn C"}) end if mem.ltdtype ~= 1 then table.insert(disp,{command="addbutton",X=4,Y=4,W=2,H=1,name="dt",label="Left Turn D"}) end if mem.pedatype ~= 1 then table.insert(disp,{command="addbutton",X=7,Y=1,W=2,H=1,name="ap",label="Pedestrian A"}) end if mem.pedbtype ~= 1 then table.insert(disp,{command="addbutton",X=7,Y=2,W=2,H=1,name="bp",label="Pedestrian B"}) end if mem.pedctype ~= 1 then table.insert(disp,{command="addbutton",X=7,Y=3,W=2,H=1,name="cp",label="Pedestrian C"}) end if mem.peddtype ~= 1 then table.insert(disp,{command="addbutton",X=7,Y=4,W=2,H=1,name="dp",label="Pedestrian D"}) end table.insert(disp,{command="addbutton",X=4,Y=6,W=2,H=1,name="cancel",label="Back"}) elseif mem.menu == "log" then table.insert(disp,{command="addlabel",X=0,Y=0,label="Fault Log"}) table.insert(disp,{command="addbutton",X=2,Y=0,W=2,H=1,name="cancel",label="Back"}) table.insert(disp,{command="addbutton",X=4,Y=0,W=2,H=1,name="clear",label="Clear"}) if #mem.faultlog > 0 then for i=1,math.max(#mem.faultlog,10),1 do table.insert(disp,{command="addlabel",X=0,Y=1+(i/2),label=mem.faultlog[i]}) end else table.insert(disp,{command="addlabel",X=0,Y=1.5,label="No Faults"}) end elseif mem.menu == "monitoring" then interrupt(0.6,"monflash") local monitor_textures = {} monitor_textures.O = "streets_tl_off.png" monitor_textures.R = "streets_tl_red.png" monitor_textures.Y = "streets_tl_yellow.png" monitor_textures.G = "streets_tl_green.png" if mem.monflash then monitor_textures.FR = "streets_tl_red.png" monitor_textures.FY = "streets_tl_yellow.png" monitor_textures.FG = "streets_tl_green.png" else monitor_textures.FR = "streets_tl_off.png" monitor_textures.FY = "streets_tl_off.png" monitor_textures.FG = "streets_tl_off.png" end monitor_textures.RY = "streets_tl_redyellow.png" local monitor_textures_lt = {} monitor_textures_lt.O = "streets_tl_left_off.png" monitor_textures_lt.R = "streets_tl_left_red.png" monitor_textures_lt.Y = "streets_tl_left_yellow.png" monitor_textures_lt.G = "streets_tl_left_green.png" if mem.monflash then monitor_textures_lt.FR = "streets_tl_left_red.png" monitor_textures_lt.FY = "streets_tl_left_yellow.png" monitor_textures_lt.FG = "streets_tl_left_green.png" else monitor_textures_lt.FR = "streets_tl_left_off.png" monitor_textures_lt.FY = "streets_tl_left_off.png" monitor_textures_lt.FG = "streets_tl_left_off.png" end monitor_textures_lt.RY = "streets_tl_left_redyellow.png" local monitor_textures_ped = {} monitor_textures_ped.O = "streets_pl_off.png" monitor_textures_ped.R = "streets_pl_dontwalk.png" monitor_textures_ped.G = "streets_pl_walk.png" if mem.monflash then monitor_textures_ped.FR = "streets_pl_dontwalk.png" monitor_textures_ped.FY = "streets_pl_dontwalk.png" monitor_textures_ped.FG = "streets_pl_dontwalk.png" monitor_textures_ped.Y = "streets_pl_dontwalk.png" else monitor_textures_ped.FR = "streets_pl_off.png" monitor_textures_ped.FY = "streets_pl_off.png" monitor_textures_ped.FG = "streets_pl_off.png" monitor_textures_ped.Y = "streets_pl_off.png" end monitor_textures_ped.RY = "streets_pl_dontwalk.png" table.insert(disp,{command="addlabel",X=0,Y=0,label="Monitor"}) table.insert(disp,{command="addbutton",X=0,Y=2,W=2,H=1,name="straight",label="Straight"}) table.insert(disp,{command="addbutton",X=0,Y=3,W=2,H=1,name="leftturn",label="Left Turn"}) table.insert(disp,{command="addbutton",X=0,Y=4,W=2,H=1,name="pedestrian",label="Pedestrian"}) table.insert(disp,{command="addbutton",X=0,Y=6,W=2,H=1,name="cancel",label="Back"}) --Center of intersection table.insert(disp,{command="addimage",X=5.25, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6.75, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=5.25, Y=4, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6, Y=4, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6.75, Y=4, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=5.25, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png"}) table.insert(disp,{command="addimage",X=6.75, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png"}) --Approach Labels table.insert(disp,{command="addlabel",X=3.5, Y=4.25, label="A"}) table.insert(disp,{command="addlabel",X=6.25, Y=1.25, label="B"}) table.insert(disp,{command="addlabel",X=9.25, Y=4.25, label="C"}) table.insert(disp,{command="addlabel",X=6.25, Y=7.25, label="D"}) --Approach A (left) table.insert(disp,{command="addimage",X=4.5, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR270"}) table.insert(disp,{command="addimage",X=4.5, Y=4, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png^[transformR90"}) table.insert(disp,{command="addimage",X=4.5, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR90"}) table.insert(disp,{command="addimage",X=3.75, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR270"}) table.insert(disp,{command="addimage",X=3.75, Y=4, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png^[transformR90"}) table.insert(disp,{command="addimage",X=3.75, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR90"}) --Approach B (top) table.insert(disp,{command="addimage",X=5.25, Y=2.5, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png"}) table.insert(disp,{command="addimage",X=6, Y=2.5, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png"}) table.insert(disp,{command="addimage",X=6.75, Y=2.5, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR180"}) table.insert(disp,{command="addimage",X=5.25, Y=1.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png"}) table.insert(disp,{command="addimage",X=6, Y=1.75, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png"}) table.insert(disp,{command="addimage",X=6.75, Y=1.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR180"}) --Approach C (right) table.insert(disp,{command="addimage",X=7.5, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR270"}) table.insert(disp,{command="addimage",X=7.5, Y=4, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png^[transformR90"}) table.insert(disp,{command="addimage",X=7.5, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR90"}) table.insert(disp,{command="addimage",X=8.25, Y=3.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR270"}) table.insert(disp,{command="addimage",X=8.25, Y=4, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png^[transformR90"}) table.insert(disp,{command="addimage",X=8.25, Y=4.75, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR90"}) --Approach D (bottom) table.insert(disp,{command="addimage",X=5.25, Y=5.5, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png"}) table.insert(disp,{command="addimage",X=6, Y=5.5, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png"}) table.insert(disp,{command="addimage",X=6.75, Y=5.5, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR180"}) table.insert(disp,{command="addimage",X=5.25, Y=6.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png"}) table.insert(disp,{command="addimage",X=6, Y=6.25, W=1,H=1,texture_name="streets_asphalt.png^infrastructure_double_yellow_line.png"}) table.insert(disp,{command="addimage",X=6.75, Y=6.25, W=1,H=1,texture_name="streets_asphalt.png^streets_asphalt_side.png^[transformR180"}) --Traffic Lights if mem.monitor == 1 then table.insert(disp,{command="addimage",X=4.25, Y=5.5, W=1,H=1,texture_name=monitor_textures[mem.currentphase.a].."^[transformR270"}) --A table.insert(disp,{command="addimage",X=4.5, Y=2.25, W=1,H=1,texture_name=monitor_textures[mem.currentphase.b].."^[transformR180"}) --B table.insert(disp,{command="addimage",X=7.75, Y=2.5, W=1,H=1,texture_name=monitor_textures[mem.currentphase.c].."^[transformR90"}) --C table.insert(disp,{command="addimage",X=7.5, Y=5.75, W=1,H=1,texture_name=monitor_textures[mem.currentphase.d]}) --D elseif mem.monitor == 2 then table.insert(disp,{command="addimage",X=4.25, Y=5.5, W=1,H=1,texture_name=monitor_textures_lt[mem.currentphase.at].."^[transformR270"}) --A table.insert(disp,{command="addimage",X=4.5, Y=2.25, W=1,H=1,texture_name=monitor_textures_lt[mem.currentphase.bt].."^[transformR180"}) --B table.insert(disp,{command="addimage",X=7.75, Y=2.5, W=1,H=1,texture_name=monitor_textures_lt[mem.currentphase.ct].."^[transformR90"}) --C table.insert(disp,{command="addimage",X=7.5, Y=5.75, W=1,H=1,texture_name=monitor_textures_lt[mem.currentphase.dt]}) --D elseif mem.monitor == 3 then table.insert(disp,{command="addimage",X=4.25, Y=5.5, W=1,H=1,texture_name=monitor_textures_ped[mem.currentphase.ap].."^[transformR270"}) --A table.insert(disp,{command="addimage",X=4.5, Y=2.25, W=1,H=1,texture_name=monitor_textures_ped[mem.currentphase.bp].."^[transformR180"}) --B table.insert(disp,{command="addimage",X=7.75, Y=2.5, W=1,H=1,texture_name=monitor_textures_ped[mem.currentphase.cp].."^[transformR90"}) --C table.insert(disp,{command="addimage",X=7.5, Y=5.75, W=1,H=1,texture_name=monitor_textures_ped[mem.currentphase.dp]}) --D end elseif mem.menu == "phaselock" then local phaselock_phases = {"Off","Green","Red"} if mem.signaltype >= 2 then table.insert(phaselock_phases,"Yellow") table.insert(phaselock_phases,"FlashRed") table.insert(phaselock_phases,"FlashYellow") end if mem.signaltype == 3 then table.insert(phaselock_phases,"FlashGreen") table.insert(phaselock_phases,"RedYellow") end local shortphase_reverse = pivot(shortphases) table.insert(disp,{command="addlabel",X=0,Y=0,label="Phase Lock"}) table.insert(disp,{command="addlabel",X=0,Y=1,label="Straight A"}) table.insert(disp,{command="adddropdown",X=0.1,Y=1.5,W=2.25,H=1,name="a",selected_id=shortphase_reverse[mem.phaselock.a],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=0,Y=2.5,label="Straight B"}) table.insert(disp,{command="adddropdown",X=0.1,Y=3,W=2.25,H=1,name="b",selected_id=shortphase_reverse[mem.phaselock.b],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=0,Y=4,label="Straight C"}) table.insert(disp,{command="adddropdown",X=0.1,Y=4.5,W=2.25,H=1,name="c",selected_id=shortphase_reverse[mem.phaselock.c],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=0,Y=5.5,label="Straight D"}) table.insert(disp,{command="adddropdown",X=0.1,Y=6,W=2.25,H=1,name="d",selected_id=shortphase_reverse[mem.phaselock.d],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=3,Y=1,label="Left Turn A"}) table.insert(disp,{command="adddropdown",X=3.1,Y=1.5,W=2.25,H=1,name="at",selected_id=shortphase_reverse[mem.phaselock.at],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=3,Y=2.5,label="Left Turn B"}) table.insert(disp,{command="adddropdown",X=3.1,Y=3,W=2.25,H=1,name="bt",selected_id=shortphase_reverse[mem.phaselock.bt],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=3,Y=4,label="Left Turn C"}) table.insert(disp,{command="adddropdown",X=3.1,Y=4.5,W=2.25,H=1,name="ct",selected_id=shortphase_reverse[mem.phaselock.ct],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=3,Y=5.5,label="Left Turn D"}) table.insert(disp,{command="adddropdown",X=3.1,Y=6,W=2.25,H=1,name="dt",selected_id=shortphase_reverse[mem.phaselock.dt],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=6,Y=1,label="Pedestrian A"}) table.insert(disp,{command="adddropdown",X=6.1,Y=1.5,W=2.25,H=1,name="ap",selected_id=shortphase_reverse[mem.phaselock.ap],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=6,Y=2.5,label="Pedestrian B"}) table.insert(disp,{command="adddropdown",X=6.1,Y=3,W=2.25,H=1,name="bp",selected_id=shortphase_reverse[mem.phaselock.bp],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=6,Y=4,label="Pedestrian C"}) table.insert(disp,{command="adddropdown",X=6.1,Y=4.5,W=2.25,H=1,name="cp",selected_id=shortphase_reverse[mem.phaselock.cp],choices=phaselock_phases}) table.insert(disp,{command="addlabel",X=6,Y=5.5,label="Pedestrian D"}) table.insert(disp,{command="adddropdown",X=6.1,Y=6,W=2.25,H=1,name="dp",selected_id=shortphase_reverse[mem.phaselock.dp],choices=phaselock_phases}) table.insert(disp,{command="adddropdown",X=0.1,Y=7,W=2.25,H=1,name="enable",selected_id=(mem.phaselocked and 1 or 2),choices={"Enabled","Disabled"}}) table.insert(disp,{command="addbutton",X=3,Y=7,W=2,H=1,name="save",label="Save"}) table.insert(disp,{command="addbutton",X=6,Y=7,W=2,H=1,name="cancel",label="Cancel"}) elseif mem.menu == "about" then table.insert(disp,{command="addlabel",X=0,Y=0,label="About"}) table.insert(disp,{command="addlabel",X=0,Y=1,label="LTC-4000 "..mem.version}) table.insert(disp,{command="addlabel",X=0,Y=1.5,label="A product of Advanced Mesecons Devices, a Cheapie Systems company."}) table.insert(disp,{command="addlabel",X=0,Y=2,label="This is free and unencumbered software released into the public domain."}) table.insert(disp,{command="addlabel",X=0,Y=2.5,label="See http://unlicense.org/ for more information."}) table.insert(disp,{command="addbutton",X=0.25,Y=3.5,W=2,H=1,name="cancel",label="Back"}) else logfault("Unrecognized menu "..mem.menu,false) mem.menu = "run" end digiline_send("touchscreen",disp)