mirror of
https://github.com/xtacocorex/CHIP_IO
synced 2025-07-20 12:53:22 +00:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
40ae9a5cdc | |||
20b72490f2 | |||
7e83fa8435 | |||
c3448ec661 | |||
42e17edc4a | |||
b180fe1d6f | |||
a62a26dae0 | |||
0ed1cfb352 | |||
4f6acf4676 | |||
01347416ab | |||
e270080af8 | |||
44121ed5eb | |||
00140c2008 | |||
ee8445918e | |||
1c4168cf0d | |||
ea4a21235d | |||
bff65d346d |
@ -1,3 +1,28 @@
|
||||
0.2.1
|
||||
----
|
||||
* Pull request #12 fixes:
|
||||
- Fixed indent in the i2c-1 dts
|
||||
- Removed import dependencies in the SPI and PWM overlays
|
||||
- Re-enabled building of the dtbo on setup.py install
|
||||
|
||||
0.2.0
|
||||
----
|
||||
* Added the ability to load DTB Overlays from within CHIP_IO
|
||||
- Support for PWM0, SPI2, and I2C-1 (which comes back as i2c-3 on the 4.4 CHIP
|
||||
- Support for a custom DTB Overlay
|
||||
* Fixes to the pwm unit test, all but 2 now pass :)
|
||||
|
||||
0.1.2
|
||||
----
|
||||
* SoftPWM Fix by aninternetof
|
||||
* Added a verification test for SoftPWM
|
||||
|
||||
0.1.1
|
||||
----
|
||||
* Some refactoring of the edge detection code, made it function better
|
||||
* Added Rising and Both edge detection tests to gptest.py
|
||||
- Small issue with both edge triggering double pumping on first callback hit
|
||||
|
||||
0.1.0
|
||||
----
|
||||
* Fixed edge detection code, will trigger proper for callbacks now
|
||||
|
202
CHIP_IO/OverlayManager.py
Normal file
202
CHIP_IO/OverlayManager.py
Normal file
@ -0,0 +1,202 @@
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
DEBUG = False
|
||||
|
||||
OVERLAYINSTALLPATH = "/lib/firmware/chip_io"
|
||||
OVERLAYCONFIGPATH = "/sys/kernel/config/device-tree/overlays"
|
||||
CUSTOMOVERLAYFILEPATH = ""
|
||||
|
||||
PWMSYSFSPATH = "/sys/class/pwm/pwmchip0"
|
||||
I2C1SYSFSPATH = "/sys/class/i2c-dev/i2c-1"
|
||||
# USING THE BASE DIRECTORY FOR SPI AS THE DEVICE NUMBER CHANGES ON LOAD/UNLOAD
|
||||
SPI2SYSFSPATH = "/sys/class/spi_master/"
|
||||
|
||||
# LOADED VARIABLES
|
||||
# DO NOT MODIFY BY HAND WHEN USING
|
||||
# AS IT COULD BREAK FUNCTIONALITY
|
||||
_LOADED = {
|
||||
"I2C1" : False,
|
||||
"SPI2" : False,
|
||||
"PWM0" : False,
|
||||
"CUST" : False
|
||||
}
|
||||
|
||||
_OVERLAYS = {
|
||||
"I2C1" : "chip-i2c1.dtbo",
|
||||
"SPI2" : "chip-spi2.dtbo",
|
||||
"PWM0" : "chip-pwm0.dtbo",
|
||||
"CUST" : ""
|
||||
}
|
||||
|
||||
_FOLDERS = {
|
||||
"I2C1" : "chip-i2c",
|
||||
"SPI2" : "chip-spi",
|
||||
"PWM0" : "chip-pwm",
|
||||
"CUST" : "chip-cust"
|
||||
}
|
||||
|
||||
def enable_debug():
|
||||
global DEBUG
|
||||
DEBUG = True
|
||||
|
||||
def get_i2c_loaded():
|
||||
"""
|
||||
get_i2c_loaded - Returns True/False based upon if the i2c-1 Overlay is loaded
|
||||
"""
|
||||
global _LOADED
|
||||
return _LOADED["I2C1"]
|
||||
|
||||
def get_spi_loaded():
|
||||
"""
|
||||
get_spi_loaded - Returns True/False based upon if the spi2 Overlay is loaded
|
||||
"""
|
||||
global _LOADED
|
||||
return _LOADED["SPI2"]
|
||||
|
||||
def get_pwm_loaded():
|
||||
"""
|
||||
get_pwm_loaded - Returns True/False based upon if the pwm0 Overlay is loaded
|
||||
"""
|
||||
global _LOADED
|
||||
return _LOADED["PWM0"]
|
||||
|
||||
def get_custom_loaded():
|
||||
"""
|
||||
get_custom_loaded - Returns True/False based upon if a Custom Overlay is loaded
|
||||
"""
|
||||
global _LOADED
|
||||
return _LOADED["CUST"]
|
||||
|
||||
def _set_overlay_verify(name, overlay_path, config_path):
|
||||
"""
|
||||
_set_overlay_verify - Function to load the overlay and verify it was setup properly
|
||||
"""
|
||||
global DEBUG
|
||||
# VERIFY PATH IS NOT THERE
|
||||
if os.path.exists(config_path):
|
||||
print("Config path already exists! Not moving forward")
|
||||
print("config_path: {0}".format(config_path))
|
||||
return -1
|
||||
|
||||
# MAKE THE CONFIGURATION PATH
|
||||
os.makedirs(config_path)
|
||||
|
||||
# CAT THE OVERLAY INTO THE CONFIG FILESYSTEM
|
||||
with open(config_path + "/dtbo", 'wb') as outfile:
|
||||
with open(overlay_path, 'rb') as infile:
|
||||
shutil.copyfileobj(infile, outfile)
|
||||
|
||||
# SLEEP TO ENABLE THE KERNEL TO DO ITS JOB
|
||||
time.sleep(0.2)
|
||||
|
||||
# VERIFY
|
||||
if name == "CUST":
|
||||
# BLINDLY ACCEPT THAT IT LOADED
|
||||
return 0
|
||||
elif name == "PWM0":
|
||||
if os.path.exists(PWMSYSFSPATH):
|
||||
if DEBUG:
|
||||
print("PWM IS LOADED!")
|
||||
return 0
|
||||
else:
|
||||
if DEBUG:
|
||||
print("ERROR LOAIDNG PWM0")
|
||||
return 1
|
||||
elif name == "I2C1":
|
||||
if os.path.exists(I2C1SYSFSPATH):
|
||||
if DEBUG:
|
||||
print("I2C-1 IS LOADED!")
|
||||
return 0
|
||||
else:
|
||||
if DEBUG:
|
||||
print("ERROR LOADING I2C-1")
|
||||
return 1
|
||||
elif name == "SPI2":
|
||||
if os.listdir(SPI2SYSFSPATH) != "":
|
||||
if DEBUG:
|
||||
print("SPI2 IS LOADED!")
|
||||
return 0
|
||||
else:
|
||||
if DEBUG:
|
||||
print("ERROR LOADING SPI2")
|
||||
return 0
|
||||
|
||||
def load(overlay, path=""):
|
||||
"""
|
||||
load - Load a DTB Overlay
|
||||
|
||||
Inputs:
|
||||
overlay - Overlay Key: I2C1, SPI2, PWM0, CUST
|
||||
path - Full Path to where the custom overlay is stored
|
||||
|
||||
Returns:
|
||||
0 - Successful Load
|
||||
1 - Unsuccessful Load
|
||||
2 - Overlay was previously set
|
||||
"""
|
||||
global DEBUG
|
||||
global _LOADED
|
||||
if DEBUG:
|
||||
print("LOAD OVERLAY: {0} @ {1}".format(overlay,path))
|
||||
# SEE IF OUR OVERLAY NAME IS IN THE KEYS
|
||||
if overlay.upper() in _OVERLAYS.keys():
|
||||
cpath = OVERLAYCONFIGPATH + "/" + _FOLDERS[overlay.upper()]
|
||||
if DEBUG:
|
||||
print("VALID OVERLAY")
|
||||
print("CONFIG PATH: {0}".format(cpath))
|
||||
# CHECK TO SEE IF WE HAVE A PATH FOR CUSTOM OVERLAY
|
||||
if overlay.upper() == "CUST" and path == "":
|
||||
raise ValueError("Path must be specified for Custom Overlay Choice")
|
||||
elif overlay.upper() == "CUST" and _LOADED[overlay.upper()]:
|
||||
print("Custom Overlay already loaded")
|
||||
return 2
|
||||
elif overlay.upper() == "CUST" and not os.path.exists(path):
|
||||
print("Custom Overlay path does not exist")
|
||||
return 1
|
||||
|
||||
# SET UP THE OVERLAY PATH FOR OUR USE
|
||||
if overlay.upper() != "CUST":
|
||||
opath = OVERLAYINSTALLPATH + "/" + _OVERLAYS[overlay.upper()]
|
||||
else:
|
||||
opath = path
|
||||
if DEBUG:
|
||||
print("OVERLAY PATH: {0}".format(opath))
|
||||
|
||||
if overlay.upper() == "PWM0" and _LOADED[overlay.upper()]:
|
||||
print("PWM0 Overlay already loaded")
|
||||
return 2
|
||||
|
||||
if overlay.upper() == "I2C1" and _LOADED[overlay.upper()]:
|
||||
print("I2C1 Overlay already loaded")
|
||||
return 2
|
||||
|
||||
if overlay.upper() == "SPI2" and _LOADED[overlay.upper()]:
|
||||
print("SPI2 Overlay already loaded")
|
||||
return 2
|
||||
|
||||
# LOAD THE OVERLAY
|
||||
errc = _set_overlay_verify(overlay.upper(), opath, cpath)
|
||||
if DEBUG:
|
||||
print("_SET_OVERLAY_VERIFY ERRC: {0}".format(errc))
|
||||
if errc == 0:
|
||||
_LOADED[overlay.upper()] = True
|
||||
|
||||
else:
|
||||
raise ValueError("Invalid Overlay name specified! Choose between: I2C1, SPI2, PWM0, CUST")
|
||||
|
||||
def unload(overlay):
|
||||
global DEBUG
|
||||
global _LOADED
|
||||
if DEBUG:
|
||||
print("UNLOAD OVERLAY: {0}".format(overlay))
|
||||
# SEE IF OUR OVERLAY NAME IS IN THE KEYS
|
||||
if overlay.upper() in _OVERLAYS.keys():
|
||||
# BRUTE FORCE REMOVE AS THE DIRECTORY CONTAINS FILES
|
||||
os.system('rmdir \"{}\"'.format(OVERLAYCONFIGPATH + "/" + _FOLDERS[overlay.upper()]))
|
||||
_LOADED[overlay.upper()] = False
|
||||
else:
|
||||
raise ValueError("Invalid Overlay name specified! Choose between: I2C1, SPI2, PWM0, CUST")
|
||||
|
||||
|
5
MANIFEST.in
Normal file
5
MANIFEST.in
Normal file
@ -0,0 +1,5 @@
|
||||
include distribute_setup.py
|
||||
include README.rst
|
||||
include CHANGELOG.rst
|
||||
recursive-include source *.h
|
||||
recursive-include overlays *.dts *.py
|
62
README.rst
62
README.rst
@ -2,11 +2,17 @@ CHIP_IO
|
||||
============================
|
||||
A CHIP GPIO library
|
||||
|
||||
NOTE: Now requires the custom DTC to install the library
|
||||
|
||||
Manual::
|
||||
|
||||
sudo ntpdate pool.ntp.org
|
||||
sudo apt-get update
|
||||
sudo apt-get install git build-essential python-dev python-pip -y
|
||||
sudo apt-get install git build-essential python-dev python-pip flex bison -y
|
||||
git clone https://github.com/atenart/dtc
|
||||
cd dtc
|
||||
make
|
||||
sudo make install PREFIX=/usr
|
||||
cd ..
|
||||
git clone git://github.com/xtacocorex/CHIP_IO.git
|
||||
cd CHIP_IO
|
||||
sudo python setup.py install
|
||||
@ -17,7 +23,7 @@ Manual::
|
||||
|
||||
Using the library is very similar to the excellent RPi.GPIO library used on the Raspberry Pi. Below are some examples.
|
||||
|
||||
All scripts that require GPIO and PWM (HW and/or SW) access need to be run with super user permissions!
|
||||
All scripts that require GPIO, PWM (HW and/or SW), and Overlay Manager need to be run with super user permissions!
|
||||
|
||||
**Allowable Pin Names for the Library**
|
||||
|
||||
@ -208,22 +214,24 @@ Hardware PWM requires a DTB Overlay loaded on the CHIP to allow the kernel to kn
|
||||
|
||||
**SOFTPWM**::
|
||||
|
||||
import CHIP_IO.SOFTPWM as PWM
|
||||
#PWM.start(channel, duty, freq=2000, polarity=0)
|
||||
import CHIP_IO.SOFTPWM as SPWM
|
||||
#SPWM.start(channel, duty, freq=2000, polarity=0)
|
||||
#duty values are valid 0 (off) to 100 (on)
|
||||
#you can choose any pin
|
||||
PWM.start("XIO-P7", 50)
|
||||
PWM.set_duty_cycle("XIO-P7", 25.5)
|
||||
PWM.set_frequency("XIO-P7", 10)
|
||||
SPWM.start("XIO-P7", 50)
|
||||
SPWM.set_duty_cycle("XIO-P7", 25.5)
|
||||
SPWM.set_frequency("XIO-P7", 10)
|
||||
|
||||
PWM.stop("XIO-P7")
|
||||
PWM.cleanup()
|
||||
SPWM.stop("XIO-P7")
|
||||
SPWM.cleanup()
|
||||
|
||||
#set polarity to 1 on start:
|
||||
PWM.start("XIO-P7", 50, 2000, 1)
|
||||
SPWM.start("XIO-P7", 50, 2000, 1)
|
||||
|
||||
Use SOFTPWM at low speeds (hundreds of Hz) for the best results. Do not use for anything that needs high precision or reliability.
|
||||
|
||||
If using SOFTPWM and PWM at the same time, import CHIP_IO.SOFTPWM as SPWM or something different than PWM as to not confuse the library.
|
||||
|
||||
**ADC**::
|
||||
|
||||
Not Implemented yet
|
||||
@ -232,6 +240,38 @@ Use SOFTPWM at low speeds (hundreds of Hz) for the best results. Do not use for
|
||||
|
||||
SPI requires a DTB Overlay to access. CHIP_IO does not contain any SPI specific code as the Python spidev module works when it can see the SPI bus.
|
||||
|
||||
**Overlay Manager**::
|
||||
|
||||
The Overlay Manager enables you to quickly load simple Device Tree Overlays. The options for loading are:
|
||||
PWM0, SPI2, I2C1, CUST
|
||||
|
||||
Only one of each type of overlay can be loaded at a time, but all three options can be loaded simultaneously. So you can have SPI2 and I2C1 without PWM0, but you cannot have SPI2 loaded twice.
|
||||
|
||||
import CHIP_IO.OverlayManager as OM
|
||||
# The enable_debug() function turns on debug printing
|
||||
#OM.enable_debug()
|
||||
# To load an overlay, feed in the name to load()
|
||||
OM.load("PWM0")
|
||||
# To verify the overlay was properly loaded, the get_ functions return booleans
|
||||
OM.get_pwm_loaded()
|
||||
OM.get_i2c_loaded()
|
||||
OM.get_spi_loaded()
|
||||
# To unload an overlay, feed in the name to unload()
|
||||
OM.unload("PWM0")
|
||||
|
||||
To use a custom overlay, you must build and compile it properly per the DIP Docs: http://docs.getchip.com/dip.html#development-by-example
|
||||
There is no verification that the Custom Overlay is setup properly, it's fire and forget
|
||||
|
||||
import CHIP_IO.OverlayManager as OM
|
||||
# The full path to the dtbo file needs to be specified
|
||||
OM.load("CUST","/home/chip/projects/myfunproject/overlays/mycustomoverlay.dtbo")
|
||||
# You can check for loading like above, but it's really just there for sameness
|
||||
OM.get_custom_loaded()
|
||||
# To unload, just call unload()
|
||||
OM.unload("CUST")
|
||||
|
||||
Note that this requires the 4.4 kernel with the CONFIG_OF_CONFIGFS option enabled in the kernel config.
|
||||
|
||||
**Running tests**
|
||||
|
||||
Install py.test to run the tests. You'll also need the python compiler package for py.test.::
|
||||
|
0
overlays/__init__.py
Normal file
0
overlays/__init__.py
Normal file
24
overlays/builder.py
Normal file
24
overlays/builder.py
Normal file
@ -0,0 +1,24 @@
|
||||
from subprocess import call
|
||||
import os
|
||||
import shutil
|
||||
import glob
|
||||
|
||||
def compile():
|
||||
print("Compiling DTS Files")
|
||||
call(["dtc", "-O", "dtb", "-o", "overlays/chip-spi2.dtbo", "-b", "o", "-@", "overlays/chip-spi2.dts"])
|
||||
call(["dtc", "-O", "dtb", "-o", "overlays/chip-i2c1.dtbo", "-b", "o", "-@", "overlays/chip-i2c1.dts"])
|
||||
call(["dtc", "-O", "dtb", "-o", "overlays/chip-pwm0.dtbo", "-b", "o", "-@", "overlays/chip-pwm0.dts"])
|
||||
|
||||
def copy():
|
||||
print("Checking for DTBO Install Path")
|
||||
if not os.path.exists("/lib/firmware/chip_io/"):
|
||||
print("Path not found, creating /lib/firmware/chip_io/")
|
||||
os.makedirs("/lib/firmware/chip_io/")
|
||||
print("Removing old DTBO files (if applicable)")
|
||||
for fl in glob.glob("/lib/firmware/chip_io/chip-*-.dtbo"):
|
||||
os.remove(fl)
|
||||
print("Moving DTBO files to /lib/firmware/chip_io/")
|
||||
shutil.move("overlays/chip-spi2.dtbo", "/lib/firmware/chip_io/chip-spi2.dtbo")
|
||||
shutil.move("overlays/chip-i2c1.dtbo", "/lib/firmware/chip_io/chip-i2c1.dtbo")
|
||||
shutil.move("overlays/chip-pwm0.dtbo", "/lib/firmware/chip_io/chip-pwm0.dtbo")
|
||||
|
72
overlays/chip-i2c1.dts
Normal file
72
overlays/chip-i2c1.dts
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2016 Free Electrons
|
||||
* Copyright 2016 NextThing Co
|
||||
*
|
||||
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "nextthing,chip", "allwinner,sun5i-r8";
|
||||
|
||||
fragment@0 {
|
||||
target-path = "/aliases";
|
||||
__overlay__ {
|
||||
i2c1 = "/soc@01c00000/i2c@01c2b000";
|
||||
};
|
||||
};
|
||||
|
||||
/* Enable the I2C1 bus and the keyboard */
|
||||
fragment@1 {
|
||||
target = <&i2c1>;
|
||||
|
||||
__overlay__ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2c1_pins_a>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
61
overlays/chip-pwm0.dts
Normal file
61
overlays/chip-pwm0.dts
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2016 Free Electrons
|
||||
* Copyright 2016 NextThing Co
|
||||
*
|
||||
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "nextthing,chip", "allwinner,sun5i-r8";
|
||||
|
||||
/* Enable the PWM */
|
||||
fragment@0 {
|
||||
target = <&pwm>;
|
||||
|
||||
__overlay__ {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pwm0_pins>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
93
overlays/chip-spi2.dts
Normal file
93
overlays/chip-spi2.dts
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2016, Robert Wolterman
|
||||
* This file is an amalgamation of stuff from Kolja Windeler, Maxime Ripard, and Renzo.
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "nextthing,chip", "allwinner,sun5i-r8";
|
||||
|
||||
/* activate the gpio for interrupt */
|
||||
fragment@0 {
|
||||
target-path = <&pio>;
|
||||
|
||||
__overlay__ {
|
||||
chip_spi2_pins: spi2@0 {
|
||||
allwinner,pins = "PE1", "PE2", "PE3";
|
||||
allwinner,function = "spi2";
|
||||
allwinner,drive = "0"; //<SUN4I_PINCTRL_10_MA>;
|
||||
allwinner,pull = "0"; //<SUN4I_PINCTRL_NO_PULL>;
|
||||
};
|
||||
|
||||
chip_spi2_cs0_pins: spi2_cs0@0 {
|
||||
allwinner,pins = "PE0";
|
||||
allwinner,function = "spi2";
|
||||
allwinner,drive = "0"; //<SUN4I_PINCTRL_10_MA>;
|
||||
allwinner,pull = "0"; //<SUN4I_PINCTRL_NO_PULL>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Enable our SPI device, with an spidev device connected
|
||||
* to it
|
||||
*/
|
||||
fragment@1 {
|
||||
target = <&spi2>;
|
||||
|
||||
__overlay__ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&chip_spi2_pins>, <&chip_spi2_cs0_pins>;
|
||||
status = "okay";
|
||||
|
||||
spi2@0 {
|
||||
compatible = "rohm,dh2228fv";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <24000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
2
setup.py
2
setup.py
@ -20,7 +20,7 @@ classifiers = ['Development Status :: 3 - Alpha',
|
||||
'Topic :: System :: Hardware']
|
||||
|
||||
setup(name = 'CHIP_IO',
|
||||
version = '0.1.0',
|
||||
version = '0.2.1',
|
||||
author = 'Robert Wolterman',
|
||||
author_email = 'robert.wolterman@gmail.com',
|
||||
description = 'A module to control CHIP IO channels',
|
||||
|
@ -101,7 +101,7 @@ int softpwm_set_frequency(const char *key, float freq) {
|
||||
pwm->params.freq = freq;
|
||||
pthread_mutex_unlock(pwm->params_lock);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int softpwm_set_polarity(const char *key, int polarity) {
|
||||
@ -274,11 +274,13 @@ int softpwm_start(const char *key, float duty, float freq, int polarity)
|
||||
pwm = pwm->next;
|
||||
pwm->next = new_pwm;
|
||||
}
|
||||
pthread_mutex_unlock(new_params_lock);
|
||||
|
||||
ASSRT(softpwm_set_duty_cycle(new_pwm->key, duty) == 0);
|
||||
ASSRT(softpwm_set_frequency(new_pwm->key, freq) == 0);
|
||||
ASSRT(softpwm_set_polarity(new_pwm->key, polarity) == 0);
|
||||
|
||||
pthread_mutex_lock(new_params_lock);
|
||||
// create thread for pwm
|
||||
ret = pthread_create(&new_thread, NULL, softpwm_thread_toggle, (void *)new_pwm);
|
||||
ASSRT(ret == 0);
|
||||
|
@ -76,6 +76,6 @@ void define_constants(PyObject *module)
|
||||
both_edge = Py_BuildValue("i", BOTH_EDGE);
|
||||
PyModule_AddObject(module, "BOTH", both_edge);
|
||||
|
||||
version = Py_BuildValue("s", "0.1.0");
|
||||
version = Py_BuildValue("s", "0.2.1");
|
||||
PyModule_AddObject(module, "VERSION", version);
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ struct fdx *fd_list = NULL;
|
||||
// event callbacks
|
||||
struct callback
|
||||
{
|
||||
int fde;
|
||||
int gpio;
|
||||
int edge;
|
||||
void (*func)(int gpio);
|
||||
@ -159,7 +160,6 @@ void close_value_fd(int gpio)
|
||||
}
|
||||
} /* close_value_fd */
|
||||
|
||||
|
||||
int fd_lookup(int gpio)
|
||||
{
|
||||
struct fdx *f = fd_list;
|
||||
@ -173,6 +173,18 @@ int fd_lookup(int gpio)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fde_lookup(int gpio)
|
||||
{
|
||||
struct callback *cb = callbacks;
|
||||
while (cb != NULL)
|
||||
{
|
||||
if (cb->gpio == gpio)
|
||||
return cb->fde;
|
||||
cb = cb->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_fd_list(int gpio, int fd)
|
||||
{
|
||||
@ -213,6 +225,23 @@ int open_value_file(int gpio)
|
||||
return fd;
|
||||
} /* open_value_file */
|
||||
|
||||
int open_edge_file(int gpio)
|
||||
{
|
||||
int fd;
|
||||
char filename[MAX_FILENAME];
|
||||
|
||||
// create file descriptor of value file
|
||||
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename);
|
||||
|
||||
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "open_edge_file: could not open '%s' (%s)", filename, strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
} /* open_edge_file */
|
||||
|
||||
int gpio_unexport(int gpio)
|
||||
{
|
||||
@ -422,59 +451,44 @@ int gpio_get_value(int gpio, unsigned int *value)
|
||||
}
|
||||
|
||||
int gpio_set_edge(int gpio, unsigned int edge)
|
||||
{
|
||||
int fd;
|
||||
char filename[MAX_FILENAME];
|
||||
|
||||
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename);
|
||||
|
||||
if ((fd = open(filename, O_WRONLY)) < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "gpio_set_edge: could not open '%s' (%s)", filename, strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t s = write(fd, stredge[edge], strlen(stredge[edge]) + 1);
|
||||
if (s < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "gpio_set_edge: could not write '%s' to %s (%s)", stredge[edge], filename, strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int open_edge_file(int gpio)
|
||||
{
|
||||
int fd;
|
||||
char filename[MAX_FILENAME];
|
||||
|
||||
// create file descriptor of value file
|
||||
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/edge", gpio); BUF2SMALL(filename);
|
||||
|
||||
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
|
||||
if ((fd = open(filename, O_WRONLY)) < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "open_edge_file: could not open '%s' (%s)", filename, strerror(errno));
|
||||
snprintf(err, sizeof(err), "gpio_set_edge: could not open '%s' (%s)", filename, strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
} /* open_edge_file */
|
||||
ssize_t s = write(fd, stredge[edge], strlen(stredge[edge]) + 1);
|
||||
if (s < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "gpio_set_edge: could not write '%s' to %s (%s)", stredge[edge], filename, strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_get_edge(int gpio)
|
||||
{
|
||||
int fd;
|
||||
int fd = fde_lookup(gpio);
|
||||
int rtnedge = -1;
|
||||
|
||||
if ((fd = open_edge_file(gpio)) == -1) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "gpio_get_value: could not open GPIO %d edge file", gpio);
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
if (!fd)
|
||||
{
|
||||
if ((fd = open_edge_file(gpio)) == -1) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "gpio_get_value: could not open GPIO %d edge file", gpio);
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||
@ -542,6 +556,7 @@ int add_edge_callback(int gpio, int edge, void (*func)(int gpio))
|
||||
|
||||
new_cb = malloc(sizeof(struct callback)); ASSRT(new_cb != NULL);
|
||||
|
||||
new_cb->fde = open_edge_file(gpio);
|
||||
new_cb->gpio = gpio;
|
||||
new_cb->edge = edge;
|
||||
new_cb->func = func;
|
||||
@ -605,6 +620,7 @@ void remove_callbacks(int gpio)
|
||||
{
|
||||
if (cb->gpio == gpio)
|
||||
{
|
||||
close(cb->fde);
|
||||
if (prev == NULL)
|
||||
callbacks = cb->next;
|
||||
else
|
||||
|
@ -61,14 +61,15 @@ int gpio_set_direction(int gpio, unsigned int in_flag);
|
||||
int gpio_get_direction(int gpio, unsigned int *value);
|
||||
int gpio_set_value(int gpio, unsigned int value);
|
||||
int gpio_get_value(int gpio, unsigned int *value);
|
||||
int fd_lookup(int gpio);
|
||||
int open_value_file(int gpio);
|
||||
|
||||
int gpio_set_edge(int gpio, unsigned int edge);
|
||||
int fde_lookup(int gpio);
|
||||
int open_edge_file(int gpio);
|
||||
int gpio_set_edge(int gpio, unsigned int edge);
|
||||
int gpio_get_edge(int gpio);
|
||||
|
||||
int add_edge_detect(int gpio, unsigned int edge);
|
||||
void remove_edge_detect(int gpio);
|
||||
//int add_edge_callback(int gpio, void (*func)(int gpio));
|
||||
int add_edge_callback(int gpio, int edge, void (*func)(int gpio));
|
||||
int event_detected(int gpio);
|
||||
int gpio_event_add(int gpio);
|
||||
|
@ -16,7 +16,7 @@ loopfunction_exit = False
|
||||
|
||||
def loopfunction():
|
||||
print("LOOP FUNCTION START")
|
||||
for i in xrange(6):
|
||||
for i in xrange(4):
|
||||
if loopfunction_exit:
|
||||
break
|
||||
if i % 2:
|
||||
@ -50,7 +50,7 @@ else:
|
||||
print(" Able to use alternate names for GPIO")
|
||||
GPIO.cleanup()
|
||||
|
||||
GPIO.setup("U14_15", GPIO.IN) # XIO-P0
|
||||
GPIO.setup("U14_15", GPIO.IN) # XIO-P2
|
||||
GPIO.setup("CSID0", GPIO.OUT, initial=GPIO.LOW)
|
||||
if (GPIO.input("XIO-P2") != GPIO.LOW):
|
||||
print(" A low output on CSI0 does not lead to a low input on XIO-P2.")
|
||||
@ -98,6 +98,8 @@ GPIO.remove_event_detect("AP-EINT3")
|
||||
# ==============================================
|
||||
# EDGE DETECTION - EXPANDED GPIO
|
||||
print("\nSETTING UP FALLING EDGE DETECTION ON XIO-P2")
|
||||
# WRITING CSID0 LOW FIRST AS THERE IS A DOUBLE HIT ON HIGH
|
||||
GPIO.output("CSID0", GPIO.LOW)
|
||||
GPIO.add_event_detect("XIO-P2", GPIO.FALLING, myfuncallback)
|
||||
|
||||
print("VERIFYING EDGE DETECT")
|
||||
@ -115,7 +117,29 @@ mystr = " num_callbacks = %d" % num_callbacks
|
||||
print(mystr)
|
||||
GPIO.remove_event_detect("XIO-P2")
|
||||
|
||||
print("\nWAIT FOR EDGE TESTING")
|
||||
print("\nSETTING UP RISING EDGE DETECTION ON XIO-P2")
|
||||
# WRITING CSID0 LOW FIRST AS THERE IS A DOUBLE HIT ON HIGH
|
||||
GPIO.output("CSID0", GPIO.LOW)
|
||||
num_callbacks = 0
|
||||
GPIO.add_event_detect("XIO-P2", GPIO.RISING, myfuncallback)
|
||||
print("WAITING FOR CALLBACKS ON XIO-P2")
|
||||
loopfunction()
|
||||
mystr = " num_callbacks = %d" % num_callbacks
|
||||
print(mystr)
|
||||
GPIO.remove_event_detect("XIO-P2")
|
||||
|
||||
print("\nSETTING UP BOTH EDGE DETECTION ON XIO-P2")
|
||||
# WRITING CSID0 LOW FIRST AS THERE IS A DOUBLE HIT ON HIGH
|
||||
GPIO.output("CSID0", GPIO.LOW)
|
||||
num_callbacks = 0
|
||||
GPIO.add_event_detect("XIO-P2", GPIO.BOTH, myfuncallback)
|
||||
print("WAITING FOR CALLBACKS ON XIO-P2")
|
||||
loopfunction()
|
||||
mystr = " num_callbacks = %d" % num_callbacks
|
||||
print(mystr)
|
||||
GPIO.remove_event_detect("XIO-P2")
|
||||
|
||||
print("\nWAIT FOR EDGE TESTING, SETUP FOR FALLING EDGE")
|
||||
print("PRESS CONTROL-C TO EXIT IF SCRIPT GETS STUCK")
|
||||
try:
|
||||
# WAIT FOR EDGE
|
||||
|
49
test/omtest.py
Executable file
49
test/omtest.py
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import CHIP_IO.OverlayManager as OM
|
||||
import os
|
||||
|
||||
# ENABLE DEBUG
|
||||
print("ENABLING OVERLAY MANAGER DEBUG")
|
||||
OM.enable_debug()
|
||||
|
||||
# **************** PWM *******************
|
||||
print("\nIS PWM ENABLED: {0}".format(OM.get_pwm_loaded()))
|
||||
OM.load("PWM0")
|
||||
print("IS PWM ENABLED: {0}".format(OM.get_pwm_loaded()))
|
||||
# VERIFY PWM0 EXISTS
|
||||
if os.path.exists('/sys/class/pwm/pwmchip0'):
|
||||
print("PWM DEVICE EXISTS")
|
||||
else:
|
||||
print("PWM DEVICE DID NOT LOAD PROPERLY")
|
||||
print("UNLOADING PWM0")
|
||||
OM.unload("PWM0")
|
||||
print("IS PWM ENABLED: {0}".format(OM.get_pwm_loaded()))
|
||||
|
||||
# **************** I2C-1 *******************
|
||||
print("\nIS I2C ENABLED: {0}".format(OM.get_i2c_loaded()))
|
||||
OM.load("I2C1")
|
||||
print("IS I2C ENABLED: {0}".format(OM.get_i2c_loaded()))
|
||||
# VERIFY I2C-1 EXISTS
|
||||
if os.path.exists('/sys/class/i2c-dev/i2c-1'):
|
||||
print("I2C1 DEVICE EXISTS")
|
||||
else:
|
||||
print("I2C1 DEVICE DID NOT LOAD PROPERLY")
|
||||
print("UNLOADING I2C1")
|
||||
OM.unload("I2C1")
|
||||
print("IS I2C ENABLED: {0}".format(OM.get_i2c_loaded()))
|
||||
|
||||
# **************** SPI2 *******************
|
||||
print("\nIS SPI ENABLED: {0}".format(OM.get_spi_loaded()))
|
||||
OM.load("SPI2")
|
||||
print("IS SPI ENABLED: {0}".format(OM.get_spi_loaded()))
|
||||
# VERIFY SPI2 EXISTS
|
||||
if os.listdir('/sys/class/spi_master') != "":
|
||||
print("SPI DEVICE EXISTS")
|
||||
else:
|
||||
print("SPI DEVICE DID NOT LOAD PROPERLY")
|
||||
print("UNLOADING SPI")
|
||||
OM.unload("SPI2")
|
||||
print("IS SPI ENABLED: {0}".format(OM.get_spi_loaded()))
|
||||
|
||||
|
59
test/spwmtest.py
Executable file
59
test/spwmtest.py
Executable file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import CHIP_IO.SOFTPWM as SPWM
|
||||
import CHIP_IO.GPIO as GPIO
|
||||
import time
|
||||
import datetime
|
||||
import threading
|
||||
|
||||
class SPWMReceiver(threading.Thread):
|
||||
def __init__(self,gpio,key,maxcount=20,sleeptime=0.5):
|
||||
self.gpio = gpio
|
||||
self.key = key
|
||||
self.counter = 0
|
||||
self.maxcount = maxcount
|
||||
self.sleeptime = sleeptime
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
print("SETTING UP RECEIVER GPIO")
|
||||
self.gpio.cleanup()
|
||||
self.gpio.setup(self.key, self.gpio.IN)
|
||||
print("STARTING RECEIVE LOOP")
|
||||
try:
|
||||
while self.counter < self.maxcount:
|
||||
pwmval = self.gpio.input(self.key)
|
||||
print("SPWM VALUE: {0} @ {1}".format(pwmval, datetime.datetime.now()))
|
||||
time.sleep(self.sleeptime)
|
||||
self.counter += 1
|
||||
except KeyboardInterrupt:
|
||||
self.gpio.cleanup(self.key)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# SETUP VARIABLES
|
||||
SPWMGPIO = "XIO-P7"
|
||||
RECEIVERGPIO = "CSID0"
|
||||
COUNT = 200
|
||||
SLEEPTIME = 0.01
|
||||
|
||||
# CLEANUP THE GPIO
|
||||
GPIO.cleanup()
|
||||
SPWM.cleanup()
|
||||
|
||||
# SETUP SOFTPWM
|
||||
SPWM.start(SPWMGPIO, 50, 1)
|
||||
SPWM.set_frequency(SPWMGPIO, 2)
|
||||
|
||||
# SETUP SOFTPWM RECEIVER
|
||||
rcvr = SPWMReceiver(GPIO, RECEIVERGPIO, COUNT, SLEEPTIME)
|
||||
rcvr.start()
|
||||
|
||||
time.sleep(COUNT*SLEEPTIME + 1)
|
||||
|
||||
# CLEANUP
|
||||
print("CLEANUP")
|
||||
SPWM.stop(SPWMGPIO)
|
||||
SPWM.cleanup()
|
||||
GPIO.cleanup()
|
||||
|
||||
|
@ -13,8 +13,8 @@ class TestPwmSetup:
|
||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||
|
||||
assert os.path.exists(pwm_test)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
assert int(duty) == 0
|
||||
assert int(period) == 500000
|
||||
PWM.cleanup()
|
||||
@ -25,12 +25,12 @@ class TestPwmSetup:
|
||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||
|
||||
assert os.path.exists(pwm_test)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
polarity = open(pwm_test + '/polarity').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
polarity = open(pwm_test + '/polarity').readline().strip()
|
||||
assert int(duty) == 0
|
||||
assert int(period) == 500000
|
||||
assert string(polarity) == "inverted"
|
||||
assert str(polarity) == "inverted"
|
||||
PWM.cleanup()
|
||||
|
||||
def test_start_pwm_with_polarity_default(self):
|
||||
@ -39,12 +39,12 @@ class TestPwmSetup:
|
||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||
|
||||
assert os.path.exists(pwm_test)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
polarity = open(pwm_test + '/polarity').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
polarity = open(pwm_test + '/polarity').readline().strip()
|
||||
assert int(duty) == 0
|
||||
assert int(period) == 500000
|
||||
assert string(polarity) == "normal"
|
||||
assert str(polarity) == "normal"
|
||||
PWM.cleanup()
|
||||
|
||||
def test_start_pwm_with_polarity_zero(self):
|
||||
@ -53,12 +53,12 @@ class TestPwmSetup:
|
||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||
|
||||
assert os.path.exists(pwm_test)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
polarity = open(pwm_test + '/polarity').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
polarity = open(pwm_test + '/polarity').readline().strip()
|
||||
assert int(duty) == 0
|
||||
assert int(period) == 500000
|
||||
assert string(polarity) == "normal"
|
||||
assert str(polarity) == "normal"
|
||||
PWM.cleanup()
|
||||
|
||||
def test_pwm_start_invalid_pwm_key(self):
|
||||
@ -113,14 +113,14 @@ class TestPwmSetup:
|
||||
pwm_test = '/sys/class/pwm/pwmchip0/pwm0'
|
||||
|
||||
assert os.path.exists(pwm_test)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
assert int(duty) == 0
|
||||
assert int(period) == 500000
|
||||
|
||||
PWM.set_duty_cycle("PWM0", 100)
|
||||
duty = open(pwm_test + '/duty_cycle').read()
|
||||
period = open(pwm_test + '/period').read()
|
||||
duty = open(pwm_test + '/duty_cycle').readline().strip()
|
||||
period = open(pwm_test + '/period').readline().strip()
|
||||
assert int(duty) == 500000
|
||||
assert int(period) == 500000
|
||||
PWM.cleanup()
|
||||
@ -180,6 +180,6 @@ class TestPwmSetup:
|
||||
#PWM.start("PWM0", 1)
|
||||
#PWM.stop("PWM0")
|
||||
#assert os.path.exists('/sys/class/gpio/gpio68')
|
||||
#direction = open('/sys/class/gpio/gpio68/direction').read()
|
||||
#direction = open('/sys/class/gpio/gpio68/direction').readline().strip()
|
||||
#assert direction == 'out\n'
|
||||
#PWM.cleanup()
|
||||
|
Reference in New Issue
Block a user