mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	| @@ -8,6 +8,11 @@ from __future__ import ( | ||||
| from .pins import ( | ||||
|     Pin, | ||||
| ) | ||||
| from .pins.data import ( | ||||
|     PiBoardInfo, | ||||
|     PinInfo, | ||||
|     pi_info, | ||||
| ) | ||||
| from .exc import ( | ||||
|     GPIOZeroError, | ||||
|     DeviceClosed, | ||||
| @@ -38,6 +43,9 @@ from .exc import ( | ||||
|     PinPWMError, | ||||
|     PinPWMUnsupported, | ||||
|     PinPWMFixedValue, | ||||
|     PinUnknownPi, | ||||
|     PinMultiplePins, | ||||
|     PinNoPins, | ||||
|     GPIOZeroWarning, | ||||
|     SPIWarning, | ||||
|     SPISoftwareFallback, | ||||
|   | ||||
| @@ -100,6 +100,15 @@ class PinPWMUnsupported(PinPWMError, AttributeError): | ||||
| class PinPWMFixedValue(PinPWMError, AttributeError): | ||||
|     "Error raised when attempting to initialize PWM on an input pin" | ||||
|  | ||||
| class PinUnknownPi(PinError, RuntimeError): | ||||
|     "Error raised when gpiozero doesn't recognize a revision of the Pi" | ||||
|  | ||||
| class PinMultiplePins(PinError, RuntimeError): | ||||
|     "Error raised when multiple pins support the requested function" | ||||
|  | ||||
| class PinNoPins(PinError, RuntimeError): | ||||
|     "Error raised when no pins support the requested function" | ||||
|  | ||||
| class GPIOZeroWarning(Warning): | ||||
|     "Base class for all warnings in GPIO Zero" | ||||
|  | ||||
|   | ||||
							
								
								
									
										696
									
								
								gpiozero/pins/data.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										696
									
								
								gpiozero/pins/data.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,696 @@ | ||||
| from __future__ import ( | ||||
|     unicode_literals, | ||||
|     absolute_import, | ||||
|     print_function, | ||||
|     division, | ||||
|     ) | ||||
| str = type('') | ||||
|  | ||||
| import io | ||||
| from collections import namedtuple | ||||
|  | ||||
| from ..exc import PinUnknownPi, PinMultiplePins | ||||
|  | ||||
|  | ||||
| # Some useful constants for describing pins | ||||
|  | ||||
| V1_8   = '1V8' | ||||
| V3_3   = '3V3' | ||||
| V5     = '5V' | ||||
| GND    = 'GND' | ||||
| NC     = 'NC' # not connected | ||||
| GPIO0  = 'GPIO0' | ||||
| GPIO1  = 'GPIO1' | ||||
| GPIO2  = 'GPIO2' | ||||
| GPIO3  = 'GPIO3' | ||||
| GPIO4  = 'GPIO4' | ||||
| GPIO5  = 'GPIO5' | ||||
| GPIO6  = 'GPIO6' | ||||
| GPIO7  = 'GPIO7' | ||||
| GPIO8  = 'GPIO8' | ||||
| GPIO9  = 'GPIO9' | ||||
| GPIO10 = 'GPIO10' | ||||
| GPIO11 = 'GPIO11' | ||||
| GPIO12 = 'GPIO12' | ||||
| GPIO13 = 'GPIO13' | ||||
| GPIO14 = 'GPIO14' | ||||
| GPIO15 = 'GPIO15' | ||||
| GPIO16 = 'GPIO16' | ||||
| GPIO17 = 'GPIO17' | ||||
| GPIO18 = 'GPIO18' | ||||
| GPIO19 = 'GPIO19' | ||||
| GPIO20 = 'GPIO20' | ||||
| GPIO21 = 'GPIO21' | ||||
| GPIO22 = 'GPIO22' | ||||
| GPIO23 = 'GPIO23' | ||||
| GPIO24 = 'GPIO24' | ||||
| GPIO25 = 'GPIO25' | ||||
| GPIO26 = 'GPIO26' | ||||
| GPIO27 = 'GPIO27' | ||||
| GPIO28 = 'GPIO28' | ||||
| GPIO29 = 'GPIO29' | ||||
| GPIO30 = 'GPIO30' | ||||
| GPIO31 = 'GPIO31' | ||||
| GPIO32 = 'GPIO32' | ||||
| GPIO33 = 'GPIO33' | ||||
| GPIO34 = 'GPIO34' | ||||
| GPIO35 = 'GPIO35' | ||||
| GPIO36 = 'GPIO36' | ||||
| GPIO37 = 'GPIO37' | ||||
| GPIO38 = 'GPIO38' | ||||
| GPIO39 = 'GPIO39' | ||||
| GPIO40 = 'GPIO40' | ||||
| GPIO41 = 'GPIO41' | ||||
| GPIO42 = 'GPIO42' | ||||
| GPIO43 = 'GPIO43' | ||||
| GPIO44 = 'GPIO44' | ||||
| GPIO45 = 'GPIO45' | ||||
|  | ||||
| # Pin maps for various board revisions and headers | ||||
|  | ||||
| REV1_P1 = { | ||||
| #   pin  func  pullup  pin  func  pullup | ||||
|     1:  (V3_3,   False), 2:  (V5,     False), | ||||
|     3:  (GPIO0,  True),  4:  (V5,     False), | ||||
|     5:  (GPIO1,  True),  6:  (GND,    False), | ||||
|     7:  (GPIO4,  False), 8:  (GPIO14, False), | ||||
|     9:  (GND,    False), 10: (GPIO15, False), | ||||
|     11: (GPIO17, False), 12: (GPIO18, False), | ||||
|     13: (GPIO21, False), 14: (GND,    False), | ||||
|     15: (GPIO22, False), 16: (GPIO23, False), | ||||
|     17: (V3_3,   False), 18: (GPIO24, False), | ||||
|     19: (GPIO10, False), 20: (GND,    False), | ||||
|     21: (GPIO9,  False), 22: (GPIO25, False), | ||||
|     23: (GPIO11, False), 24: (GPIO8,  False), | ||||
|     25: (GND,    False), 26: (GPIO7,  False), | ||||
|     } | ||||
|  | ||||
| REV2_P1 = { | ||||
|     1:  (V3_3,   False), 2:  (V5,     False), | ||||
|     3:  (GPIO2,  True),  4:  (V5,     False), | ||||
|     5:  (GPIO3,  True),  6:  (GND,    False), | ||||
|     7:  (GPIO4,  False), 8:  (GPIO14, False), | ||||
|     9:  (GND,    False), 10: (GPIO15, False), | ||||
|     11: (GPIO17, False), 12: (GPIO18, False), | ||||
|     13: (GPIO27, False), 14: (GND,    False), | ||||
|     15: (GPIO22, False), 16: (GPIO23, False), | ||||
|     17: (V3_3,   False), 18: (GPIO24, False), | ||||
|     19: (GPIO10, False), 20: (GND,    False), | ||||
|     21: (GPIO9,  False), 22: (GPIO25, False), | ||||
|     23: (GPIO11, False), 24: (GPIO8,  False), | ||||
|     25: (GND,    False), 26: (GPIO7,  False), | ||||
|     } | ||||
|  | ||||
| REV2_P5 = { | ||||
|     1:  (V5,     False), 2:  (V3_3,   False), | ||||
|     3:  (GPIO28, False), 4:  (GPIO29, False), | ||||
|     5:  (GPIO30, False), 6:  (GPIO31, False), | ||||
|     7:  (GND,    False), 8:  (GND,    False), | ||||
|     } | ||||
|  | ||||
| PLUS_P1 = { | ||||
|     1:  (V3_3,   False), 2:  (V5,     False), | ||||
|     3:  (GPIO2,  True),  4:  (V5,     False), | ||||
|     5:  (GPIO3,  True),  6:  (GND,    False), | ||||
|     7:  (GPIO4,  False), 8:  (GPIO14, False), | ||||
|     9:  (GND,    False), 10: (GPIO15, False), | ||||
|     11: (GPIO17, False), 12: (GPIO18, False), | ||||
|     13: (GPIO27, False), 14: (GND,    False), | ||||
|     15: (GPIO22, False), 16: (GPIO23, False), | ||||
|     17: (V3_3,   False), 18: (GPIO24, False), | ||||
|     19: (GPIO10, False), 20: (GND,    False), | ||||
|     21: (GPIO9,  False), 22: (GPIO25, False), | ||||
|     23: (GPIO11, False), 24: (GPIO8,  False), | ||||
|     25: (GND,    False), 26: (GPIO7,  False), | ||||
|     27: (GPIO0,  False), 28: (GPIO1,  False), | ||||
|     29: (GPIO5,  False), 30: (GND,    False), | ||||
|     31: (GPIO6,  False), 32: (GPIO12, False), | ||||
|     33: (GPIO13, False), 34: (GND,    False), | ||||
|     35: (GPIO19, False), 36: (GPIO16, False), | ||||
|     37: (GPIO26, False), 38: (GPIO20, False), | ||||
|     39: (GND,    False), 40: (GPIO21, False), | ||||
|     } | ||||
|  | ||||
| CM_SODIMM = { | ||||
|     1:   (GND,              False), 2:   ('EMMC DISABLE N', False), | ||||
|     3:   (GPIO0,            False), 4:   (NC,               False), | ||||
|     5:   (GPIO1,            False), 6:   (NC,               False), | ||||
|     7:   (GND,              False), 8:   (NC,               False), | ||||
|     9:   (GPIO2,            False), 10:  (NC,               False), | ||||
|     11:  (GPIO3,            False), 12:  (NC,               False), | ||||
|     13:  (GND,              False), 14:  (NC,               False), | ||||
|     15:  (GPIO4,            False), 16:  (NC,               False), | ||||
|     17:  (GPIO5,            False), 18:  (NC,               False), | ||||
|     19:  (GND,              False), 20:  (NC,               False), | ||||
|     21:  (GPIO6,            False), 22:  (NC,               False), | ||||
|     23:  (GPIO7,            False), 24:  (NC,               False), | ||||
|     25:  (GND,              False), 26:  (GND,              False), | ||||
|     27:  (GPIO8,            False), 28:  (GPIO28,           False), | ||||
|     29:  (GPIO9,            False), 30:  (GPIO29,           False), | ||||
|     31:  (GND,              False), 32:  (GND,              False), | ||||
|     33:  (GPIO10,           False), 34:  (GPIO30,           False), | ||||
|     35:  (GPIO11,           False), 36:  (GPIO31,           False), | ||||
|     37:  (GND,              False), 38:  (GND,              False), | ||||
|     39:  ('GPIO0-27 VREF',  False), 40:  ('GPIO0-27 VREF',  False), | ||||
|     # Gap in SODIMM pins | ||||
|     41:  ('GPIO28-45 VREF', False), 42:  ('GPIO28-45 VREF', False), | ||||
|     43:  (GND,              False), 44:  (GND,              False), | ||||
|     45:  (GPIO12,           False), 46:  (GPIO32,           False), | ||||
|     47:  (GPIO13,           False), 48:  (GPIO33,           False), | ||||
|     49:  (GND,              False), 50:  (GND,              False), | ||||
|     51:  (GPIO14,           False), 52:  (GPIO34,           False), | ||||
|     53:  (GPIO15,           False), 54:  (GPIO35,           False), | ||||
|     55:  (GND,              False), 56:  (GND,              False), | ||||
|     57:  (GPIO16,           False), 58:  (GPIO36,           False), | ||||
|     59:  (GPIO17,           False), 60:  (GPIO37,           False), | ||||
|     61:  (GND,              False), 62:  (GND,              False), | ||||
|     63:  (GPIO18,           False), 64:  (GPIO38,           False), | ||||
|     65:  (GPIO19,           False), 66:  (GPIO39,           False), | ||||
|     67:  (GND,              False), 68:  (GND,              False), | ||||
|     69:  (GPIO20,           False), 70:  (GPIO40,           False), | ||||
|     71:  (GPIO21,           False), 72:  (GPIO41,           False), | ||||
|     73:  (GND,              False), 74:  (GND,              False), | ||||
|     75:  (GPIO22,           False), 76:  (GPIO42,           False), | ||||
|     77:  (GPIO23,           False), 78:  (GPIO43,           False), | ||||
|     79:  (GND,              False), 80:  (GND,              False), | ||||
|     81:  (GPIO24,           False), 82:  (GPIO44,           False), | ||||
|     83:  (GPIO25,           False), 84:  (GPIO45,           False), | ||||
|     85:  (GND,              False), 86:  (GND,              False), | ||||
|     87:  (GPIO26,           False), 88:  ('GPIO46 1V8',     False), | ||||
|     89:  (GPIO27,           False), 90:  ('GPIO47 1V8',     False), | ||||
|     91:  (GND,              False), 92:  (GND,              False), | ||||
|     93:  ('DSI0 DN1',       False), 94:  ('DSI1 DP0',       False), | ||||
|     95:  ('DSI0 DP1',       False), 96:  ('DSI1 DN0',       False), | ||||
|     97:  (GND,              False), 98:  (GND,              False), | ||||
|     99:  ('DSI0 DN0',       False), 100: ('DSI1 CP',        False), | ||||
|     101: ('DSI0 DP0',       False), 102: ('DSI1 CN',        False), | ||||
|     103: (GND,              False), 104: (GND,              False), | ||||
|     105: ('DSI0 CN',        False), 106: ('DSI1 DP3',       False), | ||||
|     107: ('DSI0 CP',        False), 108: ('DSI1 DN3',       False), | ||||
|     109: (GND,              False), 110: (GND,              False), | ||||
|     111: ('HDMI CK N',      False), 112: ('DSI1 DP2',       False), | ||||
|     113: ('HDMI CK P',      False), 114: ('DSI1 DN2',       False), | ||||
|     115: (GND,              False), 116: (GND,              False), | ||||
|     117: ('HDMI D0 N',      False), 118: ('DSI1 DP1',       False), | ||||
|     119: ('HDMI D0 P',      False), 120: ('DSI1 DN1',       False), | ||||
|     121: (GND,              False), 122: (GND,              False), | ||||
|     123: ('HDMI D1 N',      False), 124: (NC,               False), | ||||
|     125: ('HDMI D1 P',      False), 126: (NC,               False), | ||||
|     127: (GND,              False), 128: (NC,               False), | ||||
|     129: ('HDMI D2 N',      False), 130: (NC,               False), | ||||
|     131: ('HDMI D2 P',      False), 132: (NC,               False), | ||||
|     133: (GND,              False), 134: (GND,              False), | ||||
|     135: ('CAM1 DP3',       False), 136: ('CAM0 DP0',       False), | ||||
|     137: ('CAM1 DN3',       False), 138: ('CAM0 DN0',       False), | ||||
|     139: (GND,              False), 140: (GND,              False), | ||||
|     141: ('CAM1 DP2',       False), 142: ('CAM0 CP',        False), | ||||
|     143: ('CAM1 DN2',       False), 144: ('CAM0 CN',        False), | ||||
|     145: (GND,              False), 146: (GND,              False), | ||||
|     147: ('CAM1 CP',        False), 148: ('CAM0 DP1',       False), | ||||
|     149: ('CAM1 CN',        False), 150: ('CAM0 DN1',       False), | ||||
|     151: (GND,              False), 152: (GND,              False), | ||||
|     153: ('CAM1 DP1',       False), 154: (NC,               False), | ||||
|     155: ('CAM1 DN1',       False), 156: (NC,               False), | ||||
|     157: (GND,              False), 158: (NC,               False), | ||||
|     159: ('CAM1 DP0',       False), 160: (NC,               False), | ||||
|     161: ('CAM1 DN0',       False), 162: (NC,               False), | ||||
|     163: (GND,              False), 164: (GND,              False), | ||||
|     165: ('USB DP',         False), 166: ('TVDAC',          False), | ||||
|     167: ('USB DM',         False), 168: ('USB OTGID',      False), | ||||
|     169: (GND,              False), 170: (GND,              False), | ||||
|     171: ('HDMI CEC',       False), 172: ('VC TRST N',      False), | ||||
|     173: ('HDMI SDA',       False), 174: ('VC TDI',         False), | ||||
|     175: ('HDMI SCL',       False), 176: ('VC TMS',         False), | ||||
|     177: ('RUN',            False), 178: ('VC TDO',         False), | ||||
|     179: ('VDD CORE',       False), 180: ('VC TCK',         False), | ||||
|     181: (GND,              False), 182: (GND,              False), | ||||
|     183: (V1_8,             False), 184: (V1_8,             False), | ||||
|     185: (V1_8,             False), 186: (V1_8,             False), | ||||
|     187: (GND,              False), 188: (GND,              False), | ||||
|     189: ('VDAC',           False), 190: ('VDAC',           False), | ||||
|     191: (V3_3,             False), 192: (V3_3,             False), | ||||
|     193: (V3_3,             False), 194: (V3_3,             False), | ||||
|     195: (GND,              False), 196: (GND,              False), | ||||
|     197: ('VBAT',           False), 198: ('VBAT',           False), | ||||
|     199: ('VBAT',           False), 200: ('VBAT',           False), | ||||
|     } | ||||
|  | ||||
| # The following data is sourced from a combination of the following locations: | ||||
| # | ||||
| # http://elinux.org/RPi_HardwareHistory | ||||
| # http://elinux.org/RPi_Low-level_peripherals | ||||
| # https://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c#l807 | ||||
|  | ||||
| PI_REVISIONS = { | ||||
|     # rev     model    pcb_rev released soc        manufacturer ram   storage    usb eth wifi   bt     csi dsi headers | ||||
|     'beta':   ('B',    '?',   '2012Q1', 'BCM2835', '?',         256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0002':   ('B',    '1.0', '2012Q1', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0003':   ('B',    '1.0', '2012Q3', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     '0004':   ('B',    '2.0', '2012Q3', 'BCM2835', 'Sony',      256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0005':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0006':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0007':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Egoman',    256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0008':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Sony',      256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0009':   ('A',    '2.0', '2013Q1', 'BCM2835', 'Qisda',     256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000d':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000e':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Sony',      512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '000f':   ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     '0010':   ('B+',   '1.2', '2014Q3', 'BCM2835', 'Sony',      512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0011':   ('CM',   '1.2', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     '0012':   ('A+',   '1.2', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0013':   ('B+',   '1.2', '2015Q1', 'BCM2835', 'Egoman',    512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     '0014':   ('CM',   '1.1', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    0,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     '0015':   ('A+',   '1.1', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     #'a01041': ('2B',   '1.1', '2015Q1', 'BCM2836', 'Sony',      1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     #'a21041': ('2B',   '1.1', '2015Q1', 'BCM2836', 'Embest',    1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     #'900092': ('Zero', '1.2', '2015Q4', 'BCM2835', 'Sony',      512,  'MicroSD', 1,  0,  False, False, 0,  0,  {'P1': PLUS_P1},               ), | ||||
|     #'a02082': ('3B',   '1.2', '2016Q1', 'BCM2837', 'Sony',      1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     #'a22082': ('3B',   '1.2', '2016Q1', 'BCM2837', 'Embest',    1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     } | ||||
|  | ||||
|  | ||||
| class PinInfo(namedtuple('PinInfo', ( | ||||
|     'number', | ||||
|     'function', | ||||
|     'pull_up', | ||||
|     ))): | ||||
|     """ | ||||
|     This class is a :func:`~collections.namedtuple` derivative used to | ||||
|     represent information about a pin present on a GPIO header. The following | ||||
|     attributes are defined: | ||||
|  | ||||
|     .. attribute:: number | ||||
|  | ||||
|         An integer containing the physical pin number on the header (starting | ||||
|         from 1 in accordance with convention). | ||||
|  | ||||
|     .. attribute:: function | ||||
|  | ||||
|         A string describing the function of the pin. Some common examples | ||||
|         include "GND" (for pins connecting to ground), "3V3" (for pins which | ||||
|         output 3.3 volts), "GPIO9" (for GPIO9 in the Broadcom numbering | ||||
|         scheme), etc. | ||||
|  | ||||
|     .. attribute:: pull_up | ||||
|  | ||||
|         A bool indicating whether the pin has a physical pull-up resistor | ||||
|         permanently attached (this is usually ``False`` but GPIO2 and GPIO3 | ||||
|         are *usually* ``True``). This is used internally by gpiozero to raise | ||||
|         errors when pull-down is requested on a pin with a physical pull-up | ||||
|         resistor. | ||||
|     """ | ||||
|  | ||||
|  | ||||
| class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
|     'revision', | ||||
|     'model', | ||||
|     'pcb_revision', | ||||
|     'released', | ||||
|     'soc', | ||||
|     'manufacturer', | ||||
|     'memory', | ||||
|     'storage', | ||||
|     'usb', | ||||
|     'ethernet', | ||||
|     'wifi', | ||||
|     'bluetooth', | ||||
|     'csi', | ||||
|     'dsi', | ||||
|     'headers', | ||||
|     ))): | ||||
|     """ | ||||
|     This class is a :func:`~collections.namedtuple` derivative used to | ||||
|     represent information about a particular model of Raspberry Pi. While it is | ||||
|     a tuple, it is strongly recommended that you use the following named | ||||
|     attributes to access the data contained within. | ||||
|  | ||||
|     .. attribute:: revision | ||||
|  | ||||
|         A string indicating the revision of the Pi. This is unique to each | ||||
|         revision and can be considered the "key" from which all other | ||||
|         attributes are derived. However, in itself the string is fairly | ||||
|         meaningless. | ||||
|  | ||||
|     .. attribute:: model | ||||
|  | ||||
|         A string containing the model of the Pi (for example, "B", "B+", "A+", | ||||
|         "2B", "CM" (for the Compute Module), or "Zero"). | ||||
|  | ||||
|     .. attribute:: pcb_revision | ||||
|  | ||||
|         A string containing the PCB revision number which is silk-screened onto | ||||
|         the Pi (on some models). | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|             This is primarily useful to distinguish between the model B | ||||
|             revision 1.0 and 2.0 (not to be confused with the model 2B) which | ||||
|             had slightly different pinouts on their 26-pin GPIO headers. | ||||
|  | ||||
|     .. attribute:: released | ||||
|  | ||||
|         A string containing an approximate release date for this revision of | ||||
|         the Pi (formatted as yyyyQq, e.g. 2012Q1 means the first quarter of | ||||
|         2012). | ||||
|  | ||||
|     .. attribute:: soc | ||||
|  | ||||
|         A string indicating the SoC (`system on a chip`_) that this revision | ||||
|         of the Pi is based upon. | ||||
|  | ||||
|     .. attribute:: manufacturer | ||||
|  | ||||
|         A string indicating the name of the manufacturer (usually "Sony" but a | ||||
|         few others exist). | ||||
|  | ||||
|     .. attribute:: memory | ||||
|  | ||||
|         An integer indicating the amount of memory (in Mb) connected to the | ||||
|         SoC. | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|             This can differ substantially from the amount of RAM available | ||||
|             to the operating system as the GPU's memory is shared with the | ||||
|             CPU. When the camera module is activated, at least 128Mb of RAM | ||||
|             is typically reserved for the GPU. | ||||
|  | ||||
|     .. attribute:: storage | ||||
|  | ||||
|         A string indicating the type of bootable storage used with this | ||||
|         revision of Pi, e.g. "SD", "MicroSD", or "eMMC" (for the Compute | ||||
|         Module). | ||||
|  | ||||
|     .. attribute:: usb | ||||
|  | ||||
|         An integer indicating how many USB ports are physically present on | ||||
|         this revision of the Pi. | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|             This does *not* include the micro-USB port used to power the Pi. | ||||
|             On the Compute Module this is listed as 0 as the compute module | ||||
|             itself doesn't have any physical USB headers, despite providing one | ||||
|             on the I/O development board and having the pins for one on the | ||||
|             module itself. | ||||
|  | ||||
|     .. attribute:: ethernet | ||||
|  | ||||
|         An integer indicating how many Ethernet ports are physically present | ||||
|         on this revision of the Pi. | ||||
|  | ||||
|     .. attribute:: wifi | ||||
|  | ||||
|         A bool indicating whether this revision of the Pi has wifi built-in. | ||||
|  | ||||
|     .. attribute:: bluetooth | ||||
|  | ||||
|         A bool indicating whether this revision of the Pi has bluetooth | ||||
|         built-in. | ||||
|  | ||||
|     .. attribute:: csi | ||||
|  | ||||
|         An integer indicating the number of CSI (camera) ports available on | ||||
|         this revision of the Pi. | ||||
|  | ||||
|     .. attribute:: dsi | ||||
|  | ||||
|         An integer indicating the number of DSI (display) ports available on | ||||
|         this revision of the Pi. | ||||
|  | ||||
|     .. attribute:: headers | ||||
|  | ||||
|         A dictionary which maps header labels to dictionaries which map | ||||
|         physical pin numbers to :class:`PinInfo` tuples. For example, to obtain | ||||
|         information about pin 12 on header P1 you would query | ||||
|         ``headers['P1'][12]``. | ||||
|  | ||||
|     .. _system on a chip: https://en.wikipedia.org/wiki/System_on_a_chip | ||||
|     """ | ||||
|  | ||||
|     def physical_pins(self, function): | ||||
|         """ | ||||
|         Return the physical pins supporting the specified *function* as a tuple | ||||
|         of ``(header, pin_number)`` where *header* is a string specifying the | ||||
|         header containing the *pin_number*. Note that the return value is a | ||||
|         :class:`set` which is not indexable. Use :func:`physical_pin` if you | ||||
|         are expecting a single return value. | ||||
|  | ||||
|         :param str function: | ||||
|             The pin function you wish to search for. Usually this is something | ||||
|             like "GPIO9" for Broadcom GPIO pin 9, or "GND" for all the pins | ||||
|             connecting to electrical ground. | ||||
|         """ | ||||
|         return { | ||||
|             (header, pin.number) | ||||
|             for (header, pins) in self.headers.items() | ||||
|             for pin in pins.values() | ||||
|             if pin.function == function | ||||
|             } | ||||
|  | ||||
|     def physical_pin(self, function): | ||||
|         """ | ||||
|         Return the physical pin supporting the specified *function*. If no pins | ||||
|         support the desired *function*, this function raises :exc:`PinNoPins`. | ||||
|         If multiple pins support the desired *function*, :exc:`PinMultiplePins` | ||||
|         will be raised (use :func:`physical_pins` if you expect multiple pins | ||||
|         in the result, such as for electrical ground). | ||||
|  | ||||
|         :param str function: | ||||
|             The pin function you wish to search for. Usually this is something | ||||
|             like "GPIO9" for Broadcom GPIO pin 9. | ||||
|         """ | ||||
|         result = self.physical_pins(function) | ||||
|         if len(result) > 1: | ||||
|             raise PinMultiplePins('multiple pins can be used for %s' % function) | ||||
|         elif result: | ||||
|             return result.pop() | ||||
|         else: | ||||
|             raise PinNoPins('no pins can be used for %s' % function) | ||||
|  | ||||
|     def pulled_up(self, function): | ||||
|         """ | ||||
|         Returns a bool indicating whether a physical pull-up is attached to | ||||
|         the pin supporting the specified *function*. Either :exc:`PinNoPins` | ||||
|         or :exc:`PinMultiplePins` may be raised if the function is not | ||||
|         associated with a single pin. | ||||
|  | ||||
|         :param str function: | ||||
|             The pin function you wish to determine pull-up for. Usually this is | ||||
|             something like "GPIO9" for Broadcom GPIO pin 9. | ||||
|         """ | ||||
|         header, number = self.physical_pin(function) | ||||
|         return self.headers[header][number].pull_up | ||||
|  | ||||
|  | ||||
| _PI_REVISION = None | ||||
| def _get_pi_revision(): | ||||
|     with io.open('/proc/cpuinfo', 'r') as f: | ||||
|         for line in f: | ||||
|             if line.startswith('Revision'): | ||||
|                 revision = line.split(':')[1].strip().lower() | ||||
|                 overvolted = revision.startswith('1000') | ||||
|                 if overvolted: | ||||
|                     revision = revision[4:] | ||||
|                 return revision | ||||
|         raise IOError('unable to locate Pi revision in /proc/cpuinfo') | ||||
|  | ||||
|  | ||||
| def _parse_pi_revision(revision): | ||||
|     # For new-style revisions the value's bit pattern is as follows: | ||||
|     # | ||||
|     # MSB -----------------------> LSB | ||||
|     # uuuuuuuuFMMMCCCCPPPPTTTTTTTTRRRR | ||||
|     # | ||||
|     # uuuuuuuu - Unused | ||||
|     # F        - New flag (1=valid new-style revision, 0=old-style) | ||||
|     # MMM      - Memory size (0=256, 1=512, 2=1024) | ||||
|     # CCCC     - Manufacturer (0=Sony, 1=Egoman, 2=Embest) | ||||
|     # PPPP     - Processor (0=2835, 1=2836, 2=2837) | ||||
|     # TTTTTTTT - Type (0=A, 1=B, 2=A+, 3=B+, 4=2B, 5=Alpha (??), 6=CM, 8=3B, 9=Zero) | ||||
|     # RRR      - Revision (0, 1, or 2) | ||||
|     i = int(revision, base=16) | ||||
|     if not (i & 0x800000): | ||||
|         raise ValueError('cannot parse "%s"; this is not a new-style revision' % revision) | ||||
|     try: | ||||
|         model = { | ||||
|             0: 'A', | ||||
|             1: 'B', | ||||
|             2: 'A+', | ||||
|             3: 'B+', | ||||
|             4: '2B', | ||||
|             6: 'CM', | ||||
|             8: '3B', | ||||
|             9: 'Zero', | ||||
|             }[(i & 0xff0) >> 4] | ||||
|         if model in ('A', 'B'): | ||||
|             pcb_revision = { | ||||
|                 0: '1.0', # is this right? | ||||
|                 1: '1.0', | ||||
|                 2: '2.0', | ||||
|                 }[i & 0x0f] | ||||
|         else: | ||||
|             pcb_revision = '1.%d' % (i & 0x0f) | ||||
|         released = { | ||||
|             'A':    '2013Q1', | ||||
|             'B':    '2012Q1' if pcb_revision == '1.0' else '2012Q4', | ||||
|             'A+':   '2014Q4', | ||||
|             'B+':   '2014Q3', | ||||
|             '2B':   '2015Q1', | ||||
|             'CM':   '2014Q2', | ||||
|             '3B':   '2016Q1', | ||||
|             'Zero': '2015Q4', | ||||
|             }[model] | ||||
|         soc = { | ||||
|             0: 'BCM2835', | ||||
|             1: 'BCM2836', | ||||
|             2: 'BCM2837', | ||||
|             }[(i & 0xf000) >> 12] | ||||
|         manufacturer = { | ||||
|             0: 'Sony', | ||||
|             1: 'Egoman', | ||||
|             2: 'Embest', | ||||
|             }[(i & 0xf0000) >> 16] | ||||
|         memory = { | ||||
|             0: 256, | ||||
|             1: 512, | ||||
|             2: 1024, | ||||
|             }[(i & 0x700000) >> 20] | ||||
|         storage = { | ||||
|             'A': 'SD', | ||||
|             'B': 'SD', | ||||
|             'CM': 'eMMC', | ||||
|             }.get(model, 'MicroSD') | ||||
|         usb = { | ||||
|             'A':    1, | ||||
|             'A+':   1, | ||||
|             'Zero': 1, | ||||
|             'B':    2, | ||||
|             'CM':   0, | ||||
|             }.get(model, 4) | ||||
|         ethernet = { | ||||
|             'A':    0, | ||||
|             'A+':   0, | ||||
|             'Zero': 0, | ||||
|             'CM':   0, | ||||
|             }.get(model, 1) | ||||
|         wifi = { | ||||
|             '3B': True, | ||||
|             }.get(model, False) | ||||
|         bluetooth = { | ||||
|             '3B': True, | ||||
|             }.get(model, False) | ||||
|         csi = { | ||||
|             'Zero': 0, | ||||
|             'CM':   2, | ||||
|             }.get(model, 1) | ||||
|         dsi = csi | ||||
|         headers = { | ||||
|             'A':  {'P1': REV2_P1, 'P5': REV2_P5}, | ||||
|             'B':  {'P1': REV2_P1, 'P5': REV2_P5} if pcb_revision == '2.0' else {'P1': REV1_P1}, | ||||
|             'CM': {'SODIMM': CM_SODIMM}, | ||||
|             }.get(model, {'P1': PLUS_P1}) | ||||
|     except KeyError: | ||||
|         raise ValueError('unable to parse new-style revision "%s"' % revision) | ||||
|     else: | ||||
|         return ( | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             ) | ||||
|  | ||||
|  | ||||
| def pi_info(revision=None): | ||||
|     """ | ||||
|     Returns a :class:`PiBoardInfo` instance containing information about a | ||||
|     *revision* of the Raspberry Pi. | ||||
|  | ||||
|     :param str revision: | ||||
|         The revision of the Pi to return information about. If this is omitted | ||||
|         or ``None`` (the default), then the library will attempt to determine | ||||
|         the model of Pi it is running on and return information about that. | ||||
|     """ | ||||
|     # cache the result as we can reasonably assume the revision of the Pi isn't | ||||
|     # going to change at runtime... | ||||
|     if revision is None: | ||||
|         global _PI_REVISION | ||||
|         if _PI_REVISION is None: | ||||
|             try: | ||||
|                 _PI_REVISION = _get_pi_revision() | ||||
|             except IOError: | ||||
|                 _PI_REVISION = 'unknown' | ||||
|         revision = _PI_REVISION | ||||
|     try: | ||||
|         ( | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             ) = PI_REVISIONS[revision] | ||||
|     except KeyError: | ||||
|         try: | ||||
|             ( | ||||
|                 model, | ||||
|                 pcb_revision, | ||||
|                 released, | ||||
|                 soc, | ||||
|                 manufacturer, | ||||
|                 memory, | ||||
|                 storage, | ||||
|                 usb, | ||||
|                 ethernet, | ||||
|                 wifi, | ||||
|                 bluetooth, | ||||
|                 csi, | ||||
|                 dsi, | ||||
|                 headers, | ||||
|                 ) = _parse_pi_revision(revision) | ||||
|         except ValueError: | ||||
|             raise PinUnknownPi('unknown RPi revision "%s"' % revision) | ||||
|     headers = { | ||||
|         header: { | ||||
|             number: PinInfo(number, function, pull_up) | ||||
|             for number, (function, pull_up) in header_data.items() | ||||
|             } | ||||
|         for header, header_data in headers.items() | ||||
|         } | ||||
|     return PiBoardInfo( | ||||
|         revision, | ||||
|         model, | ||||
|         pcb_revision, | ||||
|         released, | ||||
|         soc, | ||||
|         manufacturer, | ||||
|         memory, | ||||
|         storage, | ||||
|         usb, | ||||
|         ethernet, | ||||
|         wifi, | ||||
|         bluetooth, | ||||
|         csi, | ||||
|         dsi, | ||||
|         headers, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @@ -17,6 +17,7 @@ from threading import Thread, Event, Lock | ||||
| from collections import Counter | ||||
|  | ||||
| from . import Pin, PINS_CLEANUP | ||||
| from .data import pi_info | ||||
| from ..exc import ( | ||||
|     PinInvalidPull, | ||||
|     PinInvalidEdges, | ||||
| @@ -198,10 +199,14 @@ class NativePin(Pin): | ||||
|     GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} | ||||
|     GPIO_EDGES_NAMES = {v: k for (k, v) in GPIO_EDGES.items()} | ||||
|  | ||||
|     PI_INFO = None | ||||
|  | ||||
|     def __new__(cls, number): | ||||
|         if not cls._PINS: | ||||
|             cls._MEM = GPIOMemory() | ||||
|             PINS_CLEANUP.append(cls._MEM.close) | ||||
|         if cls.PI_INFO is None: | ||||
|             cls.PI_INFO = pi_info() | ||||
|         if not (0 <= number < 54): | ||||
|             raise ValueError('invalid pin %d specified (must be 0..53)' % number) | ||||
|         try: | ||||
| @@ -230,7 +235,7 @@ class NativePin(Pin): | ||||
|             self._change_thread = None | ||||
|             self._change_event = Event() | ||||
|             self.function = 'input' | ||||
|             self.pull = 'up' if number in (2, 3) else 'floating' | ||||
|             self.pull = 'up' if cls.PI_INFO.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self.bounce = None | ||||
|             self.edges = 'both' | ||||
|             return self | ||||
| @@ -245,7 +250,7 @@ class NativePin(Pin): | ||||
|     def close(self): | ||||
|         self.when_changed = None | ||||
|         self.function = 'input' | ||||
|         self.pull = 'up' if self.number in (2, 3) else 'floating' | ||||
|         self.pull = 'up' if self.PI_INFO.pulled_up('GPIO%d' % self.number) else 'floating' | ||||
|  | ||||
|     def _get_function(self): | ||||
|         return self.GPIO_FUNCTION_NAMES[(self._MEM[self._func_offset] >> self._func_shift) & 7] | ||||
| @@ -278,7 +283,7 @@ class NativePin(Pin): | ||||
|     def _set_pull(self, value): | ||||
|         if self.function != 'input': | ||||
|             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||
|         if value != 'up' and self._number in (2, 3): | ||||
|         if value != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self.number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             value = self.GPIO_PULL_UPS[value] | ||||
|   | ||||
| @@ -9,6 +9,7 @@ str = type('') | ||||
| import pigpio | ||||
|  | ||||
| from . import Pin | ||||
| from .data import pi_info | ||||
| from ..exc import ( | ||||
|     PinInvalidFunction, | ||||
|     PinSetInput, | ||||
| @@ -93,7 +94,14 @@ class PiGPIOPin(Pin): | ||||
|     GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} | ||||
|     GPIO_EDGES_NAMES = {v: k for (k, v) in GPIO_EDGES.items()} | ||||
|  | ||||
|     PI_INFO = None | ||||
|  | ||||
|     def __new__(cls, number, host='localhost', port=8888): | ||||
|         # XXX What about remote pins? This should probably be instance | ||||
|         # specific rather than class specific for pigpio. Need to check how | ||||
|         # to query remote info though... | ||||
|         if cls.PI_INFO is None: | ||||
|             cls.PI_INFO = pi_info() | ||||
|         try: | ||||
|             return cls._PINS[(host, port, number)] | ||||
|         except KeyError: | ||||
| @@ -107,7 +115,7 @@ class PiGPIOPin(Pin): | ||||
|             self._host = host | ||||
|             self._port = port | ||||
|             self._number = number | ||||
|             self._pull = 'up' if number in (2, 3) else 'floating' | ||||
|             self._pull = 'up' if cls.PI_INFO.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self._pwm = False | ||||
|             self._bounce = None | ||||
|             self._when_changed = None | ||||
| @@ -150,7 +158,7 @@ class PiGPIOPin(Pin): | ||||
|             self.frequency = None | ||||
|             self.when_changed = None | ||||
|             self.function = 'input' | ||||
|             self.pull = 'up' if self.number in (2, 3) else 'floating' | ||||
|             self.pull = 'up' if self.PI_INFO.pulled_up('GPIO%d' % self.number) else 'floating' | ||||
|  | ||||
|     def _get_function(self): | ||||
|         return self.GPIO_FUNCTION_NAMES[self._connection.get_mode(self._number)] | ||||
| @@ -187,7 +195,7 @@ class PiGPIOPin(Pin): | ||||
|     def _set_pull(self, value): | ||||
|         if self.function != 'input': | ||||
|             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||
|         if value != 'up' and self._number in (2, 3): | ||||
|         if value != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             self._connection.set_pull_up_down(self._number, self.GPIO_PULL_UPS[value]) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ str = type('') | ||||
| from RPi import GPIO | ||||
|  | ||||
| from . import Pin | ||||
| from .data import pi_info | ||||
| from ..exc import ( | ||||
|     PinInvalidFunction, | ||||
|     PinSetInput, | ||||
| @@ -71,17 +72,21 @@ class RPiGPIOPin(Pin): | ||||
|     GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} | ||||
|     GPIO_EDGES_NAMES = {v: k for (k, v) in GPIO_EDGES.items()} | ||||
|  | ||||
|     PI_INFO = None | ||||
|  | ||||
|     def __new__(cls, number): | ||||
|         if not cls._PINS: | ||||
|             GPIO.setmode(GPIO.BCM) | ||||
|             GPIO.setwarnings(False) | ||||
|         if cls.PI_INFO is None: | ||||
|             cls.PI_INFO = pi_info() | ||||
|         try: | ||||
|             return cls._PINS[number] | ||||
|         except KeyError: | ||||
|             self = super(RPiGPIOPin, cls).__new__(cls) | ||||
|             cls._PINS[number] = self | ||||
|             self._number = number | ||||
|             self._pull = 'up' if number in (2, 3) else 'floating' | ||||
|             self._pull = 'up' if cls.PI_INFO.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self._pwm = None | ||||
|             self._frequency = None | ||||
|             self._duty_cycle = None | ||||
| @@ -108,7 +113,7 @@ class RPiGPIOPin(Pin): | ||||
|         GPIO.setup(self._number, GPIO.OUT, initial=state) | ||||
|  | ||||
|     def input_with_pull(self, pull): | ||||
|         if pull != 'up' and self._number in (2, 3): | ||||
|         if pull != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             GPIO.setup(self._number, GPIO.IN, self.GPIO_PULL_UPS[pull]) | ||||
| @@ -154,7 +159,7 @@ class RPiGPIOPin(Pin): | ||||
|     def _set_pull(self, value): | ||||
|         if self.function != 'input': | ||||
|             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||
|         if value != 'up' and self._number in (2, 3): | ||||
|         if value != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             GPIO.setup(self._number, GPIO.IN, self.GPIO_PULL_UPS[value]) | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import RPIO.PWM | ||||
| from RPIO.Exceptions import InvalidChannelException | ||||
|  | ||||
| from . import Pin, PINS_CLEANUP | ||||
| from .data import pi_info | ||||
| from ..exc import ( | ||||
|     PinInvalidFunction, | ||||
|     PinSetInput, | ||||
| @@ -62,6 +63,8 @@ class RPIOPin(Pin): | ||||
|     GPIO_FUNCTION_NAMES = {v: k for (k, v) in GPIO_FUNCTIONS.items()} | ||||
|     GPIO_PULL_UP_NAMES = {v: k for (k, v) in GPIO_PULL_UPS.items()} | ||||
|  | ||||
|     PI_INFO = None | ||||
|  | ||||
|     def __new__(cls, number): | ||||
|         if not cls._PINS: | ||||
|             RPIO.setmode(RPIO.BCM) | ||||
| @@ -72,13 +75,15 @@ class RPIOPin(Pin): | ||||
|             PINS_CLEANUP.append(RPIO.PWM.cleanup) | ||||
|             PINS_CLEANUP.append(RPIO.stop_waiting_for_interrupts) | ||||
|             PINS_CLEANUP.append(RPIO.cleanup) | ||||
|         if cls.PI_INFO is None: | ||||
|             cls.PI_INFO = pi_info() | ||||
|         try: | ||||
|             return cls._PINS[number] | ||||
|         except KeyError: | ||||
|             self = super(RPIOPin, cls).__new__(cls) | ||||
|             cls._PINS[number] = self | ||||
|             self._number = number | ||||
|             self._pull = 'up' if number in (2, 3) else 'floating' | ||||
|             self._pull = 'up' if cls.PI_INFO.pulled_up('GPIO%d' % number) else 'floating' | ||||
|             self._pwm = False | ||||
|             self._duty_cycle = None | ||||
|             self._bounce = None | ||||
| @@ -145,7 +150,7 @@ class RPIOPin(Pin): | ||||
|     def _set_pull(self, value): | ||||
|         if self.function != 'input': | ||||
|             raise PinFixedPull('cannot set pull on non-input pin %r' % self) | ||||
|         if value != 'up' and self._number in (2, 3): | ||||
|         if value != 'up' and self.PI_INFO.pulled_up('GPIO%d' % self._number): | ||||
|             raise PinFixedPull('%r has a physical pull-up resistor' % self) | ||||
|         try: | ||||
|             RPIO.setup(self._number, RPIO.IN, self.GPIO_PULL_UPS[value]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user