/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef INCLUDE_ECXX_PLATFORM_AVR_PIN_MAPPING_STD_H
#error "this file cannot be included directly"
#endif
#undef INCLUDE_ECXX_PLATFORM_AVR_PIN_MAPPING_STD_H


#ifndef ECXX_PLATFORM_AVR_PIN_MAPPING_STD_ABCDEFGHXJKL_H
#define ECXX_PLATFORM_AVR_PIN_MAPPING_STD_ABCDEFGHXJKL_H


//
// Available ports : A B C D E F G H J K L (e.g. Arduino variant mega)
//


// Pin number ranges
static constexpr uint8_t maxDigitalPinNumber = AVR::DMax;

static constexpr uint8_t minPWMPinNumber[2]  = {  5, 44 };
static constexpr uint8_t maxPWMPinNumber[2]  = { 12, 46 };

static constexpr uint8_t minADCPinNumber     = 54;
static constexpr uint8_t maxADCPinNumber     = 69;
static constexpr uint8_t adcPortLow          = ECXX_PF; // The 1st eight = 54 - 61
static constexpr uint8_t adcPortHigh         = ECXX_PK; // The 2nd eight = 62 - 69

static constexpr uint8_t spiPinMISO          = AVR::SPI_MISO;
static constexpr uint8_t spiPinMOSI          = AVR::SPI_MOSI;
static constexpr uint8_t spiPinSCK           = AVR::SPI_SCK;
static constexpr uint8_t spiPinSS            = AVR::SPI_SS;

static constexpr uint8_t twiPinSDA           = AVR::TWI_SDA;
static constexpr uint8_t twiPinSCL           = AVR::TWI_SCL;


// PWM pins [group][set][pin/timer]
static constexpr uint8_t pwm_pins[2][8][2] = {
    {
        {  5, ECXX_TIMER3A },
        {  6, ECXX_TIMER4A },
        {  7, ECXX_TIMER4B },
        {  8, ECXX_TIMER4C },
        {  9, ECXX_TIMER2B },
        { 10, ECXX_TIMER2A },
        { 11, ECXX_TIMER1A },
        { 12, ECXX_TIMER1B }
    },
    {
        { 44, ECXX_TIMER5C },
        { 45, ECXX_TIMER5B },
        { 46, ECXX_TIMER5A },
        {  0, ECXX_NOT_PWM },
        {  0, ECXX_NOT_PWM },
        {  0, ECXX_NOT_PWM },
        {  0, ECXX_NOT_PWM },
        {  0, ECXX_NOT_PWM }
    }
};


// Digital pin number to port number
ECXX_UINT8_ARRAY pin_to_pnum[] = {
             //               Alternate port function (TQFP100)
             //               2560
    ECXX_PE, // PE 0 **  0 ** RXD0 USART0_RX HOST_PC_COM
    ECXX_PE, // PE 1 **  1 ** TXD0 USART0_TX HOST_PC_COM
    ECXX_PE, // PE 4 **  2 ** INT4
    ECXX_PE, // PE 5 **  3 ** INT5
    ECXX_PG, // PG 5 **  4 ** OC0B           TIMER0_INTERNAL
    ECXX_PE, // PE 3 **  5 ** OC3A           PWM5
    ECXX_PH, // PH 3 **  6 ** OC4A           PWM6
    ECXX_PH, // PH 4 **  7 ** OC4B           PWM7
    ECXX_PH, // PH 5 **  8 ** OC4C           PWM8
    ECXX_PH, // PH 6 **  9 ** OC2B           PWM9
    ECXX_PB, // PB 4 ** 10 ** OC2A           PWM10
    ECXX_PB, // PB 5 ** 11 ** OC1A           PWM11
    ECXX_PB, // PB 6 ** 12 ** OC1B           PWM12
    ECXX_PB, // PB 7 ** 13 ** OC1C           INDICATOR_LED
    ECXX_PJ, // PJ 1 ** 14 ** TXD3 USART3_TX
    ECXX_PJ, // PJ 0 ** 15 ** RXD3 USART3_RX
    ECXX_PH, // PH 1 ** 16 ** TXD2 USART2_TX
    ECXX_PH, // PH 0 ** 17 ** RXD2 USART2_RX
    ECXX_PD, // PD 3 ** 18 ** INT3 USART1_TX
    ECXX_PD, // PD 2 ** 19 ** INT2 USART1_RX
    ECXX_PD, // PD 1 ** 20 ** INT1 TWI_SDA
    ECXX_PD, // PD 0 ** 21 ** INT0 TWI_SCL
    ECXX_PA, // PA 0 ** 22 **
    ECXX_PA, // PA 1 ** 23 **
    ECXX_PA, // PA 2 ** 24 **
    ECXX_PA, // PA 3 ** 25 **
    ECXX_PA, // PA 4 ** 26 **
    ECXX_PA, // PA 5 ** 27 **
    ECXX_PA, // PA 6 ** 28 **
    ECXX_PA, // PA 7 ** 29 **
    ECXX_PC, // PC 7 ** 30 **
    ECXX_PC, // PC 6 ** 31 **
    ECXX_PC, // PC 5 ** 32 **
    ECXX_PC, // PC 4 ** 33 **
    ECXX_PC, // PC 3 ** 34 **
    ECXX_PC, // PC 2 ** 35 **
    ECXX_PC, // PC 1 ** 36 **
    ECXX_PC, // PC 0 ** 37 **
    ECXX_PD, // PD 7 ** 38 **
    ECXX_PG, // PG 2 ** 39 **
    ECXX_PG, // PG 1 ** 40 **
    ECXX_PG, // PG 0 ** 41 **
    ECXX_PL, // PL 7 ** 42 **
    ECXX_PL, // PL 6 ** 43 **
    ECXX_PL, // PL 5 ** 44 ** OC5C           PWM44
    ECXX_PL, // PL 4 ** 45 ** OC5B           PWM45
    ECXX_PL, // PL 3 ** 46 ** OC5A           PWM46
    ECXX_PL, // PL 2 ** 47 **
    ECXX_PL, // PL 1 ** 48 **
    ECXX_PL, // PL 0 ** 49 **
    ECXX_PB, // PB 3 ** 50 **      SPI_MISO
    ECXX_PB, // PB 2 ** 51 **      SPI_MOSI
    ECXX_PB, // PB 1 ** 52 **      SPI_SCK
    ECXX_PB, // PB 0 ** 53 **      SPI_SS
    ECXX_PF, // PF 0 ** 54 ** A0
    ECXX_PF, // PF 1 ** 55 ** A1
    ECXX_PF, // PF 2 ** 56 ** A2
    ECXX_PF, // PF 3 ** 57 ** A3
    ECXX_PF, // PF 4 ** 58 ** A4
    ECXX_PF, // PF 5 ** 59 ** A5
    ECXX_PF, // PF 6 ** 60 ** A6
    ECXX_PF, // PF 7 ** 61 ** A7
    ECXX_PK, // PK 0 ** 62 ** A8
    ECXX_PK, // PK 1 ** 63 ** A9
    ECXX_PK, // PK 2 ** 64 ** A10
    ECXX_PK, // PK 3 ** 65 ** A11
    ECXX_PK, // PK 4 ** 66 ** A12
    ECXX_PK, // PK 5 ** 67 ** A13
    ECXX_PK, // PK 6 ** 68 ** A14
    ECXX_PK, // PK 7 ** 69 ** A15
    ECXX_PE, // PE 2 ** 70 **                      ** MEGA - NO ON-BOARD PIN **
    ECXX_PE, // PE 6 ** 71 **                      ** MEGA - NO ON-BOARD PIN **
    ECXX_PE  // PE 7 ** 72 **                      ** MEGA - NO ON-BOARD PIN **
};


// Digital pin number to port bit mask
ECXX_UINT8_ARRAY pin_to_bitmask[] = {
    _BV(0), // PE 0 **  0 **
    _BV(1), // PE 1 **  1 **
    _BV(4), // PE 4 **  2 **
    _BV(5), // PE 5 **  3 **
    _BV(5), // PG 5 **  4 **
    _BV(3), // PE 3 **  5 **
    _BV(3), // PH 3 **  6 **
    _BV(4), // PH 4 **  7 **
    _BV(5), // PH 5 **  8 **
    _BV(6), // PH 6 **  9 **
    _BV(4), // PB 4 ** 10 **
    _BV(5), // PB 5 ** 11 **
    _BV(6), // PB 6 ** 12 **
    _BV(7), // PB 7 ** 13 **
    _BV(1), // PJ 1 ** 14 **
    _BV(0), // PJ 0 ** 15 **
    _BV(1), // PH 1 ** 16 **
    _BV(0), // PH 0 ** 17 **
    _BV(3), // PD 3 ** 18 **
    _BV(2), // PD 2 ** 19 **
    _BV(1), // PD 1 ** 20 **
    _BV(0), // PD 0 ** 21 **
    _BV(0), // PA 0 ** 22 **
    _BV(1), // PA 1 ** 23 **
    _BV(2), // PA 2 ** 24 **
    _BV(3), // PA 3 ** 25 **
    _BV(4), // PA 4 ** 26 **
    _BV(5), // PA 5 ** 27 **
    _BV(6), // PA 6 ** 28 **
    _BV(7), // PA 7 ** 29 **
    _BV(7), // PC 7 ** 30 **
    _BV(6), // PC 6 ** 31 **
    _BV(5), // PC 5 ** 32 **
    _BV(4), // PC 4 ** 33 **
    _BV(3), // PC 3 ** 34 **
    _BV(2), // PC 2 ** 35 **
    _BV(1), // PC 1 ** 36 **
    _BV(0), // PC 0 ** 37 **
    _BV(7), // PD 7 ** 38 **
    _BV(2), // PG 2 ** 39 **
    _BV(1), // PG 1 ** 40 **
    _BV(0), // PG 0 ** 41 **
    _BV(7), // PL 7 ** 42 **
    _BV(6), // PL 6 ** 43 **
    _BV(5), // PL 5 ** 44 **
    _BV(4), // PL 4 ** 45 **
    _BV(3), // PL 3 ** 46 **
    _BV(2), // PL 2 ** 47 **
    _BV(1), // PL 1 ** 48 **
    _BV(0), // PL 0 ** 49 **
    _BV(3), // PB 3 ** 50 **
    _BV(2), // PB 2 ** 51 **
    _BV(1), // PB 1 ** 52 **
    _BV(0), // PB 0 ** 53 **
    _BV(0), // PF 0 ** 54 **
    _BV(1), // PF 1 ** 55 **
    _BV(2), // PF 2 ** 56 **
    _BV(3), // PF 3 ** 57 **
    _BV(4), // PF 4 ** 58 **
    _BV(5), // PF 5 ** 59 **
    _BV(6), // PF 6 ** 60 **
    _BV(7), // PF 7 ** 61 **
    _BV(0), // PK 0 ** 62 **
    _BV(1), // PK 1 ** 63 **
    _BV(2), // PK 2 ** 64 **
    _BV(3), // PK 3 ** 65 **
    _BV(4), // PK 4 ** 66 **
    _BV(5), // PK 5 ** 67 **
    _BV(6), // PK 6 ** 68 **
    _BV(7), // PK 7 ** 69 **
    _BV(2), // PE 2 ** 70 **
    _BV(2), // PE 6 ** 71 **
    _BV(2)  // PE 7 ** 72 **
};


// Port number to direction SFR
static constexpr volatile uint8_t* const pnum_to_DDR[] = {
    ECXX_NOT_IO_REG,
    &DDRA,
    &DDRB,
    &DDRC,
    &DDRD,
    &DDRE,
    &DDRF,
    &DDRG,
    &DDRH,
    ECXX_NOT_IO_REG,
    &DDRJ,
    &DDRK,
    &DDRL
};


// Port number to output SFR
static constexpr volatile uint8_t* const pnum_to_PORT[] = {
    ECXX_NOT_IO_REG,
    &PORTA,
    &PORTB,
    &PORTC,
    &PORTD,
    &PORTE,
    &PORTF,
    &PORTG,
    &PORTH,
    ECXX_NOT_IO_REG,
    &PORTJ,
    &PORTK,
    &PORTL
};


// Port number to input SFR
static constexpr volatile uint8_t* const pnum_to_PIN[] = {
    ECXX_NOT_IO_REG,
    &PINA,
    &PINB,
    &PINC,
    &PIND,
    &PINE,
    &PINF,
    &PING,
    &PINH,
    ECXX_NOT_IO_REG,
    &PINJ,
    &PINK,
    &PINL
};


#endif
