123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972 |
- # -*- coding: utf-8 -*-
- #
- # AWL simulator - PiXtend hardware interface
- #
- # Copyright 2018 Michael Buesch <m@bues.ch>
- #
- # This program 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 program 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 this program; if not, write to the Free Software Foundation, Inc.,
- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- #
- from __future__ import division, absolute_import, print_function, unicode_literals
- #from awlsim.common.cython_support cimport * #@cy
- from awlsim.common.compat import *
- from awlsim.common.util import *
- from awlsim.common.enumeration import *
- from awlsim.common.exceptions import *
- from awlsim.common.datatypehelpers import * #+cimport
- __all__ = [
- "Relay",
- "DigitalOut",
- "DigitalIn",
- "GPIO",
- "EnvSensorBase",
- "TempIn",
- "HumIn",
- "AnalogIn",
- "AnalogOut",
- "PWM0Period",
- "PWM0",
- "PWM1Period",
- "PWM1",
- ]
- class AbstractIO(object): #+cdef
- """PiXtend abstract I/O handler.
- """
- setters = ()
- getters = ()
- def __init__(self, pixtend, isV2, index, bitOffset, directOnly=False, bitSize=1):
- """PiXtend I/O abstraction layer.
- pixtend: class Pixtend instance
- isV2: True, if 'pixtend' is V2.x.
- index: Index number of this I/O resource.
- e.g. 2 for DI2.
- bitOffset: The bit offset in the AWL E or A region this
- PiXtend resource is mapped to.
- directOnly: If False, then the resource is read/written in the
- user cycle and stored in or written to the process image
- region specified by bitOffset.
- If True, this resource is only accessible by
- direct PEx or PAx access only.
- bitSize: The size of this I/O instance, in bits.
- """
- self.pixtend = pixtend
- self.isV2 = isV2
- self.index = index
- self.byteOffset = bitOffset // 8
- self.bitOffset = bitOffset % 8
- self.directOnly = directOnly
- self.bitSize = bitSize
- self.byteSize = intDivRoundUp(self.bitSize, 8)
- def setup(self, secondaryOffset): #+cpdef
- self.byteOffset = max(self.byteOffset + secondaryOffset, 0)
- try:
- self.setter = self.setters[self.index]
- except IndexError:
- self.setter = None
- try:
- self.getter = self.getters[self.index]
- except IndexError:
- self.getter = None
- def set(self, dataBytes): #@nocy
- #@cy cdef set(self, bytearray dataBytes):
- self.setWithByteOffset(dataBytes, self.byteOffset)
- def setWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef setWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- raise NotImplementedError
- def get(self, dataBytes): #@nocy
- #@cy cdef get(self, bytearray dataBytes):
- self.getWithByteOffset(dataBytes, self.byteOffset)
- def getWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef getWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- raise NotImplementedError
- class AbstractBitIO(AbstractIO): #+cdef
- """PiXtend abstract bit I/O handler.
- """
- def __init__(self, *args, **kwargs):
- AbstractIO.__init__(self, *args, bitSize=1, **kwargs)
- def setup(self, secondaryOffset): #+cpdef
- AbstractIO.setup(self, secondaryOffset)
- self.bitMask = 1 << self.bitOffset
- self.invBitMask = (~self.bitMask) & 0xFF
- def setWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef setWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- self.setter(self, (dataBytes[byteOffset] >> self.bitOffset) & 1)
- def getWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef getWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- if self.getter(self):
- dataBytes[byteOffset] |= self.bitMask
- else:
- dataBytes[byteOffset] &= self.invBitMask
- class AbstractWordIO(AbstractIO): #+cdef
- """PiXtend abstract word I/O handler.
- """
- def __init__(self, *args, **kwargs):
- AbstractIO.__init__(self, *args, bitSize=16, **kwargs)
- def setWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef setWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- self.setter(self,
- (dataBytes[byteOffset] << 8) |\
- (dataBytes[byteOffset + 1]))
- def getWithByteOffset(self, dataBytes, byteOffset): #@nocy
- #@cy cdef getWithByteOffset(self, bytearray dataBytes, uint32_t byteOffset):
- #@cy cdef uint16_t value
- value = self.getter(self)
- dataBytes[byteOffset] = (value >> 8) & 0xFF
- dataBytes[byteOffset + 1] = value & 0xFF
- class Relay(AbstractBitIO): #+cdef
- """PiXtend relay I/O handler.
- """
- def __setRelay0(self, state):
- pixtend = self.pixtend
- pixtend.relay0 = pixtend.ON if state else pixtend.OFF
- def __setRelay1(self, state):
- pixtend = self.pixtend
- pixtend.relay1 = pixtend.ON if state else pixtend.OFF
- def __setRelay2(self, state):
- pixtend = self.pixtend
- pixtend.relay2 = pixtend.ON if state else pixtend.OFF
- def __setRelay3(self, state):
- pixtend = self.pixtend
- pixtend.relay3 = pixtend.ON if state else pixtend.OFF
- setters = (
- __setRelay0,
- __setRelay1,
- __setRelay2,
- __setRelay3,
- )
- class DigitalOut(AbstractBitIO): #+cdef
- """PiXtend digital output I/O handler.
- """
- def __setDO0(self, state):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.digital_out0 = pixtend.ON if state else pixtend.OFF
- else:
- pixtend.digital_output0 = pixtend.ON if state else pixtend.OFF
- def __setDO1(self, state):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.digital_out1 = pixtend.ON if state else pixtend.OFF
- else:
- pixtend.digital_output1 = pixtend.ON if state else pixtend.OFF
- def __setDO2(self, state):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.digital_out2 = pixtend.ON if state else pixtend.OFF
- else:
- pixtend.digital_output2 = pixtend.ON if state else pixtend.OFF
- def __setDO3(self, state):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.digital_out3 = pixtend.ON if state else pixtend.OFF
- else:
- pixtend.digital_output3 = pixtend.ON if state else pixtend.OFF
- def __setDO4(self, state):
- pixtend = self.pixtend
- if self.isV2:
- assert(0)
- else:
- pixtend.digital_output4 = pixtend.ON if state else pixtend.OFF
- def __setDO5(self, state):
- pixtend = self.pixtend
- if self.isV2:
- assert(0)
- else:
- pixtend.digital_output5 = pixtend.ON if state else pixtend.OFF
- setters = (
- __setDO0,
- __setDO1,
- __setDO2,
- __setDO3,
- __setDO4,
- __setDO5,
- )
- class DigitalIn(AbstractBitIO): #+cdef
- """PiXtend digital input I/O handler.
- """
- def __getDI0(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in0 == pixtend.ON else 0
- return 1 if pixtend.digital_input0 == pixtend.ON else 0
- def __getDI1(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in1 == pixtend.ON else 0
- return 1 if pixtend.digital_input1 == pixtend.ON else 0
- def __getDI2(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in2 == pixtend.ON else 0
- return 1 if pixtend.digital_input2 == pixtend.ON else 0
- def __getDI3(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in3 == pixtend.ON else 0
- return 1 if pixtend.digital_input3 == pixtend.ON else 0
- def __getDI4(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in4 == pixtend.ON else 0
- return 1 if pixtend.digital_input4 == pixtend.ON else 0
- def __getDI5(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in5 == pixtend.ON else 0
- return 1 if pixtend.digital_input5 == pixtend.ON else 0
- def __getDI6(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in6 == pixtend.ON else 0
- return 1 if pixtend.digital_input6 == pixtend.ON else 0
- def __getDI7(self):
- pixtend = self.pixtend
- if self.isV2:
- return 1 if pixtend.digital_in7 == pixtend.ON else 0
- return 1 if pixtend.digital_input7 == pixtend.ON else 0
- getters = (
- __getDI0,
- __getDI1,
- __getDI2,
- __getDI3,
- __getDI4,
- __getDI5,
- __getDI6,
- __getDI7,
- )
- class GPIO(AbstractBitIO): #+cdef
- """PiXtend GPIO I/O handler.
- """
- EnumGen.start
- MODE_OUTPUT = EnumGen.item
- MODE_INPUT = EnumGen.item
- MODE_DHT11 = EnumGen.item
- MODE_DHT22 = EnumGen.item
- EnumGen.end
- def __init__(self, *args, **kwargs):
- AbstractBitIO.__init__(self, *args, **kwargs)
- self.mode = None
- self.pullUp = None
- def __getGPIO0(self):
- pixtend = self.pixtend
- return 1 if pixtend.gpio0 == pixtend.ON else 0
- def __getGPIO1(self):
- pixtend = self.pixtend
- return 1 if pixtend.gpio1 == pixtend.ON else 0
- def __getGPIO2(self):
- pixtend = self.pixtend
- return 1 if pixtend.gpio2 == pixtend.ON else 0
- def __getGPIO3(self):
- pixtend = self.pixtend
- return 1 if pixtend.gpio3 == pixtend.ON else 0
- getters = (
- __getGPIO0,
- __getGPIO1,
- __getGPIO2,
- __getGPIO3,
- )
- def __setGPIO0(self, state):
- pixtend = self.pixtend
- pixtend.gpio0 = pixtend.ON if state else pixtend.OFF
- def __setGPIO1(self, state):
- pixtend = self.pixtend
- pixtend.gpio1 = pixtend.ON if state else pixtend.OFF
- def __setGPIO2(self, state):
- pixtend = self.pixtend
- pixtend.gpio2 = pixtend.ON if state else pixtend.OFF
- def __setGPIO3(self, state):
- pixtend = self.pixtend
- pixtend.gpio3 = pixtend.ON if state else pixtend.OFF
- setters = (
- __setGPIO0,
- __setGPIO1,
- __setGPIO2,
- __setGPIO3,
- )
- def __getV2Ctrl(self, mode):
- pixtend = self.pixtend
- ctrlValue = {
- self.MODE_OUTPUT : pixtend.GPIO_OUTPUT,
- self.MODE_INPUT : pixtend.GPIO_INPUT,
- self.MODE_DHT11 : pixtend.GPIO_DHT11,
- self.MODE_DHT22 : pixtend.GPIO_DHT22,
- }[mode]
- return ctrlValue
- def __getV1Dir(self, mode):
- pixtend = self.pixtend
- if mode == self.MODE_OUTPUT:
- return pixtend.GPIO_OUTPUT
- return pixtend.GPIO_INPUT
- def __getV1DHTOn(self, mode):
- pixtend = self.pixtend
- if mode in {self.MODE_DHT11, self.MODE_DHT22}:
- return pixtend.ON
- return pixtend.OFF
- def __setModeGPIO0(self, mode):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.gpio0_ctrl = self.__getV2Ctrl(mode)
- else:
- pixtend.gpio0_direction = self.__getV1Dir(mode)
- pixtend.dht0 = self.__getV1DHTOn(mode)
- def __setModeGPIO1(self, mode):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.gpio1_ctrl = self.__getV2Ctrl(mode)
- else:
- pixtend.gpio1_direction = self.__getV1Dir(mode)
- pixtend.dht1 = self.__getV1DHTOn(mode)
- def __setModeGPIO2(self, mode):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.gpio2_ctrl = self.__getV2Ctrl(mode)
- else:
- pixtend.gpio2_direction = self.__getV1Dir(mode)
- pixtend.dht2 = self.__getV1DHTOn(mode)
- def __setModeGPIO3(self, mode):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.gpio3_ctrl = self.__getV2Ctrl(mode)
- else:
- pixtend.gpio3_direction = self.__getV1Dir(mode)
- pixtend.dht3 = self.__getV1DHTOn(mode)
- settersMode = (
- __setModeGPIO0,
- __setModeGPIO1,
- __setModeGPIO2,
- __setModeGPIO3,
- )
- def __setPullUp0(self, state):
- pixtend = self.pixtend
- if self.isV2:
- if pixtend.gpio_pullups_enable:
- pixtend.gpio0 = pixtend.ON if state else pixtend.OFF
- def __setPullUp1(self, state):
- pixtend = self.pixtend
- if self.isV2:
- if pixtend.gpio_pullups_enable:
- pixtend.gpio1 = pixtend.ON if state else pixtend.OFF
- def __setPullUp2(self, state):
- pixtend = self.pixtend
- if self.isV2:
- if pixtend.gpio_pullups_enable:
- pixtend.gpio2 = pixtend.ON if state else pixtend.OFF
- def __setPullUp3(self, state):
- pixtend = self.pixtend
- if self.isV2:
- if pixtend.gpio_pullups_enable:
- pixtend.gpio3 = pixtend.ON if state else pixtend.OFF
- settersPullUp = (
- __setPullUp0,
- __setPullUp1,
- __setPullUp2,
- __setPullUp3,
- )
- @staticmethod
- def setGlobalPullUpEnable(pixtend, isV2, pullUpEnable):
- if isV2:
- pixtend.gpio_pullups_enable = pixtend.ON if pullUpEnable else pixtend.OFF
- def setup(self, secondaryOffset): #+cpdef
- AbstractBitIO.setup(self, secondaryOffset)
- if self.mode is not None:
- setMode = self.settersMode[self.index]
- setMode(self, self.mode)
- if self.pullUp is not None:
- setPullUp = self.settersPullUp[self.index]
- setPullUp(self, self.pixtend.ON if self.pullUp
- else self.pixtend.OFF)
- class EnvSensorBase(AbstractWordIO): #+cdef
- """Environmental sensor base class.
- """
- EnumGen.start
- TYPE_DHT11 = EnumGen.item
- TYPE_DHT22 = EnumGen.item
- EnumGen.end
- def __init__(self, sensorType, *args, **kwargs):
- AbstractWordIO.__init__(self, *args, **kwargs)
- self.sensorType = sensorType
- # Create a child GPIO object.
- gpioMode = {
- self.TYPE_DHT11 : GPIO.MODE_DHT11,
- self.TYPE_DHT22 : GPIO.MODE_DHT22,
- }[self.sensorType]
- self.gpio = GPIO(self.pixtend, self.isV2, self.index, 0, True)
- self.gpio.mode = gpioMode
- def setup(self, secondaryOffset): #+cpdef
- AbstractWordIO.setup(self, secondaryOffset)
- # Configure the child GPIO object.
- self.gpio.setup(secondaryOffset)
- #TODO Fahrenheit
- class TempIn(EnvSensorBase): #+cdef
- """DHT11/DHT22 temperature input.
- """
- def __convert(self, temp): #@nocy
- #@cy cdef uint16_t __convert(self, double temp):
- return max(min(int(round(temp * 10.0)), 8500), -2000) & 0xFFFF
- def __getTemp0(self):
- if self.isV2:
- return self.__convert(self.pixtend.temp0)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.t0_dht11)
- return self.__convert(self.pixtend.t0_dht22)
- def __getTemp1(self):
- if self.isV2:
- return self.__convert(self.pixtend.temp1)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.t1_dht11)
- return self.__convert(self.pixtend.t1_dht22)
- def __getTemp2(self):
- if self.isV2:
- return self.__convert(self.pixtend.temp2)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.t2_dht11)
- return self.__convert(self.pixtend.t2_dht22)
- def __getTemp3(self):
- if self.isV2:
- return self.__convert(self.pixtend.temp3)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.t3_dht11)
- return self.__convert(self.pixtend.t3_dht22)
- getters = (
- __getTemp0,
- __getTemp1,
- __getTemp2,
- __getTemp3,
- )
- class HumIn(EnvSensorBase): #+cdef
- """DHT11/DHT22 humidity input.
- """
- def __convert(self, hum): #@nocy
- #@cy cdef uint16_t __convert(self, double hum):
- return max(min(int(round(hum * 10.0)), 1000), 0)
- def __getHum0(self):
- if self.isV2:
- return self.__convert(self.pixtend.humid0)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.h0_dht11)
- return self.__convert(self.pixtend.h0_dht22)
- def __getHum1(self):
- if self.isV2:
- return self.__convert(self.pixtend.humid1)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.h1_dht11)
- return self.__convert(self.pixtend.h1_dht22)
- def __getHum2(self):
- if self.isV2:
- return self.__convert(self.pixtend.humid2)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.h2_dht11)
- return self.__convert(self.pixtend.h2_dht22)
- def __getHum3(self):
- if self.isV2:
- return self.__convert(self.pixtend.humid3)
- if self.sensorType == self.TYPE_DHT11:
- return self.__convert(self.pixtend.h3_dht11)
- return self.__convert(self.pixtend.h3_dht22)
- getters = (
- __getHum0,
- __getHum1,
- __getHum2,
- __getHum3,
- )
- class AnalogIn(AbstractWordIO): #+cdef
- """PiXtend analog input I/O handler.
- """
- def __init__(self, *args, **kwargs):
- AbstractWordIO.__init__(self, *args, **kwargs)
- self.jumper10V = None
- self.numberOfSamples = None
- def __convertV(self, V): #@nocy
- #@cy cdef uint16_t __convertV(self, double V):
- return max(min(int(round(V * 2764.8)), 32767), -32768)
- def __convertMA(self, mA): #@nocy
- #@cy cdef uint16_t __convertMA(self, double mA):
- return max(min(int(round((mA - 4.0) * 1728.0)), 32767), -32768)
- def __getAI0(self):
- if self.isV2:
- return self.__convertV(self.pixtend.analog_in0)
- return self.__convertV(self.pixtend.analog_input0)
- def __getAI1(self):
- if self.isV2:
- return self.__convertV(self.pixtend.analog_in1)
- return self.__convertV(self.pixtend.analog_input1)
- def __getAI2(self):
- if self.isV2:
- assert(0)
- return 0
- return self.__convertMA(self.pixtend.analog_input2)
- def __getAI3(self):
- if self.isV2:
- assert(0)
- return 0
- return self.__convertMA(self.pixtend.analog_input3)
- getters = (
- __getAI0,
- __getAI1,
- __getAI2,
- __getAI3,
- )
- def __setJumper10V_AI0(self, jumper10V):
- pixtend = self.pixtend
- value = pixtend.ON if jumper10V else pixtend.OFF
- if self.isV2:
- pixtend.jumper_setting_ai0 = value
- else:
- pixtend.analog_input0_10volts_jumper = value
- def __setJumper10V_AI1(self, jumper10V):
- pixtend = self.pixtend
- value = pixtend.ON if jumper10V else pixtend.OFF
- if self.isV2:
- pixtend.jumper_setting_ai1 = value
- else:
- pixtend.analog_input1_10volts_jumper = value
- settersJumper10V = (
- __setJumper10V_AI0,
- __setJumper10V_AI1,
- )
- def __setNos_AI0(self, nos):
- if not self.isV2:
- self.pixtend.analog_input0_nos = nos
- def __setNos_AI1(self, nos):
- if not self.isV2:
- self.pixtend.analog_input1_nos = nos
- def __setNos_AI2(self, nos):
- if not self.isV2:
- self.pixtend.analog_input2_nos = nos
- def __setNos_AI3(self, nos):
- if not self.isV2:
- self.pixtend.analog_input3_nos = nos
- settersNos = (
- __setNos_AI0,
- __setNos_AI1,
- __setNos_AI2,
- __setNos_AI3,
- )
- @staticmethod
- def setFreq(pixtend, isV2, freqKHz):
- if isV2:
- return
- kHz2MHz = {
- 125 : 0.125,
- 250 : 0.250,
- 500 : 0.500,
- 1000 : 1.0,
- 2000 : 2.0,
- 4000 : 4.0,
- 8000 : 8.0,
- }
- try:
- freqMHz = kHz2MHz[freqKHz]
- except KeyError as e:
- raise ValueError
- pixtend.analog_input_nos_freq = freqMHz
- def setup(self, secondaryOffset): #+cpdef
- AbstractWordIO.setup(self, secondaryOffset)
- if self.jumper10V is not None:
- setJumper10V = self.settersJumper10V[self.index]
- setJumper10V(self, self.pixtend.ON if self.jumper10V
- else self.pixtend.OFF)
- if self.numberOfSamples is not None:
- setNos = self.settersNos[self.index]
- setNos(self, self.numberOfSamples)
- class AnalogOut(AbstractWordIO): #+cdef
- """PiXtend analog output I/O handler.
- """
- def __convert(self, s7Value): #@nocy
- #@cy cdef uint16_t __convert(self, uint16_t s7Value):
- # dac = (s7Value / 27648) * 1023
- return clamp(int(round((wordToSignedPyInt(s7Value) * 1023) / 27648)),
- 0, 1023)
- def __setAO0(self, value):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.set_dac_output(pixtend.DAC_A, self.__convert(value))
- else:
- pixtend.dac_selection = pixtend.DAC_A
- pixtend.set_dac_output(self.__convert(value))
- def __setAO1(self, value):
- pixtend = self.pixtend
- if self.isV2:
- pixtend.set_dac_output(pixtend.DAC_B, self.__convert(value))
- else:
- pixtend.dac_selection = pixtend.DAC_B
- pixtend.set_dac_output(self.__convert(value))
- setters = (
- __setAO0,
- __setAO1,
- )
- class PWM0Period(AbstractWordIO): #+cdef
- """PiXtend PWM0 period I/O handler.
- """
- def setPWMPeriod(self, period):
- if self.isV2:
- self.pixtend.pwm0_ctrl1 = clamp(period, 0, 65535)
- else:
- self.pixtend.pwm_ctrl_period = clamp(period, 0, 65000)
- self.pixtend.pwm_ctrl_configure()
- setters = (
- setPWMPeriod,
- )
- @staticmethod
- def setBaseFreq(pixtend, isV2, freqHz):
- cpuHz = 16000000
- csMap = {
- 0 : (0, 0, 0), # PS=off
- cpuHz // 1 : (0, 0, 1), # PS=1
- cpuHz // 8 : (0, 1, 0), # PS=8
- cpuHz // 64 : (0, 1, 1), # PS=64
- cpuHz // 256 : (1, 0, 0), # PS=256
- cpuHz // 1024 : (1, 0, 1), # PS=1024
- }
- try:
- cs2, cs1, cs0 = csMap[freqHz]
- except KeyError as e:
- raise ValueError
- if isV2:
- ctrl0 = pixtend.pwm0_ctrl0
- ctrl0 &= ~((1 << 5) | (1 << 6) | (1 << 7))
- ctrl0 |= (cs0 << 5) | (cs1 << 6) | (cs2 << 7)
- if freqHz == 0:
- ctrl0 &= ~((1 << 3) | (1 << 4)) # Disable A and B
- pixtend.pwm0_ctrl0 = ctrl0 & 0xFF
- else:
- pixtend.pwm_ctrl_cs0 = cs0
- pixtend.pwm_ctrl_cs1 = cs1
- pixtend.pwm_ctrl_cs2 = cs2
- pixtend.pwm_ctrl_configure()
- class PWM0(AbstractWordIO): #+cdef
- """PiXtend PWM0 output I/O handler.
- """
- def __init__(self, *args, **kwargs):
- AbstractWordIO.__init__(self, *args, **kwargs)
- self.enabled = False
- self.servoMode = False
- def __setPWMA(self, value):
- if self.enabled:
- if self.servoMode:
- if self.isV2:
- self.pixtend.servo0 = clamp(value, 0, 16000)
- else:
- self.pixtend.servo0 = clamp(value, 0, 250)
- else:
- if self.isV2:
- self.pixtend.pwm0a = clamp(value, 0, 65535)
- else:
- self.pixtend.pwm0 = clamp(value, 0, 65000)
- def __setPWMB(self, value):
- if self.enabled:
- if self.servoMode:
- if self.isV2:
- self.pixtend.servo1 = clamp(value, 0, 16000)
- else:
- self.pixtend.servo1 = clamp(value, 0, 250)
- else:
- if self.isV2:
- self.pixtend.pwm0b = clamp(value, 0, 65535)
- else:
- self.pixtend.pwm1 = clamp(value, 0, 65000)
- setters = (
- __setPWMA,
- __setPWMB,
- )
- @staticmethod
- def setServoMode(pixtend, isV2, enServoMode):
- if isV2:
- ctrl0 = pixtend.pwm0_ctrl0
- ctrl0 &= ~((1 << 0) | (1 << 1))
- if not enServoMode:
- ctrl0 |= 1 << 0
- pixtend.pwm0_ctrl0 = ctrl0
- else:
- pixtend.pwm_ctrl_mode = 0 if enServoMode else 1
- pixtend.pwm_ctrl_configure()
- def __doSetEnabled(self, enabled, bitNr):
- self.enabled = enabled
- if self.isV2:
- ctrl0 = self.pixtend.pwm0_ctrl0
- ctrl0 &= ~(1 << bitNr)
- if enabled:
- ctrl0 |= (1 << bitNr)
- self.pixtend.pwm0_ctrl0 = ctrl0
- def __setEnabled0(self, enabled):
- self.__doSetEnabled(enabled, 3)
- def __setEnabled1(self, enabled):
- self.__doSetEnabled(enabled, 4)
- settersEnabled = (
- __setEnabled0,
- __setEnabled1,
- )
- def setup(self, secondaryOffset): #+cpdef
- AbstractWordIO.setup(self, secondaryOffset)
- setEnabled = self.settersEnabled[self.index]
- setEnabled(self, self.enabled)
- class PWM1Period(AbstractWordIO): #+cdef
- """PiXtend PWM1 period I/O handler. (v2.x only)
- """
- def setPWMPeriod(self, period):
- if self.isV2:
- self.pixtend.pwm1_ctrl1 = clamp(period, 0, 255)
- else:
- assert(0)
- setters = (
- setPWMPeriod,
- )
- @staticmethod
- def setBaseFreq(pixtend, freqHz):
- cpuHz = 16000000
- csMap = {
- 0 : (0, 0, 0), # PS=off
- cpuHz // 1 : (0, 0, 1), # PS=1
- cpuHz // 8 : (0, 1, 0), # PS=8
- cpuHz // 32 : (0, 1, 1), # PS=32
- cpuHz // 64 : (1, 0, 0), # PS=64
- cpuHz // 128 : (1, 0, 1), # PS=128
- cpuHz // 256 : (1, 1, 0), # PS=256
- cpuHz // 1024 : (1, 1, 1), # PS=1024
- }
- try:
- cs2, cs1, cs0 = csMap[freqHz]
- except KeyError as e:
- raise ValueError
- ctrl0 = pixtend.pwm1_ctrl0
- ctrl0 &= ~((1 << 5) | (1 << 6) | (1 << 7))
- ctrl0 |= (cs0 << 5) | (cs1 << 6) | (cs2 << 7)
- if freqHz == 0:
- ctrl0 &= ~((1 << 3) | (1 << 4)) # Disable A and B
- pixtend.pwm1_ctrl0 = ctrl0 & 0xFF
- class PWM1(AbstractWordIO): #+cdef
- """PiXtend PWM1 output I/O handler. (v2.x only)
- """
- def __init__(self, *args, **kwargs):
- AbstractWordIO.__init__(self, *args, **kwargs)
- self.enabled = False
- self.servoMode = False
- def __setPWMA(self, value):
- if self.enabled:
- if self.servoMode:
- if self.isV2:
- self.pixtend.servo2 = clamp(value, 0, 125)
- else:
- assert(0)
- else:
- if self.isV2:
- self.pixtend.pwm1a = clamp(value, 0, 255)
- else:
- assert(0)
- def __setPWMB(self, value):
- if self.enabled:
- if self.servoMode:
- if self.isV2:
- self.pixtend.servo3 = clamp(value, 0, 125)
- else:
- assert(0)
- else:
- if self.isV2:
- self.pixtend.pwm1b = clamp(value, 0, 255)
- else:
- assert(0)
- setters = (
- __setPWMA,
- __setPWMB,
- )
- @staticmethod
- def setServoMode(pixtend, enServoMode):
- ctrl0 = pixtend.pwm1_ctrl0
- ctrl0 &= ~((1 << 0) | (1 << 1))
- if not enServoMode:
- ctrl0 |= 1 << 0
- pixtend.pwm1_ctrl0 = ctrl0
- def __doSetEnabled(self, enabled, bitNr):
- self.enabled = enabled
- if self.isV2:
- ctrl0 = self.pixtend.pwm1_ctrl0
- ctrl0 &= ~(1 << bitNr)
- if enabled:
- ctrl0 |= (1 << bitNr)
- self.pixtend.pwm1_ctrl0 = ctrl0
- else:
- assert(0)
- def __setEnabled0(self, enabled):
- self.__doSetEnabled(enabled, 3)
- def __setEnabled1(self, enabled):
- self.__doSetEnabled(enabled, 4)
- settersEnabled = (
- __setEnabled0,
- __setEnabled1,
- )
- def setup(self, secondaryOffset): #+cpdef
- AbstractWordIO.setup(self, secondaryOffset)
- setEnabled = self.settersEnabled[self.index]
- setEnabled(self, self.enabled)
|