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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide 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 hedin 62 /*********************************************************************
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