1 |
14 |
mjlyons |
#==========================================================================
|
2 |
|
|
# Cheetah Interface Library
|
3 |
|
|
#--------------------------------------------------------------------------
|
4 |
|
|
# Copyright (c) 2004-2008 Total Phase, Inc.
|
5 |
|
|
# All rights reserved.
|
6 |
|
|
# www.totalphase.com
|
7 |
|
|
#
|
8 |
|
|
# Redistribution and use in source and binary forms, with or without
|
9 |
|
|
# modification, are permitted provided that the following conditions
|
10 |
|
|
# are met:
|
11 |
|
|
#
|
12 |
|
|
# - Redistributions of source code must retain the above copyright
|
13 |
|
|
# notice, this list of conditions and the following disclaimer.
|
14 |
|
|
#
|
15 |
|
|
# - Redistributions in binary form must reproduce the above copyright
|
16 |
|
|
# notice, this list of conditions and the following disclaimer in the
|
17 |
|
|
# documentation and/or other materials provided with the distribution.
|
18 |
|
|
#
|
19 |
|
|
# - Neither the name of Total Phase, Inc. nor the names of its
|
20 |
|
|
# contributors may be used to endorse or promote products derived from
|
21 |
|
|
# this software without specific prior written permission.
|
22 |
|
|
#
|
23 |
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
24 |
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
25 |
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
26 |
|
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
27 |
|
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
28 |
|
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
29 |
|
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
30 |
|
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
31 |
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
32 |
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
33 |
|
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
34 |
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
35 |
|
|
#--------------------------------------------------------------------------
|
36 |
|
|
# To access Total Phase Cheetah devices through the API:
|
37 |
|
|
#
|
38 |
|
|
# 1) Use one of the following shared objects:
|
39 |
|
|
# cheetah.so -- Linux shared object
|
40 |
|
|
# or
|
41 |
|
|
# cheetah.dll -- Windows dynamic link library
|
42 |
|
|
#
|
43 |
|
|
# 2) Along with one of the following language modules:
|
44 |
|
|
# cheetah.c/h -- C/C++ API header file and interface module
|
45 |
|
|
# cheetah_py.py -- Python API
|
46 |
|
|
# cheetah.bas -- Visual Basic 6 API
|
47 |
|
|
# cheetah.cs -- C# .NET source
|
48 |
|
|
# cheetah_net.dll -- Compiled .NET binding
|
49 |
|
|
#==========================================================================
|
50 |
|
|
|
51 |
|
|
|
52 |
|
|
#==========================================================================
|
53 |
|
|
# VERSION
|
54 |
|
|
#==========================================================================
|
55 |
|
|
CH_API_VERSION = 0x0300 # v3.00
|
56 |
|
|
CH_REQ_SW_VERSION = 0x0300 # v3.00
|
57 |
|
|
|
58 |
|
|
import os
|
59 |
|
|
import sys
|
60 |
|
|
try:
|
61 |
|
|
import cheetah as api
|
62 |
|
|
except ImportError, ex1:
|
63 |
|
|
import imp, platform
|
64 |
|
|
ext = platform.system() == 'Windows' and '.dll' or '.so'
|
65 |
|
|
try:
|
66 |
|
|
api = imp.load_dynamic('cheetah', 'cheetah' + ext)
|
67 |
|
|
except ImportError, ex2:
|
68 |
|
|
msg = 'Error importing cheetah%s\n' % ext
|
69 |
|
|
msg += ' Architecture of cheetah%s may be wrong\n' % ext
|
70 |
|
|
msg += '%s\n%s' % (ex1, ex2)
|
71 |
|
|
raise ImportError(msg)
|
72 |
|
|
|
73 |
|
|
CH_SW_VERSION = api.py_version() & 0xffff
|
74 |
|
|
CH_REQ_API_VERSION = (api.py_version() >> 16) & 0xffff
|
75 |
|
|
CH_LIBRARY_LOADED = \
|
76 |
|
|
((CH_SW_VERSION >= CH_REQ_SW_VERSION) and \
|
77 |
|
|
(CH_API_VERSION >= CH_REQ_API_VERSION))
|
78 |
|
|
|
79 |
|
|
from array import array, ArrayType
|
80 |
|
|
import struct
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
#==========================================================================
|
84 |
|
|
# HELPER FUNCTIONS
|
85 |
|
|
#==========================================================================
|
86 |
|
|
def array_u08 (n): return array('B', '\0'*n)
|
87 |
|
|
def array_u16 (n): return array('H', '\0\0'*n)
|
88 |
|
|
def array_u32 (n): return array('I', '\0\0\0\0'*n)
|
89 |
|
|
def array_u64 (n): return array('K', '\0\0\0\0\0\0\0\0'*n)
|
90 |
|
|
def array_s08 (n): return array('b', '\0'*n)
|
91 |
|
|
def array_s16 (n): return array('h', '\0\0'*n)
|
92 |
|
|
def array_s32 (n): return array('i', '\0\0\0\0'*n)
|
93 |
|
|
def array_s64 (n): return array('L', '\0\0\0\0\0\0\0\0'*n)
|
94 |
|
|
|
95 |
|
|
|
96 |
|
|
#==========================================================================
|
97 |
|
|
# STATUS CODES
|
98 |
|
|
#==========================================================================
|
99 |
|
|
# All API functions return an integer which is the result of the
|
100 |
|
|
# transaction, or a status code if negative. The status codes are
|
101 |
|
|
# defined as follows:
|
102 |
|
|
# enum CheetahStatus
|
103 |
|
|
# General codes (0 to -99)
|
104 |
|
|
CH_OK = 0
|
105 |
|
|
CH_UNABLE_TO_LOAD_LIBRARY = -1
|
106 |
|
|
CH_UNABLE_TO_LOAD_DRIVER = -2
|
107 |
|
|
CH_UNABLE_TO_LOAD_FUNCTION = -3
|
108 |
|
|
CH_INCOMPATIBLE_LIBRARY = -4
|
109 |
|
|
CH_INCOMPATIBLE_DEVICE = -5
|
110 |
|
|
CH_INCOMPATIBLE_DRIVER = -6
|
111 |
|
|
CH_COMMUNICATION_ERROR = -7
|
112 |
|
|
CH_UNABLE_TO_OPEN = -8
|
113 |
|
|
CH_UNABLE_TO_CLOSE = -9
|
114 |
|
|
CH_INVALID_HANDLE = -10
|
115 |
|
|
CH_CONFIG_ERROR = -11
|
116 |
|
|
CH_UNKNOWN_PROTOCOL = -12
|
117 |
|
|
CH_STILL_ACTIVE = -13
|
118 |
|
|
CH_FUNCTION_NOT_AVAILABLE = -14
|
119 |
|
|
CH_OS_ERROR = -15
|
120 |
|
|
|
121 |
|
|
# SPI codes (-100 to -199)
|
122 |
|
|
CH_SPI_WRITE_ERROR = -100
|
123 |
|
|
CH_SPI_BATCH_EMPTY_QUEUE = -101
|
124 |
|
|
CH_SPI_BATCH_SHORT_BUFFER = -102
|
125 |
|
|
CH_SPI_ASYNC_EMPTY = -103
|
126 |
|
|
CH_SPI_ASYNC_PENDING = -104
|
127 |
|
|
CH_SPI_ASYNC_MAX_REACHED = -105
|
128 |
|
|
CH_SPI_ASYNC_EXCESS_DELAY = -106
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
#==========================================================================
|
132 |
|
|
# GENERAL TYPE DEFINITIONS
|
133 |
|
|
#==========================================================================
|
134 |
|
|
# Cheetah handle type definition
|
135 |
|
|
# typedef Cheetah => integer
|
136 |
|
|
|
137 |
|
|
# Cheetah version matrix.
|
138 |
|
|
#
|
139 |
|
|
# This matrix describes the various version dependencies
|
140 |
|
|
# of Cheetah components. It can be used to determine
|
141 |
|
|
# which component caused an incompatibility error.
|
142 |
|
|
#
|
143 |
|
|
# All version numbers are of the format:
|
144 |
|
|
# (major << 8) | minor
|
145 |
|
|
#
|
146 |
|
|
# ex. v1.20 would be encoded as: 0x0114
|
147 |
|
|
class CheetahVersion:
|
148 |
|
|
def __init__ (self):
|
149 |
|
|
# Software, firmware, and hardware versions.
|
150 |
|
|
self.software = 0
|
151 |
|
|
self.firmware = 0
|
152 |
|
|
self.hardware = 0
|
153 |
|
|
|
154 |
|
|
# Hardware revisions that are compatible with this software version.
|
155 |
|
|
# The top 16 bits gives the maximum accepted hardware revision.
|
156 |
|
|
# The lower 16 bits gives the minimum accepted hardware revision.
|
157 |
|
|
self.hw_revs_for_sw = 0
|
158 |
|
|
|
159 |
|
|
# Firmware revisions that are compatible with this software version.
|
160 |
|
|
# The top 16 bits gives the maximum accepted fw revision.
|
161 |
|
|
# The lower 16 bits gives the minimum accepted fw revision.
|
162 |
|
|
self.fw_revs_for_sw = 0
|
163 |
|
|
|
164 |
|
|
# Driver revisions that are compatible with this software version.
|
165 |
|
|
# The top 16 bits gives the maximum accepted driver revision.
|
166 |
|
|
# The lower 16 bits gives the minimum accepted driver revision.
|
167 |
|
|
# This version checking is currently only pertinent for WIN32
|
168 |
|
|
# platforms.
|
169 |
|
|
self.drv_revs_for_sw = 0
|
170 |
|
|
|
171 |
|
|
# Software requires that the API interface must be >= this version.
|
172 |
|
|
self.api_req_by_sw = 0
|
173 |
|
|
|
174 |
|
|
|
175 |
|
|
#==========================================================================
|
176 |
|
|
# GENERAL API
|
177 |
|
|
#==========================================================================
|
178 |
|
|
# Get a list of ports to which Cheetah devices are attached.
|
179 |
|
|
#
|
180 |
|
|
# num_devices = maximum number of elements to return
|
181 |
|
|
# devices = array into which the port numbers are returned
|
182 |
|
|
#
|
183 |
|
|
# Each element of the array is written with the port number.
|
184 |
|
|
# Devices that are in-use are ORed with CH_PORT_NOT_FREE
|
185 |
|
|
# (0x8000).
|
186 |
|
|
#
|
187 |
|
|
# ex. devices are attached to ports 0, 1, 2
|
188 |
|
|
# ports 0 and 2 are available, and port 1 is in-use.
|
189 |
|
|
# array => 0x0000, 0x8001, 0x0002
|
190 |
|
|
#
|
191 |
|
|
# If the array is NULL, it is not filled with any values.
|
192 |
|
|
# If there are more devices than the array size, only the
|
193 |
|
|
# first nmemb port numbers will be written into the array.
|
194 |
|
|
#
|
195 |
|
|
# Returns the number of devices found, regardless of the
|
196 |
|
|
# array size.
|
197 |
|
|
CH_PORT_NOT_FREE = 0x8000
|
198 |
|
|
def ch_find_devices (devices):
|
199 |
|
|
"""usage: (int return, u16[] devices) = ch_find_devices(u16[] devices)
|
200 |
|
|
|
201 |
|
|
All arrays can be passed into the API as an ArrayType object or as
|
202 |
|
|
a tuple (array, length), where array is an ArrayType object and
|
203 |
|
|
length is an integer. The user-specified length would then serve
|
204 |
|
|
as the length argument to the API funtion (please refer to the
|
205 |
|
|
product datasheet). If only the array is provided, the array's
|
206 |
|
|
intrinsic length is used as the argument to the underlying API
|
207 |
|
|
function.
|
208 |
|
|
|
209 |
|
|
Additionally, for arrays that are filled by the API function, an
|
210 |
|
|
integer can be passed in place of the array argument and the API
|
211 |
|
|
will automatically create an array of that length. All output
|
212 |
|
|
arrays, whether passed in or generated, are passed back in the
|
213 |
|
|
returned tuple."""
|
214 |
|
|
|
215 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
216 |
|
|
# devices pre-processing
|
217 |
|
|
__devices = isinstance(devices, int)
|
218 |
|
|
if __devices:
|
219 |
|
|
(devices, num_devices) = (array_u16(devices), devices)
|
220 |
|
|
else:
|
221 |
|
|
(devices, num_devices) = isinstance(devices, ArrayType) and (devices, len(devices)) or (devices[0], min(len(devices[0]), int(devices[1])))
|
222 |
|
|
if devices.typecode != 'H':
|
223 |
|
|
raise TypeError("type for 'devices' must be array('H')")
|
224 |
|
|
# Call API function
|
225 |
|
|
(_ret_) = api.py_ch_find_devices(num_devices, devices)
|
226 |
|
|
# devices post-processing
|
227 |
|
|
if __devices: del devices[max(0, min(_ret_, len(devices))):]
|
228 |
|
|
return (_ret_, devices)
|
229 |
|
|
|
230 |
|
|
|
231 |
|
|
# Get a list of ports to which Cheetah devices are attached
|
232 |
|
|
#
|
233 |
|
|
# This function is the same as ch_find_devices() except that
|
234 |
|
|
# it returns the unique IDs of each Cheetah device. The IDs
|
235 |
|
|
# are guaranteed to be non-zero if valid.
|
236 |
|
|
#
|
237 |
|
|
# The IDs are the unsigned integer representation of the 10-digit
|
238 |
|
|
# serial numbers.
|
239 |
|
|
def ch_find_devices_ext (devices, unique_ids):
|
240 |
|
|
"""usage: (int return, u16[] devices, u32[] unique_ids) = ch_find_devices_ext(u16[] devices, u32[] unique_ids)
|
241 |
|
|
|
242 |
|
|
All arrays can be passed into the API as an ArrayType object or as
|
243 |
|
|
a tuple (array, length), where array is an ArrayType object and
|
244 |
|
|
length is an integer. The user-specified length would then serve
|
245 |
|
|
as the length argument to the API funtion (please refer to the
|
246 |
|
|
product datasheet). If only the array is provided, the array's
|
247 |
|
|
intrinsic length is used as the argument to the underlying API
|
248 |
|
|
function.
|
249 |
|
|
|
250 |
|
|
Additionally, for arrays that are filled by the API function, an
|
251 |
|
|
integer can be passed in place of the array argument and the API
|
252 |
|
|
will automatically create an array of that length. All output
|
253 |
|
|
arrays, whether passed in or generated, are passed back in the
|
254 |
|
|
returned tuple."""
|
255 |
|
|
|
256 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
257 |
|
|
# devices pre-processing
|
258 |
|
|
__devices = isinstance(devices, int)
|
259 |
|
|
if __devices:
|
260 |
|
|
(devices, num_devices) = (array_u16(devices), devices)
|
261 |
|
|
else:
|
262 |
|
|
(devices, num_devices) = isinstance(devices, ArrayType) and (devices, len(devices)) or (devices[0], min(len(devices[0]), int(devices[1])))
|
263 |
|
|
if devices.typecode != 'H':
|
264 |
|
|
raise TypeError("type for 'devices' must be array('H')")
|
265 |
|
|
# unique_ids pre-processing
|
266 |
|
|
__unique_ids = isinstance(unique_ids, int)
|
267 |
|
|
if __unique_ids:
|
268 |
|
|
(unique_ids, num_ids) = (array_u32(unique_ids), unique_ids)
|
269 |
|
|
else:
|
270 |
|
|
(unique_ids, num_ids) = isinstance(unique_ids, ArrayType) and (unique_ids, len(unique_ids)) or (unique_ids[0], min(len(unique_ids[0]), int(unique_ids[1])))
|
271 |
|
|
if unique_ids.typecode != 'I':
|
272 |
|
|
raise TypeError("type for 'unique_ids' must be array('I')")
|
273 |
|
|
# Call API function
|
274 |
|
|
(_ret_) = api.py_ch_find_devices_ext(num_devices, num_ids, devices, unique_ids)
|
275 |
|
|
# devices post-processing
|
276 |
|
|
if __devices: del devices[max(0, min(_ret_, len(devices))):]
|
277 |
|
|
# unique_ids post-processing
|
278 |
|
|
if __unique_ids: del unique_ids[max(0, min(_ret_, len(unique_ids))):]
|
279 |
|
|
return (_ret_, devices, unique_ids)
|
280 |
|
|
|
281 |
|
|
|
282 |
|
|
# Open the Cheetah port.
|
283 |
|
|
#
|
284 |
|
|
# The port number is a zero-indexed integer.
|
285 |
|
|
#
|
286 |
|
|
# The port number is the same as that obtained from the
|
287 |
|
|
# ch_find_devices() function above.
|
288 |
|
|
#
|
289 |
|
|
# Returns an Cheetah handle, which is guaranteed to be
|
290 |
|
|
# greater than zero if it is valid.
|
291 |
|
|
#
|
292 |
|
|
# This function is recommended for use in simple applications
|
293 |
|
|
# where extended information is not required. For more complex
|
294 |
|
|
# applications, the use of ch_open_ext() is recommended.
|
295 |
|
|
def ch_open (port_number):
|
296 |
|
|
"""usage: Cheetah return = ch_open(int port_number)"""
|
297 |
|
|
|
298 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
299 |
|
|
# Call API function
|
300 |
|
|
return api.py_ch_open(port_number)
|
301 |
|
|
|
302 |
|
|
|
303 |
|
|
# Open the Cheetah port, returning extended information
|
304 |
|
|
# in the supplied structure. Behavior is otherwise identical
|
305 |
|
|
# to ch_open() above. If 0 is passed as the pointer to the
|
306 |
|
|
# structure, this function is exactly equivalent to ch_open().
|
307 |
|
|
#
|
308 |
|
|
# The structure is zeroed before the open is attempted.
|
309 |
|
|
# It is filled with whatever information is available.
|
310 |
|
|
#
|
311 |
|
|
# For example, if the hardware version is not filled, then
|
312 |
|
|
# the device could not be queried for its version number.
|
313 |
|
|
#
|
314 |
|
|
# This function is recommended for use in complex applications
|
315 |
|
|
# where extended information is required. For more simple
|
316 |
|
|
# applications, the use of ch_open() is recommended.
|
317 |
|
|
class CheetahExt:
|
318 |
|
|
def __init__ (self):
|
319 |
|
|
# Version matrix
|
320 |
|
|
self.version = CheetahVersion()
|
321 |
|
|
|
322 |
|
|
# Features of this device.
|
323 |
|
|
self.features = 0
|
324 |
|
|
|
325 |
|
|
def ch_open_ext (port_number):
|
326 |
|
|
"""usage: (Cheetah return, CheetahExt ch_ext) = ch_open_ext(int port_number)"""
|
327 |
|
|
|
328 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
329 |
|
|
# Call API function
|
330 |
|
|
(_ret_, c_ch_ext) = api.py_ch_open_ext(port_number)
|
331 |
|
|
# ch_ext post-processing
|
332 |
|
|
ch_ext = CheetahExt()
|
333 |
|
|
(ch_ext.version.software, ch_ext.version.firmware, ch_ext.version.hardware, ch_ext.version.hw_revs_for_sw, ch_ext.version.fw_revs_for_sw, ch_ext.version.drv_revs_for_sw, ch_ext.version.api_req_by_sw, ch_ext.features) = c_ch_ext
|
334 |
|
|
return (_ret_, ch_ext)
|
335 |
|
|
|
336 |
|
|
|
337 |
|
|
# Close the Cheetah port.
|
338 |
|
|
def ch_close (cheetah):
|
339 |
|
|
"""usage: int return = ch_close(Cheetah cheetah)"""
|
340 |
|
|
|
341 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
342 |
|
|
# Call API function
|
343 |
|
|
return api.py_ch_close(cheetah)
|
344 |
|
|
|
345 |
|
|
|
346 |
|
|
# Return the port for this Cheetah handle.
|
347 |
|
|
#
|
348 |
|
|
# The port number is a zero-indexed integer.
|
349 |
|
|
def ch_port (cheetah):
|
350 |
|
|
"""usage: int return = ch_port(Cheetah cheetah)"""
|
351 |
|
|
|
352 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
353 |
|
|
# Call API function
|
354 |
|
|
return api.py_ch_port(cheetah)
|
355 |
|
|
|
356 |
|
|
|
357 |
|
|
# Return the unique ID for this Cheetah adapter.
|
358 |
|
|
# IDs are guaranteed to be non-zero if valid.
|
359 |
|
|
# The ID is the unsigned integer representation of the
|
360 |
|
|
# 10-digit serial number.
|
361 |
|
|
def ch_unique_id (cheetah):
|
362 |
|
|
"""usage: u32 return = ch_unique_id(Cheetah cheetah)"""
|
363 |
|
|
|
364 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
365 |
|
|
# Call API function
|
366 |
|
|
return api.py_ch_unique_id(cheetah)
|
367 |
|
|
|
368 |
|
|
|
369 |
|
|
# Return the status string for the given status code.
|
370 |
|
|
# If the code is not valid or the library function cannot
|
371 |
|
|
# be loaded, return a NULL string.
|
372 |
|
|
def ch_status_string (status):
|
373 |
|
|
"""usage: str return = ch_status_string(int status)"""
|
374 |
|
|
|
375 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
376 |
|
|
# Call API function
|
377 |
|
|
return api.py_ch_status_string(status)
|
378 |
|
|
|
379 |
|
|
|
380 |
|
|
# Return the version matrix for the device attached to the
|
381 |
|
|
# given handle. If the handle is 0 or invalid, only the
|
382 |
|
|
# software and required api versions are set.
|
383 |
|
|
def ch_version (cheetah):
|
384 |
|
|
"""usage: (int return, CheetahVersion version) = ch_version(Cheetah cheetah)"""
|
385 |
|
|
|
386 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
387 |
|
|
# Call API function
|
388 |
|
|
(_ret_, c_version) = api.py_ch_version(cheetah)
|
389 |
|
|
# version post-processing
|
390 |
|
|
version = CheetahVersion()
|
391 |
|
|
(version.software, version.firmware, version.hardware, version.hw_revs_for_sw, version.fw_revs_for_sw, version.drv_revs_for_sw, version.api_req_by_sw) = c_version
|
392 |
|
|
return (_ret_, version)
|
393 |
|
|
|
394 |
|
|
|
395 |
|
|
# Sleep for the specified number of milliseconds
|
396 |
|
|
# Accuracy depends on the operating system scheduler
|
397 |
|
|
# Returns the number of milliseconds slept
|
398 |
|
|
def ch_sleep_ms (milliseconds):
|
399 |
|
|
"""usage: u32 return = ch_sleep_ms(u32 milliseconds)"""
|
400 |
|
|
|
401 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
402 |
|
|
# Call API function
|
403 |
|
|
return api.py_ch_sleep_ms(milliseconds)
|
404 |
|
|
|
405 |
|
|
|
406 |
|
|
# Configure the target power pin.
|
407 |
|
|
CH_TARGET_POWER_OFF = 0x00
|
408 |
|
|
CH_TARGET_POWER_ON = 0x01
|
409 |
|
|
CH_TARGET_POWER_QUERY = 0x80
|
410 |
|
|
def ch_target_power (cheetah, power_flag):
|
411 |
|
|
"""usage: int return = ch_target_power(Cheetah cheetah, u08 power_flag)"""
|
412 |
|
|
|
413 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
414 |
|
|
# Call API function
|
415 |
|
|
return api.py_ch_target_power(cheetah, power_flag)
|
416 |
|
|
|
417 |
|
|
|
418 |
|
|
CH_HOST_IFCE_FULL_SPEED = 0x00
|
419 |
|
|
CH_HOST_IFCE_HIGH_SPEED = 0x01
|
420 |
|
|
def ch_host_ifce_speed (cheetah):
|
421 |
|
|
"""usage: int return = ch_host_ifce_speed(Cheetah cheetah)"""
|
422 |
|
|
|
423 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
424 |
|
|
# Call API function
|
425 |
|
|
return api.py_ch_host_ifce_speed(cheetah)
|
426 |
|
|
|
427 |
|
|
|
428 |
|
|
# Returns the device address that the beagle is attached to.
|
429 |
|
|
def ch_dev_addr (cheetah):
|
430 |
|
|
"""usage: int return = ch_dev_addr(Cheetah cheetah)"""
|
431 |
|
|
|
432 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
433 |
|
|
# Call API function
|
434 |
|
|
return api.py_ch_dev_addr(cheetah)
|
435 |
|
|
|
436 |
|
|
|
437 |
|
|
|
438 |
|
|
#==========================================================================
|
439 |
|
|
# SPI API
|
440 |
|
|
#==========================================================================
|
441 |
|
|
# Set the SPI bit rate in kilohertz.
|
442 |
|
|
def ch_spi_bitrate (cheetah, bitrate_khz):
|
443 |
|
|
"""usage: int return = ch_spi_bitrate(Cheetah cheetah, int bitrate_khz)"""
|
444 |
|
|
|
445 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
446 |
|
|
# Call API function
|
447 |
|
|
return api.py_ch_spi_bitrate(cheetah, bitrate_khz)
|
448 |
|
|
|
449 |
|
|
|
450 |
|
|
# These configuration parameters specify how to clock the
|
451 |
|
|
# bits that are sent and received on the Cheetah SPI
|
452 |
|
|
# interface.
|
453 |
|
|
#
|
454 |
|
|
# The polarity option specifies which transition
|
455 |
|
|
# constitutes the leading edge and which transition is the
|
456 |
|
|
# falling edge. For example, CH_SPI_POL_RISING_FALLING
|
457 |
|
|
# would configure the SPI to idle the SCK clock line low.
|
458 |
|
|
# The clock would then transition low-to-high on the
|
459 |
|
|
# leading edge and high-to-low on the trailing edge.
|
460 |
|
|
#
|
461 |
|
|
# The phase option determines whether to sample or setup on
|
462 |
|
|
# the leading edge. For example, CH_SPI_PHASE_SAMPLE_SETUP
|
463 |
|
|
# would configure the SPI to sample on the leading edge and
|
464 |
|
|
# setup on the trailing edge.
|
465 |
|
|
#
|
466 |
|
|
# The bitorder option is used to indicate whether LSB or
|
467 |
|
|
# MSB is shifted first.
|
468 |
|
|
#
|
469 |
|
|
# The SS polarity option is to indicate the polarity of the
|
470 |
|
|
# slave select pin (active high or active low). Each of
|
471 |
|
|
# the lower three bits of ss_polarity corresponds to each
|
472 |
|
|
# of the SS lines. Set the bit value for a given SS line
|
473 |
|
|
# to 0 for active low or 1 for active high.
|
474 |
|
|
# enum CheetahSpiPolarity
|
475 |
|
|
CH_SPI_POL_RISING_FALLING = 0
|
476 |
|
|
CH_SPI_POL_FALLING_RISING = 1
|
477 |
|
|
|
478 |
|
|
# enum CheetahSpiPhase
|
479 |
|
|
CH_SPI_PHASE_SAMPLE_SETUP = 0
|
480 |
|
|
CH_SPI_PHASE_SETUP_SAMPLE = 1
|
481 |
|
|
|
482 |
|
|
# enum CheetahSpiBitorder
|
483 |
|
|
CH_SPI_BITORDER_MSB = 0
|
484 |
|
|
CH_SPI_BITORDER_LSB = 1
|
485 |
|
|
|
486 |
|
|
# Configure the SPI master interface
|
487 |
|
|
def ch_spi_configure (cheetah, polarity, phase, bitorder, ss_polarity):
|
488 |
|
|
"""usage: int return = ch_spi_configure(Cheetah cheetah, CheetahSpiPolarity polarity, CheetahSpiPhase phase, CheetahSpiBitorder bitorder, u08 ss_polarity)"""
|
489 |
|
|
|
490 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
491 |
|
|
# Call API function
|
492 |
|
|
return api.py_ch_spi_configure(cheetah, polarity, phase, bitorder, ss_polarity)
|
493 |
|
|
|
494 |
|
|
|
495 |
|
|
# Clear the batch queue
|
496 |
|
|
def ch_spi_queue_clear (cheetah):
|
497 |
|
|
"""usage: int return = ch_spi_queue_clear(Cheetah cheetah)"""
|
498 |
|
|
|
499 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
500 |
|
|
# Call API function
|
501 |
|
|
return api.py_ch_spi_queue_clear(cheetah)
|
502 |
|
|
|
503 |
|
|
|
504 |
|
|
# Enable / disable the master outputs
|
505 |
|
|
def ch_spi_queue_oe (cheetah, oe):
|
506 |
|
|
"""usage: int return = ch_spi_queue_oe(Cheetah cheetah, u08 oe)"""
|
507 |
|
|
|
508 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
509 |
|
|
# Call API function
|
510 |
|
|
return api.py_ch_spi_queue_oe(cheetah, oe)
|
511 |
|
|
|
512 |
|
|
|
513 |
|
|
# Queue a delay in clock cycles
|
514 |
|
|
# The return value is the actual number of cycles queued.
|
515 |
|
|
def ch_spi_queue_delay_cycles (cheetah, cycles):
|
516 |
|
|
"""usage: int return = ch_spi_queue_delay_cycles(Cheetah cheetah, int cycles)"""
|
517 |
|
|
|
518 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
519 |
|
|
# Call API function
|
520 |
|
|
return api.py_ch_spi_queue_delay_cycles(cheetah, cycles)
|
521 |
|
|
|
522 |
|
|
|
523 |
|
|
# Queue a delay in nanoseconds
|
524 |
|
|
# The return value is the approximate number of nanoseconds queued.
|
525 |
|
|
def ch_spi_queue_delay_ns (cheetah, nanoseconds):
|
526 |
|
|
"""usage: int return = ch_spi_queue_delay_ns(Cheetah cheetah, int nanoseconds)"""
|
527 |
|
|
|
528 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
529 |
|
|
# Call API function
|
530 |
|
|
return api.py_ch_spi_queue_delay_ns(cheetah, nanoseconds)
|
531 |
|
|
|
532 |
|
|
|
533 |
|
|
# Assert the slave select lines. Each of the lower three
|
534 |
|
|
# bits of ss_polarity corresponds to each of the SS lines.
|
535 |
|
|
# Set the bit value for a given SS line to 1 to assert the
|
536 |
|
|
# line or 0 to deassert the line. The polarity is determined
|
537 |
|
|
# by ch_spi_configure() above.
|
538 |
|
|
def ch_spi_queue_ss (cheetah, active):
|
539 |
|
|
"""usage: int return = ch_spi_queue_ss(Cheetah cheetah, u08 active)"""
|
540 |
|
|
|
541 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
542 |
|
|
# Call API function
|
543 |
|
|
return api.py_ch_spi_queue_ss(cheetah, active)
|
544 |
|
|
|
545 |
|
|
|
546 |
|
|
# Repeatedly send a single byte
|
547 |
|
|
def ch_spi_queue_byte (cheetah, count, data):
|
548 |
|
|
"""usage: int return = ch_spi_queue_byte(Cheetah cheetah, int count, u08 data)"""
|
549 |
|
|
|
550 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
551 |
|
|
# Call API function
|
552 |
|
|
return api.py_ch_spi_queue_byte(cheetah, count, data)
|
553 |
|
|
|
554 |
|
|
|
555 |
|
|
# Send a byte array. Repeated bytes are automatically
|
556 |
|
|
# optimized into a repeated byte sequence.
|
557 |
|
|
def ch_spi_queue_array (cheetah, data_out):
|
558 |
|
|
"""usage: int return = ch_spi_queue_array(Cheetah cheetah, u08[] data_out)
|
559 |
|
|
|
560 |
|
|
All arrays can be passed into the API as an ArrayType object or as
|
561 |
|
|
a tuple (array, length), where array is an ArrayType object and
|
562 |
|
|
length is an integer. The user-specified length would then serve
|
563 |
|
|
as the length argument to the API funtion (please refer to the
|
564 |
|
|
product datasheet). If only the array is provided, the array's
|
565 |
|
|
intrinsic length is used as the argument to the underlying API
|
566 |
|
|
function."""
|
567 |
|
|
|
568 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
569 |
|
|
# data_out pre-processing
|
570 |
|
|
(data_out, num_bytes) = isinstance(data_out, ArrayType) and (data_out, len(data_out)) or (data_out[0], min(len(data_out[0]), int(data_out[1])))
|
571 |
|
|
if data_out.typecode != 'B':
|
572 |
|
|
raise TypeError("type for 'data_out' must be array('B')")
|
573 |
|
|
# Call API function
|
574 |
|
|
return api.py_ch_spi_queue_array(cheetah, num_bytes, data_out)
|
575 |
|
|
|
576 |
|
|
|
577 |
|
|
# Calculate the expected length of the returned data
|
578 |
|
|
def ch_spi_batch_length (cheetah):
|
579 |
|
|
"""usage: int return = ch_spi_batch_length(Cheetah cheetah)"""
|
580 |
|
|
|
581 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
582 |
|
|
# Call API function
|
583 |
|
|
return api.py_ch_spi_batch_length(cheetah)
|
584 |
|
|
|
585 |
|
|
|
586 |
|
|
# Perform the SPI shift operation.
|
587 |
|
|
#
|
588 |
|
|
# After the operation completes, the batch queue is untouched.
|
589 |
|
|
# Therefore, this function may be called repeatedly in rapid
|
590 |
|
|
# succession.
|
591 |
|
|
def ch_spi_batch_shift (cheetah, data_in):
|
592 |
|
|
"""usage: (int return, u08[] data_in) = ch_spi_batch_shift(Cheetah cheetah, u08[] data_in)
|
593 |
|
|
|
594 |
|
|
All arrays can be passed into the API as an ArrayType object or as
|
595 |
|
|
a tuple (array, length), where array is an ArrayType object and
|
596 |
|
|
length is an integer. The user-specified length would then serve
|
597 |
|
|
as the length argument to the API funtion (please refer to the
|
598 |
|
|
product datasheet). If only the array is provided, the array's
|
599 |
|
|
intrinsic length is used as the argument to the underlying API
|
600 |
|
|
function.
|
601 |
|
|
|
602 |
|
|
Additionally, for arrays that are filled by the API function, an
|
603 |
|
|
integer can be passed in place of the array argument and the API
|
604 |
|
|
will automatically create an array of that length. All output
|
605 |
|
|
arrays, whether passed in or generated, are passed back in the
|
606 |
|
|
returned tuple."""
|
607 |
|
|
|
608 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
609 |
|
|
# data_in pre-processing
|
610 |
|
|
__data_in = isinstance(data_in, int)
|
611 |
|
|
if __data_in:
|
612 |
|
|
(data_in, num_bytes) = (array_u08(data_in), data_in)
|
613 |
|
|
else:
|
614 |
|
|
(data_in, num_bytes) = isinstance(data_in, ArrayType) and (data_in, len(data_in)) or (data_in[0], min(len(data_in[0]), int(data_in[1])))
|
615 |
|
|
if data_in.typecode != 'B':
|
616 |
|
|
raise TypeError("type for 'data_in' must be array('B')")
|
617 |
|
|
# Call API function
|
618 |
|
|
(_ret_) = api.py_ch_spi_batch_shift(cheetah, num_bytes, data_in)
|
619 |
|
|
# data_in post-processing
|
620 |
|
|
if __data_in: del data_in[max(0, min(num_bytes, len(data_in))):]
|
621 |
|
|
return (_ret_, data_in)
|
622 |
|
|
|
623 |
|
|
|
624 |
|
|
# Queue the current batch queue for asynchronous shifting.
|
625 |
|
|
#
|
626 |
|
|
# After the operation completes, the batch queue is untouched.
|
627 |
|
|
# Therefore, this function may be called repeatedly in rapid
|
628 |
|
|
# succession.
|
629 |
|
|
def ch_spi_async_submit (cheetah):
|
630 |
|
|
"""usage: int return = ch_spi_async_submit(Cheetah cheetah)"""
|
631 |
|
|
|
632 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
633 |
|
|
# Call API function
|
634 |
|
|
return api.py_ch_spi_async_submit(cheetah)
|
635 |
|
|
|
636 |
|
|
|
637 |
|
|
# Collect an asynchronous batch that was previously submitted.
|
638 |
|
|
def ch_spi_async_collect (cheetah, data_in):
|
639 |
|
|
"""usage: (int return, u08[] data_in) = ch_spi_async_collect(Cheetah cheetah, u08[] data_in)
|
640 |
|
|
|
641 |
|
|
All arrays can be passed into the API as an ArrayType object or as
|
642 |
|
|
a tuple (array, length), where array is an ArrayType object and
|
643 |
|
|
length is an integer. The user-specified length would then serve
|
644 |
|
|
as the length argument to the API funtion (please refer to the
|
645 |
|
|
product datasheet). If only the array is provided, the array's
|
646 |
|
|
intrinsic length is used as the argument to the underlying API
|
647 |
|
|
function.
|
648 |
|
|
|
649 |
|
|
Additionally, for arrays that are filled by the API function, an
|
650 |
|
|
integer can be passed in place of the array argument and the API
|
651 |
|
|
will automatically create an array of that length. All output
|
652 |
|
|
arrays, whether passed in or generated, are passed back in the
|
653 |
|
|
returned tuple."""
|
654 |
|
|
|
655 |
|
|
if not CH_LIBRARY_LOADED: return CH_INCOMPATIBLE_LIBRARY
|
656 |
|
|
# data_in pre-processing
|
657 |
|
|
__data_in = isinstance(data_in, int)
|
658 |
|
|
if __data_in:
|
659 |
|
|
(data_in, num_bytes) = (array_u08(data_in), data_in)
|
660 |
|
|
else:
|
661 |
|
|
(data_in, num_bytes) = isinstance(data_in, ArrayType) and (data_in, len(data_in)) or (data_in[0], min(len(data_in[0]), int(data_in[1])))
|
662 |
|
|
if data_in.typecode != 'B':
|
663 |
|
|
raise TypeError("type for 'data_in' must be array('B')")
|
664 |
|
|
# Call API function
|
665 |
|
|
(_ret_) = api.py_ch_spi_async_collect(cheetah, num_bytes, data_in)
|
666 |
|
|
# data_in post-processing
|
667 |
|
|
if __data_in: del data_in[max(0, min(num_bytes, len(data_in))):]
|
668 |
|
|
return (_ret_, data_in)
|
669 |
|
|
|
670 |
|
|
|