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

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

  ViewVC Help
Powered by ViewVC 1.1.20