Index: /webserver/example/EnergyMeters/Source/include/FreeRTOS.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/FreeRTOS.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/FreeRTOS.h (revision 14) @@ -0,0 +1,398 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +#include + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + + +/* Defines the prototype to which the application task hook function must +conform. */ +typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); + + + + + +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configUSE_PREEMPTION + #error Missing definition: configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK + #error Missing definition: configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK + #error Missing definition: configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_CO_ROUTINES + #error Missing definition: configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskPrioritySet + #error Missing definition: INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_uxTaskPriorityGet + #error Missing definition: INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelete + #error Missing definition: INCLUDE_vTaskDelete should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskCleanUpResources + #error Missing definition: INCLUDE_vTaskCleanUpResources should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskSuspend + #error Missing definition: INCLUDE_vTaskSuspend should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelayUntil + #error Missing definition: INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef INCLUDE_vTaskDelay + #error Missing definition: INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS + #error Missing definition: configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG + #define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark + #define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES + #define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES + #define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES + #define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API + #define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB + #define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD + #define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 + #undef configMAX_TASK_NAME_LEN + #define configMAX_TASK_NAME_LEN 1 +#endif + +#ifndef INCLUDE_xTaskResumeFromISR + #define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xTaskGetSchedulerState + #define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#if ( configUSE_MUTEXES == 1 ) + /* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism + within the mutex implementation so must be available if mutexes are used. */ + #undef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 1 +#else + #ifndef INCLUDE_xTaskGetCurrentTaskHandle + #define INCLUDE_xTaskGetCurrentTaskHandle 0 + #endif +#endif + + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR + #define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + + +#ifndef configQUEUE_REGISTRY_SIZE + #define configQUEUE_REGISTRY_SIZE 0 +#endif + +#if configQUEUE_REGISTRY_SIZE < 1 + #define configQUEUE_REGISTRY_SIZE 0 + #define vQueueAddToRegistry( xQueue, pcName ) + #define vQueueUnregisterQueue( xQueue ) +#endif + + +/* Remove any unused trace macros. */ +#ifndef traceSTART + /* Used to perform any necessary initialisation - for example, open a file + into which trace is to be written. */ + #define traceSTART() +#endif + +#ifndef traceEND + /* Use to close a trace, for example close a file into which trace has been + written. */ + #define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN + /* Called after a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the selected task. */ + #define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceTASK_SWITCHED_OUT + /* Called before a task has been selected to run. pxCurrentTCB holds a pointer + to the task control block of the task being switched out. */ + #define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE + /* Task is about to block because it cannot read from a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the read was attempted. pxCurrentTCB points to the TCB of the + task that attempted the read. */ + #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND + /* Task is about to block because it cannot write to a + queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore + upon which the write was attempted. pxCurrentTCB points to the TCB of the + task that attempted the write. */ + #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW + #define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceQUEUE_CREATE + #define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED + #define traceQUEUE_CREATE_FAILED() +#endif + +#ifndef traceCREATE_MUTEX + #define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED + #define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE + #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED + #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE + #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE + #define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED + #define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND + #define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED + #define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE + #define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK + #define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED + #define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR + #define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED + #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR + #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED + #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE + #define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE + #define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED + #define traceTASK_CREATE_FAILED( pxNewTCB ) +#endif + +#ifndef traceTASK_DELETE + #define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL + #define traceTASK_DELAY_UNTIL() +#endif + +#ifndef traceTASK_DELAY + #define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET + #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND + #define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME + #define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR + #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK + #define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef configGENERATE_RUN_TIME_STATS + #define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. + #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + + #ifndef portGET_RUN_TIME_COUNTER_VALUE + #error If configGENERATE_RUN_TIME_STATS is defined then portGET_RUN_TIME_COUNTER_VALUE must also be defined. portGET_RUN_TIME_COUNTER_VALUE should evaluate to the counter value of the timer/counter peripheral used as the run time counter time base. + #endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS + #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK + #define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#endif /* INC_FREERTOS_H */ + Index: /webserver/example/EnergyMeters/Source/include/StackMacros.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/StackMacros.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/StackMacros.h (revision 14) @@ -0,0 +1,167 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef STACK_MACROS_H +#define STACK_MACROS_H + +/* + * Call the stack overflow hook function if the stack of the task being swapped + * out is currently overflowed, or looks like it might have overflowed in the + * past. + * + * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check + * the current stack state only - comparing the current top of stack value to + * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 + * will also cause the last few stack bytes to be checked to ensure the value + * to which the bytes were set when the task was created have not been + * overwritten. Note this second test does not guarantee that an overflowed + * stack will always be recognised. + */ + +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 0 ) + + /* FreeRTOSConfig.h is not set to check for stack overflows. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */ +/*-----------------------------------------------------------*/ + +#if( configCHECK_FOR_STACK_OVERFLOW == 1 ) + + /* FreeRTOSConfig.h is only set to use the first method of + overflow checking. */ + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() + +#endif +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) ) + + /* Only the current stack state is to be checked. */ + #define taskFIRST_CHECK_FOR_STACK_OVERFLOW() \ + { \ + extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \ + \ + /* Is the currently saved stack pointer within the stack limit? */ \ + if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \ + static const unsigned portCHAR ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) + + #define taskSECOND_CHECK_FOR_STACK_OVERFLOW() \ + { \ + extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); \ + portCHAR *pcEndOfStack = ( portCHAR * ) pxCurrentTCB->pxEndOfStack; \ + static const unsigned portCHAR ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ + tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ + \ + \ + pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ + \ + /* Has the extremity of the task stack ever been written over? */ \ + if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ + { \ + vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ + } \ + } + +#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ +/*-----------------------------------------------------------*/ + +#endif /* STACK_MACROS_H */ + Index: /webserver/example/EnergyMeters/Source/include/list.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/list.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/list.h (revision 14) @@ -0,0 +1,299 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * xLists can only store pointers to xListItems. Each xListItem contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + +/* + Changes from V4.3.1 + + + Included local const within listGET_OWNER_OF_NEXT_ENTRY() to assist + compiler with optimisation. Thanks B.R. +*/ + +#ifndef LIST_H +#define LIST_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM +{ + portTickType xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + volatile struct xLIST_ITEM * pxNext; /*< Pointer to the next xListItem in the list. */ + volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */ + void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void * pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ +}; +typedef struct xLIST_ITEM xListItem; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM +{ + portTickType xItemValue; + volatile struct xLIST_ITEM *pxNext; + volatile struct xLIST_ITEM *pxPrevious; +}; +typedef struct xMINI_LIST_ITEM xMiniListItem; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST +{ + volatile unsigned portBASE_TYPE uxNumberOfItems; + volatile xListItem * pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */ + volatile xMiniListItem xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ +} xList; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( pxListItem )->pvOwner = ( void * ) pxOwner + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( pxListItem )->xItemValue = xValue + +/* + * Access macro the retrieve the value of the list item. The value can + * represent anything - for example a the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entries pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +xList * const pxConstList = pxList; \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + pxTCB = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( pxList->uxNumberOfItems != ( unsigned portBASE_TYPE ) 0 ) ? ( (&( pxList->xListEnd ))->pxNext->pvOwner ) : ( NULL ) ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE is the list item is in the list, otherwise pdFALSE. + * pointer against + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( pxListItem )->pvContainer == ( void * ) pxList ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise( xList *pxList ); + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem( xListItem *pxItem ); + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item to that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert( xList *pxList, xListItem *pxNewListItem ); + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pvIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pvIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pvIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ); + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param vListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * \page vListRemove vListRemove + * \ingroup LinkedList + */ +void vListRemove( xListItem *pxItemToRemove ); + +#ifdef __cplusplus +} +#endif + +#endif + Index: /webserver/example/EnergyMeters/Source/include/projdefs.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/projdefs.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/projdefs.h (revision 14) @@ -0,0 +1,71 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* Defines the prototype to which task functions must conform. */ +typedef void (*pdTASK_CODE)( void * ); + +#define pdTRUE ( 1 ) +#define pdFALSE ( 0 ) + +#define pdPASS ( 1 ) +#define pdFAIL ( 0 ) +#define errQUEUE_EMPTY ( 0 ) +#define errQUEUE_FULL ( 0 ) + +/* Error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errNO_TASK_TO_RUN ( -2 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +#endif /* PROJDEFS_H */ + + + Index: /webserver/example/EnergyMeters/Source/include/semphr.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/semphr.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/semphr.h (revision 14) @@ -0,0 +1,705 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include semphr.h" +#endif + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#include "queue.h" + +typedef xQueueHandle xSemaphoreHandle; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned portCHAR ) 1 ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portCHAR ) 0 ) +#define semGIVE_BLOCK_TIME ( ( portTickType ) 0 ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )
+ * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#define vSemaphoreCreateBinary( xSemaphore ) { \ + xSemaphore = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \ + if( xSemaphore != NULL ) \ + { \ + xSemaphoreGive( xSemaphore ); \ + } \ + } + +/** + * semphr. h + * xSemaphoreTake( + * xSemaphoreHandle xSemaphore, + * portTickType xBlockTime + * ) + * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the 
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * xSemaphoreHandle xMutex, + * portTickType xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_RATE_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( xMutex, xBlockTime ) + + +/* + * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE ) + +/** + * semphr. h + *
xSemaphoreGive( xSemaphoreHandle xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.	
+        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to 
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be 
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( xMutex ) + +/* + * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR( 
+                          xSemaphoreHandle xSemaphore, 
+                          portBASE_TYPE *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ #define LONG_TIME 0xffff
+ #define TICKS_TO_WAIT	10
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore 
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute 
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static unsigned portCHAR ucLocalTickCount = 0;
+ static portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) xSemaphore, NULL, pxHigherPriorityTaskWoken, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateMutex( void )
+ * + * Macro that implements a mutex semaphore by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros should not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateMutex() xQueueCreateMutex() + + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )
+ * + * Macro that implements a recursive mutex by using the existing queue + * mechanism. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See vSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * xSemaphoreHandle. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \ingroup Semaphores + */ +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex() + +/** + * semphr. h + *
xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
+ * + * Macro that creates a counting semaphore by using the existing + * queue mechanism. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.  
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount ) + + +#endif /* SEMAPHORE_H */ + + Index: /webserver/example/EnergyMeters/Source/include/task.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/task.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/task.h (revision 14) @@ -0,0 +1,1101 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include task.h" +#endif + + + +#ifndef TASK_H +#define TASK_H + +#include "portable.h" +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V5.4.0" + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an xTaskHandle variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \page xTaskHandle xTaskHandle + * \ingroup Tasks + */ +typedef void * xTaskHandle; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT +{ + portBASE_TYPE xOverflowCount; + portTickType xTimeOnEntering; +} xTimeOutType; + +/* + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0 ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \page taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \page taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \page taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() + +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). */ +#define taskSCHEDULER_NOT_STARTED 0 +#define taskSCHEDULER_RUNNING 1 +#define taskSCHEDULER_SUSPENDED 2 + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ portBASE_TYPE xTaskCreate(
+                              pdTASK_CODE pvTaskCode,
+                              const portCHAR * const pcName,
+                              unsigned portSHORT usStackDepth,
+                              void *pvParameters,
+                              unsigned portBASE_TYPE uxPriority,
+                              xTaskHandle *pvCreatedTask
+                          );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by tskMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file errors. h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+     for( ;; )
+     {
+         // Task code goes here.
+     }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+
+     // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+     // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+     // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+     // the new time attempts to access it.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+
+     // Use the handle to delete the task.
+     vTaskDelete( xHandle );
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pvCreatedTask ); + +/** + * task. h + *
void vTaskDelete( xTaskHandle pxTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernels management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param pxTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ xTaskHandle xHandle;
+
+     // Create the task, storing the handle.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+     // Use the handle to delete the task.
+     vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete( xTaskHandle pxTask ); + + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( portTickType xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a cyclical task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const portTickType xDelay = 500 / portTICK_RATE_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay( portTickType xTicksToDelay ); + +/** + * task. h + *
void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by cyclical + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_RATE_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ portTickType xLastWakeTime;
+ const portTickType xFrequency = 10;
+
+     // Initialise the xLastWakeTime variable with the current time.
+     xLastWakeTime = xTaskGetTickCount ();
+     for( ;; )
+     {
+         // Wait for the next cycle.
+         vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+         // Perform action here.
+     }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ); + +/** + * task. h + *
unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
+ * + * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param pxTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of pxTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+     // Create a task, storing the handle.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+     // ...
+
+     // Use the handle to obtain the priority of the created task.
+     // It was created with tskIDLE_PRIORITY, but may have changed
+     // it itself.
+     if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+     {
+         // The task has changed it's priority.
+     }
+
+     // ...
+
+     // Is our priority higher than the created task?
+     if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+     {
+         // Our priority (obtained using NULL handle) is higher.
+     }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ); + +/** + * task. h + *
void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param pxTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+     // Create a task, storing the handle.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+     // ...
+
+     // Use the handle to raise the priority of the created task.
+     vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+     // ...
+
+     // Use a NULL handle to raise our priority to the same value.
+     vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ); + +/** + * task. h + *
void vTaskSuspend( xTaskHandle pxTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param pxTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+     // Create a task, storing the handle.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+     // ...
+
+     // Use the handle to suspend the created task.
+     vTaskSuspend( xHandle );
+
+     // ...
+
+     // The created task will not run during this period, unless
+     // another task calls vTaskResume( xHandle ).
+
+     //...
+
+
+     // Suspend ourselves.
+     vTaskSuspend( NULL );
+
+     // We cannot get here unless another task calls vTaskResume
+     // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend( xTaskHandle pxTaskToSuspend ); + +/** + * task. h + *
void vTaskResume( xTaskHandle pxTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param pxTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ xTaskHandle xHandle;
+
+     // Create a task, storing the handle.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+     // ...
+
+     // Use the handle to suspend the created task.
+     vTaskSuspend( xHandle );
+
+     // ...
+
+     // The created task will not run during this period, unless
+     // another task calls vTaskResume( xHandle ).
+
+     //...
+
+
+     // Resume the suspended task ourselves.
+     vTaskResume( xHandle );
+
+     // The created task will once again get microcontroller processing
+     // time in accordance with it priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume( xTaskHandle pxTaskToResume ); + +/** + * task. h + *
void xTaskResumeFromISR( xTaskHandle pxTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one of more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * @param pxTaskToResume Handle to the task being readied. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ); + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. This function + * does not return until an executing task calls vTaskEndScheduler (). + * + * At least one task should be created via a call to xTaskCreate () + * before calling vTaskStartScheduler (). The idle task is created + * automatically when the first application task is created. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+     // Create at least one task before starting the kernel.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+     // Start the real time kernel with preemption.
+     vTaskStartScheduler ();
+
+     // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler( void ); + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+     for( ;; )
+     {
+         // Task code goes here.
+
+         // At some point we want to end the real time kernel processing
+         // so call ...
+         vTaskEndScheduler ();
+     }
+ }
+
+ void vAFunction( void )
+ {
+     // Create at least one task before starting the kernel.
+     xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+     // Start the real time kernel with preemption.
+     vTaskStartScheduler ();
+
+     // Will only get here when the vTaskCode () task has called
+     // vTaskEndScheduler ().  When we get here we are back to single task
+     // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler( void ); + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends all real time kernel activity while keeping interrupts (including the + * kernel tick) enabled. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+     for( ;; )
+     {
+         // Task code goes here.
+
+         // ...
+
+         // At some point the task wants to perform a long operation during
+         // which it does not want to get swapped out.  It cannot use
+         // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+         // operation may cause interrupts to be missed - including the
+         // ticks.
+
+         // Prevent the real time kernel swapping out the task.
+         vTaskSuspendAll ();
+
+         // Perform the operation here.  There is no need to use critical
+         // sections as we have all the microcontroller processing time.
+         // During this time interrupts will still operate and the kernel
+         // tick count will be maintained.
+
+         // ...
+
+         // The operation is complete.  Restart the kernel.
+         xTaskResumeAll ();
+     }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll( void ); + +/** + * task. h + *
portCHAR xTaskResumeAll( void );
+ * + * Resumes real time kernel activity following a call to vTaskSuspendAll (). + * After a call to vTaskSuspendAll () the kernel will take control of which + * task is executing at any time. + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+     for( ;; )
+     {
+         // Task code goes here.
+
+         // ...
+
+         // At some point the task wants to perform a long operation during
+         // which it does not want to get swapped out.  It cannot use
+         // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+         // operation may cause interrupts to be missed - including the
+         // ticks.
+
+         // Prevent the real time kernel swapping out the task.
+         vTaskSuspendAll ();
+
+         // Perform the operation here.  There is no need to use critical
+         // sections as we have all the microcontroller processing time.
+         // During this time interrupts will still operate and the real
+         // time kernel tick count will be maintained.
+
+         // ...
+
+         // The operation is complete.  Restart the kernel.  We want to force
+         // a context switch - but there is no point if resuming the scheduler
+         // caused a context switch already.
+         if( !xTaskResumeAll () )
+         {
+              taskYIELD ();
+         }
+     }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +signed portBASE_TYPE xTaskResumeAll( void ); + +/** + * task. h + *
signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask );
+ * + * Utility task that simply returns pdTRUE if the task referenced by xTask is + * currently in the Suspended state, or pdFALSE if the task referenced by xTask + * is in any other state. + * + */ +signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ); + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
volatile portTickType xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \page xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +portTickType xTaskGetTickCount( void ); + +/** + * task. h + *
unsigned portSHORT uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ); + +/** + * task. h + *
void vTaskList( portCHAR *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * NOTE: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ascii form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \page vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList( signed portCHAR *pcWriteBuffer ); + +/** + * task. h + *
void vTaskGetRunTimeStats( portCHAR *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS must be defined as 1 for this function + * to be available. The application must also then provide definitions + * for portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and + * portGET_RUN_TIME_COUNTER_VALUE to configure a peripheral timer/counter + * and return the timers current count value respectively. The counter + * should be at least 10 times the frequency of the tick count. + * + * NOTE: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ascii form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \page vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats( signed portCHAR *pcWriteBuffer ); + +/** + * task. h + *
void vTaskStartTrace( portCHAR * pcBuffer, unsigned portBASE_TYPE uxBufferSize );
+ * + * Starts a real time kernel activity trace. The trace logs the identity of + * which task is running when. + * + * The trace file is stored in binary format. A separate DOS utility called + * convtrce.exe is used to convert this into a tab delimited text file which + * can be viewed and plotted in a spread sheet. + * + * @param pcBuffer The buffer into which the trace will be written. + * + * @param ulBufferSize The size of pcBuffer in bytes. The trace will continue + * until either the buffer in full, or ulTaskEndTrace () is called. + * + * \page vTaskStartTrace vTaskStartTrace + * \ingroup TaskUtils + */ +void vTaskStartTrace( signed portCHAR * pcBuffer, unsigned portLONG ulBufferSize ); + +/** + * task. h + *
unsigned portLONG ulTaskEndTrace( void );
+ * + * Stops a kernel activity trace. See vTaskStartTrace (). + * + * @return The number of bytes that have been written into the trace buffer. + * + * \page usTaskEndTrace usTaskEndTrace + * \ingroup TaskUtils + */ +unsigned portLONG ulTaskEndTrace( void ); + +/** + * task.h + *
unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in bytes) since the task + * started. The smaller the returned number the closer the task has come + * to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in bytes) + * since the task referenced by xTask was created. + */ +unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ); + +/** + * task.h + *
void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ +void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction ); + +/** + * task.h + *
void xTaskGetApplicationTaskTag( xTaskHandle xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ +pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ); + +/** + * task.h + *
portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. + */ +portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ); + + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. + */ +void vTaskIncrementTick( void ); + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_RATE_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ); + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList () will be called if either an event occurs to + * unblock a task, or the block timeout period expires. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ); + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * INCLUDE_vTaskCleanUpResources and INCLUDE_vTaskSuspend must be defined as 1 + * for this function to be available. + * See the configuration section for more information. + * + * Empties the ready and delayed queues of task control blocks, freeing the + * memory allocated for the task control block and task stacks as it goes. + */ +void vTaskCleanUpResources( void ); + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +void vTaskSwitchContext( void ); + +/* + * Return the handle of the calling task. + */ +xTaskHandle xTaskGetCurrentTaskHandle( void ); + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ); + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ); + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield( void ); + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +portBASE_TYPE xTaskGetSchedulerState( void ); + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ); + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ); + +#ifdef __cplusplus +} +#endif +#endif /* TASK_H */ + + + Index: /webserver/example/EnergyMeters/Source/include/targets/LPC23xx.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/targets/LPC23xx.h (revision 17) +++ /webserver/example/EnergyMeters/Source/include/targets/LPC23xx.h (revision 17) @@ -0,0 +1,1131 @@ +/****************************************************************************** + * LPC23xx.h: Header file for NXP LPC23xx/24xx Family Microprocessors + * The header file is the super set of all hardware definition of the + * peripherals for the LPC23xx/24xx family microprocessor. + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2005.10.01 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ + +#ifndef __LPC23xx_H +#define __LPC23xx_H + +/* Vectored Interrupt Controller (VIC) */ +#define VIC_BASE_ADDR 0xFFFFF000 +#define VICIRQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x000)) +#define VICFIQStatus (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x004)) +#define VICRawIntr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x008)) +#define VICIntSelect (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x00C)) +#define VICIntEnable (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x010)) +#define VICIntEnClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x014)) +#define VICSoftInt (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x018)) +#define VICSoftIntClr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x01C)) +#define VICProtection (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x020)) +#define VICSWPrioMask (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x024)) + +#define VICVectAddr0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x100)) +#define VICVectAddr1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x104)) +#define VICVectAddr2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x108)) +#define VICVectAddr3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x10C)) +#define VICVectAddr4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x110)) +#define VICVectAddr5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x114)) +#define VICVectAddr6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x118)) +#define VICVectAddr7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x11C)) +#define VICVectAddr8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x120)) +#define VICVectAddr9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x124)) +#define VICVectAddr10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x128)) +#define VICVectAddr11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x12C)) +#define VICVectAddr12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x130)) +#define VICVectAddr13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x134)) +#define VICVectAddr14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x138)) +#define VICVectAddr15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x13C)) +#define VICVectAddr16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x140)) +#define VICVectAddr17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x144)) +#define VICVectAddr18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x148)) +#define VICVectAddr19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x14C)) +#define VICVectAddr20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x150)) +#define VICVectAddr21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x154)) +#define VICVectAddr22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x158)) +#define VICVectAddr23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x15C)) +#define VICVectAddr24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x160)) +#define VICVectAddr25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x164)) +#define VICVectAddr26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x168)) +#define VICVectAddr27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x16C)) +#define VICVectAddr28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x170)) +#define VICVectAddr29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x174)) +#define VICVectAddr30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x178)) +#define VICVectAddr31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x17C)) + +/* The name convention below is from previous LPC2000 family MCUs, in LPC23xx/24xx, +these registers are known as "VICVectPriority(x)". */ +#define VICVectCntl0 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x200)) +#define VICVectCntl1 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x204)) +#define VICVectCntl2 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x208)) +#define VICVectCntl3 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x20C)) +#define VICVectCntl4 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x210)) +#define VICVectCntl5 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x214)) +#define VICVectCntl6 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x218)) +#define VICVectCntl7 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x21C)) +#define VICVectCntl8 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x220)) +#define VICVectCntl9 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x224)) +#define VICVectCntl10 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x228)) +#define VICVectCntl11 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x22C)) +#define VICVectCntl12 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x230)) +#define VICVectCntl13 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x234)) +#define VICVectCntl14 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x238)) +#define VICVectCntl15 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x23C)) +#define VICVectCntl16 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x240)) +#define VICVectCntl17 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x244)) +#define VICVectCntl18 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x248)) +#define VICVectCntl19 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x24C)) +#define VICVectCntl20 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x250)) +#define VICVectCntl21 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x254)) +#define VICVectCntl22 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x258)) +#define VICVectCntl23 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x25C)) +#define VICVectCntl24 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x260)) +#define VICVectCntl25 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x264)) +#define VICVectCntl26 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x268)) +#define VICVectCntl27 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x26C)) +#define VICVectCntl28 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x270)) +#define VICVectCntl29 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x274)) +#define VICVectCntl30 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x278)) +#define VICVectCntl31 (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x27C)) + +#define VICVectAddr (*(volatile unsigned long *)(VIC_BASE_ADDR + 0xF00)) + + +/* Pin Connect Block */ +#define PINSEL_BASE_ADDR 0xE002C000 +#define PINSEL0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x00)) +#define PINSEL1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x04)) +#define PINSEL2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x08)) +#define PINSEL3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x0C)) +#define PINSEL4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x10)) +#define PINSEL5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x14)) +#define PINSEL6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x18)) +#define PINSEL7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x1C)) +#define PINSEL8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x20)) +#define PINSEL9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x24)) +#define PINSEL10 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x28)) + +#define PINMODE0 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x40)) +#define PINMODE1 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x44)) +#define PINMODE2 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x48)) +#define PINMODE3 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x4C)) +#define PINMODE4 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x50)) +#define PINMODE5 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x54)) +#define PINMODE6 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x58)) +#define PINMODE7 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x5C)) +#define PINMODE8 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x60)) +#define PINMODE9 (*(volatile unsigned long *)(PINSEL_BASE_ADDR + 0x64)) + +/* General Purpose Input/Output (GPIO) */ +#define GPIO_BASE_ADDR 0xE0028000 +#define IOPIN0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x00)) +#define IOSET0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x04)) +#define IODIR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x08)) +#define IOCLR0 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x0C)) +#define IOPIN1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x10)) +#define IOSET1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x14)) +#define IODIR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x18)) +#define IOCLR1 (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x1C)) + +/* GPIO Interrupt Registers */ +#define IO0_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x90)) +#define IO0_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x94)) +#define IO0_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x84)) +#define IO0_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x88)) +#define IO0_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x8C)) + +#define IO2_INT_EN_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB0)) +#define IO2_INT_EN_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xB4)) +#define IO2_INT_STAT_R (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA4)) +#define IO2_INT_STAT_F (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xA8)) +#define IO2_INT_CLR (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0xAC)) + +#define IO_INT_STAT (*(volatile unsigned long *)(GPIO_BASE_ADDR + 0x80)) + +#define PARTCFG_BASE_ADDR 0x3FFF8000 +#define PARTCFG (*(volatile unsigned long *)(PARTCFG_BASE_ADDR + 0x00)) + +/* Fast I/O setup */ +#define FIO_BASE_ADDR 0x3FFFC000 +#define FIO0DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x00)) +#define FIO0MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x10)) +#define FIO0PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x14)) +#define FIO0SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x18)) +#define FIO0CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x1C)) + +#define FIO1DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x20)) +#define FIO1MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x30)) +#define FIO1PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x34)) +#define FIO1SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x38)) +#define FIO1CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x3C)) + +#define FIO2DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x40)) +#define FIO2MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x50)) +#define FIO2PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x54)) +#define FIO2SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x58)) +#define FIO2CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x5C)) + +#define FIO3DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x60)) +#define FIO3MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x70)) +#define FIO3PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x74)) +#define FIO3SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x78)) +#define FIO3CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x7C)) + +#define FIO4DIR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x80)) +#define FIO4MASK (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x90)) +#define FIO4PIN (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x94)) +#define FIO4SET (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x98)) +#define FIO4CLR (*(volatile unsigned long *)(FIO_BASE_ADDR + 0x9C)) + +/* FIOs can be accessed through WORD, HALF-WORD or BYTE. */ +#define FIO0DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x01)) +#define FIO1DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x21)) +#define FIO2DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x41)) +#define FIO3DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x61)) +#define FIO4DIR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x81)) + +#define FIO0DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x03)) +#define FIO1DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x23)) +#define FIO2DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x43)) +#define FIO3DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x63)) +#define FIO4DIR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x83)) + +#define FIO0DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x00)) +#define FIO1DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x20)) +#define FIO2DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x40)) +#define FIO3DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x60)) +#define FIO4DIRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x80)) + +#define FIO0DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x02)) +#define FIO1DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x22)) +#define FIO2DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x42)) +#define FIO3DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x62)) +#define FIO4DIRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x82)) + +#define FIO0MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASK0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x11)) +#define FIO1MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x21)) +#define FIO2MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x51)) +#define FIO3MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x71)) +#define FIO4MASK1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x91)) + +#define FIO0MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASK2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x13)) +#define FIO1MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x33)) +#define FIO2MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x53)) +#define FIO3MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x73)) +#define FIO4MASK3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x93)) + +#define FIO0MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x10)) +#define FIO1MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x30)) +#define FIO2MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x50)) +#define FIO3MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x70)) +#define FIO4MASKL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x90)) + +#define FIO0MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x12)) +#define FIO1MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x32)) +#define FIO2MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x52)) +#define FIO3MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x72)) +#define FIO4MASKU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x92)) + +#define FIO0PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PIN0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x15)) +#define FIO1PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x25)) +#define FIO2PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x55)) +#define FIO3PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x75)) +#define FIO4PIN1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x95)) + +#define FIO0PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PIN2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x17)) +#define FIO1PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x37)) +#define FIO2PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x57)) +#define FIO3PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x77)) +#define FIO4PIN3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x97)) + +#define FIO0PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x14)) +#define FIO1PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x34)) +#define FIO2PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x54)) +#define FIO3PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x74)) +#define FIO4PINL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x94)) + +#define FIO0PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x16)) +#define FIO1PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x36)) +#define FIO2PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x56)) +#define FIO3PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x76)) +#define FIO4PINU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x96)) + +#define FIO0SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SET0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x19)) +#define FIO1SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x29)) +#define FIO2SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x59)) +#define FIO3SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x79)) +#define FIO4SET1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x99)) + +#define FIO0SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SET2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1B)) +#define FIO1SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3B)) +#define FIO2SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5B)) +#define FIO3SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7B)) +#define FIO4SET3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9B)) + +#define FIO0SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x18)) +#define FIO1SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x38)) +#define FIO2SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x58)) +#define FIO3SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x78)) +#define FIO4SETL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x98)) + +#define FIO0SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1A)) +#define FIO1SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3A)) +#define FIO2SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5A)) +#define FIO3SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7A)) +#define FIO4SETU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9A)) + +#define FIO0CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLR0 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1D)) +#define FIO1CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x2D)) +#define FIO2CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5D)) +#define FIO3CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7D)) +#define FIO4CLR1 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9D)) + +#define FIO0CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLR2 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9E)) + +#define FIO0CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x1F)) +#define FIO1CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x3F)) +#define FIO2CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x5F)) +#define FIO3CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x7F)) +#define FIO4CLR3 (*(volatile unsigned char *)(FIO_BASE_ADDR + 0x9F)) + +#define FIO0CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1C)) +#define FIO1CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3C)) +#define FIO2CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5C)) +#define FIO3CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7C)) +#define FIO4CLRL (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9C)) + +#define FIO0CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x1E)) +#define FIO1CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x3E)) +#define FIO2CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x5E)) +#define FIO3CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x7E)) +#define FIO4CLRU (*(volatile unsigned short *)(FIO_BASE_ADDR + 0x9E)) + + +/* System Control Block(SCB) modules include Memory Accelerator Module, +Phase Locked Loop, VPB divider, Power Control, External Interrupt, +Reset, and Code Security/Debugging */ +#define SCB_BASE_ADDR 0xE01FC000 + +/* Memory Accelerator Module (MAM) */ +#define MAMCR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x000)) +#define MAMTIM (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x004)) +#define MEMMAP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x040)) + +/* Phase Locked Loop (PLL) */ +#define PLLCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x080)) +#define PLLCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x084)) +#define PLLSTAT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x088)) +#define PLLFEED (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x08C)) + +/* Power Control */ +#define PCON (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C0)) +#define PCONP (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x0C4)) + +/* Clock Divider */ +// #define APBDIV (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x100)) +#define CCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x104)) +#define USBCLKCFG (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x108)) +#define CLKSRCSEL (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x10C)) +#define PCLKSEL0 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A8)) +#define PCLKSEL1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1AC)) + +/* External Interrupts */ +#define EXTINT (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x140)) +#define INTWAKE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x144)) +#define EXTMODE (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x148)) +#define EXTPOLAR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x14C)) + +/* Reset, reset source identification */ +#define RSIR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x180)) + +/* RSID, code security protection */ +#define CSPR (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x184)) + +/* AHB configuration */ +#define AHBCFG1 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x188)) +#define AHBCFG2 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x18C)) + +/* System Controls and Status */ +#define SCS (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A0)) + +/* MPMC(EMC) registers, note: all the external memory controller(EMC) registers +are for LPC24xx only. */ +#define STATIC_MEM0_BASE 0x80000000 +#define STATIC_MEM1_BASE 0x81000000 +#define STATIC_MEM2_BASE 0x82000000 +#define STATIC_MEM3_BASE 0x83000000 + +#define DYNAMIC_MEM0_BASE 0xA0000000 +#define DYNAMIC_MEM1_BASE 0xB0000000 +#define DYNAMIC_MEM2_BASE 0xC0000000 +#define DYNAMIC_MEM3_BASE 0xD0000000 + +/* External Memory Controller (EMC) */ +#define EMC_BASE_ADDR 0xFFE08000 +#define EMC_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x000)) +#define EMC_STAT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x004)) +#define EMC_CONFIG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x008)) + +/* Dynamic RAM access registers */ +#define EMC_DYN_CTRL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x020)) +#define EMC_DYN_RFSH (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x024)) +#define EMC_DYN_RD_CFG (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x028)) +#define EMC_DYN_RP (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x030)) +#define EMC_DYN_RAS (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x034)) +#define EMC_DYN_SREX (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x038)) +#define EMC_DYN_APR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x03C)) +#define EMC_DYN_DAL (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x040)) +#define EMC_DYN_WR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x044)) +#define EMC_DYN_RC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x048)) +#define EMC_DYN_RFC (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x04C)) +#define EMC_DYN_XSR (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x050)) +#define EMC_DYN_RRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x054)) +#define EMC_DYN_MRD (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x058)) + +#define EMC_DYN_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x100)) +#define EMC_DYN_RASCAS0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x104)) +#define EMC_DYN_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x140)) +#define EMC_DYN_RASCAS1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x144)) +#define EMC_DYN_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x160)) +#define EMC_DYN_RASCAS2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x164)) +#define EMC_DYN_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x180)) +#define EMC_DYN_RASCAS3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x184)) + +/* static RAM access registers */ +#define EMC_STA_CFG0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x200)) +#define EMC_STA_WAITWEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x204)) +#define EMC_STA_WAITOEN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x208)) +#define EMC_STA_WAITRD0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x20C)) +#define EMC_STA_WAITPAGE0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x210)) +#define EMC_STA_WAITWR0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x214)) +#define EMC_STA_WAITTURN0 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x218)) + +#define EMC_STA_CFG1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x220)) +#define EMC_STA_WAITWEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x224)) +#define EMC_STA_WAITOEN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x228)) +#define EMC_STA_WAITRD1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x22C)) +#define EMC_STA_WAITPAGE1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x230)) +#define EMC_STA_WAITWR1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x234)) +#define EMC_STA_WAITTURN1 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x238)) + +#define EMC_STA_CFG2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x240)) +#define EMC_STA_WAITWEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x244)) +#define EMC_STA_WAITOEN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x248)) +#define EMC_STA_WAITRD2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x24C)) +#define EMC_STA_WAITPAGE2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x250)) +#define EMC_STA_WAITWR2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x254)) +#define EMC_STA_WAITTURN2 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x258)) + +#define EMC_STA_CFG3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x260)) +#define EMC_STA_WAITWEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x264)) +#define EMC_STA_WAITOEN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x268)) +#define EMC_STA_WAITRD3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x26C)) +#define EMC_STA_WAITPAGE3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x270)) +#define EMC_STA_WAITWR3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x274)) +#define EMC_STA_WAITTURN3 (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x278)) + +#define EMC_STA_EXT_WAIT (*(volatile unsigned long *)(EMC_BASE_ADDR + 0x880)) + + +/* Timer 0 */ +#define TMR0_BASE_ADDR 0xE0004000 +#define T0IR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x00)) +#define T0TCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x04)) +#define T0TC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x08)) +#define T0PR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x0C)) +#define T0PC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x10)) +#define T0MCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x14)) +#define T0MR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x18)) +#define T0MR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x1C)) +#define T0MR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x20)) +#define T0MR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x24)) +#define T0CCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x28)) +#define T0CR0 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x2C)) +#define T0CR1 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x30)) +#define T0CR2 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x34)) +#define T0CR3 (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x38)) +#define T0EMR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x3C)) +#define T0CTCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x70)) + +/* Timer 1 */ +#define TMR1_BASE_ADDR 0xE0008000 +#define T1IR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x00)) +#define T1TCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x04)) +#define T1TC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x08)) +#define T1PR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x0C)) +#define T1PC (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x10)) +#define T1MCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x14)) +#define T1MR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x18)) +#define T1MR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x1C)) +#define T1MR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x20)) +#define T1MR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x24)) +#define T1CCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x28)) +#define T1CR0 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x2C)) +#define T1CR1 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x30)) +#define T1CR2 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x34)) +#define T1CR3 (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x38)) +#define T1EMR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x3C)) +#define T1CTCR (*(volatile unsigned long *)(TMR1_BASE_ADDR + 0x70)) + +/* Timer 2 */ +#define TMR2_BASE_ADDR 0xE0070000 +#define T2IR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x00)) +#define T2TCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x04)) +#define T2TC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x08)) +#define T2PR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x0C)) +#define T2PC (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x10)) +#define T2MCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x14)) +#define T2MR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x18)) +#define T2MR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x1C)) +#define T2MR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x20)) +#define T2MR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x24)) +#define T2CCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x28)) +#define T2CR0 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x2C)) +#define T2CR1 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x30)) +#define T2CR2 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x34)) +#define T2CR3 (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x38)) +#define T2EMR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x3C)) +#define T2CTCR (*(volatile unsigned long *)(TMR2_BASE_ADDR + 0x70)) + +/* Timer 3 */ +#define TMR3_BASE_ADDR 0xE0074000 +#define T3IR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x00)) +#define T3TCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x04)) +#define T3TC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x08)) +#define T3PR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x0C)) +#define T3PC (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x10)) +#define T3MCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x14)) +#define T3MR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x18)) +#define T3MR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x1C)) +#define T3MR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x20)) +#define T3MR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x24)) +#define T3CCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x28)) +#define T3CR0 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x2C)) +#define T3CR1 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x30)) +#define T3CR2 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x34)) +#define T3CR3 (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x38)) +#define T3EMR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x3C)) +#define T3CTCR (*(volatile unsigned long *)(TMR3_BASE_ADDR + 0x70)) + + +/* Pulse Width Modulator (PWM) */ +#define PWM0_BASE_ADDR 0xE0014000 +#define PWM0IR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x00)) +#define PWM0TCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x04)) +#define PWM0TC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x08)) +#define PWM0PR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x0C)) +#define PWM0PC (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x10)) +#define PWM0MCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x14)) +#define PWM0MR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x18)) +#define PWM0MR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x1C)) +#define PWM0MR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x20)) +#define PWM0MR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x24)) +#define PWM0CCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x28)) +#define PWM0CR0 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x2C)) +#define PWM0CR1 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x30)) +#define PWM0CR2 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x34)) +#define PWM0CR3 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x38)) +#define PWM0EMR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x3C)) +#define PWM0MR4 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x40)) +#define PWM0MR5 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x44)) +#define PWM0MR6 (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x48)) +#define PWM0PCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x4C)) +#define PWM0LER (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x50)) +#define PWM0CTCR (*(volatile unsigned long *)(PWM0_BASE_ADDR + 0x70)) + +#define PWM1_BASE_ADDR 0xE0018000 +#define PWM1IR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x00)) +#define PWM1TCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x04)) +#define PWM1TC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x08)) +#define PWM1PR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x0C)) +#define PWM1PC (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x10)) +#define PWM1MCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x14)) +#define PWM1MR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x18)) +#define PWM1MR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x1C)) +#define PWM1MR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x20)) +#define PWM1MR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x24)) +#define PWM1CCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x28)) +#define PWM1CR0 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x2C)) +#define PWM1CR1 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x30)) +#define PWM1CR2 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x34)) +#define PWM1CR3 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x38)) +#define PWM1EMR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x3C)) +#define PWM1MR4 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x40)) +#define PWM1MR5 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x44)) +#define PWM1MR6 (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x48)) +#define PWM1PCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x4C)) +#define PWM1LER (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x50)) +#define PWM1CTCR (*(volatile unsigned long *)(PWM1_BASE_ADDR + 0x70)) + + +/* Universal Asynchronous Receiver Transmitter 0 (UART0) */ +#define UART0_BASE_ADDR 0xE000C000 +#define U0RBR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0THR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLL (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x00)) +#define U0DLM (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x04)) +#define U0IIR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0FCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x08)) +#define U0LCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x0C)) +#define U0LSR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x14)) +#define U0SCR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x1C)) +#define U0ACR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x20)) +#define U0ICR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x24)) +#define U0FDR (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x28)) +#define U0TER (*(volatile unsigned long *)(UART0_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 1 (UART1) */ +#define UART1_BASE_ADDR 0xE0010000 +#define U1RBR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1THR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLL (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x00)) +#define U1DLM (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x04)) +#define U1IIR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1FCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x08)) +#define U1LCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x0C)) +#define U1MCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x10)) +#define U1LSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x14)) +#define U1MSR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x18)) +#define U1SCR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x1C)) +#define U1ACR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x20)) +#define U1FDR (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x28)) +#define U1TER (*(volatile unsigned long *)(UART1_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 2 (UART2) */ +#define UART2_BASE_ADDR 0xE0078000 +#define U2RBR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2THR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLL (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x00)) +#define U2DLM (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x04)) +#define U2IIR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2FCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x08)) +#define U2LCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x0C)) +#define U2LSR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x14)) +#define U2SCR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x1C)) +#define U2ACR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x20)) +#define U2ICR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x24)) +#define U2FDR (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x28)) +#define U2TER (*(volatile unsigned long *)(UART2_BASE_ADDR + 0x30)) + +/* Universal Asynchronous Receiver Transmitter 3 (UART3) */ +#define UART3_BASE_ADDR 0xE007C000 +#define U3RBR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3THR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLL (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x00)) +#define U3DLM (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x04)) +#define U3IIR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3FCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x08)) +#define U3LCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x0C)) +#define U3LSR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x14)) +#define U3SCR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x1C)) +#define U3ACR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x20)) +#define U3ICR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x24)) +#define U3FDR (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x28)) +#define U3TER (*(volatile unsigned long *)(UART3_BASE_ADDR + 0x30)) + +/* I2C Interface 0 */ +#define I2C0_BASE_ADDR 0xE001C000 +#define I20CONSET (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x00)) +#define I20STAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x04)) +#define I20DAT (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x08)) +#define I20ADR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x0C)) +#define I20SCLH (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x10)) +#define I20SCLL (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x14)) +#define I20CONCLR (*(volatile unsigned long *)(I2C0_BASE_ADDR + 0x18)) + +/* I2C Interface 1 */ +#define I2C1_BASE_ADDR 0xE005C000 +#define I21CONSET (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x00)) +#define I21STAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x04)) +#define I21DAT (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x08)) +#define I21ADR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x0C)) +#define I21SCLH (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x10)) +#define I21SCLL (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x14)) +#define I21CONCLR (*(volatile unsigned long *)(I2C1_BASE_ADDR + 0x18)) + +/* I2C Interface 2 */ +#define I2C2_BASE_ADDR 0xE0080000 +#define I22CONSET (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x00)) +#define I22STAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x04)) +#define I22DAT (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x08)) +#define I22ADR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x0C)) +#define I22SCLH (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x10)) +#define I22SCLL (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x14)) +#define I22CONCLR (*(volatile unsigned long *)(I2C2_BASE_ADDR + 0x18)) + +/* SPI0 (Serial Peripheral Interface 0) */ +#define SPI0_BASE_ADDR 0xE0020000 +#define S0SPCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x00)) +#define S0SPSR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x04)) +#define S0SPDR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x08)) +#define S0SPCCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x0C)) +#define S0SPINT (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x1C)) + +/* SSP0 Controller */ +#define SSP0_BASE_ADDR 0xE0068000 +#define SSP0CR0 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x00)) +#define SSP0CR1 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x04)) +#define SSP0DR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x08)) +#define SSP0SR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x0C)) +#define SSP0CPSR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x10)) +#define SSP0IMSC (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x14)) +#define SSP0RIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x18)) +#define SSP0MIS (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x1C)) +#define SSP0ICR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x20)) +#define SSP0DMACR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x24)) + +/* SSP1 Controller */ +#define SSP1_BASE_ADDR 0xE0030000 +#define SSP1CR0 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x00)) +#define SSP1CR1 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x04)) +#define SSP1DR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x08)) +#define SSP1SR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x0C)) +#define SSP1CPSR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x10)) +#define SSP1IMSC (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x14)) +#define SSP1RIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x18)) +#define SSP1MIS (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x1C)) +#define SSP1ICR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x20)) +#define SSP1DMACR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x24)) + + +/* Real Time Clock */ +#define RTC_BASE_ADDR 0xE0024000 +#define RTC_ILR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x00)) +#define RTC_CTC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x04)) +#define RTC_CCR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x08)) +#define RTC_CIIR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x0C)) +#define RTC_AMR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x10)) +#define RTC_CTIME0 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x14)) +#define RTC_CTIME1 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x18)) +#define RTC_CTIME2 (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x1C)) +#define RTC_SEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x20)) +#define RTC_MIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x24)) +#define RTC_HOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x28)) +#define RTC_DOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x2C)) +#define RTC_DOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x30)) +#define RTC_DOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x34)) +#define RTC_MONTH (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x38)) +#define RTC_YEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x3C)) +#define RTC_CISS (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x40)) +#define RTC_ALSEC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x60)) +#define RTC_ALMIN (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x64)) +#define RTC_ALHOUR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x68)) +#define RTC_ALDOM (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x6C)) +#define RTC_ALDOW (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x70)) +#define RTC_ALDOY (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x74)) +#define RTC_ALMON (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x78)) +#define RTC_ALYEAR (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x7C)) +#define RTC_PREINT (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x80)) +#define RTC_PREFRAC (*(volatile unsigned long *)(RTC_BASE_ADDR + 0x84)) + + +/* A/D Converter 0 (AD0) */ +#define AD0_BASE_ADDR 0xE0034000 +#define AD0CR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x00)) +#define AD0GDR (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x04)) +#define AD0INTEN (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x0C)) +#define AD0DR0 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x10)) +#define AD0DR1 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x14)) +#define AD0DR2 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x18)) +#define AD0DR3 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x1C)) +#define AD0DR4 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x20)) +#define AD0DR5 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x24)) +#define AD0DR6 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x28)) +#define AD0DR7 (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x2C)) +#define AD0STAT (*(volatile unsigned long *)(AD0_BASE_ADDR + 0x30)) + + +/* D/A Converter */ +#define DAC_BASE_ADDR 0xE006C000 +#define DACR (*(volatile unsigned long *)(DAC_BASE_ADDR + 0x00)) + + +/* Watchdog */ +#define WDG_BASE_ADDR 0xE0000000 +#define WDMOD (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x00)) +#define WDTC (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x04)) +#define WDFEED (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x08)) +#define WDTV (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x0C)) +#define WDCLKSEL (*(volatile unsigned long *)(WDG_BASE_ADDR + 0x10)) + +/* CAN CONTROLLERS AND ACCEPTANCE FILTER */ +#define CAN_ACCEPT_BASE_ADDR 0xE003C000 +#define CAN_AFMR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x00)) +#define CAN_SFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x04)) +#define CAN_SFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x08)) +#define CAN_EFF_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x0C)) +#define CAN_EFF_GRP_SA (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x10)) +#define CAN_EOT (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x14)) +#define CAN_LUT_ERR_ADR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x18)) +#define CAN_LUT_ERR (*(volatile unsigned long *)(CAN_ACCEPT_BASE_ADDR + 0x1C)) + +#define CAN_CENTRAL_BASE_ADDR 0xE0040000 +#define CAN_TX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x00)) +#define CAN_RX_SR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x04)) +#define CAN_MSR (*(volatile unsigned long *)(CAN_CENTRAL_BASE_ADDR + 0x08)) + +#define CAN1_BASE_ADDR 0xE0044000 +#define CAN1MOD (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x00)) +#define CAN1CMR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x04)) +#define CAN1GSR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x08)) +#define CAN1ICR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x0C)) +#define CAN1IER (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x10)) +#define CAN1BTR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x14)) +#define CAN1EWL (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x18)) +#define CAN1SR (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x1C)) +#define CAN1RFS (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x20)) +#define CAN1RID (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x24)) +#define CAN1RDA (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x28)) +#define CAN1RDB (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x2C)) + +#define CAN1TFI1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x30)) +#define CAN1TID1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x34)) +#define CAN1TDA1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x38)) +#define CAN1TDB1 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x3C)) +#define CAN1TFI2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x40)) +#define CAN1TID2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x44)) +#define CAN1TDA2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x48)) +#define CAN1TDB2 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x4C)) +#define CAN1TFI3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x50)) +#define CAN1TID3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x54)) +#define CAN1TDA3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x58)) +#define CAN1TDB3 (*(volatile unsigned long *)(CAN1_BASE_ADDR + 0x5C)) + +#define CAN2_BASE_ADDR 0xE0048000 +#define CAN2MOD (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x00)) +#define CAN2CMR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x04)) +#define CAN2GSR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x08)) +#define CAN2ICR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x0C)) +#define CAN2IER (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x10)) +#define CAN2BTR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x14)) +#define CAN2EWL (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x18)) +#define CAN2SR (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x1C)) +#define CAN2RFS (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x20)) +#define CAN2RID (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x24)) +#define CAN2RDA (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x28)) +#define CAN2RDB (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x2C)) + +#define CAN2TFI1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x30)) +#define CAN2TID1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x34)) +#define CAN2TDA1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x38)) +#define CAN2TDB1 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x3C)) +#define CAN2TFI2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x40)) +#define CAN2TID2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x44)) +#define CAN2TDA2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x48)) +#define CAN2TDB2 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x4C)) +#define CAN2TFI3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x50)) +#define CAN2TID3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x54)) +#define CAN2TDA3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x58)) +#define CAN2TDB3 (*(volatile unsigned long *)(CAN2_BASE_ADDR + 0x5C)) + + +/* MultiMedia Card Interface(MCI) Controller */ +#define MCI_BASE_ADDR 0xE008C000 +#define MCI_POWER (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x00)) +#define MCI_CLOCK (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x04)) +#define MCI_ARGUMENT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x08)) +#define MCI_COMMAND (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x0C)) +#define MCI_RESP_CMD (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x10)) +#define MCI_RESP0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x14)) +#define MCI_RESP1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x18)) +#define MCI_RESP2 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x1C)) +#define MCI_RESP3 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x20)) +#define MCI_DATA_TMR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x24)) +#define MCI_DATA_LEN (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x28)) +#define MCI_DATA_CTRL (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x2C)) +#define MCI_DATA_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x30)) +#define MCI_STATUS (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x34)) +#define MCI_CLEAR (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x38)) +#define MCI_MASK0 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x3C)) +#define MCI_MASK1 (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x40)) +#define MCI_FIFO_CNT (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x48)) +#define MCI_FIFO (*(volatile unsigned long *)(MCI_BASE_ADDR + 0x80)) + + +/* I2S Interface Controller (I2S) */ +#define I2S_BASE_ADDR 0xE0088000 +#define I2S_DAO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x00)) +#define I2S_DAI (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x04)) +#define I2S_TX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x08)) +#define I2S_RX_FIFO (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x0C)) +#define I2S_STATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x10)) +#define I2S_DMA1 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x14)) +#define I2S_DMA2 (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x18)) +#define I2S_IRQ (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x1C)) +#define I2S_TXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x20)) +#define I2S_RXRATE (*(volatile unsigned long *)(I2S_BASE_ADDR + 0x24)) + + +/* General-purpose DMA Controller */ +#define DMA_BASE_ADDR 0xFFE04000 +#define GPDMA_INT_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x000)) +#define GPDMA_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x004)) +#define GPDMA_INT_TCCLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x008)) +#define GPDMA_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x00C)) +#define GPDMA_INT_ERR_CLR (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x010)) +#define GPDMA_RAW_INT_TCSTAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x014)) +#define GPDMA_RAW_INT_ERR_STAT (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x018)) +#define GPDMA_ENABLED_CHNS (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x01C)) +#define GPDMA_SOFT_BREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x020)) +#define GPDMA_SOFT_SREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x024)) +#define GPDMA_SOFT_LBREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x028)) +#define GPDMA_SOFT_LSREQ (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x02C)) +#define GPDMA_CONFIG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x030)) +#define GPDMA_SYNC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x034)) + +/* DMA channel 0 registers */ +#define GPDMA_CH0_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x100)) +#define GPDMA_CH0_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x104)) +#define GPDMA_CH0_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x108)) +#define GPDMA_CH0_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x10C)) +#define GPDMA_CH0_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x110)) + +/* DMA channel 1 registers */ +#define GPDMA_CH1_SRC (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x120)) +#define GPDMA_CH1_DEST (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x124)) +#define GPDMA_CH1_LLI (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x128)) +#define GPDMA_CH1_CTRL (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x12C)) +#define GPDMA_CH1_CFG (*(volatile unsigned long *)(DMA_BASE_ADDR + 0x130)) + + +/* USB Controller */ +#define USB_INT_BASE_ADDR 0xE01FC1C0 +#define USB_BASE_ADDR 0xFFE0C200 /* USB Base Address */ + +#define USB_INT_STAT (*(volatile unsigned long *)(USB_INT_BASE_ADDR + 0x00)) + +/* USB Device Interrupt Registers */ +#define DEV_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x00)) +#define DEV_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x04)) +#define DEV_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x08)) +#define DEV_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x0C)) +#define DEV_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x2C)) + +/* USB Device Endpoint Interrupt Registers */ +#define EP_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x30)) +#define EP_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x34)) +#define EP_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x38)) +#define EP_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x3C)) +#define EP_INT_PRIO (*(volatile unsigned long *)(USB_BASE_ADDR + 0x40)) + +/* USB Device Endpoint Realization Registers */ +#define REALIZE_EP (*(volatile unsigned long *)(USB_BASE_ADDR + 0x44)) +#define EP_INDEX (*(volatile unsigned long *)(USB_BASE_ADDR + 0x48)) +#define MAXPACKET_SIZE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x4C)) + +/* USB Device Command Reagisters */ +#define CMD_CODE (*(volatile unsigned long *)(USB_BASE_ADDR + 0x10)) +#define CMD_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x14)) + +/* USB Device Data Transfer Registers */ +#define RX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x18)) +#define TX_DATA (*(volatile unsigned long *)(USB_BASE_ADDR + 0x1C)) +#define RX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x20)) +#define TX_PLENGTH (*(volatile unsigned long *)(USB_BASE_ADDR + 0x24)) +#define USB_CTRL (*(volatile unsigned long *)(USB_BASE_ADDR + 0x28)) + +/* USB Device DMA Registers */ +#define DMA_REQ_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x50)) +#define DMA_REQ_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0x54)) +#define DMA_REQ_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0x58)) +#define UDCA_HEAD (*(volatile unsigned long *)(USB_BASE_ADDR + 0x80)) +#define EP_DMA_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x84)) +#define EP_DMA_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x88)) +#define EP_DMA_DIS (*(volatile unsigned long *)(USB_BASE_ADDR + 0x8C)) +#define DMA_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0x90)) +#define DMA_INT_EN (*(volatile unsigned long *)(USB_BASE_ADDR + 0x94)) +#define EOT_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA0)) +#define EOT_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA4)) +#define EOT_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xA8)) +#define NDD_REQ_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xAC)) +#define NDD_REQ_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB0)) +#define NDD_REQ_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB4)) +#define SYS_ERR_INT_STAT (*(volatile unsigned long *)(USB_BASE_ADDR + 0xB8)) +#define SYS_ERR_INT_CLR (*(volatile unsigned long *)(USB_BASE_ADDR + 0xBC)) +#define SYS_ERR_INT_SET (*(volatile unsigned long *)(USB_BASE_ADDR + 0xC0)) + +/* USB Host and OTG registers are for LPC24xx only */ +/* USB Host Controller */ +#define USBHC_BASE_ADDR 0xFFE0C000 +#define HC_REVISION (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x00)) +#define HC_CONTROL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x04)) +#define HC_CMD_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x08)) +#define HC_INT_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x0C)) +#define HC_INT_EN (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x10)) +#define HC_INT_DIS (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x14)) +#define HC_HCCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x18)) +#define HC_PERIOD_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x1C)) +#define HC_CTRL_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x20)) +#define HC_CTRL_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x24)) +#define HC_BULK_HEAD_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x28)) +#define HC_BULK_CUR_ED (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x2C)) +#define HC_DONE_HEAD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x30)) +#define HC_FM_INTERVAL (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x34)) +#define HC_FM_REMAINING (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x38)) +#define HC_FM_NUMBER (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x3C)) +#define HC_PERIOD_START (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x40)) +#define HC_LS_THRHLD (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x44)) +#define HC_RH_DESCA (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x48)) +#define HC_RH_DESCB (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x4C)) +#define HC_RH_STAT (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x50)) +#define HC_RH_PORT_STAT1 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x54)) +#define HC_RH_PORT_STAT2 (*(volatile unsigned long *)(USBHC_BASE_ADDR + 0x58)) + +/* USB OTG Controller */ +#define USBOTG_BASE_ADDR 0xFFE0C100 +#define OTG_INT_STAT (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x00)) +#define OTG_INT_EN (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x04)) +#define OTG_INT_SET (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x08)) +#define OTG_INT_CLR (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x0C)) +/* On LPC23xx, the name is USBPortSel, on LPC24xx, the name is OTG_STAT_CTRL */ +#define OTG_STAT_CTRL (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define OTG_TIMER (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x14)) + +#define USBOTG_I2C_BASE_ADDR 0xFFE0C300 +#define OTG_I2C_RX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_TX (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x00)) +#define OTG_I2C_STS (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x04)) +#define OTG_I2C_CTL (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x08)) +#define OTG_I2C_CLKHI (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x0C)) +#define OTG_I2C_CLKLO (*(volatile unsigned long *)(USBOTG_I2C_BASE_ADDR + 0x10)) + +/* On LPC23xx, the names are USBClkCtrl and USBClkSt; on LPC24xx, the names are +OTG_CLK_CTRL and OTG_CLK_STAT respectively. */ +#define USBOTG_CLK_BASE_ADDR 0xFFE0CFF0 +#define OTG_CLK_CTRL (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define OTG_CLK_STAT (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Note: below three register name convention is for LPC23xx USB device only, match +with the spec. update in USB Device Section. */ +#define USBPortSel (*(volatile unsigned long *)(USBOTG_BASE_ADDR + 0x10)) +#define USBClkCtrl (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x04)) +#define USBClkSt (*(volatile unsigned long *)(USBOTG_CLK_BASE_ADDR + 0x08)) + +/* Ethernet MAC (32 bit data bus) -- all registers are RW unless indicated in parentheses */ +#define MAC_BASE_ADDR 0xFFE00000 /* AHB Peripheral # 0 */ +#define MAC_MAC1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x000)) /* MAC config reg 1 */ +#define MAC_MAC2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x004)) /* MAC config reg 2 */ +#define MAC_IPGT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x008)) /* b2b InterPacketGap reg */ +#define MAC_IPGR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x00C)) /* non b2b InterPacketGap reg */ +#define MAC_CLRT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x010)) /* CoLlision window/ReTry reg */ +#define MAC_MAXF (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x014)) /* MAXimum Frame reg */ +#define MAC_SUPP (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x018)) /* PHY SUPPort reg */ +#define MAC_TEST (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x01C)) /* TEST reg */ +#define MAC_MCFG (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x020)) /* MII Mgmt ConFiG reg */ +#define MAC_MCMD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x024)) /* MII Mgmt CoMmanD reg */ +#define MAC_MADR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x028)) /* MII Mgmt ADdRess reg */ +#define MAC_MWTD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x02C)) /* MII Mgmt WriTe Data reg (WO) */ +#define MAC_MRDD (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x030)) /* MII Mgmt ReaD Data reg (RO) */ +#define MAC_MIND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x034)) /* MII Mgmt INDicators reg (RO) */ + +#define MAC_SA0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x040)) /* Station Address 0 reg */ +#define MAC_SA1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x044)) /* Station Address 1 reg */ +#define MAC_SA2 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x048)) /* Station Address 2 reg */ + +#define MAC_COMMAND (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x100)) /* Command reg */ +#define MAC_STATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x104)) /* Status reg (RO) */ +#define MAC_RXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x108)) /* Rx descriptor base address reg */ +#define MAC_RXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x10C)) /* Rx status base address reg */ +#define MAC_RXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x110)) /* Rx number of descriptors reg */ +#define MAC_RXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x114)) /* Rx produce index reg (RO) */ +#define MAC_RXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x118)) /* Rx consume index reg */ +#define MAC_TXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x11C)) /* Tx descriptor base address reg */ +#define MAC_TXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x120)) /* Tx status base address reg */ +#define MAC_TXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x124)) /* Tx number of descriptors reg */ +#define MAC_TXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x128)) /* Tx produce index reg */ +#define MAC_TXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x12C)) /* Tx consume index reg (RO) */ + +#define MAC_TSV0 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x158)) /* Tx status vector 0 reg (RO) */ +#define MAC_TSV1 (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x15C)) /* Tx status vector 1 reg (RO) */ +#define MAC_RSV (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x160)) /* Rx status vector reg (RO) */ + +#define MAC_FLOWCONTROLCNT (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x170)) /* Flow control counter reg */ +#define MAC_FLOWCONTROLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x174)) /* Flow control status reg */ + +#define MAC_RXFILTERCTRL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x200)) /* Rx filter ctrl reg */ +#define MAC_RXFILTERWOLSTS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x204)) /* Rx filter WoL status reg (RO) */ +#define MAC_RXFILTERWOLCLR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x208)) /* Rx filter WoL clear reg (WO) */ + +#define MAC_HASHFILTERL (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x210)) /* Hash filter LSBs reg */ +#define MAC_HASHFILTERH (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x214)) /* Hash filter MSBs reg */ + +#define MAC_INTSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE0)) /* Interrupt status reg (RO) */ +#define MAC_INTENABLE (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE4)) /* Interrupt enable reg */ +#define MAC_INTCLEAR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFE8)) /* Interrupt clear reg (WO) */ +#define MAC_INTSET (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFEC)) /* Interrupt set reg (WO) */ + +#define MAC_POWERDOWN (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFF4)) /* Power-down reg */ +#define MAC_MODULEID (*(volatile unsigned long *)(MAC_BASE_ADDR + 0xFFC)) /* Module ID reg (RO) */ + + +#endif // __LPC23xx_H + Index: /webserver/example/EnergyMeters/Source/include/queue.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/queue.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/queue.h (revision 14) @@ -0,0 +1,1249 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include queue.h" +#endif + + + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifdef __cplusplus +extern "C" { +#endif +typedef void * xQueueHandle; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( 0 ) +#define queueSEND_TO_FRONT ( 1 ) + + +/** + * queue. h + *
+ xQueueHandle xQueueCreate(
+                              unsigned portBASE_TYPE uxQueueLength,
+                              unsigned portBASE_TYPE uxItemSize
+                          );
+ * 
+ * + * Creates a new queue instance. This allocates the storage required by the + * new queue and returns a handle for the queue. + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+
+    // Create a queue capable of containing 10 unsigned long values.
+    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
+    if( xQueue1 == 0 )
+    {
+        // Queue was not created and must not be used.
+    }
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+    if( xQueue2 == 0 )
+    {
+        // Queue was not created and must not be used.
+    }
+
+    // ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToToFront(
+                                   xQueueHandle xQueue,
+                                   const void * pvItemToQueue,
+                                   portTickType xTicksToWait
+                               );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ unsigned portLONG ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 unsigned long values.
+    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+    // ...
+
+    if( xQueue1 != 0 )
+    {
+        // Send an unsigned long.  Wait for 10 ticks for space to become
+        // available if necessary.
+        if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+        {
+            // Failed to post the message, even after 10 ticks.
+        }
+    }
+
+    if( xQueue2 != 0 )
+    {
+        // Send a pointer to a struct AMessage object.  Don't block if the
+        // queue is already full.
+        pxMessage = & xMessage;
+        xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBack(
+                                   xQueueHandle xQueue,
+                                   const void * pvItemToQueue,
+                                   portTickType xTicksToWait
+                               );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ unsigned portLONG ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 unsigned long values.
+    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+    // ...
+
+    if( xQueue1 != 0 )
+    {
+        // Send an unsigned long.  Wait for 10 ticks for space to become
+        // available if necessary.
+        if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+        {
+            // Failed to post the message, even after 10 ticks.
+        }
+    }
+
+    if( xQueue2 != 0 )
+    {
+        // Send a pointer to a struct AMessage object.  Don't block if the
+        // queue is already full.
+        pxMessage = & xMessage;
+        xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSend(
+                              xQueueHandle xQueue,
+                              const void * pvItemToQueue,
+                              portTickType xTicksToWait
+                         );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ unsigned portLONG ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 unsigned long values.
+    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+    // ...
+
+    if( xQueue1 != 0 )
+    {
+        // Send an unsigned long.  Wait for 10 ticks for space to become
+        // available if necessary.
+        if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+        {
+            // Failed to post the message, even after 10 ticks.
+        }
+    }
+
+    if( xQueue2 != 0 )
+    {
+        // Send a pointer to a struct AMessage object.  Don't block if the
+        // queue is already full.
+        pxMessage = & xMessage;
+        xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSend(
+									xQueueHandle xQueue,
+									const void * pvItemToQueue,
+									portTickType xTicksToWait
+									portBASE_TYPE xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ unsigned portLONG ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ xQueueHandle xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 unsigned long values.
+    xQueue1 = xQueueCreate( 10, sizeof( unsigned portLONG ) );
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+    // ...
+
+    if( xQueue1 != 0 )
+    {
+        // Send an unsigned long.  Wait for 10 ticks for space to become
+        // available if necessary.
+        if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
+        {
+            // Failed to post the message, even after 10 ticks.
+        }
+    }
+
+    if( xQueue2 != 0 )
+    {
+        // Send a pointer to a struct AMessage object.  Don't block if the
+        // queue is already full.
+        pxMessage = & xMessage;
+        xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); + +/** + * queue. h + *
+ portBASE_TYPE xQueuePeek(
+                             xQueueHandle xQueue,
+                             void *pvBuffer,
+                             portTickType xTicksToWait
+                         );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+    if( xQueue == 0 )
+    {
+        // Failed to create the queue.
+    }
+
+    // ...
+
+    // Send a pointer to a struct AMessage object.  Don't block if the
+    // queue is already full.
+    pxMessage = & xMessage;
+    xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+    if( xQueue != 0 )
+    {
+        // Peek a message on the created queue.  Block for 10 ticks if a
+        // message is not immediately available.
+        if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+        {
+            // pcRxedMessage now points to the struct AMessage variable posted
+            // by vATask, but the item still remains on the queue.
+        }
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceive(
+                                 xQueueHandle xQueue,
+                                 void *pvBuffer,
+                                 portTickType xTicksToWait
+                            );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_RATE_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+    if( xQueue == 0 )
+    {
+        // Failed to create the queue.
+    }
+
+    // ...
+
+    // Send a pointer to a struct AMessage object.  Don't block if the
+    // queue is already full.
+    pxMessage = & xMessage;
+    xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+    if( xQueue != 0 )
+    {
+        // Receive a message on the created queue.  Block for 10 ticks if a
+        // message is not immediately available.
+        if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+        {
+            // pcRxedMessage now points to the struct AMessage variable posted
+            // by vATask.
+        }
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericReceive(
+                                       xQueueHandle xQueue,
+                                       void *pvBuffer,
+                                       portTickType xTicksToWait
+                                       portBASE_TYPE xJustPeek
+                                    );
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_RATE_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+    portCHAR ucMessageID;
+    portCHAR ucData[ 20 ];
+ } xMessage;
+
+ xQueueHandle xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+    // Create a queue capable of containing 10 pointers to AMessage structures.
+    // These should be passed by pointer as they contain a lot of data.
+    xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+    if( xQueue == 0 )
+    {
+        // Failed to create the queue.
+    }
+
+    // ...
+
+    // Send a pointer to a struct AMessage object.  Don't block if the
+    // queue is already full.
+    pxMessage = & xMessage;
+    xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+    if( xQueue != 0 )
+    {
+        // Receive a message on the created queue.  Block for 10 ticks if a
+        // message is not immediately available.
+        if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+        {
+            // pcRxedMessage now points to the struct AMessage variable posted
+            // by vATask.
+        }
+    }
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek ); + +/** + * queue. h + *
unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \page uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue ); + +/** + * queue. h + *
void vQueueDelete( xQueueHandle xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \page vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete( xQueueHandle xQueue ); + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToFrontFromISR(
+                                         xQueueHandle pxQueue,
+                                         const void *pvItemToQueue,
+                                         portBASE_TYPE *pxHigherPriorityTaskWoken
+                                      );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ portCHAR cIn;
+ portBASE_TYPE xHigherPrioritTaskWoken;
+
+    // We have not woken a task at the start of the ISR.
+    xHigherPriorityTaskWoken = pdFALSE;
+
+    // Loop until the buffer is empty.
+    do
+    {
+        // Obtain a byte from the buffer.
+        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );						
+
+        // Post the byte.  
+        xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+    } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+    // Now the buffer is empty we can switch context if necessary.
+    if( xHigherPriorityTaskWoken )
+    {
+        taskYIELD ();
+    }
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendToBackFromISR(
+                                         xQueueHandle pxQueue,
+                                         const void *pvItemToQueue,
+                                         portBASE_TYPE *pxHigherPriorityTaskWoken
+                                      );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ portCHAR cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // We have not woken a task at the start of the ISR.
+    xHigherPriorityTaskWoken = pdFALSE;
+
+    // Loop until the buffer is empty.
+    do
+    {
+        // Obtain a byte from the buffer.
+        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );						
+
+        // Post the byte.
+        xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+    } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+    // Now the buffer is empty we can switch context if necessary.
+    if( xHigherPriorityTaskWoken )
+    {
+        taskYIELD ();
+    }
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueSendFromISR(
+                                     xQueueHandle pxQueue,
+                                     const void *pvItemToQueue,
+                                     portBASE_TYPE *pxHigherPriorityTaskWoken
+                                );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ portCHAR cIn;
+ portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // We have not woken a task at the start of the ISR.
+    xHigherPriorityTaskWoken = pdFALSE;
+
+    // Loop until the buffer is empty.
+    do
+    {
+        // Obtain a byte from the buffer.
+        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );						
+
+        // Post the byte.  
+        xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+    } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+    // Now the buffer is empty we can switch context if necessary.
+    if( xHigherPriorityTaskWoken )
+    {
+        // Actual macro used here is port specific.
+        taskYIELD_FROM_ISR ();
+    }
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK ) + +/** + * queue. h + *
+ portBASE_TYPE xQueueGenericSendFromISR(
+                                           xQueueHandle pxQueue,
+                                           const void *pvItemToQueue,
+                                           portBASE_TYPE *pxHigherPriorityTaskWoken,
+										   portBASE_TYPE xCopyPosition
+                                       );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ portCHAR cIn;
+ portBASE_TYPE xHigherPriorityTaskWokenByPost;
+
+    // We have not woken a task at the start of the ISR.
+    xHigherPriorityTaskWokenByPost = pdFALSE;
+
+    // Loop until the buffer is empty.
+    do
+    {
+        // Obtain a byte from the buffer.
+        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );						
+
+        // Post each byte.
+        xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+    } while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+    // Now the buffer is empty we can switch context if necessary.  Note that the
+    // name of the yield function required is port specific.
+    if( xHigherPriorityTaskWokenByPost )
+    {
+        taskYIELD_YIELD_FROM_ISR();
+    }
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ); + +/** + * queue. h + *
+ portBASE_TYPE xQueueReceiveFromISR(
+                                       xQueueHandle pxQueue,
+                                       void *pvBuffer,
+                                       portBASE_TYPE *pxTaskWoken
+                                   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param pxQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ xQueueHandle xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ portCHAR cValueToPost;
+ const portTickType xBlockTime = ( portTickType )0xff;
+
+    // Create a queue capable of containing 10 characters.
+    xQueue = xQueueCreate( 10, sizeof( portCHAR ) );
+    if( xQueue == 0 )
+    {
+        // Failed to create the queue.
+    }
+
+    // ...
+
+    // Post some characters that will be used within an ISR.  If the queue
+    // is full then this task will block for xBlockTime ticks.
+    cValueToPost = 'a';
+    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+    cValueToPost = 'b';
+    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+
+    // ... keep posting characters ... this task may block when the queue
+    // becomes full.
+
+    cValueToPost = 'c';
+    xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+ portCHAR cRxedChar;
+
+    while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+    {
+        // A character was received.  Output the character now.
+        vOutputCharacter( cRxedChar );
+
+        // If removing the character from the queue woke the task that was
+        // posting onto the queue cTaskWokenByReceive will have been set to
+        // pdTRUE.  No matter how many times this loop iterates only one
+        // task will be woken.
+    }
+
+    if( cTaskWokenByPost != ( portCHAR ) pdFALSE;
+    {
+        taskYIELD ();
+    }
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ); + +/* + * Utilities to query queue that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ); +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ); +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ); + + +/* + * xQueueAltGenericSend() is an alternative version of xQueueGenericSend(). + * Likewise xQueueAltGenericReceive() is an alternative version of + * xQueueGenericReceive(). + * + * The source code that implements the alternative (Alt) API is much + * simpler because it executes everything from within a critical section. + * This is the approach taken by many other RTOSes, but FreeRTOS.org has the + * preferred fully featured API too. The fully featured API has more + * complex code that takes longer to execute, but makes much less use of + * critical sections. Therefore the alternative API sacrifices interrupt + * responsiveness to gain execution speed, whereas the fully featured API + * sacrifices execution speed to ensure better interrupt responsiveness. + */ +signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); +signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); +#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT ) +#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK ) +#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE ) +#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE ) + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); +signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); +signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ); +signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ); + +/* + * For internal use only. Use xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting() instead of calling these functions directly. + */ +xQueueHandle xQueueCreateMutex( void ); +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ); +portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ); + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcName ); +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + Index: /webserver/example/EnergyMeters/Source/include/croutine.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/croutine.h (revision 14) +++ /webserver/example/EnergyMeters/Source/include/croutine.h (revision 14) @@ -0,0 +1,743 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INC_FREERTOS_H + #error "#include FreeRTOS.h" must appear in source files before "#include croutine.h" +#endif + + + + +#ifndef CO_ROUTINE_H +#define CO_ROUTINE_H + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Used to hide the implementation of the co-routine control block. The +control block structure however has to be included in the header due to +the macro implementation of the co-routine functionality. */ +typedef void * xCoRoutineHandle; + +/* Defines the prototype to which co-routine functions must conform. */ +typedef void (*crCOROUTINE_CODE)( xCoRoutineHandle, unsigned portBASE_TYPE ); + +typedef struct corCoRoutineControlBlock +{ + crCOROUTINE_CODE pxCoRoutineFunction; + xListItem xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */ + xListItem xEventListItem; /*< List item used to place the CRCB in event lists. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the co-routine in relation to other co-routines. */ + unsigned portBASE_TYPE uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */ + unsigned portSHORT uxState; /*< Used internally by the co-routine implementation. */ +} corCRCB; /* Co-routine control block. Note must be identical in size down to uxPriority with tskTCB. */ + +/** + * croutine. h + *
+ portBASE_TYPE xCoRoutineCreate(
+                                 crCOROUTINE_CODE pxCoRoutineCode,
+                                 unsigned portBASE_TYPE uxPriority,
+                                 unsigned portBASE_TYPE uxIndex
+                               );
+ * + * Create a new co-routine and add it to the list of co-routines that are + * ready to run. + * + * @param pxCoRoutineCode Pointer to the co-routine function. Co-routine + * functions require special syntax - see the co-routine section of the WEB + * documentation for more information. + * + * @param uxPriority The priority with respect to other co-routines at which + * the co-routine will run. + * + * @param uxIndex Used to distinguish between different co-routines that + * execute the same function. See the example below and the co-routine section + * of the WEB documentation for further information. + * + * @return pdPASS if the co-routine was successfully created and added to a ready + * list, otherwise an error code defined with ProjDefs.h. + * + * Example usage: +
+ // Co-routine to be created.
+ void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ static const char cLedToFlash[ 2 ] = { 5, 6 };
+ static const portTickType xTimeToDelay[ 2 ] = { 200, 400 };
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // This co-routine just delays for a fixed period, then toggles
+         // an LED.  Two co-routines are created using this function, so
+         // the uxIndex parameter is used to tell the co-routine which
+         // LED to flash and how long to delay.  This assumes xQueue has
+         // already been created.
+         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+
+ // Function that creates two co-routines.
+ void vOtherFunction( void )
+ {
+ unsigned char ucParameterToPass;
+ xTaskHandle xHandle;
+		
+     // Create two co-routines at priority 0.  The first is given index 0
+     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+     // is given index 1 so toggles LED 6 every 400 ticks.
+     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+     {
+         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+     }
+ }
+   
+ * \defgroup xCoRoutineCreate xCoRoutineCreate + * \ingroup Tasks + */ +signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ); + + +/** + * croutine. h + *
+ void vCoRoutineSchedule( void );
+ * + * Run a co-routine. + * + * vCoRoutineSchedule() executes the highest priority co-routine that is able + * to run. The co-routine will execute until it either blocks, yields or is + * preempted by a task. Co-routines execute cooperatively so one + * co-routine cannot be preempted by another, but can be preempted by a task. + * + * If an application comprises of both tasks and co-routines then + * vCoRoutineSchedule should be called from the idle task (in an idle task + * hook). + * + * Example usage: +
+ // This idle task hook will schedule a co-routine each time it is called.
+ // The rest of the idle task will execute between co-routine calls.
+ void vApplicationIdleHook( void )
+ {
+	vCoRoutineSchedule();
+ }
+
+ // Alternatively, if you do not require any other part of the idle task to
+ // execute, the idle task hook can call vCoRoutineScheduler() within an
+ // infinite loop.
+ void vApplicationIdleHook( void )
+ {
+    for( ;; )
+    {
+        vCoRoutineSchedule();
+    }
+ }
+ 
+ * \defgroup vCoRoutineSchedule vCoRoutineSchedule + * \ingroup Tasks + */ +void vCoRoutineSchedule( void ); + +/** + * croutine. h + *
+ crSTART( xCoRoutineHandle xHandle );
+ * + * This macro MUST always be called at the start of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portLONG ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0: + +/** + * croutine. h + *
+ crEND();
+ * + * This macro MUST always be called at the end of a co-routine function. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portLONG ulAVariable;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+          // Co-routine functionality goes here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crSTART crSTART + * \ingroup Tasks + */ +#define crEND() } + +/* + * These macros are intended for internal use by the co-routine implementation + * only. The macros should not be used directly by application writers. + */ +#define crSET_STATE0( xHandle ) ( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return; case (__LINE__ * 2): +#define crSET_STATE1( xHandle ) ( ( corCRCB * )xHandle)->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1): + +/** + * croutine. h + *
+ crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );
+ * + * Delay a co-routine for a fixed period of time. + * + * crDELAY can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * @param xHandle The handle of the co-routine to delay. This is the xHandle + * parameter of the co-routine function. + * + * @param xTickToDelay The number of ticks that the co-routine should delay + * for. The actual amount of time this equates to is defined by + * configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_RATE_MS + * can be used to convert ticks to milliseconds. + * + * Example usage: +
+ // Co-routine to be created.
+ void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ // This may not be necessary for const variables.
+ // We are to delay for 200ms.
+ static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+
+     // Must start every co-routine with a call to crSTART();
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+        // Delay for 200ms.
+        crDELAY( xHandle, xDelayTime );
+
+        // Do something here.
+     }
+
+     // Must end every co-routine with a call to crEND();
+     crEND();
+ }
+ * \defgroup crDELAY crDELAY + * \ingroup Tasks + */ +#define crDELAY( xHandle, xTicksToDelay ) \ + if( xTicksToDelay > 0 ) \ + { \ + vCoRoutineAddToDelayedList( xTicksToDelay, NULL ); \ + } \ + crSET_STATE0( xHandle ); + +/** + *
+ crQUEUE_SEND(
+                  xCoRoutineHandle xHandle,
+                  xQueueHandle pxQueue,
+                  void *pvItemToQueue,
+                  portTickType xTicksToWait,
+                  portBASE_TYPE *pxResult
+             )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_SEND can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue on which the data will be posted. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvItemToQueue A pointer to the data being posted onto the queue. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied from pvItemToQueue into the queue + * itself. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for space to become available on the queue, should space not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example + * below). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully posted onto the queue, otherwise it will be set to an + * error defined within ProjDefs.h. + * + * Example usage: +
+ // Co-routine function that blocks for a fixed period then posts a number onto
+ // a queue.
+ static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xNumberToPost = 0;
+ static portBASE_TYPE xResult;
+
+    // Co-routines must begin with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // This assumes the queue has already been created.
+        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+        if( xResult != pdPASS )
+        {
+            // The message was not posted!
+        }
+
+        // Increment the number to be posted onto the queue.
+        xNumberToPost++;
+
+        // Delay for 100 ticks.
+        crDELAY( xHandle, 100 );
+    }
+
+    // Co-routines must end with a call to crEND().
+    crEND();
+ }
+ * \defgroup crQUEUE_SEND crQUEUE_SEND + * \ingroup Tasks + */ +#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \ +{ \ + *pxResult = xQueueCRSend( pxQueue, pvItemToQueue, xTicksToWait ); \ + if( *pxResult == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( xHandle ); \ + *pxResult = xQueueCRSend( pxQueue, pvItemToQueue, 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( xHandle ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_RECEIVE(
+                     xCoRoutineHandle xHandle,
+                     xQueueHandle pxQueue,
+                     void *pvBuffer,
+                     portTickType xTicksToWait,
+                     portBASE_TYPE *pxResult
+                 )
+ * + * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine + * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks. + * + * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas + * xQueueSend() and xQueueReceive() can only be used from tasks. + * + * crQUEUE_RECEIVE can only be called from the co-routine function itself - not + * from within a function called by the co-routine function. This is because + * co-routines do not maintain their own stack. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xHandle The handle of the calling co-routine. This is the xHandle + * parameter of the co-routine function. + * + * @param pxQueue The handle of the queue from which the data will be received. + * The handle is obtained as the return value when the queue is created using + * the xQueueCreate() API function. + * + * @param pvBuffer The buffer into which the received item is to be copied. + * The number of bytes of each queued item is specified when the queue is + * created. This number of bytes is copied into pvBuffer. + * + * @param xTickToDelay The number of ticks that the co-routine should block + * to wait for data to become available from the queue, should data not be + * available immediately. The actual amount of time this equates to is defined + * by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant + * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the + * crQUEUE_SEND example). + * + * @param pxResult The variable pointed to by pxResult will be set to pdPASS if + * data was successfully retrieved from the queue, otherwise it will be set to + * an error code as defined within ProjDefs.h. + * + * Example usage: +
+ // A co-routine receives the number of an LED to flash from a queue.  It
+ // blocks on the queue until the number is received.
+ static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+ static portBASE_TYPE xResult;
+ static unsigned portBASE_TYPE uxLEDToFlash;
+
+    // All co-routines must start with a call to crSTART().
+    crSTART( xHandle );
+
+    for( ;; )
+    {
+        // Wait for data to become available on the queue.
+        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+        if( xResult == pdPASS )
+        {
+            // We received the LED to flash - flash it!
+            vParTestToggleLED( uxLEDToFlash );
+        }
+    }
+
+    crEND();
+ }
+ * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \ +{ \ + *pxResult = xQueueCRReceive( pxQueue, pvBuffer, xTicksToWait ); \ + if( *pxResult == errQUEUE_BLOCKED ) \ + { \ + crSET_STATE0( xHandle ); \ + *pxResult = xQueueCRReceive( pxQueue, pvBuffer, 0 ); \ + } \ + if( *pxResult == errQUEUE_YIELD ) \ + { \ + crSET_STATE1( xHandle ); \ + *pxResult = pdPASS; \ + } \ +} + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvItemToQueue,
+                            portBASE_TYPE xCoRoutinePreviouslyWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue + * that is being used from within a co-routine. + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto + * the same queue multiple times from a single interrupt. The first call + * should always pass in pdFALSE. Subsequent calls should pass in + * the value returned from the previous call. + * + * @return pdTRUE if a co-routine was woken by posting onto the queue. This is + * used by the ISR to determine if a context switch may be required following + * the ISR. + * + * Example usage: +
+ // A co-routine that blocks on a queue waiting for characters to be received.
+ static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ portCHAR cRxedChar;
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Wait for data to become available on the queue.  This assumes the
+         // queue xCommsRxQueue has already been created!
+         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+         // Was a character received?
+         if( xResult == pdPASS )
+         {
+             // Process the character here.
+         }
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to send characters received on a serial port to
+ // a co-routine.
+ void vUART_ISR( void )
+ {
+ portCHAR cRxedChar;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     // We loop around reading characters until there are none left in the UART.
+     while( UART_RX_REG_NOT_EMPTY() )
+     {
+         // Obtain the character from the UART.
+         cRxedChar = UART_RX_REG;
+
+         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+         // the first time around the loop.  If the post causes a co-routine
+         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+         // In this manner we can ensure that if more than one co-routine is
+         // blocked on the queue only one is woken by this ISR no matter how
+         // many characters are posted to the queue.
+         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+     }
+ }
+ * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) + + +/** + * croutine. h + *
+  crQUEUE_SEND_FROM_ISR(
+                            xQueueHandle pxQueue,
+                            void *pvBuffer,
+                            portBASE_TYPE * pxCoRoutineWoken
+                       )
+ * + * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the + * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR() + * functions used by tasks. + * + * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to + * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and + * xQueueReceiveFromISR() can only be used to pass data between a task and and + * ISR. + * + * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data + * from a queue that is being used from within a co-routine (a co-routine + * posted to the queue). + * + * See the co-routine section of the WEB documentation for information on + * passing data between tasks and co-routines and between ISR's and + * co-routines. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvBuffer A pointer to a buffer into which the received item will be + * placed. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from the queue into + * pvBuffer. + * + * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become + * available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a + * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise + * *pxCoRoutineWoken will remain unchanged. + * + * @return pdTRUE an item was successfully received from the queue, otherwise + * pdFALSE. + * + * Example usage: +
+ // A co-routine that posts a character to a queue then blocks for a fixed
+ // period.  The character is incremented each time.
+ static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+ {
+ // cChar holds its value while this co-routine is blocked and must therefore
+ // be declared static.
+ static portCHAR cCharToTx = 'a';
+ portBASE_TYPE xResult;
+
+     // All co-routines must start with a call to crSTART().
+     crSTART( xHandle );
+
+     for( ;; )
+     {
+         // Send the next character to the queue.
+         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+         if( xResult == pdPASS )
+         {
+             // The character was successfully posted to the queue.
+         }
+		 else
+		 {
+			// Could not post the character to the queue.
+		 }
+
+         // Enable the UART Tx interrupt to cause an interrupt in this
+		 // hypothetical UART.  The interrupt will obtain the character
+		 // from the queue and send it.
+		 ENABLE_RX_INTERRUPT();
+
+		 // Increment to the next character then block for a fixed period.
+		 // cCharToTx will maintain its value across the delay as it is
+		 // declared static.
+		 cCharToTx++;
+		 if( cCharToTx > 'x' )
+		 {
+			cCharToTx = 'a';
+		 }
+		 crDELAY( 100 );
+     }
+
+     // All co-routines must end with a call to crEND().
+     crEND();
+ }
+
+ // An ISR that uses a queue to receive characters to send on a UART.
+ void vUART_ISR( void )
+ {
+ portCHAR cCharToTx;
+ portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+     while( UART_TX_REG_EMPTY() )
+     {
+         // Are there any characters in the queue waiting to be sent?
+		 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+		 // is woken by the post - ensuring that only a single co-routine is
+		 // woken no matter how many times we go around this loop.
+         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+		 {
+			 SEND_CHARACTER( cCharToTx );
+		 }
+     }
+ }
+ * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR + * \ingroup Tasks + */ +#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( pxQueue, pvBuffer, pxCoRoutineWoken ) + +/* + * This function is intended for internal use by the co-routine macros only. + * The macro nature of the co-routine implementation requires that the + * prototype appears here. The function should not be used by application + * writers. + * + * Removes the current co-routine from its ready list and places it in the + * appropriate delayed list. + */ +void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ); + +/* + * This function is intended for internal use by the queue implementation only. + * The function should not be used by application writers. + * + * Removes the highest priority co-routine from the event list and places it in + * the pending ready list. + */ +signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ); + +#ifdef __cplusplus +} +#endif + +#endif /* CO_ROUTINE_H */ Index: /webserver/example/EnergyMeters/Source/include/portable.h =================================================================== --- /webserver/example/EnergyMeters/Source/include/portable.h (revision 17) +++ /webserver/example/EnergyMeters/Source/include/portable.h (revision 17) @@ -0,0 +1,343 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Include the macro file relevant to the port being used. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT + #include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT + #include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef GCC_MEGA_AVR + #include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR + #include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT + #include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT + #include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT + #include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h" +#endif + +#ifdef _FEDPICC + #include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL + #include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +//#ifdef GCC_ARM7 + //#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +//#endif + +//#ifdef GCC_ARM7_ECLIPSE +// #include "portmacro.h" +//#endif + +//#ifdef ROWLEY_LPC23xx + #include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" + // #warning "ROWLEY_LPC23xx" + +//#endif + +#ifdef IAR_MSP430 + #include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 + #include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 + #include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS + #include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC + #include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR + #include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR + #include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR + #include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR + #include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR + #include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC + #include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR + #include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S + #include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 + #include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 + #include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 + #include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM + #include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR + #include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC + #include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE + #include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 + #include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 + #include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC + #include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR + #include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 + #include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 + #include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE + #include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\PC\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT + /* A short file name has to be used in place of the normal + FreeRTOSConfig.h when using the Borland compiler. */ + #include "frconfig.h" + #include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" + typedef void ( __interrupt __far *pxISR )(); +#endif + +#ifdef __GNUC__ + #ifdef __AVR32_AVR32A__ + #include "portmacro.h" + #endif +#endif + +#ifdef __ICCAVR32__ + #ifdef __CORE__ + #if __CORE__ == __AVR32A__ + #include "portmacro.h" + #endif + #endif +#endif + +#ifdef __91467D + #include "portmacro.h" +#endif + +#ifdef __96340 + #include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ + #include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ + #include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +/* Catch all to ensure portmacro.h is included in the build. Newer demos +have the path as part of the project options, rather than as relative from +the project location. If portENTER_CRITICAL() has not been defined then +portmacro.h has not yet been included - as every portmacro.h provides a +portENTER_CRITICAL() definition. Check the demo application for your demo +to find the path to the correct portmacro.h file. */ +#ifndef portENTER_CRITICAL + #include "portmacro.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ); + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc( size_t xSize ); +void vPortFree( void *pv ); +void vPortInitialiseBlocks( void ); + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +portBASE_TYPE xPortStartScheduler( void ); + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler( void ); + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + Index: /webserver/example/EnergyMeters/Source/queue.c =================================================================== --- /webserver/example/EnergyMeters/Source/queue.c (revision 14) +++ /webserver/example/EnergyMeters/Source/queue.c (revision 14) @@ -0,0 +1,1443 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +/* Constants used with the cRxLock and cTxLock structure members. */ +#define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 ) + +#define queueERRONEOUS_UNBLOCK ( -1 ) + +/* For internal use only. */ +#define queueSEND_TO_BACK ( 0 ) +#define queueSEND_TO_FRONT ( 1 ) + +/* Effectively make a union out of the xQUEUE structure. */ +#define pxMutexHolder pcTail +#define uxQueueType pcHead +#define uxRecursiveCallCount pcReadFrom +#define queueQUEUE_IS_MUTEX NULL + +/* Semaphores do not actually store or copy data, so have an items size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 ) +#define queueDONT_BLOCK ( ( portTickType ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 ) + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. + */ +typedef struct QueueDefinition +{ + signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */ + signed portCHAR *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + + signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */ + signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */ + + xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */ + unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */ + + signed portBASE_TYPE xRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + signed portBASE_TYPE xTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + +} xQUEUE; +/*-----------------------------------------------------------*/ + +/* + * Inside this file xQueueHandle is a pointer to a xQUEUE structure. + * To keep the definition private the API header file defines it as a + * pointer to void. + */ +typedef xQUEUE * xQueueHandle; + +/* + * Prototypes for public functions are included here so we don't have to + * include the API header file (as it defines xQueueHandle differently). These + * functions are documented in the API header file. + */ +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ); +signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ); +void vQueueDelete( xQueueHandle xQueue ); +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ); +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ); +xQueueHandle xQueueCreateMutex( void ); +xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ); +portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ); +portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ); +signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ); +signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ); +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ); +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ); +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ); + +/* + * Co-routine queue functions differ from task queue functions. Co-routines are + * an optional component. + */ +#if configUSE_CO_ROUTINES == 1 + signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ); + signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ); + signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ); + signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ); +#endif + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if configQUEUE_REGISTRY_SIZE > 0 + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + signed portCHAR *pcQueueName; + xQueueHandle xHandle; + } xQueueRegistryItem; + + /* The queue registry is simply an array of xQueueRegistryItem structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + + /* Removes a queue from the registry by simply setting the pcQueueName + member to NULL. */ + static void vQueueUnregisterQueue( xQueueHandle xQueue ); + void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName ); +#endif + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( xQueueHandle pxQueue ); + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ); + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ); + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ); + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ); +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ +{ \ + taskENTER_CRITICAL(); \ + { \ + if( pxQueue->xRxLock == queueUNLOCKED ) \ + { \ + pxQueue->xRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( pxQueue->xTxLock == queueUNLOCKED ) \ + { \ + pxQueue->xTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL(); \ +} +/*-----------------------------------------------------------*/ + + +/*----------------------------------------------------------- + * PUBLIC QUEUE MANAGEMENT API documented in queue.h + *----------------------------------------------------------*/ + +xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) +{ +xQUEUE *pxNewQueue; +size_t xQueueSizeInBytes; + + /* Allocate the new queue structure. */ + if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 ) + { + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Create the list of pointers to queue items. The queue is one byte + longer than asked for to make wrap checking easier/faster. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; + + pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes ); + if( pxNewQueue->pcHead != NULL ) + { + /* Initialise the queue members as described above where the + queue type is defined. */ + pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize ); + pxNewQueue->uxMessagesWaiting = 0; + pxNewQueue->pcWriteTo = pxNewQueue->pcHead; + pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize ); + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + /* Likewise ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + traceQUEUE_CREATE( pxNewQueue ); + + return pxNewQueue; + } + else + { + traceQUEUE_CREATE_FAILED(); + vPortFree( pxNewQueue ); + } + } + } + + /* Will only reach here if we could not allocate enough memory or no memory + was required. */ + return NULL; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + xQueueHandle xQueueCreateMutex( void ) + { + xQUEUE *pxNewQueue; + + /* Allocate the new queue structure. */ + pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) ); + if( pxNewQueue != NULL ) + { + /* Information required for priority inheritance. */ + pxNewQueue->pxMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* Queues used as a mutex no data is actually copied into or out + of the queue. */ + pxNewQueue->pcWriteTo = NULL; + pxNewQueue->pcReadFrom = NULL; + + /* Each mutex has a length of 1 (like a binary semaphore) and + an item size of 0 as nothing is actually copied into or out + of the mutex. */ + pxNewQueue->uxMessagesWaiting = 0; + pxNewQueue->uxLength = 1; + pxNewQueue->uxItemSize = 0; + pxNewQueue->xRxLock = queueUNLOCKED; + pxNewQueue->xTxLock = queueUNLOCKED; + + /* Ensure the event queues start with the correct state. */ + vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) ); + + /* Start with the semaphore in the expected state. */ + xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK ); + + traceCREATE_MUTEX( pxNewQueue ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + + return pxNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_RECURSIVE_MUTEXES == 1 + + portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex ) + { + portBASE_TYPE xReturn; + + /* If this is the task that holds the mutex then pxMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->uxRecursiveCallCount )--; + + /* Have we unwound the call count? */ + if( pxMutex->uxRecursiveCallCount == 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + + xReturn = pdPASS; + } + else + { + /* We cannot give the mutex because we are not the holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_RECURSIVE_MUTEXES == 1 + + portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime ) + { + portBASE_TYPE xReturn; + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() ) + { + ( pxMutex->uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE ); + + /* pdPASS will only be returned if we successfully obtained the mutex, + we may have blocked to reach here. */ + if( xReturn == pdPASS ) + { + ( pxMutex->uxRecursiveCallCount )++; + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if configUSE_COUNTING_SEMAPHORES == 1 + + xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) + { + xQueueHandle pxHandle; + + pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH ); + + if( pxHandle != NULL ) + { + pxHandle->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + return pxHandle; + } + +#endif /* configUSE_COUNTING_SEMAPHORES */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + taskYIELD(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( !xTaskResumeAll() ) + { + taskYIELD(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } +} +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + + signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND( pxQueue ); + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. */ + taskYIELD(); + } + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + taskYIELD(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } + taskEXIT_CRITICAL(); + } + } + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +#if configUSE_ALTERNATIVE_API == 1 + + signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) + { + signed portBASE_TYPE xEntryTimeSet = pdFALSE; + xTimeOutType xTimeOut; + signed portCHAR *pcOriginalReadPosition; + + for( ;; ) + { + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* We are actually removing data. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + taskYIELD(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + taskYIELD(); + } + } + + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + taskENTER_CRITICAL(); + { + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + taskYIELD(); + } + } + else + { + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } + taskEXIT_CRITICAL(); + } + } + + +#endif /* configUSE_ALTERNATIVE_API */ +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + /* Similar to xQueueGenericSend, except we don't block if there is no room + in the queue. Also we don't directly wake a task that was blocked on a + queue read, instead we return a flag to say whether a context switch is + required or not (i.e. has a task with a higher priority than us been woken + by this post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If the queue is locked we do not alter the event list. This will + be done when the queue is unlocked later. */ + if( pxQueue->xTxLock == queueUNLOCKED ) + { + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + ++( pxQueue->xTxLock ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) +{ +signed portBASE_TYPE xEntryTimeSet = pdFALSE; +xTimeOutType xTimeOut; +signed portCHAR *pcOriginalReadPosition; + + /* This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there data in the queue now? To be running we must be + the highest priority task wanting to access the queue. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Remember our read position in case we are just peeking. */ + pcOriginalReadPosition = pxQueue->pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + + if( xJustPeeking == pdFALSE ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* We are actually removing data. */ + --( pxQueue->uxMessagesWaiting ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle(); + } + } + #endif + + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) + { + taskYIELD(); + } + } + } + else + { + traceQUEUE_PEEK( pxQueue ); + + /* We are not removing the data, so reset our read + pointer. */ + pxQueue->pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + taskYIELD(); + } + } + + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( portTickType ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueEmpty( pxQueue ) ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + portENTER_CRITICAL(); + { + vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); + } + portEXIT_CRITICAL(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( !xTaskResumeAll() ) + { + taskYIELD(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + } +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) +{ +signed portBASE_TYPE xReturn; +unsigned portBASE_TYPE uxSavedInterruptStatus; + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* We cannot block from an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + --( pxQueue->uxMessagesWaiting ); + + /* If the queue is locked we will not modify the event list. Instead + we update the lock count so the task that unlocks the queue will know + that an ISR has removed data while the queue was locked. */ + if( pxQueue->xRxLock == queueUNLOCKED ) + { + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + *pxTaskWoken = pdTRUE; + } + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + ++( pxQueue->xRxLock ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + taskENTER_CRITICAL(); + uxReturn = pxQueue->uxMessagesWaiting; + taskEXIT_CRITICAL(); + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) +{ +unsigned portBASE_TYPE uxReturn; + + uxReturn = pxQueue->uxMessagesWaiting; + + return uxReturn; +} +/*-----------------------------------------------------------*/ + +void vQueueDelete( xQueueHandle pxQueue ) +{ + traceQUEUE_DELETE( pxQueue ); + vQueueUnregisterQueue( pxQueue ); + vPortFree( pxQueue->pcHead ); + vPortFree( pxQueue ); +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) +{ + if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder ); + pxQueue->pxMutexHolder = NULL; + } + } + #endif + } + else if( xPosition == queueSEND_TO_BACK ) + { + memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); + pxQueue->pcWriteTo += pxQueue->uxItemSize; + if( pxQueue->pcWriteTo >= pxQueue->pcTail ) + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + } + else + { + memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize ); + pxQueue->pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->pcReadFrom < pxQueue->pcHead ) + { + pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize ); + } + } + + ++( pxQueue->uxMessagesWaiting ); +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) +{ + if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX ) + { + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( xQueueHandle pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + /* See if data was added to the queue while it was locked. */ + while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + + --( pxQueue->xTxLock ); + } + else + { + break; + } + } + + pxQueue->xTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED ) + { + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + + --( pxQueue->xRxLock ); + } + else + { + break; + } + } + + pxQueue->xRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + taskENTER_CRITICAL(); + xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) +{ +signed portBASE_TYPE xReturn; + + xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) +{ +signed portBASE_TYPE xReturn; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portNOP(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) +{ +signed portBASE_TYPE xReturn; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( portTickType ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portNOP(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + + + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) +{ + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( !xCoRoutinePreviouslyWoken ) + { + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + } + } + } + + return xCoRoutinePreviouslyWoken; +} +#endif +/*-----------------------------------------------------------*/ + +#if configUSE_CO_ROUTINES == 1 +signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken ) +{ +signed portBASE_TYPE xReturn; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->pcReadFrom >= pxQueue->pcTail ) + { + pxQueue->pcReadFrom = pxQueue->pcHead; + } + --( pxQueue->uxMessagesWaiting ); + memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( !( *pxCoRoutineWoken ) ) + { + if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + } + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; +} +#endif +/*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + + void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName ) + { + unsigned portBASE_TYPE ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + break; + } + } + } + +#endif + /*-----------------------------------------------------------*/ + +#if configQUEUE_REGISTRY_SIZE > 0 + + static void vQueueUnregisterQueue( xQueueHandle xQueue ) + { + unsigned portBASE_TYPE ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + break; + } + } + } + +#endif + Index: /webserver/example/EnergyMeters/Source/tasks.c =================================================================== --- /webserver/example/EnergyMeters/Source/tasks.c (revision 21) +++ /webserver/example/EnergyMeters/Source/tasks.c (revision 21) @@ -0,0 +1,2227 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#include +#include +#include + +#include "FreeRTOS.h" +#include "task.h" +#include "StackMacros.h" + +/* + * Macro to define the amount of stack available to the idle task. + */ +#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE + +/* + * Task control block. A task control block (TCB) is allocated to each task, + * and stores the context of the task. + */ +typedef struct tskTaskControlBlock +{ + volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ + xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ + xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ + unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ + portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ + signed portCHAR pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ + + #if ( portSTACK_GROWTH > 0 ) + portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ + #endif + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + unsigned portBASE_TYPE uxCriticalNesting; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ + #endif + + #if ( configUSE_MUTEXES == 1 ) + unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + pdTASK_HOOK_CODE pxTaskTag; + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + unsigned portLONG ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ + #endif + +} tskTCB; + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + +/*lint -e956 */ + +tskTCB * volatile pxCurrentTCB = NULL; + +/* Lists for ready and blocked tasks. --------------------*/ + +static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ +static xList xDelayedTaskList1; /*< Delayed tasks. */ +static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ +static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */ +static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ +static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */ + +#if ( INCLUDE_vTaskDelete == 1 ) + + static volatile xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ + static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0; + +#endif + +#if ( INCLUDE_vTaskSuspend == 1 ) + + static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ + +#endif + +/* File private variables. --------------------------------*/ +static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0; +volatile portTickType xTickCount = ( portTickType ) 0; /* no longer volatile for electricity meter app */ +static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY; +static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; +static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; +static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; +static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0; +static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; +static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; +static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0; + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + static portCHAR pcStatsString[ 50 ]; + static unsigned portLONG ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ + static void prvGenerateRunTimeStatsForTasksInList( const signed portCHAR *pcWriteBuffer, xList *pxList, unsigned portLONG ulTotalRunTime ); + +#endif + +/* Debugging and trace facilities private variables and macros. ------------*/ + +/* + * The value used to fill the stack of a task when the task is created. This + * is used purely for checking the high water mark for tasks. + */ +#define tskSTACK_FILL_BYTE ( 0xa5 ) + +/* + * Macros used by vListTask to indicate which state a task is in. + */ +#define tskBLOCKED_CHAR ( ( signed portCHAR ) 'B' ) +#define tskREADY_CHAR ( ( signed portCHAR ) 'R' ) +#define tskDELETED_CHAR ( ( signed portCHAR ) 'D' ) +#define tskSUSPENDED_CHAR ( ( signed portCHAR ) 'S' ) + +/* + * Macros and private variables used by the trace facility. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned portLONG ) ( sizeof( unsigned portLONG ) + sizeof( unsigned portLONG ) ) ) + static volatile signed portCHAR * volatile pcTraceBuffer; + static signed portCHAR *pcTraceBufferStart; + static signed portCHAR *pcTraceBufferEnd; + static signed portBASE_TYPE xTracing = pdFALSE; + static unsigned portBASE_TYPE uxPreviousTask = 255; + static portCHAR pcStatusString[ 50 ]; + +#endif + +/*-----------------------------------------------------------*/ + +/* + * Macro that writes a trace of scheduler activity to a buffer. This trace + * shows which task is running when and is very useful as a debugging tool. + * As this macro is called each context switch it is a good idea to undefine + * it if not using the facility. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + #define vWriteTraceToBuffer() \ + { \ + if( xTracing ) \ + { \ + if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ + { \ + if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ + { \ + uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ + *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \ + pcTraceBuffer += sizeof( unsigned portLONG ); \ + *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \ + pcTraceBuffer += sizeof( unsigned portLONG ); \ + } \ + else \ + { \ + xTracing = pdFALSE; \ + } \ + } \ + } \ + } + +#else + + #define vWriteTraceToBuffer() + +#endif +/*-----------------------------------------------------------*/ + +/* + * Place the task represented by pxTCB into the appropriate ready queue for + * the task. It is inserted at the end of the list. One quirk of this is + * that if the task being inserted is at the same priority as the currently + * executing task, then it will only be rescheduled after the currently + * executing task has been rescheduled. + */ +#define prvAddTaskToReadyQueue( pxTCB ) \ +{ \ + if( pxTCB->uxPriority > uxTopReadyPriority ) \ + { \ + uxTopReadyPriority = pxTCB->uxPriority; \ + } \ + vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \ +} +/*-----------------------------------------------------------*/ + +/* + * Macro that looks at the list of tasks that are currently delayed to see if + * any require waking. + * + * Tasks are stored in the queue in the order of their wake time - meaning + * once one tasks has been found whose timer has not expired we need not look + * any further down the list. + */ +#define prvCheckDelayedTasks() \ +{ \ +register tskTCB *pxTCB; \ + \ + while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ + { \ + if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ + { \ + break; \ + } \ + vListRemove( &( pxTCB->xGenericListItem ) ); \ + /* Is the task waiting on an event also? */ \ + if( pxTCB->xEventListItem.pvContainer ) \ + { \ + vListRemove( &( pxTCB->xEventListItem ) ); \ + } \ + prvAddTaskToReadyQueue( pxTCB ); \ + } \ +} +/*-----------------------------------------------------------*/ + +/* + * Several functions take an xTaskHandle parameter that can optionally be NULL, + * where NULL is used to indicate that the handle of the currently executing + * task should be used in place of the parameter. This macro simply checks to + * see if the parameter is NULL and returns a pointer to the appropriate TCB. + */ +#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle ) + + +/* File private functions. --------------------------------*/ + +/* + * Utility to ready a TCB for a given task. Mainly just copies the parameters + * into the TCB structure. + */ +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority ); + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first task. + */ +static void prvInitialiseTaskLists( void ); + +/* + * The idle task, which as all tasks is implemented as a never ending loop. + * The idle task is automatically created and added to the ready lists upon + * creation of the first user task. + * + * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); + +/* + * Utility to free all memory allocated by the scheduler to hold a TCB, + * including the stack pointed to by the TCB. + * + * This does not free memory allocated by the task itself (i.e. memory + * allocated by calls to pvPortMalloc from within the tasks application code). + */ +#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) + + static void prvDeleteTCB( tskTCB *pxTCB ); + +#endif + +/* + * Used only by the idle task. This checks to see if anything has been placed + * in the list of tasks waiting to be deleted. If so the task is cleaned up + * and its TCB deleted. + */ +static void prvCheckTasksWaitingTermination( void ); + +/* + * Allocates memory from the heap for a TCB and associated stack. Checks the + * allocation was successful. + */ +static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth ); + +/* + * Called from vTaskList. vListTasks details all the tasks currently under + * control of the scheduler. The tasks may be in one of a number of lists. + * prvListTaskWithinSingleList accepts a list and details the tasks from + * within just that list. + * + * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM + * NORMAL APPLICATION CODE. + */ +#if ( configUSE_TRACE_FACILITY == 1 ) + + static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus ); + +#endif + +/* + * When a task is created, the stack of the task is filled with a known value. + * This function determines the 'high water mark' of the task stack by + * determining how much of the stack remains at the original preset value. + */ +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte ); + +#endif + + +/*lint +e956 */ + + + +/*----------------------------------------------------------- + * TASK CREATION API documented in task.h + *----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask ) +{ +signed portBASE_TYPE xReturn; +tskTCB * pxNewTCB; + + /* Allocate the memory required by the TCB and stack for the new task. + checking that the allocation was successful. */ + pxNewTCB = prvAllocateTCBAndStack( usStackDepth ); + + if( pxNewTCB != NULL ) + { + portSTACK_TYPE *pxTopOfStack; + + /* Setup the newly allocated TCB with the initial state of the task. */ + prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority ); + + /* Calculate the top of stack address. This depends on whether the + stack grows from high memory to low (as per the 80x86) or visa versa. + portSTACK_GROWTH is used to make the result positive or negative as + required by the port. */ + #if portSTACK_GROWTH < 0 + { + pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ) - ( ( usStackDepth - 1 ) % portBYTE_ALIGNMENT ); + } + #else + { + pxTopOfStack = pxNewTCB->pxStack; + + /* If we want to use stack checking on architectures that use + a positive stack growth direction then we also need to store the + other extreme of the stack space. */ + pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); + } + #endif + + /* Initialize the TCB stack to look as if the task was already running, + but had been interrupted by the scheduler. The return address is set + to the start of the task function. Once the stack has been initialised + the top of stack variable is updated. */ + pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pvTaskCode, pvParameters ); + + /* We are going to manipulate the task queues to add this task to a + ready list, so must make sure no interrupts occur. */ + portENTER_CRITICAL(); + { + uxCurrentNumberOfTasks++; + if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) + { + /* As this is the first task it must also be the current task. */ + pxCurrentTCB = pxNewTCB; + + /* This is the first task to be created so do the preliminary + initialisation required. We will not recover if this call + fails, but we will report the failure. */ + prvInitialiseTaskLists(); + } + else + { + /* If the scheduler is not already running, make this task the + current task if it is the highest priority task to be created + so far. */ + if( xSchedulerRunning == pdFALSE ) + { + if( pxCurrentTCB->uxPriority <= uxPriority ) + { + pxCurrentTCB = pxNewTCB; + } + } + } + + /* Remember the top priority to make context switching faster. Use + the priority in pxNewTCB as this has been capped to a valid value. */ + if( pxNewTCB->uxPriority > uxTopUsedPriority ) + { + uxTopUsedPriority = pxNewTCB->uxPriority; + } + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + /* Add a counter into the TCB for tracing only. */ + pxNewTCB->uxTCBNumber = uxTaskNumber; + } + #endif + uxTaskNumber++; + + prvAddTaskToReadyQueue( pxNewTCB ); + + xReturn = pdPASS; + traceTASK_CREATE( pxNewTCB ); + } + portEXIT_CRITICAL(); + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + traceTASK_CREATE_FAILED( pxNewTCB ); + } + + if( xReturn == pdPASS ) + { + if( ( void * ) pxCreatedTask != NULL ) + { + /* Pass the TCB out - in an anonymous way. The calling function/ + task can use this as a handle to delete the task later if + required.*/ + *pxCreatedTask = ( xTaskHandle ) pxNewTCB; + } + + if( xSchedulerRunning != pdFALSE ) + { + /* If the created task is of a higher priority than the current task + then it should run now. */ + if( pxCurrentTCB->uxPriority < uxPriority ) + { + taskYIELD(); + } + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelete == 1 ) + + void vTaskDelete( xTaskHandle pxTaskToDelete ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* Ensure a yield is performed if the current task is being + deleted. */ + if( pxTaskToDelete == pxCurrentTCB ) + { + pxTaskToDelete = NULL; + } + + /* If null is passed in here then we are deleting ourselves. */ + pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); + + /* Remove task from the ready list and place in the termination list. + This will stop the task from be scheduled. The idle task will check + the termination list and free up any memory allocated by the + scheduler for the TCB and stack. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? */ + if( pxTCB->xEventListItem.pvContainer ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); + + /* Increment the ucTasksDeleted variable so the idle task knows + there is a task that has been deleted and that it should therefore + check the xTasksWaitingTermination list. */ + ++uxTasksDeleted; + + /* Increment the uxTaskNumberVariable also so kernel aware debuggers + can detect that the task lists need re-generating. */ + uxTaskNumber++; + + traceTASK_DELETE( pxTCB ); + } + taskEXIT_CRITICAL(); + + /* Force a reschedule if we have just deleted the current task. */ + if( xSchedulerRunning != pdFALSE ) + { + if( ( void * ) pxTaskToDelete == NULL ) + { + taskYIELD(); + } + } + } + +#endif + + + + + + +/*----------------------------------------------------------- + * TASK CONTROL API documented in task.h + *----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelayUntil == 1 ) + + void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) + { + portTickType xTimeToWake; + portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; + + vTaskSuspendAll(); + { + /* Generate the tick time at which the task wants to wake. */ + xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; + + if( xTickCount < *pxPreviousWakeTime ) + { + /* The tick count has overflowed since this function was + lasted called. In this case the only time we should ever + actually delay is if the wake time has also overflowed, + and the wake time is greater than the tick time. When this + is the case it is as if neither time had overflowed. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + else + { + /* The tick time has not overflowed. In this case we will + delay if either the wake time has overflowed, and/or the + tick time is less than the wake time. */ + if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) + { + xShouldDelay = pdTRUE; + } + } + + /* Update the wake time ready for the next call. */ + *pxPreviousWakeTime = xTimeToWake; + + if( xShouldDelay ) + { + traceTASK_DELAY_UNTIL(); + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + } + } + xAlreadyYielded = xTaskResumeAll(); + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( !xAlreadyYielded ) + { + taskYIELD(); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskDelay == 1 ) + + void vTaskDelay( portTickType xTicksToDelay ) + { + portTickType xTimeToWake; + signed portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* A delay time of zero just forces a reschedule. */ + if( xTicksToDelay > ( portTickType ) 0 ) + { + vTaskSuspendAll(); + { + traceTASK_DELAY(); + + /* A task that is removed from the event list while the + scheduler is suspended will not get placed in the ready + list or removed from the blocked list until the scheduler + is resumed. + + This task cannot be in an event list as it is the currently + executing task. */ + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + } + xAlreadyYielded = xTaskResumeAll(); + } + + /* Force a reschedule if xTaskResumeAll has not already done so, we may + have put ourselves to sleep. */ + if( !xAlreadyYielded ) + { + taskYIELD(); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskPriorityGet == 1 ) + + unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxReturn; + + taskENTER_CRITICAL(); + { + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( pxTask ); + uxReturn = pxTCB->uxPriority; + } + taskEXIT_CRITICAL(); + + return uxReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskPrioritySet == 1 ) + + void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) + { + tskTCB *pxTCB; + unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE; + + /* Ensure the new priority is valid. */ + if( uxNewPriority >= configMAX_PRIORITIES ) + { + uxNewPriority = configMAX_PRIORITIES - 1; + } + + taskENTER_CRITICAL(); + { + if( pxTask == pxCurrentTCB ) + { + pxTask = NULL; + } + + /* If null is passed in here then we are changing the + priority of the calling function. */ + pxTCB = prvGetTCBFromHandle( pxTask ); + + traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); + + #if ( configUSE_MUTEXES == 1 ) + { + uxCurrentPriority = pxTCB->uxBasePriority; + } + #else + { + uxCurrentPriority = pxTCB->uxPriority; + } + #endif + + if( uxCurrentPriority != uxNewPriority ) + { + /* The priority change may have readied a task of higher + priority than the calling task. */ + if( uxNewPriority > uxCurrentPriority ) + { + if( pxTask != NULL ) + { + /* The priority of another task is being raised. If we + were raising the priority of the currently running task + there would be no need to switch as it must have already + been the highest priority task. */ + xYieldRequired = pdTRUE; + } + } + else if( pxTask == NULL ) + { + /* Setting our own priority down means there may now be another + task of higher priority that is ready to execute. */ + xYieldRequired = pdTRUE; + } + + + + #if ( configUSE_MUTEXES == 1 ) + { + /* Only change the priority being used if the task is not + currently using an inherited priority. */ + if( pxTCB->uxBasePriority == pxTCB->uxPriority ) + { + pxTCB->uxPriority = uxNewPriority; + } + + /* The base priority gets set whatever. */ + pxTCB->uxBasePriority = uxNewPriority; + } + #else + { + pxTCB->uxPriority = uxNewPriority; + } + #endif + + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); + + /* If the task is in the blocked or suspended list we need do + nothing more than change it's priority variable. However, if + the task is in a ready list it needs to be removed and placed + in the queue appropriate to its new priority. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) + { + /* The task is currently in its ready list - remove before adding + it to it's new ready list. As we are in a critical section we + can do this even if the scheduler is suspended. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + } + + if( xYieldRequired == pdTRUE ) + { + taskYIELD(); + } + } + } + taskEXIT_CRITICAL(); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskSuspend( xTaskHandle pxTaskToSuspend ) + { + tskTCB *pxTCB; + + taskENTER_CRITICAL(); + { + /* Ensure a yield is performed if the current task is being + suspended. */ + if( pxTaskToSuspend == pxCurrentTCB ) + { + pxTaskToSuspend = NULL; + } + + /* If null is passed in here then we are suspending ourselves. */ + pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); + + traceTASK_SUSPEND( pxTCB ); + + /* Remove task from the ready/delayed list and place in the suspended list. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Is the task waiting on an event also? */ + if( pxTCB->xEventListItem.pvContainer ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + } + + vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); + } + taskEXIT_CRITICAL(); + + /* We may have just suspended the current task. */ + if( ( void * ) pxTaskToSuspend == NULL ) + { + taskYIELD(); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) + { + portBASE_TYPE xReturn = pdFALSE; + const tskTCB * const pxTCB = ( tskTCB * ) xTask; + + /* Is the task we are attempting to resume actually in the + suspended list? */ + if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) + { + /* Has the task already been resumed from within an ISR? */ + if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE ) + { + /* Is it in the suspended list because it is in the + Suspended state? It is possible to be in the suspended + list because it is blocked on a task with no timeout + specified. */ + if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE ) + { + xReturn = pdTRUE; + } + } + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_vTaskSuspend == 1 ) + + void vTaskResume( xTaskHandle pxTaskToResume ) + { + tskTCB *pxTCB; + + /* Remove the task from whichever list it is currently in, and place + it in the ready list. */ + pxTCB = ( tskTCB * ) pxTaskToResume; + + /* The parameter cannot be NULL as it is impossible to resume the + currently executing task. */ + if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) + { + taskENTER_CRITICAL(); + { + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME( pxTCB ); + + /* As we are in a critical section we can access the ready + lists even if the scheduler is suspended. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* This yield may not cause the task just resumed to run, but + will leave the lists in the correct state for the next yield. */ + taskYIELD(); + } + } + } + taskEXIT_CRITICAL(); + } + } + +#endif + +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) + { + portBASE_TYPE xYieldRequired = pdFALSE; + tskTCB *pxTCB; + + pxTCB = ( tskTCB * ) pxTaskToResume; + + if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) + { + traceTASK_RESUME_FROM_ISR( pxTCB ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed, at which point a + yield will be performed if necessary. */ + vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); + } + } + + return xYieldRequired; + } + +#endif + + + + +/*----------------------------------------------------------- + * PUBLIC SCHEDULER CONTROL documented in task.h + *----------------------------------------------------------*/ + + +void vTaskStartScheduler( void ) +{ +portBASE_TYPE xReturn; + + /* Add the idle task at the lowest priority. */ + xReturn = xTaskCreate( prvIdleTask, ( signed portCHAR * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL ); + + if( xReturn == pdPASS ) + { + /* Interrupts are turned off here, to ensure a tick does not occur + before or during the call to xPortStartScheduler(). The stacks of + the created tasks contain a status word with interrupts switched on + so interrupts will automatically get re-enabled when the first task + starts to run. + + STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE + DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ + portDISABLE_INTERRUPTS(); + + xSchedulerRunning = pdTRUE; + xTickCount = ( portTickType ) 0; + + /* If configGENERATE_RUN_TIME_STATS is defined then the following + macro must be defined to configure the timer/counter used to generate + the run time counter time base. */ + portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + + /* Setting up the timer tick is hardware specific and thus in the + portable interface. */ + if( xPortStartScheduler() ) + { + /* Should not reach here as if the scheduler is running the + function will not return. */ + } + else + { + /* Should only reach here if a task calls xTaskEndScheduler(). */ + } + } +} +/*-----------------------------------------------------------*/ + +void vTaskEndScheduler( void ) +{ + /* Stop the scheduler interrupts and call the portable scheduler end + routine so the original ISRs can be restored if necessary. The port + layer must ensure interrupts enable bit is left in the correct state. */ + portDISABLE_INTERRUPTS(); + xSchedulerRunning = pdFALSE; + vPortEndScheduler(); +} +/*----------------------------------------------------------*/ + +void vTaskSuspendAll( void ) +{ + /* A critical section is not required as the variable is of type + portBASE_TYPE. */ + ++uxSchedulerSuspended; +} +/*----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskResumeAll( void ) +{ +register tskTCB *pxTCB; +signed portBASE_TYPE xAlreadyYielded = pdFALSE; + + /* It is possible that an ISR caused a task to be removed from an event + list while the scheduler was suspended. If this was the case then the + removed task will have been added to the xPendingReadyList. Once the + scheduler has been resumed it is safe to move all the pending ready + tasks from this list into their appropriate ready list. */ + portENTER_CRITICAL(); + { + --uxSchedulerSuspended; + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 ) + { + portBASE_TYPE xYieldRequired = pdFALSE; + + /* Move any readied tasks from the pending list into the + appropriate ready list. */ + while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL ) + { + vListRemove( &( pxTCB->xEventListItem ) ); + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); + + /* If we have moved a task that has a priority higher than + the current task then we should yield. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + xYieldRequired = pdTRUE; + } + } + + /* If any ticks occurred while the scheduler was suspended then + they should be processed now. This ensures the tick count does not + slip, and that any delayed tasks are resumed at the correct time. */ + if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) + { + while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) + { + vTaskIncrementTick(); + --uxMissedTicks; + } + + /* As we have processed some ticks it is appropriate to yield + to ensure the highest priority task that is ready to run is + the task actually running. */ + #if configUSE_PREEMPTION == 1 + { + xYieldRequired = pdTRUE; + } + #endif + } + + if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) ) + { + xAlreadyYielded = pdTRUE; + xMissedYield = pdFALSE; + taskYIELD(); + } + } + } + } + portEXIT_CRITICAL(); + + return xAlreadyYielded; +} + + + + + + +/*----------------------------------------------------------- + * PUBLIC TASK UTILITIES documented in task.h + *----------------------------------------------------------*/ + + + +portTickType xTaskGetTickCount( void ) +{ +portTickType xTicks; + + /* Critical section required if running on a 16 bit processor. */ + taskENTER_CRITICAL(); + { + xTicks = xTickCount; + } + taskEXIT_CRITICAL(); + + return xTicks; +} +/*-----------------------------------------------------------*/ + +unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) +{ + /* A critical section is not required because the variables are of type + portBASE_TYPE. */ + return uxCurrentNumberOfTasks; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskList( signed portCHAR *pcWriteBuffer ) + { + unsigned portBASE_TYPE uxQueue; + + /* This is a VERY costly function that should be used for debug only. + It leaves interrupts disabled for a LONG time. */ + + vTaskSuspendAll(); + { + /* Run through all the lists that could potentially contain a TCB and + report the task name, state and stack high water mark. */ + + pcWriteBuffer[ 0 ] = ( signed portCHAR ) 0x00; + strcat( ( portCHAR * ) pcWriteBuffer, ( const portCHAR * ) "\r\n" ); + + uxQueue = uxTopUsedPriority + 1; + + do + { + uxQueue--; + + if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); + } + }while( uxQueue > ( unsigned portSHORT ) tskIDLE_PRIORITY ); + + if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); + } + + if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); + } + + #if( INCLUDE_vTaskDelete == 1 ) + { + if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR ); + } + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) + { + prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR ); + } + } + #endif + } + xTaskResumeAll(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + void vTaskGetRunTimeStats( signed portCHAR *pcWriteBuffer ) + { + unsigned portBASE_TYPE uxQueue; + unsigned portLONG ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); + + /* This is a VERY costly function that should be used for debug only. + It leaves interrupts disabled for a LONG time. */ + + vTaskSuspendAll(); + { + /* Run through all the lists that could potentially contain a TCB, + generating a table of run timer percentages in the provided + buffer. */ + + pcWriteBuffer[ 0 ] = ( signed portCHAR ) 0x00; + strcat( ( portCHAR * ) pcWriteBuffer, ( const portCHAR * ) "\r\n" ); + + uxQueue = uxTopUsedPriority + 1; + + do + { + uxQueue--; + + if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime ); + } + }while( uxQueue > ( unsigned portSHORT ) tskIDLE_PRIORITY ); + + if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime ); + } + + if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime ); + } + + #if ( INCLUDE_vTaskDelete == 1 ) + { + if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime ); + } + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) + { + prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime ); + } + } + #endif + } + xTaskResumeAll(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vTaskStartTrace( signed portCHAR * pcBuffer, unsigned portLONG ulBufferSize ) + { + portENTER_CRITICAL(); + { + pcTraceBuffer = ( signed portCHAR * )pcBuffer; + pcTraceBufferStart = pcBuffer; + pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); + xTracing = pdTRUE; + } + portEXIT_CRITICAL(); + } + +#endif +/*----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + unsigned portLONG ulTaskEndTrace( void ) + { + unsigned portLONG ulBufferLength; + + portENTER_CRITICAL(); + xTracing = pdFALSE; + portEXIT_CRITICAL(); + + ulBufferLength = ( unsigned portLONG ) ( pcTraceBuffer - pcTraceBufferStart ); + + return ulBufferLength; + } + +#endif + + + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + * documented in task.h + *----------------------------------------------------------*/ + + +void vTaskIncrementTick( void ) +{ + /* Called by the portable layer each time a tick interrupt occurs. + Increments the tick then checks to see if the new tick value will cause any + tasks to be unblocked. */ + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + ++xTickCount; + if( xTickCount == ( portTickType ) 0 ) + { + xList *pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. + If there are any items in pxDelayedTaskList here then there is + an error! */ + pxTemp = pxDelayedTaskList; + pxDelayedTaskList = pxOverflowDelayedTaskList; + pxOverflowDelayedTaskList = pxTemp; + xNumOfOverflows++; + } + + /* See if this tick has made a timeout expire. */ + prvCheckDelayedTasks(); + } + else + { + ++uxMissedTicks; + + /* The tick hook gets called at regular intervals, even if the + scheduler is locked. */ + #if ( configUSE_TICK_HOOK == 1 ) + { + extern void vApplicationTickHook( void ); + + vApplicationTickHook(); + } + #endif + } + + #if ( configUSE_TICK_HOOK == 1 ) + { + extern void vApplicationTickHook( void ); + + /* Guard against the tick hook being called when the missed tick + count is being unwound (when the scheduler is being unlocked. */ + if( uxMissedTicks == 0 ) + { + vApplicationTickHook(); + } + } + #endif + + traceTASK_INCREMENT_TICK( xTickCount ); +} +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) + + void vTaskCleanUpResources( void ) + { + unsigned portSHORT usQueue; + volatile tskTCB *pxTCB; + + usQueue = ( unsigned portSHORT ) uxTopUsedPriority + ( unsigned portSHORT ) 1; + + /* Remove any TCB's from the ready queues. */ + do + { + usQueue--; + + while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) ); + vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); + + prvDeleteTCB( ( tskTCB * ) pxTCB ); + } + }while( usQueue > ( unsigned portSHORT ) tskIDLE_PRIORITY ); + + /* Remove any TCB's from the delayed queue. */ + while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 ); + vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); + + prvDeleteTCB( ( tskTCB * ) pxTCB ); + } + + /* Remove any TCB's from the overflow delayed queue. */ + while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 ); + vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); + + prvDeleteTCB( ( tskTCB * ) pxTCB ); + } + + while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) + { + listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList ); + vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); + + prvDeleteTCB( ( tskTCB * ) pxTCB ); + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue ) + { + tskTCB *xTCB; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + portENTER_CRITICAL(); + xTCB->pxTaskTag = pxTagValue; + portEXIT_CRITICAL(); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) + { + tskTCB *xTCB; + pdTASK_HOOK_CODE xReturn; + + /* If xTask is NULL then we are setting our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + /* Save the hook function in the TCB. A critical section is required as + the value can be accessed from an interrupt. */ + portENTER_CRITICAL(); + xReturn = xTCB->pxTaskTag; + portEXIT_CRITICAL(); + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + + portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) + { + tskTCB *xTCB; + portBASE_TYPE xReturn; + + /* If xTask is NULL then we are calling our own task hook. */ + if( xTask == NULL ) + { + xTCB = ( tskTCB * ) pxCurrentTCB; + } + else + { + xTCB = ( tskTCB * ) xTask; + } + + if( xTCB->pxTaskTag != NULL ) + { + xReturn = xTCB->pxTaskTag( pvParameter ); + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +void vTaskSwitchContext( void ) +{ + if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) + { + /* The scheduler is currently suspended - do not allow a context + switch. */ + xMissedYield = pdTRUE; + return; + } + + traceTASK_SWITCHED_OUT(); + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + unsigned portLONG ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); + + /* Add the amount of time the task has been running to the accumulated + time so far. The time the task started running was stored in + ulTaskSwitchedInTime. Note that there is no overflow protection here + so count values are only valid until the timer overflows. Generally + this will be about 1 hour assuming a 1uS timer increment. */ + pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); + ulTaskSwitchedInTime = ulTempCounter; + } + #endif + + taskFIRST_CHECK_FOR_STACK_OVERFLOW(); + taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + + /* Find the highest priority queue that contains ready tasks. */ + while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) + { + --uxTopReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the + same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); + + traceTASK_SWITCHED_IN(); + vWriteTraceToBuffer(); +} +/*-----------------------------------------------------------*/ + +void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) +{ +portTickType xTimeToWake; + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. */ + + /* Place the event list item of the TCB in the appropriate event list. + This is placed in the list in priority order so the highest priority task + is the first to be woken by the event. */ + vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); + + /* We must remove ourselves from the ready list before adding ourselves + to the blocked list as the same list item is used for both lists. We have + exclusive access to the ready lists as the scheduler is locked. */ + vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + if( xTicksToWait == portMAX_DELAY ) + { + /* Add ourselves to the suspended task list instead of a delayed task + list to ensure we are not woken by a timing event. We will block + indefinitely. */ + vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the current block list. */ + vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + } + } + #else + { + /* Calculate the time at which the task should be woken if the event does + not occur. This may overflow but this doesn't matter. */ + xTimeToWake = xTickCount + xTicksToWait; + + listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xTickCount ) + { + /* Wake time has overflowed. Place this item in the overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the current block list. */ + vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); + } + } + #endif +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) +{ +tskTCB *pxUnblockedTCB; +portBASE_TYPE xReturn; + + /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE + SCHEDULER SUSPENDED. It can also be called from within an ISR. */ + + /* The event list is sorted in priority order, so we can remove the + first in the list, remove the TCB from the delayed list, and add + it to the ready list. + + If an event is for a queue that is locked then this function will never + get called - the lock count on the queue will get modified instead. This + means we can always expect exclusive access to the event list here. */ + pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + vListRemove( &( pxUnblockedTCB->xEventListItem ) ); + + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + vListRemove( &( pxUnblockedTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxUnblockedTCB ); + } + else + { + /* We cannot access the delayed or ready lists, so will hold this + task pending until the scheduler is resumed. */ + vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); + } + + if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* Return true if the task removed from the event list has + a higher priority than the calling task. This allows + the calling task to know if it should force a context + switch now. */ + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) +{ + pxTimeOut->xOverflowCount = xNumOfOverflows; + pxTimeOut->xTimeOnEntering = xTickCount; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) +{ +portBASE_TYPE xReturn; + + portENTER_CRITICAL(); + { + #if ( INCLUDE_vTaskSuspend == 1 ) + /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is + the maximum block time then the task should block indefinitely, and + therefore never time out. */ + if( *pxTicksToWait == portMAX_DELAY ) + { + xReturn = pdFALSE; + } + else /* We are not blocking indefinitely, perform the checks below. */ + #endif + + if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) + { + /* The tick count is greater than the time at which vTaskSetTimeout() + was called, but has also overflowed since vTaskSetTimeOut() was called. + It must have wrapped all the way around and gone past us again. This + passed since vTaskSetTimeout() was called. */ + xReturn = pdTRUE; + } + else if( ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) < ( portTickType ) *pxTicksToWait ) + { + /* Not a genuine timeout. Adjust parameters for time remaining. */ + *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); + vTaskSetTimeOutState( pxTimeOut ); + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + } + portEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vTaskMissedYield( void ) +{ + xMissedYield = pdTRUE; +} + +/* + * ----------------------------------------------------------- + * The Idle task. + * ---------------------------------------------------------- + * + * The portTASK_FUNCTION() macro is used to allow port/compiler specific + * language extensions. The equivalent prototype for this function is: + * + * void prvIdleTask( void *pvParameters ); + * + */ +static portTASK_FUNCTION( prvIdleTask, pvParameters ) +{ + /* Stop warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* See if any tasks have been deleted. */ + prvCheckTasksWaitingTermination(); + + #if ( configUSE_PREEMPTION == 0 ) + { + /* If we are not using preemption we keep forcing a task switch to + see if any other task has become available. If we are using + preemption we don't need to do this as any task becoming available + will automatically get the processor anyway. */ + taskYIELD(); + } + #endif + + #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) + { + /* When using preemption tasks of equal priority will be + timesliced. If a task that is sharing the idle priority is ready + to run then the idle task should yield before the end of the + timeslice. + + A critical region is not required here as we are just reading from + the list, and an occasional incorrect value will not matter. If + the ready list at the idle priority contains more than one task + then a task other than the idle task is ready to execute. */ + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) + { + taskYIELD(); + } + } + #endif + + #if ( configUSE_IDLE_HOOK == 1 ) + { + extern void vApplicationIdleHook( void ); + + /* Call the user defined function from within the idle task. This + allows the application designer to add background functionality + without the overhead of a separate task. + NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, + CALL A FUNCTION THAT MIGHT BLOCK. */ + vApplicationIdleHook(); + } + #endif + } +} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ + + + + + + + +/*----------------------------------------------------------- + * File private functions documented at the top of the file. + *----------------------------------------------------------*/ + + + +static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * const pcName, unsigned portBASE_TYPE uxPriority ) +{ + /* Store the function name in the TCB. */ + #if configMAX_TASK_NAME_LEN > 1 + { + /* Don't bring strncpy into the build unnecessarily. */ + strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned portSHORT ) configMAX_TASK_NAME_LEN ); + } + #endif + pxTCB->pcTaskName[ ( unsigned portSHORT ) configMAX_TASK_NAME_LEN - ( unsigned portSHORT ) 1 ] = '\0'; + + /* This is used as an array index so must ensure it's not too large. */ + if( uxPriority >= configMAX_PRIORITIES ) + { + uxPriority = configMAX_PRIORITIES - 1; + } + + pxTCB->uxPriority = uxPriority; + #if ( configUSE_MUTEXES == 1 ) + { + pxTCB->uxBasePriority = uxPriority; + } + #endif + + vListInitialiseItem( &( pxTCB->xGenericListItem ) ); + vListInitialiseItem( &( pxTCB->xEventListItem ) ); + + /* Set the pxTCB as a link back from the xListItem. This is so we can get + back to the containing TCB from a generic item in a list. */ + listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); + listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); + + #if ( portCRITICAL_NESTING_IN_TCB == 1 ) + { + pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0; + } + #endif + + #if ( configUSE_APPLICATION_TASK_TAG == 1 ) + { + pxTCB->pxTaskTag = NULL; + } + #endif + + #if ( configGENERATE_RUN_TIME_STATS == 1 ) + { + pxTCB->ulRunTimeCounter = 0UL; + } + #endif +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseTaskLists( void ) +{ +unsigned portBASE_TYPE uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) ); + } + + vListInitialise( ( xList * ) &xDelayedTaskList1 ); + vListInitialise( ( xList * ) &xDelayedTaskList2 ); + vListInitialise( ( xList * ) &xPendingReadyList ); + + #if ( INCLUDE_vTaskDelete == 1 ) + { + vListInitialise( ( xList * ) &xTasksWaitingTermination ); + } + #endif + + #if ( INCLUDE_vTaskSuspend == 1 ) + { + vListInitialise( ( xList * ) &xSuspendedTaskList ); + } + #endif + + /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList + using list2. */ + pxDelayedTaskList = &xDelayedTaskList1; + pxOverflowDelayedTaskList = &xDelayedTaskList2; +} +/*-----------------------------------------------------------*/ + +static void prvCheckTasksWaitingTermination( void ) +{ + #if ( INCLUDE_vTaskDelete == 1 ) + { + portBASE_TYPE xListIsEmpty; + + /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called + too often in the idle task. */ + if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 ) + { + vTaskSuspendAll(); + xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); + xTaskResumeAll(); + + if( !xListIsEmpty ) + { + tskTCB *pxTCB; + + portENTER_CRITICAL(); + { + pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) ); + vListRemove( &( pxTCB->xGenericListItem ) ); + --uxCurrentNumberOfTasks; + --uxTasksDeleted; + } + portEXIT_CRITICAL(); + + prvDeleteTCB( pxTCB ); + } + } + } + #endif +} +/*-----------------------------------------------------------*/ + +static tskTCB *prvAllocateTCBAndStack( unsigned portSHORT usStackDepth ) +{ +tskTCB *pxNewTCB; + + /* Allocate space for the TCB. Where the memory comes from depends on + the implementation of the port malloc function. */ + pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); + + if( pxNewTCB != NULL ) + { + /* Allocate space for the stack used by the task being created. + The base of the stack memory stored in the TCB so the task can + be deleted later if required. */ + pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMalloc( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ); + + if( pxNewTCB->pxStack == NULL ) + { + /* Could not allocate the stack. Delete the allocated TCB. */ + vPortFree( pxNewTCB ); + pxNewTCB = NULL; + } + else + { + /* Just to help debugging. */ + memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) ); + } + } + + return pxNewTCB; +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + static void prvListTaskWithinSingleList( const signed portCHAR *pcWriteBuffer, xList *pxList, signed portCHAR cStatus ) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + unsigned portSHORT usStackRemaining; + + /* Write the details of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned portCHAR * ) pxNextTCB->pxStack ); + sprintf( pcStatusString, ( portCHAR * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); + strcat( ( portCHAR * ) pcWriteBuffer, ( portCHAR * ) pcStatusString ); + + } while( pxNextTCB != pxFirstTCB ); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + + static void prvGenerateRunTimeStatsForTasksInList( const signed portCHAR *pcWriteBuffer, xList *pxList, unsigned portLONG ulTotalRunTime ) + { + volatile tskTCB *pxNextTCB, *pxFirstTCB; + unsigned portLONG ulStatsAsPercentage; + + /* Write the run time stats of all the TCB's in pxList into the buffer. */ + listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); + do + { + /* Get next TCB in from the list. */ + listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); + + /* Divide by zero check. */ + if( ulTotalRunTime > 0UL ) + { + /* Has the task run at all? */ + if( pxNextTCB->ulRunTimeCounter == 0 ) + { + /* The task has used no CPU time at all. */ + sprintf( pcStatsString, ( portCHAR * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName ); + } + else + { + /* What percentage of the total run time as the task used? + This will always be rounded down to the nearest integer. */ + ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime; + + if( ulStatsAsPercentage > 0UL ) + { + sprintf( pcStatsString, ( portCHAR * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); + } + else + { + /* If the percentage is zero here then the task has + consumed less than 1% of the total run time. */ + sprintf( pcStatsString, ( portCHAR * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter ); + } + } + + strcat( ( portCHAR * ) pcWriteBuffer, ( portCHAR * ) pcStatsString ); + } + + } while( pxNextTCB != pxFirstTCB ); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) + + unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte ) + { + register unsigned portSHORT usCount = 0; + + while( *pucStackByte == tskSTACK_FILL_BYTE ) + { + pucStackByte -= portSTACK_GROWTH; + usCount++; + } + + usCount /= sizeof( portSTACK_TYPE ); + + return usCount; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) + + unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) + { + tskTCB *pxTCB; + unsigned portCHAR *pcEndOfStack; + + pxTCB = prvGetTCBFromHandle( xTask ); + + #if portSTACK_GROWTH < 0 + { + pcEndOfStack = ( unsigned portCHAR * ) pxTCB->pxStack; + } + #else + { + pcEndOfStack = ( unsigned portCHAR * ) pxTCB->pxEndOfStack; + } + #endif + + return usTaskCheckFreeStackSpace( pcEndOfStack ); + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) + + static void prvDeleteTCB( tskTCB *pxTCB ) + { + /* Free up the memory allocated by the scheduler for the task. It is up to + the task to free any memory allocated at the application level. */ + vPortFree( pxTCB->pxStack ); + vPortFree( pxTCB ); + } + +#endif + + +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) + + xTaskHandle xTaskGetCurrentTaskHandle( void ) + { + /* A critical section is not required as this is not called from + an interrupt and the current TCB will always be the same for any + individual execution thread. */ + return pxCurrentTCB; + } + +#endif + +/*-----------------------------------------------------------*/ + +#if ( INCLUDE_xTaskGetSchedulerState == 1 ) + + portBASE_TYPE xTaskGetSchedulerState( void ) + { + portBASE_TYPE xReturn; + + if( xSchedulerRunning == pdFALSE ) + { + xReturn = taskSCHEDULER_NOT_STARTED; + } + else + { + if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) + { + xReturn = taskSCHEDULER_RUNNING; + } + else + { + xReturn = taskSCHEDULER_SUSPENDED; + } + } + + return xReturn; + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) + { + /* Adjust the mutex holder state to account for its new priority. */ + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); + + /* If the task being modified is in the ready state it will need to + be moved in to a new list. */ + if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) + { + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Inherit the priority before being moved into the new list. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + prvAddTaskToReadyQueue( pxTCB ); + } + else + { + /* Just inherit the priority. */ + pxTCB->uxPriority = pxCurrentTCB->uxPriority; + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_MUTEXES == 1 ) + + void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) + { + tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; + + if( pxMutexHolder != NULL ) + { + if( pxTCB->uxPriority != pxTCB->uxBasePriority ) + { + /* We must be the running task to be able to give the mutex back. + Remove ourselves from the ready list we currently appear in. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + + /* Disinherit the priority before adding ourselves into the new + ready list. */ + pxTCB->uxPriority = pxTCB->uxBasePriority; + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); + prvAddTaskToReadyQueue( pxTCB ); + } + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + + void vTaskEnterCritical( void ) + { + portDISABLE_INTERRUPTS(); + + if( xSchedulerRunning != pdFALSE ) + { + pxCurrentTCB->uxCriticalNesting++; + } + } + +#endif +/*-----------------------------------------------------------*/ + +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + +void vTaskExitCritical( void ) +{ + if( xSchedulerRunning != pdFALSE ) + { + if( pxCurrentTCB->uxCriticalNesting > 0 ) + { + pxCurrentTCB->uxCriticalNesting--; + + if( pxCurrentTCB->uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + } + } +} + +#endif +/*-----------------------------------------------------------*/ + + + + Index: /webserver/example/EnergyMeters/Source/portable/MemMang/heap_2.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/MemMang/heap_2.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/MemMang/heap_2.c (revision 14) @@ -0,0 +1,270 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * A sample implementation of pvPortMalloc() and vPortFree() that permits + * allocated blocks to be freed, but does not combine adjacent free blocks + * into a single larger block. + * + * See heap_1.c and heap_3.c for alternative implementations, and the memory + * management pages of http://www.FreeRTOS.org for more information. + */ +#include + +#include "FreeRTOS.h" +#include "task.h" + +/* Setup the correct byte alignment mask for the defined byte alignment. */ + +#if portBYTE_ALIGNMENT == 8 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 ) +#endif + +#ifndef heapBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +/* Allocate the memory for the heap. The struct is used to force byte +alignment without using any non-portable code. */ +static union xRTOS_HEAP +{ + #if portBYTE_ALIGNMENT == 8 + volatile portDOUBLE dDummy; + #else + volatile unsigned portLONG ulDummy; + #endif + unsigned portCHAR ucHeap[ configTOTAL_HEAP_SIZE ]; +} xHeap; + +/* Define the linked list structure. This is used to link free blocks in order +of their size. */ +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + size_t xBlockSize; /*<< The size of the free block. */ +} xBlockLink; + + +static const unsigned portSHORT heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +/* Create a couple of list links to mark the start and end of the list. */ +static xBlockLink xStart, xEnd; + +/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ + +/* + * Insert a block into the list of free blocks - which is ordered by size of + * the block. Small blocks at the start of the list and large blocks at the end + * of the list. + */ +#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ +{ \ +xBlockLink *pxIterator; \ +size_t xBlockSize; \ + \ + xBlockSize = pxBlockToInsert->xBlockSize; \ + \ + /* Iterate through the list until a block is found that has a larger size */ \ + /* than the block we are inserting. */ \ + for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ + { \ + /* There is nothing to do here - just iterate to the correct position. */ \ + } \ + \ + /* Update the list to include the block being inserted in the correct */ \ + /* position. */ \ + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ + pxIterator->pxNextFreeBlock = pxBlockToInsert; \ +} +/*-----------------------------------------------------------*/ + +#define prvHeapInit() \ +{ \ +xBlockLink *pxFirstFreeBlock; \ + \ + /* xStart is used to hold a pointer to the first item in the list of free */ \ + /* blocks. The void cast is used to prevent compiler warnings. */ \ + xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap; \ + xStart.xBlockSize = ( size_t ) 0; \ + \ + /* xEnd is used to mark the end of the list of free blocks. */ \ + xEnd.xBlockSize = configTOTAL_HEAP_SIZE; \ + xEnd.pxNextFreeBlock = NULL; \ + \ + /* To start with there is a single free block that is sized to take up the \ + entire heap space. */ \ + pxFirstFreeBlock = ( void * ) xHeap.ucHeap; \ + pxFirstFreeBlock->xBlockSize = configTOTAL_HEAP_SIZE; \ + pxFirstFreeBlock->pxNextFreeBlock = &xEnd; \ +} +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink; +static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE; +void *pvReturn = NULL; + + vTaskSuspendAll(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if( xHeapHasBeenInitialised == pdFALSE ) + { + prvHeapInit(); + xHeapHasBeenInitialised = pdTRUE; + } + + /* The wanted size is increased so it can contain a xBlockLink + structure in addition to the requested amount of bytes. */ + if( xWantedSize > 0 ) + { + xWantedSize += heapSTRUCT_SIZE; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + if( xWantedSize & heapBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & heapBYTE_ALIGNMENT_MASK ) ); + } + } + + if( ( xWantedSize > 0 ) && ( xWantedSize < configTOTAL_HEAP_SIZE ) ) + { + /* Blocks are stored in byte order - traverse the list from the start + (smallest) block until one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If we found the end marker then a block of adequate size was not found. */ + if( pxBlock != &xEnd ) + { + /* Return the memory space - jumping over the xBlockLink structure + at its start. */ + pvReturn = ( void * ) ( ( ( unsigned portCHAR * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); + + /* This block is being returned for use so must be taken our of the + list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into two. */ + if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) + { + /* This block is to be split into two. Create a new block + following the number of bytes requested. The void cast is + used to prevent byte alignment warnings from the compiler. */ + pxNewBlockLink = ( void * ) ( ( ( unsigned portCHAR * ) pxBlock ) + xWantedSize ); + + /* Calculate the sizes of two blocks split from the single + block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); + } + } + } + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ +unsigned portCHAR *puc = ( unsigned portCHAR * ) pv; +xBlockLink *pxLink; + + if( pv ) + { + /* The memory being freed will have an xBlockLink structure immediately + before it. */ + puc -= heapSTRUCT_SIZE; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = ( void * ) puc; + + vTaskSuspendAll(); + { + /* Add this block to the list of free blocks. */ + prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) ); + } + xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + Index: /webserver/example/EnergyMeters/Source/portable/MemMang/heap_3.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/MemMang/heap_3.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/MemMang/heap_3.c (revision 14) @@ -0,0 +1,104 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Implementation of pvPortMalloc() and vPortFree() that relies on the + * compilers own malloc() and free() implementations. + * + * This file can only be used if the linker is configured to to generate + * a heap memory area. + * + * See heap_2.c and heap_1.c for alternative implementations, and the memory + * management pages of http://www.FreeRTOS.org for more information. + */ + +#include + +#include "FreeRTOS.h" +#include "task.h" + +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn; + + vTaskSuspendAll(); + { + pvReturn = malloc( xWantedSize ); + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + if( pv ) + { + vTaskSuspendAll(); + { + free( pv ); + } + xTaskResumeAll(); + } +} + + + Index: /webserver/example/EnergyMeters/Source/portable/MemMang/heap_1.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/MemMang/heap_1.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/MemMang/heap_1.c (revision 14) @@ -0,0 +1,153 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * The simplest possible implementation of pvPortMalloc(). Note that this + * implementation does NOT allow allocated memory to be freed again. + * + * See heap_2.c and heap_3.c for alternative implementations, and the memory + * management pages of http://www.FreeRTOS.org for more information. + */ +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Setup the correct byte alignment mask for the defined byte alignment. */ + +#if portBYTE_ALIGNMENT == 8 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define heapBYTE_ALIGNMENT_MASK ( ( size_t ) 0x0000 ) +#endif + +#ifndef heapBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +/* Allocate the memory for the heap. The struct is used to force byte +alignment without using any non-portable code. */ +static union xRTOS_HEAP +{ + #if portBYTE_ALIGNMENT == 8 + volatile portDOUBLE dDummy; + #else + volatile unsigned portLONG ulDummy; + #endif + unsigned portCHAR ucHeap[ configTOTAL_HEAP_SIZE ]; +} xHeap; + +static size_t xNextFreeByte = ( size_t ) 0; +/*-----------------------------------------------------------*/ + +void *pvPortMalloc( size_t xWantedSize ) +{ +void *pvReturn = NULL; + + /* Ensure that blocks are always aligned to the required number of bytes. */ + #if portBYTE_ALIGNMENT != 1 + if( xWantedSize & heapBYTE_ALIGNMENT_MASK ) + { + /* Byte alignment required. */ + xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & heapBYTE_ALIGNMENT_MASK ) ); + } + #endif + + vTaskSuspendAll(); + { + /* Check there is enough room left for the allocation. */ + if( ( ( xNextFreeByte + xWantedSize ) < configTOTAL_HEAP_SIZE ) && + ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */ + { + /* Return the next free byte then increment the index past this + block. */ + pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] ); + xNextFreeByte += xWantedSize; + } + } + xTaskResumeAll(); + + #if( configUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + } + #endif + + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vPortFree( void *pv ) +{ + /* Memory cannot be freed using this scheme. See heap_2.c and heap_3.c + for alternative implementations, and the memory management pages of + http://www.FreeRTOS.org for more information. */ + ( void ) pv; +} +/*-----------------------------------------------------------*/ + +void vPortInitialiseBlocks( void ) +{ + /* Only required when static memory is not cleared. */ + xNextFreeByte = ( size_t ) 0; +} + + Index: /webserver/example/EnergyMeters/Source/portable/Rowley/ARM7/readme.txt =================================================================== --- /webserver/example/EnergyMeters/Source/portable/Rowley/ARM7/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/Rowley/ARM7/readme.txt (revision 14) @@ -0,0 +1,1 @@ +The Rowley ARM7 demo uses the GCC ARM7 port files. Index: /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portext.asm =================================================================== --- /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portext.asm (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portext.asm (revision 14) @@ -0,0 +1,123 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#include "FreeRTOSConfig.h" +#include "portasm.h" + + +.CODE + +/* + * The RTOS tick ISR. + * + * If the cooperative scheduler is in use this simply increments the tick + * count. + * + * If the preemptive scheduler is in use a context switch can also occur. + */ +_vTickISR: + portSAVE_CONTEXT + + call #_vTaskIncrementTick + + #if configUSE_PREEMPTION == 1 + call #_vTaskSwitchContext + #endif + + portRESTORE_CONTEXT +/*-----------------------------------------------------------*/ + + +/* + * Manual context switch called by the portYIELD() macro. + */ +_vPortYield:: + + /* Mimic an interrupt by pushing the SR. */ + push SR + + /* Now the SR is stacked we can disable interrupts. */ + dint + + /* Save the context of the current task. */ + portSAVE_CONTEXT + + /* Switch to the highest priority task that is ready to run. */ + call #_vTaskSwitchContext + + /* Restore the context of the new task. */ + portRESTORE_CONTEXT +/*-----------------------------------------------------------*/ + + +/* + * Start off the scheduler by initialising the RTOS tick timer, then restoring + * the context of the first task. + */ +_xPortStartScheduler:: + + /* Setup the hardware to generate the tick. Interrupts are disabled + when this function is called. */ + call #_prvSetupTimerInterrupt + + /* Restore the context of the first task that is going to run. */ + portRESTORE_CONTEXT +/*-----------------------------------------------------------*/ + + + /* Place the tick ISR in the correct vector. */ + .VECTORS + + .KEEP + + ORG TIMERA0_VECTOR + DW _vTickISR + + + + END + Index: /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/port.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/port.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/port.c (revision 14) @@ -0,0 +1,192 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the MSP430 port. + *----------------------------------------------------------*/ + +/* Constants required for hardware setup. The tick ISR runs off the ACLK, +not the MCLK. */ +#define portACLK_FREQUENCY_HZ ( ( portTickType ) 32768 ) +#define portINITIAL_CRITICAL_NESTING ( ( unsigned portSHORT ) 10 ) +#define portFLAGS_INT_ENABLED ( ( portSTACK_TYPE ) 0x08 ) + +/* We require the address of the pxCurrentTCB variable, but don't want to know +any details of its type. */ +typedef void tskTCB; +extern volatile tskTCB * volatile pxCurrentTCB; + +/* Each task maintains a count of the critical section nesting depth. Each +time a critical section is entered the count is incremented. Each time a +critical section is exited the count is decremented - with interrupts only +being re-enabled if the count is zero. + +usCriticalNesting will get set to zero when the scheduler starts, but must +not be initialised to zero as this will cause problems during the startup +sequence. */ +volatile unsigned portSHORT usCriticalNesting = portINITIAL_CRITICAL_NESTING; +/*-----------------------------------------------------------*/ + + +/* + * Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but + * could have alternatively used the watchdog timer or timer 1. + */ +void prvSetupTimerInterrupt( void ); +/*-----------------------------------------------------------*/ + +/* + * Initialise the stack of a task to look exactly as if a call to + * portSAVE_CONTEXT had been called. + * + * See the header file portable.h. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* + Place a few bytes of known values on the bottom of the stack. + This is just useful for debugging and can be included if required. + + *pxTopOfStack = ( portSTACK_TYPE ) 0x1111; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x2222; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x3333; + pxTopOfStack--; + */ + + /* The msp430 automatically pushes the PC then SR onto the stack before + executing an ISR. We want the stack to look just as if this has happened + so place a pointer to the start of the task on the stack first - followed + by the flags we want the task to use when it starts up. */ + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; + pxTopOfStack--; + *pxTopOfStack = portFLAGS_INT_ENABLED; + pxTopOfStack--; + + /* Next the general purpose registers. */ + *pxTopOfStack = ( portSTACK_TYPE ) 0x4444; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x5555; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x6666; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x7777; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x8888; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x9999; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaa; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0xbbbb; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0xcccc; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0xdddd; + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0xeeee; + pxTopOfStack--; + + /* When the task starts is will expect to find the function parameter in + R15. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; + pxTopOfStack--; + + /* A variable is used to keep track of the critical section nesting. + This variable has to be stored as part of the task context and is + initially set to zero. */ + *pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_SECTION_NESTING; + + /* Return a pointer to the top of the stack we have generated so this can + be stored in the task control block for the task. */ + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the MSP430 port will get stopped. If required simply + disable the tick interrupt here. */ +} +/*-----------------------------------------------------------*/ + +/* + * Hardware initialisation to generate the RTOS tick. This uses timer 0 + * but could alternatively use the watchdog timer or timer 1. + */ +void prvSetupTimerInterrupt( void ) +{ + /* Ensure the timer is stopped. */ + TACTL = 0; + + /* Run the timer of the ACLK. */ + TACTL = TASSEL_1; + + /* Clear everything to start with. */ + TACTL |= TACLR; + + /* Set the compare match value according to the tick rate we want. */ + TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ; + + /* Enable the interrupts. */ + TACCTL0 = CCIE; + + /* Start up clean. */ + TACTL |= TACLR; + + /* Up mode. */ + TACTL |= MC_1; +} +/*-----------------------------------------------------------*/ + + + Index: /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portasm.h =================================================================== --- /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portasm.h (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portasm.h (revision 14) @@ -0,0 +1,100 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PORT_ASM_H +#define PORT_ASM_H + +portSAVE_CONTEXT macro + /* Save the remaining registers. */ + push r4 + push r5 + push r6 + push r7 + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + mov.w &_usCriticalNesting, r14 + push r14 + mov.w &_pxCurrentTCB, r12 + mov.w r1, @r12 + endm +/*-----------------------------------------------------------*/ + +portRESTORE_CONTEXT macro + mov.w &_pxCurrentTCB, r12 + mov.w @r12, r1 + pop r15 + mov.w r15, &_usCriticalNesting + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop r7 + pop r6 + pop r5 + pop r4 + + /* The last thing on the stack will be the status register. + Ensure the power down bits are clear ready for the next + time this power down register is popped from the stack. */ + bic.w #0xf0,0(SP) + + reti + endm +/*-----------------------------------------------------------*/ + +#endif + Index: /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portmacro.h =================================================================== --- /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portmacro.h (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/Rowley/MSP430F449/portmacro.h (revision 14) @@ -0,0 +1,147 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT int +#define portSTACK_TYPE unsigned portSHORT +#define portBASE_TYPE portSHORT + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif + +/*-----------------------------------------------------------*/ + +/* Interrupt control macros. */ +#define portDISABLE_INTERRUPTS() _DINT(); +#define portENABLE_INTERRUPTS() _EINT(); +/*-----------------------------------------------------------*/ + +/* Critical section control macros. */ +#define portNO_CRITICAL_SECTION_NESTING ( ( unsigned portSHORT ) 0 ) + +#define portENTER_CRITICAL() \ +{ \ +extern volatile unsigned portSHORT usCriticalNesting; \ + \ + portDISABLE_INTERRUPTS(); \ + \ + /* Now interrupts are disabled usCriticalNesting can be accessed */ \ + /* directly. Increment ulCriticalNesting to keep a count of how many */ \ + /* times portENTER_CRITICAL() has been called. */ \ + usCriticalNesting++; \ +} + +#define portEXIT_CRITICAL() \ +{ \ +extern volatile unsigned portSHORT usCriticalNesting; \ + \ + if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ + { \ + /* Decrement the nesting count as we are leaving a critical section. */ \ + usCriticalNesting--; \ + \ + /* If the nesting level has reached zero then interrupts should be */ \ + /* re-enabled. */ \ + if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ + { \ + portENABLE_INTERRUPTS(); \ + } \ + } \ +} +/*-----------------------------------------------------------*/ + +/* Task utilities. */ + +/* + * Manual context switch called by portYIELD or taskYIELD. + */ +extern void vPortYield( void ); +#define portYIELD() vPortYield() +/*-----------------------------------------------------------*/ + +/* Hardware specifics. */ +#define portBYTE_ALIGNMENT 2 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portNOP() +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) __toplevel + +#if configINTERRUPT_EXAMPLE_METHOD == 2 + +extern void vTaskSwitchContext( void ); +#define portYIELD_FROM_ISR( x ) if( x ) vTaskSwitchContext() + +#endif + +#endif /* PORTMACRO_H */ + Index: /webserver/example/EnergyMeters/Source/portable/readme.txt =================================================================== --- /webserver/example/EnergyMeters/Source/portable/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/readme.txt (revision 14) @@ -0,0 +1,19 @@ +Each real time kernel port consists of three files that contain the core kernel +components and are common to every port, and one or more files that are +specific to a particular microcontroller and/or compiler. + + ++ The FreeRTOS/Source/Portable/MemMang directory contains the three sample +memory allocators as described on the http://www.FreeRTOS.org WEB site. + ++ The other directories each contain files specific to a particular +microcontroller or compiler. + + + +For example, if you are interested in the GCC port for the ATMega323 +microcontroller then the port specific files are contained in +FreeRTOS/Source/Portable/GCC/ATMega323 directory. If this is the only +port you are interested in then all the other directories can be +ignored. + Index: /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portISR.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portISR.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portISR.c (revision 14) @@ -0,0 +1,232 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/*----------------------------------------------------------- + * Components that can be compiled to either ARM or THUMB mode are + * contained in port.c The ISR routines, which can only be compiled + * to ARM mode, are contained in this file. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to handle interrupts. */ +#define portTIMER_MATCH_ISR_BIT ( ( unsigned portCHAR ) 0x01 ) +#define portCLEAR_VIC_INTERRUPT ( ( unsigned portLONG ) 0 ) + +/* Constants required to handle critical sections. */ +#define portNO_CRITICAL_NESTING ( ( unsigned portLONG ) 0 ) +volatile unsigned portLONG ulCriticalNesting = 9999UL; + +/*-----------------------------------------------------------*/ + +/* ISR to handle manual context switches (from a call to taskYIELD()). */ +void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked)); + +/* + * The scheduler can only be started from ARM mode, hence the inclusion of this + * function here. + */ +void vPortISRStartFirstTask( void ); +/*-----------------------------------------------------------*/ + +void vPortISRStartFirstTask( void ) +{ + /* Simply start the scheduler. This is included here as it can only be + called from ARM mode. */ + portRESTORE_CONTEXT(); +} +/*-----------------------------------------------------------*/ + +/* + * Called by portYIELD() or taskYIELD() to manually force a context switch. + * + * When a context switch is performed from the task level the saved task + * context is made to look as if it occurred from within the tick ISR. This + * way the same restore context function can be used when restoring the context + * saved from the ISR or that saved from a call to vPortYieldProcessor. + */ +void vPortYieldProcessor( void ) +{ + /* Within an IRQ ISR the link register has an offset from the true return + address, but an SWI ISR does not. Add the offset manually so the same + ISR return code can be used in both cases. */ + asm volatile ( "ADD LR, LR, #4" ); + + /* Perform the context switch. First save the context of the current task. */ + portSAVE_CONTEXT(); + + /* Find the highest priority task that is ready to run. */ + vTaskSwitchContext(); + + /* Restore the context of the new task. */ + portRESTORE_CONTEXT(); +} +/*-----------------------------------------------------------*/ + +/* + * The ISR used for the scheduler tick depends on whether the cooperative or + * the preemptive scheduler is being used. + */ + + +#if configUSE_PREEMPTION == 0 + + /* The cooperative scheduler requires a normal IRQ service routine to + simply increment the system tick. */ + void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ"))); + void vNonPreemptiveTick( void ) + { + vTaskIncrementTick(); + T0IR = 2; + VICVectAddr = portCLEAR_VIC_INTERRUPT; + } + +#else + + /* The preemptive scheduler is defined as "naked" as the full context is + saved on entry as part of the context switch. */ + void vPreemptiveTick( void ) __attribute__((naked)); + void vPreemptiveTick( void ) + { + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + + /* Increment the RTOS tick count, then look for the highest priority + task that is ready to run. */ + vTaskIncrementTick(); + vTaskSwitchContext(); + + /* Ready for the next interrupt. */ + T0IR = 2; + VICVectAddr = portCLEAR_VIC_INTERRUPT; + + /* Restore the context of the new task. */ + portRESTORE_CONTEXT(); + } + +#endif +/*-----------------------------------------------------------*/ + +/* + * The interrupt management utilities can only be called from ARM mode. When + * THUMB_INTERWORK is defined the utilities are defined as functions here to + * ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then + * the utilities are defined as macros in portmacro.h - as per other ports. + */ +#ifdef THUMB_INTERWORK + + void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); + void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); + + void vPortDisableInterruptsFromThumb( void ) + { + asm volatile ( + "STMDB SP!, {R0} \n\t" /* Push R0. */ + "MRS R0, CPSR \n\t" /* Get CPSR. */ + "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ + "LDMIA SP!, {R0} \n\t" /* Pop R0. */ + "BX R14" ); /* Return back to thumb. */ + } + + void vPortEnableInterruptsFromThumb( void ) + { + asm volatile ( + "STMDB SP!, {R0} \n\t" /* Push R0. */ + "MRS R0, CPSR \n\t" /* Get CPSR. */ + "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ + "LDMIA SP!, {R0} \n\t" /* Pop R0. */ + "BX R14" ); /* Return back to thumb. */ + } + +#endif /* THUMB_INTERWORK */ + +/* The code generated by the GCC compiler uses the stack in different ways at +different optimisation levels. The interrupt flags can therefore not always +be saved to the stack. Instead the critical section nesting level is stored +in a variable, which is then saved as part of the stack context. */ +void vPortEnterCritical( void ) +{ + /* Disable interrupts as per portDISABLE_INTERRUPTS(); */ + asm volatile ( + "STMDB SP!, {R0} \n\t" /* Push R0. */ + "MRS R0, CPSR \n\t" /* Get CPSR. */ + "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ + "LDMIA SP!, {R0}" ); /* Pop R0. */ + + /* Now interrupts are disabled ulCriticalNesting can be accessed + directly. Increment ulCriticalNesting to keep a count of how many times + portENTER_CRITICAL() has been called. */ + ulCriticalNesting++; +} + +void vPortExitCritical( void ) +{ + if( ulCriticalNesting > portNO_CRITICAL_NESTING ) + { + /* Decrement the nesting count as we are leaving a critical section. */ + ulCriticalNesting--; + + /* If the nesting level has reached zero then interrupts should be + re-enabled. */ + if( ulCriticalNesting == portNO_CRITICAL_NESTING ) + { + /* Enable interrupts as per portEXIT_CRITICAL(). */ + asm volatile ( + "STMDB SP!, {R0} \n\t" /* Push R0. */ + "MRS R0, CPSR \n\t" /* Get CPSR. */ + "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ + "LDMIA SP!, {R0}" ); /* Pop R0. */ + } + } +} Index: /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/port.c =================================================================== --- /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/port.c (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/port.c (revision 14) @@ -0,0 +1,250 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM7 port. + * + * Components that can be compiled to either ARM or THUMB mode are + * contained in this file. The ISR routines, which can only be compiled + * to ARM mode are contained in portISR.c. + *----------------------------------------------------------*/ + + +/* Standard includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to setup the task context. */ +#define portINITIAL_SPSR ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ +#define portTHUMB_MODE_BIT ( ( portSTACK_TYPE ) 0x20 ) +#define portINSTRUCTION_SIZE ( ( portSTACK_TYPE ) 4 ) +#define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 ) + +/* Constants required to setup the tick ISR. */ +#define portENABLE_TIMER ( ( unsigned portCHAR ) 0x01 ) +#define portPRESCALE_VALUE 0x00 +#define portINTERRUPT_ON_MATCH ( ( unsigned portLONG ) 0x01 ) +#define portRESET_COUNT_ON_MATCH ( ( unsigned portLONG ) 0x02 ) + +/* Constants required to setup the VIC for the tick ISR. */ +#define portTIMER_VIC_CHANNEL ( ( unsigned portLONG ) 0x0004 ) +#define portTIMER_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x0010 ) +#define portTIMER_VIC_ENABLE ( ( unsigned portLONG ) 0x0020 ) + +/*-----------------------------------------------------------*/ + +/* Setup the timer to generate the tick interrupts. */ +static void prvSetupTimerInterrupt( void ); + +/* + * The scheduler can only be started from ARM mode, so + * vPortISRStartFirstSTask() is defined in portISR.c. + */ +extern void vPortISRStartFirstTask( void ); + +/*-----------------------------------------------------------*/ + +/* + * Initialise the stack of a task to look exactly as if a call to + * portSAVE_CONTEXT had been called. + * + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ +portSTACK_TYPE *pxOriginalTOS; + + pxOriginalTOS = pxTopOfStack; + + /* Setup the initial stack of the task. The stack is set exactly as + expected by the portRESTORE_CONTEXT() macro. */ + + /* First on the stack is the return address - which in this case is the + start of the task. The offset is added to make the return address appear + as it would within an IRQ ISR. */ + *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE; + pxTopOfStack--; + + *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000; /* R14 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909; /* R9 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808; /* R8 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707; /* R7 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606; /* R6 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505; /* R5 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404; /* R4 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101; /* R1 */ + pxTopOfStack--; + + /* When the task starts is will expect to find the function parameter in + R0. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack--; + + /* The last thing onto the stack is the status register, which is set for + system mode, with interrupts enabled. */ + *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR; + + #ifdef THUMB_INTERWORK + { + /* We want the task to start in thumb mode. */ + *pxTopOfStack |= portTHUMB_MODE_BIT; + } + #endif + + pxTopOfStack--; + + /* Some optimisation levels use the stack differently to others. This + means the interrupt flags cannot always be stored on the stack and will + instead be stored in a variable, which is then saved as part of the + tasks context. */ + *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING; + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Start the first task. */ + vPortISRStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the ARM port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +/* + * Setup the timer 0 to generate the tick interrupts at the required frequency. + */ +static void prvSetupTimerInterrupt( void ) +{ +unsigned portLONG ulCompareMatch; + + PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); + T0TCR = 2; /* Stop and reset the timer */ + T0CTCR = 0; /* Timer mode */ + + /* A 1ms tick does not require the use of the timer prescale. This is + defaulted to zero but can be used if necessary. */ + T0PR = portPRESCALE_VALUE; + + /* Calculate the match value required for our wanted tick rate. */ + ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; + + /* Protect against divide by zero. Using an if() statement still results + in a warning - hence the #if. */ + #if portPRESCALE_VALUE != 0 + { + ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); + } + #endif + T0MR1 = ulCompareMatch; + + /* Generate tick with timer 0 compare match. */ + T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */ + + /* Setup the VIC for the timer. */ + VICIntEnable = 0x00000010; + + /* The ISR installed depends on whether the preemptive or cooperative + scheduler is being used. */ + #if configUSE_PREEMPTION == 1 + { + extern void ( vPreemptiveTick )( void ); + VICVectAddr4 = ( portLONG ) vPreemptiveTick; + } + #else + { + extern void ( vNonPreemptiveTick )( void ); + VICVectAddr4 = ( portLONG ) vNonPreemptiveTick; + } + #endif + + VICVectCntl4 = 1; + + /* Start the timer - interrupts are disabled when this function is called + so it is okay to do this here. */ + T0TCR = portENABLE_TIMER; +} +/*-----------------------------------------------------------*/ + + + Index: /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portmacro.h =================================================================== --- /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portmacro.h (revision 14) +++ /webserver/example/EnergyMeters/Source/portable/GCC/ARM7_LPC23xx/portmacro.h (revision 14) @@ -0,0 +1,265 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + Changes from V3.2.3 + + + Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1. + + Changes from V3.2.4 + + + Removed the use of the %0 parameter within the assembler macros and + replaced them with hard coded registers. This will ensure the + assembler does not select the link register as the temp register as + was occasionally happening previously. + + + The assembler statements are now included in a single asm block rather + than each line having its own asm block. + + Changes from V4.5.0 + + + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros + and replaced them with portYIELD_FROM_ISR() macro. Application code + should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT() + macros as per the V4.5.1 demo code. +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE unsigned portLONG +#define portBASE_TYPE portLONG + +#if( configUSE_16_BIT_TICKS == 1 ) + typedef unsigned portSHORT portTickType; + #define portMAX_DELAY ( portTickType ) 0xffff +#else + typedef unsigned portLONG portTickType; + #define portMAX_DELAY ( portTickType ) 0xffffffff +#endif +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 4 +#define portNOP() asm volatile ( "NOP" ); +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ + +/* + * portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR + * and portEXIT_SWITCHING_ISR can only be called from ARM mode, but + * are included here for efficiency. An attempt to call one from + * THUMB mode code will result in a compile time error. + */ + +#define portRESTORE_CONTEXT() \ +{ \ +extern volatile void * volatile pxCurrentTCB; \ +extern volatile unsigned portLONG ulCriticalNesting; \ + \ + /* Set the LR to the task stack. */ \ + asm volatile ( \ + "LDR R0, =pxCurrentTCB \n\t" \ + "LDR R0, [R0] \n\t" \ + "LDR LR, [R0] \n\t" \ + \ + /* The critical nesting depth is the first item on the stack. */ \ + /* Load it into the ulCriticalNesting variable. */ \ + "LDR R0, =ulCriticalNesting \n\t" \ + "LDMFD LR!, {R1} \n\t" \ + "STR R1, [R0] \n\t" \ + \ + /* Get the SPSR from the stack. */ \ + "LDMFD LR!, {R0} \n\t" \ + "MSR SPSR, R0 \n\t" \ + \ + /* Restore all system mode registers for the task. */ \ + "LDMFD LR, {R0-R14}^ \n\t" \ + "NOP \n\t" \ + \ + /* Restore the return address. */ \ + "LDR LR, [LR, #+60] \n\t" \ + \ + /* And return - correcting the offset in the LR to obtain the */ \ + /* correct address. */ \ + "SUBS PC, LR, #4 \n\t" \ + ); \ + ( void ) ulCriticalNesting; \ + ( void ) pxCurrentTCB; \ +} +/*-----------------------------------------------------------*/ + +#define portSAVE_CONTEXT() \ +{ \ +extern volatile void * volatile pxCurrentTCB; \ +extern volatile unsigned portLONG ulCriticalNesting; \ + \ + /* Push R0 as we are going to use the register. */ \ + asm volatile ( \ + "STMDB SP!, {R0} \n\t" \ + \ + /* Set R0 to point to the task stack pointer. */ \ + "STMDB SP,{SP}^ \n\t" \ + "NOP \n\t" \ + "SUB SP, SP, #4 \n\t" \ + "LDMIA SP!,{R0} \n\t" \ + \ + /* Push the return address onto the stack. */ \ + "STMDB R0!, {LR} \n\t" \ + \ + /* Now we have saved LR we can use it instead of R0. */ \ + "MOV LR, R0 \n\t" \ + \ + /* Pop R0 so we can save it onto the system mode stack. */ \ + "LDMIA SP!, {R0} \n\t" \ + \ + /* Push all the system mode registers onto the task stack. */ \ + "STMDB LR,{R0-LR}^ \n\t" \ + "NOP \n\t" \ + "SUB LR, LR, #60 \n\t" \ + \ + /* Push the SPSR onto the task stack. */ \ + "MRS R0, SPSR \n\t" \ + "STMDB LR!, {R0} \n\t" \ + \ + "LDR R0, =ulCriticalNesting \n\t" \ + "LDR R0, [R0] \n\t" \ + "STMDB LR!, {R0} \n\t" \ + \ + /* Store the new top of stack for the task. */ \ + "LDR R0, =pxCurrentTCB \n\t" \ + "LDR R0, [R0] \n\t" \ + "STR LR, [R0] \n\t" \ + ); \ + ( void ) ulCriticalNesting; \ + ( void ) pxCurrentTCB; \ +} + + +#define portYIELD_FROM_ISR() vTaskSwitchContext() +#define portYIELD() asm volatile ( "SWI" ) +/*-----------------------------------------------------------*/ + + +/* Critical section management. */ + +/* + * The interrupt management utilities can only be called from ARM mode. When + * THUMB_INTERWORK is defined the utilities are defined as functions in + * portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not + * defined then the utilities are defined as macros here - as per other ports. + */ + +#ifdef THUMB_INTERWORK + + extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked)); + extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked)); + + #define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb() + #define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb() + +#else + + #define portDISABLE_INTERRUPTS() \ + asm volatile ( \ + "STMDB SP!, {R0} \n\t" /* Push R0. */ \ + "MRS R0, CPSR \n\t" /* Get CPSR. */ \ + "ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ \ + "LDMIA SP!, {R0} " ) /* Pop R0. */ + + #define portENABLE_INTERRUPTS() \ + asm volatile ( \ + "STMDB SP!, {R0} \n\t" /* Push R0. */ \ + "MRS R0, CPSR \n\t" /* Get CPSR. */ \ + "BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \ + "MSR CPSR, R0 \n\t" /* Write back modified value. */ \ + "LDMIA SP!, {R0} " ) /* Pop R0. */ + +#endif /* THUMB_INTERWORK */ + +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); + +#define portENTER_CRITICAL() vPortEnterCritical(); +#define portEXIT_CRITICAL() vPortExitCritical(); +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + Index: /webserver/example/EnergyMeters/Source/EnergyMeters/Meters.c =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/Meters.c (revision 22) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/Meters.c (revision 22) @@ -0,0 +1,125 @@ + +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +#define metersSTACK_SIZE configMINIMAL_STACK_SIZE+200 +/* masks for RTC */ +#define MASKSEC 0x3F // Second 00..59 00000000:00000000:00xxxxxx +#define MASKMIN 0x3F00 // Minute 00..59 00000000:00xxxxxx:00000000 +#define MASKHR 0x1F0000 // Hour 00..23 000xxxxx:00000000:00000000 + +#include "MetersIncludes.h" + +extern xTickCount; /* tick counter (milliseconds) */ + +portBASE_TYPE Init_P2_0(void); +void basementGasCalculation(void); + +portLONG basementGasReading = 0; +portTickType basementGasLastTime = 0; + +/* The semaphore used to wake the Meters task when a pulse was received or the timer expired. */ +xSemaphoreHandle xMetersSemaphore = NULL; + +portTickType xLastMeterTaskRunTime; /* keeps the last time the meter calculation ran */ + + + int rtcHOURS; + int rtcMINUTES; + int rtcSECONDS; +static portTASK_FUNCTION( vMeters_Task, pvParameters ) +{ + + + + vSemaphoreCreateBinary( xMetersSemaphore ); + + Init_P2_0(); /* init GPIO for meters */ + + for( ;; ) + { + + basementGasCalculation(); + + portENTER_CRITICAL(); + // example: do stuff + portEXIT_CRITICAL(); + + /* We did not receive a pulse, and there was no periodic + processing to perform. Block for a fixed period. If a pulse + is received during this period we will be woken by the ISR + giving us the Semaphore. */ + xLastMeterTaskRunTime = xTaskGetTickCount(); /* update last run time */ + + rtcHOURS = (RTC_CTIME0 & MASKHR)>>16; // Read Hour + rtcMINUTES = (RTC_CTIME0 & MASKMIN)>>8; // Read Minute + rtcSECONDS = RTC_CTIME0 & MASKSEC; // Read Second + + xSemaphoreTake( xMetersSemaphore, 1000 ); /* timeout 1 sec */ + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} + + + +void vStartMetersTask( unsigned portBASE_TYPE uxPriority ) +{ + + initMeterItems(); + /* Spawn the task. */ + xTaskCreate( vMeters_Task, ( signed portCHAR * ) "Meters", metersSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); +} + +void vP2_0_ISR_Wrapper( void ); + +// configure port-pins for use with LAN-controller, +// reset it and send the configuration-sequence + +portBASE_TYPE Init_P2_0(void) +{ + // not needed yet : SCS |= 1; // Enable FAST GPIO + portBASE_TYPE xReturn = 1; // return value + + /* Enable Pins. */ + + PINSEL4 &= 0xfffff3ff; /* reset bit 20 and 21, P2.10 = GPIO Port 2.10 */ + PINMODE4 &= 0xfffff3ff; /* reset bit 20 and 21, enable on-chip pull-up resistor on Port 2.10 */ + IO2_INT_EN_R |= (1<<10); /* enable rising edge interrupt for P2:10 */ + IO2_INT_EN_F &= ~(1<<10); /* disable falling edge interrupt for P2:10 */ + + VICVectAddr17 = (portLONG) vP2_0_ISR_Wrapper; /* EINT-3 interrupt handler */ + + VICIntEnable |= (1<<17); /* Enable VIC index-17 (shared by EINT3 and GPIO) */ + + return xReturn; +} + + +void basementGasCalculation(void) +{ + +} + +void initMeterItems(void) +{ + int i; + for (i = 0; i < NUMBER_OF_METERS; i++) + { + meterItems[i].meterEnabled = 0; // disable all meters + } + + // Init Gas meter + meterItems[METER_INDEX_GAS].meterEnabled = 1; /* 0: item not used, 1: meter enabled */ + meterItems[METER_INDEX_GAS].timeLastTick = getEpochTimeWithMs(); /* when did the last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].timeBeforeLastTick = getEpochTimeWithMs(); /* when did the tick before last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].valueLastTick = 0; /* what value did we have at the last tick? */ + meterItems[METER_INDEX_GAS].valueBeforeLastTick = 1; /* what value did we have at the tick before the last tick? */ + +} Index: /webserver/example/EnergyMeters/Source/EnergyMeters/Meters_ISRs.c =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/Meters_ISRs.c (revision 22) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/Meters_ISRs.c (revision 22) @@ -0,0 +1,68 @@ +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" +#include "MetersIncludes.h" + +extern xMetersSemaphore; +extern xTickCount; /* millisecond tick counter */ + +void handleGasMeterTick(void); + +/* The interrupt entry point. */ +void vP2_0_ISR_Wrapper( void ) __attribute__((naked)); + +/* The function that actually performs the interrupt processing. This must be +separate to the wrapper to ensure the correct stack frame is set up. */ +void vP2_0_ISR_Handler( void ); + +void vP2_0_ISR_Handler( void ) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if ((IO2_INT_STAT_R & (1 << 10)) != 0) /* P2.10 interrupt triggered */ + { + handleGasMeterTick(); + } + // else if ((IO2_INT_STAT_R & (1 << n)) != 0) /* some other interrupt triggered */ + { + ; + } + + /* Clear the interrupt. */ + IO2_INT_CLR |= (1<<10); + VICVectAddr = 0; + + /* Unblock the Meters task as data has arrived. */ + xSemaphoreGiveFromISR( xMetersSemaphore, &xHigherPriorityTaskWoken ); + + if( xHigherPriorityTaskWoken ) + { + /* If the Meters task was unblocked then calling "Yield from ISR" here + will ensure the interrupt returns directly to the Meters task, if it + is the highest priority read task. */ + portYIELD_FROM_ISR(); + } +} +/*-----------------------------------------------------------*/ + +void vP2_0_ISR_Wrapper( void ) +{ + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + + /* Call the handler function. This must be separate from the wrapper + function to ensure the correct stack frame is set up. */ + vP2_0_ISR_Handler(); + + /* Restore the context of whichever task is going to run next. */ + portRESTORE_CONTEXT(); +} + +void handleGasMeterTick(void) +{ + meterItems[METER_INDEX_GAS].timeBeforeLastTick = meterItems[METER_INDEX_GAS].timeLastTick; /* when did the tick before the last tick occur? */ + meterItems[METER_INDEX_GAS].timeLastTick = getEpochTimeWithMs(); /* when did the last tick occur? epoch (seconds) */ + meterItems[METER_INDEX_GAS].valueLastTick = 0; /* what value did we have at the last tick? */ + meterItems[METER_INDEX_GAS].valueBeforeLastTick = 1; /* what value did we have at the tick before the last tick? */ +} + Index: /webserver/example/EnergyMeters/Source/EnergyMeters/timeConversion.c =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/timeConversion.c (revision 22) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/timeConversion.c (revision 22) @@ -0,0 +1,92 @@ + +#include +#include "FreeRTOS.h" +#include "MetersIncludes.h" +#include "task.h" +#include "StackMacros.h" + +#define MASKSEC 0x3F // Second 00..59 00000000:00000000:00xxxxxx +#define MASKMIN 0x3F00 // Minute 00..59 00000000:00xxxxxx:00000000 +#define MASKHR 0x1F0000 // Hour 00..23 000xxxxx:00000000:00000000 + +extern xTickCount; /* tick counter (milliseconds) from FreeRTOS */ + +/* taken from Linux Kernel 2.6.30 */ +portLONG +mktime(const unsigned int year0, const unsigned int mon0, + const unsigned int day, const unsigned int hour, + const unsigned int min, const unsigned int sec); +unsigned long long getEpochTimeWithMs(void) +{ + /* get both registers while in critical section to eliminate the chance of inconsistencies when there are + * overflows of the SECONDS value. + */ + unsigned int timeHour; + unsigned int timeMin; + unsigned int timeSec; + unsigned int timeDay; + unsigned int timeMonth; + unsigned int timeYear; + unsigned long long tempTickTime; + portLONG cTIME0; + portLONG cTIME1; + +// portENTER_CRITICAL(); + cTIME0 = RTC_CTIME0; + cTIME1 = RTC_CTIME1; +// portEXIT_CRITICAL(); + + + timeHour = (cTIME0 & MASKHR)>>16; // Hour + timeMin = (cTIME0 & MASKMIN)>>8; // Minute + timeSec = cTIME0 & MASKSEC; // Second + timeDay = cTIME1 & 0xf; // Day + timeMonth = (cTIME1 >> 8) & 0xF; // Month + timeYear = (cTIME1 >> 16) & 0xFFF; // Year + + /* we get the epoch time, multiply it by 1000 and then add the milliseconds portion + of the Tick timer. This returns a millisecond time since epoch. + */ + tempTickTime = mktime(timeYear, timeMonth, timeDay, timeHour, timeMin, timeSec); + tempTickTime -= 3600 * 2; /* time zone adaptation (2 h) */ + tempTickTime = (tempTickTime * 1000) + (xTickCount % 1000); + return tempTickTime; +} + + +// mktime from linux kernel 2.6.30 kernel / time.c +/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. + * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 + * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. + * + * [For the Julian calendar (which was used in Russia before 1917, + * Britain & colonies before 1752, anywhere else before 1582, + * and is still in use by some communities) leave out the + * -year/100+year/400 terms, and add 10.] + * + * This algorithm was first published by Gauss (I think). + * + * WARNING: this function will overflow on 2106-02-07 06:28:16 on + * machines where long is 32-bit! (However, as time_t is signed, we + * will already get problems at other places on 2038-01-19 03:14:08) + */ +portLONG +mktime(const unsigned int year0, const unsigned int mon0, + const unsigned int day, const unsigned int hour, + const unsigned int min, const unsigned int sec) +{ + unsigned int mon = mon0, year = year0; + + /* 1..12 -> 11,12,1..10 */ + if (0 >= (int) (mon -= 2)) { + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return ((((portLONG) + (year/4 - year/100 + year/400 + 367*mon/12 + day) + + year*365 - 719499 + )*24 + hour /* now have hours */ + )*60 + min /* now have minutes */ + )*60 + sec; /* finally seconds */ +} Index: /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 22) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 22) @@ -0,0 +1,20 @@ + +void initMeterItems(void); +unsigned long long getEpochTimeWithMs(void); + +#define NUMBER_OF_METERS 10 /* the number of meters we use */ + +#define METER_INDEX_GAS 0 /* index of the gas meter data */ + + +typedef struct +{ + portSHORT meterEnabled; /* 0: item not used, 1: meter enabled */ + unsigned long long timeLastTick; /* when did the last tick occur? epoch time in seconds */ + unsigned long long timeBeforeLastTick; /* when did the tick before the last tick occur? epoch time in seconds */ + portLONG valueLastTick; /* what value did we have at the last tick? */ + portLONG valueBeforeLastTick; /* what value did we have at the tick before the last tick? */ +} meterItem; + +meterItem meterItems[NUMBER_OF_METERS]; /* the data for all the meters */ + Index: /webserver/example/EnergyMeters/Source/croutine.c =================================================================== --- /webserver/example/EnergyMeters/Source/croutine.c (revision 14) +++ /webserver/example/EnergyMeters/Source/croutine.c (revision 14) @@ -0,0 +1,365 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#include "FreeRTOS.h" +#include "task.h" +#include "croutine.h" + +/* + * Some kernel aware debuggers require data to be viewed to be global, rather + * than file scope. + */ +#ifdef portREMOVE_STATIC_QUALIFIER + #define static +#endif + + +/* Lists for ready and blocked co-routines. --------------------*/ +static xList pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */ +static xList xDelayedCoRoutineList1; /*< Delayed co-routines. */ +static xList xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */ +static xList * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */ +static xList * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */ +static xList xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */ + +/* Other file private variables. --------------------------------*/ +corCRCB * pxCurrentCoRoutine = NULL; +static unsigned portBASE_TYPE uxTopCoRoutineReadyPriority = 0; +static portTickType xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0; + +/* The initial state of the co-routine when it is created. */ +#define corINITIAL_STATE ( 0 ) + +/* + * Place the co-routine represented by pxCRCB into the appropriate ready queue + * for the priority. It is inserted at the end of the list. + * + * This macro accesses the co-routine ready lists and therefore must not be + * used from within an ISR. + */ +#define prvAddCoRoutineToReadyQueue( pxCRCB ) \ +{ \ + if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \ + { \ + uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \ + } \ + vListInsertEnd( ( xList * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \ +} + +/* + * Utility to ready all the lists used by the scheduler. This is called + * automatically upon the creation of the first co-routine. + */ +static void prvInitialiseCoRoutineLists( void ); + +/* + * Co-routines that are readied by an interrupt cannot be placed directly into + * the ready lists (there is no mutual exclusion). Instead they are placed in + * in the pending ready list in order that they can later be moved to the ready + * list by the co-routine scheduler. + */ +static void prvCheckPendingReadyList( void ); + +/* + * Macro that looks at the list of co-routines that are currently delayed to + * see if any require waking. + * + * Co-routines are stored in the queue in the order of their wake time - + * meaning once one co-routine has been found whose timer has not expired + * we need not look any further down the list. + */ +static void prvCheckDelayedList( void ); + +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex ) +{ +signed portBASE_TYPE xReturn; +corCRCB *pxCoRoutine; + + /* Allocate the memory that will store the co-routine control block. */ + pxCoRoutine = ( corCRCB * ) pvPortMalloc( sizeof( corCRCB ) ); + if( pxCoRoutine ) + { + /* If pxCurrentCoRoutine is NULL then this is the first co-routine to + be created and the co-routine data structures need initialising. */ + if( pxCurrentCoRoutine == NULL ) + { + pxCurrentCoRoutine = pxCoRoutine; + prvInitialiseCoRoutineLists(); + } + + /* Check the priority is within limits. */ + if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES ) + { + uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1; + } + + /* Fill out the co-routine control block from the function parameters. */ + pxCoRoutine->uxState = corINITIAL_STATE; + pxCoRoutine->uxPriority = uxPriority; + pxCoRoutine->uxIndex = uxIndex; + pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode; + + /* Initialise all the other co-routine control block parameters. */ + vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) ); + vListInitialiseItem( &( pxCoRoutine->xEventListItem ) ); + + /* Set the co-routine control block as a link back from the xListItem. + This is so we can get back to the containing CRCB from a generic item + in a list. */ + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine ); + listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine ); + + /* Event lists are always in priority order. */ + listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); + + /* Now the co-routine has been initialised it can be added to the ready + list at the correct priority. */ + prvAddCoRoutineToReadyQueue( pxCoRoutine ); + + xReturn = pdPASS; + } + else + { + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineAddToDelayedList( portTickType xTicksToDelay, xList *pxEventList ) +{ +portTickType xTimeToWake; + + /* Calculate the time to wake - this may overflow but this is + not a problem. */ + xTimeToWake = xCoRoutineTickCount + xTicksToDelay; + + /* We must remove ourselves from the ready list before adding + ourselves to the blocked list as the same list item is used for + both lists. */ + vListRemove( ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + + /* The list item will be inserted in wake time order. */ + listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake ); + + if( xTimeToWake < xCoRoutineTickCount ) + { + /* Wake time has overflowed. Place this item in the + overflow list. */ + vListInsert( ( xList * ) pxOverflowDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + else + { + /* The wake time has not overflowed, so we can use the + current block list. */ + vListInsert( ( xList * ) pxDelayedCoRoutineList, ( xListItem * ) &( pxCurrentCoRoutine->xGenericListItem ) ); + } + + if( pxEventList ) + { + /* Also add the co-routine to an event list. If this is done then the + function must be called with interrupts disabled. */ + vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckPendingReadyList( void ) +{ + /* Are there any co-routines waiting to get moved to the ready list? These + are co-routines that have been readied by an ISR. The ISR cannot access + the ready lists itself. */ + while( !listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) ) + { + corCRCB *pxUnblockedCRCB; + + /* The pending ready list can be accessed by an ISR. */ + portDISABLE_INTERRUPTS(); + { + pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) ); + vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + } + portENABLE_INTERRUPTS(); + + vListRemove( &( pxUnblockedCRCB->xGenericListItem ) ); + prvAddCoRoutineToReadyQueue( pxUnblockedCRCB ); + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckDelayedList( void ) +{ +corCRCB *pxCRCB; + + xPassedTicks = xTaskGetTickCount() - xLastTickCount; + while( xPassedTicks ) + { + xCoRoutineTickCount++; + xPassedTicks--; + + /* If the tick count has overflowed we need to swap the ready lists. */ + if( xCoRoutineTickCount == 0 ) + { + xList * pxTemp; + + /* Tick count has overflowed so we need to swap the delay lists. If there are + any items in pxDelayedCoRoutineList here then there is an error! */ + pxTemp = pxDelayedCoRoutineList; + pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList; + pxOverflowDelayedCoRoutineList = pxTemp; + } + + /* See if this tick has made a timeout expire. */ + while( ( pxCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList ) ) != NULL ) + { + if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) ) + { + /* Timeout not yet expired. */ + break; + } + + portDISABLE_INTERRUPTS(); + { + /* The event could have occurred just before this critical + section. If this is the case then the generic list item will + have been moved to the pending ready list and the following + line is still valid. Also the pvContainer parameter will have + been set to NULL so the following lines are also valid. */ + vListRemove( &( pxCRCB->xGenericListItem ) ); + + /* Is the co-routine waiting on an event also? */ + if( pxCRCB->xEventListItem.pvContainer ) + { + vListRemove( &( pxCRCB->xEventListItem ) ); + } + } + portENABLE_INTERRUPTS(); + + prvAddCoRoutineToReadyQueue( pxCRCB ); + } + } + + xLastTickCount = xCoRoutineTickCount; +} +/*-----------------------------------------------------------*/ + +void vCoRoutineSchedule( void ) +{ + /* See if any co-routines readied by events need moving to the ready lists. */ + prvCheckPendingReadyList(); + + /* See if any delayed co-routines have timed out. */ + prvCheckDelayedList(); + + /* Find the highest priority queue that contains ready co-routines. */ + while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) ) + { + if( uxTopCoRoutineReadyPriority == 0 ) + { + /* No more co-routines to check. */ + return; + } + --uxTopCoRoutineReadyPriority; + } + + /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines + of the same priority get an equal share of the processor time. */ + listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ); + + /* Call the co-routine. */ + ( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex ); + + return; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseCoRoutineLists( void ) +{ +unsigned portBASE_TYPE uxPriority; + + for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ ) + { + vListInitialise( ( xList * ) &( pxReadyCoRoutineLists[ uxPriority ] ) ); + } + + vListInitialise( ( xList * ) &xDelayedCoRoutineList1 ); + vListInitialise( ( xList * ) &xDelayedCoRoutineList2 ); + vListInitialise( ( xList * ) &xPendingReadyCoRoutineList ); + + /* Start with pxDelayedCoRoutineList using list1 and the + pxOverflowDelayedCoRoutineList using list2. */ + pxDelayedCoRoutineList = &xDelayedCoRoutineList1; + pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2; +} +/*-----------------------------------------------------------*/ + +signed portBASE_TYPE xCoRoutineRemoveFromEventList( const xList *pxEventList ) +{ +corCRCB *pxUnblockedCRCB; +signed portBASE_TYPE xReturn; + + /* This function is called from within an interrupt. It can only access + event lists and the pending ready list. */ + pxUnblockedCRCB = ( corCRCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); + vListRemove( &( pxUnblockedCRCB->xEventListItem ) ); + vListInsertEnd( ( xList * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) ); + + if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} + Index: /webserver/example/EnergyMeters/Source/readme.txt =================================================================== --- /webserver/example/EnergyMeters/Source/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/Source/readme.txt (revision 14) @@ -0,0 +1,17 @@ +Each real time kernel port consists of three files that contain the core kernel +components and are common to every port, and one or more files that are +specific to a particular microcontroller and or compiler. + ++ The FreeRTOS/Source directory contains the three files that are common to +every port - list.c, queue.c and tasks.c. The kernel is contained within these +three files. croutine.c implements the optional co-routine functionality - which +is normally only used on very memory limited systems. + ++ The FreeRTOS/Source/Portable directory contains the files that are specific to +a particular microcontroller and or compiler. + ++ The FreeRTOS/Source/include directory contains the real time kernel header +files. + +See the readme file in the FreeRTOS/Source/Portable directory for more +information. Index: /webserver/example/EnergyMeters/Source/list.c =================================================================== --- /webserver/example/EnergyMeters/Source/list.c (revision 14) +++ /webserver/example/EnergyMeters/Source/list.c (revision 14) @@ -0,0 +1,185 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +#include +#include "FreeRTOS.h" +#include "list.h" + +/*----------------------------------------------------------- + * PUBLIC LIST API documented in list.h + *----------------------------------------------------------*/ + +void vListInitialise( xList *pxList ) +{ + /* The list structure contains a list item which is used to mark the + end of the list. To initialise the list the list end is inserted + as the only list entry. */ + pxList->pxIndex = ( xListItem * ) &( pxList->xListEnd ); + + /* The list end value is the highest possible value in the list to + ensure it remains at the end of the list. */ + pxList->xListEnd.xItemValue = portMAX_DELAY; + + /* The list end next and previous pointers point to itself so we know + when the list is empty. */ + pxList->xListEnd.pxNext = ( xListItem * ) &( pxList->xListEnd ); + pxList->xListEnd.pxPrevious = ( xListItem * ) &( pxList->xListEnd ); + + pxList->uxNumberOfItems = 0; +} +/*-----------------------------------------------------------*/ + +void vListInitialiseItem( xListItem *pxItem ) +{ + /* Make sure the list item is not recorded as being on a list. */ + pxItem->pvContainer = NULL; +} +/*-----------------------------------------------------------*/ + +void vListInsertEnd( xList *pxList, xListItem *pxNewListItem ) +{ +volatile xListItem * pxIndex; + + /* Insert a new list item into pxList, but rather than sort the list, + makes the new list item the last item to be removed by a call to + pvListGetOwnerOfNextEntry. This means it has to be the item pointed to by + the pxIndex member. */ + pxIndex = pxList->pxIndex; + + pxNewListItem->pxNext = pxIndex->pxNext; + pxNewListItem->pxPrevious = pxList->pxIndex; + pxIndex->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; + pxIndex->pxNext = ( volatile xListItem * ) pxNewListItem; + pxList->pxIndex = ( volatile xListItem * ) pxNewListItem; + + /* Remember which list the item is in. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListInsert( xList *pxList, xListItem *pxNewListItem ) +{ +volatile xListItem *pxIterator; +portTickType xValueOfInsertion; + + /* Insert the new list item into the list, sorted in ulListItem order. */ + xValueOfInsertion = pxNewListItem->xItemValue; + + /* If the list already contains a list item with the same item value then + the new list item should be placed after it. This ensures that TCB's which + are stored in ready lists (all of which have the same ulListItem value) + get an equal share of the CPU. However, if the xItemValue is the same as + the back marker the iteration loop below will not end. This means we need + to guard against this by checking the value first and modifying the + algorithm slightly if necessary. */ + if( xValueOfInsertion == portMAX_DELAY ) + { + pxIterator = pxList->xListEnd.pxPrevious; + } + else + { + /* *** NOTE *********************************************************** + If you find your application is crashing here then likely causes are: + 1) Stack overflow - + see http://www.freertos.org/Stacks-and-stack-overflow-checking.html + 2) Incorrect interrupt priority assignment, especially on Cortex M3 + parts where numerically high priority values denote low actual + interrupt priories, which can seem counter intuitive. See + configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html + 3) Calling an API function from within a critical section or when + the scheduler is suspended. + 4) Using a queue or semaphore before it has been initialised or + before the scheduler has been started (are interrupts firing + before vTaskStartScheduler() has been called?). + See http://www.freertos.org/FAQHelp.html for more tips. + **********************************************************************/ + + for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) + { + /* There is nothing to do here, we are just iterating to the + wanted insertion position. */ + } + } + + pxNewListItem->pxNext = pxIterator->pxNext; + pxNewListItem->pxNext->pxPrevious = ( volatile xListItem * ) pxNewListItem; + pxNewListItem->pxPrevious = pxIterator; + pxIterator->pxNext = ( volatile xListItem * ) pxNewListItem; + + /* Remember which list the item is in. This allows fast removal of the + item later. */ + pxNewListItem->pvContainer = ( void * ) pxList; + + ( pxList->uxNumberOfItems )++; +} +/*-----------------------------------------------------------*/ + +void vListRemove( xListItem *pxItemToRemove ) +{ +xList * pxList; + + pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; + pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; + + /* The list item knows which list it is in. Obtain the list from the list + item. */ + pxList = ( xList * ) pxItemToRemove->pvContainer; + + /* Make sure the index is left pointing to a valid item. */ + if( pxList->pxIndex == pxItemToRemove ) + { + pxList->pxIndex = pxItemToRemove->pxPrevious; + } + + pxItemToRemove->pvContainer = NULL; + ( pxList->uxNumberOfItems )--; +} +/*-----------------------------------------------------------*/ + Index: /webserver/example/EnergyMeters/License/license.txt =================================================================== --- /webserver/example/EnergyMeters/License/license.txt (revision 14) +++ /webserver/example/EnergyMeters/License/license.txt (revision 14) @@ -0,0 +1,856 @@ +The FreeRTOS.org source code is licensed by the modified GNU General Public +License (GPL) text provided below. The FreeRTOS download also includes +demo application source code, some of which is provided by third parties +AND IS LICENSED SEPARATELY FROM FREERTOS.ORG. + +For the avoidance of any doubt refer to the comment included at the top +of each source and header file for license and copyright information. + +This is a list of files for which Richard Barry is not the copyright owner +and are NOT COVERED BY THE GPL. + + +1) Various header files provided by silicon manufacturers and tool vendors + that define processor specific memory addresses and utility macros. + Permission has been granted by the various copyright holders for these + files to be included in the FreeRTOS download. Users must ensure license + conditions are adhered to for any use other than compilation of the + FreeRTOS demo application. + +2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels. + Users must ensure the open source license conditions stated at the top + of each uIP source file is understood and adhered to. + +3) The lwIP TCP/IP stack the copyright of which is held by the Swedish + Institute of Computer Science. Users must ensure the open source license + conditions stated at the top of each lwIP source file is understood and + adhered to. + +4) All files contained within the FreeRTOS\Demo\CORTEX_LM3S102_GCC\hw_include + and FreeRTOS\Demo\CORTEX_LM3S316_IAR\hw_include directories. The + copyright of these files is owned by Luminary Micro. Permission has been + granted by Luminary Micro for these files to be included in the FreeRTOS + download. Users must ensure the license conditions stated in the EULA.txt + file located in the same directories is understood and adhered at all + times for all files in those directories. + +5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code, + which are slightly modified versions of code provided by and copyright to + Tern Inc. + +Errors and omissions should be reported to Richard Barry, contact details for +whom can be obtained from http://www.FreeRTOS.org. + + + + + +The GPL license text follows. + +A special exception to the GPL is included to allow you to distribute a +combined work that includes FreeRTOS.org without being obliged to provide +the source code for any proprietary components. See the licensing section +of http://www.FreeRTOS.org for full details. The exception text is also +included at the bottom of this file. + +-------------------------------------------------------------------- + + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License** as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +---------------------------------------------------------------------------- + +GPL Exception + +EXCEPTION TEXT: +Clause 1 + +Linking FreeRTOS statically or dynamically with other modules is making a combined work based on FreeRTOS. Thus, the terms and conditions of the GNU General Public License cover the whole combination. + +As a special exception, the copyright holder of FreeRTOS gives you permission to link FreeRTOS with independent modules that communicate with FreeRTOS solely through the FreeRTOS API interface, regardless of the license terms of these independent modules, and to copy and distribute the resulting combined work under terms of your choice, provided that + +Every copy of the combined work is accompanied by a written statement that details to the recipient the version of FreeRTOS used and an offer by yourself to provide the FreeRTOS source code should the recipient request it. +The combined work is not itself an RTOS, scheduler, kernel or related product. +The combined work is not itself a library intended for linking into other software applications. +Any FreeRTOS source code, whether modified or in it's original release form, or whether in whole or in part, can only be distributed by you under the terms of the GNU General Public License plus this exception. An independent module is a module which is not derived from or based on FreeRTOS. +Note that people who make modified versions of FreeRTOS are not obligated to grant this special exception for their modified versions; it is their choice whether to do so. The GNU General Public License gives permission to release a modified version without this exception; this exception also makes it possible to release a modified version which carries forward this exception. + +Clause 2 + +FreeRTOS.org may not be used for any competitive or comparative purpose, including the publication of any form of run time or compile time metric, without the express permission of Richard Barry (this is the norm within the industry and is intended to ensure information accuracy). +The FreeRTOS.org source code is licensed by the modified GNU General Public +License (GPL) text provided below. The FreeRTOS download also includes +demo application source code, some of which is provided by third parties +AND IS LICENSED SEPARATELY FROM FREERTOS.ORG. + +For the avoidance of any doubt refer to the comment included at the top +of each source and header file for license and copyright information. + +This is a list of files for which Richard Barry is not the copyright owner +and are NOT COVERED BY THE GPL. + + +1) Various header files provided by silicon manufacturers and tool vendors + that define processor specific memory addresses and utility macros. + Permission has been granted by the various copyright holders for these + files to be included in the FreeRTOS download. Users must ensure license + conditions are adhered to for any use other than compilation of the + FreeRTOS demo application. + +2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels. + Users must ensure the open source license conditions stated at the top + of each uIP source file is understood and adhered to. + +3) The lwIP TCP/IP stack the copyright of which is held by the Swedish + Institute of Computer Science. Users must ensure the open source license + conditions stated at the top of each lwIP source file is understood and + adhered to. + +4) All files contained within the FreeRTOS\Demo\CORTEX_LM3S102_GCC\hw_include + and FreeRTOS\Demo\CORTEX_LM3S316_IAR\hw_include directories. The + copyright of these files is owned by Luminary Micro. Permission has been + granted by Luminary Micro for these files to be included in the FreeRTOS + download. Users must ensure the license conditions stated in the EULA.txt + file located in the same directories is understood and adhered at all + times for all files in those directories. + +5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code, + which are slightly modified versions of code provided by and copyright to + Tern Inc. + +Errors and omissions should be reported to Richard Barry, contact details for +whom can be obtained from http://www.FreeRTOS.org. + + + + + +The GPL license text follows. + +A special exception to the GPL is included to allow you to distribute a +combined work that includes FreeRTOS.org without being obliged to provide +the source code for any proprietary components. See the licensing section +of http://www.FreeRTOS.org for full details. The exception text is also +included at the bottom of this file. + +-------------------------------------------------------------------- + + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License** as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +---------------------------------------------------------------------------- + +The FreeRTOS GPL Exception Text: + +Any FreeRTOS source code, whether modified or in it's original release form, +or whether in whole or in part, can only be distributed by you under the terms +of the GNU General Public License plus this exception. An independent module is +a module which is not derived from or based on FreeRTOS. + +Clause 1: + +Linking FreeRTOS statically or dynamically with other modules is making a +combined work based on FreeRTOS. Thus, the terms and conditions of the GNU +General Public License cover the whole combination. + +As a special exception, the copyright holder of FreeRTOS gives you permission +to link FreeRTOS with independent modules that communicate with FreeRTOS +solely through the FreeRTOS API interface, regardless of the license terms of +these independent modules, and to copy and distribute the resulting combined +work under terms of your choice, provided that + + + Every copy of the combined work is accompanied by a written statement that + details to the recipient the version of FreeRTOS used and an offer by yourself + to provide the FreeRTOS source code should the recipient request it. + + + The combined work is not itself an RTOS, scheduler, kernel or related product. + + + The combined work is not itself a library intended for linking into other + software applications. + +Clause 2: + +FreeRTOS.org may not be used for any competitive or comparative purpose, including +the publication of any form of run time or compile time metric, without the express +permission of Richard Barry (this is the norm within the industry and is intended +to ensure information accuracy). Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.c (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.c (revision 17) @@ -0,0 +1,392 @@ +/***************************************************************************** + * + * Project : lwIP Web + * Subproject : + * Name : portlcd.c + * Function : Routines for LCD + * Designer : K. Sterckx + * Creation date : 22/01/2007 + * Compiler : GNU ARM + * Processor : LPC2368 + * Last update : + * Last updated by : + * History : + * based on example code from NXP + * + ************************************************************************ + * + * This code is used to place text on the LCD. + * + ************************************************************************/ + +#include +#include "portlcd.h" +#include "FreeRTOS.h" +#include "task.h" + +/* Please note, on old MCB2300 board, the LCD_E bit is p1.30, on the new board +it's p1.31, please check the schematic carefully, and change LCD_CTRL and LCD_E +accordingly if you have a different board. */ + +/* LCD IO definitions */ +#define LCD_E 0x80000000 /* Enable control pin */ +#define LCD_RW 0x20000000 /* Read/Write control pin */ +#define LCD_RS 0x10000000 /* Data/Instruction control */ +#define LCD_CTRL 0xB0000000 /* Control lines mask */ +#define LCD_DATA 0x0F000000 /* Data lines mask */ + +/* Local variables */ +static unsigned int lcd_ptr; + +/* 8 user defined characters to be loaded into CGRAM (used for bargraph) */ +static const unsigned char UserFont[8][8] = { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 }, + { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 }, + { 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C }, + { 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E }, + { 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } +}; + +/* Local Function Prototypes */ +static void lcd_write( unsigned int c ); +static void lcd_write_4bit( unsigned int c ); +static unsigned int lcd_read_stat( void ); +static void lcd_write_cmd( unsigned int c ); +static void lcd_write_data( unsigned int d ); +static void lcd_wait_busy( void ); + + +/****************************************************************************** +** Function name: lcd_write_4bit +** +** Descriptions: +** +** parameters: four bits to write +** Returned value: None +** +******************************************************************************/ +static void lcd_write_4bit(unsigned int c) +{ + /* Write a 4-bit command to LCD controller. */ + FIO1DIR |= LCD_DATA | LCD_CTRL; + FIO1CLR = LCD_RW | LCD_DATA; + FIO1SET = (c & 0xF) << 24; + FIO1SET = LCD_E; + vTaskDelay(0); + FIO1CLR = LCD_E; + vTaskDelay(0); + return; +} + +/****************************************************************************** +** Function name: lcd_write +** +** Descriptions: +** +** parameters: word to write +** Returned value: None +** +******************************************************************************/ +static void lcd_write(unsigned int c) +{ + /* Write data/command to LCD controller. */ + lcd_write_4bit (c >> 4); + lcd_write_4bit (c); + return; +} + +/****************************************************************************** +** Function name: lcd_read_stat +** +** Descriptions: +** +** parameters: None +** Returned value: status +** +******************************************************************************/ +static unsigned int lcd_read_stat(void) +{ + /* Read status of LCD controller (ST7066) */ + unsigned int stat; + + FIO1DIR &= ~LCD_DATA; + FIO1CLR = LCD_RS; + FIO1SET = LCD_RW; + vTaskDelay( 0 ); + FIO1SET = LCD_E; + vTaskDelay( 0 ); + stat = (FIO1PIN >> 20) & 0xF0; + FIO1CLR = LCD_E; + vTaskDelay( 0 ); + FIO1SET = LCD_E; + vTaskDelay( 0 ); + stat |= (FIO1PIN >> 24) & 0xF; + FIO1CLR = LCD_E; + return (stat); +} + +/****************************************************************************** +** Function name: lcd_wait_busy +** +** Descriptions: +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +static void lcd_wait_busy(void) +{ + /* Wait until LCD controller (ST7066) is busy. */ + unsigned int stat; + + do + { + stat = lcd_read_stat(); + } + while (stat & 0x80); /* Wait for busy flag */ + + return; +} + +/****************************************************************************** +** Function name: lcd_write_cmd +** +** Descriptions: +** +** parameters: command word +** Returned value: None +** +******************************************************************************/ +static void lcd_write_cmd(unsigned int c) +{ + /* Write command to LCD controller. */ + lcd_wait_busy(); + FIO1CLR = LCD_RS; + lcd_write(c); + return; +} + +/****************************************************************************** +** Function name: lcd_write_data +** +** Descriptions: +** +** parameters: data word +** Returned value: None +** +******************************************************************************/ +static void lcd_write_data(unsigned int d) +{ + /* Write data to LCD controller. */ + lcd_wait_busy(); + FIO1SET = LCD_RS; + lcd_write(d); + return; +} + +/****************************************************************************** +** Function name: LCD_init +** +** Descriptions: +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void LCD_init(void) +{ + /* Initialize the ST7066 LCD controller to 4-bit mode. */ + PINSEL3 = 0x00000000; +#if USE_FIO + SCS |= 0x00000001;/* set GPIOx to use Fast I/O */ +#endif + FIO1DIR |= LCD_CTRL | LCD_DATA; + FIO1CLR = LCD_RW | LCD_RS | LCD_DATA; + + lcd_write_4bit(0x3); /* Select 4-bit interface */ + vTaskDelay(100); + lcd_write_4bit(0x3); + vTaskDelay(100); + lcd_write_4bit(0x3); + lcd_write_4bit(0x2); + + lcd_write_cmd(0x28); /* 2 lines, 5x8 character matrix */ + lcd_write_cmd(0x0e); /* Display ctrl:Disp/Curs/Blnk=ON */ + lcd_write_cmd(0x06); /* Entry mode: Move right, no shift */ + + LCD_load( (unsigned char *)&UserFont, sizeof (UserFont) ); + LCD_cls(); + return; +} + +/****************************************************************************** +** Function name: LCD_load +** +** Descriptions: +** +** parameters: pointer to the buffer and counter +** Returned value: None +** +******************************************************************************/ +void LCD_load(unsigned char *fp, unsigned int cnt) +{ + /* Load user-specific characters into CGRAM */ + unsigned int i; + + lcd_write_cmd( 0x40 ); /* Set CGRAM address counter to 0 */ + for (i = 0; i < cnt; i++, fp++) + { + lcd_write_data( *fp ); + } + return; +} + +/****************************************************************************** +** Function name: LCD_gotoxy +** +** Descriptions: +** +** parameters: pixel X and Y +** Returned value: None +** +******************************************************************************/ +void LCD_gotoxy(unsigned int x, unsigned int y) +{ + /* Set cursor position on LCD display. Left corner: 1,1, right: 16,2 */ + unsigned int c; + + c = --x; + if (--y) + { + c |= 0x40; + } + lcd_write_cmd (c | 0x80); + lcd_ptr = y*16 + x; + return; +} + +/****************************************************************************** +** Function name: LCD_cls +** +** Descriptions: +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void LCD_cls(void) +{ + /* Clear LCD display, move cursor to home position. */ + lcd_write_cmd (0x01); + LCD_gotoxy (1,1); + return; +} + +/****************************************************************************** +** Function name: LCD_cur_off +** +** Descriptions: +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void LCD_cur_off(void) +{ + /* Switch off LCD cursor. */ + lcd_write_cmd(0x0c); + return; +} + + +/****************************************************************************** +** Function name: LCD_on +** +** Descriptions: +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void LCD_on(void) +{ + /* Switch on LCD and enable cursor. */ + lcd_write_cmd (0x0e); + return; +} + +/****************************************************************************** +** Function name: LCD_putc +** +** Descriptions: +** +** parameters: unsigned char character +** Returned value: None +** +******************************************************************************/ +void LCD_putc(unsigned char c) +{ + /* Print a character to LCD at current cursor position. */ + if (lcd_ptr == 16) + { + lcd_write_cmd (0xc0); + } + lcd_write_data(c); + lcd_ptr++; + return; +} + +/****************************************************************************** +** Function name: LCD_puts +** +** Descriptions: +** +** parameters: pointer to the buffer +** Returned value: None +** +******************************************************************************/ +void LCD_puts(unsigned char *sp) +{ + /* Print a string to LCD display. */ + while (*sp) + { + LCD_putc (*sp++); + } + return; +} + +/****************************************************************************** +** Function name: LCD_bargraph +** +** Descriptions: +** +** parameters: value and size +** Returned value: None +** +******************************************************************************/ +void LCD_bargraph(unsigned int val, unsigned int size) +{ + /* Print a bargraph to LCD display. */ + /* - val: value 0..100 % */ + /* - size: size of bargraph 1..16 */ + unsigned int i; + + val = val * size / 20; /* Display matrix 5 x 8 pixels */ + for (i = 0; i < size; i++) + { + if (val > 5) + { + LCD_putc(5); + val -= 5; + } + else + { + LCD_putc(val); + break; + } + } + return; +} Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/LCD/portlcd.h (revision 14) @@ -0,0 +1,31 @@ +/***************************************************************************** + * rtc.h: Header file for NXP LPC23xx/24xx Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.07.13 ver 1.00 Prelimnary version, first Release + * +******************************************************************************/ +#ifndef __PORTLCD_H +#define __PORTLCD_H + +extern void LCD_init(void); +extern void LCD_load(unsigned char *fp, unsigned int cnt); +extern void LCD_gotoxy(unsigned int x, unsigned int y); +extern void LCD_cls(void); +extern void LCD_cur_off(void); +extern void LCD_on(void); +extern void LCD_putc(unsigned char c); +extern void LCD_puts(unsigned char *sp); +extern void LCD_bargraph(unsigned int val, unsigned int size); + +extern void LCD_putnibble(unsigned char nibble); +extern void LCD_puthexbyte(unsigned char abyte); + + +#endif /* end __PORTLCD_H */ +/***************************************************************************** +** End Of File +******************************************************************************/ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/ParTest/ParTest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/ParTest/ParTest.c (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/ParTest/ParTest.c (revision 17) @@ -0,0 +1,172 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* FreeRTOS.org includes. */ +#include "FreeRTOS.h" + +/* Demo application includes. */ +#include "partest.h" + +#define partstFIRST_IO ( ( unsigned portLONG ) 0x01 ) +#define partstNUM_LEDS ( 2 ) +#define partstALL_OUTPUTS_OFF ( ( unsigned portLONG ) 0xff ) + +// Pin I/O LED Control Maskbit +#define LED1 0x02000000 // P3.25(0000 00x0 0000 0000 0000 0000 0000 0000) +#define LED2 0x04000000 // P3.26(0000 0x00 0000 0000 0000 0000 0000 0000) + +#define LED1_ON() FIO3CLR = LED1 // LED1 Pin = 0 (ON LED) +#define LED1_OFF() FIO3SET = LED1 // LED1 Pin = 1 (OFF LED) +#define LED2_ON() FIO3CLR = LED2 // LED2 Pin = 0 (ON LED) +#define LED2_OFF() FIO3SET = LED2 // LED2 Pin = 1 (OFF LED) + +int led_1_state; +int led_2_state; + + +/*----------------------------------------------------------- + * Simple parallel port IO routines. + *-----------------------------------------------------------*/ + +void vParTestInitialise( void ) +{ + + // Config Pin GPIO3[26:25] + PINSEL7 &= 0xFFC3FFFF; // P3[26:25] = GPIO Function(xxxx xxxx xx00 00xx xxxx xxxx xxxx xxxx) + PINMODE7 &= 0xFFC3FFFF; // Enable Puul-Up on P3[26:25] + + FIO3DIR |= LED1; // Set GPIO-3[26:25] = Output(xxxx x11x xxxx xxxx xxxx xxxx xxxx xxxx) + FIO3DIR |= LED2; + LED1_OFF(); // Default LED Status + LED2_OFF(); + +// PINSEL10 = 0; +// FIO2DIR = 0x000000FF; +// FIO2MASK = 0x00000000; +// FIO2CLR = 0xFF; +// SCS |= (1<<0); //fast mode for port 0 and 1 + +// FIO2CLR = partstALL_OUTPUTS_OFF; +} +/*-----------------------------------------------------------*/ + +void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ) +{ +unsigned portLONG ulLED = partstFIRST_IO; +#if 0 + if( uxLED < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port */ + ulLED <<= ( unsigned portLONG ) uxLED; + + /* Set of clear the output. */ + if( xValue ) + { + FIO2CLR = ulLED; + } + else + { + FIO2SET = ulLED; + } + } +#endif +} +/*-----------------------------------------------------------*/ + +void vParTestToggleLED( unsigned portBASE_TYPE uxLED ) +{ +unsigned portLONG ulLED = partstFIRST_IO, ulCurrentState; + + + if (led_1_state == 0) + { + LED1_ON(); + + led_1_state = 1; + } + else + { + LED1_OFF(); + led_1_state = 0; + } + + +#if 0 + if( uxLED < partstNUM_LEDS ) + { + /* Rotate to the wanted bit of port 0. Only P10 to P13 have an LED + attached. */ + ulLED <<= ( unsigned portLONG ) uxLED; + + /* If this bit is already set, clear it, and visa versa. */ + ulCurrentState = FIO2PIN; + if( ulCurrentState & ulLED ) + { + FIO2CLR = ulLED; + } + else + { + FIO2SET = ulLED; + } + } +#endif +} + +/*-----------------------------------------------------------*/ +unsigned portBASE_TYPE uxParTextGetLED( unsigned portBASE_TYPE uxLED ) +{ +#if 0 +unsigned portLONG ulLED = partstFIRST_IO; + + ulLED <<= ( unsigned portLONG ) uxLED; + + return ( FIO2PIN & ulLED ); +#endif + return 0; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.h (revision 14) @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fs.h,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ +#ifndef __HTTPD_FS_H__ +#define __HTTPD_FS_H__ + +#define HTTPD_FS_STATISTICS 1 + +struct httpd_fs_file { + char *data; + int len; +}; + +/* file must be allocated by caller and will be filled in + by the function. */ +int httpd_fs_open(const char *name, struct httpd_fs_file *file); + +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 +u16_t httpd_fs_count(char *name); +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ + +void httpd_fs_init(void); + +#endif /* __HTTPD_FS_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.c (revision 15) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.c (revision 15) @@ -0,0 +1,412 @@ +/****************************************************************** + ***** ***** + ***** Name: cs8900.c ***** + ***** Ver.: 1.0 ***** + ***** Date: 07/05/2001 ***** + ***** Auth: Andreas Dannenberg ***** + ***** HTWK Leipzig ***** + ***** university of applied sciences ***** + ***** Germany ***** + ***** Func: ethernet packet-driver for use with LAN- ***** + ***** controller CS8900 from Crystal/Cirrus Logic ***** + ***** ***** + ***** Keil: Module modified for use with Philips ***** + ***** LPC2378 EMAC Ethernet controller ***** + ***** ***** + ******************************************************************/ + +/* Adapted from file originally written by Andreas Dannenberg. Supplied with permission. */ + +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" +#include "emac.h" + +/* The semaphore used to wake the uIP task when data arives. */ +xSemaphoreHandle xEMACSemaphore = NULL; + +static unsigned short *rptr; +static unsigned short *tptr; + +// easyWEB internal function +// help function to swap the byte order of a WORD + +static unsigned short SwapBytes(unsigned short Data) +{ + return (Data >> 8) | (Data << 8); +} + +// Keil: function added to write PHY +void write_PHY (int PhyReg, int Value) +{ + unsigned int tout; + + MAC_MADR = DP83848C_DEF_ADR | PhyReg; + MAC_MWTD = Value; + + /* Wait utill operation completed */ + tout = 0; + for (tout = 0; tout < MII_WR_TOUT; tout++) { + if ((MAC_MIND & MIND_BUSY) == 0) { + break; + } + } +} + + +// Keil: function added to read PHY +unsigned short read_PHY (unsigned char PhyReg) +{ + unsigned int tout; + + MAC_MADR = DP83848C_DEF_ADR | PhyReg; + MAC_MCMD = MCMD_READ; + + /* Wait until operation completed */ + tout = 0; + for (tout = 0; tout < MII_RD_TOUT; tout++) { + if ((MAC_MIND & MIND_BUSY) == 0) { + break; + } + } + MAC_MCMD = 0; + return (MAC_MRDD); +} + + +// Keil: function added to initialize Rx Descriptors +void rx_descr_init (void) +{ + unsigned int i; + + for (i = 0; i < NUM_RX_FRAG; i++) { + RX_DESC_PACKET(i) = RX_BUF(i); + RX_DESC_CTRL(i) = RCTRL_INT | (ETH_FRAG_SIZE-1); + RX_STAT_INFO(i) = 0; + RX_STAT_HASHCRC(i) = 0; + } + + /* Set EMAC Receive Descriptor Registers. */ + MAC_RXDESCRIPTOR = RX_DESC_BASE; + MAC_RXSTATUS = RX_STAT_BASE; + MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1; + + /* Rx Descriptors Point to 0 */ + MAC_RXCONSUMEINDEX = 0; +} + + +// Keil: function added to initialize Tx Descriptors +void tx_descr_init (void) { + unsigned int i; + + for (i = 0; i < NUM_TX_FRAG; i++) { + TX_DESC_PACKET(i) = TX_BUF(i); + TX_DESC_CTRL(i) = 0; + TX_STAT_INFO(i) = 0; + } + + /* Set EMAC Transmit Descriptor Registers. */ + MAC_TXDESCRIPTOR = TX_DESC_BASE; + MAC_TXSTATUS = TX_STAT_BASE; + MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1; + + /* Tx Descriptors Point to 0 */ + MAC_TXPRODUCEINDEX = 0; +} + + +// configure port-pins for use with LAN-controller, +// reset it and send the configuration-sequence + +portBASE_TYPE Init_EMAC(void) +{ +portBASE_TYPE xReturn = pdPASS; +static portBASE_TYPE xAttempt = 0; +// Keil: function modified to access the EMAC +// Initializes the EMAC ethernet controller + volatile unsigned int regv,tout,id1,id2; + + /* Enable P1 Ethernet Pins. */ + PINSEL2 = configPINSEL2_VALUE; + PINSEL3 = (PINSEL3 & ~0x0000000F) | 0x00000005; + + /* Power Up the EMAC controller. */ + PCONP |= 0x40000000; + vTaskDelay( 10 ); + + /* Reset all EMAC internal modules. */ + MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | + MAC1_SIM_RES | MAC1_SOFT_RES; + MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES; + + /* A short delay after reset. */ + vTaskDelay( 10 ); + + /* Initialize MAC control registers. */ + MAC_MAC1 = MAC1_PASS_ALL; + MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; + MAC_MAXF = ETH_MAX_FLEN; + MAC_CLRT = CLRT_DEF; + MAC_IPGR = IPGR_DEF; + + /* Enable Reduced MII interface. */ + MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM; + + /* Reset Reduced MII Logic. */ + MAC_SUPP = SUPP_RES_RMII; + MAC_SUPP = 0; + + /* Put the DP83848C in reset mode */ + write_PHY (PHY_REG_BMCR, 0x8000); + write_PHY (PHY_REG_BMCR, 0x8000); + + /* Wait for hardware reset to end. */ + for (tout = 0; tout < 100; tout++) { + vTaskDelay( 200 ); + regv = read_PHY (PHY_REG_BMCR); + if (!(regv & 0x8000)) { + /* Reset complete */ + break; + } + } + + /* Check if this is a DP83848C PHY. */ + id1 = read_PHY (PHY_REG_IDR1); + id2 = read_PHY (PHY_REG_IDR2); + if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) { + /* Configure the PHY device */ + + /* Use autonegotiation about the link speed. */ + write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG); + /* Wait to complete Auto_Negotiation. */ + for (tout = 0; tout < 10; tout++) { + vTaskDelay( 200 ); + regv = read_PHY (PHY_REG_BMSR); + if (regv & 0x0020) { + /* Autonegotiation Complete. */ + break; + } + } + } + else + { + xReturn = pdFAIL; + } + + /* Check the link status. */ + if( xReturn == pdPASS ) + { + xReturn = pdFAIL; + for (tout = 0; tout < 10; tout++) { + vTaskDelay( 200 ); + regv = read_PHY (PHY_REG_STS); + if (regv & 0x0001) { + /* Link is on. */ + xReturn = pdPASS; + break; + } + } + } + + if( xReturn == pdPASS ) + { + /* Configure Full/Half Duplex mode. */ + if (regv & 0x0004) { + /* Full duplex is enabled. */ + MAC_MAC2 |= MAC2_FULL_DUP; + MAC_COMMAND |= CR_FULL_DUP; + MAC_IPGT = IPGT_FULL_DUP; + } + else { + /* Half duplex mode. */ + MAC_IPGT = IPGT_HALF_DUP; + } + + /* Configure 100MBit/10MBit mode. */ + if (regv & 0x0002) { + /* 10MBit mode. */ + MAC_SUPP = 0; + } + else { + /* 100MBit mode. */ + MAC_SUPP = SUPP_SPEED; + } + + /* Set the Ethernet MAC Address registers */ + MAC_SA0 = (emacETHADDR0 << 8) | emacETHADDR1; + MAC_SA1 = (emacETHADDR2 << 8) | emacETHADDR3; + MAC_SA2 = (emacETHADDR4 << 8) | emacETHADDR5; + + /* Initialize Tx and Rx DMA Descriptors */ + rx_descr_init (); + tx_descr_init (); + + /* Receive Broadcast and Perfect Match Packets */ + MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; + + /* Create the semaphore used ot wake the uIP task. */ + vSemaphoreCreateBinary( xEMACSemaphore ); + + /* Reset all interrupts */ + MAC_INTCLEAR = 0xFFFF; + + /* Enable receive and transmit mode of MAC Ethernet core */ + MAC_COMMAND |= (CR_RX_EN | CR_TX_EN); + MAC_MAC1 |= MAC1_REC_EN; + } + + return xReturn; +} + + +// reads a word in little-endian byte order from RX_BUFFER + +unsigned short ReadFrame_EMAC(void) +{ + return (*rptr++); +} + +// reads a word in big-endian byte order from RX_FRAME_PORT +// (useful to avoid permanent byte-swapping while reading +// TCP/IP-data) + +unsigned short ReadFrameBE_EMAC(void) +{ + unsigned short ReturnValue; + + ReturnValue = SwapBytes (*rptr++); + return (ReturnValue); +} + + +// copies bytes from frame port to MCU-memory +// NOTES: * an odd number of byte may only be transfered +// if the frame is read to the end! +// * MCU-memory MUST start at word-boundary + +void CopyFromFrame_EMAC(void *Dest, unsigned short Size) +{ + unsigned short * piDest; // Keil: Pointer added to correct expression + + piDest = Dest; // Keil: Line added + while (Size > 1) { + *piDest++ = ReadFrame_EMAC(); + Size -= 2; + } + + if (Size) { // check for leftover byte... + *(unsigned char *)piDest = (char)ReadFrame_EMAC();// the LAN-Controller will return 0 + } // for the highbyte +} + +// does a dummy read on frame-I/O-port +// NOTE: only an even number of bytes is read! + +void DummyReadFrame_EMAC(unsigned short Size) // discards an EVEN number of bytes +{ // from RX-fifo + while (Size > 1) { + ReadFrame_EMAC(); + Size -= 2; + } +} + +// Reads the length of the received ethernet frame and checks if the +// destination address is a broadcast message or not +// returns the frame length +unsigned short StartReadFrame(void) { + unsigned short RxLen; + unsigned int idx; + + idx = MAC_RXCONSUMEINDEX; + RxLen = (RX_STAT_INFO(idx) & RINFO_SIZE) - 3; + rptr = (unsigned short *)RX_DESC_PACKET(idx); + return(RxLen); +} + +void EndReadFrame(void) { + unsigned int idx; + + /* DMA free packet. */ + idx = MAC_RXCONSUMEINDEX; + + if (++idx == NUM_RX_FRAG) + idx = 0; + + MAC_RXCONSUMEINDEX = idx; +} + +unsigned int CheckFrameReceived(void) { // Packet received ? + + if (MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX) // more packets received ? + return(1); + else + return(0); +} + +unsigned int uiGetEMACRxData( unsigned char *ucBuffer ) +{ +unsigned int uiLen = 0; + + if( MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX ) + { + uiLen = StartReadFrame(); + CopyFromFrame_EMAC( ucBuffer, uiLen ); + EndReadFrame(); + } + + return uiLen; +} + +// requests space in EMAC memory for storing an outgoing frame + +void RequestSend(void) +{ + unsigned int idx; + + idx = MAC_TXPRODUCEINDEX; + tptr = (unsigned short *)TX_DESC_PACKET(idx); +} + +// check if ethernet controller is ready to accept the +// frame we want to send + +unsigned int Rdy4Tx(void) +{ + return (1); // the ethernet controller transmits much faster +} // than the CPU can load its buffers + + +// writes a word in little-endian byte order to TX_BUFFER +void WriteFrame_EMAC(unsigned short Data) +{ + *tptr++ = Data; +} + +// copies bytes from MCU-memory to frame port +// NOTES: * an odd number of byte may only be transfered +// if the frame is written to the end! +// * MCU-memory MUST start at word-boundary + +void CopyToFrame_EMAC(void *Source, unsigned int Size) +{ + unsigned short * piSource; + + piSource = Source; + Size = (Size + 1) & 0xFFFE; // round Size up to next even number + while (Size > 0) { + WriteFrame_EMAC(*piSource++); + Size -= 2; + } +} + +void DoSend_EMAC(unsigned short FrameSize) +{ + unsigned int idx; + + idx = MAC_TXPRODUCEINDEX; + TX_DESC_CTRL(idx) = FrameSize | TCTRL_LAST; + if (++idx == NUM_TX_FRAG) idx = 0; + MAC_TXPRODUCEINDEX = idx; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makestrings =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makestrings (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makestrings (revision 14) @@ -0,0 +1,40 @@ +#!/usr/bin/perl + + +sub stringify { + my $name = shift(@_); + open(OUTPUTC, "> $name.c"); + open(OUTPUTH, "> $name.h"); + + open(FILE, "$name"); + + while() { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + $datan = $data; + $datan =~ s/\\r/\r/g; + $datan =~ s/\\n/\n/g; + $datan =~ s/\\01/\01/g; + $datan =~ s/\\0/\0/g; + + printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1); + printf(OUTPUTC "/* \"$data\" */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($datan); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1); + + } + } + close(OUTPUTC); + close(OUTPUTH); +} +stringify("http-strings"); + +exit 0; + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.c (revision 14) @@ -0,0 +1,102 @@ +const char http_http[8] = +/* "http://" */ +{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, }; +const char http_200[5] = +/* "200 " */ +{0x32, 0x30, 0x30, 0x20, }; +const char http_301[5] = +/* "301 " */ +{0x33, 0x30, 0x31, 0x20, }; +const char http_302[5] = +/* "302 " */ +{0x33, 0x30, 0x32, 0x20, }; +const char http_get[5] = +/* "GET " */ +{0x47, 0x45, 0x54, 0x20, }; +const char http_10[9] = +/* "HTTP/1.0" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, }; +const char http_11[9] = +/* "HTTP/1.1" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, }; +const char http_content_type[15] = +/* "content-type: " */ +{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, }; +const char http_texthtml[10] = +/* "text/html" */ +{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_location[11] = +/* "location: " */ +{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, }; +const char http_host[7] = +/* "host: " */ +{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, }; +const char http_crnl[3] = +/* "\r\n" */ +{0xd, 0xa, }; +const char http_index_html[12] = +/* "/index.html" */ +{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_404_html[10] = +/* "/404.html" */ +{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_referer[9] = +/* "Referer:" */ +{0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x3a, }; +const char http_header_200[84] = +/* "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_header_404[91] = +/* "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_content_type_plain[29] = +/* "Content-type: text/plain\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_html[28] = +/* "Content-type: text/html\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_css [27] = +/* "Content-type: text/css\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_text[28] = +/* "Content-type: text/text\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_png [28] = +/* "Content-type: image/png\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_gif [28] = +/* "Content-type: image/gif\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_jpg [29] = +/* "Content-type: image/jpeg\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_binary[43] = +/* "Content-type: application/octet-stream\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, }; +const char http_html[6] = +/* ".html" */ +{0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_shtml[7] = +/* ".shtml" */ +{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_htm[5] = +/* ".htm" */ +{0x2e, 0x68, 0x74, 0x6d, }; +const char http_css[5] = +/* ".css" */ +{0x2e, 0x63, 0x73, 0x73, }; +const char http_png[5] = +/* ".png" */ +{0x2e, 0x70, 0x6e, 0x67, }; +const char http_gif[5] = +/* ".gif" */ +{0x2e, 0x67, 0x69, 0x66, }; +const char http_jpg[5] = +/* ".jpg" */ +{0x2e, 0x6a, 0x70, 0x67, }; +const char http_text[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; +const char http_txt[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/stats.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/stats.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/stats.shtml (revision 14) @@ -0,0 +1,41 @@ + + + + FreeRTOS.org uIP WEB server demo + + + +RTOS Stats | TCP Stats | Connections | FreeRTOS.org Homepage | IO +

+


+

+

Network statistics

+ +
+IP           Packets dropped
+             Packets received
+             Packets sent
+IP errors    IP version/header length
+             IP length, high byte
+             IP length, low byte
+             IP fragments
+             Header checksum
+             Wrong protocol
+ICMP	     Packets dropped
+             Packets received
+             Packets sent
+             Type errors
+TCP          Packets dropped
+             Packets received
+             Packets sent
+             Checksum errors
+             Data packets without ACKs
+             Resets
+             Retransmissions
+	     No connection avaliable
+	     Connection attempts to closed ports
+
%! net-stats
+
+
+ + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/404.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/404.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/404.html (revision 14) @@ -0,0 +1,8 @@ + + +
+

404 - file not found

+

Go here instead.

+
+ + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.html (revision 14) @@ -0,0 +1,13 @@ + + + + FreeRTOS.org uIP WEB server demo + + + +Loading index.shtml. Click here if not automatically redirected. + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/tcp.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/tcp.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/tcp.shtml (revision 14) @@ -0,0 +1,22 @@ + + + + FreeRTOS.org uIP WEB server demo + + + +RTOS Stats | 65K JPG | Connections | IO +

+


+
+

Network connections

+This page displays dynamically generated status information on the TCP/IP connections. +

+ + +%! tcp-connections + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/index.shtml (revision 14) @@ -0,0 +1,20 @@ + + + + FreeRTOS.org uIP WEB server demo + + + +RTOS Stats | 65K JPG | Connections | IO +

+


+

+

Task statistics

+This page shows dynamically generated task state information. The page will refresh evey 2 seconds.

+

Task          State  Priority  Stack	#
************************************************
+%! rtos-stats +
+
+ + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/io.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/io.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs/io.shtml (revision 14) @@ -0,0 +1,28 @@ + + + + FreeRTOS.org uIP WEB server demo + + + +RTOS Stats | 65K JPG | Connections | IO +

+


+LED and LCD IO
+ +

+This page demonstrates two way communication. By using the check boxes and text boxes this WEB interface can influence the program execution.

+Use the check boxes to select the LED's to turn on or off, enter text to display on the LCD, then click "Update IO". + + +

+
+%! led-io +

+ + +

+ + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/webserver.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/webserver.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/webserver.h (revision 14) @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: webserver.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ +#ifndef __WEBSERVER_H__ +#define __WEBSERVER_H__ + +#include "httpd.h" + +typedef struct httpd_state uip_tcp_appstate_t; +/* UIP_APPCALL: the name of the application function. This function + must return void and take no arguments (i.e., C type "void + appfunc(void)"). */ +#ifndef UIP_APPCALL +#define UIP_APPCALL httpd_appcall +#endif + + +#endif /* __WEBSERVER_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/emac.h (revision 14) @@ -0,0 +1,322 @@ +/*---------------------------------------------------------------------------- + * LPC2378 Ethernet Definitions + *---------------------------------------------------------------------------- + * Name: EMAC.H + * Purpose: Philips LPC2378 EMAC hardware definitions + *---------------------------------------------------------------------------- + * Copyright (c) 2006 KEIL - An ARM Company. All rights reserved. + *---------------------------------------------------------------------------*/ +#ifndef __EMAC_H +#define __EMAC_H + +/* MAC address definition. The MAC address must be unique on the network. */ +#define emacETHADDR0 0 +#define emacETHADDR1 0xbd +#define emacETHADDR2 0x33 +#define emacETHADDR3 0x02 +#define emacETHADDR4 0x64 +#define emacETHADDR5 0x24 + + +/* EMAC Memory Buffer configuration for 16K Ethernet RAM. */ +#define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */ +#define NUM_TX_FRAG 2 /* Num.of TX Fragments 2*1536= 3.0kB */ +#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */ + +#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */ + +/* EMAC variables located in 16K Ethernet SRAM */ +#define RX_DESC_BASE 0x7FE00000 +#define RX_STAT_BASE (RX_DESC_BASE + NUM_RX_FRAG*8) +#define TX_DESC_BASE (RX_STAT_BASE + NUM_RX_FRAG*8) +#define TX_STAT_BASE (TX_DESC_BASE + NUM_TX_FRAG*8) +#define RX_BUF_BASE (TX_STAT_BASE + NUM_TX_FRAG*4) +#define TX_BUF_BASE (RX_BUF_BASE + NUM_RX_FRAG*ETH_FRAG_SIZE) + +/* RX and TX descriptor and status definitions. */ +#define RX_DESC_PACKET(i) (*(unsigned int *)(RX_DESC_BASE + 8*i)) +#define RX_DESC_CTRL(i) (*(unsigned int *)(RX_DESC_BASE+4 + 8*i)) +#define RX_STAT_INFO(i) (*(unsigned int *)(RX_STAT_BASE + 8*i)) +#define RX_STAT_HASHCRC(i) (*(unsigned int *)(RX_STAT_BASE+4 + 8*i)) +#define TX_DESC_PACKET(i) (*(unsigned int *)(TX_DESC_BASE + 8*i)) +#define TX_DESC_CTRL(i) (*(unsigned int *)(TX_DESC_BASE+4 + 8*i)) +#define TX_STAT_INFO(i) (*(unsigned int *)(TX_STAT_BASE + 4*i)) +#define RX_BUF(i) (RX_BUF_BASE + ETH_FRAG_SIZE*i) +#define TX_BUF(i) (TX_BUF_BASE + ETH_FRAG_SIZE*i) + +/* MAC Configuration Register 1 */ +#define MAC1_REC_EN 0x00000001 /* Receive Enable */ +#define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */ +#define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */ +#define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */ +#define MAC1_LOOPB 0x00000010 /* Loop Back Mode */ +#define MAC1_RES_TX 0x00000100 /* Reset TX Logic */ +#define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */ +#define MAC1_RES_RX 0x00000400 /* Reset RX Logic */ +#define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */ +#define MAC1_SIM_RES 0x00004000 /* Simulation Reset */ +#define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */ + +/* MAC Configuration Register 2 */ +#define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */ +#define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */ +#define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */ +#define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */ +#define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */ +#define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */ +#define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */ +#define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */ +#define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */ +#define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */ +#undef MAC2_NO_BACKOFF /* Remove compiler warning. */ +#define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */ +#define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */ +#define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */ + +/* Back-to-Back Inter-Packet-Gap Register */ +#define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */ +#define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */ + +/* Non Back-to-Back Inter-Packet-Gap Register */ +#define IPGR_DEF 0x00000012 /* Recommended value */ + +/* Collision Window/Retry Register */ +#define CLRT_DEF 0x0000370F /* Default value */ + +/* PHY Support Register */ +#undef SUPP_SPEED /* Remove compiler warning. */ +#define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */ +#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */ + +/* Test Register */ +#define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */ +#define TEST_TST_PAUSE 0x00000002 /* Test Pause */ +#define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */ + +/* MII Management Configuration Register */ +#define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */ +#define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */ +#define MCFG_CLK_SEL 0x0000001C /* Clock Select Mask */ +#define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */ + +/* MII Management Command Register */ +#undef MCMD_READ /* Remove compiler warning. */ +#define MCMD_READ 0x00000001 /* MII Read */ +#undef MCMD_SCAN /* Remove compiler warning. */ +#define MCMD_SCAN 0x00000002 /* MII Scan continuously */ + +#define MII_WR_TOUT 0x00050000 /* MII Write timeout count */ +#define MII_RD_TOUT 0x00050000 /* MII Read timeout count */ + +/* MII Management Address Register */ +#define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */ +#define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */ + +/* MII Management Indicators Register */ +#undef MIND_BUSY /* Remove compiler warning. */ +#define MIND_BUSY 0x00000001 /* MII is Busy */ +#define MIND_SCAN 0x00000002 /* MII Scanning in Progress */ +#define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */ +#define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */ + +/* Command Register */ +#define CR_RX_EN 0x00000001 /* Enable Receive */ +#define CR_TX_EN 0x00000002 /* Enable Transmit */ +#define CR_REG_RES 0x00000008 /* Reset Host Registers */ +#define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */ +#define CR_RX_RES 0x00000020 /* Reset Receive Datapath */ +#define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */ +#define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */ +#define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */ +#define CR_RMII 0x00000200 /* Reduced MII Interface */ +#define CR_FULL_DUP 0x00000400 /* Full Duplex */ + +/* Status Register */ +#define SR_RX_EN 0x00000001 /* Enable Receive */ +#define SR_TX_EN 0x00000002 /* Enable Transmit */ + +/* Transmit Status Vector 0 Register */ +#define TSV0_CRC_ERR 0x00000001 /* CRC error */ +#define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */ +#define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */ +#define TSV0_DONE 0x00000008 /* Tramsmission Completed */ +#define TSV0_MCAST 0x00000010 /* Multicast Destination */ +#define TSV0_BCAST 0x00000020 /* Broadcast Destination */ +#define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */ +#define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */ +#define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */ +#define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */ +#define TSV0_GIANT 0x00000400 /* Giant Frame */ +#define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */ +#define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */ +#define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */ +#define TSV0_PAUSE 0x20000000 /* Pause Frame */ +#define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */ +#define TSV0_VLAN 0x80000000 /* VLAN Frame */ + +/* Transmit Status Vector 1 Register */ +#define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */ +#define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */ + +/* Receive Status Vector Register */ +#define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */ +#define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */ +#define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */ +#define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */ +#define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */ +#define RSV_CRC_ERR 0x00100000 /* CRC Error */ +#define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */ +#define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */ +#define RSV_REC_OK 0x00800000 /* Frame Received OK */ +#define RSV_MCAST 0x01000000 /* Multicast Frame */ +#define RSV_BCAST 0x02000000 /* Broadcast Frame */ +#define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */ +#define RSV_CTRL_FRAME 0x08000000 /* Control Frame */ +#define RSV_PAUSE 0x10000000 /* Pause Frame */ +#define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */ +#define RSV_VLAN 0x40000000 /* VLAN Frame */ + +/* Flow Control Counter Register */ +#define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */ +#define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */ + +/* Flow Control Status Register */ +#define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */ + +/* Receive Filter Control Register */ +#define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */ +#define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */ +#define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */ +#define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */ +#define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/ +#define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */ +#define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */ +#define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */ + +/* Receive Filter WoL Status/Clear Registers */ +#define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */ +#define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */ +#define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */ +#define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */ +#define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */ +#define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */ +#define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */ +#define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */ + +/* Interrupt Status/Enable/Clear/Set Registers */ +#define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */ +#define INT_RX_ERR 0x00000002 /* Receive Error */ +#define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */ +#define INT_RX_DONE 0x00000008 /* Receive Done */ +#define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */ +#define INT_TX_ERR 0x00000020 /* Transmit Error */ +#define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */ +#define INT_TX_DONE 0x00000080 /* Transmit Done */ +#define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */ +#define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */ + +/* Power Down Register */ +#define PD_POWER_DOWN 0x80000000 /* Power Down MAC */ + +/* RX Descriptor Control Word */ +#define RCTRL_SIZE 0x000007FF /* Buffer size mask */ +#define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */ + +/* RX Status Hash CRC Word */ +#define RHASH_SA 0x000001FF /* Hash CRC for Source Address */ +#define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */ + +/* RX Status Information Word */ +#define RINFO_SIZE 0x000007FF /* Data size in bytes */ +#define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */ +#define RINFO_VLAN 0x00080000 /* VLAN Frame */ +#define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */ +#define RINFO_MCAST 0x00200000 /* Multicast Frame */ +#define RINFO_BCAST 0x00400000 /* Broadcast Frame */ +#define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */ +#define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */ +#define RINFO_LEN_ERR 0x02000000 /* Length Error */ +#define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */ +#define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */ +#define RINFO_OVERRUN 0x10000000 /* Receive overrun */ +#define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */ +#define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */ +#define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ + +#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | \ + RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN) + +/* TX Descriptor Control Word */ +#define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */ +#define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */ +#define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */ +#define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */ +#define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */ +#define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */ +#define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */ + +/* TX Status Information Word */ +#define TINFO_COL_CNT 0x01E00000 /* Collision Count */ +#define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */ +#define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */ +#define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */ +#define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */ +#define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */ +#define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */ +#define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ + +/* DP83848C PHY Registers */ +#define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */ +#define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */ +#define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */ +#define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */ +#define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */ +#define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */ +#define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */ +#define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */ + +/* PHY Extended Registers */ +#define PHY_REG_STS 0x10 /* Status Register */ +#define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */ +#define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */ +#define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */ +#define PHY_REG_RECR 0x15 /* Receive Error Counter */ +#define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */ +#define PHY_REG_RBR 0x17 /* RMII and Bypass Register */ +#define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */ +#define PHY_REG_PHYCR 0x19 /* PHY Control Register */ +#define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */ +#define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */ +#define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */ + +#define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */ +#define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */ +#define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */ +#define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */ +#define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */ + +#define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */ +#define DP83848C_ID 0x20005C90 /* PHY Identifier */ + +// prototypes +portBASE_TYPE Init_EMAC(void); +unsigned short ReadFrameBE_EMAC(void); +void CopyToFrame_EMAC(void *Source, unsigned int Size); +void CopyFromFrame_EMAC(void *Dest, unsigned short Size); +void DummyReadFrame_EMAC(unsigned short Size); +unsigned short StartReadFrame(void); +void EndReadFrame(void); +unsigned int CheckFrameReceived(void); +void RequestSend(void); +unsigned int Rdy4Tx(void); +void DoSend_EMAC(unsigned short FrameSize); +void vEMACWaitForInput( void ); +unsigned int uiGetEMACRxData( unsigned char *ucBuffer ); + + +#endif + +/*---------------------------------------------------------------------------- + * end of file + *---------------------------------------------------------------------------*/ + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/clock-arch.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/clock-arch.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/clock-arch.h (revision 14) @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: clock-arch.h,v 1.2 2006/06/12 08:00:31 adam Exp $ + */ + +#ifndef __CLOCK_ARCH_H__ +#define __CLOCK_ARCH_H__ + +#include "FreeRTOS.h" + +typedef unsigned long clock_time_t; +#define CLOCK_CONF_SECOND configTICK_RATE_HZ + +#endif /* __CLOCK_ARCH_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings.h (revision 14) @@ -0,0 +1,34 @@ +extern const char http_http[8]; +extern const char http_200[5]; +extern const char http_301[5]; +extern const char http_302[5]; +extern const char http_get[5]; +extern const char http_10[9]; +extern const char http_11[9]; +extern const char http_content_type[15]; +extern const char http_texthtml[10]; +extern const char http_location[11]; +extern const char http_host[7]; +extern const char http_crnl[3]; +extern const char http_index_html[12]; +extern const char http_404_html[10]; +extern const char http_referer[9]; +extern const char http_header_200[84]; +extern const char http_header_404[91]; +extern const char http_content_type_plain[29]; +extern const char http_content_type_html[28]; +extern const char http_content_type_css [27]; +extern const char http_content_type_text[28]; +extern const char http_content_type_png [28]; +extern const char http_content_type_gif [28]; +extern const char http_content_type_jpg [29]; +extern const char http_content_type_binary[43]; +extern const char http_html[6]; +extern const char http_shtml[7]; +extern const char http_htm[5]; +extern const char http_css[5]; +extern const char http_png[5]; +extern const char http_gif[5]; +extern const char http_jpg[5]; +extern const char http_text[5]; +extern const char http_txt[5]; Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uIP_Task.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uIP_Task.c (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uIP_Task.c (revision 17) @@ -0,0 +1,344 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ +/* Standard includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* uip includes. */ +#include "uip.h" +#include "uip_arp.h" +#include "httpd.h" +#include "timer.h" +#include "clock-arch.h" + +/* Demo includes. */ +#include "emac.h" +#include "partest.h" + +/*-----------------------------------------------------------*/ + +/* MAC address configuration. */ +#define uipMAC_ADDR0 0x00 +#define uipMAC_ADDR1 0x12 +#define uipMAC_ADDR2 0x13 +#define uipMAC_ADDR3 0x10 +#define uipMAC_ADDR4 0x15 +#define uipMAC_ADDR5 0x11 + +/* IP address configuration. */ +#define uipIP_ADDR0 192 +#define uipIP_ADDR1 168 +#define uipIP_ADDR2 3 +#define uipIP_ADDR3 100 + +/* How long to wait before attempting to connect the MAC again. */ +#define uipINIT_WAIT 200 + +/* Shortcut to the header within the Rx buffer. */ +#define xHeader ((struct uip_eth_hdr *) &uip_buf[ 0 ]) + +/* Standard constant. */ +#define uipTOTAL_FRAME_HEADER_SIZE 54 + +/*-----------------------------------------------------------*/ + +/* + * Send the uIP buffer to the MAC. + */ +static void prvENET_Send(void); + +/* + * Setup the MAC address in the MAC itself, and in the uIP stack. + */ +static void prvSetMACAddress( void ); + +/* + * Port functions required by the uIP stack. + */ +void clock_init( void ); +clock_time_t clock_time( void ); + +/*-----------------------------------------------------------*/ + +/* The semaphore used by the ISR to wake the uIP task. */ +extern xSemaphoreHandle xEMACSemaphore; + +/*-----------------------------------------------------------*/ + +void clock_init(void) +{ + /* This is done when the scheduler starts. */ +} +/*-----------------------------------------------------------*/ + +clock_time_t clock_time( void ) +{ + return xTaskGetTickCount(); +} +/*-----------------------------------------------------------*/ + +void vuIP_Task( void *pvParameters ) +{ +portBASE_TYPE i; +uip_ipaddr_t xIPAddr; +struct timer periodic_timer, arp_timer; +extern void ( vEMAC_ISR_Wrapper )( void ); + + /* Create the semaphore used by the ISR to wake this task. */ + vSemaphoreCreateBinary( xEMACSemaphore ); + + /* Initialise the uIP stack. */ + timer_set( &periodic_timer, configTICK_RATE_HZ / 2 ); + timer_set( &arp_timer, configTICK_RATE_HZ * 10 ); + uip_init(); + uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 ); + uip_sethostaddr( xIPAddr ); + httpd_init(); + + /* Initialise the MAC. */ + while( Init_EMAC() != pdPASS ) + { + vTaskDelay( uipINIT_WAIT ); + } + + portENTER_CRITICAL(); + { + MAC_INTENABLE = INT_RX_DONE; + VICIntEnable |= 0x00200000; + VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper; + prvSetMACAddress(); + } + portEXIT_CRITICAL(); + + + for( ;; ) + { + /* Is there received data ready to be processed? */ + uip_len = uiGetEMACRxData( uip_buf ); + + if( uip_len > 0 ) + { + /* Standard uIP loop taken from the uIP manual. */ + if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) + { + uip_arp_ipin(); + uip_input(); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + uip_arp_out(); + prvENET_Send(); + } + } + else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) + { + uip_arp_arpin(); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + prvENET_Send(); + } + } + } + else + { + if( timer_expired( &periodic_timer ) ) + { + timer_reset( &periodic_timer ); + for( i = 0; i < UIP_CONNS; i++ ) + { + uip_periodic( i ); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + uip_arp_out(); + prvENET_Send(); + } + } + + /* Call the ARP timer function every 10 seconds. */ + if( timer_expired( &arp_timer ) ) + { + timer_reset( &arp_timer ); + uip_arp_timer(); + } + } + else + { + /* We did not receive a packet, and there was no periodic + processing to perform. Block for a fixed period. If a packet + is received during this period we will be woken by the ISR + giving us the Semaphore. */ + xSemaphoreTake( xEMACSemaphore, configTICK_RATE_HZ / 2 ); + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvENET_Send(void) +{ + RequestSend(); + + /* Copy the header into the Tx buffer. */ + CopyToFrame_EMAC( uip_buf, uipTOTAL_FRAME_HEADER_SIZE ); + if( uip_len > uipTOTAL_FRAME_HEADER_SIZE ) + { + CopyToFrame_EMAC( uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) ); + } + + DoSend_EMAC( uip_len ); + + RequestSend(); + + /* Copy the header into the Tx buffer. */ + CopyToFrame_EMAC( uip_buf, uipTOTAL_FRAME_HEADER_SIZE ); + if( uip_len > uipTOTAL_FRAME_HEADER_SIZE ) + { + CopyToFrame_EMAC( uip_appdata, ( uip_len - uipTOTAL_FRAME_HEADER_SIZE ) ); + } + + DoSend_EMAC( uip_len ); +} +/*-----------------------------------------------------------*/ + +static void prvSetMACAddress( void ) +{ +struct uip_eth_addr xAddr; + + /* Configure the MAC address in the uIP stack. */ + xAddr.addr[ 0 ] = uipMAC_ADDR0; + xAddr.addr[ 1 ] = uipMAC_ADDR1; + xAddr.addr[ 2 ] = uipMAC_ADDR2; + xAddr.addr[ 3 ] = uipMAC_ADDR3; + xAddr.addr[ 4 ] = uipMAC_ADDR4; + xAddr.addr[ 5 ] = uipMAC_ADDR5; + uip_setethaddr( xAddr ); +} +/*-----------------------------------------------------------*/ + +void vApplicationProcessFormInput( portCHAR *pcInputString, portBASE_TYPE xInputLength ) +{ +char *c, *pcText; +static portCHAR cMessageForDisplay[ 32 ]; +extern xQueueHandle xLCDQueue; +xLCDMessage xLCDMessage; + + /* Process the form input sent by the IO page of the served HTML. */ + + c = strstr( pcInputString, "?" ); + if( c ) + { + /* Turn LED's on or off in accordance with the check box status. */ + if( strstr( c, "LED0=1" ) != NULL ) + { + vParTestSetLED( 5, 0 ); + } + else + { + vParTestSetLED( 5, 1 ); + } + + if( strstr( c, "LED1=1" ) != NULL ) + { + vParTestSetLED( 6, 0 ); + } + else + { + vParTestSetLED( 6, 1 ); + } + + if( strstr( c, "LED2=1" ) != NULL ) + { + vParTestSetLED( 7, 0 ); + } + else + { + vParTestSetLED( 7, 1 ); + } + + /* Find the start of the text to be displayed on the LCD. */ + pcText = strstr( c, "LCD=" ); + pcText += strlen( "LCD=" ); + + /* Terminate the file name for further processing within uIP. */ + *c = 0x00; + + /* Terminate the LCD string. */ + c = strstr( pcText, " " ); + if( c != NULL ) + { + *c = 0x00; + } + + /* Add required spaces. */ + while( ( c = strstr( pcText, "+" ) ) != NULL ) + { + *c = ' '; + } + + /* Write the message to the LCD. */ + strcpy( cMessageForDisplay, pcText ); + xLCDMessage.xColumn = 0; + xLCDMessage.pcMessage = cMessageForDisplay; + xQueueSend( xLCDQueue, &xLCDMessage, portMAX_DELAY ); + } +} + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makefsdata =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makefsdata (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/makefsdata (revision 14) @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +open(OUTPUT, "> httpd-fsdata.c"); + +chdir("httpd-fs"); + +opendir(DIR, "."); +@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); +closedir(DIR); + +foreach $file (@files) { + + if(-d $file && $file !~ /^\./) { + print "Processing directory $file\n"; + opendir(DIR, $file); + @newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); + closedir(DIR); + printf "Adding files @newfiles\n"; + @files = (@files, map { $_ = "$file/$_" } @newfiles); + next; + } +} + +foreach $file (@files) { + if(-f $file) { + + print "Adding file $file\n"; + + open(FILE, $file) || die "Could not open file $file\n"; + + $file =~ s-^-/-; + $fvar = $file; + $fvar =~ s-/-_-g; + $fvar =~ s-\.-_-g; + # for AVR, add PROGMEM here + print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); + print(OUTPUT "\t/* $file */\n\t"); + for($j = 0; $j < length($file); $j++) { + printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); + } + printf(OUTPUT "0,\n"); + + + $i = 0; + while(read(FILE, $data, 1)) { + if($i == 0) { + print(OUTPUT "\t"); + } + printf(OUTPUT "%#02x, ", unpack("C", $data)); + $i++; + if($i == 10) { + print(OUTPUT "\n"); + $i = 0; + } + } + print(OUTPUT "0};\n\n"); + close(FILE); + push(@fvars, $fvar); + push(@pfiles, $file); + } +} + +for($i = 0; $i < @fvars; $i++) { + $file = $pfiles[$i]; + $fvar = $fvars[$i]; + + if($i == 0) { + $prevfile = "NULL"; + } else { + $prevfile = "file" . $fvars[$i - 1]; + } + print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); + print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); + print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); +} + +print(OUTPUT "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n"); +print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n"); Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c (revision 17) @@ -0,0 +1,50 @@ +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +/* The interrupt entry point. */ +void vEMAC_ISR_Wrapper( void ) __attribute__((naked)); + +/* The function that actually performs the interrupt processing. This must be +separate to the wrapper to ensure the correct stack frame is set up. */ +void vEMAC_ISR_Handler( void ); + +extern xSemaphoreHandle xEMACSemaphore; + +void vEMAC_ISR_Handler( void ) +{ +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + /* Clear the interrupt. */ + MAC_INTCLEAR = 0xffff; + VICVectAddr = 0; + + /* Ensure the uIP task is not blocked as data has arrived. */ + xSemaphoreGiveFromISR( xEMACSemaphore, &xHigherPriorityTaskWoken ); + + if( xHigherPriorityTaskWoken ) + { + /* If the uIP task was unblocked then calling "Yield from ISR" here + will ensure the interrupt returns directly to the uIP task, if it + is the highest priority read task. */ + portYIELD_FROM_ISR(); + } +} +/*-----------------------------------------------------------*/ + +void vEMAC_ISR_Wrapper( void ) +{ + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + + /* Call the handler function. This must be separate from the wrapper + function to ensure the correct stack frame is set up. */ + vEMAC_ISR_Handler(); + + /* Restore the context of whichever task is going to run next. */ + portRESTORE_CONTEXT(); +} + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 19) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 19) @@ -0,0 +1,282 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * Web server script interface + * \author + * Adam Dunkels + * + */ + +/* + * Copyright (c) 2001-2006, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd-cgi.c,v 1.2 2006/06/11 21:46:37 adam Exp $ + * + */ + +#include "uip.h" +#include "psock.h" +#include "httpd.h" +#include "httpd-cgi.h" +#include "httpd-fs.h" + +#include +#include + +HTTPD_CGI_CALL(file, "file-stats", file_stats); +HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats); +HTTPD_CGI_CALL(net, "net-stats", net_stats); +HTTPD_CGI_CALL(rtos, "rtos-stats", rtos_stats ); +HTTPD_CGI_CALL(io, "led-io", led_io ); + + +static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, &rtos, &io, NULL }; + +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(nullfunction(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +httpd_cgifunction +httpd_cgi(char *name) +{ + const struct httpd_cgi_call **f; + + /* Find the matching name in the table, return the function. */ + for(f = calls; *f != NULL; ++f) { + if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) { + return (*f)->function; + } + } + return nullfunction; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_file_stats(void *arg) +{ + char *f = (char *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f)); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(file_stats(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + + PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static const char closed[] = /* "CLOSED",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0}; +static const char syn_rcvd[] = /* "SYN-RCVD",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, + 0x44, 0}; +static const char syn_sent[] = /* "SYN-SENT",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, + 0x54, 0}; +static const char established[] = /* "ESTABLISHED",*/ +{0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, + 0x45, 0x44, 0}; +static const char fin_wait_1[] = /* "FIN-WAIT-1",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x31, 0}; +static const char fin_wait_2[] = /* "FIN-WAIT-2",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x32, 0}; +static const char closing[] = /* "CLOSING",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x49, + 0x4e, 0x47, 0}; +static const char time_wait[] = /* "TIME-WAIT,"*/ +{0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, + 0x49, 0x54, 0}; +static const char last_ack[] = /* "LAST-ACK"*/ +{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, + 0x4b, 0}; + +static const char *states[] = { + closed, + syn_rcvd, + syn_sent, + established, + fin_wait_1, + fin_wait_2, + closing, + time_wait, + last_ack}; + + +static unsigned short +generate_tcp_stats(void *arg) +{ + struct uip_conn *conn; + struct httpd_state *s = (struct httpd_state *)arg; + + conn = &uip_conns[s->count]; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "

\r\n", + htons(conn->lport), + htons(conn->ripaddr[0]) >> 8, + htons(conn->ripaddr[0]) & 0xff, + htons(conn->ripaddr[1]) >> 8, + htons(conn->ripaddr[1]) & 0xff, + htons(conn->rport), + states[conn->tcpstateflags & UIP_TS_MASK], + conn->nrtx, + conn->timer, + (uip_outstanding(conn))? '*':' ', + (uip_stopped(conn))? '!':' '); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr)) +{ + + PSOCK_BEGIN(&s->sout); + + for(s->count = 0; s->count < UIP_CONNS; ++s->count) { + if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { + PSOCK_GENERATOR_SEND(&s->sout, generate_tcp_stats, s); + } + } + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_net_stats(void *arg) +{ + struct httpd_state *s = (struct httpd_state *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]); +} + +static +PT_THREAD(net_stats(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + +#if UIP_STATISTICS + + for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); + ++s->count) { + PSOCK_GENERATOR_SEND(&s->sout, generate_net_stats, s); + } + +#endif /* UIP_STATISTICS */ + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ + +extern void vTaskList( signed char *pcWriteBuffer ); +static char cCountBuf[ 32 ]; +long lRefreshCount = 0; +extern basementGasReading; +extern rtcHOURS; +extern rtcMINUTES; +extern rtcSECONDS; +static unsigned short +generate_rtos_stats(void *arg) +{ + lRefreshCount++; + + sprintf( cCountBuf, "


Refresh count = %d


Pulse Counter = %d at %02u:%02u:%02u", lRefreshCount, basementGasReading, rtcHOURS, rtcMINUTES, rtcSECONDS ); + strcat( uip_appdata, cCountBuf ); + vTaskList( uip_appdata ); + strcat( uip_appdata, cCountBuf ); + + return strlen( uip_appdata ); +} +/*---------------------------------------------------------------------------*/ + + +static +PT_THREAD(rtos_stats(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + PSOCK_GENERATOR_SEND(&s->sout, generate_rtos_stats, NULL); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ + +char *pcStatus[ 3 ]; +unsigned long ulString; +extern unsigned long uxParTextGetLED( unsigned long uxLED ); + +static unsigned short generate_io_state( void *arg ) +{ + for( ulString = 0; ulString < 4; ulString++ ) + { + if( uxParTextGetLED( ulString + 5 ) ) + { + pcStatus[ ulString ] = "checked"; + } + else + { + pcStatus[ ulString ] = ""; + } + } + + sprintf( uip_appdata, + "LED 2.5,"\ + "LED 2.6,"\ + "LED 2.7"\ + "

"\ + "", + pcStatus[ 0 ], + pcStatus[ 1 ], + pcStatus[ 2 ] ); + + return strlen( uip_appdata ); +} + +static PT_THREAD(led_io(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + PSOCK_GENERATOR_SEND(&s->sout, generate_io_state, NULL); + PSOCK_END(&s->sout); +} + +/** @} */ + + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.c (revision 14) @@ -0,0 +1,7113 @@ +static const unsigned char data_404_html[] = { + /* /404.html */ + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e, + 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33, + 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, + 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, +0}; + +static const unsigned char data_image_jpg[] = { + /* /image.jpg */ + 0x2f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2e, 0x6a, 0x70, 0x67, 0, + 0xff, 0xd8, 0xff, 0xe0, 00, 0x10, 0x4a, 0x46, 0x49, 0x46, + 00, 0x1, 0x1, 00, 00, 0x1, 00, 0x1, 00, 00, + 0xff, 0xdb, 00, 0x43, 00, 0x3, 0x2, 0x2, 0x3, 0x2, + 0x2, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, 0x4, 0x5, + 0x8, 0x5, 0x5, 0x4, 0x4, 0x5, 0xa, 0x7, 0x7, 0x6, + 0x8, 0xc, 0xa, 0xc, 0xc, 0xb, 0xa, 0xb, 0xb, 0xd, + 0xe, 0x12, 0x10, 0xd, 0xe, 0x11, 0xe, 0xb, 0xb, 0x10, + 0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0xc, 0xf, + 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, 0xff, + 0xdb, 00, 0x43, 0x1, 0x3, 0x4, 0x4, 0x5, 0x4, 0x5, + 0x9, 0x5, 0x5, 0x9, 0x14, 0xd, 0xb, 0xd, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0, + 00, 0x11, 0x8, 0x2, 0x69, 0x4, 0x39, 0x3, 0x1, 0x22, + 00, 0x2, 0x11, 0x1, 0x3, 0x11, 0x1, 0xff, 0xc4, 00, + 0x1f, 00, 00, 0x1, 0x5, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 00, 00, 00, 00, 00, 00, 00, 00, 0x1, + 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, + 0xff, 0xc4, 00, 0xb5, 0x10, 00, 0x2, 0x1, 0x3, 0x3, + 0x2, 0x4, 0x3, 0x5, 0x5, 0x4, 0x4, 00, 00, 0x1, + 0x7d, 0x1, 0x2, 0x3, 00, 0x4, 0x11, 0x5, 0x12, 0x21, + 0x31, 0x41, 0x6, 0x13, 0x51, 0x61, 0x7, 0x22, 0x71, 0x14, + 0x32, 0x81, 0x91, 0xa1, 0x8, 0x23, 0x42, 0xb1, 0xc1, 0x15, + 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x9, 0xa, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, + 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xff, 0xc4, 00, 0x1f, 0x1, 00, 0x3, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 00, + 00, 00, 00, 00, 00, 0x1, 0x2, 0x3, 0x4, 0x5, + 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xff, 0xc4, 00, 0xb5, + 0x11, 00, 0x2, 0x1, 0x2, 0x4, 0x4, 0x3, 0x4, 0x7, + 0x5, 0x4, 0x4, 00, 0x1, 0x2, 0x77, 00, 0x1, 0x2, + 0x3, 0x11, 0x4, 0x5, 0x21, 0x31, 0x6, 0x12, 0x41, 0x51, + 0x7, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x8, 0x14, 0x42, + 0x91, 0xa1, 0xb1, 0xc1, 0x9, 0x23, 0x33, 0x52, 0xf0, 0x15, + 0x62, 0x72, 0xd1, 0xa, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, + 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, + 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, + 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, + 0xda, 00, 0xc, 0x3, 0x1, 00, 0x2, 0x11, 0x3, 0x11, + 00, 0x3f, 00, 0xfd, 0x53, 0xa2, 0x8a, 0x28, 00, 0xa2, + 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x69, + 0x3c, 0xd0, 0x1, 0xba, 0x92, 0x8a, 0x28, 00, 0xe9, 0x4d, + 0x3c, 0xd0, 0x4e, 0x69, 0xa5, 0xb1, 0x40, 0x1, 0x61, 0x8a, + 0x6e, 0x69, 0x19, 0xb8, 0xa6, 0x16, 0xa0, 0x7, 0x31, 0xe7, + 0xe9, 0x4d, 0x2d, 0x4c, 0x67, 0xe2, 0xa3, 0x66, 0xa0, 0x7, + 0xb3, 0xd3, 0xc, 0x83, 0xd6, 0xa2, 0x79, 0x30, 0x9, 0x27, + 00, 0x56, 0x44, 0xba, 0xdb, 0xcb, 0x2b, 0x47, 0x65, 0x67, + 0x3d, 0xe1, 0x1d, 0x25, 0x45, 0xfd, 0xd1, 0xfa, 0x37, 0x43, + 0xe9, 0xc5, 0x67, 0x3a, 0x91, 0xa7, 0xf1, 0x18, 0xd4, 0xad, + 0xa, 0x4b, 0xde, 0x66, 0xcb, 0x3d, 0x56, 0xb9, 0xbe, 0x82, + 0xd0, 0x6e, 0x9a, 0x68, 0xe2, 0x7, 0xbc, 0x8c, 0x16, 0xb9, + 0x6b, 0x8d, 0x27, 0xc7, 0x7a, 0x8b, 0x3a, 0x8b, 0x8d, 0x3b, + 0x4f, 0x85, 0xb8, 0x6, 0x25, 0x6f, 0x33, 0x1e, 0xe4, 0xe7, + 0x9a, 0xe7, 0xef, 0x7e, 0x4, 0x6a, 0x1a, 0xdb, 0x97, 0xd5, + 0x3c, 0x47, 0xa8, 0xdc, 0x67, 0x1f, 0x27, 0xda, 0x9b, 0x60, + 0xfa, 0xc, 0x57, 0x8d, 0x5f, 0x1f, 0x89, 0x4a, 0xd8, 0x6c, + 0x3c, 0xa4, 0xfc, 0xda, 0x8a, 0xff, 00, 0x3f, 0xc0, 0xf0, + 0x71, 0x39, 0x9e, 0x31, 0x2b, 0x60, 0xf0, 0x92, 0x9b, 0xfe, + 0xf3, 0x51, 0x5f, 0xab, 0xfc, 0xe, 0xca, 0xf7, 0xc7, 0x1a, + 0xd, 0x8e, 0x7c, 0xfd, 0x62, 0xc6, 0x3c, 0xc, 0x9c, 0xce, + 0xbf, 0xe3, 0x58, 0xd2, 0xfc, 0x5e, 0xf0, 0x7c, 0x6d, 0x8f, + 0xf8, 0x48, 0x2c, 0x5b, 0xfd, 0xd9, 0x97, 0x8f, 0xd6, 0xb9, + 0xa1, 0xfb, 0x2b, 0xe8, 0x44, 0x7c, 0xf7, 0x37, 0x4, 0xf5, + 0xe6, 0x41, 0xfe, 0x15, 0x5e, 0x4f, 0xd9, 0x43, 0x44, 0x60, + 0x76, 0xdd, 0x4f, 0xf8, 0xb8, 0xff, 00, 0xe2, 0x6b, 0xc6, + 0x9e, 0x33, 0x88, 0x37, 0x86, 0x1a, 0xb, 0xfe, 0xde, 0x6f, + 0xf4, 0x47, 0xcf, 0xd4, 0xc7, 0xf1, 0x4b, 0xd6, 0x18, 0x3a, + 0x6b, 0xfe, 0xdf, 0x6f, 0xf4, 0x47, 0x55, 0x1f, 0xc6, 0xf, + 0x7, 0xbb, 0x63, 0xfb, 0x7e, 0xc1, 0x7d, 0xda, 0x75, 0xff, + 00, 0x1a, 0xb0, 0xbf, 0x14, 0xbc, 0x28, 0xdf, 0x77, 0xc4, + 0x3a, 0x71, 0x3f, 0xf5, 0xf0, 0xb5, 0xc0, 0xcb, 0xfb, 0x25, + 0xe9, 0xe7, 0xee, 0x5e, 0x4a, 0x3e, 0xb2, 0xf, 0xfe, 0x26, + 0xa9, 0x4b, 0xfb, 0x24, 0x45, 0xfc, 0x17, 0xa7, 0xf1, 0x71, + 0xff, 00, 0xc4, 0xd7, 0x33, 0xcc, 0x38, 0x8e, 0x3b, 0xe1, + 0x22, 0xff, 00, 0xed, 0xe3, 0x93, 0xfb, 0x53, 0x8b, 0x21, + 0xbe, 0xa, 0xf, 0xd2, 0x4c, 0xf5, 0x1, 0xf1, 0xf, 0xc3, + 0x92, 0xfd, 0xdd, 0x72, 0xc0, 0xfd, 0x2e, 0x17, 0xfc, 0x6a, + 0x68, 0xfc, 0x69, 0xa2, 0x49, 0xf7, 0x75, 0x7b, 0x26, 0xff, + 00, 0xb7, 0x85, 0xff, 00, 0x1a, 0xf2, 0x9, 0x7f, 0x64, + 0x89, 0xf9, 0xf2, 0xef, 0x87, 0xe3, 0x27, 0xff, 00, 0x63, + 0x54, 0xa4, 0xfd, 0x92, 0x35, 0x31, 0xfe, 0xae, 0xf6, 0x2f, + 0xc6, 0x4f, 0xfe, 0xc6, 0xa7, 0xfb, 0x5f, 0x88, 0x23, 0xbe, + 0x5, 0x3f, 0xfb, 0x7b, 0xfe, 0x1, 0x1f, 0xdb, 0xbc, 0x51, + 0xd, 0xf2, 0xd4, 0xfd, 0x25, 0xff, 00, 00, 0xf7, 0x45, + 0xf1, 0x46, 0x94, 0xdd, 0x35, 0x2b, 0x33, 0xff, 00, 0x6d, + 0xd7, 0xfc, 0x69, 0xdf, 0xf0, 0x90, 0x69, 0xc4, 0xf1, 0x7f, + 0x6a, 0x7f, 0xed, 0xb2, 0xff, 00, 0x8d, 0x7c, 0xfd, 0x27, + 0xec, 0x9b, 0xae, 0xa3, 0x65, 0x2e, 0xa0, 0xc8, 0x3d, 0x7c, + 0xc3, 0xff, 00, 0xc4, 0xd4, 0x2d, 0xfb, 0x2f, 0x78, 0xb2, + 0xc, 0x98, 0xef, 0x50, 0x7f, 0xbb, 0x33, 0xff, 00, 0x85, + 0x4f, 0xf6, 0xf6, 0x75, 0x1f, 0x8b, 0x2f, 0x7f, 0xf8, 0x17, + 0xfc, 0x2, 0x7f, 0xd6, 0x6e, 0x21, 0x8f, 0xc5, 0x95, 0x3f, + 0x94, 0xbf, 0xe0, 0x1f, 0x45, 0xae, 0xaf, 0x66, 0xe3, 0xe5, + 0xba, 0x81, 0xbe, 0x92, 0x3, 0xfd, 0x6a, 0x44, 0xbe, 0x85, + 0xfe, 0xec, 0xa8, 0xdf, 0x46, 0x15, 0xf3, 0x63, 0x7c, 0x1, + 0xf1, 0xf5, 0xa8, 0xc4, 0x5a, 0x9c, 0xe0, 0x7a, 0x25, 0xcc, + 0xa3, 0xfa, 0x53, 0x4f, 0xc2, 0xf, 0x89, 0x96, 0xdf, 0x73, + 0x56, 0xd4, 0x47, 0xfb, 0x97, 0x93, 0xa, 0xa5, 0xc4, 0x98, + 0xf8, 0xfc, 0x78, 0x9, 0xfc, 0x8a, 0xff, 00, 0x5b, 0xb3, + 0x38, 0xff, 00, 0x13, 0x2b, 0x9f, 0xc9, 0xdf, 0xf4, 0x3e, + 0x9a, 0x12, 0x83, 0x82, 0xf, 0x14, 0xbe, 0x76, 0x3b, 0xd7, + 0xcc, 0x3f, 0xf0, 0x82, 0x7c, 0x54, 0xb5, 0x1b, 0x46, 0xb1, + 0xab, 0x37, 0xd6, 0xee, 0x73, 0x4a, 0x74, 0xaf, 0x8a, 0xb6, + 0x60, 0xe6, 0xff, 00, 0x51, 0x7c, 0xfa, 0xcb, 0x31, 0xaa, + 0xff, 00, 0x5a, 0xe7, 0x1f, 0x8f, 0x5, 0x51, 0x16, 0xb8, + 0xda, 0xa4, 0x7f, 0x89, 0x97, 0xd5, 0x5f, 0x23, 0xe9, 0xef, + 0x3b, 0xde, 0x81, 0x2e, 0x4d, 0x7c, 0xc4, 0xba, 0xa7, 0xc5, + 0x3b, 0x30, 0x3e, 0x7b, 0xa9, 0x31, 0xfd, 0xf4, 0x95, 0xa9, + 0xe3, 0xc7, 0xdf, 0x14, 0x2d, 0x7a, 0xc0, 0xcd, 0x83, 0xd1, + 0xad, 0x1c, 0xff, 00, 0x4a, 0xa5, 0xc5, 0xf8, 0x75, 0xf1, + 0xd0, 0xa8, 0xbf, 0xed, 0xd2, 0xd7, 0x1d, 0xe1, 0x57, 0xf1, + 0x30, 0xd5, 0x63, 0xff, 00, 0x6e, 0xff, 00, 0xc1, 0x3e, + 0x9b, 0xf3, 0x3d, 0xe9, 0xc2, 0x5e, 0x3a, 0xd7, 0xcc, 0xf, + 0xf1, 0x7b, 0xe2, 0x64, 0x44, 0x6e, 0xb1, 0x8b, 0x8f, 0xfa, + 0x71, 0x7a, 0x61, 0xf8, 0xe3, 0xf1, 0x12, 0x13, 0xf3, 0xe9, + 0xb0, 0x37, 0xd6, 0xcd, 0xff, 00, 0xc6, 0x9f, 0xfa, 0xe5, + 0x97, 0x2f, 0x8a, 0x13, 0x5f, 0xf6, 0xef, 0xfc, 0x11, 0xff, + 00, 0xc4, 0x40, 0xca, 0x96, 0xf0, 0xa8, 0xbf, 0xed, 0xcf, + 0xf8, 0x27, 0xd4, 0x7e, 0x77, 0xbd, 0x1e, 0x6e, 0x7b, 0xd7, + 0xcb, 0x87, 0xf6, 0x83, 0xf1, 0xdc, 0x64, 0xee, 0xd2, 0xac, + 0xbf, 0x1b, 0x59, 0x7, 0xfe, 0xcd, 0x49, 0xff, 00, 0xd, + 0x25, 0xe3, 0x44, 0xfb, 0xda, 0x56, 0x9c, 0x47, 0xbc, 0x12, + 0xff, 00, 0xf1, 0x55, 0x4b, 0x8d, 0x32, 0xae, 0xae, 0x4b, + 0xfe, 0xdd, 0x63, 0x5e, 0x20, 0xe4, 0x97, 0xd5, 0xcd, 0x7f, + 0xdb, 0xac, 0xfa, 0x99, 0x65, 0xf7, 0xa7, 0xf9, 0x9e, 0xe2, + 0xbe, 0x5f, 0x87, 0xf6, 0x9c, 0xf1, 0xa, 0xf1, 0x36, 0x95, + 0x69, 0xff, 00, 00, 0x89, 0xff, 00, 0xf8, 0xba, 0xbf, + 0x6f, 0xfb, 0x51, 0xdd, 0xab, 0x9f, 0xb4, 0x69, 0x23, 0x18, + 0xff, 00, 0x96, 0x71, 0x9c, 0xfe, 0xaf, 0x5a, 0xc7, 0x8c, + 0x32, 0x89, 0x7f, 0xcb, 0xc6, 0xbe, 0x4c, 0xe8, 0x8f, 0x1e, + 0x64, 0x52, 0xde, 0xab, 0x5e, 0xa9, 0x9f, 0x48, 0xf9, 0x98, + 0xf4, 0xa5, 0x12, 0xe4, 0xd7, 0xcf, 0x91, 0x7e, 0xd4, 0xd6, + 0x63, 0x1e, 0x66, 0x91, 0x74, 0x7d, 0x76, 0xa2, 0xff, 00, + 0xf1, 0x75, 0x79, 0x3f, 0x6a, 0xad, 0xb, 0x1f, 0x36, 0x91, + 0xa8, 0xaf, 0xe0, 0x9f, 0xfc, 0x55, 0x75, 0x47, 0x8a, 0x72, + 0x89, 0x7f, 0xcb, 0xf4, 0xbe, 0xf3, 0xb2, 0x3c, 0x69, 0x90, + 0xcf, 0xfe, 0x62, 0x52, 0xfb, 0xcf, 0x78, 0xf3, 0x7, 0xf9, + 0x34, 0x79, 0x9e, 0xff, 00, 0xad, 0x78, 0x72, 0x7e, 0xd4, + 0xbe, 0x1c, 0x3f, 0x7b, 0x4f, 0xd4, 0x53, 0xfe, 00, 0xa7, + 0xff, 00, 0x66, 0xab, 0x9, 0xfb, 0x4f, 0xf8, 0x51, 0x86, + 0x5a, 0x1b, 0xf4, 0xfa, 0xc2, 0x3f, 0xc6, 0xb6, 0x5c, 0x49, + 0x94, 0x3f, 0xf9, 0x88, 0x8f, 0xde, 0x74, 0x2e, 0x2e, 0xc8, + 0xa5, 0xff, 00, 0x31, 0x70, 0xfb, 0xcf, 0x69, 0xf3, 0x7e, + 0xbf, 0x9d, 0x1e, 0x65, 0x78, 0xe2, 0xfe, 0xd3, 0x7e, 0xe, + 0x3f, 0x79, 0xef, 0x57, 0xeb, 0x6e, 0x7f, 0xc6, 0xad, 0xc5, + 0xfb, 0x48, 0xf8, 0x32, 0x5c, 0x7f, 0xa5, 0xdc, 0x2f, 0xfb, + 0xf0, 0xe3, 0xfa, 0xd6, 0xd1, 0xcf, 0xf2, 0xa9, 0x6d, 0x89, + 0x87, 0xfe, 0x4, 0x8d, 0xe3, 0xc4, 0xf9, 0x24, 0xb6, 0xc5, + 0xc3, 0xff, 00, 0x2, 0x47, 0xac, 0xf9, 0x9e, 0xf4, 0xbe, + 0x65, 0x79, 0x8c, 0x5f, 0x1f, 0xfc, 0x1b, 0x2e, 0xdf, 0xf8, + 0x99, 0x85, 0xcf, 0xf7, 0xb0, 0x31, 0xfa, 0xd5, 0xf8, 0x7e, + 0x34, 0x78, 0x42, 0x6f, 0xf9, 0x8e, 0x59, 0xa7, 0x19, 0xf9, + 0xe7, 0x41, 0xff, 00, 0xb3, 0x57, 0x44, 0x73, 0x7c, 0xbe, + 0x7f, 0xd, 0x78, 0xbf, 0xfb, 0x79, 0x1d, 0x70, 0xcf, 0x72, + 0xba, 0x9a, 0x47, 0x13, 0x7, 0xff, 00, 0x6f, 0x23, 0xd0, + 0x77, 0xe0, 0x50, 0x1e, 0xb8, 0xc8, 0x3e, 0x2a, 0xf8, 0x4a, + 0x60, 0xf, 0xfc, 0x24, 0xba, 0x52, 0x7b, 0x3d, 0xec, 0x40, + 0xff, 00, 0xe8, 0x55, 0x6d, 0x3e, 0x21, 0xf8, 0x6a, 0x4f, + 0xb9, 0xe2, 0x1d, 0x29, 0x8f, 0xb5, 0xec, 0x7f, 0xfc, 0x55, + 0x75, 0x47, 0x1b, 0x85, 0x96, 0xaa, 0xac, 0x7e, 0xf4, 0x76, + 0x47, 0x31, 0xc1, 0xcf, 0x58, 0xd6, 0x8f, 0xfe, 0x4, 0xbf, + 0xcc, 0xea, 0x77, 0xfb, 0x8a, 0x5f, 0x37, 0xde, 0xb9, 0xf8, + 0xbc, 0x5d, 0xa3, 0x4e, 0x71, 0x1e, 0xaf, 0x63, 0x21, 0xff, + 00, 0x66, 0xe5, 0xf, 0xf5, 0xab, 0x91, 0x6a, 0xd6, 0x93, + 0xe3, 0xcb, 0xbb, 0x81, 0xf3, 0xfd, 0xd9, 0x1, 0xad, 0xe3, + 0x5a, 0x94, 0xbe, 0x19, 0x27, 0xf3, 0x47, 0x4c, 0x6b, 0xd2, + 0x9f, 0xc3, 0x34, 0xfe, 0x68, 0xd4, 0xf3, 0x7d, 0xe8, 0xf3, + 0x33, 0x55, 0x16, 0x65, 0x70, 0xa, 0xb0, 0x61, 0xea, 0x29, + 0xc2, 0x60, 0x3b, 0xd6, 0xd7, 0x46, 0xd7, 0x45, 0xc5, 0x7c, + 0xa, 0x5f, 0x32, 0xa9, 0x89, 0x81, 0xe8, 0x69, 0x44, 0x99, + 0xef, 0x4a, 0xe8, 0x2e, 0x8b, 0x7e, 0x65, 0x1e, 0x66, 0x6a, + 0xb2, 0xc8, 0x3d, 0x73, 0x4e, 0xf3, 0x68, 0xb8, 0xc9, 0xf7, + 0x51, 0xba, 0xa1, 0xf3, 0x30, 0x29, 0x77, 0xd3, 0x2, 0x75, + 0x6a, 0x5d, 0xd5, 0x58, 0x3e, 0x29, 0x7c, 0xd3, 0x40, 0x16, + 0x37, 0x52, 0xef, 0xf7, 0xaa, 0xde, 0x65, 0x28, 0x93, 0x34, + 0x1, 0x63, 0x7f, 0xbd, 0x1b, 0xea, 0x10, 0xe2, 0x97, 0x78, + 0xf5, 0xa0, 0x9, 0xb3, 0xef, 0x4b, 0xba, 0xa0, 0xdf, 0xef, + 0x49, 0xbc, 0xd0, 0x4, 0xfb, 0xe9, 0x77, 0x54, 0x1b, 0xa9, + 0x43, 0xe4, 0xd0, 0x4, 0xf9, 0xa3, 0x35, 0x16, 0xfa, 0x5d, + 0xf4, 0x1, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d, 0xd4, 0x1, + 0x28, 0xa7, 0x6e, 0xa8, 0x37, 0xfd, 0x28, 0xde, 0x7d, 0x68, + 0x2, 0x7d, 0xdf, 0x5a, 0x37, 0x7d, 0x6a, 0x2d, 0xde, 0xf4, + 0x6e, 0xf7, 0xa0, 0x9, 0x77, 0x7b, 0xd2, 0x86, 0xa8, 0x77, + 0x7b, 0xd2, 0x86, 0xa0, 0x9, 0x77, 0x51, 0xba, 0xa3, 0xdd, + 0xf5, 0xa3, 0x7d, 00, 0x49, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, + 0x6f, 0xa0, 0x7, 0xee, 0xa3, 0x75, 0x33, 0x77, 0xbd, 0x1b, + 0xa8, 0x2, 0x4d, 0xd4, 0x64, 0x53, 0x37, 0x51, 0xba, 0x80, + 0x1f, 0x91, 0x46, 0x45, 0x33, 0x75, 0x1b, 0xa8, 0x1, 0xf9, + 0x14, 0xb9, 0x15, 0x1e, 0xea, 0x51, 0xcd, 00, 0x3e, 0x8a, + 0x4c, 0xd1, 0xba, 0x80, 0x16, 0x8a, 0x4d, 0xd4, 0x6e, 0xa0, + 0x7, 0x64, 0xd1, 0xf8, 0xd2, 0x66, 0x8c, 0xd0, 0x2, 0xfe, + 0x34, 0x67, 0xde, 0x93, 0x34, 0x66, 0x80, 0x17, 0x75, 0x1b, + 0xa9, 0x28, 0xa0, 0x5, 0xdd, 0x46, 0xea, 0x4a, 0x28, 0x1, + 0x77, 0x51, 0xba, 0x92, 0x8a, 00, 0x5d, 0xd4, 0xa3, 0x9a, + 0x6d, 0x28, 0x38, 0xa0, 0x7, 0x51, 0x4d, 0xc9, 0xa3, 0x75, + 00, 0x3a, 0x8a, 0x6e, 0xea, 0x37, 0x50, 0x3, 0xa8, 0xa6, + 0xee, 0xa5, 0xdd, 0x40, 0xb, 0x45, 0x26, 0xea, 0x37, 0x50, + 0x2, 0xd1, 0x49, 0xba, 0x8c, 0xd0, 0x2, 0xd1, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, + 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, + 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x26, 0x68, 0x1, 0xa7, 0xad, 0x14, 0x51, + 0x9a, 00, 0x29, 0xa4, 0xd0, 0x69, 0xac, 0x68, 00, 0x27, + 0x6, 0xa3, 0x66, 0xa1, 0x8f, 0xbd, 0x46, 0x4f, 0x34, 00, + 0x33, 0x1a, 0x8c, 0xb5, 0x23, 0xb7, 0x53, 0x50, 0xbb, 0xd0, + 0x3, 0xd9, 0xe9, 0x23, 0x57, 0x9d, 0xb0, 0xa3, 0x3e, 0xf4, + 0xfb, 0x6b, 0x66, 0xb8, 0x39, 0x3c, 0x27, 0xad, 0x69, 0x47, + 0x1a, 0xc6, 0xb8, 0x51, 0x81, 0x40, 0x14, 0x13, 0x4a, 0x53, + 0x22, 0xbc, 0xad, 0xbf, 0x6f, 0x44, 0xfe, 0x1f, 0xc4, 0x77, + 0xab, 0xa9, 0x12, 0x46, 0xa1, 0x55, 0x2, 0x8f, 0x40, 0x30, + 0x2a, 0x5a, 0x2a, 0x54, 0x56, 0xe4, 0xf2, 0xa4, 0xee, 0x27, + 0x4a, 0x4e, 0xbd, 0x29, 0xd4, 0x53, 0x28, 0x69, 0x14, 0x7e, + 0x54, 0xea, 0x29, 0x80, 0xde, 0x94, 0x62, 0x9d, 0x45, 00, + 0x37, 0x22, 0x94, 0xd2, 0xd1, 0x48, 0x6, 0xfe, 0x34, 0x62, + 0x9d, 0x45, 0x30, 0x1b, 0x8a, 0x38, 0xa7, 0x51, 0x40, 0xc, + 0xda, 0x3f, 0xba, 0x29, 0xa6, 0x24, 0x3f, 0xc0, 0xa7, 0xf0, + 0xa9, 0x68, 0xa5, 0x61, 0x59, 0x10, 0x9b, 0x68, 0x8f, 0x58, + 0x90, 0xfd, 0x54, 0x53, 0x5a, 0xc2, 0xdd, 0xbe, 0xf4, 0x11, + 0x1f, 0xf8, 00, 0xab, 0x14, 0x52, 0xe5, 0x5d, 0x89, 0xe4, + 0x8b, 0xdd, 0x14, 0xbf, 0xb2, 0x6c, 0x8e, 0x73, 0x69, 0x9, + 0xff, 00, 0x80, 0xa, 0x8d, 0xb4, 0x1d, 0x39, 0xfa, 0xd8, + 0xdb, 0x9f, 0xfb, 0x66, 0x3f, 0xc2, 0xb4, 0x68, 0xa9, 0x74, + 0xe0, 0xf7, 0x48, 0x87, 0x46, 0x9b, 0xde, 0x2b, 0xee, 0x32, + 0x5b, 0xc3, 0x1a, 0x4b, 0xfd, 0xed, 0x3a, 0xd4, 0xfd, 0x62, + 0x5f, 0xf0, 0xa8, 0x5f, 0xc1, 0x7a, 0x1b, 0xfd, 0xed, 0x2e, + 0xd4, 0xff, 00, 0xdb, 0x15, 0xff, 00, 0xa, 0xdc, 0xa2, + 0xb3, 0x78, 0x7a, 0x2f, 0x78, 0x2f, 0xb9, 0x19, 0xbc, 0x2d, + 0x7, 0xbc, 0x17, 0xdc, 0x8e, 0x6d, 0xfe, 0x1e, 0xf8, 0x76, + 0x4e, 0xba, 0x55, 0xaf, 0xfd, 0xf9, 0x5f, 0xf0, 0xaa, 0x92, + 0xfc, 0x2a, 0xf0, 0xd4, 0xdf, 0x7b, 0x4a, 0xb6, 0xff, 00, + 0xbf, 0x2b, 0xfe, 0x15, 0xd7, 0xd1, 0x58, 0xbc, 0xe, 0x16, + 0x5b, 0xd3, 0x5f, 0x72, 0x30, 0x96, 0x5d, 0x83, 0x9f, 0xc5, + 0x4a, 0x3f, 0x72, 0x38, 0x49, 0x3e, 0xc, 0x78, 0x5a, 0x5e, + 0xba, 0x6c, 0x1f, 0x84, 0x49, 0xfe, 0x15, 0x4e, 0x6f, 0x81, + 0x3e, 0x16, 0x97, 0xfe, 0x5c, 0x22, 0x1f, 0xf6, 0xc9, 0x3f, + 0xc2, 0xbd, 0x1e, 0x8a, 0xe7, 0x96, 0x55, 0x81, 0x96, 0xf4, + 0x63, 0xf7, 0x1c, 0xb2, 0xc9, 0x32, 0xd9, 0xfc, 0x54, 0x23, + 0xf7, 0x23, 0xca, 0xe6, 0xfd, 0x9e, 0x7c, 0x31, 0x20, 0xe2, + 0xd9, 0x17, 0xfe, 0xd9, 0x27, 0xf8, 0x55, 0x19, 0x7f, 0x66, + 0xaf, 0xe, 0x49, 0x9c, 0x28, 0x5f, 0xa4, 0x6b, 0xfe, 0x15, + 0xec, 0x54, 0x57, 0x3c, 0xb2, 0x2c, 0xb6, 0x5b, 0xd0, 0x8f, + 0xdc, 0x72, 0x4b, 0x86, 0xb2, 0x89, 0xef, 0x87, 0x8f, 0xdc, + 0x78, 0x84, 0xdf, 0xb2, 0xee, 0x87, 0x21, 0xca, 0xcd, 0xb7, + 0xfe, 00, 0x2a, 0x84, 0xdf, 0xb2, 0x8e, 0x97, 0x21, 0x3b, + 0x2f, 0xa, 0xfd, 0x54, 0x57, 0xbf, 0x51, 0x5c, 0xb2, 0xe1, + 0x9c, 0xa6, 0x5b, 0xd0, 0x47, 0x1c, 0xf8, 0x43, 0x24, 0x9e, + 0xf8, 0x74, 0x7c, 0xe9, 0x37, 0xec, 0x95, 0x6c, 0xd9, 0xd9, + 0xa8, 0x1, 0xff, 00, 00, 0xaa, 0x52, 0x7e, 0xc8, 0xa7, + 0xf8, 0x35, 0x38, 0x87, 0xd5, 0xd, 0x7d, 0x31, 0x45, 0x73, + 0xcb, 0x84, 0xb2, 0x89, 0x7f, 0xcb, 0xaf, 0xc5, 0x9c, 0x92, + 0xe0, 0x6c, 0x86, 0x5f, 0xf2, 0xe3, 0xf1, 0x67, 0xcb, 0x92, + 0xfe, 0xc8, 0xb7, 0x63, 0xee, 0xea, 0x90, 0x1f, 0xac, 0x66, + 0xab, 0x3f, 0xec, 0x99, 0xac, 0x47, 0xf7, 0x35, 0x58, 0xf, + 0xfc, 0x5, 0xab, 0xea, 0xca, 0x2b, 0x9d, 0xf0, 0x6e, 0x50, + 0xf6, 0xa6, 0xd7, 0xcd, 0x9c, 0xcf, 0x80, 0x32, 0x27, 0xb5, + 0x26, 0xbf, 0xed, 0xe6, 0x7c, 0x96, 0xff, 00, 0xb2, 0xf7, + 0x8a, 0x61, 0xff, 00, 0x53, 0xaa, 0xa0, 0xfa, 0x33, 0x8a, + 0x81, 0xff, 00, 0x67, 0x6f, 0x1c, 0x41, 0xfe, 0xaf, 0x53, + 0x6e, 0x3d, 0x26, 0x90, 0x57, 0xd7, 0x74, 0x56, 0x6f, 0x83, + 0x32, 0xdf, 0xb2, 0xe4, 0xbf, 0xed, 0xe6, 0x62, 0xfc, 0x3f, + 0xca, 0x3e, 0xcb, 0x9a, 0xff, 00, 0xb7, 0x99, 0xf1, 0xe4, + 0x9f, 0x3, 0x3e, 0x20, 0xc3, 0xf7, 0x75, 0x29, 0xb8, 0xf4, + 0xb9, 0x90, 0x55, 0x67, 0xf8, 0x47, 0xf1, 0x1e, 0xd7, 0x38, + 0xd4, 0xee, 0x87, 0xd2, 0xea, 0x4a, 0xfb, 0x2f, 0x14, 0x60, + 0x7a, 0x56, 0x72, 0xe0, 0xcc, 0x27, 0xd9, 0xab, 0x35, 0xff, + 00, 0x6f, 0x19, 0x3f, 0xf, 0xf0, 0x3f, 0x66, 0xbd, 0x45, + 0xff, 00, 0x6f, 0x1f, 0x16, 0x3f, 0xc3, 0xff, 00, 0x89, + 0x76, 0xdf, 0x77, 0x55, 0xbf, 0x1f, 0xee, 0xde, 0x49, 0x55, + 0x9f, 0xc3, 0xff, 00, 0x13, 0x20, 0xff, 00, 0x98, 0xbe, + 0xa9, 0xf5, 0x5b, 0xd7, 0xff, 00, 0x1a, 0xfb, 0x73, 0x68, + 0x3d, 0x85, 0x35, 0xa3, 0x53, 0xfc, 0x23, 0xf2, 0xac, 0x9f, + 0x6, 0xc1, 0x7c, 0x18, 0xa9, 0xaf, 0x99, 0x8b, 0xe0, 0xa, + 0x6b, 0xe0, 0xc6, 0x55, 0x5f, 0x33, 0xe2, 0x1d, 0xff, 00, + 0x12, 0xec, 0x4f, 0x3a, 0xae, 0xa6, 0xfc, 0xe7, 0xe7, 0xbb, + 0x73, 0xff, 00, 0xb3, 0x54, 0xa9, 0xe2, 0xff, 00, 0x88, + 0xf6, 0x58, 0xcd, 0xe5, 0xcb, 0x91, 0xff, 00, 0x3d, 0x27, + 0x73, 0xff, 00, 0xb3, 0xd7, 0xda, 0xe6, 0x4, 0x3d, 0x63, + 0x5f, 0xca, 0x98, 0x6c, 0xe0, 0x6e, 0xb1, 0x21, 0xff, 00, + 0x80, 0xd4, 0xff, 00, 0xaa, 0x55, 0xe3, 0xf0, 0x63, 0x66, + 0xbf, 0xaf, 0x52, 0x3f, 0xd4, 0x7c, 0x4c, 0x7f, 0x87, 0x98, + 0xd4, 0x5f, 0xd7, 0xa9, 0xf1, 0x94, 0x7f, 0x16, 0xbe, 0x21, + 0xd9, 0x72, 0xd2, 0x29, 0xc7, 0xf7, 0xcb, 0x9f, 0xfd, 0x9e, + 0xac, 0x27, 0xc7, 0xff, 00, 0x1f, 0xdb, 0xff, 00, 0xd, + 0x8b, 0x60, 0x63, 0xe7, 0x89, 0x8f, 0xfe, 0xcd, 0x5f, 0x60, + 0xb6, 0x97, 0x6a, 0xdf, 0x7a, 0xde, 0x23, 0xf5, 0x51, 0x51, + 0xb6, 0x87, 0xa7, 0xb7, 0xde, 0xb3, 0x84, 0xff, 00, 0xc0, + 0x5, 0x35, 0xc3, 0x79, 0x9c, 0x3e, 0xc, 0x7c, 0xbe, 0xe2, + 0x97, 0x8, 0xe7, 0x14, 0xff, 00, 0x87, 0x99, 0xcf, 0xee, + 0xff, 00, 0x82, 0x7c, 0x93, 0x1f, 0xed, 0x2d, 0xe3, 0x38, + 0x98, 0x79, 0xb6, 0xb6, 0xd, 0xeb, 0x88, 0xc8, 0xcf, 0xeb, + 0x56, 0x97, 0xf6, 0xa4, 0xf1, 0xc, 0x6d, 0xfb, 0xcd, 0x32, + 0xd5, 0x87, 0xa0, 0x62, 0x2b, 0xea, 0x57, 0xf0, 0xb6, 0x92, + 0xff, 00, 0x7a, 0xc2, 0x3, 0xff, 00, 00, 0x15, 0x5e, + 0x4f, 0x3, 0xe8, 0x92, 0xfd, 0xed, 0x3a, 0x3, 0xff, 00, + 00, 0x15, 0x7f, 0xd8, 0x99, 0xe4, 0x7e, 0x1c, 0x7d, 0xfe, + 0x46, 0x9f, 0xea, 0xef, 0x11, 0x43, 0xe1, 0xcc, 0xdb, 0xf5, + 0x89, 0xf3, 0x74, 0x5f, 0xb5, 0x7e, 0xa2, 0xbf, 0xeb, 0x34, + 0x18, 0x9f, 0xe9, 0x71, 0x8f, 0xfd, 0x96, 0xae, 0x47, 0xfb, + 0x5b, 0xba, 0xf1, 0x27, 0x86, 0x49, 0xf7, 0x5b, 0xcf, 0xfe, + 0xc2, 0xbd, 0xea, 0x5f, 0x86, 0xbe, 0x1d, 0x94, 0x9d, 0xda, + 0x64, 0x1f, 0xf7, 0xcd, 0x54, 0x97, 0xe1, 0x27, 0x86, 0x65, + 0x1c, 0xe9, 0xb0, 0xfe, 0x55, 0x4b, 0x2e, 0xe2, 0x28, 0x7c, + 0x38, 0xb4, 0xfd, 0x62, 0x57, 0xf6, 0x57, 0x15, 0xd3, 0xf8, + 0x71, 0xd1, 0x7e, 0xb1, 0x3c, 0x62, 0x2f, 0xda, 0xe6, 0xdb, + 0xfe, 0x5a, 0x78, 0x6e, 0x75, 0xff, 00, 0x76, 0xe4, 0x1f, + 0xfd, 0x96, 0xac, 0xa7, 0xed, 0x71, 0xa4, 0xf1, 0xe6, 0x68, + 0x37, 0xcb, 0xfe, 0xec, 0x88, 0x7f, 0xa8, 0xaf, 0x52, 0x97, + 0xe0, 0x97, 0x86, 0x25, 0x7, 0xfe, 0x25, 0xf1, 0x2f, 0xd0, + 0x7f, 0xf5, 0xea, 0x9c, 0xdf, 00, 0x3c, 0x31, 0x2f, 0x4b, + 0x44, 0x5f, 0xcf, 0xfc, 0x6a, 0x5e, 0x1b, 0x89, 0xe3, 0xb5, + 0x78, 0x3f, 0x91, 0xf, 0x7, 0xc6, 0x51, 0xf8, 0x71, 0x30, + 0x7f, 0xf6, 0xea, 0x38, 0x28, 0xff, 00, 0x6b, 0x7f, 0xe, + 0x7f, 0x1e, 0x8f, 0xaa, 0x83, 0xfe, 0xca, 0xc4, 0x7f, 0xf6, + 0x71, 0x56, 0x22, 0xfd, 0xac, 0xbc, 0x29, 0x26, 0x73, 0xa7, + 0xea, 0xd1, 0xff, 00, 0xbd, 0x14, 0x5f, 0xfc, 0x72, 0xba, + 0x69, 0x7f, 0x67, 0xf, 0xd, 0x48, 0x4e, 0x22, 0xb, 0x9f, + 0xf7, 0xbf, 0xc6, 0xa9, 0x4f, 0xfb, 0x31, 0x78, 0x7e, 0x5e, + 0x87, 0x67, 0xfd, 0xf5, 0xff, 00, 0xc5, 0x56, 0x7c, 0xbc, + 0x59, 0x1f, 0xb5, 0x7, 0xf2, 0x46, 0x5c, 0xbc, 0x6f, 0xd, + 0xa7, 0x4d, 0xfc, 0x91, 0x56, 0xf, 0xda, 0x7f, 0xc2, 0x13, + 0x75, 0x5b, 0xd8, 0xff, 00, 0xdf, 0x48, 0xff, 00, 0xf8, + 0xba, 0xd3, 0x87, 0xf6, 0x88, 0xf0, 0x64, 0x9b, 0x4f, 0xf6, + 0x83, 0x26, 0x7b, 0x38, 0x51, 0x8f, 0xfc, 0x7a, 0xb2, 0x26, + 0xfd, 0x95, 0x34, 0x67, 0x3f, 0x2d, 0xc6, 0xdf, 0xc1, 0xbf, + 0xf8, 0xaa, 0xa7, 0x27, 0xec, 0x99, 0xa7, 0x36, 0x76, 0xdf, + 0xed, 0xff, 00, 0x80, 0x37, 0xff, 00, 0x15, 0x42, 0xaf, + 0xc5, 0x51, 0xde, 0x94, 0x1f, 0xf5, 0xea, 0x35, 0x8a, 0xe3, + 0x58, 0x6f, 0x46, 0x9c, 0xbf, 0xaf, 0x53, 0xb0, 0x87, 0xe3, + 0xc7, 0x82, 0x65, 0xc6, 0x75, 0xc8, 0x23, 0xe7, 0xf8, 0xcd, + 0x5f, 0x8b, 0xe3, 0xf, 0x83, 0xa7, 0x20, 0x26, 0xbf, 0x6a, + 0xd9, 0xe4, 0x61, 0x8f, 0xf8, 0x57, 0x9b, 0x49, 0xfb, 0x23, + 0xdb, 0x9f, 0xbb, 0xaa, 0x2f, 0xfd, 0xfb, 0x3f, 0xfc, 0x55, + 0x52, 0x97, 0xf6, 0x43, 0x6c, 0x9d, 0xba, 0xa8, 0x3f, 0xf6, + 0xcb, 0xff, 00, 0xb2, 0xad, 0x3f, 0xb4, 0x38, 0x9a, 0x3f, + 0x16, 0x16, 0x2f, 0xe7, 0xff, 00, 0x4, 0xd1, 0x66, 0xbc, + 0x61, 0xf, 0x8b, 0x5, 0x7, 0xf3, 0xff, 00, 0x82, 0x7b, + 0x1c, 0x3f, 0x12, 0x3c, 0x37, 0x71, 0xb7, 0xcb, 0xd5, 0xe0, + 0x7d, 0xdd, 0x31, 0x9e, 0x7f, 0x4a, 0xd0, 0x87, 0xc5, 0x1a, + 0x5d, 0xc2, 0xee, 0x8e, 0xf6, 0x36, 0x1e, 0xa3, 0x35, 0xe0, + 0x13, 0x7e, 0xc8, 0xd7, 0x63, 0x3b, 0x35, 0x24, 0x3f, 0xf6, + 0xc8, 0x7f, 0xf1, 0x55, 0x4a, 0x7f, 0xd9, 0x2f, 0x55, 0x4f, + 0xf5, 0x77, 0x8a, 0xc3, 0xfd, 0xc1, 0xff, 00, 0xc5, 0x53, + 0x59, 0xce, 0x7f, 0xf, 0x8b, 0x3, 0x7f, 0x49, 0x7f, 0xc3, + 0x8f, 0xfb, 0x7f, 0x89, 0xe1, 0xfc, 0x4c, 0xb1, 0x3f, 0x49, + 0x7f, 0xc3, 0x9f, 0x4d, 0xc5, 0x7b, 0xc, 0xcb, 0xb9, 0x25, + 0x56, 0x1e, 0xb9, 0xa9, 0x5, 0xc2, 0x7f, 0x7d, 0x7f, 0x3a, + 0xf9, 0x52, 0x4f, 0xd9, 0x5f, 0x5d, 0x8b, 0x94, 0x9c, 0x12, + 0x3d, 00, 0x1f, 0xfb, 0x35, 0x56, 0x7f, 0xd9, 0xbf, 0xc5, + 0x36, 0xe0, 0xf9, 0x73, 0x49, 0xff, 00, 0x1, 0x6c, 0x7f, + 0xec, 0xd4, 0xdf, 0x10, 0xe6, 0xb1, 0xf8, 0xb2, 0xe9, 0x7f, + 0xe0, 0x5f, 0xf0, 0x6, 0xf8, 0xab, 0x3a, 0x87, 0xc7, 0x95, + 0x4b, 0xff, 00, 0x2, 0xff, 00, 0xed, 0x4f, 0xad, 0x7e, + 0xd2, 0x9f, 0xde, 0x1f, 0x9d, 0x28, 0x9d, 0x4f, 0xf1, 0xf, + 0xce, 0xbe, 0x43, 0x3f, 0x3, 0x7c, 0x71, 0x6d, 0xcc, 0x77, + 0x17, 0xab, 0xfe, 0xe4, 0xd8, 0xff, 00, 0xd9, 0xea, 0xbc, + 0x9f, 0xa, 0xfe, 0x20, 0xdb, 0xfd, 0xdb, 0x9d, 0x4f, 0x8f, + 0x4b, 0x92, 0x3f, 0xf6, 0x7a, 0xcf, 0xfd, 0x69, 0xc6, 0x47, + 0xe3, 0xc0, 0x4f, 0xef, 0xff, 00, 0x80, 0x66, 0xf8, 0xd3, + 0x1f, 0xf, 0x8f, 0x2c, 0xa8, 0xbe, 0x7f, 0xf0, 0xf, 0xb1, + 0xbc, 0xc5, 0xf5, 0x1f, 0x9d, 0x2, 0x41, 0xd8, 0xd7, 0xc6, + 0x47, 0xc1, 0x3f, 0x12, 0x6d, 0x18, 0x15, 0xba, 0xd5, 0xce, + 0x3f, 0xe9, 0xe9, 0x88, 0xff, 00, 0xd0, 0xe9, 0x7e, 0xc7, + 0xf1, 0x42, 0xcd, 0x76, 0x8b, 0x9d, 0x4f, 0xfe, 0x4, 0xfb, + 0xbf, 0xad, 0x4f, 0xfa, 0xe1, 0x35, 0xf1, 0xe0, 0xe6, 0x89, + 0xff, 00, 0x5f, 0x27, 0x1f, 0xe2, 0x60, 0x2a, 0x2f, 0x91, + 0xf6, 0x76, 0xea, 0x37, 0x7d, 0x6b, 0xe3, 0x58, 0xfc, 0x43, + 0xf1, 0x56, 0xc8, 0x60, 0x5c, 0xdf, 00, 0x3f, 0xbd, 0x1a, + 0xb5, 0x48, 0xbf, 0x11, 0x7e, 0x2b, 0x5a, 0x1c, 0x8b, 0xdb, + 0xaf, 0xf8, 0x15, 0xac, 0x67, 0xff, 00, 0x65, 0xad, 0x17, + 0x19, 0xe1, 0xd7, 0xc7, 0x42, 0x6b, 0xe4, 0x69, 0x1f, 0x10, + 0x30, 0xbf, 0x6f, 0xd, 0x51, 0x7f, 0xdb, 0xa7, 0xd8, 0xdb, + 0xe8, 0xf3, 0x31, 0x5f, 0x1f, 0x2f, 0xc6, 0x4f, 0x89, 0xf0, + 0x5, 0x12, 0xcf, 0x33, 0xe3, 0xa9, 0xfb, 0x24, 0x63, 0x3f, + 0xf8, 0xed, 0x5a, 0x8b, 0xe3, 0xf7, 0x8f, 0x6d, 0xb1, 0xe7, + 0x43, 0x24, 0xbe, 0xb9, 0x89, 0x57, 0xff, 00, 0x64, 0xad, + 0x57, 0x1a, 0x65, 0xf7, 0xd6, 0x13, 0x5f, 0xf6, 0xe9, 0xba, + 0xf1, 0x7, 0x2b, 0xfb, 0x50, 0xa8, 0xbf, 0xed, 0xd3, 0xeb, + 0x7f, 0x32, 0x8f, 0x32, 0xbe, 0x55, 0x83, 0xf6, 0x97, 0xf1, + 0x54, 00, 0x79, 0xba, 0x57, 0x9b, 0x8e, 0xbb, 0x88, 0x5f, + 0xfd, 0x92, 0xaf, 0x47, 0xfb, 0x57, 0xeb, 0x31, 0x7f, 0xac, + 0xf0, 0xdc, 0x4f, 0xff, 00, 0x6f, 0x4, 0x7f, 0xec, 0xb5, + 0xd1, 0x1e, 0x30, 0xca, 0x9e, 0xf2, 0x6b, 0xfe, 0xdd, 0x67, + 0x54, 0x38, 0xf3, 0x24, 0x97, 0xc5, 0x39, 0x2f, 0x58, 0xcb, + 0xfc, 0x8f, 0xa7, 0x81, 0xf7, 0xa7, 0x6e, 0xaf, 0x99, 0xd3, + 0xf6, 0xb9, 0xbc, 0x1f, 0x7f, 0xc3, 0x2b, 0xf8, 0x5c, 0x9f, + 0xfe, 0x26, 0xa6, 0x4f, 0xda, 0xf3, 0x7, 0xf7, 0x9e, 0x1b, + 0x70, 0x3f, 0xd9, 0xb8, 0x1f, 0xe1, 0x5b, 0x2e, 0x2d, 0xc9, + 0xdf, 0xfc, 0xbe, 0xfc, 0x1f, 0xf9, 0x1d, 0xb, 0x8e, 0x72, + 0x1f, 0xf9, 0xff, 00, 0xff, 00, 0x92, 0xcb, 0xfc, 0x8f, + 0xa4, 0xb7, 0x51, 0xba, 0xbe, 0x74, 0x4f, 0xda, 0xf6, 0xcb, + 0xf8, 0xfc, 0x3b, 0x72, 0x3d, 0x71, 0x32, 0xff, 00, 0x85, + 0x58, 0x8f, 0xf6, 0xbc, 0xd2, 0x58, 0xfc, 0xda, 0x5, 0xea, + 0x7b, 0xf9, 0x8a, 0x45, 0x68, 0xb8, 0xab, 0x26, 0x7f, 0xf2, + 0xfd, 0x7d, 0xcf, 0xfc, 0x8d, 0x23, 0xc6, 0xd9, 0x4, 0xbf, + 0xe6, 0x25, 0x2f, 0x93, 0xff, 00, 0x23, 0xe8, 0x3d, 0xd4, + 0xbb, 0xab, 0xc1, 0x60, 0xfd, 0xad, 0x3c, 0x3f, 0x20, 0xfd, + 0xe6, 0x9b, 0x75, 0xf, 0xb3, 0x1c, 0xff, 00, 0x21, 0x5a, + 0x10, 0xfe, 0xd4, 0xfe, 0x11, 0x7f, 0xbe, 0xd3, 0x44, 0x7d, + 0xe3, 0x73, 0xfc, 0x92, 0xba, 0x23, 0xc4, 0x99, 0x44, 0xf6, + 0xc4, 0x44, 0xea, 0x87, 0x17, 0x64, 0x53, 0xdb, 0x15, 0x1f, + 0xcb, 0xf3, 0x3d, 0xab, 0x77, 0xd6, 0x8d, 0xd5, 0xe4, 0x90, + 0x7e, 0xd3, 0x5e, 0x5, 0x7f, 0xbf, 0xa9, 0x49, 0x1f, 0xfd, + 0xbb, 0x4c, 0x7f, 0x92, 0x55, 0xf8, 0xff, 00, 0x68, 0xcf, + 0x87, 0xf3, 0xc, 0xae, 0xbb, 0xc7, 0x4e, 0x6d, 0x27, 0x1f, + 0xfb, 0x25, 0x75, 0x47, 0x3b, 0xcb, 0x27, 0xb6, 0x22, 0x1f, + 0xf8, 0x12, 0xff, 00, 0x33, 0xb6, 0x1c, 0x45, 0x93, 0xcf, + 0xe1, 0xc5, 0xd3, 0xff, 00, 0xc0, 0xa3, 0xfe, 0x67, 0xa6, + 0x6e, 0xf7, 0xa7, 0x6, 0xe2, 0xb8, 0x8, 0x7e, 0x38, 0x78, + 0x2e, 0x70, 0xa, 0x6b, 0x48, 0x41, 0xf5, 0x86, 0x41, 0xff, + 00, 0xb2, 0xd6, 0x95, 0xbf, 0xc5, 0xf, 0xb, 0xdc, 0x1, + 0xb3, 0x59, 0xb7, 0x39, 0xf5, 0xc8, 0xfe, 0x62, 0xba, 0xa3, + 0x98, 0x60, 0xe7, 0xf0, 0xd6, 0x8b, 0xf9, 0xa3, 0xb6, 0x19, + 0xae, 0x2, 0xa6, 0x90, 0xaf, 0x7, 0xff, 00, 0x6f, 0x2f, + 0xf3, 0x3a, 0xdd, 0xd4, 0x6e, 0xac, 0x38, 0x3c, 0x63, 0xa1, + 0xce, 0x37, 0x26, 0xad, 0x67, 0x8f, 0x79, 0x94, 0x7f, 0x33, + 0x53, 0x8f, 0x13, 0x69, 0x2d, 0xd3, 0x53, 0xb3, 0x3f, 0xf6, + 0xdd, 0x7f, 0xc6, 0xba, 0x95, 0x6a, 0x4f, 0x55, 0x25, 0xf7, + 0xa3, 0xb5, 0x62, 0x28, 0xb5, 0x75, 0x35, 0xf7, 0x9a, 0xd9, + 0x14, 0x64, 0x56, 0x72, 0xeb, 0xba, 0x7b, 0xfd, 0xdb, 0xeb, + 0x66, 0xfa, 0x4a, 0xbf, 0xe3, 0x52, 0x2e, 0xa9, 0x68, 0xdd, + 0x2e, 0x61, 0x3f, 0x47, 0x14, 0xfd, 0xad, 0x3f, 0xe6, 0x45, + 0x2a, 0xd4, 0x9f, 0xda, 0x5f, 0x79, 0x77, 0x22, 0x8c, 0xe6, + 0xab, 0xb, 0xd8, 0x4f, 0x49, 0x50, 0xff, 00, 0xc0, 0x85, + 0x38, 0x5c, 0x46, 0x47, 0xe, 0xa7, 0xf1, 0xaa, 0xe7, 0x8f, + 0x72, 0xb9, 0xe2, 0xfa, 0x93, 0xd2, 0xe7, 0x15, 0x10, 0x91, + 0x4f, 0x46, 0x1f, 0x9d, 0x2e, 0xe1, 0xeb, 0x54, 0x9a, 0x65, + 0x5d, 0x12, 0x64, 0xd1, 0x93, 0x51, 0xe6, 0x8c, 0xd3, 0x19, + 0x26, 0x4d, 0x28, 0x39, 0xa8, 0xc1, 0xc5, 0x2e, 0xe3, 0x40, + 0x12, 0x51, 0x4c, 0xdd, 0xef, 0x4a, 0x1a, 0x80, 0x1d, 0x45, + 0x37, 0x26, 0x8c, 0x9a, 00, 0x75, 0x14, 0xdc, 0x9a, 0x37, + 0x50, 0x3, 0xb3, 0x46, 0x69, 0xbb, 0xa8, 0xdd, 0x40, 0xe, + 0xcd, 0x3, 0x83, 0x4d, 0xdd, 0xed, 0x4e, 0x7, 0x34, 00, + 0xec, 0x8a, 0x32, 0x29, 0xb4, 0x50, 0x3, 0xb2, 0x29, 0x69, + 0x94, 0xe0, 0x45, 00, 0x2d, 0x14, 0x99, 0x14, 0x66, 0x80, + 0x16, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, + 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, + 0x28, 0xa0, 0x2, 0x98, 0x79, 0xa7, 0x1a, 0x6d, 00, 0x14, + 0xd3, 0xd6, 0x82, 0x69, 0x9, 0xc5, 00, 0x23, 0x54, 0x6c, + 0x69, 0xc5, 0xaa, 0x36, 0x39, 0x14, 00, 0xd6, 0x3c, 0x54, + 0x4c, 0xd8, 0xef, 0x4a, 0xed, 0x8a, 0x82, 0x47, 0xa0, 0x1, + 0xde, 0xab, 0xdb, 0xcc, 0x97, 0x57, 0xa6, 0xdc, 0x1c, 0x95, + 0x19, 0x7e, 0x3a, 0xa, 0xe6, 0x3c, 0x71, 0xe3, 0x78, 0x7c, + 0x32, 0x2d, 0x2c, 0xe3, 0xd, 0x2e, 0xa9, 0xa8, 0xb1, 0x8a, + 0xd2, 0x24, 00, 0xe1, 0xb0, 0x49, 0x66, 0xc9, 0xfb, 0xa3, + 0x1d, 0x70, 0x6b, 0xa0, 0xf0, 0x65, 0x84, 0xd6, 0xb6, 0x11, + 0x9b, 0xa9, 0x3c, 0xeb, 0xb7, 0x1b, 0xe6, 0x94, 0x9c, 0xee, + 0x63, 0xd6, 0xb9, 0xd5, 0x55, 0x3a, 0x8e, 0x9c, 0x7a, 0x6e, + 0x72, 0xaa, 0xca, 0x75, 0x5d, 0x28, 0x74, 0xdf, 0xfc, 0x8e, + 0x9d, 00, 0x55, 0xa, 0x6, 00, 0xa7, 0x51, 0x45, 0x74, + 0x1d, 0x41, 0x45, 0x14, 0x50, 0x1, 0x45, 0x14, 0x84, 0xed, + 0x19, 0x34, 00, 0xb4, 0xdd, 0xe0, 0xe, 0x4e, 0x3e, 0xb5, + 0xe6, 0xdf, 0x12, 0xbf, 0x68, 0x2f, 0x8, 0xfc, 0x2b, 0xc, + 0x35, 0xab, 0xb7, 0xe, 0x17, 0x21, 0x61, 0xd8, 0x4f, 0xea, + 0xc3, 0xd2, 0xbe, 0x29, 0xf8, 0xb9, 0xff, 00, 0x5, 0x24, + 0xd0, 0xc5, 0xe5, 0xcc, 0x7a, 0x1d, 0xfd, 0xf2, 0xaa, 0xb1, + 0xb, 0x85, 0x8c, 0x7f, 0x27, 0x34, 0x1, 0xfa, 0x3a, 0x67, + 0x8d, 0x7a, 0xba, 0x8f, 0xc6, 0xa3, 0xfb, 0x7d, 0xbe, 0xec, + 0x79, 0xaa, 0x4f, 0xb5, 0x7e, 0x2b, 0x78, 0xab, 0xfe, 0xa, + 0x39, 0xe2, 0x47, 0x93, 0x16, 0xba, 0x9e, 0xa1, 0xb7, 0x9e, + 0x9b, 0x3f, 0xc6, 0xb4, 0x7e, 0x15, 0x7e, 0xdc, 0xde, 0x34, + 0xf1, 0x5e, 0xbf, 0x6d, 0x6d, 0xf6, 0xeb, 0xd7, 0x12, 0xc8, + 0x10, 0x67, 0x6f, 0x72, 0x7, 0x6a, 00, 0xfd, 0x9e, 0x57, + 0xc, 0x1, 0x1c, 0x83, 0xdc, 0x53, 0xab, 0x82, 0xf8, 0x47, + 0xaa, 0xde, 0xdd, 0xf8, 0xa, 0xc2, 0xff, 00, 0x55, 0x97, + 0xf7, 0xb2, 0xa0, 0x62, 0xce, 0xde, 0xc2, 0xaf, 0x5e, 0x7c, + 0x57, 0xf0, 0xcd, 0x85, 0xcb, 0x41, 0x36, 0xa5, 0x1a, 0xc8, + 0xa7, 0x4, 0x64, 0x7f, 0x8d, 00, 0x75, 0xf4, 0x57, 0x33, + 0xa7, 0xfc, 0x45, 0xd0, 0x35, 0x59, 0x44, 0x56, 0xda, 0x84, + 0x72, 0x39, 0xe8, 0x33, 0x5d, 0x22, 0x38, 0x75, 0xc, 0xa7, + 0x20, 0xd0, 0x3, 0xa9, 0x1, 0xa0, 0xd5, 0x3b, 0xed, 0x46, + 0x2b, 0x8, 0xcb, 0xc8, 0x7d, 0xea, 0x65, 0x25, 0x15, 0x77, + 0xb1, 0x12, 0x9c, 0x60, 0xb9, 0xa4, 0xec, 0x8b, 0x99, 0xa0, + 0x9a, 0xe5, 0x4f, 0x8f, 0x6c, 0xf7, 0x11, 0x86, 0xfd, 0x3f, + 0xc6, 0xa4, 0x1e, 0x39, 0xb2, 0xfe, 0xeb, 0x7e, 0x9f, 0xe3, + 0x5c, 0x5f, 0x5f, 0xc3, 0x7f, 0x3a, 0x3c, 0xf5, 0x99, 0xe1, + 0x1f, 0xfc, 0xbc, 0x47, 0x4d, 0x93, 0xe9, 0x46, 0x4f, 0xa5, + 0x73, 0x83, 0xc6, 0xf6, 0x27, 0xa8, 0x6f, 0xc8, 0x53, 0xc7, + 0x8d, 0x2c, 0x4f, 0xf7, 0xbf, 0x4a, 0xaf, 0xae, 0xe1, 0xdf, + 0xdb, 0x45, 0xac, 0xc3, 0xa, 0xf6, 0xa8, 0x8e, 0x83, 0x27, + 0xd2, 0x8c, 0xfb, 0x56, 0x12, 0xf8, 0xba, 0xc4, 0xf7, 0x6f, + 0xd2, 0x9e, 0x3c, 0x57, 0x62, 0x7f, 0x89, 0xbf, 0x4a, 0xaf, + 0xad, 0x50, 0x7f, 0x6d, 0x16, 0xb1, 0xb8, 0x77, 0xf6, 0xd1, + 0xb5, 0x9a, 0x33, 0x58, 0xeb, 0xe2, 0x7b, 0x33, 0xd1, 0x8d, + 0x3f, 0xfe, 0x12, 0x3b, 0x43, 0xfc, 0x66, 0xab, 0xeb, 0x14, + 0xbf, 0x99, 0x14, 0xb1, 0x54, 0x1f, 0xdb, 0x46, 0xae, 0x45, + 0x19, 0xac, 0xc1, 0xaf, 0xda, 0x1f, 0xe3, 0xa7, 0x8d, 0x6a, + 0xd8, 0xff, 00, 0x1f, 0xeb, 0x55, 0xed, 0xa9, 0xbf, 0xb4, + 0x8b, 0x58, 0x8a, 0x4f, 0xed, 0x23, 0x42, 0x8c, 0xd5, 0x11, + 0xab, 0x5b, 0x9e, 0x92, 0xa, 0x94, 0x6a, 0x10, 0xb7, 0xfc, + 0xb4, 0x1f, 0x9d, 0x5a, 0xa9, 0x7, 0xb3, 0x2d, 0x55, 0xa6, + 0xf6, 0x92, 0x2c, 0xd2, 0xd4, 0x31, 0xce, 0x8e, 0x7e, 0x56, + 0x7, 0xf1, 0xa9, 0x7a, 0xd5, 0xa7, 0x7d, 0x8d, 0x13, 0x4f, + 0x61, 0x68, 0xa2, 0x8a, 0x63, 0xa, 0x28, 0xa2, 0x80, 0xa, + 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, + 0x80, 0xa, 0x28, 0xa2, 0x80, 0x13, 0x9f, 0x5a, 0x31, 0x4b, + 0x45, 00, 0x26, 0x28, 0xc5, 0x2d, 0x14, 00, 0x98, 0xa3, + 0x1e, 0xf4, 0xb4, 0x50, 0x2, 0x51, 0x4b, 0x45, 0x2b, 00, + 0x52, 0x52, 0xd1, 0x4c, 0x4, 0xc5, 0x18, 0x34, 0xb4, 0x50, + 0x2, 0x62, 0x80, 0x29, 0x68, 0xa0, 0x4, 0xc5, 0x2d, 0x14, + 0x50, 0x2, 0x62, 0x8c, 0x52, 0xd1, 0x40, 0xd, 0xdb, 0x46, + 0xda, 0x75, 0x14, 00, 0x98, 0xa4, 0x2a, 0xd, 0x3a, 0x8a, + 00, 0x69, 0x40, 0x69, 0x3c, 0xa5, 0xee, 0xa0, 0xfe, 0x14, + 0xfa, 0x28, 0x15, 0x91, 0x19, 0xb7, 0x8c, 0xff, 00, 0x2, + 0xfe, 0x54, 0xc3, 0x65, 0x3, 0x7f, 0xcb, 0x25, 0xfc, 0xaa, + 0x7a, 0x4a, 0x9e, 0x48, 0xbe, 0x84, 0xb8, 0x45, 0xee, 0x8a, + 0xad, 0xa5, 0x5a, 0x3f, 0x58, 0x10, 0xfe, 0x15, 0xb, 0xf8, + 0x7f, 0x4f, 0x7e, 0xb6, 0xc9, 0xf9, 0x56, 0x8d, 0x15, 0xe, + 0x95, 0x37, 0xbc, 0x57, 0xdc, 0x66, 0xe8, 0x52, 0x96, 0xf1, + 0x5f, 0x71, 0x8f, 0x27, 0x84, 0xb4, 0xa9, 0x47, 0xcd, 0x68, + 0x86, 0xaa, 0x49, 0xf0, 0xff, 00, 0x44, 0x97, 0xad, 0x9a, + 0xfe, 0x66, 0xba, 0x3a, 0x2b, 0x27, 0x84, 0xc3, 0xcb, 0x78, + 0x2f, 0xb8, 0xc2, 0x58, 0x1c, 0x2c, 0xfe, 0x2a, 0x51, 0x7f, + 0x24, 0x72, 0x52, 0xfc, 0x2f, 0xd0, 0x25, 0xeb, 0x66, 0x3f, + 0x33, 0x54, 0xe6, 0xf8, 0x37, 0xe1, 0xb9, 0xba, 0xda, 0x11, + 0xff, 00, 0x2, 0x35, 0xdc, 0xd1, 0x5c, 0xf2, 0xcb, 0x70, + 0x52, 0xde, 0x94, 0x7e, 0xe4, 0x73, 0x4b, 0x28, 0xcb, 0xe7, + 0xf1, 0x50, 0x8f, 0xdc, 0x8f, 0x38, 0x97, 0xe0, 0x37, 0x86, + 0x26, 0xeb, 0x6e, 0xc3, 0xe8, 0xd5, 0x4a, 0x6f, 0xd9, 0xd7, + 0xc2, 0xf2, 0x9f, 0xf5, 0x72, 0xf, 0xf8, 0x15, 0x7a, 0xa5, + 0x15, 0xcf, 0x2c, 0x97, 0x2e, 0x96, 0xf4, 0x23, 0xf7, 0x1c, + 0xb2, 0xe1, 0xec, 0xaa, 0x7b, 0xe1, 0xe3, 0xf7, 0x1e, 0x3b, + 0x3f, 0xec, 0xc7, 0xe1, 0x99, 0x7a, 0x34, 0xab, 0x54, 0xe5, + 0xfd, 0x95, 0xfc, 0x3e, 0xe7, 0x8b, 0xa9, 0x97, 0xf0, 0x15, + 0xed, 0xd4, 0x84, 0x66, 0xb9, 0xa5, 0xc3, 0xb9, 0x54, 0xb7, + 0xa0, 0x8e, 0x49, 0xf0, 0xae, 0x4b, 0x3f, 0x8b, 0xd, 0x1f, + 0xc4, 0xf0, 0x69, 0x7f, 0x64, 0xed, 0x15, 0x8f, 0xcb, 0xa8, + 0xce, 0x3f, 0xe0, 0x22, 0xa9, 0x4b, 0xfb, 0x24, 0x69, 0xcd, + 0x9d, 0xba, 0xac, 0xff, 00, 0xf7, 0xca, 0xd7, 0xd0, 0xbc, + 0x51, 0x8a, 0xe7, 0x97, 0xb, 0xe5, 0x12, 0xde, 0x82, 0xfb, + 0xdf, 0xf9, 0x9c, 0xb2, 0xe0, 0xbc, 0x86, 0x7b, 0xe1, 0x97, + 0xde, 0xff, 00, 0xcc, 0xf9, 0xbe, 0x6f, 0xd9, 0x16, 0x6, + 0xfb, 0x9a, 0xb4, 0x83, 0xea, 0x8b, 0x54, 0xe5, 0xfd, 0x91, + 0x25, 0x1f, 0x73, 0x56, 0x6c, 0xfb, 0xa0, 0xff, 00, 0x1a, + 0xfa, 0x73, 0x6, 0x8c, 0x1a, 0xe7, 0x7c, 0x21, 0x93, 0xcb, + 0xfe, 0x5d, 0x7e, 0x2c, 0xe5, 0x97, 0x2, 0x64, 0x32, 0xff, + 00, 0x97, 0x1f, 0x8b, 0xff, 00, 0x33, 0xe5, 0x89, 0xbf, + 0x64, 0x7d, 0x47, 0x9d, 0x9a, 0x92, 0x1f, 0xaa, 0x8f, 0xf1, + 0xaa, 0x72, 0x7e, 0xc9, 0x7a, 0xd8, 0xce, 0xdb, 0xe8, 0xdb, + 0xea, 0x3f, 0xfb, 0x2a, 0xfa, 0xcf, 0x6, 0x97, 0x15, 0x83, + 0xe0, 0xcc, 0xa1, 0xed, 0x6, 0xbe, 0x6c, 0xe6, 0x97, 0x87, + 0xd9, 0x13, 0xda, 0x9b, 0x5f, 0xf6, 0xf3, 0x3e, 0x41, 0x93, + 0xf6, 0x53, 0xf1, 0x22, 0x67, 0x6d, 0xd2, 0x1f, 0xc7, 0x1f, + 0xd6, 0xaa, 0xcb, 0xfb, 0x2e, 0xf8, 0xb2, 0x3f, 0xba, 0xe8, + 0xc3, 0xda, 0x40, 0x3f, 0xad, 0x7d, 0x8f, 0xc5, 0x18, 0x15, + 0x9b, 0xe0, 0xbc, 0xb3, 0xec, 0xb9, 0x2f, 0xfb, 0x78, 0xc5, + 0xf8, 0x7b, 0x94, 0x7d, 0x97, 0x35, 0xff, 00, 0x6f, 0x1f, + 0x17, 0xbf, 0xec, 0xdf, 0xe3, 0x3b, 0x66, 0xc, 0x80, 0x12, + 0x39, 0x4, 0x4a, 0x3f, 0xc6, 0x88, 0xbe, 0x9, 0xfc, 0x40, + 0xb0, 0x25, 0xa2, 0xca, 0xb7, 0xb4, 0x88, 0x7f, 0x9d, 0x7d, + 0xa0, 00, 0xa3, 0x68, 0xf4, 0xa8, 0xff, 00, 0x53, 0x30, + 0x6b, 0xe1, 0xab, 0x35, 0xff, 00, 0x6f, 0x19, 0xff, 00, + 0xc4, 0x3e, 0xc0, 0x47, 0xe0, 0xad, 0x51, 0x7f, 0xdb, 0xc7, + 0xc6, 0x91, 0xf8, 0x2b, 0xe2, 0x95, 0x82, 0xe2, 0x39, 0xa5, + 0x45, 0xf4, 0x6, 0x3f, 0xf0, 0xa9, 0x52, 0xf, 0x8b, 0x96, + 0x3f, 0x72, 0xf6, 0xe1, 0x78, 0xc7, 0x1e, 0x57, 0xf8, 0x57, + 0xd8, 0xa5, 0x17, 0xb8, 0x14, 0xd3, 0x14, 0x67, 0xaa, 0x3, + 0xf8, 0x51, 0xfe, 0xa9, 0x28, 0xff, 00, 0xf, 0x15, 0x51, + 0x7c, 0xc6, 0xb8, 0x1a, 0x30, 0xfe, 0x1e, 0x36, 0xaa, 0xff, + 00, 0xb7, 0x8f, 0x90, 0x7, 0x88, 0x7e, 0x2f, 0xdb, 0xc, + 0x35, 0xf5, 0xc3, 0xe3, 0xfb, 0xc2, 0x2a, 0x90, 0x7c, 0x44, + 0xf8, 0xaf, 0x69, 0xf7, 0xdc, 0xbf, 0xfb, 0xca, 0xbf, 0xd0, + 0xd7, 0xd7, 0x26, 0xce, 0x16, 0xeb, 0x12, 0x1f, 0xc2, 0xa3, + 0x3a, 0x6d, 0xa3, 0xe7, 0x75, 0xbc, 0x67, 0xfe, 0x2, 0x29, + 0xff, 00, 0xab, 0x58, 0xb8, 0xfc, 0x18, 0xe9, 0xfd, 0xe3, + 0xff, 00, 0x53, 0xf1, 0xb1, 0xfe, 0x1e, 0x63, 0x53, 0xe6, + 0xdb, 0x3e, 0x4f, 0x5f, 0x8d, 0x1f, 0x13, 0x6d, 0x7e, 0xfd, + 0xad, 0xbb, 0xf7, 0xf9, 0x93, 0x3f, 0xc9, 0xaa, 0x55, 0xfd, + 0xa2, 0xbe, 0x21, 0xdb, 0xc, 0x3e, 0x97, 0x60, 0xff, 00, + 0xef, 0xc4, 0xff, 00, 0xd1, 0xeb, 0xea, 0x67, 0xd0, 0xb4, + 0xf6, 0xfb, 0xd6, 0x90, 0x9f, 0xf8, 00, 0xa8, 0x24, 0xf0, + 0xae, 0x95, 0x27, 0xde, 0xb0, 0x80, 0xff, 00, 0xc0, 0x5, + 0x3f, 0xec, 0x2c, 0xd6, 0x1f, 0x6, 0x3a, 0x5f, 0x31, 0xff, + 00, 0xab, 0x59, 0xd5, 0x3f, 0xe1, 0xe6, 0x52, 0xf9, 0xa3, + 0xe6, 0x31, 0xfb, 0x50, 0x78, 0xd9, 0x8, 0xdf, 0xa1, 0xd8, + 0x37, 0xae, 0x12, 0x41, 0xff, 00, 0xb3, 0x54, 0xb1, 0xfe, + 0xd5, 0xbe, 0x27, 0x8d, 0xbf, 0x7b, 0xe1, 0xcb, 0x46, 0xf5, + 0xda, 0xec, 0xbf, 0xe3, 0x5f, 0x48, 0x3f, 0x82, 0x34, 0x29, + 0x3e, 0xf6, 0x99, 0x6e, 0x7f, 0xe0, 0x2, 0xab, 0xc9, 0xf0, + 0xe3, 0xc3, 0x72, 0x7d, 0xed, 0x22, 0xd8, 0xff, 00, 0xc0, + 0x29, 0x3c, 0xa7, 0x3f, 0x5f, 0xe, 0x3b, 0xf0, 0x5f, 0xe4, + 0x4b, 0xc8, 0xb8, 0x9e, 0x3f, 0x6, 0x65, 0xf7, 0xc5, 0x7f, + 0x91, 0xe0, 0x3, 0xf6, 0xb9, 0xd6, 0x14, 0x9f, 0x33, 0xc2, + 0x90, 0x9f, 0xa5, 0xd1, 0x1f, 0xfb, 0x25, 0x4c, 0xbf, 0xb6, + 0x15, 0xe2, 0xfd, 0xff, 00, 0x8, 0x2e, 0x3d, 0xb5, 0xf, + 0xfe, 0xd7, 0x5e, 0xe1, 0x27, 0xc2, 0x8f, 0xa, 0xcb, 0xf7, + 0xb4, 0x5b, 0x63, 0xff, 00, 0x1, 0xaa, 0x33, 0xfc, 0x16, + 0xf0, 0x84, 0xe3, 0x7, 0x45, 0xb7, 0xff, 00, 0xbe, 0x6b, + 0x37, 0x96, 0xf1, 0x34, 0x7e, 0x1c, 0x64, 0x5f, 0xaa, 0x5f, + 0xfc, 0x89, 0x93, 0xca, 0x78, 0xc2, 0x3f, 0x6, 0x61, 0x17, + 0xeb, 0x15, 0xff, 00, 0xc8, 0x9e, 0x57, 0x63, 0xfb, 0x60, + 0xd9, 0xc9, 0x26, 0x2f, 0x34, 0x7, 0xb5, 0x4f, 0xef, 0x25, + 0xc9, 0x7f, 0xd3, 0x60, 0xae, 0x9a, 0xcb, 0xf6, 0xad, 0xf0, + 0x2c, 0xe1, 0x7e, 0xd1, 0x75, 0x73, 0x68, 0xc7, 0xae, 0xfb, + 0x77, 0x60, 0x3f, 0x10, 0x2b, 0x57, 0x50, 0xfd, 0x9c, 0xfc, + 0x23, 0x78, 0xa7, 0x6d, 0x84, 0x71, 0xe7, 0xfb, 0xb9, 0x1f, + 0xd6, 0xbc, 0xff, 00, 0x5f, 0xfd, 0x92, 0xac, 0xe6, 0x2e, + 0x6c, 0xa5, 0x8e, 0x20, 0x7e, 0xee, 0xf9, 0x1b, 0xfc, 0xd, + 0x45, 0xf8, 0xa7, 0xb, 0xbb, 0x85, 0x4f, 0x97, 0xf9, 0x58, + 0x94, 0xf8, 0xd3, 0x7, 0xf1, 0x3a, 0x75, 0x7e, 0x56, 0x7f, + 0x85, 0x8f, 0x65, 0xf0, 0xaf, 0xc4, 0xff, 00, 0xd, 0x78, + 0xca, 0x2f, 0x33, 0x4a, 0xd5, 0x23, 0xb8, 0x5f, 0xf6, 0xd5, + 0xa3, 0xff, 00, 0xd0, 0x80, 0xae, 0xa5, 0x64, 0xe, 0xa0, + 0x82, 0x8, 0x3d, 0xc1, 0xaf, 0x8c, 0x35, 0x6f, 0xd9, 0x47, + 0xc4, 0x56, 0x13, 0x79, 0xba, 0x7d, 0xf5, 0x90, 0x75, 0x39, + 0x56, 0x13, 0x3a, 0x90, 0x7d, 0xbe, 0x4a, 0x65, 0xb4, 0xbf, + 0x1a, 0xbe, 0x1c, 0xb6, 0xe8, 0x75, 0x99, 0x75, 0xb, 0x54, + 0xeb, 0xc, 0x8d, 0xe7, 0x82, 0x7, 0x60, 0x5d, 0x9, 0x1f, + 0x85, 0x7a, 0x14, 0x33, 0xcc, 0x75, 0x25, 0x6c, 0x76, 0x16, + 0x4b, 0xce, 0x3a, 0xa3, 0xd4, 0xc3, 0x71, 0x1e, 0x63, 0x45, + 0x5b, 0x32, 0xc1, 0x49, 0x79, 0xc7, 0x55, 0xf7, 0x1f, 0x69, + 0x86, 0xa7, 0x3, 0x8a, 0xf9, 0x87, 0x44, 0xfd, 0xb4, 0x2c, + 0xb4, 0x9b, 0x6f, 0x27, 0xc5, 0xfe, 0x1e, 0xd4, 0xed, 0x2f, + 0x81, 0xc1, 0x6b, 0x18, 0x55, 0xe3, 0xc7, 0xa9, 0x2c, 0xea, + 0x7f, 0x21, 0x5e, 0xdb, 0xe0, 0xf, 0x8a, 0xde, 0x1a, 0xf8, + 0x99, 0x63, 0xf6, 0x9d, 0x3, 0x53, 0x8a, 0xeb, 0x3, 0xe7, + 0x80, 0xb0, 0x59, 0x93, 0xfd, 0xe4, 0xea, 0x2b, 0xe8, 0xf0, + 0xb9, 0x9e, 0x13, 0x16, 0xf9, 0x69, 0x4f, 0x5e, 0xdb, 0x3f, + 0xb8, 0xfa, 0xcc, 0x1e, 0x6f, 0x82, 0xc7, 0xbe, 0x5a, 0x15, + 0x13, 0x97, 0x67, 0xa3, 0xfb, 0x99, 0xd9, 0x6e, 0xa3, 0x75, + 0x47, 0xbe, 0x80, 0xd5, 0xea, 0x1e, 0xc9, 0x26, 0x79, 0xa5, + 0xa6, 0xe7, 0x14, 0x64, 0xd0, 0x3, 0xa8, 0x1c, 0x1a, 0x40, + 0x73, 0x4b, 0x40, 0xe, 0xdd, 0x40, 0x39, 0xa6, 0xe6, 0x8c, + 0xe2, 0x80, 0x1f, 0x45, 0x37, 0x26, 0x9d, 0x40, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, + 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x21, + 0xa5, 0xa6, 0x50, 0x1, 0x45, 0x14, 0xd2, 0x68, 0x1, 0xac, + 0x69, 0x28, 0x63, 0x4c, 0x26, 0x80, 0x1a, 0xe7, 0x2, 0xa2, + 0x62, 0x69, 0xce, 0x6a, 0x17, 0x6e, 0xb4, 00, 0xc7, 0x7a, + 0xab, 0x3c, 0xdb, 0x15, 0x98, 0xf4, 0x3, 0x9a, 0x91, 0xdb, + 0xad, 0x78, 0x47, 0xed, 0x61, 0xf1, 0x36, 0x2f, 0x5, 0xf8, + 0xe, 0x4d, 0x26, 0x19, 0x88, 0xd4, 0xf5, 0x85, 0x68, 0x22, + 0x11, 0xb8, 0xc, 0x89, 0xc6, 0xe6, 0xf5, 0x1d, 0x7a, 0x8a, + 0xe4, 0xc5, 0xe2, 0x23, 0x85, 0xa3, 0x2a, 0xd3, 0xd9, 0x2b, + 0x9c, 0x58, 0xdc, 0x54, 0x30, 0x58, 0x79, 0xd7, 0x9e, 0xd1, + 0x46, 0x47, 0xc3, 0x6f, 0x11, 0xbf, 0xc5, 0xdf, 0x89, 0xba, + 0x9f, 0x89, 0x58, 0xee, 0xd2, 0xec, 0xcf, 0x91, 0xa7, 0xa3, + 0x64, 0xed, 0x5e, 0x85, 0xb1, 0x92, 0x1, 0x38, 0xec, 0x6b, + 0xe9, 0x9d, 0x2b, 0x9, 0x1a, 0x8e, 0xb5, 0xe0, 0x1f, 0xb3, + 0x67, 0x86, 0x1b, 0x43, 0xf0, 0x45, 0x80, 0x74, 0xda, 0xf2, + 0x2e, 0xf3, 0xc7, 0x3d, 0x4d, 0x7d, 0x9, 0xa7, 0x47, 0x85, + 0x15, 0xc7, 0x95, 0xc2, 0x4b, 0xc, 0xa7, 0x53, 0xe2, 0x96, + 0xaf, 0xe6, 0x79, 0xf9, 0x2d, 0x39, 0xc7, 0x8, 0xaa, 0x55, + 0xf8, 0xa7, 0xef, 0x3f, 0x56, 0x5f, 0xa2, 0x8a, 0x2b, 0xd7, + 0x3d, 0xd0, 0xa2, 0x8a, 0x28, 0x1, 0x9, 0xc0, 0x24, 0xf4, + 0x15, 0xe0, 0xbf, 0xb4, 0xe7, 0xed, 0x9, 0x63, 0xf0, 0x97, + 0xc2, 0x17, 0x73, 0xc5, 0x31, 0x37, 0x4a, 0x8c, 0x7f, 0x76, + 0xc0, 0x11, 0xc1, 0xff, 00, 0x68, 0x7a, 0x57, 0xa3, 0xfc, + 0x59, 0xf1, 0xd5, 0xaf, 0x80, 0xbc, 0x11, 0xa9, 0x6a, 0x77, + 0x2e, 0xa9, 0xe5, 0xc4, 0x76, 0xe5, 0xc2, 0xf3, 0x8f, 0x5a, + 0xfc, 0x27, 0xfd, 0xa8, 0x7f, 0x68, 0xab, 0xdf, 0x88, 0x5a, + 0xd6, 0xa1, 0x1c, 0x57, 0x72, 0x49, 0xb, 0x4a, 0xca, 0x7, + 0x9a, 0x4a, 0xe3, 0x26, 0x80, 0x13, 0xf6, 0x85, 0xfd, 0xab, + 0xb5, 0x6f, 0x89, 0x5a, 0xcc, 0xa7, 0xed, 0x37, 0x4a, 0x87, + 0x70, 0x1b, 0xe4, 0x3e, 0xa7, 0xfd, 0xa3, 0x5f, 0x36, 0xdc, + 0x6a, 0x57, 0x37, 0x32, 0xb3, 0xbc, 0xf2, 0x12, 0xc7, 0x27, + 0x2e, 0x69, 0x16, 0x39, 0x6f, 0xa6, 0x3, 0x25, 0x9d, 0x8f, + 0x15, 0xd1, 0xc1, 0xf0, 0xdb, 0x57, 0x9e, 0xdc, 0x4c, 0xb0, + 0xbe, 0xc2, 0x33, 0x9d, 0x94, 0x1, 0xcb, 0x99, 0x64, 0x73, + 0xcb, 0xb1, 0xfa, 0x9a, 0xfa, 0x9f, 0xf6, 0x2f, 0xf0, 0x43, + 0x78, 0x87, 0xc7, 0xda, 0x34, 0x64, 0x67, 0xf7, 0xea, 0xc4, + 0x63, 0xaf, 0xcc, 0x3d, 0xab, 0xe6, 0x27, 0xd3, 0x65, 0xb6, + 0xbf, 0x5b, 0x67, 0x1f, 0x3e, 0xec, 0x60, 0x8a, 0xfd, 0x2c, + 0xff, 00, 0x82, 0x69, 0xfc, 0x3e, 0x7b, 0xff, 00, 0x18, + 0x5a, 0xde, 0x34, 0x79, 0x8e, 0x2, 0x18, 0x9f, 0x2f, 0x3d, + 0x30, 0x7a, 0xd0, 0x7, 0xe8, 0xb7, 0xc4, 0x3b, 0xc1, 0xe0, + 0x3f, 0x85, 0x1, 0x91, 0x8c, 0x9, 0x6b, 0x69, 0xd2, 0x33, + 0xb7, 0x90, 0x9f, 0x85, 0x7e, 0x42, 0xf8, 0xf3, 0xf6, 0xb3, + 0xd4, 0x1b, 0xc6, 0x3a, 0x97, 0x97, 0xa8, 0xdc, 0x4, 0x8e, + 0x67, 0x40, 0x4, 0xa7, 0xb1, 0x3f, 0xed, 0xd7, 0xeb, 0x1f, + 0xed, 0x6b, 0x30, 0x8b, 0xe1, 0x35, 0xf4, 0xa, 0x76, 0xb4, + 0x88, 0xcb, 0x80, 0x39, 0x23, 0x69, 0xaf, 0xc0, 0x2f, 0x8b, + 0xda, 0x7a, 0x69, 0x7e, 0x28, 0xb8, 0x8d, 0x7e, 0xf3, 0xbb, + 0x31, 0x20, 0x63, 0xb9, 0xcd, 00, 0x7e, 0x80, 0xfe, 0xc9, + 0xdf, 0x1e, 0x35, 0xf, 0x17, 0xf8, 0xa0, 0x99, 0x6f, 0xe7, + 0x9a, 0x35, 0x60, 0x36, 0xb4, 0xa4, 0x8e, 0x87, 0xde, 0xbf, + 0x55, 0x7c, 0x2d, 0x70, 0xd7, 0x7a, 0x25, 0xbc, 0xcd, 0x9c, + 0xb8, 0xcf, 0x35, 0xf8, 0x7d, 0xfb, 0x9, 0xdb, 0xb2, 0xeb, + 0xf6, 0xb0, 0xaf, 0x2d, 0x24, 0x80, 0x9f, 0x41, 0xd7, 0xad, + 0x7e, 0xe3, 0xf8, 0x7e, 0xd4, 0xd9, 0x68, 0xd6, 0x90, 0x9c, + 0xe5, 0x50, 0x3, 0x91, 0x8a, 00, 0xd0, 0x6e, 0x95, 0xe7, + 0x7f, 0x11, 0x75, 0x77, 0xb6, 0xb7, 0x70, 0xad, 0x83, 0x5e, + 0x81, 0x3b, 0x6c, 0x8d, 0x9b, 0xd0, 0x57, 0x8b, 0xfc, 0x49, + 0xbf, 0xf3, 0x64, 0xf2, 0xc1, 0xce, 0x5b, 0xfc, 0x6b, 0xe7, + 0x33, 0xda, 0xee, 0x86, 0x15, 0xd9, 0xee, 0x7c, 0x9f, 0x12, + 0xe2, 0x5e, 0x1f, 0x5, 0x2b, 0x3d, 0x59, 0xc6, 0x2e, 0xab, + 0x73, 0x92, 0x77, 0x75, 0xfa, 0xff, 00, 0x8d, 0x48, 0x35, + 0x9b, 0x91, 0xdf, 0xf5, 0x35, 0x54, 0xc, 0xa, 0x2b, 0xf2, + 0x25, 0x52, 0xa7, 0xf3, 0x33, 0xf0, 0x95, 0x56, 0xaf, 0xf3, + 0x32, 0xe2, 0xeb, 0x97, 00, 0x75, 0x3f, 0x99, 0xa7, 0xaf, + 0x88, 0x2e, 0x7, 0x73, 0xf9, 0x9a, 0xa1, 0x46, 0x2a, 0xbd, + 0xb5, 0x55, 0xb4, 0x8b, 0x58, 0x8a, 0xcb, 0xed, 0x33, 0x4c, + 0x78, 0x96, 0xe0, 0x7f, 0x7b, 0xf3, 0x34, 0xe5, 0xf1, 0x44, + 0xe3, 0xfb, 0xdf, 0x99, 0xac, 0xac, 0x51, 0x8a, 0xb5, 0x89, + 0xae, 0xbe, 0xd1, 0x6b, 0x17, 0x88, 0x5b, 0x4c, 0xd8, 0x5f, + 0x15, 0xcc, 0x3f, 0xbd, 0xf9, 0xff, 00, 0xf5, 0xea, 0x41, + 0xe2, 0xd9, 0x47, 0x76, 0xfc, 0xff, 00, 0xfa, 0xf5, 0x84, + 0x54, 0x1a, 0x36, 0x8f, 0x4a, 0xa5, 0x8b, 0xae, 0xbe, 0xd1, + 0x6b, 0x1d, 0x89, 0x5f, 0x6c, 0xe8, 0x47, 0x8c, 0x64, 0x1f, + 0xc4, 0xdf, 0x9f, 0xff, 00, 0x5e, 0xa5, 0x4f, 0x19, 0x38, + 0x3f, 0x78, 0xfe, 0x7f, 0xfd, 0x7a, 0xe6, 0x76, 0x8f, 0x4a, + 0x36, 0x8a, 0xb5, 0x8e, 0xc4, 0xaf, 0xb4, 0x6a, 0xb3, 0x1c, + 0x5a, 0xfb, 0x47, 0x56, 0x9e, 0x34, 0x60, 0x7e, 0xf3, 0x7e, + 0x7f, 0xfd, 0x7a, 0xb5, 0x17, 0x8e, 0x88, 0xc7, 0xcc, 0x7f, + 0x3f, 0xfe, 0xbd, 0x71, 0x3b, 0x5, 0x1e, 0x58, 0xad, 0x56, + 0x65, 0x89, 0x8f, 0x53, 0x68, 0xe6, 0xf8, 0xc8, 0xed, 0x23, + 0xd3, 0xf4, 0xef, 0x88, 0x8, 0xae, 0x32, 0x49, 0xfc, 0x7f, + 0xfa, 0xf5, 0xd6, 0xe9, 0xfe, 0x38, 0xb7, 0xb8, 00, 0x30, + 0x3f, 0x86, 0x3f, 0xc6, 0xbc, 0x11, 0x54, 0x29, 0xcf, 0x15, + 0x7a, 0xd7, 0x56, 0x6b, 0x43, 0xc6, 0x78, 0xf4, 0x35, 0xec, + 0x61, 0x78, 0x82, 0xbd, 0x2d, 0x27, 0xb1, 0xef, 0x60, 0xf8, + 0xa3, 0x13, 0x45, 0xda, 0xa6, 0xc7, 0xd1, 0x96, 0x5a, 0x94, + 0x57, 0xbf, 0x72, 0xad, 0xe6, 0xbc, 0x5b, 0xc3, 0x9e, 0x39, + 0x78, 0x1d, 0x54, 0x96, 0x1d, 0xba, 0xd7, 0xaa, 0x68, 0x5a, + 0xba, 0x6a, 0x76, 0xaa, 0xfb, 0x86, 0x48, 0xaf, 0xbe, 0xcb, + 0xf3, 0x3a, 0x58, 0xd8, 0xe8, 0xf5, 0x3f, 0x4e, 0xca, 0xf3, + 0x8a, 0x39, 0x84, 0x6c, 0x9f, 0xbc, 0x6b, 0xd1, 0x48, 0xd, + 0x2d, 0x7b, 0x67, 0xd1, 0x5, 0x21, 0x1d, 0xe9, 0x69, 0xd, + 00, 0x41, 0x75, 0x38, 0xb5, 0xb7, 0x79, 0x5b, 0xa2, 0x8c, + 0xd7, 0x1b, 0x37, 0x8e, 0x76, 0xcc, 0x40, 0x3c, 0x3, 0x8e, + 0xbf, 0xfd, 0x7a, 0xd6, 0xf1, 0xcd, 0xe1, 0xb3, 0xd0, 0x6e, + 0x58, 0x1c, 0x1d, 0x87, 0x1c, 0xe2, 0xbc, 0x5, 0xef, 0xae, + 0x19, 0xf3, 0xbc, 0xfe, 0x75, 0xf1, 0xb9, 0xde, 0x6b, 0x2c, + 0xd, 0x48, 0xd3, 0xa6, 0x7e, 0x7f, 0xc4, 0x59, 0xdc, 0xf2, + 0xea, 0xd0, 0xa5, 0x4f, 0xaa, 0xb9, 0xed, 0x2b, 0xe3, 0xa0, + 0x7f, 0xfd, 0x7f, 0xfd, 0x7a, 0x95, 0x7c, 0x72, 0xa7, 0xaf, + 0xf3, 0xff, 00, 0xeb, 0xd7, 0x89, 0xb, 0xfb, 0x81, 0xfc, + 0x44, 0xfe, 0x34, 0xf1, 0xa9, 0xdc, 0xe, 0xe7, 0xf3, 0xaf, + 0x9d, 0x5c, 0x47, 0x58, 0xf9, 0x58, 0xf1, 0x66, 0x21, 0x6e, + 0x7b, 0x7a, 0xf8, 0xe2, 0x3c, 0x74, 0xff, 00, 0x3f, 0x9d, + 0x48, 0xbe, 0x35, 0x88, 0xf5, 0x5c, 0xff, 00, 0x9f, 0xad, + 0x78, 0x77, 0xf6, 0xc5, 0xc0, 0xee, 0x7f, 0x3a, 0x72, 0xeb, + 0x77, 0x3, 0xb9, 0x3f, 0x8d, 0x6c, 0xb8, 0x96, 0xa2, 0xdc, + 0xe8, 0x8f, 0x17, 0x55, 0x5b, 0x9e, 0xe8, 0xbe, 0x33, 0x83, + 0xfb, 0x9f, 0xe7, 0xf3, 0xa9, 0x57, 0xc5, 0xd6, 0xe7, 0xf8, + 0x4f, 0xe7, 0x5e, 0x12, 0x3c, 0x41, 0x38, 0xf5, 0xfc, 0xe9, + 0xe3, 0xc4, 0x57, 0xb, 0xd8, 0xfe, 0x75, 0xb2, 0xe2, 0x69, + 0x75, 0xfc, 0x8d, 0xe3, 0xc6, 0x13, 0x5b, 0xfe, 0x47, 0xbb, + 0x8f, 0x15, 0xdb, 0x9e, 0xc7, 0xf3, 0xa7, 0xf, 0x13, 0xdb, + 0x13, 0xd0, 0xfe, 0x75, 0xe1, 0x23, 0xc4, 0xd3, 0xe, 0xc7, + 0xf3, 0xa7, 0x8f, 0x14, 0xcc, 0x3f, 0xbd, 0xff, 00, 0x7d, + 0x56, 0xab, 0x89, 0xbb, 0x9b, 0xae, 0x30, 0xef, 0xf9, 0x1e, + 0xee, 0xbe, 0x22, 0xb6, 0x6f, 0xff, 00, 0x58, 0xa9, 0x6, + 0xbb, 0x6c, 0x7b, 0xfe, 0xb5, 0xe1, 0xb, 0xe2, 0xb9, 0x3d, + 0x5b, 0xf3, 0xa9, 0x17, 0xc5, 0xce, 0xbd, 0xdb, 0xf3, 0xad, + 0x97, 0x13, 0x47, 0xaa, 0x37, 0x8f, 0x17, 0xc3, 0xaa, 0x3d, + 0xd9, 0x75, 0xab, 0x73, 0xfc, 0x42, 0x9e, 0x35, 0x5b, 0x7f, + 0xef, 0xd7, 0x85, 0x2f, 0x8c, 0x1b, 0xfb, 0xcc, 0x3f, 0xe0, + 0x55, 0x2a, 0xf8, 0xcc, 0xff, 00, 0x7c, 0xfe, 0x75, 0xb2, + 0xe2, 0x4a, 0x6f, 0xa1, 0xd1, 0x1e, 0x2e, 0xa5, 0xd5, 0x1e, + 0xe4, 0x35, 0x28, 0xf, 0xf1, 0x8a, 0x78, 0xbe, 0x84, 0xff, + 00, 0x18, 0xfc, 0xeb, 0xc3, 0x97, 0xc6, 0xb8, 0xff, 00, + 0x96, 0x84, 0x7f, 0xc0, 0xaa, 0x55, 0xf1, 0xbf, 0xfd, 0x35, + 0x3f, 0xf7, 0xd5, 0x6c, 0xb8, 0x8e, 0x8f, 0x53, 0x78, 0xf1, + 0x66, 0x1d, 0xee, 0x7b, 0x70, 0xbb, 0x88, 0xff, 00, 0x10, + 0xa7, 0x79, 0xe8, 0x7f, 0x8c, 0x57, 0x8a, 0x47, 0xe3, 0x8f, + 0xfa, 0x6a, 0x7f, 0xef, 0xaa, 0x98, 0x78, 0xeb, 0x8e, 0x24, + 0x3f, 0xf7, 0xd5, 0x6a, 0xb8, 0x87, 0xe, 0xf7, 0x37, 0x5c, + 0x53, 0x85, 0x67, 0xb3, 0xab, 0x6, 0xe8, 0x41, 0xfa, 0x53, + 0xab, 0x85, 0xf0, 0x7e, 0xb8, 0xda, 0x88, 0xdd, 0xb8, 0x90, + 0x7d, 0xeb, 0xb9, 0x1d, 0x2b, 0xe8, 0x30, 0xb8, 0x98, 0xe2, + 0xa9, 0xaa, 0x91, 0x3e, 0xa7, 0x7, 0x8b, 0x86, 0x32, 0x92, + 0xab, 0xd, 0x85, 0xa2, 0x8a, 0x2b, 0xb0, 0xee, 0xa, 0x28, + 0xa2, 0x80, 0xa, 0x28, 0xa4, 0xcd, 00, 0x2d, 0x15, 0x1b, + 0x4e, 0x89, 0xf7, 0x98, 0x2f, 0xd4, 0xd6, 0x7d, 0xee, 0xbf, + 0x6d, 0x68, 0xa4, 0xf9, 0x8a, 0x7f, 0xe0, 0x55, 0x9c, 0xea, + 0x42, 0xa, 0xf2, 0x66, 0x55, 0x2a, 0xc2, 0x92, 0xbc, 0xdd, + 0x8d, 0x3c, 0xd2, 0x71, 0x5c, 0x7c, 0xfe, 0x3e, 0xb6, 0x84, + 0xfa, 0xe3, 0xde, 0xb3, 0x6e, 0xbe, 0x29, 0x5b, 0xc7, 0xc0, + 0x1c, 0xfb, 0x1f, 0xfe, 0xb5, 0x79, 0xb3, 0xcd, 0x30, 0x94, + 0xfe, 0x29, 0x9e, 0x45, 0x4c, 0xeb, 0x3, 0x4b, 0xe2, 0xa8, + 0x8f, 0x42, 0xc8, 0xa3, 0x2b, 0x5e, 0x5c, 0xff, 00, 0x14, + 0xa1, 0x63, 0xd7, 0x1f, 0x56, 0xa5, 0x4f, 0x89, 0xb0, 0x13, + 0xcb, 0x7f, 0xe3, 0xd5, 0xca, 0xf3, 0xbc, 0x25, 0xed, 0xcc, + 0x71, 0x7f, 0xac, 0x79, 0x7d, 0xfe, 0x33, 0xd4, 0x73, 0x46, + 0x6b, 0xcc, 0xd3, 0xe2, 0x5d, 0xb1, 0xfe, 0x3f, 0xfc, 0x7a, + 0xaf, 0x5a, 0xfc, 0x48, 0xb4, 0x63, 0x82, 0xe3, 0xfe, 0xfa, + 0xad, 0xa3, 0x9b, 0xe1, 0x24, 0xed, 0xce, 0x6f, 0xc, 0xfb, + 0x3, 0x37, 0x65, 0x34, 0x77, 0xf4, 0x57, 0x37, 0x6d, 0xe3, + 0x9b, 0xb, 0x8c, 0x7c, 0xe0, 0x7e, 0x35, 0xa7, 0x6, 0xbb, + 0x69, 0x3f, 0xdd, 0x90, 0x67, 0xeb, 0x5e, 0x84, 0x31, 0x54, + 0x6a, 0x7c, 0x12, 0x4c, 0xf5, 0xa9, 0xe3, 0x30, 0xf5, 0x7e, + 0x9, 0xa6, 0x68, 0xd1, 0x4c, 0x49, 0x4, 0x8a, 0xa, 0xf2, + 0x29, 0xd9, 0xae, 0x9b, 0x9d, 0x82, 0xd1, 0x48, 0xd, 0x2d, + 0x30, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, + 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, + 0x80, 0xa, 0x29, 0x28, 0xa0, 0x5, 0xa2, 0x92, 0x82, 0x71, + 0x40, 0xb, 0x45, 0x34, 0xb6, 0x29, 0x72, 0x3d, 0x68, 0xb, + 0x8b, 0x45, 0x26, 0xe1, 0x46, 0xea, 00, 0x5a, 0x29, 0x37, + 0x52, 0x6e, 0xa0, 0x7, 0x51, 0x4d, 0xdd, 0x4b, 0x9a, 00, + 0x5a, 0x64, 0x8b, 0xb9, 0x69, 0xf4, 0x8d, 0xf7, 0x4d, 00, + 0x62, 0x5e, 0xc4, 0xa4, 0x1c, 0x81, 0x5c, 0xae, 0xaf, 0x65, + 0x1c, 0x81, 0x83, 0x28, 0x61, 0xe8, 0x45, 0x75, 0xd7, 0xfd, + 0xe, 0x2b, 0x9c, 0xd4, 0x30, 0x43, 0x52, 0xb2, 0x64, 0xb8, + 0xa7, 0xb9, 0xe4, 0x7e, 0x30, 0xf8, 0x77, 0xa3, 0x6b, 0x91, + 0xc8, 0x27, 0xb2, 0x83, 0x79, 0xfe, 0x31, 0x1a, 0xe7, 0xf9, + 0x57, 0x89, 0x6a, 0xbf, 0xa, 0xf5, 0xbf, 0x4, 0x5f, 0xb6, + 0xa9, 0xe1, 0x1d, 0x72, 0xe7, 0x4a, 0x9d, 0x48, 0x72, 0x90, + 0xc8, 0xc8, 0xaf, 0x8e, 0x81, 0x82, 0x81, 0xb8, 0x75, 0xe0, + 0xfa, 0xd7, 0xd3, 0x9a, 0xb4, 0x63, 0xe6, 0xae, 0x23, 0x59, + 0x88, 0x10, 0xdc, 0x57, 0x95, 0x88, 0xcb, 0x30, 0xd8, 0x87, + 0xcc, 0xe3, 0x69, 0x77, 0x5a, 0x33, 0xc5, 0xc5, 0x64, 0xf8, + 0x4c, 0x53, 0xe7, 0x70, 0xb4, 0xbb, 0xad, 0x1a, 0xf9, 0xa3, + 0x53, 0xe0, 0x57, 0xed, 0x27, 0xff, 00, 0x9, 0x6d, 0xfd, + 0xaf, 0x84, 0x7c, 0x4b, 0x69, 0x2d, 0xa7, 0x8a, 0x15, 0x8, + 0x13, 0xa8, 0x2, 0x1b, 0x8d, 0xa3, 0x92, 0x37, 0x36, 0xec, + 0xfe, 0x1e, 0xb5, 0xef, 0xe1, 0xab, 0xe1, 0x8f, 0x1a, 0xe9, + 0xb, 0x75, 0x19, 0x96, 0xde, 0x46, 0xb2, 0xbe, 0x89, 0x83, + 0xc1, 0x77, 0x9, 0x2b, 0x2c, 0x4c, 0xf, 0xc, 0xac, 0x30, + 0x41, 0xfa, 0x1a, 0xf6, 0x1f, 0x82, 0x3f, 0xb4, 0x62, 0xea, + 0x4f, 0x67, 0xe1, 0x8f, 0x16, 0x3a, 0xdb, 0xea, 0xaa, 0x8b, + 0x14, 0x3a, 0x94, 0xb3, 0xd, 0x97, 0x67, 0x80, 0x1, 0xc8, + 0xe1, 0xcf, 0xb9, 0x39, 0xf5, 0xad, 0xa8, 0x3a, 0x94, 0x7f, + 0x77, 0x59, 0xdd, 0x74, 0x7f, 0xe7, 0xe6, 0x74, 0x61, 0xdd, + 0x6c, 0x3a, 0xf6, 0x55, 0xdf, 0x37, 0x67, 0xfe, 0x7e, 0x67, + 0xd1, 0x1, 0xb3, 0x4b, 0x9a, 0x84, 0x3e, 0x71, 0x8a, 0x7e, + 0xea, 0xf4, 0xf, 0x50, 0x95, 0x4d, 0x2e, 0x7d, 0xea, 0x30, + 0x78, 0xa7, 0x29, 0x19, 0xa0, 0x9, 0x16, 0x96, 0x99, 0x9a, + 0x51, 0xd6, 0x80, 0x1d, 0x4b, 0x9f, 0x7a, 0x4c, 0xd1, 0x40, + 0xe, 0x1d, 0x29, 0x69, 0x99, 0xa7, 0x2d, 00, 0x2d, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, + 0x5, 0x14, 0x52, 0x1e, 0x94, 00, 0x99, 0xe2, 0x92, 0x8a, + 0x28, 00, 0x35, 0x1b, 0x74, 0xa7, 0xb5, 0x46, 0xc6, 0x80, + 0x10, 0xb0, 0xc5, 0x46, 0xcd, 0x4a, 0xd5, 0x13, 0x9c, 0x66, + 0x80, 0x1b, 0x23, 0x75, 0xaa, 0xf2, 0x36, 0x33, 0x4f, 0x76, + 0xe2, 0xab, 0xc8, 0xdd, 0x68, 0x2, 0x29, 0x5f, 00, 0xf3, + 0x5f, 0x5, 0xfe, 0xd1, 0x5a, 0xd5, 0xcf, 0x8f, 0x7f, 0x68, + 0x57, 0xd1, 0x5b, 0x1e, 0x46, 0x95, 0xb2, 0xd5, 0x14, 0xc, + 0x75, 0x1, 0xc9, 0xfa, 0xfc, 0xc3, 0xf2, 0xaf, 0xbb, 0x66, + 0x94, 0x20, 0x66, 0x62, 0x15, 0x40, 0xc9, 0x24, 0xf0, 0x2b, + 0xe1, 0xbf, 0x1, 0x45, 0xff, 00, 0xb, 0x7, 0xf6, 0x8c, + 0xf1, 0x6, 0xb0, 0x47, 0x9f, 0x1a, 0xde, 0x38, 0x2e, 0x40, + 0x1f, 0x74, 0x6c, 0xed, 0xfe, 0xe5, 0x7c, 0xa7, 0x10, 0x5e, + 0xac, 0x29, 0x61, 0xd7, 0xdb, 0x92, 0x5f, 0x23, 0xe2, 0x78, + 0xa1, 0x3a, 0xd4, 0xe8, 0x61, 0x62, 0xff, 00, 0x89, 0x34, + 0xbe, 0x47, 0xd8, 0xde, 0x4, 0xd2, 0x57, 0x4e, 0xd3, 0x2d, + 0xa0, 0x51, 0x80, 0x88, 0x5, 0x7a, 0x15, 0xaa, 0x6d, 0x5a, + 0xe6, 0xf4, 0xb, 0x7d, 0xb1, 0x20, 0xc5, 0x75, 0x31, 0x2e, + 0xd4, 0x2, 0xbe, 0xa2, 0x11, 0xe5, 0x8a, 0x8a, 0xe8, 0x7d, + 0x95, 0x38, 0xa8, 0x41, 0x45, 0x74, 0x1f, 0x45, 0x14, 0x55, + 0x9a, 0x5, 0x47, 0x34, 0xa2, 0x18, 0xd9, 0xdb, 0x85, 0x51, + 0x92, 0x6a, 0x4a, 0xe6, 0x3e, 0x22, 0xeb, 0x23, 0x42, 0xf0, + 0x96, 0xa1, 0x73, 0xbb, 0x61, 0x11, 0xf0, 0xde, 0x94, 0x1, + 0xf0, 0x77, 0xfc, 0x14, 0x3f, 0xf6, 0x80, 0x7d, 0x3b, 0xc1, + 0xd7, 0x9a, 0x4c, 0x13, 0x84, 0x32, 0x12, 0xa0, 0x1, 0xec, + 0x7f, 0xd9, 0xf7, 0xaf, 0xc7, 0xc9, 0x5a, 0x5d, 0x4e, 0xe4, + 0xb7, 0x2f, 0x23, 0xb1, 0x3d, 0x7b, 0x93, 0x5f, 0x52, 0xfe, + 0xdb, 0xfe, 0x3c, 0x9b, 0x5d, 0xf1, 0x2c, 0xb6, 0xc6, 0x66, + 0x60, 0x5c, 0x9c, 0x10, 0x3f, 0xc2, 0xbc, 0x8f, 0xe0, 0x5f, + 0x81, 0x8f, 0x8b, 0xbc, 0x4f, 0xa6, 0xdb, 0xf9, 0x3e, 0x68, + 0x96, 0xe1, 0x17, 0x6f, 0xaf, 0xcc, 0x28, 0x3, 0xe8, 0x4f, + 0xd9, 0x6b, 0xf6, 0x2a, 0x9f, 0xe2, 0x85, 0xb5, 0xae, 0xa1, + 0x71, 0x6b, 0x23, 0xa1, 0x61, 0xca, 0xb8, 0x3, 0xa0, 0xff, + 00, 0x68, 0x7a, 0xd7, 0xd2, 0x5f, 0x19, 0x7f, 0x65, 0x2b, + 0xf, 0x85, 0x3e, 0xb, 0xbd, 0xb9, 0x31, 0x1d, 0xd0, 0xc2, + 0x39, 0x66, 0xe3, 0xb7, 0xfb, 0x46, 0xbe, 0xe4, 0xfd, 0x9f, + 0x3e, 0x18, 0xd8, 0x7c, 0x3d, 0xf8, 0x73, 0xa5, 0x42, 0x96, + 0xe8, 0x93, 0x98, 0x83, 0xb1, 0x5c, 0xf1, 0xf2, 0x8e, 0x3f, + 0x4a, 0xf9, 0x37, 0xfe, 0xa, 0x3d, 0xf1, 0x23, 0xfb, 0x23, + 0xc1, 0x97, 0xf6, 0xa9, 0x3e, 0x1a, 0x4e, 0x2, 0xf1, 0x8e, + 0xa3, 0xaf, 0x14, 0x1, 0xf9, 0x24, 0x90, 0xd, 0x53, 0xc7, + 0x13, 0x84, 0x19, 0x41, 0x27, 0x6, 0xbf, 0x67, 0x3f, 0xe0, + 0x9b, 0xde, 0x2, 0xfe, 0xc6, 0xf0, 0x6c, 0xba, 0x9c, 0x91, + 0xec, 0x69, 0x14, 0xed, 0xe7, 0x3d, 0xc7, 0xbd, 0x7e, 0x3d, + 0xfc, 0x18, 0xd2, 0x9f, 0xc4, 0x3e, 0x30, 0xc6, 0x3, 0xbb, + 0x48, 0xb9, 0x3f, 0x52, 0x6b, 0xfa, 00, 0xfd, 0x98, 0x7c, + 0x28, 0x9e, 0x12, 0xf8, 0x53, 0xa6, 0x44, 0x63, 0x11, 0xb3, + 0xc6, 0x18, 0x9c, 0xf5, 0xa0, 0xe, 0x37, 0xf6, 0xc5, 0xd7, + 0x56, 0xd7, 0xc2, 0x33, 0x40, 0xc7, 0x2a, 0xb0, 0xb3, 0x10, + 0x3e, 0x8d, 0x5f, 0x83, 0x7f, 0x15, 0xf5, 0x31, 0xac, 0x78, + 0xea, 0xfe, 0x45, 0x70, 0xe8, 0x25, 0x65, 0x18, 0x18, 0x3, + 0xe6, 0x35, 0xfa, 0xe3, 0xfb, 0x7f, 0x7c, 0x48, 0x8b, 0x4f, + 0xd1, 0xb5, 0x18, 0xc4, 0xcd, 0xfe, 0xad, 0x94, 0x28, 0x3, + 0x9e, 0x1a, 0xbf, 0x1a, 0xae, 0x26, 0x3a, 0x86, 0xab, 0x34, + 0xa7, 0x96, 0x92, 0x46, 0x73, 0xf8, 0x9c, 0xd0, 0x7, 0xdd, + 0xff, 00, 0xf0, 0x4d, 0x8f, 0xd, 0xbe, 0xbf, 0xe3, 0xd8, + 0x5c, 0xa9, 0x31, 0xc0, 0xc8, 0x33, 0xd8, 0x70, 0xdc, 0xf5, + 0xe6, 0xbf, 0x6a, 0x14, 00, 0xa0, 0xe, 0x95, 0xf9, 0xa3, + 0xff, 00, 0x4, 0xaa, 0xf8, 0x78, 0x6d, 0x74, 0x9b, 0x8d, + 0x5e, 0x58, 0x40, 0x62, 0xc0, 0x86, 0x24, 0xf1, 0xf7, 0xbf, + 0x33, 0x5f, 0xa5, 0xdd, 0xa8, 0x2, 0x9e, 0xaf, 0x37, 0x93, + 0x66, 0xe7, 0xda, 0xbc, 0x7, 0xc5, 0xf7, 0x66, 0xeb, 0x53, + 0x61, 0x9c, 0x85, 0x27, 0x8a, 0xf6, 0xaf, 0x16, 0xde, 0xb, + 0x7b, 0x27, 0xfa, 0x57, 0x80, 0xdf, 0xcb, 0xe7, 0xdf, 0xca, + 0xfd, 0x7e, 0x63, 0x5f, 0x9d, 0xf1, 0x3d, 0x7b, 0xf2, 0xd2, + 0x4c, 0xfc, 0xa7, 0x8c, 0xb1, 0x3a, 0xc2, 0x8a, 0x21, 0xa2, + 0x8a, 0x2b, 0xe0, 0xf, 0xcc, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x82, 0x1, 0xa2, 0x8a, + 00, 0x54, 0x95, 0xa0, 0x39, 0x5e, 0x2b, 0xb9, 0xf0, 0x47, + 0x89, 0x25, 0x8a, 0x54, 0x49, 0x1f, 0xb, 0xf4, 0xae, 0x16, + 0xa6, 0xb3, 0x9d, 0xa0, 0x9d, 0x48, 0x62, 0x6, 0x7b, 0x57, + 0x6e, 0xf, 0x11, 0x2c, 0x2d, 0x55, 0x38, 0xb3, 0xd0, 0xc0, + 0x63, 0x27, 0x82, 0xad, 0x1a, 0x91, 0x67, 0xd2, 0xf6, 0x17, + 0x49, 0x77, 0x2, 0xba, 0x9c, 0xf1, 0x56, 0x6b, 0x8c, 0xf0, + 0x26, 0xaa, 0x2f, 0x2d, 0x95, 0x1, 0xc8, 00, 0x57, 0x64, + 0x39, 0xaf, 0xda, 0xf0, 0xb5, 0xd6, 0x22, 0x8c, 0x6a, 0x2e, + 0xa7, 0xf4, 0x3e, 0xb, 0x10, 0xb1, 0x54, 0x23, 0x55, 0x75, + 0x16, 0x90, 0xd2, 0xd3, 0x58, 0xe0, 0x57, 0x59, 0xdc, 0x70, + 0x5f, 0x14, 0x2e, 0xf6, 0x69, 0x72, 0xc7, 0x9e, 0xa3, 0xa5, + 0x78, 0xc5, 0x7a, 0x37, 0xc5, 0x2d, 0x43, 0x7c, 0xc2, 0x20, + 0x7e, 0xa0, 0x57, 0x9c, 0xd7, 0xe3, 0xf9, 0xf5, 0x6f, 0x6b, + 0x8c, 0x69, 0x74, 0x3f, 0x5, 0xe2, 0x6a, 0xfe, 0xdb, 0x30, + 0x95, 0xba, 0x68, 0x14, 0x51, 0x45, 0x7c, 0xe9, 0xf2, 0x81, + 0x8a, 0x28, 0xa2, 0x90, 0x5, 0x18, 0xa2, 0x8a, 00, 0x36, + 0x8a, 0x4d, 0xa3, 0xd2, 0x96, 0x8a, 0x34, 0x16, 0x82, 0x6d, + 0x1e, 0x94, 0x6c, 0x1e, 0x94, 0xb4, 0x51, 0x64, 0x16, 0x42, + 0x6c, 0x14, 0x6c, 0x5f, 0x4a, 0x5a, 0x29, 0x59, 0x5, 0x90, + 0x86, 0x35, 0x34, 0x9e, 0x58, 0xf5, 0xa7, 0x51, 0x47, 0x2a, + 0x15, 0x90, 0xdf, 0x2c, 0x53, 0x5a, 0x2c, 0xf4, 0x26, 0xa4, + 0xa9, 0x6d, 0x13, 0xcc, 0xbb, 0x85, 0x3a, 0xe5, 0x80, 0xc5, + 0x35, 0x14, 0xda, 0x43, 0x50, 0x4e, 0x49, 0x1e, 0xb7, 0xf0, + 0xe7, 0x4e, 0xf2, 0x6d, 0x90, 0x90, 0x6b, 0xd1, 0x6b, 0x9b, + 0xf0, 0x75, 0xa7, 0x93, 0x62, 0xa4, 0x8e, 0xd5, 0xd2, 0xd7, + 0xed, 0xf9, 0x6d, 0x2f, 0x63, 0x86, 0x8c, 0x4f, 0xe8, 0xcc, + 0x9e, 0x82, 0xc3, 0xe0, 0xe1, 0x5, 0xd8, 0x28, 0xa2, 0x8a, + 0xf5, 0xf, 0x68, 0x29, 0x29, 0x7, 0xad, 0x50, 0xd5, 0x75, + 0x58, 0xb4, 0xf8, 0x19, 0x99, 0xc0, 0x6c, 0x74, 0xa8, 0x9c, + 0xe3, 0x8, 0xb9, 0x4b, 0x64, 0x67, 0x52, 0xa4, 0x69, 0xc5, + 0xca, 0x6e, 0xc9, 0x16, 0xe6, 0x99, 0x6d, 0xd4, 0xb3, 0x1c, + 0x57, 0x3d, 0xaa, 0xf8, 0xca, 0xd6, 0xce, 0x36, 0x1, 0x86, + 0xef, 0xaf, 0xff, 00, 0x5a, 0xb8, 0x6f, 0x11, 0xfc, 0x44, + 0x79, 0x19, 0xa3, 0x47, 0x6c, 0x67, 0x1c, 0xa, 0xe1, 0xaf, + 0xf5, 0x49, 0x2f, 0x98, 0xb6, 0xe3, 0xcd, 0x7c, 0x56, 0x3f, + 0x88, 0xa1, 0x4e, 0xf0, 0xa1, 0xab, 0x3f, 0x3b, 0xcc, 0xf8, + 0xaa, 0x14, 0xaf, 0xc, 0x36, 0xac, 0xed, 0x75, 0x8f, 0x1d, + 0x4a, 0xe4, 0xf9, 0x4f, 0x8a, 0xe4, 0xaf, 0x3c, 0x4f, 0x7b, + 0x70, 0x4e, 0x5e, 0xb2, 0x40, 0x3d, 0xcd, 0x2d, 0x7c, 0x2e, + 0x23, 0x30, 0xc4, 0x62, 0x1d, 0xe5, 0x26, 0x7e, 0x6f, 0x89, + 0xcd, 0x71, 0x58, 0xa7, 0x79, 0x49, 0xa2, 0xc3, 0x6a, 0x97, + 0xf, 0xf7, 0x8d, 0x42, 0xd2, 0xb4, 0x87, 0x2d, 0x4d, 0xa2, + 0xbc, 0xf7, 0x29, 0x4b, 0x76, 0x79, 0x6e, 0x53, 0x97, 0xc4, + 0xee, 0x18, 0x14, 0x9b, 0x45, 0x2d, 0x15, 0x36, 0x44, 0xd8, + 0x4d, 0xb4, 0xe4, 0x25, 0xf, 0x4, 0x8a, 0x4a, 0x28, 0xb0, + 0x6d, 0xa9, 0x76, 0xdf, 0x53, 0x6b, 0x72, 0xe, 0xe3, 0xc5, + 0x6d, 0x69, 0xfe, 0x31, 0x6b, 0x77, 0x1f, 0x35, 0x73, 0x18, + 0x6, 0x80, 00, 0x3d, 0x2b, 0xae, 0x9e, 0x26, 0xb5, 0x1f, + 0x85, 0x9d, 0xb4, 0x71, 0xb5, 0xe8, 0x3b, 0xc1, 0x9e, 0xc5, + 0xa1, 0xf8, 0xf8, 0x4c, 0x8a, 0xa5, 0x86, 0x2b, 0xb5, 0xd3, + 0xf5, 0x15, 0xbe, 0x40, 0x46, 0x2b, 0xe6, 0xfb, 0x7d, 0x46, + 0x4b, 0x56, 0x1b, 0x7b, 0x57, 0x63, 0xe1, 0xbf, 0x18, 0xcd, + 0x13, 0x28, 0x66, 0x2a, 0x3f, 0xa, 0xfb, 0x4c, 0xb7, 0x88, + 0x1b, 0x6a, 0x15, 0x99, 0xfa, 0x1e, 0x53, 0xc5, 0xf, 0x99, + 0x53, 0xc4, 0x33, 0xdb, 0x47, 0x4a, 0x5a, 0xc5, 0xd1, 0x75, + 0xa8, 0xef, 0x62, 0x5c, 0xc9, 0x92, 0x6b, 0x60, 0x73, 0xcd, + 0x7e, 0x81, 0x4e, 0xac, 0x6a, 0xc7, 0x9a, 0x27, 0xea, 0x14, + 0xaa, 0xc2, 0xb4, 0x54, 0xe0, 0xf4, 0x1d, 0x45, 0x14, 0x56, + 0xa6, 0xc1, 0x45, 0x14, 0x50, 0x1, 0x45, 0x14, 0x50, 0x1, + 0x45, 0x14, 0x86, 0x80, 0x16, 0x8a, 0x8a, 0x59, 0x56, 0x24, + 0x2c, 0xe7, 00, 0x56, 0xe, 0xa7, 0xe2, 0xfb, 0x4b, 0x35, + 0x23, 0x7f, 0x22, 0xb0, 0xab, 0x5e, 0x9d, 0x15, 0x79, 0xbb, + 0x1c, 0xd5, 0xb1, 0x14, 0xb0, 0xea, 0xf5, 0x25, 0x63, 0xa0, + 0x67, 0x3, 0xa9, 0xc5, 0x50, 0xbe, 0xd5, 0xe2, 0xb2, 0x42, + 0x4b, 0x2, 0x45, 0x79, 0x9e, 0xad, 0xe3, 0xb6, 0x77, 0x6f, + 0x26, 0x43, 0x5c, 0x96, 0xa3, 0xe2, 0xbb, 0xcb, 0x96, 0x3f, + 0xbc, 0x62, 0x3f, 0xa, 0xf9, 0x6c, 0x57, 0x11, 0x51, 0xa5, + 0x75, 0x5, 0x76, 0x7c, 0x5e, 0x37, 0x8a, 0xb0, 0xf4, 0x13, + 0x8d, 0x35, 0x76, 0x7a, 0xec, 0xde, 0x3a, 0x86, 0x2c, 0xf4, + 0xaa, 0x13, 0xfc, 0x4a, 0x86, 0x3e, 0x32, 0x33, 0xf4, 0x35, + 0xe4, 0x7, 0x56, 0x9d, 0xc7, 0x24, 0x9a, 0x85, 0xee, 0x5d, + 0xfa, 0xe6, 0xbe, 0x6e, 0xa7, 0x12, 0x62, 0x1f, 0xc0, 0x7c, + 0x9d, 0x5e, 0x2d, 0xc4, 0xbf, 0x80, 0xf5, 0x79, 0xbe, 0x27, + 0xa1, 0x3f, 0x7c, 0xf, 0xc3, 0xff, 00, 0xad, 0x51, 0xaf, + 0xc4, 0x98, 0xcf, 0xf1, 0x8f, 0xf3, 0xf8, 0x57, 0x94, 0x75, + 0xa4, 0xdb, 0x5c, 0x8f, 0x3f, 0xc6, 0x37, 0x7b, 0x9e, 0x7b, + 0xe2, 0x7c, 0x7b, 0x77, 0xb9, 0xeb, 0xab, 0xf1, 0x1a, 0x1f, + 0xef, 0xff, 00, 0x3a, 0xb3, 0xf, 0xc4, 0x48, 0x1b, 0xab, + 0x8f, 0xd7, 0xfc, 0x2b, 0xc6, 0x76, 0xfb, 0xd2, 0x8c, 0x8e, + 0xe6, 0xaa, 0x3c, 0x43, 0x8b, 0x46, 0x91, 0xe2, 0x9c, 0x6c, + 0x5e, 0xb6, 0x3d, 0xe2, 0xd3, 0xc7, 0x36, 0x8f, 0xf7, 0x9c, + 0x67, 0xf1, 0xff, 00, 0xa, 0xd5, 0x83, 0xc4, 0xf6, 0x53, + 0x8e, 0x24, 0xc7, 0xe7, 0x5f, 0x3c, 0x45, 0x72, 0xf1, 0xff, + 00, 0x11, 0xad, 0xb, 0x6d, 0x75, 0xa0, 0xc6, 0x5d, 0x85, + 0x7a, 0x94, 0x38, 0x9a, 0xa2, 0xd2, 0x69, 0x1e, 0xce, 0x1f, + 0x8c, 0x2a, 0xad, 0x2a, 0x45, 0x1f, 0x41, 0xa6, 0xad, 0x6d, + 0x27, 0x49, 0x33, 0x56, 0x52, 0x55, 0x7e, 0x41, 0xcd, 0x78, + 0x4d, 0x9f, 0x8c, 0x4c, 0x4c, 0x33, 0x23, 0x7e, 0x55, 0xd8, + 0xe8, 0x5e, 0x3e, 0x85, 0x99, 0x55, 0x9f, 0x24, 0xfb, 0x57, + 0xd0, 0x61, 0x73, 0xda, 0x35, 0xdd, 0xa4, 0xec, 0x7d, 0x4e, + 0xb, 0x89, 0x70, 0xf8, 0x96, 0xa3, 0x36, 0x91, 0xe9, 0x35, + 0x14, 0xcf, 0xb5, 0x6a, 0xb5, 0x86, 0xa4, 0x97, 0xa8, 0x19, + 0x4f, 0x5a, 0x4b, 0xc9, 0xb1, 0x9e, 0x6b, 0xe9, 0xe3, 0x25, + 0x35, 0x74, 0x7d, 0x84, 0x27, 0x1a, 0x8b, 0x9a, 0x3b, 0x14, + 0x6f, 0x64, 0xe0, 0xf3, 0x5c, 0xee, 0xa1, 0x27, 0x5a, 0xd5, + 0xbc, 0x9f, 0xad, 0x73, 0xba, 0x84, 0xff, 00, 0x7b, 0x9a, + 0xa2, 0xcc, 0x5d, 0x4d, 0xf2, 0xd, 0x71, 0x9a, 0xae, 0xe, + 0x6b, 0xa7, 0xd4, 0x67, 0xe1, 0xb9, 0xae, 0x3b, 0x56, 0x9b, + 0x93, 0x40, 0x1c, 0x3f, 0x89, 0x63, 0x1e, 0x5c, 0x98, 0xaf, + 0x1c, 0xf1, 0x85, 0xc0, 0xb3, 0x63, 0x2a, 0x31, 0x8e, 0x64, + 0x3b, 0x91, 0xd4, 0xe0, 0xa9, 0x1d, 0x8, 0xf7, 0xaf, 0x5e, + 0xf1, 0x35, 0xc0, 0x4b, 0x69, 0x58, 0x9c, 0x60, 0x57, 0xce, + 0xdf, 0x11, 0x35, 0x8c, 0x34, 0x9f, 0x37, 0x1c, 0xff, 00, + 0x5a, 0xe4, 0xc4, 0xd5, 0x54, 0xe1, 0xa9, 0xc3, 0x8b, 0xad, + 0x1a, 0x50, 0x77, 0x3e, 0xbb, 0xfd, 0x95, 0x7f, 0x69, 0xe4, + 0xf1, 0xf7, 0xfc, 0x52, 0x7e, 0x22, 0xb8, 0x8d, 0x7c, 0x43, + 0x6e, 0xbf, 0xe8, 0xf2, 0x85, 0x23, 0xed, 0x51, 0x81, 0xce, + 0x40, 0x5d, 0xa0, 0x8e, 0xfc, 0xf3, 0x5f, 0x4f, 0x7, 0xe2, + 0xbf, 0xb, 0x67, 0xf1, 0xed, 0xf7, 0x84, 0xfc, 0x4b, 0x6b, + 0xaa, 0xe9, 0xb7, 0xf, 0x6f, 0x77, 0x6b, 0x20, 0x92, 0x39, + 0x13, 0x19, 0x1e, 0xa3, 0x9f, 0x6e, 0x3f, 0x1a, 0xfd, 0x62, + 0xfd, 0x97, 0x3e, 0x3b, 0xda, 0xfc, 0x68, 0xf8, 0x7d, 0x63, + 0x74, 0xf7, 0x46, 0x5d, 0x52, 0x34, 0xc4, 0xde, 0x66, 0xd5, + 0x67, 0xe4, 0x8c, 0xe0, 0x7d, 0xf, 0x1e, 0x83, 0x3d, 0xeb, + 0xc, 0x1e, 0x2a, 0x35, 0xd3, 0x8f, 0x54, 0x73, 0x60, 0x31, + 0x91, 0xc4, 0x27, 0x1b, 0xea, 0x8f, 0x71, 0xd, 0x4f, 0x56, + 0xe6, 0xa0, 0x57, 0xcd, 0x38, 0x35, 0x7a, 0x47, 0xae, 0x58, + 0xd, 0xcd, 0x3b, 0x75, 0x42, 0x8d, 0x4f, 0xdd, 0x40, 0x12, + 0x75, 0xa7, 0x8c, 0x54, 0x60, 0x80, 0x29, 0xca, 0x45, 00, + 0x3a, 0x8a, 0x4c, 0x8a, 0x5a, 00, 0x75, 0x2d, 0x34, 0x1c, + 0x52, 0xe7, 0x34, 00, 0xb4, 0x51, 0x45, 00, 0x14, 0x51, + 0x45, 00, 0x14, 0xd2, 0x69, 0xd4, 0xd3, 0xd6, 0x80, 0x12, + 0x90, 0x9a, 0x5a, 0x6b, 0x50, 0x2, 0x66, 0x98, 0x7a, 0x52, + 0x93, 0x83, 0x4d, 0x2c, 0x28, 0x1, 0x8c, 0x6a, 0x9, 0x1a, + 0xa4, 0x73, 0xc5, 0x57, 0x91, 0xa8, 0x2, 0x37, 0x35, 0x56, + 0x56, 0xa9, 0x9d, 0xb8, 0xaa, 0x93, 0x3f, 0x5a, 00, 0xe3, + 0x3e, 0x2f, 0x78, 0x9a, 0x3f, 0xa, 0x7c, 0x38, 0xf1, 0x16, + 0xa4, 0xed, 0xb4, 0xc7, 0x67, 0x22, 0x21, 0xc8, 0x18, 0x76, + 0x52, 0xab, 0xd4, 0x8e, 0xe4, 0x57, 0xce, 0x9f, 0xb1, 0xcf, + 0x87, 0xde, 0xe2, 0xc6, 0xfb, 0x59, 0x9d, 0x1, 0x96, 0xe6, + 0x5c, 0xee, 0xee, 0x4f, 0xcc, 0x4f, 0xf3, 0xae, 0x8b, 0xf6, + 0xdf, 0xf1, 0x7f, 0xd8, 0x3c, 0xb, 0xa7, 0xf8, 0x7e, 0x17, + 0xc4, 0xda, 0x95, 0xd2, 0xb4, 0xab, 0x9c, 0x66, 0x15, 0xc, + 0x73, 0x8c, 0xff, 00, 0x78, 0x2f, 0x51, 0x5d, 0x8f, 0xec, + 0xbd, 0xe1, 0xe5, 0xd3, 0x3e, 0x1a, 0x69, 0xd, 0xb1, 0x91, + 0xe5, 0x42, 0xec, 0x8, 0xc1, 0xce, 0xe2, 0x2b, 0xe5, 0x6a, + 0xc9, 0x62, 0xb3, 0x78, 0x53, 0x5b, 0x53, 0x8d, 0xfe, 0x6c, + 0xf8, 0x9a, 0xd2, 0x58, 0xcc, 0xf6, 0x14, 0xba, 0x52, 0x8d, + 0xfe, 0x6c, 0xf7, 0xad, 0x26, 0x1d, 0xa8, 0xbc, 0x56, 0xd8, + 0xe0, 0xa, 0xa3, 0x61, 0x16, 0xd5, 0x2, 0xaf, 0xd7, 0xd5, + 0x1f, 0x6c, 0x14, 0x51, 0x45, 00, 0x15, 0xe2, 0x1f, 0xb5, + 0x4f, 0x89, 0x7f, 0xb1, 0x3c, 0x9, 0x3c, 0x6a, 0xec, 0xac, + 0xc8, 0x58, 0xe3, 0xea, 0x2b, 0xdb, 0xeb, 0xe6, 0xf, 0xdb, + 0x62, 0x46, 0xb2, 0xf0, 0x6, 0xa3, 0x7d, 0x23, 0xf9, 0x69, + 0x1c, 0x58, 0x42, 0x7a, 0x13, 0xc5, 00, 0x7e, 0x21, 0xfc, + 0x7b, 0xd7, 0xce, 0xbb, 0xe3, 0xab, 0x9f, 0x9d, 0x9d, 0x55, + 0xba, 0xb1, 0xf5, 0xaf, 0x7d, 0xfd, 0x82, 0xbc, 0x37, 0x1e, + 0xbb, 0xf1, 0x2b, 0x44, 0xb7, 0x28, 0x19, 0x56, 0x78, 0xc9, + 0xff, 00, 0xbe, 0xd7, 0xf4, 0xaf, 0x94, 0x7c, 0x5d, 0x7a, + 0xfa, 0x87, 0x88, 0x6f, 0x2e, 0x9b, 0xab, 0xc8, 0x6b, 0xdb, + 0x3f, 0x65, 0x4f, 0x8a, 0xef, 0xf0, 0xeb, 0xc5, 0x10, 0x5d, + 0xf9, 0xd0, 0xc6, 0xe6, 0x55, 0xe6, 0x43, 0x82, 0x6, 0x47, + 0xb8, 0xf4, 0xa0, 0xf, 0xe8, 0x22, 0xe1, 0xe3, 0xd2, 0xbc, + 0x3a, 0x15, 0x70, 0xa9, 0x14, 0x21, 0x46, 0xd3, 0xd3, 0x8a, + 0xfc, 0x6f, 0xff, 00, 0x82, 0x99, 0x7c, 0x40, 0x37, 0xfa, + 0xcb, 0x69, 0x49, 0x31, 0x60, 0x64, 0x19, 0x40, 0x78, 0xe3, + 0x7, 0x9e, 0x7d, 0xab, 0xee, 0x1b, 0x3f, 0xdb, 0xf, 0xc3, + 0x77, 0x5e, 0x3, 0x48, 0xe6, 0xd4, 0xa0, 0x7b, 0x9f, 0x2b, + 0x73, 0xec, 0x91, 0x4f, 0x6f, 0xf7, 0xeb, 0xf2, 0x27, 0xf6, + 0xa9, 0xf8, 0x8f, 0xff, 00, 0xb, 0x13, 0xe2, 0x5d, 0xe4, + 0xf1, 0x48, 0xaf, 0x2, 0xb9, 0x20, 0xa9, 0xe0, 0x9c, 0xfd, + 0x4e, 0x68, 0x3, 0xb1, 0xfd, 0x88, 0x3c, 0x14, 0x7c, 0x4f, + 0xf1, 0x6, 0x15, 0x30, 0x89, 00, 0x74, 0x3c, 0x8e, 0x9f, + 0x7b, 0xda, 0xbf, 0x77, 0x2e, 0xee, 0xad, 0xfc, 0xd, 0xf0, + 0xec, 0xc8, 0xe4, 0x45, 0x1d, 0xad, 0xa7, 0x7e, 00, 0x21, + 0x7f, 0xa, 0xfc, 0x83, 0xff, 00, 0x82, 0x76, 0x6a, 0x5e, + 0x1b, 0xf0, 0xa7, 0x88, 0x6e, 0x6f, 0xf5, 0x9b, 0xa8, 0xed, + 0xd2, 0x25, 0x8d, 0x81, 0x91, 0xd4, 0x2, 0x7e, 0x7f, 0x5f, + 0xc2, 0xbd, 0x53, 0xf6, 0xbd, 0xfd, 0xbe, 0xef, 0x6f, 0x74, + 0xed, 0x43, 0x43, 0xd1, 0x2e, 0x6d, 0x24, 0xb3, 0x70, 0x50, + 0xb0, 0x2d, 0x92, 0x31, 0x8f, 0xe1, 0x92, 0x80, 0x3c, 0x7, + 0xf6, 0xde, 0xf8, 0xe0, 0x9e, 0x2f, 0xd5, 0xaf, 0xed, 0x2d, + 0xae, 0x9a, 0x44, 0x67, 0x28, 0x70, 0x41, 0xcf, 0x27, 0xdc, + 0xfa, 0xd7, 0xc9, 0x5e, 0x13, 0xd2, 0x65, 0xd6, 0x35, 0x78, + 0x21, 0x8d, 0x59, 0x8c, 0x8e, 0x13, 0xa, 0x33, 0x9c, 0x9a, + 0xaf, 0xae, 0x6b, 0xb7, 0x3e, 0x22, 0xbf, 0x92, 0xe2, 0xe0, + 0xe6, 0x49, 0x18, 0xb1, 0xe4, 0xf2, 0x49, 0xfa, 0xd7, 0xd6, + 0x7f, 0xb1, 0x97, 0xec, 0xf6, 0xde, 0x36, 0xf1, 0xe, 0x95, + 0x75, 0x71, 0x6d, 0x31, 0x42, 0xca, 0xf9, 0x1c, 0xe, 0xa3, + 0xfd, 0x9a, 00, 0xfd, 0x4a, 0xfd, 0x85, 0xfe, 0x1e, 0x8f, + 0x5, 0xfc, 0x24, 0xb3, 0x66, 0x81, 0x62, 0x79, 0x80, 0x6e, + 0x6, 0x3d, 0x7d, 0x87, 0xad, 0x7d, 0x29, 0x59, 0x1e, 0x10, + 0xd0, 0x61, 0xf0, 0xcf, 0x86, 0xec, 0x34, 0xdb, 0x75, 0xdb, + 0x1c, 0x11, 0x5, 0x3, 0xf9, 0xd6, 0xb3, 0x36, 0xd0, 0x4d, + 0x26, 0x7, 0x1, 0xf1, 0x26, 0xfc, 0x41, 0x6d, 0x22, 0xe7, + 0xb5, 0x78, 0xd8, 0x39, 0xc9, 0xf5, 0x39, 0xae, 0xf3, 0xe2, + 0x86, 0xa6, 0x65, 0xbd, 0x78, 0x81, 0x18, 0x27, 0x1c, 0x57, + 0x6, 0x6, 00, 0xaf, 0xc7, 0x73, 0xca, 0xfe, 0xdb, 0x18, + 0xd2, 0xe8, 0x7e, 0x5, 0xc4, 0x78, 0x8f, 0xac, 0x63, 0xe4, + 0x96, 0xd1, 0xd0, 0x28, 0xa2, 0x8a, 0xf9, 0xf3, 0xe5, 0xc2, + 0x8a, 0x28, 0xa6, 0x1, 0xf8, 0x66, 0x93, 0x77, 0xb1, 0xae, + 0x9f, 0x44, 0xf0, 0xa4, 0xda, 0x94, 0x4a, 0xea, 0x8d, 0x83, + 0xed, 0x5b, 0x7, 0xe1, 0xdd, 0xc7, 0xf7, 0x1b, 0xfc, 0xfe, + 0x15, 0xe9, 0xd3, 0xcb, 0x31, 0x35, 0x63, 0xcf, 0x18, 0xe8, + 0x7b, 0x34, 0x72, 0x8c, 0x5d, 0x78, 0x29, 0xc2, 0x1a, 0x1c, + 0x6, 0xef, 0x63, 0x46, 0xea, 0xef, 0x1b, 0xe1, 0xfd, 0xc0, + 0x1f, 0xea, 0x98, 0xfe, 0x1f, 0xfd, 0x6a, 0xcf, 0xbb, 0xf0, + 0x45, 0xdc, 0x59, 0xc4, 0x27, 0xf2, 0x3f, 0xe1, 0x44, 0xf2, + 0xcc, 0x54, 0x15, 0xdc, 0x42, 0x79, 0x36, 0x36, 0xa, 0xee, + 0xf, 0xee, 0x39, 0x4a, 0x2b, 0x4a, 0xe7, 0xc3, 0xd7, 0xd0, + 0x13, 0xfb, 0x9f, 0xe7, 0xfe, 0x15, 0x42, 0x4b, 0x79, 0x60, + 0x38, 0x91, 0x76, 0xd7, 0x4, 0xe9, 0x4e, 0x9f, 0xc7, 0x1b, + 0x1e, 0x5d, 0x4a, 0x35, 0x29, 0x69, 0x38, 0xb4, 0x32, 0x8a, + 0x28, 0xac, 0x8c, 0x82, 0x8a, 0x28, 0xa0, 0x2, 0x90, 0xf1, + 0x83, 0x4b, 0x41, 0xa1, 0x89, 0xec, 0x7a, 0x37, 0xc3, 0x9d, + 0x44, 0xc6, 0xc2, 0x31, 0x9c, 0x9a, 0xf5, 0xd4, 0x3f, 0x2e, + 0x7d, 0xab, 0xc3, 0xbe, 0x1d, 0x3e, 0xeb, 0xf0, 0xc7, 0xa0, + 0x38, 0xaf, 0x6f, 0x85, 0xb7, 0xc4, 0xa7, 0xd4, 0x57, 0xeb, + 0x3c, 0x3d, 0x37, 0x3c, 0x2e, 0xa7, 0xee, 0x3c, 0x2b, 0x55, + 0xd4, 0xc1, 0x59, 0xf4, 0x25, 0xa8, 0x6e, 0xe4, 0x10, 0xc0, + 0xec, 0x7a, 00, 0x6a, 0x45, 0x35, 0x8f, 0xe2, 0xab, 0xef, + 0xb1, 0xe9, 0x53, 0x36, 0x40, 0x3b, 0x4f, 0x5f, 0xa5, 0x7d, + 0x25, 0x69, 0xaa, 0x74, 0xe5, 0x37, 0xd0, 0xfa, 0xdc, 0x45, + 0x45, 0x4a, 0x94, 0xa6, 0xfa, 0x23, 0xc5, 0xfc, 0x73, 0x7b, + 0xf6, 0xad, 0x62, 0x4c, 0x1e, 0x7, 0xf8, 0xd7, 0x37, 0x56, + 0x35, 0x2b, 0xa3, 0x73, 0x7b, 0x2c, 0x84, 0xe7, 0x2c, 0x6a, + 0xb6, 0xe1, 0xeb, 0x5f, 0x85, 0x62, 0x6a, 0xfb, 0x6a, 0xd2, + 0x9f, 0x76, 0x7f, 0x36, 0x63, 0x2b, 0x7b, 0x7c, 0x44, 0xea, + 0x3e, 0xac, 0x5a, 0x28, 0xdc, 0x28, 0xc8, 0xae, 0x7b, 0xa3, + 0x92, 0xe8, 0x28, 0xa2, 0x8a, 0x2e, 0x17, 0xa, 0x28, 0xa2, + 0x81, 0x85, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, + 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x5f, 0xf0, + 0xfc, 0x1f, 0x69, 0xd6, 0x6d, 0x97, 0x1d, 0x18, 0x55, 0x3, + 0xd2, 0xba, 0x7f, 0x87, 0xb6, 0x5f, 0x69, 0xd6, 0x15, 0x8e, + 0x4e, 0x8, 0xae, 0xbc, 0x24, 0x3d, 0xae, 0x22, 0x10, 0x5d, + 0xce, 0xec, 0xd, 0x2f, 0x6f, 0x8a, 0xa7, 0x5, 0xdd, 0x1e, + 0xdd, 0xa2, 0x42, 0x21, 0xb3, 0x51, 0x8c, 0x71, 0x5a, 0x35, + 0xd, 0xbc, 0x7e, 0x54, 0x48, 0xa2, 0xa6, 0xaf, 0xdd, 0x29, + 0xc7, 0x92, 0x2a, 0x28, 0xfe, 0x92, 0xa5, 0x1e, 0x48, 0x28, + 0x89, 0x46, 0x68, 0x6a, 0xe7, 0x7c, 0x49, 0xe2, 0x88, 0xb4, + 0x98, 0x5c, 0x2b, 0xa9, 0x71, 0x51, 0x5a, 0xb4, 0x28, 0x41, + 0xce, 0xa3, 0xb2, 0x22, 0xbd, 0x7a, 0x78, 0x68, 0x3a, 0x95, + 0x1d, 0x92, 0x2d, 0xeb, 0x1a, 0xf5, 0xbe, 0x95, 0x3, 0x33, + 0x38, 0x7, 0x1e, 0xa2, 0xbc, 0x7b, 0xc5, 0xbe, 0x2e, 0x9b, + 0x50, 0xb9, 0x22, 0x19, 0x4e, 0xca, 0xce, 0xd7, 0xfc, 0x57, + 0x73, 0xac, 0xb3, 0x7, 0x23, 0x67, 0xb7, 0xff, 00, 0xae, + 0xb0, 0xc7, 0xbf, 0x5a, 0xfc, 0xbf, 0x35, 0xce, 0xa7, 0x8b, + 0x7e, 0xca, 0x96, 0x91, 0x3f, 0x19, 0xce, 0xf8, 0x86, 0x78, + 0xe6, 0xe9, 0x50, 0x76, 0x80, 0xac, 0xed, 0x21, 0xcb, 0x9c, + 0x9a, 0x4a, 0x28, 0xaf, 0x93, 0x3e, 0x23, 0xcd, 0x85, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, + 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x83, 0x2, + 0x95, 0x25, 0x78, 0xdb, 0xe4, 0x6c, 0x52, 0x51, 0xd6, 0x8f, + 0x41, 0xea, 0xb5, 0x47, 0x5d, 0xe1, 0x6f, 0x11, 0xc9, 0x6f, + 0x32, 0x9, 0x25, 0x38, 0xcf, 0xad, 0x7b, 0x36, 0x8f, 0xaa, + 0x47, 0xa8, 0x5b, 0x29, 0x43, 0x92, 0x7, 0x35, 0xf3, 0x5a, + 0x37, 0x94, 0xe1, 0x87, 0x5a, 0xf4, 0x2f, 0x2, 0x78, 0xa6, + 0x58, 0xa7, 0x58, 0x49, 0x1, 0x3d, 0xeb, 0xed, 0x32, 0x3c, + 0xd5, 0xd2, 0x9a, 0xa3, 0x51, 0xe8, 0xcf, 0xd0, 0xb8, 0x73, + 0x3b, 0x74, 0x2a, 0x2a, 0x15, 0x9e, 0x8c, 0xf6, 0x3a, 0x5a, + 0x82, 0xde, 0x75, 0xb8, 0x8c, 0x30, 0x20, 0xfb, 0x8a, 0x98, + 0x57, 0xe9, 0xc9, 0xa6, 0xae, 0x8f, 0xd8, 0x93, 0x4d, 0x5d, + 0xb, 0x45, 0x14, 0x53, 0x18, 0x51, 0x45, 0x14, 00, 0x99, + 0xac, 0xfd, 0x53, 0x56, 0x87, 0x4f, 0x88, 0xb3, 0x38, 0x6, + 0xb3, 0x7c, 0x4d, 0xe2, 0x78, 0xb4, 0x68, 0x1f, 0xe6, 0x50, + 0xfe, 0xe6, 0xbc, 0x83, 0xc4, 0x1e, 0x31, 0xba, 0xd4, 0x65, + 0x3b, 0x1c, 0x14, 0xf6, 0xff, 00, 0xf5, 0xd7, 0xce, 0x66, + 0x79, 0xc5, 0x2c, 0xa, 0xe5, 0x5a, 0xc8, 0xf9, 0x3c, 0xdf, + 0x3e, 0xa1, 0x97, 0x45, 0xc1, 0x6b, 0x23, 0xa8, 0xf1, 0x17, + 0xc4, 0x5c, 0x97, 0x8d, 0x19, 0xb0, 0x38, 0xe3, 0xff, 00, + 0xd7, 0x5c, 0x1e, 0xa1, 0xac, 0x4d, 0x7a, 0xe5, 0xbc, 0xc6, + 0xe7, 0xde, 0xa8, 0x33, 0xb4, 0xa4, 0x97, 0xea, 0x69, 0x31, + 0x8a, 0xfc, 0xc7, 0x17, 0x98, 0xd7, 0xc5, 0xc9, 0xb9, 0xbd, + 0xf, 0xc7, 0x71, 0xb9, 0xae, 0x27, 0x1d, 0x2b, 0xd4, 0x7a, + 0x9, 0xf3, 0x93, 0xcb, 0x13, 0xf8, 0xd2, 0xe3, 0x34, 0x51, + 0x5e, 0x69, 0xe3, 0xd8, 0x30, 0x28, 0xa2, 0x8a, 0x6, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x85, 0x73, + 0x4b, 0x45, 0x16, 0x15, 0x86, 0xf9, 0x62, 0xad, 0xe9, 0xe, + 0xc6, 0xf9, 0x15, 0x7f, 0x4a, 0xac, 0x6b, 0x7f, 0xc1, 0x1a, + 0x60, 0xbc, 0xd4, 0x37, 0x36, 0x48, 0x18, 0xae, 0x8c, 0x35, + 0x37, 0x56, 0xb4, 0x61, 0x1e, 0xe7, 0x56, 0x12, 0x94, 0xab, + 0x57, 0x84, 0x21, 0xdc, 0xf5, 0xbf, 0xa, 0xee, 0x5b, 0x65, + 0x27, 0x23, 0x8e, 0xf5, 0x6e, 0xf6, 0x72, 0x33, 0xcd, 0x4d, + 0xa7, 0xdb, 0x8b, 0x6b, 0x5e, 0x6, 0x38, 0xac, 0xfb, 0xe9, + 0x39, 0x3f, 0x5a, 0xfd, 0xc3, 0xb, 0x4d, 0xd3, 0xa4, 0xa2, + 0xcf, 0xe8, 0xec, 0x15, 0x27, 0x4a, 0x84, 0x62, 0xcc, 0xcb, + 0xdb, 0xa3, 0xcf, 0x35, 0xce, 0x6a, 0x17, 0x7d, 0x6b, 0x5e, + 0xf9, 0xf8, 0x6a, 0xe5, 0xb5, 0x39, 0x71, 0x9e, 0x6b, 0xac, + 0xee, 0x33, 0x35, 0xb, 0xb1, 0x86, 0xe4, 0xd7, 0x23, 0xaa, + 0x5d, 0x2f, 0x3c, 0xd6, 0xb6, 0xa9, 0x39, 0x50, 0xd8, 0xae, + 0x33, 0x57, 0xbb, 0x3c, 0xf4, 0xa0, 0xe, 0x63, 0xc6, 0xd7, + 0xa2, 0x1d, 0x36, 0x63, 0xbb, 0x92, 0x3d, 0x6b, 0xe5, 0x8f, + 0x89, 0x3a, 0xc1, 0x6, 0x41, 0xbc, 0xf4, 0xff, 00, 0x1a, + 0xf7, 0x7f, 0x88, 0xfa, 0xc3, 0x43, 0x63, 0x28, 0xc8, 0xe9, + 0x5f, 0x28, 0xf8, 0xf3, 0x57, 0x37, 0x17, 0x6c, 0xa0, 0x8f, + 0xf3, 0x9a, 0xf9, 0x7c, 0xde, 0xb5, 0xad, 0x14, 0x7c, 0x66, + 0x79, 0x5f, 0x97, 0xdd, 0x47, 0x9e, 0xeb, 0x53, 0x19, 0x64, + 0x76, 0x63, 0x92, 0x6b, 0xd9, 0x3f, 0x63, 0x3f, 0x8e, 0x57, + 0x3f, 0xd, 0x3e, 0x21, 0x26, 0x9a, 0xd7, 0x4d, 0xc, 0x17, + 0x52, 0x6, 0x81, 0xb, 0x62, 0x3d, 0xc0, 0x1c, 0xa9, 0xf9, + 0x86, 0x77, 0x70, 0x31, 0x5e, 0x25, 0xa9, 0xcb, 0x92, 0x6b, + 0x8f, 0xd4, 0x2f, 0x65, 0xb0, 0xba, 0x4b, 0x9b, 0x79, 0x1a, + 0x39, 0xa3, 0x6c, 0xa3, 0x21, 0xc1, 0x7, 0xea, 0x2b, 0xcf, + 0xcb, 0xa6, 0xe1, 0x35, 0x24, 0x79, 0x59, 0x4c, 0xdd, 0x3a, + 0x8a, 0x47, 0xf4, 0x51, 0xa0, 0xeb, 0x96, 0xfe, 0x20, 0xd2, + 0x2d, 0x75, 0xb, 0x57, 0xf, 0x4, 0xe8, 0x19, 0x79, 0x7, + 0x1e, 0xdd, 0x6b, 0x4d, 0x5f, 0x38, 0xaf, 0x92, 0xbf, 0x61, + 0x1f, 0x8d, 0x2d, 0xf1, 0x23, 0xc0, 0x16, 0xb1, 0x4f, 0x22, + 0x6f, 0x78, 0x7c, 0xcc, 0x2f, 0x18, 0x94, 0x1c, 0x48, 0xa0, + 0x6e, 0x3c, 0x64, 0x8f, 0xd6, 0xbe, 0xae, 0x8d, 0xeb, 0xee, + 0x13, 0xb9, 0xfa, 0x42, 0x77, 0x57, 0x2e, 0x2b, 0x75, 0xa9, + 0x14, 0xf0, 0x2a, 0xb2, 0xbf, 0xbd, 0x4a, 0xae, 0x4d, 00, + 0x4f, 0x9a, 0x72, 0x9a, 0x84, 0x31, 0x35, 0x22, 0x9f, 0x4a, + 00, 0x96, 0x9c, 0xe, 0x69, 0x82, 0x97, 0x38, 0xa0, 0x7, + 0x52, 0x83, 0x8a, 0x4a, 0x28, 0x1, 0xc3, 0x9a, 0x5a, 0x6e, + 0x69, 0xd4, 00, 0x51, 0x45, 0x14, 00, 0x87, 0xa5, 0x36, + 0x9c, 0x4e, 0x29, 0xb4, 00, 0x53, 0x18, 0xd3, 0xcf, 0x15, + 0x1b, 0x50, 0x3, 0x18, 0xd4, 0x6c, 0x69, 0xe7, 0xbd, 0x46, + 0xdd, 0x28, 0x1, 0x8f, 0xd2, 0xab, 0x48, 0x6a, 0x77, 0x35, + 0x5a, 0x53, 0x40, 0x10, 0x48, 0x70, 0xd, 0x53, 0x95, 0xaa, + 0xc4, 0xcd, 0xc5, 0x66, 0xdf, 0xdc, 0x8b, 0x5b, 0x69, 0xa6, + 0x6e, 0x56, 0x24, 0x67, 0x38, 0xf4, 0x3, 0x34, 0x6d, 0xab, + 0x7, 0xa1, 0xf0, 0xff, 00, 0xed, 0x67, 0xac, 0xb7, 0x8a, + 0xbe, 0x35, 0x58, 0x69, 0x31, 0x4d, 0xe7, 0x47, 0x61, 0xa, + 0xc1, 0xb1, 0xf, 0xa, 0xcc, 0xd9, 0x20, 0xfa, 0x9c, 0xe6, + 0xbe, 0xc4, 0xf8, 0x4b, 0xa2, 0x8d, 0x23, 0xc2, 0x5a, 0x65, + 0xb2, 0xa9, 0x51, 0x1c, 0x40, 0x60, 0x9f, 0x72, 0x6b, 0xe1, + 0x6f, 0x4, 0x8f, 0xf8, 0x59, 0x5f, 0x1f, 0x35, 0x3d, 0x55, + 0x23, 0xcd, 0xbd, 0xce, 0xa5, 0x3d, 0xca, 0x2b, 0x1f, 0xba, + 0x86, 0x46, 0x2a, 0x3f, 0x22, 0x2b, 0xf4, 0x4b, 0xc2, 0xf6, + 0xc2, 0x1b, 0x8, 0x54, 0xc, 0x6d, 0x5c, 0x57, 0xc6, 0x64, + 0x9f, 0xed, 0x18, 0xac, 0x46, 0x2d, 0xf5, 0x76, 0x5f, 0x23, + 0xe0, 0x38, 0x77, 0xfd, 0xab, 0x19, 0x8a, 0xc7, 0x3f, 0xb4, + 0xec, 0xbd, 0x11, 0xd3, 0x5a, 0xa6, 0xd5, 0xa9, 0xe9, 0xb1, + 0x8c, 0x20, 0xa7, 0x57, 0xd9, 0x9f, 0x7e, 0x14, 0x51, 0x45, + 00, 0x15, 0xf2, 0xd7, 0xed, 0xed, 0x1c, 0xf7, 0xbf, 0xc, + 0xe5, 0xb3, 0x82, 0x32, 0xc6, 0x44, 0x39, 0x20, 0x67, 0xb8, + 0xaf, 0xa9, 0x6b, 0xcc, 0xbe, 0x3c, 0xf8, 0x56, 0xdf, 0x5f, + 0xf0, 0x4d, 0xfb, 0x3c, 0x7b, 0xe6, 0x11, 0xe1, 0x48, 0x27, + 0x23, 0xa5, 00, 0x7f, 0x39, 0x3e, 0x3e, 0xd3, 0x8e, 0x99, + 0xaf, 0xdc, 0x5b, 0xec, 0x29, 0xb0, 0xf2, 0xf, 0x5a, 0xc4, + 0xb0, 0xbd, 0x92, 0xce, 0x75, 0x75, 0x90, 0xa6, 0x3d, 0xd, + 0x7b, 0x17, 0xed, 0x19, 0xe0, 0xb, 0xef, 0xe, 0x78, 0xb2, + 0xf6, 0x4b, 0x88, 0x84, 0x42, 0x49, 0x49, 0x55, 0xdc, 0x9, + 0x2, 0xbc, 0x51, 0x97, 0x69, 0xc1, 0xa0, 0xf, 0x42, 0xb6, + 0xf8, 0xa1, 0x7b, 0x6d, 0xa7, 0xbc, 0x2, 0xf6, 0x43, 0x95, + 0xdb, 0x8d, 0xcd, 0x5c, 0x35, 0xd5, 0xeb, 0xde, 0x5e, 0x3c, + 0xf2, 0xbe, 0xe6, 0x63, 0x9c, 0xd5, 0x5a, 0x28, 0x3, 0xb4, + 0xd0, 0x7c, 0x7b, 0x7d, 0xe1, 0xfb, 0x69, 0x16, 0xce, 0xf1, + 0xe0, 0x2e, 00, 0x3b, 0x9, 0x19, 0xae, 0x73, 0x54, 0xd7, + 0xef, 0x75, 0x79, 0x99, 0xee, 0xae, 0x24, 0x9b, 0x71, 0xc9, + 0x2c, 0x6b, 0x3a, 0xaf, 0x69, 0x7a, 0x2d, 0xde, 0xb1, 0x32, + 0xc5, 0x6b, 0x9, 0x91, 0xd8, 0xe0, 0x1, 0x81, 0xfc, 0xe8, + 0x3, 0x5f, 0xc0, 0xbe, 0x12, 0xb9, 0xf1, 0x56, 0xbf, 0x65, + 0x69, 0xc, 0x6c, 0xfe, 0x64, 0xca, 0xbf, 0x2e, 0x3d, 0x6b, + 0xf7, 0x27, 0xf6, 0x33, 0xf8, 0x3, 0x17, 0x82, 0xbc, 0x2d, + 0xa5, 0x5e, 0x5c, 0x5a, 0x3a, 0x37, 0x92, 0xad, 0x97, 0x23, + 0x9f, 0x94, 0x57, 0xc9, 0x5f, 0xb0, 0xaf, 0xec, 0x85, 0x2e, + 0xaa, 0x96, 0x1a, 0xee, 0xa5, 0x68, 0xb9, 0x49, 0x15, 0x81, + 0x66, 0xc6, 0x3e, 0xe9, 0xec, 0xd5, 0xfa, 0xc5, 0xa3, 0xe9, + 0xb1, 0x69, 0x1a, 0x75, 0xbd, 0xa4, 0x4a, 0x15, 0x21, 0x45, + 0x41, 0xf8, 0xc, 0x50, 0x5, 0xc0, 0x30, 0x2a, 0xbd, 0xec, + 0xbe, 0x4d, 0xbb, 0x9e, 0x9c, 0x55, 0x9a, 0xc7, 0xf1, 0x1d, + 0xc8, 0x86, 0xc1, 0xfe, 0x95, 0x8d, 0x59, 0x72, 0x41, 0xc8, + 0xe7, 0xc4, 0x4f, 0xd9, 0xd2, 0x94, 0xfb, 0x1e, 0x1d, 0xe3, + 0x6b, 0xbf, 0xb4, 0xeb, 0xb2, 0x8c, 0xe4, 0x29, 0xac, 0x2a, + 0xb9, 0xac, 0xc9, 0xe7, 0x6a, 0xb7, 0xf, 0xfe, 0xd5, 0x53, + 0xaf, 0xc2, 0xf1, 0x33, 0xf6, 0x95, 0xa7, 0x2e, 0xec, 0xfe, + 0x6c, 0xc5, 0xd4, 0x75, 0x71, 0x15, 0x26, 0xfa, 0xb6, 0x14, + 0x51, 0x45, 0x73, 0x1c, 0xa1, 0x52, 0x5b, 0xa7, 0x9b, 0x71, + 0x1a, 0x77, 0x66, 0x2, 0xa3, 0xab, 0xda, 0x14, 0x26, 0xe3, + 0x59, 0xb6, 0x41, 0xfd, 0xf0, 0x6b, 0x4a, 0x71, 0xe7, 0x9c, + 0x63, 0xdd, 0x9a, 0xd2, 0x8f, 0x3d, 0x48, 0xc7, 0xbb, 0x3d, + 0xb7, 0xc1, 0x5a, 0x78, 0x82, 0xc2, 0x3c, 0xaf, 0xf0, 0x8f, + 0xe5, 0x5d, 0x46, 0xd0, 0x47, 0x41, 0x54, 0x34, 0x48, 0x4, + 0x36, 0x68, 0x3d, 0xab, 0x44, 0xc, 0x57, 0xee, 0x78, 0x4a, + 0x6a, 0x95, 0x18, 0xc4, 0xfe, 0x91, 0xc0, 0xd1, 0x54, 0x70, + 0xf0, 0x82, 0xec, 0x33, 0xca, 0x53, 0xfc, 0x22, 0xa3, 0x92, + 0xd2, 0x29, 0x7, 0x28, 0x3f, 0x2a, 0x9e, 0x81, 0x5d, 0x6e, + 0x29, 0xee, 0x76, 0x38, 0xa7, 0xba, 0x30, 0x35, 0x1f, 0xd, + 0xc5, 0x70, 0xe, 0xd4, 0x15, 0xe6, 0xbe, 0x34, 0xf0, 0xa3, + 0x5a, 0x61, 0xc2, 0x90, 0xbd, 0x4d, 0x7b, 0x49, 0x15, 0xcd, + 0x78, 0xd2, 0xc3, 0xed, 0x7a, 0x79, 0x38, 0xe4, 0x3, 0x5f, + 0x3d, 0x9a, 0x65, 0xd4, 0xab, 0x51, 0x94, 0x92, 0xd4, 0xf9, + 0x8c, 0xe7, 0x29, 0xa3, 0x88, 0xc3, 0x4e, 0x49, 0x6a, 0x8f, + 00, 0x2a, 0x55, 0x88, 0xf4, 0xa4, 0xab, 0x9a, 0xa4, 0x22, + 0xde, 0xed, 0x90, 0x76, 0xeb, 0x54, 0xeb, 0xf2, 0x19, 0x47, + 0x92, 0x4e, 0x3d, 0x8f, 0xc1, 0xa5, 0xe, 0x49, 0xb8, 0xf6, + 0xa, 0x28, 0xa2, 0xa0, 0x90, 0xa4, 0x6e, 0x94, 0xb4, 0x87, + 0x92, 0x7, 0xa9, 0xa1, 0x89, 0x9d, 0xb7, 0xc3, 0xe8, 0x8, + 0x99, 0x70, 0x3a, 0x9a, 0xf6, 0xd8, 0x86, 0xd8, 0xd4, 0x77, + 0xc5, 0x79, 0x5f, 0xc3, 0x8b, 0x2d, 0xd2, 0xa9, 0xc7, 0x3, + 0x15, 0xea, 0xc3, 0x8a, 0xfd, 0x6f, 0x87, 0xe9, 0x72, 0x61, + 0x6e, 0xfa, 0x9f, 0xba, 0x70, 0xbd, 0x1f, 0x67, 0x82, 0xbb, + 0xea, 0x2e, 0x39, 0xac, 0x4f, 0x13, 0xe9, 0xa7, 0x50, 0xb1, + 0x68, 0xc0, 0xc9, 0x39, 0xad, 0xca, 0x6b, 0xa0, 0x71, 0xcf, + 0x35, 0xf4, 0x55, 0x69, 0xaa, 0xb0, 0x70, 0x7d, 0x4f, 0xab, + 0xad, 0x46, 0x35, 0xe9, 0xba, 0x72, 0xd9, 0x9e, 0x3f, 0x27, + 0xc3, 0x80, 0xcc, 0xc7, 0xcb, 0x6e, 0x7d, 0xea, 0x16, 0xf8, + 0x71, 0xe8, 0x8d, 0xf9, 0xd7, 0xb1, 0x1b, 0x68, 0xc9, 0xfb, + 0xb4, 0x1b, 0x58, 0xcf, 0xf0, 0xd7, 0xce, 0x3e, 0x1f, 0xc2, + 0xbe, 0x87, 0xc9, 0x3e, 0x17, 0xc1, 0xbf, 0xb2, 0x78, 0xb3, + 0xfc, 0x39, 0x61, 0xd1, 0x1f, 0xf3, 0xa8, 0x5b, 0xe1, 0xdc, + 0xa3, 0xf8, 0x64, 0xfc, 0xc5, 0x7b, 0x69, 0xb3, 0x8c, 0xf6, + 0xa4, 0x36, 0x11, 0x1e, 0xd5, 0x93, 0xe1, 0xdc, 0x33, 0xe8, + 0x60, 0xf8, 0x4f, 0x8, 0xfa, 0x1e, 0x1d, 0x27, 0xc3, 0xf9, + 0xd0, 0x13, 0x87, 0xe3, 0xe9, 0x58, 0x9a, 0x96, 0x92, 0xda, + 0x69, 0xc3, 0xe4, 0x1f, 0x7a, 0xfa, 0xe, 0xee, 0xc2, 0x3f, + 0x25, 0xb8, 0xe3, 0x1d, 0xeb, 0xc4, 0xbc, 0x75, 0x32, 0xff, + 00, 0x69, 0x18, 0xd4, 0xf4, 0x35, 0xf3, 0x79, 0xbe, 0x55, + 0x47, 0x3, 0x4b, 0x9e, 0x3b, 0xb3, 0xe4, 0xf3, 0xcc, 0x97, + 0xf, 0x96, 0x51, 0xf6, 0x90, 0xdd, 0x9c, 0xcd, 0x25, 0x14, + 0x57, 0xc7, 0x23, 0xe0, 0x42, 0x8a, 0x28, 0xa0, 0x3, 0xa5, + 0x4b, 0x1d, 0xb4, 0xb3, 0xfd, 0xc5, 0xcd, 0x42, 0xc7, 0xa0, + 0xf5, 0x38, 0xaf, 0x44, 0xf0, 0x4f, 0x87, 0x85, 0xda, 0x21, + 0x65, 0xc8, 0xe2, 0xbb, 0xb0, 0x78, 0x59, 0x63, 0x2a, 0xfb, + 0x38, 0x9e, 0x96, 0x5f, 0x82, 0x96, 0x3e, 0xb7, 0xb2, 0x89, + 0xc2, 0x9d, 0x2a, 0xf0, 0x7f, 0xcb, 0x13, 0x8f, 0xc2, 0x9a, + 0x74, 0xeb, 0xb1, 0xff, 00, 0x2c, 0x1b, 0xf4, 0xaf, 0x7a, + 0x3e, 0x13, 0x83, 0x3, 0x31, 0xe7, 0xf1, 0xa8, 0xdb, 0xc2, + 0x30, 0x1f, 0xf9, 0x67, 0xfa, 0xd7, 0xd4, 0x3e, 0x19, 0x9a, + 0xda, 0x47, 0xd9, 0x3e, 0xf, 0xab, 0xd2, 0x47, 0x83, 0x9b, + 0x3b, 0x85, 0xeb, 0xb, 0xa, 0x69, 0xb7, 0x9c, 0x7f, 0xcb, + 0x26, 0xaf, 0x75, 0x6f, 0x7, 0x40, 0x47, 0xfa, 0xbf, 0xd6, + 0xa2, 0x6f, 0x5, 0x40, 0xdf, 0xf2, 0xce, 0xb2, 0x7c, 0x37, + 0x5b, 0xa3, 0x30, 0x7c, 0x23, 0x5d, 0x6d, 0x23, 0xc3, 0x24, + 0x8a, 0x55, 0x1c, 0xc6, 0xdf, 0x95, 0x7a, 0x2f, 0xc2, 0xfd, + 0x3d, 0x95, 0xd6, 0x46, 0x42, 0x32, 0x73, 0xcd, 0x75, 0xf, + 0xe0, 0x68, 0x18, 0x8f, 0x93, 0xfc, 0xfe, 0x75, 0xd1, 0x68, + 0xda, 0x14, 0x5a, 0x6c, 0x60, 0x20, 0xc5, 0x77, 0xe5, 0xb9, + 0x15, 0x5c, 0x3e, 0x21, 0x54, 0x9b, 0xd1, 0x1e, 0xa6, 0x51, + 0xc3, 0x55, 0xb0, 0xb8, 0xa5, 0x5a, 0xa3, 0xba, 0x46, 0xaa, + 0xd0, 0x4d, 0x2e, 0x2a, 0xbd, 0xdd, 0xd2, 0x5a, 0x42, 0x5d, + 0xce, 00, 0x15, 0xfa, 0x13, 0x6a, 0x2a, 0xec, 0xfd, 0x4a, + 0x52, 0x51, 0x5c, 0xcc, 0xa1, 0xaf, 0x6b, 0x71, 0xe9, 0x36, + 0xe5, 0x8b, 00, 0xd5, 0xe1, 0xfe, 0x26, 0xf1, 0xc, 0xba, + 0x9d, 0xf4, 0x98, 0x7c, 0xae, 0x6b, 0x6b, 0xc7, 0xfe, 0x26, + 0x37, 0x57, 0x7e, 0x52, 0x31, 0xc6, 0x6b, 0x87, 0x1f, 0x78, + 0xb7, 0x73, 0x5f, 0x95, 0x67, 0x99, 0xa4, 0xb1, 0x35, 0x1d, + 0x1a, 0x6f, 0xdd, 0x47, 0xe2, 0xdc, 0x49, 0x9c, 0xcb, 0x17, + 0x55, 0xe1, 0xe9, 0x3f, 0x75, 00, 0xe9, 0x45, 0x14, 0x57, + 0xc9, 0x1f, 0xa, 0x14, 0x51, 0x45, 00, 0x14, 0x50, 0x78, + 0x15, 0x25, 0xbd, 0xbb, 0x5c, 0xb8, 0x45, 0x19, 0x26, 0x9a, + 0xbb, 0x76, 0x40, 0x93, 0x93, 0xb2, 0x23, 0x7, 0x26, 0x97, + 0xca, 0x90, 0xf2, 0x10, 0x9a, 0xea, 0x34, 0xbf, 0x3, 0x5d, + 0xdd, 0x61, 0xb0, 0x71, 0x5d, 0x65, 0xa7, 0x80, 0xa4, 0x8e, + 0x35, 0xc, 0x99, 0x38, 0xff, 00, 0x3d, 0xeb, 0xd8, 0xc3, + 0xe5, 0x38, 0x9a, 0xea, 0xee, 0x36, 0x47, 0xd0, 0x61, 0xb2, + 0x3c, 0x5e, 0x25, 0x73, 0x72, 0xd9, 0x1e, 0x55, 0xe5, 0x4c, + 0x3f, 0xe5, 0x99, 0xa4, 0x29, 0x2f, 0x75, 0x35, 0xec, 0xd, + 0xe0, 0x7e, 0x3e, 0xe1, 0xcd, 0x66, 0xde, 0xf8, 0x26, 0x42, + 0xe, 0xd8, 0xeb, 0xa6, 0x79, 0x16, 0x22, 0xa, 0xfa, 0x9d, + 0x75, 0x38, 0x6f, 0x15, 0x4d, 0x5c, 0xf3, 0x20, 0x8, 0xea, + 0x31, 0x45, 0x6f, 0xea, 0xde, 0x1a, 0xba, 0xb6, 0x62, 0x76, + 0x60, 0x56, 0x13, 0xc4, 0xf0, 0xb6, 0xd7, 0x18, 0x35, 0xe1, + 0xd5, 0xa3, 0x52, 0x8b, 0xb4, 0xd1, 0xf3, 0x75, 0xb0, 0xf5, + 0x70, 0xf2, 0xe5, 0x9a, 0xb0, 0xda, 0x28, 0xa2, 0xb1, 0x30, + 0xa, 0x28, 0xa2, 0x80, 0xa, 0xbb, 0xa4, 0xde, 0xb5, 0xa5, + 0xd2, 0x90, 0xd8, 0xc9, 0x15, 0x4a, 0x80, 0x76, 0xb8, 0x6f, + 0x4a, 0xa8, 0x4d, 0xd3, 0x92, 0x92, 0x2e, 0x13, 0x74, 0xe4, + 0xa6, 0xba, 0x1f, 0x41, 0xf8, 0x32, 0xfc, 0x5e, 0xe9, 0xcb, + 0xf3, 0x65, 0x86, 0x33, 0x5d, 0x10, 0x18, 0xaf, 0x36, 0xf8, + 0x57, 0xa9, 0x6f, 0xb6, 0x64, 0x27, 0xa9, 0xaf, 0x49, 0xaf, + 0xdb, 0x32, 0xca, 0xff, 00, 0x58, 0xc2, 0xc2, 0x67, 0xf4, + 0x46, 0x4f, 0x88, 0xfa, 0xce, 0xa, 0x9c, 0xfc, 0x85, 0xa2, + 0x8a, 0x2b, 0xd5, 0x3d, 0xa1, 0xd, 0x54, 0xd4, 0x2f, 0xe3, + 0xb1, 0x85, 0x99, 0x98, 0x2, 0x5, 0x5a, 0x66, 0xda, 0x32, + 0x7a, 0x57, 0x97, 0x7c, 0x44, 0xf1, 0x19, 0x8e, 0x76, 0x81, + 0x1b, 0xa0, 0xaf, 0x37, 0x1f, 0x8b, 0x8e, 0xa, 0x8b, 0xa8, + 0xcf, 0x23, 0x34, 0xc7, 0xc7, 0x2f, 0xc3, 0xba, 0xb2, 0x39, + 0xf, 0x17, 0xf8, 0x8a, 0x4d, 0x4e, 0xf6, 0x75, 0xdd, 0x95, + 0xdd, 0xc5, 0x73, 0x6a, 0x30, 0x29, 0x5d, 0x8c, 0x8e, 0xce, + 0xc7, 0x24, 0x9c, 0xd2, 0x57, 0xe2, 0xb5, 0xeb, 0x4b, 0x11, + 0x51, 0xd4, 0x9b, 0xdc, 0xfe, 0x7a, 0xc4, 0xe2, 0x27, 0x8a, + 0xaa, 0xea, 0xd4, 0x7a, 0xb0, 0xa2, 0x8a, 0x2b, 0x3, 0x98, + 0x28, 0xa2, 0x8a, 00, 0x28, 0xa3, 0xad, 0x1b, 0x5c, 0xf4, + 0x53, 0x40, 0x5, 0x14, 0x85, 0x64, 0xfe, 0xe9, 0xa4, 0x3b, + 0xc7, 0xf0, 0x9a, 0x57, 0xf2, 0x15, 0xfc, 0x87, 0x51, 0x4c, + 0xde, 0x47, 0x50, 0x7f, 0x2a, 0x5d, 0xfc, 0x51, 0x71, 0x5c, + 0x75, 0x14, 0x3, 0x9a, 0x29, 0x8c, 0x1b, 0x90, 0x6b, 0xd1, + 0x7e, 0x1a, 0x69, 0xe4, 0x27, 0x98, 0x57, 0x9e, 0xb5, 0xe7, + 0x68, 0xbb, 0xdc, 0x1, 0xde, 0xbd, 0xa7, 0xc0, 0x96, 0x2, + 0xdb, 0x4f, 0x53, 0x8e, 0xb5, 0xf4, 0x79, 0xd, 0xf, 0x6b, + 0x8a, 0x4d, 0xf4, 0x3e, 0xb7, 0x86, 0x70, 0xfe, 0xdb, 0x1b, + 0xcc, 0xfa, 0x1d, 0x44, 0x9f, 0x24, 00, 0x7b, 0x56, 0xd, + 0xeb, 0xf5, 0xfa, 0xd6, 0xe5, 0xd9, 0xc2, 0x91, 0x9a, 0xe7, + 0x6f, 0x9f, 0x4, 0xfd, 0x6b, 0xf5, 0xf4, 0xac, 0x8f, 0xde, + 0x12, 0xb2, 0xb1, 0x89, 0xa8, 0xbe, 0x1, 0xae, 0x5b, 0x52, + 0x93, 0x83, 0x5d, 0xe, 0xa4, 0xfd, 0x6b, 0x95, 0xd4, 0xe4, + 0xeb, 0x4c, 0x67, 0x37, 0xab, 0xc9, 0xc1, 0xae, 0x1b, 0x58, + 0x97, 0x1b, 0xab, 0xad, 0xd6, 0x25, 0xeb, 0x5c, 0x2e, 0xb9, + 0x3e, 0xd4, 0x73, 0xed, 0x40, 0x6c, 0x78, 0xdf, 0xc5, 0x3b, + 0xfd, 0xb6, 0x97, 0x3, 0x77, 0x6a, 0xf9, 0x57, 0xc4, 0xd7, + 0x86, 0x5b, 0xd9, 0x9, 0x39, 0x3, 0xff, 00, 0xaf, 0x5f, + 0x43, 0xfc, 0x56, 0xd4, 0x3f, 0xd1, 0x2e, 0x79, 0x35, 0xf3, + 0x2e, 0xb5, 0x3f, 0x99, 0x34, 0x8d, 0xea, 0x6b, 0xe1, 0xb3, + 0x29, 0x73, 0xd5, 0xe5, 0x3f, 0x38, 0xcd, 0xe7, 0xcf, 0x59, + 0x23, 0x7, 0x50, 0x9f, 0x83, 0xcd, 0x72, 0x1a, 0xd3, 0xe5, + 0x4f, 0xbd, 0x6f, 0x6a, 0x53, 0x63, 0x35, 0xce, 0x6a, 0x4d, + 0xbe, 0x33, 0x5a, 0xe1, 0x61, 0x66, 0x99, 0xae, 0xa, 0x1c, + 0xb6, 0x67, 0xdb, 0x5f, 0xf0, 0x4c, 0x4f, 0x1c, 0x3d, 0x86, + 0xaf, 0x71, 0x61, 0x2d, 0xcf, 0xee, 0xed, 0xee, 0xd7, 0x6c, + 0x44, 0x9f, 0xba, 0xe1, 0xf3, 0xfa, 0xed, 0xaf, 0xd6, 0x44, + 0x7e, 0x2b, 0xf1, 0xb, 0xfe, 0x9, 0xfd, 0x7c, 0xf6, 0xdf, + 0x14, 0x75, 0x18, 0x83, 0x60, 0x79, 0x29, 0x2e, 0x31, 0xdc, + 0x48, 0x83, 0x3f, 0xad, 0x7e, 0xd8, 0xd9, 0x4e, 0x65, 0xb5, + 0x85, 0xf3, 0x9d, 0xc8, 0x1b, 0x3f, 0x85, 0x7d, 0x85, 0x3f, + 0x85, 0x1f, 0x7b, 0x4d, 0xde, 0x8, 0xd4, 0x46, 0xe9, 0x53, + 0x21, 0x15, 0x4a, 0x37, 0xcf, 0x5a, 0xb3, 0x1b, 0x71, 0x5a, + 0x1a, 0x96, 0x57, 0x8a, 0x91, 0x4e, 0x4f, 0x5a, 0x85, 0x4d, + 0x3d, 0x4f, 0x14, 0x1, 0x3a, 0xf7, 0xa7, 0x8e, 0x95, 0xa, + 0x9f, 0x7a, 0x91, 0x48, 0xcd, 00, 0x48, 0x29, 0x69, 0xbd, + 0xe9, 0xd4, 00, 0xa3, 0xad, 0x3a, 0x99, 0x4e, 0x1d, 0x28, + 0x1, 0x68, 0xa2, 0x8a, 00, 0x6b, 0x52, 0x50, 0x68, 0xa0, + 0x4, 0x6a, 0x8d, 0xa9, 0xec, 0x79, 0xa8, 0xd8, 0xd0, 0x3, + 0x1a, 0xa3, 0x63, 0x8a, 0x7b, 0x54, 0x6d, 0xd2, 0x80, 0x21, + 0x73, 0xc5, 0x56, 0x90, 0xe7, 0x35, 0x62, 0x43, 0x55, 0x65, + 0x34, 0x1, 0x56, 0x73, 0x8a, 0xf3, 0x1f, 0xda, 0xb, 0xc4, + 0xf1, 0x78, 0x57, 0xe1, 0x2f, 0x88, 0xee, 0xde, 0x63, 0x4, + 0xd2, 0x5b, 0x3c, 0x16, 0xe7, 0xbb, 0x4a, 0xca, 0x76, 0x8f, + 0x6e, 0x86, 0xbd, 0x2e, 0x66, 0xe6, 0xbe, 0x55, 0xfd, 0xb9, + 0xfc, 0x47, 0xe5, 0x78, 0x6f, 0x42, 0xd0, 0x22, 0x95, 0x77, + 0x5d, 0x5d, 0x7d, 0xa2, 0x48, 0xc3, 0x7c, 0xc0, 0x28, 0x21, + 0x4e, 0x3d, 0x39, 0x35, 0xe5, 0xe6, 0x75, 0xfe, 0xad, 0x83, + 0xa9, 0x53, 0xc8, 0xf1, 0xb3, 0x8c, 0x4f, 0xd5, 0x30, 0x15, + 0x6a, 0xf6, 0x4f, 0xf1, 0xd0, 0xe3, 0x7f, 0x63, 0x9f, 0xc, + 0xfd, 0xa3, 0x55, 0xb8, 0xd4, 0x18, 0x13, 0xb1, 0x76, 0x83, + 0x8e, 0x33, 0xc5, 0x7d, 0xe1, 0xa3, 0x45, 0xb2, 0xdd, 0x31, + 0xe9, 0x5f, 0x35, 0x7e, 0xca, 0x3e, 0x1a, 0x3a, 0x5f, 0x82, + 0x6d, 0xa6, 0x65, 0x2a, 0xf3, 0xfc, 0xfd, 0x3b, 0x1c, 0x57, + 0xd4, 0x1a, 0x64, 0x7b, 0x61, 0x5a, 0xe2, 0xc8, 0xa8, 0x7b, + 0xc, 0xc, 0x2f, 0xbb, 0xd7, 0xef, 0x3c, 0xfe, 0x1a, 0xc3, + 0xfd, 0x5f, 0x2d, 0xa7, 0x7d, 0xe5, 0xaf, 0xdf, 0xa9, 0x7f, + 0xa5, 0x2d, 0x14, 0x57, 0xd0, 0x9f, 0x52, 0x14, 0x51, 0x45, + 00, 0x15, 0x53, 0x53, 0xb2, 0x5d, 0x42, 0xce, 0x58, 0x1b, + 0xa3, 0x8c, 0x55, 0xba, 0x28, 0x3, 0xf3, 0x43, 0xf6, 0xd8, + 0xfd, 0x94, 0xc6, 0xaa, 0x66, 0xd6, 0x9c, 0x49, 0xc9, 0x62, + 0x36, 0xe, 0xbc, 0x7f, 0xbd, 0x5f, 0x98, 0x3e, 0x38, 0xf8, + 0x7c, 0xde, 0x1a, 0xba, 0x91, 0x36, 0x4b, 0xf2, 0x93, 0xf7, + 0x94, 0xd7, 0xf4, 0x91, 0xe3, 0x3f, 0x3, 0xd9, 0xf8, 0xde, + 0xc3, 0xec, 0xb7, 0xa5, 0x96, 0x3f, 0xf6, 0x40, 0x3f, 0xce, + 0xbe, 0x66, 0xf8, 0x9f, 0xfb, 0x10, 0xf8, 0x77, 0x56, 0x57, + 0x92, 0x29, 0x65, 0x24, 0x8c, 0xe0, 0x46, 0x9f, 0xfc, 0x4d, + 00, 0x7e, 0xb, 0x32, 0x90, 0xc4, 0x60, 0xd2, 0xc6, 0xbb, + 0xdc, 0x2f, 0xad, 0x7e, 0xab, 0x78, 0x8f, 0xf6, 0x11, 0xb3, + 0x5b, 0x87, 0x11, 0x2c, 0xe4, 0xe, 0x9f, 0xba, 0x1f, 0xfc, + 0x45, 0x5e, 0xf0, 0x9f, 0xfc, 0x13, 0xa6, 0xc7, 0x54, 0x91, + 0x3c, 0xdc, 0xa6, 0x7a, 0xee, 0x88, 0x3, 0xff, 00, 0xa2, + 0xe8, 0x3, 0xf3, 0x43, 0xc0, 0xff, 00, 0xc, 0xaf, 0x3c, + 0x69, 0x7a, 0x20, 0xb7, 0x59, 0x33, 0xc7, 0x28, 0x9b, 0xab, + 0xf4, 0x17, 0xf6, 0x48, 0xfd, 0x86, 0x2e, 0xa0, 0xbb, 0x86, + 0xf7, 0x56, 0x8a, 0xe1, 0xd7, 0x70, 0x7d, 0xaf, 0x9, 0x5e, + 0xe3, 0xfd, 0xaa, 0xfa, 0xdb, 0xe1, 0x2f, 0xec, 0x21, 0xa2, + 0x7c, 0x3d, 0xbe, 0x5b, 0xcf, 0x3f, 0x73, 0xf0, 0x70, 0x15, + 0x7b, 0x7f, 0xc0, 0x5, 0x7d, 0x53, 0xa4, 0xe9, 0x50, 0xe8, + 0xf6, 0x8b, 0x4, 0x23, 0xe5, 0x51, 0x8e, 0x68, 0x3, 0x1f, + 0xc0, 0xbe, 0xd, 0xb3, 0xf0, 0x66, 0x85, 0x6f, 0x63, 0x6c, + 0x9b, 0x42, 0x28, 0xe7, 0xf0, 0xff, 00, 0xeb, 0x57, 0x4b, + 0x45, 0x14, 00, 0x57, 0x1b, 0xe3, 0xcb, 0xdf, 0x26, 0xc5, + 0xf9, 0xed, 0x5d, 0x83, 0x30, 0xa, 0x4d, 0x79, 0x57, 0xc4, + 0xad, 0x47, 0xfd, 0x1d, 0x90, 0x1c, 0x92, 0x71, 0x5e, 0x26, + 0x6f, 0x5b, 0xd8, 0xe1, 0x64, 0xcf, 0x9d, 0xcf, 0x71, 0x1f, + 0x57, 0xc1, 0x4d, 0xf9, 0x1e, 0x65, 0x23, 0xf9, 0x92, 0xbb, + 0x7a, 0x9a, 0x6d, 0x22, 0xf4, 0x14, 0xb5, 0xf8, 0xbd, 0xef, + 0xa9, 0xfc, 0xf9, 0x7b, 0xea, 0x14, 0x51, 0x45, 0x30, 0xa, + 0xe8, 0x7c, 0x7, 0x6b, 0xf6, 0x8d, 0x7a, 0x32, 0x47, 0xb, + 0x5c, 0xf1, 0xe9, 0x5d, 0xff, 00, 0xc2, 0xdb, 0x12, 0xd7, + 0x82, 0x5c, 0x1e, 0xb5, 0xe9, 0x65, 0x94, 0xfd, 0xae, 0x2e, + 0x11, 0xf3, 0x3d, 0x8c, 0xa2, 0x8f, 0xb6, 0xc7, 0x53, 0x8f, + 0x99, 0xec, 0x56, 0xc8, 0x12, 0x15, 0x3, 0xd2, 0xa5, 0xa6, + 0xaf, 0x2, 0x9d, 0x5f, 0xb7, 0xa5, 0x65, 0x63, 0xfa, 0x31, + 0x2b, 0x2b, 0x5, 0x14, 0x51, 0x4c, 0x61, 0x59, 0xda, 0xe6, + 0xd1, 0xa7, 0x4a, 0x5b, 0x9c, 0x29, 0xad, 0x1a, 0xe6, 0xfc, + 0x6d, 0x7b, 0xf6, 0x3d, 0x1e, 0x43, 0x90, 0x37, 0x2, 0x39, + 0xae, 0x5c, 0x54, 0xd5, 0x3a, 0x33, 0x93, 0xe8, 0x8e, 0x3c, + 0x65, 0x45, 0x4b, 0xf, 0x39, 0xcb, 0x64, 0x99, 0xe1, 0xda, + 0xe3, 0x6f, 0xd4, 0x25, 0x6f, 0xf6, 0x8d, 0x67, 0x55, 0x8b, + 0xd9, 0x7c, 0xd9, 0x98, 0xfb, 0x9a, 0xaf, 0x5f, 0x85, 0x55, + 0x7c, 0xd5, 0x24, 0xcf, 0xe6, 0xba, 0xd2, 0xe7, 0xab, 0x29, + 0x77, 0xa, 0x28, 0xa2, 0xb3, 0x32, 0xa, 0x92, 0xd9, 0x3c, + 0xcb, 0x94, 0x15, 0x1d, 0x69, 0xf8, 0x76, 0xd8, 0xdc, 0xdf, + 0xc, 0x74, 0xc8, 0xe9, 0x5a, 0x53, 0x87, 0xb4, 0xa9, 0x18, + 0xa3, 0x6a, 0x30, 0x75, 0x2a, 0x46, 0xb, 0xa9, 0xeb, 0xbf, + 0xf, 0x2c, 0x3c, 0xab, 0x53, 0x21, 0x1c, 0xf1, 0xda, 0xbb, + 0x40, 0x2b, 0x33, 0xc3, 0x96, 0xa2, 0xd7, 0x4e, 0x41, 0xdc, + 0x8a, 0xd5, 0xaf, 0xdc, 0x30, 0x34, 0x95, 0x1a, 0x11, 0x82, + 0x3f, 0xa3, 0x72, 0xea, 0x1f, 0x57, 0xc2, 0xc2, 0x1e, 0x41, + 0x45, 0x14, 0x57, 0x79, 0xe9, 0x5, 0x14, 0x51, 0x40, 0x5, + 0x14, 0x51, 0x40, 0x19, 0x7a, 0xed, 0xc7, 0x91, 0x61, 0x23, + 0x7a, 0x29, 0xaf, 0x9f, 0x35, 0xeb, 0x9f, 0xb5, 0x6a, 0xb3, + 0x3e, 0x73, 0xc9, 0x15, 0xed, 0x3e, 0x3b, 0xbd, 0x16, 0xfa, + 0x64, 0xbc, 0x8f, 0xba, 0x6b, 0xc2, 0x64, 0x7f, 0x32, 0x57, + 0x63, 0xdc, 0x9a, 0xfc, 0xd7, 0x89, 0xeb, 0x73, 0x54, 0x8d, + 0x24, 0x7e, 0x43, 0xc6, 0x58, 0x8e, 0x6a, 0xb0, 0xa2, 0xba, + 0xd, 0xa2, 0x8a, 0x2b, 0xe1, 0x8f, 0xce, 0x2, 0x8a, 0x28, + 0xa0, 0x7, 0xdb, 0x46, 0x66, 0xbb, 0x8d, 0x7b, 0x64, 0x57, + 0xb9, 0xf8, 0x16, 0xd3, 0xca, 0xb6, 0x7, 0xd8, 0x57, 0x8c, + 0xf8, 0x72, 0xf, 0xb4, 0xea, 0x4b, 0xc6, 0x71, 0x5e, 0xff, + 00, 0xe1, 0xbb, 0x6f, 0x22, 0xc5, 0x7d, 0xc0, 0xaf, 0xb8, + 0xe1, 0x8a, 0x1c, 0xd3, 0x75, 0x4f, 0xd1, 0xb8, 0x3b, 0xf, + 0xcf, 0x56, 0x55, 0x59, 0xaa, 0x6, 0x29, 0x71, 0x4b, 0x45, + 0x7e, 0x96, 0x7e, 0xbe, 0x26, 0x28, 0xc7, 0xb9, 0xa5, 0xa2, + 0x80, 0x1b, 0xc7, 0x7e, 0xb4, 0xa2, 0x96, 0x90, 0xd0, 00, + 0x48, 0x3, 0x26, 0xbc, 0xfb, 0xe2, 0x2f, 0x88, 0x85, 0xac, + 0x3e, 0x52, 0x10, 0x38, 0xf5, 0xae, 0xb7, 0x5f, 0xbf, 0x5b, + 0xb, 0x17, 0x72, 0x70, 0x71, 0x5e, 0x13, 0xe2, 0xdd, 0x54, + 0xea, 0x37, 0xc7, 0xb8, 0x15, 0xf2, 0x79, 0xf6, 0x3f, 0xea, + 0xd4, 0x1d, 0x38, 0xbd, 0x59, 0xf1, 0x1c, 0x4f, 0x99, 0xfd, + 0x53, 0xe, 0xe8, 0xc1, 0xfb, 0xcc, 0xc8, 0xb9, 0x99, 0xae, + 0x67, 0x2e, 0xdc, 0xd4, 0x74, 0x51, 0x5f, 0x94, 0xb6, 0xdb, + 0xbb, 0x3f, 0x12, 0x6d, 0xb6, 0xe4, 0xf7, 0xa, 0x28, 0xa2, + 0x90, 0x82, 0x8a, 0x2a, 0xc6, 0x9d, 0x68, 0xd7, 0xf7, 0x22, + 0x35, 0x4, 0xe7, 0xd0, 0x53, 0x49, 0xc9, 0xa8, 0xae, 0xa5, + 0x46, 0x2e, 0x72, 0x51, 0x8e, 0xec, 0x93, 0x4f, 0xd3, 0xe4, + 0xbe, 0x90, 0x2a, 0xa9, 0x3c, 0xf6, 0x15, 0xea, 0x7e, 0x16, + 0xf0, 0x24, 0x62, 0x14, 0x96, 0x41, 0x83, 0x56, 0x7c, 0xb, + 0xe1, 0x34, 0xb4, 0xb7, 0xdf, 0x30, 0x3b, 0x8e, 0x3a, 0x8a, + 0xee, 0xa3, 0x8c, 0x46, 0x81, 0x40, 0xe0, 0x57, 0xe9, 0x59, + 0x3e, 0x49, 0x1a, 0x71, 0x55, 0xab, 0xad, 0x4f, 0xd7, 0x32, + 0xe, 0x1d, 0x85, 0x28, 0x2c, 0x46, 0x21, 0x5d, 0xbe, 0x84, + 0x16, 0x76, 0x31, 0xda, 0x26, 0xd5, 0x15, 0x67, 0x2, 0x9d, + 0x45, 0x7d, 0xb4, 0x62, 0xa2, 0xac, 0x8f, 0xd1, 0x63, 0x15, + 0x5, 0xcb, 0x1d, 0x86, 0xe2, 0x82, 0xaa, 0x47, 0x23, 0x34, + 0xea, 0x29, 0xd8, 0x66, 0x1e, 0xb7, 0xa2, 0x2d, 0xf4, 0x47, + 0x6a, 0x8a, 0xf1, 0xff, 00, 0x15, 0x78, 0x71, 0xac, 0x66, + 0x77, 0x39, 0xc6, 0x6b, 0xde, 0x98, 0x67, 0x8e, 0xd5, 0xc8, + 0xf8, 0xd3, 0x44, 0x5b, 0x9b, 0x66, 0x6e, 0x78, 0x19, 0xc5, + 0x7c, 0xce, 0x71, 0x97, 0x47, 0x11, 0x49, 0xce, 0x2b, 0x54, + 0x7c, 0x7e, 0x7d, 0x94, 0xc3, 0x17, 0x45, 0xd4, 0x8a, 0xf7, + 0x91, 0xe1, 0x44, 0x60, 0xd2, 0x55, 0x9d, 0x42, 0x13, 0x5, + 0xdb, 0xa9, 0x4, 00, 0x71, 0x55, 0xab, 0xf2, 0x47, 0x17, + 0x16, 0xe2, 0xcf, 0xc3, 0x65, 0x17, 0x9, 0x38, 0xbe, 0x81, + 0x45, 0x14, 0x52, 0x24, 0x28, 0x23, 0x39, 0xa2, 0x8a, 0x1e, + 0xc0, 0x77, 0x7f, 0xc, 0xaf, 0xa, 0xdd, 0x94, 0xe8, 0x1, + 0xaf, 0x69, 0x8d, 0x83, 0x20, 0x23, 0xd2, 0xbe, 0x7f, 0xf0, + 0x34, 0xc6, 0x1d, 0x40, 0x1, 0xd5, 0x8d, 0x7b, 0xdd, 0x91, + 0xcd, 0xb4, 0x67, 0xda, 0xbf, 0x53, 0xe1, 0xaa, 0xbc, 0xf8, + 0x6e, 0x5e, 0xc7, 0xed, 0x3c, 0x23, 0x5b, 0x9f, 0x7, 0xc9, + 0xd8, 0x9e, 0x9b, 0x93, 0x4e, 0xa6, 0x9e, 0x73, 0x5f, 0x60, + 0x7d, 0xe1, 0x8d, 0xe2, 0x4d, 0x53, 0xfb, 0x3e, 0xd1, 0x8e, + 0x70, 0x48, 0xaf, 0x6, 0xf1, 0x6, 0xa2, 0xda, 0x86, 0xa5, + 0x23, 0x13, 0xd0, 0xd7, 0xa4, 0xfc, 0x46, 0xd5, 0x42, 0xb3, + 0x44, 0xf, 0x4c, 0xd7, 0x92, 0x33, 0x6f, 0x95, 0xdb, 0xd4, + 0xd7, 0xe5, 0xbc, 0x47, 0x8c, 0x75, 0x2a, 0xaa, 0x31, 0x7a, + 0x23, 0xf1, 0x8e, 0x2c, 0xc7, 0x3a, 0xd5, 0xd5, 0x4, 0xf4, + 0x41, 0x45, 0x14, 0x57, 0xc7, 0x1f, 0x2, 0x14, 0x51, 0x45, + 0x30, 0xa, 0x92, 0xde, 0xdd, 0xae, 0xdf, 0x62, 0xf5, 0xa4, + 0x89, 0xc, 0xb2, 0x4, 00, 0x92, 0x7d, 0x2b, 0xd1, 0xbc, + 0x9, 0xe0, 0xe1, 0x70, 0xcb, 0x34, 0x80, 0x81, 0xd7, 0x91, + 0x5d, 0xf8, 0x2c, 0x1d, 0x4c, 0x6d, 0x55, 0x4e, 0x8, 0xf5, + 0x32, 0xec, 0x5, 0x4c, 0xc2, 0xb2, 0xa5, 0x4, 0x73, 0xba, + 0x67, 0x82, 0xae, 0x6e, 0x48, 0x3f, 0x36, 0x3f, 0xdd, 0xae, + 0x8e, 0xdf, 0xc0, 0x92, 0x2a, 0x8d, 0xca, 0x7f, 0x2a, 0xf5, + 0x1b, 0x4b, 0x8, 0xec, 0xd0, 0x5, 0x15, 0x64, 0x28, 0xf4, + 0x19, 0xaf, 0xd1, 0xb0, 0xfc, 0x3d, 0x87, 0xa7, 0x1f, 0x7b, + 0x73, 0xf5, 0x8c, 0x37, 0xa, 0xe1, 0x69, 0x47, 0xde, 0xd5, + 0x9e, 0x60, 0x9e, 0x7, 0x3, 0xaa, 0x9f, 0xca, 0x91, 0xfc, + 0x10, 0x3f, 0xb8, 0x7f, 0xef, 0x9a, 0xf5, 0x1c, 0xf, 0x4a, + 0x4d, 0x8b, 0xe9, 0xfa, 0x57, 0x6f, 0xf6, 0x2e, 0x1b, 0xb1, + 0xe8, 0xff, 00, 0xab, 0xd8, 0x4b, 0x5a, 0xc7, 0x92, 0x5c, + 0x78, 0x2b, 0x1d, 0x11, 0xbf, 0x2a, 0xca, 0xbc, 0xf0, 0x8b, + 0xc4, 0x38, 0x46, 0xfc, 0xab, 0xdb, 0x8c, 0x48, 0xdf, 0xc3, + 0x9a, 0x89, 0xec, 0xe2, 0x7e, 0xa8, 0xd, 0x72, 0xd4, 0xc8, + 0x28, 0x4d, 0x68, 0x70, 0xd5, 0xe1, 0x8c, 0x3c, 0xfe, 0x13, + 0xe7, 0x4b, 0xdd, 0x16, 0xe2, 0x2, 0x7f, 0x74, 0xdf, 0x95, + 0x66, 0xbc, 0x33, 0x47, 0xc3, 0x21, 0x15, 0xf4, 0x46, 0xa3, + 0xe1, 0xc8, 0x27, 0x53, 0xb5, 0x39, 0xfa, 0x57, 0x15, 0xaf, + 0xf8, 0x35, 0xca, 0x37, 0x96, 0x8c, 0x3f, 0xe0, 0x35, 0xf2, + 0xd8, 0xce, 0x1e, 0xa9, 0x45, 0x39, 0x43, 0x53, 0xe3, 0x31, + 0xfc, 0x2d, 0x56, 0x85, 0xe5, 0x4d, 0xdc, 0xf3, 0x8d, 0x1e, + 0xdc, 0xdc, 0x5f, 0x44, 0x87, 0xd6, 0xbd, 0xf3, 0x43, 0xb6, + 0x16, 0xd6, 0x31, 0x28, 0xf4, 0xaf, 0x2d, 0xf0, 0xe7, 0x85, + 0xe7, 0x8f, 0x57, 0x52, 0xc0, 0x85, 0x53, 0xd3, 0x15, 0xec, + 0x28, 0xbe, 0x54, 0x20, 0x7a, 0xc, 0x57, 0xb1, 0xc3, 0x78, + 0x49, 0x52, 0x8c, 0xa7, 0x35, 0x66, 0x7b, 0xfc, 0x25, 0x81, + 0x95, 0x18, 0xce, 0xa5, 0x45, 0x66, 0x52, 0xbc, 0x7c, 0x66, + 0xb9, 0xcb, 0xf7, 0xeb, 0xf5, 0xad, 0xdb, 0xd7, 0xeb, 0x5c, + 0xe5, 0xfb, 0xfd, 0xea, 0xfb, 0xb3, 0xf4, 0xa3, 0x3, 0x52, + 0x93, 0xad, 0x72, 0x9a, 0x94, 0x9d, 0x6b, 0xa2, 0xd4, 0xa4, + 0xeb, 0x5c, 0xa6, 0xa7, 0x26, 0x3, 0x50, 0x7, 0x2f, 0xac, + 0xcb, 0xd6, 0xbc, 0xff, 00, 0xc4, 0xf7, 0x3e, 0x5d, 0xbc, + 0x84, 0x7a, 0x75, 0xae, 0xd3, 0x58, 0x97, 0xef, 0x73, 0x5e, + 0x67, 0xe3, 0x6b, 0xa0, 0x96, 0xad, 0xf3, 0x1, 0xc5, 0x44, + 0xdd, 0xa2, 0xd9, 0x9d, 0x47, 0xcb, 0x6, 0xcf, 0x9f, 0x7e, + 0x2b, 0xdf, 0x7f, 0xa3, 0x4e, 0x5, 0x7c, 0xf7, 0xa9, 0xcb, + 0x9d, 0xc6, 0xbd, 0x8b, 0xe2, 0x95, 0xee, 0xe8, 0xe5, 0x5c, + 0xd7, 0x8a, 0x6a, 0x72, 0x70, 0x45, 0x7c, 0xd, 0x77, 0xcf, + 0x5a, 0xe7, 0xe6, 0x18, 0x99, 0x7b, 0x4c, 0x49, 0xce, 0x6a, + 0x4f, 0xc9, 0xac, 0x3b, 0x93, 0x90, 0x45, 0x6a, 0x6a, 0xf, + 0x96, 0x35, 0x8f, 0x3b, 0x73, 0x5e, 0xb5, 0x5, 0x64, 0x7b, + 0xb8, 0x68, 0xd9, 0x23, 0xdf, 0xbf, 0x61, 0x1b, 0x76, 0xff, + 00, 0x85, 0xb1, 0xa9, 0x48, 0x9, 0x3, 0xec, 0x21, 0x78, + 0xf5, 0xf3, 0x52, 0xbf, 0x6b, 0xf4, 0x62, 0x57, 0x4c, 0xb3, + 0x52, 0x79, 0x10, 0x27, 0xfe, 0x82, 0x2b, 0xf2, 0x3, 0xfe, + 0x9, 0xf7, 0xa0, 0x3d, 0xef, 0x89, 0xb5, 0x5b, 0xc0, 0xa4, + 0x7e, 0xfa, 0x8, 0x41, 0xc7, 0x18, 0x2d, 0x93, 0xff, 00, + 0xa0, 0xd7, 0xec, 0x5, 0xa8, 0x11, 0xc4, 0x8a, 0xf, 0xdd, + 00, 0x57, 0xd2, 0xd2, 0xf8, 0x11, 0xf5, 0xf4, 0x3f, 0x86, + 0x8d, 0x48, 0x5e, 0xac, 0xa3, 0x73, 0x59, 0xf0, 0x9c, 0xd5, + 0xb4, 0x6a, 0xd8, 0xdc, 0xb9, 0x1b, 0xd4, 0xca, 0xd9, 0xaa, + 0xb1, 0x9c, 0xd4, 0xea, 0xdd, 0x28, 0x2, 0x75, 0x22, 0xa4, + 0x53, 0x50, 0xa1, 0xcd, 0x4c, 0xa7, 0x8a, 00, 0x90, 0x1a, + 0x55, 0xa6, 0xad, 0x2d, 00, 0x3e, 0x94, 0x75, 0xa4, 0xa5, + 0x14, 00, 0xea, 0x28, 0xa2, 0x80, 0x19, 0x45, 0x14, 0x87, + 0x8a, 00, 0x6b, 0x1e, 0x2a, 0x36, 0xa7, 0xb5, 0x46, 0x4d, + 00, 0x31, 0x8d, 0x46, 0xfc, 0xa, 0x7b, 0x54, 0x52, 0x1e, + 0x28, 0x2, 0x9, 0xd, 0x55, 0x94, 0xd4, 0xf2, 0x1a, 0xab, + 0x29, 0xa0, 0xa, 0xb3, 0x1a, 0xf8, 0x23, 0xf6, 0x95, 0xd7, + 0x1f, 0xc7, 0x5f, 0x1e, 0xa3, 0xd3, 0xed, 0xa4, 0x5b, 0xab, + 0x7b, 0x18, 0xa2, 0xb4, 0xb, 0x1, 0xdc, 0x37, 0xef, 0x62, + 0x7d, 0x79, 0xc3, 0xa, 0xfb, 0x9b, 0xc4, 0x3a, 0xa2, 0x68, + 0x9a, 0x35, 0xfe, 0xa1, 0x22, 0xee, 0x8e, 0xd2, 0x7, 0x9d, + 0x94, 0x1c, 0x64, 0x2a, 0x92, 0x7f, 0x95, 0x7c, 0xb, 0xf0, + 0x46, 0xc2, 0x4f, 0x1b, 0xfc, 0x61, 0xb8, 0xd4, 0x66, 0x3b, + 0xf7, 0x5d, 0x3c, 0xe4, 0x9e, 0x78, 0xdf, 0xc7, 0x5f, 0x6a, + 0xf9, 0xe, 0x21, 0x9b, 0xa9, 0x1a, 0x58, 0x48, 0xfd, 0xb9, + 0x2b, 0xfa, 0x23, 0xe0, 0xf8, 0xaa, 0xa3, 0xa9, 0xa, 0x18, + 0x18, 0xef, 0x52, 0x4a, 0xfe, 0x88, 0xfb, 0x7b, 0xe1, 0x36, + 0x80, 0x34, 0x4f, 0xc, 0xe9, 0xb6, 0xa2, 0x32, 0x9e, 0x5c, + 0x8, 0xa, 0x9e, 0xa0, 0xed, 0x15, 0xea, 0xf6, 0x69, 0x88, + 0x45, 0x73, 0x1e, 0x1d, 0xb6, 0x11, 0xc1, 0x18, 0x3, 0xf8, + 0x6b, 0xac, 0x88, 0x62, 0x35, 0xaf, 0xaa, 0xa5, 0x5, 0x4e, + 0x9c, 0x60, 0xba, 0x23, 0xed, 0x68, 0x53, 0x54, 0xa9, 0x46, + 0x9a, 0xd9, 0x21, 0xf4, 0x51, 0x45, 0x6a, 0x6e, 0x14, 0x51, + 0x45, 00, 0x14, 0x51, 0x5c, 0x3f, 0x8e, 0x3e, 0x2e, 0x68, + 0x9e, 0x4, 0x57, 0xfb, 0x73, 0xb1, 0x75, 0xfe, 0x15, 0xc7, + 0x34, 0x1, 0xdb, 0x34, 0x8a, 0x83, 0x2c, 0xc1, 0x7e, 0xa7, + 0x15, 0xc, 0xaf, 0x6d, 0x30, 0xc3, 0xbc, 0x6c, 0x3d, 0xc8, + 0x35, 0xf0, 0xa7, 0xc6, 0x3f, 0xdb, 0x66, 0xc2, 0x11, 0x22, + 0xe9, 0xad, 0x74, 0x84, 0x67, 0x95, 0x97, 0x3, 0xf4, 0x35, + 0xf3, 0x7e, 0xaf, 0xfb, 0x74, 0x6b, 0x30, 0xca, 0xe6, 0x2b, + 0x8b, 0xb2, 0x1, 0xef, 0x72, 0xff, 00, 0xe3, 0x40, 0x1f, + 0xad, 0x92, 0x68, 0xba, 0x4c, 0xcc, 0x4b, 0x45, 0xb, 0x37, + 0xe1, 0x56, 0xed, 0x34, 0xcb, 0x4b, 0x5e, 0x61, 0x89, 0x7, + 0xb8, 0x2, 0xbf, 0x20, 0xbc, 0x13, 0xfb, 0x6d, 0xf8, 0x97, + 0x5e, 0xd7, 0xe3, 0x80, 0xcb, 0x74, 0x54, 0xb6, 0xd1, 0xfe, + 0x96, 0xfc, 0x9c, 0xfd, 0x6b, 0xf5, 0x13, 0xe0, 0x76, 0xb3, + 0x77, 0xad, 0xf8, 0xa, 0xca, 0xfe, 0xf5, 0x9b, 0xcc, 0x95, + 0x3, 0x7c, 0xee, 0x58, 0xfe, 0x66, 0x80, 0x3d, 0x10, 0xc, + 0x52, 0xd6, 0x7b, 0xeb, 0xd6, 0x11, 0xc9, 0xe5, 0xbd, 0xca, + 0xab, 0xfa, 0x10, 0x6a, 0x68, 0x35, 0x1b, 0x7b, 0xa3, 0x88, + 0xa5, 0x57, 0xfa, 0x50, 0x5, 0xaa, 0x43, 0x4b, 0x49, 0x40, + 0x15, 0xef, 0x65, 0xf2, 0x6d, 0xdc, 0xe6, 0xbc, 0x2b, 0xc7, + 0x97, 0xe6, 0xe2, 0xff, 00, 0xcb, 0xc, 0x8, 0xce, 0x78, + 0xaf, 0x63, 0xf1, 0x3d, 0xcf, 0xd9, 0xec, 0x9b, 0x9c, 0x71, + 0x5f, 0x3f, 0x6a, 0xf7, 0x6, 0xe7, 0x51, 0x91, 0x89, 0x27, + 0x9a, 0xf8, 0x1e, 0x27, 0xc4, 0x5a, 0xa, 0x92, 0xea, 0x7e, + 0x61, 0xc6, 0x38, 0xae, 0x58, 0x46, 0x82, 0xea, 0x55, 0xe9, + 0x45, 0x14, 0x57, 0xe7, 0x47, 0xe5, 0x3b, 0x5, 0x14, 0x51, + 0x4c, 00, 0x8c, 0x8c, 0xe, 0xa6, 0xbd, 0x8f, 0xe1, 0xae, + 0x9d, 0xf6, 0x7b, 0x64, 0x72, 0xb8, 0x38, 0xaf, 0x24, 0xd3, + 0x62, 0xf3, 0xef, 0xe2, 0x4f, 0xf6, 0xab, 0xdf, 0xfc, 0x29, + 0x6e, 0xb0, 0x59, 0xa8, 0x3, 0x1c, 0x57, 0xd8, 0x70, 0xdd, + 0xe, 0x7a, 0xee, 0xa3, 0xe8, 0x7d, 0xef, 0x8, 0xe1, 0xbd, + 0xae, 0x29, 0xd6, 0x7d, 0xd, 0xe1, 0x4b, 0x48, 0x29, 0x6b, + 0xf5, 0x23, 0xf6, 0x80, 0xa4, 0xcd, 0x23, 0x38, 0x3, 0x93, + 0x50, 0xbd, 0xd4, 0x71, 0xa9, 0x25, 0x80, 0xa9, 0x6d, 0x2d, + 0xd9, 0x2e, 0x49, 0x6e, 0xc9, 0x5e, 0x40, 0x8a, 0x49, 0xe0, + 0xf, 0x5a, 0xf2, 0xdf, 0x8a, 0x5e, 0x20, 0x8e, 0x58, 0x63, + 0xb7, 0x8a, 0x40, 0xdc, 0x9e, 0x95, 0xb3, 0xe2, 0xef, 0x19, + 0x25, 0xa4, 0x2f, 0x1c, 0x64, 0xf4, 0xec, 0x6b, 0xc8, 0x35, + 0x2b, 0xf3, 0xa8, 0xcf, 0xbd, 0x89, 0x3d, 0x4f, 0x26, 0xbe, + 0x1b, 0x3e, 0xcd, 0xa2, 0xa9, 0xbc, 0x3d, 0x27, 0x76, 0xf7, + 0x3f, 0x38, 0xe2, 0x6c, 0xee, 0xa, 0x94, 0xb0, 0x94, 0x5d, + 0xdb, 0xdc, 0xaa, 0x4e, 0xee, 0x69, 0x28, 0xa2, 0xbf, 0x37, + 0x3f, 0x23, 0xa, 0x28, 0xa2, 0x80, 0xc, 0xd7, 0x79, 0xf0, + 0xe7, 0x44, 0x7b, 0xad, 0xb3, 0x18, 0xdb, 0x6e, 0x7a, 0xd7, + 0x17, 0xa7, 0xda, 0x9b, 0xcb, 0x8d, 0xa2, 0xbd, 0xeb, 0xc0, + 0xfa, 0x62, 0xe9, 0xfa, 0x14, 0xb, 0x81, 0xb8, 0x8c, 0xe7, + 0x15, 0xf4, 0xf9, 0x6, 0xf, 0xeb, 0x38, 0x8e, 0x79, 0x6c, + 0x8f, 0xb2, 0xe1, 0x8c, 0xbf, 0xeb, 0x98, 0xbf, 0x69, 0x2f, + 0x86, 0x26, 0xfd, 0xbc, 0x62, 0x28, 0x95, 00, 0xe0, 0xa, + 0x96, 0x90, 0x1, 0x4b, 0x5f, 0xad, 0xa5, 0x6d, 0x8f, 0xdc, + 0x92, 0xb2, 0xb2, 0xa, 0x28, 0xa2, 0x98, 0xc2, 0x8a, 0x28, + 0xa0, 0x4, 0x27, 0x14, 0x8c, 0xdb, 0x41, 0x3e, 0x94, 0xa7, + 0xa8, 0xa8, 0x2e, 0xdf, 0x64, 0x2c, 0x69, 0x37, 0x65, 0x72, + 0x64, 0xf9, 0x53, 0x67, 0x9a, 0x7c, 0x50, 0xd4, 0x82, 0xc2, + 0xd1, 0x6, 0x19, 0x22, 0xbc, 0xad, 0x47, 0x15, 0xd5, 0x7c, + 0x41, 0xbe, 0x37, 0x1a, 0xa1, 0x4c, 0x9c, 0xf, 0x7f, 0xad, + 0x72, 0xc2, 0xbf, 0x16, 0xcd, 0xeb, 0xfb, 0x7c, 0x5c, 0x9f, + 0x6d, 0xf, 0xe7, 0xbc, 0xf7, 0x11, 0xf5, 0x9c, 0x74, 0xdf, + 0x45, 0xa0, 0x51, 0x45, 0x15, 0xe3, 0x1e, 00, 0x50, 0x4e, + 0x5, 0x14, 0x8d, 0xe9, 0xeb, 0x43, 0xd8, 0x4f, 0x63, 0xa9, + 0xf0, 0x1d, 0x89, 0x9a, 0xe8, 0x3e, 0xd3, 0xd6, 0xbd, 0xd6, + 0xc2, 0x3f, 0x2a, 0xd9, 0x17, 0xa1, 0xc5, 0x79, 0x8f, 0xc3, + 0x7b, 0x1f, 0x96, 0x33, 0x81, 0xd2, 0xbd, 0x55, 00, 00, + 0x1, 0x5f, 0xab, 0xf0, 0xf6, 0x1f, 0xd9, 0x61, 0xb9, 0xbb, + 0x9f, 0xb7, 0xf0, 0xae, 0x17, 0xd8, 0xe1, 0x39, 0xdf, 0x51, + 0xd4, 0x51, 0x45, 0x7d, 0x61, 0xf6, 0xe1, 0x45, 0x14, 0x50, + 0x1, 0x48, 0xc4, 0x1, 0x93, 0x4b, 0x54, 0x75, 0x8b, 0xa1, + 0x69, 0x61, 0x2c, 0x87, 0xb2, 0x9a, 0x89, 0xc9, 0x42, 0x2e, + 0x4f, 0xa1, 0x13, 0x92, 0x84, 0x5c, 0x9f, 0x43, 0x83, 0xf8, + 0x9f, 0xaf, 0x2c, 0x70, 0x2c, 0x31, 0xb8, 0xcf, 0xa5, 0x79, + 0x2c, 0x8e, 0x65, 0x72, 0xc6, 0xb6, 0x3c, 0x57, 0xa8, 0xb5, + 0xf6, 0xa2, 0x72, 0x49, 00, 0x93, 0x58, 0xb5, 0xf8, 0xbe, + 0x6b, 0x8b, 0x78, 0xbc, 0x4c, 0xa5, 0xd1, 0x1f, 0xcf, 0x99, + 0xde, 0x39, 0xe3, 0xb1, 0x72, 0x9f, 0x44, 0x14, 0x51, 0x45, + 0x79, 0x7, 0x80, 0x14, 0x51, 0x41, 0xa4, 0x21, 0xd1, 0xa3, + 0x4b, 0x22, 0xa2, 0x82, 0x49, 0xec, 0x2b, 0xd2, 0xbe, 0x1e, + 0xf8, 0x51, 0x8c, 0xe2, 0x69, 0xa2, 0x60, 0x31, 0xde, 0xb9, + 0x7f, 0x5, 0xe9, 0x1f, 0x6e, 0xd5, 0xa3, 0xc8, 0xc8, 0x1c, + 0xf4, 0xaf, 0x78, 0xb1, 0xb3, 0x4b, 0x38, 0x55, 0x15, 0x40, + 0xe3, 0xb0, 0xaf, 0xb5, 0xe1, 0xfc, 0xb1, 0x57, 0x7f, 0x58, + 0xa9, 0xb2, 0x3f, 0x45, 0xe1, 0x7c, 0x9d, 0x62, 0x25, 0xf5, + 0xaa, 0xbb, 0x45, 0xe8, 0x4b, 0x14, 0x4b, 0x12, 0xed, 0x40, + 00, 0x15, 0x26, 0x28, 0x14, 0xb5, 0xfa, 0x75, 0x8f, 0xd8, + 0x12, 0x49, 0x59, 0x5, 0x14, 0x51, 0x40, 0xc2, 0x8a, 0x28, + 0xa0, 0x4, 0x35, 0x4f, 0x54, 0x83, 0xed, 0x16, 0x8e, 0xb8, + 0xc9, 0xc5, 0x5c, 0x34, 0xc9, 0x7e, 0xe3, 0x7d, 0x2a, 0x27, + 0x15, 0x28, 0xb4, 0xc8, 0x9c, 0x54, 0xa2, 0xd3, 0x3c, 0x3, + 0xc6, 0x96, 0x82, 0xd7, 0x50, 0x2a, 0x6, 0x39, 0xe6, 0xb9, + 0xca, 0xee, 0xbe, 0x21, 0xdb, 0x84, 0xb8, 0x77, 0x3d, 0x79, + 0xae, 0x14, 0x74, 0xaf, 0xc4, 0xb3, 0x1a, 0x7e, 0xcf, 0x13, + 0x28, 0x9f, 0xce, 0x99, 0xb5, 0x3f, 0x65, 0x8c, 0x9c, 0x7c, + 0xc2, 0x8a, 0x28, 0xaf, 0x30, 0xf2, 0x2, 0x8a, 0x28, 0xa0, + 0xd, 0xbf, 0x8, 0x30, 0x5d, 0x55, 0x9, 0xe8, 0xd, 0x7b, + 0xfe, 0x97, 0x2f, 0x9b, 0x68, 0x87, 0xda, 0xbe, 0x78, 0xd0, + 0x18, 0xa5, 0xf2, 0x1, 0xdd, 0xab, 0xe8, 0x2d, 0x5, 0x71, + 0xa6, 0xc3, 0xf4, 0xaf, 0xd1, 0xb8, 0x5e, 0x5e, 0xe4, 0xa2, + 0x8f, 0xd6, 0x38, 0x32, 0x6d, 0xc2, 0x71, 0x34, 0x6a, 0x19, + 0xe5, 0x11, 0x44, 0xee, 0x4e, 00, 0x1d, 0x6a, 0x6a, 0xc8, + 0xf1, 0x2c, 0xff, 00, 0x67, 0xd2, 0xa5, 0x6c, 0xe0, 0xe2, + 0xbe, 0xe2, 0xac, 0xfd, 0x9c, 0x1c, 0xfb, 0x1f, 0xa3, 0x57, + 0xa9, 0xec, 0xa9, 0x4a, 0x7d, 0x91, 0xe3, 0x9e, 0x37, 0xd5, + 0x3e, 0xd7, 0xa8, 0xcb, 0xb5, 0x81, 0x19, 0x23, 0xf5, 0xae, + 0x48, 0x77, 0xab, 0xba, 0xa3, 0xf9, 0x97, 0x72, 0x31, 0x39, + 0xcb, 0x13, 0x54, 0xeb, 0xf0, 0xbc, 0x5d, 0x57, 0x5e, 0xbc, + 0xa6, 0xfb, 0x9f, 0xcd, 0xf8, 0xea, 0xd2, 0xc4, 0xe2, 0x25, + 0x52, 0x5d, 0xc2, 0x8a, 0x28, 0xae, 0x53, 0x84, 0x28, 0xa2, + 0x82, 0x70, 0x28, 0x6e, 0xc8, 0x46, 0xf7, 0x83, 0x74, 0xcf, + 0xed, 0xd, 0x49, 0x72, 0x85, 0x80, 0x3e, 0x95, 0xef, 0x1a, + 0x3d, 0x82, 0x58, 0xda, 0xaa, 0xaa, 0xe3, 0x8a, 0xf2, 0xaf, + 0x86, 0x4a, 0xa8, 0xfb, 0x8f, 0x52, 0x6b, 0xd8, 0xa3, 0xfb, + 0x80, 0xfb, 0x66, 0xbf, 0x52, 0xe1, 0xcc, 0x3c, 0x21, 0x87, + 0xf6, 0x9d, 0x59, 0xfb, 0x3f, 0x9, 0x61, 0x61, 0xc, 0x2f, + 0xb5, 0xea, 0xc7, 0xd2, 0xa, 0x5a, 0x2b, 0xec, 0x4f, 0xbf, + 0xa, 0x28, 0xa2, 0x80, 0x10, 0x8c, 0xd1, 0x4b, 0x45, 00, + 0x26, 0x33, 0x4c, 0x92, 0x25, 0x91, 0x70, 0xc0, 0x1f, 0xad, + 0x49, 0x48, 0x7a, 0x8a, 0x56, 0x13, 0x57, 0xd1, 0x99, 0xd0, + 0x69, 0x71, 0xc5, 0x39, 0x90, 0x28, 0x15, 0x2d, 0xc1, 0xa, + 0xd, 0x5b, 0x6e, 0x14, 0xd6, 0x75, 0xdb, 0xf0, 0x6a, 0x61, + 0x8, 0xc1, 0x5a, 0x24, 0x42, 0x9c, 0x69, 0xab, 0x45, 0x19, + 0x37, 0xaf, 0xd6, 0xb9, 0xbd, 0x42, 0x4f, 0xbd, 0x5b, 0x97, + 0xaf, 0xd6, 0xb9, 0xad, 0x49, 0xf1, 0x9a, 0xb3, 0x43, 0x3, + 0x52, 0x90, 0x73, 0xcd, 0x72, 0x3a, 0xac, 0x98, 0xd, 0xcd, + 0x74, 0x5a, 0x93, 0xf5, 0xae, 0x47, 0x57, 0x93, 00, 0xd0, + 0x7, 0x2b, 0xac, 0x4b, 0xf7, 0xb9, 0xaf, 0x25, 0xf8, 0x83, + 0x7f, 0xb6, 0x36, 0x19, 0x1d, 0x2b, 0xd3, 0x35, 0xa9, 0x71, + 0xba, 0xbc, 0x37, 0xe2, 0x45, 0xf7, 0x12, 0x63, 0x3c, 0xf, + 0x5a, 0xe3, 0xc5, 0x4b, 0x96, 0x9b, 0x38, 0x31, 0xb3, 0xe4, + 0xa2, 0xcf, 0x9f, 0xbe, 0x22, 0x5e, 0xf9, 0x92, 0xc8, 0x37, + 0x3, 0xcd, 0x79, 0x4e, 0xa9, 0x27, 0x26, 0xbb, 0x7f, 0x18, + 0xdc, 0xf9, 0xb7, 0x52, 0x72, 0x48, 0xc9, 0xaf, 0x3d, 0xd5, + 0x24, 0xeb, 0x5f, 0xf, 0xf, 0x7e, 0xa3, 0x67, 0xe7, 0x14, + 0xff, 00, 0x79, 0x59, 0xb3, 0x6, 0xf5, 0xb2, 0xc6, 0xb2, + 0xa7, 0x6e, 0xb5, 0x7e, 0xe9, 0xf9, 0x35, 0x99, 0x33, 0x63, + 0x9a, 0xf7, 0xe9, 0x2e, 0x87, 0xd4, 0x50, 0x89, 0xfa, 0x31, + 0xff, 00, 0x4, 0xe7, 0xf0, 0x44, 0xd1, 0x68, 0x9a, 0x6d, + 0xe4, 0xd6, 0xce, 0xa6, 0x7b, 0x87, 0xb8, 0x70, 0xc3, 0x39, + 0x8c, 0x64, 0x23, 0x7b, 0xf, 0x9a, 0xbf, 0x46, 0x61, 0x7e, + 0x3a, 0xd7, 0xcc, 0xbf, 0xb1, 0xe7, 0x84, 0x8f, 0x85, 0xfc, + 0x29, 0xd, 0xbb, 0x2a, 0xa7, 0xd8, 0xac, 0xe1, 0xb6, 0xe9, + 0xd4, 0xe0, 0xe7, 0xf9, 0x7e, 0xb5, 0xf4, 0xa4, 0x2f, 0xc0, + 0xaf, 0xa2, 0x82, 0xb4, 0x52, 0x3e, 0xae, 0x9a, 0xe5, 0x82, + 0x46, 0xa4, 0x2d, 0x56, 0x91, 0xab, 0x3e, 0x6, 0xcd, 0x5d, + 0x88, 0xd5, 0x96, 0x5d, 0x8d, 0xaa, 0xc2, 0x1c, 0xd5, 0x48, + 0xaa, 0xc2, 0x1e, 0x28, 0x2, 0xca, 0x1c, 0xa, 0x95, 0x4d, + 0x40, 0x3b, 0x54, 0xc9, 0x40, 0x13, 0x2b, 0x71, 0x4e, 0xa8, + 0xc7, 0x4a, 0x72, 0x9a, 00, 0x90, 0x1c, 0xd1, 0x48, 0x3a, + 0x52, 0xd0, 0x3, 0xe8, 0xa4, 0x7, 0x34, 0xb4, 00, 0xca, + 0x46, 0xa5, 0xa2, 0x80, 0x22, 0x26, 0xa3, 0x6a, 0x94, 0x8c, + 0x53, 0x18, 0xa, 00, 0x84, 0xf5, 0xa8, 0x65, 0x3c, 0x54, + 0xed, 0x55, 0xe5, 0x34, 0x1, 0x5a, 0x43, 0x55, 0x25, 0x3c, + 0x9a, 0xb3, 0x21, 0xaa, 0x72, 0x9a, 00, 0xf1, 0xff, 00, + 0xda, 0x8f, 0xc4, 0xcb, 0xe1, 0xcf, 0x83, 0x7a, 0xf3, 0x6f, + 0x65, 0x9e, 0xee, 0x31, 0x6b, 0x1a, 0xa9, 0xc6, 0xed, 0xec, + 0x15, 0x86, 0x71, 0xfd, 0xd2, 0x7a, 0xd7, 0x8a, 0xfe, 0xc6, + 0x7e, 0x18, 0x38, 0xbb, 0xd4, 0x59, 0x30, 0x32, 0x23, 0x53, + 0x8e, 0xbd, 0xf, 0xad, 0x68, 0xfe, 0xdd, 0x5e, 0x20, 0x2d, + 0xf, 0x86, 0x74, 0x8, 0xd9, 0x33, 0x24, 0xad, 0x74, 0xe0, + 0x7d, 0xe2, 00, 0x2b, 0x8f, 0xa6, 0x48, 0xaf, 0x4a, 0xfd, + 0x98, 0xfc, 0x34, 0x34, 0x7f, 0x3, 0x59, 0x12, 0x8, 0x79, + 0xbf, 0x78, 0x77, 0x2e, 0x3a, 0x81, 0xfe, 0x15, 0xf1, 0x93, + 0xff, 00, 0x6b, 0xce, 0x94, 0x7a, 0x53, 0x5f, 0x8b, 0x3f, + 0x3e, 0xab, 0xfe, 0xdd, 0xc4, 0x51, 0x8f, 0x4a, 0x51, 0xfc, + 0x59, 0xef, 0xfa, 0x3c, 0x3b, 0x62, 0x1f, 0x4a, 0xdd, 0x51, + 0x85, 0x15, 0x9d, 0xa7, 0x47, 0xb5, 0x14, 0x56, 0x95, 0x7d, + 0x99, 0xfa, 0x8, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x62, + 0x78, 0xc7, 0xc4, 0x31, 0x78, 0x63, 0xc3, 0xb7, 0xba, 0x84, + 0xcc, 0xa8, 0xb0, 0xc6, 0x5b, 0x2e, 0xc0, 0xc, 0xe2, 0x80, + 0x39, 0x9f, 0x8d, 0x3f, 0x14, 0x6c, 0xbe, 0x18, 0x78, 0x32, + 0xef, 0x54, 0x9e, 0x54, 0xf3, 0x15, 0x4e, 0xd5, 0xdd, 0x83, + 0xfc, 0x8d, 0x7e, 0x28, 0x7e, 0xd2, 0xff, 00, 0xb5, 0x9d, + 0xf7, 0xc4, 0x4d, 0x6a, 0xf0, 0x5b, 0xdd, 0x4c, 0x81, 0xb8, + 0xca, 0xbf, 0xb0, 0xe9, 0xf2, 0x8a, 0xef, 0x7f, 0x6d, 0x8f, + 0xda, 0xa6, 0xfb, 0xc5, 0x73, 0xdc, 0xe9, 0x96, 0xcd, 0x3, + 0x41, 0xbc, 0x8c, 0xab, 0x6, 0x27, 0x91, 0x5f, 0x7, 0xcb, + 0x23, 0xdd, 0xce, 0x5c, 0xf2, 0xcc, 0x68, 0x2, 0xed, 0xc7, + 0x88, 0xb5, 0xb, 0x87, 0x2c, 0xd7, 0x93, 0x36, 0x4f, 0x77, + 0x35, 0x7, 0xf6, 0xa5, 0xd1, 0xeb, 0x3b, 0x9f, 0xc6, 0x8f, + 0xec, 0xab, 0x9d, 0xbb, 0xbc, 0xb6, 0xc7, 0xae, 0xd, 0x57, + 0x8e, 0x32, 0xd2, 0xaa, 0x11, 0x82, 0x58, 0xf, 0xd6, 0x80, + 0x3e, 0x8a, 0xfd, 0x94, 0x7c, 0x39, 0x71, 0xe2, 0xf, 0x19, + 0xe9, 0xd1, 0xe4, 0x9d, 0xf2, 0x82, 0x49, 0x19, 0xe3, 0xf3, + 0xaf, 0xdb, 0xed, 0x56, 0x57, 0xf0, 0x2f, 0xc2, 0x4b, 0x24, + 0x8d, 0xbc, 0x81, 0x6f, 0x6a, 0x19, 0x9b, 0xf5, 0xf7, 0xf5, + 0xaf, 0xcc, 0x3f, 0xf8, 0x27, 0x4f, 0x80, 0x4e, 0xad, 0xe3, + 0x5b, 0x29, 0xb6, 0xbe, 0x23, 0x23, 0x9d, 0xa7, 0x1d, 0xab, + 0xf4, 0xc3, 0xf6, 0xa4, 0x65, 0xb1, 0xf8, 0x4b, 0xa8, 0x84, + 0x3b, 0x5b, 0xca, 0xda, 0x9, 0xec, 0x1, 0x1f, 0x99, 0xa0, + 0xf, 0xcd, 0x4f, 0x88, 0x1f, 0xb5, 0xb6, 0xa3, 0x6d, 0xe3, + 0x1b, 0xd8, 0x63, 0xbf, 0x90, 0x47, 0x1b, 0x1, 0x8f, 0x33, + 0xdb, 0xfd, 0xda, 0xf7, 0xcf, 0xd8, 0xff, 00, 0xe3, 0x85, + 0xef, 0x8d, 0xf5, 0xa3, 0x2c, 0xf7, 0x4f, 0x2a, 0x6f, 0xc0, + 0xcb, 0xf0, 0x3a, 0x7b, 0xa, 0xfc, 0xa5, 0xf8, 0xa7, 0xa7, + 0x9d, 0x3f, 0xc5, 0x57, 0x4, 0x12, 0x1e, 0x69, 0x19, 0x8e, + 0x7f, 0xa, 0xfb, 0xa3, 0xfe, 0x9, 0xdb, 0x6a, 0xc9, 0x7d, + 0xa7, 0xc0, 0xa4, 0x96, 0x91, 0xc1, 0x3c, 0x70, 0x32, 0x45, + 00, 0x7e, 0xc0, 0x69, 0x92, 0x99, 0xec, 0x61, 0x90, 0xe7, + 0xe6, 0x50, 0x79, 0xab, 0x55, 0x5b, 0x4f, 0x8b, 0xc9, 0xb2, + 0x85, 0x3f, 0xba, 0x80, 0x7e, 0x95, 0x34, 0x8d, 0xb5, 0x9, + 0xf6, 0xa0, 0xe, 0x27, 0xe2, 0x5, 0xf8, 0x8a, 0xd5, 0xc6, + 0x7b, 0x57, 0x88, 0xee, 0x2e, 0xec, 0xc7, 0xb9, 0xcd, 0x7a, + 0x47, 0xc4, 0xcb, 0xfc, 0x86, 0x40, 0x79, 0x3c, 0x57, 0x9b, + 0xa8, 0xc0, 0xaf, 0xc8, 0x33, 0xfa, 0xde, 0xdb, 0x16, 0xd7, + 0x63, 0xf0, 0x6e, 0x26, 0xc4, 0x7b, 0x6c, 0x73, 0x8f, 0x44, + 0x2d, 0x14, 0x51, 0x5f, 0x36, 0x7c, 0x98, 0x51, 0x45, 0x14, + 0x1, 0x77, 0x48, 0x9d, 0x6d, 0x6f, 0x16, 0x56, 0xed, 0x5e, + 0x91, 0xa6, 0x78, 0xfe, 0x2b, 0x68, 0x82, 0xf1, 0xf9, 0xff, + 00, 0xf5, 0xab, 0xca, 0xc1, 0xc5, 0x2f, 0x98, 0x71, 0xd2, + 0xbd, 0x4c, 0x1e, 0x61, 0x57, 0x5, 0xfc, 0x33, 0xd9, 0xc0, + 0x66, 0x95, 0xb2, 0xe5, 0xfb, 0xa3, 0xd9, 0x93, 0xe2, 0x44, + 0x18, 0xe4, 0x8f, 0xcf, 0xff, 00, 0xad, 0x49, 0x2f, 0xc4, + 0x68, 0x31, 0xd5, 0x7f, 0x3f, 0xfe, 0xb5, 0x78, 0xd7, 0x9a, + 0x7d, 0x29, 0x19, 0xb7, 0xf5, 0xaf, 0x5b, 0xfd, 0x62, 0xc5, + 0x58, 0xf6, 0xff, 00, 0xd6, 0xbc, 0x6d, 0xac, 0x7a, 0xad, + 0xe7, 0xc4, 0x8, 0xdd, 0x48, 0xd, 0x8f, 0xa1, 0xff, 00, + 0xeb, 0x57, 0x37, 0xa9, 0x78, 0xca, 0x59, 0x41, 0x9, 0x21, + 0xfc, 0xff, 00, 0xfa, 0xd5, 0xc5, 0xf9, 0x62, 0x94, 0x2e, + 0x2b, 0xcf, 0xad, 0x9b, 0xe2, 0x6b, 0x6e, 0xec, 0x79, 0xb5, + 0xf3, 0xec, 0x66, 0x23, 0x46, 0xec, 0x59, 0xba, 0xbf, 0x96, + 0xed, 0xc9, 0x76, 0x24, 0x1f, 0x7a, 0xaf, 0x45, 0x15, 0xe3, + 0xb9, 0x39, 0x3b, 0xb6, 0x7c, 0xfc, 0xa5, 0x29, 0xbb, 0xc9, + 0xea, 0x14, 0x51, 0x41, 0x38, 0xa9, 0x24, 0x29, 0xd1, 0xa3, + 0x4a, 0xe1, 0x14, 0x64, 0x9a, 0x48, 0xd4, 0xca, 0xc1, 0x54, + 0x12, 0x4d, 0x76, 0xfe, 0xd, 0xf0, 0x64, 0xb7, 0x37, 0x29, + 0x2c, 0xa1, 0x82, 0xfa, 0x62, 0xba, 0xf0, 0xb8, 0x5a, 0x98, + 0xba, 0x8a, 0x10, 0x47, 0x76, 0xb, 0x7, 0x57, 0x1d, 0x55, + 0x53, 0xa4, 0x8d, 0x1f, 0x87, 0x7e, 0x14, 0x32, 0xb1, 0x9a, + 0x55, 0xc0, 0xeb, 0xc8, 0xaf, 0x57, 0x86, 0x1, 0x6f, 0x10, + 0x45, 0xe8, 0x2a, 0xd, 0x3b, 0x4f, 0x8f, 0x4f, 0x80, 0x22, + 0xe, 0xd5, 0x72, 0xbf, 0x63, 0xcb, 0xb0, 0x30, 0xc0, 0xd1, + 0x50, 0x5b, 0x9f, 0xbe, 0xe5, 0x59, 0x74, 0x32, 0xea, 0xa, + 0x9c, 0x56, 0xbd, 0x40, 0xc, 0x52, 0xd1, 0x45, 0x7a, 0xa7, + 0xb4, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x21, + 0xac, 0xdd, 0x7a, 0xe3, 0xc8, 0xb2, 0x73, 0xd3, 0x83, 0x5a, + 0x58, 0xae, 0x53, 0xc7, 0x57, 0xa2, 0xdf, 0x4f, 0x93, 0xe9, + 0x5c, 0x78, 0xba, 0x9e, 0xca, 0x84, 0xa4, 0x70, 0x63, 0xaa, + 0xfb, 0x1c, 0x3c, 0xe7, 0xe4, 0x78, 0xaf, 0x88, 0x6e, 0x3e, + 0xd3, 0xab, 0xcc, 0xd9, 0xc8, 0xce, 0x2b, 0x3e, 0x9f, 0x33, + 0x99, 0x67, 0x91, 0xcf, 0x73, 0x4c, 0xaf, 0xc3, 0x2a, 0x4f, + 0xda, 0x4e, 0x53, 0x7d, 0x4f, 0xe6, 0xda, 0xb3, 0xf6, 0x95, + 0x25, 0x3e, 0xed, 0x85, 0x14, 0x51, 0x59, 0x99, 0x85, 0x3a, + 0x8, 0xfc, 0xeb, 0xa8, 0xd0, 0x73, 0xc8, 0xa6, 0xd5, 0xed, + 0x6, 0xf, 0xb4, 0x6a, 0x89, 0xc7, 0x2, 0xae, 0x11, 0xe7, + 0x9c, 0x63, 0xdd, 0x9a, 0x53, 0x8f, 0xb4, 0xa9, 0x18, 0xf7, + 0x67, 0xb0, 0xf8, 0x6, 0xc8, 0xc5, 0x2, 0x92, 0x3b, 0x57, + 0x6d, 0x58, 0x9e, 0x17, 0xb7, 0xf2, 0x6c, 0x14, 0xfa, 0x81, + 0x5b, 0x75, 0xfb, 0x86, 0x2, 0x97, 0xb2, 0xc3, 0xc6, 0x27, + 0xf4, 0x6e, 0x5b, 0x4b, 0xd8, 0xe1, 0x61, 0x11, 0x68, 0xa2, + 0x8a, 0xf4, 0xf, 0x50, 0x28, 0xa2, 0x8a, 00, 0x69, 0xae, + 0x4b, 0xe2, 0x1e, 0xa6, 0x2d, 0x34, 0x97, 0x8c, 0x1f, 0x99, + 0x81, 0xae, 0xb0, 0x9c, 0x3, 0x5e, 0x47, 0xf1, 0x4b, 0x52, + 0xf3, 0x2e, 0x4, 0x43, 0x9e, 0xdd, 0x6b, 0xc3, 0xce, 0x31, + 0x1f, 0x57, 0xc2, 0x49, 0xad, 0xde, 0x87, 0xce, 0x67, 0xf8, + 0xaf, 0xaa, 0xe0, 0x67, 0x25, 0xbb, 0xd0, 0xf3, 0xab, 0x89, + 0xc, 0xb3, 0x97, 0xf5, 0x34, 0xda, 0x5, 0x15, 0xf8, 0xc5, + 0xdb, 0x6d, 0xb3, 0xf9, 0xf6, 0xf7, 0x77, 0x61, 0x45, 0x14, + 0x50, 0x1, 0x4f, 0x82, 0x33, 0x35, 0xc4, 0x69, 0xea, 0x69, + 0x95, 0xaf, 0xe1, 0x8b, 0x33, 0x77, 0xaa, 0xc4, 0x30, 0x70, + 0x8, 0xad, 0xa9, 0x41, 0xd5, 0xa9, 0x18, 0x2e, 0xa6, 0xd4, + 0x69, 0xba, 0xd5, 0x63, 0x4d, 0x75, 0x67, 0xa6, 0xfc, 0x3d, + 0xd0, 0xc5, 0xb0, 0xf3, 0x98, 0x73, 0x8a, 0xf4, 0x11, 0x59, + 0x9a, 0x1d, 0xa0, 0xb6, 0xb3, 0x51, 0xed, 0x5a, 0x95, 0xfb, + 0x6e, 0x3, 0xe, 0xb0, 0xd4, 0x23, 0x4, 0x7f, 0x45, 0x65, + 0x98, 0x58, 0xe1, 0x30, 0xd1, 0xa7, 0x10, 0xa2, 0x8a, 0x2b, + 0xd0, 0x3d, 0x50, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, + 0x1, 0x8, 0xce, 0x29, 0x1c, 0x65, 0x48, 0xf6, 0xa7, 0x52, + 0x13, 0x80, 0x68, 0x13, 0x3c, 0x77, 0xe2, 0x87, 0x13, 0x95, + 0x3, 0xde, 0xbc, 0xf2, 0xbd, 0x17, 0xe2, 0x5a, 0xee, 0x9a, + 0x47, 0x3d, 0xab, 0xce, 0x57, 0xa5, 0x7e, 0x2f, 0x9c, 0xab, + 0x63, 0x66, 0x7f, 0x3e, 0xe7, 0xff, 00, 0xef, 0xf3, 0x16, + 0x8a, 0x28, 0xaf, 0x10, 0xf9, 0xd0, 0xa2, 0x8a, 0x28, 0x3, + 0x5f, 0xc2, 0xf1, 0x79, 0xba, 0xb4, 0x43, 0xd0, 0xe6, 0xbe, + 0x82, 0xd2, 0x6, 0x2c, 0x90, 0x7a, 0xa, 0xf0, 0x2f, 0x8, + 0xf, 0xf8, 0x99, 0x6e, 0xf4, 0x35, 0xef, 0x7a, 0x38, 0x3f, + 0x63, 0x43, 0xed, 0x5f, 0xa3, 0x70, 0xba, 0xf7, 0x24, 0xcf, + 0xd6, 0x78, 0x35, 0x5a, 0x9c, 0xd9, 0x7e, 0xb9, 0x6f, 0x1e, + 0x4f, 0xb3, 0x4a, 0x65, 0xee, 0x41, 0xae, 0xa6, 0xb8, 0x5f, + 0x88, 0x92, 0x11, 0x9, 0x51, 0xd3, 0x15, 0xf5, 0x59, 0x94, + 0xf9, 0x30, 0xb3, 0x67, 0xda, 0x66, 0xd5, 0x3d, 0x9e, 0xe, + 0xa3, 0xf2, 0x3c, 0x66, 0xf4, 0xff, 00, 0xa4, 0x11, 0xef, + 0x50, 0xd3, 0xa6, 0x6d, 0xf7, 0x32, 0x1f, 0x73, 0x4d, 0xaf, + 0xc4, 0x5b, 0xbb, 0x67, 0xf3, 0x9c, 0x9d, 0xe4, 0xc2, 0x8a, + 0x28, 0xa9, 0x10, 0x50, 0x7a, 0x51, 0x45, 0x2, 0x3a, 0xff, + 00, 0x5, 0x6a, 0x2b, 0x6b, 0x74, 0x8a, 0x4e, 0x5, 0x7b, + 0x65, 0x85, 0xec, 0x57, 0x70, 0xa9, 0x46, 0x7, 0x8a, 0xf9, + 0xae, 0xce, 0xe3, 0xec, 0xb2, 0x86, 0xcd, 0x7a, 0x47, 0x84, + 0x3c, 0x66, 0x23, 0x65, 0x88, 0x95, 0x23, 0xdd, 0xab, 0xee, + 0x72, 0x2c, 0xd2, 0x34, 0x57, 0xb1, 0xa9, 0xd4, 0xfd, 0x27, + 0x86, 0x73, 0x88, 0x61, 0xff, 00, 0xd9, 0xea, 0xbd, 0x19, + 0xea, 0xf4, 0x56, 0x7d, 0x86, 0xae, 0x97, 0xa0, 0x74, 0x19, + 0xf4, 0x35, 0x7f, 0x76, 0x47, 0x15, 0xfa, 0x3c, 0x67, 0x19, + 0xab, 0xc5, 0x9f, 0xac, 0xc2, 0xa4, 0x6a, 0x2e, 0x68, 0xbb, + 0x8b, 0x45, 0x20, 0x34, 0x3, 0x9a, 0xb3, 0x41, 0x68, 0xa2, + 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0x64, 0xa7, 0xb, 0x59, + 0x37, 0x8f, 0xd7, 0xeb, 0x5a, 0x73, 0x9e, 0x2b, 0x1a, 0xf5, + 0xba, 0xd0, 0x6, 0x3d, 0xf3, 0xf0, 0x6b, 0x97, 0xd4, 0xa4, + 0xc1, 0x6a, 0xe8, 0xaf, 0x5f, 0x83, 0x5c, 0xa6, 0xa7, 0x27, + 0x2d, 0x40, 0x1c, 0xee, 0xa5, 0x27, 0x5a, 0xe3, 0xf5, 0x89, + 0x78, 0x6a, 0xe9, 0xf5, 0x17, 0xfb, 0xdc, 0xd7, 0x19, 0xac, + 0x4b, 0xf7, 0xa8, 0x3, 0x90, 0xd7, 0xe7, 0x9, 0x14, 0x86, + 0xbe, 0x77, 0xf8, 0x97, 0x7e, 0x2, 0xcb, 0xce, 0x3a, 0xd7, + 0xba, 0x78, 0xae, 0xe7, 0xcb, 0xb5, 0x90, 0xd7, 0xcc, 0xff, + 00, 0x13, 0x2f, 0xf3, 0xe6, 0x8c, 0x8e, 0xfd, 0xeb, 0xc5, + 0xcc, 0xa7, 0xcb, 0x4e, 0xc7, 0xcf, 0x66, 0xf5, 0x39, 0x69, + 0xd8, 0xf1, 0x3f, 0x10, 0xdc, 0x19, 0x27, 0x94, 0xfb, 0xd7, + 0x11, 0xa9, 0xc9, 0x9c, 0xd7, 0x53, 0xac, 0x4b, 0x9d, 0xe7, + 0xd4, 0xd7, 0x1b, 0xa9, 0x49, 0x92, 0x45, 0x7c, 0xbe, 0x16, + 0x37, 0x77, 0x3e, 0x37, 0x5, 0x1b, 0xbb, 0x99, 0x17, 0xd, + 0xd6, 0xb6, 0x7e, 0x19, 0x68, 0x5f, 0xf0, 0x94, 0xfc, 0x43, + 0xd0, 0xf4, 0xc3, 0xf7, 0x2e, 0x2e, 0x55, 0x5c, 0xe3, 0x38, + 0x5e, 0xe7, 0x1d, 0xeb, 0xa, 0x76, 0xaf, 0x60, 0xfd, 0x91, + 0xbc, 0x38, 0x75, 0xaf, 0x8a, 0xf1, 0x5e, 0xb0, 0x26, 0x1b, + 0x8, 0x9a, 0x43, 0xb4, 0x7f, 0x11, 0x7, 0x6f, 0x3f, 0x51, + 0x5f, 0x4b, 0x42, 0x37, 0x92, 0x3e, 0xbb, 0xd, 0x1b, 0xc9, + 0x1f, 0xae, 0x9f, 0x5, 0xb4, 0xef, 0xec, 0xff, 00, 0x7, + 0xc5, 0x21, 0x3f, 0x34, 0xcc, 0x5b, 0xa7, 0x6e, 0xd5, 0xe8, + 0xf0, 0xb7, 0x4e, 0x6b, 0x9a, 0xf0, 0x85, 0x8a, 0xe9, 0x5e, + 0x1f, 0xb1, 0xb5, 0x4, 0x9f, 0x2e, 0x20, 0x9, 0x3d, 0xeb, + 0xa2, 0x81, 0xb9, 0xaf, 0x74, 0xfa, 0x53, 0x4e, 0x3, 0xfc, + 0xea, 0xf4, 0x47, 0x26, 0xb3, 0xad, 0xdb, 0x35, 0x7a, 0x23, + 0xcd, 00, 0x5d, 0x8c, 0x8a, 0xb2, 0x95, 0x52, 0x3a, 0xb3, + 0x19, 0xe2, 0x80, 0x2d, 0x27, 0x5a, 0x95, 0x7a, 0x54, 0x11, + 0xe3, 0x19, 0xab, 0x9, 0x40, 0x12, 0x2d, 0x3d, 0x69, 0x8b, + 0x52, 0xe, 0x94, 00, 0xa3, 0x93, 0x4e, 0xa6, 0xaf, 0x5a, + 0x75, 00, 0x39, 0x69, 0x69, 0xa0, 0xd3, 0xa8, 0x1, 0x94, + 0x87, 0xa5, 0x2d, 0x23, 0x50, 0x3, 0x1b, 0x93, 0x51, 0xb1, + 0xa7, 0x31, 0xc8, 0xa6, 0x35, 00, 0x44, 0xf5, 0x5e, 0x53, + 0x53, 0xc9, 0x55, 0x65, 0xa0, 0xa, 0xf2, 0x9a, 0xa7, 0x29, + 0xab, 0x32, 0x1a, 0xc8, 0xd7, 0x75, 0x18, 0x74, 0xad, 0x36, + 0xea, 0xee, 0x79, 0x52, 0x8, 0xa1, 0x8c, 0xb3, 0x4b, 0x21, + 0xc0, 0x5a, 0x99, 0x4b, 0x96, 0x2e, 0x4f, 0xa1, 0x32, 0x92, + 0x84, 0x5c, 0x9f, 0x43, 0xe1, 0x1f, 0x8e, 0xba, 0xb7, 0xfc, + 0x2c, 0x4f, 0xda, 0x2a, 0x5b, 0x3b, 0x6d, 0xd2, 0x5b, 0x5b, + 0x4b, 0x15, 0x9a, 0x7, 0x18, 0xc3, 00, 0xa1, 0xfa, 0x76, + 0xdc, 0xd, 0x7d, 0xb7, 0xf0, 0xef, 0x49, 0x1a, 0x76, 0x8b, + 0x65, 0x6e, 0x10, 0x28, 0x8e, 0x35, 0x5c, 0x1, 0xc7, 0x41, + 0x5f, 0xa, 0x7c, 00, 0xb5, 0x97, 0xc7, 0x7f, 0x16, 0x1b, + 0x58, 0xba, 0x3e, 0x64, 0x92, 0xdc, 0x35, 0xdb, 0xee, 0xe7, + 0x92, 0x73, 0xef, 0x5f, 0xa1, 0xbe, 0x1d, 0xb6, 0x11, 0xc2, + 0x83, 00, 0x60, 0x1, 0xc5, 0x7c, 0x7e, 0x42, 0x9d, 0x6a, + 0xb5, 0xf1, 0x6f, 0xed, 0x4b, 0x4f, 0x44, 0x7c, 0x17, 0xc, + 0xc5, 0xe2, 0x2b, 0x62, 0x71, 0xd2, 0xfb, 0x72, 0x69, 0x7a, + 0x23, 0xa5, 0xb4, 0x5c, 0xa, 0xb5, 0x51, 0x40, 0x30, 0xb5, + 0x2d, 0x7d, 0x91, 0xf7, 0xe1, 0x45, 0x14, 0x50, 0x3, 0x59, + 0x82, 0x82, 0x4f, 0x40, 0x33, 0x5f, 0x12, 0xfe, 0xde, 0xdf, + 0xb4, 0x4, 0x5e, 0x18, 0xf0, 0x16, 0xa3, 0xa6, 0xdb, 0x5d, + 0x98, 0xa5, 0x2a, 0xc3, 0xe5, 0xc6, 0x3a, 0x11, 0xfd, 0x2b, + 0xec, 0x1f, 0x18, 0xea, 0x83, 0x46, 0xf0, 0xdd, 0xfd, 0xde, + 0x9, 0x29, 0x13, 0x11, 0x8f, 0xa1, 0xaf, 0xc4, 0x9f, 0xdb, + 0xc3, 0xe2, 0x75, 0xc6, 0xbb, 0xac, 0x5d, 0x5a, 0x99, 0x1f, + 0x69, 0x90, 0x8c, 0x6e, 0x38, 0x1c, 0x9f, 0x7a, 00, 0xf8, + 0xff, 00, 0x58, 0xd5, 0x2e, 0x35, 0xfd, 0x4d, 0xe4, 0x92, + 0x67, 0x99, 0xe5, 0x93, 0xab, 0x9c, 0xe7, 0x26, 0xbe, 0x8d, + 0xf8, 0x1d, 0xfb, 0x1a, 0x6b, 0xff, 00, 0x12, 0x5e, 0xda, + 0x78, 0x6c, 0xdd, 0xc4, 0x9d, 0x39, 0x6c, 0x77, 0xf4, 0x5a, + 0xf1, 0x8f, 0x84, 0x3e, 0xf, 0x6f, 0x16, 0x78, 0xbb, 0x4a, + 0xb5, 0xca, 0x81, 0x2d, 0xd4, 0x6b, 0x96, 0x19, 0x1f, 0x7b, + 0xe9, 0x5f, 0xd0, 0x7f, 0xc1, 0x9f, 0x83, 0x5a, 0x57, 0xc3, + 0x1f, 0x9, 0xd8, 0xf9, 0x70, 0x42, 0x66, 0x48, 0x43, 0x16, + 0x11, 0xa8, 0x39, 0x39, 0x3e, 0x83, 0xd6, 0x80, 0x3f, 0x24, + 0xfe, 0x33, 0xfe, 0xca, 0x17, 0xbf, 0xb, 0x7c, 0x3b, 0x3d, + 0xd5, 0xdd, 0xba, 0xc5, 0xe5, 0x8c, 0x64, 0x93, 0xe9, 0xee, + 0xa2, 0xbe, 0x37, 0xd2, 0x2d, 0x3e, 0xdd, 0xaf, 0xa4, 0x6a, + 0x3, 0xf, 0x34, 0x7b, 0x77, 0xaf, 0xd4, 0xdf, 0xf8, 0x29, + 0x7f, 0xc4, 0x21, 0xa7, 0x78, 0x6d, 0xec, 0xa3, 0x53, 0xba, + 0x42, 0x78, 0x5e, 0x9c, 0xfa, 0xf3, 0x5f, 0x9a, 0x9f, 0xa, + 0x74, 0x93, 0xaa, 0xf8, 0x92, 0xdc, 0x1e, 0x73, 0x22, 0x81, + 0xf9, 0x8f, 0xf1, 0xa0, 0xf, 0xd6, 0xff, 00, 0xf8, 0x26, + 0x97, 0x80, 0x3e, 0xc5, 0xa4, 0x49, 0xaa, 0x49, 00, 0xc8, + 0x1c, 0x39, 0x1e, 0xc3, 0xa5, 0x7b, 0xe7, 0xed, 0x77, 0xaa, + 0x45, 0xf, 0x82, 0x66, 0xb7, 0x91, 0x88, 0x1b, 0x72, 0x40, + 0xfc, 0x2a, 0x4f, 0xd8, 0xd3, 0xc2, 0x9, 0xe1, 0x8f, 0x85, + 0x36, 0xaf, 0xb5, 0x43, 0xcd, 0xb4, 0xe4, 0xc, 0x7f, 0x8, + 0xaf, 0x22, 0xfd, 0xbb, 0xbc, 0x72, 0xba, 0x5e, 0x81, 0xa8, + 0xae, 0xf2, 0xa1, 0x17, 0x6f, 0xca, 0x79, 0xed, 0xd3, 0x9a, + 00, 0xfc, 0x72, 0xf8, 0xbb, 0x7d, 0x1e, 0xa1, 0xf1, 0x2, + 0xec, 0x45, 0x83, 0x1a, 0x3e, 0x3a, 0xd7, 0xe8, 0x57, 0xfc, + 0x13, 0x7, 0x42, 0x93, 0x56, 0xd7, 0xe3, 0xba, 0x64, 0xd, + 0x14, 0xc, 0x31, 0x9f, 0xba, 0x31, 0x8f, 0xd6, 0xbf, 0x34, + 0x2f, 0xee, 0x9b, 0x56, 0xf1, 0xd, 0xc4, 0xe4, 0x92, 0x5e, + 0x42, 0x79, 0x39, 0xaf, 0xd9, 0x4f, 0xf8, 0x25, 0xff, 00, + 0x80, 0xce, 0x8f, 0xe0, 0x73, 0xa8, 0xb8, 0x5, 0xdd, 0x7a, + 0x81, 0xeb, 0x8f, 0x6e, 0xb4, 0x1, 0xf7, 0xc8, 0x18, 0x2, + 0xab, 0x6a, 0x33, 0x79, 0x36, 0xce, 0x7d, 0xaa, 0xc7, 0x6a, + 0xc6, 0xf1, 0x2d, 0xc8, 0xb7, 0xb2, 0x3c, 0xf6, 0xac, 0x2b, + 0xcd, 0x53, 0xa6, 0xe4, 0x73, 0x62, 0x2a, 0x7b, 0x2a, 0x52, + 0x9b, 0xe8, 0x78, 0xc7, 0x8f, 0x2f, 0x4d, 0xce, 0xa5, 0xb3, + 0x39, 00, 0xd7, 0x37, 0x57, 0x35, 0xab, 0x8f, 0xb5, 0x6a, + 0x73, 0x37, 0x3c, 0x1c, 0x55, 0x3a, 0xfc, 0x37, 0x15, 0x53, + 0xda, 0xd7, 0x9c, 0xdf, 0x73, 0xf9, 0xbf, 0x1b, 0x55, 0xd7, + 0xc4, 0xce, 0x6f, 0xb8, 0x51, 0x45, 0x15, 0xca, 0x71, 0x85, + 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, + 0x40, 0x82, 0x8a, 0x28, 0xa0, 0x61, 0x45, 0x14, 0xaa, 0x37, + 0x11, 0x40, 0x87, 0x2c, 0x32, 0x49, 0xf7, 0x17, 0x35, 0xa3, + 0x61, 0xa0, 0xdc, 0xdd, 0x38, 0x6, 0x23, 0x8a, 0xe8, 0xbc, + 0x1f, 0xa6, 0xc3, 0x73, 0x22, 0xef, 0x40, 0xd9, 0xaf, 0x56, + 0xd3, 0xfc, 0x3f, 0x67, 0x4, 0x2a, 0xc2, 0x15, 0xce, 0x3d, + 0x5, 0x7d, 0x66, 0x5b, 0x92, 0x3c, 0x62, 0xf6, 0x8d, 0xe8, + 0x7d, 0xc6, 0x53, 0xc3, 0xaf, 0x1f, 0x15, 0x52, 0x52, 0xd0, + 0xe2, 0x3c, 0x39, 0xf0, 0xed, 0xe, 0xd9, 0x24, 0x8d, 0x78, + 0xe7, 0x9a, 0xf4, 0x5b, 0xd, 0x3e, 0x2b, 0x18, 0x42, 0x46, + 0xa1, 0x70, 0x3b, 0xa, 0x9d, 0x23, 0x58, 0x86, 0xd5, 0x18, + 0x1e, 0xd5, 0x20, 0xaf, 0xd1, 0x30, 0x78, 0xa, 0x38, 0x38, + 0xda, 0x9a, 0xd4, 0xfd, 0x5f, 0x1, 0x96, 0x61, 0xf2, 0xf8, + 0xda, 0x94, 0x75, 0x13, 0xaf, 0x14, 0xea, 0x28, 0xaf, 0x4c, + 0xf5, 0xc2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x4, 0x63, 0x81, 0x5e, 0x65, 0xf1, 0x42, + 0xff, 00, 0x65, 0xb1, 0x4c, 0xf5, 0xe3, 0x15, 0xe9, 0x53, + 0xb0, 0x48, 0xc9, 0x35, 0xe2, 0x3f, 0x12, 0xaf, 0xfc, 0xeb, + 0xc1, 0x18, 0x27, 0xad, 0x7c, 0xce, 0x7f, 0x5b, 0xd9, 0x61, + 0x1a, 0xee, 0x7c, 0x7f, 0x13, 0xe2, 0x3d, 0x8e, 0x6, 0x4b, + 0xb9, 0xc5, 0x8e, 0x94, 0x51, 0x45, 0x7e, 0x44, 0x7e, 0x12, + 0x82, 0x8a, 0x28, 0xa0, 0x60, 0x4e, 0x1, 0x35, 0xd2, 0x78, + 0x1a, 0xcf, 0xce, 0xbc, 0xdf, 0x8c, 0xf3, 0x5c, 0xd3, 0x9e, + 0x3d, 0xeb, 0xd1, 0x3e, 0x1b, 0xd8, 0xef, 0x2a, 0x71, 0xd6, + 0xbd, 0x4c, 0xb2, 0x97, 0xb6, 0xc5, 0xc5, 0x1e, 0xce, 0x4f, + 0x47, 0xdb, 0xe3, 0x61, 0x13, 0xd5, 0xf4, 0xc8, 0xbc, 0x9b, + 0x38, 0xc7, 0xb7, 0xf4, 0xab, 0x62, 0x99, 0x1a, 0x6d, 0x40, + 0x5, 0x49, 0x5f, 0xb6, 0x41, 0x72, 0xc5, 0x23, 0xfa, 0x26, + 0x11, 0xe5, 0x8a, 0x41, 0x45, 0x14, 0x55, 0x96, 0x14, 0x51, + 0x45, 00, 0x56, 0xd4, 0x25, 0xf2, 0x2d, 0x9d, 0xf3, 0x8c, + 0xa, 0xf0, 0x1f, 0x18, 0xdf, 0x1b, 0xbd, 0x5a, 0x4e, 0x73, + 0x83, 0x5e, 0xd3, 0xe2, 0xcb, 0xc1, 0x6d, 0xa6, 0xca, 0x73, + 0x8e, 0x3b, 0x57, 0xcf, 0xf7, 0xf3, 0x19, 0xef, 0x25, 0x7c, + 0xe7, 0x2c, 0x6b, 0xf3, 0xee, 0x27, 0xaf, 0x65, 0x1a, 0x49, + 0x9f, 0x97, 0x71, 0x96, 0x26, 0xca, 0x14, 0x13, 0x2b, 0xd1, + 0x45, 0x15, 0xf9, 0xe9, 0xf9, 0x58, 0x51, 0x45, 0x14, 00, + 0x1e, 0x95, 0xdf, 0xfc, 0x2d, 0xd3, 0x3e, 0xd5, 0x74, 0xf2, + 0x11, 0x9d, 0xa4, 0x73, 0x5c, 0xa, 0xae, 0xe6, 0x2, 0xbd, + 0x8f, 0xe1, 0x2d, 0x8f, 0x95, 0xa6, 0xcd, 0x21, 0x1c, 0x96, + 0xe2, 0xbe, 0x87, 0x22, 0xa3, 0xed, 0xb1, 0xb1, 0xbe, 0xc8, + 0xfa, 0xae, 0x19, 0xc3, 0xfd, 0x63, 0x30, 0x8d, 0xd6, 0x8b, + 0x53, 0xbe, 0x8e, 0x31, 0x1a, 0x80, 0x38, 0x2, 0xa4, 0xa4, + 0xc5, 0x2d, 0x7e, 0xc2, 0x7e, 0xf4, 0x95, 0xb4, 0xa, 0x28, + 0xa2, 0x98, 0xc2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0x4, 0xef, 0x51, 0xcc, 0xdb, 0x63, 0x6f, 0xa5, 0x4b, 0x55, + 0xef, 0x1b, 0x6c, 0xe, 0x6a, 0x64, 0xec, 0x9b, 0x22, 0x6e, + 0xd1, 0x6c, 0xf1, 0xff, 00, 0x89, 0x13, 0x81, 0x23, 0x2e, + 0x7a, 0xf1, 0x5c, 0x8, 0xe9, 0x5d, 0x4f, 0x8f, 0xee, 0xbc, + 0xed, 0x4c, 0xa8, 0xe9, 0x9f, 0xf1, 0xae, 0x5a, 0xbf, 0x12, + 0xcc, 0xe7, 0xed, 0x31, 0x73, 0x67, 0xf3, 0xbe, 0x73, 0x53, + 0xda, 0x63, 0x66, 0xd0, 0x51, 0x45, 0x15, 0xe5, 0x9e, 0x28, + 0x50, 0x68, 0xa0, 0xf4, 0xa0, 0xe, 0x87, 0xc1, 0x51, 0x19, + 0x2f, 0xd4, 0x1, 0x9c, 0xb5, 0x7b, 0xed, 0x82, 0x79, 0x76, + 0xb1, 0xaf, 0xb5, 0x78, 0xb7, 0xc3, 0x6b, 0x4f, 0x3b, 0x51, + 0x4e, 0x3a, 0x57, 0xb7, 0xa0, 0xc2, 0x81, 0xe9, 0x5f, 0xa9, + 0x70, 0xd5, 0x3e, 0x5c, 0x33, 0x91, 0xfb, 0x37, 0x7, 0xd1, + 0xe5, 0xc2, 0x39, 0xf7, 0x1d, 0x5c, 0x2f, 0xc4, 0x48, 0x8a, + 0x59, 0x3b, 0x9f, 0x43, 0x5d, 0xd5, 0x72, 0x5e, 0x3b, 0xb7, + 0x33, 0xd8, 0x95, 0x3, 0x23, 0x15, 0xee, 0xe6, 0x51, 0xe7, + 0xc2, 0xcd, 0x1f, 0x4d, 0x9b, 0xc3, 0x9f, 0x7, 0x51, 0x2e, + 0xc7, 0x83, 0xb0, 0xc3, 0xb7, 0xd6, 0x92, 0xa6, 0xbd, 0x4f, + 0x2e, 0xed, 0xd7, 0x18, 00, 0xd4, 0x35, 0xf8, 0x8b, 0x56, + 0x93, 0x47, 0xf3, 0xa4, 0x97, 0x2c, 0x9a, 0x61, 0x45, 0x14, + 0x52, 0x10, 0x51, 0x45, 0x14, 00, 0x11, 0x9a, 0x96, 0xda, + 0xf1, 0xad, 0x24, 0xc, 0x99, 0xcf, 0xb5, 0x45, 0x45, 0x34, + 0xda, 0x77, 0x40, 0x9b, 0x8b, 0xbc, 0x77, 0x3a, 0x9d, 0x27, + 0xc6, 0x97, 0x36, 0xec, 0x3e, 0x76, 0x15, 0xda, 0xe9, 0x7e, + 0x39, 0x69, 0x2, 0x87, 0x90, 0xfe, 0x38, 0xaf, 0x20, 0xcb, + 0xe, 0x86, 0xa5, 0x8e, 0xfa, 0xe2, 0x36, 0xf9, 0x5c, 0x8f, + 0xc6, 0xbd, 0xac, 0x2e, 0x71, 0x5f, 0xf, 0xa3, 0x6d, 0xa3, + 0xe8, 0xf0, 0x79, 0xee, 0x27, 0x9, 0xa3, 0x93, 0x68, 0xfa, + 0x2f, 0x4c, 0xd6, 0xe2, 0xbb, 0x41, 0x99, 0x6, 0x7e, 0xb5, + 0xa8, 0xb2, 0xa3, 0xf4, 0x60, 0x7e, 0x86, 0xbe, 0x7d, 0xd2, + 0xbc, 0x4d, 0x77, 0x6e, 0xc3, 0x32, 0x9f, 0xcc, 0xff, 00, + 0x8d, 0x76, 0xda, 0x1f, 0x8c, 0xcb, 0x32, 0x89, 0x1c, 0xe3, + 0xeb, 0xff, 00, 0xd7, 0xaf, 0xba, 0xc1, 0x67, 0xd4, 0xab, + 0x25, 0x19, 0xe8, 0xcf, 0xd2, 0x32, 0xfe, 0x26, 0xa3, 0x88, + 0x4a, 0x35, 0x34, 0x67, 0xa7, 0xd1, 0x59, 0x36, 0x1a, 0xed, + 0xbd, 0xd2, 0xf, 0x9b, 0x9f, 0xad, 0x6a, 0x2b, 0xac, 0x8b, + 0x90, 0x72, 0x2b, 0xea, 0xa1, 0x52, 0x35, 0x15, 0xe2, 0xcf, + 0xb5, 0xa7, 0x56, 0x15, 0x55, 0xe0, 0xee, 0x3a, 0x8a, 0x29, + 0xf, 0x4a, 0xd0, 0xd4, 0xab, 0x72, 0xdc, 0x1a, 0xc5, 0xbc, + 0x7e, 0xb5, 0xad, 0x74, 0xdc, 0x1a, 0xc2, 0xbd, 0x6c, 0x66, + 0x80, 0x31, 0xaf, 0x9f, 0x86, 0xae, 0x4b, 0x53, 0x93, 0x96, + 0xae, 0x9a, 0xfd, 0xfe, 0x53, 0x5c, 0x86, 0xa6, 0xfc, 0xb7, + 0xd6, 0x80, 0x39, 0xed, 0x4a, 0x4e, 0x1a, 0xb8, 0x9d, 0x62, + 0x5f, 0xbd, 0x5d, 0x66, 0xab, 0x2f, 0x6, 0xb8, 0x7d, 0x66, + 0x5f, 0xbd, 0x40, 0x1e, 0x77, 0xe3, 0xab, 0xcf, 0x2e, 0xd9, + 0xc6, 0xec, 0x7f, 0x91, 0x5f, 0x2e, 0xfc, 0x49, 0xbf, 0xdc, + 0xee, 0x3, 0x73, 0x5f, 0x42, 0xfc, 0x45, 0xbd, 0x28, 0x92, + 0x2e, 0x4e, 00, 0xff, 00, 0xa, 0xf9, 0x6f, 0xc7, 0x97, + 0x9e, 0x65, 0xd1, 00, 0xf1, 0xef, 0x5f, 0x2b, 0x9a, 0xcf, + 0xa1, 0xf1, 0x39, 0xdd, 0x5e, 0x88, 0xf3, 0xdd, 0x56, 0x4c, + 0x2b, 0x57, 0x21, 0x7e, 0xf9, 0x63, 0x5d, 0x36, 0xab, 0x27, + 0xc8, 0xd5, 0xc9, 0x5e, 0x3f, 0x26, 0xbc, 0xfc, 0x24, 0x74, + 0x3c, 0xcc, 0x14, 0x74, 0x33, 0xe7, 0x3c, 0x1a, 0xfa, 0xff, + 00, 0xfe, 0x9, 0xf7, 0xe1, 0x44, 0xbf, 0xbb, 0xd4, 0xef, + 0x9a, 0xdc, 0x39, 0xb9, 0xb9, 0x8a, 0xd7, 0x79, 0x52, 0x70, + 0x17, 0x24, 0xfb, 0x7f, 0x15, 0x7c, 0x79, 0x3b, 0x57, 0xe9, + 0x57, 0xfc, 0x13, 0xf3, 0xc2, 0x46, 0xc3, 0xc1, 0x7a, 0x1d, + 0xcb, 0xc6, 0x11, 0xe7, 0xf3, 0xae, 0x64, 0x52, 0x39, 0xce, + 0xf7, 0x55, 0x3d, 0x3d, 0x14, 0x57, 0xd2, 0xe1, 0x63, 0xef, + 0x5c, 0xfa, 0xfc, 0x14, 0x7d, 0xeb, 0x9f, 0x72, 0x41, 0x91, + 0x81, 0xe8, 0x2a, 0xfc, 0x24, 0xf1, 0x59, 0xf0, 0xe7, 0xd6, + 0xaf, 0xc2, 0x78, 0x15, 0xea, 0x9e, 0xd1, 0xa3, 0x5, 0x5e, + 0x84, 0xf4, 0xac, 0xfb, 0x7c, 0xd5, 0xf8, 0x4f, 0x2, 0x80, + 0x2e, 0xc4, 0x78, 0xab, 0x51, 0xf4, 0xaa, 0x90, 0xd5, 0xb8, + 0xce, 0x28, 0x2, 0xc2, 0xa, 0x9d, 0x2a, 0x4, 0x3c, 0x8a, + 0x99, 0xe, 0x7b, 0x50, 0x4, 0xa3, 0x9a, 0x91, 0x6a, 0x35, + 0xed, 0x52, 0x2d, 00, 0x3d, 0x69, 0x69, 0x1, 0xe2, 0x96, + 0x80, 0x14, 0x75, 0xa5, 0xcd, 0x36, 0x8a, 00, 0x29, 0xa4, + 0xd3, 0x8d, 0x46, 0xd4, 00, 0xc3, 0xe9, 0x4c, 0x63, 0x4f, + 0x3d, 0x6a, 0x26, 0x34, 0x1, 0x1c, 0x87, 0x8a, 0xab, 0x23, + 0x71, 0x56, 0x64, 0x38, 0xaa, 0x92, 0x9a, 00, 0xab, 0x2b, + 0x57, 0x87, 0xfe, 0xd6, 0x9e, 0x32, 0x8b, 0xc3, 0x1f, 0x7, + 0xf5, 0x5b, 0x7c, 0x31, 0xb9, 0xd5, 0x31, 0x69, 0xe, 0xd6, + 0x20, 0xa9, 0x24, 0x12, 0xdd, 0x3b, 0x7f, 0x5a, 0xf6, 0xd9, + 0x8e, 0x2b, 0xe2, 0xaf, 0xdb, 0x8b, 0xc4, 0x8d, 0xa8, 0xf8, + 0xc7, 0xc3, 0x5e, 0x1c, 0x42, 0x7, 0xd9, 0x22, 0x7b, 0x99, + 00, 0xce, 0x4f, 0x98, 0x50, 0x2f, 0xfe, 0x8b, 0x6a, 0xf1, + 0x73, 0x9c, 0x47, 0xd5, 0xb0, 0x35, 0x26, 0xb7, 0x6a, 0xcb, + 0xe6, 0x7c, 0xf6, 0x7f, 0x8a, 0xfa, 0x9e, 0x5d, 0x56, 0xa2, + 0xdd, 0xab, 0x2f, 0x9e, 0x86, 0xaf, 0xec, 0x75, 0xe0, 0xf6, + 0x8a, 0xd2, 0x7d, 0x51, 0xf6, 0xfc, 0xe7, 0x62, 0xf1, 0xce, + 0x32, 0x3f, 0xc2, 0xbe, 0xce, 0xd2, 0x21, 0xd9, 0x12, 0xd7, + 0x8a, 0x7e, 0xcf, 0x7e, 0x1a, 0x1a, 0x27, 0x82, 0x74, 0xe8, + 0xb6, 0x6d, 0x2c, 0xa1, 0xcf, 0x39, 0xeb, 0xff, 00, 0xeb, + 0xaf, 0x77, 0xb0, 0x8f, 0x6a, 0xa8, 0x14, 0x64, 0xf8, 0x7f, + 0xab, 0x60, 0xa1, 0xe, 0xb6, 0xb8, 0x64, 0x18, 0x55, 0x84, + 0xcb, 0xa9, 0x43, 0xab, 0x57, 0xfb, 0xcd, 0x4, 0x18, 0x51, + 0x4e, 0xa2, 0x8a, 0xf6, 0x8f, 0xa1, 0xa, 0x28, 0xa4, 0x3d, + 0x28, 0x3, 0xc6, 0xff, 00, 0x6a, 0xf, 0x16, 0xa7, 0x87, + 0x3e, 0x1e, 0xdd, 0x47, 0xf3, 0xee, 0x94, 0x1f, 0xb9, 0xe9, + 0xb4, 0xf7, 0xaf, 0xc1, 0x8f, 0xda, 0x2f, 0xc4, 0xff, 00, + 0xf0, 0x90, 0x78, 0xe2, 0xed, 0x6, 0xed, 0xab, 0x21, 0xea, + 0x73, 0xdc, 0xd7, 0xed, 0x17, 0xed, 0xb5, 0x75, 0x2a, 0xf8, + 0x3a, 0xf6, 0x4c, 0x8f, 0x2e, 0x28, 0xcf, 0xfe, 0x82, 0x6b, + 0xf0, 0x8f, 0xc7, 0x77, 0xe7, 0x51, 0xf1, 0x6e, 0xa3, 0x3e, + 0xed, 0xe0, 0xce, 0xc0, 0x1c, 0x7a, 0x13, 0x40, 0x1f, 0x50, + 0x7e, 0xc1, 0xde, 0xc, 0x4f, 0x10, 0x7c, 0x4f, 0xd1, 0x53, + 0x6a, 0x1f, 0x2a, 0x65, 0x90, 0x96, 0x1d, 0x31, 0x9a, 0xfd, + 0xc9, 0xf1, 0x5d, 0xf2, 0xe9, 0x5a, 0x4, 0xc7, 0xd1, 0x30, + 0x31, 0x5f, 0x85, 0x9f, 0xb0, 0xcf, 0x8e, 0x17, 0xc2, 0x9e, + 0x39, 0xb7, 0xbb, 0x99, 0xc4, 0x59, 0x91, 0x57, 0x79, 0x19, + 0xf5, 0xed, 0x5f, 0xae, 0x1f, 0x14, 0x7e, 0x33, 0x68, 0x3, + 0xc0, 0xb2, 0x3a, 0xea, 0x4a, 0xf2, 0x8b, 0x72, 0xc4, 0x8, + 0xd8, 0x64, 0xfa, 0x74, 0xa0, 0xf, 0xc9, 0xff, 00, 0xf8, + 0x28, 0x87, 0xc4, 0x65, 0xf1, 0x1f, 0x8f, 0xe, 0x99, 0x11, + 0x93, 0x11, 0x36, 0x58, 0x13, 0xc1, 0xae, 0x23, 0xf6, 0x47, + 0xf0, 0x2c, 0xbe, 0x25, 0xf1, 0xa6, 0x95, 0x12, 0x95, 0x1, + 0xee, 0x23, 0x24, 0xb0, 0xe3, 0x1b, 0x96, 0xbc, 0xef, 0xe3, + 0xc7, 0x89, 0x4f, 0x8c, 0x3e, 0x29, 0x6a, 0x17, 0xb, 0x28, + 0x9a, 0x22, 0xe1, 0x50, 0xa8, 0xc0, 0xaf, 0xb3, 0xff, 00, + 0xe0, 0x9d, 0x9e, 0x16, 0xb0, 0x6f, 0x16, 0x58, 0x5e, 0x5d, + 0x30, 0x55, 0x85, 0x91, 0x89, 0x24, 0x80, 0x30, 0x54, 0xd0, + 0x7, 0xea, 0xc7, 0x86, 0xed, 0xe2, 0xf0, 0x27, 0xc3, 0x8b, + 0x75, 0x97, 0x1, 0x2d, 0xad, 0x83, 0x36, 0xc1, 0x81, 0xf7, + 0x6b, 0xf2, 0x43, 0xf6, 0xf1, 0xf8, 0xf9, 0x6b, 0xe2, 0x29, + 0xf5, 0x1b, 0x2b, 0x4f, 0x3f, 0x73, 0x48, 0x54, 0x92, 0x7b, + 0x64, 0x57, 0xd8, 0x7f, 0xb6, 0x4f, 0xed, 0x61, 0x6b, 0xe1, + 0x3f, 0x8, 0xea, 0x1a, 0x4e, 0x97, 0x77, 0x13, 0x13, 0x19, + 0x52, 0x76, 0x1e, 0xc0, 0x8f, 0xee, 0xd7, 0xe2, 0xe7, 0x8d, + 0x7c, 0x5d, 0x71, 0xe2, 0xbd, 0x4a, 0xe2, 0xe6, 0x79, 0x37, + 0x99, 0x24, 0x2e, 0x4f, 0x4c, 0x93, 0xf8, 0x50, 0x4, 0xdf, + 0xe, 0xb4, 0x19, 0xbc, 0x4b, 0xe2, 0x9b, 0x4b, 0x48, 0xb1, + 0xba, 0x49, 0x54, 0x73, 0xcf, 0x7a, 0xfe, 0x84, 0xbf, 0x65, + 0x1f, 0x1, 0x1f, 0x3, 0xfc, 0x2b, 0xd2, 0xed, 0xdc, 0x26, + 0xe7, 0x8c, 0x11, 0xb5, 0x71, 0xc6, 0x2b, 0xf1, 0xf7, 0xf6, + 0x6, 0xf8, 0x42, 0xde, 0x37, 0xf8, 0x83, 0x5, 0xc4, 0x90, + 0x99, 0x12, 0x12, 0x8d, 0xf7, 0xb1, 0xd7, 0x77, 0x3d, 0x7d, + 0xab, 0xf7, 0x83, 0x47, 0xb0, 0x4d, 0x33, 0x4b, 0xb5, 0xb5, + 0x8c, 0x61, 0x62, 0x8c, 0x28, 0xfc, 0xa8, 0x2, 0xe1, 0xe9, + 0x5c, 0x37, 0x8f, 0xf5, 0x11, 0x5, 0x9c, 0xbd, 0x78, 0x6, + 0xbb, 0x79, 0x1b, 0x64, 0x6c, 0x7d, 0x5, 0x78, 0xf7, 0xc4, + 0xad, 0x40, 0x90, 0xc8, 0xf, 0x53, 0x8a, 0xf0, 0x33, 0x9c, + 0x47, 0xb0, 0xc2, 0xb3, 0xe5, 0xf8, 0x87, 0x13, 0xf5, 0x6c, + 0x14, 0x9f, 0x73, 0xcf, 0x59, 0xbc, 0xc9, 0x19, 0xfd, 0x4e, + 0x68, 0xa4, 0x5f, 0xba, 0x29, 0x6b, 0xf1, 0xb3, 0xf0, 0x1b, + 0xdf, 0x50, 0xa2, 0x8a, 0x28, 0x18, 0x51, 0x45, 0x48, 0x96, + 0xd2, 0xcc, 0x3f, 0x76, 0xb9, 0xa6, 0x93, 0x7b, 0x2, 0x4d, + 0xe8, 0x88, 0xe8, 0xa9, 0xbf, 0xb3, 0xae, 0xc7, 0xfc, 0xb3, + 0xa6, 0x35, 0xa5, 0xc2, 0x75, 0x43, 0x4f, 0x96, 0x6b, 0x74, + 0xca, 0xe4, 0x9a, 0xde, 0x2c, 0x65, 0x14, 0x6d, 0x75, 0x3f, + 0x32, 0xe2, 0x8a, 0x92, 0x7d, 0x42, 0x8a, 0x28, 0xa0, 0x2, + 0x94, 0x36, 0xd3, 0x9a, 0x4a, 0x28, 0x3, 0x7f, 0xc3, 0xfe, + 0x25, 0x6d, 0x3e, 0x75, 0x1, 0x9, 0xfa, 0x1a, 0xf6, 0xbf, + 0xd, 0xea, 0xff, 00, 0xda, 0x96, 0x6a, 0xc7, 0x83, 0x8e, + 0x84, 0xd7, 0xce, 0xab, 0x95, 0x91, 0x48, 0xf5, 0xaf, 0x5a, + 0xf8, 0x6d, 0x7e, 0xd2, 0xe1, 0x4b, 0x70, 0x2b, 0xed, 0x38, + 0x7b, 0x1d, 0x52, 0x35, 0xbd, 0x8c, 0x9e, 0x87, 0xe8, 0x3c, + 0x2b, 0x99, 0x54, 0x8d, 0x7f, 0xab, 0xc9, 0xe8, 0xcf, 0x4b, + 0xc5, 0x2d, 0x20, 0xe9, 0x4b, 0x5f, 0xa7, 0x9f, 0xb2, 0x5, + 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, + 0x40, 0x5, 0x26, 0x78, 0xa5, 0xa4, 0x3d, 0x28, 0x2, 0x8e, + 0xad, 0x70, 0x20, 0xb5, 0x66, 0xf6, 0x35, 0xf3, 0xff, 00, + 0x8a, 0x6f, 0x3e, 0xd7, 0xab, 0x48, 0x7b, 0x3, 0xde, 0xbd, + 0xa3, 0xc6, 0x97, 0x9f, 0x67, 0xd3, 0xe4, 0x39, 0xc7, 0x15, + 0xe0, 0x97, 0x12, 0x19, 0xae, 0x65, 0x73, 0xd4, 0xb5, 0x7e, + 0x71, 0xc4, 0xf5, 0xef, 0x28, 0xd2, 0x47, 0xe4, 0xdc, 0x65, + 0x89, 0xbc, 0xa1, 0x41, 0x7a, 0x91, 0xd1, 0x45, 0x15, 0xf0, + 0x67, 0xe6, 0x61, 0x45, 0x14, 0x50, 0x20, 0x55, 0xf3, 0x26, + 0x8d, 0x7, 0x52, 0x6b, 0xd9, 0xfe, 0x1e, 0xe9, 0xc6, 0x18, + 0x51, 0xbd, 0x5, 0x79, 0x16, 0x8f, 0xf, 0x9f, 0xa8, 0xc6, + 0x7, 0x63, 0x5e, 0xf9, 0xe1, 0x2b, 0x51, 0xd, 0x8a, 0x9c, + 0x60, 0xe2, 0xbe, 0xc7, 0x86, 0xa8, 0x7b, 0x4a, 0xce, 0xa3, + 0xe8, 0x7d, 0xff, 00, 0x8, 0xe1, 0xbd, 0xa6, 0x21, 0xd5, + 0x7d, 0xd, 0xfa, 0x5a, 0x28, 0xaf, 0xd4, 0x8f, 0xd9, 0xc2, + 0x8a, 0x28, 0xa0, 0x2, 0x92, 0x8a, 0x6b, 0xb6, 0x10, 0x9a, + 0x4f, 0x41, 0x37, 0x63, 0x80, 0xf8, 0x95, 0xa9, 0xfd, 0x9e, + 0xc1, 0x97, 0x9e, 0x7d, 0xeb, 0xc6, 0xf3, 0xb8, 0x93, 0xeb, + 0x5e, 0x81, 0xf1, 0x3e, 0xf3, 0x7c, 0xfe, 0x5e, 0x7b, 0xf4, + 0xaf, 0x3f, 0x1d, 0x2b, 0xf1, 0xec, 0xf2, 0xb3, 0xad, 0x8c, + 0x92, 0xec, 0x7e, 0x9, 0xc4, 0x98, 0x8f, 0x6f, 0x8f, 0x92, + 0xed, 0xa0, 0x51, 0x45, 0x15, 0xf3, 0xc7, 0xcb, 0x5, 0x14, + 0x51, 0x43, 0xd8, 0xb, 0x16, 0x51, 0x19, 0x27, 0x51, 0xeb, + 0x5e, 0xf9, 0xe0, 0x7b, 0x1f, 0xb0, 0xe8, 0xa8, 0xa7, 0x92, + 0x79, 0xaf, 0x13, 0xf0, 0xdd, 0xbf, 0xda, 0x2f, 0xe2, 0x5c, + 0x67, 0x9a, 0xfa, 0xb, 0x4b, 0x84, 0x41, 0x65, 0x12, 0x1, + 0xd1, 0x45, 0x7d, 0xff, 00, 0xb, 0xd0, 0xf7, 0xa7, 0x54, + 0xfd, 0x43, 0x83, 0x70, 0xfe, 0xf4, 0xeb, 0x76, 0xd0, 0xb6, + 0x69, 0x68, 0xa2, 0xbf, 0x44, 0x3f, 0x55, 0xa, 0x28, 0xa2, + 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0x10, + 0xd6, 0x6e, 0xb7, 0x70, 0x2d, 0xec, 0xdc, 0x9f, 0x43, 0x5a, + 0x75, 0xca, 0x78, 0xea, 0xef, 0xc8, 0xd3, 0xe4, 0xe7, 0xb5, + 0x71, 0xe2, 0xea, 0x7b, 0x2a, 0x12, 0x97, 0x91, 0xc1, 0x8e, + 0xab, 0xec, 0x70, 0xf3, 0x9f, 0x64, 0x78, 0xb7, 0x88, 0xae, + 0xbe, 0xd7, 0xaa, 0xca, 0xdd, 0x81, 0x35, 0x9b, 0x4f, 0x99, + 0xbc, 0xc9, 0xe4, 0x73, 0xd4, 0xb1, 0x34, 0xca, 0xfc, 0x36, + 0xa4, 0xfd, 0xa4, 0xe5, 0x37, 0xd4, 0xfe, 0x6e, 0xad, 0x37, + 0x56, 0xa4, 0xa6, 0xfa, 0xb0, 0xa2, 0x8a, 0x2b, 0x23, 0x20, + 0xa5, 0x3, 0x26, 0x92, 0x9d, 0x1f, 0x2e, 0x5, 0x1b, 0xe8, + 0x1b, 0xe8, 0x7a, 0x7f, 0xc2, 0x6b, 0x2f, 0x32, 0x59, 0x65, + 0x3d, 0x16, 0xbd, 0x50, 0xa, 0xe1, 0x7e, 0x15, 0xda, 0x79, + 0x3a, 0x54, 0x92, 0xe3, 0x96, 0x35, 0xdd, 0xe, 0xa6, 0xbf, + 0x67, 0xc9, 0x69, 0xfb, 0x3c, 0x14, 0x17, 0x73, 0xfa, 0x7, + 0x87, 0xe9, 0x7b, 0x1c, 0xba, 0x9a, 0xef, 0xa8, 0xb5, 0x9d, + 0xac, 0xda, 0xb, 0xab, 0x39, 0x17, 0x19, 0x38, 0xad, 0x1a, + 0x6b, 0x28, 0x2a, 0x41, 0xe8, 0x6b, 0xd9, 0x9c, 0x54, 0xe2, + 0xe2, 0xfa, 0x9f, 0x41, 0x52, 0xa, 0xa4, 0x1c, 0x1f, 0x53, + 0xe7, 0x7f, 0x14, 0xe9, 0x6f, 0x63, 0x78, 0xf9, 0x23, 0x96, + 0xed, 0x58, 0x60, 0xe6, 0xbd, 0x87, 0xc7, 0x5e, 0x1c, 0x49, + 0x23, 0x79, 0x82, 0xe5, 0xb9, 0xef, 0x5e, 0x47, 0x75, 0x6e, + 0xf6, 0xf2, 0x95, 0xda, 0x47, 0x35, 0xf8, 0xce, 0x6b, 0x82, + 0x96, 0x12, 0xbb, 0xd3, 0x46, 0x7f, 0x3f, 0x67, 0x79, 0x7c, + 0xf0, 0x38, 0x97, 0xa6, 0x8c, 0x8a, 0x8a, 0x28, 0xaf, 0x14, + 0xf9, 0xf0, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 0x1, + 0x69, 0x28, 0xa2, 0x80, 0x10, 0x83, 0xd8, 0xe2, 0x9f, 0x14, + 0xb2, 0xc4, 0x72, 0x24, 0x61, 0xf8, 0xd3, 0x68, 0xa3, 0x6d, + 0x50, 0x2d, 0x35, 0x47, 0x41, 0xa4, 0x78, 0xad, 0xac, 0x1d, + 0x77, 0xb3, 0xb7, 0xe2, 0x6b, 0xd4, 0xfc, 0x2b, 0xe3, 0x48, + 0xb5, 0x28, 0xfc, 0xb0, 0x87, 0x23, 0xb9, 0x35, 0xe1, 0x64, + 0xa, 0xd4, 0xd1, 0x35, 0x89, 0x6c, 0x2e, 0x6, 0xd3, 0x81, + 0x9a, 0xfa, 0x1c, 0xb7, 0x36, 0xad, 0x84, 0xa8, 0xa3, 0x27, + 0xee, 0x9f, 0x55, 0x94, 0xe7, 0xb5, 0xb0, 0x55, 0x14, 0x64, + 0xef, 0x13, 0xe9, 0x4, 0x90, 0x48, 0xa0, 0x8e, 0x86, 0x89, + 0x1b, 0xb, 0x5c, 0x9f, 0x84, 0xbc, 0x43, 0xf6, 0xe8, 0x57, + 0x7b, 0x73, 0x8e, 0xf5, 0xd4, 0x48, 0xfb, 0x97, 0x39, 0xaf, + 0xd6, 0x30, 0xf8, 0x88, 0x62, 0x29, 0xa9, 0xc4, 0xfd, 0xbf, + 0x9, 0x8a, 0x86, 0x2e, 0x92, 0xa9, 0xe, 0xa5, 0x1b, 0xb9, + 0x38, 0x35, 0x85, 0x7e, 0xfc, 0x1a, 0xd6, 0xbc, 0x6e, 0xb5, + 0x83, 0x7c, 0xfc, 0x9a, 0xea, 0x3b, 0xc, 0x4d, 0x46, 0x4c, + 0x29, 0xae, 0x43, 0x52, 0x97, 0x96, 0xfa, 0xd7, 0x4d, 0xa9, + 0x3f, 0x6, 0xb8, 0xfd, 0x4a, 0x4e, 0x5b, 0xeb, 0x40, 0x1c, + 0xe6, 0xaf, 0x2e, 0x33, 0x5c, 0x2e, 0xb5, 0x3f, 0xd, 0x5d, + 0x6e, 0xb1, 0x2f, 0xde, 0xaf, 0x3f, 0xf1, 0x1d, 0xcf, 0x97, + 0x6f, 0x29, 0xcf, 0x6a, 0x4d, 0xd9, 0x5c, 0x4d, 0xd9, 0x5c, + 0xf1, 0xaf, 0x89, 0x3a, 0x98, 0xb, 0x37, 0x5f, 0xf3, 0x8a, + 0xf9, 0x9b, 0xc5, 0x37, 0x66, 0x6b, 0xd9, 0xf, 0x6a, 0xf6, + 0xcf, 0x89, 0x3a, 0x9f, 0x33, 0xc, 0xd7, 0xcf, 0xda, 0xcc, + 0xfb, 0xe6, 0x90, 0xe7, 0xa9, 0xaf, 0x85, 0xc7, 0xd4, 0xe7, + 0xa9, 0x63, 0xf3, 0x5c, 0xd2, 0xa7, 0xb4, 0xad, 0x63, 0x99, + 0xd5, 0xa5, 0xf9, 0x1a, 0xb9, 0x6b, 0x97, 0xce, 0x6b, 0x7b, + 0x56, 0x93, 0x2a, 0xd5, 0xcd, 0xdc, 0x1c, 0xe6, 0xba, 0x70, + 0xd1, 0xb2, 0x3b, 0x70, 0x91, 0xb4, 0x48, 0x60, 0xb5, 0x6b, + 0xfb, 0xeb, 0x6b, 0x68, 0xf1, 0xbe, 0x69, 0x16, 0x35, 0xcf, + 0xa9, 0x20, 0xf, 0xe7, 0x5f, 0xb2, 0x7f, 0xb3, 0x7, 0x86, + 0x6, 0x83, 0xe1, 0x28, 0xd7, 0x6a, 0x2a, 0xc5, 0x4, 0x70, + 00, 00, 0x18, 0x60, 0x37, 0x1c, 0x7f, 0xdf, 0x55, 0xf9, + 0x3b, 0xf0, 0x4b, 0xc3, 0x6b, 0xe2, 0xdf, 0x8a, 0xde, 0x1f, + 0xd3, 0xdc, 0x6e, 0x8c, 0xce, 0x66, 0x3c, 0xe3, 0x1b, 0x14, + 0xb8, 0xee, 0x3b, 0xa8, 0xaf, 0xda, 0xf, 0x85, 0xda, 0x77, + 0xd8, 0x3c, 0x27, 0x6a, 0x48, 0xc3, 0xca, 0x59, 0xc8, 0xfc, + 0x48, 0x1f, 0xa6, 0x2b, 0xe9, 0x70, 0xd1, 0xb4, 0x5b, 0x3e, + 0xbb, 0x7, 0x1b, 0x45, 0xb3, 0xb8, 0x87, 0xa0, 0xab, 0xf0, + 0xf6, 0xaa, 0x30, 0x91, 0xc6, 0x6a, 0xf4, 0x18, 0xcd, 0x76, + 0x9e, 0x81, 0xa1, 0x6f, 0xf5, 0xab, 0xf1, 0xe, 0x95, 0x46, + 0xd6, 0xb4, 0x22, 0xc5, 00, 0x5b, 0x84, 0x1a, 0xb4, 0x83, + 0xa5, 0x55, 0x88, 0x71, 0x56, 0xa3, 0x18, 0xc5, 00, 0x59, + 0x41, 0x53, 0x20, 0xe2, 0xa0, 0x41, 0xc5, 0x4c, 0xbc, 0x1a, + 00, 0x99, 0x45, 0x48, 0x3a, 0x54, 0x4a, 0x4d, 0x48, 0xf, + 0x34, 00, 0xe1, 0xd6, 0x9d, 0x48, 0xb4, 0xb4, 00, 0x53, + 0xb1, 0x48, 0x3a, 0xd3, 0xa8, 0x2, 0x36, 0xa8, 0xc9, 0xe6, + 0x9e, 0x7a, 0xd4, 0x6c, 0x68, 0x1, 0x87, 0xa5, 0x46, 0xdd, + 0xaa, 0x46, 0xa8, 0x98, 0xe4, 0x50, 0x4, 0x32, 0x1a, 0xab, + 0x21, 0xe2, 0xac, 0x49, 0x55, 0x65, 0xa0, 0xa, 0x93, 0x9e, + 0x3a, 0xe2, 0xbf, 0x3b, 0xfc, 0x79, 0x7e, 0x3e, 0x24, 0xfe, + 0xd1, 0x5a, 0x9c, 0xd6, 0xf9, 0x7b, 0x53, 0x72, 0x91, 0x42, + 0x5f, 0xae, 0xc5, 0x51, 0xe9, 0xef, 0x9f, 0x5a, 0xfb, 0xcb, + 0xc7, 0xba, 0xfa, 0x78, 0x67, 0xc2, 0x1a, 0xc6, 0xa8, 0xf2, + 0x88, 0xbe, 0xc9, 0x6b, 0x24, 0xa1, 0x89, 0x3, 0x90, 0xa7, + 0x18, 0xcf, 0x72, 0x6b, 0xe1, 0x7f, 0xd9, 0x77, 0x43, 0x6f, + 0x10, 0xfc, 0x40, 0x96, 0xfe, 0x60, 0x66, 0xd8, 0x4c, 0xac, + 0xf2, 0x2, 0x4e, 0x49, 0x3f, 0xaf, 0x15, 0xf1, 0xb9, 0xfc, + 0x9d, 0x6a, 0x94, 0x30, 0x8b, 0xed, 0x4a, 0xef, 0xe4, 0x7c, + 0x7, 0x13, 0xc9, 0xd7, 0xab, 0x86, 0xc0, 0xc7, 0xed, 0xca, + 0xef, 0xe4, 0x7d, 0xdb, 0xe0, 0xad, 0x38, 0x59, 0x69, 0xf6, + 0xf0, 0x85, 00, 0x22, 0x81, 0x8f, 0xc2, 0xbb, 0xcb, 0x45, + 0xc0, 0xae, 0x7f, 0x42, 0xb7, 0x11, 0xc2, 0xbd, 0xb0, 0x2b, + 0xa5, 0xb7, 0x5c, 0x2d, 0x7d, 0x7c, 0x22, 0xa3, 0x15, 0x15, + 0xd0, 0xfb, 0xc8, 0x45, 0x42, 0xa, 0x2b, 0xa1, 0x35, 0x14, + 0x51, 0x56, 0x58, 0x52, 0x52, 0xd1, 0x40, 0x1f, 0x29, 0x7e, + 0xdf, 0xf3, 0x18, 0x7e, 0x16, 0x5d, 0x45, 0x1f, 0xfa, 0xc9, + 0x54, 0xff, 00, 0xe8, 0x2d, 0xd6, 0xbf, 0x7, 0xfc, 0x5b, + 0x6c, 0x6d, 0x75, 0x9b, 0x84, 0x63, 0x96, 0x2e, 0x4b, 0x1f, + 0x7c, 0x9a, 0xfe, 0x85, 0xff, 00, 0x6a, 0xef, 0x6, 0x45, + 0xe2, 0x7f, 0x1, 0x5f, 0x49, 0x2a, 0x9, 0x56, 0x18, 0x89, + 0x8, 0x47, 0x4, 0xed, 0x3e, 0xd5, 0xf8, 0x21, 0xf1, 0x97, + 0x40, 0x9f, 0x4c, 0xf1, 0x86, 0xa6, 0xcf, 0xf, 0x94, 0x82, + 0x76, 0x55, 0xe3, 0x1c, 0x66, 0x80, 0x39, 0x8f, 0xc, 0x78, + 0x92, 0xf7, 0x42, 0xd4, 0x21, 0x96, 0xda, 0xe1, 0xa1, 0xd8, + 0xc0, 0xe4, 00, 0x6b, 0xd7, 0xf5, 0xbf, 0xda, 0x3, 0x5a, + 0xd4, 0x34, 0x39, 0x6d, 0xa4, 0xd5, 0x26, 0x90, 0x3a, 0x6d, + 0xdb, 0xb5, 0x7a, 0x7a, 0x74, 0xaf, 0x4, 0xe9, 0x4e, 0xf3, + 0x1b, 0x18, 0xdc, 0x71, 0xe9, 0x9a, 00, 0xb0, 0x6e, 0xda, + 0x7b, 0xf3, 0x3c, 0x87, 0x73, 0x16, 0xdc, 0x7d, 0xeb, 0xd9, + 0xbe, 0x1d, 0x7c, 0x6b, 0xd5, 0x3c, 0x7, 0x67, 0x21, 0xb1, + 0xbb, 0x78, 0x58, 0xa1, 0x1f, 0x2e, 0x3d, 0x3d, 0xc1, 0xaf, + 0xf, 0xa7, 0x9, 0x5c, 0xc, 0x6, 0x38, 0xa0, 0xe, 0xe7, + 0xc7, 0x9f, 0x16, 0xf5, 0xcf, 0x1c, 0x5c, 0xca, 0xda, 0x85, + 0xdb, 0xce, 0xac, 0x7f, 0x88, 0x2f, 0x4f, 0xc0, 0xf, 0x5a, + 0xe3, 0xf4, 0xdd, 0x36, 0x6d, 0x4a, 0xea, 0x28, 0x62, 0x42, + 0xec, 0xec, 0x14, 0x62, 0xaa, 0xe0, 0xb1, 0xe9, 0x5f, 0x57, + 0xfe, 0xc9, 0xbf, 0xb3, 0x5d, 0xd7, 0xc4, 0x4d, 0x57, 0x4d, + 0xbe, 0x92, 0xdd, 0x9e, 0xdf, 0xcc, 0xc, 0x4e, 0xc2, 0x72, + 0x39, 0xff, 00, 0x64, 0xd0, 0x7, 0xdf, 0x5f, 0xf0, 0x4d, + 0xbf, 0x82, 0x6d, 0xe1, 0x8d, 0x12, 0x4d, 0x52, 0xee, 0xd9, + 0x11, 0x9d, 0x50, 0xa8, 0x7, 0xa6, 0x37, 0xff, 00, 0x8d, + 0x7d, 0xfa, 0x3a, 0x57, 0x23, 0xf0, 0xc3, 0xc1, 0x16, 0x7e, + 0x5, 0xf0, 0xad, 0x9e, 0x9f, 0x6b, 0x6e, 0x96, 0xe5, 0x63, + 0x1, 0x82, 0x80, 0x32, 0x79, 0xeb, 0xc0, 0xf5, 0xae, 0xba, + 0x80, 0x2a, 0x6a, 0x72, 0x88, 0xad, 0x5c, 0xe7, 0xb5, 0x78, + 0x37, 0x8e, 0x2f, 0x3e, 0xd3, 0xa9, 0x6d, 0x1c, 0xe0, 0x93, + 0x5e, 0xcf, 0xe2, 0x8b, 0x9f, 0x22, 0xc9, 0x86, 0x71, 0xc1, + 0x35, 0xe0, 0x5a, 0xc4, 0xff, 00, 0x69, 0xd4, 0xa5, 0x6c, + 0xf4, 0x35, 0xf9, 0xff, 00, 0x13, 0xd7, 0xb4, 0x63, 0x49, + 0x1f, 0x97, 0x71, 0x8e, 0x26, 0xd1, 0x8d, 0x14, 0x54, 0x1c, + 0x51, 0x45, 0x15, 0xf9, 0xe1, 0xf9, 0x50, 0x51, 0x45, 0x14, + 00, 0x60, 0xb1, 0x3, 0xd4, 0xd7, 0xa6, 0xf8, 0x43, 0xc3, + 0x2, 0xe2, 0xd9, 0x19, 0xa3, 0x7, 0x38, 0xeb, 0x5e, 0x75, + 0xa6, 0x40, 0x6e, 0x2f, 0xe2, 0x4e, 0xbf, 0x30, 0xeb, 0x5e, + 0xff, 00, 0xe1, 0x4b, 0x51, 0x5, 0x92, 0xc, 0x63, 00, + 0x57, 0xd5, 0xf0, 0xfe, 0xe, 0x38, 0x9a, 0xae, 0x53, 0x5a, + 0x23, 0xee, 0x38, 0x5b, 0x3, 0x1c, 0x5d, 0x79, 0x4e, 0x6b, + 0x44, 0x51, 0x1e, 0x10, 0x8b, 0xfe, 0x78, 0x8a, 0xa7, 0x7f, + 0xe0, 0xf8, 0xcc, 0x4d, 0xb6, 0x2e, 0x71, 0x5d, 0xc6, 0x29, + 0xa, 0x82, 0x30, 0x79, 0x1e, 0x95, 0xfa, 0x24, 0xb2, 0xec, + 0x3c, 0x95, 0xac, 0x7e, 0xab, 0x3c, 0xab, 0xd, 0x28, 0xdb, + 0x94, 0xf0, 0x7f, 0x11, 0x78, 0x66, 0x6b, 0x56, 0x66, 0x11, + 0xe0, 0x57, 0x28, 0xc8, 0x50, 0xe1, 0xba, 0x8a, 0xfa, 0xf, + 0xc5, 0x1a, 0x32, 0xde, 0x5a, 0x3e, 0xd4, 0x5e, 0x9e, 0x95, + 0xe1, 0x9a, 0xe5, 0x9f, 0xd9, 0x2f, 0x9d, 0x3d, 0xd, 0x7e, + 0x6d, 0x9d, 0x65, 0xdf, 0x53, 0x9f, 0x34, 0x76, 0x67, 0xe4, + 0x9c, 0x43, 0x94, 0xfd, 0x42, 0xa7, 0x3c, 0x36, 0x66, 0x75, + 0x14, 0x51, 0x5f, 0x32, 0x7c, 0x70, 0x51, 0x45, 0x14, 00, + 0x8e, 0x70, 0xb5, 0xe8, 0x9f, 0xd, 0xa6, 0xf2, 0x98, 0x28, + 0xfb, 0xc6, 0xbc, 0xf0, 0x8c, 0xd7, 0x71, 0xf0, 0xd9, 0x8b, + 0x6a, 0x4a, 0xf, 0xdd, 0x6, 0xbd, 0x9c, 0xa2, 0x5c, 0xb8, + 0xc8, 0x1e, 0xf6, 0x45, 0x3e, 0x5c, 0x7c, 0x2d, 0xd4, 0xf6, + 0xd5, 0xfb, 0xa2, 0x96, 0x9a, 0xad, 0x90, 0x29, 0xd5, 0xfb, + 0x51, 0xfd, 0xc, 0x82, 0x8a, 0x28, 0xa0, 0x61, 0x45, 0x14, + 0x50, 0x1, 0x45, 0x14, 0x50, 0x1, 0x4d, 0x3c, 0xa, 0x75, + 0x47, 0x29, 0xdb, 0x1b, 0x1a, 0x4, 0xcf, 0x3d, 0xf8, 0x97, + 0x7e, 0x12, 0xc9, 0x97, 0x38, 0x3c, 0xd7, 0x8f, 0xe, 0x71, + 0x5d, 0xe7, 0xc4, 0xeb, 0xff, 00, 0x32, 0xe4, 0x44, 0x9, + 0xc1, 0x35, 0xc2, 0x1, 0x81, 0x5f, 0x8d, 0xe7, 0x75, 0xbd, + 0xae, 0x31, 0xf9, 0x1f, 0x81, 0x71, 0x16, 0x23, 0xdb, 0xe3, + 0xe5, 0xe4, 0x14, 0x51, 0x45, 0x78, 0x7, 0xcc, 0x5, 0x4, + 0xe2, 0x8a, 0x47, 0xfb, 0xb4, 0x9, 0xec, 0x74, 0x1e, 0xb, + 0xb4, 0x33, 0xdf, 0x86, 0xc7, 0x7a, 0xf7, 0x9d, 0x26, 0x1f, + 0x26, 0xcd, 0x6, 0x3b, 0x57, 0x91, 0x7c, 0x3a, 0xb2, 0x2d, + 0x22, 0x31, 0x1d, 0x48, 0xaf, 0x67, 0x85, 0x76, 0x46, 0xa0, + 0x76, 0x15, 0xfa, 0x8f, 0xd, 0x50, 0xe4, 0xa0, 0xe7, 0xdc, + 0xfd, 0x9b, 0x84, 0x70, 0xfc, 0x98, 0x67, 0x51, 0xf5, 0x24, + 0xa2, 0x8a, 0x2b, 0xec, 0x8f, 0xd0, 0x2, 0x8a, 0x28, 0xa0, + 0x2, 0xa0, 0xba, 0x7d, 0x90, 0x39, 0xa9, 0xb3, 0x54, 0x35, + 0xa9, 0x3c, 0x9d, 0x3e, 0x56, 0xf4, 0x6, 0xb3, 0xa8, 0xf9, + 0x60, 0xd9, 0x95, 0x59, 0x72, 0x53, 0x94, 0x8f, 0xd, 0xf1, + 0xc5, 0xdf, 0xda, 0x75, 0x67, 0xe7, 0x80, 0x7a, 0x57, 0x36, + 0x3a, 0x56, 0x86, 0xb7, 0x31, 0x9a, 0xfe, 0x56, 0x3d, 0xcd, + 0x67, 0xd7, 0xe1, 0x58, 0xaa, 0x9e, 0xd2, 0xbc, 0xa5, 0xe6, + 0x7f, 0x36, 0x63, 0x6a, 0x3a, 0xb8, 0x99, 0xcd, 0xf7, 0xa, + 0x28, 0xa2, 0xb9, 0x4e, 0x20, 0xa2, 0x8a, 0x28, 0x7b, 0x9, + 0x9d, 0x57, 0x80, 0x6d, 0x4c, 0xda, 0xb2, 0x7a, 0xa, 0xf7, + 0x88, 0x57, 0x6a, 0x28, 0xf4, 0x18, 0xaf, 0x18, 0xf8, 0x61, + 0x16, 0xeb, 0xc3, 0x21, 0x1e, 0x9f, 0xd6, 0xbd, 0xa2, 0x3f, + 0xb8, 0x2b, 0xf5, 0x5e, 0x1b, 0x87, 0x26, 0x15, 0xbe, 0xe7, + 0xed, 0x9c, 0x23, 0x5, 0xc, 0x17, 0x37, 0x71, 0xf4, 0x51, + 0x45, 0x7d, 0x71, 0xf7, 0x41, 0x45, 0x14, 0x50, 0x1, 0x45, + 0x14, 0x50, 0x1, 0x45, 0x14, 0x50, 0x2, 0x31, 0xc0, 0xaf, + 0x33, 0xf8, 0x9d, 0x7f, 0xb6, 0xd8, 0xa0, 0x6e, 0xbc, 0x57, + 0xa3, 0x5d, 0xc9, 0xe5, 0xc0, 0xcd, 0xd3, 0x2, 0xbc, 0x47, + 0xe2, 0x2e, 0xa1, 0xf6, 0x8b, 0xad, 0x99, 0xef, 0x5f, 0x31, + 0x9f, 0xd7, 0xf6, 0x58, 0x57, 0x1e, 0xe7, 0xc7, 0x71, 0x3e, + 0x25, 0x50, 0xc1, 0x4a, 0x3d, 0x59, 0xc7, 0xe, 0x94, 0x50, + 0x6, 0x5, 0x15, 0xf9, 0x1f, 0x43, 0xf0, 0xae, 0x81, 0x45, + 0x14, 0x50, 0x30, 0xab, 0x16, 0x31, 0x19, 0x67, 0x50, 0x3d, + 0x71, 0x55, 0xc9, 0xc0, 0xad, 0x9f, 0xd, 0xda, 0x1b, 0x9b, + 0xd8, 0x94, 0xe, 0xac, 0x2b, 0x6a, 0x30, 0xf6, 0x95, 0x23, + 0x13, 0xa3, 0xd, 0x4f, 0xda, 0xd6, 0x8c, 0x17, 0x53, 0xda, + 0xbc, 0xf, 0x67, 0xf6, 0x3d, 0x16, 0x31, 0x8c, 0x64, 0xf, + 0xe5, 0x5d, 0x10, 0xaa, 0x5a, 0x4c, 0x1e, 0x45, 0x84, 0x29, + 0xe8, 0xa3, 0xf9, 0x55, 0xd1, 0x5f, 0xba, 0x61, 0xa9, 0xfb, + 0x2a, 0x31, 0x87, 0x64, 0x7f, 0x49, 0x61, 0x29, 0x7b, 0x1c, + 0x3c, 0x29, 0xf6, 0x42, 0xd1, 0x45, 0x15, 0xd2, 0x75, 0x95, + 0x6f, 0xac, 0xe3, 0xbc, 0x88, 0xa3, 0xae, 0x45, 0x79, 0x77, + 0x8b, 0xbc, 0x2b, 0x20, 0x67, 0x68, 0xa3, 0xe2, 0xbd, 0x68, + 0xd5, 0x5b, 0xdb, 0x18, 0xee, 0xa2, 0x21, 0x91, 0x49, 0x3e, + 0xa2, 0xbc, 0xac, 0x7e, 0x2, 0x18, 0xd8, 0x59, 0xee, 0x78, + 0x99, 0x9e, 0x5b, 0x4f, 0x30, 0xa4, 0xe3, 0x2d, 0xcf, 0x9a, + 0x6e, 0x2c, 0xa5, 0xb5, 0x94, 0x87, 0x18, 0xc5, 0x45, 0x91, + 0x5e, 0xa5, 0xe2, 0x6f, 0x3, 0xc9, 0x2b, 0xbb, 0xa2, 0xc, + 0x67, 0xb0, 0xff, 00, 0xeb, 0x57, 0x5, 0xa8, 0x78, 0x72, + 0x5b, 0x27, 0x6d, 0xd9, 0xfc, 0xab, 0xf2, 0x7c, 0x66, 0x5b, + 0x5b, 0xb, 0x26, 0xad, 0xa1, 0xf8, 0x86, 0x3f, 0x28, 0xc4, + 0x60, 0xa6, 0xd3, 0x8b, 0xb1, 0x95, 0x45, 0xc, 0x36, 0x1c, + 0x1a, 0x40, 0xd9, 0xaf, 0x26, 0xfd, 0x19, 0xe1, 0xdf, 0x5b, + 0x31, 0x68, 0xa2, 0x8a, 0x6, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x8d, 0x91, 0xf7, 0x78, 0x34, 0xb4, + 0x52, 0x62, 0x67, 0x51, 0xe0, 0xfd, 0x65, 0xed, 0xee, 0xa3, + 0x46, 0x73, 0x8e, 0xf5, 0xec, 0xb6, 0x17, 0xe9, 0x75, 0x6c, + 0x19, 0x4e, 0x70, 0x2b, 0xe7, 0x5b, 0x4b, 0x83, 0x6d, 0x3a, + 0xb6, 0x71, 0xcd, 0x7b, 0x17, 0x84, 0x35, 0x4f, 0x32, 0xc5, + 0x17, 0x24, 0x9c, 0x77, 0xaf, 0xbe, 0xe1, 0xbc, 0x6b, 0xbb, + 0xa3, 0x23, 0xf4, 0xee, 0x12, 0xcc, 0x24, 0xe4, 0xe8, 0x49, + 0x9b, 0xf7, 0x8f, 0xd6, 0xb9, 0xfb, 0xc7, 0xeb, 0x5b, 0x37, + 0xb2, 0x71, 0x9a, 0xc0, 0xbe, 0x6c, 0x3, 0x5f, 0xa3, 0x1f, + 0xac, 0x18, 0x1a, 0x94, 0x9d, 0x6b, 0x90, 0xd4, 0xe4, 0xfb, + 0xf5, 0xd3, 0x6a, 0x72, 0x7d, 0xea, 0xe3, 0xf5, 0x59, 0x30, + 0x1a, 0x80, 0x39, 0x5d, 0x62, 0x5f, 0xbd, 0x5e, 0x6b, 0xe3, + 0x2b, 0xbf, 0x2a, 0xcd, 0xf9, 0xc5, 0x77, 0xda, 0xcc, 0xbf, + 0x7a, 0xbc, 0x9b, 0xe2, 0x15, 0xe6, 0xcb, 0x76, 0x5c, 0x90, + 0x70, 0x6b, 0x1a, 0xd2, 0xe5, 0x83, 0x67, 0x3e, 0x22, 0x5c, + 0x94, 0xdb, 0x3e, 0x7a, 0xf8, 0x8d, 0x7d, 0x9f, 0x37, 0x9f, + 0xf3, 0xc5, 0x78, 0xae, 0xa5, 0x27, 0x5a, 0xf4, 0xaf, 0x88, + 0x37, 0xa5, 0xe5, 0x71, 0x93, 0x9c, 0xd7, 0x96, 0x6a, 0x4f, + 0xc1, 0xe6, 0xbe, 0x2, 0xab, 0xe7, 0xaa, 0x7e, 0x5f, 0x59, + 0xfb, 0x4a, 0xe7, 0x39, 0xaa, 0x3e, 0x41, 0xac, 0x9, 0xdb, + 0xad, 0x6b, 0xea, 0x32, 0x64, 0xb5, 0x62, 0x5c, 0x36, 0x33, + 0x5e, 0xd6, 0x1d, 0x59, 0x1f, 0x47, 0x86, 0x8d, 0xa2, 0x7d, + 0x1, 0xfb, 0x15, 0x78, 0x69, 0xb5, 0x6f, 0x89, 0x37, 0x37, + 0xec, 0xa0, 0xa5, 0xad, 0xb9, 0x44, 0x6c, 0xf2, 0x1d, 0x88, + 0x5f, 0xe4, 0x4d, 0x7e, 0xb8, 0xe8, 0x76, 0xcb, 0x67, 0xa5, + 0xda, 0x40, 0xa3, 0x2, 0x38, 0xc0, 0xfc, 0x7b, 0xd7, 0xe7, + 0x67, 0xfc, 0x13, 0xe3, 0xc1, 0xd1, 0x4b, 0x63, 0x2e, 0xa0, + 0xc8, 0xb2, 0x49, 0x7d, 0x76, 00, 0x2c, 0x73, 0x85, 0x8f, + 0x77, 0x1f, 0xa5, 0x7e, 0x8e, 0xc1, 0xc6, 00, 0x15, 0xf4, + 0xb4, 0x55, 0xa0, 0x8f, 0xad, 0xc3, 0xc6, 0xd4, 0xd1, 0xa1, + 00, 0xab, 0xf0, 0xad, 0x52, 0x87, 0x3c, 0x55, 0xe8, 0x8f, + 0x2, 0xb6, 0x3a, 0xd, 0xb, 0x61, 0xc5, 0x5f, 0x88, 0x55, + 0x2b, 0x6e, 0x95, 0x7a, 0x3a, 00, 0xb7, 0x17, 0x41, 0x56, + 0x63, 0xc7, 0x15, 0x5e, 0x31, 0x56, 0x63, 0x1d, 0x28, 0x2, + 0xc2, 0xc, 0xd4, 0xcb, 0x51, 0x46, 0x2a, 0x55, 0xe9, 0x40, + 0x12, 0x2f, 0x6a, 0x91, 0x6a, 0x31, 0x52, 0x2d, 00, 0x3d, + 0x7a, 0x52, 0xd0, 0x38, 0xa2, 0x80, 0x15, 0x69, 0xd4, 0x8b, + 0x4b, 0x40, 0x10, 0xb7, 0x7a, 0x63, 0x53, 0x9a, 0xa3, 0x63, + 0xcd, 00, 0x31, 0x8d, 0x44, 0xfc, 0xa, 0x91, 0xba, 0x54, + 0x32, 0x1a, 00, 0x86, 0x43, 0x55, 0x65, 0x35, 0x3c, 0x86, + 0xaa, 0x4e, 0x7e, 0x53, 0x40, 0x1f, 0x3f, 0xfe, 0xd9, 0xbe, + 0x29, 0x6d, 0x7, 0xe1, 0x14, 0xf6, 0x71, 0x48, 0xb1, 0xcd, + 0xa9, 0xdc, 0x47, 0x2, 0xe4, 0xe0, 0x90, 0x18, 0x33, 0x1, + 0xcf, 0xa0, 0x3f, 0xad, 0x71, 0x9f, 0xb1, 0xdf, 0x85, 0x7e, + 0xcd, 0xa3, 0x5c, 0x6a, 0xf, 0x11, 0xd, 0x29, 0x50, 0xac, + 0x47, 0x61, 0x9e, 0x9c, 0x7b, 0xd7, 0x37, 0xfb, 0x70, 0xf8, + 0x88, 0x6a, 0x9e, 0x30, 0xf0, 0xf7, 0x87, 0xa1, 0x90, 0xc8, + 0xb6, 0xf1, 0x19, 0xe5, 0x8c, 0x64, 0x6d, 0x90, 0x92, 0x7, + 0x5e, 0x3e, 0xe9, 0x15, 0xef, 0xdf, 00, 0x3c, 0x34, 0x34, + 0x2f, 0x6, 0xe9, 0xf0, 0x14, 0x28, 0xc5, 0x77, 0x30, 0x3e, + 0xbc, 0xd7, 0xc6, 0x47, 0xfd, 0xaf, 0x3b, 0x72, 0xe9, 0x4d, + 0x5b, 0xe6, 0x7e, 0x7d, 0xf, 0xf6, 0xee, 0x23, 0x94, 0xba, + 0x52, 0x8d, 0xbe, 0x67, 0xb2, 0xe9, 0xd1, 0xed, 0x45, 0xad, + 0xa8, 0xc6, 0x14, 0x55, 0xb, 0x48, 0xf8, 0x5a, 0xd1, 0x15, + 0xf6, 0x67, 0xe8, 0x22, 0xd1, 0x45, 0x14, 00, 0x51, 0x45, + 0x66, 0xea, 0x5e, 0x21, 0xd3, 0xf4, 0x90, 0x7e, 0xd5, 0x75, + 0x1c, 0x24, 0x7f, 0x78, 0xd0, 0x5, 0xf, 0x1c, 0x68, 0x6b, + 0xe2, 0x1d, 0x2, 0xe2, 0xcd, 0xa3, 0xf3, 0x3, 0x83, 0xf2, + 0x81, 0x9c, 0xf1, 0x5f, 0x91, 0x1f, 0xb6, 0x9f, 0xec, 0xd9, + 0xa8, 0xc7, 0xad, 0xdc, 0xde, 0xdb, 0x58, 0x4b, 0xd, 0xb0, + 0x25, 0x8b, 0x8, 0xf6, 0x82, 0x72, 0x7d, 0x16, 0xbf, 0x5d, + 0x2d, 0xfe, 0x20, 0x68, 0x57, 0x2c, 0x55, 0x75, 0x2b, 0x72, + 0x7a, 0x63, 0x75, 0x79, 0xd7, 0xc6, 0x1f, 0x86, 0x3a, 0x5f, + 0xc5, 0xd, 0x2d, 0xe1, 0x49, 0x63, 0x98, 0xb2, 0x9e, 0x51, + 0x80, 0x3d, 0xe8, 0x3, 0xf9, 0xd6, 0xd7, 0xf4, 0x9, 0x74, + 0x3b, 0xb6, 0x86, 0x51, 0x86, 0x4, 0xf0, 0x7f, 0xfd, 0x55, + 0x93, 0x5f, 0xa5, 0x3f, 0x1b, 0xbf, 0x60, 0xa4, 0xb7, 0xbb, + 0x96, 0xed, 0x2d, 0x2e, 0x32, 0x73, 0x8d, 0xb2, 0x8e, 0x79, + 0xff, 00, 0x7a, 0xbe, 0x72, 0xbd, 0xfd, 0x91, 0xee, 0x60, + 0x99, 0x90, 0x59, 0xdc, 0x8c, 0x1c, 0x7f, 0xac, 0x7, 0xfa, + 0xd0, 0x7, 0xcc, 0x75, 0x7f, 0x4d, 0xd0, 0xef, 0x75, 0x67, + 0x9, 0x6b, 0x3, 0xca, 0xc7, 0x80, 0x14, 0x75, 0xaf, 0xa6, + 0xf4, 0x1f, 0xd8, 0x9b, 0x56, 0xd7, 0xa7, 0xf2, 0xe1, 0xb5, + 0xbc, 0x27, 0x3d, 0x99, 0x7f, 0xc6, 0xbe, 0x9e, 0xf8, 0x23, + 0xff, 00, 0x4, 0xe9, 0xbe, 0xd3, 0x6e, 0x2d, 0x6e, 0xef, + 0xec, 0x2e, 0xda, 0x35, 0x60, 0x49, 0x77, 0x4c, 0x75, 0x1e, + 0xf4, 0x1, 0xf2, 0xbf, 0xec, 0xdf, 0xfb, 0x2a, 0x78, 0x83, + 0xc7, 0x5a, 0xd4, 0x7f, 0x6e, 0xd1, 0xe7, 0x10, 0x6f, 0x1c, + 0xbc, 0x67, 0x18, 0xf7, 0xca, 0x9a, 0xfd, 0x9b, 0xfd, 0x9f, + 0xbe, 00, 0x69, 0x1f, 0xc, 0x7c, 0x2d, 0x60, 0x89, 0x6c, + 0x91, 0xdc, 0x2a, 0x2, 0x54, 0x46, 0xa3, 0x1f, 0xf8, 0xe8, + 0xad, 0x8f, 0x84, 0xbf, 0x4, 0x74, 0x4f, 00, 0xe9, 0xc8, + 0x23, 0xd3, 0xc4, 0x73, 0x80, 0x39, 0x63, 0x9e, 0xc2, 0xbd, + 0x4d, 0x50, 0x20, 00, 0xc, 0x28, 0xe8, 0x5, 00, 0x28, + 0x18, 0x14, 0xb4, 0x87, 0xa5, 0x32, 0x46, 0xd8, 0xa4, 0xfa, + 0xa, 0x5b, 0x6, 0xc7, 0xf, 0xf1, 0xb, 0x50, 0xf2, 0x6d, + 0x64, 00, 0xe3, 0x8c, 0x57, 0x8a, 0x96, 0x2f, 0x23, 0xb1, + 0xee, 0x4d, 0x7a, 0x27, 0xc4, 0xbd, 0x43, 0x24, 0xc6, 0xf, + 0x27, 0xb5, 0x79, 0xd2, 0xf4, 0xaf, 0xc8, 0x33, 0xda, 0xfe, + 0xdb, 0x16, 0xd7, 0x63, 0xf0, 0x5e, 0x25, 0xc4, 0x7b, 0x7c, + 0x6b, 0x8d, 0xf6, 0x16, 0x8a, 0x28, 0xaf, 0x9c, 0x3e, 0x50, + 0x28, 0xa2, 0x83, 0x43, 0x3, 0x7f, 0xc1, 0x36, 0x5f, 0x6a, + 0xd5, 0x15, 0x88, 0x27, 0x6, 0xbd, 0xef, 0x4c, 0x88, 0x45, + 0x6c, 0xa0, 0x57, 0x92, 0xfc, 0x33, 0xd3, 0xf7, 0x3f, 0x9a, + 0x57, 0x8c, 0xf5, 0xaf, 0x62, 0x85, 0x76, 0x46, 0x7, 0xb5, + 0x7e, 0xa5, 0xc3, 0x74, 0x39, 0x30, 0xfc, 0xef, 0xa9, 0xfb, + 0x3f, 0x8, 0xe1, 0xbd, 0x96, 0x13, 0xda, 0x35, 0xb9, 0x25, + 0x14, 0x51, 0x5f, 0x62, 0x7d, 0xf1, 0xd, 0xd2, 0x6f, 0x81, + 0xd7, 0xd4, 0x57, 0x88, 0x7c, 0x41, 0xb2, 0xfb, 0x35, 0xe1, + 0x2a, 0x39, 0x26, 0xbd, 0xd1, 0xba, 0x57, 0x92, 0x7c, 0x4b, + 0xb7, 0xcc, 0xed, 0x21, 0x18, 0x2, 0xbe, 0x53, 0x88, 0xa9, + 0x29, 0xe1, 0x5c, 0xbb, 0x1f, 0x15, 0xc5, 0x54, 0x55, 0x4c, + 0x13, 0x97, 0x63, 0xcd, 0x68, 0xa4, 0x53, 0x9c, 0xd2, 0xd7, + 0xe4, 0xc8, 0xfc, 0x39, 0x5, 0x14, 0x51, 0x4c, 0x60, 0x78, + 0x15, 0xda, 0xfc, 0x3e, 0x95, 0x61, 0xb8, 0x51, 0xc6, 0xe2, + 0x6b, 0x8a, 0xae, 0xb7, 0xc0, 0x7, 0x76, 0xa6, 0xa0, 0xf4, + 0x6, 0xbd, 0x4c, 0xb1, 0xdb, 0x15, 0xb, 0x77, 0x3d, 0x8c, + 0x9e, 0x5c, 0xb8, 0xd8, 0x58, 0xf7, 0x58, 0xbe, 0xe2, 0xfd, + 0x29, 0xfd, 0xe9, 0x91, 0x30, 0x64, 0x52, 0x3d, 0x29, 0xe2, + 0xbf, 0x6e, 0x5b, 0x1f, 0xd1, 0x6b, 0x64, 0x2d, 0x14, 0x51, + 0x4c, 0xa0, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, + 0xaa, 0x5a, 0x94, 0xe2, 0xb, 0x57, 0x24, 0xf6, 0xab, 0xb5, + 0xce, 0x78, 0xc6, 0xf0, 0x5b, 0x69, 0xd2, 0x1d, 0xd8, 0xe2, + 0xb9, 0xb1, 0x35, 0x3d, 0x95, 0x29, 0x4f, 0xb1, 0xc9, 0x8b, + 0xab, 0xec, 0x68, 0x4a, 0x6f, 0xa2, 0x3c, 0x63, 0xc6, 0x17, + 0xa2, 0xf3, 0x56, 0x72, 0xe, 0x42, 0xd6, 0x1d, 0x4d, 0x79, + 0x31, 0x9e, 0xee, 0x57, 0x3d, 0xda, 0xa1, 0xaf, 0xc3, 0x2b, + 0xd4, 0x75, 0x6a, 0xca, 0x6f, 0xab, 0x3f, 0x9b, 0x71, 0x35, + 0x5d, 0x6a, 0xf3, 0xa8, 0xfa, 0xb0, 0xa2, 0x8a, 0x2b, 0x3, + 0x9c, 0x29, 0xa, 0xee, 0x65, 0x5f, 0x53, 0x4b, 0x53, 0xe9, + 0x90, 0xfd, 0xa2, 0xfe, 0x35, 0x3, 0x38, 0x34, 0xd4, 0x79, + 0x9a, 0x8a, 0xea, 0x38, 0xc7, 0x9e, 0x4a, 0x2b, 0xa9, 0xeb, + 0x1f, 0xf, 0x74, 0xfd, 0x91, 0xc6, 0xdb, 0x7d, 0xeb, 0xd1, + 0x47, 0x15, 0xcd, 0x78, 0x36, 0xd3, 0xc9, 0xb3, 0x7, 0x18, + 0xe2, 0xba, 0x6c, 0x75, 0xaf, 0xdb, 0x72, 0xca, 0x5e, 0xc7, + 0xd, 0x14, 0x7f, 0x44, 0xe4, 0xf4, 0x15, 0xc, 0x24, 0x22, + 0x2d, 0x14, 0x51, 0x5e, 0xa9, 0xed, 0x85, 0x14, 0x51, 0x40, + 0x8, 0x6b, 0xb, 0xc5, 0xf2, 0x98, 0xb4, 0xa9, 0x31, 0xdc, + 0x1a, 0xde, 0xae, 0x77, 0xc6, 0x43, 0x36, 0x4, 0x76, 0xc5, + 0x71, 0xe3, 0x1d, 0xa8, 0x4e, 0xdd, 0x8e, 0xc, 0x7b, 0x6b, + 0xd, 0x3b, 0x76, 0x3c, 0x13, 0x53, 0x38, 0xb9, 0x23, 0xbe, + 0x6a, 0xb5, 0x58, 0xd4, 0x9b, 0x75, 0xf4, 0x9f, 0x5a, 0xaf, + 0x5f, 0x86, 0x54, 0xf8, 0xe4, 0x7f, 0x36, 0xd5, 0xd6, 0xa4, + 0x98, 0x51, 0x45, 0x15, 0x99, 0x98, 0x52, 0x31, 0xc0, 0xa5, + 0xa0, 0x8d, 0xd8, 0xa1, 0x89, 0xec, 0x7a, 0x6f, 0xc3, 0x5b, + 0x70, 0x81, 0x78, 0xe6, 0xbd, 0x61, 0x46, 0x14, 0x57, 0x94, + 0x7c, 0x33, 0x2d, 0x2c, 0xff, 00, 0xec, 0x8a, 0xf5, 0x71, + 0x5f, 0xb0, 0x64, 0x4b, 0xfd, 0x8e, 0x36, 0x3f, 0x7a, 0xe1, + 0xa4, 0x96, 0x6, 0x2d, 0xb, 0x45, 0x14, 0x57, 0xd1, 0x9f, + 0x58, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x4d, 0x24, 0x1, 0xcf, 0x14, 0x1, 0x8d, 0xe2, 0x7d, + 0x41, 0x6c, 0xec, 0xce, 0x58, 0xc, 0xfa, 0xd7, 0x82, 0xf8, + 0x86, 0xf3, 0xed, 0x9a, 0x8b, 0x1c, 0xe7, 0x7, 0xd6, 0xbd, + 0x1b, 0xe2, 0x4e, 0xba, 0xaa, 0xfe, 0x4a, 0x3f, 0x23, 0xd2, + 0xbc, 0xa5, 0xcf, 0x99, 0x23, 0x31, 0xee, 0x6b, 0xf2, 0xde, + 0x23, 0xc6, 0x2a, 0xb5, 0xbd, 0x94, 0x7a, 0x1f, 0x8b, 0xf1, + 0x66, 0x3f, 0xdb, 0x57, 0xf6, 0x11, 0x7a, 0x21, 0x28, 0xa2, + 0x8a, 0xf8, 0xe3, 0xe0, 0x82, 0x8a, 0x28, 0xa0, 0x4, 0x6e, + 0x46, 0x2b, 0xbb, 0xf8, 0x7f, 0xa6, 0x99, 0xaf, 0xa3, 0x25, + 0x4e, 0x1, 0xae, 0x1e, 0x4, 0x32, 0xdc, 0xc6, 0x83, 0xa9, + 0x23, 0x8a, 0xf6, 0x7f, 0x87, 0xfa, 0x4f, 0xd9, 0xe3, 0x12, + 0x15, 0x23, 0x23, 0x39, 0xaf, 0xa0, 0xc8, 0xf0, 0xde, 0xdf, + 0x12, 0x9f, 0x44, 0x7d, 0x4f, 0xe, 0x61, 0x1e, 0x27, 0x18, + 0x9f, 0x44, 0x77, 0x48, 0xbb, 0x42, 0x8f, 0x41, 0x4e, 0x14, + 0xb4, 0x57, 0xec, 0x67, 0xef, 0x76, 0xa, 0x28, 0xa2, 0x81, + 0x85, 0x21, 0xa5, 0xa2, 0x80, 0x20, 0x96, 0x15, 0x99, 0x76, + 0xb0, 0xac, 0x1d, 0x53, 0xc2, 0x10, 0x5e, 0xab, 0x1c, 0x2, + 0x6b, 0xa5, 0xa4, 0x35, 0xcf, 0x56, 0x85, 0x3a, 0xca, 0xd5, + 0x15, 0xce, 0x5a, 0xf8, 0x6a, 0x58, 0x85, 0x6a, 0x91, 0xb9, + 0xe4, 0x3a, 0xc7, 0x80, 0x12, 0x1d, 0xc5, 0x53, 0xf4, 0xff, + 00, 0xeb, 0x57, 0x1d, 0xa9, 0xe8, 0x8d, 0x66, 0x4f, 0xc8, + 0xdc, 0x7b, 0x57, 0xd0, 0xf3, 0x59, 0x45, 0x36, 0x77, 0x2e, + 0x73, 0x58, 0x7a, 0xb7, 0x84, 0xad, 0x6e, 0x50, 0x9d, 0x9c, + 0xd7, 0xc8, 0x63, 0x78, 0x7a, 0x35, 0x13, 0x95, 0x1d, 0x19, + 0xf0, 0x99, 0x8f, 0xb, 0x42, 0xa2, 0x72, 0xa0, 0x92, 0x3e, + 0x7d, 0x60, 0xca, 0x70, 0x54, 0xfe, 0x22, 0x94, 0x74, 0xaf, + 0x46, 0xd7, 0x3c, 0x1b, 0xe5, 0x6, 0x31, 0xc4, 0x4d, 0x70, + 0xba, 0x86, 0x9b, 0x3d, 0xa3, 0xb6, 0xe8, 0xc8, 0x1e, 0xf5, + 0xf0, 0x78, 0xac, 0xd, 0x6c, 0x2b, 0xb4, 0x91, 0xf9, 0x9e, + 0x33, 0x2d, 0xaf, 0x82, 0x7e, 0xfa, 0xd0, 0xa7, 0x45, 0x3, + 0x3d, 0xe8, 0xaf, 0x3c, 0xf2, 0xc2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0x3d, 0x29, 0x31, 0x32, 0x23, 0xc3, 0x29, 0x3d, + 0x8d, 0x7a, 0x37, 0x80, 0x2f, 0xc, 0xe4, 0x29, 0x38, 0x51, + 0x5e, 0x6f, 0x31, 0xda, 0xb5, 0xd9, 0xf8, 0x12, 0xe7, 0xc9, + 0xc7, 0x3f, 0x31, 0xff, 00, 0xeb, 0x57, 0xb9, 0x92, 0x4b, + 0x93, 0x14, 0x8f, 0xa3, 0xe1, 0xda, 0x9e, 0xcf, 0x1a, 0x8f, + 0x49, 0xbd, 0x97, 0x2b, 0x58, 0x1a, 0x84, 0x98, 0x52, 0x2b, + 0x56, 0x59, 0x33, 0x12, 0x9f, 0x6a, 0xc2, 0xd4, 0x5f, 00, + 0xd7, 0xec, 0xe9, 0xdd, 0x5c, 0xfe, 0x81, 0x8b, 0xba, 0xb9, + 0xce, 0xea, 0x52, 0x75, 0xe6, 0xb8, 0xfd, 0x5e, 0x4f, 0xbd, + 0xcd, 0x75, 0x1a, 0x8c, 0x9d, 0x6b, 0x8c, 0xd6, 0x65, 0xfb, + 0xd4, 0xca, 0x39, 0x1d, 0x66, 0x6e, 0x5b, 0x9a, 0xf1, 0x1f, + 0x89, 0x5a, 0x87, 0xfa, 0xd0, 0xf, 0x6a, 0xf6, 0x1d, 0x6e, + 0x6c, 0x24, 0x87, 0xda, 0xbe, 0x7a, 0xf8, 0x95, 0xa8, 0x65, + 0xa5, 0xe7, 0xd7, 0xf9, 0xd7, 0x9d, 0x8e, 0x9f, 0x2d, 0x23, + 0xca, 0xcc, 0x67, 0xc9, 0x44, 0xf0, 0x4f, 0x19, 0xdd, 0x79, + 0xb7, 0x6c, 0x33, 0xde, 0xbc, 0xff, 00, 0x52, 0x93, 0x19, + 0xae, 0xb3, 0xc4, 0x57, 0x1e, 0x6d, 0xdc, 0xa7, 0x35, 0xc5, + 0x6a, 0x72, 0x7d, 0xea, 0xf8, 0x9a, 0x7e, 0xf4, 0xee, 0x7e, + 0x77, 0x45, 0x73, 0x54, 0x6c, 0xe7, 0xef, 0x5f, 0x25, 0xab, + 0x22, 0xe0, 0xe7, 0x23, 0xae, 0x6b, 0x4a, 0xe9, 0xbe, 0xf5, + 0x57, 0xd3, 0x6c, 0xe4, 0xd4, 0xb5, 0x8b, 0x2b, 0x58, 0x90, + 0xc9, 0x24, 0xb3, 0x22, 0x5, 0xce, 0x33, 0x93, 0x5f, 0x47, + 0x45, 0x6c, 0x8f, 0xac, 0xc3, 0xc6, 0xf6, 0x47, 0xe9, 0xef, + 0xec, 0x31, 0xe1, 0x6f, 0xec, 0x9f, 0x2, 0x68, 0x5, 0xad, + 0xda, 0x16, 0xfb, 0x17, 0xda, 0x18, 0x3a, 0x5, 0x3b, 0xdf, + 0x4, 0xff, 00, 0x33, 0xef, 0x5f, 0x5d, 0x5b, 0x8e, 0x95, + 0xe4, 0x7f, 0xb3, 0xf6, 0x83, 0x1e, 0x8b, 0xe1, 0x8d, 0x91, + 0xae, 0x22, 0x44, 0x8e, 0x28, 0xfd, 0x82, 0xaf, 0x23, 0xf9, + 0x57, 0xaf, 0x40, 0x38, 0x15, 0xf4, 0x51, 0x56, 0x56, 0x3e, + 0xae, 0x2b, 0x95, 0x24, 0x5f, 0x84, 0x70, 0x2a, 0xf4, 0x23, + 0x91, 0x54, 0xed, 0xc5, 0x5e, 0x82, 0xa8, 0xa3, 0x42, 0xdd, + 0x78, 0xab, 0xd1, 0x2f, 0x35, 0x4a, 0xdc, 0x74, 0xab, 0xd1, + 0xe, 0x68, 0x2, 0xdc, 0x62, 0xac, 0xc6, 0x2a, 0xbc, 0x43, + 0x22, 0xac, 0xc6, 0x28, 0x2, 0x74, 0x15, 0x2a, 0x8a, 0x62, + 0x8e, 0x2a, 0x41, 0xd6, 0x80, 0x1e, 0xb5, 0x20, 0xed, 0x4c, + 0x5a, 0x90, 0x75, 0xa0, 0x7, 0x51, 0x45, 0x14, 00, 0xe1, + 0xd2, 0x96, 0x90, 0x52, 0xd0, 0x5, 0x76, 0x35, 0x1b, 0x53, + 0xcd, 0x46, 0xd4, 00, 0xd6, 0x35, 0x5e, 0x43, 0x53, 0x31, + 0xaa, 0xd2, 0x1a, 00, 0x82, 0x43, 0x54, 0xaf, 0x25, 0x58, + 0x21, 0x79, 0x1c, 0xed, 0x45, 0x5, 0x98, 0x9e, 0xc0, 0x77, + 0xab, 0x72, 0x1a, 0xe2, 0x3e, 0x2e, 0xf8, 0x8d, 0xbc, 0x2b, + 0xf0, 0xe7, 0xc4, 0x3a, 0xa2, 0x22, 0xc8, 0xd6, 0xf6, 0x72, + 0x30, 0x57, 0x6d, 0xa0, 0xe4, 0x63, 0xaf, 0xe3, 0x59, 0xd4, + 0x9a, 0xa7, 0x9, 0x4d, 0xec, 0x8c, 0xaa, 0xcd, 0x52, 0xa7, + 0x2a, 0x8f, 0x64, 0xae, 0x7c, 0x41, 0xab, 0x5d, 0xb7, 0xc5, + 0x3f, 0xda, 0x33, 0x51, 0x98, 0xb1, 0xba, 0xb6, 0x37, 0xc6, + 0x18, 0xc9, 0xe3, 0x31, 0xc7, 0xf2, 0x8f, 0x4e, 0x30, 0xbd, + 0xeb, 0xef, 0xaf, 0x7, 0xe9, 0xcb, 0x67, 0x67, 0xc, 0x6a, + 0xbb, 0x55, 0x54, 00, 0x2b, 0xe1, 0xcf, 0xd9, 0x1b, 0xc3, + 0x87, 0x54, 0xf1, 0x44, 0xba, 0x94, 0xc0, 0xb3, 0x44, 0x33, + 0xb8, 0xaf, 0x56, 0x20, 0xe7, 0xf9, 0xd7, 0xdf, 0x9a, 0x1d, + 0xb8, 0x48, 0x57, 0x15, 0xf2, 0x9c, 0x3b, 0x7, 0x52, 0x9d, + 0x4c, 0x54, 0xb7, 0x9c, 0x9f, 0xdc, 0x7c, 0x47, 0xa, 0x41, + 0xd4, 0xa7, 0x57, 0x1b, 0x3d, 0xea, 0x49, 0xfd, 0xc6, 0xed, + 0xb4, 0x78, 0xab, 0x34, 0xd4, 0x5d, 0xaa, 0x29, 0xd5, 0xf5, + 0xe7, 0xde, 0x5, 0x14, 0x51, 0x40, 0x15, 0xf5, 0xb, 0x91, + 0x67, 0x65, 0x3c, 0xec, 0x70, 0x23, 0x42, 0xd5, 0xf9, 0x5f, + 0xfb, 0x6e, 0x7e, 0xd2, 0x7a, 0xf6, 0x81, 0x75, 0x7a, 0x9a, + 0x76, 0xac, 0xf6, 0xe4, 0x64, 0x2e, 0x22, 0x53, 0xf8, 0x72, + 0xb5, 0xfa, 0x5b, 0xf1, 0x3b, 0x50, 0x93, 0x4f, 0xf0, 0x66, + 0xa0, 0xf1, 0xc, 0xc8, 0xc9, 0xb4, 0x1, 0xf8, 0x57, 0xe1, + 0x3f, 0xed, 0xb5, 0xe2, 0x9, 0xee, 0x3c, 0x59, 0x2d, 0xac, + 0x87, 0xef, 0x37, 0x73, 0xc9, 0x1f, 0x4e, 0xd4, 0x1, 0xc8, + 0xe9, 0x7f, 0xb5, 0x5f, 0xc4, 0x8, 0x27, 0x7, 0xfe, 0x12, + 0x16, 0xe4, 0xff, 00, 0xcf, 0xbc, 0x5f, 0xfc, 0x45, 0x7d, + 0xc9, 0xfb, 0x1f, 0x7c, 0x60, 0xf1, 0x97, 0x8f, 0xf5, 0x9b, + 0xb, 0x6b, 0xed, 0x5d, 0xe7, 0x8d, 0xca, 0x86, 0x1e, 0x5a, + 0x1, 0x83, 0xf4, 0x51, 0x5f, 0x96, 0x1a, 0x44, 0x3f, 0x69, + 0xd4, 0x60, 0x8c, 0x9e, 0xb, 0xa, 0xfd, 0x69, 0xff, 00, + 0x82, 0x69, 0xf8, 0x22, 0x1b, 0xad, 0x45, 0x2f, 0x8a, 0x87, + 0x10, 0x80, 0xdf, 0x30, 0xe0, 0x60, 0x3, 0xeb, 0xd6, 0x80, + 0x3f, 0x45, 0x2e, 0xbc, 0x17, 0xa4, 0xea, 0x96, 0x89, 0x15, + 0xe5, 0xa8, 0x9b, 0xa, 0x1, 0xcb, 0x11, 0x9f, 0xc8, 0xd6, + 0x4, 0xbf, 0x3, 0xbc, 0x1d, 0x2b, 0x16, 0x3a, 0x4a, 0x67, + 0xfd, 0xf7, 0xff, 00, 0x1a, 0xef, 0x47, 0x14, 0xb4, 0x1, + 0xc8, 0x69, 0x3f, 0xa, 0x7c, 0x37, 0xa2, 0x49, 0xbe, 0xd7, + 0x4f, 0x58, 0xcf, 0xb3, 0x37, 0xf8, 0xd7, 0x57, 0xc, 0x29, + 0x4, 0x61, 0x10, 0x6d, 0x50, 0x30, 0x7, 0xa5, 0x49, 0x45, + 00, 0x25, 0x2d, 0x14, 0x50, 0x2, 0x55, 0x3d, 0x4e, 0x6f, + 0x22, 0xd2, 0x46, 0xf6, 0x35, 0x70, 0xf4, 0xac, 0xf, 0x16, + 0xdd, 0xfd, 0x9e, 0xc5, 0xf0, 0x7b, 0x66, 0xb9, 0xf1, 0x13, + 0xf6, 0x74, 0xa5, 0x23, 0x97, 0x15, 0x53, 0xd9, 0x51, 0x94, + 0xfb, 0x23, 0xc6, 0x3c, 0x6d, 0x7a, 0x6e, 0xb5, 0x46, 0x5d, + 0xdc, 0x3, 0xfd, 0x4d, 0x60, 0x55, 0x9d, 0x52, 0x63, 0x71, + 0xa8, 0xca, 0xe4, 0xe7, 0x9a, 0xad, 0x5f, 0x86, 0x62, 0x2a, + 0x7b, 0x5a, 0xd2, 0x9b, 0xea, 0xcf, 0xe6, 0xec, 0x55, 0x57, + 0x5a, 0xbc, 0xea, 0x3e, 0xac, 0x28, 0xa2, 0x8a, 0xe7, 0x39, + 0x42, 0x94, 0xd, 0xcc, 0xaa, 0x3b, 0x9c, 0x52, 0x55, 0xad, + 0x2a, 0xf, 0xb4, 0xea, 0x31, 0x27, 0xb8, 0xab, 0x8c, 0x79, + 0xa4, 0xa3, 0xdc, 0xa8, 0x45, 0xce, 0x4a, 0x2b, 0xa9, 0xec, + 0x1f, 0xe, 0xb4, 0xd1, 0x5, 0x84, 0x67, 0x6f, 0x38, 0xeb, + 0x5d, 0xd8, 0x18, 0x15, 0x87, 0xe1, 0x6b, 0x41, 0x6f, 0x60, + 0x9c, 0x63, 0xe5, 0x15, 0xb8, 0x2b, 0xf6, 0xfc, 0x5, 0x2f, + 0x63, 0x87, 0x84, 0x7c, 0x8f, 0xe8, 0xec, 0xae, 0x82, 0xc3, + 0xe1, 0x61, 0xf, 0x21, 0x68, 0xa2, 0x8a, 0xf4, 0x4f, 0x54, + 0x42, 0x33, 0x5e, 0x65, 0xf1, 0x45, 0x31, 0x16, 0xd5, 0xe7, + 0x3d, 0x6b, 0xd3, 0x6b, 0xce, 0xfe, 0x24, 0x28, 0x31, 0x33, + 0x1e, 0xc2, 0xbc, 0x2c, 0xe6, 0x3c, 0xd8, 0x39, 0xa3, 0xe6, + 0xf8, 0x82, 0x3c, 0xd8, 0x9, 0xa3, 0xc7, 0xb1, 0xb4, 0x90, + 0x28, 0xa4, 0x7, 0x73, 0x13, 0xeb, 0x4b, 0x5f, 0x8c, 0xa3, + 0xf9, 0xf4, 0x28, 0xa2, 0x8a, 0x6, 0x7, 0xa5, 0x74, 0xde, + 0x7, 0x90, 0xc5, 0x7a, 0xa0, 0x7d, 0xe6, 0x35, 0xcc, 0x9e, + 0x95, 0xd1, 0xf8, 0x24, 0xe7, 0x55, 0x4c, 0xf4, 0x6, 0xbb, + 0xb0, 0x3f, 0xef, 0x30, 0xf5, 0x3d, 0x2c, 0xb5, 0xdb, 0x17, + 0x4f, 0xd5, 0x1e, 0xf7, 0x68, 0xbb, 0x6d, 0xd0, 0x1f, 0x4a, + 0x9e, 0xa1, 0xb5, 0x71, 0x24, 0x2a, 0x45, 0x4d, 0x5f, 0xb9, + 0x43, 0xe1, 0x47, 0xf4, 0x84, 0x2d, 0xca, 0xac, 0x2d, 0x14, + 0x51, 0x56, 0x58, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x21, + 0xa0, 0x2, 0xbc, 0xe7, 0xe2, 0x6e, 0xa4, 0x61, 0xb3, 0x64, + 0xc, 0x79, 0xaf, 0x43, 0x95, 0xb6, 0xc6, 0x4d, 0x78, 0xb7, + 0xc4, 0xcd, 0x40, 0xcb, 0x73, 0xe5, 0x67, 0x3f, 0x35, 0x7c, + 0xe6, 0x7b, 0x5f, 0xd8, 0xe1, 0x24, 0xbb, 0x9f, 0x25, 0xc4, + 0xb8, 0x9f, 0x61, 0x81, 0x97, 0x99, 0xc3, 0xe, 0x79, 0xf5, + 0xa2, 0x81, 0xd2, 0x8a, 0xfc, 0x7c, 0xfc, 0x19, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x6e, 0x78, 0x36, 0xd3, 0xed, 0x37, 0xe0, + 0xe3, 0xb8, 0xac, 0x26, 0x38, 0x53, 0x5d, 0xdf, 0xc3, 0xcb, + 0xd, 0xd2, 0xab, 0x11, 0xe9, 0x5e, 0x8e, 0x5f, 0x49, 0xd6, + 0xc5, 0x46, 0x27, 0xad, 0x95, 0x50, 0x75, 0xf1, 0x90, 0x89, + 0xeb, 0xba, 0x3d, 0xb8, 0x82, 0xc9, 00, 0x18, 0xe2, 0xaf, + 0xd4, 0x70, 0x2e, 0xc8, 0x94, 0xe, 0xc2, 0xa4, 0xaf, 0xdb, + 0xe1, 0x1e, 0x58, 0xa4, 0x7f, 0x46, 0x53, 0x8f, 0x24, 0x14, + 0x7b, 0x5, 0x14, 0x51, 0x56, 0x68, 0x14, 0x51, 0x45, 00, + 0x15, 0xcd, 0xf8, 0xd9, 0xfc, 0xbd, 0x2d, 0xdb, 0xbe, 0x2b, + 0xa3, 0x35, 0xcd, 0xf8, 0xd9, 0x3c, 0xcd, 0x38, 0xaf, 0x6c, + 0x57, 0xe, 0x37, 0xfd, 0xde, 0x7e, 0x87, 0x9d, 0x98, 0xdf, + 0xea, 0xb5, 0x2d, 0xd8, 0xf0, 0x2b, 0xac, 0x99, 0xd8, 0x9e, + 0xa4, 0xd4, 0x75, 0x3e, 0xa3, 0xf2, 0xde, 0x3a, 0xfa, 0x1a, + 0x82, 0xbf, 0xd, 0x9f, 0xc4, 0xd1, 0xfc, 0xdd, 0x51, 0x5a, + 0x72, 0x41, 0x45, 0x14, 0x54, 0x10, 0x14, 0x13, 0x81, 0x45, + 0x7, 0xa5, 0x26, 0x1d, 0xf, 0x48, 0xf8, 0x67, 0x75, 0xe4, + 0x38, 0x1f, 0xc4, 0x45, 0x7a, 0xea, 0x9c, 0x81, 0x5e, 0xf, + 0xe0, 0x1b, 0xd2, 0xba, 0x96, 0xf, 0xa, 0x31, 0xfd, 0x6b, + 0xdc, 0xed, 0x64, 0x12, 0xc2, 0xac, 0x3b, 0x8a, 0xfd, 0x67, + 0x87, 0x6a, 0xa9, 0xe1, 0x79, 0x57, 0x43, 0xf6, 0xfe, 0x14, + 0xae, 0xaa, 0x60, 0xf9, 0x7b, 0x13, 0x51, 0x45, 0x15, 0xf5, + 0x67, 0xdb, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x52, 0x50, + 0x2, 0xd6, 0x2f, 0x89, 0x35, 0x51, 0xa7, 0x5a, 0x31, 0xdd, + 0xb5, 0xab, 0x52, 0x79, 0x85, 0xba, 0x16, 0x35, 0xe4, 0x7f, + 0x11, 0x3c, 0x4c, 0xd3, 0xdc, 0xf9, 0x51, 0xbe, 0x7, 0xa0, + 0xaf, 0x1b, 0x35, 0xc6, 0xc7, 0x5, 0x87, 0x72, 0xbe, 0xa7, + 0xcf, 0xe7, 0x39, 0x84, 0x30, 0x18, 0x69, 0x49, 0xbd, 0x5e, + 0xc7, 0x1f, 0xe2, 0x3d, 0x49, 0xf5, 0xd, 0x4a, 0x46, 0x2d, + 0x91, 0x9a, 0xcb, 0xa5, 0x66, 0x2e, 0xe5, 0x8f, 0x53, 0x49, + 0x5f, 0x8c, 0xd4, 0xa8, 0xea, 0xcd, 0xce, 0x5d, 0x4f, 0xe7, + 0xfa, 0xb5, 0x65, 0x5a, 0xa4, 0xaa, 0x4b, 0x76, 0x14, 0x51, + 0x45, 0x66, 0x64, 0x14, 0x51, 0x4a, 0x8b, 0xe6, 0x48, 0xaa, + 0x3b, 0xd0, 0x6, 0xef, 0x83, 0x74, 0xef, 0xb7, 0xea, 0xf1, + 0x82, 0x32, 0x1, 0x15, 0xef, 0x3a, 0x5d, 0x92, 0x59, 0xdb, + 0x2a, 0xaa, 0xe3, 0x8a, 0xf3, 0xdf, 0x86, 0x5a, 0x28, 0x49, + 0x3c, 0xe7, 0x5e, 0x7a, 0xe4, 0x8a, 0xf4, 0xec, 0xc, 0xf, + 0x4a, 0xfd, 0x5b, 0x87, 0xb0, 0x7e, 0xc7, 0xf, 0xed, 0x24, + 0xb5, 0x67, 0xed, 0x9c, 0x2b, 0x81, 0xfa, 0xbe, 0x17, 0xda, + 0xc9, 0x6b, 0x21, 0xf4, 0x51, 0x45, 0x7d, 0x69, 0xf7, 0x21, + 0x45, 0x14, 0x50, 0x1, 0x45, 0x14, 0x50, 0x1, 0x48, 0x46, + 0x69, 0x68, 0xa0, 0x4, 0x2, 0x82, 0x32, 0x31, 0x4b, 0x45, + 00, 0x41, 0x2d, 0xa4, 0x52, 0x82, 0x19, 0x1, 0xcd, 0x72, + 0x1e, 0x2d, 0xf0, 0xac, 0x77, 0x16, 0xae, 0xd1, 0xa6, 0x3e, + 0x86, 0xbb, 0x53, 0x51, 0x5c, 0x42, 0xb3, 0xc2, 0xc8, 0x7b, + 0xd7, 0x1e, 0x27, 0xd, 0x4f, 0x11, 0x7, 0x9, 0x23, 0x83, + 0x17, 0x83, 0xa5, 0x8a, 0xa4, 0xe1, 0x34, 0x7c, 0xdd, 0xab, + 0x69, 0xe6, 0xc2, 0x7d, 0x87, 0xd6, 0xa8, 0x57, 0x77, 0xe3, + 0xdd, 0x2d, 0x2d, 0xe6, 0x77, 0x3, 0xa5, 0x70, 0x6a, 0xc5, + 0xb9, 0xaf, 0xc5, 0xb1, 0xb4, 0x3e, 0xad, 0x5e, 0x54, 0xcf, + 0xe7, 0xbc, 0xc7, 0xd, 0xf5, 0x4c, 0x44, 0xa9, 0xb, 0x45, + 0x14, 0x57, 0x9, 0xe6, 0x85, 0x23, 0x74, 0xa5, 0xa4, 0x6e, + 0x94, 0x99, 0x2c, 0xaf, 0x71, 0xc9, 0x3, 0xad, 0x75, 0x3e, + 0xa, 0x52, 0xf7, 0x61, 0x6b, 0x95, 0x90, 0xe6, 0x4a, 0xee, + 0x3c, 0x3, 00, 0x32, 0x6f, 0xaf, 0x6f, 0x26, 0xa6, 0xe7, + 0x8a, 0x89, 0xf4, 0xbc, 0x3d, 0x49, 0xd4, 0xc6, 0xc4, 0xed, + 0xe7, 0x6c, 0x46, 0xa0, 0x76, 0x15, 0xcf, 0x6a, 0x72, 0x75, + 0xad, 0xbb, 0xa7, 0xc2, 0x57, 0x35, 0xa9, 0x49, 0x9c, 0xd7, + 0xed, 0xb, 0x43, 0xfa, 0x5, 0x68, 0x91, 0x81, 0xa8, 0xc9, + 0xc1, 0xe6, 0xb8, 0x7d, 0x6a, 0x6f, 0xbd, 0xcd, 0x75, 0xda, + 0x94, 0x9c, 0x35, 0x70, 0x9a, 0xd4, 0xdc, 0xb7, 0xd6, 0x98, + 0xce, 0x2b, 0xc5, 0x17, 0x66, 0x1b, 0x39, 0x5b, 0x38, 0xe2, + 0xbe, 0x67, 0xf8, 0x8f, 0xa8, 0x96, 0x69, 0x7e, 0x7f, 0x5a, + 0xf7, 0xff, 00, 0x1d, 0xdd, 0x98, 0xac, 0xdf, 0x1d, 0xc5, + 0x7c, 0xbb, 0xf1, 0x16, 0xfc, 0xb3, 0x48, 0x33, 0xeb, 0x5f, + 0x3d, 0x9a, 0x54, 0xb2, 0xb1, 0xf2, 0xd9, 0xd5, 0x5e, 0x58, + 0xf2, 0x9e, 0x53, 0xab, 0x4c, 0x5d, 0xdd, 0x89, 0xea, 0x6b, + 0x92, 0xd4, 0xe5, 0xeb, 0xcd, 0x74, 0x5a, 0x94, 0x9c, 0x1a, + 0xe5, 0x35, 0x19, 0x32, 0x4d, 0x7c, 0xfe, 0x1a, 0x37, 0x67, + 0xcb, 0x60, 0xe3, 0x7d, 0x4c, 0x7b, 0x96, 0xce, 0x6b, 0xbe, + 0xfd, 0x9b, 0xfc, 0x3b, 0xff, 00, 0x9, 0x3f, 0xc6, 0x2d, + 0x16, 0x2f, 0x2c, 0x48, 0xb6, 0x8d, 0xf6, 0xb6, 0x4, 0xe3, + 0x84, 0x23, 0x3c, 0xfe, 0x3d, 0x2b, 0xcf, 0x6e, 0x1b, 0x8a, + 0xfa, 0x4b, 0xf6, 0x14, 0xf0, 0xbf, 0xf6, 0xa7, 0x8c, 0xb5, + 0x5d, 0x48, 0x8f, 0x9e, 0x15, 0x4b, 0x78, 0xfe, 0x5c, 0xe7, + 0x79, 0xf9, 0xb9, 0xfc, 0xab, 0xe9, 0xb0, 0xd1, 0xbc, 0x91, + 0xf6, 0x18, 0x48, 0xde, 0x48, 0xfd, 0x3b, 0xf8, 0x7b, 0xa7, + 0x7f, 0x67, 0x78, 0x5a, 0xca, 0x3d, 0xa1, 0x4c, 0x89, 0xe6, + 0x11, 0xee, 0x79, 0xae, 0xc6, 0xdd, 0x7a, 0x56, 0x6e, 0x9f, + 0x6e, 0x2d, 0xed, 0xe2, 0x89, 0x7e, 0xea, 0x20, 0x2, 0xb5, + 0x20, 0xe3, 0x15, 0xed, 0x9f, 0x44, 0x5d, 0x80, 0x56, 0x85, + 0xba, 0xf4, 0xe2, 0xa9, 0x42, 0x38, 0x15, 0xa1, 0x7, 0x4, + 0x50, 0x5, 0xd8, 0x5, 0x5e, 0x85, 0x78, 0x6, 0xa9, 0xc1, + 0x57, 0xe2, 0x1c, 0xa, 00, 0xb1, 0x10, 0xab, 0x31, 0xf6, + 0xaa, 0xf1, 0x8c, 0x55, 0x98, 0xc7, 0x4a, 00, 0x9d, 0x2a, + 0x55, 0xa8, 0x90, 0x54, 0xa3, 0xa5, 00, 0x48, 0xbd, 0xaa, + 0x45, 0xa6, 0x2d, 0x3c, 0x74, 0xa0, 0x5, 0xa5, 0x1d, 0x69, + 0x29, 0x56, 0x80, 0x1d, 0x45, 0x14, 0x50, 0x5, 0x56, 0xa8, + 0xcf, 0x7a, 0x7b, 0x1a, 0x8d, 0xa8, 0x2, 0x37, 0xe9, 0x55, + 0xa4, 0xa9, 0xe4, 0x35, 0x5a, 0x43, 0x40, 0x15, 0xe4, 0x3c, + 0xd7, 0xce, 0xdf, 0xb6, 0xe5, 0xdc, 0xb6, 0xff, 00, 0x7, + 0x61, 0x48, 0x8e, 0x4, 0xfa, 0xa4, 0x30, 0xbf, 0xba, 0x94, + 0x94, 0x9f, 0xe4, 0x2b, 0xe8, 0x79, 0x5b, 00, 0xd7, 0xc9, + 0x5f, 0xb6, 0xcf, 0x88, 0x9a, 0xe6, 0x6f, 0xc, 0xf8, 0x5a, + 0x19, 0x43, 0x79, 0xf2, 0x9b, 0xb9, 0xa1, 00, 0xe7, 0x2b, + 0xf2, 0xa1, 0xf4, 0xfe, 0x26, 0xaf, 0x17, 0x39, 0xa9, 0xec, + 0xf0, 0x15, 0x5f, 0x75, 0x6f, 0xbc, 0xf9, 0xfc, 0xfe, 0xaf, + 0xb2, 0xcb, 0x2b, 0x3e, 0xad, 0x5b, 0xef, 0xd0, 0xd5, 0xfd, + 0x91, 0x3c, 0x2f, 0xfd, 0x9f, 0xe1, 0x61, 0x78, 0xca, 0x43, + 0x5c, 0x36, 0x72, 0x47, 0x50, 0x32, 0x2b, 0xeb, 0x1d, 0x32, + 0x20, 0xb1, 0x8a, 0xf2, 0x3f, 0x82, 0x5e, 0x1e, 0x5d, 0x1b, + 0xc2, 0x5a, 0x5c, 0x2, 0x3d, 0xa5, 0x61, 0x5c, 0xf1, 0xdf, + 0xad, 0x7b, 0x35, 0x8a, 00, 0xa2, 0xb6, 0xca, 0xe8, 0x7d, + 0x5b, 0x9, 0x4e, 0x9f, 0x91, 0xb6, 0x4d, 0x86, 0x58, 0x4c, + 0xd, 0x2a, 0x5e, 0x45, 0xda, 0x28, 0xa2, 0xbd, 0x43, 0xda, + 0xa, 0x28, 0xa2, 0x80, 0x39, 0xbf, 0x1e, 0x58, 0x7d, 0xbf, + 0xc3, 0xd7, 0x2a, 0x46, 0x42, 0xa1, 0x38, 0xaf, 0xc1, 0x9f, + 0xdb, 0x5b, 0xc3, 0x77, 0x2b, 0xf1, 0x2b, 0x52, 0xbc, 0x93, + 0x7a, 0xc2, 0x87, 0x3, 0x78, 0xc6, 0x7f, 0x4a, 0xfd, 0xfb, + 0xd6, 0x44, 0x72, 0x69, 0x93, 0xc7, 0x23, 0xa4, 0x6a, 0xeb, + 0xb7, 0x32, 0x30, 0x2, 0xbf, 0x2c, 0xff, 00, 0x6e, 0x5f, + 0x83, 0x3a, 0x5d, 0xdd, 0xd5, 0xdd, 0xca, 0x4b, 0x14, 0xa7, + 0x1b, 0x98, 0xa4, 0xca, 0x73, 0xf4, 0xc5, 00, 0x7e, 0x5f, + 0xe9, 0x53, 0x79, 0x17, 0xc9, 0x20, 0x3c, 0x8f, 0x5a, 0xfd, + 0x7b, 0xff, 00, 0x82, 0x6c, 0x78, 0xae, 0xc3, 0x4a, 0xd0, + 0x12, 0x39, 0x24, 0x43, 0x75, 0x28, 00, 0xd, 0xc3, 0x3, + 0x20, 0x74, 0xc9, 0xcd, 0x7e, 0x47, 0xeb, 0x76, 0x11, 0x69, + 0x9a, 0x9c, 0xb1, 0xc6, 0x70, 0x88, 0xe4, 0x2, 0xf, 0xa1, + 0xaf, 0xa8, 0xbf, 0x65, 0xf, 0xda, 0x2, 0xdf, 0xe1, 0xc6, + 0xaf, 0x6e, 0xf7, 0x17, 0x91, 0xc6, 0xa8, 0xea, 0x2, 0xcb, + 0x92, 0xbd, 0xbd, 0xe8, 0x3, 0xf7, 0xae, 0x27, 0xe, 0x81, + 0x87, 0x42, 0x33, 0x4f, 0xaf, 0x9b, 0x3e, 0x17, 0x7e, 0xd5, + 0x96, 0x3e, 0x30, 0xb4, 0x87, 0x75, 0xc5, 0xab, 0x96, 0xe9, + 0xb1, 0x48, 0x3f, 0xce, 0xbd, 0x86, 0xf, 0x89, 0x3a, 0x74, + 0xa8, 0x18, 0xcc, 0x83, 0x34, 0x1, 0xd9, 0x51, 0x5c, 0xaa, + 0xf8, 0xff, 00, 0x4e, 0x6f, 0xf9, 0x6e, 0x9f, 0x9d, 0x4e, + 0x9e, 0x39, 0xd3, 0x1b, 0xfe, 0x5b, 0xad, 00, 0x74, 0x74, + 0x56, 0x75, 0x8e, 0xbb, 0x69, 0x7f, 0x8f, 0x2a, 0x50, 0xc4, + 0xd6, 0x8d, 00, 0x21, 0xae, 0x3, 0xe2, 0x2e, 0xa0, 0x22, + 0xb4, 0x90, 0x3, 0xd8, 0xd7, 0x7b, 0x29, 0xda, 0x84, 0xfb, + 0x57, 0x8e, 0x7c, 0x4b, 0xd4, 0xb, 0x31, 0x8c, 0x1e, 0xa6, + 0xbe, 0x7f, 0x3b, 0xaf, 0xec, 0x70, 0x92, 0x3e, 0x5b, 0x88, + 0xf1, 0x1e, 0xc3, 0x5, 0x2b, 0x75, 0x3c, 0xff, 00, 0x3b, + 0x98, 0xb7, 0xa9, 0xcd, 0x14, 0x8b, 0xc0, 0xa5, 0xaf, 0xc7, + 0x11, 0xf8, 0x12, 0xa, 0x28, 0xa2, 0x81, 0x85, 0x74, 0x3e, + 0x6, 0xb3, 0x37, 0x3a, 0xb8, 0x6c, 0x70, 0x3f, 0xc4, 0x57, + 0x3c, 0x7a, 0x1a, 0xf4, 0x1f, 0x86, 0x5a, 0x7e, 0xe9, 0x3c, + 0xc2, 0x3a, 0xd7, 0xa9, 0x96, 0x52, 0xf6, 0xd8, 0xa8, 0x44, + 0xf6, 0x32, 0x7a, 0x1f, 0x58, 0xc6, 0xd3, 0x8f, 0x9d, 0xcf, + 0x5a, 0xd3, 0xa2, 0xf2, 0xed, 0x94, 0x63, 0x1c, 0x55, 0xaa, + 0x6c, 0x6b, 0xb5, 0x14, 0x53, 0xeb, 0xf6, 0xc8, 0xae, 0x54, + 0x91, 0xfd, 0x15, 0x8, 0xf2, 0xc5, 0x44, 0x28, 0xa2, 0x8a, + 0xb2, 0xc4, 0xaf, 0x3d, 0xf8, 0x9f, 0xc5, 0x99, 0x51, 0xd4, + 0x8a, 0xf4, 0x23, 0x5e, 0x79, 0xf1, 0x24, 0xef, 0x8c, 0xfb, + 0xa, 0xf1, 0x73, 0x8f, 0xf7, 0x39, 0x9f, 0x3d, 0x9f, 0x7f, + 0xb8, 0x4d, 0x1e, 0x3c, 0x57, 0x69, 0x23, 0xd2, 0x92, 0x82, + 0x77, 0x3b, 0x1a, 0x2b, 0xf1, 0x63, 0xf9, 0xec, 0x28, 0xa2, + 0x8a, 00, 0x2b, 0x6b, 0xc2, 0x6f, 0xe5, 0xde, 0x8f, 0x52, + 0x6b, 0x16, 0xb6, 0x3c, 0x2f, 0xf3, 0x6a, 0x91, 0x8e, 0xc0, + 0xf5, 0xae, 0xac, 0x2e, 0x95, 0xe1, 0xea, 0x76, 0xe0, 0x9d, + 0xb1, 0x30, 0xf5, 0x3e, 0x82, 0xd2, 0xc6, 0xdb, 0x28, 0xf3, + 0xe9, 0x56, 0xd6, 0xaa, 0x69, 0xcf, 0xe6, 0x5a, 0x21, 0xf4, + 0x15, 0x6c, 0x57, 0xee, 0x94, 0xed, 0xc8, 0xac, 0x7f, 0x49, + 0x52, 0xb7, 0x24, 0x6d, 0xd9, 0xb, 0x45, 0x14, 0x56, 0xa6, + 0xc1, 0x45, 0x14, 0x50, 0x1, 0x48, 0xdd, 0x29, 0x69, 0xd, + 00, 0x55, 0xd4, 0x24, 0xf2, 0xac, 0xe5, 0x63, 0xd8, 0x57, + 0xcf, 0xde, 0x2d, 0xba, 0xfb, 0x56, 0xb1, 0x27, 0x39, 0xa, + 0x6b, 0xdd, 0x3c, 0x4b, 0x3f, 0x91, 0xa4, 0xdc, 0x36, 0x7a, + 0x29, 0x35, 0xf3, 0xc5, 0xf4, 0xa6, 0x7b, 0xc9, 0x64, 0xf5, + 0x63, 0x5f, 0x9f, 0x71, 0x4d, 0x5b, 0x28, 0x52, 0x47, 0xe5, + 0xbc, 0x67, 0x5e, 0xca, 0x9d, 0x15, 0xd7, 0x52, 0xa, 0x28, + 0xa2, 0xbf, 0x3e, 0x3f, 0x2c, 0xa, 0x28, 0xa2, 0x80, 0x1a, + 0x46, 0x58, 0xf, 0x5a, 0xf6, 0xf, 0x87, 0x76, 0x25, 0x23, + 0x52, 0x47, 0x4a, 0xf2, 0x7b, 0x28, 0x7c, 0xfb, 0xc8, 0xd7, + 0x19, 0xe6, 0xbd, 0xdb, 0xc1, 0x16, 0x9e, 0x4d, 0xae, 0x48, + 0xed, 0x5f, 0x59, 0xc3, 0x94, 0x7d, 0xa6, 0x25, 0xcf, 0xb1, + 0xf6, 0xfc, 0x29, 0x87, 0xf6, 0xb8, 0xa7, 0x37, 0xd0, 0xea, + 0x14, 0x62, 0x9d, 0x48, 0x29, 0x6b, 0xf5, 0x63, 0xf6, 0xe0, + 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, 0xac, 0x4f, + 0x14, 0x45, 0xbf, 0x4d, 0x95, 0xbb, 0xe2, 0xb6, 0xea, 0x86, + 0xb1, 0xf, 0x9f, 0x64, 0xe9, 0x5c, 0xf8, 0x88, 0xf3, 0xd2, + 0x92, 0xf2, 0x39, 0x71, 0x51, 0xe7, 0xa3, 0x28, 0xf9, 0x1f, + 0x39, 0xea, 0x91, 0x79, 0x77, 0x6e, 0xd8, 0xc6, 0x4d, 0x54, + 0xad, 0xaf, 0x16, 0x40, 0x62, 0xd4, 0x8a, 0xe3, 0x81, 0x58, + 0xb5, 0xf8, 0x66, 0x22, 0x1c, 0x95, 0x65, 0x13, 0xf9, 0xb7, + 0x15, 0xf, 0x67, 0x5e, 0x71, 0xf3, 0xa, 0x28, 0xa2, 0xb9, + 0xce, 0x60, 0xa2, 0x8a, 0x28, 0x3, 0x4b, 0x43, 0xba, 0xfb, + 0x2d, 0xd2, 0x74, 0xe4, 0xf7, 0xaf, 0x7a, 0xf0, 0xbd, 0xfa, + 0x5e, 0x69, 0xcb, 0xb4, 0xe4, 0xaf, 0x5a, 0xf9, 0xd1, 0x5b, + 0xcb, 0x70, 0xc3, 0xb5, 0x7a, 0x87, 0xc3, 0xdf, 0x11, 0x88, + 0xa2, 0x30, 0x96, 0x1f, 0x31, 0xaf, 0xb0, 0xe1, 0xec, 0x62, + 0xa1, 0x57, 0xd9, 0x4d, 0xe8, 0xcf, 0xbd, 0xe1, 0x5c, 0xc1, + 0x61, 0xeb, 0xba, 0x33, 0xd9, 0x9e, 0xa8, 0xd, 0x2d, 0x43, + 0x4, 0xeb, 0x34, 0x61, 0x87, 0x39, 0xf4, 0xa9, 0x6b, 0xf5, + 0x24, 0xd3, 0xd5, 0x1f, 0xb3, 0xa7, 0x75, 0x74, 0x2d, 0x14, + 0x51, 0x4c, 0x62, 0x53, 0x5d, 0xc4, 0x60, 0x96, 0x20, 0xa, + 0x49, 0x25, 0x11, 0x2e, 0xe6, 0x38, 0x1e, 0xf5, 0xc5, 0x78, + 0xaf, 0xc6, 0x50, 0xdb, 0x43, 0x2c, 0x71, 0x48, 0x37, 0xe, + 0x2b, 0x8f, 0x13, 0x8a, 0xa7, 0x85, 0x83, 0x9c, 0xd9, 0xc1, + 0x8b, 0xc6, 0x52, 0xc1, 0xd3, 0x75, 0x2a, 0x32, 0x1f, 0x1e, + 0xf8, 0xb5, 0x6c, 0x60, 0xd9, 0x13, 0x6, 0x27, 0x8e, 0xd, + 0x78, 0xfd, 0xf5, 0xdb, 0x5f, 0x5c, 0x99, 0x18, 0xd4, 0xfa, + 0xae, 0xa9, 0x2e, 0xa5, 0x29, 0x2e, 0xdb, 0x86, 0x6a, 0x8f, + 0x4a, 0xfc, 0x87, 0x33, 0xcc, 0x27, 0x8f, 0xaa, 0xdf, 0x43, + 0xf0, 0x8c, 0xe3, 0x34, 0xa9, 0x99, 0x57, 0x72, 0xbf, 0xbb, + 0xd8, 0x28, 0xa2, 0x8a, 0xf1, 0x8f, 00, 0x28, 0xa2, 0x8a, + 00, 0x2b, 0x63, 0xc2, 0x9a, 0x61, 0xd4, 0x35, 0x25, 0x18, + 0x24, 0xf, 0x6a, 0xc9, 0x85, 0x1a, 0x69, 0x95, 0x14, 0x67, + 0x35, 0xea, 0xff, 00, 0xe, 0x7c, 0x3a, 0x21, 0x73, 0x33, + 0xa9, 0xfc, 0x6b, 0xd8, 0xca, 0xf0, 0x8f, 0x17, 0x88, 0x8c, + 0x7a, 0x23, 0xdd, 0xc9, 0xb0, 0x32, 0xc7, 0x62, 0xa3, 0x1b, + 0x68, 0xb7, 0x3b, 0x9d, 0xb, 0x4d, 0x5b, 0xb, 0x45, 00, + 0x60, 0xe2, 0xb5, 0x29, 0x14, 0x60, 0x52, 0xd7, 0xec, 0xf4, + 0xe0, 0xa9, 0xc5, 0x45, 0x74, 0x3f, 0xa0, 0xe9, 0x53, 0x54, + 0xa0, 0xa1, 0x1d, 0x90, 0x51, 0x49, 0x9f, 0x6a, 0xcb, 0xbe, + 0xd7, 0xa0, 0xb1, 0x97, 0x63, 0x38, 0xcd, 0x13, 0xa9, 0x1a, + 0x6a, 0xf2, 0x76, 0xa, 0x95, 0x61, 0x49, 0x73, 0x4d, 0xd9, + 0x1a, 0xb4, 0x55, 0x1b, 0x2d, 0x52, 0x2b, 0xd5, 0xca, 0x30, + 0x3f, 0x4a, 0xbb, 0x55, 0x19, 0x29, 0xab, 0xc5, 0x95, 0x9, + 0xa9, 0xae, 0x68, 0xbd, 0x5, 0xa2, 0x8a, 0x2a, 0x8b, 0xa, + 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0x12, 0x91, 0xcf, + 0xca, 0x68, 0x6a, 0x8a, 0xe6, 0x41, 0x14, 0x2c, 0xc4, 0xe0, + 0xa, 0x96, 0xec, 0xae, 0x4c, 0x9d, 0x93, 0x67, 0x94, 0x7c, + 0x4f, 0x91, 0x50, 0x6c, 0x1d, 0x4d, 0x79, 0xb8, 0x18, 0x15, + 0xd7, 0x7c, 0x44, 0xd4, 0x45, 0xce, 0xa4, 0x10, 0x36, 0x40, + 0xf4, 0xae, 0x46, 0xbf, 0x15, 0xcd, 0xaa, 0xaa, 0x98, 0xb9, + 0xb5, 0xd0, 0xfe, 0x79, 0xcf, 0x2b, 0x2a, 0xd8, 0xf9, 0xc9, + 0x74, 0xa, 0x28, 0xa2, 0xbc, 0x83, 0xc1, 0xa, 0x6b, 0x9e, + 0xd, 0x3a, 0xa2, 0x95, 0xbe, 0x53, 0x52, 0xc9, 0x64, 0x7, + 0xe6, 0x92, 0xbd, 0x2f, 0xc1, 0x36, 0xde, 0x55, 0xa6, 0xea, + 0xf3, 0xab, 0x28, 0xbc, 0xe9, 0xd1, 0x71, 0x9c, 0x9c, 0x57, + 0xad, 0x68, 0x56, 0xff, 00, 0x67, 0xd3, 0x93, 0x8c, 0x12, + 0x5, 0x7d, 0xa7, 0xd, 0x50, 0x73, 0xac, 0xe6, 0xfa, 0x1f, + 0xa1, 0xf0, 0x8e, 0x1b, 0x9f, 0x10, 0xea, 0x76, 0x44, 0xb7, + 0xb2, 0x61, 0xd, 0x72, 0xfa, 0x8b, 0xf5, 0xae, 0x87, 0x51, + 0x93, 00, 0xd7, 0x2d, 0xa8, 0xc9, 0xd6, 0xbf, 0x51, 0x3f, + 0x65, 0x39, 0xed, 0x4e, 0x4c, 0x2b, 0x57, 0x3, 0xac, 0xcb, + 0xf3, 0x35, 0x76, 0x9a, 0xac, 0x98, 0x6, 0xbc, 0xff, 00, + 0x59, 0x9b, 0x97, 0x3f, 0x5a, 00, 0xf2, 0xbf, 0x89, 0x17, + 0xbb, 0x63, 0x75, 0x4, 0x70, 0xd, 0x7c, 0xb9, 0xe3, 0xdb, + 0xbf, 0x32, 0xe1, 0x96, 0xbe, 0x81, 0xf8, 0x99, 0xa8, 0xd, + 0xf3, 0x60, 0x8e, 0x33, 0xfd, 0x6b, 0xe6, 0x5f, 0x16, 0xdd, + 0x79, 0xd7, 0x6f, 0xce, 0x79, 0xaf, 0x8e, 0xcd, 0x2a, 0x5e, + 0x56, 0x3e, 0x3, 0x3a, 0xab, 0xcd, 0x3b, 0x1c, 0x6e, 0xa6, + 0xfd, 0x45, 0x72, 0xb7, 0xef, 0x97, 0x35, 0xd0, 0xea, 0x6f, + 0xcb, 0x73, 0x5c, 0xc5, 0xe3, 0xe5, 0x8d, 0x73, 0xe1, 0x63, + 0x63, 0x9b, 0x7, 0x1b, 0x23, 0x3a, 0xe1, 0xb8, 0x22, 0xbe, + 0xf7, 0xff, 00, 0x82, 0x7c, 0xf8, 0x33, 0xc8, 0xf0, 0xdc, + 0x57, 0x92, 0x67, 0x7d, 0xde, 0xa0, 0xd7, 0x4a, 0x3b, 0x6c, + 0x55, 0x8f, 0x3, 0xa7, 0xa8, 0x35, 0xf0, 0x2d, 0xc1, 0xc8, + 0x6f, 0xf0, 0xaf, 0xd6, 0x2f, 0xd8, 0xe3, 0xc2, 0xe9, 0xa1, + 0xf8, 0x1b, 0x48, 0x45, 0x89, 0x93, 0xca, 0xb1, 0x46, 0xdc, + 0x47, 0x52, 0xfc, 0x9f, 0x7e, 0x84, 0x57, 0xd3, 0x61, 0x23, + 0xad, 0xcf, 0xb0, 0xc0, 0xc7, 0x5b, 0x9f, 0x4b, 0x41, 0xd6, + 0xb4, 0x61, 0xe0, 0xa, 0xa1, 0x8, 0xe2, 0xb4, 0x20, 0x1d, + 0x2b, 0xd3, 0x3d, 0x82, 0xf4, 0x39, 0xe2, 0xb4, 0x21, 0x1d, + 0x2a, 0x8c, 0x23, 0x9a, 0xbd, 0xf, 0x41, 0x40, 0x17, 0xed, + 0xc6, 00, 0xab, 0xd1, 0x72, 0x2a, 0x9c, 0x1c, 0xe3, 0xda, + 0xae, 0xc5, 0xd2, 0x80, 0x2c, 0xc6, 0x2a, 0xcc, 0x62, 0xab, + 0xc7, 0x56, 0x63, 0xa0, 0x9, 0x93, 0xa5, 0x4a, 0x3a, 0xd4, + 0x4b, 0x52, 0x29, 0xa0, 0x9, 0x7, 0x4a, 0x90, 0x54, 0x6a, + 0x6a, 0x40, 0x73, 0x40, 0x5, 0x39, 0x69, 0xb4, 0xe1, 0xd2, + 0x80, 0x16, 0x8a, 0x28, 0xa0, 0xa, 0x6d, 0x51, 0xb1, 0xa7, + 0xb5, 0x46, 0xc7, 0xad, 00, 0x43, 0x21, 0xcd, 0x55, 0x90, + 0xd5, 0x89, 0x3a, 0x55, 0x69, 0x28, 0x2, 0xb4, 0xc7, 0xa8, + 0xaf, 0x86, 0xbe, 0x26, 0x5f, 0xb7, 0xc4, 0x8f, 0xda, 0x99, + 0xac, 0xe, 0xc, 0x3a, 0x57, 0xfa, 0x16, 0xd0, 0x31, 0xca, + 0x33, 0x12, 0x7f, 0xf1, 0xe1, 0xf9, 0x57, 0xda, 0x9e, 0x23, + 0xd5, 0x23, 0xd1, 0x34, 0x3d, 0x4b, 0x51, 0x98, 0x81, 0x15, + 0xa5, 0xbc, 0x97, 0xf, 0x93, 0x81, 0xb5, 0x10, 0xb1, 0xe7, + 0xb7, 0x2, 0xbe, 0x18, 0xfd, 0x99, 0xe1, 0x93, 0xc5, 0x1f, + 0x1a, 0xf5, 0x5d, 0x5a, 0x45, 0x2c, 0x24, 0x13, 0xcc, 0x4f, + 0x1d, 0x4b, 0xae, 0x3f, 0x4a, 0xf9, 0x5c, 0xee, 0x5e, 0xd2, + 0x74, 0x30, 0xbf, 0xcd, 0x25, 0xf7, 0x23, 0xe2, 0xb8, 0x8a, + 0x7e, 0xd6, 0x78, 0x6c, 0x1a, 0xfb, 0x73, 0x57, 0xf4, 0x47, + 0xdc, 0xfe, 0x10, 0xb0, 0x16, 0xb6, 0x70, 0xa0, 0x18, 0xa, + 0xa0, 0xa, 0xed, 0x6d, 0x97, 0xb, 0x9a, 0xc1, 0xd1, 0x20, + 0xf2, 0xe2, 0x5a, 0xe8, 0xa3, 0x1b, 0x50, 0x57, 0xd4, 0xc5, + 0x72, 0xab, 0x1f, 0x67, 0x15, 0xcb, 0x14, 0x90, 0xfa, 0x28, + 0xa2, 0x99, 0x41, 0x4d, 0x77, 0x8, 0xa5, 0x8f, 0x41, 0x4e, + 0xaa, 0x1a, 0xd5, 0xc8, 0xb6, 0xd3, 0xe5, 0x62, 0x40, 0xe3, + 0xbd, 00, 0x7c, 0x79, 0xfb, 0x71, 0xfe, 0xd1, 0xd7, 0xbf, + 0xb, 0xbc, 0x32, 0xc9, 0xa7, 0xbe, 0xdb, 0x89, 0xe, 0x7, + 00, 0xe3, 0x91, 0xea, 0x3d, 0xeb, 0xf2, 0xff, 00, 0xc7, + 0xff, 00, 0xb4, 0x7e, 0xb9, 0xe3, 0x3b, 0x19, 0x7e, 0xdd, + 0x3e, 0xe7, 0x71, 0x83, 0x85, 0x51, 0xfc, 0x85, 0x7a, 0xdf, + 0xfc, 0x14, 0xd3, 0xe2, 0x7, 0xf6, 0xaf, 0x8b, 0x62, 0xd2, + 0xe0, 0xb9, 0xc, 0x91, 0xb1, 0xdc, 0x88, 0xd9, 0xc7, 0xb, + 0xd6, 0xbe, 0x11, 0x33, 0xc8, 0x46, 0xb, 0x93, 0xf8, 0xd0, + 0x5, 0xad, 0x56, 0xec, 0xdd, 0x5c, 0x33, 0x12, 0x4e, 0x49, + 0x3c, 0xd2, 0xe9, 0x7a, 0x9b, 0xe9, 0xd3, 0xa4, 0x8b, 0xce, + 0xd3, 0x9a, 0xa2, 0x4e, 0x68, 0xa0, 0xf, 0x78, 0xf0, 0x47, + 0xed, 0x4f, 0xab, 0xf8, 0x31, 0x63, 0x58, 0x22, 0x24, 0x2f, + 0x71, 0xb7, 0xfa, 0x8a, 0xf4, 0xfb, 0x3f, 0xf8, 0x28, 0x66, + 0xbf, 00, 0x50, 0x62, 0x90, 0x1, 0xfe, 0xcc, 0x67, 0xfa, + 0x57, 0xc7, 0x14, 0x50, 0x7, 0xdb, 0xf6, 0xbf, 0xf0, 0x51, + 0x7d, 0x65, 0x71, 0xba, 0x37, 0xce, 0x39, 0xca, 0x47, 0x5b, + 0xba, 0x6f, 0xfc, 0x14, 0x6b, 0x51, 0x92, 0x78, 0xd0, 0xc6, + 0x72, 0xce, 0x14, 0x60, 0x47, 0xdf, 0xf0, 0xaf, 0x80, 0xeb, + 0x7b, 0xc1, 0x5a, 0x6b, 0x6a, 0x7a, 0xfd, 0xac, 0x61, 0x4b, + 00, 0xeb, 0x9c, 0xc, 0xf7, 0xa0, 0xf, 0xdb, 0xaf, 0xd9, + 0x33, 0xf6, 0x84, 0xbc, 0xf8, 0xa9, 0xa8, 0xc1, 0x13, 0x2, + 0xab, 0x81, 0xd5, 0x57, 0x24, 0xe0, 0x74, 0xc5, 0x7d, 0xa1, + 0x5f, 0xf, 0xff, 00, 0xc1, 0x3b, 0xbc, 0x4, 0xda, 0x66, + 0x85, 0x26, 0xa4, 0xf1, 0x6c, 0xc2, 0x85, 0xcb, 0x2e, 0x9, + 0xc8, 0x1c, 0x75, 0xaf, 0xb7, 0xf3, 0x40, 0x15, 0x75, 0x39, + 0xbc, 0x9b, 0x66, 0x3e, 0xd5, 0xe0, 0x9e, 0x37, 0xbd, 0x37, + 0x3a, 0x99, 0x4e, 0xc0, 0xd7, 0xb4, 0xf8, 0xae, 0xe8, 0x5b, + 0xd8, 0xe7, 0x38, 0xeb, 0x5f, 0x3f, 0xea, 0x93, 0x7d, 0xa7, + 0x50, 0x95, 0xfb, 0x67, 0x15, 0xf9, 0xff, 00, 0x13, 0xd7, + 0xd2, 0x34, 0x91, 0xf9, 0x77, 0x19, 0x62, 0x6d, 0x18, 0xd1, + 0x4f, 0x72, 0xb7, 0x4a, 0x28, 0xa2, 0xbf, 0x3c, 0x3f, 0x2a, + 0x5a, 0x5, 0x14, 0x51, 0x4c, 0x60, 0x6, 0xe6, 0x51, 0xea, + 0x6b, 0xd9, 0xfe, 0x1d, 0x69, 0xe2, 0x1b, 0x38, 0xcf, 0x4c, + 0x81, 0x5e, 0x43, 0xa6, 0x40, 0x6e, 0x2f, 0xe1, 0x40, 0x33, + 0xf3, 0xa, 0xf7, 0xef, 0xb, 0x5a, 0x7d, 0x9a, 0xc5, 0x32, + 0x3b, 0x57, 0xd8, 0xf0, 0xd5, 0xe, 0x7a, 0xce, 0xa3, 0x5b, + 0x1f, 0x7d, 0xc2, 0x18, 0x6f, 0x69, 0x89, 0x95, 0x56, 0xb6, + 0x37, 0xa9, 0x68, 0xa2, 0xbf, 0x51, 0x3f, 0x67, 0xa, 0x28, + 0xa2, 0x80, 0x13, 0x38, 0xaf, 0x3d, 0xf8, 0x99, 0x1f, 0x97, + 0x66, 0xc4, 0x75, 0x22, 0xbd, 0xa, 0xbc, 0xff, 00, 0xe2, + 0x4b, 0x6f, 0x8b, 0x1d, 0x80, 0xaf, 0x1b, 0x37, 0xff, 00, + 0x73, 0x99, 0xf3, 0xf9, 0xed, 0xbe, 0xa3, 0x33, 0xc6, 0xb1, + 0xb7, 0x8a, 0x28, 0x63, 0xba, 0x46, 0x34, 0x57, 0xe2, 0xa7, + 0xf3, 0xd0, 0x51, 0x45, 0x14, 00, 0x56, 0xb7, 0x86, 0x5b, + 0x65, 0xee, 0xec, 0xf7, 0xac, 0x9a, 0xd1, 0xd0, 0x1b, 0xfe, + 0x26, 0x8, 0x3d, 0xeb, 0xa3, 0xe, 0xed, 0x56, 0x3e, 0xa7, + 0x4e, 0x15, 0xdb, 0x11, 0xf, 0x53, 0xe8, 0x4d, 0x10, 0x11, + 0x61, 0x1e, 0x7a, 0x9a, 0xd0, 0x15, 0x9d, 0xa2, 0x4a, 0x24, + 0xb2, 0x40, 0x3b, 0xa, 0xd1, 0x15, 0xfb, 0xa5, 0x1f, 0xe1, + 0xc7, 0xd0, 0xfe, 0x94, 0xc3, 0xdb, 0xd9, 0x46, 0xdd, 0x85, + 0xa2, 0x8a, 0x2b, 0x73, 0xa0, 0x28, 0xa2, 0x8a, 00, 0x29, + 0xd, 0x2d, 0x23, 0x1c, 0x50, 0x7, 0x23, 0xf1, 0x6, 0xf3, + 0xc8, 0xd1, 0xae, 0x31, 0xfd, 0xc3, 0x5e, 0x10, 0xe, 0x72, + 0x7d, 0x6b, 0xd6, 0x3e, 0x29, 0x5f, 0x3, 0x66, 0xd1, 0x67, + 0xaf, 0x1d, 0x6b, 0xc9, 0xc7, 0x4a, 0xfc, 0x9b, 0x88, 0xaa, + 0xfb, 0x4c, 0x5d, 0x97, 0x44, 0x7e, 0x1d, 0xc5, 0x95, 0xfd, + 0xae, 0x3b, 0x95, 0x6c, 0x90, 0x51, 0x45, 0x15, 0xf2, 0xa7, + 0xc5, 0x85, 0x14, 0x50, 0x4e, 0x5, 00, 0x6a, 0xf8, 0x5a, + 0xdf, 0xed, 0x1a, 0xa0, 0x1d, 0x85, 0x7b, 0xf6, 0x83, 00, + 0xb7, 0xb3, 0x5f, 0x7a, 0xf1, 0x5f, 0x87, 0x96, 0xa6, 0x7d, + 0x45, 0x9f, 0x15, 0xee, 0xd6, 0xd1, 0xec, 0x85, 0x16, 0xbf, + 0x49, 0xe1, 0x8a, 0x36, 0xa4, 0xea, 0x33, 0xf5, 0xce, 0xe, + 0xa1, 0x6a, 0xe, 0xab, 0x5b, 0x93, 0xa, 0x5a, 0x28, 0xaf, + 0xba, 0x3f, 0x49, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, + 0x80, 0x10, 0x9a, 0x8e, 0x65, 0xcc, 0x6e, 0x2a, 0x5a, 0x42, + 0x33, 0x49, 0xab, 0x89, 0xab, 0xab, 0x1e, 0x21, 0xf1, 0x3, + 0x4d, 0xfb, 0x3c, 0xed, 0x21, 0xea, 0x4f, 0xf8, 0x57, 0x12, + 0x3a, 0x57, 0xb2, 0xfc, 0x41, 0xd2, 0xc, 0xf1, 0x3c, 0x9b, + 0x49, 0xc7, 0xa0, 0xaf, 0x1c, 0x95, 0x1a, 0x39, 0x59, 0x58, + 0x15, 0xe7, 0xbd, 0x7e, 0x39, 0x9d, 0x61, 0x9d, 0xc, 0x53, + 0x76, 0xd1, 0x9f, 0x81, 0x71, 0x16, 0x11, 0xe1, 0xb1, 0x8d, + 0xa5, 0xa3, 0x1b, 0x45, 0x14, 0x57, 0x80, 0x7c, 0xc0, 0x51, + 0x45, 0x14, 00, 0x11, 0x91, 0x57, 0x74, 0xcd, 0x56, 0x4d, + 0x3a, 0x40, 0x53, 0x39, 0xaa, 0x54, 0x1c, 0xf6, 0xaa, 0x8c, + 0xa5, 0x7, 0xcd, 0x1d, 0xca, 0x84, 0xe5, 0x4e, 0x4a, 0x71, + 0x76, 0x67, 0xa6, 0x68, 0x7e, 0x3b, 0x98, 0x5, 0x56, 0xe9, + 0xf8, 0x57, 0x6b, 0x61, 0xe2, 0x84, 0x99, 0x6, 0xe2, 0x2b, + 0xe7, 0xf4, 0x9e, 0x58, 0xcf, 0xca, 0xd8, 0xab, 0x90, 0xeb, + 0x17, 0x51, 0x74, 0x90, 0xd7, 0xd5, 0x61, 0x33, 0xfa, 0xb4, + 0x15, 0xa7, 0xa9, 0xf6, 0xb8, 0x1e, 0x27, 0xad, 0x87, 0x4a, + 0x35, 0x2e, 0xcf, 0xa0, 0x8f, 0x88, 0x22, 0x3, 0x39, 0x15, + 0x95, 0xa8, 0xf8, 0xd1, 0x2d, 0x41, 0xc7, 0x35, 0xe2, 0xe7, + 0xc4, 0x37, 0x78, 0xc6, 0xf3, 0xf9, 0xd5, 0x79, 0x75, 0x7b, + 0x89, 0x78, 0x66, 0x26, 0xbb, 0xaa, 0xf1, 0x34, 0xa5, 0x1b, + 0x41, 0x58, 0xf4, 0xab, 0x71, 0x84, 0xa5, 0x1b, 0x53, 0x56, + 0x67, 0xa1, 0x6b, 0x3f, 0x13, 0xb, 0xa3, 0x22, 0x8a, 0xf3, + 0xed, 0x43, 0x51, 0x92, 0xfe, 0x79, 0x1c, 0xb1, 0xf9, 0x89, + 0x35, 0x55, 0xd8, 0xbf, 0x5a, 0x4a, 0xf9, 0x7c, 0x5e, 0x3e, + 0xbe, 0x35, 0xfe, 0xf1, 0xe8, 0x7c, 0x66, 0x37, 0x34, 0xc4, + 0xe6, 0xf, 0xf7, 0xd2, 0xd0, 0x3a, 0x8a, 0x28, 0xa2, 0xbc, + 0xe3, 0xc8, 0xa, 0x28, 0xa2, 0x90, 0xc2, 0x8e, 0xe2, 0x8a, + 0xd1, 0xd1, 0x74, 0x79, 0x75, 0x2b, 0xc8, 0x80, 0x46, 0x2b, + 0x9e, 0xc2, 0xb4, 0x85, 0x39, 0x54, 0x92, 0x8c, 0x16, 0xac, + 0xd2, 0x9d, 0x39, 0xd6, 0x9a, 0x84, 0x15, 0xdb, 0x35, 0xfc, + 0x19, 0xe1, 0xc9, 0x2f, 0xf5, 0x4, 0x66, 0xfb, 0xb9, 0xe9, + 0x5e, 0xe1, 0xa6, 0x69, 0xe9, 0x63, 00, 0x55, 0x18, 0x26, + 0xb2, 0xfc, 0x2f, 0xa0, 0x8d, 0x36, 0xd9, 0x9, 0x18, 0x6c, + 0x57, 0x45, 0x5f, 0xae, 0xe4, 0xf9, 0x74, 0x70, 0x54, 0x53, + 0x6b, 0xde, 0x67, 0xee, 0xf9, 0xe, 0x53, 0x1c, 0xba, 0x82, + 0x72, 0x5e, 0xf3, 0x12, 0x96, 0x8a, 0x2b, 0xe8, 0x8f, 0xaa, + 0x23, 0x99, 0xc2, 0x46, 0xcd, 0xe8, 0x2b, 0xc5, 0xfc, 0x69, + 0xaf, 0xb4, 0x5a, 0x84, 0x84, 0x13, 0xc1, 0xc7, 0x15, 0xeb, + 0x5a, 0xed, 0xc8, 0xb5, 0xd3, 0x65, 0x62, 0x71, 0xc6, 0x2b, + 0xe7, 0xdf, 0x10, 0xdc, 0x7d, 0xa6, 0xed, 0xcf, 0xa9, 0xaf, + 0x89, 0xe2, 0x4c, 0x4b, 0xa5, 0x4e, 0x30, 0x8b, 0xd4, 0xfc, + 0xef, 0x8b, 0xb1, 0x92, 0xa3, 0x4a, 0x34, 0xa0, 0xf5, 0x3a, + 0xaf, 0xd, 0xf8, 0xe9, 0xad, 0xf0, 0xa7, 0x35, 0xe8, 0x3a, + 0x5f, 0x8b, 0x96, 0xf4, 0xa8, 0x3c, 0x66, 0xbc, 0xa, 0x39, + 0x1a, 0x1e, 0x54, 0x56, 0x95, 0x97, 0x88, 0x2e, 0x2d, 0x9c, + 0x63, 0x38, 0xfa, 0xd7, 0xcd, 0xe0, 0x33, 0xca, 0xb8, 0x7b, + 0x42, 0xa3, 0xd0, 0xf9, 0xc, 0xb3, 0x89, 0x2b, 0x61, 0x52, + 0x85, 0x57, 0x74, 0x7d, 0x1f, 0x14, 0xeb, 0x2a, 0x82, 0xd, + 0x49, 0x9a, 0xf1, 0x3b, 0xf, 0x1d, 0xce, 0x98, 0x5, 0x88, + 0xfc, 0x6b, 0xa3, 0xd3, 0xbc, 0x71, 0xe6, 0x63, 0x7c, 0x98, + 0xfc, 0x7f, 0xfa, 0xd5, 0xf6, 0xd4, 0x33, 0xcc, 0x35, 0x5d, + 0xf, 0xd1, 0xb0, 0xdc, 0x49, 0x84, 0xaf, 0x65, 0x7b, 0x1e, + 0x95, 0x45, 0x73, 0x36, 0x9e, 0x29, 0xb7, 0x92, 0x30, 0x4c, + 0xc9, 0x9f, 0xf7, 0xaa, 0xf2, 0x6b, 0xf6, 0xcc, 0x38, 0x99, + 0xf, 0xfc, 0xa, 0xbd, 0x98, 0xe2, 0xa9, 0x4d, 0x69, 0x23, + 0xdf, 0x86, 0x36, 0x84, 0xd5, 0xd4, 0x91, 0xb1, 0x45, 0x64, + 0x1d, 0x7a, 0xd8, 0x7f, 0xcb, 0x64, 0xff, 00, 0xbe, 0x85, + 0x52, 0xbb, 0xf1, 0x75, 0xbd, 0xbe, 0x70, 0xea, 0x7f, 0x1a, + 0x25, 0x8a, 0xa3, 0x5, 0x79, 0x48, 0x27, 0x8d, 0xc3, 0xd3, + 0x57, 0x94, 0x91, 0xd1, 0x31, 00, 0x64, 0xf4, 0xae, 0x5b, + 0xc6, 0x5a, 0xfc, 0x76, 0x3a, 0x74, 0x8a, 0xa7, 0xe6, 0x35, + 0x8d, 0xa9, 0xfc, 0x46, 0x8d, 0x23, 0x65, 0x52, 0x7, 0x1e, + 0xbf, 0xfd, 0x6a, 0xf3, 0x7f, 0x10, 0x6b, 0xcf, 0xab, 0x31, + 0xc3, 0x1c, 0x66, 0xbe, 0x6b, 0x33, 0xce, 0xe9, 0x53, 0xa4, + 0xe1, 0x45, 0xdd, 0xb3, 0xe4, 0x33, 0x8e, 0x22, 0xa1, 0x4a, + 0x8c, 0xa1, 0x41, 0xde, 0x4c, 0xce, 0xd5, 0x6e, 0xda, 0xf2, + 0xf1, 0xa4, 0x27, 0x35, 0x5a, 0x8a, 0x2b, 0xf2, 0xc9, 0x49, + 0xce, 0x4e, 0x4f, 0xa9, 0xf8, 0xbc, 0xe4, 0xe7, 0x27, 0x27, + 0xbb, 0xa, 0x28, 0xa2, 0xa4, 0x80, 0x35, 0x5e, 0xe0, 0xe1, + 0x45, 0x4e, 0xdd, 0x2a, 0x6, 0x43, 0x3c, 0xa8, 0x8a, 0x9, + 0xc9, 0xed, 0x45, 0xae, 0xec, 0x81, 0x27, 0x26, 0x92, 0x35, + 0x7c, 0x39, 0x65, 0xe7, 0x5c, 0xc4, 0x7d, 0xeb, 0xd5, 0x51, + 0x4, 0x36, 0xb1, 0xaf, 0xfb, 0x22, 0xb9, 0x8f, 0xc, 0x68, + 0x86, 0x2f, 0x2d, 0xd9, 0x8, 0xfa, 0x8a, 0xea, 0x6e, 0xdb, + 0x6a, 0xfd, 0x2b, 0xf5, 0xbc, 0x83, 0xa, 0xe8, 0x51, 0xe6, + 0x6b, 0x73, 0xf7, 0x3e, 0x18, 0xc1, 0x3c, 0x36, 0x1f, 0x9e, + 0x4b, 0x56, 0x62, 0xea, 0x52, 0x75, 0xae, 0x57, 0x50, 0x7e, + 0xb5, 0xbf, 0xa9, 0x49, 0x92, 0xd5, 0xcc, 0x6a, 0x32, 0x75, + 0xaf, 0xaa, 0x3e, 0xd4, 0xe6, 0xb5, 0x89, 0x70, 0xad, 0x5e, + 0x79, 0xaf, 0x4f, 0xb2, 0x39, 0xf, 0xb1, 0xae, 0xdf, 0x5a, + 0x9b, 0x86, 0xc1, 0xaf, 0x33, 0xf1, 0x6d, 0xd0, 0x8a, 0xce, + 0x62, 0x4e, 0x38, 0xa9, 0x93, 0xb2, 0x6c, 0x99, 0xbe, 0x58, + 0xb6, 0x78, 0x47, 0xc4, 0xad, 0x43, 0x26, 0x73, 0xdf, 0x27, + 0xfa, 0xd7, 0xce, 0xda, 0xf4, 0xe5, 0xee, 0x24, 0x3e, 0xf5, + 0xec, 0xbf, 0x12, 0x2f, 0xfe, 0x69, 0x7e, 0x6e, 0xe7, 0xbf, + 0xb9, 0xaf, 0xc, 0xd5, 0x25, 0xc9, 0x73, 0xef, 0x5f, 0x5, + 0x8c, 0x97, 0x3d, 0x53, 0xf3, 0x2c, 0x7c, 0xfd, 0xa5, 0x6b, + 0x1c, 0xe6, 0xa7, 0x27, 0x7, 0x9e, 0xf5, 0xcd, 0xdc, 0xb7, + 0x26, 0xb6, 0xb5, 0x39, 0x39, 0x35, 0x83, 0x70, 0x7a, 0xd7, + 0x76, 0x1d, 0x68, 0x8f, 0x4b, 0xb, 0x1b, 0x45, 0x1a, 0x1e, + 0xa, 0xd2, 0xce, 0xbb, 0xe3, 0x5d, 0xa, 0xc0, 0x2e, 0xe1, + 0x71, 0x7d, 0xc, 0x6c, 0x3f, 0xd9, 0x32, 0xc, 0xfe, 0x99, + 0xaf, 0xd9, 0x4f, 0x82, 0x3a, 0x3a, 0xe9, 0x5e, 0x14, 0x50, + 0x31, 0x80, 0xc2, 0x35, 0x3f, 0xec, 0xaa, 0x28, 0x15, 0xf9, + 0x39, 0xfb, 0x35, 0xdb, 0x47, 0x79, 0xf1, 0xaf, 0xc3, 0xd1, + 0xc8, 0x3, 00, 0xee, 0xc0, 0x11, 0x9e, 0x42, 0x12, 0x3f, + 0x5a, 0xfd, 0x8a, 0xf0, 0x45, 0x81, 0xb0, 0xf0, 0xd5, 0x84, + 0x4c, 0xe, 0xed, 0x81, 0x8e, 0x47, 0xaf, 0x3f, 0xd6, 0xbe, + 0x97, 0xc, 0xbd, 0xdb, 0x9f, 0x5d, 0x83, 0x56, 0x8d, 0xce, + 0xa2, 0x11, 0x5a, 0x36, 0xe3, 0xa5, 0x50, 0xb7, 0x18, 0xab, + 0xf0, 0xe, 0x5, 0x76, 0x1d, 0xe5, 0xf8, 0x57, 0xa5, 0x5e, + 0x84, 0x74, 0xaa, 0x56, 0xea, 0x2b, 0x42, 0x11, 0xc8, 0x34, + 0x1, 0x76, 0xdc, 0x75, 0xab, 0xb1, 0x8e, 0x95, 0x4e, 0xe, + 0xb5, 0x7a, 0x31, 0x40, 0x13, 0xc6, 0x2a, 0xca, 0x54, 0x9, + 0x56, 0x13, 0xb5, 00, 0x48, 0xbd, 0x69, 0xeb, 0xd2, 0x98, + 0xb5, 0x20, 0x14, 00, 0xf5, 0xed, 0x52, 0x2d, 0x31, 0x69, + 0xe3, 0xa5, 00, 0x2d, 0x28, 0xeb, 0x49, 0x4a, 0xb4, 00, + 0xea, 0x28, 0xa2, 0x80, 0x28, 0xb7, 0x7a, 0x89, 0xcd, 0x48, + 0xd5, 0x14, 0x87, 0x14, 0x1, 0x4, 0x86, 0xab, 0x48, 0x6a, + 0x79, 0xd, 0x56, 0x94, 0xf1, 0x40, 0x1e, 0x17, 0xfb, 0x5f, + 0x78, 0x95, 0x74, 0x1f, 0x83, 0x7a, 0x9c, 0x23, 0x6, 0x6d, + 0x41, 0x85, 0xa2, 0xa9, 0xf4, 0x6e, 0x18, 0xfe, 00, 0x9a, + 0xf3, 0x4f, 0xd8, 0xb3, 0xc3, 0x86, 0x1b, 0x7b, 0xbd, 0x41, + 0xb2, 0x37, 0x8d, 0x83, 0x8e, 0xdc, 0x1f, 0xf0, 0xaa, 0x3f, + 0xb7, 0x47, 0x8a, 0x85, 0xe6, 0xb7, 0xe1, 0xbf, 0xb, 0x45, + 0x20, 0x63, 0x1e, 0x2f, 0xa4, 0x54, 0xed, 0x92, 0xc9, 0x83, + 0xcf, 0xa0, 0x7, 0x4, 0x57, 0xb2, 0xfe, 0xcd, 0x3e, 0x18, + 0x3a, 0x17, 0x83, 0x2c, 0x51, 0x94, 0x2b, 0x48, 0x81, 0xcf, + 0xe2, 0x7, 0xb5, 0x7c, 0x63, 0xff, 00, 0x6b, 0xce, 0xfc, + 0xa9, 0xaf, 0xc4, 0xfc, 0xfd, 0xff, 00, 0xb7, 0x71, 0x12, + 0xb6, 0xd4, 0xa3, 0xf8, 0xb3, 0xde, 0x34, 0xe8, 0xf0, 0x8a, + 0x2b, 0x54, 0x71, 0x54, 0xec, 0x93, 00, 0x54, 0x97, 0xf7, + 0xd1, 0x69, 0xf6, 0xcf, 0x3c, 0xcc, 0x11, 0x14, 0x75, 0x35, + 0xf6, 0x67, 0xe8, 0x5, 0x9a, 0x2b, 0xe7, 0x3f, 0x88, 0x1f, + 0xb5, 0xbe, 0x8f, 0xe1, 0x3d, 0x51, 0xac, 0xa3, 0x96, 0x22, + 0xe3, 0x83, 0x9c, 0x13, 0xff, 00, 0xa1, 0x56, 0x57, 0x87, + 0xff, 00, 0x6b, 0xeb, 0x3d, 0x72, 0xf6, 0x38, 0x11, 0xe3, + 0xcb, 0x7a, 0x2f, 0xff, 00, 0x65, 0x40, 0x1f, 0x50, 0xd7, + 0xb, 0xf1, 0x63, 0x56, 0xfe, 0xcc, 0xf0, 0xdd, 0xc4, 0x80, + 0x67, 0x6a, 0x13, 0x8c, 0xf5, 0xad, 0xdf, 0x8, 0x78, 0x83, + 0xfe, 0x12, 0x3d, 0x29, 0x2e, 0xf1, 0x80, 0xc0, 0x63, 0x1d, + 0xeb, 0x37, 0xe2, 0x3f, 0x83, 0x9f, 0xc6, 0x1a, 0xd, 0xc5, + 0x94, 0x6d, 0xb5, 0xa5, 0x5d, 0xbd, 0x71, 0x40, 0x1f, 0xcf, + 0xc7, 0xed, 0x2a, 0x6f, 0xfc, 0x63, 0xf1, 0x43, 0x53, 0xba, + 0xc6, 0x55, 0x5f, 0x3, 0x6a, 0x92, 0x31, 0x81, 0xfe, 0x15, + 0xe4, 0xaf, 0xe1, 0x6b, 0xd5, 0xfe, 0x6, 0x3f, 0xf0, 0x3, + 0x5f, 0xb0, 0x3a, 0xff, 00, 0xfc, 0x13, 0x7e, 0xe3, 0x53, + 0xbd, 0xb8, 0xb9, 0x3b, 0x59, 0xe4, 0x62, 0xc4, 0x99, 0x87, + 0xff, 00, 0x1b, 0xae, 0x6e, 0xef, 0xfe, 0x9, 0xa1, 0xa8, + 0x63, 0xe5, 0x88, 0x9f, 0xf7, 0x66, 0xff, 00, 0xed, 0x74, + 0x1, 0xf9, 0x3c, 0x7c, 0x39, 0x7a, 0x3f, 0xe5, 0x93, 0x7f, + 0xdf, 0x27, 0xfc, 0x2a, 0x36, 0xd0, 0xaf, 0x17, 0xfe, 0x58, + 0xb1, 0xfa, 0x29, 0xff, 00, 0xa, 0xfd, 0x4b, 0xbb, 0xff, + 00, 0x82, 0x6b, 0xeb, 0x28, 0x4e, 0xcb, 0x79, 0x4f, 0x5e, + 0xac, 0x7f, 0xf8, 0xdd, 0x63, 0x5d, 0x7f, 0xc1, 0x38, 0xbc, + 0x44, 0x84, 0xe2, 0xd5, 0xff, 00, 0x33, 0xff, 00, 0xc6, + 0xe8, 0x3, 0xf3, 0x21, 0xb4, 0x9b, 0xa5, 0x1c, 0xc2, 0xff, + 00, 0xf7, 0xc9, 0xff, 00, 0xa, 0x61, 0xb0, 0xb8, 0x1f, + 0xf2, 0xc6, 0x4f, 0xfb, 0xe4, 0xd7, 0xe8, 0xf5, 0xdf, 0xfc, + 0x13, 0xc7, 0xc4, 0xd1, 0xe7, 0x16, 0x6e, 0x7f, 0x3, 0xff, + 00, 0xc6, 0xeb, 0x9f, 0xbb, 0xfd, 0x81, 0xbc, 0x57, 0x11, + 0x20, 0x59, 0x3, 0xed, 0xf3, 0x7f, 0xf1, 0xba, 00, 0xfc, + 0xfe, 0xfb, 0x24, 0xff, 00, 0xf3, 0xc6, 0x41, 0xff, 00, + 00, 0x35, 0xea, 0xff, 00, 00, 0x7c, 0x3b, 0x2e, 0xa1, + 0xe2, 0x8b, 0x72, 0x62, 0x93, 0x99, 0x55, 0x47, 0xc8, 0x7d, + 0x45, 0x7d, 0x25, 0x75, 0xfb, 0xb, 0xf8, 0xba, 0x1d, 0xdf, + 0xf1, 0x2f, 0x7, 0x3, 0xb6, 0xe3, 0xff, 00, 0xb4, 0xeb, + 0xd8, 0xff, 00, 0x67, 0x5f, 0xd8, 0xfb, 0x5b, 0xd0, 0xb5, + 0xcb, 0x19, 0x6f, 0xac, 0x95, 0x15, 0x66, 0x56, 0x62, 0x41, + 0xe3, 0x91, 0xea, 0x94, 0x1, 0xf7, 0xcf, 0xec, 0xc3, 0xe1, + 0xaf, 0xf8, 0x47, 0x3e, 0x17, 0xd8, 0xa1, 0x52, 0x8d, 0x20, + 0xc, 0x41, 0x18, 0x3f, 0x74, 0x75, 0xaf, 0x5c, 0x3d, 0x45, + 0x66, 0xf8, 0x6b, 0x49, 0x4d, 0x17, 0x43, 0xb3, 0xb3, 0x55, + 0xb, 0xe5, 0x46, 0x14, 0xe3, 0xe9, 0x5a, 0x67, 0xa6, 0x28, + 0x3, 0x84, 0xf8, 0x97, 0x7e, 0x20, 0xb0, 0xc7, 0xb1, 0xeb, + 0xf8, 0x57, 0x89, 0xac, 0x9b, 0x89, 0x27, 0xa9, 0x35, 0xeb, + 0xff, 00, 0x12, 0x6c, 0x26, 0xbe, 0x8d, 0x11, 0x10, 0xb7, + 0x27, 0xa7, 0xe1, 0x5e, 0x7f, 0xff, 00, 0x8, 0xbc, 0xca, + 0x7, 0xee, 0xcd, 0x7e, 0x55, 0x9e, 0xd3, 0xad, 0x5f, 0x16, + 0xdc, 0x56, 0x88, 0xfc, 0x4f, 0x89, 0xa8, 0xd7, 0xc4, 0xe3, + 0x9b, 0x8a, 0xd1, 0x23, 0x7, 0x75, 0x1b, 0xab, 0x6d, 0xbc, + 0x39, 0x28, 0xff, 00, 0x96, 0x7f, 0xa5, 0x44, 0xde, 0x1f, + 0x95, 0x7f, 0x80, 0xfe, 0x55, 0xf3, 0x4f, 0xb, 0x59, 0x74, + 0x3e, 0x45, 0xe0, 0xeb, 0xaf, 0xb2, 0x65, 0x66, 0x8c, 0x8a, + 0xd2, 0x6d, 0xa, 0x51, 0xfc, 0x7, 0xf2, 0xa8, 0xdb, 0x46, + 0x90, 0xe, 0x8d, 0x50, 0xe8, 0x55, 0x5d, 0xc, 0xde, 0x1e, + 0xb2, 0xfb, 0x26, 0x9f, 0x82, 0x2d, 0x3e, 0xd3, 0xab, 0x29, + 0xe7, 00, 0x8a, 0xf7, 0xad, 0x3e, 0x2d, 0x96, 0xc8, 0x3d, + 0xab, 0xcb, 0x3e, 0x1b, 0xe8, 0x6c, 0x92, 0x19, 0x18, 0x1e, + 0x4f, 0x7f, 0xad, 0x7a, 0xda, 0x2e, 0xd4, 00, 0x76, 0x15, + 0xfa, 0x7f, 0xe, 0x61, 0xdd, 0x2c, 0x37, 0x34, 0xb7, 0x67, + 0xec, 0x7c, 0x27, 0x85, 0x74, 0x30, 0xae, 0x72, 0x5a, 0xb1, + 0xf4, 0x51, 0x45, 0x7d, 0x71, 0xf7, 0x61, 0x45, 0x14, 0x50, + 0x2, 0x1a, 0xf3, 0xff, 00, 0x89, 0x29, 0xe5, 0xd9, 0x33, + 0x13, 0xc9, 0x15, 0xe8, 0xd, 0xd2, 0xbc, 0xf3, 0xe2, 0x73, + 0x34, 0xb1, 0x4, 0x3, 0xa0, 0xaf, 0x17, 0x37, 0x76, 0xc1, + 0xcc, 0xf9, 0xec, 0xf6, 0xdf, 0x51, 0x9b, 0x3c, 0x77, 0x6e, + 0xde, 0x28, 0xa1, 0xe3, 0x7f, 0x30, 0xf1, 0x46, 0xd7, 0x1d, + 0x8d, 0x7e, 0x2d, 0xf2, 0x3f, 0x9e, 0xb6, 0xe8, 0x14, 0x51, + 0xb5, 0xbf, 0xba, 0x69, 0x39, 0xf4, 0xa2, 0xe1, 0x71, 0x6b, + 0x43, 0x42, 0x6d, 0x97, 0x80, 0xf7, 0xcd, 0x67, 0x64, 0xf7, + 0x1f, 0xa5, 0x5a, 0xd2, 0x58, 0x9d, 0x42, 0x35, 0xf7, 0xcd, + 0x6b, 0x45, 0xfe, 0xf6, 0x26, 0xf4, 0x25, 0x6a, 0xb1, 0x7e, + 0x67, 0xd0, 0xbe, 0x1b, 0x18, 0xd3, 0xd4, 0xf5, 0xcd, 0x6b, + 0x8a, 0xc6, 0xf0, 0xd3, 0xee, 0xb1, 0x51, 0xe8, 0x2b, 0x66, + 0xbf, 0x74, 0xc3, 0x7f, 0x6, 0x3e, 0x87, 0xf4, 0x9e, 0xf, + 0x5a, 0x10, 0xf4, 0x16, 0x8a, 0x28, 0xae, 0xa3, 0xb0, 0x28, + 0xa2, 0x8a, 00, 0x2a, 0x2b, 0x96, 0xd9, 0xb, 0x1f, 0x6a, + 0x96, 0xb3, 0xb5, 0xab, 0x81, 0x5, 0x94, 0x8d, 0xe8, 0xd, + 0x67, 0x52, 0x5c, 0xb0, 0x72, 0x66, 0x55, 0x65, 0xc9, 0x7, + 0x26, 0x78, 0xdf, 0xc4, 0x7b, 0xef, 0x3e, 0xfc, 0x47, 0xd8, + 0x1f, 0x5a, 0xe3, 0xab, 0x4f, 0xc4, 0xb7, 0x7f, 0x6b, 0xd5, + 0xa5, 0x3d, 0x70, 0x48, 0xac, 0xca, 0xfc, 0x3b, 0x1b, 0x57, + 0xdb, 0x62, 0x27, 0x3f, 0x33, 0xf9, 0xc3, 0x31, 0xad, 0xf5, + 0x8c, 0x5d, 0x49, 0xf9, 0x85, 0x14, 0x51, 0x5c, 0x27, 0x9c, + 0x14, 0x8f, 0xf7, 0x4d, 0x2d, 0x26, 0xdf, 0x32, 0x45, 0x5f, + 0x53, 0x43, 0xf2, 0x13, 0xd7, 0x43, 0xd3, 0x3e, 0x16, 0x59, + 0x64, 0xee, 0xaf, 0x5a, 0x3, 0x18, 0xae, 0xf, 0xe1, 0xad, + 0x9f, 0x93, 0x6f, 0xbb, 0x1f, 0xc3, 0x5d, 0xed, 0x7e, 0xcb, + 0x92, 0xd2, 0xf6, 0x58, 0x38, 0xa3, 0xfa, 0x3, 0x87, 0xa8, + 0x7b, 0x1c, 0xbe, 0x8, 0x28, 0xa2, 0x8a, 0xf7, 0x8f, 0xa6, + 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, + 0xa2, 0x80, 0x28, 0x6a, 0xd6, 0x82, 0xee, 0xd1, 0x93, 0x19, + 0x35, 0xe2, 0x1e, 0x31, 0xd0, 0xde, 0xd6, 0xed, 0xe4, 0xe4, + 0x28, 0xf6, 0xaf, 0x7c, 0x20, 0x10, 0x7d, 0x2b, 0x8c, 0xf1, + 0xaf, 0x87, 0x45, 0xe5, 0xa4, 0x8e, 0x6, 0x78, 0x26, 0xbe, + 0x67, 0x3b, 0xc0, 0xfd, 0x6a, 0x8b, 0x92, 0x5a, 0xa3, 0xe3, + 0xf8, 0x8b, 0x2d, 0x58, 0xda, 0xe, 0x71, 0x5a, 0xa3, 0xc3, + 0x81, 0xc8, 0xa2, 0xac, 0x5f, 0xda, 0x35, 0xac, 0xac, 0x36, + 0x10, 0x33, 0x8e, 0x95, 0x5c, 0x57, 0xe4, 0x6e, 0x2e, 0xf, + 0x96, 0x47, 0xe1, 0x72, 0x8b, 0x83, 0xe5, 0x90, 0x51, 0x45, + 0x14, 0x8, 0x28, 0xa2, 0x8a, 0x40, 0x14, 0x51, 0x45, 00, + 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, + 0x45, 00, 0x14, 0x13, 0x8a, 0xe, 0x7b, 0x55, 0xdd, 0x37, + 0x4b, 0x97, 0x51, 0x9d, 0x54, 0x21, 0xe7, 0xbd, 0x54, 0x63, + 0x2a, 0x92, 0xe5, 0x8e, 0xe5, 0xc2, 0x12, 0xab, 0x2e, 0x48, + 0x2b, 0xb1, 0x9a, 0x66, 0x9d, 0x26, 0xa1, 0x74, 0xb1, 0xa0, + 0x27, 0x24, 0x3, 0x81, 0x5e, 0xe3, 0xe1, 0x1f, 0xc, 0xc7, + 0x61, 0x69, 0x1b, 0x38, 0x3b, 0xb8, 0xea, 0x2b, 0x27, 0xc1, + 0x9e, 0x8, 0x5d, 0x39, 0x96, 0x59, 0x17, 0x9e, 0xbf, 0xe7, + 0x8a, 0xef, 0xd1, 0x42, 00, 00, 0xc0, 0xaf, 0xd3, 0x72, + 0x3c, 0xa3, 0xea, 0xf1, 0xf6, 0xd5, 0x97, 0xbc, 0xcf, 0xd8, + 0x78, 0x6f, 0x23, 0xfa, 0xac, 0x3d, 0xbd, 0x75, 0xef, 0x31, + 0x40, 0x2, 0x96, 0x8a, 0x2b, 0xed, 0xf, 0xd0, 0x42, 0x8a, + 0x29, 0x9, 0xc0, 0xcd, 00, 0x71, 0xdf, 0x12, 0x2f, 0xbe, + 0xcb, 0xa5, 0x6d, 0xcf, 0xde, 0xaf, 0xe, 0x9d, 0xb7, 0xca, + 0x4d, 0x7a, 0x5f, 0xc5, 0xbd, 0x50, 0x17, 0x86, 0x10, 0x7b, + 0x74, 0xaf, 0x32, 0x3c, 0x92, 0x6b, 0xf2, 0x3e, 0x21, 0xaf, + 0xed, 0x71, 0x8e, 0x2b, 0x64, 0x7e, 0x19, 0xc5, 0x58, 0x8f, + 0x6d, 0x8f, 0x94, 0x13, 0xd2, 0x21, 0x48, 0x46, 0x68, 0xa2, + 0xbe, 0x60, 0xf8, 0xd1, 0xb8, 0x23, 0xbd, 0x1, 0xa4, 0x5e, + 0x8c, 0x45, 0x3a, 0x8a, 0x5b, 0x6c, 0x4e, 0xdb, 0x31, 0xeb, + 0x79, 0x3a, 0xc, 0x9, 0xd, 0x4c, 0x9a, 0xad, 0xca, 0xc, + 0x79, 0x86, 0xab, 0x51, 0x54, 0xaa, 0x4d, 0x6c, 0xcb, 0x55, + 0x6a, 0x47, 0x69, 0x32, 0xd9, 0xd6, 0x6e, 0xb1, 0xc3, 0xd4, + 0x4f, 0xa9, 0xdc, 0xc9, 0xc3, 0x1c, 0xd4, 0x34, 0x55, 0x3a, + 0xb3, 0x7f, 0x68, 0xa7, 0x5a, 0xab, 0xde, 0x4c, 0x53, 0x23, + 0x49, 0xd6, 0x93, 0x14, 0x51, 0x59, 0x19, 0x36, 0xde, 0xe1, + 0x45, 0x14, 0x50, 0x20, 0xa2, 0x8a, 0xf, 0x2, 0x80, 0x19, + 0x23, 0x71, 0x5b, 0x9e, 0x11, 0xd2, 0x7e, 0xdb, 0x7a, 0x92, + 0x1c, 0xe0, 0x1f, 0x4a, 0xc8, 0xb6, 0xb4, 0x92, 0xf1, 0x82, + 0xa2, 0xe7, 0x9a, 0xf5, 0xbf, 0x7, 0xf8, 0x7f, 0xec, 0x16, + 0x6a, 0xf2, 0x28, 0xd, 0xe9, 0x5e, 0xf6, 0x4f, 0x81, 0x96, + 0x2f, 0x10, 0x9b, 0x5a, 0x23, 0xe9, 0xb8, 0x7f, 0x2e, 0x96, + 0x37, 0x14, 0xa4, 0xd7, 0xba, 0x8d, 0x41, 0x6e, 0xb6, 0xf1, + 0xa8, 0x3, 0x18, 0x15, 0x97, 0x7a, 0xf8, 0x53, 0x5a, 0xf7, + 0x8f, 0xc9, 0xac, 0xd, 0x42, 0x4c, 0x29, 0xaf, 0xd9, 0x21, + 0x15, 0x5, 0x64, 0x7e, 0xff, 00, 0x8, 0x2a, 0x71, 0x51, + 0x89, 0x81, 0xa8, 0xbf, 0x27, 0x9a, 0xe5, 0xf5, 0x17, 0x18, + 0x35, 0xbf, 0xa8, 0xc9, 0xd6, 0xb9, 0x6d, 0x4e, 0x4c, 0x2b, + 0x55, 0x96, 0x72, 0x9a, 0xcc, 0x83, 0xe6, 0xaf, 0x24, 0xf8, + 0x85, 0x7b, 0xe5, 0xda, 0xb2, 0xff, 00, 0x5a, 0xf4, 0xfd, + 0x5e, 0x6e, 0x5a, 0xbc, 0x47, 0xe2, 0x5d, 0xfe, 0xdd, 0xe3, + 0xb0, 0xae, 0x6c, 0x44, 0xb9, 0x69, 0xb6, 0x71, 0xe2, 0xe7, + 0xc9, 0x49, 0xb3, 0xe7, 0x9f, 0x88, 0x77, 0xa1, 0xa6, 0x94, + 0x7b, 0x9f, 0xe6, 0x6b, 0xc9, 0xf5, 0x39, 0x38, 0x35, 0xde, + 0x78, 0xde, 0xeb, 0xcd, 0xba, 0x70, 0x3f, 0xbc, 0x7f, 0xad, + 0x79, 0xde, 0xa5, 0x27, 0x5a, 0xf8, 0x26, 0xf9, 0xaa, 0xb6, + 0x7e, 0x65, 0x27, 0xcf, 0x5d, 0xb3, 0x9c, 0xd4, 0x5f, 0x2e, + 0x6b, 0x1e, 0x63, 0x9e, 0x33, 0x8a, 0xd1, 0xbd, 0x7c, 0xb9, + 0xac, 0xa9, 0xcf, 0xcd, 0x5e, 0xed, 0x15, 0x64, 0x7d, 0x2d, + 0x8, 0xd9, 0x23, 0xde, 0xbf, 0x62, 0x2f, 0xa, 0x37, 0x89, + 0x3e, 0x36, 0xdb, 0x4c, 0x54, 0xec, 0xb2, 0x8b, 0xcd, 0xdd, + 0x83, 0xdd, 0xd5, 0x48, 0xfc, 0x98, 0xd7, 0xeb, 0x9d, 0x9c, + 0x22, 0x18, 0xa3, 0x8c, 0x74, 0x45, 0xb, 0xf9, 0x57, 0xe7, + 0x5f, 0xfc, 0x13, 0x8f, 0xc3, 0x2a, 0x2f, 0xee, 0x75, 0x89, + 0x41, 0xdf, 0x3d, 0xc9, 0x86, 0x3c, 0x74, 0xda, 0x17, 0x27, + 0xb7, 0x5c, 0xad, 0x7e, 0x8d, 0x40, 0xb5, 0xf4, 0x54, 0x63, + 0x68, 0x23, 0xea, 0xf0, 0xf1, 0xe5, 0xa6, 0x8b, 0x90, 0x2f, + 0x35, 0xa3, 0xa, 0xf0, 0x2a, 0x8c, 0x2, 0xb4, 0x61, 0x1d, + 0x2b, 0x73, 0xa4, 0xb7, 0x8, 0xc9, 0xad, 0x18, 0x47, 0x19, + 0xaa, 0x30, 0xe, 0x6a, 0xfc, 0x27, 0x20, 0x50, 0x5, 0xd8, + 0x5, 0x5c, 0x8e, 0xaa, 0xc1, 0xc5, 0x5b, 0x8e, 0x80, 0x27, + 0x8c, 0x66, 0xac, 0x20, 0xa8, 0x63, 0xc5, 0x4e, 0x94, 0x1, + 0x20, 0xe8, 0x2a, 0x41, 0xd6, 0x98, 0x3a, 0xd4, 0x8b, 0x40, + 0xf, 0x5a, 0x7d, 0x31, 0x7b, 0x53, 0xe8, 00, 0xa7, 0x1, + 0xc5, 0x36, 0x9c, 0x3a, 0x50, 0x2, 0xd1, 0x45, 0x14, 0x1, + 0x9e, 0xd5, 0xc, 0x86, 0xa6, 0x7a, 0x82, 0x4a, 00, 0xaf, + 0x21, 0xaa, 0xb2, 0x9a, 0xb3, 0x21, 0xae, 0x7b, 0xc6, 0x3a, + 0xbc, 0x7a, 0x17, 0x86, 0xb5, 0x4b, 0xf9, 0x66, 0xf2, 0x16, + 0xde, 0xd9, 0xdf, 0xcc, 0xe7, 0xe5, 0x3b, 0x4e, 0x3f, 0x5c, + 0x54, 0xc9, 0xa8, 0xa7, 0x27, 0xd0, 0x99, 0x49, 0x42, 0x2e, + 0x4f, 0xa1, 0xf0, 0x77, 0xc5, 0xeb, 0xf3, 0xf1, 0x17, 0xf6, + 0x93, 0xba, 0x48, 0xff, 00, 0xd4, 0xc3, 0x75, 0x15, 0x9a, + 0x86, 0x39, 0xc6, 0xd6, 0xa, 0xdf, 0xf8, 0xf6, 0x4d, 0x7d, + 0xd3, 0xf0, 0xf3, 0x4c, 0x5d, 0x3f, 0x4c, 0xb7, 0x89, 0x40, + 0x1, 0x23, 0x3, 0x81, 0xec, 0x2b, 0xe1, 0x4f, 0xd9, 0xab, + 0x4b, 0x93, 0xc5, 0x9f, 0x13, 0x66, 0xd5, 0x6e, 0x3f, 0x7a, + 0xef, 0x33, 0xdd, 0xc8, 0xcf, 0x8c, 0x97, 0x67, 0xdc, 0x49, + 0xf7, 0xc9, 0x35, 0xfa, 0x17, 0xe1, 0xbb, 0x7f, 0x2e, 0x34, + 0x1e, 0xd5, 0xf2, 0x1c, 0x3e, 0xbd, 0xb4, 0xab, 0x62, 0xe5, + 0xbc, 0xe4, 0x7c, 0x1f, 0xb, 0x45, 0xe2, 0x25, 0x88, 0xc7, + 0x4b, 0x79, 0xc9, 0xdb, 0xd0, 0xe8, 0xad, 0x97, 0x9, 0x5e, + 0x47, 0xfb, 0x4b, 0xf8, 0xec, 0xf8, 0x2f, 0xc1, 0x6f, 0x22, + 0x6e, 0xde, 0xc1, 0x8e, 0x54, 0xe3, 0xd3, 0x1d, 0xfd, 0xeb, + 0xd8, 0x54, 0x61, 0x45, 0x7c, 0x3b, 0xff, 00, 0x5, 0x9, + 0xf1, 0xe2, 0x69, 0x1e, 0x1c, 0xb9, 0x8c, 0x31, 0x3b, 0x10, + 0x82, 0x1, 0xc7, 0xf7, 0x6b, 0xec, 0x4f, 0xbe, 0x3f, 0x2c, + 0xfe, 0x2e, 0x7e, 0xd0, 0x7a, 0xde, 0xaf, 0xe3, 0x7d, 0x42, + 0x58, 0xee, 0x25, 0x8, 0xb2, 0x15, 0x3, 0xcc, 0x6f, 0xfe, + 0x2a, 0xbb, 0x9f, 0xd9, 0xa3, 0xc7, 0x7e, 0x21, 0xf1, 0x47, + 0x8a, 0x23, 0xd, 0x72, 0xc1, 0xc, 0x8a, 0x80, 0xb3, 0xb7, + 0xa8, 0xf7, 0x35, 0xf2, 0xbe, 0xa3, 0x72, 0x6f, 0x2f, 0xa6, + 0x98, 0xe7, 0x2e, 0xc4, 0xf3, 0x5f, 0x76, 0x7f, 0xc1, 0x3f, + 0x7c, 0x3, 0xfd, 0xa3, 0xaf, 0x58, 0x48, 0x63, 0xf, 0xb9, + 0xd5, 0xce, 0x47, 0xba, 0xd0, 0x7, 0xeb, 0xef, 0xc1, 0xed, + 0x3e, 0x4d, 0x3f, 0xc0, 0x5a, 0x62, 0xca, 0xc5, 0xe4, 0x68, + 0x95, 0x8b, 0x1e, 0xff, 00, 0x28, 0xae, 0xca, 0x59, 0xd2, + 0x11, 0x97, 0x6c, 0x55, 0x4d, 0x3a, 0x5, 0xd3, 0x34, 0x9b, + 0x78, 0xf0, 0x2, 0xc5, 0x12, 0x8e, 0x3d, 0x85, 0x7c, 0x83, + 0xfb, 0x44, 0xfe, 0xda, 0xda, 0x3f, 0xc3, 0x4f, 0x1a, 0xc9, + 0xa1, 0xc8, 0x24, 0x67, 0x88, 0xe1, 0xb6, 0x92, 0x7, 0x40, + 0x7f, 0xba, 0x7d, 0x68, 0x3, 0xec, 0x65, 0xbd, 0x89, 0x8f, + 0xe, 0x2a, 0x65, 0x21, 0x86, 0x41, 0xcd, 0x7c, 0x1, 0xe1, + 0x4f, 0xdb, 0xdb, 0x46, 0xd7, 0xb5, 0x4b, 0x7b, 0x44, 0x8e, + 0x66, 0x79, 0xe, 0x7, 0xce, 0x47, 0xfe, 0xc9, 0x5f, 0x66, + 0xfc, 0x35, 0xf1, 0xa4, 0x7e, 0x30, 0xd2, 0x56, 0xe2, 0x35, + 0x2a, 0xa4, 0x67, 0x93, 0x9f, 0xe9, 0x40, 0x1d, 0x91, 00, + 0xf5, 0xa6, 0x98, 0x90, 0xf5, 0x45, 0x3f, 0x85, 0x3e, 0x8a, + 00, 0x85, 0xad, 0x21, 0x6e, 0xb1, 0x21, 0xff, 00, 0x80, + 0x8a, 0x8d, 0xb4, 0xcb, 0x46, 0xeb, 0x6b, 0x1, 0xfa, 0xc6, + 0x2a, 0xd5, 0x14, 0x1, 0x41, 0xb4, 0x2d, 0x39, 0xba, 0xd8, + 0xdb, 0x9f, 0xac, 0x4b, 0xfe, 0x14, 0xf8, 0x34, 0x7b, 0x1b, + 0x66, 0x6, 0x2b, 0x38, 0x62, 0x23, 0xba, 0xc6, 0x5, 0x5c, + 0xa2, 0x80, 0x10, 0x51, 0x8c, 0xa, 0x5a, 0x42, 0x33, 0x40, + 0x15, 0xe7, 0xb2, 0x86, 0xeb, 0x1e, 0x64, 0x6a, 0xf8, 0xf5, + 0x15, 0x5d, 0xb4, 0x3b, 0x46, 0xff, 00, 0x96, 0x4a, 0x3f, + 0xa, 0xd0, 0xdb, 0x46, 0x2b, 0x39, 0x53, 0x84, 0xb5, 0x68, + 0xca, 0x54, 0xa9, 0xc9, 0xde, 0x51, 0x4c, 0xcb, 0x6f, 0xe, + 0xd9, 0x37, 0xfc, 0xb2, 0x1f, 0x90, 0xa8, 0xdb, 0xc2, 0xf6, + 0x4c, 0x7f, 0xd5, 0x8f, 0xc8, 0x56, 0xc6, 0x28, 0xc5, 0x66, + 0xf0, 0xf4, 0x9e, 0xf1, 0x46, 0x4f, 0xb, 0x41, 0xef, 0x5, + 0xf7, 0x18, 0x4f, 0xe1, 0x1b, 0x36, 0xfe, 0x1, 0xf9, 0xa, + 0x85, 0xfc, 0x17, 0x66, 0xdf, 0xc2, 0xbf, 0x95, 0x74, 0x78, + 0xa3, 0x15, 0x93, 0xc1, 0xd0, 0x7f, 0x61, 0x19, 0x3c, 0x6, + 0x19, 0xef, 0x4, 0x66, 0xe9, 0x9a, 0x2c, 0x1a, 0x64, 0x61, + 0x63, 0x3, 0xeb, 0x8a, 0xd1, 0x14, 0xb8, 0xe2, 0x8a, 0xe9, + 0x84, 0x23, 0x4e, 0x3c, 0xb1, 0x56, 0x3a, 0xe9, 0xd3, 0x8d, + 0x28, 0xf2, 0xc1, 0x59, 0xb, 0x45, 0x14, 0x56, 0x86, 0x81, + 0x45, 0x14, 0x50, 0x2, 0x1a, 0xe6, 0x7c, 0x51, 0xa1, 0xb6, + 0xa6, 0xa7, 0x68, 0x1c, 0xfa, 0x8a, 0xe9, 0x8f, 0x34, 0x9b, + 0x6b, 0xa, 0xf4, 0x63, 0x5e, 0xe, 0x13, 0xd8, 0xe6, 0xc4, + 0x61, 0xe1, 0x89, 0xa6, 0xe9, 0xcf, 0x66, 0x79, 0x1, 0xf8, + 0x7f, 0x38, 0x24, 0xf1, 0xf9, 0x7f, 0xf5, 0xaa, 0x17, 0xf0, + 0x1c, 0xe3, 0xb0, 0xfc, 0xab, 0xd9, 0x4a, 0xa, 0x4f, 0x2c, + 0x7a, 0xf, 0xca, 0xbe, 0x7d, 0xe4, 0x18, 0x56, 0x7c, 0xbc, + 0xb8, 0x63, 0x6, 0xf6, 0x3c, 0x55, 0xbc, 0xf, 0x70, 0x3a, + 0x28, 0xfc, 0x8d, 0x44, 0xfe, 0xc, 0x9c, 0x7f, 0xa, 0xfe, + 00, 0xd7, 0xb7, 0x18, 0x50, 0xff, 00, 0x8, 0xfc, 0xa9, + 0xd, 0xb4, 0x47, 0xf8, 0x17, 0xf2, 0xac, 0x5f, 0xe, 0xe1, + 0xde, 0xcc, 0xc2, 0x5c, 0x29, 0x85, 0x7b, 0x33, 0xc2, 0x9f, + 0xc2, 0x13, 0xaf, 0xf0, 0xf, 0xca, 0xa4, 0xd3, 0x3c, 0x2b, + 0x34, 0x57, 0x61, 0xfc, 0xb1, 0xf9, 0x57, 0xb7, 0x9b, 0x28, + 0x5b, 0xfe, 0x59, 0xaf, 0xe5, 0x48, 0x2c, 0x20, 0x7, 0x88, + 0xd7, 0xf2, 0xac, 0xd7, 0xe, 0x52, 0x52, 0x52, 0x52, 0xd8, + 0xc5, 0x70, 0x9d, 0x18, 0xc9, 0x49, 0x4b, 0x62, 0x96, 0x83, + 0x6c, 0xd6, 0xd6, 0x40, 0x30, 0xc1, 0xad, 0x41, 0x48, 0x14, + 0x1, 0x81, 0xc0, 0xa5, 0xaf, 0xad, 0xa7, 0x5, 0x4e, 0xa, + 0x2b, 0xa1, 0xf7, 0x34, 0xa9, 0xaa, 0x50, 0x50, 0x5d, 0x5, + 0xa2, 0x8a, 0x2b, 0x43, 0x50, 0xa2, 0x8a, 0x28, 0x1, 0xa7, + 0xa5, 0x73, 0x9e, 0x32, 0x95, 0x93, 0x4d, 0x94, 0x3, 0x82, + 0x54, 0x81, 0x5d, 0x21, 0x15, 0x9f, 0xab, 0x69, 0x4b, 0xa9, + 0x44, 0x50, 0x90, 0x33, 0xea, 0x2b, 0x97, 0x13, 0x9, 0x54, + 0xa5, 0x28, 0x47, 0x76, 0x71, 0x63, 0x29, 0xce, 0xad, 0x9, + 0x42, 0x1b, 0xb3, 0xe7, 0x5b, 0x8b, 0x29, 0x26, 0xb9, 0x91, + 0xf3, 0xd4, 0x9e, 0x4d, 0x44, 0x6c, 0x64, 0x1d, 0xeb, 0xda, + 0x5f, 0xe1, 0xec, 0x47, 0x3c, 0xa1, 0x3f, 0xee, 0xd4, 0xf, + 0xf0, 0xed, 0x4f, 0x42, 0xbf, 0xf7, 0xcf, 0xff, 00, 0x5e, + 0xbf, 0x35, 0x97, 0xe, 0xe2, 0x2f, 0x7b, 0x1f, 0x91, 0x4f, + 0x85, 0x31, 0x57, 0x6e, 0xc7, 0x8e, 0x1b, 0x39, 0x7, 0x7a, + 0x6f, 0xd9, 0x64, 0xcf, 0x5a, 0xf5, 0xf6, 0xf8, 0x77, 0xd7, + 0x5, 0x7f, 0x2a, 0x81, 0xfe, 0x1d, 0x37, 0xb7, 0xe5, 0x5c, + 0xef, 0x20, 0xc4, 0xae, 0x87, 0x2c, 0xb8, 0x5f, 0x16, 0xb6, + 0x89, 0xe4, 0xc6, 0x9, 0x5, 0x4f, 0xa5, 0xda, 0x3c, 0xda, + 0x84, 0x63, 0x1d, 0xd, 0x7a, 0x5c, 0x9f, 0xf, 0x24, 0xec, + 0x7f, 0x4f, 0xfe, 0xbd, 0x4b, 0xa4, 0xf8, 0xa, 0x4b, 0x6b, + 0xb0, 0xec, 0x47, 0x1f, 0xec, 0xd4, 0xc3, 0x22, 0xc4, 0x7b, + 0x48, 0xde, 0x3a, 0x11, 0x4f, 0x86, 0xf1, 0x7e, 0xd6, 0x37, + 0x8e, 0x87, 0x53, 0xe0, 0xeb, 0x43, 0x6f, 0x62, 0xe, 0x31, + 0xc5, 0x74, 0x95, 0x56, 0xc2, 0xd8, 0x5a, 0xdb, 0xaa, 0x77, + 0xab, 0x55, 0xfa, 0xae, 0x1e, 0x9f, 0xb2, 0xa5, 0x18, 0x76, + 0x3f, 0x6c, 0xc2, 0x52, 0xf6, 0x14, 0x63, 0x4f, 0xb0, 0x51, + 0x45, 0x15, 0xd2, 0x75, 0x85, 0x14, 0x51, 0x40, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x41, 0x75, 0x6e, + 0xb7, 0x31, 0x14, 0x6e, 0x84, 0x54, 0xf4, 0x94, 0x9a, 0x4d, + 0x59, 0x89, 0xa5, 0x25, 0x66, 0x79, 0x77, 0x8b, 0xfc, 0x2a, + 0xa3, 0x7b, 0x46, 0x83, 0xf2, 0xaf, 0x35, 0xbc, 0xd3, 0x67, + 0xb7, 0x90, 0xee, 0x50, 0x2b, 0xe9, 0x5b, 0x8b, 0x54, 0xb8, + 0x8c, 0xab, 0x28, 0x3f, 0x85, 0x71, 0x1e, 0x22, 0xf0, 0x93, + 0x5c, 0xee, 0x31, 0xa8, 0x1f, 0x85, 0x7c, 0x26, 0x6d, 0x91, + 0xfb, 0x4b, 0xd4, 0xa4, 0x7e, 0x6b, 0x9d, 0xf0, 0xef, 0xb5, + 0x6e, 0xb5, 0xf, 0xb8, 0xf1, 0x7c, 0x63, 0x83, 0x46, 0x6b, + 0xa5, 0xd5, 0x3c, 0x1d, 0x73, 0x3, 0x13, 0xbb, 0x1f, 0x87, + 0xff, 00, 0x5e, 0xb0, 0x66, 0xd3, 0xe4, 0xb7, 0x38, 0x63, + 0x9f, 0xc2, 0xbe, 0x6, 0xae, 0x1a, 0xad, 0x17, 0x69, 0xc6, + 0xc7, 0xe6, 0x15, 0xf0, 0x95, 0xf0, 0xee, 0xd3, 0x8d, 0x88, + 0x28, 0xa5, 0xc1, 0x1c, 0x1a, 0x4c, 0x8a, 0xe6, 0xbf, 0x73, + 0x8e, 0xfd, 0xc2, 0x8a, 0x37, 0xa, 0x37, 0xf, 0x5a, 0x2e, + 0x17, 0x41, 0x45, 0x14, 0x50, 0x30, 0xa2, 0x82, 0x71, 0xdb, + 0x34, 0xaa, 0x8c, 0xe7, 0x85, 0x34, 0x6a, 0x24, 0xdb, 0x76, + 0x42, 0x12, 0x5, 0x2c, 0x68, 0x66, 0x20, 0x28, 0xe6, 0xb5, + 0x74, 0xed, 0x2, 0x4b, 0xf6, 0xc6, 0x31, 0xee, 0x6b, 0xb5, + 0xd0, 0x7e, 0x1d, 0xb0, 0x91, 0x5d, 0xb1, 0xff, 00, 0x7c, + 0xd7, 0xa7, 0x85, 0xcb, 0xb1, 0x18, 0xa6, 0xb9, 0x56, 0x87, + 0xb5, 0x83, 0xca, 0x71, 0x58, 0xc9, 0x2e, 0x48, 0xe8, 0x72, + 0x5a, 0x37, 0x85, 0xae, 0x2f, 0xa4, 0x19, 0x1c, 0x67, 0xd2, + 0xbd, 0x63, 0xc3, 0x9e, 0xd, 0x82, 0xca, 0x15, 0x77, 0x40, + 0x5b, 0xe9, 0x5b, 0x9a, 0x56, 0x89, 0x15, 0x84, 0x40, 0x6d, + 0x5c, 0x8f, 0x6a, 0xd2, 0xb, 0x81, 0x8e, 0xd5, 0xfa, 0x4e, + 0x5d, 0x92, 0xd2, 0xc2, 0x25, 0x39, 0x2b, 0xb3, 0xf5, 0xac, + 0xa7, 0x87, 0xa8, 0xe0, 0x57, 0x3d, 0x45, 0x79, 0xc, 0x8e, + 0x31, 0x1a, 0xed, 0x51, 0x52, 0xa, 0x31, 0x4b, 0x5f, 0x4c, + 0x95, 0x8f, 0xb1, 0x4a, 0xda, 0x20, 0xa2, 0x8a, 0x29, 0x8c, + 0x2a, 0xb5, 0xe4, 0xc2, 0x18, 0x1d, 0x8d, 0x58, 0xac, 0x3f, + 0x14, 0xdd, 0x1b, 0x7b, 0x33, 0x8f, 0x4a, 0xc2, 0xbc, 0xfd, + 0x9d, 0x39, 0x4c, 0xe6, 0xc4, 0x55, 0x54, 0x69, 0x4a, 0x7d, + 0x8f, 0x1e, 0xf8, 0x87, 0x7d, 0xf6, 0xbd, 0x61, 0x70, 0x4e, + 00, 0x3f, 0xce, 0xb9, 0x7a, 0xbd, 0xae, 0x5c, 0x35, 0xce, + 0xa4, 0xec, 0x7b, 0x13, 0x54, 0x6b, 0xf0, 0xec, 0x65, 0x57, + 0x5a, 0xbc, 0xe6, 0xfa, 0xb3, 0xf9, 0xc3, 0x1d, 0x59, 0xd7, + 0xc4, 0xd4, 0xa8, 0xfa, 0xb0, 0xa2, 0x8a, 0x2b, 0x8e, 0xc7, + 0xd, 0x82, 0x8a, 0x28, 0xa7, 0x60, 0xb0, 0x51, 0x45, 0x14, + 0x58, 0x2c, 0x14, 0x51, 0x45, 0x2b, 0x5, 0x82, 0x8a, 0x28, + 0xa7, 0x60, 0xb0, 0x51, 0x45, 0x3, 0xe6, 0xe0, 0x52, 0x10, + 0x84, 0xe2, 0xa4, 0xb5, 0xb7, 0x6b, 0xc9, 0x76, 0x28, 0x39, + 0x35, 0x6f, 0x4f, 0xd2, 0x27, 0xbb, 0x95, 0x40, 0x5e, 0x9, + 0xaf, 0x4e, 0xf0, 0xaf, 0x82, 0x95, 0x4a, 0xbb, 0x81, 0x9f, + 0xa5, 0x7a, 0xd8, 0x2c, 0xb6, 0xae, 0x36, 0x76, 0x4b, 0x43, + 0xdc, 0xcb, 0x72, 0x8a, 0xf9, 0x84, 0xd2, 0x4a, 0xc8, 0xcf, + 0xf0, 0x67, 0x83, 0xf6, 0x44, 0x24, 0x91, 0x43, 0x7b, 0x91, + 0x5d, 0xe4, 0x90, 0xad, 0xac, 0xa, 0x80, 0x1, 0x5a, 0x96, + 0xb6, 0x89, 0x67, 0xe, 0xc5, 0x3, 0x8f, 0x41, 0x54, 0x75, + 0x7, 0xe3, 0x15, 0xfa, 0xd6, 0x3, 0x3, 0x4f, 0x5, 0x4d, + 0x46, 0x2b, 0x53, 0xf7, 0x2c, 0xb7, 0x2d, 0xa7, 0x97, 0xd2, + 0x50, 0x8a, 0xd4, 0xe7, 0xef, 0x1a, 0xb9, 0xed, 0x49, 0xf8, + 0x35, 0xd0, 0x5e, 0xbf, 0x5a, 0xe7, 0x75, 0x27, 0xeb, 0x5e, + 0xa1, 0xec, 0x9c, 0xce, 0xa2, 0xfd, 0x6b, 0x94, 0xd5, 0xe5, + 0xc2, 0x9a, 0xe9, 0xf5, 0x29, 0x3a, 0xd7, 0x23, 0xab, 0xcb, + 0xc1, 0xe6, 0x80, 0x38, 0xcd, 0x5e, 0x4f, 0xbf, 0x5f, 0x3d, + 0x7c, 0x4e, 0xd4, 0xe, 0xf9, 0xb9, 0x38, 0xc9, 0xaf, 0x7e, + 0xd6, 0xe6, 0xda, 0xae, 0x7d, 0xab, 0xe6, 0x3f, 0x89, 0x97, + 0xf8, 0x79, 0xb9, 0x27, 0x93, 0xde, 0xbc, 0xac, 0xc2, 0x7c, + 0xb4, 0x8f, 0x17, 0x34, 0x9f, 0x25, 0x13, 0xc2, 0x3c, 0x4d, + 0x70, 0x64, 0xbd, 0x90, 0x92, 0x7a, 0x9f, 0xe6, 0x6b, 0x88, + 0xd4, 0xe4, 0xeb, 0x5d, 0x56, 0xb9, 0x36, 0xf9, 0xe4, 0x3e, + 0xe6, 0xb8, 0xed, 0x4d, 0xf8, 0x6a, 0xf8, 0xea, 0x3e, 0xf4, + 0xee, 0x7c, 0x6, 0x19, 0x73, 0x4e, 0xe6, 0x5, 0xd3, 0x65, + 0x8d, 0x66, 0x4e, 0x72, 0x4f, 0xbd, 0x68, 0x5c, 0xb7, 0x26, + 0xaa, 0xda, 0xc2, 0x6e, 0xaf, 0xed, 0xa1, 00, 0x93, 0x24, + 0x8a, 0xb8, 0x3, 0x3d, 0x4d, 0x7d, 0x1d, 0x25, 0xb1, 0xf5, + 0xb4, 0x23, 0xb2, 0x3f, 0x4b, 0x7f, 0x61, 0x2f, 0x9, 0x47, + 0xa2, 0xf8, 0x1f, 0x45, 0x65, 0xc3, 0xbc, 0x91, 0x35, 0xeb, + 0x3e, 0x39, 0xfd, 0xe6, 0xe, 0x9, 0xe3, 0xa6, 0xea, 0xfb, + 0x16, 0x1c, 0xe0, 0x67, 0xad, 0x78, 0xdf, 0xec, 0xeb, 0xe1, + 0xf1, 0xa1, 0xf8, 0x5a, 0xde, 00, 0xaa, 0xab, 0x6f, 0x6f, + 0x15, 0xb2, 0x6d, 00, 0xc, 0x2a, 0x81, 0xc0, 0x1d, 0x3a, + 0x57, 0xb3, 0x42, 0xb5, 0xf4, 0x31, 0x56, 0x49, 0x1f, 0x55, + 0x15, 0x68, 0xa4, 0x5e, 0xb7, 0x7, 0xd6, 0xb4, 0x21, 0xaa, + 0x56, 0xeb, 0x57, 0xe0, 0x1c, 0xa, 0xa2, 0x8b, 0xb0, 0xe, + 0x5, 0x5f, 0x8b, 0x8c, 0x55, 0x4b, 0x75, 0xe9, 0x57, 0x63, + 0x1d, 0x28, 0x2, 0xe4, 0x3c, 0xd5, 0xb8, 0xc5, 0x56, 0xb7, + 0x18, 0x15, 0x6e, 0x3a, 00, 0x9e, 0x31, 0x53, 0xaf, 0x41, + 0x51, 0x46, 0x2a, 0x75, 0x14, 00, 0xf5, 0xa7, 0x81, 0xc5, + 0x31, 0x7a, 0x54, 0x8b, 0xc5, 00, 0x3d, 0x69, 0xd4, 0x8b, + 0x4b, 0x40, 0x5, 0x3e, 0x9a, 0x3a, 0xd3, 0xa8, 00, 0xa2, + 0x8a, 0x28, 0x3, 0x39, 0xfa, 0xd5, 0x79, 0xd, 0x4e, 0xf5, + 0x5a, 0x43, 0x40, 0x15, 0xe4, 0x35, 0xe0, 0x9f, 0xb6, 0x37, + 0x8b, 0xcf, 0x86, 0xbe, 0xf, 0x5d, 0xda, 0xa2, 0x2b, 0xbe, + 0xaf, 0x32, 0x59, 0x6e, 0x24, 0xe5, 0x41, 0xf9, 0xf7, 0xf, + 0xfb, 0xe3, 0x1f, 0x8d, 0x7b, 0xcc, 0xb5, 0xf1, 0x27, 0xed, + 0xb7, 0xe2, 0xe8, 0xbc, 0x41, 0xe3, 0x9d, 0x7, 0xc2, 0x96, + 0xbb, 0x9a, 0x5d, 0x3d, 0x4c, 0xf3, 0xff, 00, 0x74, 0xb4, + 0x98, 0x8, 0x38, 0xee, 0x30, 0x7f, 0x3a, 0xf0, 0xf3, 0xac, + 0x47, 0xd5, 0xb0, 0x35, 0x25, 0x7d, 0x5a, 0xb2, 0xf9, 0x9f, + 0x39, 0xc4, 0x18, 0xaf, 0xaa, 0x65, 0xb5, 0x67, 0x7d, 0x5a, + 0xb2, 0xf5, 0x66, 0xe7, 0xec, 0x73, 0xe1, 0x63, 0x6, 0x93, + 0x36, 0xa2, 0xd9, 0xcc, 0x8f, 0xb4, 0xf, 0x6c, 0x2d, 0x7d, + 0x97, 0xa3, 0xc3, 0xb1, 0x17, 0x35, 0xe2, 0x7f, 0xb3, 0xe7, + 0x85, 0xf, 0x87, 0xfc, 0x13, 0xa6, 0xc2, 0xc8, 0xaa, 0xec, + 0x81, 0xdb, 0x69, 0x3d, 0x48, 0x15, 0xee, 0xd6, 0x11, 0xed, + 0x1f, 0x85, 0x5e, 0x51, 0x87, 0xfa, 0xb6, 0xa, 0x9c, 0x1e, + 0xf6, 0xbb, 0xf9, 0x9a, 0x64, 0x38, 0x6f, 0xaa, 0x65, 0xf4, + 0xa9, 0xdb, 0x5b, 0x5d, 0xfc, 0xcb, 0x57, 0x12, 0x8b, 0x7b, + 0x79, 0x24, 0x6e, 0x15, 0x14, 0x93, 0x5f, 0x90, 0x1f, 0xf0, + 0x52, 0x9f, 0x88, 0xbf, 0x69, 0x96, 0x4b, 0x34, 0x70, 0x1e, + 0x42, 0x47, 0x4e, 0xbf, 0x77, 0xda, 0xbf, 0x57, 0xfe, 0x20, + 0xea, 0xa3, 0x48, 0xf0, 0xad, 0xec, 0xb9, 0x21, 0x8a, 0x60, + 0x62, 0xbf, 0x4, 0x7f, 0x6d, 0xef, 0x1b, 0x7f, 0xc2, 0x43, + 0xf1, 0x15, 0xed, 0x56, 0x46, 0x91, 0x61, 0xcf, 0xc, 00, + 0xc7, 0xdd, 0xff, 00, 0xa, 0xf6, 0x4f, 0x7c, 0xf9, 0xd7, + 0x4b, 0xb5, 0x37, 0x97, 0xf6, 0xf0, 0x81, 0xf7, 0xe4, 0x51, + 0xf8, 0x67, 0x9a, 0xfd, 0x7f, 0xff, 00, 0x82, 0x71, 0xf8, + 0x22, 0x12, 0x22, 0xb9, 0xc9, 0x6f, 0x29, 0x57, 0x20, 0xe, + 0x6, 0x36, 0xfb, 0xd7, 0xe4, 0x37, 0x87, 0xef, 0x22, 0xb0, + 0xd4, 0xe1, 0x9e, 0x5c, 0xed, 0x46, 0x7, 0x8a, 0xfd, 0x48, + 0xfd, 0x88, 0xbf, 0x6a, 0x8f, 0xb, 0xfc, 0x3a, 0xf0, 0xff, + 00, 0xd9, 0xef, 0x96, 0xe1, 0xa6, 0x90, 0x1, 0xfb, 0xb8, + 0xd4, 0x8e, 0x8b, 0xea, 0x7d, 0xa8, 0x3, 0xf4, 0xd3, 0xc5, + 0x97, 0xc3, 0x4f, 0xd1, 0x2e, 0x25, 0xec, 0xa8, 0x49, 0xfa, + 0x62, 0xbf, 0x9e, 0xdf, 0xdb, 0x5f, 0xc5, 0xb2, 0xf8, 0x9f, + 0xf6, 0x86, 0xf1, 0x44, 0xc6, 0x42, 0x56, 0x39, 0xc2, 0x2e, + 0x38, 0x3, 0xa, 0xb5, 0xfa, 0xb9, 0xf1, 0x87, 0xf6, 0xe6, + 0xf0, 0x99, 0xf0, 0x8e, 0xa0, 0x90, 0x47, 0x77, 0xbc, 0xc4, + 0x55, 0x7e, 0x45, 0xea, 0x47, 0xfb, 0xd5, 0xf8, 0x9f, 0xf1, + 0x3b, 0xc4, 0x43, 0xc5, 0x9e, 0x3e, 0xd6, 0xf5, 0x65, 0xdd, + 0xb6, 0xea, 0xe0, 0xb8, 0xdd, 0xd7, 0xb0, 0xfe, 0x94, 0x1, + 0xe8, 0xbf, 0xb2, 0xdf, 0x86, 0xe5, 0xf1, 0x17, 0xc4, 0x1b, + 0x43, 0x96, 0x65, 0x47, 0x1d, 0xfa, 0xf5, 0xaf, 0xde, 0x8f, + 0xd9, 0xef, 0xc3, 0xc3, 0x45, 0xf0, 0x4d, 0xbb, 0x75, 0x67, + 0x18, 0xcf, 0xb0, 0xaf, 0xc6, 0x5f, 0xd8, 0x9e, 0xeb, 0x49, + 0xf0, 0xfe, 0xb3, 0x15, 0xde, 0xa6, 0x33, 0x96, 0xc9, 0xda, + 0x32, 0x4f, 0x5c, 0xe, 0xa2, 0xbf, 0x5f, 0x7c, 0x1d, 0xfb, + 0x45, 0x78, 0x27, 0x4e, 0xd0, 0x6d, 0x2d, 0xbe, 0xd1, 0x3a, + 0xb2, 0xa7, 0x41, 0x18, 0xff, 00, 0xe2, 0xa8, 0x3, 0xdc, + 0x68, 0xaf, 0x31, 0x8f, 0xf6, 0x89, 0xf0, 0x6c, 0xa3, 0x8b, + 0xa9, 0xff, 00, 0xef, 0x81, 0xff, 00, 0xc5, 0x55, 0xb8, + 0xfe, 0x3c, 0x78, 0x46, 0x4e, 0x97, 0xb2, 0xf, 0xaa, 0xf, + 0xf1, 0xa0, 0xf, 0x43, 0xa2, 0xb8, 0x68, 0xbe, 0x33, 0x78, + 0x5e, 0x53, 0xc5, 0xf1, 0x1f, 0x55, 0xff, 00, 0xeb, 0xd5, + 0xc8, 0xfe, 0x29, 0x78, 0x72, 0x5e, 0x97, 0xe0, 0x7f, 0xc0, + 0x4d, 00, 0x75, 0xb4, 0x56, 0x5e, 0x99, 0xe2, 0x5d, 0x3b, + 0x57, 0x20, 0x5a, 0xdc, 0xac, 0xa4, 0xf4, 0x2, 0xb5, 0x28, + 00, 0xa2, 0x8a, 0x8a, 0x5b, 0xa8, 0x60, 0x19, 0x92, 0x45, + 0x4f, 0xa9, 0xa0, 0x9, 0x68, 0xa8, 0x16, 0xfa, 0xdd, 0xba, + 0x4f, 0x19, 0xff, 00, 0x81, 0xa, 0x78, 0x9e, 0x33, 0xd2, + 0x45, 0x3f, 0x46, 0x14, 0x1, 0x25, 0x14, 0xdd, 0xea, 0x7f, + 0x88, 0x7e, 0x74, 0xbb, 0x87, 0xa8, 0xa0, 0x5, 0xa2, 0x8a, + 0x4a, 00, 0x5a, 0x28, 0xa4, 0xcd, 00, 0x2d, 0x14, 0x51, + 0x40, 0x5, 0x14, 0x99, 0x14, 0xb4, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, + 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x52, 0x1a, 0x5a, 0x28, 0x1, + 0xb8, 0xa3, 0x8a, 0x75, 0x14, 00, 0xde, 0x28, 0xcd, 0x3a, + 0x8a, 00, 0x6e, 0x1, 0xa5, 0xc0, 0x14, 0xb4, 0x50, 0x3, + 0x69, 0xd4, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, + 0x5, 0x14, 0x51, 0x40, 0x5, 0x34, 0x80, 0x69, 0xd4, 0x50, + 0x6, 0x5e, 0xa1, 0xa3, 0x25, 0xe0, 0x23, 0x81, 0x9a, 0xe4, + 0xb5, 0x3f, 0x87, 0x9f, 0x69, 0x25, 0x87, 0x5f, 0x63, 0x5e, + 0x83, 0x48, 0x46, 0x6b, 0xcf, 0xc4, 0x60, 0x28, 0x62, 0x7f, + 0x88, 0x8f, 0x2b, 0x13, 0x96, 0x61, 0xb1, 0x7f, 0xc5, 0x89, + 0xe3, 0x97, 0x3f, 0xd, 0x1d, 0x49, 0xc6, 0x7f, 0x3f, 0xfe, + 0xbd, 0x64, 0x5d, 0xf8, 0xa, 0x58, 0xf, 0x53, 0x5e, 0xec, + 0xd0, 0xab, 0xf5, 0x5a, 0xab, 0x3e, 0x95, 0x14, 0xfd, 0xbf, + 0x3a, 0xf0, 0x2b, 0x70, 0xee, 0x1a, 0x4b, 0xdc, 0x47, 0xcc, + 0xd7, 0xe1, 0x4c, 0x2c, 0xd7, 0xb8, 0x8f, 0x2, 0x7f, 0x8, + 0xce, 0x3b, 0x9a, 0x8f, 0xfe, 0x11, 0x4b, 0x8c, 0xf5, 0x35, + 0xee, 0xcf, 0xe1, 0xb8, 0x5b, 0xb0, 0xa6, 0x8f, 0xc, 0xc2, + 0xe, 0x70, 0xb5, 0xe6, 0x3e, 0x19, 0x8d, 0xcf, 0x1d, 0xf0, + 0x7c, 0x6f, 0xa1, 0xe2, 0x49, 0xe0, 0xeb, 0xb6, 0x1c, 0x67, + 0xf4, 0xa9, 0x53, 0xc1, 0x77, 0x9e, 0x87, 0xfc, 0xfe, 0x35, + 0xee, 0x31, 0xe8, 0x91, 0x20, 0x3, 0x2, 0xac, 0x26, 0x9d, + 0x12, 0x7f, 0x8, 0x35, 0xbc, 0x38, 0x66, 0x97, 0x56, 0x75, + 0x43, 0x83, 0xa8, 0xfd, 0xa6, 0x78, 0xc5, 0x8f, 0x81, 0xee, + 0x59, 0x86, 0xe1, 0x91, 0xf4, 0xff, 00, 0xeb, 0xd7, 0x67, + 0xa4, 0xf8, 0xa, 0x2d, 0x8a, 0x64, 0x18, 0x38, 0xae, 0xe8, + 0x40, 0x8b, 0xd1, 0x45, 0x48, 0xa0, 0x1, 0xc5, 0x7b, 0x18, + 0x6c, 0x8f, 0xd, 0x87, 0x7a, 0xab, 0x9e, 0xee, 0x13, 0x87, + 0x30, 0x98, 0x67, 0x76, 0xae, 0x62, 0xd9, 0xf8, 0x5e, 0xd6, + 0xd3, 0x5, 0x46, 0x6b, 0x5e, 0x38, 0x96, 0x31, 0x80, 0x31, + 0xf4, 0xa9, 0x28, 0xaf, 0x7a, 0x9d, 0x28, 0x52, 0x56, 0x82, + 0xb1, 0xf4, 0xb4, 0xa8, 0xd3, 0xa2, 0xad, 0x4e, 0x36, 0x10, + 0x63, 0xb5, 0x2d, 0x14, 0x56, 0xa6, 0xe1, 0x45, 0x14, 0x50, + 0x1, 0x45, 0x14, 0x50, 0x2, 0x56, 0x3f, 0x88, 0x74, 0xd6, + 0xbf, 0xb7, 0x21, 0x73, 0xd3, 0x15, 0xb3, 0x45, 0x65, 0x52, + 0x9a, 0xab, 0x17, 0x9, 0x75, 0x31, 0xad, 0x4a, 0x35, 0xa0, + 0xe9, 0xcb, 0x66, 0x78, 0x66, 0xaf, 0xe0, 0x6b, 0x95, 0x99, + 0x98, 0x67, 0x93, 0x9a, 0xe7, 0x6e, 0xfc, 0x3d, 0x71, 0x6e, + 0xc7, 0x35, 0xf4, 0x65, 0xcd, 0x9a, 0xdc, 0xae, 0x8, 0x19, + 0xae, 0x7f, 0x51, 0xf0, 0x72, 0x5d, 0x93, 0x8d, 0xa3, 0xeb, + 0x5f, 0xd, 0x8b, 0xe1, 0xb8, 0xc9, 0xb7, 0x48, 0xfc, 0xe3, + 0x1d, 0xc2, 0x70, 0x95, 0xe5, 0x40, 0xf0, 0x56, 0xb6, 0x78, + 0xcf, 0x34, 0xdc, 0x62, 0xbd, 0x66, 0xf7, 0xe1, 0x93, 0xc8, + 0x49, 0x5d, 0x9f, 0x99, 0xac, 0x9b, 0x8f, 0x86, 0x13, 0x8c, + 0xe0, 0x2f, 0xfd, 0xf4, 0x6b, 0xe6, 0xaa, 0xe4, 0x78, 0xb8, + 0x3d, 0x22, 0x7c, 0x7d, 0x5e, 0x1b, 0xc7, 0x52, 0x7a, 0x40, + 0xf3, 0xbc, 0xe2, 0x8c, 0x8a, 0xec, 0xe7, 0xf8, 0x6d, 0x76, + 0x99, 0xc6, 0xdf, 0xcc, 0xd6, 0x74, 0xfe, 0x5, 0xbc, 0x8c, + 0xf6, 0xfc, 0xcd, 0x79, 0xf3, 0xcb, 0xb1, 0x54, 0xf7, 0x81, + 0xe6, 0x4f, 0x2a, 0xc7, 0x53, 0xde, 0x9b, 0x39, 0xdc, 0x8a, + 0x33, 0x9a, 0xd9, 0x6f, 0x6, 0xde, 0xaf, 0xa7, 0xe6, 0x69, + 0x17, 0xc1, 0xfa, 0x81, 0x3c, 0x5, 0x3f, 0x89, 0xac, 0x3e, + 0xab, 0x88, 0xfe, 0x46, 0x73, 0x7d, 0x4b, 0x15, 0xff, 00, + 0x3e, 0xd9, 0x8f, 0x45, 0x6e, 0xaf, 0x82, 0x35, 0x36, 0xe8, + 0x8b, 0xf9, 0x9a, 0x90, 0x78, 0x1f, 0x53, 0xff, 00, 0x9e, + 0x6b, 0xf9, 0x9a, 0xd1, 0x60, 0xb1, 0x2f, 0xec, 0x32, 0xd6, + 0x5f, 0x8b, 0x7f, 0xf2, 0xed, 0x9c, 0xf1, 0x34, 0x81, 0xb2, + 0x71, 0x8a, 0xec, 0x2d, 0x3c, 0x1, 0xa8, 0x39, 0x1b, 0xa3, + 0x5c, 0x7d, 0x4d, 0x74, 0xfa, 0x5f, 0xc3, 0x82, 0xd8, 0xf3, + 0x51, 0x3f, 0x33, 0x5d, 0xb4, 0x32, 0x7c, 0x5d, 0x77, 0xa4, + 0x6c, 0x7a, 0x58, 0x7c, 0x83, 0x1d, 0x88, 0x76, 0xe5, 0x68, + 0xf3, 0x4b, 0x3d, 0x32, 0x4b, 0xd6, 0x1, 0x41, 0xe6, 0xba, + 0x8d, 0x17, 0xe1, 0xf4, 0xf7, 0x32, 0x6, 0xc9, 0xc5, 0x7a, + 0x55, 0x87, 0x81, 0xad, 0xad, 0x8, 0x25, 0x57, 0xf0, 0xae, + 0x82, 0xd2, 0xce, 0x3b, 0x45, 0xc2, 0x2e, 0x2b, 0xea, 0xf0, + 0x7c, 0x37, 0x18, 0xb4, 0xeb, 0x9f, 0x6d, 0x97, 0xf0, 0x8c, + 0x62, 0xd4, 0xb1, 0x46, 0x6, 0x83, 0xe1, 0x18, 0xb4, 0xf8, + 0xd7, 0xcc, 0x5c, 0x9a, 0xe9, 0x63, 0x85, 0x63, 0x18, 0x51, + 0x8f, 0xa5, 0x3e, 0x8a, 0xfb, 0x6a, 0x34, 0x29, 0xd0, 0x8f, + 0x2d, 0x35, 0x63, 0xf4, 0x4c, 0x3e, 0x16, 0x96, 0x1a, 0xa, + 0x14, 0x95, 0x91, 0x14, 0xa7, 0x2, 0xb1, 0xb5, 0x6, 0xe7, + 0xf0, 0xad, 0x6b, 0x86, 0xc0, 0x35, 0x85, 0xa8, 0xbf, 0xf5, + 0xae, 0x83, 0xa8, 0xc5, 0xbc, 0x7e, 0x4d, 0x73, 0x5a, 0x94, + 0x9d, 0x6b, 0x7a, 0xf6, 0x4e, 0xb5, 0xcb, 0xea, 0x52, 0xf5, + 0xa0, 0xe, 0x7f, 0x52, 0x93, 0xad, 0x71, 0xda, 0xc4, 0xbd, + 0x6b, 0xa8, 0xd4, 0xe5, 0xc6, 0xea, 0xe2, 0xf5, 0x79, 0xb3, + 0x9e, 0x68, 0x3, 0x8c, 0xf1, 0x35, 0xcf, 0x95, 0x6b, 0x2b, + 0xf, 0x4a, 0xf9, 0x47, 0xe2, 0x56, 0xa1, 0xba, 0x49, 0xb1, + 0xea, 0x6b, 0xe9, 0x4f, 0x1b, 0xdf, 0x8, 0x6c, 0xdf, 0x9e, + 0xd5, 0xf2, 0x37, 0xc4, 0x2d, 0x47, 0xcc, 0x9e, 0x45, 0xc9, + 0xe4, 0xd7, 0xcd, 0xe6, 0xd5, 0x2d, 0x14, 0x8f, 0x92, 0xcf, + 0x2a, 0xa5, 0x15, 0x13, 0xcd, 0xb5, 0x49, 0x32, 0x58, 0xfa, + 0x9a, 0xe4, 0xb5, 0x29, 0x32, 0x4d, 0x74, 0x5a, 0x94, 0xbd, + 0x6b, 0x95, 0xd4, 0x65, 0xc9, 0x35, 0xe1, 0xe1, 0x62, 0x7c, + 0xde, 0xa, 0x26, 0x4d, 0xcb, 0x75, 0xae, 0xaf, 0xe0, 0x96, + 0x84, 0xde, 0x24, 0xf8, 0xab, 0xe1, 0xeb, 0x4d, 0xa1, 0xa2, + 0x17, 0x4a, 0xf2, 0xf3, 0x8c, 0x20, 0x3c, 0x9a, 0xe4, 0x6e, + 0x1b, 0x93, 0x5e, 0xf9, 0xfb, 0x14, 0x78, 0x62, 0x4d, 0x67, + 0xe2, 0x36, 0xa1, 0xa9, 0x85, 0xd, 0x1d, 0x8d, 0xb0, 0x8c, + 0x82, 0x70, 0x4b, 0x48, 0x78, 0x3f, 0xf8, 0xe1, 0xfc, 0xeb, + 0xe9, 0x30, 0xf1, 0xbc, 0x91, 0xf5, 0xb8, 0x58, 0xde, 0x49, + 0x1f, 0xa8, 0x5f, 0xc, 0x74, 0xf3, 0x63, 0xe1, 0x8b, 0x7c, + 0xf5, 0x90, 0xef, 0xfc, 0xf, 0x4a, 0xed, 0xe1, 0x1c, 0xd6, + 0x4e, 0x89, 0x67, 0xf6, 0x1d, 0x3e, 0xd6, 0xdf, 0x8f, 0xdd, + 0x46, 0xa9, 0xc7, 0xb0, 0x15, 0xb5, 00, 0xe6, 0xbd, 0xc3, + 0xe9, 0xb, 0xb0, 0xae, 0x5, 0x5f, 0x81, 0x72, 0x5, 0x54, + 0x89, 0x6a, 0xf4, 0x2b, 0xd2, 0x80, 0x2f, 0x40, 0x3a, 0x55, + 0xc8, 0x85, 0x56, 0x85, 0x71, 0x8a, 0xb9, 0x8, 0xa0, 0xb, + 0x71, 0xe, 0x5, 0x5b, 0x8c, 0x55, 0x78, 0x85, 0x5a, 0x8c, + 0x50, 0x4, 0xd1, 0x8a, 0x99, 0x6a, 0x34, 0x15, 0x2a, 0xf6, + 0xa0, 0x7, 0x8e, 0xd5, 0x22, 0xf5, 0xa6, 0x2d, 0x3d, 0x7a, + 0x50, 0x4, 0x83, 0xa5, 0x14, 0xa, 0x28, 0x1, 0xcb, 0x4b, + 0x48, 0x3a, 0x52, 0xd0, 0x1, 0x45, 0x14, 0x50, 0x6, 0x5c, + 0x86, 0xab, 0x48, 0x6a, 0xc4, 0x9d, 0x6a, 0xac, 0x94, 0x1, + 0x5e, 0x53, 0x5f, 0x9c, 0xda, 0xc5, 0xdf, 0xfc, 0x2c, 0xbf, + 0xda, 0x33, 0x50, 0xbc, 0x4f, 0xde, 0x5b, 0xc9, 0x7c, 0x16, + 0x20, 0x79, 0xf9, 0x17, 0xb1, 0xc6, 0x47, 0xad, 0x7d, 0xd9, + 0xf1, 0x6b, 0xc4, 0xcb, 0xe0, 0xef, 0x87, 0x7a, 0xf6, 0xb0, + 0xd2, 0xb4, 0x4d, 0x6b, 0x6a, 0xee, 0x85, 0x5b, 0x6b, 0x16, + 0xc7, 0xca, 0x1, 0xf5, 0x27, 0x8a, 0xf8, 0xab, 0xf6, 0x4d, + 0xf0, 0xe3, 0xea, 0xde, 0x30, 0x96, 0xfd, 0xd3, 0x72, 0xc4, + 0x37, 0x12, 0xc3, 0x27, 0x24, 0x8a, 0xf8, 0xcc, 0xf9, 0xfb, + 0x7a, 0xd8, 0x7c, 0x22, 0xea, 0xee, 0xfe, 0x47, 0xe7, 0xfc, + 0x4d, 0x2f, 0xac, 0xe2, 0x30, 0xb8, 0x15, 0xf6, 0xa5, 0x77, + 0xe8, 0x8f, 0xb9, 0xfc, 0x17, 0xa7, 0xad, 0x96, 0x9f, 0x6f, + 0x1a, 0xae, 0xd0, 0x88, 0x6, 0x31, 0xe8, 0x5, 0x77, 0x56, + 0xab, 0x85, 0xcd, 0x73, 0xfa, 0x15, 0xbf, 0x97, 0xa, 0xc, + 0x76, 0xae, 0x96, 0x21, 0x84, 0xaf, 0xb1, 0x8a, 0xe5, 0x49, + 0x1f, 0x7b, 0x8, 0xf2, 0xc5, 0x44, 0xf3, 0xff, 00, 0x8d, + 0xf2, 0xfd, 0x9f, 0xc0, 0xd7, 0xf3, 0x31, 0x21, 0x23, 0x89, + 0x98, 0xe3, 0xd6, 0xbf, 0x9d, 0xcf, 0x8e, 0xba, 0xab, 0xeb, + 0x5f, 0x11, 0x75, 0x5b, 0xa6, 0x24, 0x83, 0x26, 0x1, 0x35, + 0xfd, 0x9, 0x7e, 0xd2, 0x30, 0xdc, 0x5d, 0x7c, 0x2e, 0xd5, + 0x6d, 0xad, 0x43, 0x19, 0xa6, 0x4d, 0xa3, 0x68, 0x24, 0xf5, + 0x1e, 0x95, 0xfc, 0xf9, 0xfc, 0x6f, 0xf0, 0xfc, 0xda, 0x7, + 0x8b, 0xee, 0x6d, 0xa6, 0x3b, 0xa4, 0xc, 0x4b, 0x1c, 0x7d, + 0x2a, 0x8b, 0x3c, 0xdc, 0x70, 0x6b, 0xaf, 0xf0, 0xff, 00, + 0xc4, 0x3b, 0xcd, 0x1, 0x54, 0x40, 0xec, 0x9b, 0x7f, 0xbb, + 0x9f, 0xf1, 0xae, 0x42, 0x8a, 00, 0xef, 0xb5, 0xef, 0x8b, + 0x7a, 0x9e, 0xb9, 0x64, 0xd0, 0x49, 0x73, 0x31, 0xd, 0xd4, + 0x12, 0x71, 0xfc, 0xeb, 0x82, 0x76, 0x2e, 0xc5, 0x8f, 0x24, + 0x9c, 0xd2, 0x51, 0x40, 0x1d, 0xef, 0x82, 0xfe, 0x23, 0x3f, + 0x85, 0xca, 0x79, 0x72, 0x48, 0x9b, 0x7f, 0xbb, 0xff, 00, + 0xeb, 0xaf, 0x4e, 0xb6, 0xfd, 0xa8, 0x6f, 0xa2, 0x1, 0x7e, + 0xdd, 0x70, 00, 0xe3, 0x4, 0x9f, 0xfe, 0x2a, 0xbe, 0x74, + 0xa2, 0x80, 0x3e, 0x9e, 0xb6, 0xfd, 0xab, 0x2f, 0x53, 0x1f, + 0xf1, 0x30, 0xb8, 0x5f, 0xa3, 0x1f, 0xfe, 0x2a, 0xb4, 0xed, + 0xff, 00, 0x6b, 0x5b, 0xd1, 0x8f, 0xf8, 0x9a, 0x5c, 0xaf, + 0xfc, 0xf, 0xff, 00, 0xb2, 0xaf, 0x93, 0xa8, 0xdc, 0x7d, + 0x4d, 00, 0x7d, 0x8f, 0x6b, 0xfb, 0x5d, 0xde, 0x86, 0x4, + 0x6a, 0xd2, 0xe7, 0xfe, 0xba, 0x7f, 0xf6, 0x75, 0xbb, 0xa7, + 0x7e, 0xd7, 0x77, 0xf3, 0xcf, 0x14, 0x6b, 0xab, 0xcf, 0x96, + 0x20, 0x7f, 0xac, 0xff, 00, 0xec, 0xab, 0xe1, 0xcd, 0xec, + 0x3f, 0x88, 0xfe, 0x75, 0xd2, 0x78, 0xe, 0xc2, 0x5d, 0x53, + 0xc4, 0x36, 0xf1, 0x82, 0xcc, 0x1, 0xfa, 0x8a, 00, 0xfd, + 0xb4, 0xfd, 0x8e, 0xfe, 0x22, 0x5e, 0xf8, 0xee, 0xf9, 0xc, + 0xb7, 0x4f, 0x3a, 0x2a, 0x2, 0x77, 0x36, 0x73, 0xd3, 0xdc, + 0xd7, 0xd9, 0xc2, 0xbe, 0x36, 0xff, 00, 0x82, 0x7b, 0x78, + 0x11, 0xb4, 0x4f, 0xa, 0x49, 0x7d, 0x2a, 0x6d, 0x2e, 0x83, + 0xef, 0x2f, 0x3f, 0xfd, 0x6e, 0x95, 0xf6, 0x4d, 00, 0x67, + 0xeb, 0xba, 0xa2, 0x69, 0x1a, 0x6c, 0xd7, 0x2e, 0xdb, 0x42, + 0xf, 0x51, 0x5f, 0xb, 0x7e, 0xd0, 0xbf, 0xb5, 0xa4, 0xbe, + 0x17, 0xd6, 0xd, 0xa5, 0xae, 0xa0, 0xf1, 0x90, 0xf8, 0xf9, + 0x5f, 0xff, 00, 0xb3, 0xaf, 0xa8, 0xbf, 0x68, 0x6f, 0x10, + 0xd, 0x1b, 0xc1, 0xf3, 0x8f, 0x30, 0xa1, 0x2a, 0x5b, 0xe5, + 0x6c, 0x1e, 0x86, 0xbf, 0x6, 0x3f, 0x69, 0x8f, 0x1d, 0x5d, + 0x6b, 0x7f, 0x11, 0xaf, 0x7c, 0xab, 0xb9, 0x8a, 0x46, 0xe7, + 0xee, 0xca, 0x71, 0xf8, 0x73, 0x40, 0x1f, 0x78, 0xd9, 0x7e, + 0xdb, 0x7a, 0x8a, 0xf5, 0xd5, 0x25, 0xff, 00, 0xbe, 0xff, + 00, 0xfb, 0x3a, 0xdd, 0xb4, 0xfd, 0xb8, 0x2f, 0x94, 0x8f, + 0xf8, 0x99, 0xca, 0x7e, 0x92, 0x7f, 0xf6, 0x75, 0xf9, 0x32, + 0x9e, 0x21, 0xd4, 0x53, 0xa5, 0xe4, 0xff, 00, 0xf7, 0xf5, + 0xbf, 0xc6, 0xa7, 0x5f, 0x16, 0xea, 0x89, 0xd2, 0xf2, 0x5f, + 0xfb, 0xf8, 0xdf, 0xe3, 0x40, 0x1f, 0xae, 0xf6, 0x9f, 0xb7, + 0x1d, 0xe7, 00, 0xea, 0x73, 0x7f, 0xdf, 0x63, 0xff, 00, + 0x8b, 0xad, 0x8b, 0x4f, 0xdb, 0x8e, 0xe3, 0x1c, 0xea, 0xe, + 0x7f, 0xe0, 0x43, 0xff, 00, 0x8b, 0xaf, 0xc7, 0x88, 0xfc, + 0x73, 0xab, 0xc6, 0x78, 0xbb, 0x97, 0xfe, 0xfe, 0xb7, 0xf8, + 0xd5, 0x94, 0xf8, 0x8d, 0xac, 0x46, 0x31, 0xf6, 0x87, 0x3f, + 0xf6, 0xd5, 0xbf, 0xc6, 0x80, 0x3f, 0x65, 0xad, 0xff, 00, + 0x6e, 0x6, 0x38, 0xdd, 0x7b, 0x27, 0xe8, 0x7f, 0xf6, 0x7a, + 0xd6, 0xb4, 0xfd, 0xb6, 0xe3, 0x6c, 0x66, 0xeb, 0x3c, 0x7f, + 0x10, 0x1f, 0xfc, 0x5d, 0x7e, 0x2e, 0x47, 0xf1, 0x4f, 0x59, + 0x8f, 0xfe, 0x5b, 0x49, 0xff, 00, 0x7f, 0x9b, 0xfc, 0x6a, + 0xdc, 0x5f, 0x18, 0x75, 0x88, 0xcf, 0xdf, 0x90, 0xff, 00, + 0xdb, 0x66, 0xff, 00, 0x1a, 00, 0xfd, 0xb2, 0xb5, 0xfd, + 0xb4, 0x6c, 0xca, 0x82, 0xd3, 0x29, 0xff, 00, 0xbe, 0x7f, + 0xf8, 0xba, 0xd6, 0xb5, 0xfd, 0xb2, 0x74, 0xc7, 0x3, 0x74, + 0xb1, 0xf3, 0xeb, 0xb4, 0x7f, 0xec, 0xf5, 0xf8, 0x89, 0xf, + 0xc6, 0xfd, 0x5a, 0x30, 0x32, 0x66, 0x3f, 0x49, 0x9b, 0xfc, + 0x6a, 0xec, 0x3f, 0x1f, 0x35, 0x48, 0xcf, 0x26, 0x73, 0xff, + 00, 0x6d, 0xda, 0x80, 0x3f, 0x70, 0xed, 0xbf, 0x6b, 0xbd, + 0x22, 0x4f, 0xbc, 0xf1, 0xfe, 0x6b, 0xff, 00, 0xc5, 0xd6, + 0x9d, 0xbf, 0xed, 0x5d, 0xa1, 0x49, 0xf7, 0x9d, 0x7f, 0x35, + 0xff, 00, 0xe2, 0xeb, 0xf0, 0xde, 0x1f, 0xda, 0x23, 0x51, + 0x8c, 0xf3, 0xf6, 0x8f, 0xc2, 0x73, 0xfe, 0x35, 0x7a, 0x1f, + 0xda, 0x4a, 0xf9, 0x47, 0x2f, 0x74, 0x3f, 0xed, 0xb1, 0xff, + 00, 0x1a, 00, 0xfd, 0xcc, 0xb7, 0xfd, 0xa7, 0x7c, 0x3d, + 0x2e, 0x9, 0x75, 0xfc, 0x19, 0x3f, 0xf8, 0xba, 0xd1, 0x87, + 0xf6, 0x8b, 0xf0, 0xd4, 0xa4, 0x66, 0x42, 0x33, 0xfe, 0xd2, + 0x7f, 0xf1, 0x55, 0xf8, 0x67, 0x7, 0xed, 0x39, 0x76, 0xa1, + 0x73, 0x25, 0xc0, 0xff, 00, 0xb6, 0xe7, 0xfc, 0x6b, 0x46, + 0xdb, 0xf6, 0xa6, 0x9d, 0x59, 0x77, 0x4f, 0x72, 0xa3, 0xfe, + 0xbe, 0xf, 0xf8, 0xd0, 0x7, 0xee, 0x5c, 0x1f, 0x1d, 0xbc, + 0x37, 0x2e, 0x3f, 0x7f, 0xd7, 0xfd, 0xb4, 0xff, 00, 0xe2, + 0xaa, 0xec, 0x5f, 0x19, 0xbc, 0x39, 0x20, 0xcf, 0xda, 0x31, + 0xff, 00, 0x2, 0x4f, 0xf1, 0xaf, 0xc3, 0xcb, 0x7f, 0xda, + 0xba, 0x54, 0xe7, 0xed, 0x93, 0xf, 0xad, 0xc1, 0xff, 00, + 0x1a, 0xd2, 0xb7, 0xfd, 0xad, 0xdd, 0x71, 0xfe, 0x9f, 0x38, + 0x3f, 0xf5, 0xf4, 0x7f, 0xc6, 0x80, 0x3f, 0x6e, 0xa2, 0xf8, + 0xaf, 0xe1, 0xf9, 0x7a, 0x5d, 0x1, 0xf5, 0x65, 0xff, 00, + 0x1a, 0xb9, 0x17, 0xc4, 0x5d, 0xe, 0x53, 0xc5, 0xe4, 0x7f, + 0xf7, 0xda, 0xff, 00, 0x8d, 0x7e, 0x25, 0x5b, 0x7e, 0xd7, + 0xae, 0x98, 0xff, 00, 0x89, 0x8c, 0xff, 00, 0x8d, 0xd1, + 0xff, 00, 0x1a, 0xd5, 0xb6, 0xfd, 0xb1, 0x48, 0x23, 0x3a, + 0x9c, 0x83, 0xfe, 0xde, 0xcf, 0xf8, 0xd0, 0x7, 0xed, 0x4a, + 0x78, 0xd7, 0x47, 0x7e, 0x97, 0x91, 0x7f, 0xdf, 0xc5, 0xff, + 00, 0x1a, 0xb3, 0x1f, 0x89, 0xb4, 0xc9, 0x7e, 0xed, 0xe4, + 0x27, 0xfe, 0xda, 0x2f, 0xf8, 0xd7, 0xe3, 0x1d, 0xa7, 0xed, + 0x96, 0xca, 0x72, 0x35, 0x49, 0x7f, 0xf0, 0x2c, 0xff, 00, + 0xf1, 0x55, 0xb1, 0x69, 0xfb, 0x68, 0xb0, 0xff, 00, 0x98, + 0x9b, 0xff, 00, 0xe0, 0x51, 0xff, 00, 0xe2, 0xa8, 0x3, + 0xf6, 0x2d, 0x35, 0x9b, 0x27, 0xe9, 0x73, 0xf, 0xfd, 0xfc, + 0x1f, 0xe3, 0x52, 0xad, 0xfd, 0xb3, 0xf4, 0x9e, 0x3f, 0xfb, + 0xec, 0x57, 0xe4, 0x4d, 0xa7, 0xed, 0xaa, 0xc0, 0x8f, 0xf8, + 0x99, 0x4b, 0xff, 00, 0x81, 0x67, 0xff, 00, 0x8a, 0xad, + 0x9b, 0x4f, 0xdb, 0x71, 0xd7, 0xfe, 0x62, 0x4f, 0x8f, 0x7b, + 0xa3, 0xfe, 0x34, 0x1, 0xfa, 0xc2, 0x2e, 0x22, 0x23, 0x89, + 0x10, 0xff, 00, 0xc0, 0x85, 0x38, 0x48, 0xa7, 0xa3, 0x3, + 0xf4, 0x35, 0xf9, 0x67, 0x6b, 0xfb, 0x70, 0x9c, 0x1, 0xf6, + 0xf7, 0xfc, 0x2f, 0xf, 0xf8, 0xd6, 0xcd, 0xa7, 0xed, 0xc6, + 0x1, 0x1f, 0xe9, 0xf2, 0x7e, 0x37, 0x47, 0xfc, 0x68, 0x3, + 0xf4, 0xd3, 0x34, 0x66, 0xbf, 0x39, 0x2d, 0x7f, 0x6e, 0x74, + 0x7, 0x9b, 0xd7, 0x3f, 0xf6, 0xf5, 0xff, 00, 0xd7, 0xad, + 0xab, 0x2f, 0xdb, 0xa6, 0xd, 0xa3, 0x75, 0xe3, 0xf5, 0xfe, + 0x2b, 0x9f, 0xfe, 0xbd, 00, 0x7e, 0x80, 0xe6, 0x8c, 0xd7, + 0xc3, 0x16, 0xdf, 0xb7, 0x45, 0x9f, 0x19, 0xba, 0xcf, 0xfd, + 0xbc, 0x7f, 0xf5, 0xeb, 0x62, 0xd3, 0xf6, 0xe4, 0xd3, 0x9b, + 0x1b, 0xa7, 0x1f, 0x8c, 0xe3, 0xfc, 0x68, 0x3, 0xec, 0xfa, + 0x33, 0x5f, 0x23, 0x5a, 0xfe, 0xdb, 0xfa, 0x43, 0x81, 0xba, + 0x58, 0xcf, 0xfd, 0xb6, 0x1f, 0xe3, 0x5a, 0xd6, 0xff, 00, + 0xb6, 0xae, 0x84, 0xf8, 0xcc, 0x91, 0x1f, 0xfb, 0x6c, 0xb4, + 0x1, 0xf5, 0x25, 0x15, 0xf3, 0x7d, 0xb7, 0xed, 0x95, 0xe1, + 0xb7, 0x20, 0x34, 0x90, 0x8f, 0xac, 0xcb, 0x5a, 0x96, 0xff, + 00, 0xb5, 0xdf, 0x85, 0xa5, 0x3, 0x32, 0xc4, 0x3e, 0x93, + 0xad, 00, 0x7b, 0xe5, 0x15, 0xe2, 0xb0, 0x7e, 0xd5, 0x3e, + 0x13, 0x97, 0x19, 0xb8, 0x45, 0xcf, 0xfd, 0x36, 0x4f, 0xf1, + 0xab, 0xf0, 0xfe, 0xd2, 0xfe, 0x11, 0x94, 0x81, 0xf6, 0xb8, + 0xc7, 0xfd, 0xb6, 0x4f, 0xf1, 0xa0, 0xf, 0x5b, 0xa2, 0xbc, + 0xca, 0x2f, 0xda, 0x13, 0xc2, 0x32, 0xe3, 0xfd, 0x39, 0x7, + 0xfd, 0xb4, 0x4f, 0xf1, 0xab, 0xb1, 0x7c, 0x71, 0xf0, 0x9c, + 0xbd, 0x35, 0x28, 0x87, 0xfc, 0xd, 0x7f, 0xc6, 0x80, 0x3d, + 0x2, 0x8a, 0xe2, 0xe2, 0xf8, 0xbd, 0xe1, 0x79, 0xba, 0x6a, + 0x70, 0x8f, 0xab, 0xaf, 0xf8, 0xd5, 0xb8, 0xfe, 0x26, 0x78, + 0x6a, 0x51, 0xc6, 0xad, 0x6e, 0x3e, 0xb2, 0xf, 0xf1, 0xa0, + 0xe, 0xa6, 0x8a, 0xe7, 0xe3, 0xf1, 0xee, 0x81, 0x27, 0xdd, + 0xd5, 0x6d, 0x4f, 0xfd, 0xb4, 0x1f, 0xe3, 0x56, 0x17, 0xc5, + 0xfa, 0x2b, 0xf4, 0xd4, 0xed, 0x8f, 0xfd, 0xb4, 0x14, 0x1, + 0xb1, 0x45, 0x66, 0xaf, 0x89, 0x34, 0xa7, 0xfb, 0xba, 0x8d, + 0xb1, 0xff, 00, 0xb6, 0xa2, 0xa5, 0x5d, 0x66, 0xc5, 0x87, + 0x17, 0x90, 0x1f, 0xa4, 0x82, 0x80, 0x2e, 0xd1, 0x55, 0x86, + 0xa1, 0x6c, 0xdd, 0x2e, 0x22, 0x3f, 0x47, 0x15, 0x22, 0xdc, + 0xc4, 0xdd, 0x25, 0x46, 0xfa, 0x30, 0xa0, 0x9, 0x68, 0xa6, + 0x9, 0x50, 0xf4, 0x60, 0x7f, 0x1a, 0x70, 0x60, 0x7a, 0x1a, + 00, 0x5a, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, + 0x28, 0xa2, 0x80, 0x10, 0x52, 0xd1, 0x45, 00, 0x21, 0xa2, + 0x96, 0x8a, 00, 0x29, 0x3f, 0x1a, 0x5a, 0x28, 0x1, 0x31, + 0x40, 0x18, 0xa5, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, + 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x28, 0xa2, + 0x80, 0xa, 0x28, 0xa2, 0x80, 0xa, 0x4c, 0x52, 0xd1, 0x40, + 0x9, 0x8a, 0x6b, 0x44, 0xad, 0xd4, 0xa, 0x7d, 0x14, 0x1, + 0x3, 0xd9, 0xc6, 0xfd, 0x56, 0xaa, 0x4b, 0xa2, 0xc1, 0x26, + 0x72, 0xa2, 0xb4, 0xa8, 0xac, 0xe5, 0x4e, 0x12, 0xdd, 0x19, + 0x4a, 0x94, 0x27, 0xf1, 0x23, 0x1c, 0xf8, 0x7a, 0x3, 0xfc, + 0x23, 0xf2, 0xa5, 0x5d, 0x2, 0x15, 0x39, 0xa, 0x3f, 0x2a, + 0xd6, 0xc5, 0x18, 0xac, 0xfe, 0xaf, 0x4f, 0xb1, 0x8f, 0xd5, + 0x68, 0xff, 00, 0x29, 0x45, 0x34, 0xa8, 0x93, 0xf8, 0x47, + 0xe5, 0x52, 0xa6, 0x9f, 0xa, 0xff, 00, 0xcb, 0x35, 0xfc, + 0xaa, 0xce, 0x29, 0x6b, 0x45, 0x4e, 0x2b, 0xa1, 0xb2, 0xa5, + 0x5, 0xb2, 0x23, 0x5b, 0x78, 0x97, 0xa4, 0x6a, 0x3f, 0xa, + 0x78, 0x50, 0xbd, 00, 0x1f, 0x4a, 0x5a, 0x2a, 0xec, 0x69, + 0x64, 0x84, 0xa2, 0x96, 0x8a, 0x63, 0xa, 0x28, 0xa4, 0x63, + 0x80, 0x68, 0x2, 0x9d, 0xd3, 0x70, 0x79, 0xae, 0x7f, 0x51, + 0x7a, 0xda, 0xbc, 0x6e, 0x2b, 0x9e, 0xd4, 0x1e, 0x80, 0x31, + 0x6f, 0x9f, 0x83, 0x5c, 0xae, 0xa5, 0x27, 0x5a, 0xe8, 0xb5, + 0x19, 0x38, 0x35, 0xca, 0x6a, 0x32, 0x75, 0xa0, 0xe, 0x7b, + 0x54, 0x93, 00, 0xd7, 0x13, 0xab, 0xc9, 0xd6, 0xba, 0xbd, + 0x5a, 0x5c, 0x3, 0x5c, 0x46, 0xb1, 0x2e, 0x33, 0x40, 0x1e, + 0x57, 0xf1, 0x22, 0xf7, 0x64, 0x2e, 0xb9, 0xed, 0x5f, 0x24, + 0xf8, 0xd2, 0xe7, 0xcd, 0xbc, 0x71, 0x9c, 0xf3, 0x5f, 0x49, + 0x7c, 0x4d, 0xbf, 0x4, 0xcb, 0x86, 0xe3, 0xeb, 0x5f, 0x2c, + 0xf8, 0x92, 0xe3, 0xcc, 0xbc, 0x90, 0xe7, 0xbd, 0x7c, 0x56, + 0x69, 0x3e, 0x6a, 0x89, 0x23, 0xf3, 0xcc, 0xea, 0xa7, 0x3d, + 0x44, 0x8e, 0x4b, 0x52, 0x7e, 0xd, 0x72, 0xf7, 0xad, 0x96, + 0x35, 0xbf, 0xa9, 0xc9, 0xc3, 0x57, 0x35, 0x74, 0xf9, 0x26, + 0xa7, 0xd, 0x1d, 0x9, 0xc1, 0xc7, 0x43, 0x3e, 0x76, 0xeb, + 0x5f, 0x73, 0xff, 00, 0xc1, 0x3e, 0xfc, 0x19, 0x9d, 0x25, + 0xb5, 0x27, 0x41, 0xba, 0xf6, 0xec, 0x2, 0x71, 0xd6, 0x34, + 0xe9, 0xce, 0x3f, 0xda, 0x35, 0xf0, 0xad, 0xc1, 0xeb, 0x5f, + 0xaa, 0x3f, 0xb1, 0x6f, 0x84, 0x3f, 0xb0, 0x3c, 0xb, 0xa3, + 0xc4, 0xe3, 0x32, 0x41, 0x6b, 0xb9, 0xce, 0x31, 0x96, 0x76, + 0x38, 0x3f, 0x96, 0x2b, 0xe8, 0xf0, 0xab, 0x5b, 0x9f, 0x59, + 0x82, 0x8d, 0xe5, 0x73, 0xea, 0x38, 0x17, 0xa7, 0xb7, 0x15, + 0xa1, 0x6e, 0x7, 0x15, 0x4a, 0x5, 0xe9, 0x5a, 0x56, 0xe3, + 0x81, 0xc5, 0x7a, 0x87, 0xb2, 0x5c, 0x85, 0x79, 0xab, 0xf0, + 0x2f, 0x4a, 0xa7, 0x8, 0xe6, 0xaf, 0xdb, 0xaf, 0x2, 0x80, + 0x2e, 0xc4, 0x3a, 0x55, 0xc8, 0x47, 0x22, 0xab, 0x44, 0xb5, + 0x72, 0x11, 0x40, 0x16, 0xa3, 0x15, 0x66, 0x31, 0xc8, 0xa8, + 0x22, 0x1d, 0x2a, 0xcc, 0x74, 0x1, 0x3a, 0x8e, 0x2a, 0x45, + 0xa6, 0x28, 0xc1, 0xa9, 0x16, 0x80, 0x1c, 0xb5, 0x22, 0x8e, + 0x29, 0x8b, 0x52, 0x2f, 0x5a, 00, 0x75, 0x14, 0x50, 0x28, + 0x1, 0xc3, 0x8a, 0x5a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0xc, 0x89, 0xd, 0x56, 0x91, 0xaa, 0x79, 0xd, 0x55, 0x90, + 0xe6, 0x80, 0x3e, 0x72, 0xfd, 0xb7, 0x7c, 0x58, 0xda, 0x37, + 0xc2, 0xe8, 0x74, 0x88, 0xe5, 0x54, 0x93, 0x57, 0xb8, 0x11, + 0x8c, 0x83, 0xb8, 0x84, 0x65, 0x66, 0x3, 0xb7, 0x4e, 0xb9, + 0xae, 0x7f, 0xf6, 0x40, 0xf0, 0xb7, 0xd8, 0xbc, 0x3b, 0x25, + 0xf3, 0x46, 0x43, 0x4c, 0xc0, 0x6, 0x3d, 0xc5, 0x70, 0xdf, + 0xb6, 0xd6, 0xb6, 0x35, 0xbf, 0x89, 0xba, 0x36, 0x89, 0xf, + 0xce, 0x6c, 0x2d, 0xf2, 0xe0, 0x8e, 0x3, 0xbe, 0xf, 0xfe, + 0x82, 0x45, 0x7d, 0x23, 0xf0, 0x37, 0xc3, 0xa3, 0x44, 0xf0, + 0x86, 0x9d, 00, 0x50, 0xa4, 0x46, 0xa4, 0xfd, 0x6b, 0xe2, + 0xa9, 0x7f, 0xb5, 0x67, 0x73, 0x93, 0xda, 0x9a, 0xb1, 0xf9, + 0xed, 0x1f, 0xf6, 0xee, 0x22, 0xa9, 0x37, 0xb5, 0x25, 0x6f, + 0x9b, 0x3d, 0x7f, 0x4c, 0x8b, 0x6c, 0x6a, 0x2b, 0x60, 0xc, + 0xa, 0xa1, 0x63, 0x1e, 00, 0xf6, 0xad, 0xa, 0xfb, 0x53, + 0xf4, 0x23, 0xb, 0xc6, 0x5a, 0x22, 0xeb, 0xba, 0x1d, 0xc5, + 0xb9, 0x1b, 0x89, 0x43, 0x81, 0x5f, 0x8f, 0x3f, 0xb6, 0x37, + 0xec, 0xec, 0xda, 0x3e, 0xb5, 0x73, 0x77, 0x67, 0x61, 0x2c, + 0xf3, 0x48, 0xc7, 0x24, 0x30, 0xe3, 0xa7, 0xbd, 0x7e, 0xd1, + 0x32, 0x86, 0x4, 0x11, 0x90, 0x6b, 0x8a, 0xf1, 0x87, 0xc2, + 0x9d, 0x7, 0xc5, 0x50, 0x48, 0x6e, 0xac, 0xc4, 0x92, 0x63, + 0x8f, 0x9d, 0x87, 0xf2, 0x34, 0x1, 0xfc, 0xda, 0x6a, 0x9e, + 00, 0xd7, 0x2d, 0x2e, 0x1c, 0x1d, 0x3a, 0x44, 0x50, 0x71, + 0x92, 0x47, 0xf8, 0xd6, 0x54, 0xde, 0x1c, 0xd4, 0xad, 0xc6, + 0x64, 0xb4, 0x75, 0x1e, 0xf8, 0xaf, 0xdb, 0xef, 0x88, 0x9f, + 0xb2, 0x65, 0x96, 0xa1, 0x73, 0x21, 0xb4, 0xb0, 0x50, 0xe, + 0x4e, 0x37, 0x1f, 0xfe, 0x2a, 0xbe, 0x59, 0xf8, 0xe7, 0xfb, + 0x34, 0x8f, 0x7, 0xe8, 0x17, 0x97, 0xaf, 0x6a, 0x91, 0xa2, + 0x21, 0x39, 0xc9, 0xf4, 0x3f, 0xed, 0x7b, 0x50, 0x7, 0xe6, + 0xbc, 0x91, 0xb4, 0x4c, 0x55, 0x86, 0x8, 0xed, 0x42, 0xc6, + 0xcf, 0xd0, 0x66, 0xaf, 0xf8, 0x80, 0x8f, 0xed, 0x7b, 0x95, + 0x5f, 0xba, 0xb2, 0x30, 0x1c, 0xfb, 0xd7, 0xa9, 0xfc, 0x16, + 0xf8, 0x47, 0x7b, 0xe3, 0x85, 0x49, 0x21, 0x80, 0x4a, 0x8c, + 0x78, 0xc9, 0xc6, 0x7a, 0xfb, 0xd0, 0x7, 0x8f, 0x79, 0x2e, + 0x7, 0xdd, 0x34, 0xd2, 0xa4, 0x76, 0xaf, 0xbe, 0xe0, 0xfd, + 0x8e, 0x6f, 0xcd, 0x94, 0x6c, 0x74, 0xf4, 0xc9, 00, 0xfd, + 0xfc, 0xff, 00, 0xec, 0xd5, 0x9d, 0x77, 0xfb, 0x1f, 0x5e, + 0xc, 0xff, 00, 0xa0, 0x27, 0xe2, 0xdf, 0xfd, 0x95, 00, + 0x7c, 0x29, 0x45, 0x7d, 0xab, 0x71, 0xfb, 0x21, 0x5d, 0xae, + 0x7f, 0xe2, 0x5e, 0x87, 0xe8, 0xdf, 0xfd, 0x95, 0x64, 0xdd, + 0x7e, 0xc9, 0x37, 0x6b, 0xd6, 0xc5, 0x47, 0xe3, 0xff, 00, + 0xd9, 0x50, 0x7, 0xc8, 0x15, 0xeb, 0x7f, 0xb3, 0xf6, 0x87, + 0xfd, 0xa7, 0xe2, 0x38, 0x49, 0x5d, 0xd9, 0x90, 0x1, 0x5e, + 0x9f, 0x71, 0xfb, 0x27, 0x5d, 0xa9, 0xff, 00, 0x8f, 0x18, + 0xff, 00, 0xef, 0xaf, 0xfe, 0xca, 0xbd, 0xd7, 0xf6, 0x63, + 0xfd, 0x95, 0xe7, 0xb4, 0xf1, 0x5, 0x8c, 0x8f, 0x6c, 0xa8, + 0x4, 0x9b, 0x89, 0xdd, 0xd3, 0x93, 0xfe, 0xd5, 00, 0x7e, + 0x97, 0xfe, 0xcd, 0x3e, 0x18, 0x5f, 0xe, 0x7c, 0x35, 0xb1, + 0x51, 0x19, 0x8d, 0xa4, 0x50, 0xc4, 0x1e, 0xa7, 0x8e, 0xf5, + 0xeb, 0x27, 0xa5, 0x66, 0x78, 0x67, 0x49, 0x4d, 0xf, 0x43, + 0xb4, 0xb2, 0x45, 0xda, 0x22, 0x40, 0xb8, 0xad, 0x27, 0x3b, + 0x54, 0x9f, 0x41, 0x40, 0x1f, 0x26, 0x7e, 0xdb, 0x7e, 0x33, + 0x5d, 0x1f, 0xc3, 0x37, 0x88, 0x25, 0xb, 0xb6, 0x12, 0x30, + 0x3f, 0x1a, 0xfc, 0x29, 0xf1, 0xae, 0xaa, 0xda, 0xcf, 0x89, + 0xb5, 0xb, 0xa6, 0x70, 0xe5, 0xe4, 0x38, 0x23, 0xa1, 0xe7, + 0xb5, 0x7e, 0xbd, 0x7e, 0xdf, 0x50, 0x5f, 0x6a, 0xda, 0x5d, + 0xe4, 0x30, 0x37, 0xdf, 0xc, 0x36, 0xfe, 0x75, 0xf9, 0x6f, + 0x73, 0xf0, 0x47, 0x59, 0x2c, 0xce, 0xc0, 0x64, 0xf2, 0x4e, + 0x47, 0xf8, 0xd0, 0x7, 0x98, 0x51, 0x5e, 0x81, 0x37, 0xc1, + 0x9d, 0x6a, 0x3e, 0x8a, 0xf, 0xe2, 0x3f, 0xc6, 0xaa, 0x3f, + 0xc2, 0x6d, 0x6d, 0x3f, 0xe5, 0x9a, 0xff, 00, 0xdf, 0x42, + 0x80, 0x38, 0xaa, 0x2b, 0xac, 0x93, 0xe1, 0x96, 0xb7, 0x1f, + 0x58, 0x57, 0xfe, 0xfa, 0x15, 0x5d, 0xfe, 0x1f, 0x6b, 0x28, + 0x70, 0x6d, 0xc7, 0xfd, 0xf4, 0x28, 0x3, 0x9b, 0xa2, 0xb7, + 0x1f, 0xc1, 0x5a, 0xb2, 0x75, 0xb6, 0xff, 00, 0xc7, 0x85, + 0x42, 0xde, 0x15, 0xd4, 0xd3, 0xad, 0xb1, 0xfc, 0xc5, 00, + 0x64, 0xd1, 0x5a, 0xf, 0xa0, 0x5f, 0xa1, 0xe6, 0xdd, 0xbf, + 0x30, 0x6a, 0x26, 0xd2, 0xae, 0xd7, 0xac, 0xd, 0x40, 0x15, + 0x28, 0xa9, 0xda, 0xc2, 0xe1, 0x7a, 0xc2, 0xc3, 0xf0, 0xa8, + 0xcd, 0xbc, 0xa3, 0xac, 0x6e, 0x3f, 0xe0, 0x26, 0x80, 0x19, + 0x45, 0x3b, 0xca, 0x7f, 0xee, 0x37, 0xe5, 0x49, 0xb4, 0x8e, + 0xc7, 0xf2, 0xa0, 0x4, 0xa2, 0x8c, 0x71, 0x46, 0x3d, 0xe8, + 0x1, 0x77, 0x1f, 0x53, 0xf9, 0xd1, 0xbd, 0xbf, 0xbc, 0x7f, + 0x3a, 0x4a, 0x28, 0x1, 0xe2, 0x79, 0x7, 0x49, 0x1c, 0x7f, + 0xc0, 0x8d, 0x3d, 0x6f, 0x27, 0x5e, 0x93, 0x38, 0xff, 00, + 0x81, 0x54, 0x34, 0x50, 0x5, 0x95, 0xd4, 0xee, 0xd3, 0xa5, + 0xc4, 0x83, 0xfe, 0x5, 0x52, 0xae, 0xb9, 0x7e, 0xa3, 0x2, + 0xea, 0x4f, 0xce, 0xa8, 0xd1, 0x40, 0x1a, 0x6b, 0xe2, 0x5d, + 0x4d, 0x3a, 0x5d, 0xc9, 0xf9, 0xd4, 0xc9, 0xe3, 0xd, 0x5e, + 0x3e, 0x97, 0x8f, 0xf8, 0xd6, 0x35, 0x14, 0x1, 0xd0, 0x27, + 0x8e, 0xf5, 0x94, 0xff, 00, 0x97, 0xb2, 0x7f, 0xa, 0xb3, + 0x17, 0xc4, 0x9d, 0x72, 0x2c, 0x62, 0xec, 0x90, 0x3d, 0xab, + 0x96, 0xa2, 0x80, 0x3b, 0x28, 0xfe, 0x2b, 0x6b, 0xb1, 0x9f, + 0xf8, 0xf9, 0xcf, 0xfc, 0x7, 0xff, 00, 0xaf, 0x57, 0x22, + 0xf8, 0xc7, 0xae, 0x46, 0x3f, 0xd7, 0x9f, 0xcb, 0xff, 00, + 0xaf, 0x5c, 0xd, 0x14, 0x1, 0xe9, 0x51, 0xfc, 0x6f, 0xd6, + 0xd0, 0xf, 0xdf, 0xff, 00, 0xe3, 0xb5, 0x6e, 0x1f, 0x8f, + 0x7a, 0xc4, 0x67, 0x99, 0x4f, 0xe0, 0x2b, 0xca, 0xa8, 0xa0, + 0xf, 0x64, 0x87, 0xf6, 0x87, 0xd5, 0x53, 0x19, 0x9c, 0x8f, + 0xaa, 0x9a, 0xd2, 0x87, 0xf6, 0x91, 0xd4, 0x53, 00, 0xdc, + 0x63, 0xe8, 0xd, 0x78, 0x4d, 0x14, 0x1, 0xf4, 0x3d, 0xbf, + 0xed, 0x39, 0x7c, 0x98, 0xcd, 0xe9, 0x5c, 0x7f, 0xb2, 0x7f, + 0xc2, 0xb4, 0x20, 0xfd, 0xa8, 0xef, 0x14, 0xf3, 0x7e, 0x3f, + 0x22, 0x2b, 0xe6, 0x8a, 0x28, 0x3, 0xea, 0xab, 0x6f, 0xda, + 0xae, 0xe5, 0x40, 0x1f, 0xda, 0x58, 0x3f, 0xf0, 0x2a, 0xd5, + 0xb6, 0xfd, 0xac, 0xee, 0x86, 0x3f, 0xe2, 0x68, 0x9f, 0x91, + 0xaf, 0x90, 0x28, 0xa0, 0xf, 0xb5, 0x6d, 0x3f, 0x6b, 0x8b, + 0xa4, 0x39, 0xfe, 0xd5, 0x5f, 0xc3, 0x35, 0xb1, 0x6d, 0xfb, + 0x5f, 0x5d, 0xa8, 00, 0x6a, 0xe8, 0x7f, 0x3, 0xfe, 0x15, + 0xf0, 0x90, 0x38, 0xa5, 0xe, 0xc3, 0xa1, 0xa0, 0xf, 0xd0, + 0x3b, 0x5f, 0xdb, 0xe, 0xf4, 0x63, 0xfe, 0x26, 0xa9, 0xf8, + 0x3, 0xfe, 0x15, 0xb1, 0x6b, 0xfb, 0x64, 0xdf, 0x29, 0xe3, + 0x56, 0x4f, 0xc5, 0x49, 0xfe, 0x95, 0xf9, 0xcc, 0x25, 0x61, + 0xd0, 0xfe, 0x95, 0x22, 0xde, 0xcc, 0x9f, 0x75, 0xf1, 0xf8, + 0xa, 00, 0xfd, 0x2b, 0xb5, 0xfd, 0xb3, 0xaf, 0xd7, 0x9f, + 0xed, 0x58, 0xbf, 0x23, 0x5b, 0x36, 0x9f, 0xb6, 0x9d, 0xf2, + 0xff, 00, 0xcc, 0x55, 0x7, 0xe0, 0x7f, 0xc2, 0xbf, 0x2f, + 0xd7, 0x56, 0xba, 0x5e, 0x92, 0xfe, 0x82, 0xa6, 0x4f, 0x10, + 0x5f, 0x47, 0xf7, 0x67, 0xc7, 0xe0, 0x28, 0x3, 0xf5, 0x5a, + 0xd3, 0xf6, 0xd9, 0xbd, 0x18, 0xce, 0xa9, 0x11, 0xfc, 0xd, + 0x6c, 0x5a, 0x7e, 0xdb, 0xb7, 0x8a, 0x3f, 0xe4, 0x23, 0x1f, + 0xe4, 0x7f, 0xc2, 0xbf, 0x25, 0xd3, 0xc5, 0x7a, 0x9c, 0x7d, + 0x27, 0xff, 00, 0xc7, 0x45, 0x58, 0x4f, 0x1c, 0x6a, 0xc9, + 0xd2, 0x7e, 0x3f, 0xdd, 0x1f, 0xe1, 0x40, 0x1f, 0xaf, 0x36, + 0x9f, 0xb7, 0xd, 0xc8, 0xb, 0x9d, 0x4a, 0x23, 0xed, 0xb4, + 0xff, 00, 0x85, 0x6d, 0xda, 0xfe, 0xdb, 0xf3, 0x1c, 0x67, + 0x50, 0x84, 0xfd, 0x10, 0xff, 00, 0x85, 0x7e, 0x38, 0xaf, + 0xc4, 0x2d, 0x61, 0x31, 0x89, 0x87, 0xfd, 0xf2, 0x3f, 0xc2, + 0xac, 0xc7, 0xf1, 0x3b, 0x59, 0x4f, 0xf9, 0x68, 0xf, 0xe0, + 0x3f, 0xc2, 0x80, 0x3f, 0x67, 0x6d, 0xbf, 0x6d, 0xdf, 0x5d, + 0x46, 0xc, 0x7b, 0xc6, 0x7f, 0xc2, 0xb5, 0xac, 0xff, 00, + 0x6d, 0x98, 0x58, 0x82, 0xf7, 0xb6, 0xc7, 0xdb, 0xcb, 0x3f, + 0xe1, 0x5f, 0x8a, 0xf1, 0x7c, 0x5c, 0xd6, 0x63, 0x1f, 0xeb, + 0x7, 0xe4, 0x3f, 0xc2, 0xad, 0x43, 0xf1, 0x9f, 0x57, 0x8c, + 0x8c, 0xb6, 0x7f, 0x2f, 0xfe, 0x26, 0x80, 0x3f, 0x6e, 0x6d, + 0x7f, 0x6c, 0xfb, 0x17, 0xfb, 0xd7, 0x76, 0xbf, 0xf7, 0xc3, + 0x7f, 0x85, 0x69, 0xdb, 0x7e, 0xd8, 0x9a, 0x5c, 0x9f, 0x7a, + 0xea, 0xd0, 0x8f, 0xf7, 0x5b, 0xfc, 0x2b, 0xf1, 0x12, 0x1f, + 0x8e, 0xba, 0xaa, 0x1, 0x97, 0x23, 0xf0, 0x1f, 0xfc, 0x4d, + 0x5c, 0x87, 0xf6, 0x80, 0xd4, 0x10, 0x60, 0xb1, 0xfc, 0x87, + 0xff, 00, 0x13, 0x40, 0x1f, 0xb8, 0x56, 0xdf, 0xb5, 0xb6, + 0x8b, 0x20, 0x1b, 0xae, 0x2d, 0x87, 0xe0, 0xdf, 0xe1, 0x5a, + 0x70, 0x7e, 0xd4, 0xde, 0x1f, 0x97, 0x19, 0xb9, 0xb7, 0xff, + 00, 0xc7, 0xbf, 0xc2, 0xbf, 0xe, 0x6d, 0xff, 00, 0x68, + 0x9b, 0xd4, 0xff, 00, 0x96, 0x8e, 0xb8, 0xff, 00, 0x64, + 0x1f, 0xfd, 0x96, 0xaf, 0xc5, 0xfb, 0x4b, 0x5c, 0xc6, 0x79, + 0x99, 0xff, 00, 0xef, 0x81, 0xff, 00, 0xc4, 0xd0, 0x7, + 0xee, 0x54, 0x1f, 0xb4, 0x97, 0x87, 0x25, 0xeb, 0x73, 0xf, + 0xd4, 0x16, 0xff, 00, 0xa, 0xd0, 0xb7, 0xfd, 0xa0, 0x7c, + 0x33, 0x30, 0xff, 00, 0x8f, 0xc8, 0x87, 0x3f, 0xed, 0x7f, + 0x85, 0x7e, 0x1a, 0xdb, 0xfe, 0xd3, 0xd3, 0x27, 0x59, 0x98, + 0x1f, 0x5d, 0x9f, 0xfd, 0x8d, 0x69, 0xdb, 0x7e, 0xd5, 0x12, + 0xa6, 0x7, 0xda, 0x9c, 0x7f, 0xdb, 0x2c, 0xff, 00, 0xec, + 0xb4, 0x1, 0xfb, 0x8f, 0xf, 0xc6, 0xcf, 0xc, 0xcb, 0xff, + 00, 0x2f, 0xf1, 0x73, 0xfe, 0xf7, 0xf8, 0x55, 0xc8, 0xbe, + 0x2d, 0xf8, 0x6a, 0x5f, 0xf9, 0x89, 0x46, 0x3f, 0x6, 0xff, + 00, 0xa, 0xfc, 0x41, 0xb6, 0xfd, 0xab, 0xe4, 0x5f, 0xf9, + 0x7a, 0x7f, 0xfb, 0xf7, 0xff, 00, 0xd8, 0x56, 0xbd, 0xb7, + 0xed, 0x6f, 0x2a, 0xe3, 0xfd, 0x39, 0xc7, 0xfd, 0xb3, 0xff, + 00, 0xec, 0x68, 0x3, 0xf6, 0xca, 0x3f, 0x89, 0x7e, 0x1d, + 0x97, 0xa6, 0xa5, 0x11, 0xfc, 0xff, 00, 0xc2, 0xad, 0x27, + 0x8e, 0xf4, 0x29, 0x3a, 0x6a, 0x31, 0x7e, 0xbf, 0xe1, 0x5f, + 0x8a, 0xf6, 0xbf, 0xb5, 0xdc, 0xdc, 0x1, 0x7a, 0xc7, 0xfe, + 0xd9, 0x8f, 0xfe, 0x26, 0xb6, 0x2d, 0x7f, 0x6b, 0xf9, 0x90, + 0x8c, 0x5f, 0x30, 0xc7, 0xfb, 0x3, 0xff, 00, 0x89, 0xa0, + 0xf, 0xd9, 0x74, 0xf1, 0x76, 0x8d, 0x27, 0xdd, 0xd4, 0x21, + 0x3f, 0x89, 0xab, 0x9, 0xaf, 0xe9, 0xce, 0x32, 0xb7, 0x91, + 0x1f, 0xc6, 0xbf, 0x1d, 0xad, 0x7f, 0x6c, 0x6b, 0x80, 0x47, + 0xfa, 0x7b, 0x7f, 0xdf, 0xaf, 0xfe, 0xc6, 0xb6, 0xed, 0x3f, + 0x6c, 0xcb, 0x80, 0x7, 0xfa, 0x6b, 0x8c, 0xfa, 0x20, 0xff, + 00, 0xe2, 0x28, 0x3, 0xf5, 0xcd, 0x75, 0x6b, 0x36, 0xe9, + 0x70, 0x87, 0xf1, 0xa9, 0x56, 0xf2, 0x6, 0xe9, 0x2a, 0x9f, + 0xc6, 0xbf, 0x27, 0xad, 0xbf, 0x6d, 0x1b, 0x85, 0x23, 0xfd, + 0x39, 0x8f, 0xd6, 0x31, 0xff, 00, 0xc4, 0x56, 0xd5, 0xa7, + 0xed, 0xad, 0x30, 0x23, 0x37, 0x4c, 0x7f, 0xe0, 0x23, 0xff, + 00, 0x88, 0xa0, 0xf, 0xd4, 0xa1, 0x32, 0x1e, 0x8c, 0x29, + 0x43, 0x83, 0xd0, 0xd7, 0xe6, 0x6d, 0xa7, 0xed, 0xb9, 0x22, + 0xa8, 0xcd, 0xe3, 0x8f, 0xfb, 0x66, 0x3f, 0xf8, 0x8a, 0xd8, + 0xb4, 0xfd, 0xb7, 0xe4, 0xe3, 0xfd, 0x31, 0xcf, 0xd1, 00, + 0xff, 00, 0xd9, 0x28, 0x3, 0xf4, 0x72, 0x8a, 0xfc, 0xfd, + 0xb3, 0xfd, 0xb8, 0xa, 0x91, 0xfe, 0x98, 0xe3, 0xfe, 00, + 0xf, 0xfe, 0xc9, 0x5b, 0x56, 0x9f, 0xb7, 0xa, 0x7f, 0xcf, + 0xdb, 0x1f, 0xfb, 0x67, 0x8f, 0xfd, 0x92, 0x80, 0x3e, 0xe8, + 0xa4, 0xaf, 0x8c, 0x6d, 0xbf, 0x6d, 0xf8, 0x30, 0x37, 0x5c, + 0x37, 0xe0, 0x9f, 0xfd, 0x85, 0x6b, 0xdb, 0x7e, 0xdb, 0x3a, + 0x7b, 0x91, 0xba, 0xe1, 0xbf, 0xef, 0xdf, 0xff, 00, 0x61, + 0x40, 0x1f, 0x5c, 0x52, 0x66, 0xbe, 0x5f, 0xb6, 0xfd, 0xb2, + 0xb4, 0x99, 00, 0xdd, 0x29, 0xe7, 0xfd, 0x93, 0xff, 00, + 0xc4, 0xd6, 0x9d, 0xbf, 0xed, 0x7d, 0xa1, 0xbe, 0x37, 0x48, + 0xdf, 0xf7, 0xc9, 0xff, 00, 0xe2, 0x68, 0x3, 0xe8, 0xdc, + 0x8a, 0x5a, 0xf0, 0x6b, 0x5f, 0xda, 0xb7, 0xc3, 0xd3, 0xe, + 0x5c, 0xb7, 0xe7, 0xff, 00, 0xc4, 0xd6, 0x94, 0x1f, 0xb4, + 0xf7, 0x86, 0x64, 0x19, 0x2e, 0xe3, 0xfe, 0x2, 0x7f, 0xf8, + 0x9a, 00, 0xf6, 0x7a, 0x2b, 0xca, 0x6d, 0xff, 00, 0x68, + 0xbf, 0xb, 0xcd, 0x8f, 0xdf, 0x3f, 0x3f, 0xec, 0xb7, 0xff, + 00, 0x13, 0x57, 0xe1, 0xf8, 0xf1, 0xe1, 0x79, 0xbf, 0xe5, + 0xe1, 0xc7, 0xfc, 0x1, 0xbf, 0xc2, 0x80, 0x3d, 0x1e, 0x8a, + 0xe1, 0x62, 0xf8, 0xcd, 0xe1, 0x99, 0x47, 0x17, 0x6d, 0xff, + 00, 0x7e, 0xdb, 0xfc, 0x2a, 0xe4, 0x5f, 0x14, 0xfc, 0x3b, + 0x2f, 0x4b, 0xd3, 0xff, 00, 0x7e, 0xdb, 0xfc, 0x28, 0x3, + 0xae, 0xa2, 0xb9, 0xc8, 0xbe, 0x21, 0x68, 0x53, 0x7d, 0xdb, + 0xd1, 0xf8, 0xa3, 0x7f, 0x85, 0x5a, 0x4f, 0x18, 0x69, 0x32, + 0x7d, 0xdb, 0xb5, 0x3f, 0xf0, 0x13, 0x40, 0x1b, 0x34, 0x56, + 0x6a, 0xf8, 0x8f, 0x4e, 0x7e, 0x97, 0x4b, 0xf9, 0x1a, 0x99, + 0x35, 0x7b, 0x39, 0x3e, 0xec, 0xe8, 0x68, 0x2, 0xe5, 0x15, + 0x2, 0xdf, 0x40, 0xc3, 0x89, 0x54, 0xfe, 0x34, 0xf5, 0xb8, + 0x8d, 0xba, 0x3a, 0x9f, 0xc6, 0x80, 0x24, 0xa2, 0x9a, 0x1d, + 0x4f, 0x46, 0x7, 0xf1, 0xa5, 0xdc, 0x3d, 0x68, 0x1, 0x69, + 0x92, 0x9c, 0x2d, 0x3b, 0x35, 0x14, 0xed, 0xc5, 00, 0x66, + 0x5e, 0xbe, 0x3f, 0x2a, 0xe7, 0x6f, 0xde, 0xb6, 0xef, 0xde, + 0xb9, 0xeb, 0xf6, 0xa0, 0xc, 0x2d, 0x4a, 0x4e, 0xb5, 0xca, + 0x6a, 0x52, 0x75, 0xae, 0x8b, 0x53, 0x93, 0xad, 0x72, 0x9a, + 0x8c, 0x9c, 0x1a, 00, 0xe6, 0x75, 0x89, 0x71, 0xba, 0xb8, + 0x4d, 0x76, 0x7d, 0x91, 0x48, 0x49, 0xe9, 0x5d, 0x86, 0xb1, + 0x2e, 0x37, 0x57, 0x9d, 0xf8, 0xae, 0xeb, 0xcb, 0xb3, 0x90, + 0x83, 0x8a, 0x99, 0x3b, 0x26, 0xc9, 0x93, 0xe5, 0x8b, 0x67, + 0x82, 0x7c, 0x4a, 0xd4, 0x32, 0xd3, 0x1d, 0xd5, 0xf3, 0x86, + 0xb3, 0x36, 0xe9, 0xa4, 0x39, 0xee, 0x6b, 0xdb, 0x7e, 0x23, + 0x5f, 0xe7, 0xcd, 0xe6, 0xbc, 0x1b, 0x56, 0x97, 0x2c, 0xe7, + 0xdc, 0xd7, 0xc0, 0xe2, 0x9f, 0x3d, 0x63, 0xf3, 0xc, 0x6c, + 0xbd, 0xa5, 0x73, 0x9b, 0xd4, 0xe4, 0xeb, 0x5c, 0xfd, 0xc3, + 0x75, 0xad, 0x8d, 0x4a, 0x4c, 0x93, 0x58, 0x57, 0xd, 0xd6, + 0xbd, 0x1a, 0x11, 0xb2, 0x47, 0xad, 0x86, 0x8d, 0x91, 0x37, + 0x87, 0xb4, 0xd1, 0xad, 0xf8, 0x8b, 0x4c, 0xd3, 0xdc, 0x16, + 0x5b, 0xab, 0x98, 0xe1, 0x20, 0x75, 0x3b, 0x98, 0xa, 0xfd, + 0x97, 0xf8, 0x1d, 0xa3, 0xae, 0x97, 0xe1, 0x81, 0xb6, 0x3d, + 0x98, 0xb, 0x10, 0xe3, 0x1c, 0x28, 0xff, 00, 0x12, 0x6b, + 0xf2, 0x8f, 0xf6, 0x6d, 0xd0, 0xdf, 0x5f, 0xf8, 0xcb, 0xe1, + 0xf4, 0xd9, 0xbe, 0x8, 0x5e, 0x49, 0xa4, 0x39, 0xc6, 0x36, + 0xc4, 0xe5, 0x4f, 0x5e, 0x7e, 0x60, 0x2b, 0xf6, 0xf, 0xe1, + 0xfd, 0x91, 0xb1, 0xf0, 0xb5, 0x9a, 0x30, 0xc3, 0xb0, 0x2c, + 0xd8, 0xfa, 0x9a, 0xfa, 0x3c, 0x32, 0xb4, 0x6e, 0x7d, 0x66, + 0x12, 0x36, 0x8b, 0x67, 0x59, 00, 0xe9, 0x5a, 0x50, 0xa, + 0xa1, 00, 0xf9, 0x85, 0x69, 0x42, 0x38, 0xae, 0xc3, 0xbc, + 0xb9, 0x8, 0xad, 0xb, 0x71, 0xd2, 0xa9, 0x42, 0xbd, 0x2b, + 0x42, 0x5, 0xc0, 0x6, 0x80, 0x2d, 0xc6, 0x39, 0xab, 0xb0, + 0x81, 0x81, 0x55, 0x22, 0x1d, 0x2a, 0xec, 0x43, 0xa5, 00, + 0x58, 0x88, 0x55, 0xa4, 0x1c, 0xd5, 0x78, 0x85, 0x5a, 0x8c, + 0x50, 0x4, 0xab, 0x4f, 0x5a, 0x62, 0xf4, 0xa9, 0x7, 0x6a, + 00, 0x78, 0xeb, 0x52, 0x2d, 0x31, 0x69, 0xeb, 0xd2, 0x80, + 0x16, 0x95, 0x69, 0x29, 0x56, 0x80, 0x1d, 0x45, 0x14, 0x50, + 0x1, 0x45, 0x14, 0x50, 0x6, 0x24, 0x95, 0x52, 0x77, 0x54, + 0x46, 0x67, 0x21, 0x55, 0x41, 0x25, 0x8f, 0x40, 0x2a, 0xd4, + 0x95, 0xe7, 0x3f, 0x1d, 0xfc, 0x5e, 0x7c, 0xf, 0xf0, 0xab, + 0xc4, 0x5a, 0xaa, 0x18, 0x4c, 0xc9, 0x7, 0x95, 0x1a, 0xce, + 0xd8, 0xc, 0x64, 0x60, 0x87, 0xf1, 0xc3, 0x13, 0xf8, 0x56, + 0x55, 0x6a, 0x2a, 0x54, 0xe5, 0x37, 0xb2, 0x46, 0x35, 0xaa, + 0xaa, 0x34, 0xe5, 0x52, 0x5d, 0x15, 0xcf, 0x89, 0x35, 0x6b, + 0xa9, 0x3e, 0x29, 0x7e, 0xd1, 0xda, 0xb5, 0xd8, 0x73, 0x73, + 0x1c, 0x97, 0xc2, 0x25, 0x2d, 0xc2, 0xed, 0x8d, 0x56, 0x3e, + 0x31, 0xc6, 0x3e, 0x4e, 0xdd, 0x7a, 0xd7, 0xdf, 0xbe, 0x12, + 0xb2, 0x5b, 0x4b, 0x38, 0x50, 00, 0xa1, 0x54, 0xc, 0xa, + 0xf8, 0x73, 0xf6, 0x48, 0xd0, 0xd6, 0xe3, 0xc4, 0x32, 0xdf, + 0xca, 0x37, 0x34, 0x43, 0x86, 0x3e, 0xa7, 0x3c, 0xd7, 0xdc, + 0xba, 0x4d, 0xc6, 0xd4, 00, 0x1e, 0x82, 0xbe, 0x57, 0x87, + 0x69, 0xb9, 0xd3, 0xa9, 0x8a, 0x96, 0xf3, 0x6c, 0xf8, 0x9e, + 0x14, 0xa6, 0xe7, 0x4a, 0xae, 0x36, 0x5b, 0xd4, 0x93, 0x67, + 0x69, 0x66, 0xc0, 0x28, 0x15, 0x6a, 0xb0, 0x6d, 0x6e, 0xba, + 0x73, 0x5a, 0x71, 0x5d, 0x64, 0xe, 0x6b, 0xeb, 0xcf, 0xbc, + 0x2d, 0xd1, 0x4c, 0x59, 0x3, 0x53, 0xb2, 0x28, 0x1, 0xaf, + 0x1a, 0x10, 0x4b, 0x20, 0x3f, 0x51, 0x5f, 0x8, 0xff, 00, + 0xc1, 0x47, 0x3c, 0x79, 0x69, 0xe1, 0xff, 00, 0x87, 0xd7, + 0x56, 0xd1, 0x22, 0x47, 0x34, 0x8a, 0xdc, 0x88, 0xc7, 0x1f, + 0x2b, 0x74, 0xf7, 0xaf, 0xba, 0xee, 0x9b, 0x10, 0x39, 0x1d, + 0x71, 0x5f, 0x15, 0x7e, 0xd7, 0x1f, 0x9, 0x6e, 0x3e, 0x25, + 0x5c, 0x47, 0xf, 0x90, 0xd3, 0x20, 0xe0, 0xfc, 0x9b, 0x87, + 0x7f, 0x63, 0xeb, 0x40, 0x1f, 0x87, 0x57, 0x1b, 0xe7, 0xb8, + 0x96, 0x42, 0xac, 0xcc, 0xec, 0x5b, 0x27, 0xaf, 0x26, 0xbf, + 0x56, 0x3f, 0xe0, 0x9c, 0xdf, 0xc, 0xac, 0x2f, 0xfc, 0x2b, + 0xa5, 0x3d, 0xe6, 0x9f, 0x1c, 0xcd, 0x26, 0x49, 0x2e, 0x32, + 0x4f, 0xcc, 0xdf, 0xa5, 0x70, 0xa9, 0xfb, 0x19, 0xab, 0x5d, + 0x46, 0xe, 0x94, 0x71, 0xb8, 0x64, 0x8b, 0x7f, 0x7f, 0xf7, + 0x6b, 0xf4, 0x2b, 0xf6, 0x64, 0xf8, 0x5b, 0x6b, 0xe0, 0xf, + 0xb, 0xda, 0x43, 0x1d, 0xb0, 0x81, 0xe3, 0x8f, 0x18, 0x9, + 0x8e, 0xe7, 0xd8, 0x7a, 0xd0, 0x7, 0xad, 0xf, 0x2, 0x68, + 0x1b, 0x15, 0x7f, 0xb2, 0xad, 0xc0, 0x3, 0x18, 0xdb, 0x55, + 0xe5, 0xf8, 0x73, 0xe1, 0xd9, 0x7e, 0xf6, 0x95, 0x6e, 0x7f, + 0xe0, 0x35, 0xd3, 0x51, 0x40, 0x1c, 0x74, 0xbf, 0x9, 0xfc, + 0x31, 0x2e, 0x73, 0xa5, 0xc2, 0x3e, 0x82, 0xa9, 0xcd, 0xf0, + 0x53, 0xc2, 0xd2, 0xf5, 0xd3, 0xa3, 0xc7, 0xfb, 0xb5, 0xde, + 0xd1, 0x40, 0x1e, 0x67, 0x37, 0xc0, 0x1f, 0xa, 0xcb, 0x9f, + 0xf8, 0x97, 0xc4, 0x3f, 0xe0, 0x35, 0xb5, 0xe1, 0xbf, 0x85, + 0xda, 0x2f, 0x86, 0x65, 0x49, 0x2d, 0x6d, 0x63, 0x57, 0x5f, + 0xbb, 0x81, 0xd2, 0xbb, 0x2a, 0x28, 0x1, 0x29, 0x1d, 0x77, + 0xa1, 0x5f, 0x51, 0x8a, 0x75, 0x14, 0x1, 0xe3, 0xbf, 0x14, + 0x3e, 0x2, 0x5a, 0xfc, 0x42, 0xe2, 0x58, 0xe0, 0x91, 0x49, + 0xe4, 0x48, 0xc4, 0x7f, 0x43, 0x5e, 0x55, 0x73, 0xfb, 0x10, + 0x69, 0xef, 0xf7, 0x6c, 0xec, 0xfa, 0xf6, 0x90, 0xff, 00, + 0x85, 0x7d, 0x6f, 0x45, 00, 0x7c, 0x5f, 0x79, 0xfb, 0xb, + 0x40, 0xe3, 0xf7, 0x76, 0x76, 0xa7, 0xfe, 0x6, 0x7f, 0xf8, + 0x9a, 0xc6, 0xba, 0xfd, 0x84, 0xe, 0xe, 0xdd, 0x3a, 0xdc, + 0xfd, 0x1d, 0xbf, 0xf8, 0x9a, 0xfb, 0xa6, 0x8a, 00, 0xfc, + 0xfe, 0xbb, 0xfd, 0x83, 0x67, 0x39, 0xb, 0xa7, 0x45, 0x9f, + 0x72, 0xdf, 0xfc, 0x4d, 0x62, 0xdd, 0x7e, 0xc1, 0xd7, 0xc0, + 0xb6, 0x34, 0xc8, 0xb1, 0xec, 0x5b, 0xff, 00, 0x89, 0xaf, + 0xd1, 0xba, 0x28, 0x3, 0xf3, 0x2a, 0xf3, 0xf6, 0x15, 0xd4, + 0x14, 0x1c, 0x69, 0x8b, 0xf8, 0x6e, 0xff, 00, 0xe2, 0x6b, + 0x12, 0xf3, 0xf6, 0x1b, 0xd4, 0xd7, 0xa6, 0x97, 0x19, 0xfc, + 0x1b, 0xff, 00, 0x89, 0xaf, 0xd5, 0xa, 0x42, 0xa0, 0xf5, + 0x14, 0x1, 0xf9, 0x29, 0x7b, 0xfb, 0x11, 0xea, 0x68, 0x5b, + 0xfe, 0x25, 0xb, 0xd7, 0xb0, 0x6f, 0xfe, 0x26, 0xb1, 0x2e, + 0xbf, 0x62, 0xad, 0x50, 0xf, 0xf9, 0x4, 0x45, 0xf8, 0xab, + 0x7f, 0xf1, 0x35, 0xfb, 0x4, 0xd6, 0xf1, 0xb7, 0x54, 0x53, + 0xf5, 0x14, 0xc6, 0xb0, 0xb7, 0x7f, 0xbd, 0xa, 0x1f, 0xa8, + 0xa0, 0xf, 0xc6, 0x9b, 0xbf, 0xd8, 0xc7, 0x52, 0x5f, 0xf9, + 0x83, 0xa1, 0x3e, 0xc1, 0xbf, 0xf8, 0x9a, 0xc7, 0xbb, 0xfd, + 0x8e, 0xf5, 0x4, 0xce, 0x74, 0x75, 0xfc, 0x55, 0xbf, 0xf8, + 0x9a, 0xfd, 0xa9, 0x6d, 0x16, 0xc5, 0xba, 0xda, 0xc4, 0x7e, + 0xab, 0x51, 0x37, 0x87, 0x74, 0xc7, 0xfb, 0xd6, 0x30, 0x1f, + 0xf8, 00, 0xa0, 0xf, 0xc4, 0x4b, 0x9f, 0xd9, 0x6, 0xf5, + 0x41, 0xce, 0x8c, 0xbf, 0x80, 0x6f, 0xfe, 0x26, 0xb2, 0x2f, + 0x3f, 0x64, 0x9b, 0xc4, 0x7, 0x3a, 0x40, 0x3, 0xfd, 0xd6, + 0xff, 00, 0xe2, 0x6b, 0xf7, 0x31, 0xfc, 0x23, 0xa2, 0xbf, + 0xde, 0xd3, 0x2d, 0x9b, 0xeb, 0x18, 0xa8, 0xa4, 0xf0, 0x3e, + 0x81, 0x27, 0xde, 0xd2, 0x2d, 0x3f, 0xef, 0xd0, 0xa0, 0xf, + 0xc2, 0x1b, 0x8f, 0xd9, 0x4a, 0xed, 0x73, 0xff, 00, 0x12, + 0xac, 0x7d, 0x3, 0x7f, 0xf1, 0x35, 0x99, 0x71, 0xfb, 0x2d, + 0xde, 0x20, 0xe3, 0x4d, 0x75, 0xfc, 0x1b, 0x1f, 0xfa, 0xd, + 0x7e, 0xf3, 0xc9, 0xf0, 0xd7, 0xc3, 0x32, 0x83, 0xbb, 0x46, + 0xb4, 0x39, 0xff, 00, 0xa6, 0x4b, 0xfe, 0x15, 0x56, 0x4f, + 0x84, 0xbe, 0x15, 0x97, 0xef, 0x69, 0x16, 0xdf, 0x84, 0x4b, + 0xfe, 0x14, 0x1, 0xf8, 0x23, 0x3f, 0xec, 0xcd, 0x79, 0x1e, + 0x7f, 0xd0, 0x58, 0xf, 0xf8, 0x17, 0xf8, 0x56, 0x74, 0xff, + 00, 0xb3, 0x75, 0xf2, 0x1e, 0x2d, 0x1c, 0x7f, 0xdf, 0x5f, + 0xe1, 0x5f, 0xbe, 0x72, 0xfc, 0x11, 0xf0, 0x8c, 0xc4, 0x96, + 0xd2, 0xa1, 0xff, 00, 0xbf, 0x69, 0xff, 00, 0xc4, 0xd5, + 0x39, 0x7f, 0x67, 0xef, 0x6, 0xc9, 0x9f, 0xf8, 0x95, 0xc4, + 0x33, 0xe9, 0x12, 0x7f, 0xf1, 0x34, 0x1, 0xf8, 0x11, 0x3f, + 0xec, 0xf5, 0xa8, 0xc7, 0x9c, 0x40, 0xc3, 0xea, 0x5b, 0xff, + 00, 0x89, 0xaa, 0x33, 0x7c, 0x3, 0xd5, 0x23, 0x3c, 0x44, + 0xff, 00, 0x81, 0x3f, 0xfc, 0x4d, 0x7e, 0xfc, 0x4f, 0xfb, + 0x35, 0x78, 0x2e, 0x71, 0x83, 0x60, 0xa0, 0x7a, 0x79, 0x49, + 0xff, 00, 0xc4, 0xd6, 0x7d, 0xc7, 0xec, 0xab, 0xe0, 0xa9, + 0xf2, 0x7e, 0xc6, 0x80, 0x9f, 0xfa, 0x63, 0x1f, 0xff, 00, + 0x13, 0x40, 0x1f, 0x81, 0x32, 0xfc, 0xf, 0xd5, 0xd0, 0xf1, + 0x1b, 0x7e, 0x39, 0xff, 00, 0xe2, 0x6a, 0x9c, 0xbf, 0x6, + 0xb5, 0xa4, 0xe9, 0x17, 0xea, 0x7f, 0xf8, 0x9a, 0xfd, 0xf0, + 0xb8, 0xfd, 0x90, 0x3c, 0x1d, 0x30, 0xe2, 0x4, 0x5f, 0xfb, + 0x65, 0x1f, 0xff, 00, 0x13, 0x59, 0xb3, 0xfe, 0xc5, 0xbe, + 0x11, 0x90, 0x8d, 0xb1, 0x45, 0xf8, 0xc4, 0x9f, 0xfc, 0x4d, + 00, 0x7e, 0xb, 0xcb, 0xf0, 0x97, 0x5b, 0x8f, 0xfe, 0x58, + 0x8f, 0xfc, 0x7b, 0xff, 00, 0x89, 0xaa, 0xaf, 0xf0, 0xcb, + 0x5b, 0x4f, 0xf9, 0x62, 0xf, 0xd3, 0x3f, 0xe1, 0x5f, 0xbc, + 0x17, 0x1f, 0xb1, 0x7, 0x86, 0x24, 0xe0, 0x24, 0x23, 0xe9, + 0x1a, 0xff, 00, 0xf1, 0x15, 0x93, 0x73, 0xfb, 0x9, 0xf8, + 0x7e, 0x4c, 0xe1, 0x62, 0xe7, 0xfe, 0x99, 0xaf, 0xff, 00, + 0x11, 0x40, 0x1f, 0x85, 0xcf, 0xf0, 0xf3, 0x59, 0x4e, 0xb6, + 0xe4, 0xfd, 0x14, 0xff, 00, 0x85, 0x57, 0x7f, 0x4, 0xea, + 0xc9, 0xd6, 0xdd, 0xbf, 0x23, 0xfe, 0x15, 0xfb, 0x87, 0x75, + 0xfb, 0x6, 0x69, 0xd, 0xf7, 0x62, 0x8b, 0xf0, 0x8c, 0x7f, + 0xf1, 0x15, 0x8b, 0x79, 0xfb, 0x3, 0x69, 0xee, 0xcd, 0xb6, + 0x11, 0xff, 00, 0x7e, 0xc7, 0xff, 00, 0x11, 0x40, 0x1f, + 0x8a, 0xf, 0xe1, 0x4d, 0x4d, 0x3a, 0xdb, 0x3f, 0xe0, 0xa7, + 0xfc, 0x2a, 0x6, 0xf0, 0xfd, 0xfa, 0xe, 0x6d, 0xe4, 0xff, + 00, 0xbe, 0xf, 0xf8, 0x57, 0xec, 0xe5, 0xd7, 0xec, 0x5, + 0x6, 0xe, 0xdb, 0x60, 0x7e, 0x91, 0xf, 0xfe, 0x22, 0xb1, + 0xae, 0xbf, 0x60, 0x35, 0xe4, 0xb, 0x39, 0x31, 0xff, 00, + 0x5c, 0x47, 0xff, 00, 0x11, 0x40, 0x1f, 0x8e, 0xed, 0xa4, + 0xdd, 0xaf, 0x5b, 0x79, 0x7, 0xfc, 00, 0xd4, 0x6d, 0x61, + 0x70, 0x9d, 0x60, 0x93, 0xfe, 0xf9, 0x35, 0xfa, 0xe7, 0x77, + 0xfb, 0x2, 0x38, 0x24, 0xad, 0x8c, 0x87, 0xeb, 0x7, 0xff, + 00, 0x61, 0x58, 0xd7, 0x7f, 0xb0, 0x5c, 0xeb, 0x9c, 0x69, + 0xd2, 0x1f, 0xa5, 0xbf, 0xff, 00, 0x61, 0x40, 0x1f, 0x94, + 0x5f, 0x66, 0x94, 0xe, 0x62, 0x7f, 0xfb, 0xe4, 0xd3, 0x4c, + 0x4e, 0x3a, 0xa3, 0xf, 0xc2, 0xbf, 0x51, 0xaf, 0x3f, 0x61, + 0x9, 0xd1, 0x4f, 0xfc, 0x4b, 0x24, 0x3f, 0x5b, 0x73, 0xff, + 00, 0xc4, 0x56, 0x1d, 0xdf, 0xec, 0x37, 0x74, 0x80, 0xff, + 00, 0xc4, 0xad, 0xcf, 0xd2, 0xdb, 0xff, 00, 0xb0, 0xa0, + 0xf, 0xcd, 0x4d, 0xa4, 0x76, 0x34, 0x98, 0x3e, 0x86, 0xbf, + 0x44, 0xee, 0xbf, 0x62, 0x3b, 0x90, 0x32, 0x74, 0xa7, 0xfc, + 0x6d, 0xbf, 0xfb, 0xa, 0xc7, 0xba, 0xfd, 0x8b, 0x2e, 0x54, + 0x1f, 0xf8, 0x94, 0x93, 0xec, 0x2d, 0xff, 00, 0xfb, 0xa, + 00, 0xf8, 0x12, 0x8a, 0xfb, 0x92, 0xe3, 0xf6, 0x34, 0xb9, + 0x52, 0x73, 0xa4, 0x49, 0xff, 00, 0x80, 0xdf, 0xfd, 0x85, + 0x65, 0x5c, 0x7e, 0xc7, 0xd7, 0x8, 0x73, 0xfd, 0x93, 0x20, + 0xff, 00, 0xb7, 0x7f, 0xfe, 0xc2, 0x80, 0x3e, 0x30, 0xa2, + 0xbe, 0xba, 0xba, 0xfd, 0x92, 0x6e, 0x53, 0xfe, 0x61, 0x93, + 0xaf, 0xd2, 0xdf, 0xff, 00, 0xb0, 0xac, 0xbb, 0x8f, 0xd9, + 0x52, 0xe5, 0x33, 0xfe, 0x81, 0x38, 0xfa, 0xc1, 0xff, 00, + 0xd8, 0xd0, 0x7, 0xcb, 0x34, 0x57, 0xd2, 0x97, 0x1f, 0xb2, + 0xed, 0xda, 0xff, 00, 0xcb, 0xa5, 0xc0, 0xfa, 0x44, 0x7f, + 0xf8, 0x9a, 0xcf, 0x9f, 0xf6, 0x65, 0xbc, 0x51, 0xc4, 0x17, + 0x23, 0xfe, 0xd9, 0x1f, 0xfe, 0x26, 0x80, 0x3e, 0x7b, 0xa2, + 0xbd, 0xce, 0x7f, 0xd9, 0xbe, 0xf9, 0x3f, 0xe5, 0x95, 0xcf, + 0xfd, 0xfb, 0xff, 00, 0xec, 0x6a, 0x8c, 0xbf, 0xb3, 0xcd, + 0xfa, 0x67, 0xf7, 0x77, 0x3f, 0xf7, 0xc1, 0xff, 00, 0xe2, + 0x68, 0x3, 0xc6, 0xa8, 0xaf, 0x56, 0x9b, 0xe0, 0x3e, 0xa4, + 0x84, 0xed, 0x49, 0x8f, 0xfc, 0x4, 0xff, 00, 0xf1, 0x35, + 0x4e, 0x4f, 0x82, 0x7a, 0xa2, 0x7f, 0xcb, 0x39, 0xbf, 0xef, + 0x83, 0xfe, 0x14, 0x1, 0xe6, 0xb4, 0x57, 0x7f, 0x2f, 0xc1, + 0xed, 0x59, 0x3a, 0x45, 0x21, 0xfa, 0xa9, 0xff, 00, 0xa, + 0xa9, 0x2f, 0xc2, 0xbd, 0x62, 0x3f, 0xf9, 0x77, 0x93, 0xfe, + 0xf9, 0x6f, 0xf0, 0xa0, 0xe, 0x2e, 0x8a, 0xea, 0xe4, 0xf8, + 0x6f, 0xac, 0xa1, 0xff, 00, 0x8f, 0x77, 0x3f, 0xf0, 0x16, + 0xff, 00, 0xa, 0xab, 0x27, 0x80, 0xb5, 0x98, 0xc9, 0xff, + 00, 0x44, 0x73, 0xff, 00, 0x1, 0x6f, 0xf0, 0xa0, 0xe, + 0x7a, 0x8a, 0xda, 0x7f, 0x7, 0x6a, 0xc9, 0xff, 00, 0x2e, + 0x72, 0xff, 00, 0xdf, 0x6, 0xa1, 0x6f, 0xc, 0x6a, 0x8b, + 0xff, 00, 0x2e, 0x72, 0xff, 00, 0xdf, 0x26, 0x80, 0x32, + 0xe8, 0xab, 0xed, 0xa0, 0xea, 0x9, 0xd6, 0xce, 0x6f, 0xfb, + 0xe4, 0xd4, 0x67, 0x49, 0xbd, 0x5e, 0xb6, 0xb2, 0x8f, 0xf8, + 0x9, 0xa0, 0xa, 0x94, 0x55, 0x83, 0xa7, 0x5d, 0x2f, 0x5b, + 0x79, 0x47, 0xfc, 00, 0xd4, 0x6d, 0x6b, 0x32, 0x9e, 0x62, + 0x71, 0xf5, 0x53, 0x40, 0x11, 0xd2, 0xee, 0x3e, 0xa6, 0x9c, + 0x61, 0x90, 0x7f, 0x3, 0x7e, 0x54, 0xd2, 0x8c, 0xbd, 0x54, + 0x8f, 0xa8, 0xa0, 0x3, 0x7b, 0x7f, 0x78, 0xfe, 0x74, 0xe1, + 0x71, 0x2a, 0xf4, 0x91, 0x87, 0xe3, 0x4c, 0xa2, 0x80, 0x26, + 0x17, 0xb7, 0xb, 0xd2, 0x69, 0x7, 0xfc, 0x8, 0xd4, 0x8b, + 0xaa, 0xde, 0x27, 0xdd, 0xba, 0x94, 0x7d, 0x1c, 0xd5, 0x5c, + 0x1f, 0x4a, 0x28, 0x2, 0xf2, 0xeb, 0xda, 0x8a, 0x74, 0xbc, + 0x9b, 0xfe, 0xfa, 0xa9, 0x93, 0xc4, 0xfa, 0xa2, 0x74, 0xbd, + 0x97, 0xfe, 0xfa, 0xac, 0xba, 0x28, 0x3, 0x69, 0x7c, 0x65, + 0xac, 0x27, 0x4b, 0xe9, 0x7f, 0xef, 0xaa, 0xb0, 0x9e, 0x3e, + 0xd6, 0x50, 0xff, 00, 0xc7, 0xe4, 0x87, 0xf1, 0xae, 0x76, + 0x8a, 00, 0xeb, 0x62, 0xf8, 0x97, 0xad, 0x47, 0x8f, 0xf4, + 0xc9, 0x7f, 0x3a, 0xb5, 0x1f, 0xc5, 0xad, 0x6d, 0xf, 0x37, + 0x32, 0x1f, 0xc6, 0xb8, 0x8a, 0x28, 0x3, 0xd0, 0xa2, 0xf8, + 0xcb, 0xac, 0x47, 0x83, 0xf6, 0x89, 0x47, 0xd1, 0xaa, 0xec, + 0x3f, 0x1c, 0xb5, 0x78, 0xfa, 0xdc, 0x4c, 0x7f, 0x2a, 0xf3, + 0xa, 0x28, 0x3, 0xd7, 0x21, 0xf8, 0xfd, 0xa9, 0xc7, 0x8c, + 0xcf, 0x70, 0x3e, 0x98, 0xff, 00, 0x1a, 0xbf, 0xf, 0xed, + 0x15, 0xa8, 0x21, 0x7, 0xed, 0x57, 0x3f, 0x8f, 0xff, 00, + 0xae, 0xbc, 0x52, 0x8a, 00, 0xf7, 0xcb, 0x7f, 0xda, 0x56, + 0xf1, 0x3a, 0xdd, 0xdc, 0x3, 0xf4, 0xff, 00, 0xeb, 0xd6, + 0x8c, 0x3f, 0xb5, 0x5, 0xca, 0x60, 0x7d, 0xba, 0xe4, 0x7e, + 0x1f, 0xfd, 0x7a, 0xf9, 0xca, 0x8a, 00, 0xfa, 0x7e, 0xdb, + 0xf6, 0xa9, 0x9d, 0x4f, 0x3a, 0x8d, 0xc6, 0x7f, 0xcf, 0xbd, + 0x6a, 0x5b, 0x7e, 0xd6, 0x33, 0x2f, 0xfc, 0xc5, 0x6e, 0x41, + 0xf7, 0x3f, 0xfd, 0x7a, 0xf9, 0x32, 0x8a, 00, 0xfb, 0x26, + 0xdf, 0xf6, 0xb9, 0x98, 0x60, 0x7f, 0x6c, 0x4c, 0x7f, 0x11, + 0xfe, 0x35, 0xaf, 0x69, 0xfb, 0x5f, 0x4c, 0xbf, 0xf3, 0x18, + 0x9c, 0xf, 0xf7, 0x87, 0xf8, 0xd7, 0xc3, 0xf4, 0x50, 0x7, + 0xdf, 0x36, 0x7f, 0xb6, 0x25, 0xc0, 0x3, 0xfe, 0x27, 0x32, + 0x9f, 0xab, 0xf, 0xf1, 0xad, 0xab, 0x5f, 0xdb, 0x22, 0xe0, + 0x63, 0xfe, 0x27, 0x13, 0x7e, 0xc, 0x3f, 0xc6, 0xbf, 0x3b, + 0x43, 0x91, 0xde, 0x9c, 0x26, 0x75, 0x3c, 0x31, 0x14, 0x1, + 0xfa, 0x4f, 0x6b, 0xfb, 0x67, 0x5c, 0xa9, 0x1f, 0xf1, 0x39, + 0x9b, 0xf1, 0x2b, 0xfe, 0x35, 0xaf, 0x69, 0xfb, 0x69, 0xdc, + 0x8e, 0xba, 0xbc, 0xa4, 0xfb, 0x30, 0xff, 00, 0x1a, 0xfc, + 0xc4, 0x17, 0xb3, 0x28, 0xc0, 0x90, 0x8a, 0x7a, 0xea, 0x77, + 0x4b, 0xd2, 0x66, 0x14, 0x1, 0xfa, 0xa3, 0x6d, 0xfb, 0x6b, + 0xdc, 0xa8, 0x1f, 0xf1, 0x37, 0x9c, 0x7d, 0x48, 0xff, 00, + 0x1a, 0xd8, 0xb2, 0xfd, 0xb7, 0x6e, 0x1, 0x1f, 0xf1, 0x36, + 0x9b, 0xf3, 0x5f, 0xf1, 0xaf, 0xc9, 0xb5, 0xd7, 0x2f, 0x93, + 0xee, 0xdc, 0xb8, 0xfc, 0xaa, 0x41, 0xe2, 0x3d, 0x49, 0x7a, + 0x5d, 0xb8, 0xfc, 0xa8, 0x3, 0xf5, 0xf2, 0xd3, 0xf6, 0xe0, + 0x91, 0x79, 0x3a, 0xac, 0xff, 00, 0x9a, 0xff, 00, 0xf1, + 0x55, 0xb3, 0x67, 0xfb, 0x71, 0x31, 0x23, 0x3a, 0xac, 0xc7, + 0xdb, 0xe5, 0xff, 00, 0x1a, 0xfc, 0x70, 0x4f, 0x17, 0x6a, + 0xc9, 0xd2, 0xf1, 0xc7, 0xd3, 0x15, 0x2a, 0x78, 0xe3, 0x5a, + 0x43, 0x91, 0x7d, 0x27, 0xe3, 0x40, 0x1f, 0xb5, 0x96, 0x3f, + 0xb6, 0xec, 0x4d, 0x80, 0xda, 0x94, 0xa7, 0xea, 0xab, 0xfe, + 0x35, 0xd2, 0xe9, 0x9f, 0xb6, 0x55, 0x95, 0xdc, 0x8a, 0xaf, + 0x79, 0x9c, 0xfa, 0xa2, 0x7f, 0x8d, 0x7e, 0x1c, 0xc3, 0xf1, + 0x2b, 0x5e, 0x84, 0xc, 0x5e, 0x31, 0xae, 0x83, 0xc3, 0xdf, + 0x15, 0xfc, 0x44, 0xd7, 0xd0, 0xa2, 0xce, 0x5f, 0x73, 0x81, + 0xd4, 0xff, 00, 0x8d, 00, 0x7f, 0x40, 0x5e, 0xb, 0xf8, + 0x95, 0x6f, 0xe3, 0xab, 0x31, 0x34, 0x27, 0x70, 0xf5, 0xc0, + 0x1f, 0xc8, 0xd6, 0xb6, 0xa1, 0x27, 0x19, 0xaf, 0x9c, 0xff, + 00, 0x63, 0x1f, 0xb5, 0xc9, 0xf0, 0xee, 0x1b, 0x9b, 0xb5, + 0x75, 0x77, 0x3, 0x5, 0xc1, 0xc9, 0xeb, 0x5f, 0x41, 0xdf, + 0xb9, 0x9, 0xf8, 0x50, 0x7, 0x3f, 0xa9, 0x49, 0xd6, 0xb9, + 0x5d, 0x4a, 0x4c, 0x6, 0xae, 0x83, 0x53, 0x97, 0xad, 0x72, + 0x7a, 0xac, 0xbf, 0x29, 0xa0, 0xe, 0x5b, 0x58, 0x97, 0xef, + 0x57, 0x97, 0xf8, 0xf2, 0xef, 0xca, 0xb3, 0x60, 0xe, 0x2b, + 0xd0, 0xb5, 0x99, 0x7e, 0xf7, 0x35, 0xe3, 0x1f, 0x12, 0xf5, + 0x12, 0xaa, 0xeb, 0x9e, 0x5, 0x73, 0x62, 0x65, 0xc9, 0x4d, + 0xb3, 0x8f, 0x17, 0x3e, 0x4a, 0x4d, 0x9f, 0x3f, 0xfc, 0x42, + 0xbd, 0xdc, 0xd2, 0xc, 0x9a, 0xf1, 0xed, 0x52, 0x4e, 0x5a, + 0xbd, 0x7, 0xc6, 0xd7, 0x66, 0x59, 0x9c, 0x67, 0xbd, 0x79, + 0x9e, 0xa9, 0x2f, 0x27, 0x9a, 0xf8, 0x2f, 0x8e, 0xab, 0x3f, + 0x33, 0xbf, 0xb4, 0xae, 0xd9, 0xcf, 0xea, 0xf, 0x92, 0x6b, + 0x1a, 0x76, 0xad, 0x1b, 0xd7, 0xcb, 0x1a, 0xca, 0xb8, 0x6e, + 0xb5, 0xef, 0x52, 0x47, 0xd3, 0x50, 0x8d, 0x92, 0x3e, 0x93, + 0xfd, 0x86, 0xbc, 0x36, 0x75, 0x3f, 0x19, 0xea, 0xb7, 0xec, + 0x80, 0xac, 0x51, 0xa4, 0x11, 0xbe, 0x39, 0xe, 0xc7, 0x7, + 0x1f, 0x81, 0xaf, 0xd5, 0x6d, 0x36, 0xdc, 0x5b, 0x5a, 0x41, + 0x1e, 0x31, 0xb5, 00, 0xfd, 0x2b, 0xe1, 0xaf, 0xd8, 0x7, + 0xc1, 0x42, 0xdf, 0xc2, 0x5a, 0x7d, 0xf3, 0xa0, 0x7, 0x50, + 0x9e, 0x4b, 0x89, 0x6, 0x39, 0xfd, 0xd9, 0x91, 0x54, 0x9f, + 0xc8, 0x57, 0xdd, 0xb0, 0x1e, 0x73, 0x8c, 0x57, 0xd1, 0x52, + 0x8f, 0x2c, 0x11, 0xf5, 0x74, 0x23, 0xcb, 0x4d, 0x22, 0xed, + 0xba, 0xf2, 0x2b, 0x4e, 0x11, 0xd2, 0xb3, 0xed, 0xfa, 0x8a, + 0xd1, 0x83, 0xb5, 0x6c, 0x6e, 0x5d, 0x84, 0x64, 0xd6, 0x84, + 0x2b, 0xf2, 0x8a, 0xa5, 0x6, 0x3d, 0x2b, 0x42, 0x1e, 0x82, + 0x80, 0x2d, 0x44, 0x33, 0x8a, 0xb9, 0x18, 0xaa, 0xd0, 0x81, + 0x9a, 0xb7, 0x18, 0xa0, 0xb, 0x11, 0xe, 0x95, 0x65, 0x2a, + 0x8, 0x85, 0x59, 0x51, 0xc5, 00, 0x3d, 0x47, 0x6a, 0x90, + 0x75, 0xa6, 0x2f, 0x5a, 0x91, 0x68, 0x1, 0xcb, 0x52, 0xe, + 0x94, 0xc5, 0xed, 0x4f, 0xa0, 0x2, 0x9c, 0x3a, 0x53, 0x69, + 0xc2, 0x80, 0x16, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0xc, 0x19, 0xd, 0x7c, 0xaf, 0xfb, 0x7b, 0x78, 0x9d, 0x2c, + 0x7e, 0x1f, 0x69, 0x3a, 0x32, 0xb9, 0x5b, 0x8b, 0xeb, 0xc1, + 0x21, 0x50, 0x7a, 0xc6, 0x80, 0xe7, 0xf5, 0x2b, 0x5f, 0x54, + 0x49, 0x8c, 0xd7, 0xe7, 0xff, 00, 0xed, 0xfd, 0xae, 0x3d, + 0xdf, 0xc4, 0xed, 0x3, 0x4d, 0x2f, 0xfb, 0xbb, 0x3b, 0x47, + 0x75, 0x4f, 0x4f, 0x30, 0xa9, 0xfc, 0x7e, 0xed, 0x78, 0x39, + 0xe5, 0x57, 0x4b, 0x1, 0x51, 0xad, 0xde, 0x9f, 0x79, 0xf3, + 0x3c, 0x47, 0x59, 0xd1, 0xcb, 0x2a, 0x35, 0xbb, 0xd3, 0xef, + 0x3a, 0x6f, 0xd9, 0x3e, 0xd0, 0x5b, 0x68, 0x53, 0x5c, 0x63, + 0x6, 0x47, 0xc6, 0x7f, 0x12, 0x2b, 0xea, 0x3d, 0x32, 0xef, + 0xa, 0x39, 0x15, 0xf3, 0x57, 0xec, 0xe7, 0x8b, 0x3f, 0x7, + 0x5b, 0x8e, 0x85, 0x8b, 0x1f, 0xfc, 0x78, 0xd7, 0xbb, 0x69, + 0xf7, 0xf8, 0xc7, 0x3c, 0x56, 0xd9, 0x45, 0x2f, 0x65, 0x82, + 0xa7, 0x1f, 0x23, 0x7c, 0x8a, 0x8a, 0xa1, 0x97, 0x52, 0x8a, + 0xec, 0x77, 0xb6, 0xd7, 0x9e, 0xf5, 0xa5, 0xd, 0xef, 0x1d, + 0x45, 0x71, 0xb0, 0x5f, 0x71, 0xd7, 0xf4, 0xad, 0x18, 0x2f, + 0xc7, 0x73, 0x5e, 0xc1, 0xef, 0x9d, 0x64, 0x77, 0xbe, 0xf5, + 0x38, 0xbf, 0xf7, 0xae, 0x5d, 0x6f, 0xf1, 0xfc, 0x54, 0xe1, + 0xa8, 0xfb, 0xd0, 0x7, 0x48, 0xf7, 0xa1, 0x87, 0x27, 0x8a, + 0xcf, 0xba, 0xd3, 0xf4, 0xfb, 0xe6, 0xdd, 0x3d, 0xbc, 0x72, + 0xb7, 0xab, 0x28, 0x26, 0xb2, 0x9b, 0x51, 0xe3, 0xad, 0x20, + 0xd4, 0xbd, 0xff, 00, 0x4a, 00, 0xbb, 0xff, 00, 0x8, + 0xd6, 0x8f, 0xb8, 0x30, 0xb4, 0x8c, 0x1f, 0xa0, 0xad, 0x5b, + 0x4f, 0x26, 0xc6, 0x30, 0x90, 0xa8, 0x45, 0x1d, 0x85, 0x73, + 0xe3, 0x52, 0x3e, 0xbf, 0xa5, 0x3c, 0x6a, 0x5e, 0xf4, 0x1, + 0xd3, 0xfd, 0xbb, 0xde, 0x94, 0x5e, 0xfb, 0xd7, 0x32, 0x35, + 0x2f, 0x7a, 0x7a, 0xea, 0x78, 0xef, 0x40, 0x1d, 0x20, 0xbc, + 0xcf, 0x7a, 0x77, 0xdb, 0x7d, 0xeb, 0x9a, 0x1a, 0x96, 0x7b, + 0xd3, 0xff, 00, 0xb4, 0xb8, 0xeb, 0xfa, 0x50, 0x7, 0x46, + 0x2f, 0x5, 0x2f, 0xda, 0x81, 0xae, 0x74, 0x6a, 0x5e, 0xf4, + 0xe1, 0xa8, 0xfb, 0xd0, 0x7, 0x43, 0xf6, 0xa1, 0xeb, 0x47, + 0xda, 0x47, 0xad, 0x60, 0x7f, 0x68, 0x7b, 0x8a, 0x70, 0xd4, + 0x7, 0xad, 00, 0x6f, 0xfd, 0xa0, 0x7a, 0xd2, 0x89, 0xd7, + 0xd6, 0xb0, 0x7e, 0xde, 0x3d, 0x7f, 0x4a, 0x51, 0x7e, 0x3d, + 0x68, 0x3, 0x7b, 0xce, 0x5f, 0x5a, 0x5f, 0x35, 0x7d, 0x6b, + 0xc, 0x5f, 0x83, 0xde, 0x94, 0x5f, 0x8c, 0xf5, 0xfd, 0x28, + 0x3, 0x6f, 0xcc, 0x5f, 0x5a, 0x50, 0xe0, 0xf7, 0xac, 0x5f, + 0xb6, 0x8f, 0x51, 0x4f, 0x17, 0xdc, 0x75, 0xa0, 0xd, 0x7d, + 0xc3, 0xd6, 0x97, 0x22, 0xb2, 0x3e, 0xdb, 0xcf, 0xde, 0xa7, + 0x7d, 0xbb, 0xfd, 0xaa, 00, 0xd5, 0xcd, 0x19, 0xac, 0xc1, + 0x7d, 0xef, 0x4e, 0x17, 0xbc, 0xf5, 0x14, 0x1, 0xa5, 0x45, + 0x67, 0x7d, 0xb7, 0xde, 0x97, 0xed, 0xbe, 0xff, 00, 0xa5, + 00, 0x68, 0x51, 0x54, 0x45, 0xe7, 0xa9, 0xfd, 0x29, 0xdf, + 0x6d, 0xf7, 0x14, 0x1, 0x72, 0x8a, 0xa8, 0x2f, 0x33, 0xdc, + 0x53, 0xbe, 0xd6, 0x3d, 0x68, 0x2, 0xcd, 0x15, 0x5c, 0x5d, + 0x8c, 0x76, 0xa3, 0xed, 0x62, 0x80, 0x2c, 0x51, 0x50, 0xfd, + 0xa5, 0x73, 0x4a, 0x2e, 0x14, 0xd0, 0x4, 0xb4, 0x54, 0x7e, + 0x7a, 0xfa, 0xd2, 0x89, 0x94, 0xf7, 0xa0, 0x7, 0xd1, 0x4c, + 0xf3, 0x54, 0xf7, 0xa5, 0xde, 0x3d, 0x68, 0x1, 0x71, 0x46, + 0x7, 0xa5, 0x20, 0x71, 0xeb, 0x46, 0xe1, 0xeb, 0x40, 0xb, + 0x8a, 0x31, 0x46, 0x45, 0x2d, 00, 0x21, 0x50, 0x7a, 0x8c, + 0xfd, 0x69, 0x86, 0x8, 0xc8, 0xc1, 0x45, 0x3f, 0xf0, 0x1a, + 0x92, 0x8a, 00, 0x81, 0xac, 0x6d, 0xdf, 0xef, 0x5b, 0xc4, + 0xdf, 0x54, 0x6, 0xa2, 0x6d, 0x1e, 0xc5, 0xf3, 0x9b, 0x48, + 0x3f, 0xef, 0xd8, 0xab, 0x94, 0x50, 0x6, 0x63, 0xf8, 0x6f, + 0x4c, 0x90, 0x61, 0xac, 0x60, 0x3f, 0xf6, 0xcc, 0x7f, 0x85, + 0x56, 0x93, 0xc1, 0x7a, 0x2c, 0xbd, 0x74, 0xe8, 0x3f, 0x8, + 0xc7, 0xf8, 0x56, 0xe5, 0x14, 0x1, 0xcd, 0x3f, 0xc3, 0xbd, + 0x2, 0x4c, 0xee, 0xd3, 0xa2, 0x39, 0xff, 00, 0x64, 0x7f, + 0x85, 0x55, 0x93, 0xe1, 0x47, 0x86, 0x65, 0xfb, 0xda, 0x6c, + 0x5f, 0x82, 0x8f, 0xf0, 0xae, 0xbe, 0x8a, 00, 0xe1, 0x25, + 0xf8, 0x29, 0xe1, 0x49, 0xb3, 0x9d, 0x3c, 0xc, 0xfa, 0x6d, + 0xff, 00, 0xa, 0xa3, 0x37, 0xc0, 0x1f, 0x8, 0xcd, 0xd6, + 0xc4, 0xff, 00, 0xe3, 0xbf, 0xfc, 0x4d, 0x7a, 0x4d, 0x27, + 0x4a, 00, 0xf2, 0x69, 0xff, 00, 0x66, 0xaf, 0x8, 0x4c, + 0x78, 0xb4, 0x23, 0xf1, 0x5f, 0xfe, 0x26, 0xb3, 0xee, 0x7f, + 0x65, 0xaf, 0x9, 0xcb, 0xd2, 0xdf, 0xf3, 0xda, 0x7f, 0xf6, + 0x5a, 0xf6, 0x9a, 0x5a, 00, 0xf0, 0x1b, 0x9f, 0xd9, 0x1b, + 0xc2, 0xd3, 0x67, 0x16, 0xeb, 0xf9, 0xaf, 0xff, 00, 0x13, + 0x59, 0x97, 0x1f, 0xb1, 0xb7, 0x87, 0x1c, 0x7c, 0x90, 0xf, + 0xcd, 0x7f, 0xf8, 0x9a, 0xfa, 0x46, 0x92, 0x80, 0x3e, 0x56, + 0xbb, 0xfd, 0x89, 0x74, 0x49, 0x18, 0xec, 0xb5, 0x52, 0x3d, + 0x9d, 0x7, 0xf4, 0xac, 0x8b, 0x9f, 0xd8, 0x73, 0x4d, 0x6c, + 0x95, 0xb4, 0x39, 0x3c, 0xf1, 0x22, 0x7f, 0x85, 0x7d, 0x81, + 0x45, 00, 0x7c, 0x4f, 0x77, 0xfb, 0xa, 0x5a, 0x91, 0xf2, + 0x58, 0x96, 0xfa, 0x3a, 0x7f, 0x85, 0x63, 0xdd, 0x7e, 0xc2, + 0xb, 0xce, 0x34, 0xd9, 0x8e, 0x3d, 0x1d, 0x4f, 0xf4, 0xaf, + 0xbc, 0x68, 0xa0, 0xf, 0xcf, 0x6b, 0xbf, 0xd8, 0x3d, 0xf9, + 0x2b, 0xa6, 0x4d, 0xf8, 0xed, 0xff, 00, 0xa, 0xc4, 0xbc, + 0xfd, 0x84, 0xee, 0x50, 0x1c, 0x69, 0x13, 0xfe, 0x1b, 0x7f, + 0xc2, 0xbf, 0x48, 0xf0, 0x3d, 0x29, 0x36, 0x29, 0xec, 0x3f, + 0x2a, 00, 0xfc, 0xc0, 0xbb, 0xfd, 0x86, 0xee, 0xc1, 0x3f, + 0xf1, 0x2a, 0x9f, 0x3, 0xd4, 0x2f, 0xf8, 0x56, 0x2d, 0xdf, + 0xec, 0x45, 0x7c, 0xb9, 0xff, 00, 0x89, 0x3c, 0xdf, 0x92, + 0xff, 00, 0x85, 0x7e, 0xac, 0x18, 0x90, 0xf5, 0x45, 0x3f, + 0x85, 0x31, 0xac, 0xe0, 0x71, 0x83, 0x12, 0x91, 0xf4, 0xa0, + 0xf, 0xc9, 0xb, 0xbf, 0xd8, 0xaa, 0xf9, 0x3f, 0xe6, 0xf, + 0x3f, 0xfd, 0xf2, 0x3f, 0xc2, 0xb1, 0xee, 0xff, 00, 0x63, + 0x1b, 0xe5, 0x27, 0xfe, 0x24, 0xf2, 0x91, 0xec, 0xa3, 0xfc, + 0x2b, 0xf6, 0x9, 0xb4, 0xab, 0x47, 0xeb, 0x2, 0x9a, 0x82, + 0x4f, 0xe, 0x69, 0xb2, 0xe7, 0x75, 0xa2, 0x1c, 0xfb, 0x9f, + 0xf1, 0xa0, 0xf, 0xc6, 0xbb, 0xaf, 0xd8, 0xea, 0xf5, 0x3f, + 0xe6, 0xd, 0x3f, 0xfd, 0xf2, 0x3f, 0xc2, 0xb1, 0xaf, 0x3f, + 0x64, 0x2b, 0xc5, 0x3f, 0xf2, 0x6, 0x98, 0xe7, 0xd5, 0x47, + 0xf8, 0x57, 0xed, 0x23, 0xf8, 0x3b, 0x47, 0x90, 0x73, 0x64, + 0xa7, 0xfe, 0x4, 0xdf, 0xe3, 0x55, 0x66, 0xf8, 0x79, 0xa0, + 0x4d, 0xf7, 0xec, 0x47, 0xa7, 0xe, 0xc3, 0xfa, 0xd0, 0x7, + 0xe2, 0x75, 0xcf, 0xec, 0x93, 0x74, 0x3a, 0xe8, 0xb3, 0xff, + 00, 0xdf, 0x23, 0xfc, 0x2b, 0x26, 0xe7, 0xf6, 0x51, 0xb8, + 0x4c, 0xff, 00, 0xc4, 0x9e, 0x71, 0xff, 00, 0x1, 0x1f, + 0xe1, 0x5f, 0xb7, 0x92, 0x7c, 0x28, 0xf0, 0xd4, 0xbd, 0x6c, + 0x4f, 0xe1, 0x23, 0x7f, 0x8d, 0x54, 0x9b, 0xe0, 0xbf, 0x85, + 0xe6, 0x4, 0x1b, 0x16, 0xff, 00, 0xbf, 0x8d, 0xfe, 0x34, + 0x1, 0xf8, 0x77, 0x71, 0xfb, 0x2c, 0x5c, 0x27, 0xfc, 0xc2, + 0x6e, 0x3f, 00, 0x3f, 0xc2, 0xb3, 0x6e, 0x3f, 0x66, 0x19, + 0xd3, 0xfe, 0x61, 0xb7, 0x4b, 0xf8, 0x7f, 0xf5, 0xab, 0xf7, + 0x22, 0x6f, 0x80, 0x1e, 0x13, 0x98, 0x93, 0xf6, 0x47, 0x19, + 0xff, 00, 0xa6, 0x8d, 0xfe, 0x35, 0x42, 0x7f, 0xd9, 0xbb, + 0xc2, 0x92, 0xe7, 0x10, 0xb8, 0xcf, 0xfb, 0x4c, 0x7f, 0xf6, + 0x6a, 00, 0xfc, 0x34, 0x9b, 0xf6, 0x6a, 0xb8, 0x5c, 0xe2, + 0xc6, 0xe3, 0x8f, 0x43, 0xff, 00, 0xd6, 0xac, 0xdb, 0x8f, + 0xd9, 0xd2, 0xea, 0x3c, 0xe2, 0xd6, 0xe4, 0x7e, 0x35, 0xfb, + 0x99, 0x71, 0xfb, 0x2d, 0xf8, 0x56, 0x50, 0x7f, 0x76, 0xd9, + 0xfa, 0xb7, 0xff, 00, 0x15, 0x59, 0x37, 0x1f, 0xb2, 0x3f, + 0x86, 0xa5, 0x27, 0x6a, 0xb8, 0xfa, 0x93, 0xff, 00, 0xc5, + 0x50, 0x7, 0xe1, 0xd4, 0xbf, 0xb3, 0xfd, 0xea, 0xf4, 0x82, + 0x7f, 0xce, 0xa9, 0x4b, 0xf0, 0x27, 0x51, 0x4f, 0xf9, 0x61, + 0x38, 0xff, 00, 0x3f, 0x4a, 0xfd, 0xbd, 0xba, 0xfd, 0x8e, + 0x34, 0x29, 0x33, 0xb5, 0x9, 0xff, 00, 0x81, 0x1f, 0xfe, + 0x2a, 0xb2, 0x6e, 0x7f, 0x62, 0x8d, 0x1e, 0x40, 0x76, 0xa3, + 0x73, 0xfe, 0xd1, 0xff, 00, 0xe2, 0xe8, 0x3, 0xf1, 0x2e, + 0x5f, 0x82, 0x9a, 0xa2, 0x74, 0x8a, 0x6f, 0xc4, 0xf, 0xf0, + 0xaa, 0x92, 0xfc, 0x1f, 0xd5, 0xd3, 0xa5, 0xbc, 0xbf, 0x90, + 0xaf, 0xda, 0x9b, 0xaf, 0xd8, 0x76, 0xc1, 0xb3, 0xb6, 0x22, + 0xc0, 0xff, 00, 0xb6, 0x7f, 0xf8, 0xba, 0xc9, 0xb9, 0xfd, + 0x85, 0x2d, 0xdb, 0x25, 0x6d, 0x5b, 0xf0, 0x93, 0xff, 00, + 0xb3, 0xa0, 0xf, 0xc6, 0x29, 0x7e, 0x15, 0x6a, 0xe9, 0x9f, + 0xdc, 0x48, 0x3e, 0xab, 0x54, 0xe4, 0xf8, 0x6f, 0xad, 0x27, + 0xfc, 0xba, 0xc8, 0x47, 0xfb, 0xbf, 0xfd, 0x7a, 0xfd, 0x91, + 0xbc, 0xfd, 0x84, 0x41, 0xc9, 0x5b, 0x66, 0xfa, 0x6f, 0x1f, + 0xfc, 0x5d, 0x60, 0xdd, 0x7e, 0xc2, 0x52, 0xe4, 0xe2, 0xcd, + 0xb1, 0xea, 0x1c, 0x1f, 0xfd, 0x9e, 0x80, 0x3f, 0x21, 0x1f, + 0xc0, 0x9a, 0xc4, 0x7d, 0x6c, 0xe5, 0xff, 00, 0xbe, 0x6a, + 0xbb, 0xf8, 0x3f, 0x56, 0x4e, 0xb6, 0x52, 0xfe, 0x55, 0xfa, + 0xd5, 0x77, 0xfb, 0xc, 0xce, 0x9, 0xff, 00, 0x45, 0x71, + 0xf5, 0x60, 0x7f, 0xf6, 0x7a, 0xc4, 0xbb, 0xfd, 0x87, 0xae, + 0xc0, 0xff, 00, 0x8f, 0x46, 0x3f, 0xf0, 0x30, 0x3f, 0xf6, + 0x7a, 00, 0xfc, 0xaa, 0x7f, 0xd, 0x6a, 0x69, 0xd6, 0xca, + 0x5f, 0xca, 0xa2, 0x6d, 0xe, 0xfd, 0x3a, 0xda, 0x4a, 0x3f, + 0xe0, 0x35, 0xfa, 0x83, 0x79, 0xfb, 0x12, 0xde, 0x27, 0xfc, + 0xb9, 0xb0, 0xfa, 0xb8, 0xff, 00, 0xe2, 0xeb, 0x16, 0xeb, + 0xf6, 0x2e, 0xbd, 00, 0xe2, 0xd0, 0xb7, 0xfc, 0x8, 0xf, + 0xfd, 0x9e, 0x80, 0x3f, 0x35, 0x1b, 0x4b, 0xbb, 0x5e, 0xb6, + 0xd2, 0x8f, 0xf8, 0x1, 0xa8, 0xcd, 0x94, 0xeb, 0xd6, 0x17, + 0x1f, 0x55, 0xaf, 0xd1, 0x4b, 0xdf, 0xd8, 0xda, 0xf6, 0x3c, + 0x9f, 0xb1, 0x30, 0xfa, 0x48, 0x3f, 0xf8, 0xaa, 0xc5, 0xb9, + 0xfd, 0x90, 0x6f, 0x39, 0xff, 00, 0x42, 0x27, 0xeb, 0x20, + 0xff, 00, 0xe2, 0xa8, 0x3, 0xe0, 0x33, 0x6f, 0x28, 0xeb, + 0x1b, 0xf, 0xc2, 0x98, 0x51, 0x87, 0x55, 0x23, 0xf0, 0xaf, + 0xba, 0xae, 0x3f, 0x64, 0x5b, 0xb5, 0xce, 0x6c, 0x1b, 0xf0, + 0x90, 0x7f, 0xf1, 0x55, 0x8f, 0x75, 0xfb, 0x28, 0x5c, 0x26, + 0x7f, 0xd0, 0x5b, 0xfe, 0xfb, 0x1f, 0xfc, 0x55, 00, 0x7c, + 0x5b, 0xb4, 0xd2, 0x60, 0x8a, 0xfa, 0xfa, 0xe3, 0xf6, 0x53, + 0xb8, 0xc9, 0xcd, 0x8b, 0x1f, 0xfb, 0x68, 0x3f, 0xf8, 0xaa, + 0xcb, 0xb9, 0xfd, 0x96, 0xe5, 0x4e, 0xb6, 0x6e, 0x31, 0xff, + 00, 0x4d, 0x7, 0xff, 00, 0x15, 0x40, 0x1f, 0x2a, 0xd1, + 0x5f, 0x4a, 0x5d, 0x7e, 0xcc, 0x92, 0xa1, 0x23, 0xec, 0xad, + 0x9f, 0xfa, 0xe9, 0xff, 00, 0xd9, 0x56, 0x74, 0xff, 00, + 0xb3, 0x6c, 0xb1, 0xe7, 0x36, 0xee, 0x3d, 0xf7, 0xf, 0xfe, + 0x2a, 0x80, 0x3e, 0x7c, 0xa2, 0xbd, 0xce, 0x5f, 0xd9, 0xde, + 0x75, 0xce, 0xd8, 0xdb, 0xf3, 0xff, 00, 0xec, 0xaa, 0x94, + 0xbf, 00, 0x6e, 0xd0, 0x1c, 0x46, 0xdf, 0x98, 0xff, 00, + 0xe2, 0xa8, 0x3, 0xc6, 0x68, 0xaf, 0x58, 0x9b, 0xe0, 0x5d, + 0xfa, 0x7d, 0xd5, 0x3f, 0xa7, 0xff, 00, 0x15, 0x54, 0x66, + 0xf8, 0x29, 0xaa, 0x2e, 0x76, 0xaf, 0x4f, 0x71, 0xfe, 0x34, + 0x1, 0xe6, 0xb4, 0x57, 0x7b, 0x27, 0xc2, 0x1d, 0x55, 0x7, + 0x4f, 0xe5, 0xfe, 0x35, 0x9d, 0x71, 0xf0, 0xd3, 0x57, 0x83, + 0xfe, 0x59, 0x83, 0xf8, 0x8f, 0xf1, 0xa0, 0xe, 0x4e, 0xbb, + 0xef, 0x84, 0x9a, 0x1f, 0xf6, 0xd7, 0x8b, 0xf4, 0xbb, 0x6f, + 0x2c, 0xcb, 0xbe, 0x50, 0x76, 0x8e, 0xf5, 0xce, 0xcd, 0xe0, + 0xcd, 0x52, 0xf, 0xbd, 00, 0xc7, 0xfb, 0xc2, 0xbd, 0xaf, + 0xf6, 0x4d, 0xf0, 0x8d, 0xd6, 0xa5, 0xf1, 0x4b, 0x4f, 0x8e, + 0x58, 0x76, 0xa2, 0x37, 0x2d, 0x91, 0xc7, 0xeb, 0x40, 0x1f, + 0xb1, 0xbf, 00, 0xfc, 0x3e, 0x34, 0x2f, 00, 0x69, 0xb0, + 0xec, 0xd8, 0xc5, 0x32, 0x47, 0xe7, 0x5d, 0xee, 0xa8, 0xf8, + 0x1f, 0x85, 0x55, 0xf0, 0x95, 0x8a, 0xe9, 0xfa, 0x25, 0x9c, + 0x28, 0xbb, 0x55, 0x23, 0x3, 0x14, 0xed, 0x59, 0xe8, 0x3, + 0x99, 0xd4, 0xa4, 0xeb, 0x5c, 0x96, 0xaf, 0x2e, 0x14, 0xd7, + 0x49, 0xa9, 0xc9, 0xc9, 0xae, 0x43, 0x58, 0x97, 0xad, 00, + 0x72, 0x5a, 0xd4, 0xd8, 0xd, 0xcd, 0x78, 0x7, 0xc4, 0xbd, + 0x43, 0x2f, 0x27, 0x22, 0xbd, 0xbf, 0xc4, 0x37, 0x1e, 0x5c, + 0x52, 0x12, 0x71, 0xc1, 0xaf, 0x9a, 0xfe, 0x24, 0x5f, 0xe5, + 0xa5, 0x3b, 0xab, 0xc8, 0xcc, 0x67, 0xcb, 0x4e, 0xc7, 0x87, + 0x9a, 0xd4, 0xe5, 0xa5, 0x63, 0xc4, 0x7c, 0x4f, 0x71, 0xe6, + 0x5c, 0xbf, 0x22, 0xb8, 0xd, 0x52, 0x4e, 0x5a, 0xba, 0xed, + 0x6e, 0x6d, 0xf3, 0x48, 0x73, 0x9a, 0xe2, 0x35, 0x49, 0x39, + 0x6a, 0xf9, 0x2c, 0x3a, 0xe6, 0x9d, 0xcf, 0x84, 0xc2, 0xae, + 0x69, 0xb6, 0x62, 0x5c, 0xb7, 0x26, 0xb3, 0x9d, 0x4c, 0x92, + 0x2a, 0xaf, 0x25, 0x8e, 00, 0xfc, 0x6a, 0xe5, 0xc3, 0x67, + 0x35, 0xa1, 0xe0, 0x4d, 0x14, 0x78, 0x93, 0xc6, 0xba, 0x4e, + 0x9a, 0xd9, 0x2b, 0x71, 0x38, 0x52, 0x1, 0xc7, 0x41, 0x9f, + 0xe9, 0x5f, 0x45, 0x46, 0x3a, 0xd8, 0xfa, 0xda, 0x11, 0xbb, + 0x48, 0xfd, 0x50, 0xfd, 0x92, 0xbc, 0x26, 0xbe, 0x1c, 0xf0, + 0x46, 0x99, 0x6e, 0x51, 0x92, 0x4b, 0x7b, 0x34, 0xc, 0xad, + 0xd9, 0xdb, 0x96, 0xfe, 0x66, 0xbe, 0x88, 0x84, 0x71, 0x5e, + 0x7f, 0xf0, 0x8b, 0x4b, 0x8e, 0xc3, 0xc3, 0x61, 0xe3, 0x5d, + 0x8b, 0x23, 0x10, 0x3e, 0x8a, 0x48, 0x1f, 0xca, 0xbd, 0xe, + 0x11, 0xd3, 0x15, 0xf4, 0x2b, 0x45, 0x63, 0xea, 0x56, 0x8a, + 0xc5, 0xdb, 0x61, 0x92, 0x31, 0x5a, 0x50, 0x8a, 0xa3, 0x6e, + 0x3a, 0x56, 0x84, 0x23, 0xa5, 0x31, 0x97, 0x60, 0x5a, 0xd0, + 0x8b, 0x8c, 0x55, 0x38, 00, 0xc5, 0x5e, 0x88, 0x50, 0x5, + 0xa8, 0xbd, 0x6a, 0xec, 0x63, 0xa5, 0x55, 0x88, 0x70, 0x2a, + 0xd4, 0x62, 0x80, 0x2d, 0x45, 0x56, 0x16, 0xab, 0xc4, 0x3a, + 0x55, 0x95, 0xa0, 0x7, 0xad, 0x3c, 0x76, 0xa6, 0xe, 0x95, + 0x20, 0xeb, 0x40, 0xf, 0x1d, 0x69, 0xd4, 0x8b, 0x4b, 0x40, + 0xa, 0x3a, 0xd3, 0xa9, 0xab, 0x4e, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0xe, 0x7e, 0x43, 0x8a, 0xfc, + 0xd7, 0xfd, 0xb8, 0xaf, 0x4d, 0xcf, 0xed, 0x4, 0xe9, 0x9c, + 0xa4, 0x56, 0x10, 0x20, 0x19, 0xcf, 0x3f, 0x36, 0x7f, 0xa5, + 0x7e, 0x94, 0x4d, 0x93, 0x5f, 0x98, 0x9f, 0xb6, 0x89, 0xc7, + 0xed, 0xd, 0x7f, 0x81, 0x8f, 0xdc, 0xc5, 0xfc, 0xda, 0xbe, + 0x67, 0x88, 0x3f, 0xdc, 0xd2, 0xee, 0xd1, 0xf1, 0xfc, 0x51, + 0xae, 0x5, 0x47, 0xbc, 0x91, 0xec, 0xff, 00, 0x6, 0xee, + 0x45, 0xa7, 0x85, 0x6c, 0x50, 0x1f, 0xe1, 0x3f, 0xcc, 0xd7, + 0xac, 0x58, 0xea, 0x20, 0x1, 0xcf, 0xeb, 0x5e, 0x19, 0xf0, + 0xce, 0xf3, 0xc9, 0xd0, 0x6c, 0xd7, 0x3d, 0x13, 0xfa, 0x9a, + 0xf4, 0x7b, 0x4d, 0x4f, 0x81, 0xcd, 0x7b, 0xb8, 0x68, 0xf2, + 0xd1, 0x82, 0xf2, 0x47, 0xd2, 0x60, 0xe3, 0xc9, 0x87, 0x84, + 0x7c, 0x91, 0xe9, 0x16, 0xda, 0x96, 0x40, 0xff, 00, 0x1a, + 0xd0, 0x8f, 0x51, 0xc7, 0xff, 00, 0xae, 0xbc, 0xfe, 0xdb, + 0x56, 0xc6, 0x39, 0x1f, 0x9d, 0x68, 0x47, 0xab, 0xae, 0x39, + 0x75, 0x1f, 0x8d, 0x74, 0x9d, 0x87, 0x72, 0xba, 0x98, 0x1d, + 0xea, 0x41, 0xa9, 0x3, 0xde, 0xb8, 0x71, 0xae, 0x44, 0x3f, + 0xe5, 0xa2, 0xfe, 0x62, 0x9d, 0xfd, 0xbf, 0x8, 0x1f, 0xeb, + 0x17, 0xfe, 0xfa, 0xa9, 0xe6, 0x5d, 0xc9, 0xe6, 0x8a, 0xea, + 0x76, 0xaf, 0xa8, 0x8c, 0x75, 0xa8, 0xff, 00, 0xb4, 0x7d, + 0xff, 00, 0x5a, 0xe3, 0x5b, 0x5f, 0x87, 0x1f, 0xeb, 0x17, + 0xfe, 0xfa, 0x14, 0xc5, 0xd7, 0xa3, 0xcf, 0xdf, 0x5f, 0xfb, + 0xea, 0x8e, 0x65, 0xdc, 0x39, 0xa3, 0xdc, 0xed, 0xc6, 0xa5, + 0xef, 0x4f, 0x1a, 0x8f, 0xbd, 0x71, 0x43, 0x5b, 0x42, 0x7f, + 0xd6, 0x2f, 0xfd, 0xf4, 0x2a, 0x45, 0xd6, 0x54, 0xff, 00, + 0x1a, 0x9f, 0xf8, 0x15, 0x3b, 0xa1, 0xdd, 0x77, 0x3b, 0x41, + 0xa9, 0x7b, 0xd3, 0x86, 0xa3, 0xef, 0x5c, 0x62, 0xeb, 0x2b, + 0x9f, 0xbc, 0xbf, 0x9d, 0x48, 0xba, 0xb8, 0x3d, 0xc7, 0xe7, + 0x45, 0xc2, 0xe8, 0xec, 0x46, 0xa5, 0xef, 0x4f, 0x1a, 0x8f, + 0xbd, 0x71, 0xa3, 0x56, 0x19, 0xea, 0x3f, 0x3a, 0x72, 0xea, + 0xd9, 0xee, 0x3f, 0x3a, 0x63, 0x3b, 0x2f, 0xed, 0x2f, 0x7a, + 0x70, 0xd4, 0x7d, 0xeb, 0x8f, 0x1a, 0xaf, 0xb8, 0xfc, 0xe9, + 0xeb, 0xaa, 0xfb, 0x8f, 0xce, 0x80, 0x3b, 0x1, 0xa8, 0xe3, + 0xbd, 0x38, 0x6a, 0x5e, 0xf5, 0xc8, 0x2e, 0xab, 0xc7, 0x51, + 0xf9, 0xd3, 0x97, 0x55, 0xe3, 0xa8, 0xfc, 0xe8, 0x3, 0xaf, + 0x1a, 0x8f, 0xbd, 0x38, 0x6a, 0x3e, 0xf5, 0xc8, 0x8d, 0x50, + 0x7a, 0x8f, 0xce, 0x9c, 0x35, 0x4c, 0xf7, 0x1f, 0x9d, 00, + 0x75, 0xcb, 0xa8, 0x8f, 0xf2, 0x69, 0xe3, 0x51, 0xf7, 0xae, + 0x45, 0x75, 0x41, 0xea, 0x3f, 0x3a, 0x70, 0xd4, 0xc7, 0x5c, + 0x8f, 0xce, 0x80, 0x3a, 0xe1, 0xa8, 0xfb, 0xd3, 0x86, 0xa3, + 0xef, 0x5c, 0x90, 0xd5, 0x3d, 0xc7, 0xe7, 0x4f, 0x1a, 0x98, + 0xf5, 0x1f, 0x9d, 00, 0x75, 0xa3, 0x51, 0xf7, 0xa7, 0xd, + 0x47, 0xdf, 0xf5, 0xae, 0x48, 0x6a, 0x63, 0xd4, 0x7e, 0x74, + 0xe1, 0xa9, 0x7b, 0xfe, 0xb4, 0x1, 0xd6, 0x8d, 0x47, 0xde, + 0x9d, 0xfd, 0xa3, 0xef, 0x5c, 0x98, 0xd4, 0xbd, 0xc7, 0xe7, + 0x4e, 0x1a, 0x9f, 0xb8, 0xfc, 0xe8, 0x3, 0xad, 0xfe, 0xd1, + 0xf7, 0xa7, 0xd, 0x4a, 0xb9, 0x2f, 0xed, 0x2f, 0x71, 0xf9, + 0xd3, 0x86, 0xa5, 0xee, 0x7, 0xe3, 0x40, 0x1d, 0x68, 0xd4, + 0x47, 0xaf, 0xeb, 0x4f, 0x1a, 0x97, 0x3d, 0x6b, 0x92, 0xfe, + 0xd2, 0xf7, 0x1f, 0x9d, 0x38, 0x6a, 0x5e, 0xe3, 0xf3, 0xa0, + 0xe, 0xb4, 0x6a, 0x3e, 0xf4, 0xe1, 0xa8, 0x8f, 0x5a, 0xe4, + 0x86, 0xa5, 0xee, 0xf, 0xe3, 0x4e, 0xfe, 0xd1, 0xf7, 0xfd, + 0x68, 0x3, 0xad, 0xfe, 0xd1, 0x14, 0xe1, 0xa8, 0xa, 0xe4, + 0xc6, 0xa4, 0x3d, 0x45, 0x38, 0x6a, 0x7e, 0xe2, 0x80, 0x3a, + 0xc5, 0xd4, 0x7, 0xad, 0x38, 0x6a, 0x3, 0xd7, 0xf5, 0xae, + 0x4c, 0x6a, 0x5e, 0xe2, 0x9c, 0x35, 0x3f, 0x7f, 0xd6, 0x80, + 0x3a, 0xd1, 0xa8, 0xf, 0x5a, 0x51, 0x7e, 0xf, 0x53, 0x5c, + 0xa0, 0xd4, 0xfd, 0xe9, 0xcb, 0xa9, 0x67, 0xb8, 0xa0, 0xe, + 0xaf, 0xed, 0xc0, 0xff, 00, 0xfa, 0xe9, 0xdf, 0x6d, 0x1d, + 0x8d, 0x72, 0x83, 0x52, 0x1e, 0xbf, 0xad, 0x3c, 0x6a, 0x7e, + 0xe2, 0x80, 0x3a, 0xa1, 0x7a, 0x3d, 0x69, 0xc2, 0xf7, 0xde, + 0xb9, 0x51, 0xa9, 0xf3, 0xd4, 0x53, 0x97, 0x52, 0xf7, 0x1f, + 0x9d, 00, 0x75, 0x3f, 0x6d, 0x1e, 0xb9, 0xa7, 0xb, 0xce, + 0x3a, 0xd7, 0x2e, 0x35, 0x2f, 0x71, 0xf9, 0xd3, 0x86, 0xa5, + 0xee, 0x28, 0x3, 0xa8, 0x17, 0x83, 0xb7, 0xf3, 0xa5, 0x17, + 0xbc, 0xd7, 0x30, 0x35, 0x2f, 0x7f, 0xd6, 0x9c, 0x35, 0x2f, + 0x71, 0x40, 0x1d, 0x38, 0xbc, 0xf7, 0xa5, 0x17, 0x9e, 0xff, + 00, 0xad, 0x73, 0x23, 0x52, 0xe7, 0xa8, 0xa7, 0x8d, 0x48, + 0x7a, 0x8a, 00, 0xe9, 0x85, 0xed, 0x28, 0xbc, 0x15, 0xcd, + 0xd, 0x47, 0xdc, 0x53, 0x86, 0xa3, 0x8e, 0xe3, 0xf3, 0xa0, + 0xe, 0x97, 0xed, 0x82, 0x8f, 0xb5, 0x8a, 0xe7, 0x6, 0xa3, + 0xee, 0x29, 0xdf, 0xda, 0x3, 0xdb, 0xf3, 0xa0, 0xe, 0x8b, + 0xed, 0x6b, 0x4e, 0xfb, 0x4a, 0xf7, 0xae, 0x74, 0x6a, 0x23, + 0xdb, 0xf3, 0xa7, 0x8d, 0x40, 0x63, 0xa8, 0xa0, 0xd, 0xff, + 00, 0xb4, 0x25, 0x28, 0x9d, 0x6b, 00, 0x6a, 0x3e, 0xe2, + 0x9e, 0x35, 0x1, 0xea, 0x28, 0x3, 0x74, 0x4e, 0xa6, 0x97, + 0xcd, 0x5f, 0x5a, 0xc2, 0x1a, 0x80, 0xf5, 0xfd, 0x69, 0xdf, + 0x6f, 0x1e, 0xb4, 0x1, 0xb8, 0x24, 0x53, 0xde, 0x8d, 0xe3, + 0xd6, 0xb1, 0x45, 0xf8, 0xf5, 0xfd, 0x69, 0xc2, 0xfb, 0xfd, + 0xaf, 0xd6, 0x80, 0x36, 0x77, 0xf, 0x5a, 0x32, 0x3d, 0x6b, + 0x23, 0xed, 0xde, 0xff, 00, 0xad, 0x38, 0x5f, 0xf, 0x5f, + 0xd6, 0x80, 0x35, 0x73, 0x46, 0x6b, 0x33, 0xed, 0xc0, 0xf7, + 0xa5, 0xfb, 0x6f, 0xbf, 0xeb, 0x40, 0x1a, 0x74, 0x56, 0x70, + 0xbd, 0xf7, 0xa7, 0xb, 0xdf, 0x7a, 00, 0xbf, 0x45, 0x52, + 0x17, 0xb9, 0xef, 0x4b, 0xf6, 0xcc, 0xf7, 0xa0, 0xb, 0x94, + 0x55, 0x4f, 0xb6, 0x53, 0x85, 0xd8, 0xf6, 0xa0, 0xb, 0x34, + 0x55, 0x71, 0x74, 0xd, 0x28, 0xba, 0x6, 0x80, 0x27, 0xa2, + 0xa1, 0x17, 0x22, 0x8f, 0xb4, 0xad, 00, 0x4d, 0x45, 0x46, + 0x27, 0x53, 0x47, 0x9c, 0xb4, 0x1, 0x25, 0x14, 0xcf, 0x35, + 0x7d, 0x68, 0xf3, 0x17, 0xd6, 0x80, 0x1f, 0x45, 0x37, 0x70, + 0x3d, 0xe9, 0x77, 0xf, 0x5a, 00, 0x5a, 0x29, 0x32, 0x28, + 0xcd, 00, 0x18, 0xcd, 0x21, 0x40, 0x7a, 0x80, 0x69, 0x73, + 0x4b, 0x40, 0x11, 0x98, 0x50, 0xff, 00, 0x2, 0xfe, 0x42, + 0x9a, 0xd6, 0x90, 0xb7, 0x58, 0x63, 0x3f, 0x55, 0x15, 0x35, + 0x14, 0x1, 0x51, 0xf4, 0xab, 0x37, 0x3f, 0x35, 0xb4, 0x47, + 0xfe, 0x2, 0x2a, 0x17, 0xf0, 0xfe, 0x9d, 0x27, 0xde, 0xb3, + 0x88, 0xff, 00, 0xc0, 0x6b, 0x46, 0x8a, 00, 0xc6, 0x93, + 0xc1, 0xfa, 0x34, 0xa3, 0xe6, 0xd3, 0xe2, 0x3f, 0x9f, 0xf8, + 0xd5, 0x69, 0x7c, 0x1, 0xa1, 0xca, 0x72, 0x6c, 0x22, 0xfa, + 0x60, 0xff, 00, 0x8d, 0x74, 0x54, 0x50, 0x7, 0x21, 0x37, + 0xc2, 0xcf, 0xf, 0x4d, 0xf7, 0xac, 0x23, 0x19, 0xf4, 0x7, + 0xfc, 0x6a, 0x8c, 0xff, 00, 0x6, 0x3c, 0x3b, 0x36, 0x7f, + 0xd1, 0x51, 0x7f, 0x3, 0xfe, 0x35, 0xde, 0xd1, 0x40, 0x1e, + 0x65, 0x71, 0xf0, 0xf, 0xc3, 0x93, 0xff, 00, 0xcb, 0xbc, + 0x63, 0xfe, 0x2, 0x7f, 0xf8, 0xaa, 0xce, 0x9f, 0xf6, 0x6c, + 0xf0, 0xe4, 0xc4, 0xe1, 0x11, 0x33, 0xfe, 0xc1, 0x3f, 0xfb, + 0x35, 0x7a, 0xf5, 0x14, 0x1, 0xe2, 0x33, 0xfe, 0xcb, 0x5e, + 0x1e, 0x94, 0x70, 0x63, 0xfc, 0x63, 0x3f, 0xfc, 0x55, 0x66, + 0x5d, 0x7e, 0xc8, 0xfa, 0xc, 0xdf, 0x74, 0xc6, 0x3f, 0xed, + 0x99, 0xff, 00, 0xe2, 0xab, 0xe8, 0x1a, 0x28, 0x3, 0xe6, + 0x9b, 0x9f, 0xd8, 0xdf, 0x48, 0x93, 0x38, 0x68, 0xcf, 0x6f, + 0xf5, 0x7f, 0xfd, 0x9d, 0x63, 0xdd, 0xfe, 0xc5, 0x56, 0x12, + 0x29, 0xc2, 0xc7, 0x93, 0xdc, 0x2f, 0xff, 00, 0x67, 0x5f, + 0x57, 0x51, 0x40, 0x1f, 0x1b, 0x5e, 0xfe, 0xc4, 0x36, 0xec, + 0xa7, 0x6c, 0x6a, 0x7e, 0x8b, 0xff, 00, 0xd9, 0xd7, 0x15, + 0xad, 0xfe, 0xc4, 0x2e, 0xa4, 0xec, 0xb6, 0x61, 0xf4, 0x4c, + 0xff, 00, 0xec, 0xf5, 0xf7, 0xee, 0x2a, 0x39, 0x24, 0x8, + 0x3d, 0x68, 0x3, 0xf3, 0x1f, 0x5a, 0xfd, 0x8c, 0x2e, 0x60, + 0x66, 0xc5, 0xb3, 0x8c, 0x67, 0xfe, 0x59, 0x7f, 0xf6, 0x55, + 0xd9, 0x7e, 0xcf, 0x7f, 0xb3, 0x87, 0xfc, 0x22, 0x3e, 0x2a, + 0x17, 0x93, 0x5b, 0xe1, 0x94, 0x9c, 0x12, 0x98, 0xc7, 0xfe, + 0x3c, 0x6b, 0xef, 0x5b, 0xb9, 0x51, 0x94, 0x83, 0x83, 0x5c, + 0xfd, 0xda, 0x44, 0x8e, 0x59, 0x54, 0x6, 0xf5, 0xcd, 00, + 0x66, 0x8, 0x44, 0x11, 0x6d, 0x1c, 0x60, 0x57, 0x3f, 0xab, + 0xc9, 0x5b, 0x77, 0x97, 0x38, 0xcd, 0x73, 0x3a, 0xad, 0xc0, + 0x39, 0xa0, 0xe, 0x73, 0x52, 0x93, 0x93, 0x5c, 0x6e, 0xb1, + 0x27, 0xde, 0xae, 0xa7, 0x52, 0x90, 0x73, 0xcd, 0x71, 0x5a, + 0xcc, 0xb8, 0xdd, 0x40, 0x1c, 0x1f, 0x8c, 0xae, 0xbc, 0xab, + 0x39, 0x7d, 0xeb, 0xe5, 0xef, 0x88, 0x97, 0xd9, 0x32, 0x57, + 0xd0, 0xbf, 0x10, 0xaf, 0x76, 0x5b, 0x30, 0x4, 0x67, 0x15, + 0xf2, 0xdf, 0x8f, 0xaf, 0xb, 0x3b, 0x8e, 0x39, 0x3d, 0xab, + 0xe6, 0x73, 0x5a, 0x9d, 0xf, 0x8f, 0xce, 0xea, 0x7d, 0x93, + 0xcd, 0x75, 0x39, 0x32, 0x58, 0xe6, 0xb8, 0xed, 0x49, 0xf2, + 0xed, 0x5d, 0x46, 0xa7, 0x27, 0x6, 0xb8, 0xfb, 0xf7, 0xcb, + 0x9a, 0xf1, 0xf0, 0xb1, 0x3c, 0xc, 0xc, 0x7a, 0x99, 0x93, + 0xb5, 0x7a, 0xbf, 0xec, 0x9b, 0xa3, 0x36, 0xaf, 0xf1, 0x96, + 0xc9, 0xf6, 0x16, 0x4b, 0x48, 0x64, 0x9f, 0x76, 0xde, 0x1, + 0x18, 0x3, 0x9e, 0xdd, 0x4d, 0x79, 0x25, 0xc3, 0x72, 0x6b, + 0xea, 0xcf, 0xd8, 0x33, 0xc3, 0xd, 0x7b, 0xa9, 0x6b, 0x7a, + 0x83, 0xc, 0x16, 0x92, 0x18, 0x22, 0x60, 0x33, 0x9f, 0xbd, + 0xbb, 0xfa, 0x57, 0xd2, 0xe1, 0xa3, 0x79, 0x23, 0xeb, 0xf0, + 0xb1, 0xbc, 0xd1, 0xfa, 0x49, 0xe0, 0xfb, 0x53, 0x69, 0xe1, + 0xeb, 0x8, 0xca, 0xed, 0x6f, 0x28, 0x12, 0x3d, 0xcf, 0x26, + 0xba, 0x58, 0x6b, 0x3e, 0xda, 0x31, 0x1a, 0xaa, 0x8e, 0x2, + 0x8c, 0xa, 0xd1, 0x80, 0x66, 0xbd, 0x93, 0xe8, 0xb, 0xf6, + 0xfd, 0x45, 0x69, 0x42, 0x2b, 0x3e, 0x1, 0xd2, 0xb4, 0x21, + 0x1c, 0xd0, 0x5, 0xf8, 0x32, 0x2a, 0xec, 0x43, 0xa5, 0x54, + 0x84, 0x55, 0xd8, 0x86, 00, 0xa0, 0xb, 0x91, 0xc, 0x62, + 0xad, 0x47, 0x55, 0xa2, 0x19, 0xab, 0x51, 0x8e, 0x5, 00, + 0x59, 0x88, 0xd4, 0xeb, 0x50, 0xc5, 0x53, 0xaf, 0x6a, 00, + 0x90, 0x75, 0xa7, 0xad, 0x30, 0x75, 0xa9, 0x7, 0x4a, 00, + 0x70, 0xe9, 0x4b, 0x45, 0x14, 00, 0xab, 0x4e, 0xa4, 0x1d, + 0x29, 0x68, 00, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, + 0x3, 0x9e, 0x92, 0xbf, 0x33, 0x3f, 0x6e, 0x2b, 0x17, 0xb0, + 0xfd, 0xa1, 0x26, 0x76, 0xce, 0xc9, 0xec, 0xe1, 0x90, 0x12, + 0x38, 0xe7, 0x76, 0x47, 0xe1, 0x5f, 0xa6, 0xb2, 0x62, 0xbf, + 0x3e, 0x7f, 0xe0, 0xa1, 0x1a, 0xb, 0x43, 0xe3, 0xed, 0x27, + 0x59, 0x4, 0x5, 0x68, 0x4, 0xd, 0x8e, 0xa4, 0x80, 0x2b, + 0xc1, 0xce, 0xe9, 0xb9, 0xe1, 0x1b, 0x5d, 0x1a, 0x67, 0xcc, + 0xf1, 0x15, 0x27, 0x53, 0x2, 0xe4, 0xbe, 0xcb, 0x4c, 0xab, + 0xe0, 0x8d, 0x41, 0x61, 0xd1, 0x6d, 0xe, 0xe0, 0x6, 0xce, + 0xb9, 0xae, 0xc3, 0xfe, 0x12, 0x48, 0x20, 0x4f, 0xf5, 0xc9, + 0x9f, 0xf7, 0xab, 0xc6, 0xbc, 0x37, 0xad, 0x81, 0xa0, 0x5b, + 0xa0, 0x27, 0x85, 0xeb, 0x9f, 0x7a, 0xa5, 0xa9, 0x78, 0xbc, + 0xdb, 0xe5, 0x72, 0x49, 0x1d, 0xf3, 0xff, 00, 0xd7, 0xad, + 0x16, 0x36, 0x34, 0xe8, 0xc5, 0xf9, 0x1a, 0xc7, 0x31, 0x85, + 0x3c, 0x34, 0x1a, 0xec, 0x8f, 0x6b, 0x6f, 0x1d, 0xc7, 0x1f, + 0x1e, 0x7c, 0x60, 0x7f, 0xbd, 0xff, 00, 0xd7, 0xaa, 0xf2, + 0xfc, 0x43, 0x84, 0x7f, 0xcb, 0xd4, 0x7f, 0xf7, 0xdf, 0xff, + 00, 0x5e, 0xbe, 0x73, 0xd4, 0x7c, 0x70, 0x70, 0x70, 0xcd, + 0xff, 00, 0x7d, 0x7f, 0xf5, 0xeb, 0x9f, 0xba, 0xf1, 0xbc, + 0xc4, 0x9d, 0xac, 0xe7, 0xfe, 0x4, 0x7f, 0xc6, 0xbc, 0x3a, + 0xf9, 0xbd, 0xb6, 0x3e, 0x73, 0x13, 0x9f, 0x59, 0xd9, 0x1f, + 0x52, 0x37, 0xc4, 0x6b, 0x71, 0xff, 00, 0x2f, 0x71, 0x7f, + 0xdf, 0x7f, 0xfd, 0x7a, 0x89, 0xbe, 0x24, 0xdb, 0xff, 00, + 0xcf, 0xdc, 0x7f, 0xf7, 0xdf, 0xff, 00, 0x5e, 0xbe, 0x54, + 0x6f, 0x18, 0xdc, 0x1f, 0xe2, 0x71, 0xf5, 0x63, 0xfe, 0x34, + 0xd3, 0xe2, 0xbb, 0x82, 0x7e, 0xfb, 0xf, 0xf8, 0x11, 0xff, + 00, 0x1a, 0xf2, 0xe5, 0x9b, 0xce, 0xe7, 0x8d, 0x2c, 0xfa, + 0xa7, 0x43, 0xea, 0xb3, 0xf1, 0x2a, 0xdf, 0x1f, 0xf1, 0xf7, + 0x1f, 0xfd, 0xf7, 0xff, 00, 0xd7, 0xa7, 0xc7, 0xf1, 0x22, + 0xdc, 0xe3, 0xfd, 0x2e, 0x3f, 0xfb, 0xe8, 0x7f, 0x8d, 0x7c, + 0x9e, 0x7c, 0x55, 0x71, 0x9f, 0xbe, 0xdf, 0xf7, 0xd1, 0xff, + 00, 0x1a, 0x72, 0xf8, 0xbe, 0xe0, 0x7f, 0x13, 0x7f, 0xdf, + 0x47, 0xfc, 0x68, 0x59, 0xbc, 0xc1, 0x67, 0xd5, 0x3b, 0x1f, + 0x5b, 0x2f, 0xc4, 0x7b, 0x73, 0xff, 00, 0x2f, 0x71, 0xff, + 00, 0xdf, 0x7f, 0xfd, 0x7a, 0xb1, 0x1f, 0xc4, 0x78, 0x30, + 0x3f, 0xd2, 0xe2, 0xff, 00, 0xbf, 0x9f, 0xfd, 0x7a, 0xf9, + 0x19, 0x7c, 0x65, 0x70, 0x3f, 0x89, 0xbf, 0x33, 0xfe, 0x35, + 0x61, 0x7c, 0x6f, 0x32, 0xf7, 0x7f, 0xfb, 0xe8, 0xff, 00, + 0x8d, 0x68, 0xb3, 0x99, 0x1a, 0xac, 0xfe, 0x7d, 0x4f, 0xae, + 0x63, 0xf8, 0x8d, 0xf, 0xfc, 0xfd, 0xc5, 0xff, 00, 0x7f, + 0x3f, 0xfa, 0xf5, 0x61, 0x3e, 0x23, 0x43, 0xc7, 0xfa, 0x5c, + 0x5f, 0xf7, 0xdf, 0xff, 00, 0x5e, 0xbe, 0x44, 0x4f, 0x1e, + 0x4c, 0x3b, 0xbf, 0xfd, 0xf5, 0xff, 00, 0xd7, 0xa9, 0x93, + 0xc7, 0xf2, 0xff, 00, 0x79, 0xff, 00, 0xef, 0xa3, 0xfe, + 0x35, 0xb2, 0xce, 0xa4, 0x6c, 0xb8, 0x86, 0x48, 0xfa, 0xf1, + 0x7e, 0x23, 0x43, 0x9f, 0xf8, 0xfb, 0x8b, 0xfe, 0xfb, 0xff, + 00, 0xeb, 0xd5, 0x84, 0xf8, 0x8b, 0x17, 0xfc, 0xfd, 0x45, + 0xff, 00, 0x7d, 0xff, 00, 0xf5, 0xeb, 0xe4, 0x34, 0xf8, + 0x81, 0x20, 0x3f, 0x79, 0xff, 00, 0xef, 0xa3, 0xfe, 0x35, + 0x62, 0x3f, 0x88, 0x8f, 0xfd, 0xf6, 0xff, 00, 0xbe, 0xbf, + 0xfa, 0xf5, 0xa2, 0xce, 0x9f, 0x73, 0x65, 0xc4, 0x4c, 0xfa, + 0xf1, 0x3e, 0x22, 0x42, 0x7f, 0xe5, 0xe6, 0x33, 0xff, 00, + 0x2, 0xff, 00, 0xeb, 0xd5, 0x84, 0xf8, 0x85, 0xf, 0xfc, + 0xfc, 0x27, 0xfd, 0xf5, 0xff, 00, 0xd7, 0xaf, 0x90, 0xd3, + 0xe2, 0x33, 0x9f, 0xe3, 0x71, 0xff, 00, 0x2, 0xff, 00, + 0xeb, 0xd5, 0x98, 0xfe, 0x23, 0x38, 0xff, 00, 0x96, 0x8f, + 0xff, 00, 0x7d, 0x7f, 0xf5, 0xeb, 0x58, 0xe7, 0x7e, 0x66, + 0xf1, 0xe2, 0x23, 0xeb, 0xa4, 0xf1, 0xfc, 0x1f, 0xf3, 0xf1, + 0x1f, 0xfd, 0xf5, 0xff, 00, 0xd7, 0xa9, 0xe3, 0xf1, 0xfd, + 0xbf, 0xfc, 0xf7, 0x8f, 0xfe, 0xfa, 0xff, 00, 0xeb, 0xd7, + 0xc8, 0xc9, 0xf1, 0x21, 0x87, 0xfc, 0xb4, 0x6f, 0xfb, 0xeb, + 0xff, 00, 0xaf, 0x56, 0x63, 0xf8, 0x92, 0xc7, 0xf8, 0xdb, + 0xfe, 0xfa, 0xff, 00, 0xeb, 0xd6, 0xeb, 0x3b, 0x46, 0xf1, + 0xe2, 0x24, 0x7d, 0x6c, 0xbe, 0x3b, 0xb5, 0x3f, 0xf2, 0xde, + 0x3f, 0xfb, 0xe8, 0x7f, 0x8d, 0x4a, 0x9e, 0x39, 0xb5, 0x3f, + 0xf2, 0xde, 0x3f, 0xfb, 0xe8, 0x7f, 0x8d, 0x7c, 0x9a, 0x9f, + 0x12, 0x1b, 0xfb, 0xed, 0xff, 00, 0x7d, 0x7f, 0xf5, 0xea, + 0xca, 0x7c, 0x49, 0x3c, 0x65, 0xd8, 0x7f, 0xc0, 0xbf, 0xfa, + 0xf5, 0xa2, 0xce, 0x93, 0x36, 0x5c, 0x40, 0x99, 0xf5, 0x7a, + 0x78, 0xd6, 0xd0, 0x8f, 0xf5, 0xe9, 0xf8, 0x11, 0xfe, 0x35, + 0x30, 0xf1, 0x8d, 0xa1, 0xff, 00, 0x97, 0x84, 0xfc, 0xc7, + 0xf8, 0xd7, 0xca, 0x71, 0xfc, 0x4a, 0x27, 0xa3, 0x37, 0xfd, + 0xf5, 0xff, 00, 0xd7, 0xab, 0x31, 0xfc, 0x48, 0x3d, 0xd9, + 0xbf, 0xef, 0xaf, 0xfe, 0xbd, 0x6a, 0xb3, 0x88, 0xb3, 0x75, + 0x9f, 0xc0, 0xfa, 0xa5, 0x3c, 0x61, 0x66, 0xc3, 0xfe, 0x3e, + 0x13, 0xfe, 0xfa, 0x1f, 0xe3, 0x52, 0xaf, 0x8b, 0x2d, 0x1b, + 0xfe, 0x5e, 0x63, 0xff, 00, 0xbe, 0x87, 0xf8, 0xd7, 0xcb, + 0x51, 0xfc, 0x46, 0xc8, 0xfb, 0xcf, 0xff, 00, 0x7d, 0x7f, + 0xf5, 0xea, 0xcc, 0x7f, 0x11, 0xf1, 0x8e, 0x58, 0xff, 00, + 0xc0, 0xbf, 0xfa, 0xf5, 0xaa, 0xcd, 0xe0, 0xcd, 0x96, 0x7b, + 0x4c, 0xfa, 0x80, 0x78, 0xa6, 0xd4, 0xff, 00, 0xcb, 0xcc, + 0x7f, 0xf7, 0xd0, 0xa9, 0x57, 0xc4, 0xf6, 0xa4, 0xf, 0xf4, + 0x98, 0xff, 00, 0xef, 0xb1, 0x5f, 0x31, 0x47, 0xf1, 0x14, + 0x67, 0xef, 0x37, 0xe7, 0xff, 00, 0xd7, 0xab, 0x9, 0xf1, + 0x10, 0x1f, 0xe2, 0x6f, 0xfb, 0xeb, 0xff, 00, 0xaf, 0x5a, + 0x2c, 0xd6, 0xc, 0xd5, 0x67, 0x74, 0xd9, 0xf4, 0xc8, 0xf1, + 0x25, 0xb7, 0xfc, 0xfd, 0x47, 0xff, 00, 0x7d, 0x8f, 0xf1, + 0xa9, 0x7, 0x88, 0xed, 0xcf, 0xfc, 0xbc, 0x45, 0xff, 00, + 0x7d, 0xf, 0xf1, 0xaf, 0x9b, 0x23, 0xf8, 0x86, 0x8, 0xfb, + 0xcd, 0xff, 00, 0x7d, 0x7f, 0xf5, 0xea, 0xc4, 0x7f, 0x10, + 0x47, 0xf7, 0x9b, 0xfe, 0xfa, 0xff, 00, 0xeb, 0xd6, 0x8b, + 0x33, 0x81, 0xaa, 0xce, 0x29, 0xb3, 0xe8, 0xf1, 0xe2, 0x18, + 0x3b, 0x5c, 0x47, 0xff, 00, 0x7d, 0xf, 0xf1, 0xa7, 0x8d, + 0x7e, 0x1f, 0xf9, 0xef, 0x1f, 0xfd, 0xf4, 0x3f, 0xc6, 0xbe, + 0x75, 0x8f, 0xe2, 0x6, 0x7f, 0x89, 0xbf, 0xef, 0xaf, 0xfe, + 0xbd, 0x58, 0x4f, 0x88, 0x1f, 0xed, 0xb7, 0xfd, 0xf5, 0xff, + 00, 0xd7, 0xab, 0x59, 0x95, 0x36, 0x6a, 0xb3, 0x6a, 0x4c, + 0xfa, 0x17, 0xfb, 0x76, 0x23, 0xff, 00, 0x2d, 0x93, 0xfe, + 0xfa, 0xa9, 0x6, 0xb9, 0x19, 0xe9, 0x22, 0xff, 00, 0xdf, + 0x55, 0xf3, 0xf2, 0x78, 0xf8, 0x90, 0x3e, 0x76, 0xff, 00, + 0xbe, 0xbf, 0xfa, 0xf5, 0x61, 0x3c, 0x7c, 0x7f, 0xbe, 0xdf, + 0xf7, 0xd7, 0xff, 00, 0x5e, 0xad, 0x66, 0x14, 0xd9, 0x6b, + 0x33, 0xa4, 0xcf, 0x7d, 0x1a, 0xd4, 0x64, 0xff, 00, 0xac, + 0x5f, 0xfb, 0xea, 0x9e, 0x35, 0x94, 0x3f, 0xf2, 0xd1, 0x4f, + 0xe3, 0x5e, 0x10, 0x9e, 0x3d, 0x38, 0xfb, 0xed, 0xff, 00, + 0x7d, 0x7f, 0xf5, 0xea, 0xc2, 0x78, 0xf4, 0x9f, 0xe2, 0x6f, + 0xfb, 0xeb, 0xff, 00, 0xaf, 0x5a, 0x2c, 0x6d, 0x36, 0x6a, + 0xb3, 0xa, 0x4c, 0xf7, 0x21, 0xac, 0x27, 0xf7, 0xd7, 0xf3, + 0xa7, 0xd, 0x5d, 0x73, 0xf7, 0xd7, 0xf3, 0xaf, 0x13, 0x4f, + 0x1e, 0xb6, 0x7e, 0xf1, 0xfc, 0xff, 00, 0xfa, 0xf5, 0x3a, + 0xf8, 0xf1, 0x8f, 0xf1, 0x37, 0xe7, 0xff, 00, 0xd7, 0xab, + 0x58, 0xba, 0x6f, 0xa9, 0xa2, 0xc7, 0x52, 0x7d, 0x4f, 0x68, + 0x1a, 0xc2, 0xff, 00, 0x79, 0x7f, 0x3a, 0x72, 0xea, 0xc9, + 0xfd, 0xf5, 0xfc, 0xeb, 0xc7, 0x13, 0xc7, 0x7c, 0x8e, 0x5b, + 0xf3, 0xff, 00, 0xeb, 0xd5, 0x88, 0xfc, 0x75, 0x8f, 0x5f, + 0xcf, 0xff, 00, 0xaf, 0x56, 0xb1, 0x34, 0xdf, 0x52, 0xfe, + 0xb9, 0x49, 0xf5, 0x3d, 0x79, 0x75, 0x65, 0xfe, 0xfa, 0xfe, + 0x74, 0xe1, 0xab, 0x2e, 0x7e, 0xfa, 0xfe, 0x75, 0xe4, 0xcb, + 0xe3, 0x91, 0xef, 0xf9, 0xff, 00, 0xf5, 0xea, 0x65, 0xf1, + 0xba, 0xf7, 0xce, 0x3e, 0xbf, 0xfd, 0x7a, 0xaf, 0x6f, 0x4f, + 0xb9, 0x6b, 0x13, 0x49, 0xf5, 0x3d, 0x58, 0x6a, 0xa9, 0xfd, + 0xf5, 0xfc, 0xe9, 0xc3, 0x56, 0x4f, 0xef, 0xaf, 0xe7, 0x5e, + 0x5a, 0x9e, 0x36, 0x8c, 0xf6, 0x3f, 0x9f, 0xff, 00, 0x5e, + 0xa6, 0x4f, 0x19, 0x46, 0x7b, 0x1f, 0xce, 0xab, 0xdb, 0x41, + 0xf5, 0x2f, 0xdb, 0xd3, 0xee, 0x7a, 0x78, 0xd5, 0x53, 0xfb, + 0xeb, 0xf9, 0xd3, 0x86, 0xa8, 0xb8, 0xfb, 0xeb, 0xf9, 0xd7, + 0x99, 0xaf, 0x8b, 0xe2, 0x27, 0xf8, 0xbf, 0x3a, 0x99, 0x7c, + 0x59, 0x17, 0xab, 0x7e, 0x62, 0xab, 0xda, 0x43, 0xb8, 0xd5, + 0x58, 0x3e, 0xa7, 0xa4, 0xd, 0x55, 0x7f, 0xbe, 0xbf, 0x9d, + 0x3c, 0x6a, 0xab, 0xfd, 0xf5, 0xfc, 0xeb, 0xce, 0x57, 0xc5, + 0x31, 0x1e, 0x85, 0xbf, 0x31, 0x53, 0x27, 0x89, 0xa3, 0x3c, + 0x64, 0x8f, 0xc6, 0x9f, 0x3c, 0x7b, 0x95, 0xed, 0x23, 0xdc, + 0xf4, 0x21, 0xaa, 0xa0, 0xfe, 0x35, 0xfc, 0xe9, 0xc3, 0x55, + 0x5f, 0xef, 0xaf, 0xe7, 0x5e, 0x7e, 0x9e, 0x21, 0x8d, 0xba, + 0x31, 0xfc, 0xea, 0x45, 0xd7, 0x93, 0xfb, 0xe7, 0xf3, 0xa7, + 0xcc, 0xbb, 0x95, 0xcd, 0x1e, 0xe7, 0x7e, 0x35, 0x55, 0xfe, + 0xf2, 0xfe, 0x74, 0xf1, 0xaa, 0x2f, 0xf7, 0x87, 0xe7, 0x5c, + 0x12, 0x6b, 0x88, 0x7a, 0x37, 0xeb, 0x52, 0xae, 0xb2, 0xb8, + 0xfb, 0xc7, 0xf3, 0xaa, 0xba, 0x1d, 0xd1, 0xdd, 0x7f, 0x6a, + 0xf, 0xef, 0xf, 0xce, 0x9c, 0x35, 0x45, 0xfe, 0xf0, 0xfc, + 0xeb, 0x86, 0x1a, 0xc0, 0x3f, 0xc4, 0x7f, 0x3a, 0x7a, 0xea, + 0xf9, 0x1d, 0x4f, 0xe7, 0x40, 0xce, 0xe0, 0x6a, 0x8b, 0x8f, + 0xbc, 0x3f, 0x3a, 0x70, 0xd5, 0x17, 0xfb, 0xc3, 0xf3, 0xae, + 0x24, 0x6a, 0xbc, 0x75, 0x3f, 0x9d, 0x38, 0x6a, 0xa4, 0xe, + 0xa7, 0xf3, 0xa0, 0xe, 0xdd, 0x75, 0x41, 0xfd, 0xe1, 0xf9, + 0xd3, 0x86, 0xa8, 0x3f, 0xbc, 0x3f, 0x3a, 0xe2, 0x6, 0xac, + 0x71, 0xd4, 0xd4, 0x83, 0x55, 0xc7, 0x52, 0x7f, 0x3a, 00, + 0xed, 0x46, 0xa8, 0xbf, 0xde, 0x1f, 0x9d, 0x3f, 0xfb, 0x50, + 0x7f, 0x78, 0x7e, 0x75, 0xc4, 0x8d, 0x54, 0x9e, 0xe7, 0xf3, + 0xa7, 0x8d, 0x57, 0x8e, 0xf4, 0x1, 0xda, 0x8d, 0x50, 0x63, + 0xef, 0xf, 0xce, 0x9c, 0x35, 0x41, 0xfd, 0xe1, 0xf9, 0xd7, + 0x14, 0x35, 0x43, 0x8e, 0xf4, 0xe5, 0xd5, 0x7e, 0xbf, 0x9d, + 00, 0x76, 0xa3, 0x54, 0x5f, 0xef, 0xf, 0xce, 0x9e, 0x35, + 0x41, 0xfd, 0xe5, 0xfc, 0xeb, 0x8a, 0x1a, 0xaf, 0xd7, 0xf3, + 0xa7, 0x8d, 0x4f, 0x9e, 0xa6, 0x80, 0x3b, 0x41, 0xaa, 0x2f, + 0xf7, 0x87, 0xe7, 0x4e, 0x1a, 0xa0, 0xfe, 0xf0, 0xfc, 0xeb, + 0x8c, 0x1a, 0xa7, 0xb9, 0xa7, 0xd, 0x53, 0x9e, 0xa7, 0xf3, + 0xa0, 0xe, 0xcc, 0x6a, 0x83, 0xfb, 0xc3, 0xf3, 0xa7, 0x8d, + 0x50, 0x7f, 0x78, 0x7e, 0x75, 0xc5, 0x8d, 0x4b, 0xdc, 0xd3, + 0x86, 0xa5, 0xd3, 0x93, 0x40, 0x1d, 0xa0, 0xd5, 0x7, 0xf7, + 0x87, 0xe7, 0x4f, 0x1a, 0xa2, 0xff, 00, 0x79, 0x7f, 0x3a, + 0xe2, 0xc6, 0xa5, 0xcf, 0x53, 0x4f, 0x1a, 0x97, 0xb9, 0xa0, + 0xe, 0xc8, 0x6a, 0x8a, 0x3f, 0x8c, 0x7e, 0x74, 0xf1, 0xaa, + 0x2f, 0xf7, 0x87, 0xe7, 0x5c, 0x5f, 0xf6, 0x97, 0xb9, 0xa7, + 0x8d, 0x48, 0x9e, 0xe6, 0x80, 0x3b, 0x31, 0xaa, 0x3, 0xfc, + 0x43, 0xf3, 0xa7, 0xd, 0x51, 0x7f, 0xbc, 0xbf, 0x9d, 0x71, + 0x83, 0x52, 0xe3, 0xa9, 0xa7, 0xd, 0x47, 0xdc, 0xd0, 0x7, + 0x66, 0x35, 0x35, 0xcf, 0xde, 0x5f, 0xce, 0x9c, 0x35, 0x35, + 0xcf, 0xde, 0x5f, 0xce, 0xb8, 0xd1, 0xa9, 0x7b, 0x9f, 0xce, + 0x9c, 0x35, 0x2f, 0x73, 0x40, 0x1d, 0x97, 0xf6, 0x92, 0xff, + 00, 0x7c, 0x7e, 0x74, 0xe1, 0xa9, 0x2f, 0xf7, 0x97, 0xf3, + 0xae, 0x34, 0x6a, 0x5e, 0xe7, 0xf3, 0xa7, 0x8d, 0x4b, 0xde, + 0x80, 0x3b, 0x11, 0xa9, 0x2f, 0xf7, 0x97, 0xf3, 0xa7, 0xd, + 0x41, 0x3f, 0xbc, 0x3f, 0x3a, 0xe3, 0x46, 0xa5, 0xc7, 0x53, + 0xf9, 0xd3, 0xd7, 0x53, 0xf7, 0xa0, 0xe, 0xc7, 0xfb, 0x45, + 0x7f, 0xbe, 0xbf, 0x9d, 0x2a, 0xea, 0x9, 0xfd, 0xe1, 0xf9, + 0xd7, 0x1e, 0x35, 0x2f, 0x7f, 0xd6, 0x9c, 0x35, 0x2f, 0x73, + 0xf9, 0xd0, 0x7, 0x60, 0x35, 0x5, 0xfe, 0xf0, 0x1f, 0x8d, + 0x38, 0x6a, 0xa, 0x3f, 0x88, 0x7e, 0x75, 0xc7, 0x8d, 0x4b, + 0x3d, 0xcd, 0x3c, 0x6a, 0x5e, 0xe7, 0xf3, 0xa0, 0xe, 0xbf, + 0xed, 0xeb, 0xfd, 0xf1, 0xf9, 0xd3, 0xbe, 0xde, 0xf, 0xf1, + 0xf, 0xce, 0xb9, 0xf, 0xed, 0x2f, 0x73, 0xf9, 0xd3, 0x86, + 0xa5, 0xee, 0x7f, 0x3a, 00, 0xeb, 0x85, 0xfa, 0xff, 00, + 0x78, 0x7e, 0x74, 0xe1, 0x7e, 0x3f, 0xbc, 0x3f, 0x3a, 0xe4, + 0x86, 0xa5, 0xee, 0x7f, 0x3a, 0x70, 0xd4, 0x7d, 0xce, 0x3e, + 0xb4, 0x1, 0xd6, 0x7d, 0xbc, 0x7f, 0x78, 0x7e, 0x74, 0xe1, + 0x7c, 0xbf, 0xde, 0x1f, 0x9d, 0x72, 0x5f, 0xda, 0x5e, 0xe6, + 0x9e, 0x35, 0x1c, 0xf7, 0x3f, 0x9d, 00, 0x75, 0x82, 0xf5, + 0x7f, 0xbc, 0x29, 0x45, 0xea, 0x8e, 0xe2, 0xb9, 0x41, 0xa9, + 0x7b, 0x9f, 0xce, 0x9e, 0x35, 0x2f, 0x7a, 00, 0xea, 0x85, + 0xea, 0x9e, 0xe2, 0x97, 0xed, 0x8b, 0xea, 0x2b, 0x96, 0x1a, + 0x8f, 0x3d, 0x4f, 0xe7, 0x4e, 0x1a, 0x91, 0xf5, 0x3f, 0x9d, + 00, 0x75, 0x2, 0xed, 0x7d, 0x47, 0xe7, 0x4a, 0x2e, 0x90, + 0xf7, 0x1f, 0x9d, 0x73, 0x3, 0x52, 0xf7, 0x34, 0xf1, 0xa8, + 0xfb, 0x9a, 00, 0xe9, 0x7e, 0xd2, 0x9e, 0xa3, 0xf3, 0xa5, + 0x17, 0x9, 0xfd, 0xe1, 0xf9, 0xd7, 0x36, 0x35, 0x1f, 0xad, + 0x3b, 0xfb, 0x47, 0xeb, 0xf9, 0xd0, 0x7, 0x47, 0xe7, 0xa7, + 0xf7, 0xa8, 0xf3, 0x93, 0xfb, 0xc2, 0xb9, 0xe1, 0xa8, 0x7d, + 0x7f, 0x3a, 0x51, 0xa8, 0x7d, 0x7f, 0x3a, 00, 0xe8, 0x44, + 0xc8, 0x7f, 0x88, 0x7e, 0x74, 0x86, 0x74, 0x1f, 0xc4, 0x3f, + 0x3a, 0xc2, 0xfe, 0xd0, 0xe3, 0xa9, 0xa8, 0x5f, 0x50, 0xeb, + 0xc9, 0xfc, 0xe8, 0x3, 0x72, 0x5b, 0xd5, 0x3, 0xa8, 0xac, + 0xeb, 0x8b, 0xe5, 0x19, 0xcb, 0xa, 0xc9, 0x9b, 0x51, 0xe3, + 0x82, 0x6b, 0x32, 0xeb, 0x51, 0x3c, 0xf2, 0x68, 0x3, 0x4e, + 0xeb, 0x50, 0x1c, 0xfc, 0xc2, 0xb1, 0x6e, 0xf5, 0x1, 0xcf, + 0xcc, 0x2a, 0x85, 0xd6, 0xa1, 0xd7, 0x9a, 0xc7, 0xbb, 0xd4, + 0x31, 0x9e, 0x4d, 00, 0x5a, 0xbe, 0xbf, 0x5c, 0x1f, 0x98, + 0x7e, 0x75, 0xcd, 0x6a, 0x97, 0xcb, 0xfd, 0xe1, 0x51, 0x5f, + 0x6a, 0x39, 0xee, 0x6b, 0x9c, 0xd4, 0x75, 0xc, 0x77, 0x34, + 00, 0xdd, 0x46, 0xfc, 0x60, 0xfc, 0xc2, 0xb9, 0xd, 0x52, + 0xf5, 0x4e, 0xec, 0xb0, 0xfc, 0xea, 0xc6, 0xa7, 0xa8, 0xf5, + 0xe4, 0xd7, 0x23, 0xaa, 0xea, 0x4, 0x2b, 0x73, 0x40, 0x1e, + 0x7d, 0xf1, 0x2f, 0x50, 0x4f, 0xde, 00, 0xe3, 0xa7, 0xad, + 0x7c, 0xc5, 0xe3, 0x2b, 0xa1, 0x2d, 0xc3, 0x61, 0xb3, 0x5e, + 0xd5, 0xf1, 0x1b, 0x54, 0x2c, 0xf2, 0xf2, 0x7b, 0xd7, 0xcf, + 0x5e, 0x21, 0xbb, 0xf3, 0x2e, 0x5f, 0xae, 0x2b, 0xe2, 0x73, + 0x29, 0x39, 0x54, 0xb1, 0xf9, 0xd6, 0x6f, 0x37, 0x3a, 0x96, + 0x39, 0x8d, 0x4a, 0x4c, 0x67, 0xa5, 0x72, 0x57, 0x8d, 0x97, + 0x6f, 0xad, 0x74, 0x5a, 0x9c, 0x83, 0xd, 0x5c, 0xbd, 0xcb, + 0x64, 0xb7, 0xd6, 0x8c, 0x2c, 0x74, 0x1e, 0xe, 0x36, 0x45, + 0x9, 0xdb, 0x93, 0x5f, 0xa2, 0x3f, 0xb0, 0x37, 0x84, 0x65, + 0xb0, 0xf0, 0x6e, 0x9f, 0x71, 0x2c, 0x2e, 0xbf, 0x68, 0x99, + 0xee, 0xc3, 0x38, 0xfe, 0x1c, 00, 0x3b, 0x74, 0xeb, 0x5f, + 0x9e, 0x11, 0xc0, 0xf7, 0xb7, 0x90, 0x5b, 0xc7, 0xcc, 0x92, + 0xc8, 0xb1, 0xaf, 0xd4, 0x9c, 0xa, 0xfd, 0x82, 0xfd, 0x9b, + 0x7c, 0x31, 0x1e, 0x81, 0xe1, 0x2b, 0x68, 0x13, 0x5, 0x6d, + 0xe0, 0x8e, 0x24, 0xe3, 0x18, 0xe3, 0x27, 0xf9, 0xd7, 0xd2, + 0xe1, 0x57, 0x53, 0xeb, 0xb0, 0x51, 0xdd, 0x9e, 0xd5, 0xa, + 0xfb, 0x55, 0xf8, 0x6, 0x2a, 0x9c, 0x23, 0x8a, 0xbf, 0xa, + 0xe0, 0xd7, 0xa2, 0x7a, 0xc5, 0xeb, 0x7e, 0xd5, 0xa3, 00, + 0xe9, 0x54, 0x6d, 0xd7, 0xa5, 0x68, 0x42, 0xbd, 0x28, 0x2, + 0xf4, 0x42, 0xae, 0xc5, 0xda, 0xa9, 0xc2, 0x39, 0xab, 0xd0, + 0x8e, 0x28, 0x2, 0xd4, 0x42, 0xac, 0xc7, 0xd0, 0x54, 0x11, + 0x8e, 0x95, 0x66, 0x31, 0x40, 0x16, 0x23, 0xe2, 0xa7, 0x5e, + 0xd5, 0x4, 0x62, 0xa5, 0x5a, 00, 0x99, 0x69, 0xe3, 0xb5, + 0x44, 0x5, 0x48, 0xbd, 0x68, 0x2, 0x4a, 0x29, 0x7, 0x4a, + 0x5a, 00, 0x70, 0xe9, 0x4b, 0x4d, 0x5e, 0xf4, 0xea, 00, + 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0xc1, 0x7a, + 0xf9, 0x4b, 0xf6, 0xe9, 0xf0, 0x7c, 0x9a, 0xdf, 0x84, 0x20, + 0xbd, 0x89, 0x3, 0x32, 0x29, 0x51, 0x90, 0x32, 0x1b, 0x72, + 0x9e, 0xe7, 0xfb, 0xa1, 0xab, 0xea, 0xf7, 0xe6, 0xbc, 0xfb, + 0xe3, 0x4f, 0x85, 0xff, 00, 0xe1, 0x2b, 0xf0, 0xe, 0xa1, + 0x6c, 0xab, 0x99, 0x63, 0x2, 0x44, 0xfc, 0x8, 0xcf, 0xfe, + 0x3b, 0x9a, 0xc6, 0xb5, 0x35, 0x56, 0x9c, 0xa0, 0xfa, 0xa3, + 0x9f, 0x11, 0x49, 0x57, 0xa5, 0x2a, 0x6f, 0xaa, 0x3f, 0x2c, + 0xf4, 0x4d, 0x65, 0xa0, 0xd3, 0x17, 0x93, 0x80, 0x8, 0x3c, + 0xf4, 0xe6, 0xb9, 0xbd, 0x73, 0x59, 0x6b, 0x99, 0x98, 0x29, + 0x20, 0xfa, 0x83, 0x5d, 0x1f, 0x8b, 0xf4, 0x47, 0xf0, 0xce, + 0xb1, 0xa8, 0x58, 0xed, 0x6f, 0x2b, 0x7e, 0xf8, 0xd9, 0x86, + 0x32, 0x8, 0x7, 0xf4, 0xce, 0x3f, 0xa, 0xe2, 0x5a, 0x2, + 0xb2, 0x73, 0xfa, 0xd7, 0xe5, 0x15, 0xeb, 0xce, 0x1f, 0xb9, + 0x96, 0xeb, 0x43, 0xf1, 0x2c, 0x4e, 0x2a, 0xa5, 0x3f, 0xf6, + 0x69, 0xef, 0x1d, 0xa, 0x12, 0x5c, 0x3e, 0x7e, 0x66, 0x39, + 0xfa, 0xd3, 0x7c, 0xdc, 0x9e, 0xb5, 0x62, 0xe6, 0xdb, 0x3d, + 0xaa, 0x93, 0x42, 0xd1, 0xf3, 0x5c, 0xc9, 0xa9, 0x6e, 0x71, + 0x45, 0xc6, 0x5a, 0x93, 0x96, 0xc8, 0xeb, 0x4d, 0x2c, 0x47, + 0x7a, 0x8b, 0x79, 0xe8, 0x69, 0xc0, 0xe4, 0x51, 0x61, 0xd8, + 0x46, 0x99, 0x80, 0xa6, 0x89, 0x98, 0x52, 0x3f, 0x7a, 0x65, + 0x55, 0x8d, 0x12, 0x56, 0x25, 0xfb, 0x41, 0xa5, 0xfb, 0x53, + 0x7f, 0x93, 0x50, 0xd1, 0x45, 0x90, 0x72, 0xa2, 0x7f, 0xb4, + 0x9a, 0x70, 0xba, 0x35, 0x5a, 0x8a, 0x39, 0x50, 0x72, 0x22, + 0xcf, 0xda, 0x8e, 0x69, 0xc2, 0xee, 0xaa, 0x52, 0xe6, 0x8e, + 0x54, 0x27, 0x4e, 0x25, 0xb1, 0x77, 0xf5, 0xfc, 0xe9, 0xdf, + 0x6c, 0xf7, 0x3f, 0x9d, 0x51, 0xa2, 0x97, 0x22, 0x17, 0xb3, + 0x45, 0xff, 00, 0xb6, 0x1f, 0x53, 0xf9, 0xd3, 0xc5, 0xf3, + 0x2f, 0xf1, 0x1f, 0xce, 0xb3, 0x68, 0xcd, 0x2e, 0x44, 0x2f, + 0x66, 0x8d, 0x41, 0xa8, 0x3f, 0xf7, 0x9b, 0xf3, 0xa7, 0x8d, + 0x45, 0xc7, 0xf1, 0xb7, 0xe7, 0x59, 0x19, 0xa5, 0xc9, 0xa3, + 0x95, 0x7, 0xb3, 0xf3, 0x36, 0x57, 0x56, 0x95, 0x7a, 0x3b, + 0x7e, 0x75, 0x20, 0xd6, 0x66, 0x3, 0xfd, 0x61, 0xfc, 0xeb, + 0xb, 0x71, 0xf5, 0xa5, 0xde, 0xde, 0xb4, 0x72, 0x8b, 0xd9, + 0xbe, 0xe6, 0xfa, 0xeb, 0x93, 0xc, 0xf, 0x31, 0xbf, 0x3a, + 0x99, 0x7c, 0x41, 0x30, 0xea, 0xc7, 0xfe, 0xfa, 0xae, 0x6b, + 0x7b, 0x52, 0xf9, 0x8d, 0x47, 0x2b, 0xee, 0x3e, 0x49, 0x77, + 0x3a, 0x81, 0xe2, 0x49, 0xc1, 0xfb, 0xcd, 0xf9, 0xd4, 0x8b, + 0xe2, 0xa9, 0xc0, 0xfb, 0xcd, 0xff, 00, 0x7d, 0x57, 0x26, + 0x25, 0x61, 0xde, 0x97, 0xce, 0x34, 0xfd, 0xee, 0xe1, 0x69, + 0xf7, 0x3b, 0x24, 0xf1, 0x74, 0xaa, 0x3a, 0xbf, 0xfd, 0xf5, + 0x53, 0x27, 0x8d, 0x25, 0x5e, 0xed, 0xff, 00, 0x7d, 0x57, + 0xf, 0xe7, 0xb5, 0x38, 0x5c, 0x1a, 0x77, 0x9a, 0xea, 0x3b, + 0xd4, 0x5d, 0x4e, 0xed, 0x7c, 0x6d, 0x2f, 0xab, 0x8f, 0xf8, + 0x15, 0x58, 0x8f, 0xc7, 0x4e, 0xa3, 0xab, 0xfe, 0x75, 0xe7, + 0xbf, 0x69, 0x3e, 0xb4, 0xbf, 0x6a, 0x6a, 0x7c, 0xf5, 0x57, + 0x52, 0x95, 0x4a, 0xab, 0xa9, 0xe9, 0x11, 0xf8, 0xfd, 0xc7, + 0xf1, 0x3f, 0xe7, 0xff, 00, 0xd6, 0xab, 0x9, 0xf1, 0x1, + 0xbd, 0x5c, 0xf, 0xa9, 0xff, 00, 0xa, 0xf3, 0x1, 0x74, + 0xd9, 0xe6, 0x9c, 0x2e, 0xc8, 0x1c, 0xd5, 0x7b, 0x5a, 0xab, + 0xa8, 0xfd, 0xb5, 0x75, 0xd4, 0xf5, 0x54, 0xf8, 0x82, 0x47, + 0xf1, 0x3f, 0xe7, 0xff, 00, 0xd6, 0xab, 0x31, 0xfc, 0x43, + 0x3f, 0xde, 0x7c, 0xfd, 0x7f, 0xfa, 0xd5, 0xe4, 0x3f, 0x6c, + 0xfc, 0x69, 0xe2, 0xef, 0xd0, 0xe2, 0xab, 0xdb, 0xd6, 0x5d, + 0x4b, 0x58, 0x9a, 0xeb, 0xa9, 0xec, 0x89, 0xf1, 0x1b, 0x3f, + 0xc4, 0xdf, 0x9f, 0xff, 00, 0x5a, 0xac, 0x47, 0xf1, 0x13, + 0x9f, 0xbe, 0xff, 00, 0x9f, 0xff, 00, 0x5a, 0xbc, 0x57, + 0xed, 0x67, 0xd7, 0xf5, 0xa5, 0xfb, 0x71, 0xf5, 0xfd, 0x6a, + 0x96, 0x26, 0xb1, 0x4b, 0x1b, 0x5d, 0x75, 0x3d, 0xc9, 0x3e, + 0x22, 0xff, 00, 0xb4, 0xdf, 0x9f, 0xff, 00, 0x5a, 0xac, + 0xc7, 0xf1, 0x1f, 0xfd, 0xa6, 0xfc, 0xff, 00, 0xfa, 0xd5, + 0xe0, 0xc2, 0xf9, 0xbb, 0x37, 0xeb, 0x52, 0x2e, 0xa2, 0xe3, + 0xa3, 0x1a, 0xa5, 0x8c, 0xaa, 0x8b, 0x58, 0xfa, 0xe8, 0xf7, + 0xe8, 0xfe, 0x23, 0x67, 0xf8, 0x9b, 0xf3, 0xff, 00, 0xeb, + 0x55, 0xa8, 0xfe, 0x22, 0x83, 0xfc, 0x4d, 0xf9, 0xff, 00, + 0xf5, 0xab, 0xe7, 0xa1, 0xaa, 0x48, 0x31, 0x87, 0xa7, 0x2e, + 0xaf, 0x28, 0x3f, 0x7c, 0xd5, 0xac, 0x75, 0x54, 0x6a, 0xb3, + 0x3a, 0xc8, 0xfa, 0x2d, 0x3e, 0x23, 0x2f, 0xab, 0x7e, 0x7f, + 0xfd, 0x6a, 0xb1, 0x1f, 0xc4, 0x55, 0x38, 0xe5, 0xbf, 0x3f, + 0xfe, 0xb5, 0x7c, 0xe2, 0xba, 0xdc, 0xcb, 0xfc, 0x62, 0xa4, + 0x5d, 0x7e, 0x75, 0xe8, 0xc2, 0xb4, 0x59, 0x8d, 0x43, 0x45, + 0x9b, 0x55, 0x47, 0xd2, 0x69, 0xf1, 0x9, 0x4f, 0x42, 0xdf, + 0x9f, 0xff, 00, 0x5a, 0xac, 0xa7, 0xc4, 0x34, 0x3f, 0xc4, + 0xdf, 0x9d, 0x7c, 0xce, 0xbe, 0x24, 0xb8, 0x1f, 0xc4, 0x2a, + 0x55, 0xf1, 0x44, 0xeb, 0xe9, 0xf9, 0xd5, 0xac, 0xce, 0x68, + 0xd5, 0x67, 0x15, 0x11, 0xf4, 0xda, 0x7c, 0x41, 0x4f, 0xef, + 0x37, 0xe7, 0xff, 00, 0xd6, 0xab, 0x31, 0xf8, 0xfd, 0xe, + 0x3e, 0x76, 0xfc, 0xff, 00, 0xfa, 0xd5, 0xf3, 0xa, 0xf8, + 0xb6, 0x71, 0xe9, 0x52, 0xa7, 0x8c, 0xee, 0x7, 0xff, 00, + 0xae, 0xb5, 0x59, 0xa4, 0x91, 0xb2, 0xce, 0xa6, 0x8f, 0xa8, + 0x53, 0xc7, 0xe9, 0xfd, 0xf3, 0xf9, 0xff, 00, 0xf5, 0xaa, + 0xc4, 0x7e, 0x3f, 0x4f, 0xef, 0xb7, 0xe7, 0xff, 00, 0xd6, + 0xaf, 0x97, 0x53, 0xc6, 0xb3, 0xe, 0xa6, 0xa6, 0x5f, 0x1d, + 0x4a, 0x3b, 0xfe, 0xbf, 0xfd, 0x6a, 0xd1, 0x66, 0xcc, 0xd5, + 0x67, 0x92, 0x3e, 0xa4, 0x4f, 0x1f, 0x2f, 0x1f, 0x3b, 0x3, + 0xf5, 0x3f, 0xe1, 0x56, 0x93, 0xc7, 0x83, 0xfb, 0xec, 0x3f, + 0x13, 0x5f, 0x2c, 0x47, 0xe3, 0xd9, 0x3d, 0x47, 0xe7, 0xff, + 00, 0xd6, 0xab, 0x11, 0xf8, 0xfd, 0xc6, 0x3e, 0x65, 0xff, + 00, 0xbe, 0xbf, 0xfa, 0xd5, 0xb2, 0xcd, 0xdf, 0x73, 0x78, + 0xe7, 0xaf, 0xb9, 0xf5, 0x34, 0x7e, 0x3d, 0x18, 0xfb, 0xe7, + 0xf3, 0x35, 0x61, 0x3c, 0x78, 0xf, 0xf1, 0x9f, 0xcf, 0xff, + 00, 0xad, 0x5f, 0x2c, 0xc7, 0xf1, 0xd, 0x81, 0xfb, 0xcb, + 0xff, 00, 0x7d, 0x7f, 0xf5, 0xaa, 0xc2, 0x7c, 0x46, 0x7f, + 0x55, 0xff, 00, 0xbe, 0xbf, 0xfa, 0xd5, 0xaa, 0xce, 0x3c, + 0xcd, 0xd6, 0x7d, 0xe6, 0x7d, 0x4a, 0x9e, 0x3c, 0xe3, 0xef, + 0xb7, 0xe6, 0x6a, 0x75, 0xf1, 0xd0, 0xfe, 0xf3, 0x7e, 0x7f, + 0xfd, 0x6a, 0xf9, 0x6d, 0x3e, 0x22, 0x37, 0xf7, 0xd7, 0xfe, + 0xfa, 0xff, 00, 0xeb, 0x55, 0x98, 0xfe, 0x22, 0xb7, 0xf7, + 0x97, 0xfe, 0xfa, 0xff, 00, 0xeb, 0x56, 0xab, 0x37, 0xf3, + 0x37, 0x59, 0xf2, 0x7d, 0x4f, 0xa8, 0xe3, 0xf1, 0xc8, 0x3, + 0xef, 0x1f, 0xcf, 0xff, 00, 0xad, 0x56, 0x17, 0xc7, 0x60, + 0xf7, 0x3f, 0xe7, 0xf0, 0xaf, 0x97, 0x63, 0xf8, 0x8e, 0x47, + 0xf1, 0x29, 0x3f, 0xef, 0x7f, 0xf5, 0xaa, 0xd4, 0x7f, 0x11, + 0x8e, 0x7e, 0xf2, 0xff, 00, 0xdf, 0x5f, 0xfd, 0x6a, 0xda, + 0x39, 0xba, 0xee, 0x6f, 0x1c, 0xf9, 0x77, 0x3e, 0x9f, 0x4f, + 0x1c, 0x29, 0xc7, 0x27, 0xf3, 0xff, 00, 0xeb, 0x54, 0xc9, + 0xe3, 0x74, 0xf7, 0xfc, 0xff, 00, 0xfa, 0xd5, 0xf3, 0x1c, + 0x7f, 0x11, 0x4f, 0xf7, 0x93, 0xf1, 0x6f, 0xfe, 0xb5, 0x58, + 0x4f, 0x88, 0xff, 00, 0xed, 0x21, 0xff, 00, 0x81, 0x7f, + 0xf5, 0xab, 0x65, 0x9b, 0xae, 0xe6, 0xf1, 0xcf, 0x63, 0xdc, + 0xfa, 0x6d, 0x7c, 0x6b, 0x1f, 0x52, 0xf, 0xe7, 0xff, 00, + 0xd6, 0xa9, 0x57, 0xc6, 0x51, 0x1f, 0x5f, 0xcf, 0xff, 00, + 0xad, 0x5f, 0x33, 0xc7, 0xf1, 0x1b, 0x3f, 0xc4, 0x9f, 0xf7, + 0xd7, 0xff, 00, 0x5a, 0xac, 0xa7, 0xc4, 0x5c, 0xff, 00, + 0x12, 0x67, 0xfd, 0xef, 0xfe, 0xb5, 0x68, 0xb3, 0x68, 0xf7, + 0x36, 0x59, 0xe4, 0x7b, 0x9f, 0x4b, 0x27, 0x8c, 0x21, 0xe3, + 0x39, 0xfc, 0xff, 00, 0xfa, 0xd5, 0x2a, 0x78, 0xb2, 0x3, + 0xeb, 0xf9, 0xff, 00, 0xf5, 0xab, 0xe6, 0xe8, 0xfe, 0x22, + 0x8c, 0xc, 0xb2, 0xff, 00, 0xdf, 0x5f, 0xfd, 0x6a, 0x9d, + 0x3e, 0x22, 0x3, 0xdd, 0x7f, 0xef, 0xaf, 0xfe, 0xb5, 0x6c, + 0xb3, 0x58, 0xbe, 0xa6, 0xf1, 0xce, 0xa0, 0xfa, 0x9f, 0x48, + 0x2f, 0x8a, 0x21, 0xcf, 0x53, 0xfe, 0x7f, 0xa, 0x91, 0x3c, + 0x4b, 0x9, 0xfe, 0x23, 0xfe, 0x7f, 0xa, 0xf9, 0xd2, 0x3f, + 0x88, 0x20, 0x91, 0xf3, 0x2f, 0xd3, 0x77, 0xff, 00, 0x5a, + 0xac, 0xa7, 0xc4, 0x5, 0xfe, 0xfa, 0xf, 0xf8, 0x17, 0xff, + 00, 0x5a, 0xb4, 0x59, 0x9c, 0x4d, 0x96, 0x71, 0x4c, 0xfa, + 0x20, 0x78, 0x8a, 0xf, 0xef, 0x1a, 0x7a, 0xeb, 0xf1, 0x13, + 0xf7, 0x8f, 0xf9, 0xfc, 0x2b, 0xe7, 0xc4, 0xf8, 0x82, 0x9, + 0xfb, 0xeb, 0xff, 00, 0x7d, 0x7f, 0xf5, 0xaa, 0xc4, 0x7e, + 0x3e, 0x1c, 0x7c, 0xe9, 0xff, 00, 0x7d, 0x7f, 0xf5, 0xab, + 0x45, 0x99, 0x41, 0x9b, 0x2c, 0xda, 0x9b, 0x3e, 0x81, 0x5d, + 0x6e, 0x32, 0x7e, 0xf7, 0xeb, 0x52, 0x2e, 0xb2, 0x9f, 0xde, + 0xfd, 0x6b, 0xc0, 0xe3, 0xf1, 0xea, 0x8f, 0xe3, 0x4f, 0xfb, + 0xe8, 0x7f, 0x85, 0x58, 0x4f, 0x1e, 0x82, 0x71, 0xbd, 0x3f, + 0xef, 0xaf, 0xfe, 0xb5, 0x6a, 0xb3, 0xa, 0x66, 0x8b, 0x34, + 0xa6, 0xcf, 0x77, 0x5d, 0x61, 0x4f, 0x46, 0xfd, 0x6a, 0x41, + 0xab, 0xf, 0x5f, 0xd6, 0xbc, 0x32, 0x3f, 0x1e, 0x67, 0xfe, + 0x5a, 0x20, 0xff, 00, 0x81, 0x7f, 0xf5, 0xaa, 0xc2, 0x78, + 0xef, 0x27, 0xef, 0x28, 0xff, 00, 0x81, 0xf, 0xf0, 0xab, + 0x58, 0xea, 0x66, 0xab, 0x32, 0xa4, 0xcf, 0x6e, 0x5d, 0x59, + 0x7a, 0xe4, 0xfe, 0x74, 0xf5, 0xd5, 0xb3, 0xdc, 0xd7, 0x8a, + 0x27, 0x8e, 0xce, 0x7e, 0xfa, 0xff, 00, 0xdf, 0x5f, 0xfd, + 0x6a, 0xb3, 0x17, 0x8e, 0x8e, 0x3e, 0xf2, 0x7e, 0x7f, 0xfd, + 0x6a, 0xb5, 0x8c, 0xa6, 0x68, 0xb1, 0xf4, 0x99, 0xec, 0xab, + 0xaa, 0xfb, 0x9a, 0x7a, 0xea, 0x9e, 0xe6, 0xbc, 0x7e, 0x3f, + 0x1d, 0x9f, 0x54, 0xfc, 0xff, 00, 0xfa, 0xd5, 0x3a, 0xf8, + 0xe8, 0x9e, 0x72, 0x9f, 0x9f, 0xff, 00, 0x5a, 0xaf, 0xeb, + 0x54, 0xfb, 0x9a, 0x2c, 0x6d, 0x17, 0xd4, 0xf5, 0xb5, 0xd5, + 0x7d, 0xcf, 0xe7, 0x4f, 0x5d, 0x53, 0x9e, 0xbf, 0xad, 0x79, + 0x3a, 0x78, 0xe7, 0xdd, 0x3f, 0x3f, 0xfe, 0xb5, 0x58, 0x5f, + 0x1c, 0xfb, 0xa7, 0xfd, 0xf5, 0xff, 00, 0xd6, 0xab, 0x58, + 0x8a, 0x6f, 0xa9, 0x6b, 0x15, 0x4b, 0xb9, 0xea, 0x4b, 0xaa, + 0x7b, 0xfe, 0xb4, 0xf5, 0xd5, 0x6, 0x3a, 0xfe, 0xb5, 0xe6, + 0x9, 0xe3, 0x75, 0x3c, 0xfc, 0x9f, 0xf7, 0xd7, 0xff, 00, + 0x5a, 0xa7, 0x4f, 0x1a, 0x27, 0xfb, 0x3f, 0xf7, 0xd5, 0x57, + 0xb6, 0x87, 0x72, 0x96, 0x22, 0x9b, 0xea, 0x7a, 0x50, 0xd5, + 0x3f, 0xce, 0x69, 0xe3, 0x54, 0xff, 00, 0x39, 0xaf, 0x38, + 0x1e, 0x30, 0x8c, 0xff, 00, 0x77, 0xfe, 0xfa, 0xa9, 0x57, + 0xc5, 0xd1, 0x9e, 0x85, 0x7f, 0xef, 0xaa, 0xaf, 0x6b, 0xe, + 0xe5, 0xfb, 0x6a, 0x7d, 0xcf, 0x44, 0x5d, 0x4c, 0x77, 0x3f, + 0xad, 0x38, 0x6a, 0x59, 0xee, 0x7f, 0x3a, 0xf3, 0xf5, 0xf1, + 0x5c, 0x47, 0xab, 0x28, 0xff, 00, 0x81, 0x54, 0xab, 0xe2, + 0x88, 0x4f, 0xf1, 0xaf, 0xfd, 0xf5, 0x4d, 0x54, 0x8f, 0x72, + 0xbd, 0xa4, 0x3b, 0x9d, 0xf0, 0xd4, 0xbd, 0xff, 00, 0x5a, + 0x78, 0xd4, 0xbd, 0xcf, 0xe7, 0x5c, 0x1a, 0xf8, 0x92, 0x23, + 0xfc, 0x6b, 0xff, 00, 0x7d, 0x54, 0xab, 0xe2, 0x8, 0xcf, + 0xf1, 0xaf, 0xe7, 0x55, 0xcd, 0x1e, 0xe3, 0x53, 0x8b, 0xea, + 0x77, 0x23, 0x52, 0xf7, 0x3f, 0x9d, 0x38, 0x6a, 0x5c, 0x75, + 0xfd, 0x6b, 0x88, 0x5d, 0x76, 0x3e, 0xd2, 0x2f, 0xe7, 0x52, + 0xd, 0x71, 0x3f, 0xe7, 0xa0, 0xa7, 0x74, 0x57, 0x32, 0xee, + 0x76, 0xc3, 0x52, 0xf7, 0xfd, 0x69, 0x46, 0xa5, 0xef, 0xfa, + 0xd7, 0x18, 0xba, 0xca, 0x9c, 0x61, 0xd7, 0xf3, 0xa9, 0x6, + 0xae, 0x3f, 0xbc, 0x3f, 0x3a, 0x63, 0xba, 0x3b, 0x25, 0xd4, + 0x7d, 0xff, 00, 0x5a, 0x70, 0xd4, 0x7d, 0xcf, 0xe7, 0x5c, + 0x72, 0xea, 0xc3, 0xb3, 0x3, 0xf8, 0xd4, 0x8b, 0xaa, 0xfb, + 0xfe, 0xb4, 0x1, 0xd8, 0xd, 0x47, 0xdc, 0xfe, 0x74, 0xef, + 0xed, 0x1f, 0x7f, 0xd6, 0xb8, 0xf1, 0xaa, 0xf3, 0xf7, 0xbf, + 0x5a, 0x78, 0xd5, 0x79, 0xed, 0xf9, 0xd0, 0x7, 0x5e, 0x35, + 0x2f, 0x7f, 0xd6, 0x9e, 0x35, 0x1f, 0x73, 0xf9, 0xd7, 0x20, + 0x35, 0x5f, 0x71, 0xf9, 0xd3, 0xff, 00, 0xb5, 0x72, 0x7a, + 0xd0, 0x7, 0x5c, 0x35, 0x2f, 0x7f, 0xd6, 0x9c, 0x35, 0x2f, + 0x73, 0xf9, 0xd7, 0x22, 0x35, 0x4f, 0x71, 0xf9, 0xd3, 0xc6, + 0xa9, 0xee, 0x28, 0x3, 0xae, 0x1a, 0x97, 0xb9, 0xfc, 0xe9, + 0x46, 0xa5, 0xef, 0xfa, 0xd7, 0x26, 0x35, 0x41, 0xeb, 0xfa, + 0xd3, 0x86, 0xa9, 0xee, 0x3f, 0x3a, 00, 0xeb, 0x7f, 0xb4, + 0xb8, 0xeb, 0xfa, 0xd4, 0x32, 0x6a, 0x3e, 0xe7, 0xf3, 0xae, + 0x6b, 0xfb, 0x4f, 0x3d, 0xea, 0x39, 0x75, 0x31, 0xeb, 0x40, + 0x1b, 0xb3, 0xea, 0x5c, 0x75, 0x3f, 0x9d, 0x67, 0x5c, 0x6a, + 0x1d, 0x79, 0x3f, 0x9d, 0x62, 0xdc, 0x6a, 0x83, 0xb7, 0xf3, + 0xac, 0xcb, 0x9d, 0x53, 0xdc, 0x7e, 0x74, 0x1, 0xad, 0x75, + 0xa9, 0x63, 0x23, 0x35, 0x8d, 0x79, 0xaa, 0x67, 0x3c, 0xfe, + 0xb5, 0x97, 0x77, 0xa9, 0xf5, 0xe6, 0xb1, 0x6e, 0xf5, 0x3e, + 0xbc, 0x8a, 00, 0xd0, 0xbe, 0xd4, 0xbf, 0xce, 0x6b, 0x9c, + 0xd4, 0xf5, 0x3e, 0x3a, 0xfe, 0xb5, 0x5a, 0xfb, 0x53, 0xeb, + 0xcf, 0xeb, 0x5c, 0xce, 0xa5, 0xaa, 0x7b, 0xfe, 0xb4, 0x1, + 0x2e, 0xa5, 0xa9, 0x75, 0xe7, 0xf5, 0xae, 0x43, 0x5b, 0xd5, + 0x36, 0xc4, 0xfc, 0xfe, 0xb4, 0xfd, 0x43, 0x52, 0xce, 0x6b, + 0x90, 0xf1, 0x5, 0xf9, 0xfb, 0x2c, 0x86, 0x93, 0xd8, 0x99, + 0x6c, 0xcf, 0x31, 0xf1, 0xf6, 0xab, 0xb9, 0xa5, 0xeb, 0xdf, + 0xbd, 0x78, 0x96, 0xa9, 0x75, 0xbe, 0x67, 0x39, 0xaf, 0x40, + 0xf1, 0xc6, 0xa4, 0x4b, 0xcb, 0xcf, 0xad, 0x79, 0x65, 0xdc, + 0xbb, 0xd9, 0x8e, 0x7b, 0xd7, 0xc4, 0xe2, 0xe3, 0x7a, 0xa7, + 0xe7, 0x98, 0xd8, 0xf3, 0x55, 0x33, 0x75, 0x9, 0x38, 0x35, + 0xcf, 0x5c, 0x37, 0x5a, 0xda, 0xbc, 0x24, 0x9e, 0x4d, 0x62, + 0xdc, 0xaf, 0x5f, 0xad, 0x74, 0xd0, 0x56, 0xd0, 0xeb, 0xc3, + 0x2b, 0x2b, 0x1d, 0x17, 0xc1, 0xef, 0xf, 0xb7, 0x8a, 0x3e, + 0x28, 0x78, 0x76, 0xcc, 0x36, 0x2, 0xde, 0x45, 0x33, 0x8c, + 0x75, 0x54, 0x70, 0xc4, 0x75, 0x1d, 0x85, 0x7e, 0xc7, 0x7c, + 0x31, 0xb0, 0x4b, 0x1f, 0xc, 0x43, 0xb0, 0x60, 0x48, 0xdb, + 0xbf, 0x90, 0xfe, 0x95, 0xf9, 0x71, 0xfb, 0x1b, 0x68, 0x6b, + 0xa9, 0xfc, 0x55, 0x96, 0xec, 0xa1, 0x76, 0xb2, 0xb5, 0x67, + 0x5c, 0xc, 0xf2, 0xc7, 0x6f, 0xf5, 0xaf, 0xd6, 0x5f, 0xf, + 0x5b, 0x7d, 0x97, 0x4a, 0xb4, 0x8b, 0xa6, 0xd8, 0xd7, 0x8f, + 0xc2, 0xbe, 0x93, 0xe, 0xad, 0xb, 0x9f, 0x5b, 0x84, 0x8d, + 0xa1, 0x73, 0x66, 0x1e, 0xd5, 0xa1, 00, 0xef, 0x54, 0xa1, + 0x1c, 0xd5, 0xf8, 0x33, 0xeb, 0x5d, 0x47, 0x69, 0x7e, 0x3, + 0xd2, 0xb4, 0x60, 0x15, 0x9f, 00, 0xe4, 0x56, 0x94, 0x14, + 0x1, 0x72, 0x11, 0x57, 0x62, 0xe7, 0x2, 0xaa, 0xc4, 0x38, + 0xab, 0xb0, 0xe, 0x94, 0x1, 0x6a, 0x35, 0xe6, 0xac, 0xc6, + 0x2a, 0xbc, 0x62, 0xac, 0xc4, 0x3a, 0x50, 0x4, 0xe9, 0xc0, + 0xa9, 0x17, 0xa0, 0xa6, 0x20, 0xa9, 0x7, 0x5a, 00, 0x78, + 0xeb, 0x4f, 0x5a, 0x62, 0xd4, 0x83, 0xa5, 00, 0x3c, 0x74, + 0xa2, 0x8a, 0x28, 0x1, 0xcb, 0x4b, 0x48, 0x3a, 0x52, 0xd0, + 0x1, 0x45, 0x14, 0x50, 0x1, 0x45, 0x14, 0x50, 0x6, 0x34, + 0x83, 0xda, 0xaa, 0xca, 0x81, 0x83, 0x2, 0x32, 0xf, 0x15, + 0x71, 0xf3, 0x55, 0xdd, 0x68, 0x3, 0xe0, 0x8f, 0xda, 0xc7, + 0xe0, 0xec, 0xba, 0x76, 0xbb, 0x71, 0x7f, 0x6d, 00, 0xf2, + 0x9c, 0x99, 0x61, 0x29, 0x93, 0xbc, 0x1c, 0x16, 0x5e, 0x7b, + 0x83, 0xbb, 0x8a, 0xf9, 0x56, 0x7d, 0x38, 0x83, 0xc8, 0xaf, + 0xd6, 0xef, 0x89, 0x7e, 0x3, 0x83, 0xc7, 0x9e, 0x1e, 0x9a, + 0xc9, 0x96, 0x31, 0x74, 0xa0, 0x9b, 0x79, 0x9c, 0x7d, 0xc6, + 0xfa, 0xe0, 0x9c, 0x1c, 0x73, 0x5f, 0x9d, 0xbf, 0x13, 0x7e, + 0x1a, 0x4f, 0xe1, 0x5d, 0x5a, 0xe1, 0x56, 0x10, 0x91, 0xab, + 0xed, 0x78, 0xc2, 0x9f, 0x90, 0xfe, 0x5d, 0x2b, 0xf3, 0xce, + 0x24, 0xcb, 0xa7, 0x17, 0xf5, 0xda, 0x2b, 0xfc, 0x5f, 0xe6, + 0x7e, 0x57, 0xc5, 0xd9, 0x4c, 0xa2, 0xff, 00, 0xb4, 0x28, + 0x2b, 0xaf, 0xb4, 0x97, 0xe7, 0xfe, 0x67, 0x8b, 0xcb, 0x60, + 0x79, 0x18, 0xe2, 0xa9, 0xcd, 0x61, 0xed, 0x5d, 0x94, 0xda, + 0x6e, 0x72, 0x40, 0xaa, 0x32, 0xe9, 0xd8, 0xed, 0x5f, 0x1, + 0x1c, 0x4d, 0xcf, 0xcb, 0xe9, 0xe2, 0xee, 0x72, 0x12, 0x69, + 0xfe, 0xd5, 0x3, 0x58, 0x91, 0xd0, 0x57, 0x64, 0xba, 0x2b, + 0xcb, 0xdb, 0xf0, 0xc5, 0x2b, 0x78, 0x61, 0x9b, 0xb6, 0x4f, + 0xb0, 0xff, 00, 0xeb, 0x57, 0x7c, 0x2a, 0xb9, 0x6c, 0x7a, + 0x54, 0xeb, 0xca, 0x47, 0xc, 0xf6, 0x4c, 0x3a, 0x3, 0x51, + 0x9b, 0x57, 0x15, 0xdd, 0x3f, 0x85, 0x5f, 0xfb, 0x87, 0xf2, + 0x3f, 0xe1, 0x51, 0x37, 0x85, 0x9f, 0xfb, 0x87, 0xf2, 0xff, + 00, 0xeb, 0x57, 0x4a, 0x9c, 0xbb, 0x1d, 0x8a, 0xa4, 0xfb, + 0x1c, 0x4f, 0xd9, 0xdf, 0xd2, 0x93, 0xc8, 0x7c, 0xe3, 0x15, + 0xd8, 0xb7, 0x86, 0x1c, 0x7f, 0x9, 0xfc, 0xbf, 0xfa, 0xd5, + 0x13, 0x78, 0x69, 0xc7, 0x6f, 0xd3, 0xff, 00, 0xad, 0x4f, + 0x9d, 0xf6, 0x2b, 0xda, 0x4b, 0xaa, 0x39, 0x23, 0xb, 0xe, + 0xd4, 0xd3, 0x13, 0xe, 0xd5, 0xd4, 0xb7, 0x87, 0xe4, 0x1d, + 0x87, 0xe4, 0x7f, 0xc2, 0xa3, 0x3a, 0xc, 0x9e, 0x9f, 0xa1, + 0xff, 00, 0xa, 0x7e, 0xd3, 0xc8, 0x7e, 0xd5, 0xf6, 0x39, + 0xad, 0x8d, 0xe9, 0x49, 0xb4, 0xfa, 0x57, 0x49, 0xfd, 0x89, + 0x27, 0xf7, 0x3f, 0x43, 0x51, 0xbe, 0x8b, 0x20, 0xfe, 0x1f, + 0xd0, 0xd3, 0xf6, 0x81, 0xed, 0x7c, 0x8e, 0x7f, 0x69, 0xf4, + 0xa4, 0xc5, 0x6e, 0x9d, 0x21, 0xff, 00, 0xbb, 0xfa, 0x1a, + 0x8c, 0xe9, 0x4e, 0x3f, 0x80, 0xfe, 0x46, 0x8e, 0x74, 0x57, + 0xb5, 0x5d, 0x8c, 0x6c, 0x51, 0x5a, 0xe7, 0x4c, 0x61, 0xfc, + 0x7, 0xf2, 0xa6, 0x9d, 0x38, 0xf7, 0x43, 0xf9, 0x53, 0xf6, + 0x88, 0x3d, 0xac, 0x4c, 0xaa, 0x2b, 0x48, 0xe9, 0xdf, 0xec, + 0xe2, 0x98, 0x6c, 0x3d, 0xa9, 0xf3, 0xc4, 0x7e, 0xd6, 0x25, + 0xa, 0x2a, 0xef, 0xd8, 0x69, 0xd, 0x89, 0xa3, 0x9d, 0x15, + 0xed, 0x22, 0x53, 0xc5, 0x15, 0x6b, 0xec, 0x64, 0x53, 0x4d, + 0xa3, 0x53, 0xe6, 0x41, 0xed, 0x23, 0xdc, 0xaf, 0x45, 0x4e, + 0x6d, 0x5b, 0xd6, 0x93, 0xec, 0xaf, 0x45, 0xd0, 0xf9, 0x97, + 0x72, 0x1a, 0x2a, 0x5f, 0xb3, 0xb5, 0x27, 0x90, 0xd4, 0xee, + 0x87, 0x74, 0x47, 0x45, 0x49, 0xe4, 0x36, 0x29, 0xc, 0x4c, + 0x3b, 0x51, 0x70, 0xba, 0x19, 0x45, 0x3b, 0x63, 0x7a, 0x51, + 0xb0, 0xfa, 0x50, 0x31, 0xb4, 0x52, 0xed, 0x34, 0x6d, 0x34, + 00, 0x94, 0x52, 0xe2, 0x92, 0x80, 0x17, 0x3e, 0xf4, 0x67, + 0xde, 0x92, 0x8c, 0x53, 0x18, 0xbb, 0x88, 0xa5, 0xdc, 0x7d, + 0x69, 0xb4, 0x52, 0xd, 0x7, 0x6e, 0x6f, 0x53, 0x46, 0xf6, + 0x1d, 0xe9, 0xb4, 0x53, 0xb0, 0xac, 0x87, 0xf9, 0xad, 0x47, + 0x9a, 0x69, 0x94, 0x52, 0xb0, 0xb9, 0x51, 0x20, 0x99, 0x85, + 0x2f, 0x9e, 0x6a, 0x2a, 0x28, 0xb2, 0xe, 0x54, 0x4d, 0xf6, + 0x83, 0x4a, 0x2e, 0x4d, 0x41, 0x45, 0x2b, 0x21, 0x72, 0x22, + 0xc7, 0xda, 0x69, 0xdf, 0x6c, 0x3e, 0xa6, 0xaa, 0xd1, 0x45, + 0x90, 0xb9, 0x11, 0x68, 0x5d, 0x7b, 0xe2, 0x94, 0x5d, 0xff, + 00, 0xb5, 0xfa, 0x55, 0x4a, 0x29, 0x72, 0xa1, 0x7b, 0x38, + 0x97, 0x45, 0xef, 0xbd, 0x38, 0x5e, 0xe3, 0xb9, 0xaa, 0x14, + 0x66, 0x8e, 0x44, 0x1e, 0xce, 0x26, 0x90, 0xbe, 0x3f, 0xde, + 0xa7, 0xd, 0x41, 0xbf, 0xbe, 0x6b, 0x2f, 0x34, 0x66, 0x97, + 0x22, 0x17, 0xb3, 0x46, 0xb8, 0xd4, 0x9c, 0x7f, 0x19, 0xa7, + 0xae, 0xab, 0x28, 0xe9, 0x23, 0x56, 0x36, 0xe3, 0xeb, 0x46, + 0xe3, 0xeb, 0x47, 0x22, 0xf, 0x66, 0xbb, 0x9b, 0xa3, 0x57, + 0x9c, 0x7f, 0xcb, 0x53, 0x4e, 0x1a, 0xdc, 0xe3, 0xfe, 0x5a, + 0xb5, 0x60, 0x6e, 0x34, 0xa2, 0x46, 0x1d, 0xe8, 0xe5, 0xf3, + 0x17, 0x23, 0xee, 0x74, 0x69, 0xe2, 0x9, 0xc6, 0x3f, 0x78, + 0x4d, 0x4a, 0x3c, 0x49, 0x72, 0x3f, 0xe5, 0xa1, 0xae, 0x63, + 0xcd, 0x6f, 0x5a, 0x4, 0xcc, 0x3d, 0xe8, 0xe5, 0x6b, 0x66, + 0x3e, 0x59, 0x2e, 0xa7, 0x56, 0xbe, 0x29, 0xb9, 0x5f, 0xf9, + 0x6a, 0xc3, 0xf2, 0xff, 00, 0xa, 0x9a, 0x3f, 0x16, 0x4e, + 0x3a, 0xc8, 0xdf, 0xa5, 0x71, 0xfe, 0x79, 0xa5, 0xfb, 0x43, + 0xa, 0x3d, 0xee, 0xe1, 0xfb, 0xce, 0xe7, 0x68, 0xbe, 0x32, + 0x9d, 0x4f, 0xdf, 0x7f, 0xd2, 0xa6, 0x4f, 0x1b, 0x4e, 0x3f, + 0x8d, 0xff, 00, 0x4a, 0xe1, 0xc5, 0xc3, 0xe, 0xe6, 0x97, + 0xed, 0x27, 0xde, 0x9f, 0x35, 0x45, 0xb3, 0x2a, 0xf5, 0x57, + 0x53, 0xbe, 0x4f, 0x1c, 0xca, 0x3a, 0xca, 0xff, 00, 0x90, + 0xab, 0x9, 0xe3, 0xe7, 0x5f, 0xf9, 0x6a, 0xe3, 0xf0, 0x15, + 0xe7, 0x22, 0xe8, 0x8e, 0xc6, 0x97, 0xed, 0x59, 0xf5, 0xab, + 0x55, 0x2a, 0xae, 0xa3, 0xf6, 0x95, 0x97, 0x53, 0xd2, 0xd3, + 0xe2, 0xb, 0xff, 00, 0xcf, 0x57, 0xfc, 0x85, 0x58, 0x8f, + 0xe2, 0x13, 0x77, 0x99, 0xbf, 0x21, 0x5e, 0x5b, 0xf6, 0xa3, + 0x4e, 0x17, 0x98, 0xef, 0x4f, 0xdb, 0x56, 0x5d, 0x4a, 0x55, + 0xeb, 0xae, 0xa7, 0xac, 0x27, 0xc4, 0x42, 0x3f, 0xe5, 0xb3, + 0x7e, 0x42, 0xad, 0x47, 0xf1, 0x18, 0xf6, 0x99, 0xbf, 0x21, + 0x5e, 0x3d, 0xf6, 0xc3, 0xeb, 0x4e, 0x5b, 0xd2, 0x3b, 0x9a, + 0xa5, 0x88, 0xaa, 0x8a, 0x58, 0xaa, 0xeb, 0xa9, 0xec, 0xf1, + 0xfc, 0x46, 0x3f, 0xf3, 0xdd, 0xbf, 0x21, 0x56, 0x63, 0xf8, + 0x8d, 0xff, 00, 0x4d, 0xdb, 0xf2, 0x15, 0xe2, 0x42, 0xfc, + 0xff, 00, 0x78, 0xfe, 0x74, 0xa3, 0x50, 0x7f, 0xef, 0xb7, + 0xe7, 0x55, 0xf5, 0xaa, 0xa8, 0xd1, 0x63, 0xab, 0xa3, 0xdd, + 0x63, 0xf8, 0x90, 0x7, 0xfc, 0xb7, 0x6f, 0xc8, 0x54, 0xe9, + 0xf1, 0x1f, 0x3f, 0xf2, 0xdd, 0xbf, 0x21, 0x5e, 0xe, 0x35, + 0x29, 0x7, 0xfc, 0xb4, 0x6f, 0xce, 0x9c, 0x35, 0x59, 0x7f, + 0xe7, 0xab, 0x7e, 0x75, 0x6b, 0x1b, 0x59, 0x1a, 0x2c, 0xc6, + 0xb9, 0xf4, 0x4, 0x7f, 0x11, 0xbf, 0xe9, 0xb3, 0x7e, 0x42, + 0xad, 0x27, 0xc4, 0x70, 0x3a, 0xce, 0xdf, 0x90, 0xaf, 0x9e, + 0x6, 0xb1, 0x30, 0xff, 00, 0x96, 0xcd, 0xf9, 0xd4, 0x8b, + 0xad, 0xce, 0xbf, 0xf2, 0xd5, 0xbf, 0x3a, 0xb5, 0x8f, 0xa8, + 0x8b, 0x59, 0xa5, 0x64, 0x7d, 0x14, 0x9f, 0x11, 0x81, 0xff, + 00, 0x96, 0xcd, 0xf9, 0xa, 0xb3, 0x1f, 0xc4, 0x54, 0x3d, + 0x67, 0x3f, 0xa5, 0x7c, 0xe0, 0x3c, 0x43, 0x72, 0x3f, 0xe5, + 0xa9, 0xfc, 0xea, 0x51, 0xe2, 0x5b, 0xa1, 0xff, 00, 0x2d, + 0x8f, 0xe7, 0x56, 0xb3, 0x2a, 0x88, 0xd5, 0x66, 0xf5, 0x51, + 0xf4, 0x9a, 0x7c, 0x45, 0x4e, 0xf3, 0x11, 0xf8, 0xa, 0xb0, + 0x9f, 0x11, 0x10, 0xff, 00, 0xcb, 0x76, 0xfd, 0x2b, 0xe6, + 0x85, 0xf1, 0x45, 0xd0, 0xff, 00, 0x96, 0xa7, 0xf3, 0xff, + 00, 0xeb, 0xd4, 0xcb, 0xe2, 0xcb, 0x90, 0x3f, 0xd6, 0x37, + 0xf9, 0xfc, 0x6b, 0x55, 0x9a, 0x4d, 0x1a, 0xac, 0xe6, 0xa1, + 0xf4, 0xcc, 0x7f, 0x10, 0x93, 0x3f, 0xeb, 0x9b, 0xf2, 0x15, + 0x69, 0x3e, 0x20, 0xa7, 0xfc, 0xf7, 0x23, 0xf0, 0x15, 0xf3, + 0xa, 0xf8, 0xca, 0xe5, 0x7f, 0xe5, 0xa3, 0x7f, 0x9f, 0xc6, + 0xa6, 0x4f, 0x1a, 0xdc, 0x7f, 0xcf, 0x47, 0xfc, 0xff, 00, + 0xfa, 0xf5, 0xa2, 0xcd, 0x64, 0x6a, 0xb3, 0xb9, 0x1f, 0x4f, + 0xa7, 0xc4, 0x4, 0x3f, 0xf2, 0xdc, 0xfe, 0x95, 0x62, 0x3f, + 0x88, 0xa, 0x7f, 0xe5, 0xb9, 0xfc, 0x85, 0x7c, 0xbc, 0xbe, + 0x39, 0x9c, 0x7f, 0xcb, 0x47, 0xff, 00, 0x3f, 0x8d, 0x4e, + 0x9e, 0x3e, 0x98, 0x7f, 0xcb, 0x47, 0x3f, 0xe7, 0xeb, 0x5a, + 0xac, 0xd9, 0x9b, 0x2c, 0xf2, 0x47, 0xd4, 0x69, 0xe3, 0xe5, + 0xff, 00, 0x9e, 0xe4, 0x7e, 0x55, 0x3a, 0xf8, 0xf4, 0x1f, + 0xf9, 0x78, 0x3f, 0xa5, 0x7c, 0xb8, 0x9f, 0x10, 0x25, 0xe3, + 0x32, 0xb7, 0xf9, 0xfc, 0x6a, 0xc2, 0x7c, 0x41, 0x90, 0x7f, + 0xcb, 0x56, 0xfc, 0xff, 00, 0xfa, 0xf5, 0xaa, 0xcd, 0xcd, + 0xe3, 0x9e, 0xbe, 0xe7, 0xd4, 0x71, 0xf8, 0xf5, 0x7b, 0x4e, + 0x7f, 0x4a, 0xb2, 0x9e, 0x3c, 0xe9, 0xfb, 0xf3, 0xf9, 0xa, + 0xf9, 0x72, 0x3f, 0x88, 0xce, 0x3f, 0xe5, 0xb1, 0xfc, 0xff, + 00, 0xfa, 0xf5, 0x66, 0x3f, 0x88, 0xd2, 0x7f, 0xcf, 0x66, + 0xff, 00, 0xbe, 0xbf, 0xfa, 0xf5, 0xaa, 0xcd, 0xfc, 0xcd, + 0xe3, 0x9e, 0xf9, 0x9f, 0x50, 0xaf, 0x8f, 0x79, 0xc7, 0x9e, + 0xdf, 0xa5, 0x4e, 0x9e, 0x3b, 0x1f, 0xf3, 0xd9, 0xbf, 0x4a, + 0xf9, 0x7e, 0x3f, 0x88, 0xcf, 0xff, 00, 0x3d, 0xdb, 0xfe, + 0xfa, 0xff, 00, 0xeb, 0xd5, 0x98, 0xfe, 0x24, 0x37, 0xfc, + 0xf6, 0x6f, 0xfb, 0xeb, 0xff, 00, 0xaf, 0x5b, 0x47, 0x37, + 0xf3, 0x37, 0x59, 0xf2, 0xee, 0x7d, 0x3e, 0x9e, 0x3c, 0xcf, + 0xfc, 0xb6, 0x3f, 0x90, 0xa9, 0x97, 0xc7, 0x43, 0xbc, 0xa7, + 0xf2, 0x15, 0xf3, 0x12, 0x7c, 0x48, 0x7f, 0xf9, 0xec, 0x7f, + 0x3f, 0xfe, 0xbd, 0x59, 0x8b, 0xe2, 0x3b, 0xf1, 0xfb, 0xe6, + 0xfc, 0xff, 00, 0xfa, 0xf5, 0xb2, 0xcd, 0xd7, 0x73, 0x78, + 0xe7, 0xab, 0xb9, 0xf4, 0xdc, 0x7e, 0x38, 0x4c, 0x7f, 0xad, + 0x3f, 0x90, 0xa9, 0xd3, 0xc7, 0x11, 0xe7, 0xef, 0x9f, 0xd2, + 0xbe, 0x66, 0x8f, 0xe2, 0x43, 0xf, 0xf9, 0x6c, 0x7f, 0xef, + 0xaf, 0xfe, 0xbd, 0x5a, 0x4f, 0x89, 0xc, 0x7f, 0xe5, 0xa9, + 0xfc, 0xff, 00, 0xfa, 0xf5, 0xaa, 0xcd, 0x97, 0x73, 0x78, + 0xe7, 0x8b, 0xb9, 0xf4, 0xaa, 0xf8, 0xda, 0x23, 0xff, 00, + 0x2d, 0xd, 0x4c, 0x9e, 0x32, 0x84, 0xf2, 0x5c, 0xd7, 0xcd, + 0x71, 0xfc, 0x46, 0x3f, 0xf3, 0xd4, 0xff, 00, 0xdf, 0x5f, + 0xfd, 0x7a, 0xb2, 0x9f, 0x11, 0x4f, 0x79, 0x8f, 0xe7, 0xff, + 00, 0xd7, 0xad, 0x56, 0x6d, 0x13, 0x75, 0x9d, 0xc7, 0xb9, + 0xf4, 0x8a, 0x78, 0xc6, 0xf, 0xef, 0x9a, 0x6b, 0xf8, 0xb2, + 0x6, 0xfe, 0x32, 0x3e, 0xb5, 0xf3, 0xc2, 0x7c, 0x46, 0xed, + 0xe6, 0x9f, 0xfb, 0xeb, 0xff, 00, 0xaf, 0x4f, 0x1f, 0x10, + 0x43, 0x1f, 0xf5, 0xa7, 0xf3, 0x1f, 0xe3, 0x5b, 0x47, 0x34, + 0x8b, 0x37, 0x8e, 0x73, 0x16, 0x7b, 0xe4, 0x9e, 0x25, 0x85, + 0xc7, 0x12, 0x73, 0x54, 0xe6, 0xd6, 0xd1, 0x81, 0xc4, 0x95, + 0xe2, 0x2b, 0xe3, 0xdd, 0xdd, 0x26, 0x3f, 0x98, 0xff, 00, + 0x1a, 0x7f, 0xfc, 0x26, 0xe5, 0xbf, 0xe5, 0xa9, 0xff, 00, + 0xbe, 0x87, 0xf8, 0xd7, 0x64, 0x31, 0xd0, 0x91, 0xdd, 0x4f, + 0x32, 0x84, 0xcf, 0x58, 0xba, 0xd5, 0x86, 0xf, 0xcf, 0x58, + 0x97, 0xba, 0xb7, 0x5f, 0x9a, 0xb8, 0x13, 0xe3, 0x56, 0x3f, + 0xf2, 0xd4, 0xff, 00, 0xdf, 0x43, 0xfc, 0x6a, 0x9, 0x7c, + 0x58, 0x1c, 0x1c, 0xbe, 0x7f, 0x1f, 0xfe, 0xbd, 0x76, 0x46, + 0xbc, 0x65, 0xb1, 0xe8, 0x43, 0x11, 0x9, 0xec, 0x74, 0xd7, + 0xda, 0xbf, 0xfb, 0x75, 0xce, 0xdf, 0xea, 0xbb, 0xb8, 0xce, + 0x6b, 0x26, 0xe3, 0x5f, 0x59, 0x8f, 0xc, 0x7f, 0x3a, 0xa1, + 0x25, 0xd9, 0x73, 0x9c, 0xe6, 0xb7, 0x4d, 0x3d, 0x8e, 0x94, + 0xd3, 0xd8, 0xb3, 0x73, 0x79, 0xd7, 0x26, 0xb9, 0x3f, 0x11, + 0x5e, 0x62, 0xde, 0x41, 0x9a, 0xd4, 0xbc, 0xb8, 0xe3, 0xa9, + 0xae, 0x57, 0xc4, 0x13, 0x19, 0x2d, 0xd8, 0x52, 0x9f, 0xc2, + 0xc9, 0x9f, 0xc2, 0xcf, 0x21, 0xf1, 0x7c, 0xbe, 0x64, 0xd2, + 0x73, 0xdc, 0xd7, 0x3, 0x36, 0x77, 0x1e, 0x7b, 0xd7, 0x79, + 0xe2, 0x94, 0xe5, 0x8f, 0xbd, 0x70, 0xd2, 0x8e, 0x4d, 0x7c, + 0x66, 0x25, 0xfe, 0xf0, 0xfc, 0xff, 00, 0x16, 0xff, 00, + 0x7a, 0x66, 0xdc, 0x2e, 0x73, 0x59, 0x17, 0x69, 0x80, 0x6b, + 0x6e, 0xe0, 0x75, 0xac, 0xd9, 0x2d, 0x9a, 0xea, 0x78, 0xa1, + 0x8f, 0x97, 0x91, 0x82, 0x28, 0x3e, 0xa4, 0xe0, 0x56, 0x94, + 0x5e, 0xa6, 0xd4, 0x1e, 0xb6, 0x3e, 0xbe, 0xfd, 0x82, 0x3c, + 0x18, 0xd2, 0x59, 0xdc, 0xea, 0x6c, 0x83, 0xcc, 0xba, 0xbd, + 0x8, 0xa4, 0xe7, 0x98, 0x97, 0x69, 0x6f, 0xd4, 0x1a, 0xfd, + 0x10, 0xb5, 0x4d, 0xaa, 0x7, 0x40, 0x2b, 0xe7, 0xf, 0xd9, + 0x2b, 0xc0, 0x3, 0xc2, 0x5e, 0xe, 0xd2, 0x20, 0x31, 0xa8, + 0x78, 0x6d, 0x12, 0x49, 0x4e, 0x3f, 0xe5, 0xb3, 0xaa, 0x96, + 0xed, 0xee, 0x6b, 0xe9, 0x38, 0x17, 0x8a, 0xfa, 0xda, 0x71, + 0xe5, 0x82, 0x47, 0xdb, 0xd2, 0x8f, 0x2c, 0x12, 0x2e, 0x42, + 0x38, 0xab, 0xf0, 0x2d, 0x52, 0x84, 0x70, 0x2b, 0x46, 0x5, + 0xe2, 0xb4, 0x36, 0x2e, 0x40, 0x39, 0x15, 0xa5, 0x6e, 0x2a, + 0x84, 0xb, 0xcd, 0x69, 0x5b, 0x8c, 0x62, 0x80, 0x2e, 0x46, + 0x2a, 0xe4, 0x23, 0x8a, 0xab, 0x18, 0xe6, 0xae, 0x44, 0x38, + 0x14, 0x1, 0x66, 0x3e, 0xd5, 0x61, 0x3a, 0x54, 0x11, 0x8e, + 0x95, 0x61, 0x7, 0x14, 0x1, 0x32, 0x54, 0xab, 0x51, 0xa8, + 0xa9, 0x7, 0x4a, 00, 0x7a, 0xf4, 0xa9, 0x7, 0x6a, 0x60, + 0x1d, 0xa9, 0xeb, 0x40, 0xe, 0xa2, 0x8a, 0x28, 0x1, 0xc2, + 0x96, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, + 0x28, 0x3, 0x31, 0x96, 0xa0, 0x91, 0x2a, 0xd3, 0xe, 0x6a, + 0x17, 0x5e, 0xb4, 0x1, 0x52, 0x45, 0xe6, 0xbc, 0xd3, 0xe2, + 0xa7, 0xc1, 0xdb, 0x1f, 0x88, 0x71, 0x46, 0xeb, 0x24, 0x56, + 0x37, 0x91, 0xe7, 0x73, 0x98, 0x3, 0xac, 0xab, 0x8f, 0xba, + 0xc3, 0x23, 0xb8, 0x1c, 0xf3, 0x8a, 0xf5, 0x6, 0x4a, 0xaf, + 0x22, 0x52, 0x69, 0x49, 0x59, 0x89, 0xa5, 0x25, 0x67, 0xb1, + 0xf9, 0xcb, 0xf1, 0x13, 0xe0, 0xb5, 0xef, 0x85, 0x35, 0x8b, + 0x8b, 0x52, 0x63, 0xf3, 0x14, 0x96, 0x11, 0x81, 0xc1, 0x5f, + 0x50, 0x7f, 0xe, 0xf8, 0xaf, 0x3d, 0x83, 0x41, 0xf3, 0x6e, + 0xbc, 0xb7, 0xc0, 0x23, 0xd4, 0x57, 0xe9, 0xf7, 0x89, 0x7c, + 0x29, 0xa6, 0x78, 0xa6, 0xc1, 0xed, 0x35, 0x2b, 0x55, 0x9e, + 0x36, 0x18, 0x7, 0x38, 0x65, 0x3e, 0xa0, 0x8e, 0x6b, 0xe6, + 0x7f, 0x8a, 0x1f, 00, 0xa7, 0xd0, 0x6e, 0x7e, 0xd9, 0xa7, + 0xc3, 0x2d, 0xee, 0x9e, 0xa0, 0x9f, 0x38, 0x6d, 0xdf, 0x1f, + 0xb3, 0x7a, 0xf4, 0xeb, 0x8c, 0x57, 0xe7, 0xd9, 0x9f, 0xb, + 0x46, 0xa3, 0xf6, 0xd8, 0x1d, 0x1f, 0x6e, 0x8f, 0xfc, 0x8f, + 0xca, 0xf3, 0x9e, 0xb, 0x85, 0x57, 0xf5, 0x8c, 0xb9, 0xf2, + 0xcb, 0xac, 0x7a, 0x3f, 0x4e, 0xdf, 0x91, 0xf3, 0xf5, 0x9f, + 0x83, 0x3, 0x81, 0xca, 0xff, 00, 0xdf, 0x35, 0xa9, 0xf, + 0x81, 0xf3, 0xdd, 0x49, 0xff, 00, 0x76, 0xbb, 0x8d, 0x2a, + 0xd6, 0x4, 0xa, 0xac, 0xc0, 0x30, 0x1c, 0x66, 0xba, 0xe8, + 0xb4, 0x55, 0x65, 0x52, 0x6, 0x46, 0x2b, 0xe7, 0xe9, 0xe1, + 0x2a, 0x50, 0xf7, 0x6b, 0x41, 0xc5, 0xf9, 0x9f, 0x2f, 0x4b, + 0x3, 0x57, 0xd, 0xee, 0xd7, 0x83, 0x8b, 0xf3, 0x3c, 0x71, + 0xfc, 0xa, 0x7f, 0xbc, 0x9f, 0xf7, 0xcd, 0x42, 0xfe, 0x7, + 0xc7, 0xf1, 0x27, 0xfd, 0xf3, 0x5e, 0xcd, 0x2e, 0x8c, 0x39, + 0xf9, 0x2a, 0xa4, 0x9a, 0x37, 0xfb, 0x6, 0xbb, 0x14, 0x20, + 0x77, 0xa8, 0x53, 0x3c, 0x75, 0xbc, 0x10, 0x7d, 0x53, 0xfe, + 0xf8, 0xa8, 0x9b, 0xc0, 0xf9, 0xfe, 0xe1, 0xff, 00, 0x80, + 0xa, 0xf6, 0x23, 0xa4, 0xf, 0xee, 0x1a, 0x63, 0x68, 0xe3, + 0xfb, 0x94, 0xf9, 0x20, 0x5f, 0xb3, 0x81, 0xe3, 0x4f, 0xe0, + 0x5c, 0xe7, 0x38, 0xfc, 0x14, 0x54, 0x2f, 0xe0, 0x51, 0xdf, + 0x1f, 0xf7, 0xc8, 0xaf, 0x67, 0x6d, 0x19, 0x4f, 0xf0, 0x53, + 0xe, 0x8a, 0xbf, 0xdc, 0x34, 0xbd, 0x9c, 0x9, 0xf6, 0x50, + 0x3c, 0x4d, 0xfc, 0xc, 0xbf, 0xec, 0xfe, 0x2b, 0x50, 0xbf, + 0x81, 0xd4, 0x9e, 0xa8, 0x3f, 0xe0, 0x35, 0xed, 0xc7, 0x44, + 0x5f, 0xee, 0x1a, 0x63, 0x68, 0x4a, 0x7f, 0x80, 0xd2, 0x74, + 0xa2, 0xc5, 0xec, 0x20, 0xcf, 0xe, 0x7f, 0x2, 0x83, 0xdd, + 0x3f, 0xef, 0x9a, 0x81, 0xfc, 0x8, 0x8, 0xea, 0xbf, 0xf7, + 0xc8, 0xaf, 0x75, 0x6d, 0x5, 0x71, 0xf7, 0xd, 0x44, 0x7c, + 0x3e, 0xb8, 0xfb, 0x87, 0xf4, 0xa5, 0xec, 0x62, 0x4f, 0xd5, + 0xe0, 0x78, 0x53, 0x78, 0xc, 0x7b, 0x7f, 0xdf, 0x22, 0xa1, + 0x6f, 0x1, 0x8f, 0x55, 0xfc, 0x50, 0x57, 0xbb, 0x37, 0x87, + 0x93, 0xfb, 0x95, 0x1b, 0x78, 0x71, 0xf, 0xf0, 0x52, 0xfa, + 0xbc, 0x49, 0xfa, 0xac, 0x4f, 0x6, 0x7f, 0x2, 0xf, 0xef, + 0x20, 0xff, 00, 0x80, 0x54, 0xd, 0xe0, 0x51, 0x9f, 0xbe, + 0xa3, 0xfe, 0x3, 0x5e, 0xf6, 0xde, 0x1a, 0x8c, 0x8c, 0x6c, + 0xa8, 0x8f, 0x86, 0x50, 0xff, 00, 0x7, 0xeb, 0x52, 0xf0, + 0xc8, 0x97, 0x84, 0x47, 0x81, 0xbf, 0x81, 0x1, 0xff, 00, + 0x96, 0x8a, 0x7f, 0xe0, 0x35, 0x13, 0xf8, 0xc, 0xff, 00, + 0x79, 0x7f, 0xef, 0x9a, 0xf7, 0xd7, 0xf0, 0xba, 0x7f, 0xcf, + 0x33, 0xf9, 0xd4, 0x2f, 0xe1, 0x65, 0xc1, 0xf9, 0xf, 0xe9, + 0x4b, 0xea, 0xc8, 0x5f, 0x54, 0x47, 0x81, 0x37, 0x81, 0x1b, + 0xb1, 0x5f, 0xfb, 0xe6, 0xa1, 0x6f, 0x2, 0xb8, 0xfe, 0x25, + 0x1f, 0xf0, 0x1a, 0xf7, 0xe6, 0xf0, 0xaa, 0x9f, 0xf9, 0x66, + 0x7f, 0x4a, 0x89, 0xbc, 0x24, 0xa4, 0xf0, 0x94, 0xbe, 0xac, + 0x4f, 0xd5, 0x17, 0x63, 0xc0, 0x5f, 0xc1, 0xe, 0x3a, 0xb2, + 0xfe, 0x55, 0x13, 0x78, 0x29, 0x87, 0x1b, 0xc7, 0xe5, 0x5e, + 0xfc, 0xde, 0x12, 0x5c, 0x1f, 0x93, 0xfc, 0xfe, 0x75, 0xb, + 0xf8, 0x45, 0x7f, 0xb8, 0x6a, 0x7e, 0xac, 0x4b, 0xc2, 0x1e, + 0x2, 0xde, 0xe, 0x90, 0x7f, 0x10, 0xfc, 0xaa, 0x26, 0xf0, + 0x7c, 0xbf, 0xde, 0x1f, 0x95, 0x7b, 0xe3, 0x78, 0x4c, 0x3, + 0xfe, 0xac, 0xfe, 0x75, 0x13, 0xf8, 0x48, 0x7f, 0xcf, 0x23, + 0xf9, 0x8a, 0x9f, 0xab, 0x13, 0xf5, 0x53, 0xc1, 0xf, 0x84, + 0xa5, 0x1f, 0xc4, 0x3f, 0x2a, 0x89, 0xbc, 0x2d, 0x22, 0xf5, + 0x65, 0xfc, 0xab, 0xde, 0x9b, 0xc2, 0x3f, 0xf4, 0xc8, 0xfe, + 0x95, 0x13, 0xf8, 0x3f, 0x3f, 0xf2, 0xcc, 0xd2, 0xf6, 0xc, + 0x9f, 0xab, 0x48, 0xf0, 0x66, 0xf0, 0xcb, 0xf6, 0x23, 0xf2, + 0xa6, 0x37, 0x87, 0x25, 0xc7, 0x5f, 0xd2, 0xbd, 0xd9, 0xbc, + 0x1c, 0xf, 0xfc, 0xb3, 0xa8, 0x24, 0xf0, 0x70, 0xff, 00, + 0x9e, 0x47, 0xfc, 0xfe, 0x34, 0xbd, 0x8c, 0x85, 0xf5, 0x79, + 0x9e, 0x16, 0x7c, 0x3b, 0x20, 0xf4, 0xfc, 0xa9, 0x87, 0x42, + 0x71, 0xe9, 0x5e, 0xe0, 0xfe, 0x10, 0x51, 0xff, 00, 0x2c, + 0xbf, 0x95, 0x40, 0xde, 0x11, 0x1f, 0xf3, 0xc8, 0xfe, 0x62, + 0x97, 0xb2, 0x90, 0xbd, 0x84, 0xcf, 0x12, 0x3a, 0x23, 0xf, + 0x4a, 0x61, 0xd1, 0x9f, 0xd0, 0x7e, 0x55, 0xed, 0x6f, 0xe0, + 0xf5, 0x3f, 0xf2, 0xc9, 0x87, 0xe2, 0x2a, 0x27, 0xf0, 0x6a, + 0xff, 00, 0xcf, 0x26, 0x3f, 0x8d, 0x2f, 0x67, 0x31, 0x7b, + 0x2a, 0x87, 0x8b, 0x1d, 0x1d, 0xc7, 0x6f, 0xd2, 0x9a, 0xda, + 0x53, 0xe, 0xd5, 0xec, 0xaf, 0xe0, 0xc1, 0xff, 00, 0x3c, + 0x8d, 0x42, 0xfe, 0xd, 00, 0xf0, 0x86, 0x97, 0x24, 0xd0, + 0xbd, 0x9d, 0x53, 0xc7, 0x1b, 0x4b, 0x34, 0xc3, 0xa6, 0x9f, + 0x7a, 0xf5, 0xf7, 0xf0, 0x70, 0xfe, 0xe3, 0x55, 0x77, 0xf0, + 0x70, 0xff, 00, 0x9e, 0x64, 0xfe, 0x34, 0xad, 0x34, 0x4f, + 0x2d, 0x54, 0x79, 0x41, 0xd3, 0x88, 0xa6, 0x9d, 0x3d, 0xbd, + 0xff, 00, 0x2a, 0xf5, 0x36, 0xf0, 0x76, 0x7f, 0xe5, 0x99, + 0xfc, 0xff, 00, 0xfa, 0xf5, 0x13, 0x78, 0x37, 0xaf, 0xee, + 0xcd, 0x1e, 0xf8, 0x7e, 0xf0, 0xf2, 0xf3, 0x62, 0x47, 0x7a, + 0x4f, 0xb1, 0x37, 0xad, 0x7a, 0x63, 0xf8, 0x39, 0xbf, 0xe7, + 0x91, 0x35, 0x5d, 0xfc, 0x1e, 0xc3, 0xfe, 0x59, 0x37, 0xe7, + 0x45, 0xe6, 0x17, 0xa8, 0x8f, 0x3a, 0xfb, 0x23, 0xa, 0x3e, + 0xca, 0x6b, 0xbf, 0x7f, 0x8, 0xb0, 0x3f, 0xea, 0xdb, 0xf3, + 0xa8, 0x9b, 0xc2, 0x6f, 0xfd, 0xc3, 0xf5, 0xa5, 0xcd, 0x3e, + 0xc1, 0xcd, 0x53, 0xb1, 0xc1, 0xfd, 0x95, 0xa9, 0xd, 0xbb, + 0xa, 0xee, 0x1b, 0xc2, 0xae, 0x3f, 0x84, 0xfe, 0x75, 0x1b, + 0x78, 0x5e, 0x41, 0xfc, 0xd, 0xf9, 0xd1, 0xcf, 0x2e, 0xc2, + 0xf6, 0x93, 0xea, 0x8e, 0x2c, 0xc0, 0xde, 0xd4, 0x86, 0x16, + 0xae, 0xbd, 0xfc, 0x35, 0x20, 0xfe, 0x6, 0xfc, 0xea, 0x13, + 0xe1, 0xe9, 0x7, 0xf0, 0xd1, 0xce, 0xfb, 0xf, 0xda, 0xbe, + 0xc7, 0x28, 0x63, 0x6f, 0x4a, 0x36, 0x37, 0xa1, 0xae, 0xa0, + 0xf8, 0x7e, 0x4f, 0xee, 0x54, 0x6d, 0xa1, 0x4b, 0xd9, 0xd, + 0x1c, 0xfe, 0x41, 0xed, 0x9f, 0x63, 0x9a, 0xda, 0x7d, 0x28, + 0xc7, 0xb5, 0x74, 0x2d, 0xa2, 0xc9, 0xfd, 0xc3, 0xf9, 0xd4, + 0x67, 0x47, 0x90, 0x75, 0x8f, 0xf5, 0x14, 0x7b, 0x44, 0x35, + 0x59, 0x76, 0x30, 0x68, 0xad, 0xb6, 0xd2, 0x1c, 0x1f, 0xb8, + 0x69, 0xad, 0xa5, 0x3f, 0xf7, 0xd, 0x3f, 0x68, 0x83, 0xda, + 0xa3, 0x1a, 0x8a, 0xd6, 0xfe, 0xca, 0x6e, 0xe8, 0x69, 0x87, + 0x4d, 0x6f, 0xee, 0x53, 0xe7, 0x43, 0xf6, 0xb1, 0x33, 0x28, + 0xad, 0x3, 0xa7, 0x1f, 0xee, 0x9a, 0x4f, 0xb0, 0xfb, 0x53, + 0xe7, 0x88, 0xfd, 0xa4, 0x4a, 0x14, 0x55, 0xd3, 0x60, 0x7f, + 0xc9, 0xa6, 0xfd, 0x85, 0xbd, 0xd, 0x1c, 0xc8, 0xaf, 0x69, + 0x12, 0xa5, 0x15, 0x6f, 0xec, 0x44, 0x76, 0x34, 0xcf, 0xb2, + 0x37, 0xa5, 0x3e, 0x64, 0x1c, 0xf1, 0x2b, 0xe6, 0x8a, 0x9c, + 0xda, 0xb0, 0xa3, 0xec, 0xcd, 0x8e, 0x94, 0x5d, 0x15, 0xcd, + 0x12, 0xa, 0x2a, 0x5f, 0x21, 0xbd, 0x39, 0xa4, 0xf2, 0x5f, + 0xd0, 0xd3, 0xb8, 0xf9, 0x91, 0x1d, 0x14, 0xf3, 0x13, 0x7a, + 0x1a, 0x4f, 0x2d, 0xb1, 0xd2, 0x9e, 0x81, 0x74, 0x36, 0x8a, + 0x76, 0xc6, 0xf4, 0xa4, 0xd8, 0x47, 0x63, 0x40, 0x5d, 0x9, + 0x46, 0x69, 0x76, 0x9f, 0x4a, 0x30, 0x68, 0x1, 0x32, 0x68, + 0xcd, 0x18, 0xa2, 0x80, 0x17, 0x79, 0xf5, 0xa5, 0xde, 0xde, + 0xb4, 0xda, 0x28, 0xb0, 0x58, 0x77, 0x98, 0xde, 0xa6, 0x94, + 0x48, 0xd9, 0xea, 0x7f, 0x3a, 0x65, 0x18, 0xa4, 0x16, 0x25, + 0xf3, 0x9b, 0xd7, 0xf5, 0xa3, 0xcf, 0x61, 0xde, 0xa2, 0xc5, + 0x18, 0xa0, 0x5c, 0xa8, 0x97, 0xed, 0x6, 0x97, 0xed, 0x2c, + 0x3d, 0x6a, 0x1a, 0x29, 0x59, 0xb, 0x95, 0x13, 0x8b, 0xa6, + 0xf7, 0xa7, 0x7d, 0xa9, 0xbd, 0x3f, 0x5a, 0xad, 0x45, 0x16, + 0x41, 0xca, 0xbb, 0x16, 0x4d, 0xdb, 0x7a, 0x52, 0x8b, 0xc3, + 0xe9, 0x55, 0x68, 0xa5, 0xca, 0x85, 0xc8, 0x8b, 0x82, 0xf4, + 0x8a, 0x51, 0x7e, 0x47, 0x73, 0xf9, 0xd5, 0x2a, 0x28, 0xe5, + 0x41, 0xc9, 0x1e, 0xc5, 0xf1, 0xa8, 0x1f, 0x56, 0xfc, 0xe9, + 0x45, 0xfb, 0xf, 0xe2, 0x6f, 0xce, 0xb3, 0xe8, 0xa3, 0x95, + 0xb, 0xd9, 0xc4, 0xd2, 0x1a, 0x9b, 0x8f, 0xe3, 0x61, 0xff, + 00, 0x2, 0xa7, 0x8d, 0x52, 0x41, 0xfc, 0x6d, 0xff, 00, + 0x7d, 0x1a, 0xca, 0xa2, 0x97, 0x2a, 0x17, 0xb3, 0x46, 0xc2, + 0xea, 0xd2, 0xaf, 0xf1, 0xb7, 0xfd, 0xf5, 0x52, 0x8d, 0x72, + 0x60, 0x3e, 0xfb, 0x7e, 0x66, 0xb0, 0xa9, 0x41, 0xc5, 0x1c, + 0xa1, 0xec, 0xd7, 0x73, 0x7d, 0x7c, 0x41, 0x38, 0xfe, 0x36, + 0xff, 00, 0xbe, 0x8d, 0x48, 0xbe, 0x23, 0x9d, 0x7f, 0x8d, + 0x8f, 0xfc, 0x8, 0xd7, 0x39, 0xb8, 0xfa, 0xd2, 0xef, 0x3e, + 0xa6, 0x8e, 0x57, 0xdc, 0x7c, 0x8f, 0xa3, 0x3a, 0x71, 0xe2, + 0x7b, 0x85, 0x1c, 0x33, 0x7f, 0xdf, 0x46, 0x90, 0xf8, 0xba, + 0xe5, 0x47, 0x56, 0xff, 00, 0xbe, 0xcd, 0x73, 0x25, 0xcf, + 0xa9, 0xa8, 0xe4, 0x90, 0x9a, 0xd2, 0x29, 0xf7, 0x2e, 0x2a, + 0x49, 0xee, 0x75, 0x63, 0xc7, 0x37, 0x9, 0xfc, 0x2d, 0xff, + 00, 0x7f, 0x2a, 0x44, 0xf8, 0x85, 0x2a, 0xf5, 0x57, 0x1f, + 0xf6, 0xd2, 0xb8, 0xa3, 0xcf, 0x7a, 0x6b, 0x29, 0x3d, 0xeb, + 0xaa, 0x15, 0x27, 0x1d, 0x99, 0xdb, 0xa, 0xd5, 0x21, 0xb3, + 0x3b, 0xe8, 0xfe, 0x21, 0xc8, 0xc7, 0xee, 0xb7, 0xfd, 0xf7, + 0x5a, 0x36, 0xfe, 0x34, 0x69, 0x7a, 0xee, 0xff, 00, 0xbe, + 0xab, 0xcb, 0xc2, 0x11, 0xde, 0x9e, 0x97, 0x12, 0x44, 0x7e, + 0x52, 0x6b, 0xbe, 0x9e, 0x3a, 0xa4, 0x77, 0x3d, 0x3a, 0x39, + 0x95, 0x58, 0x3d, 0x4f, 0x63, 0xb6, 0xf1, 0x26, 0xef, 0x5f, + 0xce, 0xb4, 0x21, 0xd7, 0x77, 0xe, 0x87, 0xf3, 0xaf, 0x1a, + 0xb6, 0xd6, 0xe5, 0x88, 0x8c, 0xb5, 0x6f, 0x69, 0xde, 0x20, + 0x27, 0xab, 0x8c, 0x7d, 0x2b, 0xdb, 0xc3, 0xe6, 0x57, 0x76, + 0x6c, 0xfa, 0x3c, 0x2e, 0x6d, 0x77, 0x66, 0xcf, 0x4d, 0x7d, + 0x44, 0x5c, 0xe, 0x41, 0x1f, 0x8d, 0x65, 0xeb, 0x3, 0x36, + 0xac, 0x7a, 0xd6, 0x2d, 0xae, 0xae, 0x1c, 0x7d, 0xea, 0x5b, + 0xcd, 0x57, 0x75, 0xbb, 0x2e, 0xe1, 0x5e, 0xea, 0xc5, 0x46, + 0x71, 0x67, 0xd2, 0x47, 0x17, 0x19, 0xc1, 0xea, 0x79, 0xff, + 00, 0x8a, 00, 0x66, 0x7f, 0xa9, 0xae, 0x12, 0x61, 0xc9, + 0xfa, 0xd7, 0x6d, 0xe2, 0x9, 0x3c, 0xc6, 0x93, 0x7, 0x3c, + 0xd7, 0x19, 0x30, 0xc9, 0x35, 0xf2, 0xd5, 0xdd, 0xe7, 0x73, + 0xe2, 0xf1, 0x32, 0xe6, 0xa9, 0x73, 0x3a, 0x75, 0xe2, 0xbd, + 0x2b, 0xf6, 0x71, 0xf8, 0x63, 0x2f, 0x8f, 0x7c, 0x73, 0xd, + 0xeb, 0x98, 0xd7, 0x4f, 0xd2, 0xa4, 0x59, 0xa5, 0x59, 0x17, + 0x77, 0x9a, 0xd9, 0xf9, 0x53, 0x1d, 0x7, 0x73, 0x9e, 0x7a, + 0x57, 0x9d, 0xb4, 0x4f, 0x71, 0x22, 0x45, 0x1a, 0x97, 0x91, + 0x88, 0x1, 0x47, 0x73, 0x5f, 0xa4, 0x7f, 0xb3, 0x1f, 0xc2, + 0x9b, 0x5f, 0xb, 0xf8, 0x6a, 0xc6, 0x3f, 0x24, 0x85, 0x8d, + 0x4, 0xb2, 0x48, 0x4f, 0xdf, 0x98, 0x81, 0x93, 0xf9, 0xe, + 0x95, 0xe9, 0xe5, 0xf4, 0xbd, 0xa4, 0xf9, 0x9e, 0xc8, 0xf6, + 0x32, 0xca, 0x3e, 0xd6, 0x7c, 0xcf, 0x64, 0x7b, 0x67, 0x82, + 0x74, 0x21, 0xa1, 0xe8, 0xb0, 0xc2, 0x76, 0x99, 0x5c, 0x7, + 0x7c, 0xc, 0x60, 0x91, 0xd3, 0xf0, 0xe9, 0x5d, 0x64, 0x2b, + 0xc0, 0xaa, 0x70, 0x20, 0x38, 0xad, 0x8, 0x90, 0x71, 0x5f, + 0x4e, 0x7d, 0x89, 0x6a, 0x11, 0xc8, 0xad, 0x8, 0x7, 0x15, + 0x52, 0x4, 0xe6, 0xb4, 0x21, 0x4e, 0x28, 0x2, 0xd4, 0xb, + 0xd2, 0xb4, 0xed, 0xc5, 0x51, 0x85, 0x3e, 0x61, 0x5a, 0x30, + 0xe, 0x28, 0x2, 0xd4, 0x62, 0xae, 0x46, 0xbd, 0x2a, 0xac, + 0x2b, 0xcd, 0x5d, 0x8c, 0x50, 0x4, 0xc8, 0x39, 0xa9, 0xd0, + 0x74, 0xa8, 0x90, 0x74, 0xa9, 0xd0, 0x50, 0x4, 0xab, 0x52, + 0x1, 0xd2, 0x98, 0xa2, 0xa4, 0x1d, 0x68, 0x1, 0xeb, 0xd6, + 0x9e, 0xb4, 0xc5, 0xe9, 0x52, 0xe, 0x94, 00, 0x52, 0xaf, + 0x26, 0x92, 0x95, 0x68, 0x1, 0xd4, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x51, 0x61, 0xed, + 0x51, 0xba, 0xe4, 0x54, 0xf8, 0xcd, 0x30, 0x8c, 0x9a, 00, + 0xac, 0xcb, 0x50, 0x32, 0x66, 0xae, 0x32, 0x8a, 0x85, 0xd4, + 0x50, 0x5, 0x27, 0x8f, 0x9a, 0x82, 0x48, 0x81, 0x7, 0x23, + 0xad, 0x5e, 0x64, 0xa8, 0x9e, 0x3e, 0x28, 0x3, 0x81, 0xf1, + 0x27, 0xc2, 0xaf, 0xe, 0xf8, 0x92, 0x49, 0x26, 0xb9, 0xb0, + 0x51, 0x72, 0xe7, 0x26, 0x64, 0x66, 0x4, 0x9f, 0xc0, 0xd7, + 0x9a, 0xea, 0x5f, 0x2, 0xf5, 0xbd, 0x2a, 0x69, 0x1b, 0x42, + 0xd5, 0x22, 0x78, 0x98, 0xf1, 0x1c, 0xab, 0xb3, 0x3, 0xd3, + 0x3f, 0x35, 0x7d, 00, 0xe9, 0xed, 0x50, 0xb4, 0x5c, 0x74, + 0xa8, 0x9c, 0x23, 0x35, 0x69, 0xab, 0xa3, 0x39, 0xd3, 0x85, + 0x45, 0xcb, 0x35, 0x75, 0xe6, 0x7c, 0xd3, 0x75, 0xe0, 0xcf, + 0x1c, 0x69, 0xd, 0x9b, 0x8d, 0x3a, 0x3b, 0xa8, 0xc7, 0x3b, + 0xa2, 0x96, 0x3f, 0xf1, 0xcf, 0xe9, 0x59, 0x13, 0xde, 0xea, + 0x56, 0x80, 0x8b, 0x9d, 0xe, 0x65, 0x20, 0xe0, 0x95, 0x6c, + 0xff, 00, 0x21, 0x5f, 0x53, 0x3c, 0x3c, 0x54, 0x12, 0x40, + 0x18, 0x10, 0x40, 0x20, 0xf1, 0x83, 0x5c, 0x33, 0xcb, 0xb0, + 0xb3, 0xde, 0x8, 0xf3, 0x2a, 0x65, 0x38, 0x2a, 0xba, 0xba, + 0x6b, 0xe5, 0xa7, 0xe4, 0x7c, 0xb3, 0xfd, 0xbb, 0x18, 0xff, + 00, 0x59, 0xa7, 0xdc, 0x2f, 0xfc, 00, 0xff, 00, 0x85, + 0x1f, 0xf0, 0x91, 0xe9, 0xe3, 0xef, 0xc7, 0x32, 0x7d, 0x52, + 0xbe, 0x97, 0x9f, 0x44, 0xb2, 0x9b, 0x3b, 0xec, 0xed, 0xdf, + 0x3c, 0x1d, 0xd1, 0x29, 0xfe, 0x95, 0x9f, 0x37, 0x83, 0xb4, + 0x69, 0x81, 0xf3, 0x34, 0x8b, 0x7, 0x7, 0xae, 0xeb, 0x64, + 0x3f, 0xd2, 0xb9, 0x5e, 0x4f, 0x85, 0x7b, 0x27, 0xf7, 0x9c, + 0x92, 0xc8, 0x70, 0x4f, 0xa3, 0x5f, 0x33, 0xe7, 0x7f, 0xf8, + 0x48, 0xf4, 0xb6, 0xfe, 0x29, 0x7, 0xd5, 0x29, 0x7f, 0xb7, + 0x74, 0x93, 0xd6, 0x62, 0x3f, 0xe0, 0x6, 0xbd, 0xf2, 0x5f, + 00, 0x78, 0x79, 0xba, 0xe8, 0x7a, 0x78, 0xff, 00, 0x76, + 0xd9, 0x7, 0xf2, 0x15, 0x4a, 0x5f, 0x86, 0x7e, 0x1b, 0x93, + 0xae, 0x8b, 0x6d, 0xff, 00, 0x1, 0x52, 0x3f, 0x95, 0x66, + 0xf2, 0x5c, 0x3f, 0x46, 0xcc, 0x9f, 0xf, 0x61, 0x1e, 0xcd, + 0xfd, 0xe7, 0x89, 0xd, 0x57, 0x4a, 0x7e, 0x97, 0x23, 0x3f, + 0xee, 0x37, 0xf8, 0x53, 0xd6, 0xf3, 0x4d, 0x90, 0xfc, 0xb3, + 0x83, 0xff, 00, 0x1, 0x6f, 0xf0, 0xaf, 0x5f, 0x93, 0xe1, + 0x37, 0x85, 0xe4, 0xe0, 0xe9, 0x8, 0x3f, 0xdd, 0x96, 0x41, + 0xfc, 0x9a, 0xa9, 0xcd, 0xf0, 0x73, 0xc3, 0x2f, 0xc2, 0xd8, + 0xb4, 0x67, 0xda, 0x69, 0xf, 0xf3, 0x6a, 0x87, 0x92, 0x51, + 0x7b, 0x49, 0x99, 0x3e, 0x1d, 0xa1, 0xd2, 0x6c, 0xf3, 0x15, + 0x16, 0x72, 0xf, 0x96, 0x54, 0xfd, 0x69, 0xff, 00, 0x61, + 0x88, 0xe3, 0xe, 0x87, 0xfe, 0x4, 0x2b, 0xbf, 0x9b, 0xe0, + 0x96, 0x82, 0xc7, 0xe4, 0x13, 0xa7, 0x18, 0xc0, 0x90, 0xff, + 00, 0x5a, 0xa3, 0x27, 0xc0, 0x9d, 0x33, 0x4, 0xc7, 0x7d, + 0x79, 0x19, 0xf4, 0xca, 0xe3, 0xf9, 0x56, 0x2f, 0x23, 0x8f, + 0x49, 0xbf, 0xb8, 0xc2, 0x5c, 0x39, 0x1f, 0xb3, 0x51, 0xfd, + 0xc7, 0x18, 0x74, 0xd4, 0x27, 0x82, 0xa7, 0xfe, 0x4, 0x29, + 0xe, 0x94, 0xf, 0x61, 0x5d, 0x5c, 0xbf, 0x4, 0x2, 0x7f, + 0xc7, 0xbe, 0xa9, 0x70, 0xf, 0xfb, 0x52, 0x63, 0xf9, 0x2d, + 0x54, 0x7f, 0x83, 0x9a, 0xba, 0x9f, 0xdc, 0xeb, 0x4, 0x7f, + 0xbd, 0x3b, 0x8f, 0xe4, 0xb5, 0x8b, 0xc8, 0xe7, 0xd2, 0xa1, + 0x84, 0xb8, 0x72, 0xa7, 0xd9, 0xa8, 0x73, 0xa7, 0x49, 0xf6, + 0xa6, 0x36, 0x93, 0x9f, 0xe1, 0xad, 0xb9, 0x3e, 0x12, 0xf8, + 0xa9, 0x7e, 0xe6, 0xaf, 0x1, 0x5f, 0xf6, 0xa7, 0x93, 0x3f, + 0xfa, 0xd, 0x30, 0xfc, 0x30, 0xf1, 0x7c, 0x67, 0x8b, 0xfb, + 0x66, 0xff, 00, 0xb6, 0xcd, 0xfd, 0x56, 0xb3, 0x79, 0x25, + 0x6e, 0x93, 0x46, 0x2f, 0x87, 0x71, 0x1d, 0x26, 0xbf, 0x13, + 0x15, 0xb4, 0x8c, 0xff, 00, 0xd, 0x46, 0xda, 0x47, 0xfb, + 0x35, 0xb6, 0x7e, 0x1f, 0xf8, 0xd2, 0x33, 0xc4, 0xf6, 0xed, + 0xff, 00, 0x3, 0x53, 0xfc, 0xd6, 0xa3, 0x7f, 0x7, 0xf8, + 0xce, 0x2c, 0xe6, 0x28, 0x64, 0xc7, 0xa1, 0x53, 0xfc, 0x85, + 0x43, 0xc9, 0x71, 0x3d, 0xd7, 0xe2, 0x43, 0xe1, 0xfc, 0x5a, + 0xda, 0x4b, 0xf1, 0x31, 0x8e, 0x91, 0x8f, 0xe1, 0xa6, 0x36, + 0x91, 0x9f, 0xe1, 0xad, 0x56, 0xd1, 0x7c, 0x59, 0x8, 0xf9, + 0xb4, 0xdf, 0x33, 0xfd, 0xd4, 0x27, 0xf9, 0xa, 0x88, 0xc3, + 0xe2, 0x58, 0x87, 0xcf, 0xa0, 0x4c, 0xe3, 0xd5, 0x60, 0x73, + 0xfc, 0xab, 0x27, 0x94, 0xe2, 0xd7, 0x44, 0xfe, 0x66, 0xf, + 0x23, 0xc7, 0x2d, 0x92, 0x7f, 0x33, 0x30, 0xe8, 0xff, 00, + 0xec, 0xd3, 0xe, 0x8f, 0x91, 0xf7, 0x6b, 0x41, 0xae, 0xb5, + 0x84, 0xff, 00, 0x59, 0xa0, 0x5d, 0xaf, 0xae, 0x6d, 0x9c, + 0x52, 0x1d, 0x62, 0x58, 0xc7, 0xef, 0x74, 0xbb, 0xb4, 0xcf, + 0xfd, 0x31, 0x3f, 0xe3, 0x59, 0x3c, 0xb7, 0x19, 0x1f, 0xb2, + 0x63, 0x2c, 0xa3, 0x1d, 0x1f, 0xb1, 0xf8, 0xa3, 0x35, 0xb4, + 0x8e, 0xbf, 0x2d, 0x46, 0xda, 0x3f, 0xfb, 0x35, 0xa4, 0xfe, + 0x27, 0xb1, 0x4e, 0x24, 0xb6, 0xb9, 0x46, 0xf7, 0x41, 0xfe, + 0x34, 0xd1, 0xe2, 0x7d, 0x30, 0xff, 00, 0xc, 0xab, 0xf5, + 0x41, 0xfe, 0x35, 0x93, 0xc1, 0x62, 0x97, 0xfc, 0xbb, 0x66, + 0x2f, 0x2e, 0xc7, 0x2f, 0xf9, 0x74, 0xff, 00, 0x3, 0x30, + 0xe8, 0xa3, 0xfb, 0xa2, 0x98, 0xda, 0x2f, 0xfb, 0x23, 0xf3, + 0xad, 0x81, 0xe2, 0x2d, 0x2c, 0xf7, 0x71, 0xff, 00, 00, + 0xa7, 0xd, 0x6f, 0x4b, 0x61, 0xfe, 0xb3, 0x1f, 0x55, 0x35, + 0xf, 0xb, 0x89, 0x5f, 0xf2, 0xed, 0xfd, 0xc4, 0x3c, 0x16, + 0x2d, 0x6f, 0x49, 0xfd, 0xc6, 0xb, 0x68, 0x80, 0xff, 00, + 00, 0x34, 0xd6, 0xd0, 0xc7, 0xf7, 0x5, 0x74, 0x43, 0x53, + 0xd3, 0x5c, 0xf1, 0x3a, 0xf, 0xaf, 0x15, 0x28, 0xb9, 0xd3, + 0x9f, 0xfe, 0x5e, 0xa0, 0x19, 0xe7, 0x99, 00, 0xac, 0xdd, + 0x2a, 0xcb, 0x78, 0x3f, 0xb8, 0xc6, 0x54, 0x2b, 0xc7, 0x7a, + 0x6f, 0xee, 0x39, 0x36, 0xd0, 0xc7, 0xf7, 0x29, 0x87, 0x42, + 0x7, 0xf8, 0x6b, 0xb1, 0xdb, 0x64, 0xdd, 0x2e, 0x6d, 0xcf, + 0xfd, 0xb5, 0x14, 0xa2, 0xca, 0xdd, 0xf9, 0x59, 0x22, 0x23, + 0xd9, 0xc1, 0xac, 0xda, 0x92, 0xde, 0x3f, 0x81, 0x93, 0x53, + 0x5b, 0xc5, 0xfd, 0xc7, 0xe, 0xde, 0x1f, 0x53, 0xdb, 0xfc, + 0xfe, 0x75, 0x1b, 0xf8, 0x71, 0xf, 0xf0, 0xf, 0xf3, 0xf8, + 0xd7, 0x7d, 0xfd, 0x96, 0xad, 0xd3, 0x69, 0xfa, 0x52, 0x1d, + 0x27, 0x3f, 0xc3, 0x51, 0x75, 0xd8, 0xca, 0xeb, 0xaa, 0x3c, + 0xf8, 0xf8, 0x69, 0x3f, 0xb8, 0x3f, 0x33, 0x51, 0xb7, 0x86, + 0x97, 0xfb, 0xa3, 0x1f, 0x53, 0x5e, 0x82, 0x74, 0x9e, 0x7e, + 0xed, 0x35, 0xb4, 0x8f, 0xf6, 0x5, 0x2b, 0xa0, 0xe6, 0x89, + 0xe7, 0x6d, 0xe1, 0x95, 0xfe, 0xe0, 0xfc, 0xea, 0x26, 0xf0, + 0xb8, 0x3f, 0xc0, 0x2b, 0xd1, 0x4e, 0x91, 0xfe, 0xc0, 0xa6, + 0x7f, 0x64, 0xff, 00, 0xb3, 0x47, 0xba, 0x17, 0x81, 0xe7, + 0xd, 0xe1, 0x40, 0x7f, 0x84, 0x7f, 0x9f, 0xc6, 0xa0, 0x7f, + 0x9, 0x3, 0xd8, 0x7e, 0x5f, 0xfd, 0x7a, 0xf4, 0xc3, 0xa4, + 0x7f, 0xb1, 0x51, 0xb6, 0x91, 0xfe, 0xc5, 0x1e, 0xe8, 0x7b, + 0x87, 0x98, 0xb7, 0x84, 0x47, 0xf7, 0x7f, 0xcf, 0xe7, 0x51, + 0x37, 0x84, 0xbf, 0xd8, 0x5f, 0xd6, 0xbd, 0x44, 0xe9, 0x1c, + 0x7d, 0xca, 0x61, 0xd1, 0xff, 00, 0xd9, 0xa2, 0xd1, 0x17, + 0x2c, 0xf, 0x2b, 0x6f, 0x9, 0x1f, 0xf9, 0xe6, 0x3f, 0x3, + 0x51, 0x37, 0x84, 0x8f, 0xf7, 0x7, 0xe7, 0x5e, 0xaa, 0x74, + 0x61, 0xfd, 0xca, 0x63, 0x68, 0xc3, 0xfe, 0x79, 0x8f, 0xca, + 0x97, 0x2c, 0x45, 0xc9, 0x3, 0xca, 0x1b, 0xc2, 0xd, 0xfd, + 0xdf, 0xd4, 0x7f, 0x8d, 0x42, 0xfe, 0xe, 0x63, 0xd5, 0x7f, + 0x5f, 0xfe, 0xbd, 0x7a, 0xd1, 0xd1, 0x47, 0xf7, 0x17, 0xf2, + 0xa8, 0xce, 0x88, 0xa4, 0xff, 00, 0xab, 0x14, 0x38, 0x40, + 0x5e, 0xce, 0x7, 0x91, 0x3f, 0x83, 0x88, 0xfe, 0x11, 0xfe, + 0x7f, 0x1a, 0x85, 0xbc, 0x24, 0x7f, 0xb9, 0xfc, 0xeb, 0xd8, + 0x5b, 0x43, 0x5f, 0xf9, 0xe6, 0x2a, 0x36, 0xd1, 0x17, 0xfb, + 0x95, 0x3e, 0xca, 0x2, 0xf6, 0x50, 0x67, 0x8d, 0xbf, 0x84, + 0x49, 0xff, 00, 0x96, 0x79, 0xfc, 0x4d, 0x42, 0xde, 0xf, + 0x7, 0xfe, 0x59, 0xf, 0xcc, 0xd7, 0xb2, 0xb6, 0x84, 0xa7, + 0xf8, 0x2a, 0x36, 0xf0, 0xfa, 0x1f, 0xf9, 0x66, 0x3f, 0x2a, + 0x4e, 0x8c, 0x45, 0xec, 0x22, 0x78, 0xcb, 0xf8, 0x3b, 0xfd, + 0x81, 0xff, 00, 0x7d, 0x7f, 0xf5, 0xea, 0x16, 0xf0, 0x71, + 0x27, 0xee, 0x1, 0xf8, 0xff, 00, 0xf5, 0xeb, 0xda, 0x1b, + 0xc3, 0xb1, 0x9f, 0xf9, 0x64, 0xb9, 0xfa, 0x54, 0x67, 0xc3, + 0x68, 0x7f, 0xe5, 0x92, 0xfe, 0x54, 0xbd, 0x82, 0x27, 0xea, + 0xe8, 0xf1, 0x47, 0xf0, 0x6f, 0xfb, 0x23, 0xf3, 0xff, 00, + 0xeb, 0xd4, 0xf, 0xe0, 0xe0, 0x3f, 0xe5, 0x98, 0x3f, 0x9d, + 0x7b, 0x6b, 0x78, 0x69, 0x3f, 0xe7, 0x9a, 0xfe, 0xb5, 0x13, + 0x78, 0x65, 0x7f, 0xe7, 0x98, 0xfc, 0xcd, 0x2f, 0x60, 0x84, + 0xf0, 0xc9, 0x9e, 0x1e, 0xfe, 0xe, 0xcf, 0xf0, 0xf, 0xd6, + 0xa2, 0x6f, 0x6, 0xb7, 0x64, 0x15, 0xee, 0x2d, 0xe1, 0x75, + 0x3f, 0xf2, 0xcc, 0x7e, 0x75, 0x13, 0x78, 0x51, 0x71, 0xf7, + 0x5, 0x4f, 0xd5, 0xd1, 0x1f, 0x55, 0x47, 0x87, 0x37, 0x83, + 0x4f, 0x75, 0x5f, 0xf3, 0xf8, 0xd4, 0x4d, 0xe0, 0xc6, 0x3d, + 0x10, 0x1f, 0xc7, 0xff, 00, 0xaf, 0x5e, 0xe2, 0xde, 0x13, + 0x4f, 0xf9, 0xe6, 0x33, 0xf4, 0xa8, 0x5f, 0xc2, 0x49, 0xff, + 00, 0x3c, 0x97, 0xfe, 0xf9, 0xa9, 0xfa, 0xb9, 0x3f, 0x54, + 0x47, 0x86, 0xbf, 0x83, 0xd8, 0x1f, 0xf5, 0x63, 0xf3, 0xaa, + 0xef, 0xe0, 0xf6, 0xfe, 0xe0, 0xaf, 0x74, 0x7f, 0x8, 0xfa, + 0x44, 0xbf, 0x91, 0xa8, 0x4f, 0x84, 0xbd, 0x62, 0x5f, 0xcc, + 0xd2, 0xfa, 0xb9, 0x1f, 0x55, 0x3c, 0x31, 0xbc, 0x20, 0xe3, + 0xa2, 0xf, 0xf3, 0xf8, 0xd4, 0x67, 0xc2, 0x2e, 0x3f, 0x83, + 0xf5, 0xff, 00, 0xeb, 0xd7, 0xb9, 0x3f, 0x84, 0xbf, 0xe9, + 0x98, 0x15, 0x13, 0x78, 0x47, 0xfe, 0x99, 0x8a, 0x8f, 0xab, + 0x13, 0xf5, 0x43, 0xc3, 0x5f, 0xc2, 0x92, 0x8f, 0xe0, 0x1f, + 0x9f, 0xff, 00, 0x5e, 0xa1, 0x93, 0xc2, 0xf2, 0xf, 0xe1, + 0x1f, 0x9d, 0x7b, 0x93, 0xf8, 0x3c, 0x67, 0xfd, 0x50, 0xfc, + 0xaa, 0x17, 0xf0, 0x79, 0x1d, 0x22, 0x1f, 0x80, 0xa9, 0xfa, + 0xbb, 0x27, 0xea, 0xac, 0xf0, 0xe6, 0xf0, 0xcc, 0x98, 0xe8, + 0x2a, 0x26, 0xf0, 0xd4, 0xbf, 0xdd, 0xaf, 0x6f, 0x7f, 0x8, + 0x1f, 0xf9, 0xe2, 0x3f, 0x23, 0x50, 0xbf, 0x84, 0xf, 0xfc, + 0xf1, 0x1f, 0x91, 0xa5, 0xec, 0x24, 0x4f, 0xd5, 0xa4, 0x78, + 0x9b, 0x78, 0x72, 0x6f, 0xee, 0xff, 00, 0x2a, 0x89, 0xb4, + 0x9, 0x47, 0xf0, 0x8a, 0xf6, 0xb6, 0xf0, 0x78, 0xcf, 0xfa, + 0x95, 0xfd, 0x6a, 0x16, 0xf0, 0x72, 0xff, 00, 0xcf, 0x15, + 0xa5, 0xec, 0x64, 0x4f, 0xd5, 0xe7, 0xdc, 0xf1, 0x53, 0xa1, + 0xc9, 0xfd, 0xc1, 0x4c, 0x3a, 0x2c, 0xbf, 0xdd, 0x1f, 0x9d, + 0x7b, 0x43, 0xf8, 0x35, 0x7f, 0xe7, 0x98, 0xfc, 0x2a, 0x9, + 0x3c, 0x1a, 0x33, 0xc4, 0x54, 0xbd, 0x94, 0xd0, 0xbd, 0x84, + 0xcf, 0x1c, 0x3a, 0x3c, 0xa3, 0xf8, 0x3f, 0x51, 0x51, 0x9d, + 0x25, 0xc7, 0xf0, 0xf, 0xcc, 0x57, 0xb0, 0x3f, 0x83, 0x78, + 0xff, 00, 0x53, 0xfa, 0x1a, 0x81, 0xbc, 0x1b, 0xff, 00, + 0x4c, 0x47, 0xe4, 0x69, 0x7b, 0x39, 0x8b, 0xd9, 0x54, 0x47, + 0x91, 0xb6, 0x96, 0xff, 00, 0xdc, 0xfd, 0x45, 0x30, 0xe9, + 0xa7, 0x3f, 0x76, 0xbd, 0x69, 0xbc, 0x1a, 0x3f, 0xe7, 0x98, + 0xfc, 0xbf, 0xfa, 0xd5, 0xb, 0xf8, 0x3b, 0xfd, 0x81, 0x47, + 0x2c, 0xc3, 0x92, 0xa2, 0x3c, 0xab, 0xfb, 0x3f, 0x1f, 0xc2, + 0x7f, 0x2a, 0x61, 0xd3, 0xce, 0x4f, 0x18, 0xfc, 0x2b, 0xd4, + 0x9b, 0xc1, 0xbf, 0xf4, 0xcd, 0x4f, 0xe3, 0x50, 0x3f, 0x83, + 0x5b, 0xfe, 0x79, 0x2f, 0xeb, 0x4a, 0xd3, 0xb, 0x54, 0x3c, + 0xc8, 0xd8, 0xfb, 0x1a, 0x69, 0xb2, 0xc7, 0xa9, 0xaf, 0x49, + 0x7f, 0x6, 0x37, 0xfc, 0xf2, 0x1f, 0x97, 0xff, 00, 0x5a, + 0xa1, 0x7f, 0x7, 0x3f, 0xfc, 0xf3, 0xfd, 0x28, 0xf7, 0xc5, + 0x7a, 0x88, 0xf3, 0xbf, 0xb1, 0x9a, 0x69, 0xb4, 0x61, 0x5e, + 0x82, 0xde, 0xf, 0x61, 0xff, 00, 0x2c, 0xea, 0x16, 0xf0, + 0x9b, 0x8f, 0xf9, 0x66, 0x3f, 0x33, 0x45, 0xe7, 0xd8, 0x39, + 0xaa, 0x23, 0x84, 0x6b, 0x56, 0x2, 0x9a, 0x6d, 0x9c, 0x57, + 0x6e, 0xde, 0x14, 0x90, 0x7f, 0xcb, 0x31, 0xfa, 0xd4, 0x6d, + 0xe1, 0x69, 0x7, 0xf0, 0x1f, 0xca, 0x8e, 0x69, 0x76, 0xf, + 0x69, 0x2e, 0xc7, 0x17, 0xf6, 0x77, 0xa4, 0x36, 0xee, 0x3b, + 0x57, 0x60, 0x7c, 0x33, 0x28, 0xfe, 0x3, 0xfe, 0x7f, 0xa, + 0x88, 0xf8, 0x72, 0x5f, 0xee, 0x51, 0xce, 0xfb, 0x7, 0xb4, + 0x97, 0x63, 0x93, 0xf2, 0x5f, 0xd2, 0x8f, 0x29, 0xbd, 0x2b, + 0xa8, 0x6f, 0xf, 0xcd, 0xfd, 0xd1, 0xfa, 0xd4, 0x47, 0x40, + 0x98, 0x1f, 0xb9, 0xfa, 0x1f, 0xf0, 0xa3, 0xda, 0x79, 0xf, + 0xda, 0xbe, 0xc7, 0x37, 0xe5, 0xb0, 0xed, 0x48, 0x50, 0xfa, + 0x57, 0x44, 0x74, 0x29, 0xbf, 0xe7, 0x9f, 0xe8, 0x6a, 0x36, + 0xd1, 0xa4, 0x1f, 0xf2, 0xce, 0x8f, 0x68, 0x83, 0xda, 0x98, + 0x3b, 0x4f, 0xa5, 0x18, 0xad, 0xb3, 0xa4, 0x48, 0x3f, 0x83, + 0xf5, 0xa6, 0x9d, 0x29, 0xff, 00, 0xb8, 0x69, 0xfb, 0x44, + 0x3f, 0x6c, 0x8c, 0x5c, 0x51, 0x5a, 0xed, 0xa6, 0x3f, 0xfc, + 0xf3, 0x3f, 0x95, 0x30, 0xe9, 0xad, 0xfd, 0xc3, 0xf9, 0x53, + 0xf6, 0x91, 0x1f, 0xb5, 0x89, 0x97, 0x45, 0x69, 0x1d, 0x3d, + 0xbf, 0xb9, 0x4c, 0x36, 0x7, 0xd2, 0x9f, 0x3c, 0x47, 0xed, + 0x62, 0x50, 0xa2, 0xaf, 0x1b, 0xc, 0x76, 0xa6, 0xfd, 0x88, + 0xd1, 0xcf, 0x11, 0xfb, 0x48, 0x94, 0xea, 0x37, 0xab, 0xc6, + 0xcc, 0x8f, 0x5a, 0x63, 0x59, 0x9e, 0xe2, 0xa9, 0x4d, 0x14, + 0xa7, 0x1e, 0xe5, 0xa, 0x50, 0x33, 0x57, 0x45, 0xa7, 0xb5, + 0xd, 0x6a, 0x17, 0xb5, 0x5f, 0x3a, 0x2f, 0xda, 0x22, 0x9e, + 0xda, 0x42, 0xbe, 0xd5, 0x73, 0xc9, 0xa8, 0x5e, 0x2d, 0xb4, + 0xd4, 0xae, 0x35, 0x2b, 0x95, 0x18, 0x60, 0xd2, 0x2c, 0xad, + 0x11, 0xf9, 0x4d, 0x4c, 0xc9, 0x9e, 0x2a, 0x36, 0x80, 0xfa, + 0x56, 0xd1, 0x95, 0x8d, 0xe1, 0x3e, 0x57, 0x72, 0xfd, 0x8e, + 0xb4, 0xd1, 0x9c, 0x31, 0x20, 0xfd, 0x2b, 0x46, 0x4d, 0x50, + 0xbc, 0x67, 0xe6, 0x35, 0xcd, 0x98, 0xfd, 0xb1, 0x4e, 0x8e, + 0x77, 0x1f, 0x29, 0x26, 0xbd, 0x3a, 0x38, 0x96, 0xb4, 0x67, + 0xb3, 0x87, 0xc6, 0x35, 0xa3, 0x64, 0x7a, 0x95, 0xc6, 0xf7, + 0x61, 0x9e, 0xb5, 0x84, 0xf1, 0x65, 0x8f, 0x6a, 0xd8, 0xba, + 0x81, 0xb7, 0x6e, 0xeb, 0x5e, 0x97, 0xf0, 0x7b, 0xe0, 0xad, + 0xd7, 0x8d, 0x75, 0x8, 0x2f, 0xf5, 0xb, 0x62, 0xba, 0x3a, + 0xb7, 0xdd, 0x7d, 0xca, 0xd3, 0x1e, 0x70, 0x17, 0x8e, 0x47, + 0xe3, 0x5d, 0x14, 0xe3, 0x2c, 0x44, 0xd4, 0x21, 0xab, 0x3a, + 0xa9, 0x42, 0x78, 0xaa, 0x8a, 0x14, 0xd5, 0xd9, 0xa1, 0xfb, + 0x35, 0x7c, 0x15, 0xb8, 0xf1, 0x6, 0xb3, 0x6f, 0xaf, 0xea, + 0x36, 0x99, 0x81, 0x5c, 0x7d, 0x8a, 0x37, 0x38, 0x2e, 0xe0, + 0xe3, 0x77, 0x5e, 00, 0x3e, 0xbe, 0x95, 0xfa, 0x2f, 0xa2, + 0x69, 0xd1, 0xe9, 0x7a, 0x74, 0x36, 0xd1, 0xa8, 0x50, 0x8a, + 0x1, 0xc7, 0x3c, 0xf7, 0xae, 0x4f, 0xe1, 0xff, 00, 0x81, + 0x2d, 0xbc, 0x33, 0x61, 0x1, 0x36, 0xd1, 0x45, 0x2a, 0xae, + 0xd8, 0xe3, 0x41, 0xc4, 0x4b, 0xd8, 0xe, 0x38, 0xae, 0xf6, + 0x24, 0xe9, 0xc5, 0x7d, 0xae, 0x1e, 0x84, 0x68, 0x41, 0x45, + 0x1f, 0xa2, 0x61, 0x70, 0xf1, 0xc3, 0x53, 0x50, 0x45, 0x88, + 0x54, 0xe, 0xd5, 0x7e, 0x11, 0x55, 0xa1, 0x8f, 0xda, 0xaf, + 0x42, 0x80, 0x57, 0x49, 0xd6, 0x5a, 0xb7, 0x19, 0xc5, 0x68, + 0x42, 0x3a, 0x55, 0x48, 0x10, 0x71, 0x5a, 0x10, 0xa0, 0x27, + 0xa5, 00, 0x5a, 0x81, 0x79, 0xad, 0x18, 0x97, 0x8a, 0xa7, + 0x6e, 0xbd, 0x2b, 0x42, 0x21, 0xd2, 0x80, 0x2c, 0x44, 0xbc, + 0xd5, 0xb8, 0xc7, 0x4a, 0xaf, 0x12, 0xe6, 0xad, 0x20, 0xa0, + 0x9, 0xe3, 0x15, 0x3a, 0xf4, 0xa8, 0x63, 0x15, 0x3a, 0xaf, + 0x14, 00, 0xf5, 0xed, 0x4f, 0x5a, 0x45, 0x5a, 0x70, 0x18, + 0xa0, 0x7, 0x28, 0xe2, 0xa4, 0xa6, 0xaf, 0x5a, 0x75, 00, + 0x14, 0xe1, 0xd2, 0x9b, 0x4f, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0xa, 0xf8, + 0xf6, 0xa6, 0x30, 0xa9, 0x4f, 0x4a, 0x6e, 0x3d, 0xa8, 0x2, + 0x16, 0x5a, 0x89, 0x93, 0xa9, 0xab, 0x24, 0x73, 0xd2, 0xa3, + 0x64, 0x18, 0xa0, 0xa, 0xac, 0x9c, 0x54, 0x6e, 0x95, 0x6c, + 0xae, 0x29, 0x8e, 0x94, 0x1, 0x49, 0xa2, 0xe2, 0xa2, 0x31, + 0xfb, 0x55, 0xd6, 0x41, 0xe9, 0x51, 0xb2, 0x71, 0x40, 0x14, + 0x1e, 0x2f, 0x6a, 0x89, 0xa2, 0x1e, 0x95, 0x7d, 0xa3, 0xcd, + 0x46, 0xd1, 0xf5, 0xe0, 0xd0, 0x6, 0x7b, 0x46, 0x3f, 0xc8, + 0xa8, 0xda, 0x1c, 0xff, 00, 0xfa, 0xab, 0x40, 0xc4, 0x3d, + 0x29, 0x86, 0x21, 0xe9, 0x40, 0x19, 0xaf, 0x5, 0x46, 0x60, + 0xf6, 0xad, 0x23, 0xf, 0x14, 0xd3, 0xe, 0x28, 0x3, 0x30, + 0xc1, 0x4c, 0x30, 0x64, 0xe6, 0xb4, 0x9a, 0x2f, 0x6a, 0x67, + 0x91, 0x40, 0x19, 0xc6, 0xa, 0x61, 0x84, 0xe3, 0xa7, 0xe9, + 0x5a, 0x66, 0x1c, 0xe, 0x95, 0x1f, 0x92, 0x3d, 0x28, 0x3, + 0x37, 0xec, 0xfe, 0xd4, 0x86, 0xf, 0x6f, 0xd2, 0xb4, 0xbc, + 0x9a, 0x69, 0xb7, 0xc5, 00, 0x65, 0xf9, 0x39, 0xed, 0xfa, + 0x52, 0x1b, 0x7f, 0x6f, 0xd2, 0xb5, 0x3c, 0x9c, 0x53, 0x5a, + 0x1e, 0x3a, 0x50, 0x6, 0x49, 0xb7, 0x3, 0xb5, 0x21, 0xb7, + 0x1e, 0x9c, 0x56, 0x99, 0xb7, 0x18, 0xe9, 0x4d, 0x30, 0x71, + 0xd2, 0x80, 0x32, 0x8d, 0xb6, 0x7b, 0x50, 0x2d, 0x80, 0xad, + 0x2f, 0x26, 0x90, 0xc0, 0x3d, 0x28, 0x3, 0x25, 0xed, 0x11, + 0x8f, 0x2a, 0x1b, 0xea, 0x33, 0x50, 0xbe, 0x93, 0x6f, 0x27, + 0xde, 0xb7, 0x8c, 0xfd, 0x50, 0x1f, 0xe9, 0x5b, 0x26, 0xd8, + 0x7a, 0x52, 0x1b, 0x71, 0xe9, 0x40, 0x18, 0x12, 0x78, 0x7e, + 0xc1, 0xcf, 0xcd, 0x65, 0x6e, 0x7e, 0xb1, 0x2f, 0xf8, 0x54, + 0xf, 0xe1, 0x7d, 0x31, 0xfa, 0xe9, 0xd6, 0xc7, 0xfe, 0xd8, + 0xaf, 0xf8, 0x57, 0x46, 0x6d, 0xf3, 0xd4, 0x53, 0x4d, 0xb8, + 0xec, 0x28, 0x3, 0x97, 0x6f, 0x6, 0x68, 0xef, 0xd7, 0x4b, + 0xb5, 0x3f, 0xf6, 0xc5, 0x7f, 0xc2, 0xa2, 0x93, 0xc0, 0x7a, + 0x13, 0x8c, 0x1d, 0x26, 0xd7, 0xeb, 0xe4, 0x8c, 0xd7, 0x5a, + 0x6d, 0xf8, 0xe9, 0x4d, 0xfb, 0x31, 0xa0, 0xe, 0x22, 0x7f, + 0x86, 0xda, 0x14, 0xa7, 0x8b, 0x18, 0xe3, 0xff, 00, 0x71, + 0x14, 0x7f, 0x4a, 0xcf, 0x9b, 0xe1, 0x26, 0x89, 0x3e, 0x40, + 0x59, 0xe3, 0xc9, 0xcf, 0xc8, 0x54, 0x63, 0xff, 00, 0x1d, + 0xaf, 0x45, 0x36, 0xe4, 0x53, 0x7c, 0x83, 0x40, 0x1e, 0x62, + 0xdf, 0x5, 0xf4, 0x7c, 0xe5, 0x6e, 0xaf, 0xd7, 0xfe, 0xda, + 0x2f, 0xff, 00, 0x13, 0x51, 0xb7, 0xc1, 0xab, 0x5, 0xce, + 0xcd, 0x46, 0xf9, 0x7f, 0xe0, 0x4b, 0xfe, 0x15, 0xea, 0x1f, + 0x67, 0x3e, 0x94, 0x1b, 0x71, 0xdc, 0x54, 0xb8, 0xa7, 0xba, + 0x25, 0xc6, 0x2f, 0x74, 0x79, 0x67, 0xfc, 0x29, 0xf8, 0x86, + 0x76, 0x6a, 0xf7, 0xab, 0x4c, 0x6f, 0x84, 0x72, 0x2e, 0x76, + 0x6b, 0x77, 0x5f, 0xf0, 0x21, 0x8f, 0xeb, 0x5e, 0xa6, 0xd0, + 0xfb, 0x53, 0x7c, 0x8a, 0x9f, 0x65, 0x7, 0xbc, 0x57, 0xdc, + 0x47, 0xb2, 0xa6, 0xf7, 0x8a, 0xfb, 0x91, 0xe4, 0x92, 0xfc, + 0x2b, 0xd5, 0x23, 0xff, 00, 0x55, 0xac, 0x31, 0xff, 00, + 0x79, 0x98, 0x7f, 0x4a, 0xad, 0x27, 0xc3, 0x4f, 0x11, 0xa1, + 0xfd, 0xce, 0xa9, 0x3, 0x7f, 0xbf, 0x23, 0x8f, 0xfd, 0x94, + 0xd7, 0xb1, 0x34, 0x1e, 0xa2, 0x9a, 0x60, 0x1e, 0x95, 0xe, + 0x85, 0x27, 0xf6, 0x17, 0xdc, 0x66, 0xf0, 0xd4, 0x1e, 0xf0, + 0x5f, 0x72, 0x3c, 0x61, 0xfc, 0xd, 0xe2, 0xa8, 0x7, 0xfc, + 0x7c, 0x5b, 0x49, 0xf4, 0x77, 0x3f, 0xfb, 0x2d, 0x44, 0xfa, + 0x7, 0x8a, 0xad, 0xcf, 0xfc, 0x7b, 0x43, 0x2f, 0x19, 0xe0, + 0x39, 0xaf, 0x69, 0x68, 0x3b, 0x62, 0x9b, 0xf6, 0x70, 0x3b, + 0x62, 0xb3, 0x78, 0x3c, 0x3c, 0xb7, 0xa6, 0xbe, 0xe3, 0x29, + 0x60, 0x30, 0xb2, 0xde, 0x9a, 0xfb, 0x8f, 0x12, 0x92, 0xd7, + 0xc5, 0x31, 0x71, 0xfd, 0x8c, 0x24, 0xf7, 0x58, 0xdb, 0xfc, + 0x6a, 0x22, 0x7c, 0x46, 0xbf, 0x7b, 0x42, 0x6f, 0xc2, 0x36, + 0xaf, 0x70, 0x68, 0x6, 0x3a, 0x53, 0x3c, 0x8f, 0xad, 0x63, + 0xfd, 0x9d, 0x85, 0x7f, 0xf2, 0xed, 0x18, 0x3c, 0xab, 0x4, + 0xff, 00, 0xe5, 0xd2, 0x3c, 0x3d, 0xae, 0xf5, 0xb8, 0xfe, + 0xf6, 0x85, 0x2f, 0xe1, 0x1b, 0x7f, 0x85, 0x30, 0xea, 0x9a, + 0x8a, 0xff, 00, 0xac, 0xd1, 0x2e, 0x14, 0xff, 00, 0xd7, + 0x36, 0xff, 00, 0xa, 0xf7, 0x26, 0xb6, 0xea, 0x79, 0xa8, + 0xda, 0xd5, 0x4f, 0x51, 0x9f, 0xad, 0x43, 0xcb, 0x30, 0xaf, + 0xec, 0x19, 0xbc, 0x9f, 0x4, 0xff, 00, 0xe5, 0xda, 0xfc, + 0x4f, 0x10, 0xfe, 0xdb, 0x75, 0x27, 0xcc, 0xd2, 0xee, 0x57, + 0x1e, 0x91, 0x9f, 0xeb, 0x48, 0x7c, 0x45, 0x6a, 0xbc, 0xc9, + 0x69, 0x74, 0xbf, 0xf6, 0xcc, 0x7f, 0x8d, 0x7b, 0x4c, 0x9a, + 0x55, 0xbc, 0x9f, 0x7a, 0xde, 0x26, 0xcf, 0xf7, 0x90, 0x1a, + 0xae, 0xfe, 0x1b, 0xd3, 0xa4, 0x1f, 0x3e, 0x9f, 0x6a, 0xdf, + 0x58, 0x54, 0xff, 00, 0x4a, 0xc9, 0xe5, 0x18, 0x57, 0xd2, + 0xdf, 0x33, 0x9, 0x64, 0x58, 0x27, 0xf6, 0x5f, 0xde, 0x78, + 0xfa, 0xf8, 0x8b, 0x4d, 0x63, 0xca, 0xca, 0xbf, 0xef, 0x2a, + 0xff, 00, 0x8d, 0x4a, 0xba, 0xce, 0x9a, 0xff, 00, 0xf2, + 0xd3, 0x6f, 0xd7, 0x1f, 0xe3, 0x5e, 0xa6, 0xfe, 0x10, 0xd1, + 0xcb, 0x73, 0xa5, 0xd9, 0x8f, 0xa4, 0xa, 0x3f, 0xa5, 0x55, + 0x97, 0xc0, 0x7a, 0x2c, 0x84, 0xff, 00, 0xc4, 0xba, 0x11, + 0x9f, 0xee, 0xa0, 0x15, 0x8b, 0xc9, 0xb0, 0xfd, 0x1b, 0x30, + 0x7c, 0x3f, 0x85, 0x7b, 0x36, 0xbe, 0x67, 0x9d, 0xb, 0xed, + 0x31, 0xcf, 0x17, 0x31, 0x8f, 0xa9, 0x14, 0xef, 0x3f, 0x4e, + 0x61, 0xc5, 0xd4, 0x3f, 0xf7, 0xd0, 0xae, 0xe2, 0x4f, 0x86, + 0x7a, 0x14, 0xa0, 0x86, 0xb2, 0xc6, 0x7f, 0xba, 0xe4, 0x55, + 0x76, 0xf8, 0x53, 0xa0, 0xb7, 0x48, 0x25, 0x5f, 0xa4, 0xc6, + 0xb2, 0x79, 0x25, 0x2e, 0x93, 0x66, 0xf, 0x87, 0x28, 0xbd, + 0xaa, 0x33, 0x8f, 0xff, 00, 0x41, 0x6e, 0x97, 0x30, 0xfe, + 0xc, 0x28, 0xf2, 0x6d, 0x5b, 0xa5, 0xc4, 0x47, 0xfe, 0x6, + 0x2b, 0xa9, 0x93, 0xe1, 0x2e, 0x89, 0xd8, 0x5c, 0xa7, 0xd2, + 0x5f, 0xfe, 0xb5, 0x42, 0xdf, 0x8, 0xb4, 0x9e, 0x4a, 0x4f, + 0x7a, 0x87, 0xda, 0x45, 0xff, 00, 0xe2, 0x6a, 0x1e, 0x47, + 0x1e, 0x95, 0x1f, 0xdc, 0x8c, 0xdf, 0xd, 0xd3, 0xe9, 0x55, + 0xfd, 0xc7, 0x39, 0xf6, 0x38, 0xf, 0x49, 0x50, 0xff, 00, + 0xc0, 0x85, 0x28, 0xd3, 0xa3, 0x3d, 0x18, 0x1f, 0xca, 0xb7, + 0x24, 0xf8, 0x4f, 0x6e, 0xa3, 0xf7, 0x57, 0xd7, 0x6b, 0xf5, + 0x71, 0xfd, 0x16, 0xa0, 0x93, 0xe1, 0x85, 0xc8, 0xe2, 0x2d, + 0x52, 0x71, 0xfe, 0xf4, 0x87, 0xfc, 0x2b, 0x27, 0x91, 0xcb, + 0xec, 0xd4, 0xfc, 0xc, 0xa5, 0xc3, 0x6f, 0xec, 0xd5, 0xfb, + 0xd1, 0x92, 0xda, 0x48, 0x3d, 0xb3, 0x51, 0x9d, 0x1f, 0xfd, + 0x9f, 0xd2, 0xb4, 0xdf, 0xe1, 0xc6, 0xb5, 0x1f, 0x31, 0x6a, + 0xec, 0x7d, 0x99, 0xda, 0xa2, 0x6f, 0x4, 0x78, 0x8e, 0x23, + 0xf2, 0xde, 0xa4, 0x9f, 0x53, 0xfe, 0x26, 0xb2, 0x79, 0x25, + 0x65, 0xb4, 0xd1, 0x84, 0xb8, 0x76, 0xba, 0xda, 0xa2, 0xfc, + 0x4c, 0xff, 00, 0xec, 0x7f, 0xf6, 0x4f, 0xe5, 0x4c, 0x6d, + 0x1c, 0x7f, 0x76, 0xaf, 0x1f, 0xd, 0xf8, 0xb2, 0x21, 0xf2, + 0x84, 0x7f, 0xf8, 0x12, 0x7f, 0x8d, 0x44, 0xda, 0x57, 0x8c, + 0x10, 0xf3, 0x62, 0x8d, 0xf4, 0x68, 0xff, 00, 0xf8, 0xaa, + 0xc9, 0xe4, 0xd8, 0x9e, 0x8d, 0x7d, 0xe6, 0xf, 0x20, 0xc6, + 0x2d, 0x9a, 0xfb, 0xff, 00, 0xe0, 0x15, 0xe, 0x91, 0xfe, + 0xcf, 0xe9, 0x4c, 0x6d, 0x23, 0x8f, 0xba, 0x7f, 0x2a, 0xb4, + 0xd6, 0xde, 0x2b, 0x4e, 0xba, 0x60, 0x6c, 0x7a, 0x28, 0x3f, + 0xc8, 0xd4, 0x65, 0xfc, 0x4c, 0xa7, 0xe6, 0xd1, 0xc9, 0xc7, + 0xfd, 0x31, 0x63, 0xfc, 0x8d, 0x47, 0xf6, 0x4e, 0x2d, 0x76, + 0xfb, 0xcc, 0xde, 0x45, 0x8d, 0x5d, 0xbe, 0xf2, 0xa9, 0xd1, + 0xc0, 0xfe, 0x3, 0xf9, 0x53, 0x3f, 0xb1, 0xff, 00, 0xd9, + 0xfd, 0x2a, 0xd7, 0xdb, 0xb5, 0xa5, 0x27, 0xcd, 0xd1, 0x65, + 0x1f, 0x4b, 0x77, 0x14, 0xdf, 0xed, 0xbb, 0x88, 0x94, 0x19, + 0x74, 0xb9, 0x97, 0x3f, 0xf4, 0xcc, 0x8a, 0xc9, 0xe5, 0x98, + 0xb5, 0xf6, 0x4c, 0xde, 0x4f, 0x8e, 0x5f, 0x66, 0xe5, 0x56, + 0xd1, 0x87, 0xf7, 0x7f, 0x4a, 0x8c, 0xe8, 0xcb, 0xfd, 0xdf, + 0xd2, 0xaf, 0x1f, 0x14, 0x5b, 0xa7, 0x12, 0xda, 0x4e, 0x9f, + 0x86, 0x28, 0x1e, 0x28, 0xd3, 0xdb, 0xaa, 0x48, 0xbf, 0x5a, + 0xcd, 0xe0, 0x71, 0x6b, 0xfe, 0x5d, 0xb3, 0x7, 0x96, 0x63, + 0x56, 0xf4, 0xd9, 0x9e, 0x74, 0x55, 0xcf, 0xdc, 0x1f, 0x95, + 0x46, 0xda, 0x22, 0xff, 00, 0x70, 0x7e, 0x55, 0xb2, 0xbe, + 0x21, 0xd2, 0xdb, 0xab, 0xb2, 0xfd, 0x54, 0x9f, 0xe9, 0x4f, + 0x1a, 0xd6, 0x92, 0xff, 00, 0xf2, 0xf3, 0xb7, 0xea, 0x8d, + 0xfe, 0x15, 0x8b, 0xc3, 0x62, 0x16, 0xf0, 0x66, 0xf, 0x9, + 0x8a, 0x8e, 0xf4, 0xdf, 0xdc, 0x73, 0xef, 0xa2, 0x29, 0xfe, + 0x11, 0xf9, 0x7f, 0xf5, 0xaa, 0x36, 0xd0, 0x93, 0x1f, 0x77, + 0xf4, 0xae, 0x94, 0x6a, 0x3a, 0x5b, 0xf4, 0xbb, 0x4f, 0xc4, + 0x11, 0xfd, 0x29, 0xc2, 0xe7, 0x4d, 0x6e, 0x97, 0x70, 0xfe, + 0x2e, 0x5, 0x43, 0xa5, 0x59, 0x6f, 0x7, 0xf7, 0x19, 0x3a, + 0x15, 0xd6, 0xf4, 0xdf, 0xdc, 0xce, 0x50, 0xf8, 0x7d, 0xf, + 0xf0, 0x7e, 0x94, 0xc7, 0xf0, 0xf2, 0x7f, 0x73, 0xf4, 0x15, + 0xd8, 0x66, 0xc5, 0xba, 0x5d, 0x40, 0x7e, 0x92, 0xad, 0x2f, + 0xd9, 0xed, 0x9f, 0xa4, 0xb1, 0x9f, 0xa3, 0x8a, 0xcd, 0xc6, + 0x6b, 0x78, 0xb3, 0x37, 0x9, 0xad, 0xe0, 0xfe, 0xe6, 0x71, + 0x4d, 0xe1, 0xc8, 0xcf, 0xf0, 0xff, 00, 0xe3, 0xa2, 0xa3, + 0x6f, 0xd, 0xc6, 0x3f, 0x80, 0x7f, 0xdf, 0x35, 0xdd, 0xae, + 0x9b, 0x1b, 0x74, 0x20, 0xfd, 0xd, 0x7, 0x48, 0x7, 0xf8, + 0x4d, 0x45, 0xed, 0xba, 0x33, 0xbd, 0xb7, 0x47, 0x9f, 0xb7, + 0x86, 0xe3, 0x3d, 0x10, 0xf, 0xc2, 0xa2, 0x6f, 0xc, 0x46, + 0x7f, 0x84, 0x7e, 0x5f, 0xfd, 0x6a, 0xf4, 0x13, 0xa4, 0x8f, + 0xee, 0x9a, 0x6b, 0x69, 0x23, 0xfb, 0xb4, 0xaf, 0x1e, 0xc2, + 0xe6, 0x8f, 0x63, 0xce, 0xdb, 0xc2, 0xb1, 0x9f, 0xe1, 0xff, + 00, 0x3f, 0x95, 0x42, 0xfe, 0x13, 0x8f, 0xfb, 0xbf, 0xa0, + 0xff, 00, 0xa, 0xf4, 0x83, 0xa4, 0xff, 00, 0xb2, 0x6a, + 0x33, 0xa4, 0xff, 00, 0xb2, 0x68, 0xbc, 0x42, 0xf1, 0x3c, + 0xd9, 0xbc, 0x24, 0x9f, 0xdc, 0x3f, 0x90, 0xff, 00, 0xa, + 0x8d, 0xbc, 0x24, 0x9f, 0xdc, 0xff, 00, 0xc7, 0x6b, 0xd2, + 0xce, 0x91, 0xfe, 0xc9, 0xa8, 0xce, 0x91, 0xd7, 0xe4, 0x34, + 0x7b, 0xa1, 0x68, 0x1e, 0x66, 0xde, 0x12, 0x4f, 0xee, 0x7e, + 0x3b, 0x6a, 0x17, 0xf0, 0x8a, 0x9e, 0x88, 0x3f, 0x2f, 0xfe, + 0xb5, 0x7a, 0x87, 0xf6, 0x47, 0xfb, 0x26, 0x98, 0x74, 0x8c, + 0x7f, 0x9, 0xa2, 0xd1, 0xb, 0x40, 0xf2, 0xc6, 0xf0, 0x70, + 0xfe, 0xe8, 0xfc, 0xbf, 0xfa, 0xd5, 0xb, 0xf8, 0x38, 0x7a, + 0x7e, 0x9f, 0xfd, 0x6a, 0xf5, 0x63, 0xa4, 0x75, 0xf9, 0xd, + 0x33, 0xfb, 0x1c, 0x7f, 0x76, 0x8e, 0x48, 0x93, 0xc9, 0x6, + 0x79, 0x33, 0xf8, 0x40, 0x7f, 0x70, 0x9f, 0xf8, 0xf, 0xff, + 00, 0x5a, 0xa1, 0x6f, 0x8, 0x2f, 0xfc, 0xf3, 0x3f, 0xf7, + 0xc8, 0xaf, 0x5b, 0x6d, 0x18, 0x63, 0xee, 0x7f, 0x2a, 0x8c, + 0xe8, 0x83, 0xba, 0x7f, 0x2a, 0x9e, 0x48, 0x87, 0xb2, 0x81, + 0xe4, 0x6d, 0xe1, 0x1, 0xff, 00, 0x3c, 0xbf, 0x34, 0xa8, + 0x5b, 0xc1, 0xc0, 0xff, 00, 0xcb, 0x1f, 0xfc, 0x77, 0xff, + 00, 0xad, 0x5e, 0xc0, 0xda, 0x22, 0xe3, 0xee, 0x1a, 0x88, + 0xe8, 0x69, 0xff, 00, 0x3c, 0xe8, 0xf6, 0x71, 0x17, 0xb2, + 0x81, 0xe3, 0xd2, 0x78, 0x30, 0x1f, 0xf9, 0x66, 0x3f, 0xef, + 0x9f, 0xfe, 0xb5, 0x42, 0xfe, 0xc, 0x1f, 0xf3, 0xcc, 0x7e, + 0x5f, 0xfd, 0x6a, 0xf6, 0x46, 0xd0, 0x97, 0xfb, 0x94, 0xc6, + 0xd0, 0x13, 0x1f, 0xea, 0xff, 00, 0x95, 0x2f, 0x63, 0x2, + 0x7d, 0x84, 0x4f, 0x18, 0x6f, 0x6, 0xa8, 0xff, 00, 0x96, + 0x67, 0xf2, 0xff, 00, 0xeb, 0x54, 0xf, 0xe0, 0xe5, 0xff, + 00, 0x9e, 0x47, 0xfe, 0xf9, 0xaf, 0x69, 0x6f, 0xf, 0x46, + 0x3f, 0xe5, 0x97, 0xe8, 0x2a, 0x33, 0xe1, 0xd8, 0xcf, 0xfc, + 0xb3, 0xc7, 0xe0, 0x2a, 0x7d, 0x82, 0x17, 0xd5, 0xe2, 0x78, + 0xa3, 0x78, 0x35, 0x48, 0xff, 00, 0x56, 0xdf, 0xf7, 0xc8, + 0xa8, 0x9f, 0xc1, 0x4b, 0xfd, 0xc6, 0xff, 00, 0xbe, 0x7f, + 0xfa, 0xd5, 0xed, 0x6d, 0xe1, 0xa8, 0xcf, 0xfc, 0xb3, 0x1f, + 0x95, 0x44, 0xde, 0x19, 0x8f, 0xb4, 0x7f, 0x95, 0x2f, 0x60, + 0x89, 0xfa, 0xb2, 0x3c, 0x49, 0xbc, 0x14, 0x7, 0xf0, 0x1f, + 0xfb, 0xe7, 0xff, 00, 0xad, 0x50, 0xbf, 0x82, 0xff, 00, + 0xd8, 0xfd, 0x3f, 0xfa, 0xd5, 0xed, 0xe7, 0xc3, 0xa, 0x7f, + 0xe5, 0x99, 0xfc, 0xea, 0x36, 0xf0, 0xb2, 0x7f, 0xcf, 0x22, + 0x6a, 0x7e, 0xae, 0x89, 0xfa, 0xac, 0x4f, 0xe, 0x7f, 0x6, + 0xf, 0xee, 0xfe, 0x9f, 0xfd, 0x6a, 0x82, 0x4f, 0x7, 0xf, + 0xee, 0x9f, 0xc8, 0x7f, 0x85, 0x7b, 0x9b, 0x78, 0x56, 0x3f, + 0xf9, 0xe6, 0x7f, 0x4a, 0x85, 0xbc, 0x26, 0x87, 0xfe, 0x59, + 0x1f, 0xc8, 0x52, 0xfa, 0xba, 0x27, 0xea, 0xa8, 0xf0, 0xc6, + 0xf0, 0x69, 0xfe, 0xe1, 0xfc, 0xbf, 0xfa, 0xd5, 0x13, 0x78, + 0x35, 0x87, 0xfc, 0xb3, 0x3f, 0xf7, 0xcf, 0xff, 00, 0x5a, + 0xbd, 0xc9, 0xbc, 0x24, 0xbf, 0xf3, 0xcc, 0xfe, 0x55, 0xb, + 0xf8, 0x45, 0x7f, 0xe7, 0x9f, 0xe9, 0x53, 0xf5, 0x72, 0x3e, + 0xa8, 0x78, 0x73, 0xf8, 0x39, 0xbf, 0xb8, 0x7f, 0xef, 0x9f, + 0xfe, 0xb5, 0x54, 0xb8, 0xf0, 0x9b, 0xaa, 0x9f, 0x95, 0x87, + 0xe1, 0xff, 00, 0xd6, 0xaf, 0x77, 0x6f, 0x8, 0x81, 0xff, + 00, 0x2c, 0xea, 0xa5, 0xc7, 0x84, 0xb2, 0x8, 0xf2, 0x89, + 0xfc, 0x6a, 0x7e, 0xae, 0x2f, 0xaa, 0x9e, 0x9, 0x37, 0x87, + 0x24, 0x8f, 0x9d, 0xad, 0xf9, 0x7f, 0xf5, 0xaa, 0x84, 0xda, + 0x4c, 0x91, 0xf5, 0x4f, 0xd2, 0xbd, 0xca, 0xef, 0xc1, 0xf8, + 0x7, 0xf7, 0x44, 0xa, 0xc2, 0xbe, 0xf0, 0x89, 0x19, 0xcc, + 0x67, 0xda, 0xb0, 0x95, 0x16, 0x8e, 0x59, 0xd0, 0x94, 0x4f, + 0x1f, 0x92, 0xc4, 0x8e, 0x30, 0x45, 0x40, 0xd6, 0x15, 0xe8, + 0xd7, 0xfe, 0x16, 0x61, 0x9c, 0x46, 0xd9, 0xac, 0x3b, 0x9d, + 0x15, 0xa1, 0xfe, 0x6, 0xc5, 0x72, 0x3a, 0x92, 0x83, 0xb3, + 0x38, 0xa5, 0x56, 0x54, 0xdd, 0x99, 0xc8, 0x35, 0x87, 0xb5, + 0x34, 0xd9, 0x7b, 0x57, 0x4c, 0xda, 0x7f, 0x1d, 0xd, 0x46, + 0xda, 0x7f, 0xa0, 0xa6, 0xb1, 0x3, 0x58, 0xa3, 0x99, 0x7b, + 0x2c, 0x9e, 0x5, 0x47, 0x1e, 0x98, 0xf2, 0xc8, 0xa9, 0x1a, + 0x33, 0xc8, 0xc7, 0x1, 0x54, 0x64, 0x93, 0x5d, 0xe6, 0x87, + 0xe0, 0x8d, 0x43, 0xc4, 0x57, 0xb, 0x15, 0x9d, 0xac, 0x92, + 0x2e, 0x40, 0x69, 0x71, 0xf2, 0xa8, 0xf5, 0x24, 0xf1, 0x5e, + 0xed, 0xf0, 0xd7, 0xe0, 0xd, 0xb5, 0xb5, 0xc4, 0x57, 0x2f, + 0x6c, 0xd7, 0xb7, 0x63, 0xef, 0x4b, 0x2e, 0xc, 0x49, 0xf4, + 0x4, 0x75, 0xfc, 0xeb, 0xdf, 0xcb, 0xf0, 0x78, 0x8c, 0x6b, + 0xbc, 0x15, 0xa3, 0xdc, 0xfa, 0x7c, 0xb3, 0x2f, 0xc5, 0x66, + 0x2d, 0x38, 0x2b, 0x47, 0xbb, 0xfd, 0x3b, 0x9e, 0x5f, 0xf0, + 0xc3, 0xe0, 0x1d, 0xcf, 0x88, 0x24, 0x86, 0xf3, 0x57, 0x86, + 0x54, 0x8c, 0x30, 0x64, 0xb4, 0x9, 0xf3, 0xbe, 0x3f, 0xbc, + 0xa, 0xe3, 0x15, 0xf6, 0x47, 0x82, 0x3c, 0x1, 0x67, 0xe1, + 0xdb, 0x58, 0x8b, 0x41, 0x18, 0x70, 0x3e, 0x58, 0x95, 00, + 0x48, 0xfe, 0x83, 0x15, 0xa9, 0xe1, 0xef, 0xa, 0xda, 0x68, + 0x91, 0xa9, 0x44, 0xdf, 0x3e, 0x39, 0x91, 0xb0, 0x71, 0xf4, + 0xe3, 0x81, 0x5d, 0x4, 0x69, 0x9e, 0x6b, 0xf4, 0x5c, 0x2e, + 0x12, 0x9e, 0x16, 0x3c, 0xb0, 0x5a, 0xf7, 0x3f, 0x58, 0xc1, + 0x60, 0x69, 0x60, 0xa1, 0xcb, 0xd, 0x5f, 0x57, 0xd5, 0x92, + 0xc4, 0x9e, 0xd5, 0x7a, 0x24, 0x35, 0x4, 0x51, 0xd5, 0xf8, + 0x53, 0xda, 0xbb, 0x4f, 0x40, 0x9e, 0x14, 0xe2, 0xae, 0xc2, + 0xbd, 0x38, 0xa8, 0x61, 0x4c, 0x1, 0xc5, 0x5e, 0x86, 0x3e, + 0x9c, 0x50, 0x5, 0x88, 0x17, 0xda, 0xaf, 0x42, 0xbc, 0x55, + 0x78, 0x53, 0xda, 0xaf, 0x44, 0xa2, 0x80, 0x2c, 0xc0, 0xbc, + 0x8a, 0xbd, 0x1a, 0x73, 0x55, 0xa1, 0x51, 0x9e, 0x95, 0x7a, + 0x25, 0xa0, 0x9, 0xa2, 0x15, 0x65, 0x14, 0x11, 0x50, 0xa2, + 0xd5, 0x94, 0x1d, 0x28, 0x2, 0x54, 0x1d, 0x2a, 0x75, 0xed, + 0x51, 0xa2, 0xd4, 0x8b, 0xfc, 0xa8, 0x2, 0x45, 0xa7, 0x1, + 0x4d, 0x5e, 0x31, 0x52, 0x1, 0x9a, 00, 0x55, 0xa5, 0xa0, + 0xc, 0x51, 0x40, 00, 0xe4, 0xd3, 0xe9, 0xab, 0xd6, 0x9d, + 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, + 0x14, 0x51, 0x40, 0x11, 0x6d, 0xa4, 0xa7, 0xd2, 0x6d, 0xa0, + 0x6, 0x6d, 0xa6, 0x32, 0xf3, 0x52, 0x9e, 0xd, 0x37, 0x6f, + 0x34, 0x1, 0x11, 0x5a, 0x61, 0x5a, 0x9d, 0x87, 0xbd, 0x37, + 0x14, 0x1, 0x5c, 0xa0, 0x34, 0xd6, 0x8c, 0x55, 0x82, 0xb8, + 0x34, 0xc2, 0xb4, 0x1, 0x59, 0xa3, 00, 0x9a, 0x61, 0x8c, + 0x1a, 0xb6, 0x50, 0x62, 0x9b, 0xb0, 0x50, 0x5, 0x33, 0x10, + 0x1d, 0xa9, 0x8d, 0x17, 0xb5, 0x5c, 0x31, 0x83, 0x4c, 0x64, + 0x19, 0xe9, 0x40, 0x15, 0x3c, 0x9f, 0x63, 0x4c, 0x30, 0x8c, + 0xf2, 0xb5, 0x77, 0xcb, 0xf6, 0xa6, 0xb4, 0x54, 0x1, 0x49, + 0xa2, 0x7, 0xb5, 0x33, 0xc9, 0xab, 0xde, 0x5d, 0x27, 0x97, + 0x40, 0x14, 0x5a, 0x1, 0xe9, 0x4d, 0xf2, 0x7, 0xa5, 0x5f, + 0x31, 0x53, 0x4c, 0x42, 0x80, 0x28, 0x79, 0x34, 0x86, 0xdc, + 0x7a, 0x55, 0xff, 00, 0x26, 0x90, 0xc2, 0x31, 0x40, 0x19, + 0xe6, 0x1, 0xe9, 0x4c, 0x30, 0xf3, 0x5a, 0x6, 0x1a, 0x4f, + 0x27, 0xda, 0x80, 0x33, 0xcd, 0xbf, 0xb5, 0x31, 0xa0, 0x19, + 0xe9, 0x5a, 0x46, 0xc, 0xf6, 0xa6, 0x18, 0x28, 0x3, 0x3b, + 0xc8, 0xf6, 0xa4, 0xf2, 0x33, 0xd8, 0xd6, 0x8f, 0x93, 0xed, + 0x48, 0x60, 0xf6, 0xa0, 0xc, 0xc6, 0xb7, 0x19, 0xa4, 0x30, + 0x7b, 0x56, 0x8f, 0x91, 0x49, 0xe4, 0xe2, 0x80, 0x33, 0x7e, + 0xcf, 0xed, 0x48, 0xd6, 0xe0, 0x76, 0xad, 0x13, 0xf, 0xb5, + 0x23, 0x43, 0x40, 0x19, 0xbe, 0x47, 0xb6, 0x29, 0x3e, 0xcf, + 0x5a, 0x1e, 0x4d, 0x1e, 0x4d, 00, 0x66, 0x9b, 0x51, 0xe9, + 0x48, 0x6d, 0x87, 0xa5, 0x69, 0x79, 0x14, 0x9e, 0x48, 0xa0, + 0xc, 0xd3, 0x6f, 0xed, 0x4c, 0x36, 0xc3, 0x15, 0xa9, 0xe4, + 0x67, 0xb5, 0x30, 0xc0, 0x3d, 0x28, 0x3, 0x33, 0xec, 0xe3, + 0x3d, 0x29, 0x1a, 0xdf, 0xda, 0xb4, 0xcc, 0x22, 0x98, 0x60, + 0xa0, 0xc, 0xc3, 0x6b, 0x93, 0xd2, 0x9a, 0x6d, 0xc0, 0xed, + 0x9a, 0xd3, 0xf2, 0x33, 0xda, 0x90, 0xc1, 0x40, 0x19, 0x46, + 0xdb, 0x3d, 0xa8, 0xfb, 0x2f, 0xb5, 0x69, 0x79, 0x34, 0x9e, + 0x41, 0xf4, 0xa0, 0xc, 0xa6, 0xb6, 0x1e, 0x94, 0xdf, 0xb3, + 0x7b, 0x56, 0xa3, 0x5b, 0xf3, 0x49, 0xe4, 0xfb, 0x50, 0x6, + 0x53, 0x5b, 0x71, 0xd2, 0x99, 0xf6, 0x60, 0x3b, 0x56, 0xa9, + 0xb7, 0x27, 0xb5, 0x27, 0xd9, 0xf1, 0x40, 0x19, 0x5f, 0x67, + 0x1e, 0x86, 0x93, 0xec, 0xb9, 0xec, 0x6b, 0x54, 0xc3, 0x4d, + 0x30, 0x7b, 0x50, 0x6, 0x51, 0xb4, 0x3, 0xb7, 0xeb, 0x4d, + 0x36, 0xc3, 0xd2, 0xb5, 0x3e, 0xcf, 0xed, 0x48, 0x60, 0x1e, + 0x94, 0x1, 0x97, 0xf6, 0x6a, 0x43, 0x6b, 0x8a, 0xd4, 0xf2, + 0x3d, 0xa9, 0xd, 0xb8, 0xc7, 0x4a, 00, 0xc9, 0x36, 0xfc, + 0xf4, 0xa6, 0xfd, 0x9f, 0xda, 0xb5, 0xd, 0xb8, 0xa3, 0xec, + 0xfe, 0xd4, 0x1, 0x90, 0xd6, 0xde, 0xd4, 0xdf, 0xb3, 0xfb, + 0x66, 0xb5, 0x4d, 0xb0, 0x26, 0x93, 0xec, 0xe0, 0x76, 0xa0, + 0xc, 0x96, 0xb6, 0xf6, 0x34, 0xd3, 0x6c, 0x2b, 0x55, 0xad, + 0xf2, 0x69, 0xbf, 0x66, 0xf5, 0xa0, 0xc, 0x96, 0xb6, 0x50, + 0x3a, 0x53, 0x7e, 0xce, 0xd, 0x6a, 0xb5, 0xbf, 0x34, 0xd3, + 0x6f, 0xed, 0x40, 0x19, 0x66, 0xd8, 0x7a, 0x53, 0x5a, 0xdc, + 0xe, 0xd5, 0xa8, 0xd6, 0xe7, 0xd2, 0x98, 0x6d, 0xb3, 0xda, + 0x80, 0x32, 0xcd, 0xb0, 0x27, 0x3b, 0x73, 0x4c, 0x36, 0x28, + 0x7a, 0xa0, 0x3f, 0x51, 0x5a, 0xa6, 00, 0x38, 0xc5, 0x1f, + 0x67, 0xff, 00, 0x38, 0xa0, 0xc, 0x86, 0xd3, 0xa1, 0xef, + 0x12, 0xff, 00, 0xdf, 0x22, 0xab, 0x49, 0xa2, 0x5a, 0x4a, + 0x30, 0xf6, 0xe8, 0xd5, 0xbe, 0x6d, 0xf0, 0x2a, 0x3f, 0x22, + 0x80, 0x39, 0x99, 0x7c, 0x25, 0xa6, 0x4c, 0x7e, 0x7b, 0x35, + 0x3f, 0xf0, 0x26, 0x1f, 0xd6, 0xaa, 0xcb, 0xe0, 0xd, 0x12, + 0x5f, 0xbd, 0x62, 0xf, 0xfd, 0xb4, 0x71, 0xfd, 0x6b, 0xaf, + 0xf2, 0x28, 0x36, 0xa2, 0x80, 0x38, 0xb3, 0xf0, 0xe7, 0x41, + 0xff, 00, 0x9f, 0x1, 0xff, 00, 0x7f, 0x5f, 0xff, 00, + 0x8a, 0xa6, 0xff, 00, 0xc2, 0xbb, 0xd0, 0x41, 0xff, 00, + 0x8f, 0x1, 0xff, 00, 0x7f, 0x64, 0xff, 00, 0xe2, 0xab, + 0xb3, 0x30, 0x1, 0xd2, 0x98, 0x6d, 0xf3, 0xd3, 0x8a, 00, + 0xe3, 0xcf, 0xc3, 0xcd, 0xb, 0x1c, 0x58, 0xe3, 0xe9, 0x2b, + 0xff, 00, 0xf1, 0x55, 0x1b, 0x7c, 0x3c, 0xd1, 0x7b, 0x5b, + 0x3a, 0xfd, 0x26, 0x6f, 0xf1, 0xae, 0xd3, 0xec, 0xc7, 0xeb, + 0x4c, 0x30, 0x73, 0xd2, 0x81, 0x34, 0x9e, 0xe7, 0x15, 0xff, + 00, 0xa, 0xeb, 0x49, 0xec, 0x93, 0x8f, 0xa4, 0xad, 0x4c, + 0x3f, 0xf, 0x6c, 0x13, 0x98, 0xe5, 0xb8, 0x4f, 0xac, 0x99, + 0xae, 0xd8, 0xdb, 0xfb, 0x52, 0x1b, 0x7f, 0x5a, 0x87, 0x8, + 0xbd, 0xd1, 0x2e, 0x9c, 0x1e, 0xe9, 0x33, 0x88, 0x3e, 0x6, + 0xa, 0x3f, 0x77, 0x7f, 0x2a, 0x7d, 0x50, 0x35, 0x46, 0x7c, + 0x1d, 0x7c, 0xa3, 0x11, 0xeb, 0x2c, 0xbf, 0x5b, 0x65, 0x3f, + 0xd6, 0xbb, 0x8f, 0x22, 0x9a, 0x61, 0xf6, 0xac, 0x9e, 0x1e, + 0x8b, 0xde, 0xb, 0xee, 0x30, 0x96, 0x17, 0xf, 0x2f, 0x8a, + 0x9a, 0x7f, 0x24, 0x70, 0x4f, 0xe1, 0x1d, 0x61, 0x49, 0xdb, + 0xac, 0x86, 0xfa, 0xdb, 0x28, 0xfe, 0xb5, 0x56, 0x5f, 0xc, + 0x78, 0x81, 0x4f, 0xcb, 0xa8, 0xab, 0x7d, 0x62, 0x41, 0x5e, + 0x88, 0x60, 0xf6, 0xa4, 0xf2, 00, 0xed, 0x51, 0xf5, 0x4c, + 0x3f, 0xfc, 0xfb, 0x5f, 0x71, 0x1f, 0x51, 0xc2, 0xff, 00, + 0xcf, 0xa8, 0xfd, 0xc8, 0xf3, 0x29, 0x7c, 0x3d, 0xe2, 0x85, + 0xfb, 0xb3, 0xc6, 0xdf, 0x5d, 0x83, 0xfa, 0x54, 0x47, 0x46, + 0xf1, 0x52, 0x7f, 0xc, 0x4d, 0xf8, 0xad, 0x7a, 0x8f, 0x92, + 0x3d, 0x29, 0x86, 0xe, 0x7d, 0xa8, 0xfa, 0xa6, 0x1f, 0xfe, + 0x7d, 0xaf, 0xb8, 0x4f, 0x3, 0x85, 0x7f, 0xf2, 0xea, 0x3f, + 0x72, 0x3c, 0xb8, 0xe9, 0xfe, 0x28, 0x53, 0xff, 00, 0x1e, + 0xa8, 0xdf, 0x8a, 0xff, 00, 0x8d, 0x21, 0xb7, 0xf1, 0x22, + 0x2, 0x5f, 0x4e, 0x52, 0x3d, 0x41, 0x1f, 0xe3, 0x5e, 0xa2, + 0x6d, 0xe9, 0x3c, 0x9a, 0x87, 0x81, 0xc3, 0x3f, 0xf9, 0x76, + 0x8c, 0xde, 0x5b, 0x83, 0x7f, 0xf2, 0xe9, 0x1e, 0x58, 0xd3, + 0xeb, 0x10, 0x9c, 0x49, 0xa6, 0x8c, 0xff, 00, 0xbc, 0x5, + 0x42, 0xda, 0xe5, 0xc4, 0x5f, 0xeb, 0x34, 0xde, 0x9c, 0x1f, + 0xde, 0xe3, 0xfa, 0x57, 0xac, 0x18, 0x29, 0xad, 0x7, 0xb5, + 0x64, 0xf2, 0xdc, 0x2b, 0xfb, 0x6, 0x32, 0xca, 0x30, 0x52, + 0xff, 00, 0x97, 0x67, 0x92, 0x8f, 0x15, 0x45, 0xd1, 0xec, + 0xa, 0xff, 00, 0xdb, 0x52, 0x7f, 0xa5, 0x4c, 0xbe, 0x25, + 0xb1, 0x3f, 0x7a, 0x16, 0x5f, 0xc4, 0x9a, 0xf5, 0x6, 0xb7, + 0x56, 0x18, 0x2a, 0x18, 0x7a, 0x11, 0x50, 0x3e, 0x93, 0x6d, + 0x27, 0xde, 0xb7, 0x8c, 0xfd, 0x56, 0xb1, 0x79, 0x4e, 0x15, + 0xf4, 0xfc, 0x4c, 0x25, 0x91, 0xe0, 0xa5, 0xf6, 0x5a, 0xf9, + 0x9e, 0x74, 0xbe, 0x20, 0xd2, 0x9b, 0xef, 0x19, 0x13, 0xe8, + 0xa4, 0xd3, 0xbf, 0xb6, 0x74, 0x86, 0xff, 00, 0x96, 0x8c, + 0x3f, 0xe0, 0x2d, 0x5d, 0xdb, 0xf8, 0x6f, 0x4f, 0x7c, 0xee, + 0xb2, 0x85, 0x81, 0xf5, 0x4a, 0x80, 0xf8, 0x4f, 0x49, 0x3d, + 0x74, 0xeb, 0x7f, 0xc1, 0x31, 0x59, 0x3c, 0x9b, 0xd, 0xd1, + 0xb3, 0x7, 0xc3, 0xf8, 0x47, 0xd5, 0xfd, 0xe7, 0x17, 0xfd, + 0xa9, 0xa4, 0x1f, 0xf9, 0x6f, 0xfa, 0x35, 0x3b, 0xfb, 0x43, + 0x48, 0x6f, 0xf9, 0x79, 0x51, 0xf5, 0xdd, 0x5d, 0x6b, 0xf8, + 0x33, 0x47, 0x6e, 0xba, 0x7c, 0x5f, 0x86, 0x47, 0xf5, 0xa8, + 0x9b, 0xc0, 0xba, 0x33, 0x75, 0xb1, 0x3, 0xe9, 0x23, 0x8f, + 0xeb, 0x50, 0xf2, 0x4a, 0x1d, 0x24, 0xff, 00, 0x3, 0x37, + 0xc3, 0xb8, 0x67, 0xb4, 0xa5, 0xf8, 0x7f, 0x91, 0xcd, 0x2c, + 0x9a, 0x74, 0xa7, 0xb, 0x32, 0x93, 0xf8, 0xd4, 0x89, 0x69, + 0x6a, 0xfd, 0x18, 0x1f, 0xce, 0xb6, 0x24, 0xf8, 0x7f, 0xa4, + 0xb7, 0xdd, 0x80, 0xa7, 0xd1, 0xd8, 0xff, 00, 0x5a, 0xad, + 0x27, 0xc3, 0x9b, 0x6, 0xfb, 0xac, 0xe9, 0xf9, 0x9f, 0xeb, + 0x59, 0x3c, 0x8e, 0x9f, 0xd9, 0x9b, 0x31, 0x97, 0xe, 0x53, + 0xfb, 0x35, 0x1f, 0xdc, 0x55, 0x3a, 0x4c, 0x6c, 0x32, 0x17, + 0x23, 0xeb, 0x4d, 0x3a, 0x3a, 0x7f, 0x77, 0xf5, 0xa9, 0x5f, + 0xe1, 0xad, 0xb8, 0x39, 0x4b, 0xb9, 0x13, 0xd8, 0x28, 0x3f, + 0xd6, 0x9b, 0xff, 00, 0xa, 0xf1, 0x90, 0xd, 0x9a, 0x94, + 0xab, 0xff, 00, 0x1, 0xff, 00, 0xeb, 0xd6, 0x2f, 0x23, + 0x7d, 0x2a, 0x7e, 0x6, 0xf, 0x86, 0xdf, 0xd9, 0xab, 0xf8, + 0x7f, 0xc1, 0x21, 0xfe, 0xc6, 0x43, 0xfc, 0x3f, 0xad, 0x31, + 0xb4, 0x55, 0xfe, 0xef, 0xeb, 0x56, 0x8f, 0x82, 0x2f, 0x14, + 0xfc, 0x9a, 0xbc, 0x80, 0x7f, 0xbb, 0xff, 00, 0xd7, 0xa0, + 0xf8, 0x43, 0x55, 0x4f, 0xbb, 0xac, 0xb9, 0xf6, 0x2a, 0x7f, + 0xc6, 0xb2, 0x79, 0x25, 0x6e, 0x93, 0x5f, 0x89, 0x83, 0xe1, + 0xda, 0xeb, 0x6a, 0x88, 0xa2, 0xda, 0x2a, 0xff, 00, 0x77, + 0xf5, 0xa6, 0x9d, 0x15, 0x7f, 0xb9, 0xfa, 0xd5, 0xb9, 0x3c, + 0x39, 0xaf, 0x46, 0x4e, 0xcd, 0x40, 0xb8, 0x1d, 0xe, 0xd1, + 0xfd, 0x4d, 0x40, 0xda, 0x3f, 0x89, 0x94, 0xfc, 0xb2, 0xee, + 0xfc, 0x23, 0xfe, 0xb5, 0x2f, 0x25, 0xc4, 0x2f, 0xb4, 0x8c, + 0xdf, 0xf, 0xe2, 0x96, 0xd2, 0x5f, 0x89, 0x1, 0xd1, 0x57, + 0xfb, 0x9f, 0xad, 0x31, 0xb4, 0x55, 0xc7, 0xdc, 0xfd, 0x6a, + 0x63, 0x67, 0xe2, 0x98, 0xcf, 0xcd, 0x8, 0x7f, 0xc6, 0x2a, + 0x43, 0x2e, 0xbf, 0x11, 0x3b, 0xec, 0x4b, 0x7f, 0xdf, 0x3f, + 0xd2, 0xb2, 0x79, 0x46, 0x29, 0x6d, 0x63, 0x27, 0x91, 0x63, + 0x16, 0xd6, 0x7f, 0x32, 0xf, 0xec, 0x55, 0xfe, 0xe7, 0xeb, + 0x50, 0xcb, 0xa2, 0x23, 0xf, 0xb9, 0xfa, 0xd5, 0xc3, 0xaa, + 0x6a, 0xb1, 0xf, 0x9f, 0x4a, 0x76, 0x1f, 0x43, 0xfd, 0x5, + 0x30, 0xeb, 0xf7, 0x9d, 0x1b, 0x48, 0x94, 0x7e, 0xd, 0xfe, + 0x15, 0x9b, 0xca, 0xf1, 0x6b, 0xec, 0xfe, 0x26, 0x2f, 0x26, + 0xc7, 0x2d, 0xa2, 0xbe, 0xf3, 0x26, 0x5f, 0xf, 0x44, 0x41, + 0xcc, 0x79, 0xfa, 0x93, 0x59, 0xb7, 0x5e, 0x15, 0x81, 0xf3, + 0xfb, 0xaf, 0xd4, 0xd7, 0x46, 0xda, 0xd5, 0xd3, 0xf0, 0x34, + 0xa9, 0x9, 0xfa, 0x37, 0xf8, 0x53, 0x3c, 0xdd, 0x52, 0xf1, + 0xb1, 0x16, 0x99, 0x22, 0x7d, 0x54, 0x8f, 0xe7, 0x42, 0xca, + 0xb1, 0x52, 0xd1, 0xc7, 0xf1, 0x1a, 0xc9, 0x71, 0xb3, 0xd1, + 0xc3, 0xf1, 0x47, 0x9e, 0x6a, 0x9e, 0x10, 0x8d, 0x57, 0xfd, + 0x58, 0xf6, 0xf9, 0xba, 0xfe, 0xb5, 0xc6, 0xea, 0xbe, 0x13, + 0x56, 0x62, 0x16, 0x3c, 0x92, 0x78, 0xe7, 0xff, 00, 0xaf, + 0x5e, 0xee, 0xbe, 0x13, 0xd6, 0xef, 0x48, 0xf3, 0x61, 0x11, + 0x46, 0x79, 0xc9, 0x28, 0x71, 0xfa, 0xe6, 0xb4, 0xad, 0xbe, + 0x19, 0x28, 0x6c, 0xcb, 0x77, 0x9e, 0xe4, 0x2a, 0x63, 0xfa, + 0xd4, 0xbe, 0x1c, 0xa9, 0x55, 0xfe, 0xf2, 0x69, 0x21, 0x3e, + 0x13, 0xab, 0x5d, 0xfe, 0xf2, 0xa2, 0x8a, 0xf2, 0x57, 0x67, + 0xcc, 0x71, 0x7c, 0x2e, 0xd4, 0x6e, 0xa4, 0x4, 0x42, 0xb0, + 0xc6, 0x7f, 0x89, 0x9c, 0x1f, 0xd3, 0x35, 0xe8, 0x7e, 0x14, + 0xf8, 0x9, 0x67, 0x7b, 0x16, 0xe9, 0x20, 0xfb, 0x71, 0x4, + 0x6e, 0x91, 0xdc, 0xc6, 0x7, 0xd0, 0x6, 0xaf, 0x79, 0xb0, + 0xf0, 0x6e, 0x99, 0x62, 0x14, 0x8b, 0x65, 0x79, 0x17, 0xf8, + 0xdc, 0x93, 0xfa, 0x13, 0x5b, 0x91, 0x40, 0x10, 00, 0xa3, + 00, 0x74, 0x2, 0xbd, 0x9c, 0x27, 0xf, 0xe0, 0xb0, 0x8f, + 0x99, 0xae, 0x67, 0xe7, 0xaf, 0xe1, 0xb1, 0xef, 0xe0, 0x38, + 0x5f, 0x2f, 0xc1, 0x3e, 0x67, 0x1e, 0x77, 0xfd, 0xed, 0x7f, + 0xd, 0x8e, 0x33, 0xc3, 0xff, 00, 0xb, 0xf4, 0x9d, 0x1e, + 0xce, 0x38, 0x4c, 0x26, 0x5d, 0xa3, 00, 0x2, 0x54, 0x7f, + 0x3c, 0x9f, 0xce, 0xbb, 0xb, 0x6b, 0x28, 0xed, 0xa2, 0x58, + 0xe3, 0x8c, 0x22, 0x2f, 00, 0xa, 0xb2, 0x90, 0xfb, 0x54, + 0xe9, 0xf, 0x3d, 0x2b, 0xe8, 0xd4, 0x54, 0x52, 0x4b, 0x63, + 0xeb, 0x23, 0x15, 0x4, 0xa3, 0x15, 0x64, 0x86, 0x45, 0x17, + 0xb5, 0x58, 0x8a, 0x3a, 0x91, 0x22, 0xab, 0x11, 0x43, 0xed, + 0x54, 0x50, 0x45, 0x15, 0x5f, 0x86, 0x3e, 0x3a, 0x53, 0x22, + 0x87, 0xa5, 0x5d, 0x86, 0x2e, 0x94, 0x1, 0x24, 0x31, 0x55, + 0xe8, 0x63, 0xa8, 0xe1, 0x8e, 0xae, 0xc5, 0x1f, 0x4a, 00, + 0x92, 0x24, 0xe2, 0xae, 0xc3, 0x1f, 0x35, 0x1c, 0x68, 0x6a, + 0xe4, 0x28, 0x7a, 0xd0, 0x4, 0xb0, 0xc7, 0xcd, 0x5c, 0x89, + 0x5, 0x45, 0x12, 0x74, 0xab, 0x71, 0xa9, 0xa0, 0x7, 0xaa, + 0x8a, 0x9d, 0x13, 0x8a, 0x6a, 0xa, 0x99, 0x46, 0x68, 0x1, + 0xeb, 0x4f, 0x1d, 0x29, 0x10, 0x71, 0x52, 00, 0x31, 0xd2, + 0x80, 0x15, 0x7b, 0x54, 0x83, 0xa5, 0x31, 0x69, 0xe3, 0xa5, + 00, 0x2d, 0x14, 0x52, 0x81, 0x40, 0x2, 0xd3, 0xa9, 0x29, + 0x68, 00, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, + 0xa2, 0x8a, 0x28, 0x1, 0x94, 0x53, 0xb0, 0x29, 0xa6, 0x80, + 0xc, 0x52, 0x6d, 0xa5, 0xa2, 0x80, 0x18, 0x57, 0x9a, 0x4d, + 0xb4, 0xf2, 0x28, 0xc0, 0xf5, 0xa0, 0x8, 0xc8, 0xa6, 0xed, + 0xcd, 0x48, 0x79, 0x14, 0x9b, 0x68, 0x2, 0x32, 0x29, 0x84, + 0x54, 0xfb, 0x69, 0xbb, 0x7e, 0xb4, 0x1, 0xe, 0xda, 0x4d, + 0x82, 0xa6, 0xc6, 0xd, 0x18, 0xf6, 0xa0, 0x8, 0xa, 0xe2, + 0x98, 0x63, 0xab, 0x5, 0x69, 0x36, 0x50, 0x4, 0x1e, 0x55, + 0x1e, 0x5f, 0xb5, 0x4d, 0xb2, 0x8d, 0x94, 0x1, 0x58, 0xc7, + 0xcd, 0x27, 0x97, 0xf5, 0xab, 0x25, 0x5, 0x26, 0xc1, 0x40, + 0x15, 0xcc, 0x74, 0x86, 0x2c, 0xd5, 0x8d, 0x98, 0x14, 0x6d, + 0xcd, 00, 0x56, 0xf2, 0x40, 0xa6, 0xf9, 0x75, 0x68, 0xa6, + 0x78, 0xa4, 0xf2, 0xc5, 00, 0x55, 0xf2, 0xe9, 0x3c, 0x9a, + 0xb5, 0xb0, 0xd3, 0x4a, 0x73, 0x40, 0x15, 0x4a, 0x9a, 0x6e, + 0xca, 0xb6, 0x63, 0xa4, 0xf2, 0xfe, 0xb4, 0x1, 0x50, 0xc5, + 0x49, 0xe5, 0xd5, 0xcf, 0x2f, 0xd8, 0xd2, 0x79, 0x7e, 0xd4, + 0x1, 0x4c, 0xc6, 0x4d, 0x34, 0xc3, 0x9a, 0xbd, 0xb3, 0x34, + 0xd6, 0x4e, 0x28, 0x2, 0x97, 0x92, 0x29, 0xc, 0x3e, 0x95, + 0x70, 0xc5, 0xed, 0x49, 0xb3, 0xda, 0x80, 0x29, 0x79, 0x54, + 0x79, 0x42, 0xae, 0x79, 0x74, 0x79, 0x42, 0x80, 0x29, 0x79, + 0x5c, 0x53, 0xc, 0x19, 0xad, 0xf, 0x2f, 0xeb, 0x4d, 0xf2, + 0xa8, 0x2, 0x87, 0x91, 0x48, 0xd1, 0x71, 0x57, 0x8c, 0x5c, + 0x53, 0x7c, 0x9f, 0xc6, 0x80, 0x28, 0x79, 0x19, 0xa6, 0x98, + 0x30, 0x2b, 0x47, 0xca, 0xa6, 0xb4, 0x1c, 0x50, 0x6, 0x6f, + 0x93, 0x47, 0x93, 0x5a, 0x6, 0xf, 0x63, 0x4d, 0xf2, 0x7d, + 0x8d, 00, 0x67, 0xb4, 0x14, 0xc3, 0xd, 0x69, 0x34, 0x1f, + 0x5a, 0x69, 0xb7, 0x3, 0xd6, 0x80, 0x33, 0xfc, 0xaa, 0x4f, + 0xb3, 0xd5, 0xff, 00, 0x23, 0xeb, 0x41, 0x84, 0xd0, 0x6, + 0x61, 0x87, 0x34, 0x9e, 0x4e, 0x45, 0x68, 0x18, 0x31, 0xd8, + 0xd2, 0x79, 0x54, 0x1, 0x43, 0xec, 0xf4, 0x9e, 0x4e, 0x3f, + 0xfd, 0x55, 0xa1, 0xe4, 0x7d, 0x69, 0xc, 0x1f, 0x5a, 00, + 0xce, 0x68, 0xa9, 0x9e, 0x4d, 0x69, 0xb4, 0x5c, 0x54, 0x7e, + 0x47, 0xd6, 0x80, 0x33, 0xfc, 0x80, 0x29, 0x8d, 0xf, 0x3d, + 0x2b, 0x4b, 0xc8, 0xfc, 0x29, 0x1a, 0x1c, 0x7a, 0xd0, 0x6, + 0x61, 0xb7, 0xcd, 0x35, 0xad, 0xc0, 0x35, 0xa5, 0xe4, 0x1f, + 0x7a, 0x43, 0x6f, 0x40, 0x19, 0x9f, 0x67, 0xa4, 0x36, 0xf5, + 0xa3, 0xe4, 0xd3, 0x7c, 0x93, 0xe9, 0x40, 0x19, 0x8d, 0x6d, + 0xcd, 0x37, 0xec, 0xf5, 0xa6, 0xd6, 0xfe, 0xb9, 0xa6, 0xf9, + 0x3, 0xde, 0x80, 0x33, 0x4c, 0x1e, 0xd4, 0xd3, 0x5, 0x69, + 0x98, 0xd, 0x37, 0xec, 0xf9, 0xa0, 0xc, 0xcf, 0x22, 0x90, + 0xc0, 0x4f, 0x6a, 0xd2, 0xf2, 0x71, 0xd8, 0xd1, 0xe4, 0xfb, + 0x1a, 00, 0xcb, 0x68, 0x38, 0xa6, 0xf9, 0x38, 0xad, 0x36, + 0xb7, 0x27, 0xb1, 0x34, 0x9e, 0x41, 0xf4, 0x34, 0x1, 0x96, + 0x61, 0xcf, 0x6a, 0x3e, 0xce, 0x3d, 0x2b, 0x4c, 0xc2, 0x41, + 0xe9, 0x4d, 0x30, 0x13, 0xda, 0x80, 0x32, 0xda, 0xde, 0x99, + 0xe4, 0x7b, 0x56, 0xa7, 0xd9, 0xfd, 0xa9, 0x3c, 0x8f, 0x63, + 0x40, 0x19, 0x9f, 0x67, 0xcd, 0x33, 0xec, 0xf5, 0xaa, 0x6d, + 0xf2, 0x2a, 0x3f, 0xb3, 0x7e, 0x14, 0x1, 0x99, 0xf6, 0x7a, + 0x63, 0x5b, 0xf3, 0x5a, 0xbe, 0x40, 0xa6, 0x1b, 0x7e, 0x68, + 0x3, 0x30, 0xdb, 0xd3, 0xc, 0x1c, 0xd6, 0xa1, 0xb6, 0xa6, + 0x1b, 0x7f, 0xad, 00, 0x66, 0x7d, 0x9c, 0x9a, 0x6b, 0xdb, + 0xe3, 0xad, 0x6a, 0x1b, 0x7a, 0x63, 0x5b, 0xe4, 0xf3, 0x40, + 0x19, 0x9e, 0x47, 0xe3, 0x4d, 0x36, 0xf9, 0xed, 0x5a, 0x7f, + 0x67, 0xfa, 0xd2, 0x18, 0xf, 0xa5, 00, 0x66, 0x7d, 0x9f, + 0x8a, 0x46, 0x83, 0x3, 0xa5, 0x69, 0xb4, 0x7, 0x1d, 0x29, + 0x9e, 0x47, 0xb5, 00, 0x66, 0x79, 0x54, 0xd3, 0x6f, 0x9a, + 0xd4, 0x30, 0x7b, 0x52, 0x79, 0x1f, 0x5a, 00, 0xcb, 0x30, + 0x76, 0xe6, 0x9b, 0xe4, 0xe2, 0xb5, 0x7e, 0xcf, 0xf5, 0xa8, + 0xcc, 0x3e, 0xc6, 0x80, 0x33, 0x4c, 0x39, 0xa6, 0x1b, 0x7d, + 0xbe, 0xf5, 0xa9, 0xe4, 0x7b, 0x1a, 0x63, 0x5b, 0xf3, 0xc8, + 0xe2, 0x80, 0x33, 0x7c, 0xaa, 0x6b, 0x43, 0x91, 0x5a, 0x46, + 0xdc, 0x76, 0x6, 0x9a, 0x61, 0xc0, 0xe8, 0x68, 0x3, 0x30, + 0xc1, 0x8e, 0xb4, 0x86, 0x2f, 0x4a, 0xd2, 0x36, 0xf9, 0x3d, + 0xe9, 0xa6, 0xc, 0x7a, 0x9a, 00, 0xcc, 0x30, 0x9e, 0xf4, + 0x9e, 0x45, 0x68, 0x9b, 0x7c, 0xd2, 0x7d, 0x98, 0xfb, 0xd0, + 0x6, 0x71, 0x82, 0x93, 0xcb, 0xc7, 0x6a, 0xd0, 0x30, 0x63, + 0xb5, 0x31, 0xa0, 0x24, 0xf4, 0x34, 0x1, 0x43, 0xca, 0xcf, + 0x6a, 0xc, 0x78, 0xab, 0xc6, 0xdc, 0xd1, 0xe4, 0x7b, 0x50, + 0x5, 0xd, 0x94, 0x9e, 0x57, 0xb7, 0xe9, 0x57, 0x8c, 0x27, + 0xd2, 0x93, 0xc9, 0x3e, 0x86, 0x80, 0x29, 0x79, 0x62, 0x8f, + 0x2b, 0xd2, 0xae, 0xf9, 0x1e, 0xc6, 0x90, 0x43, 0xcf, 0x4a, + 00, 0xa4, 0x21, 0xc5, 0x2f, 0x93, 0x9e, 0xbc, 0xd5, 0xef, + 0x27, 0xeb, 0x4b, 0xf6, 0x7f, 0x5a, 00, 0xa5, 0xe4, 0xe0, + 0x52, 0xac, 0x26, 0xae, 0x88, 0x29, 0xe2, 0x1e, 0x28, 0x2, + 0x9a, 0xc3, 0x8a, 0x95, 0x63, 0x20, 0x55, 0xa1, 0x7, 0x3d, + 0xea, 0x44, 0x87, 0xeb, 0x40, 0x15, 0x52, 0x23, 0x56, 0x23, + 0x87, 0x9a, 0x9d, 0x21, 0xe6, 0xac, 0x24, 0x18, 0xa0, 0x8, + 0x56, 0x3c, 0x55, 0x88, 0xe3, 0xa9, 0x52, 0x1a, 0xb3, 0x1c, + 0x44, 0xf6, 0xa0, 0x6, 0xc5, 0x16, 0x6a, 0xec, 0x71, 0x7b, + 0x51, 0x14, 0x27, 0xd2, 0xae, 0xc5, 0x17, 0xb5, 00, 0x24, + 0x51, 0x74, 0xe2, 0xae, 0x45, 0x1d, 0x11, 0x45, 0x56, 0xa3, + 0x8e, 0x80, 0x16, 0x28, 0xea, 0xdc, 0x51, 0xd3, 0x63, 0x8f, + 0xa5, 0x59, 0x8d, 0x31, 0x40, 0x12, 0x46, 0x87, 0xb5, 0x5a, + 0x8d, 0x4d, 0x47, 0x1a, 0x55, 0x88, 0xd2, 0x80, 0x1c, 0xa3, + 0x9a, 0x95, 0x6, 0x3b, 0x52, 0x5, 0xa9, 0x94, 0x70, 0x28, + 00, 0x3, 0x8a, 0x91, 0x79, 0x34, 0x80, 0x52, 0x81, 0x40, + 0xa, 0x5, 0x3e, 0x81, 0xd2, 0x8a, 00, 0x29, 0xcb, 0xd2, + 0x90, 0xc, 0xd2, 0xf4, 0xa0, 0x5, 0xa2, 0x8a, 0x28, 00, + 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, 0x28, 00, 0xa2, 0x8a, + 0x28, 00, 0xa2, 0x8a, 0x28, 0x1, 0x31, 0x4d, 0xa7, 0xd2, + 0x62, 0x80, 0x1b, 0x45, 0x3b, 0x14, 0xdc, 0x50, 0x2, 0x6d, + 0xa3, 0x6d, 0x2d, 0x14, 00, 0x9b, 0x69, 0x8, 0xc1, 0xa7, + 0x51, 0x81, 0x40, 0x11, 0x91, 0x46, 0xda, 0x7e, 0x5, 0x1b, + 0x68, 0x1, 0x9b, 0x28, 0xdb, 0x4f, 0xdb, 0x46, 0xda, 00, + 0x8f, 0x67, 0xb5, 0x1b, 0x6a, 0x4d, 0xb4, 0x6d, 0xa0, 0x8, + 0x4a, 0xd2, 0x14, 0xa9, 0x8a, 0xfe, 0x34, 0x9b, 0x7d, 0xa8, + 0x2, 0x2d, 0x94, 0x9b, 0x6a, 0x52, 0x38, 0xa4, 0xc5, 00, + 0x47, 0xb6, 0x93, 0x65, 0x4b, 0x8a, 0x31, 0x40, 0x11, 0x6d, + 0xa6, 0x95, 0xa9, 0x8a, 0xd2, 0x6d, 0xa0, 0x8, 0x76, 0xd1, + 0xb7, 0xda, 0xa6, 0xdb, 0x46, 0xca, 00, 0x83, 0x6d, 0x1b, + 0x6a, 0x6d, 0x94, 0x6c, 0xa0, 0x8, 0x76, 0x8a, 0x6b, 0x26, + 0x4d, 0x58, 0xd9, 0x41, 0x5c, 0x76, 0xa0, 0xa, 0xbe, 0x5d, + 0x2f, 0x96, 0x3d, 0xaa, 0x7d, 0xb9, 0xa3, 0x60, 0xa0, 0xa, + 0xfe, 0x5f, 0xd2, 0x93, 0xcb, 0x15, 0x67, 0x6f, 0xb5, 0x34, + 0xa5, 00, 0x40, 0x63, 0x2, 0x90, 0xc7, 0x53, 0xec, 0xa4, + 0xd9, 0x40, 0x10, 0x79, 0x34, 0xd3, 0x10, 0xcd, 0x59, 0xd8, + 0x69, 0x3c, 0xba, 00, 0xad, 0xe5, 0xd2, 0x79, 0x59, 0xab, + 0x5e, 0x5d, 0x21, 0x8f, 0x2, 0x80, 0x2a, 0x98, 0xa9, 0xbb, + 0x2a, 0xd1, 0x8f, 0x34, 0x9e, 0x5e, 0x28, 0x2, 0xa7, 0x95, + 0x9a, 0x3c, 0x9f, 0xc6, 0xad, 0x79, 0x74, 0x79, 0x54, 0x1, + 0x53, 0xcb, 0xa4, 0xf2, 0x73, 0x56, 0xfc, 0xbf, 0x6a, 0x3c, + 0xb3, 0x40, 0x14, 0x4c, 0x3c, 0xd1, 0xe4, 0x8a, 0xb6, 0xd1, + 0x1c, 0xf3, 0x49, 0xe5, 0xd0, 0x5, 0x43, 0x17, 0xb7, 0xe9, + 0x4d, 0x30, 0xe6, 0xae, 0x6c, 0xf6, 0xa3, 0xcb, 0xf6, 0xa0, + 0xa, 0x46, 0x2f, 0x6a, 0x4f, 0x26, 0xae, 0xf9, 0x7e, 0xd4, + 0x85, 0x38, 0xe9, 0x40, 0x14, 0x3c, 0x81, 0xf5, 0xa4, 0x31, + 0xa, 0xbd, 0xe4, 0xd2, 0x79, 0x3e, 0xd4, 0x1, 0x43, 0xc9, + 0xcf, 0xff, 00, 0xaa, 0x91, 0xa0, 0xe3, 0x9a, 0xd0, 0xf2, + 0x69, 0x8f, 0xf, 0x4a, 00, 0xce, 0xf2, 0x5, 0x1e, 0x45, + 0x5f, 0xf2, 0x68, 0xf2, 0xbd, 0x6, 0x68, 0x3, 0x39, 0xe1, + 0xf6, 0xa6, 0x79, 0x2, 0xb4, 0x5a, 0x2, 0x4f, 0x4a, 0x4f, + 0x23, 0xe9, 0x40, 0x19, 0xfe, 0x4d, 0x21, 0x87, 0xda, 0xb4, + 0x3c, 0x9f, 0x6a, 0x43, 0x6e, 0x68, 0x3, 0x30, 0xc1, 0xcf, + 0x4a, 0x3c, 0xaa, 0xd0, 0xfb, 0x3d, 0x37, 0xc8, 0xf6, 0xa0, + 0xc, 0xf3, 0xe, 0x69, 0x3c, 0x8f, 0x6a, 0xd1, 0xfb, 0x39, + 0x3d, 0xa9, 0x3e, 0xcf, 0xed, 0x40, 0x19, 0xe6, 0x11, 0x8a, + 0x61, 0x83, 0xaf, 0x15, 0xa5, 0xe4, 0x7b, 0x52, 0x34, 0x3c, + 0x50, 0x6, 0x67, 0x91, 0xfe, 0x71, 0x49, 0xe4, 0x8f, 0x4a, + 0xd1, 0xfb, 0x39, 0x34, 0x9e, 0x45, 00, 0x66, 0x18, 0x3d, + 0xa9, 0xd, 0xbd, 0x68, 0xb4, 0x27, 0x34, 0x9f, 0x67, 0x27, + 0xd2, 0x80, 0x33, 0xc, 0x3, 0xd2, 0x9b, 0xf6, 0x7f, 0x6a, + 0xd3, 0x68, 0x3d, 0xa9, 0x86, 0xc, 0x74, 0xa0, 0xc, 0xe3, + 0x6f, 0xc5, 0x46, 0x6d, 0x80, 0xad, 0x5f, 0xb3, 0x93, 0x4c, + 0x36, 0xfc, 0xd0, 0x6, 0x67, 0xd9, 0xfd, 0xa9, 0x86, 0xdb, + 0x9f, 0xfe, 0xb5, 0x6a, 0x18, 0x3d, 0xa9, 0xbf, 0x65, 0x27, + 0xda, 0x80, 0x33, 0x3e, 0xcd, 0x8a, 0x3e, 0xcf, 0xf4, 0xad, + 0x2f, 0xb3, 0x7f, 0x9c, 0x53, 0x7c, 0x9f, 0x6a, 00, 0xcd, + 0x36, 0xf8, 0x14, 0xc3, 0x6f, 0x8f, 0xff, 00, 0x55, 0x69, + 0xb5, 0xb9, 0x34, 0xd3, 0x6c, 0x7d, 0x28, 0x3, 0x30, 0xc1, + 0xfe, 0x71, 0x48, 0x6d, 0xf3, 0xda, 0xb5, 0x5, 0xbf, 0xb5, + 0x34, 0xc2, 0x73, 0xd2, 0x80, 0x33, 0xd, 0xbd, 0x30, 0xdb, + 0x8f, 0x4c, 0xd6, 0xa1, 0xb7, 0xe3, 0xa5, 0x37, 0xec, 0xfe, + 0xd4, 0x1, 0x96, 0x6d, 0xfd, 0xbf, 0x4a, 0x61, 0xb7, 0xcd, + 0x6a, 0x98, 0x49, 0xed, 0x4c, 0xfb, 0x31, 0xf4, 0xa0, 0xc, + 0xcf, 0xb3, 0x8f, 0x4a, 0x63, 0x40, 0x33, 0xd2, 0xb5, 0x7e, + 0xcf, 0xed, 0x4c, 0x36, 0xff, 00, 0xec, 0xd0, 0x6, 0x59, + 0xb7, 0x6, 0x98, 0xd6, 0xe3, 0x35, 0xab, 0xf6, 0x7f, 0x6a, + 0x61, 0xb7, 0x19, 0xe9, 0x40, 0x19, 0x7f, 0x67, 0xf6, 0xa4, + 0x36, 0xfc, 0xd6, 0xa1, 0xb7, 0xf6, 0xa6, 0x35, 0xb1, 0xf4, + 0xa0, 0xc, 0xb3, 0x6f, 0x48, 0x6d, 0xfe, 0x95, 0xa7, 0xf6, + 0x6a, 0x4f, 0xb3, 0xfb, 0x50, 0x6, 0x67, 0xd9, 0x8d, 0x21, + 0xb7, 0xad, 0x36, 0xb6, 0x34, 0x86, 0xd8, 0x8f, 0x4a, 00, + 0xcc, 0x30, 0x62, 0x93, 0xec, 0xf9, 0xed, 0xfa, 0x56, 0x9f, + 0xd9, 0xe8, 0x36, 0xed, 0xe9, 0x40, 0x19, 0x7f, 0x67, 0xff, + 00, 0x38, 0xa4, 0xf2, 0x3d, 0xab, 0x4c, 0xdb, 0x1f, 0x4a, + 0x5, 0xb1, 0xf4, 0xa0, 0xc, 0xef, 0x23, 0xdb, 0x1f, 0x85, + 0x2, 0xdc, 0x56, 0x99, 0xb7, 0x27, 0xb5, 0x2, 0xd8, 0x81, + 0xd2, 0x80, 0x33, 0x7c, 0x80, 0x29, 0xc2, 0x1e, 0x6b, 0x43, + 0xec, 0xdc, 0xf4, 0xa7, 0xfd, 0x9f, 0xda, 0x80, 0x33, 0xc4, + 0x15, 0x22, 0xc1, 0xed, 0x57, 0x96, 0xdf, 0xda, 0xa4, 0x5b, + 0x7f, 0x6a, 00, 0xa4, 0xb0, 0x55, 0x88, 0xe0, 0xfc, 0x6a, + 0xd0, 0xb6, 0xc0, 0xe9, 0x52, 0xad, 0xb9, 0xa0, 0xa, 0xe9, + 00, 0x1c, 0xd5, 0x88, 0xa1, 0xa9, 0xe3, 0xb7, 0x35, 0x61, + 0x20, 0xf6, 0xa0, 0x8, 0xe3, 0x86, 0xae, 0x45, 0x10, 0xa7, + 0x47, 0x6e, 0x41, 0xab, 0x51, 0xc3, 0x40, 0xd, 0x8e, 0x2e, + 0x2a, 0xc2, 0x45, 0xd2, 0x95, 0x13, 0xa0, 0xc5, 0x59, 0x48, + 0xe8, 0x1, 0x12, 0x2a, 0xb0, 0x89, 0x42, 0x47, 0x53, 0xa4, + 0x74, 00, 0xa8, 0x98, 0xc5, 0x4c, 0xa3, 0x14, 0x8a, 0xb5, + 0x22, 0xaf, 0x14, 00, 0xf5, 0x5e, 0x3a, 0xd4, 0x81, 0x79, + 0xa6, 0xa8, 0xa9, 0x16, 0x80, 00, 0x3d, 0x69, 0xdb, 0x69, + 0x29, 0xf4, 00, 0xa, 0x72, 0xd3, 0x69, 0xc3, 0xa5, 00, + 0x2d, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, + 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x5, 0x14, + 0x51, 0x40, 0x5, 0x14, 0x51, 0x40, 0x8, 0x7a, 0x53, 0x69, + 0xf4, 0x50, 0x3, 0x28, 0xa7, 0x62, 0x8c, 0x50, 0x3, 0x68, + 0xa7, 0x62, 0x8c, 0xa, 00, 0x6d, 0x14, 0xec, 0xa, 0x36, + 0xd0, 0x3, 0x68, 0xa7, 0x6d, 0xa4, 0x23, 0x14, 00, 0xcd, + 0xb4, 0x6d, 0xa7, 0x51, 0x40, 0xd, 0xc1, 0xa3, 0x6, 0x9d, + 0x45, 00, 0x37, 0x6, 0x8c, 0x1a, 0x75, 0x14, 00, 0xdc, + 0x1a, 0x31, 0x8a, 0x75, 0x14, 00, 0xca, 0x31, 0x4f, 0xa2, + 0x80, 0x19, 0x81, 0x49, 0x8a, 0x92, 0x93, 0xf0, 0xa0, 0x8, + 0xf6, 0x50, 0x57, 0x15, 0x26, 0x5, 0x1b, 0x68, 0x2, 0x2c, + 0xa, 0x36, 0x54, 0xbb, 0x69, 0x8, 0xc5, 00, 0x47, 0xb6, + 0x93, 0x6d, 0x48, 0x46, 0x69, 0x36, 0xd0, 0x3, 0x36, 0xd2, + 0x6c, 0xa7, 0xe0, 0xd1, 0x83, 0x40, 0xc, 0xda, 0x5, 0x23, + 0x26, 0x45, 0x49, 0x83, 0x46, 0xd2, 0x68, 0x2, 0x1d, 0x94, + 0x6c, 0xa9, 0x76, 0x51, 0xb2, 0x80, 0x22, 0xd9, 0x46, 0xca, + 0x97, 0x6f, 0xd6, 0x8d, 0xb4, 0x1, 0xe, 0xda, 0x8, 0xa9, + 0xb6, 0xd2, 0x6d, 0xa0, 0x8, 0x3c, 0xba, 0x3c, 0xba, 0x98, + 0xae, 0x69, 0x36, 0xd0, 0x4, 0x3b, 0x5, 0x26, 0xcc, 0x7a, + 0x9a, 0x9f, 0x6d, 0x21, 0x5c, 0x9a, 00, 0x83, 0x2, 0x8d, + 0xbe, 0xf5, 0x36, 0xda, 0x36, 0xfd, 0x68, 0x2, 0xd, 0x94, + 0xdf, 0x2e, 0xac, 0x6d, 0xa3, 0x65, 00, 0x56, 0xd9, 0xed, + 0x41, 0x8e, 0xac, 0xed, 0xa6, 0xb2, 0xf1, 0x40, 0x15, 0x5a, + 0x3a, 0x4f, 0x2c, 0x7a, 0x55, 0x9d, 0x94, 0x6c, 0xa0, 0xa, + 0xbe, 0x56, 0x68, 0xf2, 0x80, 0xab, 0x5b, 0x29, 0x3c, 0xba, + 00, 0xaa, 0x62, 0x14, 0xd3, 0x1d, 0x5c, 0xd9, 0x49, 0xb2, + 0x80, 0x29, 0xf9, 0x42, 0x93, 0x65, 0x5a, 0x31, 0x8c, 0xd1, + 0xe5, 0x8a, 00, 0xa8, 0x63, 0x27, 0xb5, 0x27, 0x94, 0x7d, + 0xea, 0xd9, 0x8f, 0x3d, 0xa9, 0x3c, 0xaa, 00, 0xa9, 0xe5, + 0x52, 0x18, 0x89, 0xab, 0x9e, 0x5f, 0xd6, 0x90, 0xc7, 0x40, + 0x14, 0x8c, 0x20, 0x53, 0x4c, 0x40, 0x55, 0xe6, 0x88, 0xb5, + 0x37, 0xca, 0xc7, 0xa5, 00, 0x51, 0x31, 0x64, 0xd2, 0x79, + 0x15, 0x7b, 0xcb, 0xa4, 0xf2, 0x89, 0xa0, 0xa, 0xd, 0xf, + 0x34, 0xd3, 0x15, 0x5e, 0x31, 0xd2, 0x79, 0x67, 0xd2, 0x80, + 0x28, 0x98, 0x79, 0xa6, 0x34, 0x35, 0xa2, 0x62, 0xcf, 0x6a, + 0x69, 0x84, 0xa, 00, 0xcf, 0xf2, 0xa9, 0xc, 0x39, 0xab, + 0xfe, 0x55, 0x21, 0x8a, 0x80, 0x28, 0x18, 0x71, 0x51, 0x98, + 0xb1, 0x5a, 0x26, 0x1e, 0x29, 0x3c, 0x8a, 00, 0xce, 0xf2, + 0x73, 0x47, 0x91, 0x5a, 0x1e, 0x41, 0xa6, 0x98, 0x31, 0x40, + 0x14, 0x3c, 0xac, 0x53, 0x4c, 0x35, 0xa3, 0xe4, 0xfb, 0x53, + 0x5a, 0x1f, 0x6a, 00, 0xcd, 0xf2, 0x69, 0xc, 0x42, 0xb4, + 0x7e, 0xce, 0x69, 0xc, 0x34, 0x1, 0x9a, 0x61, 0xc0, 0x14, + 0xdf, 0x22, 0xb4, 0x5a, 0x1e, 0x7a, 0x53, 0x7c, 0x83, 0x40, + 0x19, 0xcd, 0x6, 0x29, 0xbe, 0x5d, 0x68, 0xb4, 0x3c, 0x53, + 0x7c, 0x9a, 00, 0xcf, 0xf2, 0x69, 0x9e, 0x4f, 0xb5, 0x69, + 0x18, 0x49, 0xed, 0x4c, 0x68, 0x70, 0x68, 0x3, 0x3c, 0xc2, + 0x3d, 0x29, 0x86, 0x3, 0xef, 0x5a, 0x3e, 0x4f, 0xb5, 0x1e, + 0x45, 00, 0x66, 0x7d, 0x9c, 0x7a, 0x52, 0x79, 0x1e, 0xd5, + 0xa7, 0xe4, 0xd2, 0x34, 0x3c, 0x74, 0xa0, 0xc, 0xc3, 0x6f, + 0x9a, 0x4f, 0xb3, 0xfa, 0xd6, 0x89, 0x86, 0x90, 0xc1, 0x40, + 0x19, 0xa6, 0x1a, 0xd, 0xbe, 0x7e, 0x95, 0xa3, 0xe4, 0xd2, + 0x79, 0x1e, 0xd4, 0x1, 0x9d, 0xf6, 0x7a, 0x4, 0x1c, 0xd6, + 0x97, 0xd9, 0xa8, 0xf2, 0x31, 0x40, 0x19, 0xde, 0x41, 0x3d, + 0xa8, 0xf2, 0x31, 0x5a, 0x22, 0xc, 0x9a, 0x3e, 0xcd, 0x8a, + 00, 0xcf, 0x10, 0xe3, 0xb5, 0x38, 0x43, 0x57, 0xfe, 0xcf, + 0x4e, 0x10, 0x76, 0xc5, 00, 0x51, 0x10, 0x73, 0x52, 0x2c, + 0x22, 0xae, 0xb, 0x7c, 0xd3, 0xd6, 0xde, 0x80, 0x2a, 0x2c, + 0x39, 0xa9, 0x16, 0x1a, 0xb6, 0xb0, 0xd4, 0xab, 0x7, 0xe5, + 0x40, 0x15, 0x56, 0xc, 0xe2, 0xac, 0xa4, 0x38, 0xed, 0x53, + 0xac, 0x38, 0xa9, 0x56, 0x2a, 00, 0x85, 0x22, 0xcd, 0x58, + 0x58, 0xe9, 0xe9, 0x15, 0x4e, 0xb1, 0xe3, 0x14, 00, 0xc5, + 0x8e, 0xa6, 0x8d, 0x29, 0xe8, 0xb5, 0x28, 0x4a, 00, 0x6a, + 0xa5, 0x4c, 0xab, 0x40, 0x5a, 0x91, 0x45, 00, 0xb, 0x4f, + 00, 0x71, 0x4a, 0xa3, 0xa5, 0x3c, 0xe, 0x7a, 0x50, 00, + 0xa0, 0x66, 0x9d, 0xd2, 0x8c, 0x62, 0x9c, 0x7, 0x14, 00, + 0x60, 0x52, 0xd1, 0x45, 00, 0x28, 0x19, 0xa7, 0x52, 0xe, + 0x94, 0xb4, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, + 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, + 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, + 00, 0x51, 0x45, 0x14, 00, 0x52, 0x60, 0x1a, 0x5a, 0x28, + 0x1, 0xbb, 0x68, 0xdb, 0x4e, 0xa2, 0x80, 0x1b, 0xb6, 0x8d, + 0xb4, 0xea, 0x28, 0x1, 0xbb, 0x68, 0xdb, 0x4e, 0xa2, 0x80, + 0x1b, 0x83, 0x46, 0xd, 0x3a, 0x8a, 00, 0x66, 0x28, 0xc5, + 0x3e, 0x8a, 00, 0x65, 0x14, 0xfa, 0x4c, 0x50, 0x3, 0x68, + 0xa7, 0x60, 0x51, 0x81, 0x40, 0xd, 0xa2, 0x9d, 0x81, 0x41, + 0x1c, 0x50, 0x3, 0x30, 0x28, 0xc0, 0xa5, 0xa2, 0x80, 0x13, + 0x6d, 0x1b, 0x69, 0x68, 0xa0, 0x4, 0xdb, 0x49, 0xb6, 0x9d, + 0x46, 0x28, 0x1, 0xbb, 0x68, 0xc1, 0xa7, 0x62, 0x8a, 00, + 0x6e, 0x28, 0xc7, 0xb5, 0x3a, 0x8a, 00, 0x66, 0x28, 0xc5, + 0x3e, 0x8a, 00, 0x8c, 0xad, 0x26, 0xda, 0x96, 0x8c, 0x50, + 0x4, 0x5b, 0x68, 0xdb, 0x52, 0xe2, 0x91, 0xa8, 0x2, 0x22, + 0xb4, 0x9b, 0x6a, 0x4c, 0x51, 0x81, 0x40, 0x11, 0xed, 0x34, + 0x6d, 0xa7, 0x91, 0x46, 0xda, 00, 0x66, 0xda, 0x6b, 0x2d, + 0x4b, 0xb6, 0x8d, 0xb4, 0x1, 0xe, 0xca, 0x36, 0xd4, 0xbb, + 0x68, 0xdb, 0x40, 0x11, 0x14, 0xcd, 0x26, 0xcf, 0x7a, 0x9b, + 0x6f, 0xb5, 0x26, 0xcc, 0xd0, 0x4, 0x5b, 0x29, 0x36, 0xd4, + 0xdb, 0x28, 0xdb, 0x40, 0x10, 0x6c, 0xa3, 0x67, 0xb0, 0xa9, + 0x88, 0xf6, 0xa4, 0xc6, 0x28, 0x2, 0x2d, 0x83, 0xd0, 0x52, + 0x79, 0x62, 0xa6, 0xc5, 0x26, 0x5, 00, 0x40, 0x52, 0x8d, + 0x9e, 0xd5, 0x36, 0xda, 0x30, 0x68, 0x2, 0x1d, 0xb4, 0xd6, + 0x4a, 0x9f, 0x66, 0x68, 0xd9, 0x40, 0x15, 0xfc, 0xba, 0x3c, + 0xba, 0xb1, 0xb4, 0x52, 0x6d, 0xa0, 0xa, 0xfe, 0x5f, 0xd2, + 0x9a, 0x63, 0xf6, 0xab, 0xc, 0xbc, 0xd2, 0x6d, 0xa0, 0xa, + 0xde, 0x5d, 0x21, 0x8f, 0x35, 0x6b, 0x6d, 0x26, 0xca, 00, + 0xab, 0xe5, 0x7b, 0x50, 0x62, 0xf6, 0xab, 0x5b, 0x29, 0x36, + 0x50, 0x5, 0x5f, 0x26, 0x9b, 0xb0, 0x7a, 0x55, 0xc2, 0x9c, + 0x54, 0x7b, 0x68, 0x2, 0xbf, 0x96, 0x3d, 0x5, 0x34, 0xc3, + 0x93, 0x56, 0xb6, 0xd1, 0xe5, 0xd0, 0x5, 0x43, 0xd, 0x1e, + 0x49, 0xab, 0x5e, 0x5d, 0x1e, 0x5d, 00, 0x54, 0x30, 0xfb, + 0x53, 0x1a, 0x21, 0x57, 0x4c, 0x59, 0xa6, 0x98, 0x68, 0x2, + 0x91, 0x8b, 0x3d, 0xa9, 0x3c, 0xaf, 0xa5, 0x5d, 0xf2, 0xfd, + 0xe9, 0x36, 0x50, 0x5, 0x16, 0x87, 0x9e, 0x82, 0x93, 0xc9, + 0xf6, 0xab, 0xa6, 0x23, 0x49, 0xe5, 0xd0, 0x5, 0x2f, 0x27, + 0x34, 0xc6, 0x80, 0x75, 0xab, 0xfe, 0x5d, 0x35, 0xa3, 0xc0, + 0xe9, 0x40, 0x19, 0xfe, 0x50, 0xa4, 0x30, 0x66, 0xaf, 0xf9, + 0x7e, 0xd4, 0x9e, 0x5e, 0x68, 0x2, 0x89, 0x82, 0x93, 0xc8, + 0xc7, 0xa1, 0xab, 0xe6, 0x2a, 0x4f, 0x2c, 0x50, 0x6, 0x71, + 0xb7, 0x24, 0xd2, 0x7d, 0x9f, 0xda, 0xb4, 0x7c, 0xbc, 0xd2, + 0x79, 0x22, 0x80, 0x33, 0x8c, 0x1f, 0x4a, 0x41, 0x6, 0x4f, + 0x4a, 0xd2, 0x31, 0x52, 0x79, 0x34, 0x1, 0x40, 0xc1, 0xea, + 0x29, 0xc, 0x1e, 0xd5, 0xa1, 0xe4, 0xd2, 0x18, 0x68, 0x2, + 0x82, 0xc1, 0xcf, 0x41, 0x4a, 0x60, 0xcf, 0x61, 0x57, 0x84, + 0x54, 0xbe, 0x51, 0xa0, 0xa, 0x42, 0xe, 0x28, 0x11, 0x73, + 0x57, 0x44, 0x54, 0xbe, 0x5d, 00, 0x54, 0x10, 0xf1, 0xda, + 0x9e, 0x21, 0xab, 0x42, 0x2a, 0x78, 0x8b, 0xda, 0x80, 0x2a, + 0xac, 0x35, 0x20, 0x8e, 0xac, 0x88, 0xf8, 0xe9, 0x4a, 0x22, + 0xe6, 0x80, 0x21, 0x58, 0x86, 0x7a, 0x54, 0xab, 0x10, 0xa9, + 0x56, 0x3c, 0x54, 0x9b, 0x45, 00, 0x42, 0x22, 0xc5, 0x4c, + 0x91, 0xe7, 0xd2, 0x9f, 0xb2, 0x9e, 0xab, 0x40, 0xd, 0x54, + 0xc5, 0x4a, 0x13, 0x38, 0xa5, 0x55, 0xa7, 0xaa, 0xd0, 0x3, + 0x42, 0xd3, 0xc0, 0x34, 0xbb, 0x69, 0xd8, 0xc0, 0xa0, 00, + 0x66, 0x9f, 0x8a, 0x4a, 0x78, 0xe9, 0x40, 0x9, 0x81, 0x4b, + 0x45, 0x14, 00, 0x52, 0x81, 0x4a, 0x7, 0x14, 0xb4, 00, + 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, + 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, + 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, + 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, + 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, + 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, + 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, + 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, + 0x51, 0x45, 0x14, 00, 0x51, 0x45, 0x14, 00, 0x51, 0x45, + 0x14, 00, 0x98, 0x14, 0x6d, 0xa5, 0xa2, 0x80, 0x13, 0x6d, + 0x18, 0xa5, 0xa2, 0x80, 0x13, 0x1e, 0xf4, 0x63, 0xde, 0x96, + 0x8a, 00, 0x69, 0x7, 0xeb, 0x46, 0xd, 0x3a, 0x8a, 00, + 0x6e, 0xd, 0x26, 0x29, 0xf4, 0x50, 0x3, 0x31, 0x46, 0x29, + 0xf4, 0x50, 0x3, 0x31, 0x46, 0x29, 0xf4, 0x50, 0x3, 0x28, + 0xa7, 0x62, 0x8c, 0x50, 0x3, 0x31, 0x9a, 0x36, 0xd2, 0xe2, + 0x8a, 00, 0x4d, 0xb4, 0x6d, 0xa5, 0xa2, 0x80, 0x13, 0x6d, + 0x1b, 0x69, 0x68, 0xa0, 0x4, 0xdb, 0x46, 0xda, 0x5a, 0x28, + 0x1, 0xb8, 0x34, 0x60, 0xd3, 0xa8, 0xa0, 0x6, 0xe0, 0xd1, + 0x83, 0x4e, 0xa2, 0x80, 0x19, 0xb3, 0x34, 0x9b, 0x6a, 0x4a, + 0x28, 0x2, 0x3c, 0x51, 0xb7, 0xde, 0xa4, 0xc5, 0x18, 0xa0, + 0x8, 0xf6, 0x53, 0x70, 0x2a, 0x42, 0x3d, 0xa9, 0x31, 0x40, + 0xc, 0xdb, 0x46, 0xda, 0x7e, 0x28, 0xc0, 0xa0, 0x6, 0x6d, + 0xa3, 0x1e, 0xf4, 0xfc, 0xa, 0x4d, 0xb4, 0x1, 0x19, 0x5e, + 0x69, 0x36, 0xd4, 0xbb, 0x68, 0xdb, 0x40, 0x10, 0xed, 0xa3, + 0x60, 0xa9, 0xb6, 0xd1, 0xb6, 0x80, 0x21, 0xd8, 0x29, 0x36, + 0x66, 0xa7, 0xd9, 0x49, 0xb6, 0x80, 0x21, 0xf2, 0xe9, 0x36, + 0x54, 0xfb, 0x29, 0xbb, 0x68, 0x2, 0x2d, 0x94, 0x6c, 0xa9, + 0x76, 0xd2, 0x6d, 0xa0, 0x8, 0xa, 0x51, 0xb6, 0xa6, 0xf2, + 0xe8, 0xd9, 0x40, 0x10, 0x6d, 0x26, 0x93, 0x65, 0x58, 0xd9, + 0x49, 0xb0, 0x50, 0x5, 0x7f, 0x2e, 0x8f, 0x2e, 0xac, 0x6c, + 0xa3, 0x65, 00, 0x56, 0x31, 0xe3, 0xad, 0x35, 0x93, 0xd2, + 0xac, 0xb2, 0x7b, 0x52, 0x6c, 0xf6, 0xa0, 0xa, 0xbe, 0x5d, + 0x1e, 0x55, 0x59, 0xd9, 0x49, 0xb2, 0x80, 0x2b, 0xf9, 0x5e, + 0xd4, 0x9e, 0x5f, 0xb5, 0x59, 0xf2, 0xe8, 0xf2, 0xe8, 0x2, + 0xaf, 0x95, 0xed, 0x49, 0xe5, 0xf, 0x4a, 0xb7, 0xe5, 0xd1, + 0xb2, 0x80, 0x2a, 0x79, 0x54, 0x86, 0x2c, 0xd5, 0xbf, 0x2e, + 0x93, 0xcb, 0xcd, 00, 0x55, 0xf2, 0x47, 0xf9, 0x14, 0x9e, + 0x4d, 0x5b, 0xf2, 0xe8, 0xf2, 0xe8, 0x2, 0x9f, 0x91, 0x47, + 0x91, 0xef, 0x56, 0xcc, 0x54, 0x79, 0x43, 0xd2, 0x80, 0x2a, + 0x8, 0xa8, 0xf2, 0x8d, 0x5a, 0xf2, 0xc7, 0xa5, 0x1e, 0x5d, + 00, 0x56, 0x11, 0x7a, 0x9a, 0x5f, 0x2f, 0xd2, 0xad, 0x79, + 0x74, 0x79, 0x74, 0x1, 0x5f, 0xcb, 0xa5, 0x58, 0xaa, 0x7f, + 0x2e, 0x9c, 0x23, 0xe2, 0x80, 0x21, 0xd9, 0x4a, 0x23, 0x3e, + 0x95, 0x32, 0xa7, 0x34, 0xed, 0x80, 0xd0, 0x4, 0x41, 0x29, + 0xea, 0x9c, 0xd3, 0xc2, 0x71, 0x4e, 0xb, 0x40, 0xc, 0xb, + 0x4f, 0xb, 0xd2, 0x9c, 0x12, 0x9c, 0x16, 0x80, 0x1a, 0x17, + 0x6, 0x9e, 0x17, 0x8a, 0x5c, 0x7b, 0x50, 0x5, 00, 0x26, + 0xda, 0x70, 0x19, 0x34, 0xb8, 0x14, 0xb4, 00, 0x63, 0x14, + 0x51, 0x4a, 0x6, 0x68, 00, 0x3, 0x34, 0xa0, 0x71, 0x40, + 0x18, 0xa5, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, + 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, + 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x4, + 0xc0, 0xa3, 0x2, 0x96, 0x8a, 00, 0x4c, 0xa, 0x36, 0xd2, + 0xd1, 0x40, 0x9, 0xb6, 0x93, 0x6d, 0x3a, 0x8a, 00, 0x6e, + 0xda, 0x36, 0xd3, 0xa8, 0xa0, 0x6, 0xed, 0xa3, 0x6d, 0x3a, + 0x8a, 00, 0x6e, 0x28, 0xc7, 0xb5, 0x3a, 0x8a, 00, 0x6e, + 0x29, 0x29, 0xc4, 0x66, 0x93, 0x6, 0x80, 0x12, 0x8a, 0x31, + 0x46, 0x28, 00, 0xa2, 0x8a, 0x28, 0x1, 0x30, 0x28, 0xc0, + 0xa5, 0xa2, 0x80, 0x13, 0x6e, 0x68, 0xc0, 0xf5, 0xa5, 0xa2, + 0x80, 0x13, 0x3, 0xd6, 0x93, 0x6d, 0x3a, 0x8a, 00, 0x6e, + 0xda, 0x36, 0xd3, 0xa8, 0xa0, 0x6, 0xed, 0xa4, 0xd9, 0xed, + 0x4f, 0xa2, 0x80, 0x19, 0xb7, 0x14, 0x84, 0x53, 0xc8, 0xcd, + 0x26, 0xd, 00, 0x32, 0x93, 0x2, 0xa4, 0xc1, 0xa3, 0x6, + 0x80, 0x23, 0xc5, 0x18, 0xa9, 0x31, 0x46, 0x28, 0x2, 0x2d, + 0xb4, 0x6d, 0xa9, 0x31, 0x46, 0x28, 0x2, 0x3d, 0x94, 0x9b, + 0x2a, 0x4d, 0xb4, 0x6d, 0xa0, 0x8, 0xf6, 0xd2, 0x6d, 0xfa, + 0xd4, 0xbb, 0x68, 0xdb, 0x40, 0x11, 0x15, 0x1d, 0xe9, 0x36, + 0x8a, 0x9b, 0x6d, 0x1b, 0x28, 0x2, 0x1d, 0x94, 0x6c, 0xa9, + 0x76, 0xd1, 0xb6, 0x80, 0x22, 0xd9, 0x49, 0xb2, 0xa6, 0xdb, + 0xed, 0x46, 0xdf, 0x6a, 00, 0x87, 0x65, 0x1b, 0x2a, 0x5d, + 0x94, 0x6c, 0xa0, 0x8, 0x76, 0x1a, 0x36, 0x7a, 0xd4, 0xdb, + 0x7e, 0xb4, 0x6d, 0xa0, 0x8, 0xf6, 0x51, 0xb7, 0xda, 0xa4, + 0xc5, 0x18, 0xa0, 0x8, 0xf6, 0x52, 0x85, 0xc7, 0x15, 0x26, + 0xda, 0x50, 0xb4, 00, 0xc0, 0xb4, 0x6d, 0xa7, 0xed, 0xa0, + 0xa, 00, 0x68, 0x5e, 0x69, 0xdb, 0x69, 0xc0, 0x66, 0x97, + 0x6d, 00, 0x36, 0x97, 0x6, 0x94, 0xc, 0x1a, 0x5a, 00, + 0x40, 0x30, 0x29, 0x68, 0xa3, 0x14, 00, 0x51, 0x4e, 0x3, + 0x8a, 0x31, 0x40, 0x6, 0x28, 0xe9, 0x4b, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0x51, 0x45, 00, 0x14, 0x51, 0x45, + 00, 0x14, 0x51, 0x45, 00, 0x14, 0x98, 0xa5, 0xa2, 0x80, + 0x13, 0x14, 0x62, 0x96, 0x8a, 00, 0x6e, 0xda, 0x36, 0xd3, + 0xa8, 0xa0, 0x6, 0xed, 0xa3, 0x6d, 0x3a, 0x8a, 00, 0x6e, + 0xda, 0x36, 0xd3, 0xa8, 0xa0, 0x6, 0x91, 0x8a, 0x4a, 0x56, + 0xa4, 0xa0, 0x2, 0x8a, 0x28, 0xa0, 0x2, 0x8a, 0x28, 0xa0, + 0x3, 0x14, 0x62, 0x8a, 0x28, 00, 0xc5, 0x26, 0x5, 0x2d, + 0x14, 00, 0x98, 0x14, 0x60, 0x52, 0xd1, 0x40, 0x9, 0x81, + 0x46, 0x5, 0x2d, 0x14, 00, 0x9b, 0x68, 0xdb, 0x4b, 0x45, + 00, 0x37, 0x14, 0x62, 0x9d, 0x45, 00, 0x37, 0x14, 0x62, + 0x9d, 0x45, 00, 0x37, 0x14, 0x98, 0xa7, 0xd1, 0x40, 0xc, + 0xc5, 0x18, 0xa7, 0xd1, 0x40, 0xd, 0x3, 0x34, 0xb8, 0x14, + 0xb4, 0x50, 0x2, 0x60, 0x51, 0x81, 0x4b, 0x45, 00, 0x14, + 0x51, 0x45, 00, 0x14, 0xb8, 0xa4, 0xa7, 0xe, 0x94, 00, + 0x80, 0x73, 0x4e, 0xa2, 0x8a, 00, 0x28, 0xa2, 0x8a, 00, + 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, + 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, 0x8a, 00, + 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0x28, 0xa2, + 0x8a, 00, 0x28, 0xa2, 0x8a, 00, 0xff, 0xd9, 0}; + +static const unsigned char data_index_html[] = { + /* /index.html */ + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x46, 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, + 0x72, 0x67, 0x20, 0x75, 0x49, 0x50, 0x20, 0x57, 0x45, 0x42, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, + 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x42, 0x4f, 0x44, 0x59, 0x20, 0x6f, + 0x6e, 0x4c, 0x6f, 0x61, 0x64, 0x3d, 0x22, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x28, 0x26, 0x71, 0x75, 0x6f, 0x74, + 0x3b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x27, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x27, 0x26, 0x71, + 0x75, 0x6f, 0x74, 0x3b, 0x2c, 0x31, 0x30, 0x30, 0x29, 0x22, + 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, + 0x43, 0x43, 0x43, 0x43, 0x66, 0x66, 0x22, 0x3e, 0xa, 0x3c, + 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3d, + 0x22, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3e, 0xa, 0x4c, + 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x2e, 0x20, + 0x20, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x20, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x68, + 0x65, 0x72, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x66, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, + 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x72, + 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, + 0xa, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, + 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x62, + 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, + 0x6c, 0x3e, 0xa, 0xa, 0}; + +static const unsigned char data_index_shtml[] = { + /* /index.shtml */ + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x46, 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, + 0x72, 0x67, 0x20, 0x75, 0x49, 0x50, 0x20, 0x57, 0x45, 0x42, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, + 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x42, 0x4f, 0x44, 0x59, 0x20, 0x6f, + 0x6e, 0x4c, 0x6f, 0x61, 0x64, 0x3d, 0x22, 0x77, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x2e, 0x73, 0x65, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x6f, 0x75, 0x74, 0x28, 0x26, 0x71, 0x75, 0x6f, 0x74, + 0x3b, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x27, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x27, 0x26, 0x71, + 0x75, 0x6f, 0x74, 0x3b, 0x2c, 0x32, 0x30, 0x30, 0x30, 0x29, + 0x22, 0x3e, 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, + 0x61, 0x63, 0x65, 0x3d, 0x22, 0x61, 0x72, 0x69, 0x61, 0x6c, + 0x22, 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x52, 0x54, 0x4f, 0x53, 0x20, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, + 0x3c, 0x62, 0x3e, 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x2e, 0x6a, 0x70, 0x67, 0x22, 0x3e, 0x36, + 0x35, 0x4b, 0x20, 0x4a, 0x50, 0x47, 0x3c, 0x2f, 0x61, 0x3e, + 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, + 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, + 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6f, 0x2e, 0x73, 0x68, 0x74, + 0x6d, 0x6c, 0x22, 0x3e, 0x49, 0x4f, 0x3c, 0x2f, 0x61, 0x3e, + 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x70, 0x3e, 0xa, 0x3c, + 0x68, 0x72, 0x3e, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x70, + 0x3e, 0xa, 0x3c, 0x68, 0x32, 0x3e, 0x54, 0x61, 0x73, 0x6b, + 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, + 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0xa, 0x54, 0x68, 0x69, + 0x73, 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x73, 0x68, 0x6f, + 0x77, 0x73, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x61, 0x73, 0x6b, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, + 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x67, 0x65, 0x20, 0x77, + 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x20, 0x65, 0x76, 0x65, 0x79, 0x20, 0x32, 0x20, 0x73, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x2e, 0x3c, 0x70, 0x3e, + 0xa, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, + 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, + 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x54, 0x61, 0x73, + 0x6b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x20, 0x50, 0x72, + 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x20, 0x53, 0x74, + 0x61, 0x63, 0x6b, 0x9, 0x23, 0x3c, 0x62, 0x72, 0x3e, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, + 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x3c, 0x62, 0x72, + 0x3e, 0xa, 0x25, 0x21, 0x20, 0x72, 0x74, 0x6f, 0x73, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72, + 0x65, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, + 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, + 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, + 0x6d, 0x6c, 0x3e, 0xa, 0xa, 0}; + +static const unsigned char data_io_shtml[] = { + /* /io.shtml */ + 0x2f, 0x69, 0x6f, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x46, 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, + 0x72, 0x67, 0x20, 0x75, 0x49, 0x50, 0x20, 0x57, 0x45, 0x42, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, + 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x42, 0x4f, 0x44, 0x59, 0x3e, 0xa, + 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, 0x65, + 0x3d, 0x22, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3e, 0xa, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0x22, 0x3e, 0x52, 0x54, 0x4f, 0x53, 0x20, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, + 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, + 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x2e, 0x6a, 0x70, 0x67, 0x22, 0x3e, 0x36, 0x35, 0x4b, 0x20, + 0x4a, 0x50, 0x47, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, + 0x3e, 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, + 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, 0x2f, 0x62, + 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, + 0x22, 0x69, 0x6f, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x49, 0x4f, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c, 0x62, + 0x72, 0x3e, 0x3c, 0x70, 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, + 0xa, 0x3c, 0x62, 0x3e, 0x4c, 0x45, 0x44, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x4c, 0x43, 0x44, 0x20, 0x49, 0x4f, 0x3c, 0x2f, + 0x62, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0xa, 0x3c, 0x70, + 0x3e, 0xa, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61, 0x67, + 0x65, 0x20, 0x64, 0x65, 0x6d, 0x6f, 0x6e, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x77, + 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x42, + 0x79, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x62, 0x6f, + 0x78, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x20, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x74, + 0x68, 0x69, 0x73, 0x20, 0x57, 0x45, 0x42, 0x20, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x63, 0x61, + 0x6e, 0x20, 0x69, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, + 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x67, + 0x72, 0x61, 0x6d, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x3c, 0x70, 0x3e, 0xa, 0x55, 0x73, + 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x20, 0x62, 0x6f, 0x78, 0x65, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x4c, 0x45, 0x44, 0x27, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x6f, + 0x72, 0x20, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x74, 0x6f, + 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x6f, + 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x43, 0x44, 0x2c, + 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6c, 0x69, 0x63, + 0x6b, 0x20, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, + 0x49, 0x4f, 0x22, 0x2e, 0xa, 0xa, 0xa, 0x3c, 0x70, 0x3e, + 0xa, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6e, 0x61, 0x6d, + 0x65, 0x3d, 0x22, 0x61, 0x46, 0x6f, 0x72, 0x6d, 0x22, 0x20, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x2f, 0x69, + 0x6f, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x20, 0x6d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x67, 0x65, 0x74, + 0x22, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x6c, 0x65, 0x64, 0x2d, + 0x69, 0x6f, 0xa, 0x3c, 0x70, 0x3e, 0xa, 0x3c, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, + 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x22, 0x20, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x20, 0x49, 0x4f, 0x22, 0x3e, 0xa, 0x3c, 0x2f, 0x66, + 0x6f, 0x72, 0x6d, 0x3e, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, + 0x70, 0x3e, 0xa, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, + 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, + 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0xa, 0}; + +static const unsigned char data_stats_shtml[] = { + /* /stats.shtml */ + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x46, 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, + 0x72, 0x67, 0x20, 0x75, 0x49, 0x50, 0x20, 0x57, 0x45, 0x42, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, + 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x42, 0x4f, 0x44, 0x59, 0x20, 0x62, + 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, 0x43, + 0x43, 0x43, 0x43, 0x66, 0x66, 0x22, 0x3e, 0xa, 0x3c, 0x66, + 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3d, 0x22, + 0x61, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3e, 0xa, 0x3c, 0x61, + 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, + 0x52, 0x54, 0x4f, 0x53, 0x20, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, + 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x54, 0x43, 0x50, 0x20, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, + 0x3c, 0x62, 0x3e, 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, + 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, + 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x72, 0x74, + 0x6f, 0x73, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x22, 0x3e, 0x46, + 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, 0x72, + 0x67, 0x20, 0x48, 0x6f, 0x6d, 0x65, 0x70, 0x61, 0x67, 0x65, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, + 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x69, 0x6f, 0x2e, 0x73, 0x68, 0x74, 0x6d, + 0x6c, 0x22, 0x3e, 0x49, 0x4f, 0x3c, 0x2f, 0x61, 0x3e, 0xa, + 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x70, 0x3e, 0xa, 0x3c, 0x68, + 0x72, 0x3e, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x70, 0x3e, + 0xa, 0x3c, 0x68, 0x32, 0x3e, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, + 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0xa, 0x3c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x22, 0x33, 0x30, 0x30, 0x22, 0x20, 0x62, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x3d, 0x22, 0x30, 0x22, 0x3e, 0xa, + 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x22, + 0x3e, 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, + 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, + 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49, 0x50, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, + 0x6e, 0x74, 0xa, 0x49, 0x50, 0x20, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x73, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x2c, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, + 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, + 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x6c, + 0x6f, 0x77, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x49, 0x50, 0x20, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x72, 0x6f, 0x6e, + 0x67, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0xa, 0x49, 0x43, 0x4d, 0x50, 0x9, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, + 0x6e, 0x74, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54, 0x79, 0x70, 0x65, + 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x54, 0x43, + 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x73, 0x65, + 0x6e, 0x74, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, + 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x41, 0x43, 0x4b, 0x73, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x73, 0x65, 0x74, 0x73, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0xa, + 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x6f, 0x20, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61, 0x62, 0x6c, 0x65, 0xa, + 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x74, 0x74, + 0x65, 0x6d, 0x70, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x70, 0x6f, 0x72, 0x74, + 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, + 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, + 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x25, + 0x21, 0x20, 0x6e, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x74, + 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x66, + 0x6f, 0x6e, 0x74, 0x3e, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, + 0xa, 0}; + +static const unsigned char data_tcp_shtml[] = { + /* /tcp.shtml */ + 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x46, 0x72, 0x65, 0x65, 0x52, 0x54, 0x4f, 0x53, 0x2e, 0x6f, + 0x72, 0x67, 0x20, 0x75, 0x49, 0x50, 0x20, 0x57, 0x45, 0x42, + 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x64, 0x65, + 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x42, 0x4f, 0x44, 0x59, 0x3e, 0xa, + 0x3c, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x66, 0x61, 0x63, 0x65, + 0x3d, 0x22, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3e, 0xa, + 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0x22, 0x3e, 0x52, 0x54, 0x4f, 0x53, 0x20, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, + 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, + 0x72, 0x65, 0x66, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x2e, 0x6a, 0x70, 0x67, 0x22, 0x3e, 0x36, 0x35, 0x4b, 0x20, + 0x4a, 0x50, 0x47, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x62, + 0x3e, 0x7c, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, + 0x61, 0x3e, 0x20, 0x3c, 0x62, 0x3e, 0x7c, 0x3c, 0x2f, 0x62, + 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, + 0x22, 0x69, 0x6f, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x49, 0x4f, 0x3c, 0x2f, 0x61, 0x3e, 0xa, 0x3c, 0x62, + 0x72, 0x3e, 0x3c, 0x70, 0x3e, 0xa, 0x3c, 0x68, 0x72, 0x3e, + 0xa, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x68, 0x32, 0x3e, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, + 0x2f, 0x68, 0x32, 0x3e, 0xa, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x70, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, + 0x61, 0x79, 0x73, 0x20, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, + 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0x20, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0xa, 0x3c, 0x70, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, + 0x68, 0x3e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x74, + 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, + 0x3e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, + 0x69, 0x6d, 0x65, 0x72, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, + 0x74, 0x68, 0x3e, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, + 0x21, 0x20, 0x74, 0x63, 0x70, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa, 0x3c, 0x2f, + 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, + 0x3e, 0xa, 0x3c, 0x2f, 0x66, 0x6f, 0x6e, 0x74, 0x3e, 0xa, + 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, + 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0xa, 0}; + +const struct httpd_fsdata_file file_404_html[] = {{NULL, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; + +const struct httpd_fsdata_file file_image_jpg[] = {{file_404_html, data_image_jpg, data_image_jpg + 11, sizeof(data_image_jpg) - 11}}; + +const struct httpd_fsdata_file file_index_html[] = {{file_image_jpg, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; + +const struct httpd_fsdata_file file_index_shtml[] = {{file_index_html, data_index_shtml, data_index_shtml + 13, sizeof(data_index_shtml) - 13}}; + +const struct httpd_fsdata_file file_io_shtml[] = {{file_index_shtml, data_io_shtml, data_io_shtml + 10, sizeof(data_io_shtml) - 10}}; + +const struct httpd_fsdata_file file_stats_shtml[] = {{file_io_shtml, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}}; + +const struct httpd_fsdata_file file_tcp_shtml[] = {{file_stats_shtml, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}}; + +#define HTTPD_FS_ROOT file_tcp_shtml + +#define HTTPD_FS_NUMFILES 7 Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.c (revision 14) @@ -0,0 +1,346 @@ +/** + * \addtogroup apps + * @{ + */ + +/** + * \defgroup httpd Web server + * @{ + * The uIP web server is a very simplistic implementation of an HTTP + * server. It can serve web pages and files from a read-only ROM + * filesystem, and provides a very small scripting language. + + */ + +/** + * \file + * Web server + * \author + * Adam Dunkels + */ + + +/* + * Copyright (c) 2004, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $ + */ + +#include "uip.h" +#include "httpd.h" +#include "httpd-fs.h" +#include "httpd-cgi.h" +#include "http-strings.h" + +#include + +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 + +#define ISO_nl 0x0a +#define ISO_space 0x20 +#define ISO_bang 0x21 +#define ISO_percent 0x25 +#define ISO_period 0x2e +#define ISO_slash 0x2f +#define ISO_colon 0x3a + + +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_part_of_file(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if(s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + memcpy(uip_appdata, s->file.data, s->len); + + return s->len; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_file(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sout); + + do { + PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s); + s->file.len -= s->len; + s->file.data += s->len; + } while(s->file.len > 0); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_part_of_file(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sout); + + PSOCK_SEND(&s->sout, s->file.data, s->len); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static void +next_scriptstate(struct httpd_state *s) +{ + char *p; + p = strchr(s->scriptptr, ISO_nl) + 1; + s->scriptlen -= (unsigned short)(p - s->scriptptr); + s->scriptptr = p; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_script(struct httpd_state *s)) +{ + char *ptr; + + PT_BEGIN(&s->scriptpt); + + + while(s->file.len > 0) { + + /* Check if we should start executing a script. */ + if(*s->file.data == ISO_percent && + *(s->file.data + 1) == ISO_bang) { + s->scriptptr = s->file.data + 3; + s->scriptlen = s->file.len - 3; + if(*(s->scriptptr - 1) == ISO_colon) { + httpd_fs_open(s->scriptptr + 1, &s->file); + PT_WAIT_THREAD(&s->scriptpt, send_file(s)); + } else { + PT_WAIT_THREAD(&s->scriptpt, + httpd_cgi(s->scriptptr)(s, s->scriptptr)); + } + next_scriptstate(s); + + /* The script is over, so we reset the pointers and continue + sending the rest of the file. */ + s->file.data = s->scriptptr; + s->file.len = s->scriptlen; + } else { + /* See if we find the start of script marker in the block of HTML + to be sent. */ + + if(s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + + if(*s->file.data == ISO_percent) { + ptr = strchr(s->file.data + 1, ISO_percent); + } else { + ptr = strchr(s->file.data, ISO_percent); + } + if(ptr != NULL && + ptr != s->file.data) { + s->len = (int)(ptr - s->file.data); + if(s->len >= uip_mss()) { + s->len = uip_mss(); + } + } + PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s)); + s->file.data += s->len; + s->file.len -= s->len; + + } + } + + PT_END(&s->scriptpt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) +{ + char *ptr; + + PSOCK_BEGIN(&s->sout); + + PSOCK_SEND_STR(&s->sout, statushdr); + + ptr = strrchr(s->filename, ISO_period); + if(ptr == NULL) { + PSOCK_SEND_STR(&s->sout, http_content_type_binary); + } else if(strncmp(http_html, ptr, 5) == 0 || + strncmp(http_shtml, ptr, 6) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_html); + } else if(strncmp(http_css, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_css); + } else if(strncmp(http_png, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_png); + } else if(strncmp(http_gif, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_gif); + } else if(strncmp(http_jpg, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_jpg); + } else { + PSOCK_SEND_STR(&s->sout, http_content_type_plain); + } + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_output(struct httpd_state *s)) +{ + char *ptr; + + PT_BEGIN(&s->outputpt); + + if(!httpd_fs_open(s->filename, &s->file)) { + httpd_fs_open(http_404_html, &s->file); + strcpy(s->filename, http_404_html); + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, + http_header_404)); + PT_WAIT_THREAD(&s->outputpt, + send_file(s)); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, + http_header_200)); + ptr = strchr(s->filename, ISO_period); + if(ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) { + PT_INIT(&s->scriptpt); + PT_WAIT_THREAD(&s->outputpt, handle_script(s)); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_file(s)); + } + } + PSOCK_CLOSE(&s->sout); + PT_END(&s->outputpt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_input(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sin); + + PSOCK_READTO(&s->sin, ISO_space); + + + if(strncmp(s->inputbuf, http_get, 4) != 0) { + PSOCK_CLOSE_EXIT(&s->sin); + } + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + + if(s->inputbuf[1] == ISO_space) { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } else { + + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + + /* Process any form input being sent to the server. */ + { + extern void vApplicationProcessFormInput( char *pcInputString, long xInputLength ); + vApplicationProcessFormInput( s->inputbuf, PSOCK_DATALEN(&s->sin) ); + } + + strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename)); + } + + /* httpd_log_file(uip_conn->ripaddr, s->filename);*/ + + s->state = STATE_OUTPUT; + + while(1) { + PSOCK_READTO(&s->sin, ISO_nl); + + if(strncmp(s->inputbuf, http_referer, 8) == 0) { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; + /* httpd_log(&s->inputbuf[9]);*/ + } + } + + PSOCK_END(&s->sin); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connection(struct httpd_state *s) +{ + handle_input(s); + if(s->state == STATE_OUTPUT) { + handle_output(s); + } +} +/*---------------------------------------------------------------------------*/ +void +httpd_appcall(void) +{ + struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate); + + if(uip_closed() || uip_aborted() || uip_timedout()) { + } else if(uip_connected()) { + PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1); + PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1); + PT_INIT(&s->outputpt); + s->state = STATE_WAITING; + /* timer_set(&s->timer, CLOCK_SECOND * 100);*/ + s->timer = 0; + handle_connection(s); + } else if(s != NULL) { + if(uip_poll()) { + ++s->timer; + if(s->timer >= 20) { + uip_abort(); + } + } else { + s->timer = 0; + } + handle_connection(s); + } else { + uip_abort(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the web server + * + * This function initializes the web server and should be + * called at system boot-up. + */ +void +httpd_init(void) +{ + uip_listen(HTONS(80)); +} +/*---------------------------------------------------------------------------*/ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/http-strings (revision 14) @@ -0,0 +1,35 @@ +http_http "http://" +http_200 "200 " +http_301 "301 " +http_302 "302 " +http_get "GET " +http_10 "HTTP/1.0" +http_11 "HTTP/1.1" +http_content_type "content-type: " +http_texthtml "text/html" +http_location "location: " +http_host "host: " +http_crnl "\r\n" +http_index_html "/index.html" +http_404_html "/404.html" +http_referer "Referer:" +http_header_200 "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_header_404 "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_content_type_plain "Content-type: text/plain\r\n\r\n" +http_content_type_html "Content-type: text/html\r\n\r\n" +http_content_type_css "Content-type: text/css\r\n\r\n" +http_content_type_text "Content-type: text/text\r\n\r\n" +http_content_type_png "Content-type: image/png\r\n\r\n" +http_content_type_gif "Content-type: image/gif\r\n\r\n" +http_content_type_jpg "Content-type: image/jpeg\r\n\r\n" +http_content_type_binary "Content-type: application/octet-stream\r\n\r\n" +http_html ".html" +http_shtml ".shtml" +http_htm ".htm" +http_css ".css" +http_png ".png" +http_gif ".gif" +http_jpg ".jpg" +http_text ".txt" +http_txt ".txt" + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uip-conf.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uip-conf.h (revision 16) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/uip-conf.h (revision 16) @@ -0,0 +1,157 @@ +/** + * \addtogroup uipopt + * @{ + */ + +/** + * \name Project-specific configuration options + * @{ + * + * uIP has a number of configuration options that can be overridden + * for each project. These are kept in a project-specific uip-conf.h + * file and all configuration names have the prefix UIP_CONF. + */ + +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uip-conf.h,v 1.6 2006/06/12 08:00:31 adam Exp $ + */ + +/** + * \file + * An example uIP configuration file + * \author + * Adam Dunkels + */ + +#ifndef __UIP_CONF_H__ +#define __UIP_CONF_H__ + +#include + +/** + * 8 bit datatype + * + * This typedef defines the 8-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint8_t u8_t; + +/** + * 16 bit datatype + * + * This typedef defines the 16-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint16_t u16_t; + +/** + * Statistics datatype + * + * This typedef defines the dataype used for keeping statistics in + * uIP. + * + * \hideinitializer + */ +typedef unsigned short uip_stats_t; + +/** + * Maximum number of TCP connections. + * + * \hideinitializer + */ +#define UIP_CONF_MAX_CONNECTIONS 5 + +/** + * Maximum number of listening TCP ports. + * + * \hideinitializer + */ +#define UIP_CONF_MAX_LISTENPORTS 10 + +/** + * uIP buffer size. + * + * \hideinitializer + */ +#define UIP_CONF_BUFFER_SIZE 1480 + +/** + * CPU byte order. + * + * \hideinitializer + */ +#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN + +/** + * Logging on or off + * + * \hideinitializer + */ +#define UIP_CONF_LOGGING 0 + +/** + * UDP support on or off + * + * \hideinitializer + */ +#define UIP_CONF_UDP 0 + +/** + * UDP checksums on or off + * + * \hideinitializer + */ +#define UIP_CONF_UDP_CHECKSUMS 1 + +/** + * uIP statistics on or off + * + * \hideinitializer + */ +#define UIP_CONF_STATISTICS 1 + +/* Here we include the header file for the application(s) we use in + our project. */ +/*#include "smtp.h"*/ +/*#include "hello-world.h"*/ +/*#include "telnetd.h"*/ +#include "webserver.h" +/*#include "dhcpc.h"*/ +/*#include "resolv.h"*/ +/*#include "webclient.h"*/ + +#endif /* __UIP_CONF_H__ */ + +/** @} */ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd.h (revision 14) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2005, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ + +#ifndef __HTTPD_H__ +#define __HTTPD_H__ + +#include "psock.h" +#include "httpd-fs.h" + +struct httpd_state { + unsigned char timer; + struct psock sin, sout; + struct pt outputpt, scriptpt; + char inputbuf[50]; + char filename[20]; + char state; + struct httpd_fs_file file; + int len; + char *scriptptr; + int scriptlen; + + unsigned short count; +}; + +void httpd_init(void); +void httpd_appcall(void); + +void httpd_log(char *msg); +void httpd_log_file(u16_t *requester, char *file); + +#endif /* __HTTPD_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fsdata.h (revision 14) @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fsdata.h,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ +#ifndef __HTTPD_FSDATA_H__ +#define __HTTPD_FSDATA_H__ + +#include "uip.h" + +struct httpd_fsdata_file { + const struct httpd_fsdata_file *next; + const char *name; + const char *data; + const int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + u16_t count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +struct httpd_fsdata_file_noconst { + struct httpd_fsdata_file *next; + char *name; + char *data; + int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + u16_t count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +#endif /* __HTTPD_FSDATA_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.h (revision 14) @@ -0,0 +1,84 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * Web server script interface header file + * \author + * Adam Dunkels + * + */ + + + +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd-cgi.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ + +#ifndef __HTTPD_CGI_H__ +#define __HTTPD_CGI_H__ + +#include "psock.h" +#include "httpd.h" + +typedef PT_THREAD((* httpd_cgifunction)(struct httpd_state *, char *)); + +httpd_cgifunction httpd_cgi(char *name); + +struct httpd_cgi_call { + const char *name; + const httpd_cgifunction function; +}; + +/** + * \brief HTTPD CGI function declaration + * \param name The C variable name of the function + * \param str The string name of the function, used in the script file + * \param function A pointer to the function that implements it + * + * This macro is used for declaring a HTTPD CGI + * function. This function is then added to the list of + * HTTPD CGI functions with the httpd_cgi_add() function. + * + * \hideinitializer + */ +#define HTTPD_CGI_CALL(name, str, function) \ +static PT_THREAD(function(struct httpd_state *, char *)); \ +static const struct httpd_cgi_call name = {str, function} + +void httpd_cgi_init(void); +#endif /* __HTTPD_CGI_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-fs.c (revision 14) @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fs.c,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ + +#include "httpd.h" +#include "httpd-fs.h" +#include "httpd-fsdata.h" + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +#include "httpd-fsdata.c" + +#if HTTPD_FS_STATISTICS +static u16_t count[HTTPD_FS_NUMFILES]; +#endif /* HTTPD_FS_STATISTICS */ + +/*-----------------------------------------------------------------------------------*/ +static u8_t +httpd_fs_strcmp(const char *str1, const char *str2) +{ + u8_t i; + i = 0; + loop: + + if(str2[i] == 0 || + str1[i] == '\r' || + str1[i] == '\n') { + return 0; + } + + if(str1[i] != str2[i]) { + return 1; + } + + + ++i; + goto loop; +} +/*-----------------------------------------------------------------------------------*/ +int +httpd_fs_open(const char *name, struct httpd_fs_file *file) +{ +#if HTTPD_FS_STATISTICS + u16_t i = 0; +#endif /* HTTPD_FS_STATISTICS */ + struct httpd_fsdata_file_noconst *f; + + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + file->data = f->data; + file->len = f->len; +#if HTTPD_FS_STATISTICS + ++count[i]; +#endif /* HTTPD_FS_STATISTICS */ + return 1; + } +#if HTTPD_FS_STATISTICS + ++i; +#endif /* HTTPD_FS_STATISTICS */ + + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void +httpd_fs_init(void) +{ +#if HTTPD_FS_STATISTICS + u16_t i; + for(i = 0; i < HTTPD_FS_NUMFILES; i++) { + count[i] = 0; + } +#endif /* HTTPD_FS_STATISTICS */ +} +/*-----------------------------------------------------------------------------------*/ +#if HTTPD_FS_STATISTICS +u16_t httpd_fs_count +(char *name) +{ + struct httpd_fsdata_file_noconst *f; + u16_t i; + + i = 0; + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + return count[i]; + } + ++i; + } + return 0; +} +#endif /* HTTPD_FS_STATISTICS */ +/*-----------------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/FreeRTOSConfig.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/FreeRTOSConfig.h (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/FreeRTOSConfig.h (revision 17) @@ -0,0 +1,140 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include +#include +#define vPortYieldProcessor swi_handler + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + + +/* Value to use on old rev '-' devices. */ +//#define configPINSEL2_VALUE 0x50151105 + +/* Value to use on rev 'A' and newer devices. */ +#define configPINSEL2_VALUE 0x50150105 + +#ifndef configPINSEL2_VALUE + #error Please uncomment one of the two configPINSEL2_VALUE definitions above, depending on the revision of the LPC2000 device being used. +#endif + +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 57600000 ) +#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 4 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 120 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 18 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 + + +#endif /* FREERTOS_CONFIG_H */ + + +#ifndef sbi +#define sbi(x,y) x|=(1 << (y)) +#endif + +#ifndef cbi +#define cbi(x,y) x&=~(1 << (y)) +#endif + +#ifndef tstb +#define tstb(x,y) (x & (1 << (y)) ? 1 : 0) +#endif + +#ifndef toggle +#define toggle(x,y) x^=(1 << (y)) +#endif + +#ifndef BIT +#define BIT(x) (1 << (x)) + + +//#define VICVectAddr VICAddress +//#define VICVectCntl4 VICVectPriority4 +typedef struct +{ + long xColumn; + signed char *pcMessage; +} xLCDMessage; + +#endif Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/main.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/main.c (revision 22) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/main.c (revision 22) @@ -0,0 +1,261 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* Environment includes. */ +#include + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo app includes. */ + +#include "portlcd.h" +#include "flash.h" + + +/* Demo application definitions. */ +#define mainQUEUE_SIZE ( 3 ) +#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) +#define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) + +/* Task priorities. */ +#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainFLASH_PRIORITY ( tskIDLE_PRIORITY + 2 ) + + + +void setRTC(void); +void startRTC(void); + +/* + * Checks the status of all the demo tasks then prints a message to the + * CrossStudio terminal IO windows. The message will be either PASS or FAIL + * depending on the status of the demo applications tasks. A FAIL status will + * be latched. + * + * Messages are not written directly to the terminal, but passed to vPrintTask + * via a queue. + */ +static void vCheckTask( void *pvParameters ); + +/* + * The task that handles the uIP stack. All TCP/IP processing is performed in + * this task. + */ +extern void vuIP_Task( void *pvParameters ); + +/* + * The task that handles the electricity meter handling/calculations. + */ +extern void vMeters_Task( void *pvParameters ); + +/* + * The LCD is written two by more than one task so is controlled by a + * 'gatekeeper' task. This is the only task that is actually permitted to + * access the LCD directly. Other tasks wanting to display a message send + * the message to the gatekeeper. + */ +static void vLCDTask( void *pvParameters ); + +/* The queue used to send messages to the LCD task. */ +xQueueHandle xLCDQueue; + +/*-----------------------------------------------------------*/ + +int main (void) +{ + startRTC(); /* start the RTC */ + + /* Setup the led's on the MCB2300 board */ + vParTestInitialise(); + + /* Create the queue used by the LCD task. Messages for display on the LCD + are received via this queue. */ + xLCDQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( xLCDMessage ) ); + + /* Create the lwIP task. This uses the lwIP RTOS abstraction layer.*/ + xTaskCreate( vuIP_Task, ( signed portCHAR * ) "uIP", mainBASIC_WEB_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + +// vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vStartMetersTask( mainFLASH_PRIORITY ); + /* Start the standard demo tasks. */ +// vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); +// vCreateBlockTimeTasks(); + vStartLEDFlashTasks( mainFLASH_PRIORITY ); +// vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); +// vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); +// vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); + + /* Start the tasks defined within this file/specific to this demo. */ + // xTaskCreate( vCheckTask, ( signed portCHAR * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); + xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + + /* The suicide tasks must be created last as they need to know how many + tasks were running prior to their creation in order to ascertain whether + or not the correct/expected number of tasks are running at any given time. */ + // vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Will only get here if there was insufficient memory to create the idle + task. */ + return 0; +} +/*-----------------------------------------------------------*/ + +static void vCheckTask( void *pvParameters ) +{ +portBASE_TYPE xErrorOccurred = pdFALSE; +portTickType xLastExecutionTime; +unsigned portBASE_TYPE uxColumn = 0; +xLCDMessage xMessage; + + xLastExecutionTime = xTaskGetTickCount(); + + xMessage.xColumn = 0; + xMessage.pcMessage = "PASS"; + + for( ;; ) + { + /* Perform this check every mainCHECK_DELAY milliseconds. */ + vTaskDelayUntil( &xLastExecutionTime, mainCHECK_DELAY ); + + /* Has an error been found in any task? */ + + + + LCD_cls(); + xMessage.xColumn++; + LCD_gotoxy( ( uxColumn & 0x07 ) + 1, ( uxColumn & 0x01 ) + 1 ); + + if( xErrorOccurred == pdTRUE ) + { + xMessage.pcMessage = "FAIL"; + } + + /* Send the message to the LCD gatekeeper for display. */ + xQueueSend( xLCDQueue, &xMessage, portMAX_DELAY ); + } +} +/*-----------------------------------------------------------*/ + +void vLCDTask( void *pvParameters ) +{ +xLCDMessage xMessage; + + /* Initialise the LCD and display a startup message. */ + LCD_init(); + LCD_cur_off(); + LCD_cls(); + LCD_gotoxy( 1, 1 ); + LCD_puts( ( signed portCHAR * ) "www.FreeRTOS.org" ); + + for( ;; ) + { + /* Wait for a message to arrive that requires displaying. */ + while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS ); + + /* Display the message. Print each message to a different position. */ + LCD_cls(); + LCD_gotoxy( ( xMessage.xColumn & 0x07 ) + 1, ( xMessage.xColumn & 0x01 ) + 1 ); + LCD_puts( xMessage.pcMessage ); + } + +} +/*-----------------------------------------------------------*/ + +/* Keep the compiler quiet. */ +#include +int __putchar( int c ) +{ + return EOF; +} + +void setRTC(void) +{ +/* + This function needs to be called when the RTC battery was replaces + + SEC 6 Seconds value in the range of 0 to 59 R/W 0xE002 4020 + MIN 6 Minutes value in the range of 0 to 59 R/W 0xE002 4024 + HOUR 5 Hours value in the range of 0 to 23 R/W 0xE002 4028 + DOM 5 Day of month value in the range of 1 to 28, 29, 30, + or 31 (depending on the month and whether it is a + leap year).[1] + R/W 0xE002 402C + DOW 3 Day of week value in the range of 0 to 6[1] R/W 0xE002 4030 + DOY 9 Day of year value in the range of 1 to 365 (366 for + leap years)[1] + R/W 0xE002 4034 + MONTH 4 Month value in the range of 1 to 12 R/W 0xE002 4038 + YEAR 12 Year value in the range of 0 to 4095 R/W 0xE002 403C +*/ + RTC_SEC = 00; + RTC_MIN = 22; + RTC_HOUR = 17; + RTC_DOM = 11; + RTC_DOW = 2-1; + RTC_DOY = 223; + RTC_MONTH = 8; + RTC_YEAR = 2009; +} + +void startRTC(void) +{ + // Initial RTC Function + RTC_CCR = 0; // Reset All Bit Control + RTC_CCR |= 0x00000010; // CLKSRC = 1 = Used EXT 32.768 KHz + RTC_CCR |= 0x00000002; // Reset Clock + RTC_CCR &= 0xFFFFFFFD; // Release Reset + RTC_CCR |= 0x00000001; // Start RTC Clock +} Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzp =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzp (revision 28) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzp (revision 28) @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzs =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzs (revision 28) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/EnergyMeters.hzs (revision 28) @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/comtest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/comtest.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/comtest.c (revision 14) @@ -0,0 +1,366 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * Creates two tasks that operate on an interrupt driven serial port. A loopback + * connector should be used so that everything that is transmitted is also received. + * The serial port does not use any flow control. On a standard 9way 'D' connector + * pins two and three should be connected together. + * + * The first task repeatedly sends a string to a queue, character at a time. The + * serial port interrupt will empty the queue and transmit the characters. The + * task blocks for a pseudo random period before resending the string. + * + * The second task blocks on a queue waiting for a character to be received. + * Characters received by the serial port interrupt routine are posted onto the + * queue - unblocking the task making it ready to execute. If this is then the + * highest priority task ready to run it will run immediately - with a context + * switch occurring at the end of the interrupt service routine. The task + * receiving characters is spawned with a higher priority than the task + * transmitting the characters. + * + * With the loop back connector in place, one task will transmit a string and the + * other will immediately receive it. The receiving task knows the string it + * expects to receive so can detect an error. + * + * This also creates a third task. This is used to test semaphore usage from an + * ISR and does nothing interesting. + * + * \page ComTestC comtest.c + * \ingroup DemoFiles + *


+ */ + +/* +Changes from V1.00: + + + The priority of the Rx task has been lowered. Received characters are + now processed (read from the queue) at the idle priority, allowing low + priority tasks to run evenly at times of a high communications overhead. + +Changes from V1.01: + + + The Tx task now waits a pseudo random time between transissions. + Previously a fixed period was used but this was not such a good test as + interrupts fired at regular intervals. + +Changes From V1.2.0: + + + Use vSerialPutString() instead of single character puts. + + Only stop the check variable incrementing after two consecutive errors. + +Changed from V1.2.5 + + + Made the Rx task 2 priorities higher than the Tx task. Previously it was + only 1. This is done to tie in better with the other demo application + tasks. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. + + Slight modification to task priorities. + +*/ + + +/* Scheduler include files. */ +#include +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "print.h" + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( portTickType ) 0x15e ) +#define comTX_MIN_BLOCK_TIME ( ( portTickType ) 0xc8 ) + +#define comMAX_CONSECUTIVE_ERRORS ( 2 ) + +#define comSTACK_SIZE ( ( unsigned portSHORT ) 256 ) + +#define comRX_RELATIVE_PRIORITY ( 1 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort; + +/* The transmit function as described at the top of the file. */ +static void vComTxTask( void *pvParameters ); + +/* The receive function as described at the top of the file. */ +static void vComRxTask( void *pvParameters ); + +/* The semaphore test function as described at the top of the file. */ +static void vSemTestTask( void * pvParameters ); + +/* The string that is repeatedly transmitted. */ +const portCHAR * const pcMessageToExchange = "Send this message over and over again to check communications interrupts. " + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"; + +/* Variables that are incremented on each cycle of each task. These are used to +check that both tasks are still executing. */ +volatile portSHORT sTxCount = 0, sRxCount = 0, sSemCount = 0; + +/* The handle to the semaphore test task. */ +static xTaskHandle xSemTestTaskHandle = NULL; + +/*-----------------------------------------------------------*/ + +void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate ) +{ +const unsigned portBASE_TYPE uxBufferLength = 255; + + /* Initialise the com port then spawn both tasks. */ + xPort = xSerialPortInit( ePort, eBaudRate, serNO_PARITY, serBITS_8, serSTOP_1, uxBufferLength ); + xTaskCreate( vComTxTask, "COMTx", comSTACK_SIZE, NULL, uxPriority, NULL ); + xTaskCreate( vComRxTask, "COMRx", comSTACK_SIZE, NULL, uxPriority + comRX_RELATIVE_PRIORITY, NULL ); + xTaskCreate( vSemTestTask, "ISRSem", comSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xSemTestTaskHandle ); +} +/*-----------------------------------------------------------*/ + +static void vComTxTask( void *pvParameters ) +{ +const portCHAR * const pcTaskStartMsg = "COM Tx task started.\r\n"; +portTickType xTimeToWait; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Send the string to the serial port. */ + vSerialPutString( xPort, pcMessageToExchange, strlen( pcMessageToExchange ) ); + + /* We have posted all the characters in the string - increment the variable + used to check that this task is still running, then wait before re-sending + the string. */ + sTxCount++; + + xTimeToWait = xTaskGetTickCount(); + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vComRxTask( void *pvParameters ) +{ +const portCHAR * const pcTaskStartMsg = "COM Rx task started.\r\n"; +const portCHAR * const pcTaskErrorMsg = "COM read error\r\n"; +const portCHAR * const pcTaskRestartMsg = "COM resynced\r\n"; +const portCHAR * const pcTaskTimeoutMsg = "COM Rx timed out\r\n"; +const portTickType xBlockTime = ( portTickType ) 0xffff / portTICK_RATE_MS; +const portCHAR *pcExpectedChar; +portBASE_TYPE xGotChar; +portCHAR cRxedChar; +portSHORT sResyncRequired, sConsecutiveErrors, sLatchedError; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The first expected character is the first character in the string. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + sConsecutiveErrors = 0; + sLatchedError = pdFALSE; + + for( ;; ) + { + /* Receive a message from the com port interrupt routine. If a message is + not yet available the call will block the task. */ + xGotChar = xSerialGetChar( xPort, &cRxedChar, xBlockTime ); + if( xGotChar == pdTRUE ) + { + if( sResyncRequired == pdTRUE ) + { + /* We got out of sequence and are waiting for the start of the next + transmission of the string. */ + if( cRxedChar == '\n' ) + { + /* This is the end of the message so we can start again - with + the first character in the string being the next thing we expect + to receive. */ + pcExpectedChar = pcMessageToExchange; + sResyncRequired = pdFALSE; + + /* Queue a message for printing to say that we are going to try + again. */ + vPrintDisplayMessage( &pcTaskRestartMsg ); + + /* Stop incrementing the check variable, if consecutive errors occur. */ + sConsecutiveErrors++; + if( sConsecutiveErrors >= comMAX_CONSECUTIVE_ERRORS ) + { + sLatchedError = pdTRUE; + } + } + } + else + { + /* We have received a character, but is it the expected character? */ + if( cRxedChar != *pcExpectedChar ) + { + /* This was not the expected character so post a message for + printing to say that an error has occurred. We will then wait + to resynchronise. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sResyncRequired = pdTRUE; + } + else + { + /* This was the expected character so next time we will expect + the next character in the string. Wrap back to the beginning + of the string when the null terminator has been reached. */ + pcExpectedChar++; + if( *pcExpectedChar == '\0' ) + { + pcExpectedChar = pcMessageToExchange; + + /* We have got through the entire string without error. */ + sConsecutiveErrors = 0; + } + } + } + + /* Increment the count that is used to check that this task is still + running. This is only done if an error has never occurred. */ + if( sLatchedError == pdFALSE ) + { + sRxCount++; + } + } + else + { + vPrintDisplayMessage( &pcTaskTimeoutMsg ); + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static void vSemTestTask( void * pvParameters ) +{ +const portCHAR * const pcTaskStartMsg = "ISR Semaphore test started.\r\n"; +portBASE_TYPE xError = pdFALSE; + + /* Stop warnings. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xSerialWaitForSemaphore( xPort ) ) + { + if( xError == pdFALSE ) + { + sSemCount++; + } + } + else + { + xError = pdTRUE; + } + } +} /*lint !e715 !e830 !e818 pvParameters not used but function prototype must be standard for task function. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreComTestTasksStillRunning( void ) +{ +static portSHORT sLastTxCount = 0, sLastRxCount = 0, sLastSemCount = 0; +portBASE_TYPE xReturn; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. */ + + if( ( sTxCount == sLastTxCount ) || ( sRxCount == sLastRxCount ) || ( sSemCount == sLastSemCount ) ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastTxCount = sTxCount; + sLastRxCount = sRxCount; + sLastSemCount = sSemCount; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +void vComTestUnsuspendTask( void ) +{ + /* The task that is suspended on the semaphore will be referenced from the + Suspended list as it is blocking indefinitely. This call just checks that + the kernel correctly detects this and does not attempt to unsuspend the + task. */ + xTaskResumeFromISR( xSemTestTaskHandle ); +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flop.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flop.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flop.c (revision 14) @@ -0,0 +1,351 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * Creates eight tasks, each of which loops continuously performing an (emulated) + * floating point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + * + * \page FlopC flop.c + * \ingroup DemoFiles + *
+ */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE ( ( unsigned portSHORT ) 512 ) +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static void vCompetingMathTask1( void *pvParameters ); +static void vCompetingMathTask2( void *pvParameters ); +static void vCompetingMathTask3( void *pvParameters ); +static void vCompetingMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile unsigned portSHORT usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask1( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned portSHORT *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( 123.4567 + 2345.6789 ) * -918.222; +const portCHAR * const pcTaskStartMsg = "Math task 1 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Math task 1 failed.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask2( void *pvParameters ) +{ +portDOUBLE d1, d2, d3, d4; +volatile unsigned portSHORT *pusTaskCheckVariable; +const portDOUBLE dAnswer = ( -389.38 / 32498.2 ) * -2.0001; +const portCHAR * const pcTaskStartMsg = "Math task 2 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Math task 2 failed.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask3( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned portSHORT *pusTaskCheckVariable; +const unsigned portSHORT usArraySize = 250; +unsigned portSHORT usPosition; +const portCHAR * const pcTaskStartMsg = "Math task 3 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Math task 3 failed.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition + 5.5; + dTotal1 += ( portDOUBLE ) usPosition + 5.5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompetingMathTask4( void *pvParameters ) +{ +portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned portSHORT *pusTaskCheckVariable; +const unsigned portSHORT usArraySize = 250; +unsigned portSHORT usPosition; +const portCHAR * const pcTaskStartMsg = "Math task 4 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Math task 4 failed.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( ( size_t ) 250 * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + pdArray[ usPosition ] = ( portDOUBLE ) usPosition * 12.123; + dTotal1 += ( portDOUBLE ) usPosition * 12.123; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + dTotal2 += pdArray[ usPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned portSHORT usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/dynamic.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/dynamic.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/dynamic.c (revision 14) @@ -0,0 +1,598 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises it's priority above that of the controller task before each + * increment, lowering it again to it's original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of it's loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume (). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from it's suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + * + * The final set of two tasks implements a third test. This simply raises the + * priority of a task while the scheduler is suspended. Again this test was + * added to exercise parts of the code not covered by the first test. + * + * \page Priorities dynamic.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. + + Added a second, simple test that uses the functions + vQueueReceiveWhenSuspendedTask() and vQueueSendWhenSuspendedTask(). + +Changes from V3.1.1 + + + Added a third simple test that uses the vTaskPrioritySet() function + while the scheduler is suspended. + + Modified the controller task slightly to test the calling of + vTaskResumeAll() while the scheduler is suspended. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" +#include "print.h" + +/* Function that implements the "limited count" task as described above. */ +static void vLimitedIncrementTask( void * pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static void vContinuousIncrementTask( void * pvParameters ); + +/* Function that implements the controller task as described above. */ +static void vCounterControlTask( void * pvParameters ); + +/* The simple test functions that check sending and receiving while the +scheduler is suspended. */ +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ); +static void vQueueSendWhenSuspendedTask( void *pvParameters ); + +/* The simple test functions that check raising and lowering of task priorities +while the scheduler is suspended. */ +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ); +static void prvChangePriorityHelperTask( void *pvParameters ); + + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( portTickType ) 50 ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( unsigned portLONG ) 0xff ) +#define priNO_BLOCK ( ( portTickType ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static xTaskHandle xContinuousIncrementHandle, xLimitedIncrementHandle, xChangePriorityWhenSuspendedHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static unsigned portLONG ulCounter; + +/* Variable used in a similar way by the test that checks the raising and +lowering of task priorities while the scheduler is suspended. */ +static unsigned portLONG ulPrioritySetCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static unsigned portSHORT usCheckVariable = ( unsigned portSHORT ) 0; +static portBASE_TYPE xSuspendedQueueSendError = pdFALSE; +static portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE; +static portBASE_TYPE xPriorityRaiseWhenSuspendedError = pdFALSE; + +/* Queue used by the second test. */ +xQueueHandle xSuspendedTestQueue; + +/*-----------------------------------------------------------*/ +/* + * Start the seven tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned portLONG ) ); + xTaskCreate( vContinuousIncrementTask, "CONT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinuousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, "SUSP_SEND", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, "SUSP_RECV", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvChangePriorityWhenSuspendedTask, "1st_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL ); + xTaskCreate( prvChangePriorityHelperTask, "2nd_P_CHANGE", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, &xChangePriorityWhenSuspendedHandle ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static void vLimitedIncrementTask( void * pvParameters ) +{ +unsigned portLONG *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned portLONG * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static void vContinuousIncrementTask( void * pvParameters ) +{ +unsigned portLONG *pulCounter; +unsigned portBASE_TYPE uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned portLONG * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise our priority above the controller task to ensure a context + switch does not occur while we are accessing this variable. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + ( *pulCounter )++; + vTaskPrioritySet( NULL, uxOurPriority ); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static void vCounterControlTask( void * pvParameters ) +{ +unsigned portLONG ulLastCounter; +portSHORT sLoops; +portSHORT sError = pdFALSE; +const portCHAR * const pcTaskStartMsg = "Priority manipulation tasks started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Priority manipulation Task Failed\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( unsigned portLONG ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. */ + vTaskSuspend( xContinuousIncrementHandle ); + ulLastCounter = ulCounter; + vTaskResume( xContinuousIncrementHandle ); + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + } + xTaskResumeAll(); + } + + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared variable. */ + vTaskSuspend( xContinuousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( unsigned portLONG ) 0; + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. + The scheduler suspension is not necessary but is included for test + purposes. */ + vTaskSuspendAll(); + vTaskResume( xLimitedIncrementHandle ); + xTaskResumeAll(); + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinuousIncrementHandle ); + } +} +/*-----------------------------------------------------------*/ + +static void vQueueSendWhenSuspendedTask( void *pvParameters ) +{ +static unsigned portLONG ulValueToSend = ( unsigned portLONG ) 0; +const portCHAR * const pcTaskStartMsg = "Queue send while suspended task started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Queue send while suspended failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + if( xSuspendedQueueSendError == pdFALSE ) + { + xTaskResumeAll(); + vPrintDisplayMessage( &pcTaskFailMsg ); + vTaskSuspendAll(); + } + + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static void vQueueReceiveWhenSuspendedTask( void *pvParameters ) +{ +static unsigned portLONG ulExpectedValue = ( unsigned portLONG ) 0, ulReceivedValue; +const portCHAR * const pcTaskStartMsg = "Queue receive while suspended task started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Queue receive while suspended failed.\r\n"; +portBASE_TYPE xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + if( xSuspendedQueueReceiveError == pdFALSE ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + } + xSuspendedQueueReceiveError = pdTRUE; + } + + ++ulExpectedValue; + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityWhenSuspendedTask( void *pvParameters ) +{ +const portCHAR * const pcTaskStartMsg = "Priority change when suspended task started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Priority change when suspended task failed.\r\n"; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Start with the counter at 0 so we know what the counter should be + when we check it next. */ + ulPrioritySetCounter = ( unsigned portLONG ) 0; + + /* Resume the helper task. At this time it has a priority lower than + ours so no context switch should occur. */ + vTaskResume( xChangePriorityWhenSuspendedHandle ); + + /* Check to ensure the task just resumed has not executed. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned portLONG ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Now try raising the priority while the scheduler is suspended. */ + vTaskSuspendAll(); + { + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, ( configMAX_PRIORITIES - 1 ) ); + + /* Again, even though the helper task has a priority greater than + ours, it should not have executed yet because the scheduler is + suspended. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned portLONG ) 0 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + } + xTaskResumeAll(); + + /* Now the scheduler has been resumed the helper task should + immediately preempt us and execute. When it executes it will increment + the ulPrioritySetCounter exactly once before suspending itself. + + We should now always find the counter set to 1. */ + portENTER_CRITICAL(); + { + if( ulPrioritySetCounter != ( unsigned portLONG ) 1 ) + { + xPriorityRaiseWhenSuspendedError = pdTRUE; + vPrintDisplayMessage( &pcTaskFailMsg ); + } + } + portEXIT_CRITICAL(); + + /* Delay until we try this again. */ + vTaskDelay( priSLEEP_TIME * 2 ); + + /* Set the priority of the helper task back ready for the next + execution of this task. */ + vTaskSuspendAll(); + vTaskPrioritySet( xChangePriorityWhenSuspendedHandle, tskIDLE_PRIORITY ); + xTaskResumeAll(); + } +} +/*-----------------------------------------------------------*/ + +static void prvChangePriorityHelperTask( void *pvParameters ) +{ + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* This is the helper task for prvChangePriorityWhenSuspendedTask(). + It has it's priority raised and lowered. When it runs it simply + increments the counter then suspends itself again. This allows + prvChangePriorityWhenSuspendedTask() to know how many times it has + executed. */ + ulPrioritySetCounter++; + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static unsigned portSHORT usLastTaskCheck = ( unsigned portSHORT ) 0; +portBASE_TYPE xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xPriorityRaiseWhenSuspendedError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + return xReturn; +} + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/events.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/events.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/events.c (revision 14) @@ -0,0 +1,388 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * This file exercises the event mechanism whereby more than one task is + * blocked waiting for the same event. + * + * The demo creates five tasks - four 'event' tasks, and a controlling task. + * The event tasks have various different priorities and all block on reading + * the same queue. The controlling task writes data to the queue, then checks + * to see which of the event tasks read the data from the queue. The + * controlling task has the lowest priority of all the tasks so is guaranteed + * to always get preempted immediately upon writing to the queue. + * + * By selectively suspending and resuming the event tasks the controlling task + * can check that the highest priority task that is blocked on the queue is the + * task that reads the posted data from the queue. + * + * Two of the event tasks share the same priority. When neither of these tasks + * are suspended they should alternate - one reading one message from the queue, + * the other the next message, etc. + */ + +/* Standard includes. */ +#include +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "mevents.h" +#include "print.h" + +/* Demo specific constants. */ +#define evtSTACK_SIZE ( ( unsigned portBASE_TYPE ) configMINIMAL_STACK_SIZE ) +#define evtNUM_TASKS ( 4 ) +#define evtQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 3 ) +#define evtNO_DELAY 0 + +/* Just indexes used to uniquely identify the tasks. Note that two tasks are +'highest' priority. */ +#define evtHIGHEST_PRIORITY_INDEX_2 3 +#define evtHIGHEST_PRIORITY_INDEX_1 2 +#define evtMEDIUM_PRIORITY_INDEX 1 +#define evtLOWEST_PRIORITY_INDEX 0 + +/* Each event task increments one of these counters each time it reads data +from the queue. */ +static volatile portBASE_TYPE xTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Each time the controlling task posts onto the queue it increments the +expected count of the task that it expected to read the data from the queue +(i.e. the task with the highest priority that should be blocked on the queue). + +xExpectedTaskCounters are incremented from the controlling task, and +xTaskCounters are incremented from the individual event tasks - therefore +comparing xTaskCounters to xExpectedTaskCounters shows whether or not the +correct task was unblocked by the post. */ +static portBASE_TYPE xExpectedTaskCounters[ evtNUM_TASKS ] = { 0, 0, 0, 0 }; + +/* Handles to the four event tasks. These are required to suspend and resume +the tasks. */ +static xTaskHandle xCreatedTasks[ evtNUM_TASKS ]; + +/* The single queue onto which the controlling task posts, and the four event +tasks block. */ +static xQueueHandle xQueue; + +/* Flag used to indicate whether or not an error has occurred at any time. +An error is either the queue being full when not expected, or an unexpected +task reading data from the queue. */ +static portBASE_TYPE xHealthStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* Function that implements the event task. This is created four times. */ +static void prvMultiEventTask( void *pvParameters ); + +/* Function that implements the controlling task. */ +static void prvEventControllerTask( void *pvParameters ); + +/* This is a utility function that posts data to the queue, then compares +xExpectedTaskCounters with xTaskCounters to ensure everything worked as +expected. + +The event tasks all have higher priorities the controlling task. Therefore +the controlling task will always get preempted between writhing to the queue +and checking the task counters. + +@param xExpectedTask The index to the task that the controlling task thinks + should be the highest priority task waiting for data, and + therefore the task that will unblock. + +@param xIncrement The number of items that should be written to the queue. +*/ +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ); + +/* This is just incremented each cycle of the controlling tasks function so +the main application can ensure the test is still running. */ +static portBASE_TYPE xCheckVariable = 0; + +/*-----------------------------------------------------------*/ + +void vStartMultiEventTasks( void ) +{ + /* Create the queue to be used for all the communications. */ + xQueue = xQueueCreate( evtQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) ); + + /* Start the controlling task. This has the idle priority to ensure it is + always preempted by the event tasks. */ + xTaskCreate( prvEventControllerTask, "EvntCTRL", evtSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + + /* Start the four event tasks. Note that two have priority 3, one + priority 2 and the other priority 1. */ + xTaskCreate( prvMultiEventTask, "Event0", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 0 ] ), 1, &( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event1", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 1 ] ), 2, &( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ) ); + xTaskCreate( prvMultiEventTask, "Event2", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 2 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ) ); + xTaskCreate( prvMultiEventTask, "Event3", evtSTACK_SIZE, ( void * ) &( xTaskCounters[ 3 ] ), 3, &( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ) ); +} +/*-----------------------------------------------------------*/ + +static void prvMultiEventTask( void *pvParameters ) +{ +portBASE_TYPE *pxCounter; +unsigned portBASE_TYPE uxDummy; +const portCHAR * const pcTaskStartMsg = "Multi event task started.\r\n"; + + /* The variable this task will increment is passed in as a parameter. */ + pxCounter = ( portBASE_TYPE * ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* Block on the queue. */ + if( xQueueReceive( xQueue, &uxDummy, portMAX_DELAY ) ) + { + /* We unblocked by reading the queue - so simply increment + the counter specific to this task instance. */ + ( *pxCounter )++; + } + else + { + xHealthStatus = pdFAIL; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvEventControllerTask( void *pvParameters ) +{ +const portCHAR * const pcTaskStartMsg = "Multi event controller task started.\r\n"; +portBASE_TYPE xDummy = 0; + + /* Just to stop warnings. */ + ( void ) pvParameters; + + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + /* All tasks are blocked on the queue. When a message is posted one of + the two tasks that share the highest priority should unblock to read + the queue. The next message written should unblock the other task with + the same high priority, and so on in order. No other task should + unblock to read data as they have lower priorities. */ + + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_2, 1 ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* For the rest of these tests we don't need the second 'highest' + priority task - so it is suspended. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + + + /* Now suspend the other highest priority task. The medium priority + task will then be the task with the highest priority that remains + blocked on the queue. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + /* This time, when we post onto the queue we will expect the medium + priority task to unblock and preempt us. */ + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + /* Now try resuming the highest priority task while the scheduler is + suspended. The task should start executing as soon as the scheduler + is resumed - therefore when we post to the queue again, the highest + priority task should again preempt us. */ + vTaskSuspendAll(); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now we are going to suspend the high and medium priority tasks. The + low priority task should then preempt us. Again the task suspension is + done with the whole scheduler suspended just for test purposes. */ + vTaskSuspendAll(); + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + /* Do the same basic test another few times - selectively suspending + and resuming tasks and each time calling prvCheckTaskCounters() passing + to the function the number of the task we expected to be unblocked by + the post. */ + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for test. */ + vTaskSuspendAll(); /* Just for even more test. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + xTaskResumeAll(); + xTaskResumeAll(); + xTaskResumeAll(); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtMEDIUM_PRIORITY_INDEX, 1 ); + + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + prvCheckTaskCounters( evtHIGHEST_PRIORITY_INDEX_1, 1 ); + + /* Now a slight change, first suspend all tasks. */ + vTaskSuspend( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + vTaskSuspend( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* Now when we resume the low priority task and write to the queue 3 + times. We expect the low priority task to service the queue three + times. */ + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + prvCheckTaskCounters( evtLOWEST_PRIORITY_INDEX, evtQUEUE_LENGTH ); + + /* Again suspend all tasks (only the low priority task is not suspended + already). */ + vTaskSuspend( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + + /* This time we are going to suspend the scheduler, resume the low + priority task, then resume the high priority task. In this state we + will write to the queue three times. When the scheduler is resumed + we expect the high priority task to service all three messages. */ + vTaskSuspendAll(); + { + vTaskResume( xCreatedTasks[ evtLOWEST_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_1 ] ); + + for( xDummy = 0; xDummy < evtQUEUE_LENGTH; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + xHealthStatus = pdFAIL; + } + } + + /* The queue should not have been serviced yet!. The scheduler + is still suspended. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + } + xTaskResumeAll(); + + /* We should have been preempted by resuming the scheduler - so by the + time we are running again we expect the high priority task to have + removed three items from the queue. */ + xExpectedTaskCounters[ evtHIGHEST_PRIORITY_INDEX_1 ] += evtQUEUE_LENGTH; + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + xHealthStatus = pdFAIL; + } + + /* The medium priority and second high priority tasks are still + suspended. Make sure to resume them before starting again. */ + vTaskResume( xCreatedTasks[ evtMEDIUM_PRIORITY_INDEX ] ); + vTaskResume( xCreatedTasks[ evtHIGHEST_PRIORITY_INDEX_2 ] ); + + /* Just keep incrementing to show the task is still executing. */ + xCheckVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvCheckTaskCounters( portBASE_TYPE xExpectedTask, portBASE_TYPE xIncrement ) +{ +portBASE_TYPE xDummy = 0; + + /* Write to the queue the requested number of times. The data written is + not important. */ + for( xDummy = 0; xDummy < xIncrement; xDummy++ ) + { + if( xQueueSend( xQueue, &xDummy, evtNO_DELAY ) != pdTRUE ) + { + /* Did not expect to ever find the queue full. */ + xHealthStatus = pdFAIL; + } + } + + /* All the tasks blocked on the queue have a priority higher than the + controlling task. Writing to the queue will therefore have caused this + task to be preempted. By the time this line executes the event task will + have executed and incremented its counter. Increment the expected counter + to the same value. */ + ( xExpectedTaskCounters[ xExpectedTask ] ) += xIncrement; + + /* Check the actual counts and expected counts really are the same. */ + if( memcmp( ( void * ) xExpectedTaskCounters, ( void * ) xTaskCounters, sizeof( xExpectedTaskCounters ) ) ) + { + /* The counters were not the same. This means a task we did not expect + to unblock actually did unblock. */ + xHealthStatus = pdFAIL; + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreMultiEventTasksStillRunning( void ) +{ +static portBASE_TYPE xPreviousCheckVariable = 0; + + /* Called externally to periodically check that this test is still + operational. */ + + if( xPreviousCheckVariable == xCheckVariable ) + { + xHealthStatus = pdFAIL; + } + + xPreviousCheckVariable = xCheckVariable; + + return xHealthStatus; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/semtest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/semtest.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/semtest.c (revision 14) @@ -0,0 +1,305 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * Creates two sets of two tasks. The tasks within a set share a variable, access + * to which is guarded by a semaphore. + * + * Each task starts by attempting to obtain the semaphore. On obtaining a + * semaphore a task checks to ensure that the guarded variable has an expected + * value. It then clears the variable to zero before counting it back up to the + * expected value in increments of 1. After each increment the variable is checked + * to ensure it contains the value to which it was just set. When the starting + * value is again reached the task releases the semaphore giving the other task in + * the set a chance to do exactly the same thing. The starting value is high + * enough to ensure that a tick is likely to occur during the incrementing loop. + * + * An error is flagged if at any time during the process a shared variable is + * found to have a value other than that expected. Such an occurrence would + * suggest an error in the mutual exclusion mechanism by which access to the + * variable is restricted. + * + * The first set of two tasks poll their semaphore. The second set use blocking + * calls. + * + * \page SemTestC semtest.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.0: + + + The tasks that operate at the idle priority now use a lower expected + count than those running at a higher priority. This prevents the low + priority tasks from signaling an error because they have not been + scheduled enough time for each of them to count the shared variable to + the high value. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "semtest.h" +#include "print.h" + +/* The value to which the shared variables are counted. */ +#define semtstBLOCKING_EXPECTED_VALUE ( ( unsigned portLONG ) 0xfff ) +#define semtstNON_BLOCKING_EXPECTED_VALUE ( ( unsigned portLONG ) 0xff ) + +#define semtstSTACK_SIZE configMINIMAL_STACK_SIZE + +#define semtstNUM_TASKS ( 4 ) + +#define semtstDELAY_FACTOR ( ( portTickType ) 10 ) + +/* The task function as described at the top of the file. */ +static void prvSemaphoreTest( void *pvParameters ); + +/* Structure used to pass parameters to each task. */ +typedef struct SEMAPHORE_PARAMETERS +{ + xSemaphoreHandle xSemaphore; + volatile unsigned portLONG *pulSharedVariable; + portTickType xBlockTime; +} xSemaphoreParameters; + +/* Variables used to check that all the tasks are still running without errors. */ +static volatile portSHORT sCheckVariables[ semtstNUM_TASKS ] = { 0 }; +static volatile portSHORT sNextCheckVariable = 0; + +/* Strings to print if USE_STDIO is defined. */ +const portCHAR * const pcPollingSemaphoreTaskError = "Guarded shared variable in unexpected state.\r\n"; +const portCHAR * const pcSemaphoreTaskStart = "Guarded shared variable task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority ) +{ +xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters; +const portTickType xBlockTime = ( portTickType ) 100; + + /* Create the structure used to pass parameters to the first two tasks. */ + pxFirstSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + + if( pxFirstSemaphoreParameters != NULL ) + { + /* Create the semaphore used by the first two tasks. */ + vSemaphoreCreateBinary( pxFirstSemaphoreParameters->xSemaphore ); + + if( pxFirstSemaphoreParameters->xSemaphore != NULL ) + { + /* Create the variable which is to be shared by the first two tasks. */ + pxFirstSemaphoreParameters->pulSharedVariable = ( unsigned portLONG * ) pvPortMalloc( sizeof( unsigned portLONG ) ); + + /* Initialise the share variable to the value the tasks expect. */ + *( pxFirstSemaphoreParameters->pulSharedVariable ) = semtstNON_BLOCKING_EXPECTED_VALUE; + + /* The first two tasks do not block on semaphore calls. */ + pxFirstSemaphoreParameters->xBlockTime = ( portTickType ) 0; + + /* Spawn the first two tasks. As they poll they operate at the idle priority. */ + xTaskCreate( prvSemaphoreTest, "PolSEM1", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL ); + xTaskCreate( prvSemaphoreTest, "PolSEM2", semtstSTACK_SIZE, ( void * ) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, ( xTaskHandle * ) NULL ); + } + } + + /* Do exactly the same to create the second set of tasks, only this time + provide a block time for the semaphore calls. */ + pxSecondSemaphoreParameters = ( xSemaphoreParameters * ) pvPortMalloc( sizeof( xSemaphoreParameters ) ); + if( pxSecondSemaphoreParameters != NULL ) + { + vSemaphoreCreateBinary( pxSecondSemaphoreParameters->xSemaphore ); + + if( pxSecondSemaphoreParameters->xSemaphore != NULL ) + { + pxSecondSemaphoreParameters->pulSharedVariable = ( unsigned portLONG * ) pvPortMalloc( sizeof( unsigned portLONG ) ); + *( pxSecondSemaphoreParameters->pulSharedVariable ) = semtstBLOCKING_EXPECTED_VALUE; + pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_RATE_MS; + + xTaskCreate( prvSemaphoreTest, "BlkSEM1", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL ); + xTaskCreate( prvSemaphoreTest, "BlkSEM2", semtstSTACK_SIZE, ( void * ) pxSecondSemaphoreParameters, uxPriority, ( xTaskHandle * ) NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prvSemaphoreTest( void *pvParameters ) +{ +xSemaphoreParameters *pxParameters; +volatile unsigned portLONG *pulSharedVariable, ulExpectedValue; +unsigned portLONG ulCounter; +portSHORT sError = pdFALSE, sCheckVariableToUse; + + /* See which check variable to use. sNextCheckVariable is not semaphore + protected! */ + portENTER_CRITICAL(); + sCheckVariableToUse = sNextCheckVariable; + sNextCheckVariable++; + portEXIT_CRITICAL(); + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcSemaphoreTaskStart ); + + /* A structure is passed in as the parameter. This contains the shared + variable being guarded. */ + pxParameters = ( xSemaphoreParameters * ) pvParameters; + pulSharedVariable = pxParameters->pulSharedVariable; + + /* If we are blocking we use a much higher count to ensure loads of context + switches occur during the count. */ + if( pxParameters->xBlockTime > ( portTickType ) 0 ) + { + ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE; + } + else + { + ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE; + } + + for( ;; ) + { + /* Try to obtain the semaphore. */ + if( xSemaphoreTake( pxParameters->xSemaphore, pxParameters->xBlockTime ) == pdPASS ) + { + /* We have the semaphore and so expect any other tasks using the + shared variable to have left it in the state we expect to find + it. */ + if( *pulSharedVariable != ulExpectedValue ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + /* Clear the variable, then count it back up to the expected value + before releasing the semaphore. Would expect a context switch or + two during this time. */ + for( ulCounter = ( unsigned portLONG ) 0; ulCounter <= ulExpectedValue; ulCounter++ ) + { + *pulSharedVariable = ulCounter; + if( *pulSharedVariable != ulCounter ) + { + if( sError == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + } + sError = pdTRUE; + } + } + + /* Release the semaphore, and if no errors have occurred increment the check + variable. */ + if( xSemaphoreGive( pxParameters->xSemaphore ) == pdFALSE ) + { + vPrintDisplayMessage( &pcPollingSemaphoreTaskError ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + if( sCheckVariableToUse < semtstNUM_TASKS ) + { + ( sCheckVariables[ sCheckVariableToUse ] )++; + } + } + + /* If we have a block time then we are running at a priority higher + than the idle priority. This task takes a long time to complete + a cycle (deliberately so to test the guarding) so will be starving + out lower priority tasks. Block for some time to allow give lower + priority tasks some processor time. */ + vTaskDelay( pxParameters->xBlockTime * semtstDELAY_FACTOR ); + } + else + { + if( pxParameters->xBlockTime == ( portTickType ) 0 ) + { + /* We have not got the semaphore yet, so no point using the + processor. We are not blocking when attempting to obtain the + semaphore. */ + taskYIELD(); + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreSemaphoreTasksStillRunning( void ) +{ +static portSHORT sLastCheckVariables[ semtstNUM_TASKS ] = { 0 }; +portBASE_TYPE xTask, xReturn = pdTRUE; + + for( xTask = 0; xTask < semtstNUM_TASKS; xTask++ ) + { + if( sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ] ) + { + xReturn = pdFALSE; + } + + sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ]; + } + + return xReturn; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/death.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/death.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/death.c (revision 14) @@ -0,0 +1,223 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * Create a single persistent task which periodically dynamically creates another + * four tasks. The original task is called the creator task, the four tasks it + * creates are called suicidal tasks. + * + * Two of the created suicidal tasks kill one other suicidal task before killing + * themselves - leaving just the original task remaining. + * + * The creator task must be spawned after all of the other demo application tasks + * as it keeps a check on the number of tasks under the scheduler control. The + * number of tasks it expects to see running should never be greater than the + * number of tasks that were in existence when the creator task was spawned, plus + * one set of four suicidal tasks. If this number is exceeded an error is flagged. + * + * \page DeathC death.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "death.h" +#include "print.h" + +#define deathSTACK_SIZE ( ( unsigned portSHORT ) 512 ) + +/* The task originally created which is responsible for periodically dynamically +creating another four tasks. */ +static void vCreateTasks( void *pvParameters ); + +/* The task function of the dynamically created tasks. */ +static void vSuicidalTask( void *pvParameters ); + +/* A variable which is incremented every time the dynamic tasks are created. This +is used to check that the task is still running. */ +static volatile portSHORT sCreationCount = 0; + +/* Used to store the number of tasks that were originally running so the creator +task can tell if any of the suicidal tasks have failed to die. */ +static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0; +static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 5; + +/* Used to store a handle to the tasks that should be killed by a suicidal task, +before it kills itself. */ +xTaskHandle xCreatedTask1, xCreatedTask2; + +/*-----------------------------------------------------------*/ + +void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE *puxPriority; + + /* Create the Creator tasks - passing in as a parameter the priority at which + the suicidal tasks should be created. */ + puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) ); + *puxPriority = uxPriority; + + xTaskCreate( vCreateTasks, "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL ); + + /* Record the number of tasks that are running now so we know if any of the + suicidal tasks have failed to be killed. */ + uxTasksRunningAtStart = uxTaskGetNumberOfTasks(); +} +/*-----------------------------------------------------------*/ + +static void vSuicidalTask( void *pvParameters ) +{ +portDOUBLE d1, d2; +xTaskHandle xTaskToKill; +const portTickType xDelay = ( portTickType ) 500 / portTICK_RATE_MS; + + if( pvParameters != NULL ) + { + /* This task is periodically created four times. Tow created tasks are + passed a handle to the other task so it can kill it before killing itself. + The other task is passed in null. */ + xTaskToKill = *( xTaskHandle* )pvParameters; + } + else + { + xTaskToKill = NULL; + } + + for( ;; ) + { + /* Do something random just to use some stack and registers. */ + d1 = 2.4; + d2 = 89.2; + d2 *= d1; + vTaskDelay( xDelay ); + + if( xTaskToKill != NULL ) + { + /* Make sure the other task has a go before we delete it. */ + vTaskDelay( ( portTickType ) 0 ); + /* Kill the other task that was created by vCreateTasks(). */ + vTaskDelete( xTaskToKill ); + /* Kill ourselves. */ + vTaskDelete( NULL ); + } + } +}/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ +/*-----------------------------------------------------------*/ + +static void vCreateTasks( void *pvParameters ) +{ +const portTickType xDelay = ( portTickType ) 1000 / portTICK_RATE_MS; +unsigned portBASE_TYPE uxPriority; +const portCHAR * const pcTaskStartMsg = "Create task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; + vPortFree( pvParameters ); + + for( ;; ) + { + /* Just loop round, delaying then creating the four suicidal tasks. */ + vTaskDelay( xDelay ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask1 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask1, uxPriority, NULL ); + + xTaskCreate( vSuicidalTask, "SUICIDE1", deathSTACK_SIZE, NULL, uxPriority, &xCreatedTask2 ); + xTaskCreate( vSuicidalTask, "SUICIDE2", deathSTACK_SIZE, &xCreatedTask2, uxPriority, NULL ); + + ++sCreationCount; + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that the creator task is still running and that there +are not any more than four extra tasks. */ +portBASE_TYPE xIsCreateTaskStillRunning( void ) +{ +static portSHORT sLastCreationCount = 0; +portSHORT sReturn = pdTRUE; +unsigned portBASE_TYPE uxTasksRunningNow; + + if( sLastCreationCount == sCreationCount ) + { + sReturn = pdFALSE; + } + + uxTasksRunningNow = uxTaskGetNumberOfTasks(); + + if( uxTasksRunningNow < uxTasksRunningAtStart ) + { + sReturn = pdFALSE; + } + else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) + { + sReturn = pdFALSE; + } + else + { + /* Everything is okay. */ + } + + return sReturn; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/PollQ.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/PollQ.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/PollQ.c (revision 14) @@ -0,0 +1,240 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/** + * This is a very simple queue test. See the BlockQ. c documentation for a more + * comprehensive version. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + * + * \page PollQC pollQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "print.h" + +/* Demo program include files. */ +#include "PollQ.h" + +#define pollqSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE ) + +/* The task that posts the incrementing number onto the queue. */ +static void vPolledQueueProducer( void *pvParameters ); + +/* The task that empties the queue. */ +static void vPolledQueueConsumer( void *pvParameters ); + +/* Variables that are used to check that the tasks are still running with no errors. */ +static volatile portSHORT sPollingConsumerCount = 0, sPollingProducerCount = 0; +/*-----------------------------------------------------------*/ + +void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +static xQueueHandle xPolledQueue; +const unsigned portBASE_TYPE uxQueueSize = 10; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); + xTaskCreate( vPolledQueueProducer, "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueProducer( void *pvParameters ) +{ +unsigned portSHORT usValue = 0, usLoop; +xQueueHandle *pxQueue; +const portTickType xDelay = ( portTickType ) 200 / portTICK_RATE_MS; +const unsigned portSHORT usNumToProduce = 3; +const portCHAR * const pcTaskStartMsg = "Polled queue producer started.\r\n"; +const portCHAR * const pcTaskErrorMsg = "Could not post on polled queue.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( xQueueHandle * ) pvParameters; + + for( ;; ) + { + for( usLoop = 0; usLoop < usNumToProduce; ++usLoop ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueSendToBack( *pxQueue, ( void * ) &usValue, ( portTickType ) 0 ) != pdPASS ) + { + /* We should never find the queue full - this is an error. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + } + else + { + if( sError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + ++sPollingProducerCount; + } + + /* Update the value we are going to post next time around. */ + ++usValue; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +static void vPolledQueueConsumer( void *pvParameters ) +{ +unsigned portSHORT usData, usExpectedValue = 0; +xQueueHandle *pxQueue; +const portTickType xDelay = ( portTickType ) 200 / portTICK_RATE_MS; +const portCHAR * const pcTaskStartMsg = "Polled queue consumer started.\r\n"; +const portCHAR * const pcTaskErrorMsg = "Incorrect value received on polled queue.\r\n"; +portSHORT sError = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The queue being used is passed in as the parameter. */ + pxQueue = ( xQueueHandle * ) pvParameters; + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *pxQueue ) ) + { + if( xQueueReceive( *pxQueue, &usData, ( portTickType ) 0 ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + vPrintDisplayMessage( &pcTaskErrorMsg ); + sError = pdTRUE; + /* Catch-up to the value we received so our next expected value + should again be correct. */ + usExpectedValue = usData; + } + else + { + if( sError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + ++sPollingConsumerCount; + } + } + ++usExpectedValue; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( xDelay ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +portBASE_TYPE xArePollingQueuesStillRunning( void ) +{ +static portSHORT sLastPollingConsumerCount = 0, sLastPollingProducerCount = 0; +portBASE_TYPE xReturn; + + if( ( sLastPollingConsumerCount == sPollingConsumerCount ) || + ( sLastPollingProducerCount == sPollingProducerCount ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + sLastPollingConsumerCount = sPollingConsumerCount; + sLastPollingProducerCount = sPollingProducerCount; + + return xReturn; +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/BlockQ.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/BlockQ.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/BlockQ.c (revision 14) @@ -0,0 +1,328 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + * \page BlockQC blockQ.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.00: + + + Reversed the priority and block times of the second two demo tasks so + they operate as per the description above. + +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. + +Changes from V4.0.2 + + + The second set of tasks were created the wrong way around. This has been + corrected. +*/ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "BlockQ.h" +#include "print.h" + +#define blckqSTACK_SIZE ( ( unsigned portSHORT ) configMINIMAL_STACK_SIZE ) +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + xQueueHandle xQueue; /*< The queue to be used by the task. */ + portTickType xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile portSHORT *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static void vBlockingQueueProducer( void *pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static void vBlockingQueueConsumer( void *pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile portSHORT sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( portSHORT ) 0, ( portSHORT ) 0, ( portSHORT ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile portSHORT sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( portSHORT ) 0, ( portSHORT ) 0, ( portSHORT ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5; +const portTickType xBlockTime = ( portTickType ) 1000 / portTICK_RATE_MS; +const portTickType xDontBlock = ( portTickType ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueProducer( void *pvParameters ) +{ +unsigned portSHORT usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const portCHAR * const pcTaskStartMsg = "Blocking queue producer started.\r\n"; +const portCHAR * const pcTaskErrorMsg = "Could not post on blocking queue\r\n"; +portSHORT sErrorEverOccurred = pdFALSE; + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + for( ;; ) + { + if( xQueueSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static void vBlockingQueueConsumer( void *pvParameters ) +{ +unsigned portSHORT usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +const portCHAR * const pcTaskStartMsg = "Blocking queue consumer started.\r\n"; +const portCHAR * const pcTaskErrorMsg = "Incorrect value received on blocking queue.\r\n"; +portSHORT sErrorEverOccurred = pdFALSE; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + vPrintDisplayMessage( &pcTaskErrorMsg ); + + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreBlockingQueuesStillRunning( void ) +{ +static portSHORT sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( portSHORT ) 0, ( portSHORT ) 0, ( portSHORT ) 0 }; +static portSHORT sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( portSHORT ) 0, ( portSHORT ) 0, ( portSHORT ) 0 }; +portBASE_TYPE xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/print.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/print.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/print.c (revision 14) @@ -0,0 +1,126 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * Manages a queue of strings that are waiting to be displayed. This is used to + * ensure mutual exclusion of console output. + * + * A task wishing to display a message will call vPrintDisplayMessage (), with a + * pointer to the string as the parameter. The pointer is posted onto the + * xPrintQueue queue. + * + * The task spawned in main. c blocks on xPrintQueue. When a message becomes + * available it calls pcPrintGetNextMessage () to obtain a pointer to the next + * string, then uses the functions defined in the portable layer FileIO. c to + * display the message. + * + * NOTE: + * Using console IO can disrupt real time performance - depending on the port. + * Standard C IO routines are not designed for real time applications. While + * standard IO is useful for demonstration and debugging an alternative method + * should be used if you actually require console IO as part of your application. + * + * \page PrintC print.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "queue.h" + +/* Demo program include files. */ +#include "print.h" + +static xQueueHandle xPrintQueue; + +/*-----------------------------------------------------------*/ + +void vPrintInitialise( void ) +{ +const unsigned portBASE_TYPE uxQueueSize = 20; + + /* Create the queue on which errors will be reported. */ + xPrintQueue = xQueueCreate( uxQueueSize, ( unsigned portBASE_TYPE ) sizeof( portCHAR * ) ); +} +/*-----------------------------------------------------------*/ + +void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ) +{ + #ifdef USE_STDIO + xQueueSend( xPrintQueue, ( void * ) ppcMessageToSend, ( portTickType ) 0 ); + #else + /* Stop warnings. */ + ( void ) ppcMessageToSend; + #endif +} +/*-----------------------------------------------------------*/ + +const portCHAR *pcPrintGetNextMessage( portTickType xPrintRate ) +{ +portCHAR *pcMessage; + + if( xQueueReceive( xPrintQueue, &pcMessage, xPrintRate ) == pdPASS ) + { + return pcMessage; + } + else + { + return NULL; + } +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flash.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flash.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/flash.c (revision 14) @@ -0,0 +1,148 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/** + * Creates eight tasks, each of which flash an LED at a different rate. The first + * LED flashes every 125ms, the second every 250ms, the third every 375ms, etc. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + * The PC port uses the standard parallel port for outputs, the Flashlite 186 port + * uses IO port F. + * + * \page flashC flash.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. + +Changes from V2.1.1 + + + The stack size now uses configMINIMAL_STACK_SIZE. + + String constants made file scope to decrease stack depth on 8051 port. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" +#include "print.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE + +/* Structure used to pass parameters to the LED tasks. */ +typedef struct LED_PARAMETERS +{ + unsigned portBASE_TYPE uxLED; /*< The output the task should use. */ + portTickType xFlashRate; /*< The rate at which the LED should flash. */ +} xLEDParameters; + +/* The task that is created eight times - each time with a different xLEDParaemtes +structure passed in as the parameter. */ +static void vLEDFlashTask( void *pvParameters ); + +/* String to print if USE_STDIO is defined. */ +const portCHAR * const pcTaskStartMsg = "LED flash task started.\r\n"; + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ) +{ +unsigned portBASE_TYPE uxLEDTask; +xLEDParameters *pxLEDParameters; +const unsigned portBASE_TYPE uxNumOfLEDs = 8; +const portTickType xFlashRate = 125; + + /* Create the eight tasks. */ + for( uxLEDTask = 0; uxLEDTask < uxNumOfLEDs; ++uxLEDTask ) + { + /* Create and complete the structure used to pass parameters to the next + created task. */ + pxLEDParameters = ( xLEDParameters * ) pvPortMalloc( sizeof( xLEDParameters ) ); + pxLEDParameters->uxLED = uxLEDTask; + pxLEDParameters->xFlashRate = ( xFlashRate + ( xFlashRate * ( portTickType ) uxLEDTask ) ); + pxLEDParameters->xFlashRate /= portTICK_RATE_MS; + + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, "LEDx", ledSTACK_SIZE, ( void * ) pxLEDParameters, uxPriority, ( xTaskHandle * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void vLEDFlashTask( void *pvParameters ) +{ +xLEDParameters *pxParameters; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + pxParameters = ( xLEDParameters * ) pvParameters; + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelay( pxParameters->xFlashRate / ( portTickType ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelay( pxParameters->xFlashRate / ( portTickType ) 2 ); + vParTestToggleLED( pxParameters->uxLED ); + } +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Full/integer.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Full/integer.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Full/integer.c (revision 14) @@ -0,0 +1,347 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* +Changes from V1.2.3 + + + The created tasks now include calls to tskYIELD(), allowing them to be used + with the cooperative scheduler. +*/ + +/** + * This does the same as flop. c, but uses variables of type long instead of + * type double. + * + * As with flop. c, the tasks created in this file are a good test of the + * scheduler context switch mechanism. The processor has to access 32bit + * variables in two or four chunks (depending on the processor). The low + * priority of these tasks means there is a high probability that a context + * switch will occur mid calculation. See the flop. c documentation for + * more information. + * + * \page IntegerC integer.c + * \ingroup DemoFiles + *
+ */ + +/* +Changes from V1.2.1 + + + The constants used in the calculations are larger to ensure the + optimiser does not truncate them to 16 bits. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "print.h" + +/* Demo program include files. */ +#include "integer.h" + +#define intgSTACK_SIZE ( ( unsigned portSHORT ) 256 ) +#define intgNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different calculation on four byte +variables. Each of the four is created twice. */ +static void vCompeteingIntMathTask1( void *pvParameters ); +static void vCompeteingIntMathTask2( void *pvParameters ); +static void vCompeteingIntMathTask3( void *pvParameters ); +static void vCompeteingIntMathTask4( void *pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will stop incrementing its check variable. */ +static volatile unsigned portSHORT usTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; +/*-----------------------------------------------------------*/ + +void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompeteingIntMathTask1, "IntMath1", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath2", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath3", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath4", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask1, "IntMath5", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask2, "IntMath6", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask3, "IntMath7", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompeteingIntMathTask4, "IntMath8", intgSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask1( void *pvParameters ) +{ +portLONG l1, l2, l3, l4; +portSHORT sError = pdFALSE; +volatile unsigned portSHORT *pusTaskCheckVariable; +const portLONG lAnswer = ( ( portLONG ) 74565L + ( portLONG ) 1234567L ) * ( portLONG ) -918L; +const portCHAR * const pcTaskStartMsg = "Integer math task 1 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Integer math task 1 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + l1 = ( portLONG ) 74565L; + l2 = ( portLONG ) 1234567L; + l3 = ( portLONG ) -918L; + + l4 = ( l1 + l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask2( void *pvParameters ) +{ +portLONG l1, l2, l3, l4; +portSHORT sError = pdFALSE; +volatile unsigned portSHORT *pusTaskCheckVariable; +const portLONG lAnswer = ( ( portLONG ) -389000L / ( portLONG ) 329999L ) * ( portLONG ) -89L; +const portCHAR * const pcTaskStartMsg = "Integer math task 2 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Integer math task 2 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + l1 = -389000L; + l2 = 329999L; + l3 = -89L; + + l4 = ( l1 / l2 ) * l3; + + taskYIELD(); + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( l4 != lAnswer ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask3( void *pvParameters ) +{ +portLONG *plArray, lTotal1, lTotal2; +portSHORT sError = pdFALSE; +volatile unsigned portSHORT *pusTaskCheckVariable; +const unsigned portSHORT usArraySize = ( unsigned portSHORT ) 250; +unsigned portSHORT usPosition; +const portCHAR * const pcTaskStartMsg = "Integer math task 3 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Integer math task 3 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( portLONG ) 0; + lTotal2 = ( portLONG ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( portLONG ) usPosition + ( portLONG ) 5; + lTotal1 += ( portLONG ) usPosition + ( portLONG ) 5; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static void vCompeteingIntMathTask4( void *pvParameters ) +{ +portLONG *plArray, lTotal1, lTotal2; +portSHORT sError = pdFALSE; +volatile unsigned portSHORT *pusTaskCheckVariable; +const unsigned portSHORT usArraySize = 250; +unsigned portSHORT usPosition; +const portCHAR * const pcTaskStartMsg = "Integer math task 4 started.\r\n"; +const portCHAR * const pcTaskFailMsg = "Integer math task 4 failed.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Create the array we are going to use for our check calculation. */ + plArray = ( portLONG * ) pvPortMalloc( ( size_t ) 250 * sizeof( portLONG ) ); + + /* Keep filling the array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + lTotal1 = ( portLONG ) 0; + lTotal2 = ( portLONG ) 0; + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + plArray[ usPosition ] = ( portLONG ) usPosition * ( portLONG ) 12; + lTotal1 += ( portLONG ) usPosition * ( portLONG ) 12; + } + + taskYIELD(); + + for( usPosition = 0; usPosition < usArraySize; usPosition++ ) + { + lTotal2 += plArray[ usPosition ]; + } + + + if( lTotal1 != lTotal2 ) + { + vPrintDisplayMessage( &pcTaskFailMsg ); + sError = pdTRUE; + } + + taskYIELD(); + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreIntegerMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned portSHORT usLastTaskCheck[ intgNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < intgNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/GenQTest.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/GenQTest.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/GenQTest.h (revision 14) @@ -0,0 +1,57 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef GEN_Q_TEST_H +#define GEN_Q_TEST_H + +void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreGenericQueueTasksStillRunning( void ); + +#endif /* GEN_Q_TEST_H */ + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlock.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlock.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlock.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FAST_BLOCK_TIME_TEST_H +#define FAST_BLOCK_TIME_TEST_H + +void vCreateAltBlockTimeTasks( void ); +portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/recmutex.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/recmutex.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/recmutex.h (revision 14) @@ -0,0 +1,55 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef RECURSIVE_MUTEX_TEST_H +#define RECURSIVE_MUTEX_TEST_H + +void vStartRecursiveMutexTasks( void ); +portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/print.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/print.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/print.h (revision 14) @@ -0,0 +1,57 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PRINT_H +#define PRINT_H + +void vPrintInitialise( void ); +void vPrintDisplayMessage( const portCHAR * const * pcMessageToSend ); +const portCHAR *pcPrintGetNextMessage( portTickType xPrintRate ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/integer.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/integer.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/integer.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef INTEGER_TASKS_H +#define INTEGER_TASKS_H + +void vStartIntegerMathTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreIntegerMathsTaskStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/flash.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/flash.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/flash.h (revision 14) @@ -0,0 +1,54 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FLASH_LED_H +#define FLASH_LED_H + +void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlckQ.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlckQ.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltBlckQ.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef ALT_BLOCK_Q_H +#define ALT_BLOCK_Q_H + +void vStartAltBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreAltBlockingQueuesStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/countsem.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/countsem.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/countsem.h (revision 14) @@ -0,0 +1,55 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef COUNT_SEMAPHORE_TEST_H +#define COUNT_SEMAPHORE_TEST_H + +void vStartCountingSemaphoreTasks( void ); +portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/IntQueue.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/IntQueue.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/IntQueue.h (revision 14) @@ -0,0 +1,62 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef QUEUE_ACCESS_TEST +#define QUEUE_ACCESS_TEST + +void vStartInterruptQueueTasks( void ); +portBASE_TYPE xAreIntQueueTasksStillRunning( void ); +portBASE_TYPE xFirstTimerHandler( void ); +portBASE_TYPE xSecondTimerHandler( void ); + +#endif /* QUEUE_ACCESS_TEST */ + + + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/flop.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/flop.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/flop.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FLOP_TASKS_H +#define FLOP_TASKS_H + +void vStartMathTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreMathsTaskStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest2.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest2.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest2.h (revision 14) @@ -0,0 +1,55 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( unsigned portBASE_TYPE uxPriority, unsigned portLONG ulBaudRate, unsigned portBASE_TYPE uxLED ); +portBASE_TYPE xAreComTestTasksStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltQTest.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltQTest.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltQTest.h (revision 14) @@ -0,0 +1,57 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FAST_GEN_Q_TEST_H +#define FAST_GEN_Q_TEST_H + +void vStartAltGenericQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreAltGenericQueueTasksStillRunning( void ); + +#endif /* GEN_Q_TEST_H */ + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/blocktim.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/blocktim.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/blocktim.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef BLOCK_TIME_TEST_H +#define BLOCK_TIME_TEST_H + +void vCreateBlockTimeTasks( void ); +portBASE_TYPE xAreBlockTimeTestTasksStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/QPeek.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/QPeek.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/QPeek.h (revision 14) @@ -0,0 +1,57 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef Q_PEEK_TEST_H +#define Q_PEEK_TEST_H + +void vStartQueuePeekTasks( void ); +portBASE_TYPE xAreQueuePeekTasksStillRunning( void ); + +#endif /* Q_PEEK_TEST_H */ + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/fileIO.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/fileIO.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/fileIO.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FILE_IO_H +#define FILE_OI_H + +void vDisplayMessage( const portCHAR * const pcMessageToPrint ); +void vWriteMessageToDisk( const portCHAR * const pcMessage ); +void vWriteBufferToDisk( const portCHAR * const pcBuffer, unsigned portLONG ulBufferLength ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/BlockQ.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/BlockQ.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/BlockQ.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef BLOCK_Q_H +#define BLOCK_Q_H + +void vStartBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreBlockingQueuesStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/comtest.h (revision 14) @@ -0,0 +1,57 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef COMTEST_H +#define COMTEST_H + +void vAltStartComTestTasks( unsigned portBASE_TYPE uxPriority, unsigned portLONG ulBaudRate, unsigned portBASE_TYPE uxLED ); +void vStartComTestTasks( unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate ); +portBASE_TYPE xAreComTestTasksStillRunning( void ); +void vComTestUnsuspendTask( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/serial.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/serial.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/serial.h (revision 14) @@ -0,0 +1,118 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef SERIAL_COMMS_H +#define SERIAL_COMMS_H + +typedef void * xComPortHandle; + +typedef enum +{ + serCOM1, + serCOM2, + serCOM3, + serCOM4, + serCOM5, + serCOM6, + serCOM7, + serCOM8 +} eCOMPort; + +typedef enum +{ + serNO_PARITY, + serODD_PARITY, + serEVEN_PARITY, + serMARK_PARITY, + serSPACE_PARITY +} eParity; + +typedef enum +{ + serSTOP_1, + serSTOP_2 +} eStopBits; + +typedef enum +{ + serBITS_5, + serBITS_6, + serBITS_7, + serBITS_8 +} eDataBits; + +typedef enum +{ + ser50, + ser75, + ser110, + ser134, + ser150, + ser200, + ser300, + ser600, + ser1200, + ser1800, + ser2400, + ser4800, + ser9600, + ser19200, + ser38400, + ser57600, + ser115200 +} eBaud; + +xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxQueueLength ); +xComPortHandle xSerialPortInit( eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength ); +void vSerialPutString( xComPortHandle pxPort, const signed portCHAR * const pcString, unsigned portSHORT usStringLength ); +signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed portCHAR *pcRxedChar, portTickType xBlockTime ); +signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed portCHAR cOutChar, portTickType xBlockTime ); +portBASE_TYPE xSerialWaitForSemaphore( xComPortHandle xPort ); +void vSerialClose( xComPortHandle xPort ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/mevents.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/mevents.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/mevents.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef EVENTS_TEST_H +#define EVENTS_TEST_H + +void vStartMultiEventTasks( void ); +portBASE_TYPE xAreMultiEventTasksStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/crflash.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/crflash.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/crflash.h (revision 14) @@ -0,0 +1,67 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef CRFLASH_LED_H +#define CRFLASH_LED_H + +/* + * Create the co-routines used to flash the LED's at different rates. + * + * @param uxPriority The number of 'fixed delay' co-routines to create. This + * also effects the number of LED's that will be utilised. For example, + * passing in 3 will cause LED's 0 to 2 to be utilised. + */ +void vStartFlashCoRoutines( unsigned portBASE_TYPE uxPriority ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +portBASE_TYPE xAreFlashCoRoutinesStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/partest.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/partest.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/partest.h (revision 14) @@ -0,0 +1,58 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef PARTEST_H +#define PARTEST_H + +#define partstDEFAULT_PORT_ADDRESS ( ( unsigned portSHORT ) 0x378 ) + +void vParTestInitialise( void ); +void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue ); +void vParTestToggleLED( unsigned portBASE_TYPE uxLED ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/dynamic.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/dynamic.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/dynamic.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef DYNAMIC_MANIPULATION_H +#define DYNAMIC_MANIPULATION_H + +void vStartDynamicPriorityTasks( void ); +portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/semtest.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/semtest.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/semtest.h (revision 14) @@ -0,0 +1,55 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef SEMAPHORE_TEST_H +#define SEMAPHORE_TEST_H + +void vStartSemaphoreTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreSemaphoreTasksStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/death.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/death.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/death.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef SUICIDE_TASK_H +#define SUICIDE_TASK_H + +void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xIsCreateTaskStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/crhook.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/crhook.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/crhook.h (revision 14) @@ -0,0 +1,63 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef CRHOOK_H +#define CRHOOK_H + +/* + * Create the co-routines used to communicate wit the tick hook. + */ +void vStartHookCoRoutines( void ); + +/* + * Return pdPASS or pdFAIL depending on whether an error has been detected + * or not. + */ +portBASE_TYPE xAreHookCoRoutinesStillRunning( void ); + +#endif + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/PollQ.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/PollQ.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/PollQ.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef POLLED_Q_H +#define POLLED_Q_H + +void vStartPolledQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xArePollingQueuesStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltPollQ.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltPollQ.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/include/AltPollQ.h (revision 14) @@ -0,0 +1,56 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef ALT_POLLED_Q_H +#define ALT_POLLED_Q_H + +void vStartAltPolledQueueTasks( unsigned portBASE_TYPE uxPriority ); +portBASE_TYPE xAreAltPollingQueuesStillRunning( void ); + +#endif + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/comtest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/comtest.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/comtest.c (revision 14) @@ -0,0 +1,285 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * This version of comtest. c is for use on systems that have limited stack + * space and no display facilities. The complete version can be found in + * the Demo/Common/Full directory. + * + * Creates two tasks that operate on an interrupt driven serial port. A + * loopback connector should be used so that everything that is transmitted is + * also received. The serial port does not use any flow control. On a + * standard 9way 'D' connector pins two and three should be connected together. + * + * The first task posts a sequence of characters to the Tx queue, toggling an + * LED on each successful post. At the end of the sequence it sleeps for a + * pseudo-random period before resending the same sequence. + * + * The UART Tx end interrupt is enabled whenever data is available in the Tx + * queue. The Tx end ISR removes a single character from the Tx queue and + * passes it to the UART for transmission. + * + * The second task blocks on the Rx queue waiting for a character to become + * available. When the UART Rx end interrupt receives a character it places + * it in the Rx queue, waking the second task. The second task checks that the + * characters removed from the Rx queue form the same sequence as those posted + * to the Tx queue, and toggles an LED for each correct character. + * + * The receiving task is spawned with a higher priority than the transmitting + * task. The receiver will therefore wake every time a character is + * transmitted so neither the Tx or Rx queue should ever hold more than a few + * characters. + * + */ + +/* Scheduler include files. */ +#include +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "serial.h" +#include "comtest.h" +#include "partest.h" + +#define comSTACK_SIZE configMINIMAL_STACK_SIZE +#define comTX_LED_OFFSET ( 0 ) +#define comRX_LED_OFFSET ( 1 ) +#define comTOTAL_PERMISSIBLE_ERRORS ( 2 ) + +/* The Tx task will transmit the sequence of characters at a pseudo random +interval. This is the maximum and minimum block time between sends. */ +#define comTX_MAX_BLOCK_TIME ( ( portTickType ) 0x96 ) +#define comTX_MIN_BLOCK_TIME ( ( portTickType ) 0x32 ) +#define comOFFSET_TIME ( ( portTickType ) 3 ) + +/* We should find that each character can be queued for Tx immediately and we +don't have to block to send. */ +#define comNO_BLOCK ( ( portTickType ) 0 ) + +/* The Rx task will block on the Rx queue for a long period. */ +#define comRX_BLOCK_TIME ( ( portTickType ) 0xffff ) + +/* The sequence transmitted is from comFIRST_BYTE to and including comLAST_BYTE. */ +#define comFIRST_BYTE ( 'A' ) +#define comLAST_BYTE ( 'X' ) + +#define comBUFFER_LEN ( ( unsigned portBASE_TYPE ) ( comLAST_BYTE - comFIRST_BYTE ) + ( unsigned portBASE_TYPE ) 1 ) +#define comINITIAL_RX_COUNT_VALUE ( 0 ) + +/* Handle to the com port used by both tasks. */ +static xComPortHandle xPort = NULL; + +/* The transmit task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComTxTask, pvParameters ); + +/* The receive task as described at the top of the file. */ +static portTASK_FUNCTION_PROTO( vComRxTask, pvParameters ); + +/* The LED that should be toggled by the Rx and Tx tasks. The Rx task will +toggle LED ( uxBaseLED + comRX_LED_OFFSET). The Tx task will toggle LED +( uxBaseLED + comTX_LED_OFFSET ). */ +static unsigned portBASE_TYPE uxBaseLED = 0; + +/* Check variable used to ensure no error have occurred. The Rx task will +increment this variable after every successfully received sequence. If at any +time the sequence is incorrect the the variable will stop being incremented. */ +static volatile unsigned portBASE_TYPE uxRxLoops = comINITIAL_RX_COUNT_VALUE; + +/*-----------------------------------------------------------*/ + +void vAltStartComTestTasks( unsigned portBASE_TYPE uxPriority, unsigned portLONG ulBaudRate, unsigned portBASE_TYPE uxLED ) +{ + /* Initialise the com port then spawn the Rx and Tx tasks. */ + uxBaseLED = uxLED; + xSerialPortInitMinimal( ulBaudRate, comBUFFER_LEN ); + + /* The Tx task is spawned with a lower priority than the Rx task. */ + xTaskCreate( vComTxTask, ( signed portCHAR * ) "COMTx", comSTACK_SIZE, NULL, uxPriority - 1, ( xTaskHandle * ) NULL ); + xTaskCreate( vComRxTask, ( signed portCHAR * ) "COMRx", comSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComTxTask, pvParameters ) +{ +signed portCHAR cByteToSend; +portTickType xTimeToWait; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Simply transmit a sequence of characters from comFIRST_BYTE to + comLAST_BYTE. */ + for( cByteToSend = comFIRST_BYTE; cByteToSend <= comLAST_BYTE; cByteToSend++ ) + { + if( xSerialPutChar( xPort, cByteToSend, comNO_BLOCK ) == pdPASS ) + { + vParTestToggleLED( uxBaseLED + comTX_LED_OFFSET ); + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comTX_LED_OFFSET, pdFALSE ); + + /* We have posted all the characters in the string - wait before + re-sending. Wait a pseudo-random time as this will provide a better + test. */ + xTimeToWait = xTaskGetTickCount() + comOFFSET_TIME; + + /* Make sure we don't wait too long... */ + xTimeToWait %= comTX_MAX_BLOCK_TIME; + + /* ...but we do want to wait. */ + if( xTimeToWait < comTX_MIN_BLOCK_TIME ) + { + xTimeToWait = comTX_MIN_BLOCK_TIME; + } + + vTaskDelay( xTimeToWait ); + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vComRxTask, pvParameters ) +{ +signed portCHAR cExpectedByte, cByteRxed; +portBASE_TYPE xResyncRequired = pdFALSE, xErrorOccurred = pdFALSE; + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + /* We expect to receive the characters from comFIRST_BYTE to + comLAST_BYTE in an incrementing order. Loop to receive each byte. */ + for( cExpectedByte = comFIRST_BYTE; cExpectedByte <= comLAST_BYTE; cExpectedByte++ ) + { + /* Block on the queue that contains received bytes until a byte is + available. */ + if( xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ) ) + { + /* Was this the byte we were expecting? If so, toggle the LED, + otherwise we are out on sync and should break out of the loop + until the expected character sequence is about to restart. */ + if( cByteRxed == cExpectedByte ) + { + vParTestToggleLED( uxBaseLED + comRX_LED_OFFSET ); + } + else + { + xResyncRequired = pdTRUE; + break; /*lint !e960 Non-switch break allowed. */ + } + } + } + + /* Turn the LED off while we are not doing anything. */ + vParTestSetLED( uxBaseLED + comRX_LED_OFFSET, pdFALSE ); + + /* Did we break out of the loop because the characters were received in + an unexpected order? If so wait here until the character sequence is + about to restart. */ + if( xResyncRequired == pdTRUE ) + { + while( cByteRxed != comLAST_BYTE ) + { + /* Block until the next char is available. */ + xSerialGetChar( xPort, &cByteRxed, comRX_BLOCK_TIME ); + } + + /* Note that an error occurred which caused us to have to resync. + We use this to stop incrementing the loop counter so + sAreComTestTasksStillRunning() will return false - indicating an + error. */ + xErrorOccurred++; + + /* We have now resynced with the Tx task and can continue. */ + xResyncRequired = pdFALSE; + } + else + { + if( xErrorOccurred < comTOTAL_PERMISSIBLE_ERRORS ) + { + /* Increment the count of successful loops. As error + occurring (i.e. an unexpected character being received) will + prevent this counter being incremented for the rest of the + execution. Don't worry about mutual exclusion on this + variable - it doesn't really matter as we just want it + to change. */ + uxRxLoops++; + } + } + } +} /*lint !e715 !e818 pvParameters is required for a task function even if it is not referenced. */ +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreComTestTasksStillRunning( void ) +{ +portBASE_TYPE xReturn; + + /* If the count of successful reception loops has not changed than at + some time an error occurred (i.e. a character was received out of sequence) + and we will return false. */ + if( uxRxLoops == comINITIAL_RX_COUNT_VALUE ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Reset the count of successful Rx loops. When this function is called + again we expect this to have been incremented. */ + uxRxLoops = comINITIAL_RX_COUNT_VALUE; + + return xReturn; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/IntQueue.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/IntQueue.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/IntQueue.c (revision 14) @@ -0,0 +1,716 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This file defines one of the more complex set of demo/test tasks. They are + * designed to stress test the queue implementation though pseudo simultaneous + * multiple reads and multiple writes from both tasks of varying priority and + * interrupts. The interrupts are prioritised such to ensure that nesting + * occurs (for those ports that support it). + * + * The test ensures that, while being accessed from three tasks and two + * interrupts, all the data sent to the queues is also received from + * the same queue, and that no duplicate items are either sent or received. + * The tests also ensure that a low priority task is never able to successfully + * read from or write to a queue when a task of higher priority is attempting + * the same operation. + */ + +/* Standard includes. */ +#include + +/* SafeRTOS includes. */ +#include "FreeRTOS.h" +#include "queue.h" +#include "task.h" + +/* Demo app includes. */ +#include "IntQueue.h" +#include "IntQueueTimer.h" + +/* Priorities used by test tasks. */ +#define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 2 ) +#define intqLOWER_PRIORITY ( tskIDLE_PRIORITY ) + +/* The number of values to send/receive before checking that all values were +processed as expected. */ +#define intqNUM_VALUES_TO_LOG ( 200 ) +#define intqSHORT_DELAY ( 75 ) + +/* The value by which the value being sent to or received from a queue should +increment past intqNUM_VALUES_TO_LOG before we check that all values have been +sent/received correctly. This is done to ensure that all tasks and interrupts +accessing the queue have completed their accesses with the +intqNUM_VALUES_TO_LOG range. */ +#define intqVALUE_OVERRUN ( 50 ) + +/* The delay used by the polling task. A short delay is used for code +coverage. */ +#define intqONE_TICK_DELAY ( 1 ) + +/* Each task and interrupt is given a unique identifier. This value is used to +identify which task sent or received each value. The identifier is also used +to distinguish between two tasks that are running the same task function. */ +#define intqHIGH_PRIORITY_TASK1 ( ( unsigned portBASE_TYPE ) 1 ) +#define intqHIGH_PRIORITY_TASK2 ( ( unsigned portBASE_TYPE ) 2 ) +#define intqLOW_PRIORITY_TASK ( ( unsigned portBASE_TYPE ) 3 ) +#define intqFIRST_INTERRUPT ( ( unsigned portBASE_TYPE ) 4 ) +#define intqSECOND_INTERRUPT ( ( unsigned portBASE_TYPE ) 5 ) +#define intqQUEUE_LENGTH ( ( unsigned portBASE_TYPE ) 10 ) + +/* At least intqMIN_ACCEPTABLE_TASK_COUNT values should be sent to/received +from each queue by each task, otherwise an error is detected. */ +#define intqMIN_ACCEPTABLE_TASK_COUNT ( 5 ) + +/* Send the next value to the queue that is normally empty. This is called +from within the interrupts. */ +#define timerNORMALLY_EMPTY_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyEmptyQueue ) != pdTRUE ) \ + { \ + unsigned portBASE_TYPE uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyEmptyQueue++; \ + xQueueSendFromISR( xNormallyEmptyQueue, ( void * ) &uxValueForNormallyEmptyQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Send the next value to the queue that is normally full. This is called +from within the interrupts. */ +#define timerNORMALLY_FULL_TX() \ + if( xQueueIsQueueFullFromISR( xNormallyFullQueue ) != pdTRUE ) \ + { \ + unsigned portBASE_TYPE uxSavedInterruptStatus; \ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + uxValueForNormallyFullQueue++; \ + xQueueSendFromISR( xNormallyFullQueue, ( void * ) &uxValueForNormallyFullQueue, &xHigherPriorityTaskWoken ); \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } \ + +/* Receive a value from the normally empty queue. This is called from within +an interrupt. */ +#define timerNORMALLY_EMPTY_RX() \ + if( xQueueReceiveFromISR( xNormallyEmptyQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) != pdPASS ) \ + { \ + prvQueueAccessLogError( __LINE__ ); \ + } \ + else \ + { \ + prvRecordValue_NormallyEmpty( uxRxedValue, intqSECOND_INTERRUPT ); \ + } + +/* Receive a value from the normally full queue. This is called from within +an interrupt. */ +#define timerNORMALLY_FULL_RX() \ + if( xQueueReceiveFromISR( xNormallyFullQueue, &uxRxedValue, &xHigherPriorityTaskWoken ) == pdPASS ) \ + { \ + prvRecordValue_NormallyFull( uxRxedValue, intqSECOND_INTERRUPT ); \ + } \ + + +/*-----------------------------------------------------------*/ + +/* The two queues used by the test. */ +static xQueueHandle xNormallyEmptyQueue, xNormallyFullQueue; + +/* Variables used to detect a stall in one of the tasks. */ +static unsigned portBASE_TYPE uxHighPriorityLoops1 = 0, uxHighPriorityLoops2 = 0, uxLowPriorityLoops1 = 0, uxLowPriorityLoops2 = 0; + +/* Any unexpected behaviour sets xErrorStatus to fail and log the line that +caused the error in xErrorLine. */ +static portBASE_TYPE xErrorStatus = pdPASS; +static unsigned portBASE_TYPE xErrorLine = ( unsigned portBASE_TYPE ) 0; + +/* Used for sequencing between tasks. */ +static portBASE_TYPE xWasSuspended = pdFALSE; + +/* The values that are sent to the queues. An incremented value is sent each +time to each queue. */ +volatile unsigned portBASE_TYPE uxValueForNormallyEmptyQueue = 0, uxValueForNormallyFullQueue = 0; + +/* A handle to some of the tasks is required so they can be suspended/resumed. */ +xTaskHandle xHighPriorityNormallyEmptyTask1, xHighPriorityNormallyEmptyTask2, xHighPriorityNormallyFullTask1, xHighPriorityNormallyFullTask2; + +/* When a value is received in a queue the value is ticked off in the array +the array position of the value is set to a the identifier of the task or +interrupt that accessed the queue. This way missing or duplicate values can be +detected. */ +static unsigned portCHAR ucNormallyEmptyReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; +static unsigned portCHAR ucNormallyFullReceivedValues[ intqNUM_VALUES_TO_LOG ] = { 0 }; + +/* The test tasks themselves. */ +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ); +static void prvLowerPriorityNormallyFullTask( void *pvParameters ); +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ); +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ); +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ); + +/* Used to mark the positions within the ucNormallyEmptyReceivedValues and +ucNormallyFullReceivedValues arrays, while checking for duplicates. */ +static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource ); +static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource ); + +/* Logs the line on which an error occurred. */ +static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine ); + +/*-----------------------------------------------------------*/ + +void vStartInterruptQueueTasks( void ) +{ + /* Start the test tasks. */ + xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H1QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask1 ); + xTaskCreate( prvHigherPriorityNormallyEmptyTask, ( signed portCHAR * ) "H2QRx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyEmptyTask2 ); + xTaskCreate( prvLowerPriorityNormallyEmptyTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + xTaskCreate( prv1stHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK1, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask1 ); + xTaskCreate( prv2ndHigherPriorityNormallyFullTask, ( signed portCHAR * ) "H1QTx", configMINIMAL_STACK_SIZE, ( void * ) intqHIGH_PRIORITY_TASK2, intqHIGHER_PRIORITY, &xHighPriorityNormallyFullTask2 ); + xTaskCreate( prvLowerPriorityNormallyFullTask, ( signed portCHAR * ) "LQRx", configMINIMAL_STACK_SIZE, NULL, intqLOWER_PRIORITY, NULL ); + + /* Create the queues that are accessed by multiple tasks and multiple + interrupts. */ + xNormallyFullQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) ); + xNormallyEmptyQueue = xQueueCreate( intqQUEUE_LENGTH, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xNormallyFullQueue, ( signed portCHAR * ) "NormallyFull" ); + vQueueAddToRegistry( xNormallyEmptyQueue, ( signed portCHAR * ) "NormallyEmpty" ); +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyFull( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyFullReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyFullReceivedValues[ uxValue ] = uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecordValue_NormallyEmpty( unsigned portBASE_TYPE uxValue, unsigned portBASE_TYPE uxSource ) +{ + if( uxValue < intqNUM_VALUES_TO_LOG ) + { + /* We don't expect to receive the same value twice, so if the value + has already been marked as received an error has occurred. */ + if( ucNormallyEmptyReceivedValues[ uxValue ] != 0x00 ) + { + prvQueueAccessLogError( __LINE__ ); + } + + /* Log that this value has been received. */ + ucNormallyEmptyReceivedValues[ uxValue ] = uxSource; + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueAccessLogError( unsigned portBASE_TYPE uxLine ) +{ + /* Latch the line number that caused the error. */ + xErrorLine = uxLine; + xErrorStatus = pdFAIL; +} +/*-----------------------------------------------------------*/ + +static void prvHigherPriorityNormallyEmptyTask( void *pvParameters ) +{ +unsigned portBASE_TYPE uxRxed, ux, uxTask1, uxTask2, uxErrorCount1 = 0, uxErrorCount2 = 0; + + /* The timer should not be started until after the scheduler has started. + More than one task is running this code so we check the parameter value + to determine which task should start the timer. */ + if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + vInitialiseTimerForIntQueueTest(); + } + + for( ;; ) + { + /* Block waiting to receive a value from the normally empty queue. + Interrupts will write to the queue so we should receive a value. */ + if( xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqSHORT_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + /* Note which value was received so we can check all expected + values are received and no values are duplicated. */ + prvRecordValue_NormallyEmpty( uxRxed, ( unsigned portBASE_TYPE ) pvParameters ); + } + + /* Ensure the other task running this code gets a chance to execute. */ + taskYIELD(); + + if( ( unsigned portBASE_TYPE ) pvParameters == intqHIGH_PRIORITY_TASK1 ) + { + /* Have we received all the expected values? */ + if( uxValueForNormallyEmptyQueue > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + vTaskSuspend( xHighPriorityNormallyEmptyTask2 ); + + uxTask1 = 0; + uxTask2 = 0; + + /* Loop through the array, checking that both tasks have + placed values into the array, and that no values are missing. + Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyEmptyReceivedValues[ ux ] == 0 ) + { + /* A value is missing. */ + prvQueueAccessLogError( __LINE__ ); + } + else + { + if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK1 ) + { + /* Value was placed into the array by task 1. */ + uxTask1++; + } + else if( ucNormallyEmptyReceivedValues[ ux ] == intqHIGH_PRIORITY_TASK2 ) + { + /* Value was placed into the array by task 2. */ + uxTask2++; + } + } + } + + if( uxTask1 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 2 seemed to log any values. */ + uxErrorCount1++; + if( uxErrorCount1 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount1 = 0; + } + + if( uxTask2 < intqMIN_ACCEPTABLE_TASK_COUNT ) + { + /* Only task 1 seemed to log any values. */ + uxErrorCount2++; + if( uxErrorCount2 > 2 ) + { + prvQueueAccessLogError( __LINE__ ); + } + } + else + { + uxErrorCount2 = 0; + } + + /* Clear the array again, ready to start a new cycle. */ + memset( ucNormallyEmptyReceivedValues, 0x00, sizeof( ucNormallyEmptyReceivedValues ) ); + + uxHighPriorityLoops1++; + uxValueForNormallyEmptyQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyEmptyTask2 ); + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyEmptyTask( void *pvParameters ) +{ +unsigned portBASE_TYPE uxValue, uxRxed; +portBASE_TYPE xQueueStatus; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( ( xQueueStatus = xQueueReceive( xNormallyEmptyQueue, &uxRxed, intqONE_TICK_DELAY ) ) != errQUEUE_EMPTY ) + { + /* We should only obtain a value when the high priority task is + suspended. */ + if( xTaskIsTaskSuspended( xHighPriorityNormallyEmptyTask1 ) == pdFALSE ) + { + prvQueueAccessLogError( __LINE__ ); + } + + prvRecordValue_NormallyEmpty( uxRxed, intqLOW_PRIORITY_TASK ); + + /* Wake the higher priority task again. */ + vTaskResume( xHighPriorityNormallyEmptyTask1 ); + uxLowPriorityLoops1++; + } + else + { + /* Raise our priority while we send so we can preempt the higher + priority task, and ensure we get the Tx value into the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + portENTER_CRITICAL(); + { + uxValueForNormallyEmptyQueue++; + uxValue = uxValueForNormallyEmptyQueue; + } + portEXIT_CRITICAL(); + + if( xQueueSend( xNormallyEmptyQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv1stHigherPriorityNormallyFullTask( void *pvParameters ) +{ +unsigned portBASE_TYPE uxValueToTx, ux; +portBASE_TYPE xQueueStatus; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS ) + { + /* intqHIGH_PRIORITY_TASK2 is never suspended so we would not + expect it to ever time out. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Allow the other task running this code to run. */ + taskYIELD(); + + /* Have all the expected values been sent to the queue? */ + if( uxValueToTx > ( intqNUM_VALUES_TO_LOG + intqVALUE_OVERRUN ) ) + { + /* Make sure the other high priority task completes its send of + any values below intqNUM_VALUE_TO_LOG. */ + vTaskDelay( intqSHORT_DELAY ); + + vTaskSuspend( xHighPriorityNormallyFullTask2 ); + + if( xWasSuspended == pdTRUE ) + { + /* We would have expected the other high priority task to have + set this back to false by now. */ + prvQueueAccessLogError( __LINE__ ); + } + + /* Set the suspended flag so an error is not logged if the other + task recognises a time out when it is unsuspended. */ + xWasSuspended = pdTRUE; + + /* Start at 1 as we expect position 0 to be unused. */ + for( ux = 1; ux < intqNUM_VALUES_TO_LOG; ux++ ) + { + if( ucNormallyFullReceivedValues[ ux ] == 0 ) + { + /* A value was missing. */ + prvQueueAccessLogError( __LINE__ ); + } + } + + /* Reset the array ready for the next cycle. */ + memset( ucNormallyFullReceivedValues, 0x00, sizeof( ucNormallyFullReceivedValues ) ); + + uxHighPriorityLoops2++; + uxValueForNormallyFullQueue = 0; + + /* Suspend ourselves, allowing the lower priority task to + actually receive something from the queue. Until now it + will have been prevented from doing so by the higher + priority tasks. The lower priority task will resume us + if it receives something. We will then resume the other + higher priority task. */ + vTaskSuspend( NULL ); + vTaskResume( xHighPriorityNormallyFullTask2 ); + } + } +} +/*-----------------------------------------------------------*/ + +static void prv2ndHigherPriorityNormallyFullTask( void *pvParameters ) +{ +unsigned portBASE_TYPE uxValueToTx, ux; +portBASE_TYPE xQueueStatus; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + /* Make sure the queue starts full or near full. >> 1 as there are two + high priority tasks. */ + for( ux = 0; ux < ( intqQUEUE_LENGTH >> 1 ); ux++ ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ); + } + + for( ;; ) + { + portENTER_CRITICAL(); + { + uxValueForNormallyFullQueue++; + uxValueToTx = uxValueForNormallyFullQueue; + } + portEXIT_CRITICAL(); + + if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxValueToTx, intqSHORT_DELAY ) ) != pdPASS ) + { + if( xWasSuspended != pdTRUE ) + { + /* It is ok to time out if the task has been suspended. */ + prvQueueAccessLogError( __LINE__ ); + } + } + + xWasSuspended = pdFALSE; + + taskYIELD(); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowerPriorityNormallyFullTask( void *pvParameters ) +{ +unsigned portBASE_TYPE uxValue, uxTxed = 9999; +portBASE_TYPE xQueueStatus; + + /* The parameters are not being used so avoid compiler warnings. */ + ( void ) pvParameters; + + for( ;; ) + { + if( ( xQueueStatus = xQueueSend( xNormallyFullQueue, &uxTxed, intqONE_TICK_DELAY ) ) != errQUEUE_FULL ) + { + /* We would only expect to succeed when the higher priority task + is suspended. */ + if( xTaskIsTaskSuspended( xHighPriorityNormallyFullTask1 ) == pdFALSE ) + { + prvQueueAccessLogError( __LINE__ ); + } + + vTaskResume( xHighPriorityNormallyFullTask1 ); + uxLowPriorityLoops2++; + } + else + { + /* Raise our priority while we receive so we can preempt the higher + priority task, and ensure we get the value from the queue. */ + vTaskPrioritySet( NULL, intqHIGHER_PRIORITY + 1 ); + + if( xQueueReceive( xNormallyFullQueue, &uxValue, portMAX_DELAY ) != pdPASS ) + { + prvQueueAccessLogError( __LINE__ ); + } + else + { + prvRecordValue_NormallyFull( uxValue, intqLOW_PRIORITY_TASK ); + } + + vTaskPrioritySet( NULL, intqLOWER_PRIORITY ); + } + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xFirstTimerHandler( void ) +{ +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, uxRxedValue; +static unsigned portBASE_TYPE uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_RX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xSecondTimerHandler( void ) +{ +unsigned portBASE_TYPE uxRxedValue; +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; +static unsigned portBASE_TYPE uxNextOperation = 0; + + /* Called from a timer interrupt. Perform various read and write + accesses on the queues. */ + + uxNextOperation++; + + if( uxNextOperation & ( unsigned portBASE_TYPE ) 0x01 ) + { + timerNORMALLY_EMPTY_TX(); + timerNORMALLY_EMPTY_TX(); + + timerNORMALLY_EMPTY_RX(); + timerNORMALLY_EMPTY_RX(); + } + else + { + timerNORMALLY_FULL_RX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + timerNORMALLY_FULL_TX(); + } + + return xHigherPriorityTaskWoken; +} +/*-----------------------------------------------------------*/ + + +portBASE_TYPE xAreIntQueueTasksStillRunning( void ) +{ +static unsigned portBASE_TYPE uxLastHighPriorityLoops1 = 0, uxLastHighPriorityLoops2 = 0, uxLastLowPriorityLoops1 = 0, uxLastLowPriorityLoops2 = 0; + + /* xErrorStatus can be set outside of this function. This function just + checks that all the tasks are still cycling. */ + + if( uxHighPriorityLoops1 == uxLastHighPriorityLoops1 ) + { + /* The high priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops1 = uxHighPriorityLoops1; + + if( uxHighPriorityLoops2 == uxLastHighPriorityLoops2 ) + { + /* The high priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastHighPriorityLoops2 = uxHighPriorityLoops2; + + if( uxLowPriorityLoops1 == uxLastLowPriorityLoops1 ) + { + /* The low priority 1 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops1 = uxLowPriorityLoops1; + + if( uxLowPriorityLoops2 == uxLastLowPriorityLoops2 ) + { + /* The low priority 2 task has stalled. */ + prvQueueAccessLogError( __LINE__ ); + } + + uxLastLowPriorityLoops2 = uxLowPriorityLoops2; + + return xErrorStatus; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flop.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flop.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flop.c (revision 14) @@ -0,0 +1,345 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * Creates eight tasks, each of which loops continuously performing an (emulated) + * floating point calculation. + * + * All the tasks run at the idle priority and never block or yield. This causes + * all eight tasks to time slice with the idle task. Running at the idle priority + * means that these tasks will get pre-empted any time another task is ready to run + * or a time slice occurs. More often than not the pre-emption will occur mid + * calculation, creating a good test of the schedulers context switch mechanism - a + * calculation producing an unexpected result could be a symptom of a corruption in + * the context of a task. + */ + +#include +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "flop.h" + +#define mathSTACK_SIZE configMINIMAL_STACK_SIZE +#define mathNUMBER_OF_TASKS ( 8 ) + +/* Four tasks, each of which performs a different floating point calculation. +Each of the four is created twice. */ +static portTASK_FUNCTION_PROTO( vCompetingMathTask1, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask2, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask3, pvParameters ); +static portTASK_FUNCTION_PROTO( vCompetingMathTask4, pvParameters ); + +/* These variables are used to check that all the tasks are still running. If a +task gets a calculation wrong it will +stop incrementing its check variable. */ +static volatile unsigned portSHORT usTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartMathTasks( unsigned portBASE_TYPE uxPriority ) +{ + xTaskCreate( vCompetingMathTask1, ( signed portCHAR * ) "Math1", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 0 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, ( signed portCHAR * ) "Math2", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 1 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, ( signed portCHAR * ) "Math3", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 2 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, ( signed portCHAR * ) "Math4", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 3 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask1, ( signed portCHAR * ) "Math5", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 4 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask2, ( signed portCHAR * ) "Math6", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 5 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask3, ( signed portCHAR * ) "Math7", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 6 ] ), uxPriority, NULL ); + xTaskCreate( vCompetingMathTask4, ( signed portCHAR * ) "Math8", mathSTACK_SIZE, ( void * ) &( usTaskCheck[ 7 ] ), uxPriority, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask1, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile unsigned portSHORT *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +portSHORT sError = pdFALSE; + + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + dAnswer = ( d1 + d2 ) * d3; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for(;;) + { + d1 = 123.4567; + d2 = 2345.6789; + d3 = -918.222; + + d4 = ( d1 + d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask2, pvParameters ) +{ +volatile portDOUBLE d1, d2, d3, d4; +volatile unsigned portSHORT *pusTaskCheckVariable; +volatile portDOUBLE dAnswer; +portSHORT sError = pdFALSE; + + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + dAnswer = ( d1 / d2 ) * d3; + + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + /* Keep performing a calculation and checking the result against a constant. */ + for( ;; ) + { + d1 = -389.38; + d2 = 32498.2; + d3 = -2.0001; + + d4 = ( d1 / d2 ) * d3; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the calculation does not match the expected constant, stop the + increment of the check variable. */ + if( fabs( d4 - dAnswer ) > 0.001 ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know + this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask3, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned portSHORT *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +portSHORT sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition + 5.5; + dTotal1 += ( portDOUBLE ) xPosition + 5.5; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vCompetingMathTask4, pvParameters ) +{ +volatile portDOUBLE *pdArray, dTotal1, dTotal2, dDifference; +volatile unsigned portSHORT *pusTaskCheckVariable; +const size_t xArraySize = 10; +size_t xPosition; +portSHORT sError = pdFALSE; + + /* The variable this task increments to show it is still running is passed in + as the parameter. */ + pusTaskCheckVariable = ( unsigned portSHORT * ) pvParameters; + + pdArray = ( portDOUBLE * ) pvPortMalloc( xArraySize * sizeof( portDOUBLE ) ); + + /* Keep filling an array, keeping a running total of the values placed in the + array. Then run through the array adding up all the values. If the two totals + do not match, stop the check variable from incrementing. */ + for( ;; ) + { + dTotal1 = 0.0; + dTotal2 = 0.0; + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + pdArray[ xPosition ] = ( portDOUBLE ) xPosition * 12.123; + dTotal1 += ( portDOUBLE ) xPosition * 12.123; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + for( xPosition = 0; xPosition < xArraySize; xPosition++ ) + { + dTotal2 += pdArray[ xPosition ]; + } + + dDifference = dTotal1 - dTotal2; + if( fabs( dDifference ) > 0.001 ) + { + sError = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + if( sError == pdFALSE ) + { + /* If the calculation has always been correct, increment the check + variable so we know this task is still running okay. */ + ( *pusTaskCheckVariable )++; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreMathsTaskStillRunning( void ) +{ +/* Keep a history of the check variables so we know if they have been incremented +since the last call. */ +static unsigned portSHORT usLastTaskCheck[ mathNUMBER_OF_TASKS ] = { ( unsigned portSHORT ) 0 }; +portBASE_TYPE xReturn = pdTRUE, xTask; + + /* Check the maths tasks are still running by ensuring their check variables + are still incrementing. */ + for( xTask = 0; xTask < mathNUMBER_OF_TASKS; xTask++ ) + { + if( usTaskCheck[ xTask ] == usLastTaskCheck[ xTask ] ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + usLastTaskCheck[ xTask ] = usTaskCheck[ xTask ]; + } + + return xReturn; +} + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltQTest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltQTest.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltQTest.c (revision 14) @@ -0,0 +1,569 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * This file implements the same demo and test as GenQTest.c, but uses the + * light weight API in place of the fully featured API. + * + * See the comments at the top of GenQTest.c for a description. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "AltQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueAltSendToFront() and xQueueAltSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static portBASE_TYPE xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile unsigned portLONG ulLoopCounter = 0; +static volatile unsigned portLONG ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile unsigned portLONG ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/*-----------------------------------------------------------*/ + +void vStartAltGenericQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xQueueHandle xQueue; +xSemaphoreHandle xMutex; + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "Alt_Gen_Test_Queue" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, ( signed portCHAR * ) "FGenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Alt_Q_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, ( signed portCHAR * ) "FMuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * ) "FMuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * ) "FMuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +unsigned portLONG ulData, ulData2; +xQueueHandle xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( xQueueHandle ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueAltSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueAltSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueueAltPeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueAltSendToBack( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueAltSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueAltReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Fast mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + + for( ;; ) + { + /* Take the mutex. It should be available now. */ + if( xSemaphoreAltTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set our guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* Our priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + /* We should now have inherited the prioritoy of the high priority task, + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* We can attempt to set our priority to the test priority - between the + idle priority and the medium/high test priorities, but our actual + prioroity should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as our + inherited priority is above that of the medium priority task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the did run then it will have incremented our guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* When we give back the semaphore our priority should be disinherited + back to the priority to which we attempted to set ourselves. This means + that when the high priority task next blocks, the medium priority task + should execute and increment the guarded variable. When we next run + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Check that the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that our priority has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set our priority back to our original priority ready for the next + loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); + + /* Just to show we are still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters; + + ( void ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreAltTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When we eventually obtain the mutex we just give it back then + return to suspend ready for the next test. */ + if( xSemaphoreAltGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreAltGenericQueueTasksStillRunning( void ) +{ +static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loopcounters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return !xErrorDetected; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crflash.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crflash.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crflash.c (revision 14) @@ -0,0 +1,228 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This demo application file demonstrates the use of queues to pass data + * between co-routines. + * + * N represents the number of 'fixed delay' co-routines that are created and + * is set during initialisation. + * + * N 'fixed delay' co-routines are created that just block for a fixed + * period then post the number of an LED onto a queue. Each such co-routine + * uses a different block period. A single 'flash' co-routine is also created + * that blocks on the same queue, waiting for the number of the next LED it + * should flash. Upon receiving a number it simply toggle the instructed LED + * then blocks on the queue once more. In this manner each LED from LED 0 to + * LED N-1 is caused to flash at a different rate. + * + * The 'fixed delay' co-routines are created with co-routine priority 0. The + * flash co-routine is created with co-routine priority 1. This means that + * the queue should never contain more than a single item. This is because + * posting to the queue will unblock the 'flash' co-routine, and as this has + * a priority greater than the tasks posting to the queue it is guaranteed to + * have emptied the queue and blocked once again before the queue can contain + * any more date. An error is indicated if an attempt to post data to the + * queue fails - indicating that the queue is already full. + * + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "partest.h" +#include "crflash.h" + +/* The queue should only need to be of length 1. See the description at the +top of the file. */ +#define crfQUEUE_LENGTH 1 + +#define crfFIXED_DELAY_PRIORITY 0 +#define crfFLASH_PRIORITY 1 + +/* Only one flash co-routine is created so the index is not significant. */ +#define crfFLASH_INDEX 0 + +/* Don't allow more than crfMAX_FLASH_TASKS 'fixed delay' co-routines to be +created. */ +#define crfMAX_FLASH_TASKS 8 + +/* We don't want to block when posting to the queue. */ +#define crfPOSTING_BLOCK_TIME 0 + +/* + * The 'fixed delay' co-routine as described at the top of the file. + */ +static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ); + +/* + * The 'flash' co-routine as described at the top of the file. + */ +static void prvFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ); + +/* The queue used to pass data between the 'fixed delay' co-routines and the +'flash' co-routine. */ +static xQueueHandle xFlashQueue; + +/* This will be set to pdFALSE if we detect an error. */ +static portBASE_TYPE xCoRoutineFlashStatus = pdPASS; + +/*-----------------------------------------------------------*/ + +/* + * See the header file for details. + */ +void vStartFlashCoRoutines( unsigned portBASE_TYPE uxNumberToCreate ) +{ +unsigned portBASE_TYPE uxIndex; + + if( uxNumberToCreate > crfMAX_FLASH_TASKS ) + { + uxNumberToCreate = crfMAX_FLASH_TASKS; + } + + /* Create the queue used to pass data between the co-routines. */ + xFlashQueue = xQueueCreate( crfQUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) ); + + if( xFlashQueue ) + { + /* Create uxNumberToCreate 'fixed delay' co-routines. */ + for( uxIndex = 0; uxIndex < uxNumberToCreate; uxIndex++ ) + { + xCoRoutineCreate( prvFixedDelayCoRoutine, crfFIXED_DELAY_PRIORITY, uxIndex ); + } + + /* Create the 'flash' co-routine. */ + xCoRoutineCreate( prvFlashCoRoutine, crfFLASH_PRIORITY, crfFLASH_INDEX ); + } +} +/*-----------------------------------------------------------*/ + +static void prvFixedDelayCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) +{ +/* Even though this is a co-routine the xResult variable does not need to be +static as we do not need it to maintain its state between blocks. */ +signed portBASE_TYPE xResult; +/* The uxIndex parameter of the co-routine function is used as an index into +the xFlashRates array to obtain the delay period to use. */ +static const portTickType xFlashRates[ crfMAX_FLASH_TASKS ] = { 150 / portTICK_RATE_MS, + 200 / portTICK_RATE_MS, + 250 / portTICK_RATE_MS, + 300 / portTICK_RATE_MS, + 350 / portTICK_RATE_MS, + 400 / portTICK_RATE_MS, + 450 / portTICK_RATE_MS, + 500 / portTICK_RATE_MS }; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + + for( ;; ) + { + /* Post our uxIndex value onto the queue. This is used as the LED to + flash. */ + crQUEUE_SEND( xHandle, xFlashQueue, ( void * ) &uxIndex, crfPOSTING_BLOCK_TIME, &xResult ); + + if( xResult != pdPASS ) + { + /* For the reasons stated at the top of the file we should always + find that we can post to the queue. If we could not then an error + has occurred. */ + xCoRoutineFlashStatus = pdFAIL; + } + + crDELAY( xHandle, xFlashRates[ uxIndex ] ); + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +static void prvFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) +{ +/* Even though this is a co-routine the variable do not need to be +static as we do not need it to maintain their state between blocks. */ +signed portBASE_TYPE xResult; +unsigned portBASE_TYPE uxLEDToFlash; + + /* Co-routines MUST start with a call to crSTART. */ + crSTART( xHandle ); + ( void ) uxIndex; + + for( ;; ) + { + /* Block to wait for the number of the LED to flash. */ + crQUEUE_RECEIVE( xHandle, xFlashQueue, &uxLEDToFlash, portMAX_DELAY, &xResult ); + + if( xResult != pdPASS ) + { + /* We would not expect to wake unless we received something. */ + xCoRoutineFlashStatus = pdFAIL; + } + else + { + /* We received the number of an LED to flash - flash it! */ + vParTestToggleLED( uxLEDToFlash ); + } + } + + /* Co-routines MUST end with a call to crEND. */ + crEND(); +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreFlashCoRoutinesStillRunning( void ) +{ + /* Return pdPASS or pdFAIL depending on whether an error has been detected + or not. */ + return xCoRoutineFlashStatus; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/dynamic.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/dynamic.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/dynamic.c (revision 14) @@ -0,0 +1,421 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * The first test creates three tasks - two counter tasks (one continuous count + * and one limited count) and one controller. A "count" variable is shared + * between all three tasks. The two counter tasks should never be in a "ready" + * state at the same time. The controller task runs at the same priority as + * the continuous count task, and at a lower priority than the limited count + * task. + * + * One counter task loops indefinitely, incrementing the shared count variable + * on each iteration. To ensure it has exclusive access to the variable it + * raises it's priority above that of the controller task before each + * increment, lowering it again to it's original priority before starting the + * next iteration. + * + * The other counter task increments the shared count variable on each + * iteration of it's loop until the count has reached a limit of 0xff - at + * which point it suspends itself. It will not start a new loop until the + * controller task has made it "ready" again by calling vTaskResume (). + * This second counter task operates at a higher priority than controller + * task so does not need to worry about mutual exclusion of the counter + * variable. + * + * The controller task is in two sections. The first section controls and + * monitors the continuous count task. When this section is operational the + * limited count task is suspended. Likewise, the second section controls + * and monitors the limited count task. When this section is operational the + * continuous count task is suspended. + * + * In the first section the controller task first takes a copy of the shared + * count variable. To ensure mutual exclusion on the count variable it + * suspends the continuous count task, resuming it again when the copy has been + * taken. The controller task then sleeps for a fixed period - during which + * the continuous count task will execute and increment the shared variable. + * When the controller task wakes it checks that the continuous count task + * has executed by comparing the copy of the shared variable with its current + * value. This time, to ensure mutual exclusion, the scheduler itself is + * suspended with a call to vTaskSuspendAll (). This is for demonstration + * purposes only and is not a recommended technique due to its inefficiency. + * + * After a fixed number of iterations the controller task suspends the + * continuous count task, and moves on to its second section. + * + * At the start of the second section the shared variable is cleared to zero. + * The limited count task is then woken from it's suspension by a call to + * vTaskResume (). As this counter task operates at a higher priority than + * the controller task the controller task should not run again until the + * shared variable has been counted up to the limited value causing the counter + * task to suspend itself. The next line after vTaskResume () is therefore + * a check on the shared variable to ensure everything is as expected. + * + * + * The second test consists of a couple of very simple tasks that post onto a + * queue while the scheduler is suspended. This test was added to test parts + * of the scheduler not exercised by the first test. + * + */ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "dynamic.h" + +/* Function that implements the "limited count" task as described above. */ +static portTASK_FUNCTION_PROTO( vLimitedIncrementTask, pvParameters ); + +/* Function that implements the "continuous count" task as described above. */ +static portTASK_FUNCTION_PROTO( vContinuousIncrementTask, pvParameters ); + +/* Function that implements the controller task as described above. */ +static portTASK_FUNCTION_PROTO( vCounterControlTask, pvParameters ); + +static portTASK_FUNCTION_PROTO( vQueueReceiveWhenSuspendedTask, pvParameters ); +static portTASK_FUNCTION_PROTO( vQueueSendWhenSuspendedTask, pvParameters ); + +/* Demo task specific constants. */ +#define priSTACK_SIZE ( configMINIMAL_STACK_SIZE ) +#define priSLEEP_TIME ( ( portTickType ) 128 / portTICK_RATE_MS ) +#define priLOOPS ( 5 ) +#define priMAX_COUNT ( ( unsigned portLONG ) 0xff ) +#define priNO_BLOCK ( ( portTickType ) 0 ) +#define priSUSPENDED_QUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* Handles to the two counter tasks. These could be passed in as parameters +to the controller task to prevent them having to be file scope. */ +static xTaskHandle xContinousIncrementHandle, xLimitedIncrementHandle; + +/* The shared counter variable. This is passed in as a parameter to the two +counter variables for demonstration purposes. */ +static unsigned portLONG ulCounter; + +/* Variables used to check that the tasks are still operating without error. +Each complete iteration of the controller task increments this variable +provided no errors have been found. The variable maintaining the same value +is therefore indication of an error. */ +static volatile unsigned portSHORT usCheckVariable = ( unsigned portSHORT ) 0; +static volatile portBASE_TYPE xSuspendedQueueSendError = pdFALSE; +static volatile portBASE_TYPE xSuspendedQueueReceiveError = pdFALSE; + +/* Queue used by the second test. */ +xQueueHandle xSuspendedTestQueue; + +/*-----------------------------------------------------------*/ +/* + * Start the three tasks as described at the top of the file. + * Note that the limited count task is given a higher priority. + */ +void vStartDynamicPriorityTasks( void ) +{ + xSuspendedTestQueue = xQueueCreate( priSUSPENDED_QUEUE_LENGTH, sizeof( unsigned portLONG ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xSuspendedTestQueue, ( signed portCHAR * ) "Suspended_Test_Queue" ); + + xTaskCreate( vContinuousIncrementTask, ( signed portCHAR * ) "CNT_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY, &xContinousIncrementHandle ); + xTaskCreate( vLimitedIncrementTask, ( signed portCHAR * ) "LIM_INC", priSTACK_SIZE, ( void * ) &ulCounter, tskIDLE_PRIORITY + 1, &xLimitedIncrementHandle ); + xTaskCreate( vCounterControlTask, ( signed portCHAR * ) "C_CTRL", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueSendWhenSuspendedTask, ( signed portCHAR * ) "SUSP_TX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vQueueReceiveWhenSuspendedTask, ( signed portCHAR * ) "SUSP_RX", priSTACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +/* + * Just loops around incrementing the shared variable until the limit has been + * reached. Once the limit has been reached it suspends itself. + */ +static portTASK_FUNCTION( vLimitedIncrementTask, pvParameters ) +{ +unsigned portLONG *pulCounter; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned portLONG * ) pvParameters; + + /* This will run before the control task, so the first thing it does is + suspend - the control task will resume it when ready. */ + vTaskSuspend( NULL ); + + for( ;; ) + { + /* Just count up to a value then suspend. */ + ( *pulCounter )++; + + if( *pulCounter >= priMAX_COUNT ) + { + vTaskSuspend( NULL ); + } + } +} +/*-----------------------------------------------------------*/ + +/* + * Just keep counting the shared variable up. The control task will suspend + * this task when it wants. + */ +static portTASK_FUNCTION( vContinuousIncrementTask, pvParameters ) +{ +unsigned portLONG *pulCounter; +unsigned portBASE_TYPE uxOurPriority; + + /* Take a pointer to the shared variable from the parameters passed into + the task. */ + pulCounter = ( unsigned portLONG * ) pvParameters; + + /* Query our priority so we can raise it when exclusive access to the + shared variable is required. */ + uxOurPriority = uxTaskPriorityGet( NULL ); + + for( ;; ) + { + /* Raise our priority above the controller task to ensure a context + switch does not occur while we are accessing this variable. */ + vTaskPrioritySet( NULL, uxOurPriority + 1 ); + ( *pulCounter )++; + vTaskPrioritySet( NULL, uxOurPriority ); + } +} +/*-----------------------------------------------------------*/ + +/* + * Controller task as described above. + */ +static portTASK_FUNCTION( vCounterControlTask, pvParameters ) +{ +unsigned portLONG ulLastCounter; +portSHORT sLoops; +portSHORT sError = pdFALSE; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Start with the counter at zero. */ + ulCounter = ( unsigned portLONG ) 0; + + /* First section : */ + + /* Check the continuous count task is running. */ + for( sLoops = 0; sLoops < priLOOPS; sLoops++ ) + { + /* Suspend the continuous count task so we can take a mirror of the + shared variable without risk of corruption. */ + vTaskSuspend( xContinousIncrementHandle ); + ulLastCounter = ulCounter; + vTaskResume( xContinousIncrementHandle ); + + /* Now delay to ensure the other task has processor time. */ + vTaskDelay( priSLEEP_TIME ); + + /* Check the shared variable again. This time to ensure mutual + exclusion the whole scheduler will be locked. This is just for + demo purposes! */ + vTaskSuspendAll(); + { + if( ulLastCounter == ulCounter ) + { + /* The shared variable has not changed. There is a problem + with the continuous count task so flag an error. */ + sError = pdTRUE; + } + } + xTaskResumeAll(); + } + + + /* Second section: */ + + /* Suspend the continuous counter task so it stops accessing the shared variable. */ + vTaskSuspend( xContinousIncrementHandle ); + + /* Reset the variable. */ + ulCounter = ( unsigned portLONG ) 0; + + /* Resume the limited count task which has a higher priority than us. + We should therefore not return from this call until the limited count + task has suspended itself with a known value in the counter variable. */ + vTaskResume( xLimitedIncrementHandle ); + + /* Does the counter variable have the expected value? */ + if( ulCounter != priMAX_COUNT ) + { + sError = pdTRUE; + } + + if( sError == pdFALSE ) + { + /* If no errors have occurred then increment the check variable. */ + portENTER_CRITICAL(); + usCheckVariable++; + portEXIT_CRITICAL(); + } + + /* Resume the continuous count task and do it all again. */ + vTaskResume( xContinousIncrementHandle ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueSendWhenSuspendedTask, pvParameters ) +{ +static unsigned portLONG ulValueToSend = ( unsigned portLONG ) 0; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + vTaskSuspendAll(); + { + /* We must not block while the scheduler is suspended! */ + if( xQueueSend( xSuspendedTestQueue, ( void * ) &ulValueToSend, priNO_BLOCK ) != pdTRUE ) + { + xSuspendedQueueSendError = pdTRUE; + } + } + xTaskResumeAll(); + + vTaskDelay( priSLEEP_TIME ); + + ++ulValueToSend; + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vQueueReceiveWhenSuspendedTask, pvParameters ) +{ +static unsigned portLONG ulExpectedValue = ( unsigned portLONG ) 0, ulReceivedValue; +portBASE_TYPE xGotValue; + + /* Just to stop warning messages. */ + ( void ) pvParameters; + + for( ;; ) + { + do + { + /* Suspending the scheduler here is fairly pointless and + undesirable for a normal application. It is done here purely + to test the scheduler. The inner xTaskResumeAll() should + never return pdTRUE as the scheduler is still locked by the + outer call. */ + vTaskSuspendAll(); + { + vTaskSuspendAll(); + { + xGotValue = xQueueReceive( xSuspendedTestQueue, ( void * ) &ulReceivedValue, priNO_BLOCK ); + } + if( xTaskResumeAll() ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + } + xTaskResumeAll(); + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + + } while( xGotValue == pdFALSE ); + + if( ulReceivedValue != ulExpectedValue ) + { + xSuspendedQueueReceiveError = pdTRUE; + } + + ++ulExpectedValue; + } +} +/*-----------------------------------------------------------*/ + +/* Called to check that all the created tasks are still running without error. */ +portBASE_TYPE xAreDynamicPriorityTasksStillRunning( void ) +{ +/* Keep a history of the check variables so we know if it has been incremented +since the last call. */ +static unsigned portSHORT usLastTaskCheck = ( unsigned portSHORT ) 0; +portBASE_TYPE xReturn = pdTRUE; + + /* Check the tasks are still running by ensuring the check variable + is still incrementing. */ + + if( usCheckVariable == usLastTaskCheck ) + { + /* The check has not incremented so an error exists. */ + xReturn = pdFALSE; + } + + if( xSuspendedQueueSendError == pdTRUE ) + { + xReturn = pdFALSE; + } + + if( xSuspendedQueueReceiveError == pdTRUE ) + { + xReturn = pdFALSE; + } + + usLastTaskCheck = usCheckVariable; + return xReturn; +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/QPeek.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/QPeek.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/QPeek.c (revision 14) @@ -0,0 +1,440 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Tests the behaviour when data is peeked from a queue when there are + * multiple tasks blocked on the queue. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "QPeek.h" + +#define qpeekQUEUE_LENGTH ( 5 ) +#define qpeekNO_BLOCK ( 0 ) +#define qpeekSHORT_DELAY ( 10 ) + +#define qpeekLOW_PRIORITY ( tskIDLE_PRIORITY + 0 ) +#define qpeekMEDIUM_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define qpeekHIGH_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define qpeekHIGHEST_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * The following three tasks are used to demonstrate the peeking behaviour. + * Each task is given a different priority to demonstrate the order in which + * tasks are woken as data is peeked from a queue. + */ +static void prvLowPriorityPeekTask( void *pvParameters ); +static void prvMediumPriorityPeekTask( void *pvParameters ); +static void prvHighPriorityPeekTask( void *pvParameters ); +static void prvHighestPriorityPeekTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile portBASE_TYPE xErrorDetected = pdFALSE; + +/* Counter that is incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile unsigned portLONG ulLoopCounter = 0; + +/* Handles to the test tasks. */ +xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask; +/*-----------------------------------------------------------*/ + +void vStartQueuePeekTasks( void ) +{ +xQueueHandle xQueue; + + /* Create the queue that we are going to use for the test/demo. */ + xQueue = xQueueCreate( qpeekQUEUE_LENGTH, sizeof( unsigned portLONG ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "QPeek_Test_Queue" ); + + /* Create the demo tasks and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityPeekTask, ( signed portCHAR * )"PeekL", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekLOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityPeekTask, ( signed portCHAR * )"PeekM", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask ); + xTaskCreate( prvHighPriorityPeekTask, ( signed portCHAR * )"PeekH1", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask ); + xTaskCreate( prvHighestPriorityPeekTask, ( signed portCHAR * )"PeekH2", configMINIMAL_STACK_SIZE, ( void * ) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask ); +} +/*-----------------------------------------------------------*/ + +static void prvHighestPriorityPeekTask( void *pvParameters ) +{ +xQueueHandle xQueue = ( xQueueHandle ) pvParameters; +unsigned portLONG ulValue; + + #ifdef USE_STDIO + { + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + } + #endif + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the high priority task to execute. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we reach here the high and medium priority tasks should still + be blocked on the queue. We unblocked because the low priority task + wrote a value to the queue, which we should have peeked. Peeking the + data (rather than receiving it) will leave the data on the queue, so + the high priority task should then have also been unblocked, but not + yet executed. */ + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Now we are going to actually receive the data, so when the high + priority task runs it will find the queue empty and return to the + blocked state. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the value. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x11223344 ) + { + /* We did not receive the expected value - which should have been + the same value as was peeked. */ + xErrorDetected = pdTRUE; + } + + /* Now we will block again as the queue is once more empty. The low + priority task can then execute again. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the low priority task should have again written to the + queue. */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the high priority task to also peek the data. The high priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + + /* This time we are going to do the same as the above test, but the + high priority task is going to receive the data, rather than peek it. + This means that the medium priority task should never peek the value. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityPeekTask( void *pvParameters ) +{ +xQueueHandle xQueue = ( xQueueHandle ) pvParameters; +unsigned portLONG ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the medium priority task to execute. Both the high + and highest priority tasks will then be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the highest priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* We only peeked the data, so suspending ourselves now should enable + the medium priority task to also peek the data. The medium priority task + will have been unblocked when we peeked the data as we left the data + in the queue. */ + vTaskSuspend( NULL ); + + + /* This time we are going actually receive the value, so the medium + priority task will never peek the data - we removed it from the queue. */ + if( xQueueReceive( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulValue != 0xaabbaabb ) + { + xErrorDetected = pdTRUE; + } + + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityPeekTask( void *pvParameters ) +{ +xQueueHandle xQueue = ( xQueueHandle ) pvParameters; +unsigned portLONG ulValue; + + for( ;; ) + { + /* Try peeking from the queue. The queue should be empty so we will + block, allowing the low priority task to execute. The highest, high + and medium priority tasks will then all be blocked on the queue. */ + if( xQueuePeek( xQueue, &ulValue, portMAX_DELAY ) != pdPASS ) + { + /* We expected to have received something by the time we unblock. */ + xErrorDetected = pdTRUE; + } + + /* When we get here the high priority task should have peeked the data + (unblocking this task) then suspended (allowing this task to also peek + the data). */ + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + /* The message should have been left on the queue. */ + xErrorDetected = pdTRUE; + } + + /* Just so we know the test is still running. */ + ulLoopCounter++; + + /* Now we can suspend ourselves so the low priority task can execute + again. */ + vTaskSuspend( NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityPeekTask( void *pvParameters ) +{ +xQueueHandle xQueue = ( xQueueHandle ) pvParameters; +unsigned portLONG ulValue; + + for( ;; ) + { + /* Write some data to the queue. This should unblock the highest + priority task that is waiting to peek data from the queue. */ + ulValue = 0x11223344; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + /* By the time we get here the data should have been removed from + the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* Write another value to the queue, again waking the highest priority + task that is blocked on the queue. */ + ulValue = 0x01234567; + if( xQueueSendToBack( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + /* All the other tasks should now have successfully peeked the data. + The data is still in the queue so we should be able to receive it. */ + ulValue = 0; + if( xQueueReceive( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + if( ulValue != 0x01234567 ) + { + /* We did not receive the expected value. */ + } + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + + /* Unsuspend the other tasks so we can repeat the test - this time + however not all the other tasks will peek the data as the high + priority task is actually going to remove it from the queue. Send + to front is used just to be different. As the queue is empty it + makes no difference to the result. */ + vTaskResume( xMediumPriorityTask ); + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + ulValue = 0xaabbaabb; + if( xQueueSendToFront( xQueue, &ulValue, qpeekNO_BLOCK ) != pdPASS ) + { + /* We were expecting the queue to be empty so we should not of + had a problem writing to the queue. */ + xErrorDetected = pdTRUE; + } + + /* This time we should find that the queue is empty. The high priority + task actually removed the data rather than just peeking it. */ + if( xQueuePeek( xQueue, &ulValue, qpeekNO_BLOCK ) != errQUEUE_EMPTY ) + { + /* We expected to receive the data. */ + xErrorDetected = pdTRUE; + } + + /* Unsuspend the highest and high priority tasks so we can go back + and repeat the whole thing. The medium priority task should not be + suspended as it was not able to peek the data in this last case. */ + vTaskResume( xHighPriorityTask ); + vTaskResume( xHighestPriorityTask ); + + /* Lets just delay a while as this is an intensive test as we don't + want to starve other tests of processing time. */ + vTaskDelay( qpeekSHORT_DELAY ); + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreQueuePeekTasksStillRunning( void ) +{ +static unsigned portLONG ulLastLoopCounter = 0; + + /* If the demo task is still running then we expect the loopcounter to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return !xErrorDetected; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crhook.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crhook.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/crhook.c (revision 14) @@ -0,0 +1,252 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This demo file demonstrates how to send data between an ISR and a + * co-routine. A tick hook function is used to periodically pass data between + * the RTOS tick and a set of 'hook' co-routines. + * + * hookNUM_HOOK_CO_ROUTINES co-routines are created. Each co-routine blocks + * to wait for a character to be received on a queue from the tick ISR, checks + * to ensure the character received was that expected, then sends the number + * back to the tick ISR on a different queue. + * + * The tick ISR checks the numbers received back from the 'hook' co-routines + * matches the number previously sent. + * + * If at any time a queue function returns unexpectedly, or an incorrect value + * is received either by the tick hook or a co-routine then an error is + * latched. + * + * This demo relies on each 'hook' co-routine to execute between each + * hookTICK_CALLS_BEFORE_POST tick interrupts. This and the heavy use of + * queues from within an interrupt may result in an error being detected on + * slower targets simply due to timing. + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "croutine.h" +#include "queue.h" + +/* Demo application includes. */ +#include "crhook.h" + +/* The number of 'hook' co-routines that are to be created. */ +#define hookNUM_HOOK_CO_ROUTINES ( 4 ) + +/* The number of times the tick hook should be called before a character is +posted to the 'hook' co-routines. */ +#define hookTICK_CALLS_BEFORE_POST ( 500 ) + +/* There should never be more than one item in any queue at any time. */ +#define hookHOOK_QUEUE_LENGTH ( 1 ) + +/* Don't block when initially posting to the queue. */ +#define hookNO_BLOCK_TIME ( 0 ) + +/* The priority relative to other co-routines (rather than tasks) that the +'hook' co-routines should take. */ +#define mainHOOK_CR_PRIORITY ( 1 ) +/*-----------------------------------------------------------*/ + +/* + * The co-routine function itself. + */ +static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ); + + +/* + * The tick hook function. This receives a number from each 'hook' co-routine + * then sends a number to each co-routine. An error is flagged if a send or + * receive fails, or an unexpected number is received. + */ +void vApplicationTickHook( void ); + +/*-----------------------------------------------------------*/ + +/* Queues used to send data FROM a co-routine TO the tick hook function. +The hook functions received (Rx's) on these queues. One queue per +'hook' co-routine. */ +static xQueueHandle xHookRxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Queues used to send data FROM the tick hook TO a co-routine function. +The hood function transmits (Tx's) on these queues. One queue per +'hook' co-routine. */ +static xQueueHandle xHookTxQueues[ hookNUM_HOOK_CO_ROUTINES ]; + +/* Set to true if an error is detected at any time. */ +static portBASE_TYPE xCoRoutineErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +void vStartHookCoRoutines( void ) +{ +unsigned portBASE_TYPE uxIndex, uxValueToPost = 0; + + for( uxIndex = 0; uxIndex < hookNUM_HOOK_CO_ROUTINES; uxIndex++ ) + { + /* Create a queue to transmit to and receive from each 'hook' + co-routine. */ + xHookRxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) ); + xHookTxQueues[ uxIndex ] = xQueueCreate( hookHOOK_QUEUE_LENGTH, sizeof( unsigned portBASE_TYPE ) ); + + /* To start things off the tick hook function expects the queue it + uses to receive data to contain a value. */ + xQueueSend( xHookRxQueues[ uxIndex ], &uxValueToPost, hookNO_BLOCK_TIME ); + + /* Create the 'hook' co-routine itself. */ + xCoRoutineCreate( prvHookCoRoutine, mainHOOK_CR_PRIORITY, uxIndex ); + } +} +/*-----------------------------------------------------------*/ + +static unsigned portBASE_TYPE uxCallCounter = 0, uxNumberToPost = 0; +void vApplicationTickHook( void ) +{ +unsigned portBASE_TYPE uxReceivedNumber; +signed portBASE_TYPE xIndex, xCoRoutineWoken; + + /* Is it time to talk to the 'hook' co-routines again? */ + uxCallCounter++; + if( uxCallCounter >= hookTICK_CALLS_BEFORE_POST ) + { + uxCallCounter = 0; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + xCoRoutineWoken = pdFALSE; + if( crQUEUE_RECEIVE_FROM_ISR( xHookRxQueues[ xIndex ], &uxReceivedNumber, &xCoRoutineWoken ) != pdPASS ) + { + /* There is no reason why we would not expect the queue to + contain a value. */ + xCoRoutineErrorDetected = pdTRUE; + } + else + { + /* Each queue used to receive data from the 'hook' co-routines + should contain the number we last posted to the same co-routine. */ + if( uxReceivedNumber != uxNumberToPost ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Nothing should be blocked waiting to post to the queue. */ + if( xCoRoutineWoken != pdFALSE ) + { + xCoRoutineErrorDetected = pdTRUE; + } + } + } + + /* Start the next cycle by posting the next number onto each Tx queue. */ + uxNumberToPost++; + + for( xIndex = 0; xIndex < hookNUM_HOOK_CO_ROUTINES; xIndex++ ) + { + if( crQUEUE_SEND_FROM_ISR( xHookTxQueues[ xIndex ], &uxNumberToPost, pdFALSE ) != pdTRUE ) + { + /* Posting to the queue should have woken the co-routine that + was blocked on the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + } +} +/*-----------------------------------------------------------*/ + +static void prvHookCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex ) +{ +static unsigned portBASE_TYPE uxReceivedValue[ hookNUM_HOOK_CO_ROUTINES ]; +portBASE_TYPE xResult; + + /* Each co-routine MUST start with a call to crSTART(); */ + crSTART( xHandle ); + + for( ;; ) + { + /* Wait to receive a value from the tick hook. */ + xResult = pdFAIL; + crQUEUE_RECEIVE( xHandle, xHookTxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), portMAX_DELAY, &xResult ); + + /* There is no reason why we should not have received something on + the queue. */ + if( xResult != pdPASS ) + { + xCoRoutineErrorDetected = pdTRUE; + } + + /* Send the same number back to the idle hook so it can verify it. */ + xResult = pdFAIL; + crQUEUE_SEND( xHandle, xHookRxQueues[ uxIndex ], &( uxReceivedValue[ uxIndex ] ), hookNO_BLOCK_TIME, &xResult ); + if( xResult != pdPASS ) + { + /* There is no reason why we should not have been able to post to + the queue. */ + xCoRoutineErrorDetected = pdTRUE; + } + } + + /* Each co-routine MUST end with a call to crEND(). */ + crEND(); +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreHookCoRoutinesStillRunning( void ) +{ + if( xCoRoutineErrorDetected ) + { + return pdFALSE; + } + else + { + return pdTRUE; + } +} + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltPollQ.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltPollQ.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltPollQ.c (revision 14) @@ -0,0 +1,257 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This is a version of PollQ.c that uses the alternative (Alt) API. + * + * Creates two tasks that communicate over a single queue. One task acts as a + * producer, the other a consumer. + * + * The producer loops for three iteration, posting an incrementing number onto the + * queue each cycle. It then delays for a fixed period before doing exactly the + * same again. + * + * The consumer loops emptying the queue. Each item removed from the queue is + * checked to ensure it contains the expected value. When the queue is empty it + * blocks for a fixed period, then does the same again. + * + * All queue access is performed without blocking. The consumer completely empties + * the queue each time it runs so the producer should never find the queue full. + * + * An error is flagged if the consumer obtains an unexpected value or the producer + * find the queue is full. + */ + +/* +Changes from V2.0.0 + + + Delay periods are now specified using variables and constants of + portTickType rather than unsigned portLONG. +*/ + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltPollQ.h" + +#define pollqSTACK_SIZE configMINIMAL_STACK_SIZE +#define pollqQUEUE_SIZE ( 10 ) +#define pollqPRODUCER_DELAY ( ( portTickType ) 200 / portTICK_RATE_MS ) +#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( portTickType ) ( 20 / portTICK_RATE_MS ) ) +#define pollqNO_DELAY ( ( portTickType ) 0 ) +#define pollqVALUES_TO_PRODUCE ( ( signed portBASE_TYPE ) 3 ) +#define pollqINITIAL_VALUE ( ( signed portBASE_TYPE ) 0 ) + +/* The task that posts the incrementing number onto the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueProducer, pvParameters ); + +/* The task that empties the queue. */ +static portTASK_FUNCTION_PROTO( vPolledQueueConsumer, pvParameters ); + +/* Variables that are used to check that the tasks are still running with no +errors. */ +static volatile signed portBASE_TYPE xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE; + +/*-----------------------------------------------------------*/ + +void vStartAltPolledQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +static xQueueHandle xPolledQueue; + + /* Create the queue used by the producer and consumer. */ + xPolledQueue = xQueueCreate( pollqQUEUE_SIZE, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xPolledQueue, ( signed portCHAR * ) "AltPollQueue" ); + + + /* Spawn the producer and consumer. */ + xTaskCreate( vPolledQueueConsumer, ( signed portCHAR * ) "QConsNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL ); + xTaskCreate( vPolledQueueProducer, ( signed portCHAR * ) "QProdNB", pollqSTACK_SIZE, ( void * ) &xPolledQueue, uxPriority, ( xTaskHandle * ) NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueProducer, pvParameters ) +{ +unsigned portSHORT usValue = ( unsigned portSHORT ) 0; +signed portBASE_TYPE xError = pdFALSE, xLoop; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt polling queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + for( xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++ ) + { + /* Send an incrementing number on the queue without blocking. */ + if( xQueueAltSendToBack( *( ( xQueueHandle * ) pvParameters ), ( void * ) &usValue, pollqNO_DELAY ) != pdPASS ) + { + /* We should never find the queue full so if we get here there + has been an error. */ + xError = pdTRUE; + } + else + { + if( xError == pdFALSE ) + { + /* If an error has ever been recorded we stop incrementing the + check variable. */ + portENTER_CRITICAL(); + xPollingProducerCount++; + portEXIT_CRITICAL(); + } + + /* Update the value we are going to post next time around. */ + usValue++; + } + } + + /* Wait before we start posting again to ensure the consumer runs and + empties the queue. */ + vTaskDelay( pollqPRODUCER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vPolledQueueConsumer, pvParameters ) +{ +unsigned portSHORT usData, usExpectedValue = ( unsigned portSHORT ) 0; +signed portBASE_TYPE xError = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + /* Loop until the queue is empty. */ + while( uxQueueMessagesWaiting( *( ( xQueueHandle * ) pvParameters ) ) ) + { + if( xQueueAltReceive( *( ( xQueueHandle * ) pvParameters ), &usData, pollqNO_DELAY ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* This is not what we expected to receive so an error has + occurred. */ + xError = pdTRUE; + + /* Catch-up to the value we received so our next expected + value should again be correct. */ + usExpectedValue = usData; + } + else + { + if( xError == pdFALSE ) + { + /* Only increment the check variable if no errors have + occurred. */ + portENTER_CRITICAL(); + xPollingConsumerCount++; + portEXIT_CRITICAL(); + } + } + + /* Next time round we would expect the number to be one higher. */ + usExpectedValue++; + } + } + + /* Now the queue is empty we block, allowing the producer to place more + items in the queue. */ + vTaskDelay( pollqCONSUMER_DELAY ); + } +} /*lint !e818 Function prototype must conform to API. */ +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running with no errors. */ +portBASE_TYPE xAreAltPollingQueuesStillRunning( void ) +{ +portBASE_TYPE xReturn; + + /* Check both the consumer and producer poll count to check they have both + been changed since out last trip round. We do not need a critical section + around the check variables as this is called from a higher priority than + the other tasks that access the same variables. */ + if( ( xPollingConsumerCount == pollqINITIAL_VALUE ) || + ( xPollingProducerCount == pollqINITIAL_VALUE ) + ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + /* Set the check variables back down so we know if they have been + incremented the next time around. */ + xPollingConsumerCount = pollqINITIAL_VALUE; + xPollingProducerCount = pollqINITIAL_VALUE; + + return xReturn; +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/GenQTest.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/GenQTest.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/GenQTest.c (revision 14) @@ -0,0 +1,566 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 - + * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and + * mutex behaviour. + * + * See the comments above the prvSendFrontAndBackTest() and + * prvLowPriorityMutexTask() prototypes below for more information. + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "GenQTest.h" + +#define genqQUEUE_LENGTH ( 5 ) +#define genqNO_BLOCK ( 0 ) + +#define genqMUTEX_LOW_PRIORITY ( tskIDLE_PRIORITY ) +#define genqMUTEX_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 ) + +/*-----------------------------------------------------------*/ + +/* + * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack() + * macros by using both to fill a queue, then reading from the queue to + * check the resultant queue order is as expected. Queue data is also + * peeked. + */ +static void prvSendFrontAndBackTest( void *pvParameters ); + +/* + * The following three tasks are used to demonstrate the mutex behaviour. + * Each task is given a different priority to demonstrate the priority + * inheritance mechanism. + * + * The low priority task obtains a mutex. After this a high priority task + * attempts to obtain the same mutex, causing its priority to be inherited + * by the low priority task. The task with the inherited high priority then + * resumes a medium priority task to ensure it is not blocked by the medium + * priority task while it holds the inherited high priority. Once the mutex + * is returned the task with the inherited priority returns to its original + * low priority, and is therefore immediately preempted by first the high + * priority task and then the medium prioroity task before it can continue. + */ +static void prvLowPriorityMutexTask( void *pvParameters ); +static void prvMediumPriorityMutexTask( void *pvParameters ); +static void prvHighPriorityMutexTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static portBASE_TYPE xErrorDetected = pdFALSE; + +/* Counters that are incremented on each cycle of a test. This is used to +detect a stalled task - a test that is no longer running. */ +static volatile unsigned portLONG ulLoopCounter = 0; +static volatile unsigned portLONG ulLoopCounter2 = 0; + +/* The variable that is guarded by the mutex in the mutex demo tasks. */ +static volatile unsigned portLONG ulGuardedVariable = 0; + +/* Handles used in the mutext test to suspend and resume the high and medium +priority mutex test tasks. */ +static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask; + +/*-----------------------------------------------------------*/ + +void vStartGenericQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xQueueHandle xQueue; +xSemaphoreHandle xMutex; + + /* Create the queue that we are going to use for the + prvSendFrontAndBackTest demo. */ + xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( unsigned portLONG ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xQueue, ( signed portCHAR * ) "Gen_Queue_Test" ); + + /* Create the demo task and pass it the queue just created. We are + passing the queue handle by value so it does not matter that it is + declared on the stack here. */ + xTaskCreate( prvSendFrontAndBackTest, ( signed portCHAR * )"GenQ", configMINIMAL_STACK_SIZE, ( void * ) xQueue, uxPriority, NULL ); + + /* Create the mutex used by the prvMutexTest task. */ + xMutex = xSemaphoreCreateMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutexes and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Gen_Queue_Mutex" ); + + /* Create the mutex demo tasks and pass it the mutex just created. We are + passing the mutex handle by value so it does not matter that it is declared + on the stack here. */ + xTaskCreate( prvLowPriorityMutexTask, ( signed portCHAR * )"MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL ); + xTaskCreate( prvMediumPriorityMutexTask, ( signed portCHAR * )"MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask ); + xTaskCreate( prvHighPriorityMutexTask, ( signed portCHAR * )"MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask ); +} +/*-----------------------------------------------------------*/ + +static void prvSendFrontAndBackTest( void *pvParameters ) +{ +unsigned portLONG ulData, ulData2; +xQueueHandle xQueue; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + xQueue = ( xQueueHandle ) pvParameters; + + for( ;; ) + { + /* The queue is empty, so sending an item to the back of the queue + should have the same efect as sending it to the front of the queue. + + First send to the front and check everything is as expected. */ + xQueueSendToFront( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + /* Then do the same, sending the data to the back, checking everything + is as expected. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + xQueueSendToBack( xQueue, ( void * ) &ulLoopCounter, genqNO_BLOCK ); + + if( uxQueueMessagesWaiting( xQueue ) != 1 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueReceive( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* The data we sent to the queue should equal the data we just received + from the queue. */ + if( ulLoopCounter != ulData ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + + /* Place 2, 3, 4 into the queue, adding items to the back of the queue. */ + for( ulData = 2; ulData < 5; ulData++ ) + { + xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + } + + /* Now the order in the queue should be 2, 3, 4, with 2 being the first + thing to be read out. Now add 1 then 0 to the front of the queue. */ + if( uxQueueMessagesWaiting( xQueue ) != 3 ) + { + xErrorDetected = pdTRUE; + } + ulData = 1; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + ulData = 0; + xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ); + + /* Now the queue should be full, and when we read the data out we + should receive 0, 1, 2, 3, 4. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 0; ulData < genqQUEUE_LENGTH; ulData++ ) + { + /* Try peeking the data first. */ + if( xQueuePeek( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + + + /* Now try receiving the data for real. The value should be the + same. Clobber the value first so we know we really received it. */ + ulData2 = ~ulData2; + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + /* The queue should now be empty again. */ + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /* Our queue is empty once more, add 10, 11 to the back. */ + ulData = 10; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + ulData = 11; + if( xQueueSend( xQueue, &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( uxQueueMessagesWaiting( xQueue ) != 2 ) + { + xErrorDetected = pdTRUE; + } + + /* Now we should have 10, 11 in the queue. Add 7, 8, 9 to the + front. */ + for( ulData = 9; ulData >= 7; ulData-- ) + { + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } + + /* Now check that the queue is full, and that receiving data provides + the expected sequence of 7, 8, 9, 10, 11. */ + if( uxQueueMessagesWaiting( xQueue ) != 5 ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToFront( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + if( xQueueSendToBack( xQueue, ( void * ) &ulData, genqNO_BLOCK ) != errQUEUE_FULL ) + { + xErrorDetected = pdTRUE; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* Check the data we read out is in the expected order. */ + for( ulData = 7; ulData < ( 7 + genqQUEUE_LENGTH ); ulData++ ) + { + if( xQueueReceive( xQueue, &ulData2, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + if( ulData != ulData2 ) + { + xErrorDetected = pdTRUE; + } + } + + if( uxQueueMessagesWaiting( xQueue ) != 0 ) + { + xErrorDetected = pdTRUE; + } + + ulLoopCounter++; + } +} +/*-----------------------------------------------------------*/ + +static void prvLowPriorityMutexTask( void *pvParameters ) +{ +xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + for( ;; ) + { + /* Take the mutex. It should be available now. */ + if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Set our guarded variable to a known start value. */ + ulGuardedVariable = 0; + + /* Our priority should be as per that assigned when the task was + created. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the high priority task. This will attempt to take the + mutex, and block when it finds it cannot obtain it. */ + vTaskResume( xHighPriorityMutexTask ); + + /* We should now have inherited the prioritoy of the high priority task, + as by now it will have attempted to get the mutex. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* We can attempt to set our priority to the test priority - between the + idle priority and the medium/high test priorities, but our actual + prioroity should remain at the high priority. */ + vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY ); + if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Now unsuspend the medium priority task. This should not run as our + inherited priority is above that of the medium priority task. */ + vTaskResume( xMediumPriorityMutexTask ); + + /* If the did run then it will have incremented our guarded variable. */ + if( ulGuardedVariable != 0 ) + { + xErrorDetected = pdTRUE; + } + + /* When we give back the semaphore our priority should be disinherited + back to the priority to which we attempted to set ourselves. This means + that when the high priority task next blocks, the medium priority task + should execute and increment the guarded variable. When we next run + both the high and medium priority tasks will have been suspended again. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* Check that the guarded variable did indeed increment... */ + if( ulGuardedVariable != 1 ) + { + xErrorDetected = pdTRUE; + } + + /* ... and that our priority has been disinherited to + genqMUTEX_TEST_PRIORITY. */ + if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY ) + { + xErrorDetected = pdTRUE; + } + + /* Set our priority back to our original priority ready for the next + loop around this test. */ + vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY ); + + /* Just to show we are still running. */ + ulLoopCounter2++; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + } +} +/*-----------------------------------------------------------*/ + +static void prvMediumPriorityMutexTask( void *pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + /* The medium priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is increment the guarded + variable, this is so the low priority task knows that it has + executed. */ + ulGuardedVariable++; + } +} +/*-----------------------------------------------------------*/ + +static void prvHighPriorityMutexTask( void *pvParameters ) +{ +xSemaphoreHandle xMutex = ( xSemaphoreHandle ) pvParameters; + + for( ;; ) + { + /* The high priority task starts by suspending itself. The low + priority task will unsuspend this task when required. */ + vTaskSuspend( NULL ); + + /* When this task unsuspends all it does is attempt to obtain + the mutex. It should find the mutex is not available so a + block time is specified. */ + if( xSemaphoreTake( xMutex, portMAX_DELAY ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* When we eventually obtain the mutex we just give it back then + return to suspend ready for the next test. */ + if( xSemaphoreGive( xMutex ) != pdPASS ) + { + xErrorDetected = pdTRUE; + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreGenericQueueTasksStillRunning( void ) +{ +static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0; + + /* If the demo task is still running then we expect the loopcounters to + have incremented since this function was last called. */ + if( ulLastLoopCounter == ulLoopCounter ) + { + xErrorDetected = pdTRUE; + } + + if( ulLastLoopCounter2 == ulLoopCounter2 ) + { + xErrorDetected = pdTRUE; + } + + ulLastLoopCounter = ulLoopCounter; + ulLastLoopCounter2 = ulLoopCounter2; + + /* Errors detected in the task itself will have latched xErrorDetected + to true. */ + + return !xErrorDetected; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlock.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlock.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlock.c (revision 14) @@ -0,0 +1,531 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This is a version of BlockTim.c that uses the light weight API. + * + * This file contains some test scenarios that ensure tasks do not exit queue + * send or receive functions prematurely. A description of the tests is + * included within the code. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo includes. */ +#include "AltBlock.h" + +/* Task priorities. */ +#define bktPRIMARY_PRIORITY ( 3 ) +#define bktSECONDARY_PRIORITY ( 2 ) + +/* Task behaviour. */ +#define bktQUEUE_LENGTH ( 5 ) +#define bktSHORT_WAIT ( ( ( portTickType ) 20 ) / portTICK_RATE_MS ) +#define bktPRIMARY_BLOCK_TIME ( 10 ) +#define bktALLOWABLE_MARGIN ( 12 ) +#define bktTIME_TO_BLOCK ( 175 ) +#define bktDONT_BLOCK ( ( portTickType ) 0 ) +#define bktRUN_INDICATOR ( ( unsigned portBASE_TYPE ) 0x55 ) + +/* The queue on which the tasks block. */ +static xQueueHandle xTestQueue; + +/* Handle to the secondary task is required by the primary task for calls +to vTaskSuspend/Resume(). */ +static xTaskHandle xSecondary; + +/* Used to ensure that tasks are still executing without error. */ +static portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0; +static portBASE_TYPE xErrorOccurred = pdFALSE; + +/* Provides a simple mechanism for the primary task to know when the +secondary task has executed. */ +static volatile unsigned portBASE_TYPE xRunIndicator; + +/* The two test tasks. Their behaviour is commented within the files. */ +static void vPrimaryBlockTimeTestTask( void *pvParameters ); +static void vSecondaryBlockTimeTestTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +void vCreateAltBlockTimeTasks( void ) +{ + /* Create the queue on which the two tasks block. */ + xTestQueue = xQueueCreate( bktQUEUE_LENGTH, sizeof( portBASE_TYPE ) ); + + /* vQueueAddToRegistry() adds the queue to the queue registry, if one is + in use. The queue registry is provided as a means for kernel aware + debuggers to locate queues and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( xTestQueue, ( signed portCHAR * ) "AltBlockQueue" ); + + + /* Create the two test tasks. */ + xTaskCreate( vPrimaryBlockTimeTestTask, ( signed portCHAR * )"FBTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL ); + xTaskCreate( vSecondaryBlockTimeTestTask, ( signed portCHAR * )"FBTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary ); +} +/*-----------------------------------------------------------*/ + +static void vPrimaryBlockTimeTestTask( void *pvParameters ) +{ +portBASE_TYPE xItem, xData; +portTickType xTimeWhenBlocking; +portTickType xTimeToBlock, xBlockedTime; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt primary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 + + Simple block time wakeup test on queue receives. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is empty. Attempt to read from the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + /* A critical section is used to minimise the jitter in the time + measurements. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltReceive( xTestQueue, &xData, xTimeToBlock ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 2 + + Simple block time wakeup test on queue sends. + + First fill the queue. It should be empty so all sends should pass. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* The queue is full. Attempt to write to the queue using a block + time. When we wake, ensure the delta in time is as expected. */ + xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem; + + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after xTimeToBlock having not received + anything on the queue. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, xTimeToBlock ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we blocked for? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + if( xBlockedTime < xTimeToBlock ) + { + /* Should not have blocked for less than we requested. */ + xErrorOccurred = pdTRUE; + } + + if( xBlockedTime > ( xTimeToBlock + bktALLOWABLE_MARGIN ) ) + { + /* Should not have blocked for longer than we requested, + although we would not necessarily run as soon as we were + unblocked so a margin is allowed. */ + xErrorOccurred = pdTRUE; + } + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + + /********************************************************************* + Test 3 + + Wake the other task, it will block attempting to post to the queue. + When we read from the queue the other task will wake, but before it + can run we will post to the queue again. When the other task runs it + will find the queue still full, even though it was woken. It should + recognise that its block time has not expired and return to block for + the remains of its block time. + + Wake the other task so it blocks attempting to post to the already + full queue. */ + xRunIndicator = 0; + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + /* The other task has not yet executed. */ + vTaskDelay( bktSHORT_WAIT ); + } + /* Make sure the other task is blocked on the queue. */ + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we make space on the queue the other task should wake + but not execute as this task has higher priority. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now fill the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + full ourselves, and the other task have set xRunIndicator. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + + /* Set the priority back down. */ + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /********************************************************************* + Test 4 + + As per test 3 - but with the send and receive the other way around. + The other task blocks attempting to read from the queue. + + Empty the queue. We should find that it is full. */ + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Wake the other task so it blocks attempting to read from the + already empty queue. */ + vTaskResume( xSecondary ); + + /* We need to wait a little to ensure the other task executes. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + xRunIndicator = 0; + + for( xItem = 0; xItem < bktQUEUE_LENGTH; xItem++ ) + { + /* Now when we place an item on the queue the other task should + wake but not execute as this task has higher priority. */ + if( xQueueAltSendToBack( xTestQueue, &xItem, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Now empty the queue again before the other task gets a chance to + execute. If the other task had executed we would find the queue + empty ourselves, and the other task would be suspended. */ + if( xQueueAltReceive( xTestQueue, &xData, bktDONT_BLOCK ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed. */ + xErrorOccurred = pdTRUE; + } + + /* Raise the priority of the other task so it executes and blocks + on the queue again. */ + vTaskPrioritySet( xSecondary, bktPRIMARY_PRIORITY + 2 ); + + /* The other task should now have re-blocked without exiting the + queue function. */ + if( xRunIndicator == bktRUN_INDICATOR ) + { + /* The other task should not have executed outside of the + queue function. */ + xErrorOccurred = pdTRUE; + } + vTaskPrioritySet( xSecondary, bktSECONDARY_PRIORITY ); + } + + /* Let the other task timeout. When it unblockes it will check that it + unblocked at the correct time, then suspend itself. */ + while( xRunIndicator != bktRUN_INDICATOR ) + { + vTaskDelay( bktSHORT_WAIT ); + } + vTaskDelay( bktSHORT_WAIT ); + + xPrimaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void vSecondaryBlockTimeTestTask( void *pvParameters ) +{ +portTickType xTimeWhenBlocking, xBlockedTime; +portBASE_TYPE xData; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt secondary block time test started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + ( void ) pvParameters; + + for( ;; ) + { + /********************************************************************* + Test 1 and 2 + + This task does does not participate in these tests. */ + vTaskSuspend( NULL ); + + /********************************************************************* + Test 3 + + The first thing we do is attempt to read from the queue. It should be + full so we block. Note the time before we block so we can check the + wake time is as per that expected. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xData = 0; + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltSendToBack( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_FULL ) + { + xErrorOccurred = pdTRUE; + } + + /* How long were we inside the send function? */ + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as + soon as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Suspend ready for test 3. */ + xRunIndicator = bktRUN_INDICATOR; + vTaskSuspend( NULL ); + + /********************************************************************* + Test 4 + + As per test three, but with the send and receive reversed. */ + portENTER_CRITICAL(); + { + xTimeWhenBlocking = xTaskGetTickCount(); + + /* We should unblock after bktTIME_TO_BLOCK having not received + anything on the queue. */ + xRunIndicator = bktRUN_INDICATOR; + if( xQueueAltReceive( xTestQueue, &xData, bktTIME_TO_BLOCK ) != errQUEUE_EMPTY ) + { + xErrorOccurred = pdTRUE; + } + + xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking; + } + portEXIT_CRITICAL(); + + /* We should not have blocked for less time than bktTIME_TO_BLOCK. */ + if( xBlockedTime < bktTIME_TO_BLOCK ) + { + xErrorOccurred = pdTRUE; + } + + /* We should of not blocked for much longer than bktALLOWABLE_MARGIN + either. A margin is permitted as we would not necessarily run as soon + as we unblocked. */ + if( xBlockedTime > ( bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN ) ) + { + xErrorOccurred = pdTRUE; + } + + xRunIndicator = bktRUN_INDICATOR; + + xSecondaryCycles++; + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning( void ) +{ +static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0; +portBASE_TYPE xReturn = pdPASS; + + /* Have both tasks performed at least one cycle since this function was + last called? */ + if( xPrimaryCycles == xLastPrimaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xSecondaryCycles == xLastSecondaryCycleCount ) + { + xReturn = pdFAIL; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + + xLastSecondaryCycleCount = xSecondaryCycles; + xLastPrimaryCycleCount = xPrimaryCycles; + + return xReturn; +} Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/recmutex.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/recmutex.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/recmutex.c (revision 14) @@ -0,0 +1,363 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + The tasks defined on this page demonstrate the use of recursive mutexes. + + For recursive mutex functionality the created mutex should be created using + xSemaphoreCreateRecursiveMutex(), then be manipulated + using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API + functions. + + This demo creates three tasks all of which access the same recursive mutex: + + prvRecursiveMutexControllingTask() has the highest priority so executes + first and grabs the mutex. It then performs some recursive accesses - + between each of which it sleeps for a short period to let the lower + priority tasks execute. When it has completed its demo functionality + it gives the mutex back before suspending itself. + + prvRecursiveMutexBlockingTask() attempts to access the mutex by performing + a blocking 'take'. The blocking task has a lower priority than the + controlling task so by the time it executes the mutex has already been + taken by the controlling task, causing the blocking task to block. It + does not unblock until the controlling task has given the mutex back, + and it does not actually run until the controlling task has suspended + itself (due to the relative priorities). When it eventually does obtain + the mutex all it does is give the mutex back prior to also suspending + itself. At this point both the controlling task and the blocking task are + suspended. + + prvRecursiveMutexPollingTask() runs at the idle priority. It spins round + a tight loop attempting to obtain the mutex with a non-blocking call. As + the lowest priority task it will not successfully obtain the mutex until + both the controlling and blocking tasks are suspended. Once it eventually + does obtain the mutex it first unsuspends both the controlling task and + blocking task prior to giving the mutex back - resulting in the polling + task temporarily inheriting the controlling tasks priority. +*/ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo app include files. */ +#include "recmutex.h" + +/* Priorities assigned to the three tasks. */ +#define recmuCONTROLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define recmuBLOCKING_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define recmuPOLLING_TASK_PRIORITY ( tskIDLE_PRIORITY + 0 ) + +/* The recursive call depth. */ +#define recmuMAX_COUNT ( 10 ) + +/* Misc. */ +#define recmuSHORT_DELAY ( 20 / portTICK_RATE_MS ) +#define recmuNO_DELAY ( ( portTickType ) 0 ) +#define recmuTWO_TICK_DELAY ( ( portTickType ) 2 ) + +/* The three tasks as described at the top of this file. */ +static void prvRecursiveMutexControllingTask( void *pvParameters ); +static void prvRecursiveMutexBlockingTask( void *pvParameters ); +static void prvRecursiveMutexPollingTask( void *pvParameters ); + +/* The mutex used by the demo. */ +static xSemaphoreHandle xMutex; + +/* Variables used to detect and latch errors. */ +static volatile portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE; +static volatile unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles, uxPollingCycles = 0; + +/* Handles of the two higher priority tasks, required so they can be resumed +(unsuspended). */ +static xTaskHandle xControllingTaskHandle, xBlockingTaskHandle; + +/*-----------------------------------------------------------*/ + +void vStartRecursiveMutexTasks( void ) +{ + /* Just creates the mutex and the three tasks. */ + + xMutex = xSemaphoreCreateRecursiveMutex(); + + /* vQueueAddToRegistry() adds the mutex to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate mutex and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( xQueueHandle ) xMutex, ( signed portCHAR * ) "Recursive_Mutex" ); + + + if( xMutex != NULL ) + { + xTaskCreate( prvRecursiveMutexControllingTask, ( signed portCHAR * ) "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle ); + xTaskCreate( prvRecursiveMutexBlockingTask, ( signed portCHAR * ) "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle ); + xTaskCreate( prvRecursiveMutexPollingTask, ( signed portCHAR * ) "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexControllingTask( void *pvParameters ) +{ +unsigned portBASE_TYPE ux; + + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Should not be able to 'give' the mutex, as we have not yet 'taken' + it. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* We should now be able to take the mutex as many times as + we like. A one tick delay is used so the polling task will + inherit our priority on all but the first cycle of this task. + If we did not block attempting to receive the mutex then no + priority inheritance would occur. */ + if( xSemaphoreTakeRecursive( xMutex, recmuTWO_TICK_DELAY ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute. */ + vTaskDelay( recmuSHORT_DELAY ); + } + + /* For each time we took the mutex, give it back. */ + for( ux = 0; ux < recmuMAX_COUNT; ux++ ) + { + /* Ensure the other task attempting to access the mutex (and the + other demo tasks) are able to execute. */ + vTaskDelay( recmuSHORT_DELAY ); + + /* We should now be able to give the mutex as many times as we + took it. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + + /* Having given it back the same number of times as it was taken, we + should no longer be the mutex owner, so the next give sh ould fail. */ + if( xSemaphoreGiveRecursive( xMutex ) == pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxControllingCycles++; + + /* Suspend ourselves to the blocking task can execute. */ + xControllingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xControllingIsSuspended = pdFALSE; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexBlockingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Attempt to obtain the mutex. We should block until the + controlling task has given up the mutex, and not actually execute + past this call until the controlling task is suspended. */ + if( xSemaphoreTakeRecursive( xMutex, portMAX_DELAY ) == pdPASS ) + { + if( xControllingIsSuspended != pdTRUE ) + { + /* Did not expect to execute until the controlling task was + suspended. */ + xErrorOccurred = pdTRUE; + } + else + { + /* Give the mutex back before suspending ourselves to allow + the polling task to obtain the mutex. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + + xBlockingIsSuspended = pdTRUE; + vTaskSuspend( NULL ); + xBlockingIsSuspended = pdFALSE; + } + } + else + { + /* We should not leave the xSemaphoreTakeRecursive() function + until the mutex was obtained. */ + xErrorOccurred = pdTRUE; + } + + /* The controlling and blocking tasks should be in lock step. */ + if( uxControllingCycles != ( uxBlockingCycles + 1 ) ) + { + xErrorOccurred = pdTRUE; + } + + /* Keep count of the number of cycles this task has performed so a + stall can be detected. */ + uxBlockingCycles++; + } +} +/*-----------------------------------------------------------*/ + +static void prvRecursiveMutexPollingTask( void *pvParameters ) +{ + /* Just to remove compiler warning. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Keep attempting to obtain the mutex. We should only obtain it when + the blocking task has suspended itself. */ + if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS ) + { + /* Is the blocking task suspended? */ + if( xBlockingIsSuspended != pdTRUE ) + { + xErrorOccurred = pdTRUE; + } + else + { + /* Keep count of the number of cycles this task has performed so + a stall can be detected. */ + uxPollingCycles++; + + /* We can resume the other tasks here even though they have a + higher priority than the polling task. When they execute they + will attempt to obtain the mutex but fail because the polling + task is still the mutex holder. The polling task (this task) + will then inherit the higher priority. */ + vTaskResume( xBlockingTaskHandle ); + vTaskResume( xControllingTaskHandle ); + + /* Release the mutex, disinheriting the higher priority again. */ + if( xSemaphoreGiveRecursive( xMutex ) != pdPASS ) + { + xErrorOccurred = pdTRUE; + } + } + } + + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreRecursiveMutexTasksStillRunning( void ) +{ +portBASE_TYPE xReturn; +static unsigned portBASE_TYPE uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0; + + /* Is the controlling task still cycling? */ + if( uxLastControllingCycles == uxControllingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastControllingCycles = uxControllingCycles; + } + + /* Is the blocking task still cycling? */ + if( uxLastBlockingCycles == uxBlockingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastBlockingCycles = uxBlockingCycles; + } + + /* Is the polling task still cycling? */ + if( uxLastPollingCycles == uxPollingCycles ) + { + xErrorOccurred = pdTRUE; + } + else + { + uxLastPollingCycles = uxPollingCycles; + } + + if( xErrorOccurred == pdTRUE ) + { + xReturn = pdFAIL; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} + + + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlckQ.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlckQ.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/AltBlckQ.c (revision 14) @@ -0,0 +1,314 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/* + * This is a version of BlockQ.c that uses the alternative (Alt) API. + * + * Creates six tasks that operate on three queues as follows: + * + * The first two tasks send and receive an incrementing number to/from a queue. + * One task acts as a producer and the other as the consumer. The consumer is a + * higher priority than the producer and is set to block on queue reads. The queue + * only has space for one item - as soon as the producer posts a message on the + * queue the consumer will unblock, pre-empt the producer, and remove the item. + * + * The second two tasks work the other way around. Again the queue used only has + * enough space for one item. This time the consumer has a lower priority than the + * producer. The producer will try to post on the queue blocking when the queue is + * full. When the consumer wakes it will remove the item from the queue, causing + * the producer to unblock, pre-empt the consumer, and immediately re-fill the + * queue. + * + * The last two tasks use the same queue producer and consumer functions. This time the queue has + * enough space for lots of items and the tasks operate at the same priority. The + * producer will execute, placing items into the queue. The consumer will start + * executing when either the queue becomes full (causing the producer to block) or + * a context switch occurs (tasks of the same priority will time slice). + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Demo program include files. */ +#include "AltBlckQ.h" + +#define blckqSTACK_SIZE configMINIMAL_STACK_SIZE +#define blckqNUM_TASK_SETS ( 3 ) + +/* Structure used to pass parameters to the blocking queue tasks. */ +typedef struct BLOCKING_QUEUE_PARAMETERS +{ + xQueueHandle xQueue; /*< The queue to be used by the task. */ + portTickType xBlockTime; /*< The block time to use on queue reads/writes. */ + volatile portSHORT *psCheckVariable; /*< Incremented on each successful cycle to check the task is still running. */ +} xBlockingQueueParameters; + +/* Task function that creates an incrementing number and posts it on a queue. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueProducer, pvParameters ); + +/* Task function that removes the incrementing number from a queue and checks that +it is the expected number. */ +static portTASK_FUNCTION_PROTO( vBlockingQueueConsumer, pvParameters ); + +/* Variables which are incremented each time an item is removed from a queue, and +found to be the expected value. +These are used to check that the tasks are still running. */ +static volatile portSHORT sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; + +/* Variable which are incremented each time an item is posted on a queue. These +are used to check that the tasks are still running. */ +static volatile portSHORT sBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; + +/*-----------------------------------------------------------*/ + +void vStartAltBlockingQueueTasks( unsigned portBASE_TYPE uxPriority ) +{ +xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2; +xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4; +xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6; +const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5; +const portTickType xBlockTime = ( portTickType ) 1000 / portTICK_RATE_MS; +const portTickType xDontBlock = ( portTickType ) 0; + + /* Create the first two tasks as described at the top of the file. */ + + /* First create the structure used to pass parameters to the consumer tasks. */ + pxQueueParameters1 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Create the queue used by the first two tasks to pass the incrementing number. + Pass a pointer to the queue in the parameter structure. */ + pxQueueParameters1->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + + /* The consumer is created first so gets a block time as described above. */ + pxQueueParameters1->xBlockTime = xBlockTime; + + /* Pass in the variable that this task is going to increment so we can check it + is still running. */ + pxQueueParameters1->psCheckVariable = &( sBlockingConsumerCount[ 0 ] ); + + /* Create the structure used to pass parameters to the producer task. */ + pxQueueParameters2 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + + /* Pass the queue to this task also, using the parameter structure. */ + pxQueueParameters2->xQueue = pxQueueParameters1->xQueue; + + /* The producer is not going to block - as soon as it posts the consumer will + wake and remove the item so the producer should always have room to post. */ + pxQueueParameters2->xBlockTime = xDontBlock; + + /* Pass in the variable that this task is going to increment so we can check + it is still running. */ + pxQueueParameters2->psCheckVariable = &( sBlockingProducerCount[ 0 ] ); + + + /* Note the producer has a lower priority than the consumer when the tasks are + spawned. */ + xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB1", blckqSTACK_SIZE, ( void * ) pxQueueParameters1, uxPriority, NULL ); + xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB2", blckqSTACK_SIZE, ( void * ) pxQueueParameters2, tskIDLE_PRIORITY, NULL ); + + + + /* Create the second two tasks as described at the top of the file. This uses + the same mechanism but reverses the task priorities. */ + + pxQueueParameters3 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters3->xQueue = xQueueCreate( uxQueueSize1, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + pxQueueParameters3->xBlockTime = xDontBlock; + pxQueueParameters3->psCheckVariable = &( sBlockingProducerCount[ 1 ] ); + + pxQueueParameters4 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters4->xQueue = pxQueueParameters3->xQueue; + pxQueueParameters4->xBlockTime = xBlockTime; + pxQueueParameters4->psCheckVariable = &( sBlockingConsumerCount[ 1 ] ); + + xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QProdB3", blckqSTACK_SIZE, ( void * ) pxQueueParameters3, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QConsB4", blckqSTACK_SIZE, ( void * ) pxQueueParameters4, uxPriority, NULL ); + + + + /* Create the last two tasks as described above. The mechanism is again just + the same. This time both parameter structures are given a block time. */ + pxQueueParameters5 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters5->xQueue = xQueueCreate( uxQueueSize5, ( unsigned portBASE_TYPE ) sizeof( unsigned portSHORT ) ); + pxQueueParameters5->xBlockTime = xBlockTime; + pxQueueParameters5->psCheckVariable = &( sBlockingProducerCount[ 2 ] ); + + pxQueueParameters6 = ( xBlockingQueueParameters * ) pvPortMalloc( sizeof( xBlockingQueueParameters ) ); + pxQueueParameters6->xQueue = pxQueueParameters5->xQueue; + pxQueueParameters6->xBlockTime = xBlockTime; + pxQueueParameters6->psCheckVariable = &( sBlockingConsumerCount[ 2 ] ); + + xTaskCreate( vBlockingQueueProducer, ( signed portCHAR * ) "QProdB5", blckqSTACK_SIZE, ( void * ) pxQueueParameters5, tskIDLE_PRIORITY, NULL ); + xTaskCreate( vBlockingQueueConsumer, ( signed portCHAR * ) "QConsB6", blckqSTACK_SIZE, ( void * ) pxQueueParameters6, tskIDLE_PRIORITY, NULL ); +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueProducer, pvParameters ) +{ +unsigned portSHORT usValue = 0; +xBlockingQueueParameters *pxQueueParameters; +portSHORT sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt blocking queue producer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltSendToBack( pxQueueParameters->xQueue, ( void * ) &usValue, pxQueueParameters->xBlockTime ) != pdPASS ) + { + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully posted a message, so increment the variable + used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the variable we are going to post next time round. The + consumer will expect the numbers to follow in numerical order. */ + ++usValue; + } + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vBlockingQueueConsumer, pvParameters ) +{ +unsigned portSHORT usData, usExpectedValue = 0; +xBlockingQueueParameters *pxQueueParameters; +portSHORT sErrorEverOccurred = pdFALSE; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Alt blocking queue consumer task started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + pxQueueParameters = ( xBlockingQueueParameters * ) pvParameters; + + for( ;; ) + { + if( xQueueAltReceive( pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime ) == pdPASS ) + { + if( usData != usExpectedValue ) + { + /* Catch-up. */ + usExpectedValue = usData; + + sErrorEverOccurred = pdTRUE; + } + else + { + /* We have successfully received a message, so increment the + variable used to check we are still running. */ + if( sErrorEverOccurred == pdFALSE ) + { + ( *pxQueueParameters->psCheckVariable )++; + } + + /* Increment the value we expect to remove from the queue next time + round. */ + ++usExpectedValue; + } + } + } +} +/*-----------------------------------------------------------*/ + +/* This is called to check that all the created tasks are still running. */ +portBASE_TYPE xAreAltBlockingQueuesStillRunning( void ) +{ +static portSHORT sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; +static portSHORT sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = { ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0, ( unsigned portSHORT ) 0 }; +portBASE_TYPE xReturn = pdPASS, xTasks; + + /* Not too worried about mutual exclusion on these variables as they are 16 + bits and we are only reading them. We also only care to see if they have + changed or not. + + Loop through each check variable to and return pdFALSE if any are found not + to have changed since the last call. */ + + for( xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++ ) + { + if( sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ]; + + + if( sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ] ) + { + xReturn = pdFALSE; + } + sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ]; + } + + return xReturn; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/countsem.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/countsem.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/countsem.c (revision 14) @@ -0,0 +1,304 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + + +/* + * Simple demonstration of the usage of counting semaphore. + */ + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* Demo program include files. */ +#include "countsem.h" + +/* The maximum count value that the semaphore used for the demo can hold. */ +#define countMAX_COUNT_VALUE ( 200 ) + +/* Constants used to indicate whether or not the semaphore should have been +created with its maximum count value, or its minimum count value. These +numbers are used to ensure that the pointers passed in as the task parameters +are valid. */ +#define countSTART_AT_MAX_COUNT ( 0xaa ) +#define countSTART_AT_ZERO ( 0x55 ) + +/* Two tasks are created for the test. One uses a semaphore created with its +count value set to the maximum, and one with the count value set to zero. */ +#define countNUM_TEST_TASKS ( 2 ) +#define countDONT_BLOCK ( 0 ) + +/*-----------------------------------------------------------*/ + +/* Flag that will be latched to pdTRUE should any unexpected behaviour be +detected in any of the tasks. */ +static volatile portBASE_TYPE xErrorDetected = pdFALSE; + +/*-----------------------------------------------------------*/ + +/* + * The demo task. This simply counts the semaphore up to its maximum value, + * the counts it back down again. The result of each semaphore 'give' and + * 'take' is inspected, with an error being flagged if it is found not to be + * the expected result. + */ +static void prvCountingSemaphoreTask( void *pvParameters ); + +/* + * Utility function to increment the semaphore count value up from zero to + * countMAX_COUNT_VALUE. + */ +static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ); + +/* + * Utility function to decrement the semaphore count value up from + * countMAX_COUNT_VALUE to zero. + */ +static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ); + +/*-----------------------------------------------------------*/ + +/* The structure that is passed into the task as the task parameter. */ +typedef struct COUNT_SEM_STRUCT +{ + /* The semaphore to be used for the demo. */ + xSemaphoreHandle xSemaphore; + + /* Set to countSTART_AT_MAX_COUNT if the semaphore should be created with + its count value set to its max count value, or countSTART_AT_ZERO if it + should have been created with its count value set to 0. */ + unsigned portBASE_TYPE uxExpectedStartCount; + + /* Incremented on each cycle of the demo task. Used to detect a stalled + task. */ + unsigned portBASE_TYPE uxLoopCounter; +} xCountSemStruct; + +/* Two structures are defined, one is passed to each test task. */ +static volatile xCountSemStruct xParameters[ countNUM_TEST_TASKS ]; + +/*-----------------------------------------------------------*/ + +void vStartCountingSemaphoreTasks( void ) +{ + /* Create the semaphores that we are going to use for the test/demo. The + first should be created such that it starts at its maximum count value, + the second should be created such that it starts with a count value of zero. */ + xParameters[ 0 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, countMAX_COUNT_VALUE ); + xParameters[ 0 ].uxExpectedStartCount = countSTART_AT_MAX_COUNT; + xParameters[ 0 ].uxLoopCounter = 0; + + xParameters[ 1 ].xSemaphore = xSemaphoreCreateCounting( countMAX_COUNT_VALUE, 0 ); + xParameters[ 1 ].uxExpectedStartCount = 0; + xParameters[ 1 ].uxLoopCounter = 0; + + /* vQueueAddToRegistry() adds the semaphore to the registry, if one is + in use. The registry is provided as a means for kernel aware + debuggers to locate semaphores and has no purpose if a kernel aware debugger + is not being used. The call to vQueueAddToRegistry() will be removed + by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is + defined to be less than 1. */ + vQueueAddToRegistry( ( xQueueHandle ) xParameters[ 0 ].xSemaphore, ( signed portCHAR * ) "Counting_Sem_1" ); + vQueueAddToRegistry( ( xQueueHandle ) xParameters[ 1 ].xSemaphore, ( signed portCHAR * ) "Counting_Sem_2" ); + + + /* Were the semaphores created? */ + if( ( xParameters[ 0 ].xSemaphore != NULL ) || ( xParameters[ 1 ].xSemaphore != NULL ) ) + { + /* Create the demo tasks, passing in the semaphore to use as the parameter. */ + xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT1", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 0 ] ), tskIDLE_PRIORITY, NULL ); + xTaskCreate( prvCountingSemaphoreTask, ( signed portCHAR * ) "CNT2", configMINIMAL_STACK_SIZE, ( void * ) &( xParameters[ 1 ] ), tskIDLE_PRIORITY, NULL ); + } +} +/*-----------------------------------------------------------*/ + +static void prvDecrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ) +{ +unsigned portBASE_TYPE ux; + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'take' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvIncrementSemaphoreCount( xSemaphoreHandle xSemaphore, unsigned portBASE_TYPE *puxLoopCounter ) +{ +unsigned portBASE_TYPE ux; + + /* If the semaphore count is zero then we should not be able to 'take' + the semaphore. */ + if( xSemaphoreTake( xSemaphore, countDONT_BLOCK ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + /* We should be able to 'give' the semaphore countMAX_COUNT_VALUE times. */ + for( ux = 0; ux < countMAX_COUNT_VALUE; ux++ ) + { + if( xSemaphoreGive( xSemaphore ) != pdPASS ) + { + /* We expected to be able to take the semaphore. */ + xErrorDetected = pdTRUE; + } + + ( *puxLoopCounter )++; + } + + #if configUSE_PREEMPTION == 0 + taskYIELD(); + #endif + + /* If the semaphore count is at its maximum then we should not be able to + 'give' the semaphore. */ + if( xSemaphoreGive( xSemaphore ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +static void prvCountingSemaphoreTask( void *pvParameters ) +{ +xCountSemStruct *pxParameter; + + #ifdef USE_STDIO + void vPrintDisplayMessage( const portCHAR * const * ppcMessageToSend ); + + const portCHAR * const pcTaskStartMsg = "Counting semaphore demo started.\r\n"; + + /* Queue a message for printing to say the task has started. */ + vPrintDisplayMessage( &pcTaskStartMsg ); + #endif + + /* The semaphore to be used was passed as the parameter. */ + pxParameter = ( xCountSemStruct * ) pvParameters; + + /* Did we expect to find the semaphore already at its max count value, or + at zero? */ + if( pxParameter->uxExpectedStartCount == countSTART_AT_MAX_COUNT ) + { + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } + + /* Now we expect the semaphore count to be 0, so this time there is an + error if we can take the semaphore. */ + if( xSemaphoreTake( pxParameter->xSemaphore, 0 ) == pdPASS ) + { + xErrorDetected = pdTRUE; + } + + for( ;; ) + { + prvIncrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + prvDecrementSemaphoreCount( pxParameter->xSemaphore, &( pxParameter->uxLoopCounter ) ); + } +} +/*-----------------------------------------------------------*/ + +portBASE_TYPE xAreCountingSemaphoreTasksStillRunning( void ) +{ +static unsigned portBASE_TYPE uxLastCount0 = 0, uxLastCount1 = 0; +portBASE_TYPE xReturn = pdPASS; + + /* Return fail if any 'give' or 'take' did not result in the expected + behaviour. */ + if( xErrorDetected != pdFALSE ) + { + xReturn = pdFAIL; + } + + /* Return fail if either task is not still incrementing its loop counter. */ + if( uxLastCount0 == xParameters[ 0 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount0 = xParameters[ 0 ].uxLoopCounter; + } + + if( uxLastCount1 == xParameters[ 1 ].uxLoopCounter ) + { + xReturn = pdFAIL; + } + else + { + uxLastCount1 = xParameters[ 1 ].uxLoopCounter; + } + + return xReturn; +} + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flash.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flash.c (revision 17) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/Minimal/flash.c (revision 17) @@ -0,0 +1,139 @@ +/* + FreeRTOS V5.4.1 - Copyright (C) 2009 Real Time Engineers Ltd. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation and modified by the FreeRTOS exception. + **NOTE** The exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + Alternative commercial license and support terms are also available upon + request. See the licensing section of http://www.FreeRTOS.org for full + license details. + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + + *************************************************************************** + * * + * Looking for a quick start? Then check out the FreeRTOS eBook! * + * See http://www.FreeRTOS.org/Documentation for details * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +/** + * This version of flash .c is for use on systems that have limited stack space + * and no display facilities. The complete version can be found in the + * Demo/Common/Full directory. + * + * Three tasks are created, each of which flash an LED at a different rate. The first + * LED flashes every 200ms, the second every 400ms, the third every 600ms. + * + * The LED flash tasks provide instant visual feedback. They show that the scheduler + * is still operational. + * + */ + + +#include + +/* Scheduler include files. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Demo program include files. */ +#include "partest.h" +#include "flash.h" + +#define ledSTACK_SIZE configMINIMAL_STACK_SIZE +#define ledNUMBER_OF_LEDS ( 1 ) +#define ledFLASH_RATE_BASE ( ( portTickType ) 333 ) + +/* Variable used by the created tasks to calculate the LED number to use, and +the rate at which they should flash the LED. */ +static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0; + +/* The task that is created three times. */ +static portTASK_FUNCTION_PROTO( vLEDFlashTask, pvParameters ); + +/*-----------------------------------------------------------*/ + +void vStartLEDFlashTasks( unsigned portBASE_TYPE uxPriority ) +{ +signed portBASE_TYPE xLEDTask; + + /* Create the three tasks. */ + for( xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask ) + { + /* Spawn the task. */ + xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); + } +} +/*-----------------------------------------------------------*/ + +static portTASK_FUNCTION( vLEDFlashTask, pvParameters ) +{ +portTickType xFlashRate, xLastFlashTime; +unsigned portBASE_TYPE uxLED; + + /* The parameters are not used. */ + ( void ) pvParameters; + + /* Calculate the LED and flash rate. */ + portENTER_CRITICAL(); + { + /* See which of the eight LED's we should use. */ + uxLED = uxFlashTaskNumber; + + /* Update so the next task uses the next LED. */ + uxFlashTaskNumber++; + } + portEXIT_CRITICAL(); + + xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( portTickType ) uxLED ); + xFlashRate /= portTICK_RATE_MS; + + /* We will turn the LED on and off again in the delay period, so each + delay is only half the total period. */ + xFlashRate /= ( portTickType ) 2; + + /* We need to initialise xLastFlashTime prior to the first call to + vTaskDelayUntil(). */ + xLastFlashTime = xTaskGetTickCount(); + + for(;;) + { + /* Delay for half the flash period then turn the LED on. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + + /* Delay for half the flash period then turn the LED off. */ + vTaskDelayUntil( &xLastFlashTime, xFlashRate ); + vParTestToggleLED( uxLED ); + } +} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */ + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.h (revision 14) @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fs.h,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ +#ifndef __HTTPD_FS_H__ +#define __HTTPD_FS_H__ + +#define HTTPD_FS_STATISTICS 1 + +struct httpd_fs_file { + char *data; + int len; +}; + +/* file must be allocated by caller and will be filled in + by the function. */ +int httpd_fs_open(const char *name, struct httpd_fs_file *file); + +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 +u16_t httpd_fs_count(char *name); +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ + +void httpd_fs_init(void); + +#endif /* __HTTPD_FS_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/Makefile.webserver =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/Makefile.webserver (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/Makefile.webserver (revision 14) @@ -0,0 +1,1 @@ +APP_SOURCES += httpd.c http-strings.c httpd-fs.c httpd-cgi.c Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.c (revision 14) @@ -0,0 +1,102 @@ +const char http_http[8] = +/* "http://" */ +{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, }; +const char http_200[5] = +/* "200 " */ +{0x32, 0x30, 0x30, 0x20, }; +const char http_301[5] = +/* "301 " */ +{0x33, 0x30, 0x31, 0x20, }; +const char http_302[5] = +/* "302 " */ +{0x33, 0x30, 0x32, 0x20, }; +const char http_get[5] = +/* "GET " */ +{0x47, 0x45, 0x54, 0x20, }; +const char http_10[9] = +/* "HTTP/1.0" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, }; +const char http_11[9] = +/* "HTTP/1.1" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, }; +const char http_content_type[15] = +/* "content-type: " */ +{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, }; +const char http_texthtml[10] = +/* "text/html" */ +{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_location[11] = +/* "location: " */ +{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, }; +const char http_host[7] = +/* "host: " */ +{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, }; +const char http_crnl[3] = +/* "\r\n" */ +{0xd, 0xa, }; +const char http_index_html[12] = +/* "/index.html" */ +{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_404_html[10] = +/* "/404.html" */ +{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_referer[9] = +/* "Referer:" */ +{0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x3a, }; +const char http_header_200[84] = +/* "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_header_404[91] = +/* "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, 0x2f, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_content_type_plain[29] = +/* "Content-type: text/plain\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_html[28] = +/* "Content-type: text/html\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_css [27] = +/* "Content-type: text/css\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_text[28] = +/* "Content-type: text/text\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_png [28] = +/* "Content-type: image/png\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_gif [28] = +/* "Content-type: image/gif\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_jpg [29] = +/* "Content-type: image/jpeg\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_binary[43] = +/* "Content-type: application/octet-stream\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, }; +const char http_html[6] = +/* ".html" */ +{0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_shtml[7] = +/* ".shtml" */ +{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_htm[5] = +/* ".htm" */ +{0x2e, 0x68, 0x74, 0x6d, }; +const char http_css[5] = +/* ".css" */ +{0x2e, 0x63, 0x73, 0x73, }; +const char http_png[5] = +/* ".png" */ +{0x2e, 0x70, 0x6e, 0x67, }; +const char http_gif[5] = +/* ".gif" */ +{0x2e, 0x67, 0x69, 0x66, }; +const char http_jpg[5] = +/* ".jpg" */ +{0x2e, 0x6a, 0x70, 0x67, }; +const char http_text[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; +const char http_txt[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makestrings =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makestrings (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makestrings (revision 14) @@ -0,0 +1,40 @@ +#!/usr/bin/perl + + +sub stringify { + my $name = shift(@_); + open(OUTPUTC, "> $name.c"); + open(OUTPUTH, "> $name.h"); + + open(FILE, "$name"); + + while() { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + $datan = $data; + $datan =~ s/\\r/\r/g; + $datan =~ s/\\n/\n/g; + $datan =~ s/\\01/\01/g; + $datan =~ s/\\0/\0/g; + + printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1); + printf(OUTPUTC "/* \"$data\" */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($datan); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1); + + } + } + close(OUTPUTC); + close(OUTPUTH); +} +stringify("http-strings"); + +exit 0; + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/footer.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/footer.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/footer.html (revision 14) @@ -0,0 +1,2 @@ + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/stats.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/stats.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/stats.shtml (revision 14) @@ -0,0 +1,31 @@ +%!: /header.html +

Network statistics

+
+
LocalRemoteStateRetransmissionsTimerFlags
%d%u.%u.%u.%u:%u%s%u%u%c %c
+
+IP           Packets received
+             Packets sent
+	     Packets dropped
+IP errors    IP version/header length
+             IP length, high byte
+             IP length, low byte
+             IP fragments
+             Header checksum
+             Wrong protocol
+ICMP	     Packets received
+             Packets sent
+             Packets dropped
+             Type errors
+TCP          Packets received
+             Packets sent
+             Packets dropped
+             Checksum errors
+             Data packets without ACKs
+             Resets
+             Retransmissions
+	     No connection avaliable
+	     Connection attempts to closed ports
+
%! net-stats
+
+ +%!: /footer.html Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/style.css =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/style.css (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/style.css (revision 14) @@ -0,0 +1,92 @@ +h1 +{ + text-align: center; + font-size:14pt; + font-family:arial,helvetica; + font-weight:bold; + padding:10px; +} + +body +{ + + background-color: #fffeec; + color:black; + + font-size:8pt; + font-family:arial,helvetica; +} + +.menu +{ + margin: 4px; + width:60%; + + padding:2px; + + border: solid 1px; + background-color: #fffcd2; + text-align:left; + + font-size:9pt; + font-family:arial,helvetica; +} + +div.menubox +{ + width: 25%; + border: 0; + float: left; +text-align: center; +} + +.contentblock +{ + margin: 4px; + width:60%; + + padding:2px; + + border: 1px dotted; + background-color: white; + + font-size:8pt; + font-family:arial,helvetica; + +} + +p.intro +{ + margin-left:20px; + margin-right:20px; + + font-size:10pt; +/* font-weight:bold; */ + font-family:arial,helvetica; +} + +p.clink +{ + font-size:12pt; + font-family:courier,monospace; + text-align:center; +} + +p.clink9 +{ + font-size:9pt; + font-family:courier,monospace; + text-align:center; +} + + +p +{ + padding-left:10px; +} + +p.right +{ + text-align:right; +} + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/files.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/files.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/files.shtml (revision 14) @@ -0,0 +1,35 @@ +%!: /header.html +

File statistics

+
+ + + + + + + + + + + + + + + +
/index.html%! file-stats /index.html +
/files.shtml%! file-stats /files.shtml +
/tcp.shtml%! file-stats /tcp.shtml +
/stats.shtml%! file-stats /stats.shtml +
/style.css%! file-stats /style.css +
/404.html%! file-stats /404.html +
/fade.png%! file-stats /fade.png +
+
+%!: /footer.html Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/404.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/404.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/404.html (revision 14) @@ -0,0 +1,8 @@ + + +
+

404 - file not found

+

Go here instead.

+
+ + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/index.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/index.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/index.html (revision 14) @@ -0,0 +1,29 @@ + + + + Welcome to the uIP web server! + + + + + + +
+

+ These web pages are served by a small web server running on top of + the uIP embedded TCP/IP + stack. +

+

+ Click on the links above for web server statistics. +

+ + + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/header.html =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/header.html (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/header.html (revision 14) @@ -0,0 +1,18 @@ + + + + Welcome to the uIP web server! + + + + + + +
Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/processes.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/processes.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/processes.shtml (revision 14) @@ -0,0 +1,5 @@ +%!: /header.html +

System processes


+ +%! processes +%!: /footer.html Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/tcp.shtml =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/tcp.shtml (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs/tcp.shtml (revision 14) @@ -0,0 +1,5 @@ +%!: /header.html +

Current connections


IDNamePriorityPoll handlerEvent handlerProcstate
+ +%! tcp-connections +%!: /footer.html Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/webserver.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/webserver.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/webserver.h (revision 14) @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2002, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: webserver.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ +#ifndef __WEBSERVER_H__ +#define __WEBSERVER_H__ + +#include "httpd.h" + +typedef struct httpd_state uip_tcp_appstate_t; +/* UIP_APPCALL: the name of the application function. This function + must return void and take no arguments (i.e., C type "void + appfunc(void)"). */ +#ifndef UIP_APPCALL +#define UIP_APPCALL httpd_appcall +#endif + + +#endif /* __WEBSERVER_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings.h (revision 14) @@ -0,0 +1,34 @@ +extern const char http_http[8]; +extern const char http_200[5]; +extern const char http_301[5]; +extern const char http_302[5]; +extern const char http_get[5]; +extern const char http_10[9]; +extern const char http_11[9]; +extern const char http_content_type[15]; +extern const char http_texthtml[10]; +extern const char http_location[11]; +extern const char http_host[7]; +extern const char http_crnl[3]; +extern const char http_index_html[12]; +extern const char http_404_html[10]; +extern const char http_referer[9]; +extern const char http_header_200[84]; +extern const char http_header_404[91]; +extern const char http_content_type_plain[29]; +extern const char http_content_type_html[28]; +extern const char http_content_type_css [27]; +extern const char http_content_type_text[28]; +extern const char http_content_type_png [28]; +extern const char http_content_type_gif [28]; +extern const char http_content_type_jpg [29]; +extern const char http_content_type_binary[43]; +extern const char http_html[6]; +extern const char http_shtml[7]; +extern const char http_htm[5]; +extern const char http_css[5]; +extern const char http_png[5]; +extern const char http_gif[5]; +extern const char http_jpg[5]; +extern const char http_text[5]; +extern const char http_txt[5]; Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makefsdata =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makefsdata (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/makefsdata (revision 14) @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +open(OUTPUT, "> httpd-fsdata.c"); + +chdir("httpd-fs"); + +opendir(DIR, "."); +@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); +closedir(DIR); + +foreach $file (@files) { + + if(-d $file && $file !~ /^\./) { + print "Processing directory $file\n"; + opendir(DIR, $file); + @newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); + closedir(DIR); + printf "Adding files @newfiles\n"; + @files = (@files, map { $_ = "$file/$_" } @newfiles); + next; + } +} + +foreach $file (@files) { + if(-f $file) { + + print "Adding file $file\n"; + + open(FILE, $file) || die "Could not open file $file\n"; + + $file =~ s-^-/-; + $fvar = $file; + $fvar =~ s-/-_-g; + $fvar =~ s-\.-_-g; + # for AVR, add PROGMEM here + print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); + print(OUTPUT "\t/* $file */\n\t"); + for($j = 0; $j < length($file); $j++) { + printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); + } + printf(OUTPUT "0,\n"); + + + $i = 0; + while(read(FILE, $data, 1)) { + if($i == 0) { + print(OUTPUT "\t"); + } + printf(OUTPUT "%#02x, ", unpack("C", $data)); + $i++; + if($i == 10) { + print(OUTPUT "\n"); + $i = 0; + } + } + print(OUTPUT "0};\n\n"); + close(FILE); + push(@fvars, $fvar); + push(@pfiles, $file); + } +} + +for($i = 0; $i < @fvars; $i++) { + $file = $pfiles[$i]; + $fvar = $fvars[$i]; + + if($i == 0) { + $prevfile = "NULL"; + } else { + $prevfile = "file" . $fvars[$i - 1]; + } + print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); + print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); + print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); +} + +print(OUTPUT "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n"); +print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n"); Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.c (revision 14) @@ -0,0 +1,203 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * Web server script interface + * \author + * Adam Dunkels + * + */ + +/* + * Copyright (c) 2001-2006, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd-cgi.c,v 1.2 2006/06/11 21:46:37 adam Exp $ + * + */ + +#include "uip.h" +#include "psock.h" +#include "httpd.h" +#include "httpd-cgi.h" +#include "httpd-fs.h" + +#include +#include + +HTTPD_CGI_CALL(file, "file-stats", file_stats); +HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats); +HTTPD_CGI_CALL(net, "net-stats", net_stats); + +static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, NULL }; + +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(nullfunction(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +httpd_cgifunction +httpd_cgi(char *name) +{ + const struct httpd_cgi_call **f; + + /* Find the matching name in the table, return the function. */ + for(f = calls; *f != NULL; ++f) { + if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) { + return (*f)->function; + } + } + return nullfunction; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_file_stats(void *arg) +{ + char *f = (char *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f)); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(file_stats(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + + PSOCK_GENERATOR_SEND(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static const char closed[] = /* "CLOSED",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0}; +static const char syn_rcvd[] = /* "SYN-RCVD",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, + 0x44, 0}; +static const char syn_sent[] = /* "SYN-SENT",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, + 0x54, 0}; +static const char established[] = /* "ESTABLISHED",*/ +{0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, + 0x45, 0x44, 0}; +static const char fin_wait_1[] = /* "FIN-WAIT-1",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x31, 0}; +static const char fin_wait_2[] = /* "FIN-WAIT-2",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x32, 0}; +static const char closing[] = /* "CLOSING",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x49, + 0x4e, 0x47, 0}; +static const char time_wait[] = /* "TIME-WAIT,"*/ +{0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, + 0x49, 0x54, 0}; +static const char last_ack[] = /* "LAST-ACK"*/ +{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, + 0x4b, 0}; + +static const char *states[] = { + closed, + syn_rcvd, + syn_sent, + established, + fin_wait_1, + fin_wait_2, + closing, + time_wait, + last_ack}; + + +static unsigned short +generate_tcp_stats(void *arg) +{ + struct uip_conn *conn; + struct httpd_state *s = (struct httpd_state *)arg; + + conn = &uip_conns[s->count]; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "\r\n", + htons(conn->lport), + htons(conn->ripaddr[0]) >> 8, + htons(conn->ripaddr[0]) & 0xff, + htons(conn->ripaddr[1]) >> 8, + htons(conn->ripaddr[1]) & 0xff, + htons(conn->rport), + states[conn->tcpstateflags & UIP_TS_MASK], + conn->nrtx, + conn->timer, + (uip_outstanding(conn))? '*':' ', + (uip_stopped(conn))? '!':' '); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(tcp_stats(struct httpd_state *s, char *ptr)) +{ + + PSOCK_BEGIN(&s->sout); + + for(s->count = 0; s->count < UIP_CONNS; ++s->count) { + if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { + PSOCK_GENERATOR_SEND(&s->sout, generate_tcp_stats, s); + } + } + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_net_stats(void *arg) +{ + struct httpd_state *s = (struct httpd_state *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]); +} + +static +PT_THREAD(net_stats(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + +#if UIP_STATISTICS + + for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); + ++s->count) { + PSOCK_GENERATOR_SEND(&s->sout, generate_net_stats, s); + } + +#endif /* UIP_STATISTICS */ + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.c (revision 14) @@ -0,0 +1,607 @@ +static const unsigned char data_processes_shtml[] = { + /* /processes.shtml */ + 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3c, 0x2f, 0x68, + 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, + 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x49, 0x44, 0x3c, 0x2f, 0x74, + 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4e, 0x61, 0x6d, 0x65, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3c, 0x2f, 0x74, + 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, 0x6f, 0x6c, 0x6c, + 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, + 0x72, 0x6f, 0x63, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, + 0x21, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, 0x6f, 0x6f, + 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0}; + +static const unsigned char data_404_html[] = { + /* /404.html */ + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e, + 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33, + 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, + 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, +0}; + +static const unsigned char data_files_shtml[] = { + /* /files.shtml */ + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, 0x30, 0x22, 0x3e, + 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, + 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, + 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, + 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, + 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, + 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, + 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, + 0x73, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, + 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, + 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, + 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, + 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, + 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, + 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, + 0x20, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, + 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, + 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, + 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, + 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, + 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, + 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, + 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, + 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, + 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, + 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x2f, 0x73, + 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x3c, 0x2f, + 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, + 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3c, 0x2f, 0x74, + 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, + 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, + 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3e, 0x20, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x34, + 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, + 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, + 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, + 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, + 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, + 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x3e, 0x2f, 0x66, 0x61, + 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, + 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, + 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, + 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, + 0x6d, 0x6c, 0xa, 0}; + +static const unsigned char data_footer_html[] = { + /* /footer.html */ + 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0}; + +static const unsigned char data_header_html[] = { + /* /header.html */ + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77, + 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21, + 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, + 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, + 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, + 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20, + 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, + 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, + 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22, + 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, + 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, + 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, + 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, + 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, + 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, + 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, + 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, + 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, + 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0xa, 0x20, + 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x3d, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0}; + +static const unsigned char data_index_html[] = { + /* /index.html */ + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77, + 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21, + 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, + 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, + 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, + 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20, + 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, + 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, + 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22, + 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, + 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, + 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, + 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, + 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, + 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, + 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, + 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, + 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, + 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, + 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, + 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x70, + 0x3e, 0xa, 0x20, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, + 0x77, 0x65, 0x62, 0x20, 0x70, 0x61, 0x67, 0x65, 0x73, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, + 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c, + 0x6c, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66, + 0xa, 0x20, 0x20, 0x74, 0x68, 0x65, 0x20, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x69, 0x63, + 0x73, 0x2e, 0x73, 0x65, 0x2f, 0x7e, 0x61, 0x64, 0x61, 0x6d, + 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x3e, 0x75, 0x49, 0x50, + 0x20, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, + 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0xa, 0x20, 0x20, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa, + 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x70, 0x3e, 0xa, 0x20, 0x20, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, + 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, + 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, + 0x6c, 0x3e, 0xa, 0}; + +static const unsigned char data_style_css[] = { + /* /style.css */ + 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0, + 0x68, 0x31, 0x20, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, + 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, + 0x31, 0x34, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, + 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, + 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, + 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x70, + 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x31, 0x30, 0x70, + 0x78, 0x3b, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x62, 0x6f, 0x64, + 0x79, 0xa, 0x7b, 0xa, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, + 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x65, + 0x65, 0x63, 0x3b, 0xa, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0xa, 0xa, + 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, + 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, + 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x7d, 0xa, + 0xa, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0xa, 0x7b, 0xa, 0x20, + 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, + 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3a, 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, + 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, + 0x78, 0x3b, 0xa, 0x9, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x3a, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, + 0x20, 0x31, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, + 0x63, 0x64, 0x32, 0x3b, 0xa, 0x20, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x6c, 0x65, + 0x66, 0x74, 0x3b, 0xa, 0x20, 0x20, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, + 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, + 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, + 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, + 0x69, 0x63, 0x61, 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, + 0x64, 0x69, 0x76, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3a, 0x20, 0x32, 0x35, 0x25, 0x3b, 0xa, 0x20, 0x20, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, + 0xa, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, + 0x6c, 0x65, 0x66, 0x74, 0x3b, 0xa, 0x74, 0x65, 0x78, 0x74, + 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, 0xa, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0xa, 0x7b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x6d, + 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, 0x70, 0x78, + 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, + 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, 0x70, 0x61, + 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, 0x78, 0x3b, + 0xa, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f, 0x74, 0x74, + 0x65, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3b, + 0xa, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, + 0x69, 0x7a, 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, + 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, + 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0x20, + 0x20, 0xa, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x69, 0x6e, + 0x74, 0x72, 0x6f, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x6d, 0x61, + 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, + 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x6d, 0x61, + 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x3a, 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0xa, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, + 0x31, 0x30, 0x70, 0x74, 0x3b, 0xa, 0x2f, 0x2a, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x20, 0x2a, 0x2f, + 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, + 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, + 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, + 0x6c, 0x69, 0x6e, 0x6b, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x31, + 0x32, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, + 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, + 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, + 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, + 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x3a, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, + 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x6e, + 0x6b, 0x39, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, + 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, 0x70, 0x74, + 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, 0x6f, 0x75, 0x72, + 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, + 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, + 0xa, 0xa, 0x70, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x70, 0x61, + 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74, + 0x3a, 0x31, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x7d, 0xa, 0xa, + 0x70, 0x2e, 0x72, 0x69, 0x67, 0x68, 0x74, 0xa, 0x7b, 0xa, + 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, + 0xa, 0x7d, 0xa, 0xa, 0}; + +static const unsigned char data_tcp_shtml[] = { + /* /tcp.shtml */ + 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, + 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, + 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, + 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46, + 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, + 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x74, 0x63, + 0x70, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, + 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, +0}; + +static const unsigned char data_fade_png[] = { + /* /fade.png */ + 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0, + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00, + 00, 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 00, 0x4, + 00, 00, 00, 0xa, 0x8, 0x2, 00, 00, 00, 0x1c, + 0x99, 0x68, 0x59, 00, 00, 00, 0x9, 0x70, 0x48, 0x59, + 0x73, 00, 00, 0xb, 0x13, 00, 00, 0xb, 0x13, 0x1, + 00, 0x9a, 0x9c, 0x18, 00, 00, 00, 0x7, 0x74, 0x49, + 0x4d, 0x45, 0x7, 0xd6, 0x6, 0x8, 0x14, 0x1b, 0x39, 0xaf, + 0x5b, 0xc0, 0xe3, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 00, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, + 0xef, 0x64, 0x25, 0x6e, 00, 00, 00, 0x3a, 0x49, 0x44, + 0x41, 0x54, 0x8, 0xd7, 0x75, 0x8c, 0x31, 0x12, 00, 0x10, + 0x10, 0xc4, 0x2e, 0x37, 0x9e, 0x40, 0x65, 0xfd, 0xff, 0x83, + 0xf4, 0xa, 0x1c, 0x8d, 0x54, 0x9b, 0xc9, 0xcc, 0x9a, 0x3d, + 0x90, 0x73, 0x71, 0x67, 0x91, 0xd4, 0x74, 0x36, 0xa9, 0x55, + 0x1, 0xf8, 0x29, 0x58, 0xc8, 0xbf, 0x48, 0xc4, 0x81, 0x74, + 0xb, 0xa3, 0xf, 0x7c, 0xdb, 0x4, 0xe8, 0x40, 0x5, 0xdf, + 0xa1, 0xf3, 0xfc, 0x73, 00, 00, 00, 00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0}; + +static const unsigned char data_stats_shtml[] = { + /* /stats.shtml */ + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, + 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, + 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, + 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49, + 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, + 0x73, 0x65, 0x6e, 0x74, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x49, 0x50, 0x20, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x20, 0x20, 0x20, + 0x49, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, + 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x68, + 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x20, 0x62, 0x79, 0x74, + 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x66, 0x72, + 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0xa, 0x49, 0x43, 0x4d, 0x50, 0x9, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x54, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0xa, 0x54, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, + 0x61, 0x74, 0x61, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, + 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x20, + 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, + 0x70, 0x6f, 0x72, 0x74, 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72, + 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, + 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x25, 0x21, 0x20, 0x6e, + 0x65, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x3c, + 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, + 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, + 0xa, 0}; + +const struct httpd_fsdata_file file_processes_shtml[] = {{NULL, data_processes_shtml, data_processes_shtml + 17, sizeof(data_processes_shtml) - 17}}; + +const struct httpd_fsdata_file file_404_html[] = {{file_processes_shtml, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; + +const struct httpd_fsdata_file file_files_shtml[] = {{file_404_html, data_files_shtml, data_files_shtml + 13, sizeof(data_files_shtml) - 13}}; + +const struct httpd_fsdata_file file_footer_html[] = {{file_files_shtml, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}}; + +const struct httpd_fsdata_file file_header_html[] = {{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}}; + +const struct httpd_fsdata_file file_index_html[] = {{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; + +const struct httpd_fsdata_file file_style_css[] = {{file_index_html, data_style_css, data_style_css + 11, sizeof(data_style_css) - 11}}; + +const struct httpd_fsdata_file file_tcp_shtml[] = {{file_style_css, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}}; + +const struct httpd_fsdata_file file_fade_png[] = {{file_tcp_shtml, data_fade_png, data_fade_png + 10, sizeof(data_fade_png) - 10}}; + +const struct httpd_fsdata_file file_stats_shtml[] = {{file_fade_png, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}}; + +#define HTTPD_FS_ROOT file_stats_shtml + +#define HTTPD_FS_NUMFILES 10 Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.c (revision 14) @@ -0,0 +1,338 @@ +/** + * \addtogroup apps + * @{ + */ + +/** + * \defgroup httpd Web server + * @{ + * The uIP web server is a very simplistic implementation of an HTTP + * server. It can serve web pages and files from a read-only ROM + * filesystem, and provides a very small scripting language. + + */ + +/** + * \file + * Web server + * \author + * Adam Dunkels + */ + + +/* + * Copyright (c) 2004, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $ + */ + +#include "uip.h" +#include "httpd.h" +#include "httpd-fs.h" +#include "httpd-cgi.h" +#include "http-strings.h" + +#include + +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 + +#define ISO_nl 0x0a +#define ISO_space 0x20 +#define ISO_bang 0x21 +#define ISO_percent 0x25 +#define ISO_period 0x2e +#define ISO_slash 0x2f +#define ISO_colon 0x3a + + +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_part_of_file(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if(s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + memcpy(uip_appdata, s->file.data, s->len); + + return s->len; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_file(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sout); + + do { + PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s); + s->file.len -= s->len; + s->file.data += s->len; + } while(s->file.len > 0); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_part_of_file(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sout); + + PSOCK_SEND(&s->sout, s->file.data, s->len); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static void +next_scriptstate(struct httpd_state *s) +{ + char *p; + p = strchr(s->scriptptr, ISO_nl) + 1; + s->scriptlen -= (unsigned short)(p - s->scriptptr); + s->scriptptr = p; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_script(struct httpd_state *s)) +{ + char *ptr; + + PT_BEGIN(&s->scriptpt); + + + while(s->file.len > 0) { + + /* Check if we should start executing a script. */ + if(*s->file.data == ISO_percent && + *(s->file.data + 1) == ISO_bang) { + s->scriptptr = s->file.data + 3; + s->scriptlen = s->file.len - 3; + if(*(s->scriptptr - 1) == ISO_colon) { + httpd_fs_open(s->scriptptr + 1, &s->file); + PT_WAIT_THREAD(&s->scriptpt, send_file(s)); + } else { + PT_WAIT_THREAD(&s->scriptpt, + httpd_cgi(s->scriptptr)(s, s->scriptptr)); + } + next_scriptstate(s); + + /* The script is over, so we reset the pointers and continue + sending the rest of the file. */ + s->file.data = s->scriptptr; + s->file.len = s->scriptlen; + } else { + /* See if we find the start of script marker in the block of HTML + to be sent. */ + + if(s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + + if(*s->file.data == ISO_percent) { + ptr = strchr(s->file.data + 1, ISO_percent); + } else { + ptr = strchr(s->file.data, ISO_percent); + } + if(ptr != NULL && + ptr != s->file.data) { + s->len = (int)(ptr - s->file.data); + if(s->len >= uip_mss()) { + s->len = uip_mss(); + } + } + PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s)); + s->file.data += s->len; + s->file.len -= s->len; + + } + } + + PT_END(&s->scriptpt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) +{ + char *ptr; + + PSOCK_BEGIN(&s->sout); + + PSOCK_SEND_STR(&s->sout, statushdr); + + ptr = strrchr(s->filename, ISO_period); + if(ptr == NULL) { + PSOCK_SEND_STR(&s->sout, http_content_type_binary); + } else if(strncmp(http_html, ptr, 5) == 0 || + strncmp(http_shtml, ptr, 6) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_html); + } else if(strncmp(http_css, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_css); + } else if(strncmp(http_png, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_png); + } else if(strncmp(http_gif, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_gif); + } else if(strncmp(http_jpg, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_jpg); + } else { + PSOCK_SEND_STR(&s->sout, http_content_type_plain); + } + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_output(struct httpd_state *s)) +{ + char *ptr; + + PT_BEGIN(&s->outputpt); + + if(!httpd_fs_open(s->filename, &s->file)) { + httpd_fs_open(http_404_html, &s->file); + strcpy(s->filename, http_404_html); + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, + http_header_404)); + PT_WAIT_THREAD(&s->outputpt, + send_file(s)); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, + http_header_200)); + ptr = strchr(s->filename, ISO_period); + if(ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) { + PT_INIT(&s->scriptpt); + PT_WAIT_THREAD(&s->outputpt, handle_script(s)); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_file(s)); + } + } + PSOCK_CLOSE(&s->sout); + PT_END(&s->outputpt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(handle_input(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sin); + + PSOCK_READTO(&s->sin, ISO_space); + + + if(strncmp(s->inputbuf, http_get, 4) != 0) { + PSOCK_CLOSE_EXIT(&s->sin); + } + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + + if(s->inputbuf[1] == ISO_space) { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } else { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename)); + } + + /* httpd_log_file(uip_conn->ripaddr, s->filename);*/ + + s->state = STATE_OUTPUT; + + while(1) { + PSOCK_READTO(&s->sin, ISO_nl); + + if(strncmp(s->inputbuf, http_referer, 8) == 0) { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; + /* httpd_log(&s->inputbuf[9]);*/ + } + } + + PSOCK_END(&s->sin); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connection(struct httpd_state *s) +{ + handle_input(s); + if(s->state == STATE_OUTPUT) { + handle_output(s); + } +} +/*---------------------------------------------------------------------------*/ +void +httpd_appcall(void) +{ + struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate); + + if(uip_closed() || uip_aborted() || uip_timedout()) { + } else if(uip_connected()) { + PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1); + PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1); + PT_INIT(&s->outputpt); + s->state = STATE_WAITING; + /* timer_set(&s->timer, CLOCK_SECOND * 100);*/ + s->timer = 0; + handle_connection(s); + } else if(s != NULL) { + if(uip_poll()) { + ++s->timer; + if(s->timer >= 20) { + uip_abort(); + } + } else { + s->timer = 0; + } + handle_connection(s); + } else { + uip_abort(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the web server + * + * This function initializes the web server and should be + * called at system boot-up. + */ +void +httpd_init(void) +{ + uip_listen(HTONS(80)); +} +/*---------------------------------------------------------------------------*/ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/http-strings (revision 14) @@ -0,0 +1,35 @@ +http_http "http://" +http_200 "200 " +http_301 "301 " +http_302 "302 " +http_get "GET " +http_10 "HTTP/1.0" +http_11 "HTTP/1.1" +http_content_type "content-type: " +http_texthtml "text/html" +http_location "location: " +http_host "host: " +http_crnl "\r\n" +http_index_html "/index.html" +http_404_html "/404.html" +http_referer "Referer:" +http_header_200 "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_header_404 "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_content_type_plain "Content-type: text/plain\r\n\r\n" +http_content_type_html "Content-type: text/html\r\n\r\n" +http_content_type_css "Content-type: text/css\r\n\r\n" +http_content_type_text "Content-type: text/text\r\n\r\n" +http_content_type_png "Content-type: image/png\r\n\r\n" +http_content_type_gif "Content-type: image/gif\r\n\r\n" +http_content_type_jpg "Content-type: image/jpeg\r\n\r\n" +http_content_type_binary "Content-type: application/octet-stream\r\n\r\n" +http_html ".html" +http_shtml ".shtml" +http_htm ".htm" +http_css ".css" +http_png ".png" +http_gif ".gif" +http_jpg ".jpg" +http_text ".txt" +http_txt ".txt" + Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-cgi.h (revision 14) @@ -0,0 +1,84 @@ +/** + * \addtogroup httpd + * @{ + */ + +/** + * \file + * Web server script interface header file + * \author + * Adam Dunkels + * + */ + + + +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd-cgi.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ + +#ifndef __HTTPD_CGI_H__ +#define __HTTPD_CGI_H__ + +#include "psock.h" +#include "httpd.h" + +typedef PT_THREAD((* httpd_cgifunction)(struct httpd_state *, char *)); + +httpd_cgifunction httpd_cgi(char *name); + +struct httpd_cgi_call { + const char *name; + const httpd_cgifunction function; +}; + +/** + * \brief HTTPD CGI function declaration + * \param name The C variable name of the function + * \param str The string name of the function, used in the script file + * \param function A pointer to the function that implements it + * + * This macro is used for declaring a HTTPD CGI + * function. This function is then added to the list of + * HTTPD CGI functions with the httpd_cgi_add() function. + * + * \hideinitializer + */ +#define HTTPD_CGI_CALL(name, str, function) \ +static PT_THREAD(function(struct httpd_state *, char *)); \ +static const struct httpd_cgi_call name = {str, function} + +void httpd_cgi_init(void); +#endif /* __HTTPD_CGI_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fsdata.h (revision 14) @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fsdata.h,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ +#ifndef __HTTPD_FSDATA_H__ +#define __HTTPD_FSDATA_H__ + +#include "uip.h" + +struct httpd_fsdata_file { + const struct httpd_fsdata_file *next; + const char *name; + const char *data; + const int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + u16_t count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +struct httpd_fsdata_file_noconst { + struct httpd_fsdata_file *next; + char *name; + char *data; + int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + u16_t count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +#endif /* __HTTPD_FSDATA_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd.h (revision 14) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2005, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: httpd.h,v 1.2 2006/06/11 21:46:38 adam Exp $ + * + */ + +#ifndef __HTTPD_H__ +#define __HTTPD_H__ + +#include "psock.h" +#include "httpd-fs.h" + +struct httpd_state { + unsigned char timer; + struct psock sin, sout; + struct pt outputpt, scriptpt; + char inputbuf[50]; + char filename[20]; + char state; + struct httpd_fs_file file; + int len; + char *scriptptr; + int scriptlen; + + unsigned short count; +}; + +void httpd_init(void); +void httpd_appcall(void); + +void httpd_log(char *msg); +void httpd_log_file(u16_t *requester, char *file); + +#endif /* __HTTPD_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/webserver/httpd-fs.c (revision 14) @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fs.c,v 1.1 2006/06/07 09:13:08 adam Exp $ + */ + +#include "httpd.h" +#include "httpd-fs.h" +#include "httpd-fsdata.h" + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +#include "httpd-fsdata.c" + +#if HTTPD_FS_STATISTICS +static u16_t count[HTTPD_FS_NUMFILES]; +#endif /* HTTPD_FS_STATISTICS */ + +/*-----------------------------------------------------------------------------------*/ +static u8_t +httpd_fs_strcmp(const char *str1, const char *str2) +{ + u8_t i; + i = 0; + loop: + + if(str2[i] == 0 || + str1[i] == '\r' || + str1[i] == '\n') { + return 0; + } + + if(str1[i] != str2[i]) { + return 1; + } + + + ++i; + goto loop; +} +/*-----------------------------------------------------------------------------------*/ +int +httpd_fs_open(const char *name, struct httpd_fs_file *file) +{ +#if HTTPD_FS_STATISTICS + u16_t i = 0; +#endif /* HTTPD_FS_STATISTICS */ + struct httpd_fsdata_file_noconst *f; + + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + file->data = f->data; + file->len = f->len; +#if HTTPD_FS_STATISTICS + ++count[i]; +#endif /* HTTPD_FS_STATISTICS */ + return 1; + } +#if HTTPD_FS_STATISTICS + ++i; +#endif /* HTTPD_FS_STATISTICS */ + + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void +httpd_fs_init(void) +{ +#if HTTPD_FS_STATISTICS + u16_t i; + for(i = 0; i < HTTPD_FS_NUMFILES; i++) { + count[i] = 0; + } +#endif /* HTTPD_FS_STATISTICS */ +} +/*-----------------------------------------------------------------------------------*/ +#if HTTPD_FS_STATISTICS +u16_t httpd_fs_count +(char *name) +{ + struct httpd_fsdata_file_noconst *f; + u16_t i; + + i = 0; + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + return count[i]; + } + ++i; + } + return 0; +} +#endif /* HTTPD_FS_STATISTICS */ +/*-----------------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/README =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/README (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/apps/README (revision 14) @@ -0,0 +1,2 @@ +This directory contains a few example applications. They are not all +heavily tested, however. Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip-1.0-changelog.txt =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip-1.0-changelog.txt (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip-1.0-changelog.txt (revision 14) @@ -0,0 +1,98 @@ +* A new API: protosockets that are similar to BSD sockets but does not + require any underlying multithreading system. + +* Very rudimentary IPv6 support + +* New application: DHCP client. Web server rewritten with protosockets. + +* Removed uIP zero-copy functionality in order to simplify uIP device + driver coding: outbound packets are now *always* stored in full in + the uip_buf buffer. + +* Checksum computation is now part of uip.c, but it still is possible + to implement them in assembly code by specifying a configuration + option. Checksum code now runs on architectures with 2-byte alignment. + +* Added TCP persistent timer. + +* Made all IP address representations use the new uip_ipaddr_ip + datatype for clarity. + +* Updated window behavior so that sending to a host with a small open + window works better now. + +* UDP API change: uip_udp_new() now takes port numbers in network byte + order like TCP functions. + +* Allow reception of packets when no IP address is configured to make + DHCP work. + +* Moved Ethernet address into main uIP module from ARP module. + +* Made constants explicit #defines and moved them out of the code + (header sizes, TCP options, TCP header length field). + +* If uip_len is less than that reported by the IP header, the packet + is discarded. If uip_len is greater than the length reported by the + IP header, uip_len is adjusted. + +* Moved header size definitions into header file. + +* Added uIP call for polling an application without triggering any + timer events. Removed redundant assignments of uip_len and uip_slen. + +* Removed compiler warning about icmp_input label being defined when + UIP_PINGADDRCONF was not used. + +* Added UIP_APPDATA_SIZE macro that holds the available buffer size + for user data. + +* Added uip_udp_bind() call. + +* Moved checksum code into main uIP module. + +* Switched the TCP, UDP and IP header structures to be structs rather + than typedefs. + +* Prefixed TCP state names with UIP_ to avoid name space + contamination. + +* Changed declarations of uip_appdatap and friends to void * to avoid + explicit typecasts. + +* Bugfixes + + o TCP: Fixed bug with high byte of peer window size. + + o TCP: Fixed bug that in some cases prevented concurrent reception and + transmission of TCP data. + + o TCP: uip_connect() didn't correctly calculate age of TIME_WAIT + connections. + + o TCP: Array index for uip_conns[] array was out of bounds in + comparison. Comparison changed to make index within bounds. + + o TCP: if the remote host crashes and tries to reestablish an old + connection, uIP should respond with an ACK with the correct + sequence and acknowledgment numbers, to which the remote host + should respond with an ACK. uIP did not respond with the correct + ACK. + + o TCP: Fixed check for SYNACK segment: now checks only relevant TCP + control flags and discards flags reserved for future expansion. + + o TCP: Fixed bug where uIP did not inform application that a connection + had been aborted during an active open. + + o TCP: FIN segment was accepted even though application had stopped + incoming data with uip_stop(). + + o TCP: A FINACK segment would not always correctly acknowledge data. + + o UDP: checksums are now calculated after all fields have been + filled in. + + o UDP: network byte order on lastport in uip_udp_new(). + + o IP: memset() bugs in IP fragment reassembly code fixed. Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/README =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/README (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/README (revision 14) @@ -0,0 +1,13 @@ +uIP is a very small implementation of the TCP/IP stack that is written +by Adam Dunkels . More information can be obtained +at the uIP homepage at http://www.sics.se/~adam/uip/. + +This is version $Name: uip-1-0 $. + +The directory structure look as follows: + +apps/ - Example applications +doc/ - Documentation +lib/ - Library code used by some applications +uip/ - uIP TCP/IP stack code +unix/ - uIP as a user space process under FreeBSD or Linux Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-addrlabels.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-addrlabels.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-addrlabels.h (revision 14) @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2004-2005, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: lc-addrlabels.h,v 1.3 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \addtogroup lc + * @{ + */ + +/** + * \file + * Implementation of local continuations based on the "Labels as + * values" feature of gcc + * \author + * Adam Dunkels + * + * This implementation of local continuations is based on a special + * feature of the GCC C compiler called "labels as values". This + * feature allows assigning pointers with the address of the code + * corresponding to a particular C label. + * + * For more information, see the GCC documentation: + * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + * + * Thanks to dividuum for finding the nice local scope label + * implementation. + */ + +#ifndef __LC_ADDRLABELS_H__ +#define __LC_ADDRLABELS_H__ + +/** \hideinitializer */ +typedef void * lc_t; + +#define LC_INIT(s) s = NULL + + +#define LC_RESUME(s) \ + do { \ + if(s != NULL) { \ + goto *s; \ + } \ + } while(0) + +#define LC_SET(s) \ + do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0) + +#define LC_END(s) + +#endif /* __LC_ADDRLABELS_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.c (revision 14) @@ -0,0 +1,439 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uiparp uIP Address Resolution Protocol + * @{ + * + * The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * \note This ARP implementation only supports Ethernet. + */ + +/** + * \file + * Implementation of the ARP Address Resolution Protocol. + * \author Adam Dunkels + * + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ + * + */ + + +#include "uip_arp.h" + +#include + +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct arp_hdr { + struct uip_eth_hdr ethhdr; + u16_t hwtype; + u16_t protocol; + u8_t hwlen; + u8_t protolen; + u16_t opcode; + struct uip_eth_addr shwaddr; + u16_t sipaddr[2]; + struct uip_eth_addr dhwaddr; + u16_t dipaddr[2]; +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct ethip_hdr { + struct uip_eth_hdr ethhdr; + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +struct arp_entry { + u16_t ipaddr[2]; + struct uip_eth_addr ethaddr; + u8_t time; +}; + +static const struct uip_eth_addr broadcast_ethaddr = + {{0xff,0xff,0xff,0xff,0xff,0xff}}; +static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff}; + +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; +static u16_t ipaddr[2]; +static u8_t i, c; + +static u8_t arptime; +static u8_t tmpage; + +#define BUF ((struct arp_hdr *)&uip_buf[0]) +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the ARP module. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_init(void) +{ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + memset(arp_table[i].ipaddr, 0, 4); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_timer(void) +{ + struct arp_entry *tabptr; + + ++arptime; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && + arptime - tabptr->time >= UIP_ARP_MAXAGE) { + memset(tabptr->ipaddr, 0, 4); + } + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) +{ + register struct arp_entry *tabptr; + /* Walk through the ARP mapping table and try to find an entry to + update. If none is found, the IP -> MAC address mapping is + inserted in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + + tabptr = &arp_table[i]; + /* Only check those entries that are actually in use. */ + if(tabptr->ipaddr[0] != 0 && + tabptr->ipaddr[1] != 0) { + + /* Check if the source IP address of the incoming packet matches + the IP address in this ARP table entry. */ + if(ipaddr[0] == tabptr->ipaddr[0] && + ipaddr[1] == tabptr->ipaddr[1]) { + + /* An old entry found, update this and return. */ + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; + + return; + } + } + } + + /* If we get here, no existing ARP table entry was found, so we + create one. */ + + /* First, we try to find an unused entry in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(tabptr->ipaddr[0] == 0 && + tabptr->ipaddr[1] == 0) { + break; + } + } + + /* If no unused entry is found, we try to find the oldest entry and + throw it away. */ + if(i == UIP_ARPTAB_SIZE) { + tmpage = 0; + c = 0; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(arptime - tabptr->time > tmpage) { + tmpage = arptime - tabptr->time; + c = i; + } + } + i = c; + tabptr = &arp_table[i]; + } + + /* Now, i is the ARP table entry which we will fill with the new + information. */ + memcpy(tabptr->ipaddr, ipaddr, 4); + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; +} +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP + * packet has been received. The function will check if the address is + * in the ARP cache, and if so the ARP cache entry will be + * refreshed. If no ARP cache entry was found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header + * in the uip_buf[] buffer, and the length of the packet in the global + * variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +#if 1 +void +uip_arp_ipin(void) +{ + uip_len -= sizeof(struct uip_eth_hdr); + + /* Only insert/update an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + if((IPBUF->srcipaddr[0] & uip_netmask[0]) != + (uip_hostaddr[0] & uip_netmask[0])) { + return; + } + if((IPBUF->srcipaddr[1] & uip_netmask[1]) != + (uip_hostaddr[1] & uip_netmask[1])) { + return; + } + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + + return; +} +#endif /* 0 */ +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the uip_buf[] buffer. + * + * When the function returns, the value of the global variable uip_len + * indicates whether the device driver should send out a packet or + * not. If uip_len is zero, no packet should be sent. If uip_len is + * non-zero, it contains the length of the outbound packet that is + * present in the uip_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the uip_buf[] buffer, and the length of the packet in the + * global variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_arpin(void) +{ + + if(uip_len < sizeof(struct arp_hdr)) { + uip_len = 0; + return; + } + uip_len = 0; + + switch(BUF->opcode) { + case HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + reply. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + /* First, we register the one who made the request in our ARP + table, since it is likely that we will do more communication + with this host in the future. */ + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + + /* The reply opcode is 2. */ + BUF->opcode = HTONS(2); + + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); + + BUF->dipaddr[0] = BUF->sipaddr[0]; + BUF->dipaddr[1] = BUF->sipaddr[1]; + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; + + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + uip_len = sizeof(struct arp_hdr); + } + break; + case HTONS(ARP_REPLY): + /* ARP reply. We insert or update the ARP table if it was meant + for us. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + } + break; + } + + return; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the uip_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the uip_buf[] + * buffer, and the length of the packet is in the global variable + * uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_out(void) +{ + struct arp_entry *tabptr; + + /* Find the destination IP address in the ARP table and construct + the Ethernet header. If the destination IP addres isn't on the + local network, we use the default router's IP address instead. + + If not ARP table entry is found, we overwrite the original IP + packet with an ARP request for the IP address. */ + + /* First check if destination is a local broadcast. */ + if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { + memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); + } else { + /* Check if the destination address is on the local network. */ + if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { + /* Destination address was not on the local network, so we need to + use the default router's IP address instead of the destination + address when determining the MAC address. */ + uip_ipaddr_copy(ipaddr, uip_draddr); + } else { + /* Else, we use the destination IP address. */ + uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); + } + + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { + break; + } + } + + if(i == UIP_ARPTAB_SIZE) { + /* The destination address was not in our ARP table, so we + overwrite the IP packet with an ARP request. */ + + memset(BUF->ethhdr.dest.addr, 0xff, 6); + memset(BUF->dhwaddr.addr, 0x00, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + + uip_ipaddr_copy(BUF->dipaddr, ipaddr); + uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->protocol = HTONS(UIP_ETHTYPE_IP); + BUF->hwlen = 6; + BUF->protolen = 4; + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + + uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; + + uip_len = sizeof(struct arp_hdr); + return; + } + + /* Build an ethernet header. */ + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); + } + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + + uip_len += sizeof(struct uip_eth_hdr); +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arch.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arch.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arch.h (revision 14) @@ -0,0 +1,138 @@ +/** + * \addtogroup uip + * {@ + */ + +/** + * \defgroup uiparch Architecture specific uIP functions + * @{ + * + * The functions in the architecture specific module implement the IP + * check sum and 32-bit additions. + * + * The IP checksum calculation is the most computationally expensive + * operation in the TCP/IP stack and it therefore pays off to + * implement this in efficient assembler. The purpose of the uip-arch + * module is to let the checksum functions to be implemented in + * architecture specific assembler. + * + */ + +/** + * \file + * Declarations of architecture specific functions. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $ + * + */ + +#ifndef __UIP_ARCH_H__ +#define __UIP_ARCH_H__ + +#include "uip.h" + +/** + * Carry out a 32-bit addition. + * + * Because not all architectures for which uIP is intended has native + * 32-bit arithmetic, uIP uses an external C function for doing the + * required 32-bit additions in the TCP protocol processing. This + * function should add the two arguments and place the result in the + * global variable uip_acc32. + * + * \note The 32-bit integer pointed to by the op32 parameter and the + * result in the uip_acc32 variable are in network byte order (big + * endian). + * + * \param op32 A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). + * + * \param op16 A 16-bit integer in host byte order. + */ +void uip_add32(u8_t *op32, u16_t op16); + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \note This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \note The uip_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the uip_buf buffer. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +u16_t uip_udpchksum(void); + +/** @} */ +/** @} */ + +#endif /* __UIP_ARCH_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/clock.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/clock.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/clock.h (revision 14) @@ -0,0 +1,88 @@ +/** + * \defgroup clock Clock interface + * + * The clock interface is the interface between the \ref timer "timer library" + * and the platform specific clock functionality. The clock + * interface must be implemented for each platform that uses the \ref + * timer "timer library". + * + * The clock interface does only one this: it measures time. The clock + * interface provides a macro, CLOCK_SECOND, which corresponds to one + * second of system time. + * + * \sa \ref timer "Timer library" + * + * @{ + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __CLOCK_H__ +#define __CLOCK_H__ + +#include "clock-arch.h" + +/** + * Initialize the clock library. + * + * This function initializes the clock library and should be called + * from the main() function of the system. + * + */ +void clock_init(void); + +/** + * Get the current clock time. + * + * This function returns the current system clock time. + * + * \return The current clock time, measured in system ticks. + */ +clock_time_t clock_time(void); + +/** + * A second, measured in system clock time. + * + * \hideinitializer + */ +#ifdef CLOCK_CONF_SECOND +#define CLOCK_SECOND CLOCK_CONF_SECOND +#else +#define CLOCK_SECOND (clock_time_t)32 +#endif + +#endif /* __CLOCK_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.h (revision 14) @@ -0,0 +1,1638 @@ + +/** + * \addtogroup uip + * @{ + */ + +/** + * \file + * Header file for the uIP TCP/IP stack. + * \author Adam Dunkels + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $ + * + */ + +#ifndef __UIP_H__ +#define __UIP_H__ + +#include "uipopt.h" + +/** + * Repressentation of an IP address. + * + */ +typedef u16_t uip_ip4addr_t[2]; +typedef u16_t uip_ip6addr_t[8]; +#if UIP_CONF_IPV6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else /* UIP_CONF_IPV6 */ +typedef uip_ip4addr_t uip_ipaddr_t; +#endif /* UIP_CONF_IPV6 */ + +/*---------------------------------------------------------------------------*/ +/* First, the functions that should be called from the + * system. Initialization, the periodic timer and incoming packets are + * handled by the following three functions. + */ + +/** + * \defgroup uipconffunc uIP configuration functions + * @{ + * + * The uIP configuration functions are used for setting run-time + * parameters in uIP such as IP addresses. + */ + +/** + * Set the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + + uip_ipaddr_t addr; + + uip_ipaddr(&addr, 192,168,1,2); + uip_sethostaddr(&addr); + + \endcode + * \param addr A pointer to an IP address of type uip_ipaddr_t; + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) + +/** + * Get the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + uip_ipaddr_t hostaddr; + + uip_gethostaddr(&hostaddr); + \endcode + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the currently configured IP address. + * + * \hideinitializer + */ +#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) + +/** + * Set the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the default router. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) + +/** + * Set the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the netmask. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) + + +/** + * Get the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address of the default router. + * + * \hideinitializer + */ +#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) + +/** + * Get the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the value of the netmask. + * + * \hideinitializer + */ +#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) + +/** @} */ + +/** + * \defgroup uipinit uIP initialization functions + * @{ + * + * The uIP initialization functions are used for booting uIP. + */ + +/** + * uIP initialization function. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. + */ +void uip_init(void); + +/** + * uIP initialization function. + * + * This function may be used at boot time to set the initial ip_id. + */ +void uip_setipid(u16_t id); + +/** @} */ + +/** + * \defgroup uipdevfunc uIP device driver functions + * @{ + * + * These functions are used by a network device driver for interacting + * with uIP. + */ + +/** + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the uip_buf buffer, and the length of the packet + * should be placed in the uip_len variable. + * + * When the function returns, there may be an outbound packet placed + * in the uip_buf packet buffer. If so, the uip_len variable is set to + * the length of the packet. If no packet is to be sent out, the + * uip_len variable is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + \code + uip_len = devicedriver_poll(); + if(uip_len > 0) { + uip_input(); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + \code + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + uip_len = ethernet_devicedrver_poll(); + if(uip_len > 0) { + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); + if(uip_len > 0) { + ethernet_devicedriver_send(); + } + } + \endcode + * + * \hideinitializer + */ +#define uip_input() uip_process(UIP_DATA) + +/** + * Periodic processing for a connection identified by its number. + * + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called when the + * periodic uIP timer goes off. It should be called for every + * connection, regardless of whether they are open of closed. + * + * When the function returns, it may have an outbound packet waiting + * for service in the uIP packet buffer, and if so the uip_len + * variable is set to a value larger than zero. The device driver + * should be called to send out the packet. + * + * The ususal way of calling the function is through a for() loop like + * this: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uip_arp_out() function before + * calling the device driver: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the connection which is to be periodically polled. + * + * \hideinitializer + */ +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_process(UIP_TIMER); } while (0) + +/** + * + * + */ +#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) + +/** + * Perform periodic processing for a connection identified by a pointer + * to its structure. + * + * Same as uip_periodic() but takes a pointer to the actual uip_conn + * struct instead of an integer as its argument. This function can be + * used to force periodic processing of a specific connection. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) + +/** + * Reuqest that a particular connection should be polled. + * + * Similar to uip_periodic_conn() but does not perform any timer + * processing. The application is polled for new data. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_poll_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_POLL_REQUEST); } while (0) + + +#if UIP_UDP +/** + * Periodic processing for a UDP connection identified by its number. + * + * This function is essentially the same as uip_periodic(), but for + * UDP connections. It is called in a similar fashion as the + * uip_periodic() function: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note As for the uip_periodic() function, special care has to be + * taken when using uIP together with ARP and Ethernet: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the UDP connection to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_process(UIP_UDP_TIMER); } while (0) + +/** + * Periodic processing for a UDP connection identified by a pointer to + * its structure. + * + * Same as uip_udp_periodic() but takes a pointer to the actual + * uip_conn struct instead of an integer as its argument. This + * function can be used to force periodic processing of a specific + * connection. + * + * \param conn A pointer to the uip_udp_conn struct for the connection + * to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while (0) + + +#endif /* UIP_UDP */ + +/** + * The uIP packet buffer. + * + * The uip_buf array is used to hold incoming and outgoing + * packets. The device driver should place incoming data into this + * buffer. When sending data, the device driver should read the link + * level headers and the TCP/IP headers from this buffer. The size of + * the link level headers is configured by the UIP_LLH_LEN define. + * + * \note The application data need not be placed in this buffer, so + * the device driver must read it from the place pointed to by the + * uip_appdata pointer as illustrated by the following example: + \code + void + devicedriver_send(void) + { + hwsend(&uip_buf[0], UIP_LLH_LEN); + if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { + hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); + } else { + hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); + hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); + } + } + \endcode + */ +#ifndef UIP_CONF_EXTERNAL_BUFFER + extern u8_t uip_buf[UIP_BUFSIZE+2]; +#else + extern unsigned char *uip_buf; +#endif + +/** @} */ + +/*---------------------------------------------------------------------------*/ +/* Functions that are used by the uIP application program. Opening and + * closing connections, sending and receiving data, etc. is all + * handled by the functions below. +*/ +/** + * \defgroup uipappfunc uIP application functions + * @{ + * + * Functions used by an application running of top of uIP. + */ + +/** + * Start listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_listen(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_listen(u16_t port); + +/** + * Stop listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_unlisten(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_unlisten(u16_t port); + +/** + * Connect to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It allocates a new connection identifier, + * sets the connection to the SYN_SENT state and sets the + * retransmission timer to 0. This will cause a TCP SYN segment to be + * sent out the next time this connection is periodically processed, + * which usually is done within 0.5 seconds after the call to + * uip_connect(). + * + * \note This function is avaliable only if support for active open + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. + * + * \note Since this function requires the port number to be in network + * byte order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_ipaddr_t ipaddr; + + uip_ipaddr(&ipaddr, 192,168,1,2); + uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param ripaddr The IP address of the remote hot. + * + * \param port A 16-bit port number in network byte order. + * + * \return A pointer to the uIP connection identifier for the new connection, + * or NULL if no connection could be allocated. + * + */ +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port); + + + +/** + * \internal + * + * Check if a connection has outstanding (i.e., unacknowledged) data. + * + * \param conn A pointer to the uip_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_outstanding(conn) ((conn)->len) + +/** + * Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * \note This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the uip_rexmit() event being + * set. The application will then have to resend the data using this + * function. + * + * \param data A pointer to the data which is to be sent. + * + * \param len The maximum amount of data bytes to be sent. + * + * \hideinitializer + */ +void uip_send(const void *data, int len); + +/** + * The length of any incoming data that is currently avaliable (if avaliable) + * in the uip_appdata buffer. + * + * The test function uip_data() must first be used to check if there + * is any data available at all. + * + * \hideinitializer + */ +/*void uip_datalen(void);*/ +#define uip_datalen() uip_len + +/** + * The length of any out-of-band data (urgent data) that has arrived + * on the connection. + * + * \note The configuration parameter UIP_URGDATA must be set for this + * function to be enabled. + * + * \hideinitializer + */ +#define uip_urgdatalen() uip_urglen + +/** + * Close the current connection. + * + * This function will close the current connection in a nice way. + * + * \hideinitializer + */ +#define uip_close() (uip_flags = UIP_CLOSE) + +/** + * Abort the current connection. + * + * This function will abort (reset) the current connection, and is + * usually used when an error has occured that prevents using the + * uip_close() function. + * + * \hideinitializer + */ +#define uip_abort() (uip_flags = UIP_ABORT) + +/** + * Tell the sending host to stop sending data. + * + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) + +/** + * Find out if the current connection has been previously stopped with + * uip_stop(). + * + * \hideinitializer + */ +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + +/** + * Restart the current connection, if is has previously been stopped + * with uip_stop(). + * + * This function will open the receiver's window again so that we + * start receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) + + +/* uIP tests that can be made to determine in what state the current + connection is, and what the application function should do. */ + +/** + * Is the current connection a UDP connection? + * + * This function checks whether the current connection is a UDP connection. + * + * \hideinitializer + * + */ +#define uip_udpconnection() (uip_conn == NULL) + +/** + * Is new incoming data available? + * + * Will reduce to non-zero if there is new data for the application + * present at the uip_appdata pointer. The size of the data is + * avaliable through the uip_len variable. + * + * \hideinitializer + */ +#define uip_newdata() (uip_flags & UIP_NEWDATA) + +/** + * Has previously sent data been acknowledged? + * + * Will reduce to non-zero if the previously sent data has been + * acknowledged by the remote host. This means that the application + * can send new data. + * + * \hideinitializer + */ +#define uip_acked() (uip_flags & UIP_ACKDATA) + +/** + * Has the connection just been connected? + * + * Reduces to non-zero if the current connection has been connected to + * a remote host. This will happen both if the connection has been + * actively opened (with uip_connect()) or passively opened (with + * uip_listen()). + * + * \hideinitializer + */ +#define uip_connected() (uip_flags & UIP_CONNECTED) + +/** + * Has the connection been closed by the other end? + * + * Is non-zero if the connection has been closed by the remote + * host. The application may then do the necessary clean-ups. + * + * \hideinitializer + */ +#define uip_closed() (uip_flags & UIP_CLOSE) + +/** + * Has the connection been aborted by the other end? + * + * Non-zero if the current connection has been aborted (reset) by the + * remote host. + * + * \hideinitializer + */ +#define uip_aborted() (uip_flags & UIP_ABORT) + +/** + * Has the connection timed out? + * + * Non-zero if the current connection has been aborted due to too many + * retransmissions. + * + * \hideinitializer + */ +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + +/** + * Do we need to retransmit previously data? + * + * Reduces to non-zero if the previously sent data has been lost in + * the network, and the application should retransmit it. The + * application should send the exact same data as it did the last + * time, using the uip_send() function. + * + * \hideinitializer + */ +#define uip_rexmit() (uip_flags & UIP_REXMIT) + +/** + * Is the connection being polled by uIP? + * + * Is non-zero if the reason the application is invoked is that the + * current connection has been idle for a while and should be + * polled. + * + * The polling event can be used for sending data without having to + * wait for the remote host to send data. + * + * \hideinitializer + */ +#define uip_poll() (uip_flags & UIP_POLL) + +/** + * Get the initial maxium segment size (MSS) of the current + * connection. + * + * \hideinitializer + */ +#define uip_initialmss() (uip_conn->initialmss) + +/** + * Get the current maxium segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the + * connection is computed from the receiver's window and the MSS of + * the connection (which also is available by calling + * uip_initialmss()). + * + * \hideinitializer + */ +#define uip_mss() (uip_conn->mss) + +/** + * Set up a new UDP connection. + * + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udp_bind() call, after the uip_udp_new() function has been + * called. + * + * Example: + \code + uip_ipaddr_t addr; + struct uip_udp_conn *c; + + uip_ipaddr(&addr, 192,168,2,1); + c = uip_udp_new(&addr, HTONS(12345)); + if(c != NULL) { + uip_udp_bind(c, HTONS(12344)); + } + \endcode + * \param ripaddr The IP address of the remote host. + * + * \param rport The remote port number in network byte order. + * + * \return The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport); + +/** + * Removed a UDP connection. + * + * \param conn A pointer to the uip_udp_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_udp_remove(conn) (conn)->lport = 0 + +/** + * Bind a UDP connection to a local port. + * + * \param conn A pointer to the uip_udp_conn structure for the + * connection. + * + * \param port The local port number, in network byte order. + * + * \hideinitializer + */ +#define uip_udp_bind(conn, port) (conn)->lport = port + +/** + * Send a UDP datagram of length len on the current connection. + * + * This function can only be called in response to a UDP event (poll + * or newdata). The data must be present in the uip_buf buffer, at the + * place pointed to by the uip_appdata pointer. + * + * \param len The length of the data in the uip_buf buffer. + * + * \hideinitializer + */ +#define uip_udp_send(len) uip_send((char *)uip_appdata, len) + +/** @} */ + +/* uIP convenience and converting functions. */ + +/** + * \defgroup uipconvfunc uIP conversion functions + * @{ + * + * These functions can be used for converting between different data + * formats used by uIP. + */ + +/** + * Construct an IP address from four bytes. + * + * This function constructs an IP address of the type that uIP handles + * internally from four bytes. The function is handy for specifying IP + * addresses to use with e.g. the uip_connect() function. + * + * Example: + \code + uip_ipaddr_t ipaddr; + struct uip_conn *c; + + uip_ipaddr(&ipaddr, 192,168,1,2); + c = uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address. + * + * \param addr0 The first octet of the IP address. + * \param addr1 The second octet of the IP address. + * \param addr2 The third octet of the IP address. + * \param addr3 The forth octet of the IP address. + * + * \hideinitializer + */ +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ + ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ + } while(0) + +/** + * Construct an IPv6 address from eight 16-bit words. + * + * This function constructs an IPv6 address. + * + * \hideinitializer + */ +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ + ((u16_t *)(addr))[0] = HTONS((addr0)); \ + ((u16_t *)(addr))[1] = HTONS((addr1)); \ + ((u16_t *)(addr))[2] = HTONS((addr2)); \ + ((u16_t *)(addr))[3] = HTONS((addr3)); \ + ((u16_t *)(addr))[4] = HTONS((addr4)); \ + ((u16_t *)(addr))[5] = HTONS((addr5)); \ + ((u16_t *)(addr))[6] = HTONS((addr6)); \ + ((u16_t *)(addr))[7] = HTONS((addr7)); \ + } while(0) + +/** + * Copy an IP address to another IP address. + * + * Copies an IP address from one place to another. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr_copy(&ipaddr2, &ipaddr1); + \endcode + * + * \param dest The destination for the copy. + * \param src The source from where to copy. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_copy(dest, src) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \ + } while(0) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses + * + * Compares two IP addresses. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ + ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1]) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses with netmasks + * + * Compares two IP addresses with netmasks. The masks are used to mask + * out the bits that are to be compared. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, mask; + + uip_ipaddr(&mask, 255,255,255,0); + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&ipaddr2, 192,16,1,3); + if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ + (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ + ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ + (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) + + +/** + * Mask out the network part of an IP address. + * + * Masks out the network part of an IP address, given the address and + * the netmask. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, netmask; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&netmask, 255,255,255,0); + uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask); + \endcode + * + * In the example above, the variable "ipaddr2" will contain the IP + * address 192.168.1.0. + * + * \param dest Where the result is to be placed. + * \param src The IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ + } while(0) + +/** + * Pick the first octet of an IP address. + * + * Picks out the first octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr1(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 1. + * + * \hideinitializer + */ +#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8) + +/** + * Pick the second octet of an IP address. + * + * Picks out the second octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr2(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 2. + * + * \hideinitializer + */ +#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff) + +/** + * Pick the third octet of an IP address. + * + * Picks out the third octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr3(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 3. + * + * \hideinitializer + */ +#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8) + +/** + * Pick the fourth octet of an IP address. + * + * Picks out the fourth octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr4(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 4. + * + * \hideinitializer + */ +#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff) + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This macro is primarily used for converting constants from host + * byte order to network byte order. For converting variables to + * network byte order, use the htons() function instead. + * + * \hideinitializer + */ +#ifndef HTONS +# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN +# define HTONS(n) (n) +# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) +# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#else +#error "HTONS already defined!" +#endif /* HTONS */ + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This function is primarily used for converting variables from host + * byte order to network byte order. For converting constants to + * network byte order, use the HTONS() macro instead. + */ +#ifndef htons +u16_t htons(u16_t val); +#endif /* htons */ +#ifndef ntohs +#define ntohs htons +#endif + +/** @} */ + +/** + * Pointer to the application data in the packet buffer. + * + * This pointer points to the application data when the application is + * called. If the application wishes to send data, the application may + * use this space to write the data into before calling uip_send(). + */ +extern void *uip_appdata; + +#if UIP_URGDATA > 0 +/* u8_t *uip_urgdata: + * + * This pointer points to any urgent data that has been received. Only + * present if compiled with support for urgent data (UIP_URGDATA). + */ +extern void *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + + +/** + * \defgroup uipdrivervars Variables used in uIP device drivers + * @{ + * + * uIP has a few global variables that are used in device drivers for + * uIP. + */ + +/** + * The length of the packet in the uip_buf buffer. + * + * The global variable uip_len holds the length of the packet in the + * uip_buf buffer. + * + * When the network device driver calls the uIP input function, + * uip_len should be set to the length of the packet in the uip_buf + * buffer. + * + * When sending packets, the device driver should use the contents of + * the uip_len variable to determine the length of the outgoing + * packet. + * + */ +extern u16_t uip_len; + +/** @} */ + +#if UIP_URGDATA > 0 +extern u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + + +/** + * Representation of a uIP TCP connection. + * + * The uip_conn structure is used for identifying a connection. All + * but one field in the structure are to be considered read-only by an + * application. The only exception is the appstate field whos purpose + * is to let the application store application-specific state (e.g., + * file pointers) for the connection. The type of this field is + * configured in the "uipopt.h" header file. + */ +struct uip_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */ + + u16_t lport; /**< The local TCP port, in network byte order. */ + u16_t rport; /**< The local remote TCP port, in network byte + order. */ + + u8_t rcv_nxt[4]; /**< The sequence number that we expect to + receive next. */ + u8_t snd_nxt[4]; /**< The sequence number that was last sent by + us. */ + u16_t len; /**< Length of the data that was previously sent. */ + u16_t mss; /**< Current maximum segment size for the + connection. */ + u16_t initialmss; /**< Initial maximum segment size for the + connection. */ + u8_t sa; /**< Retransmission time-out calculation state + variable. */ + u8_t sv; /**< Retransmission time-out calculation state + variable. */ + u8_t rto; /**< Retransmission time-out. */ + u8_t tcpstateflags; /**< TCP state and flags. */ + u8_t timer; /**< The retransmission timer. */ + u8_t nrtx; /**< The number of retransmissions for the last + segment sent. */ + + /** The application state. */ + uip_tcp_appstate_t appstate; +}; + + +/** + * Pointer to the current TCP connection. + * + * The uip_conn pointer can be used to access the current TCP + * connection. + */ +extern struct uip_conn *uip_conn; +/* The array containing all uIP connections. */ +extern struct uip_conn uip_conns[UIP_CONNS]; +/** + * \addtogroup uiparch + * @{ + */ + +/** + * 4-byte array used for the 32-bit sequence number calculations. + */ +extern u8_t uip_acc32[4]; + +/** @} */ + + +#if UIP_UDP +/** + * Representation of a uIP UDP connection. + */ +struct uip_udp_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ + u16_t lport; /**< The local port number in network byte order. */ + u16_t rport; /**< The remote port number in network byte order. */ + u8_t ttl; /**< Default time-to-live. */ + + /** The application state. */ + uip_udp_appstate_t appstate; +}; + +/** + * The current UDP connection. + */ +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/** + * The structure holding the TCP/IP statistics that are gathered if + * UIP_STATISTICS is set to 1. + * + */ +struct uip_stats { + struct { + uip_stats_t drop; /**< Number of dropped packets at the IP + layer. */ + uip_stats_t recv; /**< Number of received packets at the IP + layer. */ + uip_stats_t sent; /**< Number of sent packets at the IP + layer. */ + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /**< Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /**< Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /**< Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /**< IP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped ICMP packets. */ + uip_stats_t recv; /**< Number of received ICMP packets. */ + uip_stats_t sent; /**< Number of sent ICMP packets. */ + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong + type. */ + } icmp; /**< ICMP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped TCP segments. */ + uip_stats_t recv; /**< Number of recived TCP segments. */ + uip_stats_t sent; /**< Number of sent TCP segments. */ + uip_stats_t chkerr; /**< Number of TCP segments with a bad + checksum. */ + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK + number. */ + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /**< Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /**< TCP statistics. */ +#if UIP_UDP + struct { + uip_stats_t drop; /**< Number of dropped UDP segments. */ + uip_stats_t recv; /**< Number of recived UDP segments. */ + uip_stats_t sent; /**< Number of sent UDP segments. */ + uip_stats_t chkerr; /**< Number of UDP segments with a bad + checksum. */ + } udp; /**< UDP statistics. */ +#endif /* UIP_UDP */ +}; + +/** + * The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ +extern struct uip_stats uip_stat; + + +/*---------------------------------------------------------------------------*/ +/* All the stuff below this point is internal to uIP and should not be + * used directly by an application or by a device driver. + */ +/*---------------------------------------------------------------------------*/ +/* u8_t uip_flags: + * + * When the application is called, uip_flags will contain the flags + * that are defined in this file. Please read below for more + * infomation. + */ +extern u8_t uip_flags; + +/* The following flags may be set in the global variable uip_flags + before calling the application callback. The UIP_ACKDATA, + UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time, + whereas the others are mutualy exclusive. Note that these flags + should *NOT* be accessed directly, but only through the uIP + functions/macros. */ + +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was + acked and the application should send + out new data instead of retransmitting + the last data. */ +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent + us new data. */ +#define UIP_REXMIT 4 /* Tells the application to retransmit the + data that was last sent. */ +#define UIP_POLL 8 /* Used for polling the application, to + check if the application has data that + it wants to send. */ +#define UIP_CLOSE 16 /* The remote host has closed the + connection, thus the connection has + gone away. Or the application signals + that it wants to close the + connection. */ +#define UIP_ABORT 32 /* The remote host has aborted the + connection, thus the connection has + gone away. Or the application signals + that it wants to abort the + connection. */ +#define UIP_CONNECTED 64 /* We have got a connection from a remote + host and have set up a new connection + for it, or an active connection has + been successfully established. */ + +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to + too many retransmissions. */ + +/* uip_process(flag): + * + * The actual uIP function which does all the work. + */ +void uip_process(u8_t flag); + +/* The following flags are passed as an argument to the uip_process() + function. They are used to distinguish between the two cases where + uip_process() is called. It can be called either because we have + incoming data that should be processed, or because the periodic + timer has fired. These values are never used directly, but only in + the macrose defined in this file. */ + +#define UIP_DATA 1 /* Tells uIP that there is incoming + data in the uip_buf buffer. The + length of the data is stored in the + global variable uip_len. */ +#define UIP_TIMER 2 /* Tells uIP that the periodic timer + has fired. */ +#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should + be polled. */ +#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram + should be constructed in the + uip_buf buffer. */ +#if UIP_UDP +#define UIP_UDP_TIMER 5 +#endif /* UIP_UDP */ + +/* The TCP states used in the uip_conn->tcpstateflags. */ +#define UIP_CLOSED 0 +#define UIP_SYN_RCVD 1 +#define UIP_SYN_SENT 2 +#define UIP_ESTABLISHED 3 +#define UIP_FIN_WAIT_1 4 +#define UIP_FIN_WAIT_2 5 +#define UIP_CLOSING 6 +#define UIP_TIME_WAIT 7 +#define UIP_LAST_ACK 8 +#define UIP_TS_MASK 15 + +#define UIP_STOPPED 16 + +/* The TCP and IP headers. */ + +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct uip_tcpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcflow; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* TCP header. */ + u16_t srcport, + destport; + u8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + +/* The ICMP and IP headers. */ +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct uip_icmpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; +#if !UIP_CONF_IPV6 + u16_t id, seqno; +#else /* !UIP_CONF_IPV6 */ + u8_t flags, reserved1, reserved2, reserved3; + u8_t icmp6data[16]; + u8_t options[1]; +#endif /* !UIP_CONF_IPV6 */ +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + + +/* The UDP and IP headers. */ +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct uip_udpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* UDP header. */ + u16_t srcport, + destport; + u16_t udplen; + u16_t udpchksum; +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + + + +/** + * The buffer size available for user data in the \ref uip_buf buffer. + * + * This macro holds the available size for user data in the \ref + * uip_buf buffer. The macro is intended to be used for checking + * bounds of available user data. + * + * Example: + \code + snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i); + \endcode + * + * \hideinitializer + */ +#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 + +/* Header sizes. */ +#if UIP_CONF_IPV6 +#define UIP_IPH_LEN 40 +#else /* UIP_CONF_IPV6 */ +#define UIP_IPH_LEN 20 /* Size of IP header */ +#endif /* UIP_CONF_IPV6 */ +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + + UDP + header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + + TCP + header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN + + +#if UIP_FIXEDADDR +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#else /* UIP_FIXEDADDR */ +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#endif /* UIP_FIXEDADDR */ + + + +/** + * Representation of a 48-bit Ethernet address. + */ +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct uip_eth_addr { + u8_t addr[6]; +} PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +/** + * Calculate the UDP checksum of the packet in uip_buf and uip_appdata. + * + * The UDP checksum is the Internet checksum of data contents of the + * UDP segment, and a pseudo-header as defined in RFC768. + * + * \return The UDP checksum of the UDP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_udpchksum(void); + + +#endif /* __UIP_H__ */ + + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-switch.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-switch.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc-switch.h (revision 14) @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004-2005, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: lc-switch.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \addtogroup lc + * @{ + */ + +/** + * \file + * Implementation of local continuations based on switch() statment + * \author Adam Dunkels + * + * This implementation of local continuations uses the C switch() + * statement to resume execution of a function somewhere inside the + * function's body. The implementation is based on the fact that + * switch() statements are able to jump directly into the bodies of + * control structures such as if() or while() statmenets. + * + * This implementation borrows heavily from Simon Tatham's coroutines + * implementation in C: + * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + */ + +#ifndef __LC_SWITCH_H__ +#define __LC_SWTICH_H__ + +/* WARNING! lc implementation using switch() does not work if an + LC_SET() is done within another switch() statement! */ + +/** \hideinitializer */ +typedef unsigned short lc_t; + +#define LC_INIT(s) s = 0; + +#define LC_RESUME(s) switch(s) { case 0: + +#define LC_SET(s) s = __LINE__; case __LINE__: + +#define LC_END(s) } + +#endif /* __LC_SWITCH_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/lc.h (revision 14) @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2004-2005, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: lc.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \defgroup lc Local continuations + * @{ + * + * Local continuations form the basis for implementing protothreads. A + * local continuation can be set in a specific function to + * capture the state of the function. After a local continuation has + * been set can be resumed in order to restore the state of the + * function at the point where the local continuation was set. + * + * + */ + +/** + * \file lc.h + * Local continuations + * \author + * Adam Dunkels + * + */ + +#ifdef DOXYGEN +/** + * Initialize a local continuation. + * + * This operation initializes the local continuation, thereby + * unsetting any previously set continuation state. + * + * \hideinitializer + */ +#define LC_INIT(lc) + +/** + * Set a local continuation. + * + * The set operation saves the state of the function at the point + * where the operation is executed. As far as the set operation is + * concerned, the state of the function does not include the + * call-stack or local (automatic) variables, but only the program + * counter and such CPU registers that needs to be saved. + * + * \hideinitializer + */ +#define LC_SET(lc) + +/** + * Resume a local continuation. + * + * The resume operation resumes a previously set local continuation, thus + * restoring the state in which the function was when the local + * continuation was set. If the local continuation has not been + * previously set, the resume operation does nothing. + * + * \hideinitializer + */ +#define LC_RESUME(lc) + +/** + * Mark the end of local continuation usage. + * + * The end operation signifies that local continuations should not be + * used any more in the function. This operation is not needed for + * most implementations of local continuation, but is required by a + * few implementations. + * + * \hideinitializer + */ +#define LC_END(lc) + +/** + * \var typedef lc_t; + * + * The local continuation type. + * + * \hideinitializer + */ +#endif /* DOXYGEN */ + +#ifndef __LC_H__ +#define __LC_H__ + +#ifdef LC_CONF_INCLUDE +#include LC_CONF_INCLUDE +#else +#include "lc-switch.h" +#endif /* LC_CONF_INCLUDE */ + +#endif /* __LC_H__ */ + +/** @} */ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip_arp.h (revision 14) @@ -0,0 +1,152 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \addtogroup uiparp + * @{ + */ + +/** + * \file + * Macros and definitions for the ARP module. + * \author Adam Dunkels + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $ + * + */ + +#ifndef __UIP_ARP_H__ +#define __UIP_ARP_H__ + +#include "uip.h" + + +extern struct uip_eth_addr uip_ethaddr; + +/** + * The Ethernet header. + */ +#ifdef __ICCARM__ + #pragma pack(1) +#endif + +struct uip_eth_hdr { + struct uip_eth_addr dest; + struct uip_eth_addr src; + u16_t type; +}PACK_STRUCT_END; + +#ifdef __ICCARM__ + #pragma pack() +#endif + +#define UIP_ETHTYPE_ARP 0x0806 +#define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + + +/* The uip_arp_init() function must be called before any of the other + ARP functions. */ +void uip_arp_init(void); + +/* The uip_arp_ipin() function should be called whenever an IP packet + arrives from the Ethernet. This function refreshes the ARP table or + inserts a new mapping if none exists. The function assumes that an + IP packet with an Ethernet header is present in the uip_buf buffer + and that the length of the packet is in the uip_len variable. */ +void uip_arp_ipin(void); +//#define uip_arp_ipin() + +/* The uip_arp_arpin() should be called when an ARP packet is received + by the Ethernet driver. This function also assumes that the + Ethernet frame is present in the uip_buf buffer. When the + uip_arp_arpin() function returns, the contents of the uip_buf + buffer should be sent out on the Ethernet if the uip_len variable + is > 0. */ +void uip_arp_arpin(void); + +/* The uip_arp_out() function should be called when an IP packet + should be sent out on the Ethernet. This function creates an + Ethernet header before the IP header in the uip_buf buffer. The + Ethernet header will have the correct Ethernet MAC destination + address filled in if an ARP table entry for the destination IP + address (or the IP address of the default router) is present. If no + such table entry is found, the IP packet is overwritten with an ARP + request and we rely on TCP to retransmit the packet that was + overwritten. In any case, the uip_len variable holds the length of + the Ethernet frame that should be transmitted. */ +void uip_arp_out(void); + +/* The uip_arp_timer() function should be called every ten seconds. It + is responsible for flushing old entries in the ARP table. */ +void uip_arp_timer(void); + +/** @} */ + +/** + * \addtogroup uipconffunc + * @{ + */ + + +/** + * Specifiy the Ethernet MAC address. + * + * The ARP code needs to know the MAC address of the Ethernet card in + * order to be able to respond to ARP queries and to generate working + * Ethernet headers. + * + * \note This macro only specifies the Ethernet MAC address to the ARP + * code. It cannot be used to change the MAC address of the Ethernet + * card. + * + * \param eaddr A pointer to a struct uip_eth_addr containing the + * Ethernet MAC address of the Ethernet card. + * + * \hideinitializer + */ +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ + uip_ethaddr.addr[1] = eaddr.addr[1];\ + uip_ethaddr.addr[2] = eaddr.addr[2];\ + uip_ethaddr.addr[3] = eaddr.addr[3];\ + uip_ethaddr.addr[4] = eaddr.addr[4];\ + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) + +/** @} */ +/** @} */ + +#endif /* __UIP_ARP_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.c (revision 14) @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: uip-fw.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uipfw uIP packet forwarding + * @{ + * + */ + +/** + * \file + * uIP packet forwarding. + * \author Adam Dunkels + * + * This file implements a number of simple functions which do packet + * forwarding over multiple network interfaces with uIP. + * + */ + +#include "uip.h" +#include "uip_arch.h" +#include "uip-fw.h" + +#include /* for memcpy() */ + +/* + * The list of registered network interfaces. + */ +static struct uip_fw_netif *netifs = NULL; + +/* + * A pointer to the default network interface. + */ +static struct uip_fw_netif *defaultnetif = NULL; + +struct tcpip_hdr { + /* IP header. */ + u8_t vhl, + tos; + u16_t len, + ipid, + ipoffset; + u8_t ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; + + /* TCP header. */ + u16_t srcport, + destport; + u8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; +} PACK_STRUCT_END; + +struct icmpip_hdr { + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; + u16_t id, seqno; + u8_t payload[1]; +} PACK_STRUCT_END; + +/* ICMP ECHO. */ +#define ICMP_ECHO 8 + +/* ICMP TIME-EXCEEDED. */ +#define ICMP_TE 11 + +/* + * Pointer to the TCP/IP headers of the packet in the uip_buf buffer. + */ +#define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/* + * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer. + */ +#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/* + * Certain fields of an IP packet that are used for identifying + * duplicate packets. + */ +struct fwcache_entry { + u16_t timer; + + u16_t srcipaddr[2]; + u16_t destipaddr[2]; + u16_t ipid; + u8_t proto; + u8_t unused; + +#if notdef + u16_t payload[2]; +#endif + +#if UIP_REASSEMBLY > 0 + u16_t len, offset; +#endif +}; + +/* + * The number of packets to remember when looking for duplicates. + */ +#ifdef UIP_CONF_FWCACHE_SIZE +#define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE +#else +#define FWCACHE_SIZE 2 +#endif + + +/* + * A cache of packet header fields which are used for + * identifying duplicate packets. + */ +static struct fwcache_entry fwcache[FWCACHE_SIZE]; + +/** + * \internal + * The time that a packet cache is active. + */ +#define FW_TIME 20 + +/*------------------------------------------------------------------------------*/ +/** + * Initialize the uIP packet forwarding module. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_init(void) +{ + struct uip_fw_netif *t; + defaultnetif = NULL; + while(netifs != NULL) { + t = netifs; + netifs = netifs->next; + t->next = NULL; + } +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Check if an IP address is within the network defined by an IP + * address and a netmask. + * + * \param ipaddr The IP address to be checked. + * \param netipaddr The IP address of the network. + * \param netmask The netmask of the network. + * + * \return Non-zero if IP address is in network, zero otherwise. + */ +/*------------------------------------------------------------------------------*/ +static unsigned char +ipaddr_maskcmp(u16_t *ipaddr, u16_t *netipaddr, u16_t *netmask) +{ + return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) && + (ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]); +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Send out an ICMP TIME-EXCEEDED message. + * + * This function replaces the packet in the uip_buf buffer with the + * ICMP packet. + */ +/*------------------------------------------------------------------------------*/ +static void +time_exceeded(void) +{ + u16_t tmp16; + + /* We don't send out ICMP errors for ICMP messages. */ + if(ICMPBUF->proto == UIP_PROTO_ICMP) { + uip_len = 0; + return; + } + /* Copy fields from packet header into payload of this ICMP packet. */ + memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28); + + /* Set the ICMP type and code. */ + ICMPBUF->type = ICMP_TE; + ICMPBUF->icode = 0; + + /* Calculate the ICMP checksum. */ + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36); + + /* Set the IP destination address to be the source address of the + original packet. */ + tmp16= BUF->destipaddr[0]; + BUF->destipaddr[0] = BUF->srcipaddr[0]; + BUF->srcipaddr[0] = tmp16; + tmp16 = BUF->destipaddr[1]; + BUF->destipaddr[1] = BUF->srcipaddr[1]; + BUF->srcipaddr[1] = tmp16; + + /* Set our IP address as the source address. */ + BUF->srcipaddr[0] = uip_hostaddr[0]; + BUF->srcipaddr[1] = uip_hostaddr[1]; + + /* The size of the ICMP time exceeded packet is 36 + the size of the + IP header (20) = 56. */ + uip_len = 56; + ICMPBUF->len[0] = 0; + ICMPBUF->len[1] = uip_len; + + /* Fill in the other fields in the IP header. */ + ICMPBUF->vhl = 0x45; + ICMPBUF->tos = 0; + ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0; + ICMPBUF->ttl = UIP_TTL; + ICMPBUF->proto = UIP_PROTO_ICMP; + + /* Calculate IP checksum. */ + ICMPBUF->ipchksum = 0; + ICMPBUF->ipchksum = ~(uip_ipchksum()); + + +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Register a packet in the forwarding cache so that it won't be + * forwarded again. + */ +/*------------------------------------------------------------------------------*/ +static void +fwcache_register(void) +{ + struct fwcache_entry *fw; + int i, oldest; + + oldest = FW_TIME; + fw = NULL; + + /* Find the oldest entry in the cache. */ + for(i = 0; i < FWCACHE_SIZE; ++i) { + if(fwcache[i].timer == 0) { + fw = &fwcache[i]; + break; + } else if(fwcache[i].timer <= oldest) { + fw = &fwcache[i]; + oldest = fwcache[i].timer; + } + } + + fw->timer = FW_TIME; + fw->ipid = BUF->ipid; + fw->srcipaddr[0] = BUF->srcipaddr[0]; + fw->srcipaddr[1] = BUF->srcipaddr[1]; + fw->destipaddr[0] = BUF->destipaddr[0]; + fw->destipaddr[1] = BUF->destipaddr[1]; + fw->proto = BUF->proto; +#if notdef + fw->payload[0] = BUF->srcport; + fw->payload[1] = BUF->destport; +#endif +#if UIP_REASSEMBLY > 0 + fw->len = BUF->len; + fw->offset = BUF->ipoffset; +#endif +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Find a network interface for the IP packet in uip_buf. + */ +/*------------------------------------------------------------------------------*/ +static struct uip_fw_netif * +find_netif(void) +{ + struct uip_fw_netif *netif; + + /* Walk through every network interface to check for a match. */ + for(netif = netifs; netif != NULL; netif = netif->next) { + if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr, + netif->netmask)) { + /* If there was a match, we break the loop. */ + return netif; + } + } + + /* If no matching netif was found, we use default netif. */ + return defaultnetif; +} +/*------------------------------------------------------------------------------*/ +/** + * Output an IP packet on the correct network interface. + * + * The IP packet should be present in the uip_buf buffer and its + * length in the global uip_len variable. + * + * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet + * transmission was attempted and that no packet was sent. + * + * \retval UIP_FW_NOROUTE No suitable network interface could be found + * for the outbound packet, and the packet was not sent. + * + * \return The return value from the actual network interface output + * function is passed unmodified as a return value. + */ +/*------------------------------------------------------------------------------*/ +u8_t +uip_fw_output(void) +{ + struct uip_fw_netif *netif; + + if(uip_len == 0) { + return UIP_FW_ZEROLEN; + } + + fwcache_register(); + +#if UIP_BROADCAST + /* Link local broadcasts go out on all interfaces. */ + if(/*BUF->proto == UIP_PROTO_UDP &&*/ + BUF->destipaddr[0] == 0xffff && + BUF->destipaddr[1] == 0xffff) { + if(defaultnetif != NULL) { + defaultnetif->output(); + } + for(netif = netifs; netif != NULL; netif = netif->next) { + netif->output(); + } + return UIP_FW_OK; + } +#endif /* UIP_BROADCAST */ + + netif = find_netif(); + /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif, + netif->output, + uip_len);*/ + + if(netif == NULL) { + return UIP_FW_NOROUTE; + } + /* If we now have found a suitable network interface, we call its + output function to send out the packet. */ + return netif->output(); +} +/*------------------------------------------------------------------------------*/ +/** + * Forward an IP packet in the uip_buf buffer. + * + * + * + * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if + * the packet should be processed locally. + */ +/*------------------------------------------------------------------------------*/ +u8_t +uip_fw_forward(void) +{ + struct fwcache_entry *fw; + + /* First check if the packet is destined for ourselves and return 0 + to indicate that the packet should be processed locally. */ + if(BUF->destipaddr[0] == uip_hostaddr[0] && + BUF->destipaddr[1] == uip_hostaddr[1]) { + return UIP_FW_LOCAL; + } + + /* If we use ping IP address configuration, and our IP address is + not yet configured, we should intercept all ICMP echo packets. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 && + BUF->proto == UIP_PROTO_ICMP && + ICMPBUF->type == ICMP_ECHO) { + return UIP_FW_LOCAL; + } +#endif /* UIP_PINGADDRCONF */ + + /* Check if the packet is in the forwarding cache already, and if so + we drop it. */ + + for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { + if(fw->timer != 0 && +#if UIP_REASSEMBLY > 0 + fw->len == BUF->len && + fw->offset == BUF->ipoffset && +#endif + fw->ipid == BUF->ipid && + fw->srcipaddr[0] == BUF->srcipaddr[0] && + fw->srcipaddr[1] == BUF->srcipaddr[1] && + fw->destipaddr[0] == BUF->destipaddr[0] && + fw->destipaddr[1] == BUF->destipaddr[1] && +#if notdef + fw->payload[0] == BUF->srcport && + fw->payload[1] == BUF->destport && +#endif + fw->proto == BUF->proto) { + /* Drop packet. */ + return UIP_FW_FORWARDED; + } + } + + /* If the TTL reaches zero we produce an ICMP time exceeded message + in the uip_buf buffer and forward that packet back to the sender + of the packet. */ + if(BUF->ttl <= 1) { + /* No time exceeded for broadcasts and multicasts! */ + if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { + return UIP_FW_LOCAL; + } + time_exceeded(); + } + + /* Decrement the TTL (time-to-live) value in the IP header */ + BUF->ttl = BUF->ttl - 1; + + /* Update the IP checksum. */ + if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) { + BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1; + } else { + BUF->ipchksum = BUF->ipchksum + HTONS(0x0100); + } + + if(uip_len > 0) { + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]; + uip_fw_output(); + } + +#if UIP_BROADCAST + if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { + return UIP_FW_LOCAL; + } +#endif /* UIP_BROADCAST */ + + /* Return non-zero to indicate that the packet was forwarded and that no + other processing should be made. */ + return UIP_FW_FORWARDED; +} +/*------------------------------------------------------------------------------*/ +/** + * Register a network interface with the forwarding module. + * + * \param netif A pointer to the network interface that is to be + * registered. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_register(struct uip_fw_netif *netif) +{ + netif->next = netifs; + netifs = netif; +} +/*------------------------------------------------------------------------------*/ +/** + * Register a default network interface. + * + * All packets that don't go out on any of the other interfaces will + * be routed to the default interface. + * + * \param netif A pointer to the network interface that is to be + * registered. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_default(struct uip_fw_netif *netif) +{ + defaultnetif = netif; +} +/*------------------------------------------------------------------------------*/ +/** + * Perform periodic processing. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_periodic(void) +{ + struct fwcache_entry *fw; + for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { + if(fw->timer > 0) { + --fw->timer; + } + } +} +/*------------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-fw.h (revision 14) @@ -0,0 +1,176 @@ +/** + * \addtogroup uipfw + * @{ + */ + +/** + * \file + * uIP packet forwarding header file. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: uip-fw.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ +#ifndef __UIP_FW_H__ +#define __UIP_FW_H__ + +#include "uip.h" + +/** + * Representation of a uIP network interface. + */ +struct uip_fw_netif { + struct uip_fw_netif *next; /**< Pointer to the next interface when + linked in a list. */ + u16_t ipaddr[2]; /**< The IP address of this interface. */ + u16_t netmask[2]; /**< The netmask of the interface. */ + u8_t (* output)(void); + /**< A pointer to the function that + sends a packet. */ +}; + +/** + * Intantiating macro for a uIP network interface. + * + * Example: + \code + struct uip_fw_netif slipnetif = + {UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)}; + \endcode + * \param ip1,ip2,ip3,ip4 The IP address of the network interface. + * + * \param nm1,nm2,nm3,nm4 The netmask of the network interface. + * + * \param outputfunc A pointer to the output function of the network interface. + * + * \hideinitializer + */ +#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \ + NULL, \ + {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \ + {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \ + outputfunc + +/** + * Set the IP address of a network interface. + * + * \param netif A pointer to the uip_fw_netif structure for the network interface. + * + * \param addr A pointer to an IP address. + * + * \hideinitializer + */ +#define uip_fw_setipaddr(netif, addr) \ + do { (netif)->ipaddr[0] = ((u16_t *)(addr))[0]; \ + (netif)->ipaddr[1] = ((u16_t *)(addr))[1]; } while(0) +/** + * Set the netmask of a network interface. + * + * \param netif A pointer to the uip_fw_netif structure for the network interface. + * + * \param addr A pointer to an IP address representing the netmask. + * + * \hideinitializer + */ +#define uip_fw_setnetmask(netif, addr) \ + do { (netif)->netmask[0] = ((u16_t *)(addr))[0]; \ + (netif)->netmask[1] = ((u16_t *)(addr))[1]; } while(0) + +void uip_fw_init(void); +u8_t uip_fw_forward(void); +u8_t uip_fw_output(void); +void uip_fw_register(struct uip_fw_netif *netif); +void uip_fw_default(struct uip_fw_netif *netif); +void uip_fw_periodic(void); + + +/** + * A non-error message that indicates that a packet should be + * processed locally. + * + * \hideinitializer + */ +#define UIP_FW_LOCAL 0 + +/** + * A non-error message that indicates that something went OK. + * + * \hideinitializer + */ +#define UIP_FW_OK 0 + +/** + * A non-error message that indicates that a packet was forwarded. + * + * \hideinitializer + */ +#define UIP_FW_FORWARDED 1 + +/** + * A non-error message that indicates that a zero-length packet + * transmission was attempted, and that no packet was sent. + * + * \hideinitializer + */ +#define UIP_FW_ZEROLEN 2 + +/** + * An error message that indicates that a packet that was too large + * for the outbound network interface was detected. + * + * \hideinitializer + */ +#define UIP_FW_TOOLARGE 3 + +/** + * An error message that indicates that no suitable interface could be + * found for an outbound packet. + * + * \hideinitializer + */ +#define UIP_FW_NOROUTE 4 + +/** + * An error message that indicates that a packet that should be + * forwarded or output was dropped. + * + * \hideinitializer + */ +#define UIP_FW_DROPPED 5 + + +#endif /* __UIP_FW_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/Makefile.include =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/Makefile.include (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/Makefile.include (revision 14) @@ -0,0 +1,47 @@ + + +ifdef APPS + APPDIRS = $(foreach APP, $(APPS), ../apps/$(APP)) + -include $(foreach APP, $(APPS), ../apps/$(APP)/Makefile.$(APP)) + CFLAGS += $(addprefix -I../apps/,$(APPS)) +endif + +ifndef CCDEP + CCDEP = $(CC) +endif +ifndef CCDEPCFLAGS + CCDEPCFLAGS = $(CFLAGS) +endif +ifndef OBJECTDIR + OBJECTDIR = obj +endif + +ifeq (${wildcard $(OBJECTDIR)},) + DUMMY := ${shell mkdir $(OBJECTDIR)} +endif + + +vpath %.c . ../uip ../lib $(APPDIRS) + +$(OBJECTDIR)/%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(OBJECTDIR)/%.d: %.c + @set -e; rm -f $@; \ + $(CCDEP) -MM $(CCDEPCFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,$(OBJECTDIR)/\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +UIP_SOURCES=uip.c uip_arp.c uiplib.c psock.c timer.c uip-neighbor.c + + +ifneq ($(MAKECMDGOALS),clean) +-include $(addprefix $(OBJECTDIR)/,$(UIP_SOURCES:.c=.d) \ + $(APP_SOURCES:.c=.d)) +endif + +uip.a: ${addprefix $(OBJECTDIR)/, $(UIP_SOURCES:.c=.o)} + $(AR) rcf $@ $^ + +apps.a: ${addprefix $(OBJECTDIR)/, $(APP_SOURCES:.c=.o)} + $(AR) rcf $@ $^ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.c (revision 14) @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +#include +#include + +#include "uipopt.h" +#include "psock.h" +#include "uip.h" + +#define STATE_NONE 0 +#define STATE_ACKED 1 +#define STATE_READ 2 +#define STATE_BLOCKED_NEWDATA 3 +#define STATE_BLOCKED_CLOSE 4 +#define STATE_BLOCKED_SEND 5 +#define STATE_DATA_SENT 6 + +/* + * Return value of the buffering functions that indicates that a + * buffer was not filled by incoming data. + * + */ +#define BUF_NOT_FULL 0 +#define BUF_NOT_FOUND 0 + +/* + * Return value of the buffering functions that indicates that a + * buffer was completely filled by incoming data. + * + */ +#define BUF_FULL 1 + +/* + * Return value of the buffering functions that indicates that an + * end-marker byte was found. + * + */ +#define BUF_FOUND 2 + +/*---------------------------------------------------------------------------*/ +static void +buf_setup(struct psock_buf *buf, + u8_t *bufptr, u16_t bufsize) +{ + buf->ptr = bufptr; + buf->left = bufsize; +} +/*---------------------------------------------------------------------------*/ +static u8_t +buf_bufdata(struct psock_buf *buf, u16_t len, + u8_t **dataptr, u16_t *datalen) +{ + ( void ) len; + if(*datalen < buf->left) { + memcpy(buf->ptr, *dataptr, *datalen); + buf->ptr += *datalen; + buf->left -= *datalen; + *dataptr += *datalen; + *datalen = 0; + return BUF_NOT_FULL; + } else if(*datalen == buf->left) { + memcpy(buf->ptr, *dataptr, *datalen); + buf->ptr += *datalen; + buf->left = 0; + *dataptr += *datalen; + *datalen = 0; + return BUF_FULL; + } else { + memcpy(buf->ptr, *dataptr, buf->left); + buf->ptr += buf->left; + *datalen -= buf->left; + *dataptr += buf->left; + buf->left = 0; + return BUF_FULL; + } +} +/*---------------------------------------------------------------------------*/ +static u8_t +buf_bufto(register struct psock_buf *buf, u8_t endmarker, + register u8_t **dataptr, register u16_t *datalen) +{ + u8_t c; + while(buf->left > 0 && *datalen > 0) { + c = *buf->ptr = **dataptr; + ++*dataptr; + ++buf->ptr; + --*datalen; + --buf->left; + + if(c == endmarker) { + return BUF_FOUND; + } + } + + if(*datalen == 0) { + return BUF_NOT_FOUND; + } + + while(*datalen > 0) { + c = **dataptr; + --*datalen; + ++*dataptr; + + if(c == endmarker) { + return BUF_FOUND | BUF_FULL; + } + } + + return BUF_FULL; +} +/*---------------------------------------------------------------------------*/ +static char +send_data(register struct psock *s) +{ + if(s->state != STATE_DATA_SENT || uip_rexmit()) { + if(s->sendlen > uip_mss()) { + uip_send(s->sendptr, uip_mss()); + } else { + uip_send(s->sendptr, s->sendlen); + } + s->state = STATE_DATA_SENT; + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static char +data_acked(register struct psock *s) +{ + if(s->state == STATE_DATA_SENT && uip_acked()) { + if(s->sendlen > uip_mss()) { + s->sendlen -= uip_mss(); + s->sendptr += uip_mss(); + } else { + s->sendptr += s->sendlen; + s->sendlen = 0; + } + s->state = STATE_ACKED; + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(psock_send(register struct psock *s, const char *buf, + unsigned int len)) +{ + PT_BEGIN(&s->psockpt); + + /* If there is no data to send, we exit immediately. */ + if(len == 0) { + PT_EXIT(&s->psockpt); + } + + /* Save the length of and a pointer to the data that is to be + sent. */ + s->sendptr = (unsigned char*)buf; + s->sendlen = len; + + s->state = STATE_NONE; + + /* We loop here until all data is sent. The s->sendlen variable is + updated by the data_sent() function. */ + while(s->sendlen > 0) { + + /* + * The condition for this PT_WAIT_UNTIL is a little tricky: the + * protothread will wait here until all data has been acknowledged + * (data_acked() returns true) and until all data has been sent + * (send_data() returns true). The two functions data_acked() and + * send_data() must be called in succession to ensure that all + * data is sent. Therefore the & operator is used instead of the + * && operator, which would cause only the data_acked() function + * to be called when it returns false. + */ + PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); + } + + s->state = STATE_NONE; + + PT_END(&s->psockpt); +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(psock_generator_send(register struct psock *s, + unsigned short (*generate)(void *), void *arg)) +{ + PT_BEGIN(&s->psockpt); + + /* Ensure that there is a generator function to call. */ + if(generate == NULL) { + PT_EXIT(&s->psockpt); + } + + /* Call the generator function to generate the data in the + uip_appdata buffer. */ + s->sendlen = generate(arg); + s->sendptr = uip_appdata; + + s->state = STATE_NONE; + do { + /* Call the generator function again if we are called to perform a + retransmission. */ + if(uip_rexmit()) { + generate(arg); + } + /* Wait until all data is sent and acknowledged. */ + PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s)); + } while(s->sendlen > 0); + + s->state = STATE_NONE; + + PT_END(&s->psockpt); +} +/*---------------------------------------------------------------------------*/ +u16_t +psock_datalen(struct psock *psock) +{ + return psock->bufsize - psock->buf.left; +} +/*---------------------------------------------------------------------------*/ +char +psock_newdata(struct psock *s) +{ + if(s->readlen > 0) { + /* There is data in the uip_appdata buffer that has not yet been + read with the PSOCK_READ functions. */ + return 1; + } else if(s->state == STATE_READ) { + /* All data in uip_appdata buffer already consumed. */ + s->state = STATE_BLOCKED_NEWDATA; + return 0; + } else if(uip_newdata()) { + /* There is new data that has not been consumed. */ + return 1; + } else { + /* There is no new data. */ + return 0; + } +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(psock_readto(register struct psock *psock, unsigned char c)) +{ + PT_BEGIN(&psock->psockpt); + + buf_setup(&psock->buf, (unsigned char*)psock->bufptr, psock->bufsize); + + /* XXX: Should add buf_checkmarker() before do{} loop, if + incoming data has been handled while waiting for a write. */ + + do { + if(psock->readlen == 0) { + PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); + psock->state = STATE_READ; + psock->readptr = (u8_t *)uip_appdata; + psock->readlen = uip_datalen(); + } + } while((buf_bufto(&psock->buf, c, + &psock->readptr, + &psock->readlen) & BUF_FOUND) == 0); + + if(psock_datalen(psock) == 0) { + psock->state = STATE_NONE; + PT_RESTART(&psock->psockpt); + } + PT_END(&psock->psockpt); +} +/*---------------------------------------------------------------------------*/ +PT_THREAD(psock_readbuf(register struct psock *psock)) +{ + PT_BEGIN(&psock->psockpt); + + buf_setup(&psock->buf, (unsigned char * ) psock->bufptr, psock->bufsize); + + /* XXX: Should add buf_checkmarker() before do{} loop, if + incoming data has been handled while waiting for a write. */ + + do { + if(psock->readlen == 0) { + PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock)); + printf("Waited for newdata\n"); + psock->state = STATE_READ; + psock->readptr = (u8_t *)uip_appdata; + psock->readlen = uip_datalen(); + } + } while(buf_bufdata(&psock->buf, psock->bufsize, + &psock->readptr, + &psock->readlen) != BUF_FULL); + + if(psock_datalen(psock) == 0) { + psock->state = STATE_NONE; + PT_RESTART(&psock->psockpt); + } + PT_END(&psock->psockpt); +} +/*---------------------------------------------------------------------------*/ +void +psock_init(register struct psock *psock, char *buffer, unsigned int buffersize) +{ + psock->state = STATE_NONE; + psock->readlen = 0; + psock->bufptr = buffer; + psock->bufsize = buffersize; + buf_setup(&psock->buf, (unsigned char*) buffer, buffersize); + PT_INIT(&psock->pt); + PT_INIT(&psock->psockpt); +} +/*---------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.c (revision 14) @@ -0,0 +1,127 @@ +/** + * \addtogroup timer + * @{ + */ + +/** + * \file + * Timer library implementation. + * \author + * Adam Dunkels + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +#include "clock.h" +#include "timer.h" + +/*---------------------------------------------------------------------------*/ +/** + * Set a timer. + * + * This function is used to set a timer for a time sometime in the + * future. The function timer_expired() will evaluate to true after + * the timer has expired. + * + * \param t A pointer to the timer + * \param interval The interval before the timer expires. + * + */ +void +timer_set(struct timer *t, clock_time_t interval) +{ + t->interval = interval; + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Reset the timer with the same interval. + * + * This function resets the timer with the same interval that was + * given to the timer_set() function. The start point of the interval + * is the exact time that the timer last expired. Therefore, this + * function will cause the timer to be stable over time, unlike the + * timer_rester() function. + * + * \param t A pointer to the timer. + * + * \sa timer_restart() + */ +void +timer_reset(struct timer *t) +{ + t->start += t->interval; +} +/*---------------------------------------------------------------------------*/ +/** + * Restart the timer from the current point in time + * + * This function restarts a timer with the same interval that was + * given to the timer_set() function. The timer will start at the + * current time. + * + * \note A periodic timer will drift if this function is used to reset + * it. For preioric timers, use the timer_reset() function instead. + * + * \param t A pointer to the timer. + * + * \sa timer_reset() + */ +void +timer_restart(struct timer *t) +{ + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if a timer has expired. + * + * This function tests if a timer has expired and returns true or + * false depending on its status. + * + * \param t A pointer to the timer + * + * \return Non-zero if the timer has expired, zero otherwise. + * + */ +int +timer_expired(struct timer *t) +{ + return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; +} +/*---------------------------------------------------------------------------*/ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.c (revision 14) @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004, Adam Dunkels and the Swedish Institute of + * Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uiplib.c,v 1.2 2006/06/12 08:00:31 adam Exp $ + * + */ + + +#include "uip.h" +#include "uiplib.h" + + +/*-----------------------------------------------------------------------------------*/ +unsigned char +uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr) +{ + unsigned char tmp; + char c; + unsigned char i, j; + + tmp = 0; + + for(i = 0; i < 4; ++i) { + j = 0; + do { + c = *addrstr; + ++j; + if(j > 4) { + return 0; + } + if(c == '.' || c == 0) { + *ipaddr = tmp; + ++ipaddr; + tmp = 0; + } else if(c >= '0' && c <= '9') { + tmp = (tmp * 10) + (c - '0'); + } else { + return 0; + } + ++addrstr; + } while(c != '.' && c != 0); + } + return 1; +} + +/*-----------------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/psock.h (revision 14) @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \defgroup psock Protosockets library + * @{ + * + * The protosocket library provides an interface to the uIP stack that is + * similar to the traditional BSD socket interface. Unlike programs + * written for the ordinary uIP event-driven interface, programs + * written with the protosocket library are executed in a sequential + * fashion and does not have to be implemented as explicit state + * machines. + * + * Protosockets only work with TCP connections. + * + * The protosocket library uses \ref pt protothreads to provide + * sequential control flow. This makes the protosockets lightweight in + * terms of memory, but also means that protosockets inherits the + * functional limitations of protothreads. Each protosocket lives only + * within a single function. Automatic variables (stack variables) are + * not retained across a protosocket library function call. + * + * \note Because the protosocket library uses protothreads, local + * variables will not always be saved across a call to a protosocket + * library function. It is therefore advised that local variables are + * used with extreme care. + * + * The protosocket library provides functions for sending data without + * having to deal with retransmissions and acknowledgements, as well + * as functions for reading data without having to deal with data + * being split across more than one TCP segment. + * + * Because each protosocket runs as a protothread, the protosocket has to be + * started with a call to PSOCK_BEGIN() at the start of the function + * in which the protosocket is used. Similarly, the protosocket protothread can + * be terminated by a call to PSOCK_EXIT(). + * + */ + +/** + * \file + * Protosocket library header file + * \author + * Adam Dunkels + * + */ + +#ifndef __PSOCK_H__ +#define __PSOCK_H__ + +#include "uipopt.h" +#include "pt.h" + + /* + * The structure that holds the state of a buffer. + * + * This structure holds the state of a uIP buffer. The structure has + * no user-visible elements, but is used through the functions + * provided by the library. + * + */ +struct psock_buf { + u8_t *ptr; + unsigned short left; +}; + +/** + * The representation of a protosocket. + * + * The protosocket structrure is an opaque structure with no user-visible + * elements. + */ +struct psock { + struct pt pt, psockpt; /* Protothreads - one that's using the psock + functions, and one that runs inside the + psock functions. */ + const u8_t *sendptr; /* Pointer to the next data to be sent. */ + u8_t *readptr; /* Pointer to the next data to be read. */ + + char *bufptr; /* Pointer to the buffer used for buffering + incoming data. */ + + u16_t sendlen; /* The number of bytes left to be sent. */ + u16_t readlen; /* The number of bytes left to be read. */ + + struct psock_buf buf; /* The structure holding the state of the + input buffer. */ + unsigned int bufsize; /* The size of the input buffer. */ + + unsigned char state; /* The state of the protosocket. */ +}; + +void psock_init(struct psock *psock, char *buffer, unsigned int buffersize); +/** + * Initialize a protosocket. + * + * This macro initializes a protosocket and must be called before the + * protosocket is used. The initialization also specifies the input buffer + * for the protosocket. + * + * \param psock (struct psock *) A pointer to the protosocket to be + * initialized + * + * \param buffer (char *) A pointer to the input buffer for the + * protosocket. + * + * \param buffersize (unsigned int) The size of the input buffer. + * + * \hideinitializer + */ +#define PSOCK_INIT(psock, buffer, buffersize) \ + psock_init(psock, buffer, buffersize) + +/** + * Start the protosocket protothread in a function. + * + * This macro starts the protothread associated with the protosocket and + * must come before other protosocket calls in the function it is used. + * + * \param psock (struct psock *) A pointer to the protosocket to be + * started. + * + * \hideinitializer + */ +#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt)) + +PT_THREAD(psock_send(struct psock *psock, const char *buf, unsigned int len)); +/** + * Send data. + * + * This macro sends data over a protosocket. The protosocket protothread blocks + * until all data has been sent and is known to have been received by + * the remote end of the TCP connection. + * + * \param psock (struct psock *) A pointer to the protosocket over which + * data is to be sent. + * + * \param data (char *) A pointer to the data that is to be sent. + * + * \param datalen (unsigned int) The length of the data that is to be + * sent. + * + * \hideinitializer + */ +#define PSOCK_SEND(psock, data, datalen) \ + PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen)) + +/** + * \brief Send a null-terminated string. + * \param psock Pointer to the protosocket. + * \param str The string to be sent. + * + * This function sends a null-terminated string over the + * protosocket. + * + * \hideinitializer + */ +#define PSOCK_SEND_STR(psock, str) \ + PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str))) + +PT_THREAD(psock_generator_send(struct psock *psock, + unsigned short (*f)(void *), void *arg)); + +/** + * \brief Generate data with a function and send it + * \param psock Pointer to the protosocket. + * \param generator Pointer to the generator function + * \param arg Argument to the generator function + * + * This function generates data and sends it over the + * protosocket. This can be used to dynamically generate + * data for a transmission, instead of generating the data + * in a buffer beforehand. This function reduces the need for + * buffer memory. The generator function is implemented by + * the application, and a pointer to the function is given + * as an argument with the call to PSOCK_GENERATOR_SEND(). + * + * The generator function should place the generated data + * directly in the uip_appdata buffer, and return the + * length of the generated data. The generator function is + * called by the protosocket layer when the data first is + * sent, and once for every retransmission that is needed. + * + * \hideinitializer + */ +#define PSOCK_GENERATOR_SEND(psock, generator, arg) \ + PT_WAIT_THREAD(&((psock)->pt), \ + psock_generator_send(psock, generator, arg)) + + +/** + * Close a protosocket. + * + * This macro closes a protosocket and can only be called from within the + * protothread in which the protosocket lives. + * + * \param psock (struct psock *) A pointer to the protosocket that is to + * be closed. + * + * \hideinitializer + */ +#define PSOCK_CLOSE(psock) uip_close() + +PT_THREAD(psock_readbuf(struct psock *psock)); +/** + * Read data until the buffer is full. + * + * This macro will block waiting for data and read the data into the + * input buffer specified with the call to PSOCK_INIT(). Data is read + * until the buffer is full.. + * + * \param psock (struct psock *) A pointer to the protosocket from which + * data should be read. + * + * \hideinitializer + */ +#define PSOCK_READBUF(psock) \ + PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock)) + +PT_THREAD(psock_readto(struct psock *psock, unsigned char c)); +/** + * Read data up to a specified character. + * + * This macro will block waiting for data and read the data into the + * input buffer specified with the call to PSOCK_INIT(). Data is only + * read until the specifieed character appears in the data stream. + * + * \param psock (struct psock *) A pointer to the protosocket from which + * data should be read. + * + * \param c (char) The character at which to stop reading. + * + * \hideinitializer + */ +#define PSOCK_READTO(psock, c) \ + PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c)) + +/** + * The length of the data that was previously read. + * + * This macro returns the length of the data that was previously read + * using PSOCK_READTO() or PSOCK_READ(). + * + * \param psock (struct psock *) A pointer to the protosocket holding the data. + * + * \hideinitializer + */ +#define PSOCK_DATALEN(psock) psock_datalen(psock) + +u16_t psock_datalen(struct psock *psock); + +/** + * Exit the protosocket's protothread. + * + * This macro terminates the protothread of the protosocket and should + * almost always be used in conjunction with PSOCK_CLOSE(). + * + * \sa PSOCK_CLOSE_EXIT() + * + * \param psock (struct psock *) A pointer to the protosocket. + * + * \hideinitializer + */ +#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt)) + +/** + * Close a protosocket and exit the protosocket's protothread. + * + * This macro closes a protosocket and exits the protosocket's protothread. + * + * \param psock (struct psock *) A pointer to the protosocket. + * + * \hideinitializer + */ +#define PSOCK_CLOSE_EXIT(psock) \ + do { \ + PSOCK_CLOSE(psock); \ + PSOCK_EXIT(psock); \ + } while(0) + +/** + * Declare the end of a protosocket's protothread. + * + * This macro is used for declaring that the protosocket's protothread + * ends. It must always be used together with a matching PSOCK_BEGIN() + * macro. + * + * \param psock (struct psock *) A pointer to the protosocket. + * + * \hideinitializer + */ +#define PSOCK_END(psock) PT_END(&((psock)->pt)) + +char psock_newdata(struct psock *s); + +/** + * Check if new data has arrived on a protosocket. + * + * This macro is used in conjunction with the PSOCK_WAIT_UNTIL() + * macro to check if data has arrived on a protosocket. + * + * \param psock (struct psock *) A pointer to the protosocket. + * + * \hideinitializer + */ +#define PSOCK_NEWDATA(psock) psock_newdata(psock) + +/** + * Wait until a condition is true. + * + * This macro blocks the protothread until the specified condition is + * true. The macro PSOCK_NEWDATA() can be used to check if new data + * arrives when the protosocket is waiting. + * + * Typically, this macro is used as follows: + * + \code + PT_THREAD(thread(struct psock *s, struct timer *t)) + { + PSOCK_BEGIN(s); + + PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t)); + + if(PSOCK_NEWDATA(s)) { + PSOCK_READTO(s, '\n'); + } else { + handle_timed_out(s); + } + + PSOCK_END(s); + } + \endcode + * + * \param psock (struct psock *) A pointer to the protosocket. + * \param condition The condition to wait for. + * + * \hideinitializer + */ +#define PSOCK_WAIT_UNTIL(psock, condition) \ + PT_WAIT_UNTIL(&((psock)->pt), (condition)); + +#define PSOCK_WAIT_THREAD(psock, condition) \ + PT_WAIT_THREAD(&((psock)->pt), (condition)) + +#endif /* __PSOCK_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/timer.h (revision 14) @@ -0,0 +1,86 @@ +/** + * \defgroup timer Timer library + * + * The timer library provides functions for setting, resetting and + * restarting timers, and for checking if a timer has expired. An + * application must "manually" check if its timers have expired; this + * is not done automatically. + * + * A timer is declared as a \c struct \c timer and all access to the + * timer is made by a pointer to the declared timer. + * + * \note The timer library uses the \ref clock "Clock library" to + * measure time. Intervals should be specified in the format used by + * the clock library. + * + * @{ + */ + + +/** + * \file + * Timer library header file. + * \author + * Adam Dunkels + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include "clock.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with timer_set() before it can be used. + * + * \hideinitializer + */ +struct timer { + clock_time_t start; + clock_time_t interval; +}; + +void timer_set(struct timer *t, clock_time_t interval); +void timer_reset(struct timer *t); +void timer_restart(struct timer *t); +int timer_expired(struct timer *t); + +#endif /* __TIMER_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uipopt.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uipopt.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uipopt.h (revision 14) @@ -0,0 +1,539 @@ +/** + * \defgroup uipopt Configuration options for uIP + * @{ + * + * uIP is configured using the per-project configuration file + * uipopt.h. This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + * + * \note Most of the configuration options in the uipopt.h should not + * be changed, but rather the per-project uip-conf.h file. + */ + +/** + * \file + * Configuration options for uIP. + * \author Adam Dunkels + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $ + * + */ + +#ifndef __UIPOPT_H__ +#define __UIPOPT_H__ + +#ifndef UIP_LITTLE_ENDIAN +#define UIP_LITTLE_ENDIAN 3412 +#endif /* UIP_LITTLE_ENDIAN */ +#ifndef UIP_BIG_ENDIAN +#define UIP_BIG_ENDIAN 1234 +#endif /* UIP_BIG_ENDIAN */ + +#include "uip-conf.h" + +/*------------------------------------------------------------------------------*/ + +/** + * \name Static configuration options + * @{ + * + * These configuration options can be used for setting the IP address + * settings statically, but only if UIP_FIXEDADDR is set to 1. The + * configuration options for a specific node includes IP address, + * netmask and default router as well as the Ethernet address. The + * netmask, default router and Ethernet address are appliciable only + * if uIP should be run over Ethernet. + * + * All of these should be changed to suit your project. +*/ + +/** + * Determines if uIP should use a fixed IP address or not. + * + * If uIP should use a fixed IP address, the settings are set in the + * uipopt.h file. If not, the macros uip_sethostaddr(), + * uip_setdraddr() and uip_setnetmask() should be used instead. + * + * \hideinitializer + */ +#define UIP_FIXEDADDR 0 + +/** + * Ping IP address asignment. + * + * uIP uses a "ping" packets for setting its own IP address if this + * option is set. If so, uIP will start with an empty IP address and + * the destination IP address of the first incoming "ping" (ICMP echo) + * packet will be used for setting the hosts IP address. + * + * \note This works only if UIP_FIXEDADDR is 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_PINGADDRCONF +#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF +#else /* UIP_CONF_PINGADDRCONF */ +#define UIP_PINGADDRCONF 0 +#endif /* UIP_CONF_PINGADDRCONF */ + + +/** + * Specifies if the uIP ARP module should be compiled with a fixed + * Ethernet MAC address or not. + * + * If this configuration option is 0, the macro uip_setethaddr() can + * be used to specify the Ethernet address at run-time. + * + * \hideinitializer + */ +#define UIP_FIXEDETHADDR 0 + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name IP configuration options + * @{ + * + */ +/** + * The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ +#define UIP_TTL 64 + +/** + * Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the uip_buf buffer + * (configured by UIP_BUFSIZE). + * + * \note IP packet reassembly is not heavily tested. + * + * \hideinitializer + */ +#define UIP_REASSEMBLY 0 + +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 40 + +/** @} */ + +/*------------------------------------------------------------------------------*/ +/** + * \name UDP configuration options + * @{ + */ + +/** + * Toggles wether UDP support should be compiled in or not. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP +#define UIP_UDP UIP_CONF_UDP +#else /* UIP_CONF_UDP */ +#define UIP_UDP 0 +#endif /* UIP_CONF_UDP */ + +/** + * Toggles if UDP checksums should be used or not. + * + * \note Support for UDP checksums is currently not included in uIP, + * so this option has no function. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CHECKSUMS +#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS +#else +#define UIP_UDP_CHECKSUMS 0 +#endif + +/** + * The maximum amount of concurrent UDP connections. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CONNS +#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS +#else /* UIP_CONF_UDP_CONNS */ +#define UIP_UDP_CONNS 10 +#endif /* UIP_CONF_UDP_CONNS */ + +/** + * The name of the function that should be called when UDP datagrams arrive. + * + * \hideinitializer + */ + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name TCP configuration options + * @{ + */ + +/** + * Determines if support for opening connections from uIP should be + * compiled in. + * + * If the applications that are running on top of uIP for this project + * do not need to open outgoing TCP connections, this configration + * option can be turned off to reduce the code size of uIP. + * + * \hideinitializer + */ +#define UIP_ACTIVE_OPEN 1 + +/** + * The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_CONNECTIONS +#define UIP_CONNS 10 +#else /* UIP_CONF_MAX_CONNECTIONS */ +#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS +#endif /* UIP_CONF_MAX_CONNECTIONS */ + + +/** + * The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_LISTENPORTS +#define UIP_LISTENPORTS 20 +#else /* UIP_CONF_MAX_LISTENPORTS */ +#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS +#endif /* UIP_CONF_MAX_LISTENPORTS */ + +/** + * Determines if support for TCP urgent data notification should be + * compiled in. + * + * Urgent data (out-of-band data) is a rarely used TCP feature that + * very seldom would be required. + * + * \hideinitializer + */ +#define UIP_URGDATA 0 + +/** + * The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ +#define UIP_RTO 3 + +/** + * The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ +#define UIP_MAXRTX 8 + +/** + * The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ +#define UIP_MAXSYNRTX 5 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ +#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_RECEIVE_WINDOW UIP_TCP_MSS +#else +#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW +#endif + +/** + * How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. + */ +#define UIP_TIME_WAIT_TIMEOUT 120 + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name ARP configuration options + * @{ + */ + +/** + * The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + * + * \hideinitializer + */ +#ifdef UIP_CONF_ARPTAB_SIZE +#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE +#else +#define UIP_ARPTAB_SIZE 8 +#endif + +/** + * The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ +#define UIP_ARP_MAXAGE 120 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \name General configuration options + * @{ + */ + +/** + * The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + * + * \hideinitializer + */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_BUFSIZE 1500 +#else /* UIP_CONF_BUFFER_SIZE */ +#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE +#endif /* UIP_CONF_BUFFER_SIZE */ + + +/** + * Determines if statistics support should be compiled in. + * + * The statistics is useful for debugging and to show the user. + * + * \hideinitializer + */ +#ifndef UIP_CONF_STATISTICS +#define UIP_STATISTICS 0 +#else /* UIP_CONF_STATISTICS */ +#define UIP_STATISTICS UIP_CONF_STATISTICS +#endif /* UIP_CONF_STATISTICS */ + +/** + * Determines if logging of certain events should be compiled in. + * + * This is useful mostly for debugging. The function uip_log() + * must be implemented to suit the architecture of the project, if + * logging is turned on. + * + * \hideinitializer + */ +#ifndef UIP_CONF_LOGGING +#define UIP_LOGGING 0 +#else /* UIP_CONF_LOGGING */ +#define UIP_LOGGING UIP_CONF_LOGGING +#endif /* UIP_CONF_LOGGING */ + +/** + * Broadcast support. + * + * This flag configures IP broadcast support. This is useful only + * together with UDP. + * + * \hideinitializer + * + */ +#ifndef UIP_CONF_BROADCAST +#define UIP_BROADCAST 0 +#else /* UIP_CONF_BROADCAST */ +#define UIP_BROADCAST UIP_CONF_BROADCAST +#endif /* UIP_CONF_BROADCAST */ + +/** + * Print out a uIP log message. + * + * This function must be implemented by the module that uses uIP, and + * is called by uIP whenever a log message is generated. + */ +void uip_log(char *msg); + +/** + * The link level header length. + * + * This is the offset into the uip_buf where the IP header can be + * found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_LLH_LEN +#define UIP_LLH_LEN UIP_CONF_LLH_LEN +#else /* UIP_CONF_LLH_LEN */ +#define UIP_LLH_LEN 14 +#endif /* UIP_CONF_LLH_LEN */ + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name CPU architecture configuration + * @{ + * + * The CPU architecture configuration is where the endianess of the + * CPU on which uIP is to be run is specified. Most CPUs today are + * little endian, and the most notable exception are the Motorolas + * which are big endian. The BYTE_ORDER macro should be changed to + * reflect the CPU architecture on which uIP is to be run. + */ + +/** + * The byte order of the CPU architecture on which uIP is to be run. + * + * This option can be either BIG_ENDIAN (Motorola byte order) or + * LITTLE_ENDIAN (Intel byte order). + * + * \hideinitializer + */ +#ifdef UIP_CONF_BYTE_ORDER +#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER +#else /* UIP_CONF_BYTE_ORDER */ +#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif /* UIP_CONF_BYTE_ORDER */ + +/** @} */ +/*------------------------------------------------------------------------------*/ + +/** + * \name Appication specific configurations + * @{ + * + * An uIP application is implemented using a single application + * function that is called by uIP whenever a TCP/IP event occurs. The + * name of this function must be registered with uIP at compile time + * using the UIP_APPCALL definition. + * + * uIP applications can store the application state within the + * uip_conn structure by specifying the type of the application + * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t. + * + * The file containing the definitions must be included in the + * uipopt.h file. + * + * The following example illustrates how this can look. + \code + +void httpd_appcall(void); +#define UIP_APPCALL httpd_appcall + +struct httpd_state { + u8_t state; + u16_t count; + char *dataptr; + char *script; +}; +typedef struct httpd_state uip_tcp_appstate_t + \endcode + */ + +/** + * \var #define UIP_APPCALL + * + * The name of the application function that uIP should call in + * response to TCP/IP events. + * + */ + +/** + * \var typedef uip_tcp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ + +/** + * \var typedef uip_udp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ +/** @} */ +/** @} */ + +#endif /* __UIPOPT_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.c (revision 14) @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: uip-split.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +#include + +#include "uip-split.h" +#include "uip.h" +#include "uip-fw.h" +#include "uip_arch.h" + + + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/*-----------------------------------------------------------------------------*/ +void +uip_split_output(void) +{ + u16_t tcplen, len1, len2; + + /* We only try to split maximum sized TCP segments. */ + if(BUF->proto == UIP_PROTO_TCP && + uip_len == UIP_BUFSIZE - UIP_LLH_LEN) { + + tcplen = uip_len - UIP_TCPIP_HLEN; + /* Split the segment in two. If the original packet length was + odd, we make the second packet one byte larger. */ + len1 = len2 = tcplen / 2; + if(len1 + len2 < tcplen) { + ++len2; + } + + /* Create the first packet. This is done by altering the length + field of the IP header and updating the checksums. */ + uip_len = len1 + UIP_TCPIP_HLEN; +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = uip_len >> 8; + BUF->len[1] = uip_len & 0xff; +#endif /* UIP_CONF_IPV6 */ + + /* Recalculate the TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#if !UIP_CONF_IPV6 + /* Recalculate the IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); +#endif /* UIP_CONF_IPV6 */ + + /* Transmit the first packet. */ + /* uip_fw_output();*/ + tcpip_output(); + + /* Now, create the second packet. To do this, it is not enough to + just alter the length field, but we must also update the TCP + sequence number and point the uip_appdata to a new place in + memory. This place is detemined by the length of the first + packet (len1). */ + uip_len = len2 + UIP_TCPIP_HLEN; +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = uip_len >> 8; + BUF->len[1] = uip_len & 0xff; +#endif /* UIP_CONF_IPV6 */ + + /* uip_appdata += len1;*/ + memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2); + + uip_add32(BUF->seqno, len1); + BUF->seqno[0] = uip_acc32[0]; + BUF->seqno[1] = uip_acc32[1]; + BUF->seqno[2] = uip_acc32[2]; + BUF->seqno[3] = uip_acc32[3]; + + /* Recalculate the TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#if !UIP_CONF_IPV6 + /* Recalculate the IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); +#endif /* UIP_CONF_IPV6 */ + + /* Transmit the second packet. */ + /* uip_fw_output();*/ + tcpip_output(); + } else { + /* uip_fw_output();*/ + tcpip_output(); + } + +} +/*-----------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.c (revision 14) @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \file + * Database of link-local neighbors, used by IPv6 code and + * to be used by a future ARP code rewrite. + * \author + * Adam Dunkels + */ + +#include "uip-neighbor.h" + +#include +#include + +#define MAX_TIME 128 + +#ifdef UIP_NEIGHBOR_CONF_ENTRIES +#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES +#else /* UIP_NEIGHBOR_CONF_ENTRIES */ +#define ENTRIES 8 +#endif /* UIP_NEIGHBOR_CONF_ENTRIES */ + +struct neighbor_entry { + uip_ipaddr_t ipaddr; + struct uip_neighbor_addr addr; + u8_t time; +}; +static struct neighbor_entry entries[ENTRIES]; + +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_init(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + entries[i].time = MAX_TIME; + } +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_periodic(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + if(entries[i].time < MAX_TIME) { + entries[i].time++; + } + } +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr) +{ + int i, oldest; + u8_t oldest_time; + + printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3], + addr->addr.addr[4], addr->addr.addr[5]); + + /* Find the first unused entry or the oldest used entry. */ + oldest_time = 0; + oldest = 0; + for(i = 0; i < ENTRIES; ++i) { + if(entries[i].time == MAX_TIME) { + oldest = i; + break; + } + if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) { + oldest = i; + break; + } + if(entries[i].time > oldest_time) { + oldest = i; + oldest_time = entries[i].time; + } + } + + /* Use the oldest or first free entry (either pointed to by the + "oldest" variable). */ + entries[oldest].time = 0; + uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr); + memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr)); +} +/*---------------------------------------------------------------------------*/ +static struct neighbor_entry * +find_entry(uip_ipaddr_t ipaddr) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) { + return &entries[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_update(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if(e != NULL) { + e->time = 0; + } +} +/*---------------------------------------------------------------------------*/ +struct uip_neighbor_addr * +uip_neighbor_lookup(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if(e != NULL) { + /* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", + e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3], + e->addr.addr.addr[4], e->addr.addr.addr[5]);*/ + + return &e->addr; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/pt.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/pt.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/pt.h (revision 14) @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2004-2005, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \file + * Protothreads implementation. + * \author + * Adam Dunkels + * + */ + +#ifndef __PT_H__ +#define __PT_H__ + +#include "lc.h" + +struct pt { + lc_t lc; +}; + +#define PT_WAITING 0 +#define PT_EXITED 1 +#define PT_ENDED 2 +#define PT_YIELDED 3 + +/** + * \name Initialization + * @{ + */ + +/** + * Initialize a protothread. + * + * Initializes a protothread. Initialization must be done prior to + * starting to execute the protothread. + * + * \param pt A pointer to the protothread control structure. + * + * \sa PT_SPAWN() + * + * \hideinitializer + */ +#define PT_INIT(pt) LC_INIT((pt)->lc) + +/** @} */ + +/** + * \name Declaration and definition + * @{ + */ + +/** + * Declaration of a protothread. + * + * This macro is used to declare a protothread. All protothreads must + * be declared with this macro. + * + * \param name_args The name and arguments of the C function + * implementing the protothread. + * + * \hideinitializer + */ +#define PT_THREAD(name_args) char name_args + +/** + * Declare the start of a protothread inside the C function + * implementing the protothread. + * + * This macro is used to declare the starting point of a + * protothread. It should be placed at the start of the function in + * which the protothread runs. All C statements above the PT_BEGIN() + * invokation will be executed each time the protothread is scheduled. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc) + +/** + * Declare the end of a protothread. + * + * This macro is used for declaring that a protothread ends. It must + * always be used together with a matching PT_BEGIN() macro. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \ + PT_INIT(pt); return PT_ENDED; } + +/** @} */ + +/** + * \name Blocked wait + * @{ + */ + +/** + * Block and wait until condition is true. + * + * This macro blocks the protothread until the specified condition is + * true. + * + * \param pt A pointer to the protothread control structure. + * \param condition The condition. + * + * \hideinitializer + */ +#define PT_WAIT_UNTIL(pt, condition) \ + do { \ + LC_SET((pt)->lc); \ + if(!(condition)) { \ + return PT_WAITING; \ + } \ + } while(0) + +/** + * Block and wait while condition is true. + * + * This function blocks and waits while condition is true. See + * PT_WAIT_UNTIL(). + * + * \param pt A pointer to the protothread control structure. + * \param cond The condition. + * + * \hideinitializer + */ +#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) + +/** @} */ + +/** + * \name Hierarchical protothreads + * @{ + */ + +/** + * Block and wait until a child protothread completes. + * + * This macro schedules a child protothread. The current protothread + * will block until the child protothread completes. + * + * \note The child protothread must be manually initialized with the + * PT_INIT() function before this function is used. + * + * \param pt A pointer to the protothread control structure. + * \param thread The child protothread with arguments + * + * \sa PT_SPAWN() + * + * \hideinitializer + */ +#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread)) + +/** + * Spawn a child protothread and wait until it exits. + * + * This macro spawns a child protothread and waits until it exits. The + * macro can only be used within a protothread. + * + * \param pt A pointer to the protothread control structure. + * \param child A pointer to the child protothread's control structure. + * \param thread The child protothread with arguments + * + * \hideinitializer + */ +#define PT_SPAWN(pt, child, thread) \ + do { \ + PT_INIT((child)); \ + PT_WAIT_THREAD((pt), (thread)); \ + } while(0) + +/** @} */ + +/** + * \name Exiting and restarting + * @{ + */ + +/** + * Restart the protothread. + * + * This macro will block and cause the running protothread to restart + * its execution at the place of the PT_BEGIN() call. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_RESTART(pt) \ + do { \ + PT_INIT(pt); \ + return PT_WAITING; \ + } while(0) + +/** + * Exit the protothread. + * + * This macro causes the protothread to exit. If the protothread was + * spawned by another protothread, the parent protothread will become + * unblocked and can continue to run. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_EXIT(pt) \ + do { \ + PT_INIT(pt); \ + return PT_EXITED; \ + } while(0) + +/** @} */ + +/** + * \name Calling a protothread + * @{ + */ + +/** + * Schedule a protothread. + * + * This function shedules a protothread. The return value of the + * function is non-zero if the protothread is running or zero if the + * protothread has exited. + * + * \param f The call to the C function implementing the protothread to + * be scheduled + * + * \hideinitializer + */ +#define PT_SCHEDULE(f) ((f) == PT_WAITING) + +/** @} */ + +/** + * \name Yielding from a protothread + * @{ + */ + +/** + * Yield from the current protothread. + * + * This function will yield the protothread, thereby allowing other + * processing to take place in the system. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_YIELD(pt) \ + do { \ + PT_YIELD_FLAG = 0; \ + LC_SET((pt)->lc); \ + if(PT_YIELD_FLAG == 0) { \ + return PT_YIELDED; \ + } \ + } while(0) + +/** + * \brief Yield from the protothread until a condition occurs. + * \param pt A pointer to the protothread control structure. + * \param cond The condition. + * + * This function will yield the protothread, until the + * specified condition evaluates to true. + * + * + * \hideinitializer + */ +#define PT_YIELD_UNTIL(pt, cond) \ + do { \ + PT_YIELD_FLAG = 0; \ + LC_SET((pt)->lc); \ + if((PT_YIELD_FLAG == 0) || !(cond)) { \ + return PT_YIELDED; \ + } \ + } while(0) + +/** @} */ + +#endif /* __PT_H__ */ + +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uiplib.h (revision 14) @@ -0,0 +1,71 @@ +/** + * \file + * Various uIP library functions. + * \author + * Adam Dunkels + * + */ + +/* + * Copyright (c) 2002, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uiplib.h,v 1.1 2006/06/07 09:15:19 adam Exp $ + * + */ +#ifndef __UIPLIB_H__ +#define __UIPLIB_H__ + +/** + * \addtogroup uipconvfunc + * @{ + */ + +/** + * Convert a textual representation of an IP address to a numerical representation. + * + * This function takes a textual representation of an IP address in + * the form a.b.c.d and converts it into a 4-byte array that can be + * used by other uIP functions. + * + * \param addrstr A pointer to a string containing the IP address in + * textual form. + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the numerical representation of the address. + * + * \retval 0 If the IP address could not be parsed. + * \retval Non-zero If the IP address was parsed. + */ +unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr); + +/** @} */ + +#endif /* __UIPLIB_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-split.h (revision 14) @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: uip-split.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uipsplit uIP TCP throughput booster hack + * @{ + * + * The basic uIP TCP implementation only allows each TCP connection to + * have a single TCP segment in flight at any given time. Because of + * the delayed ACK algorithm employed by most TCP receivers, uIP's + * limit on the amount of in-flight TCP segments seriously reduces the + * maximum achievable throughput for sending data from uIP. + * + * The uip-split module is a hack which tries to remedy this + * situation. By splitting maximum sized outgoing TCP segments into + * two, the delayed ACK algorithm is not invoked at TCP + * receivers. This improves the throughput when sending data from uIP + * by orders of magnitude. + * + * The uip-split module uses the uip-fw module (uIP IP packet + * forwarding) for sending packets. Therefore, the uip-fw module must + * be set up with the appropriate network interfaces for this module + * to work. + */ + + +/** + * \file + * Module for splitting outbound TCP segments in two to avoid the + * delayed ACK throughput degradation. + * \author + * Adam Dunkels + * + */ + +#ifndef __UIP_SPLIT_H__ +#define __UIP_SPLIT_H__ + +/** + * Handle outgoing packets. + * + * This function inspects an outgoing packet in the uip_buf buffer and + * sends it out using the uip_fw_output() function. If the packet is a + * full-sized TCP segment it will be split into two segments and + * transmitted separately. This function should be called instead of + * the actual device driver output function, or the uip_fw_output() + * function. + * + * The headers of the outgoing packet is assumed to be in the uip_buf + * buffer and the payload is assumed to be wherever uip_appdata + * points. The length of the outgoing packet is assumed to be in the + * uip_len variable. + * + */ +void uip_split_output(void); + +#endif /* __UIP_SPLIT_H__ */ + +/** @} */ +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.h =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.h (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip-neighbor.h (revision 14) @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +/** + * \file + * Header file for database of link-local neighbors, used by + * IPv6 code and to be used by future ARP code. + * \author + * Adam Dunkels + */ + +#ifndef __UIP_NEIGHBOR_H__ +#define __UIP_NEIGHBOR_H__ + +#include "uip.h" + +struct uip_neighbor_addr { +#if UIP_NEIGHBOR_CONF_ADDRTYPE + UIP_NEIGHBOR_CONF_ADDRTYPE addr; +#else + struct uip_eth_addr addr; +#endif +}; + +void uip_neighbor_init(void); +void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr); +void uip_neighbor_update(uip_ipaddr_t ipaddr); +struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr); +void uip_neighbor_periodic(void); + +#endif /* __UIP-NEIGHBOR_H__ */ Index: /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.c (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/Common/ethernet/uIP/uip-1.0/uip/uip.c (revision 14) @@ -0,0 +1,1906 @@ +#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/ + +/** + * \defgroup uip The uIP TCP/IP stack + * @{ + * + * uIP is an implementation of the TCP/IP protocol stack intended for + * small 8-bit and 16-bit microcontrollers. + * + * uIP provides the necessary protocols for Internet communication, + * with a very small code footprint and RAM requirements - the uIP + * code size is on the order of a few kilobytes and RAM usage is on + * the order of a few hundred bytes. + */ + +/** + * \file + * The uIP TCP/IP stack code. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $ + * + */ + +/* + * uIP is a small implementation of the IP, UDP and TCP protocols (as + * well as some basic ICMP stuff). The implementation couples the IP, + * UDP, TCP and the application layers very tightly. To keep the size + * of the compiled code down, this code frequently uses the goto + * statement. While it would be possible to break the uip_process() + * function into many smaller functions, this would increase the code + * size because of the overhead of parameter passing and the fact that + * the optimier would not be as efficient. + * + * The principle is that we have a small buffer, called the uip_buf, + * in which the device driver puts an incoming packet. The TCP/IP + * stack parses the headers in the packet, and calls the + * application. If the remote host has sent data to the application, + * this data is present in the uip_buf and the application read the + * data from there. It is up to the application to put this data into + * a byte stream if needed. The application will not be fed with data + * that is out of sequence. + * + * If the application whishes to send data to the peer, it should put + * its data into the uip_buf. The uip_appdata pointer points to the + * first available byte. The TCP/IP stack will calculate the + * checksums, and fill in the necessary header fields and finally send + * the packet back to the peer. +*/ + +#include "uip.h" +#include "uipopt.h" +#include "uip_arch.h" + +#if UIP_CONF_IPV6 +#include "uip-neighbor.h" +#endif /* UIP_CONF_IPV6 */ + +#include + +/*---------------------------------------------------------------------------*/ +/* Variable definitions. */ + + +/* The IP address of this host. If it is defined to be fixed (by + setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set + here. Otherwise, the address */ +#if UIP_FIXEDADDR > 0 +const uip_ipaddr_t uip_hostaddr = + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; +const uip_ipaddr_t uip_draddr = + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; +const uip_ipaddr_t uip_netmask = + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; +#else +uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; +#endif /* UIP_FIXEDADDR */ + +static const uip_ipaddr_t all_ones_addr = +#if UIP_CONF_IPV6 + {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; +#else /* UIP_CONF_IPV6 */ + {0xffff,0xffff}; +#endif /* UIP_CONF_IPV6 */ +static const uip_ipaddr_t all_zeroes_addr = +#if UIP_CONF_IPV6 + {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; +#else /* UIP_CONF_IPV6 */ + {0x0000,0x0000}; +#endif /* UIP_CONF_IPV6 */ + +#if UIP_FIXEDETHADDR +const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, + UIP_ETHADDR1, + UIP_ETHADDR2, + UIP_ETHADDR3, + UIP_ETHADDR4, + UIP_ETHADDR5}}; +#else +struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; +#endif + +#ifndef UIP_CONF_EXTERNAL_BUFFER + +#ifdef __ICCARM__ + #pragma data_alignment=4 + u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */ +#else + u8_t uip_buf[UIP_BUFSIZE + 2] ALIGN_STRUCT_END; /* The packet buffer that contains incoming packets. */ +#endif + +#endif /* UIP_CONF_EXTERNAL_BUFFER */ + +void *uip_appdata; /* The uip_appdata pointer points to + application data. */ +void *uip_sappdata; /* The uip_appdata pointer points to + the application data which is to + be sent. */ +#if UIP_URGDATA > 0 +void *uip_urgdata; /* The uip_urgdata pointer points to + urgent data (out-of-band data), if + present. */ +u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + +u16_t uip_len, uip_slen; + /* The uip_len is either 8 or 16 bits, + depending on the maximum packet + size. */ + +u8_t uip_flags; /* The uip_flags variable is used for + communication between the TCP/IP stack + and the application program. */ +struct uip_conn *uip_conn; /* uip_conn always points to the current + connection. */ + +struct uip_conn uip_conns[UIP_CONNS]; + /* The uip_conns array holds all TCP + connections. */ +u16_t uip_listenports[UIP_LISTENPORTS]; + /* The uip_listenports list all currently + listning ports. */ +#if UIP_UDP +struct uip_udp_conn *uip_udp_conn; +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +static u16_t ipid; /* Ths ipid variable is an increasing + number that is used for the IP ID + field. */ + +void uip_setipid(u16_t id) { ipid = id; } + +static u8_t iss[4]; /* The iss variable is used for the TCP + initial sequence number. */ + +#if UIP_ACTIVE_OPEN +static u16_t lastport; /* Keeps track of the last port used for + a new connection. */ +#endif /* UIP_ACTIVE_OPEN */ + +/* Temporary variables. */ +u8_t uip_acc32[4]; +static u8_t c, opt; +static u16_t tmp16; + +/* Structures and definitions. */ +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +#define TCP_OPT_END 0 /* End of TCP options list */ +#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ +#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ + +#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +#define ICMP6_ECHO_REPLY 129 +#define ICMP6_ECHO 128 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 + +#define ICMP6_FLAG_S (1 << 6) + +#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 +#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 + + +/* Macros. */ +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) +#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + + +#if UIP_STATISTICS == 1 +struct uip_stats uip_stat; +#define UIP_STAT(s) s +#else +#define UIP_STAT(s) +#endif /* UIP_STATISTICS == 1 */ + +#if UIP_LOGGING == 1 +#include +void uip_log(char *msg); +#define UIP_LOG(m) uip_log(m) +#else +#define UIP_LOG(m) +#endif /* UIP_LOGGING == 1 */ + +#if ! UIP_ARCH_ADD32 +void +uip_add32(u8_t *op32, u16_t op16) +{ + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if(uip_acc32[2] < (op16 >> 8)) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + + + if(uip_acc32[3] < (op16 & 0xff)) { + ++uip_acc32[2]; + if(uip_acc32[2] == 0) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + } +} + +#endif /* UIP_ARCH_ADD32 */ + +#if ! UIP_ARCH_CHKSUM +/*---------------------------------------------------------------------------*/ +static u16_t +chksum(u16_t sum, const u8_t *data, u16_t len) +{ + u16_t t; + const u8_t *dataptr; + const u8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} +/*---------------------------------------------------------------------------*/ +u16_t +uip_chksum(u16_t *data, u16_t len) +{ + return htons(chksum(0, (u8_t *)data, len)); +} +/*---------------------------------------------------------------------------*/ +#ifndef UIP_ARCH_IPCHKSUM +u16_t +uip_ipchksum(void) +{ + u16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif +/*---------------------------------------------------------------------------*/ +static u16_t +upper_layer_chksum(u8_t proto) +{ + u16_t upper_layer_len; + u16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ + sum = upper_layer_len + proto; + /* Sum IP source and destination addresses. */ + sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], + upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} +/*---------------------------------------------------------------------------*/ +#if UIP_CONF_IPV6 +u16_t +uip_icmp6chksum(void) +{ + return upper_layer_chksum(UIP_PROTO_ICMP6); + +} +#endif /* UIP_CONF_IPV6 */ +/*---------------------------------------------------------------------------*/ +u16_t +uip_tcpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_TCP); +} +/*---------------------------------------------------------------------------*/ +#if UIP_UDP_CHECKSUMS +u16_t +uip_udpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_UDP); +} +#endif /* UIP_UDP_CHECKSUMS */ +#endif /* UIP_ARCH_CHKSUM */ +/*---------------------------------------------------------------------------*/ +void +uip_init(void) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + uip_listenports[c] = 0; + } + for(c = 0; c < UIP_CONNS; ++c) { + uip_conns[c].tcpstateflags = UIP_CLOSED; + } +#if UIP_ACTIVE_OPEN + lastport = 1024; +#endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP + for(c = 0; c < UIP_UDP_CONNS; ++c) { + uip_udp_conns[c].lport = 0; + } +#endif /* UIP_UDP */ + + + /* IPv4 initialization. */ +#if UIP_FIXEDADDR == 0 + /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ +#endif /* UIP_FIXEDADDR */ + +} +/*---------------------------------------------------------------------------*/ +#if UIP_ACTIVE_OPEN +struct uip_conn * +uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_conn *conn, *cconn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + /* Check if this port is already in use, and if so try to find + another one. */ + for(c = 0; c < UIP_CONNS; ++c) { + conn = &uip_conns[c]; + if(conn->tcpstateflags != UIP_CLOSED && + conn->lport == htons(lastport)) { + goto again; + } + } + + conn = 0; + for(c = 0; c < UIP_CONNS; ++c) { + cconn = &uip_conns[c]; + if(cconn->tcpstateflags == UIP_CLOSED) { + conn = cconn; + break; + } + if(cconn->tcpstateflags == UIP_TIME_WAIT) { + if(conn == 0 || + cconn->timer > conn->timer) { + conn = cconn; + } + } + } + + if(conn == 0) { + return 0; + } + + conn->tcpstateflags = UIP_SYN_SENT; + + conn->snd_nxt[0] = iss[0]; + conn->snd_nxt[1] = iss[1]; + conn->snd_nxt[2] = iss[2]; + conn->snd_nxt[3] = iss[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons(lastport); + conn->rport = rport; + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + + return conn; +} +#endif /* UIP_ACTIVE_OPEN */ +/*---------------------------------------------------------------------------*/ +#if UIP_UDP +struct uip_udp_conn * +uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_udp_conn *conn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == htons(lastport)) { + goto again; + } + } + + + conn = 0; + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == 0) { + conn = &uip_udp_conns[c]; + break; + } + } + + if(conn == 0) { + return 0; + } + + conn->lport = HTONS(lastport); + conn->rport = rport; + if(ripaddr == NULL) { + memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); + } else { + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + } + conn->ttl = UIP_TTL; + + return conn; +} +#endif /* UIP_UDP */ +/*---------------------------------------------------------------------------*/ +void +uip_unlisten(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == port) { + uip_listenports[c] = 0; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +void +uip_listen(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == 0) { + uip_listenports[c] = port; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/* XXX: IP fragment reassembly: not well-tested. */ + +#if UIP_REASSEMBLY && !UIP_CONF_IPV6 +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, + 0x0f, 0x07, 0x03, 0x01}; +static u16_t uip_reasslen; +static u8_t uip_reassflags; +#define UIP_REASS_FLAG_LASTFRAG 0x01 +static u8_t uip_reasstmr; + +#define IP_MF 0x20 + +static u8_t +uip_reass(void) +{ + u16_t offset, len; + u16_t i; + + /* If ip_reasstmr is zero, no packet is present in the buffer, so we + write the IP header of the fragment into the reassembly + buffer. The timer is updated with the maximum age. */ + if(uip_reasstmr == 0) { + memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + /* Clear the bitmap. */ + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); + } + + /* Check if the incoming fragment matches the one currently present + in the reasembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && + BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && + BUF->ipid[1] == FBUF->ipid[1]) { + + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + reassembly buffer, we discard the entire packet. */ + if(offset > UIP_REASS_BUFSIZE || + offset + len > UIP_REASS_BUFSIZE) { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right + offset. */ + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), + len); + + /* Update the bitmap. */ + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { + /* If the two endpoints are in the same byte, we only update + that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } else { + /* If the two endpoints are in different bytes, we update the + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7]; + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we + know that this is the last fragment, so we can calculate the + size of the entire packet. We also set the + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received + the final fragment. */ + + if((BUF->ipoffset[0] & IP_MF) == 0) { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do + this by checking if we have the last fragment and if all bits + in the bitmap are set. */ + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { + /* Check all bytes up to and including all but the last byte in + the bitmap. */ + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { + if(uip_reassbitmap[i] != 0xff) { + goto nullreturn; + } + } + /* Check the last byte in the bitmap. It should contain just the + right amount of bits. */ + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet + from now on. */ + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } + } + + nullreturn: + return 0; +} +#endif /* UIP_REASSEMBLY */ +/*---------------------------------------------------------------------------*/ +static void +uip_add_rcv_nxt(u16_t n) +{ + uip_add32(uip_conn->rcv_nxt, n); + uip_conn->rcv_nxt[0] = uip_acc32[0]; + uip_conn->rcv_nxt[1] = uip_acc32[1]; + uip_conn->rcv_nxt[2] = uip_acc32[2]; + uip_conn->rcv_nxt[3] = uip_acc32[3]; +} +/*---------------------------------------------------------------------------*/ +void +uip_process(u8_t flag) +{ + register struct uip_conn *uip_connr = uip_conn; + +#if UIP_UDP + if(flag == UIP_UDP_SEND_CONN) { + goto udp_send; + } +#endif /* UIP_UDP */ + + uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + /* Check if we were invoked because of a poll request for a + particular connection. */ + if(flag == UIP_POLL_REQUEST) { + if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && + !uip_outstanding(uip_connr)) { + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + goto drop; + + /* Check if we were invoked because of the perodic timer fireing. */ + } else if(flag == UIP_TIMER) { +#if UIP_REASSEMBLY + if(uip_reasstmr != 0) { + --uip_reasstmr; + } +#endif /* UIP_REASSEMBLY */ + /* Increase the initial sequence number. */ + if(++iss[3] == 0) { + if(++iss[2] == 0) { + if(++iss[1] == 0) { + ++iss[0]; + } + } + } + + /* Reset the length variables. */ + uip_len = 0; + uip_slen = 0; + + /* Check if the connection is in a state in which we simply wait + for the connection to time out. If so, we increase the + connection's timer and remove the connection if it times + out. */ + if(uip_connr->tcpstateflags == UIP_TIME_WAIT || + uip_connr->tcpstateflags == UIP_FIN_WAIT_2) { + ++(uip_connr->timer); + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { + uip_connr->tcpstateflags = UIP_CLOSED; + } + } else if(uip_connr->tcpstateflags != UIP_CLOSED) { + /* If the connection has outstanding data, we increase the + connection's timer and see if it has reached the RTO value + in which case we retransmit. */ + if(uip_outstanding(uip_connr)) { + uip_connr->timer = uip_connr->timer - 1; + if(uip_connr->timer == 0) { + if(uip_connr->nrtx == UIP_MAXRTX || + ((uip_connr->tcpstateflags == UIP_SYN_SENT || + uip_connr->tcpstateflags == UIP_SYN_RCVD) && + uip_connr->nrtx == UIP_MAXSYNRTX)) { + uip_connr->tcpstateflags = UIP_CLOSED; + + /* We call UIP_APPCALL() with uip_flags set to + UIP_TIMEDOUT to inform the application that the + connection has timed out. */ + uip_flags = UIP_TIMEDOUT; + UIP_APPCALL(); + + /* We also send a reset packet to the remote host. */ + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + /* Exponential backoff. */ + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? + 4: + uip_connr->nrtx); + ++(uip_connr->nrtx); + + /* Ok, so we need to retransmit. We do this differently + depending on which state we are in. In ESTABLISHED, we + call upon the application so that it may prepare the + data for the retransmit. In SYN_RCVD, we resend the + SYNACK that we sent earlier and in LAST_ACK we have to + retransmit our FINACK. */ + UIP_STAT(++uip_stat.tcp.rexmit); + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our + SYNACK. */ + goto tcp_send_synack; + +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + BUF->flags = 0; + goto tcp_send_syn; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application + to do the actual retransmit after which we jump into + the code for sending out the packet (the apprexmit + label). */ + uip_flags = UIP_REXMIT; + UIP_APPCALL(); + goto apprexmit; + + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + goto tcp_send_finack; + + } + } + } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { + /* If there was no need for a retransmission, we poll the + application for new data. */ + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + } + goto drop; + } +#if UIP_UDP + if(flag == UIP_UDP_TIMER) { + if(uip_udp_conn->lport != 0) { + uip_conn = NULL; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_len = uip_slen = 0; + uip_flags = UIP_POLL; + UIP_UDP_APPCALL(); + goto udp_send; + } else { + goto drop; + } + } +#endif + + /* This is where the input processing starts. */ + UIP_STAT(++uip_stat.ip.recv); + + /* Start of IP input header processing code. */ + +#if UIP_CONF_IPV6 + /* Check validity of the IP header. */ + if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ipv6: invalid version."); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* Check validity of the IP header. */ + if(BUF->vhl != 0x45) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ip: invalid version or header length."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + /* Check the size of the packet. If the size reported to us in + uip_len is smaller the size reported in the IP header, we assume + that the packet has been corrupted in transit. If the size of + uip_len is larger than the size reported in the IP packet header, + the packet has been padded and we set uip_len to the correct + value.. */ + + if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { + uip_len = (BUF->len[0] << 8) + BUF->len[1]; +#if UIP_CONF_IPV6 + uip_len += 40; /* The length reported in the IPv6 header is the + length of the payload that follows the + header. However, uIP uses the uip_len variable + for holding the size of the entire packet, + including the IP header. For IPv4 this is not a + problem as the length field in the IPv4 header + contains the length of the entire packet. But + for IPv6 we need to add the size of the IPv6 + header (40 bytes). */ +#endif /* UIP_CONF_IPV6 */ + } else { + UIP_LOG("ip: packet shorter than reported in IP header."); + goto drop; + } + +#if !UIP_CONF_IPV6 + /* Check the fragment flag. */ + if((BUF->ipoffset[0] & 0x3f) != 0 || + BUF->ipoffset[1] != 0) { +#if UIP_REASSEMBLY + uip_len = uip_reass(); + if(uip_len == 0) { + goto drop; + } +#else /* UIP_REASSEMBLY */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; +#endif /* UIP_REASSEMBLY */ + } +#endif /* UIP_CONF_IPV6 */ + + if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) { + /* If we are configured to use ping IP address configuration and + hasn't been assigned an IP address yet, we accept all ICMP + packets. */ +#if UIP_PINGADDRCONF && !UIP_CONF_IPV6 + if(BUF->proto == UIP_PROTO_ICMP) { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } else { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } +#endif /* UIP_PINGADDRCONF */ + + } else { + /* If IP broadcast support is configured, we check for a broadcast + UDP packet, which may be destined to us. */ +#if UIP_BROADCAST + DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); + if(BUF->proto == UIP_PROTO_UDP && + uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) + /*&& + uip_ipchksum() == 0xffff*/) { + goto udp_input; + } +#endif /* UIP_BROADCAST */ + + /* Check if the packet is destined for our IP address. */ +#if !UIP_CONF_IPV6 + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* For IPv6, packet reception is a little trickier as we need to + make sure that we listen to certain multicast addresses (all + hosts multicast address, and the solicited-node multicast + address) as well. However, we will cheat here and accept all + multicast packets that are sent to the ff02::/16 addresses. */ + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && + BUF->destipaddr[0] != HTONS(0xff02)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + } + +#if !UIP_CONF_IPV6 + if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header + checksum. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.chkerr); + UIP_LOG("ip: bad checksum."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, + proceed with TCP input + processing. */ + goto tcp_input; + } + +#if UIP_UDP + if(BUF->proto == UIP_PROTO_UDP) { + goto udp_input; + } +#endif /* UIP_UDP */ + +#if !UIP_CONF_IPV6 + /* ICMPv4 processing code follows. */ + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp."); + goto drop; + } + +#if UIP_PINGADDRCONF + icmp_input: +#endif /* UIP_PINGADDRCONF */ + UIP_STAT(++uip_stat.icmp.recv); + + /* ICMP echo (i.e., ping) processing. This is simple, we only change + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP + checksum before we return the packet. */ + if(ICMPBUF->type != ICMP_ECHO) { + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: not icmp echo."); + goto drop; + } + + /* If we are configured to use ping IP address assignment, we use + the destination IP address of this ping packet and assign it to + ourself. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { + uip_hostaddr[0] = BUF->destipaddr[0]; + uip_hostaddr[1] = BUF->destipaddr[1]; + } +#endif /* UIP_PINGADDRCONF */ + + ICMPBUF->type = ICMP_ECHO_REPLY; + + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; + } else { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); + } + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + + /* End of IPv4 input header processing code. */ +#else /* !UIP_CONF_IPV6 */ + + /* This is IPv6 ICMPv6 processing code. */ + DEBUG_PRINTF("icmp6_input: length %d\n", uip_len); + + if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp6."); + goto drop; + } + + UIP_STAT(++uip_stat.icmp.recv); + + /* If we get a neighbor solicitation for our address we should send + a neighbor advertisement message back. */ + if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) { + if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) { + + if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { + /* Save the sender's address in our neighbor list. */ + uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); + } + + /* We should now send a neighbor advertisement back to where the + neighbor solicication came from. */ + ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ + + ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; + + uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); + uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr); + ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + goto send; + + } + goto drop; + } else if(ICMPBUF->type == ICMP6_ECHO) { + /* ICMP echo (i.e., ping) processing. This is simple, we only + change the ICMP type from ECHO to ECHO_REPLY and update the + ICMP checksum before we return the packet. */ + + ICMPBUF->type = ICMP6_ECHO_REPLY; + + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + } else { + DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type); + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: unknown ICMP message."); + goto drop; + } + + /* End of IPv6 ICMP processing. */ + +#endif /* !UIP_CONF_IPV6 */ + +#if UIP_UDP + /* UDP input processing. */ + udp_input: + /* UDP processing is really just a hack. We don't do anything to the + UDP/IP headers, but let the UDP application do all the hard + work. If the application sets uip_slen, it has a packet to + send. */ +#if UIP_UDP_CHECKSUMS + uip_len = uip_len - UIP_IPUDPH_LEN; + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } +#else /* UIP_UDP_CHECKSUMS */ + uip_len = uip_len - UIP_IPUDPH_LEN; +#endif /* UIP_UDP_CHECKSUMS */ + + /* Demultiplex this UDP packet between the UDP "connections". */ + for(uip_udp_conn = &uip_udp_conns[0]; + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; + ++uip_udp_conn) { + /* If the local UDP port is non-zero, the connection is considered + to be used. If so, the local port number is checked against the + destination port number in the received packet. If the two port + numbers match, the remote port number is checked if the + connection is bound to a remote port. Finally, if the + connection is bound to a remote IP address, the source IP + address of the packet is checked. */ + if(uip_udp_conn->lport != 0 && + UDPBUF->destport == uip_udp_conn->lport && + (uip_udp_conn->rport == 0 || + UDPBUF->srcport == uip_udp_conn->rport) && + (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || + uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || + uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) { + goto udp_found; + } + } + UIP_LOG("udp: no matching connection found"); + goto drop; + + udp_found: + UIP_STAT(++uip_stat.udp.recv); + uip_conn = NULL; + uip_flags = UIP_NEWDATA; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_slen = 0; + UIP_UDP_APPCALL(); + udp_send: + if(uip_slen == 0) { + goto drop; + } + uip_len = uip_slen + UIP_IPUDPH_LEN; + +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->ttl = uip_udp_conn->ttl; + BUF->proto = UIP_PROTO_UDP; + + UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); + UDPBUF->udpchksum = 0; + + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); + + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; + +#if UIP_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + UDPBUF->udpchksum = ~(uip_udpchksum()); + if(UDPBUF->udpchksum == 0) { + UDPBUF->udpchksum = 0xffff; + } +#endif /* UIP_UDP_CHECKSUMS */ + UIP_STAT(++uip_stat.udp.sent); + goto ip_send_nolen; +#endif /* UIP_UDP */ + + /* TCP input processing. */ + tcp_input: + UIP_STAT(++uip_stat.tcp.recv); + + /* Start of TCP input header processing code. */ + + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP + checksum. */ + UIP_STAT(++uip_stat.tcp.drop); + UIP_STAT(++uip_stat.tcp.chkerr); + UIP_LOG("tcp: bad checksum."); + goto drop; + } + + + /* Demultiplex this segment. */ + /* First check any active connections. */ + for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; + ++uip_connr) { + if(uip_connr->tcpstateflags != UIP_CLOSED && + BUF->destport == uip_connr->lport && + BUF->srcport == uip_connr->rport && + uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) { + goto found; + } + } + + /* If we didn't find and active connection that expected the packet, + either this packet is an old duplicate, or this is a SYN packet + destined for a connection in LISTEN. If the SYN flag isn't set, + it is an old packet and we send a RST. */ + if((BUF->flags & TCP_CTL) != TCP_SYN) { + goto reset; + } + + tmp16 = BUF->destport; + /* Next, check listening connections. */ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(tmp16 == uip_listenports[c]) + goto found_listen; + } + + /* No matching connection found, so we send a RST packet. */ + UIP_STAT(++uip_stat.tcp.synrst); + reset: + + /* We do not send resets in response to resets. */ + if(BUF->flags & TCP_RST) { + goto drop; + } + + UIP_STAT(++uip_stat.tcp.rst); + + BUF->flags = TCP_RST | TCP_ACK; + uip_len = UIP_IPTCPH_LEN; + BUF->tcpoffset = 5 << 4; + + /* Flip the seqno and ackno fields in the TCP header. */ + c = BUF->seqno[3]; + BUF->seqno[3] = BUF->ackno[3]; + BUF->ackno[3] = c; + + c = BUF->seqno[2]; + BUF->seqno[2] = BUF->ackno[2]; + BUF->ackno[2] = c; + + c = BUF->seqno[1]; + BUF->seqno[1] = BUF->ackno[1]; + BUF->ackno[1] = c; + + c = BUF->seqno[0]; + BUF->seqno[0] = BUF->ackno[0]; + BUF->ackno[0] = c; + + /* We also have to increase the sequence number we are + acknowledging. If the least significant byte overflowed, we need + to propagate the carry to the other bytes as well. */ + if(++BUF->ackno[3] == 0) { + if(++BUF->ackno[2] == 0) { + if(++BUF->ackno[1] == 0) { + ++BUF->ackno[0]; + } + } + } + + /* Swap port numbers. */ + tmp16 = BUF->srcport; + BUF->srcport = BUF->destport; + BUF->destport = tmp16; + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + /* And send out the RST packet! */ + goto tcp_send_noconn; + + /* This label will be jumped to if we matched the incoming packet + with a connection in LISTEN. In that case, we should create a new + connection and send a SYNACK in return. */ + found_listen: + /* First we check if there are any connections avaliable. Unused + connections are kept in the same table as used connections, but + unused ones have the tcpstate set to CLOSED. Also, connections in + TIME_WAIT are kept track of and we'll use the oldest one if no + CLOSED connections are found. Thanks to Eddie C. Dost for a very + nice algorithm for the TIME_WAIT search. */ + uip_connr = 0; + for(c = 0; c < UIP_CONNS; ++c) { + if(uip_conns[c].tcpstateflags == UIP_CLOSED) { + uip_connr = &uip_conns[c]; + break; + } + if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) { + if(uip_connr == 0 || + uip_conns[c].timer > uip_connr->timer) { + uip_connr = &uip_conns[c]; + } + } + } + + if(uip_connr == 0) { + /* All connections are used already, we drop packet and hope that + the remote end will retransmit the packet at a time when we + have more spare connections. */ + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; + } + uip_conn = uip_connr; + + /* Fill in the necessary fields for the new connection. */ + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; + uip_connr->lport = BUF->destport; + uip_connr->rport = BUF->srcport; + uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); + uip_connr->tcpstateflags = UIP_SYN_RCVD; + + uip_connr->snd_nxt[0] = iss[0]; + uip_connr->snd_nxt[1] = iss[1]; + uip_connr->snd_nxt[2] = iss[2]; + uip_connr->snd_nxt[3] = iss[3]; + uip_connr->len = 1; + + /* rcv_nxt should be the seqno from the incoming packet + 1. */ + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_add_rcv_nxt(1); + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + + /* Our response will be a SYNACK. */ +#if UIP_ACTIVE_OPEN + tcp_send_synack: + BUF->flags = TCP_ACK; + + tcp_send_syn: + BUF->flags |= TCP_SYN; +#else /* UIP_ACTIVE_OPEN */ + tcp_send_synack: + BUF->flags = TCP_SYN | TCP_ACK; +#endif /* UIP_ACTIVE_OPEN */ + + /* We send out the TCP Maximum Segment Size option with our + SYNACK. */ + BUF->optdata[0] = TCP_OPT_MSS; + BUF->optdata[1] = TCP_OPT_MSS_LEN; + BUF->optdata[2] = (UIP_TCP_MSS) / 256; + BUF->optdata[3] = (UIP_TCP_MSS) & 255; + uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + goto tcp_send; + + /* This label will be jumped to if we found an active connection. */ + found: + uip_conn = uip_connr; + uip_flags = 0; + /* We do a very naive form of TCP reset processing; we just accept + any RST and kill our connection. We should in fact check if the + sequence number of this reset is wihtin our advertised window + before we accept the reset. */ + if(BUF->flags & TCP_RST) { + uip_connr->tcpstateflags = UIP_CLOSED; + UIP_LOG("tcp: got reset, aborting connection."); + uip_flags = UIP_ABORT; + UIP_APPCALL(); + goto drop; + } + /* Calculated the length of the data, if the application has sent + any data to us. */ + c = (BUF->tcpoffset >> 4) << 2; + /* uip_len will contain the length of the actual TCP data. This is + calculated by subtracing the length of the TCP header (in + c) and the length of the IP header (20 bytes). */ + uip_len = uip_len - c - UIP_IPH_LEN; + + /* First, check if the sequence number of the incoming packet is + what we're expecting next. If not, we send out an ACK with the + correct numbers in. */ + if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) { + if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { + goto tcp_send_ack; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + data. If so, we update the sequence number, reset the length of + the outstanding data, calculate RTT estimations, and reset the + retransmission timer. */ + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + + if(BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) { + /* Update sequence number. */ + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + + /* Do RTT estimation, unless we have done retransmissions. */ + if(uip_connr->nrtx == 0) { + signed char m; + m = uip_connr->rto - uip_connr->timer; + /* This is taken directly from VJs original code in his paper */ + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if(m < 0) { + m = -m; + } + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + + } + /* Set the acknowledged flag. */ + uip_flags = UIP_ACKDATA; + /* Reset the retransmission timer. */ + uip_connr->timer = uip_connr->rto; + + /* Reset length of outstanding data. */ + uip_connr->len = 0; + } + + } + + /* Do different things depending on in what state the connection is. */ + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + implemented, since we force the application to close when the + peer sends a FIN (hence the application goes directly from + ESTABLISHED to LAST_ACK). */ + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + we are waiting for an ACK that acknowledges the data we sent + out the last time. Therefore, we want to have the UIP_ACKDATA + flag set. If so, we enter the ESTABLISHED state. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_flags = UIP_CONNECTED; + uip_connr->len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + goto drop; +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + our SYN. The rcv_nxt is set to sequence number in the SYNACK + plus one, and we send an ACK. We move into the ESTABLISHED + state. */ + if((uip_flags & UIP_ACKDATA) && + (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + uip_len = 0; + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + /* Inform the application that the connection failed */ + uip_flags = UIP_ABORT; + UIP_APPCALL(); + /* The connection is closed after we send the RST */ + uip_conn->tcpstateflags = UIP_CLOSED; + goto reset; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + data into the uip_buf. If the UIP_ACKDATA flag is set, the + application should put new data into the buffer, otherwise we are + retransmitting an old segment, and the application should put that + data into the buffer. + + If the incoming packet is a FIN, we should close the connection on + this side as well, and we send out a FIN and enter the LAST_ACK + state. We require that there is no outstanding data; otherwise the + sequence numbers will be screwed up. */ + + if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + if(uip_outstanding(uip_connr)) { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); + uip_flags |= UIP_CLOSE; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + } + UIP_APPCALL(); + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->nrtx = 0; + tcp_send_finack: + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if((BUF->flags & TCP_URG) != 0) { +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if(uip_urglen > uip_len) { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; + } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } else { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ + } + + /* If uip_len > 0 we have TCP data in the packet, and we flag this + by setting the UIP_NEWDATA flag and update the sequence number + we acknowledge. If the application has stopped the dataflow + using uip_stop(), we must not accept any data packets from the + remote host. */ + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + + /* Check if the available buffer space advertised by the other end + is smaller than the initial MSS for this connection. If so, we + set the current MSS to the window size to ensure that the + application does not send more data than the other end can + handle. + + If the remote host advertises a zero window, we set the MSS to + the initial MSS so that the application will send an entire MSS + of data. This data will not be acknowledged by the receiver, + and the application will retransmit it. This is called the + "persistent timer" and uses the retransmission mechanim. + */ + tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1]; + if(tmp16 > uip_connr->initialmss || + tmp16 == 0) { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + by the UIP_ACKDATA flag, we should call the application since it + might want to send more data. If the incoming packet had data + from the peer (as flagged by the UIP_NEWDATA flag), the + application must also be notified. + + When the application is called, the global variable uip_len + contains the length of the incoming data. The application can + access the incoming data through the global pointer + uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + bytes into the uip_buf array. + + If the application wishes to send any data, this data should be + put into the uip_appdata and the length of the data should be + put into uip_len. If the application don't have any data to + send, uip_len must be set to 0. */ + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { + uip_slen = 0; + UIP_APPCALL(); + + appsend: + + if(uip_flags & UIP_ABORT) { + uip_slen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + if(uip_flags & UIP_CLOSE) { + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->nrtx = 0; + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* If uip_slen > 0, the application has data to be sent. */ + if(uip_slen > 0) { + + /* If the connection has acknowledged data, the contents of + the ->len variable should be discarded. */ + if((uip_flags & UIP_ACKDATA) != 0) { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + already data in transit and cannot send anymore right + now. */ + if(uip_connr->len == 0) { + + /* The application cannot send more than what is allowed by + the mss (the minumum of the MSS and the available + window). */ + if(uip_slen > uip_connr->mss) { + uip_slen = uip_connr->mss; + } + + /* Remember how much data we send out now so that we know + when everything has been acknowledged. */ + uip_connr->len = uip_slen; + } else { + + /* If the application already had unacknowledged data, we + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ + uip_slen = uip_connr->len; + } + } + uip_connr->nrtx = 0; + apprexmit: + uip_appdata = uip_sappdata; + + /* If the application has data to be sent, or if the incoming + packet had new data in it, we must send out a packet. */ + if(uip_slen > 0 && uip_connr->len > 0) { + /* Add the length of the IP and TCP headers. */ + uip_len = uip_connr->len + UIP_TCPIP_HLEN; + /* We always set the ACK flag in response packets. */ + BUF->flags = TCP_ACK | TCP_PSH; + /* Send the packet. */ + goto tcp_send_noopts; + } + /* If there is no data to send, just send out a pure ACK if + there is newdata. */ + if(uip_flags & UIP_NEWDATA) { + uip_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } + } + goto drop; + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + FIN. This is indicated by the UIP_ACKDATA flag. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_CLOSED; + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + } + break; + + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + hasn't closed its end yet. Thus we do nothing but wait for a + FIN from the other side. */ + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; + } else { + uip_connr->tcpstateflags = UIP_CLOSING; + } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } else if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + goto drop; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_FIN_WAIT_2: + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_TIME_WAIT: + goto tcp_send_ack; + + case UIP_CLOSING: + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + } + } + goto drop; + + + /* We jump here when we are ready to send the packet, and just want + to set the appropriate TCP sequence numbers in the TCP header. */ + tcp_send_ack: + BUF->flags = TCP_ACK; + tcp_send_nodata: + uip_len = UIP_IPTCPH_LEN; + tcp_send_noopts: + BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; + tcp_send: + /* We're done with the input processing. We are now ready to send a + reply. Our job is to fill in all the fields of the TCP and IP + headers before calculating the checksum and finally send the + packet. */ + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; + + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; + + BUF->proto = UIP_PROTO_TCP; + + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr); + + if(uip_connr->tcpstateflags & UIP_STOPPED) { + /* If the connection has issued uip_stop(), we advertise a zero + window so that the remote host will stop sending data. */ + BUF->wnd[0] = BUF->wnd[1] = 0; + } else { + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); + } + + tcp_send_noconn: + BUF->ttl = UIP_TTL; +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->urgp[0] = BUF->urgp[1] = 0; + + /* Calculate TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#if UIP_UDP + ip_send_nolen: +#endif /* UIP_UDP */ + +#if UIP_CONF_IPV6 + BUF->vtc = 0x60; + BUF->tcflow = 0x00; + BUF->flow = 0x00; +#else /* UIP_CONF_IPV6 */ + BUF->vhl = 0x45; + BUF->tos = 0; + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + ++ipid; + BUF->ipid[0] = ipid >> 8; + BUF->ipid[1] = ipid & 0xff; + /* Calculate IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum()); +#endif /* UIP_CONF_IPV6 */ + + UIP_STAT(++uip_stat.tcp.sent); + send: + DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len, + (BUF->len[0] << 8) | BUF->len[1]); + + UIP_STAT(++uip_stat.ip.sent); + /* Return and let the caller do the actual transmission. */ + uip_flags = 0; + return; + drop: + uip_len = 0; + uip_flags = 0; + return; +} +/*---------------------------------------------------------------------------*/ +u16_t +htons(u16_t val) +{ + return HTONS(val); +} +/*---------------------------------------------------------------------------*/ +void +uip_send(const void *data, int len) +{ + if(len > 0) { + uip_slen = len; + if(data != uip_sappdata) { + memcpy(uip_sappdata, (data), uip_slen); + } + } +} +/** @} */ Index: /webserver/example/EnergyMeters/EnergyMeters/readme.txt =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/EnergyMeters/readme.txt (revision 14) @@ -0,0 +1,16 @@ +Each RTOS port has a demo application to demonstrate it's use. + ++ The Demo/Common directory contains the demo application files as described on +the http://www.FreeRTOS.org WEB site. Each file creates one or more tasks. +The files in the Demo/Common directory are used by every demo application for +every port. + ++ All the other directories contain a project or makefile for the demo +application targeted at a particular microcontroller. + + +For example, if you are interested in the ATMega323 demo application for +the WinAVR tools then the AVR_ATMega323_WinAVR directory contains the +relevant makefile. The makefile includes files from the Demo/ATMega323 +and the Demo/Common directories. If this is the only port you are +interested in then all the other directories can be ignored. Index: /webserver/example/EnergyMeters/readme.txt =================================================================== --- /webserver/example/EnergyMeters/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/readme.txt (revision 14) @@ -0,0 +1,19 @@ +The download includes the kernel source code, and a demo application for EVERY +RTOS port. See http://www.freertos.org/a00017.html for full details of the +directory structure and information on locating the files you require. + +The easiest way to use FreeRTOS is start start with one of the demo application +projects. Once this is running the project can be modified to include your own +source files. This way the correct files and compiler options will be +automatically included in your application. + ++ The Source directory contains the real time kernel source files for every +port. The kernel itself is only 3 files. + ++ The Demo directory contains the demo application source files for every +port. + ++ The TraceCon directory contains the trace visualisation exe file. + +See the readme files in the respective directories for further information. + Index: /webserver/example/EnergyMeters/TraceCon/readme.txt =================================================================== --- /webserver/example/EnergyMeters/TraceCon/readme.txt (revision 14) +++ /webserver/example/EnergyMeters/TraceCon/readme.txt (revision 14) @@ -0,0 +1,6 @@ +Tracecon.exe is a very simplistic utility for converting the trace data captured by the scheduler into a tab delimited text file. The text file can be opened using a spread sheet program as described on www.FreeRTOS.org. + +Tracecon should be executed from a command prompt. It looks for a file called Trace.bin in the current directory and creates a file called trace.txt. + +Use the big endian version for file captured on big endian targets. +
LocalRemoteStateRetransmissionsTimerFlags
%d%u.%u.%u.%u:%u%s%u%u%c %c