Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
205 arune 1
/*********************************************
2
 * vim:sw=8:ts=8:si:et
3
 * To use the above modeline in vim you must have "set modeline" in your .vimrc
4
 * Author: Guido Socher
5
 * Copyright: GPL V2
6
 *
7
 * Ethernet remote device and sensor
8
 *
9
 * Title: Microchip ENC28J60 Ethernet Interface Driver
10
 * Chip type           : ATMEGA88 with ENC28J60
11
 *********************************************/
12
/*-----------------------------------------------------------------------------
13
 * Includes
14
 *---------------------------------------------------------------------------*/
15
/* system files */
16
#include <avr/io.h>
17
#include <stdlib.h>
18
#include <string.h>
19
 
20
/* lib files */
21
#include <ip_arp_udp_tcp.h>
22
#include <enc28j60.h>
23
#include <timeout.h>
24
#include <avr_compat.h>
25
#include <net.h>
26
 
27
 
28
// please modify the following two lines. mac and ip have to be unique
29
// in your local area network. You can not have the same numbers in
30
// two devices:
31
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x25};
32
static uint8_t myip[4] = {193,11,254,22};
33
static uint16_t myport =1200; // listen port for udp
34
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX
35
 
36
#define BUFFER_SIZE 550
37
static uint8_t buf[BUFFER_SIZE+1];
38
 
39
// prepare the webpage by writing the data to the tcp send buffer
40
uint16_t print_webpage(uint8_t *buf,uint8_t rev)
41
{
42
        char vstr[5];
43
        uint16_t plen;
44
        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
45
        plen=fill_tcp_data_p(buf,plen,PSTR("<center><p>ENC28J60 silicon rev is: "));
46
        itoa((enc28j60getrev()),vstr,10);
47
        plen=fill_tcp_data(buf,plen,vstr);
48
        plen=fill_tcp_data_p(buf,plen,PSTR("</center><hr><br>ver 2.2, tuxgraphics.org\n"));
49
        return(plen);
50
}
51
 
52
int main(void){
53
 
54
 
55
        uint16_t plen;
56
        uint16_t dat_p;
57
        uint8_t i=0;
58
        uint8_t payloadlen=0;
59
        char str[20];
60
 
61
        // set the clock speed to 8MHz
62
        // set the clock prescaler. First write CLKPCE to enable setting of clock the
63
        // next four instructions.
64
        CLKPR=(1<<CLKPCE);
65
        CLKPR=0; // 8 MHZ
66
 
67
        /* enable PB0, reset as output */
68
        DDRB|= (1<<DDB0);
69
 
70
        /* set output to gnd, reset the ethernet chip */
71
        PORTB &= ~(1<<PB0);
72
        delay_ms(30);
73
        /* set output to Vcc, reset inactive */
74
        PORTB|= (1<<PB0);
75
        delay_ms(200);
76
 
77
        /*initialize enc28j60*/
78
        enc28j60Init(mymac);
79
        delay_ms(20);
80
 
81
        // LED
82
        /* enable PB1, LED as output */
83
        DDRD|= (1<<DDD6);
84
 
85
        /* set output to Vcc, LED off */
86
        PORTD|= (1<<PD6);
87
 
88
        /* Magjack leds configuration, see enc28j60 datasheet, page 11 */
89
        // LEDB=yellow LEDA=green
90
        //
91
        // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
92
        // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);
93
        enc28j60PhyWrite(PHLCON,0x476);
94
        delay_ms(20);
95
 
96
        /* set output to GND, red LED on */
97
        PORTD &= ~(1<<PD6);
98
        i=1;
99
 
100
        //init the ethernet/ip layer:
101
        init_ip_arp_udp_tcp(mymac,myip,80);
102
 
103
        while(1){
104
                // get the next new packet:
105
                plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
106
 
107
                /*plen will ne unequal to zero if there is a valid
108
                 * packet (without crc error) */
109
                if(plen==0){
110
                        continue;
111
                }
112
                // arp is broadcast if unknown but a host may also
113
                // verify the mac address by sending it to 
114
                // a unicast address.
115
                if(eth_type_is_arp_and_my_ip(buf,plen)){
116
                        make_arp_answer_from_request(buf);
117
                        continue;
118
                }
119
                // check if ip packets (icmp or udp) are for us:
120
                if(eth_type_is_ip_and_my_ip(buf,plen)==0){
121
                        continue;
122
                }
123
 
124
                if (i){
125
                        /* set output to Vcc, LED off */
126
                        PORTD|= (1<<PD6);
127
                        i=0;
128
                }else{
129
                        /* set output to GND, LED on */
130
                        PORTD &= ~(1<<PD6);
131
                        i=1;
132
                }
133
 
134
                if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
135
                        // a ping packet, let's send pong
136
                        make_echo_reply_from_request(buf,plen);
137
                        continue;
138
                }
139
 
140
                // tcp port 80 start
141
                if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==80){
142
                        if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){
143
                                make_tcp_synack_from_syn(buf);
144
                                // make_tcp_synack_from_syn does already send the syn,ack
145
                                continue;
146
                        }
147
                        if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
148
                                init_len_info(buf); // init some data structures
149
                                // we can possibly have no data, just ack:
150
                                dat_p=get_tcp_data_pointer();
151
                                if (dat_p==0){
152
                                        if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){
153
                                                // finack, answer with ack
154
                                                make_tcp_ack_from_any(buf);
155
                                        }
156
                                        // just an ack with no data, wait for next packet
157
                                        continue;
158
                                }
159
                                if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){
160
                                        // head, post and other methods:
161
                                        //
162
                                        // for possible status codes see:
163
                                        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
164
                                        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
165
                                        goto SENDTCP;
166
                                }
167
                                // any GET, any url:
168
                                plen=print_webpage(buf,enc28j60getrev());
169
SENDTCP:
170
                                make_tcp_ack_from_any(buf); // send ack for http get
171
                                make_tcp_ack_with_data(buf,plen); // send data
172
                                continue;
173
                        }
174
                }
175
                // tcp port 80 end
176
                //
177
                // udp start, we listen on udp port 1200=0x4B0
178
                if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==4&&buf[UDP_DST_PORT_L_P]==0xb0){
179
                        payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
180
                        // you must sent a string starting with v
181
                        // e.g udpcom version 10.0.0.24
182
                        if (buf[UDP_DATA_P]=='v' ){
183
                                str[0]='v';
184
                                str[1]='e';
185
                                str[2]='r';
186
                                str[3]='=';
187
                                itoa((enc28j60getrev()),&(str[4]),10);
188
                                make_udp_reply_from_request(buf,str,strnlen(str,10),myport);
189
                        }
190
                }
191
        }
192
        return (0);
193
}