Hello! I choose Codea to make an old project: an EKG simulator (and multiparameter monitor simulator) for educational purposes. I am a nurse, working and living in Chile. I work on an hospital and teaching on a University to Nursing students. So, i use a lot an early prototype and now i started from draft because i want it to put on AppStore. I also learning to code directly on XCode but i choose Codea because aircode and i can test on the fly my program. I want to show you some photos of my first prototype, working but very buggy.
Copy and paste this code, if program stops just put play again,LANDSCAPE only.
The new version is more object oriented. The precision is very low, so 60BPM actually wont run at 60/minute.
-- Monitor Sim
-- Use this function to perform your initial setup
function setup()
backingMode(RETAINED)
deltaCumulative=0
ecgVal=0
ecgLastX=0
ecgLastY=0
smooth()
startTime= os.clock()
deltaFps=0
fpsDelta= os.clock()
intFps=0
currentFrecState=0
valFps=0
Sist = 0
Diast = 0
deltaEcgBox=10
ecgBoxWidth = 3
parameter.integer("FC",0,180,70)
parameter.integer("FR",0,50,17)
parameter.integer("Sist",0,240,125, function() if Sist < Diast then Diast = Sist end end)
parameter.integer("Diast",0,140,80, function() if Diast > Sist then Sist = Diast end end)
parameter.integer("Sat",0,100,95)
parameter.action("Sano",function() setPar(70, 17, 125, 80, 90) end)
parameter.action("Sepsis", function() setPar(140, 24, 94, 50, 92) end)
parameter.action("Bradi. Asintomática", function() setPar(41, 19, 123, 87, 94) end)
parameter.action("Bradi. Sintomática", function() setPar(34, 23, 86, 43, 85) end)
parameter.action("Crisis HTA", function() setPar(90, 21, 210, 102, 93) end)
parameter.action("Insuf. Resp I", function() setPar(142, 47, 115, 72, 72) end)
parameter.action("Insuf. Resp II", function() setPar(45, 5, 0, 0, 30) end)
parameter.action("Vaciar", function() setPar(0,0,0,0,0) end)
intResolution = 6
XCuad = (WIDTH / intResolution)-30
YCuad = (HEIGHT / intResolution)-10
textAlign(RIGHT)
font("Futura-Medium")
textMode(CORNER)
sep="- -"
end
function setPar(intFC, intFR, intSist, intDiast, intSat)
FC=intFC
FR=intFR
Sist=intSist
Diast=intDiast
Sat=intSat
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
-- background(0, 0, 0, 255)
stroke(0, 0, 0, 255)
fill(25, 25, 25, 255)
rect(WIDTH/2,0,WIDTH/2,HEIGHT)
rect(0,0,12, HEIGHT)
fps()
-- Formatting
strokeWidth(1)
stroke(69, 69, 69, 0)
for ix=1, intResolution - 1 do
line(XCuad*ix,0,XCuad*ix,HEIGHT)
end
for iy=1, intResolution - 1 do
line(0, YCuad*iy,WIDTH, YCuad*iy)
end
if FC == 0 then sFC = sep else sFC = FC end
if FR == 0 then sFR = sep else sFR = FR end
if Sist == 0 then sSist = sep else sSist = Sist end
if Diast == 0 then sDiast = sep else sDiast = Diast end
if Sat == 0 then sSat = sep else sSat = Sat end
txt("FREC CARDIACA",10,"G",XCuad * (intResolution - 3), YCuad * (intResolution - 1))
txt(sFC , 120,"G", XCuad * (intResolution - 2), YCuad * (intResolution - 1)-30)
txt("FREC RESP", 10, "W", XCuad * (intResolution - 3), YCuad * (intResolution - 2))
txt(sFR , 100, "W", XCuad * (intResolution - 2), YCuad * (intResolution - 2)-30)
if Sist == sep or Diast == sep then
PAM = sep
else
PAM = math.floor((Sist + Diast + Diast)/ 3)
end
if Sist == Diast then PAM = sep end
txt("PANI", 10, "R" , XCuad * (intResolution - 3), YCuad * (intResolution - 3))
txt(sSist .. "/" .. sDiast , 90, "R", XCuad * (intResolution - 2), YCuad * (intResolution - 3)-5)
txt("(" .. PAM .. ")", 30, "R", XCuad * (intResolution) +30, YCuad * (intResolution - 3)-30)
txt("SpO2", 10, "Y", XCuad * (intResolution - 3), YCuad * (intResolution - 4))
txt(sSat, 120, "Y", XCuad * (intResolution - 2), YCuad * (intResolution - 4)-30)
debugFpsData()
eraseBg()
drawECG()
end
function drawECG()
-- Mostrar corazon
if currentFrecState <= 0.2 then
txt("SYMBOL",20,"W",XCuad * (intResolution) + 40, YCuad * (intResolution - 1) +50)
end
-- Trazar linea
-- fill(40, 255, 0, 255)
-- ecgVal=HEIGHT -120 + (math.sin(currentFrecState*2*math.pi)*30)
ecgVal=HEIGHT -120 + (getEcgVal())
--ecgVal=g
-- ellipse(deltaEcgBox -5,ecgVal,5,5)
strokeWidth(2)
stroke(58, 255, 0, 255)
if ecgLastX == 0 then
else
line(ecgLastX,ecgLastY,deltaEcgBox,ecgVal)
end
ecgLastX=deltaEcgBox
ecgLastY=ecgVal
fill(255, 255, 255, 255)
ellipse(deltaEcgBox +4,ecgVal,4,4)
end
-- tiempo = 60' = 120'
-- 60 seg = 1 = 2
--
function eraseBg()
fill(0, 0, 0, 255)
noStroke()
rect(deltaEcgBox,0,ecgBoxWidth,HEIGHT)
fill(20, 20, 20, 255)
rect(deltaEcgBox+ecgBoxWidth,0,ecgBoxWidth,HEIGHT)
deltaEcgBox = deltaEcgBox + ecgBoxWidth -1
if deltaEcgBox >= WIDTH/2 then
deltaEcgBox=10
ecgLastX=0
end
end
function debugFpsData()
deltaTime = os.clock() - startTime
currentFrecState = currentFrecState + (deltaTime * FC/ 60)
startTime = os.clock()
deltaCumulative = deltaCumulative + 1
if currentFrecState>=1 then
print(currentFrecState)
currentFrecState = 0.001
print(deltaCumulative)
deltaCumulative = 0
end
txt("fps=" .. valFps, 12, "Y", XCuad * (intResolution - 1), YCuad * (intResolution - 4)-70)
end
function getEcgVal()
local ecgStringId = math.ceil(currentFrecState*(string.len(ecgData)/3))
local eValue = tonumber(string.sub(ecgData,(ecgStringId*3),(ecgStringId*3)+2))/10
txt(eValue, 12, "Y", XCuad * (intResolution - 1), YCuad * (intResolution - 3))
return eValue
end
function txt(strString, intSize, strColor, intX, intY) -- Imprime un texto en la pantalla
cR = 255
cG = 255
cB = 255
if strColor == "R" then
cR=255
cG=0
cB=0
elseif strColor == "G" then
cR=0
cG=255
cB=0
elseif strColor == "Y" then
cR = 255
cG = 255
cB = 0
elseif strColor == "W" then
cB = 255
cR = 255
cG = 255
end
fill(cR,cG,cB,255)
fontSize(intSize)
text(strString,intX, intY)
end
function fps()
intFps = intFps + 1
local finalFps = deltaFps +1
if os.clock()>=finalFps then
deltaFps = os.clock()
valFps=intFps
intFps=0
end
end
--ECG DATABANK
ecgData="00500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550550551552553554555556557557558558559559560560560559559558558557556555554552550547543539535531528526524522520518517516515514512510509508507506505504503502501500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500499498497496495494493492491490488486484482480478476474472470467464461458455452449446442438434430426422420435450465480495510525540555570585600615630645660675690705720735750765780795810825840855870885900915930945930915900885870855840825810795780765750735720705690675660645630615600585570555540525510495480465450435420405390375360345375405435450460468474480485489492494496497498499500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630630631631632632633633632632631631630629628627625622620618616614612610608606604602600598596594592590588586584582580578576574572570568566564562560558556554552550548546544542540538536534532530528526524522520518516515514513512511510509509508508507507506506505505504504504503503503502502502501501501500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500501501501502502502503503504504505505506506507508509510511512513514515516516517517518518518519519519519520520520520520520519519519518518518517517517516515514513512511510509508507506505504504503503503502502502502501501501501501500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500500"