1
0
mirror of https://github.com/xtacocorex/CHIP_IO synced 2025-07-19 20:33:21 +00:00

Merge branch 'master' into hotfix/hwpwmfix

This commit is contained in:
Robert Wolterman
2016-12-30 17:16:17 +00:00
19 changed files with 543 additions and 143 deletions

View File

@ -1,3 +1,11 @@
0.2.3
----
* LRADC Support
* Added Utilities
- Enable/Disable the 1.8V Pin
- Change 1.8V Pin to output either 2.0V, 2.6V, or 3.3V
(Current limited to 50mA)
0.2.2
----
* Fixes for Issue #16

228
CHIP_IO/LRADC.py Normal file
View File

@ -0,0 +1,228 @@
# Copyright (c) 2016 Robert Wolterman
#
# 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.
import os
import time
# Global Variables
DEBUG = False
DEVICE_EXIST = True
# Default Sample Rate Variables
SAMPLE_RATE_32P25 = 32.25
SAMPLE_RATE_62O5 = 62.5
SAMPLE_RATE_125 = 125
SAMPLE_RATE_250 = 250
SAMPLE_RATES = []
# Scale Factor
SCALE_FACTOR = 31.25
# File Locations
LRADC_BASE_DEVICE_FILE = "/sys/bus/iio/devices/iio:device0"
AVAILABLE_SAMPLE_RATE_FILE = "/sampling_frequency_available"
SCALE_FACTOR_FILE = "/in_voltage_scale"
CURRENT_SAMPLE_RATE_FILE = "/in_voltage_sampling_frequency"
RAW_VOLTAGE_CHAN0_FILE = "/in_voltage0_raw"
RAW_VOLTAGE_CHAN1_FILE = "/in_voltage1_raw"
def enable_debug():
global DEBUG
DEBUG = True
def setup(rate=250):
# First we determine if the device exists
if not os.path.exists(LRADC_BASE_DEVICE_FILE):
global DEVICE_EXIST
DEVICE_EXIST = False
raise Exception("LRADC Device does not exist")
else:
# Set the Sample Rate
set_sample_rate(rate)
def get_device_exist():
return DEVICE_EXIST
def get_scale_factor():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the data from the file
f = open(LRADC_BASE_DEVICE_FILE+SCALE_FACTOR_FILE,"r")
dat = f.readline()
f.close()
# Set the Scale Factor
global SCALE_FACTOR
SCALE_FACTOR = float(dat.strip())
# Debug
if DEBUG:
print("Current LRADC Scaling Factor: {0}").format(SCALE_FACTOR)
return SCALE_FACTOR
def get_allowable_sample_rates():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the data from the file
f = open(LRADC_BASE_DEVICE_FILE+AVAILABLE_SAMPLE_RATE_FILE,"r")
dat = f.readline()
f.close()
global SAMPLE_RATES
tmp = dat.strip().split(" ")
for i in xrange(len(tmp)):
if "." in tmp[i]:
tmp[i] = float(tmp[i])
else:
tmp[i] = int(tmp[i])
SAMPLE_RATES = tmp
# Debug
if DEBUG:
print("Allowable Sampling Rates:")
for rate in SAMPLE_RATES:
print("{0}").format(rate)
return tuple(SAMPLE_RATES)
def set_sample_rate(rate):
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Debug
if DEBUG:
print("Setting Sample Rate to: {0}").format(rate)
# Check to see if the rates were gathered already
global SAMPLE_RATES
if SAMPLE_RATES == []:
tmp = get_allowable_sample_rates()
# Range check the input rate
if rate not in SAMPLE_RATES:
raise ValueError("Input Rate an Acceptable Value")
# Write the rate
f = open(LRADC_BASE_DEVICE_FILE+CURRENT_SAMPLE_RATE_FILE,"w")
mystr = "%.2f" % rate
f.write(mystr)
f.close()
# Verify write went well
crate = get_sample_rate()
if crate != rate:
raise Exception("Unable to write new Sampling Rate")
def get_sample_rate():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the data from the file
f = open(LRADC_BASE_DEVICE_FILE+CURRENT_SAMPLE_RATE_FILE,"r")
dat = f.read()
f.close()
dat = dat.strip()
if "." in dat:
dat = float(dat)
else:
dat = int(dat)
# Debug
if DEBUG:
print("Current Sampling Rate: {0}").format(dat)
return dat
def get_chan0_raw():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the data from the file
f = open(LRADC_BASE_DEVICE_FILE+RAW_VOLTAGE_CHAN0_FILE,"r")
dat = f.readline()
f.close()
dat = float(dat.strip())
# Debug
if DEBUG:
print("CHAN0 RAW: {0}").format(dat)
return dat
def get_chan1_raw():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the data from the file
f = open(LRADC_BASE_DEVICE_FILE+RAW_VOLTAGE_CHAN1_FILE,"r")
dat = f.readline()
f.close()
dat = float(dat.strip())
# Debug
if DEBUG:
print("CHAN1 RAW: {0}").format(dat)
return dat
def get_chan0():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the raw data first
dat = get_chan0_raw()
# Apply scale factor
dat *= SCALE_FACTOR
# Debug
if DEBUG:
print("CHAN0: {0}").format(dat)
return dat
def get_chan1():
# If we do not have a device, lets throw an exception
if not DEVICE_EXIST:
raise Exception("LRADC Device does not exist")
# Get the raw data first
dat = get_chan1_raw()
# Apply scale factor
dat *= SCALE_FACTOR
# Debug
if DEBUG:
print("CHAN1: {0}").format(dat)
return dat

View File

@ -1,3 +1,22 @@
# Copyright (c) 2016 Robert Wolterman
#
# 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.
import os
import shutil
import time
@ -79,7 +98,7 @@ def _set_overlay_verify(name, overlay_path, 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)
@ -198,5 +217,5 @@ def unload(overlay):
_LOADED[overlay.upper()] = False
else:
raise ValueError("Invalid Overlay name specified! Choose between: I2C1, SPI2, PWM0, CUST")

66
CHIP_IO/Utilities.py Normal file
View File

@ -0,0 +1,66 @@
# Copyright (c) 2016 Robert Wolterman
#
# 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.
# CHIP_IO Utilities
# Random functions to enable fun stuff on the CHIP!
# Credit goes to nonokuono (https://bbs.nextthing.co/users/nonokunono)
# for gathering the i2cset commands from the AXP-209 datasheet for 2.0, 2.6, and 3.3V output
# and for figuring out the ADC setup on the AXP-209
import subprocess
# Set the 1.8V-pin on the CHIP U13-header to given voltage
# Return False on error
def set_1v8_pin_voltage(voltage):
if not isinstance(voltage, int) and not isinstance(voltage, float):
return False
if voltage < 1.8 or voltage > 3.3:
return False
voltage=round((voltage - 1.8) / 0.1) << 4
if subprocess.call(["/usr/sbin/i2cset", "-f", "-y" ,"0", "0x34", "0x90", "0x03"]):
return False
if subprocess.call(["/usr/sbin/i2cset", "-f", "-y", "0", "0x34", "0x91", str(voltage)]):
return False
return True
# Get the voltage the 1.8V-pin on the CHIP U13-header has been configured as
# Return False on error
def get_1v8_pin_voltage():
p=subprocess.Popen(["/usr/sbin/i2cget", "-f", "-y", "0", "0x34", "0x90"], stdout=subprocess.PIPE)
output=p.communicate()[0].decode("utf-8").strip()
#Not configured as an output
if output != "0x03":
return False
p=subprocess.Popen(["/usr/sbin/i2cget", "-f", "-y", "0", "0x34", "0x91"], stdout=subprocess.PIPE)
output=p.communicate()[0].decode("utf-8").strip()
voltage=round((int(output, 16) >> 4) * 0.1 + 1.8, 1)
return voltage
# Enable 1.8V Pin on CHIP U13 Header
def enable_1v8_pin():
set_1v8_pin_voltage(1.8)
# Disable 1.8V Pin on CHIP U13 Header
def disable_1v8_pin():
# CANNOT USE I2C LIB AS WE NEED TO FORCE THE COMMAND DUE TO THE KERNEL OWNING THE DEVICE
# First we have to write 0x05 to AXP-209 Register 0x91
subprocess.call('/usr/sbin/i2cset -f -y 0 0x34 0x91 0x05', shell=True)
# Then we have to write 0x07 to AXP-209 Register 0x90
subprocess.call('/usr/sbin/i2cset -f -y 0 0x34 0x90 0x07', shell=True)

View File

@ -1,8 +1,8 @@
time:
/usr/bin/ntpdate -b -s -u pool.ntp.org
package: clean
python setup.py sdist
publish: clean
python setup.py sdist upload
publish: package
twine upload dist/*
clean:
rm -rf CHIP_IO.* build dist

View File

@ -6,6 +6,8 @@ NOTE: Now requires the custom DTC to install the library
Manual::
For Python2.7::
sudo apt-get update
sudo apt-get install git build-essential python-dev python-pip flex bison -y
git clone https://github.com/atenart/dtc
@ -19,6 +21,21 @@ Manual::
cd ..
sudo rm -rf CHIP_IO
For Python3::
sudo apt-get update
sudo apt-get install git build-essential python3-dev python3-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 python3 setup.py install
cd ..
sudo rm -rf CHIP_IO
**Usage**
Using the library is very similar to the excellent RPi.GPIO library used on the Raspberry Pi. Below are some examples.
@ -170,16 +187,16 @@ Inputs work similarly to outputs.::
Polling inputs::
if GPIO.input("CSID0"):
print("HIGH")
print("HIGH")
else:
print("LOW")
print("LOW")
Waiting for an edge (GPIO.RISING, GPIO.FALLING, or GPIO.BOTH::
This only works for the AP-EINT1, AP-EINT3, and XPO Pins on the CHIP
GPIO.wait_for_edge(channel, GPIO.RISING)
This only works for the AP-EINT1, AP-EINT3, and XPO Pins on the CHIP
Detecting events::
GPIO.setup("XIO-P0", GPIO.IN)
@ -187,7 +204,7 @@ Detecting events::
#your amazing code here
#detect wherever:
if GPIO.event_detected("XIO-P0"):
print "event detected!"
print "event detected!"
**GPIO Cleanup**
@ -198,18 +215,17 @@ To clean up the GPIO when done, do the following::
**PWM**::
Hardware PWM requires a DTB Overlay loaded on the CHIP to allow the kernel to know there is a PWM device available to use.
::
import CHIP_IO.PWM as PWM
#PWM.start(channel, duty, freq=2000, polarity=0)
#duty values are valid 0 (off) to 100 (on)
PWM.start("PWM0", 50)
PWM.set_duty_cycle("PWM0", 25.5)
PWM.set_frequency("PWM0", 10)
# To stop PWM
PWM.stop("PWM0")
PWM.cleanup()
#set polarity to 1 on start:
#For specific polarity: this example sets polarity to 1 on start:
PWM.start("PWM0", 50, 2000, 1)
**SOFTPWM**::
@ -221,20 +237,44 @@ Hardware PWM requires a DTB Overlay loaded on the CHIP to allow the kernel to kn
SPWM.start("XIO-P7", 50)
SPWM.set_duty_cycle("XIO-P7", 25.5)
SPWM.set_frequency("XIO-P7", 10)
# To Stop SPWM
SPWM.stop("XIO-P7")
SPWM.cleanup()
#set polarity to 1 on start:
#For specific polarity: this example sets polarity to 1 on start:
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**::
**LRADC**::
Not Implemented yet
The LRADC was enabled in the 4.4.13-ntc-mlc. This is a 6 bit ADC that is 2 Volt tolerant.
Sample code below details how to talk to the LRADC.
import CHIP_IO.LRADC as ADC
# Enable Debug
ADC.enable_debug()
# Check to see if the LRADC Device exists
# Returns True/False
ADC.get_device_exists()
# Setup the LRADC
# Specify a sampling rate if needed
ADC.setup(rate)
# Get the Scale Factor
factor = ADC.get_scale_factor()
# Get the allowable Sampling Rates
sampleratestuple = ADC.get_allowable_sample_rates()
# Set the sampling rate
ADC.set_sample_rate(rate)
# Get the current sampling rate
currentrate = ADC.get_sample_rate()
# Get the Raw Channel 0 or 1 data
raw = ADC.get_chan0_raw()
raw = ADC.get_chan1_raw()
# Get the factored ADC Channel data
fulldata = ADC.get_chan0()
fulldata = ADC.get_chan1()
**SPI**::
@ -246,7 +286,7 @@ The Overlay Manager enables you to quickly load simple Device Tree Overlays. Th
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()
@ -261,7 +301,7 @@ Only one of each type of overlay can be loaded at a time, but all three options
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")
@ -270,7 +310,27 @@ There is no verification that the Custom Overlay is setup properly, it's fire an
# 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.
**OverlayManager requires a 4.4 kernel with the CONFIG_OF_CONFIGFS option enabled in the kernel config.**
**Utilties**::
CHIP_IO now supports the ability to enable and disable the 1.8V port on U13. This voltage rail isn't enabled during boot.
To use the utilities, here is sample code::
import CHIP_IO.Utilities as UT
# Enable 1.8V Output
UT.enable_1v8_pin()
# Set 2.0V Output
UT.set_1v8_pin_voltage(2.0)
# Set 2.6V Output
UT.set_1v8_pin_voltage(2.6)
# Set 3.3V Output
UT.set_1v8_pin_voltage(3.3)
# Disable 1.8V Output
UT.disable_1v8_pin()
# Get currently-configured voltage (returns False if the pin is not enabled as output)
UT.get_1v8_pin_voltage()
**Running tests**

View File

@ -2,6 +2,7 @@ from subprocess import call
import os
import shutil
import glob
import sys
def compile():
print("Compiling DTS Files")
@ -10,15 +11,16 @@ def compile():
call(["dtc", "-O", "dtb", "-o", "overlays/chip-pwm0.dtbo", "-b", "o", "-@", "overlays/chip-pwm0.dts"])
def copy():
target_dir = os.environ.get('TARGET_DIR', '')
overlay_path = target_dir + "/lib/firmware/chip_io"
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/")
if not os.path.exists(overlay_path):
print("Path not found, creating "+overlay_path)
os.makedirs(overlay_path)
print("Removing old DTBO files (if applicable)")
for fl in glob.glob("/lib/firmware/chip_io/chip-*-.dtbo"):
for fl in glob.glob(overlay_path+"/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")
print("Moving DTBO files to "+overlay_path)
shutil.move("overlays/chip-spi2.dtbo", overlay_path+"/chip-spi2.dtbo")
shutil.move("overlays/chip-i2c1.dtbo", overlay_path+"/chip-i2c1.dtbo")
shutil.move("overlays/chip-pwm0.dtbo", overlay_path+"/chip-pwm0.dtbo")

View File

@ -20,7 +20,7 @@ classifiers = ['Development Status :: 3 - Alpha',
'Topic :: System :: Hardware']
setup(name = 'CHIP_IO',
version = '0.2.2',
version = '0.2.3',
author = 'Robert Wolterman',
author_email = 'robert.wolterman@gmail.com',
description = 'A module to control CHIP IO channels',

View File

@ -41,7 +41,6 @@ SOFTWARE.
#include "c_pwm.h"
#include "common.h"
#include "event_gpio.h"
#include "Python.h"
#define KEYLEN 7

View File

@ -36,7 +36,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "Python.h"
#include <dirent.h>
#include <time.h>
#include "common.h"

View File

@ -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.2.2");
version = Py_BuildValue("s", "0.2.3");
PyModule_AddObject(module, "VERSION", version);
}

View File

@ -66,7 +66,8 @@ struct callback
int fde;
int gpio;
int edge;
void (*func)(int gpio);
void* data;
void (*func)(int gpio, void* data);
struct callback *next;
};
struct callback *callbacks = NULL;
@ -549,7 +550,7 @@ void exports_cleanup(void)
gpio_unexport(exported_gpios->gpio);
}
int add_edge_callback(int gpio, int edge, void (*func)(int gpio))
int add_edge_callback(int gpio, int edge, void (*func)(int gpio, void* data), void* data)
{
struct callback *cb = callbacks;
struct callback *new_cb;
@ -559,6 +560,7 @@ int add_edge_callback(int gpio, int edge, void (*func)(int gpio))
new_cb->fde = open_edge_file(gpio);
new_cb->gpio = gpio;
new_cb->edge = edge;
new_cb->data = data;
new_cb->func = func;
new_cb->next = NULL;
@ -602,7 +604,7 @@ void run_callbacks(int gpio)
// Only run if we are allowed
if (canrun)
{
cb->func(cb->gpio);
cb->func(cb->gpio, cb->data);
}
}

View File

@ -70,7 +70,7 @@ 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, int edge, void (*func)(int gpio));
int add_edge_callback(int gpio, int edge, void (*func)(int gpio, void* data), void* data);
int event_detected(int gpio);
int gpio_event_add(int gpio);
int gpio_event_remove(int gpio);

View File

@ -225,7 +225,7 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args)
return py_value;
}
static void run_py_callbacks(int gpio)
static void run_py_callbacks(int gpio, void* data)
{
PyObject *result;
PyGILState_STATE gstate;
@ -294,7 +294,7 @@ static int add_py_callback(char *channel, int gpio, int edge, unsigned int bounc
cb = cb->next;
cb->next = new_py_cb;
}
add_edge_callback(gpio, edge, run_py_callbacks);
add_edge_callback(gpio, edge, run_py_callbacks, NULL);
return 0;
}
@ -749,6 +749,54 @@ static PyObject *py_selftest(PyObject *self, PyObject *args)
static const char moduledocstring[] = "GPIO functionality of a CHIP using Python";
/*
mine for changing pin directipn
*/
static PyObject *py_set_direction(PyObject *self, PyObject *args, PyObject *kwargs)
{
int gpio;
char *channel;
int direction;
static char *kwlist[] = { "channel", "direction", NULL };
clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction))
return NULL;
if (!module_setup) {
init_module();
}
if (direction != INPUT && direction != OUTPUT)
{
PyErr_SetString(PyExc_ValueError, "An invalid direction was passed to setup()");
return NULL;
}
if (get_gpio_number(channel, &gpio) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Invalid channel %s. (%s)", channel, get_error_msg());
PyErr_SetString(PyExc_ValueError, err);
return NULL;
}
if (gpio_set_direction(gpio, direction) < 0) {
char err[2000];
snprintf(err, sizeof(err), "Error setting direction %d on channel %s. (%s)", direction, channel, get_error_msg());
PyErr_SetString(PyExc_RuntimeError, err);
return NULL;
}
remember_gpio_direction(gpio, direction);
Py_RETURN_NONE;
}
PyMethodDef gpio_methods[] = {
{"setup", (PyCFunction)py_setup_channel, METH_VARARGS | METH_KEYWORDS, "Set up the GPIO channel, direction and (optional) pull/up down control\nchannel - Either: CHIP board pin number (not R8 GPIO 00..nn number). Pins start from 1\n or : CHIP GPIO name\ndirection - INPUT or OUTPUT\n[pull_up_down] - PUD_OFF (default), PUD_UP or PUD_DOWN\n[initial] - Initial value for an output channel"},
{"cleanup", py_cleanup, METH_VARARGS, "Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection"},
@ -763,9 +811,11 @@ PyMethodDef gpio_methods[] = {
{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"},
{"get_gpio_base", py_gpio_base, METH_VARARGS, "Get the XIO base number for sysfs"},
{"selftest", py_selftest, METH_VARARGS, "Internal unit tests"},
{ "direction", (PyCFunction)py_set_direction, METH_VARARGS, "Change direction of gpio channel. Either INPUT or OUTPUT\n" },
{NULL, NULL, 0, NULL}
};
#if PY_MAJOR_VERSION > 2
static struct PyModuleDef rpigpiomodule = {
PyModuleDef_HEAD_INIT,
@ -815,4 +865,4 @@ PyMODINIT_FUNC initGPIO(void)
#else
return;
#endif
}
}

View File

@ -1,96 +0,0 @@
# The default ``config.py``
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = [
'*.pyc', '*~', '.ropeproject', '.hg', '.svn', '_svn', '.git',
'.tox', '.env', 'node_modules', 'bower_components']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
#prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
#prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
#prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will sort imports alphabetically by module name
# instead of alphabetically by import statement, with from imports
# after normal imports.
prefs['sort_imports_alphabetically'] = False
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!

View File

@ -1,2 +0,0 @@
<EFBFBD>}q(Utest_softpwm_setup]q(Uteardown_moduleqUTestSoftpwmSetupqeUtest_gpio_output]q(hUTestGPIOOutputqeUtest_pwm_setup]q(hU TestPwmSetupqeUtest_gpio_setup]q (hU TestSetupq
eUtest_gpio_input]q (hU

View File

@ -1 +0,0 @@
<EFBFBD>]q(]q]qe.

View File

@ -1 +0,0 @@
<EFBFBD>}q.

67
test/lradc_test.py Normal file
View File

@ -0,0 +1,67 @@
#!/usr/bin/python
import CHIP_IO.LRADC as ADC
# == ENABLE DEBUG ==
print("ENABLING LRADC DEBUG OUTPUT")
ADC.enable_debug()
# == SETUP ==
print("LRADC SETUP WITH SAMPLE RATE OF 125")
ADC.setup(125)
# == SCALE FACTOR ==
print("GETTING SCALE FACTOR")
scalefactor = ADC.get_scale_factor()
print(scalefactor)
print("")
# == ALLOWABLE SAMPLING RATES ==
print("GETTING ALLOWABLE SAMPLE RATES")
rates = ADC.get_allowable_sample_rates()
print(rates)
print("IS 32.25 IN RATE TUPLE")
print(ADC.SAMPLE_RATE_32P25 in rates)
print("")
# == CURRENT SAMPLE RATE ==
print("CURRENT SAMPLING RATE")
crate = ADC.get_sample_rate()
print(crate)
print("")
# == SET SAMPLE RATE ==
print("SETTING SAMPLE RATE TO 62.5")
ADC.set_sample_rate(62.5)
crate = ADC.get_sample_rate()
print(crate)
print("")
# == CHAN 0 RAW ==
print("READING LRADC CHAN0 RAW")
raw0 = ADC.get_chan0_raw()
print(raw0)
print("")
# == CHAN 1 RAW ==
print("READING LRADC CHAN1 RAW")
raw1 = ADC.get_chan1_raw()
print(raw1)
print("")
# == CHAN 0 ==
print("READING LRADC CHAN0 WITH SCALE APPLIED")
full0 = ADC.get_chan0()
print(full0)
print("")
# == CHAN 1 ==
print("READING LRADC CHAN1 WITH SCALE APPLIED")
full1 = ADC.get_chan1()
print(full1)
print("")
# == RESET ==
print("RESETING SAMPLE RATE TO 250")
ADC.set_sample_rate(250)