/*
 * 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_XBCDE_H
#define ECXX_PLATFORM_AVR_PIN_MAPPING_STD_XBCDE_H


//
// Available ports : B C D E (no Arduino variant)
//


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

static constexpr uint8_t minPWMPinNumber[1]  = {  9 };
static constexpr uint8_t maxPWMPinNumber[1]  = { 11 };

static constexpr uint8_t minADCPinNumber     = 14;
static constexpr uint8_t maxADCPinNumber     = 21;
static constexpr uint8_t adcPortLow          = ECXX_PX;
static constexpr uint8_t adcPortHigh         = ECXX_NOT_ADC;

static constexpr uint8_t spiPinsMISO[2]      = { AVR::SPI0_MISO, AVR::SPI1_MISO };
static constexpr uint8_t spiPinsMOSI[2]      = { AVR::SPI0_MOSI, AVR::SPI1_MOSI };
static constexpr uint8_t spiPinsSCK [2]      = { AVR::SPI0_SCK,  AVR::SPI1_SCK  };
static constexpr uint8_t spiPinsSS  [2]      = { AVR::SPI0_SS,   AVR::SPI1_SS   };

static constexpr uint8_t spiPinMISO          = spiPinsMISO[0];
static constexpr uint8_t spiPinMOSI          = spiPinsMOSI[0];
static constexpr uint8_t spiPinSCK           = spiPinsSCK [0];
static constexpr uint8_t spiPinSS            = spiPinsSS  [0];

static constexpr uint8_t twiPinsSDA[2]       = { AVR::TWI_SDA, 22 }; // ** TWI1 is not implemented in eCxx **
static constexpr uint8_t twiPinsSCL[2]       = { AVR::TWI_SCL, 23 }; // ** TWI1 is not implemented in eCxx **

static constexpr uint8_t twiPinSDA           = twiPinsSDA[0];
static constexpr uint8_t twiPinSCL           = twiPinsSCL[0];


// PWM pins [group][set][pin/timer]
static constexpr uint8_t pwm_pins[1][3][2] = { {
    {  9, ECXX_TIMER1A },
    { 10, ECXX_TIMER1B },
    { 11, ECXX_TIMER2A }
} };


// Digital pin number to port number
ECXX_UINT8_ARRAY pin_to_pnum[] = {
             //               Alternate port function (TQFP32)
             //               328PB
    ECXX_PD, // PD 0 **  0 ** RXD0      USART0_RX HOST_PC_COM
    ECXX_PD, // PD 1 **  1 ** TXD0      USART0_TX HOST_PC_COM
    ECXX_PD, // PD 2 **  2 ** INT0
    ECXX_PD, // PD 3 **  3 ** INT1
    ECXX_PD, // PD 4 **  4 **
    ECXX_PD, // PD 5 **  5 ** OC0B                TIMER0_INTERNAL
    ECXX_PD, // PD 6 **  6 ** OC0A
    ECXX_PD, // PD 7 **  7 **
    ECXX_PB, // PB 0 **  8 **
    ECXX_PB, // PB 1 **  9 ** OC1A                PWM9
    ECXX_PB, // PB 2 ** 10 ** OC1B      SPI0_SS   PWM10
    ECXX_PB, // PB 3 ** 11 ** OC2A/TXD1 SPI0_MOSI PWM11
    ECXX_PB, // PB 4 ** 12 **      RXD1 SPI0_MISO
    ECXX_PB, // PB 5 ** 13 **           SPI0_SCK  INDICATOR_LED
    ECXX_PC, // PC 0 ** 14 ** A0        SPI1_MISO
    ECXX_PC, // PC 1 ** 15 ** A1        SPI1_SCK
    ECXX_PC, // PC 2 ** 16 ** A2
    ECXX_PC, // PC 3 ** 17 ** A3
    ECXX_PC, // PC 4 ** 18 ** A4        TWI0_SDA
    ECXX_PC, // PC 5 ** 19 ** A5        TWI0_SCL
    ECXX_PE, // PE 2 ** 20 ** A6        SPI1_SS
    ECXX_PE, // PE 3 ** 21 ** A7        SPI1_MOSI
    ECXX_PE, // PE 0 ** 22 **           TWI1_SDA  ** TWI1 is not implemented in eCxx **
    ECXX_PE  // PE 1 ** 23 **           TWI1_SCL  ** TWI1 is not implemented in eCxx **
};


// Digital pin number to port bit mask
ECXX_UINT8_ARRAY pin_to_bitmask[] = {
    _BV(0), // PD 0 **  0 **
    _BV(1), // PD 1 **  1 **
    _BV(2), // PD 2 **  2 **
    _BV(3), // PD 3 **  3 **
    _BV(4), // PD 4 **  4 **
    _BV(5), // PD 5 **  5 **
    _BV(6), // PD 6 **  6 **
    _BV(7), // PD 7 **  7 **
    _BV(0), // PB 0 **  8 **
    _BV(1), // PB 1 **  9 **
    _BV(2), // PB 2 ** 10 **
    _BV(3), // PB 3 ** 11 **
    _BV(4), // PB 4 ** 12 **
    _BV(5), // PB 5 ** 13 **
    _BV(0), // PC 0 ** 14 **
    _BV(1), // PC 1 ** 15 **
    _BV(2), // PC 2 ** 16 **
    _BV(3), // PC 3 ** 17 **
    _BV(4), // PC 4 ** 18 **
    _BV(5), // PC 5 ** 19 **
    _BV(2), // PE 2 ** 20 **
    _BV(3), // PE 3 ** 21 **
    _BV(0), // PE 0 ** 22 **
    _BV(1)  // PE 1 ** 23 **
};


// Port number to direction SFR
static constexpr volatile uint8_t* const pnum_to_DDR[] = {
    ECXX_NOT_IO_REG,
    ECXX_NOT_IO_REG,
    &DDRB,
    &DDRC,
    &DDRD,
    &DDRE
};


// Port number to output SFR
static constexpr volatile uint8_t* const pnum_to_PORT[] = {
    ECXX_NOT_IO_REG,
    ECXX_NOT_IO_REG,
    &PORTB,
    &PORTC,
    &PORTD,
    &PORTE
};


// Port number to input SFR
static constexpr volatile uint8_t* const pnum_to_PIN[] = {
    ECXX_NOT_IO_REG,
    ECXX_NOT_IO_REG,
    &PINB,
    &PINC,
    &PIND,
    &PINE
};


#endif
