/****************************************************************************
* Copyright (C) 2016-2022 Philipp Gahtow
*
* DCC Waveform Timer Configuration
*
* DCC Master Interface can generate DCC Signal
* either with Timer1 (16-bit) or with Timer2 (8-bit) by default!
* for ARM on Arduino DUE with TC3 = Timer4 (TC1 Channel 0)
* for ESP8266 with Timer1
* for ESP32 with Timer1
****************************************************************************/

#define PREAMBLE_LENGTH 16  //1's for the preamble (NMRA mind. 10x, normal: 12x plus RailCom cutout)
#define ADD_LONG_PREAMBLE_LENGTH 8  //additional length for Service Mode Packet
#define RAILCOM_CUTOUT_LENGTH 4   //length the preamble will be cut out when railcom data will transmit

//--------------------------------------------------------------------------------------
/*
NEM 670 – Ausgabe 2013:
Dauer des Teil-Einsbits: t = 58 µs & zulässige Toleranzen +/- 3 µs am Gleis
Dauer des Teil-Nullbits: t ≥ 100 µs, normal: 116µs
*/
/******************************************/
#if defined(__AVR__)
//CONTROL What Timer we should use:
//#define DCC_USE_TIMER1  //USE 16-bit TIMER1
#undef DCC_USE_TIMER1   //USE 8-bit TIMER2
#endif

/******************************************/
//DCC truth table:

//OFF:
#if defined(__AVR__)
#define DCC_OUTPUT1_OFF()       {*d1reg &= ~d1bit;}   //LOW
#endif
#define DCC_OUTPUT1_OFF_legacy    LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_OFF()       {*d2reg &= ~d2bit;}   //LOW
#endif
#define DCC_OUTPUT2_OFF_legacy    LOW

//RailCom:
#if defined(__AVR__)
#define DCC_OUTPUT1_RC()      {*d1reg &= ~d1bit;}    //LOW
#endif
#define DCC_OUTPUT1_RC_legacy   LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_RC()      {*d2reg &= ~d2bit;}   //LOW
#endif
#define DCC_OUTPUT2_RC_legacy   LOW

//DCC LOW:
#if defined(__AVR__)
#define DCC_OUTPUT1_LOW()       {*d1reg &= ~d1bit;}   //LOW
#endif
#define DCC_OUTPUT1_LOW_legacy    LOW
#if defined(__AVR__)
#define DCC_OUTPUT2_LOW()       {*d2reg |= d2bit;}   //HIGH
#endif
#define DCC_OUTPUT2_LOW_legacy    HIGH

//DCC HIGH:
#if defined(__AVR__)
#define DCC_OUTPUT1_HIGH()      {*d1reg |= d1bit;}   //HIGH
#endif
#define DCC_OUTPUT1_HIGH_legacy   HIGH
#if defined(__AVR__)
#define DCC_OUTPUT2_HIGH()      {*d2reg &= ~d2bit;}  //LOW
#endif
#define DCC_OUTPUT2_HIGH_legacy   LOW

/******************************************/
//USE the Timer1 for the DCC Signal generation on AVR
#if defined(DCC_USE_TIMER1)
#undef DCC_USE_TIMER2

#define half_one_count 57  //29usec pulse
#define one_count 115 //58us = 115
#define zero_high_count 199 //100us = 199 !old: 116us = 228
#define zero_low_count 199  //100us

#define DCC_TMR_SIGNAL         TIMER1_COMPA_vect
#define DCC_INIT_COMPARATOR    TCCR1A
#define DCC_TMR_CONTROL_REG    TCCR1B
//turn on CTC mode in WGM12 and set CS11 for 8 prescaler in TCCR1B
#define DCC_TMR_CONTROL_SET()  {DCC_TMR_CONTROL_REG = 1 << WGM12 | 1 << CS11;}
#define DCC_TMR_COUNT_REG    TCNT1
#define DCC_TMR_MATCH_INT()    {TIMSK1 |= (1 << OCIE1A);} //Compare Match Interrupt Enable
#define DCC_TMR_OUTP_CAPT_REG  OCR1A

#define DCC_TMR_OUTP_ONE_HALF()  {OCR1A = OCR1B = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {OCR1A = OCR1B = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {OCR1A = OCR1B = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW()  {OCR1A = OCR1B = zero_low_count;}

/******************************************/
//USE the Timer2 for the DCC Signal generation on AVR
#else
#define DCC_USE_TIMER2

#define half_one_count 198  //29usec pulse
#define one_count 141  //58usec pulse length = 141 = 0x8D
#define zero_high_count 56  //100us = 56    !old: 116us = 0x1B (27) pulse length
#define zero_low_count 56  //100us

#define DCC_TMR_SIGNAL         TIMER2_OVF_vect
#define DCC_INIT_COMPARATOR    TCCR2A
#define DCC_TMR_CONTROL_REG    TCCR2B
//Timer2 Settings: Timer Prescaler /8, mode 0
//Timmer clock = 16MHz/8 = 2MHz oder 0,5usec
#define DCC_TMR_CONTROL_SET()  {DCC_TMR_CONTROL_REG = 0 << CS22 | 1 << CS21 | 0 << CS20;}
#define DCC_TMR_COUNT_REG    TCNT2
#define DCC_TMR_MATCH_INT()    {TIMSK2 = 1 << TOIE2;} //Overflow Interrupt Enable

//note that there is a latency so take the last time of Timer2 also:
#define DCC_TMR_OUTP_ONE_HALF()  {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + half_one_count; last_timer = half_one_count;}
#define DCC_TMR_OUTP_ONE_COUNT() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + one_count; last_timer = one_count;}
#define DCC_TMR_OUTP_ZERO_HIGH() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + zero_high_count; last_timer = zero_high_count;}
#define DCC_TMR_OUTP_ZERO_LOW() {DCC_TMR_COUNT_REG = DCC_TMR_COUNT_REG + zero_low_count; last_timer = zero_low_count;}

/******************************************/
#endif
