#include <stdio.h>
#include <stdlib.h>
#include <uart.h>
#include <i2c.h>
#include <spi.h>
#include "p33ep128gp504.h"
#include "sserial.h"

extern unsigned int DAC[6];
extern unsigned char ADC[2];
extern unsigned char INPUT[6];

typedef struct {
   unsigned char record_type;
   unsigned char data_size;
   unsigned char data_type; // 0x08 - s32, 0x06 - u32,
   unsigned char data_direction;
   float param_min;
   float param_max;
   unsigned short int param_addr;
   char unit_name_string[32];
} PTOC;

typedef struct {
    unsigned char record_type;
    unsigned char mode_index;
    unsigned char mode_type;
    unsigned char unused;
    char mode_name_string[16];
} MD;

int bytes2read1, bytes2read2;
unsigned char UART1_command, UART2_command;
unsigned char RX1_buf[16];
unsigned char RX2_buf[16];
char readDataSizeRX1, readDataSizeRX2;
int p_UART_RX1, p_UART_RX2;
int p_UART_TX1, p_UART_TX2;
unsigned char TX1_buf[16];
unsigned char TX2_buf[16];
int bytes2send1, bytes2send2;
int processU1, processU2;
char UART1_CRC, UART2_CRC;
unsigned char CRC1, CRC2;
char DAC_ready;
char readAddr1L, readAddr2L;
char readAddr1H, readAddr2H;
int readAddr1, readAddr2;
char LBP1_status, LBP2_status;
char remoteSWmode1, remoteSWmode2;
char commandTimeout1, commandTimeout2;
char dummy;
unsigned char OUTPUT[4];

//unsigned char outbyte1[4];
//unsigned char outbyte2[4];

#define CONFIG1

PTOC ptoc_rec1[32]  = {

#ifdef CONFIG1
			0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0000, "mV\x00" "ANOUT1",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0002, "mV\x00" "ANOUT2",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0004, "mV\x00" "ANOUT3",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0006, "mV\x00" "ANOUT4",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0008, "mV\x00" "ANOUT5",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x000A, "mV\x00" "ANOUT6",

                        0xa0, 8, 0x01, 0x00, 0.0f, 1.0f, 0x000C, "xxx\x00" "IN",

			0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x000D, "xxx\x00" "IN2D",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x000E, "xxx\x00" "IN2C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x000F, "xxx\x00" "IN2B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0010, "xxx\x00" "IN2A",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0011, "xxx\x00" "IN1A",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0012, "xxx\x00" "IN1B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0013, "xxx\x00" "IN1C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0014, "xxx\x00" "IN1D",

                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0015, "xxx\x00" "IN4D",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0016, "xxx\x00" "IN4C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0017, "xxx\x00" "IN4B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0018, "xxx\x00" "IN4A",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0019, "xxx\x00" "IN3A",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001A, "xxx\x00" "IN3B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001B, "xxx\x00" "IN3C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001C, "xxx\x00" "IN3D",

                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001D, "xxx\x00" "IN6D",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001E, "xxx\x00" "IN6C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x001F, "xxx\x00" "IN6B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0020, "xxx\x00" "INA6",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0021, "xxx\x00" "IN5A",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0022, "xxx\x00" "IN5B",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0023, "xxx\x00" "IN5C",
                        0xa0, 1, 0x01, 0x00, 0.0f, 1.0f, 0x0024, "xxx\x00" "IN5D",

                        0xa0, 13, 0x01, 0x00, 0.0f, 1.0f, 0x0025, "xxx\x00" "LIM"
#endif

#ifdef CONFIG2
			0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0000, "mV\x00" "ANOUT1",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0002, "mV\x00" "ANOUT2",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0004, "mV\x00" "ANOUT3",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0006, "mV\x00" "ANOUT4",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x0008, "mV\x00" "ANOUT5",
                        0xa0, 14, 0x03, 0x80, -10.0f, 10.0f, 0x000A, "mV\x00" "ANOUT6",

                        0xa0,  8, 0x01, 0x00, 0.0f, 1.0f, 0x000C, "xxx\x00" "IN",
			0xa0, 24, 0x01, 0x00, 0.0f, 1.0f, 0x000D, "xxx\x00" "IND",
                        0xa0, 13, 0x01, 0x00, 0.0f, 1.0f, 0x0024, "xxx\x00" "LIM"
#endif
                     };

MD md_rec1[2] = {0xb0, 0, 0x00, 0x00, "hw mode 0",
		 0xb0, 0, 0x01, 0x00, "sw mode 0"};

char PTOCtable1[70] =  {
#ifdef CONFIG1
                        0x00, 0x08,
                        0x2E, 0x08,
                        0x5C, 0x08,
                        0x8A, 0x08,
                        0xB8, 0x08,
                        0xE6, 0x08,

                        0x14, 0x09,

                        0x42, 0x09,
                        0x70, 0x09,
                        0x9E, 0x09,
                        0xCC, 0x09,
                        0xFA, 0x09,
                        0x28, 0x0A,
                        0x56, 0x0A,
                        0x84, 0x0A,

                        0xB2, 0x0A,
                        0xE0, 0x0A,
                        0x0E, 0x0B,
                        0x3C, 0x0B,
                        0x6A, 0x0B,
                        0x98, 0x0B,
                        0xC6, 0x0B,
                        0xF4, 0x0B,

                        0x22, 0x0C,
                        0x50, 0x0C,
                        0x7E, 0x0C,
                        0xAC, 0x0C,
                        0xDA, 0x0C,
                        0x08, 0x0D,
                        0x36, 0x0D,
                        0x64, 0x0D,

                        0x92, 0x0D,
#endif


#ifdef CONFIG2
                        0x00, 0x08,
                        0x2E, 0x08,
                        0x5C, 0x08,
                        0x8A, 0x08,
                        0xB8, 0x08,
                        0xE6, 0x08,

                        0x14, 0x09,
                        0x42, 0x09,
                        0x70, 0x09,
#endif

/*
                        0xC0, 0x0D,
                        0xEE, 0x0D,
                        0x1C, 0x0E,
                        0x4A, 0x0E,
                        0x78, 0x0E,
                        0xA6, 0x0E,
                        0xD4, 0x0E,
                        0x02, 0x0F,

                        0x30, 0x0F,
                        0x5E, 0x0F,
                        0x8C, 0x0F,
                        0xBA, 0x0F,
                        0xE8, 0x0F,
                        0x16, 0x10,
                        0x44, 0x10,
                        0x72, 0x10,

                        0xA0, 0x10,
                        0xCE, 0x10,
                        0xFC, 0x10,
*/
                        0x00, 0x20,
                        0x14, 0x20,
                        0x00, 0x00};


PTOC ptoc_rec2[27]  = {
                        // 24 + 8 + 13 + 16 in	24 + 8 / 13 + 16 = 32 / 29
                        // 18 + 5 + 144 out	24 + 24 + 24 + 12 / 24 + 24 + 24 + 6 + 5  = 84 / 83
                        // 51 zaznamu

#ifdef CONFIG1
                        0xa0, 5, 0x01, 0x80, 0.0f, 1.0f, 0x0000, "xxx\x00" "OUT",

                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0001, "xxx\x00" "OUT2B",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0002, "xxx\x00" "OUT2A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0003, "xxx\x00" "OUT2C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0004, "xxx\x00" "EN2",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0005, "xxx\x00" "EN1",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0006, "xxx\x00" "OUT1C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0007, "xxx\x00" "OUT1A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0008, "xxx\x00" "OUT1B",

                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0009, "xxx\x00" "OUT4B",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000A, "xxx\x00" "OUT4A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000B, "xxx\x00" "OUT4C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000C, "xxx\x00" "EN4",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000D, "xxx\x00" "EN3",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000E, "xxx\x00" "OUT3C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x000F, "xxx\x00" "OUT3A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0010, "xxx\x00" "OUT3B",

                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0011, "xxx\x00" "OUT6B",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0012, "xxx\x00" "OUT6A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0013, "xxx\x00" "OUT6C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0014, "xxx\x00" "EN6",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0015, "xxx\x00" "EN5",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0016, "xxx\x00" "OUT5C",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0017, "xxx\x00" "OUT5A",
                        0xa0, 1, 0x01, 0x80, 0.0f, 1.0f, 0x0018, "xxx\x00" "OUT5B",

                        0xa0, 8, 0x02, 0x00, 0.0f, 19.8f, 0x0019, "mV\x00" "ANIN1",
                        0xa0, 8, 0x02, 0x00, 0.0f, 19.8f, 0x001A, "mV\x00" "ANIN2"
#endif

#ifdef CONFIG2
                        0xa0, 5, 0x01, 0x80, 0.0f, 1.0f, 0x0000, "xxx\x00" "OUT",

                        0xa0, 6, 0x01, 0x80, 0.0f, 1.0f, 0x0001, "xxx\x00" "EN",
                        0xa0, 18, 0x01, 0x80, 0.0f, 1.0f, 0x0002, "xxx\x00" "OUTD",

                        0xa0, 8, 0x03, 0x00, -129.0f, 127.0f, 0x0019, "mV\x00" "ANIN1",
                        0xa0, 8, 0x03, 0x00, -129.0f, 127.0f, 0x001A, "mV\x00" "ANIN2"
#endif

                        /*
                            0 - LIM 8..12 (3..7)
                            1 - LIM 0..7
                            2 - IN 1/2
                            3 - IN 3/4
                            4 - IN 5/6
                            5 - IN 0..7
                        */
                     };

MD md_rec2[2] = {0xb0, 0, 0x00, 0x00, "hw mode 0",
		0xb0, 0, 0x01, 0x00, "sw mode 0"};

char PTOCtable2[108] = {0x00, 0x08,

#ifdef CONFIG1
                        0x2E, 0x08,
                        0x5C, 0x08,
                        0x8A, 0x08,
                        0xB8, 0x08,
                        0xE6, 0x08,
                        0x14, 0x09,
                        0x42, 0x09,
                        0x70, 0x09,

                        0x9E, 0x09,
                        0xCC, 0x09,
                        0xFA, 0x09,
                        0x28, 0x0A,
                        0x56, 0x0A,
                        0x84, 0x0A,
                        0xB2, 0x0A,
                        0xE0, 0x0A,

                        0x0E, 0x0B,
                        0x3C, 0x0B,
                        0x6A, 0x0B,
                        0x98, 0x0B,
                        0xC6, 0x0B,
                        0xF4, 0x0B,
                        0x22, 0x0C,
                        0x50, 0x0C,

                        0x7E, 0x0C,
                        0xAC, 0x0C,
#endif

#ifdef CONFIG2
                        0x2E, 0x08,
                        0x5C, 0x08,
                        0x8A, 0x08,
                        0xB8, 0x08,
                        0xE6, 0x08,
#endif

/*
                        0xDA, 0x0C,
                        0x08, 0x0D,
                        0x36, 0x0D,
                        0x64, 0x0D,
                        0x92, 0x0D,

                        0xC0, 0x0D,
                        0xEE, 0x0D,
                        0x1C, 0x0E,
                        0x4A, 0x0E,
                        0x78, 0x0E,
                        0xA6, 0x0E,
                        0xD4, 0x0E,
                        0x02, 0x0F,

                        0x30, 0x0F,
                        0x5E, 0x0F,
                        0x8C, 0x0F,
                        0xBA, 0x0F,
                        0xE8, 0x0F,
                        0x16, 0x10,
                        0x44, 0x10,
                        0x72, 0x10,

                        0xA0, 0x10,
                        0xCE, 0x10,
                        0xFC, 0x10,
                        */

                        0x00, 0x20,
                        0x14, 0x20,
                        0x00, 0x00};


void __attribute__ ((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
    int i;

    IFS0bits.U1RXIF = 0; // Clear interrupt flag before returning

    if (bytes2read1 == 0xFF) {
        // prvni byte
        UART1_command = ReadUART1();

       /*
       rxtest[pRXtest] = UART1_command;
       if (pRXtest < 4095) pRXtest++;
       else pRXtest = 0;
       */

        p_UART_RX1 = 1;
        p_UART_TX1 = 1;
        if (UART1_command == 0xBD) {
            // RPC
            bytes2read1 = 12;
        }
        else {
            if ((UART1_command & 0xE0) == 0x40) {
                // data read
                if ((UART1_command & 0x04) == 0x04) {
                    // 2 byte address
                    bytes2read1 = 3;
                }
                else {
                    // current address
                     bytes2read1 = 1;
                }
            }
            else {
                if ((UART1_command & 0xF0) == 0x0110) {
                // data write

                }
                else {
                    switch (UART1_command) {
                        case 0xBB:
                        case 0xBC:
                        case 0xC1:
                        case 0xC7:
                        case 0xD0:
                        case 0xD1:
                        case 0xD2:
                        case 0xD3:
                        case 0xD4:
                        case 0xD5:
                        case 0xD6:
                        case 0xD7:
                        case 0xDF: 	bytes2read1 = 1;
                                        break;
                        case 0xE1:
                        case 0xE6:
                        case 0xE7:
                        case 0xEB:	bytes2read1 = 2;
                                        break;
                        default :	bytes2read1 = 0xFF;
                                        break;
                    }
                }
            }
        }
    }
    else {
        // dalsi byte
        RX1_buf[p_UART_RX1] = ReadUART1();

        /*
        rxtest[pRXtest] = RX1_buf[p_UART_RX1];
        if (pRXtest < 4095) pRXtest++;
        else pRXtest = 0;
        */

        bytes2read1--;
        if (bytes2read1 == 0) {
            bytes2read1 = 0xFF;
            // posledni byte, zpracujeme povel
            processU1 = 1;

        }
        else {
            p_UART_RX1++;
        }
    }
}


void __attribute__ ((interrupt, no_auto_psv)) _U2RXInterrupt(void)
{
    int i;

    IFS1bits.U2RXIF = 0; // Clear interrupt flag before returning

    if (bytes2read2 == 0xFF) {
        // prvni byte
        UART2_command = ReadUART2();
        /*
        txtest[pTXtest] = UART2_command;
        if (pTXtest < 511) pTXtest++;
        */
        p_UART_RX2 = 1;
        p_UART_TX2 = 1;
        if (UART2_command == 0xBD) {
            // RPC
            bytes2read2 = 5;
        }
        else {
            if ((UART2_command & 0xE0) == 0x40) {
                // data read
                if ((UART2_command & 0x04) == 0x04) {
                    // 2 byte address
                    bytes2read2 = 3;
                }
                else {
                    // current address
                     bytes2read2 = 1;
                }
            }
            else {
                if ((UART2_command & 0xF0) == 0x0110) {
                // data write

                }
                else {
                    switch (UART2_command) {
                        case 0xBB:
                        case 0xBC:
                        case 0xC1:
                        case 0xC7:
                        case 0xD0:
                        case 0xD1:
                        case 0xD2:
                        case 0xD3:
                        case 0xD4:
                        case 0xD5:
                        case 0xD6:
                        case 0xD7:
                        case 0xDF: 	bytes2read2 = 1;
                                        break;
                        case 0xE1:
                        case 0xE6:
                        case 0xE7:
                        case 0xEB:	bytes2read2 = 2;
                                        break;
                        default :	bytes2read2 = 0xFF;
                                        break;
                    }
                }
            }
        }
    }
    else {
        // dalsi byte
        RX2_buf[p_UART_RX2] = ReadUART2();
        /*
        txtest[pTXtest] = RX2_buf[p_UART_RX2];
        if (pTXtest < 511) pTXtest++;
        */
        bytes2read2--;
        if (bytes2read2 == 0) {
            bytes2read2 = 0xFF;
            // posledni byte, zpracujeme povel
            processU2 = 1;
        }
        else {
            p_UART_RX2++;
        }
    }
}

void __attribute__ ((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
    IFS0bits.U1TXIF = 0; // Clear interrupt flag before returning

    if (bytes2send1 > 0) {
        WriteUART1(TX1_buf[p_UART_TX1]);

        /*
        txtest[pTXtest] = UART2_command;
        if (pTXtest < 4095) pTXtest++;
        else pTXtest = 0;
        */
        bytes2send1--;
        p_UART_TX1++;
    }
}

void __attribute__ ((interrupt, no_auto_psv)) _U2TXInterrupt(void)
{
    IFS1bits.U2TXIF = 0; // Clear interrupt flag before returning

    if (bytes2send2 > 0) {
        WriteUART2(TX2_buf[p_UART_TX2]);
        /*
        rxtest[pRXtest] = TX2_buf[p_UART_TX2];
        if (pRXtest < 511) pRXtest++;
        */
        bytes2send2--;
        p_UART_TX2++;
    }
}

void ZpracujU1(void)
{
    int i;

    if (UART1_command == 0xBD) {
        // RPC
        DAC[0] = (RX1_buf[1] << 8) | (RX1_buf[2] & 0xFC);
        DAC[1] = (RX1_buf[2] << 14) | (RX1_buf[3] << 6) | ((RX1_buf[4] >> 2) & 0xFC);
        DAC[2] = (RX1_buf[4] << 12) | (RX1_buf[5] << 4) | ((RX1_buf[6] >> 4) & 0xFC);
        DAC[3] = (RX1_buf[6] << 10) | (RX1_buf[7] << 2);
        DAC[4] = (RX1_buf[8] << 8) | (RX1_buf[9] & 0xFC);
        DAC[5] = (RX1_buf[9] << 14) | (RX1_buf[10] << 6) | ((RX1_buf[11] >> 2) & 0xFC);
        UART1_CRC = RX1_buf[12];

        TX1_buf[0] = 0x00;
        TX1_buf[7] = CalcCRC(TX1_buf[0], 0);
        TX1_buf[1] = INPUT[5];
        TX1_buf[7] = CalcCRC(TX1_buf[1], TX1_buf[7]);
        TX1_buf[2] = INPUT[2];
        TX1_buf[7] = CalcCRC(TX1_buf[2], TX1_buf[7]);
        TX1_buf[3] = INPUT[3];
        TX1_buf[7] = CalcCRC(TX1_buf[3], TX1_buf[7]);
        TX1_buf[4] = INPUT[4];
        TX1_buf[7] = CalcCRC(TX1_buf[4], TX1_buf[7]);
        TX1_buf[5] = INPUT[1];
        TX1_buf[7] = CalcCRC(TX1_buf[5], TX1_buf[7]);
        TX1_buf[6] = INPUT[0];
        TX1_buf[7] = CalcCRC(TX1_buf[6], TX1_buf[7]);
        bytes2send1 = 7;
        WriteUART1(TX1_buf[0]);

        DAC_ready = DAC_ready | 0x01;

        /*
        txtest[pTXtest] = TX1_buf[0];
        if (pTXtest < 4095) pTXtest++;
        else pTXtest = 0;
        */
    }
    else {
        // ostani povely
        if ((UART1_command & 0xE0) == 0x40) {
            // data read
            if ((UART1_command & 0x04) == 0x04) {
                // 2 byte address
                readAddr1L = RX1_buf[1];
                readAddr1H = RX1_buf[2];
                UART1_CRC = RX1_buf[3];
            }
            else {
                // current address
                UART1_CRC = RX1_buf[1];
            }
            switch (UART1_command & 0x03) {
                case 0x00:  readDataSizeRX1 = 1;
                            break;
                case 0x01:  readDataSizeRX1 = 2;
                            break;
                case 0x10:  readDataSizeRX1 = 4;
                            break;
                case 0x11:  readDataSizeRX1 = 8;
                            break;
                default:    break;
            }
            switch (readAddr1H) {
                case 0x01:  // PTOC table
                            TX1_buf[0] = PTOCtable1[readAddr1L];
                            TX1_buf[1] = PTOCtable1[readAddr1L + 1];
                            TX1_buf[2] = CalcCRC(TX1_buf[0], 0);
                            TX1_buf[2] = CalcCRC(TX1_buf[1], TX1_buf[2]);
                            bytes2send1 = 2;
                            WriteUART1(TX1_buf[0]);
                            if ((UART1_command & 0x08) == 0x08) readAddr1L++;
                            break;
                case 0x08:  // PDD read - Process data descriptor
                case 0x09:
                case 0x0A:
                case 0x0B:
                case 0x0C:
                case 0x0D:
                case 0x0E:
                case 0x0F:
                case 0x10:
                case 0x11:
                case 0x12:
                            CRC1 = 0;
                            readAddr1 = (((readAddr1H & 0x00FF) << 8) | (readAddr1L & 0x00FF)) - 0x0800;
                            for (i = 0; i < readDataSizeRX1; i++) {
                                TX1_buf[i] =  *((char*)&ptoc_rec1[0] + readAddr1 + i);
                                CRC1 = CalcCRC(TX1_buf[i], CRC1);
                            }
                            TX1_buf[readDataSizeRX1] = CRC1;
                            bytes2send1 = readDataSizeRX1;
                            WriteUART1(TX1_buf[0]);
                            /*
                            rxtest[pRXtest] = TX1_buf[0];
                            if (pRXtest < 4095) pRXtest++;
                            */
                            if ((UART1_command & 0x08) == 0x08) readAddr1L = readAddr1L + readDataSizeRX1;
                            break;
                case 0x20:  // MD read - Mode descriptor
                            CRC1 = 0;
                            readAddr1 = (((readAddr1H & 0x00FF) << 8) | (readAddr1L & 0x00FF)) - 0x2000;
                            for (i = 0; i < readDataSizeRX1; i++) {
                                    TX1_buf[i] =  *((char*)&md_rec1[0] + readAddr1 + i);
                                    CRC1 = CalcCRC(TX1_buf[i], CRC1);
                            }
                            TX1_buf[readDataSizeRX1] = CRC1;
                            bytes2send1 = readDataSizeRX1;
                            WriteUART1(TX1_buf[0]);
                            if ((UART1_command & 0x08) == 0x08) readAddr1L = readAddr1L + readDataSizeRX1;
                            break;
                default:    break;
            }

        }
        else {
            if ((UART1_command & 0xF0) == 0x0110) {
            // data write

            }
            else {
                switch (UART1_command) {
                    case 0xBB:	// RPC command "GetDiscoveryInfo"
                                // return 6 bytes + CRC
                                UART1_CRC = RX1_buf[1];
                                // number of bytes in
                                TX1_buf[0] = 0x07;
                                // number of bytes out
                                TX1_buf[1] = 0x0B;
                                // PTOC address
                                TX1_buf[2] = 0x00;
                                TX1_buf[3] = 0x01;
                                // GTOC address
                                TX1_buf[4] = 0x00;
                                TX1_buf[5] = 0x00;
                                TX1_buf[6] = 0x5E;   // CRC
                                bytes2send1 = 6;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xBC:	// RPC command "GetUnitNumber"
                                // return 4 bytes + CRC
                                UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = '0';
                                TX1_buf[1] = '0';
                                TX1_buf[2] = '0';
                                TX1_buf[3] = '3';
                                TX1_buf[4] = 0xE7;
                                bytes2send1 = 4;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xC1:	// get LBP status
                                UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = LBP1_status;
                                TX1_buf[1] = 0x00;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xC7:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 0x00;
                                TX1_buf[1] = 0x00;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD0:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = '7';
                                TX1_buf[1] = 0x3D;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD1:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 'm';
                                TX1_buf[1] = 0x98;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD2:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = '8';
                                TX1_buf[1] = 0x7C;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD3:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = '4';
                                TX1_buf[1] = 0xDF;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD4:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 'R';
                                TX1_buf[1] = 0x67;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD5:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 'O';
                                TX1_buf[1] = 0x07;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD6:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 'B';
                                TX1_buf[1] = 0xFA;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xD7:	UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 0x00;
                                TX1_buf[1] = 0x00;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xDF: 	// return cookie
                                UART1_CRC = RX1_buf[1];
                                TX1_buf[0] = 0x5A;
                                TX1_buf[1] = 0xA5;
                                bytes2send1 = 1;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xE1:	// set LBP status
                                LBP1_status = RX1_buf[1];
                                UART1_CRC = RX1_buf[2];
                                TX1_buf[0] = 0x00;
                                bytes2send1 = 0;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xE6:	// set remote SW mode
                                remoteSWmode1 = RX1_buf[1];
                                UART1_CRC = RX1_buf[2];
                                TX1_buf[0] = 0x00;
                                bytes2send1 = 0;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xE7:	//
                                dummy = RX1_buf[1];
                                UART1_CRC = RX1_buf[2];
                                TX1_buf[0] = 0x00;
                                bytes2send1 = 0;
                                WriteUART1(TX1_buf[0]);
                                break;
                    case 0xEB:	// set command timeout
                                commandTimeout1 = RX1_buf[1];
                                UART1_CRC = RX1_buf[2];
                                TX1_buf[0] = 0x00;
                                bytes2send1 = 0;
                                WriteUART1(TX1_buf[0]);
                                break;
                    default :	break;
                }
            }
        }
    }
    processU1 = 0;
}


void ZpracujU2(void)
{
    int i;

    if (UART2_command == 0xBD) {
        // RPC
        OUTPUT[0] = OUTPUT[0] | (RX2_buf[1] & 0xF8); // out
        OUTPUT[1] = RX2_buf[2]; // out 2/1
        OUTPUT[2] = RX2_buf[3]; // out 4/3
        OUTPUT[3] = RX2_buf[4]; // out 6/5
        UART2_CRC = RX2_buf[5];

        TX2_buf[0] = 0x00;
        TX2_buf[3] = CalcCRC(TX2_buf[0], 0);
        TX2_buf[1] = ADC[0];
        TX2_buf[3] = CalcCRC(TX2_buf[1], TX2_buf[3]);
        TX2_buf[2] = ADC[1];
        TX2_buf[3] = CalcCRC(TX2_buf[2], TX2_buf[3]);
        bytes2send2 = 3;
        WriteUART2(TX2_buf[0]);




        DAC_ready = DAC_ready | 0x02;
    }
    else {
        // ostani povely
        if ((UART2_command & 0xE0) == 0x40) {
            // data read
            if ((UART2_command & 0x04) == 0x04) {
                // 2 byte address
                readAddr2L = RX2_buf[1];
                readAddr2H = RX2_buf[2];
                UART2_CRC = RX2_buf[3];
            }
            else {
                // current address
                UART2_CRC = RX2_buf[1];
            }
            switch (UART2_command & 0x03) {
                case 0x00:  readDataSizeRX2 = 1;
                            break;
                case 0x01:  readDataSizeRX2 = 2;
                            break;
                case 0x10:  readDataSizeRX2 = 4;
                            break;
                case 0x11:  readDataSizeRX2 = 8;
                            break;
                default:    break;
            }
            switch (readAddr2H) {
                case 0x01:  // PTOC table
                            TX2_buf[0] = PTOCtable2[readAddr2L];
                            TX2_buf[1] = PTOCtable2[readAddr2L + 1];
                            TX2_buf[2] = CalcCRC(TX2_buf[0], 0);
                            TX2_buf[2] = CalcCRC(TX2_buf[1], TX2_buf[2]);
                            bytes2send2 = 2;
                            WriteUART2(TX2_buf[0]);
                            if ((UART2_command & 0x08) == 0x08) readAddr2L++;
                            break;
                case 0x08:  // PDD read - Process data descriptor
                case 0x09:
                case 0x0A:
                case 0x0B:
                case 0x0C:
                case 0x0D:
                case 0x0E:
                case 0x0F:
                case 0x10:
                case 0x11:
                case 0x12:
                            CRC2 = 0;
                            readAddr2 = (((readAddr2H & 0x00FF) << 8) | (readAddr2L & 0x00FF)) - 0x0800;
                            for (i = 0; i < readDataSizeRX2; i++) {
                                TX2_buf[i] =  *((char*)&ptoc_rec2[0] + readAddr2 + i);
                                CRC2 = CalcCRC(TX2_buf[i], CRC2);
                            }
                            TX2_buf[readDataSizeRX2] = CRC2;
                            bytes2send2 = readDataSizeRX2;
                            WriteUART2(TX2_buf[0]);
                            if ((UART2_command & 0x08) == 0x08) readAddr2L = readAddr2L + readDataSizeRX2;
                            break;
                case 0x20:  // MD read - Mode descriptor
                            CRC2 = 0;
                            readAddr2 = ((readAddr2H << 8) | readAddr2L) - 0x2000;
                            for (i = 0; i < readDataSizeRX2; i++) {
                                    TX2_buf[i] =  *((char*)&md_rec2[0] + readAddr2 + i);
                                    CRC2 = CalcCRC(TX2_buf[i], CRC2);
                            }
                            TX2_buf[readDataSizeRX2] = CRC2;
                            bytes2send2 = readDataSizeRX2;
                            WriteUART2(TX2_buf[0]);
                            if ((UART2_command & 0x08) == 0x08) readAddr2L = readAddr2L + readDataSizeRX2;
                            break;
                default:    break;
            }

        }
        else {
            if ((UART2_command & 0xF0) == 0x0110) {
            // data write

            }
            else {
                switch (UART2_command) {
                    case 0xBB:	// RPC command "GetDiscoveryInfo"
                                // return 6 bytes + CRC
                                UART2_CRC = RX2_buf[1];
                                // number of bytes in
                                TX2_buf[0] = 0x03;
                                // number of bytes out
                                TX2_buf[1] = 0x04;
                                // PTOC address
                                TX2_buf[2] = 0x00;
                                TX2_buf[3] = 0x01;
                                // GTOC address
                                TX2_buf[4] = 0x00;
                                TX2_buf[5] = 0x00;
                                TX2_buf[6] = 0xED;
                                bytes2send2 = 6;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xBC:	// RPC command "GetUnitNumber"
                                // return 4 bytes + CRC
                                UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = '0';
                                TX2_buf[1] = '0';
                                TX2_buf[2] = '0';
                                TX2_buf[3] = '3';
                                TX2_buf[4] = 0xE7;
                                bytes2send2 = 4;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xC1:	// get LBP status
                                UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = LBP2_status;
                                TX2_buf[1] = 0x00;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xC7:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 0x00;
                                TX2_buf[1] = 0x00;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD0:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = '7';
                                TX2_buf[1] = 0x3D;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD1:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 'm';
                                TX2_buf[1] = 0x98;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD2:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = '8';
                                TX2_buf[1] = 0x7C;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD3:	UART2_CRC = RX2_buf[1];
                                /*
                                TX2_buf[0] = '5';
                                TX2_buf[1] = 0x81;
                                */
                                TX2_buf[0] = '4';
                                TX2_buf[1] = 0xDF;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD4:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 'R';
                                TX2_buf[1] = 0x67;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD5:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 'O';
                                TX2_buf[1] = 0x07;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD6:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 'B';
                                TX2_buf[1] = 0xFA;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xD7:	UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 0x00;
                                TX2_buf[1] = 0x00;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xDF: 	// return cookie
                                UART2_CRC = RX2_buf[1];
                                TX2_buf[0] = 0x5A;
                                TX2_buf[1] = 0xA5;
                                bytes2send2 = 1;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xE1:	// set LBP status
                                LBP2_status = RX2_buf[1];
                                UART2_CRC = RX2_buf[2];
                                TX2_buf[0] = 0x00;
                                bytes2send2 = 0;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xE6:	// set remote SW mode
                                remoteSWmode2 = RX2_buf[1];
                                UART2_CRC = RX2_buf[2];
                                TX2_buf[0] = 0x00;
                                bytes2send2 = 0;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xE7:	//
                                dummy = RX2_buf[1];
                                UART2_CRC = RX2_buf[2];
                                TX2_buf[0] = 0x00;
                                bytes2send2 = 0;
                                WriteUART2(TX2_buf[0]);
                                break;
                    case 0xEB:	// set command timeout
                                commandTimeout2 = RX2_buf[1];
                                UART2_CRC = RX2_buf[2];
                                TX2_buf[0] = 0x00;
                                bytes2send2 = 0;
                                WriteUART2(TX2_buf[0]);
                                break;
                    default :	break;
                }
            }
        }
    }
    processU2 = 0;
}

void InitUARTs(void)
{
    OpenUART1(UART_EN & UART_IDLE_STOP & UART_IrDA_DISABLE & UART_UEN_00
              & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD
              & UART_NO_PAR_8BIT & UART_BRGH_FOUR & UART_1STOPBIT
              & UART_UXRX_IDLE_ONE & UART_MODE_SIMPLEX,
              UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED & UART_TX_ENABLE
              & UART_INT_RX_CHAR & UART_INT_TX_BUF_EMPTY & UART_ADR_DETECT_DIS,
              5);   // 129
    OpenUART2(UART_EN & UART_IDLE_STOP & UART_IrDA_DISABLE & UART_UEN_00
              & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD
              & UART_NO_PAR_8BIT & UART_BRGH_FOUR & UART_1STOPBIT
              & UART_UXRX_IDLE_ONE & UART_MODE_SIMPLEX,
              UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED & UART_TX_ENABLE
              & UART_INT_RX_CHAR & UART_INT_TX_BUF_EMPTY & UART_ADR_DETECT_DIS,
              5);   // 129


    EnableIntU1RX;
    EnableIntU1TX;
    EnableIntU2RX;
    EnableIntU2TX;
    SetPriorityIntU1RX(2);
    SetPriorityIntU1TX(2);
    SetPriorityIntU2RX(3);
    SetPriorityIntU2TX(3);
    bytes2read1 = 0xFF;
    bytes2read2 = 0xFF;
    processU1 = 0;
    processU2 = 0;
    DAC_ready = 0;    
}
