Commit b0ae82ab authored by Marcus Greiff's avatar Marcus Greiff

Added PWM tests

parent b8734a6c
......@@ -48,7 +48,7 @@ const gpio_channels =[
]
# These pins are exported with the Device Tree Overlay cape-universaln (default)
const validPins = Dict(
const pwm_pins = Dict(
"P9.22" => ("PWM0A", "pwmchip0", "0"),
"P9.21" => ("PWM0B", "pwmchip0", "1"),
"P9.14" => ("PWM1A", "pwmchip2", "0"),
......
......@@ -10,29 +10,25 @@ type PWM <: IO_Object
i::Int32
pin::String
chip::String
basedir::String
filestreams::Array{IOStream,1}
function PWM(i::Int32)
pins = collect(keys(validPins))
(i < 1 || i > length(pins)) && error("Invalid PWM index: $i")
pin = pins[i]
# Configure the pin to run PWM if possible
Base.run(`config-pin $(pin) pwm`)
# Find chip and export number
chip = validPins[pin][2]
filename = "/sys/class/pwm/$(chip)/export"
exportNumber = validPins[pin][3]
(i < 1 || i > length(pwm_pins)) && error("Invalid PWM index: $i")
# Export the filestructure of the corresponding chip
write(filename, exportNumber)
# Export the PWM pin
basedir = export_pwm(i)
# Setup filestreams
enable_filestream = open("/sys/class/pwm/$(validPins[pin][2])/pwm$(validPins[pin][3])/enable","r+")
period_filestream = open("/sys/class/pwm/$(validPins[pin][2])/pwm$(validPins[pin][3])/period","r+")
duty_cycle_filestream = open("/sys/class/pwm/$(validPins[pin][2])/pwm$(validPins[pin][3])/duty_cycle","r+")
polarity_filestream = open("/sys/class/pwm/$(validPins[pin][2])/pwm$(validPins[pin][3])/polarity","r+")
return new(i, pin, chip, [enable_filestream, period_filestream, duty_cycle_filestream, polarity_filestream])
pins = collect(keys(pwm_pins))
pin = pins[i]
chip = pwm_pins[pin][2]
enable_filestream = open("$(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3])/enable","r+")
period_filestream = open("$(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3])/period","r+")
duty_cycle_filestream = open("$(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3])/duty_cycle","r+")
polarity_filestream = open("$(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3])/polarity","r+")
return new(i, pin, chip, basedir, [enable_filestream, period_filestream, duty_cycle_filestream, polarity_filestream])
end
end
......@@ -46,40 +42,114 @@ function write!(pwm::PWM, args::Tuple{Int32,String}, debug::Bool=false)
operation, entry = args[1], args[2]
(operation < 1 || operation > length(pwm.filestreams)) && error("Invalid PWM operation: $operation")
#TODO: Add a list of allowed entries for error checking
write(pwm.filestreams[operation], entry)
# Input data check
assert_pwm_write(operation, entry)
# Write to file
seekstart(pwm.filestreams[operation])
write(pwm.filestreams[operation], "$entry\n")
flush(pwm.filestreams[operation])
end
"""
assert_pwm_write(operation::Int32, entry::String)
Assertsion for the PWM input data
"""
function assert_pwm_write(operation::Int32, entry::String)
if operation == "1"
entry ["0", "1"] && error("Invalid SysLED entry $(entry), valid options are 0 and 1 ::String")
else
number = try
parse(Int32, entry)
catch
error("Invalid SysLED entry $(entry), cannot parse as Int32")
end
(number < 0 || number > 100000000) && error("Invalid SysLED entry $(entry), not in the range [0,100000000]")
end
end
"""
l = read(pwm::PWM, operation::Int32, debug::Bool=false)
Reads the current value from an operation on a PWM.
Reads the current value from an operation on a GPIO.
"""
function read(pwm::PWM, operation::Int32, debug::Bool=false)
debug && return
(operation < 1 || operation > length(pwm.filestreams)) && error("Invalid PWM operation: $operation")
l = readline(pwm.filestreams[operation])
# Filestreams 1, 2 and 3 are readable
operation [1,2,3,4] && error("Invalid GPIO operation: $operation for reading")
seekstart(pwm.filestreams[operation])
l = readline(pwm.filestreams[operation])
return l
end
"""
teardown!(pwd::PWM)
Closes all open streams on the PWM, and unexports it from the file system
"""
function teardown!(pwm::PWM, debug::Bool=false)
debug && return
#Close all IOStreams
for stream in pwm.filestreams
close(stream)
end
#Unexport filestructure
filename = "/sys/class/pwm/$(pwm.chip)/unexport"
export_number = validPins[pwm.pin][3]
write(filename, export_number)
return
function teardown(pwm::PWM, debug::Bool=false)
debug && return
#Close all IOStreams
for stream in pwm.filestreams
close(stream)
end
if isdefined(:RUNNING_TESTS)
# Remove the dummy file system for testing
try
rm("$(pwm.basedir)/$(pwm_pins[pwm.pin][2])/pwm$(pwm_pins[pwm.pin][3])"; recursive=true)
catch
error("Could not remove the requested GPIO testfiles for channel $(pwm_pins[pwm.pin][2])/pwm$(pwm_pins[pwm.pin][3]).")
end
else
#Unexport filestructure
filename = "/sys/class/pwm/$(pwm.chip)/unexport"
export_number = pwm_pins[pwm.pin][3]
write(filename, export_number)
end
end
"""
export_gpio(i::Int32, debug::Bool=false)
Export the GPIO file system, either for real-time or testing usecases.
"""
function export_pwm(i::Int32)
# Find chip and export number
pins = collect(keys(pwm_pins))
pin = pins[i]
chip = pwm_pins[pin][2]
if isdefined(:RUNNING_TESTS)
# Export a dummy file system for testing
basedir = "$(pwd())/testfilesystem/pwm"
complete_path = "$(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3])"
try
mkpath(complete_path)
catch
error("Could not export the PWM device for $(pwm_pins[pin][2]) for testing as the directory $(basedir)/$(pwm_pins[pin][2])/pwm$(pwm_pins[pin][3]) already exists.")
end
try
f = open("$(complete_path)/enable", "w"); write(f,"0"); close(f);
f = open("$(complete_path)/period", "w"); write(f,"0"); close(f);
f = open("$(complete_path)/duty_cycle", "w"); write(f,"0"); close(f);
f = open("$(complete_path)/polarity", "w"); write(f,"0"); close(f);
catch
error("Could not open the requested GPIO testfiles for $(complete_path).")
end
else
basedir = "/sys/class/pwm"
# Configure the pin to run PWM if possible
Base.run(`config-pin $(pin) pwm`)
# Export the filestructure of the corresponding chip
filename = "/sys/class/pwm/$(chip)/export"
exportNumber = pwm_pins[pin][3]
write(filename, exportNumber)
end
return basedir
end
"""
......
using LabConnections.BeagleBone
import LabConnections.BeagleBone: initdev, listdev, closedev, printdev, write!, read, pwm_pins
using Base.Test
@testset "PWM tests" begin
@testset "Inialization and termination" begin
@test 1 == 1
@testset "Inialization/Termination" begin
# Initialize three devices
initdev("pwm", Int32(1))
@test sum(listdev()) == 1
initdev("pwm", Int32(3))
@test sum(listdev()) == 2
initdev("pwm", Int32(5))
@test sum(listdev()) == 3
#printdev("gpio", 3)
# Attempt to initialize a device which has already been initialized
@test_throws ErrorException initdev("pwm", Int32(1))
@test_throws ErrorException initdev("pwm", Int32(3))
@test_throws ErrorException initdev("pwm", Int32(5))
# Attempt to initialize a device with a very high index (no matching channel)
@test_throws ErrorException initdev("pwm", Int32(1000))
# Attempt to remove devices which have not been initialized
@test_throws ErrorException closedev("pwm", Int32(2))
@test_throws ErrorException closedev("pwm", Int32(4))
@test_throws ErrorException closedev("pwm", Int32(6))
#printdev("gpio", 3)
# Remove devices from TOC
closedev("pwm", Int32(1))
@test sum(listdev()) == 2
closedev("pwm", Int32(3))
@test sum(listdev()) == 1
closedev("pwm", Int32(5))
@test sum(listdev()) == 0
end
@testset "Read and write" begin
@test 1 == 1
@testset "Read/Write" begin
# Fixture
device = initdev("pwm", Int32(1))
# Test that an exception is thrown when an invalid operation is given
# supported operations are 1,2,3,
@test_throws ErrorException write!(device, (Int32(0), "something"))
@test_throws ErrorException write!(device, (Int32(5), "something"))
# Test thet exceptions are thrown when attempting to write faulty entries
@test_throws ErrorException write!(device, (Int32(1), "-1"))
@test_throws ErrorException write!(device, (Int32(1), "bad_entry"))
@test_throws ErrorException write!(device, (Int32(2), "-1"))
@test_throws ErrorException write!(device, (Int32(2), "100000001"))
@test_throws ErrorException write!(device, (Int32(2), "bad_entry"))
@test_throws ErrorException write!(device, (Int32(3), "-1"))
@test_throws ErrorException write!(device, (Int32(3), "100000001"))
@test_throws ErrorException write!(device, (Int32(3), "bad_entry"))
@test_throws ErrorException write!(device, (Int32(4), "-1"))
@test_throws ErrorException write!(device, (Int32(4), "100000001"))
@test_throws ErrorException write!(device, (Int32(4), "bad_entry"))
# Close Gpio
closedev("pwm", Int32(1))
end
@testset "All pins" begin
# Instanciate all possible leds and perform 10 read/write commands
# with the set high/low operation ("value")
# Configure the GPIO for output usage
devices = []
for ii = 1:length(pwm_pins)
device = initdev("pwm", Int32(ii))
# Operation 2 -> in/out, set out
write!(device, (Int32(2), "100000000"))
@test read(device, Int32(2)) == "100000000"
write!(device, (Int32(3), "50000000"))
@test read(device, Int32(3)) == "50000000"
write!(device, (Int32(1), "1"))
@test read(device, Int32(1)) == "1"
# Append to list
append!(devices, [device])
end
@test sum(listdev()) == 6
sleep(1.0)
# Closes all devices
for ii = 1:length(pwm_pins)
write!(devices[ii], (Int32(1), "0"))
closedev("pwm", Int32(ii))
end
@test sum(listdev()) == 0
end
end
using LabConnections.BeagleBone
using Base.Test
# This flag is enabled if a dummy filesystem should be used for testing (for online testing)
# disabling the flag allows the BBB to be run in the loop, in this case blinking LEDS
#RUNNING_TESTS = true
RUNNING_TESTS = true
# Run tests
include("BeagleBone/SYS_LED_test.jl")
include("BeagleBone/GPIO_test.jl")
include("BeagleBone/PWM_test.jl")
# Remove the testfilesystem
try
rm("$(pwd())/testfilesystem", recursive=true)
catch
println("Warning. Could not remove the testfilesystem.")
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment