...
 
Commits (8)
......@@ -25,6 +25,6 @@ import box0.driver as driver
__all__ = ["Device", "ResultException", "usb", "Version", "RefType", "module",
"driver"]
__version__ = '0.3.0'
__version__ = '0.3.1'
__author__ = 'Kuldeep Singh Dhaka <kuldeep@madresistor.com>'
__licence__ = 'GNU General Public License v3 or later (GPLv3+)'
......@@ -2,7 +2,7 @@
#
# This file is part of pyBox0.
# Copyright (C) 2014-2016 Kuldeep Singh Dhaka <kuldeep@madresistor.com>
# Copyright (C) 2014-2018 Kuldeep Singh Dhaka <kuldeep@madresistor.com>
#
# pyBox0 is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -99,7 +99,17 @@ ffi.cdef("""
B0_AIN_CAPAB_ALIGN_MSB = 0x02,
B0_AIN_CAPAB_ENDIAN_LITTLE = 0x00,
B0_AIN_CAPAB_ENDIAN_BIG = 0x04
B0_AIN_CAPAB_ENDIAN_BIG = 0x04,
B0_AIN_CAPAB_SAMPLING_SEQUENTIAL = 0x00,
B0_AIN_CAPAB_SAMPLING_PARALLEL = 0x10,
B0_AIN_CAPAB_PACKED = 0x20,
B0_AIN_CAPAB_FORMAT_MASK = 0x01,
B0_AIN_CAPAB_ALIGN_MASK = 0x02,
B0_AIN_CAPAB_ENDIAN_MASK = 0x04,
B0_AIN_CAPAB_SAMPLING_MASK = 0x10,
};
typedef enum b0_ain_capab b0_ain_capab;
......@@ -145,7 +155,18 @@ ffi.cdef("""
B0_AOUT_CAPAB_ENDIAN_BIG = 0x04,
/* Repeat supported */
B0_AOUT_CAPAB_REPEAT = 0x08
B0_AOUT_CAPAB_REPEAT = 0x08,
B0_AOUT_CAPAB_SAMPLING_SEQUENTIAL = 0x00,
B0_AOUT_CAPAB_SAMPLING_PARALLEL = 0x10,
B0_AOUT_CAPAB_PACKED = 0x20,
B0_AOUT_CAPAB_FORMAT_MASK = 0x01,
B0_AOUT_CAPAB_ALIGN_MASK = 0x02,
B0_AOUT_CAPAB_ENDIAN_MASK = 0x04,
B0_AOUT_CAPAB_REPEAT_MASK = 0x08,
B0_AOUT_CAPAB_SAMPLING_MASK = 0x10,
};
typedef enum b0_aout_capab b0_aout_capab;
......@@ -558,28 +579,28 @@ ffi.cdef("""
b0_result_code b0_dio_close(b0_dio *mod);
b0_result_code b0_dio_open(b0_device *dev, b0_dio **mod, int index);
b0_result_code b0_dio_value_get(b0_dio *mod, uint8_t pin, bool *value);
b0_result_code b0_dio_value_set(b0_dio *mod, uint8_t pin, bool value);
b0_result_code b0_dio_value_toggle(b0_dio *mod, uint8_t pin);
b0_result_code b0_dio_dir_get(b0_dio *mod, uint8_t pin, bool *value);
b0_result_code b0_dio_dir_set(b0_dio *mod, uint8_t pin, bool value);
b0_result_code b0_dio_hiz_get(b0_dio *mod, uint8_t pin, bool *value);
b0_result_code b0_dio_hiz_set(b0_dio *mod, uint8_t pin, bool value);
b0_result_code b0_dio_value_get(b0_dio *mod, unsigned pin, bool *value);
b0_result_code b0_dio_value_set(b0_dio *mod, unsigned pin, bool value);
b0_result_code b0_dio_value_toggle(b0_dio *mod, unsigned pin);
b0_result_code b0_dio_dir_get(b0_dio *mod, unsigned pin, bool *value);
b0_result_code b0_dio_dir_set(b0_dio *mod, unsigned pin, bool value);
b0_result_code b0_dio_hiz_get(b0_dio *mod, unsigned pin, bool *value);
b0_result_code b0_dio_hiz_set(b0_dio *mod, unsigned pin, bool value);
b0_result_code b0_dio_multiple_value_set(b0_dio *mod,
uint8_t *pins, size_t size, bool value);
unsigned *pins, size_t size, bool value);
b0_result_code b0_dio_multiple_value_get(b0_dio *mod,
uint8_t *pins, bool *values, size_t size);
unsigned *pins, bool *values, size_t size);
b0_result_code b0_dio_multiple_value_toggle(b0_dio *mod,
uint8_t *pins, size_t size);
unsigned *pins, size_t size);
b0_result_code b0_dio_multiple_dir_set(b0_dio *mod,
uint8_t *pins, size_t size, bool value);
unsigned *pins, size_t size, bool value);
b0_result_code b0_dio_multiple_dir_get(b0_dio *mod,
uint8_t *pins, bool *values, size_t size);
unsigned *pins, bool *values, size_t size);
b0_result_code b0_dio_multiple_hiz_get(b0_dio *mod,
uint8_t *pins, bool *values, size_t size);
unsigned *pins, bool *values, size_t size);
b0_result_code b0_dio_multiple_hiz_set(b0_dio *mod,
uint8_t *pins, size_t size, bool value);
unsigned *pins, size_t size, bool value);
b0_result_code b0_dio_all_value_set(b0_dio *mod, bool value);
b0_result_code b0_dio_all_value_get(b0_dio *mod, bool *values);
......@@ -698,6 +719,23 @@ ffi.cdef("""
b0_ads1220_vref_source source, double low, double high);
b0_result_code b0_ads1220_filter_set(b0_ads1220 *drv, b0_ads1220_filter type);
/* BMP180 */
enum b0_bmp180_over_samp {
B0_BMP180_OVER_SAMP_1 = 0,
B0_BMP180_OVER_SAMP_2 = 1,
B0_BMP180_OVER_SAMP_4 = 2,
B0_BMP180_OVER_SAMP_8 = 3
};
typedef enum b0_bmp180_over_samp b0_bmp180_over_samp;
typedef struct b0_bmp180 b0_bmp180;
b0_result_code b0_bmp180_open(b0_i2c *mod, b0_bmp180 **drv);
b0_result_code b0_bmp180_over_samp_set(b0_bmp180 *drv,
b0_bmp180_over_samp over_sampling);
b0_result_code b0_bmp180_close(b0_bmp180 *drv);
b0_result_code b0_bmp180_read(b0_bmp180 *drv, double *pressure, double *temp);
/* box-v5 */
b0_result_code b0v5_valid_test(b0_device *dev);
......
......@@ -20,5 +20,6 @@ from box0.driver.adxl345 import Adxl345
from box0.driver.hbridge import HBridge
from box0.driver.mcp342x import Mcp342x
from box0.driver.ads1220 import Ads1220
from box0.driver.bmp180 import Bmp180
__all__ = ["Adxl345", "HBridge", "Mcp342x", "Ads1220"]
__all__ = ["Adxl345", "HBridge", "Mcp342x", "Ads1220", "Bmp180"]
#
# This file is part of pyBox0.
# Copyright (C) 2018 Kuldeep Singh Dhaka <kuldeep@madresistor.com>
#
# pyBox0 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 3 of the License, or
# (at your option) any later version.
#
# pyBox0 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.
#
# You should have received a copy of the GNU General Public License
# along with pyBox0. If not, see <http://www.gnu.org/licenses/>.
#
from box0._binding import libbox0, ffi
from box0.driver.driver import Driver
from box0.module import I2c
from box0.exceptions import ResultException
class Bmp180(Driver):
"""
BMP180 (Pressure sensor) Driver
"""
OVER_SAMP_1 = libbox0.B0_BMP180_OVER_SAMP_1
OVER_SAMP_2 = libbox0.B0_BMP180_OVER_SAMP_2
OVER_SAMP_4 = libbox0.B0_BMP180_OVER_SAMP_4
OVER_SAMP_8 = libbox0.B0_BMP180_OVER_SAMP_8
_open = libbox0.b0_bmp180_open
_over_samp_set = libbox0.b0_bmp180_over_samp_set
_close = libbox0.b0_bmp180_close
_read = libbox0.b0_bmp180_read
def __init__(self, module):
drv = ffi.new("b0_bmp180 **")
ResultException.act(self._open(module._pointer, drv))
"""Cache the objects"""
Driver.__init__(self, drv[0], module)
def over_samp_set(self, value):
ResultException.act(self._over_samp_set(self._pointer, value))
def read(self):
arr = ffi.new("double [2]")
ResultException.act(self._read(self._pointer, arr+0 , arr+1))
return (arr[0], arr[1])
......@@ -21,7 +21,7 @@ from box0._binding import ffi, libbox0, string_array_converter, \
from box0.exceptions import ResultException
import numpy as np
from box0.module import ModuleInstance
from box0.module.module import np_dtype_map, bitsize_speed_set, \
from box0.module.module import bitsize_speed_set, \
bitsize_speed_get, chan_seq_set, chan_seq_get
class Ain(ModuleInstance):
......@@ -125,23 +125,38 @@ class Ain(ModuleInstance):
"""
ResultException.act(self._snapshot_prepare(self._pointer))
def snapshot_start(self, data):
def snapshot_start(self, data, count=None):
"""
Get data in snapshot mode
:param numpy.ndarray data: NumPy array to store readed value
:param int count: Number of samples to read (Only mandatory for data type Void)
:raises ResultException: if libbox0 return negative result code
.. warning::
This function is blocking and will not return until acquire all data
"""
sel = np_dtype_map(data.dtype,
void = ("void *", self._snapshot_start),
float32 = ("float *", self._snapshot_start_float),
float64 = ("double *", self._snapshot_start_double))
data_ptr = ffi.cast(sel[0], data.ctypes.data)
ResultException.act(sel[1](self._pointer, data_ptr, data.size))
RAW = {'cast': 'void *', 'call': self._snapshot_start}
sel = {
np.void: RAW, np.int8: RAW, np.uint8: RAW, np.int16: RAW, np.uint16: RAW,
np.int32: RAW, np.uint32: RAW, np.int64: RAW, np.uint64: RAW,
np.float32: {'cast': 'float *', 'call': self._snapshot_start_float},
np.float64: {'cast': 'double *', 'call': self._snapshot_start_double}
}.get(np.obj2sctype(data.dtype))
if sel is None:
raise Exception("numpy memory type not supported")
# Beware, we are not checking array overflow
if count is None:
if np.obj2sctype(data.dtype) is np.void:
raise Exception("If data type is Void, count is mandatory")
else:
count = data.size
data_ptr = ffi.cast(sel['cast'], data.ctypes.data)
ResultException.act(sel['call'](self._pointer, data_ptr, count))
def snapshot_stop(self):
"""
......@@ -168,11 +183,12 @@ class Ain(ModuleInstance):
ResultException.act(self._stream_start(self._pointer))
def stream_read(self, data, allowPartial=False):
def stream_read(self, data, count=None, allowPartial=False):
"""
Read data from stream
:param numpy.ndarray data: Store readed data
:param int count: Number of samples to read (Only mandatory for data type Void)
:param bool allowPartial: if False, return only after reading total requested samples
:rtype: int
:return: number of samples readed
......@@ -187,15 +203,29 @@ class Ain(ModuleInstance):
non-blocking: if `allowPartial is True`, try to read as much as requested data and return
"""
sel = np_dtype_map(data.dtype,
void = ("void *", self._stream_read),
float32 = ("float *", self._stream_read_float),
float64 = ("double *", self._stream_read_double))
data_ptr = ffi.cast(sel[0], data.ctypes.data)
RAW = {'cast' : 'void *', 'call': self._stream_read}
sel = {
np.void: RAW, np.int8: RAW, np.uint8: RAW, np.int16: RAW, np.uint16: RAW,
np.int32: RAW, np.uint32: RAW, np.int64: RAW, np.uint64: RAW,
np.float32: {'cast': 'float *', 'call': self._stream_read_float},
np.float64: {'cast': 'double *', 'call': self._stream_read_double}
}.get(np.obj2sctype(data.dtype))
if sel is None:
raise Exception("numpy memory type not supported, (hint: use numpy.void)")
# Beware, we are not checking array overflow
if count is None:
if np.obj2sctype(data.dtype) is np.void:
raise Exception("If data type is Void, count is mandatory")
else:
count = data.size
data_ptr = ffi.cast(sel['cast'], data.ctypes.data)
actual_readed = ffi.new("size_t *") if allowPartial else ffi.NULL
ResultException.act(sel[1](self._pointer, data_ptr, data.size, \
ResultException.act(sel['call'](self._pointer, data_ptr, count, \
actual_readed))
return actual_readed[0] if allowPartial else data.size
return actual_readed[0] if allowPartial else count
def stream_stop(self):
"""
......
......@@ -21,7 +21,7 @@ from box0._binding import libbox0, ffi, string_array_converter, \
from box0.exceptions import ResultException
import numpy as np
from box0.module import ModuleInstance
from box0.module.module import np_dtype_map, bitsize_speed_set, \
from box0.module.module import bitsize_speed_set, \
bitsize_speed_get, chan_seq_set, chan_seq_get
class Aout(ModuleInstance):
......@@ -134,19 +134,34 @@ class Aout(ModuleInstance):
currently double only supported
data is numpy array
"""
def stream_write(self, data):
def stream_write(self, data, count=None):
"""
wrtie data to stream
:param numpy.ndarray data: Store readed data
:param int count: Number of samples to write (Only mandatory for data type Void)
:raises ResultException: if libbox0 return negative result code
"""
sel = np_dtype_map(data.dtype,
void = ("void *", self._stream_write),
float32 = ("float *", self._stream_write_float),
float64 = ("double *", self._stream_write_double))
data_ptr = ffi.cast(sel[0], data.ctypes.data)
ResultException.act(sel[1](self._pointer, data_ptr, data.size))
RAW = {'cast': 'void *', 'call': self._stream_write}
sel = {
np.void: RAW, np.int8: RAW, np.uint8: RAW, np.int16: RAW, np.uint16: RAW,
np.int32: RAW, np.uint32: RAW, np.int64: RAW, np.uint64: RAW,
np.float32: {'cast': 'float *', 'call': self._stream_write_float},
np.float64: {'cast': 'double *', 'call': self._stream_write_double}
}.get(np.obj2sctype(data.dtype))
if sel is None:
raise Exception("numpy memory type not supported")
# Beware, we are not checking array overflow
if count is None:
if np.obj2sctype(data.dtype) is np.void:
raise Exception("If data type is Void, count is mandatory")
else:
count = data.size
data_ptr = ffi.cast(sel['cast'], data.ctypes.data)
ResultException.act(sel['call'](self._pointer, data_ptr, count))
def stream_start(self):
"""
......@@ -171,19 +186,34 @@ class Aout(ModuleInstance):
"""
ResultException.act(self._snapshot_prepare(self._pointer))
def snapshot_start(self, data):
def snapshot_start(self, data, count=None):
"""
Get data in snapshot mode
:param numpy.ndarray data: NumPy array to output
:param int count: Number of samples to write (Only mandatory for data type Void)
:raises ResultException: if libbox0 return negative result code
"""
sel = np_dtype_map(data.dtype,
void = ("void *", self._snapshot_start),
float32 = ("float *", self._snapshot_start_float),
float64 = ("double *", self._snapshot_start_double))
data_ptr = ffi.cast(sel[0], data.ctypes.data)
ResultException.act(sel[1](self._pointer, data_ptr, data.size))
RAW = {'cast': 'void *', 'call': self._snapshot_start}
sel = {
np.void: RAW, np.int8: RAW, np.uint8: RAW, np.int16: RAW, np.uint16: RAW,
np.int32: RAW, np.uint32: RAW, np.int64: RAW, np.uint64: RAW,
np.float32: {'cast': 'float *', 'call': self._snapshot_start_float},
np.float64: {'cast': 'double *', 'call': self._snapshot_start_double}
}.get(np.obj2sctype(data.dtype))
if sel is None:
raise Exception("numpy memory type not supported")
# Beware, we are not checking array overflow
if count is None:
if np.obj2sctype(data.dtype) is np.void:
raise Exception("If data type is Void, count is mandatory")
else:
count = data.size
data_ptr = ffi.cast(sel['cast'], data.ctypes.data)
ResultException.act(sel['call'](self._pointer, data_ptr, count))
def snapshot_stop(self):
"""
......
......@@ -333,7 +333,7 @@ class Dio(ModuleInstance):
"""
value = self._HIGH if value else self._LOW
ResultException.act(self._multiple_value_set(self._pointer,
ffi.new("uint8_t []", pins), len(pins), value))
ffi.new("unsigned []", pins), len(pins), value))
def multiple_value_get(self, pins):
"""
......@@ -345,7 +345,7 @@ class Dio(ModuleInstance):
"""
values = ffi.new("bool []", len(pins))
ResultException.act(self._multiple_value_get(self._pointer,
ffi.new("uint8_t []", pins), values, len(pins)))
ffi.new("unsigned []", pins), values, len(pins)))
return [i != self._LOW for i in values]
def multiple_value_toggle(self, pins):
......@@ -356,7 +356,7 @@ class Dio(ModuleInstance):
:raises ResultException: if libbox0 return negative result code
"""
ResultException.act(self._multiple_value_toggle(self._pointer,
ffi.new("uint8_t []", pins), len(pins)))
ffi.new("unsigned []", pins), len(pins)))
def multiple_dir_set(self, pins, value):
"""
......@@ -368,7 +368,7 @@ class Dio(ModuleInstance):
"""
value = self._OUTPUT if value else self._INPUT
ResultException.act(self._multiple_dir_set(self._pointer,
ffi.new("uint8_t []", pins), len(pins), value))
ffi.new("unsigned []", pins), len(pins), value))
def multiple_dir_get(self, pins):
"""
......@@ -380,7 +380,7 @@ class Dio(ModuleInstance):
"""
values = ffi.new("bool []", len(pins))
ResultException.act(self._multiple_dir_get(self._pointer,
ffi.new("uint8_t []", pins), values, len(pins)))
ffi.new("unsigned []", pins), values, len(pins)))
return [i != self._INPUT for i in values]
def multiple_hiz_set(self, pins, value):
......@@ -393,7 +393,7 @@ class Dio(ModuleInstance):
"""
value = self._ENABLE if value else self._DISABLE
ResultException.act(self._multiple_hiz_set(self._pointer,
ffi.new("uint8_t []", pins), len(pins), value))
ffi.new("unsigned []", pins), len(pins), value))
def multiple_hiz_get(self, pins):
"""
......@@ -405,7 +405,7 @@ class Dio(ModuleInstance):
"""
values = ffi.new("bool []", len(pins))
ResultException.act(self._multiple_hiz_get(self._pointer,
ffi.new("uint8_t []", pins), values, len(pins)))
ffi.new("unsigned []", pins), values, len(pins)))
return [i != self._DISABLE for i in values]
def all_value_set(self, value):
......
......@@ -22,28 +22,28 @@ from box0.module import ModuleInstance
import numpy as np
class Slave(object):
def __init__(self, addr, version, mod):
def __init__(self, addr, mod, version=None):
self.addr = addr
self.mod = mod
self._arg = ffi.new("b0_i2c_sugar_arg *", {
'addr': addr,
'version': version
'version': I2c.SM if version is None else version
})
def detect(self):
return self.mod.slave_detect(self._arg)
return self.mod.master_slave_detect(self._arg)
def read(self, read):
return self.mod.read(self._arg, read)
return self.mod.master_read(self._arg, read)
def write(self, write):
return self.mod.read(self._arg, write)
return self.mod.master_write(self._arg, write)
def write8_read(self, write_byte, read):
return self.mod.write8_read(self, self._arg, write_byte, read)
return self.mod.master_write8_read(self._arg, write_byte, read)
def write_read(self, write, read):
return self.mod.write_read(self, self._arg, write, read)
return self.mod.master_write_read(self._arg, write, read)
def __str__(self):
return "Slave Address: " + hex(self.addr)
......@@ -259,7 +259,7 @@ class I2c(ModuleInstance):
"""
arg = to_sugar_arg(arg)
write_ptr = ffi.cast("void *", write.ctypes.data)
result = self._write(self._pointer, arg, write_ptr, write.nbytes)
result = self._master_write(self._pointer, arg, write_ptr, write.nbytes)
ResultException.act(result)
def master_read(self, arg, read):
......@@ -273,13 +273,13 @@ class I2c(ModuleInstance):
read = np.empty(read, dtype=np.uint8)
data_ptr = ffi.cast("void *", read.ctypes.data)
result = self._read(self._pointer, arg, data_ptr, read.nbytes)
result = self._master_read(self._pointer, arg, data_ptr, read.nbytes)
ResultException.act(result)
return read
def slave(self, addr, version):
def slave(self, addr, **kwargs):
"""
construct a Slave Object
modX.slave(addr, version) => Slave(addr, version, modX)
modX.slave(addr, ...) => Slave(addr, modX, ...)
"""
return Slave(addr, version, self)
return Slave(addr, self, **kwargs)
......@@ -109,15 +109,6 @@ class ModuleInstance(Module, Close):
def openable(self):
raise Exception("You already have the module opened!")
def np_dtype_map(dtype, float32, float64, void):
if dtype == np.float32:
return float32
elif dtype == np.float64:
return float64
elif dtype == np.void:
return void
raise Exception("numpy memory type not supported, (hint: numpy.void)")
def bitsize_speed_set(self, bitsize, speed):
ResultException.act(self._bitsize_speed_set(self._pointer, bitsize, speed))
......
......@@ -51,7 +51,7 @@ def _to_cflags(mode, lsb_first, cpol, cpha):
return _flags
class Slave(object):
def __init__(self, addr, bitsize=None, speed=0, lsb_first=False, \
def __init__(self, addr, mod, bitsize=None, speed=0, lsb_first=False, \
mode=None, cpha=None, cpol=None):
self.addr = addr
self.mod = mod
......@@ -313,13 +313,12 @@ class Spi(ModuleInstance):
ResultException.act(self._fd(self._pointer, arg, write_buf, read_buf, count))
return read
def slave(self, addr, bitsize=None, speed=0, lsb_first=False, mode=None, \
cpha=None, cpol=None):
def slave(self, addr, **kwargs):
"""
construct a Slave Object
modX.slave(addr, ...) => Slave(addr, ..., modX)
modX.slave(addr, ...) => Slave(addr, modX, ...)
"""
return Slave(addr, bitsize, speed, lsb_first, mode, cpha, cpol, self)
return Slave(addr, self, **kwargs)
speed_set = speed_set
speed_get = speed_get
......@@ -66,7 +66,7 @@ author = 'Kuldeep Singh Dhaka'
# The short X.Y version.
version = '0.3'
# The full version, including alpha/beta/rc tags.
release = '0.3.0'
release = '0.3.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......