#include <mega8.h>
#include <delay.h>
////////////////////////////////////////////////////////////////////////////////
// ATmega8: 
// начальное: RC - 1 МHz: Low E1; Higt D9; 
//                    RC - 8 МHz: Low E4; Higt D9; 
//               кварц - 8 МHz: Low EF; Higt C9 (CKOPT -on); XTAL2 – выход--V
//               кварц - 8 МHz: Low EF; Higt D9 (CKOPT -off); 
//               XTAL1 – вход:  Low E0; Higt D9  
////////////////////////////////////////////////////////////////////////////////
// ATmega328: 
// начальное: RC -1 МHz: Higt D9; Ext 07; Lok 3F; Low 62
//                    RC -8 МHz: Higt D9; Ext 07; Lok 3F; Low E2
//            кварц - 20 МHz: Higt D9; Ext 07; Lok 3F; Low E7(CKOUT -off); XTAL2 – выход--V
//            кварц - 20 МHz: Higt D9; Ext 07; Lok 3F; Low E7(CKOUT -on); CKOUT – выход
////////////////////////////////////////////////////////////////////////////////
// W5500:       
// 3,3 V - 80 mA.  - 10 МБит/c
// 3,3 V - 135 mA. - 100 МБит/c
// Socket_0 - MACRAW
////////////////////////////////////////////////////////////////////////////////
                                             

////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////// счёт: 
unsigned char x;          // x - счёт 
unsigned char x1;        // x1 - счёт 
unsigned char x2;        // x2 - счёт 
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// SPI:
unsigned char tx;        // tx - SPI 
unsigned char rx;        // rx - SPI
////////////////////////////////// SPI: 
void SPI(void)
{
  SPDR=tx; while(!(SPSR & (1<<7))); rx=SPDR;      
}
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// RX MACRAW: 
unsigned char RX_int[160]={ 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};  
unsigned int RX_len = 32;     
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////// W5500:
unsigned int add;         // add - адрес данных W5500 (RX/TX)
unsigned int len;          // len - длина данных W5500 (RX/TX) 
////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// TX_MACRAW:
void TX_MACRAW(void)
{
////////////////////////////////////////////////////////////////////////////////
// Читаем начальный адрес для записи данных Socket_0  Sn_TX_WR MACRAW:
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x24; SPI(); tx=0x08; SPI(); // Address Registers + Control Registers    
tx=0x00; SPI(); x1 = rx;   // Data  -Sn_TX_WR0 -начальный адрес для записи данных //сарший регистр
tx=0x00; SPI(); x2 = rx;   // Data  -Sn_TX_WR1 -начальный адрес для записи данных //младший регистр
PORTB.0=1;        // SS W5500
add=x1; add = (add<<8)|x2; // начальный адрес для записи данных // 0x0000...0xFFFF
////////////////////////////////////////////////////////////////////////////////
//Пишем данные с начального адреса буфера  Socket 0 TX Buffer MACRAW: 
x1 = (add>>8);
x2 = add; 

PORTB.0=0;        // SS W5500
tx=x1; SPI(); tx=x2; SPI(); tx=0x14; SPI();   // Address = add

len = 0;              // сброс len              

for (x=0; x<RX_len; x++) {      
    RX_int[x] = 0;                         
};

PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
// Пишем регистр указателя  Socket 0 Sn_TX_WR до увеличенного значения MACRAW: 
add = add + len;  
x1 = (add>>8);
x2 = add; 
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x24; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers    
tx=x1; SPI();      // Data  -Sn_TX_WR0 -конечный адрес передачи данных //сарший регистр
tx=x2; SPI();      // Data  -Sn_TX_WR1 -конечный адрес передачи данных //младший регистр
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
//Пишем команду передачи SEND Socket 0 Command MACRAW:  
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x01; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers     
//tx=0x20; SPI(); // Data -0x20 (команда SEND c автоматическим ARP-запросом)  
tx=0x21; SPI();   // Data -0x21 (команда SEND без автоматического ARP-запроса)    
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
//If (Sn_CR == 0x00) по окончанию передачи статус меняется на Sn_CR = 0x00 
}
////////////////////////////////////////////////////////////////////////////////




////////////////////////////////////////////////////////////////////////////////
void main(void)
{
/////////////////////////////////////////////// SPI (мастер) 
DDRB.5=1;         // выход SCK
PORTB.5=0;        // выход SCK
DDRB.4=0;         // вход MISO
PORTB.4=0;        // вход MISO
DDRB.3=1;         // выход MOSI
PORTB.3=0;        // выход MOSI
DDRB.2=1;         // выход SS (! SS настроен на выход)  
PORTB.2=1;        // выход SS (! SS настроен на выход)
/////////////////////////////////////////////// W5500
DDRD.0=0;         // вход INT W5500   
PORTD.0=1;        // вход  INT W5500 +
DDRD.5=1;         // выход  RESET W5500 
PORTD.5=1;        // выход RESET W5500   
DDRB.0=1;         // выход SS W5500      
PORTB.0=1;        // выход SS W5500   
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// SPI:
SPCR=0x50;        // 8 МГц/4 = 2 МГц -режим мастер
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// инициализация W5500:
// 00000000 - Address Registers (автоматическая инкрементная адресация +1).
// 00000000 - Address Registers (автоматическая инкрементная адресация +1).
///////////////////////////////////////////////
// Control Registers:
// 0000 0... -  BSB [4:0] блок 
// .... .0..     - R/W - 0 чтение/1 запись 
// ....  ..00   - OP Mode (VDM)- данные переменной длины (Длина данных контролируется SS).
/////////////////////////////////////////////// RESET W5500:
PORTD.5=0;          //  
delay_ms(100);    //  
PORTD.5=1;          //  
delay_ms(100);    //  
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////// W5500 PHY:
// перед настройкой PHY сделать программный Cброс PHY: 
PORTB.0=0;         // SS W5500
tx=0x00; SPI(); tx=0x2E; SPI(); tx=0x04; SPI(); // Address Registers + Control Registers 
tx=0x00; SPI();                                     // Data  -0x00
tx=0x00; SPI();                                     // Data  -0x00
PORTB.0=1;         // SS W5500
// пишем режим PHY:
// 1...  ....  RST - 1.
// .1..  ....  программная настройка режима - 1
// ..0.  ....  10BT Full-duplex, Auto-negotiation disabled / Power Down mode
// ...0  ....  10BT Full-duplex, Auto-negotiation disabled / Power Down mode
// ....  1...  10BT Full-duplex, Auto-negotiation disabled / Power Down mode
// ....  .1..  Duplex Status
// ....  ..0.  Speed Status 
// ....  ...1  Link Status
PORTB.0=0;     // SS W5500
tx=0x00; SPI(); tx=0x2E; SPI(); tx=0x04; SPI(); // Address Registers + Control Registers  
tx=0xC8; SPI();                                     // Data -0xC8 (10 Мбит/с, Full-duplex)  
tx=0x00; SPI();                                     // Data -0x00                     
PORTB.0=1;      // SS W5500
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////// Socket_0 - MACRAW:
// Протокол: пишем протокол MACRAW Socket_0: 
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x00; SPI(); tx=0x0C; SPI();  // Address Registers + Control Registers    
tx=0x04; SPI();                               // Data -0x04 // MACRAW // Socket_0
//tx=0xE4; SPI();                             // Data -0xE4 // MACRAW // Socket_0
// 0xE4:  - Блокирование широковещательной и многоадресной рассылки в режиме MACRAW:
// 1... .... - блокировка широковещательной и многоадресной рассылки в режиме MACRAW
// .1.. .... - блокировка broadcast в режиме MACRAW
// ..1. .... - блокировка multicast в режиме MACRAW
PORTB.0=1;        // SS W5500
// пишем команду OPEN Socket_0:
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x01; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers    
tx=0x01; SPI();  // Data -0x01 (команда OPEN)  
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////  Socket_0 - INT:
// INT Mask Socket_0: пишем INT Mask Socket_0: (SIMR) 0x0018
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x18; SPI();  tx=0x04; SPI(); // Address Registers + Control Registers    
tx=0x01; SPI();  // Data 0x01 -Enable INT Socket_0.
PORTB.0=1;        // SS W5500
// INT Mask Socket_0 RECV: пишем INT Mask завершение приёма Socket_0: (Sn_IMR) 0x002C
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x2C; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers    
tx=0x04; SPI();  // Data 0x04 -INT Mask завершение приёма. 
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////


 
 
_1:
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////// TX_MACRAW:
delay_ms(1);         
////////////////////////////////////////////////////////////////////////////////
// проверка  INT  RX_MACRAW: 
if (PIND.0 == 1) {goto _1;};    // MACRAW пуст > _1
// пишем: сброс флаг завершение приёма INT Socket_0: (Sn_IR) 0x0002
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x02; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers    
tx=0x04; SPI();  // Data 0x04 -сброс флаг завершение приёма. 
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
// читаем размер принятых данных Socket_0 MACRAW: 
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x26; SPI(); tx=0x08; SPI();  // Address Registers + Control Registers                 
tx=0x00; SPI(); x1 = rx;      // Data  -Sn_RX_RSR0 -размер принятых данных //сарший регистр
tx=0x00; SPI(); x2 = rx;      // Data  -Sn_RX_RSR1 -размер принятых данных //младший регистр
PORTB.0=1;        // SS W5500
len = x1; len = (len<<8)|x2;  // len - размер принятых данных
x1 = (len>>8);
x2 = len; 
////////////////////////////////////////////////////////////////////////////////
if (len == 0x00) {
  goto _1;              // MACRAW пуст > _1;
};
////////////////////////////////////////////////////////////////////////////////
// Читаем начальный адрес принятых данных Socket_0  Sn_RX_RD MACRAW
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x28; SPI(); tx=0x08; SPI(); // Address Registers + Control Registers    
tx=0x00; SPI(); x1 = rx;  // Data  -Sn_RX_RD0 -начальный адрес принятых данных //сарший регистр
tx=0x00; SPI(); x2 = rx;  // Data  -Sn_RX_RD1 -начальный адрес принятых данных //младший регистр
PORTB.0=1;        // SS W5500
add=x1; add=(add<<8)|x2; // начальный адрес принятых данных // 0x0000...0xFFFF
////////////////////////////////////////////////////////////////////////////////
// Читаем данные с начального адреса буфера Socket_0 RX Buffer MACRAW:
x1 = (add>>8);
x2 = add; 
PORTB.0=0;        // SS W5500
tx=x1; SPI(); tx=x2; SPI(); tx=0x18; SPI();     // Address = add       

// MACRAW // len | Data 
// len - 0x00 0x00(len=len+Data).
    
// RX_len - 0x00 0x00
tx=0x00; SPI(); RX_len=rx;  
RX_len=(RX_len<<8);
tx=0x00; SPI(); RX_len|=rx;    
// len - 0x00 0x00(len=len+Data).
RX_len -=2;  

// MACRAW MAX=160
if (RX_len > 159) {RX_len= 160;};  

// MACRAW > RX_int  
for (x=0; x<RX_len; x++) {   
    tx=0x00; SPI(); RX_int[x]=rx;         
};
     
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
// Пишем регистр указателя Sn_RX_RD MACRAW до увеличенного значения: 
add = add + len; //add - начальный/конечный адрес принятых данных // 0x0000...0xFFFF
                          //len - размер полученных данных // 0x0000...0xFFFF  
x1 = (add>>8);
x2 = add; 
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x28; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers       
tx=x1; SPI();      // Data  -Sn_RX_RD0 -конечный адрес принятых данных //сарший регистр
tx=x2; SPI();      // Data  -Sn_RX_RD1 -конечный адрес принятых данных //младший регистр
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////
// Пишем команду завершения приема RECV MACRAW:
PORTB.0=0;        // SS W5500
tx=0x00; SPI(); tx=0x01; SPI(); tx=0x0C; SPI(); // Address Registers + Control Registers    
tx=0x40; SPI();  // Data -0x40 (команда RECV)    
PORTB.0=1;        // SS W5500
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
TX_MACRAW();   // > TX_MACRAW()
////////////////////////////////////////////////////////////////////////////////
goto _1; // > _1
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
}    
