-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmain.c
More file actions
378 lines (342 loc) · 12.1 KB
/
main.c
File metadata and controls
378 lines (342 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
//********************************************************************************************
//
// AVRnet firmware Version 1.1
//
// MCU : ATMEGA32 @ 16MHz
// Ethernet controller : ENC28J60
// IDE & Compiler : AVR Studio version 4.13.528 & WINAVR version 20070525
// Author : Jirawat Kongkaen
// Website : http://www.avrportal.com/
//
//********************************************************************************************
//
// File : main.c main program for AVRnet development board.
//
//********************************************************************************************
//
// Copyright (C) 2007
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
// This program is distributed in the hope that it will be useful, but
//
// WITHOUT ANY WARRANTY;
//
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin St, Fifth Floor, Boston, MA 02110, USA
//
// http://www.gnu.de/gpl-ger.html
//
//********************************************************************************************
#include "includes.h"
// Global variables
MAC_ADDR avr_mac;
IP_ADDR avr_ip;
MAC_ADDR server_mac;
IP_ADDR server_ip;
//BYTE generic_buf[128];
// added in V1.1
prog_int8_t version[] = "AVRnet V1.1";
// end added in V1.1
// Change your avr and server ip address here
// avr and server ip address are stored in eeprom
BYTE ee_avr_ip[4] EEMEM = { 10, 1, 1, 1 };
BYTE ee_server_ip[4] EEMEM = { 10, 1, 1, 76 };
// added in V1.1 ==========================================================================
//*****************************************************************************************
//
// Function : software_reset
// Description : reset mcu by enable watchdog
//
//*****************************************************************************************
#ifndef REMOVE_BOOTLOADER_SUPPORT
void software_reset(void) __attribute__ ((naked));
void software_reset(void)
{
wdt_enable(WDTO_15MS);
for(;;);
}
#endif
// end added in V1.1 ======================================================================
//*****************************************************************************************
//
// Function : server_process
// Description : Run web server and listen on port 80
//
//*****************************************************************************************
void server_process ( void )
{
MAC_ADDR client_mac;
IP_ADDR client_ip;
// you can change rx,tx buffer size in includes.h
BYTE rxtx_buffer[MAX_RXTX_BUFFER];
WORD plen;
if ( flag1.bits.syn_is_sent )
return;
// get new packet
plen = enc28j60_packet_receive( (BYTE*)&rxtx_buffer, MAX_RXTX_BUFFER );
//plen will ne unequal to zero if there is a valid packet (without crc error)
if(plen==0)
return;
// copy client mac address from buffer to client mac variable
memcpy ( (BYTE*)&client_mac, &rxtx_buffer[ ETH_SRC_MAC_P ], sizeof(MAC_ADDR) );
// check arp packet if match with avr ip let's send reply
if ( arp_packet_is_arp( rxtx_buffer, (WORD_BYTES){ARP_OPCODE_REQUEST_V} ) )
{
arp_send_reply ( (BYTE*)&rxtx_buffer, (BYTE*)&client_mac );
return;
}
// get client ip address
memcpy ( (BYTE*)&client_ip, &rxtx_buffer[ IP_SRC_IP_P ], sizeof(IP_ADDR) );
// check ip packet send to avr or not?
if ( ip_packet_is_ip ( (BYTE*)&rxtx_buffer ) == 0 )
{
return;
}
// check ICMP packet, if packet is icmp packet let's send icmp echo reply
if ( icmp_send_reply ( (BYTE*)&rxtx_buffer, (BYTE*)&client_mac, (BYTE*)&client_ip ) )
{
return;
}
// check UDP packet
if (udp_receive ( (BYTE *)&rxtx_buffer, (BYTE *)&client_mac, (BYTE *)&client_ip ))
{
// added in V1.1 ***********************************
#ifndef REMOVE_BOOTLOADER_SUPPORT
if( flag2.bits.software_reset )
software_reset();
#endif
// end added in V1.1 *******************************
return;
}
// tcp start here
// start web server at port 80, see http.c
http_webserver_process ( (BYTE*)rxtx_buffer, (BYTE*)&client_mac, (BYTE*)&client_ip );
}
//*****************************************************************************************
//
// Function : client_process
// Description : send temparature to web server, this option is disabled by default.
// YOU MUST install webserver and server script before enable this option,
// I recommented Apache webserver and PHP script.
// More detail about Apache and PHP installation please visit http://www.avrportal.com/
//
//*****************************************************************************************
void client_process ( void )
{
WORD dlength;
// you can change rx,tx buffer size in includes.h
BYTE rxtx_buffer[MAX_RXTX_BUFFER];
// wait for send temparature flag is set, this flag set by time_base function (menu.c)
if ( flag1.bits.send_temp == 0 )
return;
// AVR busy now and wait untill transfer data to web browser completed.
if ( flag1.bits.syn_is_received )
return;
// AVR sent temparature to web server but not found web server on port 80
//if ( flag1.bits.not_found_server )
// return;
// send SYN to initial connection
if ( flag1.bits.syn_is_sent == 0 )
{
// start arp
// server ip was not found on network
if ( arp_who_is ( rxtx_buffer, (BYTE*)&server_mac, (BYTE*)&server_ip ) == 0 )
{
flag1.bits.send_temp = 0;
return;
}
// send SYN packet to initial connection
tcp_send_packet (
rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_SYN_V, // flag
1, // (bool)maximum segment size
1, // (bool)clear sequence ack number
0, // 0=use old seq, seqack : 1=new seq,seqack no data : new seq,seqack with data
0, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
flag1.bits.syn_is_sent = 1;
}
// get new packet
dlength = enc28j60_packet_receive( (BYTE*)&rxtx_buffer, MAX_RXTX_BUFFER );
// no new packet incoming
if ( dlength == 0 )
{
// timeout occured, when SYN has been sent but no response from web server
// reset send_temp and syn_is_sent flags
if ( flag1.bits.send_temp_timeout )
{
flag1.bits.send_temp_timeout = 0;
flag1.bits.send_temp = 0;
flag1.bits.syn_is_sent = 0;
}
return;
}
// check ip packet send to avr or not?
// accept ip packet only
if ( ip_packet_is_ip ( (BYTE*)&rxtx_buffer ) == 0 )
{
return;
}
// check SYNACK flag, after AVR send SYN server response by send SYNACK to AVR
if ( rxtx_buffer [ TCP_FLAGS_P ] == ( TCP_FLAG_SYN_V | TCP_FLAG_ACK_V ) )
{
// send ACK to answer SYNACK
tcp_send_packet (
(BYTE*)&rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_ACK_V, // flag
0, // (bool)maximum segment size
0, // (bool)clear sequence ack number
1, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
0, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
// setup http request to server
dlength = http_put_request( (BYTE*)&rxtx_buffer );
// send http request packet
// send packet with PSHACK
tcp_send_packet (
(BYTE*)&rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_ACK_V | TCP_FLAG_PSH_V, // flag
0, // (bool)maximum segment size
0, // (bool)clear sequence ack number
0, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
dlength, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
return;
}
// after AVR send http request to server, server response by send data with PSHACK to AVR
// AVR answer by send ACK and FINACK to server
if ( rxtx_buffer [ TCP_FLAGS_P ] == (TCP_FLAG_ACK_V|TCP_FLAG_PSH_V) )
{
dlength = tcp_get_dlength( (BYTE*)&rxtx_buffer );
// send ACK to answer PSHACK from server
tcp_send_packet (
(BYTE*)&rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_ACK_V, // flag
0, // (bool)maximum segment size
0, // (bool)clear sequence ack number
dlength, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
0, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
// send finack to disconnect from web server
tcp_send_packet (
(BYTE*)&rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_FIN_V|TCP_FLAG_ACK_V, // flag
0, // (bool)maximum segment size
0, // (bool)clear sequence ack number
0, // (bool)calculate new seq and seqack number
0, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
return;
//menu_flag.bits.send_temp = 0;
//send_syn = 0;
}
// answer FINACK from web server by send ACK to web server
if ( rxtx_buffer [ TCP_FLAGS_P ] == (TCP_FLAG_FIN_V|TCP_FLAG_ACK_V) )
{
// send ACK with seqack = 1
tcp_send_packet (
(BYTE*)&rxtx_buffer,
(WORD_BYTES){80}, // destination port
(WORD_BYTES){1200}, // source port
TCP_FLAG_ACK_V, // flag
0, // (bool)maximum segment size
0, // (bool)clear sequence ack number
1, // 0=use old seq, seqack : 1=new seq,seqack no data : >1 new seq,seqack with data
0, // tcp data length
(BYTE*)&server_mac, // server mac address
(BYTE*)&server_ip ); // server ip address
// temparature has been sent
// and wait for next schedule to send temparature
flag1.bits.send_temp = 0;
flag1.bits.syn_is_sent = 0;
}
}
//*****************************************************************************************
//
// Function : main
// Description : main program,
//
//*****************************************************************************************
int main (void)
{
// change your mac address here
avr_mac.byte[0] = 'A';
avr_mac.byte[1] = 'V';
avr_mac.byte[2] = 'R';
avr_mac.byte[3] = 'P';
avr_mac.byte[4] = 'O';
avr_mac.byte[5] = 'R';
// read avr and server ip from eeprom
eeprom_read_block ( &avr_ip, ee_avr_ip, 4 );
eeprom_read_block ( &server_ip, ee_server_ip, 4 );
// setup port as input and enable pull-up
SW_DDR &= ~ ( _BV( SW_MENU ) | _BV( SW_EXIT ) | _BV( SW_UP ) | _BV( SW_DW ) );
SW_PORT |= _BV( SW_MENU ) | _BV( SW_EXIT ) | _BV( SW_UP ) | _BV( SW_DW );
SFIOR &= ~_BV( PUD );
// setup lcd backlight as output
LCD_BL_DDR |= _BV( LCD_BL_PIN );
// lcd backlight on
LCD_BL_PORT |= _BV( LCD_BL_PIN );
// setup clock for timer1
TCCR1B = 0x01; // clk/1 no prescaling
// initial adc, lcd, and menu
adc_init();
lcd_init ();
menu_init ();
// set LED1, LED2 as output */
LED_DDR |= _BV( LED_PIN1_DDR ) | _BV( LED_PIN2_DDR );
// set LED pin to "1" ( LED1,LED2 off)
LED_PORT |= _BV( LED_PIN1 ) | _BV( LED_PIN2 );
// initial enc28j60
enc28j60_init( (BYTE*)&avr_mac );
// added in V1.1
lcd_print_p( (PGM_P)version );
// end added in V1.1
// loop forever
for(;;)
{
// wait until timer1 overflow
while ( (TIFR & _BV ( TOV1 )) == 0 );
TIFR |= _BV(TOV1);
TCNT1 = 1536; // Timer1 overflow every 1/16MHz * ( 65536 - 1536 ) = 4ms, 250Hz
// general time base, generate by timer1
// overflow every 1/250 seconds
time_base ();
// read temparature
adc_read_temp();
// server process response for arp, icmp, http
server_process ();
// send temparature to web server unsing http protocol
// disable by default.
client_process ();
// lcd user interface menu
// setup IP address, countdown timer
menu_process ();
// display AVR ethernet status
// temparature, AVR ip, server ip, countdown time
standby_display ();
}
return 0;
}