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

Annotation of /trunk/docs/MCHPStack2.20/Source/MasterDemo.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: 44752 byte(s)
Removed tcpip stack 4.02 and added tcpip stack 2.20.
1 hedin 62 /*********************************************************************
2     *
3     * One Example that includes all Microchip Stack modules
4     *
5     *********************************************************************
6     * FileName: DemoAll.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 6/20/01 Original (Rev. 1.0)
48     ********************************************************************/
49    
50     /*
51     * Following define uniquely deines this file as main
52     * entry/application In whole project, there should only be one such
53     * definition and application file must define AppConfig variable as
54     * described below.
55     */
56     #define THIS_IS_STACK_APPLICATION
57    
58     #define BAUD_RATE (19200) // bps
59    
60     #define USART_USE_BRGH_LOW
61     #if defined(USART_USE_BRGH_LOW)
62     #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/64) - 1)
63     #else
64     #define SPBRG_VAL ( ((CLOCK_FREQ/BAUD_RATE)/16) - 1)
65     #endif
66    
67     #if SPBRG_VAL > 255
68     #error "Calculated SPBRG value is out of range for currnet CLOCK_FREQ."
69     #endif
70    
71    
72    
73     #include <string.h>
74    
75     /*
76     * These headers must be included for required defs.
77     */
78     #include "stacktsk.h"
79     #include "tick.h"
80    
81     #if defined(STACK_USE_DHCP)
82     #include "dhcp.h"
83     #endif
84    
85     #if defined(STACK_USE_HTTP_SERVER)
86     #include "http.h"
87     #endif
88    
89     #include "mpfs.h"
90    
91     #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
92     #include "ftp.h"
93     #endif
94    
95     #if defined(STACK_USE_SNMP_SERVER)
96     #include "snmp.h"
97     #include "mib.h"
98     #endif
99    
100     #include "xlcd.h"
101    
102     #if defined(MPFS_USE_EEPROM)
103     #include "xeeprom.h"
104     #endif
105    
106    
107     // For debug only.
108     #include "tcp.h"
109     #include "icmp.h"
110    
111     #include "delay.h"
112    
113     #define STARTUP_MSG "MpStack 2.20+"
114    
115     ROM char StartupMsg[] = STARTUP_MSG;
116     ROM char InitializingMsg[] = "Initializing...";
117    
118     #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
119     ROM char DHCPMsg[] = "DHCP/Gleaning...";
120     #endif
121    
122     ROM char SetupMsg[] = "Board Setup...";
123    
124    
125     /*
126     * These are hardware I/O labels to ease access.
127     */
128     #define SW_S3 PORTB_RB5
129     #define LED_D5_CONTROL LATA2
130     #define LED_D6_CONTROL LATA3
131    
132     /*
133     * Analog pots.
134     */
135     static WORD_VAL AN0Value;
136     static WORD_VAL AN1Value;
137    
138    
139     /*
140     * LCD Display
141     */
142     #define LCD_DISPLAY_LEN (16)
143     char LCDDisplayString[LCD_DISPLAY_LEN] = STARTUP_MSG;
144     BYTE LCDDisplayStringLen = sizeof(STARTUP_MSG)-1;
145    
146     /*
147     * Trap information.
148     * This table maintains list of intereseted receivers
149     * who should receive notifications when some interesting
150     * event occurs.
151     */
152     #define TRAP_TABLE_SIZE (2)
153     #define MAX_COMMUNITY_LEN (8)
154     typedef struct _TRAP_INFO
155     {
156     BYTE Size;
157     struct
158     {
159     BYTE communityLen;
160     char community[MAX_COMMUNITY_LEN];
161     IP_ADDR IPAddress;
162     struct
163     {
164     unsigned int bEnabled : 1;
165     } Flags;
166     } table[TRAP_TABLE_SIZE];
167     } TRAP_INFO;
168    
169     /*
170     * Initialize trap table with no entries.
171     */
172     TRAP_INFO trapInfo = { TRAP_TABLE_SIZE };
173    
174    
175     /*
176     * This is used by other stack elements.
177     * Main application must define this and initialize it with
178     * proper values.
179     */
180     APP_CONFIG AppConfig;
181    
182     BYTE myDHCPBindCount = 0;
183     #if defined(STACK_USE_DHCP)
184     extern BYTE DHCPBindCount;
185     #else
186     /*
187     * If DHCP is not enabled, force DHCP update.
188     */
189     BYTE DHCPBindCount = 1;
190     #endif
191    
192     #if defined(MCHP_C18) && defined(__18F8720)
193     #define TXSTAbits TXSTA1bits
194     #define TXREG TXREG1
195     #define TXSTA TXSTA1
196     #define RCSTA RCSTA1
197     #define SPBRG SPBRG1
198     #define RCREG RCREG1
199     #endif
200    
201    
202     /*
203     * Set configuration fuses for HITECH compiler.
204     * For MCC18 compiler, separately linked config.asm file
205     * will set the correct fuses.
206     */
207     #if defined(HITECH_C18)
208     __CONFIG(1, UNPROTECT & HS);
209     __CONFIG(2, PWRTEN & BORDIS & WDTDIS);
210     #endif
211    
212     /*
213     * Private helper functions.
214     * These may or may not be present in all applications.
215     */
216     static void InitAppConfig(void);
217    
218     static void InitializeBoard(void);
219     static void ProcessIO(void);
220    
221     void NotifyRemoteUser(void);
222     static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD);
223     static void SetConfig(void);
224    
225     #if defined(STACK_USE_SNMP_SERVER)
226     static BOOL SendNotification(BYTE receiverIndex, SNMP_ID var, SNMP_VAL val);
227     #endif
228    
229    
230     #if defined(MPFS_USE_EEPROM)
231     static BOOL DownloadMPFS(void);
232     static void SaveAppConfig(void);
233     #endif
234    
235     #if defined(MCHP_C18)
236     #pragma interrupt HighISR save=section(".tmpdata")
237     void HighISR(void)
238     #elif defined(HITECH_C18)
239     #if defined(STACK_USE_SLIP)
240     extern void MACISR(void);
241     #endif
242     void interrupt HighISR(void)
243     #endif
244     {
245     TickUpdate();
246    
247     #if defined(STACK_USE_SLIP)
248     MACISR();
249     #endif
250     }
251    
252     #if defined(MCHP_C18)
253     #pragma code highVector=0x08
254     void HighVector (void)
255     {
256     _asm goto HighISR _endasm
257     }
258     #pragma code /* return to default code section */
259     #endif
260    
261    
262    
263     static void USARTPut(BYTE c)
264     {
265     while( !TXSTA_TRMT);
266     TXREG = c;
267     }
268    
269     static void USARTPutString(BYTE *s)
270     {
271     BYTE c;
272    
273     while( (c = *s++) )
274     USARTPut(c);
275     }
276    
277     #define USARTIsGetReady() (PIR1_RCIF)
278     #define USARTGet() (RCREG)
279    
280    
281    
282     /*
283     * Main entry point.
284     */
285     void main(void)
286     {
287     static TICK t = 0;
288    
289     /*
290     * Initialize any application specific hardware.
291     */
292     InitializeBoard();
293    
294     /*
295     * Initialize all stack related components.
296     * Following steps must be performed for all applications using
297     * PICmicro TCP/IP Stack.
298     */
299     TickInit();
300    
301     /*
302     * Following steps must be performed for all applications using
303     * PICmicro TCP/IP Stack.
304     */
305     MPFSInit();
306    
307    
308     /*
309     * Initialize Stack and application related NV variables.
310     */
311     InitAppConfig();
312    
313    
314     /*
315     * Depending on whether internal program memor is used or external
316     * EEPROM is used, keep/remove these block.
317     */
318    
319     /*
320     * This implementation, initiates Board setup process if RB5
321     * is detected low on startup.
322     */
323     if ( PORTB_RB5 == 0 )
324     {
325     XLCDGoto(1, 0);
326     XLCDPutROMString(SetupMsg);
327    
328     SetConfig();
329     }
330    
331     StackInit();
332    
333     #if defined(STACK_USE_HTTP_SERVER)
334     HTTPInit();
335     #endif
336    
337     #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
338     FTPInit();
339     #endif
340    
341     #if defined(STACK_USE_SNMP_SERVER)
342     SNMPInit();
343     #endif
344    
345    
346     #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
347     if ( AppConfig.Flags.bIsDHCPEnabled )
348     {
349     XLCDGoto(1, 0);
350     XLCDPutROMString(DHCPMsg);
351     }
352     else
353     {
354     /*
355     * Force IP address display update.
356     */
357     myDHCPBindCount = 1;
358     #if defined(STACK_USE_DHCP)
359     DHCPDisable();
360     #endif
361     }
362     #endif
363    
364    
365    
366     /*
367     * Once all items are initialized, go into infinite loop and let
368     * stack items execute their tasks.
369     * If application needs to perform its own task, it should be
370     * done at the end of while loop.
371     * Note that this is a "co-operative mult-tasking" mechanism
372     * where every task performs its tasks (whether all in one shot
373     * or part of it) and returns so that other tasks can do their
374     * job.
375     * If a task needs very long time to do its job, it must broken
376     * down into smaller pieces so that other tasks can have CPU time.
377     */
378     while(1)
379     {
380     /*
381     * Blink SYSTEM LED every second.
382     */
383     if ( TickGetDiff(TickGet(), t) >= TICK_SECOND/2 )
384     {
385     t = TickGet();
386     LATA4 ^= 1;
387     }
388    
389     /*
390     * This task performs normal stack task including checking
391     * for incoming packet, type of packet and calling
392     * appropriate stack entity to process it.
393     */
394     StackTask();
395    
396     #if defined(STACK_USE_HTTP_SERVER)
397     /*
398     * This is a TCP application. It listens to TCP port 80
399     * with one or more sockets and responds to remote requests.
400     */
401     HTTPServer();
402     #endif
403    
404     #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
405     FTPServer();
406     #endif
407    
408    
409     #if defined(STACK_USE_SNMP_SERVER)
410     /*
411     * This task performs common SNMP Agent tasks. When
412     * a request is received and processed,
413     * it callbacks to application.
414     */
415     SNMPTask();
416     #endif
417    
418     /*
419     * In future, as new TCP/IP applications are written, it
420     * will be added here as new tasks.
421     */
422    
423     /*
424     * Add your application speicifc tasks here.
425     */
426     ProcessIO();
427    
428     /*
429     * For DHCP information, display how many times we have renewed the IP
430     * configuration since last reset.
431     */
432     if ( DHCPBindCount != myDHCPBindCount )
433     {
434     DisplayIPValue(&AppConfig.MyIPAddr, TRUE);
435     myDHCPBindCount = DHCPBindCount;
436    
437     if ( AppConfig.Flags.bIsDHCPEnabled )
438     {
439     XLCDGoto(1, 14);
440     if ( myDHCPBindCount < 0x0a )
441     XLCDPut(myDHCPBindCount + '0');
442     else
443     XLCDPut(myDHCPBindCount + 'A');
444     }
445     }
446    
447     }
448     }
449    
450     // 1234567890123456
451     ROM char blankLCDLine[] = " ";
452    
453     static void DisplayIPValue(IP_ADDR *IPVal, BOOL bToLCD)
454     {
455     char IPDigit[8];
456    
457     if ( bToLCD )
458     {
459     /*
460     * Erase second line.
461     */
462     XLCDGoto(1, 0);
463     XLCDPutROMString(blankLCDLine);
464    
465     }
466    
467     /*
468     * Rewrite the second line.
469     */
470     XLCDGoto(1, 0);
471    
472     itoa(IPVal->v[0], IPDigit);
473     if ( bToLCD )
474     {
475     XLCDPutString(IPDigit);
476     XLCDPut('.');
477     }
478     else
479     {
480     USARTPutString((BYTE*)IPDigit);
481     USARTPut('.');
482     }
483    
484     itoa(IPVal->v[1], IPDigit);
485     if ( bToLCD )
486     {
487     XLCDPutString(IPDigit);
488     XLCDPut('.');
489     }
490     else
491     {
492     USARTPutString((BYTE*)IPDigit);
493     USARTPut('.');
494     }
495    
496     itoa(IPVal->v[2], IPDigit);
497     if ( bToLCD )
498     {
499     XLCDPutString(IPDigit);
500     XLCDPut('.');
501     }
502     else
503     {
504     USARTPutString((BYTE*)IPDigit);
505     USARTPut('.');
506     }
507    
508     itoa(IPVal->v[3], IPDigit);
509     if ( bToLCD )
510     XLCDPutString(IPDigit);
511     else
512     USARTPutString((BYTE*)IPDigit);
513     }
514    
515    
516    
517     static char AN0String[8];
518     static char AN1String[8];
519    
520    
521     static void ProcessIO(void)
522     {
523     #if defined(STACK_USE_SNMP_SERVER)
524     static BOOL lbNotify = FALSE;
525     static BYTE i = 0;
526     SNMP_VAL val;
527    
528     if ( PORTB_RB5 == 0 && !lbNotify )
529     lbNotify = TRUE;
530    
531     if ( i == trapInfo.Size )
532     {
533     i = 0;
534     lbNotify = FALSE;
535     }
536    
537     if ( lbNotify )
538     {
539     if ( trapInfo.table[i].Flags.bEnabled )
540     {
541     val.byte = 0;
542     if ( SendNotification(i, PUSH_BUTTON, val) )
543     i++;
544     }
545     else
546     i++;
547     }
548     #endif
549    
550     /*
551     * Select AN0 channel, Fosc/32 clock
552     */
553     ADCON0 = 0b10000001;
554    
555     /*
556     * Wait for acquisition time.
557     * Here, rather than waiting for exact time, a simple wait is
558     * used. Real applications requiring high accuracy should
559     * calculate exact acquisition time and wait accordingly.
560     */
561     AN0Value.v[0] = 100;
562     while( AN0Value.v[0]-- );
563    
564     /*
565     * First convert AN0 channel.
566     * AN0 is already setup as an analog input.
567     */
568     ADCON0_GO = 1;
569    
570     /*
571     * Wait until conversion is done.
572     */
573     while( ADCON0_GO );
574    
575     /*
576     * Save the result.
577     */
578     AN0Value.v[0] = ADRESL;
579     AN0Value.v[1] = ADRESH;
580    
581     /*
582     * Convert 10-bit value into ASCII String.
583     */
584     itoa(AN0Value.Val, AN0String);
585    
586     /*
587     * Now, convert AN1 channel.
588     *
589     * In PICDEM.net board, RA2 thru RA7 should be digital or else
590     * LED, LCD and NIC would not operate correctly.
591     * Since there is no mode where only AN0 and AN1 be analog inputs
592     * while rests are digial pins, we will temperoraily switch
593     * select a mode where RA2 becomes analog input while we do
594     * conversion of RA1. Once conversion is done, we will convert
595     * RA2 back to digital pin.
596     */
597     //ADCON1 = 0b10000100;
598     /*
599     * For 8720, there is a mode where AN0 and AN1 will be analog
600     * while rests digital
601     */
602     ADCON1 = 0b00001101;
603    
604     /*
605     * Select AN1 channel.
606     */
607     ADCON0 = 0b10001001;
608    
609     /*
610     * Wait for acquisition time.
611     * Here, rather than waiting for exact time, a simple wait is
612     * used. Real applications requiring high accuracy should
613     * calculate exact acquisition time and wait accordingly.
614     */
615     AN1Value.v[0] = 100;
616     while( AN1Value.v[0]-- );
617    
618     /*
619     * Start the conversion.
620     */
621     ADCON0_GO = 1;
622    
623     /*
624     * Wait until it is done.
625     */
626     while( ADCON0_GO );
627    
628     /*
629     * Save the result.
630     */
631     AN1Value.v[0] = ADRESL;
632     AN1Value.v[1] = ADRESH;
633    
634     /*
635     * Convert 10-bit value into ASCII String.
636     */
637     itoa(AN1Value.Val, AN1String);
638    
639     /*
640     * Reset RA2 pin back to digital output.
641     */
642     ADCON1 = 0b10001110; // RA0 as analog input.
643    
644     }
645    
646     /*
647     * CGI Command Codes.
648     */
649     #define CGI_CMD_DIGOUT (0)
650     #define CGI_CMD_LCDOUT (1)
651    
652     /*
653     * CGI Variable codes. - There could be 0-255 variables.
654     */
655     #define VAR_LED_D5 (0)
656     #define VAR_LED_D6 (1)
657     #define VAR_ANAIN_AN0 (2)
658     #define VAR_ANAIN_AN1 (3)
659     #define VAR_DIGIN_RB5 (4)
660     #define VAR_STROUT_LCD (5)
661    
662     /*********************************************************************
663     * Function: void HTTPExecCmd(BYTE** argv, BYTE argc)
664     *
665     * PreCondition: None
666     *
667     * Input: argv - List of arguments
668     * argc - Argument count.
669     *
670     * Output: None
671     *
672     * Side Effects: None
673     *
674     * Overview: This function is a "callback" from HTTPServer
675     * task. Whenever a remote node performs
676     * interactive task on page that was served,
677     * HTTPServer calls this functions with action
678     * arguments info.
679     * Main application should interpret this argument
680     * and act accordingly.
681     *
682     * Following is the format of argv:
683     * If HTTP action was : thank.htm?name=Joe&age=25
684     * argv[0] => thank.htm
685     * argv[1] => name
686     * argv[2] => Joe
687     * argv[3] => age
688     * argv[4] => 25
689     *
690     * Use argv[0] as a command identifier and rests
691     * of the items as command arguments.
692     *
693     * Note: THIS IS AN EXAMPLE CALLBACK.
694     ********************************************************************/
695     #if defined(STACK_USE_HTTP_SERVER)
696    
697     ROM char COMMANDS_OK_PAGE[] = "COMMANDS.CGI";
698    
699     // Copy string with NULL termination.
700     #define COMMANDS_OK_PAGE_LEN (sizeof(COMMANDS_OK_PAGE))
701    
702     ROM char CMD_UNKNOWN_PAGE[] = "INDEX.HTM";
703    
704     // Copy string with NULL termination.
705     #define CMD_UNKNOWN_PAGE_LEN (sizeof(CMD_UNKNOWN_PAGE))
706    
707     void HTTPExecCmd(BYTE** argv, BYTE argc)
708     {
709     BYTE command;
710     BYTE var;
711    
712     /*
713     * Design your pages such that they contain command code
714     * as a one character numerical value.
715     * Being a one character numerical value greatly simplifies
716     * the job.
717     */
718     command = argv[0][0] - '0';
719    
720     /*
721     * Find out the cgi file name and interpret parameters
722     * accordingly
723     */
724     switch(command)
725     {
726     case CGI_CMD_DIGOUT:
727     /*
728     * This DIGOUTS.CGI. Any arguments with this file
729     * must be about controlling digital outputs.
730     */
731    
732     /*
733     * Identify the parameters.
734     * Compare it in upper case format.
735     */
736     var = argv[1][0] - '0';
737    
738     switch(var)
739     {
740     case VAR_LED_D5:
741     /*
742     * This is "D5".
743     * Toggle D5.
744     */
745     LATA3 ^= 1;
746     break;
747    
748     case VAR_LED_D6:
749     /*
750     * This is "D6".
751     * Toggle it.
752     */
753     LATA2 ^= 1;
754     break;
755     }
756    
757     memcpypgm2ram((void*)argv[0],
758     (ROM void*)COMMANDS_OK_PAGE, COMMANDS_OK_PAGE_LEN);
759     break;
760    
761     case CGI_CMD_LCDOUT:
762     /*
763     * Note implemented.
764     */
765     break;
766    
767     default:
768     memcpypgm2ram((void*)argv[0],
769     (ROM void*)CMD_UNKNOWN_PAGE, CMD_UNKNOWN_PAGE_LEN);
770     break;
771     }
772    
773     }
774     #endif
775    
776    
777     /*********************************************************************
778     * Function: WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)
779     *
780     * PreCondition: None
781     *
782     * Input: var - Variable Identifier
783     * ref - Current callback reference with
784     * respect to 'var' variable.
785     * val - Buffer for value storage.
786     *
787     * Output: Variable reference as required by application.
788     *
789     * Side Effects: None
790     *
791     * Overview: This is a callback function from HTTPServer() to
792     * main application.
793     * Whenever a variable substitution is required
794     * on any html pages, HTTPServer calls this function
795     * 8-bit variable identifier, variable reference,
796     * which indicates whether this is a first call or
797     * not. Application should return one character
798     * at a time as a variable value.
799     *
800     * Note: Since this function only allows one character
801     * to be returned at a time as part of variable
802     * value, HTTPServer() calls this function
803     * multiple times until main application indicates
804     * that there is no more value left for this
805     * variable.
806     * On begining, HTTPGetVar() is called with
807     * ref = HTTP_START_OF_VAR to indicate that
808     * this is a first call. Application should
809     * use this reference to start the variable value
810     * extraction and return updated reference. If
811     * there is no more values left for this variable
812     * application should send HTTP_END_OF_VAR. If
813     * there are any bytes to send, application should
814     * return other than HTTP_START_OF_VAR and
815     * HTTP_END_OF_VAR reference.
816     *
817     * THIS IS AN EXAMPLE CALLBACK.
818     * MODIFY THIS AS PER YOUR REQUIREMENTS.
819     ********************************************************************/
820     #if defined(STACK_USE_HTTP_SERVER)
821     WORD HTTPGetVar(BYTE var, WORD ref, BYTE* val)
822     {
823     /*
824     * First of all identify variable.
825     */
826     switch(var)
827     {
828     case VAR_LED_D5:
829     if ( LATA3 )
830     *val = '0';
831     else
832     *val = '1';
833     break;
834    
835     case VAR_LED_D6:
836     if ( LATA2 )
837     *val = '0';
838     else
839     *val = '1';
840     break;
841    
842     case VAR_ANAIN_AN0:
843     if ( ref == HTTP_START_OF_VAR )
844     {
845     ref = (BYTE)0;
846     }
847     *val = AN0String[(BYTE)ref];
848     if ( AN0String[(BYTE)ref] == '\0' )
849     return HTTP_END_OF_VAR;
850    
851     (BYTE)ref++;
852     return ref;
853    
854     case VAR_ANAIN_AN1:
855     if ( ref == HTTP_START_OF_VAR )
856     {
857     ref = (BYTE)0;
858     }
859     *val = AN1String[(BYTE)ref];
860     if ( AN1String[(BYTE)ref] == '\0' )
861     return HTTP_END_OF_VAR;
862    
863     (BYTE)ref++;
864     return ref;
865    
866     case VAR_DIGIN_RB5:
867     if ( PORTB_RB5 )
868     *val = '1';
869     else
870     *val = '0';
871     break;
872     }
873    
874     return HTTP_END_OF_VAR;
875     }
876     #endif
877    
878    
879     #if defined(STACK_USE_FTP_SERVER) && defined(MPFS_USE_EEPROM)
880     ROM char FTP_USER_NAME[] = "ftp";
881     #undef FTP_USER_NAME_LEN
882     #define FTP_USER_NAME_LEN (sizeof(FTP_USER_NAME)-1)
883    
884     ROM char FTP_USER_PASS[] = "microchip";
885     #define FTP_USER_PASS_LEN (sizeof(FTP_USER_PASS)-1)
886    
887     BOOL FTPVerify(char *login, char *password)
888     {
889     if ( !memcmppgm2ram(login, (ROM void*)FTP_USER_NAME, FTP_USER_NAME_LEN) )
890     {
891     if ( !memcmppgm2ram(password, (ROM void*)FTP_USER_PASS, FTP_USER_PASS_LEN) )
892     return TRUE;
893     }
894     return FALSE;
895     }
896     #endif
897    
898    
899     #if defined(STACK_USE_SNMP_SERVER)
900    
901     static BOOL SendNotification(BYTE receiverIndex, SNMP_ID var, SNMP_VAL val)
902     {
903     static enum { SM_PREPARE, SM_NOTIFY_WAIT } smState = SM_PREPARE;
904     IP_ADDR IPAddress;
905    
906     // Convert local to network order.
907     IPAddress.v[0] = trapInfo.table[receiverIndex].IPAddress.v[3];
908     IPAddress.v[1] = trapInfo.table[receiverIndex].IPAddress.v[2];
909     IPAddress.v[2] = trapInfo.table[receiverIndex].IPAddress.v[1];
910     IPAddress.v[3] = trapInfo.table[receiverIndex].IPAddress.v[0];
911    
912     switch(smState)
913     {
914     case SM_PREPARE:
915     SNMPNotifyPrepare(&IPAddress,
916     trapInfo.table[receiverIndex].community,
917     trapInfo.table[receiverIndex].communityLen,
918     MICROCHIP, // Agent ID Var
919     6, // Notification code
920     (DWORD)TickGet());
921     smState = SM_NOTIFY_WAIT;
922    
923     break;
924    
925     case SM_NOTIFY_WAIT:
926     if ( SNMPIsNotifyReady(&IPAddress) )
927     {
928     smState = SM_PREPARE;
929     SNMPNotify(var, val, 0);
930     return TRUE;
931     }
932     }
933     return FALSE;
934     }
935    
936     BOOL SNMPValidate(SNMP_ACTION SNMPAction, char* community)
937     {
938     return TRUE;
939     }
940    
941    
942    
943     // Only dynamic variables with ASCII_STRING or OCTET_STRING data type
944     // needs to be handled.
945     BOOL SNMPIsValidSetLen(SNMP_ID var, BYTE len)
946     {
947     switch(var)
948     {
949     case TRAP_COMMUNITY:
950     if ( len < MAX_COMMUNITY_LEN+1 )
951     return TRUE;
952     break;
953    
954     case LCD_DISPLAY:
955     if ( len < LCD_DISPLAY_LEN+1 )
956     return TRUE;
957     break;
958     }
959     return FALSE;
960     }
961    
962    
963     // Only dynamic read-write variables needs to be handled.
964     BOOL SNMPSetVar(SNMP_ID var, SNMP_INDEX index, BYTE ref, SNMP_VAL val)
965     {
966     switch(var)
967     {
968     case LED_D5:
969     LED_D5_CONTROL = val.byte;
970     return TRUE;
971    
972     case LED_D6:
973     LED_D6_CONTROL = val.byte;
974     return TRUE;
975    
976     case TRAP_RECEIVER_IP:
977     // Make sure that index is within our range.
978     if ( index < trapInfo.Size )
979     {
980     // This is just an update to an existing entry.
981     trapInfo.table[index].IPAddress.Val = val.dword;
982     return TRUE;
983     }
984     else if ( index < TRAP_TABLE_SIZE )
985     {
986     // This is an addition to table.
987     trapInfo.table[index].IPAddress.Val = val.dword;
988     trapInfo.table[index].communityLen = 0;
989     trapInfo.Size++;
990     return TRUE;
991     }
992     break;
993    
994     case TRAP_RECEIVER_ENABLED:
995     // Make sure that index is within our range.
996     if ( index < trapInfo.Size )
997     {
998     // Value of '1' means Enabled".
999     if ( val.byte == 1 )
1000     trapInfo.table[index].Flags.bEnabled = 1;
1001     // Value of '0' means "Disabled.
1002     else if ( val.byte == 0 )
1003     trapInfo.table[index].Flags.bEnabled = 0;
1004     else
1005     // This is unknown value.
1006     return FALSE;
1007     return TRUE;
1008     }
1009     // Given index is more than our current table size.
1010     // If it is within our range, treat it as an addition to table.
1011     else if ( index < TRAP_TABLE_SIZE )
1012     {
1013     // Treat this as an addition to table.
1014     trapInfo.Size++;
1015     trapInfo.table[index].communityLen = 0;
1016     }
1017    
1018     break;
1019    
1020     case TRAP_COMMUNITY:
1021     // Since this is a ASCII_STRING data type, SNMP will call with
1022     // SNMP_END_OF_VAR to indicate no more bytes.
1023     // Use this information to determine if we just added new row
1024     // or updated an existing one.
1025     if ( ref == SNMP_END_OF_VAR )
1026     {
1027     // Index equal to table size means that we have new row.
1028     if ( index == trapInfo.Size )
1029     trapInfo.Size++;
1030    
1031     // Length of string is one more than index.
1032     trapInfo.table[index].communityLen++;
1033    
1034     return TRUE;
1035     }
1036    
1037     // Make sure that index is within our range.
1038     if ( index < trapInfo.Size )
1039     {
1040     // Copy given value into local buffer.
1041     trapInfo.table[index].community[ref] = val.byte;
1042     // Keep track of length too.
1043     // This may not be NULL terminate string.
1044     trapInfo.table[index].communityLen = (BYTE)ref;
1045     return TRUE;
1046     }
1047     break;
1048    
1049     case LCD_DISPLAY:
1050     // Copy all bytes until all bytes are transferred
1051     if ( ref != SNMP_END_OF_VAR )
1052     {
1053     LCDDisplayString[ref] = val.byte;
1054     LCDDisplayStringLen++;
1055     }
1056     else
1057     {
1058     XLCDGoto(0, 0);
1059     XLCDPutString(LCDDisplayString);
1060     }
1061    
1062     return TRUE;
1063    
1064     }
1065    
1066     return FALSE;
1067     }
1068    
1069     // Only sequence index needs to be handled in this function.
1070     BOOL SNMPGetNextIndex(SNMP_ID var, SNMP_INDEX *index)
1071     {
1072     SNMP_INDEX tempIndex;
1073    
1074     tempIndex = *index;
1075    
1076     switch(var)
1077     {
1078     case TRAP_RECEIVER_ID:
1079     // There is no next possible index if table itself is empty.
1080     if ( trapInfo.Size == 0 )
1081     return FALSE;
1082    
1083     // INDEX_INVALID means start with first index.
1084     if ( tempIndex == SNMP_INDEX_INVALID )
1085     {
1086     *index = 0;
1087     return TRUE;
1088     }
1089     else if ( tempIndex < (trapInfo.Size-1) )
1090     {
1091     *index = tempIndex+1;
1092     return TRUE;
1093     }
1094     break;
1095     }
1096     return FALSE;
1097     }
1098    
1099    
1100     BOOL SNMPGetVar(SNMP_ID var, SNMP_INDEX index, BYTE *ref, SNMP_VAL* val)
1101     {
1102     BYTE myRef;
1103    
1104     myRef = *ref;
1105    
1106     switch(var)
1107     {
1108     case SYS_UP_TIME:
1109     val->dword = TickGet();
1110     return TRUE;
1111    
1112     case LED_D5:
1113     val->byte = LED_D5_CONTROL;
1114     return TRUE;
1115    
1116     case LED_D6:
1117     val->byte = LED_D6_CONTROL;
1118     return TRUE;
1119    
1120     case PUSH_BUTTON:
1121     // There is only one button - meaning only index of 0 is allowed.
1122     val->byte = SW_S3;
1123     return TRUE;
1124    
1125     case ANALOG_POT0:
1126     val->word = AN0Value.Val;
1127     return TRUE;
1128    
1129     case ANALOG_POT1:
1130     val->word = AN1Value.Val;
1131     return TRUE;
1132    
1133     case TRAP_RECEIVER_ID:
1134     if ( index < trapInfo.Size )
1135     {
1136     val->byte = index;
1137     return TRUE;
1138     }
1139     break;
1140    
1141     case TRAP_RECEIVER_ENABLED:
1142     if ( index < trapInfo.Size )
1143     {
1144     val->byte = trapInfo.table[index].Flags.bEnabled;
1145     return TRUE;
1146     }
1147     break;
1148    
1149     case TRAP_RECEIVER_IP:
1150     if ( index < trapInfo.Size )
1151     {
1152     val->dword = trapInfo.table[index].IPAddress.Val;
1153     return TRUE;
1154     }
1155     break;
1156    
1157     case TRAP_COMMUNITY:
1158     if ( index < trapInfo.Size )
1159     {
1160     if ( trapInfo.table[index].communityLen == 0 )
1161     *ref = SNMP_END_OF_VAR;
1162     else
1163     {
1164     val->byte = trapInfo.table[index].community[myRef];
1165    
1166     myRef++;
1167    
1168     if ( myRef == trapInfo.table[index].communityLen )
1169     *ref = SNMP_END_OF_VAR;
1170     else
1171     *ref = myRef;
1172     }
1173     return TRUE;
1174     }
1175     break;
1176    
1177     case LCD_DISPLAY:
1178     if ( LCDDisplayStringLen == 0 )
1179     myRef = SNMP_END_OF_VAR;
1180     else
1181     {
1182     val->byte = LCDDisplayString[myRef++];
1183     if ( myRef == LCDDisplayStringLen )
1184     myRef = SNMP_END_OF_VAR;
1185     }
1186    
1187     *ref = myRef;
1188     return TRUE;
1189    
1190     }
1191    
1192     return FALSE;
1193     }
1194     #endif
1195    
1196    
1197    
1198     /*********************************************************************
1199     * Function: void InitializeBoard(void)
1200     *
1201     * PreCondition: None
1202     *
1203     * Input: None
1204     *
1205     * Output: None
1206     *
1207     * Side Effects: None
1208     *
1209     * Overview: Initialize board specific hardware.
1210     *
1211     * Note: None
1212     ********************************************************************/
1213     static void InitializeBoard(void)
1214     {
1215     /*
1216     * Setup for PORTA.RA0 as analog input while rests
1217     * as digital i/o lines.
1218     */
1219     ADCON1 = 0b10001110; // RA0 as analog input, Right justified
1220     TRISA = 0x03;
1221    
1222     /*
1223     * Right justified, Fosc/32
1224     */
1225     ADCON2 = 0b00000010;
1226    
1227     /*
1228     * LCD is enabled using RA5.
1229     */
1230     PORTA_RA5 = 0; // Disable LCD.
1231    
1232     /*
1233     * Turn off the LED's.
1234     */
1235     LATA2 = 1;
1236     LATA3 = 1;
1237    
1238     /*
1239     * External data EEPROM needs pull-ups, so enable internal
1240     * pull-ups.
1241     */
1242     INTCON2_RBPU = 0;
1243    
1244     XLCDInit();
1245     XLCDGoto(0, 0);
1246     XLCDPutROMString(StartupMsg);
1247     XLCDGoto(1, 0);
1248     XLCDPutROMString(InitializingMsg);
1249    
1250    
1251     TXSTA = 0b00100000; // Low BRG speed
1252     RCSTA = 0b10010000;
1253     SPBRG = SPBRG_VAL;
1254    
1255     T0CON = 0;
1256     INTCON_GIEH = 1;
1257     INTCON_GIEL = 1;
1258    
1259     }
1260    
1261     /*********************************************************************
1262     * Function: void InitAppConfig(void)
1263     *
1264     * PreCondition: MPFSInit() is already called.
1265     *
1266     * Input: None
1267     *
1268     * Output: Write/Read non-volatile config variables.
1269     *
1270     * Side Effects: None
1271     *
1272     * Overview: None
1273     *
1274     * Note: None
1275     ********************************************************************/
1276     static void InitAppConfig(void)
1277     {
1278     #if defined(MPFS_USE_EEPROM)
1279     BYTE c;
1280     BYTE *p;
1281     #endif
1282    
1283     /*
1284     * Load default configuration into RAM.
1285     */
1286     AppConfig.MyIPAddr.v[0] = MY_DEFAULT_IP_ADDR_BYTE1;
1287     AppConfig.MyIPAddr.v[1] = MY_DEFAULT_IP_ADDR_BYTE2;
1288     AppConfig.MyIPAddr.v[2] = MY_DEFAULT_IP_ADDR_BYTE3;
1289     AppConfig.MyIPAddr.v[3] = MY_DEFAULT_IP_ADDR_BYTE4;
1290    
1291     AppConfig.MyMask.v[0] = MY_DEFAULT_MASK_BYTE1;
1292     AppConfig.MyMask.v[1] = MY_DEFAULT_MASK_BYTE2;
1293     AppConfig.MyMask.v[2] = MY_DEFAULT_MASK_BYTE3;
1294     AppConfig.MyMask.v[3] = MY_DEFAULT_MASK_BYTE4;
1295    
1296     AppConfig.MyGateway.v[0] = MY_DEFAULT_GATE_BYTE1;
1297     AppConfig.MyGateway.v[1] = MY_DEFAULT_GATE_BYTE2;
1298     AppConfig.MyGateway.v[2] = MY_DEFAULT_GATE_BYTE3;
1299     AppConfig.MyGateway.v[3] = MY_DEFAULT_GATE_BYTE4;
1300    
1301     AppConfig.MyMACAddr.v[0] = MY_DEFAULT_MAC_BYTE1;
1302     AppConfig.MyMACAddr.v[1] = MY_DEFAULT_MAC_BYTE2;
1303     AppConfig.MyMACAddr.v[2] = MY_DEFAULT_MAC_BYTE3;
1304     AppConfig.MyMACAddr.v[3] = MY_DEFAULT_MAC_BYTE4;
1305     AppConfig.MyMACAddr.v[4] = MY_DEFAULT_MAC_BYTE5;
1306     AppConfig.MyMACAddr.v[5] = MY_DEFAULT_MAC_BYTE6;
1307    
1308     #if defined(STACK_USE_DHCP) || defined(STACK_USE_IP_GLEANING)
1309     AppConfig.Flags.bIsDHCPEnabled = TRUE;
1310     #else
1311     AppConfig.Flags.bIsDHCPEnabled = FALSE;
1312     #endif
1313    
1314     #if defined(MPFS_USE_EEPROM)
1315     p = (BYTE*)&AppConfig;
1316    
1317    
1318     XEEBeginRead(EEPROM_CONTROL, 0x00);
1319     c = XEERead();
1320     XEEEndRead();
1321    
1322     /*
1323     * When a record is saved, first byte is written as 0x55 to indicate
1324     * that a valid record was saved.
1325     */
1326     if ( c == 0x55 )
1327     {
1328     XEEBeginRead(EEPROM_CONTROL, 0x01);
1329     for ( c = 0; c < sizeof(AppConfig); c++ )
1330     *p++ = XEERead();
1331     XEEEndRead();
1332     }
1333     else
1334     SaveAppConfig();
1335     #endif
1336     }
1337    
1338     #if defined(MPFS_USE_EEPROM)
1339     static void SaveAppConfig(void)
1340     {
1341     BYTE c;
1342     BYTE *p;
1343    
1344     p = (BYTE*)&AppConfig;
1345     XEEBeginWrite(EEPROM_CONTROL, 0x00);
1346     XEEWrite(0x55);
1347     for ( c = 0; c < sizeof(AppConfig); c++ )
1348     {
1349     XEEWrite(*p++);
1350     }
1351    
1352     XEEEndWrite();
1353     }
1354     #endif
1355    
1356     ROM char menu[] =
1357     "\r\n\r\n\r\MCHPStack Master Demo Application 1.1 ("STARTUP_MSG", " __DATE__ ")\r\n\r\n"
1358    
1359     "\t1: Change Board serial number.\r\n"
1360     "\t2: Change default IP address.\r\n"
1361     "\t3: Change default gateway address.\r\n"
1362     "\t4: Change default subnet mask.\r\n"
1363     "\t5: Enable DHCP & IP Gleaning.\r\n"
1364     "\t6: Disable DHCP & IP Gleaning.\r\n"
1365     "\t7: Download MPFS image.\r\n"
1366     "\t8: Save & Quit.\r\n"
1367     "\r\n"
1368     "Enter a menu choice (1-8): ";
1369    
1370     typedef enum _MENU_CMD
1371     {
1372     MENU_CMD_SERIAL_NUMBER = '1',
1373     MENU_CMD_IP_ADDRESS,
1374     MENU_CMD_GATEWAY_ADDRESS,
1375     MENU_CMD_SUBNET_MASK,
1376     MENU_CMD_ENABLE_AUTO_CONFIG,
1377     MENU_CMD_DISABLE_AUTO_CONFIG,
1378     MENU_CMD_DOWNLOAD_MPFS,
1379     MENU_CMD_QUIT,
1380     MENU_CMD_INVALID
1381     } MENU_CMD;
1382    
1383     ROM char* menuCommandPrompt[] =
1384     {
1385     "\r\nSerial Number (",
1386     "\r\nDefault IP Address (",
1387     "\r\nDefault Gateway Address (",
1388     "\r\nDefault Subnet Mask (",
1389     "\r\nDHCP & IP Gleaning enabled.\r\n",
1390     "\r\nDHCP & IP Gleaning disabled.\r\n",
1391     "\r\nReady to download MPFS image - Use Xmodem protocol.\r\n",
1392     "\r\nNow running application..."
1393     };
1394    
1395     ROM char InvalidInputMsg[] = "\r\nInvalid input received - Input ignored.\r\n"
1396     "Press any key to continue...\r\n";
1397    
1398     void USARTPutROMString(ROM char* str)
1399     {
1400     BYTE v;
1401    
1402     while( v = *str++ )
1403     USARTPut(v);
1404     }
1405    
1406    
1407     BYTE USARTGetString(char *buffer, BYTE bufferLen)
1408     {
1409     BYTE v;
1410     BYTE count;
1411    
1412     count = 0;
1413     do
1414     {
1415     while( !USARTIsGetReady() );
1416    
1417     v = USARTGet();
1418    
1419     if ( v == '\r' || v == '\n' )
1420     break;
1421    
1422     count++;
1423     *buffer++ = v;
1424     *buffer = '\0';
1425     if ( bufferLen-- == 0 )
1426     break;
1427     } while(1);
1428     return count;
1429     }
1430    
1431     BOOL StringToIPAddress(char *str, IP_ADDR *buffer)
1432     {
1433     BYTE v;
1434     char *temp;
1435     BYTE byteIndex;
1436    
1437     temp = str;
1438     byteIndex = 0;
1439    
1440     while( v = *str )
1441     {
1442     if ( v == '.' )
1443     {
1444     *str++ = '\0';
1445     buffer->v[byteIndex++] = atoi(temp);
1446     temp = str;
1447     }
1448     else if ( v < '0' || v > '9' )
1449     return FALSE;
1450    
1451     str++;
1452     }
1453    
1454     buffer->v[byteIndex] = atoi(temp);
1455    
1456     return (byteIndex == 3);
1457     }
1458    
1459    
1460    
1461     MENU_CMD GetMenuChoice(void)
1462     {
1463     BYTE c;
1464    
1465     while ( !USARTIsGetReady() );
1466    
1467     c = USARTGet();
1468    
1469     if ( c >= '1' && c < MENU_CMD_INVALID )
1470     return c;
1471     else
1472     return MENU_CMD_INVALID;
1473     }
1474    
1475     #define MAX_USER_RESPONSE_LEN (20)
1476     void ExecuteMenuChoice(MENU_CMD choice)
1477     {
1478     char response[MAX_USER_RESPONSE_LEN];
1479     IP_ADDR tempIPValue;
1480     IP_ADDR *destIPValue;
1481    
1482     USARTPut('\r');
1483     USARTPut('\n');
1484     USARTPutROMString(menuCommandPrompt[choice-'0'-1]);
1485    
1486     switch(choice)
1487     {
1488     case MENU_CMD_SERIAL_NUMBER:
1489     itoa(AppConfig.SerialNumber.Val, response);
1490     USARTPutString((BYTE*)response);
1491     USARTPut(')');
1492     USARTPut(':');
1493     USARTPut(' ');
1494    
1495     if ( USARTGetString(response, sizeof(response)) )
1496     {
1497     AppConfig.SerialNumber.Val = atoi(response);
1498    
1499     AppConfig.MyMACAddr.v[4] = AppConfig.SerialNumber.v[1];
1500     AppConfig.MyMACAddr.v[5] = AppConfig.SerialNumber.v[0];
1501     }
1502     else
1503     goto HandleInvalidInput;
1504    
1505     break;
1506    
1507     case MENU_CMD_IP_ADDRESS:
1508     destIPValue = &AppConfig.MyIPAddr;
1509     goto ReadIPConfig;
1510    
1511     case MENU_CMD_GATEWAY_ADDRESS:
1512     destIPValue = &AppConfig.MyGateway;
1513     goto ReadIPConfig;
1514    
1515     case MENU_CMD_SUBNET_MASK:
1516     destIPValue = &AppConfig.MyMask;
1517    
1518     ReadIPConfig:
1519     DisplayIPValue(destIPValue, FALSE);
1520     USARTPut(')');
1521     USARTPut(':');
1522     USARTPut(' ');
1523    
1524     USARTGetString(response, sizeof(response));
1525    
1526     if ( !StringToIPAddress(response, &tempIPValue) )
1527     {
1528     HandleInvalidInput:
1529     USARTPutROMString(InvalidInputMsg);
1530     while( !USARTIsGetReady() );
1531     USARTGet();
1532     }
1533     else
1534     {
1535     destIPValue->Val = tempIPValue.Val;
1536     }
1537     break;
1538    
1539    
1540     case MENU_CMD_ENABLE_AUTO_CONFIG:
1541     AppConfig.Flags.bIsDHCPEnabled = TRUE;
1542     break;
1543    
1544     case MENU_CMD_DISABLE_AUTO_CONFIG:
1545     AppConfig.Flags.bIsDHCPEnabled = FALSE;
1546     break;
1547    
1548     case MENU_CMD_DOWNLOAD_MPFS:
1549     #if defined(MPFS_USE_EEPROM)
1550     DownloadMPFS();
1551     #endif
1552     break;
1553    
1554     case MENU_CMD_QUIT:
1555     #if defined(MPFS_USE_EEPROM)
1556     SaveAppConfig();
1557     #endif
1558     break;
1559     }
1560     }
1561    
1562    
1563    
1564    
1565     static void SetConfig(void)
1566     {
1567     MENU_CMD choice;
1568    
1569     do
1570     {
1571     USARTPutROMString(menu);
1572     choice = GetMenuChoice();
1573     if ( choice != MENU_CMD_INVALID )
1574     ExecuteMenuChoice(choice);
1575     } while(choice != MENU_CMD_QUIT);
1576    
1577     }
1578    
1579    
1580     #if defined(MPFS_USE_EEPROM)
1581    
1582     /*********************************************************************
1583     * Function: BOOL DownloadMPFS(void)
1584     *
1585     * PreCondition: MPFSInit() is already called.
1586     *
1587     * Input: None
1588     *
1589     * Output: TRUE if successful
1590     * FALSE otherwise
1591     *
1592     * Side Effects: This function uses 128 bytes of Bank 4 using
1593     * indirect pointer. This requires that no part of
1594     * code is using this block during or before calling
1595     * this function. Once this function is done,
1596     * that block of memory is available for general use.
1597     *
1598     * Overview: This function implements XMODEM protocol to
1599     * be able to receive a binary file from PC
1600     * applications such as HyperTerminal.
1601     *
1602     * Note: In current version, this function does not
1603     * implement user interface to set IP address and
1604     * other informations. User should create their
1605     * own interface to allow user to modify IP
1606     * information.
1607     * Also, this version implements simple user
1608     * action to start file transfer. User may
1609     * evaulate its own requirement and implement
1610     * appropriate start action.
1611     *
1612     ********************************************************************/
1613     #define XMODEM_SOH 0x01
1614     #define XMODEM_EOT 0x04
1615     #define XMODEM_ACK 0x06
1616     #define XMODEM_NAK 0x15
1617     #define XMODEM_CAN 0x18
1618     #define XMODEM_BLOCK_LEN 128
1619    
1620     static BOOL DownloadMPFS(void)
1621     {
1622     enum SM_MPFS
1623     {
1624     SM_MPFS_SOH,
1625     SM_MPFS_BLOCK,
1626     SM_MPFS_BLOCK_CMP,
1627     SM_MPFS_DATA,
1628     } state;
1629    
1630     BYTE c;
1631     MPFS handle;
1632     BOOL lbDone;
1633     BYTE blockLen;
1634     BYTE lResult;
1635     BYTE tempData[XMODEM_BLOCK_LEN];
1636     TICK lastTick;
1637     TICK currentTick;
1638    
1639     state = SM_MPFS_SOH;
1640     lbDone = FALSE;
1641    
1642     handle = MPFSFormat();
1643    
1644     /*
1645     * Notify the host that we are ready to receive...
1646     */
1647     lastTick = TickGet();
1648     do
1649     {
1650     /*
1651     * Update tick here too - just in case interrupt is not used.
1652     */
1653     TickUpdate();
1654    
1655     currentTick = TickGet();
1656     if ( TickGetDiff(currentTick, lastTick) >= (TICK_SECOND/2) )
1657     {
1658     lastTick = TickGet();
1659     USARTPut(XMODEM_NAK);
1660    
1661     /*
1662     * Blink LED to indicate that we are waiting for
1663     * host to send the file.
1664     */
1665     LATA2 ^= 1;
1666     }
1667    
1668     } while( !USARTIsGetReady() );
1669    
1670    
1671     while(!lbDone)
1672     {
1673     /*
1674     * Update tick here too - just in case interrupt is not used.
1675     */
1676     TickUpdate();
1677    
1678     if ( USARTIsGetReady() )
1679     {
1680     /*
1681     * Toggle LED as we receive the data from host.
1682     */
1683     LATA2 ^= 1;
1684     c = USARTGet();
1685     }
1686     else
1687     {
1688     /*
1689     * Real application should put some timeout to make sure
1690     * that we do not wait forever.
1691     */
1692     continue;
1693     }
1694    
1695     switch(state)
1696     {
1697     default:
1698     if ( c == XMODEM_SOH )
1699     {
1700     state = SM_MPFS_BLOCK;
1701     }
1702     else if ( c == XMODEM_EOT )
1703     {
1704     /*
1705     * Turn off LED when we are done.
1706     */
1707     LATA2 = 1;
1708    
1709     MPFSClose();
1710     USARTPut(XMODEM_ACK);
1711     lbDone = TRUE;
1712     }
1713     else
1714     USARTPut(XMODEM_NAK);
1715    
1716     break;
1717    
1718     case SM_MPFS_BLOCK:
1719     /*
1720     * We do not use block information.
1721     */
1722     lResult = XMODEM_ACK;
1723     blockLen = 0;
1724     state = SM_MPFS_BLOCK_CMP;
1725     break;
1726    
1727     case SM_MPFS_BLOCK_CMP:
1728     /*
1729     * We do not use 1's comp. block value.
1730     */
1731     state = SM_MPFS_DATA;
1732     break;
1733    
1734     case SM_MPFS_DATA:
1735     /*
1736     * Buffer block data until it is over.
1737     */
1738     tempData[blockLen++] = c;
1739     if ( blockLen > XMODEM_BLOCK_LEN )
1740     {
1741     /*
1742     * We have one block data.
1743     * Write it to EEPROM.
1744     */
1745     MPFSPutBegin(handle);
1746    
1747     lResult = XMODEM_ACK;
1748     for ( c = 0; c < XMODEM_BLOCK_LEN; c++ )
1749     MPFSPut(tempData[c]);
1750    
1751     handle = MPFSPutEnd();
1752    
1753     USARTPut(lResult);
1754     state = SM_MPFS_SOH;
1755     }
1756     break;
1757    
1758     }
1759    
1760     }
1761    
1762    
1763     /*
1764     * This small wait is required if SLIP is in use.
1765     * If this is not used, PC might misinterpret SLIP
1766     * module communication and never close file transfer
1767     * dialog box.
1768     */
1769     #if defined(STACK_USE_SLIP)
1770     {
1771     BYTE i;
1772     i = 255;
1773     while( i-- );
1774     }
1775     #endif
1776     return TRUE;
1777     }
1778    
1779     #endif
1780    
1781    
1782     void XLCDDelay15ms(void)
1783     {
1784     DelayMs(20);
1785     }
1786     void XLCDDelay4ms(void)
1787     {
1788     DelayMs(10);
1789     }
1790    
1791     void XLCDDelay100us(void)
1792     {
1793     INTCON_GIEH = 0;
1794     Delay10us(1);
1795     INTCON_GIEH = 1;
1796     }

  ViewVC Help
Powered by ViewVC 1.1.20