#include <p24Hxxxx.h>
#include <timer.h>
#include <uart.h>
#include <pps.h>
#include <dma.h>

_FBS(RBS_NO_RAM & BSS_NO_FLASH & BWRP_WRPROTECT_OFF)
_FSS(RSS_NO_RAM & SSS_NO_FLASH & SWRP_WRPROTECT_OFF)
_FGS(GSS_OFF & GCP_OFF & GWRP_OFF)
_FOSCSEL(FNOSC_FRC & IESO_OFF)
_FOSC(FCKSM_CSDCMD & IOL1WAY_OFF & POSCMD_NONE)
_FWDT(FWDTEN_OFF & WINDIS_OFF)
_FPOR(ALTI2C_OFF & FPWRT_PWR1)
_FICD(JTAGEN_OFF & ICS_PGD1)

void UART1AndDMAInit(void);

volatile unsigned char flag = 0;
volatile unsigned char dma0_flag = 0;
char RXBufferA[5] __attribute__((space(dma)));
char RXBufferB[5] __attribute__((space(dma)));
char TXBuffer[5] __attribute__((space(dma)));

void __attribute__((interrupt, auto_psv)) _DMA0Interrupt(void)
{
    dma0_flag = 1;
    IFS0bits.DMA0IF = 0;
}
 
void __attribute__((interrupt, auto_psv)) _T1Interrupt(void)
{
    flag = ~flag;
    WriteTimer1(0);
    IFS0bits.T1IF = 0;
}

int main(void)
{
    unsigned char index;

    PORTB = 0;
    LATB = 0;
    TRISB = 0x7FFF;

    PPSUnLock;
    PPSInput(PPS_U1RX, PPS_RP11);
    PPSOutput(PPS_U1TX, PPS_RP10);
    PPSLock;

    UART1AndDMAInit();
    WriteTimer1(0);
    ConfigIntTimer1(T1_INT_PRIOR_1 & T1_INT_ON);
    OpenTimer1(T1_ON & T1_IDLE_STOP & T1_GATE_OFF & T1_PS_1_256 & T1_SYNC_EXT_OFF & T1_SOURCE_INT, 7200);

    while(1)
    {
        if(flag == 0)   LATBbits.LATB15 = 1;
        else LATBbits.LATB15 = 0;

        if(dma0_flag)
        {
            if(DMACS1bits.PPST0)
            {
                for(index = 0; index < 5; index++)    TXBuffer[index] = RXBufferB[index];
            }
            else
            {
                for(index = 0; index < 5; index++)    TXBuffer[index] = RXBufferA[index];
            }
            DMA1CONbits.CHEN = 1;
            DMA1REQbits.FORCE = 1;
            dma0_flag = 0;
        }
    }
    return 0;
}

void UART1AndDMAInit(void)
{
    #define RXDMAConfig (DMA0_MODULE_OFF & DMA0_SIZE_BYTE & PERIPHERAL_TO_DMA0 & DMA0_INTERRUPT_BLOCK & DMA0_NORMAL & DMA0_REGISTER_POST_INCREMENT & DMA0_CONTINUOUS_PING_PONG)
    #define TXDMAConfig (DMA1_MODULE_OFF & DMA1_SIZE_BYTE & DMA1_TO_PERIPHERAL & DMA1_INTERRUPT_BLOCK & DMA1_NORMAL & DMA1_REGISTER_POST_INCREMENT & DMA1_ONE_SHOT)
    #define BaudValue 23

    //DMA 0 csatorna konfiguralasa vetelhez
    DMA0CON = RXDMAConfig;
    DMA0CNT = 4;
    DMA0REQ = 0xB;
    DMA0PAD = (volatile unsigned int) &U1RXREG;
    DMA0STA = __builtin_dmaoffset(RXBufferA);
    DMA0STB = __builtin_dmaoffset(RXBufferB);
    IFS0bits.DMA0IF = 0;
    IEC0bits.DMA0IE = 1;
    DMA0CONbits.CHEN = 1;

    //DMA1 csatorna konfiguralasa adashoz
    DMA1CON = TXDMAConfig;
    DMA1CNT = 4;
    DMA1REQ = 0xC;
    DMA1PAD = (volatile unsigned int) &U1TXREG;
    DMA1STA = __builtin_dmaoffset(TXBuffer);

    //UART1 konfiguralasa
    U1MODEbits.UARTEN = 0;
    U1MODE = 0x0800;
    U1STA = 0x2400;
    U1BRG = BaudValue;
    U1MODEbits.UARTEN = 1;
    U1STAbits.UTXEN = 1;
}
