Modularizando o src

Dependencies:   EALib EthernetInterface_vz mbed-rtos mbed

Fork of header_main_colinas_V0-20-09-14 by VZTECH

main.cpp

Committer:
klauss
Date:
2015-03-13
Revision:
106:a34fcf9f0e02
Parent:
105:a930035b6556
Child:
107:cf1e43414adb

File content as of revision 106:a34fcf9f0e02:

#include "main_includes.h"

// Contador low-level de pacotes recebifos na interface eth da embarcada, extern de lpc17_emac.c
volatile u16_t lpc_low_level_input_counter = 0;

int main()
{   
    // configura e inicia o wdt 
    init_wdt();

    // configs de sistema, irqs, I/O bounds
    config_lpc();

    // inicializa a comunicacao com a laser
    start_cpld();

    // habilita a impressao de caracteres na interface UART3
    debug_uart3 = true;
    
    // rotina de verificacao do uso do sistema de memoria
    if( sdram_init() == 1 ) {
        pc.printf("\r\n******* Failed to initialize SDRAM *******\r\n");
        return 1;
    } else {
        pc.printf("\r\n******* Success to initialize SDRAM *******\r\n");
    }

    // inicializa o sistema de arquivo para uso
    init_fsystem();

    // exibe endereco MAC da lpc
    {
        char s[ 32 ];
        mbed_mac_address( s );
        pc.printf( "\r\n******* ::Mac::%02x:%02x:%02x:%02x:%02x:%02x:: *******\r\n", s[0],s[1],s[2],s[3],s[4],s[5] );
    }

    // rotina de inicializacao da interface ETH
    short int eth_status = __init_eth__();
    if( eth_status ) {
        pc.printf("\r\n******* Cannot connect to eth *******\r\n");
    } else {
        pc.printf("\r\n******* Connection eth - ok *******\r\n");
        init_prompt_eth();
        init_external_wdt()
    }

    // sync_timer : usado para sincronizar eventos a cada x unidades de tempo, usualmente em debugs
    // led_sync_timer : usado para controlar a taxa de toggle do led de debug
    Timer sync_timer, led_sync_timer;
    
    sync_timer.start();
    led_sync_timer.start();

    // representa ramal do call box
    int ext = 0;

    // representa porta do call box
    int port = 0;

    // buffer para onde se copia os dados vindos do cb para tratameno interno
    uint8_t buffer[ CB_BUFFER_SIZE ];

    // buffer de escrita do pacote de saida que sera enviado pro cb / servidor
    uint8_t write_buffer[ CB_BUFFER_SIZE ];

    // ponteiro que aponta para os dados vindo do CPLD
    uint8_t * buffer_from_cb_ptr = ( uint8_t * )RXBuffer;

    // Armazena o ultimo pacote recebido dos CBx
    uint8_t cb_rx_buffer[ CB_BUFFER_SIZE ];

    // referencia para os dados contidos no pacote, sem o header
    uint8_t * data = NULL;

    // gerencia o tipo do pacote para providenciar tratamento adequado
    volatile uint8_t type = __DO_NOTHING__;

    // representa a lista dos Call Boxes atualmente recfonhecidos pela cabeceira
    Vector * v_cb = new Vector();

    // representa a lista de ligacoes ativas na cabeceira
    Vector * v_call = new Vector();

    // gerencia a distribuicao de timeslice para os call boxes
    Timeslice * ts = new Timeslice();
    if( ts == NULL ) {
        memory_is_over = true;
        if( debug_memory ) debug_msg("TS allocation fail");
    }

    // aloca o vetor de call boxes
    if( v_cb == NULL ) {
        while( v_cb == NULL ) {
            Vector * v_cb = new Vector();
            if( sync_timer.read() > 5 ) {
                send_msg("Erro ao alocar o vetor de CBx");
                sync_timer.reset();
            }
        }
    } 
    
    // aloca o vetor de calls
    if( v_call == NULL ) {
        while( v_call == NULL ) {
            Vector * v_call = new Vector();
            if( sync_timer.read() > 5 ) {
                send_msg("Erro ao alocar o vetor de Calls");
                sync_timer.reset();
            }
        }
    }

    if( v_cb == NULL ) {
        memory_is_over = true;
        if( debug_memory ) debug_msg("Call_Box vector allocation fail");
    }

    if( v_call == NULL ) {
        memory_is_over = true;
        if( debug_memory ) debug_msg("Call vector allocation fail");
    }

    // inicializa buffers de armazenamento temporario de I/O com o CBx
    for( register uint16_t i = 0; i < CB_BUFFER_SIZE; i++ ) {
        cb_rx_buffer[ i ] = 0;
        cb_tx_buffer[ i ] = 0;
    }

    // apagar os leds do lpc
    reset_leds();

    //FIXME remover caso compravado desuso
    udp_timer.start();
    
    // inicializa o sistema para envio de pacotes do tipo __FW?__ e __TELEMETRY__ para servidor ( ip, porta ) previamente configurado.
    init_fw_handler();
    
    led2 = 0;
    
    // le do sistema de arquivos valores previamente configurados de primeiro e ultimo ramal de um determinado ramo.
    init_ranges();
    
    // inicializa o timer de refresh dos cbx
    init_refresh();

    // inicializa o time de envelhecimento do CBx
    init_aging();

    // inicislizs o yimrt para sincronizar as rotinas de wake_all_up e refresh
    init_sync_refresh();

    // usada para delay na ativacao de algumas funcoes, wake_all_up e tentativa de eth reconnect
    static uint8_t count = 0;

    // contador usado para indicar quantos cbx foram registrados na logica
    uint8_t max_registered_cbx = 0;

    // inicia dizendo que a rotina nao deve rodar agora ( 35 sec. nas versoes originais )
    bool wake_all = false;

    // inico das variaveis controladoras do extern wdt
    
    // atribui valor maximo ao countdown que verifica comunicao com os CBx
    uint16_t pkg_wdt = RX_CB_IDLE;
    
    // atribi  falor maximo ao countdown que verifica conexao eth
    uint16_t eth_wdt = ETH_CONNECT_TIMEOUT;
    
    // inicializa o contador de uptime da header
    uint32_t uptime = 0;
    
    led1 = 0;
    
    send_msg("\r\nReady");
    
    // inicializa o timer de retry dos pacotes de invite, necessario para o comportamento "metralhadora" da header.
    Timer invite_retry_timer;
    invite_retry_timer.start();
    
    // desabilita a impressao de caracteres na interface UART3
    //debug_uart3 = false;
    
    reset_leds();

    /*------------------------------------------ main loop ---------------------------------------------------------------*/
    while( true ) {
        // inicializa o loop afirmando que nao existe comando externo para ser processado pelo prompt.
        udp_query = false;
        from_eth = false;
        
        // chama rotina de processamento de entrada serial para o prompp
        prompt_process( NULL, 0 );
        
        //begin verificacao e tratamento dos pacotes recebidos via UDP-ETH 
        {
            fd_set fdSet;
            FD_ZERO(&fdSet);

            // coloca o socket SIP de todos os CBx
            for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                Call_Box * cb = (Call_Box *)v_cb->get_element( i );
                FD_SET( cb->get_sip_socket_fd(), &fdSet );
            }

            // adiciona o socket do watchdog
            FD_SET( udp_wdt_client.get_fd(), &fdSet );
            
            // adiciona o socket de comandos prompt-UDP-ETH
            FD_SET( udp_client.get_fd(), &fdSet );
            
            struct timeval t;
            t.tv_sec = 0;
            t.tv_usec = 0;
            // verifica se existe algo pendente para ser tratado
            int ret = lwip_select( FD_SETSIZE, &fdSet, NULL, NULL, &t );

            if(ret > 0 ) {
                // existe algo na fila UDP pendente.
                // verigica o socket SIP de cada CBx
                for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                    Call_Box * cb = (Call_Box *)v_cb->get_element( i );
                    int fd =  cb->get_sip_socket_fd();
                    if( FD_ISSET( fd, &fdSet ) ) {
                        int rcv = cb->sip_udp_incomming_pkg();
                    }
                }
                
                // verifica o socket do prompt-UDP-ETH
                if( FD_ISSET( udp_client.get_fd(), &fdSet ) ) {
                    char to_prompt_process[ PROMPT_UDP_COMMAND_SIZE ];
                    //for( register int i = 0; i < PROMPT_UDP_COMMAND_SIZE; i++ ) to_prompt_process[ i ] = 0;
                    
                    int prompt_process_msg_rcv = udp_client.receiveFrom( udp_server, to_prompt_process, ( sizeof( to_prompt_process ) - 1 ) );
                    
                    to_prompt_process[ prompt_process_msg_rcv ] = 0;
                    if( prompt_process_msg_rcv == -1 )
                    {
                        if( debug_reconnect ) send_msg("Reconnect Prompt Process");
                        reconnect_udp_prompt_process();
                        miss_prompt_udp_rcv_pkg++;
                    } 
                        else if( prompt_process_msg_rcv > 0 )
                    {
                        udp_query = true;
                        prompt_process( to_prompt_process, prompt_process_msg_rcv );
                    }
                } 
                
                // verifica o socket do watchdog
                if( FD_ISSET( udp_wdt_client.get_fd(), &fdSet ) ) {
                    char wake_msg[ 768 ];
                    Endpoint udp_wdt_server;
                    
                    int wake_msg_rcv = udp_wdt_client.receiveFrom( udp_wdt_server, wake_msg, sizeof( wake_msg ) );
                    
                    if( wake_msg_rcv == -1 )
                    {
                        if( debug_reconnect ) send_msg("Reconnect Extern wdt");
                        reconnect_extern_wdt_socket();
                        miss_wdt_send_pkg++;
                    } 
                        else if( wake_msg_rcv > 0 )
                    {
                        if( !( strncmp( wake_msg, "alive", 5 ) ) ) {
                            // Just ckeck but not set 'alive?'
                            // 'alive*' - force wdt tick right now
                            // Ckecking and set 'alive'
                            bool question_alive = ( wake_msg[ 5 ] == '?' );
                            if( wake_msg[ 5 ] == '*' ) wdt.kick();
                            
                            snprintf( wake_msg, 48,"wdt:%u,%u,%u,%c,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u:", 
                                uptime, 
                                invite_counter, 
                                external_wdt, 
                                ( wdt.WatchdogCausedReset() ) ? '1' : '0', 
                                cb_new_counter, 
                                v_cb->size(),
                                ts->remain_timeslices(), 
                                sip_socket_send_failure, 
                                v_call->size(),
                                pkg_cksok,
                                pkg_ckserr,
                                pkg_zero,
                                out_of_range,
                                missed_pkg,
                                delayed_pkg_to_cb,
                                cpld_pkg_tx_counter,
                                cpld_pkg_rx_counter,
                                eth_wdt,
                                pkg_wdt,
                                miss_fw_send_pkg,
                                miss_prompt_udp_send_pkg,
                                miss_sip_registry_send_pkg,
                                miss_sip_invite_send_pkg,
                                miss_sip_bye_send_pkg,
                                miss_sip_unregistry_send_pkg,
                                miss_sip_ok_send_pkg,
                                miss_sip_rcv_bye_send_pkg,
                                miss_wdt_send_pkg,
                                miss_prompt_udp_send_pkg,
                                miss_ftp_udp_send_pkg,
                                miss_prompt_udp_rcv_pkg                                
                            );
            
                            wake_msg[ 768 - 1 ] = 0;
                            int send = udp_wdt_client.sendTo( udp_wdt_server, wake_msg, strlen( wake_msg ) );
                            if( send != strlen( wake_msg ) )
                            {
                                if( debug_reconnect ) debug_msg("Reconnect Extern wdt (%d, %d)", send, strlen( wake_msg ) );
                                reconnect_extern_wdt_socket();
                                miss_wdt_send_pkg++;
                            }
        
                            if( ( (!question_alive) && ( cb_new_counter <= __MAX_CB_IN_A_BRANCH__ ) && ( cb_new_counter >= 2 ) ) ) {
                                external_wdt = EXTERN_WDT_IDLE;
                            }
                        } else if( !( strncmp( wake_msg, "reset", 5 ) ) ) {
                            external_wdt = 0;
        
                            sprintf( wake_msg, "rst:%u:", uptime );
                            int send = udp_wdt_client.sendTo( udp_wdt_server, wake_msg, strlen( wake_msg ) );
                            if( send != strlen( wake_msg ) )
                            {
                                if( debug_reconnect ) send_msg("Reconnect Extern wdt");
                                reconnect_extern_wdt_socket();
                                miss_wdt_send_pkg++;
                            }
                        }
                    }
                }
            }
        }//end verificacao e tratamento dos pacotes recebidos via UDP-ETH 
        
        // atualiza o valor do contador max_registered_cbx
        if( v_cb->size() > max_registered_cbx ) max_registered_cbx = v_cb->size();
        
         

        // executa a cada 5 segundos comandos e verificacoes ( principalmente debugs )
        if( sync_timer.read() > 5 ) {
            sync_timer.reset();
            
            // atualiza valor da variavel de delay
            count++;

            // enable na variavel que exibe estatisticas de cks dos pacotes recebidos pela header
            if( debug_cks == true ) {
                pcks_s = true;
            }

            // enable na variavel que exibe uma lista ( por ordem de pedido de registro ) dos cbx
            if( debug_alive == true ) {
                pshowcb = true;
            }
            
            // enable na variavel que exibe lista com estatisticas de pacotes que falharam ao serem enviados via interface eth
            if( debug_missed )
            {
                missed_send_udp_pkg = true;
            }
            
            // verifica status da conexao eth, em caso de falha na inicializacao anterior, tenta conectar periodicamente a cada 75 sec.
            // nas implementacoes inicias
            if( !( count % 15 ) ) {
                if( eth_status ) {
                    eth_status = __init_eth__();
                    if( eth_status ) {
                        if( debug_main ) pc.printf("\r\nCannot connect to eth\r\n");
                    } else {
                        if( debug_main ) pc.printf("\r\nConnection eth - ok");
                        init_prompt_eth();
                        init_external_wdt()
                    }
                }
            }
            
            // inicializa rotina de verificacao de "pares" de CBx apos 35 sec. nas implementacoes iniciais
            if( ( count > 7 ) && ( wake_all == false ) ) {
                wake_all = true;
                if( debug_wake == true ) send_msg( "Time to wake" );
            }
        }
        
         

        // zera os contadores de pacotes recebidos na interface CBx->Header
        if( r_stats ) {
            boot_counter = 0;
            registry_counter = 0;
            invite_counter = 0;
            audio_counter = 0;
            telemetry_counter = 0;
            cb_bye_counter = 0;
            prompt_counter = 0;
            flood_counter = 0;
            bootloader_cbx_counter = 0;
            cb_stats_counter = 0;
            fw_counter = 0;
            r_stats = false;
            stats = true;
        }
        
         

        // exibe o valor dos contadores de pacotes recebidos na interfacao CBx->ETH
        if( stats ) {
            char str[ 200 ];
            snprintf( str, 200, "\n\r Received Pkgs ::\n\r Boot :: %u\n\r Registry :: %u\n\r Invite :: %u\n\r Audio :: %u\n\r Telemetry :: %u\n\r CB_stats :: %u\n\r CB_bye :: %u\n\r Prompt :: %u\n\r Flood :: %u\n\r Bootloader_cbx :: %u\n\r Fw :: %u\n\r",
                      boot_counter, registry_counter, invite_counter, audio_counter, telemetry_counter, cb_stats_counter, cb_bye_counter, prompt_counter, flood_counter, bootloader_cbx_counter, fw_counter );
            send_msg( str );
            stats =false;
        }
        
         

        // exibe uma lista ( em ordem crescente e por ramais ) dos cbx que ja se registraram ao menos uma vez
        if( list ) 
        {
            uint8_t missed_cb = ( ( max_ext - min_ext ) + 1 ) - v_cb->size();

            if( ( max_ext % 2 ) == 0 ) missed_cb++;

            if( min_ext % 2 ) missed_cb++;

            if( min_ext == 0 && max_ext == 0 ) missed_cb = 0;

            send_msg("Registered %d[ %d ] CBx ( %d - %d ) - Missed %d -- Remain_timeslices :: %d :: v_call->size() :: %d", v_cb->size(), max_registered_cbx, min_ext, max_ext, missed_cb, ts->remain_timeslices(), v_call->size() );
            if( v_cb->size() == 1 ) {
                send_msg(" %d ", ( ( Call_Box * )v_cb->get_element( 0 ) )->get_ext() );
            } else if( v_cb->size() > 1 ) {
                char str[ 1024 ];
                int ext_list[ __MAX_CB_IN_A_BRANCH__ ];
                register int i = 0;
                for( ; i < v_cb->size(); i++ ) {
                    ext_list[ i ] = ( ( Call_Box * )v_cb->get_element( i ) )->get_ext();
                }

                qsort( ext_list, v_cb->size(), sizeof( int ), ls_comp );

                char aux[ 16 ];
                strcpy( str, "\r\n> " );
                for( i = 0; i < v_cb->size() - 1; i++ ) {
                    sprintf( aux, "%i, ", ext_list[ i ] );
                    strcat( str, aux );
                    if( ( i != 0 ) && !( ( i + 1 ) % 16 ) ) strcat( str, "\r\n> " );
                }
                sprintf( aux, "%i ", ext_list[ i ] );
                strcat( str, aux );
                send_msg( "%s", str );
            }
            list = false;
        }
        
         
        
        // validar na proxima iteracao.
        if( long_list ) 
        {
            uint8_t missed_cb = ( ( max_ext - min_ext ) + 1 ) - v_cb->size();

            if( ( max_ext % 2 ) == 0 ) missed_cb++;

            if( min_ext % 2 ) missed_cb++;

            if( min_ext == 0 && max_ext == 0 ) missed_cb = 0;

            {
                int ext_list[ __MAX_CB_IN_A_BRANCH__ ];
                
                if( v_cb->size() >= 1 ) {
                    for( register int i = 0; i < v_cb->size(); i++ )
                    {
                        ext_list[ i ] = ( ( Call_Box * )v_cb->get_element( i ) )->get_ext();
                    }
                    qsort( ext_list, v_cb->size(), sizeof( int ), ls_comp );
                }   
                
                send_msg("Registered %d[ %d ] CBx ( %d - %d ) - Missed %d -- Remain_timeslices :: %d :: v_call->size() :: %d", v_cb->size(), max_registered_cbx, min_ext, max_ext, missed_cb, ts->remain_timeslices(), v_call->size() );
                
                for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                    
                    Call_Box * cb = __find_CB__( v_cb, ext_list[ i ] );
            
                    if( cb != NULL )
                    {
                        char cb_status[ 32 ];
                        char cb_sip_status[ 32 ];
                        switch( cb->status ) {
                            case cb_idle : {
                                strcpy( cb_status, "cb_idle" );
                                break;
                            }
                            case cb_ringing : {
                                strcpy( cb_status, "cb_ringing" );
                                break;
                            }
                            case cb_trying : {
                                strcpy( cb_status,"cb_trying" );
                                break;
                            }
                            case cb_on_call : {
                                strcpy( cb_status, "cb_on_call" );
                                break;
                            }
                            case cb_busy : {
                                strcpy( cb_status, "cb_busy" );
                                break;
                            }
                            case cb_denied : {
                                strcpy( cb_status, "cb_denied" );
                                break;
                            }
                        }
                        switch( cb->sip->status ) {
                            case sip_idle : {
                                strcpy( cb_sip_status, "sip_idle" );
                                break;
                            }
                            case sip_waiting_trying : {
                                strcpy( cb_sip_status, "sip_waiting_trying" );
                                break;
                            }
                            case sip_trying : {
                                strcpy( cb_sip_status, "sip_trying" );
                                break;
                            }
                            case sip_ringing : {
                                strcpy( cb_sip_status, "sip_ringing" );
                                break;
                            }
                            case sip_busy : {
                                strcpy( cb_sip_status, "sip_busy" );
                                break;
                            }
                            case sip_ok : {
                                strcpy( cb_sip_status, "sip_ok" );
                                break;
                            }
                            case sip_on_call : {
                                strcpy( cb_sip_status, "sip_on_call" );
                                break;
                            }
                            case sip_denied : {
                                strcpy( cb_sip_status, "sip_denied" );
                                break;
                            }
                        }
                        char cbx_to_string[ 254 ];
                        char aux[ 16 ];
                        strcpy( cbx_to_string, "Ext :: " );
                        itoa( cb->get_ext(), aux , 10 );
                        strcat( cbx_to_string, aux );
                        strcat( cbx_to_string, " :: Port :: " );
                        itoa( cb->get_port(), aux , 10 );
                        strcat( cbx_to_string, aux );
                        strcat( cbx_to_string, " :: Status -- " );
                        strcat( cbx_to_string, cb_status );
                        strcat( cbx_to_string, " - " );
                        strcat( cbx_to_string, cb_sip_status );
                        if( cb->get_timeslice() != 0 ) {
                            strcat( cbx_to_string, " -- on TimeSlice :: " );
                            itoa( cb->get_timeslice(), aux , 10 );
                            strcat( cbx_to_string, aux );
                        }
                        send_msg( cbx_to_string );
                    }
                }   
                
            }
            long_list = false;
        }
        
         

        // exibe uma lista de cbx por ordem de registro contendo status do cbx e do sip vinculado nesse cbx
        if( pshowcb == true ) 
        {            
            send_msg("Registered %d ( of %d ) CBx ( %d - %d ) -- Remain_timeslices :: %d :: v_call->size() :: %d", v_cb->size(), max_registered_cbx, min_ext, max_ext, ts->remain_timeslices(), v_call->size() );
            for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                Call_Box * cb = ( Call_Box * )v_cb->get_element( i );
                char cb_status[ 32 ];
                char cb_sip_status[ 32 ];
                switch( cb->status ) {
                    case cb_idle : {
                        strcpy( cb_status, "cb_idle" );
                        break;
                    }
                    case cb_ringing : {
                        strcpy( cb_status, "cb_ringing" );
                        break;
                    }
                    case cb_trying : {
                        strcpy( cb_status,"cb_trying" );
                        break;
                    }
                    case cb_on_call : {
                        strcpy( cb_status, "cb_on_call" );
                        break;
                    }
                    case cb_busy : {
                        strcpy( cb_status, "cb_busy" );
                        break;
                    }
                    case cb_denied : {
                        strcpy( cb_status, "cb_denied" );
                        break;
                    }
                }
                switch( cb->sip->status ) {
                    case sip_idle : {
                        strcpy( cb_sip_status, "sip_idle" );
                        break;
                    }
                    case sip_waiting_trying : {
                        strcpy( cb_sip_status, "sip_waiting_trying" );
                        break;
                    }
                    case sip_trying : {
                        strcpy( cb_sip_status, "sip_trying" );
                        break;
                    }
                    case sip_ringing : {
                        strcpy( cb_sip_status, "sip_ringing" );
                        break;
                    }
                    case sip_busy : {
                        strcpy( cb_sip_status, "sip_busy" );
                        break;
                    }
                    case sip_ok : {
                        strcpy( cb_sip_status, "sip_ok" );
                        break;
                    }
                    case sip_on_call : {
                        strcpy( cb_sip_status, "sip_on_call" );
                        break;
                    }
                    case sip_denied : {
                        strcpy( cb_sip_status, "sip_denied" );
                        break;
                    }
                }
                char cbx_to_string[ 254 ];
                char aux[ 16 ];
                strcpy( cbx_to_string, "Ext :: " );
                itoa( cb->get_ext(), aux , 10 );
                strcat( cbx_to_string, aux );
                strcat( cbx_to_string, " :: Port :: " );
                itoa( cb->get_port(), aux , 10 );
                strcat( cbx_to_string, aux );
                strcat( cbx_to_string, " :: Status -- " );
                strcat( cbx_to_string, cb_status );
                strcat( cbx_to_string, " - " );
                strcat( cbx_to_string, cb_sip_status );
                if( cb->get_timeslice() != 0 ) {
                    strcat( cbx_to_string, " -- on TimeSlice :: " );
                    itoa( cb->get_timeslice(), aux , 10 );
                    strcat( cbx_to_string, aux );
                }
                send_msg( cbx_to_string );
            }
            pshowcb = false;
        }
        
        // exibe Ramal e Porta do objeto SIP associado a cada cbx
        // assim como exibe um timer crescente em segundos, desde o ultimo pacote recebido deste cbx respondendo registro.
        if( show_sip == true ){
            show_sip = false;
            send_msg(":: Sip :: %u", v_cb->size() );
            for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                Call_Box * cb = ( Call_Box * )v_cb->get_element( i );
                send_msg("ext :: %d -- port :: %d -- timer %d", cb->get_sip_ext(), cb->get_sip_port(), cb->get_timer() );
            }
        } 
        
         

        // aciona rotina de envio de pacote de flood
        if( pflood == true ) flood();
        
         

        // exibe status de conexao ETH
        if( debug_eth ) {
            debug_eth = false;
            send_msg("Eth status %s", ( eth_status == 0 ) ? "Connected" : "Disconnected" );
        }
        
         

        // testa se existe um pacote recebido pela interface CBx->Header pendente para ser processado.
        if( status != __WAITING__ ) {
            pkg_wdt = RX_CB_IDLE;
            xmemcpy( cb_rx_buffer, buffer_from_cb_ptr, CB_BUFFER_SIZE );
            status = __WAITING__;
            missed_pkg--;
            xmemcpy( buffer, cb_rx_buffer, CB_BUFFER_SIZE );

            // exibe esta pacote caso seja solicitado
            // TODO implementar um debug que exibe somente, todos os pacotes recebidos
            if( rx ) {
                char str[ 1024 ];
                strcpy( str, "RX :: \n\r " );
                for( register uint16_t i = 0; i < CB_BUFFER_SIZE; i++ ) {
                    char tmp[ 16 ];
                    strcat( str, itoa( cb_rx_buffer[ i ], tmp, 16 ) );
                    if( ( i != 0 ) && !( ( i + 1 ) % 50 ) ) strcat( str, "\n\r " );

                    else strcat( str, " " );
                }
                send_msg( "%s", str );
                rx = false;
            }
            
            // chama rotina para interpretar e validar o pacote recebido
            data = parse_vz_pkg( &ext, &port, &type, buffer );

            // caso parse_vz_pkg tenha retorno diferente de NULL, trata-se de um pacote valido para ser processado
            if( data != NULL ) {
                // atualiza referencias de menor e maior ramal conhecidos ate o momento
                if( min_ext == 0 ) min_ext = ext;

                if( ext > max_ext ) max_ext = ext;

                if( ext < min_ext ) min_ext = ext;
                
                // verifica se precisa "exportar" esse pacote para debug externo
                if( debug_fw ){
                    fw_cbx_pkg( ext, port, ( char *)buffer );
                }
                
                // por decisao de projeto, todos os pacote de telemetria sao exportados para parse no servidor
                if( type == __TELEMETRY__ )
                {
                    telemetry_counter++;
                    //FIXME colocar o dtelos aqui    
                }
                
                // alguns tratamentos adicionais que sao pertinentes em caso de pacotes diferentes do tipo __AUDIO__
                if( type != __AUDIO__ ) 
                {
                    // vefifica quais pacotes precisam ser exportados para o servidor e faz a substituicao do typo para __FW__ sem com isso
                    // alterar o pacote de origem.
                    if( 
                        type == __TELEMETRY__ || 
                        type == __CB_STATS__ ||
                        type == __FW1__ ||
                        type == __FW2__ ||
                        type == __FW3__ ||
                        type == __FW4__ ||
                        type == __FW5__ ||
                        type == __FW6__
                     ) type = __FW__;
                    
                    // exibe que o pacote foi recebido porem sem exibir o conteudo do pacote, apenas ramal e porta do remetente e tipo do pkg
                    if( debug_cb_rx == true ){
                        send_msg("Pkg from CBx :: ( %d, %d ) -- Type :: %d", ext, port, type );
                    }
                    
                    // exibe o pacote recebido propriamente
                    if( debug_show_cpld )
                    {
                        char str[ 1024 ];
                        strcpy( str, "RX :: \n\r " );
                        for( register uint16_t i = 0; i < CB_BUFFER_SIZE; i++ ) {
                            char tmp[ 16 ];
                            strcat( str, itoa( cb_rx_buffer[ i ], tmp, 16 ) );
                            if( ( i != 0 ) && !( ( i + 1 ) % 50 ) ) strcat( str, "\n\r " );
        
                            else strcat( str, " " );
                        }
                        send_msg( "%s", str );                   
                    }

                    // verificacoes de ACKS
                    Call_Box * cb = __find_CB__( v_cb, ext );
                    if( cb != NULL ) {
                        if( data[ 0 ] & BIT7 ) {
                            if( type == __BOOT__ ) {
                                send2callboxes( build_cb_package( ext, port, __REGISTRY__,
                                    ( char * )data, cb->get_msg_id(), CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );
                            } else {
                                if( debug_main ) debug_msg("Received ack pkg with seq_num %d", data[ 0 ] );

                                switch( type ) {
                                    case __INVITE__ : {
                                        if( debug_main || debug_invite ) debug_msg("Invite Ack from %d on msg_id %d", ext, cb->get_msg_id() );
                                        break;
                                    }
                                    case __CB_BYE__ : {
                                        if( debug_main || debug_invite ) debug_msg("BYE Ack from %d on msg_id %d", ext, cb->get_msg_id() );
                                        cb->set_bye_response_ok();
                                        break;
                                    }
                                    case __REGISTRY__ : {
                                        if( debug_main || debug_aging ) debug_msg("Registry ACK from %d in pkg :: %d", ext, cb->get_msg_id() );
                                        break;
                                    }
                                    default : {
                                        if( debug_main || debug_aging ) debug_msg("ACK from %d in pkg :: %d :: type %d", ext, cb->get_msg_id(), type );
                                    }
                                }
                                if( type != __REGISTRY__ && type != __CB_BYE__ ) type = __DO_NOTHING__;
                                if( type == __CB_BYE__ ){
                                    VZ_call * call = __find_Call__( v_call, ext );
                                    if( call != NULL ){
                                        if( call->get_elapsed_time() < 120000 ){
                                            // devido a um bug na implementacao do protocolo, eventualmente o cbx envia
                                            // um pacote de bye nao intencional que encerrava ligacoes precocemente
                                            // solucao encontrada, colocado um timer de controle.
                                            if( debug_invite ) debug_msg("%d ack bye ignored", ext );
                                            type = __DO_NOTHING__;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } else type = __DO_NOTHING__;
        }
        
         
        
        // exibe uptime atual
        if( show_uptime )
        {
            show_uptime = false;
            send_msg("Uptime: %d", uptime );
        }
        
         

        // exibe algumas informacoes pertinentes sobre quantidade de variaveis alocadas e tamanho de alguns objetos.
        if( sizes == true ) {
            sizes = false;
            send_msg("CB_New (%u) -- CB_Delete (%u)", cb_new_counter, cb_delete_counter );
            send_msg("SIP_New (%u) -- SIP_Delete (%u)", sip_new_counter, sip_delete_counter );
            send_msg("RTP_header_New (%u) -- RTP_header_Delete (%u)", rtp_header_new_counter, rtp_header_delete_counter );
            send_msg("RTP_body_New (%u) -- RTP_body_Delete (%u)", rtp_body_new_counter, rtp_body_delete_counter );
            send_msg("Call_New (%u) -- Call_Delete (%u)", call_new_counter, call_delete_counter );
            send_msg("lpc_low_level_input_counter :: %d", lpc_low_level_input_counter );
            send_msg("Memory is %s", ( memory_is_over ) ? "Over" : "Ok" );
            send_msg("Missed_Pkg :: %d ::", missed_pkg );
            send_msg("Sizeof Sip :: %u", sizeof( Sip ) );
            send_msg("Sizeof Call_Box :: %u", sizeof( Call_Box ) );
            send_msg("Sizeof VZ_call :: %u", sizeof( VZ_call ) );
            send_msg("Sizeof RTP :: %u", sizeof( RTP ) );
            send_msg("Sizeof RTP_Header :: %u", sizeof( RTP_Header ) );
            send_msg("Sizeof RTP_Body :: %u", sizeof( RTP_Body ) );
            send_msg("Sizeof Vector :: %u", sizeof( Vector ) );
            send_msg("Sizeof Timeslice :: %u", sizeof( Timeslice ) );
            send_msg("Sizeof Watchdog :: %u", sizeof( Watchdog ) );
        }
        
         

        // zera os contadores de cks de pacotes recebidos na interface CBx->Header, e outros contadores relacionados
        if( reset_cks == true ) {
            pkg_cksok = 0;
            pkg_ckserr = 0;
            pkg_zero = 0;
            reset_cks = false;
            out_of_range = 0;
            missed_pkg = 0;
            delayed_pkg_to_cb = 0;
            cpld_pkg_tx_counter = 0;
            cpld_pkg_rx_counter = 0;
            pcks_s = true;
        }
        
         

        // exibe os contadores de cks de pacotes recebidos na interface CBx->Header, e outros contadores relacionados
        if( pcks_s == true ) {
            send_msg( 
                "\r\n"
                "   PKG_CKS OK: %d ( %003.2f )\r\n"
                "   PKG_CKS ERR: %d ( %003.2f )\r\n"
                "   PKG_0: %d ( %003.2f )\r\n"
                "   Out_of_range: %d ( %003.2f )\r\n"
                "   Miss_Pkg: %d\r\n"
                "   TX_delayed: %d\n\r"
                "   TX_Counter: %d\n\r"
                "   RX_Counter: %d\r\n",
                pkg_cksok, ( cpld_pkg_rx_counter  == 0 ) ? 0.00 : ( (  double ) pkg_cksok / cpld_pkg_rx_counter ) * 100, 
                pkg_ckserr, ( cpld_pkg_rx_counter  == 0 ) ? 0.00 : ( ( double ) pkg_ckserr / cpld_pkg_rx_counter ) * 100, 
                pkg_zero, ( cpld_pkg_rx_counter  == 0 ) ? 0.00 : ( ( double ) pkg_zero / cpld_pkg_rx_counter ) * 100, 
                out_of_range, ( cpld_pkg_rx_counter  == 0 ) ? 0.00 : ( ( double ) out_of_range / cpld_pkg_rx_counter ) * 100, 
                missed_pkg, 
                delayed_pkg_to_cb, 
                cpld_pkg_tx_counter, 
                cpld_pkg_rx_counter 
            );
            pcks_s = false;
        }
        
         
        
        // zera os contadores de pacotes que resultaram em falha de envio vio ETH
        if( reset_missed_send_udp_pkg ){        
            miss_fw_send_pkg = 0;                                                                                                                 
            miss_prompt_udp_send_pkg = 0;                                                                                                         
            miss_sip_registry_send_pkg = 0;                                                                                                       
            miss_sip_invite_send_pkg = 0;                                                                                                         
            miss_sip_bye_send_pkg = 0;                                                                                                            
            miss_sip_unregistry_send_pkg = 0;                                                                                                     
            miss_sip_ok_send_pkg = 0;                                                                                                             
            miss_sip_rcv_bye_send_pkg = 0;
            miss_wdt_send_pkg = 0;
            miss_prompt_udp_send_pkg = 0;
            miss_ftp_udp_send_pkg = 0;
            miss_prompt_udp_rcv_pkg = 0;
            reset_missed_send_udp_pkg = false;
            missed_send_udp_pkg = true;
        }
        
         
        
        // exibe estatisticas de pacotes que resultaram em falha de envio na interface ETH
        if( missed_send_udp_pkg )
        {
            send_msg(   "\r\nMissed pkgs ::\r\n "
                        "FW: %d\r\n "
                        "Prompt UDP %d\r\n "
                        "Registry %d\r\n "
                        "Invite %d\r\n "
                        "Bye %d\r\n "
                        "Unregistry %d\r\n "
                        "UDP incoming ( invite ans ) %d\r\n "
                        "UDP incoming ( bye from * ) %d\r\n "
                        "Wdt [ alive | rst ] %d\r\n "
                        "Rcv prompt %d\r\n "
                        "[ debug | send ]_msg %d\r\n "
                        "RTP %d\r\n", 
                miss_fw_send_pkg, 
                miss_prompt_udp_send_pkg, 
                miss_sip_registry_send_pkg, 
                miss_sip_invite_send_pkg, 
                miss_sip_bye_send_pkg, 
                miss_sip_unregistry_send_pkg, 
                miss_sip_ok_send_pkg, 
                miss_sip_rcv_bye_send_pkg, 
                miss_wdt_send_pkg, 
                miss_prompt_udp_send_pkg,
                miss_prompt_udp_rcv_pkg,
                miss_ftp_udp_send_pkg 
            );
            
            missed_send_udp_pkg = false;
        }
        
         
        // rotina de teste para sobrecarga do processamento do cbx.
        if( flood_bug_pkg ){
            static int id = 0x10;
            if( id < 10 ) id = 0x0b;
            send2callboxes( build_cb_package( 5828, 5123, __REGISTRY__,
                ( char * )buffer, id++, CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );    
        }
        
         
        // toggle nos leds de debug da header.
        if( led_sync_timer.read() >= 1 ) {
            led_sync_timer.reset();
            led3 = !led3;
            CAB_LED = !CAB_LED;
        }
        
         
        // rotina de teste ( usados durante desenvolvimento
        /*
        if( main_test )
        {
            static int n = 0;
            static int next_ext = 5000;
            
            main_test = false;
            data = buffer;
            ext = next_ext + ( n * ( ( n % 2 ) ? 1 : -1 ) );
            n++;
            port = ext;
            type = __REGISTRY__;
        }
        */
         
        // begin switch para tratemento de pacote baseado no type
        switch( type ) {
            case __DO_NOTHING__ :
            {}
            break;

            case __CB_BYE__ : {
                /***
                    -- Fluxo -- 
                    [ Principio ] 
                        -- Receber um pedido de bye
                        -- procurar e encerrar a ligacao
                        
                    - Incrementa o contador de pacotes recebidos
                    - Procura por este cbx no vetor logico de CBx.
                        - Em caso de nao localizacao - Nao executa tratamento e exibe mensagem informando, caso seja habilitado degub
                        - Em caso de localizacao do cbx
                            - Seta o BIT7 para ACK
                            - assume que esta ligacao já foi removida
                            - procura por essa call no vetor logico de calls
                                - Em caso de nao localizacao 
                                    - Executa Busca no vetor logico de CBX
                                        - Em caso de localizacao
                                            - assume que esta ligacao já foi removida
                                            - Confirma que a ligacao nao tinha sido removida
                                            - Envia pacote de BYE para o servidor asterisk ( * )                                                                                    
                                            - Recupera o TimeSlice ( ts ) usado nesta call
                                            - Atribui o TS 0 neste cbx
                                            - Preenche a posição do TS com 0
                                            - Retorna o status do CBx e do SIP deste CBx para idle
                                            - Remove a call do vetor
                                            - Envia pacote de ack para o CBx
                                            - Atualiza o id da próxima msg que sera enviada para este CBx
                                        - Em caso de nao localizacao 
                                            Exibe mensagem informando que exta call ja tinha sido removida, caso habilitado debug
                                - Em caso de localizacao
                                    - Confirma que a ligacao nao tinha sido removida
                                    - Envia pacote de BYE para o servidor asterisk ( * )                                                                                    
                                    - Recupera o TimeSlice ( ts ) usado nesta call
                                    - Atribui o TS 0 neste cbx
                                    - Preenche a posição do TS com 0
                                    - Retorna o status do CBx e do SIP deste CBx para idle
                                    - Remove a call do vetor
                                    - Envia pacote de ack para o CBx
                                    - Atualiza o id da próxima msg que sera enviada para este CBx
                                    - Deleta o objeto call. 
                                - Em caso de nao localizacao 
                                    Exibe mensagem informando que exta call ja tinha sido removida, caso habilitado debug
                ***/

                cb_bye_counter++;
                Call_Box * cb = __find_CB__( v_cb, ext );
                if( cb != NULL ) {
                    if( debug_invite || debug_main ) debug_msg("Received bye pkg with msg_id %d e pkg_id %d", cb->get_msg_id(), data[ 0 ] );
                    data[ 0 ] |= BIT7;
                    cb->set_msg_id( data[ 0 ] );
                    if( debug_main || debug_invite ) debug_msg( "Request bye from CBx " );
                    
                    bool already_removed = true;
                    for( register uint8_t i = 0; i < v_call->size(); i++ ) {
                        VZ_call * call = (VZ_call *)v_call->get_element( i );
                        if( call->get_cb_ext() == ext ) {
                            already_removed = false;
                            cb->send_bye();

                            ts->return_timeslice( cb->get_timeslice() );
                            cb->set_timeslice( 0x00 );
                            data[ __TIMESLICE_PLACE__ ] = 0x00;

                            set_status( cb->status, cb_idle );
                            set_status( cb->sip->status, sip_idle );

                            v_call->remove_element( i );

                            send2callboxes( build_cb_package( ext, port, __CB_BYE__,
                                ( char * )data, cb->get_msg_id(), CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );
                              
                            // envia o ack bye depois atualiza o msg_id  
                            cb->set_msg_id( ( cb->get_msg_id() + 1 ) & ~BIT7 );

                            delete( call );
                        }
                    }
                    
                    if( already_removed ) if( debug_main || debug_invite ) debug_msg( "Already removed from vector call" );
            
                    // ok, mas nem sempre o cbx "entrou" em call
                    // Faz-se agora a busca no vetor logico de CBx e nao no de calls como acima
                    for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                        Call_Box * cb = (Call_Box *)v_cb->get_element( i );
                        if( cb->get_ext() == ext ) {
                            already_removed = true;
                            // nao entra nesse if caso tenha sido removido no for de cima.
                            if( cb->get_status() != cb_idle ) {
                                already_removed = false;
                                cb->send_bye();

                                ts->return_timeslice( cb->get_timeslice() );
                                cb->set_timeslice( 0x00 );
                                data[ __TIMESLICE_PLACE__ ] = 0x00;

                                set_status( cb->status, cb_idle );
                                set_status( cb->sip->status, sip_idle );

                                send2callboxes( build_cb_package( ext, port, __CB_BYE__,
                                    ( char * )data, cb->get_msg_id(), CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );

                                cb->set_msg_id( ( cb->get_msg_id() + 1 ) & ~BIT7 );
                            }
                        }
                    }

                    if( already_removed ) if( debug_main || debug_invite ) debug_msg( "Already removed from inviting queue" );

                    cb->registry();
                } else if( debug_invite || debug_main ) debug_msg("Bye from who ? %d", ext );
            }
            break;

            case __INVITE__ : {
                /***
                    [ Principio ] 
                        -- Receber um pedido de chamada
                        -- tratar com o cbx o andamento da negociacao SIP ( informando disponibilidade de TS )
                        -- tratar com o * a negociacao SIP
                    
                    -- Fluxo -- 
                    - Incrementa o contador de pacotes de pedido de chamada ( invite ) enviados.
                    - Procura por este CBx no vetor logico de CBX
                        - Em caso de nao localizacao
                            - Verifica se nao existem mais cbx criados do que o permitido por definicao de projeto
                            - Tenta criar o objeto CBx
                                - Caso consiga criar : adiciona o novo elemento no vetor logico de CBx
                                - Caso nao consiga criar : Exibe msg de erro condicionada a debuf e seta variavel indicando ausencia de memoria
                        - Em caso de localizacao ( ou tenha conseguido criar no caso acima )
                            - Atribui o valor recebido no pacote na posicao ID como sendo o id da proxima msg
                            - Verifica o status do CBx
                                - Caso status idle, inicia timer de tratamento de envio de ACK pro CBx
                            - Invoca rotina de tratamento SIP deste pedido de chamada.
                ***/
                
                invite_counter++;
                if( debug_invite ) debug_msg("Request Invite received from Cbx %i", ext);
                Call_Box * cb = __find_CB__( v_cb, ext );
                if( cb == NULL ) {
                    if( v_cb->size() < __MAX_CB_IN_A_BRANCH__ ) {
                        if( debug_main ) debug_msg( "Adding CBx :: %i", ext );
                        cb = new Call_Box( ext, port );

                        if( cb == NULL ) {
                            memory_is_over = true;
                            if( debug_memory ) debug_msg("Invite allocation cb fail");
                        } else {
                            v_cb->add( cb );
                        }
                    }
                }
                if( cb != NULL ) {
                    cb->set_msg_id( data[ 0 ] );
                    if( cb->status == cb_idle ){
                        cb->set_invite_response_ok();
                        cb->invite_retry_count_reset();
                    }
                    invite_handler( v_call, v_cb, ts, cb );
                }
            }
            break;
            case __REGISTRY__ : {
                /***
                    [ Principio ]
                        -- Receber um pacote de registro
                        -- Encaminhar para o *
                    
                    -- Fluxo --
                    - incrementa o contador de pacotes de registro recebidos
                    - Procura por este cbx no vetor logico de CBx.
                    - Verifica se nao existem mais cbx criados do que o permitido por definicao de projeto
                        - Caso nao exista
                            - Verifica se o CBx foi encontrado no vetor
                                - Caso nao tenha sido
                                    - Tentar criar este elemento
                                    - Verifica criacao bem sucedida
                                        - Caso tenha criado o elemento
                                            - Adiciona o mesmo no vetor logico de CBX
                                        - Caso nao tenha criado o elemento
                                            - seta variavel de erro
                                            - exibe mensagem de erro condicionada a debug.
                    - Caso o CBx tenha sido encontrado ( ou criado acima )
                        - Envia pacote de registro para o *                
                ***/
                registry_counter++;
                Call_Box * cb = __find_CB__( v_cb, ext );
                if( v_cb->size() < __MAX_CB_IN_A_BRANCH__ ) {
                    if( cb == NULL ) {
                        if( debug_main ) debug_msg("Adding Cbx :: %d", ext );
                        cb = new Call_Box( ext, port );

                        if( cb == NULL ) {
                            memory_is_over = true;
                            if( debug_memory ) debug_msg("Registry cb allocation fail");
                        } else {
                            v_cb->add( cb );
                            if( debug_main ) debug_msg("Added CBx -- %d", ext );
                        }
                    }
                }
                if( debug_main ) debug_msg("Registered %d - %d", ext, port );

                if( cb != NULL ) cb->registry();
            }
            break;
            case __BOOT__ : {
                /***
                    [ Principio ]
                        -- Receber um pacote de boot do CBx
                        -- Encaminhar um pacote do tipo "Registro" para o CBx
                        [ NOTA ] Por decisao de projeto, o CBx responde pacotes do tipo __REGISTRY__ pendindo pra se registrar.
                        
                    -- Fluxo --
                    - Incrementa o contador de pacotes de boot recebidos
                    - Envia para o CBx remetendo o mesmo pacote, contendo o tipo __REGISTRY__ e o id como sendo o id recebido "OR" BIT7
                    
                ***/
                boot_counter++;
                if( debug_boot == true ){
                    send_msg("Rcv boot pkg from (%d, %d) pkg-id %d", ext, port, data[ 0 ] );    
                }
                send2callboxes( build_cb_package( ext, port, __REGISTRY__,
                    ( char * )data, data[ 0 ] | BIT7, CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );
            }
            break;
            
            case __FW__ : {
                /***
                    [ Principio ]
                        -- Encaminhar para o servidor predeterminado todo pacote do tipo __FW__
                        
                    -- Fluxo --
                        - Incrementa o contador de pacotes de __FW__ recebidos
                        - invoca rotina que exporta este pacote para o servidor
                ***/
                fw_counter++;
                if( debug_fw_print ) send_msg("::FW pkg from %d - %d::", ext, port );
                fw_cbx_pkg( ext, port, ( char *)buffer );
            }
            break;

            case __BOOTLOADER_CBX__ : {
                /***
                    [ Principio ] 
                        -- A definir, a priori a header seria um bypass responsavel apenas por gerenciar um TS.
                    -- Fluxo --
                        - incrementa o contador de pacote de bootloader CBx recebidos
                        - ???
                ***/
                bootloader_cbx_counter++;
            }
            break;

            case __PROMPT__ : {    
                /***
                    [ Principio ] 
                        -- Receber um pacote do CBx
                        -- Criar, adicionar e registrar o CBx remetente
                        -- Exibir na tela possiveis comandos/saidas do CBx de interesse.
                    -- Fluxo -- 
                        - Procura por este cbx no vetor logico de CBx.
                        - Verifica se o CBx foi encontrado no vetor
                            - Caso nao tenha sido encontrado
                                - Verifica se nao existem mais cbx criados do que o permitido por definicao de projeto
                                - Caso nao exista
                                    - Tentar criar este elemento
                                    - Verifica criacao bem sucedida 
                                        - Caso nao tenha criado o elemento
                                            - seta variavel de erro
                                        - Caso tenha criado o elemento
                                            - Adiciona o mesmo no vetor logico de CBX
                            - Caso tenha sido encontrado ( ou criado no caso acima )
                                - Encaminha pedido de registro para o *
                        - Verifica se o pacote recebido possui como conteudo "ping"
                            - em caso positivo
                                - exibe msg indicativa condicionada a debug
                            - em caso negativo
                                - Incrementa o contador de pacotes recebidos
                                - Exibe conteudo de pacote ( 32 primeiros bytes ) condicionado a debug
                ***/
            
                Call_Box * cb = __find_CB__( v_cb, ext );

                if( cb == NULL ) {
                    if( v_cb->size() < __MAX_CB_IN_A_BRANCH__ ) {
                        if( debug_main ) debug_msg("Adding Cbx :: %d", ext );
                        cb = new Call_Box( ext, port );
                        if( cb == NULL ) {
                            memory_is_over = true;
                        } else {
                            v_cb->add( cb );
                            if( debug_main ) debug_msg("Added CBx -- %d", ext );
                        }
                    }
                }

                if( cb!= NULL ) cb->registry();

                if( xstrmatch( ( uint8_t * )data, ( uint8_t * )"ping" ) ) {
                    if( debug_ping ) send_msg( "Prompt pkg from ( %i, %i ) :: Ping", ext, port );
                } else {
                    prompt_counter++;
                    //FIXME acumular a string e mandar via send_msg
                    send_msg( "Prompt pkg from ( %i, %i ) ::", ext, port );
                    for( register uint8_t i = 0; i < 32; i++ ) {
                        if( debug_uart3 ) pc.printf("%c", data[ i ] );
                        if( i == 15 ) if( debug_uart3 ) pc.printf( "\r\n" );
                    }
                    if( debug_uart3 ) pc.printf("\n\r> ");

                    if( tcp_session && !udp_query ) {
                        char aux[ CB_BUFFER_SIZE + 3 ];
                        strncpy( aux, (char * )data, CB_BUFFER_SIZE );
                        strcat( aux, "\n\r\0" );
                        tcp_client.send_all( ( char *)data, strlen( (char * )data ) );
                        tcp_client.send_all( "\r\n> ", strlen( "\r\n> " ) );
                    }
                        else if( udp_query )
                    {
                        char aux[ CB_BUFFER_SIZE + 3 ];
                        strncpy( aux, (char * )data, CB_BUFFER_SIZE );
                        strcat( aux, "\n\r\0" );
                        udp_query_send_msg( ( char *)data );
                        udp_query_send_msg( "\r\n> " );
                    }
                }
            }
            break;
            case __AUDIO__ : {
                /***
                    [ Principio ]
                        -- Receber pacote de audio do CBx
                        -- Encaminhar para o *
                    -- Fluxo --
                        - Incrementa o contador de pacotes recebidos
                        - Procura por este cbx no vetor logico de calls.
                            - Caso nao encontre
                                - Exibe mensagem de erro condicionada a debug
                            - Caso encontre
                                - Encaminha o pacote para o servidor
                                - Reseta o timer de idle desta ligacao
                                - Busca pelo CBX no vetor logico de CBx
                                    - Caso encontre
                                        - Informa que esta tendo comunicacao CBx->Header
                ***/
                audio_counter++;
                VZ_call * call = __find_Call__( v_call, ext );
                if( call != NULL ) {
                    // Por definicao de projeto, os dados de audio comecam no data + 2
                    // esses 2 bytes foram usados para id de debug durante o desenvolvimento
                    char * pkg = call->build_eth_package( data + 2 );
                    call->send_message( pkg );
                    call->cbx_pkg_idle_timer_reset();
                    Call_Box * cb = __find_CB__( v_cb, ext );
                    if( cb != NULL ){                      
                        cb->set_invite_response_ok();
                        cb->invite_retry_count_reset();
                    } 
                } else {
                    if( debug_main ) debug_msg("received missed package  from CBx :: %i", ext );
                }
            }
            break;
        }//end switch para tratemento de pacote baseado no type
        
        { // rajada
            /***
                [ Principio ]
                    -- Verifica se existem CBx em ligaçao
                    -- Verifica se os mesmos estao enviando pacotes de audio
                    -- Re-envio o pacote avisando que o CBx pode entrar no status "on_call"
            ***/
            if( invite_retry_timer.read_ms() > 30 ) {
                invite_retry_timer.reset();
                static int retry_invite_pkg = 0;

                if( retry_invite_pkg >= v_cb->size() ) retry_invite_pkg = 0;

                // procura por CBx em ligaçao sequencialmente
                register int i = 0;
                
                for( ; i < v_cb->size(); i++ ) {
                    Call_Box * cb = (Call_Box * )v_cb->get_element( i );
                    debug_msg("--%p--", cb );
                    if( ( cb->status == cb_ringing ) || ( cb->status == cb_trying ) || ( cb->status == cb_on_call ) ) {
                        if( i > retry_invite_pkg ) {
                            retry_invite_pkg = i;
                            break;
                        }
                    }
                }
                
                if( i != v_cb->size() ){
                    Call_Box * cb = (Call_Box *)v_cb->get_element( retry_invite_pkg++ );
                    
                    if( ( cb->status == cb_ringing ) || ( cb->status == cb_trying ) || ( cb->status == cb_on_call ) ) {
                        if( cb->get_invite_response() == false ) {
                            cb->set_msg_id( ( cb->get_msg_id() + 1 ) & ~BIT7 );

                            buffer[ __TIMESLICE_PLACE__ ] = cb->get_timeslice();
        
                            // re-envia pacote confirmando que ligacao esta ok, CBx pode ligar o mic. e o speaker
                            send2callboxes( build_cb_package( cb->get_ext(), cb->get_port(), __INVITE__, ( char * )buffer,
                                cb->get_msg_id(), CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );
                                
                            if( debug_invite ) debug_msg("resend invite OK to Cbx : ( %d,  %d )", cb->get_ext(), cb->get_port() );
                        }
                        
                        // fim das tentativas
                        if( cb->get_invite_retry_count() == 0 ) {
                            cb->send_bye();

                            ts->return_timeslice( cb->get_timeslice() );
                            cb->set_timeslice( 0x00 );

                            cb->set_msg_id( ( cb->get_msg_id() + 1 ) & ~BIT7 );

                            for( register uint8_t i = 0; i < v_call->size(); i++ ) {
                                VZ_call * call = ( VZ_call * )v_call->get_element( i );
                                if( call->get_cb_ext() == cb->get_ext() ) {
                                    v_call->remove_element( i );
                                    if( call != NULL ) delete( call );
                                    break;
                                }
                            }

                            if( debug_invite ) debug_msg( "-- No audio pkgs --" );
                            set_status( cb->status, cb_idle );
                            set_status( cb->sip->status, sip_idle );
                        }
                    }
                }
            }
        }
        
        //
        
        /***
            [ Principio ]
                -- Para cada CBx em ligaçao
                -- Verificar e encaminhar pacotes recebidos da interface ETH-Header-CBx
            -- Fluxo --
            - Para cada elemento do vetor call
                - Verificar se consta algo pendente para processamento no sentido ETH->Header->Cbx
                    - Caso existe
                        - Procurar por este CBx no vetor lógico de CBx
                            - Caso seja encontrado
                                - Enviar pacote recebido para este CBx
                            - Caso nao seja encontrado
                                - Exibe msg de erro condicionado a debug
        ***/
        
        for( register uint8_t i = 0; i < v_call->size(); i++ ) {
            //debug_msg("");
            VZ_call * call = ( VZ_call * )v_call->get_element( i );
            int length = 0;
            char * tmp = call->get_eth_message( &length );
            if( tmp != NULL ) {
                int cb_port = 0xffff;
                Call_Box * cb = __find_CB__( v_cb, call->get_cb_ext() );
                if( cb != NULL ) {
                    cb_port = cb->get_port();

                    uint8_t * pkg2cb = build_cb_package( call->get_cb_ext(), cb_port, __AUDIO__,
                        tmp, __AUDIO__, length, write_buffer );
                    
                    send2callboxes( pkg2cb );
                    
                } else if( debug_main ) debug_msg("received missed package  from CBx :: %i -- Type :: %i", ext, type );
            }
        }
        //
        /***
            [ Principio ]
                -- Verificar se já se passou determinada unidade de tempo
                -- Baseado nisso, chamar a funcao [ 1 ] refresh ou [ 2 ] wake_all_up
                [ 1 ] -- Encaminha periodicamente um pacote de __REGISTRY__ para cada CBx, um por vez.
                [ 2 ] -- Busca por elementos que constem sem seus pares registrados e manda um __PROMPT__ ping para cada um, um por vez.
        ***/

        if( timer_sync_refresh.read_ms() > 250 )
        {
            timer_sync_refresh.reset();

            static uint8_t mode = TIME_TO_REFRESH;
            
            if( mode == TIME_TO_REFRESH )
            {
                mode = TIME_TO_WAKE_UP;
                refresh( v_cb );
            }
                else
            {
                mode = TIME_TO_REFRESH;
                if( wake_all ) if( v_call->size() == 0 ) wake_all_up( v_cb );
            }
        }
        
        // check sip messages only for cbx in call ?
        int ext_to__be_removed = sip_manager( v_cb );
        if( ext_to__be_removed > 0x00 ) {
            Call_Box * cb = __find_CB__( v_cb, ext_to__be_removed );
            if( cb != NULL ) {
                if( cb->status == cb_on_call ) {
                    ts->return_timeslice( cb->get_timeslice() );
                    cb->set_timeslice( 0x00 );
                    buffer[ __TIMESLICE_PLACE__ ] = 0x00;

                    set_status( cb->status, cb_idle );
                    set_status( cb->sip->status, sip_idle );

                    for( register uint8_t i = 0; i < v_call->size(); i++ ) {
                        VZ_call * call = ( VZ_call * )v_call->get_element( i );
                        if( call->get_cb_ext() == ext_to__be_removed ) {
                            v_call->remove_element( i );
                            delete( call );
                        }
                    }

                    cb->set_msg_id( ( cb->get_msg_id() + 1 ) & ~BIT7 );

                    send2callboxes( build_cb_package( ext, port, __CB_BYE__,
                        ( char * )buffer, cb->get_msg_id(), CB_BUFFER_SIZE - __VZ_HEADER_OFFSET__, write_buffer ) );
                        
                    if( debug_invite ) debug_msg("Received Bye from *");
                }
            } else if( debug_main ) debug_msg("Missed bye request from * CBx :: %d", ext );
        }

        /* Verifica andamento de ligações para eventualmente encerra-las por timeout */
        call_manager( v_call, v_cb, buffer, write_buffer, ts );

        
        /* tratamento de pedidos de ligação já em andamento com o * */
        invite_handler( v_call, v_cb, ts, NULL );

        
        /* rotina de verificação de TS's perdidos */
        if( ( v_call->size() == 0 ) && ( ts->remain_timeslices() != __MAX_TIMESLICES__ ) ) {
            bool ts_reset = true;
            for( register uint8_t i = 0; i < v_cb->size(); i++ ) {
                if ( ( ( Call_Box * )v_cb->get_element( i ) )->get_status() != cb_idle &&
                        ( ( Call_Box * )v_cb->get_element( i ) )->get_sip_status() != sip_idle ) {
                    ts_reset = false;
                    break;
                }
            }
            if( ts_reset ) {
                if( debug_invite ) debug_msg("Resetando TS");
                ts->reset();
            }
        }

        
        /* rotina que esvazia possiveis pacotes que não foram transmitidos para evitar conflito */
        tx_buffer_ring_buffer_handler();

        
        // atribui o valor default para a variavel type
        type = __DO_NOTHING__;

        
        // verifica o status da conexao ETH, caso exteja conectado ( == 0 ) atribui o valor maximo ao contador de controle
        if( eth_status == 0 ) eth_wdt = ETH_CONNECT_TIMEOUT;
        
        
        
        // responsavel por atualizar os contadores de controle utilizados para tickar o wdt
        // e tickar o wdt
        if( wdt_timer.read() >= 1 ) {
            
            //FIXME remove myself
            uptime++;

            wdt_timer.reset();

            if( wdt_show ) debug_wdt = true;

            if( external_wdt ) external_wdt--;
            if( pkg_wdt ) pkg_wdt--;
            if( eth_wdt ) eth_wdt--;

            if( eth_wdt && external_wdt && pkg_wdt ){
                wdt.kick();
            }
        }
        
        
        // exibe informacoes referentes ao wdt, ultimo reset, status da eth, tempo em segundos desde o ultimo tick dowdt externo, 
        // tempo em segundos desde o ultimo pacote recebido da interface fibra
        if( debug_wdt ) {
            send_msg("lpc_low_level_input_counter :: %d", lpc_low_level_input_counter );
            lpc_low_level_input_counter = 0;

            debug_wdt = false;
            if( eth_status == 0 ) {
                send_msg( "Wdt last reset: %s - status_eth :: Connected - Extern Wdt idle for :: %3d sec ( %3d ) - Rx from CBx idle for :: %3d sec ( %3d )",
                          ( wdt.WatchdogCausedReset() ) ? "true" : "false",
                          EXTERN_WDT_IDLE - external_wdt,
                          EXTERN_WDT_IDLE,
                          RX_CB_IDLE - pkg_wdt,
                          RX_CB_IDLE
                        );
            } else {
                send_msg( "Wdt last reset: %s - status_eth :: Disconnected :: since %3d sec - Extern Wdt idle for :: %3d sec ( %3d ) - Rx from CBx idle for :: %3d sec ( %3d )",
                          ( wdt.WatchdogCausedReset() ) ? "true" : "false",
                          ETH_CONNECT_TIMEOUT - eth_wdt,
                          EXTERN_WDT_IDLE - external_wdt,
                          EXTERN_WDT_IDLE,
                          RX_CB_IDLE - pkg_wdt,
                          RX_CB_IDLE
                        );
            }
        }
        
        // atribui o valor default ao ponteiro de dados
        data = NULL;
    }//fim while ( main loop )
}