Coverage for /usr/lib/python3/dist-packages/gpiozero/pins/data.py: 38%
320 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 16:40 +0100
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 16:40 +0100
1# vim: set fileencoding=utf-8:
2#
3# GPIO Zero: a library for controlling the Raspberry Pi's GPIO pins
4#
5# Copyright (c) 2016-2021 Dave Jones <dave@waveform.org.uk>
6# Copyright (c) 2018-2021 Ben Nuttall <ben@bennuttall.com>
7# Copyright (c) 2020 chrisruk <chrisrichardsonuk@gmail.com>
8# Copyright (c) 2016-2019 Andrew Scheller <github@loowis.durge.org>
9#
10# SPDX-License-Identifier: BSD-3-Clause
12from __future__ import (
13 unicode_literals,
14 absolute_import,
15 print_function,
16 division,
17 )
18str = type('')
20import os
21import sys
22from textwrap import dedent
23from itertools import cycle
24from operator import attrgetter
25from collections import namedtuple
27from ..exc import PinUnknownPi, PinMultiplePins, PinNoPins, PinInvalidPin
28from ..devices import Device
31# Some useful constants for describing pins
33V1_8 = '1V8'
34V3_3 = '3V3'
35V5 = '5V'
36GND = 'GND'
37NC = 'NC' # not connected
38GPIO0 = 'GPIO0'
39GPIO1 = 'GPIO1'
40GPIO2 = 'GPIO2'
41GPIO3 = 'GPIO3'
42GPIO4 = 'GPIO4'
43GPIO5 = 'GPIO5'
44GPIO6 = 'GPIO6'
45GPIO7 = 'GPIO7'
46GPIO8 = 'GPIO8'
47GPIO9 = 'GPIO9'
48GPIO10 = 'GPIO10'
49GPIO11 = 'GPIO11'
50GPIO12 = 'GPIO12'
51GPIO13 = 'GPIO13'
52GPIO14 = 'GPIO14'
53GPIO15 = 'GPIO15'
54GPIO16 = 'GPIO16'
55GPIO17 = 'GPIO17'
56GPIO18 = 'GPIO18'
57GPIO19 = 'GPIO19'
58GPIO20 = 'GPIO20'
59GPIO21 = 'GPIO21'
60GPIO22 = 'GPIO22'
61GPIO23 = 'GPIO23'
62GPIO24 = 'GPIO24'
63GPIO25 = 'GPIO25'
64GPIO26 = 'GPIO26'
65GPIO27 = 'GPIO27'
66GPIO28 = 'GPIO28'
67GPIO29 = 'GPIO29'
68GPIO30 = 'GPIO30'
69GPIO31 = 'GPIO31'
70GPIO32 = 'GPIO32'
71GPIO33 = 'GPIO33'
72GPIO34 = 'GPIO34'
73GPIO35 = 'GPIO35'
74GPIO36 = 'GPIO36'
75GPIO37 = 'GPIO37'
76GPIO38 = 'GPIO38'
77GPIO39 = 'GPIO39'
78GPIO40 = 'GPIO40'
79GPIO41 = 'GPIO41'
80GPIO42 = 'GPIO42'
81GPIO43 = 'GPIO43'
82GPIO44 = 'GPIO44'
83GPIO45 = 'GPIO45'
85# Board layout ASCII art
87REV1_BOARD = """\
88{style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset}
89{style:white on green}| {P1:{style} col2}{style:white on green} P1 {style:black on yellow}|C|{style:white on green} {style:on cyan}|A|{style:on green} |{style:reset}
90{style:white on green}| {P1:{style} col1}{style:white on green} {style:black on yellow}+-+{style:white on green} {style:on cyan}+-+{style:on green} |{style:reset}
91{style:white on green}| |{style:reset}
92{style:white on green}| {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
93{style:white on green}| {style:on black}|SoC|{style:on green} {style:black on white}| USB{style:reset}
94{style:white on green}| {style:on black}|D|{style:on green} {style:bold}Pi Model{style:normal} {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
95{style:white on green}| {style:on black}|S|{style:on green} {style:bold}{model:3s}V{pcb_revision:3s}{style:normal} |{style:reset}
96{style:white on green}| {style:on black}|I|{style:on green} {style:on black}|C|{style:black on white}+======{style:reset}
97{style:white on green}| {style:on black}|S|{style:black on white}| Net{style:reset}
98{style:white on green}| {style:on black}|I|{style:black on white}+======{style:reset}
99{style:black on white}=pwr{style:on green} {style:on white}|HDMI|{style:white on green} |{style:reset}
100{style:white on green}+----------------{style:black on white}| |{style:white on green}----------+{style:reset}"""
102REV2_BOARD = """\
103{style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset}
104{style:white on green}| {P1:{style} col2}{style:white on green} P1 {style:black on yellow}|C|{style:white on green} {style:on cyan}|A|{style:on green} |{style:reset}
105{style:white on green}| {P1:{style} col1}{style:white on green} {style:black on yellow}+-+{style:white on green} {style:on cyan}+-+{style:on green} |{style:reset}
106{style:white on green}| {P5:{style} col1}{style:white on green} |{style:reset}
107{style:white on green}| P5 {P5:{style} col2}{style:white on green} {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
108{style:white on green}| {style:on black}|SoC|{style:on green} {style:black on white}| USB{style:reset}
109{style:white on green}| {style:on black}|D|{style:on green} {style:bold}Pi Model{style:normal} {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
110{style:white on green}| {style:on black}|S|{style:on green} {style:bold}{model:3s}V{pcb_revision:3s}{style:normal} |{style:reset}
111{style:white on green}| {style:on black}|I|{style:on green} {style:on black}|C|{style:black on white}+======{style:reset}
112{style:white on green}| {style:on black}|S|{style:black on white}| Net{style:reset}
113{style:white on green}| {style:on black}|I|{style:black on white}+======{style:reset}
114{style:black on white}=pwr{style:on green} {style:on white}|HDMI|{style:white on green} |{style:reset}
115{style:white on green}+----------------{style:black on white}| |{style:white on green}----------+{style:reset}"""
117A_BOARD = """\
118{style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset}
119{style:white on green}| {P1:{style} col2}{style:white on green} P1 {style:black on yellow}|C|{style:white on green} {style:on cyan}|A|{style:on green} |{style:reset}
120{style:white on green}| {P1:{style} col1}{style:white on green} {style:black on yellow}+-+{style:white on green} {style:on cyan}+-+{style:on green} |{style:reset}
121{style:white on green}| {P5:{style} col1}{style:white on green} |{style:reset}
122{style:white on green}| P5 {P5:{style} col2}{style:white on green} {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
123{style:white on green}| {style:on black}|SoC|{style:on green} {style:black on white}| USB{style:reset}
124{style:white on green}| {style:on black}|D|{style:on green} {style:bold}Pi Model{style:normal} {style:on black}+---+{style:on green} {style:black on white}+===={style:reset}
125{style:white on green}| {style:on black}|S|{style:on green} {style:bold}{model:3s}V{pcb_revision:3s}{style:normal} |{style:reset}
126{style:white on green}| {style:on black}|I|{style:on green} {style:on black}|C|{style:on green} |{style:reset}
127{style:white on green}| {style:on black}|S|{style:on green} |{style:reset}
128{style:white on green}| {style:on black}|I|{style:on green} |{style:reset}
129{style:black on white}=pwr{style:on green} {style:on white}|HDMI|{style:white on green} |{style:reset}
130{style:white on green}+----------------{style:black on white}| |{style:white on green}----------+{style:reset}"""
132BPLUS_BOARD = """\
133{style:white on green},--------------------------------.{style:reset}
134{style:white on green}| {J8:{style} col2}{style:white on green} J8 {style:black on white}+===={style:reset}
135{style:white on green}| {J8:{style} col1}{style:white on green} {style:black on white}| USB{style:reset}
136{style:white on green}| {style:black on white}+===={style:reset}
137{style:white on green}| {style:bold}Pi Model {model:4s}V{pcb_revision:3s}{style:normal} |{style:reset}
138{style:white on green}| {style:on black}+----+{style:on green} {style:black on white}+===={style:reset}
139{style:white on green}| {style:on black}|D|{style:on green} {style:on black}|SoC |{style:on green} {style:black on white}| USB{style:reset}
140{style:white on green}| {style:on black}|S|{style:on green} {style:on black}| |{style:on green} {style:black on white}+===={style:reset}
141{style:white on green}| {style:on black}|I|{style:on green} {style:on black}+----+{style:on green} |{style:reset}
142{style:white on green}| {style:on black}|C|{style:on green} {style:black on white}+======{style:reset}
143{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}| Net{style:reset}
144{style:white on green}| {style:black on white}pwr{style:white on green} {style:black on white}|HDMI|{style:white on green} {style:on black}|I||A|{style:on green} {style:black on white}+======{style:reset}
145{style:white on green}`-{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}----{style:on black}|V|{style:on green}-------'{style:reset}"""
147B3PLUS_BOARD = """\
148{style:white on green},--------------------------------.{style:reset}
149{style:white on green}| {J8:{style} col2}{style:white on green} J8 {style:black on white}+===={style:reset}
150{style:white on green}| {J8:{style} col1}{style:white on green} PoE {style:black on white}| USB{style:reset}
151{style:white on green}| {style:black on white} Wi {style:white on green} {POE:{style} row1}{style:on green} {style:black on white}+===={style:reset}
152{style:white on green}| {style:black on white} Fi {style:white on green} {style:bold}Pi Model {model:4s}V{pcb_revision:3s}{style:normal} {POE:{style} row2}{style:on green} |{style:reset}
153{style:white on green}| {style:black on white},----.{style:on green} {style:black on white}+===={style:reset}
154{style:white on green}| {style:on black}|D|{style:on green} {style:black on white}|SoC |{style:on green} {style:black on white}| USB{style:reset}
155{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}| |{style:on green} {style:black on white}+===={style:reset}
156{style:white on green}| {style:on black}|I|{style:on green} {style:black on white}`----'{style:white on green} |{style:reset}
157{style:white on green}| {style:on black}|C|{style:on green} {style:black on white}+======{style:reset}
158{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}| Net{style:reset}
159{style:white on green}| {style:black on white}pwr{style:white on green} {style:black on white}|HDMI|{style:white on green} {style:on black}|I||A|{style:on green} {style:black on white}+======{style:reset}
160{style:white on green}`-{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}----{style:on black}|V|{style:on green}-------'{style:reset}"""
162B4_BOARD = """\
163{style:white on green},--------------------------------.{style:reset}
164{style:white on green}| {J8:{style} col2}{style:white on green} J8 {style:black on white}+======{style:reset}
165{style:white on green}| {J8:{style} col1}{style:white on green} PoE {style:black on white}| Net{style:reset}
166{style:white on green}| {style:black on white} Wi {style:white on green} {POE:{style} row1}{style:on green} {style:black on white}+======{style:reset}
167{style:white on green}| {style:black on white} Fi {style:white on green} {style:bold}Pi Model {model:4s}V{pcb_revision:3s}{style:normal} {POE:{style} row2}{style:normal white on green} |{style:reset}
168{style:white on green}| {style:black on white},----.{style:on green} {style:white on black}+---+{style:on green} {style:blue on white}+===={style:reset}
169{style:white on green}| {style:on black}|D|{style:on green} {style:black on white}|SoC |{style:on green} {style:white on black}|RAM|{style:on green} {style:blue on white}|USB3{style:reset}
170{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}| |{style:on green} {style:white on black}| |{style:on green} {style:blue on white}+===={style:reset}
171{style:white on green}| {style:on black}|I|{style:on green} {style:black on white}`----'{style:white on green} {style:white on black}+---+{style:on green} |{style:reset}
172{style:white on green}| {style:on black}|C|{style:on green} {style:black on white}+===={style:reset}
173{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}|USB2{style:reset}
174{style:white on green}| {style:black on white}pwr{style:white on green} {style:black on white}|hd|{style:white on green} {style:black on white}|hd|{style:white on green} {style:on black}|I||A|{style:on green} {style:black on white}+===={style:reset}
175{style:white on green}`-{style:black on white}| |{style:white on green}---{style:black on white}|m0|{style:white on green}---{style:black on white}|m1|{style:white on green}----{style:on black}|V|{style:on green}-------'{style:reset}"""
177APLUS_BOARD = """\
178{style:white on green},--------------------------.{style:reset}
179{style:white on green}| {J8:{style} col2}{style:white on green} J8 |{style:reset}
180{style:white on green}| {J8:{style} col1}{style:white on green} |{style:reset}
181{style:white on green}| |{style:reset}
182{style:white on green}| {style:bold}Pi Model {model:4s}V{pcb_revision:3s}{style:normal} |{style:reset}
183{style:white on green}| {style:on black}+----+{style:on green} {style:black on white}+===={style:reset}
184{style:white on green}| {style:on black}|D|{style:on green} {style:on black}|SoC |{style:on green} {style:black on white}| USB{style:reset}
185{style:white on green}| {style:on black}|S|{style:on green} {style:on black}| |{style:on green} {style:black on white}+===={style:reset}
186{style:white on green}| {style:on black}|I|{style:on green} {style:on black}+----+{style:on green} |{style:reset}
187{style:white on green}| {style:on black}|C|{style:on green} |{style:reset}
188{style:white on green}| {style:on black}|S|{style:on green} |{style:reset}
189{style:white on green}| {style:black on white}pwr{style:white on green} {style:black on white}|HDMI|{style:white on green} {style:on black}|I||A|{style:on green} |{style:reset}
190{style:white on green}`-{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}----{style:on black}|V|{style:on green}-'{style:reset}"""
192A3PLUS_BOARD = """\
193{style:white on green},--------------------------.{style:reset}
194{style:white on green}| {J8:{style} col2}{style:white on green} J8 |{style:reset}
195{style:white on green}| {J8:{style} col1}{style:white on green} |{style:reset}
196{style:white on green}| {style:black on white} Wi {style:white on green} |{style:reset}
197{style:white on green}| {style:black on white} Fi {style:white on green} {style:bold}Pi Model {model:4s}V{pcb_revision:3s}{style:normal} |{style:reset}
198{style:white on green}| {style:black on white},----.{style:on green} {style:black on white}+===={style:reset}
199{style:white on green}| {style:on black}|D|{style:on green} {style:black on white}|SoC |{style:on green} {style:black on white}| USB{style:reset}
200{style:white on green}| {style:on black}|S|{style:on green} {style:black on white}| |{style:on green} {style:black on white}+===={style:reset}
201{style:white on green}| {style:on black}|I|{style:on green} {style:black on white}`----'{style:white on green} |{style:reset}
202{style:white on green}| {style:on black}|C|{style:on green} |{style:reset}
203{style:white on green}| {style:on black}|S|{style:on green} |{style:reset}
204{style:white on green}| {style:black on white}pwr{style:white on green} {style:black on white}|HDMI|{style:white on green} {style:on black}|I||A|{style:on green} |{style:reset}
205{style:white on green}`-{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}----{style:on black}|V|{style:on green}-'{style:reset}"""
207ZERO12_BOARD = """\
208{style:white on green},-------------------------.{style:reset}
209{style:white on green}| {J8:{style} col2}{style:white on green} J8 |{style:reset}
210{style:white on green}| {J8:{style} col1}{style:white on green} |{style:reset}
211{style:black on white}---+{style:white on green} {style:on black}+---+{style:on green} {style:bold}PiZero{style:normal} |{style:reset}
212{style:black on white} sd|{style:white on green} {style:on black}|SoC|{style:on green} {style:bold}V{pcb_revision:3s}{style:normal} |{style:reset}
213{style:black on white}---+|hdmi|{style:white on green} {style:on black}+---+{style:on green} {style:black on white}usb{style:on green} {style:black on white}pwr{style:white on green} |{style:reset}
214{style:white on green}`---{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}-{style:black on white}| |{style:white on green}-'{style:reset}"""
216ZERO13_BOARD = """\
217{style:white on green}.-------------------------.{style:reset}
218{style:white on green}| {J8:{style} col2}{style:white on green} J8 |{style:reset}
219{style:white on green}| {J8:{style} col1}{style:white on green} {style:black on white}|c{style:reset}
220{style:black on white}---+{style:white on green} {style:on black}+---+{style:on green} {style:bold}Pi{model:6s}{style:normal}{style:black on white}|s{style:reset}
221{style:black on white} sd|{style:white on green} {style:on black}|SoC|{style:on green} {style:bold}V{pcb_revision:3s}{style:normal} {style:black on white}|i{style:reset}
222{style:black on white}---+|hdmi|{style:white on green} {style:on black}+---+{style:on green} {style:black on white}usb{style:on green} {style:on white}pwr{style:white on green} |{style:reset}
223{style:white on green}`---{style:black on white}| |{style:white on green}--------{style:black on white}| |{style:white on green}-{style:black on white}| |{style:white on green}-'{style:reset}"""
225CM_BOARD = """\
226{style:white on green}+---------------------------------------+{style:reset}
227{style:white on green}| {style:yellow on black}O{style:bold white on green} Raspberry Pi {model:4s} {style:normal yellow on black}O{style:white on green} |{style:reset}
228 {style:white on green}) Version {pcb_revision:3s} {style:on black}+---+{style:on green} ({style:reset}
229{style:white on green}| {style:on black}|SoC|{style:on green} |{style:reset}
230 {style:white on green}) {style:on black}+---+{style:on green} ({style:reset}
231{style:white on green}| {style:on black}O{style:on green} _ {style:on black}O{style:on green} |{style:reset}
232{style:white on green}||||||{style:reset} {style:white on green}||||||||||||||||||||||||||||||||||{style:reset}"""
234CM3PLUS_BOARD = """\
235{style:white on green}+---------------------------------------+{style:reset}
236{style:white on green}| {style:yellow on black}O{style:bold white on green} Raspberry Pi {model:4s} {style:normal yellow on black}O{style:white on green} |{style:reset}
237 {style:white on green}) Version {pcb_revision:3s} {style:black on white},---.{style:white on green} ({style:reset}
238{style:white on green}| {style:black on white}|SoC|{style:white on green} |{style:reset}
239 {style:white on green}) {style:black on white}`---'{style:white on green} ({style:reset}
240{style:white on green}| {style:on black}O{style:on green} _ {style:on black}O{style:on green} |{style:reset}
241{style:white on green}||||||{style:reset} {style:white on green}||||||||||||||||||||||||||||||||||{style:reset}"""
243CM4_BOARD = """\
244{style:white on green},--{style:black on white}csi1{style:white on green}---{style:black on white}dsi0{style:white on green}---{style:black on white}dsi1{style:white on green}-----------{style:bold},-------------.{style:normal}-----------.{style:reset}
245{style:white on green}| {style:black on white}----{style:white on green} {style:black on white}----{style:white on green} {style:black on white}----{style:white on green} J2{J2:{style} col2}{style:bold white on green}|{style:yellow}O O{style:white}|{style:normal} |{style:reset}
246{style:white on green}{style:black on white}c|{style:white on green} {style:bold yellow}O {style:white}Pi {model:4s} Rev {pcb_revision:3s}{style:normal} {J2:{style} col1}{style:bold white on green}| {style:normal black on white} Wi {style:white on green} {style:bold}|{style:normal} {style:bold yellow}O{style:normal white} |{style:reset}
247{style:white on green}{style:black on white}s|{style:white on green} {style:bold}IO Board{style:normal} {style:bold}| {style:normal black on white} Fi {style:white on green} {style:bold}|{style:normal} |{style:reset}
248{style:white on green}{style:black on white}i|{style:white on green} J6{J6:{style} col2}{style:bold white on green} | {style:normal white on black}+--+{style:on green}{style:bold}| {style:normal white on black}|P|{style:on green} |{style:reset}
249{style:white on green}| J8 {J6:{style} col1}{style:bold white on green} | {style:normal black on white},----.{style:on green} {style:white on black}|eM|{style:bold on green}| {style:normal white on black}}}-{{{style:on green} |{style:reset}
250{style:white on green}|{style:bold yellow}O{J8:{style} col2}{style:white on green} {style:bold yellow}O{style:white} | {style:normal black on white}|SoC |{style:on green} {style:white on black}|MC|{style:bold on green}| {style:normal white on black}|C|{style:on green} |{style:reset}
251{style:white on green}| {J8:{style} col1}{style:white on green} PoE {style:bold}| {style:normal black on white}| |{style:on green} {style:white on black}+--+{style:bold on green}| {style:normal white on black}|I|{style:on green} |{style:reset}
252{style:white on green}| {style:black on white},---.{style:white on green} {POE:{style} row1}{style:bold white on green} | {style:normal black on white}`----'{style:white on green} {style:bold}| {style:normal white on black}|e|{style:on green} |{style:reset}
253{style:white on green}|{style:black on white}( ={style:on green}O{style:on white} |{style:white on green} {POE:{style} row2}{style:bold white on green} | {style:normal white on black}+----+{style:on green} {style:bold}|{style:normal} |{style:reset}
254{style:white on green}| {style:black on white}) + |{style:white on green} {style:bold}|{style:yellow}O {style:normal white on black}|RAM |{style:on green} {style:bold yellow}O{style:white}|{style:normal} |{style:reset}
255{style:white on green}|{style:black on white}( ={style:on green}O{style:on white} |{style:white on green} {style:bold}`--{style:normal white on black}+----+{style:bold on green}-----'{style:normal} |{style:reset}
256{style:white on green}| {style:black on white}`---'{style:white on green} |{style:reset}
257{style:white on green}| |{style:reset}
258{style:white on green}| |{style:reset}
259{style:white on green}| {style:bold yellow}O {style:normal black on white}|Net |{style:on green} {style:black on white}|USB|{style:on green} {style:black on white}|uSD|{style:white on green} {style:bold yellow}O{style:normal white on black}|p|{style:on green}|{style:reset}
260{style:white on green}|{style:bold yellow}O {style:normal black on white}|HDMI|{style:on green} {style:black on white}|HDMI|{style:white on green} {style:bold yellow}O {style:normal black on white}| |{style:on green} {style:black on white}| 2 |{style:on green} {style:black on white}usb{style:white on green} {style:black on white}| |{style:white on green} {style:on black}|w|{style:on green}|{style:reset}
261{style:white on green}`----{style:black on white}| 0 |{style:white on green}---{style:black on white}| 1 |{style:white on green}-------{style:black on white}| |{style:white on green}-{style:black on white}| |{style:white on green}-{style:black on white}| |{style:white on green}------------{style:white on black}|r|{style:on green}'{style:reset}"""
263P400_BOARD = """\
264 {style:white on red},------+----+----+----+----+---+--+--+--+--------------------+---.{style:reset}
265 {style:white on red},' |{style:white on black}Net {style:white on red}|{style:white on black}USB {style:white on red}|{style:cyan on black}USB {style:white on red}|{style:cyan on black}USB {style:white on red}|{style:white on black}pwr{style:white on red}|{style:white on black}hd{style:white on red}|{style:white on black}hd{style:white on red}|{style:white on black}sd{style:white on red}|{J8:{style} col2}{style:white on red}| `.{style:reset}
266 {style:white on red}/ {style:black}=={style:white} |{style:white on black} {style:white on red}|{style:white on black} 2 {style:white on red}|{style:cyan on black} 3 {style:white on red}|{style:cyan on black} 3 {style:white on red}|{style:white on black} {style:white on red}|{style:white on black}m1{style:white on red}|{style:white on black}m0{style:white on red}|{style:white on black} {style:white on red}|{J8:{style} col1}{style:white on red}| \\{style:reset}
267{style:black on white},------------------------------------------------------------------------.{style:reset}
268{style:black on white}| ___ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ {style:bold on white}o o {style:green}o{style:normal black}____ |{style:reset}
269{style:black on white}| |Esc|F1{style:red}11{style:black}|F2{style:red}12{style:black}|F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10{style:red}o{style:black}|NumL|Pt{style:red}Sq{style:black}|Dl{style:red}In{style:black}| |{style:reset}
270{style:black on white}| ___ ___ ____ ____ ____ ____ ____ ___ ____ ____ ____ ___ ____ _______ |{style:reset}
271{style:black on white}| |¬ |! |" |£ |$ |% |^ |& {style:red}7{style:black}|* {style:red}8{style:black}|( {style:red}9{style:black}|) {style:red}*{style:black}|_ |+ |BkSpc | |{style:reset}
272{style:black on white}| |` ||1 |2 |3 |4 |5 |6 |7 |8 |9 |0 |- |= |<-- | |{style:reset}
273{style:black on white}| _____ ___ ____ ____ ____ ____ ____ ___ ____ ____ ____ ____ __ ______ |{style:reset}
274{style:black on white}| |Tab |Q |W |E |R |T |Y |U {style:red}4{style:black}|I {style:red}5{style:black}|O {style:red}6{style:black}|P {style:red}-{style:black}|{{ |}} |Enter | |{style:reset}
275{style:black on white}| |->| | | | | | | | | | | |[ |] |<-' | |{style:reset}
276{style:black on white}| ______ ____ ____ ____ ____ ____ ____ ___ ____ ____ ____ ____ __ | |{style:reset}
277{style:black on white}| |Caps |A |S |D |F |G |H |J {style:red}1{style:black}|K {style:red}2{style:black}|L {style:red}3{style:black}|: {style:red}+{style:black}|@ |~ | | |{style:reset}
278{style:black on white}| |Lock | | | | | | | | | |; |' |# | | |{style:reset}
279{style:black on white}| _____ ___ ___ ____ ____ ____ ____ ____ ___ ____ ____ ____ __________ |{style:reset}
280{style:black on white}| |Shift|| |Z |X |C |V |B |N |M {style:red}0{style:black}|< |> {style:red}.{style:black}|? {style:red}/{style:black}|Shift | |{style:reset}
281{style:black on white}| |^ |\\ | | | | | | | |, |. |/ |^ | |{style:reset}
282{style:black on white}| ____ ___ ____ ____ _______________________ ____ ____ _____ |{style:reset}
283{style:black on white}| |Ctrl|{style:red}Fn{style:black} | {style:red}**{style:black} |Alt | |Alt |Ctrl|____|^{style:red}PgUp{style:black}|____ |{style:reset}
284{style:black on white}| | | | {style:red}{{}}{style:black} | | | | |<{style:red}Hom{style:black}|v{style:red}PgDn{style:black}|>{style:red}End{style:black}| |{style:reset}
285{style:black on white}`------------------------------------------------------------------------'{style:reset}
286 Raspberry Pi {style:bold red}{model}{style:reset} Rev {pcb_revision}"""
288# Pin maps for various board revisions and headers
290REV1_P1 = {
291# pin func pullup pin func pullup
292 1: (V3_3, False), 2: (V5, False),
293 3: (GPIO0, True), 4: (V5, False),
294 5: (GPIO1, True), 6: (GND, False),
295 7: (GPIO4, False), 8: (GPIO14, False),
296 9: (GND, False), 10: (GPIO15, False),
297 11: (GPIO17, False), 12: (GPIO18, False),
298 13: (GPIO21, False), 14: (GND, False),
299 15: (GPIO22, False), 16: (GPIO23, False),
300 17: (V3_3, False), 18: (GPIO24, False),
301 19: (GPIO10, False), 20: (GND, False),
302 21: (GPIO9, False), 22: (GPIO25, False),
303 23: (GPIO11, False), 24: (GPIO8, False),
304 25: (GND, False), 26: (GPIO7, False),
305 }
307REV2_P1 = {
308 1: (V3_3, False), 2: (V5, False),
309 3: (GPIO2, True), 4: (V5, False),
310 5: (GPIO3, True), 6: (GND, False),
311 7: (GPIO4, False), 8: (GPIO14, False),
312 9: (GND, False), 10: (GPIO15, False),
313 11: (GPIO17, False), 12: (GPIO18, False),
314 13: (GPIO27, False), 14: (GND, False),
315 15: (GPIO22, False), 16: (GPIO23, False),
316 17: (V3_3, False), 18: (GPIO24, False),
317 19: (GPIO10, False), 20: (GND, False),
318 21: (GPIO9, False), 22: (GPIO25, False),
319 23: (GPIO11, False), 24: (GPIO8, False),
320 25: (GND, False), 26: (GPIO7, False),
321 }
323REV2_P5 = {
324 1: (V5, False), 2: (V3_3, False),
325 3: (GPIO28, False), 4: (GPIO29, False),
326 5: (GPIO30, False), 6: (GPIO31, False),
327 7: (GND, False), 8: (GND, False),
328 }
330PLUS_J8 = {
331 1: (V3_3, False), 2: (V5, False),
332 3: (GPIO2, True), 4: (V5, False),
333 5: (GPIO3, True), 6: (GND, False),
334 7: (GPIO4, False), 8: (GPIO14, False),
335 9: (GND, False), 10: (GPIO15, False),
336 11: (GPIO17, False), 12: (GPIO18, False),
337 13: (GPIO27, False), 14: (GND, False),
338 15: (GPIO22, False), 16: (GPIO23, False),
339 17: (V3_3, False), 18: (GPIO24, False),
340 19: (GPIO10, False), 20: (GND, False),
341 21: (GPIO9, False), 22: (GPIO25, False),
342 23: (GPIO11, False), 24: (GPIO8, False),
343 25: (GND, False), 26: (GPIO7, False),
344 27: (GPIO0, False), 28: (GPIO1, False),
345 29: (GPIO5, False), 30: (GND, False),
346 31: (GPIO6, False), 32: (GPIO12, False),
347 33: (GPIO13, False), 34: (GND, False),
348 35: (GPIO19, False), 36: (GPIO16, False),
349 37: (GPIO26, False), 38: (GPIO20, False),
350 39: (GND, False), 40: (GPIO21, False),
351 }
353PLUS_POE = {
354 1: ('TR01', False), 2: ('TR00', False),
355 3: ('TR03', False), 4: ('TR02', False),
356 }
358CM_SODIMM = {
359 1: (GND, False), 2: ('EMMC DISABLE N', False),
360 3: (GPIO0, False), 4: (NC, False),
361 5: (GPIO1, False), 6: (NC, False),
362 7: (GND, False), 8: (NC, False),
363 9: (GPIO2, False), 10: (NC, False),
364 11: (GPIO3, False), 12: (NC, False),
365 13: (GND, False), 14: (NC, False),
366 15: (GPIO4, False), 16: (NC, False),
367 17: (GPIO5, False), 18: (NC, False),
368 19: (GND, False), 20: (NC, False),
369 21: (GPIO6, False), 22: (NC, False),
370 23: (GPIO7, False), 24: (NC, False),
371 25: (GND, False), 26: (GND, False),
372 27: (GPIO8, False), 28: (GPIO28, False),
373 29: (GPIO9, False), 30: (GPIO29, False),
374 31: (GND, False), 32: (GND, False),
375 33: (GPIO10, False), 34: (GPIO30, False),
376 35: (GPIO11, False), 36: (GPIO31, False),
377 37: (GND, False), 38: (GND, False),
378 39: ('GPIO0-27 VREF', False), 40: ('GPIO0-27 VREF', False),
379 # Gap in SODIMM pins
380 41: ('GPIO28-45 VREF', False), 42: ('GPIO28-45 VREF', False),
381 43: (GND, False), 44: (GND, False),
382 45: (GPIO12, False), 46: (GPIO32, False),
383 47: (GPIO13, False), 48: (GPIO33, False),
384 49: (GND, False), 50: (GND, False),
385 51: (GPIO14, False), 52: (GPIO34, False),
386 53: (GPIO15, False), 54: (GPIO35, False),
387 55: (GND, False), 56: (GND, False),
388 57: (GPIO16, False), 58: (GPIO36, False),
389 59: (GPIO17, False), 60: (GPIO37, False),
390 61: (GND, False), 62: (GND, False),
391 63: (GPIO18, False), 64: (GPIO38, False),
392 65: (GPIO19, False), 66: (GPIO39, False),
393 67: (GND, False), 68: (GND, False),
394 69: (GPIO20, False), 70: (GPIO40, False),
395 71: (GPIO21, False), 72: (GPIO41, False),
396 73: (GND, False), 74: (GND, False),
397 75: (GPIO22, False), 76: (GPIO42, False),
398 77: (GPIO23, False), 78: (GPIO43, False),
399 79: (GND, False), 80: (GND, False),
400 81: (GPIO24, False), 82: (GPIO44, False),
401 83: (GPIO25, False), 84: (GPIO45, False),
402 85: (GND, False), 86: (GND, False),
403 87: (GPIO26, False), 88: ('GPIO46 1V8', False),
404 89: (GPIO27, False), 90: ('GPIO47 1V8', False),
405 91: (GND, False), 92: (GND, False),
406 93: ('DSI0 DN1', False), 94: ('DSI1 DP0', False),
407 95: ('DSI0 DP1', False), 96: ('DSI1 DN0', False),
408 97: (GND, False), 98: (GND, False),
409 99: ('DSI0 DN0', False), 100: ('DSI1 CP', False),
410 101: ('DSI0 DP0', False), 102: ('DSI1 CN', False),
411 103: (GND, False), 104: (GND, False),
412 105: ('DSI0 CN', False), 106: ('DSI1 DP3', False),
413 107: ('DSI0 CP', False), 108: ('DSI1 DN3', False),
414 109: (GND, False), 110: (GND, False),
415 111: ('HDMI CK N', False), 112: ('DSI1 DP2', False),
416 113: ('HDMI CK P', False), 114: ('DSI1 DN2', False),
417 115: (GND, False), 116: (GND, False),
418 117: ('HDMI D0 N', False), 118: ('DSI1 DP1', False),
419 119: ('HDMI D0 P', False), 120: ('DSI1 DN1', False),
420 121: (GND, False), 122: (GND, False),
421 123: ('HDMI D1 N', False), 124: (NC, False),
422 125: ('HDMI D1 P', False), 126: (NC, False),
423 127: (GND, False), 128: (NC, False),
424 129: ('HDMI D2 N', False), 130: (NC, False),
425 131: ('HDMI D2 P', False), 132: (NC, False),
426 133: (GND, False), 134: (GND, False),
427 135: ('CAM1 DP3', False), 136: ('CAM0 DP0', False),
428 137: ('CAM1 DN3', False), 138: ('CAM0 DN0', False),
429 139: (GND, False), 140: (GND, False),
430 141: ('CAM1 DP2', False), 142: ('CAM0 CP', False),
431 143: ('CAM1 DN2', False), 144: ('CAM0 CN', False),
432 145: (GND, False), 146: (GND, False),
433 147: ('CAM1 CP', False), 148: ('CAM0 DP1', False),
434 149: ('CAM1 CN', False), 150: ('CAM0 DN1', False),
435 151: (GND, False), 152: (GND, False),
436 153: ('CAM1 DP1', False), 154: (NC, False),
437 155: ('CAM1 DN1', False), 156: (NC, False),
438 157: (GND, False), 158: (NC, False),
439 159: ('CAM1 DP0', False), 160: (NC, False),
440 161: ('CAM1 DN0', False), 162: (NC, False),
441 163: (GND, False), 164: (GND, False),
442 165: ('USB DP', False), 166: ('TVDAC', False),
443 167: ('USB DM', False), 168: ('USB OTGID', False),
444 169: (GND, False), 170: (GND, False),
445 171: ('HDMI CEC', False), 172: ('VC TRST N', False),
446 173: ('HDMI SDA', False), 174: ('VC TDI', False),
447 175: ('HDMI SCL', False), 176: ('VC TMS', False),
448 177: ('RUN', False), 178: ('VC TDO', False),
449 179: ('VDD CORE', False), 180: ('VC TCK', False),
450 181: (GND, False), 182: (GND, False),
451 183: (V1_8, False), 184: (V1_8, False),
452 185: (V1_8, False), 186: (V1_8, False),
453 187: (GND, False), 188: (GND, False),
454 189: ('VDAC', False), 190: ('VDAC', False),
455 191: (V3_3, False), 192: (V3_3, False),
456 193: (V3_3, False), 194: (V3_3, False),
457 195: (GND, False), 196: (GND, False),
458 197: ('VBAT', False), 198: ('VBAT', False),
459 199: ('VBAT', False), 200: ('VBAT', False),
460 }
462CM3_SODIMM = CM_SODIMM.copy()
463CM3_SODIMM.update({
464 4: ('NC / SDX VREF', False),
465 6: ('NC / SDX VREF', False),
466 8: (GND, False),
467 10: ('NC / SDX CLK', False),
468 12: ('NC / SDX CMD', False),
469 14: (GND, False),
470 16: ('NC / SDX D0', False),
471 18: ('NC / SDX D1', False),
472 20: (GND, False),
473 22: ('NC / SDX D2', False),
474 24: ('NC / SDX D3', False),
475 88: ('HDMI HPD N 1V8', False),
476 90: ('EMMC EN N 1V8', False),
477 })
479CM4_J6 = {
480 1: ('1-2 CAM0+DISP0', False), 2: ('1-2 CAM0+DISP0', False),
481 3: ('3-4 CAM0+DISP0', False), 4: ('3-4 CAM0+DISP0', False),
482 }
484CM4_J2 = {
485 1: ('1-2 DISABLE eMMC BOOT', False), 2: ('1-2 DISABLE eMMC BOOT', False),
486 3: ('3-4 WRITE-PROT EEPROM', False), 4: ('3-4 WRITE-PROT EEPROM', False),
487 5: ('UNKNOWN', False), 6: ('UNKNOWN', False),
488 7: ('UNKNOWN', False), 8: ('UNKNOWN', False),
489 9: ('UNKNOWN', False), 10: ('UNKNOWN', False),
490 11: ('UNKNOWN', False), 12: ('UNKNOWN', False),
491 13: ('UNKNOWN', False), 14: ('UNKNOWN', False),
492 }
494# The following data is sourced from a combination of the following locations:
495#
496# http://elinux.org/RPi_HardwareHistory
497# http://elinux.org/RPi_Low-level_peripherals
498# https://git.drogon.net/?p=wiringPi;a=blob;f=wiringPi/wiringPi.c#l807
499# https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
501PI_REVISIONS = {
502 # rev model pcb_rev released soc manufacturer ram storage usb eth wifi bt csi dsi headers board
503 0x2: ('B', '1.0', '2012Q1', 'BCM2835', 'Egoman', 256, 'SD', 2, 1, False, False, 1, 1, {'P1': REV1_P1}, REV1_BOARD, ),
504 0x3: ('B', '1.0', '2012Q3', 'BCM2835', 'Egoman', 256, 'SD', 2, 1, False, False, 1, 1, {'P1': REV1_P1}, REV1_BOARD, ),
505 0x4: ('B', '2.0', '2012Q3', 'BCM2835', 'Sony', 256, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
506 0x5: ('B', '2.0', '2012Q4', 'BCM2835', 'Qisda', 256, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
507 0x6: ('B', '2.0', '2012Q4', 'BCM2835', 'Egoman', 256, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
508 0x7: ('A', '2.0', '2013Q1', 'BCM2835', 'Egoman', 256, 'SD', 1, 0, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD, ),
509 0x8: ('A', '2.0', '2013Q1', 'BCM2835', 'Sony', 256, 'SD', 1, 0, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD, ),
510 0x9: ('A', '2.0', '2013Q1', 'BCM2835', 'Qisda', 256, 'SD', 1, 0, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD, ),
511 0xd: ('B', '2.0', '2012Q4', 'BCM2835', 'Egoman', 512, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
512 0xe: ('B', '2.0', '2012Q4', 'BCM2835', 'Sony', 512, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
513 0xf: ('B', '2.0', '2012Q4', 'BCM2835', 'Qisda', 512, 'SD', 2, 1, False, False, 1, 1, {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD, ),
514 0x10: ('B+', '1.2', '2014Q3', 'BCM2835', 'Sony', 512, 'MicroSD', 4, 1, False, False, 1, 1, {'J8': PLUS_J8}, BPLUS_BOARD, ),
515 0x11: ('CM', '1.1', '2014Q2', 'BCM2835', 'Sony', 512, 'eMMC', 1, 0, False, False, 2, 2, {'SODIMM': CM_SODIMM}, CM_BOARD, ),
516 0x12: ('A+', '1.1', '2014Q4', 'BCM2835', 'Sony', 256, 'MicroSD', 1, 0, False, False, 1, 1, {'J8': PLUS_J8}, APLUS_BOARD, ),
517 0x13: ('B+', '1.2', '2015Q1', 'BCM2835', 'Egoman', 512, 'MicroSD', 4, 1, False, False, 1, 1, {'J8': PLUS_J8}, BPLUS_BOARD, ),
518 0x14: ('CM', '1.1', '2014Q2', 'BCM2835', 'Embest', 512, 'eMMC', 1, 0, False, False, 2, 2, {'SODIMM': CM_SODIMM}, CM_BOARD, ),
519 0x15: ('A+', '1.1', '2014Q4', 'BCM2835', 'Embest', 256, 'MicroSD', 1, 0, False, False, 1, 1, {'J8': PLUS_J8}, APLUS_BOARD, ),
520 }
523# ANSI color codes, for the pretty printers (nothing comprehensive, just enough
524# for our purposes)
526class Style(object):
527 def __init__(self, color=None):
528 self.color = self._term_supports_color() if color is None else bool(color)
529 self.effects = {
530 'reset': 0,
531 'bold': 1,
532 'normal': 22,
533 }
534 self.colors = {
535 'black': 0,
536 'red': 1,
537 'green': 2,
538 'yellow': 3,
539 'blue': 4,
540 'magenta': 5,
541 'cyan': 6,
542 'white': 7,
543 'default': 9,
544 }
546 @staticmethod
547 def _term_supports_color():
548 try:
549 stdout_fd = sys.stdout.fileno()
550 except IOError:
551 return False
552 else:
553 is_a_tty = os.isatty(stdout_fd)
554 is_windows = sys.platform.startswith('win')
555 return is_a_tty and not is_windows
557 @classmethod
558 def from_style_content(cls, format_spec):
559 specs = set(format_spec.split())
560 style = specs & {'mono', 'color'}
561 content = specs - style
562 if len(style) > 1:
563 raise ValueError('cannot specify both mono and color styles')
564 try:
565 style = style.pop()
566 except KeyError:
567 style = 'color' if cls._term_supports_color() else 'mono'
568 if len(content) > 1:
569 raise ValueError('cannot specify more than one content element')
570 try:
571 content = content.pop()
572 except KeyError:
573 content = 'full'
574 return cls(style == 'color'), content
576 def __call__(self, format_spec):
577 specs = format_spec.split()
578 codes = []
579 fore = True
580 for spec in specs:
581 if spec == 'on':
582 fore = False
583 else:
584 try:
585 codes.append(self.effects[spec])
586 except KeyError:
587 try:
588 if fore:
589 codes.append(30 + self.colors[spec])
590 else:
591 codes.append(40 + self.colors[spec])
592 except KeyError:
593 raise ValueError(
594 'invalid format specification "%s"' % spec)
595 if self.color:
596 return '\x1b[%sm' % (';'.join(str(code) for code in codes))
597 else:
598 return ''
600 def __format__(self, format_spec):
601 if format_spec == '':
602 return 'color' if self.color else 'mono'
603 else:
604 return self(format_spec)
607class PinInfo(namedtuple('PinInfo', (
608 'number',
609 'function',
610 'pull_up',
611 'row',
612 'col',
613 ))):
614 """
615 This class is a :func:`~collections.namedtuple` derivative used to
616 represent information about a pin present on a GPIO header. The following
617 attributes are defined:
619 .. attribute:: number
621 An integer containing the physical pin number on the header (starting
622 from 1 in accordance with convention).
624 .. attribute:: function
626 A string describing the function of the pin. Some common examples
627 include "GND" (for pins connecting to ground), "3V3" (for pins which
628 output 3.3 volts), "GPIO9" (for GPIO9 in the Broadcom numbering
629 scheme), etc.
631 .. attribute:: pull_up
633 A bool indicating whether the pin has a physical pull-up resistor
634 permanently attached (this is usually :data:`False` but GPIO2 and GPIO3
635 are *usually* :data:`True`). This is used internally by gpiozero to
636 raise errors when pull-down is requested on a pin with a physical
637 pull-up resistor.
639 .. attribute:: row
641 An integer indicating on which row the pin is physically located in
642 the header (1-based)
644 .. attribute:: col
646 An integer indicating in which column the pin is physically located
647 in the header (1-based)
648 """
649 __slots__ = () # workaround python issue #24931
652class HeaderInfo(namedtuple('HeaderInfo', (
653 'name',
654 'rows',
655 'columns',
656 'pins',
657 ))):
658 """
659 This class is a :func:`~collections.namedtuple` derivative used to
660 represent information about a pin header on a board. The object can be used
661 in a format string with various custom specifications::
663 from gpiozero import *
665 print('{0}'.format(pi_info().headers['J8']))
666 print('{0:full}'.format(pi_info().headers['J8']))
667 print('{0:col2}'.format(pi_info().headers['P1']))
668 print('{0:row1}'.format(pi_info().headers['P1']))
670 "color" and "mono" can be prefixed to format specifications to force the
671 use of `ANSI color codes`_. If neither is specified, ANSI codes will only
672 be used if stdout is detected to be a tty::
674 print('{0:color row2}'.format(pi_info().headers['J8'])) # force use of ANSI codes
675 print('{0:mono row2}'.format(pi_info().headers['P1'])) # force plain ASCII
677 The following attributes are defined:
679 .. automethod:: pprint
681 .. attribute:: name
683 The name of the header, typically as it appears silk-screened on the
684 board (e.g. "P1" or "J8").
686 .. attribute:: rows
688 The number of rows on the header.
690 .. attribute:: columns
692 The number of columns on the header.
694 .. attribute:: pins
696 A dictionary mapping physical pin numbers to :class:`PinInfo` tuples.
698 .. _ANSI color codes: https://en.wikipedia.org/wiki/ANSI_escape_code
699 """
700 __slots__ = () # workaround python issue #24931
702 def _func_style(self, function, style):
703 if function == V5:
704 return style('bold red')
705 elif function in (V3_3, V1_8):
706 return style('bold cyan')
707 elif function in (GND, NC):
708 return style('bold black')
709 elif function.startswith('GPIO') and function[4:].isdigit():
710 return style('bold green')
711 else:
712 return style('yellow')
714 def _format_full(self, style):
715 Cell = namedtuple('Cell', ('content', 'align', 'style'))
717 lines = []
718 for row in range(self.rows):
719 line = []
720 for col in range(self.columns):
721 pin = (row * self.columns) + col + 1
722 try:
723 pin = self.pins[pin]
724 cells = [
725 Cell(pin.function, '><'[col % 2], self._func_style(pin.function, style)),
726 Cell('(%d)' % pin.number, '><'[col % 2], ''),
727 ]
728 if col % 2:
729 cells = reversed(cells)
730 line.extend(cells)
731 except KeyError:
732 line.append(Cell('', '<', ''))
733 lines.append(line)
734 cols = list(zip(*lines))
735 col_lens = [max(len(cell.content) for cell in col) for col in cols]
736 lines = [
737 ' '.join(
738 '{cell.style}{cell.content:{cell.align}{width}s}{style:reset}'.format(
739 cell=cell, width=width, style=style)
740 for cell, width, align in zip(line, col_lens, cycle('><')))
741 for line in lines
742 ]
743 return '\n'.join(lines)
745 def _format_pin(self, pin, style):
746 return ''.join((
747 style('on black'),
748 (
749 ' ' if pin is None else
750 self._func_style(pin.function, style) +
751 ('1' if pin.number == 1 else 'o')
752 ),
753 style('reset')
754 ))
756 def _format_row(self, row, style):
757 if row > self.rows:
758 raise ValueError('invalid row %d for header %s' % (row, self.name))
759 start_pin = (row - 1) * self.columns + 1
760 return ''.join(
761 self._format_pin(pin, style)
762 for n in range(start_pin, start_pin + self.columns)
763 for pin in (self.pins.get(n),)
764 )
766 def _format_col(self, col, style):
767 if col > self.columns:
768 raise ValueError('invalid col %d for header %s' % (col, self.name))
769 return ''.join(
770 self._format_pin(pin, style)
771 for n in range(col, self.rows * self.columns + 1, self.columns)
772 for pin in (self.pins.get(n),)
773 )
775 def __format__(self, format_spec):
776 style, content = Style.from_style_content(format_spec)
777 if content == 'full':
778 return self._format_full(style)
779 elif content.startswith('row') and content[3:].isdigit():
780 return self._format_row(int(content[3:]), style)
781 elif content.startswith('col') and content[3:].isdigit():
782 return self._format_col(int(content[3:]), style)
783 else:
784 raise ValueError('Invalid format specifier')
786 def pprint(self, color=None):
787 """
788 Pretty-print a diagram of the header pins.
790 If *color* is :data:`None` (the default, the diagram will include ANSI
791 color codes if stdout is a color-capable terminal). Otherwise *color*
792 can be set to :data:`True` or :data:`False` to force color or
793 monochrome output.
794 """
795 print('{0:{style} full}'.format(self, style=Style(color)))
798class PiBoardInfo(namedtuple('PiBoardInfo', (
799 'revision',
800 'model',
801 'pcb_revision',
802 'released',
803 'soc',
804 'manufacturer',
805 'memory',
806 'storage',
807 'usb',
808 'usb3',
809 'ethernet',
810 'eth_speed',
811 'wifi',
812 'bluetooth',
813 'csi',
814 'dsi',
815 'headers',
816 'board',
817 ))):
818 """
819 This class is a :func:`~collections.namedtuple` derivative used to
820 represent information about a particular model of Raspberry Pi. While it is
821 a tuple, it is strongly recommended that you use the following named
822 attributes to access the data contained within. The object can be used
823 in format strings with various custom format specifications::
825 from gpiozero import *
827 print('{0}'.format(pi_info()))
828 print('{0:full}'.format(pi_info()))
829 print('{0:board}'.format(pi_info()))
830 print('{0:specs}'.format(pi_info()))
831 print('{0:headers}'.format(pi_info()))
833 "color" and "mono" can be prefixed to format specifications to force the
834 use of `ANSI color codes`_. If neither is specified, ANSI codes will only
835 be used if stdout is detected to be a tty::
837 print('{0:color board}'.format(pi_info())) # force use of ANSI codes
838 print('{0:mono board}'.format(pi_info())) # force plain ASCII
840 .. _ANSI color codes: https://en.wikipedia.org/wiki/ANSI_escape_code
842 .. automethod:: physical_pin
844 .. automethod:: physical_pins
846 .. automethod:: pprint
848 .. automethod:: pulled_up
850 .. automethod:: to_gpio
852 .. attribute:: revision
854 A string indicating the revision of the Pi. This is unique to each
855 revision and can be considered the "key" from which all other
856 attributes are derived. However, in itself the string is fairly
857 meaningless.
859 .. attribute:: model
861 A string containing the model of the Pi (for example, "B", "B+", "A+",
862 "2B", "CM" (for the Compute Module), or "Zero").
864 .. attribute:: pcb_revision
866 A string containing the PCB revision number which is silk-screened onto
867 the Pi (on some models).
869 .. note::
871 This is primarily useful to distinguish between the model B
872 revision 1.0 and 2.0 (not to be confused with the model 2B) which
873 had slightly different pinouts on their 26-pin GPIO headers.
875 .. attribute:: released
877 A string containing an approximate release date for this revision of
878 the Pi (formatted as yyyyQq, e.g. 2012Q1 means the first quarter of
879 2012).
881 .. attribute:: soc
883 A string indicating the SoC (`system on a chip`_) that this revision
884 of the Pi is based upon.
886 .. attribute:: manufacturer
888 A string indicating the name of the manufacturer (usually "Sony" but a
889 few others exist).
891 .. attribute:: memory
893 An integer indicating the amount of memory (in Mb) connected to the
894 SoC.
896 .. note::
898 This can differ substantially from the amount of RAM available
899 to the operating system as the GPU's memory is shared with the
900 CPU. When the camera module is activated, at least 128Mb of RAM
901 is typically reserved for the GPU.
903 .. attribute:: storage
905 A string indicating the type of bootable storage used with this
906 revision of Pi, e.g. "SD", "MicroSD", or "eMMC" (for the Compute
907 Module).
909 .. attribute:: usb
911 An integer indicating how many USB ports are physically present on
912 this revision of the Pi, of any type.
914 .. note::
916 This does *not* include the micro-USB or USB-C port used to power
917 the Pi.
919 .. attribute:: usb3
921 An integer indicating how many of the USB ports are USB3 ports on this
922 revision of the Pi.
924 .. attribute:: ethernet
926 An integer indicating how many Ethernet ports are physically present
927 on this revision of the Pi.
929 .. attribute:: eth_speed
931 An integer indicating the maximum speed (in Mbps) of the Ethernet ports
932 (if any). If no Ethernet ports are present, this is 0.
934 .. attribute:: wifi
936 A bool indicating whether this revision of the Pi has wifi built-in.
938 .. attribute:: bluetooth
940 A bool indicating whether this revision of the Pi has bluetooth
941 built-in.
943 .. attribute:: csi
945 An integer indicating the number of CSI (camera) ports available on
946 this revision of the Pi.
948 .. attribute:: dsi
950 An integer indicating the number of DSI (display) ports available on
951 this revision of the Pi.
953 .. attribute:: headers
955 A dictionary which maps header labels to :class:`HeaderInfo` tuples.
956 For example, to obtain information about header P1 you would query
957 ``headers['P1']``. To obtain information about pin 12 on header J8 you
958 would query ``headers['J8'].pins[12]``.
960 A rendered version of this data can be obtained by using the
961 :class:`PiBoardInfo` object in a format string::
963 from gpiozero import *
964 print('{0:headers}'.format(pi_info()))
966 .. attribute:: board
968 An ASCII art rendition of the board, primarily intended for console
969 pretty-print usage. A more usefully rendered version of this data can
970 be obtained by using the :class:`PiBoardInfo` object in a format
971 string. For example::
973 from gpiozero import *
974 print('{0:board}'.format(pi_info()))
976 .. _system on a chip: https://en.wikipedia.org/wiki/System_on_a_chip
977 """
978 __slots__ = () # workaround python issue #24931
980 @classmethod
981 def from_revision(cls, revision):
982 if revision & 0x800000: 982 ↛ 1177line 982 didn't jump to line 1177, because the condition on line 982 was never false
983 # New-style revision, parse information from bit-pattern:
984 #
985 # MSB -----------------------> LSB
986 # NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
987 #
988 # N - Overvoltage (0=allowed, 1=disallowed)
989 # O - OTP programming (0=allowed, 1=disallowed)
990 # Q - OTP read (0=allowed, 1=disallowed)
991 # u - Unused
992 # W - Warranty bit (0=intact, 1=voided by overclocking)
993 # F - New flag (1=valid new-style revision, 0=old-style)
994 # MMM - Memory size (0=256, 1=512, 2=1024)
995 # CCCC - Manufacturer (0=Sony, 1=Egoman, 2=Embest, 3=Sony Japan, 4=Embest, 5=Stadium)
996 # PPPP - Processor (0=2835, 1=2836, 2=2837)
997 # TTTTTTTT - Type (0=A, 1=B, 2=A+, 3=B+, 4=2B, 5=Alpha (??), 6=CM,
998 # 8=3B, 9=Zero, 10=CM3, 12=Zero W, 13=3B+, 14=3A+)
999 # RRRR - Revision (0, 1, 2, etc.)
1000 revcode_memory = (revision & 0x700000) >> 20
1001 revcode_manufacturer = (revision & 0xf0000) >> 16
1002 revcode_processor = (revision & 0xf000) >> 12
1003 revcode_type = (revision & 0xff0) >> 4
1004 revcode_revision = (revision & 0x0f)
1005 model = {
1006 0x0: 'A',
1007 0x1: 'B',
1008 0x2: 'A+',
1009 0x3: 'B+',
1010 0x4: '2B',
1011 0x6: 'CM',
1012 0x8: '3B',
1013 0x9: 'Zero',
1014 0xa: 'CM3',
1015 0xc: 'Zero W',
1016 0xd: '3B+',
1017 0xe: '3A+',
1018 0x10: 'CM3+',
1019 0x11: '4B',
1020 0x13: '400',
1021 0x14: 'CM4',
1022 }.get(revcode_type, '???')
1023 if model in ('A', 'B'): 1023 ↛ 1024line 1023 didn't jump to line 1024, because the condition on line 1023 was never true
1024 pcb_revision = {
1025 0: '1.0', # is this right?
1026 1: '1.0',
1027 2: '2.0',
1028 }.get(revcode_revision, 'Unknown')
1029 else:
1030 pcb_revision = '1.%d' % revcode_revision
1031 soc = {
1032 0: 'BCM2835',
1033 1: 'BCM2836',
1034 2: 'BCM2837',
1035 3: 'BCM2711',
1036 }.get(revcode_processor, 'Unknown')
1037 manufacturer = {
1038 0: 'Sony',
1039 1: 'Egoman',
1040 2: 'Embest',
1041 3: 'Sony Japan',
1042 4: 'Embest',
1043 5: 'Stadium',
1044 }.get(revcode_manufacturer, 'Unknown')
1045 memory = {
1046 0: 256,
1047 1: 512,
1048 2: 1024,
1049 3: 2048,
1050 4: 4096,
1051 5: 8192,
1052 }.get(revcode_memory, None)
1053 released = {
1054 'A': '2013Q1',
1055 'B': '2012Q1' if pcb_revision == '1.0' else '2012Q4',
1056 'A+': '2014Q4' if memory == 512 else '2016Q3',
1057 'B+': '2014Q3',
1058 '2B': '2015Q1' if pcb_revision in ('1.0', '1.1') else '2016Q3',
1059 'CM': '2014Q2',
1060 '3B': '2016Q1' if manufacturer in ('Sony', 'Embest') else '2016Q4',
1061 'Zero': '2015Q4' if pcb_revision == '1.2' else '2016Q2',
1062 'CM3': '2017Q1',
1063 'Zero W': '2017Q1',
1064 '3B+': '2018Q1',
1065 '3A+': '2018Q4',
1066 'CM3+': '2019Q1',
1067 '4B': '2020Q2' if memory == 8192 else '2019Q2',
1068 'CM4': '2020Q4',
1069 '400': '2020Q4',
1070 }.get(model, 'Unknown')
1071 storage = {
1072 'A': 'SD',
1073 'B': 'SD',
1074 'CM': 'eMMC',
1075 'CM3': 'eMMC / off-board',
1076 'CM3+': 'eMMC / off-board',
1077 'CM4': 'eMMC / off-board',
1078 }.get(model, 'MicroSD')
1079 usb = {
1080 'A': 1,
1081 'A+': 1,
1082 'Zero': 1,
1083 'Zero W': 1,
1084 'B': 2,
1085 'CM': 1,
1086 'CM3': 1,
1087 '3A+': 1,
1088 'CM3+': 1,
1089 'CM4': 2,
1090 '400': 3,
1091 }.get(model, 4)
1092 usb3 = {
1093 '4B': 2,
1094 '400': 2,
1095 }.get(model, 0)
1096 ethernet = {
1097 'A': 0,
1098 'A+': 0,
1099 'Zero': 0,
1100 'Zero W': 0,
1101 'CM': 0,
1102 'CM3': 0,
1103 '3A+': 0,
1104 'CM3+': 0,
1105 }.get(model, 1)
1106 eth_speed = {
1107 'B': 100,
1108 'B+': 100,
1109 '2B': 100,
1110 '3B': 100,
1111 '3B+': 300,
1112 '4B': 1000,
1113 '400': 1000,
1114 'CM4': 1000,
1115 }.get(model, 0)
1116 wifi = {
1117 '3B': True,
1118 'Zero W': True,
1119 '3B+': True,
1120 '3A+': True,
1121 '4B': True,
1122 '400': True,
1123 'CM4': True,
1124 }.get(model, False)
1125 bluetooth = {
1126 '3B': True,
1127 'Zero W': True,
1128 '3B+': True,
1129 '3A+': True,
1130 '4B': True,
1131 '400': True,
1132 'CM4': True,
1133 }.get(model, False)
1134 csi = {
1135 'Zero': 0 if pcb_revision == '1.0' else 1,
1136 'Zero W': 1,
1137 'CM': 2,
1138 'CM3': 2,
1139 'CM3+': 2,
1140 '400': 0,
1141 'CM4': 2,
1142 }.get(model, 1)
1143 dsi = {
1144 'Zero': 0,
1145 'Zero W': 0,
1146 'CM': 2,
1147 'CM3': 2,
1148 'CM3+': 2,
1149 }.get(model, csi)
1150 headers = {
1151 'A': {'P1': REV2_P1, 'P5': REV2_P5},
1152 'B': {'P1': REV1_P1} if pcb_revision == '1.0' else {'P1': REV2_P1, 'P5': REV2_P5},
1153 'CM': {'SODIMM': CM_SODIMM},
1154 'CM3': {'SODIMM': CM3_SODIMM},
1155 'CM3+': {'SODIMM': CM3_SODIMM},
1156 '3B+': {'J8': PLUS_J8, 'POE': PLUS_POE},
1157 '4B': {'J8': PLUS_J8, 'POE': PLUS_POE},
1158 'CM4': {'J8': PLUS_J8, 'J2': CM4_J2, 'J6': CM4_J6, 'POE': PLUS_POE},
1159 }.get(model, {'J8': PLUS_J8})
1160 board = {
1161 'A': A_BOARD,
1162 'B': REV1_BOARD if pcb_revision == '1.0' else REV2_BOARD,
1163 'A+': APLUS_BOARD,
1164 'CM': CM_BOARD,
1165 'CM3': CM_BOARD,
1166 'CM3+': CM3PLUS_BOARD,
1167 'Zero': ZERO12_BOARD if pcb_revision == '1.2' else ZERO13_BOARD,
1168 'Zero W': ZERO13_BOARD,
1169 '3A+': A3PLUS_BOARD,
1170 '3B+': B3PLUS_BOARD,
1171 '4B': B4_BOARD,
1172 'CM4': CM4_BOARD,
1173 '400': P400_BOARD,
1174 }.get(model, BPLUS_BOARD)
1175 else:
1176 # Old-style revision, use the lookup table
1177 try:
1178 (
1179 model,
1180 pcb_revision,
1181 released,
1182 soc,
1183 manufacturer,
1184 memory,
1185 storage,
1186 usb,
1187 ethernet,
1188 wifi,
1189 bluetooth,
1190 csi,
1191 dsi,
1192 headers,
1193 board,
1194 ) = PI_REVISIONS[revision]
1195 usb3 = 0
1196 eth_speed = ethernet * 100
1197 except KeyError:
1198 raise PinUnknownPi('unknown old-style revision "%x"' % revision)
1199 headers = {
1200 header: HeaderInfo(name=header, rows=max(header_data) // 2, columns=2, pins={
1201 number: PinInfo(
1202 number=number, function=function, pull_up=pull_up,
1203 row=row + 1, col=col + 1)
1204 for number, (function, pull_up) in header_data.items()
1205 for row, col in (divmod(number - 1, 2),)
1206 })
1207 for header, header_data in headers.items()
1208 }
1209 return cls(
1210 '%04x' % revision,
1211 model,
1212 pcb_revision,
1213 released,
1214 soc,
1215 manufacturer,
1216 memory,
1217 storage,
1218 usb,
1219 usb3,
1220 ethernet,
1221 eth_speed,
1222 wifi,
1223 bluetooth,
1224 csi,
1225 dsi,
1226 headers,
1227 board,
1228 )
1230 def physical_pins(self, function):
1231 """
1232 Return the physical pins supporting the specified *function* as tuples
1233 of ``(header, pin_number)`` where *header* is a string specifying the
1234 header containing the *pin_number*. Note that the return value is a
1235 :class:`set` which is not indexable. Use :func:`physical_pin` if you
1236 are expecting a single return value.
1238 :param str function:
1239 The pin function you wish to search for. Usually this is something
1240 like "GPIO9" for Broadcom GPIO pin 9, or "GND" for all the pins
1241 connecting to electrical ground.
1242 """
1243 return {
1244 (header, pin.number)
1245 for (header, info) in self.headers.items()
1246 for pin in info.pins.values()
1247 if pin.function == function
1248 }
1250 def physical_pin(self, function):
1251 """
1252 Return the physical pin supporting the specified *function*. If no pins
1253 support the desired *function*, this function raises :exc:`PinNoPins`.
1254 If multiple pins support the desired *function*, :exc:`PinMultiplePins`
1255 will be raised (use :func:`physical_pins` if you expect multiple pins
1256 in the result, such as for electrical ground).
1258 :param str function:
1259 The pin function you wish to search for. Usually this is something
1260 like "GPIO9" for Broadcom GPIO pin 9.
1261 """
1262 result = self.physical_pins(function)
1263 if len(result) > 1: 1263 ↛ 1264line 1263 didn't jump to line 1264, because the condition on line 1263 was never true
1264 raise PinMultiplePins('multiple pins can be used for %s' % function)
1265 elif result: 1265 ↛ 1268line 1265 didn't jump to line 1268, because the condition on line 1265 was never false
1266 return result.pop()
1267 else:
1268 raise PinNoPins('no pins can be used for %s' % function)
1270 def pulled_up(self, function):
1271 """
1272 Returns a bool indicating whether a physical pull-up is attached to
1273 the pin supporting the specified *function*. Either :exc:`PinNoPins`
1274 or :exc:`PinMultiplePins` may be raised if the function is not
1275 associated with a single pin.
1277 :param str function:
1278 The pin function you wish to determine pull-up for. Usually this is
1279 something like "GPIO9" for Broadcom GPIO pin 9.
1280 """
1281 try:
1282 header, number = self.physical_pin(function)
1283 except PinNoPins:
1284 return False
1285 else:
1286 return self.headers[header].pins[number].pull_up
1288 def to_gpio(self, spec):
1289 """
1290 Parses a pin *spec*, returning the equivalent Broadcom GPIO port number
1291 or raising a :exc:`ValueError` exception if the spec does not represent
1292 a GPIO port.
1294 The *spec* may be given in any of the following forms:
1296 * An integer, which will be accepted as a GPIO number
1297 * 'GPIOn' where n is the GPIO number
1298 * 'WPIn' where n is the `wiringPi`_ pin number
1299 * 'BCMn' where n is the GPIO number (alias of GPIOn)
1300 * 'BOARDn' where n is the physical pin number on the main header
1301 * 'h:n' where h is the header name and n is the physical pin number
1302 (for example J8:5 is physical pin 5 on header J8, which is the main
1303 header on modern Raspberry Pis)
1305 .. _wiringPi: http://wiringpi.com/pins/
1306 """
1307 if isinstance(spec, int): 1307 ↛ 1313line 1307 didn't jump to line 1313, because the condition on line 1307 was never false
1308 if not 0 <= spec < 54: 1308 ↛ 1309line 1308 didn't jump to line 1309, because the condition on line 1308 was never true
1309 raise PinInvalidPin('invalid GPIO port %d specified '
1310 '(range 0..53) ' % spec)
1311 return spec
1312 else:
1313 if isinstance(spec, bytes):
1314 spec = spec.decode('ascii')
1315 spec = spec.upper()
1316 if spec.isdigit():
1317 return self.to_gpio(int(spec))
1318 if spec.startswith('GPIO') and spec[4:].isdigit():
1319 return self.to_gpio(int(spec[4:]))
1320 elif spec.startswith('BCM') and spec[3:].isdigit():
1321 return self.to_gpio(int(spec[3:]))
1322 elif spec.startswith('WPI') and spec[3:].isdigit():
1323 main_head = 'P1' if 'P1' in self.headers else 'J8'
1324 try:
1325 return self.to_gpio({
1326 0: '%s:11' % main_head,
1327 1: '%s:12' % main_head,
1328 2: '%s:13' % main_head,
1329 3: '%s:15' % main_head,
1330 4: '%s:16' % main_head,
1331 5: '%s:18' % main_head,
1332 6: '%s:22' % main_head,
1333 7: '%s:7' % main_head,
1334 8: '%s:3' % main_head,
1335 9: '%s:5' % main_head,
1336 10: '%s:24' % main_head,
1337 11: '%s:26' % main_head,
1338 12: '%s:19' % main_head,
1339 13: '%s:21' % main_head,
1340 14: '%s:23' % main_head,
1341 15: '%s:8' % main_head,
1342 16: '%s:10' % main_head,
1343 17: 'P5:3',
1344 18: 'P5:4',
1345 19: 'P5:5',
1346 20: 'P5:6',
1347 21: '%s:29' % main_head,
1348 22: '%s:31' % main_head,
1349 23: '%s:33' % main_head,
1350 24: '%s:35' % main_head,
1351 25: '%s:37' % main_head,
1352 26: '%s:32' % main_head,
1353 27: '%s:36' % main_head,
1354 28: '%s:38' % main_head,
1355 29: '%s:40' % main_head,
1356 30: '%s:27' % main_head,
1357 31: '%s:28' % main_head,
1358 }[int(spec[3:])])
1359 except KeyError:
1360 raise PinInvalidPin('%s is not a valid wiringPi pin' % spec)
1361 elif ':' in spec:
1362 header, pin = spec.split(':', 1)
1363 if pin.isdigit():
1364 try:
1365 header = self.headers[header]
1366 except KeyError:
1367 raise PinInvalidPin(
1368 'there is no %s header on this Pi' % header)
1369 try:
1370 function = header.pins[int(pin)].function
1371 except KeyError:
1372 raise PinInvalidPin(
1373 'no such pin %s on header %s' % (pin, header.name))
1374 if function.startswith('GPIO') and function[4:].isdigit():
1375 return self.to_gpio(int(function[4:]))
1376 else:
1377 raise PinInvalidPin('%s is not a GPIO pin' % spec)
1378 elif spec.startswith('BOARD') and spec[5:].isdigit():
1379 main_head = ({'P1', 'J8', 'SODIMM'} & set(self.headers)).pop()
1380 return self.to_gpio('%s:%s' % (main_head, spec[5:]))
1381 raise PinInvalidPin('%s is not a valid pin spec' % spec)
1383 def __repr__(self):
1384 return '{cls}({fields})'.format(
1385 cls=self.__class__.__name__,
1386 fields=', '.join(
1387 (
1388 '{name}=...' if name in ('headers', 'board') else
1389 '{name}={value!r}').format(name=name, value=value)
1390 for name, value in zip(self._fields, self)
1391 )
1392 )
1394 def __format__(self, format_spec):
1395 style, content = Style.from_style_content(format_spec)
1396 if content == 'full':
1397 return dedent("""\
1398 {self:{style} board}
1400 {self:{style} specs}
1402 {self:{style} headers}"""
1403 ).format(self=self, style=style)
1404 elif content == 'board':
1405 kw = self._asdict()
1406 kw.update({
1407 name: header
1408 for name, header in self.headers.items()
1409 })
1410 return self.board.format(style=style, **kw)
1411 elif content == 'specs':
1412 specs = self._asdict()
1413 if specs['memory'] < 1024:
1414 specs['memory_unit'] = "MB"
1415 else:
1416 specs['memory'] = int(specs['memory'] / 1024)
1417 specs['memory_unit'] = "GB"
1418 return dedent("""\
1419 {style:bold}Revision {style:reset}: {revision}
1420 {style:bold}SoC {style:reset}: {soc}
1421 {style:bold}RAM {style:reset}: {memory}{memory_unit}
1422 {style:bold}Storage {style:reset}: {storage}
1423 {style:bold}USB ports {style:reset}: {usb} (of which {usb3} USB3)
1424 {style:bold}Ethernet ports {style:reset}: {ethernet} ({eth_speed}Mbps max. speed)
1425 {style:bold}Wi-fi {style:reset}: {wifi}
1426 {style:bold}Bluetooth {style:reset}: {bluetooth}
1427 {style:bold}Camera ports (CSI) {style:reset}: {csi}
1428 {style:bold}Display ports (DSI){style:reset}: {dsi}"""
1429 ).format(style=style, **specs)
1430 elif content == 'headers':
1431 return '\n\n'.join(
1432 dedent("""\
1433 {style:bold}{header.name}{style:reset}:
1434 {header:{style} full}"""
1435 ).format(header=header, style=style)
1436 for header in sorted(self.headers.values(), key=attrgetter('name'))
1437 )
1438 else:
1439 raise ValueError('Invalid format specifier')
1441 def pprint(self, color=None):
1442 """
1443 Pretty-print a representation of the board along with header diagrams.
1445 If *color* is :data:`None` (the default), the diagram will include ANSI
1446 color codes if stdout is a color-capable terminal. Otherwise *color*
1447 can be set to :data:`True` or :data:`False` to force color or monochrome
1448 output.
1449 """
1450 print('{0:{style} full}'.format(self, style=Style(color)))
1453def pi_info(revision=None):
1454 """
1455 Returns a :class:`PiBoardInfo` instance containing information about a
1456 *revision* of the Raspberry Pi.
1458 :param str revision:
1459 The revision of the Pi to return information about. If this is omitted
1460 or :data:`None` (the default), then the library will attempt to determine
1461 the model of Pi it is running on and return information about that.
1462 """
1463 if revision is None:
1464 if Device.pin_factory is None:
1465 Device.pin_factory = Device._default_pin_factory()
1466 result = Device.pin_factory.pi_info
1467 if result is None:
1468 raise PinUnknownPi('The default pin_factory is not attached to a Pi')
1469 else:
1470 return result
1471 else:
1472 if isinstance(revision, bytes):
1473 revision = revision.decode('ascii')
1474 if isinstance(revision, str):
1475 revision = int(revision, base=16)
1476 else:
1477 # be nice to people passing an int (or something numeric anyway)
1478 revision = int(revision)
1479 return PiBoardInfo.from_revision(revision)