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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue May 1 08:17:39 2007 UTC (17 years, 1 month 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 /*********************************************************************
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