byte can_tx_data[8];
byte can_rx_data[8];
dword can_rx_id;
byte can_rx_len;
byte can_mode;
byte can_missing_rx;
byte tx_result;

proc can_io_init()
{
    PORTB |= (1<<3);        //CS_H;
    PORTA |= (1<<1);        //WR_H;
    PORTB |= (1<<6);        //RD_H;
    PORTB &= (1<<5)^255;    //ALE_L;
    PWM0 = (16000000<<7)|64;
}

proc can_wr_reg(adr,value)
{
    var dummy;
    PORTB |= (1<<6)|(1<<5);         // RD_H, ALE_H
    PORTE = adr;
    PORTB &= ((1<<5)|(1<<3))^255;   // ALE_L,CS_L    
    PORTA &= (1<<1)^255;            // WR_L    
    PORTE = value; 
    PORTA |= (1<<1);                // WR_H
    PORTB |= (1<<3);                // CS_H
}


proc can_rd_reg(adr)
{
    var value;

    PORTA |= (1<<1);                // WR_H
    PORTB |= (1<<5);                // ALE_H    
    PORTE = adr; 
    PORTB &= (1<<5)^255;            // ALE_L    
    PORTE = 255;
    PORTE = 255;
    PORTE = 255;
    PORTB &= ((1<<3)|(1<<6))^255;   // CS_L, RD_L
    value = PORTE; 
    value = PORTE; 
    value = PORTE; 
    PORTB |= (1<<6)|(1<<3);         // RD_H, CS_H
    return(value);
}

proc can_check_adapter()
{
    var error,x;
    error = 0;

//    if((can_rd_reg(0) & 0x21) != 0x21) error++;
    if(can_rd_reg(2) != 0x0C) error++;
    if(can_rd_reg(3) != 0xE0) error++;
    if(can_rd_reg(31) != 0x00) error++;
    return(error);
}

proc can_set_baudrate(baud)
{
    var btr0,btr1,x;
    
    btr0 = 0;
    btr1 = 0;

    if(baud <= 500000)
    {
        btr0 = (500000/baud-1)+64;
        btr1 = 28;
    }
    if(baud = 800000)
    {
        btr0 = 64;
        btr1 = 22;
    }
    if(baud = 1000000)
    {
        btr0 = 64;
        btr1 = 20;
    }
    x = (btr1 << 8)|btr0;
    if(x = 0)   return(x);

    can_wr_reg(0,1);

    can_wr_reg(6,btr0);
    can_wr_reg(7,btr1);

    can_wr_reg(0,0);
}

proc can_init(mode,baud,id_filter)
{
    var temp,error,btr0,btr1;

    // вычисление делителей скорости

    btr0 = 0;btr1 = 0;
    baud *= 1000;
    if(baud <= 500000)  {   btr0 = (500000/baud-1)+64; btr1 = 28;   }
    if(baud = 800000)   {   btr0 = 64; btr1 = 22;                   }
    if(baud = 1000000)  {   btr0 = 64; btr1 = 20;                   }
    temp = btr0 + btr1;
    if(temp = 0) return(1);         // недопустимое значение скорости

    can_mode = mode;                // запоминаем режим работы
    can_wr_reg(0,1);                // reset mode

    can_wr_reg(31,(0x80+0x40+0x08)); // PeliCAN mode, CLOCKOUT off
    can_wr_reg(4,0);                // Выключаем прерывания
    can_wr_reg(6,btr0);             // установка скорости
    can_wr_reg(7,btr1);

    if(id_filter != 0xFFFFFFFF)     // установка фильтра, если надо
    {
        temp = id_filter << 21;
        can_wr_reg(16,temp >> 24);  // acceptance code
        can_wr_reg(17,temp >> 16);
        can_wr_reg(18,temp >> 8);
        can_wr_reg(19,temp & 255);
        temp = 0x001FFFFF;
        can_wr_reg(20,temp >> 24);  // acceptance mask
        can_wr_reg(21,temp >> 16);
        can_wr_reg(22,temp >> 8);
        can_wr_reg(23,temp & 255);
    }
    else
    {
        for(btr0 = 16; btr0 <= 23; btr0++)
        {
            can_wr_reg(btr0,255);
        }
    }
    can_wr_reg(8,0x18+2);           // Tx0PshPull | NormalMode);  
    error = 0;
    temp = can_rd_reg(31);
    temp ^= (0x80+0x40+0x08) & 255;
    can_wr_reg(0,8);                // 32-битный фильтр           
    return(temp);
}

proc can_init2(mode,baud,id_filter)
{
    var temp,error,btr0,btr1;

    // вычисление делителей скорости

    btr0 = 0;btr1 = 0;
//    baud *= 1000;
    if(baud <= 500000)  {   btr0 = (500000/baud-1)+64; btr1 = 28;   }
    if(baud = 800000)   {   btr0 = 64; btr1 = 22;                   }
    if(baud = 1000000)  {   btr0 = 64; btr1 = 20;                   }
    temp = btr0 + btr1;
    if(temp = 0) return(1);         // недопустимое значение скорости

    can_mode = mode;                // запоминаем режим работы
    can_wr_reg(0,1);                // reset mode

    can_wr_reg(31,(0x80+0x40+0x08)); // PeliCAN mode, CLOCKOUT off
    can_wr_reg(4,0);                // Выключаем прерывания
    can_wr_reg(6,btr0);             // установка скорости
    can_wr_reg(7,btr1);

    if(id_filter != 0xFFFFFFFF)     // установка фильтра, если надо
    {
        temp = id_filter << 21;
        can_wr_reg(16,temp >> 24);  // acceptance code
        can_wr_reg(17,temp >> 16);
        can_wr_reg(18,temp >> 8);
        can_wr_reg(19,temp & 255);
        temp = 0x001FFFFF;
        can_wr_reg(20,temp >> 24);  // acceptance mask
        can_wr_reg(21,temp >> 16);
        can_wr_reg(22,temp >> 8);
        can_wr_reg(23,temp & 255);
    }
    else
    {
        for(btr0 = 16; btr0 <= 23; btr0++)
        {
            can_wr_reg(btr0,255);
        }
    }
    can_wr_reg(8,0x18+2);           // Tx0PshPull | NormalMode);  
    error = 0;
    temp = can_rd_reg(31);
    temp ^= (0x80+0x40+0x08) & 255;
    can_wr_reg(0,8);                // 32-битный фильтр           
    return(temp);
}

proc can_tx(cid,clen)
{
    var i;

    if(can_mode = 0)                // Стандартный режим, идентификатор 11 бит
    {
        can_wr_reg(16,clen);
        can_wr_reg(17,cid >> 3);
        can_wr_reg(18,cid << 5);
        for(i = 0;i < 8; i++)
        {
            can_wr_reg(i+19,can_tx_data[i]);
        }
    }
    else                        // Расширенный режим, 29 бит
    {                           
        can_wr_reg(16,0x80+clen);
        can_wr_reg(17,cid >> 24);
        can_wr_reg(18,cid >> 16);
        can_wr_reg(19,cid >> 8);
        can_wr_reg(20,cid);
        for(i = 0;i < 8; i++)
        {
            can_wr_reg(i+21,can_tx_data[i]);
        }
    }

    can_wr_reg(1,1);    // флаг передачи

    for(;;) 
    {
        i = can_rd_reg(2);
        if((i & 0x48) != 0) break;
    }
    tx_result = i;
    if(i & 0x40)
    {
        can_wr_reg(1,2);        // прерываем передачу
    }
    return(i & 8);
}

proc wait_can_tx(w,cid,clen)
{
    var i;

    if(w != 0)
    {
        TIMER2 = 0;
        while(TIMER2 < w) ;    
    }

    if(can_mode = 0)                // Стандартный режим, идентификатор 11 бит
    {
        can_wr_reg(16,clen);
        can_wr_reg(17,cid >> 3);
        can_wr_reg(18,cid << 5);
        for(i = 0;i < 8; i++)
        {
            can_wr_reg(i+19,can_tx_data[i]);
        }
    }
    else                        // Расширенный режим, 29 бит
    {                           
        can_wr_reg(16,0x80+clen);
        can_wr_reg(17,cid >> 24);
        can_wr_reg(18,cid >> 16);
        can_wr_reg(19,cid >> 8);
        can_wr_reg(20,cid);
        for(i = 0;i < 8; i++)
        {
            can_wr_reg(i+21,can_tx_data[i]);
        }
    }

    can_wr_reg(1,1);    // флаг передачи

    for(;;) 
    {
        i = can_rd_reg(2);
        if((i & 0x48) != 0) break;
    }
    tx_result = i;
    if(i & 0x40)
    {
        can_wr_reg(1,2);        // прерываем передачу
    }
    return(i & 8);
}

proc can_rx_message()
{
    var a;
    a = can_rd_reg(2);
    if(a & 2)
    {
        can_missing_rx = 255;
        can_wr_reg(1,0x8);     
    }
    else can_missing_rx = 0;

    if(a & 1 = 0)   return(0);              // нет принятого сообщения
    
    if(can_mode = 0)                        // стандартный режим
    {
        can_rx_len = can_rd_reg(16) & 15;   // длина принятой посылки
        can_rx_id = ((can_rd_reg(17)<<8)+can_rd_reg(18)) >> 5;
        for(a = 0;a < 8; a++)
        {
            can_rx_data[a] = can_rd_reg(a+19);
        }
    }
    can_wr_reg(1,4);                    // освобождаем приемный буфер
    return(can_rx_len);
}

proc can_set_listen_mode(mode)
{
    var a;
    a = can_rd_reg(0); 
    can_wr_reg(0,1);                // reset mode
    if(mode) { can_wr_reg(0,a | 2); }
    else     { can_wr_reg(0,a ); }
}

