#ifndef MAPPINGS_H
#define MAPPINGS_H

// CHOOSE ONE, comment the other or comment both and use -D SN_FRONT
//#define SN_FRONT
#define SN_REAR

#include <stdint.h>
#include "main.h"

#define NUM_DIO_PINS 6

static struct {
  GPIO_TypeDef* port;
  uint16_t pin;
} DIO_PIN_MAP[NUM_DIO_PINS] = {
/* 0 */ { .port = D1_IC_GPIO_Port,  .pin = D1_IC_Pin},
/* 1 */ { .port = D2_GPIO_Port,     .pin = D2_Pin},
/* 2 */ { .port = D3_GPIO_Port,     .pin = D3_Pin},
/* 3 */ { .port = D4_IC_GPIO_Port,  .pin = D4_IC_Pin},
/* 4 */ { .port = D5_GPIO_Port,     .pin = D5_Pin},
/* 5 */ { .port = D6_GPIO_Port,     .pin = D6_Pin},
};

typedef enum {
    L1 = 0,
    L2 = 1,
    L3 = 2,
    L4 = 3,
    L5 = 4,
    L6 = 5,
    L7 = 6,
    L8 = 7,
    R9 = 8,
    RA = 9,
    RB = 10,
    RC = 11,
    RD = 12,
    RE = 13,
    RF = 14,
    R0 = 15,
} analog_pin_t;

typedef enum {
    L9 = 0,
    LA = 1,
    LC = 2,
    R5 = 3,
    R6 = 4,
    R7 = 5,
} digital_pin_t;

typedef enum {
    LB = 0,
    R8 = 1,
} freq_pin_t;

typedef enum {
    NONE = 0,   // Not used
    AIN  = 1,   // Analog in
    DIN  = 2,   // Digital in
    FIN  = 3,   // Frequency in
    DOUT = 4,   // Digital out
    POUT = 5,   // PWM out
} signal_type_t;

typedef struct {
    signal_type_t type;

    // PERIPHERY INFO
    uint8_t channel;    // ADC or PWM or Freq channel

    // CAN INFO
    uint8_t start;      // start bit
    uint8_t length;     // in bits

    // METADATA
    float factor; // (phys_range/can_scale)/adc_quants
    char name[16];
} can_signal_t;

typedef struct {
    uint16_t can_id;
    uint8_t dlc;
    int8_t num_signals;     // -1 => packet disabled
    uint16_t period;        // ms
    can_signal_t signals[9];
} can_pkt_t;

#define NUM_TX_PKT 4
#define ADQ (1<<12)

#ifdef SN_FRONT

static can_pkt_t CAN_SIGNAL_MAP[NUM_TX_PKT] = {
    {
        .can_id = 0x0D1, .dlc = 3, .num_signals = 7, .period = 100,  .signals = {
            { .type = DIN, .channel = R5, .start =  0, .length =  1, .factor = 1., .name = "LS L" },
            { .type = DIN, .channel = L9, .start =  1, .length =  1, .factor = 1., .name = "LS R" },
            { .type = DIN, .channel = LA, .start =  2, .length =  1, .factor = 1., .name = "SDC M pre BOTS" },
            { .type = DIN, .channel = LC, .start =  3, .length =  1, .factor = 1., .name = "SDC M post INS" },
            { .type = DIN, .channel = R7, .start =  4, .length =  1, .factor = 1., .name = "SDC M post BSPD" },

            { .type = AIN, .channel = R0, .start =  8, .length =  8, .factor = ((512./2)/ADQ), .name = "BDTS FL" },
            { .type = AIN, .channel = L8, .start = 16, .length =  8, .factor = ((512./2)/ADQ), .name = "BDTS FR" },
        }
    },
    {
        .can_id = 0x0D3, .dlc = 7, .num_signals = 6, .period = 10, .signals = {
            { .type = AIN, .channel = L1, .start =  0, .length =  8, .factor = (256./ADQ), .name = "APPS 1" },
            { .type = AIN, .channel = L2, .start =  8, .length =  8, .factor = (256./ADQ), .name = "APPS 2" },
            { .type = AIN, .channel = RA, .start = 16, .length =  8, .factor = ((512./2)/ADQ), .name = "BP F" },
            { .type = AIN, .channel = R9, .start = 24, .length = 12, .factor = 1., .name = "SAS" },
            { .type = FIN, .channel = R8, .start = 40, .length =  8, .factor = 1., .name = "WSS FL" },
            { .type = FIN, .channel = LB, .start = 48, .length =  8, .factor = 1., .name = "WSS FR" },
        }
    },
    {
        .can_id = 0x0D5, .dlc = 3, .num_signals = 2, .period = 10, .signals = {
            { .type = AIN, .channel = RC, .start =  0, .length = 12, .factor = 1., .name = "DS FL" },
            { .type = AIN, .channel = L4, .start = 12, .length = 12, .factor = 1., .name = "DS FR" },
        }
    },
    {
        .can_id = 0x0D7, .dlc = 3, .num_signals = 2, .period = 1, .signals = {
            { .type = AIN, .channel = RE, .start =  0, .length = 12, .factor = 1., .name = "SLS FL" },
            { .type = AIN, .channel = L6, .start = 12, .length = 12, .factor = 1., .name = "SLS FR" },
        }
    }
};

#endif

#ifdef SN_REAR

static can_pkt_t CAN_SIGNAL_MAP[NUM_TX_PKT] = {
    {
        .can_id = 0x0D2, .dlc = 7, .num_signals = 9, .period = 100,  .signals = {
            { .type = DIN, .channel = L9, .start =  0, .length =  1, .factor = 1., .name = "ExtTSOn" },
            { .type = DIN, .channel = LA, .start =  1, .length =  1, .factor = 1., .name = "SDC M pre TSMS" },
            { .type = DIN, .channel = LC, .start =  2, .length =  1, .factor = 1., .name = "SDC M post TSMS" },

            { .type = AIN, .channel = R0, .start =  8, .length =  8, .factor = ((512./2)/ADQ), .name = "BDTS RL" },
            { .type = AIN, .channel = L8, .start = 16, .length =  8, .factor = ((512./2)/ADQ), .name = "BDTS RR" },

            { .type = AIN, .channel = R9, .start = 24, .length =  8, .factor = (256./ADQ), .name = "WT BAT" },
            { .type = AIN, .channel = RB, .start = 32, .length =  8, .factor = (256./ADQ), .name = "WT DT" },
            { .type = AIN, .channel = RD, .start = 40, .length =  8, .factor = (256./ADQ), .name = "WP BAT" },
            { .type = AIN, .channel = RF, .start = 48, .length =  8, .factor = (256./ADQ), .name = "WP DT" },
        }
    },
    {
        .can_id = 0x0D4, .dlc = 8, .num_signals = 7, .period = 10, .signals = {
            { .type = AIN, .channel = L1, .start =  0, .length =  8, .factor = ((25.6/.1)/ADQ), .name = "EBS APS 1" },
            { .type = AIN, .channel = L2, .start =  8, .length =  8, .factor = ((25.6/.1)/ADQ), .name = "EBS APS 2" },
            { .type = AIN, .channel = RA, .start = 16, .length =  8, .factor = ((512./2)/ADQ), .name = "BP F" },
            { .type = FIN, .channel = R8, .start = 24, .length =  8, .factor = 1., .name = "WSS RL" },
            { .type = FIN, .channel = LB, .start = 32, .length =  8, .factor = 1., .name = "WSS RR" },
            { .type = AIN, .channel = RC, .start = 40, .length = 12, .factor = 1., .name = "DS RL" },
            { .type = AIN, .channel = L4, .start = 52, .length = 12, .factor = 1., .name = "DS RR" },
        }
    },
    {
        .can_id = 0x0D6, .dlc = 0, .num_signals = -1, .period = 10, .signals = {}
    },
    {
        .can_id = 0x0D8, .dlc = 3, .num_signals = 2, .period = 1, .signals = {
            { .type = AIN, .channel = RE, .start =  0, .length = 12, .factor = 1., .name = "SLS RL" },
            { .type = AIN, .channel = L6, .start = 12, .length = 12, .factor = 1., .name = "SLS RR" },
        }
    }
};

#define CAN_PWM_DC_ID 0x0DC
#define CAN_PWM_CONF_ID 0x0DD

#endif

/* user needs
TIM_HandleTypeDef* PWM_TIM_MAP[3] = {&htim1, &htim4, &htim3};
*/

typedef enum {
    PWM1 = 0, // TIM1
    PWM3 = 1, // TIM4
    PWM2 = 2, // TIM3
} pwm_tim_t; // Used as index for PWM_TIM_MAP

typedef struct {
    uint8_t tim;
    uint8_t ch;
} pwm_ch_t;

static pwm_ch_t PWM_CH_MAP[8] = {
    { .tim = PWM1, .ch = 0 }, // TIM1_CH1
    { .tim = PWM1, .ch = 1 }, // TIM1_CH2
    { .tim = PWM1, .ch = 2 }, // TIM1_CH3
    { .tim = PWM1, .ch = 3 }, // TIM1_CH4
    { .tim = PWM3, .ch = 0 }, // TIM4_CH1
    { .tim = PWM3, .ch = 1 }, // TIM4_CH2
    { .tim = PWM2, .ch = 1 }, // TIM3_CH2
    { .tim = PWM2, .ch = 3 }  // TIM3_CH4
};

#endif