#!/usr/bin/env python3

# Copyright 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse

class Style:
    BOLD      = 1
    DEFAULT   = 39
    RED       = 31
    GREEN     = 32
    YELLOW    = 33
    BLUE      = 34
    MAGENTA   = 35
    CYAN      = 36
    DARK_GRAY = 90

class Kind:
    GND, POWER, I2C, UART, GPIO, SAI, SPI, PWM = range(8)

KINDS = {
    Kind.GND:   (Style.DARK_GRAY, 'GND',   'Ground'),
    Kind.POWER: (Style.RED,       'POWER', 'Power: +5V or +3.3V'),
    Kind.I2C:   (Style.GREEN,     'I2C',   'Inter-Integrated Circuit [/dev/i2c-N]'),
    Kind.UART:  (Style.MAGENTA,   'UART',  'Serial Port'),
    Kind.GPIO:  (Style.DEFAULT,   'GPIO',  'General Purpose Input Output [/sys/class/gpio/gpioN]'),
    Kind.SAI:   (Style.CYAN,      'SAI',   'Serial Audio Interface'),
    Kind.SPI:   (Style.BLUE,      'SPI',   'Serial Peripheral Interface'),
    Kind.PWM:   (Style.YELLOW,    'PWM',   'Pulse Width Modulation [/sys/class/pwm/pwmchipN/pwm0]'),
}

PINS = {
    1:  ('3.3.V',             Kind.POWER), 2:  ('5V',                 Kind.POWER),
    3:  ('I2C2_SDA (i2c-1)',  Kind.I2C),   4:  ('5V',                 Kind.POWER),
    5:  ('I2C2_SCL (i2c-1)',  Kind.I2C),   6:  ('GND',                Kind.GND),
    7:  ('UART3_TXD',         Kind.UART),  8:  ('UART1_TX',           Kind.UART),
    9:  ('GND',               Kind.GND),   10: ('UART1_RX',           Kind.UART),
    11: ('UART3_RXD',         Kind.UART),  12: ('SAI1_TXC',           Kind.SAI),
    13: ('GPIO_P13 (gpio6)',  Kind.GPIO),  14: ('GND',                Kind.GND),
    15: ('PWM3 (pwmchip2)',   Kind.PWM),   16: ('GPIO_P16 (gpio73)',  Kind.GPIO),
    17: ('3.3V',              Kind.POWER), 18: ('GPIO_P18 (gpio138)', Kind.GPIO),
    19: ('SPI1_MOSI',         Kind.SPI),   20: ('GND',                Kind.GND),
    21: ('SPI1_MISO',         Kind.SPI),   22: ('GPIO_P22 (gpio140)', Kind.GPIO),
    23: ('SPI1_SCLK',         Kind.SPI),   24: ('SPI1_SS0',           Kind.SPI),
    25: ('GND',               Kind.GND),   26: ('SPI1_SS1',           Kind.SPI),
    27: ('I2C3_SDA (i2c-2)',  Kind.I2C),   28: ('I2C3_SCL (i2c-2)',   Kind.I2C),
    29: ('GPIO_P29 (gpio7)',  Kind.GPIO),  30: ('GND',                Kind.GND),
    31: ('GPIO_P31 (gpio8)',  Kind.GPIO),  32: ('PWM1 (pwmchip0)',    Kind.PWM),
    33: ('PWM2 (pwmchip1)',   Kind.PWM),   34: ('GND',                Kind.GND),
    35: ('SAI1_TXFS',         Kind.SAI),   36: ('GPIO_P36 (gpio141)', Kind.GPIO),
    37: ('GPIO_P37 (gpio77)', Kind.GPIO),  38: ('SAI1_RXD0',          Kind.SAI),
    39: ('GND',               Kind.GND),   40: ('SAI1_TXD0',          Kind.SAI)
}

assert(len(PINS) % 2 == 0)
assert(set(PINS.keys()) == set(range(1, len(PINS) + 1)))

def pins():
    for i in range(len(PINS) // 2):
        yield (2 * i + 1, 2 * i + 2)

def pin_desc(pin):
    text, _ = PINS[pin]
    return text

def pin_kind(pin):
    _, kind = PINS[pin]
    return kind

def stylize(text, style, esc='\033['):
    return '%s%dm%s%s0m' % (esc, style, text, esc)

def stylize_pin(text, pin):
    style, _, _ = KINDS[pin_kind(pin)]
    return stylize(text, style)

def print_pinout(color):
    max_len = max(len(pin_desc(l)) for l, _ in pins())

    for l, r in pins():
        l_pin, r_pin = str(l).ljust(2), str(r).rjust(2)
        l_txt, r_txt = pin_desc(l).rjust(max_len), pin_desc(r)

        if color:
            l_pin = stylize(l_pin, Style.BOLD)
            r_pin = stylize(r_pin, Style.BOLD)
            l_txt, r_txt = stylize_pin(l_txt, l), stylize_pin(r_txt, r)

        print('%s -> %s  %s <- %s' % (l_txt, l_pin, r_pin, r_txt))

def print_legend(color):
    max_len = max(len(name) for _, (_, name, _) in KINDS.items())

    for kind, (style, name, desc) in KINDS.items():
        txt = name.ljust(max_len)
        if color:
            txt = stylize(txt, style)
        print('%s - %s' % (txt, desc))

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--nocolor', dest='color', action='store_false',
                        default=True, help='Do not output in color.')
    parser.add_argument('--nolegend', dest='legend', action='store_false',
                        default=True, help='Do not output legend.')
    args = parser.parse_args()

    print_pinout(args.color)
    if args.legend:
        print()
        print_legend(args.color)

if __name__ == '__main__':
    main()
