/[H8]/trunk/docs/MCHPStack2.20/Source/websrvr.c
ViewVC logotype

Contents of /trunk/docs/MCHPStack2.20/Source/websrvr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue May 1 08:17:39 2007 UTC (17 years, 2 months ago) by hedin
File MIME type: text/plain
File size: 34759 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 /*********************************************************************
2 *
3 * Example Web Server Application using Microchip TCP/IP Stack
4 *
5 *********************************************************************
6 * FileName: WebSrvr.c
7 * Dependencies: string.H
8 * usart.h
9 * StackTsk.h
10 * Tick.h
11 * http.h
12 * MPFS.h
13 * Processor: PIC18
14 * Complier: MCC18 v1.00.50 or higher
15 * HITECH PICC-18 V8.10PL1 or higher
16 * Company: Microchip Technology, Inc.
17 *
18 * Software License Agreement
19 *
20 * The software supplied herewith by Microchip Technology Incorporated
21 * (the “Company”) for its PICmicro® Microcontroller is intended and
22 * supplied to you, the Company’s customer, for use solely and
23 * exclusively on Microchip PICmicro Microcontroller products. The
24 * software is owned by the Company and/or its supplier, and is
25 * protected under applicable copyright laws. All rights are reserved.
26 * Any use in violation of the foregoing restrictions may subject the
27 * user to criminal sanctions under applicable laws, as well as to
28 * civil liability for the breach of the terms and conditions of this
29 * license.
30 *
31 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
32 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
33 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
34 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
35 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
36 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
37 *
38 *
39 * HiTech PICC18 Compiler Options excluding device selection:
40 * -FAKELOCAL -G -O -Zg -E -C
41 *
42 *
43 *
44 *
45 * Author Date Comment
46 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
47 * Nilesh Rajbharti 4/19/01 Original (Rev. 1.0)
48 * Nilesh Rajbharti 2/09/02 Cleanup
49 * Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
50 * Nilesh Rajbharti 7/9/02 Rev 2.1 (See version.log for detail)
51 * Nilesh Rajbharti 4/7/03 Rev 2.11.01 (See version log for detail)
52 ********************************************************************/
53
54 /*
55 * Following define uniquely deines this file as main
56 * entry/application In whole project, there should only be one such
57 * definition and application file must define AppConfig variable as
58 * described below.
59 */
60 #define THIS_IS_STACK_APPLICATION
61
62 #define BAUD_RATE (19200) // bps
63
64 #define USART_USE_BRGH_LOW
65 #if defined(USART_USE_BRGH_LOW)
66 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/64) - 1)
67 #else
68 #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/16) - 1)
69 #endif
70
71 #if SPBRG_VAL > 255
72 #error "Calculated SPBRG value is out of range for currnet CLOCK_FREQ."
73 #endif
74
75
76
77 #include <string.h>
78
79 /*
80 * These headers must be included for required defs.
81 */
82 #include "stacktsk.h"
83 #include "tick.h"
84
85 #if defined(STACK_USE_DHCP)
86 #include "dhcp.h"
87 #endif
88
89 #if defined(STACK_USE_HTTP_SERVER)
90 #include "http.h"
91 #endif
92
93 #include "mpfs.h"
94
95 #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
96 #include "ftp.h"
97 #endif
98
99 #include "xlcd.h"
100
101 #if defined(MPFS_USE_EEPROM)
102 #include "xeeprom.h"
103 #endif
104
105
106 // For debug only.
107 #include "tcp.h"
108 #include "icmp.h"
109
110 #include "delay.h"
111
112 #define STARTUP_MSG "MpStack 2.20.04"
113
114 ROM char StartupMsg[] = STARTUP_MSG;
115
116 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
117 ROM char DHCPMsg[] = "DHCP/Gleaning...";
118 #endif
119
120 ROM char SetupMsg[] = "Board Setup...";
121
122 /*
123 * This is used by other stack elements.
124 * Main application must define this and initialize it with
125 * proper values.
126 */
127 APP_CONFIG AppConfig;
128
129 BYTE myDHCPBindCount = 0;
130 #if defined(STACK_USE_DHCP)
131 extern BYTE DHCPBindCount;
132 #else
133 /*
134 * If DHCP is not enabled, force DHCP update.
135 */
136 BYTE DHCPBindCount = 1;
137 #endif
138
139 #if defined(MCHP_C18) && defined(__18F8720)
140 #define TXSTAbits TXSTA1bits
141 #define TXREG TXREG1
142 #define TXSTA TXSTA1
143 #define RCSTA RCSTA1
144 #define SPBRG SPBRG1
145 #define RCREG RCREG1
146 #endif
147
148
149 /*
150 * Set configuration fuses for HITECH compiler.
151 * For MCC18 compiler, separately linked config.asm file
152 * will set the correct fuses.
153 */
154 #if defined(HITECH_C18)
155 __CONFIG(1, UNPROTECT & HS);
156 __CONFIG(2, PWRTEN & BORDIS & WDTDIS);
157 #endif
158
159 /*
160 * Private helper functions.
161 * These may or may not be present in all applications.
162 */
163 static void InitAppConfig(void);
164
165 static void InitializeBoard(void);
166 static void ProcessIO(void);
167
168 void NotifyRemoteUser(void);
169 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD);
170 static void SetConfig(void);
171
172
173 #if defined(MPFS_USE_EEPROM)
174 static BOOL DownloadMPFS(void);
175 static void SaveAppConfig(void);
176 #endif
177
178 #if defined(MCHP_C18)
179 #pragma interrupt HighISR save=section(".tmpdata")
180 void HighISR(void)
181 #elif defined(HITECH_C18)
182 #if defined(STACK_USE_SLIP)
183 extern void MACISR(void);
184 #endif
185 void interrupt HighISR(void)
186 #endif
187 {
188 TickUpdate();
189
190 #if defined(STACK_USE_SLIP)
191 MACISR();
192 #endif
193 }
194
195 #if defined(MCHP_C18)
196 #pragma code highVector=0x08
197 void HighVector (void)
198 {
199 _asm goto HighISR _endasm
200 }
201 #pragma code /* return to default code section */
202 #endif
203
204
205
206 static void USARTPut(BYTE c)
207 {
208 while( !TXSTA_TRMT);
209 TXREG = c;
210 }
211
212 static void USARTPutString(BYTE *s)
213 {
214 BYTE c;
215
216 while( (c = *s++) )
217 USARTPut(c);
218 }
219
220 #define USARTIsGetReady() (PIR1_RCIF)
221 #define USARTGet() (RCREG)
222
223
224
225 /*
226 * Main entry point.
227 */
228 void main(void)
229 {
230 static TICK t = 0;
231
232 /*
233 * Initialize any application specific hardware.
234 */
235 InitializeBoard();
236
237 /*
238 * Initialize all stack related components.
239 * Following steps must be performed for all applications using
240 * PICmicro TCP/IP Stack.
241 */
242 TickInit();
243
244 /*
245 * Following steps must be performed for all applications using
246 * PICmicro TCP/IP Stack.
247 */
248 MPFSInit();
249
250
251 /*
252 * Initialize Stack and application related NV variables.
253 */
254 InitAppConfig();
255
256
257 /*
258 * Depending on whether internal program memor is used or external
259 * EEPROM is used, keep/remove these block.
260 */
261
262 /*
263 * This implementation, initiates Board setup process if RB5
264 * is detected low on startup.
265 */
266 if ( PORTB_RB5 == 0 )
267 {
268 XLCDGoto(1, 0);
269 XLCDPutROMString(SetupMsg);
270
271 SetConfig();
272 }
273
274 StackInit();
275
276 #if defined(STACK_USE_HTTP_SERVER)
277 HTTPInit();
278 #endif
279
280 #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
281 FTPInit();
282 #endif
283
284
285 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
286 if ( AppConfig.Flags.bIsDHCPEnabled )
287 {
288 XLCDGoto(1, 0);
289 XLCDPutROMString(DHCPMsg);
290 }
291 else
292 {
293 /*
294 * Force IP address display update.
295 */
296 myDHCPBindCount = 1;
297 #if defined(STACK_USE_DHCP)
298 DHCPDisable();
299 #endif
300 }
301 #endif
302
303
304
305 /*
306 * Once all items are initialized, go into infinite loop and let
307 * stack items execute their tasks.
308 * If application needs to perform its own task, it should be
309 * done at the end of while loop.
310 * Note that this is a "co-operative mult-tasking" mechanism
311 * where every task performs its tasks (whether all in one shot
312 * or part of it) and returns so that other tasks can do their
313 * job.
314 * If a task needs very long time to do its job, it must broken
315 * down into smaller pieces so that other tasks can have CPU time.
316 */
317 while(1)
318 {
319 /*
320 * Blink SYSTEM LED every second.
321 */
322 if ( TickGetDiff(TickGet(), t) >= TICK_SECOND/2 )
323 {
324 t = TickGet();
325 LATA4 ^= 1;
326 }
327
328 /*
329 * This task performs normal stack task including checking
330 * for incoming packet, type of packet and calling
331 * appropriate stack entity to process it.
332 */
333 StackTask();
334
335 #if defined(STACK_USE_HTTP_SERVER)
336 /*
337 * This is a TCP application. It listens to TCP port 80
338 * with one or more sockets and responds to remote requests.
339 */
340 HTTPServer();
341 #endif
342
343 #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
344 FTPServer();
345 #endif
346
347 /*
348 * In future, as new TCP/IP applications are written, it
349 * will be added here as new tasks.
350 */
351
352 /*
353 * Add your application speicifc tasks here.
354 */
355 ProcessIO();
356
357 /*
358 * For DHCP information, display how many times we have renewed the IP
359 * configuration since last reset.
360 */
361 if ( DHCPBindCount != myDHCPBindCount )
362 {
363 DisplayIPValue(&AppConfig.MyIPAddr, TRUE);
364 myDHCPBindCount = DHCPBindCount;
365
366 if ( AppConfig.Flags.bIsDHCPEnabled )
367 {
368 XLCDGoto(1, 14);
369 if ( myDHCPBindCount < 0x0a )
370 XLCDPut(myDHCPBindCount + '0');
371 else
372 XLCDPut(myDHCPBindCount + 'A');
373 }
374 }
375
376 }
377 }
378
379 // 1234567890123456
380 ROM char blankLCDLine[] = " ";
381
382 static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD)
383 {
384 char IPDigit[8];
385
386 if ( bToLCD )
387 {
388 /*
389 * Erase second line.
390 */
391 XLCDGoto(1, 0);
392 XLCDPutROMString(blankLCDLine);
393
394 }
395
396 /*
397 * Rewrite the second line.
398 */
399 XLCDGoto(1, 0);
400
401 itoa(IPVal->v[0], IPDigit);
402 if ( bToLCD )
403 {
404 XLCDPutString(IPDigit);
405 XLCDPut('.');
406 }
407 else
408 {
409 USARTPutString((BYTE*)IPDigit);
410 USARTPut('.');
411 }
412
413 itoa(IPVal->v[1], IPDigit);
414 if ( bToLCD )
415 {
416 XLCDPutString(IPDigit);
417 XLCDPut('.');
418 }
419 else
420 {
421 USARTPutString((BYTE*)IPDigit);
422 USARTPut('.');
423 }
424
425 itoa(IPVal->v[2], IPDigit);
426 if ( bToLCD )
427 {
428 XLCDPutString(IPDigit);
429 XLCDPut('.');
430 }
431 else
432 {
433 USARTPutString((BYTE*)IPDigit);
434 USARTPut('.');
435 }
436
437 itoa(IPVal->v[3], IPDigit);
438 if ( bToLCD )
439 XLCDPutString(IPDigit);
440 else
441 USARTPutString((BYTE*)IPDigit);
442 }
443
444
445
446 static char AN0String[8];
447 static char AN1String[8];
448
449
450 static void ProcessIO(void)
451 {
452 WORD_VAL ADCResult;
453
454 /*
455 * Select AN0 channel, Fosc/32 clock
456 */
457 ADCON0 = 0b10000001;
458
459 /*
460 * Wait for acquisition time.
461 * Here, rather than waiting for exact time, a simple wait is
462 * used. Real applications requiring high accuracy should
463 * calculate exact acquisition time and wait accordingly.
464 */
465 ADCResult.v[0] = 100;
466 while( ADCResult.v[0]-- );
467
468 /*
469 * First convert AN0 channel.
470 * AN0 is already setup as an analog input.
471 */
472 ADCON0_GO = 1;
473
474 /*
475 * Wait until conversion is done.
476 */
477 while( ADCON0_GO );
478
479 /*
480 * Save the result.
481 */
482 ADCResult.v[0] = ADRESL;
483 ADCResult.v[1] = ADRESH;
484
485 /*
486 * Convert 10-bit value into ASCII String.
487 */
488 itoa(ADCResult.Val, AN0String);
489
490 /*
491 * Now, convert AN1 channel.
492 *
493 * In PICDEM.net board, RA2 thru RA7 should be digital or else
494 * LED, LCD and NIC would not operate correctly.
495 * Since there is no mode where only AN0 and AN1 be analog inputs
496 * while rests are digial pins, we will temperoraily switch
497 * select a mode where RA2 becomes analog input while we do
498 * conversion of RA1. Once conversion is done, we will convert
499 * RA2 back to digital pin.
500 */
501 ADCON1 = 0b10000100;
502
503 /*
504 * Select AN1 channel.
505 */
506 ADCON0 = 0b10001001;
507
508 /*
509 * Wait for acquisition time.
510 * Here, rather than waiting for exact time, a simple wait is
511 * used. Real applications requiring high accuracy should
512 * calculate exact acquisition time and wait accordingly.
513 */
514 ADCResult.v[0] = 100;
515 while( ADCResult.v[0]-- );
516
517 /*
518 * Start the conversion.
519 */
520 ADCON0_GO = 1;
521
522 /*
523 * Wait until it is done.
524 */
525 while( ADCON0_GO );
526
527 /*
528 * Save the result.
529 */
530 ADCResult.v[0] = ADRESL;
531 ADCResult.v[1] = ADRESH;
532
533 /*
534 * Convert 10-bit value into ASCII String.
535 */
536 itoa(ADCResult.Val, AN1String);
537
538 /*
539 * Reset RA2 pin back to digital output.
540 */
541 ADCON1 = 0b10001110; // RA0 as analog input.
542
543 }
544
545 /*
546 * CGI Command Codes.
547 */
548 #define CGI_CMD_DIGOUT (0)
549 #define CGI_CMD_LCDOUT (1)
550
551 /*
552 * CGI Variable codes. - There could be 0-255 variables.
553 */
554 #define VAR_LED_D5 (0)
555 #define VAR_LED_D6 (1)
556 #define VAR_ANAIN_AN0 (2)
557 #define VAR_ANAIN_AN1 (3)
558 #define VAR_DIGIN_RB5 (4)
559 #define VAR_STROUT_LCD (5)
560
561 /*********************************************************************
562 * Function: void HTTPExecCmd(BYTE** argv, BYTE argc)
563 *
564 * PreCondition: None
565 *
566 * Input: argv - List of arguments
567 * argc - Argument count.
568 *
569 * Output: None
570 *
571 * Side Effects: None
572 *
573 * Overview: This function is a "callback" from HTTPServer
574 * task. Whenever a remote node performs
575 * interactive task on page that was served,
576 * HTTPServer calls this functions with action
577 * arguments info.
578 * Main application should interpret this argument
579 * and act accordingly.
580 *
581 * Following is the format of argv:
582 * If HTTP action was : thank.htm?name=Joe&age=25
583 * argv[0] => thank.htm
584 * argv[1] => name
585 * argv[2] => Joe
586 * argv[3] => age
587 * argv[4] => 25
588 *
589 * Use argv[0] as a command identifier and rests
590 * of the items as command arguments.
591 *
592 * Note: THIS IS AN EXAMPLE CALLBACK.
593 ********************************************************************/
594 #if defined(STACK_USE_HTTP_SERVER)
595
596 ROM char COMMANDS_OK_PAGE[] = "COMMANDS.CGI";
597
598 // Copy string with NULL termination.
599 #define COMMANDS_OK_PAGE_LEN (sizeof(COMMANDS_OK_PAGE))
600
601 ROM char CMD_UNKNOWN_PAGE[] = "INDEX.HTM";
602
603 // Copy string with NULL termination.
604 #define CMD_UNKNOWN_PAGE_LEN (sizeof(CMD_UNKNOWN_PAGE))
605
606 void HTTPExecCmd(BYTE** argv, BYTE argc)
607 {
608 BYTE command;
609 BYTE var;
610
611 /*
612 * Design your pages such that they contain command code
613 * as a one character numerical value.
614 * Being a one character numerical value greatly simplifies
615 * the job.
616 */
617 command = argv[0][0] - '0';
618
619 /*
620 * Find out the cgi file name and interpret parameters
621 * accordingly
622 */
623 switch(command)
624 {
625 case CGI_CMD_DIGOUT:
626 /*
627 * This DIGOUTS.CGI. Any arguments with this file
628 * must be about controlling digital outputs.
629 */
630
631 /*
632 * Identify the parameters.
633 * Compare it in upper case format.
634 */
635 var = argv[1][0] - '0';
636
637 switch(var)
638 {
639 case VAR_LED_D5:
640 /*
641 * This is "D5".
642 * Toggle D5.
643 */
644 LATA3 ^= 1;
645 break;
646
647 case VAR_LED_D6:
648 /*
649 * This is "D6".
650 * Toggle it.
651 */
652 LATA2 ^= 1;
653 break;
654 }
655
656 memcpypgm2ram((void*)argv[0],
657 (ROM void*)COMMANDS_OK_PAGE, COMMANDS_OK_PAGE_LEN);
658 break;
659
660 case CGI_CMD_LCDOUT:
661 /*
662 * Note implemented.
663 */
664 break;
665
666 default:
667 memcpypgm2ram((void*)argv[0],
668 (ROM void*)CMD_UNKNOWN_PAGE, CMD_UNKNOWN_PAGE_LEN);
669 break;
670 }
671
672 }
673 #endif
674
675
676 /*********************************************************************
677 * Function: WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)
678 *
679 * PreCondition: None
680 *
681 * Input: var - Variable Identifier
682 * ref - Current callback reference with
683 * respect to 'var' variable.
684 * val - Buffer for value storage.
685 *
686 * Output: Variable reference as required by application.
687 *
688 * Side Effects: None
689 *
690 * Overview: This is a callback function from HTTPServer() to
691 * main application.
692 * Whenever a variable substitution is required
693 * on any html pages, HTTPServer calls this function
694 * 8-bit variable identifier, variable reference,
695 * which indicates whether this is a first call or
696 * not. Application should return one character
697 * at a time as a variable value.
698 *
699 * Note: Since this function only allows one character
700 * to be returned at a time as part of variable
701 * value, HTTPServer() calls this function
702 * multiple times until main application indicates
703 * that there is no more value left for this
704 * variable.
705 * On begining, HTTPGetVar() is called with
706 * ref = HTTP_START_OF_VAR to indicate that
707 * this is a first call. Application should
708 * use this reference to start the variable value
709 * extraction and return updated reference. If
710 * there is no more values left for this variable
711 * application should send HTTP_END_OF_VAR. If
712 * there are any bytes to send, application should
713 * return other than HTTP_START_OF_VAR and
714 * HTTP_END_OF_VAR reference.
715 *
716 * THIS IS AN EXAMPLE CALLBACK.
717 * MODIFY THIS AS PER YOUR REQUIREMENTS.
718 ********************************************************************/
719 #if defined(STACK_USE_HTTP_SERVER)
720 WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)
721 {
722 /*
723 * First of all identify variable.
724 */
725 switch(var)
726 {
727 case VAR_LED_D5:
728 if ( LATA3 )
729 *val = '0';
730 else
731 *val = '1';
732 break;
733
734 case VAR_LED_D6:
735 if ( LATA2 )
736 *val = '0';
737 else
738 *val = '1';
739 break;
740
741 case VAR_ANAIN_AN0:
742 if ( ref == HTTP_START_OF_VAR )
743 {
744 ref = (BYTE)0;
745 }
746 *val = AN0String[(BYTE)ref];
747 if ( AN0String[(BYTE)ref] == '\0' )
748 return HTTP_END_OF_VAR;
749
750 (BYTE)ref++;
751 return ref;
752
753 case VAR_ANAIN_AN1:
754 if ( ref == HTTP_START_OF_VAR )
755 {
756 ref = (BYTE)0;
757 }
758 *val = AN1String[(BYTE)ref];
759 if ( AN1String[(BYTE)ref] == '\0' )
760 return HTTP_END_OF_VAR;
761
762 (BYTE)ref++;
763 return ref;
764
765 case VAR_DIGIN_RB5:
766 if ( PORTB_RB5 )
767 *val = '1';
768 else
769 *val = '0';
770 break;
771 }
772
773 return HTTP_END_OF_VAR;
774 }
775 #endif
776
777
778 #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
779 ROM char FTP_USER_NAME[] = "ftp";
780 #undef FTP_USER_NAME_LEN
781 #define FTP_USER_NAME_LEN (sizeof(FTP_USER_NAME)-1)
782
783 ROM char FTP_USER_PASS[] = "microchip";
784 #define FTP_USER_PASS_LEN (sizeof(FTP_USER_PASS)-1)
785
786 BOOL FTPVerify(char *login, char *password)
787 {
788 if ( !memcmppgm2ram(login, (ROM void*)FTP_USER_NAME, FTP_USER_NAME_LEN) )
789 {
790 if ( !memcmppgm2ram(password, (ROM void*)FTP_USER_PASS, FTP_USER_PASS_LEN) )
791 return TRUE;
792 }
793 return FALSE;
794 }
795 #endif
796
797
798
799
800 /*********************************************************************
801 * Function: void InitializeBoard(void)
802 *
803 * PreCondition: None
804 *
805 * Input: None
806 *
807 * Output: None
808 *
809 * Side Effects: None
810 *
811 * Overview: Initialize board specific hardware.
812 *
813 * Note: None
814 ********************************************************************/
815 static void InitializeBoard(void)
816 {
817 /*
818 * Setup for PORTA.RA0 as analog input while rests
819 * as digital i/o lines.
820 */
821 ADCON1 = 0b10001110; // RA0 as analog input, Right justified
822 TRISA = 0x03;
823
824 /*
825 * LCD is enabled using RA5.
826 */
827 PORTA_RA5 = 0; // Disable LCD.
828
829 /*
830 * Turn off the LED's.
831 */
832 LATA2 = 1;
833 LATA3 = 1;
834
835 /*
836 * External data EEPROM needs pull-ups, so enable internal
837 * pull-ups.
838 */
839 INTCON2_RBPU = 0;
840
841 XLCDInit();
842 XLCDGoto(0, 0);
843 XLCDPutROMString(StartupMsg);
844
845
846 TXSTA = 0b00100000; // Low BRG speed
847 RCSTA = 0b10010000;
848 SPBRG = SPBRG_VAL;
849
850 T0CON = 0;
851 INTCON_GIEH = 1;
852 INTCON_GIEL = 1;
853
854 }
855
856 /*********************************************************************
857 * Function: void InitAppConfig(void)
858 *
859 * PreCondition: MPFSInit() is already called.
860 *
861 * Input: None
862 *
863 * Output: Write/Read non-volatile config variables.
864 *
865 * Side Effects: None
866 *
867 * Overview: None
868 *
869 * Note: None
870 ********************************************************************/
871 static void InitAppConfig(void)
872 {
873 #if defined(MPFS_USE_EEPROM)
874 BYTE c;
875 BYTE *p;
876 #endif
877
878 /*
879 * Load default configuration into RAM.
880 */
881 AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1;
882 AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2;
883 AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3;
884 AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4;
885
886 AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1;
887 AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2;
888 AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3;
889 AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4;
890
891 AppConfig.MyGateway.v[0] = MY_DEFAULT_GATE_BYTE1;
892 AppConfig.MyGateway.v[1] = MY_DEFAULT_GATE_BYTE2;
893 AppConfig.MyGateway.v[2] = MY_DEFAULT_GATE_BYTE3;
894 AppConfig.MyGateway.v[3] = MY_DEFAULT_GATE_BYTE4;
895
896 AppConfig.MyMACAddr.v[0] = MY_DEFAULT_MAC_BYTE1;
897 AppConfig.MyMACAddr.v[1] = MY_DEFAULT_MAC_BYTE2;
898 AppConfig.MyMACAddr.v[2] = MY_DEFAULT_MAC_BYTE3;
899 AppConfig.MyMACAddr.v[3] = MY_DEFAULT_MAC_BYTE4;
900 AppConfig.MyMACAddr.v[4] = MY_DEFAULT_MAC_BYTE5;
901 AppConfig.MyMACAddr.v[5] = MY_DEFAULT_MAC_BYTE6;
902
903 #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
904 AppConfig.Flags.bIsDHCPEnabled = TRUE;
905 #else
906 AppConfig.Flags.bIsDHCPEnabled = FALSE;
907 #endif
908
909 #if defined(MPFS_USE_EEPROM)
910 p = (BYTE*)&AppConfig;
911
912
913 XEEBeginRead(EEPROM_CONTROL, 0x00);
914 c = XEERead();
915 XEEEndRead();
916
917 /*
918 * When a record is saved, first byte is written as 0x55 to indicate
919 * that a valid record was saved.
920 */
921 if ( c == 0x55 )
922 {
923 XEEBeginRead(EEPROM_CONTROL, 0x01);
924 for ( c = 0; c < sizeof(AppConfig); c++ )
925 *p++ = XEERead();
926 XEEEndRead();
927 }
928 else
929 SaveAppConfig();
930 #endif
931 }
932
933 #if defined(MPFS_USE_EEPROM)
934 static void SaveAppConfig(void)
935 {
936 BYTE c;
937 BYTE *p;
938
939 p = (BYTE*)&AppConfig;
940 XEEBeginWrite(EEPROM_CONTROL, 0x00);
941 XEEWrite(0x55);
942 for ( c = 0; c < sizeof(AppConfig); c++ )
943 {
944 XEEWrite(*p++);
945 }
946
947 XEEEndWrite();
948 }
949 #endif
950
951 ROM char menu[] =
952 "\r\n\r\n\r\MCHPStack Demo Application v1.1 ("STARTUP_MSG", " __DATE__ ")\r\n\r\n"
953
954 "\t1: Change Board serial number.\r\n"
955 "\t2: Change default IP address.\r\n"
956 "\t3: Change default gateway address.\r\n"
957 "\t4: Change default subnet mask.\r\n"
958 "\t5: Enable DHCP & IP Gleaning.\r\n"
959 "\t6: Disable DHCP & IP Gleaning.\r\n"
960 "\t7: Download MPFS image.\r\n"
961 "\t8: Save & Quit.\r\n"
962 "\r\n"
963 "Enter a menu choice (1-8): ";
964
965 typedef enum _MENU_CMD
966 {
967 MENU_CMD_SERIAL_NUMBER = '1',
968 MENU_CMD_IP_ADDRESS,
969 MENU_CMD_GATEWAY_ADDRESS,
970 MENU_CMD_SUBNET_MASK,
971 MENU_CMD_ENABLE_AUTO_CONFIG,
972 MENU_CMD_DISABLE_AUTO_CONFIG,
973 MENU_CMD_DOWNLOAD_MPFS,
974 MENU_CMD_QUIT,
975 MENU_CMD_INVALID
976 } MENU_CMD;
977
978 ROM char* menuCommandPrompt[] =
979 {
980 "\r\nSerial Number (",
981 "\r\nDefault IP Address (",
982 "\r\nDefault Gateway Address (",
983 "\r\nDefault Subnet Mask (",
984 "\r\nDHCP & IP Gleaning enabled.\r\n",
985 "\r\nDHCP & IP Gleaning disabled.\r\n",
986 "\r\nReady to download MPFS image - Use Xmodem protocol.\r\n",
987 "\r\nNow running application..."
988 };
989
990 ROM char InvalidInputMsg[] = "\r\nInvalid input received - Input ignored.\r\n"
991 "Press any key to continue...\r\n";
992
993 void USARTPutROMString(ROM char* str)
994 {
995 BYTE v;
996
997 while( v = *str++ )
998 USARTPut(v);
999 }
1000
1001
1002 BYTE USARTGetString(char *buffer, BYTE bufferLen)
1003 {
1004 BYTE v;
1005 BYTE count;
1006
1007 count = 0;
1008 do
1009 {
1010 while( !USARTIsGetReady() );
1011
1012 v = USARTGet();
1013
1014 if ( v == '\r' || v == '\n' )
1015 break;
1016
1017 count++;
1018 *buffer++ = v;
1019 *buffer = '\0';
1020 if ( bufferLen-- == 0 )
1021 break;
1022 } while(1);
1023 return count;
1024 }
1025
1026 BOOL StringToIPAddress(char *str, IP_ADDR *buffer)
1027 {
1028 BYTE v;
1029 char *temp;
1030 BYTE byteIndex;
1031
1032 temp = str;
1033 byteIndex = 0;
1034
1035 while( v = *str )
1036 {
1037 if ( v == '.' )
1038 {
1039 *str++ = '\0';
1040 buffer->v[byteIndex++] = atoi(temp);
1041 temp = str;
1042 }
1043 else if ( v < '0' || v > '9' )
1044 return FALSE;
1045
1046 str++;
1047 }
1048
1049 buffer->v[byteIndex] = atoi(temp);
1050
1051 return (byteIndex == 3);
1052 }
1053
1054
1055
1056 MENU_CMD GetMenuChoice(void)
1057 {
1058 BYTE c;
1059
1060 while ( !USARTIsGetReady() );
1061
1062 c = USARTGet();
1063
1064 if ( c >= '1' && c < MENU_CMD_INVALID )
1065 return c;
1066 else
1067 return MENU_CMD_INVALID;
1068 }
1069
1070 #define MAX_USER_RESPONSE_LEN (20)
1071 void ExecuteMenuChoice(MENU_CMD choice)
1072 {
1073 char response[MAX_USER_RESPONSE_LEN];
1074 IP_ADDR tempIPValue;
1075 IP_ADDR *destIPValue;
1076
1077 USARTPut('\r');
1078 USARTPut('\n');
1079 USARTPutROMString(menuCommandPrompt[choice-'0'-1]);
1080
1081 switch(choice)
1082 {
1083 case MENU_CMD_SERIAL_NUMBER:
1084 itoa(AppConfig.SerialNumber.Val, response);
1085 USARTPutString((BYTE*)response);
1086 USARTPut(')');
1087 USARTPut(':');
1088 USARTPut(' ');
1089
1090 if ( USARTGetString(response, sizeof(response)) )
1091 {
1092 AppConfig.SerialNumber.Val = atoi(response);
1093
1094 AppConfig.MyMACAddr.v[4] = AppConfig.SerialNumber.v[1];
1095 AppConfig.MyMACAddr.v[5] = AppConfig.SerialNumber.v[0];
1096 }
1097 else
1098 goto HandleInvalidInput;
1099
1100 break;
1101
1102 case MENU_CMD_IP_ADDRESS:
1103 destIPValue = &AppConfig.MyIPAddr;
1104 goto ReadIPConfig;
1105
1106 case MENU_CMD_GATEWAY_ADDRESS:
1107 destIPValue = &AppConfig.MyGateway;
1108 goto ReadIPConfig;
1109
1110 case MENU_CMD_SUBNET_MASK:
1111 destIPValue = &AppConfig.MyMask;
1112
1113 ReadIPConfig:
1114 DisplayIPValue(destIPValue, FALSE);
1115 USARTPut(')');
1116 USARTPut(':');
1117 USARTPut(' ');
1118
1119 USARTGetString(response, sizeof(response));
1120
1121 if ( !StringToIPAddress(response, &tempIPValue) )
1122 {
1123 HandleInvalidInput:
1124 USARTPutROMString(InvalidInputMsg);
1125 while( !USARTIsGetReady() );
1126 USARTGet();
1127 }
1128 else
1129 {
1130 destIPValue->Val = tempIPValue.Val;
1131 }
1132 break;
1133
1134
1135 case MENU_CMD_ENABLE_AUTO_CONFIG:
1136 AppConfig.Flags.bIsDHCPEnabled = TRUE;
1137 break;
1138
1139 case MENU_CMD_DISABLE_AUTO_CONFIG:
1140 AppConfig.Flags.bIsDHCPEnabled = FALSE;
1141 break;
1142
1143 case MENU_CMD_DOWNLOAD_MPFS:
1144 #if defined(MPFS_USE_EEPROM)
1145 DownloadMPFS();
1146 #endif
1147 break;
1148
1149 case MENU_CMD_QUIT:
1150 #if defined(MPFS_USE_EEPROM)
1151 SaveAppConfig();
1152 #endif
1153 break;
1154 }
1155 }
1156
1157
1158
1159
1160 static void SetConfig(void)
1161 {
1162 MENU_CMD choice;
1163
1164 do
1165 {
1166 USARTPutROMString(menu);
1167 choice = GetMenuChoice();
1168 if ( choice != MENU_CMD_INVALID )
1169 ExecuteMenuChoice(choice);
1170 } while(choice != MENU_CMD_QUIT);
1171
1172 }
1173
1174
1175 #if defined(MPFS_USE_EEPROM)
1176
1177 /*********************************************************************
1178 * Function: BOOL DownloadMPFS(void)
1179 *
1180 * PreCondition: MPFSInit() is already called.
1181 *
1182 * Input: None
1183 *
1184 * Output: TRUE if successful
1185 * FALSE otherwise
1186 *
1187 * Side Effects: This function uses 128 bytes of Bank 4 using
1188 * indirect pointer. This requires that no part of
1189 * code is using this block during or before calling
1190 * this function. Once this function is done,
1191 * that block of memory is available for general use.
1192 *
1193 * Overview: This function implements XMODEM protocol to
1194 * be able to receive a binary file from PC
1195 * applications such as HyperTerminal.
1196 *
1197 * Note: In current version, this function does not
1198 * implement user interface to set IP address and
1199 * other informations. User should create their
1200 * own interface to allow user to modify IP
1201 * information.
1202 * Also, this version implements simple user
1203 * action to start file transfer. User may
1204 * evaulate its own requirement and implement
1205 * appropriate start action.
1206 *
1207 ********************************************************************/
1208 #define XMODEM_SOH 0x01
1209 #define XMODEM_EOT 0x04
1210 #define XMODEM_ACK 0x06
1211 #define XMODEM_NAK 0x15
1212 #define XMODEM_CAN 0x18
1213 #define XMODEM_BLOCK_LEN 128
1214
1215 static BOOL DownloadMPFS(void)
1216 {
1217 enum SM_MPFS
1218 {
1219 SM_MPFS_SOH,
1220 SM_MPFS_BLOCK,
1221 SM_MPFS_BLOCK_CMP,
1222 SM_MPFS_DATA,
1223 } state;
1224
1225 BYTE c;
1226 MPFS handle;
1227 BOOL lbDone;
1228 BYTE blockLen;
1229 BYTE lResult;
1230 BYTE tempData[XMODEM_BLOCK_LEN];
1231 TICK lastTick;
1232 TICK currentTick;
1233
1234 state = SM_MPFS_SOH;
1235 lbDone = FALSE;
1236
1237 handle = MPFSFormat();
1238
1239 /*
1240 * Notify the host that we are ready to receive...
1241 */
1242 lastTick = TickGet();
1243 do
1244 {
1245 /*
1246 * Update tick here too - just in case interrupt is not used.
1247 */
1248 TickUpdate();
1249
1250 currentTick = TickGet();
1251 if ( TickGetDiff(currentTick, lastTick) >= (TICK_SECOND/2) )
1252 {
1253 lastTick = TickGet();
1254 USARTPut(XMODEM_NAK);
1255
1256 /*
1257 * Blink LED to indicate that we are waiting for
1258 * host to send the file.
1259 */
1260 LATA2 ^= 1;
1261 }
1262
1263 } while( !USARTIsGetReady() );
1264
1265
1266 while(!lbDone)
1267 {
1268 /*
1269 * Update tick here too - just in case interrupt is not used.
1270 */
1271 TickUpdate();
1272
1273 if ( USARTIsGetReady() )
1274 {
1275 /*
1276 * Toggle LED as we receive the data from host.
1277 */
1278 LATA2 ^= 1;
1279 c = USARTGet();
1280 }
1281 else
1282 {
1283 /*
1284 * Real application should put some timeout to make sure
1285 * that we do not wait forever.
1286 */
1287 continue;
1288 }
1289
1290 switch(state)
1291 {
1292 default:
1293 if ( c == XMODEM_SOH )
1294 {
1295 state = SM_MPFS_BLOCK;
1296 }
1297 else if ( c == XMODEM_EOT )
1298 {
1299 /*
1300 * Turn off LED when we are done.
1301 */
1302 LATA2 = 1;
1303
1304 MPFSClose();
1305 USARTPut(XMODEM_ACK);
1306 lbDone = TRUE;
1307 }
1308 else
1309 USARTPut(XMODEM_NAK);
1310
1311 break;
1312
1313 case SM_MPFS_BLOCK:
1314 /*
1315 * We do not use block information.
1316 */
1317 lResult = XMODEM_ACK;
1318 blockLen = 0;
1319 state = SM_MPFS_BLOCK_CMP;
1320 break;
1321
1322 case SM_MPFS_BLOCK_CMP:
1323 /*
1324 * We do not use 1's comp. block value.
1325 */
1326 state = SM_MPFS_DATA;
1327 break;
1328
1329 case SM_MPFS_DATA:
1330 /*
1331 * Buffer block data until it is over.
1332 */
1333 tempData[blockLen++] = c;
1334 if ( blockLen > XMODEM_BLOCK_LEN )
1335 {
1336 /*
1337 * We have one block data.
1338 * Write it to EEPROM.
1339 */
1340 MPFSPutBegin(handle);
1341
1342 lResult = XMODEM_ACK;
1343 for ( c = 0; c < XMODEM_BLOCK_LEN; c++ )
1344 MPFSPut(tempData[c]);
1345
1346 handle = MPFSPutEnd();
1347
1348 USARTPut(lResult);
1349 state = SM_MPFS_SOH;
1350 }
1351 break;
1352
1353 }
1354
1355 }
1356
1357
1358 /*
1359 * This small wait is required if SLIP is in use.
1360 * If this is not used, PC might misinterpret SLIP
1361 * module communication and never close file transfer
1362 * dialog box.
1363 */
1364 #if defined(STACK_USE_SLIP)
1365 {
1366 BYTE i;
1367 i = 255;
1368 while( i-- );
1369 }
1370 #endif
1371 return TRUE;
1372 }
1373
1374 #endif
1375
1376
1377 void XLCDDelay15ms(void)
1378 {
1379 DelayMs(15);
1380 }
1381 void XLCDDelay4ms(void)
1382 {
1383 DelayMs(4);
1384 }
1385
1386 void XLCDDelay100us(void)
1387 {
1388 INTCON_GIEH = 0;
1389 Delay10us(1);
1390 INTCON_GIEH = 1;
1391 }

  ViewVC Help
Powered by ViewVC 1.1.20