###############################################################################
# Distribution : HiPi Modules for Raspberry Pi
# File         : lib/HiPi/RaspberryPi.pm
# Description  : Information about host Raspberry Pi
# Copyright    : Copyright (c) 2013-2024 Mark Dootson
# License      : This is free software; you can redistribute it and/or modify it under
#                the same terms as the Perl 5 programming language system itself.
#########################################################################################

package HiPi::RaspberryPi;

###############################################################################
use strict;
use warnings;
use Carp;

our $VERSION ='0.94';

my ( $btype1, $btype2, $btype3, $btype4) = ( 1, 2, 3, 4 );

my $israspberry  = 0;
my $israspberry1 = 0;
my $israspberry2 = 0;
my $israspberry3 = 0;
my $israspberry4 = 0;
my $israspberry5 = 0;
my $hasdevicetree = 0;
my $homedir = '/tmp';

my $_min_gpio = 0;
my $_max_gpio = 53;

my @_alt_func_names_2708 =
(
    [ 'SDA0'      , 'SA5'        , 'PCLK'      , 'AVEOUT_VCLK'   , 'AVEIN_VCLK' , '-'         ],
    [ 'SCL0'      , 'SA4'        , 'DE'        , 'AVEOUT_DSYNC'  , 'AVEIN_DSYNC', '-'         ],
    [ 'SDA1'      , 'SA3'        , 'LCD_VSYNC' , 'AVEOUT_VSYNC'  , 'AVEIN_VSYNC', '-'         ],
    [ 'SCL1'      , 'SA2'        , 'LCD_HSYNC' , 'AVEOUT_HSYNC'  , 'AVEIN_HSYNC', '-'         ],
    [ 'GPCLK0'    , 'SA1'        , 'DPI_D0'    , 'AVEOUT_VID0'   , 'AVEIN_VID0' , 'ARM_TDI'   ],
    [ 'GPCLK1'    , 'SA0'        , 'DPI_D1'    , 'AVEOUT_VID1'   , 'AVEIN_VID1' , 'ARM_TDO'   ],
    [ 'GPCLK2'    , 'SOE_N_SE'   , 'DPI_D2'    , 'AVEOUT_VID2'   , 'AVEIN_VID2' , 'ARM_RTCK'  ],
    [ 'SPI0_CE1_N', 'SWE_N_SRW_N', 'DPI_D3'    , 'AVEOUT_VID3'   , 'AVEIN_VID3' , '-'         ],
    [ 'SPI0_CE0_N', 'SD0'        , 'DPI_D4'    , 'AVEOUT_VID4'   , 'AVEIN_VID4' , '-'         ],
    [ 'SPI0_MISO' , 'SD1'        , 'DPI_D5'    , 'AVEOUT_VID5'   , 'AVEIN_VID5' , '-'         ],
    [ 'SPI0_MOSI' , 'SD2'        , 'DPI_D6'    , 'AVEOUT_VID6'   , 'AVEIN_VID6' , '-'         ],
    [ 'SPI0_SCLK' , 'SD3'        , 'DPI_D7'    , 'AVEOUT_VID7'   , 'AVEIN_VID7' , '-'         ],
    [ 'PWM0'      , 'SD4'        , 'DPI_D8'    , 'AVEOUT_VID8'   , 'AVEIN_VID8' , 'ARM_TMS'   ],
    [ 'PWM1'      , 'SD5'        , 'DPI_D9'    , 'AVEOUT_VID9'   , 'AVEIN_VID9' , 'ARM_TCK'   ],
    [ 'TXD0'      , 'SD6'        , 'DPI_D10'   , 'AVEOUT_VID10'  , 'AVEIN_VID10', 'TXD1'      ],
    [ 'RXD0'      , 'SD7'        , 'DPI_D11'   , 'AVEOUT_VID11'  , 'AVEIN_VID11', 'RXD1'      ],
    [ 'FL0'       , 'SD8'        , 'DPI_D12'   , 'CTS0'          , 'SPI1_CE2_N' , 'CTS1'      ],
    [ 'FL1'       , 'SD9'        , 'DPI_D13'   , 'RTS0'          , 'SPI1_CE1_N' , 'RTS1'      ],
    [ 'PCM_CLK'   , 'SD10'       , 'DPI_D14'   , 'I2CSL_SDA_MOSI', 'SPI1_CE0_N' , 'PWM0'      ],
    [ 'PCM_FS'    , 'SD11'       , 'DPI_D15'   , 'I2CSL_SCL_SCLK', 'SPI1_MISO'  , 'PWM1'      ],
    [ 'PCM_DIN'   , 'SD12'       , 'DPI_D16'   , 'I2CSL_MISO'    , 'SPI1_MOSI'  , 'GPCLK0'    ],
    [ 'PCM_DOUT'  , 'SD13'       , 'DPI_D17'   , 'I2CSL_CE_N'    , 'SPI1_SCLK'  , 'GPCLK1'    ],
    [ 'SD0_CLK'   , 'SD14'       , 'DPI_D18'   , 'SD1_CLK'       , 'ARM_TRST'   , '-'         ],
    [ 'SD0_CMD'   , 'SD15'       , 'DPI_D19'   , 'SD1_CMD'       , 'ARM_RTCK'   , '-'         ],
    [ 'SD0_DAT0'  , 'SD16'       , 'DPI_D20'   , 'SD1_DAT0'      , 'ARM_TDO'    , '-'         ],
    [ 'SD0_DAT1'  , 'SD17'       , 'DPI_D21'   , 'SD1_DAT1'      , 'ARM_TCK'    , '-'         ],
    [ 'SD0_DAT2'  , 'TE0'        , 'DPI_D22'   , 'SD1_DAT2'      , 'ARM_TDI'    , '-'         ],
    [ 'SD0_DAT3'  , 'TE1'        , 'DPI_D23'   , 'SD1_DAT3'      , 'ARM_TMS'    , '-'         ],
    [ 'SDA0'      , 'SA5'        , 'PCM_CLK'   , 'FL0'           , '-'          , '-'         ],
    [ 'SCL0'      , 'SA4'        , 'PCM_FS'    , 'FL1'           , '-'          , '-'         ],
    [ 'TE0'       , 'SA3'        , 'PCM_DIN'   , 'CTS0'          , '-'          , 'CTS1'      ],
    [ 'FL0'       , 'SA2'        , 'PCM_DOUT'  , 'RTS0'          , '-'          , 'RTS1'      ],
    [ 'GPCLK0'    , 'SA1'        , 'RING_OCLK' , 'TXD0'          , '-'          , 'TXD1'      ],
    [ 'FL1'       , 'SA0'        , 'TE1'       , 'RXD0'          , '-'          , 'RXD1'      ],
    [ 'GPCLK0'    , 'SOE_N_SE'   , 'TE2'       , 'SD1_CLK'       , '-'          , '-'         ],
    [ 'SPI0_CE1_N', 'SWE_N_SRW_N', '-'         , 'SD1_CMD'       , '-'          , '-'         ],
    [ 'SPI0_CE0_N', 'SD0'        , 'TXD0'      , 'SD1_DAT0'      , '-'          , '-'         ],
    [ 'SPI0_MISO' , 'SD1'        , 'RXD0'      , 'SD1_DAT1'      , '-'          , '-'         ],
    [ 'SPI0_MOSI' , 'SD2'        , 'RTS0'      , 'SD1_DAT2'      , '-'          , '-'         ],
    [ 'SPI0_SCLK' , 'SD3'        , 'CTS0'      , 'SD1_DAT3'      , '-'          , '-'         ],
    [ 'PWM0'      , 'SD4'        , '-'         , 'SD1_DAT4'      , 'SPI2_MISO'  , 'TXD1'      ],
    [ 'PWM1'      , 'SD5'        , 'TE0'       , 'SD1_DAT5'      , 'SPI2_MOSI'  , 'RXD1'      ],
    [ 'GPCLK1'    , 'SD6'        , 'TE1'       , 'SD1_DAT6'      , 'SPI2_SCLK'  , 'RTS1'      ],
    [ 'GPCLK2'    , 'SD7'        , 'TE2'       , 'SD1_DAT7'      , 'SPI2_CE0_N' , 'CTS1'      ],
    [ 'GPCLK1'    , 'SDA0'       , 'SDA1'      , 'TE0'           , 'SPI2_CE1_N' , '-'         ],
    [ 'PWM1'      , 'SCL0'       , 'SCL1'      , 'TE1'           , 'SPI2_CE2_N' , '-'         ],
    [ 'SDA0'      , 'SDA1'       , 'SPI0_CE0_N', '-'             , '-'          , 'SPI2_CE1_N'],
    [ 'SCL0'      , 'SCL1'       , 'SPI0_MISO' , '-'             , '-'          , 'SPI2_CE0_N'],
    [ 'SD0_CLK'   , 'FL0'        , 'SPI0_MOSI' , 'SD1_CLK'       , 'ARM_TRST'   , 'SPI2_SCLK' ],
    [ 'SD0_CMD'   , 'GPCLK0'     , 'SPI0_SCLK' , 'SD1_CMD'       , 'ARM_RTCK'   , 'SPI2_MOSI' ],
    [ 'SD0_DAT0'  , 'GPCLK1'     , 'PCM_CLK'   , 'SD1_DAT0'      , 'ARM_TDO'    , '-'         ],
    [ 'SD0_DAT1'  , 'GPCLK2'     , 'PCM_FS'    , 'SD1_DAT1'      , 'ARM_TCK'    , '-'         ],
    [ 'SD0_DAT2'  , 'PWM0'       , 'PCM_DIN'   , 'SD1_DAT2'      , 'ARM_TDI'    , '-'         ],
    [ 'SD0_DAT3'  , 'PWM1'       , 'PCM_DOUT'  , 'SD1_DAT3'      , 'ARM_TMS'    , '-'         ],
);

my @_alt_func_names_2711 =
(
    # BANK 0
    [ 'SDA0'            , 'SA5'             , 'PCLK'            , 'SPI3_CE0_N'      , 'TXD2'            , 'SDA6'            ], # 0
    [ 'SCL0'            , 'SA4'             , 'DE'              , 'SPI3_MISO'       , 'RXD2'            , 'SCL6'            ], # 1
    [ 'SDA1'            , 'SA3'             , 'LCD_VSYNC'       , 'SPI3_MOSI'       , 'CTS2'            , 'SDA3'            ], # 2
    [ 'SCL1'            , 'SA2'             , 'LCD_HSYNC'       , 'SPI3_SCLK'       , 'RTS2'            , 'SCL3'            ], # 3
    [ 'GPCLK0'          , 'SA1'             , 'DPI_D0'          , 'SPI4_CE0_N'      , 'TXD3'            , 'SDA3'            ], # 4
    [ 'GPCLK1'          , 'SA0'             , 'DPI_D1'          , 'SPI4_MISO'       , 'RXD3'            , 'SCL3'            ], # 5
    [ 'GPCLK2'          , 'SOE_N_SE'        , 'DPI_D2'          , 'SPI4_MOSI'       , 'CTS3'            , 'SDA4'            ], # 6
    [ 'SPI0_CE1_N'      , 'SWE_N_SRW_N'     , 'DPI_D3'          , 'SPI4_SCLK'       , 'RTS3'            , 'SCL4'            ], # 7
    [ 'SPI0_CE0_N'      , 'SD0'             , 'DPI_D4'          , 'I2CSL_CE_N'      , 'TXD4'            , 'SDA4'            ], # 8
    [ 'SPI0_MISO'       , 'SD1'             , 'DPI_D5'          , 'I2CSL_SDI_MISO'  , 'RXD4'            , 'SCL4'            ], # 9
    [ 'SPI0_MOSI'       , 'SD2'             , 'DPI_D6'          , 'I2CSL_SDA_MOSI'  , 'CTS4'            , 'SDA5'            ], # 10
    [ 'SPI0_SCLK'       , 'SD3'             , 'DPI_D7'          , 'I2CSL_SCL_SCLK'  , 'RTS4'            , 'SCL5'            ], # 11
    [ 'PWM0_0'          , 'SD4'             , 'DPI_D8'          , 'SPI5_CE0_N'      , 'TXD5'            , 'SDA5'            ], # 12
    [ 'PWM0_1'          , 'SD5'             , 'DPI_D9'          , 'SPI5_MISO'       , 'RXD5'            , 'SCL5'            ], # 13
    [ 'TXD0'            , 'SD6'             , 'DPI_D10'         , 'SPI5_MOSI'       , 'CTS5'            , 'TXD1'            ], # 14
    [ 'RXD0'            , 'SD7'             , 'DPI_D11'         , 'SPI5_SCLK'       , 'RTS5'            , 'RXD1'            ], # 15
    [ '-'               , 'SD8'             , 'DPI_D12'         , 'CTS0'            , 'SPI1_CE2_N'      , 'CTS1'            ], # 16
    [ '-'               , 'SD9'             , 'DPI_D13'         , 'RTS0'            , 'SPI1_CE1_N'      , 'RTS1'            ], # 17
    [ 'PCM_CLK'         , 'SD10'            , 'DPI_D14'         , 'SPI6_CE0_N'      , 'SPI1_CE0_N'      , 'PWM0_0'          ], # 18
    [ 'PCM_FS'          , 'SD11'            , 'DPI_D15'         , 'SPI6_MISO'       , 'SPI1_MISO'       , 'PWM0_1'          ], # 19
    [ 'PCM_DIN'         , 'SD12'            , 'DPI_D16'         , 'SPI6_MOSI'       , 'SPI1_MOSI'       , 'GPCLK0'          ], # 20
    [ 'PCM_DOUT'        , 'SD13'            , 'DPI_D17'         , 'SPI6_SCLK'       , 'SPI1_SCLK'       , 'GPCLK1'          ], # 21
    [ 'SD0_CLK'         , 'SD14'            , 'DPI_D18'         , 'SD1_CLK'         , 'ARM_TRST'        , 'SDA6'            ], # 22
    [ 'SD0_CMD'         , 'SD15'            , 'DPI_D19'         , 'SD1_CMD'         , 'ARM_RTCK'        , 'SCL6'            ], # 23
    [ 'SD0_DAT0'        , 'SD16'            , 'DPI_D20'         , 'SD1_DAT0'        , 'ARM_TDO'         , 'SPI3_CE1_N'      ], # 24
    [ 'SD0_DAT1'        , 'SD17'            , 'DPI_D21'         , 'SD1_DAT1'        , 'ARM_TCK'         , 'SPI4_CE1_N'      ], # 25
    [ 'SD0_DAT2'        , '-'               , 'DPI_D22'         , 'SD1_DAT2'        , 'ARM_TDI'         , 'SPI5_CE1_N'      ], # 26
    [ 'SD0_DAT3'        , '-'               , 'DPI_D23'         , 'SD1_DAT3'        , 'ARM_TMS'         , 'SPI6_CE1_N'      ], # 27
    
    # BANK 1
    [ 'SDA0'            , 'SA5'             , 'PCM_CLK'         , '-'               , 'MII_A_RX_ERR'    , 'RGMII_MDIO'      ], # 28
    [ 'SCL0'            , 'SA4'             , 'PCM_FS'          , '-'               , 'MII_A_TX_ERR'    , 'RGMII_MDC'       ], # 29
    [ '-'               , 'SA3'             , 'PCM_DIN'         , 'CTS0'            , 'MII_A_CRS'       , 'CTS1'            ], # 30
    [ '-'               , 'SA2'             , 'PCM_DOUT'        , 'RTS0'            , 'MII_A_COL'       , 'RTS1'            ], # 31
    [ 'GPCLK0'          , 'SA1'             , '-'               , 'TXD0'            , 'SD_CARD_PRES'    , 'TXD1'            ], # 32
    [ '-'               , 'SA0'             , '-'               , 'RXD0'            , 'SD_CARD_WRPROT'  , 'RXD1'            ], # 33
    [ 'GPCLK0'          , 'SOE_N_SE'        , '-'               , 'SD1_CLK'         , 'SD_CARD_LED'     , 'RGMII_IRQ'       ], # 34
    [ 'SPI0_CE1_N'      , 'SWE_N_SRW_N'     , '-'               , 'SD1_CMD'         , 'RGMII_START_STOP', '-'               ], # 35
    [ 'SPI0_CE0_N'      , 'SD0'             , 'TXD0'            , 'SD1_DAT0'        , 'RGMII_RX_OK'     , 'MII_A_RX_ERR'    ], # 36
    [ 'SPI0_MISO'       , 'SD1'             , 'RXD0'            , 'SD1_DAT1'        , 'RGMII_MDIO'      , 'MII_A_TX_ERR'    ], # 37
    [ 'SPI0_MOSI'       , 'SD2'             , 'RTS0'            , 'SD1_DAT2'        , 'RGMII_MDC'       , 'MII_A_CRS'       ], # 38
    [ 'SPI0_SCLK'       , 'SD3'             , 'CTS0'            , 'SD1_DAT3'        , 'RGMII_IRQ'       , 'MII_A_COL'       ], # 39
    [ 'PWM1_0'          , 'SD4'             , '-'               , 'SD1_DAT4'        , 'SPI0_MISO'       , 'TXD1'            ], # 40
    [ 'PWM1_1'          , 'SD5'             , '-'               , 'SD1_DAT5'        , 'SPI0_MOSI'       , 'RXD1'            ], # 41
    [ 'GPCLK1'          , 'SD6'             , '-'               , 'SD1_DAT6'        , 'SPI0_SCLK'       , 'RTS1'            ], # 42
    [ 'GPCLK2'          , 'SD7'             , '-'               , 'SD1_DAT7'        , 'SPI0_CE0_N'      , 'CTS1'            ], # 43
    [ 'GPCLK1'          , 'SDA0'            , 'SDA1'            , '-'               , 'SPI0_CE1_N'      , 'SD_CARD_VOLT'    ], # 44
    [ 'PWM0_1'          , 'SCL0'            , 'SCL1'            , '-'               , 'SPI0_CE2_N'      , 'SD_CARD_PWR0'    ], # 45
    
    # BANK 2
    [ 'SDA0'            , 'SDA1'            , 'SPI0_CE0_N'      , '-'               , '-'               , 'SPI2_CE1_N'      ], # 46
    [ 'SCL0'            , 'SCL1'            , 'SPI0_MISO'       , '-'               , '-'               , 'SPI2_CE0_N'      ], # 47
    [ 'SD0_CLK'         , '-'               , 'SPI0_MOSI'       , 'SD1_CLK'         , 'ARM_TRST'        , 'SPI2_SCLK'       ], # 48
    [ 'SD0_CMD'         , 'GPCLK0'          , 'SPI0_SCLK'       , 'SD1_CMD'         , 'ARM_RTCK'        , 'SPI2_MOSI'       ], # 49
    [ 'SD0_DAT0'        , 'GPCLK1'          , 'PCM_CLK'         , 'SD1_DAT0'        , 'ARM_TDO'         , 'SPI2_MISO'       ], # 50
    [ 'SD0_DAT1'        , 'GPCLK2'          , 'PCM_FS'          , 'SD1_DAT1'        , 'ARM_TCK'         , 'SD_CARD_LED'     ], # 51
    [ 'SD0_DAT2'        , 'PWM0_0'          , 'PCM_DIN'         , 'SD1_DAT2'        , 'ARM_TDI'         , '-'               ], # 52
    [ 'SD0_DAT3'        , 'PWM0_1'          , 'PCM_DOUT'        , 'SD1_DAT3'        , 'ARM_TMS'         , '-'               ], # 53
);

my @_alt_func_names_2712 =
(
    # BANK 0
    #  spi0,           dpi,         uart1,          i2c0,           _,             gpio,           proc_rio,       pio,          spi2),
    [ 'SPI0_SIO[3]',  'DPI_PCLK',  'UART1_TX',     'I2C0_SDA',     '-',           'SYS_RIO[0]',   'PROC_RIO[0]',  'PIO[0]',      'SPI2_CSn[0]' ], #  0
    [ 'SPI0_SIO[2]',  'DPI_DE',    'UART1_RX',     'I2C0_SCL',     '-',           'SYS_RIO[1]',   'PROC_RIO[1]',  'PIO[1]',      'SPI2_SIO[1]' ], #  1
    [ 'SPI0_CSn[3]',  'DPI_VSYNC', 'UART1_CTS',    'I2C1_SDA',     'UART0_IR_RX', 'SYS_RIO[2]',   'PROC_RIO[2]',  'PIO[2]',      'SPI2_SIO[0]' ], #  2
    [ 'SPI0_CSn[2]',  'DPI_HSYNC', 'UART1_RTS',    'I2C1_SCL',     'UART0_IR_TX', 'SYS_RIO[3]',   'PROC_RIO[3]',  'PIO[3]',      'SPI2_SCLK'   ], #  3
    [ 'GPCLK[0]',     'DPI_D[0]',  'UART2_TX',     'I2C2_SDA',     'UART0_RI',    'SYS_RIO[4]',   'PROC_RIO[4]',  'PIO[4]',      'SPI3_CSn[0]' ], #  4
    [ 'GPCLK[1]',     'DPI_D[1]',  'UART2_RX',     'I2C2_SCL',     'UART0_DTR',   'SYS_RIO[5]',   'PROC_RIO[5]',  'PIO[5]',      'SPI3_SIO[1]' ], #  5
    [ 'GPCLK[2]',     'DPI_D[2]',  'UART2_CTS',    'I2C3_SDA',     'UART0_DCD',   'SYS_RIO[6]',   'PROC_RIO[6]',  'PIO[6]',      'SPI3_SIO[0]' ], #  6
    [ 'SPI0_CSn[1]',  'DPI_D[3]',  'UART2_RTS',    'I2C3_SCL',     'UART0_DSR',   'SYS_RIO[7]',   'PROC_RIO[7]',  'PIO[7]',      'SPI3_SCLK'   ], #  7
    [ 'SPI0_CSn[0]',  'DPI_D[4]',  'UART3_TX',     'I2C0_SDA',     '-',           'SYS_RIO[8]',   'PROC_RIO[8]',  'PIO[8]',      'SPI4_CSn[0]' ], #  8  
    [ 'SPI0_SIO[1]',  'DPI_D[5]',  'UART3_RX',     'I2C0_SCL',     '-',           'SYS_RIO[9]',   'PROC_RIO[9]',  'PIO[9]',      'SPI4_SIO[0]' ], #  9
    [ 'SPI0_SIO[0]',  'DPI_D[6]',  'UART3_CTS',    'I2C1_SDA',     '-',           'SYS_RIO[10]',  'PROC_RIO[10]', 'PIO[10]',     'SPI4_SIO[1]' ], # 10
    [ 'SPI0_SCLK',    'DPI_D[7]',  'UART3_RTS',    'I2C1_SCL',     '-',           'SYS_RIO[11]',  'PROC_RIO[11]', 'PIO[11]',     'SPI4_SCLK',  ], # 11
    [ 'PWM0[0]',      'DPI_D[8]',  'UART4_TX',     'I2C2_SDA',     'AUDIO_OUT_L', 'SYS_RIO[12]',  'PROC_RIO[12]', 'PIO[12]',     'SPI5_CSn[0]' ], # 12
    [ 'PWM0[1]',      'DPI_D[9]',  'UART4_RX',     'I2C2_SCL',     'AUDIO_OUT_R', 'SYS_RIO[13]',  'PROC_RIO[13]', 'PIO[13]',     'SPI5_SIO[1]' ], # 13
    [ 'PWM0[2]',      'DPI_D[10]', 'UART4_CTS',    'I2C3_SDA',     'UART0_TX',    'SYS_RIO[14]',  'PROC_RIO[14]', 'PIO[14]',     'SPI5_SIO[0]' ], # 14
    [ 'PWM0[3]',      'DPI_D[11]', 'UART4_RTS',    'I2C3_SCL',     'UART0_RX',    'SYS_RIO[15]',  'PROC_RIO[15]', 'PIO[15]',     'SPI5_SCLK'   ], # 15
    [ 'SPI1_CSn[2]',  'DPI_D[12]', 'MIPI0_DSI_TE', '-',            'UART0_CTS',   'SYS_RIO[16]',  'PROC_RIO[16]', 'PIO[16]',      '-'          ], # 16
    [ 'SPI1_CSn[1]',  'DPI_D[13]', 'MIPI1_DSI_TE', '-',            'UART0_RTS',   'SYS_RIO[17]',  'PROC_RIO[17]', 'PIO[17]',      '-'          ], # 17
    [ 'SPI1_CSn[0]',  'DPI_D[14]', 'I2S0_SCLK',    'PWM0[2]',      'I2S1_SCLK',   'SYS_RIO[18]',  'PROC_RIO[18]', 'PIO[18]',     'GPCLK[1]'    ], # 18
    [ 'SPI1_SIO[1]',  'DPI_D[15]', 'I2S0_WS',      'PWM0[3]',      'I2S1_WS',     'SYS_RIO[19]',  'PROC_RIO[19]', 'PIO[19]',     '-'           ], # 19
    [ 'SPI1_SIO[0]',  'DPI_D[16]', 'I2S0_SDI[0]',  'GPCLK[0]',     'I2S1_SDI[0]', 'SYS_RIO[20]',  'PROC_RIO[20]', 'PIO[20]',     '-'           ], # 20
    [ 'SPI1_SCLK',    'DPI_D[17]', 'I2S0_SDO[0]',  'GPCLK[1]',     'I2S1_SDO[0]', 'SYS_RIO[21]',  'PROC_RIO[21]', 'PIO[21]',     '-'           ], # 21
    [ 'SDIO0_CLK',    'DPI_D[18]', 'I2S0_SDI[1]',  'I2C3_SDA',     'I2S1_SDI[1]', 'SYS_RIO[22]',  'PROC_RIO[22]', 'PIO[22]',     '-'           ], # 22
    [ 'SDIO0_CMD',    'DPI_D[19]', 'I2S0_SDO[1]',  'I2C3_SCL',     'I2S1_SDO[1]', 'SYS_RIO[23]',  'PROC_RIO[23]', 'PIO[23]',     '-'           ], # 23
    [ 'SDIO0_DAT[0]', 'DPI_D[20]', 'I2S0_SDI[2]',  '-',            'I2S1_SDI[2]', 'SYS_RIO[24]',  'PROC_RIO[24]', 'PIO[24]',     'SPI2_CSn[1]' ], # 24
    [ 'SDIO0_DAT[1]', 'DPI_D[21]', 'I2S0_SDO[2]',  'AUDIO_IN_CLK', 'I2S1_SDO[2]', 'SYS_RIO[25]',  'PROC_RIO[25]', 'PIO[25]',     'SPI3_CSn[1]' ], # 25
    [ 'SDIO0_DAT[2]', 'DPI_D[22]', 'I2S0_SDI[3]',  'AUDIO_IN_DAT', 'I2S1_SDI[3]', 'SYS_RIO[26]',  'PROC_RIO[26]', 'PIO[26]',     'SPI5_CSn[1]' ], # 26
    [ 'SDIO0_DAT[3]', 'DPI_D[23]', 'I2S0_SDO[3]',  'AUDIO_IN_DAT', 'I2S1_SDO[3]', 'SYS_RIO[27]',  'PROC_RIO[27]', 'PIO[27]',     'SPI1_CSn[1]' ], # 27
    
    # BANK 1
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 28
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 29
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 30
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 31
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 32
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 33
   
    # BANK 2
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 34
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 35
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 36
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 37
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 38
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 39
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 40
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 41
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 42
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 43
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 44
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 45
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 46
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 47
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 48
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 49
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 50
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 51
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 52
    [ '-',            '-',         '-',            '-',            '-',           '-',            '-',            '-',           '-'           ], # 53
    
);

my $_alt_function_names;
my $_alt_function_names_version;

my %_revstash = (
    'beta'      => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision beta', revision => 'beta', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
    '0002'      => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision 1.0',  revision => '0002', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
    '0003'      => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 1.0',  revision => '0003', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
    '0004'      => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 2.0',  revision => '0004', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
    '0005'      => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0',  revision => '0005', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
    '0006'      => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0',  revision => '0006', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
    '0007'      => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0007', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
    '0008'      => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0008', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
    '0009'      => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0009', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
    
    '000d'      => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000d', board_type => $btype2, memory => 512, manufacturer => 'Egoman' },
    '000e'      => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000e', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
    '000f'      => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000f', board_type => $btype2, memory => 512, manufacturer => 'Qisda' },
    
    '0010'      => { release => 'Q3 2014', model_name => 'Raspberry Pi Model B +', revision => '0010', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
    '0011'      => { release => 'Q2 2013', model_name => 'Compute Module', revision => '0011', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
    '0012'      => { release => 'Q4 2014', model_name => 'Raspberry Pi Model A +', revision => '0012', board_type => $btype3, memory => 256, manufacturer => 'Sony' },
    
    '0014'      => { release => 'Q2 2015', model_name => 'Compute Module', revision => '0014', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
    '0015'      => { release => 'Q4 2015', model_name => 'Raspberry Pi Model A +', revision => '0015', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
    'unknown'   => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype2, memory => 512,  manufacturer => 'HiPi Virtual' },
    'unknownex' => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype3, memory => 1024, manufacturer => 'HiPi Virtual' },
);

# MAP 24 bits of Revision  NEW:1, MEMSIZE:3, MANUFACTURER:4, PROCESSOR:4, MODEL:8, BOARD REVISION:4

my %_revinfostash = (
    memsize => {
        '0' => 256,
        '1' => 512,
        '2' => 1024,
        '3' => 2048,
        '4' => 4096,
        '5' => 8192,
        '6' => 16284,
    },
    manufacturer => {
        '0' => 'Sony UK',
        '1' => 'Egoman',
        '2' => 'Embest',
        '3' => 'Sony Japan',
        '4' => 'Embest',
        '5' => 'Stadium',
    },
    processor => {
        '0' => 'BCM2835',
        '1' => 'BCM2836',
        '2' => 'BCM2837',
        '3' => 'BCM2711',
        '4' => 'BCM2712',
    },
    processor_info => {
        'UNKNOWN' => {
            arm                 => 'UNKNOWN',
            cores               => 1,
            architecture_width  => 32,
            hardware            => 'UNKNOWN',
            raspios_supported   => [ 'armhf' ],
        },
        'BCM2835' => {
            arm                 => 'ARM1176',
            cores               => 1,
            architecture_width  => 32,
            hardware            => 'BCM2835',
            raspios_supported   => [ 'armhf' ],
        },
        'BCM2836' => {
            arm                 => 'Cortex-A7',
            cores               => 4,
            architecture_width  => 32,
            hardware            => 'BCM2835',
            raspios_supported   => [ 'armhf' ],
        },
        'BCM2837' => {
            arm                 => 'Cortex-A53',
            cores               => 4,
            architecture_width  => 64,
            hardware            => 'BCM2835',
            raspios_supported   => [ 'armhf', 'arm64' ],
        },
        'BCM2711' => {
            arm                 => 'Cortex-A72',
            cores               => 4,
            architecture_width  => 64,
            hardware            => 'BCM2835',
            raspios_supported   => [ 'armhf', 'arm64' ],
        },
        'BCM2712' => {
            arm                 => 'Cortex-A76',
            cores               => 4,
            architecture_width  => 64,
            hardware            => 'RP1',
            raspios_supported   => [ 'armhf', 'arm64' ],
        },
    },
    type => {
        '0'  => 'Raspberry Pi Model A',                 # 00
        '1'  => 'Raspberry Pi Model B',                 # 01
        '2'  => 'Raspberry Pi Model A Plus',            # 02
        '3'  => 'Raspberry Pi Model B Plus',            # 03
        '4'  => 'Raspberry Pi 2 Model B',               # 04
        '5'  => 'Raspberry Pi Alpha',                   # 05
        '6'  => 'Raspberry Pi Compute Module 1',        # 06
        '7'  => 'UNKNOWN Raspberry Pi Model 07',        # 07
        '8'  => 'Raspberry Pi 3 Model B',               # 08
        '9'  => 'Raspberry Pi Zero',                    # 09
        '10' => 'Raspberry Pi Compute Module 3',        # 0A
        '11' => 'UNKNOWN Raspberry Pi Model 11',        # 0B
        '12' => 'Raspberry Pi Zero W',                  # 0C
        '13' => 'Raspberry Pi 3 Model B Plus',          # 0D
        '14' => 'Raspberry Pi 3 Model A Plus',          # 0E
        '15' => 'UNKNOWN Rasberry Pi Model 15',         # 0F
        '16' => 'Raspberry Pi Compute Module 3 Plus',   # 10
        '17' => 'Raspberry Pi 4 Model B',               # 11
        '18' => 'Raspberry Pi Zero 2 W',                # 12
        '19' => 'Raspberry Pi Model 400',               # 13
        '20' => 'Raspberry Pi Compute Module 4',        # 14
        '21' => 'Raspberry Pi Compute Module 4S',       # 15
        '22' => 'UNKOWN Rasberry Pi Model 22',          # 16
        '23' => 'Rasberry Pi 5 Model B',                # 17
        '24' => 'Rasberry Pi Compute Module 5',         # 18
        '25' => 'Rasberry Pi Model 500',                # 19
        '26' => 'Rasberry Pi Compute Module 5 Lite',    # 1A
    },
    board_type => {
        '0'  => $btype2,
        '1'  => $btype2,
        '2'  => $btype3,
        '3'  => $btype3,
        '4'  => $btype3,
        '5'  => $btype1,
        '6'  => $btype2,
        '7'  => $btype3,
        '8'  => $btype3,
        '9'  => $btype3,
        '10' => $btype4,
        '11' => $btype3,
        '12' => $btype3,
        '13' => $btype3,
        '14' => $btype3,
        '15' => $btype3,
        '16' => $btype4,
        '17' => $btype3,
        '18' => $btype3,
        '19' => $btype3,
        '20' => $btype4,
        '21' => $btype4,
        '22' => $btype3,
        '23' => $btype3,
        '24' => $btype4,
        '25' => $btype3,
        '26' => $btype4,
    },
    release => {
        '0'  => 'Q1 2013',
        '1'  => 'Q3 2012',
        '2'  => 'Q4 2014',
        '3'  => 'Q3 2014',
        '4'  => 'Q1 2015',
        '5'  => 'Q1 2012',
        '6'  => 'Q2 2013',
        '7'  => 'Q2 2015',
        '8'  => 'Q1 2016',
        '9'  => 'Q4 2015',
        '10' => 'Q1 2017',
        '11' => 'unknown',
        '12' => 'Q1 2017',
        '13' => 'Q1 2018',
        '14' => 'Q4 2018',
        '15' => 'unknown',
        '16' => 'Q1 2019',
        '17' => 'Q2 2019',
        '18' => 'Q4 2021',
        '19' => 'Q4 2020',
        '20' => 'Q4 2020',
        '21' => 'Q4 2020',
        '22' => 'unknown',
        '23' => 'Q4 2023',
        '24' => 'Q3 2024',
        '25' => 'Q4 2024',
        '26' => 'Q3 2024',
    },
    extended_release => {
        'a03111' => 'Q2 2019', #	4B	1.1	1GB	Sony UK
        'a03115' => 'Q1 2022', #	4B	1.5	1GB	Sony UK
        
        'b03111' => 'Q2 2019', #	4B	1.1	2GB	Sony UK
        'b03112' => 'Q1 2020', #	4B	1.2	2GB	Sony UK
        'b03114' => 'Q3 2020', #	4B	1.4	2GB	Sony UK
        'b03115' => 'Q1 2022', #	4B	1.5	2GB	Sony UK
        
        'b04170' => 'Q3 2024', #    5B  1.0 2GB Sony UK
        'b04171' => 'Q4 2024', #    5B  1.1 2GB Sony UK
        
        'c03111' => 'Q2 2019', # 	4B	1.1	4GB	Sony UK
        'c03112' => 'Q1 2020', #	4B	1.2	4GB	Sony UK
        'c03114' => 'Q2 2020', #	4B	1.4	4GB	Sony UK
        'c03115' => 'Q1 2022', #	4B	1.5	4GB	Sony UK
        
        'c03130' => 'Q3 2020', #    400 1.0 4GB Sony UK
        
        'c04170' => 'Q4 2023', #	5B	1.0	4GB	Sony UK
        'c04171' => 'Q4 2023', #	5B	1.1	4GB	Sony UK
        
        'd03114' => 'Q2 2020', #	4B	1.4	8GB	Sony UK
        'd03115' => 'Q1 2022', #	4B	1.5	8GB	Sony UK
        
        'd04170' => 'Q4 2023', #	5B	1.0	8GB	Sony UK
        'd04171' => 'Q4 2024', #	5B	1.1	8GB	Sony UK
        
        
        'd04190' => 'Q4 2024', #    500 1.0 8GB Sony UK
        'e04190' => 'Q3 2025', #    500+ 1.0 16GB Sony UK
        
        'e04171' => 'Q1 2025', #    5B  1.1 16GB Sony UK
    },
        
);

my $_config = $_revstash{unknownex};

sub os_is_windows { return ( $^O =~ /^mswin/i ) ? 1 : 0; }

sub os_is_osx { return ( $^O =~ /^darwen/i ) ? 1 : 0; }

sub os_is_linux { return ( $^O =~ /^linux/i ) ? 1 : 0; }

sub os_is_other { return ( $^O !~ /^mswin|linux|darwen/i ) ? 1 : 0; }

sub os_supported { return ( $^O =~ /^linux/i ) ? 1 : 0; }

sub is_raspberry { return $israspberry; }

sub is_raspberry_1 { return $israspberry1; }

sub is_raspberry_2 { return $israspberry2; }

sub is_raspberry_3 { return $israspberry3; }

sub is_raspberry_4 { return $israspberry4; }

sub is_raspberry_5 { return $israspberry5; }

sub has_device_tree { return $hasdevicetree; }

sub home_directory { return $homedir; }

sub board_type { return $_config->{board_type}; }

sub gpio_header_type { return $_config->{board_type}; }

sub manufacturer { return $_config->{manufacturer}; }

sub release_date { return $_config->{release}; }

sub processor { return $_config->{processor}; }

sub has_rp1 { return ( $israspberry5 ) ? 1 : 0; }

sub hardware { return $_config->{processor_info}->{hardware}; }

sub model_name { return $_config->{modelname}; }

sub revision { return $_config->{revision}; }

sub memory { return $_config->{memory}; }

sub serial_number { return $_config->{serial}; }

sub short_serial_number { return $_config->{short_serial}; }

sub get_alt_function_names { return $_alt_function_names; }

sub alt_func_version { return $_alt_function_names_version; }

sub architecture_width { return $_config->{processor_info}->{architecture_width}; }

sub arm_core { return $_config->{processor_info}->{arm}; }

sub rasberrypi_os_support {
    return ( wantarray )
        ? @{ $_config->{processor_info}->{raspios_supported} }
        : join(', ', @{ $_config->{processor_info}->{raspios_supported} } );
}

sub number_of_cores { return $_config->{processor_info}->{cores}; }

sub board_description {
    my $description = 'Unknown board type';
    if($_config->{board_type} == $btype1 ) {
        $description = 'Type 1 26 pin GPIO header';
    } elsif($_config->{board_type} == $btype2 ) {
        $description = 'Type 2 26 pin GPIO header';
    } elsif($_config->{board_type} == $btype3 ) {
        $description = 'Type 3 40 pin GPIO header';
    } elsif($_config->{board_type} == $btype4 ) {
        $description = 'Type 4 Compute Module';
    }
    return $description;
}

sub _configure {
    
    my %_cpuinfostash = ();
    
    my $device_tree_boardname = '';
    
    if( os_is_linux() ) {
        # clean our path for safety
        local $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
        my $output = qx(cat /proc/cpuinfo);
        
        if( $output ) {
            for ( split(/\n/, $output) ) {
                if( $_ =~ /^([^\s]+)\s*:\s(.+)$/ ) {
                    $_cpuinfostash{$1} = $2;
                }
            }
        }
        
        $hasdevicetree = ( -e '/proc/device-tree/soc/ranges' ) ? 1 : 0;
        if( $hasdevicetree ) {
            my $bname = qx(cat /proc/device-tree/model);
            chomp $bname;
            
            $device_tree_boardname = $bname if( $bname );
        }
    }
    
    my $serial = ($_cpuinfostash{Serial}) ?  $_cpuinfostash{Serial} : 'SERIALNONOTFOUND';
    my $short_serial = $serial;
    $short_serial =~ s/^(.{8})(.{8})$/$2/;
    my $defaultkey = 'unknownex';
    my $rev = ($_cpuinfostash{Revision}) ?  lc( $_cpuinfostash{Revision} ) : $defaultkey;
    $rev =~ s/^\s+//;
    $rev =~ s/\s+$//;
    
    if ( $rev =~ /(beta|unknown|unknownex)$/) {
        my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
        $_config = { %{ $_revstash{$infokey} } };
        $_config->{processor} = 'UNKNOWN';
        $_config->{revision} = 'UNKNOWN';
        $_config->{processor_info} = $_revinfostash{processor_info}->{'UNKNOWN'};
    } else {
        # is this a scheme 0 or 1 number
        my $revnum = oct( '0x' . $rev );
        #          NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
        #                  ^
        my $rev_scheme_new_type = ( $revnum >> 23 ) & 1;
        
        if ( $rev_scheme_new_type ) {
            #            NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR

            # revision                               RRRR
            my $s_revision  =                      0b1111 & $revnum;
            # raspberry type                 TTTTTTTT
            my $s_raspberry_type =       ( 0b111111110000 & $revnum ) >> 4;
            # processor                  PPPP
            my $s_processor =        ( 0b1111000000000000 & $revnum ) >> 12;
            # manufacturer           CCCC
            my $s_manufacturer = ( 0b11110000000000000000 & $revnum ) >> 16;
            # memory              MMM
            my $s_memory =    ( 0b11100000000000000000000 & $revnum ) >> 20;           
            # warranty   NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
            #                  ^
            my $s_warranty    = ( $revnum >> 25 ) & 1;
            # otp read   NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
            #              ^
            my $s_otp_read    = ( $revnum >> 29 ) & 1;
            # otp prog   NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
            #             ^
            my $s_otp_prog    = ( $revnum >> 30 ) & 1;
            # no o volt  NOQuuuWuFMMMCCCCPPPPTTTTTTTTRRRR
            #            ^
            my $s_no_overvolt = ( $revnum >> 31 ) & 1;
            
            # base type
            my $binfo = $_revstash{$defaultkey};
                        
            $binfo->{release}  = $_revinfostash{extended_release}->{$rev} || $_revinfostash{release}->{$s_raspberry_type} || 'Q1 2015';
            $binfo->{model_name} = $_revinfostash{type}->{$s_raspberry_type} || qq(Unknown Raspberry Pi Type : $s_raspberry_type);
            $binfo->{model_name} = $device_tree_boardname if $device_tree_boardname;
            $binfo->{memory}   = $_revinfostash{memsize}->{$s_memory} || 256;
            $binfo->{manufacturer} = $_revinfostash{manufacturer}->{$s_manufacturer} || 'Sony';
            $binfo->{board_type} =  $_revinfostash{board_type}->{$s_raspberry_type} || 3;
            $binfo->{processor} = $_revinfostash{processor}->{$s_processor} || 'BCM2835';
            $binfo->{revision} = $rev;
            $binfo->{revisionnumber} = $s_revision;
            $binfo->{processor_info} = $_revinfostash{processor_info}->{$binfo->{processor}};
            
            my $unknown_raspberry_type =
                            ( $s_raspberry_type == 5  ||
                              $s_raspberry_type == 7  ||
                              $s_raspberry_type == 11 ||
                              $s_raspberry_type == 15 ||
                              $s_raspberry_type == 22  ) ? 1 : 0;
            
            $israspberry1 = ( $s_raspberry_type == 0 ||
                              $s_raspberry_type == 1 ||
                              $s_raspberry_type == 2 ||
                              $s_raspberry_type == 3 ||
                              $s_raspberry_type == 6 ||
                              $s_raspberry_type == 9 ||
                              $s_raspberry_type == 12 ) ? 1 : 0;
            
            $israspberry2 = ( $s_raspberry_type == 4 ) ? 1 : 0;
            
            $israspberry3 = ( $s_raspberry_type == 8  ||
                              $s_raspberry_type == 10 ||
                              $s_raspberry_type == 13 ||
                              $s_raspberry_type == 14 ||
                              $s_raspberry_type == 16 ||
                              $s_raspberry_type == 18 ) ? 1 : 0;
            
            $israspberry4 = ( $s_raspberry_type == 17 ||
                              $s_raspberry_type == 19 ||
                              $s_raspberry_type == 20 ||
                              $s_raspberry_type == 21 ) ? 1 : 0;
            
            $israspberry5 = ( $s_raspberry_type == 23 ) ? 1 : 0;
            
            $israspberry = (
                $israspberry1 || $israspberry2 || $israspberry3 || $israspberry4 || $israspberry5
            ) ? 1 : 0;
            
            $_config = { %$binfo };
        } else {
            my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
            $_config = { %{ $_revstash{$infokey} } };
            $_config->{processor} = 'BCM2835';
            $_config->{revisionnumber} = 0;
            $_config->{processor_info} = $_revinfostash{processor_info}->{'BCM2835'};
            $israspberry1 = $israspberry = exists($_revstash{$rev}) ? 1 : 0;
        }
        
    }    
   
    # Home Dir
    if( os_is_windows ) {
        require Win32;
        $homedir = Win32::GetFolderPath( 0x001C, 1);
        $homedir = Win32::GetShortPathName( $homedir );
        $homedir =~ s/\\/\//g;
    } else {
        $homedir = (getpwuid($<))[7];
    }
    
    $_config->{serial}  = $serial;
    $_config->{short_serial}  = $short_serial;
    
    if($_config->{processor} eq 'BCM2712' ) {
        $_alt_function_names = \@_alt_func_names_2712;
        $_alt_function_names_version = 3;
    } elsif($_config->{processor} eq 'BCM2711' ) {
        $_alt_function_names = \@_alt_func_names_2711;
        $_alt_function_names_version = 2;
    } else {
        $_alt_function_names = \@_alt_func_names_2708;
        $_alt_function_names_version = 1;
    }
    
    return;
}

sub new {
    my $class = shift;
    my $self = bless {}, $class;
    return  $self;
}

sub validpins {
    my $type = board_type();
    if ( $type == 1 ) {
        return ( 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25 );
    } elsif ( $type == 2 ) {    
        return ( 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, 28, 29, 30, 31 );
    } else {
        # return current latest known pinset
        return ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 );
    }
}

sub dump_board_info {
    my $processor = $_config->{processor};
    my $dump = qq(--------------------------------------------------\n);
    $dump .= qq(Raspberry Pi Board Info\n);
    $dump .= qq(--------------------------------------------------\n);
    $dump .= qq(Model Name       : $_config->{model_name}\n);
    $dump .= qq(Released         : $_config->{release}\n);
    $dump .= qq(Manufacturer     : $_config->{manufacturer}\n);
    $dump .= qq(Memory           : $_config->{memory}\n);
    $dump .= qq(Processor        : $processor\n);
    $dump .= qq(Hardware         : ) . hardware() . qq(\n);
    my $description = board_description();
    $dump .= qq(Description      : $description\n);
    $dump .= qq(Revision         : $_config->{revision}\n);
    $dump .= qq(Serial Number    : $_config->{serial}\n);
    $dump .= qq(Short Serial No  : $_config->{short_serial}\n);
    $dump .= qq(GPIO Header Type : $_config->{board_type}\n);
    $dump .= qq(Revision Number  : $_config->{revisionnumber}\n);
    my $devtree = ( has_device_tree() ) ? 'Yes' : 'No';
    
    $dump .= qq(Device Tree      : $devtree\n);
    $dump .= q(Is Raspberry     : ) . (($israspberry) ? 'Yes' : 'No' ) . qq(\n);
    $dump .= q(Is Raspberry 1   : ) . (($israspberry1) ? 'Yes' : 'No' ) . qq(\n);
    $dump .= q(Is Raspberry 2   : ) . (($israspberry2) ? 'Yes' : 'No' ) . qq(\n);
    $dump .= q(Is Raspberry 3   : ) . (($israspberry3) ? 'Yes' : 'No' ) . qq(\n);
    $dump .= q(Is Raspberry 4   : ) . (($israspberry4) ? 'Yes' : 'No' ) . qq(\n);
    $dump .= q(Is Raspberry 5   : ) . (($israspberry5) ? 'Yes' : 'No' ) . qq(\n);
    
    $dump .= q(Alt Function Map : Version ) . alt_func_version() . qq(\n);
    
    $dump .= qq(ARM Core         : ) . arm_core() . qq(\n);
    $dump .= qq(Number of Cores  : ) . number_of_cores() . qq(\n);
    $dump .= qq(Architecture     : Width ) . architecture_width() . qq( bit\n);
    $dump .= qq(OS arch support  : ) . rasberrypi_os_support() . qq(\n);
    
    return $dump;
}

_configure();

1;

__END__