#!/usr/bin/env python3

# Copyright 2018-2020 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
import os

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 [/dev/ttySN]'),
    Kind.GPIO:  (Style.DEFAULT,   'GPIO',  'General Purpose Input Output [/sys/class/gpio/gpioN]'),
    Kind.SAI:   (Style.CYAN,      'SAI',   'Synchronous Audio Interface'),
    Kind.SPI:   (Style.BLUE,      'SPI',   'Serial Peripheral Interface [/dev/spidevN.N]'),
    Kind.PWM:   (Style.YELLOW,    'PWM',   'Pulse Width Modulation [/sys/class/pwm/pwmchipN/pwm0]'),
}

I2C_DEVICES = {
    'I2C1': '1100a000.i2c',
    'I2C2': '1100b000.i2c',
}

def lookup_i2c_bus(device_tree_name):
    sysfs_directory = '/sys/devices/platform/soc/{}'.format(device_tree_name)
    return [x for x in os.listdir(sysfs_directory) if x.startswith('i2c-')][0]

PINS = {
    1:  ('3.3.V',                     Kind.POWER), 2:  ('5V',                       Kind.POWER),
    3:  ('I2C1_SDA ({})'.format(lookup_i2c_bus(I2C_DEVICES['I2C1'])), Kind.I2C),
    4:  ('5V',                        Kind.POWER),
    5:  ('I2C1_SCL ({})'.format(lookup_i2c_bus(I2C_DEVICES['I2C1'])), Kind.I2C),
    6:  ('GND',                       Kind.GND),
    7:  ('GPIO (gpio409)',            Kind.GPIO),  8:  ('UART0_TX (ttyS0)',         Kind.UART),
    9:  ('GND',                       Kind.GND),   10: ('UART0_RX (ttyS0)',         Kind.UART),
    11: ('GPIO (gpio396)',            Kind.GPIO),  12: ('GPIO (gpio423) / I2S_BCK', Kind.SAI),
    13: ('GPIO (gpio397)',            Kind.GPIO),  14: ('GND',                      Kind.GND),
    15: ('PWM (pwmchip0.2)',          Kind.PWM),   16: ('GPIO (gpio387)',           Kind.GPIO),
    17: ('3.3V',                      Kind.POWER), 18: ('GPIO (gpio399)',           Kind.GPIO),
    19: ('SPI_MOSI (spidev0)',        Kind.SPI),   20: ('GND',                      Kind.GND),
    21: ('SPI_MISO (spidev0)',        Kind.SPI),   22: ('GPIO (gpio394)',           Kind.GPIO),
    23: ('SPI_SCLK (spidev0)',        Kind.SPI),   24: ('SPI_CSB (spidev0.0)',      Kind.SPI),
    25: ('GND',                       Kind.GND),   26: ('GPIO (gpio395)',           Kind.GPIO),
    27: ('I2C2_SDA ({})'.format(lookup_i2c_bus(I2C_DEVICES['I2C2'])), Kind.I2C),
    28: ('I2C2_SCL ({})'.format(lookup_i2c_bus(I2C_DEVICES['I2C2'])), Kind.I2C),
    29: ('UART1_TX (ttyS1)',          Kind.UART),  30: ('GND',                      Kind.GND),
    31: ('UART1_RX (ttyS1)',          Kind.UART),  32: ('PWM (pwmchip0.0)',         Kind.PWM),
    33: ('PWM (pwmchip0.1)',          Kind.PWM),   34: ('GND',                      Kind.GND),
    35: ('GPIO (gpio424) / I2S_LRCK', Kind.SAI),   36: ('GPIO (gpio400)',           Kind.GPIO),
    37: ('GPIO (gpio432)',            Kind.GPIO),  38: ('GPIO (gpio425) / I2S_DO',  Kind.SAI),
    39: ('GND',                       Kind.GND),   40: ('GPIO (gpio426) / I2S_MCK', 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()
