mirror of
				https://github.com/KevinMidboe/python-gpiozero.git
				synced 2025-10-29 17:50:37 +00:00 
			
		
		
		
	Fix #354
Actually, "fix" doesn't really do this justice. This is closer to "nukes from orbit" ...
This commit is contained in:
		| @@ -11,6 +11,7 @@ from .pins import ( | ||||
| ) | ||||
| from .pins.data import ( | ||||
|     PiBoardInfo, | ||||
|     HeaderInfo, | ||||
|     PinInfo, | ||||
|     pi_info, | ||||
| ) | ||||
|   | ||||
| @@ -7,6 +7,11 @@ from __future__ import ( | ||||
| str = type('') | ||||
|  | ||||
| import io | ||||
| import os | ||||
| import sys | ||||
| from textwrap import dedent | ||||
| from itertools import cycle | ||||
| from operator import attrgetter | ||||
| from collections import namedtuple | ||||
|  | ||||
| from ..exc import PinUnknownPi, PinMultiplePins, PinNoPins | ||||
| @@ -66,6 +71,110 @@ GPIO43 = 'GPIO43' | ||||
| GPIO44 = 'GPIO44' | ||||
| GPIO45 = 'GPIO45' | ||||
|  | ||||
| # Board layout ASCII art | ||||
|  | ||||
| REV1_BOARD = """\ | ||||
| {style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset} | ||||
| {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} | ||||
| {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} | ||||
| {style:white on green}|                                |{style:reset} | ||||
| {style:white on green}|                {style:on black}+---+{style:on green}          {style:black on white}+===={style:reset} | ||||
| {style:white on green}|                {style:on black}|SoC|{style:on green}          {style:black on white}| USB{style:reset} | ||||
| {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} | ||||
| {style:white on green}|   {style:on black}|S|{style:on green} {style:bold}{model:2s} V{pcb_revision:3s}{style:normal}                  |{style:reset} | ||||
| {style:white on green}|   {style:on black}|I|{style:on green}                  {style:on black}|C|{style:black on white}+======{style:reset} | ||||
| {style:white on green}|                        {style:on black}|S|{style:black on white}|   Net{style:reset} | ||||
| {style:white on green}|                        {style:on black}|I|{style:black on white}+======{style:reset} | ||||
| {style:black on white}=pwr{style:on green}             {style:on white}|HDMI|{style:white on green}          |{style:reset} | ||||
| {style:white on green}+----------------{style:black on white}|    |{style:white on green}----------+{style:reset}""" | ||||
|  | ||||
| REV2_BOARD = """\ | ||||
| {style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset} | ||||
| {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} | ||||
| {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} | ||||
| {style:white on green}|    {P5:{style} col1}{style:white on green}                        |{style:reset} | ||||
| {style:white on green}| P5 {P5:{style} col2}{style:white on green}        {style:on black}+---+{style:on green}          {style:black on white}+===={style:reset} | ||||
| {style:white on green}|                {style:on black}|SoC|{style:on green}          {style:black on white}| USB{style:reset} | ||||
| {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} | ||||
| {style:white on green}|   {style:on black}|S|{style:on green} {style:bold}{model:2s} V{pcb_revision:3s}{style:normal}                  |{style:reset} | ||||
| {style:white on green}|   {style:on black}|I|{style:on green}                  {style:on black}|C|{style:black on white}+======{style:reset} | ||||
| {style:white on green}|                        {style:on black}|S|{style:black on white}|   Net{style:reset} | ||||
| {style:white on green}|                        {style:on black}|I|{style:black on white}+======{style:reset} | ||||
| {style:black on white}=pwr{style:on green}             {style:on white}|HDMI|{style:white on green}          |{style:reset} | ||||
| {style:white on green}+----------------{style:black on white}|    |{style:white on green}----------+{style:reset}""" | ||||
|  | ||||
| A_BOARD = """\ | ||||
| {style:white on green}+------------------{style:black on white}| |{style:white on green}--{style:on cyan}| |{style:on green}------+{style:reset} | ||||
| {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} | ||||
| {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} | ||||
| {style:white on green}|    {P5:{style} col1}{style:white on green}                        |{style:reset} | ||||
| {style:white on green}| P5 {P5:{style} col2}{style:white on green}        {style:on black}+---+{style:on green}          {style:black on white}+===={style:reset} | ||||
| {style:white on green}|                {style:on black}|SoC|{style:on green}          {style:black on white}| USB{style:reset} | ||||
| {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} | ||||
| {style:white on green}|   {style:on black}|S|{style:on green} {style:bold}{model:2s} V{pcb_revision:3s}{style:normal}                  |{style:reset} | ||||
| {style:white on green}|   {style:on black}|I|{style:on green}                  {style:on black}|C|{style:on green}     |{style:reset} | ||||
| {style:white on green}|                        {style:on black}|S|{style:on green}     |{style:reset} | ||||
| {style:white on green}|                        {style:on black}|I|{style:on green}     |{style:reset} | ||||
| {style:black on white}=pwr{style:on green}             {style:on white}|HDMI|{style:white on green}          |{style:reset} | ||||
| {style:white on green}+----------------{style:black on white}|    |{style:white on green}----------+{style:reset}""" | ||||
|  | ||||
| BPLUS_BOARD = """\ | ||||
| {style:white on green},--------------------------------.{style:reset} | ||||
| {style:white on green}| {P1:{style} col2}{style:white on green} P1     {style:black on white}+===={style:reset} | ||||
| {style:white on green}| {P1:{style} col1}{style:white on green}        {style:black on white}| USB{style:reset} | ||||
| {style:white on green}|                             {style:black on white}+===={style:reset} | ||||
| {style:white on green}|      {style:bold}Pi Model {model:2s} V{pcb_revision:3s}{style:normal}          |{style:reset} | ||||
| {style:white on green}|      {style:on black}+----+{style:on green}                 {style:black on white}+===={style:reset} | ||||
| {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} | ||||
| {style:white on green}| {style:on black}|S|{style:on green}  {style:on black}|    |{style:on green}                 {style:black on white}+===={style:reset} | ||||
| {style:white on green}| {style:on black}|I|{style:on green}  {style:on black}+----+{style:on green}                    |{style:reset} | ||||
| {style:white on green}|                   {style:on black}|C|{style:on green}     {style:black on white}+======{style:reset} | ||||
| {style:white on green}|                   {style:on black}|S|{style:on green}     {style:black on white}|   Net{style:reset} | ||||
| {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} | ||||
| {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}""" | ||||
|  | ||||
| APLUS_BOARD = """\ | ||||
| {style:white on green},--------------------------.{style:reset} | ||||
| {style:white on green}| {P1:{style} col2}{style:white on green} P1  |{style:reset} | ||||
| {style:white on green}| {P1:{style} col1}{style:white on green}     |{style:reset} | ||||
| {style:white on green}|                          |{style:reset} | ||||
| {style:white on green}|      {style:bold}Pi Model {model:2s} V{pcb_revision:3s}{style:normal}    |{style:reset} | ||||
| {style:white on green}|      {style:on black}+----+{style:on green}           {style:black on white}+===={style:reset} | ||||
| {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} | ||||
| {style:white on green}| {style:on black}|S|{style:on green}  {style:on black}|    |{style:on green}           {style:black on white}+===={style:reset} | ||||
| {style:white on green}| {style:on black}|I|{style:on green}  {style:on black}+----+{style:on green}              |{style:reset} | ||||
| {style:white on green}|                   {style:on black}|C|{style:on green}    |{style:reset} | ||||
| {style:white on green}|                   {style:on black}|S|{style:on green}    |{style:reset} | ||||
| {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} | ||||
| {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}""" | ||||
|  | ||||
| ZERO12_BOARD = """\ | ||||
| {style:white on green},-------------------------.{style:reset} | ||||
| {style:white on green}| {P1:{style} col2}{style:white on green} P1 |{style:reset} | ||||
| {style:white on green}| {P1:{style} col1}{style:white on green}    |{style:reset} | ||||
| {style:black on white}---+{style:white on green}       {style:on black}+----+{style:on green} {style:bold}PiZero{style:normal}  |{style:reset} | ||||
| {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} | ||||
| {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} | ||||
| {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}""" | ||||
|  | ||||
| ZERO13_BOARD = """\ | ||||
| {style:white on green}.-------------------------.{style:reset} | ||||
| {style:white on green}| {P1:{style} col2}{style:white on green} P1 |{style:reset} | ||||
| {style:white on green}| {P1:{style} col1}{style:white on green}   {style:black on white}|c{style:reset} | ||||
| {style:black on white}---+{style:white on green}       {style:on black}+----+{style:on green} {style:bold}PiZero{style:normal} {style:black on white}|s{style:reset} | ||||
| {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} | ||||
| {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} | ||||
| {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}""" | ||||
|  | ||||
| CM_BOARD = """\ | ||||
| {style:white on green}+-----------------------------------------------------------------------------------------------------------------------+{style:reset} | ||||
| {style:white on green}| Raspberry Pi Compute Module                                                                                           |{style:reset} | ||||
| {style:white on green}|                                                                                                                       |{style:reset} | ||||
| {style:white on green}| You were expecting more detail? Sorry, the Compute Module's a bit hard to do right now!                               |{style:reset} | ||||
| {style:white on green}|                                                                                                                       |{style:reset} | ||||
| {style:white on green}|                                                                                                                       |{style:reset} | ||||
| {style:white on green}||||||||||||||||||||-||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||{style:reset}""" | ||||
|  | ||||
| # Pin maps for various board revisions and headers | ||||
|  | ||||
| REV1_P1 = { | ||||
| @@ -242,37 +351,113 @@ CM_SODIMM = { | ||||
| # 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 | ||||
|     0x2:      ('B',    '1.0', '2012Q1', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     0x3:      ('B',    '1.0', '2012Q3', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},               ), | ||||
|     0x4:      ('B',    '2.0', '2012Q3', 'BCM2835', 'Sony',      256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x5:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x6:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x7:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Egoman',    256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x8:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Sony',      256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x9:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Qisda',     256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xd:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xe:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Sony',      512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0xf:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5},), | ||||
|     0x10:     ('B+',   '1.2', '2014Q3', 'BCM2835', 'Sony',      512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x11:     ('CM',   '1.2', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    1,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     0x12:     ('A+',   '1.2', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x13:     ('B+',   '1.2', '2015Q1', 'BCM2835', 'Egoman',    512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x14:     ('CM',   '1.1', '2014Q2', 'BCM2835', 'Embest',    512,  'eMMC',    1,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},         ), | ||||
|     0x15:     ('A+',   '1.1', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa01041: ('2B',   '1.1', '2015Q1', 'BCM2836', 'Sony',      1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa21041: ('2B',   '1.1', '2015Q1', 'BCM2836', 'Embest',    1024, 'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x900092: ('Zero', '1.2', '2015Q4', 'BCM2835', 'Sony',      512,  'MicroSD', 1,  0,  False, False, 0,  0,  {'P1': PLUS_P1},               ), | ||||
|     0xa02082: ('3B',   '1.2', '2016Q1', 'BCM2837', 'Sony',      1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0xa22082: ('3B',   '1.2', '2016Q1', 'BCM2837', 'Embest',    1024, 'MicroSD', 4,  1,  True,  True,  1,  1,  {'P1': PLUS_P1},               ), | ||||
|     0x900093: ('Zero', '1.3', '2016Q2', 'BCM2835', 'Sony',      512,  'MicroSD', 1,  0,  False, False, 1,  0,  {'P1': PLUS_P1},               ), | ||||
|     # rev     model    pcb_rev released soc        manufacturer ram   storage    usb eth wifi   bt     csi dsi headers                         board | ||||
|     0x2:      ('B',    '1.0', '2012Q1', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},                REV1_BOARD,   ), | ||||
|     0x3:      ('B',    '1.0', '2012Q3', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV1_P1},                REV1_BOARD,   ), | ||||
|     0x4:      ('B',    '2.0', '2012Q3', 'BCM2835', 'Sony',      256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0x5:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0x6:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    256,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0x7:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Egoman',    256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD,      ), | ||||
|     0x8:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Sony',      256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD,      ), | ||||
|     0x9:      ('A',    '2.0', '2013Q1', 'BCM2835', 'Qisda',     256,  'SD',      1,  0,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, A_BOARD,      ), | ||||
|     0xd:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Egoman',    512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0xe:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Sony',      512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0xf:      ('B',    '2.0', '2012Q4', 'BCM2835', 'Qisda',     512,  'SD',      2,  1,  False, False, 1,  1,  {'P1': REV2_P1, 'P5': REV2_P5}, REV2_BOARD,   ), | ||||
|     0x10:     ('B+',   '1.2', '2014Q3', 'BCM2835', 'Sony',      512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},                BPLUS_BOARD,  ), | ||||
|     0x11:     ('CM',   '1.1', '2014Q2', 'BCM2835', 'Sony',      512,  'eMMC',    1,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},          CM_BOARD,     ), | ||||
|     0x12:     ('A+',   '1.1', '2014Q4', 'BCM2835', 'Sony',      256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},                APLUS_BOARD,  ), | ||||
|     0x13:     ('B+',   '1.2', '2015Q1', 'BCM2835', 'Egoman',    512,  'MicroSD', 4,  1,  False, False, 1,  1,  {'P1': PLUS_P1},                BPLUS_BOARD,  ), | ||||
|     0x14:     ('CM',   '1.1', '2014Q2', 'BCM2835', 'Embest',    512,  'eMMC',    1,  0,  False, False, 2,  2,  {'SODIMM': CM_SODIMM},          CM_BOARD,     ), | ||||
|     0x15:     ('A+',   '1.1', '2014Q4', 'BCM2835', 'Embest',    256,  'MicroSD', 1,  0,  False, False, 1,  1,  {'P1': PLUS_P1},                APLUS_BOARD,  ), | ||||
|     } | ||||
|  | ||||
|  | ||||
| # ANSI color codes, for the pretty printers (nothing comprehensive, just enough | ||||
| # for our purposes) | ||||
|  | ||||
| class Style(object): | ||||
|     def __init__(self, color=None): | ||||
|         self.color = self._term_supports_color() if color is None else bool(color) | ||||
|         self.effects = { | ||||
|             'reset':  0, | ||||
|             'bold':   1, | ||||
|             'normal': 22, | ||||
|             } | ||||
|         self.colors = { | ||||
|             'black':   0, | ||||
|             'red':     1, | ||||
|             'green':   2, | ||||
|             'yellow':  3, | ||||
|             'blue':    4, | ||||
|             'magenta': 5, | ||||
|             'cyan':    6, | ||||
|             'white':   7, | ||||
|             'default': 9, | ||||
|             } | ||||
|  | ||||
|     @staticmethod | ||||
|     def _term_supports_color(): | ||||
|         try: | ||||
|             stdout_fd = sys.stdout.fileno() | ||||
|         except IOError: | ||||
|             return False | ||||
|         else: | ||||
|             is_a_tty = os.isatty(stdout_fd) | ||||
|             is_windows = sys.platform.startswith('win') | ||||
|             return is_a_tty and not is_windows | ||||
|  | ||||
|     @classmethod | ||||
|     def from_style_content(cls, format_spec): | ||||
|         specs = set(format_spec.split()) | ||||
|         style = specs & {'mono', 'color'} | ||||
|         content = specs - style | ||||
|         if len(style) > 1: | ||||
|             raise ValueError('cannot specify both mono and color styles') | ||||
|         try: | ||||
|             style = style.pop() | ||||
|         except KeyError: | ||||
|             style = 'color' if cls._term_supports_color() else 'mono' | ||||
|         if len(content) > 1: | ||||
|             raise ValueError('cannot specify more than one content element') | ||||
|         content = content.pop() | ||||
|         return cls(style == 'color'), content | ||||
|  | ||||
|     def __call__(self, format_spec): | ||||
|         specs = format_spec.split() | ||||
|         codes = [] | ||||
|         fore = True | ||||
|         for spec in specs: | ||||
|             if spec == 'on': | ||||
|                 fore = False | ||||
|             else: | ||||
|                 try: | ||||
|                     codes.append(self.effects[spec]) | ||||
|                 except KeyError: | ||||
|                     try: | ||||
|                         if fore: | ||||
|                             codes.append(30 + self.colors[spec]) | ||||
|                         else: | ||||
|                             codes.append(40 + self.colors[spec]) | ||||
|                     except KeyError: | ||||
|                         raise ValueError('invalid format specification "%s"' % spec) | ||||
|         if self.color: | ||||
|             return '\x1b[%sm' % (';'.join(str(code) for code in codes)) | ||||
|         else: | ||||
|             return '' | ||||
|  | ||||
|     def __format__(self, format_spec): | ||||
|         if format_spec == '': | ||||
|             return 'color' if self.color else 'mono' | ||||
|         else: | ||||
|             return self(format_spec) | ||||
|  | ||||
|  | ||||
| class PinInfo(namedtuple('PinInfo', ( | ||||
|     'number', | ||||
|     'function', | ||||
|     'pull_up', | ||||
|     'row', | ||||
|     'col', | ||||
|     ))): | ||||
|     """ | ||||
|     This class is a :func:`~collections.namedtuple` derivative used to | ||||
| @@ -298,7 +483,162 @@ class PinInfo(namedtuple('PinInfo', ( | ||||
|         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. | ||||
|  | ||||
|     .. attribute:: row | ||||
|  | ||||
|         An integer indicating on which row the pin is physically located in | ||||
|         the header (1-based) | ||||
|  | ||||
|     .. attribute:: col | ||||
|  | ||||
|         An integer indicating in which column the pin is physically located | ||||
|         in the header (1-based) | ||||
|     """ | ||||
|     __slots__ = () # workaround python issue #24931 | ||||
|  | ||||
|  | ||||
| class HeaderInfo(namedtuple('HeaderInfo', ( | ||||
|     'name', | ||||
|     'rows', | ||||
|     'columns', | ||||
|     'pins', | ||||
|     ))): | ||||
|     """ | ||||
|     This class is a :func:`~collections.namedtuple` derivative used to | ||||
|     represent information about a pin header on a board. The object can be used | ||||
|     in a format string with various custom specifications:: | ||||
|  | ||||
|         from gpiozero import * | ||||
|  | ||||
|         print('{0:full}'.format(pi_info().headers['P1'])) | ||||
|         print('{0:col2}'.format(pi_info().headers['P1'])) | ||||
|         print('{0:row1}'.format(pi_info().headers['P1'])) | ||||
|  | ||||
|     `'color'` and `'mono'` can be prefixed to format specifications to force | ||||
|     the use of `ANSI color codes`_. If neither is specified, ANSI codes will | ||||
|     only be used if stdout is detected to be a tty:: | ||||
|  | ||||
|         print('{0:color row2}'.format(pi_info().headers['P1'])) # force use of ANSI codes | ||||
|         print('{0:mono row2}'.format(pi_info().headers['P1'])) # force plain ASCII | ||||
|  | ||||
|     .. _ANSI color codes: https://en.wikipedia.org/wiki/ANSI_escape_code | ||||
|     The following attributes are defined: | ||||
|  | ||||
|     .. automethod:: pprint | ||||
|  | ||||
|     .. attribute:: name | ||||
|  | ||||
|         The name of the header, typically as it appears silk-screened on the | ||||
|         board (e.g. "P1"). | ||||
|  | ||||
|     .. attribute:: rows | ||||
|  | ||||
|         The number of rows on the header. | ||||
|  | ||||
|     .. attribute:: columns | ||||
|  | ||||
|         The number of columns on the header. | ||||
|  | ||||
|     .. attribute:: pins | ||||
|  | ||||
|         A dictionary mapping physical pin numbers to :class:`PinInfo` tuples. | ||||
|     """ | ||||
|     __slots__ = () # workaround python issue #24931 | ||||
|  | ||||
|     def _func_style(self, function, style): | ||||
|         if function == V5: | ||||
|             return style('bold red') | ||||
|         elif function in (V3_3, V1_8): | ||||
|             return style('bold cyan') | ||||
|         elif function in (GND, NC): | ||||
|             return style('bold black') | ||||
|         elif function.startswith('GPIO') and function[4:].isdigit(): | ||||
|             return style('bold green') | ||||
|         else: | ||||
|             return style('yellow') | ||||
|  | ||||
|     def _format_full(self, style): | ||||
|         Cell = namedtuple('Cell', ('content', 'align', 'style')) | ||||
|  | ||||
|         pin_digits = len(str(self.rows * self.columns)) | ||||
|         lines = [] | ||||
|         for row in range(self.rows): | ||||
|             line = [] | ||||
|             for col in range(self.columns): | ||||
|                 pin = (row * self.columns) + col + 1 | ||||
|                 try: | ||||
|                     pin = self.pins[pin] | ||||
|                     cells = [ | ||||
|                         Cell(pin.function, '><'[col % 2], self._func_style(pin.function, style)), | ||||
|                         Cell('(%d)' % pin.number, '><'[col % 2], ''), | ||||
|                         ] | ||||
|                     if col % 2: | ||||
|                         cells = reversed(cells) | ||||
|                     line.extend(cells) | ||||
|                 except KeyError: | ||||
|                     line.append(Cell('', '<', '')) | ||||
|             lines.append(line) | ||||
|         cols = list(zip(*lines)) | ||||
|         col_lens = [max(len(cell.content) for cell in col) for col in cols] | ||||
|         lines = [ | ||||
|             ' '.join( | ||||
|                 '{cell.style}{cell.content:{cell.align}{width}s}{style:reset}'.format( | ||||
|                     cell=cell, width=width, style=style) | ||||
|                 for cell, width, align in zip(line, col_lens, cycle('><'))) | ||||
|             for line in lines | ||||
|             ] | ||||
|         return '\n'.join(lines) | ||||
|  | ||||
|     def _format_pin(self, pin, style): | ||||
|         return ''.join(( | ||||
|             style('on black'), | ||||
|             ( | ||||
|                 ' ' if pin is None else | ||||
|                 self._func_style(pin.function, style) + | ||||
|                 ('1' if pin.number == 1 else 'o') | ||||
|                 ), | ||||
|             style('reset') | ||||
|             )) | ||||
|  | ||||
|     def _format_row(self, row, style): | ||||
|         if row > self.rows: | ||||
|             raise ValueError('invalid row %d for header %s' % (row, self.name)) | ||||
|         start_pin = (row - 1) * self.columns + 1 | ||||
|         return ''.join( | ||||
|             self._format_pin(pin, style) | ||||
|             for n in range(start_pin, start_pin + self.columns) | ||||
|             for pin in (self.pins.get(n),) | ||||
|             ) | ||||
|  | ||||
|     def _format_col(self, col, style): | ||||
|         if col > self.columns: | ||||
|             raise ValueError('invalid col %d for header %s' % (col, self.name)) | ||||
|         return ''.join( | ||||
|             self._format_pin(pin, style) | ||||
|             for n in range(col, self.rows * self.columns + 1, self.columns) | ||||
|             for pin in (self.pins.get(n),) | ||||
|             ) | ||||
|  | ||||
|     def __format__(self, format_spec): | ||||
|         style, content = Style.from_style_content(format_spec) | ||||
|         if content == 'full': | ||||
|             return self._format_full(style) | ||||
|         elif content.startswith('row') and content[3:].isdigit(): | ||||
|             return self._format_row(int(content[3:]), style) | ||||
|         elif content.startswith('col') and content[3:].isdigit(): | ||||
|             return self._format_col(int(content[3:]), style) | ||||
|  | ||||
|     def pprint(self, color=None): | ||||
|         """ | ||||
|         Pretty-print a diagram of the header pins. | ||||
|  | ||||
|         If *color* is ``None`` (the default, the diagram will include ANSI | ||||
|         color codes if stdout is a color-capable terminal). Otherwise *color* | ||||
|         can be set to ``True`` or ``False`` to force color or monochrome | ||||
|         output. | ||||
|         """ | ||||
|         print('{0:{style} full}'.format(self, style=Style(color))) | ||||
|  | ||||
|  | ||||
|  | ||||
| class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
| @@ -317,17 +657,37 @@ class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
|     'csi', | ||||
|     'dsi', | ||||
|     'headers', | ||||
|     'board', | ||||
|     ))): | ||||
|     """ | ||||
|     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. | ||||
|     attributes to access the data contained within. The object can be used | ||||
|     in format strings with various custom format specifications:: | ||||
|  | ||||
|         from gpiozero import * | ||||
|  | ||||
|         print('{0:full}'.format(pi_info())) | ||||
|         print('{0:board}'.format(pi_info())) | ||||
|         print('{0:specs}'.format(pi_info())) | ||||
|         print('{0:headers}'.format(pi_info())) | ||||
|  | ||||
|     `'color'` and `'mono'` can be prefixed to format specifications to force | ||||
|     the use of `ANSI color codes`_. If neither is specified, ANSI codes will | ||||
|     only be used if stdout is detected to be a tty:: | ||||
|  | ||||
|         print('{0:color board}'.format(pi_info())) # force use of ANSI codes | ||||
|         print('{0:mono board}'.format(pi_info())) # force plain ASCII | ||||
|  | ||||
|     .. _ANSI color codes: https://en.wikipedia.org/wiki/ANSI_escape_code | ||||
|  | ||||
|     .. automethod:: physical_pin | ||||
|  | ||||
|     .. automethod:: physical_pins | ||||
|  | ||||
|     .. automethod:: pprint | ||||
|  | ||||
|     .. automethod:: pulled_up | ||||
|  | ||||
|     .. attribute:: revision | ||||
| @@ -422,13 +782,185 @@ class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
|  | ||||
|     .. 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]``. | ||||
|         A dictionary which maps header labels to :class:`HeaderInfo` tuples. | ||||
|         For example, to obtain information about header P1 you would query | ||||
|         ``headers['P1']``. To obtain information about pin 12 on header P1 you | ||||
|         would query ``headers['P1'].pins[12]``. | ||||
|  | ||||
|         A rendered version of this data can be obtained by using the | ||||
|         :class:`PiBoardInfo` object in a format string:: | ||||
|  | ||||
|             from gpiozero import * | ||||
|             print('{0:headers}'.format(pi_info())) | ||||
|  | ||||
|     .. attribute:: board | ||||
|  | ||||
|         An ASCII art rendition of the board, primarily intended for console | ||||
|         pretty-print usage. A more usefully rendered version of this data can | ||||
|         be obtained by using the :class:`PiBoardInfo` object in a format | ||||
|         string. For example:: | ||||
|  | ||||
|             from gpiozero import * | ||||
|             print('{0:board}'.format(pi_info())) | ||||
|  | ||||
|     .. _system on a chip: https://en.wikipedia.org/wiki/System_on_a_chip | ||||
|     """ | ||||
|     __slots__ = () # workaround python issue #24931 | ||||
|  | ||||
|     @classmethod | ||||
|     def from_revision(cls, revision): | ||||
|         if revision & 0x800000: | ||||
|             # New-style revision, parse information from bit-pattern: | ||||
|             # | ||||
|             # 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) | ||||
|             # RRRR     - Revision (0, 1, 2, etc.) | ||||
|             try: | ||||
|                 model = { | ||||
|                     0: 'A', | ||||
|                     1: 'B', | ||||
|                     2: 'A+', | ||||
|                     3: 'B+', | ||||
|                     4: '2B', | ||||
|                     6: 'CM', | ||||
|                     8: '3B', | ||||
|                     9: 'Zero', | ||||
|                     }[(revision & 0xff0) >> 4] | ||||
|                 if model in ('A', 'B'): | ||||
|                     pcb_revision = { | ||||
|                         0: '1.0', # is this right? | ||||
|                         1: '1.0', | ||||
|                         2: '2.0', | ||||
|                         }[revision & 0x0f] | ||||
|                 else: | ||||
|                     pcb_revision = '1.%d' % (revision & 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' if pcb_revision == '1.2' else '2016Q2', | ||||
|                     }[model] | ||||
|                 soc = { | ||||
|                     0: 'BCM2835', | ||||
|                     1: 'BCM2836', | ||||
|                     2: 'BCM2837', | ||||
|                     }[(revision & 0xf000) >> 12] | ||||
|                 manufacturer = { | ||||
|                     0: 'Sony', | ||||
|                     1: 'Egoman', | ||||
|                     2: 'Embest', | ||||
|                     }[(revision & 0xf0000) >> 16] | ||||
|                 memory = { | ||||
|                     0: 256, | ||||
|                     1: 512, | ||||
|                     2: 1024, | ||||
|                     }[(revision & 0x700000) >> 20] | ||||
|                 storage = { | ||||
|                     'A': 'SD', | ||||
|                     'B': 'SD', | ||||
|                     'CM': 'eMMC', | ||||
|                     }.get(model, 'MicroSD') | ||||
|                 usb = { | ||||
|                     'A':    1, | ||||
|                     'A+':   1, | ||||
|                     'Zero': 1, | ||||
|                     'B':    2, | ||||
|                     'CM':   1, | ||||
|                     }.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 if pcb_revision == '1.2' else 1, | ||||
|                     'CM':   2, | ||||
|                     }.get(model, 1) | ||||
|                 dsi = { | ||||
|                     'Zero': 0, | ||||
|                     }.get(model, csi) | ||||
|                 headers = { | ||||
|                     'A':  {'P1': REV2_P1, 'P5': REV2_P5}, | ||||
|                     'B':  {'P1': REV1_P1} if pcb_revision == '1.0' else {'P1': REV2_P1, 'P5': REV2_P5}, | ||||
|                     'CM': {'SODIMM': CM_SODIMM}, | ||||
|                     }.get(model, {'P1': PLUS_P1}) | ||||
|                 board = { | ||||
|                     'A':    A_BOARD, | ||||
|                     'B':    REV1_BOARD if pcb_revision == '1.0' else REV2_BOARD, | ||||
|                     'A+':   APLUS_BOARD, | ||||
|                     'CM':   CM_BOARD, | ||||
|                     'Zero': ZERO12_BOARD if pcb_revision == '1.2' else ZERO13_BOARD, | ||||
|                     }.get(model, BPLUS_BOARD) | ||||
|             except KeyError: | ||||
|                 raise PinUnknownPi('unable to parse new-style revision "%x"' % revision) | ||||
|         else: | ||||
|             # Old-style revision, use the lookup table | ||||
|             try: | ||||
|                 ( | ||||
|                     model, | ||||
|                     pcb_revision, | ||||
|                     released, | ||||
|                     soc, | ||||
|                     manufacturer, | ||||
|                     memory, | ||||
|                     storage, | ||||
|                     usb, | ||||
|                     ethernet, | ||||
|                     wifi, | ||||
|                     bluetooth, | ||||
|                     csi, | ||||
|                     dsi, | ||||
|                     headers, | ||||
|                     board, | ||||
|                     ) = PI_REVISIONS[revision] | ||||
|             except KeyError: | ||||
|                 raise PinUnknownPi('unknown old-style revision "%x"' % revision) | ||||
|         headers = { | ||||
|             header: HeaderInfo(name=header, rows=max(header_data) // 2, columns=2, pins={ | ||||
|                 number: PinInfo( | ||||
|                     number=number, function=function, pull_up=pull_up, | ||||
|                     row=row + 1, col=col + 1) | ||||
|                 for number, (function, pull_up) in header_data.items() | ||||
|                 for row, col in (divmod(number, 2),) | ||||
|                 }) | ||||
|             for header, header_data in headers.items() | ||||
|             } | ||||
|         return cls( | ||||
|             '%04x' % revision, | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             board, | ||||
|             ) | ||||
|  | ||||
|     def physical_pins(self, function): | ||||
|         """ | ||||
| @@ -445,8 +977,8 @@ class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
|         """ | ||||
|         return { | ||||
|             (header, pin.number) | ||||
|             for (header, pins) in self.headers.items() | ||||
|             for pin in pins.values() | ||||
|             for (header, info) in self.headers.items() | ||||
|             for pin in info.pins.values() | ||||
|             if pin.function == function | ||||
|             } | ||||
|  | ||||
| @@ -486,124 +1018,69 @@ class PiBoardInfo(namedtuple('PiBoardInfo', ( | ||||
|         except PinNoPins: | ||||
|             return False | ||||
|         else: | ||||
|             return self.headers[header][number].pull_up | ||||
|             return self.headers[header].pins[number].pull_up | ||||
|  | ||||
|  | ||||
| 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) | ||||
|     # RRRR     - Revision (0, 1, or 2) | ||||
|     if not (revision & 0x800000): | ||||
|         raise PinUnknownPi('cannot parse "%x"; 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', | ||||
|             }[(revision & 0xff0) >> 4] | ||||
|         if model in ('A', 'B'): | ||||
|             pcb_revision = { | ||||
|                 0: '1.0', # is this right? | ||||
|                 1: '1.0', | ||||
|                 2: '2.0', | ||||
|                 }[revision & 0x0f] | ||||
|         else: | ||||
|             pcb_revision = '1.%d' % (revision & 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' if pcb_revision == '1.0' else '2016Q2', | ||||
|             }[model] | ||||
|         soc = { | ||||
|             0: 'BCM2835', | ||||
|             1: 'BCM2836', | ||||
|             2: 'BCM2837', | ||||
|             }[(revision & 0xf000) >> 12] | ||||
|         manufacturer = { | ||||
|             0: 'Sony', | ||||
|             1: 'Egoman', | ||||
|             2: 'Embest', | ||||
|             }[(revision & 0xf0000) >> 16] | ||||
|         memory = { | ||||
|             0: 256, | ||||
|             1: 512, | ||||
|             2: 1024, | ||||
|             }[(revision & 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 if pcb_revision == '1.0' else 1, | ||||
|             'CM':   2, | ||||
|             }.get(model, 1) | ||||
|         dsi = { | ||||
|             'Zero': 0, | ||||
|             }.get(model, 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 PinUnknownPi('unable to parse new-style revision "%x"' % revision) | ||||
|     else: | ||||
|         return ( | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|     def __repr__(self): | ||||
|         return '{cls}({fields})'.format( | ||||
|             cls=self.__class__.__name__, | ||||
|             fields=', '.join( | ||||
|                 ( | ||||
|                     '{name}=...' if name in ('headers', 'board') else | ||||
|                     '{name}={value!r}').format(name=name, value=value) | ||||
|                 for name, value in zip(self._fields, self) | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
|     def __format__(self, format_spec): | ||||
|         style, content = Style.from_style_content(format_spec) | ||||
|         if content == 'full': | ||||
|             return dedent("""\ | ||||
|                 {self:{style} board} | ||||
|  | ||||
|                 {self:{style} specs} | ||||
|  | ||||
|                 {self:{style} headers}""" | ||||
|                 ).format(self=self, style=style) | ||||
|         elif content == 'board': | ||||
|             kw = self._asdict() | ||||
|             kw.update({ | ||||
|                 name: header | ||||
|                 for name, header in self.headers.items() | ||||
|                 }) | ||||
|             return self.board.format(style=style, **kw) | ||||
|         elif content == 'specs': | ||||
|             return dedent("""\ | ||||
|                 {style:bold}Revision           {style:reset}: {revision} | ||||
|                 {style:bold}SoC                {style:reset}: {soc} | ||||
|                 {style:bold}RAM                {style:reset}: {memory}Mb | ||||
|                 {style:bold}Storage            {style:reset}: {storage} | ||||
|                 {style:bold}USB ports          {style:reset}: {usb} {style:yellow}(excluding power){style:reset} | ||||
|                 {style:bold}Ethernet ports     {style:reset}: {ethernet} | ||||
|                 {style:bold}Wi-fi              {style:reset}: {wifi} | ||||
|                 {style:bold}Bluetooth          {style:reset}: {bluetooth} | ||||
|                 {style:bold}Camera ports (CSI) {style:reset}: {csi} | ||||
|                 {style:bold}Display ports (DSI){style:reset}: {dsi}""" | ||||
|                 ).format(style=style, **self._asdict()) | ||||
|         elif content == 'headers': | ||||
|             return '\n\n'.join( | ||||
|                 dedent("""\ | ||||
|                 {style:bold}{header.name}{style:reset}: | ||||
|                 {header:{style} full}""" | ||||
|                 ).format(header=header, style=style) | ||||
|                 for header in sorted(self.headers.values(), key=attrgetter('name')) | ||||
|                 ) | ||||
|  | ||||
|     def pprint(self, color=None): | ||||
|         """ | ||||
|         Pretty-print a representation of the board along with header diagrams. | ||||
|  | ||||
|         If *color* is ``None`` (the default, the diagram will include ANSI | ||||
|         color codes if stdout is a color-capable terminal). Otherwise *color* | ||||
|         can be set to ``True`` or ``False`` to force color or monochrome | ||||
|         output. | ||||
|         """ | ||||
|         print('{0:{style} full}'.format(self, style=Style(color))) | ||||
|  | ||||
|  | ||||
| def pi_info(revision=None): | ||||
|     """ | ||||
| @@ -635,63 +1112,5 @@ def pi_info(revision=None): | ||||
|         else: | ||||
|             # be nice to people passing an int (or something numeric anyway) | ||||
|             revision = int(revision) | ||||
|     try: | ||||
|         ( | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             ) = PI_REVISIONS[revision] | ||||
|     except KeyError: | ||||
|         ( | ||||
|             model, | ||||
|             pcb_revision, | ||||
|             released, | ||||
|             soc, | ||||
|             manufacturer, | ||||
|             memory, | ||||
|             storage, | ||||
|             usb, | ||||
|             ethernet, | ||||
|             wifi, | ||||
|             bluetooth, | ||||
|             csi, | ||||
|             dsi, | ||||
|             headers, | ||||
|             ) = _parse_pi_revision(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( | ||||
|         '%04x' % revision, | ||||
|         model, | ||||
|         pcb_revision, | ||||
|         released, | ||||
|         soc, | ||||
|         manufacturer, | ||||
|         memory, | ||||
|         storage, | ||||
|         usb, | ||||
|         ethernet, | ||||
|         wifi, | ||||
|         bluetooth, | ||||
|         csi, | ||||
|         dsi, | ||||
|         headers, | ||||
|         ) | ||||
|  | ||||
|         return PiBoardInfo.from_revision(revision) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user